@eddyskywalker/dsh-chatgpt-subscription 0.2.14 → 0.2.16

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,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.15 - 2026-09-11
4
+
5
+ - 新增子代理模型授权守卫:DSH 的「Subagent」允许列表(`subagent-model-selection`)原本只在模型**显式**填写 `provider`/`model` 时生效,而委派调用不填路由时子代理会继承父级模型——于是 DeepSeek 会话里的子代理仍会在未授权模型上运行。插件现在在 Host 工具注册表上注册一个单调守卫(`ctx.tools.guard`),当调用会话(或最近的、记录了策略的祖先会话)带有允许列表时,任何生效路由不在此列表内的委派都会在子代理启动前被拒绝,拒绝理由里带上全部已授权路由,模型据此重试即可选中合规模型。
6
+ - 该守卫只在会话确实记录了允许列表时介入(与 DSH 委派工具的会话快照语义一致),不会改变未启用该设置的会话;`subagentModelScope: 'preference'` 可让当前设置卡允许列表也约束未记录策略的会话(含恢复的旧会话)。
7
+ - 只读取公开接口:会话日志事件 `subagent/model-selection-policy`、父会话谱系、Host 设置文档与 `ctx.tools.guard`,不修改 DSH 本体。
8
+ - 新增配置项:`subagentModelAuthorization`(默认 `true`)、`subagentModelTools`(默认 `['subagent']`)、`subagentModelScope`(默认 `session`,可选 `preference`)。
9
+ - 新增 14 条单测覆盖策略解析、谱系继承、设置读取、显式/继承路由的拒绝与放行、作用域切换以及守卫安装路径(含注册与释放)。
10
+ ## 0.2.14 - 2026-09-10
11
+
12
+ - 移除失效的「子代理最大嵌套深度 / 子代理上下文预算」设置:这两个偏好键在 DSH 侧没有任何消费方(全仓库无引用),插件自身也只有写、没有读,保存了也不生效。它们源于 2026-08-28 的 `5b08e2e`——那次提交迁移到 DSH 原生子代理模型路由,删除了 `subagent-context-adapter` / `subagent-policy` / `SubagentSettingsSection`,但把这两个控件和偏好键留了下来。相关 DTO 字段、schema、路由校验、界面控件、6 条未引用文案与失效单测一并移除;子代理模型与思考深度改用 DSH 自身的“Subagent”设置卡片,最大嵌套深度由 preset 中 `tool-subagent` 的 `maxDepth` 决定,README 同步更正。
13
+
3
14
  ## 0.2.13 - 2026-09-10
4
15
 
5
16
  - 回退 Codex 与 Antigravity 模型上新增的 `systemPromptUpdate: 'in-history'` 声明:Responses 线路把系统提示词放在顶层 `instructions`,Antigravity 把它放在固定的 `systemInstruction` 加一条 user turn,两条路由都无法把"历史中最后一条 system 消息"当作完整系统提示词。声明该能力会让 DSH 在提示词变化时改为追加 system 节点并保留旧节点,而两个 mapper 会把新旧提示词一并发出。Codex mapper 同时改为只取最新一条非空 system 消息,避免将来重新声明时再次拼接过期提示词。
@@ -57,4 +68,4 @@
57
68
  - 适配 DSH `0.1.0-rc.8`:peerDependencies / devDependencies 中全部 DSH 包范围从 `^0.1.0-rc.6` 提升至 `^0.1.0-rc.8`,并重新生成 package-lock.json。已在本机 rc.8 依赖集上验证:typecheck、55 项测试与 tsdown 构建全部通过,插件代码无需改动。
58
69
  - 移除已无引用的 `@deepseek-ai/dsh-agent` peer 依赖(子代理报告去重兼容模块已于 0.1.11 移除)。
59
70
  - 新增 `@deepseek-ai/dsh-client-connection` peer 依赖(客户端 `ContentBlock` 类型来源,符合 rc.8 客户端包 peer 声明惯例)。
