@gt-fe/eap-runtime 0.0.10 → 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 (87) hide show
  1. package/README.md +3 -3
  2. package/dist/api/handlers/invoke.handler.js +4 -0
  3. package/dist/api/handlers/stream.handler.js +5 -1
  4. package/dist/api/routes/agent.routes.d.ts +2 -2
  5. package/dist/common/types.d.ts +5 -5
  6. package/dist/common/types.js +2 -2
  7. package/dist/contracts/permission-checker.d.ts +1 -1
  8. package/dist/contracts/trace-collector.d.ts +1 -1
  9. package/dist/governance/governance-client.d.ts +1 -1
  10. package/dist/governance/governance-client.js +40 -16
  11. package/dist/governance/index.d.ts +2 -2
  12. package/dist/governance/index.js +1 -1
  13. package/dist/governance/permission-guard.d.ts +2 -1
  14. package/dist/governance/permission-guard.js +13 -4
  15. package/dist/graph/adapters/langgraph.adapter.js +12 -7
  16. package/dist/graph/contracts/executable-graph.d.ts +8 -6
  17. package/dist/graph/contracts/executable-graph.js +1 -1
  18. package/dist/graph/hitl/hitl-handler.d.ts +3 -0
  19. package/dist/graph/hitl/hitl-handler.js +4 -1
  20. package/dist/graph/nodes/tool-node.js +27 -2
  21. package/dist/index.d.ts +2 -2
  22. package/dist/index.js +1 -1
  23. package/dist/providers/echo-llm-provider.js +2 -2
  24. package/dist/providers/local-llm-provider.d.ts +1 -1
  25. package/dist/providers/local-llm-provider.js +1 -1
  26. package/dist/providers/routing-llm-provider.js +1 -1
  27. package/dist/registry/agent-models.d.ts +1 -1
  28. package/dist/registry/agent-models.js +1 -1
  29. package/dist/registry/agent-registry-client.d.ts +1 -1
  30. package/dist/registry/deployment-snapshot.d.ts +14 -2
  31. package/dist/registry/deployment-snapshot.js +57 -31
  32. package/dist/registry/graph-loader.d.ts +1 -1
  33. package/dist/registry/graph-loader.js +4 -4
  34. package/dist/registry/index.d.ts +1 -1
  35. package/dist/registry/index.js +1 -1
  36. package/dist/registry/preload-errors.d.ts +1 -1
  37. package/dist/registry/preload-errors.js +1 -1
  38. package/dist/registry/skill-io-guard.js +1 -1
  39. package/dist/registry/skill-tree.js +1 -1
  40. package/dist/runtime/agent-runtime.js +19 -5
  41. package/dist/runtime/dev-runtime.d.ts +1 -1
  42. package/dist/runtime/dev-runtime.js +6 -10
  43. package/dist/runtime/types.d.ts +2 -2
  44. package/dist/server.js +1 -1
  45. package/dist/sse/events/skill-events.d.ts +1 -1
  46. package/dist/sse/events/skill-events.js +1 -1
  47. package/dist/tool/create-tool-executor.d.ts +1 -1
  48. package/dist/tool/dev-http-executor.d.ts +1 -1
  49. package/dist/tool/dev-http-executor.js +10 -7
  50. package/dist/tool/dev-mcp-executor.js +5 -3
  51. package/dist/tool/dev-tool-executor.d.ts +1 -1
  52. package/dist/tool/dev-tool-executor.js +2 -2
  53. package/dist/tool/harness-command.d.ts +32 -0
  54. package/dist/tool/harness-command.js +276 -0
  55. package/dist/tool/harness-primitives.d.ts +25 -3
  56. package/dist/tool/harness-primitives.js +157 -50
  57. package/dist/tool/http-tool-executor.js +15 -20
  58. package/dist/tool/index.d.ts +3 -2
  59. package/dist/tool/index.js +3 -2
  60. package/dist/tool/local-mcp-client.d.ts +1 -1
  61. package/dist/tool/local-mcp-client.js +54 -23
  62. package/dist/tool/local-tool-executor.d.ts +1 -1
  63. package/dist/tool/local-tool-executor.js +13 -9
  64. package/dist/tool/mcp-tool-executor.js +14 -6
  65. package/dist/tool/skill-script-refs.d.ts +20 -0
  66. package/dist/tool/skill-script-refs.js +62 -0
  67. package/dist/tool/system-prompt-builder.d.ts +2 -2
  68. package/dist/tool/system-prompt-builder.js +8 -5
  69. package/dist/tool/timeout.d.ts +14 -0
  70. package/dist/tool/timeout.js +36 -0
  71. package/dist/tool/tool-confirmation.js +2 -1
  72. package/dist/tool/tool-execution-router.d.ts +1 -1
  73. package/dist/tool/tool-execution-router.js +1 -1
  74. package/dist/tool/tool-executor.interface.d.ts +13 -3
  75. package/dist/tool/tool-orchestrator.d.ts +1 -1
  76. package/dist/tool/tool-orchestrator.js +6 -3
  77. package/dist/utils/format-error.d.ts +2 -2
  78. package/dist/utils/format-error.js +2 -2
  79. package/dist/utils/http-error.d.ts +2 -2
  80. package/dist/utils/http-error.js +2 -2
  81. package/package.json +2 -2
  82. package/dist/common/concurrency.d.ts +0 -79
  83. package/dist/common/concurrency.js +0 -121
  84. package/dist/common/queue-consumer.d.ts +0 -125
  85. package/dist/common/queue-consumer.js +0 -159
  86. package/dist/tool/mock-tool-executor.d.ts +0 -28
  87. package/dist/tool/mock-tool-executor.js +0 -65
