Terminal host example¶
How does a terminal receive application bytes, execute Block Operations, render content, and send replies? This runnable example connects the streaming application to the existing browser xterm adapter. Read main.ts for the connection, not the test suite.
The terminal protocol module is independent of
prototypes and has a local JavaScript build. This browser example still imports
the xterm renderer and mixed-input adapter from prototypes/; it is not a
standalone renderer or an adapter for an arbitrary terminal.
The multi-round example reuses this wiring with optional command buttons, a native-row diagnostic view, and a longer page deadline. Those are example controls, not terminal protocol APIs; the original page keeps its twelve-second deadline and one-shot application.
The Pi multi-round trial
also reuses the host. Its opt-in form mode disables forwarding terminal
keystrokes and sends application-owned commands through sendApplicationInput;
protocol replies still use the same return transport. Other pages retain their
original keyboard forwarding. This helper is local example wiring, not an SDK API.
Local browser checks also use the exported terminal/history instances and
settleHost to observe actual rendering and copy handling after queued work;
these exports are not a portable or stable adapter interface.
Run¶
On Windows with Node 24 or newer, from the repository root:
pnpm install
pnpm example:terminal
Open http://127.0.0.1:4178/ and choose Connect application. The host
prepares the built SDK application and starts it through bundled ConPTY.
Thinking grows, becomes Thinking complete, and is followed by the answer.
Expect Child exited: 0, two sealed Blocks, and a closed Context. The
Context states before EOF observation distinguishes the application’s
explicit close from the Session’s cleanup when a stream ends.
Choose Find next to search for Result: in retained terminal content.
Disconnect ends a running connection without promising a successful child
exit. Reload to start fresh; the example does not reuse a finished Session.
Stop the server with Ctrl+C. This and the other PTY examples share port 4178;
run only one at a time.
The connection¶
Application stdout → PTY bridge → incoming bytes
↓
XtermMixedStreamIngress
├─ ordinary bytes → xterm parser
└─ Messages → endpoint / Session → history adapter
↓
Application stdin ← PTY bridge ← encoded response frames
The ingress keeps ordinary writes and protocol rendering in order. Feed each
incoming byte chunk into it exactly once; do not also call terminal.write
with the same bytes or use the protocol-only decoder for the mixed stream.
Responses go back to the application, not onto the displayed terminal.
Terminal input uses the same outbound transport. Diagnostics are local
observations, not substitute wire responses.
On normal disconnect, wait for queued input and call ingress.finish() before
releasing the renderer. This example keeps rendered history available for
search after EOF and disposes it when leaving the page. A rendering or transport
failure stops the example; it does not attempt rollback or reconnect recovery.
What a terminal implementer owns¶
Part |
Existing implementation and responsibility |
|---|---|
Message validation and encoding |
Shared protocol; transport-independent and included in the local SDK build. |
Capability, Context, and Operation state |
Terminal module: Endpoint and Session; experimental APIs, independent of xterm rendering. |
Rendering and native history |
xterm adapter and browser history; replace these with your terminal’s implementation. |
Transport and process lifetime |
Development host; fixed child, loopback WebSocket, and bundled ConPTY, not protocol requirements. |
An adapter must connect accepted content changes to history, layout, reading anchors, selection/copy, and other applicable native behavior. It must also keep rendered Block identity and Session state consistent when history is discarded or destructive controls invalidate content. The current adapter’s prepare step can reject before Session commit; later asynchronous rendering is not automatically rollback-safe.
completeBaselineSupported: true is an explicit assertion for this experimental
fixture, not capability detection or proof of complete conformance. A different
terminal must not claim support merely because it can parse the Messages.
The TUI SDK does not provide that missing renderer. Fallback remains the
application’s decision; this page demonstrates only the supported path.
Verification and limits¶
This example selects local Session and pending-input budgets. Exhaustion is reported as a stopped connection where continued execution is unsafe; a new page is required. This does not establish a process-memory bound.
Run pnpm typecheck, pnpm test, and pnpm build:terminal-example from the root.
The build checks browser bundling, not a standalone deployment: running the page
still requires its development PTY host and injected connection token.
For repeatable browser checks, open http://127.0.0.1:4178/checks.html while the
development server is running and choose Run browser checks. Keep other
example connections closed. The runner operates the actual example
UI in a same-origin iframe, using two fresh SDK child processes:
Completion: final sealed content, explicit Context close before EOF, exit zero, a retained answer search match, and no match for replaced thinking text.
Early disconnect: stop after observing the initial mutable thinking Block; verify closed/sealed partial state, searchable partial content, no successful child-exit confirmation, and no answer inherited from the previous run.
Expect 2 browser scenarios passed. The runner reports FAIL on a mismatched
result or a local fifteen-second wait deadline. It observes content instead of
sleeping a fixed interval before disconnecting. If a delayed delivery skips the
initial observable state, that check fails rather than claiming an interruption
was exercised. Reloading or rerunning uses fresh Sessions, not recovery.
These browser checks are separate from pnpm test; they do not establish full
protocol conformance or replace the native-capability regression suites.
On 2026-09-12, the local browser run showed the expected final content, explicit
Context close before EOF, exit zero, and a retained Result: search match.
An interrupted run retained its partial content and reported no child exit
confirmation. Both checks used the fixed SDK child through bundled ConPTY.
The repeatable runner subsequently passed these two scenarios locally.
The example uses pinned xterm 6.0 private history interfaces and experimental
OSC 9002. It has a fixed 40-by-8 viewport and a local twelve-second connection
deadline. It adds no resize, Unicode, capacity, clipboard, other-terminal,
Unix/SSH/tmux, backpressure, or crash-recovery guarantees. The underlying
PTY evidence and limitations
remain applicable. No protocol semantics or stable public APIs are added here.