@bolloon/bolloon-agent 0.1.34 → 0.1.36

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.
Files changed (226) hide show
  1. package/.auto-evolve-calls +1 -0
  2. package/.last-auto-evolve-baseline +1 -0
  3. package/.playwright-mcp/page-2026-06-16T07-51-45-706Z.yml +130 -0
  4. package/.playwright-mcp/page-2026-06-16T07-56-44-116Z.yml +131 -0
  5. package/Bolloon.md +144 -0
  6. package/Dive-into/CITATION.cff +17 -0
  7. package/Dive-into/LICENSE +25 -0
  8. package/Dive-into/README.md +598 -0
  9. package/Dive-into/README_zh.md +599 -0
  10. package/Dive-into/assets/context.png +0 -0
  11. package/Dive-into/assets/extensibility.png +0 -0
  12. package/Dive-into/assets/iteration.png +0 -0
  13. package/Dive-into/assets/layered_architecture.png +0 -0
  14. package/Dive-into/assets/main_structure.png +0 -0
  15. package/Dive-into/assets/permission.png +0 -0
  16. package/Dive-into/assets/session_compact.png +0 -0
  17. package/Dive-into/assets/subagent.png +0 -0
  18. package/Dive-into/paper/Dive_into_Claude_Code.pdf +0 -0
  19. package/README.md +1 -1
  20. package/dist/agents/p2p-chat-tools.js +6 -6
  21. package/dist/agents/permission-mode.js +115 -0
  22. package/dist/agents/pi-sdk.js +687 -25
  23. package/dist/agents/pre-tool-validator.js +194 -0
  24. package/dist/agents/workflow-pivot-loop.js +113 -12
  25. package/dist/bollharness/src/scripts/checks/check_doc_freshness.js +1 -1
  26. package/dist/bollharness/src/scripts/checks/check_doc_links.js +1 -1
  27. package/dist/bollharness/src/scripts/context_router.js +1 -1
  28. package/dist/bollharness/src/scripts/deploy-guard.js +1 -1
  29. package/dist/bollharness/src/scripts/guard_router.js +1 -1
  30. package/dist/bollharness/src/scripts/hooks/_hook_output.js +1 -1
  31. package/dist/bollharness/src/scripts/hooks/risk-tracker.js +1 -1
  32. package/dist/bollharness-integration/context-router.js +2 -2
  33. package/dist/bollharness-integration/guard-checker.js +1 -1
  34. package/dist/bootstrap/bootstrap.js +117 -0
  35. package/dist/bootstrap/context-collector.js +312 -0
  36. package/dist/bootstrap/context-hierarchy.js +218 -0
  37. package/dist/bootstrap/lifecycle-hooks.js +171 -0
  38. package/dist/bootstrap/project-context.js +158 -0
  39. package/dist/context-compaction/auto-compact.js +144 -0
  40. package/dist/context-compaction/budget-gate.js +28 -0
  41. package/dist/context-compaction/budget-reduce.js +35 -0
  42. package/dist/context-compaction/context-collapse.js +66 -0
  43. package/dist/context-compaction/index.js +21 -0
  44. package/dist/context-compaction/microcompact.js +51 -0
  45. package/dist/context-compaction/pipeline.js +123 -0
  46. package/dist/context-compaction/snip.js +45 -0
  47. package/dist/context-compaction/token-estimator.js +35 -0
  48. package/dist/context-compaction/types.js +19 -0
  49. package/dist/heartbeat/HealthMonitor.js +3 -2
  50. package/dist/index.js +49 -2
  51. package/dist/llm/llm-judgment-client.js +32 -30
  52. package/dist/llm/pi-ai.js +125 -28
  53. package/dist/llm/system-prompt/health.js +129 -0
  54. package/dist/llm/system-prompt/registry.js +246 -0
  55. package/dist/llm/system-prompt/strip-hibsml.js +51 -0
  56. package/dist/llm/tool-manifest/ask_user_input.js +35 -0
  57. package/dist/llm/tool-manifest/bash.js +23 -0
  58. package/dist/llm/tool-manifest/create_file.js +24 -0
  59. package/dist/llm/tool-manifest/fetch_sports_data.js +26 -0
  60. package/dist/llm/tool-manifest/image_search.js +24 -0
  61. package/dist/llm/tool-manifest/index.js +69 -0
  62. package/dist/llm/tool-manifest/mcp.js +43 -0
  63. package/dist/llm/tool-manifest/message_compose.js +31 -0
  64. package/dist/llm/tool-manifest/places.js +83 -0
  65. package/dist/llm/tool-manifest/present_files.js +21 -0
  66. package/dist/llm/tool-manifest/recipe.js +40 -0
  67. package/dist/llm/tool-manifest/recommend_apps.js +23 -0
  68. package/dist/llm/tool-manifest/str_replace.js +27 -0
  69. package/dist/llm/tool-manifest/types.js +7 -0
  70. package/dist/llm/tool-manifest/view.js +24 -0
  71. package/dist/llm/tool-manifest/weather.js +27 -0
  72. package/dist/llm/tool-manifest/web.js +51 -0
  73. package/dist/network/p2p-direct.js +23 -0
  74. package/dist/network/source-intent-broadcaster.js +203 -0
  75. package/dist/network/source-intent.js +100 -0
  76. package/dist/pi-ecosystem-judgment/adaptive-scan.js +279 -0
  77. package/dist/pi-ecosystem-judgment/causal-judge.js +449 -0
  78. package/dist/pi-ecosystem-judgment/detect-hook.js +168 -0
  79. package/dist/pi-ecosystem-judgment/distill-prompt.js +226 -0
  80. package/dist/pi-ecosystem-judgment/evolve-judgment.js +170 -0
  81. package/dist/pi-ecosystem-judgment/human-value-pipeline.js +21 -0
  82. package/dist/pi-ecosystem-judgment/human-value-store.js +283 -22
  83. package/dist/pi-ecosystem-judgment/injection-gate.js +208 -0
  84. package/dist/pi-ecosystem-judgment/monitor-gate.js +188 -0
  85. package/dist/pi-ecosystem-judgment/value-injection.js +8 -2
  86. package/dist/security/builtin-guards.js +124 -0
  87. package/dist/security/context-router-tool.js +106 -0
  88. package/dist/security/input-scanner.js +223 -0
  89. package/dist/security/react-harness.js +143 -0
  90. package/dist/security/tool-gate.js +235 -0
  91. package/dist/utils/auto-evolve-policy.js +117 -0
  92. package/dist/utils/clamp.js +7 -0
  93. package/dist/utils/double.js +6 -0
  94. package/dist/web/client.js +3810 -3830
  95. package/dist/web/components/p2p/P2PModal.js +188 -0
  96. package/dist/web/components/p2p/index.js +264 -226
  97. package/dist/web/components/p2p/p2p-modal.js +657 -0
  98. package/dist/web/components/p2p/p2p-tools.js +248 -0
  99. package/dist/web/index.html +60 -49
  100. package/dist/web/server.js +827 -124
  101. package/dist/web/style.css +531 -249
  102. package/dist/web/ui/message-renderer.js +463 -0
  103. package/dist/web/ui/step-timeline.js +375 -0
  104. package/lefthook.yml +33 -0
  105. package/package.json +3 -2
  106. package/scripts/auto-evolve-loop.ts +481 -0
  107. package/scripts/auto-evolve-oneshot.sh +155 -0
  108. package/scripts/auto-evolve-snapshot.sh +136 -0
  109. package/scripts/build-web.ts +35 -1
  110. package/scripts/detect-schema-changes.sh +48 -0
  111. package/scripts/diff-reviewer.ts +159 -0
  112. package/scripts/validate-system-prompt.ts +142 -0
  113. package/scripts/weekly-report.ts +364 -0
  114. package/src/agents/p2p-chat-tools.ts +6 -6
  115. package/src/agents/permission-mode.ts +127 -0
  116. package/src/agents/pi-sdk.ts +741 -30
  117. package/src/agents/pre-tool-validator.ts +213 -0
  118. package/src/agents/workflow-pivot-loop.ts +110 -19
  119. package/src/bollharness/CLAUDE.md +1 -1
  120. package/src/bollharness/README.md +2 -2
  121. package/src/bollharness/README.zh-CN.md +2 -2
  122. package/src/bollharness/reference/boll-reference/scripts/hooks/find-boll-root.sh +2 -2
  123. package/src/bollharness/scripts/context-fragments/truth-source-hierarchy.md +2 -2
  124. package/src/bollharness/scripts/context-fragments/version-sources.md +1 -1
  125. package/src/bollharness/scripts/hooks/find-project-root.sh +4 -4
  126. package/src/bollharness/src/scripts/checks/check_doc_freshness.ts +1 -1
  127. package/src/bollharness/src/scripts/checks/check_doc_links.ts +1 -1
  128. package/src/bollharness/src/scripts/context_router.ts +1 -1
  129. package/src/bollharness/src/scripts/deploy-guard.ts +1 -1
  130. package/src/bollharness/src/scripts/guard_router.ts +1 -1
  131. package/src/bollharness/src/scripts/hooks/_hook_output.ts +1 -1
  132. package/src/bollharness/src/scripts/hooks/risk-tracker.ts +1 -1
  133. package/src/bollharness/templates/scaffold/.gitignore.append +1 -1
  134. package/src/bollharness/templates/scaffold/CLAUDE.md +2 -2
  135. package/src/bollharness-integration/context-router.ts +2 -2
  136. package/src/bollharness-integration/guard-checker.ts +1 -1
  137. package/src/bootstrap/bootstrap.ts +135 -0
  138. package/src/bootstrap/context-collector.ts +371 -0
  139. package/src/bootstrap/context-hierarchy.ts +283 -0
  140. package/src/bootstrap/lifecycle-hooks.ts +289 -0
  141. package/src/bootstrap/project-context.ts +171 -0
  142. package/src/context-compaction/auto-compact.ts +153 -0
  143. package/src/context-compaction/budget-gate.ts +32 -0
  144. package/src/context-compaction/budget-reduce.ts +37 -0
  145. package/src/context-compaction/context-collapse.ts +72 -0
  146. package/src/context-compaction/index.ts +24 -0
  147. package/src/context-compaction/microcompact.ts +54 -0
  148. package/src/context-compaction/pipeline.ts +133 -0
  149. package/src/context-compaction/snip.ts +51 -0
  150. package/src/context-compaction/token-estimator.ts +36 -0
  151. package/src/context-compaction/types.ts +99 -0
  152. package/src/heartbeat/HealthMonitor.ts +3 -2
  153. package/src/index.ts +47 -2
  154. package/src/llm/llm-judgment-client.ts +36 -35
  155. package/src/llm/pi-ai.ts +135 -29
  156. package/src/llm/system-prompt/health.ts +159 -0
  157. package/src/llm/system-prompt/layers/channel/local.md +14 -0
  158. package/src/llm/system-prompt/layers/channel/p2p-agent.md +18 -0
  159. package/src/llm/system-prompt/layers/channel/p2p-visitor.md +19 -0
  160. package/src/llm/system-prompt/layers/core/artifacts_storage.md +89 -0
  161. package/src/llm/system-prompt/layers/core/evenhandedness.md +21 -0
  162. package/src/llm/system-prompt/layers/core/hibs_reminders.md +15 -0
  163. package/src/llm/system-prompt/layers/core/identity.md +37 -0
  164. package/src/llm/system-prompt/layers/core/knowledge.md +17 -0
  165. package/src/llm/system-prompt/layers/core/memory_system.md +12 -0
  166. package/src/llm/system-prompt/layers/core/network_filesystem.md +28 -0
  167. package/src/llm/system-prompt/layers/core/refusal.md +37 -0
  168. package/src/llm/system-prompt/layers/core/tone.md +31 -0
  169. package/src/llm/system-prompt/layers/core/tools.thin.md +13 -0
  170. package/src/llm/system-prompt/layers/core/wellbeing.md +41 -0
  171. package/src/llm/system-prompt/layers/role/architect.md +20 -0
  172. package/src/llm/system-prompt/layers/role/expert.md +19 -0
  173. package/src/llm/system-prompt/layers/role/implementer.md +15 -0
  174. package/src/llm/system-prompt/layers/role/security.md +15 -0
  175. package/src/llm/system-prompt/layers/tool/artifacts.md +72 -0
  176. package/src/llm/system-prompt/layers/tool/bash.md +25 -0
  177. package/src/llm/system-prompt/layers/tool/hibs_api.md +171 -0
  178. package/src/llm/system-prompt/layers/tool/image_search.md +70 -0
  179. package/src/llm/system-prompt/layers/tool/manifest.md +89 -0
  180. package/src/llm/system-prompt/layers/tool/mcp_apps.md +53 -0
  181. package/src/llm/system-prompt/layers/tool/web_search.md +83 -0
  182. package/src/llm/system-prompt/registry.ts +325 -0
  183. package/src/llm/system-prompt/strip-hibsml.ts +52 -0
  184. package/src/llm/tool-manifest/ask_user_input.ts +37 -0
  185. package/src/llm/tool-manifest/bash.ts +25 -0
  186. package/src/llm/tool-manifest/create_file.ts +26 -0
  187. package/src/llm/tool-manifest/fetch_sports_data.ts +28 -0
  188. package/src/llm/tool-manifest/image_search.ts +26 -0
  189. package/src/llm/tool-manifest/index.ts +88 -0
  190. package/src/llm/tool-manifest/mcp.ts +46 -0
  191. package/src/llm/tool-manifest/message_compose.ts +33 -0
  192. package/src/llm/tool-manifest/places.ts +86 -0
  193. package/src/llm/tool-manifest/present_files.ts +23 -0
  194. package/src/llm/tool-manifest/recipe.ts +42 -0
  195. package/src/llm/tool-manifest/recommend_apps.ts +25 -0
  196. package/src/llm/tool-manifest/str_replace.ts +29 -0
  197. package/src/llm/tool-manifest/types.ts +52 -0
  198. package/src/llm/tool-manifest/view.ts +26 -0
  199. package/src/llm/tool-manifest/weather.ts +29 -0
  200. package/src/llm/tool-manifest/web.ts +54 -0
  201. package/src/network/p2p-direct.ts +22 -0
  202. package/src/network/source-intent-broadcaster.ts +242 -0
  203. package/src/network/source-intent.ts +167 -0
  204. package/src/security/builtin-guards.ts +162 -0
  205. package/src/security/context-router-tool.ts +122 -0
  206. package/src/security/input-scanner.ts +287 -0
  207. package/src/security/react-harness.ts +177 -0
  208. package/src/security/tool-gate.ts +294 -0
  209. package/src/utils/auto-evolve-policy.ts +138 -0
  210. package/src/utils/clamp.ts +5 -0
  211. package/src/web/client.js +105 -2187
  212. package/src/web/client.ts +4326 -0
  213. package/src/web/index.html +60 -49
  214. package/src/web/server.ts +894 -148
  215. package/src/web/style.css +531 -249
  216. package/src/web/ui/message-renderer.ts +540 -0
  217. package/src/web/ui/step-timeline.ts +394 -0
  218. package/staging/auto-evolve/clean-001/.review-verdict +9 -0
  219. package/staging/auto-evolve/clean-001/clean-001.patch +14 -0
  220. package/staging/auto-evolve/e2e-001/.patch-id +1 -0
  221. package/staging/auto-evolve/e2e-001/.review-verdict +12 -0
  222. package/staging/auto-evolve/e2e-001/e2e-001.patch +11 -0
  223. package/staging/auto-evolve/test-bad/.review-verdict +12 -0
  224. package/staging/auto-evolve/test-bad/test-bad.patch +11 -0
  225. package/test-results/.last-run.json +6 -0
  226. package/test-results/src-test-web-loop-status-b-5734c-atus-bar-/346/230/276/347/244/272-spinner-/344/270/215/346/230/276/347/244/272/345/276/252/347/216/257/350/256/241/346/225/260/error-context.md +285 -0
