@bolloon/bolloon-agent 0.4.5 → 0.4.6

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 (206) hide show
  1. package/README.md +135 -135
  2. package/bin/bolloon-cli.cjs +183 -183
  3. package/bin/bolloon.cjs +0 -0
  4. package/bin/bolloon.js +157 -0
  5. package/dist/agents/constraint-layer.js +19 -19
  6. package/dist/agents/judgment-protocol.js +14 -14
  7. package/dist/agents/pi-sdk-tools.js +62 -45
  8. package/dist/agents/pi-sdk-types.js +12 -12
  9. package/dist/agents/pi-sdk.js +103 -90
  10. package/dist/agents/skill-organizer.js +19 -19
  11. package/dist/agents/skill-writer.js +15 -3
  12. package/dist/agents/workflow-pivot-loop.js +13 -3
  13. package/dist/bollharness/src/scripts/deploy-guard.js +8 -8
  14. package/dist/bollharness-integration/context-router-judgment.js +4 -4
  15. package/dist/bollharness-integration/context-router.js +292 -292
  16. package/dist/bollharness-integration/gate-state-machine.js +13 -13
  17. package/dist/bollharness-integration/llm-judgment-engine.js +134 -134
  18. package/dist/bollharness-integration/skill-adapter.js +21 -21
  19. package/dist/bootstrap/chat-archiver.js +14 -14
  20. package/dist/bootstrap/context-os.js +24 -24
  21. package/dist/bootstrap/memory-compressor.js +14 -14
  22. package/dist/cli/ink-app.js +18 -0
  23. package/dist/cli-entry.js +36 -36
  24. package/dist/context-compaction/auto-compact.js +7 -7
  25. package/dist/electron/first-run.js +54 -54
  26. package/dist/electron-build/electron/first-run.js +54 -54
  27. package/dist/electron-preload.js.map +1 -1
  28. package/dist/electron.js.map +1 -1
  29. package/dist/index.js +222 -138
  30. package/dist/llm/llm-judgment-client.js +102 -102
  31. package/dist/llm/pi-ai.js +48 -48
  32. package/dist/llm/system-prompt/layers/channel/human-async.md +41 -41
  33. package/dist/llm/system-prompt/layers/channel/local.md +14 -14
  34. package/dist/llm/system-prompt/layers/channel/p2p-agent.md +18 -18
  35. package/dist/llm/system-prompt/layers/channel/p2p-peer-sync.md +51 -51
  36. package/dist/llm/system-prompt/layers/channel/p2p-proactive.md +43 -43
  37. package/dist/llm/system-prompt/layers/channel/p2p-visitor.md +19 -19
  38. package/dist/llm/system-prompt/layers/channel/session-handoff.md +61 -61
  39. package/dist/llm/system-prompt/layers/core/artifacts_storage.md +89 -89
  40. package/dist/llm/system-prompt/layers/core/evenhandedness.md +21 -21
  41. package/dist/llm/system-prompt/layers/core/external-engagement.md +73 -73
  42. package/dist/llm/system-prompt/layers/core/hibs_reminders.md +15 -15
  43. package/dist/llm/system-prompt/layers/core/identity.md +48 -48
  44. package/dist/llm/system-prompt/layers/core/knowledge.md +17 -17
  45. package/dist/llm/system-prompt/layers/core/memory_system.md +12 -12
  46. package/dist/llm/system-prompt/layers/core/network_filesystem.md +28 -28
  47. package/dist/llm/system-prompt/layers/core/refusal.md +37 -37
  48. package/dist/llm/system-prompt/layers/core/tone.md +31 -31
  49. package/dist/llm/system-prompt/layers/core/tools.thin.md +13 -13
  50. package/dist/llm/system-prompt/layers/core/wellbeing.md +41 -41
  51. package/dist/llm/system-prompt/layers/role/architect.md +20 -20
  52. package/dist/llm/system-prompt/layers/role/expert.md +19 -19
  53. package/dist/llm/system-prompt/layers/role/implementer.md +15 -15
  54. package/dist/llm/system-prompt/layers/role/security.md +15 -15
  55. package/dist/llm/system-prompt/layers/tool/artifacts.md +72 -72
  56. package/dist/llm/system-prompt/layers/tool/bash.md +25 -25
  57. package/dist/llm/system-prompt/layers/tool/goal_handoff.md +77 -77
  58. package/dist/llm/system-prompt/layers/tool/hibs_api.md +171 -171
  59. package/dist/llm/system-prompt/layers/tool/image_search.md +70 -70
  60. package/dist/llm/system-prompt/layers/tool/manifest.md +89 -89
  61. package/dist/llm/system-prompt/layers/tool/mcp_apps.md +53 -53
  62. package/dist/llm/system-prompt/layers/tool/p2p_request.md +61 -61
  63. package/dist/llm/system-prompt/layers/tool/web_search.md +83 -83
  64. package/dist/llm/tool-manifest/ask_user_input.js +1 -1
  65. package/dist/llm/tool-manifest/bash.js +3 -3
  66. package/dist/llm/tool-manifest/create_file.js +4 -4
  67. package/dist/llm/tool-manifest/fetch_sports_data.js +3 -3
  68. package/dist/llm/tool-manifest/image_search.js +2 -2
  69. package/dist/llm/tool-manifest/index.js +0 -59
  70. package/dist/llm/tool-manifest/mcp.js +2 -2
  71. package/dist/llm/tool-manifest/message_compose.js +3 -3
  72. package/dist/llm/tool-manifest/places.js +2 -2
  73. package/dist/llm/tool-manifest/present_files.js +1 -1
  74. package/dist/llm/tool-manifest/recipe.js +2 -2
  75. package/dist/llm/tool-manifest/str_replace.js +5 -5
  76. package/dist/llm/tool-manifest/view.js +3 -3
  77. package/dist/llm/tool-manifest/weather.js +4 -4
  78. package/dist/llm/tool-manifest/web.js +4 -4
  79. package/dist/orbitdb/agent-tools.js +139 -0
  80. package/dist/orbitdb/kanban-store.js +259 -0
  81. package/dist/orbitdb/task-store.js +112 -0
  82. package/dist/pi-ecosystem-colony/index.js +365 -0
  83. package/dist/pi-ecosystem-judgment/causal-judge.js +51 -51
  84. package/dist/pi-ecosystem-judgment/distill-prompt.js +42 -42
  85. package/dist/pi-ecosystem-judgment/distillation.js +14 -14
  86. package/dist/pi-ecosystem-judgment/monitor-gate.js +28 -28
  87. package/dist/pi-ecosystem-judgment/value-injection.js +102 -102
  88. package/dist/security/context-router-tool.js +15 -15
  89. package/dist/security/tool-gate.js +2 -0
  90. package/dist/social/ant-colony/AdaptiveHeartbeat.js +101 -0
  91. package/dist/social/ant-colony/PheromoneEngine.js +227 -0
  92. package/dist/social/ant-colony/index.js +6 -0
  93. package/dist/social/ant-colony/types.js +24 -0
  94. package/dist/storage/trajectory.js +101 -0
  95. package/dist/test/ai-judgment-test.js +80 -0
  96. package/dist/test/bollharness-integration.test.js +318 -0
  97. package/dist/test/channel-agent-multi-dialogue.js +205 -0
  98. package/dist/test/channel-heartbeat-agent-test.js +201 -0
  99. package/dist/test/constraint-layer.test.js +164 -0
  100. package/dist/test/diap-identity-test.js +172 -0
  101. package/dist/test/diap-quick-test.js +62 -0
  102. package/dist/test/global-shared-context.test.js +315 -0
  103. package/dist/test/harness-judgment-injection.test.js +246 -0
  104. package/dist/test/harness-workflow-integrator-test.js +228 -0
  105. package/dist/test/human-value-store.test.js +243 -0
  106. package/dist/test/hybrid-integration-test.js +118 -0
  107. package/dist/test/hybrid-messenger-verify.js +55 -0
  108. package/dist/test/iroh-bistream-debug.js +38 -0
  109. package/dist/test/iroh-communication.test.js +66 -0
  110. package/dist/test/iroh-debug-test.js +57 -0
  111. package/dist/test/iroh-diap-test.js +71 -0
  112. package/dist/test/iroh-direct-connect.js +55 -0
  113. package/dist/test/iroh-e2e-fixed.js +89 -0
  114. package/dist/test/iroh-e2e-same-process.js +63 -0
  115. package/dist/test/iroh-e2e.js +66 -0
  116. package/dist/test/iroh-final-e2e.js +72 -0
  117. package/dist/test/iroh-relay-test.js +37 -0
  118. package/dist/test/iroh-simple-test.js +41 -0
  119. package/dist/test/iroh-transport-verify.js +54 -0
  120. package/dist/test/iroh-transport.test.js +37 -0
  121. package/dist/test/iroh-two-nodes.js +70 -0
  122. package/dist/test/iroh-verify.js +44 -0
  123. package/dist/test/judgment-decision.test.js +219 -0
  124. package/dist/test/llm-judgment-integration.test.js +220 -0
  125. package/dist/test/p2p-agent-complex-dialogue.js +385 -0
  126. package/dist/test/p2p-agent-dialogue.js +341 -0
  127. package/dist/test/p2p-agent-full-bidirectional.js +510 -0
  128. package/dist/test/p2p-agent-harness-flow.js +437 -0
  129. package/dist/test/p2p-agent-harness-single.js +143 -0
  130. package/dist/test/p2p-ai-dialogue-test.js +318 -0
  131. package/dist/test/p2p-cid-connect-test.js +195 -0
  132. package/dist/test/p2p-connect-receiver.js +69 -0
  133. package/dist/test/p2p-doc-transfer.js +110 -0
  134. package/dist/test/p2p-identity-page-test.js +77 -0
  135. package/dist/test/p2p-iroh-test.js +171 -0
  136. package/dist/test/p2p-minimal-test.js +241 -0
  137. package/dist/test/p2p-node-1.js +148 -0
  138. package/dist/test/p2p-node-2.js +148 -0
  139. package/dist/test/p2p-server.js +281 -0
  140. package/dist/test/p2p-two-nodes-test.js +438 -0
  141. package/dist/test/pi-sdk.test.js +44 -0
  142. package/dist/test/set-persona.js +40 -0
  143. package/dist/test/simple.test.js +9 -0
  144. package/dist/test/storage-integration.test.js +150 -0
  145. package/dist/test/subagent-manager.test.js +276 -0
  146. package/dist/test/test-gate-flow.test.js +81 -0
  147. package/dist/test/workflow-engine.test.js +87 -0
  148. package/dist/test/workflow-pivot-loop.test.js +246 -0
  149. package/dist/web/api-config.html +779 -779
  150. package/dist/web/client-hearth.js +10 -10
  151. package/dist/web/components/wallet-viem.mjs +118 -118
  152. package/dist/web/index.html +472 -472
  153. package/dist/web/manifest.json +20 -20
  154. package/dist/web/server-storage.js +29 -0
  155. package/dist/web/server.js +30 -14
  156. package/dist/web/style.css +4946 -4946
  157. package/package.json +195 -195
  158. package/scripts/build-cli.js +215 -215
  159. package/scripts/build-web.ts +130 -130
  160. package/scripts/postinstall.js +152 -152
  161. package/bin/bolloon-daemon.sh +0 -207
  162. package/dist/constraint-runtime/reference_data/archive_surface_snapshot.json +0 -63
  163. package/dist/constraint-runtime/reference_data/commands_snapshot.json +0 -1037
  164. package/dist/constraint-runtime/reference_data/subsystems/assistant.json +0 -8
  165. package/dist/constraint-runtime/reference_data/subsystems/bootstrap.json +0 -8
  166. package/dist/constraint-runtime/reference_data/subsystems/bridge.json +0 -32
  167. package/dist/constraint-runtime/reference_data/subsystems/buddy.json +0 -13
  168. package/dist/constraint-runtime/reference_data/subsystems/cli.json +0 -26
  169. package/dist/constraint-runtime/reference_data/subsystems/components.json +0 -32
  170. package/dist/constraint-runtime/reference_data/subsystems/constants.json +0 -28
  171. package/dist/constraint-runtime/reference_data/subsystems/coordinator.json +0 -8
  172. package/dist/constraint-runtime/reference_data/subsystems/entrypoints.json +0 -15
  173. package/dist/constraint-runtime/reference_data/subsystems/hooks.json +0 -32
  174. package/dist/constraint-runtime/reference_data/subsystems/keybindings.json +0 -21
  175. package/dist/constraint-runtime/reference_data/subsystems/memdir.json +0 -15
  176. package/dist/constraint-runtime/reference_data/subsystems/migrations.json +0 -18
  177. package/dist/constraint-runtime/reference_data/subsystems/moreright.json +0 -8
  178. package/dist/constraint-runtime/reference_data/subsystems/native_ts.json +0 -11
  179. package/dist/constraint-runtime/reference_data/subsystems/outputStyles.json +0 -8
  180. package/dist/constraint-runtime/reference_data/subsystems/plugins.json +0 -9
  181. package/dist/constraint-runtime/reference_data/subsystems/remote.json +0 -11
  182. package/dist/constraint-runtime/reference_data/subsystems/schemas.json +0 -8
  183. package/dist/constraint-runtime/reference_data/subsystems/screens.json +0 -10
  184. package/dist/constraint-runtime/reference_data/subsystems/server.json +0 -10
  185. package/dist/constraint-runtime/reference_data/subsystems/services.json +0 -32
  186. package/dist/constraint-runtime/reference_data/subsystems/skills.json +0 -27
  187. package/dist/constraint-runtime/reference_data/subsystems/state.json +0 -13
  188. package/dist/constraint-runtime/reference_data/subsystems/types.json +0 -18
  189. package/dist/constraint-runtime/reference_data/subsystems/upstreamproxy.json +0 -9
  190. package/dist/constraint-runtime/reference_data/subsystems/utils.json +0 -32
  191. package/dist/constraint-runtime/reference_data/subsystems/vim.json +0 -12
  192. package/dist/constraint-runtime/reference_data/subsystems/voice.json +0 -8
  193. package/dist/constraint-runtime/reference_data/tools_snapshot.json +0 -922
  194. package/dist/electron/config.js.map +0 -1
  195. package/dist/electron/dialogs.js.map +0 -1
  196. package/dist/electron/first-run.js.map +0 -1
  197. package/dist/electron/ipc.js.map +0 -1
  198. package/dist/electron/logger.js.map +0 -1
  199. package/dist/electron/main.js.map +0 -1
  200. package/dist/electron/menu.js.map +0 -1
  201. package/dist/electron/paths.js.map +0 -1
  202. package/dist/electron/server.js.map +0 -1
  203. package/dist/electron/tray.js.map +0 -1
  204. package/dist/electron/window.js.map +0 -1
  205. package/dist/utils/auto-update.js.map +0 -1
  206. package/dist/web/client.js.map +0 -7
