@gt-fe/eap-runtime 0.0.8 → 0.0.11

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 (130) hide show
  1. package/README.md +15 -20
  2. package/dist/api/handlers/invoke.handler.js +7 -3
  3. package/dist/api/handlers/messages.handler.js +0 -1
  4. package/dist/api/handlers/stream.handler.js +8 -4
  5. package/dist/api/routes/agent.routes.d.ts +2 -2
  6. package/dist/api/routes/agent.routes.js +2 -2
  7. package/dist/checkpoint/checkpoint-ref-notify.d.ts +10 -0
  8. package/dist/checkpoint/checkpoint-ref-notify.js +59 -0
  9. package/dist/checkpoint/index.d.ts +1 -0
  10. package/dist/checkpoint/index.js +1 -0
  11. package/dist/checkpoint/pg-checkpoint-saver.js +25 -2
  12. package/dist/common/agent-code.d.ts +2 -4
  13. package/dist/common/agent-code.js +4 -5
  14. package/dist/common/types.d.ts +5 -5
  15. package/dist/common/types.js +2 -2
  16. package/dist/contracts/permission-checker.d.ts +1 -1
  17. package/dist/contracts/trace-collector.d.ts +16 -2
  18. package/dist/debug/llm-turn-log.d.ts +100 -0
  19. package/dist/debug/llm-turn-log.js +130 -0
  20. package/dist/debug/pg-llm-turn-log.d.ts +22 -0
  21. package/dist/debug/pg-llm-turn-log.js +57 -0
  22. package/dist/governance/governance-client.d.ts +1 -1
  23. package/dist/governance/governance-client.js +40 -16
  24. package/dist/governance/index.d.ts +2 -2
  25. package/dist/governance/index.js +1 -1
  26. package/dist/governance/permission-guard.d.ts +2 -1
  27. package/dist/governance/permission-guard.js +13 -4
  28. package/dist/graph/adapters/langgraph-checkpointer.js +3 -1
  29. package/dist/graph/adapters/langgraph.adapter.d.ts +1 -0
  30. package/dist/graph/adapters/langgraph.adapter.js +153 -92
  31. package/dist/graph/adapters/skill-read.d.ts +12 -0
  32. package/dist/graph/adapters/skill-read.js +63 -0
  33. package/dist/graph/adapters/subgraph-compiler.js +5 -0
  34. package/dist/graph/contracts/executable-graph.d.ts +11 -9
  35. package/dist/graph/contracts/executable-graph.js +1 -1
  36. package/dist/graph/hitl/hitl-handler.d.ts +10 -0
  37. package/dist/graph/hitl/hitl-handler.js +50 -6
  38. package/dist/graph/nodes/llm-node.d.ts +14 -0
  39. package/dist/graph/nodes/skill-bind-node.js +1 -2
  40. package/dist/graph/nodes/tool-node.d.ts +2 -0
  41. package/dist/graph/nodes/tool-node.js +50 -10
  42. package/dist/graph/trace-span.d.ts +22 -0
  43. package/dist/graph/trace-span.js +69 -0
  44. package/dist/index.d.ts +5 -2
  45. package/dist/index.js +3 -1
  46. package/dist/memory/compression/compression.repository.d.ts +1 -15
  47. package/dist/providers/echo-llm-provider.d.ts +1 -1
  48. package/dist/providers/echo-llm-provider.js +4 -3
  49. package/dist/providers/http-llm-provider.d.ts +4 -0
  50. package/dist/providers/http-llm-provider.js +129 -4
  51. package/dist/providers/local-llm-provider.d.ts +5 -1
  52. package/dist/providers/local-llm-provider.js +14 -6
  53. package/dist/providers/routing-llm-provider.d.ts +4 -0
  54. package/dist/providers/routing-llm-provider.js +12 -2
  55. package/dist/registry/agent-models.d.ts +1 -1
  56. package/dist/registry/agent-models.js +1 -1
  57. package/dist/registry/agent-registry-client.d.ts +3 -3
  58. package/dist/registry/deployment-snapshot.d.ts +17 -5
  59. package/dist/registry/deployment-snapshot.js +97 -49
  60. package/dist/registry/graph-loader.d.ts +2 -2
  61. package/dist/registry/graph-loader.js +43 -80
  62. package/dist/registry/index.d.ts +2 -2
  63. package/dist/registry/index.js +2 -2
  64. package/dist/registry/preload-errors.d.ts +1 -1
  65. package/dist/registry/preload-errors.js +1 -1
  66. package/dist/registry/skill-io-guard.js +1 -1
  67. package/dist/registry/skill-tree.d.ts +3 -0
  68. package/dist/registry/skill-tree.js +41 -3
  69. package/dist/runtime/agent-runtime.d.ts +42 -3
  70. package/dist/runtime/agent-runtime.js +129 -39
  71. package/dist/runtime/dev-runtime.d.ts +7 -4
  72. package/dist/runtime/dev-runtime.js +24 -21
  73. package/dist/runtime/index.d.ts +3 -3
  74. package/dist/runtime/index.js +1 -1
  75. package/dist/runtime/storage-profile.d.ts +19 -10
  76. package/dist/runtime/storage-profile.js +42 -29
  77. package/dist/runtime/types.d.ts +17 -19
  78. package/dist/server.js +2 -2
  79. package/dist/session/session.service.d.ts +5 -0
  80. package/dist/session/session.service.js +12 -0
  81. package/dist/sse/events/index.d.ts +5 -3
  82. package/dist/sse/events/index.js +2 -0
  83. package/dist/sse/events/skill-events.d.ts +12 -1
  84. package/dist/sse/events/skill-events.js +1 -1
  85. package/dist/sse/trace-collector.d.ts +10 -0
  86. package/dist/sse/trace-collector.js +1 -0
  87. package/dist/token/token-budget.service.d.ts +2 -2
  88. package/dist/token/token-budget.service.js +1 -1
  89. package/dist/tool/create-tool-executor.d.ts +1 -1
  90. package/dist/tool/create-tool-executor.js +3 -2
  91. package/dist/tool/dev-http-executor.d.ts +1 -1
  92. package/dist/tool/dev-http-executor.js +10 -7
  93. package/dist/tool/dev-mcp-executor.js +5 -3
  94. package/dist/tool/dev-tool-executor.d.ts +1 -1
  95. package/dist/tool/dev-tool-executor.js +2 -2
  96. package/dist/tool/harness-command.d.ts +32 -0
  97. package/dist/tool/harness-command.js +276 -0
  98. package/dist/tool/harness-primitives.d.ts +54 -0
  99. package/dist/tool/harness-primitives.js +492 -0
  100. package/dist/tool/http-tool-executor.js +16 -21
  101. package/dist/tool/index.d.ts +4 -2
  102. package/dist/tool/index.js +4 -2
  103. package/dist/tool/local-mcp-client.d.ts +1 -1
  104. package/dist/tool/local-mcp-client.js +54 -23
  105. package/dist/tool/local-tool-executor.d.ts +4 -4
  106. package/dist/tool/local-tool-executor.js +18 -16
  107. package/dist/tool/mcp-tool-executor.js +23 -7
  108. package/dist/tool/skill-script-refs.d.ts +20 -0
  109. package/dist/tool/skill-script-refs.js +62 -0
  110. package/dist/tool/system-prompt-builder.d.ts +61 -25
  111. package/dist/tool/system-prompt-builder.js +198 -92
  112. package/dist/tool/timeout.d.ts +14 -0
  113. package/dist/tool/timeout.js +36 -0
  114. package/dist/tool/tool-confirmation.js +2 -1
  115. package/dist/tool/tool-execution-router.d.ts +1 -1
  116. package/dist/tool/tool-execution-router.js +2 -2
  117. package/dist/tool/tool-executor.interface.d.ts +23 -7
  118. package/dist/tool/tool-orchestrator.d.ts +1 -1
  119. package/dist/tool/tool-orchestrator.js +6 -3
  120. package/dist/utils/format-error.d.ts +2 -2
  121. package/dist/utils/format-error.js +2 -2
  122. package/dist/utils/http-error.d.ts +2 -2
  123. package/dist/utils/http-error.js +2 -2
  124. package/package.json +3 -3
  125. package/dist/common/concurrency.d.ts +0 -79
  126. package/dist/common/concurrency.js +0 -121
  127. package/dist/common/queue-consumer.d.ts +0 -125
  128. package/dist/common/queue-consumer.js +0 -159
  129. package/dist/tool/mock-tool-executor.d.ts +0 -28
  130. package/dist/tool/mock-tool-executor.js +0 -65
