@gt-fe/eap-runtime 0.0.8 → 0.0.10
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 +12 -17
- package/dist/api/handlers/invoke.handler.js +3 -3
- package/dist/api/handlers/messages.handler.js +0 -1
- package/dist/api/handlers/stream.handler.js +3 -3
- 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/contracts/trace-collector.d.ts +15 -1
- 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/graph/adapters/langgraph-checkpointer.js +3 -1
- package/dist/graph/adapters/langgraph.adapter.d.ts +1 -0
- package/dist/graph/adapters/langgraph.adapter.js +147 -91
- 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 +3 -3
- package/dist/graph/hitl/hitl-handler.d.ts +7 -0
- package/dist/graph/hitl/hitl-handler.js +47 -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 +24 -9
- package/dist/graph/trace-span.d.ts +22 -0
- package/dist/graph/trace-span.js +69 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- 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 +2 -1
- 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 +2 -2
- package/dist/registry/deployment-snapshot.d.ts +4 -4
- package/dist/registry/deployment-snapshot.js +50 -28
- package/dist/registry/graph-loader.d.ts +1 -1
- package/dist/registry/graph-loader.js +39 -76
- package/dist/registry/index.d.ts +1 -1
- package/dist/registry/index.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 +110 -34
- package/dist/runtime/dev-runtime.d.ts +6 -3
- package/dist/runtime/dev-runtime.js +21 -14
- 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 +15 -17
- package/dist/server.js +1 -1
- 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 +11 -0
- 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.js +3 -2
- package/dist/tool/harness-primitives.d.ts +32 -0
- package/dist/tool/harness-primitives.js +385 -0
- package/dist/tool/http-tool-executor.js +1 -1
- package/dist/tool/index.d.ts +2 -1
- package/dist/tool/index.js +2 -1
- package/dist/tool/local-tool-executor.d.ts +3 -3
- package/dist/tool/local-tool-executor.js +5 -7
- package/dist/tool/mcp-tool-executor.js +9 -1
- package/dist/tool/system-prompt-builder.d.ts +61 -25
- package/dist/tool/system-prompt-builder.js +195 -92
- package/dist/tool/tool-execution-router.js +1 -1
- package/dist/tool/tool-executor.interface.d.ts +12 -6
- package/package.json +2 -2
|
@@ -30,8 +30,9 @@ import { RoutingLLMProvider } from '../providers/routing-llm-provider.js';
|
|
|
30
30
|
import { createToolExecutor } from '../tool/create-tool-executor.js';
|
|
31
31
|
import { MockToolExecutor } from '../tool/mock-tool-executor.js';
|
|
32
32
|
import { DevToolExecutor } from '../tool/dev-tool-executor.js';
|
|
33
|
+
import { withHarnessPrimitives } from '../tool/harness-primitives.js';
|
|
33
34
|
import { AllowAllGovernanceClient, HttpGovernanceClient, } from '../governance/index.js';
|
|
34
|
-
import { InvokeOrchestrator, StreamOrchestrator, SessionService, MessageService, SessionContextService, TaskService, LangGraphAdapter, HitlHandler, TokenBudgetService,
|
|
35
|
+
import { InvokeOrchestrator, StreamOrchestrator, SessionService, MessageService, SessionContextService, TaskService, LangGraphAdapter, HitlHandler, TokenBudgetService, TokenStatsService, TokenBudgetGuard, SessionBudgetChecker, createAgentRegistryClient, GraphLoader, } from '../index.js';
|
|
35
36
|
import { createAgentRuntime } from './agent-runtime.js';
|
|
36
37
|
import { assembleRuntimeStorage } from './storage-profile.js';
|
|
37
38
|
import { resolveSkillHotReload, watchPreinstallSkillRoot, watchSkillRoots } from '../registry/skill-tree.js';
|
|
@@ -46,43 +47,45 @@ export function createDevRuntime() {
|
|
|
46
47
|
const foundationConfigured = Boolean(process.env.FOUNDATION_SERVICE_URL && process.env.FOUNDATION_SERVICE_URL.trim().length > 0);
|
|
47
48
|
const toolExecutionMode = (process.env.EAP_TOOL_EXECUTION_MODE ?? 'mcp').toLowerCase();
|
|
48
49
|
const deploymentContext = process.env.EAP_DEPLOYMENT_CONTEXT ?? 'server';
|
|
49
|
-
// ──
|
|
50
|
-
// 兼容旧变量:EAP_SESSION_STORE=memory → 强制 test(全内存)
|
|
51
|
-
const legacySessionStore = process.env.EAP_SESSION_STORE?.toLowerCase();
|
|
50
|
+
// ── 存储:未配库默认文件;配齐 DATABASE + Redis 则 Redis+PG ──
|
|
52
51
|
const storage = assembleRuntimeStorage({
|
|
53
|
-
defaultProfile:
|
|
54
|
-
profile: legacySessionStore === 'memory' || legacySessionStore === 'in-memory'
|
|
55
|
-
? 'test'
|
|
56
|
-
: undefined,
|
|
52
|
+
defaultProfile: 'dev',
|
|
57
53
|
});
|
|
54
|
+
const turnLog = process.env.EAP_LLM_TURN_LOG === '0' ? undefined : storage.turnLog;
|
|
58
55
|
// ── LLM Provider(本地 eap.config runtime.llm 优先,再 Foundation 路由,再环境直连)──
|
|
59
56
|
let llmProviderKind;
|
|
60
57
|
let llmProvider;
|
|
61
58
|
const localLlm = process.env.EAP_LLM_MODE === 'local';
|
|
62
59
|
if (localLlm || (!foundationConfigured && process.env.OPENAI_API_KEY)) {
|
|
63
60
|
llmProvider = localLlm
|
|
64
|
-
? createLocalLlmProvider(requireLocalLlmConnections())
|
|
61
|
+
? createLocalLlmProvider(requireLocalLlmConnections(), turnLog)
|
|
65
62
|
: new HttpLLMProvider({
|
|
66
63
|
apiKey: process.env.OPENAI_API_KEY ?? '',
|
|
67
64
|
baseUrl: process.env.OPENAI_BASE_URL,
|
|
68
65
|
defaultModel: process.env.EAP_DEFAULT_MODEL,
|
|
66
|
+
turnLog,
|
|
69
67
|
});
|
|
70
68
|
llmProviderKind = 'openai-http';
|
|
71
69
|
}
|
|
72
70
|
else if (foundationConfigured) {
|
|
73
|
-
llmProvider = new RoutingLLMProvider({ foundationUrl });
|
|
71
|
+
llmProvider = new RoutingLLMProvider({ foundationUrl, turnLog });
|
|
74
72
|
llmProviderKind = 'routing';
|
|
75
73
|
}
|
|
76
74
|
else {
|
|
77
|
-
llmProvider = createDefaultLLMProvider();
|
|
75
|
+
llmProvider = createDefaultLLMProvider(turnLog);
|
|
78
76
|
llmProviderKind = 'echo';
|
|
79
77
|
}
|
|
80
78
|
// ── Tool Executor(显式 mock → dev+mcp 直连,缺配置失败 → 通用路由)──
|
|
81
|
-
const
|
|
79
|
+
const needsHarnessWrap = toolExecutionMode === 'mock' ||
|
|
80
|
+
(toolExecutionMode === 'mcp' && deploymentContext === 'dev');
|
|
81
|
+
const innerExecutor = toolExecutionMode === 'mock'
|
|
82
82
|
? new MockToolExecutor({ toolsDir: process.env.EAP_LOCAL_TOOLS_DIR })
|
|
83
83
|
: toolExecutionMode === 'mcp' && deploymentContext === 'dev'
|
|
84
84
|
? new DevToolExecutor()
|
|
85
85
|
: createToolExecutor({ foundationUrl, deploymentContext });
|
|
86
|
+
const toolExecutor = needsHarnessWrap
|
|
87
|
+
? withHarnessPrimitives(innerExecutor)
|
|
88
|
+
: innerExecutor;
|
|
86
89
|
// ── Governance ──
|
|
87
90
|
const governanceClient = process.env.GOVERNANCE_DISABLED === '1' || !foundationConfigured
|
|
88
91
|
? new AllowAllGovernanceClient()
|
|
@@ -99,7 +102,7 @@ export function createDevRuntime() {
|
|
|
99
102
|
const sessionContextService = new SessionContextService(sessionService, messageService);
|
|
100
103
|
// ── Task / Token ──
|
|
101
104
|
const taskService = new TaskService();
|
|
102
|
-
const budgetService = new TokenBudgetService(
|
|
105
|
+
const budgetService = new TokenBudgetService(storage.tokenBudgetRepository);
|
|
103
106
|
const tokenStatsService = new TokenStatsService();
|
|
104
107
|
const tokenBudgetGuard = new TokenBudgetGuard(budgetService);
|
|
105
108
|
const sessionBudgetChecker = new SessionBudgetChecker(budgetService);
|
|
@@ -168,6 +171,8 @@ export function createDevRuntime() {
|
|
|
168
171
|
hitlHandler,
|
|
169
172
|
graphLoader,
|
|
170
173
|
messageService,
|
|
174
|
+
sessionService,
|
|
175
|
+
turnLog,
|
|
171
176
|
});
|
|
172
177
|
return {
|
|
173
178
|
invokeOrchestrator,
|
|
@@ -177,6 +182,7 @@ export function createDevRuntime() {
|
|
|
177
182
|
streamResumeHitl: (taskId, response) => agentRuntime.streamResumeHitl(taskId, response),
|
|
178
183
|
sessionService,
|
|
179
184
|
messageService,
|
|
185
|
+
turnLog,
|
|
180
186
|
sessionContextService,
|
|
181
187
|
taskService,
|
|
182
188
|
tokenStatsService,
|
|
@@ -189,9 +195,10 @@ export function createDevRuntime() {
|
|
|
189
195
|
llmDefaultModel: process.env.EAP_DEFAULT_MODEL ?? 'DeepSeek-V4-Pro',
|
|
190
196
|
governanceKind: governanceClient instanceof AllowAllGovernanceClient ? 'AllowAll' : 'Http',
|
|
191
197
|
storageProfile: storage.profile,
|
|
192
|
-
sessionStoreKind: storage.diagnostics.sessionKind
|
|
198
|
+
sessionStoreKind: storage.diagnostics.sessionKind,
|
|
193
199
|
messageStoreKind: storage.diagnostics.messageKind,
|
|
194
200
|
checkpointKind: storage.diagnostics.checkpointKind,
|
|
201
|
+
llmTurnKind: storage.diagnostics.llmTurnKind,
|
|
195
202
|
foundationConfigured,
|
|
196
203
|
skillHotReload,
|
|
197
204
|
},
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { AgentRuntime, createAgentRuntime, type AgentRuntimeDeps, type ForkRelationRecord, type RecordForkRelation, } from './agent-runtime.js';
|
|
2
|
-
export type { ExecuteParams, ExecuteResult, ForkOverrides, ForkResult, HitlResponse, ResumeHitlResult, SSEEvent, } from './types.js';
|
|
1
|
+
export { AgentRuntime, createAgentRuntime, type AgentRuntimeDeps, type ForkRelationRecord, type RecordForkRelation, type ConversationDetail, } from './agent-runtime.js';
|
|
2
|
+
export type { ExecuteParams, ExecuteResult, ForkParams, ForkOverrides, ForkResult, HitlResponse, ResumeHitlResult, SSEEvent, } from './types.js';
|
|
3
3
|
export { createDevRuntime, type DevRuntime, } from './dev-runtime.js';
|
|
4
|
-
export { assembleRuntimeStorage, resolveRuntimeStorageProfile, type RuntimeStorageProfile, type AssembleRuntimeStorageOptions, type AssembledRuntimeStorage, } from './storage-profile.js';
|
|
4
|
+
export { assembleRuntimeStorage, resolveRuntimeStorageProfile, resolveDevStorageDirs, type RuntimeStorageProfile, type AssembleRuntimeStorageOptions, type AssembledRuntimeStorage, } from './storage-profile.js';
|
package/dist/runtime/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { AgentRuntime, createAgentRuntime, } from './agent-runtime.js';
|
|
2
2
|
export { createDevRuntime, } from './dev-runtime.js';
|
|
3
|
-
export { assembleRuntimeStorage, resolveRuntimeStorageProfile, } from './storage-profile.js';
|
|
3
|
+
export { assembleRuntimeStorage, resolveRuntimeStorageProfile, resolveDevStorageDirs, } from './storage-profile.js';
|
|
@@ -9,11 +9,13 @@ import type { ICheckpointSaver } from '../checkpoint/contracts/checkpoint-saver.
|
|
|
9
9
|
import { type IPgPool } from '../checkpoint/pg-checkpoint-saver.js';
|
|
10
10
|
import type { ISessionRepository } from '../session/session.service.js';
|
|
11
11
|
import type { IFullMessageRepository } from '../session/message.service.js';
|
|
12
|
+
import type { ILlmTurnLog } from '../debug/llm-turn-log.js';
|
|
13
|
+
import { type ITokenBudgetRepository } from '../token/token-budget.service.js';
|
|
12
14
|
export type RuntimeStorageProfile = 'test' | 'dev' | 'integration' | 'production';
|
|
13
15
|
export interface AssembleRuntimeStorageOptions {
|
|
14
16
|
/** 显式 profile;缺省读 EAP_RUNTIME_STORAGE_PROFILE */
|
|
15
17
|
profile?: RuntimeStorageProfile;
|
|
16
|
-
/** 未指定 profile
|
|
18
|
+
/** 未指定 profile 且未配库时的默认值(本地 CLI → `dev` 文件) */
|
|
17
19
|
defaultProfile: RuntimeStorageProfile;
|
|
18
20
|
/** File Checkpoint / Session / Message 根目录 */
|
|
19
21
|
checkpointDir?: string;
|
|
@@ -31,20 +33,27 @@ export interface AssembledRuntimeStorage {
|
|
|
31
33
|
/** undefined = SessionService 默认 InMemory */
|
|
32
34
|
sessionRepository?: ISessionRepository;
|
|
33
35
|
messageRepository: IFullMessageRepository;
|
|
36
|
+
turnLog: ILlmTurnLog;
|
|
37
|
+
tokenBudgetRepository: ITokenBudgetRepository;
|
|
34
38
|
diagnostics: {
|
|
35
39
|
profile: RuntimeStorageProfile;
|
|
36
|
-
checkpointKind: '
|
|
37
|
-
sessionKind: '
|
|
38
|
-
messageKind: '
|
|
40
|
+
checkpointKind: 'file' | 'redis+pg';
|
|
41
|
+
sessionKind: 'file' | 'hosting';
|
|
42
|
+
messageKind: 'file' | 'postgres';
|
|
43
|
+
llmTurnKind: 'file' | 'postgres';
|
|
44
|
+
tokenBudgetKind: 'process' | 'postgres';
|
|
39
45
|
};
|
|
40
46
|
}
|
|
41
47
|
export declare function resolveRuntimeStorageProfile(explicit: RuntimeStorageProfile | undefined, defaultProfile: RuntimeStorageProfile, env?: NodeJS.ProcessEnv): RuntimeStorageProfile;
|
|
48
|
+
/** 本地 File 存储默认落工程 `.eap/`,可用 EAP_DATA_DIR / EAP_*_DIR 覆盖。 */
|
|
49
|
+
export declare function resolveDevStorageDirs(env?: NodeJS.ProcessEnv, cwd?: string): {
|
|
50
|
+
checkpointDir: string;
|
|
51
|
+
sessionDir: string;
|
|
52
|
+
messageDir: string;
|
|
53
|
+
};
|
|
42
54
|
/**
|
|
43
|
-
* 按 profile 装配 Checkpoint /
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* - dev: File Checkpoint + File Session + File Message
|
|
47
|
-
* - integration/production: Message=PG;Checkpoint=Redis 热 + PG 备;
|
|
48
|
-
* Session 仓储不落 PG(sessionId 权威在 Hosting.sessions,Runtime 内存采纳)
|
|
55
|
+
* 按 profile 装配 Checkpoint / Message / Token / LLM 回合存储。
|
|
56
|
+
* `dev`:文件。其余 profile:Redis + PostgreSQL(缺配置则抛错)。
|
|
57
|
+
* 未设 profile 时:已配置 DB 或 Redis 则按 Redis+PostgreSQL;否则使用 defaultProfile。
|
|
49
58
|
*/
|
|
50
59
|
export declare function assembleRuntimeStorage(options: AssembleRuntimeStorageOptions, env?: NodeJS.ProcessEnv): AssembledRuntimeStorage;
|
|
@@ -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
|
@@ -12,12 +12,8 @@ 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;
|
|
@@ -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
|
@@ -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
|
@@ -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;
|
|
@@ -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
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 平台默认 Harness 原语:read_file / write_file / execute_command。
|
|
3
|
+
*
|
|
4
|
+
* 不写进 agent.manifest.toolsets。同名业务工具优先(问数 file-io 等)。
|
|
5
|
+
* 读:工作目录 + 技能包 + EAP_LOCAL_SKILLS_DIR + FILE_IO_ROOT。
|
|
6
|
+
* 写:仅工作目录,且不跟随符号链接。
|
|
7
|
+
* 命令:cwd 落在 jail 内;环境变量白名单,不继承 process.env。
|
|
8
|
+
*/
|
|
9
|
+
import type { LoadedToolMap } from './loaded-tool-definition.js';
|
|
10
|
+
import type { IToolExecutor, ToolCallRequest, ToolCallResult } from './tool-executor.interface.js';
|
|
11
|
+
export declare function mergeHarnessPrimitives(loadedTools: LoadedToolMap | undefined): LoadedToolMap | undefined;
|
|
12
|
+
/** 装配点:业务 toolsets + 平台 Harness 原语。 */
|
|
13
|
+
export declare function assembleLoadedTools(loadedTools: LoadedToolMap | undefined): LoadedToolMap | undefined;
|
|
14
|
+
export interface HarnessJailOptions {
|
|
15
|
+
workdir?: string;
|
|
16
|
+
extraRoots?: string[];
|
|
17
|
+
}
|
|
18
|
+
export declare function resolveJailRoots(options?: HarnessJailOptions): string[];
|
|
19
|
+
export declare function resolveJailedPath(requested: string, roots: string[], opts?: {
|
|
20
|
+
mustExist?: boolean;
|
|
21
|
+
}): string;
|
|
22
|
+
export declare class HarnessPrimitiveExecutor implements IToolExecutor {
|
|
23
|
+
private readonly workdir?;
|
|
24
|
+
private readonly extraRoots?;
|
|
25
|
+
constructor(options?: HarnessJailOptions);
|
|
26
|
+
private rootsFor;
|
|
27
|
+
execute(request: ToolCallRequest): Promise<ToolCallResult>;
|
|
28
|
+
private readFile;
|
|
29
|
+
private writeFile;
|
|
30
|
+
private executeCommand;
|
|
31
|
+
}
|
|
32
|
+
export declare function withHarnessPrimitives(inner: IToolExecutor, options?: HarnessJailOptions): IToolExecutor;
|