# The dsh-base bundle patch: the shared core of each base-backed profile, applied as
# ONE insert over the empty profile root. Later bundle patches and the user's
# profile cordis.patch.yml address these rows by id, with the last write
# winning per row.
#
# A patch replaces the targeted row's whole `config` rather than merging into
# it, so a row whose value differs by mode does NOT live here: it belongs to
# each mode bundle, keeping any single row down to one bundle layer plus the
# user's. Mode-specific rows appear below only with shared plugin identity and
# neutral defaults; each mode bundle restates its complete configuration.
#
# Row order carries no load semantics (activation is service-availability
# driven); the grouping is for readers.

- insert:
    - id: tool-plugin-manager
      name: '@deepseek-ai/dsh-plugin-manager/tools'
      disabled: true

    - id: plugin-manager
      name: '@deepseek-ai/dsh-plugin-manager'
      disabled: !!js "!ctx.get('profileContext')"

    - id: timer
      name: '@deepseek-ai/cordis-plugin-timer'

    # Profile configuration reloads by default; module roots are opt-in.
    - id: hmr
      name: '@deepseek-ai/dsh-hmr'
      disabled: !!js "!ctx.get('profileContext')"
      config:
        root: []

    - id: llm
      name: '@deepseek-ai/dsh-llm'

    - id: deepseek-llm-api-extensions
      name: '@deepseek-ai/dsh-deepseek-llm-api-extensions'

    - id: session
      name: '@deepseek-ai/dsh-session'

    - id: session-log-deepseek
      name: '@deepseek-ai/dsh-session-log-deepseek'

    - id: typert
      name: '@deepseek-ai/dsh-typert-registry'

    - id: typert-loader
      name: '@deepseek-ai/dsh-typert-loader'

    - id: typert-gateway
      name: '@deepseek-ai/dsh-api-gateway'

    - id: session-title
      name: '@deepseek-ai/dsh-session-title'
      config:
        fallbackMaxWords: 5
        fallbackMaxBytes: 40
        maxTitleBytes: 80

    - id: session-title-llm
      name: '@deepseek-ai/dsh-session-title-first-prompt-llm'
      config:
        targetWords: 5
        targetCjkCharacters: 10
        maxInputBytes: 4096
        maxOutputTokens: 64
        timeoutMs: 60000

    - id: user-questions
      name: '@deepseek-ai/dsh-user-questions'

    - id: agent
      name: '@deepseek-ai/dsh-agent'

    - id: plugin-package-inventory-deepseek
      name: '@deepseek-ai/dsh-plugin-package-inventory-deepseek'

    # The transport-independent default for Agents created by entry points.
    # Settings may supply a saved selection; consumers read it at creation time.
    - id: agent-default-model
      name: '@deepseek-ai/dsh-agent-default-model'
      config:
        provider: deepseek-official
        model: deepseek-flash

    - id: jobs
      name: '@deepseek-ai/dsh-jobs-local'

    - id: llm-retry
      name: '@deepseek-ai/dsh-llm-retry'

    # Live Config forms persist through the active profile patch.

    # Live configuration forms persist through the launcher's profile.
    - id: config-editor
      name: '@deepseek-ai/dsh-config-editor'
      disabled: !!js "!ctx.get('profileContext')"

    - id: settings
      name: '@deepseek-ai/dsh-settings'
      disabled: !!js "!ctx.get('profileContext')"

    # Credential sources: inherited environment over the managed
    # `$DSH_HOME/.credentials.yaml`, with project and user `.env` fallbacks.
    # Adapters resolve references per request; the Models page writes only the
    # managed document, which is never materialized into the process environment.
    - id: authorization
      name: '@deepseek-ai/dsh-authorization'

    - id: deepseek-account
      name: '@deepseek-ai/dsh-deepseek-account-platform'
      config:
        desktopPlatform: !!js "ctx.get('profileContext')?.name === 'desktop' && ['darwin', 'win32'].includes(process.platform) ? process.platform : null"

    - id: credentials
      name: '@toddzheng024/dscode-bundle/credentials'

    # The pi-ai multi-provider twin, mounted dormant: zero routes (and no extra
    # models in the picker) until a `llm-pi-ai:` settings section supplies provider
    # profiles — then those routes register live, keys resolving per request
    # through their apiKeyEnv references, and drop again when the section empties.
    # Supplying those profiles is exactly what the web Models page does. Which
    # adapters exist is composition; which providers run is the user's settings
    # document.
    - id: llm-pi-ai
      name: '@deepseek-ai/dsh-llm-pi-ai'

    - id: session-persistence-jsonl
      name: '@deepseek-ai/dsh-session-persistence-jsonl'
      config:
        root: !!js dshHomePath('sessions')

    # Durable image bytes live outside the append-only session log. Messages
    # keep content-addressed references that this shared backend resolves for
    # provider requests and authorized history reads.
    - id: attachment-local
      name: '@deepseek-ai/dsh-attachment-local'

    # Full-text session search is opt-in. `openAt: never` keeps
    # ctx.sessionQuery mounted — exact reads, titles, and lineage traces
    # (session export, subagent-fork Workspace inheritance) stay available —
    # while search calls fail with SESSION_QUERY_SEARCH_DISABLED and SQLite is
    # never opened; the Web sidebar search matches titles and workspace names
    # only. Deployments enabling content search override `openAt` to
    # `first-search` or `startup` in a later patch layer (profile
    # cordis.patch.yml or a --patch overlay), typically with a durable `path`.
    - id: session-query-sqlite
      name: '@deepseek-ai/dsh-session-query-sqlite'
      config:
        path: ':memory:'
        openAt: never

    # Shared projection registry: subagent catalog identity (mode/label) folds
    # through its registered units, so the `list_agents` surface below fails
    # loud without it; web layers reuse this same mount for list rows.
    - id: session-projection
      name: '@deepseek-ai/dsh-session-projection'

    # Durable KV storage: the storage hub, the json backend, and the
    # schema-validated domain form over them. Session-layer persistence (the
    # projection cache below; workspace in web layers)
    # routes through this stack, so it belongs to the shared base.
    - 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

    # Persisted projection cache: throttled write-behind over the
    # session_projcache domain (per-record layout — one version-stamped
    # checkpoint document per session), serving the session listing's
    # projection column.
    - id: session-projection-cache
      name: '@deepseek-ai/dsh-session-projection-cache'
      config:
        writeEveryEvents: 200
        writeIntervalMs: 5000

    - id: otel
      name: '@deepseek-ai/dsh-otel'

    # OTel releases a Session-log prefix only after explicit user feedback,
    # regardless of model provider. Ordinary activity never triggers capture.
    # DSH_TELEMETRY_OTLP_URL overrides the production endpoint. A non-empty
    # DSH_TELEMETRY_DISABLED — any value, including '0'/'false' — opts the
    # process out (the launchers patch the row disabled; config cannot disable
    # a row). Exports carry the harness home's anonymous user id ($DSH_HOME/.anonymous-user-id,
    # random UUID; delete the file to reset the identity) as the Resource's
    # user.id. Byte-bounded batching may turn an authorized prefix into
    # several HTTP requests. Requests run serially; each has its own 1s
    # transport timeout and 1.5s watchdog. A watchdog does not release the
    # active request slot. The outer 3s shutdown deadline stops queued sends;
    # large prefixes or an unsettled transport may leave records unsent.
    # Every CLI exit path drains by disposing the root on SIGINT/SIGTERM.
    - id: session-telemetry-otel
      name: '@deepseek-ai/dsh-session-telemetry-otel'
      config:
        mode: !!js process.env.DSH_TELEMETRY_MODE || 'FEEDBACK_ONLY'
        shutdownTimeoutMillis: 3000
        maxRequestBytes: 4000000
        exporter:
          url: !!js process.env.DSH_TELEMETRY_OTLP_URL ?? 'https://dsh-otel-collector.deepseeksvc.com/v1/logs'
          compression: gzip
          timeoutMillis: 1000
        processor:
          scheduledDelayMillis: 10000
          maxQueueSize: 2048
          maxExportBatchSize: 2048
          exportTimeoutMillis: 1500

    - id: subprocess
      name: '@deepseek-ai/dsh-subprocess-local'

    # Every shipped CLI mode starts with the same file-effect boundary.
    # The environment remains an explicit deployment override; otherwise fresh
    # sessions pin workspace-write + ask through the permission service below.
    - id: sandbox
      name: '@deepseek-ai/dsh-sandbox-local'

    - id: sandbox-policy
      name: '@deepseek-ai/dsh-sandbox-policy'
      config:
        mode: !!js process.env.DSH_PERMISSION_MODE ?? 'workspace-write'
        workspaceRoot: !!js process.cwd()

    - id: bash-sandbox
      name: '@deepseek-ai/dsh-bash-sandbox'
      disabled: !!js process.platform === 'win32'
      config:
        timeoutMs: 60000

    - id: pwsh-sandbox
      name: '@deepseek-ai/dsh-pwsh-sandbox'
      disabled: !!js process.platform !== 'win32'

    - id: approval
      name: '@deepseek-ai/dsh-user-approval'
      config:
        policy: !!js "(process.env.DSH_PERMISSION_MODE ?? 'workspace-write') === 'danger-full-access' ? 'never' : 'ask'"

    - id: permission
      name: '@deepseek-ai/dsh-permission-presets'
      config:
        presets:
          read-only:
            sandbox: read-only
            approval: ask
          workspace-write:
            sandbox: workspace-write
            approval: ask
          danger-full-access:
            sandbox: danger-full-access
            approval: never

    - id: shell-env
      name: '@deepseek-ai/dsh-shell-env'

    - id: tool-bash
      name: '@deepseek-ai/dsh-tool-bash'
      disabled: !!js process.platform === 'win32'

    - id: tool-pwsh
      name: '@deepseek-ai/dsh-tool-pwsh'
      disabled: !!js process.platform !== 'win32'

    - id: tool-jobs
      name: '@deepseek-ai/dsh-tool-jobs'

    - id: fs-observation-policy
      name: '@deepseek-ai/dsh-fs-observation-policy'

    - id: tool-fs
      name: '@deepseek-ai/dsh-tool-fs'

    - id: tool-fs-search
      name: '@deepseek-ai/dsh-tool-fs-search'
      config:
        sampleOverCapGlobResults: false

    - id: agent-instructions
      name: '@deepseek-ai/dsh-agent-instructions'
      config:
        maxBytes: 65536

    - id: skill
      name: '@deepseek-ai/dsh-skill'

    - id: skill-filesystem
      name: '@deepseek-ai/dsh-skill-filesystem'

    - id: skill-badge
      name: '@deepseek-ai/dsh-skill-badge'
      disabled: true

    - id: tool-skill
      name: '@deepseek-ai/dsh-tool-skill'

    - id: commands
      name: '@deepseek-ai/dsh-commands'

    - id: command-feedback
      name: '@deepseek-ai/dsh-command-feedback'

    - id: goal
      name: '@deepseek-ai/dsh-goal'

    - id: goal-round-driver
      name: '@deepseek-ai/dsh-goal-round-driver'

    - id: command-goal
      name: '@deepseek-ai/dsh-command-goal'

    - id: plan-mode
      name: '@deepseek-ai/dsh-plan-mode'
      config:
        section: |
              You are in plan mode. Stay in plan mode until exit_plan_mode succeeds or the user switches the session mode. Imperative language to implement changes means plan the implementation, not execute it. A user's conversational agreement — including an answer confirming something you asked — approves nothing and does not end plan mode; fold the confirmed decision into the plan and submit it through exit_plan_mode.

              Explore first. Use non-mutating reads, searches, static analysis, and checks to ground the plan in the actual repository. Do not edit or write files, change configuration, run formatters or code generation that rewrites tracked files, commit, or otherwise carry out the plan. Prefer existing functions and patterns over new machinery.

              The tool catalog stays the same across modes for request-cache stability. These plan-mode rules override any later tool description or guidance that suggests using mutation tools; those tools remain listed only to keep the request shape stable. Do not use todo_write to track this planning phase: it tracks implementation after an approved plan, while the plan itself belongs in exit_plan_mode.

              Resolve discoverable facts by inspection. Use ask_user_question only for user-owned choices or material ambiguity that inspection cannot answer. Do not ask the user where code lives or how current behavior works when you can find out.

              Make the plan decision-complete: state the goal and success criteria; group implementation changes by subsystem; identify public API, schema, and data-flow changes; cover edge cases, failure modes, tests, acceptance criteria, and explicit assumptions. Keep it concise enough to review but detailed enough that another engineer can implement it without making design decisions.

              When ready, call exit_plan_mode with the complete plan markdown, starting with a # title. Make exit_plan_mode the only and final tool call in that assistant response: it presents the plan for approval, and implementation begins only in a later step after approval. Do not paste the final plan as a plain reply or ask "should I proceed?" through prose or ask_user_question. If review rejects it, incorporate the feedback and present again. If the review channel is unavailable or aborted, stay in plan mode and ask the user to switch modes manually; do not proceed with implementation.

    - id: token-meter
      name: '@deepseek-ai/dsh-token-meter'

    - id: compaction-basic
      name: '@deepseek-ai/dsh-compaction-basic'

    # Human `/compact`: one useful reduction below the automatic threshold. Backend
    # independent, so it follows whichever compaction service this leaf mounts.
    - id: command-compact
      name: '@deepseek-ai/dsh-command-compact'

    - id: subagent
      name: '@toddzheng024/dscode-bundle/subagent-core'

    - id: subagent-spawn-in-process
      name: '@toddzheng024/dscode-bundle/subagent-spawn'
      config:
        providerName: spawn

    - id: subagent-fork-in-process
      name: '@toddzheng024/dscode-bundle/subagent-fork'
      config:
        providerName: fork

    # Continuable background children are selected per delegation tool. The
    # separately loaded follow-up tool registers the one global `send_message`.
    - id: tool-subagent-control
      name: '@deepseek-ai/dsh-tool-subagent-control'

    - id: tool-subagent-list-agents
      name: '@deepseek-ai/dsh-tool-subagent-control/list-agents'

    - id: tool-subagent
      name: '@deepseek-ai/dsh-tool-subagent'
      config:
        provider: spawn
        toolName: subagent
        backgroundMode: continuable

    # Fork omits model selection so provider/model stay equal to the parent and
    # the inherited history remains eligible for KV Cache reuse. This base row
    # stays one-shot; preset layers may select continuable mode without adding a
    # child-only system-prompt section or tool schema ahead of that history.
    # See .agents/notes/implemented/feature/2026-08-18-model-selected-subagent-routes.md
    # and .agents/notes/implemented/architecture/2026-08-10-fork-children-stay-one-shot.md.
    - id: tool-subagent-fork
      name: '@deepseek-ai/dsh-tool-subagent'
      config:
        provider: fork
        toolName: subagent_fork
        backgroundMode: one-shot

    - id: ptc-runtime
      name: '@deepseek-ai/dsh-ptc-runtime-node'

    - id: workflow-ptc
      name: '@deepseek-ai/dsh-workflow-ptc'
      config:
        provider: spawn

    - id: tool-workflow
      name: '@deepseek-ai/dsh-tool-workflow'

    - id: timeout-policy
      name: '@deepseek-ai/dsh-tool-call-timeout-policy'

    - id: spill-local
      name: '@deepseek-ai/dsh-spill-local'

    - id: spill-policy
      name: '@deepseek-ai/dsh-spill-policy'
      config:
        maxInlineTokens: 12500

    # Durability checkpoints before each model request and top-level dispatch.
    - id: session-checkpoint-policy
      name: '@deepseek-ai/dsh-session-checkpoint-policy'

    # Compacts oversized tool results before the broader conversation compactor
    # runs, preserving the model-visible result within the configured budget.
    - id: tool-result-pruner
      name: '@deepseek-ai/dsh-compaction-tool-result-pruner'
      config:
        thresholdChars: 8192
        headChars: 4096
        tailChars: 1024

    # When an image-capable route rejects a request as over its image budget,
    # replace the oldest images with placeholders on the surface and retry.
    - id: image-offload
      name: '@deepseek-ai/dsh-compaction-image-offload'

    - id: tool-todo
      name: '@deepseek-ai/dsh-tool-todo'
      config:
        allowParallelInProgress: true

    # Persisted same-session goals reach the model and the slash menu here; the
    # domain, driver, and `/goal` command are above.
    - id: tool-goal
      name: '@deepseek-ai/dsh-tool-goal'

    # Fresh-agent Ralph iteration over a build-time-fixed script. Off by
    # default: the tool description restricts `ralph` to runs the human
    # explicitly asked for, and completion is a worker self-report, not an
    # independent evaluation. An overlay row restores it for a base-backed
    # profile (`$DSH_HOME/cordis.patch.yml`, or a `--patch <file>`):
    #   - id: tool-ralph
    #     disabled: false
    - id: tool-ralph
      name: '@deepseek-ai/dsh-tool-ralph'
      disabled: true
      config:
        subagentProvider: spawn
        maxRounds: 64

    # Consecutive-repeat reminders on the tool chain.
    - id: repeat-tool-reminder
      name: '@deepseek-ai/dsh-repeat-tool-reminder'
      config:
        thresholds: [3, 5, 8]
        argumentsPreviewChars: 500

    # The shared base enables the stable model-facing web_search and web_fetch
    # tools. The Web app disables this host row and composes both tools per agent
    # preset; products with a stricter network policy override tool-web. DeepSeek
    # search resolves the same DEEPSEEK_API_KEY
    # credential the Models page manages for chat, at each search; its Messages
    # endpoint is configured independently from the model route, so it takes its own
    # base-URL override. Anonymous fetch accepts only public HTTP(S) destinations,
    # resolves and validates every destination, and pins every actual connection.
    # Search is a full auxiliary model request with server-side retrieval, so this
    # shipped DeepSeek route gets 60s while the provider-neutral tool default
    # remains 30s.
    - id: web
      name: '@deepseek-ai/dsh-web'
      config:
        searchProvider: deepseek-official
        fetchProvider: http

    - id: web-search-deepseek
      name: '@deepseek-ai/dsh-web-search-deepseek'
      config:
        apiKeyEnv: DEEPSEEK_API_KEY

    - id: web-fetch-http
      name: '@deepseek-ai/dsh-web-fetch-http'

    - id: tool-web
      name: '@deepseek-ai/dsh-tool-web'
      config:
        fetch: true
        searchTimeoutMs: 60000

    - id: mcp-resources
      name: '@deepseek-ai/dsh-mcp-resources'

    # ── rows every mode mounts, whose values each overlay may state ──────────────

    # The tool registry. Presentation mode is a deployment choice; omitting it here
    # keeps the schema default (native).
    - id: tools
      name: '@deepseek-ai/dsh-tools'

    # The deployment persona is a deployment choice; plan-mode and tool plugins own
    # their own prompt sections.
    - id: system-prompt
      name: '@deepseek-ai/dsh-system-prompt'
      config:
        personaPrefix: ''

    # Agents created at startup. The base stays empty; raw overlays may create
    # agents, while Web creates sessions on client request.
    - id: agent-loop
      name: '@deepseek-ai/dsh-agent-loop'
      config:
        agents: []

    # The sandboxed filesystem provider. `cwd` defaults to `process.cwd()`; an
    # overlay can pin another workspace.
    - id: fs-sandbox
      name: '@deepseek-ai/dsh-fs-sandbox'

    # The native DeepSeek adapter. No key or endpoint is inlined: both resolve per
    # request from the `llm-deepseek:` settings section over this entry, with the
    # key coming from the credential store below. Thinking defaults are a deployment
    # choice.
    - id: llm-deepseek
      name: '@deepseek-ai/dsh-llm-deepseek-api-key'

    - id: llm-deepseek-account
      name: '@toddzheng024/dscode-bundle/deepseek-account'