60
- - 说明:rc.8 中 `@deepseek-ai/dsh-client-ui-slots` 不再是 DSH 运行时依赖图成员(仅保留为各客户端包的 devDependency),插件继续将其声明为 peer 依赖以保证安装时解析(`^0.1.0-rc.6` 联网安装时解析到 rc.8;本地锁文件因离线环境暂固定 rc.7,API 与 rc.8 用法一致)。
71
+ - 说明:rc.8 中 `@deepseek-ai/dsh-client-ui-slots` 不再是 DSH 运行时依赖图成员(仅保留为各客户端包的 devDependency),插件继续将其声明为 peer 依赖以保证安装时解析(`^0.1.0-rc.6` 联网安装时解析到 rc.8;本地锁文件因离线环境暂固定 rc.7,API 与 rc.8 用法一致)。
package/README.md CHANGED
@@ -11,6 +11,7 @@
11
11
  - [环境要求](#环境要求)
12
12
  - [安装](#安装)
13
13
  - [使用](#使用)
14
+ - [子代理模型授权](#子代理模型授权0215-起)
14
15
  - [升级、降级与卸载](#升级降级与卸载)
15
16
  - [安全边界](#安全边界)
16
17
  - [插件路由](#插件路由)
@@ -39,8 +40,8 @@
39
40
  **设置页**
40
41
 
41
42
  - 展示账号(脱敏 email、套餐、账号 ID 后四位)、连接状态、额度与订阅增强功能开关;
42
- - 独立的“子代理”设置页可全局选择 DSH 当前接入的任意 Provider/模型(如 DeepSeek V4 Flash);思考深度来自所选模型公开能力,上下文在选定模型后展开配置,并适用于所有 DSH 内置子代理,不受父 Agent 当前 Provider/模型影响;
43
- - 可全局设置 0–3 的最大嵌套深度与每个父 Agent 子树的活动子代理数量上限;限制即时作用于新委派,不中断已运行的子代理;
43
+ - 子代理的模型与思考深度沿用 DSH 自身设置:**设置 Subagent** 卡片授权 Agent 可以为子代理挑选的模型(来自 DSH 已接入的全部 Provider,包含本插件的 Codex / Antigravity),新 Agent 的默认路由由 DSH 的 `agent-default-model` 设置提供;
44
+ - 最大嵌套深度是 DSH 子代理工具的装配配置(preset `tool-subagent` 的 `maxDepth`,默认 3;`provider-managed` 表示把预算交给进程外提供方),不在本插件设置内;
44
45
  - 6 Astra 与 5.6 Sol / Terra / Luna 默认使用 272K 有效上下文;订阅侧 6 Astra 可配置最高 872K,5.6 系列最高 1M,用于 DSH 压缩与溢出判断;其他模型保持目录声明值;
45
46
  - 可访问的进度条、窄窗口/200% 缩放布局、深浅主题与 reduced-motion。
46
47
 
@@ -116,7 +117,7 @@ npx @deepseek-ai/dsh plugin --profile web add "link:C:\absolute\path\to\dsh-chat
116
117
  3. 完成 ChatGPT 登录;
117
118
  4. 执行 **测试连接**。
118
119
 
119
- DSH 模型选择器应显示 **“Codex(ChatGPT 订阅)”**。6 Astra 与 GPT-5.6 系列的有效上下文窗口仍在“Codex 订阅 → 增强功能”中配置;子代理模型、思考深度、子代理上下文、最大嵌套深度和数量上限则统一位于独立的 **“子代理”** 设置页。模型路由适用于会话标记为 `origin: subagent` 的 DSH 内置子代理;运行限制在内置 spawn/fork 及已启用的原生子代理委派工具入口统一执行。
120
+ DSH 模型选择器应显示 **“Codex(ChatGPT 订阅)”**。6 Astra 与 GPT-5.6 系列的有效上下文窗口在“Codex 订阅 → 增强功能”中配置。子代理的模型与思考深度由 DSH 自身的设置决定(**设置 → Subagent** 卡片授权的模型清单,以及 `agent-default-model` 的默认路由);最大嵌套深度由 DSH preset 中 `tool-subagent` 的 `maxDepth` 决定。
120
121
 
121
122
  **设置 → Codex 订阅 → 网络代理** 同时控制 GPT 与 Antigravity(Gemini)的 Host 请求,可选择系统代理(自动检测)、自定义代理或直连。Gemini 模型生成、网页登录后的令牌交换、令牌刷新、账号信息、项目发现、配额与模型目录查询均使用此设置;修改后对后续请求生效,无需重启 DSH。浏览器中的 Google 授权页面使用浏览器自己的网络设置。
122
123
 
@@ -132,6 +133,27 @@ DSH 模型选择器应显示 **“Codex(ChatGPT 订阅)”**。6 Astra 与 G
132
133
 
133
134
  > Windows 文件只能由创建它的用户通过 DPAPI 解密。macOS 凭据由登录钥匙串在本机加密保存。Linux 文件是未额外加密的 JSON,依赖目录 `0700` 和文件 `0600` 隔离;不要复制、打印或提交该文件。跨平台迁移需要重新登录。
134
135
 
136
+ ## 子代理模型授权(0.2.15 起)
137
+
138
+ DSH 设置页的「Subagent」卡片会把勾选的模型写成会话级的允许列表(会话日志事件 `subagent/model-selection-policy`)。DSH 内置委派工具只拒绝**模型显式填写**且不在列表内的路由;调用里不写 `provider`/`model` 时,子代理会继承父级模型,于是白名单之外的主模型(例如 `deepseek-official/deepseek-flash`)仍会被子代理使用。
139
+
140
+ 插件在 Host 工具注册表上补一个单调守卫(`ctx.tools.guard`),在委派执行前判定生效路由:
141
+
142
+ - 调用会话(或最近的、记录了策略的祖先会话)带有允许列表时,生效路由必须落在列表内;
143
+ - 不写路由的委派按“继承父级模型”判定,因此父级模型不在列表内时会被拒绝;
144
+ - 拒绝结果里会列出全部已授权路由(例如 `antigravity/gemini-3.8-flash`),模型照此重试即可;`list_subagent_models` 仍只展示已授权路由;
145
+ - 未记录允许列表的会话(例如恢复的旧会话、未启用该设置的会话)保持 DSH 原有行为。
146
+
147
+ 配置项(插件行 `config`,全部可省略):
148
+
149
+ | 字段 | 默认 | 含义 |
150
+ |---|---|---|
151
+ | `subagentModelAuthorization` | `true` | 是否启用上述授权守卫;设为 `false` 回到 DSH 原有行为 |
152
+ | `subagentModelTools` | `['subagent']` | 需要授权的委派工具名;preset 里自定义了 `toolName` 时在此列出 |
153
+ | `subagentModelScope` | `session` | `session` 只约束记录了允许列表的会话;`preference` 额外用当前设置卡列表约束未记录的会话 |
154
+
155
+ 改动只在设置卡片里保存过的勾选生效:设置改动只影响之后新建的会话(DSH 的会话快照语义),已运行的会话继续使用它自己记录的那份列表。
156
+
135
157
  ## 安全边界
136
158
 
137
159
  Antigravity 的 access token / refresh token 使用独立的系统凭据存储:Windows 使用 CurrentUser DPAPI(`$DSH_HOME/storages/antigravity-oauth.json.dpapi`),macOS 使用登录钥匙串,Linux 使用 Secret Service。macOS / Linux 的服务名为 `dsh-antigravity`,账号键按旧凭据文件的绝对路径生成,隔离不同的 `DSH_HOME`。
@@ -192,4 +214,4 @@ npm pack --dry-run
192
214
  | 模型不可用 | 检查 ChatGPT 套餐、workspace 权限与当前模型可用性 |
193
215
  | DPAPI 读取失败 | 确认 DSH 以创建凭据时的同一 Windows 用户运行;必要时清理凭据后重新登录 |
194
216
  | Linux 凭据存储不可用 | 确认凭据属于当前用户且权限为 `0600`,父目录权限为 `0700`;修复权限或注销后重新登录 |
195
- | Linux 上工具调用语法错误 | 确认 DSH 暴露的是 `bash`、`sh` 或 `shell`,并使用相应的 Bash/POSIX 语法与 `/` 路径 |
217
+ | Linux 上工具调用语法错误 | 确认 DSH 暴露的是 `bash`、`sh` 或 `shell`,并使用相应的 Bash/POSIX 语法与 `/` 路径 |
package/lib/client.js CHANGED
@@ -372,7 +372,6 @@ window.__ModuleLoader__.load({
372
372
  const [resetCreditNotice, setResetCreditNotice] = (0, react.useState)(null);
373
373
  const [connection, setConnection] = (0, react.useState)(null);
374
374
  const [contextDrafts, setContextDrafts] = (0, react.useState)({});
375
- const [subagentContextDraft, setSubagentContextDraft] = (0, react.useState)(null);
376
375
  const [customProxyDraft, setCustomProxyDraft] = (0, react.useState)(null);
377
376
  const load = (0, react.useCallback)(async (quiet = false) => {
378
377
  if (!quiet) setError(null);
@@ -524,21 +523,6 @@ window.__ModuleLoader__.load({
524
523
  [model]: String(parsed)
525
524
  }));
526
525
  };
527
- const updateSubagentContextWindow = async () => {
528
- const draft = subagentContextDraft?.trim();
529
- if (draft === void 0 || draft === "") {
530
- await updatePreferences({ subagentContextWindow: null });
531
- setSubagentContextDraft(null);
532
- return;
533
- }
534
- const parsed = parsePositiveCapacity$1(draft);
535
- if (parsed === null) {
536
- setError(t("contextWindowInvalid"));
537
- return;
538
- }
539
- await updatePreferences({ subagentContextWindow: parsed });
540
- setSubagentContextDraft(null);
541
- };
542
526
  const updateCustomProxyUrl = async () => {
543
527
  const draft = customProxyDraft?.trim();
544
528
  await updatePreferences({ customProxyUrl: draft ? draft : null });
@@ -906,91 +890,6 @@ window.__ModuleLoader__.load({
906
890
  ]
907
891
  })]
908
892
  }),
909
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
910
- className: "dsh-codex-pref-row",
911
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("subagentMaxDepth") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
912
- className: "dsh-codex-muted",
913
- children: t("subagentMaxDepthHint")
914
- })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
915
- className: "dsh-codex-select",
916
- "aria-label": t("subagentMaxDepth"),
917
- value: preferences?.subagentMaxDepth === null || preferences?.subagentMaxDepth === void 0 ? "" : String(preferences.subagentMaxDepth),
918
- disabled: busy !== null,
919
- onChange: (event) => {
920
- const value = event.currentTarget.value;
921
- updatePreferences({ subagentMaxDepth: value === "" ? null : Number(value) });
922
- },
923
- children: [
924
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
925
- value: "",
926
- children: t("providerDefault")
927
- }),
928
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
929
- value: "0",
930
- children: [
931
- "0 (",
932
- t("subagentDisabled"),
933
- ")"
934
- ]
935
- }),
936
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
937
- value: "1",
938
- children: ["1 ", t("levels")]
939
- }),
940
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
941
- value: "2",
942
- children: ["2 ", t("levels")]
943
- }),
944
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
945
- value: "3",
946
- children: ["3 ", t("levels")]
947
- })
948
- ]
949
- })]
950
- }),
951
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
952
- className: "dsh-codex-context-settings",
953
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("subagentContextWindow") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
954
- className: "dsh-codex-muted",
955
- children: t("subagentContextWindowHint")
956
- })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
957
- className: "dsh-codex-context-row",
958
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
959
- htmlFor: "dsh-codex-subagent-context",
960
- children: t("subagentContextWindow")
961
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
962
- className: "dsh-codex-capacity-control",
963
- children: [
964
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
965
- id: "dsh-codex-subagent-context",
966
- type: "text",
967
- inputMode: "numeric",
968
- placeholder: t("providerDefault"),
969
- value: subagentContextDraft ?? (preferences?.subagentContextWindow ? formatCapacity$1(preferences.subagentContextWindow) : ""),
970
- disabled: busy !== null,
971
- "aria-label": t("subagentContextWindow"),
972
- onChange: (event) => {
973
- setSubagentContextDraft(event.currentTarget.value);
974
- },
975
- onKeyDown: (event) => {
976
- if (event.key !== "Enter") return;
977
- event.preventDefault();
978
- updateSubagentContextWindow();
979
- }
980
- }),
981
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: t("tokens") }),
982
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
983
- className: "dsh-codex-context-save",
984
- type: "button",
985
- "aria-label": t("save") + " " + t("subagentContextWindow"),
986
- disabled: busy !== null || subagentContextDraft === null,
987
- onClick: () => void updateSubagentContextWindow(),
988
- children: t("save")
989
- })
990
- ]
991
- })]
992
- })]
993
- }),
994
893
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
995
894
  className: "dsh-codex-context-settings",
