dsh-advisor 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.i18n.yaml CHANGED
@@ -3,5 +3,5 @@
3
3
  # editing either side, bring the other along and re-record with:
4
4
  # git hash-object README.md
5
5
  # git hash-object README.zh.md
6
- README.md: ef98d163d84f2db4ee6a5345d467eee27644ff3b
7
- README.zh.md: 228f1d220635cbf7aba0ef72dc32e293a6635eaa
6
+ README.md: 5caf5c759a30682228bc562d914d801b64f94f08
7
+ README.zh.md: 7913542a4f734da470b0f334a8a2870c9a2c06a3
package/README.md CHANGED
@@ -4,7 +4,8 @@
4
4
 
5
5
  [![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
6
6
  ![node](https://img.shields.io/badge/node-%5E22.19%20%7C%7C%20%3E%3D24-339933.svg)
7
- ![dsh](https://img.shields.io/badge/dsh-DeepSeek%20Harness%20compatible-4B32C3.svg)
7
+ ![dsh](https://img.shields.io/badge/dsh-0.1.0--rc.8-4B32C3.svg)
8
+ ![dsh tui](https://img.shields.io/badge/dsh%20tui-compatible-4B32C3.svg)
8
9
  [![dshfind](https://dshfind.com/api/badge/omdsh-dev/dsh-advisor)](https://dshfind.com/plugins/omdsh-dev/dsh-advisor?ref=badge)
9
10
 
10
11
  A standalone dsh (DeepSeek Harness) plugin bundle porting the omp "advisor" subsystem: a per-session independent reviewer model that observes the primary transcript, reviews each stepped turn with an explicitly configured model (provider + model are required), and injects severity-ranked advice (nit / concern / blocker) back into the session — without polluting or recursively reviewing itself.
@@ -43,7 +44,7 @@ The advisor is off by default. When enabled, `provider` and `model` are **mandat
43
44
  The same keys compose across **three surfaces** (later layers override earlier ones; every surface shares the same key set and the same hard gate, with the host-side gate as the final line of defense on every path):
44
45
 
45
46
  1. **Plugin-row config** — the profile patch layer (`$DSH_HOME/profiles/<profile>/cordis.patch.yml`). This is the composition base.
46
- 2. **dsh web Settings page — the "插件配置" (Plugin Configuration) page** — the Advisor **card** (id `advisor`) with the enabled toggle, provider / model selects restricted to system-configured providers and their models, and the optional fields. Saving writes into the `advisor` settings namespace and applies to new sessions immediately — no restart. The card requires a current dsh web build whose shell declares the `settings.plugin.item` card slot and loads packages that declare `dsh.client`; it reads and writes the namespace through the official `GatewayService` RPC channel (`/api/advisor/get` + `/api/advisor/set`), which is not gated by the settings exposure allowlist. It additionally blocks saving while enabled with a required field empty.
47
+ 2. **dsh web Settings page — the "插件配置" (Plugin Configuration) page** — the Advisor **card** (namespace key `advisor`) with the enabled toggle, provider / model selects restricted to system-configured providers and their models, and the optional fields. Saving writes into the `advisor` settings namespace and applies to new sessions immediately — no restart. The card requires a current dsh web build whose shell declares the `settings.plugin.item` card slot and loads packages that declare `dsh.client`; it reads and writes the namespace through the official `GatewayService` RPC channel (`/api/advisor/get` + `/api/advisor/set`), which is not gated by the settings exposure allowlist. It additionally blocks saving while enabled with a required field empty.
47
48
  3. **`/advisor` command** — per-session and ephemeral: it flips a session override, never the persisted config (see [Verify](#verify)).
48
49
 
49
50
  In a **dsh-tui** profile the same five keys are editable in the TUI `/settings` screen: run `dsh --profile dsh-tui`, open `/settings`, and edit the **Advisor** section (`enabled` / `provider` / `model` / `immuneTurns` / `maxDeltaMessages`, each with zh/en label + hint). Edits are staged and written on save through the revision-fenced `settings.mutate` into the same `advisor` namespace user layer the web card writes, and re-apply live without a restart. `systemPrompt` is NOT a TUI field (the TUI text control is single-line; a multi-line prompt would be truncated) — edit it via the web card or `$DSH_HOME/settings.yaml`. The section requires dsh-tui ≥ v0.8.0 (shipped in the `dsh-tui-settings-sections` row of the v0.8.0+ bundle); older dsh-tui versions no-op it cleanly and the two file paths — profile patch layer + global `$DSH_HOME/settings.yaml` — remain the edit paths. `/advisor config` stays a read-only readback whose edit hint names the `/settings` screen when the seam is mounted. Save behavior differs from the web card: the TUI seam has no cross-field validation, so a save may set `enabled: true` with empty `provider`/`model` — the explicit model gate resolves that to disabled-with-reason at runtime (visible via `/advisor status` and `/advisor config`); the web card blocks such a save outright. Full reference → [docs/configuration.md](docs/configuration.md).
package/README.zh.md CHANGED
@@ -4,7 +4,8 @@
4
4
 
5
5
  [![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
6
6
  ![node](https://img.shields.io/badge/node-%5E22.19%20%7C%7C%20%3E%3D24-339933.svg)
7
- ![dsh](https://img.shields.io/badge/dsh-DeepSeek%20Harness%20compatible-4B32C3.svg)
7
+ ![dsh](https://img.shields.io/badge/dsh-0.1.0--rc.8-4B32C3.svg)
8
+ ![dsh tui](https://img.shields.io/badge/dsh%20tui-compatible-4B32C3.svg)
8
9
  [![dshfind](https://dshfind.com/api/badge/omdsh-dev/dsh-advisor?lang=zh)](https://dshfind.com/zh/plugins/omdsh-dev/dsh-advisor?ref=badge)
9
10
 
10
11
  一个移植 omp「advisor」子系统的独立 dsh(DeepSeek Harness)插件组合包:一个按会话运行的独立评审模型,观察主会话 transcript,用显式配置的模型(provider 与 model 均为必填)评审每个已完成的 stepped turn,并把按严重度排序的建议(nit / concern / blocker)注入回会话——不污染主循环,也不递归地评审自己。
@@ -43,7 +44,7 @@ advisor 默认关闭。启用后,`provider` 与 `model` 为**必填**:`enabl
43
44
  同一组键在**三个配置面**之间合成(后一层覆盖前一层;各处使用同一组键与同一个硬门禁,宿主侧门禁始终是所有路径上的最后防线):
44
45
 
45
46
  1. **插件行 config** —— profile 补丁层(`$DSH_HOME/profiles/<profile>/cordis.patch.yml`)。这是合成 base。
46
- 2. **dsh web Settings 页 —— "插件配置"页** —— Advisor **卡片**(id `advisor`),含 enabled 开关、只列出系统内已配置 provider 及其模型的 provider/model 选择框与可选字段。保存写入 `advisor` settings namespace,新会话立即生效,无需重启。卡片要求当前版本的 dsh web 构建(其 web shell 声明了 `settings.plugin.item` 卡片 slot 并能加载 `dsh.client` 声明包);它通过官方 `GatewayService` RPC 通道读写该命名空间(`/api/advisor/get` + `/api/advisor/set`),不受 settings 暴露白名单门控。卡片还会在 enabled 且必填字段为空时阻止保存。
47
+ 2. **dsh web Settings 页 —— "插件配置"页** —— Advisor **卡片**(namespace key `advisor`),含 enabled 开关、只列出系统内已配置 provider 及其模型的 provider/model 选择框与可选字段。保存写入 `advisor` settings namespace,新会话立即生效,无需重启。卡片要求当前版本的 dsh web 构建(其 web shell 声明了 `settings.plugin.item` 卡片 slot 并能加载 `dsh.client` 声明包);它通过官方 `GatewayService` RPC 通道读写该命名空间(`/api/advisor/get` + `/api/advisor/set`),不受 settings 暴露白名单门控。卡片还会在 enabled 且必填字段为空时阻止保存。
47
48
  3. **`/advisor` 指令** —— 按会话且临时:翻转的是会话级 override,从不修改持久化配置(见[验证](#验证))。
48
49
 
49
50
  在 **dsh-tui** profile 中,同样的五个键可在 TUI `/settings` 屏幕编辑:运行 `dsh --profile dsh-tui`、打开 `/settings`,编辑 **Advisor** 分节(`enabled` / `provider` / `model` / `immuneTurns` / `maxDeltaMessages`,每项均带中英文标签与提示)。编辑先暂存,保存时经 revision 栅栏保护的 `settings.mutate` 写入 web 卡片所写的同一个 `advisor` 命名空间 user layer,并 live 重应用、无需重启。`systemPrompt` **不是** TUI 字段(TUI text 控件为单行;多行 prompt 会被截断)——请经 web 卡片或 `$DSH_HOME/settings.yaml` 编辑。该分节要求 dsh-tui ≥ v0.8.0(随 v0.8.0+ 组合包的 `dsh-tui-settings-sections` 行提供);旧版 dsh-tui 会干净地 no-op,仍以两个文件路径——profile 补丁层 + 全局 `$DSH_HOME/settings.yaml`——作为编辑路径。`/advisor config` 仍是只读回读,seam 挂载时其编辑提示指向 `/settings` 屏幕。保存行为与 web 卡片不同:TUI seam 没有跨字段校验,一次保存可能把 `enabled: true` 与空 `provider`/`model` 一起写入——显式模型门禁会在运行时把它解析为 disabled-with-reason(可见于 `/advisor status` 与 `/advisor config`);web 卡片则会直接阻止这样的保存。完整参考 → [docs/configuration.md](docs/configuration.md)。
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * Advisor settings card (plan dsh-advisor-plugin-config-card-ux, task 1): the
3
3
  * card registered into the "插件配置" settings page's `settings.plugin.item`
4
- * slot (id `advisor`, order 30). It keeps the n5 gateway channel — the store
4
+ * keyed slot (key `advisor` the settings namespace the card edits). It keeps
5
+ * the n5 gateway channel — the store
5
6
  * reads/writes the advisor config through `/api/advisor/get` +
6
7
  * `/api/advisor/set` (KD-G3) — while the card chrome is rebuilt to replicate
7
8
  * the upstream `PluginCard` contract (self-drawn: the upstream client value
@@ -62,14 +63,18 @@
62
63
  */
63
64
  import { type ReactNode } from 'react';
64
65
  import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
65
- import type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-web-react';
66
+ import type { SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client';
66
67
  import type { AdvisorSettingsState, AdvisorSettingsStore } from './advisor-store.ts';
67
- /** Injected dependencies of {@link AdvisorCard} (slot `inject`). */
68
+ /** Injected dependencies of {@link AdvisorCard} (slot `inject`). The `hooks`
69
+ * compartment carries the bare snapshot store; the slot renderer binds it to
70
+ * the `useSnapshot` selector hook the component consumes (rc.8 contract). */
68
71
  export interface AdvisorCardInjected {
69
72
  /** The card store (loaded on mount, refreshed on pushed invalidations). */
70
73
  controller: AdvisorSettingsStore;
71
- /** uSES subscription hook bound to the store. */
72
- useSnapshot: SnapshotSelectorHook<AdvisorSettingsState>;
74
+ /** Bare snapshot source the renderer binds as `useSnapshot`. */
75
+ hooks: {
76
+ snapshot: SnapshotStore<AdvisorSettingsState>;
77
+ };
73
78
  }
74
79
  /**
75
80
  * Props the renderer binds for the card: the `settings.plugin.item` runtime
@@ -39,6 +39,13 @@
39
39
  */
40
40
  import type { ClientConnectionRpc, IApiClient, SettingsNamespaceView } from '@deepseek-ai/dsh-client-connection/client';
41
41
  import type { SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client';
42
+ import type { SettingsSchemaService } from '@deepseek-ai/dsh-client-ui-settings/client';
43
+ /**
44
+ * The rc.8 schema face the card store uses: ui-settings owns the immutable
45
+ * path writers (`ctx.settingsSchema`); this narrow pick hides the Cordis
46
+ * service identity from the store and its tests.
47
+ */
48
+ export type SettingsSchemaOperations = Pick<SettingsSchemaService, 'getPath' | 'setPath' | 'deletePath'>;
42
49
  /**
43
50
  * The wire `config` value the host gateway returns — mirror of the node-side
44
51
  * `ResolvedAdvisorConfig` (src/config.ts). Kept as a local structural type
@@ -177,6 +184,7 @@ export interface AdvisorSettingsState {
177
184
  export declare class AdvisorSettingsStore {
178
185
  private readonly api;
179
186
  private readonly rpc;
187
+ private readonly schema;
180
188
  /** The snapshot the card renders from (uSES-safe store). */
181
189
  readonly store: SnapshotStore<AdvisorSettingsState>;
182
190
  /** Latest load wins; an older response never overwrites a newer one. */
@@ -203,7 +211,9 @@ export declare class AdvisorSettingsStore {
203
211
  * @param rpc - the connection's generic RPC caller for the host gateway
204
212
  * channel (`/api`), injected from the connection handle.
205
213
  */
206
- constructor(api: Pick<IApiClient, 'settings' | 'llm'>, rpc: ClientConnectionRpc);
214
+ constructor(api: Pick<IApiClient, 'settings' | 'llm'>, rpc: ClientConnectionRpc, schema: SettingsSchemaOperations);
215
+ /** Profile-declared models (the provider's `models` directory), when the profile has one. */
216
+ private profileModels;
207
217
  /**
208
218
  * Refresh the whole page snapshot: the provider directory and the settings
209
219
  * namespaces in parallel, then the advisor config over the gateway channel,
@@ -296,9 +306,9 @@ export declare class AdvisorSettingsStore {
296
306
  * write (the frozen-snapshot write would be dropped by the snapshot store).
297
307
  */
298
308
  private recomputeDirty;
299
- /** Edit one always-present draft field via the schema-form path writer. */
309
+ /** Edit one always-present draft field via the settings schema path writer. */
300
310
  private setField;
301
- /** Remove one optional draft field via the schema-form path writer. */
311
+ /** Remove one optional draft field via the settings schema path writer. */
302
312
  private clearField;
303
313
  private clampInt;
304
314
  }
@@ -1,16 +1,17 @@
1
1
  /**
2
2
  * Advisor settings plugin, browser half. Registers the `advisor` card into
3
- * the shell-declared `settings.plugin.item` slot (the "插件配置" settings
4
- * page — id `advisor`, order 30, after the upstream bash / agent-loop /
5
- * web-search cards). The card's store joins the settings namespaces and the
3
+ * the shell-declared `settings.plugin.item` keyed slot (the "插件配置"
4
+ * settings page — key `advisor`, the settings namespace the card edits,
5
+ * appearing after the upstream bash / agent-loop / web-search cards in
6
+ * registration order). The card's store joins the settings namespaces and the
6
7
  * provider directory through the connection wire, and keeps fresh on pushed
7
8
  * invalidations. Export discipline: the client half value-imports ONLY the
8
9
  * frozen platform module table (CLIENT_EXTERNALS: react /
9
- * @deepseek-ai/cordis / ui-slots / web-react / ui-primitives /
10
- * schema-form / the documented `@deepseek-ai/dsh-client-runtime/client`
11
- * exemption); every other `@deepseek-ai/*` import is type-only (erased at
12
- * build) — values arrive via cordis injection (`ctx.get('connection')`, slot
13
- * inject faces). Mirrors the ui-models reference entry.
10
+ * @deepseek-ai/cordis / ui-slots / ui-primitives / the documented
11
+ * `@deepseek-ai/dsh-client-runtime/client` exemption); every other
12
+ * `@deepseek-ai/*` import is type-only (erased at build) — values arrive via
13
+ * cordis injection (`ctx.get('connection')`, slot inject faces, the
14
+ * `settingsSchema` service). Mirrors the ui-models reference entry.
14
15
  */
15
16
  import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
16
17
  import { type AdvisorKey } from './locales.ts';
package/lib/client.js CHANGED
@@ -29,7 +29,6 @@ __export(index_exports, {
29
29
  refreshIfLoaded: () => refreshIfLoaded
30
30
  });
31
31
  module.exports = __toCommonJS(index_exports);
32
- var import_dsh_client_web_react = require("@deepseek-ai/dsh-client-web-react");
33
32
 
34
33
  // src/client/advisor-card.tsx
35
34
  var import_react = require("react");
@@ -285,7 +284,6 @@ function AdvisorCard(props) {
285
284
 
286
285
  // src/client/advisor-store.ts
287
286
  var import_client = require("@deepseek-ai/dsh-client-runtime/client");
288
- var import_dsh_client_schema_form = require("@deepseek-ai/dsh-client-schema-form");
289
287
  function defaultDraft() {
290
288
  return { enabled: false, systemPrompt: "", immuneTurns: 3, maxDeltaMessages: 60 };
291
289
  }
@@ -311,20 +309,6 @@ function gateFailure(draft) {
311
309
  if (draft.model === void 0) return "model";
312
310
  return void 0;
313
311
  }
314
- function profileModels(profile) {
315
- const models = (0, import_dsh_client_schema_form.getPath)(profile, ["models"]);
316
- if (!Array.isArray(models)) return void 0;
317
- return models.flatMap((entry) => {
318
- if (typeof entry !== "object" || entry === null) return [];
319
- const model = entry;
320
- if (typeof model.id !== "string" || model.id.length === 0) return [];
321
- return [{
322
- id: model.id,
323
- name: typeof model.name === "string" ? model.name : model.id,
324
- ...typeof model.description === "string" ? { description: model.description } : {}
325
- }];
326
- });
327
- }
328
312
  var AdvisorSettingsStore = class {
329
313
  /**
330
314
  * @param api - the wire face (settings/llm domains) for the provider/model
@@ -332,9 +316,10 @@ var AdvisorSettingsStore = class {
332
316
  * @param rpc - the connection's generic RPC caller for the host gateway
333
317
  * channel (`/api`), injected from the connection handle.
334
318
  */
335
- constructor(api, rpc) {
319
+ constructor(api, rpc, schema) {
336
320
  __publicField(this, "api", api);
337
321
  __publicField(this, "rpc", rpc);
322
+ __publicField(this, "schema", schema);
338
323
  /** The snapshot the card renders from (uSES-safe store). */
339
324
  __publicField(this, "store", (0, import_client.createSnapshotStore)({
340
325
  status: "idle",
@@ -375,6 +360,21 @@ var AdvisorSettingsStore = class {
375
360
  /** The resolved advisor config at the last get/apply (patch diff baseline). */
376
361
  __publicField(this, "seed", defaultDraft());
377
362
  }
363
+ /** Profile-declared models (the provider's `models` directory), when the profile has one. */
364
+ profileModels(profile) {
365
+ const models = this.schema.getPath(profile, ["models"]);
366
+ if (!Array.isArray(models)) return void 0;
367
+ return models.flatMap((entry) => {
368
+ if (typeof entry !== "object" || entry === null) return [];
369
+ const model = entry;
370
+ if (typeof model.id !== "string" || model.id.length === 0) return [];
371
+ return [{
372
+ id: model.id,
373
+ name: typeof model.name === "string" ? model.name : model.id,
374
+ ...typeof model.description === "string" ? { description: model.description } : {}
375
+ }];
376
+ });
377
+ }
378
378
  /**
379
379
  * Refresh the whole page snapshot: the provider directory and the settings
380
380
  * namespaces in parallel, then the advisor config over the gateway channel,
@@ -429,7 +429,7 @@ var AdvisorSettingsStore = class {
429
429
  const options = [];
430
430
  for (const entry of providers) {
431
431
  const namespace = namespaces[entry.settingsNs];
432
- const configured = namespace !== void 0 && (entry.settingsPath.length === 0 || (0, import_dsh_client_schema_form.getPath)(namespace.value, entry.settingsPath) !== void 0);
432
+ const configured = namespace !== void 0 && (entry.settingsPath.length === 0 || this.schema.getPath(namespace.value, entry.settingsPath) !== void 0);
433
433
  if (!configured) continue;
434
434
  options.push({
435
435
  provider: entry.provider,
@@ -483,8 +483,8 @@ var AdvisorSettingsStore = class {
483
483
  const option = state.providers.find((candidate) => candidate.provider === provider);
484
484
  if (option === void 0) return;
485
485
  const namespace = state.namespaces[option.settingsNs];
486
- const profile = namespace !== void 0 ? (0, import_dsh_client_schema_form.getPath)(namespace.value, option.settingsPath) : void 0;
487
- const declared = profileModels(profile);
486
+ const profile = namespace !== void 0 ? this.schema.getPath(namespace.value, option.settingsPath) : void 0;
487
+ const declared = this.profileModels(profile);
488
488
  if (declared !== void 0) {
489
489
  this.store.update((s) => {
490
490
  if (declared.length > 0) {
@@ -553,8 +553,8 @@ var AdvisorSettingsStore = class {
553
553
  const trimmed = provider.trim();
554
554
  this.store.update((s) => {
555
555
  const draft = s.draft;
556
- const withoutProvider = trimmed.length === 0 ? (0, import_dsh_client_schema_form.deletePath)(draft, ["provider"]) : (0, import_dsh_client_schema_form.setPath)(draft, ["provider"], trimmed);
557
- s.draft = (0, import_dsh_client_schema_form.deletePath)(withoutProvider, ["model"]);
556
+ const withoutProvider = trimmed.length === 0 ? this.schema.deletePath(draft, ["provider"]) : this.schema.setPath(draft, ["provider"], trimmed);
557
+ s.draft = this.schema.deletePath(withoutProvider, ["model"]);
558
558
  s.applyState = { kind: "idle" };
559
559
  s.dirty = this.recomputeDirty(s.draft);
560
560
  });
@@ -716,18 +716,18 @@ var AdvisorSettingsStore = class {
716
716
  recomputeDirty(draft) {
717
717
  return Object.keys(this.patchFor(draft)).length > 0;
718
718
  }
719
- /** Edit one always-present draft field via the schema-form path writer. */
719
+ /** Edit one always-present draft field via the settings schema path writer. */
720
720
  setField(key, value) {
721
721
  this.store.update((s) => {
722
- s.draft = (0, import_dsh_client_schema_form.setPath)(s.draft, [key], value);
722
+ s.draft = this.schema.setPath(s.draft, [key], value);
723
723
  s.applyState = { kind: "idle" };
724
724
  s.dirty = this.recomputeDirty(s.draft);
725
725
  });
726
726
  }
727
- /** Remove one optional draft field via the schema-form path writer. */
727
+ /** Remove one optional draft field via the settings schema path writer. */
728
728
  clearField(key) {
729
729
  this.store.update((s) => {
730
- s.draft = (0, import_dsh_client_schema_form.deletePath)(s.draft, [key]);
730
+ s.draft = this.schema.deletePath(s.draft, [key]);
731
731
  s.applyState = { kind: "idle" };
732
732
  s.dirty = this.recomputeDirty(s.draft);
733
733
  });
@@ -805,12 +805,11 @@ var zh = {
805
805
 
806
806
  // src/client/index.ts
807
807
  var NS = "settings.advisor";
808
- var inject = ["slots", "locale", "connection"];
808
+ var inject = ["slots", "locale", "connection", "settingsSchema"];
809
809
  function apply(ctx) {
810
810
  ctx.effect(() => ctx.locale.register(NS, { zh, en }), "advisor: copy dictionaries");
811
811
  const connection = ctx.get("connection");
812
- const controller = new AdvisorSettingsStore(connection.api, connection.rpc);
813
- const useSnapshot = (0, import_dsh_client_web_react.bindSnapshotSelector)(controller.store);
812
+ const controller = new AdvisorSettingsStore(connection.api, connection.rpc, ctx.settingsSchema);
814
813
  ctx.effect(() => {
815
814
  let pending = false;
816
815
  const refresh = () => {
@@ -834,11 +833,18 @@ function apply(ctx) {
834
833
  ctx.slots.inject("settings.plugin.item", function* () {
835
834
  yield ctx.slots.register({
836
835
  name: "settings.plugin.item",
837
- id: "advisor",
838
- order: 30,
839
- // bash 0 / agent-loop 10 / web-search 20 / advisor 30
836
+ // rc.8 keyed slot: the key is the settings namespace the card edits —
837
+ // the already-installed `advisor` namespace (ADVISOR_SETTINGS_NAMESPACE
838
+ // in src/settings.ts; spelled as a literal here because the host-half
839
+ // settings module is outside the client bundle's externals). Keyed
840
+ // entries declare no `id`/`order` — appearance order is registration
841
+ // order, which still places this card after the upstream three.
842
+ key: "advisor",
840
843
  locale: NS,
841
- inject: () => ({ controller, useSnapshot })
844
+ // rc.8 hooks compartment: the renderer binds `hooks.snapshot` to the
845
+ // component's `useSnapshot` selector hook (the old web-react
846
+ // bindSnapshotSelector call is gone with that package).
847
+ inject: () => ({ controller, hooks: { snapshot: controller.store } })
842
848
  }, AdvisorCard);
843
849
  });
844
850
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-advisor",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "type": "module",
5
5
  "description": "dsh plugin bundle porting the omp advisor subsystem: a per-session reviewer model that observes the primary transcript and injects severity-ranked advice (nit/concern/blocker).",
6
6
  "repository": {
@@ -51,24 +51,22 @@
51
51
  },
52
52
  "peerDependencies": {
53
53
  "@deepseek-ai/cordis": "^4.0.1",
54
- "@deepseek-ai/dsh-agent": "^0.1.0-rc.6",
55
- "@deepseek-ai/dsh-api-gateway": "^0.1.0-rc.6",
56
- "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6",
57
- "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6",
58
- "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6",
59
- "@deepseek-ai/dsh-client-schema-form": "^0.1.0-rc.6",
60
- "@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.0-rc.6",
61
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6",
62
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6",
63
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6",
64
- "@deepseek-ai/dsh-client-web-react": "^0.1.0-rc.6",
65
- "@deepseek-ai/dsh-commands": "^0.1.0-rc.6",
66
- "@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
67
- "@deepseek-ai/dsh-session": "^0.1.0-rc.6",
68
- "@deepseek-ai/dsh-settings": "^0.1.0-rc.6",
69
- "@deepseek-ai/dsh-timeout": "^0.1.0-rc.6",
70
- "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.6",
71
- "@deepseek-ai/dsh-typert-registry": "^0.1.0-rc.6",
54
+ "@deepseek-ai/dsh-agent": "^0.1.0-rc.8",
55
+ "@deepseek-ai/dsh-api-gateway": "^0.1.0-rc.8",
56
+ "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.8",
57
+ "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.8",
58
+ "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.8",
59
+ "@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.0-rc.8",
60
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.8",
61
+ "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.8",
62
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.8",
63
+ "@deepseek-ai/dsh-commands": "^0.1.0-rc.8",
64
+ "@deepseek-ai/dsh-llm": "^0.1.0-rc.8",
65
+ "@deepseek-ai/dsh-session": "^0.1.0-rc.8",
66
+ "@deepseek-ai/dsh-settings": "^0.1.0-rc.8",
67
+ "@deepseek-ai/dsh-timeout": "^0.1.0-rc.8",
68
+ "@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.8",
69
+ "@deepseek-ai/dsh-typert-registry": "^0.1.0-rc.8",
72
70
  "react": "^18.2.0",
73
71
  "@deepseek-ai/schemastery": "^3.18.1"
74
72
  },
@@ -53,9 +53,7 @@ export const CLIENT_EXTERNALS = [
53
53
  'react-dom/client',
54
54
  '@deepseek-ai/cordis',
55
55
  '@deepseek-ai/dsh-client-ui-slots',
56
- '@deepseek-ai/dsh-client-web-react',
57
56
  '@deepseek-ai/dsh-client-ui-primitives',
58
- '@deepseek-ai/dsh-client-schema-form',
59
57
  '@deepseek-ai/dsh-client-runtime/client',
60
58
  ]
61
59