package/bin/bolloon.js ADDED
@@ -0,0 +1,157 @@
1
+ #!/usr/bin/env node
2
+ const path = require("path");
3
+ const { spawn } = require("child_process");
4
+ const fs = require("fs");
5
+
6
+ const RESET = "\x1b[0m";
7
+ const BOLD = "\x1b[1m";
8
+ const CYAN = "\x1b[36m";
9
+ const GREEN = "\x1b[32m";
10
+ const MAGENTA = "\x1b[35m";
11
+
12
+ function log(msg, color) {
13
+ console.log((color || RESET) + msg + RESET);
14
+ }
15
+
16
+ function printBanner() {
17
+ console.log("\n" + CYAN + BOLD + [
18
+ " ╔═══════════════════════════════════════════╗",
19
+ " ║ 🤖 Bolloon Agent ║",
20
+ " ║ P2P AI Document Processor ║",
21
+ " ╚═══════════════════════════════════════════╝"
22
+ ].join("\n") + RESET + "\n");
23
+ }
24
+
25
+ function getMainEntry() {
26
+ const distDir = path.dirname(require.main.filename);
27
+ const distIndex = path.join(distDir, "index.js");
28
+ if (fs.existsSync(distIndex)) {
29
+ return distIndex;
30
+ }
31
+ return path.join(process.cwd(), "src", "index.ts");
32
+ }
33
+
34
+ function parseArgs() {
35
+ const args = process.argv.slice(2);
36
+ if (args.length === 0) {
37
+ return { mode: "gui", args: [] };
38
+ }
39
+ const first = args[0];
40
+ switch (first) {
41
+ case "-v":
42
+ case "--version":
43
+ return { mode: "version", args: [] };
44
+ case "-h":
45
+ case "--help":
46
+ return { mode: "help", args: [] };
47
+ case "-g":
48
+ case "--gui":
49
+ return { mode: "gui", args: args.slice(1) };
50
+ case "-w":
51
+ case "--web":
52
+ return { mode: "web", args: args.slice(1) };
53
+ case "-c":
54
+ case "--cli":
55
+ return { mode: "cli", args: args.slice(1) };
56
+ default:
57
+ return { mode: "passthrough", args };
58
+ }
59
+ }
60
+
61
+ async function startElectron(additionalArgs) {
62
+ try {
63
+ const electron = require("electron");
64
+ const distDir = path.dirname(require.main.filename);
65
+ let mainPath = path.join(distDir, "electron.js");
66
+ if (!fs.existsSync(mainPath)) {
67
+ mainPath = path.join(process.cwd(), "src", "electron.ts");
68
+ }
69
+ log("启动 Electron...", CYAN);
70
+ const child = spawn(electron, [mainPath, ...additionalArgs], {
71
+ stdio: "inherit",
72
+ env: { ...process.env, NODE_ENV: "development" }
73
+ });
74
+ child.on("error", (err) => {
75
+ log("Electron 启动失败: " + err.message, MAGENTA);
76
+ process.exit(1);
77
+ });
78
+ child.on("exit", (code) => process.exit(code || 0));
79
+ } catch (err) {
80
+ log("Electron 不可用,切换到 Web 模式...", CYAN);
81
+ await startWebServer(additionalArgs);
82
+ }
83
+ }
84
+
85
+ async function startWebServer(additionalArgs) {
86
+ const mainPath = getMainEntry();
87
+ const webArgs = ["--web", ...additionalArgs];
88
+ log("启动 Web 服务...", CYAN);
89
+ const child = spawn(process.execPath, [mainPath, ...webArgs], { stdio: "inherit" });
90
+ child.on("error", (err) => {
91
+ log("Web 服务启动失败: " + err.message, MAGENTA);
92
+ process.exit(1);
93
+ });
94
+ child.on("exit", (code) => process.exit(code || 0));
95
+ }
96
+
97
+ async function startCLI(additionalArgs) {
98
+ const mainPath = getMainEntry();
99
+ log("启动命令行界面...", CYAN);
100
+ const child = spawn(process.execPath, [mainPath, ...additionalArgs], { stdio: "inherit" });
101
+ child.on("error", (err) => {
102
+ log("CLI 启动失败: " + err.message, MAGENTA);
103
+ process.exit(1);
104
+ });
105
+ child.on("exit", (code) => process.exit(code || 0));
106
+ }
107
+
108
+ async function main() {
109
+ const { mode, args } = parseArgs();
110
+ switch (mode) {
111
+ case "version":
112
+ console.log("Bolloon Agent v0.1.1");
113
+ break;
114
+ case "help":
115
+ printBanner();
116
+ console.log(BOLD + "用法:" + RESET + " bolloon [选项] [命令] [参数]");
117
+ console.log(BOLD + "选项:" + RESET + " --gui, -g 启动图形界面");
118
+ console.log(" --web, -w 启动 Web UI");
119
+ console.log(" --cli, -c 启动命令行界面");
120
+ console.log(" --version, -v 显示版本");
121
+ console.log(" --help, -h 显示帮助");
122
+ console.log(BOLD + "示例:" + RESET + " bolloon # 启动图形界面");
123
+ console.log(" bolloon --web # 启动 Web UI");
124
+ console.log(" bolloon --read file # 读取文档");
125
+ break;
126
+ case "gui":
127
+ printBanner();
128
+ await startElectron(args);
129
+ break;
130
+ case "web":
131
+ printBanner();
132
+ await startWebServer(args);
133
+ break;
134
+ case "cli":
135
+ await startCLI(args);
136
+ break;
137
+ case "passthrough":
138
+ const mainPath = getMainEntry();
139
+ const child = spawn(process.execPath, [mainPath, ...args], { stdio: "inherit" });
140
+ child.on("error", (err) => {
141
+ log("执行失败: " + err.message, MAGENTA);
142
+ process.exit(1);
143
+ });
144
+ child.on("exit", (code) => process.exit(code || 0));
145
+ break;
146
+ default:
147
+ log("未知模式: " + mode, MAGENTA);
148
+ printBanner();
149
+ console.log("输入 --help 查看帮助");
150
+ process.exit(1);
151
+ }
152
+ }
153
+
154
+ main().catch((err) => {
155
+ console.error("Fatal error:", err);
156
+ process.exit(1);
157
+ });
@@ -7,25 +7,25 @@ import { ToolPermissionContext, BudgetTracker } from '@bolloon/constraint-runtim
7
7
  * System prompt for constraint layer
