@gt-fe/eap-runtime 0.0.8

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 (326) hide show
  1. package/README.md +323 -0
  2. package/dist/api/handlers/index.d.ts +3 -0
  3. package/dist/api/handlers/index.js +4 -0
  4. package/dist/api/handlers/invoke.handler.d.ts +77 -0
  5. package/dist/api/handlers/invoke.handler.js +411 -0
  6. package/dist/api/handlers/messages.handler.d.ts +53 -0
  7. package/dist/api/handlers/messages.handler.js +80 -0
  8. package/dist/api/handlers/stream.handler.d.ts +92 -0
  9. package/dist/api/handlers/stream.handler.js +432 -0
  10. package/dist/api/index.d.ts +3 -0
  11. package/dist/api/index.js +4 -0
  12. package/dist/api/middleware/auth.middleware.d.ts +96 -0
  13. package/dist/api/middleware/auth.middleware.js +158 -0
  14. package/dist/api/middleware/index.d.ts +1 -0
  15. package/dist/api/middleware/index.js +2 -0
  16. package/dist/api/routes/agent.routes.d.ts +44 -0
  17. package/dist/api/routes/agent.routes.js +204 -0
  18. package/dist/api/routes/index.d.ts +3 -0
  19. package/dist/api/routes/index.js +4 -0
  20. package/dist/api/routes/session.routes.d.ts +82 -0
  21. package/dist/api/routes/session.routes.js +169 -0
  22. package/dist/api/routes/task.routes.d.ts +75 -0
  23. package/dist/api/routes/task.routes.js +108 -0
  24. package/dist/checkpoint/checkpoint-serializer.d.ts +58 -0
  25. package/dist/checkpoint/checkpoint-serializer.js +81 -0
  26. package/dist/checkpoint/composite-checkpoint-saver.d.ts +42 -0
  27. package/dist/checkpoint/composite-checkpoint-saver.js +118 -0
  28. package/dist/checkpoint/contracts/checkpoint-saver.contract.d.ts +65 -0
  29. package/dist/checkpoint/contracts/checkpoint-saver.contract.js +12 -0
  30. package/dist/checkpoint/contracts/index.d.ts +1 -0
  31. package/dist/checkpoint/contracts/index.js +1 -0
  32. package/dist/checkpoint/file-checkpoint-saver.d.ts +19 -0
  33. package/dist/checkpoint/file-checkpoint-saver.js +98 -0
  34. package/dist/checkpoint/hybrid-checkpoint-saver.d.ts +130 -0
  35. package/dist/checkpoint/hybrid-checkpoint-saver.js +211 -0
  36. package/dist/checkpoint/in-memory-checkpoint-saver.d.ts +14 -0
  37. package/dist/checkpoint/in-memory-checkpoint-saver.js +46 -0
  38. package/dist/checkpoint/index.d.ts +16 -0
  39. package/dist/checkpoint/index.js +13 -0
  40. package/dist/checkpoint/mongo-checkpoint-saver.d.ts +38 -0
  41. package/dist/checkpoint/mongo-checkpoint-saver.js +56 -0
  42. package/dist/checkpoint/pg-checkpoint-saver.d.ts +59 -0
  43. package/dist/checkpoint/pg-checkpoint-saver.js +140 -0
  44. package/dist/checkpoint/redis-checkpoint-saver.d.ts +68 -0
  45. package/dist/checkpoint/redis-checkpoint-saver.js +173 -0
  46. package/dist/checkpoint/restore-checkpoint.d.ts +33 -0
  47. package/dist/checkpoint/restore-checkpoint.js +33 -0
  48. package/dist/common/agent-code.d.ts +10 -0
  49. package/dist/common/agent-code.js +12 -0
  50. package/dist/common/concurrency.d.ts +79 -0
  51. package/dist/common/concurrency.js +121 -0
  52. package/dist/common/health.d.ts +40 -0
  53. package/dist/common/health.js +37 -0
  54. package/dist/common/index.d.ts +5 -0
  55. package/dist/common/index.js +5 -0
  56. package/dist/common/logger.d.ts +34 -0
  57. package/dist/common/logger.js +38 -0
  58. package/dist/common/queue-consumer.d.ts +125 -0
  59. package/dist/common/queue-consumer.js +159 -0
  60. package/dist/common/trace-id.d.ts +2 -0
  61. package/dist/common/trace-id.js +8 -0
  62. package/dist/common/types.d.ts +104 -0
  63. package/dist/common/types.js +14 -0
  64. package/dist/contracts/index.d.ts +11 -0
  65. package/dist/contracts/index.js +10 -0
  66. package/dist/contracts/permission-checker.d.ts +10 -0
  67. package/dist/contracts/permission-checker.js +4 -0
  68. package/dist/contracts/trace-collector.d.ts +211 -0
  69. package/dist/contracts/trace-collector.js +13 -0
  70. package/dist/governance/governance-client.d.ts +38 -0
  71. package/dist/governance/governance-client.js +95 -0
  72. package/dist/governance/index.d.ts +7 -0
  73. package/dist/governance/index.js +5 -0
  74. package/dist/governance/permission-guard.d.ts +19 -0
  75. package/dist/governance/permission-guard.js +59 -0
  76. package/dist/graph/adapters/index.d.ts +3 -0
  77. package/dist/graph/adapters/index.js +3 -0
  78. package/dist/graph/adapters/langgraph-checkpointer.d.ts +40 -0
  79. package/dist/graph/adapters/langgraph-checkpointer.js +211 -0
  80. package/dist/graph/adapters/langgraph.adapter.d.ts +190 -0
  81. package/dist/graph/adapters/langgraph.adapter.js +1303 -0
  82. package/dist/graph/adapters/subgraph-compiler.d.ts +39 -0
  83. package/dist/graph/adapters/subgraph-compiler.js +248 -0
  84. package/dist/graph/condition-evaluator.d.ts +57 -0
  85. package/dist/graph/condition-evaluator.js +162 -0
  86. package/dist/graph/contracts/executable-graph.d.ts +340 -0
  87. package/dist/graph/contracts/executable-graph.js +10 -0
  88. package/dist/graph/contracts/index.d.ts +2 -0
  89. package/dist/graph/contracts/index.js +2 -0
  90. package/dist/graph/contracts/state-graph.contract.d.ts +76 -0
  91. package/dist/graph/contracts/state-graph.contract.js +11 -0
  92. package/dist/graph/hitl/hitl-handler.d.ts +199 -0
  93. package/dist/graph/hitl/hitl-handler.js +480 -0
  94. package/dist/graph/hitl/index.d.ts +1 -0
  95. package/dist/graph/hitl/index.js +1 -0
  96. package/dist/graph/index.d.ts +7 -0
  97. package/dist/graph/index.js +7 -0
  98. package/dist/graph/nodes/index.d.ts +2 -0
  99. package/dist/graph/nodes/index.js +2 -0
  100. package/dist/graph/nodes/llm-node.d.ts +182 -0
  101. package/dist/graph/nodes/llm-node.js +281 -0
  102. package/dist/graph/nodes/skill-bind-node.d.ts +32 -0
  103. package/dist/graph/nodes/skill-bind-node.js +116 -0
  104. package/dist/graph/nodes/tool-node.d.ts +75 -0
  105. package/dist/graph/nodes/tool-node.js +324 -0
  106. package/dist/graph/resolve-graph-prompt.d.ts +5 -0
  107. package/dist/graph/resolve-graph-prompt.js +75 -0
  108. package/dist/graph/retry/budget-aware-retry.d.ts +91 -0
  109. package/dist/graph/retry/budget-aware-retry.js +126 -0
  110. package/dist/graph/retry/index.d.ts +9 -0
  111. package/dist/graph/retry/index.js +8 -0
  112. package/dist/graph/retry/node-retry.d.ts +123 -0
  113. package/dist/graph/retry/node-retry.js +235 -0
  114. package/dist/graph/skill-audit-recorder.d.ts +126 -0
  115. package/dist/graph/skill-audit-recorder.js +114 -0
  116. package/dist/index.d.ts +21 -0
  117. package/dist/index.js +32 -0
  118. package/dist/memory/compression/compression-stats.d.ts +109 -0
  119. package/dist/memory/compression/compression-stats.js +144 -0
  120. package/dist/memory/compression/compression.repository.d.ts +62 -0
  121. package/dist/memory/compression/compression.repository.js +71 -0
  122. package/dist/memory/compression/index.d.ts +10 -0
  123. package/dist/memory/compression/index.js +15 -0
  124. package/dist/memory/compression/llm-summarize.d.ts +58 -0
  125. package/dist/memory/compression/llm-summarize.js +192 -0
  126. package/dist/memory/compression/sliding-window.compression.d.ts +60 -0
  127. package/dist/memory/compression/sliding-window.compression.js +175 -0
  128. package/dist/memory/index.d.ts +4 -0
  129. package/dist/memory/index.js +7 -0
  130. package/dist/memory/long-term-memory.service.d.ts +94 -0
  131. package/dist/memory/long-term-memory.service.js +120 -0
  132. package/dist/memory/message-compression.service.d.ts +128 -0
  133. package/dist/memory/message-compression.service.js +69 -0
  134. package/dist/memory/pg-memory.repository.d.ts +44 -0
  135. package/dist/memory/pg-memory.repository.js +108 -0
  136. package/dist/memory/semantic-retrieval.service.d.ts +148 -0
  137. package/dist/memory/semantic-retrieval.service.js +238 -0
  138. package/dist/providers/echo-llm-provider.d.ts +10 -0
  139. package/dist/providers/echo-llm-provider.js +87 -0
  140. package/dist/providers/http-llm-provider.d.ts +35 -0
  141. package/dist/providers/http-llm-provider.js +404 -0
  142. package/dist/providers/index.d.ts +7 -0
  143. package/dist/providers/index.js +5 -0
  144. package/dist/providers/local-llm-provider.d.ts +27 -0
  145. package/dist/providers/local-llm-provider.js +105 -0
  146. package/dist/providers/resolve-llm-model.d.ts +13 -0
  147. package/dist/providers/resolve-llm-model.js +30 -0
  148. package/dist/providers/routing-llm-provider.d.ts +28 -0
  149. package/dist/providers/routing-llm-provider.js +79 -0
  150. package/dist/registry/agent-models.d.ts +1 -0
  151. package/dist/registry/agent-models.js +1 -0
  152. package/dist/registry/agent-registry-client.d.ts +56 -0
  153. package/dist/registry/agent-registry-client.js +36 -0
  154. package/dist/registry/definition-cache.d.ts +37 -0
  155. package/dist/registry/definition-cache.js +82 -0
  156. package/dist/registry/deployment-snapshot.d.ts +99 -0
  157. package/dist/registry/deployment-snapshot.js +542 -0
  158. package/dist/registry/graph-loader.d.ts +134 -0
  159. package/dist/registry/graph-loader.js +985 -0
  160. package/dist/registry/index.d.ts +9 -0
  161. package/dist/registry/index.js +9 -0
  162. package/dist/registry/preload-errors.d.ts +13 -0
  163. package/dist/registry/preload-errors.js +35 -0
  164. package/dist/registry/preload-flags.d.ts +22 -0
  165. package/dist/registry/preload-flags.js +44 -0
  166. package/dist/registry/skill-io-guard.d.ts +25 -0
  167. package/dist/registry/skill-io-guard.js +98 -0
  168. package/dist/registry/skill-tree.d.ts +27 -0
  169. package/dist/registry/skill-tree.js +183 -0
  170. package/dist/runtime/agent-runtime.d.ts +106 -0
  171. package/dist/runtime/agent-runtime.js +777 -0
  172. package/dist/runtime/dev-runtime.d.ts +69 -0
  173. package/dist/runtime/dev-runtime.js +199 -0
  174. package/dist/runtime/index.d.ts +4 -0
  175. package/dist/runtime/index.js +3 -0
  176. package/dist/runtime/storage-profile.d.ts +50 -0
  177. package/dist/runtime/storage-profile.js +138 -0
  178. package/dist/runtime/types.d.ts +120 -0
  179. package/dist/runtime/types.js +9 -0
  180. package/dist/server.d.ts +12 -0
  181. package/dist/server.js +161 -0
  182. package/dist/session/compression-middleware.d.ts +126 -0
  183. package/dist/session/compression-middleware.js +230 -0
  184. package/dist/session/file-message.repository.d.ts +25 -0
  185. package/dist/session/file-message.repository.js +78 -0
  186. package/dist/session/file-session.repository.d.ts +72 -0
  187. package/dist/session/file-session.repository.js +212 -0
  188. package/dist/session/index.d.ts +13 -0
  189. package/dist/session/index.js +12 -0
  190. package/dist/session/message.service.d.ts +80 -0
  191. package/dist/session/message.service.js +128 -0
  192. package/dist/session/persist-turn-messages.d.ts +145 -0
  193. package/dist/session/persist-turn-messages.js +325 -0
  194. package/dist/session/pg-message.repository.d.ts +49 -0
  195. package/dist/session/pg-message.repository.js +149 -0
  196. package/dist/session/pg-session.repository.d.ts +46 -0
  197. package/dist/session/pg-session.repository.js +117 -0
  198. package/dist/session/session-context.service.d.ts +49 -0
  199. package/dist/session/session-context.service.js +66 -0
  200. package/dist/session/session.service.d.ts +194 -0
  201. package/dist/session/session.service.js +166 -0
  202. package/dist/sse/connection-event-logger.d.ts +21 -0
  203. package/dist/sse/connection-event-logger.js +33 -0
  204. package/dist/sse/contracts/index.d.ts +1 -0
  205. package/dist/sse/contracts/index.js +1 -0
  206. package/dist/sse/contracts/sse-emitter.contract.d.ts +74 -0
  207. package/dist/sse/contracts/sse-emitter.contract.js +11 -0
  208. package/dist/sse/event-buffer.d.ts +20 -0
  209. package/dist/sse/event-buffer.js +45 -0
  210. package/dist/sse/events/code-events.d.ts +19 -0
  211. package/dist/sse/events/code-events.js +9 -0
  212. package/dist/sse/events/collaboration-events.d.ts +37 -0
  213. package/dist/sse/events/collaboration-events.js +11 -0
  214. package/dist/sse/events/connection-events.d.ts +13 -0
  215. package/dist/sse/events/connection-events.js +9 -0
  216. package/dist/sse/events/file-events.d.ts +29 -0
  217. package/dist/sse/events/file-events.js +10 -0
  218. package/dist/sse/events/hitl-events.d.ts +33 -0
  219. package/dist/sse/events/hitl-events.js +10 -0
  220. package/dist/sse/events/index.d.ts +107 -0
  221. package/dist/sse/events/index.js +96 -0
  222. package/dist/sse/events/plan-events.d.ts +38 -0
  223. package/dist/sse/events/plan-events.js +11 -0
  224. package/dist/sse/events/reasoning-events.d.ts +35 -0
  225. package/dist/sse/events/reasoning-events.js +13 -0
  226. package/dist/sse/events/response-events.d.ts +25 -0
  227. package/dist/sse/events/response-events.js +12 -0
  228. package/dist/sse/events/session-events.d.ts +43 -0
  229. package/dist/sse/events/session-events.js +12 -0
  230. package/dist/sse/events/skill-events.d.ts +48 -0
  231. package/dist/sse/events/skill-events.js +11 -0
  232. package/dist/sse/events/stats-events.d.ts +44 -0
  233. package/dist/sse/events/stats-events.js +12 -0
  234. package/dist/sse/events/tool-events.d.ts +68 -0
  235. package/dist/sse/events/tool-events.js +14 -0
  236. package/dist/sse/index.d.ts +8 -0
  237. package/dist/sse/index.js +8 -0
  238. package/dist/sse/sse-connection-manager.d.ts +116 -0
  239. package/dist/sse/sse-connection-manager.js +185 -0
  240. package/dist/sse/sse-emitter.d.ts +108 -0
  241. package/dist/sse/sse-emitter.js +210 -0
  242. package/dist/sse/sse-heartbeat.d.ts +58 -0
  243. package/dist/sse/sse-heartbeat.js +76 -0
  244. package/dist/sse/trace-collector.d.ts +60 -0
  245. package/dist/sse/trace-collector.js +107 -0
  246. package/dist/task/contracts/index.d.ts +2 -0
  247. package/dist/task/contracts/index.js +1 -0
  248. package/dist/task/contracts/task-manager.contract.d.ts +160 -0
  249. package/dist/task/contracts/task-manager.contract.js +10 -0
  250. package/dist/task/index.d.ts +7 -0
  251. package/dist/task/index.js +5 -0
  252. package/dist/task/pg-task.repository.d.ts +47 -0
  253. package/dist/task/pg-task.repository.js +131 -0
  254. package/dist/task/task-progress-tracker.d.ts +67 -0
  255. package/dist/task/task-progress-tracker.js +80 -0
  256. package/dist/task/task-timeout.d.ts +70 -0
  257. package/dist/task/task-timeout.js +116 -0
  258. package/dist/task/task.service.d.ts +84 -0
  259. package/dist/task/task.service.js +233 -0
  260. package/dist/token/compression-budget-integration.d.ts +145 -0
  261. package/dist/token/compression-budget-integration.js +185 -0
  262. package/dist/token/context-window-budget.d.ts +113 -0
  263. package/dist/token/context-window-budget.js +134 -0
  264. package/dist/token/contracts/index.d.ts +1 -0
  265. package/dist/token/contracts/index.js +1 -0
  266. package/dist/token/contracts/token-budget.contract.d.ts +77 -0
  267. package/dist/token/contracts/token-budget.contract.js +11 -0
  268. package/dist/token/index.d.ts +12 -0
  269. package/dist/token/index.js +10 -0
  270. package/dist/token/pg-token-budget.repository.d.ts +39 -0
  271. package/dist/token/pg-token-budget.repository.js +116 -0
  272. package/dist/token/session-budget-checker.d.ts +54 -0
  273. package/dist/token/session-budget-checker.js +72 -0
  274. package/dist/token/token-budget-guard.d.ts +66 -0
  275. package/dist/token/token-budget-guard.js +97 -0
  276. package/dist/token/token-budget.service.d.ts +86 -0
  277. package/dist/token/token-budget.service.js +130 -0
  278. package/dist/token/token-detail-mode.d.ts +73 -0
  279. package/dist/token/token-detail-mode.js +107 -0
  280. package/dist/token/token-estimator.d.ts +80 -0
  281. package/dist/token/token-estimator.js +134 -0
  282. package/dist/token/token-stats.service.d.ts +88 -0
  283. package/dist/token/token-stats.service.js +94 -0
  284. package/dist/tool/create-tool-executor.d.ts +33 -0
  285. package/dist/tool/create-tool-executor.js +60 -0
  286. package/dist/tool/dev-http-executor.d.ts +18 -0
  287. package/dist/tool/dev-http-executor.js +96 -0
  288. package/dist/tool/dev-mcp-executor.d.ts +29 -0
  289. package/dist/tool/dev-mcp-executor.js +84 -0
  290. package/dist/tool/dev-tool-executor.d.ts +23 -0
  291. package/dist/tool/dev-tool-executor.js +55 -0
  292. package/dist/tool/file-artifact.d.ts +11 -0
  293. package/dist/tool/file-artifact.js +90 -0
  294. package/dist/tool/http-tool-executor.d.ts +17 -0
  295. package/dist/tool/http-tool-executor.js +158 -0
  296. package/dist/tool/index.d.ts +18 -0
  297. package/dist/tool/index.js +17 -0
  298. package/dist/tool/loaded-tool-definition.d.ts +35 -0
  299. package/dist/tool/loaded-tool-definition.js +9 -0
  300. package/dist/tool/local-mcp-client.d.ts +23 -0
  301. package/dist/tool/local-mcp-client.js +225 -0
  302. package/dist/tool/local-tool-executor.d.ts +37 -0
  303. package/dist/tool/local-tool-executor.js +249 -0
  304. package/dist/tool/mcp-tool-executor.d.ts +23 -0
  305. package/dist/tool/mcp-tool-executor.js +160 -0
  306. package/dist/tool/mock-tool-executor.d.ts +28 -0
  307. package/dist/tool/mock-tool-executor.js +65 -0
  308. package/dist/tool/system-prompt-builder.d.ts +114 -0
  309. package/dist/tool/system-prompt-builder.js +213 -0
  310. package/dist/tool/tool-confirmation.d.ts +29 -0
  311. package/dist/tool/tool-confirmation.js +81 -0
  312. package/dist/tool/tool-event-emitter.d.ts +58 -0
  313. package/dist/tool/tool-event-emitter.js +154 -0
  314. package/dist/tool/tool-execution-router.d.ts +25 -0
  315. package/dist/tool/tool-execution-router.js +50 -0
  316. package/dist/tool/tool-executor.interface.d.ts +85 -0
  317. package/dist/tool/tool-executor.interface.js +7 -0
  318. package/dist/tool/tool-orchestrator.d.ts +22 -0
  319. package/dist/tool/tool-orchestrator.js +104 -0
  320. package/dist/tool/tool-result-injector.d.ts +64 -0
  321. package/dist/tool/tool-result-injector.js +65 -0
  322. package/dist/utils/format-error.d.ts +4 -0
  323. package/dist/utils/format-error.js +4 -0
  324. package/dist/utils/http-error.d.ts +11 -0
  325. package/dist/utils/http-error.js +24 -0
  326. package/package.json +56 -0
