@roarpeng/graphflow 0.6.5

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 (271) hide show
  1. package/AGENTS.md +58 -0
  2. package/CHANGELOG.md +205 -0
  3. package/CLAUDE.md +39 -0
  4. package/LICENSE +17 -0
  5. package/README.md +434 -0
  6. package/dist/agents/brainstormer.d.ts +5 -0
  7. package/dist/agents/brainstormer.d.ts.map +1 -0
  8. package/dist/agents/brainstormer.js +61 -0
  9. package/dist/agents/brainstormer.js.map +1 -0
  10. package/dist/agents/planner.d.ts +14 -0
  11. package/dist/agents/planner.d.ts.map +1 -0
  12. package/dist/agents/planner.js +166 -0
  13. package/dist/agents/planner.js.map +1 -0
  14. package/dist/agents/validator.d.ts +6 -0
  15. package/dist/agents/validator.d.ts.map +1 -0
  16. package/dist/agents/validator.js +133 -0
  17. package/dist/agents/validator.js.map +1 -0
  18. package/dist/agents/worker.d.ts +18 -0
  19. package/dist/agents/worker.d.ts.map +1 -0
  20. package/dist/agents/worker.js +34 -0
  21. package/dist/agents/worker.js.map +1 -0
  22. package/dist/config/defaults.d.ts +16 -0
  23. package/dist/config/defaults.d.ts.map +1 -0
  24. package/dist/config/defaults.js +85 -0
  25. package/dist/config/defaults.js.map +1 -0
  26. package/dist/config/embedding-factory.d.ts +4 -0
  27. package/dist/config/embedding-factory.d.ts.map +1 -0
  28. package/dist/config/embedding-factory.js +37 -0
  29. package/dist/config/embedding-factory.js.map +1 -0
  30. package/dist/config/loader.d.ts +4 -0
  31. package/dist/config/loader.d.ts.map +1 -0
  32. package/dist/config/loader.js +194 -0
  33. package/dist/config/loader.js.map +1 -0
  34. package/dist/config/merge.d.ts +6 -0
  35. package/dist/config/merge.d.ts.map +1 -0
  36. package/dist/config/merge.js +130 -0
  37. package/dist/config/merge.js.map +1 -0
  38. package/dist/config/paths.d.ts +6 -0
  39. package/dist/config/paths.d.ts.map +1 -0
  40. package/dist/config/paths.js +32 -0
  41. package/dist/config/paths.js.map +1 -0
  42. package/dist/config/resolve.d.ts +4 -0
  43. package/dist/config/resolve.d.ts.map +1 -0
  44. package/dist/config/resolve.js +45 -0
  45. package/dist/config/resolve.js.map +1 -0
  46. package/dist/config/scaffold.d.ts +11 -0
  47. package/dist/config/scaffold.d.ts.map +1 -0
  48. package/dist/config/scaffold.js +42 -0
  49. package/dist/config/scaffold.js.map +1 -0
  50. package/dist/config/schema.d.ts +102 -0
  51. package/dist/config/schema.d.ts.map +1 -0
  52. package/dist/config/schema.js +3 -0
  53. package/dist/config/schema.js.map +1 -0
  54. package/dist/config/secrets.d.ts +9 -0
  55. package/dist/config/secrets.d.ts.map +1 -0
  56. package/dist/config/secrets.js +55 -0
  57. package/dist/config/secrets.js.map +1 -0
  58. package/dist/core/dag-engine.d.ts +14 -0
  59. package/dist/core/dag-engine.d.ts.map +1 -0
  60. package/dist/core/dag-engine.js +97 -0
  61. package/dist/core/dag-engine.js.map +1 -0
  62. package/dist/core/errors.d.ts +15 -0
  63. package/dist/core/errors.d.ts.map +1 -0
  64. package/dist/core/errors.js +29 -0
  65. package/dist/core/errors.js.map +1 -0
  66. package/dist/core/orchestrator.d.ts +31 -0
  67. package/dist/core/orchestrator.d.ts.map +1 -0
  68. package/dist/core/orchestrator.js +321 -0
  69. package/dist/core/orchestrator.js.map +1 -0
  70. package/dist/core/state-machine.d.ts +14 -0
  71. package/dist/core/state-machine.d.ts.map +1 -0
  72. package/dist/core/state-machine.js +77 -0
  73. package/dist/core/state-machine.js.map +1 -0
  74. package/dist/core/triage.d.ts +6 -0
  75. package/dist/core/triage.d.ts.map +1 -0
  76. package/dist/core/triage.js +58 -0
  77. package/dist/core/triage.js.map +1 -0
  78. package/dist/core/types.d.ts +61 -0
  79. package/dist/core/types.d.ts.map +1 -0
  80. package/dist/core/types.js +3 -0
  81. package/dist/core/types.js.map +1 -0
  82. package/dist/graph/client-factory.d.ts +22 -0
  83. package/dist/graph/client-factory.d.ts.map +1 -0
  84. package/dist/graph/client-factory.js +60 -0
  85. package/dist/graph/client-factory.js.map +1 -0
  86. package/dist/graph/context-slicer.d.ts +47 -0
  87. package/dist/graph/context-slicer.d.ts.map +1 -0
  88. package/dist/graph/context-slicer.js +246 -0
  89. package/dist/graph/context-slicer.js.map +1 -0
  90. package/dist/graph/file-indexer.d.ts +15 -0
  91. package/dist/graph/file-indexer.d.ts.map +1 -0
  92. package/dist/graph/file-indexer.js +343 -0
  93. package/dist/graph/file-indexer.js.map +1 -0
  94. package/dist/graph/graph-indexer.d.ts +7 -0
  95. package/dist/graph/graph-indexer.d.ts.map +1 -0
  96. package/dist/graph/graph-indexer.js +32 -0
  97. package/dist/graph/graph-indexer.js.map +1 -0
  98. package/dist/graph/graphify-client.d.ts +30 -0
  99. package/dist/graph/graphify-client.d.ts.map +1 -0
  100. package/dist/graph/graphify-client.js +186 -0
  101. package/dist/graph/graphify-client.js.map +1 -0
  102. package/dist/graph/graphify-file-client.d.ts +26 -0
  103. package/dist/graph/graphify-file-client.d.ts.map +1 -0
  104. package/dist/graph/graphify-file-client.js +140 -0
  105. package/dist/graph/graphify-file-client.js.map +1 -0
  106. package/dist/graph/graphify-mcp-client.d.ts +18 -0
  107. package/dist/graph/graphify-mcp-client.d.ts.map +1 -0
  108. package/dist/graph/graphify-mcp-client.js +73 -0
  109. package/dist/graph/graphify-mcp-client.js.map +1 -0
  110. package/dist/graph/language-indexers/c-cpp.d.ts +3 -0
  111. package/dist/graph/language-indexers/c-cpp.d.ts.map +1 -0
  112. package/dist/graph/language-indexers/c-cpp.js +121 -0
  113. package/dist/graph/language-indexers/c-cpp.js.map +1 -0
  114. package/dist/graph/language-indexers/go.d.ts +3 -0
  115. package/dist/graph/language-indexers/go.d.ts.map +1 -0
  116. package/dist/graph/language-indexers/go.js +97 -0
  117. package/dist/graph/language-indexers/go.js.map +1 -0
  118. package/dist/graph/language-indexers/index.d.ts +29 -0
  119. package/dist/graph/language-indexers/index.d.ts.map +1 -0
  120. package/dist/graph/language-indexers/index.js +27 -0
  121. package/dist/graph/language-indexers/index.js.map +1 -0
  122. package/dist/graph/language-indexers/python.d.ts +3 -0
  123. package/dist/graph/language-indexers/python.d.ts.map +1 -0
  124. package/dist/graph/language-indexers/python.js +91 -0
  125. package/dist/graph/language-indexers/python.js.map +1 -0
  126. package/dist/graph/language-indexers/rust.d.ts +3 -0
  127. package/dist/graph/language-indexers/rust.d.ts.map +1 -0
  128. package/dist/graph/language-indexers/rust.js +99 -0
  129. package/dist/graph/language-indexers/rust.js.map +1 -0
  130. package/dist/graph/language-indexers/tree-sitter-loader.d.ts +18 -0
  131. package/dist/graph/language-indexers/tree-sitter-loader.d.ts.map +1 -0
  132. package/dist/graph/language-indexers/tree-sitter-loader.js +34 -0
  133. package/dist/graph/language-indexers/tree-sitter-loader.js.map +1 -0
  134. package/dist/graph/language-indexers/typescript.d.ts +3 -0
  135. package/dist/graph/language-indexers/typescript.d.ts.map +1 -0
  136. package/dist/graph/language-indexers/typescript.js +194 -0
  137. package/dist/graph/language-indexers/typescript.js.map +1 -0
  138. package/dist/graph/semantic-enricher.d.ts +17 -0
  139. package/dist/graph/semantic-enricher.d.ts.map +1 -0
  140. package/dist/graph/semantic-enricher.js +97 -0
  141. package/dist/graph/semantic-enricher.js.map +1 -0
  142. package/dist/graph/sqlite-client.d.ts +24 -0
  143. package/dist/graph/sqlite-client.d.ts.map +1 -0
  144. package/dist/graph/sqlite-client.js +215 -0
  145. package/dist/graph/sqlite-client.js.map +1 -0
  146. package/dist/hooks/post-run-sync.d.ts +7 -0
  147. package/dist/hooks/post-run-sync.d.ts.map +1 -0
  148. package/dist/hooks/post-run-sync.js +26 -0
  149. package/dist/hooks/post-run-sync.js.map +1 -0
  150. package/dist/index.d.ts +10 -0
  151. package/dist/index.d.ts.map +1 -0
  152. package/dist/index.js +42 -0
  153. package/dist/index.js.map +1 -0
  154. package/dist/integrations/agent-mcp-installer.d.ts +50 -0
  155. package/dist/integrations/agent-mcp-installer.d.ts.map +1 -0
  156. package/dist/integrations/agent-mcp-installer.js +414 -0
  157. package/dist/integrations/agent-mcp-installer.js.map +1 -0
  158. package/dist/learning/canary-gate.d.ts +6 -0
  159. package/dist/learning/canary-gate.d.ts.map +1 -0
  160. package/dist/learning/canary-gate.js +13 -0
  161. package/dist/learning/canary-gate.js.map +1 -0
  162. package/dist/learning/embeddings.d.ts +19 -0
  163. package/dist/learning/embeddings.d.ts.map +1 -0
  164. package/dist/learning/embeddings.js +160 -0
  165. package/dist/learning/embeddings.js.map +1 -0
  166. package/dist/learning/episodic-memory.d.ts +36 -0
  167. package/dist/learning/episodic-memory.d.ts.map +1 -0
  168. package/dist/learning/episodic-memory.js +228 -0
  169. package/dist/learning/episodic-memory.js.map +1 -0
  170. package/dist/learning/exporter.d.ts +10 -0
  171. package/dist/learning/exporter.d.ts.map +1 -0
  172. package/dist/learning/exporter.js +25 -0
  173. package/dist/learning/exporter.js.map +1 -0
  174. package/dist/learning/feedback-collector.d.ts +12 -0
  175. package/dist/learning/feedback-collector.d.ts.map +1 -0
  176. package/dist/learning/feedback-collector.js +14 -0
  177. package/dist/learning/feedback-collector.js.map +1 -0
  178. package/dist/learning/learning-events.d.ts +4 -0
  179. package/dist/learning/learning-events.d.ts.map +1 -0
  180. package/dist/learning/learning-events.js +35 -0
  181. package/dist/learning/learning-events.js.map +1 -0
  182. package/dist/learning/local-embedding.d.ts +3 -0
  183. package/dist/learning/local-embedding.d.ts.map +1 -0
  184. package/dist/learning/local-embedding.js +21 -0
  185. package/dist/learning/local-embedding.js.map +1 -0
  186. package/dist/learning/nightly-trainer.d.ts +14 -0
  187. package/dist/learning/nightly-trainer.d.ts.map +1 -0
  188. package/dist/learning/nightly-trainer.js +56 -0
  189. package/dist/learning/nightly-trainer.js.map +1 -0
  190. package/dist/learning/reflector.d.ts +19 -0
  191. package/dist/learning/reflector.d.ts.map +1 -0
  192. package/dist/learning/reflector.js +130 -0
  193. package/dist/learning/reflector.js.map +1 -0
  194. package/dist/learning/sample-builder.d.ts +7 -0
  195. package/dist/learning/sample-builder.d.ts.map +1 -0
  196. package/dist/learning/sample-builder.js +10 -0
  197. package/dist/learning/sample-builder.js.map +1 -0
  198. package/dist/learning/skill-flywheel.d.ts +52 -0
  199. package/dist/learning/skill-flywheel.d.ts.map +1 -0
  200. package/dist/learning/skill-flywheel.js +533 -0
  201. package/dist/learning/skill-flywheel.js.map +1 -0
  202. package/dist/learning/vector-store.d.ts +18 -0
  203. package/dist/learning/vector-store.d.ts.map +1 -0
  204. package/dist/learning/vector-store.js +73 -0
  205. package/dist/learning/vector-store.js.map +1 -0
  206. package/dist/routing/model-router.d.ts +13 -0
  207. package/dist/routing/model-router.d.ts.map +1 -0
  208. package/dist/routing/model-router.js +113 -0
  209. package/dist/routing/model-router.js.map +1 -0
  210. package/dist/routing/provider-adapters/anthropic.d.ts +3 -0
  211. package/dist/routing/provider-adapters/anthropic.d.ts.map +1 -0
  212. package/dist/routing/provider-adapters/anthropic.js +57 -0
  213. package/dist/routing/provider-adapters/anthropic.js.map +1 -0
  214. package/dist/routing/provider-adapters/bailian.d.ts +3 -0
  215. package/dist/routing/provider-adapters/bailian.d.ts.map +1 -0
  216. package/dist/routing/provider-adapters/bailian.js +56 -0
  217. package/dist/routing/provider-adapters/bailian.js.map +1 -0
  218. package/dist/routing/provider-adapters/doubao.d.ts +3 -0
  219. package/dist/routing/provider-adapters/doubao.d.ts.map +1 -0
  220. package/dist/routing/provider-adapters/doubao.js +56 -0
  221. package/dist/routing/provider-adapters/doubao.js.map +1 -0
  222. package/dist/routing/provider-adapters/openai.d.ts +6 -0
  223. package/dist/routing/provider-adapters/openai.d.ts.map +1 -0
  224. package/dist/routing/provider-adapters/openai.js +80 -0
  225. package/dist/routing/provider-adapters/openai.js.map +1 -0
  226. package/dist/routing/provider-adapters/openbmb.d.ts +16 -0
  227. package/dist/routing/provider-adapters/openbmb.d.ts.map +1 -0
  228. package/dist/routing/provider-adapters/openbmb.js +368 -0
  229. package/dist/routing/provider-adapters/openbmb.js.map +1 -0
  230. package/dist/routing/provider-executor.d.ts +21 -0
  231. package/dist/routing/provider-executor.d.ts.map +1 -0
  232. package/dist/routing/provider-executor.js +260 -0
  233. package/dist/routing/provider-executor.js.map +1 -0
  234. package/dist/routing/provider-health.d.ts +9 -0
  235. package/dist/routing/provider-health.d.ts.map +1 -0
  236. package/dist/routing/provider-health.js +66 -0
  237. package/dist/routing/provider-health.js.map +1 -0
  238. package/dist/surfaces/cli/index.d.ts +3 -0
  239. package/dist/surfaces/cli/index.d.ts.map +1 -0
  240. package/dist/surfaces/cli/index.js +200 -0
  241. package/dist/surfaces/cli/index.js.map +1 -0
  242. package/dist/surfaces/cli/init.d.ts +2 -0
  243. package/dist/surfaces/cli/init.d.ts.map +1 -0
  244. package/dist/surfaces/cli/init.js +121 -0
  245. package/dist/surfaces/cli/init.js.map +1 -0
  246. package/dist/surfaces/cli/output.d.ts +16 -0
  247. package/dist/surfaces/cli/output.d.ts.map +1 -0
  248. package/dist/surfaces/cli/output.js +74 -0
  249. package/dist/surfaces/cli/output.js.map +1 -0
  250. package/dist/surfaces/cli/runtime.d.ts +218 -0
  251. package/dist/surfaces/cli/runtime.d.ts.map +1 -0
  252. package/dist/surfaces/cli/runtime.js +1130 -0
  253. package/dist/surfaces/cli/runtime.js.map +1 -0
  254. package/dist/surfaces/mcp/server.d.ts +60 -0
  255. package/dist/surfaces/mcp/server.d.ts.map +1 -0
  256. package/dist/surfaces/mcp/server.js +425 -0
  257. package/dist/surfaces/mcp/server.js.map +1 -0
  258. package/dist/surfaces/vscode/extension.d.ts +17 -0
  259. package/dist/surfaces/vscode/extension.d.ts.map +1 -0
  260. package/dist/surfaces/vscode/extension.js +35 -0
  261. package/dist/surfaces/vscode/extension.js.map +1 -0
  262. package/dist/utils/file-lock.d.ts +9 -0
  263. package/dist/utils/file-lock.d.ts.map +1 -0
  264. package/dist/utils/file-lock.js +90 -0
  265. package/dist/utils/file-lock.js.map +1 -0
  266. package/dist/utils/logger.d.ts +3 -0
  267. package/dist/utils/logger.d.ts.map +1 -0
  268. package/dist/utils/logger.js +36 -0
  269. package/dist/utils/logger.js.map +1 -0
  270. package/package.json +89 -0
  271. package/scripts/safe-postinstall.cjs +14 -0
