@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.
- package/README.md +323 -0
- package/dist/api/handlers/index.d.ts +3 -0
- package/dist/api/handlers/index.js +4 -0
- package/dist/api/handlers/invoke.handler.d.ts +77 -0
- package/dist/api/handlers/invoke.handler.js +411 -0
- package/dist/api/handlers/messages.handler.d.ts +53 -0
- package/dist/api/handlers/messages.handler.js +80 -0
- package/dist/api/handlers/stream.handler.d.ts +92 -0
- package/dist/api/handlers/stream.handler.js +432 -0
- package/dist/api/index.d.ts +3 -0
- package/dist/api/index.js +4 -0
- package/dist/api/middleware/auth.middleware.d.ts +96 -0
- package/dist/api/middleware/auth.middleware.js +158 -0
- package/dist/api/middleware/index.d.ts +1 -0
- package/dist/api/middleware/index.js +2 -0
- package/dist/api/routes/agent.routes.d.ts +44 -0
- package/dist/api/routes/agent.routes.js +204 -0
- package/dist/api/routes/index.d.ts +3 -0
- package/dist/api/routes/index.js +4 -0
- package/dist/api/routes/session.routes.d.ts +82 -0
- package/dist/api/routes/session.routes.js +169 -0
- package/dist/api/routes/task.routes.d.ts +75 -0
- package/dist/api/routes/task.routes.js +108 -0
- package/dist/checkpoint/checkpoint-serializer.d.ts +58 -0
- package/dist/checkpoint/checkpoint-serializer.js +81 -0
- package/dist/checkpoint/composite-checkpoint-saver.d.ts +42 -0
- package/dist/checkpoint/composite-checkpoint-saver.js +118 -0
- package/dist/checkpoint/contracts/checkpoint-saver.contract.d.ts +65 -0
- package/dist/checkpoint/contracts/checkpoint-saver.contract.js +12 -0
- package/dist/checkpoint/contracts/index.d.ts +1 -0
- package/dist/checkpoint/contracts/index.js +1 -0
- package/dist/checkpoint/file-checkpoint-saver.d.ts +19 -0
- package/dist/checkpoint/file-checkpoint-saver.js +98 -0
- package/dist/checkpoint/hybrid-checkpoint-saver.d.ts +130 -0
- package/dist/checkpoint/hybrid-checkpoint-saver.js +211 -0
- package/dist/checkpoint/in-memory-checkpoint-saver.d.ts +14 -0
- package/dist/checkpoint/in-memory-checkpoint-saver.js +46 -0
- package/dist/checkpoint/index.d.ts +16 -0
- package/dist/checkpoint/index.js +13 -0
- package/dist/checkpoint/mongo-checkpoint-saver.d.ts +38 -0
- package/dist/checkpoint/mongo-checkpoint-saver.js +56 -0
- package/dist/checkpoint/pg-checkpoint-saver.d.ts +59 -0
- package/dist/checkpoint/pg-checkpoint-saver.js +140 -0
- package/dist/checkpoint/redis-checkpoint-saver.d.ts +68 -0
- package/dist/checkpoint/redis-checkpoint-saver.js +173 -0
- package/dist/checkpoint/restore-checkpoint.d.ts +33 -0
- package/dist/checkpoint/restore-checkpoint.js +33 -0
- package/dist/common/agent-code.d.ts +10 -0
- package/dist/common/agent-code.js +12 -0
- package/dist/common/concurrency.d.ts +79 -0
- package/dist/common/concurrency.js +121 -0
- package/dist/common/health.d.ts +40 -0
- package/dist/common/health.js +37 -0
- package/dist/common/index.d.ts +5 -0
- package/dist/common/index.js +5 -0
- package/dist/common/logger.d.ts +34 -0
- package/dist/common/logger.js +38 -0
- package/dist/common/queue-consumer.d.ts +125 -0
- package/dist/common/queue-consumer.js +159 -0
- package/dist/common/trace-id.d.ts +2 -0
- package/dist/common/trace-id.js +8 -0
- package/dist/common/types.d.ts +104 -0
- package/dist/common/types.js +14 -0
- package/dist/contracts/index.d.ts +11 -0
- package/dist/contracts/index.js +10 -0
- package/dist/contracts/permission-checker.d.ts +10 -0
- package/dist/contracts/permission-checker.js +4 -0
- package/dist/contracts/trace-collector.d.ts +211 -0
- package/dist/contracts/trace-collector.js +13 -0
- package/dist/governance/governance-client.d.ts +38 -0
- package/dist/governance/governance-client.js +95 -0
- package/dist/governance/index.d.ts +7 -0
- package/dist/governance/index.js +5 -0
- package/dist/governance/permission-guard.d.ts +19 -0
- package/dist/governance/permission-guard.js +59 -0
- package/dist/graph/adapters/index.d.ts +3 -0
- package/dist/graph/adapters/index.js +3 -0
- package/dist/graph/adapters/langgraph-checkpointer.d.ts +40 -0
- package/dist/graph/adapters/langgraph-checkpointer.js +211 -0
- package/dist/graph/adapters/langgraph.adapter.d.ts +190 -0
- package/dist/graph/adapters/langgraph.adapter.js +1303 -0
- package/dist/graph/adapters/subgraph-compiler.d.ts +39 -0
- package/dist/graph/adapters/subgraph-compiler.js +248 -0
- package/dist/graph/condition-evaluator.d.ts +57 -0
- package/dist/graph/condition-evaluator.js +162 -0
- package/dist/graph/contracts/executable-graph.d.ts +340 -0
- package/dist/graph/contracts/executable-graph.js +10 -0
- package/dist/graph/contracts/index.d.ts +2 -0
- package/dist/graph/contracts/index.js +2 -0
- package/dist/graph/contracts/state-graph.contract.d.ts +76 -0
- package/dist/graph/contracts/state-graph.contract.js +11 -0
- package/dist/graph/hitl/hitl-handler.d.ts +199 -0
- package/dist/graph/hitl/hitl-handler.js +480 -0
- package/dist/graph/hitl/index.d.ts +1 -0
- package/dist/graph/hitl/index.js +1 -0
- package/dist/graph/index.d.ts +7 -0
- package/dist/graph/index.js +7 -0
- package/dist/graph/nodes/index.d.ts +2 -0
- package/dist/graph/nodes/index.js +2 -0
- package/dist/graph/nodes/llm-node.d.ts +182 -0
- package/dist/graph/nodes/llm-node.js +281 -0
- package/dist/graph/nodes/skill-bind-node.d.ts +32 -0
- package/dist/graph/nodes/skill-bind-node.js +116 -0
- package/dist/graph/nodes/tool-node.d.ts +75 -0
- package/dist/graph/nodes/tool-node.js +324 -0
- package/dist/graph/resolve-graph-prompt.d.ts +5 -0
- package/dist/graph/resolve-graph-prompt.js +75 -0
- package/dist/graph/retry/budget-aware-retry.d.ts +91 -0
- package/dist/graph/retry/budget-aware-retry.js +126 -0
- package/dist/graph/retry/index.d.ts +9 -0
- package/dist/graph/retry/index.js +8 -0
- package/dist/graph/retry/node-retry.d.ts +123 -0
- package/dist/graph/retry/node-retry.js +235 -0
- package/dist/graph/skill-audit-recorder.d.ts +126 -0
- package/dist/graph/skill-audit-recorder.js +114 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +32 -0
- package/dist/memory/compression/compression-stats.d.ts +109 -0
- package/dist/memory/compression/compression-stats.js +144 -0
- package/dist/memory/compression/compression.repository.d.ts +62 -0
- package/dist/memory/compression/compression.repository.js +71 -0
- package/dist/memory/compression/index.d.ts +10 -0
- package/dist/memory/compression/index.js +15 -0
- package/dist/memory/compression/llm-summarize.d.ts +58 -0
- package/dist/memory/compression/llm-summarize.js +192 -0
- package/dist/memory/compression/sliding-window.compression.d.ts +60 -0
- package/dist/memory/compression/sliding-window.compression.js +175 -0
- package/dist/memory/index.d.ts +4 -0
- package/dist/memory/index.js +7 -0
- package/dist/memory/long-term-memory.service.d.ts +94 -0
- package/dist/memory/long-term-memory.service.js +120 -0
- package/dist/memory/message-compression.service.d.ts +128 -0
- package/dist/memory/message-compression.service.js +69 -0
- package/dist/memory/pg-memory.repository.d.ts +44 -0
- package/dist/memory/pg-memory.repository.js +108 -0
- package/dist/memory/semantic-retrieval.service.d.ts +148 -0
- package/dist/memory/semantic-retrieval.service.js +238 -0
- package/dist/providers/echo-llm-provider.d.ts +10 -0
- package/dist/providers/echo-llm-provider.js +87 -0
- package/dist/providers/http-llm-provider.d.ts +35 -0
- package/dist/providers/http-llm-provider.js +404 -0
- package/dist/providers/index.d.ts +7 -0
- package/dist/providers/index.js +5 -0
- package/dist/providers/local-llm-provider.d.ts +27 -0
- package/dist/providers/local-llm-provider.js +105 -0
- package/dist/providers/resolve-llm-model.d.ts +13 -0
- package/dist/providers/resolve-llm-model.js +30 -0
- package/dist/providers/routing-llm-provider.d.ts +28 -0
- package/dist/providers/routing-llm-provider.js +79 -0
- package/dist/registry/agent-models.d.ts +1 -0
- package/dist/registry/agent-models.js +1 -0
- package/dist/registry/agent-registry-client.d.ts +56 -0
- package/dist/registry/agent-registry-client.js +36 -0
- package/dist/registry/definition-cache.d.ts +37 -0
- package/dist/registry/definition-cache.js +82 -0
- package/dist/registry/deployment-snapshot.d.ts +99 -0
- package/dist/registry/deployment-snapshot.js +542 -0
- package/dist/registry/graph-loader.d.ts +134 -0
- package/dist/registry/graph-loader.js +985 -0
- package/dist/registry/index.d.ts +9 -0
- package/dist/registry/index.js +9 -0
- package/dist/registry/preload-errors.d.ts +13 -0
- package/dist/registry/preload-errors.js +35 -0
- package/dist/registry/preload-flags.d.ts +22 -0
- package/dist/registry/preload-flags.js +44 -0
- package/dist/registry/skill-io-guard.d.ts +25 -0
- package/dist/registry/skill-io-guard.js +98 -0
- package/dist/registry/skill-tree.d.ts +27 -0
- package/dist/registry/skill-tree.js +183 -0
- package/dist/runtime/agent-runtime.d.ts +106 -0
- package/dist/runtime/agent-runtime.js +777 -0
- package/dist/runtime/dev-runtime.d.ts +69 -0
- package/dist/runtime/dev-runtime.js +199 -0
- package/dist/runtime/index.d.ts +4 -0
- package/dist/runtime/index.js +3 -0
- package/dist/runtime/storage-profile.d.ts +50 -0
- package/dist/runtime/storage-profile.js +138 -0
- package/dist/runtime/types.d.ts +120 -0
- package/dist/runtime/types.js +9 -0
- package/dist/server.d.ts +12 -0
- package/dist/server.js +161 -0
- package/dist/session/compression-middleware.d.ts +126 -0
- package/dist/session/compression-middleware.js +230 -0
- package/dist/session/file-message.repository.d.ts +25 -0
- package/dist/session/file-message.repository.js +78 -0
- package/dist/session/file-session.repository.d.ts +72 -0
- package/dist/session/file-session.repository.js +212 -0
- package/dist/session/index.d.ts +13 -0
- package/dist/session/index.js +12 -0
- package/dist/session/message.service.d.ts +80 -0
- package/dist/session/message.service.js +128 -0
- package/dist/session/persist-turn-messages.d.ts +145 -0
- package/dist/session/persist-turn-messages.js +325 -0
- package/dist/session/pg-message.repository.d.ts +49 -0
- package/dist/session/pg-message.repository.js +149 -0
- package/dist/session/pg-session.repository.d.ts +46 -0
- package/dist/session/pg-session.repository.js +117 -0
- package/dist/session/session-context.service.d.ts +49 -0
- package/dist/session/session-context.service.js +66 -0
- package/dist/session/session.service.d.ts +194 -0
- package/dist/session/session.service.js +166 -0
- package/dist/sse/connection-event-logger.d.ts +21 -0
- package/dist/sse/connection-event-logger.js +33 -0
- package/dist/sse/contracts/index.d.ts +1 -0
- package/dist/sse/contracts/index.js +1 -0
- package/dist/sse/contracts/sse-emitter.contract.d.ts +74 -0
- package/dist/sse/contracts/sse-emitter.contract.js +11 -0
- package/dist/sse/event-buffer.d.ts +20 -0
- package/dist/sse/event-buffer.js +45 -0
- package/dist/sse/events/code-events.d.ts +19 -0
- package/dist/sse/events/code-events.js +9 -0
- package/dist/sse/events/collaboration-events.d.ts +37 -0
- package/dist/sse/events/collaboration-events.js +11 -0
- package/dist/sse/events/connection-events.d.ts +13 -0
- package/dist/sse/events/connection-events.js +9 -0
- package/dist/sse/events/file-events.d.ts +29 -0
- package/dist/sse/events/file-events.js +10 -0
- package/dist/sse/events/hitl-events.d.ts +33 -0
- package/dist/sse/events/hitl-events.js +10 -0
- package/dist/sse/events/index.d.ts +107 -0
- package/dist/sse/events/index.js +96 -0
- package/dist/sse/events/plan-events.d.ts +38 -0
- package/dist/sse/events/plan-events.js +11 -0
- package/dist/sse/events/reasoning-events.d.ts +35 -0
- package/dist/sse/events/reasoning-events.js +13 -0
- package/dist/sse/events/response-events.d.ts +25 -0
- package/dist/sse/events/response-events.js +12 -0
- package/dist/sse/events/session-events.d.ts +43 -0
- package/dist/sse/events/session-events.js +12 -0
- package/dist/sse/events/skill-events.d.ts +48 -0
- package/dist/sse/events/skill-events.js +11 -0
- package/dist/sse/events/stats-events.d.ts +44 -0
- package/dist/sse/events/stats-events.js +12 -0
- package/dist/sse/events/tool-events.d.ts +68 -0
- package/dist/sse/events/tool-events.js +14 -0
- package/dist/sse/index.d.ts +8 -0
- package/dist/sse/index.js +8 -0
- package/dist/sse/sse-connection-manager.d.ts +116 -0
- package/dist/sse/sse-connection-manager.js +185 -0
- package/dist/sse/sse-emitter.d.ts +108 -0
- package/dist/sse/sse-emitter.js +210 -0
- package/dist/sse/sse-heartbeat.d.ts +58 -0
- package/dist/sse/sse-heartbeat.js +76 -0
- package/dist/sse/trace-collector.d.ts +60 -0
- package/dist/sse/trace-collector.js +107 -0
- package/dist/task/contracts/index.d.ts +2 -0
- package/dist/task/contracts/index.js +1 -0
- package/dist/task/contracts/task-manager.contract.d.ts +160 -0
- package/dist/task/contracts/task-manager.contract.js +10 -0
- package/dist/task/index.d.ts +7 -0
- package/dist/task/index.js +5 -0
- package/dist/task/pg-task.repository.d.ts +47 -0
- package/dist/task/pg-task.repository.js +131 -0
- package/dist/task/task-progress-tracker.d.ts +67 -0
- package/dist/task/task-progress-tracker.js +80 -0
- package/dist/task/task-timeout.d.ts +70 -0
- package/dist/task/task-timeout.js +116 -0
- package/dist/task/task.service.d.ts +84 -0
- package/dist/task/task.service.js +233 -0
- package/dist/token/compression-budget-integration.d.ts +145 -0
- package/dist/token/compression-budget-integration.js +185 -0
- package/dist/token/context-window-budget.d.ts +113 -0
- package/dist/token/context-window-budget.js +134 -0
- package/dist/token/contracts/index.d.ts +1 -0
- package/dist/token/contracts/index.js +1 -0
- package/dist/token/contracts/token-budget.contract.d.ts +77 -0
- package/dist/token/contracts/token-budget.contract.js +11 -0
- package/dist/token/index.d.ts +12 -0
- package/dist/token/index.js +10 -0
- package/dist/token/pg-token-budget.repository.d.ts +39 -0
- package/dist/token/pg-token-budget.repository.js +116 -0
- package/dist/token/session-budget-checker.d.ts +54 -0
- package/dist/token/session-budget-checker.js +72 -0
- package/dist/token/token-budget-guard.d.ts +66 -0
- package/dist/token/token-budget-guard.js +97 -0
- package/dist/token/token-budget.service.d.ts +86 -0
- package/dist/token/token-budget.service.js +130 -0
- package/dist/token/token-detail-mode.d.ts +73 -0
- package/dist/token/token-detail-mode.js +107 -0
- package/dist/token/token-estimator.d.ts +80 -0
- package/dist/token/token-estimator.js +134 -0
- package/dist/token/token-stats.service.d.ts +88 -0
- package/dist/token/token-stats.service.js +94 -0
- package/dist/tool/create-tool-executor.d.ts +33 -0
- package/dist/tool/create-tool-executor.js +60 -0
- package/dist/tool/dev-http-executor.d.ts +18 -0
- package/dist/tool/dev-http-executor.js +96 -0
- package/dist/tool/dev-mcp-executor.d.ts +29 -0
- package/dist/tool/dev-mcp-executor.js +84 -0
- package/dist/tool/dev-tool-executor.d.ts +23 -0
- package/dist/tool/dev-tool-executor.js +55 -0
- package/dist/tool/file-artifact.d.ts +11 -0
- package/dist/tool/file-artifact.js +90 -0
- package/dist/tool/http-tool-executor.d.ts +17 -0
- package/dist/tool/http-tool-executor.js +158 -0
- package/dist/tool/index.d.ts +18 -0
- package/dist/tool/index.js +17 -0
- package/dist/tool/loaded-tool-definition.d.ts +35 -0
- package/dist/tool/loaded-tool-definition.js +9 -0
- package/dist/tool/local-mcp-client.d.ts +23 -0
- package/dist/tool/local-mcp-client.js +225 -0
- package/dist/tool/local-tool-executor.d.ts +37 -0
- package/dist/tool/local-tool-executor.js +249 -0
- package/dist/tool/mcp-tool-executor.d.ts +23 -0
- package/dist/tool/mcp-tool-executor.js +160 -0
- package/dist/tool/mock-tool-executor.d.ts +28 -0
- package/dist/tool/mock-tool-executor.js +65 -0
- package/dist/tool/system-prompt-builder.d.ts +114 -0
- package/dist/tool/system-prompt-builder.js +213 -0
- package/dist/tool/tool-confirmation.d.ts +29 -0
- package/dist/tool/tool-confirmation.js +81 -0
- package/dist/tool/tool-event-emitter.d.ts +58 -0
- package/dist/tool/tool-event-emitter.js +154 -0
- package/dist/tool/tool-execution-router.d.ts +25 -0
- package/dist/tool/tool-execution-router.js +50 -0
- package/dist/tool/tool-executor.interface.d.ts +85 -0
- package/dist/tool/tool-executor.interface.js +7 -0
- package/dist/tool/tool-orchestrator.d.ts +22 -0
- package/dist/tool/tool-orchestrator.js +104 -0
- package/dist/tool/tool-result-injector.d.ts +64 -0
- package/dist/tool/tool-result-injector.js +65 -0
- package/dist/utils/format-error.d.ts +4 -0
- package/dist/utils/format-error.js +4 -0
- package/dist/utils/http-error.d.ts +11 -0
- package/dist/utils/http-error.js +24 -0
- package/package.json +56 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSEEmitter — SSE 事件发射器实现
|
|
3
|
+
*
|
|
4
|
+
* 将 SSEEvent 格式化为 SSE 协议并推送到客户端 HTTP 响应流。
|
|
5
|
+
* 管理连接生命周期(connected → emit → close),支持心跳保活。
|
|
6
|
+
*
|
|
7
|
+
* @see contracts/sse-emitter.contract.ts ISSEEmitter 接口
|
|
8
|
+
* @see design.md §1.6 SSE事件协议定义
|
|
9
|
+
* @see requirements.md Requirement 5 AC1-AC5
|
|
10
|
+
* @see requirements.md Requirement 9 AC1-AC4
|
|
11
|
+
*/
|
|
12
|
+
import { SSEHeartbeat } from './sse-heartbeat.js';
|
|
13
|
+
/** SSEEmitterOptions 默认值 */
|
|
14
|
+
const DEFAULT_OPTIONS = {
|
|
15
|
+
heartbeatInterval: 30000,
|
|
16
|
+
setHeaders: true,
|
|
17
|
+
};
|
|
18
|
+
// ─────────────────────────────────────────────
|
|
19
|
+
// SSEEmitter 实现
|
|
20
|
+
// ─────────────────────────────────────────────
|
|
21
|
+
/**
|
|
22
|
+
* SSEEmitter — ISSEEmitter 实现类
|
|
23
|
+
*
|
|
24
|
+
* 用法:
|
|
25
|
+
* ```ts
|
|
26
|
+
* const emitter = new SSEEmitter(res, { heartbeatInterval: 30000 });
|
|
27
|
+
* emitter.emit({ type: 'task.started', data: {...}, correlationId, taskId, timestamp });
|
|
28
|
+
* emitter.heartbeat();
|
|
29
|
+
* emitter.close();
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export class SSEEmitter {
|
|
33
|
+
stream;
|
|
34
|
+
state = 'connected';
|
|
35
|
+
options;
|
|
36
|
+
heartbeatScheduler = null;
|
|
37
|
+
/** 最后发送的事件 ID */
|
|
38
|
+
lastEventId = null;
|
|
39
|
+
constructor(stream, options) {
|
|
40
|
+
this.stream = stream;
|
|
41
|
+
this.options = {
|
|
42
|
+
...DEFAULT_OPTIONS,
|
|
43
|
+
...options,
|
|
44
|
+
};
|
|
45
|
+
// 设置 SSE HTTP 响应头
|
|
46
|
+
if (this.options.setHeaders && this.isServerResponse(stream)) {
|
|
47
|
+
this.setSSEHeaders(stream);
|
|
48
|
+
}
|
|
49
|
+
// 监听流关闭/错误事件以更新连接状态
|
|
50
|
+
this.stream.on('close', () => {
|
|
51
|
+
this.stopHeartbeat();
|
|
52
|
+
this.state = 'disconnected';
|
|
53
|
+
});
|
|
54
|
+
this.stream.on('error', () => {
|
|
55
|
+
this.stopHeartbeat();
|
|
56
|
+
this.state = 'disconnected';
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* 发射单个 SSE 事件到客户端
|
|
61
|
+
*
|
|
62
|
+
* 格式(含 id 行):
|
|
63
|
+
* ```
|
|
64
|
+
* id: {eventId}
|
|
65
|
+
* event: {type}
|
|
66
|
+
* data: {"correlationId":"...", "taskId":"...", "timestamp":"...", ...data}
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
emit(event, eventId) {
|
|
70
|
+
if (this.state !== 'connected') {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (eventId) {
|
|
74
|
+
this.lastEventId = eventId;
|
|
75
|
+
}
|
|
76
|
+
const payload = this.formatEvent(event, eventId ?? this.lastEventId);
|
|
77
|
+
this.write(payload);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* 重连时回放断开期间的事件
|
|
81
|
+
*/
|
|
82
|
+
replayFrom(lastEventId, buffer) {
|
|
83
|
+
const events = buffer.getEventsSince(lastEventId);
|
|
84
|
+
for (const event of events) {
|
|
85
|
+
this.emit(event);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 关闭 SSE 连接
|
|
90
|
+
*
|
|
91
|
+
* 终止事件流并标记为断开。自动停止心跳定时器。调用后不可再 emit。
|
|
92
|
+
*/
|
|
93
|
+
close() {
|
|
94
|
+
if (this.state === 'disconnected') {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
this.stopHeartbeat();
|
|
98
|
+
this.state = 'disconnected';
|
|
99
|
+
if (!this.stream.destroyed) {
|
|
100
|
+
this.stream.end();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* 发送心跳事件保持连接活跃
|
|
105
|
+
*
|
|
106
|
+
* 推送 `connection.heartbeat` 事件,防止代理/LB 因空闲超时断开连接。
|
|
107
|
+
*/
|
|
108
|
+
heartbeat() {
|
|
109
|
+
if (this.state !== 'connected') {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const heartbeatEvent = {
|
|
113
|
+
type: 'connection.heartbeat',
|
|
114
|
+
data: { timestamp: new Date().toISOString() },
|
|
115
|
+
correlationId: this.options.correlationId ?? '',
|
|
116
|
+
taskId: this.options.taskId ?? '',
|
|
117
|
+
timestamp: new Date().toISOString(),
|
|
118
|
+
};
|
|
119
|
+
this.emit(heartbeatEvent);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* 启动自动周期心跳
|
|
123
|
+
*
|
|
124
|
+
* 按配置的 heartbeatInterval(默认 30s)定时发送心跳事件。
|
|
125
|
+
* 重复调用不会创建多个定时器。
|
|
126
|
+
*/
|
|
127
|
+
startHeartbeat() {
|
|
128
|
+
if (this.heartbeatScheduler !== null) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
this.heartbeatScheduler = new SSEHeartbeat(this, {
|
|
132
|
+
interval: this.options.heartbeatInterval,
|
|
133
|
+
});
|
|
134
|
+
this.heartbeatScheduler.start();
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* 停止自动周期心跳
|
|
138
|
+
*
|
|
139
|
+
* 清除心跳定时器。close() 时自动调用。
|
|
140
|
+
*/
|
|
141
|
+
stopHeartbeat() {
|
|
142
|
+
if (this.heartbeatScheduler !== null) {
|
|
143
|
+
this.heartbeatScheduler.stop();
|
|
144
|
+
this.heartbeatScheduler = null;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// ─────────────────────────────────────────────
|
|
148
|
+
// Public Accessors
|
|
149
|
+
// ─────────────────────────────────────────────
|
|
150
|
+
/** 获取当前连接状态 */
|
|
151
|
+
get connectionState() {
|
|
152
|
+
return this.state;
|
|
153
|
+
}
|
|
154
|
+
/** 是否处于连接状态 */
|
|
155
|
+
get isConnected() {
|
|
156
|
+
return this.state === 'connected';
|
|
157
|
+
}
|
|
158
|
+
// ─────────────────────────────────────────────
|
|
159
|
+
// Private Methods
|
|
160
|
+
// ─────────────────────────────────────────────
|
|
161
|
+
/**
|
|
162
|
+
* 将 SSEEvent 格式化为 SSE 协议字符串(含 id 行)
|
|
163
|
+
*/
|
|
164
|
+
formatEvent(event, eventId) {
|
|
165
|
+
const dataPayload = {
|
|
166
|
+
correlationId: event.correlationId,
|
|
167
|
+
taskId: event.taskId,
|
|
168
|
+
timestamp: event.timestamp,
|
|
169
|
+
...event.data,
|
|
170
|
+
};
|
|
171
|
+
const dataLine = JSON.stringify(dataPayload);
|
|
172
|
+
const idLine = eventId ? `id: ${eventId}\n` : '';
|
|
173
|
+
return `${idLine}event: ${event.type}\ndata: ${dataLine}\n\n`;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* 写入底层流,处理写入错误
|
|
177
|
+
*/
|
|
178
|
+
write(payload) {
|
|
179
|
+
try {
|
|
180
|
+
const canWrite = this.stream.write(payload);
|
|
181
|
+
if (!canWrite) {
|
|
182
|
+
// 背压:流缓冲区满,但不断开连接,等待 drain
|
|
183
|
+
// 对 SSE 场景,通常不需要特别处理背压
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
// 写入异常,标记为断开
|
|
188
|
+
this.state = 'disconnected';
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* 设置 SSE 特定的 HTTP 响应头
|
|
193
|
+
*/
|
|
194
|
+
setSSEHeaders(res) {
|
|
195
|
+
if (!res.headersSent) {
|
|
196
|
+
res.writeHead(200, {
|
|
197
|
+
'Content-Type': 'text/event-stream',
|
|
198
|
+
'Cache-Control': 'no-cache',
|
|
199
|
+
'Connection': 'keep-alive',
|
|
200
|
+
'X-Accel-Buffering': 'no', // 禁用 Nginx 缓冲
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* 类型守卫:判断是否为 ServerResponse
|
|
206
|
+
*/
|
|
207
|
+
isServerResponse(stream) {
|
|
208
|
+
return 'writeHead' in stream && typeof stream.writeHead === 'function';
|
|
209
|
+
}
|
|
210
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSEHeartbeat — 自动周期心跳调度器
|
|
3
|
+
*
|
|
4
|
+
* 管理 SSE 连接的定时心跳发送,防止代理/负载均衡器因空闲超时断开连接。
|
|
5
|
+
* 使用 setInterval 定时调用 emitter.heartbeat(),支持可配置间隔。
|
|
6
|
+
*
|
|
7
|
+
* @see design.md §1.6 connection.heartbeat 事件
|
|
8
|
+
* @see requirements.md Requirement 5 AC5
|
|
9
|
+
*/
|
|
10
|
+
import type { ISSEEmitter } from './contracts/index.js';
|
|
11
|
+
/**
|
|
12
|
+
* SSEHeartbeatOptions — 心跳调度器配置
|
|
13
|
+
*/
|
|
14
|
+
export interface SSEHeartbeatOptions {
|
|
15
|
+
/** 心跳间隔(毫秒),默认 30000 (30s) */
|
|
16
|
+
interval?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* SSEHeartbeat — 周期心跳调度器
|
|
20
|
+
*
|
|
21
|
+
* 用法:
|
|
22
|
+
* ```ts
|
|
23
|
+
* const emitter = new SSEEmitter(res);
|
|
24
|
+
* const heartbeat = new SSEHeartbeat(emitter, { interval: 30000 });
|
|
25
|
+
* heartbeat.start();
|
|
26
|
+
* // ... 业务逻辑 ...
|
|
27
|
+
* heartbeat.stop(); // 或 emitter.close() 时自动停止
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare class SSEHeartbeat {
|
|
31
|
+
private readonly emitter;
|
|
32
|
+
private readonly interval;
|
|
33
|
+
private timer;
|
|
34
|
+
constructor(emitter: ISSEEmitter, options?: SSEHeartbeatOptions);
|
|
35
|
+
/**
|
|
36
|
+
* 启动周期心跳
|
|
37
|
+
*
|
|
38
|
+
* 使用 setInterval 定时调用 emitter.heartbeat()。
|
|
39
|
+
* timer.unref() 防止心跳定时器阻塞进程退出。
|
|
40
|
+
* 重复调用 start() 不会创建多个定时器。
|
|
41
|
+
*/
|
|
42
|
+
start(): void;
|
|
43
|
+
/**
|
|
44
|
+
* 停止周期心跳
|
|
45
|
+
*
|
|
46
|
+
* 清除 setInterval 定时器,释放资源。
|
|
47
|
+
* 重复调用 stop() 是安全的(幂等操作)。
|
|
48
|
+
*/
|
|
49
|
+
stop(): void;
|
|
50
|
+
/**
|
|
51
|
+
* 是否正在运行
|
|
52
|
+
*/
|
|
53
|
+
get isRunning(): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* 获取配置的心跳间隔(毫秒)
|
|
56
|
+
*/
|
|
57
|
+
get heartbeatInterval(): number;
|
|
58
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSEHeartbeat — 自动周期心跳调度器
|
|
3
|
+
*
|
|
4
|
+
* 管理 SSE 连接的定时心跳发送,防止代理/负载均衡器因空闲超时断开连接。
|
|
5
|
+
* 使用 setInterval 定时调用 emitter.heartbeat(),支持可配置间隔。
|
|
6
|
+
*
|
|
7
|
+
* @see design.md §1.6 connection.heartbeat 事件
|
|
8
|
+
* @see requirements.md Requirement 5 AC5
|
|
9
|
+
*/
|
|
10
|
+
/** 默认心跳间隔:30 秒 */
|
|
11
|
+
const DEFAULT_HEARTBEAT_INTERVAL = 30000;
|
|
12
|
+
// ─────────────────────────────────────────────
|
|
13
|
+
// SSEHeartbeat 实现
|
|
14
|
+
// ─────────────────────────────────────────────
|
|
15
|
+
/**
|
|
16
|
+
* SSEHeartbeat — 周期心跳调度器
|
|
17
|
+
*
|
|
18
|
+
* 用法:
|
|
19
|
+
* ```ts
|
|
20
|
+
* const emitter = new SSEEmitter(res);
|
|
21
|
+
* const heartbeat = new SSEHeartbeat(emitter, { interval: 30000 });
|
|
22
|
+
* heartbeat.start();
|
|
23
|
+
* // ... 业务逻辑 ...
|
|
24
|
+
* heartbeat.stop(); // 或 emitter.close() 时自动停止
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export class SSEHeartbeat {
|
|
28
|
+
emitter;
|
|
29
|
+
interval;
|
|
30
|
+
timer = null;
|
|
31
|
+
constructor(emitter, options) {
|
|
32
|
+
this.emitter = emitter;
|
|
33
|
+
this.interval = options?.interval ?? DEFAULT_HEARTBEAT_INTERVAL;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 启动周期心跳
|
|
37
|
+
*
|
|
38
|
+
* 使用 setInterval 定时调用 emitter.heartbeat()。
|
|
39
|
+
* timer.unref() 防止心跳定时器阻塞进程退出。
|
|
40
|
+
* 重复调用 start() 不会创建多个定时器。
|
|
41
|
+
*/
|
|
42
|
+
start() {
|
|
43
|
+
if (this.timer !== null) {
|
|
44
|
+
return; // 已在运行,防止重复启动
|
|
45
|
+
}
|
|
46
|
+
this.timer = setInterval(() => {
|
|
47
|
+
this.emitter.heartbeat();
|
|
48
|
+
}, this.interval);
|
|
49
|
+
// unref 使定时器不会阻塞 Node.js 进程退出
|
|
50
|
+
this.timer.unref();
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* 停止周期心跳
|
|
54
|
+
*
|
|
55
|
+
* 清除 setInterval 定时器,释放资源。
|
|
56
|
+
* 重复调用 stop() 是安全的(幂等操作)。
|
|
57
|
+
*/
|
|
58
|
+
stop() {
|
|
59
|
+
if (this.timer !== null) {
|
|
60
|
+
clearInterval(this.timer);
|
|
61
|
+
this.timer = null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* 是否正在运行
|
|
66
|
+
*/
|
|
67
|
+
get isRunning() {
|
|
68
|
+
return this.timer !== null;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 获取配置的心跳间隔(毫秒)
|
|
72
|
+
*/
|
|
73
|
+
get heartbeatInterval() {
|
|
74
|
+
return this.interval;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TraceCollector — SSE 侧 Trace 采集实现
|
|
3
|
+
*
|
|
4
|
+
* 类型定义统一使用 contracts/trace-collector;本模块仅提供内存实现与 SSE 桥接。
|
|
5
|
+
*
|
|
6
|
+
* @see contracts/trace-collector.ts
|
|
7
|
+
* @see sse/sse-emitter.ts
|
|
8
|
+
*/
|
|
9
|
+
import type { ExecutionFlowEvent, ExecutionNodeEvent, ITraceCollector, TraceEvent, TraceLinkEvent, TraceLinkNodeEvent, TraceSession } from '../contracts/trace-collector.js';
|
|
10
|
+
/**
|
|
11
|
+
* InMemoryTraceCollector — 内存 Trace 采集器(测试用)
|
|
12
|
+
*/
|
|
13
|
+
export declare class InMemoryTraceCollector implements ITraceCollector {
|
|
14
|
+
private readonly sessions;
|
|
15
|
+
collect(event: TraceEvent): Promise<void>;
|
|
16
|
+
startSession(sessionId: string, taskId: string): Promise<void>;
|
|
17
|
+
endSession(sessionId: string, status: 'completed' | 'failed'): Promise<void>;
|
|
18
|
+
getSession(sessionId: string): Promise<TraceSession | null>;
|
|
19
|
+
createFlow(_event: ExecutionFlowEvent): Promise<string>;
|
|
20
|
+
createNode(_event: ExecutionNodeEvent): Promise<string>;
|
|
21
|
+
completeNode(_nodeId: string, _params: {
|
|
22
|
+
status: 'completed' | 'failed';
|
|
23
|
+
output?: unknown;
|
|
24
|
+
error?: string;
|
|
25
|
+
inputTokens?: number;
|
|
26
|
+
outputTokens?: number;
|
|
27
|
+
totalTokens?: number;
|
|
28
|
+
}): Promise<void>;
|
|
29
|
+
createLink(_event: TraceLinkEvent): Promise<string>;
|
|
30
|
+
createLinkNode(_event: TraceLinkNodeEvent): Promise<string>;
|
|
31
|
+
completeLinkNode(_nodeId: string, _params: {
|
|
32
|
+
status: 'completed' | 'failed';
|
|
33
|
+
error?: string;
|
|
34
|
+
}): Promise<void>;
|
|
35
|
+
/** 获取所有会话(调试用) */
|
|
36
|
+
getAllSessions(): TraceSession[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* SSE 事件转 Trace 事件
|
|
40
|
+
*/
|
|
41
|
+
export declare function sseEventToTraceEvent(sseEvent: {
|
|
42
|
+
type: string;
|
|
43
|
+
data: Record<string, unknown>;
|
|
44
|
+
}, correlationId: string, taskId: string, sessionId: string): TraceEvent;
|
|
45
|
+
/**
|
|
46
|
+
* Trace 采集中间件
|
|
47
|
+
*
|
|
48
|
+
* 包装 SSE Emitter,在推送 SSE 事件的同时收集 Trace 事件。
|
|
49
|
+
*/
|
|
50
|
+
export declare class TraceCollectorMiddleware {
|
|
51
|
+
private readonly collector;
|
|
52
|
+
constructor(collector: ITraceCollector);
|
|
53
|
+
wrapEmit(emitFn: (type: string, data: Record<string, unknown>) => void, context: {
|
|
54
|
+
correlationId: string;
|
|
55
|
+
taskId: string;
|
|
56
|
+
sessionId: string;
|
|
57
|
+
}): (type: string, data: Record<string, unknown>) => void;
|
|
58
|
+
startSession(sessionId: string, taskId: string): Promise<void>;
|
|
59
|
+
endSession(sessionId: string, status: 'completed' | 'failed'): Promise<void>;
|
|
60
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TraceCollector — SSE 侧 Trace 采集实现
|
|
3
|
+
*
|
|
4
|
+
* 类型定义统一使用 contracts/trace-collector;本模块仅提供内存实现与 SSE 桥接。
|
|
5
|
+
*
|
|
6
|
+
* @see contracts/trace-collector.ts
|
|
7
|
+
* @see sse/sse-emitter.ts
|
|
8
|
+
*/
|
|
9
|
+
import { randomUUID } from 'node:crypto';
|
|
10
|
+
// ─────────────────────────────────────────────
|
|
11
|
+
// Trace 采集器实现
|
|
12
|
+
// ─────────────────────────────────────────────
|
|
13
|
+
/**
|
|
14
|
+
* InMemoryTraceCollector — 内存 Trace 采集器(测试用)
|
|
15
|
+
*/
|
|
16
|
+
export class InMemoryTraceCollector {
|
|
17
|
+
sessions = new Map();
|
|
18
|
+
async collect(event) {
|
|
19
|
+
const session = this.sessions.get(event.sessionId);
|
|
20
|
+
if (session) {
|
|
21
|
+
session.events.push(event);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async startSession(sessionId, taskId) {
|
|
25
|
+
this.sessions.set(sessionId, {
|
|
26
|
+
sessionId,
|
|
27
|
+
taskId,
|
|
28
|
+
startTime: new Date().toISOString(),
|
|
29
|
+
events: [],
|
|
30
|
+
status: 'running',
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
async endSession(sessionId, status) {
|
|
34
|
+
const session = this.sessions.get(sessionId);
|
|
35
|
+
if (session) {
|
|
36
|
+
session.endTime = new Date().toISOString();
|
|
37
|
+
session.status = status;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async getSession(sessionId) {
|
|
41
|
+
return this.sessions.get(sessionId) ?? null;
|
|
42
|
+
}
|
|
43
|
+
async createFlow(_event) {
|
|
44
|
+
return `flow-${randomUUID()}`;
|
|
45
|
+
}
|
|
46
|
+
async createNode(_event) {
|
|
47
|
+
return `node-${randomUUID()}`;
|
|
48
|
+
}
|
|
49
|
+
async completeNode(_nodeId, _params) { }
|
|
50
|
+
async createLink(_event) {
|
|
51
|
+
return `link-${randomUUID()}`;
|
|
52
|
+
}
|
|
53
|
+
async createLinkNode(_event) {
|
|
54
|
+
return `link-node-${randomUUID()}`;
|
|
55
|
+
}
|
|
56
|
+
async completeLinkNode(_nodeId, _params) { }
|
|
57
|
+
/** 获取所有会话(调试用) */
|
|
58
|
+
getAllSessions() {
|
|
59
|
+
return Array.from(this.sessions.values());
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// ─────────────────────────────────────────────
|
|
63
|
+
// SSE 事件转 Trace 事件
|
|
64
|
+
// ─────────────────────────────────────────────
|
|
65
|
+
/**
|
|
66
|
+
* SSE 事件转 Trace 事件
|
|
67
|
+
*/
|
|
68
|
+
export function sseEventToTraceEvent(sseEvent, correlationId, taskId, sessionId) {
|
|
69
|
+
return {
|
|
70
|
+
id: `trace-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`,
|
|
71
|
+
type: sseEvent.type,
|
|
72
|
+
correlationId,
|
|
73
|
+
taskId,
|
|
74
|
+
sessionId,
|
|
75
|
+
timestamp: new Date().toISOString(),
|
|
76
|
+
payload: sseEvent.data,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
// ─────────────────────────────────────────────
|
|
80
|
+
// Trace 采集中间件
|
|
81
|
+
// ─────────────────────────────────────────────
|
|
82
|
+
/**
|
|
83
|
+
* Trace 采集中间件
|
|
84
|
+
*
|
|
85
|
+
* 包装 SSE Emitter,在推送 SSE 事件的同时收集 Trace 事件。
|
|
86
|
+
*/
|
|
87
|
+
export class TraceCollectorMiddleware {
|
|
88
|
+
collector;
|
|
89
|
+
constructor(collector) {
|
|
90
|
+
this.collector = collector;
|
|
91
|
+
}
|
|
92
|
+
wrapEmit(emitFn, context) {
|
|
93
|
+
return (type, data) => {
|
|
94
|
+
emitFn(type, data);
|
|
95
|
+
const traceEvent = sseEventToTraceEvent({ type, data }, context.correlationId, context.taskId, context.sessionId);
|
|
96
|
+
this.collector.collect(traceEvent).catch((err) => {
|
|
97
|
+
console.error('[TraceCollectorMiddleware] Failed to collect trace event:', err);
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
async startSession(sessionId, taskId) {
|
|
102
|
+
await this.collector.startSession(sessionId, taskId);
|
|
103
|
+
}
|
|
104
|
+
async endSession(sessionId, status) {
|
|
105
|
+
await this.collector.endSession(sessionId, status);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task Manager Contract — 任务生命周期管理接口
|
|
3
|
+
*
|
|
4
|
+
* 定义 Task 的创建、状态流转、查询、Token 消耗记录等核心操作。
|
|
5
|
+
* 状态流转:pending → running → success/failed/timeout/token_exhausted
|
|
6
|
+
*
|
|
7
|
+
* @see design.md §1.3 数据模型 — tasks 表
|
|
8
|
+
* @see requirements.md Requirement 7 AC1-AC5
|
|
9
|
+
*/
|
|
10
|
+
import type { TaskStatus } from '../../common/types.js';
|
|
11
|
+
/**
|
|
12
|
+
* CreateTaskParams — 创建 Task 所需参数
|
|
13
|
+
*/
|
|
14
|
+
export interface CreateTaskParams {
|
|
15
|
+
/**
|
|
16
|
+
* 上游发号的 Task ID(如 Hosting `task.id`)。
|
|
17
|
+
* 有则 Runtime 复用;无则自行生成。
|
|
18
|
+
*/
|
|
19
|
+
id?: string;
|
|
20
|
+
/** Agent 对外主键(值为 agentCode;字段名保留 agentId 对齐存储列 agent_id) */
|
|
21
|
+
agentId: string;
|
|
22
|
+
/** 会话 ID */
|
|
23
|
+
sessionId: string;
|
|
24
|
+
/** 用户 ID */
|
|
25
|
+
userId: string;
|
|
26
|
+
/** 请求关联 ID(用于链路追踪) */
|
|
27
|
+
correlationId: string;
|
|
28
|
+
/** 用户输入 */
|
|
29
|
+
input: unknown;
|
|
30
|
+
/** 超时时间(毫秒) */
|
|
31
|
+
timeout: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* TaskRecord — Task 完整记录(对应 tasks 表)
|
|
35
|
+
*/
|
|
36
|
+
export interface TaskRecord {
|
|
37
|
+
/** Task 唯一 ID */
|
|
38
|
+
id: string;
|
|
39
|
+
/** Agent 对外主键(值为 agentCode;字段名保留 agentId 对齐存储列 agent_id) */
|
|
40
|
+
agentId: string;
|
|
41
|
+
/** 会话 ID */
|
|
42
|
+
sessionId: string;
|
|
43
|
+
/** 用户 ID */
|
|
44
|
+
userId: string;
|
|
45
|
+
/** 请求关联 ID */
|
|
46
|
+
correlationId: string;
|
|
47
|
+
/** 用户输入 */
|
|
48
|
+
input: unknown;
|
|
49
|
+
/** 执行输出 */
|
|
50
|
+
output: unknown | null;
|
|
51
|
+
/** 当前状态 */
|
|
52
|
+
status: TaskStatus;
|
|
53
|
+
/** Trace ID(链路追踪) */
|
|
54
|
+
traceId: string | null;
|
|
55
|
+
/** Token 消耗汇总 */
|
|
56
|
+
tokenUsage: TokenUsageRecord[];
|
|
57
|
+
/** 累计成本 */
|
|
58
|
+
cost: number;
|
|
59
|
+
/** 开始执行时间 (ISO 8601) */
|
|
60
|
+
startedAt: string | null;
|
|
61
|
+
/** 完成时间 (ISO 8601) */
|
|
62
|
+
completedAt: string | null;
|
|
63
|
+
/** 创建人 */
|
|
64
|
+
createdBy: string;
|
|
65
|
+
/** 创建时间 (ISO 8601) */
|
|
66
|
+
createdAt: string;
|
|
67
|
+
/** 最后更新人 */
|
|
68
|
+
updatedBy: string;
|
|
69
|
+
/** 最后更新时间 (ISO 8601) */
|
|
70
|
+
updatedAt: string;
|
|
71
|
+
/** 是否删除(软删除标记) */
|
|
72
|
+
isDeleted: boolean;
|
|
73
|
+
/** 删除人 */
|
|
74
|
+
deletedBy?: string | null;
|
|
75
|
+
/** 删除时间 (ISO 8601) */
|
|
76
|
+
deletedAt?: string | null;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* TaskStatusInfo — 轮询接口返回的任务状态信息
|
|
80
|
+
*
|
|
81
|
+
* 用于 GET /tasks/{taskId}/status,客户端轮询长任务进度。
|
|
82
|
+
*/
|
|
83
|
+
export interface TaskStatusInfo {
|
|
84
|
+
/** 当前状态 */
|
|
85
|
+
status: TaskStatus;
|
|
86
|
+
/** 执行进度(0-100) */
|
|
87
|
+
progress: number;
|
|
88
|
+
/** 开始执行时间 (ISO 8601) */
|
|
89
|
+
startedAt: string | null;
|
|
90
|
+
/** 已运行时长(毫秒) */
|
|
91
|
+
duration: number;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* TokenUsageRecord — 单次 Token 消耗记录
|
|
95
|
+
*
|
|
96
|
+
* 每次 LLM 调用产生一条,关联到具体节点和模型。
|
|
97
|
+
*/
|
|
98
|
+
export interface TokenUsageRecord {
|
|
99
|
+
/** 产生消耗的节点 ID */
|
|
100
|
+
nodeId: string;
|
|
101
|
+
/** 使用的模型标识 */
|
|
102
|
+
model: string;
|
|
103
|
+
/** 输入 Token 数 */
|
|
104
|
+
inputTokens: number;
|
|
105
|
+
/** 输出 Token 数 */
|
|
106
|
+
outputTokens: number;
|
|
107
|
+
/** 预估成本(美元) */
|
|
108
|
+
costEstimate: number;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* ITaskManager — 任务管理器接口
|
|
112
|
+
*
|
|
113
|
+
* 负责 Task 的创建、状态流转、状态查询和 Token 消耗记录。
|
|
114
|
+
* 由 TaskService 实现,提供 Task 生命周期的完整管理能力。
|
|
115
|
+
*/
|
|
116
|
+
export interface ITaskManager {
|
|
117
|
+
/**
|
|
118
|
+
* 创建新 Task(初始状态为 pending)
|
|
119
|
+
*
|
|
120
|
+
* @param params - 创建参数
|
|
121
|
+
* @returns 创建后的完整 TaskRecord
|
|
122
|
+
*/
|
|
123
|
+
create(params: CreateTaskParams): Promise<TaskRecord>;
|
|
124
|
+
/**
|
|
125
|
+
* 更新 Task 状态
|
|
126
|
+
*
|
|
127
|
+
* 合法流转:pending→running, running→success/failed/timeout/token_exhausted
|
|
128
|
+
*
|
|
129
|
+
* @param taskId - Task ID
|
|
130
|
+
* @param status - 目标状态
|
|
131
|
+
* @param output - 执行输出(success 时设置)
|
|
132
|
+
*/
|
|
133
|
+
updateStatus(taskId: string, status: TaskStatus, output?: unknown): Promise<void>;
|
|
134
|
+
/**
|
|
135
|
+
* 获取 Task 当前状态(供轮询使用)
|
|
136
|
+
*
|
|
137
|
+
* @param taskId - Task ID
|
|
138
|
+
* @returns 状态信息(包含进度百分比和运行时长)
|
|
139
|
+
*/
|
|
140
|
+
getStatus(taskId: string): Promise<TaskStatusInfo>;
|
|
141
|
+
/**
|
|
142
|
+
* 记录一次 Token 消耗
|
|
143
|
+
*
|
|
144
|
+
* 每次 LLM 调用后调用此方法,累计 Token 消耗。
|
|
145
|
+
*
|
|
146
|
+
* @param taskId - Task ID
|
|
147
|
+
* @param usage - Token 消耗记录
|
|
148
|
+
*/
|
|
149
|
+
recordTokenUsage(taskId: string, usage: TokenUsageRecord): Promise<void>;
|
|
150
|
+
/**
|
|
151
|
+
* 更新 Task 的执行进度(用于长任务)
|
|
152
|
+
*
|
|
153
|
+
* 显式设置进度百分比,供 getStatus() 返回细粒度进度。
|
|
154
|
+
* 适用于分钟级/小时级长任务,客户端通过轮询获取实时进度。
|
|
155
|
+
*
|
|
156
|
+
* @param taskId - Task ID
|
|
157
|
+
* @param progress - 进度百分比 (0-100)
|
|
158
|
+
*/
|
|
159
|
+
updateProgress(taskId: string, progress: number): Promise<void>;
|
|
160
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task Manager Contract — 任务生命周期管理接口
|
|
3
|
+
*
|
|
4
|
+
* 定义 Task 的创建、状态流转、查询、Token 消耗记录等核心操作。
|
|
5
|
+
* 状态流转:pending → running → success/failed/timeout/token_exhausted
|
|
6
|
+
*
|
|
7
|
+
* @see design.md §1.3 数据模型 — tasks 表
|
|
8
|
+
* @see requirements.md Requirement 7 AC1-AC5
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './contracts/index.js';
|
|
2
|
+
export { TaskService, InMemoryTaskRepository } from './task.service.js';
|
|
3
|
+
export type { ITaskRepository } from './task.service.js';
|
|
4
|
+
export { TaskTimeoutManager } from './task-timeout.js';
|
|
5
|
+
export type { TaskTimeoutManagerOptions } from './task-timeout.js';
|
|
6
|
+
export { TaskProgressTracker } from './task-progress-tracker.js';
|
|
7
|
+
export type { TaskProgressInfo } from './task-progress-tracker.js';
|