@@ -0,0 +1,39 @@
1
+ /**
2
+ * SubGraphCompiler — 子图嵌套编译器
3
+ *
4
+ * 将 Skill DSL 编译为子图节点函数,嵌入父 Graph 执行。
5
+ * 子图作为独立 StateGraph 编译,父图通过节点函数调用子图并合并输出。
6
+ *
7
+ * @see design.md §1.4 子图嵌套: Skill作为子图嵌入主Graph
8
+ * @see requirements.md Requirement 1 AC2 — 子图嵌套(Skill作为子图)
9
+ */
10
+ import type { NodeFunction } from '@langchain/langgraph';
11
+ import type { GraphDSL } from '../contracts/executable-graph.js';
12
+ import type { IGovernanceClient } from '../../governance/governance-client.js';
13
+ import { LangGraphAdapter } from './langgraph.adapter.js';
14
+ import type { SkillAuditRecorder } from '../skill-audit-recorder.js';
15
+ /** LangGraph 内部状态类型 */
16
+ type LangGraphState = Record<string, unknown>;
17
+ /**
18
+ * SubGraphCompiler — 子图编译器
19
+ *
20
+ * 职责:
21
+ * 1. 接收 Skill 的 GraphDSL 定义
22
+ * 2. 通过 LangGraphAdapter 将其编译为独立的 ExecutableGraph
23
+ * 3. 返回一个 NodeFunction,父图将此函数当作普通节点执行
24
+ * 4. 执行时,子图内部运行完整的 graph invoke 流程,输出合并回父图 state
25
+ */
26
+ export declare class SubGraphCompiler {
27
+ private readonly adapter;
28
+ private readonly governanceClient?;
29
+ private readonly skillAuditRecorder?;
30
+ constructor(adapter?: LangGraphAdapter, governanceClient?: IGovernanceClient, skillAuditRecorder?: SkillAuditRecorder);
31
+ /**
32
+ * 将 Skill DSL 编译为可嵌入父图的 NodeFunction
33
+ *
34
+ * @param dsl - Skill 的 GraphDSL 定义
35
+ * @param skillId - Skill 资源 ID(用于 checkPermission skill:use)
36
+ */
37
+ compileSubGraph(dsl: GraphDSL, skillId?: string): NodeFunction<LangGraphState>;
38
+ }
39
+ export {};
@@ -0,0 +1,248 @@
1
+ /**
2
+ * SubGraphCompiler — 子图嵌套编译器
3
+ *
4
+ * 将 Skill DSL 编译为子图节点函数,嵌入父 Graph 执行。
5
+ * 子图作为独立 StateGraph 编译,父图通过节点函数调用子图并合并输出。
6
+ *
7
+ * @see design.md §1.4 子图嵌套: Skill作为子图嵌入主Graph
8
+ * @see requirements.md Requirement 1 AC2 — 子图嵌套(Skill作为子图)
9
+ */
10
+ import { assertSkillPermission } from '../../governance/permission-guard.js';
11
+ import { LangGraphAdapter } from './langgraph.adapter.js';
12
+ import { resolveTraceId } from '../../common/trace-id.js';
13
+ import { filterLoadedToolsForSkill, } from '../../tool/system-prompt-builder.js';
14
+ import { unwrapHitlPaused } from '../hitl/hitl-handler.js';
15
+ import { assertSkillIoIfEnabled, coerceSkillInputFromMessages, } from '../../registry/skill-io-guard.js';
16
+ /**
17
+ * SubGraphCompiler — 子图编译器
18
+ *
19
+ * 职责:
20
+ * 1. 接收 Skill 的 GraphDSL 定义
21
+ * 2. 通过 LangGraphAdapter 将其编译为独立的 ExecutableGraph
22
+ * 3. 返回一个 NodeFunction,父图将此函数当作普通节点执行
23
+ * 4. 执行时,子图内部运行完整的 graph invoke 流程,输出合并回父图 state
24
+ */
25
+ export class SubGraphCompiler {
26
+ adapter;
27
+ governanceClient;
28
+ skillAuditRecorder;
29
+ constructor(adapter, governanceClient, skillAuditRecorder) {
30
+ this.adapter = adapter ?? new LangGraphAdapter();
31
+ this.governanceClient = governanceClient;
32
+ this.skillAuditRecorder = skillAuditRecorder;
33
+ }
34
+ /**
35
+ * 将 Skill DSL 编译为可嵌入父图的 NodeFunction
36
+ *
37
+ * @param dsl - Skill 的 GraphDSL 定义
38
+ * @param skillId - Skill 资源 ID(用于 checkPermission skill:use)
39
+ */
40
+ compileSubGraph(dsl, skillId) {
41
+ const adapter = this.adapter;
42
+ const resolvedSkillId = skillId ?? dsl.name ?? '';
43
+ const subGraphNodeFn = async (state) => {
44
+ const executionContext = state['executionContext'];
45
+ if (executionContext) {
46
+ await assertSkillPermission(this.governanceClient, executionContext, resolvedSkillId);
47
+ }
48
+ const existingSpanId = typeof state['skillSpanId'] === 'string' && state['skillSpanId']
49
+ ? state['skillSpanId']
50
+ : '';
51
+ const resuming = Boolean(existingSpanId);
52
+ const auditCtx = resuming
53
+ ? undefined
54
+ : this.skillAuditRecorder?.startInvocation({
55
+ skillId: resolvedSkillId,
56
+ skillName: dsl.name,
57
+ agentCode: (state['agentCode'] ?? state['agentId']),
58
+ userId: state['userId'] ?? '',
59
+ taskId: state['taskId'],
60
+ correlationId: state['correlationId'],
61
+ });
62
+ const traceCollector = state['traceCollector'];
63
+ const traceId = resolveTraceId(state);
64
+ const skillName = dsl.name || resolvedSkillId;
65
+ if (!resuming) {
66
+ adapter.emitStreamEvent({
67
+ type: 'skill.started',
68
+ taskId: state['taskId'],
69
+ correlationId: state['correlationId'],
70
+ timestamp: new Date().toISOString(),
71
+ payload: {
72
+ skillId: resolvedSkillId,
73
+ skillName,
74
+ },
75
+ });
76
+ }
77
+ let skillSpanId = existingSpanId || null;
78
+ if (!resuming && traceCollector && traceId) {
79
+ try {
80
+ skillSpanId = await traceCollector.createNode({
81
+ traceId,
82
+ name: resolvedSkillId || dsl.name || 'skill',
83
+ type: 'skill',
84
+ agentCode: state['agentCode'] ?? state['agentId'],
85
+ metadata: { skillId: resolvedSkillId, taskId: state['taskId'], correlationId: state['correlationId'] },
86
+ });
87
+ }
88
+ catch {
89
+ skillSpanId = null;
90
+ }
91
+ }
92
+ try {
93
+ // 1. 编译子图(每次执行时编译,确保子图实例独立)
94
+ const subGraph = await adapter.buildGraph(dsl);
95
+ // 2. 从父 state 提取 messages 和上下文,构造子图输入
96
+ const messages = Array.isArray(state['messages']) ? state['messages'] : [];
97
+ const userId = state['userId'] ?? '';
98
+ const delegationToken = state['delegationToken'];
99
+ const agentCode = state['agentCode'] ?? state['agentId'];
100
+ const defs = state['skillDefinitions'];
101
+ const skillInfo = resolvedSkillId ? defs?.[resolvedSkillId] : undefined;
102
+ const skillPrompt = skillInfo?.prompt;
103
+ const parentTools = state['loadedTools'];
104
+ const scopedTools = filterLoadedToolsForSkill(parentTools, skillInfo);
105
+ const skillInput = skillInfo
106
+ ? coerceSkillInputFromMessages(skillInfo, state['skillInput'], messages)
107
+ : state['skillInput'];
108
+ if (skillInfo) {
109
+ assertSkillIoIfEnabled(skillInfo, skillInput);
110
+ }
111
+ const subGraphState = {
112
+ messages: messages.map((msg) => ({
113
+ role: msg['role'] ?? 'user',
114
+ content: msg['content'] ?? '',
115
+ toolCalls: msg['tool_calls'] ?? msg['toolCalls'],
116
+ ...(typeof msg['toolCallId'] === 'string' ? { toolCallId: msg['toolCallId'] } : {}),
117
+ ...(typeof msg['toolName'] === 'string' ? { toolName: msg['toolName'] } : {}),
118
+ ...(typeof msg['success'] === 'boolean' ? { success: msg['success'] } : {}),
119
+ ...(typeof msg['reasoningContent'] === 'string'
120
+ ? { reasoningContent: msg['reasoningContent'] }
121
+ : {}),
122
+ })),
123
+ // 子图与父图共用 session thread;入口必须 __set,否则 checkpointer 会把父图 messages 再 append 一遍
124
+ replaceCheckpointMessages: true,
125
+ userId,
126
+ delegationToken,
127
+ agentCode,
128
+ taskId: state['taskId'],
129
+ correlationId: state['correlationId'],
130
+ sessionId: state['sessionId'],
131
+ executionContext: state['executionContext'],
132
+ loadedTools: scopedTools,
133
+ loadedSkills: state['loadedSkills'],
134
+ skillDefinitions: defs,
135
+ activeSkillPrompt: skillPrompt,
136
+ activatedSkill: resolvedSkillId || undefined,
137
+ skillInput,
138
+ traceId,
139
+ traceCollector,
140
+ skillSpanId: skillSpanId ?? undefined,
141
+ hitlChoice: state['hitlChoice'],
142
+ hitlRespondedBy: state['hitlRespondedBy'],
143
+ };
144
+ const result = await adapter.runIsolatedLlmStreamFlags(() => adapter.invoke(subGraph, subGraphState));
145
+ // RT-6: 记录成功
146
+ await auditCtx?.finish({
147
+ status: 'success',
148
+ tokenUsage: result.tokenUsage,
149
+ });
150
+ if (traceCollector && skillSpanId) {
151
+ try {
152
+ await traceCollector.completeNode(skillSpanId, {
153
+ status: 'completed',
154
+ output: result.output,
155
+ inputTokens: result.tokenUsage?.input,
156
+ outputTokens: result.tokenUsage?.output,
157
+ totalTokens: result.tokenUsage?.total,
158
+ });
159
+ }
160
+ catch {
161
+ // ignore
162
+ }
163
+ }
164
+ // 4. 只回写子图本步新增消息(含内部 tool 回合),禁止把入口历史再 append
165
+ const subMessages = Array.isArray(result.finalState?.messages)
166
+ ? result.finalState.messages
167
+ : [];
168
+ const reasoningContent = lastAssistantReasoning(subMessages);
169
+ adapter.emitStreamEvent({
170
+ type: 'skill.completed',
171
+ taskId: state['taskId'],
172
+ correlationId: state['correlationId'],
173
+ timestamp: new Date().toISOString(),
174
+ payload: {
175
+ skillId: resolvedSkillId,
176
+ skillName,
177
+ output: result.output,
178
+ ...(reasoningContent ? { reasoningContent } : {}),
179
+ },
180
+ });
181
+ const added = subMessages.slice(messages.length);
182
+ const outputMessages = added.length > 0
183
+ ? added
184
+ : result.output
185
+ ? [{ role: 'assistant', content: result.output }]
186
+ : [];
187
+ const perNode = result.tokenUsage?.perNode;
188
+ return {
189
+ messages: outputMessages,
190
+ currentNode: `subgraph:${dsl.name}`,
191
+ ...(Array.isArray(perNode) && perNode.length > 0
192
+ ? {
193
+ __llmTokenUsage: perNode.map((u) => ({
194
+ nodeId: u.nodeId,
195
+ model: u.model,
196
+ inputTokens: u.inputTokens,
197
+ outputTokens: u.outputTokens,
198
+ })),
199
+ }
200
+ : {}),
201
+ };
202
+ }
203
+ catch (err) {
204
+ const hitlPaused = unwrapHitlPaused(err);
205
+ if (hitlPaused) {
206
+ throw err;
207
+ }
208
+ await auditCtx?.finish({
209
+ status: 'failed',
210
+ errorMessage: err instanceof Error ? err.message : String(err),
211
+ });
212
+ if (traceCollector && skillSpanId) {
213
+ try {
214
+ await traceCollector.completeNode(skillSpanId, {
215
+ status: 'failed',
216
+ error: err instanceof Error ? err.message : String(err),
217
+ });
218
+ }
219
+ catch {
220
+ // ignore
221
+ }
222
+ }
223
+ adapter.emitStreamEvent({
224
+ type: 'skill.failed',
225
+ taskId: state['taskId'],
226
+ correlationId: state['correlationId'],
227
+ timestamp: new Date().toISOString(),
228
+ payload: {
229
+ skillId: resolvedSkillId,
230
+ skillName,
231
+ error: err instanceof Error ? err.message : String(err),
232
+ },
233
+ });
234
+ throw err;
235
+ }
236
+ };
237
+ return subGraphNodeFn;
238
+ }
239
+ }
240
+ function lastAssistantReasoning(messages) {
241
+ for (let i = messages.length - 1; i >= 0; i--) {
242
+ const content = messages[i]?.reasoningContent;
243
+ if (messages[i]?.role === 'assistant' && typeof content === 'string' && content) {
244
+ return content;
245
+ }
246
+ }
247
+ return undefined;
248
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * ConditionEvaluator — Graph 条件路由评估器
3
+ *
4
+ * 支持三种条件评估模式:
5
+ * 1. **stateField** — 读取 state 中指定字段的值,与分支 value 匹配
6
+ * 2. **expression** — 简单表达式求值(支持 ===, !==, >, <, >=, <=, includes, truthy/falsy)
7
+ * 3. **custom** — 注册自定义评估函数
8
+ *
9
+ * @see executable-graph.ts ConditionalEdge.conditionFn
10
+ */
11
+ type LangGraphState = Record<string, unknown>;
12
+ /**
13
+ * 自定义条件评估函数签名
14
+ */
15
+ export type ConditionEvaluatorFn = (state: LangGraphState) => string | Promise<string>;
16
+ /**
17
+ * ConditionEvaluator — 条件路由评估服务
18
+ *
19
+ * 管理已注册的自定义评估函数,并提供状态字段读取和表达式求值能力。
20
+ */
21
+ export declare class ConditionEvaluator {
22
+ private readonly customEvaluators;
23
+ /**
24
+ * 注册自定义条件评估函数
25
+ */
26
+ register(name: string, fn: ConditionEvaluatorFn): void;
27
+ /**
28
+ * 评估条件表达式,返回匹配的分支值
29
+ *
30
+ * @param conditionExpr - 条件表达式字符串(DSL 中 conditionFn 字段)
31
+ * @param state - 当前 Graph State
32
+ * @param branches - 可用的分支值列表
33
+ * @param fallback - 默认分支值
34
+ * @returns 匹配的分支值
35
+ */
36
+ evaluate(conditionExpr: string | undefined, state: LangGraphState, branches: string[], fallback: string): Promise<string>;
37
+ /**
38
+ * 从 state 中按路径读取值(支持嵌套路径如 `a.b.c`)
39
+ */
40
+ readStatePath(state: LangGraphState, path: string): unknown;
41
+ /**
42
+ * 简单表达式求值
43
+ *
44
+ * 支持格式:
45
+ * - `field === 'value'`
46
+ * - `field !== 'value'`
47
+ * - `field > number`
48
+ * - `field includes 'substring'`
49
+ * - `field`(truthy 检查)
50
+ */
51
+ private evaluateExpression;
52
+ /**
53
+ * 解析字面量值(字符串、数字、布尔)
54
+ */
55
+ private parseLiteral;
56
+ }
57
+ export {};
@@ -0,0 +1,162 @@
1
+ /**
2
+ * ConditionEvaluator — Graph 条件路由评估器
3
+ *
4
+ * 支持三种条件评估模式:
5
+ * 1. **stateField** — 读取 state 中指定字段的值,与分支 value 匹配
6
+ * 2. **expression** — 简单表达式求值(支持 ===, !==, >, <, >=, <=, includes, truthy/falsy)
7
+ * 3. **custom** — 注册自定义评估函数
8
+ *
9
+ * @see executable-graph.ts ConditionalEdge.conditionFn
10
+ */
11
+ /**
12
+ * ConditionEvaluator — 条件路由评估服务
13
+ *
14
+ * 管理已注册的自定义评估函数,并提供状态字段读取和表达式求值能力。
15
+ */
16
+ export class ConditionEvaluator {
17
+ customEvaluators = new Map();
18
+ /**
19
+ * 注册自定义条件评估函数
20
+ */
21
+ register(name, fn) {
22
+ this.customEvaluators.set(name, fn);
23
+ }
24
+ /**
25
+ * 评估条件表达式,返回匹配的分支值
26
+ *
27
+ * @param conditionExpr - 条件表达式字符串(DSL 中 conditionFn 字段)
28
+ * @param state - 当前 Graph State
29
+ * @param branches - 可用的分支值列表
30
+ * @param fallback - 默认分支值
31
+ * @returns 匹配的分支值
32
+ */
33
+ async evaluate(conditionExpr, state, branches, fallback) {
34
+ if (!conditionExpr) {
35
+ // 无表达式时,尝试从 state.__conditionResult 读取(condition 节点写入)
36
+ const stateResult = this.readStatePath(state, '__conditionResult');
37
+ if (stateResult !== undefined && branches.includes(String(stateResult))) {
38
+ return String(stateResult);
39
+ }
40
+ return fallback;
41
+ }
42
+ // 1. 检查是否为已注册的自定义函数名
43
+ const customFn = this.customEvaluators.get(conditionExpr);
44
+ if (customFn) {
45
+ const result = await customFn(state);
46
+ if (branches.includes(result))
47
+ return result;
48
+ // afterSkillRoute 返回 skillId;图可用精确边,或用 "skill" 兜底所有命中
49
+ if (conditionExpr === 'afterSkillRoute' &&
50
+ result !== 'none' &&
51
+ result !== 'clarify' &&
52
+ branches.includes('skill')) {
53
+ return 'skill';
54
+ }
55
+ return fallback;
56
+ }
57
+ // 2. 检查是否为 stateField 引用(格式:`state.fieldName` 或 `field.subField`)
58
+ if (conditionExpr.startsWith('state.') || !conditionExpr.includes(' ')) {
59
+ const path = conditionExpr.startsWith('state.')
60
+ ? conditionExpr.slice(6)
61
+ : conditionExpr;
62
+ const value = this.readStatePath(state, path);
63
+ if (value !== undefined) {
64
+ const strValue = String(value);
65
+ return branches.includes(strValue) ? strValue : fallback;
66
+ }
67
+ return fallback;
68
+ }
69
+ // 3. 简单表达式求值
70
+ const result = this.evaluateExpression(conditionExpr, state, branches);
71
+ return result ?? fallback;
72
+ }
73
+ /**
74
+ * 从 state 中按路径读取值(支持嵌套路径如 `a.b.c`)
75
+ */
76
+ readStatePath(state, path) {
77
+ const parts = path.split('.');
78
+ let current = state;
79
+ for (const part of parts) {
80
+ if (current === null || current === undefined)
81
+ return undefined;
82
+ if (typeof current === 'object') {
83
+ current = current[part];
84
+ }
85
+ else {
86
+ return undefined;
87
+ }
88
+ }
89
+ return current;
90
+ }
91
+ /**
92
+ * 简单表达式求值
93
+ *
94
+ * 支持格式:
95
+ * - `field === 'value'`
96
+ * - `field !== 'value'`
97
+ * - `field > number`
98
+ * - `field includes 'substring'`
99
+ * - `field`(truthy 检查)
100
+ */
101
+ evaluateExpression(expr, state, branches) {
102
+ const trimmed = expr.trim();
103
+ // 二元操作符匹配
104
+ const binaryOps = [
105
+ { op: '===', fn: (a, b) => a === b },
106
+ { op: '!==', fn: (a, b) => a !== b },
107
+ { op: '>=', fn: (a, b) => Number(a) >= Number(b) },
108
+ { op: '<=', fn: (a, b) => Number(a) <= Number(b) },
109
+ { op: '>', fn: (a, b) => Number(a) > Number(b) },
110
+ { op: '<', fn: (a, b) => Number(a) < Number(b) },
111
+ { op: ' includes ', fn: (a, b) => String(a).includes(String(b)) },
112
+ ];
113
+ for (const { op, fn } of binaryOps) {
114
+ const idx = trimmed.indexOf(op);
115
+ if (idx > 0) {
116
+ const leftPath = trimmed.slice(0, idx).trim();
117
+ const rightRaw = trimmed.slice(idx + op.length).trim();
118
+ const leftValue = this.readStatePath(state, leftPath);
119
+ const rightValue = this.parseLiteral(rightRaw);
120
+ const result = fn(leftValue, rightValue);
121
+ const resultStr = String(result);
122
+ return branches.includes(resultStr) ? resultStr : undefined;
123
+ }
124
+ }
125
+ // 无操作符:truthy 检查,返回字段值
126
+ const value = this.readStatePath(state, trimmed);
127
+ if (value !== undefined) {
128
+ const strValue = String(value);
129
+ if (branches.includes(strValue))
130
+ return strValue;
131
+ // truthy/falsy → true/false
132
+ const boolStr = String(!!value);
133
+ if (branches.includes(boolStr))
134
+ return boolStr;
135
+ }
136
+ return undefined;
137
+ }
138
+ /**
139
+ * 解析字面量值(字符串、数字、布尔)
140
+ */
141
+ parseLiteral(raw) {
142
+ // 带引号的字符串
143
+ if ((raw.startsWith("'") && raw.endsWith("'")) || (raw.startsWith('"') && raw.endsWith('"'))) {
144
+ return raw.slice(1, -1);
145
+ }
146
+ // 布尔
147
+ if (raw === 'true')
148
+ return true;
149
+ if (raw === 'false')
150
+ return false;
151
+ if (raw === 'null')
152
+ return null;
153
+ if (raw === 'undefined')
154
+ return undefined;
155
+ // 数字
156
+ const num = Number(raw);
157
+ if (!isNaN(num))
158
+ return num;
159
+ // 其他视为字符串
160
+ return raw;
161
+ }
162
+ }