@gt-fe/eap-runtime 0.0.20 → 0.0.22

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 (133) hide show
  1. package/README.md +4 -3
  2. package/dist/api/handlers/invoke.handler.d.ts +7 -0
  3. package/dist/api/handlers/invoke.handler.js +52 -10
  4. package/dist/api/handlers/stream.handler.d.ts +6 -0
  5. package/dist/api/handlers/stream.handler.js +60 -39
  6. package/dist/api/routes/agent.routes.d.ts +8 -1
  7. package/dist/checkpoint/file-checkpoint-saver.d.ts +4 -0
  8. package/dist/checkpoint/file-checkpoint-saver.js +51 -22
  9. package/dist/checkpoint/index.d.ts +1 -1
  10. package/dist/checkpoint/index.js +1 -1
  11. package/dist/common/types.d.ts +2 -2
  12. package/dist/common/types.js +1 -1
  13. package/dist/execution/index.d.ts +2 -0
  14. package/dist/execution/index.js +2 -0
  15. package/dist/execution/interceptors.d.ts +40 -0
  16. package/dist/execution/interceptors.js +23 -0
  17. package/dist/execution/ports.d.ts +18 -0
  18. package/dist/execution/ports.js +13 -0
  19. package/dist/governance/audit-reporter.d.ts +14 -0
  20. package/dist/governance/audit-reporter.js +18 -0
  21. package/dist/governance/index.d.ts +2 -0
  22. package/dist/governance/index.js +1 -0
  23. package/dist/governance/permission-guard.d.ts +6 -2
  24. package/dist/governance/permission-guard.js +38 -5
  25. package/dist/graph/adapters/graph-nesting.d.ts +12 -0
  26. package/dist/graph/adapters/graph-nesting.js +29 -0
  27. package/dist/graph/adapters/index.d.ts +2 -0
  28. package/dist/graph/adapters/index.js +2 -0
  29. package/dist/graph/adapters/langgraph-checkpointer.d.ts +11 -0
  30. package/dist/graph/adapters/langgraph-checkpointer.js +48 -9
  31. package/dist/graph/adapters/langgraph.adapter.d.ts +33 -11
  32. package/dist/graph/adapters/langgraph.adapter.js +200 -98
  33. package/dist/graph/adapters/skill-isolate.d.ts +13 -0
  34. package/dist/graph/adapters/skill-isolate.js +39 -0
  35. package/dist/graph/adapters/subgraph-compiler.d.ts +7 -2
  36. package/dist/graph/adapters/subgraph-compiler.js +63 -30
  37. package/dist/graph/contracts/executable-graph.d.ts +33 -5
  38. package/dist/graph/hitl/hitl-handler.d.ts +13 -4
  39. package/dist/graph/hitl/hitl-handler.js +80 -7
  40. package/dist/graph/nodes/index.d.ts +1 -0
  41. package/dist/graph/nodes/index.js +1 -0
  42. package/dist/graph/nodes/llm-node.d.ts +3 -1
  43. package/dist/graph/nodes/llm-node.js +26 -2
  44. package/dist/graph/nodes/rag/dedup.d.ts +20 -0
  45. package/dist/graph/nodes/rag/dedup.js +77 -0
  46. package/dist/graph/nodes/rag/denoise.d.ts +58 -0
  47. package/dist/graph/nodes/rag/denoise.js +220 -0
  48. package/dist/graph/nodes/rag/fusion/fuse.d.ts +11 -0
  49. package/dist/graph/nodes/rag/fusion/fuse.js +25 -0
  50. package/dist/graph/nodes/rag/fusion/normalize.d.ts +9 -0
  51. package/dist/graph/nodes/rag/fusion/normalize.js +135 -0
  52. package/dist/graph/nodes/rag/index.d.ts +18 -0
  53. package/dist/graph/nodes/rag/index.js +17 -0
  54. package/dist/graph/nodes/rag/prompts.d.ts +12 -0
  55. package/dist/graph/nodes/rag/prompts.js +40 -0
  56. package/dist/graph/nodes/rag/rag-node.d.ts +21 -0
  57. package/dist/graph/nodes/rag/rag-node.js +135 -0
  58. package/dist/graph/nodes/rag/rag-search-tool.d.ts +48 -0
  59. package/dist/graph/nodes/rag/rag-search-tool.js +230 -0
  60. package/dist/graph/nodes/rag/react-loop.d.ts +57 -0
  61. package/dist/graph/nodes/rag/react-loop.js +467 -0
  62. package/dist/graph/nodes/rag/retrievers/http-embedder.d.ts +29 -0
  63. package/dist/graph/nodes/rag/retrievers/http-embedder.js +66 -0
  64. package/dist/graph/nodes/rag/retrievers/in-memory-retriever.d.ts +17 -0
  65. package/dist/graph/nodes/rag/retrievers/in-memory-retriever.js +18 -0
  66. package/dist/graph/nodes/rag/retrievers/local-sqlite-retriever.d.ts +46 -0
  67. package/dist/graph/nodes/rag/retrievers/local-sqlite-retriever.js +85 -0
  68. package/dist/graph/nodes/rag/tools.d.ts +90 -0
  69. package/dist/graph/nodes/rag/tools.js +260 -0
  70. package/dist/graph/nodes/rag/types.d.ts +226 -0
  71. package/dist/graph/nodes/rag/types.js +9 -0
  72. package/dist/graph/nodes/tool-node.d.ts +19 -1
  73. package/dist/graph/nodes/tool-node.js +158 -33
  74. package/dist/index.d.ts +2 -0
  75. package/dist/index.js +1 -0
  76. package/dist/memory/semantic-retrieval.service.d.ts +1 -1
  77. package/dist/memory/semantic-retrieval.service.js +13 -23
  78. package/dist/providers/index.d.ts +2 -2
  79. package/dist/providers/index.js +2 -2
  80. package/dist/providers/local-llm-provider.d.ts +6 -0
  81. package/dist/providers/local-llm-provider.js +29 -5
  82. package/dist/providers/routing-llm-provider.d.ts +7 -2
  83. package/dist/providers/routing-llm-provider.js +71 -16
  84. package/dist/registry/deployment-snapshot.js +18 -4
  85. package/dist/registry/graph-loader.d.ts +2 -0
  86. package/dist/registry/graph-loader.js +39 -2
  87. package/dist/registry/preload-flags.d.ts +1 -1
  88. package/dist/registry/preload-flags.js +1 -1
  89. package/dist/runtime/agent-runtime.d.ts +5 -0
  90. package/dist/runtime/agent-runtime.js +107 -70
  91. package/dist/runtime/dev-rag-deps.d.ts +21 -0
  92. package/dist/runtime/dev-rag-deps.js +186 -0
  93. package/dist/runtime/dev-runtime.d.ts +18 -2
  94. package/dist/runtime/dev-runtime.js +68 -8
  95. package/dist/runtime/index.d.ts +1 -1
  96. package/dist/runtime/types.d.ts +10 -9
  97. package/dist/session/apply-session-compression.d.ts +85 -0
  98. package/dist/session/apply-session-compression.js +281 -0
  99. package/dist/session/apply-session-memory.d.ts +21 -0
  100. package/dist/session/apply-session-memory.js +48 -0
  101. package/dist/session/index.d.ts +2 -0
  102. package/dist/session/index.js +2 -0
  103. package/dist/session/persist-turn-messages.d.ts +57 -1
  104. package/dist/session/persist-turn-messages.js +160 -5
  105. package/dist/sse/events/index.d.ts +13 -4
  106. package/dist/sse/events/index.js +9 -1
  107. package/dist/sse/events/rag-events.d.ts +63 -0
  108. package/dist/sse/events/rag-events.js +9 -0
  109. package/dist/sse/events/session-events.d.ts +38 -0
  110. package/dist/sse/events/session-events.js +4 -0
  111. package/dist/token/index.d.ts +2 -1
  112. package/dist/token/index.js +2 -1
  113. package/dist/token/record-task-token-usage.d.ts +25 -0
  114. package/dist/token/record-task-token-usage.js +44 -0
  115. package/dist/token/token-detail-mode.d.ts +4 -4
  116. package/dist/token/token-detail-mode.js +4 -4
  117. package/dist/token/token-detail.d.ts +8 -0
  118. package/dist/token/token-detail.js +22 -0
  119. package/dist/token/token-stats.service.d.ts +2 -2
  120. package/dist/token/token-stats.service.js +1 -1
  121. package/dist/tool/create-tool-executor.d.ts +6 -0
  122. package/dist/tool/create-tool-executor.js +4 -3
  123. package/dist/tool/harness-primitives.d.ts +9 -1
  124. package/dist/tool/harness-primitives.js +43 -12
  125. package/dist/tool/index.d.ts +2 -1
  126. package/dist/tool/index.js +2 -1
  127. package/dist/tool/tool-confirmation.js +8 -5
  128. package/dist/tool/tool-executor.interface.d.ts +27 -0
  129. package/dist/tool/tool-orchestrator.d.ts +3 -1
  130. package/dist/tool/tool-orchestrator.js +15 -6
  131. package/dist/tool/tool-retry.d.ts +15 -0
  132. package/dist/tool/tool-retry.js +69 -0
  133. package/package.json +2 -2