# One aggregate row initializes the macOS Service provider before publishing
# the model-facing Skill and Agent-scoped Tools.
- insert:
    - id: computer-use
      name: '@anionex/dsh-computer-use'
      config:
        observationTtlMs: 0
        interaction:
          focusPolicy: preserve
          keyboardPolicy: activate
          pointerInputPolicy: targeted
          cursorVisualization: visible
          cursorSpeedPxPerSecond: 1600
          cursorAccelerationPxPerSecondSquared: 6000
          cursorClickDelayMs: 90
          cursorAutoHideMs: 0

# The dsh-code bundle patch: an Ink client over the Harness host plane. Model-
# facing rows move behind per-session agent presets, while process registries,
# persistence, sandbox/approval, session query, permissions, goals, and
# subagent providers stay shared. The runner owns one persistent terminal and
# can create, resume, and switch between top-level Agent sessions.
# (DeepSeek blue, whale wordmark), answers approval asks with a y/n bar,
# dispatches slash commands through the shared registry, and folds submitted
# prompts back into the same durable session until the user quits.

# 0.1.5 split the deployment persona into a prefix and a suffix template
# around the first-party guidance sections; this terminal keeps its identity
# line as the prefix ({{variable}} interpolation stays strict upstream).
- id: system-prompt
  config:
    personaPrefix: >-
      You are a coding agent powered by the {{model}} model. Your working directory is {{cwd}}.

