hypercore-cli 1.1.0

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 (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +110 -0
  3. package/dist/api-XGC7D5AW.js +162 -0
  4. package/dist/auth-DNQWYQKT.js +21 -0
  5. package/dist/background-2EGCAAQH.js +14 -0
  6. package/dist/backlog-Q2NZCLNY.js +24 -0
  7. package/dist/chunk-2CMSCWQW.js +162 -0
  8. package/dist/chunk-2LJ2DVEB.js +167 -0
  9. package/dist/chunk-3RPFCQKJ.js +288 -0
  10. package/dist/chunk-43OLRXM5.js +263 -0
  11. package/dist/chunk-4DVYJAJL.js +57 -0
  12. package/dist/chunk-6OL3GA3P.js +173 -0
  13. package/dist/chunk-AUHU7ALH.js +2023 -0
  14. package/dist/chunk-B6A2AKLN.js +139 -0
  15. package/dist/chunk-BE46C7JW.js +46 -0
  16. package/dist/chunk-CUVAUOXL.js +58 -0
  17. package/dist/chunk-GH7E2OJE.js +223 -0
  18. package/dist/chunk-GOOTEPBK.js +271 -0
  19. package/dist/chunk-GPPMJYSM.js +133 -0
  20. package/dist/chunk-GU2FZQ6A.js +69 -0
  21. package/dist/chunk-IOPKN5GD.js +190 -0
  22. package/dist/chunk-IXOIOGR5.js +1505 -0
  23. package/dist/chunk-KRPOPWGA.js +251 -0
  24. package/dist/chunk-MGLJ53QN.js +219 -0
  25. package/dist/chunk-MV4TTRYX.js +533 -0
  26. package/dist/chunk-OPZYEVYR.js +150 -0
  27. package/dist/chunk-QTSLP47C.js +166 -0
  28. package/dist/chunk-R3GPQC7I.js +393 -0
  29. package/dist/chunk-RKB2JOV2.js +43 -0
  30. package/dist/chunk-RNG3K465.js +80 -0
  31. package/dist/chunk-TGTYKBGC.js +86 -0
  32. package/dist/chunk-U5SGAIMM.js +681 -0
  33. package/dist/chunk-V5UHPPSY.js +140 -0
  34. package/dist/chunk-WHLVZCQY.js +245 -0
  35. package/dist/chunk-XDRCBMZZ.js +66 -0
  36. package/dist/chunk-XOS6HPEF.js +134 -0
  37. package/dist/chunk-ZSBHUGWR.js +262 -0
  38. package/dist/claude-NSQ442XD.js +12 -0
  39. package/dist/commands-CK3WFAGI.js +128 -0
  40. package/dist/commands-U63OEO5J.js +1044 -0
  41. package/dist/commands-ZE6GD3WC.js +232 -0
  42. package/dist/config-4EW42BSF.js +8 -0
  43. package/dist/config-loader-SXO674TF.js +24 -0
  44. package/dist/diagnose-AFW3ZTZ4.js +12 -0
  45. package/dist/display-IIUBEYWN.js +58 -0
  46. package/dist/extractor-QV53W2YJ.js +129 -0
  47. package/dist/history-WMSCHERZ.js +180 -0
  48. package/dist/index.d.ts +1 -0
  49. package/dist/index.js +406 -0
  50. package/dist/instance-registry-YSIJXSO7.js +15 -0
  51. package/dist/keybindings-JAAMLH3G.js +15 -0
  52. package/dist/loader-WHNTZTLP.js +58 -0
  53. package/dist/network-MM6YWPGO.js +279 -0
  54. package/dist/notify-HPTALZDC.js +14 -0
  55. package/dist/openai-compat-UQWJXBEK.js +12 -0
  56. package/dist/permissions-JUKXMNDH.js +10 -0
  57. package/dist/prompt-QV45TXRL.js +166 -0
  58. package/dist/quality-ST7PPNFR.js +16 -0
  59. package/dist/repl-RT3AHL7M.js +3375 -0
  60. package/dist/roadmap-5OBEKROY.js +17 -0
  61. package/dist/server-PORT7OEG.js +57 -0
  62. package/dist/session-4VUNDWLH.js +21 -0
  63. package/dist/skills-V4A35XKG.js +175 -0
  64. package/dist/store-Y4LU5QTO.js +25 -0
  65. package/dist/team-HO7Z4SIM.js +385 -0
  66. package/dist/telemetry-6R4EIE6O.js +30 -0
  67. package/dist/test-runner-ZQH5Y6OJ.js +619 -0
  68. package/dist/theme-3SYJ3UQA.js +14 -0
  69. package/dist/upgrade-7TGI3SXO.js +83 -0
  70. package/dist/verify-JUDKTPKZ.js +14 -0
  71. package/dist/web/static/app.js +562 -0
  72. package/dist/web/static/index.html +132 -0
  73. package/dist/web/static/mirror.css +1001 -0
  74. package/dist/web/static/mirror.html +184 -0
  75. package/dist/web/static/mirror.js +1125 -0
  76. package/dist/web/static/onboard.css +302 -0
  77. package/dist/web/static/onboard.html +140 -0
  78. package/dist/web/static/onboard.js +260 -0
  79. package/dist/web/static/style.css +602 -0
  80. package/dist/web/static/workspace.css +1568 -0
  81. package/dist/web/static/workspace.html +408 -0
  82. package/dist/web/static/workspace.js +1683 -0
  83. package/dist/web-Z5HSCQHW.js +39 -0
  84. package/package.json +67 -0
@@ -0,0 +1,681 @@
1
+ import {
2
+ broadcastToTeam,
3
+ sendToMember
4
+ } from "./chunk-2LJ2DVEB.js";
5
+ import {
6
+ listTasks,
7
+ loadTeam
8
+ } from "./chunk-6OL3GA3P.js";
9
+ import {
10
+ generateId
11
+ } from "./chunk-XDRCBMZZ.js";
12
+ import {
13
+ callLLM,
14
+ createLLMClient
15
+ } from "./chunk-43OLRXM5.js";
16
+ import {
17
+ callOpenAILLM
18
+ } from "./chunk-GOOTEPBK.js";
19
+ import {
20
+ MODEL_ALIASES,
21
+ MODEL_PROVIDERS
22
+ } from "./chunk-V5UHPPSY.js";
23
+
24
+ // src/network/store.ts
25
+ import fs from "fs/promises";
26
+ import path from "path";
27
+ import os from "os";
28
+
29
+ // src/network/types.ts
30
+ var DEFAULT_NETWORK_CONFIG = {
31
+ autoEnabled: false,
32
+ autoIntervalMs: 4 * 60 * 60 * 1e3,
33
+ // 4 小时
34
+ budgetPerRoundUSD: 0.5,
35
+ matchmakerModel: "flash",
36
+ dialogueModel: "flash",
37
+ maxDialogueTurns: 3,
38
+ maxMatchPairs: 5
39
+ };
40
+
41
+ // src/network/store.ts
42
+ function networkDir(teamId) {
43
+ return path.join(os.homedir(), ".hypercore", "teams", teamId, "network");
44
+ }
45
+ function profilesDir(teamId) {
46
+ return path.join(networkDir(teamId), "profiles");
47
+ }
48
+ function roundsDir(teamId) {
49
+ return path.join(networkDir(teamId), "rounds");
50
+ }
51
+ function configPath(teamId) {
52
+ return path.join(networkDir(teamId), "config.json");
53
+ }
54
+ async function ensureDir(dir) {
55
+ await fs.mkdir(dir, { recursive: true });
56
+ }
57
+ async function saveProfile(teamId, profile) {
58
+ const dir = profilesDir(teamId);
59
+ await ensureDir(dir);
60
+ await fs.writeFile(
61
+ path.join(dir, `${profile.memberId}.json`),
62
+ JSON.stringify(profile, null, 2),
63
+ "utf-8"
64
+ );
65
+ }
66
+ async function loadProfile(teamId, memberId) {
67
+ try {
68
+ const data = await fs.readFile(
69
+ path.join(profilesDir(teamId), `${memberId}.json`),
70
+ "utf-8"
71
+ );
72
+ return JSON.parse(data);
73
+ } catch {
74
+ return null;
75
+ }
76
+ }
77
+ async function loadAllProfiles(teamId) {
78
+ const dir = profilesDir(teamId);
79
+ try {
80
+ const files = await fs.readdir(dir);
81
+ const profiles = [];
82
+ for (const file of files) {
83
+ if (file.endsWith(".json")) {
84
+ const data = await fs.readFile(path.join(dir, file), "utf-8");
85
+ profiles.push(JSON.parse(data));
86
+ }
87
+ }
88
+ return profiles;
89
+ } catch {
90
+ return [];
91
+ }
92
+ }
93
+ async function saveRound(teamId, round) {
94
+ const dir = roundsDir(teamId);
95
+ await ensureDir(dir);
96
+ await fs.writeFile(
97
+ path.join(dir, `${round.id}.json`),
98
+ JSON.stringify(round, null, 2),
99
+ "utf-8"
100
+ );
101
+ }
102
+ async function loadRound(teamId, roundId) {
103
+ try {
104
+ const data = await fs.readFile(
105
+ path.join(roundsDir(teamId), `${roundId}.json`),
106
+ "utf-8"
107
+ );
108
+ return JSON.parse(data);
109
+ } catch {
110
+ return null;
111
+ }
112
+ }
113
+ async function listRounds(teamId) {
114
+ const dir = roundsDir(teamId);
115
+ try {
116
+ const files = await fs.readdir(dir);
117
+ const rounds = [];
118
+ for (const file of files) {
119
+ if (file.endsWith(".json")) {
120
+ const data = await fs.readFile(path.join(dir, file), "utf-8");
121
+ rounds.push(JSON.parse(data));
122
+ }
123
+ }
124
+ rounds.sort((a, b) => new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime());
125
+ return rounds;
126
+ } catch {
127
+ return [];
128
+ }
129
+ }
130
+ async function getLatestRound(teamId) {
131
+ const rounds = await listRounds(teamId);
132
+ return rounds[0] || null;
133
+ }
134
+ async function loadNetworkConfig(teamId) {
135
+ try {
136
+ const data = await fs.readFile(configPath(teamId), "utf-8");
137
+ return { ...DEFAULT_NETWORK_CONFIG, ...JSON.parse(data) };
138
+ } catch {
139
+ return { ...DEFAULT_NETWORK_CONFIG };
140
+ }
141
+ }
142
+ async function saveNetworkConfig(teamId, config) {
143
+ await ensureDir(networkDir(teamId));
144
+ await fs.writeFile(configPath(teamId), JSON.stringify(config, null, 2), "utf-8");
145
+ }
146
+
147
+ // src/network/profile.ts
148
+ async function gatherProfile(teamId, memberId, memberName) {
149
+ const existing = await loadProfile(teamId, memberId);
150
+ const tasks = await listTasks(teamId);
151
+ const myTasks = tasks.filter((t) => t.assignee === memberId || t.createdBy === memberId);
152
+ const currentTasks = myTasks.filter((t) => t.status !== "done").map((t) => ({ title: t.title, status: t.status, priority: t.priority }));
153
+ const recentContext = buildRecentContext(myTasks);
154
+ const profile = {
155
+ memberId,
156
+ memberName,
157
+ currentTasks,
158
+ skills: existing?.skills || [],
159
+ needs: existing?.needs || [],
160
+ offerings: existing?.offerings || [],
161
+ recentContext,
162
+ customNote: existing?.customNote,
163
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
164
+ };
165
+ await saveProfile(teamId, profile);
166
+ return profile;
167
+ }
168
+ async function updateProfileField(teamId, memberId, field, value) {
169
+ const profile = await loadProfile(teamId, memberId);
170
+ if (!profile) return null;
171
+ if (field === "customNote") {
172
+ profile.customNote = value;
173
+ } else {
174
+ profile[field] = value;
175
+ }
176
+ profile.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
177
+ await saveProfile(teamId, profile);
178
+ return profile;
179
+ }
180
+ function buildRecentContext(tasks) {
181
+ if (tasks.length === 0) return "\u6682\u65E0\u4EFB\u52A1";
182
+ const doing = tasks.filter((t) => t.status === "doing");
183
+ const todo = tasks.filter((t) => t.status === "todo");
184
+ const done = tasks.filter((t) => t.status === "done").slice(0, 3);
185
+ const parts = [];
186
+ if (doing.length > 0) {
187
+ parts.push(`\u6B63\u5728\u505A: ${doing.map((t) => t.title).join(", ")}`);
188
+ }
189
+ if (todo.length > 0) {
190
+ parts.push(`\u8BA1\u5212\u505A: ${todo.map((t) => t.title).join(", ")}`);
191
+ }
192
+ if (done.length > 0) {
193
+ parts.push(`\u5DF2\u5B8C\u6210: ${done.map((t) => t.title).join(", ")}`);
194
+ }
195
+ return parts.join("\uFF1B") || "\u6682\u65E0\u4EFB\u52A1";
196
+ }
197
+ async function gatherAllProfiles(teamId) {
198
+ const team = await loadTeam(teamId);
199
+ if (!team) return [];
200
+ const profiles = [];
201
+ for (const member of team.members) {
202
+ const profile = await gatherProfile(teamId, member.id, member.name);
203
+ profiles.push(profile);
204
+ }
205
+ return profiles;
206
+ }
207
+
208
+ // src/network/runner.ts
209
+ import chalk from "chalk";
210
+
211
+ // src/network/matchmaker.ts
212
+ import OpenAI from "openai";
213
+ var MATCHMAKER_SYSTEM = `\u4F60\u662F Hyper Network \u7684\u5339\u914D\u5F15\u64CE\u3002\u4F60\u7684\u4EFB\u52A1\u662F\u5206\u6790\u56E2\u961F\u6210\u5458\u7684 Profile\uFF0C\u627E\u51FA\u6700\u5177\u4E92\u8865\u4EF7\u503C\u7684\u914D\u5BF9\u3002
214
+
215
+ \u5339\u914D\u539F\u5219\uFF1A
216
+ 1. A \u7684 needs \u5339\u914D B \u7684 offerings\uFF08\u6216\u53CD\u4E4B\uFF09
217
+ 2. \u4EFB\u52A1\u6709\u534F\u540C\u7A7A\u95F4\uFF08\u6B63\u5728\u505A\u7C7B\u4F3C\u6216\u76F8\u5173\u7684\u4E8B\uFF09
218
+ 3. \u6280\u80FD\u4E92\u8865\uFF08A\u64C5\u957F\u7684\u6070\u597D\u662FB\u9700\u8981\u7684\uFF09
219
+ 4. \u7ECF\u9A8C\u4E92\u6362\uFF08\u53CC\u65B9\u90FD\u80FD\u4ECE\u4EA4\u6D41\u4E2D\u83B7\u76CA\uFF09
220
+
221
+ \u8BC4\u5206\u6807\u51C6\uFF080-100\uFF09\uFF1A
222
+ - 90+\uFF1A\u5F3A\u4E92\u8865\uFF0C\u53CC\u65B9\u90FD\u6709\u660E\u786E\u7684\u7ED9\u4E88\u548C\u83B7\u53D6
223
+ - 70-89\uFF1A\u4E2D\u5EA6\u4E92\u8865\uFF0C\u81F3\u5C11\u4E00\u65B9\u80FD\u660E\u663E\u53D7\u76CA
224
+ - 50-69\uFF1A\u8F7B\u5EA6\u5173\u8054\uFF0C\u53EF\u4EE5\u4EA4\u6D41\u4F46\u4EF7\u503C\u6709\u9650
225
+ - <50\uFF1A\u4E0D\u63A8\u8350\u914D\u5BF9
226
+
227
+ \u4E25\u683C\u8F93\u51FA JSON \u6570\u7EC4\uFF0C\u6BCF\u9879\u5305\u542B\uFF1AmemberA_id, memberB_id, reason, score, suggestedTopic
228
+ \u4E0D\u8981\u914D\u5BF9 score < 50 \u7684\u3002\u4E0D\u8981\u8F93\u51FA\u591A\u4F59\u6587\u5B57\uFF0C\u53EA\u8F93\u51FA JSON\u3002`;
229
+ function buildMatchPrompt(profiles, maxPairs) {
230
+ const profilesText = profiles.map((p, i) => {
231
+ const skills = p.skills.length > 0 ? p.skills.join(", ") : "\u672A\u8BBE\u7F6E";
232
+ const needs = p.needs.length > 0 ? p.needs.join(", ") : "\u672A\u8BBE\u7F6E";
233
+ const offerings = p.offerings.length > 0 ? p.offerings.join(", ") : "\u672A\u8BBE\u7F6E";
234
+ const tasks = p.currentTasks.length > 0 ? p.currentTasks.map((t) => `${t.title}(${t.status}/${t.priority})`).join(", ") : "\u65E0";
235
+ return `## \u6210\u5458${i + 1}: ${p.memberName} (ID: ${p.memberId})
236
+ - \u6280\u80FD: ${skills}
237
+ - \u9700\u6C42: ${needs}
238
+ - \u53EF\u63D0\u4F9B: ${offerings}
239
+ - \u5F53\u524D\u4EFB\u52A1: ${tasks}
240
+ - \u8FD1\u671F\u5DE5\u4F5C: ${p.recentContext}
241
+ ${p.customNote ? `- \u5907\u6CE8: ${p.customNote}` : ""}`;
242
+ }).join("\n\n");
243
+ return `\u4EE5\u4E0B\u662F\u56E2\u961F\u6210\u5458\u7684 Profile\uFF0C\u8BF7\u627E\u51FA\u6700\u591A ${maxPairs} \u5BF9\u4E92\u8865\u914D\u5BF9\u3002
244
+
245
+ ${profilesText}
246
+
247
+ \u8BF7\u8F93\u51FA JSON \u6570\u7EC4\uFF08\u65E0\u591A\u4F59\u6587\u5B57\uFF09:
248
+ [{"memberA_id":"...","memberB_id":"...","reason":"\u5339\u914D\u539F\u56E0","score":85,"suggestedTopic":"\u5EFA\u8BAE\u5BF9\u8BDD\u4E3B\u9898"}, ...]`;
249
+ }
250
+ function parseMatches(output, profiles) {
251
+ const jsonMatch = output.match(/\[[\s\S]*\]/);
252
+ if (!jsonMatch) return [];
253
+ try {
254
+ const raw = JSON.parse(jsonMatch[0]);
255
+ const profileMap = new Map(profiles.map((p) => [p.memberId, p]));
256
+ return raw.filter((m) => m.score >= 50 && profileMap.has(m.memberA_id) && profileMap.has(m.memberB_id)).map((m) => ({
257
+ id: generateId(),
258
+ memberA: { id: m.memberA_id, name: profileMap.get(m.memberA_id).memberName },
259
+ memberB: { id: m.memberB_id, name: profileMap.get(m.memberB_id).memberName },
260
+ reason: m.reason,
261
+ score: m.score,
262
+ suggestedTopic: m.suggestedTopic
263
+ }));
264
+ } catch {
265
+ return [];
266
+ }
267
+ }
268
+ function resolveModel(modelAlias, config) {
269
+ const alias = MODEL_ALIASES[modelAlias.toLowerCase()];
270
+ if (alias) {
271
+ const providerInfo = MODEL_PROVIDERS[alias.provider];
272
+ const apiKey = config.providerKeys[alias.provider] || config.modelConfig.apiKey;
273
+ return { model: alias.model, sdkType: providerInfo.sdkType, baseURL: providerInfo.baseURL, apiKey };
274
+ }
275
+ return {
276
+ model: config.modelConfig.model,
277
+ sdkType: config.modelConfig.sdkType,
278
+ baseURL: config.modelConfig.baseURL,
279
+ apiKey: config.modelConfig.apiKey
280
+ };
281
+ }
282
+ async function runMatchmaker(profiles, netConfig, config) {
283
+ if (profiles.length < 2) {
284
+ return { matches: [], tokenUsage: { inputTokens: 0, outputTokens: 0 } };
285
+ }
286
+ const userPrompt = buildMatchPrompt(profiles, netConfig.maxMatchPairs);
287
+ const resolved = resolveModel(netConfig.matchmakerModel, config);
288
+ if (resolved.sdkType === "openai") {
289
+ const client = new OpenAI({ apiKey: resolved.apiKey, baseURL: resolved.baseURL });
290
+ const result = await callOpenAILLM(client, {
291
+ systemPrompt: MATCHMAKER_SYSTEM,
292
+ userPrompt,
293
+ tools: [],
294
+ model: resolved.model,
295
+ maxTokens: 4096
296
+ });
297
+ const matches = parseMatches(result.output, profiles);
298
+ return { matches, tokenUsage: result.tokenUsage };
299
+ } else {
300
+ const client = createLLMClient({
301
+ provider: "anthropic",
302
+ model: resolved.model,
303
+ apiKey: resolved.apiKey,
304
+ sdkType: "anthropic"
305
+ });
306
+ const result = await callLLM(client, {
307
+ systemPrompt: MATCHMAKER_SYSTEM,
308
+ userPrompt,
309
+ tools: [],
310
+ model: resolved.model,
311
+ maxTokens: 4096
312
+ });
313
+ const matches = parseMatches(result.output, profiles);
314
+ return { matches, tokenUsage: result.tokenUsage };
315
+ }
316
+ }
317
+
318
+ // src/network/dialogue.ts
319
+ import OpenAI2 from "openai";
320
+ function avatarSystemPrompt(profile, partner, match) {
321
+ const tasks = profile.currentTasks.map((t) => `${t.title}(${t.status})`).join(", ") || "\u65E0";
322
+ const skills = profile.skills.join(", ") || "\u672A\u8BBE\u7F6E";
323
+ const needs = profile.needs.join(", ") || "\u672A\u8BBE\u7F6E";
324
+ const offerings = profile.offerings.join(", ") || "\u672A\u8BBE\u7F6E";
325
+ return `\u4F60\u662F ${profile.memberName} \u7684 AI Agent Avatar\uFF0C\u4EE3\u8868\u4ED6\u4E0E ${partner.memberName} \u7684 Avatar \u4EA4\u6D41\u3002
326
+
327
+ \u4F60\u4EE3\u8868\u7684\u7528\u6237\u4FE1\u606F\uFF1A
328
+ - \u5F53\u524D\u4EFB\u52A1: ${tasks}
329
+ - \u6280\u80FD: ${skills}
330
+ - \u9700\u8981\u5E2E\u52A9: ${needs}
331
+ - \u53EF\u63D0\u4F9B: ${offerings}
332
+ - \u8FD1\u671F\u5DE5\u4F5C: ${profile.recentContext}
333
+
334
+ \u5339\u914D\u539F\u56E0\uFF1A${match.reason}
335
+ \u5EFA\u8BAE\u4E3B\u9898\uFF1A${match.suggestedTopic}
336
+
337
+ \u89C4\u5219\uFF1A
338
+ 1. \u7AD9\u5728\u4F60\u4EE3\u8868\u7684\u7528\u6237\u7ACB\u573A\uFF0C\u4E3B\u52A8\u4EA4\u6362\u5177\u4F53\u4FE1\u606F
339
+ 2. \u6BCF\u8F6E 2-4 \u53E5\u8BDD\uFF0C\u7B80\u6D01\u6709\u6599
340
+ 3. \u91CD\u70B9\u4EA4\u6362\u5B9E\u9645\u6709\u4EF7\u503C\u7684\u7ECF\u9A8C\u3001\u8D44\u6E90\u3001\u5EFA\u8BAE
341
+ 4. \u4F7F\u7528\u4E2D\u6587`;
342
+ }
343
+ var SUMMARY_SYSTEM = `\u4F60\u662F\u5BF9\u8BDD\u603B\u7ED3\u5668\u3002\u5206\u6790\u4E24\u4E2A AI Avatar \u7684\u5BF9\u8BDD\uFF0C\u63D0\u53D6\u5BF9\u53CC\u65B9\u7684\u4EF7\u503C\u3002
344
+ \u4E25\u683C\u8F93\u51FA JSON\uFF08\u65E0\u591A\u4F59\u6587\u5B57\uFF09:
345
+ {
346
+ "valueForA": "\u5BF9\u6210\u5458A\u7684\u4EF7\u503C\uFF081-2\u53E5\uFF09",
347
+ "valueForB": "\u5BF9\u6210\u5458B\u7684\u4EF7\u503C\uFF081-2\u53E5\uFF09",
348
+ "actionItems": ["\u53EF\u884C\u52A8\u5EFA\u8BAE1", "\u53EF\u884C\u52A8\u5EFA\u8BAE2"],
349
+ "keyInsights": ["\u5173\u952E\u4FE1\u606F1", "\u5173\u952E\u4FE1\u606F2"]
350
+ }`;
351
+ async function runDialogue(match, profileA, profileB, netConfig, config) {
352
+ const resolved = resolveModel(netConfig.dialogueModel, config);
353
+ const turns = [];
354
+ let totalTokens = { inputTokens: 0, outputTokens: 0 };
355
+ const conversationHistory = [];
356
+ for (let round = 0; round < netConfig.maxDialogueTurns; round++) {
357
+ const turnA = await callAvatar(
358
+ profileA,
359
+ profileB,
360
+ match,
361
+ conversationHistory,
362
+ "A",
363
+ resolved,
364
+ config
365
+ );
366
+ turns.push({
367
+ speaker: profileA.memberId,
368
+ speakerName: profileA.memberName,
369
+ content: turnA.text
370
+ });
371
+ totalTokens = addTokens(totalTokens, turnA.tokenUsage);
372
+ conversationHistory.push({ role: "assistant", content: `${profileA.memberName}: ${turnA.text}` });
373
+ const turnB = await callAvatar(
374
+ profileB,
375
+ profileA,
376
+ match,
377
+ conversationHistory,
378
+ "B",
379
+ resolved,
380
+ config
381
+ );
382
+ turns.push({
383
+ speaker: profileB.memberId,
384
+ speakerName: profileB.memberName,
385
+ content: turnB.text
386
+ });
387
+ totalTokens = addTokens(totalTokens, turnB.tokenUsage);
388
+ conversationHistory.push({ role: "assistant", content: `${profileB.memberName}: ${turnB.text}` });
389
+ }
390
+ const summaryResult = await callSummary(
391
+ match,
392
+ profileA,
393
+ profileB,
394
+ turns,
395
+ resolved,
396
+ config
397
+ );
398
+ totalTokens = addTokens(totalTokens, summaryResult.tokenUsage);
399
+ return {
400
+ matchId: match.id,
401
+ memberA: match.memberA,
402
+ memberB: match.memberB,
403
+ turns,
404
+ summary: summaryResult.summary,
405
+ tokenUsage: totalTokens
406
+ };
407
+ }
408
+ async function callAvatar(self, partner, match, history, role, resolved, config) {
409
+ const systemPrompt = avatarSystemPrompt(self, partner, match);
410
+ let userPrompt;
411
+ if (history.length === 0) {
412
+ userPrompt = `\u8BF7\u5F00\u59CB\u5BF9\u8BDD\uFF0C\u4E3B\u52A8\u5C31\u300C${match.suggestedTopic}\u300D\u8BDD\u9898\u53D1\u8D77\u4EA4\u6D41\u3002`;
413
+ } else {
414
+ const lastMsg = history[history.length - 1].content;
415
+ userPrompt = `\u5BF9\u65B9\u8BF4\uFF1A${lastMsg}
416
+
417
+ \u8BF7\u56DE\u5E94\uFF0C\u7EE7\u7EED\u6DF1\u5165\u4EA4\u6D41\u3002`;
418
+ }
419
+ if (resolved.sdkType === "openai") {
420
+ const client = new OpenAI2({ apiKey: resolved.apiKey, baseURL: resolved.baseURL });
421
+ const result = await callOpenAILLM(client, {
422
+ systemPrompt,
423
+ userPrompt,
424
+ tools: [],
425
+ model: resolved.model,
426
+ maxTokens: 1024
427
+ });
428
+ return { text: result.output.trim(), tokenUsage: result.tokenUsage };
429
+ } else {
430
+ const client = createLLMClient({
431
+ provider: "anthropic",
432
+ model: resolved.model,
433
+ apiKey: resolved.apiKey,
434
+ sdkType: "anthropic"
435
+ });
436
+ const result = await callLLM(client, {
437
+ systemPrompt,
438
+ userPrompt,
439
+ tools: [],
440
+ model: resolved.model,
441
+ maxTokens: 1024
442
+ });
443
+ return { text: result.output.trim(), tokenUsage: result.tokenUsage };
444
+ }
445
+ }
446
+ async function callSummary(match, profileA, profileB, turns, resolved, config) {
447
+ const dialogueText = turns.map((t) => `${t.speakerName}: ${t.content}`).join("\n");
448
+ const userPrompt = `\u4EE5\u4E0B\u662F ${profileA.memberName}(\u6210\u5458A) \u548C ${profileB.memberName}(\u6210\u5458B) \u7684 Avatar \u5BF9\u8BDD\uFF1A
449
+
450
+ ${dialogueText}
451
+
452
+ \u8BF7\u603B\u7ED3\u5BF9\u8BDD\u4EF7\u503C\uFF0C\u8F93\u51FA JSON\u3002`;
453
+ const defaultSummary = {
454
+ valueForA: "\u5BF9\u8BDD\u4EA4\u6D41",
455
+ valueForB: "\u5BF9\u8BDD\u4EA4\u6D41",
456
+ actionItems: [],
457
+ keyInsights: []
458
+ };
459
+ if (resolved.sdkType === "openai") {
460
+ const client = new OpenAI2({ apiKey: resolved.apiKey, baseURL: resolved.baseURL });
461
+ const result = await callOpenAILLM(client, {
462
+ systemPrompt: SUMMARY_SYSTEM,
463
+ userPrompt,
464
+ tools: [],
465
+ model: resolved.model,
466
+ maxTokens: 2048
467
+ });
468
+ return { summary: parseSummary(result.output) || defaultSummary, tokenUsage: result.tokenUsage };
469
+ } else {
470
+ const client = createLLMClient({
471
+ provider: "anthropic",
472
+ model: resolved.model,
473
+ apiKey: resolved.apiKey,
474
+ sdkType: "anthropic"
475
+ });
476
+ const result = await callLLM(client, {
477
+ systemPrompt: SUMMARY_SYSTEM,
478
+ userPrompt,
479
+ tools: [],
480
+ model: resolved.model,
481
+ maxTokens: 2048
482
+ });
483
+ return { summary: parseSummary(result.output) || defaultSummary, tokenUsage: result.tokenUsage };
484
+ }
485
+ }
486
+ function parseSummary(output) {
487
+ const jsonMatch = output.match(/\{[\s\S]*\}/);
488
+ if (!jsonMatch) return null;
489
+ try {
490
+ const parsed = JSON.parse(jsonMatch[0]);
491
+ return {
492
+ valueForA: parsed.valueForA || "",
493
+ valueForB: parsed.valueForB || "",
494
+ actionItems: Array.isArray(parsed.actionItems) ? parsed.actionItems : [],
495
+ keyInsights: Array.isArray(parsed.keyInsights) ? parsed.keyInsights : []
496
+ };
497
+ } catch {
498
+ return null;
499
+ }
500
+ }
501
+ function addTokens(a, b) {
502
+ return {
503
+ inputTokens: a.inputTokens + b.inputTokens,
504
+ outputTokens: a.outputTokens + b.outputTokens
505
+ };
506
+ }
507
+
508
+ // src/network/digest.ts
509
+ function compileDigests(matches, dialogues) {
510
+ const memberMap = /* @__PURE__ */ new Map();
511
+ for (const dialogue of dialogues) {
512
+ const match = matches.find((m) => m.id === dialogue.matchId);
513
+ if (!match) continue;
514
+ const { memberA, memberB } = dialogue;
515
+ if (!memberMap.has(memberA.id)) {
516
+ memberMap.set(memberA.id, { name: memberA.name, entries: [] });
517
+ }
518
+ memberMap.get(memberA.id).entries.push({
519
+ partnerName: memberB.name,
520
+ reason: match.reason,
521
+ valueForMe: dialogue.summary.valueForA,
522
+ actionItems: dialogue.summary.actionItems,
523
+ keyInsights: dialogue.summary.keyInsights
524
+ });
525
+ if (!memberMap.has(memberB.id)) {
526
+ memberMap.set(memberB.id, { name: memberB.name, entries: [] });
527
+ }
528
+ memberMap.get(memberB.id).entries.push({
529
+ partnerName: memberA.name,
530
+ reason: match.reason,
531
+ valueForMe: dialogue.summary.valueForB,
532
+ actionItems: dialogue.summary.actionItems,
533
+ keyInsights: dialogue.summary.keyInsights
534
+ });
535
+ }
536
+ const now = (/* @__PURE__ */ new Date()).toISOString();
537
+ const digests = [];
538
+ for (const [memberId, data] of memberMap) {
539
+ digests.push({
540
+ memberId,
541
+ memberName: data.name,
542
+ matches: data.entries,
543
+ generatedAt: now
544
+ });
545
+ }
546
+ return digests;
547
+ }
548
+
549
+ // src/network/runner.ts
550
+ var autoTimer = null;
551
+ async function executeRound(teamId, triggeredBy, config, onProgress) {
552
+ const netConfig = await loadNetworkConfig(teamId);
553
+ const roundId = generateId();
554
+ const now = (/* @__PURE__ */ new Date()).toISOString();
555
+ const round = {
556
+ id: roundId,
557
+ teamId,
558
+ status: "running",
559
+ startedAt: now,
560
+ triggeredBy,
561
+ profiles: [],
562
+ matches: [],
563
+ dialogues: [],
564
+ digests: [],
565
+ totalTokenUsage: { inputTokens: 0, outputTokens: 0 }
566
+ };
567
+ await saveRound(teamId, round);
568
+ broadcastToTeam(teamId, {
569
+ type: "network_round_start",
570
+ payload: { roundId },
571
+ timestamp: now
572
+ });
573
+ try {
574
+ onProgress?.("gather", "\u91C7\u96C6\u6210\u5458 Profile...");
575
+ const profiles = await gatherAllProfiles(teamId);
576
+ round.profiles = profiles;
577
+ if (profiles.length < 2) {
578
+ round.status = "completed";
579
+ round.completedAt = (/* @__PURE__ */ new Date()).toISOString();
580
+ round.error = "\u56E2\u961F\u6210\u5458\u4E0D\u8DB3 2 \u4EBA\uFF0C\u65E0\u6CD5\u5339\u914D";
581
+ await saveRound(teamId, round);
582
+ return round;
583
+ }
584
+ onProgress?.("match", `\u5339\u914D ${profiles.length} \u4F4D\u6210\u5458...`);
585
+ const matchResult = await runMatchmaker(profiles, netConfig, config);
586
+ round.matches = matchResult.matches;
587
+ round.totalTokenUsage = addTokens2(round.totalTokenUsage, matchResult.tokenUsage);
588
+ if (matchResult.matches.length === 0) {
589
+ round.status = "completed";
590
+ round.completedAt = (/* @__PURE__ */ new Date()).toISOString();
591
+ round.error = "\u672A\u627E\u5230\u4E92\u8865\u914D\u5BF9";
592
+ await saveRound(teamId, round);
593
+ return round;
594
+ }
595
+ broadcastToTeam(teamId, {
596
+ type: "network_match_found",
597
+ payload: { roundId, matchCount: matchResult.matches.length },
598
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
599
+ });
600
+ const profileMap = new Map(profiles.map((p) => [p.memberId, p]));
601
+ for (let i = 0; i < matchResult.matches.length; i++) {
602
+ const match = matchResult.matches[i];
603
+ const profileA = profileMap.get(match.memberA.id);
604
+ const profileB = profileMap.get(match.memberB.id);
605
+ if (!profileA || !profileB) continue;
606
+ onProgress?.("dialogue", `\u5BF9\u8BDD ${i + 1}/${matchResult.matches.length}: ${match.memberA.name} \u2194 ${match.memberB.name}`);
607
+ const dialogueResult = await runDialogue(match, profileA, profileB, netConfig, config);
608
+ round.dialogues.push(dialogueResult);
609
+ round.totalTokenUsage = addTokens2(round.totalTokenUsage, dialogueResult.tokenUsage);
610
+ broadcastToTeam(teamId, {
611
+ type: "network_dialogue_complete",
612
+ payload: {
613
+ roundId,
614
+ matchId: match.id,
615
+ memberA: match.memberA.name,
616
+ memberB: match.memberB.name
617
+ },
618
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
619
+ });
620
+ }
621
+ onProgress?.("digest", "\u7F16\u8BD1\u4E2A\u4EBA\u6458\u8981...");
622
+ const digests = compileDigests(round.matches, round.dialogues);
623
+ round.digests = digests;
624
+ for (const digest of digests) {
625
+ sendToMember(digest.memberId, {
626
+ type: "network_digest_ready",
627
+ payload: { roundId, digest },
628
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
629
+ });
630
+ }
631
+ round.status = "completed";
632
+ round.completedAt = (/* @__PURE__ */ new Date()).toISOString();
633
+ await saveRound(teamId, round);
634
+ onProgress?.("done", `\u8F6E\u6B21\u5B8C\u6210: ${round.matches.length} \u5BF9\u5339\u914D, ${round.dialogues.length} \u573A\u5BF9\u8BDD`);
635
+ return round;
636
+ } catch (err) {
637
+ round.status = "failed";
638
+ round.error = err instanceof Error ? err.message : String(err);
639
+ round.completedAt = (/* @__PURE__ */ new Date()).toISOString();
640
+ await saveRound(teamId, round);
641
+ throw err;
642
+ }
643
+ }
644
+ async function startAutoRound(teamId, config) {
645
+ stopAutoRound();
646
+ const netConfig = await loadNetworkConfig(teamId);
647
+ if (!netConfig.autoEnabled) return;
648
+ autoTimer = setInterval(async () => {
649
+ try {
650
+ await executeRound(teamId, "auto", config);
651
+ } catch (err) {
652
+ console.error(chalk.red(`[Network] \u81EA\u52A8\u8F6E\u6B21\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`));
653
+ }
654
+ }, netConfig.autoIntervalMs);
655
+ }
656
+ function stopAutoRound() {
657
+ if (autoTimer) {
658
+ clearInterval(autoTimer);
659
+ autoTimer = null;
660
+ }
661
+ }
662
+ function addTokens2(a, b) {
663
+ return {
664
+ inputTokens: a.inputTokens + b.inputTokens,
665
+ outputTokens: a.outputTokens + b.outputTokens
666
+ };
667
+ }
668
+
669
+ export {
670
+ loadAllProfiles,
671
+ loadRound,
672
+ listRounds,
673
+ getLatestRound,
674
+ loadNetworkConfig,
675
+ saveNetworkConfig,
676
+ gatherProfile,
677
+ updateProfileField,
678
+ executeRound,
679
+ startAutoRound,
680
+ stopAutoRound
681
+ };