`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.
132 lines
5.2 KiB
YAML
132 lines
5.2 KiB
YAML
# `dsh` (the default surface) — the full-screen TUI, as a patch list over
|
|
# `base.cordis.yml`. The launcher includes the base and applies this file, then
|
|
# any `--config` overlay, then the personal `~/.dsh/config.yaml`, as sibling
|
|
# patch lists at ONE include level: patches never cross an include boundary, so
|
|
# stacking overlays as nested includes would silently stop reaching base rows.
|
|
#
|
|
# A patch replaces the targeted row's whole `config`, so each row below restates
|
|
# every key it owns. A patch whose `id` matches no row is skipped with a Loader
|
|
# warning, which is deliberate: one personal overlay is shared across surfaces,
|
|
# so a row that exists only under `web` must not fail the TUI's boot.
|
|
#
|
|
# The launcher owns session identity and the exit line, and provides both on the
|
|
# boot context rather than through config, so no key here — and no overlay
|
|
# replacing one — can drop `--resume`.
|
|
|
|
# ── surface-specific values the base deliberately omits ─────────────────────
|
|
|
|
# `main` is the agent the TUI drives. `provider`/`model` are the route `dsh
|
|
# login` rewrites and a personal overlay repoints; `cwd` anchors the session to
|
|
# the invoking directory, which is also what scopes `/resume` to this workspace.
|
|
- id: agent-loop
|
|
config:
|
|
agents:
|
|
- id: main
|
|
provider: deepseek
|
|
model: deepseek-v4-pro
|
|
cwd: !!js process.cwd()
|
|
|
|
# Keep the persona to identity and behavior; tool plugins own tool guidance.
|
|
# The loop resolves {{model}} from this agent's configuration.
|
|
- id: system-prompt
|
|
config:
|
|
persona: |
|
|
You are a coding agent powered by the {{model}} model.
|
|
|
|
Verify your work by running the code or tests. Keep answers brief and
|
|
factual.
|
|
|
|
# Shipped default: full thinking at max effort on every request (wire-only
|
|
# defaults; they never enter the request header).
|
|
- id: llm-deepseek
|
|
config:
|
|
apiKey: !!js process.env.DEEPSEEK_API_KEY
|
|
baseURL: !!js process.env.DEEPSEEK_BASE_URL
|
|
thinking: enabled
|
|
reasoningEffort: max
|
|
|
|
# This single-session app resolves relative paths from the process cwd.
|
|
- id: fs-local
|
|
config:
|
|
cwd: !!js process.cwd()
|
|
|
|
# The shipped TUI presents the native tool registry. `examples/code-mode` is the
|
|
# overlay that switches this row to the `run_code` transport.
|
|
- id: tools
|
|
config:
|
|
mode: native
|
|
|
|
# ── TUI-only rows ───────────────────────────────────────────────────────────
|
|
|
|
- insert:
|
|
# Development-only hot reload; it depends on Loader internals, so it stays a
|
|
# surface row rather than joining the shared base.
|
|
- id: hmr
|
|
name: '@cordisjs/plugin-hmr'
|
|
config:
|
|
root: ['.']
|
|
|
|
# Relational runtime checks over the authoritative event streams; each
|
|
# companion registers the assertions its own package owns.
|
|
- id: invariants
|
|
name: '@deepseek-ai/dsh-invariants'
|
|
- id: session-invariant
|
|
name: '@deepseek-ai/dsh-session/invariant'
|
|
- id: agent-invariant
|
|
name: '@deepseek-ai/dsh-agent/invariant'
|
|
- id: scope-invariant
|
|
name: '@deepseek-ai/dsh-scope/invariant'
|
|
- id: agent-loop-invariant
|
|
name: '@deepseek-ai/dsh-agent-loop/invariant'
|
|
|
|
- id: session-checkpoint-policy
|
|
name: '@deepseek-ai/dsh-session-checkpoint-policy'
|
|
|
|
# The derived query index behind `/resume`. The launcher owns the session
|
|
# store location, so it provides the resolved index path on the boot context
|
|
# (`launcherSessionQueryPath`); the index and the logs it indexes therefore
|
|
# cannot diverge. The project-local fallback applies when no launcher sets it.
|
|
- id: session-query-sqlite
|
|
name: '@deepseek-ai/dsh-session-query-sqlite'
|
|
config:
|
|
path: !!js launcherSessionQueryPath ?? './.sessions/session-query.db'
|
|
|
|
- id: session-reference
|
|
name: '@deepseek-ai/dsh-session-reference'
|
|
|
|
# Refuses write/edit inside the dsh checkout this launcher runs from, on that
|
|
# checkout's own branch, until the session loads dsh-customize. Inert
|
|
# everywhere else, so an ordinary project sees no change.
|
|
- id: source-guard
|
|
name: '@deepseek-ai/dsh-source-guard'
|
|
|
|
- id: tool-result-prune
|
|
name: '@deepseek-ai/dsh-compact-tool-result-prune'
|
|
|
|
# Persisted same-session goals reach the model and the slash menu here; the
|
|
# domain, driver, and `/goal` command are in the base.
|
|
- id: tool-goal
|
|
name: '@deepseek-ai/dsh-tool-goal'
|
|
|
|
# A separate fixed consumer demonstrates fresh-agent Ralph iteration without
|
|
# changing the workflow tool or same-session goal behavior.
|
|
- id: tool-ralph
|
|
name: '@deepseek-ai/dsh-tool-ralph'
|
|
|
|
# The keyboard-backed provider behind ask_user_question and the plan-mode
|
|
# review, and the front door it renders inside.
|
|
- id: tui-prompt
|
|
name: '@deepseek-ai/dsh-tui/prompt'
|
|
|
|
# The TUI renders exactly the agent the agent-loop row bound, so it reads the
|
|
# same launcher-owned identity rather than restating one.
|
|
- id: tui
|
|
name: '@deepseek-ai/dsh-tui'
|
|
config:
|
|
sessionId: !!js configuredAgentIdentities?.main?.id ?? 'main'
|
|
showReasoning: true
|
|
maxToolOutputLines: 6
|
|
|
|
- id: tool-ask-user
|
|
name: '@deepseek-ai/dsh-tool-ask-user'
|