# The shared module-reload HMR row stays off; the launcher's watch-only
# fallback still keeps the user patch layers live until the app exits.
- id: hmr
  disabled: true

- id: tools
  config:
    mode: !!js process.env.DSH_TOOLS_MODE

# The base row keeps full-text search off entirely (openAt: never) so nothing
# imports node:sqlite at boot; the terminal replaces it with the bundle's
# skip-tolerant subclass below. An override row cannot retarget a row's
# MODULE (name is only honored on inserts), so the base row is disabled and
# an equivalent row mounts the subclass: the derived index opens lazily on
# the first search (no startup cost, no Node 22 experimental warning), and
# one unreadable source (a pre-release artifact the frozen codecs reject)
# is skipped with a warning instead of failing every cross-session search.
- id: session-query-sqlite
  disabled: true

# Agent-plane rows are mounted by the selected preset. Keep this list aligned
# with the upstream Web bundle so two sessions can use different compositions
# without leaking model-facing registrations through the host layer.
- id: tool-bash
  disabled: true
- id: tool-pwsh
  disabled: true
- id: tool-jobs
  disabled: true
- id: tool-fs
  disabled: true
- id: tool-fs-search
  disabled: true
# skill-filesystem stays ENABLED on the host: it only feeds the skill
# REGISTRY (local-root discovery), never the model-facing tool surface —
# tool-skill below stays disabled and presets mount it per session. The
# terminal offers skills in the slash menu before any session exists, and a
# bare launch has no preset layer yet, so the registry's global layer needs
# this provider; presets shadow it with the same discovery on their scope.
- id: skill-filesystem
  disabled: false
