2026-08-06 04:40:11 +08:00
|
|
|
# The dsh-web-app bundle patch: the browser surface over the dsh-base layer.
|
|
|
|
|
# Applied after dsh-base's insert; rows here override base rows by id, with
|
|
|
|
|
# the profile's own cordis.patch.yml and any --patch overlays still to come.
|
|
|
|
|
#
|
|
|
|
|
# A patch replaces the targeted row's whole `config`, so each row below
|
|
|
|
|
# restates every key it owns. The `dsh web` launcher alias turns --host/--port/
|
|
|
|
|
# --dev/--workspace-root/--trusted-host into further patches over these rows
|
|
|
|
|
# (`--dev` inserts the dsh-client-hmr row).
|
|
|
|
|
|
|
|
|
|
# ── surface-specific values the base deliberately omits ─────────────────────
|
|
|
|
|
|
|
|
|
|
- id: system-prompt
|
|
|
|
|
config:
|
|
|
|
|
persona: >-
|
|
|
|
|
You are a coding agent powered by the {{model}} model. Your working directory is {{cwd}}.
|
|
|
|
|
|
|
|
|
|
# TODO: Re-enable shared HMR for Web after its reload lifecycle is tested.
|
|
|
|
|
- id: hmr
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
# Web content search runs on an ephemeral in-memory index. The service
|
|
|
|
|
# activates at boot, while first-search defers the node:sqlite import and
|
|
|
|
|
# in-memory handle so Node 22 startup stays quiet until content search
|
|
|
|
|
# actually uses SQLite. That search then reconciles this boot's sources.
|
|
|
|
|
- id: session-query-sqlite
|
|
|
|
|
config:
|
|
|
|
|
path: ':memory:'
|
|
|
|
|
openAt: first-search
|
|
|
|
|
|
|
|
|
|
- id: tools
|
|
|
|
|
config:
|
|
|
|
|
# TEMPORARY workaround: DSH_TOOLS_MODE (native|code|both) opts a whole dsh
|
|
|
|
|
# process into Code Mode while per-session tool-mode selection is being
|
|
|
|
|
# designed; unset keeps the schema default (native). Remove the env seam
|
|
|
|
|
# once the web UI owns the choice per session.
|
|
|
|
|
mode: !!js process.env.DSH_TOOLS_MODE
|
|
|
|
|
|
|
|
|
|
- id: llm-deepseek
|
|
|
|
|
config:
|
|
|
|
|
apiKey: !!js process.env.DEEPSEEK_API_KEY
|
|
|
|
|
baseURL: !!js process.env.DEEPSEEK_BASE_URL
|
|
|
|
|
|
|
|
|
|
# ── web-only host rows, the transport layer, and the browser roster ─────────
|
|
|
|
|
|
|
|
|
|
# `dshClient` rows are the browser roster the modules node half scans into
|
|
|
|
|
# window.__DSH_BOOT__; the modules row is simultaneously a host row.
|
|
|
|
|
- insert:
|
|
|
|
|
- id: session-projection
|
|
|
|
|
name: '@deepseek-ai/dsh-session-projection'
|
|
|
|
|
|
|
|
|
|
- id: code-runtime
|
|
|
|
|
name: '@deepseek-ai/dsh-code-runtime-worker'
|
|
|
|
|
|
|
|
|
|
- id: storage
|
|
|
|
|
name: '@deepseek-ai/dsh-storage'
|
|
|
|
|
|
|
|
|
|
- id: storage-json
|
|
|
|
|
name: '@deepseek-ai/dsh-storage-json'
|
|
|
|
|
config:
|
|
|
|
|
root: !!js dshHomePath('storages')
|
|
|
|
|
|
|
|
|
|
- id: storage-domain
|
|
|
|
|
name: '@deepseek-ai/dsh-storage-domain'
|
|
|
|
|
config:
|
|
|
|
|
backend: json
|
|
|
|
|
|
|
|
|
|
- id: workspace
|
|
|
|
|
name: '@deepseek-ai/dsh-workspace'
|
|
|
|
|
|
|
|
|
|
- id: session-projection-cache
|
|
|
|
|
name: '@deepseek-ai/dsh-session-projection-cache'
|
|
|
|
|
config:
|
|
|
|
|
writeEveryEvents: 200
|
|
|
|
|
writeIntervalMs: 5000
|
|
|
|
|
|
|
|
|
|
# Resolve bind host, SSH launch, and display once at boot, then mount the
|
|
|
|
|
# matching dual-face directory picker. Mount -native or -browse directly in
|
|
|
|
|
# an overlay to pin the interaction.
|
|
|
|
|
- id: directory-picker
|
|
|
|
|
name: '@deepseek-ai/dsh-host-directory-picker-auto'
|
|
|
|
|
|
|
|
|
|
# The API gateway: the transport-agnostic dispatch face every client shape
|
|
|
|
|
# shares. provider/model are the host default routing — the profile json's
|
|
|
|
|
# mapping target (user config overrides these engineering defaults).
|
|
|
|
|
- id: api-gateway
|
|
|
|
|
name: '@deepseek-ai/dsh-host-apiproxy'
|
|
|
|
|
config:
|
|
|
|
|
provider: deepseek-official
|
|
|
|
|
model: deepseek-v4-flash
|
|
|
|
|
|
|
|
|
|
# ── layer 2: transport/service ──────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
# Plain route-registration carrier; host and port arrive as `dsh web`
|
|
|
|
|
# flag patches over these defaults. The dist is served by the web-runtime
|
|
|
|
|
# row below through the fallback seat.
|
|
|
|
|
- id: webserver
|
|
|
|
|
name: '@deepseek-ai/dsh-host-webserver'
|
|
|
|
|
config:
|
|
|
|
|
host: 127.0.0.1
|
|
|
|
|
port: 3080
|
|
|
|
|
|
|
|
|
|
# Web glue owned by this bundle: resolves the built frontend dist (an
|
|
|
|
|
# assembly fact of dsh-web-app, never user config), mounts the
|
|
|
|
|
# frontend-static fallback owner, registers the web-surface prompt
|
|
|
|
|
# section and bash runtime variables, and prints the URL line. `dsh web`
|
|
|
|
|
# patches mode/lanAddresses over these defaults.
|
|
|
|
|
- id: web-runtime
|
|
|
|
|
name: '@deepseek-ai/dsh-web-app'
|
|
|
|
|
config:
|
|
|
|
|
mode: production
|
|
|
|
|
printUrl: true
|
|
|
|
|
|
|
|
|
|
# ── browser plugin roster (dshClient rows; node halves are layer-2 hosts) ──
|
|
|
|
|
|
|
|
|
|
# Dual-face: node half scans this very tree for dshClient rows, composes
|
|
|
|
|
# window.__DSH_BOOT__, serves /plugins/<id>/client.js; browser half is the
|
|
|
|
|
# module table the shell kernel constructs before cordis exists (§4.7 —
|
|
|
|
|
# adopted as a plugin entry by the kernel, never fetched).
|
|
|
|
|
- id: modules
|
|
|
|
|
name: '@deepseek-ai/dsh-client-modules'
|
|
|
|
|
|
|
|
|
|
# Owns both ends of the web transport: node half binds the gateway to the
|
|
|
|
|
# webserver under /api; browser half is the fetch/SSE client.
|
|
|
|
|
- id: connection
|
|
|
|
|
name: '@deepseek-ai/dsh-client-connection'
|
|
|
|
|
|
|
|
|
|
- id: client-runtime
|
|
|
|
|
name: '@deepseek-ai/dsh-client-runtime'
|
|
|
|
|
|
|
|
|
|
- id: ui-theme
|
|
|
|
|
name: '@deepseek-ai/dsh-client-ui-theme'
|
|
|
|
|
|
|
|
|
|
- id: locale
|
|
|
|
|
name: '@deepseek-ai/dsh-client-locale'
|
|
|
|
|
|
|
|
|
|
- id: ui-layout
|
|
|
|
|
name: '@deepseek-ai/dsh-client-ui-layout'
|
|
|
|
|
|
|
|
|
|
- id: ui-sidebar
|
|
|
|
|
name: '@deepseek-ai/dsh-client-ui-sidebar'
|
|
|
|
|
|
|
|
|
|
- id: ui-settings
|
|
|
|
|
name: '@deepseek-ai/dsh-client-ui-settings'
|
|
|
|
|
|
|
|
|
|
- id: ui-settings-general
|
|
|
|
|
name: '@deepseek-ai/dsh-client-ui-settings-general'
|
|
|
|
|
|
|
|
|
|
- id: ui-models
|
|
|
|
|
name: '@deepseek-ai/dsh-client-ui-models'
|
|
|
|
|
|
|
|
|
|
- id: ui-conversation
|
|
|
|
|
name: '@deepseek-ai/dsh-client-ui-conversation'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- id: ui-workspace
|
|
|
|
|
name: '@deepseek-ai/dsh-client-ui-workspace'
|
|
|
|
|
|
|
|
|
|
# Input triggers: the '/' | '@' pipeline (ui-slash), the command surface over
|
|
|
|
|
# it (ui-command), and the two reference sources (ui-skill / ui-subagent).
|
|
|
|
|
- id: ui-slash
|
|
|
|
|
name: '@deepseek-ai/dsh-client-ui-slash'
|
|
|
|
|
|
|
|
|
|
- id: ui-command
|
|
|
|
|
name: '@deepseek-ai/dsh-client-ui-command'
|
|
|
|
|
|
|
|
|
|
- id: ui-skill
|
|
|
|
|
name: '@deepseek-ai/dsh-client-ui-skill'
|
|
|
|
|
|
|
|
|
|
- id: ui-subagent
|
|
|
|
|
name: '@deepseek-ai/dsh-client-ui-subagent'
|
|
|
|
|
|
|
|
|
|
# Goal surface: GoalBar in the input dock over the goal session projection.
|
|
|
|
|
- id: ui-goal
|
|
|
|
|
name: '@deepseek-ai/dsh-client-ui-goal'
|
|
|
|
|
|
|
|
|
|
# Model selection: the /model popupSelect + composer seat over session.models.
|
|
|
|
|
- id: ui-model
|
|
|
|
|
name: '@deepseek-ai/dsh-client-ui-model'
|
|
|
|
|
|
|
|
|
|
- id: ui-permission
|
|
|
|
|
name: '@deepseek-ai/dsh-client-ui-permission'
|
|
|
|
|
|
2026-08-04 00:25:19 +08:00
|
|
|
# The agent-preset row in General settings: the default preset for
|
|
|
|
|
# sessions created later. Absent a roster it renders nothing.
|
|
|
|
|
- id: ui-agent-preset
|
|
|
|
|
name: '@deepseek-ai/dsh-client-ui-agent-preset'
|
|
|
|
|
|
2026-08-06 04:40:11 +08:00
|
|
|
# Plan control: the composer plan seat over the plan projection + /plan channel.
|
|
|
|
|
- id: ui-plan
|
|
|
|
|
name: '@deepseek-ai/dsh-client-ui-plan'
|
|
|
|
|
|
|
|
|
|
- id: ui-question
|
|
|
|
|
name: '@deepseek-ai/dsh-client-ui-question'
|
|
|
|
|
|
|
|
|
|
- id: ui-trajectory
|
|
|
|
|
name: '@deepseek-ai/dsh-client-ui-trajectory'
|
feat(web): move the agent plane behind per-session presets
The Web overlay disables base's 32 agent-plane rows and mounts the preset
roster instead, so each session composes its own tools and prompt rather than
sharing one process-wide set. The TUI keeps base unchanged: it is single-session
and composing its agent process-wide is correct there.
`roots` is patched in by AppCLIEntry, like `distIndex`: the shipped presets sit
beside the composition that names them and the user's live under the Harness
home, neither of which a config author chooses.
A session's preset is fixed at creation. Naming a different one for an existing
identity is `agent-preset-conflict` rather than a switch, because that
session's history was produced under the first preset's tools. The guard sits
after `await creation`, beside the cwd check, so it covers every path that
yields a live agent — freshly created, adopted live, resumed, or recovered by
the concurrent-creation catch. A request naming no preset adopts the session as
it is, keeping reconnect and retry ordinary.
Two bugs the real-composition test caught, both invisible to unit tests:
`PresetTree` now refuses to write. The Loader persists a tree whose plugin
self-disposed, and tearing an agent down disposes its whole subtree — inherited,
that rewrote the shipped composition, truncating a 241-line preset to `[]` the
first time a session ended.
`dsh-tool-skill` compared against a lookup of its own name in the global layer,
so it threw inside any preset: `register()` files into the calling context's
scope. It now compares against the definition it registered, which is what the
identity check meant all along.
The `standard` catalog is asserted exactly, not spot-checked: a row that
registers into the wrong layer mounts cleanly and simply contributes nothing, so
an omission is this design's quietest failure. It matches the shipped TUI
catalog plus `glob`/`grep`, the pair that composition documents as
ripgrep-dependent.
Re-records `cordis-inspect-jsdoc`, whose rendered `SessionHeader` gains the
`agentPreset` field. `fs-glob-sampling` fails identically on pristine master
and is untouched here.
The browser e2e scaffold gains the roster fact AppCLIEntry supplies. `roots` is
resolved and patched in by the CLI entry, like `distIndex` on the webserver row,
and this lane boots the shipped tree without that entry — so it has to supply
the same fact or the roster resolves nothing and every session in the lane
composes an agent with no tools, no persona, and no token meter. Only the
shipped root: a developer's own `~/.dsh/.agent-presets` must not decide a golden. The
`cordis:group` builtin comes with it, exactly as `boot()` registers it, because
a preset resolving package names from its own directory cannot reach
`@cordisjs/plugin-group` by name.
The lane stays red through this layer and the next four for the reason stated
above — the api-proxy injects `subagents`, `workspace`, and `tools`, so
`api-gateway` cannot activate and the browser has no `/api` at all. It goes
green again in the layer that returns those registries to the host plane; this
change is what makes that layer's fix sufficient rather than partial.
2026-08-03 23:44:09 +08:00
|
|
|
|
|
|
|
|
# ── the agent plane moves behind agent presets ─────────────────────────────
|
|
|
|
|
#
|
|
|
|
|
# Every row below composes what ONE agent contributes to the host registries:
|
|
|
|
|
# its tools, its prompt sections, its delegation backends. The base keeps them
|
|
|
|
|
# for the TUI, which is single-session and composes its agent process-wide; the
|
|
|
|
|
# Web surface disables them here and lets each session mount a preset instead.
|
|
|
|
|
#
|
|
|
|
|
# Disabling rather than deleting is deliberate: the base is shared, and a row
|
|
|
|
|
# absent from a surface overlay would silently reappear the day someone reorders
|
|
|
|
|
# the composition.
|
|
|
|
|
|
2026-08-05 15:40:32 +08:00
|
|
|
- id: bash-env
|
|
|
|
|
disabled: true
|
|
|
|
|
|
feat(web): move the agent plane behind per-session presets
The Web overlay disables base's 32 agent-plane rows and mounts the preset
roster instead, so each session composes its own tools and prompt rather than
sharing one process-wide set. The TUI keeps base unchanged: it is single-session
and composing its agent process-wide is correct there.
`roots` is patched in by AppCLIEntry, like `distIndex`: the shipped presets sit
beside the composition that names them and the user's live under the Harness
home, neither of which a config author chooses.
A session's preset is fixed at creation. Naming a different one for an existing
identity is `agent-preset-conflict` rather than a switch, because that
session's history was produced under the first preset's tools. The guard sits
after `await creation`, beside the cwd check, so it covers every path that
yields a live agent — freshly created, adopted live, resumed, or recovered by
the concurrent-creation catch. A request naming no preset adopts the session as
it is, keeping reconnect and retry ordinary.
Two bugs the real-composition test caught, both invisible to unit tests:
`PresetTree` now refuses to write. The Loader persists a tree whose plugin
self-disposed, and tearing an agent down disposes its whole subtree — inherited,
that rewrote the shipped composition, truncating a 241-line preset to `[]` the
first time a session ended.
`dsh-tool-skill` compared against a lookup of its own name in the global layer,
so it threw inside any preset: `register()` files into the calling context's
scope. It now compares against the definition it registered, which is what the
identity check meant all along.
The `standard` catalog is asserted exactly, not spot-checked: a row that
registers into the wrong layer mounts cleanly and simply contributes nothing, so
an omission is this design's quietest failure. It matches the shipped TUI
catalog plus `glob`/`grep`, the pair that composition documents as
ripgrep-dependent.
Re-records `cordis-inspect-jsdoc`, whose rendered `SessionHeader` gains the
`agentPreset` field. `fs-glob-sampling` fails identically on pristine master
and is untouched here.
The browser e2e scaffold gains the roster fact AppCLIEntry supplies. `roots` is
resolved and patched in by the CLI entry, like `distIndex` on the webserver row,
and this lane boots the shipped tree without that entry — so it has to supply
the same fact or the roster resolves nothing and every session in the lane
composes an agent with no tools, no persona, and no token meter. Only the
shipped root: a developer's own `~/.dsh/.agent-presets` must not decide a golden. The
`cordis:group` builtin comes with it, exactly as `boot()` registers it, because
a preset resolving package names from its own directory cannot reach
`@cordisjs/plugin-group` by name.
The lane stays red through this layer and the next four for the reason stated
above — the api-proxy injects `subagents`, `workspace`, and `tools`, so
`api-gateway` cannot activate and the browser has no `/api` at all. It goes
green again in the layer that returns those registries to the host plane; this
change is what makes that layer's fix sufficient rather than partial.
2026-08-03 23:44:09 +08:00
|
|
|
- id: tool-bash
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: tool-tasks
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: tasks
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: tool-fs
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: tool-fs-search
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: tool-str-replace-editor
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: skill
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: skill-local
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: tool-skill
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: goal
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: goal-session
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: command-goal
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: tool-goal
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: plan-mode
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: token-meter
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: compact-basic
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: command-compact
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: tool-result-prune
|
|
|
|
|
disabled: true
|
|
|
|
|
|
2026-08-04 12:46:57 +08:00
|
|
|
# The subagent registry and its backends STAY in the host plane. `subagents` is
|
|
|
|
|
# a process singleton with a cross-session query surface (`listChildren`,
|
|
|
|
|
# `followup`) that the host api-proxy serves to the browser, and a provider
|
|
|
|
|
# registers under a globally unique name, so a per-session copy would both
|
|
|
|
|
# starve that host row and collide on the second session. What a preset
|
|
|
|
|
# chooses is which delegation TOOLS its agent sees, below.
|
feat(web): move the agent plane behind per-session presets
The Web overlay disables base's 32 agent-plane rows and mounts the preset
roster instead, so each session composes its own tools and prompt rather than
sharing one process-wide set. The TUI keeps base unchanged: it is single-session
and composing its agent process-wide is correct there.
`roots` is patched in by AppCLIEntry, like `distIndex`: the shipped presets sit
beside the composition that names them and the user's live under the Harness
home, neither of which a config author chooses.
A session's preset is fixed at creation. Naming a different one for an existing
identity is `agent-preset-conflict` rather than a switch, because that
session's history was produced under the first preset's tools. The guard sits
after `await creation`, beside the cwd check, so it covers every path that
yields a live agent — freshly created, adopted live, resumed, or recovered by
the concurrent-creation catch. A request naming no preset adopts the session as
it is, keeping reconnect and retry ordinary.
Two bugs the real-composition test caught, both invisible to unit tests:
`PresetTree` now refuses to write. The Loader persists a tree whose plugin
self-disposed, and tearing an agent down disposes its whole subtree — inherited,
that rewrote the shipped composition, truncating a 241-line preset to `[]` the
first time a session ended.
`dsh-tool-skill` compared against a lookup of its own name in the global layer,
so it threw inside any preset: `register()` files into the calling context's
scope. It now compares against the definition it registered, which is what the
identity check meant all along.
The `standard` catalog is asserted exactly, not spot-checked: a row that
registers into the wrong layer mounts cleanly and simply contributes nothing, so
an omission is this design's quietest failure. It matches the shipped TUI
catalog plus `glob`/`grep`, the pair that composition documents as
ripgrep-dependent.
Re-records `cordis-inspect-jsdoc`, whose rendered `SessionHeader` gains the
`agentPreset` field. `fs-glob-sampling` fails identically on pristine master
and is untouched here.
The browser e2e scaffold gains the roster fact AppCLIEntry supplies. `roots` is
resolved and patched in by the CLI entry, like `distIndex` on the webserver row,
and this lane boots the shipped tree without that entry — so it has to supply
the same fact or the roster resolves nothing and every session in the lane
composes an agent with no tools, no persona, and no token meter. Only the
shipped root: a developer's own `~/.dsh/.agent-presets` must not decide a golden. The
`cordis:group` builtin comes with it, exactly as `boot()` registers it, because
a preset resolving package names from its own directory cannot reach
`@cordisjs/plugin-group` by name.
The lane stays red through this layer and the next four for the reason stated
above — the api-proxy injects `subagents`, `workspace`, and `tools`, so
`api-gateway` cannot activate and the browser has no `/api` at all. It goes
green again in the layer that returns those registries to the host plane; this
change is what makes that layer's fix sufficient rather than partial.
2026-08-03 23:44:09 +08:00
|
|
|
|
|
|
|
|
- id: tool-subagent-control
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: tool-subagent-list-agents
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: tool-subagent
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: tool-subagent-fork
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: tool-subagent-report
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: workflow-workerthread
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: tool-workflow
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: tool-ralph
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: workspace-context
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: tool-todo
|
|
|
|
|
disabled: true
|
|
|
|
|
|
|
|
|
|
- id: tool-web
|
|
|
|
|
disabled: true
|
|
|
|
|
|
2026-08-06 13:43:32 +08:00
|
|
|
# The preset roster. `config/agent-presets/` ships with the deployment and is
|
|
|
|
|
# read-only (its entries carry `system` trust);
|
feat(web): move the agent plane behind per-session presets
The Web overlay disables base's 32 agent-plane rows and mounts the preset
roster instead, so each session composes its own tools and prompt rather than
sharing one process-wide set. The TUI keeps base unchanged: it is single-session
and composing its agent process-wide is correct there.
`roots` is patched in by AppCLIEntry, like `distIndex`: the shipped presets sit
beside the composition that names them and the user's live under the Harness
home, neither of which a config author chooses.
A session's preset is fixed at creation. Naming a different one for an existing
identity is `agent-preset-conflict` rather than a switch, because that
session's history was produced under the first preset's tools. The guard sits
after `await creation`, beside the cwd check, so it covers every path that
yields a live agent — freshly created, adopted live, resumed, or recovered by
the concurrent-creation catch. A request naming no preset adopts the session as
it is, keeping reconnect and retry ordinary.
Two bugs the real-composition test caught, both invisible to unit tests:
`PresetTree` now refuses to write. The Loader persists a tree whose plugin
self-disposed, and tearing an agent down disposes its whole subtree — inherited,
that rewrote the shipped composition, truncating a 241-line preset to `[]` the
first time a session ended.
`dsh-tool-skill` compared against a lookup of its own name in the global layer,
so it threw inside any preset: `register()` files into the calling context's
scope. It now compares against the definition it registered, which is what the
identity check meant all along.
The `standard` catalog is asserted exactly, not spot-checked: a row that
registers into the wrong layer mounts cleanly and simply contributes nothing, so
an omission is this design's quietest failure. It matches the shipped TUI
catalog plus `glob`/`grep`, the pair that composition documents as
ripgrep-dependent.
Re-records `cordis-inspect-jsdoc`, whose rendered `SessionHeader` gains the
`agentPreset` field. `fs-glob-sampling` fails identically on pristine master
and is untouched here.
The browser e2e scaffold gains the roster fact AppCLIEntry supplies. `roots` is
resolved and patched in by the CLI entry, like `distIndex` on the webserver row,
and this lane boots the shipped tree without that entry — so it has to supply
the same fact or the roster resolves nothing and every session in the lane
composes an agent with no tools, no persona, and no token meter. Only the
shipped root: a developer's own `~/.dsh/.agent-presets` must not decide a golden. The
`cordis:group` builtin comes with it, exactly as `boot()` registers it, because
a preset resolving package names from its own directory cannot reach
`@cordisjs/plugin-group` by name.
The lane stays red through this layer and the next four for the reason stated
above — the api-proxy injects `subagents`, `workspace`, and `tools`, so
`api-gateway` cannot activate and the browser has no `/api` at all. It goes
green again in the layer that returns those registries to the host plane; this
change is what makes that layer's fix sufficient rather than partial.
2026-08-03 23:44:09 +08:00
|
|
|
# `$DSH_HOME/.agent-presets` is where a person — or an agent — authors their own, and
|
|
|
|
|
# carries the same trust as shell access because a preset IS a composition.
|
|
|
|
|
# `roots` is an assembly fact, not user config: the shipped preset directory
|
|
|
|
|
# ships beside this file, so AppCLIEntry resolves it and patches it in — the
|
|
|
|
|
# same treatment `distIndex` gets on the webserver row.
|
|
|
|
|
- insert:
|
|
|
|
|
- id: agent-presets
|
|
|
|
|
name: '@deepseek-ai/dsh-agent-presets'
|
|
|
|
|
config:
|
|
|
|
|
default: standard
|