Skip to content

DSCODE 0.7.47

Choose a tag to compare

@github-actions github-actions released this 15 Oct 03:41
· 6 commits to main since this release

DSCODE 0.7.47

The terminal and the agent runtime now run as separate processes: dscode attaches to a local background host that owns sessions, so work survives the terminal and several terminals can share a session.

A background host

Until now the terminal was a plugin inside the runtime process and created its agents itself, so quitting or crashing the terminal ended the session's live state, and no second client could drive it. The first dscode in a state directory now starts a host: the terminal composition without its interface, plus the upstream API assembly and a DSCODE local carrier. The launcher waits until the host answers (about a second in local runs) and starts the terminal as a separate client process with the same arguments.

The host listens only on a Unix socket (host.sock, mode 0600) in an owner-checked 0700 directory under /tmp derived from the state directory, the location the session bridge already uses to stay within the macOS socket-path limit. Nothing listens on TCP, and filesystem permissions are the authentication. An exclusive lock beside the socket admits one host per state directory; a host that loses the race exits, and the starter retries until one answers. The host exits after ten minutes with no attached terminal and no running turn (DSCODE_HOST_IDLE_MS, 0 to disable); status probes do not count as activity. dscode host status|start|stop|serve inspects and controls it, and its output goes to run/host.log in the state directory.

When a terminal quits, the session stays on the host and a running turn continues. dscode --resume <id> from any terminal attaches to it, pages in the whole history, sees the turn as running and can interrupt it. A protocol client delivering into a session that a terminal is showing appears in that terminal live. One host serves every folder: the preset's process-wide instruction and ancestor-skill rows are switched off in host mode, and each session mounts the AGENTS.md/CLAUDE.md files, ancestor skill roots and project hooks of its own folder, the mechanism the Desktop plugin already used.

--in-process or DSCODE_RUNTIME=in-process keeps the single-process terminal, and the launcher falls back to it, with a message, when the host cannot start. Launcher flags (--dump-config, --patch, --profile) keep the single-process path. A single-process terminal cannot open a session the host is driving; it exits with session … is already owned by an active write handle. dscode update stops a host with no attached terminal before replacing the package and refuses while one is attached.

Behaviour stops there. Remote access is not offered. dscode exec, dscode acp, the trigger scheduler and the Desktop plugin keep their own runtimes. A terminal that joins a running turn shows its streamed text from that point on; earlier text appears once the message is committed. If the host exits under an attached terminal, the terminal reports failed requests and must be restarted. With several terminals on one session, approvals and questions follow the upstream rule that the first answer settles them; the automated checks exercise one answering terminal.

How the terminal reaches the runtime

The terminal's 2,500-line runner no longer receives a Cordis context. It talks to a RuntimeClient with two implementations: in process, and over the carrier. Standard session work uses the upstream Typert methods (create, resume by follow, fork, model selection, the follow stream with live assistant frames, approvals and questions as forwarded waterfalls). Everything DSCODE adds — commands, models and the /subagent override, provider settings, credentials and interactive login, the OpenRouter account, custom providers, the session catalog, jobs, reminders, plugins, permission presets, skills, @-mentions and session references, attachments, delivery, queue edits, interrupts, /btw, child-session events, footer status and host notices — is a named host operation in packages/tui/src/host. The single-process terminal invokes the same registry directly, with arguments and results normalized through JSON, so both modes run one implementation. The subagent model reroute and the background capability sync moved to the host; dscode exec, acp and trigger runs disable that host plugin. OpenRouter helpers that resolved key values moved out of the terminal UI. Client and runtime protocol specifies the wire protocol, the client lifecycle and every DSCODE operation for anyone writing another client. The plugin and jobs panels now load asynchronously, and the Desktop preset build sets the shared per-session switch instead of inserting a second disabled key.

Fixes

A /btw side question that inherits the conversation created its child session without the seeded marker, which the session store rejects; it now starts. The single-process terminal had the same defect before this release.

The subagent route makes delegated agents follow the session's current model and effort, which the kernel otherwise fixes at the parent's creation. It used to override a child's own reasoning_effort or model as well. A child's options inherit the parent's creation-time options, so a value that differs from them is now treated as the child's own choice and kept; /subagent still overrides both. Because the route now runs on the host, it also applies to sessions a separate terminal drives.

Verification

On macOS (arm64), every stage of npm run check passed outside the session sandbox: lint, both TypeScript configurations, 1,248 unit and component cases with 80.05% first-party .mjs line coverage, all fifteen integration verifiers, the package checks and 63 offline evaluations. npm run doctor passed. The local darwin-arm64 package passed verify-standalone.mjs, which now also starts, queries and stops the host through the packaged launcher. npm run test:e2e passed all eight steps on linux/arm64 in 5.3 minutes, including the integration verifiers, the self-contained Linux package and the Hub lifecycle.

Two new verifiers carry this release. verify-tui-runner.mjs drives the real terminal on an in-memory TTY against a deterministic fixture model in three modes: single-process, same-process protocol and a separate host through the real launcher (asserting a separate host process). Each mode passes sixteen behaviours plus resume: streamed reply, a registry command, rejecting an escalated write, answering a question, @-file completion, /title, /usage, /jobs, interrupting a running turn, /btw, /permission and /fork. verify-host.mjs covers a second client delivering into a session shown live in a terminal, a terminal showing a session's own model route, a terminal killed mid-turn whose turn keeps running and is reattached through paged history and interrupted, three concurrent starts converging on one host, idle exit only after the last terminal detaches, and one host giving two folders their own ancestor AGENTS.md. Both ran on macOS and inside the Linux end-to-end container. A unit case covers the footer-source mirror, and a Desktop composition case parses the generated preset.

Not covered by an automated case: approvals answered by two terminals at once, project hooks and ancestor skill roots per session on a shared host (instructions are covered, the other two use the same mount), the host exiting under an attached terminal, Intel macOS and Linux x64 runs of the new verifiers (release CI qualifies those packages), live model calls, and a terminal in a real macOS terminal emulator rather than the in-memory TTY.