@@ -0,0 +1,1130 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.installMcpToDetectedAgents = exports.formatModelConfigGuide = exports.detectInstalledAgents = exports.buildMcpServerNode = exports.resolveConfigPath = exports.resolveConfig = exports.resolveGlobalConfigPath = exports.ensureWorkspaceGraphFlowConfig = exports.ensureGlobalGraphFlowConfig = exports.getDefaultConfig = void 0;
4
+ exports.prepareSemanticEnrichmentRuntime = prepareSemanticEnrichmentRuntime;
5
+ exports.applyEnrichmentProviderEnv = applyEnrichmentProviderEnv;
6
+ exports.applyOpenBmbRuntimeEnv = applyOpenBmbRuntimeEnv;
7
+ exports.getGraphFlowSettings = getGraphFlowSettings;
8
+ exports.saveGraphFlowSettings = saveGraphFlowSettings;
9
+ exports.previewContext = previewContext;
10
+ exports.indexGraph = indexGraph;
11
+ exports.rebuildGraph = rebuildGraph;
12
+ exports.enrichSemanticsSilent = enrichSemanticsSilent;
13
+ exports.downloadOpenBmbModel = downloadOpenBmbModel;
14
+ exports.inspectGraph = inspectGraph;
15
+ exports.getSkillInsights = getSkillInsights;
16
+ exports.runTaskResult = runTaskResult;
17
+ exports.runTask = runTask;
18
+ exports.diagnoseRoutingResult = diagnoseRoutingResult;
19
+ exports.diagnoseRouting = diagnoseRouting;
20
+ exports.getSettingsPanelStatus = getSettingsPanelStatus;
21
+ exports.runLearningNightlyResult = runLearningNightlyResult;
22
+ exports.runLearningNightly = runLearningNightly;
23
+ exports.planAndBrainstormResult = planAndBrainstormResult;
24
+ exports.planAndBrainstorm = planAndBrainstorm;
25
+ const node_fs_1 = require("node:fs");
26
+ const node_path_1 = require("node:path");
27
+ const node_crypto_1 = require("node:crypto");
28
+ const node_os_1 = require("node:os");
29
+ const brainstormer_1 = require("../../agents/brainstormer");
30
+ const planner_1 = require("../../agents/planner");
31
+ const loader_1 = require("../../config/loader");
32
+ const secrets_1 = require("../../config/secrets");
33
+ const merge_1 = require("../../config/merge");
34
+ const resolve_1 = require("../../config/resolve");
35
+ const embedding_factory_1 = require("../../config/embedding-factory");
36
+ const paths_1 = require("../../config/paths");
37
+ const triage_1 = require("../../core/triage");
38
+ const orchestrator_1 = require("../../core/orchestrator");
39
+ const client_factory_1 = require("../../graph/client-factory");
40
+ const semantic_enricher_1 = require("../../graph/semantic-enricher");
41
+ const sqlite_client_1 = require("../../graph/sqlite-client");
42
+ const file_indexer_1 = require("../../graph/file-indexer");
43
+ const context_slicer_1 = require("../../graph/context-slicer");
44
+ const nightly_trainer_1 = require("../../learning/nightly-trainer");
45
+ const learning_events_1 = require("../../learning/learning-events");
46
+ const model_router_1 = require("../../routing/model-router");
47
+ const provider_health_1 = require("../../routing/provider-health");
48
+ const file_lock_1 = require("../../utils/file-lock");
49
+ const logger_1 = require("../../utils/logger");
50
+ var defaults_1 = require("../../config/defaults");
51
+ Object.defineProperty(exports, "getDefaultConfig", { enumerable: true, get: function () { return defaults_1.getDefaultConfig; } });
52
+ var scaffold_1 = require("../../config/scaffold");
53
+ Object.defineProperty(exports, "ensureGlobalGraphFlowConfig", { enumerable: true, get: function () { return scaffold_1.ensureGlobalGraphFlowConfig; } });
54
+ Object.defineProperty(exports, "ensureWorkspaceGraphFlowConfig", { enumerable: true, get: function () { return scaffold_1.ensureWorkspaceGraphFlowConfig; } });
55
+ Object.defineProperty(exports, "resolveGlobalConfigPath", { enumerable: true, get: function () { return scaffold_1.resolveGlobalConfigPath; } });
56
+ var resolve_2 = require("../../config/resolve");
57
+ Object.defineProperty(exports, "resolveConfig", { enumerable: true, get: function () { return resolve_2.resolveConfig; } });
58
+ Object.defineProperty(exports, "resolveConfigPath", { enumerable: true, get: function () { return resolve_2.resolveConfigPath; } });
59
+ function buildEmbeddingOptions(config) {
60
+ const embeddingProvider = (0, embedding_factory_1.createEmbeddingProviderFromConfig)(config);
61
+ if (!embeddingProvider) {
62
+ return {};
63
+ }
64
+ return {
65
+ embeddingProvider,
66
+ enableVectorRecall: true,
67
+ ...(config.embeddingPolicy?.topK !== undefined ? { vectorTopK: config.embeddingPolicy.topK } : {}),
68
+ ...(config.embeddingPolicy?.minSimilarity !== undefined
69
+ ? { vectorMinSimilarity: config.embeddingPolicy.minSimilarity }
70
+ : {}),
71
+ };
72
+ }
73
+ function resolveEnrichmentBackend(policy) {
74
+ if (policy?.backend === "network" || policy?.backend === "local" || policy?.backend === "inherit") {
75
+ return policy.backend;
76
+ }
77
+ if (policy?.provider === "openbmb") {
78
+ return "local";
79
+ }
80
+ if (policy?.model || policy?.provider || policy?.apiKey || policy?.baseUrl) {
81
+ return "network";
82
+ }
83
+ return "inherit";
84
+ }
85
+ /** Apply enrichment-specific cloud credentials over generic provider env (network backend only). */
86
+ function prepareSemanticEnrichmentRuntime(configPath) {
87
+ if (!configPath) {
88
+ return;
89
+ }
90
+ const config = (0, resolve_1.resolveConfig)(configPath);
91
+ applyOpenBmbRuntimeEnv(config);
92
+ applyEnrichmentProviderEnv(config);
93
+ }
94
+ function applyEnrichmentProviderEnv(config) {
95
+ const policy = config.graphPolicy.semanticEnrichment;
96
+ const backend = resolveEnrichmentBackend(policy);
97
+ if (backend === "local") {
98
+ return;
99
+ }
100
+ const providerName = (policy?.provider ?? config.tiers.economy.provider).toUpperCase();
101
+ const providerCfg = config.providers[providerName.toLowerCase()] ?? {};
102
+ const apiKey = (0, secrets_1.resolveConfigSecret)(policy?.apiKey) ?? (0, secrets_1.resolveConfigSecret)(providerCfg.apiKey);
103
+ const baseUrl = policy?.baseUrl ?? providerCfg.baseUrl;
104
+ if (apiKey) {
105
+ process.env[`${providerName}_API_KEY`] = apiKey;
106
+ }
107
+ if (baseUrl) {
108
+ process.env[`${providerName}_BASE_URL`] = baseUrl;
109
+ }
110
+ }
111
+ function applyOpenBmbRuntimeEnv(config) {
112
+ const genericProviders = ["openai", "anthropic", "bailian", "doubao"];
113
+ for (const name of genericProviders) {
114
+ const cfg = config.providers[name];
115
+ if (!cfg) {
116
+ continue;
117
+ }
118
+ const envPrefix = name.toUpperCase();
119
+ const apiKey = (0, secrets_1.resolveConfigSecret)(cfg.apiKey);
120
+ if (apiKey) {
121
+ process.env[`${envPrefix}_API_KEY`] = apiKey;
122
+ }
123
+ if (cfg.baseUrl) {
124
+ process.env[`${envPrefix}_BASE_URL`] = cfg.baseUrl;
125
+ }
126
+ }
127
+ const openbmb = config.providers.openbmb;
128
+ if (!openbmb) {
129
+ return;
130
+ }
131
+ if (openbmb.mode) {
132
+ process.env.GRAPHFLOW_OPENBMB_MODE = openbmb.mode;
133
+ }
134
+ if (openbmb.baseUrl) {
135
+ process.env.GRAPHFLOW_OPENBMB_BASE_URL = openbmb.baseUrl;
136
+ }
137
+ const openbmbApiKey = (0, secrets_1.resolveConfigSecret)(openbmb.apiKey);
138
+ if (openbmbApiKey) {
139
+ process.env.GRAPHFLOW_OPENBMB_API_KEY = openbmbApiKey;
140
+ }
141
+ const modelPath = (0, secrets_1.resolveConfigSecret)(openbmb.modelPath);
142
+ if (modelPath) {
143
+ process.env.GRAPHFLOW_OPENBMB_MODEL_PATH = modelPath;
144
+ }
145
+ const commandPath = (0, secrets_1.resolveConfigSecret)(openbmb.commandPath);
146
+ if (commandPath) {
147
+ process.env.GRAPHFLOW_MINICPM_COMMAND = commandPath;
148
+ }
149
+ if (openbmb.modelUrl) {
150
+ process.env.GRAPHFLOW_MINICPM_MODEL_URL = openbmb.modelUrl;
151
+ }
152
+ if (openbmb.modelSha256) {
153
+ process.env.GRAPHFLOW_MINICPM_MODEL_SHA256 = openbmb.modelSha256;
154
+ }
155
+ if (openbmb.autoDownloadModel !== undefined) {
156
+ process.env.GRAPHFLOW_OPENBMB_AUTO_DOWNLOAD = openbmb.autoDownloadModel ? "1" : "0";
157
+ }
158
+ if (openbmb.engine) {
159
+ process.env.GRAPHFLOW_MINICPM_ENGINE = openbmb.engine;
160
+ }
161
+ if (openbmb.timeoutMs !== undefined) {
162
+ process.env.GRAPHFLOW_OPENBMB_TIMEOUT_MS = String(openbmb.timeoutMs);
163
+ }
164
+ if (openbmb.maxTokens !== undefined) {
165
+ process.env.GRAPHFLOW_OPENBMB_MAX_TOKENS = String(openbmb.maxTokens);
166
+ }
167
+ if (openbmb.temperature !== undefined) {
168
+ process.env.GRAPHFLOW_OPENBMB_TEMPERATURE = String(openbmb.temperature);
169
+ }
170
+ const evolution = config.learningPolicy.skillEvolution;
171
+ if (evolution?.model) {
172
+ process.env.GRAPHFLOW_SKILL_EVOLVE_MODEL = evolution.model;
173
+ }
174
+ if (evolution?.minCoOccur !== undefined) {
175
+ process.env.GRAPHFLOW_SKILL_EVOLVE_MIN_COOCCUR = String(evolution.minCoOccur);
176
+ }
177
+ if (evolution?.minSuccess !== undefined) {
178
+ process.env.GRAPHFLOW_SKILL_EVOLVE_MIN_SUCCESS = String(evolution.minSuccess);
179
+ }
180
+ process.env.GRAPHFLOW_SKILL_TRIPLE_FUSION = evolution?.enableTripleFusion === false ? "0" : "1";
181
+ }
182
+ function getGraphFlowSettings(configPath = "graphflow.config.json") {
183
+ const actualPath = (0, resolve_1.resolveConfigPath)(configPath);
184
+ const config = (0, resolve_1.resolveConfig)(actualPath);
185
+ const provider = config.tiers.smart.provider;
186
+ const rawConfig = readRawConfig(actualPath);
187
+ const providerConfig = config.providers[provider] ?? {};
188
+ const rawProviderConfig = rawConfig?.providers?.[provider] ?? {};
189
+ const rawOpenBmbConfig = rawConfig?.providers?.openbmb ?? {};
190
+ const openbmbConfig = config.providers.openbmb ?? {};
191
+ const apiKeyEnvVar = (0, secrets_1.formatApiKeyForSettings)(rawProviderConfig.apiKey ?? providerConfig.apiKey);
192
+ const openbmbModelUrl = rawOpenBmbConfig.modelUrl ?? openbmbConfig.modelUrl ?? process.env.GRAPHFLOW_MINICPM_MODEL_URL;
193
+ const openbmbModelSha256 = rawOpenBmbConfig.modelSha256 ?? openbmbConfig.modelSha256 ?? process.env.GRAPHFLOW_MINICPM_MODEL_SHA256;
194
+ const openbmbAutoDownloadRaw = rawOpenBmbConfig.autoDownloadModel ?? openbmbConfig.autoDownloadModel;
195
+ const openbmbAutoDownload = typeof openbmbAutoDownloadRaw === "boolean"
196
+ ? openbmbAutoDownloadRaw
197
+ : String(process.env.GRAPHFLOW_OPENBMB_AUTO_DOWNLOAD ?? "0") === "1";
198
+ return {
199
+ configPath: actualPath,
200
+ provider,
201
+ smartModel: config.tiers.smart.model ?? "",
202
+ economyModel: config.tiers.economy.model ?? "",
203
+ ...(apiKeyEnvVar ? { apiKeyEnvVar } : {}),
204
+ ...(rawProviderConfig.baseUrl || providerConfig.baseUrl
205
+ ? { baseUrl: rawProviderConfig.baseUrl ?? providerConfig.baseUrl }
206
+ : {}),
207
+ maxContextTokens: config.graphPolicy.maxContextTokens,
208
+ layerQuota: config.graphPolicy.layerQuota ?? { l1: 6, l2: 4, l3: 3 },
209
+ enableNearLosslessMode: config.graphPolicy.enableNearLosslessMode ?? false,
210
+ autoIndexOnPreview: config.graphPolicy.autoIndexOnPreview ?? true,
211
+ autoIndexOnRun: config.graphPolicy.autoIndexOnRun ?? true,
212
+ autoIndexOnSave: config.graphPolicy.autoIndexOnSave ?? false,
213
+ transport: config.graphPolicy.transport,
214
+ graphStorePath: config.graphPolicy.graphStorePath ?? "tmp/graphflow-graph.json",
215
+ enrichmentBackend: resolveEnrichmentBackend(config.graphPolicy.semanticEnrichment),
216
+ enrichmentProvider: config.graphPolicy.semanticEnrichment?.provider ?? "",
217
+ enrichmentModel: config.graphPolicy.semanticEnrichment?.model ?? "",
218
+ ...(() => {
219
+ const enrichPolicy = config.graphPolicy.semanticEnrichment;
220
+ const enrichProvider = enrichPolicy?.provider ?? config.tiers.economy.provider;
221
+ const rawEnrichPolicy = rawConfig?.graphPolicy?.semanticEnrichment ?? {};
222
+ const rawEnrichProvider = rawConfig?.providers?.[enrichProvider] ?? {};
223
+ const apiKey = (0, secrets_1.formatApiKeyForSettings)(rawEnrichPolicy.apiKey ?? rawEnrichProvider.apiKey);
224
+ const baseUrl = rawEnrichPolicy.baseUrl ?? rawEnrichProvider.baseUrl;
225
+ return {
226
+ ...(apiKey ? { enrichmentApiKey: apiKey } : {}),
227
+ ...(typeof baseUrl === "string" && baseUrl.trim() ? { enrichmentBaseUrl: baseUrl.trim() } : {}),
228
+ };
229
+ })(),
230
+ openbmbMode: (openbmbConfig.mode ?? "embedded"),
231
+ openbmbEngine: (openbmbConfig.engine ?? "command"),
232
+ openbmbModel: config.learningPolicy.skillEvolution?.model ??
233
+ (provider === "openbmb" ? config.tiers.economy.model ?? config.tiers.smart.model ?? "" : ""),
234
+ ...(rawOpenBmbConfig.baseUrl || openbmbConfig.baseUrl
235
+ ? { openbmbBaseUrl: rawOpenBmbConfig.baseUrl ?? openbmbConfig.baseUrl }
236
+ : {}),
237
+ ...(rawOpenBmbConfig.modelPath || openbmbConfig.modelPath
238
+ ? { openbmbModelPath: rawOpenBmbConfig.modelPath ?? openbmbConfig.modelPath }
239
+ : {}),
240
+ ...(rawOpenBmbConfig.commandPath || openbmbConfig.commandPath
241
+ ? { openbmbCommandPath: rawOpenBmbConfig.commandPath ?? openbmbConfig.commandPath }
242
+ : {}),
243
+ openbmbAutoDownload,
244
+ ...(typeof openbmbModelUrl === "string" && openbmbModelUrl.trim().length > 0
245
+ ? { openbmbModelUrl }
246
+ : {}),
247
+ ...(typeof openbmbModelSha256 === "string" && openbmbModelSha256.trim().length > 0
248
+ ? { openbmbModelSha256 }
249
+ : {}),
250
+ };
251
+ }
252
+ function saveGraphFlowSettings(settings, configPath = "graphflow.config.json") {
253
+ const actualPath = (0, resolve_1.resolveConfigPath)(configPath);
254
+ const current = (0, resolve_1.resolveConfig)(actualPath);
255
+ const providerConfig = {
256
+ ...(settings.apiKeyEnvVar?.trim() ? { apiKey: (0, secrets_1.formatApiKeyForConfig)(settings.apiKeyEnvVar) } : {}),
257
+ ...(settings.baseUrl ? { baseUrl: settings.baseUrl } : {}),
258
+ };
259
+ const openbmbProviderConfig = {
260
+ ...(settings.openbmbBaseUrl ? { baseUrl: settings.openbmbBaseUrl } : {}),
261
+ ...(settings.openbmbModelPath ? { modelPath: settings.openbmbModelPath } : {}),
262
+ ...(settings.openbmbCommandPath ? { commandPath: settings.openbmbCommandPath } : {}),
263
+ ...(settings.openbmbModelUrl ? { modelUrl: settings.openbmbModelUrl } : {}),
264
+ ...(settings.openbmbModelSha256 ? { modelSha256: settings.openbmbModelSha256 } : {}),
265
+ mode: settings.openbmbMode,
266
+ engine: settings.openbmbEngine,
267
+ autoDownloadModel: settings.openbmbAutoDownload,
268
+ };
269
+ const nextSmartModel = settings.provider === "openbmb" ? settings.openbmbModel : settings.smartModel;
270
+ const nextEconomyModel = settings.provider === "openbmb" ? settings.openbmbModel : settings.economyModel;
271
+ const updated = (0, loader_1.validateConfig)({
272
+ ...current,
273
+ providers: {
274
+ ...current.providers,
275
+ [settings.provider]: providerConfig,
276
+ openbmb: {
277
+ ...(current.providers.openbmb ?? {}),
278
+ ...openbmbProviderConfig,
279
+ },
280
+ },
281
+ tiers: {
282
+ smart: {
283
+ provider: settings.provider,
284
+ ...(nextSmartModel?.trim()
285
+ ? { model: nextSmartModel.trim() }
286
+ : current.tiers.smart.model
287
+ ? { model: current.tiers.smart.model }
288
+ : {}),
289
+ },
290
+ economy: {
291
+ provider: settings.provider,
292
+ ...(nextEconomyModel?.trim()
293
+ ? { model: nextEconomyModel.trim() }
294
+ : current.tiers.economy.model
295
+ ? { model: current.tiers.economy.model }
296
+ : {}),
297
+ },
298
+ },
299
+ graphPolicy: {
300
+ ...current.graphPolicy,
301
+ enableNearLosslessMode: settings.enableNearLosslessMode,
302
+ autoIndexOnPreview: settings.autoIndexOnPreview,
303
+ autoIndexOnRun: settings.autoIndexOnRun,
304
+ autoIndexOnSave: settings.autoIndexOnSave,
305
+ transport: settings.transport,
306
+ graphStorePath: settings.graphStorePath,
307
+ maxContextTokens: Math.max(1, Math.floor(settings.maxContextTokens)),
308
+ layerQuota: {
309
+ l1: Math.max(0, Math.floor(settings.layerQuota.l1)),
310
+ l2: Math.max(0, Math.floor(settings.layerQuota.l2)),
311
+ l3: Math.max(0, Math.floor(settings.layerQuota.l3)),
312
+ },
313
+ semanticEnrichment: {
314
+ ...(current.graphPolicy.semanticEnrichment ?? {}),
315
+ backend: settings.enrichmentBackend,
316
+ ...(settings.enrichmentBackend === "local"
317
+ ? { provider: "openbmb" }
318
+ : settings.enrichmentProvider?.trim()
319
+ ? { provider: settings.enrichmentProvider.trim() }
320
+ : settings.enrichmentBackend === "inherit"
321
+ ? {}
322
+ : current.graphPolicy.semanticEnrichment?.provider
323
+ ? { provider: current.graphPolicy.semanticEnrichment.provider }
324
+ : {}),
325
+ ...(settings.enrichmentModel?.trim()
326
+ ? { model: settings.enrichmentModel.trim() }
327
+ : current.graphPolicy.semanticEnrichment?.model
328
+ ? { model: current.graphPolicy.semanticEnrichment.model }
329
+ : {}),
330
+ ...(settings.enrichmentBackend !== "local" && settings.enrichmentApiKey?.trim()
331
+ ? { apiKey: (0, secrets_1.formatApiKeyForConfig)(settings.enrichmentApiKey) }
332
+ : {}),
333
+ ...(settings.enrichmentBackend !== "local" && settings.enrichmentBaseUrl?.trim()
334
+ ? { baseUrl: settings.enrichmentBaseUrl.trim() }
335
+ : {}),
336
+ },
337
+ },
338
+ learningPolicy: {
339
+ ...current.learningPolicy,
340
+ skillEvolution: {
341
+ ...(current.learningPolicy.skillEvolution ?? {}),
342
+ ...(settings.openbmbModel?.trim() ? { model: settings.openbmbModel.trim() } : {}),
343
+ },
344
+ },
345
+ });
346
+ if (settings.openbmbModelUrl) {
347
+ process.env.GRAPHFLOW_MINICPM_MODEL_URL = settings.openbmbModelUrl;
348
+ }
349
+ if (settings.openbmbModelSha256) {
350
+ process.env.GRAPHFLOW_MINICPM_MODEL_SHA256 = settings.openbmbModelSha256;
351
+ }
352
+ process.env.GRAPHFLOW_OPENBMB_AUTO_DOWNLOAD = settings.openbmbAutoDownload ? "1" : "0";
353
+ const dir = (0, node_path_1.dirname)(actualPath);
354
+ if (dir && dir !== ".") {
355
+ (0, node_fs_1.mkdirSync)(dir, { recursive: true });
356
+ }
357
+ (0, node_fs_1.writeFileSync)(actualPath, `${JSON.stringify(updated, null, 2)}\n`, "utf8");
358
+ return getGraphFlowSettings(actualPath);
359
+ }
360
+ async function previewContext(query, configPath) {
361
+ const config = (0, resolve_1.resolveConfig)(configPath);
362
+ applyOpenBmbRuntimeEnv(config);
363
+ const graphClient = (0, client_factory_1.createGraphClient)(config);
364
+ if (config.graphPolicy.autoIndexOnPreview) {
365
+ const indexOptions = config.graphPolicy.includeExtensions
366
+ ? { includeExtensions: config.graphPolicy.includeExtensions }
367
+ : undefined;
368
+ await (0, file_indexer_1.indexWorkspaceFiles)(graphClient, config.graphPolicy.workspaceRoot ?? process.cwd(), {
369
+ ...indexOptions,
370
+ });
371
+ }
372
+ const packageOptions = {
373
+ ...(config.graphPolicy.layerQuota ? { layerQuota: config.graphPolicy.layerQuota } : {}),
374
+ ...buildEmbeddingOptions(config),
375
+ };
376
+ const pkg = await (0, context_slicer_1.buildLayeredContextPackage)(graphClient, query, config.graphPolicy.maxContextTokens, packageOptions);
377
+ const refill = (0, context_slicer_1.createContextRefillManager)(graphClient, config.graphPolicy.maxContextTokens, packageOptions);
378
+ await refill.initialPackage(query);
379
+ const refillPreview = await refill.refill([query]);
380
+ const rawTokenEstimate = estimateRawContextTokens(await resolveGraphStoreAfterIndex(config, graphClient), query, pkg.tokenEstimate);
381
+ return {
382
+ query,
383
+ summaryCount: pkg.summaryChannel.length,
384
+ anchorCount: pkg.anchorChannel.length,
385
+ tokenEstimate: pkg.tokenEstimate,
386
+ truncated: pkg.truncated,
387
+ anchorsByLayer: {
388
+ l1: pkg.anchorChannel.filter((item) => item.layer === "L1").length,
389
+ l2: pkg.anchorChannel.filter((item) => item.layer === "L2").length,
390
+ l3: pkg.anchorChannel.filter((item) => item.layer === "L3").length,
391
+ },
392
+ refillPreview,
393
+ summary: pkg.summaryChannel,
394
+ anchors: pkg.anchorChannel,
395
+ tokenBudget: {
396
+ maxContextTokens: config.graphPolicy.maxContextTokens,
397
+ estimatedRawTokens: rawTokenEstimate,
398
+ compressedTokens: pkg.tokenEstimate,
399
+ estimatedSavingsPercent: calculateSavingsPercent(rawTokenEstimate, pkg.tokenEstimate),
400
+ budgetUsedPercent: calculateBudgetUsedPercent(pkg.tokenEstimate, config.graphPolicy.maxContextTokens),
401
+ },
402
+ };
403
+ }
404
+ async function indexGraph(rootDir, configPath) {
405
+ const config = (0, resolve_1.resolveConfig)(configPath);
406
+ applyOpenBmbRuntimeEnv(config);
407
+ const graphClient = (0, client_factory_1.createGraphClient)(config);
408
+ const targetDir = rootDir || config.graphPolicy.workspaceRoot || process.cwd();
409
+ const indexOptions = config.graphPolicy.includeExtensions
410
+ ? { includeExtensions: config.graphPolicy.includeExtensions }
411
+ : undefined;
412
+ const indexed = await (0, file_indexer_1.indexWorkspaceFiles)(graphClient, targetDir, {
413
+ ...indexOptions,
414
+ });
415
+ await maybeRunSemanticEnrichment(config, graphClient);
416
+ return indexed;
417
+ }
418
+ async function rebuildGraph(rootDir, configPath) {
419
+ const config = (0, resolve_1.resolveConfig)(configPath);
420
+ applyOpenBmbRuntimeEnv(config);
421
+ const graphClient = (0, client_factory_1.createGraphClient)(config);
422
+ const targetDir = rootDir || config.graphPolicy.workspaceRoot || process.cwd();
423
+ const storePath = (0, paths_1.resolveGraphStorePath)(config);
424
+ (0, file_indexer_1.clearGraphIndexArtifacts)(targetDir, storePath);
425
+ const indexOptions = config.graphPolicy.includeExtensions
426
+ ? { includeExtensions: config.graphPolicy.includeExtensions }
427
+ : undefined;
428
+ const indexed = await (0, file_indexer_1.indexWorkspaceFiles)(graphClient, targetDir, {
429
+ ...indexOptions,
430
+ forceReindex: true,
431
+ });
432
+ await maybeRunSemanticEnrichment(config, graphClient);
433
+ return {
434
+ ...indexed,
435
+ cleared: true,
436
+ storePath,
437
+ };
438
+ }
439
+ async function maybeRunSemanticEnrichment(config, graphClient) {
440
+ const enrichPolicy = config.graphPolicy.semanticEnrichment;
441
+ if (!enrichPolicy?.enabled || !enrichPolicy.autoRunOnIndex || enrichPolicy.mode === "off") {
442
+ return;
443
+ }
444
+ const selection = (0, model_router_1.resolveModelForRole)("enricher");
445
+ const health = (0, provider_health_1.buildProviderHealthMap)(config);
446
+ if (!health[selection.provider]) {
447
+ logger_1.logger.warn(`Skipping semantic enrichment: ${selection.provider} provider is not configured or healthy`);
448
+ return;
449
+ }
450
+ applyEnrichmentProviderEnv(config);
451
+ try {
452
+ await (0, semantic_enricher_1.enrichGraphSemanticsSilent)(graphClient, {
453
+ ...(enrichPolicy.batchSize !== undefined ? { batchSize: enrichPolicy.batchSize } : {}),
454
+ ...(enrichPolicy.sleepMs !== undefined ? { sleepMs: enrichPolicy.sleepMs } : {}),
455
+ ...(enrichPolicy.model ? { model: enrichPolicy.model } : {}),
456
+ ...(enrichPolicy.timeoutMs !== undefined ? { timeoutMs: enrichPolicy.timeoutMs } : {}),
457
+ });
458
+ }
459
+ catch (error) {
460
+ logger_1.logger.warn({ error }, "Semantic enrichment skipped after provider failure");
461
+ }
462
+ }
463
+ async function enrichSemanticsSilent(configPath, options) {
464
+ const config = (0, resolve_1.resolveConfig)(configPath);
465
+ applyOpenBmbRuntimeEnv(config);
466
+ applyEnrichmentProviderEnv(config);
467
+ const graphClient = (0, client_factory_1.createGraphClient)(config);
468
+ const enrichPolicy = config.graphPolicy.semanticEnrichment;
469
+ const enricherOptions = {};
470
+ const batchSize = options?.batchSize ?? enrichPolicy?.batchSize;
471
+ if (batchSize !== undefined) {
472
+ enricherOptions.batchSize = batchSize;
473
+ }
474
+ const sleepMs = options?.sleepMs ?? enrichPolicy?.sleepMs;
475
+ if (sleepMs !== undefined) {
476
+ enricherOptions.sleepMs = sleepMs;
477
+ }
478
+ const timeoutMs = options?.timeoutMs ?? enrichPolicy?.timeoutMs;
479
+ if (timeoutMs !== undefined) {
480
+ enricherOptions.timeoutMs = timeoutMs;
481
+ }
482
+ if (enrichPolicy?.model) {
483
+ enricherOptions.model = enrichPolicy.model;
484
+ }
485
+ return (0, semantic_enricher_1.enrichGraphSemanticsSilent)(graphClient, enricherOptions);
486
+ }
487
+ async function downloadOpenBmbModel(configPath, options) {
488
+ const config = (0, resolve_1.resolveConfig)(configPath);
489
+ applyOpenBmbRuntimeEnv(config);
490
+ const model = options?.model ?? "minicpm5-1b";
491
+ const defaultUrl = process.env.GRAPHFLOW_MINICPM_MODEL_URL;
492
+ const url = options?.url ?? defaultUrl;
493
+ const configuredPath = options?.targetPath ?? config.providers.openbmb?.modelPath;
494
+ const fallbackPath = (0, node_path_1.join)((0, node_os_1.tmpdir)(), "graphflow-models", `${model}.gguf`);
495
+ const targetPath = configuredPath ?? fallbackPath;
496
+ const force = options?.force ?? false;
497
+ const expectedSha = options?.sha256 ?? process.env.GRAPHFLOW_MINICPM_MODEL_SHA256;
498
+ const partialPath = `${targetPath}.part`;
499
+ const lockPath = `${targetPath}.lock`;
500
+ return (0, file_lock_1.withFileLock)(lockPath, async () => {
501
+ if ((0, node_fs_1.existsSync)(targetPath) && !force) {
502
+ const bytes = getFileSize(targetPath);
503
+ const verified = expectedSha ? (await sha256File(targetPath)) === expectedSha.toLowerCase() : true;
504
+ options?.onProgress?.({
505
+ model,
506
+ targetPath,
507
+ downloadedBytes: bytes,
508
+ totalBytes: bytes,
509
+ resumed: false,
510
+ percent: 100,
511
+ stage: "skipped",
512
+ });
513
+ return {
514
+ model,
515
+ targetPath,
516
+ bytes,
517
+ skipped: true,
518
+ verified,
519
+ };
520
+ }
521
+ if (!url) {
522
+ throw new Error("Model download URL is required. Set GRAPHFLOW_MINICPM_MODEL_URL or pass --url.");
523
+ }
524
+ (0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(targetPath), { recursive: true });
525
+ let partialSize = 0;
526
+ if ((0, node_fs_1.existsSync)(partialPath) && !force) {
527
+ try {
528
+ partialSize = (0, node_fs_1.statSync)(partialPath).size;
529
+ }
530
+ catch {
531
+ partialSize = 0;
532
+ }
533
+ }
534
+ if (force) {
535
+ (0, node_fs_1.rmSync)(partialPath, { force: true });
536
+ partialSize = 0;
537
+ }
538
+ options?.onProgress?.({
539
+ model,
540
+ targetPath,
541
+ downloadedBytes: partialSize,
542
+ resumed: partialSize > 0,
543
+ stage: "starting",
544
+ });
545
+ const fetchInit = {};
546
+ if (partialSize > 0) {
547
+ fetchInit.headers = { range: `bytes=${partialSize}-` };
548
+ }
549
+ const response = await fetch(url, fetchInit);
550
+ if (!response.ok) {
551
+ throw new Error(`Model download failed: ${response.status} ${response.statusText}`);
552
+ }
553
+ const acceptsRange = response.status === 206;
554
+ if (!acceptsRange && partialSize > 0) {
555
+ (0, node_fs_1.rmSync)(partialPath, { force: true });
556
+ partialSize = 0;
557
+ }
558
+ const contentLength = Number(response.headers.get("content-length") ?? "0");
559
+ const totalBytes = Number.isFinite(contentLength) && contentLength > 0
560
+ ? partialSize + contentLength
561
+ : undefined;
562
+ const stream = response.body;
563
+ if (!stream) {
564
+ throw new Error("Model download failed: empty response body");
565
+ }
566
+ const reader = stream.getReader();
567
+ const resumed = partialSize > 0 && acceptsRange;
568
+ const writer = (0, node_fs_1.createWriteStream)(partialPath, { flags: resumed ? "a" : "w" });
569
+ let downloadedBytes = partialSize;
570
+ let lastReportedBytes = -1;
571
+ const emitProgress = (stage) => {
572
+ if (downloadedBytes === lastReportedBytes && stage === "downloading") {
573
+ return;
574
+ }
575
+ lastReportedBytes = downloadedBytes;
576
+ const percent = totalBytes && totalBytes > 0
577
+ ? Math.min(100, Number(((downloadedBytes / totalBytes) * 100).toFixed(1)))
578
+ : undefined;
579
+ options?.onProgress?.({
580
+ model,
581
+ targetPath,
582
+ downloadedBytes,
583
+ ...(totalBytes ? { totalBytes } : {}),
584
+ resumed,
585
+ ...(percent !== undefined ? { percent } : {}),
586
+ stage,
587
+ });
588
+ };
589
+ emitProgress("downloading");
590
+ while (true) {
591
+ const { done, value } = await reader.read();
592
+ if (done) {
593
+ break;
594
+ }
595
+ if (value) {
596
+ const chunk = Buffer.from(value);
597
+ await new Promise((resolve, reject) => {
598
+ writer.write(chunk, (error) => {
599
+ if (error) {
600
+ reject(error);
601
+ return;
602
+ }
603
+ resolve();
604
+ });
605
+ });
606
+ downloadedBytes += chunk.length;
607
+ emitProgress("downloading");
608
+ }
609
+ }
610
+ await new Promise((resolve, reject) => {
611
+ writer.end((error) => {
612
+ if (error) {
613
+ reject(error);
614
+ return;
615
+ }
616
+ resolve();
617
+ });
618
+ });
619
+ (0, node_fs_1.renameSync)(partialPath, targetPath);
620
+ if (expectedSha) {
621
+ options?.onProgress?.({
622
+ model,
623
+ targetPath,
624
+ downloadedBytes,
625
+ ...(totalBytes ? { totalBytes } : {}),
626
+ resumed,
627
+ percent: 100,
628
+ stage: "verifying",
629
+ });
630
+ const actual = await sha256File(targetPath);
631
+ if (actual !== expectedSha.toLowerCase()) {
632
+ (0, node_fs_1.rmSync)(targetPath, { force: true });
633
+ throw new Error(`Model sha256 mismatch. expected=${expectedSha.toLowerCase()} actual=${actual}`);
634
+ }
635
+ }
636
+ const finalBytes = getFileSize(targetPath);
637
+ options?.onProgress?.({
638
+ model,
639
+ targetPath,
640
+ downloadedBytes: finalBytes,
641
+ totalBytes: finalBytes,
642
+ resumed,
643
+ percent: 100,
644
+ stage: "completed",
645
+ });
646
+ return {
647
+ model,
648
+ targetPath,
649
+ bytes: finalBytes,
650
+ skipped: false,
651
+ verified: Boolean(expectedSha),
652
+ ...(resumed ? { resumed: true } : {}),
653
+ };
654
+ });
655
+ }
656
+ async function inspectGraph(configPath, options) {
657
+ const config = (0, resolve_1.resolveConfig)(configPath);
658
+ const nodeLimit = Math.max(1, options?.nodeLimit ?? 24);
659
+ const edgeLimit = Math.max(1, options?.edgeLimit ?? 36);
660
+ const emptyTypeCount = {
661
+ File: 0,
662
+ Symbol: 0,
663
+ Module: 0,
664
+ TaskRun: 0,
665
+ Decision: 0,
666
+ Skill: 0,
667
+ };
668
+ if (config.graphPolicy.transport === "mcp-http") {
669
+ return {
670
+ transport: config.graphPolicy.transport,
671
+ storePath: (0, paths_1.resolveGraphStorePath)(config),
672
+ nodeCount: 0,
673
+ edgeCount: 0,
674
+ nodeTypeCount: emptyTypeCount,
675
+ topRelations: [],
676
+ sampleNodes: [],
677
+ sampleEdges: [],
678
+ };
679
+ }
680
+ let store = loadGraphStore(config);
681
+ if (store.nodes.length === 0) {
682
+ const graphClient = (0, client_factory_1.createGraphClient)(config);
683
+ const indexOptions = config.graphPolicy.includeExtensions
684
+ ? { includeExtensions: config.graphPolicy.includeExtensions }
685
+ : undefined;
686
+ await (0, file_indexer_1.indexWorkspaceFiles)(graphClient, config.graphPolicy.workspaceRoot ?? process.cwd(), {
687
+ ...indexOptions,
688
+ });
689
+ store = await resolveGraphStoreAfterIndex(config, graphClient);
690
+ }
691
+ const relationCounts = new Map();
692
+ for (const edge of store.edges) {
693
+ relationCounts.set(edge.relation, (relationCounts.get(edge.relation) ?? 0) + 1);
694
+ }
695
+ const nodeTypeCount = { ...emptyTypeCount };
696
+ for (const node of store.nodes) {
697
+ nodeTypeCount[node.type] += 1;
698
+ }
699
+ return {
700
+ transport: config.graphPolicy.transport,
701
+ storePath: (0, paths_1.resolveGraphStorePath)(config),
702
+ nodeCount: store.nodes.length,
703
+ edgeCount: store.edges.length,
704
+ nodeTypeCount,
705
+ topRelations: Array.from(relationCounts.entries())
706
+ .map(([relation, count]) => ({ relation, count }))
707
+ .sort((a, b) => b.count - a.count || a.relation.localeCompare(b.relation))
708
+ .slice(0, 8),
709
+ ...(() => {
710
+ const isMetaFile = (id) => {
711
+ const lower = id.toLowerCase();
712
+ return lower.includes(".md") || lower.includes(".json") || lower.includes(".yml") || lower.includes(".yaml") || lower.includes(".github") || lower.includes(".claude") || lower.includes(".codex");
713
+ };
714
+ const adj = new Map();
715
+ for (const e of store.edges) {
716
+ if (!adj.has(e.from))
717
+ adj.set(e.from, []);
718
+ if (!adj.has(e.to))
719
+ adj.set(e.to, []);
720
+ adj.get(e.from).push(e.to);
721
+ adj.get(e.to).push(e.from);
722
+ }
723
+ const nodeMap = new Map(store.nodes.map(n => [n.id, n]));
724
+ const degree = (id) => adj.get(id)?.length || 0;
725
+ const sortedCandidates = store.nodes
726
+ .filter(n => n.type === "File" && !isMetaFile(n.id))
727
+ .sort((a, b) => degree(b.id) - degree(a.id));
728
+ if (sortedCandidates.length === 0) {
729
+ return { sampleNodes: [], sampleEdges: [] };
730
+ }
731
+ const visited = new Set();
732
+ const selected = [];
733
+ let candidateIndex = 0;
734
+ while (selected.length < nodeLimit && candidateIndex < sortedCandidates.length) {
735
+ let root = sortedCandidates[candidateIndex++];
736
+ while (root && visited.has(root.id) && candidateIndex < sortedCandidates.length) {
737
+ root = sortedCandidates[candidateIndex++];
738
+ }
739
+ if (!root || visited.has(root.id))
740
+ break;
741
+ const queue = [root.id];
742
+ while (queue.length > 0 && selected.length < nodeLimit) {
743
+ const id = queue.shift();
744
+ if (visited.has(id))
745
+ continue;
746
+ visited.add(id);
747
+ const node = nodeMap.get(id);
748
+ if (node) {
749
+ selected.push(node);
750
+ const neighbors = adj.get(id) || [];
751
+ queue.push(...neighbors);
752
+ }
753
+ }
754
+ }
755
+ const sampleNodeIds = new Set(selected.map(n => n.id));
756
+ return {
757
+ sampleNodes: selected.map(node => ({
758
+ id: node.id,
759
+ type: node.type,
760
+ contentPreview: compactPreview(node.content, 96),
761
+ })),
762
+ sampleEdges: store.edges
763
+ .filter(edge => sampleNodeIds.has(edge.from) && sampleNodeIds.has(edge.to))
764
+ .slice(0, edgeLimit)
765
+ .map(edge => ({
766
+ from: edge.from,
767
+ relation: edge.relation,
768
+ to: edge.to,
769
+ }))
770
+ };
771
+ })(),
772
+ };
773
+ }
774
+ async function getSkillInsights(configPath, limit = 12) {
775
+ const config = (0, resolve_1.resolveConfig)(configPath);
776
+ const boundedLimit = Math.max(1, limit);
777
+ if (config.graphPolicy.transport === "mcp-http") {
778
+ return {
779
+ source: "unavailable",
780
+ transport: config.graphPolicy.transport,
781
+ storePath: (0, paths_1.resolveGraphStorePath)(config),
782
+ skills: [],
783
+ };
784
+ }
785
+ let store = loadGraphStore(config);
786
+ if (store.nodes.length === 0) {
787
+ const graphClient = (0, client_factory_1.createGraphClient)(config);
788
+ const indexOptions = config.graphPolicy.includeExtensions
789
+ ? { includeExtensions: config.graphPolicy.includeExtensions }
790
+ : undefined;
791
+ await (0, file_indexer_1.indexWorkspaceFiles)(graphClient, config.graphPolicy.workspaceRoot ?? process.cwd(), {
792
+ ...indexOptions,
793
+ });
794
+ store = await resolveGraphStoreAfterIndex(config, graphClient);
795
+ }
796
+ const skills = store.nodes
797
+ .filter((node) => node.type === "Skill")
798
+ .map((node) => parseSkillInsight(node))
799
+ .filter((state) => Boolean(state))
800
+ .sort((a, b) => b.score - a.score || b.uses - a.uses || b.updatedAt - a.updatedAt)
801
+ .slice(0, boundedLimit);
802
+ return {
803
+ source: "graph-store",
804
+ transport: config.graphPolicy.transport,
805
+ storePath: (0, paths_1.resolveGraphStorePath)(config),
806
+ skills,
807
+ };
808
+ }
809
+ async function runTaskResult(task, configPath) {
810
+ const config = (0, resolve_1.resolveConfig)(configPath);
811
+ applyOpenBmbRuntimeEnv(config);
812
+ const eventsPath = (0, paths_1.resolveLearningPath)(config, "eventsPath");
813
+ try {
814
+ const graphClient = (0, client_factory_1.createGraphClient)(config);
815
+ if (config.graphPolicy.autoIndexOnRun) {
816
+ const indexOptions = config.graphPolicy.includeExtensions
817
+ ? { includeExtensions: config.graphPolicy.includeExtensions }
818
+ : undefined;
819
+ await (0, file_indexer_1.indexWorkspaceFiles)(graphClient, config.graphPolicy.workspaceRoot ?? process.cwd(), {
820
+ ...indexOptions,
821
+ });
822
+ }
823
+ const embeddingOptions = buildEmbeddingOptions(config);
824
+ const orchestrateOptions = {
825
+ graphClient,
826
+ enableAutoGraphSync: config.graphPolicy.enableAutoBuild,
827
+ maxContextTokens: config.graphPolicy.maxContextTokens,
828
+ enableEpisodicMemory: config.learningPolicy.enableFlywheel,
829
+ enableLlmAgents: config.tiers.smart.provider === "openbmb" || config.tiers.economy.provider === "openbmb",
830
+ enableLlmTriage: config.tiers.smart.provider === "openbmb" || config.tiers.economy.provider === "openbmb",
831
+ ...(configPath ? { configPath } : {}),
832
+ ...embeddingOptions,
833
+ ...(config.skillPolicy?.enableSkillFlywheel
834
+ ? {
835
+ enableSkillFlywheel: true,
836
+ ...(config.skillPolicy.maxSkillHints !== undefined
837
+ ? { skillHintsLimit: config.skillPolicy.maxSkillHints }
838
+ : {}),
839
+ }
840
+ : { enableSkillFlywheel: false }),
841
+ providerHealth: (0, provider_health_1.buildProviderHealthMap)(config),
842
+ ...(config.routingPolicy?.enableDynamicRouting
843
+ ? { providerFallbackChain: (0, provider_health_1.buildFallbackChain)(config) }
844
+ : {}),
845
+ ...(config.graphPolicy.enableNearLosslessMode !== undefined
846
+ ? { enableNearLosslessMode: config.graphPolicy.enableNearLosslessMode }
847
+ : {}),
848
+ ...(config.graphPolicy.layerQuota ? { layerQuota: config.graphPolicy.layerQuota } : {}),
849
+ };
850
+ const result = await (0, orchestrator_1.orchestrate)({ task }, orchestrateOptions);
851
+ (0, learning_events_1.appendFeedbackEvent)(eventsPath, {
852
+ query: task,
853
+ passed: result.status === "COMPLETED",
854
+ tokenCost: extractTokenCost(result.feedback),
855
+ retries: Math.max(0, result.attempts - 1),
856
+ });
857
+ return {
858
+ status: result.status,
859
+ attempts: result.attempts,
860
+ feedback: result.feedback,
861
+ };
862
+ }
863
+ catch (error) {
864
+ (0, learning_events_1.appendFeedbackEvent)(eventsPath, {
865
+ query: task,
866
+ passed: false,
867
+ tokenCost: 0,
868
+ retries: 0,
869
+ });
870
+ throw error;
871
+ }
872
+ }
873
+ async function runTask(task, configPath) {
874
+ const result = await runTaskResult(task, configPath);
875
+ return `status=${result.status}; attempts=${result.attempts}; feedback=${result.feedback}`;
876
+ }
877
+ function diagnoseRoutingResult(configPath) {
878
+ const config = (0, resolve_1.resolveConfig)(configPath);
879
+ const health = (0, provider_health_1.buildProviderHealthMap)(config);
880
+ const chain = (0, provider_health_1.buildFallbackChain)(config);
881
+ const resolve = (role) => {
882
+ if (!config.routingPolicy?.enableDynamicRouting) {
883
+ return (0, model_router_1.resolveModelForRole)(role);
884
+ }
885
+ return (0, model_router_1.resolveModelWithFallback)(role, health, chain);
886
+ };
887
+ const planner = resolve("planner");
888
+ const worker = resolve("worker");
889
+ const validator = resolve("validator");
890
+ return {
891
+ dynamicRouting: config.routingPolicy?.enableDynamicRouting ?? false,
892
+ health,
893
+ priority: chain,
894
+ planner: {
895
+ provider: planner.provider,
896
+ model: planner.model,
897
+ fallbackApplied: planner.fallbackApplied,
898
+ },
899
+ worker: {
900
+ provider: worker.provider,
901
+ model: worker.model,
902
+ fallbackApplied: worker.fallbackApplied,
903
+ },
904
+ validator: {
905
+ provider: validator.provider,
906
+ model: validator.model,
907
+ fallbackApplied: validator.fallbackApplied,
908
+ },
909
+ };
910
+ }
911
+ function diagnoseRouting(configPath) {
912
+ const result = diagnoseRoutingResult(configPath);
913
+ return [
914
+ `dynamicRouting=${result.dynamicRouting ? "on" : "off"}`,
915
+ `health=openai:${result.health.openai},anthropic:${result.health.anthropic},bailian:${result.health.bailian},doubao:${result.health.doubao},openbmb:${result.health.openbmb}`,
916
+ `priority=${result.priority.join(",")}`,
917
+ `planner=${result.planner.provider}/${result.planner.model}${result.planner.fallbackApplied ? ":fallback" : ""}`,
918
+ `worker=${result.worker.provider}/${result.worker.model}${result.worker.fallbackApplied ? ":fallback" : ""}`,
919
+ `validator=${result.validator.provider}/${result.validator.model}${result.validator.fallbackApplied ? ":fallback" : ""}`,
920
+ ].join("; ");
921
+ }
922
+ async function getSettingsPanelStatus(configPath) {
923
+ const config = (0, resolve_1.resolveConfig)(configPath);
924
+ const snapshot = await inspectGraph(configPath, { nodeLimit: 1, edgeLimit: 1 });
925
+ const storePath = (0, paths_1.resolveGraphStorePath)(config);
926
+ let graphLastModified = null;
927
+ if ((0, node_fs_1.existsSync)(storePath)) {
928
+ graphLastModified = new Date((0, node_fs_1.statSync)(storePath).mtimeMs).toISOString();
929
+ }
930
+ return {
931
+ graphNodeCount: snapshot.nodeCount,
932
+ graphEdgeCount: snapshot.edgeCount,
933
+ graphLastModified,
934
+ diagnoseSummary: diagnoseRouting(configPath),
935
+ overlayKeys: (0, merge_1.listConfigOverlayKeys)(),
936
+ baseConfigPath: (0, node_fs_1.existsSync)("graphflow.config.json") ? "graphflow.config.json" : "(未创建)",
937
+ };
938
+ }
939
+ function runLearningNightlyResult(configPath) {
940
+ const config = (0, resolve_1.resolveConfig)(configPath);
941
+ const summary = (0, nightly_trainer_1.runNightlyLearning)(config);
942
+ return {
943
+ events: summary.totalEvents,
944
+ passRate: summary.passRate,
945
+ avgTokens: summary.averageTokenCost,
946
+ canary: summary.canaryAllowed ? "allow" : "block",
947
+ reason: summary.canaryReason,
948
+ dataset: summary.exportedPath,
949
+ };
950
+ }
951
+ function runLearningNightly(configPath) {
952
+ const result = runLearningNightlyResult(configPath);
953
+ return [
954
+ `events=${result.events}`,
955
+ `passRate=${result.passRate.toFixed(3)}`,
956
+ `avgTokens=${result.avgTokens.toFixed(1)}`,
957
+ `canary=${result.canary}`,
958
+ `reason=${result.reason}`,
959
+ `dataset=${result.dataset}`,
960
+ ].join("; ");
961
+ }
962
+ function planAndBrainstormResult(task) {
963
+ const mode = (0, triage_1.triageTask)(task);
964
+ const ideas = (0, brainstormer_1.brainstormTask)(task);
965
+ const nodes = (0, planner_1.planTasks)(task).map((node) => ({
966
+ id: node.id,
967
+ description: node.description,
968
+ dependencies: node.dependencies,
969
+ }));
970
+ return {
971
+ mode,
972
+ ideas,
973
+ nodes,
974
+ };
975
+ }
976
+ function planAndBrainstorm(task) {
977
+ const result = planAndBrainstormResult(task);
978
+ return [
979
+ `mode=${result.mode}`,
980
+ `ideas=${result.ideas.join(" | ")}`,
981
+ `plan=${result.nodes
982
+ .map((node) => `${node.id}[${node.dependencies.join(",") || "-"}]:${node.description}`)
983
+ .join(" | ")}`,
984
+ ].join("; ");
985
+ }
986
+ var agent_mcp_installer_1 = require("../../integrations/agent-mcp-installer");
987
+ Object.defineProperty(exports, "buildMcpServerNode", { enumerable: true, get: function () { return agent_mcp_installer_1.buildMcpServerNode; } });
988
+ Object.defineProperty(exports, "detectInstalledAgents", { enumerable: true, get: function () { return agent_mcp_installer_1.detectInstalledAgents; } });
989
+ Object.defineProperty(exports, "formatModelConfigGuide", { enumerable: true, get: function () { return agent_mcp_installer_1.formatModelConfigGuide; } });
990
+ Object.defineProperty(exports, "installMcpToDetectedAgents", { enumerable: true, get: function () { return agent_mcp_installer_1.installMcpToDetectedAgents; } });
991
+ function extractTokenCost(feedback) {
992
+ const match = feedback.match(/tokens=(\d+)/);
993
+ if (match && match[1]) {
994
+ return Number(match[1]);
995
+ }
996
+ return Math.max(1, Math.ceil(feedback.length / 4));
997
+ }
998
+ function loadGraphStore(config) {
999
+ const transport = config.graphPolicy.transport;
1000
+ if (transport === "memory") {
1001
+ return { nodes: [], edges: [] };
1002
+ }
1003
+ if (transport === "sqlite") {
1004
+ const dbPath = (0, paths_1.resolveGraphStorePath)(config);
1005
+ try {
1006
+ const client = new sqlite_client_1.GraphifySqliteClient(dbPath);
1007
+ const snapshot = client.readSnapshot();
1008
+ client.close();
1009
+ return snapshot;
1010
+ }
1011
+ catch {
1012
+ const fallbackPath = dbPath.replace(/\.sqlite$/i, ".json");
1013
+ return readFileGraphStore(fallbackPath);
1014
+ }
1015
+ }
1016
+ return readFileGraphStore((0, paths_1.resolveGraphStorePath)(config));
1017
+ }
1018
+ async function resolveGraphStoreAfterIndex(config, graphClient) {
1019
+ if (config.graphPolicy.transport === "memory" && graphClient.readSnapshot) {
1020
+ return graphClient.readSnapshot();
1021
+ }
1022
+ return loadGraphStore(config);
1023
+ }
1024
+ function readFileGraphStore(storePath) {
1025
+ if (!storePath || !(0, node_fs_1.existsSync)(storePath)) {
1026
+ return { nodes: [], edges: [] };
1027
+ }
1028
+ try {
1029
+ const raw = (0, node_fs_1.readFileSync)(storePath, "utf8");
1030
+ if (!raw.trim()) {
1031
+ return { nodes: [], edges: [] };
1032
+ }
1033
+ const parsed = JSON.parse(raw);
1034
+ return {
1035
+ nodes: parsed.nodes ?? [],
1036
+ edges: parsed.edges ?? [],
1037
+ };
1038
+ }
1039
+ catch {
1040
+ return { nodes: [], edges: [] };
1041
+ }
1042
+ }
1043
+ function getFileSize(path) {
1044
+ try {
1045
+ return (0, node_fs_1.statSync)(path).size;
1046
+ }
1047
+ catch {
1048
+ return 0;
1049
+ }
1050
+ }
1051
+ async function sha256File(path) {
1052
+ const hash = (0, node_crypto_1.createHash)("sha256");
1053
+ const stream = (0, node_fs_1.createReadStream)(path);
1054
+ for await (const chunk of stream) {
1055
+ hash.update(chunk);
1056
+ }
1057
+ return hash.digest("hex");
1058
+ }
1059
+ function readRawConfig(configPath) {
1060
+ if (!(0, node_fs_1.existsSync)(configPath)) {
1061
+ return undefined;
1062
+ }
1063
+ try {
1064
+ return JSON.parse((0, node_fs_1.readFileSync)(configPath, "utf8"));
1065
+ }
1066
+ catch {
1067
+ return undefined;
1068
+ }
1069
+ }
1070
+ function estimateRawContextTokens(store, query, compressedTokens) {
1071
+ const matching = store.nodes.filter((node) => {
1072
+ const haystack = `${node.id} ${node.type} ${node.content}`.toLowerCase();
1073
+ const terms = query
1074
+ .toLowerCase()
1075
+ .split(/[^a-z0-9_]+/g)
1076
+ .filter((item) => item.length >= 2);
1077
+ return terms.length === 0 || terms.some((term) => haystack.includes(term));
1078
+ });
1079
+ const nodes = matching.length > 0 ? matching : store.nodes;
1080
+ const rawTokens = nodes.reduce((sum, node) => sum + estimateTokenCount(`${node.id}\n${node.type}\n${node.content}`), 0);
1081
+ return Math.max(compressedTokens, rawTokens, estimateTokenCount(query));
1082
+ }
1083
+ function calculateSavingsPercent(rawTokens, compressedTokens) {
1084
+ if (rawTokens <= 0) {
1085
+ return 0;
1086
+ }
1087
+ return Math.max(0, Math.min(100, Math.round(((rawTokens - compressedTokens) / rawTokens) * 100)));
1088
+ }
1089
+ function calculateBudgetUsedPercent(compressedTokens, maxContextTokens) {
1090
+ if (maxContextTokens <= 0) {
1091
+ return 0;
1092
+ }
1093
+ return Math.max(0, Math.round((compressedTokens / maxContextTokens) * 100));
1094
+ }
1095
+ function estimateTokenCount(text) {
1096
+ try {
1097
+ const { encode } = require("gpt-tokenizer/model/gpt-4o");
1098
+ return Math.max(1, encode(text).length);
1099
+ }
1100
+ catch {
1101
+ return Math.max(1, Math.ceil(text.replace(/\s+/g, " ").trim().length / 4));
1102
+ }
1103
+ }
1104
+ function compactPreview(content, maxLength) {
1105
+ const compacted = content.replace(/\s+/g, " ").trim();
1106
+ if (compacted.length <= maxLength) {
1107
+ return compacted;
1108
+ }
1109
+ return `${compacted.slice(0, Math.max(0, maxLength - 1))}\u2026`;
1110
+ }
1111
+ function parseSkillInsight(node) {
1112
+ try {
1113
+ const parsed = JSON.parse(node.content);
1114
+ if (!parsed.id || !parsed.name) {
1115
+ return undefined;
1116
+ }
1117
+ return {
1118
+ id: parsed.id,
1119
+ name: parsed.name,
1120
+ score: parsed.score ?? 0,
1121
+ uses: parsed.uses ?? 0,
1122
+ lastOutcome: parsed.lastOutcome === "fail" ? "fail" : "pass",
1123
+ updatedAt: parsed.updatedAt ?? 0,
1124
+ };
1125
+ }
1126
+ catch {
1127
+ return undefined;
1128
+ }
1129
+ }
1130
+ //# sourceMappingURL=runtime.js.map