dsh-model-switch 0.4.39 → 0.4.41

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/CHANGELOG.md CHANGED
@@ -1,3 +1,25 @@
1
+ ## v0.4.41
2
+
3
+ DSH `0.2.1-rc.3`(2026-10-23 发布,当前在 `next` 通道)兼容性更新:**插件本体零改动**,本轮做的是实证与声明;旧线(`0.1.7-alpha.2` … `0.2.1-rc.2`)的声明与依赖下界原样保留。
4
+
5
+ - **rc.3 是纯客户端加法**(compare `dsh-v0.2.1-rc.2...dsh-v0.2.1-rc.3`,300 个文件):`ui-conversation` 只新增 `conversation.session.header.views.actions` 槽位与 header 的 `entryPins`/`entryActions`/`setPinned`(`conversation.composer` 链与 `ComposerChainProps` 一字未改);输入侧新增 `whenDraftExists`,`clearPreviousDraft` 语义保持兼容(本插件从不调用 `requestDraftInitialization`);`ui-user-questions`、`ui-primitives` 只加不改;`experimental-auto-review`、`dsh-tools`、`dsh-session`、`dsh-subagent` 与 `api/*` 源码未变(只有版本号)。
6
+ - **rc.3 lab 实测**(独立 home `~/.dsh-lab3`、端口 3083、`@deepseek-ai/dsh@0.2.1-rc.3`):挂载无 `best-effort on unverified runtime` 告警;「审查豁免」卡片正常,「恢复默认名单」得到 **58 条**;自动审查预设下 `read`+`glob`+`read` 让跳过计数到 **3**,随后 `write` 让计数保持 **3**(写操作仍走审查);计划卡「去聊天里说」使回合以 **`aborted`** 结束、输入框回来、显示「已停止」;草稿跨会话切换保留(rc.3 的修复点)。
7
+ - **rc.2 回归**(3082,同一份 0.4.41 产物):挂载正常、卡片正常、`glob`+`read` 跳过计数 **2**,与 0.4.40 行为一致。
8
+ - **声明**:`package.json#dsh.compatibility.dshReleases` 增加 `0.2.1-rc.3`;`README.md`、`README.zh.md` 与 `docs/dsh-compat-watch.md` 同步(含「rc.3 走 `next` 通道」与本次「用户显式要求、先于 `latest` 触发」的例外记录)。
9
+ - **测试**:`tests/compatibility.spec.ts` 新增两例——真实 `package.json` 必须同时保留旧线与 rc.3 的声明;rc.3 分类为 verified(不产生告警),未知版本仍 fail-open。
10
+
11
+ ## v0.4.40
12
+
13
+ 按你的点名,默认豁免名单从 47 条扩到 **58 条**:新增 11 个工具,全部在「设置 → 模型切换 → 审查豁免」里可查、可删、可恢复默认。
14
+
15
+ - **纯读 / 无副作用(6 个)**:`load_workspace_dependencies`(只返回打包依赖路径与版本)、`wait_agent`(只等待队友变化)、`ask_user_question`(把问题抛给人,决策权本来就在人手里)、`present`(只登记交付物卡片,不复制内容)、`sidebar_open`(只在侧栏打开文件/文件夹/URL)、`exit_plan_mode`(计划门由人审批,第二个审查者多余)。
16
+ - **只派发、副作用仍留在审查内(3 个)**:`send_message`(给队友投递消息,目标会话的预设是它被创建时定好的)、`team_task_create`(只写共享任务板)、`terminal_open`(只起 shell,后续 `terminal_send` 仍在审查)。
17
+ - **自治项(2 个,按你的明确决定放出)**:`create_goal`(创建持久目标,让本会话跨轮继续)、`schedule_create`(排一条未来投递的提示)。它们触发的新回合仍跑同一个 auto 预设,所以每轮里的工具调用照样逐次审查;风险是无人值守的 token 消耗,已在名单注释里标明。
18
+ - **明确排除:`subagent` / `subagent_fork` / `spawn_teammate` 永不进默认名单。** `dsh-subagent` 生成子会话时会读 `permissionPresets.current(parent.session)`,只有 `auto` / `danger-full-access` 会被继承;而本插件在"名单命中的调用正在飞"时把 `current()` 答成 `'custom'`——放行这三个会让子会话拿不到 auto 预设,等于造出**无审查的子 agent**。`tests/tool-allowlist.spec.ts` 新增 `DELEGATION_SPAWNS` 专项守卫,防止以后被顺手加进去。
19
+ - **守卫调整**:`MUTATING` 里移除 `send_message`、`team_task_create`(现按"派发类"放行),补入 `subagent`、`subagent_fork`。
20
+ - **注意**:默认名单只是"出厂值"。已经保存过名单的部署(含桌面)升级后不会自动多出这 11 条——需要点一次「恢复默认名单」,或手动加入。
21
+ - 测试:59 个测试文件 / **541** 测试(新增 delegation 守卫与"用户放行清单"两例)。
22
+
1
23
  ## v0.4.39
