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,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
- };