8
8
  * Defines boundaries and autonomous permissions
9
9
  */
10
- export const SYSTEM_PROMPT = `
11
- 你是一个文档处理Agent,在以下规则下运行:
12
-
13
- 【边界规则】
14
- 1. 只处理:txt, md, pdf, docx 格式文档
15
- 2. 不修改原始文件,只输出改进版本
16
- 3. 发送前必须记录操作日志
17
-
18
- 【自主权限】
19
- - ✅ 自主决定:摘要详细程度、chunk分块策略
20
- - ✅ 自主决定:重试次数(最多3次)
21
- - ✅ 自主决定:是否需要补充信息
22
- - ❌ 必须确认:首次向新对等节点发送文档
23
- - ❌ 必须确认:删除操作
24
-
25
- 【敏感操作拦截】
26
- if (操作 === '发送文档' && 对等节点不在已知列表) {
27
- 拦截 → 记录 → 等待确认
28
- }
10
+ export const SYSTEM_PROMPT = `
11
+ 你是一个文档处理Agent,在以下规则下运行:
12
+
13
+ 【边界规则】
14
+ 1. 只处理:txt, md, pdf, docx 格式文档
15
+ 2. 不修改原始文件,只输出改进版本
16
+ 3. 发送前必须记录操作日志
17
+
18
+ 【自主权限】
19
+ - ✅ 自主决定:摘要详细程度、chunk分块策略
20
+ - ✅ 自主决定:重试次数(最多3次)
21
+ - ✅ 自主决定:是否需要补充信息
22
+ - ❌ 必须确认:首次向新对等节点发送文档
23
+ - ❌ 必须确认:删除操作
24
+
25
+ 【敏感操作拦截】
26
+ if (操作 === '发送文档' && 对等节点不在已知列表) {
27
+ 拦截 → 记录 → 等待确认
28
+ }
29
29
  `;
30
30
  /**
31
31
  * Actions that can be executed autonomously without confirmation
@@ -148,20 +148,20 @@ export async function distillDissent(ask) {
148
148
  .slice(-10)
149
149
  .flatMap((j) => j.reasons || [])
150
150
  .slice(0, 20);
151
- const prompt = `你是用户的判断力代理. 用户发起了一个决定: "${ask.decision}"
152
- ${ask.context ? `\n补充: ${ask.context}` : ''}
153
-
154
- [用户价值画像] ${valueHint}
155
- [相关历史判断 (${relevant.length} 条)] ${relevant.slice(0, 3).map((j) => j.decision || '').join(' | ').slice(0, 300)}
156
- [历史理由样本] ${recentReasons.join(' | ').slice(0, 400) || '(无)'}
157
-
158
- 请基于上述判断力, 生成正好 3 个"反方观点" (用户应该考虑但可能忽略的风险/盲点).
159
- 要求:
160
- - 每个反方 1-2 句, 总长 < 80 字
161
- - 必须是这个特定决定的"反对声音", 不是通用建议
162
- - 第 1 个: 历史/经验类风险
163
- - 第 2 个: 关系/信任类风险
164
- - 第 3 个: 隐藏代价/时间类风险
151
+ const prompt = `你是用户的判断力代理. 用户发起了一个决定: "${ask.decision}"
152
+ ${ask.context ? `\n补充: ${ask.context}` : ''}
153
+
154
+ [用户价值画像] ${valueHint}
155
+ [相关历史判断 (${relevant.length} 条)] ${relevant.slice(0, 3).map((j) => j.decision || '').join(' | ').slice(0, 300)}
156
+ [历史理由样本] ${recentReasons.join(' | ').slice(0, 400) || '(无)'}
157
+
158
+ 请基于上述判断力, 生成正好 3 个"反方观点" (用户应该考虑但可能忽略的风险/盲点).
159
+ 要求:
160
+ - 每个反方 1-2 句, 总长 < 80 字
161
+ - 必须是这个特定决定的"反对声音", 不是通用建议
162
+ - 第 1 个: 历史/经验类风险
163
+ - 第 2 个: 关系/信任类风险
164
+ - 第 3 个: 隐藏代价/时间类风险
165
165
  - 用 JSON 数组返回: ["反方1", "反方2", "反方3"]`;