- id: tool-skill
  disabled: true
- id: command-goal
  disabled: true
- id: tool-goal
  disabled: true
- id: plan-mode
  disabled: true
- id: compaction-basic
  disabled: true
- id: command-compact
  disabled: true
- id: tool-result-pruner
  disabled: true
- id: tool-subagent-control
  disabled: true
- id: tool-subagent-list-agents
  disabled: true
- id: tool-subagent
  disabled: true
- id: tool-subagent-fork
  disabled: true
# The workflow engine is preset-owned: DSCODE's delegation group mounts it inside an
# entry-local `workflowEngine` realm, so the host row stays off. DSH 0.1.7 renamed this
# row from `workflow-worker-thread`, and a patch addresses rows by id — an id that no
# longer exists silently patches nothing, which is how the host engine came back.
- id: workflow-ptc
  disabled: true
- id: tool-workflow
  disabled: true
- id: tool-ralph
  disabled: true
- id: agent-instructions
  disabled: true
- id: tool-todo
  disabled: true
# tool-web keeps the 0.1.5-rc.1 base default (web_fetch enabled over the
# bundled web-fetch-http provider): the host row exposes web_fetch while the
# per-preset agent-plane rows keep their own fetch stance. The upstream base
# bundle dropped tool-str-replace-editor entirely in 0.1.5 (the minimal
# preset became a single-tool composition), so this patch no longer lists it.

