Files
deepseek-harness/apps/cli/composition.md
T
Turtle f290a8b851 refactor(cli)!: one shared base config with per-surface overlays
`dsh` shipped two config trees that were 43 rows the same: apps/cli/cordis.yml
composed web as 74 flat rows, while the TUI booted examples/tui-agent/cordis.yml
whose single `@deepseek-ai/dsh-tui-demo` row mounted twelve plugins behind a
twenty-key pass-through Config. Neither file was what its location claimed —
apps/cli hardcoded the "example" as the product default and the "demo" bundle
was the application — and every capability change had to be made twice.

- apps/cli/base.cordis.yml holds the 43 shared rows; tui.cordis.yml and
  web.cordis.yml are patch lists stating only what differs per surface
- overlays apply as SIBLING patch lists at one include level, because include
  patches never cross an include boundary. Precedence: base < surface <
  (--config | personal ~/.dsh/config.yaml) < launcher flag/profile patches
- `--config` now applies an overlay INSTEAD OF the personal one, so a demo or
  test tree never inherits the user's route; new `--config-replace` boots a file
  as the entire tree (the old `--config` behaviour). Both survive /resume
- vendor/include: index each `insert`ed row as it is added so a later patch can
  configure or disable it. Upstream built the id index once before the patch
  loop, leaving every surface-only row — the whole TUI front door — silently
  unpatchable from user config. Logged as local modification 8
- session identity moves to dsh-agent-loop's CONFIGURED_AGENT_IDENTITIES_KEY;
  dsh-tui's MAIN_SESSION_ID_KEY is deleted (only the bundle read it)
- delete examples/tui-agent, examples/cordis-agent, packages/examples/tui-demo;
  TUI tests → apps/cli/tests, cordis e2e → packages/cordis/tool-cordis/tests,
  examples/code-mode survives as an overlay leaf
- `dsh web` gains --config, threaded into AppCLIEntry as an extra overlay

Three latent defects surfaced and are fixed here: the TUI captured the optional
sessionQuery service once at construction and could permanently disable /resume
when it won the mount race; the session-store root silently reverted to a
project-local ./.sessions; --config-replace was dropped by the resume handoff.

Verified by booting each tree through the real Loader (TUI 55 entries, web 75,
zero unsettled) rather than reading YAML. All eight terminal snapshots replay
byte-identically; 14/14 PTY smoke, 112/112 snapshots, 25/25 doc-sync, hygiene
and lint clean.
2026-07-29 21:15:42 +08:00

7.2 KiB

dsh TUI Composition

The TUI agent combines the real DeepSeek adapter, coding tools, compaction, subagents, and workflows with the full-screen terminal app package.