166
166
  // LLM 调用 (OpenAI 兼容, 复用 p2p-chat-tools 的方式)
167
167
  let dissents = [];
@@ -34,6 +34,43 @@ export const SIDE_EFFECT_TOOLS = new Set([
34
34
  'write_file', 'edit_file', 'shell_exec', 'git_commit', 'git_push', 'git_branch',
35
35
  'create_task', 'update_task',
36
36
  ]);
37
+ export async function runTerminalCommand(raw, opts = {}) {
38
+ const { checkTerminalCommand } = await import('./shell-guard.js');
39
+ const timeoutMs = opts.timeoutMs ?? 30000;
40
+ const list = (opts.commands && opts.commands.length > 0) ? opts.commands : [raw];
41
+ for (const c of list) {
42
+ const guard = checkTerminalCommand(String(c || '').trim());
43
+ if (!guard.allowed) {
44
+ return { success: false, error: `[terminal-guard] ${guard.reason}`, deniedByGuard: true };
45
+ }
46
+ }
47
+ const { exec } = await import('child_process');
48
+ const runOne = (cmdStr) => new Promise((resolve) => {
49
+ exec(cmdStr, {
50
+ cwd: opts.cwd ?? process.cwd(),
51
+ timeout: timeoutMs,
52
+ maxBuffer: 8 * 1024 * 1024,
53
+ env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
54
+ }, (err, stdout, stderr) => {
55
+ const output = ((stdout || '') + (stderr ? `\n[stderr]\n${stderr}` : '')).trim().slice(0, 8000);
56
+ if (err) {
57
+ resolve({ success: false, cmd: cmdStr.slice(0, 120), error: `exit ${err.code ?? '?'}: ${String(err.message || '').slice(0, 200)}`, output: output || undefined });
58
+ }
59
+ else {
60
+ resolve({ success: true, cmd: cmdStr.slice(0, 120), output: output || '(无输出)' });
61
+ }
62
+ });
63
+ });
64
+ if (list.length === 1)
65
+ return runOne(list[0]);
66
+ const results = await Promise.all(list.map((c) => runOne(c)));
67
+ const failed = results.filter((r) => !r.success);
68
+ const allOutput = results.map((r) => `${r.cmd}\n${r.output || r.error || ''}`).join('\n\n---\n\n');
69
+ if (failed.length > 0) {
70
+ return { success: false, error: `${failed.length}/${list.length} 条命令失败: ${failed[0].error}`, output: allOutput, partial: results };
71
+ }
72
+ return { success: true, output: allOutput, count: list.length, parallel: true };
73
+ }
37
74
  export function registerBuiltinTools(ctx) {
38
75
  ctx.tools.set('read_document', {
39
76
  name: 'read_document',
@@ -621,17 +658,22 @@ export function registerBuiltinTools(ctx) {
621
658
  for (const tool of p2pDocumentTools) {
622
659
  ctx.tools.set(tool.name, tool);
623
660
  }
624
- // shell_exec
661
+ // 2026-08-12 (Task2): shell_exec / terminal 统一走模块级 runTerminalCommand (宽松护栏 + 多命令并行).
662
+ // shell_exec — 2026-08-12 (Task2): 与 terminal 统一走宽松护栏 (denylist-only).
663
+ // 兼容旧格式 (command + args 数组), 内部转成完整命令字符串交给 runTerminal,
664
+ // 不再用窄白名单 → 模型不会因 "command 不在白名单" 报错.
625
665
  ctx.tools.set('shell_exec', {
626
666
  name: 'shell_exec',
627
- description: ' cwd 跑 shell 命令. 仅支持白名单内命令: git, npm, npx, tsx, tsc, vitest, cat, head, tail, ls, wc, echo, pwd, date, mkdir, touch. 禁止管道/重定向/rm -rf/sudo. 命中护栏黑名单会被拒.',
628
- parameters: { command: '可执行文件 (必填, 必须在白名单)', args: '参数数组, 逗号分隔', timeoutMs: '超时毫秒, 默认 30000' },
667
+ description: '执行 shell 命令 (兼容模式, 参数数组或命令字符串均可). 护栏只挡高危破坏操作 (sudo/格式化/rm -rf 根目录/写 ~/.bolloon 数据). 推荐直接用 terminal 传完整命令字符串.',
668
+ parameters: { command: '可执行文件 或 完整命令 (必填)', args: '参数数组, 逗号分隔 (可选)', timeoutMs: '超时毫秒, 默认 30000' },
629
669
  execute: async (args) => {
630
670
  const cmd = String(args.command || '').trim();
631
671
  if (!cmd)
632
672
  return { success: false, error: 'command 必填' };
633
- let argList = [];
673
+ // 兼容参数数组 拼成命令字符串
674
+ let full = cmd;
634
675
  const rawArgs = args.args;
676
+ let argList = [];
635
677
  if (Array.isArray(rawArgs)) {
636
678
  argList = rawArgs.map((s) => String(s).trim()).filter(Boolean);
637
679
  }
@@ -640,61 +682,36 @@ export function registerBuiltinTools(ctx) {
640
682
  if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
641
683
  try {
642
684
  const parsed = JSON.parse(trimmed);
643
- if (Array.isArray(parsed)) {
685
+ if (Array.isArray(parsed))
644
686
  argList = parsed.map((s) => String(s).trim()).filter(Boolean);
645
- }
646
687
  }
647
- catch { /* fall through to comma split */ }
688
+ catch { /* JSON 数组 */ }
648
689
  }
649
- if (argList.length === 0) {
690
+ if (argList.length === 0)
650
691
  argList = trimmed.split(',').map(s => s.trim()).filter(Boolean);
651
- }
652
- }
653
- const timeoutMs = Number(args.timeoutMs) || 30000;
654
- const result = await shellExec(cmd, argList, { timeoutMs });
655
- if (result.deniedByGuard) {
656
- return { success: false, error: result.error };
657
692
  }
658
- if (!result.success) {
659
- return { success: false, error: result.error, output: result.output };
693
+ // command 只是可执行文件名且带 args → 拼成 "cmd arg1 arg2"; 否则原样
694
+ if (argList.length > 0 && !/\s/.test(cmd) && !cmd.includes('&&') && !cmd.includes(';') && !cmd.includes('|')) {
695
+ full = `${cmd} ${argList.map(a => (/[\s"&|<>^()%!`]/.test(a) ? `"${a.replace(/"/g, '""')}"` : a)).join(' ')}`;
660
696
  }
661
- return { success: true, output: result.output };
697
+ const timeoutMs = Number(args.timeoutMs) || 30000;
698
+ return await runTerminalCommand(full, { timeoutMs, cwd: ctx.cwd });
662
699
  }
663
700
  });
664
701
  // 2026-08-10: terminal — 灵活终端写命令 (用户要求: bolloon 自己写命令进 terminal, 少围栏).
665
- // shell_exec 的区别: 接受**完整 shell 命令字符串** (管道/重定向/写文件都行),
666
- // 护栏只挡高危破坏模式 (checkTerminalCommand: 提权/格式化/删根/.bolloon 数据), 其余放行.
702
+ // 2026-08-12 (Task2): 支持 commands 数组并行执行; shell_exec 统一走 runTerminalCommand.
703
+ // shell_exec 的区别: 直接接受完整 shell 命令字符串, 更适合模型自主写命令.
667
704
  ctx.tools.set('terminal', {
668
705
  name: 'terminal',
669
- description: '执行完整 shell 命令 (支持管道/重定向/写文件/跑脚本). 护栏只挡高危破坏操作 (sudo/格式化/rm -rf 根目录/写 ~/.bolloon 数据), 其余灵活放行. 适合: 写 HTML 文件、跑 python/node 脚本、查系统状态、装依赖.',
670
- parameters: { command: '完整 shell 命令 (必填, 如: echo "<html>" > /tmp/site/index.html && ls /tmp/site)', timeoutMs: '超时毫秒, 默认 30000' },
706
+ description: '执行完整 shell 命令 (支持管道/重定向/写文件/跑脚本). 护栏只挡高危破坏操作 (sudo/格式化/rm -rf 根目录/写 ~/.bolloon 数据), 其余灵活放行. 适合: 写 HTML 文件、跑 python/node 脚本、查系统状态、装依赖. 多条命令用 commands 数组并行执行.',
707
+ parameters: { command: '完整 shell 命令 (必填, 如: echo "<html>" > /tmp/site/index.html && ls /tmp/site)', commands: '可选: 多条命令数组 (并行执行), 每条独立字符串', timeoutMs: '超时毫秒, 默认 30000' },
671
708
  execute: async (args) => {
672
709
  const raw = String(args.command || '').trim();
673
- if (!raw)
674
- return { success: false, error: 'command 必填' };
675
- const { checkTerminalCommand } = await import('./shell-guard.js');
676
- const guard = checkTerminalCommand(raw);
677
- if (!guard.allowed) {
678
- return { success: false, error: `[terminal-guard] ${guard.reason}`, deniedByGuard: true };
679
- }
680
- const { exec } = await import('child_process');
710
+ const commands = Array.isArray(args.commands) ? args.commands.map((c) => String(c || '').trim()).filter(Boolean) : [];
711
+ if (!raw && commands.length === 0)
712
+ return { success: false, error: 'command 或 commands 必填' };
681
713
  const timeoutMs = Number(args.timeoutMs) || 30000;
682
- return new Promise((resolve) => {
683
- exec(raw, {
684
- cwd: process.cwd(),
685
- timeout: timeoutMs,
686
- maxBuffer: 8 * 1024 * 1024,
687
- env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
688
- }, (err, stdout, stderr) => {
689
- const output = ((stdout || '') + (stderr ? `\n[stderr]\n${stderr}` : '')).trim().slice(0, 8000);
690
- if (err) {
691
- resolve({ success: false, error: `exit ${err.code ?? '?'}: ${String(err.message || '').slice(0, 200)}`, output: output || undefined });
692
- }
693
- else {
694
- resolve({ success: true, output: output || '(无输出)' });
695
- }
696
- });
697
- });
714
+ return await runTerminalCommand(raw, { timeoutMs, cwd: ctx.cwd, commands: commands.length > 0 ? commands : undefined });
698
715
  }
699
716
  });
700
717
  // self_improve
@@ -1,13 +1,13 @@
1
- export const TOOL_DEFINITIONS = `
2
- 可用工具:
3
- 1. read_document(path) - 读取文档内容,支持 .txt, .md, .pdf, .docx
4
- 2. summarize_document(path, context?) - 总结文档内容,可选提供上下文
5
- 3. improve_document(path, requirements) - 改进文档,需提供文件路径和改进要求
6
- 4. list_peers() - 列出已连接的对等节点
7
- 5. send_message(peer_id, message) - 向指定对等节点发送消息
8
- 6. broadcast_message(message) - 向所有对等节点广播消息
9
- 7. get_identity() - 获取当前智能体身份信息
10
- 8. set_persona(persona_json) - 更新智能体 persona,包含 name、description、personality、greeting 等
11
- 9. run_workflow(steps) - 执行预定义工作流
12
- 10. get_operation_logs() - 获取操作日志
1
+ export const TOOL_DEFINITIONS = `
2
+ 可用工具:
3
+ 1. read_document(path) - 读取文档内容,支持 .txt, .md, .pdf, .docx
4
+ 2. summarize_document(path, context?) - 总结文档内容,可选提供上下文
5
+ 3. improve_document(path, requirements) - 改进文档,需提供文件路径和改进要求
6
+ 4. list_peers() - 列出已连接的对等节点
7
+ 5. send_message(peer_id, message) - 向指定对等节点发送消息
8
+ 6. broadcast_message(message) - 向所有对等节点广播消息
9
+ 7. get_identity() - 获取当前智能体身份信息
10
+ 8. set_persona(persona_json) - 更新智能体 persona,包含 name、description、personality、greeting 等
11
+ 9. run_workflow(steps) - 执行预定义工作流
12
+ 10. get_operation_logs() - 获取操作日志
13
13
  `;
@@ -201,6 +201,15 @@ export class PiAgentSession {
201
201
  currentSignal = null;
202
202
  /** Bootstrap SessionStart 拼的 system prompt 片段 (用完即清) */
203
203
  bootstrapAddition = '';
204
+ /** 2026-08-12 (Task3 认知卸载): 工具选择与认知卸载指南 — 注入 system prompt, 降低"模型不触发 write/edit/read"率. */
205
+ static TOOL_SELECTION_GUIDE = `【工具选择与认知卸载指南 (严格遵循)】
206
+ - 写/改文件: 必须用 write_file / edit_file (不要用 terminal 拼字符串写文件).
207
+ - 读文件: 用 read_file / read_directory / list_files.
208
+ - 跑命令/查状态/装依赖/跑脚本: 用 terminal.
209
+ - 执行 git 操作: 用 git_* 专用工具 (git_diff/git_commit/git_push/git_branch/git_log).
210
+ - 查看/调用技能: 用 list_skills / use_skill.
211
+ - 认知卸载: 当任务对你过大或反复失败时, 不要死磕 — 用 delegate_to_engine 把编码/复杂任务委派给外部引擎 (codex/claude-code/opencode), 或把目标拆小分步完成.
212
+ - 每步只选一个最合适的工具, 先读后写, 写完验证 (跑 tsc/vitest 或读回文件).`;
204
213
  /** 当前 prompt 开始时间 (供 Stop hook 计算 durationMs) */
205
214
  promptStartTime = 0;
206
215
  /** 当前 channel id (由 getAgentForChannel / prompt 4 参注入, 供 hook / log 使用) */
@@ -1042,38 +1051,40 @@ export class PiAgentSession {
1042
1051
  }
1043
1052
  // M2.4: persona 缓存
1044
1053
  if (!this.cachedPersonaSection && this.persona) {
1045
- this.cachedPersonaSection = `
1046
- 角色描述: ${this.persona.description || '无'}
1047
- 性格特点: ${this.persona.personality || '无'}
1048
- 问候语: ${this.persona.greeting || '无'}
1054
+ this.cachedPersonaSection = `
1055
+ 角色描述: ${this.persona.description || '无'}
1056
+ 性格特点: ${this.persona.personality || '无'}
1057
+ 问候语: ${this.persona.greeting || '无'}
1049
1058
  `;
1050
1059
  }
1051
- const systemPrompt = `${this.bootstrapAddition}你是 ${this.identity.name},基于ReAct (Reasoning + Acting)模式工作。${this.cachedPersonaSection}
1052
- 当前工作目录: ${this.cwd}
1053
- 当前身份: ${this.identity.name} (${this.identity.did})
1054
- ${this.currentIntentHint}
1055
-
1056
- ${this.getToolDefinitions()}
1057
-
1058
- 工作模式:
1059
- 1. 理解用户自然语言请求
1060
- 2. 分析需要哪些工具来完成
1061
- 3. 按顺序调用工具并观察结果
1062
- 4. 根据观察结果决定下一步
1063
- 5. 最终给出完整回答
1064
-
1065
- 重要 (一次命中要求):
1066
- - 每次只调用一个工具
1067
- - 仔细分析工具返回结果
1068
- - 当任务完成时,必须在回答末尾添加 <final gen> 标记表示结束
1069
- - 如果需要更多信息,继续调用工具
1070
-
1071
- 【工具调用格式 (严格遵守, 否则系统无法解析)】
1072
- - 你只能输出**一个**工具调用, 不要堆叠多个 invoke
1073
- - 工具调用格式: {"name":"<tool_name>","input":{"arg1":"value1"}}
1074
- - markdown json code block 包裹: \`\`\`json\n{"name":"X","input":{...}}\n\`\`\`
1075
- - 工具调用前可以简短思考 (1-2 句话), 但**不要写长篇 thinking** (会撞 max_tokens)
1076
- - 工具调用后必须等结果, 不要在同一个回复里继续输出
1060
+ const systemPrompt = `${this.bootstrapAddition}你是 ${this.identity.name},基于ReAct (Reasoning + Acting)模式工作。${this.cachedPersonaSection}
1061
+ 当前工作目录: ${this.cwd}
1062
+ 当前身份: ${this.identity.name} (${this.identity.did})
1063
+ ${this.currentIntentHint}
1064
+
1065
+ ${this.getToolDefinitions()}
1066
+
1067
+ ${PiAgentSession.TOOL_SELECTION_GUIDE}
1068
+
1069
+ 工作模式:
1070
+ 1. 理解用户自然语言请求
1071
+ 2. 分析需要哪些工具来完成
1072
+ 3. 按顺序调用工具并观察结果
1073
+ 4. 根据观察结果决定下一步
1074
+ 5. 最终给出完整回答
1075
+
1076
+ 重要 (一次命中要求):
1077
+ - 每次只调用一个工具
1078
+ - 仔细分析工具返回结果
1079
+ - 当任务完成时,必须在回答末尾添加 <final gen> 标记表示结束
1080
+ - 如果需要更多信息,继续调用工具
1081
+
1082
+ 【工具调用格式 (严格遵守, 否则系统无法解析)】
1083
+ - 你只能输出**一个**工具调用, 不要堆叠多个 invoke
1084
+ - 工具调用格式: {"name":"<tool_name>","input":{"arg1":"value1"}}
1085
+ - markdown json code block 包裹: \`\`\`json\n{"name":"X","input":{...}}\n\`\`\`
1086
+ - 工具调用前可以简短思考 (1-2 句话), 但**不要写长篇 thinking** (会撞 max_tokens)
1087
+ - 工具调用后必须等结果, 不要在同一个回复里继续输出
1077
1088
  - <final gen> 只在**真完成所有任务**时输出, 不要在工具调用前/中输出${this.judgmentGateAddition}${this.contextHintAddition}`;
1078
1089
  // 2026-06-15: 把 currentOnStream 传给 loop, 让 step-timeline 在 pivot 循环里也能 emit step_start/done
1079
1090
  // 之前 loop.execute() 不接 streamCallback, 导致 step-timeline 只能看到老 runReActLoop 路径
@@ -1265,10 +1276,10 @@ ${this.getToolDefinitions()}
1265
1276
  }
1266
1277
  // M2.4: persona section 缓存 — persona 在 loadPersona() 时一次设定, 此后不变
1267
1278
  if (!this.cachedPersonaSection && this.persona) {
1268
- this.cachedPersonaSection = `
1269
- 角色描述: ${this.persona.description || '无'}
1270
- 性格特点: ${this.persona.personality || '无'}
1271
- 问候语: ${this.persona.greeting || '无'}
1279
+ this.cachedPersonaSection = `
1280
+ 角色描述: ${this.persona.description || '无'}
1281
+ 性格特点: ${this.persona.personality || '无'}
1282
+ 问候语: ${this.persona.greeting || '无'}
1272
1283
  `;
1273
1284
  }
1274
1285
  const personaSection = this.cachedPersonaSection;
@@ -1286,26 +1297,28 @@ ${this.getToolDefinitions()}
1286
1297
  .join('\n');
1287
1298
  loopProgressSection = `\n【本轮循环进度】你已完成以下 ${loopActionLog.length} 个动作, 这是连续执行的同一轮任务:\n${actionLines}\n请基于已有结果继续推进, 不要重复执行上面已成功的动作. 全部完成后用 <final gen> 结束.\n`;
1288
1299
  }
1289
- const systemPrompt = `${this.bootstrapAddition}你是 ${this.identity.name},基于ReAct (Reasoning + Acting)模式工作。${personaSection}
1290
- 当前工作目录: ${this.cwd}
1291
- 当前身份: ${this.identity.name} (${this.identity.did})
1292
- ${refineContext}
1293
- ${this.currentIntentHint}
1294
- ${loopProgressSection}
1295
-
1296
- ${toolDefs}
1297
-
1298
- 工作模式:
1299
- 1. 理解用户自然语言请求
1300
- 2. 分析需要哪些工具来完成
1301
- 3. 按顺序调用工具并观察结果
1302
- 4. 根据观察结果决定下一步
1303
- 5. 最终给出完整回答
1304
-
1305
- 重要:
1306
- - 每次只调用一个工具
1307
- - 仔细分析工具返回结果
1308
- - 当任务完成时,必须在回答末尾添加 <final gen> 标记表示结束
1300
+ const systemPrompt = `${this.bootstrapAddition}你是 ${this.identity.name},基于ReAct (Reasoning + Acting)模式工作。${personaSection}
1301
+ 当前工作目录: ${this.cwd}
1302
+ 当前身份: ${this.identity.name} (${this.identity.did})
1303
+ ${refineContext}
1304
+ ${this.currentIntentHint}
1305
+ ${loopProgressSection}
1306
+
1307
+ ${toolDefs}
1308
+
1309
+ ${PiAgentSession.TOOL_SELECTION_GUIDE}
1310
+
1311
+ 工作模式:
1312
+ 1. 理解用户自然语言请求
1313
+ 2. 分析需要哪些工具来完成
1314
+ 3. 按顺序调用工具并观察结果
1315
+ 4. 根据观察结果决定下一步
1316
+ 5. 最终给出完整回答
1317
+
1318
+ 重要:
1319
+ - 每次只调用一个工具
1320
+ - 仔细分析工具返回结果
1321
+ - 当任务完成时,必须在回答末尾添加 <final gen> 标记表示结束
1309
1322
  - 如果需要更多信息,继续调用工具${this.judgmentGateAddition}${this.contextHintAddition}`;
1310
1323
  // 3 个恢复机制 (Claude Code 论文 9-step pipeline 内部):
1311
1324
  // 1. max output token 升级 (最多 3 次, 每次 maxOutputTokens 翻倍)
@@ -2376,37 +2389,37 @@ ${toolDefs}
2376
2389
  getDefaultResponse(input) {
2377
2390
  const operationsRef = PiAgentSession.getOperationsReference();
2378
2391
  if (operationsRef) {
2379
- return `收到了: "${input}"
2380
-
2381
- 我是一个判断力处理智能体,支持自然语言交互。
2382
-
2383
- 可用操作(直接说出即可):
2384
- ${this.extractOperationsFromRef(operationsRef)}
2385
-
2386
- 示例请求:
2387
- - "读取 src/index.ts 文件"
2388
- - "总结一下 README.md"
2389
- - "查看当前连接了哪些节点"
2392
+ return `收到了: "${input}"
2393
+
2394
+ 我是一个判断力处理智能体,支持自然语言交互。
2395
+
2396
+ 可用操作(直接说出即可):
2397
+ ${this.extractOperationsFromRef(operationsRef)}
2398
+
2399
+ 示例请求:
2400
+ - "读取 src/index.ts 文件"
2401
+ - "总结一下 README.md"
2402
+ - "查看当前连接了哪些节点"
2390
2403
  - "向 QmABC... 发送测试消息"`;
2391
2404
  }
2392
- return `收到了: "${input}"
2393
-
2394
- 我是一个判断力处理智能体,支持自然语言交互。
2395
-
2396
- 可用操作(直接说出即可):
2397
- - "读取 README.md" - 读取并分析文档
2398
- - "总结文档" - 总结文档内容
2399
- - "改进文档,按照X要求" - 改进文档
2400
- - "查看节点" - 查看已连接的对等节点
2401
- - "向X发送消息Y" - 向对等节点发送消息
2402
- - "广播消息X" - 广播消息到所有节点
2403
- - "查看身份" - 查看当前智能体身份
2404
- - "查看日志" - 查看最近操作日志
2405
-
2406
- 示例请求:
2407
- - "读取 src/index.ts 文件"
2408
- - "总结一下 README.md"
2409
- - "查看当前连接了哪些节点"
2405
+ return `收到了: "${input}"
2406
+
2407
+ 我是一个判断力处理智能体,支持自然语言交互。
2408
+
2409
+ 可用操作(直接说出即可):
2410
+ - "读取 README.md" - 读取并分析文档
2411
+ - "总结文档" - 总结文档内容
2412
+ - "改进文档,按照X要求" - 改进文档
2413
+ - "查看节点" - 查看已连接的对等节点
2414
+ - "向X发送消息Y" - 向对等节点发送消息
2415
+ - "广播消息X" - 广播消息到所有节点
2416
+ - "查看身份" - 查看当前智能体身份
2417
+ - "查看日志" - 查看最近操作日志
2418
+
2419
+ 示例请求:
2420
+ - "读取 src/index.ts 文件"
2421
+ - "总结一下 README.md"
2422
+ - "查看当前连接了哪些节点"
2410
2423
  - "向 QmABC... 发送测试消息"`;
2411
2424
  }
2412
2425
  extractOperationsFromRef(ref) {
@@ -2431,13 +2444,13 @@ ${this.extractOperationsFromRef(operationsRef)}
2431
2444
  }
2432
2445
  }
2433
2446
  return operationLines.length > 0 ? operationLines.join('\n') :
2434
- ` - "读取 README.md" - 读取并分析文档
2435
- - "总结文档" - 总结文档内容
2436
- - "改进文档,按照X要求" - 改进文档
2437
- - "查看节点" - 查看已连接的对等节点
2438
- - "向X发送消息Y" - 向对等节点发送消息
2439
- - "广播消息X" - 广播消息到所有节点
2440
- - "查看身份" - 查看当前智能体身份
2447
+ ` - "读取 README.md" - 读取并分析文档
2448
+ - "总结文档" - 总结文档内容
2449
+ - "改进文档,按照X要求" - 改进文档
2450
+ - "查看节点" - 查看已连接的对等节点
2451
+ - "向X发送消息Y" - 向对等节点发送消息
2452
+ - "广播消息X" - 广播消息到所有节点
2453
+ - "查看身份" - 查看当前智能体身份
2441
2454
  - "查看日志" - 查看最近操作日志`;
2442
2455
  }
2443
2456
  async suggestRename(messages) {