@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.
- package/README.md +15 -20
- package/dist/api/handlers/invoke.handler.js +7 -3
- package/dist/api/handlers/messages.handler.js +0 -1
- package/dist/api/handlers/stream.handler.js +8 -4
- package/dist/api/routes/agent.routes.d.ts +2 -2
- package/dist/api/routes/agent.routes.js +2 -2
- package/dist/checkpoint/checkpoint-ref-notify.d.ts +10 -0
- package/dist/checkpoint/checkpoint-ref-notify.js +59 -0
- package/dist/checkpoint/index.d.ts +1 -0
- package/dist/checkpoint/index.js +1 -0
- package/dist/checkpoint/pg-checkpoint-saver.js +25 -2
- package/dist/common/agent-code.d.ts +2 -4
- package/dist/common/agent-code.js +4 -5
- package/dist/common/types.d.ts +5 -5
- package/dist/common/types.js +2 -2
- package/dist/contracts/permission-checker.d.ts +1 -1
- package/dist/contracts/trace-collector.d.ts +16 -2
- package/dist/debug/llm-turn-log.d.ts +100 -0
- package/dist/debug/llm-turn-log.js +130 -0
- package/dist/debug/pg-llm-turn-log.d.ts +22 -0
- package/dist/debug/pg-llm-turn-log.js +57 -0
- package/dist/governance/governance-client.d.ts +1 -1
- package/dist/governance/governance-client.js +40 -16
- package/dist/governance/index.d.ts +2 -2
- package/dist/governance/index.js +1 -1
- package/dist/governance/permission-guard.d.ts +2 -1
- package/dist/governance/permission-guard.js +13 -4
- package/dist/graph/adapters/langgraph-checkpointer.js +3 -1
- package/dist/graph/adapters/langgraph.adapter.d.ts +1 -0
- package/dist/graph/adapters/langgraph.adapter.js +153 -92
- package/dist/graph/adapters/skill-read.d.ts +12 -0
- package/dist/graph/adapters/skill-read.js +63 -0
- package/dist/graph/adapters/subgraph-compiler.js +5 -0
- package/dist/graph/contracts/executable-graph.d.ts +11 -9
- package/dist/graph/contracts/executable-graph.js +1 -1
- package/dist/graph/hitl/hitl-handler.d.ts +10 -0
- package/dist/graph/hitl/hitl-handler.js +50 -6
- package/dist/graph/nodes/llm-node.d.ts +14 -0
- package/dist/graph/nodes/skill-bind-node.js +1 -2
- package/dist/graph/nodes/tool-node.d.ts +2 -0
- package/dist/graph/nodes/tool-node.js +50 -10
- package/dist/graph/trace-span.d.ts +22 -0
- package/dist/graph/trace-span.js +69 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.js +3 -1
- package/dist/memory/compression/compression.repository.d.ts +1 -15
- package/dist/providers/echo-llm-provider.d.ts +1 -1
- package/dist/providers/echo-llm-provider.js +4 -3
- package/dist/providers/http-llm-provider.d.ts +4 -0
- package/dist/providers/http-llm-provider.js +129 -4
- package/dist/providers/local-llm-provider.d.ts +5 -1
- package/dist/providers/local-llm-provider.js +14 -6
- package/dist/providers/routing-llm-provider.d.ts +4 -0
- package/dist/providers/routing-llm-provider.js +12 -2
- package/dist/registry/agent-models.d.ts +1 -1
- package/dist/registry/agent-models.js +1 -1
- package/dist/registry/agent-registry-client.d.ts +3 -3
- package/dist/registry/deployment-snapshot.d.ts +17 -5
- package/dist/registry/deployment-snapshot.js +97 -49
- package/dist/registry/graph-loader.d.ts +2 -2
- package/dist/registry/graph-loader.js +43 -80
- package/dist/registry/index.d.ts +2 -2
- package/dist/registry/index.js +2 -2
- package/dist/registry/preload-errors.d.ts +1 -1
- package/dist/registry/preload-errors.js +1 -1
- package/dist/registry/skill-io-guard.js +1 -1
- package/dist/registry/skill-tree.d.ts +3 -0
- package/dist/registry/skill-tree.js +41 -3
- package/dist/runtime/agent-runtime.d.ts +42 -3
- package/dist/runtime/agent-runtime.js +129 -39
- package/dist/runtime/dev-runtime.d.ts +7 -4
- package/dist/runtime/dev-runtime.js +24 -21
- package/dist/runtime/index.d.ts +3 -3
- package/dist/runtime/index.js +1 -1
- package/dist/runtime/storage-profile.d.ts +19 -10
- package/dist/runtime/storage-profile.js +42 -29
- package/dist/runtime/types.d.ts +17 -19
- package/dist/server.js +2 -2
- package/dist/session/session.service.d.ts +5 -0
- package/dist/session/session.service.js +12 -0
- package/dist/sse/events/index.d.ts +5 -3
- package/dist/sse/events/index.js +2 -0
- package/dist/sse/events/skill-events.d.ts +12 -1
- package/dist/sse/events/skill-events.js +1 -1
- package/dist/sse/trace-collector.d.ts +10 -0
- package/dist/sse/trace-collector.js +1 -0
- package/dist/token/token-budget.service.d.ts +2 -2
- package/dist/token/token-budget.service.js +1 -1
- package/dist/tool/create-tool-executor.d.ts +1 -1
- package/dist/tool/create-tool-executor.js +3 -2
- package/dist/tool/dev-http-executor.d.ts +1 -1
- package/dist/tool/dev-http-executor.js +10 -7
- package/dist/tool/dev-mcp-executor.js +5 -3
- package/dist/tool/dev-tool-executor.d.ts +1 -1
- package/dist/tool/dev-tool-executor.js +2 -2
- package/dist/tool/harness-command.d.ts +32 -0
- package/dist/tool/harness-command.js +276 -0
- package/dist/tool/harness-primitives.d.ts +54 -0
- package/dist/tool/harness-primitives.js +492 -0
- package/dist/tool/http-tool-executor.js +16 -21
- package/dist/tool/index.d.ts +4 -2
- package/dist/tool/index.js +4 -2
- package/dist/tool/local-mcp-client.d.ts +1 -1
- package/dist/tool/local-mcp-client.js +54 -23
- package/dist/tool/local-tool-executor.d.ts +4 -4
- package/dist/tool/local-tool-executor.js +18 -16
- package/dist/tool/mcp-tool-executor.js +23 -7
- package/dist/tool/skill-script-refs.d.ts +20 -0
- package/dist/tool/skill-script-refs.js +62 -0
- package/dist/tool/system-prompt-builder.d.ts +61 -25
- package/dist/tool/system-prompt-builder.js +198 -92
- package/dist/tool/timeout.d.ts +14 -0
- package/dist/tool/timeout.js +36 -0
- package/dist/tool/tool-confirmation.js +2 -1
- package/dist/tool/tool-execution-router.d.ts +1 -1
- package/dist/tool/tool-execution-router.js +2 -2
- package/dist/tool/tool-executor.interface.d.ts +23 -7
- package/dist/tool/tool-orchestrator.d.ts +1 -1
- package/dist/tool/tool-orchestrator.js +6 -3
- package/dist/utils/format-error.d.ts +2 -2
- package/dist/utils/format-error.js +2 -2
- package/dist/utils/http-error.d.ts +2 -2
- package/dist/utils/http-error.js +2 -2
- package/package.json +3 -3
- package/dist/common/concurrency.d.ts +0 -79
- package/dist/common/concurrency.js +0 -121
- package/dist/common/queue-consumer.d.ts +0 -125
- package/dist/common/queue-consumer.js +0 -159
- package/dist/tool/mock-tool-executor.d.ts +0 -28
- package/dist/tool/mock-tool-executor.js +0 -65
|
@@ -6,16 +6,19 @@
|
|
|
6
6
|
*/
|
|
7
7
|
// @ts-expect-error pg 无内置类型;Hosting 侧同样按 any 使用
|
|
8
8
|
import pg from 'pg';
|
|
9
|
+
import path from 'node:path';
|
|
9
10
|
import { Redis } from 'ioredis';
|
|
10
11
|
import { FileCheckpointSaver } from '../checkpoint/file-checkpoint-saver.js';
|
|
11
12
|
import { PostgresCheckpointSaver } from '../checkpoint/pg-checkpoint-saver.js';
|
|
12
13
|
import { RedisCheckpointSaver } from '../checkpoint/redis-checkpoint-saver.js';
|
|
13
14
|
import { CompositeCheckpointSaver } from '../checkpoint/composite-checkpoint-saver.js';
|
|
14
|
-
import { InMemoryCheckpointSaver } from '../checkpoint/in-memory-checkpoint-saver.js';
|
|
15
15
|
import { FileSessionRepository } from '../session/file-session.repository.js';
|
|
16
|
-
import { InMemoryFullMessageRepository } from '../session/message.service.js';
|
|
17
16
|
import { FileMessageRepository } from '../session/file-message.repository.js';
|
|
18
17
|
import { PostgresMessageRepository } from '../session/pg-message.repository.js';
|
|
18
|
+
import { FileLlmTurnLog, resolveLlmTurnDir } from '../debug/llm-turn-log.js';
|
|
19
|
+
import { PostgresLlmTurnLog } from '../debug/pg-llm-turn-log.js';
|
|
20
|
+
import { InMemoryTokenBudgetRepository } from '../token/token-budget.service.js';
|
|
21
|
+
import { PostgresTokenBudgetRepository } from '../token/pg-token-budget.repository.js';
|
|
19
22
|
const { Pool } = pg;
|
|
20
23
|
const VALID_PROFILES = new Set([
|
|
21
24
|
'test',
|
|
@@ -23,11 +26,20 @@ const VALID_PROFILES = new Set([
|
|
|
23
26
|
'integration',
|
|
24
27
|
'production',
|
|
25
28
|
]);
|
|
29
|
+
function hasDbEnv(env) {
|
|
30
|
+
return Boolean(env.DATABASE_URL?.trim() || (env.DB_HOST && env.DB_NAME && env.DB_USER));
|
|
31
|
+
}
|
|
32
|
+
function hasRedisEnv(env) {
|
|
33
|
+
return Boolean(env.REDIS_URL?.trim() || env.REDIS_HOST);
|
|
34
|
+
}
|
|
26
35
|
export function resolveRuntimeStorageProfile(explicit, defaultProfile, env = process.env) {
|
|
27
36
|
const raw = explicit ?? env.EAP_RUNTIME_STORAGE_PROFILE;
|
|
28
37
|
if (raw && VALID_PROFILES.has(raw)) {
|
|
29
38
|
return raw;
|
|
30
39
|
}
|
|
40
|
+
if (hasDbEnv(env) || hasRedisEnv(env)) {
|
|
41
|
+
return 'integration';
|
|
42
|
+
}
|
|
31
43
|
return defaultProfile;
|
|
32
44
|
}
|
|
33
45
|
function requireDbEnv(env) {
|
|
@@ -39,12 +51,12 @@ function requireDbEnv(env) {
|
|
|
39
51
|
if (!env.DB_USER && !env.DATABASE_URL)
|
|
40
52
|
missing.push('DB_USER 或 DATABASE_URL');
|
|
41
53
|
if (missing.length > 0) {
|
|
42
|
-
throw new Error(`[EAP_RUNTIME_STORAGE_PROFILE]
|
|
54
|
+
throw new Error(`[EAP_RUNTIME_STORAGE_PROFILE] Redis+PostgreSQL 路径缺少数据库配置: ${missing.join(', ')}`);
|
|
43
55
|
}
|
|
44
56
|
}
|
|
45
57
|
function requireRedisEnv(env) {
|
|
46
58
|
if (!env.REDIS_HOST && !env.REDIS_URL) {
|
|
47
|
-
throw new Error('[EAP_RUNTIME_STORAGE_PROFILE]
|
|
59
|
+
throw new Error('[EAP_RUNTIME_STORAGE_PROFILE] Redis+PostgreSQL 路径缺少 REDIS_HOST 或 REDIS_URL');
|
|
48
60
|
}
|
|
49
61
|
}
|
|
50
62
|
function createPgPoolFromEnv(env) {
|
|
@@ -73,44 +85,41 @@ function createRedisFromEnv(env) {
|
|
|
73
85
|
maxRetriesPerRequest: 1,
|
|
74
86
|
});
|
|
75
87
|
}
|
|
88
|
+
/** 本地 File 存储默认落工程 `.eap/`,可用 EAP_DATA_DIR / EAP_*_DIR 覆盖。 */
|
|
89
|
+
export function resolveDevStorageDirs(env = process.env, cwd = process.cwd()) {
|
|
90
|
+
const root = env.EAP_DATA_DIR?.trim() || path.join(cwd, '.eap');
|
|
91
|
+
const checkpointDir = env.EAP_CHECKPOINT_DIR?.trim() || path.join(root, 'checkpoints');
|
|
92
|
+
const sessionDir = env.EAP_SESSION_DIR?.trim() || path.join(root, 'sessions');
|
|
93
|
+
const messageDir = env.EAP_MESSAGE_DIR?.trim() || path.join(sessionDir, 'messages');
|
|
94
|
+
return { checkpointDir, sessionDir, messageDir };
|
|
95
|
+
}
|
|
76
96
|
/**
|
|
77
|
-
* 按 profile 装配 Checkpoint /
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* - dev: File Checkpoint + File Session + File Message
|
|
81
|
-
* - integration/production: Message=PG;Checkpoint=Redis 热 + PG 备;
|
|
82
|
-
* Session 仓储不落 PG(sessionId 权威在 Hosting.sessions,Runtime 内存采纳)
|
|
97
|
+
* 按 profile 装配 Checkpoint / Message / Token / LLM 回合存储。
|
|
98
|
+
* `dev`:文件。其余 profile:Redis + PostgreSQL(缺配置则抛错)。
|
|
99
|
+
* 未设 profile 时:已配置 DB 或 Redis 则按 Redis+PostgreSQL;否则使用 defaultProfile。
|
|
83
100
|
*/
|
|
84
101
|
export function assembleRuntimeStorage(options, env = process.env) {
|
|
85
102
|
const profile = resolveRuntimeStorageProfile(options.profile, options.defaultProfile, env);
|
|
86
|
-
const
|
|
87
|
-
const
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
checkpointSaver: new InMemoryCheckpointSaver(),
|
|
93
|
-
sessionRepository: undefined,
|
|
94
|
-
messageRepository: new InMemoryFullMessageRepository(),
|
|
95
|
-
diagnostics: {
|
|
96
|
-
profile,
|
|
97
|
-
checkpointKind: 'memory',
|
|
98
|
-
sessionKind: 'memory',
|
|
99
|
-
messageKind: 'memory',
|
|
100
|
-
},
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
if (profile === 'dev') {
|
|
103
|
+
const defaults = resolveDevStorageDirs(env);
|
|
104
|
+
const checkpointDir = options.checkpointDir ?? defaults.checkpointDir;
|
|
105
|
+
const sessionDir = options.sessionDir ?? defaults.sessionDir;
|
|
106
|
+
const messageDir = options.messageDir ?? defaults.messageDir;
|
|
107
|
+
const useFiles = profile === 'dev';
|
|
108
|
+
if (useFiles) {
|
|
104
109
|
return {
|
|
105
110
|
profile,
|
|
106
111
|
checkpointSaver: new FileCheckpointSaver(checkpointDir),
|
|
107
112
|
sessionRepository: new FileSessionRepository({ baseDir: sessionDir }),
|
|
108
113
|
messageRepository: new FileMessageRepository({ baseDir: messageDir }),
|
|
114
|
+
turnLog: new FileLlmTurnLog(resolveLlmTurnDir(env)),
|
|
115
|
+
tokenBudgetRepository: new InMemoryTokenBudgetRepository(),
|
|
109
116
|
diagnostics: {
|
|
110
117
|
profile,
|
|
111
118
|
checkpointKind: 'file',
|
|
112
119
|
sessionKind: 'file',
|
|
113
120
|
messageKind: 'file',
|
|
121
|
+
llmTurnKind: 'file',
|
|
122
|
+
tokenBudgetKind: 'process',
|
|
114
123
|
},
|
|
115
124
|
};
|
|
116
125
|
}
|
|
@@ -128,11 +137,15 @@ export function assembleRuntimeStorage(options, env = process.env) {
|
|
|
128
137
|
checkpointSaver,
|
|
129
138
|
sessionRepository: undefined,
|
|
130
139
|
messageRepository: new PostgresMessageRepository(pool),
|
|
140
|
+
turnLog: new PostgresLlmTurnLog(pool),
|
|
141
|
+
tokenBudgetRepository: new PostgresTokenBudgetRepository(pool),
|
|
131
142
|
diagnostics: {
|
|
132
143
|
profile,
|
|
133
144
|
checkpointKind: 'redis+pg',
|
|
134
|
-
sessionKind: '
|
|
145
|
+
sessionKind: 'hosting',
|
|
135
146
|
messageKind: 'postgres',
|
|
147
|
+
llmTurnKind: 'postgres',
|
|
148
|
+
tokenBudgetKind: 'postgres',
|
|
136
149
|
},
|
|
137
150
|
};
|
|
138
151
|
}
|
package/dist/runtime/types.d.ts
CHANGED
|
@@ -6,18 +6,14 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @see 04-runtime-core/design.md §1.5
|
|
8
8
|
*/
|
|
9
|
-
import type { ExecutionContext, InvokeConfig, ResumeHitlResult } from '@
|
|
9
|
+
import type { ExecutionContext, InvokeConfig, ResumeHitlResult } from '@eap/contracts';
|
|
10
10
|
import type { InvokeResponseData } from '../api/routes/agent.routes.js';
|
|
11
11
|
import type { GraphMessage } from '../graph/contracts/executable-graph.js';
|
|
12
12
|
import type { SSEEvent } from '../sse/contracts/sse-emitter.contract.js';
|
|
13
13
|
/** 同步/流式执行参数 */
|
|
14
14
|
export interface ExecuteParams {
|
|
15
|
-
/**
|
|
16
|
-
|
|
17
|
-
*/
|
|
18
|
-
agentId?: string;
|
|
19
|
-
/** 对外主键(优先) */
|
|
20
|
-
agentCode?: string;
|
|
15
|
+
/** 对外主键 */
|
|
16
|
+
agentCode: string;
|
|
21
17
|
input: string;
|
|
22
18
|
/** 平台执行上下文(Hosting / eap dev 注入,对齐 04 R15) */
|
|
23
19
|
executionContext?: ExecutionContext;
|
|
@@ -35,7 +31,7 @@ export interface ExecuteParams {
|
|
|
35
31
|
}
|
|
36
32
|
/** 同步执行结果 */
|
|
37
33
|
export type ExecuteResult = InvokeResponseData;
|
|
38
|
-
/** HITL 恢复结果(与 @
|
|
34
|
+
/** HITL 恢复结果(与 @eap/contracts ResumeHitlResult 对齐) */
|
|
39
35
|
export type { ResumeHitlResult };
|
|
40
36
|
/** HITL 用户响应 */
|
|
41
37
|
export interface HitlResponse {
|
|
@@ -48,6 +44,16 @@ export interface HitlResponse {
|
|
|
48
44
|
*/
|
|
49
45
|
threadId?: string;
|
|
50
46
|
}
|
|
47
|
+
/** Fork 入参:上层先发 taskId / traceId,Runtime 不再 createFlow */
|
|
48
|
+
export interface ForkParams {
|
|
49
|
+
checkpointId: string;
|
|
50
|
+
/** 上层已发号的 Task ID(Hosting createTask / 本地 UUID) */
|
|
51
|
+
taskId: string;
|
|
52
|
+
/** 上层已创建的 Trace id(Hosting createTrace / 本地 UUID) */
|
|
53
|
+
traceId: string;
|
|
54
|
+
executionContext?: ExecutionContext;
|
|
55
|
+
overrides?: ForkOverrides;
|
|
56
|
+
}
|
|
51
57
|
/** Fork 参数覆盖 */
|
|
52
58
|
export interface ForkOverrides {
|
|
53
59
|
model?: string;
|
|
@@ -56,11 +62,7 @@ export interface ForkOverrides {
|
|
|
56
62
|
state?: Record<string, unknown>;
|
|
57
63
|
/** 源 Trace ID(未提供时从 checkpoint 元数据读取) */
|
|
58
64
|
originalTraceId?: string;
|
|
59
|
-
/**
|
|
60
|
-
* @deprecated 使用 agentCode
|
|
61
|
-
*/
|
|
62
|
-
agentId?: string;
|
|
63
|
-
/** 执行所用 Agent(未提供时从 checkpoint state 读取) */
|
|
65
|
+
/** 执行所用 Agent(未提供时从 checkpoint state.agentCode 读取) */
|
|
64
66
|
agentCode?: string;
|
|
65
67
|
/** 预装版本(未提供时从 checkpoint state.agentVersion 读取) */
|
|
66
68
|
agentVersion?: string;
|
|
@@ -95,12 +97,8 @@ export interface ForkResult {
|
|
|
95
97
|
* - 该 session 已有历史时,视作已种入,跳过写入(exactly-once 幂等)。
|
|
96
98
|
*/
|
|
97
99
|
export interface SeedSessionMessagesParams {
|
|
98
|
-
/**
|
|
99
|
-
|
|
100
|
-
*/
|
|
101
|
-
agentId?: string;
|
|
102
|
-
/** 对外主键(优先) */
|
|
103
|
-
agentCode?: string;
|
|
100
|
+
/** 对外主键 */
|
|
101
|
+
agentCode: string;
|
|
104
102
|
/** 预装版本(写入 session.metadata.agentVersion,续聊回退) */
|
|
105
103
|
agentVersion?: string;
|
|
106
104
|
/** 会话 ID;未提供时新建 session */
|
package/dist/server.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* TODO: Phase 2 将本文件迁移至 dev-tools/cli(作为 `eap dev` 命令实现),
|
|
8
8
|
* runtime 包不再包含 HTTP 服务代码,仅作为纯库导出。
|
|
9
9
|
*/
|
|
10
|
-
import { ErrorCodes } from '@
|
|
10
|
+
import { ErrorCodes } from '@eap/contracts';
|
|
11
11
|
import { createServer } from 'node:http';
|
|
12
12
|
import { URL } from 'node:url';
|
|
13
13
|
import { resolveExecutionContext } from './governance/index.js';
|
|
@@ -49,7 +49,7 @@ const server = createServer(async (req, res) => {
|
|
|
49
49
|
if (req.method === 'GET' && url.pathname === '/metrics') {
|
|
50
50
|
sendJson(res, 200, {
|
|
51
51
|
mode: 'standalone',
|
|
52
|
-
checkpointDir: process.env.EAP_CHECKPOINT_DIR ?? '/
|
|
52
|
+
checkpointDir: process.env.EAP_CHECKPOINT_DIR ?? '.eap/checkpoints',
|
|
53
53
|
foundationUrl: process.env.FOUNDATION_SERVICE_URL ?? 'http://localhost:3100',
|
|
54
54
|
});
|
|
55
55
|
return;
|
|
@@ -102,6 +102,8 @@ export interface ISessionRepository {
|
|
|
102
102
|
findById(id: string): Promise<SessionRecord | null>;
|
|
103
103
|
findByUserId(userId: string, limit?: number, offset?: number): Promise<SessionRecord[]>;
|
|
104
104
|
update(session: SessionRecord): Promise<void>;
|
|
105
|
+
/** 本地排查:列出全部未删除会话(File / 内存实现;PG 可不提供) */
|
|
106
|
+
listAll?(): Promise<SessionRecord[]>;
|
|
105
107
|
}
|
|
106
108
|
/**
|
|
107
109
|
* IMessageRepository — Message 查询接口(最小定义)
|
|
@@ -143,6 +145,7 @@ export declare class InMemorySessionRepository implements ISessionRepository {
|
|
|
143
145
|
findById(id: string): Promise<SessionRecord | null>;
|
|
144
146
|
findByUserId(userId: string, limit?: number, offset?: number): Promise<SessionRecord[]>;
|
|
145
147
|
update(session: SessionRecord): Promise<void>;
|
|
148
|
+
listAll(): Promise<SessionRecord[]>;
|
|
146
149
|
}
|
|
147
150
|
/**
|
|
148
151
|
* InMemoryMessageRepository — 内存 Message 存储(stub)
|
|
@@ -181,6 +184,8 @@ export declare class SessionService {
|
|
|
181
184
|
limit?: number;
|
|
182
185
|
offset?: number;
|
|
183
186
|
}): Promise<SessionRecord[]>;
|
|
187
|
+
/** 本地排查:列出全部会话(仓储未实现 listAll 时返回空) */
|
|
188
|
+
listAllSessions(): Promise<SessionRecord[]>;
|
|
184
189
|
/**
|
|
185
190
|
* 归档 Session(标记为 archived)
|
|
186
191
|
*/
|
|
@@ -35,6 +35,11 @@ export class InMemorySessionRepository {
|
|
|
35
35
|
async update(session) {
|
|
36
36
|
this.store.set(session.id, { ...session });
|
|
37
37
|
}
|
|
38
|
+
async listAll() {
|
|
39
|
+
return Array.from(this.store.values())
|
|
40
|
+
.filter((s) => !s.isDeleted)
|
|
41
|
+
.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
42
|
+
}
|
|
38
43
|
}
|
|
39
44
|
/**
|
|
40
45
|
* InMemoryMessageRepository — 内存 Message 存储(stub)
|
|
@@ -138,6 +143,13 @@ export class SessionService {
|
|
|
138
143
|
async listSessions(userId, options) {
|
|
139
144
|
return this.sessionRepository.findByUserId(userId, options?.limit, options?.offset);
|
|
140
145
|
}
|
|
146
|
+
/** 本地排查:列出全部会话(仓储未实现 listAll 时返回空) */
|
|
147
|
+
async listAllSessions() {
|
|
148
|
+
if (typeof this.sessionRepository.listAll !== 'function') {
|
|
149
|
+
return [];
|
|
150
|
+
}
|
|
151
|
+
return this.sessionRepository.listAll();
|
|
152
|
+
}
|
|
141
153
|
/**
|
|
142
154
|
* 归档 Session(标记为 archived)
|
|
143
155
|
*/
|
|
@@ -39,13 +39,13 @@ export declare const CORE_SSE_EVENTS: readonly ["session.created", "task.started
|
|
|
39
39
|
/**
|
|
40
40
|
* 可选事件类型(Agent 按需支持)
|
|
41
41
|
*/
|
|
42
|
-
export declare const OPTIONAL_SSE_EVENTS: readonly ["skill.matched", "skill.unmatched", "skill.started", "skill.completed", "skill.failed", "reasoning.step", "tool.progress", "file.created", "file.updated", "code.executed", "collaboration.handed_off", "collaboration.subtask.started", "collaboration.subtask.completed", "plan.created", "plan.step.started", "plan.step.completed", "response.max_iterations_reached", "stats.node_token_usage"];
|
|
42
|
+
export declare const OPTIONAL_SSE_EVENTS: readonly ["skill.matched", "skill.unmatched", "skill.started", "skill.completed", "skill.failed", "skill.loaded", "skill.resource_read", "reasoning.step", "tool.progress", "file.created", "file.updated", "code.executed", "collaboration.handed_off", "collaboration.subtask.started", "collaboration.subtask.completed", "plan.created", "plan.step.started", "plan.step.completed", "response.max_iterations_reached", "stats.node_token_usage"];
|
|
43
43
|
/**
|
|
44
44
|
* SSEEventType — SSE 事件类型字符串联合类型
|
|
45
45
|
*/
|
|
46
|
-
export type SSEEventType = 'session.created' | 'task.started' | 'task.completed' | 'task.error' | 'reasoning.started' | 'response.chunk' | 'tool.called' | 'tool.result' | 'tool.error' | 'hitl.waited' | 'hitl.resumed' | 'response.final' | 'stats.token_usage' | 'connection.heartbeat' | 'skill.matched' | 'skill.unmatched' | 'skill.started' | 'skill.completed' | 'skill.failed' | 'reasoning.step' | 'tool.progress' | 'file.created' | 'file.updated' | 'code.executed' | 'collaboration.handed_off' | 'collaboration.subtask.started' | 'collaboration.subtask.completed' | 'plan.created' | 'plan.step.started' | 'plan.step.completed' | 'response.max_iterations_reached' | 'stats.node_token_usage';
|
|
46
|
+
export type SSEEventType = 'session.created' | 'task.started' | 'task.completed' | 'task.error' | 'reasoning.started' | 'response.chunk' | 'tool.called' | 'tool.result' | 'tool.error' | 'hitl.waited' | 'hitl.resumed' | 'response.final' | 'stats.token_usage' | 'connection.heartbeat' | 'skill.matched' | 'skill.unmatched' | 'skill.started' | 'skill.completed' | 'skill.failed' | 'skill.loaded' | 'skill.resource_read' | 'reasoning.step' | 'tool.progress' | 'file.created' | 'file.updated' | 'code.executed' | 'collaboration.handed_off' | 'collaboration.subtask.started' | 'collaboration.subtask.completed' | 'plan.created' | 'plan.step.started' | 'plan.step.completed' | 'response.max_iterations_reached' | 'stats.node_token_usage';
|
|
47
47
|
import type { SessionCreatedPayload, TaskStartedPayload, TaskCompletedPayload, TaskErrorPayload } from './session-events.js';
|
|
48
|
-
import type { SkillMatchedPayload, SkillUnmatchedPayload, SkillStartedPayload, SkillCompletedPayload, SkillFailedPayload } from './skill-events.js';
|
|
48
|
+
import type { SkillMatchedPayload, SkillUnmatchedPayload, SkillStartedPayload, SkillCompletedPayload, SkillFailedPayload, SkillLoadedPayload, SkillResourceReadPayload } from './skill-events.js';
|
|
49
49
|
import type { ReasoningStartedPayload, ReasoningStepPayload, ResponseChunkPayload } from './reasoning-events.js';
|
|
50
50
|
import type { ToolCalledPayload, ToolResultPayload, ToolProgressPayload, ToolErrorPayload } from './tool-events.js';
|
|
51
51
|
import type { FileCreatedPayload, FileUpdatedPayload } from './file-events.js';
|
|
@@ -79,6 +79,8 @@ export interface SSEEventPayloadMap {
|
|
|
79
79
|
'skill.started': SkillStartedPayload;
|
|
80
80
|
'skill.completed': SkillCompletedPayload;
|
|
81
81
|
'skill.failed': SkillFailedPayload;
|
|
82
|
+
'skill.loaded': SkillLoadedPayload;
|
|
83
|
+
'skill.resource_read': SkillResourceReadPayload;
|
|
82
84
|
'reasoning.step': ReasoningStepPayload;
|
|
83
85
|
'tool.progress': ToolProgressPayload;
|
|
84
86
|
'file.created': FileCreatedPayload;
|
package/dist/sse/events/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* - skill.started / skill.completed / skill.failed(子图执行生命周期)
|
|
7
7
|
*
|
|
8
8
|
* @see design.md §1.6 SSE事件协议定义
|
|
9
|
-
* @see @
|
|
9
|
+
* @see @eap/contracts OPTIONAL_SSE_EVENTS
|
|
10
10
|
*/
|
|
11
11
|
/** 技能匹配成功 */
|
|
12
12
|
export interface SkillMatchedPayload {
|
|
@@ -46,3 +46,14 @@ export interface SkillFailedPayload {
|
|
|
46
46
|
skillName: string;
|
|
47
47
|
error: string;
|
|
48
48
|
}
|
|
49
|
+
/** 读入 SKILL.md(Harness,不是业务 Tool) */
|
|
50
|
+
export interface SkillLoadedPayload {
|
|
51
|
+
skillId: string;
|
|
52
|
+
skillName?: string;
|
|
53
|
+
path: string;
|
|
54
|
+
}
|
|
55
|
+
/** 读取 Skill 包内附属文件 */
|
|
56
|
+
export interface SkillResourceReadPayload {
|
|
57
|
+
skillId?: string;
|
|
58
|
+
path: string;
|
|
59
|
+
}
|
|
@@ -32,6 +32,16 @@ export declare class InMemoryTraceCollector implements ITraceCollector {
|
|
|
32
32
|
status: 'completed' | 'failed';
|
|
33
33
|
error?: string;
|
|
34
34
|
}): Promise<void>;
|
|
35
|
+
recordCheckpointRef(_input: {
|
|
36
|
+
checkpointId: string;
|
|
37
|
+
traceId: string;
|
|
38
|
+
spanId: string;
|
|
39
|
+
summary?: {
|
|
40
|
+
nodeId?: string;
|
|
41
|
+
threadId?: string;
|
|
42
|
+
step?: number;
|
|
43
|
+
};
|
|
44
|
+
}): Promise<void>;
|
|
35
45
|
/** 获取所有会话(调试用) */
|
|
36
46
|
getAllSessions(): TraceSession[];
|
|
37
47
|
}
|
|
@@ -32,7 +32,7 @@ export interface BudgetRecord {
|
|
|
32
32
|
/**
|
|
33
33
|
* ITokenBudgetRepository — 配额记录持久化抽象
|
|
34
34
|
*
|
|
35
|
-
* 由 InMemoryTokenBudgetRepository
|
|
35
|
+
* 由 InMemoryTokenBudgetRepository 或 PostgresTokenBudgetRepository 注入。
|
|
36
36
|
*/
|
|
37
37
|
export interface ITokenBudgetRepository {
|
|
38
38
|
/**
|
|
@@ -47,7 +47,7 @@ export interface ITokenBudgetRepository {
|
|
|
47
47
|
/**
|
|
48
48
|
* InMemoryTokenBudgetRepository — 基于 Map 的内存持久化
|
|
49
49
|
*
|
|
50
|
-
*
|
|
50
|
+
* 用于 `profile=dev` 文件路径及单测。Redis+PostgreSQL 路径使用 PostgresTokenBudgetRepository。
|
|
51
51
|
*/
|
|
52
52
|
export declare class InMemoryTokenBudgetRepository implements ITokenBudgetRepository {
|
|
53
53
|
private store;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* `EAP_TOOL_GATEWAY_TRANSPORT=http` 时用 HttpToolExecutor(仅调试)。
|
|
6
6
|
* desktop 经 ToolExecutionRouter 分流 Local / Gateway。
|
|
7
7
|
*/
|
|
8
|
-
import type { ILocalToolInstallStore, LocalToolInstallRecord } from '@
|
|
8
|
+
import type { ILocalToolInstallStore, LocalToolInstallRecord } from '@eap/contracts';
|
|
9
9
|
import { type DeploymentContext } from './tool-execution-router.js';
|
|
10
10
|
import type { IToolExecutor } from './tool-executor.interface.js';
|
|
11
11
|
export declare class EmptyInstallStore implements ILocalToolInstallStore {
|
|
@@ -9,6 +9,7 @@ import { HttpToolExecutor } from './http-tool-executor.js';
|
|
|
9
9
|
import { McpToolExecutor } from './mcp-tool-executor.js';
|
|
10
10
|
import { LocalToolExecutor } from './local-tool-executor.js';
|
|
11
11
|
import { ToolExecutionRouter, } from './tool-execution-router.js';
|
|
12
|
+
import { withHarnessPrimitives } from './harness-primitives.js';
|
|
12
13
|
export class EmptyInstallStore {
|
|
13
14
|
get() {
|
|
14
15
|
return null;
|
|
@@ -48,7 +49,7 @@ export function createToolExecutor(options) {
|
|
|
48
49
|
const transport = resolveGatewayTransport(options.gatewayTransport);
|
|
49
50
|
const serverExecutor = createServerExecutor(options.foundationUrl, transport, options.httpTimeout);
|
|
50
51
|
const localExecutor = new LocalToolExecutor({ installStore });
|
|
51
|
-
return new ToolExecutionRouter({
|
|
52
|
+
return withHarnessPrimitives(new ToolExecutionRouter({
|
|
52
53
|
httpExecutor: serverExecutor,
|
|
53
54
|
localExecutor,
|
|
54
55
|
installStore,
|
|
@@ -56,5 +57,5 @@ export function createToolExecutor(options) {
|
|
|
56
57
|
toolTypes: options.toolTypes,
|
|
57
58
|
toolRuntimes: options.toolRuntimes,
|
|
58
59
|
forceToolServer: options.forceToolServer,
|
|
59
|
-
});
|
|
60
|
+
}));
|
|
60
61
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Dev 下按 type:http 清单直连出站(gateway.baseUrl + pathTemplate)。
|
|
3
|
-
* URL 拼接与 host 白名单与 Tool Gateway 共用 @
|
|
3
|
+
* URL 拼接与 host 白名单与 Tool Gateway 共用 @eap/contracts http-outbound。
|
|
4
4
|
*/
|
|
5
5
|
import type { IToolExecutor, ToolCallRequest, ToolCallResult } from './tool-executor.interface.js';
|
|
6
6
|
export interface DevHttpExecution {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Dev 下按 type:http 清单直连出站(gateway.baseUrl + pathTemplate)。
|
|
3
|
-
* URL 拼接与 host 白名单与 Tool Gateway 共用 @
|
|
3
|
+
* URL 拼接与 host 白名单与 Tool Gateway 共用 @eap/contracts http-outbound。
|
|
4
4
|
*/
|
|
5
|
-
import { assertHttpHostAllowlisted, buildHttpToolUrl as buildSharedHttpToolUrl } from '@
|
|
5
|
+
import { assertHttpHostAllowlisted, buildHttpToolUrl as buildSharedHttpToolUrl, ErrorCodes } from '@eap/contracts';
|
|
6
|
+
import { abortOrTimeoutMessage, DEFAULT_HTTP_TOOL_TIMEOUT_SEC, isAbortError, resolveToolTimeoutSec, toToolTimeoutMs, } from './timeout.js';
|
|
6
7
|
export function resolveHttpExecutionFromRequest(request) {
|
|
7
8
|
const raw = request.execution;
|
|
8
9
|
if (!raw || typeof raw !== 'object')
|
|
@@ -22,7 +23,7 @@ export function resolveHttpExecutionFromRequest(request) {
|
|
|
22
23
|
allowedHosts: Array.isArray(e.allowedHosts)
|
|
23
24
|
? e.allowedHosts.filter((item) => typeof item === 'string')
|
|
24
25
|
: [],
|
|
25
|
-
timeout:
|
|
26
|
+
timeout: resolveToolTimeoutSec(e.timeout, DEFAULT_HTTP_TOOL_TIMEOUT_SEC),
|
|
26
27
|
};
|
|
27
28
|
}
|
|
28
29
|
export function buildHttpToolUrl(spec, args) {
|
|
@@ -48,8 +49,9 @@ export class DevHttpExecutor {
|
|
|
48
49
|
const args = request.arguments ?? {};
|
|
49
50
|
const url = buildHttpToolUrl(spec, args);
|
|
50
51
|
const method = (spec.method ?? 'GET').toUpperCase();
|
|
52
|
+
const timeoutSec = resolveToolTimeoutSec(spec.timeout, DEFAULT_HTTP_TOOL_TIMEOUT_SEC);
|
|
51
53
|
const controller = new AbortController();
|
|
52
|
-
const timer = setTimeout(() => controller.abort(),
|
|
54
|
+
const timer = setTimeout(() => controller.abort(), toToolTimeoutMs(timeoutSec, DEFAULT_HTTP_TOOL_TIMEOUT_SEC));
|
|
53
55
|
const headers = {
|
|
54
56
|
Accept: 'application/json, text/plain;q=0.9',
|
|
55
57
|
};
|
|
@@ -81,14 +83,15 @@ export class DevHttpExecutor {
|
|
|
81
83
|
};
|
|
82
84
|
}
|
|
83
85
|
catch (err) {
|
|
84
|
-
const
|
|
86
|
+
const timeoutSec = resolveToolTimeoutSec(spec?.timeout, DEFAULT_HTTP_TOOL_TIMEOUT_SEC);
|
|
87
|
+
const aborted = isAbortError(err);
|
|
85
88
|
return {
|
|
86
89
|
toolCallId: request.toolCallId,
|
|
87
90
|
toolName: request.toolName,
|
|
88
91
|
content: '',
|
|
89
92
|
success: false,
|
|
90
|
-
error:
|
|
91
|
-
errorCode: 'EXECUTION_FAILED',
|
|
93
|
+
error: abortOrTimeoutMessage(err, timeoutSec),
|
|
94
|
+
errorCode: aborted ? ErrorCodes.TOOL_TIMEOUT : 'EXECUTION_FAILED',
|
|
92
95
|
runtime: 'local',
|
|
93
96
|
};
|
|
94
97
|
}
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
* @see docs/workflows/local-agent-dev-loop.md
|
|
18
18
|
* @see runtime/src/tool/local-mcp-client.ts
|
|
19
19
|
*/
|
|
20
|
+
import { ErrorCodes } from '@eap/contracts';
|
|
21
|
+
import { isAbortError } from './timeout.js';
|
|
20
22
|
import { LocalMcpClient } from './local-mcp-client.js';
|
|
21
23
|
export class DevMcpExecutor {
|
|
22
24
|
client;
|
|
@@ -50,14 +52,14 @@ export class DevMcpExecutor {
|
|
|
50
52
|
};
|
|
51
53
|
}
|
|
52
54
|
catch (err) {
|
|
53
|
-
const
|
|
55
|
+
const aborted = isAbortError(err);
|
|
54
56
|
return {
|
|
55
57
|
toolCallId: request.toolCallId,
|
|
56
58
|
toolName: request.toolName,
|
|
57
59
|
content: '',
|
|
58
60
|
success: false,
|
|
59
|
-
error: message,
|
|
60
|
-
errorCode: 'EXECUTION_FAILED',
|
|
61
|
+
error: err instanceof Error ? err.message : String(err),
|
|
62
|
+
errorCode: aborted ? ErrorCodes.TOOL_TIMEOUT : 'EXECUTION_FAILED',
|
|
61
63
|
runtime: 'local',
|
|
62
64
|
};
|
|
63
65
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* - execution.protocol=mcp → DevMcpExecutor
|
|
8
8
|
* - execution.protocol=http → DevHttpExecutor
|
|
9
9
|
* - 能解析出 code handler → LocalToolExecutor
|
|
10
|
-
* - 其余 → NOT_CONFIGURED
|
|
10
|
+
* - 其余 → NOT_CONFIGURED
|
|
11
11
|
*/
|
|
12
12
|
import { DevMcpExecutor } from './dev-mcp-executor.js';
|
|
13
13
|
import type { IToolExecutor, ToolCallRequest, ToolCallResult } from './tool-executor.interface.js';
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* - execution.protocol=mcp → DevMcpExecutor
|
|
8
8
|
* - execution.protocol=http → DevHttpExecutor
|
|
9
9
|
* - 能解析出 code handler → LocalToolExecutor
|
|
10
|
-
* - 其余 → NOT_CONFIGURED
|
|
10
|
+
* - 其余 → NOT_CONFIGURED
|
|
11
11
|
*/
|
|
12
12
|
import { EmptyInstallStore } from './create-tool-executor.js';
|
|
13
13
|
import { DevMcpExecutor } from './dev-mcp-executor.js';
|
|
@@ -42,7 +42,7 @@ export class DevToolExecutor {
|
|
|
42
42
|
content: '',
|
|
43
43
|
success: false,
|
|
44
44
|
error: `Dev tool "${request.toolName}" is not executable: no MCP server, ` +
|
|
45
|
-
'HTTP gateway+pathTemplate, or code handler.
|
|
45
|
+
'HTTP gateway+pathTemplate, or code handler.',
|
|
46
46
|
errorCode: 'NOT_CONFIGURED',
|
|
47
47
|
runtime: 'local',
|
|
48
48
|
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* execute_command 的跨 OS 底板:本机壳、沙箱环境、解释器 shim、超时杀树。
|
|
3
|
+
* 不翻译 ls/dir;命令字符串按当前壳解释。
|
|
4
|
+
*/
|
|
5
|
+
import { type ChildProcess, type SpawnOptions } from 'node:child_process';
|
|
6
|
+
export interface ShellSpawn {
|
|
7
|
+
file: string;
|
|
8
|
+
args: string[];
|
|
9
|
+
shellName: string;
|
|
10
|
+
windowsVerbatimArguments?: boolean;
|
|
11
|
+
windowsHide?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare function shellNameFor(platform?: string): string;
|
|
14
|
+
/** system / 工具描述用的本机命令对照(只渲染当前 OS)。 */
|
|
15
|
+
export declare function commandDialectLines(platform?: string): string[];
|
|
16
|
+
export declare function resolveShellSpawn(command: string, platform?: string): ShellSpawn;
|
|
17
|
+
export declare function spawnOptionsFor(shell: ShellSpawn): Pick<SpawnOptions, 'windowsHide' | 'windowsVerbatimArguments'>;
|
|
18
|
+
export declare function findOnPath(names: string[], extraDirs?: string[]): string | undefined;
|
|
19
|
+
export declare function findPythonInterpreter(): string | undefined;
|
|
20
|
+
export declare function findNodeInterpreter(): string | undefined;
|
|
21
|
+
/** 在写根建立 python/node/sh shim。本机一个都没有则返回 undefined。 */
|
|
22
|
+
export declare function ensureInterpreterShims(workdir: string): string | undefined;
|
|
23
|
+
/** @deprecated 使用 ensureInterpreterShims */
|
|
24
|
+
export declare function ensurePythonShims(workdir: string): string | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* 模型可能从 SKILL.md 抄 `$EAP_SKILL_DIR`(POSIX)或 `%EAP_SKILL_DIR%`(cmd)。
|
|
27
|
+
* spawn 前替换成绝对路径,不依赖壳去展开。
|
|
28
|
+
*/
|
|
29
|
+
export declare function substituteSkillDir(command: string, skillDir?: string): string;
|
|
30
|
+
export declare function sandboxEnv(workdir: string, cwd: string, allowlist: string[], shimDir?: string, skillDir?: string): NodeJS.ProcessEnv;
|
|
31
|
+
export declare function formatSpawnError(err: unknown, shellFile: string): Error;
|
|
32
|
+
export declare function killProcessTree(child: ChildProcess): void;
|