2
24
 
3
25
  「自动审查」下,**纯读工具不再调用审查模型**:`read` / `grep` / `glob` 这类只读调用直接执行,写操作、命令执行与删除仍然逐次审查。功能默认**关闭**,在「设置 → 模型切换 → 审查豁免」一键开启。
package/README.md CHANGED
@@ -158,7 +158,7 @@ A packed tarball installs the same build without a registry:
158
158
  dsh plugin --profile web add --force ./dsh-model-switch-0.4.26.tgz
159
159
  ```
160
160
 
161
- Then install only the provider adapters you use. This release was checked against official DeepSeek Harness `0.1.7-rc.2` and verified on `0.2.0-rc.2` and `0.2.1-rc.2`:
161
+ Then install only the provider adapters you use. This release was checked against official DeepSeek Harness `0.1.7-rc.2` and verified on `0.2.0-rc.2`, `0.2.1-rc.2` and `0.2.1-rc.3` (rc.3 currently ships on the `next` dist-tag):
162
162
 
163
163
  ```sh
164
164
  dsh plugin --profile web add --force \
package/README.zh.md CHANGED
@@ -156,7 +156,7 @@ dsh plugin --profile web add --force dsh-model-switch
156
156
  dsh plugin --profile web add --force ./dsh-model-switch-0.4.17.tgz
157
157
  ```
158
158
 
159
- 然后只安装实际使用的 Provider Adapter。此版本已在官方 DeepSeek Harness `0.1.7-rc.2` 上检查,并在 `0.2.0-rc.2` 上验证:
159
+ 然后只安装实际使用的 Provider Adapter。此版本已在官方 DeepSeek Harness `0.1.7-rc.2` 上检查,并在 `0.2.0-rc.2`、`0.2.1-rc.2` 与 `0.2.1-rc.3`(rc.3 目前走 `next` 通道)上验证:
160
160
 
161
161
  ```sh
162
162
  dsh plugin --profile web add --force \
@@ -187,7 +187,7 @@ DeepSeek 薄适配器调用官方公开 `DeepSeekSearchProvider`,复用用户
187
187
 
188
188
  DSH Host peer 和开发依赖接受 `>=0.1.7-alpha.2`,包括 rc.1 和后续版本。开发锁文件解析到 rc.2。Cordis 接受 `>=4.0.4 <5.0.0`。
189
189
 