996
895
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: t("contextWindows") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
@@ -1416,13 +1315,6 @@ window.__ModuleLoader__.load({
1416
1315
  searchProviderDsh: "DSH 默认",
1417
1316
  searchProviderCodex: "ChatGPT(代理隧道)",
1418
1317
  providerDefault: "使用 Provider 默认值",
1419
- subagentEnhancements: "子代理设置",
1420
- subagentContextWindow: "子代理上下文预算",
1421
- subagentContextWindowHint: "限制子代理运行时的最大上下文 Token 数(例如 128K、256K);留空跟随模型主设置。",
1422
- subagentMaxDepth: "子代理最大嵌套深度",
1423
- subagentMaxDepthHint: "限制子代理的递归层级(0–3);0 禁止创建子代理。",
1424
- subagentDisabled: "已禁用",
1425
- levels: "层",
1426
1318
  contextWindows: "模型上下文窗口",
1427
1319
  contextWindowsHint: "默认 272K;6 Astra 最高 872K,GPT-5.6 最高 1M。该值用于 DSH 的压缩与溢出判断,可输入 872K、512K 等容量。",
1428
1320
  contextWindow: "上下文窗口",
@@ -1547,13 +1439,6 @@ window.__ModuleLoader__.load({
1547
1439
  searchProviderDsh: "DSH default",
1548
1440
  searchProviderCodex: "ChatGPT (Proxy tunnel)",
1549
1441
  providerDefault: "Use provider default",
1550
- subagentEnhancements: "Subagent settings",
1551
- subagentContextWindow: "Subagent context window budget",
1552
- subagentContextWindowHint: "Limits context capacity in tokens for subagents (e.g. 128K, 256K); leave empty to follow main model settings.",
1553
- subagentMaxDepth: "Subagent maximum nesting depth",
1554
- subagentMaxDepthHint: "Limits child levels for subagents (0–3); 0 disables subagents.",
1555
- subagentDisabled: "Disabled",
1556
- levels: "levels",
1557
1442
  contextWindows: "Model context windows",
1558
1443
  contextWindowsHint: "Defaults to 272K, with up to 872K for 6 Astra and 1M for GPT-5.6. DSH uses it for compaction and overflow detection; values such as 872K and 512K are accepted.",
1559
1444
  contextWindow: "Context window",