package/README.md CHANGED
@@ -28,6 +28,7 @@ Enterprise Agent Platform **执行引擎**(LangGraph.js):Agent Graph 编
28
28
  | 环境变量总表 | [`docs/governance/governance-env-config.md`](../docs/governance/governance-env-config.md) |
29
29
  | 预装联调契约 | [`docs/contracts/preload-hosting-runtime-contract.md`](../docs/contracts/preload-hosting-runtime-contract.md) |
30
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) |
31
32
  | 本地 Agent 闭环 | [`docs/workflows/local-agent-dev-loop.md`](../docs/workflows/local-agent-dev-loop.md) |
32
33
 
33
34
  ---
@@ -197,8 +198,7 @@ node ../fixtures/eap-preinstall-sample/scripts/seal-snapshot.mjs
197
198
 
198
199
  | 模式 | 何时 | 说明 |
199
200
  |------|------|------|
200
- | `mock` | 本地默认 | 不调真实 Tool |
201
- | `mcp` / DevMcp | `eap chat --tool-mode mcp` | 本机直连 MCP(`EAP_TOOL_EXECUTION_MODE`,仅 createDevRuntime) |
201
+ | `mcp` / DevToolExecutor | 本地默认(`dev` + `mcp`) | 按清单直连 MCP / HTTP / 本机 code |
202
202
  | Gateway | 生产 / Hosting | `EAP_TOOL_GATEWAY_TRANSPORT=mcp`(生产);`http` 仅调试 |
203
203
 
204
204
  - 编排:`ToolOrchestrator` + `ToolExecutionRouter`(`deploymentContext`: `server` \| `desktop` \| `dev`)
@@ -254,7 +254,7 @@ FOUNDATION_SERVICE_URL=...
254
254
  EAP_DEPLOYMENT_CONTEXT=dev
255
255
  EAP_PREINSTALL_ROOT=/abs/path/to/preinstall # 或 Agent 工程内预装树
256
256
  EAP_RUNTIME_STORAGE_PROFILE=dev
257
- EAP_TOOL_EXECUTION_MODE=mock # 或 mcp
257
+ EAP_TOOL_EXECUTION_MODE=mcp # 本地默认;http-debug 走 Gateway 调试口
258
258
  # OPENAI_BASE_URL / OPENAI_API_KEY / EAP_DEFAULT_MODEL