@@ -4,13 +4,13 @@
4
4
  * 收集每次 LLM 调用的 Token 消耗,按 taskId 聚合统计。
5
5
  * 提供 total/byNode/byModel 多维度汇总能力。
6
6
  *
7
- * @see design.md §1.6 stats.token_usage / stats.node_token 事件
7
+ * @see design.md §1.6 stats.token_usage / stats.node_token_usage 事件
8
8
  * @see requirements.md Requirement 6 AC1-AC4
9
9
  */
10
10
  /**
11
11
  * NodeTokenUsage — 单次 LLM 调用的 Token 消耗数据
12
12
  *
13
- * 对应 SSE 事件 stats.node_token 的 payload 结构。
13
+ * 对应 SSE 事件 stats.node_token_usage 的 payload 结构。
14
14
  */
15
15
  export interface NodeTokenUsage {
16
16
  /** 产生消耗的节点 ID */
@@ -4,7 +4,7 @@
4
4
  * 收集每次 LLM 调用的 Token 消耗,按 taskId 聚合统计。
5
5
  * 提供 total/byNode/byModel 多维度汇总能力。
6
6
  *
7
- * @see design.md §1.6 stats.token_usage / stats.node_token 事件
7
+ * @see design.md §1.6 stats.token_usage / stats.node_token_usage 事件
8
8
  * @see requirements.md Requirement 6 AC1-AC4
9
9
  */
10
10
  // ─────────────────────────────────────────────
@@ -10,6 +10,7 @@
10
10
  import type { ILocalToolInstallStore, LocalToolInstallRecord } from '@gt-fe/eap-contracts';
11
11
  import { type DeploymentContext } from './tool-execution-router.js';
12
12
  import type { IToolExecutor } from './tool-executor.interface.js';
13
+ import { type HarnessJailOptions } from './harness-primitives.js';
13
14
  export declare class EmptyInstallStore implements ILocalToolInstallStore {
14
15
  get(): null;
15
16
  listReady(): LocalToolInstallRecord[];
@@ -28,6 +29,11 @@ export interface CreateToolExecutorOptions {
28
29
  * 也可用环境变量 EAP_TOOL_GATEWAY_TRANSPORT=http|mcp。
29
30
  */
30
31
  gatewayTransport?: ToolGatewayTransport;
32
+ /**
33
+ * 开发 overlay jail。缺省则在本函数调用时从 process.env 捕获。
34
+ * SDK createAgent 会在 createDevRuntime 返回后恢复 env,必须在那时之前钉死。
35
+ */
36
+ jail?: HarnessJailOptions;
31
37
  }
32
38
  /**
33
39
  * 创建经 ToolExecutionRouter 包装的 IToolExecutor(生产装配入口)
@@ -11,7 +11,7 @@ import { HttpToolExecutor } from './http-tool-executor.js';
11
11
  import { isAbsoluteHttpUrl, McpToolExecutor } from './mcp-tool-executor.js';
12
12
  import { LocalToolExecutor } from './local-tool-executor.js';
13
13
  import { ToolExecutionRouter, } from './tool-execution-router.js';
14
- import { withHarnessPrimitives } from './harness-primitives.js';
14
+ import { captureOverlayJailOptions, withHarnessPrimitives, } from './harness-primitives.js';
15
15
  export class EmptyInstallStore {
16
16
  get() {
17
17
  return null;
@@ -51,8 +51,9 @@ export function createToolExecutor(options) {
51
51
  const localExecutor = new LocalToolExecutor({ installStore });
52
52
  const deploymentContext = resolveDeploymentContext(options.deploymentContext);
53
53
  const hasGateway = isAbsoluteHttpUrl(options.foundationUrl);
54
+ const jail = options.jail ?? captureOverlayJailOptions();
54
55
  if (!hasGateway && (deploymentContext === 'desktop' || deploymentContext === 'dev')) {
55
- return withHarnessPrimitives(localExecutor);
56
+ return withHarnessPrimitives(localExecutor, jail);
56
57
  }
57
58
  const transport = resolveGatewayTransport(options.gatewayTransport);
58
59
  const serverExecutor = createServerExecutor(options.foundationUrl, transport, options.httpTimeout);
@@ -64,5 +65,5 @@ export function createToolExecutor(options) {
64
65
  toolTypes: options.toolTypes,
65
66
  toolRuntimes: options.toolRuntimes,
66
67
  forceToolServer: options.forceToolServer,
67
- }));
68
+ }), jail);
68
69
  }
@@ -5,7 +5,9 @@
5
5
  * 写:`users/<userId>/`(含用户自己的 skills)。
6
6
  * 读:写根 + 已装配 `preinstall/tools`、`preinstall/skills`。
7
7
  * 命令:cwd 仅写根。技能包只读,EAP_SKILL_DIR 为整包绝对根(不限 scripts/)。不把预装拷进用户装配槽。
8
- * 开发态可选 overlay:`EAP_LOCAL_SKILLS_DIR` / `EAP_LOCAL_TOOLS_DIR`(只读)。
8
+ * 开发态 overlay:`EAP_LOCAL_SKILLS_DIR` / `EAP_LOCAL_TOOLS_DIR`(只读)。在 `createDevRuntime` /
9
+ * `createToolExecutor` 时钉进执行器 extraRoots;SDK `createAgent` 构造完会恢复 process.env,
10
+ * 请求时不再读这两项。相对 `read_file` 会把 overlay 根下直接子目录里带 SKILL.md 的包纳入唯一命中。
9
11
  */
10
12
  import type { LoadedToolMap } from './loaded-tool-definition.js';
11
13
  import type { IToolExecutor, ToolCallRequest, ToolCallResult } from './tool-executor.interface.js';
@@ -31,6 +33,12 @@ export declare function resolveJailFromState(state: {
31
33
  bundlePath?: string;
32
34
  }>;
33
35
  }): HarnessJailOptions;
36
+ /**
37
+ * 把开发 overlay 钉进 Harness extraRoots。
38
+ * SDK `createAgent` 在 createDevRuntime 返回后恢复 process.env,请求时不能再读这两项。
39
+ */
40
+ export declare function captureOverlayJailOptions(env?: NodeJS.ProcessEnv): Pick<HarnessJailOptions, 'extraRoots'>;
41
+ /** 只认 workdir + extraRoots。开发 overlay 必须由调用方在构造时传入,不在此处读 process.env。 */
34
42
  export declare function resolveJailRoots(options?: HarnessJailOptions): string[];
35
43
  /** 路径落在写根外的 extraRoot 时,返回该 extraRoot。 */
36
44
  export declare function extraRootContaining(abs: string, extraRoots: string[], workdir: string): string | undefined;
@@ -5,10 +5,12 @@
5
5
  * 写:`users/<userId>/`(含用户自己的 skills)。
6
6
  * 读:写根 + 已装配 `preinstall/tools`、`preinstall/skills`。
7
7
  * 命令:cwd 仅写根。技能包只读,EAP_SKILL_DIR 为整包绝对根(不限 scripts/)。不把预装拷进用户装配槽。
8
- * 开发态可选 overlay:`EAP_LOCAL_SKILLS_DIR` / `EAP_LOCAL_TOOLS_DIR`(只读)。
8
+ * 开发态 overlay:`EAP_LOCAL_SKILLS_DIR` / `EAP_LOCAL_TOOLS_DIR`(只读)。在 `createDevRuntime` /
9
+ * `createToolExecutor` 时钉进执行器 extraRoots;SDK `createAgent` 构造完会恢复 process.env,
10
+ * 请求时不再读这两项。相对 `read_file` 会把 overlay 根下直接子目录里带 SKILL.md 的包纳入唯一命中。
9
11
  */
10
12
  import { spawn } from 'node:child_process';
11
- import { constants as fsConstants, existsSync, realpathSync } from 'node:fs';
13
+ import { constants as fsConstants, existsSync, readdirSync, realpathSync } from 'node:fs';
12
14
  import { mkdir, open, readFile } from 'node:fs/promises';
13
15
  import path from 'node:path';
14
16
  import { BUILTIN_TOOL_SOURCE, DEFAULT_BUILTIN_TIMEOUT_MS, MAX_BUILTIN_TIMEOUT_MS, clampBuiltinTimeout, isBuiltinToolExecution, resolveBuiltinToolsConfig, } from '@gt-fe/eap-contracts';
@@ -150,21 +152,29 @@ export function resolveJailFromState(state) {
150
152
  extraRoots: scoped,
151
153
  };
152
154
  }