190
- 已验证版本:`0.1.7-alpha.2`、`0.1.7-rc.1`、`0.1.7-rc.2`、`0.2.0-rc.2`、`0.2.1-rc.2`。0.2.0 的声明覆盖三处差异:Host 改名的提问撤下动词(`cancel()` → `dismiss()`)、`session.selectModel` 不 await 的部署默认值写入、以返回值报出的 `ModelDirectory.select` 拒绝;三者均已在 lab(3082/3085)与真实桌面会话中逐一验证。0.2.1 的声明覆盖两处被替换的 seam:共享命名调用改为 provider 自备提示词与解析的 `executeSessionTitleLlm`(本插件按安装行在运行时适配,并镜像官方 0.2.1 的提示词、取最低 reasoning effort 与 `currentTitle` 锚定);Subagent 运行时以 `startActivation` 取代 `start()`/`startContinuable()`,本插件同时识别两条已发布线,并为激活入口覆写 `spec.request.agentOptions`(显式路由仍优先、非 agentOptions 能力的外部适配器不改写),路由语义与旧线一致(0.4.28,记录于 `docs/seam-gap.md`);0.2.1 还新增了自动审查门禁对 `ctx.workingDirectory` 的读取,旧实现因在自己的 fiber 里直调 `official.apply` 而需要手工镜像门禁的 `inject`,于是每个工具调用都被拒(`cannot get property "workingDirectory" without inject`),0.4.28 改为把官方门禁以插件方式挂载、由官方 `inject` 解析依赖,本行只声明自身需要的服务。0.4.28 的真实包证据:0.2.1 上旧形态精确复现该注入错误、新形态到达 `workingDirectory.ensure` 且成功注册门禁、激活入口的路由改写与 spec 透传通过;0.2.0 上无需 `workingDirectory` 服务即可注册门禁,`start()` 路由改写与父身份保持不变。0.2.1 的 lab 证据为:npm 安装的 0.2.1 运行时 + 打包后的 0.4.26 组合 `exit 0`、命名/压缩/自动审查/子代理四行均来自本插件、Web Host 在 3082 启动并服务需要鉴权的页面;该次未经浏览器调用 3082 能力 RPC,真实桌面的 0.2.1 命名差分在应用升级后复验。0.2.1 还暴露出一处预设层面的差异(0.2.1 校验提示词变量、只有 `provider`/`model`,且把 `time-context`/`tool-schedule` 移进预设):0.4.26 的静态预设副本因此让每一轮都报 `unknown prompt variable "{{cwd}}"`,0.4.27 删除副本改为启动期运行时桥接,并在 lab 的 0.2.1 headless 真实回合中验证通过(展开见 CHANGELOG 0.4.27)。
190
+ 已验证版本:`0.1.7-alpha.2`、`0.1.7-rc.1`、`0.1.7-rc.2`、`0.2.0-rc.2`、`0.2.1-rc.2`、`0.2.1-rc.3`。0.2.0 的声明覆盖三处差异:Host 改名的提问撤下动词(`cancel()` → `dismiss()`)、`session.selectModel` 不 await 的部署默认值写入、以返回值报出的 `ModelDirectory.select` 拒绝;三者均已在 lab(3082/3085)与真实桌面会话中逐一验证。0.2.1 的声明覆盖两处被替换的 seam:共享命名调用改为 provider 自备提示词与解析的 `executeSessionTitleLlm`(本插件按安装行在运行时适配,并镜像官方 0.2.1 的提示词、取最低 reasoning effort 与 `currentTitle` 锚定);Subagent 运行时以 `startActivation` 取代 `start()`/`startContinuable()`,本插件同时识别两条已发布线,并为激活入口覆写 `spec.request.agentOptions`(显式路由仍优先、非 agentOptions 能力的外部适配器不改写),路由语义与旧线一致(0.4.28,记录于 `docs/seam-gap.md`);0.2.1 还新增了自动审查门禁对 `ctx.workingDirectory` 的读取,旧实现因在自己的 fiber 里直调 `official.apply` 而需要手工镜像门禁的 `inject`,于是每个工具调用都被拒(`cannot get property "workingDirectory" without inject`),0.4.28 改为把官方门禁以插件方式挂载、由官方 `inject` 解析依赖,本行只声明自身需要的服务。0.4.28 的真实包证据:0.2.1 上旧形态精确复现该注入错误、新形态到达 `workingDirectory.ensure` 且成功注册门禁、激活入口的路由改写与 spec 透传通过;0.2.0 上无需 `workingDirectory` 服务即可注册门禁,`start()` 路由改写与父身份保持不变。0.2.1 的 lab 证据为:npm 安装的 0.2.1 运行时 + 打包后的 0.4.26 组合 `exit 0`、命名/压缩/自动审查/子代理四行均来自本插件、Web Host 在 3082 启动并服务需要鉴权的页面;该次未经浏览器调用 3082 能力 RPC,真实桌面的 0.2.1 命名差分在应用升级后复验。0.2.1 还暴露出一处预设层面的差异(0.2.1 校验提示词变量、只有 `provider`/`model`,且把 `time-context`/`tool-schedule` 移进预设):0.4.26 的静态预设副本因此让每一轮都报 `unknown prompt variable "{{cwd}}"`,0.4.27 删除副本改为启动期运行时桥接,并在 lab 的 0.2.1 headless 真实回合中验证通过(展开见 CHANGELOG 0.4.27)。0.2.1-rc.3 是纯客户端改动:本品读到的三个包都是加法——`ui-conversation` 新增 `conversation.session.header.views.actions` 槽位与 header 的 `entryPins`/`entryActions`/`setPinned`(`conversation.composer` 链与 `ComposerChainProps` 一字未改)、`ui-primitives` 新增 `IconAppsAddOutline*` 图标、`ui-user-questions` 只有版本号;`experimental-auto-review`、`dsh-tools`、`dsh-session`、`dsh-subagent` 与 `api/*` 在 rc.3 中源码未变(后者只有版本号)。插件本体零改动,在 rc.3 lab(3083,`@deepseek-ai/dsh@0.2.1-rc.3`)复验:挂载无 unverified 告警、58 条默认名单、纯读跳过计数、写操作仍审查、计划卡「去聊天里说」回合以 `aborted` 结束、草稿跨会话保留;再用同一产物在 rc.2 lab(3082)回归通过(展开见 CHANGELOG 0.4.41)。
191
191
 