flowchart LR
  cfg["apps/cli (dsh)<br/>cordis.yml"]
  plugin_tui_timer["timer<br/>@cordisjs/plugin-timer"]
  cfg --> plugin_tui_timer
  plugin_tui_llm["llm<br/>@deepseek-ai/dsh-llm"]
  cfg --> plugin_tui_llm
  plugin_tui_session["session<br/>@deepseek-ai/dsh-session"]
  cfg --> plugin_tui_session
  plugin_tui_session_title["session-title<br/>@deepseek-ai/dsh-session-title"]
  cfg --> plugin_tui_session_title
  plugin_tui_session_title_llm["session-title-llm<br/>@deepseek-ai/dsh-session-title-first-message-llm"]
  cfg --> plugin_tui_session_title_llm
  plugin_tui_user_interaction["user-interaction<br/>@deepseek-ai/dsh-user-interaction"]
  cfg --> plugin_tui_user_interaction
  plugin_tui_agent["agent<br/>@deepseek-ai/dsh-agent"]
  cfg --> plugin_tui_agent
  plugin_tui_tasks["tasks<br/>@deepseek-ai/dsh-tasks-local"]
  cfg --> plugin_tui_tasks
  plugin_tui_llm_retry["llm-retry<br/>@deepseek-ai/dsh-llm-retry"]
  cfg --> plugin_tui_llm_retry
  plugin_tui_session_persistence_jsonl["session-persistence-jsonl<br/>@deepseek-ai/dsh-session-persistence-jsonl"]
  cfg --> plugin_tui_session_persistence_jsonl
  plugin_tui_subprocess["subprocess<br/>@deepseek-ai/dsh-subprocess-local"]
  cfg --> plugin_tui_subprocess
  plugin_tui_bash_local["bash-local<br/>@deepseek-ai/dsh-bash-local"]
  cfg --> plugin_tui_bash_local
  plugin_tui_tool_bash["tool-bash<br/>@deepseek-ai/dsh-tool-bash"]
  cfg --> plugin_tui_tool_bash
  plugin_tui_tool_tasks["tool-tasks<br/>@deepseek-ai/dsh-tool-tasks"]
  cfg --> plugin_tui_tool_tasks
  plugin_tui_fs_policy["fs-policy<br/>@deepseek-ai/dsh-fs-policy"]
  cfg --> plugin_tui_fs_policy
  plugin_tui_tool_fs["tool-fs<br/>@deepseek-ai/dsh-tool-fs"]
  cfg --> plugin_tui_tool_fs
  plugin_tui_tool_fs_search["tool-fs-search<br/>@deepseek-ai/dsh-tool-fs-search"]
  cfg --> plugin_tui_tool_fs_search
  plugin_tui_workspace_context["workspace-context<br/>@deepseek-ai/dsh-workspace-context"]
  cfg --> plugin_tui_workspace_context
  plugin_tui_skill["skill<br/>@deepseek-ai/dsh-skill"]
  cfg --> plugin_tui_skill
  plugin_tui_skill_local["skill-local<br/>@deepseek-ai/dsh-skill-local"]
  cfg --> plugin_tui_skill_local
  plugin_tui_tool_skill["tool-skill<br/>@deepseek-ai/dsh-tool-skill"]
  cfg --> plugin_tui_tool_skill
  plugin_tui_commands["commands<br/>@deepseek-ai/dsh-commands"]
  cfg --> plugin_tui_commands
  plugin_tui_goal["goal<br/>@deepseek-ai/dsh-goal"]
  cfg --> plugin_tui_goal
  plugin_tui_goal_session["goal-session<br/>@deepseek-ai/dsh-goal-session"]
  cfg --> plugin_tui_goal_session
  plugin_tui_command_goal["command-goal<br/>@deepseek-ai/dsh-command-goal"]
  cfg --> plugin_tui_command_goal
  plugin_tui_plan_mode["plan-mode<br/>@deepseek-ai/dsh-plan-mode"]
  cfg --> plugin_tui_plan_mode
  plugin_tui_token_meter["token-meter<br/>@deepseek-ai/dsh-token-meter"]
  cfg --> plugin_tui_token_meter
  plugin_tui_compact_basic["compact-basic<br/>@deepseek-ai/dsh-compact-basic"]
  cfg --> plugin_tui_compact_basic
  plugin_tui_subagent["subagent<br/>@deepseek-ai/dsh-subagent"]
  cfg --> plugin_tui_subagent
  plugin_tui_subagent_spawn["subagent-spawn<br/>@deepseek-ai/dsh-subagent-spawn"]
  cfg --> plugin_tui_subagent_spawn
  plugin_tui_subagent_fork["subagent-fork<br/>@deepseek-ai/dsh-subagent-fork"]
  cfg --> plugin_tui_subagent_fork
  plugin_tui_tool_subagent["tool-subagent<br/>@deepseek-ai/dsh-tool-subagent"]
  cfg --> plugin_tui_tool_subagent
  plugin_tui_tool_subagent_fork["tool-subagent-fork<br/>@deepseek-ai/dsh-tool-subagent"]
  cfg --> plugin_tui_tool_subagent_fork
  plugin_tui_workflow_workerthread["workflow-workerthread<br/>@deepseek-ai/dsh-workflow-workerthread"]
  cfg --> plugin_tui_workflow_workerthread
  plugin_tui_tool_workflow["tool-workflow<br/>@deepseek-ai/dsh-tool-workflow"]
  cfg --> plugin_tui_tool_workflow
  plugin_tui_timeout_policy["timeout-policy<br/>@deepseek-ai/dsh-timeout-policy"]
  cfg --> plugin_tui_timeout_policy
  plugin_tui_spill_local["spill-local<br/>@deepseek-ai/dsh-spill-local"]
  cfg --> plugin_tui_spill_local
  plugin_tui_spill_policy["spill-policy<br/>@deepseek-ai/dsh-spill-policy"]
  cfg --> plugin_tui_spill_policy
  plugin_tui_tools["tools<br/>@deepseek-ai/dsh-tools"]
  cfg --> plugin_tui_tools
  plugin_tui_system_prompt["system-prompt<br/>@deepseek-ai/dsh-system-prompt"]
  cfg --> plugin_tui_system_prompt
  plugin_tui_agent_loop["agent-loop<br/>@deepseek-ai/dsh-agent-loop"]
  cfg --> plugin_tui_agent_loop
  plugin_tui_fs_local["fs-local<br/>@deepseek-ai/dsh-fs-local"]
  cfg --> plugin_tui_fs_local
  plugin_tui_llm_deepseek["llm-deepseek<br/>@deepseek-ai/dsh-llm-deepseek"]
  cfg --> plugin_tui_llm_deepseek