- insert:
    # The account login's browser callback: `deepseekAccount` registers /oauth/callback on
    # `ctx.webServer` for the lifetime of one attempt, so the terminal needs an HTTP
    # transport of its own. Loopback only and an OS-assigned port. The native
    # session controller below also registers authenticated Connection routes;
    # no browser frontend is mounted.
    # `DSCODE_ACCOUNT_LOGIN=0` removes the listener, and `/account` then says why.
    - id: webserver
      name: '@deepseek-ai/dsh-host-webserver'
      disabled: !!js process.env.DSCODE_ACCOUNT_LOGIN === '0'
      config:
        host: 127.0.0.1
        port: 0

    # Cross-session @mentions: bounded read-only snapshots of other sessions
    # as sourced model context. Opt-in upstream; the TUI's completion menu
    # lists candidates and submission expands them through prepare().
    - id: session-reference
      name: '@deepseek-ai/dsh-session-reference'

    # Workspace @file mention discovery: a bounded per-agent fuzzy index over
    # the session cwd (directory listing, symlink guards, tool/result
    # invalidation). The TUI's @ completion consumes ctx.fileReferences
    # instead of running its own workspace scan.
    - id: file-reference-local
      name: '@deepseek-ai/dsh-file-reference-local'

    # Preset selection. DSH 0.1.7 split the old `agent-presets` service into this
    # registry plus one `@deepseek-ai/dsh-agent-preset` row per preset, and dropped
    # discovery from directories: the shipped rows live in the `dsh-web-app` bundle
    # this profile does not carry, so the DSCODE declaration in the profile patch is
    # the roster, and that patch also names it the deployment default.
    - id: agent-preset-registry
      name: '@deepseek-ai/dsh-agent-preset-registry'
      config:
        default: dscode

    # Cordis self-inspection (the shipped `cordis` agent preset's toolset):
    # the host runner publishes the `dynamicCordisRunner`/`cordisInspect`
    # services `tool-cordis` injects. Without this host row the preset mount
    # fails ("1 row(s) did not activate: tool-cordis"), because models write
    # composition through the agent plane but the runner is a host singleton.
    - id: cordis-host-runner
      name: '@deepseek-ai/dsh-cordis-host-runner'

    # Host-owned opt-in the preset delegation tools sample: standard/ptc's
    # tool-subagent rows set `modelSelectionSettings: true`, whose start
    # resolves this service and fails the whole preset mount when absent
    # ("failed to apply loader entry delegation (cordis:group)"). The upstream
    # web-app bundle carries this host row in 0.1.5-rc.1; dsh-base still does
    # not ship it.
    - id: subagent-model-selection-settings
      name: '@deepseek-ai/dsh-tool-subagent/model-selection-settings'

    # Interactive provider authorization. The base bundle supplies the
    # credential store; mounting the neutral authorization seam wakes the
    # login flows already registered by llm-pi-ai without coupling the TUI to
    # any provider's OAuth or device-code protocol.
    - id: authorization
      name: '@deepseek-ai/dsh-authorization'

    # The bundle's skip-tolerant session-query engine replacing the disabled
    # base row above: same SQLite FTS5 service, observation loop patched to
    # skip unreadable sources instead of failing every search.
    - id: session-query-skip
      name: '@toddzheng024/dscode-bundle/session-query'
      config:
        path: ':memory:'
        openAt: first-search

    # Model-facing session-log search/trace/read tools over the sessionQuery
    # service (read-only, workspace-scoped by exact cwd). A host-plane mount
    # is deployment-global: every preset session sees the five tools. Kept
    # ENABLED deliberately — read-only search leaks no capability — but note
    # it does reach minimal-preset sessions too. The host CLI does not bundle
    # this package, so it ships as a real dependency and resolves from the
    # profile's own node_modules.
    - id: tool-session-query
      name: '@deepseek-ai/dsh-tool-session-query'

    # DSH 0.2 resolves both live and persisted reminder targets through the
    # native session controller. Its host dependencies do not mount a browser
    # frontend; Connection also works without the optional login webserver.
    - id: workspace
      name: '@deepseek-ai/dsh-workspace'
    - id: connection
      name: '@deepseek-ai/dsh-client-connection'
    - id: file-upload
      name: '@deepseek-ai/dsh-client-file-upload'
    - id: session-controller
      name: '@deepseek-ai/dsh-api-session-controller'
      config:
        nativeOpen: false

    # Durable reminders: the schedule service arms Host timers and resumes
    # sessions for delivery. /schedule reads the active native catalog;
    # old schedule/change events are historical migration inputs. time-context
    # gives the model a clock reading so 'at' times are phrased against the
    # actual time; the 30s throttle bounds durable snapshot growth.
    - id: schedule
      name: '@deepseek-ai/dsh-schedule'

    - id: time-context
      name: '@deepseek-ai/dsh-time-context'
      config:
        refreshIntervalMs: 30000

    # Persistent PTY plumbing: the owner-scoped registry and the one backend
    # package in both dialects (pwsh is the Windows/ConPTY path, bash covers
    # POSIX) mount as host SERVICES — no model-facing surface, so they break
    # no preset boundary. The six terminal_* TOOLS ship DISABLED like LSP:
    # enabling them at the host plane would hand every preset (including the
    # shell-restricted minimal one) raw shell capability, the exact leak the
    # disables above exist to prevent. Flip tool-terminal to disabled: false
    # in the PROFILE layer to opt the deployment into PTY tools — but install
    # @deepseek-ai/dsh-tool-terminal into the profile first (the host CLI does
    # not bundle it; an enabled row over a missing package fails the boot):
    #   dsh plugin --profile cli add @deepseek-ai/dsh-tool-terminal
    - id: pty
      name: '@deepseek-ai/dsh-terminal'

    - id: terminal-pwsh
      name: '@deepseek-ai/dsh-terminal-bash'
      disabled: !!js process.platform !== 'win32'
      config:
        shellDialect: pwsh

    - id: terminal-bash
      name: '@deepseek-ai/dsh-terminal-bash'
      disabled: !!js process.platform === 'win32'

    - id: tool-terminal
      name: '@deepseek-ai/dsh-tool-terminal'
      disabled: true

    # LSP navigation ships DISABLED: lsp-stdio resolves every server command
    # at mount and a missing binary would fail the whole composition boot.
    # Enable in the PROFILE layer with real servers, e.g.:
    #   lsp / lsp-stdio / tool-lsp rows with disabled: false and
    #   lsp-stdio config.servers mapping extensions to server commands.
    # The three packages are also not bundled by the host CLI: install them
    # into the profile first or the enabled rows fail the boot.
    - id: lsp
      name: '@deepseek-ai/dsh-lsp'
      disabled: true

    - id: lsp-stdio
      name: '@deepseek-ai/dsh-lsp-stdio'
      disabled: true

    - id: tool-lsp
      name: '@deepseek-ai/dsh-tool-lsp'
      disabled: true

    # MCP servers (dsh-mcp-client) and hooks bridges (dsh-hooks-claude-code /
    # -codex) take per-instance config (server transports, hooks.json paths),
    # so they mount as rows in the USER profile layer, not here; the host CLI
    # bundles these peers, so those rows resolve. README documents the row
    # shapes, and rows over packages the host does not bundle need the package
    # added to the profile first.

    - id: tui-startup
      name: '@toddzheng024/dscode-bundle/startup'

    # Reads its startup through lazy config, which waits for the tuiStartup
    # provider the row above publishes from the parsed command line.
    - id: tui-runner
      name: '@toddzheng024/dscode-bundle/tui'
      inject: [tuiStartup]
      config:
        startup: !!js ctx.tuiStartup.startup

# Host/profile overlay. The DSCODE Agent Preset declaration at the end of the
# profile patch supplies coding, skills, planning, compaction and native
# subagents in their correct scopes, and names itself the registry default.

- id: sandbox-policy
  config:
    mode: workspace-write

- id: approval
  config:
    policy: ask

# OpenRouter is DSCODE's own adapter (plugins/openrouter); the pi-ai route that
# served it before stays unmounted so the two never claim the same route.
- id: llm-pi-ai
  disabled: true

