@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
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Context Compaction Pipeline — 5 层编排
3
+ *
4
+ * 严格对齐 Claude Code 论文: 每次 LLM call 前顺序执行 5 个 shaper, 由便宜到重, 任一层 fit 就短路.
5
+ *
6
+ * 1. Budget Reduction (总是, 截断 > 阈值的单条消息)
7
+ * 2. Snip (feature flag BOLLOON_SNIP_ENABLED)
8
+ * 3. Microcompact (总是, 折叠老 tool_result)
9
+ * 4. Context Collapse (feature flag BOLLOON_CONTEXT_COLLAPSE, 读时虚拟投影)
10
+ * 5. Auto-Compact (LLM 摘要, 兜底)
11
+ *
12
+ * 短路: 任一层后 budget fit (< 0.8) → 返回该层结果, 不跑后续.
13
+ *
14
+ * 关键不变量:
15
+ * - 任何异常 → 整 pipeline 返回原 history (与现状一致)
16
+ * - 第 1-3 层不破坏 messageHistory 内存引用 (内容可改)
17
+ * - 第 4 层读时投影, memory 不变
18
+ * - 第 5 层破坏性, 折叠 N 对成 1 条
19
+ *
20
+ * 失败静默: 整 pipeline 用 try/catch 包, 任何 stage 失败不影响整体
21
+ */
22
+ import { budgetGate } from './budget-gate.js';
23
+ import { budgetReduce } from './budget-reduce.js';
24
+ import { snip, isSnipEnabled } from './snip.js';
25
+ import { microcompact } from './microcompact.js';
26
+ import { contextCollapse, isContextCollapseEnabled } from './context-collapse.js';
27
+ import { autoCompact } from './auto-compact.js';
28
+ const DEFAULT_MAX_TOKENS = 8000;
29
+ export async function compactPipeline(history, opts = {}) {
30
+ const maxTokens = opts.maxTokens ?? DEFAULT_MAX_TOKENS;
31
+ const ctx = {
32
+ inputHistory: history,
33
+ history,
34
+ estimatedTokens: 0,
35
+ opts,
36
+ stages: [],
37
+ };
38
+ try {
39
+ // Stage 1: Budget Reduction
40
+ let result = budgetReduce(history, opts);
41
+ ctx.history = result.history;
42
+ ctx.stages.push(stageRecord('budgetReduce', result, history));
43
+ let gate = budgetGate(ctx.history, maxTokens);
44
+ ctx.estimatedTokens = gate.estimatedTokens;
45
+ if (gate.fit)
46
+ return finalize(ctx, result.applied); // 短路但可能 budgetReduce 实际改了内容
47
+ // Stage 2: Snip (feature flag)
48
+ if (isSnipEnabled()) {
49
+ const before = ctx.history;
50
+ result = snip(ctx.history, opts);
51
+ ctx.history = result.history;
52
+ ctx.stages.push(stageRecord('snip', result, before));
53
+ gate = budgetGate(ctx.history, maxTokens);
54
+ ctx.estimatedTokens = gate.estimatedTokens;
55
+ if (gate.fit)
56
+ return finalize(ctx, true);
57
+ }
58
+ else {
59
+ ctx.stages.push({ stage: 'snip', applied: false, before: ctx.history.length, after: ctx.history.length, detail: 'feature flag off' });
60
+ }
61
+ // Stage 3: Microcompact
62
+ const before3 = ctx.history;
63
+ result = microcompact(ctx.history, opts);
64
+ ctx.history = result.history;
65
+ ctx.stages.push(stageRecord('microcompact', result, before3));
66
+ gate = budgetGate(ctx.history, maxTokens);
67
+ ctx.estimatedTokens = gate.estimatedTokens;
68
+ if (gate.fit)
69
+ return finalize(ctx, result.applied || true);
70
+ // Stage 4: Context Collapse (feature flag)
71
+ if (isContextCollapseEnabled()) {
72
+ const before4 = ctx.history;
73
+ result = contextCollapse(ctx.history, opts);
74
+ ctx.history = result.history;
75
+ ctx.stages.push(stageRecord('contextCollapse', result, before4));
76
+ gate = budgetGate(ctx.history, maxTokens);
77
+ ctx.estimatedTokens = gate.estimatedTokens;
78
+ if (gate.fit)
79
+ return finalize(ctx, true);
80
+ }
81
+ else {
82
+ ctx.stages.push({ stage: 'contextCollapse', applied: false, before: ctx.history.length, after: ctx.history.length, detail: 'feature flag off' });
83
+ }
84
+ // Stage 5: Auto-Compact (兜底)
85
+ const before5 = ctx.history;
86
+ result = await autoCompact(ctx.history, opts);
87
+ ctx.history = result.history;
88
+ ctx.stages.push(stageRecord('autoCompact', result, before5));
89
+ return finalize(ctx, true);
90
+ }
91
+ catch (err) {
92
+ console.warn('[compactor] pipeline failed (silent, returning original):', err);
93
+ return {
94
+ history,
95
+ estimatedTokens: 0,
96
+ stages: ctx.stages,
97
+ compacted: false,
98
+ };
99
+ }
100
+ }
101
+ function stageRecord(name, result, before) {
102
+ return {
103
+ stage: name,
104
+ applied: result.applied,
105
+ before: before.length,
106
+ after: result.history.length,
107
+ detail: result.detail,
108
+ };
109
+ }
110
+ function finalize(ctx, compacted) {
111
+ return {
112
+ history: ctx.history,
113
+ estimatedTokens: ctx.estimatedTokens,
114
+ stages: ctx.stages,
115
+ compacted,
116
+ };
117
+ }
118
+ // ============================================================
119
+ // 测试钩子
120
+ // ============================================================
121
+ export function _resetPipelineForTest() {
122
+ // pipeline 是 stateless, 但保留 API 一致性
123
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Snip — 第 2 层: 裁掉老 history
3
+ *
4
+ * 论文: feature flag 关闭 (默认), 用户开启后才生效
5
+ * 开启环境变量: BOLLOON_SNIP_ENABLED=1
6
+ *
7
+ * 行为: 只保留最近 N 对 user/assistant (默认 20 对)
8
+ * 工具结果消息按其所属 round 一起保留
9
+ *
10
+ * 失败静默: 异常 → 返回原 history
11
+ */
12
+ const DEFAULT_KEEP_PAIRS = 20;
13
+ export function isSnipEnabled() {
14
+ return process.env.BOLLOON_SNIP_ENABLED === '1';
15
+ }
16
+ export function snip(history, opts = {}) {
17
+ try {
18
+ if (opts.skip || !isSnipEnabled()) {
19
+ return { history, applied: false, detail: isSnipEnabled() ? 'skipped' : 'feature flag off' };
20
+ }
21
+ const keepPairs = opts.snipKeepPairs ?? DEFAULT_KEEP_PAIRS;
22
+ // 从后往前数 N 对 user/assistant 边界
23
+ let pairsFound = 0;
24
+ let cutFrom = -1;
25
+ for (let i = history.length - 1; i >= 0; i--) {
26
+ const m = history[i];
27
+ if (m.role === 'user') {
28
+ pairsFound++;
29
+ if (pairsFound >= keepPairs) {
30
+ cutFrom = i;
31
+ break;
32
+ }
33
+ }
34
+ }
35
+ if (cutFrom <= 0) {
36
+ return { history, applied: false, detail: 'history too short' };
37
+ }
38
+ const out = history.slice(cutFrom);
39
+ return { history: out, applied: true, detail: `kept last ${keepPairs} pairs, dropped ${cutFrom} older messages` };
40
+ }
41
+ catch (err) {
42
+ console.warn('[compactor] snip failed (silent, returning original):', err);
43
+ return { history, applied: false, detail: 'error' };
44
+ }
45
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Token Estimator — 4 字符 ≈ 1 token 的粗估
3
+ *
4
+ * 为什么不引 tiktoken 依赖:
5
+ * - bolloon 默认 npm 用户, 引依赖增加 install 体积
6
+ * - Claude Code 论文也指出: 精确 token 计数不是关键, 渐进压缩才是
7
+ * - 4 字符/token 在中文/英文混合场景下误差约 ±20%, 对预算判定足够
8
+ *
9
+ * 失败静默: 任何异常 → 返回估算值 (不抛错)
10
+ */
11
+ const CHARS_PER_TOKEN = 4;
12
+ export function estimateTokens(messages) {
13
+ let total = 0;
14
+ for (const m of messages) {
15
+ total += Math.ceil((m.content?.length || 0) / CHARS_PER_TOKEN);
16
+ if (m.toolResult) {
17
+ try {
18
+ const s = typeof m.toolResult === 'string' ? m.toolResult : JSON.stringify(m.toolResult);
19
+ total += Math.ceil(s.length / CHARS_PER_TOKEN);
20
+ }
21
+ catch { /* circular ref, ignore */ }
22
+ }
23
+ if (m.toolCall) {
24
+ try {
25
+ const s = typeof m.toolCall === 'string' ? m.toolCall : JSON.stringify(m.toolCall);
26
+ total += Math.ceil(s.length / CHARS_PER_TOKEN);
27
+ }
28
+ catch { /* ignore */ }
29
+ }
30
+ }
31
+ return total;
32
+ }
33
+ export function estimateStringTokens(s) {
34
+ return Math.ceil(s.length / CHARS_PER_TOKEN);
35
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Context Compaction — 类型定义
3
+ *
4
+ * 严格对齐 Claude Code 论文 5 层压缩流水线:
5
+ * 1. Budget Reduction (单条消息大小限制)
6
+ * 2. Snip (裁掉老历史, feature flag 关闭)
7
+ * 3. Microcompact (cache-aware 细粒度压缩, 老 tool_result 折叠)
8
+ * 4. Context Collapse (读时虚拟投影, 非破坏)
9
+ * 5. Auto-Compact (LLM 摘要, 兜底)
10
+ *
11
+ * 关键不变量:
12
+ * - 第 1-3 层不破坏 messageHistory 内存结构, 只改 buildContext 输出
13
+ * - 第 4 层读时投影, 绝不改 messageHistory
14
+ * - 第 5 层破坏 messageHistory, 把 N 对折叠成 1 条 summary
15
+ *
16
+ * 类型设计: Message 在本模块内独立定义, 靠 structural typing 与 pi-sdk.ts 的 Message 兼容.
17
+ * 不 import pi-sdk 避免循环依赖.
18
+ */
19
+ export {};
@@ -231,9 +231,10 @@ export class HealthMonitor {
231
231
  async pingLLM(minimax) {
232
232
  const start = Date.now();
233
233
  try {
234
- // 简单的 chat 测试
234
+ // 2026-06-15: signal 位置正确传 undefined (chat signature 是 (message, context?, signal?))
235
+ // 之前传 { maxTokens: 1 } 被当 signal, Node 22+ undici 强类型 AbortSignal 校验 throw
235
236
  if (minimax.chat) {
236
- await minimax.chat('ping', 'test', { maxTokens: 1 });
237
+ await minimax.chat('ping', 'test', undefined);
237
238
  }
238
239
  else if (minimax.ping) {
239
240
  await minimax.ping();
package/dist/index.js CHANGED
@@ -978,6 +978,34 @@ async function runNonInteractive(args, comm) {
978
978
  console.log(`✅ 结果已保存到: ${output}`);
979
979
  return;
980
980
  }
981
+ if (tool === 'prompt' && prompt) {
982
+ // 2026-06-15: --prompt "text" 走直接调 a.prompt(prompt) 路径, 避开 runToolCommand
983
+ // (case 'prompt' 内的 [text] = args 从 toolArgs 取值是空数组, 永远报"缺少 prompt 文本"是 CLI bug)
984
+ const startTime = Date.now();
985
+ const a = await getAgent();
986
+ try {
987
+ const response = await a.prompt(prompt);
988
+ const elapsed = Date.now() - startTime;
989
+ if (json) {
990
+ console.log(JSON.stringify({ success: true, response, elapsedMs: elapsed }, null, 2));
991
+ }
992
+ else {
993
+ console.log(response);
994
+ console.log(`\n耗时: ${elapsed}ms`);
995
+ }
996
+ }
997
+ catch (e) {
998
+ const error = e?.message || String(e);
999
+ if (json) {
1000
+ console.log(JSON.stringify({ success: false, error }, null, 2));
1001
+ }
1002
+ else {
1003
+ console.log(`\n错误: ${error}`);
1004
+ }
1005
+ process.exit(1);
1006
+ }
1007
+ return;
1008
+ }
981
1009
  if (tool) {
982
1010
  await runToolCommand(tool, toolArgs, !!json, comm);
983
1011
  }
@@ -1367,7 +1395,9 @@ async function main() {
1367
1395
  s.banner();
1368
1396
  s.section('系统初始化');
1369
1397
  const hasOpenAI = !!process.env.OPENAI_API_KEY;
1370
- const hasAnthropic = !!process.env.ANTHROPIC_API_KEY;
1398
+ // 2026-06-15: 修复 — 之前 anthropic 401 是因为 shell env 残留的旧 ANTHROPIC_API_KEY 抢了 provider 选择
1399
+ // 用 BOLLOON_LLM_PROVIDER env 显式覆盖, 否则还是按 env hasXxx 顺序自动选
1400
+ const hasAnthropic = !!process.env.ANTHROPIC_API_KEY && !process.env.BOLLOON_LLM_PROVIDER;
1371
1401
  const hasMinimax = !!process.env.MINIMAX_API_KEY;
1372
1402
  const hasDeepSeek = !!process.env.DEEPSEEK_API_KEY;
1373
1403
  const hasKimi = !!(process.env.KIMI_API_KEY || process.env.MOONSHOT_API_KEY);
@@ -1433,12 +1463,29 @@ async function main() {
1433
1463
  s.warn('将使用无 P2P 模式运行');
1434
1464
  }
1435
1465
  await bootstrapIroh(keypair, name);
1466
+ // Bolloon Bootstrap: 启动扫描 + Context 收集 + 挂定时任务
1467
+ // 失败静默 (主流程不被阻塞)
1468
+ try {
1469
+ const { bootstrapBolloon } = await import('./pi-ecosystem-judgment/human-value-pipeline.js');
1470
+ s.info('正在 bootstrap bolloon 上下文...');
1471
+ const bs = await bootstrapBolloon({ cwd: process.cwd() });
1472
+ s.info(`Bootstrap 完成 (${bs.durationMs}ms, ${bs.errors.length} 个非致命错误)`);
1473
+ }
1474
+ catch (err) {
1475
+ s.warn(`Bootstrap 失败 (非致命, 主流程继续): ${err.message}`);
1476
+ }
1436
1477
  s.divider();
1437
1478
  if (mode === 'web') {
1438
1479
  const port = parseInt(process.env.PORT || '54188');
1480
+ // 2026-06-16: BOLLOON_DEV_MODE=1 或 selfImprove=true 启动项 → 开发者模式, 启用自迭代 (健康监控+自改总线)
1481
+ // 默认用户模式: 不自迭代, 自改卡片不自动出现, 仍可 POST /api/self-improve/trigger 手动触发
1482
+ const selfImprove = process.env.BOLLOON_DEV_MODE === '1' || process.env.BOLLOON_DEV_MODE === 'true';
1483
+ if (selfImprove) {
1484
+ console.log('[startup] BOLLOON_DEV_MODE=1, 开发者模式: 自迭代已启用');
1485
+ }
1439
1486
  const { createWebServer, openBrowser } = await import('./web/server.js');
1440
1487
  s.info(`启动 Web 服务端口 ${port}...`);
1441
- const { port: actualPort } = await createWebServer(port);
1488
+ const { port: actualPort } = await createWebServer(port, { selfImprove });
1442
1489
  s.success(`浏览器已打开 → http://localhost:${actualPort}`);
1443
1490
  openBrowser(`http://localhost:${actualPort}`);
1444
1491
  }
@@ -6,19 +6,31 @@
6
6
  */
7
7
  import { llmConfigStore } from './config-store.js';
8
8
  import { PiAIModel } from './pi-ai.js';
9
+ import * as fs from 'fs/promises';
10
+ import * as path from 'path';
11
+ import { fileURLToPath } from 'url';
12
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
13
+ const LAYERS_DIR = path.join(__dirname, 'system-prompt', 'layers');
14
+ /**
15
+ * 从 layer 读 .md 文件作为系统 prompt
16
+ * 失败时降级到兜底字符串 (不挂)
17
+ */
18
+ async function loadRoleLayer(layerId, fallback) {
19
+ const [group, ...rest] = layerId.split('.');
20
+ const path2md = path.join(LAYERS_DIR, group, `${rest.join('.')}.md`);
21
+ try {
22
+ return await fs.readFile(path2md, 'utf-8');
23
+ }
24
+ catch {
25
+ return fallback;
26
+ }
27
+ }
9
28
  // 预定义的判断 Prompt 配置
10
29
  export const JUDGMENT_PROMPTS = {
11
30
  // 默认判断 Prompt
12
31
  default: {
13
- systemPrompt: `你是一个专业的 AI 任务分析专家。你的职责是深入理解用户的问题,并给出精准的判断。
14
-
15
- 核心原则:
16
- 1. 第一性原理:追问问题的本质,而非表面现象
17
- 2. 多角度思考:考虑不同视角和影响因素
18
- 3. 上下文感知:理解对话历史和隐含意图
19
- 4. 动态评估:根据实际情况判断复杂性
20
-
21
- 你的判断会影响后续的智能体协作方式,请认真分析。`,
32
+ systemPrompt: '',
33
+ systemPromptResolver: () => loadRoleLayer('role.expert', '你是一个专业的 AI 任务分析专家. '),
22
34
  userPromptTemplate: `【当前输入】
23
35
  {user_input}
24
36
 
@@ -73,16 +85,8 @@ export const JUDGMENT_PROMPTS = {
73
85
  },
74
86
  // 架构相关问题
75
87
  architecture: {
76
- systemPrompt: `你是一个经验丰富的系统架构师。你擅长:
77
- - 从需求中提取本质问题
78
- - 设计可扩展的系统架构
79
- - 权衡技术方案
80
- - 识别架构风险
81
-
82
- 你相信:
83
- - 本质和实现必须分离
84
- - 好的架构从简单规则中生长
85
- - 复杂性应该被控制而非消除`,
88
+ systemPrompt: '',
89
+ systemPromptResolver: () => loadRoleLayer('role.architect', '你是一个经验丰富的系统架构师. '),
86
90
  userPromptTemplate: `【架构设计问题】
87
91
  {user_input}
88
92
 
@@ -108,11 +112,8 @@ export const JUDGMENT_PROMPTS = {
108
112
  },
109
113
  // 代码相关问题
110
114
  code: {
111
- systemPrompt: `你是一个高效的代码实现专家。你擅长:
112
- - 快速理解和实现需求
113
- - 编写清晰、可维护的代码
114
- - 遵循最佳实践
115
- - 处理边界情况`,
115
+ systemPrompt: '',
116
+ systemPromptResolver: () => loadRoleLayer('role.implementer', '你是一个高效的代码实现专家. '),
116
117
  userPromptTemplate: `【代码问题】
117
118
  {user_input}
118
119
 
@@ -134,11 +135,8 @@ export const JUDGMENT_PROMPTS = {
134
135
  },
135
136
  // 安全相关问题
136
137
  security: {
137
- systemPrompt: `你是一个严格的安全专家。你擅长:
138
- - 识别安全风险
139
- - 评估威胁模型
140
- - 设计安全方案
141
- - 遵循安全最佳实践`,
138
+ systemPrompt: '',
139
+ systemPromptResolver: () => loadRoleLayer('role.security', '你是一个严格的安全专家. '),
142
140
  userPromptTemplate: `【安全问题】
143
141
  {user_input}
144
142
 
@@ -221,8 +219,12 @@ export class LLMJudgmentClient {
221
219
  }
222
220
  try {
223
221
  // 调用 LLM
222
+ // 优先用 systemPromptResolver (从 layer 读), fallback 静态 systemPrompt
223
+ const systemPrompt = this.promptConfig.systemPromptResolver
224
+ ? await this.promptConfig.systemPromptResolver()
225
+ : this.promptConfig.systemPrompt;
224
226
  const messages = [
225
- { role: 'system', content: this.promptConfig.systemPrompt },
227
+ { role: 'system', content: systemPrompt },
226
228
  { role: 'user', content: userPrompt }
227
229
  ];
228
230
  const response = await this.model.chat(userPrompt);