hypercore-cli 1.1.2 → 1.4.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 (162) 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-ELP6F4NC.js +1 -0
  5. package/dist/auth-SICBMA3P.js +1 -0
  6. package/dist/auth-X6CUT3DW.js +1 -0
  7. package/dist/background-ACODXSUG.js +1 -0
  8. package/dist/backlog-JD2IM336.js +1 -0
  9. package/dist/chunk-2QI2IU2V.js +1 -0
  10. package/dist/chunk-3KFRDIPQ.js +1 -0
  11. package/dist/chunk-42C5J7PN.js +1 -0
  12. package/dist/chunk-4D7XVJ7Q.js +1 -0
  13. package/dist/chunk-5KUSGQP2.js +1 -0
  14. package/dist/chunk-5OEFAGD5.js +1 -0
  15. package/dist/chunk-AUQ64BK2.js +1 -0
  16. package/dist/chunk-AV244H5C.js +1 -0
  17. package/dist/chunk-BQVBEFS4.js +1 -0
  18. package/dist/chunk-BYWQLFP2.js +1 -0
  19. package/dist/chunk-C6YL7UHE.js +1 -0
  20. package/dist/chunk-COITWWZJ.js +1 -0
  21. package/dist/chunk-CR7UUJVX.js +1 -0
  22. package/dist/chunk-E3MULLBX.js +1 -0
  23. package/dist/chunk-EZHYVJGQ.js +1 -0
  24. package/dist/chunk-FAMURNNH.js +1 -0
  25. package/dist/chunk-FGP56E4W.js +1 -0
  26. package/dist/chunk-FHGATV5B.js +1 -0
  27. package/dist/chunk-I2G27Y5P.js +1 -0
  28. package/dist/chunk-IKF43TX2.js +1 -0
  29. package/dist/chunk-INSPHCBN.js +1 -0
  30. package/dist/chunk-JHMV366T.js +1 -0
  31. package/dist/chunk-L52HX5SX.js +1 -0
  32. package/dist/chunk-LQMDUKIE.js +1 -0
  33. package/dist/chunk-M3MTKGA5.js +1 -0
  34. package/dist/chunk-MPO54FU3.js +1 -0
  35. package/dist/chunk-PVKCZI6A.js +1 -0
  36. package/dist/chunk-Q7KEPCYL.js +1 -0
  37. package/dist/chunk-ROBZ6PAL.js +1 -0
  38. package/dist/chunk-RXB5BS2N.js +1 -0
  39. package/dist/chunk-RZ3HNYMT.js +1 -0
  40. package/dist/chunk-UCGLRMTG.js +1 -0
  41. package/dist/chunk-UEHJVRKB.js +1 -0
  42. package/dist/chunk-UZYX5GGF.js +1 -0
  43. package/dist/chunk-XQJBB725.js +1 -0
  44. package/dist/chunk-YXCRL6K3.js +1 -0
  45. package/dist/claude-US2QPRBA.js +1 -0
  46. package/dist/commands-EKPWCB3T.js +1 -0
  47. package/dist/commands-GYNKP5WV.js +1 -0
  48. package/dist/commands-QHJLREPM.js +1 -0
  49. package/dist/config-2OUL5FLS.js +1 -0
  50. package/dist/config-loader-N7IBWN2P.js +1 -0
  51. package/dist/diagnose-NLHN4SAJ.js +1 -0
  52. package/dist/display-RYAW2GFB.js +1 -0
  53. package/dist/extractor-3KTM2IUL.js +1 -0
  54. package/dist/feature-flag-VVIF5FJG.js +1 -0
  55. package/dist/history-3R2UHRDQ.js +1 -0
  56. package/dist/index.js +1 -402
  57. package/dist/instance-registry-I5AIVJE2.js +1 -0
  58. package/dist/keybindings-RN3A7CRW.js +1 -0
  59. package/dist/loader-3IKPXP4R.js +1 -0
  60. package/dist/network-K5HRJE44.js +1 -0
  61. package/dist/notify-O6FNVHC4.js +1 -0
  62. package/dist/openai-compat-IPCMINVF.js +1 -0
  63. package/dist/panels-2R5YEFXH.js +1 -0
  64. package/dist/permissions-5O7KVAXU.js +1 -0
  65. package/dist/prompt-VWFPFM4N.js +1 -0
  66. package/dist/quality-GPQD25UL.js +1 -0
  67. package/dist/repl-CL4SYHU4.js +1 -0
  68. package/dist/roadmap-QRZODSNJ.js +1 -0
  69. package/dist/server-PKOHK5M2.js +1 -0
  70. package/dist/session-5HDDQQP6.js +1 -0
  71. package/dist/skills-DXWSVJSU.js +1 -0
  72. package/dist/store-WXXTKTTL.js +1 -0
  73. package/dist/team-N2GF4YYS.js +1 -0
  74. package/dist/telemetry-NT4UZLBS.js +1 -0
  75. package/dist/test-runner-F6B6RH3S.js +1 -0
  76. package/dist/theme-JJJ6ABR2.js +1 -0
  77. package/dist/upgrade-RUG3R7R5.js +1 -0
  78. package/dist/verify-6OGRY2PR.js +1 -0
  79. package/dist/version-4RHTDUNQ.js +1 -0
  80. package/dist/web/static/app.js +1 -562
  81. package/dist/web/static/index.html +114 -126
  82. package/dist/web/static/mirror.css +1 -1001
  83. package/dist/web/static/mirror.html +155 -178
  84. package/dist/web/static/mirror.js +1 -1125
  85. package/dist/web/static/onboard.css +1 -302
  86. package/dist/web/static/onboard.html +121 -145
  87. package/dist/web/static/onboard.js +1 -300
  88. package/dist/web/static/style.css +1 -602
  89. package/dist/web/static/utils.js +1 -0
  90. package/dist/web/static/workspace.css +1 -1568
  91. package/dist/web/static/workspace.html +369 -402
  92. package/dist/web/static/workspace.js +1 -1683
  93. package/dist/web-CIC7ZKBM.js +1 -0
  94. package/package.json +26 -4
  95. package/dist/api-JHHOZTL6.js +0 -162
  96. package/dist/auth-5QFJLW7J.js +0 -21
  97. package/dist/background-2EGCAAQH.js +0 -14
  98. package/dist/backlog-Q2NZCLNY.js +0 -24
  99. package/dist/chunk-2CMSCWQW.js +0 -162
  100. package/dist/chunk-4DVYJAJL.js +0 -57
  101. package/dist/chunk-5GDYH676.js +0 -271
  102. package/dist/chunk-5NLVGLD7.js +0 -66
  103. package/dist/chunk-6XTEAFZQ.js +0 -575
  104. package/dist/chunk-AQBSMYLT.js +0 -2025
  105. package/dist/chunk-BE46C7JW.js +0 -46
  106. package/dist/chunk-CLKIMCXZ.js +0 -139
  107. package/dist/chunk-DN4ASQ26.js +0 -167
  108. package/dist/chunk-DUWREZXK.js +0 -173
  109. package/dist/chunk-FCW3K6F2.js +0 -263
  110. package/dist/chunk-GFORWAMW.js +0 -251
  111. package/dist/chunk-GH7E2OJE.js +0 -223
  112. package/dist/chunk-GU2FZQ6A.js +0 -69
  113. package/dist/chunk-I7WI3BMB.js +0 -161
  114. package/dist/chunk-IOPKN5GD.js +0 -190
  115. package/dist/chunk-LBVHDGZE.js +0 -133
  116. package/dist/chunk-MGLJ53QN.js +0 -219
  117. package/dist/chunk-NETIY5UB.js +0 -134
  118. package/dist/chunk-NP47L7LG.js +0 -288
  119. package/dist/chunk-O6MG7TOH.js +0 -58
  120. package/dist/chunk-OPZYEVYR.js +0 -150
  121. package/dist/chunk-R3GPQC7I.js +0 -393
  122. package/dist/chunk-R5T3A2NQ.js +0 -166
  123. package/dist/chunk-RKB2JOV2.js +0 -43
  124. package/dist/chunk-RNG3K465.js +0 -80
  125. package/dist/chunk-TGTYKBGC.js +0 -86
  126. package/dist/chunk-UCX4VZCT.js +0 -681
  127. package/dist/chunk-WHLVZCQY.js +0 -245
  128. package/dist/chunk-Y6HMJZDJ.js +0 -1505
  129. package/dist/chunk-ZSBHUGWR.js +0 -262
  130. package/dist/claude-4BX3MJSK.js +0 -12
  131. package/dist/commands-2X4OB5RF.js +0 -128
  132. package/dist/commands-GLBCEVQK.js +0 -1044
  133. package/dist/commands-IINRNBYX.js +0 -232
  134. package/dist/config-RSNQJQPS.js +0 -8
  135. package/dist/config-loader-SXO674TF.js +0 -24
  136. package/dist/diagnose-7UPLS7I4.js +0 -12
  137. package/dist/display-IIUBEYWN.js +0 -58
  138. package/dist/extractor-D3XWOAXI.js +0 -129
  139. package/dist/history-6I6FADAU.js +0 -180
  140. package/dist/index.d.ts +0 -1
  141. package/dist/instance-registry-J7UJ7U4Z.js +0 -15
  142. package/dist/keybindings-PDXIOV3O.js +0 -15
  143. package/dist/loader-GKEYT6Y7.js +0 -58
  144. package/dist/network-JYGHQXAR.js +0 -279
  145. package/dist/notify-HPTALZDC.js +0 -14
  146. package/dist/openai-compat-R7EKWG6Z.js +0 -12
  147. package/dist/permissions-JUKXMNDH.js +0 -10
  148. package/dist/prompt-UWHSZU4P.js +0 -166
  149. package/dist/quality-ST7PPNFR.js +0 -16
  150. package/dist/repl-QHIZ2JGF.js +0 -3374
  151. package/dist/roadmap-5OBEKROY.js +0 -17
  152. package/dist/server-HCNIP7ZQ.js +0 -57
  153. package/dist/session-5EBECDUP.js +0 -21
  154. package/dist/skills-HBQQTYO4.js +0 -175
  155. package/dist/store-FKUTR7GW.js +0 -25
  156. package/dist/team-7BBBP5YQ.js +0 -385
  157. package/dist/telemetry-6R4EIE6O.js +0 -30
  158. package/dist/test-runner-AUAGIBNM.js +0 -619
  159. package/dist/theme-3SYJ3UQA.js +0 -14
  160. package/dist/upgrade-MZFH7OCN.js +0 -83
  161. package/dist/verify-JUDKTPKZ.js +0 -14
  162. package/dist/web-KS3FUGJA.js +0 -39
