Terminal protocol module¶
Terminal-side Session execution, protocol-byte handling, and an Operation adapter interface for connecting a host renderer. The module is experimental and unpublished; protocol drafts define the design.
Responsibilities¶
src/session.ts: Capability, Context, Block lifecycle, content-state IDs, correlated errors, and prepared Operations over validated Messages.src/endpoint.ts: decode protocol bytes, execute the Session, consult a host adapter, and encode response frames. Also exportsTerminalOperationAdapter.src/resource-limits.tsandsrc/input-budget.ts: host-configured retained-state and pending-input budgets.src/index.ts: the module entry point.test/holds the module checks and an isolated build-consumer test.
Runtime code depends only on shared protocol code. The terminal host example shows how the experimental xterm adapter connects this layer to a real rendering path.
Build and use¶
pnpm build:terminal
The command prints a fresh .tmp/terminal-build-* directory with ESM JavaScript,
declarations, the Apache 2.0 license, and private package metadata. Keep the whole
directory: terminal/src/index.js imports the included
node_modules/@tui-protocol/protocol package by name.
The exports are . for terminal execution and ./protocol for shared types
and codecs. @tui-protocol/terminal is the private workspace/distribution name.
Import TerminalProtocolEndpoint from @tui-protocol/terminal in the workspace
or when the complete built distribution is installed under that name.
Supply the host’s completeBaselineSupported assertion and its
operationAdapter. Assert support only when the host implements the complete
baseline, including native history and rendering behavior. The adapter may be
omitted for state-only tests.
For a protocol-only stream, call push(bytes) and return
each responseFrames entry to the application; handle diagnostics locally.
For ordinary terminal output mixed with protocol frames, use one decoder with
emitOrdinaryData: true. Route ordinary events to the native parser, protocol
events to acceptDecoded(event), and preserve execution/rendering order.
Do not also feed those same bytes to push(): it owns a separate protocol-only
decoder and does not return ordinary data. Finalize the external decoder and
deliver its remaining events before calling endpoint.finish() at EOF.
Host adapter boundary¶
prepare(operation) runs before Session commit. Return undefined to accept
the preparation, or resource_exhausted / internal_error to reject without
changing Block content. A thrown preparation error becomes a local diagnostic
and an internal_error response. accept(operation) runs only after commit;
it is synchronous and must arrange any later rendering and failure handling.
An accept exception aborts endpoint processing and throws to the host. For a
later asynchronous rendering failure, the host calls abort(reason). Further
push, acceptDecoded, invalidation, and finish calls then throw; abort does
not Seal Blocks, produce a close response, roll back state, or clear history.
Snapshots remain diagnostic observations, not usable Context authority.
The host owns serialization with rendering, resource checks, native history
behavior, and detection of changes that invalidate a Context’s rendered
identity. It calls invalidateContext(id) to apply that determination. See the
native-behavior draft.
The host must retire the failed execution session and establish trustworthy renderer state before renegotiating with a fresh endpoint. Creating only a new Context is insufficient. The host handles transport shutdown, renderer restart, and detection of asynchronous failures. A host callback already running when abort occurs must settle under host control. The failure draft distinguishes this stop from an ordinary atomic rejection.
Session snapshots expose protocol state; the host tracks rendering completion. Successful Operations have no response. The host and application coordinate recovery; the module performs no automatic rollback or retry.
Verification and limits¶
Optional resourceLimits configure local retained-state budgets; the exported
trialSessionLimits profile is used by the terminal-host and multi-round
examples. Content growth can return resource_exhausted; identity/replay
exhaustion stops the endpoint while preserving consumed IDs. PendingInputBudget
helps hosts bound owned queued bytes and items. The
resource-budget note explains the
values, accounting scope, and exhaustion behavior.
Run pnpm typecheck and pnpm test. Existing Session and Endpoint scenarios
now live under test/; their experiment records are retained in the original
Session record and
Endpoint record.
test/artifact.test.ts copies separately built TUI and terminal modules outside
the checkout, disables Node’s TypeScript execution, and exchanges all five
Operations through an in-memory adapter. It checks rejection/unchanged content,
Context close, and external declaration resolution.
Extraction checks on 2026-09-12 passed type checking, 158 Node tests, the 66 existing browser endpoint scenarios, and both real-PTY terminal-example checks.
The xterm adapters and real-PTY fixtures remain in prototypes/. Their existing
capacity, Unicode, asynchronous rendering, and platform limits still apply.
Further integration work includes authentication, general transport
backpressure, production recovery, and broader terminal compatibility.