Binary file
Binary file
Binary file
Binary file
package/README.md CHANGED
@@ -274,7 +274,7 @@ Gate 8: Test & Integration (测试集成) → 完成
274
274
  | src/network/ | truth-source-hierarchy, protocol-consumers |
275
275
  | src/constraints/ | truth-source-hierarchy, fixed-three-layers |
276
276
  | docs/ | truth-source-hierarchy, two-language |
277
- | CLAUDE.md | truth-source-hierarchy, bridge-constitution |
277
+ | Bolloon.md | truth-source-hierarchy, bridge-constitution |
278
278
 
279
279
  #### 4.2.5 Session Archive (操作历史归档)
280
280
 
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * p2p-chat-tools — 异步 chat 通道 + 持久化 inbox + 判断力外包 (draft)
3
3
  *
4
- * 解决痛点: 两个节点的智能体代替各自人类主人做异步判断
4
+ * 解决痛点: 两个节点的智能体代替各自人类用户做异步判断
5
5
  *
6
6
  * 流程:
7
7
  * 1. A 节点 (人类在线) 通过 sendChat(peerDID, text) 发消息 → iroh 'agent_chat'
@@ -9,7 +9,7 @@
9
9
  * - onMessage('agent_chat') → 落 ~/.bolloon/inbox/<peerDID>.jsonl