153
- function deploymentAllowsLocalOverlay() {
154
- const ctx = process.env.EAP_DEPLOYMENT_CONTEXT?.trim();
155
+ function deploymentAllowsLocalOverlay(env = process.env) {
156
+ const ctx = env.EAP_DEPLOYMENT_CONTEXT?.trim();
155
157
  return ctx === 'dev' || ctx === 'desktop';
156
158
  }
157
- function devOverlayRoots() {
158
- if (!deploymentAllowsLocalOverlay())
159
+ function overlayRootsFromEnv(env = process.env) {
160
+ if (!deploymentAllowsLocalOverlay(env))
159
161
  return [];
160
162
  const extra = [];
161
163
  for (const key of ['EAP_LOCAL_SKILLS_DIR', 'EAP_LOCAL_TOOLS_DIR']) {
162
- const value = process.env[key]?.trim();
164
+ const value = env[key]?.trim();
163
165
  if (value)
164
166
  extra.push(value);
165
167
  }
166
168
  return extra;
167
169
  }
170
+ /**
171
+ * 把开发 overlay 钉进 Harness extraRoots。
172
+ * SDK `createAgent` 在 createDevRuntime 返回后恢复 process.env,请求时不能再读这两项。
173
+ */
174
+ export function captureOverlayJailOptions(env = process.env) {
175
+ const extraRoots = overlayRootsFromEnv(env);
176
+ return extraRoots.length > 0 ? { extraRoots } : {};
177
+ }
168
178
  function tryRealpath(p) {
169
179
  try {
170
180
  return realpathSync(p);
@@ -173,11 +183,11 @@ function tryRealpath(p) {
173
183
  return undefined;
174
184
  }
175
185
  }
186
+ /** 只认 workdir + extraRoots。开发 overlay 必须由调用方在构造时传入,不在此处读 process.env。 */
176
187
  export function resolveJailRoots(options) {
177
188
  const workdir = options?.workdir?.trim() ? path.resolve(options.workdir) : undefined;
178
189
  const candidates = [
179
190
  ...(workdir ? [workdir] : []),
180
- ...devOverlayRoots(),
181
191
  ...(options?.extraRoots ?? []),
182
192
  ];
183
193
  const roots = [];
@@ -257,16 +267,37 @@ function userReadBase(workdir) {
257
267
  ? (tryRealpath(path.resolve(workdir)) ?? path.resolve(workdir))
258
268
  : undefined;
259
269
  }
270
+ function isSkillPackageDir(dir) {
271
+ return existsSync(path.join(dir, 'SKILL.md')) || existsSync(path.join(dir, 'skill.md'));
272
+ }
260
273
  function skillPackageRoots(roots) {
261
274
  const out = [];
262
275
  const seen = new Set();
276
+ const add = (dir) => {
277
+ if (seen.has(dir))
278
+ return;
279
+ seen.add(dir);
280
+ out.push(dir);
281
+ };
263
282
  for (const root of roots) {
264
283
  const resolved = path.resolve(root);
265
- if (seen.has(resolved))
284
+ if (isSkillPackageDir(resolved)) {
285
+ add(resolved);
266
286
  continue;
267
- seen.add(resolved);
268
- if (existsSync(path.join(resolved, 'SKILL.md')) || existsSync(path.join(resolved, 'skill.md'))) {
269
- out.push(resolved);
287
+ }
288
+ let entries;
289
+ try {
290
+ entries = readdirSync(resolved, { withFileTypes: true });
291
+ }
292
+ catch {
293
+ continue;
294
+ }
295
+ for (const ent of entries) {
296
+ if (!ent.isDirectory())
297
+ continue;
298
+ const child = path.join(resolved, ent.name);
299
+ if (isSkillPackageDir(child))
300
+ add(child);
270
301
  }
271
302
  }
272
303
  return out;
@@ -2,6 +2,7 @@ export type { AuthContext, ToolCallRequest, ToolCallResult, LLMToolCall, LLMTool
2
2
  export { hydrateMcpTools, isMcpDiscoverStub, needsMcpHydration, parseListedTools, toolsetCodeFromLoaded, toolTraceIdentity, } from './mcp-list.js';
3
3
  export { toLoadedToolMap, type LoadedToolDefinition, type LoadedToolMap, type LoadedToolManifestRef, } from './loaded-tool-definition.js';
4
4
  export { ToolOrchestrator } from './tool-orchestrator.js';
5
+ export { isRetryableToolFailure, resolveToolRetryConfig, type ToolFailureShape, } from './tool-retry.js';
5
6
  export { HttpToolExecutor, type HttpToolExecutorOptions, } from './http-tool-executor.js';
6
7
  export { McpToolExecutor, isAbsoluteHttpUrl, type McpToolExecutorOptions, } from './mcp-tool-executor.js';
7
8
  export { LocalToolExecutor, isLocalPreferredExecution, resolveCodeExecutionFromRequest } from './local-tool-executor.js';
@@ -12,7 +13,7 @@ export { LocalMcpClient, type ILocalMcpClient, type LocalMcpInvokeContext, type
12
13
  export { fileArtifactFromToolOutput, extractFileReference, resolveFileArtifact, type FileArtifact, } from './file-artifact.js';
13
14
  export { ToolExecutionRouter, type DeploymentContext, type ToolExecutionRouterOptions, } from './tool-execution-router.js';
14
15
  export { createToolExecutor, EmptyInstallStore, type CreateToolExecutorOptions, } from './create-tool-executor.js';
15
- export { assembleLoadedTools, mergeHarnessPrimitives as mergeBuiltinTools, withHarnessPrimitives as withBuiltinTools, HarnessPrimitiveExecutor as BuiltinToolExecutor, resolveUserDir, resolveJailFromState, collectToolBundlePaths, type HarnessJailOptions as BuiltinJailOptions, } from './harness-primitives.js';
16
+ export { assembleLoadedTools, mergeHarnessPrimitives as mergeBuiltinTools, withHarnessPrimitives as withBuiltinTools, HarnessPrimitiveExecutor as BuiltinToolExecutor, resolveUserDir, resolveJailFromState, captureOverlayJailOptions, collectToolBundlePaths, type HarnessJailOptions as BuiltinJailOptions, } from './harness-primitives.js';
16
17
  export { resolveShellSpawn, shellNameFor, commandDialectLines, findPythonInterpreter, findNodeInterpreter, ensureInterpreterShims, substituteSkillDir, } from './harness-command.js';
17
18
  export { expandSkillScriptRefs, isSkillEntryFile, EAP_SKILL_DIR_ENV, } from './skill-script-refs.js';
18
19
  export { ToolResultInjector, type ToolMessage, } from './tool-result-injector.js';
@@ -1,6 +1,7 @@
1
1
  export { hydrateMcpTools, isMcpDiscoverStub, needsMcpHydration, parseListedTools, toolsetCodeFromLoaded, toolTraceIdentity, } from './mcp-list.js';
2
2
  export { toLoadedToolMap, } from './loaded-tool-definition.js';
3
3
  export { ToolOrchestrator } from './tool-orchestrator.js';
4
+ export { isRetryableToolFailure, resolveToolRetryConfig, } from './tool-retry.js';
4
5
  export { HttpToolExecutor, } from './http-tool-executor.js';
5
6
  export { McpToolExecutor, isAbsoluteHttpUrl, } from './mcp-tool-executor.js';
6
7
  export { LocalToolExecutor, isLocalPreferredExecution, resolveCodeExecutionFromRequest } from './local-tool-executor.js';
@@ -11,7 +12,7 @@ export { LocalMcpClient, } from './local-mcp-client.js';
11
12
  export { fileArtifactFromToolOutput, extractFileReference, resolveFileArtifact, } from './file-artifact.js';
12
13
  export { ToolExecutionRouter, } from './tool-execution-router.js';
13
14
  export { createToolExecutor, EmptyInstallStore, } from './create-tool-executor.js';
14
- export { assembleLoadedTools, mergeHarnessPrimitives as mergeBuiltinTools, withHarnessPrimitives as withBuiltinTools, HarnessPrimitiveExecutor as BuiltinToolExecutor, resolveUserDir, resolveJailFromState, collectToolBundlePaths, } from './harness-primitives.js';
15
+ export { assembleLoadedTools, mergeHarnessPrimitives as mergeBuiltinTools, withHarnessPrimitives as withBuiltinTools, HarnessPrimitiveExecutor as BuiltinToolExecutor, resolveUserDir, resolveJailFromState, captureOverlayJailOptions, collectToolBundlePaths, } from './harness-primitives.js';
15
16
  export { resolveShellSpawn, shellNameFor, commandDialectLines, findPythonInterpreter, findNodeInterpreter, ensureInterpreterShims, substituteSkillDir, } from './harness-command.js';
16
17
  export { expandSkillScriptRefs, isSkillEntryFile, EAP_SKILL_DIR_ENV, } from './skill-script-refs.js';
17
18
  export { ToolResultInjector, } from './tool-result-injector.js';
@@ -9,6 +9,7 @@
9
9
  * @see tasks.md Task 17
10
10
  */
11
11
  import { DEFAULT_HITL_TIMEOUT_MS, HitlPausedError, } from '../graph/hitl/hitl-handler.js';
12
+ import { checkpointStorageThreadId } from '../graph/adapters/langgraph-checkpointer.js';
12
13
  import { resolveCheckpointThreadId } from '../session/persist-turn-messages.js';
13
14
  export class ToolConfirmationInterceptor {
14
15
  confirmationTools;
@@ -54,11 +55,13 @@ export class ToolConfirmationInterceptor {
54
55
  errorCode: 'hitl_rejected',
55
56
  };
56
57
  }
57
- const resolvedThreadId = threadId ??
58
- resolveCheckpointThreadId({
59
- sessionId: typeof state.sessionId === 'string' ? state.sessionId : undefined,
60
- taskId,
61
- });
58
+ const sessionId = typeof state.sessionId === 'string' && state.sessionId.trim()
59
+ ? state.sessionId.trim()
60
+ : undefined;
61
+ const parentThreadId = sessionId ??
62
+ threadId ??
63
+ resolveCheckpointThreadId({ taskId });
64
+ const resolvedThreadId = checkpointStorageThreadId(parentThreadId, typeof state.checkpointNs === 'string' ? state.checkpointNs : undefined);
62
65
  const question = `确认执行 ${request.toolName}?\n参数: ${JSON.stringify(request.arguments)}`;
63
66
  const options = ['confirm', 'reject'];
64
67
  const timeoutMs = DEFAULT_HITL_TIMEOUT_MS;
@@ -61,6 +61,33 @@ export interface ToolCallRequest {
61
61
  * 对标 Claude CLAUDE_SKILL_DIR。
62
62
  */
63
63
  skillDir?: string;
64
+ /**
65
+ * 会话级 rag 数据源勾选(数据源 id 列表,tool 节点从 GraphState 转递)。
66
+ * RagSearchToolExecutor 等检索型装饰器消费;普通工具执行器忽略。
67
+ */
68
+ ragSources?: string[];
69
+ /**
70
+ * 图声明的 rag 检索面(tool 节点 config.retrievalSources 原样转递,工具形态声明位)。
71
+ * RagSearchToolExecutor 以其为该请求的数据源目录(覆盖装配期配置);
72
+ * 普通工具执行器忽略。
73
+ */
74
+ ragSourcesConfig?: import('../graph/nodes/rag/types.js').RagRetrievalSources;
75
+ /**
76
+ * 图声明的融合总条数(tool 节点 config.totalK 原样转递,工具形态声明位)。
77
+ * RagSearchToolExecutor 以其为该请求的 totalK 缺省(调用级 topK 参数仍可覆盖);
78
+ * 普通工具执行器忽略。
79
+ */
80
+ ragTotalK?: number;
81
+ /**
82
+ * 请求级 rag 检索范围(fileIds/dirPaths,tool 节点从 GraphState 转递)。
83
+ * 与 ragSources 同一消费面。
84
+ */
85
+ ragScope?: import('../graph/nodes/rag/types.js').RagScope;
86
+ /**
87
+ * 本轮 loadedTools 快照(tool 节点从 GraphState 转递,引用传递零拷贝)。
88
+ * rag_search 装饰器据此组装内层工具表(含会话勾选后的圈定);普通执行器忽略。
89
+ */
90
+ loadedTools?: import('./loaded-tool-definition.js').LoadedToolMap;
64
91
  }
65
92
  /**
66
93
  * ToolCallResult — Tool 调用结果
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import { type ExecutionContext } from '@gt-fe/eap-contracts';
8
8
  import type { IGovernanceClient } from '../governance/governance-client.js';
9
+ import type { IAuditReporter } from '../governance/audit-reporter.js';
9
10
  export type { AuthContext, ToolCallRequest, ToolCallResult, LLMToolCall, LLMToolCallResponse, IToolExecutor, } from './tool-executor.interface.js';
10
11
  import type { AuthContext, ToolCallRequest, ToolCallResult, LLMToolCallResponse, IToolExecutor } from './tool-executor.interface.js';
11
12
  /**
@@ -14,7 +15,8 @@ import type { AuthContext, ToolCallRequest, ToolCallResult, LLMToolCallResponse,
14
15
  export declare class ToolOrchestrator {
15
16
  private readonly toolExecutor;
16
17
  private readonly governanceClient?;
17
- constructor(toolExecutor: IToolExecutor, governanceClient?: IGovernanceClient | undefined);
18
+ private readonly auditReporter?;
19
+ constructor(toolExecutor: IToolExecutor, governanceClient?: IGovernanceClient | undefined, auditReporter?: IAuditReporter | undefined);
18
20
  extractToolCalls(llmResponse: LLMToolCallResponse, authContext: AuthContext): ToolCallRequest[];
19
21
  executeSingle(request: ToolCallRequest, executionContext?: ExecutionContext): Promise<ToolCallResult>;
20
22
  executeAll(requests: ToolCallRequest[], executionContext?: ExecutionContext): Promise<ToolCallResult[]>;
@@ -12,9 +12,11 @@ import { assertToolPermission, GovernanceUnavailableError, PermissionDeniedError
12
12
  export class ToolOrchestrator {
13
13
  toolExecutor;
14
14
  governanceClient;
15
- constructor(toolExecutor, governanceClient) {
15
+ auditReporter;
16
+ constructor(toolExecutor, governanceClient, auditReporter) {
16
17
  this.toolExecutor = toolExecutor;
17
18
  this.governanceClient = governanceClient;
19
+ this.auditReporter = auditReporter;
18
20
  }
19
21
  extractToolCalls(llmResponse, authContext) {
20
22
  if (!llmResponse.toolCalls || llmResponse.toolCalls.length === 0) {
@@ -37,13 +39,20 @@ export class ToolOrchestrator {
37
39
  });
38
40
  }
39
41
  async executeSingle(request, executionContext) {
40
- if (this.governanceClient &&
41
- executionContext?.delegationToken &&
42
- !isBuiltinToolExecution(request.execution)) {
42
+ if (this.governanceClient && !isBuiltinToolExecution(request.execution)) {
43
+ const ctx = executionContext ?? {
44
+ userId: '',
45
+ callerType: 'user',
46
+ roles: [],
47
+ permissions: [],
48
+ delegationToken: '',
49
+ correlationId: request.correlationId ?? '',
50
+ };
43
51
  try {
44
- await assertToolPermission(this.governanceClient, executionContext, request.toolName, {
52
+ await assertToolPermission(this.governanceClient, ctx, request.toolName, {
45
53
  dataScope: request.dataScope ?? 'user-bound',
46
- resourceOwnerId: request.resourceOwnerId ?? executionContext.userId ?? undefined,
54
+ resourceOwnerId: request.resourceOwnerId ?? (ctx.userId || undefined),
55
+ auditReporter: this.auditReporter,
47
56
  });
48
57
  }
49
58
  catch (error) {
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Tool 单次调用的瞬时失败重试。
3
+ * 不整段重跑节点 / Skill 子图(会重复 LLM 流式输出)。
4
+ */
5
+ import type { BackoffStrategy, NodeRetryConfig } from '../graph/contracts/executable-graph.js';
6
+ export interface ToolFailureShape {
7
+ success: boolean;
8
+ error?: string;
9
+ errorCode?: string;
10
+ retryable?: boolean;
11
+ }
12
+ export declare function isRetryableToolFailure(result: ToolFailureShape): boolean;
13
+ export declare function resolveToolRetryConfig(retry?: NodeRetryConfig): Required<NodeRetryConfig> | undefined;
14
+ export declare function toolRetryDelayMs(attemptIndex: number, backoff: BackoffStrategy): number;
15
+ export declare function sleepToolRetry(ms: number): Promise<void>;
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Tool 单次调用的瞬时失败重试。
3
+ * 不整段重跑节点 / Skill 子图(会重复 LLM 流式输出)。
4
+ */
5
+ import { DEFAULT_NODE_RETRY_CONFIG } from '../graph/retry/node-retry.js';
6
+ import { isAbortError } from './timeout.js';
7
+ const NON_RETRYABLE_CODES = new Set([
8
+ 'interceptor_denied',
9
+ 'interceptor_ask',
10
+ 'hitl_rejected',
11
+ 'NO_PERMISSION',
12
+ 'DATA_SCOPE_DENIED',
13
+ 'TOOL_NOT_FOUND',
14
+ 'INVALID_ARGUMENTS',
15
+ 'PARAMS_INVALID',
16
+ 'TOOL_TIMEOUT',
17
+ ]);
18
+ export function isRetryableToolFailure(result) {
19
+ if (result.success)
20
+ return false;
21
+ if (result.retryable === true)
22
+ return true;
23
+ if (result.retryable === false)
24
+ return false;
25
+ const code = result.errorCode ?? '';
26
+ if (NON_RETRYABLE_CODES.has(code))
27
+ return false;
28
+ const msg = (result.error ?? '').toLowerCase();
29
+ if (/timeout after \d+s/.test(msg) || isAbortError(result.error))
30
+ return false;
31
+ if (code === 'RATE_LIMITED' || code === 'CIRCUIT_OPEN')
32
+ return true;
33
+ return (/(?:^|\D)(429|502|503|504)(?:\D|$)/.test(msg) ||
34
+ /econnreset|econnrefused|enotfound|etimedout|socket hang up|fetch failed|network error/.test(msg));
35
+ }
36
+ export function resolveToolRetryConfig(retry) {
37
+ if (!retry || typeof retry.maxRetries !== 'number' || retry.maxRetries <= 0) {
38
+ return undefined;
39
+ }
40
+ return {
41
+ maxRetries: retry.maxRetries,
42
+ backoff: retry.backoff ?? DEFAULT_NODE_RETRY_CONFIG.backoff,
43
+ };
44
+ }
45
+ export function toolRetryDelayMs(attemptIndex, backoff) {
46
+ let delay;
47
+ switch (backoff.type) {
48
+ case 'exponential':
49
+ delay = backoff.baseDelay * Math.pow(2, attemptIndex);
50
+ break;
51
+ case 'linear':
52
+ delay = backoff.baseDelay * (attemptIndex + 1);
53
+ break;
54
+ default:
55
+ delay = backoff.baseDelay;
56
+ }
57
+ delay = Math.min(delay, backoff.maxDelay);
58
+ if (backoff.jitter && backoff.jitter > 0) {
59
+ const jitterRange = delay * backoff.jitter;
60
+ delay += Math.random() * jitterRange * 2 - jitterRange;
61
+ delay = Math.max(0, delay);
62
+ }
63
+ return Math.round(delay);
64
+ }
65
+ export async function sleepToolRetry(ms) {
66
+ if (ms <= 0)
67
+ return;
68
+ await new Promise((resolve) => setTimeout(resolve, ms));
69
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gt-fe/eap-runtime",
3
- "version": "0.0.20",
3
+ "version": "0.0.22",
4
4
  "description": "Enterprise Agent Platform — Runtime核心:Graph执行引擎、Task生命周期、Session管理、Checkpoint持久化",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -20,7 +20,7 @@
20
20
  "ioredis": "^5.4.0",
21
21
  "pg": "^8.13.0",
22
22
  "yaml": "^2.6.1",
23
- "@gt-fe/eap-contracts": "0.0.11"
23
+ "@gt-fe/eap-contracts": "0.0.12"
24
24
  },
25
25
  "publishConfig": {
26
26
  "registry": "https://registry.npmjs.org/",