package/README.md CHANGED
@@ -8,6 +8,8 @@ Enterprise Agent Platform **执行引擎**(LangGraph.js):Agent Graph 编
8
8
 
9
9
  | 日期 | 摘要 |
10
10
  |------|------|
11
+ | 2026-08-24 | 0.0.10:官方 Skill / Harness、`ForkParams`、对话详情、存储两档。依赖 `@eap/contracts@0.0.9`。详见 [CHANGELOG.md](./CHANGELOG.md) |
12
+ | 2026-08-21 | 0.0.9:Gateway `/mcp` JSON-RPC 补 `Accept`;`tools/call` 透传工具版本。详见 [CHANGELOG.md](./CHANGELOG.md) |
11
13
  | 2026-08-19 | 0.0.8:Skill 子图 SSE 闭环;`ExecuteParams.traceId`;`tool.called` 改为 Tool 节点开始执行。依赖 `@eap/contracts@0.0.8`。详见 [CHANGELOG.md](./CHANGELOG.md) |
12
14
  | 2026-08-18 | 0.0.7:`DevHttpExecutor`、`mode=mcp` 缺配置失败、HTTP 出站语义与 Gateway 共用 `@eap/contracts@0.0.7` |
13
15
  | 2026-07-29 | 补全 `.env.example` 全量环境变量(部署上下文 / Tool / 预装 / 存储装配 / 调试分区);§5 预装开关表补 `EAP_PRELOAD_DEFINITION_CACHE` |
@@ -21,10 +23,12 @@ Enterprise Agent Platform **执行引擎**(LangGraph.js):Agent Graph 编
21
23
  | 权威文档 | 路径 |
22
24
  |----------|------|
23
25
  | 模块规格 | [`.kiro/specs/04-runtime-core/`](../.kiro/specs/04-runtime-core/) |
26
+ | Runtime DDL | [`docs/ddl.md`](./docs/ddl.md) |
24
27
  | SDK 集成手册 | [`docs/contracts/runtime-sdk-integration-final.md`](../docs/contracts/runtime-sdk-integration-final.md) |
25
28
  | 环境变量总表 | [`docs/governance/governance-env-config.md`](../docs/governance/governance-env-config.md) |
26
29
  | 预装联调契约 | [`docs/contracts/preload-hosting-runtime-contract.md`](../docs/contracts/preload-hosting-runtime-contract.md) |