10
10
  * - 状态 = 'received' (未处理)
11
11
  * 3. B 节点 wake-up (processPendingInbox) → 扫描 status='received' 的消息
12
- * - 调 LLM 生成 draft (注入主人历史判断 + ValueProfile)
12
+ * - 调 LLM 生成 draft (注入用户历史判断 + ValueProfile)
13
13
  * - 写 status='drafted', draft 落盘
14
14
  * - 通过 'agent_chat' 消息类型回送 draft (前缀 [DRAFT] 表明是代回)
15
15
  * 4. A 节点收到 draft → 写到 A 的 outbox (inbox 中 from=B 的那条)
@@ -203,7 +203,7 @@ async function buildValueHint(text) {
203
203
  .slice(-10)
204
204
  .flatMap((j) => j.reasons || [])
205
205
  .slice(0, 20);
206
- return `\n[主人历史判断 (style 参考, 不可外泄)]\n关注维度: ${profileHint}\n关键理由示例: ${reasons.join(' | ').slice(0, 400) || '(无)'}\n`;
206
+ return `\n[用户历史判断 (style 参考, 不可外泄)]\n关注维度: ${profileHint}\n关键理由示例: ${reasons.join(' | ').slice(0, 400) || '(无)'}\n`;
207
207
  }
208
208
  catch (e) {
209
209
  return '';
@@ -217,7 +217,7 @@ export async function generateDraft(messageId, peerDID, transport = defaultIrohT
217
217
  if (entry.status !== 'received')
218
218
  return entry;
219
219
  const valueHint = await buildValueHint(entry.text);
220
- const promptForDraft = `你是主人的代理. 对方发来这条消息: "${entry.text.slice(0, 1500)}"\n${valueHint}\n请基于主人的历史判断, 用 1-2 句话代主人拟一个回复草案. 草案要保留主人的语气和立场, 开头标注 [DRAFT]. 直接给草案文本, 不要解释.`;
220
+ const promptForDraft = `你是用户的代理. 对方发来这条消息: "${entry.text.slice(0, 1500)}"\n${valueHint}\n请基于用户的历史判断, 用 1-2 句话代用户拟一个回复草案. 草案要保留用户的语气和立场, 开头标注 [DRAFT]. 直接给草案文本, 不要解释.`;
221
221
  let draftText = '';
222
222
  let confidence = 0.5;
223
223
  try {
@@ -232,7 +232,7 @@ export async function generateDraft(messageId, peerDID, transport = defaultIrohT
232
232
  body: JSON.stringify({
233
233
  model: openaiModel,
234
234
  messages: [
235
- { role: 'system', content: '你是主人的代理. 你的输出会被主人审阅后才发出. 请谨慎.' },
235
+ { role: 'system', content: '你是用户的代理. 你的输出会被用户审阅后才发出. 请谨慎.' },
236
236
  { role: 'user', content: promptForDraft },
237
237
  ],
238
238
  temperature: 0.4,
@@ -253,7 +253,7 @@ export async function generateDraft(messageId, peerDID, transport = defaultIrohT
253
253
  console.warn(`[DraftEngine] LLM call failed: ${e.message}`);
254
254
  }
255
255
  if (!draftText) {
256
- draftText = `[DRAFT] 已收到. (本地 draft 引擎未配置 LLM, 主人上线后请手写回复)`;
256
+ draftText = `[DRAFT] 已收到. (本地 draft 引擎未配置 LLM, 用户上线后请手写回复)`;
257
257
  confidence = 0.1;
258
258
  }
259
259
  const updated = await updateInboxEntry(peerDID, messageId, {
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Permission Mode — 3 种模式枚举 + 解析
3
+ *
4
+ * 设计: 严格对齐 Claude Code 论文 3 种 mode (default / acceptEdits / bypassPermissions)
5
+ * 论文第 7 种 (plan/dontAsk/bubble) bolloon 暂不引入, 减少 API surface.
6
+ *
7
+ * 关键设计: shell-guard **不受** mode 影响
8
+ * - 路径黑名单 (.bolloon/, pi-sdk.ts, shell-guard.ts, .env, .git/ 等) 永远生效
9
+ * - 命令 allowlist 默认: git/node/npm/npx/tsx/tsc/vitest/cat/head/tail/wc/ls/echo/pwd/date/mkdir/touch 永远生效
10
+ * - 即使用户设 bypassPermissions, shell 类工具仍走 shell-guard
11
+ *
12
+ * 失败静默: 任何异常 → 返回 'default' (向后兼容)
13
+ */
14
+ export const ALL_PERMISSION_MODES = [
15
+ 'default',
16
+ 'acceptEdits',
17
+ 'bypassPermissions',
18
+ ];
19
+ /**
20
+ * 解析当前 permission mode.
21
+ * 优先级 (由高到低):
22
+ * 1. opts.permissionMode (BootstrapOptions 显式传入)
23
+ * 2. runtime override (~/.bolloon/sessions/permission-mode.json, UI 设置)
24
+ * 3. env BOLLOON_PERM_MODE (环境变量)
25
+ * 4. 'default' (兜底)
26
+ *
27
+ * 非法值 → fallback 'default', console.warn
28
+ * 失败静默: 任何异常 → 'default' (不阻塞主对话)
29
+ */
30
+ export function resolvePermissionMode(opts) {
31
+ try {
32
+ if (opts?.permissionMode && ALL_PERMISSION_MODES.includes(opts.permissionMode)) {
33
+ return opts.permissionMode;
34
+ }
35
+ // runtime override (UI 设置, 存 ~/.bolloon/sessions/permission-mode.json)
36
+ const override = readRuntimeOverride();
37
+ if (override) {
38
+ return override;
39
+ }
40
+ const env = process.env.BOLLOON_PERM_MODE;
41
+ if (env === 'default' || env === 'acceptEdits' || env === 'bypassPermissions') {
42
+ return env;
43
+ }
44
+ if (env && env.length > 0) {
45
+ console.warn(`[permission-mode] unknown BOLLOON_PERM_MODE="${env}", fallback to "default"`);
46
+ }
47
+ return 'default';
48
+ }
49
+ catch (err) {
50
+ console.warn('[permission-mode] resolvePermissionMode failed (silent, using default):', err);
51
+ return 'default';
52
+ }
53
+ }
54
+ /**
55
+ * 读 runtime override 文件 (UI 设的 mode).
56
+ * 失败静默: 任何异常 → null (回到 env/default)
57
+ */
58
+ function readRuntimeOverride() {
59
+ try {
60
+ const fs = require('fs');
61
+ const os = require('os');
62
+ const path = require('path');
63
+ const file = path.join(process.env.HOME || os.homedir() || '/tmp', '.bolloon', 'sessions', 'permission-mode.json');
64
+ if (!fs.existsSync(file))
65
+ return null;
66
+ const raw = fs.readFileSync(file, 'utf-8');
67
+ const obj = JSON.parse(raw);
68
+ if (obj && typeof obj.mode === 'string' && ALL_PERMISSION_MODES.includes(obj.mode)) {
69
+ return obj.mode;
70
+ }
71
+ return null;
72
+ }
73
+ catch {
74
+ return null;
75
+ }
76
+ }
77
+ /**
78
+ * 工具名分类: 是不是"编辑"类 (受 acceptEdits 模式影响)
79
+ * 简单按前缀, 不做完整注册表
80
+ */
81
+ export function isEditTool(toolName) {
82
+ const lc = toolName.toLowerCase();
83
+ return lc.startsWith('edit_') || lc.startsWith('write_') || lc === 'str_replace' || lc === 'create_file' || lc === 'present_files';
84
+ }
85
+ /**
86
+ * 工具名分类: 是不是"shell"类 (永远走 shell-guard, 不受 mode 影响)
87
+ */
88
+ export function isShellTool(toolName) {
89
+ const lc = toolName.toLowerCase();
90
+ return lc === 'shell' || lc === 'shell_exec' || lc === 'bash';
91
+ }
92
+ /**
93
+ * 判断当前 mode + tool 的最终是否需要走 blacklist
94
+ *
95
+ * 逻辑表:
96
+ * - shell 工具: 永远走 blacklist (shell-guard 接管)
97
+ * - bypassPermissions 模式: 非 shell 全部放行
98
+ * - acceptEdits 模式: edit_* / write_* 类跳过 blacklist
99
+ * - default 模式: 全部走 blacklist
100
+ */
101
+ export function shouldRunBlacklist(toolName, mode) {
102
+ if (isShellTool(toolName))
103
+ return true; // shell-guard 永远跑
104
+ if (mode === 'bypassPermissions')
105
+ return false;
106
+ if (mode === 'acceptEdits' && isEditTool(toolName))
107
+ return false;
108
+ return true; // default
109
+ }
110
+ // ============================================================
111
+ // 测试钩子
112
+ // ============================================================
113
+ export function _resetPermissionModeForTest() {
114
+ // 解析只读 env, 无内部状态, 保留 API 一致
115
+ }