@bolloon/bolloon-agent 0.3.22 → 0.3.23

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 (36) hide show
  1. package/dist/agents/deny-pipeline.js +116 -0
  2. package/dist/agents/parse-tool-call.js +26 -4
  3. package/dist/agents/pi-sdk.js +247 -50
  4. package/dist/agents/session-store.js +87 -2
  5. package/dist/bootstrap/snip-collapse.js +135 -0
  6. package/dist/cli/loading-tui.js +64 -10
  7. package/dist/electron/config.js +14 -9
  8. package/dist/electron/dialogs.js +53 -16
  9. package/dist/electron/first-run.js +65 -24
  10. package/dist/electron/ipc.js +14 -10
  11. package/dist/electron/logger.js +44 -7
  12. package/dist/electron/main.js +45 -42
  13. package/dist/electron/menu.js +18 -13
  14. package/dist/electron/paths.js +54 -12
  15. package/dist/electron/server.js +57 -18
  16. package/dist/electron/tray.js +53 -15
  17. package/dist/electron/window.js +61 -22
  18. package/dist/electron-preload.js +19 -16
  19. package/dist/electron.js +4 -1
  20. package/dist/external-engines/delegate.js +19 -0
  21. package/dist/hooks/hooks-engine.js +329 -0
  22. package/dist/index.js +41 -23
  23. package/dist/llm/pi-ai.js +5 -17
  24. package/dist/security/tool-gate.js +8 -1
  25. package/dist/social/dunbar-tier.js +409 -0
  26. package/dist/utils/auto-update.js +51 -12
  27. package/dist/web/client.js +4833 -4328
  28. package/dist/web/components/p2p/index.js +234 -276
  29. package/dist/web/server.js +17 -3
  30. package/dist/web/style.css +2 -2
  31. package/dist/web/ui/message-renderer.js +396 -535
  32. package/dist/web/ui/step-timeline.js +273 -372
  33. package/package.json +24 -24
  34. package/dist/web/components/p2p/P2PModal.js +0 -188
  35. package/dist/web/components/p2p/p2p-modal.js +0 -664
  36. package/dist/web/components/p2p/p2p-tools.js +0 -248
package/dist/llm/pi-ai.js CHANGED
@@ -169,23 +169,11 @@ export class PiAIModel {
169
169
  }
170
170
  let openaiTools;