27
30
  | 预装加载与请求流转 | [`docs/contracts/runtime-preinstall-load-flow.md`](../docs/contracts/runtime-preinstall-load-flow.md) |
31
+ | 技能 FS 待办 | [`docs/TODO-skill-fs.md`](./docs/TODO-skill-fs.md) |
28
32
  | 本地 Agent 闭环 | [`docs/workflows/local-agent-dev-loop.md`](../docs/workflows/local-agent-dev-loop.md) |
29
33
 
30
34
  ---
@@ -82,7 +86,7 @@ for await (const ev of agentRuntime.stream({ agentCode, input, sessionId, taskId
82
86
  await agentRuntime.seedSessionMessages({ agentCode, messages: [ /* role: user | assistant */ ] });
83
87
  await agentRuntime.resumeHitl(taskId, { choice, userId, /* … */ });
84
88
  for await (const ev of agentRuntime.streamResumeHitl(taskId, { choice, userId })) { /* HITL 续跑事件 */ }
85
- await agentRuntime.fork(checkpointId, { /* overrides */ });
89
+ await agentRuntime.fork({ checkpointId, taskId, traceId, overrides: { /* … */ } });
86
90
  ```
87
91
 
88
92
  细则与字段表见 [`docs/contracts/runtime-sdk-integration-final.md`](../docs/contracts/runtime-sdk-integration-final.md)。
@@ -175,26 +179,18 @@ node ../fixtures/eap-preinstall-sample/scripts/seal-snapshot.mjs
175
179
 
176
180
  ## 6. 持久化与存储 Profile
177
181
 
178
- 由 `assembleRuntimeStorage()` / `EAP_RUNTIME_STORAGE_PROFILE` 统一装配 Checkpoint、Session、Message。
182
+ `assembleRuntimeStorage()` 按 profile 与环境变量选择介质。表结构见 [`docs/ddl.md`](./docs/ddl.md)。
179
183
 
180
- | Profile | Checkpoint | Session | Message | 典型场景 |
181
- |---------|------------|---------|---------|----------|
182
- | `test` | Memory | Memory | Memory | 单测 |
183
- | `dev` | File | File | File | `eap chat` / 本机 |
184
- | `integration` | Redis + PG | (Hosting Session) | PG | Hosting 内嵌联调 |
185
- | `production` | Redis + PG | (Hosting Session) | PG | 多副本生产 |
184
+ | 条件 | Checkpoint | Message / LLM 回合 | Token 配额 |
185
+ |------|------------|-------------------|------------|
186
+ | `EAP_RUNTIME_STORAGE_PROFILE=dev`,或未设 profile 且未配置数据库与 Redis | 文件(默认 `.eap/checkpoints`) | 文件 | 进程内,不落库 |
187
+ | `test` / `integration` / `production`,或未设 profile 但已配置 `DATABASE_URL`/`DB_*` 或 `REDIS_*` | Redis + PostgreSQL | PostgreSQL | PostgreSQL `token_budgets` |
186
188
 
187
- 常用目录变量(**仅 `dev` profile**):
189
+ 后一路径缺少数据库或 Redis 时抛错。显式 `dev` 时即使已配置数据库仍使用文件。
188
190
 
189
- | 变量 | 说明 |
190
- |------|------|
191
- | `EAP_CHECKPOINT_DIR` | File Checkpoint |
192
- | `EAP_SESSION_DIR` | File Session |
193
- | `EAP_MESSAGE_DIR` | File Message |
194
-
195
- 完整策略与库表约定:[`docs/governance/governance-env-config.md` §9](../docs/governance/governance-env-config.md#9-runtime-存储装配策略)、[`docs/architecture/session-message-checkpoint-alignment.md`](../docs/architecture/session-message-checkpoint-alignment.md)、[`docs/verification/db-storage-verification.md`](../docs/verification/db-storage-verification.md)。
191
+ 仅文件路径使用的目录变量:`EAP_CHECKPOINT_DIR`、`EAP_SESSION_DIR`、`EAP_MESSAGE_DIR`(可用 `EAP_DATA_DIR` 作为根目录)。
196
192
 
197
- 本地带 File 存储的 fixture 示例:[`fixtures/eap-local-test/`](../fixtures/eap-local-test/)(`chat.sh` / `chat-db.sh`)。
193
+ 环境变量总表:[governance-env-config.md §9](../docs/governance/governance-env-config.md#9-runtime-存储装配策略)。
198
194
 
199
195
  ---
200
196
 
@@ -202,8 +198,7 @@ node ../fixtures/eap-preinstall-sample/scripts/seal-snapshot.mjs
202
198
 
203
199
  | 模式 | 何时 | 说明 |
204
200
  |------|------|------|
205
- | `mock` | 本地默认 | 不调真实 Tool |
206
- | `mcp` / DevMcp | `eap chat --tool-mode mcp` | 本机直连 MCP(`EAP_TOOL_EXECUTION_MODE`,仅 createDevRuntime) |
201
+ | `mcp` / DevToolExecutor | 本地默认(`dev` + `mcp`) | 按清单直连 MCP / HTTP / 本机 code |
207
202
  | Gateway | 生产 / Hosting | `EAP_TOOL_GATEWAY_TRANSPORT=mcp`(生产);`http` 仅调试 |
208
203
 
209
204
  - 编排:`ToolOrchestrator` + `ToolExecutionRouter`(`deploymentContext`: `server` \| `desktop` \| `dev`)
@@ -259,7 +254,7 @@ FOUNDATION_SERVICE_URL=...
259
254
  EAP_DEPLOYMENT_CONTEXT=dev
260
255
  EAP_PREINSTALL_ROOT=/abs/path/to/preinstall # 或 Agent 工程内预装树
261
256
  EAP_RUNTIME_STORAGE_PROFILE=dev
262
- EAP_TOOL_EXECUTION_MODE=mock # 或 mcp
257
+ EAP_TOOL_EXECUTION_MODE=mcp # 本地默认;http-debug 走 Gateway 调试口
263
258
  # OPENAI_BASE_URL / OPENAI_API_KEY / EAP_DEFAULT_MODEL
264
259
  ```
265
260
 
@@ -21,7 +21,8 @@ import { TokenBudgetExhaustedError } from '../../token/token-budget-guard.js';
21
21
  import { resolveExecutionContext } from '../../governance/governance-client.js';
22
22
  import { resolveSkillInputFromInvokeInput } from '../../registry/skill-io-guard.js';
23
23
  import { toLoadedToolMap } from '../../tool/loaded-tool-definition.js';
24
- import { toLoadedSkillMap, mergeSkillScriptTools } from '../../tool/system-prompt-builder.js';
24
+ import { toLoadedSkillMap } from '../../tool/system-prompt-builder.js';
25
+ import { assembleLoadedTools } from '../../tool/harness-primitives.js';
25
26
  import { resolveAgentCode } from '../../common/agent-code.js';
26
27
  import { unwrapHitlPaused } from '../../graph/hitl/hitl-handler.js';
27
28
  import { resolveTraceId } from '../../common/trace-id.js';
@@ -173,11 +174,13 @@ export class InvokeOrchestrator {
173
174
  })
174
175
  : undefined;
175
176
  const skillDefinitions = toLoadedSkillMap(loadedSkills);
176
- // Skill scripts 虚拟 Tool 并入 loadedTools(同名不覆盖平台 Tool)
177
- const loadedTools = mergeSkillScriptTools(loadedToolsBase, loadedSkills);
177
+ const loadedTools = assembleLoadedTools(loadedToolsBase);
178
178
  const promptRoots = this.graphLoader
179
179
  ? await this.graphLoader.resolvePromptRoots(agentCode, req.agentVersion)
180
180
  : [];
181
+ const agentDir = this.graphLoader
182
+ ? (await this.graphLoader.resolveAgentDir(agentCode, req.agentVersion)) ?? undefined
183
+ : undefined;
181
184
  // 组装 GraphState:有 Checkpoint 历史则只追加本轮 user,避免双重 append
182
185
  const history = messageRecordsToGraphMessages(sessionContext.messages);
183
186
  const messages = await buildTurnGraphMessages({
@@ -204,6 +207,7 @@ export class InvokeOrchestrator {
204
207
  skillDefinitions,
205
208
  skillInput,
206
209
  promptRoots,
210
+ agentDir,
207
211
  traceId: resolveTraceId(req),
208
212
  traceCollector: this.traceCollector,
209
213
  });
@@ -47,7 +47,6 @@ export class MessagesOrchestrator {
47
47
  const agentVersion = req.agentVersion ?? metaVersion;
48
48
  // ─── Step 2: 委托 InvokeOrchestrator(user/assistant Message 由 invoke 主路径写回)───
49
49
  const invokeReq = {
50
- agentId: session.agentId,
51
50
  agentCode: session.agentId,
52
51
  input,
53
52
  sessionId,
@@ -25,10 +25,11 @@ import { TokenBudgetExhaustedError } from '../../token/token-budget-guard.js';
25
25
  import { SSEEmitter } from '../../sse/sse-emitter.js';
26
26
  import { resolveExecutionContext } from '../../governance/governance-client.js';
27
27
  import { resolveSkillInputFromInvokeInput } from '../../registry/skill-io-guard.js';
28
- import { ErrorCodes } from '@gt-fe/eap-contracts';
28
+ import { ErrorCodes } from '@eap/contracts';
29
29
  import { classifyRuntimeError } from '../../utils/http-error.js';
30
30
  import { toLoadedToolMap } from '../../tool/loaded-tool-definition.js';
31
- import { toLoadedSkillMap, mergeSkillScriptTools } from '../../tool/system-prompt-builder.js';
31
+ import { toLoadedSkillMap } from '../../tool/system-prompt-builder.js';
32
+ import { assembleLoadedTools } from '../../tool/harness-primitives.js';
32
33
  import { resolveAgentCode } from '../../common/agent-code.js';
33
34
  import { unwrapHitlPaused } from './invoke.handler.js';
34
35
  import { buildHitlWaitedPayload } from '../../graph/hitl/hitl-handler.js';
@@ -195,11 +196,13 @@ export class StreamOrchestrator {
195
196
  ? await this.graphLoader.loadSkillDefinitions(agentCode, { ...loadOpts, userId })
196
197
  : undefined;
197
198
  const skillDefinitions = toLoadedSkillMap(loadedSkills);
198
- // Skill scripts 虚拟 Tool 并入 loadedTools(同名不覆盖平台 Tool)
199
- const loadedTools = mergeSkillScriptTools(loadedToolsBase, loadedSkills);
199
+ const loadedTools = assembleLoadedTools(loadedToolsBase);
200
200
  const promptRoots = this.graphLoader
201
201
  ? await this.graphLoader.resolvePromptRoots(agentCode, req.agentVersion)
202
202
  : [];
203
+ const agentDir = this.graphLoader
204
+ ? (await this.graphLoader.resolveAgentDir(agentCode, req.agentVersion)) ?? undefined
205
+ : undefined;
203
206
  // 组装 GraphState:有 Checkpoint 历史则只追加本轮 user,避免双重 append
204
207
  const history = messageRecordsToGraphMessages(sessionContext.messages);
205
208
  const messages = await buildTurnGraphMessages({
@@ -232,6 +235,7 @@ export class StreamOrchestrator {
232
235
  skillDefinitions,
233
236
  skillInput,
234
237
  promptRoots,
238
+ agentDir,
235
239
  traceId: resolveTraceId(req),
236
240
  traceCollector: this.traceCollector,
237
241
  });
@@ -4,12 +4,12 @@
4
4
  * 生产环境由 Hosting 提供对外 HTTP;本模块供 `EAP_DEV_HTTP=1` 本地调试。
5
5
  */
6
6
  import type { ServerResponse } from 'node:http';
7
- import type { InvokeRequest as ContractInvokeRequest, InvokeResponse as ContractInvokeResponse } from '@gt-fe/eap-contracts';
7
+ import type { InvokeRequest as ContractInvokeRequest, InvokeResponse as ContractInvokeResponse } from '@eap/contracts';
8
8
  import type { ITaskManager } from '../../task/task.service.js';
9
9
  import type { SessionService } from '../../session/session.service.js';
10
10
  import type { IStateGraphEngine } from '../../graph/contracts/executable-graph.js';
11
11
  import type { SSEEmitter } from '../../sse/sse-emitter.js';
12
- export type { InvokeConfig, InvokeResponseData } from '@gt-fe/eap-contracts';
12
+ export type { InvokeConfig, InvokeResponseData } from '@eap/contracts';
13
13
  /**
14
14
  * dev HTTP 层 Invoke 请求(扩展 userId,Hosting 从 auth 注入)
15
15
  */
@@ -21,7 +21,7 @@ export function createAgentRouteHandlers(deps) {
21
21
  */
22
22
  async function invokeHandler(req) {
23
23
  const { input, sessionId, config, userId } = req;
24
- const agentCode = req.agentCode ?? req.agentId;
24
+ const agentCode = req.agentCode;
25
25
  if (!agentCode) {
26
26
  throw new Error('agentCode is required');
27
27
  }
@@ -109,7 +109,7 @@ export function createAgentRouteHandlers(deps) {
109
109
  */
110
110
  async function streamHandler(req, res) {
111
111
  const { input, sessionId, config, userId } = req;
112
- const agentCode = req.agentCode ?? req.agentId;
112
+ const agentCode = req.agentCode;
113
113
  if (!agentCode) {
114
114
  res.write(`event: error\ndata: ${JSON.stringify({ error: 'agentCode is required' })}\n\n`);
115
115
  res.end();
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Checkpoint 落盘后通知上层写 checkpoint_refs。
3
+ * 无 traceId 或 spanId 则跳过;回调失败不抛。
4
+ * collector 不得写入持久化正文。
5
+ */
6
+ import type { ITraceCollector } from '../contracts/trace-collector.js';
7
+ import type { CheckpointData } from '../graph/contracts/executable-graph.js';
8
+ /** 去掉不可序列化的 collector,再交给 Saver。 */
9
+ export declare function stripCheckpointCollectors(data: CheckpointData): CheckpointData;
10
+ export declare function notifyCheckpointRef(data: CheckpointData, collectorOverride?: ITraceCollector): Promise<void>;
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Checkpoint 落盘后通知上层写 checkpoint_refs。
3
+ * 无 traceId 或 spanId 则跳过;回调失败不抛。
4
+ * collector 不得写入持久化正文。
5
+ */
6
+ function pickString(...values) {
7
+ for (const value of values) {
8
+ if (typeof value === 'string' && value.trim())
9
+ return value.trim();
10
+ }
11
+ return undefined;
12
+ }
13
+ function omitTraceCollector(record) {
14
+ const { traceCollector: _drop, ...rest } = record;
15
+ return rest;
16
+ }
17
+ /** 去掉不可序列化的 collector,再交给 Saver。 */
18
+ export function stripCheckpointCollectors(data) {
19
+ const state = omitTraceCollector({ ...data.state });
20
+ const snap = data.engineSnapshot ? { ...data.engineSnapshot } : undefined;
21
+ if (snap?.channel_values && typeof snap.channel_values === 'object') {
22
+ snap.channel_values = omitTraceCollector({
23
+ ...snap.channel_values,
24
+ });
25
+ }
26
+ return {
27
+ ...data,
28
+ state: state,
29
+ ...(snap ? { engineSnapshot: snap } : {}),
30
+ };
31
+ }
32
+ export async function notifyCheckpointRef(data, collectorOverride) {
33
+ const channels = data.engineSnapshot && typeof data.engineSnapshot.channel_values === 'object'
34
+ ? data.engineSnapshot.channel_values
35
+ : {};
36
+ const state = (data.state ?? {});
37
+ const collector = (collectorOverride ??
38
+ channels['traceCollector'] ??
39
+ state['traceCollector']);
40
+ const traceId = pickString(state['traceId'], channels['traceId']);
41
+ const spanId = pickString(state['lastSpanId'], channels['lastSpanId']);
42
+ if (!collector?.recordCheckpointRef || !traceId || !spanId)
43
+ return;
44
+ try {
45
+ await collector.recordCheckpointRef({
46
+ checkpointId: data.checkpointId,
47
+ traceId,
48
+ spanId,
49
+ summary: {
50
+ nodeId: data.currentNodeId || pickString(channels['currentNode']),
51
+ threadId: data.threadId,
52
+ step: Array.isArray(data.historyPath) ? data.historyPath.length : undefined,
53
+ },
54
+ });
55
+ }
56
+ catch {
57
+ // 采集失败不阻断 Graph / HITL
58
+ }
59
+ }
@@ -3,6 +3,7 @@ export { RedisCheckpointSaver } from './redis-checkpoint-saver.js';
3
3
  export type { RedisCheckpointSaverOptions } from './redis-checkpoint-saver.js';
4
4
  export { CompositeCheckpointSaver } from './composite-checkpoint-saver.js';
5
5
  export { restoreCheckpoint } from './restore-checkpoint.js';
6
+ export { notifyCheckpointRef, stripCheckpointCollectors } from './checkpoint-ref-notify.js';
6
7
  export { createCheckpointData, serializeCheckpoint, deserializeCheckpoint, } from './checkpoint-serializer.js';
7
8
  export type { CreateCheckpointParams } from './checkpoint-serializer.js';
8
9
  export { FileCheckpointSaver } from './file-checkpoint-saver.js';
@@ -3,6 +3,7 @@ export * from './contracts/index.js';
3
3
  export { RedisCheckpointSaver } from './redis-checkpoint-saver.js';
4
4
  export { CompositeCheckpointSaver } from './composite-checkpoint-saver.js';
5
5
  export { restoreCheckpoint } from './restore-checkpoint.js';
6
+ export { notifyCheckpointRef, stripCheckpointCollectors } from './checkpoint-ref-notify.js';
6
7
  export { createCheckpointData, serializeCheckpoint, deserializeCheckpoint, } from './checkpoint-serializer.js';
7
8
  export { FileCheckpointSaver } from './file-checkpoint-saver.js';
8
9
  export { InMemoryCheckpointSaver } from './in-memory-checkpoint-saver.js';
@@ -20,12 +20,16 @@ export class PostgresCheckpointSaver {
20
20
  */
21
21
  async save(threadId, data) {
22
22
  const sql = `
23
- INSERT INTO checkpoints (id, thread_id, checkpoint_id, current_node_id, history_path, state, created_by, created_at, updated_by, updated_at)
24
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
23
+ INSERT INTO checkpoints (
24
+ id, thread_id, checkpoint_id, current_node_id, history_path, state, engine_snapshot,
25
+ created_by, created_at, updated_by, updated_at
26
+ )
27
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
25
28
  ON CONFLICT (thread_id, checkpoint_id) DO UPDATE SET
26
29
  current_node_id = EXCLUDED.current_node_id,
27
30
  history_path = EXCLUDED.history_path,
28
31
  state = EXCLUDED.state,
32
+ engine_snapshot = EXCLUDED.engine_snapshot,
29
33
  updated_by = EXCLUDED.updated_by,
30
34
  updated_at = EXCLUDED.updated_at
31
35
  `;
@@ -36,6 +40,7 @@ export class PostgresCheckpointSaver {
36
40
  data.currentNodeId,
37
41
  JSON.stringify(data.historyPath),
38
42
  JSON.stringify(data.state),
43
+ data.engineSnapshot == null ? null : JSON.stringify(data.engineSnapshot),
39
44
  data.createdBy || 'system',
40
45
  data.createdAt,
41
46
  data.updatedBy || 'system',
@@ -105,6 +110,7 @@ export class PostgresCheckpointSaver {
105
110
  currentNodeId: source.currentNodeId,
106
111
  historyPath: source.historyPath,
107
112
  state: overrides ? { ...source.state, ...overrides } : source.state,
113
+ engineSnapshot: source.engineSnapshot,
108
114
  createdBy: 'fork',
109
115
  createdAt: now,
110
116
  updatedBy: 'fork',
@@ -128,6 +134,7 @@ export class PostgresCheckpointSaver {
128
134
  currentNodeId: row.current_node_id,
129
135
  historyPath: typeof row.history_path === 'string' ? JSON.parse(row.history_path) : row.history_path,
130
136
  state: typeof row.state === 'string' ? JSON.parse(row.state) : row.state,
137
+ engineSnapshot: parseJsonObject(row.engine_snapshot),
131
138
  createdBy: row.created_by,
132
139
  createdAt: row.created_at.toISOString(),
133
140
  updatedBy: row.updated_by,
@@ -138,3 +145,19 @@ export class PostgresCheckpointSaver {
138
145
  };
139
146
  }
140
147
  }
148
+ function parseJsonObject(value) {
149
+ if (value == null || value === '')
150
+ return undefined;
151
+ if (typeof value === 'object')
152
+ return value;
153
+ try {
154
+ const parsed = JSON.parse(value);
155
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
156
+ return parsed;
157
+ }
158
+ }
159
+ catch {
160
+ return undefined;
161
+ }
162
+ return undefined;
163
+ }
@@ -1,10 +1,8 @@
1
1
  /**
2
- * Agent 对外主键解析(迁移期双读)
3
- *
4
- * 正式字段为 agentCode;历史 agentId 仅作同义兜底。
2
+ * Agent 对外主键。只认 agentCode。
3
+ * SessionRecord.agentId 是存储列名(值为 agentCode),不是本函数的入参。
5
4
  */
6
5
  export declare function resolveAgentCode(input: {
7
6
  agentCode?: string | null;
8
- agentId?: string | null;
9
7
  fallback?: string;
10
8
  }): string;
@@ -1,12 +1,11 @@
1
1
  /**
2
- * Agent 对外主键解析(迁移期双读)
3
- *
4
- * 正式字段为 agentCode;历史 agentId 仅作同义兜底。
2
+ * Agent 对外主键。只认 agentCode。
3
+ * SessionRecord.agentId 是存储列名(值为 agentCode),不是本函数的入参。
5
4
  */
6
5
  export function resolveAgentCode(input) {
7
- const code = input.agentCode ?? input.agentId ?? input.fallback;
6
+ const code = input.agentCode ?? input.fallback;
8
7
  if (code == null || code === '') {
9
- throw new Error('agentCode is required (agentId synonym accepted during migration)');
8
+ throw new Error('agentCode is required');
10
9
  }
11
10
  return String(code);
12
11
  }
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * eap-runtime 内部共享类型定义
3
3
  *
4
- * 本文件定义 Runtime 模块内部使用的类型,与 @gt-fe/eap-contracts 中的公共协议类型互补但不重复。
5
- * - @gt-fe/eap-contracts 定义跨模块的公共协议(如 Task 实体、Session 实体、Agent Manifest)
4
+ * 本文件定义 Runtime 模块内部使用的类型,与 @eap/contracts 中的公共协议类型互补但不重复。
5
+ * - @eap/contracts 定义跨模块的公共协议(如 Task 实体、Session 实体、Agent Manifest)
6
6
  * - 本文件定义 Runtime 执行引擎内部流转的配置、上下文、枚举等
7
7
  */
8
8
  /**
@@ -32,7 +32,7 @@ export declare const DEFAULT_RUNTIME_CONFIG: RuntimeConfig;
32
32
  /**
33
33
  * 执行上下文 — 贯穿 Graph 执行生命周期(Runtime 内部)
34
34
  *
35
- * 平台级 ExecutionContext(@gt-fe/eap-contracts)由 Hosting/eap dev 注入;
35
+ * 平台级 ExecutionContext(@eap/contracts)由 Hosting/eap dev 注入;
36
36
  * 本类型在 Task 创建后组装,供引擎子服务使用。
37
37
  */
38
38
  export interface RuntimeRunContext {
@@ -62,7 +62,7 @@ export type TaskStatus = 'pending' | 'running' | 'waiting_hitl' | 'success' | 'f
62
62
  /**
63
63
  * Runtime 执行上下文绑定状态(非平台 Session 生命周期)
64
64
  *
65
- * 平台 Session 三态(active/paused/closed)由 Hosting 管理,见 @gt-fe/eap-contracts。
65
+ * 平台 Session 三态(active/paused/closed)由 Hosting 管理,见 @eap/contracts。
66
66
  * Runtime 仅在引擎内标记执行上下文是否仍可绑定:`active` | `archived`。
67
67
  */
68
68
  export type ExecutionSessionBindingStatus = 'active' | 'archived';
@@ -77,7 +77,7 @@ export type MessageRole = 'user' | 'assistant' | 'system' | 'tool';
77
77
  /**
78
78
  * 单次 LLM/Tool 调用的 Token 消耗记录
79
79
  *
80
- * 与 @gt-fe/eap-contracts.TokenUsage 的区别:
80
+ * 与 @eap/contracts.TokenUsage 的区别:
81
81
  * - contracts 版本是 Task 级聚合结果(含 byNode/byModel)
82
82
  * - 本类型是单次调用粒度的原始记录,用于 Runtime 内部累计和 stats.node_token 事件
83
83
  */
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * eap-runtime 内部共享类型定义
3
3
  *
4
- * 本文件定义 Runtime 模块内部使用的类型,与 @gt-fe/eap-contracts 中的公共协议类型互补但不重复。
5
- * - @gt-fe/eap-contracts 定义跨模块的公共协议(如 Task 实体、Session 实体、Agent Manifest)
4
+ * 本文件定义 Runtime 模块内部使用的类型,与 @eap/contracts 中的公共协议类型互补但不重复。
5
+ * - @eap/contracts 定义跨模块的公共协议(如 Task 实体、Session 实体、Agent Manifest)
6
6
  * - 本文件定义 Runtime 执行引擎内部流转的配置、上下文、枚举等
7
7
  */
8
8
  /** RuntimeConfig 默认值 */
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * 权限校验器接口(对齐 06-governance R16.8)
3
3
  */
4
- import type { ExecutionContext, GovernancePermissionCheckParams, GovernancePermissionCheckResult } from '@gt-fe/eap-contracts';
4
+ import type { ExecutionContext, GovernancePermissionCheckParams, GovernancePermissionCheckResult } from '@eap/contracts';
5
5
  /**
6
6
  * IPermissionChecker — Runtime 执行期权限校验
7
7
  */
@@ -82,9 +82,9 @@ export interface ExecutionNodeEvent {
82
82
  /** 节点名称 */
83
83
  name: string;
84
84
  /** 节点类型 */
85
- type: 'start' | 'llm' | 'tool' | 'skill' | 'condition' | 'end';
85
+ type: 'start' | 'llm' | 'tool' | 'skill' | 'condition' | 'hitl' | 'end';
86
86
  /** 工具运行环境(type=tool) */
87
- toolRuntime?: 'local' | 'server' | 'both' | 'mock';
87
+ toolRuntime?: 'local' | 'server' | 'both';
88
88
  /** Agent 对外主键 */
89
89
  agentCode?: string;
90
90
  /** 输入数据 */
@@ -184,6 +184,20 @@ export interface ITraceCollector {
184
184
  outputTokens?: number;
185
185
  totalTokens?: number;
186
186
  }): Promise<void>;
187
+ /**
188
+ * Checkpoint 已落盘后的引用回调。Hosting 适配 TraceClient.recordCheckpointRef。
189
+ * Runtime 仅在同时有 traceId 与 spanId 时调用;不传 graph state 正文。
190
+ */
191
+ recordCheckpointRef?(input: {
192
+ checkpointId: string;
193
+ traceId: string;
194
+ spanId: string;
195
+ summary?: {
196
+ nodeId?: string;
197
+ threadId?: string;
198
+ step?: number;
199
+ };
200
+ }): Promise<void>;
187
201
  /**
188
202
  * 创建链路
189
203
  *
@@ -0,0 +1,100 @@
1
+ /**
2
+ * 本地 LLM 回合落盘:每次模型调用写一份 JSON(入参、响应、URL、脱敏密钥、system 段)。
3
+ * 默认 `.eap/llm-turns/{sessionId}/`。EAP_LLM_TURN_LOG=0 关闭。
4
+ */
5
+ export interface LlmTurnContext {
6
+ sessionId?: string;
7
+ taskId?: string;
8
+ nodeId?: string;
9
+ agentCode?: string;
10
+ correlationId?: string;
11
+ }
12
+ export interface LlmTurnRecord extends LlmTurnContext {
13
+ id: string;
14
+ ts: string;
15
+ url: string;
16
+ model: string;
17
+ temperature?: number;
18
+ maxTokens?: number;
19
+ apiKey: string;
20
+ systemPrompt?: string;
21
+ systemSections?: Array<{
22
+ id: string;
23
+ title: string;
24
+ chars: number;
25
+ body?: string;
26
+ }>;
27
+ tools?: string[];
28
+ messages: Array<{
29
+ role: string;
30
+ content: string;
31
+ toolCallId?: string;
32
+ toolCalls?: unknown;
33
+ }>;
34
+ response: {
35
+ content: string;
36
+ toolCalls?: unknown;
37
+ reasoningContent?: string;
38
+ inputTokens: number;
39
+ outputTokens: number;
40
+ finishReason?: string;
41
+ error?: string;
42
+ };
43
+ latencyMs: number;
44
+ }
45
+ export interface LlmTurnIndexEntry {
46
+ id: string;
47
+ ts: string;
48
+ sessionId?: string;
49
+ taskId?: string;
50
+ nodeId?: string;
51
+ model: string;
52
+ url: string;
53
+ file: string;
54
+ inputTokens: number;
55
+ outputTokens: number;
56
+ }
57
+ export type LlmTurnLogKind = 'memory' | 'file' | 'postgres';
58
+ export interface ILlmTurnLog {
59
+ readonly kind: LlmTurnLogKind;
60
+ record(turn: Omit<LlmTurnRecord, 'id' | 'ts'> & {
61
+ id?: string;
62
+ ts?: string;
63
+ }): Promise<LlmTurnRecord>;
64
+ list(sessionId: string): Promise<LlmTurnIndexEntry[]>;
65
+ read(sessionId: string, turnId: string): Promise<LlmTurnRecord | null>;
66
+ listSessions(): Promise<string[]>;
67
+ readonly baseDir: string;
68
+ }
69
+ export declare function finalizeLlmTurn(turn: Omit<LlmTurnRecord, 'id' | 'ts'> & {
70
+ id?: string;
71
+ ts?: string;
72
+ }): LlmTurnRecord;
73
+ export declare function toLlmTurnIndexEntry(record: LlmTurnRecord, file?: string): LlmTurnIndexEntry;
74
+ export declare function maskApiKey(key: string | undefined): string;
75
+ export declare function resolveLlmTurnDir(env?: NodeJS.ProcessEnv, cwd?: string): string;
76
+ export declare function createFileLlmTurnLogFromEnv(env?: NodeJS.ProcessEnv): FileLlmTurnLog | undefined;
77
+ export declare class InMemoryLlmTurnLog implements ILlmTurnLog {
78
+ readonly kind: "memory";
79
+ readonly baseDir = "memory://llm-turns";
80
+ private readonly bySession;
81
+ record(turn: Omit<LlmTurnRecord, 'id' | 'ts'> & {
82
+ id?: string;
83
+ ts?: string;
84
+ }): Promise<LlmTurnRecord>;
85
+ list(sessionId: string): Promise<LlmTurnIndexEntry[]>;
86
+ read(sessionId: string, turnId: string): Promise<LlmTurnRecord | null>;
87
+ listSessions(): Promise<string[]>;
88
+ }
89
+ export declare class FileLlmTurnLog implements ILlmTurnLog {
90
+ readonly baseDir: string;
91
+ readonly kind: "file";
92
+ constructor(baseDir: string);
93
+ record(turn: Omit<LlmTurnRecord, 'id' | 'ts'> & {
94
+ id?: string;
95
+ ts?: string;
96
+ }): Promise<LlmTurnRecord>;
97
+ list(sessionId: string): Promise<LlmTurnIndexEntry[]>;
98
+ read(sessionId: string, turnId: string): Promise<LlmTurnRecord | null>;
99
+ listSessions(): Promise<string[]>;
100
+ }