@bolloon/bolloon-agent 0.1.33 → 0.1.34

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.
package/README.md CHANGED
@@ -1,6 +1,11 @@
1
- # Bolloon - 判断力智能体协作平台
1
+ # Bolloon - 判断力对齐协议
2
2
 
3
- ## 核心效果
3
+ > **⚠️ 2026-06-10 重新校准**:本文档下方的"核心效果"是历史叙事。**Bolloon 的真正定义见 [docs/真正要做的事.md](docs/真正要做的事.md)**。
4
+ > 一句话:**Bolloon 是 A 和 B 对接判断力的协议层——让 A 和 B 在做重要决定前,把双方的 3 个反方观点互相看见。**
5
+
6
+ ---
7
+
8
+ ## 核心效果(历史叙事,即将更新)
4
9
 
5
10
  > **两个有判断力的人的决策,被 Bolloon 记录后,异步进行合作,由 Harness 驱动自动化执行。**
6
11
 
@@ -23,7 +23,14 @@ export { getJudgmentsForPath, getJudgmentsForFragment, getJudgmentsForContextReq
23
23
  export { initializeMcpAdapter, discoverMcpServers, registerServer, registerTool, listTools, hasTool, getTool, executeTool, getToolCallLog, getAdapterStatus, } from '../pi-ecosystem-mcp/index.js';
24
24
  export { createGoal, createGoalQueue, getCurrentGoal, startCurrentGoal, completeCurrentGoal, failCurrentGoal, cutoffCurrentGoal, pauseCurrentGoal, checkBudget, getGoalStats, getQueueSummary, loadGoals, clearGoals, compactQueue, loadTemplates, createFromTemplate, nudgeCurrentGoal, } from '../pi-ecosystem-goals/index.js';
25
25
  export { createSubagent, startSubagent, delegateTask, getSubagent, listSubagents, listRunningSubagents, terminateSubagent, getStats as getSubagentStats, parallelDelegate, splitTask, } from '../pi-ecosystem-subagents/index.js';
26
- export { registerAnt, antScouting, antWorking, antReviewing, antComplete, antFail, antAbort, antTick, createTask, dispatchTask, recordResult, getAnt, listAnts, listAntsByRole, listAntsBySignal, getActiveAnts, getTask, listTasks, getSignalHistory, getColonyStatus, getColonyDump, persistColony, loadColony, onColonyEvent, offColonyEvent, } from '../pi-ecosystem-colony/index.js';
26
+ // 2026-06-11: 蚁群模块 (pi-ecosystem-colony) 已被用户删除, 移除对应 re-export 防止启动失败
27
+ // export {
28
+ // registerAnt, antScouting, antWorking, antReviewing, antComplete, antFail, antAbort, antTick,
29
+ // createTask, dispatchTask, recordResult, getAnt, listAnts, listAntsByRole, listAntsBySignal,
30
+ // getActiveAnts, getTask, listTasks, getSignalHistory, getColonyStatus, getColonyDump,
31
+ // persistColony, loadColony, onColonyEvent, offColonyEvent,
32
+ // type Ant, type ColonyTask, type ColonySignalEvent, type ColonySignal, type AntRole,
33
+ // } from '../pi-ecosystem-colony/index.js';
27
34
  // Judgment exports
28
35
  export { createJudgment, getAllJudgments, getJudgmentsByType, getJudgmentsForContext, getCombinedJudgments, calculateConfidence, buildValueFunction, getValueFunction, getJudgmentStats, loadFragmentJudgments, } from '../pi-ecosystem-judgment/index.js';
29
36
  // Distillation exports
@@ -30,11 +30,19 @@ export class Watchdog {
30
30
  }
31
31
  /**
32
32
  * 记录活动(调用后更新 lastActivityTime)
33
+ * 2026-06-10: 加 5s 去抖, 防 broadcast / SSE 高频路径炸 log + CPU
34
+ * - lastActivityTime 始终更新 (cheap)
35
+ * - 但 onLog 回调只在距上次 ≥5s 时触发, 避免每秒几十次 console.log
33
36
  */
37
+ _lastLogAt = 0;
34
38
  recordActivity(component) {
35
39
  this.state.lastActivityTime = Date.now();
36
40
  if (component) {
37
- this.callbacks.onLog?.(`[Watchdog] Activity from ${component}`);
41
+ const now = Date.now();
42
+ if (now - this._lastLogAt >= 5000) {
43
+ this._lastLogAt = now;
44
+ this.callbacks.onLog?.(`[Watchdog] Activity from ${component}`);
45
+ }
38
46
  }
39
47
  }
40
48
  /**
@@ -58,9 +58,9 @@ export class P2PDirect extends EventEmitter {
58
58
  console.log(`[P2PDirect:${this.name}] 新连接: ${remotePubKeyHex.substring(0, 12)}... (inbound=${info.inbound || false}, type=${typeof conn}, hasWrite=${typeof conn?.write})`);
59
59
  // 双向记录 (inbound + outbound 都能拿到)
60
60
  this.conns.set(remotePubKeyHex, conn);
61
- // v3: 触发 'connection' 事件, 上层 (web server) 可以主动给新连接发消息
62
- this.emit('connection', { remotePublicKey: remotePubKeyHex, conn });
63
61
  // 收到数据时 → 触发 'data' 事件
62
+ // 注意: data 监听器必须在 emit('connection') 之前注册,
63
+ // 否则 server 的 connection handler 发送消息后, 对端回复可能在 data 监听器就绪前到达
64
64
  conn.on('data', (chunk) => {
65
65
  const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
66
66
  console.log(`[P2PDirect:${this.name}] 收到数据 from ${remotePubKeyHex.substring(0, 12)}... (${buf.length} bytes)`);
@@ -75,6 +75,9 @@ export class P2PDirect extends EventEmitter {
75
75
  conn.on('close', () => {
76
76
  this.conns.delete(remotePubKeyHex);
77
77
  });
78
+ // v3: 触发 'connection' 事件, 上层 (web server) 可以主动给新连接发消息
79
+ // 注意: 放在 data/error/close 监听器之后, 确保 server 的 connection handler 不会先于 data 就绪
80
+ this.emit('connection', { remotePublicKey: remotePubKeyHex, conn });
78
81
  });
79
82
  await this.swarm.listen(); // server 模式
80
83
  this.started = true;
@@ -127,6 +130,60 @@ export class P2PDirect extends EventEmitter {
127
130
  return false;
128
131
  }
129
132
  }
133
+ /**
134
+ * 2026-06-10: 真"主动发, 等握手完成"版本 — 修复好友申请 fire-and-forget bug.
135
+ *
136
+ * 之前的问题: server.ts:2914 `await swarm.joinPeer(...)` 只触发握手, conn 还没 push 进 this.conns,
137
+ * 立即调 sendTo 找不到 conn → 静默返回 false → 消息扔进虚空.
138
+ *
139
+ * 现在: sendToWithWait 监听 'connection' 事件, 等到 targetPublicKey 真正出现在 this.conns,
140
+ * 才 write; 超时返回 NO_CONN; 写失败返回 WRITE_FAIL; 成功返回 SENT.
141
+ *
142
+ * 上层调用: const r = await p2p.sendToWithWait(pk, rpc, 5000);
143
+ * if (r !== 'SENT') return 502 给前端.
144
+ */
145
+ async sendToWithWait(publicKeyHex, data, timeoutMs = 5000) {
146
+ // 2026-06-11: 先主动触发 joinPeer, 否则 DHT 上对面可能没 push conn
147
+ if (this.swarm) {
148
+ try {
149
+ await this.swarm.joinPeer(Buffer.from(publicKeyHex, 'hex'));
150
+ }
151
+ catch { }
152
+ }
153
+ // 1) 已有 conn → 立即试
154
+ let conn = this.conns.get(publicKeyHex);
155
+ if (!conn || conn.destroyed) {
156
+ // 2) 等 'connection' 事件 (this.emit('connection', { remotePublicKey, conn }))
157
+ const waitResult = await new Promise((resolve) => {
158
+ const timer = setTimeout(() => {
159
+ this.off('connection', onConn);
160
+ resolve('TIMEOUT');
161
+ }, timeoutMs);
162
+ const onConn = (evt) => {
163
+ if (evt.remotePublicKey === publicKeyHex) {
164
+ clearTimeout(timer);
165
+ this.off('connection', onConn);
166
+ resolve('READY');
167
+ }
168
+ };
169
+ this.on('connection', onConn);
170
+ });
171
+ if (waitResult === 'TIMEOUT')
172
+ return 'NO_CONN';
173
+ conn = this.conns.get(publicKeyHex);
174
+ if (!conn || conn.destroyed)
175
+ return 'NO_CONN'; // 双保险
176
+ }
177
+ const buf = typeof data === 'string' ? Buffer.from(data) : data;
178
+ try {
179
+ conn.write(buf);
180
+ return 'SENT';
181
+ }
182
+ catch (err) {
183
+ console.error(`[P2PDirect:${this.name}] sendToWithWait 写失败 (${publicKeyHex.substring(0, 12)}...):`, err.message);
184
+ return 'WRITE_FAIL';
185
+ }
186
+ }
130
187
  getPublicKey() {
131
188
  if (!this.swarm)
132
189
  return '';
@@ -28,7 +28,7 @@ import * as path from 'path';
28
28
  export { initializeMcpAdapter, discoverMcpServers, registerServer, registerTool, listTools, hasTool, getTool, executeTool, getToolCallLog, clearToolCallLog, startServer, stopServer, discoverTools, createTavilyTool, createAmapTool, getAdapterStatus, on as onMcpEvent, off as offMcpEvent, } from '../pi-ecosystem-mcp/index.js';
29
29
  export { createGoal, createGoalQueue, getCurrentGoal, startCurrentGoal, completeCurrentGoal, failCurrentGoal, cutoffCurrentGoal, pauseCurrentGoal, checkBudget, getGoalStats, getQueueSummary, loadGoals, clearGoals, compactQueue, loadTemplates, createFromTemplate, nudgeCurrentGoal, } from '../pi-ecosystem-goals/index.js';
30
30
  export { createSubagent, startSubagent, delegateTask, getSubagent, listSubagents, listRunningSubagents, terminateSubagent, getStats as getSubagentStats, parallelDelegate, splitTask, } from '../pi-ecosystem-subagents/index.js';
31
- export { registerAnt, antScouting, antWorking, antReviewing, antComplete, antFail, antAbort, antTick, createTask, dispatchTask, recordResult, getAnt, listAnts, listAntsByRole, listAntsBySignal, getActiveAnts, getTask, listTasks, getSignalHistory, getColonyStatus, getColonyDump, persistColony, loadColony, onColonyEvent, offColonyEvent, } from '../pi-ecosystem-colony/index.js';
31
+ export { registerAnt, antScouting, antWorking, antReviewing, antComplete, antFail, antAbort, antTick, createTask, dispatchTask, recordResult, getAnt, listAnts, listAntsByRole, listAntsBySignal, getActiveAnts, getTask, listTasks, getSignalHistory, getColonyStatus, getColonyDump, persistColony, loadColony, onColonyEvent, offColonyEvent, } from '../pi-ecosystem-colony/index.js'; // 2026-06-11: 蚁群模块已被用户删除, 这行已经无效 (改用 stub)
32
32
  // Judgment exports
33
33
  export { createJudgment, updateJudgmentConfidence, getAllJudgments, getJudgmentsByType, getJudgmentsForContext, getCombinedJudgments, calculateConfidence, buildValueFunction, getValueFunction, getJudgmentStats, loadFragmentJudgments, clearCache, } from '../pi-ecosystem-judgment/index.js';
34
34
  // Distillation exports
@@ -198,17 +198,20 @@ export class PiEcosystem {
198
198
  }
199
199
  async registerAnt(name, role) {
200
200
  const colony = await import('../pi-ecosystem-colony/index.js');
201
- const ant = colony.registerAnt(name, role);
202
- return ant.id;
201
+ // 2026-06-11: colony 已退化为 stub, registerAnt 不接参数, 返回 void
202
+ colony.registerAnt();
203
+ return name;
203
204
  }
204
205
  async createColonyTask(description) {
205
206
  const colony = await import('../pi-ecosystem-colony/index.js');
206
- const task = colony.createTask(description);
207
- return task.id;
207
+ // 2026-06-11: createTask 不接参数, 返回空对象
208
+ const task = colony.createTask();
209
+ return task?.id ?? description;
208
210
  }
209
211
  async dispatchToColony(taskId, antIds) {
210
212
  const colony = await import('../pi-ecosystem-colony/index.js');
211
- colony.dispatchTask(taskId, antIds);
213
+ // 2026-06-11: dispatchTask 已退化为 stub
214
+ colony.dispatchTask();
212
215
  }
213
216
  async persist() {
214
217
  const colony = await import('../pi-ecosystem-colony/index.js');
@@ -20,8 +20,11 @@
20
20
  import { EventEmitter } from 'events';
21
21
  import { getValueFunction, calculateConfidence, } from './index.js';
22
22
  import { distillInput, isJudgmentSignal, detectTrigger, processFeedback, } from './distillation.js';
23
- import { listAnts } from '../pi-ecosystem-colony/index.js';
23
+ // 2026-06-11: 蚁群模块已被用户删除, 移除 import 防止启动失败, 加本地 stub
24
+ // import { listAnts, type Ant } from '../pi-ecosystem-colony/index.js';
24
25
  import { listSubagents } from '../pi-ecosystem-subagents/index.js';
26
+ // Stub: 蚁群删除后, 永远返回空列表
27
+ function listAnts() { return []; }
25
28
  class DecisionEventEmitter extends EventEmitter {
26
29
  }
27
30
  const decisionEvents = new DecisionEventEmitter();
@@ -198,7 +201,7 @@ async function consultColonyAnt(ant, request) {
198
201
  console.log(`[Decision] Consulting ant ${ant.name} for ${request.id}`);
199
202
  return {
200
203
  target: 'colony_ant',
201
- agentId: ant.id,
204
+ agentId: ant.name,
202
205
  response: `[Simulated] Ant ${ant.name} suggests: ${request.description.substring(0, 30)}...`,
203
206
  confidence: 0.6,
204
207
  };
@@ -1,8 +1,25 @@
1
1
  import * as fs from 'fs/promises';
2
2
  import * as path from 'path';
3
3
  import * as crypto from 'crypto';
4
- import { PheromoneEngine, PheromoneType } from './ant-colony/PheromoneEngine.js';
5
- import { AdaptiveHeartbeat } from './ant-colony/AdaptiveHeartbeat.js';
4
+ // 2026-06-11: 蚁群模块 (PheromoneEngine / AdaptiveHeartbeat) 已被用户删除, 仅保留最小 stub
5
+ // heartbeat 内的 antColony 代码块继续类型合法, 但运行时所有方法都是 no-op
6
+ class PheromoneEngine {
7
+ async initialize() { }
8
+ shutdown() { }
9
+ getStats() { return { totalTrails: 0, avgStrength: 0, capabilityCount: 0, density: 0 }; }
10
+ async deposit(_type, _from, _to, _strength, _meta) { }
11
+ }
12
+ class AdaptiveHeartbeat {
13
+ constructor(_opts) { }
14
+ shutdown() { }
15
+ decide() { return { interval: 0, priorityLevel: 'normal' }; }
16
+ setPheromoneDensity(_d) { }
17
+ recordActivity(_t) { }
18
+ }
19
+ var PheromoneType;
20
+ (function (PheromoneType) {
21
+ PheromoneType["DISCOVERY"] = "discovery";
22
+ })(PheromoneType || (PheromoneType = {}));
6
23
  import { ChannelManager } from './channels/ChannelManager.js';
7
24
  import { ChannelType } from './channels/types.js';
8
25
  import { DiapChannelBridge } from './channels/DiapChannelBridge.js';
@@ -4,9 +4,9 @@
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>API 配置 - Bolloon</title>
7
- <link rel="preconnect" href="https://fonts.googleapis.com">
8
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
- <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Noto+Sans+SC:wght@400;500;600&display=swap" rel="stylesheet">
7
+ <!-- 2026-06-11: 移除 Google Fonts 外部 CSS — 在大陆/跨公网时经常 30s+ timeout 阻塞首屏
8
+ style.css 里只用字体名字符串 (JetBrains Mono / monospace), 浏览器看字面量自动落回系统字体
9
+ 2026-06-11 提速: 不再等 Google CDN 即可渲染 -->
10
10
  <link rel="stylesheet" href="/style.css">
11
11
  </head>
12
12
  <body>