Back to home@NexusAgentX

dsh-advisor

dsh plugin bundle porting the rpiv advisor subsystem: an on-demand zero-parameter advisor() tool that forwards the full session to a separately-configured reviewer model.

Stars
0
Language
TypeScript
Created
Aug 23, 2026
Updated
Aug 23, 2026
GitHub repo

Introduction

dsh-advisor

English | 中文

license node dsh

A standalone dsh plugin bundle porting the rpiv-advisor mechanism: a zero-parameter advisor() tool registered per agent scope. When the primary model needs stronger judgment it calls advisor() on demand; the plugin forwards the full derived session history plus the executor tool inventory to a separately-configured reviewer model using the original rpiv system prompt, and the free-text plan / correction / stop signal comes back as the tool result in the same turn.

Install with a single command:

dsh plugin --profile web add dsh-advisor   # <name> = your profile name

On demand, never automatic. There is no per-turn observer, no injected [advisor:*] message, and no severity-routing runtime. The primary model keeps control: it calls advisor() when it decides a stronger reviewer would help, and it consumes the result before continuing.

Install

One-line registry install

dsh plugin --profile web add dsh-advisor   # <name> = your profile name

A registry install fetches the published tarball, which ships the built artifacts (lib/ + cordis.patch.yml), so no prepare build or build permission is needed. Runtime dependencies (@deepseek-ai/cordis, @deepseek-ai/schemastery, and the @deepseek-ai/dsh-* peers) are declared as peerDependencies and resolve through the dsh installation's flat profile module fallback — no extra install step. Pin an exact version (dsh-advisor@0.1.3) for reproducible installs.

Local directory install (recommended for development / verification)

pnpm install                    # build the bundle (the prepare self-build)
dsh plugin --profile web add .  # <name> = your profile name

Verify

dsh --profile web --dump-config   # shows a "# == dsh-advisor" layer with the advisor row
dsh --profile web

Tarball install and uninstall are covered in docs/install.md.

Config

Advisor card on the dsh web Settings (插件配置) page

The advisor is off by default. When enabled, provider and model are mandatory: enabled: true without both is a hard gate — the advisor tool is not installed for any agent and reports a disabled-with-reason status. Unknown config keys are rejected.

Configuration composes across three surfaces (later layers override earlier ones; every surface uses the same key set):

  1. Plugin-row config$DSH_HOME/profiles/web/cordis.patch.yml (below). This is the composition base.
  2. dsh web Settings page — the "插件配置" (Plugin Configuration) page — the Advisor card (id advisor, rendered after the upstream bash / agent-loop / web-search cards) with the enabled toggle, provider / model selects restricted to system-configured providers and their models, a reasoning-effort select driven by the selected model's catalog metadata, and the system-prompt override. Saving writes into the advisor settings namespace and overrides the plugin-row config without editing it. Saving applies immediately — no restart (the runtime reads the composed value live; existing sessions are reconciled). Requires a current dsh web build whose shell declares the settings.plugin.item card slot and loads packages that declare dsh.client. The card reads and writes the namespace through the official GatewayService RPC channel (/api/advisor/get + /api/advisor/set, claimed by the host's typertGateway — the same mechanism the dsh goals service uses), which is not gated by the settings exposure allowlist: the in-process write (ctx.settings.update) carries no exposed-namespace check. No host patching is applied or required.
  3. /advisor command — per-session and ephemeral: it flips a session override, never the persisted config (see Usage).

Both persisted surfaces share the same hard gate: enabled: true with empty provider/model never starts a model call (disabled-with-reason). The Settings page additionally blocks saving while enabled with a required field empty; the host-side gate stays the final line of defense on every path. guidance and disabledForModels are full config keys and ride every configuration surface; the web card currently preserves them while editing the card-exposed fields.

Plugin-row config:

# profiles/web/cordis.patch.yml — the profile's user patch layer
- id: advisor
  config:
    enabled: true               # master switch (default false)
    provider: deepseek-official # REQUIRED when enabled
    model: deepseek-v4-flash    # REQUIRED when enabled
    reasoningEffort: high       # optional; "" = auto (high when supported)
    systemPrompt: ""            # optional; "" = original rpiv advisor prompt
    guidance:                   # optional executor prompt override
      promptSnippet: "Call advisor before substantive work."
      promptGuidelines: ["Call advisor again before declaring done."]
    disabledForModels: []       # optional executor blocklist; [] = none
