424 lines
16 KiB
YAML
424 lines
16 KiB
YAML
# 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 web-startup plugin injects `cmdlineArgs` and provides `webStartup` as an
|
|
# ordinary Cordis service. Rows configured from flags inject that service, so
|
|
# Loader resolves their expressions only after it exists. The web runtime then
|
|
# provides bind-dependent `webRuntime` values to the trust fence.
|
|
# `dsh --profile web --help` provides neither service, so no server binds.
|
|
|
|
# ── 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-presentation 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
|
|
|
|
# ── web-only host rows, the transport layer, and the browser roster ─────────
|
|
|
|
# `dsh.client` rows are the browser roster the modules node half scans into
|
|
# window.__DSH_BOOT__; the modules row is simultaneously a host row.
|
|
- insert:
|
|
- id: code-runtime
|
|
name: '@deepseek-ai/dsh-code-runtime-worker-thread'
|
|
|
|
- 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: message-feedback
|
|
name: '@deepseek-ai/dsh-message-feedback'
|
|
config:
|
|
maxNoteBytes: 8192
|
|
|
|
# Browser Session export: `/export` command plus the shared download dialog.
|
|
- id: session-log-download
|
|
name: '@deepseek-ai/dsh-session-log-download'
|
|
|
|
- id: workspace
|
|
name: '@deepseek-ai/dsh-workspace'
|
|
|
|
- id: session-projection-cache
|
|
name: '@deepseek-ai/dsh-session-projection-cache'
|
|
config:
|
|
writeEveryEvents: 200
|
|
writeIntervalMs: 5000
|
|
|
|
# Whole-log turn/step counts for the chat stats strip (the sessionStats
|
|
# projection key); the projection registry itself is a base-layer row.
|
|
- id: session-stats
|
|
name: '@deepseek-ai/dsh-session-stats'
|
|
|
|
# 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'
|
|
|
|
# Read-only projection of current Loader entries for trusted client RPCs.
|
|
- id: plugin-inventory
|
|
name: '@deepseek-ai/dsh-host-plugin-inventory'
|
|
|
|
# The API gateway: the transport-agnostic dispatch face every client shape
|
|
# shares. The base layer's agent-default-model service owns the default model.
|
|
- id: api-gateway
|
|
name: '@deepseek-ai/dsh-host-apiproxy'
|
|
|
|
- id: cordis-host-runner
|
|
name: '@deepseek-ai/dsh-cordis-host-runner'
|
|
|
|
# Ordinary provider for the parsed Web flags. Its plugin-level injection
|
|
# waits for cmdlineArgs; no launcher metadata or special row kind is needed.
|
|
- id: web-startup
|
|
name: '@deepseek-ai/dsh-web-app/startup'
|
|
|
|
# ── layer 2: transport/service ──────────────────────────────────────────────
|
|
|
|
# Plain route-registration carrier; host and port come from the app's
|
|
# webStartup provider, with these deployment fallbacks. The dist is served by
|
|
# the web-runtime row below through the fallback seat.
|
|
- id: webserver
|
|
name: '@deepseek-ai/dsh-host-webserver'
|
|
inject: [webStartup]
|
|
config:
|
|
host: !!js ctx.webStartup.host ?? '127.0.0.1'
|
|
port: !!js ctx.webStartup.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 the bash runtime variable, and prints the URL line. The
|
|
# webStartup provider supplies invocation-only values; after the server
|
|
# binds, this row samples LAN trust once and provides `webRuntime`. A
|
|
# complete agent-preset persona suppresses the prompt section for that
|
|
# agent while retaining the host-owned shell variable.
|
|
- id: web-runtime
|
|
name: '@deepseek-ai/dsh-web-app'
|
|
inject: [webStartup]
|
|
config:
|
|
printUrl: true
|
|
surfaceContext: true
|
|
trustedHosts: !!js ctx.webStartup.trustedHosts
|
|
|
|
# The client-plugin reload chain, always mounted: it is idle until a
|
|
# rebuild watcher (pnpm run dev:web) actually rewrites client bundles. It
|
|
# is a row rather than a child of web-runtime because its node half is a
|
|
# client-side package, which a host-side bundle cannot import.
|
|
- id: client-hmr
|
|
name: '@deepseek-ai/dsh-client-hmr'
|
|
|
|
# ── browser plugin roster (dsh.client rows; node halves are layer-2 hosts) ──
|
|
|
|
# Dual-face: the node half scans this tree, composes window.__DSH_BOOT__,
|
|
# and serves /plugins/<id>/client.js; the browser half is the module table
|
|
# the shell kernel constructs before cordis exists (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'
|
|
inject: [webRuntime]
|
|
config:
|
|
# LAN literals derived from the active bind plus --trusted-host extras.
|
|
# A deployment adding authorities keeps this expression and concatenates
|
|
# its literals, for example: ['app.internal', ...ctx.webRuntime.trustedHosts].
|
|
trustedHosts: !!js ctx.webRuntime.trustedHosts
|
|
|
|
- id: api-remotes
|
|
name: '@deepseek-ai/dsh-api-remotes'
|
|
|
|
- id: client-runtime
|
|
name: '@deepseek-ai/dsh-client-runtime'
|
|
|
|
- id: cordis-client-runner
|
|
name: '@deepseek-ai/dsh-cordis-client-runner'
|
|
|
|
- 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-settings-models
|
|
name: '@deepseek-ai/dsh-client-ui-settings-models'
|
|
|
|
- id: ui-settings-plugin-inventory
|
|
name: '@deepseek-ai/dsh-client-ui-settings-plugin-inventory'
|
|
|
|
- id: ui-conversation
|
|
name: '@deepseek-ai/dsh-client-ui-conversation'
|
|
|
|
# Tool call tree, generic fallback, and keyed business Tool views.
|
|
- id: ui-tool
|
|
name: '@deepseek-ai/dsh-client-ui-tool'
|
|
|
|
- id: ui-cordis
|
|
name: '@deepseek-ai/dsh-client-ui-cordis'
|
|
|
|
# Durable workflow lifecycle as an independent Chat node after the
|
|
# existing generic workflow tool row.
|
|
- id: ui-workflow-run
|
|
name: '@deepseek-ai/dsh-client-ui-workflow-run'
|
|
|
|
# Turn tail: the produced-files row under each closing assistant message.
|
|
# Remove this entry to turn the surface off; the tail hole renders empty.
|
|
- id: ui-deliverables
|
|
name: '@deepseek-ai/dsh-client-ui-deliverables'
|
|
|
|
|
|
- id: ui-workspace
|
|
name: '@deepseek-ai/dsh-client-ui-workspace'
|
|
|
|
# Input triggers: the '/' | '@' pipeline (ui-input-trigger), the command surface over
|
|
# it (ui-commands), and the two reference sources (ui-skill / ui-subagent).
|
|
- id: ui-input-trigger
|
|
name: '@deepseek-ai/dsh-client-ui-input-trigger'
|
|
|
|
- id: ui-commands
|
|
name: '@deepseek-ai/dsh-client-ui-commands'
|
|
|
|
- id: ui-skill
|
|
name: '@deepseek-ai/dsh-client-ui-skill'
|
|
|
|
- id: ui-subagent
|
|
name: '@deepseek-ai/dsh-client-ui-subagent'
|
|
|
|
# Background jobs: the session-header list over the jobsBySession mirror.
|
|
- id: ui-jobs
|
|
name: '@deepseek-ai/dsh-client-ui-jobs'
|
|
|
|
# Goal surface: GoalBar in the input dock over the goal session projection.
|
|
- id: ui-goal
|
|
name: '@deepseek-ai/dsh-client-ui-goal'
|
|
|
|
# Per-message feedback: Like/Dislike plus an optional note in the
|
|
# assistant-message action strip, over the messageFeedback Remote.
|
|
- id: ui-message-feedback
|
|
name: '@deepseek-ai/dsh-client-ui-message-feedback'
|
|
|
|
# Model selection: the /model popupSelect + composer seat over session.models.
|
|
- id: ui-model-selection
|
|
name: '@deepseek-ai/dsh-client-ui-model-selection'
|
|
|
|
- id: ui-permission
|
|
name: '@deepseek-ai/dsh-client-ui-permission-presets'
|
|
|
|
# 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'
|
|
|
|
# Plugin configuration: the host-plane sections a user owns, as expandable
|
|
# cards. A namespace this deployment does not expose renders nothing.
|
|
- id: ui-settings-plugins
|
|
name: '@deepseek-ai/dsh-client-ui-settings-plugins'
|
|
|
|
# Plan control: the composer plan seat over the plan projection + /plan channel.
|
|
- id: ui-plan
|
|
name: '@deepseek-ai/dsh-client-ui-plan'
|
|
|
|
- id: ui-user-questions
|
|
name: '@deepseek-ai/dsh-client-ui-user-questions'
|
|
|
|
- id: ui-trajectory
|
|
name: '@deepseek-ai/dsh-client-ui-trajectory'
|
|
|
|
# ── 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.
|
|
|
|
# `shell-env` STAYS in the host plane: `apps/cli/src/web.ts` injects it to
|
|
# publish `DSH_WEB_URL`/`DSH_WEB_MODE`, and a host row that injects a service is
|
|
# the criterion for host-plane ownership — injection resolves before any session
|
|
# exists, so there is no agent to key by. Behind a preset realm those variables
|
|
# would never reach the model's shell at all.
|
|
|
|
- id: tool-bash
|
|
disabled: true
|
|
|
|
- id: tool-pwsh
|
|
disabled: true
|
|
|
|
# The background-job REGISTRY stays on the host plane; only the model-facing
|
|
# `job_*` controls move. Its producers — `tool-bash` here, `tool-terminal` and a
|
|
# non-continuable `tool-subagent` elsewhere — are preset rows that resolve it
|
|
# with `ctx.get`, and an entry-local realm around the registry is invisible to
|
|
# every sibling row outside that realm, so `run_in_background` answered
|
|
# "background jobs unavailable" while the controls sat in the catalog. That is
|
|
# the `goals` criterion read from inside the preset: a Service a row outside its
|
|
# realm READS belongs to the plane both can see. The registry is keyed by owning
|
|
# agent, so one host instance serves every session exactly as before presets.
|
|
|
|
- id: tool-jobs
|
|
disabled: true
|
|
|
|
- id: tool-fs
|
|
disabled: true
|
|
|
|
- id: tool-fs-search
|
|
disabled: true
|
|
|
|
- id: tool-str-replace-editor
|
|
disabled: true
|
|
|
|
# The `skill` REGISTRY stays in the host plane. It is host+per-scope layered
|
|
# (the tools-registry shape): deployment-level providers — repository plugins,
|
|
# a host skill-filesystem row — register into its global layer, while a preset's
|
|
# `skill-filesystem` registers into that preset's layer, and each agent reads the
|
|
# merged catalog its scope chain selects. Only the per-agent rows move behind
|
|
# presets: the base host `skill-filesystem` row is disabled here (presets own local
|
|
# discovery), and `tool-skill` is what a preset mounts to give its agent the
|
|
# catalog and loader at all.
|
|
|
|
- id: skill-filesystem
|
|
disabled: true
|
|
|
|
- id: tool-skill
|
|
disabled: true
|
|
|
|
# The goal SERVICE, its session driver, and the `/goal` command STAY on the
|
|
# host plane; only the model-facing tool moves. The Gateway serves the goal
|
|
# domain as Remote endpoints, and a Remote method picks its receiver Service
|
|
# from a generated descriptor — it resolves `goals` on the host, so a
|
|
# per-session realm would answer `service-unavailable` for every browser call.
|
|
# That is the `shell-env` criterion read from the other side: injection is not
|
|
# the only host relationship a Service can have. The registry is keyed by
|
|
# session, so one host instance serves every session exactly as before presets.
|
|
|
|
- id: tool-goal
|
|
disabled: true
|
|
|
|
- id: plan-mode
|
|
disabled: true
|
|
|
|
# The token METER stays on the host plane; only the compaction backend that
|
|
# reads it moves. It owns the context-meter projection units, and that table is
|
|
# process-wide, so preset ownership would make the meter a function of which
|
|
# presets happen to be mounted rather than a per-session fact. Same criterion as
|
|
# `tasks` and `goals`; the reasoning has one home in
|
|
# `.agents/notes/implemented/architecture/2026-08-10-host-plane-ownership-after-presets.md`.
|
|
|
|
- id: compaction-basic
|
|
disabled: true
|
|
|
|
- id: command-compact
|
|
disabled: true
|
|
|
|
- id: tool-result-pruner
|
|
disabled: true
|
|
|
|
# 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.
|
|
|
|
- id: tool-subagent-control
|
|
disabled: true
|
|
|
|
- id: tool-subagent-list-agents
|
|
disabled: true
|
|
|
|
- id: tool-subagent
|
|
disabled: true
|
|
|
|
- id: tool-subagent-fork
|
|
disabled: true
|
|
|
|
# `tool-subagent-report` is host-plane for the same reason as the registry, not
|
|
# because a preset may not want it: it registers a CONTINUABLE SETUP on that
|
|
# singleton rather than a tool this agent calls, and the setup list is not
|
|
# scope-aware — one copy per mounted preset means every child gets `report`
|
|
# registered once per live session, which throws on the second.
|
|
|
|
- id: workflow-worker-thread
|
|
disabled: true
|
|
|
|
- id: tool-workflow
|
|
disabled: true
|
|
|
|
- id: tool-ralph
|
|
disabled: true
|
|
|
|
- id: agent-instructions
|
|
disabled: true
|
|
|
|
- id: tool-todo
|
|
disabled: true
|
|
|
|
- id: tool-web
|
|
disabled: true
|
|
|
|
# The preset roster. `config/agent-presets/` ships with the deployment and is
|
|
# read-only (its entries carry `system` trust); `$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.
|
|
#
|
|
# Only the SHIPPED root is an assembly fact: it sits beside the installed app's
|
|
# own config, so `apps/cli`'s `composeProfile` resolves and patches it in — the
|
|
# same treatment `distIndex` gets on the webserver row. The writable root is
|
|
# `dsh-agent-presets`' own default (`includeUserRoot`), so a composition that
|
|
# never reaches that patch still finds a person's presets.
|
|
- insert:
|
|
- id: agent-presets
|
|
name: '@deepseek-ai/dsh-agent-presets'
|
|
config:
|
|
default: standard
|