Skip to content

feat(guardrails): item 14 子代理 token 预算上限 FUSION_MAX_SUBAGENT_BUDGET_TOKENS (P2.1 维度 4) - #99

Merged
dahai80 merged 1 commit into
mainfrom
feat/subagent-budget-cap-item14
Aug 20, 2026
Merged

feat(guardrails): item 14 子代理 token 预算上限 FUSION_MAX_SUBAGENT_BUDGET_TOKENS (P2.1 维度 4)#99
dahai80 merged 1 commit into
mainfrom
feat/subagent-budget-cap-item14

Conversation

@dahai80

@dahai80 dahai80 commented Aug 20, 2026

Copy link
Copy Markdown
Owner

背景

Closes #98. P2.1 子代理护栏第 4 维度 (会话级 token 预算上限)。

enhance-0819.md §201 item 14: CC --max-budget-usd 停后台子代理 → fusion-code 本地无 USD, 转 token 预算上限。维度 1/2/3 (并发/会话/深度) 已落地 PR #82, 维度 4 当时 deferred — 跨 PR 依赖 (PR #82 未合 main)。现 PR #82 已合 v0.4.23, guardrail infra 就位。

动机

fusion-code 子代理无 token 预算刹车。失控子代理 (无限循环 spawn / 大量 tool call) 可耗尽本地 MLX 上下文。预算上限 = 失控刹车, 防单一会话子代理耗光 token。默认 off (fail-open), 仅用户显式设 FUSION_MAX_SUBAGENT_BUDGET_TOKENS 时生效。零默认行为变更。

改动 (surgical, 跟 PR #82 同模式)

文件 改动
AppStateStore.ts +subagentBudgetUsedTokens: number (init 0), 并行 subagentSpawnCount
clear/conversation.ts /clear reset 0
main.tsx initialState reset 0
subagentGuardrails.ts +DEFAULT_MAX_SUBAGENT_BUDGET_TOKENS=0 + getMaxSubagentBudgetTokens() + parseBudgetCap() (0=合法 off 值); checkSubagentGuardrails 加第 4 维度 (默认 off, 末尾)
AgentTool.tsx gate input +budgetUsedTokens; 2 个 finalizeAgentTool site 累加 (backgrounded + sync)
agentToolUtils.ts 第 3 个 finalize site 累加 (async path)
tests/.../subagentGuardrails.test.ts +9 budget case

设计决策

  • 默认 off (0=off): token 预算需用户按本地 MLX 窗口定, 无合理默认。区别于并发/会话/深度 (有非零默认)
  • 近似计数: finalizeAgentTool.totalTokens = 最后 turn usage (input+cache+output), 非全程累加。失控刹车非精确计费, 低估偏安全方向 (刹车略晚触发), default off 用户自选。精确全程累加需改 ProgressTracker 透传, M-size 超 surgical
  • 3 增量点 vs 单点: 无统一 seam (sync path 不经 completeAsyncAgent)。各 1 行同模式, 注释标 keep-in-sync
  • fail-open: env 非数/空/负 → off (不静默阻所有 spawn)。0 是合法 off 值

验证

  • bun run typecheck: 0 errors
  • bun test tests/utils/subagentGuardrails.test.ts: 24 pass (15 + 9 budget)
  • bun test src/__tests__/: 167 pass, 0 fail (无回归)
  • bun run build + bun run build:dev:full: pass
  • lint: 改动文件 0 errors (9 pre-existing warnings 非本次)
  • git diff -w: 纯插入, 零 churn, 风格对齐 (tab/double-quote/semi)

风险

  • 近似计数低估: 多轮子代理末轮 usage 仍累积, 失控场景刹车最终触发。可接受
  • 3 增量点遗漏: 当前覆盖所有 finalizeAgentTool path (Explore 确认); 注释标同步, 未来新 spawn path 需补
  • 默认 off = 多数用户无感: 价值 = 用户设刹车 (先前不可)。对齐 CC --max-budget-usd (亦默认 off)

关联

…OKENS (P2.1 维度 4)

P2.1 子代理护栏第 4 维度: 会话级 token 预算上限。CC `--max-budget-usd`
停后台子代理 → 本地无 USD, 转 token 预算。依赖 PR #82 (guardrail infra,
已合 v0.4.23), 现 main 就位。

默认 off (0=off, fail-open), 仅用户显式设
FUSION_MAX_SUBAGENT_BUDGET_TOKENS 时生效 — 失控刹车防单一会话子代理
耗光本地 MLX 上下文。零默认行为变更 (对齐 PR #82/#94 env-gated opt-in 模式)。

- AppState.subagentBudgetUsedTokens (init 0, reset /clear), 并行
  subagentSpawnCount
- subagentGuardrails.ts: DEFAULT_MAX_SUBAGENT_BUDGET_TOKENS=0 +
  getMaxSubagentBudgetTokens() + parseBudgetCap() (0=合法 off 值非错误,
  区别于 parseCap); checkSubagentGuardrails 加第 4 维度 (默认 off 放末尾)
- AgentTool.tsx: gate input 加 budgetUsedTokens; 3 个 finalizeAgentTool
  返回后各加 1 行 rootSetAppState 累加 agentResult.totalTokens
- agentToolUtils.ts: 第 3 个 finalize site 累加 (async path)
- tests/utils/subagentGuardrails.test.ts: +9 budget case (off/on/reject/
  exceed/omit/order/parse-decimal), 24 pass

近似计数: totalTokens = 最后 turn usage (非全程累加), 失控刹车非精确计费,
低估偏安全方向。3 增量点无统一 seam, 注释标 keep-in-sync。

验证: typecheck 0 / 单测 24+167 pass / build + build:dev:full pass /
diff 纯插入零 churn / 风格对齐。

Closes #98

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@dahai80
dahai80 merged commit 652cd30 into main Aug 20, 2026
1 check passed
@dahai80
dahai80 deleted the feat/subagent-budget-cap-item14 branch August 20, 2026 13:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(guardrails): item 14 子代理 token 预算上限 (P2.1 维度 4)

1 participant