@bolloon/bolloon-agent 0.5.4 → 0.6.0

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 (222) hide show
  1. package/dist/agents/agent-identity-store.js +41 -5
  2. package/dist/agents/background-notices.js +124 -0
  3. package/dist/agents/channel-identity.js +54 -0
  4. package/dist/agents/code-write-gate.js +47 -0
  5. package/dist/agents/deny-pipeline.js +11 -2
  6. package/dist/agents/egress-sanitize.js +69 -0
  7. package/dist/agents/error-classifier.js +67 -5
  8. package/dist/agents/experience-review.js +226 -0
  9. package/dist/agents/gateway-group.js +153 -18
  10. package/dist/agents/iteration-budget.js +64 -0
  11. package/dist/agents/lesson-to-skill.js +211 -0
  12. package/dist/agents/managed-services.js +64 -0
  13. package/dist/agents/parse-tool-call.js +43 -32
  14. package/dist/agents/pi-sdk-session-factory.js +36 -3
  15. package/dist/agents/pi-sdk-session-manager.js +72 -3
  16. package/dist/agents/pi-sdk-tools.js +201 -32
  17. package/dist/agents/pi-sdk.js +798 -206
  18. package/dist/agents/plan-store.js +36 -0
  19. package/dist/agents/process-runner.js +64 -2
  20. package/dist/agents/run-context.js +20 -0
  21. package/dist/agents/runner-resolver.js +2 -1
  22. package/dist/agents/shell-guard.js +109 -13
  23. package/dist/agents/skill-health.js +90 -0
  24. package/dist/agents/skill-ledger.js +129 -0
  25. package/dist/agents/tool-loop-guard.js +303 -0
  26. package/dist/agents/tool-path-args.js +53 -0
  27. package/dist/agents/tool-result-gate.js +50 -0
  28. package/dist/agents/tool-subset.js +109 -0
  29. package/dist/agents/tool-telemetry.js +97 -0
  30. package/dist/bootstrap/context-collector.js +37 -7
  31. package/dist/bootstrap/lifecycle-hooks.js +12 -3
  32. package/dist/bootstrap/persona-init.js +174 -0
  33. package/dist/bootstrap/persona-loader.js +5 -1
  34. package/dist/cli/ink-app.js +153 -6
  35. package/dist/cli/input-paste.js +218 -0
  36. package/dist/cli/loading-tui.js +3 -1
  37. package/dist/cli/log-gate.js +7 -0
  38. package/dist/cli/mention-data.js +30 -0
  39. package/dist/cli/reasoning-view.js +103 -0
  40. package/dist/cli/startup-notice.js +25 -0
  41. package/dist/cli/status-segments.js +87 -2
  42. package/dist/cli/trace-line.js +54 -0
  43. package/dist/context-compaction/auto-compact.js +37 -2
  44. package/dist/electron-build/agents/agent-identity-store.js +43 -5
  45. package/dist/electron-build/agents/agent-identity-store.js.map +1 -1
  46. package/dist/electron-build/agents/background-notices.js +138 -0
  47. package/dist/electron-build/agents/background-notices.js.map +1 -0
  48. package/dist/electron-build/agents/channel-identity.js +64 -0
  49. package/dist/electron-build/agents/channel-identity.js.map +1 -0
  50. package/dist/electron-build/agents/code-write-gate.js +55 -0
  51. package/dist/electron-build/agents/code-write-gate.js.map +1 -0
  52. package/dist/electron-build/agents/deny-pipeline.js +11 -2
  53. package/dist/electron-build/agents/deny-pipeline.js.map +1 -1
  54. package/dist/electron-build/agents/egress-sanitize.js +76 -0
  55. package/dist/electron-build/agents/egress-sanitize.js.map +1 -0
  56. package/dist/electron-build/agents/error-classifier.js +68 -5
  57. package/dist/electron-build/agents/error-classifier.js.map +1 -1
  58. package/dist/electron-build/agents/experience-review.js +243 -0
  59. package/dist/electron-build/agents/experience-review.js.map +1 -0
  60. package/dist/electron-build/agents/iteration-budget.js +73 -0
  61. package/dist/electron-build/agents/iteration-budget.js.map +1 -0
  62. package/dist/electron-build/agents/lesson-to-skill.js +228 -0
  63. package/dist/electron-build/agents/lesson-to-skill.js.map +1 -0
  64. package/dist/electron-build/agents/managed-services.js +69 -0
  65. package/dist/electron-build/agents/managed-services.js.map +1 -0
  66. package/dist/electron-build/agents/parse-tool-call.js +43 -32
  67. package/dist/electron-build/agents/parse-tool-call.js.map +1 -1
  68. package/dist/electron-build/agents/pi-sdk-session-factory.js +36 -3
  69. package/dist/electron-build/agents/pi-sdk-session-factory.js.map +1 -1
  70. package/dist/electron-build/agents/pi-sdk-session-manager.js +75 -3
  71. package/dist/electron-build/agents/pi-sdk-session-manager.js.map +1 -1
  72. package/dist/electron-build/agents/pi-sdk-tools.js +200 -31
  73. package/dist/electron-build/agents/pi-sdk-tools.js.map +1 -1
  74. package/dist/electron-build/agents/pi-sdk-types.js.map +1 -1
  75. package/dist/electron-build/agents/pi-sdk.js +799 -206
  76. package/dist/electron-build/agents/pi-sdk.js.map +1 -1
  77. package/dist/electron-build/agents/plan-store.js +37 -0
  78. package/dist/electron-build/agents/plan-store.js.map +1 -1
  79. package/dist/electron-build/agents/process-runner.js +71 -2
  80. package/dist/electron-build/agents/process-runner.js.map +1 -1
  81. package/dist/electron-build/agents/run-context.js +24 -0
  82. package/dist/electron-build/agents/run-context.js.map +1 -0
  83. package/dist/electron-build/agents/runner-resolver.js +2 -1
  84. package/dist/electron-build/agents/runner-resolver.js.map +1 -1
  85. package/dist/electron-build/agents/shell-guard.js +110 -14
  86. package/dist/electron-build/agents/shell-guard.js.map +1 -1
  87. package/dist/electron-build/agents/skill-health.js +103 -0
  88. package/dist/electron-build/agents/skill-health.js.map +1 -0
  89. package/dist/electron-build/agents/skill-ledger.js +146 -0
  90. package/dist/electron-build/agents/skill-ledger.js.map +1 -0
  91. package/dist/electron-build/agents/tool-loop-guard.js +319 -0
  92. package/dist/electron-build/agents/tool-loop-guard.js.map +1 -0
  93. package/dist/electron-build/agents/tool-path-args.js +63 -0
  94. package/dist/electron-build/agents/tool-path-args.js.map +1 -0
  95. package/dist/electron-build/agents/tool-result-gate.js +59 -0
  96. package/dist/electron-build/agents/tool-result-gate.js.map +1 -0
  97. package/dist/electron-build/agents/tool-subset.js +116 -0
  98. package/dist/electron-build/agents/tool-subset.js.map +1 -0
  99. package/dist/electron-build/agents/tool-telemetry.js +108 -0
  100. package/dist/electron-build/agents/tool-telemetry.js.map +1 -0
  101. package/dist/electron-build/bootstrap/context-collector.js +38 -7
  102. package/dist/electron-build/bootstrap/context-collector.js.map +1 -1
  103. package/dist/electron-build/bootstrap/lifecycle-hooks.js +12 -3
  104. package/dist/electron-build/bootstrap/lifecycle-hooks.js.map +1 -1
  105. package/dist/electron-build/bootstrap/persona-init.js +216 -0
  106. package/dist/electron-build/bootstrap/persona-init.js.map +1 -0
  107. package/dist/electron-build/bootstrap/persona-loader.js +5 -1
  108. package/dist/electron-build/bootstrap/persona-loader.js.map +1 -1
  109. package/dist/electron-build/context-compaction/auto-compact.js +38 -2
  110. package/dist/electron-build/context-compaction/auto-compact.js.map +1 -1
  111. package/dist/electron-build/external-engines/delegate.js +22 -0
  112. package/dist/electron-build/external-engines/delegate.js.map +1 -1
  113. package/dist/electron-build/kernel/channel-actor.js +314 -0
  114. package/dist/electron-build/kernel/channel-actor.js.map +1 -0
  115. package/dist/electron-build/orbitdb/cid-database.js +55 -0
  116. package/dist/electron-build/orbitdb/cid-database.js.map +1 -1
  117. package/dist/electron-build/orbitdb/ipfs-node.js +36 -11
  118. package/dist/electron-build/orbitdb/ipfs-node.js.map +1 -1
  119. package/dist/electron-build/web/server-storage.js +26 -5
  120. package/dist/electron-build/web/server-storage.js.map +1 -1
  121. package/dist/external-engines/delegate.js +21 -0
  122. package/dist/index.js +526 -95
  123. package/dist/kernel/channel-actor.js +297 -0
  124. package/dist/kernel/control.js +95 -0
  125. package/dist/kernel/gate-scan.js +1036 -0
  126. package/dist/kernel/model-runtime.js +472 -0
  127. package/dist/kernel/plan-channel-actor.js +298 -0
  128. package/dist/kernel/plan-constraint.js +165 -0
  129. package/dist/kernel/plan-deletion.js +32 -0
  130. package/dist/kernel/plan-modelruntime.js +60 -0
  131. package/dist/kernel/plan-runcontext.js +163 -0
  132. package/dist/kernel/plan.js +153 -0
  133. package/dist/kernel/roster.js +242 -0
  134. package/dist/orbitdb/cid-database.js +55 -0
  135. package/dist/orbitdb/event-index.js +370 -0
  136. package/dist/orbitdb/event-query.js +131 -0
  137. package/dist/orbitdb/event-shell.js +510 -0
  138. package/dist/orbitdb/group-access.js +381 -0
  139. package/dist/orbitdb/group-shards.js +140 -0
  140. package/dist/orbitdb/ipfs-node.js +36 -11
  141. package/dist/web/bolloon-web.json +3 -3
  142. package/dist/web/client.js +4 -2
  143. package/dist/web/mobile-core.js +7762 -6289
  144. package/dist/web/routes-mobile-tasks.js +2 -1
  145. package/dist/web/routes-tasks.js +5 -1
  146. package/dist/web/server-storage.js +26 -5
  147. package/dist/web/server.js +60 -18
  148. package/dist/web/sw.js +1 -1
  149. package/dist/web/ui/message-renderer.js +473 -29
  150. package/dist/web/ui/step-timeline.js +13 -12
  151. package/package.json +2 -1
  152. package/scripts/build-web.ts +74 -1
  153. package/dist/constraint-runtime/_archive_helper.d.ts +0 -1
  154. package/dist/constraint-runtime/_archive_helper.js +0 -9
  155. package/dist/constraint-runtime/assistant/index.d.ts +0 -11
  156. package/dist/constraint-runtime/assistant/index.js +0 -12
  157. package/dist/constraint-runtime/bootstrap/index.d.ts +0 -11
  158. package/dist/constraint-runtime/bootstrap/index.js +0 -12
  159. package/dist/constraint-runtime/bridge/index.d.ts +0 -11
  160. package/dist/constraint-runtime/bridge/index.js +0 -12
  161. package/dist/constraint-runtime/buddy/index.d.ts +0 -11
  162. package/dist/constraint-runtime/buddy/index.js +0 -12
  163. package/dist/constraint-runtime/cli/index.d.ts +0 -11
  164. package/dist/constraint-runtime/cli/index.js +0 -12
  165. package/dist/constraint-runtime/components/index.d.ts +0 -11
  166. package/dist/constraint-runtime/components/index.js +0 -12
  167. package/dist/constraint-runtime/constants/index.d.ts +0 -11
  168. package/dist/constraint-runtime/constants/index.js +0 -12
  169. package/dist/constraint-runtime/coordinator/index.d.ts +0 -11
  170. package/dist/constraint-runtime/coordinator/index.js +0 -12
  171. package/dist/constraint-runtime/cost_hook.d.ts +0 -2
  172. package/dist/constraint-runtime/cost_hook.js +0 -4
  173. package/dist/constraint-runtime/entrypoints/index.d.ts +0 -11
  174. package/dist/constraint-runtime/entrypoints/index.js +0 -12
  175. package/dist/constraint-runtime/execution_registry.d.ts +0 -20
  176. package/dist/constraint-runtime/execution_registry.js +0 -44
  177. package/dist/constraint-runtime/hooks/index.d.ts +0 -11
  178. package/dist/constraint-runtime/hooks/index.js +0 -12
  179. package/dist/constraint-runtime/ink.d.ts +0 -1
  180. package/dist/constraint-runtime/ink.js +0 -4
  181. package/dist/constraint-runtime/keybindings/index.d.ts +0 -11
  182. package/dist/constraint-runtime/keybindings/index.js +0 -12
  183. package/dist/constraint-runtime/memdir/index.d.ts +0 -11
  184. package/dist/constraint-runtime/memdir/index.js +0 -12
  185. package/dist/constraint-runtime/migrations/index.d.ts +0 -11
  186. package/dist/constraint-runtime/migrations/index.js +0 -12
  187. package/dist/constraint-runtime/moreright/index.d.ts +0 -11
  188. package/dist/constraint-runtime/moreright/index.js +0 -12
  189. package/dist/constraint-runtime/native_ts/index.d.ts +0 -11
  190. package/dist/constraint-runtime/native_ts/index.js +0 -12
  191. package/dist/constraint-runtime/output_styles/index.d.ts +0 -11
  192. package/dist/constraint-runtime/output_styles/index.js +0 -12
  193. package/dist/constraint-runtime/plugins/index.d.ts +0 -11
  194. package/dist/constraint-runtime/plugins/index.js +0 -12
  195. package/dist/constraint-runtime/port_manifest.d.ts +0 -7
  196. package/dist/constraint-runtime/port_manifest.js +0 -11
  197. package/dist/constraint-runtime/query.d.ts +0 -6
  198. package/dist/constraint-runtime/query.js +0 -1
  199. package/dist/constraint-runtime/remote/index.d.ts +0 -11
  200. package/dist/constraint-runtime/remote/index.js +0 -12
  201. package/dist/constraint-runtime/schemas/index.d.ts +0 -11
  202. package/dist/constraint-runtime/schemas/index.js +0 -12
  203. package/dist/constraint-runtime/screens/index.d.ts +0 -11
  204. package/dist/constraint-runtime/screens/index.js +0 -12
  205. package/dist/constraint-runtime/server/index.d.ts +0 -11
  206. package/dist/constraint-runtime/server/index.js +0 -12
  207. package/dist/constraint-runtime/services/index.d.ts +0 -11
  208. package/dist/constraint-runtime/services/index.js +0 -12
  209. package/dist/constraint-runtime/state/index.d.ts +0 -11
  210. package/dist/constraint-runtime/state/index.js +0 -12
  211. package/dist/constraint-runtime/system_init.d.ts +0 -1
  212. package/dist/constraint-runtime/system_init.js +0 -20
  213. package/dist/constraint-runtime/types/index.d.ts +0 -11
  214. package/dist/constraint-runtime/types/index.js +0 -12
  215. package/dist/constraint-runtime/upstream_proxy/index.d.ts +0 -11
  216. package/dist/constraint-runtime/upstream_proxy/index.js +0 -12
  217. package/dist/constraint-runtime/utils/index.d.ts +0 -11
  218. package/dist/constraint-runtime/utils/index.js +0 -12
  219. package/dist/constraint-runtime/vim/index.d.ts +0 -11
  220. package/dist/constraint-runtime/vim/index.js +0 -12
  221. package/dist/constraint-runtime/voice/index.d.ts +0 -11
  222. package/dist/constraint-runtime/voice/index.js +0 -12
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.STALE_AFTER_MS = void 0;
7
+ exports.usagePath = usagePath;
8
+ exports.bumpUsage = bumpUsage;
9
+ exports.markCreatedBy = markCreatedBy;
10
+ exports.setPinned = setPinned;
11
+ exports.lifecycleOf = lifecycleOf;
12
+ exports.usageSummary = usageSummary;
13
+ /**
14
+ * 技能用量遥测 + 生命周期 (2026-10-01)。
15
+ * 形态要点: 遥测放**旁挂文件** ✓ —— 绝不写进用户自己写的 SKILL.md ✗(那是用户的文件 ✓)。
16
+ * 生命周期: active → stale(久未用) → archived; `pinned` 可退出自动流转 ✓。
17
+ * 边界(如实): 本模块只**计算状态并给建议** ✓, **不自动移动/删除任何技能文件** ✗(那是破坏性动作, 交人决定 ✓)。
18
+ */
19
+ const node_fs_1 = __importDefault(require("node:fs"));
20
+ const node_os_1 = __importDefault(require("node:os"));
21
+ const node_path_1 = __importDefault(require("node:path"));
22
+ function usagePath(home = node_os_1.default.homedir()) {
23
+ return node_path_1.default.join(home, '.bolloon', 'skills', '.usage.json');
24
+ }
25
+ function load(home) {
26
+ try {
27
+ const o = JSON.parse(node_fs_1.default.readFileSync(usagePath(home), 'utf-8'));
28
+ return o && typeof o === 'object' ? o : {};
29
+ }
30
+ catch {
31
+ return {};
32
+ }
33
+ }
34
+ function save(m, home) {
35
+ try {
36
+ const p = usagePath(home);
37
+ node_fs_1.default.mkdirSync(node_path_1.default.dirname(p), { recursive: true });
38
+ node_fs_1.default.writeFileSync(p, JSON.stringify(m), { mode: 0o600 });
39
+ }
40
+ catch { /* 遥测失败不影响工具调用 */ }
41
+ }
42
+ /** 用了一次(读技能时调 ✓); 失败只吞 ✓ */
43
+ function bumpUsage(skill, home, now = Date.now()) {
44
+ try {
45
+ const m = load(home);
46
+ const cur = m[skill] || { count: 0, lastUsedAt: 0 };
47
+ m[skill] = { ...cur, count: cur.count + 1, lastUsedAt: now };
48
+ save(m, home);
49
+ }
50
+ catch { /* best-effort */ }
51
+ }
52
+ /** 记下创建者(自审 / 用户点名) */
53
+ function markCreatedBy(skill, by, home, now = Date.now()) {
54
+ try {
55
+ const m = load(home);
56
+ const cur = m[skill] || { count: 0, lastUsedAt: 0 };
57
+ m[skill] = { ...cur, createdBy: by, lastUsedAt: cur.lastUsedAt || now };
58
+ save(m, home);
59
+ }
60
+ catch { /* best-effort */ }
61
+ }
62
+ /** 钉住(退出自动流转) */
63
+ function setPinned(skill, pinned, home) {
64
+ try {
65
+ const m = load(home);
66
+ const cur = m[skill] || { count: 0, lastUsedAt: 0 };
67
+ m[skill] = { ...cur, pinned };
68
+ save(m, home);
69
+ }
70
+ catch { /* best-effort */ }
71
+ }
72
+ exports.STALE_AFTER_MS = 45 * 24 * 3600 * 1000; // 45 天没用 ⇒ stale
73
+ /** 生命周期(只算不给动作 ✓): active / stale / archived-eligible */
74
+ function lifecycleOf(skill, home, now = Date.now()) {
75
+ const u = load(home)[skill];
76
+ if (!u)
77
+ return { state: 'unknown', reason: '旁挂遥测里没有它(可能是导入/内置技能)', count: 0, pinned: false };
78
+ if (u.pinned)
79
+ return { state: 'active', reason: '已 pinned(退出自动流转)', count: u.count, pinned: true };
80
+ const idle = now - (u.lastUsedAt || 0);
81
+ return {
82
+ state: idle > exports.STALE_AFTER_MS ? 'stale' : 'active',
83
+ reason: idle > exports.STALE_AFTER_MS ? `已 ${Math.round(idle / 86400000)} 天未用(仅状态, 不会自动删 ✓)` : `近用过(${u.count} 次)`,
84
+ count: u.count,
85
+ pinned: false,
86
+ };
87
+ }
88
+ /** 汇总(给面板/工具用 ✓) */
89
+ function usageSummary(home, now = Date.now()) {
90
+ const m = load(home);
91
+ let active = 0, stale = 0, pinned = 0;
92
+ for (const k of Object.keys(m)) {
93
+ const l = lifecycleOf(k, home, now);
94
+ if (l.pinned)
95
+ pinned++;
96
+ if (l.state === 'active')
97
+ active++;
98
+ else if (l.state === 'stale')
99
+ stale++;
100
+ }
101
+ return { total: Object.keys(m).length, active, stale, pinned };
102
+ }
103
+ //# sourceMappingURL=skill-health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-health.js","sourceRoot":"","sources":["../../../src/agents/skill-health.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.runWithWriteOrigin = runWithWriteOrigin;
7
+ exports.currentWriteOrigin = currentWriteOrigin;
8
+ exports.isReviewWrite = isReviewWrite;
9
+ exports.ledgerPath = ledgerPath;
10
+ exports.blobsDir = blobsDir;
11
+ exports.captureSkillBefore = captureSkillBefore;
12
+ exports.appendLedger = appendLedger;
13
+ exports.readLedger = readLedger;
14
+ exports.isAgentCreated = isAgentCreated;
15
+ exports.reviewMayTouch = reviewMayTouch;
16
+ exports.rollbackEntry = rollbackEntry;
17
+ /**
18
+ * 技能账本 + 单条回滚 + 写来源隔离 (2026-10-01, 按"账本而非闸门"的形态做)。
19
+ *
20
+ * 三件事:
21
+ * ① **账本**: 每次技能变更追加一条 JSONL(前后清单 + 内容寻址备份)⇒ 可单条回滚 ✓。
22
+ * 放 JSONL 不放数据库: 耐久 · 可 grep · 数据库重置也不丢 ✓。
23
+ * ② **单条回滚**: 按 id 还原那一次变更; **唯独回滚是 fail-closed** ✓(安全快照拿不到就拒绝回滚,
24
+ * 绝不"半还原"✗); 其余全部吞错只记日志(账本坏掉不该挡住干活 ✓)。
25
+ * ③ **写来源隔离**: 用 AsyncLocalStorage 区分"用户点名要的写"(foreground ✓)与
26
+ * "自审/复盘产生的写"(review ✓)⇒ 自审**只许治理自己造出来的技能** ✓, 用户要的归用户 ✓。
27
+ */
28
+ const node_fs_1 = __importDefault(require("node:fs"));
29
+ const node_os_1 = __importDefault(require("node:os"));
30
+ const node_path_1 = __importDefault(require("node:path"));
31
+ const node_crypto_1 = __importDefault(require("node:crypto"));
32
+ const node_async_hooks_1 = require("node:async_hooks");
33
+ const originStore = new node_async_hooks_1.AsyncLocalStorage();
34
+ /** 在"自审"上下文里跑一段(其余一律按 foreground ✓) */
35
+ function runWithWriteOrigin(origin, fn) {
36
+ return originStore.run({ origin }, fn);
37
+ }
38
+ function currentWriteOrigin() {
39
+ return originStore.getStore()?.origin ?? 'foreground';
40
+ }
41
+ function isReviewWrite() {
42
+ return currentWriteOrigin() === 'review';
43
+ }
44
+ function ledgerPath(home = node_os_1.default.homedir()) {
45
+ return node_path_1.default.join(home, '.bolloon', 'skills', '.skill-ledger.jsonl');
46
+ }
47
+ function blobsDir(home = node_os_1.default.homedir()) {
48
+ return node_path_1.default.join(home, '.bolloon', 'skills', '.ledger-blobs');
49
+ }
50
+ function sha256(text) {
51
+ return node_crypto_1.default.createHash('sha256').update(text, 'utf-8').digest('hex');
52
+ }
53
+ /** 把内容按哈希存进 blobs(已存在则复用 ✓ 天然去重) */
54
+ function putBlob(text, home) {
55
+ const h = sha256(text);
56
+ const p = node_path_1.default.join(blobsDir(home), h);
57
+ try {
58
+ if (!node_fs_1.default.existsSync(p)) {
59
+ node_fs_1.default.mkdirSync(node_path_1.default.dirname(p), { recursive: true });
60
+ node_fs_1.default.writeFileSync(p, text, { mode: 0o600 });
61
+ }
62
+ }
63
+ catch { /* 备份失败 ⇒ 由调用方决定是否允许这次变更(见 captureBefore) */ }
64
+ return h;
65
+ }
66
+ /** 变更前快照: 返回 beforeSha(拿不到安全快照时返回 undefined ⇒ 回滚能力缺失, 调用方须知道 ✓) */
67
+ function captureSkillBefore(file, home) {
68
+ try {
69
+ const text = node_fs_1.default.readFileSync(file, 'utf-8');
70
+ return { beforeSha: putBlob(text, home), bytesBefore: text.length };
71
+ }
72
+ catch {
73
+ return {}; // 文件不存在(新建)= 正常; 读不到 = 快照缺失
74
+ }
75
+ }
76
+ /** 追加一条账本(吞错只记日志 ✓ —— 账本坏掉不该挡住干活) */
77
+ function appendLedger(entry, home) {
78
+ const full = { id: entry.id || node_crypto_1.default.randomBytes(8).toString('hex'), at: entry.at ?? Date.now(), ...entry };
79
+ try {
80
+ const p = ledgerPath(home);
81
+ node_fs_1.default.mkdirSync(node_path_1.default.dirname(p), { recursive: true });
82
+ node_fs_1.default.appendFileSync(p, JSON.stringify(full) + '\n', { mode: 0o600 });
83
+ }
84
+ catch { /* telemetry, not a gate */ }
85
+ return full;
86
+ }
87
+ function readLedger(home) {
88
+ try {
89
+ const raw = node_fs_1.default.readFileSync(ledgerPath(home), 'utf-8');
90
+ const out = [];
91
+ for (const line of raw.split('\n')) {
92
+ if (!line.trim())
93
+ continue;
94
+ try {
95
+ out.push(JSON.parse(line));
96
+ }
97
+ catch { /* 坏行跳过 */ }
98
+ }
99
+ return out;
100
+ }
101
+ catch {
102
+ return [];
103
+ }
104
+ }
105
+ /** 这个技能是不是"自审造出来的"?(决定自审有没有资格改它 ✓) */
106
+ function isAgentCreated(skill, home) {
107
+ return readLedger(home).some((e) => e.skill === skill && e.tool === 'create_skill' && e.origin === 'review');
108
+ }
109
+ /**
110
+ * 自审写前的资格检查(只读判断, 不改任何东西 ✓):
111
+ * 自审只许动**自己造出来**的技能 ✓; 用户点名要的归用户 ✓。
112
+ */
113
+ function reviewMayTouch(skill, home) {
114
+ if (!isReviewWrite())
115
+ return { ok: true, reason: 'foreground(用户点名要的写)' };
116
+ return isAgentCreated(skill, home)
117
+ ? { ok: true, reason: 'review(该技能由自审创建, 可治理)' }
118
+ : { ok: false, reason: '该技能不是自审创建的(用户点名要的归用户)⇒ 自审只记候选, 不动它' };
119
+ }
120
+ /**
121
+ * 单条回滚: 把某次变更前的快照还原回去 ✓。
122
+ * **fail-closed**: 快照缺失/内容哈希对不上 ⇒ 拒绝(绝不半还原 ✗)。
123
+ */
124
+ function rollbackEntry(id, home) {
125
+ const entry = readLedger(home).find((e) => e.id === id);
126
+ if (!entry)
127
+ return { ok: false, reason: `账本里没有 id=${id}` };
128
+ if (entry.tool === 'create_skill') {
129
+ // 创建类变更: 回滚 = 删掉那个文件(要用户明确同意 ⇒ 这里只报告, 不擅自删 ✗)
130
+ return { ok: false, reason: '该条是"新建技能"; 回滚等于删除文件 —— 需要你明确同意, 我不擅自删' };
131
+ }
132
+ if (!entry.beforeSha)
133
+ return { ok: false, reason: '该条没有变更前快照 ⇒ 拒绝回滚(fail-closed, 不做半还原)' };
134
+ try {
135
+ const blob = node_fs_1.default.readFileSync(node_path_1.default.join(blobsDir(home), entry.beforeSha), 'utf-8');
136
+ if (sha256(blob) !== entry.beforeSha)
137
+ return { ok: false, reason: '快照内容与哈希不符 ⇒ 拒绝回滚' };
138
+ node_fs_1.default.writeFileSync(entry.file, blob, { mode: 0o600 });
139
+ appendLedger({ origin: 'foreground', tool: 'rollback', skill: entry.skill, file: entry.file, beforeSha: entry.afterSha, afterSha: entry.beforeSha, note: `回到 ${entry.id}` }, home);
140
+ return { ok: true, reason: `已回滚到变更前(${entry.id})`, restored: entry.file };
141
+ }
142
+ catch (e) {
143
+ return { ok: false, reason: `回滚失败: ${String(e?.message || e).slice(0, 120)}` };
144
+ }
145
+ }
146
+ //# sourceMappingURL=skill-ledger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-ledger.js","sourceRoot":"","sources":["../../../src/agents/skill-ledger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,319 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_THRESHOLDS = exports.LoopStallState = exports.STUB_ARGS_PREVIEW_CHARS = exports.REPEAT_STUB_MIN_CHARS = exports.STUB_MIN_CHARS = exports.CYCLE_HISTORY = exports.MAX_CYCLE_PERIOD = exports.IDENTICAL_CALL_THRESHOLD = exports.FAILURE_TOLERANT_TOOLS = exports.REPEATABLE_SUFFIXES = exports.REPEATABLE_TOOLS = exports.MUTATING_TOOLS = exports.IDEMPOTENT_TOOLS = exports.CONSTANT_RESULT_TOOLS = void 0;
4
+ exports.canonicalToolArgs = canonicalToolArgs;
5
+ exports.toolCallSignature = toolCallSignature;
6
+ exports.resultFingerprint = resultFingerprint;
7
+ exports.isRepeatableTool = isRepeatableTool;
8
+ exports.observeToolCall = observeToolCall;
9
+ exports.detectCycle = detectCycle;
10
+ exports.toolMayHaveSideEffect = toolMayHaveSideEffect;
11
+ exports.defaultHardStopFor = defaultHardStopFor;
12
+ exports.newProgressBookkeeping = newProgressBookkeeping;
13
+ exports.trackProgress = trackProgress;
14
+ exports.batchHint = batchHint;
15
+ /**
16
+ * tool-loop-guard.ts — 工具调用的**停滞观测与温和引导** (2026-10-01)
17
+ *
18
+ * 为什么需要它 (用户原话: 「一个简单的任务居然花这么多次工具调用」):
19
+ * 原先的防重只有一条「同工具连续 5 次 ⇒ 注入一条提示, 然后重置计数」。实测模型无视提示后
20
+ * 完全没刹车 —— 同一个 get_identity 连调 10 次 ✗; 而且**只看工具名**, 连"同工具换参数的正常
21
+ * 迭代"(逐文件读)也会被误判。
22
+ * 反过来"硬停"也不行 (用户明确否决): 那是在症状上下手, 而且会堵掉正当的重复轮询。
23
+ *
24
+ * 所以这里采用**分类 + 温和合成**的口径:
25
+ * ① 工具先分类: 幂等读 / 有副作用 / 可重复轮询 (含命名约定 `_poll` / `_get_result`);
26
+ * ② 判据看**签名** (工具名 + 参数的规范 JSON 的哈希), 不只看工具名 ⇒ 换参数不误伤;
27
+ * ③ 命中停滞**不拒绝执行**, 而是产出一条**引导文本**追加在真结果后面 (保留模型的选择权);
28
+ * ④ 完全相同的**结果**从第 2 次起用**引用 stub** 替代 (省上下文; 且明确告诉模型"与上次相同");
29
+ * ⑤ 抓**循环** (A→B→A→B…, 周期 ≤4): 相邻重复计数会被交替调用清零, 只抓相邻的会漏;
30
+ * ⑥ 失败宽容类工具 (跑测试红了 / grep 空 / 页面超时) 的"失败"是正常工作输出, 不参与停滞判定。
31
+ *
32
+ * 纯逻辑, 不碰 IO / 不发请求 —— 便于单测与变异验证。
33
+ */
34
+ const node_crypto_1 = require("node:crypto");
35
+ /** 幂等只读类: 同参数重复调用不会产生新信息 (但允许换参数继续用) */
36
+ /**
37
+ * **结果恒定**的工具 (2026-10-01): 同一会话内反复调, 返回**永远一样**, 且答案本身很短。
38
+ * 用户实测: `get_identity` 连调 3–4 次 ✗ —— 原有"引用 stub"有字符数门槛, 而它的输出才 ~90 字符
39
+ * ⇒ 门槛拦不住 ⇒ 模型看不出"再问也一样"。
40
+ * 规矩 (工具设置层, 不做硬刹车): 从**第 2 次**完全相同的调用起, 直接把结果换成一句标准答复,
41
+ * 明确告诉模型"答案就在上面那次返回里, 再调不会变" ⇒ 去掉它重复调的理由。
42
+ */
43
+ exports.CONSTANT_RESULT_TOOLS = new Set([
44
+ 'get_identity', 'bolloon_config_get', 'get_agent_info', 'whoami',
45
+ ]);
46
+ exports.IDEMPOTENT_TOOLS = new Set([
47
+ 'read_file', 'list_files', 'search_files', 'get_identity', 'get_operation_logs',
48
+ 'list_remote_channels', 'list_context_layers', 'read_context_assets', 'get_balance', 'wallet_list',
49
+ 'web_search', 'web_extract', 'check_inbox',
50
+ ]);
51
+ /** 有副作用类: 重复调用可能是正当的 (例如再跑一条命令), 由"同签名同结果"判定停滞 */
52
+ exports.MUTATING_TOOLS = new Set([
53
+ 'terminal', 'shell_exec', 'execute_code', 'write_file', 'patch', 'set_persona', 'memory',
54
+ 'todo_list', 'send_message', 'send_to_remote_channel', 'delegate_task', 'create_group', 'set_wallet',
55
+ ]);
56
+ /** 轮询类: 同参数重复**本来就正当** (等异步任务), 永不触发相同调用提示 */
57
+ exports.REPEATABLE_TOOLS = new Set(['process_manage', 'check_task_status']);
58
+ /** 生成/MCP 轮询工具的命名约定 (与上面同理) */
59
+ exports.REPEATABLE_SUFFIXES = ['_poll', '_get_result'];
60
+ /** 失败的"正常输出"类: 红了/空结果/超时属于工作产出, 不参与停滞判定 */
61
+ exports.FAILURE_TOLERANT_TOOLS = new Set(['terminal', 'shell_exec', 'execute_code', 'web_search', 'web_extract']);
62
+ /** 第几次**连续相同 (工具+参数+结果)** 触发引导 (3 = 容忍一次复核) */
63
+ exports.IDENTICAL_CALL_THRESHOLD = 3;
64
+ /** 抓循环时最长的周期 (A→B→A→B 的周期是 2) */
65
+ exports.MAX_CYCLE_PERIOD = 4;
66
+ /** 历史窗口: 够放最长的周期若干圈 + 余量 */
67
+ exports.CYCLE_HISTORY = 64;
68
+ /** 结果达到这个字符数才值得用 stub 替代 (太短本来就省不了多少) */
69
+ exports.STUB_MIN_CHARS = 512;
70
+ /**
71
+ * **同签名 + 同结果**的重复调用: 门槛降到这个值 (2026-10-01, 优化 #1 的收尾)。
72
+ * 为什么单独一条: 512 是"值不值得压缩"的门槛 ✗, 而"同一个调用又跑了一遍、结果一字不差"**本身就是浪费** ✓
73
+ * —— 实测 `get_identity` 输出才 ~90 字符 ⇒ 卡在 512 门外, 于是被连调 3–4 次 ✓。
74
+ * 现在: 同签名重复 且 结果一致 且 ≥64 字符 ⇒ 从第 2 次起换引用 stub ✓ (少于 64 字符的本来也占不了多少上下文, 放行 ✓)。
75
+ */
76
+ exports.REPEAT_STUB_MIN_CHARS = 64;
77
+ /** stub 里保留的参数预览长度 (万一压缩把原结果挤掉, 还能看出当初调了什么) */
78
+ exports.STUB_ARGS_PREVIEW_CHARS = 120;
79
+ /** 参数的规范 JSON (键排序 + 紧凑分隔符) —— 让 {a,b} 与 {b,a} 同签名 */
80
+ function canonicalToolArgs(args) {
81
+ if (args === null || typeof args !== 'object' || Array.isArray(args))
82
+ return '';
83
+ const obj = args;
84
+ const keys = Object.keys(obj).sort();
85
+ const parts = keys.map((k) => `${JSON.stringify(k)}:${stableStringify(obj[k])}`);
86
+ return `{${parts.join(',')}}`;
87
+ }
88
+ function stableStringify(v) {
89
+ if (v === null || typeof v !== 'object')
90
+ return JSON.stringify(v) ?? 'null';
91
+ if (Array.isArray(v))
92
+ return `[${v.map(stableStringify).join(',')}]`;
93
+ const o = v;
94
+ return `{${Object.keys(o).sort().map((k) => `${JSON.stringify(k)}:${stableStringify(o[k])}`).join(',')}}`;
95
+ }
96
+ /** 调用签名: 不可逆 (只留哈希), 不泄漏参数原文 */
97
+ function toolCallSignature(toolName, args) {
98
+ return (0, node_crypto_1.createHash)('sha256').update(`${toolName}\u0000${canonicalToolArgs(args)}`).digest('hex').slice(0, 16);
99
+ }
100
+ /** 结果指纹 (判"完全相同的返回") */
101
+ function resultFingerprint(resultText) {
102
+ return (0, node_crypto_1.createHash)('sha256').update(String(resultText ?? '')).digest('hex').slice(0, 16);
103
+ }
104
+ function isRepeatableTool(toolName) {
105
+ if (exports.REPEATABLE_TOOLS.has(toolName))
106
+ return true;
107
+ return exports.REPEATABLE_SUFFIXES.some((s) => toolName.endsWith(s));
108
+ }
109
+ /**
110
+ * 记录一次调用并给出观测。**纯函数式**: 调用方每次都要把上一次的 streak 传进来
111
+ * (见 `LoopStallState`), 这样状态归属清晰、也便于单测。
112
+ */
113
+ function observeToolCall(state, input) {
114
+ const ok = input.ok !== false;
115
+ const tolerant = exports.FAILURE_TOLERANT_TOOLS.has(input.toolName);
116
+ const repeatable = isRepeatableTool(input.toolName);
117
+ const text = String(input.resultText ?? '');
118
+ const chars = input.resultChars ?? text.length;
119
+ // ① 轮询类: 同参数重复本就正当 ⇒ 只记录, 不出声
120
+ if (repeatable) {
121
+ state.push(input.toolName, input.args, text);
122
+ return { action: 'allow', code: 'allow', count: 0 };
123
+ }
124
+ const sig = toolCallSignature(input.toolName, input.args);
125
+ const fp = resultFingerprint(text);
126
+ const prev = state.last;
127
+ const sameAsPrev = !!prev && prev.sig === sig && prev.fp === fp;
128
+ // ② 连续相同 (工具 + 参数 + 结果): 每次 +1, 否则归 1
129
+ state.streak = sameAsPrev ? state.streak + 1 : 1;
130
+ state.push(input.toolName, input.args, text);
131
+ // ③ 失败宽容类工具的失败不参与停滞判定 (红测试/空 grep 是产出, 不是卡住)
132
+ if (!ok && tolerant) {
133
+ return { action: 'allow', code: 'allow', count: state.streak };
134
+ }
135
+ // ③.5 恒定结果工具 (get_identity 这类): 从第 2 次起换标准答复 —— 不管结果长短
136
+ if (sameAsPrev && exports.CONSTANT_RESULT_TOOLS.has(input.toolName) && ok) {
137
+ return {
138
+ action: 'allow',
139
+ code: 'allow',
140
+ count: state.streak,
141
+ stub: `[已答] ${input.toolName} 的结果在本次会话内**恒定不变**(它读的是固定身份/配置, 不是活数据)。` +
142
+ `上面那一次返回就是答案, 直接用它作答即可; 再调一次只会得到同样的内容。` +
143
+ `若确实需要变化, 请改用写类工具(如 set_persona / 相应 update 工具)。`,
144
+ };
145
+ }
146
+ // ④ 结果引用 stub: 从**第 2 次**完全相同的返回起 (够长才替代; 失败永不替代)
147
+ let stub;
148
+ // 2026-10-01 (优化 #1 收尾): 同签名重复 + 结果一字不差 ⇒ 用更低门槛 (重复本身就是浪费, 不管长短)
149
+ const repeatFloor = input.sameSignatureBefore ? exports.REPEAT_STUB_MIN_CHARS : exports.STUB_MIN_CHARS;
150
+ if (ok && input.seenResultBefore && chars >= repeatFloor) {
151
+ stub = `[结果引用] 与本次会话中此前一次 ${input.toolName} 的返回**逐字相同** (${chars} 字符, 已折叠)。`
152
+ + `参数预览: ${canonicalToolArgs(input.args).slice(0, exports.STUB_ARGS_PREVIEW_CHARS)}`;
153
+ }
154
+ if (state.streak >= exports.IDENTICAL_CALL_THRESHOLD) {
155
+ // ⑤ 连续相同达阈值 ⇒ 温和引导 (不拒绝执行)
156
+ return {
157
+ action: 'warn',
158
+ code: 'identical_call_streak',
159
+ count: state.streak,
160
+ stub,
161
+ notice: `[系统提示] 这是第 ${state.streak} 次**用完全相同的参数**调用 ${input.toolName}, 且返回与上次完全相同。`
162
+ + `重复调用不会得到新信息 —— 请换参数、换工具, 或基于已有结果直接回答。`,
163
+ };
164
+ }
165
+ // ⑥ 循环检测: 最近 N 次里出现了周期 ≤4 的重复串 (相邻计数会被交替调用清零, 只抓相邻必漏)
166
+ const cycle = detectCycle(state.history);
167
+ if (cycle) {
168
+ return {
169
+ action: 'warn',
170
+ code: 'identical_cycle',
171
+ count: cycle.laps,
172
+ stub,
173
+ notice: `[系统提示] 检测到最近 ${cycle.laps} 圈重复同一组 ${cycle.period} 次调用`
174
+ + `(以 ${input.toolName} 结尾), 参数与返回都逐字相同。请不要重复这一组 —— 换参数、换工具, 或基于已有结果直接回答。`,
175
+ };
176
+ }
177
+ return { action: 'allow', code: 'allow', count: state.streak, stub };
178
+ }
179
+ /** 每轮 ReAct 循环一份的停滞状态 */
180
+ class LoopStallState {
181
+ streak = 0;
182
+ last = null;
183
+ history = [];
184
+ /** 已见过的结果指纹 (用于"完全相同返回"的 stub 判定) */
185
+ seenResults = new Set();
186
+ push(toolName, args, resultText) {
187
+ const step = { sig: toolCallSignature(toolName, args), fp: resultFingerprint(resultText) };
188
+ this.last = step;
189
+ this.history.push(step);
190
+ if (this.history.length > exports.CYCLE_HISTORY)
191
+ this.history.shift();
192
+ this.seenResults.add(step.fp);
193
+ }
194
+ /** 这个结果指纹此前是否出现过 (供 observeToolCall 的 seenResultBefore) */
195
+ hasSeenResult(text) {
196
+ return this.seenResults.has(resultFingerprint(text));
197
+ }
198
+ reset() {
199
+ this.streak = 0;
200
+ this.last = null;
201
+ this.history.length = 0;
202
+ this.seenResults.clear();
203
+ }
204
+ }
205
+ exports.LoopStallState = LoopStallState;
206
+ /**
207
+ * 找"最近若干圈完全重复"的串: 对每个候选周期 p ∈ [1, MAX_CYCLE_PERIOD],
208
+ * 看末尾是否由同一个 p 长度的块**重复 ≥ THRESHOLD 次**组成 (块内每个 (签名,结果指纹) 都相同)。
209
+ * 返回圈数与周期, 没有则 null。
210
+ */
211
+ function detectCycle(history) {
212
+ const h = history;
213
+ for (let p = 1; p <= exports.MAX_CYCLE_PERIOD; p++) {
214
+ const need = p * exports.IDENTICAL_CALL_THRESHOLD;
215
+ if (h.length < need)
216
+ continue;
217
+ const tail = h.slice(-need);
218
+ let same = true;
219
+ for (let i = p; i < need && same; i++) {
220
+ if (tail[i].sig !== tail[i % p].sig || tail[i].fp !== tail[i % p].fp)
221
+ same = false;
222
+ }
223
+ if (same)
224
+ return { period: p, laps: exports.IDENTICAL_CALL_THRESHOLD };
225
+ }
226
+ return null;
227
+ }
228
+ // ───────────────────────────────────────────────────────────────────────────
229
+ // 2026-10-01 第二轮 (继续学): 三处补上
230
+ // ① **无进展**是独立一轴: 幂等工具即使**换了参数**, 只要结果与上次相同 ⇒ 也是无进展
231
+ // (原先只抓"同参数" ⇒ 换个措辞再问一遍就绕过去了)
232
+ // ② **进展的定义 = 有副作用的调用成功过** (纯读再多都不算) ⇒ 用它清零失败/无进展计数
233
+ // ③ 升级策略**按在场与否分流**: 有人在 ⇒ 只提醒(从不阻止执行); 无人值守 ⇒ 才允许拦/停
234
+ // (人在场时不该替用户做决定; 但 cron/supervisor 这种无人值守的场景, 该果断收)
235
+ // ───────────────────────────────────────────────────────────────────────────
236
+ /** 有副作用 = 会改变世界 (文件/进程/网络/资金/记忆). 唯一判据, 供"进展"与"无进展"用 */
237
+ function toolMayHaveSideEffect(toolName) {
238
+ if (exports.MUTATING_TOOLS.has(toolName))
239
+ return true;
240
+ if (exports.IDEMPOTENT_TOOLS.has(toolName))
241
+ return false;
242
+ if (isRepeatableTool(toolName))
243
+ return false;
244
+ // 未登记的工具按"可能有副作用"处理 (保守: 不轻易判定"它没改变世界")
245
+ return true;
246
+ }
247
+ exports.DEFAULT_THRESHOLDS = {
248
+ exactFailureWarnAfter: 2,
249
+ exactFailureBlockAfter: 5,
250
+ sameToolFailureWarnAfter: 3,
251
+ sameToolFailureHaltAfter: 8,
252
+ noProgressWarnAfter: 2,
253
+ noProgressBlockAfter: 5,
254
+ hardStopEnabled: false,
255
+ };
256
+ /** 无人值守场景 (cron / supervisor / 非交互) —— 那里才默认允许拦与停 */
257
+ function defaultHardStopFor(context = {}) {
258
+ if (typeof context.unattended === 'boolean')
259
+ return context.unattended;
260
+ const env = context.env || process.env;
261
+ return env.BOLLOON_UNATTENDED === '1' || env.BOLLOON_CRON === '1' || env.BOLLOON_SUPERVISOR === '1';
262
+ }
263
+ function newProgressBookkeeping() {
264
+ return { progressClearedSignatures: new Set(), noProgress: new Map() };
265
+ }
266
+ /**
267
+ * 记一次调用结果, 维护"进展 / 无进展"两本账。
268
+ * - 有副作用的调用**成功** ⇒ 视为进展: 清掉该签名的失败标记 + 清掉**所有**无进展记录
269
+ * (世界变了 ⇒ 之前"读了没变化"的判定作废)
270
+ * - 幂等工具: 结果指纹与上次相同 ⇒ 无进展 +1 (**参数变没变不影响**), 不同 ⇒ 归 1
271
+ */
272
+ function trackProgress(book, input, thresholds = exports.DEFAULT_THRESHOLDS) {
273
+ const ok = input.ok !== false;
274
+ const sig = toolCallSignature(input.toolName, input.args);
275
+ const fp = resultFingerprint(String(input.resultText ?? ''));
276
+ if (ok && toolMayHaveSideEffect(input.toolName)) {
277
+ book.progressClearedSignatures.add(sig);
278
+ if (book.noProgress.size > 0)
279
+ book.noProgress.clear();
280
+ return { action: 'allow', code: 'allow', count: 0 };
281
+ }
282
+ if (!toolMayHaveSideEffect(input.toolName)) {
283
+ const prev = book.noProgress.get(input.toolName);
284
+ const count = prev && prev.lastResultFp === fp ? prev.count + 1 : 1;
285
+ book.noProgress.set(input.toolName, { lastResultFp: fp, count });
286
+ if (count >= thresholds.noProgressWarnAfter) {
287
+ return {
288
+ action: 'warn',
289
+ code: 'idempotent_no_progress',
290
+ count,
291
+ notice: `[系统提示] 连续 ${count} 次读取类调用 (${input.toolName}) 返回的都是**同一份内容**`
292
+ + `(参数不同也一样) —— 世界没有变化, 再读还是它。请基于已有内容作答, 或改去查别的来源。`,
293
+ };
294
+ }
295
+ return { action: 'allow', code: 'allow', count };
296
+ }
297
+ return { action: 'allow', code: 'allow', count: 0 };
298
+ }
299
+ /**
300
+ * 2026-10-01 (用户: 「为什么这么慢」): 量到的事实 —— 每次 LLM 往返平均 **3338ms**, 而
301
+ * `toolCalls>1`(一轮发多个工具)**只占 12/63** ✗ ⇒ 回合时长 ≈ 往返次数 × 3.3s ✓;
302
+ * 也就是说"慢"主要不是工具慢(工具合计仅占 4% ✗), 而是**同一轮只干一件事**、来回跑 ✓。
303
+ * 做法: 一轮只调了一个**只读**工具时, 在结果后附一句**带代价**的提醒(不是口号 ✓)。
304
+ * 只读工具才提醒(写类工具串行更安全 ✓ 不催)。
305
+ */
306
+ const BATCHABLE_HINT_TOOLS = new Set([
307
+ 'read_file', 'grep_files', 'glob_files', 'list_files', 'read_document',
308
+ 'git_status', 'git_log', 'git_diff', 'get_identity', 'list_tools', 'list_skills',
309
+ 'process', 'list_local_channels', 'get_balance',
310
+ ]);
311
+ function batchHint(toolName, toolCallsThisRound) {
312
+ if (toolCallsThisRound !== 1)
313
+ return '';
314
+ if (!BATCHABLE_HINT_TOOLS.has(String(toolName || '')))
315
+ return '';
316
+ return '\n⚡ 若你接下来还要查别的(或还要读别的文件), **同一轮可以一次发多个工具** —— '
317
+ + '每次来回约 3.3 秒, 分成多轮就是纯等待; 独立的读操作请并成一轮发。';
318
+ }
319
+ //# sourceMappingURL=tool-loop-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-loop-guard.js","sourceRoot":"","sources":["../../../src/agents/tool-loop-guard.ts"],"names":[],"mappings":"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"}