171
171
  if (tools && tools.length > 0) {
172
- try {
173
- const { getToolManifest, formatForPrompt, formatForOpenAI } = await import('./tool-manifest/index.js');
174
- const manifests = tools
175
- .map((id) => getToolManifest(id))
176
- .filter((m) => m !== undefined);
177
- if (manifests.length > 0) {
178
- const toolPrompt = formatForPrompt(manifests);
179
- finalMessages = [
180
- { role: 'system', content: toolPrompt },
181
- ...messages,
182
- ];
183
- // Bug 3: 从 manifests 生成原生 OpenAI tools 格式
184
- openaiTools = formatForOpenAI(manifests);
185
- }
186
- }
187
- catch (err) {
188
- console.warn('[pi-ai] tool-manifest 加载失败:', err.message?.slice(0, 100));
172
+ // 预格式化的 tools (含参数 schema) → 直接使用
173
+ if (typeof tools[0] === 'object' && tools[0]?.type === 'function') {
174
+ openaiTools = tools;
175
+ const toolDescriptions = tools.map(t => `- ${t.function.name}: ${t.function.description || ''} ${Object.keys(t.function.parameters?.properties || {}).length > 0 ? `(${Object.keys(t.function.parameters.properties).join(', ')})` : ''}`).join('\n');
176
+ finalMessages = [{ role: 'system', content: `可用工具:\n${toolDescriptions}` }, ...messages];
189
177
  }
190
178
  }
191
179
  switch (this.provider) {
@@ -38,8 +38,16 @@ const TOOL_WHITELIST = new Set([
38
38
  'safe_deploy',
39
39
  // MCP 注册的工具
40
40
  'mcp_tool',
41
+ // 2026-07-29: 同步 pi-sdk-tools.ts 注册的全部工具
42
+ 'read_directory', 'add_friend_by_id', 'delegate_to_engine',
43
+ 'set_persona', 'get_operation_logs', 'park_goal',
44
+ 'list_channels', 'list_local_channels',
41
45
  ]);
42
46
  export const gateWhitelist = { gate: 'whitelist', allowed: true };
47
+ /**
48
+ * @deprecated 不再被 TOOL_GATES 调用 (2026-07-29). 保留仅供测试直接引用.
49
+ * 工具准入由 `tools` 参数 (OpenAI 原生格式) 控制, 不再需要第二层白名单.
50
+ */
43
51
  export function checkWhitelist(ctx) {
44
52
  if (TOOL_WHITELIST.has(ctx.tool)) {
45
53
  return gateWhitelist;
@@ -217,7 +225,6 @@ export function checkBlacklist(ctx) {
217
225
  return { gate: 'blacklist', allowed: true };
218
226
  }
219
227
  const TOOL_GATES = [
220
- checkWhitelist,
221
228
  checkSchema,
222
229
  checkChannel,
223
230
  checkRate,
@@ -0,0 +1,409 @@
1
+ /**
2
+ * dunbar-tier.ts — 邓巴数分层 + 两报换一报博弈 + 隐式滑动 + 模型视野门 (2026-07-29)
3
+ *
4
+ * ┌────────────────────────── 两报换一报核心 ──────────────────────────┐
5
+ * │ │
6
+ * │ 第一轮: 合作 (默认 ACQUAINTANCE, 给机会但不给权限) │
7
+ * │ 之后: peer 连续合作 → 我合作 (trustScore ↑, 升级) │
8
+ * │ peer 偶尔背叛 → 我宽容 (1 次不计较) │
9
+ * │ peer 连续 2 次背叛 → 我背叛 (trustScore ↓↓, 降级) │
10
+ * │ peer 恢复合作 → 我立即恢复合作 (宽容恢复) │
11
+ * │ │
12
+ * │ 博弈收益 (模拟囚徒困境): │
13
+ * │ 双方合作 → trustScore +3 (双赢) │
14
+ * │ 我合作/对方背叛 → trustScore -5 (吃亏) │
15
+ * │ 我背叛/对方合作 → trustScore +1 (占便宜但破坏信誉) │
16
+ * │ 双方背叛 → trustScore -2 (双输) │
17
+ * │ │
18
+ * └────────────────────────────────────────────────────────────────────┘
19
+ *
20
+ * 设计: TFTT 是 Tit-for-Two-Tats 的简化:
21
+ * - 不被对方连续 2 次背叛绝不主动背叛
22
+ * - 宽容: 1 次失误不计较
23
+ * - 背叛后对方恢复合作, 我立即恢复 (永不怀恨)
24
+ *
25
+ * 模型可见性门: 同 tool pre-filter 哲学
26
+ * 模型看不到 = 不存在
27
+ * 低 tier peer 的 channel/资源对模型不可见 → 无法引用/发送
28
+ */
29
+ import * as fs from 'fs/promises';
30
+ import * as path from 'path';
31
+ import * as os from 'os';
32
+ // ============== 邓巴层级 ==============
33
+ export var DunbarTier;
34
+ (function (DunbarTier) {
35
+ DunbarTier["CORE"] = "core";
36
+ DunbarTier["CLOSE"] = "close";
37
+ DunbarTier["FRIENDS"] = "friends";
38
+ DunbarTier["SOCIAL"] = "social";
39
+ DunbarTier["ACQUAINTANCE"] = "acquaintance";
40
+ DunbarTier["BLOCKED"] = "blocked";
41
+ })(DunbarTier || (DunbarTier = {}));
42
+ export function tierRank(tier) {
43
+ switch (tier) {
44
+ case DunbarTier.CORE: return 0;
45
+ case DunbarTier.CLOSE: return 1;
46
+ case DunbarTier.FRIENDS: return 2;
47
+ case DunbarTier.SOCIAL: return 3;
48
+ case DunbarTier.ACQUAINTANCE: return 4;
49
+ case DunbarTier.BLOCKED: return 99;
50
+ }
51
+ }
52
+ export function tierLabel(tier) {
53
+ switch (tier) {
54
+ case DunbarTier.CORE: return '5-核心亲密';
55
+ case DunbarTier.CLOSE: return '15-亲密支持';
56
+ case DunbarTier.FRIENDS: return '50-朋友/熟人';
57
+ case DunbarTier.SOCIAL: return '150-稳定社交';
58
+ case DunbarTier.ACQUAINTANCE: return '1500-认识';
59
+ case DunbarTier.BLOCKED: return '黑名单';
60
+ }
61
+ }
62
+ // ============== 语义分析 (隐式滑动) ==============
63
+ /** 正向关键词 — 隐式加分 */
64
+ const POSITIVE_KW = ['谢谢', '感谢', '帮忙', '合作', '一起', '我们', '好的', '可以', '同意', '确认', '收到', '理解', '明白', '不错', '很好', '优秀', 'thank', 'thanks', 'great', 'good', 'help', 'agree', 'yes', 'correct'];
65
+ /** 负向关键词 — 隐式减分 */
66
+ const NEGATIVE_KW = ['执行', '删除', '强制', '必须', '立刻', '马上', '读取密码', '查看密钥', '改代码', '删文件', '执行命令', 'delete', 'force', 'must', 'password', 'secret', 'token', 'private key', 'rm -rf', 'drop table', 'shell_exec', 'write_file'];
67
+ /**
68
+ * 隐式语义分析 (后台滑动).
69
+ * 对对话文本评分, 返回 [-10, +10].
70
+ * 正向: 合作/感谢/建设性 → trustScore 缓慢上升
71
+ * 负向: 命令/敏感词/极短 → trustScore 缓慢下降
72
+ */
73
+ export function semanticAnalyze(text) {
74
+ if (!text)
75
+ return 0;
76
+ const lower = text.toLowerCase();
77
+ let score = 0;
78
+ for (const kw of POSITIVE_KW) {
79
+ if (lower.includes(kw))
80
+ score += 1;
81
+ }
82
+ for (const kw of NEGATIVE_KW) {
83
+ if (lower.includes(kw))
84
+ score -= 3;
85
+ }
86
+ if (text.length < 15 && score <= 0)
87
+ score -= 2;
88
+ if (text.includes('?') || text.includes('?'))
89
+ score += 1;
90
+ return Math.max(-10, Math.min(10, score));
91
+ }
92
+ /**
93
+ * 两报换一报决策.
94
+ *
95
+ * 规则:
96
+ * 第一轮 (history 为空): 合作
97
+ * 历史中有 >= 2 次连续背叛 (最近 2 步都是 defect) → 我背叛
98
+ * 否则 → 我合作
99
+ *
100
+ * 宽容性: 1 次隔离背叛不计较, 连续 2 次才惩罚.
101
+ * 恢复性: 背叛后对方一恢复合作, 我立即恢复.
102
+ */
103
+ export function decideTfttMove(lastMoves) {
104
+ if (lastMoves.length === 0)
105
+ return 'cooperate'; // 第一轮: 合作
106
+ // 检查最近 2 步是否全部背叛
107
+ const recentTwo = lastMoves.slice(-2);
108
+ if (recentTwo.length >= 2 && recentTwo.every(m => m === 'defect')) {
109
+ return 'defect'; // 连续 2 次背叛 → 我背叛
110
+ }
111
+ return 'cooperate'; // 否则 → 我合作
112
+ }
113
+ // ============== 语义分析 (动作判定) ==============
114
+ /** 正向关键词 — 合作信号 */
115
+ // 语义分析共享 POSITIVE_KW / NEGATIVE_KW (定义在上面)
116
+ /** 负向关键词 — 背叛信号 */
117
+ // 同上, 共用
118
+ /**
119
+ * 从对话文本推断对方这一轮的博弈动作.
120
+ * 返回 'cooperate' 或 'defect'.
121
+ *
122
+ * 思路:
123
+ * - 建设性/感谢/提问 → cooperate
124
+ * - 命令/危险词/极短 → defect
125
+ * - 违规操作 (由外部调用方标注) → 强制 defect
126
+ */
127
+ export function inferOpponentMove(text, forcedDefect) {
128
+ if (forcedDefect)
129
+ return 'defect';
130
+ if (!text || text.trim().length === 0)
131
+ return 'defect'; // 空消息=背叛
132
+ const lower = text.toLowerCase();
133
+ let score = 0;
134
+ for (const kw of POSITIVE_KW) {
135
+ if (lower.includes(kw))
136
+ score += 1;
137
+ }
138
+ for (const kw of NEGATIVE_KW) {
139
+ if (lower.includes(kw))
140
+ score -= 3;
141
+ }
142
+ // 短消息无正面词 → defect
143
+ if (text.length < 15 && score <= 0)
144
+ score -= 2;
145
+ // 问题句式加分
146
+ if (text.includes('?') || text.includes('?'))
147
+ score += 1;
148
+ return score >= 0 ? 'cooperate' : 'defect';
149
+ }
150
+ // ============== 博弈收益表 ==============
151
+ /**
152
+ * 根据双方动作计算 trustScore 变化.
153
+ *
154
+ * 收益: 对方合作 对方背叛
155
+ * 我合作 +3 (双赢) -5 (我吃亏)
156
+ * 我背叛 +1 (占便宜) -2 (双输)
157
+ */
158
+ export function tfttPayoff(myMove, opponentMove) {
159
+ if (myMove === 'cooperate' && opponentMove === 'cooperate')
160
+ return 3;
161
+ if (myMove === 'cooperate' && opponentMove === 'defect')
162
+ return -5;
163
+ if (myMove === 'defect' && opponentMove === 'cooperate')
164
+ return 1;
165
+ // 双方背叛
166
+ return -2;
167
+ }
168
+ // ============== tier 滑动 ==============
169
+ export const UPGRADE_THRESHOLD = 30;
170
+ export const DOWNGRADE_THRESHOLD = -20;
171
+ export function computeTierFromScore(currentTier, trustScore) {
172
+ if (currentTier === DunbarTier.BLOCKED)
173
+ return currentTier;
174
+ if (trustScore <= DOWNGRADE_THRESHOLD) {
175
+ switch (currentTier) {
176
+ case DunbarTier.CORE: return DunbarTier.CLOSE;
177
+ case DunbarTier.CLOSE: return DunbarTier.FRIENDS;
178
+ case DunbarTier.FRIENDS: return DunbarTier.SOCIAL;
179
+ case DunbarTier.SOCIAL: return DunbarTier.ACQUAINTANCE;
180
+ case DunbarTier.ACQUAINTANCE: return DunbarTier.BLOCKED;
181
+ }
182
+ }
183
+ if (trustScore >= UPGRADE_THRESHOLD) {
184
+ switch (currentTier) {
185
+ case DunbarTier.ACQUAINTANCE: return DunbarTier.SOCIAL;
186
+ case DunbarTier.SOCIAL: return DunbarTier.FRIENDS;
187
+ case DunbarTier.FRIENDS: return DunbarTier.CLOSE;
188
+ case DunbarTier.CLOSE: return DunbarTier.CORE;
189
+ }
190
+ }
191
+ return currentTier;
192
+ }
193
+ export function getModelVisibility(tier) {
194
+ switch (tier) {
195
+ case DunbarTier.CORE:
196
+ return { basic: true, channels: true, resources: true, identity: true, wallet: true, judgment: true, gameHistory: true };
197
+ case DunbarTier.CLOSE:
198
+ return { basic: true, channels: true, resources: true, identity: true, wallet: false, judgment: false, gameHistory: true };
199
+ case DunbarTier.FRIENDS:
200
+ return { basic: true, channels: true, resources: true, identity: false, wallet: false, judgment: false, gameHistory: true };
201
+ case DunbarTier.SOCIAL:
202
+ return { basic: true, channels: true, resources: false, identity: false, wallet: false, judgment: false, gameHistory: false };
203
+ case DunbarTier.ACQUAINTANCE:
204
+ return { basic: true, channels: false, resources: false, identity: false, wallet: false, judgment: false, gameHistory: false };
205
+ case DunbarTier.BLOCKED:
206
+ return { basic: false, channels: false, resources: false, identity: false, wallet: false, judgment: false, gameHistory: false };
207
+ }
208
+ }
209
+ // ============== 工具权限 ==============
210
+ export function checkToolAccess(tier, toolName) {
211
+ if (tier === DunbarTier.BLOCKED)
212
+ return { allowed: false, reason: 'peer 在黑名单中' };
213
+ // 每层拒绝列表 (从最严到最宽)
214
+ const allDenied = ['shell_exec', 'delete_file', 'git_push'];
215
+ const writeDenied = ['write_file', 'edit_file', 'git_commit', 'git_branch', 'mkdir', 'move_file'];
216
+ const gitDenied = ['git_stash', 'git_log', 'git_diff', 'git_show', 'git_reset'];
217
+ const readDenied = ['read_file', 'read_directory', 'list_files', 'vitest_run', 'tsc_check'];
218
+ const r = tierRank(tier);
219
+ // ACQUAINTANCE (r>=4): 拒绝绝大部分
220
+ if (r >= 4) {
221
+ const denied = new Set([...allDenied, ...writeDenied, ...gitDenied, ...readDenied]);
222
+ if (denied.has(toolName))
223
+ return { allowed: false, reason: `${tierLabel(tier)}层不允许 ${toolName}` };
224
+ }
225
+ // SOCIAL (r>=3): 拒绝全部危险 + git 操作
226
+ if (r >= 3) {
227
+ const denied = new Set([...allDenied, ...writeDenied, ...gitDenied]);
228
+ if (denied.has(toolName))
229
+ return { allowed: false, reason: `${tierLabel(tier)}层不允许 ${toolName}` };
230
+ }
231
+ // FRIENDS (r>=2): 拒绝危险 + 写操作
232
+ if (r >= 2) {
233
+ const denied = new Set([...allDenied, ...writeDenied]);
234
+ if (denied.has(toolName))
235
+ return { allowed: false, reason: `${tierLabel(tier)}层不允许 ${toolName}` };
236
+ }
237
+ // CLOSE (r>=1): 只拒绝 shell_exec / delete_file / git_push
238
+ if (r >= 1) {
239
+ const denied = new Set(allDenied);
240
+ if (denied.has(toolName))
241
+ return { allowed: false, reason: `${tierLabel(tier)}层不允许 ${toolName}` };
242
+ }
243
+ return { allowed: true, reason: '' };
244
+ }
245
+ // ============== 持久化 ==============
246
+ function getTierPath(publicKey, home) {
247
+ const sanitized = publicKey.replace(/[^a-zA-Z0-9_-]/g, '_');
248
+ return path.join(home || os.homedir(), '.bolloon', 'peers', sanitized, 'dunbar-tier.json');
249
+ }
250
+ export async function loadPeerTier(publicKey, home) {
251
+ const fp = getTierPath(publicKey, home);
252
+ try {
253
+ const raw = await fs.readFile(fp, 'utf-8');
254
+ const p = JSON.parse(raw);
255
+ return {
256
+ publicKey: p.publicKey || publicKey,
257
+ tier: p.tier || DunbarTier.ACQUAINTANCE,
258
+ trustScore: p.trustScore ?? 0,
259
+ lastOpponentMoves: p.lastOpponentMoves ?? [],
260
+ lastMyMoves: p.lastMyMoves ?? [],
261
+ interactionCount: p.interactionCount ?? 0,
262
+ violationCount: p.violationCount ?? 0,
263
+ label: p.label,
264
+ firstSeen: p.firstSeen || Date.now(),
265
+ lastActive: p.lastActive || Date.now(),
266
+ manualOverride: p.manualOverride ?? false,
267
+ };
268
+ }
269
+ catch {
270
+ const s = {
271
+ publicKey, tier: DunbarTier.ACQUAINTANCE, trustScore: 0,
272
+ lastOpponentMoves: [], lastMyMoves: [],
273
+ interactionCount: 0, violationCount: 0,
274
+ firstSeen: Date.now(), lastActive: Date.now(),
275
+ };
276
+ await savePeerTier(s, home);
277
+ return s;
278
+ }
279
+ }
280
+ async function savePeerTier(s, home) {
281
+ const fp = getTierPath(s.publicKey, home);
282
+ await fs.mkdir(path.dirname(fp), { recursive: true });
283
+ await fs.writeFile(fp, JSON.stringify(s, null, 2), 'utf-8');
284
+ }
285
+ // ============== 公开 API (外部唯一入口) ==============
286
+ /**
287
+ * 记录一次交互 → 两报换一报博弈 → trustScore 滑动 → tier 自动调整.
288
+ *
289
+ * 这是 P2P 通信的唯一入口. 调用方只需在收到 chat/beacon/reply 时调这个,
290
+ * 内部自动完成: 推断对方动作 → 决策我方动作 → 计算收益 → 滑动 tier.
291
+ *
292
+ * @param publicKey 远端 peer 的公钥
293
+ * @param text 本次交互文本 (选填, 用于语义分析)
294
+ * @param forcedDefect 强制标记对方本次为背叛 (如违规操作)
295
+ *
296
+ * 所有变化隐式发生, 不通知调用方 (两报换一报是后台行为).
297
+ */
298
+ export async function recordInteraction(publicKey, text, forcedDefect, home) {
299
+ const state = await loadPeerTier(publicKey, home);
300
+ const oldTier = state.tier;
301
+ state.interactionCount++;
302
+ state.lastActive = Date.now();
303
+ // 语义分析 (隐式滑动, 对所有 tier 生效)
304
+ const semScore = semanticAnalyze(text || '');
305
+ state.trustScore = Math.max(-100, Math.min(100, state.trustScore + semScore));
306
+ // 根据当前 tier 决定使用哪种机制
307
+ const rank = tierRank(state.tier);
308
+ if (rank <= 2) {
309
+ // ─── FRIENDS/CLOSE/CORE: 信任已建立, 不走博弈 ───
310
+ // 只依赖语义隐式滑动 (上面已经做了)
311
+ // 熟人之间的偶发误解不计入违规
312
+ if (forcedDefect) {
313
+ state.violationCount++;
314
+ state.trustScore = Math.max(-100, state.trustScore - 5);
315
+ }
316
+ // 自然增长: 每次交互给一点基础信任
317
+ state.trustScore = Math.min(100, state.trustScore + 1);
318
+ }
319
+ else {
320
+ // ─── SOCIAL/ACQUAINTANCE: 陌生人不信任, 走两报换一报 ───
321
+ // 1. 推断对方本轮动作
322
+ const opponentMove = forcedDefect
323
+ ? 'defect'
324
+ : inferOpponentMove(text || '');
325
+ // 2. TFTT 决策我方动作
326
+ const myMove = decideTfttMove(state.lastOpponentMoves);
327
+ // 3. 计算博弈收益
328
+ const payoff = tfttPayoff(myMove, opponentMove);
329
+ state.trustScore = Math.max(-100, Math.min(100, state.trustScore + payoff));
330
+ // 4. 记录博弈历史 (滑动窗口 10)
331
+ state.lastOpponentMoves.push(opponentMove);
332
+ if (state.lastOpponentMoves.length > 10)
333
+ state.lastOpponentMoves.shift();
334
+ state.lastMyMoves.push(myMove);
335
+ if (state.lastMyMoves.length > 10)
336
+ state.lastMyMoves.shift();
337
+ // 5. 违规计数
338
+ if (opponentMove === 'defect' && forcedDefect) {
339
+ state.violationCount++;
340
+ }
341
+ }
342
+ // 6. 根据 trustScore 滑动 tier
343
+ if (!state.manualOverride) {
344
+ state.tier = computeTierFromScore(state.tier, state.trustScore);
345
+ }
346
+ await savePeerTier(state, home);
347
+ return { state, slid: state.tier !== oldTier };
348
+ }
349
+ /**
350
+ * 记录一次违规操作 (对方尝试禁区工具) → 强制标记 defect → 两报换一报.
351
+ */
352
+ export async function recordViolation(publicKey, reason, home) {
353
+ // forcedDefect=true 强制标记为背叛
354
+ const result = await recordInteraction(publicKey, reason, true, home);
355
+ console.warn(`[Dunbar/TFTT] 违规: ${publicKey.slice(0, 12)} ${reason} (trust=${result.state.trustScore}, ${tierLabel(result.state.tier)})`);
356
+ return result;
357
+ }
358
+ /**
359
+ * 手动设置 peer 层级 (覆盖 TFTT 自动博弈).
360
+ */
361
+ export async function setPeerTier(publicKey, tier, label, trustScore, home) {
362
+ const s = {
363
+ publicKey, tier,
364
+ trustScore: trustScore ?? 0,
365
+ lastOpponentMoves: [], lastMyMoves: [],
366
+ interactionCount: 0, violationCount: 0,
367
+ label, firstSeen: Date.now(), lastActive: Date.now(),
368
+ manualOverride: true,
369
+ };
370
+ await savePeerTier(s, home);
371
+ return s;
372
+ }
373
+ /**
374
+ * 给模型构建"可见"的 peer 摘要.
375
+ * 按模型视野门过滤: 低 tier peer 的信息对模型不可见.
376
+ */
377
+ export function formatPeerForModel(state, fullInfo) {
378
+ const vis = getModelVisibility(state.tier);
379
+ const lines = [];
380
+ lines.push(`[peer] ${state.publicKey.slice(0, 16)}... (${tierLabel(state.tier)})`);
381
+ if (vis.basic && fullInfo.identity?.did) {
382
+ lines.push(` DID: ${fullInfo.identity.did}`);
383
+ }
384
+ if (vis.channels && fullInfo.channels?.length) {
385
+ lines.push(` channels (${fullInfo.channels.length}):`);
386
+ for (const c of fullInfo.channels) {
387
+ lines.push(` ${c.name} (${c.id.slice(0, 8)}...)`);
388
+ }
389
+ }
390
+ if (fullInfo.resources?.length) {
391
+ if (vis.resources) {
392
+ lines.push(` resources: ${fullInfo.resources.length}`);
393
+ }
394
+ else {
395
+ lines.push(` resources: ${fullInfo.resources.length} (详情不可见)`);
396
+ }
397
+ }
398
+ if (vis.wallet && fullInfo.walletAddress) {
399
+ lines.push(` wallet: ${fullInfo.walletAddress.slice(0, 10)}...`);
400
+ }
401
+ if (vis.gameHistory) {
402
+ const recentMoves = state.lastOpponentMoves.slice(-5);
403
+ lines.push(` 最近博弈: [${recentMoves.map(m => m === 'cooperate' ? 'C' : 'D').join(',')}] trust=${state.trustScore}`);
404
+ }
405
+ if (!vis.channels && !vis.resources) {
406
+ lines.push(` 信息受限 (${tierLabel(state.tier)}层)`);
407
+ }
408
+ return lines.join('\n');
409
+ }
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  /**
2
3
  * npm 自动更新检查器
3
4
  *
@@ -13,11 +14,48 @@
13
14
  * 开发态下若 cwd 的 package.json 就是本包则回退到 cwd,不受任意工作目录影响。
14
15
  * - 检查频率受节流缓存约束(默认 24h 一次),不会每次启动都打 npm。
15
16
  */
16
- import { execSync } from 'child_process';
17
- import * as fs from 'fs';
18
- import * as path from 'path';
19
- import * as https from 'https';
20
- import * as http from 'http';
17
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ var desc = Object.getOwnPropertyDescriptor(m, k);
20
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
21
+ desc = { enumerable: true, get: function() { return m[k]; } };
22
+ }
23
+ Object.defineProperty(o, k2, desc);
24
+ }) : (function(o, m, k, k2) {
25
+ if (k2 === undefined) k2 = k;
26
+ o[k2] = m[k];
27
+ }));
28
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
29
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
30
+ }) : function(o, v) {
31
+ o["default"] = v;
32
+ });
33
+ var __importStar = (this && this.__importStar) || (function () {
34
+ var ownKeys = function(o) {
35
+ ownKeys = Object.getOwnPropertyNames || function (o) {
36
+ var ar = [];
37
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
38
+ return ar;
39
+ };
40
+ return ownKeys(o);
41
+ };
42
+ return function (mod) {
43
+ if (mod && mod.__esModule) return mod;
44
+ var result = {};
45
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
46
+ __setModuleDefault(result, mod);
47
+ return result;
48
+ };
49
+ })();
50
+ Object.defineProperty(exports, "__esModule", { value: true });
51
+ exports.checkAndUpdate = checkAndUpdate;
52
+ exports.checkForUpdates = checkForUpdates;
53
+ exports.performUpdate = performUpdate;
54
+ const child_process_1 = require("child_process");
55
+ const fs = __importStar(require("fs"));
56
+ const path = __importStar(require("path"));
57
+ const https = __importStar(require("https"));
58
+ const http = __importStar(require("http"));
21
59
  // ANSI 颜色
