@bolloon/bolloon-agent 0.1.12 → 0.1.14

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 (77) hide show
  1. package/dist/agents/p2p-chat-tools.js +321 -0
  2. package/dist/agents/p2p-document-tools.js +121 -1
  3. package/dist/agents/pi-sdk.js +185 -0
  4. package/dist/agents/shell-guard.js +354 -0
  5. package/dist/agents/shell-tool.js +83 -0
  6. package/dist/agents/skill-loader.js +174 -0
  7. package/dist/agents/workflow-pivot-loop.js +4 -4
  8. package/dist/bollharness-integration/context-chain-router.js +3 -3
  9. package/dist/bollharness-integration/context-router.js +1 -1
  10. package/dist/cli-entry.js +1 -1
  11. package/dist/documents/reader.js +5 -0
  12. package/dist/documents/store.js +1 -1
  13. package/dist/heartbeat/Watchdog.js +7 -5
  14. package/dist/heartbeat/index.js +1 -0
  15. package/dist/heartbeat/self-improve-bus.js +85 -0
  16. package/dist/llm/pi-ai.js +6 -5
  17. package/dist/network/iroh-discovery.js +2 -1
  18. package/dist/network/iroh-transport.js +15 -2
  19. package/dist/network/p2p.js +9 -8
  20. package/dist/network/storage/adapters/json-adapter.js +16 -1
  21. package/dist/network/storage/index.js +2 -1
  22. package/dist/pi-ecosystem-judgment/index.js +42 -115
  23. package/dist/social/channels/channel-heartbeat-agent.js +1 -1
  24. package/dist/utils/auto-update.js +44 -12
  25. package/dist/web/client.js +839 -103
  26. package/dist/web/index.html +100 -8
  27. package/dist/web/server.js +568 -98
  28. package/dist/web/style.css +506 -9
  29. package/package.json +2 -2
  30. package/scripts/build-cli.js +11 -1
  31. package/scripts/build-web.ts +1 -1
  32. package/src/agents/p2p-chat-tools.ts +383 -0
  33. package/src/agents/p2p-document-tools.ts +151 -1
  34. package/src/agents/pi-sdk.ts +196 -0
  35. package/src/agents/shell-guard.ts +417 -0
  36. package/src/agents/shell-tool.ts +103 -0
  37. package/src/agents/skill-loader.ts +202 -0
  38. package/src/agents/workflow-pivot-loop.ts +13 -12
  39. package/src/bollharness-integration/channel-judgment-engine.ts +1 -1
  40. package/src/bollharness-integration/context-chain-router.ts +3 -3
  41. package/src/bollharness-integration/context-router.ts +1 -1
  42. package/src/documents/reader.ts +5 -0
  43. package/src/documents/store.ts +1 -1
  44. package/src/heartbeat/Watchdog.ts +7 -5
  45. package/src/heartbeat/index.ts +1 -0
  46. package/src/heartbeat/self-improve-bus.ts +110 -0
  47. package/src/llm/pi-ai.ts +6 -5
  48. package/src/network/iroh-discovery.ts +2 -1
  49. package/src/network/iroh-transport.ts +15 -2
  50. package/src/network/p2p.ts +9 -8
  51. package/src/network/storage/adapters/json-adapter.ts +17 -2
  52. package/src/network/storage/index.ts +19 -3
  53. package/src/social/channels/channel-heartbeat-agent.ts +1 -1
  54. package/src/types.d.ts +12 -0
  55. package/src/utils/auto-update.ts +45 -14
  56. package/src/web/client.js +839 -103
  57. package/src/web/index.html +88 -8
  58. package/src/web/server.ts +577 -102
  59. package/src/web/style.css +506 -9
  60. package/tsconfig.electron.json +1 -1
  61. package/tsconfig.json +1 -1
  62. package/dist/bollharness-integration/bollharness-integration/context-router-judgment.d.ts +0 -48
  63. package/dist/bollharness-integration/bollharness-integration/context-router-judgment.js +0 -261
  64. package/dist/bollharness-integration/bollharness-integration/context-router.d.ts +0 -110
  65. package/dist/bollharness-integration/bollharness-integration/context-router.js +0 -542
  66. package/dist/bollharness-integration/bollharness-integration/gate-state-machine.d.ts +0 -87
  67. package/dist/bollharness-integration/bollharness-integration/gate-state-machine.js +0 -231
  68. package/dist/bollharness-integration/bollharness-integration/gate-transition-hooks.d.ts +0 -30
  69. package/dist/bollharness-integration/bollharness-integration/gate-transition-hooks.js +0 -91
  70. package/dist/bollharness-integration/bollharness-integration/guard-checker.d.ts +0 -105
  71. package/dist/bollharness-integration/bollharness-integration/guard-checker.js +0 -353
  72. package/dist/bollharness-integration/bollharness-integration/index.d.ts +0 -66
  73. package/dist/bollharness-integration/bollharness-integration/index.js +0 -32
  74. package/dist/bollharness-integration/bollharness-integration/integration.d.ts +0 -219
  75. package/dist/bollharness-integration/bollharness-integration/integration.js +0 -420
  76. package/dist/bollharness-integration/bollharness-integration/skill-adapter.d.ts +0 -151
  77. package/dist/bollharness-integration/bollharness-integration/skill-adapter.js +0 -518
