@gt-fe/eap-runtime 0.0.15 → 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/registry/deployment-snapshot.js +25 -15
- package/dist/registry/preload-flags.d.ts +1 -1
- package/dist/registry/preload-flags.js +1 -1
- package/dist/tool/create-tool-executor.d.ts +3 -1
- package/dist/tool/create-tool-executor.js +11 -4
- package/dist/tool/index.d.ts +1 -1
- package/dist/tool/index.js +1 -1
- package/dist/tool/mcp-tool-executor.d.ts +2 -0
- package/dist/tool/mcp-tool-executor.js +24 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -163,7 +163,7 @@ DSL / 契约细节见 `.kiro/specs/04-runtime-core/design.md` §1.4 与 `src/gra
|
|
|
163
163
|
|------|------|------|
|
|
164
164
|
| `EAP_PREINSTALL_ROOT` | — | 预装根;也可用 `GraphLoader({ preinstallRoot })` |
|
|
165
165
|
| `EAP_PRELOAD_REQUIRE_READY` | 关 | 缺 `.ready` → `runtime.preload.missing` |
|
|
166
|
-
| `EAP_PRELOAD_REQUIRE_CHECKSUM` | 关 | snapshot 须含 sha256 或 artifacts |
|
|
166
|
+
| `EAP_PRELOAD_REQUIRE_CHECKSUM` | 关 | snapshot 须含 sha256 或 artifacts。加载期比对文件摘要,不匹配则 warn、不中断 |
|
|
167
167
|
| `EAP_PRELOAD_USER_SKILL_OVERRIDE` | 关 | `users` 优先于 `shared` |
|
|
168
168
|
| `EAP_PRELOAD_VALIDATE_SKILL_IO` | 关 | 校验 Skill `inputDef.required`(`state.skillInput`) |
|
|
169
169
|
| `EAP_PRELOAD_DEFINITION_CACHE` | 有预装时开 | 定义缓存;`0`/`false` 关闭,`1`/`true` 强制开 |
|
|
@@ -256,7 +256,7 @@ FOUNDATION_SERVICE_URL=...
|
|
|
256
256
|
EAP_DEPLOYMENT_CONTEXT=dev
|
|
257
257
|
EAP_PREINSTALL_ROOT=/abs/path/to/preinstall # 或 Agent 工程内预装树
|
|
258
258
|
EAP_RUNTIME_STORAGE_PROFILE=dev
|
|
259
|
-
EAP_TOOL_EXECUTION_MODE=mcp #
|
|
259
|
+
EAP_TOOL_EXECUTION_MODE=mcp # 仅 createDevRuntime / eap chat;Hosting 的 TOOL_EXECUTION_MODE 不读
|
|
260
260
|
# OPENAI_BASE_URL / OPENAI_API_KEY / EAP_DEFAULT_MODEL
|
|
261
261
|
```
|
|
262
262
|
|
|
@@ -17,6 +17,7 @@ import { parseSkillMd } from '@gt-fe/eap-contracts';
|
|
|
17
17
|
import { findSkillEntryFile } from './skill-tree.js';
|
|
18
18
|
import { preloadMissing, preloadPackageCorrupt, } from './preload-errors.js';
|
|
19
19
|
import { isRequireChecksum, resolvePreloadBehaviorFlags, } from './preload-flags.js';
|
|
20
|
+
import { emitRuntimeLog } from '../common/logger.js';
|
|
20
21
|
async function pathExists(p) {
|
|
21
22
|
try {
|
|
22
23
|
await access(p, fsConstants.F_OK);
|
|
@@ -115,17 +116,19 @@ async function findDigestMatch(items, expectedRaw) {
|
|
|
115
116
|
}
|
|
116
117
|
return undefined;
|
|
117
118
|
}
|
|
118
|
-
async function
|
|
119
|
+
async function warnIfDigestMismatch(expectedRaw, actualHex, label, details) {
|
|
119
120
|
const expected = normalizeDigest(expectedRaw);
|
|
120
121
|
if (!expected)
|
|
121
122
|
return;
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
123
|
+
const actual = actualHex.toLowerCase();
|
|
124
|
+
if (expected === actual)
|
|
125
|
+
return;
|
|
126
|
+
emitRuntimeLog('warn', 'preload', `预装校验和不匹配: ${label}`, {
|
|
127
|
+
event: 'runtime.preload.digest_mismatch',
|
|
128
|
+
expected,
|
|
129
|
+
actual,
|
|
130
|
+
...details,
|
|
131
|
+
});
|
|
129
132
|
}
|
|
130
133
|
async function pickLatestVersionDir(parent) {
|
|
131
134
|
if (!(await pathExists(parent)))
|
|
@@ -358,10 +361,14 @@ export class FileSystemDeploymentSnapshot {
|
|
|
358
361
|
const raw = (await readTextFile(pkgFile))?.trim() ?? '';
|
|
359
362
|
const fileDigest = normalizeDigest(raw);
|
|
360
363
|
if (!fileDigest) {
|
|
361
|
-
|
|
364
|
+
emitRuntimeLog('warn', 'preload', '.package.sha256 内容非法', {
|
|
365
|
+
event: 'runtime.preload.digest_mismatch',
|
|
366
|
+
path: pkgFile,
|
|
367
|
+
});
|
|
362
368
|
}
|
|
363
|
-
if (fileDigest !== expectedPkg) {
|
|
364
|
-
|
|
369
|
+
else if (fileDigest !== expectedPkg) {
|
|
370
|
+
emitRuntimeLog('warn', 'preload', 'snapshot.sha256 与 .package.sha256 不一致', {
|
|
371
|
+
event: 'runtime.preload.digest_mismatch',
|
|
365
372
|
expected: expectedPkg,
|
|
366
373
|
actual: fileDigest,
|
|
367
374
|
path: pkgFile,
|
|
@@ -387,7 +394,7 @@ export class FileSystemDeploymentSnapshot {
|
|
|
387
394
|
throw preloadPackageCorrupt(`artifacts 指向的文件不存在: ${rel}`, { path: full });
|
|
388
395
|
}
|
|
389
396
|
const actual = await sha256OfFile(full);
|
|
390
|
-
await
|
|
397
|
+
await warnIfDigestMismatch(expected, actual, `artifact ${rel}`, { path: full });
|
|
391
398
|
}
|
|
392
399
|
}
|
|
393
400
|
async resolveAgentDir(agentCode, version) {
|
|
@@ -492,7 +499,7 @@ export class FileSystemDeploymentSnapshot {
|
|
|
492
499
|
if (ref.sha256) {
|
|
493
500
|
const matched = await findDigestMatch(existingManifests, ref.sha256);
|
|
494
501
|
if (!matched) {
|
|
495
|
-
await
|
|
502
|
+
await warnIfDigestMismatch(ref.sha256, await sha256OfFile(existingManifests[0].path), `tool ${ref.name}`, { path: existingManifests[0].path });
|
|
496
503
|
}
|
|
497
504
|
chosen = matched ?? existingManifests[0];
|
|
498
505
|
}
|
|
@@ -564,9 +571,12 @@ export class FileSystemDeploymentSnapshot {
|
|
|
564
571
|
continue;
|
|
565
572
|
const isUserOverridePath = bundlePath.includes('/users/') || bundlePath.includes('\\users\\');
|
|
566
573
|
const isAuthorOverlay = extraRoots.some((root) => root && isPathInside(root, bundlePath));
|
|
567
|
-
if (ref.sha256 &&
|
|
574
|
+
if (ref.sha256 &&
|
|
575
|
+
!isUserOverridePath &&
|
|
576
|
+
!isAuthorOverlay &&
|
|
577
|
+
manifestPath.endsWith('.json')) {
|
|
568
578
|
const actual = await sha256OfFile(manifestPath);
|
|
569
|
-
await
|
|
579
|
+
await warnIfDigestMismatch(ref.sha256, actual, `skill ${ref.skillId}`, { path: manifestPath });
|
|
570
580
|
}
|
|
571
581
|
const skillId = String(ref.skillId);
|
|
572
582
|
return {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* |------|------|------|
|
|
6
6
|
* | EAP_PRELOAD_REQUIRE_READY | 关 | 强制校验 .ready |
|
|
7
7
|
* | EAP_PRELOAD_VALIDATE_SKILL_IO | **开** | 执行子图前校验 skill inputDef.required;`0`/`false` 关闭 |
|
|
8
|
-
* | EAP_PRELOAD_REQUIRE_CHECKSUM | 关 | snapshot 必须带 sha256 或 artifacts[] |
|
|
8
|
+
* | EAP_PRELOAD_REQUIRE_CHECKSUM | 关 | snapshot 必须带 sha256 或 artifacts[](字段存在性)。加载期摘要不匹配为 warn |
|
|
9
9
|
* | EAP_PRELOAD_DEFINITION_CACHE | 有预装时开 | 进程内定义缓存;`0`/`false` 关闭 |
|
|
10
10
|
* | EAP_SKILL_HOT_RELOAD | **dev 开 / server 关** | 已装配 Skill 的目录 mtime 变化则丢缓存;未写入装配名单的目录不进清单 |
|
|
11
11
|
* | EAP_LOCAL_SKILLS_DIR | 关 | 开发态作者源 Skill 根;查找优先于 preinstall,低于 users/ |
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* |------|------|------|
|
|
6
6
|
* | EAP_PRELOAD_REQUIRE_READY | 关 | 强制校验 .ready |
|
|
7
7
|
* | EAP_PRELOAD_VALIDATE_SKILL_IO | **开** | 执行子图前校验 skill inputDef.required;`0`/`false` 关闭 |
|
|
8
|
-
* | EAP_PRELOAD_REQUIRE_CHECKSUM | 关 | snapshot 必须带 sha256 或 artifacts[] |
|
|
8
|
+
* | EAP_PRELOAD_REQUIRE_CHECKSUM | 关 | snapshot 必须带 sha256 或 artifacts[](字段存在性)。加载期摘要不匹配为 warn |
|
|
9
9
|
* | EAP_PRELOAD_DEFINITION_CACHE | 有预装时开 | 进程内定义缓存;`0`/`false` 关闭 |
|
|
10
10
|
* | EAP_SKILL_HOT_RELOAD | **dev 开 / server 关** | 已装配 Skill 的目录 mtime 变化则丢缓存;未写入装配名单的目录不进清单 |
|
|
11
11
|
* | EAP_LOCAL_SKILLS_DIR | 关 | 开发态作者源 Skill 根;查找优先于 preinstall,低于 users/ |
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* createToolExecutor — 按部署上下文组装 Router + Gateway/Local 执行器
|
|
3
3
|
*
|
|
4
|
-
* server / hosting:**默认 MCP**(McpToolExecutor → POST /api/v1/mcp);
|
|
4
|
+
* server / hosting:**默认 MCP**(McpToolExecutor → POST {绝对基址}/api/v1/mcp);
|
|
5
5
|
* `EAP_TOOL_GATEWAY_TRANSPORT=http` 时用 HttpToolExecutor(仅调试)。
|
|
6
6
|
* desktop 经 ToolExecutionRouter 分流 Local / Gateway。
|
|
7
|
+
* desktop|dev 且 foundationUrl 不是绝对 http(s):不创建 Gateway 客户端,只挂 LocalToolExecutor。
|
|
8
|
+
* 不读 Hosting 的 TOOL_EXECUTION_MODE。
|
|
7
9
|
*/
|
|
8
10
|
import type { ILocalToolInstallStore, LocalToolInstallRecord } from '@gt-fe/eap-contracts';
|
|
9
11
|
import { type DeploymentContext } from './tool-execution-router.js';
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* createToolExecutor — 按部署上下文组装 Router + Gateway/Local 执行器
|
|
3
3
|
*
|
|
4
|
-
* server / hosting:**默认 MCP**(McpToolExecutor → POST /api/v1/mcp);
|
|
4
|
+
* server / hosting:**默认 MCP**(McpToolExecutor → POST {绝对基址}/api/v1/mcp);
|
|
5
5
|
* `EAP_TOOL_GATEWAY_TRANSPORT=http` 时用 HttpToolExecutor(仅调试)。
|
|
6
6
|
* desktop 经 ToolExecutionRouter 分流 Local / Gateway。
|
|
7
|
+
* desktop|dev 且 foundationUrl 不是绝对 http(s):不创建 Gateway 客户端,只挂 LocalToolExecutor。
|
|
8
|
+
* 不读 Hosting 的 TOOL_EXECUTION_MODE。
|
|
7
9
|
*/
|
|
8
10
|
import { HttpToolExecutor } from './http-tool-executor.js';
|
|
9
|
-
import { McpToolExecutor } from './mcp-tool-executor.js';
|
|
11
|
+
import { isAbsoluteHttpUrl, McpToolExecutor } from './mcp-tool-executor.js';
|
|
10
12
|
import { LocalToolExecutor } from './local-tool-executor.js';
|
|
11
13
|
import { ToolExecutionRouter, } from './tool-execution-router.js';
|
|
12
14
|
import { withHarnessPrimitives } from './harness-primitives.js';
|
|
@@ -46,14 +48,19 @@ function createServerExecutor(foundationUrl, transport, timeout) {
|
|
|
46
48
|
*/
|
|
47
49
|
export function createToolExecutor(options) {
|
|
48
50
|
const installStore = options.installStore ?? new EmptyInstallStore();
|
|
51
|
+
const localExecutor = new LocalToolExecutor({ installStore });
|
|
52
|
+
const deploymentContext = resolveDeploymentContext(options.deploymentContext);
|
|
53
|
+
const hasGateway = isAbsoluteHttpUrl(options.foundationUrl);
|
|
54
|
+
if (!hasGateway && (deploymentContext === 'desktop' || deploymentContext === 'dev')) {
|
|
55
|
+
return withHarnessPrimitives(localExecutor);
|
|
56
|
+
}
|
|
49
57
|
const transport = resolveGatewayTransport(options.gatewayTransport);
|
|
50
58
|
const serverExecutor = createServerExecutor(options.foundationUrl, transport, options.httpTimeout);
|
|
51
|
-
const localExecutor = new LocalToolExecutor({ installStore });
|
|
52
59
|
return withHarnessPrimitives(new ToolExecutionRouter({
|
|
53
60
|
httpExecutor: serverExecutor,
|
|
54
61
|
localExecutor,
|
|
55
62
|
installStore,
|
|
56
|
-
deploymentContext
|
|
63
|
+
deploymentContext,
|
|
57
64
|
toolTypes: options.toolTypes,
|
|
58
65
|
toolRuntimes: options.toolRuntimes,
|
|
59
66
|
forceToolServer: options.forceToolServer,
|
package/dist/tool/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export { hydrateMcpTools, isMcpDiscoverStub, needsMcpHydration, parseListedTools
|
|
|
3
3
|
export { toLoadedToolMap, type LoadedToolDefinition, type LoadedToolMap, type LoadedToolManifestRef, } from './loaded-tool-definition.js';
|
|
4
4
|
export { ToolOrchestrator } from './tool-orchestrator.js';
|
|
5
5
|
export { HttpToolExecutor, type HttpToolExecutorOptions, } from './http-tool-executor.js';
|
|
6
|
-
export { McpToolExecutor, type McpToolExecutorOptions, } from './mcp-tool-executor.js';
|
|
6
|
+
export { McpToolExecutor, isAbsoluteHttpUrl, type McpToolExecutorOptions, } from './mcp-tool-executor.js';
|
|
7
7
|
export { LocalToolExecutor, isLocalPreferredExecution, resolveCodeExecutionFromRequest } from './local-tool-executor.js';
|
|
8
8
|
export { DevMcpExecutor, type DevMcpExecutorOptions, } from './dev-mcp-executor.js';
|
|
9
9
|
export { DevHttpExecutor, buildHttpToolUrl, resolveHttpExecutionFromRequest, type DevHttpExecution, } from './dev-http-executor.js';
|
package/dist/tool/index.js
CHANGED
|
@@ -2,7 +2,7 @@ export { hydrateMcpTools, isMcpDiscoverStub, needsMcpHydration, parseListedTools
|
|
|
2
2
|
export { toLoadedToolMap, } from './loaded-tool-definition.js';
|
|
3
3
|
export { ToolOrchestrator } from './tool-orchestrator.js';
|
|
4
4
|
export { HttpToolExecutor, } from './http-tool-executor.js';
|
|
5
|
-
export { McpToolExecutor, } from './mcp-tool-executor.js';
|
|
5
|
+
export { McpToolExecutor, isAbsoluteHttpUrl, } from './mcp-tool-executor.js';
|
|
6
6
|
export { LocalToolExecutor, isLocalPreferredExecution, resolveCodeExecutionFromRequest } from './local-tool-executor.js';
|
|
7
7
|
export { DevMcpExecutor, } from './dev-mcp-executor.js';
|
|
8
8
|
export { DevHttpExecutor, buildHttpToolUrl, resolveHttpExecutionFromRequest, } from './dev-http-executor.js';
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* @see docs/contracts/tool-execution.md §2.0
|
|
5
5
|
*/
|
|
6
6
|
import type { IToolExecutor, McpListedTool, ToolCallRequest, ToolCallResult } from './tool-executor.interface.js';
|
|
7
|
+
/** Tool Gateway 基址:必须是绝对 http(s)。空串 / 相对路径禁止 fetch。 */
|
|
8
|
+
export declare function isAbsoluteHttpUrl(value: unknown): boolean;
|
|
7
9
|
export interface McpToolExecutorOptions {
|
|
8
10
|
baseUrl: string;
|
|
9
11
|
timeout?: number;
|
|
@@ -4,8 +4,24 @@
|
|
|
4
4
|
* @see docs/contracts/tool-execution.md §2.0
|
|
5
5
|
*/
|
|
6
6
|
import { ErrorCodes } from '@gt-fe/eap-contracts';
|
|
7
|
+
import { emitRuntimeLog } from '../common/logger.js';
|
|
7
8
|
import { abortOrTimeoutMessage, isAbortError } from './timeout.js';
|
|
8
9
|
import { nextListCursor, parseListedTools } from './mcp-list.js';
|
|
10
|
+
/** Tool Gateway 基址:必须是绝对 http(s)。空串 / 相对路径禁止 fetch。 */
|
|
11
|
+
export function isAbsoluteHttpUrl(value) {
|
|
12
|
+
if (typeof value !== 'string')
|
|
13
|
+
return false;
|
|
14
|
+
const trimmed = value.trim();
|
|
15
|
+
if (!trimmed)
|
|
16
|
+
return false;
|
|
17
|
+
try {
|
|
18
|
+
const url = new URL(trimmed);
|
|
19
|
+
return url.protocol === 'http:' || url.protocol === 'https:';
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
9
25
|
function resolveAgentCode(request) {
|
|
10
26
|
return request.authContext.agentCode;
|
|
11
27
|
}
|
|
@@ -49,7 +65,14 @@ export class McpToolExecutor {
|
|
|
49
65
|
/** endpoint+user+agent → in-flight / completed tools/list */
|
|
50
66
|
listCache = new Map();
|
|
51
67
|
constructor(options) {
|
|
52
|
-
|
|
68
|
+
if (!isAbsoluteHttpUrl(options.baseUrl)) {
|
|
69
|
+
emitRuntimeLog('warn', 'tool', 'McpToolExecutor 基址不是绝对 http(s),拒绝请求', {
|
|
70
|
+
event: 'runtime.tool.gateway_base_invalid',
|
|
71
|
+
baseUrl: options.baseUrl,
|
|
72
|
+
});
|
|
73
|
+
throw new Error(`McpToolExecutor 需要绝对 http(s) 基址,收到 ${JSON.stringify(options.baseUrl ?? '')}`);
|
|
74
|
+
}
|
|
75
|
+
this.baseUrl = options.baseUrl.trim().replace(/\/+$/, '');
|
|
53
76
|
this.timeout = options.timeout ?? 30_000;
|
|
54
77
|
const path = options.mcpPath ?? '/api/v1/mcp';
|
|
55
78
|
this.mcpUrl = `${this.baseUrl}${path.startsWith('/') ? path : `/${path}`}`;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gt-fe/eap-runtime",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "Enterprise Agent Platform
|
|
3
|
+
"version": "0.0.17",
|
|
4
|
+
"description": "Enterprise Agent Platform \u2014 Runtime\u6838\u5fc3\uff1aGraph\u6267\u884c\u5f15\u64ce\u3001Task\u751f\u547d\u5468\u671f\u3001Session\u7ba1\u7406\u3001Checkpoint\u6301\u4e45\u5316",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|