Plugin id Package / module
timer @cordisjs/plugin-timer
llm @deepseek-ai/dsh-llm
session @deepseek-ai/dsh-session
session-title @deepseek-ai/dsh-session-title
session-title-llm @deepseek-ai/dsh-session-title-first-message-llm
user-interaction @deepseek-ai/dsh-user-interaction
agent @deepseek-ai/dsh-agent
tasks @deepseek-ai/dsh-tasks-local
llm-retry @deepseek-ai/dsh-llm-retry
session-persistence-jsonl @deepseek-ai/dsh-session-persistence-jsonl
subprocess @deepseek-ai/dsh-subprocess-local
bash-local @deepseek-ai/dsh-bash-local
tool-bash @deepseek-ai/dsh-tool-bash
tool-tasks @deepseek-ai/dsh-tool-tasks
fs-policy @deepseek-ai/dsh-fs-policy
tool-fs @deepseek-ai/dsh-tool-fs
tool-fs-search @deepseek-ai/dsh-tool-fs-search
workspace-context @deepseek-ai/dsh-workspace-context
skill @deepseek-ai/dsh-skill
skill-local @deepseek-ai/dsh-skill-local
tool-skill @deepseek-ai/dsh-tool-skill
commands @deepseek-ai/dsh-commands
goal @deepseek-ai/dsh-goal
goal-session @deepseek-ai/dsh-goal-session
command-goal @deepseek-ai/dsh-command-goal
plan-mode @deepseek-ai/dsh-plan-mode
token-meter @deepseek-ai/dsh-token-meter
compact-basic @deepseek-ai/dsh-compact-basic
subagent @deepseek-ai/dsh-subagent
subagent-spawn @deepseek-ai/dsh-subagent-spawn
subagent-fork @deepseek-ai/dsh-subagent-fork
tool-subagent @deepseek-ai/dsh-tool-subagent
tool-subagent-fork @deepseek-ai/dsh-tool-subagent
workflow-workerthread @deepseek-ai/dsh-workflow-workerthread
tool-workflow @deepseek-ai/dsh-tool-workflow
timeout-policy @deepseek-ai/dsh-timeout-policy
spill-local @deepseek-ai/dsh-spill-local
spill-policy @deepseek-ai/dsh-spill-policy
tools @deepseek-ai/dsh-tools
system-prompt @deepseek-ai/dsh-system-prompt
agent-loop @deepseek-ai/dsh-agent-loop
fs-local @deepseek-ai/dsh-fs-local
llm-deepseek @deepseek-ai/dsh-llm-deepseek

Source config: apps/cli/base.cordis.yml.

Maintenance mode: hybrid: the leaf plugin list is parsed from its cordis.yml; app package expansion is curated from package source.