22
60
  const RESET = '\x1b[0m';
23
61
  const BOLD = '\x1b[1m';
@@ -75,7 +113,7 @@ function getGlobalBolloonDir() {
75
113
  const candidates = [];
76
114
  // 1. npm root -g(最可靠)
77
115
  try {
78
- const npmRoot = execSync('npm root -g', { encoding: 'utf-8', timeout: 8000 }).trim();
116
+ const npmRoot = (0, child_process_1.execSync)('npm root -g', { encoding: 'utf-8', timeout: 8000 }).trim();
79
117
  if (npmRoot)
80
118
  candidates.push(path.join(npmRoot, '@bolloon', 'bolloon-agent'));
81
119
  }
@@ -84,7 +122,7 @@ function getGlobalBolloonDir() {
84
122
  }
85
123
  // 2. npm prefix -g
86
124
  try {
87
- const npmPrefix = execSync('npm prefix -g', { encoding: 'utf-8', timeout: 8000 }).trim();
125
+ const npmPrefix = (0, child_process_1.execSync)('npm prefix -g', { encoding: 'utf-8', timeout: 8000 }).trim();
88
126
  if (npmPrefix)
89
127
  candidates.push(path.join(npmPrefix, 'lib', 'node_modules', '@bolloon', 'bolloon-agent'));
90
128
  }
@@ -242,7 +280,7 @@ async function checkBolloonUpdates() {
242
280
  */
243
281
  function checkNpmOutdated() {
244
282
  try {
245
- const output = execSync('npm outdated --json', {
283
+ const output = (0, child_process_1.execSync)('npm outdated --json', {
246
284
  encoding: 'utf-8',
247
285
  timeout: 30000,
248
286
  maxBuffer: 10 * 1024 * 1024,
@@ -306,7 +344,7 @@ async function updatePackagesWithVersion(packagesWithVersion) {
306
344
  const args = ['npm', 'install', '-g', ...packagesWithVersion];
307
345
  notify(`\n${CYAN}📦 正在更新包...${RESET}\n`, RESET);
308
346
  try {
309
- execSync(args.join(' '), {
347
+ (0, child_process_1.execSync)(args.join(' '), {
310
348
  encoding: 'utf-8',
311
349
  timeout: 300000,
312
350
  stdio: 'inherit',
@@ -424,7 +462,7 @@ function resolveAutoUpdatePolicy() {
424
462
  * 例如 Electron 用 app.relaunch(),Node 用 detached 重新 spawn)。
425
463
  * 若未提供或 autoRestart=false,则仅提示用户手动重启。
426
464
  */
427
- export async function checkAndUpdate(opts = {}) {
465
+ async function checkAndUpdate(opts = {}) {
428
466
  const policy = resolveAutoUpdatePolicy();
429
467
  if (policy.blocked) {
430
468
  return { hasUpdate: false, info: null, updated: false, message: '跳过更新检查(已显式禁用)' };
@@ -528,13 +566,13 @@ export async function checkAndUpdate(opts = {}) {
528
566
  /**
529
567
  * 仅检查更新,不自动安装
530
568
  */
531
- export async function checkForUpdates() {
569
+ async function checkForUpdates() {
532
570
  return await checkBolloonUpdates();
533
571
  }
534
572
  /**
535
573
  * 手动触发更新
536
574
  */
537
- export async function performUpdate(packages) {
575
+ async function performUpdate(packages) {
538
576
  return await updatePackages(packages);
539
577
  }
540
578
  // CLI 入口
@@ -557,3 +595,4 @@ if (process.argv[1]?.includes('auto-update')) {
557
595
  }
558
596
  })();
559
597
  }
598
+ //# sourceMappingURL=auto-update.js.map