@@ -1,575 +0,0 @@
1
- import {
2
- createToolRegistry
3
- } from "./chunk-Y6HMJZDJ.js";
4
- import {
5
- callLLM
6
- } from "./chunk-FCW3K6F2.js";
7
- import {
8
- callOpenAILLM
9
- } from "./chunk-5GDYH676.js";
10
- import {
11
- MODEL_ALIASES,
12
- MODEL_PROVIDERS
13
- } from "./chunk-I7WI3BMB.js";
14
- import {
15
- loadAgent,
16
- loadLine,
17
- loadPWP,
18
- loadSkill
19
- } from "./chunk-WHLVZCQY.js";
20
-
21
- // src/core/workspace-init.ts
22
- import { mkdir, copyFile, writeFile, readdir } from "fs/promises";
23
- import { join, dirname } from "path";
24
- import { fileURLToPath } from "url";
25
- import { existsSync } from "fs";
26
- var HYPERCORE_DIR = join(process.env.HOME || "~", ".hypercore");
27
- function getTemplatesDir() {
28
- const thisFile = fileURLToPath(import.meta.url);
29
- const projectRoot = join(dirname(thisFile), "..", "..");
30
- return join(projectRoot, "templates");
31
- }
32
- async function copyTemplateDir(srcDir, destDir) {
33
- await mkdir(destDir, { recursive: true });
34
- try {
35
- const entries = await readdir(srcDir, { withFileTypes: true });
36
- for (const entry of entries) {
37
- const srcPath = join(srcDir, entry.name);
38
- const destPath = join(destDir, entry.name);
39
- if (entry.isDirectory()) {
40
- await copyTemplateDir(srcPath, destPath);
41
- } else {
42
- if (!existsSync(destPath)) {
43
- await copyFile(srcPath, destPath);
44
- }
45
- }
46
- }
47
- } catch {
48
- }
49
- }
50
- function normalizeTemplateFileName(name, kind) {
51
- const trimmed = name.trim();
52
- if (!trimmed) return "";
53
- if (trimmed.endsWith(`.${kind}.md`)) return trimmed;
54
- if (trimmed.endsWith(".md")) return trimmed;
55
- return `${trimmed}.${kind}.md`;
56
- }
57
- async function copyTemplateSubset(srcDir, destDir, selected, kind) {
58
- if (!selected || selected.length === 0) {
59
- await copyTemplateDir(srcDir, destDir);
60
- return;
61
- }
62
- await mkdir(destDir, { recursive: true });
63
- const wanted = new Set(
64
- selected.map((name) => normalizeTemplateFileName(name, kind)).filter(Boolean)
65
- );
66
- try {
67
- const entries = await readdir(srcDir, { withFileTypes: true });
68
- for (const entry of entries) {
69
- if (!entry.isFile()) continue;
70
- if (!wanted.has(entry.name)) continue;
71
- const srcPath = join(srcDir, entry.name);
72
- const destPath = join(destDir, entry.name);
73
- if (!existsSync(destPath)) {
74
- await copyFile(srcPath, destPath);
75
- }
76
- }
77
- } catch {
78
- }
79
- }
80
- function escapeTomlValue(value) {
81
- return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r");
82
- }
83
- function generateConfigToml(provider, apiKey, tavilyKey, customBaseUrl, customModelName) {
84
- const modelConfigs = {
85
- anthropic: { name: "claude-sonnet-4-20250514" },
86
- minimax: { name: "MiniMax-M2.5", base_url: "https://api.minimax.io/anthropic" },
87
- gemini: { name: "gemini-2.5-flash", base_url: "https://generativelanguage.googleapis.com/v1beta/openai" },
88
- deepseek: { name: "deepseek-chat", base_url: "https://api.deepseek.com/v1" },
89
- "deepseek-coder": { name: "deepseek-coder", base_url: "https://api.deepseek.com/v1" },
90
- "openai-compatible": { name: customModelName || "gpt-4o", base_url: customBaseUrl }
91
- };
92
- const modelConfig = modelConfigs[provider] || modelConfigs["gemini"];
93
- let config = `# Hypercore \u914D\u7F6E\u6587\u4EF6
94
- # \u81EA\u52A8\u751F\u6210\uFF0C\u53EF\u624B\u52A8\u4FEE\u6539
95
-
96
- [model]
97
- provider = "${provider}"
98
- name = "${modelConfig.name}"
99
- api_key = "${escapeTomlValue(apiKey)}"
100
- `;
101
- if (modelConfig.base_url) {
102
- config += `base_url = "${modelConfig.base_url}"
103
- `;
104
- }
105
- config += `
106
- [output]
107
- dir = "${join(HYPERCORE_DIR, "outputs")}"
108
- `;
109
- if (tavilyKey) {
110
- config += `
111
- [search]
112
- provider = "tavily"
113
- api_key = "${escapeTomlValue(tavilyKey)}"
114
- `;
115
- }
116
- config += `
117
- # [keys] \u2014 \u591A\u6A21\u578B\u63D0\u4F9B\u5546 API Key\uFF08\u5DE5\u4F4D\u7EA7\u6A21\u578B\u5207\u6362\u65F6\u4F7F\u7528\uFF09
118
- # [keys]
119
- # anthropic = "sk-ant-..."
120
- # gemini = "AIza..."
121
- # deepseek = "sk-..."
122
- # minimax = "..."
123
- `;
124
- return config;
125
- }
126
- function generatePWP(role) {
127
- return `# \u4E2A\u4EBA\u5DE5\u4F5C\u7A7A\u95F4\u534F\u8BAE\uFF08PWP\uFF09
128
-
129
- ## \u8EAB\u4EFD
130
- \u4F60\u662F\u4E00\u4E2A AI \u534F\u4F5C\u7CFB\u7EDF\uFF0C\u4E3A\u4EE5\u4E0B\u7528\u6237\u670D\u52A1\uFF1A
131
- ${role}
132
-
133
- \u4F60\u7684\u76EE\u6807\u662F\u5E2E\u52A9\u7528\u6237\u9AD8\u6548\u5B8C\u6210\u77E5\u8BC6\u5DE5\u4F5C\uFF0C\u4EA7\u51FA\u9AD8\u8D28\u91CF\u5185\u5BB9\u3002
134
-
135
- ## \u54C1\u8D28\u6807\u51C6
136
- - \u6240\u6709\u8F93\u51FA\u5FC5\u987B\u6709\u5B9E\u8D28\u5185\u5BB9\u548C\u72EC\u5230\u6D1E\u5BDF\uFF0C\u4E0D\u8981\u7A7A\u6D1E\u7684\u5957\u8BDD
137
- - \u5B81\u6DF1\u52FF\u6D45\uFF0C\u5B81\u7CBE\u52FF\u6CDB
138
- - \u5FC5\u987B\u6709\u539F\u521B\u89C2\u70B9\u6216\u72EC\u7279\u89C6\u89D2
139
- - \u6570\u636E\u548C\u6848\u4F8B\u5FC5\u987B\u6709\u6765\u6E90\u652F\u6491
140
- - \u8BED\u8A00\u7B80\u6D01\u6709\u529B\uFF0C\u4E0D\u62D6\u6CE5\u5E26\u6C34
141
- - \u5982\u679C\u4FE1\u606F\u4E0D\u8DB3\uFF0C\u660E\u786E\u6807\u6CE8\u800C\u975E\u7F16\u9020
142
- `;
143
- }
144
- async function initializeWorkspace(options) {
145
- const {
146
- provider,
147
- apiKey,
148
- tavilyKey,
149
- role,
150
- customBaseUrl,
151
- customModelName,
152
- agents,
153
- skills,
154
- lines
155
- } = options;
156
- await mkdir(HYPERCORE_DIR, { recursive: true });
157
- for (const sub of ["agents", "skills", "lines", "outputs", "memory"]) {
158
- await mkdir(join(HYPERCORE_DIR, sub), { recursive: true });
159
- }
160
- const templatesDir = getTemplatesDir();
161
- await copyTemplateSubset(join(templatesDir, "agents"), join(HYPERCORE_DIR, "agents"), agents, "agent");
162
- await copyTemplateSubset(join(templatesDir, "skills"), join(HYPERCORE_DIR, "skills"), skills, "skill");
163
- await copyTemplateSubset(join(templatesDir, "lines"), join(HYPERCORE_DIR, "lines"), lines, "line");
164
- if (role) {
165
- const pwpPath = join(HYPERCORE_DIR, "PWP.md");
166
- if (!existsSync(pwpPath)) {
167
- await writeFile(pwpPath, generatePWP(role), "utf-8");
168
- }
169
- }
170
- const configPath = join(HYPERCORE_DIR, "config.toml");
171
- if (existsSync(configPath)) {
172
- const { copyFile: cpFile } = await import("fs/promises");
173
- await cpFile(configPath, configPath + ".bak");
174
- }
175
- await writeFile(
176
- configPath,
177
- generateConfigToml(provider, apiKey, tavilyKey, customBaseUrl, customModelName),
178
- "utf-8"
179
- );
180
- }
181
-
182
- // src/core/engine.ts
183
- import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
184
- import { join as join2 } from "path";
185
-
186
- // src/core/prompt-assembler.ts
187
- function assembleSystemPrompt(pwp, agent, skill) {
188
- const parts = [];
189
- parts.push("## \u5DE5\u4F5C\u7A7A\u95F4\u534F\u8BAE\uFF08PWP\uFF09");
190
- if (pwp.identity) {
191
- parts.push(pwp.identity);
192
- }
193
- if (pwp.qualityStandards.length > 0) {
194
- parts.push("\n### \u54C1\u8D28\u6807\u51C6");
195
- for (const standard of pwp.qualityStandards) {
196
- parts.push(`- ${standard}`);
197
- }
198
- }
199
- parts.push(`
200
- ## \u4F60\u7684\u89D2\u8272\uFF1A${agent.name}`);
201
- if (agent.role) {
202
- parts.push(agent.role);
203
- }
204
- if (agent.style) {
205
- parts.push(`
206
- ### \u98CE\u683C`);
207
- parts.push(agent.style);
208
- }
209
- if (skill) {
210
- parts.push(`
211
- ## \u9886\u57DF\u77E5\u8BC6\uFF1A${skill.name}`);
212
- if (skill.knowledge) {
213
- parts.push(skill.knowledge);
214
- }
215
- if (skill.toolStrategy) {
216
- parts.push("\n### \u5DE5\u5177\u4F7F\u7528\u7B56\u7565");
217
- parts.push(skill.toolStrategy);
218
- }
219
- if (skill.qualityStandards.length > 0) {
220
- parts.push("\n### \u9886\u57DF\u8D28\u91CF\u6807\u51C6");
221
- for (const standard of skill.qualityStandards) {
222
- parts.push(`- ${standard}`);
223
- }
224
- }
225
- }
226
- parts.push("\n## \u901A\u7528\u6307\u4EE4");
227
- parts.push("- \u6240\u6709\u8F93\u51FA\u4F7F\u7528\u4E2D\u6587");
228
- parts.push("- \u9700\u8981\u6700\u65B0\u4FE1\u606F\u65F6\u4E3B\u52A8\u4F7F\u7528 web_search \u5DE5\u5177");
229
- parts.push("- \u8F93\u51FA\u5FC5\u987B\u6709\u5B9E\u8D28\u5185\u5BB9\u548C\u6D1E\u5BDF\uFF0C\u4E0D\u8981\u7A7A\u6D1E\u7684\u5957\u8BDD");
230
- parts.push("- \u5982\u679C\u4FE1\u606F\u4E0D\u8DB3\uFF0C\u660E\u786E\u6807\u6CE8\u800C\u975E\u7F16\u9020");
231
- return parts.join("\n");
232
- }
233
- function assembleUserPrompt(station, userInputs, upstreamOutput) {
234
- const parts = [];
235
- parts.push("## \u5F53\u524D\u4EFB\u52A1");
236
- parts.push(station.task);
237
- if (Object.keys(userInputs).length > 0) {
238
- parts.push("\n## \u7528\u6237\u8F93\u5165");
239
- for (const [key, value] of Object.entries(userInputs)) {
240
- parts.push(`- **${key}**: ${value}`);
241
- }
242
- }
243
- if (upstreamOutput) {
244
- parts.push("\n## \u4E0A\u4E00\u4E2A\u5DE5\u4F4D\u7684\u4EA7\u51FA");
245
- if (upstreamOutput.length > 4e3) {
246
- parts.push(upstreamOutput.slice(0, 4e3));
247
- parts.push("\n...(\u5185\u5BB9\u5DF2\u622A\u53D6\uFF0C\u4EE5\u4E0A\u4E3A\u4E3B\u8981\u90E8\u5206)");
248
- } else {
249
- parts.push(upstreamOutput);
250
- }
251
- }
252
- if (station.checkpoint === "decision") {
253
- parts.push("\n## \u6CE8\u610F");
254
- parts.push("\u8BF7\u63D0\u4F9B\u591A\u4E2A\u5019\u9009\u65B9\u6848\u4F9B\u7528\u6237\u9009\u62E9\u3002\u5217\u51FA 2-3 \u4E2A\u65B9\u6848\uFF0C\u6BCF\u4E2A\u65B9\u6848\u5305\u542B\u6807\u9898\u548C\u7B80\u8981\u8BF4\u660E\u3002");
255
- } else if (station.checkpoint === "approval") {
256
- parts.push("\n## \u6CE8\u610F");
257
- parts.push("\u8FD9\u662F\u7EC8\u5BA1\u5DE5\u4F4D\u3002\u8BF7\u786E\u4FDD\u4EA7\u51FA\u7684\u5B8C\u6574\u6027\u548C\u8D28\u91CF\uFF0C\u7528\u6237\u5C06\u5BA1\u9605\u4F60\u7684\u6700\u7EC8\u4EA7\u51FA\u3002");
258
- }
259
- return parts.join("\n");
260
- }
261
-
262
- // src/core/engine.ts
263
- var Engine = class {
264
- client;
265
- config;
266
- hypercoreDir;
267
- tools = [];
268
- constructor(client, config, hypercoreDir) {
269
- this.client = client;
270
- this.config = config;
271
- this.hypercoreDir = hypercoreDir;
272
- }
273
- /** 初始化工具(async,需在 run 前调用) */
274
- async init() {
275
- this.tools = await createToolRegistry(this.config);
276
- }
277
- /**
278
- * 解析工位级模型覆盖
279
- * 支持别名(flash, sonnet)和完整模型名
280
- * 返回解析后的模型名和 SDK 类型
281
- */
282
- resolveStationModel(station) {
283
- if (!station.model) {
284
- return {
285
- model: this.config.modelConfig.model,
286
- sdkType: this.config.modelConfig.sdkType,
287
- baseURL: this.config.modelConfig.baseURL,
288
- apiKey: this.config.modelConfig.apiKey
289
- };
290
- }
291
- const alias = MODEL_ALIASES[station.model.toLowerCase()];
292
- if (alias) {
293
- const providerInfo = MODEL_PROVIDERS[alias.provider];
294
- const apiKey = this.config.providerKeys[alias.provider] || this.config.modelConfig.apiKey;
295
- return {
296
- model: alias.model,
297
- sdkType: providerInfo.sdkType,
298
- baseURL: providerInfo.baseURL,
299
- apiKey
300
- };
301
- }
302
- const modelLower = station.model.toLowerCase();
303
- if (modelLower.includes("claude")) {
304
- const apiKey = this.config.providerKeys["anthropic"] || this.config.modelConfig.apiKey;
305
- return { model: station.model, sdkType: "anthropic", apiKey };
306
- }
307
- if (modelLower.includes("gemini")) {
308
- const apiKey = this.config.providerKeys["gemini"] || this.config.modelConfig.apiKey;
309
- return { model: station.model, sdkType: "openai", baseURL: MODEL_PROVIDERS["gemini"].baseURL, apiKey };
310
- }
311
- if (modelLower.includes("deepseek")) {
312
- const apiKey = this.config.providerKeys["deepseek"] || this.config.modelConfig.apiKey;
313
- return { model: station.model, sdkType: "openai", baseURL: MODEL_PROVIDERS["deepseek"].baseURL, apiKey };
314
- }
315
- if (modelLower.includes("gpt")) {
316
- const apiKey = this.config.providerKeys["openai-compatible"] || this.config.modelConfig.apiKey;
317
- return { model: station.model, sdkType: "openai", baseURL: this.config.modelConfig.baseURL, apiKey };
318
- }
319
- return {
320
- model: station.model,
321
- sdkType: this.config.modelConfig.sdkType,
322
- baseURL: this.config.modelConfig.baseURL,
323
- apiKey: this.config.modelConfig.apiKey
324
- };
325
- }
326
- /**
327
- * 根据 sdkType 调用对应的 LLM 客户端
328
- * 支持工位级模型覆盖(不同 sdkType 动态创建客户端)
329
- */
330
- async invokeLLM(options, sdkTypeOverride, baseURLOverride, apiKeyOverride) {
331
- const sdkType = sdkTypeOverride || this.config.modelConfig.sdkType;
332
- const apiKey = apiKeyOverride || this.config.modelConfig.apiKey;
333
- if (sdkType === "openai") {
334
- if (this.config.modelConfig.sdkType !== "openai" || baseURLOverride || apiKeyOverride) {
335
- const OpenAI2 = await import("openai");
336
- const tempClient = new OpenAI2.default({
337
- apiKey,
338
- baseURL: baseURLOverride || this.config.modelConfig.baseURL
339
- });
340
- return callOpenAILLM(tempClient, options);
341
- }
342
- const OpenAI = await import("openai");
343
- return callOpenAILLM(this.client, options);
344
- }
345
- if (this.config.modelConfig.sdkType !== "anthropic" || apiKeyOverride) {
346
- const Anthropic2 = await import("@anthropic-ai/sdk");
347
- const tempClient = new Anthropic2.default({ apiKey });
348
- return callLLM(tempClient, options);
349
- }
350
- const Anthropic = await import("@anthropic-ai/sdk");
351
- return callLLM(this.client, options);
352
- }
353
- /**
354
- * 评估条件表达式
355
- * 支持简单的关键词匹配:检查上游输出是否包含指定关键词
356
- * 格式:'contains:关键词' 或 'not_empty' 或直接传入关键词
357
- */
358
- evaluateCondition(condition, upstreamOutput) {
359
- if (!upstreamOutput) return false;
360
- const condLower = condition.toLowerCase().trim();
361
- if (condLower === "not_empty") {
362
- return upstreamOutput.trim().length > 0;
363
- }
364
- if (condLower.startsWith("contains:")) {
365
- const keyword = condition.slice("contains:".length).trim();
366
- return upstreamOutput.includes(keyword);
367
- }
368
- if (condLower.startsWith("not_contains:")) {
369
- const keyword = condition.slice("not_contains:".length).trim();
370
- return !upstreamOutput.includes(keyword);
371
- }
372
- return upstreamOutput.includes(condition.trim());
373
- }
374
- async run(lineName, userInputs, callbacks) {
375
- const startTime = /* @__PURE__ */ new Date();
376
- if (this.tools.length === 0) {
377
- await this.init();
378
- }
379
- const line = await loadLine(this.hypercoreDir, lineName);
380
- let pwp;
381
- try {
382
- pwp = await loadPWP(this.hypercoreDir);
383
- } catch {
384
- pwp = { identity: "", qualityStandards: [], rawContent: "" };
385
- }
386
- const stationResults = [];
387
- let upstreamOutput;
388
- const totalTokens = { inputTokens: 0, outputTokens: 0 };
389
- for (const station of line.stations) {
390
- if (station.condition) {
391
- const shouldRun = this.evaluateCondition(station.condition, upstreamOutput);
392
- if (!shouldRun) {
393
- callbacks.onStationSkipped?.(station.index, station.name, `\u6761\u4EF6\u4E0D\u6EE1\u8DB3: ${station.condition}`);
394
- stationResults.push({
395
- stationIndex: station.index,
396
- stationName: station.name,
397
- agentName: station.agentName,
398
- output: upstreamOutput || "",
399
- toolCalls: [],
400
- tokenUsage: { inputTokens: 0, outputTokens: 0 }
401
- });
402
- continue;
403
- }
404
- }
405
- callbacks.onStationStart(
406
- station.index,
407
- line.stations.length,
408
- station.name,
409
- station.agentName
410
- );
411
- const { model: stationModel, sdkType: stationSdkType, baseURL: stationBaseURL, apiKey: stationApiKey } = this.resolveStationModel(station);
412
- let agent;
413
- try {
414
- agent = await loadAgent(this.hypercoreDir, station.agentName);
415
- } catch {
416
- agent = {
417
- name: station.agentName,
418
- role: `\u4F60\u662F${station.agentName}`,
419
- skillIds: [],
420
- style: "",
421
- rawContent: ""
422
- };
423
- }
424
- let skill;
425
- if (station.skillName) {
426
- try {
427
- skill = await loadSkill(this.hypercoreDir, station.skillName);
428
- } catch {
429
- }
430
- }
431
- const systemPrompt = assembleSystemPrompt(pwp, agent, skill);
432
- const userPrompt = assembleUserPrompt(station, userInputs, upstreamOutput);
433
- const maxRetry = station.retry || 0;
434
- let result = null;
435
- let lastError = null;
436
- for (let attempt = 0; attempt <= maxRetry; attempt++) {
437
- try {
438
- if (attempt > 0) {
439
- callbacks.onStationRetry?.(
440
- station.index,
441
- station.name,
442
- attempt,
443
- maxRetry,
444
- lastError?.message || "\u672A\u77E5\u9519\u8BEF"
445
- );
446
- }
447
- result = await this.invokeLLM(
448
- {
449
- systemPrompt,
450
- userPrompt,
451
- tools: this.tools,
452
- model: stationModel,
453
- onText: (text) => callbacks.onStationText(text),
454
- onToolCall: (name, input) => callbacks.onToolCall(name, input),
455
- onToolCallDone: callbacks.onToolCallDone ? (name, dur) => callbacks.onToolCallDone(name, dur) : void 0,
456
- onThinking: callbacks.onThinking ? (text) => callbacks.onThinking(text) : void 0
457
- },
458
- stationSdkType,
459
- stationBaseURL,
460
- stationApiKey !== this.config.modelConfig.apiKey ? stationApiKey : void 0
461
- );
462
- break;
463
- } catch (err) {
464
- lastError = err instanceof Error ? err : new Error(String(err));
465
- if (attempt >= maxRetry) {
466
- throw lastError;
467
- }
468
- }
469
- }
470
- if (!result) throw new Error(`\u5DE5\u4F4D ${station.name} \u6267\u884C\u5931\u8D25`);
471
- const stationResult = {
472
- stationIndex: station.index,
473
- stationName: station.name,
474
- agentName: station.agentName,
475
- output: result.output,
476
- toolCalls: result.toolCalls,
477
- tokenUsage: result.tokenUsage
478
- };
479
- stationResults.push(stationResult);
480
- totalTokens.inputTokens += result.tokenUsage.inputTokens;
481
- totalTokens.outputTokens += result.tokenUsage.outputTokens;
482
- callbacks.onStationComplete(station.index, station.name);
483
- if (station.checkpoint) {
484
- const checkpointResult = await callbacks.onCheckpoint(
485
- station.checkpoint,
486
- result.output,
487
- station.checkpointDescription
488
- );
489
- if (checkpointResult.action === "modify" && checkpointResult.feedback) {
490
- const modifyPrompt = `\u7528\u6237\u5BF9\u4F60\u7684\u4EA7\u51FA\u7ED9\u4E86\u4EE5\u4E0B\u53CD\u9988\uFF0C\u8BF7\u636E\u6B64\u4FEE\u6539\uFF1A
491
-
492
- ${checkpointResult.feedback}
493
-
494
- \u4F60\u4E4B\u524D\u7684\u4EA7\u51FA\uFF1A
495
- ${result.output}`;
496
- const modifyResult = await this.invokeLLM(
497
- {
498
- systemPrompt,
499
- userPrompt: modifyPrompt,
500
- tools: this.tools,
501
- model: stationModel,
502
- onText: (text) => callbacks.onStationText(text),
503
- onToolCall: (name, input) => callbacks.onToolCall(name, input),
504
- onToolCallDone: callbacks.onToolCallDone ? (name, dur) => callbacks.onToolCallDone(name, dur) : void 0,
505
- onThinking: callbacks.onThinking ? (text) => callbacks.onThinking(text) : void 0
506
- },
507
- stationSdkType,
508
- stationBaseURL,
509
- stationApiKey !== this.config.modelConfig.apiKey ? stationApiKey : void 0
510
- );
511
- stationResult.output = modifyResult.output;
512
- totalTokens.inputTokens += modifyResult.tokenUsage.inputTokens;
513
- totalTokens.outputTokens += modifyResult.tokenUsage.outputTokens;
514
- }
515
- }
516
- upstreamOutput = stationResult.output;
517
- }
518
- const finalOutput = stationResults[stationResults.length - 1]?.output || "";
519
- const outputDir = join2(this.config.outputDir);
520
- await mkdir2(outputDir, { recursive: true });
521
- const endTime = /* @__PURE__ */ new Date();
522
- const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
523
- const sanitizedName = lineName.replace(/[^\w\u4e00-\u9fff-]/g, "_");
524
- const outputPath = join2(outputDir, `${date}-${sanitizedName}.md`);
525
- const durationMin = ((endTime.getTime() - startTime.getTime()) / 6e4).toFixed(1);
526
- const totalTokenCount = totalTokens.inputTokens + totalTokens.outputTokens;
527
- const frontmatter = [
528
- "---",
529
- `line: ${lineName}`,
530
- `date: ${startTime.toISOString()}`,
531
- `model: ${this.config.modelConfig.model}`,
532
- `tokens: ${totalTokenCount}`,
533
- `duration: ${durationMin}min`,
534
- `stations: ${line.stations.length}`,
535
- "---",
536
- ""
537
- ].join("\n");
538
- await writeFile2(outputPath, frontmatter + finalOutput, "utf-8");
539
- const runMeta = {
540
- lineName,
541
- startTime: startTime.toISOString(),
542
- endTime: endTime.toISOString(),
543
- model: this.config.modelConfig.model,
544
- userInputs,
545
- totalTokens,
546
- stations: stationResults.map((s) => ({
547
- index: s.stationIndex,
548
- name: s.stationName,
549
- agent: s.agentName,
550
- output: s.output,
551
- toolCalls: s.toolCalls,
552
- tokens: s.tokenUsage
553
- }))
554
- };
555
- const jsonPath = outputPath.replace(/\.md$/, ".run.json");
556
- await writeFile2(jsonPath, JSON.stringify(runMeta, null, 2), "utf-8");
557
- const runResult = {
558
- lineName,
559
- stationResults,
560
- finalOutput,
561
- totalTokens,
562
- outputPath,
563
- startTime,
564
- endTime
565
- };
566
- callbacks.onComplete(runResult);
567
- return runResult;
568
- }
569
- };
570
-
571
- export {
572
- HYPERCORE_DIR,
573
- initializeWorkspace,
574
- Engine
575
- };