hypercore-cli 1.1.2 → 1.3.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 (158) hide show
  1. package/LICENSE +92 -21
  2. package/README.md +8 -1
  3. package/dist/App-YMX7FSXR.js +1 -0
  4. package/dist/api-Q2TX5JJL.js +1 -0
  5. package/dist/auth-X6CUT3DW.js +1 -0
  6. package/dist/background-ACODXSUG.js +1 -0
  7. package/dist/backlog-JD2IM336.js +1 -0
  8. package/dist/chunk-2QI2IU2V.js +1 -0
  9. package/dist/chunk-3KFRDIPQ.js +1 -0
  10. package/dist/chunk-42C5J7PN.js +1 -0
  11. package/dist/chunk-4D7XVJ7Q.js +1 -0
  12. package/dist/chunk-545IGTXV.js +1 -0
  13. package/dist/chunk-5KUSGQP2.js +1 -0
  14. package/dist/chunk-AUQ64BK2.js +1 -0
  15. package/dist/chunk-AV244H5C.js +1 -0
  16. package/dist/chunk-BQVBEFS4.js +1 -0
  17. package/dist/chunk-BYWQLFP2.js +1 -0
  18. package/dist/chunk-COITWWZJ.js +1 -0
  19. package/dist/chunk-CR7UUJVX.js +1 -0
  20. package/dist/chunk-E3MULLBX.js +1 -0
  21. package/dist/chunk-EWBV7YPP.js +1 -0
  22. package/dist/chunk-EZHYVJGQ.js +1 -0
  23. package/dist/chunk-FAKXBY7Q.js +1 -0
  24. package/dist/chunk-FHGATV5B.js +1 -0
  25. package/dist/chunk-I2G27Y5P.js +1 -0
  26. package/dist/chunk-IKF43TX2.js +1 -0
  27. package/dist/chunk-INSPHCBN.js +1 -0
  28. package/dist/chunk-LQMDUKIE.js +1 -0
  29. package/dist/chunk-M3MTKGA5.js +1 -0
  30. package/dist/chunk-MPO54FU3.js +1 -0
  31. package/dist/chunk-PVKCZI6A.js +1 -0
  32. package/dist/chunk-Q7KEPCYL.js +1 -0
  33. package/dist/chunk-R5XD3NT2.js +1 -0
  34. package/dist/chunk-ROBZ6PAL.js +1 -0
  35. package/dist/chunk-RXB5BS2N.js +1 -0
  36. package/dist/chunk-RZ3HNYMT.js +1 -0
  37. package/dist/chunk-UCGLRMTG.js +1 -0
  38. package/dist/chunk-UEHJVRKB.js +1 -0
  39. package/dist/chunk-UZYX5GGF.js +1 -0
  40. package/dist/chunk-XQJBB725.js +1 -0
  41. package/dist/chunk-ZB5ZQSXH.js +1 -0
  42. package/dist/claude-US2QPRBA.js +1 -0
  43. package/dist/commands-5TFN74MD.js +1 -0
  44. package/dist/commands-EKPWCB3T.js +1 -0
  45. package/dist/commands-QHJLREPM.js +1 -0
  46. package/dist/config-2OUL5FLS.js +1 -0
  47. package/dist/config-loader-N7IBWN2P.js +1 -0
  48. package/dist/diagnose-NLHN4SAJ.js +1 -0
  49. package/dist/display-TB5YACJV.js +1 -0
  50. package/dist/extractor-3KTM2IUL.js +1 -0
  51. package/dist/feature-flag-VVIF5FJG.js +1 -0
  52. package/dist/history-GVNDPXXQ.js +1 -0
  53. package/dist/index.js +1 -402
  54. package/dist/instance-registry-I5AIVJE2.js +1 -0
  55. package/dist/keybindings-RN3A7CRW.js +1 -0
  56. package/dist/loader-3IKPXP4R.js +1 -0
  57. package/dist/network-GI2F3IDE.js +1 -0
  58. package/dist/notify-O6FNVHC4.js +1 -0
  59. package/dist/openai-compat-IPCMINVF.js +1 -0
  60. package/dist/permissions-5O7KVAXU.js +1 -0
  61. package/dist/prompt-VWFPFM4N.js +1 -0
  62. package/dist/quality-GPQD25UL.js +1 -0
  63. package/dist/repl-YNXCDVU4.js +1 -0
  64. package/dist/roadmap-QRZODSNJ.js +1 -0
  65. package/dist/server-USQP4GC4.js +1 -0
  66. package/dist/session-5HDDQQP6.js +1 -0
  67. package/dist/skills-DXWSVJSU.js +1 -0
  68. package/dist/store-WXXTKTTL.js +1 -0
  69. package/dist/team-VTPJ3WRT.js +1 -0
  70. package/dist/telemetry-NT4UZLBS.js +1 -0
  71. package/dist/test-runner-F6B6RH3S.js +1 -0
  72. package/dist/theme-JJJ6ABR2.js +1 -0
  73. package/dist/upgrade-RUG3R7R5.js +1 -0
  74. package/dist/verify-6OGRY2PR.js +1 -0
  75. package/dist/version-DLROA5JN.js +1 -0
  76. package/dist/web/static/app.js +1 -562
  77. package/dist/web/static/index.html +114 -126
  78. package/dist/web/static/mirror.css +1 -1001
  79. package/dist/web/static/mirror.html +155 -178
  80. package/dist/web/static/mirror.js +1 -1125
  81. package/dist/web/static/onboard.css +1 -302
  82. package/dist/web/static/onboard.html +121 -145
  83. package/dist/web/static/onboard.js +1 -300
  84. package/dist/web/static/style.css +1 -602
  85. package/dist/web/static/utils.js +1 -0
  86. package/dist/web/static/workspace.css +1 -1568
  87. package/dist/web/static/workspace.html +369 -402
  88. package/dist/web/static/workspace.js +1 -1683
  89. package/dist/web-P5YUKEAU.js +1 -0
  90. package/package.json +25 -4
  91. package/dist/api-JHHOZTL6.js +0 -162
  92. package/dist/auth-5QFJLW7J.js +0 -21
  93. package/dist/background-2EGCAAQH.js +0 -14
  94. package/dist/backlog-Q2NZCLNY.js +0 -24
  95. package/dist/chunk-2CMSCWQW.js +0 -162
  96. package/dist/chunk-4DVYJAJL.js +0 -57
  97. package/dist/chunk-5GDYH676.js +0 -271
  98. package/dist/chunk-5NLVGLD7.js +0 -66
  99. package/dist/chunk-6XTEAFZQ.js +0 -575
  100. package/dist/chunk-AQBSMYLT.js +0 -2025
  101. package/dist/chunk-BE46C7JW.js +0 -46
  102. package/dist/chunk-CLKIMCXZ.js +0 -139
  103. package/dist/chunk-DN4ASQ26.js +0 -167
  104. package/dist/chunk-DUWREZXK.js +0 -173
  105. package/dist/chunk-FCW3K6F2.js +0 -263
  106. package/dist/chunk-GFORWAMW.js +0 -251
  107. package/dist/chunk-GH7E2OJE.js +0 -223
  108. package/dist/chunk-GU2FZQ6A.js +0 -69
  109. package/dist/chunk-I7WI3BMB.js +0 -161
  110. package/dist/chunk-IOPKN5GD.js +0 -190
  111. package/dist/chunk-LBVHDGZE.js +0 -133
  112. package/dist/chunk-MGLJ53QN.js +0 -219
  113. package/dist/chunk-NETIY5UB.js +0 -134
  114. package/dist/chunk-NP47L7LG.js +0 -288
  115. package/dist/chunk-O6MG7TOH.js +0 -58
  116. package/dist/chunk-OPZYEVYR.js +0 -150
  117. package/dist/chunk-R3GPQC7I.js +0 -393
  118. package/dist/chunk-R5T3A2NQ.js +0 -166
  119. package/dist/chunk-RKB2JOV2.js +0 -43
  120. package/dist/chunk-RNG3K465.js +0 -80
  121. package/dist/chunk-TGTYKBGC.js +0 -86
  122. package/dist/chunk-UCX4VZCT.js +0 -681
  123. package/dist/chunk-WHLVZCQY.js +0 -245
  124. package/dist/chunk-Y6HMJZDJ.js +0 -1505
  125. package/dist/chunk-ZSBHUGWR.js +0 -262
  126. package/dist/claude-4BX3MJSK.js +0 -12
  127. package/dist/commands-2X4OB5RF.js +0 -128
  128. package/dist/commands-GLBCEVQK.js +0 -1044
  129. package/dist/commands-IINRNBYX.js +0 -232
  130. package/dist/config-RSNQJQPS.js +0 -8
  131. package/dist/config-loader-SXO674TF.js +0 -24
  132. package/dist/diagnose-7UPLS7I4.js +0 -12
  133. package/dist/display-IIUBEYWN.js +0 -58
  134. package/dist/extractor-D3XWOAXI.js +0 -129
  135. package/dist/history-6I6FADAU.js +0 -180
  136. package/dist/index.d.ts +0 -1
  137. package/dist/instance-registry-J7UJ7U4Z.js +0 -15
  138. package/dist/keybindings-PDXIOV3O.js +0 -15
  139. package/dist/loader-GKEYT6Y7.js +0 -58
  140. package/dist/network-JYGHQXAR.js +0 -279
  141. package/dist/notify-HPTALZDC.js +0 -14
  142. package/dist/openai-compat-R7EKWG6Z.js +0 -12
  143. package/dist/permissions-JUKXMNDH.js +0 -10
  144. package/dist/prompt-UWHSZU4P.js +0 -166
  145. package/dist/quality-ST7PPNFR.js +0 -16
  146. package/dist/repl-QHIZ2JGF.js +0 -3374
  147. package/dist/roadmap-5OBEKROY.js +0 -17
  148. package/dist/server-HCNIP7ZQ.js +0 -57
  149. package/dist/session-5EBECDUP.js +0 -21
  150. package/dist/skills-HBQQTYO4.js +0 -175
  151. package/dist/store-FKUTR7GW.js +0 -25
  152. package/dist/team-7BBBP5YQ.js +0 -385
  153. package/dist/telemetry-6R4EIE6O.js +0 -30
  154. package/dist/test-runner-AUAGIBNM.js +0 -619
  155. package/dist/theme-3SYJ3UQA.js +0 -14
  156. package/dist/upgrade-MZFH7OCN.js +0 -83
  157. package/dist/verify-JUDKTPKZ.js +0 -14
  158. package/dist/web-KS3FUGJA.js +0 -39
@@ -1,681 +0,0 @@
1
- import {
2
- broadcastToTeam,
3
- sendToMember
4
- } from "./chunk-DN4ASQ26.js";
5
- import {
6
- listTasks,
7
- loadTeam
8
- } from "./chunk-DUWREZXK.js";
9
- import {
10
- generateId
11
- } from "./chunk-5NLVGLD7.js";
12
- import {
13
- callLLM,
14
- createLLMClient
15
- } from "./chunk-FCW3K6F2.js";
16
- import {
17
- callOpenAILLM
18
- } from "./chunk-5GDYH676.js";
19
- import {
20
- MODEL_ALIASES,
21
- MODEL_PROVIDERS
22
- } from "./chunk-I7WI3BMB.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
- };