@gt-fe/eap-runtime 0.0.20 → 0.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/api/handlers/invoke.handler.d.ts +7 -0
- package/dist/api/handlers/invoke.handler.js +52 -10
- package/dist/api/handlers/stream.handler.d.ts +6 -0
- package/dist/api/handlers/stream.handler.js +60 -39
- package/dist/api/routes/agent.routes.d.ts +8 -1
- package/dist/checkpoint/file-checkpoint-saver.d.ts +4 -0
- package/dist/checkpoint/file-checkpoint-saver.js +51 -22
- package/dist/checkpoint/index.d.ts +1 -1
- package/dist/checkpoint/index.js +1 -1
- package/dist/common/types.d.ts +2 -2
- package/dist/common/types.js +1 -1
- package/dist/execution/index.d.ts +2 -0
- package/dist/execution/index.js +2 -0
- package/dist/execution/interceptors.d.ts +40 -0
- package/dist/execution/interceptors.js +23 -0
- package/dist/execution/ports.d.ts +18 -0
- package/dist/execution/ports.js +13 -0
- package/dist/governance/audit-reporter.d.ts +14 -0
- package/dist/governance/audit-reporter.js +18 -0
- package/dist/governance/index.d.ts +2 -0
- package/dist/governance/index.js +1 -0
- package/dist/governance/permission-guard.d.ts +6 -2
- package/dist/governance/permission-guard.js +38 -5
- package/dist/graph/adapters/graph-nesting.d.ts +12 -0
- package/dist/graph/adapters/graph-nesting.js +29 -0
- package/dist/graph/adapters/index.d.ts +2 -0
- package/dist/graph/adapters/index.js +2 -0
- package/dist/graph/adapters/langgraph-checkpointer.d.ts +11 -0
- package/dist/graph/adapters/langgraph-checkpointer.js +48 -9
- package/dist/graph/adapters/langgraph.adapter.d.ts +33 -11
- package/dist/graph/adapters/langgraph.adapter.js +200 -98
- package/dist/graph/adapters/skill-isolate.d.ts +13 -0
- package/dist/graph/adapters/skill-isolate.js +39 -0
- package/dist/graph/adapters/subgraph-compiler.d.ts +7 -2
- package/dist/graph/adapters/subgraph-compiler.js +63 -30
- package/dist/graph/contracts/executable-graph.d.ts +33 -5
- package/dist/graph/hitl/hitl-handler.d.ts +13 -4
- package/dist/graph/hitl/hitl-handler.js +80 -7
- package/dist/graph/nodes/index.d.ts +1 -0
- package/dist/graph/nodes/index.js +1 -0
- package/dist/graph/nodes/llm-node.d.ts +3 -1
- package/dist/graph/nodes/llm-node.js +26 -2
- package/dist/graph/nodes/rag/dedup.d.ts +20 -0
- package/dist/graph/nodes/rag/dedup.js +77 -0
- package/dist/graph/nodes/rag/denoise.d.ts +58 -0
- package/dist/graph/nodes/rag/denoise.js +220 -0
- package/dist/graph/nodes/rag/fusion/fuse.d.ts +11 -0
- package/dist/graph/nodes/rag/fusion/fuse.js +25 -0
- package/dist/graph/nodes/rag/fusion/normalize.d.ts +9 -0
- package/dist/graph/nodes/rag/fusion/normalize.js +135 -0
- package/dist/graph/nodes/rag/index.d.ts +18 -0
- package/dist/graph/nodes/rag/index.js +17 -0
- package/dist/graph/nodes/rag/prompts.d.ts +12 -0
- package/dist/graph/nodes/rag/prompts.js +40 -0
- package/dist/graph/nodes/rag/rag-node.d.ts +21 -0
- package/dist/graph/nodes/rag/rag-node.js +135 -0
- package/dist/graph/nodes/rag/rag-search-tool.d.ts +48 -0
- package/dist/graph/nodes/rag/rag-search-tool.js +230 -0
- package/dist/graph/nodes/rag/react-loop.d.ts +57 -0
- package/dist/graph/nodes/rag/react-loop.js +467 -0
- package/dist/graph/nodes/rag/retrievers/http-embedder.d.ts +29 -0
- package/dist/graph/nodes/rag/retrievers/http-embedder.js +66 -0
- package/dist/graph/nodes/rag/retrievers/in-memory-retriever.d.ts +17 -0
- package/dist/graph/nodes/rag/retrievers/in-memory-retriever.js +18 -0
- package/dist/graph/nodes/rag/retrievers/local-sqlite-retriever.d.ts +46 -0
- package/dist/graph/nodes/rag/retrievers/local-sqlite-retriever.js +85 -0
- package/dist/graph/nodes/rag/tools.d.ts +90 -0
- package/dist/graph/nodes/rag/tools.js +260 -0
- package/dist/graph/nodes/rag/types.d.ts +226 -0
- package/dist/graph/nodes/rag/types.js +9 -0
- package/dist/graph/nodes/tool-node.d.ts +19 -1
- package/dist/graph/nodes/tool-node.js +158 -33
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/memory/semantic-retrieval.service.d.ts +1 -1
- package/dist/memory/semantic-retrieval.service.js +13 -23
- package/dist/providers/index.d.ts +2 -2
- package/dist/providers/index.js +2 -2
- package/dist/providers/local-llm-provider.d.ts +6 -0
- package/dist/providers/local-llm-provider.js +29 -5
- package/dist/providers/routing-llm-provider.d.ts +7 -2
- package/dist/providers/routing-llm-provider.js +71 -16
- package/dist/registry/deployment-snapshot.js +18 -4
- package/dist/registry/graph-loader.d.ts +2 -0
- package/dist/registry/graph-loader.js +39 -2
- package/dist/registry/preload-flags.d.ts +1 -1
- package/dist/registry/preload-flags.js +1 -1
- package/dist/runtime/agent-runtime.d.ts +5 -0
- package/dist/runtime/agent-runtime.js +107 -70
- package/dist/runtime/dev-rag-deps.d.ts +21 -0
- package/dist/runtime/dev-rag-deps.js +186 -0
- package/dist/runtime/dev-runtime.d.ts +18 -2
- package/dist/runtime/dev-runtime.js +68 -8
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/types.d.ts +10 -9
- package/dist/session/apply-session-compression.d.ts +85 -0
- package/dist/session/apply-session-compression.js +281 -0
- package/dist/session/apply-session-memory.d.ts +21 -0
- package/dist/session/apply-session-memory.js +48 -0
- package/dist/session/index.d.ts +2 -0
- package/dist/session/index.js +2 -0
- package/dist/session/persist-turn-messages.d.ts +57 -1
- package/dist/session/persist-turn-messages.js +160 -5
- package/dist/sse/events/index.d.ts +13 -4
- package/dist/sse/events/index.js +9 -1
- package/dist/sse/events/rag-events.d.ts +63 -0
- package/dist/sse/events/rag-events.js +9 -0
- package/dist/sse/events/session-events.d.ts +38 -0
- package/dist/sse/events/session-events.js +4 -0
- package/dist/token/index.d.ts +2 -1
- package/dist/token/index.js +2 -1
- package/dist/token/record-task-token-usage.d.ts +25 -0
- package/dist/token/record-task-token-usage.js +44 -0
- package/dist/token/token-detail-mode.d.ts +4 -4
- package/dist/token/token-detail-mode.js +4 -4
- package/dist/token/token-detail.d.ts +8 -0
- package/dist/token/token-detail.js +22 -0
- package/dist/token/token-stats.service.d.ts +2 -2
- package/dist/token/token-stats.service.js +1 -1
- package/dist/tool/create-tool-executor.d.ts +6 -0
- package/dist/tool/create-tool-executor.js +4 -3
- package/dist/tool/harness-primitives.d.ts +9 -1
- package/dist/tool/harness-primitives.js +43 -12
- package/dist/tool/index.d.ts +2 -1
- package/dist/tool/index.js +2 -1
- package/dist/tool/tool-confirmation.js +8 -5
- package/dist/tool/tool-executor.interface.d.ts +27 -0
- package/dist/tool/tool-orchestrator.d.ts +3 -1
- package/dist/tool/tool-orchestrator.js +15 -6
- package/dist/tool/tool-retry.d.ts +15 -0
- package/dist/tool/tool-retry.js +69 -0
- package/package.json +2 -2
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dev 装配的 rag 依赖 — createDevRuntime 检测显式配置后自动注入
|
|
3
|
+
*
|
|
4
|
+
* 启用条件:EAP_EMBED_API_KEY 存在(缺省不注入,行为与无 rag 的 master 一致)。
|
|
5
|
+
* retriever 惰性初始化:vector-engine(better-sqlite3+sqlite-vec,native 依赖)
|
|
6
|
+
* 只在首次检索时动态 import——装配期零 native 加载,服务端部署不受影响。
|
|
7
|
+
* import 目标可用 EAP_VECTOR_ENGINE_PATH 指定绝对路径(默认解析 @eap/vector-engine;
|
|
8
|
+
* eap-cli 发版链等无该包的环境走绝对路径注入)。
|
|
9
|
+
*
|
|
10
|
+
* 环境变量(与 .local 演示脚本同一套):
|
|
11
|
+
* - EAP_EMBED_API_KEY / EAP_EMBED_BASE_URL / EAP_EMBED_MODEL / EAP_EMBED_DIMS:embedding 网关
|
|
12
|
+
* - RAG_DB:向量库路径(缺省 ~/.eap/rag/agent.db)
|
|
13
|
+
*/
|
|
14
|
+
import type { IRetriever, RagNodeDeps } from '../graph/nodes/rag/index.js';
|
|
15
|
+
/**
|
|
16
|
+
* dev rag 装配:EAP_EMBED_API_KEY 显式配置才启用,否则 undefined(不注入)。
|
|
17
|
+
* llmProvider 复用 dev 装配已构造的实例(与 llm 节点同一体系)。
|
|
18
|
+
* EAP_RAG_TRACE=1 时接 console 观测 rag.* 事件流(轮次决策/各源检索/降噪/收束),
|
|
19
|
+
* 供多源融合行为观察;缺省静默。
|
|
20
|
+
*/
|
|
21
|
+
export declare function createDevRagNodeDeps(llmProvider: RagNodeDeps['llmProvider'], loadFn?: () => Promise<IRetriever>): RagNodeDeps | undefined;
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dev 装配的 rag 依赖 — createDevRuntime 检测显式配置后自动注入
|
|
3
|
+
*
|
|
4
|
+
* 启用条件:EAP_EMBED_API_KEY 存在(缺省不注入,行为与无 rag 的 master 一致)。
|
|
5
|
+
* retriever 惰性初始化:vector-engine(better-sqlite3+sqlite-vec,native 依赖)
|
|
6
|
+
* 只在首次检索时动态 import——装配期零 native 加载,服务端部署不受影响。
|
|
7
|
+
* import 目标可用 EAP_VECTOR_ENGINE_PATH 指定绝对路径(默认解析 @eap/vector-engine;
|
|
8
|
+
* eap-cli 发版链等无该包的环境走绝对路径注入)。
|
|
9
|
+
*
|
|
10
|
+
* 环境变量(与 .local 演示脚本同一套):
|
|
11
|
+
* - EAP_EMBED_API_KEY / EAP_EMBED_BASE_URL / EAP_EMBED_MODEL / EAP_EMBED_DIMS:embedding 网关
|
|
12
|
+
* - RAG_DB:向量库路径(缺省 ~/.eap/rag/agent.db)
|
|
13
|
+
*/
|
|
14
|
+
import { homedir } from 'node:os';
|
|
15
|
+
import { dirname, join } from 'node:path';
|
|
16
|
+
import { existsSync, mkdirSync, readFileSync, watchFile } from 'node:fs';
|
|
17
|
+
import { pathToFileURL } from 'node:url';
|
|
18
|
+
import { appendFileSync } from 'node:fs';
|
|
19
|
+
// 惰性读 env:模块顶层读不到(runtime 经 sdk import 链早于 CLI 灌 .env.local 执行)
|
|
20
|
+
const trace = (line) => {
|
|
21
|
+
console.log(line);
|
|
22
|
+
const f = process.env.EAP_RAG_TRACE_FILE;
|
|
23
|
+
if (f)
|
|
24
|
+
appendFileSync(f, line + '\n', 'utf-8');
|
|
25
|
+
};
|
|
26
|
+
/** 入库日志环形缓冲(globalThis 桥接:Playground 服务同进程读,GET /api/rag-ingest-log) */
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
+
const ingestLogBuf = (globalThis.__ragIngestLog ??= []);
|
|
29
|
+
const ingestLog = (line) => {
|
|
30
|
+
const ts = new Date().toISOString().slice(11, 19);
|
|
31
|
+
ingestLogBuf.push(`[${ts}] ${line}`);
|
|
32
|
+
if (ingestLogBuf.length > 200)
|
|
33
|
+
ingestLogBuf.splice(0, ingestLogBuf.length - 200);
|
|
34
|
+
};
|
|
35
|
+
import { HttpEmbedder, LocalSqliteRetriever } from '../graph/nodes/rag/index.js';
|
|
36
|
+
/** 惰性 IRetriever:首次调用才加载真实现;加载失败不缓存,允许下轮重试 */
|
|
37
|
+
class LazyLocalRetriever {
|
|
38
|
+
load;
|
|
39
|
+
sourceId = 'local';
|
|
40
|
+
implPromise;
|
|
41
|
+
constructor(load) {
|
|
42
|
+
this.load = load;
|
|
43
|
+
}
|
|
44
|
+
ensure() {
|
|
45
|
+
this.implPromise ??= this.load().catch((err) => {
|
|
46
|
+
this.implPromise = undefined; // 失败不缓存,下次调用重试加载
|
|
47
|
+
throw err;
|
|
48
|
+
});
|
|
49
|
+
return this.implPromise;
|
|
50
|
+
}
|
|
51
|
+
async retrieve(query, opts) {
|
|
52
|
+
return (await this.ensure()).retrieve(query, opts);
|
|
53
|
+
}
|
|
54
|
+
async retrieveByKeyword(query, opts) {
|
|
55
|
+
const impl = await this.ensure();
|
|
56
|
+
if (!impl.retrieveByKeyword)
|
|
57
|
+
return [];
|
|
58
|
+
return impl.retrieveByKeyword(query, opts);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** 默认加载器:HttpEmbedder + vector-engine + LocalSqliteRetriever(单库:RAG_DB) */
|
|
62
|
+
async function loadLocalRetriever() {
|
|
63
|
+
const dims = Number(process.env.EAP_EMBED_DIMS ?? 1024);
|
|
64
|
+
const embedder = new HttpEmbedder({
|
|
65
|
+
baseUrl: String(process.env.EAP_EMBED_BASE_URL ?? 'https://gtaiapi.gtcloud.cn'),
|
|
66
|
+
model: String(process.env.EAP_EMBED_MODEL ?? 'Qwen3-Embedding-8B'),
|
|
67
|
+
apiKey: String(process.env.EAP_EMBED_API_KEY ?? ''),
|
|
68
|
+
dims,
|
|
69
|
+
dimensions: dims,
|
|
70
|
+
});
|
|
71
|
+
const moduleName = process.env.EAP_VECTOR_ENGINE_PATH ?? '@eap/vector-engine';
|
|
72
|
+
// Windows 绝对路径须转 file:// URL(盘符字母否则被解析为 URL scheme)
|
|
73
|
+
const spec = /^[a-zA-Z]:[\\/]/.test(moduleName) ? pathToFileURL(moduleName).href : moduleName;
|
|
74
|
+
const mod = (await import(spec));
|
|
75
|
+
const dbPath = process.env.RAG_DB ?? join(homedir(), '.eap', 'rag', 'agent.db');
|
|
76
|
+
mkdirSync(dirname(dbPath), { recursive: true });
|
|
77
|
+
const engine = await mod.createAsyncEngine({ dbPath, dims });
|
|
78
|
+
// 自动向量化:EAP_RAG_AUTO_INGEST=1 时常驻调度器扫授权目录,文件放入即入库
|
|
79
|
+
// (写入侧归宿主/桌面语义;dev 演示用轮询,生产为授权事件触发)。
|
|
80
|
+
// RAG_DOCS_DIR 支持 `;` 分隔多目录——"授权一个新文件夹" = 追加一个路径。
|
|
81
|
+
//
|
|
82
|
+
// 授权清单热更新(客户端授权动作的 dev 模拟):RAG_AUTHORIZED_DIRS_FILE(json
|
|
83
|
+
// {"dirs":[...]},缺省 <库目录>/authorized-dirs.json)存在则覆盖 RAG_DOCS_DIR,
|
|
84
|
+
// 文件变更 → scheduler.updateDirs 即时生效(新目录入库/移除软删),全程不重启。
|
|
85
|
+
if (process.env.EAP_RAG_AUTO_INGEST) {
|
|
86
|
+
const envDirs = (process.env.RAG_DOCS_DIR ?? join(dirname(dbPath), 'docs'))
|
|
87
|
+
.split(';')
|
|
88
|
+
.map((s) => s.trim())
|
|
89
|
+
.filter(Boolean);
|
|
90
|
+
const authFile = process.env.RAG_AUTHORIZED_DIRS_FILE ?? join(dirname(dbPath), 'authorized-dirs.json');
|
|
91
|
+
const readAuthDirs = () => {
|
|
92
|
+
try {
|
|
93
|
+
const parsed = JSON.parse(readFileSync(authFile, 'utf-8'));
|
|
94
|
+
if (Array.isArray(parsed.dirs) && parsed.dirs.every((d) => typeof d === 'string')) {
|
|
95
|
+
const dirs = parsed.dirs.map((d) => d.trim()).filter(Boolean);
|
|
96
|
+
return dirs.length ? dirs : undefined; // 空清单视为无效,防误清库
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// 文件不存在/解析失败:保持现清单
|
|
101
|
+
}
|
|
102
|
+
return undefined;
|
|
103
|
+
};
|
|
104
|
+
let currentDirs = readAuthDirs() ?? envDirs;
|
|
105
|
+
const scheduler = new mod.IngestScheduler({
|
|
106
|
+
engine,
|
|
107
|
+
embedder,
|
|
108
|
+
userId: process.env.RAG_USER ?? 'anonymous',
|
|
109
|
+
dirs: currentDirs,
|
|
110
|
+
intervalMs: Number(process.env.EAP_RAG_SCAN_INTERVAL_MS ?? 30_000),
|
|
111
|
+
watch: process.env.EAP_RAG_SCAN_MODE !== 'interval',
|
|
112
|
+
onEvent: (e) => {
|
|
113
|
+
if (e.type === 'file.ingested') {
|
|
114
|
+
const line = `[rag-ingest] 📥 ${String(e['filePath']).split('\\').pop()} → ${e['chunks']} 片`;
|
|
115
|
+
console.log(line);
|
|
116
|
+
ingestLog(line);
|
|
117
|
+
}
|
|
118
|
+
else if (e.type === 'file.failed') {
|
|
119
|
+
const line = `[rag-ingest] ✗ ${String(e['filePath']).split('\\').pop()}: ${e['error']}`;
|
|
120
|
+
console.log(line);
|
|
121
|
+
ingestLog(line);
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
scheduler.start();
|
|
126
|
+
ingestLog(`🚀 自动向量化已启动:${currentDirs.length} 个授权目录`);
|
|
127
|
+
console.log(`[rag-ingest] 自动向量化已启动:目录 ${currentDirs.join('; ')}(${Number(process.env.EAP_RAG_SCAN_INTERVAL_MS ?? 30_000) / 1000}s 轮询${existsSync(authFile) ? `,授权清单 ${authFile} 热更新` : ''})`);
|
|
128
|
+
// 授权清单文件变更 → updateDirs(编辑器保存/前端写入均触发;stat 轮询最稳)
|
|
129
|
+
watchFile(authFile, { interval: 2000 }, () => {
|
|
130
|
+
const next = readAuthDirs();
|
|
131
|
+
if (next && next.join(';') !== currentDirs.join(';')) {
|
|
132
|
+
currentDirs = next;
|
|
133
|
+
scheduler.updateDirs(next);
|
|
134
|
+
const line = `[rag-ingest] 🔑 授权目录更新(免重启生效):${next.length} 个目录`;
|
|
135
|
+
console.log(line + `(${next.join('; ')})`);
|
|
136
|
+
ingestLog(line);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
return new LocalSqliteRetriever({ engine, embedder });
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* dev rag 装配:EAP_EMBED_API_KEY 显式配置才启用,否则 undefined(不注入)。
|
|
144
|
+
* llmProvider 复用 dev 装配已构造的实例(与 llm 节点同一体系)。
|
|
145
|
+
* EAP_RAG_TRACE=1 时接 console 观测 rag.* 事件流(轮次决策/各源检索/降噪/收束),
|
|
146
|
+
* 供多源融合行为观察;缺省静默。
|
|
147
|
+
*/
|
|
148
|
+
export function createDevRagNodeDeps(llmProvider, loadFn = loadLocalRetriever) {
|
|
149
|
+
if (!process.env.EAP_EMBED_API_KEY)
|
|
150
|
+
return undefined;
|
|
151
|
+
const fmt = (v, n = 40) => String(v ?? '').replace(/\s+/g, ' ').slice(0, n);
|
|
152
|
+
const emitEvent = process.env.EAP_RAG_TRACE
|
|
153
|
+
? (type, p) => {
|
|
154
|
+
if (type === 'rag.round') {
|
|
155
|
+
const calls = (p['toolCalls'] ?? [])
|
|
156
|
+
.map((t) => `${t.name}(${JSON.stringify(t.arguments)})`).join(' ');
|
|
157
|
+
trace(`[rag] 第${p['round']}轮: ${calls}`);
|
|
158
|
+
}
|
|
159
|
+
else if (type === 'rag.search') {
|
|
160
|
+
const head = p['kind'] === 'kb' ? `kb:${p['toolName']}` : `local:"${fmt(p['query'], 20)}"`;
|
|
161
|
+
trace(`[rag] search ${head} topK=${p['topK']} → hits=${p['hits']} ${p['durationMs']}ms${p['success'] ? '' : ` ✗${p['error']}`}${p['scope'] ? ` scope=${p['scope']}` : ''}`);
|
|
162
|
+
}
|
|
163
|
+
else if (type === 'rag.denoise') {
|
|
164
|
+
trace(`[rag] 降噪 候选${p['candidates']} → 保留${p['kept']}`);
|
|
165
|
+
for (const f of p['filtered'] ?? [])
|
|
166
|
+
trace(`[rag] 滤 ${fmt(f.rawId, 30)}(${fmt(f.reason, 30)})`);
|
|
167
|
+
}
|
|
168
|
+
else if (type === 'rag.rewrite') {
|
|
169
|
+
trace(`[rag] 空结果重写 "${fmt(p['from'], 20)}" → "${fmt(p['to'], 20)}"`);
|
|
170
|
+
}
|
|
171
|
+
else if (type === 'rag.finish') {
|
|
172
|
+
trace(`[rag] 收束: ${p['rounds']}轮 最终${p['docs']}条${p['empty'] ? '(空)' : ''}`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
: undefined;
|
|
176
|
+
// 预热:自动向量化开启时立即后台装配一次——调度器/授权热更新/入库日志不等到首次
|
|
177
|
+
// local_search 才启动(演示"先授权后提问"场景需要授权即生效)。失败静默,检索时重试。
|
|
178
|
+
if (process.env.EAP_RAG_AUTO_INGEST) {
|
|
179
|
+
void Promise.resolve(loadFn()).catch(() => undefined);
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
llmProvider,
|
|
183
|
+
retrievers: [new LazyLocalRetriever(loadFn)],
|
|
184
|
+
emitEvent,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
@@ -28,6 +28,19 @@ import { type AgentRuntime } from './agent-runtime.js';
|
|
|
28
28
|
import type { RuntimeStorageProfile } from './storage-profile.js';
|
|
29
29
|
import type { HitlResponse, ResumeHitlResult, SSEEvent } from './types.js';
|
|
30
30
|
import type { ILlmTurnLog } from '../debug/llm-turn-log.js';
|
|
31
|
+
import type { ExecutionInterceptors } from '../execution/interceptors.js';
|
|
32
|
+
import { LongTermMemoryService } from '../memory/long-term-memory.service.js';
|
|
33
|
+
export interface CreateDevRuntimeOptions {
|
|
34
|
+
interceptors?: ExecutionInterceptors;
|
|
35
|
+
compression?: {
|
|
36
|
+
enabled?: boolean;
|
|
37
|
+
persistCompressed?: boolean;
|
|
38
|
+
};
|
|
39
|
+
memory?: {
|
|
40
|
+
enabled?: boolean;
|
|
41
|
+
service?: LongTermMemoryService;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
31
44
|
/** createDevRuntime 返回值(CLI 嵌入用,可选字段后续扩展) */
|
|
32
45
|
export interface DevRuntime {
|
|
33
46
|
invokeOrchestrator: InvokeOrchestrator;
|
|
@@ -63,12 +76,15 @@ export interface DevRuntime {
|
|
|
63
76
|
llmTurnKind: 'file' | 'postgres';
|
|
64
77
|
foundationConfigured: boolean;
|
|
65
78
|
skillHotReload: boolean;
|
|
79
|
+
/** rag 节点依赖已注入(EAP_EMBED_API_KEY 显式配置时 true) */
|
|
80
|
+
ragEnabled: boolean;
|
|
66
81
|
};
|
|
67
82
|
}
|
|
68
83
|
/**
|
|
69
84
|
* 装配本地 dev 模式所需的全部 Runtime 依赖
|
|
70
85
|
*
|
|
71
86
|
* @returns DevRuntime(含 invokeOrchestrator / streamOrchestrator / 诊断摘要)
|
|
72
|
-
* @throws EAP_LLM_MODE=local
|
|
87
|
+
* @throws `EAP_LLM_MODE=local` 且解不出密钥
|
|
88
|
+
* @throws 已配 `FOUNDATION_SERVICE_URL` 且 `EAP_LLM_CONNECTIONS` 不是合法 JSON 对象
|
|
73
89
|
*/
|
|
74
|
-
export declare function createDevRuntime(): DevRuntime;
|
|
90
|
+
export declare function createDevRuntime(options?: CreateDevRuntimeOptions): DevRuntime;
|
|
@@ -25,24 +25,29 @@
|
|
|
25
25
|
*/
|
|
26
26
|
import { createDefaultLLMProvider } from '../providers/echo-llm-provider.js';
|
|
27
27
|
import { HttpLLMProvider } from '../providers/http-llm-provider.js';
|
|
28
|
-
import { createLocalLlmProvider, requireLocalLlmConnections } from '../providers/local-llm-provider.js';
|
|
28
|
+
import { createLocalLlmProvider, createOptionalLocalLlmProvider, requireLocalLlmConnections, } from '../providers/local-llm-provider.js';
|
|
29
29
|
import { RoutingLLMProvider } from '../providers/routing-llm-provider.js';
|
|
30
30
|
import { createToolExecutor } from '../tool/create-tool-executor.js';
|
|
31
31
|
import { DevToolExecutor } from '../tool/dev-tool-executor.js';
|
|
32
|
-
import { withHarnessPrimitives } from '../tool/harness-primitives.js';
|
|
32
|
+
import { captureOverlayJailOptions, withHarnessPrimitives } from '../tool/harness-primitives.js';
|
|
33
33
|
import { AllowAllGovernanceClient, HttpGovernanceClient, } from '../governance/index.js';
|
|
34
34
|
import { InvokeOrchestrator, StreamOrchestrator, SessionService, MessageService, SessionContextService, TaskService, LangGraphAdapter, HitlHandler, TokenBudgetService, TokenStatsService, TokenBudgetGuard, SessionBudgetChecker, createAgentRegistryClient, GraphLoader, } from '../index.js';
|
|
35
35
|
import { createAgentRuntime } from './agent-runtime.js';
|
|
36
36
|
import { assembleRuntimeStorage } from './storage-profile.js';
|
|
37
|
+
import { createDevRagNodeDeps } from './dev-rag-deps.js';
|
|
38
|
+
import { RagSearchToolExecutor } from '../graph/nodes/rag/index.js';
|
|
37
39
|
import { resolveSkillHotReload, watchPreinstallSkillRoot, watchSkillRoots } from '../registry/skill-tree.js';
|
|
38
40
|
import { RUNTIME_PACKAGE_VERSION } from '../common/runtime-package-version.js';
|
|
41
|
+
import { LongTermMemoryService } from '../memory/long-term-memory.service.js';
|
|
42
|
+
import { isRuntimeMemoryEnabled } from '../session/apply-session-memory.js';
|
|
39
43
|
/**
|
|
40
44
|
* 装配本地 dev 模式所需的全部 Runtime 依赖
|
|
41
45
|
*
|
|
42
46
|
* @returns DevRuntime(含 invokeOrchestrator / streamOrchestrator / 诊断摘要)
|
|
43
|
-
* @throws EAP_LLM_MODE=local
|
|
47
|
+
* @throws `EAP_LLM_MODE=local` 且解不出密钥
|
|
48
|
+
* @throws 已配 `FOUNDATION_SERVICE_URL` 且 `EAP_LLM_CONNECTIONS` 不是合法 JSON 对象
|
|
44
49
|
*/
|
|
45
|
-
export function createDevRuntime() {
|
|
50
|
+
export function createDevRuntime(options) {
|
|
46
51
|
const foundationUrl = process.env.FOUNDATION_SERVICE_URL ?? 'http://localhost:3100';
|
|
47
52
|
const foundationConfigured = Boolean(process.env.FOUNDATION_SERVICE_URL && process.env.FOUNDATION_SERVICE_URL.trim().length > 0);
|
|
48
53
|
const toolExecutionMode = (process.env.EAP_TOOL_EXECUTION_MODE ?? 'mcp').toLowerCase();
|
|
@@ -68,7 +73,12 @@ export function createDevRuntime() {
|
|
|
68
73
|
llmProviderKind = 'openai-http';
|
|
69
74
|
}
|
|
70
75
|
else if (foundationConfigured) {
|
|
71
|
-
|
|
76
|
+
const fallbackProvider = createOptionalLocalLlmProvider(turnLog);
|
|
77
|
+
llmProvider = new RoutingLLMProvider({
|
|
78
|
+
foundationUrl,
|
|
79
|
+
turnLog,
|
|
80
|
+
...(fallbackProvider ? { fallbackProvider } : {}),
|
|
81
|
+
});
|
|
72
82
|
llmProviderKind = 'routing';
|
|
73
83
|
}
|
|
74
84
|
else {
|
|
@@ -76,12 +86,14 @@ export function createDevRuntime() {
|
|
|
76
86
|
llmProviderKind = 'echo';
|
|
77
87
|
}
|
|
78
88
|
// ── Tool Executor(dev+mcp 直连,缺配置失败 → 通用路由)──
|
|
89
|
+
// overlay 必须在此处捕获:SDK createAgent 返回后会恢复 process.env。
|
|
90
|
+
const overlayJail = captureOverlayJailOptions();
|
|
79
91
|
const needsHarnessWrap = toolExecutionMode === 'mcp' && deploymentContext === 'dev';
|
|
80
92
|
const innerExecutor = toolExecutionMode === 'mcp' && deploymentContext === 'dev'
|
|
81
93
|
? new DevToolExecutor()
|
|
82
|
-
: createToolExecutor({ foundationUrl, deploymentContext });
|
|
94
|
+
: createToolExecutor({ foundationUrl, deploymentContext, jail: overlayJail });
|
|
83
95
|
const toolExecutor = needsHarnessWrap
|
|
84
|
-
? withHarnessPrimitives(innerExecutor)
|
|
96
|
+
? withHarnessPrimitives(innerExecutor, overlayJail)
|
|
85
97
|
: innerExecutor;
|
|
86
98
|
// ── Governance ──
|
|
87
99
|
const governanceClient = process.env.GOVERNANCE_DISABLED === '1' || !foundationConfigured
|
|
@@ -92,7 +104,35 @@ export function createDevRuntime() {
|
|
|
92
104
|
close: () => { },
|
|
93
105
|
heartbeat: () => { },
|
|
94
106
|
});
|
|
95
|
-
|
|
107
|
+
// rag:EAP_EMBED_API_KEY 显式配置才注入(retriever 惰性初始化,见 dev-rag-deps.ts)
|
|
108
|
+
const ragNodeDeps = createDevRagNodeDeps(llmProvider);
|
|
109
|
+
// 工具形态:RagSearchToolExecutor 装饰工具执行器——拦截 rag_search 跑 rag 内核
|
|
110
|
+
// (多轮检索/融合/降噪,与节点形态同一 runReactLoop),其余工具调用原样透传。
|
|
111
|
+
// EAP_RAG_SOURCES(JSON 数据源描述符数组,工具形态无 rag 节点时的检索面声明位):
|
|
112
|
+
// 会话勾选 ragSources 由此过滤;不配 = 内层工具表不圈定(由请求 loadedTools 决定)
|
|
113
|
+
const ragSourcesEnv = (() => {
|
|
114
|
+
const raw = process.env.EAP_RAG_SOURCES;
|
|
115
|
+
if (!raw)
|
|
116
|
+
return undefined;
|
|
117
|
+
try {
|
|
118
|
+
const parsed = JSON.parse(raw);
|
|
119
|
+
return Array.isArray(parsed) ? { sources: parsed } : undefined;
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
console.warn('[rag] EAP_RAG_SOURCES 不是合法 JSON 数组,忽略');
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
})();
|
|
126
|
+
const ragToolExecutor = ragNodeDeps
|
|
127
|
+
? new RagSearchToolExecutor(toolExecutor, ragNodeDeps, {
|
|
128
|
+
config: {
|
|
129
|
+
model: process.env.EAP_DEFAULT_MODEL ?? 'DeepSeek-V4-Flash',
|
|
130
|
+
...(ragSourcesEnv ? { retrievalSources: ragSourcesEnv } : {}),
|
|
131
|
+
},
|
|
132
|
+
})
|
|
133
|
+
: toolExecutor;
|
|
134
|
+
const graphEngine = new LangGraphAdapter(storage.checkpointSaver, llmProvider, ragToolExecutor, governanceClient, hitlHandler, ragNodeDeps, options?.interceptors);
|
|
135
|
+
graphEngine.bindOverlayExtraRoots(overlayJail.extraRoots);
|
|
96
136
|
// ── Session / Messages ──
|
|
97
137
|
const sessionService = new SessionService(storage.sessionRepository);
|
|
98
138
|
const messageService = new MessageService(storage.messageRepository);
|
|
@@ -137,6 +177,19 @@ export function createDevRuntime() {
|
|
|
137
177
|
})()
|
|
138
178
|
: () => { };
|
|
139
179
|
// ── Orchestrators ──
|
|
180
|
+
const sessionCompression = {
|
|
181
|
+
provider: llmProvider,
|
|
182
|
+
turnLog,
|
|
183
|
+
enabled: options?.compression?.enabled,
|
|
184
|
+
persistCompressed: options?.compression?.persistCompressed,
|
|
185
|
+
};
|
|
186
|
+
const sessionMemory = {
|
|
187
|
+
enabled: options?.memory?.enabled,
|
|
188
|
+
service: options?.memory?.service ??
|
|
189
|
+
(isRuntimeMemoryEnabled(options?.memory?.enabled)
|
|
190
|
+
? new LongTermMemoryService()
|
|
191
|
+
: undefined),
|
|
192
|
+
};
|
|
140
193
|
const invokeOrchestrator = new InvokeOrchestrator({
|
|
141
194
|
sessionContextService,
|
|
142
195
|
taskService,
|
|
@@ -147,6 +200,8 @@ export function createDevRuntime() {
|
|
|
147
200
|
messageService,
|
|
148
201
|
graphLoader,
|
|
149
202
|
checkpointSaver: storage.checkpointSaver,
|
|
203
|
+
sessionCompression,
|
|
204
|
+
sessionMemory,
|
|
150
205
|
});
|
|
151
206
|
const streamOrchestrator = new StreamOrchestrator({
|
|
152
207
|
sessionContextService,
|
|
@@ -158,6 +213,8 @@ export function createDevRuntime() {
|
|
|
158
213
|
messageService,
|
|
159
214
|
graphLoader,
|
|
160
215
|
checkpointSaver: storage.checkpointSaver,
|
|
216
|
+
sessionCompression,
|
|
217
|
+
sessionMemory,
|
|
161
218
|
});
|
|
162
219
|
const agentRuntime = createAgentRuntime({
|
|
163
220
|
invokeOrchestrator,
|
|
@@ -170,6 +227,8 @@ export function createDevRuntime() {
|
|
|
170
227
|
messageService,
|
|
171
228
|
sessionService,
|
|
172
229
|
turnLog,
|
|
230
|
+
sessionCompression,
|
|
231
|
+
sessionMemory,
|
|
173
232
|
});
|
|
174
233
|
return {
|
|
175
234
|
invokeOrchestrator,
|
|
@@ -199,6 +258,7 @@ export function createDevRuntime() {
|
|
|
199
258
|
llmTurnKind: storage.diagnostics.llmTurnKind,
|
|
200
259
|
foundationConfigured,
|
|
201
260
|
skillHotReload,
|
|
261
|
+
ragEnabled: ragNodeDeps !== undefined,
|
|
202
262
|
},
|
|
203
263
|
};
|
|
204
264
|
}
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { AgentRuntime, createAgentRuntime, type AgentRuntimeDeps, type ForkRelationRecord, type RecordForkRelation, type ConversationDetail, } from './agent-runtime.js';
|
|
2
2
|
export type { ExecuteParams, ExecuteResult, ForkParams, ForkOverrides, ForkResult, HitlResponse, ResumeHitlResult, SSEEvent, } from './types.js';
|
|
3
|
-
export { createDevRuntime, type DevRuntime, } from './dev-runtime.js';
|
|
3
|
+
export { createDevRuntime, type DevRuntime, type CreateDevRuntimeOptions, } from './dev-runtime.js';
|
|
4
4
|
export { assembleRuntimeStorage, resolveRuntimeStorageProfile, resolveDevStorageDirs, type RuntimeStorageProfile, type AssembleRuntimeStorageOptions, type AssembledRuntimeStorage, } from './storage-profile.js';
|
package/dist/runtime/types.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @see 04-runtime-core/design.md §1.5
|
|
8
8
|
*/
|
|
9
|
-
import type { ExecutionContext, InvokeConfig, ResumeHitlResult } from '@gt-fe/eap-contracts';
|
|
9
|
+
import type { ExecutionContext, InvokeConfig, ResumeHitlRequest, ResumeHitlResult } from '@gt-fe/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';
|
|
@@ -28,21 +28,22 @@ export interface ExecuteParams {
|
|
|
28
28
|
*/
|
|
29
29
|
traceId?: string;
|
|
30
30
|
config?: InvokeConfig;
|
|
31
|
+
/** 请求级检索范围(前端圈定已向量化文件/目录;rag 节点本地检索源生效) */
|
|
32
|
+
ragScope?: {
|
|
33
|
+
fileIds?: string[];
|
|
34
|
+
dirPaths?: string[];
|
|
35
|
+
};
|
|
36
|
+
/** 会话级数据源勾选(数据源 id 列表;缺省 = 预定义目录全部启用) */
|
|
37
|
+
ragSources?: string[];
|
|
31
38
|
}
|
|
32
39
|
/** 同步执行结果 */
|
|
33
40
|
export type ExecuteResult = InvokeResponseData;
|
|
34
41
|
/** HITL 恢复结果(与 @gt-fe/eap-contracts ResumeHitlResult 对齐) */
|
|
35
42
|
export type { ResumeHitlResult };
|
|
36
|
-
/** HITL
|
|
37
|
-
export interface HitlResponse {
|
|
43
|
+
/** HITL 用户响应(与 @gt-fe/eap-contracts ResumeHitlRequest 对齐;userId 必填) */
|
|
44
|
+
export interface HitlResponse extends ResumeHitlRequest {
|
|
38
45
|
choice: string;
|
|
39
46
|
userId: string;
|
|
40
|
-
executionContext?: ExecutionContext;
|
|
41
|
-
/**
|
|
42
|
-
* Checkpoint thread_id 提示(冷恢复)。
|
|
43
|
-
* Hosting 可从 tasks.output.hitlThreadId 注入;优先于 sessionId。
|
|
44
|
-
*/
|
|
45
|
-
threadId?: string;
|
|
46
47
|
}
|
|
47
48
|
/** Fork 入参:上层先发 taskId / traceId,Runtime 不再 createFlow */
|
|
48
49
|
export interface ForkParams {
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* execute/stream 装载历史后的压缩入口。默认关。
|
|
3
|
+
*
|
|
4
|
+
* C-1a 开关:options.enabled 或 EAP_RUNTIME_COMPRESSION=1
|
|
5
|
+
* C-1b 有窗口:用上一轮 llm_turns 的 used/window,不用字符估窗
|
|
6
|
+
* C-1c 无窗口:只按轮次上限,不按窗压
|
|
7
|
+
* C-1d 摘要只走 ILLMProvider;失败则不压缩
|
|
8
|
+
* C-1e 默认只改本轮内存历史;persistCompressed 时必须能写 compression record
|
|
9
|
+
* C-1f 流式路径在摘要前产出 session.compression.started,结束后产出 completed。
|
|
10
|
+
* 不新开「占用 ≥ 80% 再 compact」链;触发仍是 C-1b/c。
|
|
11
|
+
*/
|
|
12
|
+
import type { GraphMessage } from '../graph/contracts/executable-graph.js';
|
|
13
|
+
import type { ILLMProvider } from '../graph/nodes/llm-node.js';
|
|
14
|
+
import type { ILlmTurnLog } from '../debug/llm-turn-log.js';
|
|
15
|
+
import { type CompressionRecord } from '../memory/message-compression.service.js';
|
|
16
|
+
import type { ICompressionRepository } from '../memory/compression/compression.repository.js';
|
|
17
|
+
import type { SessionCompressionCompletedPayload, SessionCompressionReason, SessionCompressionStartedPayload } from '../sse/events/session-events.js';
|
|
18
|
+
export interface SessionCompressionOptions {
|
|
19
|
+
enabled?: boolean;
|
|
20
|
+
persistCompressed?: boolean;
|
|
21
|
+
provider?: ILLMProvider;
|
|
22
|
+
turnLog?: ILlmTurnLog;
|
|
23
|
+
compressionRepository?: ICompressionRepository;
|
|
24
|
+
maxRounds?: number;
|
|
25
|
+
preserveRecentRounds?: number;
|
|
26
|
+
/** 摘要模型;与图节点同一套:Agent `models.default`。不要传字符串 `default`。 */
|
|
27
|
+
summaryModel?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface RunSessionCompressionParams {
|
|
30
|
+
history: GraphMessage[];
|
|
31
|
+
sessionId: string;
|
|
32
|
+
userId?: string;
|
|
33
|
+
taskId?: string;
|
|
34
|
+
options?: SessionCompressionOptions;
|
|
35
|
+
env?: NodeJS.ProcessEnv;
|
|
36
|
+
}
|
|
37
|
+
export interface RunSessionCompressionResult {
|
|
38
|
+
messages: GraphMessage[];
|
|
39
|
+
compressed: boolean;
|
|
40
|
+
record?: CompressionRecord;
|
|
41
|
+
completed?: SessionCompressionCompletedPayload;
|
|
42
|
+
}
|
|
43
|
+
export interface SessionCompressionDecision {
|
|
44
|
+
needed: boolean;
|
|
45
|
+
originalMessageCount: number;
|
|
46
|
+
reason?: SessionCompressionReason;
|
|
47
|
+
used?: number;
|
|
48
|
+
window?: number;
|
|
49
|
+
percent?: number;
|
|
50
|
+
threshold?: number;
|
|
51
|
+
started?: SessionCompressionStartedPayload;
|
|
52
|
+
}
|
|
53
|
+
export type SessionCompressionStep = {
|
|
54
|
+
kind: 'started';
|
|
55
|
+
payload: SessionCompressionStartedPayload;
|
|
56
|
+
} | {
|
|
57
|
+
kind: 'completed';
|
|
58
|
+
payload: SessionCompressionCompletedPayload;
|
|
59
|
+
} | {
|
|
60
|
+
kind: 'history';
|
|
61
|
+
messages: GraphMessage[];
|
|
62
|
+
};
|
|
63
|
+
export declare function isRuntimeCompressionEnabled(explicit?: boolean, env?: NodeJS.ProcessEnv): boolean;
|
|
64
|
+
export declare function isRuntimeCompressionPersist(explicit?: boolean, env?: NodeJS.ProcessEnv): boolean;
|
|
65
|
+
export declare function formatCompressionStartedMessage(input: {
|
|
66
|
+
percent?: number;
|
|
67
|
+
reason: SessionCompressionReason;
|
|
68
|
+
threshold?: number;
|
|
69
|
+
}): string;
|
|
70
|
+
export declare function formatCompressionCompletedMessage(input: {
|
|
71
|
+
success: boolean;
|
|
72
|
+
originalMessageCount: number;
|
|
73
|
+
compressedMessageCount: number;
|
|
74
|
+
error?: string;
|
|
75
|
+
}): string;
|
|
76
|
+
export declare function applySessionCompression(params: RunSessionCompressionParams): Promise<GraphMessage[]>;
|
|
77
|
+
/** 未显式 summaryModel 时写入 Agent `models.default`。压缩未开则不解析。 */
|
|
78
|
+
export declare function withCompressionSummaryModel(options: SessionCompressionOptions | undefined, resolveDefaultModel: () => Promise<string | undefined>, env?: NodeJS.ProcessEnv): Promise<SessionCompressionOptions | undefined>;
|
|
79
|
+
/**
|
|
80
|
+
* 流式入口用:先产出 started,再跑摘要,再产出 completed,最后给出本轮历史。
|
|
81
|
+
* SDK `stream` 可在 started 之后才继续 next(),HTTP SSE 可立刻 emit。
|
|
82
|
+
*/
|
|
83
|
+
export declare function iterSessionCompression(params: RunSessionCompressionParams): AsyncGenerator<SessionCompressionStep>;
|
|
84
|
+
export declare function runSessionCompression(params: RunSessionCompressionParams): Promise<RunSessionCompressionResult>;
|
|
85
|
+
export declare function decideSessionCompression(params: RunSessionCompressionParams): Promise<SessionCompressionDecision>;
|