@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,233 @@
1
+ /**
2
+ * TaskService — ITaskManager 实现
3
+ *
4
+ * 管理 Task 生命周期:创建、状态流转、查询、Token消耗记录、进度跟踪。
5
+ * v1 使用 in-memory Map 存储,后续由 TaskRepository 替换。
6
+ *
7
+ * @see task-manager.contract.ts
8
+ * @see requirements.md Requirement 7 AC1-AC5
9
+ */
10
+ import { randomUUID } from 'node:crypto';
11
+ import { TaskProgressTracker } from './task-progress-tracker.js';
12
+ // ─────────────────────────────────────────────
13
+ // State Transition Validation
14
+ // ─────────────────────────────────────────────
15
+ /**
16
+ * 合法状态流转映射
17
+ *
18
+ * pending → running
19
+ * running → success | failed | timeout | token_exhausted
20
+ */
21
+ const VALID_TRANSITIONS = {
22
+ pending: ['running'],
23
+ running: ['success', 'failed', 'timeout', 'token_exhausted', 'waiting_hitl'],
24
+ waiting_hitl: ['running', 'timeout', 'failed'],
25
+ success: [],
26
+ failed: [],
27
+ timeout: [],
28
+ token_exhausted: [],
29
+ };
30
+ // ─────────────────────────────────────────────
31
+ // In-Memory Repository (Default)
32
+ // ─────────────────────────────────────────────
33
+ /**
34
+ * InMemoryTaskRepository — 内存存储实现
35
+ *
36
+ * 用于开发/测试阶段,后续替换为 MySQL 实现。
37
+ */
38
+ export class InMemoryTaskRepository {
39
+ store = new Map();
40
+ async save(task) {
41
+ this.store.set(task.id, { ...task });
42
+ }
43
+ async findById(id) {
44
+ const record = this.store.get(id);
45
+ return record ? { ...record } : null;
46
+ }
47
+ async update(task) {
48
+ this.store.set(task.id, { ...task });
49
+ }
50
+ }
51
+ // ─────────────────────────────────────────────
52
+ // TaskService Implementation
53
+ // ─────────────────────────────────────────────
54
+ export class TaskService {
55
+ repository;
56
+ progressTracker;
57
+ constructor(repository, progressTracker) {
58
+ this.repository = repository ?? new InMemoryTaskRepository();
59
+ this.progressTracker = progressTracker ?? new TaskProgressTracker();
60
+ }
61
+ /**
62
+ * 获取内部 progressTracker 实例(供 Graph 引擎更新节点进度)
63
+ */
64
+ getProgressTracker() {
65
+ return this.progressTracker;
66
+ }
67
+ /**
68
+ * 创建新 Task,初始状态为 pending
69
+ */
70
+ async create(params) {
71
+ const now = new Date().toISOString();
72
+ const id = params.id?.trim() || randomUUID();
73
+ // 上游复用 id 时禁止静默覆盖已有 Task
74
+ if (params.id?.trim()) {
75
+ const existing = await this.repository.findById(id);
76
+ if (existing && !existing.isDeleted) {
77
+ throw new Error(`Task already exists: ${id}`);
78
+ }
79
+ }
80
+ const task = {
81
+ id,
82
+ agentId: params.agentId,
83
+ sessionId: params.sessionId,
84
+ userId: params.userId,
85
+ correlationId: params.correlationId,
86
+ input: params.input,
87
+ output: null,
88
+ status: 'pending',
89
+ traceId: null,
90
+ tokenUsage: [],
91
+ cost: 0,
92
+ startedAt: null,
93
+ completedAt: null,
94
+ createdBy: params.userId,
95
+ createdAt: now,
96
+ updatedBy: params.userId,
97
+ updatedAt: now,
98
+ isDeleted: false,
99
+ };
100
+ await this.repository.save(task);
101
+ return task;
102
+ }
103
+ /**
104
+ * 获取完整 Task 记录(供 AgentRuntime.resumeHitl / fork 使用)
105
+ */
106
+ async getTask(taskId) {
107
+ return this.repository.findById(taskId);
108
+ }
109
+ /**
110
+ * 更新 Task 状态
111
+ *
112
+ * 验证状态流转合法性,设置时间戳:
113
+ * - pending→running: 设置 startedAt
114
+ * - running→终态: 设置 completedAt 和 output
115
+ */
116
+ async updateStatus(taskId, status, output) {
117
+ const task = await this.findTaskOrThrow(taskId);
118
+ if (!this.isValidTransition(task.status, status)) {
119
+ throw new Error(`Invalid state transition: cannot transition from '${task.status}' to '${status}' for task '${taskId}'`);
120
+ }
121
+ const now = new Date().toISOString();
122
+ task.status = status;
123
+ if (status === 'running') {
124
+ task.startedAt = now;
125
+ }
126
+ // waiting_hitl:写入 output(含 hitlThreadId)供冷恢复;非终态、不设 completedAt
127
+ if (status === 'waiting_hitl' && output !== undefined) {
128
+ task.output = output;
129
+ }
130
+ if (status === 'success' || status === 'failed' || status === 'timeout' || status === 'token_exhausted') {
131
+ task.completedAt = now;
132
+ if (output !== undefined) {
133
+ task.output = output;
134
+ }
135
+ // 终态时清理进度跟踪
136
+ this.progressTracker.removeProgress(taskId);
137
+ }
138
+ await this.repository.update(task);
139
+ }
140
+ /**
141
+ * 仅当当前状态为 `from` 时流转。并发下 timeout/resume 抢占时返回 false,不抛错。
142
+ */
143
+ async tryUpdateStatus(taskId, from, to, output) {
144
+ const task = await this.repository.findById(taskId);
145
+ if (!task || task.isDeleted || task.status !== from) {
146
+ return false;
147
+ }
148
+ if (!this.isValidTransition(from, to)) {
149
+ return false;
150
+ }
151
+ await this.updateStatus(taskId, to, output);
152
+ return true;
153
+ }
154
+ /**
155
+ * 获取 Task 当前状态信息(供轮询使用)
156
+ *
157
+ * 优先返回 progressTracker 中的显式进度,回退到基于状态的粗粒度计算。
158
+ */
159
+ async getStatus(taskId) {
160
+ const task = await this.findTaskOrThrow(taskId);
161
+ const trackedProgress = this.progressTracker.getProgress(taskId);
162
+ const progress = trackedProgress !== null
163
+ ? trackedProgress.progress
164
+ : this.calculateProgress(task.status);
165
+ const duration = this.calculateDuration(task);
166
+ return {
167
+ status: task.status,
168
+ progress,
169
+ startedAt: task.startedAt,
170
+ duration,
171
+ };
172
+ }
173
+ /**
174
+ * 记录一次 Token 消耗,累加到 Task 的 tokenUsage 和 cost
175
+ */
176
+ async recordTokenUsage(taskId, usage) {
177
+ const task = await this.findTaskOrThrow(taskId);
178
+ task.tokenUsage.push(usage);
179
+ task.cost += usage.costEstimate;
180
+ await this.repository.update(task);
181
+ }
182
+ /**
183
+ * 更新 Task 执行进度(用于长任务轮询)
184
+ *
185
+ * 进度值会被 clamp 到 0-100 范围。仅 running 状态的 Task 可更新进度。
186
+ */
187
+ async updateProgress(taskId, progress) {
188
+ const task = await this.findTaskOrThrow(taskId);
189
+ if (task.status !== 'running') {
190
+ throw new Error(`Cannot update progress for task '${taskId}' in '${task.status}' status (must be 'running')`);
191
+ }
192
+ this.progressTracker.updateProgress(taskId, progress);
193
+ }
194
+ // ─────────────────────────────────────────────
195
+ // Private Helpers
196
+ // ─────────────────────────────────────────────
197
+ async findTaskOrThrow(taskId) {
198
+ const task = await this.repository.findById(taskId);
199
+ if (!task) {
200
+ throw new Error(`Task not found: '${taskId}'`);
201
+ }
202
+ return task;
203
+ }
204
+ isValidTransition(from, to) {
205
+ return VALID_TRANSITIONS[from]?.includes(to) ?? false;
206
+ }
207
+ calculateProgress(status) {
208
+ switch (status) {
209
+ case 'pending':
210
+ return 0;
211
+ case 'running':
212
+ return 50;
213
+ case 'success':
214
+ case 'failed':
215
+ case 'timeout':
216
+ case 'token_exhausted':
217
+ return 100;
218
+ default:
219
+ return 0;
220
+ }
221
+ }
222
+ calculateDuration(task) {
223
+ if (!task.startedAt) {
224
+ return 0;
225
+ }
226
+ const start = new Date(task.startedAt).getTime();
227
+ if (task.completedAt) {
228
+ return new Date(task.completedAt).getTime() - start;
229
+ }
230
+ // 仍在运行中,返回到当前的时长
231
+ return Date.now() - start;
232
+ }
233
+ }
@@ -0,0 +1,145 @@
1
+ /**
2
+ * CompressionBudgetIntegration — 压缩与预算集成
3
+ *
4
+ * 将 CompressionMiddleware 与 ContextWindowBudget 集成,
5
+ * 实现基于 Token 预算的自动压缩触发。
6
+ *
7
+ * @see context-window-budget.ts 上下文窗口预算
8
+ * @see compression-middleware.ts 压缩中间件
9
+ */
10
+ import type { MessageRecord } from '../session/session.service.js';
11
+ import type { ILLMProvider } from '../graph/nodes/llm-node.js';
12
+ import type { ContextSource } from './context-window-budget.js';
13
+ import type { ICompressionRepository } from '../memory/compression/compression.repository.js';
14
+ import type { IMessageRepository } from '../session/session.service.js';
15
+ /**
16
+ * 集成配置
17
+ */
18
+ export interface CompressionBudgetConfig {
19
+ /** 模型 context window 大小 */
20
+ modelContextWindow: number;
21
+ /** 历史消息占比阈值(超过此比例触发压缩,默认 0.8) */
22
+ historyThreshold?: number;
23
+ /** 压缩后目标占比(默认 0.5) */
24
+ targetRatio?: number;
25
+ /** 是否启用自动压缩(默认 true) */
26
+ autoCompress?: boolean;
27
+ /** LLM 配置 */
28
+ llmConfig?: {
29
+ provider?: ILLMProvider;
30
+ model?: string;
31
+ temperature?: number;
32
+ maxTokens?: number;
33
+ };
34
+ }
35
+ /**
36
+ * 预算检查结果
37
+ */
38
+ export interface BudgetCheckResult {
39
+ /** 是否需要压缩 */
40
+ needsCompression: boolean;
41
+ /** 当前历史消息 Token 数 */
42
+ currentTokens: number;
43
+ /** 历史消息 Token 上限 */
44
+ maxTokens: number;
45
+ /** 使用率 */
46
+ usageRatio: number;
47
+ /** 压缩后目标 Token 数 */
48
+ targetTokens?: number;
49
+ }
50
+ /**
51
+ * 压缩执行结果
52
+ */
53
+ export interface CompressionExecutionResult {
54
+ /** 是否执行了压缩 */
55
+ compressed: boolean;
56
+ /** 原始消息数 */
57
+ originalCount: number;
58
+ /** 压缩后消息数 */
59
+ compressedCount?: number;
60
+ /** 原始 Token 数 */
61
+ originalTokens: number;
62
+ /** 压缩后 Token 数 */
63
+ compressedTokens?: number;
64
+ /** 压缩率 */
65
+ compressionRatio?: number;
66
+ /** 压缩耗时(毫秒) */
67
+ durationMs?: number;
68
+ }
69
+ /**
70
+ * CompressionBudgetIntegration — 压缩与预算集成服务
71
+ *
72
+ * 功能:
73
+ * 1. 监控历史消息的 Token 使用情况
74
+ * 2. 当历史消息超出预算阈值时自动触发压缩
75
+ * 3. 压缩后确保历史消息在预算范围内
76
+ */
77
+ export declare class CompressionBudgetIntegration {
78
+ private readonly budget;
79
+ private readonly compression;
80
+ private readonly config;
81
+ constructor(config: CompressionBudgetConfig, repository?: ICompressionRepository, messageRepository?: IMessageRepository);
82
+ /**
83
+ * 检查历史消息是否需要压缩
84
+ *
85
+ * @param messages - 历史消息列表
86
+ * @returns 预算检查结果
87
+ */
88
+ checkBudget(messages: MessageRecord[]): BudgetCheckResult;
89
+ /**
90
+ * 处理历史消息(自动压缩)
91
+ *
92
+ * @param messages - 原始历史消息
93
+ * @param context - 上下文信息
94
+ * @returns 处理后的消息列表
95
+ */
96
+ processHistory(messages: MessageRecord[], context: {
97
+ sessionId: string;
98
+ taskId?: string;
99
+ userId: string;
100
+ }): Promise<{
101
+ messages: MessageRecord[];
102
+ result: CompressionExecutionResult;
103
+ }>;
104
+ /**
105
+ * 获取预算分配情况
106
+ *
107
+ * @param usage - 各来源的已使用 Token 数
108
+ * @returns 预算分配结果
109
+ */
110
+ getBudgetAllocation(usage?: Partial<Record<ContextSource, number>>): import("./context-window-budget.js").BudgetAllocation;
111
+ /**
112
+ * 获取配置
113
+ */
114
+ getConfig(): {
115
+ modelContextWindow: number;
116
+ historyThreshold: number;
117
+ targetRatio: number;
118
+ autoCompress: boolean;
119
+ llmConfig?: CompressionBudgetConfig["llmConfig"];
120
+ };
121
+ /**
122
+ * MessageRecord 转 GraphMessage
123
+ */
124
+ private toGraphMessages;
125
+ }
126
+ /**
127
+ * 创建压缩预算集成服务
128
+ *
129
+ * @param config - 配置
130
+ * @param repository - 压缩记录存储(可选)
131
+ * @param messageRepository - 消息存储(可选)
132
+ * @returns CompressionBudgetIntegration 实例
133
+ */
134
+ export declare function createCompressionBudgetIntegration(config: CompressionBudgetConfig, repository?: ICompressionRepository, messageRepository?: IMessageRepository): CompressionBudgetIntegration;
135
+ /**
136
+ * 创建带 LLM 能力的压缩预算集成服务
137
+ *
138
+ * @param provider - ILLMProvider 实例
139
+ * @param modelContextWindow - 模型 context window 大小
140
+ * @param config - 可选配置
141
+ * @param repository - 压缩记录存储(可选)
142
+ * @param messageRepository - 消息存储(可选)
143
+ * @returns CompressionBudgetIntegration 实例
144
+ */
145
+ export declare function createCompressionBudgetIntegrationWithLLM(provider: ILLMProvider, modelContextWindow: number, config?: Partial<CompressionBudgetConfig>, repository?: ICompressionRepository, messageRepository?: IMessageRepository): CompressionBudgetIntegration;
@@ -0,0 +1,185 @@
1
+ /**
2
+ * CompressionBudgetIntegration — 压缩与预算集成
3
+ *
4
+ * 将 CompressionMiddleware 与 ContextWindowBudget 集成,
5
+ * 实现基于 Token 预算的自动压缩触发。
6
+ *
7
+ * @see context-window-budget.ts 上下文窗口预算
8
+ * @see compression-middleware.ts 压缩中间件
9
+ */
10
+ import { createContextBudget } from './context-window-budget.js';
11
+ import { CompressionMiddleware, createCompressionMiddlewareWithLLM, } from '../session/compression-middleware.js';
12
+ import { estimateMessagesTokens } from '../memory/message-compression.service.js';
13
+ // ─────────────────────────────────────────────
14
+ // CompressionBudgetIntegration
15
+ // ─────────────────────────────────────────────
16
+ /**
17
+ * CompressionBudgetIntegration — 压缩与预算集成服务
18
+ *
19
+ * 功能:
20
+ * 1. 监控历史消息的 Token 使用情况
21
+ * 2. 当历史消息超出预算阈值时自动触发压缩
22
+ * 3. 压缩后确保历史消息在预算范围内
23
+ */
24
+ export class CompressionBudgetIntegration {
25
+ budget;
26
+ compression;
27
+ config;
28
+ constructor(config, repository, messageRepository) {
29
+ this.config = {
30
+ modelContextWindow: config.modelContextWindow,
31
+ historyThreshold: config.historyThreshold ?? 0.8,
32
+ targetRatio: config.targetRatio ?? 0.5,
33
+ autoCompress: config.autoCompress ?? true,
34
+ llmConfig: config.llmConfig,
35
+ };
36
+ // 创建预算管理器
37
+ this.budget = createContextBudget(this.config.modelContextWindow);
38
+ // 创建压缩中间件
39
+ if (this.config.llmConfig?.provider) {
40
+ this.compression = createCompressionMiddlewareWithLLM(this.config.llmConfig.provider, {
41
+ llmConfig: this.config.llmConfig,
42
+ }, repository, messageRepository);
43
+ }
44
+ else {
45
+ this.compression = new CompressionMiddleware({}, undefined, repository, messageRepository);
46
+ }
47
+ }
48
+ /**
49
+ * 检查历史消息是否需要压缩
50
+ *
51
+ * @param messages - 历史消息列表
52
+ * @returns 预算检查结果
53
+ */
54
+ checkBudget(messages) {
55
+ // 估算当前 Token 数
56
+ const graphMessages = this.toGraphMessages(messages);
57
+ const currentTokens = estimateMessagesTokens(graphMessages);
58
+ // 获取历史消息的 Token 上限
59
+ const maxTokens = this.budget.getMaxTokens('history');
60
+ // 计算使用率
61
+ const usageRatio = maxTokens > 0 ? currentTokens / maxTokens : 0;
62
+ // 检查是否超过阈值
63
+ const needsCompression = usageRatio > this.config.historyThreshold;
64
+ // 计算压缩目标
65
+ const targetTokens = needsCompression
66
+ ? Math.floor(maxTokens * this.config.targetRatio)
67
+ : undefined;
68
+ return {
69
+ needsCompression,
70
+ currentTokens,
71
+ maxTokens,
72
+ usageRatio,
73
+ targetTokens,
74
+ };
75
+ }
76
+ /**
77
+ * 处理历史消息(自动压缩)
78
+ *
79
+ * @param messages - 原始历史消息
80
+ * @param context - 上下文信息
81
+ * @returns 处理后的消息列表
82
+ */
83
+ async processHistory(messages, context) {
84
+ // 检查预算
85
+ const budgetCheck = this.checkBudget(messages);
86
+ // 如果不需要压缩或未启用自动压缩,直接返回
87
+ if (!budgetCheck.needsCompression || !this.config.autoCompress) {
88
+ return {
89
+ messages,
90
+ result: {
91
+ compressed: false,
92
+ originalCount: messages.length,
93
+ originalTokens: budgetCheck.currentTokens,
94
+ },
95
+ };
96
+ }
97
+ // 执行压缩
98
+ const startTime = Date.now();
99
+ const compressedMessages = await this.compression.processMessages(messages, context);
100
+ const duration = Date.now() - startTime;
101
+ // 计算压缩后的 Token 数
102
+ const compressedGraphMessages = this.toGraphMessages(compressedMessages);
103
+ const compressedTokens = estimateMessagesTokens(compressedGraphMessages);
104
+ // 计算压缩率
105
+ const compressionRatio = budgetCheck.currentTokens > 0
106
+ ? compressedTokens / budgetCheck.currentTokens
107
+ : 1;
108
+ return {
109
+ messages: compressedMessages,
110
+ result: {
111
+ compressed: true,
112
+ originalCount: messages.length,
113
+ compressedCount: compressedMessages.length,
114
+ originalTokens: budgetCheck.currentTokens,
115
+ compressedTokens,
116
+ compressionRatio,
117
+ durationMs: duration,
118
+ },
119
+ };
120
+ }
121
+ /**
122
+ * 获取预算分配情况
123
+ *
124
+ * @param usage - 各来源的已使用 Token 数
125
+ * @returns 预算分配结果
126
+ */
127
+ getBudgetAllocation(usage) {
128
+ return this.budget.calculateAllocation(usage ?? {});
129
+ }
130
+ /**
131
+ * 获取配置
132
+ */
133
+ getConfig() {
134
+ return { ...this.config };
135
+ }
136
+ // ─────────────────────────────────────────────
137
+ // Private
138
+ // ─────────────────────────────────────────────
139
+ /**
140
+ * MessageRecord 转 GraphMessage
141
+ */
142
+ toGraphMessages(messages) {
143
+ return messages.map((m) => ({
144
+ role: m.role,
145
+ content: m.content,
146
+ toolCalls: m.toolCalls,
147
+ }));
148
+ }
149
+ }
150
+ // ─────────────────────────────────────────────
151
+ // 工厂函数
152
+ // ─────────────────────────────────────────────
153
+ /**
154
+ * 创建压缩预算集成服务
155
+ *
156
+ * @param config - 配置
157
+ * @param repository - 压缩记录存储(可选)
158
+ * @param messageRepository - 消息存储(可选)
159
+ * @returns CompressionBudgetIntegration 实例
160
+ */
161
+ export function createCompressionBudgetIntegration(config, repository, messageRepository) {
162
+ return new CompressionBudgetIntegration(config, repository, messageRepository);
163
+ }
164
+ /**
165
+ * 创建带 LLM 能力的压缩预算集成服务
166
+ *
167
+ * @param provider - ILLMProvider 实例
168
+ * @param modelContextWindow - 模型 context window 大小
169
+ * @param config - 可选配置
170
+ * @param repository - 压缩记录存储(可选)
171
+ * @param messageRepository - 消息存储(可选)
172
+ * @returns CompressionBudgetIntegration 实例
173
+ */
174
+ export function createCompressionBudgetIntegrationWithLLM(provider, modelContextWindow, config, repository, messageRepository) {
175
+ return new CompressionBudgetIntegration({
176
+ ...config,
177
+ modelContextWindow,
178
+ llmConfig: {
179
+ provider,
180
+ model: config?.llmConfig?.model ?? 'DeepSeek-V4-Pro',
181
+ temperature: config?.llmConfig?.temperature ?? 0.3,
182
+ maxTokens: config?.llmConfig?.maxTokens ?? 1024,
183
+ },
184
+ }, repository, messageRepository);
185
+ }
@@ -0,0 +1,113 @@
1
+ /**
2
+ * ContextWindowBudget — 上下文窗口预算分配
3
+ *
4
+ * 管理上下文窗口的 Token 分配,防止单一来源占满上下文。
5
+ * 支持配置历史消息、RAG 结果、Tool Schema 各占上下文窗口的比例上限。
6
+ *
7
+ * @see requirements.md Requirement 12.5
8
+ * @see token/token-budget.service.ts Token Budget 控制
9
+ */
10
+ /**
11
+ * 上下文来源类型
12
+ */
13
+ export type ContextSource = 'history' | 'rag' | 'tools' | 'system' | 'memory';
14
+ /**
15
+ * 上下文窗口预算配置
16
+ */
17
+ export interface ContextWindowBudgetConfig {
18
+ /** 模型 context window 总 Token 数 */
19
+ totalTokens: number;
20
+ /** 各来源的 Token 比例上限 */
21
+ sourceRatios: Record<ContextSource, number>;
22
+ /** 预留给模型输出的 Token 数(默认 20%) */
23
+ outputReserve: number;
24
+ }
25
+ /**
26
+ * 默认上下文窗口预算配置
27
+ */
28
+ export declare const DEFAULT_CONTEXT_BUDGET_CONFIG: ContextWindowBudgetConfig;
29
+ /**
30
+ * 来源 Token 分配
31
+ */
32
+ export interface SourceAllocation {
33
+ /** 来源类型 */
34
+ source: ContextSource;
35
+ /** 分配的 Token 上限 */
36
+ maxTokens: number;
37
+ /** 已使用的 Token 数 */
38
+ usedTokens: number;
39
+ /** 剩余可用 Token 数 */
40
+ remainingTokens: number;
41
+ /** 使用率(0-1) */
42
+ usageRatio: number;
43
+ }
44
+ /**
45
+ * 预算分配结果
46
+ */
47
+ export interface BudgetAllocation {
48
+ /** 总 Token 数 */
49
+ totalTokens: number;
50
+ /** 可用 Token 数(扣除输出预留) */
51
+ availableTokens: number;
52
+ /** 各来源的分配情况 */
53
+ sources: SourceAllocation[];
54
+ /** 是否超限 */
55
+ isExceeded: boolean;
56
+ /** 超限的来源列表 */
57
+ exceededSources: ContextSource[];
58
+ }
59
+ /**
60
+ * ContextWindowBudget — 上下文窗口预算管理
61
+ */
62
+ export declare class ContextWindowBudget {
63
+ private readonly config;
64
+ constructor(config?: Partial<ContextWindowBudgetConfig>);
65
+ /**
66
+ * 获取指定来源的 Token 上限
67
+ *
68
+ * @param source - 来源类型
69
+ * @returns Token 上限
70
+ */
71
+ getMaxTokens(source: ContextSource): number;
72
+ /**
73
+ * 检查指定来源是否超限
74
+ *
75
+ * @param source - 来源类型
76
+ * @param usedTokens - 已使用的 Token 数
77
+ * @returns 是否超限
78
+ */
79
+ isExceeded(source: ContextSource, usedTokens: number): boolean;
80
+ /**
81
+ * 计算预算分配
82
+ *
83
+ * @param usage - 各来源的已使用 Token 数
84
+ * @returns 预算分配结果
85
+ */
86
+ calculateAllocation(usage: Partial<Record<ContextSource, number>>): BudgetAllocation;
87
+ /**
88
+ * 裁剪消息以符合预算
89
+ *
90
+ * 如果历史消息超出预算,从前面开始删除旧消息。
91
+ *
92
+ * @param messages - 原始消息列表
93
+ * @param maxTokens - Token 上限
94
+ * @param estimateFn - Token 估算函数
95
+ * @returns 裁剪后的消息列表
96
+ */
97
+ trimMessages<T extends {
98
+ role: string;
99
+ content: string;
100
+ }>(messages: T[], maxTokens: number, estimateFn: (messages: T[]) => number): T[];
101
+ /**
102
+ * 获取配置
103
+ */
104
+ getConfig(): ContextWindowBudgetConfig;
105
+ }
106
+ /**
107
+ * 创建上下文窗口预算实例
108
+ *
109
+ * @param modelContextWindow - 模型的 context window 大小
110
+ * @param config - 可选的自定义配置
111
+ * @returns ContextWindowBudget 实例
112
+ */
113
+ export declare function createContextBudget(modelContextWindow: number, config?: Partial<ContextWindowBudgetConfig>): ContextWindowBudget;