@@ -56,6 +56,7 @@ interface MessageStore {
56
56
  dequeueOfflineMessage(id: string): Promise<void>;
57
57
  incrementOfflineRetry(id: string): Promise<void>;
58
58
  getPendingOfflineCount(): Promise<number>;
59
+ getAllOfflineTargets(): Promise<string[]>;
59
60
  savePendingResponse(req: Omit<PendingResponse, 'id'>): Promise<PendingResponse>;
60
61
  getPendingResponse(requestId: string): Promise<PendingResponse | null>;
61
62
  removePendingResponse(requestId: string): Promise<void>;
@@ -172,6 +173,9 @@ export class IrohTransport {
172
173
  for (const queue of offlineQueues.values()) count += queue.length;
173
174
  return count;
174
175
  },
176
+ async getAllOfflineTargets() {
177
+ return Array.from(offlineQueues.keys());
178
+ },
175
179
  async savePendingResponse(req) {
176
180
  const id = crypto.randomUUID();
177
181
  const pending = { ...req, id };
@@ -196,9 +200,14 @@ export class IrohTransport {
196
200
  if (!this.messageStore) return;
197
201
 
198
202
  this.offlineDeliveryInterval = setInterval(async () => {
203
+ // 遍历所有有离线消息的目标节点(不仅是"已连接"的)
204
+ // 这样目标节点一旦在线(accept 连接)就能拿到离线消息
205
+ const allTargets = await this.messageStore!.getAllOfflineTargets();
199
206
  const connectedPeers = this.getConnectedPeers();
207
+ // 合并:已连接 + 有离线消息但未连接(也会去尝试 connect)
208
+ const targets = new Set<string>([...connectedPeers, ...allTargets]);
200
209
 
201
- for (const peerId of connectedPeers) {
210
+ for (const peerId of targets) {
202
211
  const offlineMsgs = await this.messageStore!.getOfflineMessages(peerId);
203
212
 
204
213
  for (const msg of offlineMsgs) {
@@ -216,6 +225,8 @@ export class IrohTransport {
216
225
  if (success) {
217
226
  await this.messageStore!.dequeueOfflineMessage(msg.id);
218
227
  console.log(`[IrohTransport] Delivered offline message to ${peerId.substring(0, 12)}...`);
228
+ } else {
229
+ await this.messageStore!.incrementOfflineRetry(msg.id);
219
230
  }
220
231
  } catch {
221
232
  await this.messageStore!.incrementOfflineRetry(msg.id);
@@ -461,8 +472,10 @@ export class IrohTransport {
461
472
  await send.finish();
462
473
 
463
474
  // 等待响应,带超时
475
+ // 注意: server sendResponse 后会关闭连接,导致 readToEnd 以 "connection lost" 错误 reject
476
+ // 这里我们把 readToEnd 的错误吞掉(视为流结束),只有超时才视为失败
464
477
  const response = await Promise.race([
465
- recv.readToEnd(64 * 1024),
478
+ recv.readToEnd(64 * 1024).catch(() => new Uint8Array(0)),
466
479
  new Promise<null>((_, rejectTimeout) =>
467
480
  setTimeout(() => rejectTimeout(new Error('timeout')), timeout)
468
481
  ),
@@ -546,8 +546,8 @@ export class P2PNetwork {
546
546
  const colonIdx = messageStr.indexOf(':');
547
547
  const didMarker = 'DID:';
548
548
  let did: string | undefined;
549
- let type: string;
550
- let payload: string;
549
+ let type = 'message';
550
+ let payload = '';
551
551
  let requestId: string | undefined = undefined;
552
552
 
553
553
  if (messageStr.startsWith(didMarker)) {
@@ -770,7 +770,11 @@ export class P2PNetwork {
770
770
  * Register a handler for responses (used by the receiving side)
771
771
  */
772
772
  onResponse(type: string, handler: (payload: string, from: string, did?: string, requestId?: string) => void): void {
773
- this.messageHandlers.set(type, handler);
773
+ // Store as pendingResponseHandlers-shaped wrapper. Extra args (did, requestId) are not
774
+ // available in pendingResponseHandlers signature, so ignore them when invoked.
775
+ this.pendingResponseHandlers.set(type, (responseData: string, from: string) => {
776
+ handler(responseData, from, undefined, undefined);
777
+ });
774
778
  }
775
779
 
776
780
  /**
@@ -797,11 +801,8 @@ export class P2PNetwork {
797
801
  private handleRequest(type: string, payload: string, requestId: string, fromPeerId: string, did?: string): void {
798
802
  const handler = this.messageHandlers.get(type);
799
803
  if (handler) {
800
- // Create a wrapper that sends the response
801
- const originalHandler = handler;
802
- handler = (msg: Uint8Array, from: string, didParam?: string) => {
803
- originalHandler(msg, from, didParam);
804
- };
804
+ // Forward raw payload; callers register with onMessage() and adapt as needed.
805
+ handler(new TextEncoder().encode(payload), fromPeerId, did);
805
806
  }
806
807
 
807
808
  // Check if there's a response handler registered
@@ -16,7 +16,7 @@ import type {
16
16
  MessageQueryOptions,
17
17
  StorageConfig,
18
18
  MessageStatus,
19
- } from './types.js';
19
+ } from '../types';
20
20
 
21
21
  const DEFAULT_CONFIG: Required<StorageConfig> = {
22
22
  baseDir: '',
@@ -69,7 +69,7 @@ export class JsonMessageStore implements MessageStore {
69
69
  const filePath = this.getMessageFilePath(new Date(msg.timestamp));
70
70
 
71
71
  await this.withLock(filePath, async () => {
72
- const messages = await this.readJsonFile<StoredMessage[]>(filePath) || [];
72
+ let messages = await this.readJsonFile<StoredMessage[]>(filePath) || [];
73
73
  messages.push(stored);
74
74
 
75
75
  // 如果文件过大,拆分
@@ -238,6 +238,21 @@ export class JsonMessageStore implements MessageStore {
238
238
  return count;
239
239
  }
240
240
 
241
+ async getAllOfflineTargets(): Promise<string[]> {
242
+ // 重新从磁盘加载最新状态(避免内存 vs 磁盘不一致)
243
+ const baseDir = path.join(this.config.baseDir, 'offline');
244
+ let files: string[] = [];
245
+ try {
246
+ files = await fs.readdir(baseDir);
247
+ } catch {
248
+ return Array.from(this.offlineMessages.keys());
249
+ }
250
+ return files
251
+ .filter((f) => f.endsWith('.json'))
252
+ .map((f) => f.replace(/\.json$/, ''))
253
+ .filter((id) => id.length > 0);
254
+ }
255
+
241
256
  // ============================================================================
242
257
  // 待响应请求
243
258
  // ============================================================================
@@ -3,7 +3,7 @@
3
3
  * 导出消息存储工厂函数和类型
4
4
  */
5
5
 
6
- export type {
6
+ import type {
7
7
  MessageStore,
8
8
  StoredMessage,
9
9
  OfflineMessage,
@@ -18,11 +18,27 @@ export type {
18
18
  IrohMessage,
19
19
  IrohMessageHandler,
20
20
  } from './types.js';
21
+ import { DEFAULT_STORAGE_CONFIG } from './types.js';
22
+
23
+ export type {
24
+ MessageStore,
25
+ StoredMessage,
26
+ OfflineMessage,
27
+ PendingResponse,
28
+ LocalPendingRequest,
29
+ MessageQueryOptions,
30
+ StorageConfig,
31
+ MessageDirection,
32
+ MessageStatus,
33
+ TransportType,
34
+ IrohPeer,
35
+ IrohMessage,
36
+ IrohMessageHandler,
37
+ };
21
38
 
22
- export { DEFAULT_STORAGE_CONFIG } from './types.js';
39
+ export { DEFAULT_STORAGE_CONFIG };
23
40
 
24
41
  import { JsonMessageStore } from './adapters/json-adapter.js';
25
- import type { MessageStore, StorageConfig } from './types.js';
26
42
  import * as path from 'path';
27
43
 
28
44
  // 默认存储配置
@@ -388,7 +388,7 @@ export class ChannelHeartbeatAgent {
388
388
  senderName: peer.name
389
389
  };
390
390
 
391
- const decision = this.judgmentEngine.decide(context);
391
+ const decision = await this.judgmentEngine.decide(context);
392
392
 
393
393
  if (decision.shouldCall) {
394
394
  console.log(`[HeartbeatAgent] Auto-triggering Harness: Gate ${decision.gate} for ${peer.name}`);
package/src/types.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * 缺失类型模块的兜底声明 — 让 strict tsc 通过, 避免阻塞发布。
3
+ * 这些是项目里实际使用但 @types 包未安装或缺失的小依赖。
4
+ */
5
+ declare module 'js-yaml' {
6
+ const yaml: {
7
+ load: (str: string) => any;
8
+ dump: (obj: any, opts?: any) => string;
9
+ };
10
+ export default yaml;
11
+ export = yaml;
12
+ }
@@ -283,27 +283,27 @@ function checkNpmOutdated(): OutdatedPackage[] {
283
283
  * 自动更新 npm 包
284
284
  */
285
285
  async function updatePackages(packages?: string[]): Promise<UpdateResult> {
286
- try {
287
- const args = packages && packages.length > 0
288
- ? ['npm', 'install', ...packages, '--save']
289
- : ['npm', 'install', '-g', '@bolloon/bolloon-agent'];
286
+ // 记录更新前的版本,用于事后判断"是否真的升级了"
287
+ // getInstalledVersion 的"优先读全局"保持一致 —— install 也用 -g,
288
+ // 否则判断和执行落在不同的目录,永远改不到那个被读取的版本号。
289
+ const targets = packages && packages.length > 0 ? packages : ['@bolloon/bolloon-agent'];
290
+ const before = new Map<string, string | null>();
291
+ for (const p of targets) before.set(p, getInstalledVersion(p));
292
+
293
+ const isGlobal = !packages || packages.length === 0;
294
+ const args = isGlobal
295
+ ? ['npm', 'install', '-g', ...targets]
296
+ : ['npm', 'install', ...targets, '--save'];
290
297
 
291
- log(`\n${CYAN}📦 正在更新包...${RESET}\n`, RESET);
298
+ log(`\n${CYAN}📦 正在更新包...${RESET}\n`, RESET);
292
299
 
293
- // 执行 npm install
294
- const result = execSync(args.join(' '), {
300
+ try {
301
+ execSync(args.join(' '), {
295
302
  encoding: 'utf-8',
296
303
  timeout: 300000, // 5分钟超时
297
304
  stdio: 'inherit',
298
305
  cwd: process.cwd()
299
306
  });
300
-
301
- return {
302
- success: true,
303
- updated: true,
304
- message: '更新成功',
305
- updatedPackages: packages
306
- };
307
307
  } catch (e: any) {
308
308
  return {
309
309
  success: false,
@@ -312,6 +312,37 @@ async function updatePackages(packages?: string[]): Promise<UpdateResult> {
312
312
  error: e.message
313
313
  };
314
314
  }
315
+
316
+ // install 退出码 0 并不等于"真的升上去了"("up to date" 也是 0)。
317
+ // 重新读取磁盘版本,只有真的达到目标 latest 之一才算 updated。
318
+ const upgraded: string[] = [];
319
+ const failed: string[] = [];
320
+ for (const p of targets) {
321
+ const after = getInstalledVersion(p);
322
+ const was = before.get(p);
323
+ if (after && was && compareVersions(was, after) < 0) {
324
+ upgraded.push(p);
325
+ } else if (after && was && compareVersions(was, after) === 0) {
326
+ // 版本没变 —— install 跑过但没改动;不当作"刚升级"
327
+ } else {
328
+ failed.push(p);
329
+ }
330
+ }
331
+
332
+ if (upgraded.length > 0) {
333
+ return {
334
+ success: true,
335
+ updated: true,
336
+ message: `已更新: ${upgraded.join(', ')}`,
337
+ updatedPackages: upgraded
338
+ };
339
+ }
340
+ return {
341
+ success: true,
342
+ updated: false,
343
+ message: '已是最新版本,无需重启',
344
+ updatedPackages: []
345
+ };
315
346
  }
316
347
 
317
348
  /**