@eddyskywalker/dsh-chatgpt-subscription 0.2.15 → 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,12 @@
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 条单测覆盖策略解析、谱系继承、设置读取、显式/继承路由的拒绝与放行、作用域切换以及守卫安装路径(含注册与释放)。
3
10
  ## 0.2.14 - 2026-09-10
4
11
 
5
12
  - 移除失效的「子代理最大嵌套深度 / 子代理上下文预算」设置:这两个偏好键在 DSH 侧没有任何消费方(全仓库无引用),插件自身也只有写、没有读,保存了也不生效。它们源于 2026-08-28 的 `5b08e2e`——那次提交迁移到 DSH 原生子代理模型路由,删除了 `subagent-context-adapter` / `subagent-policy` / `SubagentSettingsSection`,但把这两个控件和偏好键留了下来。相关 DTO 字段、schema、路由校验、界面控件、6 条未引用文案与失效单测一并移除;子代理模型与思考深度改用 DSH 自身的“Subagent”设置卡片,最大嵌套深度由 preset 中 `tool-subagent` 的 `maxDepth` 决定,README 同步更正。
@@ -61,4 +68,4 @@
61
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 构建全部通过,插件代码无需改动。
62
69
  - 移除已无引用的 `@deepseek-ai/dsh-agent` peer 依赖(子代理报告去重兼容模块已于 0.1.11 移除)。
63
70
  - 新增 `@deepseek-ai/dsh-client-connection` peer 依赖(客户端 `ContentBlock` 类型来源,符合 rc.8 客户端包 peer 声明惯例)。