KeyType / defaultMeaning
enabledbool, falseMaster switch.
providerstring, optionalProvider route. Required (non-empty) when enabled: true.
modelstring, optionalModel id. Required (non-empty) when enabled: true.
reasoningEffortstring, """" = auto (high when the advisor model supports it); or minimal / low / medium / high / xhigh / max / off. Unsupported values are omitted.
systemPromptstring, ""Overrides the built-in original rpiv advisor prompt. "" = built-in.
guidanceobject, optionalExecutor-facing prompt override: promptSnippet and/or promptGuidelines; only non-empty values are used, otherwise rpiv defaults apply.
disabledForModelsarray, []Executor blocklist. Entries are "provider/model" or `{ model: "provider/model", minEffort?: "minimal

The old automatic-reviewer keys immuneTurns and maxDeltaMessages are accepted for profile-upgrade compatibility but are ignored: the new mechanism has no cooldown or transcript-delta window.

Usage

Once installed and enabled, every eligible agent scope gets the advisor tool plus the rpiv prompt guidance. Control it per session with the /advisor command (available when a command registry is composed):

/advisor            toggle the advisor tool for this session
/advisor on         enable the advisor tool for this session
/advisor off        disable the advisor tool for this session
/advisor status     show model, effort, tool visibility, and gate/blocklist reasons

/advisor on|off|toggle are session-scoped and ephemeral: they flip a per-session override, never the persisted config. Enabling a session whose config lacks provider/model installs no tool — /advisor status (and the /advisor on reply) shows the gate reason. A session whose executor model is listed in disabledForModels behaves the same way.

When the primary model decides it needs the reviewer, it calls:

advisor()

The result is the advisor's free-text plan, correction, or stop signal as a normal tool result. The primary model stays in its current turn, reads the guidance, and continues — per the rpiv guidance, it surfaces the key advice in its next visible reply. The advisor model is never given tools and never writes into the session transcript directly.

How it works

The plugin keeps a live resolved config bridge and wires each agent at the agent scope (agent.ctx):

  1. On agent/created, if the hard gate passes, the session override is on, and the executor model is not in disabledForModels, the plugin registers the zero-parameter advisor tool plus a tool:advisor system-prompt section (promptSnippet + promptGuidelines, defaulting to the rpiv text) into that agent. Off or blocked scopes get no tool and no prompt text.
  2. When advisor() executes, the plugin builds the request as tool inventory first, then the session's full derived history (session.deriveMessages()), stripping the in-flight advisor() call from the tail and guaranteeing a user-role tail.
  3. The side call uses ctx.llm.stream with the separately configured provider/model, the original rpiv advisor system prompt (or the configured override), no tools, and the capability-gated reasoning effort ("" auto → high when declared by the model).
  4. Collected text becomes the tool result. Expected failures — no session, session off, hard-gate disabled, blocklisted, aborted call, model error, empty response (retried once) — all return explanatory text instead of throwing, so the primary model can always react in the current turn.
  5. Settings changes reconcile every live agent (install/uninstall the scoped tool as needed); guidance text reads live config through its prompt-section provider. /advisor only changes the per-session override.

Limitations & roadmap

  • No Pi TUI model picker — dsh command handlers return text only, so model/effort selection lives in the Settings card and plugin config.
  • No advisor tools — the reviewer is an independent model call only; it cannot verify claims itself (rpiv parity behavior).
  • No in-session advisor panel — the Advisor card on the "插件配置" settings page is a config surface, not a session view.
  • No transcript persistence or cost stats — no resumable advisor history or cost observability.
  • No secret obfuscation — secrets present in the transcript can reach the advisor model; configure a trusted reviewer model.
  • No quarantine of unsafe advisor output — the original prompt asks for directive guidance only; the primary model's own rpiv guidelines tell it to treat advice as advice, but text is returned as tool output.
  • Full history is sent on every callderiveMessages() is the complete current surface; the original mechanism intentionally has no bounded delta window.

Development

The bundle builds itself on install: package.json declares "prepare": "pnpm build", so any clone is immediately buildable. Private @deepseek-ai/* runtime packages are peerDependencies only and resolve from the npm registry at dev time (autoInstallPeers: true in pnpm-workspace.yaml plus the user-level registry auth); no local dsh source tree or link farm is required.

pnpm install              # registry deps + prepare self-build
pnpm test                 # vitest (unit + client + gateway/settings suites)
pnpm typecheck            # tsc --noEmit (node) + tsc -p tsconfig.client.json --noEmit + tsc -p tsconfig.spec.json --noEmit
pnpm build                # tsc -p tsconfig.build.json emit to lib/ + node scripts/build-client.mjs (client bundle)
pnpm pack                 # build + produce dsh-advisor-0.1.3.tgz

prepack runs pnpm build; prepare is build-only, so pnpm pack builds twice (once per lifecycle) — the accepted tradeoff that keeps git-install builds working. pnpm build clears lib/ first (scripts/clean-lib.mjs) so deleted modules never linger in the tarball. There is no postinstall step: already-built tarball installs skip the build entirely.

The test suite covers the rpiv-port config/gate/policy, context massaging, inventory cache, the side-call execute contract, per-agent registration, the /advisor command, settings bridge + gateway, and the web card store/component bundle contract.

Documentation

DocContent
docs/install.mdfull install guide: git / tarball / local-directory install, web Settings exposure, uninstall, --dump-config verification
docs/configuration.mdconfig fields, hard gate, agent-scoped wiring, side-call behavior, web card behavior
docs/consumer-api.mdpackage exports, gateway service, client entry, /advisor command
docs/verification.mdtest matrix, typecheck/build expectations, real-environment verification

License

MIT