dsh-advisor
其他 活跃维护

dsh-advisor

NexusAgentX/dsh-advisor

轻量级会话审查插件包,移植自rpiv顾问子系统,提供零参数按需顾问功能,可将完整开发会话自动转发给独立配置的审查模型,无需手动调整参数即可快速获取审查建议。

0
Stars 标星
0
Forks 分支
0
Watchers 关注
0
Open Issues
TypeScript
主要语言
MIT
开源协议
936 KB
仓库大小
29 天前
最后推送
一键安装扩展 / 插件指令
dsh plugin --profile web add github:NexusAgentX/dsh-advisor
git clone https://github.com/NexusAgentX/dsh-advisor.git
git clone git@github.com:NexusAgentX/dsh-advisor.git
README.md main

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
Key Type / default Meaning
enabled bool, false Master switch.
provider string, optional Provider route. Required (non-empty) when enabled: true.
model string, optional Model id. Required (non-empty) when enabled: true.
reasoningEffort string, "" "" = auto (high when the advisor model supports it); or minimal / low / medium / high / xhigh / max / off. Unsupported values are omitted.
systemPrompt string, "" Overrides the built-in original rpiv advisor prompt. "" = built-in.
guidance object, optional Executor-facing prompt override: promptSnippet and/or promptGuidelines; only non-empty values are used, otherwise rpiv defaults apply.
disabledForModels array, [] Executor blocklist. Entries are "provider/model" or { model: "provider/model", minEffort?: "minimal|low|medium|high|xhigh|max" }. A blocked executor never sees the advisor tool. minEffort ranks graded levels only — an executor at off, or with an unset/unknown effort, never triggers a threshold (rpiv fail-soft contract).

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

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

License

MIT