64
- - 说明: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
  - [插件路由](#插件路由)
@@ -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/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
+ import z from "@deepseek-ai/schemastery";
2
3
  import * as LlmModule from "@deepseek-ai/dsh-llm";
3
4
  import { HarnessError, LlmAdapter, LlmError, ProviderRequestId, ReasoningEffortId, attributionHeaders, resolveRetryPolicy } from "@deepseek-ai/dsh-llm";
4
5
  import { WebError } from "@deepseek-ai/dsh-web";
@@ -12,7 +13,6 @@ import path, { dirname, join } from "node:path";
12
13
  import os, { homedir } from "node:os";
13
14
  import { ProxyAgent, fetch as fetch$1 } from "undici";
14
15
  import * as SettingsModule from "@deepseek-ai/dsh-settings";
15
- import z from "@deepseek-ai/schemastery";
16
16
  import fsPromises, { chmod, lstat, mkdir, open, rename, stat, unlink } from "node:fs/promises";
17
17
  import { isDeepStrictEqual } from "node:util";
18
18
  import { URL as URL$1, URLSearchParams as URLSearchParams$1 } from "node:url";
@@ -4912,7 +4912,7 @@ function sanitizeText(text) {
4912
4912
  function isRecord(value) {
4913
4913
  return typeof value === "object" && value !== null && !Array.isArray(value);
4914
4914
  }
4915
- function asString(value) {
4915
+ function asString$1(value) {
4916
4916
  return typeof value === "string" ? value : void 0;
4917
4917
  }
4918
4918
  function safeJsonParse(text) {
@@ -4935,10 +4935,10 @@ function parseArguments(raw) {
4935
4935
  return isRecord(parsed) ? parsed : {};
4936
4936
  }
4937
4937
  function imageBlockToPart(block) {
4938
- let data = asString(block.data) || asString(block.base64);
4938
+ let data = asString$1(block.data) || asString$1(block.base64);
4939
4939
  const source = isRecord(block.source) ? block.source : void 0;
4940
- if (!data && source) data = asString(source.data) || asString(source.base64);
4941
- let mimeType = asString(block.mimeType) || asString(block.mediaType) || (source ? asString(source.mimeType) || asString(source.mediaType) : void 0) || "image/png";
4940
+ if (!data && source) data = asString$1(source.data) || asString$1(source.base64);
4941
+ let mimeType = asString$1(block.mimeType) || asString$1(block.mediaType) || (source ? asString$1(source.mimeType) || asString$1(source.mediaType) : void 0) || "image/png";
4942
4942
  if (data?.startsWith("data:")) {
4943
4943
  const match = data.match(/^data:([^;,]+);base64,(.*)$/s);
4944
4944
  if (match) {
@@ -4984,7 +4984,7 @@ function replayBlockFor(message, index) {
4984
4984
  }
4985
4985
  }
4986
4986
  function thoughtSignature(part) {
4987
- return asString(part?.thoughtSignature) || asString(part?.thought_signature) || asString(part?.thinkingSignature) || asString(part?.textSignature);
4987
+ return asString$1(part?.thoughtSignature) || asString$1(part?.thought_signature) || asString$1(part?.thinkingSignature) || asString$1(part?.textSignature);
4988
4988
  }
4989
4989
  function replayPart(part) {
4990
4990
  const copy = { ...part };
@@ -5003,7 +5003,7 @@ function assistantParts(message, model, runtimeModel, toolCalls) {
5003
5003
  if (!isRecord(block)) continue;
5004
5004
  const replay = replayBlockFor(message, index);
5005
5005
  const originalParts = Array.isArray(replay?.parts) ? replay.parts.filter(isRecord) : [];
5006
- if ((block.type === "text" || block.type === "reasoning") && originalParts.length > 0 && originalParts.every((part) => !part.functionCall) && originalParts.map((part) => asString(part.text) || "").join("") === sanitizeText(String(block.text || ""))) {
5006
+ if ((block.type === "text" || block.type === "reasoning") && originalParts.length > 0 && originalParts.every((part) => !part.functionCall) && originalParts.map((part) => asString$1(part.text) || "").join("") === sanitizeText(String(block.text || ""))) {
5007
5007
  parts.push(...originalParts.map(replayPart));
5008
5008
  continue;
5009
5009
  }
@@ -5024,7 +5024,7 @@ function assistantParts(message, model, runtimeModel, toolCalls) {
5024
5024
  const toolId = String(block.id || "");
5025
5025
  const toolName = String(block.name || "");
5026
5026
  const originalCall = originalParts.find((part) => isRecord(part.functionCall));
5027
- const wireId = asString((isRecord(originalCall?.functionCall) ? originalCall.functionCall : void 0)?.id) || (toolCallIdNeeded(model.id, runtimeModel) ? sanitizeToolCallId(toolId, toolName) : originalCall ? void 0 : toolId || void 0);
5027
+ const wireId = asString$1((isRecord(originalCall?.functionCall) ? originalCall.functionCall : void 0)?.id) || (toolCallIdNeeded(model.id, runtimeModel) ? sanitizeToolCallId(toolId, toolName) : originalCall ? void 0 : toolId || void 0);
5028
5028
  toolCalls.set(toolId, {
5029
5029
  name: toolName,
5030
5030
  id: wireId
@@ -5301,8 +5301,8 @@ function processStreamLine(line, state) {
5301
5301
  if (isRecord(part.functionCall)) {
5302
5302
  out.push(...closeCurrentBlock(state));
5303
5303
  const fc = part.functionCall;
5304
- const toolName = asString(fc.name) || "";
5305
- const toolId = asString(fc.id) || sanitizeToolCallId("", toolName);
5304
+ const toolName = asString$1(fc.name) || "";
5305
+ const toolId = asString$1(fc.id) || sanitizeToolCallId("", toolName);
5306
5306
  const argsText = JSON.stringify(isRecord(fc.args) ? fc.args : {});
5307
5307
  const index = state.blocks.length;
5308
5308
  const block = {
@@ -5340,7 +5340,7 @@ function processStreamLine(line, state) {
5340
5340
  }
5341
5341
  collectUsage(chunk.usageMetadata, state);
5342
5342
  if (responseData !== chunk) collectUsage(responseData.usageMetadata, state);
5343
- const finishReason = asString(candidate?.finishReason) || asString(responseData.finishReason);
5343
+ const finishReason = asString$1(candidate?.finishReason) || asString$1(responseData.finishReason);
5344
5344
  if (finishReason) {
5345
5345
  state.finishReason = finishReason;
5346
5346
  out.push(...closeCurrentBlock(state));
@@ -5685,7 +5685,230 @@ function registerAntigravityRoutes(ctx, store, modelSettings, preferences, fetch
5685
5685
  });
5686
5686
  }
5687
5687
  //#endregion
5688
+ //#region src/host/subagent-model-authorization.ts
5689
+ /** DSH settings namespace owned by the Subagent settings card. */
5690
+ const SUBAGENT_MODEL_SELECTION_NAMESPACE = "subagent-model-selection";
5691
+ /** Durable Session event carrying one Session's authorized child routes. */
5692
+ const SUBAGENT_POLICY_EVENT = "subagent/model-selection-policy";
5693
+ /** Delegation tools whose child routes this guard authorizes. */
5694
+ const DEFAULT_DELEGATION_TOOLS = ["subagent"];
5695
+ /**
5696
+ * Read one deployment event field as a string.
5697
+ * @param value - Candidate field value from a durable event.
5698
+ * @returns the string value, or undefined for any other type.
5699
+ */
5700
+ function asString(value) {
5701
+ return typeof value === "string" ? value : void 0;
5702
+ }
5703
+ /**
5704
+ * Read one deployment event field as a plain object.
5705
+ * @param value - Candidate field value from a durable event.
5706
+ * @returns the record value, or undefined for arrays, null, and primitives.
5707
+ */
5708
+ function asRecord(value) {
5709
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
5710
+ }
5711
+ /**
5712
+ * Read one deployment event field as a boolean.
5713
+ * @param value - Candidate field value from a durable event.
5714
+ * @returns the boolean value, or undefined for any other type.
5715
+ */
5716
+ function asBoolean(value) {
5717
+ return typeof value === "boolean" ? value : void 0;
5718
+ }
5719
+ /**
5720
+ * Parse the allowlist out of a durable route-policy event.
5721
+ * @param data - `subagent/model-selection-policy` event payload.
5722
+ * @returns every well-formed route, or undefined when the payload carries none.
5723
+ */
5724
+ function parseAllowedRoutes(data) {
5725
+ const allowed = asRecord(data)?.["allowedModels"];
5726
+ if (!Array.isArray(allowed)) return void 0;
5727
+ const routes = [];
5728
+ for (const entry of allowed) {
5729
+ const record = asRecord(entry);
5730
+ const provider = asString(record?.["provider"]);
5731
+ const model = asString(record?.["model"]);
5732
+ if (provider === void 0 || model === void 0) continue;
5733
+ if (provider.length === 0 || model.length === 0) continue;
5734
+ routes.push({
5735
+ provider,
5736
+ model
5737
+ });
5738
+ }
5739
+ return routes.length === 0 ? void 0 : routes;
5740
+ }
5741
+ /**
5742
+ * Find one Session's recorded allowlist among its durable events.
5743
+ * @param session - Session whose log is scanned.
5744
+ * @returns the authorized routes, or undefined for a Session that recorded none.
5745
+ */
5746
+ function policyRoutesOf(session) {
5747
+ if (session === void 0 || typeof session.eventAt !== "function") return void 0;
5748
+ for (let seq = 0; seq < 256; seq += 1) {
5749
+ let event;
5750
+ try {
5751
+ event = session.eventAt(seq);
5752
+ } catch {
5753
+ return;
5754
+ }
5755
+ if (event === void 0) return void 0;
5756
+ if (event.type !== "subagent/model-selection-policy") continue;
5757
+ const routes = parseAllowedRoutes(event.data);
5758
+ if (routes !== void 0) return routes;
5759
+ }
5760
+ }
5761
+ /**
5762
+ * Resolve the allowlist a delegation from this agent must respect: the agent's
5763
+ * own recorded policy, else the nearest ancestor Session that recorded one
5764
+ * (the inheritance the delegation tool applies to child Sessions).
5765
+ * @param agent - Calling agent.
5766
+ * @param sessions - Session registry used for ancestor lookup.
5767
+ * @returns the authorized routes, or undefined when no Session recorded any.
5768
+ */
5769
+ function authorizedRoutesFor(agent, sessions) {
5770
+ let session = agent?.session;
5771
+ for (let depth = 0; depth < 8 && session !== void 0; depth += 1) {
5772
+ const recorded = policyRoutesOf(session);
5773
+ if (recorded !== void 0) return recorded;
5774
+ const header = session.header;
5775
+ if (header?.origin !== "subagent") return void 0;
5776
+ const parentId = asString(header.parentSession);
5777
+ if (parentId === void 0) return void 0;
5778
+ session = sessions.get(parentId);
5779
+ }
5780
+ }
5781
+ /**
5782
+ * Read the Host preference that owns the allowlist. Values in the stored
5783
+ * document are untrusted JSON, so every field is narrowed before use.
5784
+ * @param settings - Live settings service, when composed.
5785
+ * @returns the resolved preference, or undefined without a settings service.
5786
+ */
5787
+ function subagentModelSelectionPreference(settings) {
5788
+ if (settings === void 0) return void 0;
5789
+ const register = settings["register"];
5790
+ if (typeof register !== "function") return void 0;
5791
+ try {
5792
+ const value = asRecord(register.call(settings, SUBAGENT_MODEL_SELECTION_NAMESPACE, z.object({
5793
+ enabled: z.boolean().default(false),
5794
+ allowedModels: z.array(z.object({
5795
+ provider: z.string().min(1).required(),
5796
+ model: z.string().min(1).required()
5797
+ })).default([])
5798
+ })).get());
5799
+ if (value === void 0) return void 0;
5800
+ return {
5801
+ enabled: asBoolean(value["enabled"]) === true,
5802
+ allowedModels: parseAllowedRoutes(value) ?? []
5803
+ };
5804
+ } catch {
5805
+ return;
5806
+ }
5807
+ }
5808
+ /** Whether an exact route is authorized by a allowlist. */
5809
+ function routesInclude(allowed, provider, model) {
5810
+ return allowed.some((route) => route.provider === provider && route.model === model);
5811
+ }
5812
+ /**
5813
+ * Build the denial reason for a delegation that would run on an unauthorized
5814
+ * route. The reason names the authorized routes so the next call can select one.
5815
+ * @param provider - Effective child provider id, when one is known.
5816
+ * @param model - Effective child model id, when one is known.
5817
+ * @param allowed - Routes the calling Session authorizes.
5818
+ * @param explicit - Whether the model named the route in the tool arguments.
5819
+ * @returns the corrective reason handed back to the model.
5820
+ */
5821
+ function unauthorizedRouteReason(provider, model, allowed, explicit) {
5822
+ const route = provider === void 0 || model === void 0 ? "the inherited route" : `route "${provider}/${model}"`;
5823
+ return `subagent model selection: ${explicit ? "the model this call selected is not on the Session allowlist" : "the route this call would inherit from the parent is not on the Session allowlist"} (${route}). Provide an authorized provider and model — ${allowed.map((entry) => `${entry.provider}/${entry.model}`).join(", ")} — using list_subagent_models to inspect their reasoning efforts.`;
5824
+ }
5825
+ /**
5826
+ * Decide whether one delegation call may start its child.
5827
+ * @param agent - Calling agent.
5828
+ * @param toolName - Tool being dispatched.
5829
+ * @param args - Parsed tool arguments.
5830
+ * @param preference - Current Host preference, when the settings service exists.
5831
+ * @param sessions - Session registry used for ancestor lookup.
5832
+ * @param toolNames - Delegation tool names this guard authorizes.
5833
+ * @param scope - Whether an unrecorded Session falls back to the preference.
5834
+ * @returns a denial reason, or undefined to leave the call untouched.
5835
+ */
5836
+ function delegationDenialReason(agent, toolName, args, preference, sessions, toolNames = DEFAULT_DELEGATION_TOOLS, scope = "session") {
5837
+ if (!toolNames.includes(toolName)) return void 0;
5838
+ if (preference !== void 0 && !preference.enabled) return void 0;
5839
+ const allowed = authorizedRoutesFor(agent, sessions) ?? (scope === "preference" ? preference?.allowedModels ?? [] : []);
5840
+ if (allowed.length === 0) return void 0;
5841
+ const request = asRecord(args) ?? {};
5842
+ const requestedProvider = asString(request["provider"]);
5843
+ const requestedModel = asString(request["model"]);
5844
+ const explicit = requestedProvider !== void 0 || requestedModel !== void 0;
5845
+ const implicit = requestedProvider === void 0 && requestedModel === void 0;
5846
+ const provider = implicit ? asString(agent?.options?.provider) : requestedProvider;
5847
+ const model = implicit ? asString(agent?.options?.model) : requestedModel;
5848
+ if (provider === void 0 || model === void 0) return;
5849
+ if (routesInclude(allowed, provider, model)) return void 0;
5850
+ return unauthorizedRouteReason(provider, model, allowed, explicit);
5851
+ }
5852
+ /**
5853
+ * Build the monotonic tool guard for one deployment. The Host preference is
5854
+ * sampled from the live settings document on every call, because a settings
5855
+ * edit must not rebuild the guard the way it cannot rebuild a Session.
5856
+ * @param options - settings, session registry, and delegation tool names.
5857
+ * @returns a guard that denies delegations outside the Session allowlist.
5858
+ */
5859
+ function createSubagentAuthorization(options) {
5860
+ return (agent, toolName, args) => delegationDenialReason(agent, toolName, args, subagentModelSelectionPreference(options.settings), options.sessions, options.toolNames, options.scope ?? "session");
5861
+ }
5862
+ /** Delegation names this guard recognizes when configuration omits them. */
5863
+ function normalizeDelegationToolNames(value) {
5864
+ const names = Array.isArray(value) ? value.filter((entry) => typeof entry === "string" && entry.trim().length > 0) : [];
5865
+ return [...new Set(names.length === 0 ? [...DEFAULT_DELEGATION_TOOLS] : names.map((name) => name.trim()))];
5866
+ }
5867
+ /**
5868
+ * Validate the plugin configuration that owns this guard.
5869
+ * @param toolNames - Candidate delegation tool names.
5870
+ * @returns the exact names this guard authorizes.
5871
+ */
5872
+ function validateDelegationToolNames(toolNames) {
5873
+ if (toolNames.length === 0) throw new Error("dsh-chatgpt-subscription: subagentModelAuthorization.toolNames must name at least one delegation tool");
5874
+ for (const name of toolNames) if (name.length === 0 || name !== name.trim()) throw new Error(`dsh-chatgpt-subscription: subagentModelAuthorization.toolNames entry "${name}" must be a non-empty trimmed string`);
5875
+ return [...toolNames];
5876
+ }
5877
+ /**
5878
+ * Register the monotonic guard on the Host tool registry.
5879
+ * @param ctx - Host context carrying `tools` (and optionally `settings`).
5880
+ * @param sessions - Session registry used for ancestor lookup.
5881
+ * @param config - Enforcement toggle and delegation tool names.
5882
+ * @returns the exact disposer that unregisters the guard.
5883
+ */
5884
+ function installSubagentModelAuthorization(ctx, sessions, config = {}) {
5885
+ const toolNames = validateDelegationToolNames(config.toolNames ?? [...DEFAULT_DELEGATION_TOOLS]);
5886
+ const scope = validateAuthorizationScope(config.scope ?? "session");
5887
+ const settings = ctx.get?.("settings");
5888
+ const authorize = createSubagentAuthorization({
5889
+ settings,
5890
+ sessions,
5891
+ toolNames,
5892
+ scope
5893
+ });
5894
+ return ctx.tools.guard((exec) => authorize(exec.agent, exec.name, exec.arguments));
5895
+ }
5896
+ /**
5897
+ * Validate the configured authorization scope.
5898
+ * @param scope - Candidate scope from deployment configuration.
5899
+ * @returns the exact scope this guard enforces.
5900
+ */
5901
+ function validateAuthorizationScope(scope) {
5902
+ if (scope === "session" || scope === "preference") return scope;
5903
+ throw new Error(`dsh-chatgpt-subscription: subagentModelScope must be "session" or "preference", received ${JSON.stringify(scope)}`);
5904
+ }
5905
+ //#endregion
5688
5906
  //#region src/index.ts
5907
+ const Config = z.object({
5908
+ subagentModelAuthorization: z.boolean().default(true),
5909
+ subagentModelTools: z.array(z.string()).default([]),
5910
+ subagentModelScope: z.union([z.const("session"), z.const("preference")]).default("session")
5911
+ });
5689
5912
  const inject = [
5690
5913
  "webServer",
5691
5914
  "llm",
@@ -5694,12 +5917,24 @@ const inject = [
5694
5917
  "settings",
5695
5918
  "loader"
5696
5919
  ];
5697
- function apply(ctx) {
5920
+ function apply(ctx, pluginConfig = {}) {
5698
5921
  const store = createPlatformTokenStore();
5699
5922
  const preferences = registerPreferenceStore(ctx.settings);
5700
5923
  const antigravityStore = new FileCredentialStore();
5701
5924
  const antigravityModelSettings = new FileModelSettingsStore();
5702
5925
  const antigravityPreferences = registerAntigravityPreferenceStore(ctx.settings, antigravityModelSettings);
5926
+ const delegationToolNames = normalizeDelegationToolNames(pluginConfig.subagentModelTools);
5927
+ if (pluginConfig.subagentModelAuthorization !== false) ctx.inject(["sessions"], (scoped) => {
5928
+ const sessions = scoped.get("sessions");
5929
+ if (sessions === void 0) return;
5930
+ scoped.effect(() => {
5931
+ if (typeof scoped.tools?.guard !== "function") return () => void 0;
5932
+ return installSubagentModelAuthorization(scoped, sessions, {
5933
+ toolNames: delegationToolNames,
5934
+ scope: pluginConfig.subagentModelScope ?? "session"
5935
+ });
5936
+ }, "dsh-chatgpt-subscription: subagent model authorization");
5937
+ });
5703
5938
  ctx.effect(() => {
5704
5939
  const proxyManager = new ProxyManager({
5705
5940
  getPreferences: () => preferences.status(),
@@ -5753,4 +5988,4 @@ function localWebServerBaseUrl(host, port) {
5753
5988
  return `http://${host === "0.0.0.0" ? "127.0.0.1" : host}:${port}`;
5754
5989
  }
5755
5990
  //#endregion
5756
- export { AntigravityAdapter, CodexChatGptAdapter, FileCredentialStore, FileModelSettingsStore, LinuxFileTokenStore, MacKeychainTokenStore, OAuthService, ProxyManager, ResponsesClient, UsageService, WindowsDpapiTokenStore, apply, beginWebLogin, clearCachedQuota, createCodexFetchProvider, createCodexImageTool, createCodexSearchProvider, createPlatformTokenStore, credentialPath, detectSystemProxy, fetchAccountQuota, getCachedQuota, inject, loginAndSave, mapCodexUsage, modelSettingsPath, parseCodexUsage, parseResponsesStream, refreshAntigravityToken };
5991
+ export { AntigravityAdapter, CodexChatGptAdapter, Config, FileCredentialStore, FileModelSettingsStore, LinuxFileTokenStore, MacKeychainTokenStore, OAuthService, ProxyManager, ResponsesClient, SUBAGENT_MODEL_SELECTION_NAMESPACE, SUBAGENT_POLICY_EVENT, UsageService, WindowsDpapiTokenStore, apply, authorizedRoutesFor, beginWebLogin, clearCachedQuota, createCodexFetchProvider, createCodexImageTool, createCodexSearchProvider, createPlatformTokenStore, createSubagentAuthorization, credentialPath, delegationDenialReason, detectSystemProxy, fetchAccountQuota, getCachedQuota, inject, installSubagentModelAuthorization, loginAndSave, mapCodexUsage, modelSettingsPath, normalizeDelegationToolNames, parseAllowedRoutes, parseCodexUsage, parseResponsesStream, policyRoutesOf, refreshAntigravityToken, subagentModelSelectionPreference, unauthorizedRouteReason, validateAuthorizationScope, validateDelegationToolNames };
@@ -0,0 +1,177 @@
1
+ /**
2
+ * Host-side authorization for the models a subagent may run.
3
+ *
4
+ * The `subagent-model-selection` preference is sampled into each Session as a
5
+ * durable route allowlist, but the built-in delegation tool only rejects an
6
+ * explicit route outside that list: a call that selects no route lets the child
7
+ * inherit the parent's model, so a DeepSeek parent could spawn DeepSeek
8
+ * children even though the allowlist authorizes only other models.
9
+ *
10
+ * This guard closes that gap from the plugin plane. Whenever the calling
11
+ * Session (or the nearest ancestor that recorded one) carries an allowlist,
12
+ * a delegation whose effective child route the list does not authorize is
13
+ * denied before the child starts, with the authorized routes in the reason so
14
+ * the model can retry and pick one of them.
15
+ * @module dsh-chatgpt-subscription/subagent-model-authorization
16
+ */
17
+ import type { Context } from '@deepseek-ai/cordis';
18
+ import type { SettingsProvider } from '@deepseek-ai/dsh-settings';
19
+ /** DSH settings namespace owned by the Subagent settings card. */
20
+ export declare const SUBAGENT_MODEL_SELECTION_NAMESPACE = "subagent-model-selection";
21
+ /** Durable Session event carrying one Session's authorized child routes. */
22
+ export declare const SUBAGENT_POLICY_EVENT = "subagent/model-selection-policy";
23
+ /** Delegation tools whose child routes this guard authorizes. */
24
+ export declare const DEFAULT_DELEGATION_TOOLS: readonly string[];
25
+ /** One exact provider/model route the user authorized for children. */
26
+ export interface AllowedModelRoute {
27
+ readonly provider: string;
28
+ readonly model: string;
29
+ }
30
+ /** Resolved model-selection preference read from the Host settings document. */
31
+ export interface SubagentModelSelectionPreference {
32
+ readonly enabled: boolean;
33
+ readonly allowedModels: readonly AllowedModelRoute[];
34
+ }
35
+ /** One durable Session record this module reads: its events and its lineage. */
36
+ export interface PolicySession {
37
+ eventAt?(seq: number): {
38
+ type?: unknown;
39
+ data?: unknown;
40
+ } | undefined;
41
+ readonly header?: {
42
+ readonly origin?: unknown;
43
+ readonly parentSession?: unknown;
44
+ };
45
+ }
46
+ /** Session lookup the guard walks from the calling agent to its ancestors. */
47
+ export interface SessionsResolver {
48
+ get(id: string): PolicySession | undefined;
49
+ }
50
+ /** Calling agent fields the guard reads. */
51
+ export interface AuthorizationAgent {
52
+ readonly session?: PolicySession;
53
+ readonly options?: {
54
+ readonly provider?: unknown;
55
+ readonly model?: unknown;
56
+ };
57
+ }
58
+ /** What the delegation tool received from the model. */
59
+ export interface DelegationArguments {
60
+ readonly provider?: unknown;
61
+ readonly model?: unknown;
62
+ }
63
+ /**
64
+ * Parse the allowlist out of a durable route-policy event.
65
+ * @param data - `subagent/model-selection-policy` event payload.
66
+ * @returns every well-formed route, or undefined when the payload carries none.
67
+ */
68
+ export declare function parseAllowedRoutes(data: unknown): AllowedModelRoute[] | undefined;
69
+ /**
70
+ * Find one Session's recorded allowlist among its durable events.
71
+ * @param session - Session whose log is scanned.
72
+ * @returns the authorized routes, or undefined for a Session that recorded none.
73
+ */
74
+ export declare function policyRoutesOf(session: PolicySession | undefined): AllowedModelRoute[] | undefined;
75
+ /**
76
+ * Resolve the allowlist a delegation from this agent must respect: the agent's
77
+ * own recorded policy, else the nearest ancestor Session that recorded one
78
+ * (the inheritance the delegation tool applies to child Sessions).
79
+ * @param agent - Calling agent.
80
+ * @param sessions - Session registry used for ancestor lookup.
81
+ * @returns the authorized routes, or undefined when no Session recorded any.
82
+ */
83
+ export declare function authorizedRoutesFor(agent: AuthorizationAgent | undefined, sessions: SessionsResolver): AllowedModelRoute[] | undefined;
84
+ /**
85
+ * Read the Host preference that owns the allowlist. Values in the stored
86
+ * document are untrusted JSON, so every field is narrowed before use.
87
+ * @param settings - Live settings service, when composed.
88
+ * @returns the resolved preference, or undefined without a settings service.
89
+ */
90
+ export declare function subagentModelSelectionPreference(settings: SettingsProvider | undefined): SubagentModelSelectionPreference | undefined;
91
+ /**
92
+ * Build the denial reason for a delegation that would run on an unauthorized
93
+ * route. The reason names the authorized routes so the next call can select one.
94
+ * @param provider - Effective child provider id, when one is known.
95
+ * @param model - Effective child model id, when one is known.
96
+ * @param allowed - Routes the calling Session authorizes.
97
+ * @param explicit - Whether the model named the route in the tool arguments.
98
+ * @returns the corrective reason handed back to the model.
99
+ */
100
+ export declare function unauthorizedRouteReason(provider: string | undefined, model: string | undefined, allowed: readonly AllowedModelRoute[], explicit: boolean): string;
101
+ /** Which Session's recorded allowlist a delegation must respect. */
102
+ export type AuthorizationScope =
103
+ /**
104
+ * `session` (default): a Session that recorded an allowlist governs itself
105
+ * and its descendants, matching the delegation tool's durable snapshot; a
106
+ * Session that recorded none keeps the built-in behavior.
107
+ */
108
+ 'session'
109
+ /**
110
+ * `preference`: the current Host preference also governs Sessions that never
111
+ * recorded an allowlist, so the Settings card applies without restarting the
112
+ * Session. A Session that recorded its own routes still outranks it.
113
+ */
114
+ | 'preference';
115
+ /**
116
+ * Decide whether one delegation call may start its child.
117
+ * @param agent - Calling agent.
118
+ * @param toolName - Tool being dispatched.
119
+ * @param args - Parsed tool arguments.
120
+ * @param preference - Current Host preference, when the settings service exists.
121
+ * @param sessions - Session registry used for ancestor lookup.
122
+ * @param toolNames - Delegation tool names this guard authorizes.
123
+ * @param scope - Whether an unrecorded Session falls back to the preference.
124
+ * @returns a denial reason, or undefined to leave the call untouched.
125
+ */
126
+ export declare function delegationDenialReason(agent: AuthorizationAgent | undefined, toolName: string, args: unknown, preference: SubagentModelSelectionPreference | undefined, sessions: SessionsResolver, toolNames?: readonly string[], scope?: AuthorizationScope): string | undefined;
127
+ /** Runtime inputs the guard closes over. */
128
+ export interface SubagentAuthorizationOptions {
129
+ /** Live settings service, when composed; absent leaves recorded policies in charge. */
130
+ readonly settings?: SettingsProvider;
131
+ /** Session registry used for ancestor lookup. */
132
+ readonly sessions: SessionsResolver;
133
+ /** Exact delegation tool names this guard authorizes. */
134
+ readonly toolNames: readonly string[];
135
+ /** Whether an unrecorded Session falls back to the current preference. */
136
+ readonly scope?: AuthorizationScope;
137
+ }
138
+ /** The exact guard signature the Host tool registry evaluates. */
139
+ export type DelegationGuard = (agent: AuthorizationAgent | undefined, toolName: string, args: unknown) => string | undefined;
140
+ /**
141
+ * Build the monotonic tool guard for one deployment. The Host preference is
142
+ * sampled from the live settings document on every call, because a settings
143
+ * edit must not rebuild the guard the way it cannot rebuild a Session.
144
+ * @param options - settings, session registry, and delegation tool names.
145
+ * @returns a guard that denies delegations outside the Session allowlist.
146
+ */
147
+ export declare function createSubagentAuthorization(options: SubagentAuthorizationOptions): DelegationGuard;
148
+ /** Delegation names this guard recognizes when configuration omits them. */
149
+ export declare function normalizeDelegationToolNames(value: unknown): string[];
150
+ /**
151
+ * Validate the plugin configuration that owns this guard.
152
+ * @param toolNames - Candidate delegation tool names.
153
+ * @returns the exact names this guard authorizes.
154
+ */
155
+ export declare function validateDelegationToolNames(toolNames: readonly string[]): string[];
156
+ /** Configuration accepted by {@link installSubagentModelAuthorization}. */
157
+ export interface SubagentModelAuthorizationConfig {
158
+ /** Delegation tool names the guard authorizes. */
159
+ readonly toolNames?: readonly string[];
160
+ /** Whether an unrecorded Session falls back to the current preference. */
161
+ readonly scope?: AuthorizationScope;
162
+ }
163
+ /**
164
+ * Register the monotonic guard on the Host tool registry.
165
+ * @param ctx - Host context carrying `tools` (and optionally `settings`).
166
+ * @param sessions - Session registry used for ancestor lookup.
167
+ * @param config - Enforcement toggle and delegation tool names.
168
+ * @returns the exact disposer that unregisters the guard.
169
+ */
170
+ export declare function installSubagentModelAuthorization(ctx: Context, sessions: SessionsResolver, config?: SubagentModelAuthorizationConfig): () => void;
171
+ /**
172
+ * Validate the configured authorization scope.
173
+ * @param scope - Candidate scope from deployment configuration.
174
+ * @returns the exact scope this guard enforces.
175
+ */
176
+ export declare function validateAuthorizationScope(scope: unknown): AuthorizationScope;
177
+ //# sourceMappingURL=subagent-model-authorization.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subagent-model-authorization.d.ts","sourceRoot":"","sources":["../../../src/host/subagent-model-authorization.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,27 @@
1
1
  import type { Context } from '@deepseek-ai/cordis';
2
+ import z from '@deepseek-ai/schemastery';
3
+ /** Optional deployment configuration for this plugin. */
4
+ export interface Config {
5
+ /**
6
+ * Whether the Subagent model allowlist also governs the route a delegation
7
+ * that selects no model would inherit from its parent. Default `true`; set
8
+ * `false` to leave inherited routes to the built-in delegation tool.
9
+ */
10
+ subagentModelAuthorization?: boolean;
11
+ /** Delegation tool names the authorization guard recognizes (default `subagent`). */
12
+ subagentModelTools?: string[];
13
+ /**
14
+ * `session` (default) enforces the allowlist a Session recorded, matching the
15
+ * delegation tool's snapshot; `preference` also enforces the current Settings
16
+ * card allowlist for Sessions that recorded none.
17
+ */
18
+ subagentModelScope?: 'session' | 'preference';
19
+ }
20
+ export declare const Config: z<Config>;
2
21
  export declare const inject: string[];
3
- export declare function apply(ctx: Context): void;
22
+ export declare function apply(ctx: Context, pluginConfig?: Config): void;
4
23
  export { ProxyManager, detectSystemProxy } from './host/proxy-manager.ts';
24
+ export { SUBAGENT_MODEL_SELECTION_NAMESPACE, SUBAGENT_POLICY_EVENT, authorizedRoutesFor, createSubagentAuthorization, delegationDenialReason, installSubagentModelAuthorization, normalizeDelegationToolNames, parseAllowedRoutes, policyRoutesOf, subagentModelSelectionPreference, unauthorizedRouteReason, validateAuthorizationScope, validateDelegationToolNames, } from './host/subagent-model-authorization.ts';
5
25
  export { OAuthService } from './host/oauth-service.ts';
6
26
  export { CodexChatGptAdapter } from './host/adapter.ts';
7
27
  export { createCodexImageTool } from './host/codex-images.ts';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AA+BlD,eAAO,MAAM,MAAM,UAAqE,CAAA;AAExF,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAuExC;AAED,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAA;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AAChE,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAClF,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACtF,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAA;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAA;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AACtE,YAAY,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAE/E,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAA;AAClE,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,cAAc,EACd,iBAAiB,GAClB,MAAM,mCAAmC,CAAA;AAC1C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAA;AAClG,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,CAAC,MAAM,0BAA0B,CAAA;AAqCxC,yDAAyD;AACzD,MAAM,WAAW,MAAM;IACrB;;;;OAIG;IACH,0BAA0B,CAAC,EAAE,OAAO,CAAA;IACpC,qFAAqF;IACrF,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC7B;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,SAAS,GAAG,YAAY,CAAA;CAC9C;AAED,eAAO,MAAM,MAAM,EAAE,CAAC,CAAC,MAAM,CAI3B,CAAA;AAEF,eAAO,MAAM,MAAM,UAAqE,CAAA;AAExF,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,YAAY,GAAE,MAAW,GAAG,IAAI,CA0FnE;AAED,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AACzE,OAAO,EACL,kCAAkC,EAClC,qBAAqB,EACrB,mBAAmB,EACnB,2BAA2B,EAC3B,sBAAsB,EACtB,iCAAiC,EACjC,4BAA4B,EAC5B,kBAAkB,EAClB,cAAc,EACd,gCAAgC,EAChC,uBAAuB,EACvB,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAA;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AAChE,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAClF,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACtF,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAA;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAA;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AACtE,YAAY,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAE/E,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAA;AAClE,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,cAAc,EACd,iBAAiB,GAClB,MAAM,mCAAmC,CAAA;AAC1C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAA;AAClG,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eddyskywalker/dsh-chatgpt-subscription",
3
- "version": "0.2.15",
3
+ "version": "0.2.16",
4
4
  "description": "DSH provider plugin for Codex access through a ChatGPT subscription.",
5
5
  "author": {
6
6
  "name": "eddyskywalker",