description, kind
| description | kind |
|---|---|
| Persistent terminal sessions for deployments and consumers choosing, composing, or extending the owner-scoped ctx.terminals service. | package-reference |
@deepseek-ai/dsh-terminal
English | 中文
Summary
dsh-terminal provides persistent, owner-scoped terminal sessions to the harness: a session keeps shell or REPL state across tool calls, and every operation is fenced to the exact agent that created it. It provides the ctx.terminals service, which mints opaque session ids, routes session creation through registered backends, and waits for quiescent cleanup when an owner or the service disposes. It defines no terminal mechanics itself: backends such as the shipped dsh-terminal-bash own spawning and readiness, and the model-facing tools in dsh-tool-terminal own presentation. Sessions are process-local: they do not survive a harness restart.
Table of Contents
- Use this package
- Understand the implementation
- Further Exploration
- Model Experience
- Known Limitations and Deferred Work
- Dev Note
Use this package
Mount @deepseek-ai/dsh-terminal whenever a composition needs terminal sessions whose state survives across tool calls. The service alone does nothing useful: pair it with a backend such as @deepseek-ai/dsh-terminal-bash and a tool package such as @deepseek-ai/dsh-tool-terminal, and load all three in one composition.
When to choose it
Choose persistent terminals for work whose state lives in the terminal rather than a file: stepping a debugger, exploring in a Python or Node REPL, or returning to a shell after interrupting its foreground command. Choose the one-shot bash, read, write, and edit tools for bounded operations — they keep stronger validation, approval, output-bound, and replay contracts. Sessions are process-local: they disappear when the harness process exits, so durable work belongs in files or another persistent system.
Composition
Load the session service together with a backend and a tool package:
- name: '@deepseek-ai/dsh-terminal'
- name: '@deepseek-ai/dsh-terminal-bash'
- name: '@deepseek-ai/dsh-tool-terminal'
A backend provides one stable type — the shipped shell backend provides shell — and the tools open sessions by that type. The shell backend additionally requires the sandbox, sandbox-policy, and subprocess providers; see its README for the full composition.
What sessions give you
Once a session exists, consumers can open a session and receive its id and bounded startup output, send text (optionally submitting Enter) and wait until the shell is ready again or the send times out, read bounded retained output, deliver one allowed signal to the foreground process group, close a session and wait for its process tree to end, and list the sessions a caller owns. Exactly one send can be active per session at a time; a second send fails until the first settles.
Ownership and isolation
Every session is owned by the exact agent that opened it. Operations that name a session are rejected when the caller is not that agent, so the model cannot reach another agent's terminal even if it learns the id. An optional session name is owner-local display metadata — labels such as main or gdb — and is unique only within its owner.
Observable outcomes and failures
A successful open returns the session id, type, pid when the backend has one, status, and a bounded startup message. Sends settle with a wait reason: stdin_read (the shell is waiting for input), inferred_idle (output silence), timeout, or session_exit (the top-level shell exited). Failures carry stable machine-routable codes: a missing backend type (NO_BACKEND), an unknown session (NO_SESSION), another agent's session (FOREIGN_SESSION), a second concurrent send (SEND_ACTIVE), or an owner that is no longer live (OWNER_NOT_LIVE). Backend setup failures reject the open before anything is published, and a failed cleanup rejects the close rather than claiming success.
Understand the implementation
Implementation internals — click to expand
This section explains the design behind the service and points at the code that realizes it; the observable behavior is covered in Use this package.
Design concept
The service owns everything except terminal mechanics: session identity, publication, authorization, and cleanup. Backends own how a session starts, detects readiness, retains output, and shuts down; the service publishes a session only after backend setup succeeds. The split keeps one registry usable with different terminal substrates.
Source map
| File | Role |
|---|---|
src/index.ts |
TerminalSessionService: backend registry, spawn/send/read/signal/kill/list, owner cleanups, disposal |
src/types.ts |
Shared contracts: backend interface, session types, wait reasons, signal set, error codes |
| — | No runtime invariant companion is published; backend and owner-scoped session registries are private mutable state, and the service exposes neither an independent lifecycle stream nor an unscoped snapshot. |
Data model and lifecycle
Each published session is a record of its id, owner, optional name, backend type, and backend session, plus the one active send. Unpublished spawns are tracked per owner as reservations with a service-owned abort signal. Disposal aborts pending spawns, awaits their settlement and rollback, then closes every owned session and awaits quiescence before running owner detachers; a cleanup failure rejects the lifecycle instead of claiming success.
Ownership and cleanup rules
- Fencing uses the exact
Agentobject:hasOwnerActivity(owner)spans unpublished setup through final close with no publication gap, so lifecycle policy can fence the owner precisely. - A backend that cannot clean partial startup resources rejects with
TerminalBackendCleanupError; the service retains that failure as tracked owner activity until owner or service disposal consumes and reports it. - Caller cancellation keeps its exact
AbortSignal.reason;kill()and disposal resolve only after the backend's captured process tree is quiescent.
Send reservation
The service reserves a session synchronously for one active send before returning the operation, including before a background job id becomes visible; a second send fails with SEND_ACTIVE, so output and cancellation never cross operation ownership.
Further Exploration
Read these pages when the package-level contract is not enough. They move from the shared terminal model to the shipped backend, the tools, and the design evidence.
- Terminal subsystem reference — shared types, backend and session contracts, and the generated
ctx.terminalssurface. - terminal/ package map — the three-package family and how it composes.
- terminal-bash backend — the shipped shell backend that provides the
shelltype. - tool-terminal tools — the six model-facing tools that operate sessions.
- Persistent PTY Agent Note — design rationale, alternatives, and deferred boundaries.
Model Experience
Indirect consumer
What the model sees
Nothing directly. This package registers no prompt or tool; @deepseek-ai/dsh-tool-terminal owns visible schemas and result text.
Token effect
None directly. Live session state stays process-local until a consumer returns a bounded result.
KV Cache effect
No direct invalidation; @deepseek-ai/dsh-tool-terminal owns request-prefix changes.
Known Limitations and Deferred Work
These limits define when the service is a poor fit. They are current package constraints, not a task backlog.
- Process-local sessions — sessions and raw scrollback live only in this process and do not survive a harness restart; durable work must be committed to files or another persistent system.
- No cross-agent sharing — sessions are intentionally single-owner, with no path to share or transfer a session.
- No declarative auto-start — sessions are created only during agent tool calls.
Dev Note
Working context for maintainers — click to expand
This Dev Note is working context for maintainers and is explicitly non-authoritative: shipped behavior, limits, and accepted rationale live in the sections above, the package code, and the linked Agent Notes.
Undecided directions
- A shared-session design would need a separate authority contract.
- A declarative auto-start feature would compose through unpublished agent setup.