omdsh-plugins/omdsh-tui--packages-tui-app ↗★ 0
@omdsh-plugins/omdsh-tui-app
dsh 交互式终端套件:包含基于 dsh-base 的终端补丁层以及支持命令行、会话标识、恢复交接和界面提示的运行时粘合插件。
AI 分析
提供 DSH 终端运行时的核心粘合与配置管理,支持会话恢复等高级终端功能。适合需要通过命令行管理和启动 DSH 终端会话的用户。
安装
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:omdsh-plugins/omdsh-tui#b5e9898d6e9d4ec11be1d863395cb3ba18ba41b3&path:packages/tui-app说明文档
阅读完整 README ↗@omdsh-plugins/omdsh-tui-app
English | 中文
The interactive terminal bundle: the terminal patch layer over dsh-base plus the runtime glue plugin behind dsh --profile . The profile front-door Agent Note owns the composition decision; @omdsh-plugins/omdsh-tui owns terminal presentation and input.
dsh --profile omdsh-tui # a fresh session in this directory
dsh --profile omdsh-tui --resume # pick a session to resume from the list
dsh --profile omdsh-tui --resume # resume that exact session
dsh --profile omdsh-tui --session-id # drive this exact session, creating it on first use
Nothing auto-initializes: dsh ships templates for web and headless only, so this bundle has to be installed into a profile first, together with the @omdsh-plugins/omdsh-tui front door its patch names — see installing it, which also covers the stale tui profile an upgraded machine carries. The profile name above is only this repository's default; every profile-naming surface here reads the booted name from argv, so the bundle works under any name.
The invoking directory is the workspace: the session cwd, relative paths, and workspace instructions all resolve from it. Sessions themselves live under the Harness home, so /resume reaches every workspace and resuming enters the selected session's own directory.
What the patch adds
Over the shared base this layer configures the terminal persona, binds agent-loop's main agent to this invocation, pins fs-sandbox to the process directory, opens the /resume search index, and gives the front door its welcome greeting, which the banner holds for the life of the process while the session's own name rides the input's top rule. It inserts Code Mode's worker-thread runtime, session references, the storage stack behind cached /resume titles, tmux and wall-clock context, and the terminal front door with its prompt-value registry.
The agent plane moves behind agent presets
The base composes every model-facing row on the host plane, where it covers each agent in the process. This layer disables those rows and inserts dsh-agent-presets instead, so the session mounts one preset — a mode — and that preset owns its tools, its persona, its prompt sections, and its delegation backends. Disabling is what makes the choice real rather than a label: a preset can only remove a tool if nothing else registered it globally. dsh ships four (Standard, Code, Minimal, Creator) beside its own config, and /mode in the front door is the surface over them.
The disabled list mirrors dsh-web-app's, because the line it draws is the same one: a row whose service the HOST reads or injects stays on the host plane — shell-env, the job registry, goals, the skill registry, subagents, tokenMeter, the web service — and only the model-facing rows over them move. tool-ask-user is no longer inserted here for the same reason: the presets carry it, and the front door still provides its keyboard UI through the host-plane user-questions registry. Only the writable preset root is this bundle's business; the shipped root sits beside the installed app's own config, so dsh's profile boot patches it into any composed tree carrying the agent-presets row.
The tui row injects agentPresets as a result. That is a fact about THIS bundle, not about the front door: @omdsh-plugins/omdsh-tui treats the roster as optional throughout, so a composition that keeps its tools on the host plane drops both rows together and the terminal mounts exactly as it did before.
Row-by-row values are in the generated config catalog; dsh --profile --dump-config prints the tree your machine actually boots.
Command line
tui-startup owns this app's flags (app-owned command line) and publishes them as the tuiStartup service. Rows read the parsed invocation from lazy !!js expressions, so dsh --profile --help provides nothing, starts no agent, and never takes over the terminal.
--resume with an id binds that exact session at boot and fails loud when its log is missing. --resume without a value starts a fresh session and leaves the switch to the front door's own selector, which is the half that knows the persisted corpus.
--session-id is the same identity from the other direction, and the difference is which config key it lands on: --resume becomes resumeSessionId, which is persisted history and fails loud without it, while --session-id becomes sessionId, which the agent loop treats as create-or-restore. That is what an embedder needs — a surface showing this terminal inside itself has to name the session before the process exists, or it can never account for it afterwards. omdsh-codemode's Code mode is the case it was added for: it names each terminal conversation so the web sidebar can hold it and a click can reopen it. Passing both flags is refused rather than resolved: two identities for one process has no safe reading.
Create-or-restore is a question only storage can answer, so the bundle's agent-loop row injects sessionPersistence. That injection is the whole difference between the two halves of the flag: the agent loop reads persistence at the moment it starts a named agent, and with none in hand it takes the only other option — create. For an id that already has a log, that is a fresh live session over a stored one, and the first thing it writes is refused as an id collision. So the row waits for storage; --resume never needed the same line, because the loop's resume path waits for persistence itself.
The booted profile's name
--profile is the launcher's own flag, consumed before this app's arguments reach cmdlineArgs, so profile.ts recovers it from process.argv — the same seam internals.entry uses for the entry module. Three surfaces need it and would otherwise print or execute a name that is merely conventional: the --help usage line and examples, the exit line that returns to this session, and the in-place /resume handoff, whose replacement argv must re-enter the same composition the user was sitting in. A hardcoded name breaks all three in every profile called anything else.
Config
| Key | Default | Meaning |
|---|---|---|
goodbye | required | Line printed once the terminal is released on exit; the command that returns to this session |
queryIndexPath | required | Absolute path of this process's disposable /resume search index, removed on disposal |
surfaceContext | true | Register the harness-source and terminal-surface prompt sections |
Model Experience
Harness-source and terminal-surface context
What the model sees
When surfaceContext is true and this package runs from the repository checkout, the harness:source section identifies the on-disk Harness implementation without claiming it is the working directory; an installed copy has no checkout to read, so the section is absent rather than naming a path that holds no sources. The app:terminal-surface section (order −98) orients the model to the interactive terminal: replies render as Markdown, each tool call renders as its own card alongside the current plan, and the user can interrupt a turn, steer it mid-run, and answer questions — so asking beats guessing when a choice is theirs. When it is false, neither section is registered; a composition whose user is not at this terminal must turn it off, because the orientation text would otherwise be false.
Both sections are host-plane, so a preset with a complete persona — Minimal mode's — suppresses them for the agent composed from it, along with the deployment persona this layer configures. That is the preset's decision to make: a composition whose whole system prompt is one sentence cannot also carry an orientation paragraph.
Token effect
One source line and one prompt paragraph per session, about 90 tokens together; constant per process. Every tool schema in the catalog belongs to the mounted preset instead, which dsh-agent-presets owns.
KV Cache effect
Both sections sit near the system prompt's head and are fixed for the life of the process, so they never invalidate the cache across turns.
Known limitations
- The resume handoff needs
process.execve. In-place/resumereplaces this process so the resumed session runs in its own workspace. Where Node does not exposeexecve(Windows, and any build without it), the glue provides no handoff and the front door reports that the session is selectable but not resumable in place. Resuming there means exiting and rerunning with--resume. - There is no
--continue. Reopening the most recent session in this workspace without picking one needs a corpus query, and the startup plugin runs before any session service exists. The honest place for it is the front door, which already scans candidates for its selector: a config flag telling it to auto-select the newest current-workspace row on mount. Until then,--resumeopens the selector.