192
192
  `package.json#dsh.compatibility.dshReleases` 中的已验证版本是证据,不是允许列表。新增验证声明前要审查公开 API 变化并测试新 Host 版本。
193
193
 
@@ -127,13 +127,22 @@ const PLUGIN_TOOLS = /* @__PURE__ */ new Map([["generate_image", "dsh-model-swit
127
127
  /** `<base>__<owner>` — the extension-tool naming the QQ bot framework uses. */
128
128
  const EXTENSION_TOOL = /^([A-Za-z0-9_-]+)__(.+)$/;
129
129
  /**
130
- * Default allowlist: every pure-read tool this deployment exposes, calibrated on
131
- * a live desktop profile (105 tools) at dsh 0.2.1-rc.2.
130
+ * Default allowlist: every pure-read tool this deployment exposes plus the
131
+ * no-side-effect and autonomy entries the user explicitly released, calibrated
132
+ * on a live desktop profile (105 tools) at dsh 0.2.1-rc.2.
132
133
  *
133
134
  * Grouped by origin so a reader can trace each entry through {@link SOURCE_CATALOG}.
134
135
  * Entries ending in `*` are patterns: the QQ bot extension suffixes its tools with
135
136
  * the bot's own name, so `sessions_list__*` keeps working when the persona is
136
137
  * renamed.
138
+ *
139
+ * Everything here follows one rule: releasing it must not let a side effect escape
140
+ * the reviewer. Calls that merely dispatch, ask, present, wait or navigate qualify
141
+ * because the work they trigger still runs under the same auto preset. Delegation
142
+ * tools (`subagent`, `subagent_fork`, `spawn_teammate`) deliberately stay out: a
143
+ * child session seeds its preset from `permissionPresets.current(parent.session)`,
144
+ * and this bypass answers `'custom'` for an allowlisted call in flight — releasing
145
+ * them would hand the child no `auto` preset at all, i.e. no review.
137
146
  */
138
147
  const DEFAULT_READ_ONLY_TOOLS = [
139
148
  "read",
@@ -144,6 +153,11 @@ const DEFAULT_READ_ONLY_TOOLS = [
144
153
  "web_search",
145
154
  "web_search_pro",
146
155
  "web_fetch",
156
+ "load_workspace_dependencies",
157
+ "ask_user_question",
158
+ "present",
159
+ "sidebar_open",
160
+ "exit_plan_mode",
147
161
  "job_list",
148
162
  "job_output",
149
163
  "terminal_list",
@@ -153,6 +167,9 @@ const DEFAULT_READ_ONLY_TOOLS = [
153
167
  "team_task_get",
154
168
  "get_goal",
155
169
  "schedule_list",
170
+ "wait_agent",
171
+ "send_message",
172
+ "team_task_create",
156
173
  "list_mcp_resources",
157
174
  "list_mcp_resource_templates",
158
175
  "read_mcp_resource",
@@ -161,6 +178,9 @@ const DEFAULT_READ_ONLY_TOOLS = [
161
178
  "session_event_read",
162
179
  "session_event_trace",
163
180
  "session_trace",
181
+ "create_goal",
182
+ "schedule_create",
183
+ "terminal_open",
164
184
  "ops_read_files",
165
185
  "ops_discover_tools",
166
186
  "bcdp_status",
@@ -1,2 +1,2 @@
1
- import { a as bindAutoReviewSessionCorrelation, c as installToolCallSafetyNet, d as resolveSessionAutoReviewRoute, f as reviewLlm, i as autoReviewStatus, l as isReviewerInfrastructureFailure, n as autoReviewGate, o as defensivePermissionPresets, p as reviewScope, r as autoReviewRouteOf, s as inject, t as apply, u as name } from "./auto-review-C61WZIYI.js";
1
+ import { a as bindAutoReviewSessionCorrelation, c as installToolCallSafetyNet, d as resolveSessionAutoReviewRoute, f as reviewLlm, i as autoReviewStatus, l as isReviewerInfrastructureFailure, n as autoReviewGate, o as defensivePermissionPresets, p as reviewScope, r as autoReviewRouteOf, s as inject, t as apply, u as name } from "./auto-review-BDx3LjVL.js";
2
2
  export { apply, autoReviewGate, autoReviewRouteOf, autoReviewStatus, bindAutoReviewSessionCorrelation, defensivePermissionPresets, inject, installToolCallSafetyNet, isReviewerInfrastructureFailure, name, resolveSessionAutoReviewRoute, reviewLlm, reviewScope };
package/lib/client.js CHANGED
@@ -132,13 +132,22 @@ window.__ModuleLoader__.load({
132
132
  /** `<base>__<owner>` — the extension-tool naming the QQ bot framework uses. */
133
133
  const EXTENSION_TOOL = /^([A-Za-z0-9_-]+)__(.+)$/;
134
134
  /**
135
- * Default allowlist: every pure-read tool this deployment exposes, calibrated on
136
- * a live desktop profile (105 tools) at dsh 0.2.1-rc.2.
135
+ * Default allowlist: every pure-read tool this deployment exposes plus the
136
+ * no-side-effect and autonomy entries the user explicitly released, calibrated
137
+ * on a live desktop profile (105 tools) at dsh 0.2.1-rc.2.
137
138
  *
138
139
  * Grouped by origin so a reader can trace each entry through {@link SOURCE_CATALOG}.
139
140
  * Entries ending in `*` are patterns: the QQ bot extension suffixes its tools with
140
141
  * the bot's own name, so `sessions_list__*` keeps working when the persona is
141
142
  * renamed.
143
+ *
144
+ * Everything here follows one rule: releasing it must not let a side effect escape
145
+ * the reviewer. Calls that merely dispatch, ask, present, wait or navigate qualify
146
+ * because the work they trigger still runs under the same auto preset. Delegation
147
+ * tools (`subagent`, `subagent_fork`, `spawn_teammate`) deliberately stay out: a
148
+ * child session seeds its preset from `permissionPresets.current(parent.session)`,
149
+ * and this bypass answers `'custom'` for an allowlisted call in flight — releasing
150
+ * them would hand the child no `auto` preset at all, i.e. no review.
142
151
  */
143
152
  const DEFAULT_READ_ONLY_TOOLS = [
144
153
  "read",
@@ -149,6 +158,11 @@ window.__ModuleLoader__.load({
149
158
  "web_search",
150
159
  "web_search_pro",
151
160
  "web_fetch",
161
+ "load_workspace_dependencies",
162
+ "ask_user_question",
163
+ "present",
164
+ "sidebar_open",
165
+ "exit_plan_mode",
152
166
  "job_list",
153
167
  "job_output",
154
168
  "terminal_list",
@@ -158,6 +172,9 @@ window.__ModuleLoader__.load({
158
172
  "team_task_get",
159
173
  "get_goal",
160
174
  "schedule_list",
175
+ "wait_agent",
176
+ "send_message",
177
+ "team_task_create",
161
178
  "list_mcp_resources",
162
179
  "list_mcp_resource_templates",
163
180
  "read_mcp_resource",
@@ -166,6 +183,9 @@ window.__ModuleLoader__.load({
166
183
  "session_event_read",
167
184
  "session_event_trace",
168
185
  "session_trace",
186
+ "create_goal",
187
+ "schedule_create",
188
+ "terminal_open",
169
189
  "ops_read_files",
170
190
  "ops_discover_tools",
171
191
  "bcdp_status",
package/lib/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { o as normalizeProviderGroups } from "./session-route-D1zoZgf3.js";
2
- import { h as resolveToolSource, i as autoReviewStatus, m as DEFAULT_READ_ONLY_TOOLS } from "./auto-review-C61WZIYI.js";
2
+ import { h as resolveToolSource, i as autoReviewStatus, m as DEFAULT_READ_ONLY_TOOLS } from "./auto-review-BDx3LjVL.js";
3
3
  import { ModelSwitchAdapterRegistry } from "./adapter-registry.js";
4
4
  import { createRequire } from "node:module";
5
5
  import z from "@deepseek-ai/schemastery";
@@ -53,13 +53,22 @@ export declare const SOURCE_CATALOG: readonly SourceCatalogEntry[];
53
53
  /** Catalog lookup by id. */
54
54
  export declare const SOURCE_BY_ID: ReadonlyMap<string, SourceCatalogEntry>;
55
55
  /**
56
- * Default allowlist: every pure-read tool this deployment exposes, calibrated on
57
- * a live desktop profile (105 tools) at dsh 0.2.1-rc.2.
56
+ * Default allowlist: every pure-read tool this deployment exposes plus the
57
+ * no-side-effect and autonomy entries the user explicitly released, calibrated
58
+ * on a live desktop profile (105 tools) at dsh 0.2.1-rc.2.
58
59
  *
59
60
  * Grouped by origin so a reader can trace each entry through {@link SOURCE_CATALOG}.
60
61
  * Entries ending in `*` are patterns: the QQ bot extension suffixes its tools with
61
62
  * the bot's own name, so `sessions_list__*` keeps working when the persona is
62
63
  * renamed.
64
+ *
65
+ * Everything here follows one rule: releasing it must not let a side effect escape
66
+ * the reviewer. Calls that merely dispatch, ask, present, wait or navigate qualify
67
+ * because the work they trigger still runs under the same auto preset. Delegation
68
+ * tools (`subagent`, `subagent_fork`, `spawn_teammate`) deliberately stay out: a
69
+ * child session seeds its preset from `permissionPresets.current(parent.session)`,
70
+ * and this bypass answers `'custom'` for an allowlisted call in flight — releasing
71
+ * them would hand the child no `auto` preset at all, i.e. no review.
63
72
  */
64
73
  export declare const DEFAULT_READ_ONLY_TOOLS: readonly string[];
65
74
  /** Why one allowlist entry was refused. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-model-switch",
3
- "version": "0.4.39",
3
+ "version": "0.4.41",
4
4
  "description": "Explicit model routing plus composer/Plan picker for DeepSeek Harness",
5
5
  "repository": {
6
6
  "type": "git",
@@ -107,7 +107,8 @@
107
107
  "0.1.7-rc.1": "compatible",
108
108
  "0.1.7-rc.2": "compatible",
109
109
  "0.2.0-rc.2": "compatible",
110
- "0.2.1-rc.2": "compatible"
110
+ "0.2.1-rc.2": "compatible",
111
+ "0.2.1-rc.3": "compatible"
111
112
  }
112
113
  }
113
114
  },