259
259
  ```
260
260
 
@@ -178,6 +178,9 @@ export class InvokeOrchestrator {
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
  });
@@ -25,7 +25,7 @@ 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
31
  import { toLoadedSkillMap } from '../../tool/system-prompt-builder.js';
@@ -200,6 +200,9 @@ export class StreamOrchestrator {
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
  */
@@ -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
  */
@@ -84,7 +84,7 @@ export interface ExecutionNodeEvent {
84
84
  /** 节点类型 */
85
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
  /** 输入数据 */
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * 治理服务 HTTP 客户端(06-governance validateToken / checkPermission)
3
3
  */
4
- import type { ExecutionContext, GovernancePermissionCheckParams, GovernancePermissionCheckResult } from '@gt-fe/eap-contracts';
4
+ import type { ExecutionContext, GovernancePermissionCheckParams, GovernancePermissionCheckResult } from '@eap/contracts';
5
5
  export interface HttpGovernanceClientOptions {
6
6
  baseUrl: string;
7
7
  timeout?: number;
@@ -40,25 +40,29 @@ export class HttpGovernanceClient {
40
40
  if (response.status === 503 || response.status >= 500) {
41
41
  return { allowed: false, reason: 'GOVERNANCE_UNAVAILABLE' };
42
42
  }
43
+ if (response.status === 403) {
44
+ return { allowed: false, reason: await readDenyReason(response, 'NO_PERMISSION') };
45
+ }
43
46
  if (!response.ok) {
44
- if (response.status === 403) {
45
- try {
46
- const errBody = (await response.json());
47
- const errData = errBody.data ?? errBody;
48
- return { allowed: false, reason: errData.reason ?? 'NO_PERMISSION' };
49
- }
50
- catch {
51
- return { allowed: false, reason: 'NO_PERMISSION' };
52
- }
53
- }
54
- return { allowed: false, reason: 'NO_PERMISSION' };
47
+ // 401/404/400 等是 Runtime→Foundation hop 失败,不是 C2「没工具权」
48
+ return { allowed: false, reason: 'GOVERNANCE_UNAVAILABLE' };
49
+ }
50
+ let body;
51
+ try {
52
+ body = (await response.json());
53
+ }
54
+ catch {
55
+ return { allowed: false, reason: 'GOVERNANCE_UNAVAILABLE' };
55
56
  }
56
- const body = (await response.json());
57
57
  const data = body.data ?? body;
58
- return {
59
- allowed: data.allowed === true,
60
- reason: data.allowed ? undefined : (data.reason ?? 'NO_PERMISSION'),
61
- };
58
+ if (data.allowed === true) {
59
+ return { allowed: true };
60
+ }
61
+ const reason = asDenyReason(data.reason);
62
+ if (data.allowed === false && reason && reason !== 'GOVERNANCE_UNAVAILABLE') {
63
+ return { allowed: false, reason };
64
+ }
65
+ return { allowed: false, reason: 'GOVERNANCE_UNAVAILABLE' };
62
66
  }
63
67
  catch {
64
68
  clearTimeout(timeoutId);
@@ -66,6 +70,26 @@ export class HttpGovernanceClient {
66
70
  }
67
71
  }
68
72
  }
73
+ const DENY_REASONS = new Set([
74
+ 'NO_PERMISSION',
75
+ 'DATA_SCOPE_DENIED',
76
+ 'GOVERNANCE_UNAVAILABLE',
77
+ ]);
78
+ function asDenyReason(value) {
79
+ return typeof value === 'string' && DENY_REASONS.has(value)
80
+ ? value
81
+ : undefined;
82
+ }
83
+ async function readDenyReason(response, fallback) {
84
+ try {
85
+ const errBody = (await response.json());
86
+ const errData = errBody.data ?? errBody;
87
+ return asDenyReason(errData.reason) ?? fallback;
88
+ }
89
+ catch {
90
+ return fallback;
91
+ }
92
+ }
69
93
  /** 本地/测试:跳过远程校验 */
70
94
  export class AllowAllGovernanceClient {
71
95
  async checkPermission(_ctx, _params) {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * 权限校验 — 对齐 06-governance R16.8
3
3
  */
4
- export type { CallerType, ExecutionContext, GovernancePermissionCheckParams, GovernancePermissionCheckResult, PermissionAction, PermissionDenyReason, PermissionResourceType, } from '@gt-fe/eap-contracts';
4
+ export type { CallerType, ExecutionContext, GovernancePermissionCheckParams, GovernancePermissionCheckResult, PermissionAction, PermissionDenyReason, PermissionResourceType, } from '@eap/contracts';
5
5
  export type { IGovernanceClient } from './governance-client.js';
6
6
  export { HttpGovernanceClient, AllowAllGovernanceClient, resolveExecutionContext, } from './governance-client.js';
7
- export { assertToolPermission, assertSkillPermission, PermissionDeniedError, GovernanceUnavailableError, } from './permission-guard.js';
7
+ export { assertToolPermission, assertSkillPermission, permissionMessage, PermissionDeniedError, GovernanceUnavailableError, } from './permission-guard.js';
@@ -2,4 +2,4 @@
2
2
  * 权限校验 — 对齐 06-governance R16.8
3
3
  */
4
4
  export { HttpGovernanceClient, AllowAllGovernanceClient, resolveExecutionContext, } from './governance-client.js';
5
- export { assertToolPermission, assertSkillPermission, PermissionDeniedError, GovernanceUnavailableError, } from './permission-guard.js';
5
+ export { assertToolPermission, assertSkillPermission, permissionMessage, PermissionDeniedError, GovernanceUnavailableError, } from './permission-guard.js';
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * 执行期 Tool 权限守卫
3
3
  */
4
- import type { ExecutionContext, PermissionDenyReason } from '@gt-fe/eap-contracts';
4
+ import type { ExecutionContext, PermissionDenyReason } from '@eap/contracts';
5
5
  import type { IGovernanceClient } from './governance-client.js';
6
6
  export declare class GovernanceUnavailableError extends Error {
7
7
  readonly reason: PermissionDenyReason;
@@ -11,6 +11,7 @@ export declare class PermissionDeniedError extends Error {
11
11
  readonly reason: PermissionDenyReason;
12
12
  constructor(reason?: PermissionDenyReason, message?: string);
13
13
  }
14
+ export declare function permissionMessage(kind: 'tool' | 'skill', reason: PermissionDenyReason): string;
14
15
  export declare function assertToolPermission(client: IGovernanceClient | undefined, ctx: ExecutionContext, toolId: string, options?: {
15
16
  dataScope?: 'user-bound' | 'department-bound' | 'global';
16
17
  resourceOwnerId?: string;
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export class GovernanceUnavailableError extends Error {
5
5
  reason = 'GOVERNANCE_UNAVAILABLE';
6
- constructor(message = 'Governance service unavailable') {
6
+ constructor(message = '治理服务不可用') {
7
7
  super(message);
8
8
  this.name = 'GovernanceUnavailableError';
9
9
  }
@@ -11,11 +11,18 @@ export class GovernanceUnavailableError extends Error {
11
11
  export class PermissionDeniedError extends Error {
12
12
  reason;
13
13
  constructor(reason = 'NO_PERMISSION', message) {
14
- super(message ?? reason);
14
+ super(message ?? permissionMessage('tool', reason));
15
15
  this.name = 'PermissionDeniedError';
16
16
  this.reason = reason;
17
17
  }
18
18
  }
19
+ export function permissionMessage(kind, reason) {
20
+ if (reason === 'DATA_SCOPE_DENIED')
21
+ return '数据范围不足';
22
+ if (reason === 'GOVERNANCE_UNAVAILABLE')
23
+ return '治理服务不可用';
24
+ return kind === 'skill' ? '用户无该 Skill 使用权限' : '用户无该 Tool 执行权限';
25
+ }
19
26
  export async function assertToolPermission(client, ctx, toolId, options) {
20
27
  if (!client) {
21
28
  return;
@@ -34,7 +41,8 @@ export async function assertToolPermission(client, ctx, toolId, options) {
34
41
  throw new GovernanceUnavailableError();
35
42
  }
36
43
  if (!result.allowed) {
37
- throw new PermissionDeniedError(result.reason ?? 'NO_PERMISSION');
44
+ const reason = result.reason ?? 'NO_PERMISSION';
45
+ throw new PermissionDeniedError(reason, permissionMessage('tool', reason));
38
46
  }
39
47
  }
40
48
  /** Skill 激活守卫(04 R15.3) */
@@ -54,6 +62,7 @@ export async function assertSkillPermission(client, ctx, skillId) {
54
62
  throw new GovernanceUnavailableError();
55
63
  }
56
64
  if (!result.allowed) {
57
- throw new PermissionDeniedError(result.reason ?? 'NO_PERMISSION');
65
+ const reason = result.reason ?? 'NO_PERMISSION';
66
+ throw new PermissionDeniedError(reason, permissionMessage('skill', reason));
58
67
  }
59
68
  }
@@ -19,13 +19,13 @@ import { fileArtifactFromToolOutput } from '../../tool/file-artifact.js';
19
19
  import { EchoLLMProvider } from '../../providers/echo-llm-provider.js';
20
20
  import { ConditionEvaluator } from '../condition-evaluator.js';
21
21
  import { SystemPromptBuilder, buildToolCatalog, loadedToolsToApiTools } from '../../tool/system-prompt-builder.js';
22
- import { resolveJailRoots } from '../../tool/harness-primitives.js';
22
+ import { resolveJailFromState, resolveJailRoots } from '../../tool/harness-primitives.js';
23
23
  import os from 'node:os';
24
24
  import { bindSelectedSkill } from '../nodes/skill-bind-node.js';
25
25
  import { resolveGraphPrompt } from '../resolve-graph-prompt.js';
26
26
  import { SkillAuditRecorder } from '../skill-audit-recorder.js';
27
27
  import { preloadSkillNotFound } from '../../registry/preload-errors.js';
28
- import { AppError, ErrorCodes } from '@gt-fe/eap-contracts';
28
+ import { AppError, ErrorCodes } from '@eap/contracts';
29
29
  import { isHitlDecision, lastAssistantHasUnansweredToolCalls } from '../hitl/hitl-handler.js';
30
30
  import { classifySkillRead } from './skill-read.js';
31
31
  import { withGraphSpan } from '../trace-span.js';
@@ -305,6 +305,7 @@ export class LangGraphAdapter {
305
305
  skillRoute: ephemeral(undefined),
306
306
  silentOutput: ephemeral(undefined),
307
307
  promptRoots: ephemeral(undefined),
308
+ agentDir: ephemeral(undefined),
308
309
  executionContext: ephemeral(undefined),
309
310
  forceToolServer: ephemeral(undefined),
310
311
  traceCollector: ephemeral(undefined),
@@ -799,7 +800,15 @@ export class LangGraphAdapter {
799
800
  const toolCatalog = disableTools ? undefined : buildToolCatalog(loadedTools);
800
801
  const execCtx = state['executionContext'];
801
802
  const userId = (typeof execCtx?.userId === 'string' && execCtx.userId) || state['userId'];
802
- const workingDirectory = typeof process.cwd === 'function' ? process.cwd() : undefined;
803
+ const jail = resolveJailFromState({
804
+ agentDir: state['agentDir'],
805
+ userId,
806
+ executionContext: execCtx,
807
+ loadedTools,
808
+ skillDefinitions: skillDefs,
809
+ });
810
+ const workingDirectory = jail.workdir;
811
+ const jailRoots = resolveJailRoots(jail);
803
812
  const skillDirs = Object.values(skillDefs ?? {})
804
813
  .filter((skill) => Boolean(skill.bundlePath))
805
814
  .map((skill) => ({
@@ -807,10 +816,6 @@ export class LangGraphAdapter {
807
816
  bundlePath: skill.bundlePath,
808
817
  entryFile: skill.entryFile,
809
818
  }));
810
- const jailRoots = resolveJailRoots({
811
- workdir: workingDirectory,
812
- extraRoots: skillDirs.map((s) => s.bundlePath),
813
- });
814
819
  const assembled = this.systemPromptBuilder.build({
815
820
  developerPrompt: resolvedPrompt || undefined,
816
821
  skillCatalog: catalog,
@@ -2,17 +2,17 @@
2
2
  * Executable Graph 类型定义
3
3
  *
4
4
  * 定义 Graph 引擎核心的可执行图、DSL、节点、边等类型。
5
- * 与 @gt-fe/eap-contracts 的 GraphDSL 基础类型互补,在 Runtime 层提供更丰富的类型支持。
5
+ * 与 @eap/contracts 的 GraphDSL 基础类型互补,在 Runtime 层提供更丰富的类型支持。
6
6
  *
7
7
  * @see design.md §1.4 StateGraph Contract
8
8
  * @see requirements.md Requirement 1 AC1-AC2
9
9
  */
10
- import type { GraphDSL as BaseGraphDSL, GraphNode as BaseGraphNode, GraphEdge as BaseGraphEdge, GraphNodeType, GraphConfig } from '@gt-fe/eap-contracts';
10
+ import type { GraphDSL as BaseGraphDSL, GraphNode as BaseGraphNode, GraphEdge as BaseGraphEdge, GraphNodeType, GraphConfig } from '@eap/contracts';
11
11
  export type { GraphNodeType, GraphConfig };
12
12
  /**
13
13
  * RuntimeGraphConfig — Runtime 层扩展的 Graph 配置
14
14
  *
15
- * 在 @gt-fe/eap-contracts GraphConfig 基础上增加 Runtime 执行所需的 maxRetries。
15
+ * 在 @eap/contracts GraphConfig 基础上增加 Runtime 执行所需的 maxRetries。
16
16
  */
17
17
  export interface RuntimeGraphConfig extends GraphConfig {
18
18
  /** Graph 级默认重试次数(节点级 retry 可覆盖) */
@@ -21,7 +21,7 @@ export interface RuntimeGraphConfig extends GraphConfig {
21
21
  /**
22
22
  * GraphNode — Runtime 层扩展的节点定义
23
23
  *
24
- * 继承 @gt-fe/eap-contracts 基础 GraphNode,增加 Runtime 执行所需的字段:
24
+ * 继承 @eap/contracts 基础 GraphNode,增加 Runtime 执行所需的字段:
25
25
  * - 重试配置(节点级 maxRetries + 退避策略)
26
26
  * - HITL 标记(interrupt_before / interrupt_after)
27
27
  * - 描述信息(调试/Trace 用)
@@ -79,7 +79,7 @@ export interface ConditionalBranch {
79
79
  /**
80
80
  * GraphDSL — Runtime 层扩展的声明式工作流定义
81
81
  *
82
- * 扩展 @gt-fe/eap-contracts 的 BaseGraphDSL,增加条件路由、入口/终止节点等。
82
+ * 扩展 @eap/contracts 的 BaseGraphDSL,增加条件路由、入口/终止节点等。
83
83
  */
84
84
  export interface GraphDSL extends Omit<BaseGraphDSL, 'config' | 'nodes' | 'edges'> {
85
85
  /** 覆盖节点类型为 Runtime 扩展版本 */
@@ -163,7 +163,7 @@ export interface ExecutableGraph {
163
163
  /** 底层引擎内部实例引用(opaque,由 adapter 管理) */
164
164
  _engineInstance?: unknown;
165
165
  }
166
- import type { ExecutionContext as PlatformExecutionContext } from '@gt-fe/eap-contracts';
166
+ import type { ExecutionContext as PlatformExecutionContext } from '@eap/contracts';
167
167
  /**
168
168
  * GraphState — 传入 stream/invoke 的上下文数据
169
169
  */
@@ -195,6 +195,8 @@ export interface GraphState {
195
195
  silentOutput?: string;
196
196
  /** 解析 graph 内 ./prompts/*.md 的根目录(agentDir + 工程根) */
197
197
  promptRoots?: string[];
198
+ /** 预装 Agent 包目录:`{EAP_PREINSTALL_ROOT}/agents/<code>/<ver>` */
199
+ agentDir?: string;
198
200
  activatedSkill?: string | null;
199
201
  skillRoute?: string;
200
202
  /** bind / invoke 解析出的 Skill 入参;子图 IO 校验读取 */
@@ -2,7 +2,7 @@
2
2
  * Executable Graph 类型定义
3
3
  *
4
4
  * 定义 Graph 引擎核心的可执行图、DSL、节点、边等类型。
5
- * 与 @gt-fe/eap-contracts 的 GraphDSL 基础类型互补,在 Runtime 层提供更丰富的类型支持。
5
+ * 与 @eap/contracts 的 GraphDSL 基础类型互补,在 Runtime 层提供更丰富的类型支持。
6
6
  *
7
7
  * @see design.md §1.4 StateGraph Contract
8
8
  * @see requirements.md Requirement 1 AC1-AC2
@@ -16,6 +16,9 @@ import type { ISSEEmitter } from '../../sse/contracts/sse-emitter.contract.js';
16
16
  import type { GraphState } from '../contracts/executable-graph.js';
17
17
  /** HITL 默认等待时长(毫秒)= 300 秒。SSE `hitl.waited.timeout` 对外用秒。 */
18
18
  export declare const DEFAULT_HITL_TIMEOUT_MS = 300000;
19
+ /** 超时收口对外文案(Task / Trace / AppError);枚举走 `hitl_timeout`。 */
20
+ export declare const HITL_TIMEOUT_MESSAGE = "HITL \u786E\u8BA4\u8D85\u65F6";
21
+ export declare const HITL_TIMEOUT_ERROR_CODE = "hitl_timeout";
19
22
  /** HITL 超时行为 */
20
23
  export type HitlTimeoutBehavior = 'error' | 'cancel' | 'auto-confirm';
21
24
  /** HITL 中断配置 */
@@ -17,6 +17,9 @@ import { startGraphSpan, completeGraphSpan } from '../trace-span.js';
17
17
  // ─────────────────────────────────────────────
18
18
  /** HITL 默认等待时长(毫秒)= 300 秒。SSE `hitl.waited.timeout` 对外用秒。 */
19
19
  export const DEFAULT_HITL_TIMEOUT_MS = 300_000;
20
+ /** 超时收口对外文案(Task / Trace / AppError);枚举走 `hitl_timeout`。 */
21
+ export const HITL_TIMEOUT_MESSAGE = 'HITL 确认超时';
22
+ export const HITL_TIMEOUT_ERROR_CODE = 'hitl_timeout';
20
23
  /** HITL 超时错误(保留类型;timer 不再 throw,resume 逾期改走 AppError) */
21
24
  export class HitlTimeoutError extends Error {
22
25
  taskId;
@@ -444,7 +447,7 @@ export class HitlHandler {
444
447
  const hitlSpanId = waiting.hitlSpanId ?? persisted.hitlSpanId;
445
448
  await completeGraphSpan(checkpoint.state, hitlSpanId, {
446
449
  status: 'failed',
447
- error: 'hitl_timeout',
450
+ error: HITL_TIMEOUT_MESSAGE,
448
451
  }, liveCollector);
449
452
  }
450
453
  return timeoutEvent;
@@ -9,6 +9,7 @@
9
9
  * @see design.md §1.4 ToolNode: LangGraph的ToolNode封装
10
10
  * @see requirements.md Requirement 8 AC1, AC3, AC5
11
11
  */
12
+ import { resolveJailFromState } from '../../tool/harness-primitives.js';
12
13
  import { isHitlDecision, unwrapHitlPaused } from '../hitl/hitl-handler.js';
13
14
  import { ToolConfirmationInterceptor } from '../../tool/tool-confirmation.js';
14
15
  import { resolveCheckpointThreadId } from '../../session/persist-turn-messages.js';
@@ -19,6 +20,19 @@ function skillDirsFromState(state) {
19
20
  .filter((skill) => Boolean(skill.bundlePath))
20
21
  .map((skill) => ({ skillId: skill.skillId, bundlePath: skill.bundlePath }));
21
22
  }
23
+ function resolveActiveSkillDir(state) {
24
+ const defs = state['skillDefinitions'];
25
+ if (!defs)
26
+ return undefined;
27
+ const activated = state['activatedSkill'];
28
+ if (typeof activated === 'string' && defs[activated]?.bundlePath) {
29
+ return defs[activated].bundlePath;
30
+ }
31
+ const paths = Object.values(defs)
32
+ .map((skill) => skill.bundlePath)
33
+ .filter((p) => Boolean(p));
34
+ return paths.length === 1 ? paths[0] : undefined;
35
+ }
22
36
  export class ToolNode {
23
37
  orchestrator;
24
38
  injector;
@@ -53,7 +67,15 @@ export class ToolNode {
53
67
  }
54
68
  const loadedTools = state['loadedTools'];
55
69
  const skillDirs = skillDirsFromState(state);
56
- const jailExtraRoots = skillDirs.map((dir) => dir.bundlePath);
70
+ const jail = resolveJailFromState({
71
+ agentDir: state['agentDir'],
72
+ userId: state['userId'],
73
+ executionContext: state['executionContext'],
74
+ loadedTools,
75
+ skillDefinitions: state['skillDefinitions'],
76
+ });
77
+ const jailExtraRoots = jail.extraRoots ?? [];
78
+ const skillDir = resolveActiveSkillDir(state);
57
79
  // 4. 转换为 ToolCallRequest[](附带 manifest 路由字段)
58
80
  const requests = lastAssistantMessage.toolCalls.map((tc) => {
59
81
  const loaded = loadedTools?.[tc.name];
@@ -73,7 +95,9 @@ export class ToolNode {
73
95
  ...(loaded?.manifest.version ? { toolVersion: loaded.manifest.version } : {}),
74
96
  correlationId,
75
97
  taskId,
98
+ ...(jail.workdir ? { jailWorkdir: jail.workdir } : {}),
76
99
  ...(jailExtraRoots.length > 0 ? { jailExtraRoots } : {}),
100
+ ...(skillDir ? { skillDir } : {}),
77
101
  };
78
102
  });
79
103
  const executionContext = state['executionContext'];
@@ -161,7 +185,8 @@ export class ToolNode {
161
185
  toolName: req.toolName,
162
186
  content: `用户拒绝执行工具 ${req.toolName}`,
163
187
  success: false,
164
- error: 'hitl_rejected',
188
+ error: `用户拒绝执行工具 ${req.toolName}`,
189
+ errorCode: 'hitl_rejected',
165
190
  };
166
191
  }
167
192
  else {
package/dist/index.d.ts CHANGED
@@ -16,8 +16,8 @@ export * from './common/index.js';
16
16
  export * from './registry/index.js';
17
17
  export * from './providers/index.js';
18
18
  export type { ITraceCollector, TraceEvent, TraceSession, ExecutionFlowEvent, ExecutionNodeEvent, TraceLinkEvent, TraceLinkNodeEvent, } from './contracts/trace-collector.js';
19
- export type { ExecutionContext, CallerType, GovernancePermissionCheckParams, GovernancePermissionCheckResult, PermissionDenyReason, } from '@gt-fe/eap-contracts';
20
- export { HttpGovernanceClient, AllowAllGovernanceClient, resolveExecutionContext, assertToolPermission, assertSkillPermission, PermissionDeniedError, GovernanceUnavailableError, } from './governance/index.js';
19
+ export type { ExecutionContext, CallerType, GovernancePermissionCheckParams, GovernancePermissionCheckResult, PermissionDenyReason, } from '@eap/contracts';
20
+ export { HttpGovernanceClient, AllowAllGovernanceClient, resolveExecutionContext, assertToolPermission, assertSkillPermission, permissionMessage, PermissionDeniedError, GovernanceUnavailableError, } from './governance/index.js';
21
21
  export type { IGovernanceClient } from './governance/index.js';
22
22
  export { FileLlmTurnLog, InMemoryLlmTurnLog, createFileLlmTurnLogFromEnv, maskApiKey, resolveLlmTurnDir, } from './debug/llm-turn-log.js';
23
23
  export { PostgresLlmTurnLog } from './debug/pg-llm-turn-log.js';
package/dist/index.js CHANGED
@@ -29,6 +29,6 @@ export * from './common/index.js';
29
29
  export * from './registry/index.js';
30
30
  // LLM Providers
31
31
  export * from './providers/index.js';
32
- export { HttpGovernanceClient, AllowAllGovernanceClient, resolveExecutionContext, assertToolPermission, assertSkillPermission, PermissionDeniedError, GovernanceUnavailableError, } from './governance/index.js';
32
+ export { HttpGovernanceClient, AllowAllGovernanceClient, resolveExecutionContext, assertToolPermission, assertSkillPermission, permissionMessage, PermissionDeniedError, GovernanceUnavailableError, } from './governance/index.js';
33
33
  export { FileLlmTurnLog, InMemoryLlmTurnLog, createFileLlmTurnLogFromEnv, maskApiKey, resolveLlmTurnDir, } from './debug/llm-turn-log.js';
34
34
  export { PostgresLlmTurnLog } from './debug/pg-llm-turn-log.js';
@@ -7,8 +7,8 @@
7
7
  * - `call:echo-tool {"text":"hi"}` → arguments 使用解析后的 JSON
8
8
  * - `call:echo-tool hi` → arguments 兜底为 `{ text: 'hi' }`
9
9
  *
10
- * 仅用于本地闭环 (`EAP_TOOL_EXECUTION_MODE=mock`) 下驱动 ToolNode,
11
- * 让开发者无需接入真实 LLM 即可完成 tool 调用链路验证。
10
+ * 仅用于本地闭环(无真实 LLM)下驱动 ToolNode,
11
+ * 让开发者无需接入模型即可完成 tool 调用链路验证。
12
12
  */
13
13
  function parseSyntheticToolCall(content) {
14
14
  if (!content)
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import type { ILLMProvider } from '../graph/nodes/llm-node.js';
6
6
  import type { ILlmTurnLog } from '../debug/llm-turn-log.js';
7
- import { type ModelCallDefaults } from '@gt-fe/eap-contracts';
7
+ import { type ModelCallDefaults } from '@eap/contracts';
8
8
  export interface LocalLlmConnection {
9
9
  baseUrl: string;
10
10
  apiKey: string;
@@ -2,7 +2,7 @@
2
2
  * 本地多模型 LLM:按节点 model 选网关。仅 dev。
3
3
  * 连接表里只带 apiKeyEnv,密钥从 process.env 读取,不进 JSON。
4
4
  */
5
- import { mergeModelCallParams } from '@gt-fe/eap-contracts';
5
+ import { mergeModelCallParams } from '@eap/contracts';
6
6
  import { HttpLLMProvider } from './http-llm-provider.js';
7
7
  export const LLM_CONNECTIONS_ENV = 'EAP_LLM_CONNECTIONS';
8
8
  export function parseLocalLlmConnectionRefs(env = process.env) {
@@ -11,7 +11,7 @@
11
11
  * - 支持任意 OpenAI 兼容 API(OpenAI / DeepSeek / 本地 Ollama 等)
12
12
  * - 连接配置由 Foundation 统一管理,Runtime 无感知
13
13
  */
14
- import { mergeModelCallParams } from '@gt-fe/eap-contracts';
14
+ import { mergeModelCallParams } from '@eap/contracts';
15
15
  import { EchoLLMProvider } from './echo-llm-provider.js';
16
16
  import { HttpLLMProvider } from './http-llm-provider.js';
17
17
  export class RoutingLLMProvider {
@@ -1 +1 @@
1
- export { resolveDeclaredModels, resolveAgentDefaultModel, resolveAgentModelAllowlist, } from '@gt-fe/eap-contracts';
1
+ export { resolveDeclaredModels, resolveAgentDefaultModel, resolveAgentModelAllowlist, } from '@eap/contracts';
@@ -1 +1 @@
1
- export { resolveDeclaredModels, resolveAgentDefaultModel, resolveAgentModelAllowlist, } from '@gt-fe/eap-contracts';
1
+ export { resolveDeclaredModels, resolveAgentDefaultModel, resolveAgentModelAllowlist, } from '@eap/contracts';
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Agent Registry 客户端 — 从 foundation-service 拉取 Agent 定义
3
3
  */
4
- /** Agent 清单(与 @gt-fe/eap-contracts AgentManifest 对齐) */
4
+ /** Agent 清单(与 @eap/contracts AgentManifest 对齐) */
5
5
  export interface AgentManifest {
6
6
  id: string;
7
7
  name: string;