@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.
- package/dist/agents/p2p-chat-tools.js +321 -0
- package/dist/agents/p2p-document-tools.js +121 -1
- package/dist/agents/pi-sdk.js +185 -0
- package/dist/agents/shell-guard.js +354 -0
- package/dist/agents/shell-tool.js +83 -0
- package/dist/agents/skill-loader.js +174 -0
- package/dist/agents/workflow-pivot-loop.js +4 -4
- package/dist/bollharness-integration/context-chain-router.js +3 -3
- package/dist/bollharness-integration/context-router.js +1 -1
- package/dist/cli-entry.js +1 -1
- package/dist/documents/reader.js +5 -0
- package/dist/documents/store.js +1 -1
- package/dist/heartbeat/Watchdog.js +7 -5
- package/dist/heartbeat/index.js +1 -0
- package/dist/heartbeat/self-improve-bus.js +85 -0
- package/dist/llm/pi-ai.js +6 -5
- package/dist/network/iroh-discovery.js +2 -1
- package/dist/network/iroh-transport.js +15 -2
- package/dist/network/p2p.js +9 -8
- package/dist/network/storage/adapters/json-adapter.js +16 -1
- package/dist/network/storage/index.js +2 -1
- package/dist/pi-ecosystem-judgment/index.js +42 -115
- package/dist/social/channels/channel-heartbeat-agent.js +1 -1
- package/dist/utils/auto-update.js +44 -12
- package/dist/web/client.js +839 -103
- package/dist/web/index.html +100 -8
- package/dist/web/server.js +568 -98
- package/dist/web/style.css +506 -9
- package/package.json +2 -2
- package/scripts/build-cli.js +11 -1
- package/scripts/build-web.ts +1 -1
- package/src/agents/p2p-chat-tools.ts +383 -0
- package/src/agents/p2p-document-tools.ts +151 -1
- package/src/agents/pi-sdk.ts +196 -0
- package/src/agents/shell-guard.ts +417 -0
- package/src/agents/shell-tool.ts +103 -0
- package/src/agents/skill-loader.ts +202 -0
- package/src/agents/workflow-pivot-loop.ts +13 -12
- package/src/bollharness-integration/channel-judgment-engine.ts +1 -1
- package/src/bollharness-integration/context-chain-router.ts +3 -3
- package/src/bollharness-integration/context-router.ts +1 -1
- package/src/documents/reader.ts +5 -0
- package/src/documents/store.ts +1 -1
- package/src/heartbeat/Watchdog.ts +7 -5
- package/src/heartbeat/index.ts +1 -0
- package/src/heartbeat/self-improve-bus.ts +110 -0
- package/src/llm/pi-ai.ts +6 -5
- package/src/network/iroh-discovery.ts +2 -1
- package/src/network/iroh-transport.ts +15 -2
- package/src/network/p2p.ts +9 -8
- package/src/network/storage/adapters/json-adapter.ts +17 -2
- package/src/network/storage/index.ts +19 -3
- package/src/social/channels/channel-heartbeat-agent.ts +1 -1
- package/src/types.d.ts +12 -0
- package/src/utils/auto-update.ts +45 -14
- package/src/web/client.js +839 -103
- package/src/web/index.html +88 -8
- package/src/web/server.ts +577 -102
- package/src/web/style.css +506 -9
- package/tsconfig.electron.json +1 -1
- package/tsconfig.json +1 -1
- package/dist/bollharness-integration/bollharness-integration/context-router-judgment.d.ts +0 -48
- package/dist/bollharness-integration/bollharness-integration/context-router-judgment.js +0 -261
- package/dist/bollharness-integration/bollharness-integration/context-router.d.ts +0 -110
- package/dist/bollharness-integration/bollharness-integration/context-router.js +0 -542
- package/dist/bollharness-integration/bollharness-integration/gate-state-machine.d.ts +0 -87
- package/dist/bollharness-integration/bollharness-integration/gate-state-machine.js +0 -231
- package/dist/bollharness-integration/bollharness-integration/gate-transition-hooks.d.ts +0 -30
- package/dist/bollharness-integration/bollharness-integration/gate-transition-hooks.js +0 -91
- package/dist/bollharness-integration/bollharness-integration/guard-checker.d.ts +0 -105
- package/dist/bollharness-integration/bollharness-integration/guard-checker.js +0 -353
- package/dist/bollharness-integration/bollharness-integration/index.d.ts +0 -66
- package/dist/bollharness-integration/bollharness-integration/index.js +0 -32
- package/dist/bollharness-integration/bollharness-integration/integration.d.ts +0 -219
- package/dist/bollharness-integration/bollharness-integration/integration.js +0 -420
- package/dist/bollharness-integration/bollharness-integration/skill-adapter.d.ts +0 -151
- 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
|
|
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
|
),
|
package/src/network/p2p.ts
CHANGED
|
@@ -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
|
|
550
|
-
let payload
|
|
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
|
-
|
|
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
|
-
//
|
|
801
|
-
|
|
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 '
|
|
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
|
-
|
|
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
|
-
|
|
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 }
|
|
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
package/src/utils/auto-update.ts
CHANGED
|
@@ -283,27 +283,27 @@ function checkNpmOutdated(): OutdatedPackage[] {
|
|
|
283
283
|
* 自动更新 npm 包
|
|
284
284
|
*/
|
|
285
285
|
async function updatePackages(packages?: string[]): Promise<UpdateResult> {
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
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
|
-
|
|
298
|
+
log(`\n${CYAN}📦 正在更新包...${RESET}\n`, RESET);
|
|
292
299
|
|
|
293
|
-
|
|
294
|
-
|
|
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
|
/**
|