# Web search follows the session's route: OpenRouter's web plugin for an
# OpenRouter session, DeepSeek's native search for a DeepSeek one. A patch
# replaces the row's whole config, so fetch keeps its provider here.
- id: web
  config:
    searchProvider: dscode-web
    fetchProvider: http

# A reasoning model spends tokens before its title; 64 left most titles empty.
# DeepSeek's route disables thinking for titles, so its usage stays small.
- id: session-title-llm
  config:
    targetWords: 5
    targetCjkCharacters: 10
    maxInputBytes: 4096
    maxOutputTokens: 1024
    timeoutMs: 60000

# Chrome MCP belongs to the DSCODE agent preset. A fresh, prompt-free TUI
# launch can render before composing an agent or connecting the browser server.

# DSH 0.1.7 reserved the name `auto` for its own Auto integration (full access with
# approval off), so DSCODE's reviewed preset — workspace writes with every eligible
# approval request reviewed by a model, human fallback intact — is named `auto-review`.
- id: permission
  config:
    defaultPreset: auto-review
    presets:
      auto-review:
        sandbox: workspace-write
        approval: ask
        name: Auto review
        description: Workspace writes; automatic review of eligible approval requests, with human fallback.
      ask:
        sandbox: workspace-write
        approval: ask
        name: Ask me
      workspace-write:
        sandbox: workspace-write
        approval: ask
      read-only:
        sandbox: read-only
        approval: ask
      danger-full-access:
        sandbox: danger-full-access
        approval: never


- id: credentials
  disabled: true
- id: computer-use
  disabled: true
- insert:
    - id: dscode-credentials
      name: "@toddzheng024/dscode-bundle/credentials"
    - id: dscode-openrouter
      name: "@toddzheng024/dscode-bundle/openrouter"
    - id: dscode-grok
      name: "@toddzheng024/dscode-bundle/grok"
    - id: dscode-opencode-go
      name: "@toddzheng024/dscode-bundle/opencode-go"
    - id: dscode-custom
      name: "@toddzheng024/dscode-bundle/custom"
    - id: dscode-jev
      name: "@toddzheng024/dscode-bundle/jev"
    - id: dscode-auto-review
      name: "@toddzheng024/dscode-bundle/auto-review"
      config:
        timeoutMs: 30000
        maxOutputTokens: 4096
        maxReviewsPerTurn: 20
    - id: dscode-session-metrics
      name: "@toddzheng024/dscode-bundle/session-metrics"
    - id: dscode-session-cards
      name: "@toddzheng024/dscode-bundle/session-cards"
    - id: dscode-session-bridge
      name: "@toddzheng024/dscode-bundle/session-bridge"
    - id: dscode-memory
      name: "@toddzheng024/dscode-bundle/memory"
    - id: dscode-time-marks
      name: "@toddzheng024/dscode-bundle/time-marks"
    - id: dscode-tui-tools
      name: "@toddzheng024/dscode-bundle/tui-tools"
    - id: dscode-email-tools
      name: "@toddzheng024/dscode-bundle/email-tools"
    - id: dscode-triggers
      name: "@toddzheng024/dscode-bundle/triggers"
    - id: dscode-computer-use
      name: "@toddzheng024/dscode-bundle/computer-use"
      config:
        observationTtlMs: 30000
        allowAllApps: false
        interaction:
          focusPolicy: preserve
          keyboardPolicy: activate
          pointerInputPolicy: targeted
          cursorVisualization: visible
    - id: dscode-account
      name: "@toddzheng024/dscode-bundle/account"
    - id: dscode-browser
      name: "@toddzheng024/dscode-bundle/browser"
    - id: dscode-hooks
      name: "@deepseek-ai/dsh-hooks-codex"
      inject:
        - dscodePaths
      config:
        configPath: !!js ctx.dscodePaths.hooks
        defaultTimeoutMs: 10000
        stderrSummaryMaxChars: 500
- id: agent-preset-registry
  config:
    default: dscode

# The DSCODE preset: one `@deepseek-ai/dsh-agent-preset` declaration carrying the
# agent-plane composition of `presets/dscode/agent.cordis.yml`.
- insert:
    - id: preset-dscode
      name: '@deepseek-ai/dsh-agent-preset'
      config:
        id: dscode
        name: "DSCODE"
        description: "持久 Shell 编码环境，保留 Skills、压缩、目标、子代理与工作流。"
        order: 0
        plugins:
          # The `dscode` agent preset: the full coding agent, mounted once per process.
          #
          # This file is an AGENT-PLANE composition. The roster mounts it ONCE under a
          # standing scope; every session naming it joins by scope parentage, so the
          # tools and prompt sections registered here cover each joined agent while a
          # session's own state stays keyed per Session/Agent inside the plugins. The
          # host composition (`base.cordis.yml` + `web.cordis.yml`) keeps everything a
          # preset must not own: the registries themselves, the sandbox and approval
          # stack, persistence, and the model route.
          #
          # A service row here MUST sit inside a group carrying an `isolate` realm.
          # Without one it publishes into the root realm, where it is process-global —
          # another preset publishing the same name collides, and a host reader would
          # resolve one preset's instance for every session; the preset registry rejects
          # that at mount. `true` means an entry-local realm: this standing mount's own
          # private instance, apart from every other preset's. (A shared label does NOT
          # pool instances — `provide()` throws on the second registration under the
          # same realm symbol; labels join REALMS, and are not what this file needs.)

          # ── identity ────────────────────────────────────────────────────────────────

          # The preset's own persona, shadowing the deployment default for this agent.
          # `{{model}}` and `{{cwd}}` resolve from the agent's own route and workspace.
          - id: persona
            name: '@deepseek-ai/dsh-persona'
            config:
              suffix: Your working directory is {{cwd}}.
              prefix: >-
                You are a coding agent powered by the {{model}} model, working through a persistent shell.
                Reply in the language the user writes in.
                Keep the user informed during tool-driven work with ordinary assistant text, visible even when verbose mode is off. Reasoning blocks and tool descriptions do not count as progress updates.
                Before the first tool call, briefly state what you will check or change; for a simple answer without tools, answer directly.
                During sustained work, send an update when you have something to report: a significant finding, a blocker, a change of direction, or the result of a long blocking call once control returns. Do not announce routine reads, do not claim to speak while a tool is blocking, and never pad: an update says what changed and what the next step resolves, in one or two sentences, using observable facts and decisions rather than private reasoning, raw tool payloads or a narration of every command.
                Continue working after each update without asking permission for already-authorized steps. Progress text is not the final answer; finish with a self-contained result and any remaining gaps.
                Before changing code, read the relevant code and any project instructions; reuse existing functions and patterns instead of adding new machinery.
                Make routine judgment calls yourself and ask only when different answers would lead to materially different work.
                Deliver the whole requested scope; if part of it is blocked, finish the rest and say what was left out and why.
                Verify changes by running the relevant checks, and report outcomes faithfully: say when a check fails, when a step was skipped, and when something could not be verified.
                Before editing, identify the requested scope and observable acceptance checks. Keep them stable unless the user changes the task or evidence shows a necessary dependency.
                Once the requested behavior and required checks pass, move to delivery. Do not turn a finished task into optional optimization, refactoring or speculative hardening.
                Treat review findings as claims to verify against the actual code and requirements, not automatic instructions. Fix confirmed defects affecting this task; report unrelated opportunities separately.
                After a fix, rerun affected checks. Repeat broader checks only when changed behavior or a failure invalidates the earlier result; do not rerun passing suites just to feel more certain.
                If a check suddenly becomes much slower, inspect the changed workload and the existing output before rerunning it. Keep test fixtures small and independent of production-sized limits.
                Respect the automatic review budget. Reaching it is not proof of correctness: finish necessary fixes and focused checks, report unresolved issues honestly, and continue already-authorized delivery steps when their requirements are met.
                Keep the final reply concise, lead with the outcome, and never claim work you did not do.

          - id: agent-instructions
            name: '@deepseek-ai/dsh-agent-instructions'
            config:
              # The launcher folds AGENTS.md/CLAUDE.md from directories above the project
              # root, up to home, in front of the user-global file; without those files it
              # points at $DSH_HOME, exactly as before.
              dshHome: !!js 'process.env.DSCODE_INSTRUCTION_HOME'
              maxBytes: 65536

          - id: persistent-shell
            name: cordis:group
            group: true
            isolate:
              terminals: true
            config:
              - id: pty
                name: '@deepseek-ai/dsh-terminal'

              - id: terminal-bash
                name: '@toddzheng024/dscode-bundle/terminal'
                disabled: !!js process.platform === 'win32'
                config:
                  timeoutMs: 300000

              - id: persistent-bash
                name: '@toddzheng024/dscode-bundle/persistent'
                disabled: !!js process.platform === 'win32'
                config:
                  timeoutMs: 300000
                  description: |-
                    Run commands in a bash shell
                    * When invoking this tool, the contents of the "command" parameter does NOT need to be XML-escaped.
                    * Network access depends on the task environment. Prefer configured mirrors/proxies when they are available.
                    * State is persistent across command calls and discussions with the user.
                    * To inspect a particular line range of a file, e.g. lines 10-25, try 'sed -n 10,25p /path/to/the/file'.
                    * Please avoid commands that may produce a very large amount of output.
                    * Please run long lived commands in the background, e.g. 'sleep 10 &' or start a server in the background.

              - id: terminal-pwsh
                name: '@toddzheng024/dscode-bundle/terminal'
                disabled: !!js process.platform !== 'win32'
                config:
                  shellDialect: pwsh
                  timeoutMs: 300000

              - id: persistent-pwsh
                name: '@deepseek-ai/dsh-tool-pwsh-persistent'
                disabled: !!js process.platform !== 'win32'
                config:
                  timeoutMs: 300000
                  description: |-
                    Run commands in a PowerShell shell
                    * When invoking this tool, the contents of the "command" parameter does NOT need to be XML-escaped.
                    * You don't have access to the internet via this tool.
                    * State is persistent across command calls and discussions with the user.
                    * Use native Windows paths (C:\...) and $env:NAME variables; this is PowerShell, not bash.
                    * Please avoid commands that may produce a very large amount of output.
                    * Please run long lived commands in the background, e.g. 'Start-Job' or start a server with Start-Process.

              - id: dscode-policy
                name: '@toddzheng024/dscode-bundle/policy'

          # A fresh shell for reviewed escalation. It does not inherit PTY state.
          - id: shell-retry
            name: '@toddzheng024/dscode-bundle/bash'
            config:
              toolName: shell_retry


          # ── background jobs ────────────────────────────────────────────────────────

          # Only the model-facing controls. The task REGISTRY stays on the host plane:
          # its producers sit outside any realm this file could put it in — `tool-bash`
          # above resolves it with `ctx.get`, and an entry-local realm here is invisible
          # to every sibling row, so `run_in_background` would answer "background jobs
          # unavailable" while these controls sat in the catalog. The registry is keyed by
          # owning agent anyway, so one host instance serves every session. What a preset
          # chooses is whether its agent can collect and stop background work at all.
          - id: tool-jobs
            name: '@deepseek-ai/dsh-tool-jobs'

          # ── skills ──────────────────────────────────────────────────────────────────

          # The skill REGISTRY lives in the host composition and is layered per scope:
          # these rows register into THIS preset's layer of it, so they need no realm.
          # `skill-filesystem` contributes local-root discovery for agents on this preset, and
          # `tool-skill` gives them the catalog and loader; the merged catalog also
          # carries whatever the deployment registered globally (repository plugins).
          - id: skill-filesystem
            name: '@deepseek-ai/dsh-skill-filesystem'
            config:
              # Ancestor skill discovery is on by default: the skill roots of directories
              # between the working directory and home register at rank 300, nearest first,
              # so headers enter the catalog and bodies stay lazy. =0 turns it off.
              customSkillDirs: !!js 'JSON.parse(process.env.DSCODE_SKILL_ANCESTOR_DIRS ?? "[]")'

          - id: tool-skill
            name: '@deepseek-ai/dsh-tool-skill'

          # ── goals ───────────────────────────────────────────────────────────────────

          # The goal service and session driver stay on the host plane, where the Gateway
          # can resolve them. The human command and model-facing tool register into this
          # preset's scoped layers.
          - id: command-goal
            name: '@toddzheng024/dscode-bundle/command-goal'

          - id: tool-goal
            name: '@deepseek-ai/dsh-tool-goal'

          # ── plan mode ───────────────────────────────────────────────────────────────

          # Plan state is per-agent by nature, so an entry-local realm is not a
          # workaround here — it is the correct lifetime.
          - id: planning
            name: cordis:group
            group: true
            isolate:
              planMode: true
            config:
              - id: plan-mode
                name: '@deepseek-ai/dsh-plan-mode'
                config:
                  section: |
                        You are in plan mode. Stay in plan mode until exit_plan_mode succeeds or the user switches the session mode. Imperative language to implement changes means plan the implementation, not execute it. A user's conversational agreement — including an answer confirming something you asked — approves nothing and does not end plan mode; fold the confirmed decision into the plan and submit it through exit_plan_mode.

                        Explore first. Use non-mutating reads, searches, static analysis, and checks to ground the plan in the actual repository. Do not edit or write files, change configuration, run formatters or code generation that rewrites tracked files, commit, or otherwise carry out the plan. Prefer existing functions and patterns over new machinery.

                        The tool catalog stays the same across modes for request-cache stability. These plan-mode rules override any later tool description or guidance that suggests using mutation tools; those tools remain listed to keep the tool catalog unchanged. Do not use todo_write to track this planning phase: it tracks implementation after an approved plan, while the plan itself belongs in exit_plan_mode.

                        Resolve discoverable facts by inspection. Use ask_user_question only for user-owned choices or material ambiguity that inspection cannot answer. Do not ask the user where code lives or how current behavior works when you can find out.

                        Make the plan decision-complete: state the goal and success criteria; group implementation changes by subsystem; identify public API, schema, and data-flow changes; cover edge cases, failure modes, tests, acceptance criteria, and explicit assumptions. Keep it concise enough to review but detailed enough that another engineer can implement it without making design decisions.

                        When ready, call exit_plan_mode with the complete plan markdown, starting with a # title. Make exit_plan_mode the only and final tool call in that assistant response: it presents the plan for approval, and implementation begins only in a later step after approval. Do not paste the final plan as a plain reply or ask "should I proceed?" through prose or ask_user_question. If review rejects it, incorporate the feedback and present again. If the review channel is unavailable or aborted, stay in plan mode and ask the user to switch modes manually; do not proceed with implementation.

          # ── compaction ──────────────────────────────────────────────────────────────

          # `compaction-basic` reads `toolResultPrune` through `ctx.get`, so the pruner must
          # share this realm rather than sit outside it.
          #
          # `tokenMeter` is deliberately NOT in this realm: the meter stays on the HOST
          # plane, and the rows here resolve that one instance. It takes no configuration,
          # keys every fold by Session, and owns the context-meter projection units the
          # browser reads for every session — behind a realm those units would come and go
          # with whichever presets happen to be mounted. What a preset chooses is whether
          # its agent compacts at all, which is `compaction-basic` below.
          - id: compaction
            name: cordis:group
            group: true
            isolate:
              compaction: true
              toolResultPruner: true
            config:
              - id: compaction-basic
                name: '@toddzheng024/dscode-bundle/compaction'

              - id: command-compact
                name: '@deepseek-ai/dsh-command-compact'

              - id: tool-result-pruner
                name: '@deepseek-ai/dsh-compaction-tool-result-pruner'
                config:
                  thresholdChars: 8192
                  headChars: 4096
                  tailChars: 1024

          # ── delegation and workflows ────────────────────────────────────────────────

          # The `subagents` registry and its spawn/fork backends live in the HOST
          # composition: the registry is a process singleton whose cross-session queries
          # the api-proxy serves to the browser, and a provider name may only be
          # registered once. This preset contributes the delegation TOOLS, which resolve
          # that host registry.
          #
          # `workflows` is different — nothing outside an agent reads it — so every row
          # that reaches it shares one entry-local realm here, and a consumer left
          # outside would resolve a host registry this preset does not populate.
          - id: delegation
            name: cordis:group
            group: true
            isolate:
              workflowEngine: true
            config:
              - id: tool-subagent-control
                name: '@toddzheng024/dscode-bundle/control'

              - id: tool-subagent-list-agents
                name: '@deepseek-ai/dsh-tool-subagent-control/list-agents'

              - id: tool-subagent
                name: '@toddzheng024/dscode-bundle/subagent'
                config:
                  provider: spawn
                  toolName: subagent
                  modelSelectionSettings: true
                  backgroundMode: continuable
                  maxDepth: 1

              # Fork omits model selection so provider/model stay equal to the parent and
              # the inherited history remains eligible for KV Cache reuse. DSCODE exposes
              # reasoning_effort independently; changing effort does not select a new route.
              # This preset
              # keeps fork continuable; parent and child inherit the same messaging tool,
              # while the parent id and return guidance follow the inherited history.
              - id: tool-subagent-fork
                name: '@toddzheng024/dscode-bundle/subagent'
                config:
                  provider: fork
                  toolName: subagent_fork
                  backgroundMode: continuable
                  maxDepth: 1

              # Production dsh does not install these optional providers. Install the
              # matching Bundle in this Profile and restart the Host, then copy this
              # preset and remove `disabled` from the matching tool row. Host availability
              # alone grants no tool.
              - id: tool-subagent-codex
                name: '@toddzheng024/dscode-bundle/subagent'
                disabled: true
                config:
                  provider: codex
                  toolName: subagent_codex
                  backgroundMode: one-shot
                  maxDepth: provider-managed

              - id: tool-subagent-claude-code
                name: '@toddzheng024/dscode-bundle/subagent'
                disabled: true
                config:
                  provider: claude-code
                  toolName: subagent_claude_code
                  backgroundMode: one-shot
                  maxDepth: provider-managed

              - id: workflow-ptc
                name: '@deepseek-ai/dsh-workflow-ptc'
                config:
                  provider: spawn

              - id: tool-workflow
                name: '@deepseek-ai/dsh-tool-workflow'
                disabled: true

              - id: tool-ralph
                name: '@deepseek-ai/dsh-tool-ralph'
                disabled: true
                config:
                  subagentProvider: spawn
                  maxRounds: 64

          # ── remaining model-facing rows ─────────────────────────────────────────────

          - id: tool-ask-user
            name: '@deepseek-ai/dsh-tool-ask-user'

          - id: tool-todo
            name: '@deepseek-ai/dsh-tool-todo'
            config:
              allowParallelInProgress: true

          # The `web` service and its search provider stay in the host composition; only
          # the model-facing tool is per-session.
          - id: tool-web
            name: '@deepseek-ai/dsh-tool-web'
            config:
              fetch: true
              searchTimeoutMs: 60000

          - id: code-review
            name: '@toddzheng024/dscode-bundle/code-review'

          - id: present
            name: '@deepseek-ai/dsh-tool-present'

- id: llm-deepseek
  disabled: true
- insert:
    - id: dscode-deepseek
      name: '@toddzheng024/dscode-bundle/deepseek'
    - id: dscode-bootstrap
      name: '@toddzheng024/dscode-bundle/bootstrap'
