@gt-fe/eap-runtime 0.0.20 → 0.0.21
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 +3 -2
- package/dist/api/handlers/invoke.handler.d.ts +7 -0
- package/dist/api/handlers/invoke.handler.js +48 -9
- package/dist/api/handlers/stream.handler.d.ts +6 -0
- package/dist/api/handlers/stream.handler.js +56 -39
- package/dist/api/routes/agent.routes.d.ts +8 -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.adapter.d.ts +25 -11
- package/dist/graph/adapters/langgraph.adapter.js +142 -82
- package/dist/graph/adapters/skill-isolate.d.ts +17 -0
- package/dist/graph/adapters/skill-isolate.js +50 -0
- package/dist/graph/adapters/subgraph-compiler.d.ts +7 -2
- package/dist/graph/adapters/subgraph-compiler.js +68 -32
- package/dist/graph/contracts/executable-graph.d.ts +27 -5
- package/dist/graph/hitl/hitl-handler.js +2 -0
- 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 +162 -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 +1 -1
- package/dist/providers/index.js +1 -1
- package/dist/providers/routing-llm-provider.d.ts +5 -0
- package/dist/providers/routing-llm-provider.js +66 -1
- package/dist/runtime/agent-runtime.d.ts +5 -0
- package/dist/runtime/agent-runtime.js +86 -66
- 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 +16 -1
- package/dist/runtime/dev-runtime.js +59 -5
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/types.d.ts +10 -9
- package/dist/session/apply-session-compression.d.ts +81 -0
- package/dist/session/apply-session-compression.js +262 -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 +51 -0
- package/dist/session/persist-turn-messages.js +140 -3
- 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 +2 -0
- package/dist/token/record-task-token-usage.js +24 -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-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,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* rag_search — 工具封装入口(design-v2 §5.3「工具封装形态」开放形态之一)
|
|
3
|
+
*
|
|
4
|
+
* 主 Agent 的 llm 节点发 tool_calls: [rag_search(query)] → 本执行器拦截,
|
|
5
|
+
* 内部跑同一个 runReactLoop——内核同一,入口不同。query 已由主 LLM 结合
|
|
6
|
+
* 对话上下文整定(§5.4:工具封装入口拿到的已是整定过的查询,内核首轮
|
|
7
|
+
* 职责自动退化为直接检索,history 传空)。
|
|
8
|
+
*
|
|
9
|
+
* 装配(宿主三步):
|
|
10
|
+
* const ragSearch = new RagSearchToolExecutor(真实 executor, ragNodeDeps, ragConfig, registryTools);
|
|
11
|
+
* new LangGraphAdapter(checkpointer, llmProvider, ragSearch, ...); // 第 3 参
|
|
12
|
+
* loadedTools 里 merge ragSearchLoadedTool(); // 主 LLM 工具表可见
|
|
13
|
+
*
|
|
14
|
+
* 防递归:rag_search 永不进入内层工具表——config.tools 显式圈定时自动剔除
|
|
15
|
+
* rag_search 自身;未圈定时内层工具表退化为 local_search + rag_finish
|
|
16
|
+
* (registryTools 不传即无注册工具),杜绝套娃。
|
|
17
|
+
*/
|
|
18
|
+
import type { IToolExecutor, ToolCallRequest, ToolCallResult } from '../../../tool/tool-executor.interface.js';
|
|
19
|
+
import type { ToolOrchestrator } from '../../../tool/tool-orchestrator.js';
|
|
20
|
+
import type { LoadedToolMap, LoadedToolDefinition } from '../../../tool/loaded-tool-definition.js';
|
|
21
|
+
import type { RagNodeConfig, RagNodeDeps } from './types.js';
|
|
22
|
+
export declare const RAG_SEARCH_TOOL_NAME = "rag_search";
|
|
23
|
+
/** 合成 loadedTools 条目:主 agent 的 llm 节点工具表由此看到 rag_search */
|
|
24
|
+
export declare function ragSearchLoadedTool(): LoadedToolDefinition;
|
|
25
|
+
export interface RagSearchToolOptions {
|
|
26
|
+
/** rag 内核配置(totalK/quota/maxIterations/nearDupThreshold…) */
|
|
27
|
+
config?: RagNodeConfig;
|
|
28
|
+
/**
|
|
29
|
+
* 注册表快照:config.tools 显式圈定注册工具源(如 kb-search)时必传
|
|
30
|
+
* (内层路 B 路由元数据来源);未传时内层工具表 = local_search + rag_finish。
|
|
31
|
+
*/
|
|
32
|
+
registryTools?: LoadedToolMap;
|
|
33
|
+
}
|
|
34
|
+
export declare class RagSearchToolExecutor implements IToolExecutor {
|
|
35
|
+
private readonly inner;
|
|
36
|
+
private readonly deps;
|
|
37
|
+
private readonly config;
|
|
38
|
+
private readonly registryTools;
|
|
39
|
+
/** 装配期检索面的门禁映射(请求带图声明时按请求重建) */
|
|
40
|
+
private readonly sourceIdsByTool;
|
|
41
|
+
constructor(inner: IToolExecutor, deps: RagNodeDeps, options?: RagSearchToolOptions);
|
|
42
|
+
/** adapter 注入的编排器(节点形态同款回退链:deps 显式 > adapter 注入 > inner 直执) */
|
|
43
|
+
private attachedOrchestrator?;
|
|
44
|
+
/** 宿主装配(LangGraphAdapter)注入图级 ToolOrchestrator——kb 派发走与 tool 节点同一编排 */
|
|
45
|
+
attachToolOrchestrator(orchestrator: ToolOrchestrator): void;
|
|
46
|
+
private resolveOrchestrator;
|
|
47
|
+
execute(req: ToolCallRequest): Promise<ToolCallResult>;
|
|
48
|
+
}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* rag_search — 工具封装入口(design-v2 §5.3「工具封装形态」开放形态之一)
|
|
3
|
+
*
|
|
4
|
+
* 主 Agent 的 llm 节点发 tool_calls: [rag_search(query)] → 本执行器拦截,
|
|
5
|
+
* 内部跑同一个 runReactLoop——内核同一,入口不同。query 已由主 LLM 结合
|
|
6
|
+
* 对话上下文整定(§5.4:工具封装入口拿到的已是整定过的查询,内核首轮
|
|
7
|
+
* 职责自动退化为直接检索,history 传空)。
|
|
8
|
+
*
|
|
9
|
+
* 装配(宿主三步):
|
|
10
|
+
* const ragSearch = new RagSearchToolExecutor(真实 executor, ragNodeDeps, ragConfig, registryTools);
|
|
11
|
+
* new LangGraphAdapter(checkpointer, llmProvider, ragSearch, ...); // 第 3 参
|
|
12
|
+
* loadedTools 里 merge ragSearchLoadedTool(); // 主 LLM 工具表可见
|
|
13
|
+
*
|
|
14
|
+
* 防递归:rag_search 永不进入内层工具表——config.tools 显式圈定时自动剔除
|
|
15
|
+
* rag_search 自身;未圈定时内层工具表退化为 local_search + rag_finish
|
|
16
|
+
* (registryTools 不传即无注册工具),杜绝套娃。
|
|
17
|
+
*/
|
|
18
|
+
import { buildRagTools, resolveRagSources, mergeLocalDirs, sourceToolName } from './tools.js';
|
|
19
|
+
import { runReactLoop } from './react-loop.js';
|
|
20
|
+
export const RAG_SEARCH_TOOL_NAME = 'rag_search';
|
|
21
|
+
/** 合成 loadedTools 条目:主 agent 的 llm 节点工具表由此看到 rag_search */
|
|
22
|
+
export function ragSearchLoadedTool() {
|
|
23
|
+
return {
|
|
24
|
+
toolId: 'tool-rag-search',
|
|
25
|
+
name: RAG_SEARCH_TOOL_NAME,
|
|
26
|
+
manifest: {
|
|
27
|
+
id: 'tool-rag-search',
|
|
28
|
+
name: RAG_SEARCH_TOOL_NAME,
|
|
29
|
+
version: '1.0.0',
|
|
30
|
+
// http/server:无论 server/desktop 部署都锁定 httpExecutor 路径(装饰器位置),
|
|
31
|
+
// 避免被 local 安装分流绕过拦截
|
|
32
|
+
type: 'http',
|
|
33
|
+
toolRuntime: 'server',
|
|
34
|
+
dataScope: 'global',
|
|
35
|
+
description: '检索企业知识库与本地文档,返回压缩后的高相关证据上下文(内部运行 RAG 检索子智能体)。',
|
|
36
|
+
},
|
|
37
|
+
inputSchema: {
|
|
38
|
+
type: 'object',
|
|
39
|
+
properties: {
|
|
40
|
+
query: { type: 'string', description: '自包含的检索查询' },
|
|
41
|
+
topK: { type: 'number', description: '融合后返回条数上限(可选)' },
|
|
42
|
+
},
|
|
43
|
+
required: ['query'],
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 工具名 → 数据源 id 列表(会话勾选门禁用)——从检索面声明构建。
|
|
49
|
+
* 解析序必须与 resolveRagSources 一致(sources 优先,无 sources 再看
|
|
50
|
+
* retrievalTools/tools):只遍历 sources 会让 legacy 声明位不进门禁映射,
|
|
51
|
+
* 直调放行而内层按 ragSources 过滤,同图两路口径分裂。legacy 字符串条目的
|
|
52
|
+
* id 即工具名本身——映射为 {工具名:[工具名]},勾选该名才放行。
|
|
53
|
+
*/
|
|
54
|
+
function buildSourceIdsByTool(config) {
|
|
55
|
+
const map = new Map();
|
|
56
|
+
const rs = config.retrievalSources;
|
|
57
|
+
const entries = rs?.sources
|
|
58
|
+
? rs.sources.map((e) => (typeof e === 'string' ? { type: 'external', id: e } : e))
|
|
59
|
+
: ((rs?.retrievalTools ?? config.tools)?.map((n) => ({ type: 'external', id: n })) ?? []);
|
|
60
|
+
for (const e of entries) {
|
|
61
|
+
const tool = sourceToolName(e);
|
|
62
|
+
if (!tool || tool === RAG_SEARCH_TOOL_NAME)
|
|
63
|
+
continue;
|
|
64
|
+
const ids = map.get(tool) ?? [];
|
|
65
|
+
ids.push(e.id);
|
|
66
|
+
map.set(tool, ids);
|
|
67
|
+
}
|
|
68
|
+
return map;
|
|
69
|
+
}
|
|
70
|
+
export class RagSearchToolExecutor {
|
|
71
|
+
inner;
|
|
72
|
+
deps;
|
|
73
|
+
config;
|
|
74
|
+
registryTools;
|
|
75
|
+
/** 装配期检索面的门禁映射(请求带图声明时按请求重建) */
|
|
76
|
+
sourceIdsByTool;
|
|
77
|
+
constructor(inner, deps, options = {}) {
|
|
78
|
+
this.inner = inner;
|
|
79
|
+
this.deps = deps;
|
|
80
|
+
// 防递归前置:解析到 rag_search 自身的源条目剔除,描述符原样保留
|
|
81
|
+
// (三字段模型下字符串化会丢 source 资源目录);三种声明位按原位回写
|
|
82
|
+
const config = { ...options.config };
|
|
83
|
+
const rs = config.retrievalSources;
|
|
84
|
+
if (rs?.sources) {
|
|
85
|
+
config.retrievalSources = {
|
|
86
|
+
...rs,
|
|
87
|
+
sources: rs.sources.filter((e) => sourceToolName(typeof e === 'string' ? { type: 'external', id: e } : e) !== RAG_SEARCH_TOOL_NAME),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
else if (rs?.retrievalTools) {
|
|
91
|
+
config.retrievalSources = { ...rs, retrievalTools: rs.retrievalTools.filter((n) => n !== RAG_SEARCH_TOOL_NAME) };
|
|
92
|
+
}
|
|
93
|
+
else if (config.tools) {
|
|
94
|
+
config.tools = config.tools.filter((n) => n !== RAG_SEARCH_TOOL_NAME);
|
|
95
|
+
}
|
|
96
|
+
this.config = config;
|
|
97
|
+
this.registryTools = options.registryTools;
|
|
98
|
+
this.sourceIdsByTool = buildSourceIdsByTool(config);
|
|
99
|
+
}
|
|
100
|
+
/** adapter 注入的编排器(节点形态同款回退链:deps 显式 > adapter 注入 > inner 直执) */
|
|
101
|
+
attachedOrchestrator;
|
|
102
|
+
/** 宿主装配(LangGraphAdapter)注入图级 ToolOrchestrator——kb 派发走与 tool 节点同一编排 */
|
|
103
|
+
attachToolOrchestrator(orchestrator) {
|
|
104
|
+
if (!this.deps.toolOrchestrator)
|
|
105
|
+
this.attachedOrchestrator = orchestrator;
|
|
106
|
+
}
|
|
107
|
+
resolveOrchestrator() {
|
|
108
|
+
if (this.deps.toolOrchestrator)
|
|
109
|
+
return this.deps.toolOrchestrator;
|
|
110
|
+
if (this.attachedOrchestrator)
|
|
111
|
+
return this.attachedOrchestrator;
|
|
112
|
+
// 兜底:kb 调用直经 inner 执行器(与 tool 节点同一条执行链,缺省编排层记账)
|
|
113
|
+
this.attachedOrchestrator = {
|
|
114
|
+
executeAll: async (reqs) => Promise.all(reqs.map(async (r) => {
|
|
115
|
+
try {
|
|
116
|
+
return await this.inner.execute(r);
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
return {
|
|
120
|
+
toolCallId: r.toolCallId,
|
|
121
|
+
toolName: r.toolName,
|
|
122
|
+
content: '',
|
|
123
|
+
success: false,
|
|
124
|
+
error: err instanceof Error ? err.message : String(err),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
})),
|
|
128
|
+
};
|
|
129
|
+
return this.attachedOrchestrator;
|
|
130
|
+
}
|
|
131
|
+
async execute(req) {
|
|
132
|
+
// 图声明的检索面(tool 节点 config.retrievalSources)覆盖装配期配置——图即真相;
|
|
133
|
+
// 图声明的 totalK(config.totalK)同为该请求缺省(调用级 topK 参数在下方仍可覆盖)
|
|
134
|
+
const faceConfig = {
|
|
135
|
+
...this.config,
|
|
136
|
+
...(req.ragSourcesConfig ? { retrievalSources: req.ragSourcesConfig } : {}),
|
|
137
|
+
...(req.ragTotalK !== undefined ? { totalK: req.ragTotalK } : {}),
|
|
138
|
+
};
|
|
139
|
+
const gateMap = req.ragSourcesConfig ? buildSourceIdsByTool(faceConfig) : this.sourceIdsByTool;
|
|
140
|
+
if (req.toolName !== RAG_SEARCH_TOOL_NAME) {
|
|
141
|
+
// 会话勾选激活时,目录内工具按勾选放行(主 LLM 直调与 rag_search 内层同规则):
|
|
142
|
+
// 一型多源(同工具多资源)任一 id 勾选即放行;目录外工具不受影响
|
|
143
|
+
if (req.ragSources !== undefined) {
|
|
144
|
+
const ids = gateMap.get(req.toolName);
|
|
145
|
+
if (ids && !ids.some((id) => req.ragSources?.includes(id))) {
|
|
146
|
+
// 失败返回必须带 error:上层失败时丢弃 content 只读 error,缺 error 会被渲染成 unknown error
|
|
147
|
+
return {
|
|
148
|
+
toolCallId: req.toolCallId,
|
|
149
|
+
toolName: req.toolName,
|
|
150
|
+
content: `[Tool Error] 数据源(${ids.join('、')})本次会话未勾选启用(ragSources),如需使用请在面板勾选该数据源`,
|
|
151
|
+
success: false,
|
|
152
|
+
error: `数据源(${ids.join('、')})本次会话未勾选启用(ragSources),如需使用请在面板勾选该数据源`,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return this.inner.execute(req);
|
|
157
|
+
}
|
|
158
|
+
const query = String(req.arguments['query'] ?? '');
|
|
159
|
+
if (!query.trim()) {
|
|
160
|
+
return {
|
|
161
|
+
toolCallId: req.toolCallId,
|
|
162
|
+
toolName: req.toolName,
|
|
163
|
+
content: '[Tool Error] rag_search 缺少必填参数 query',
|
|
164
|
+
success: false,
|
|
165
|
+
error: 'rag_search 缺少必填参数 query',
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
const topK = typeof req.arguments['topK'] === 'number' ? req.arguments['topK'] : undefined;
|
|
169
|
+
const config = topK !== undefined ? { ...faceConfig, totalK: topK } : faceConfig;
|
|
170
|
+
// 会话级控制(tool 节点从 GraphState 转递,与节点形态同语义):
|
|
171
|
+
// 勾选按 id 过滤检索面(资源目录同步收窄);请求 ragScope 与 local-file
|
|
172
|
+
// 白名单合并(声明过但未勾 = fileIds:[] 显式关本地)
|
|
173
|
+
const { toolScope, sourceCatalog, hasLocal, hasCatalog, localDirs, localDirsAll } = resolveRagSources(faceConfig, req.ragSources);
|
|
174
|
+
// 图声明了 sources = 完整检索面:无 local-file 条目则本地源整体不可用(不进工具表)。
|
|
175
|
+
// 本地选择权与 RagNode 同规则:请求带 ragScope.dirPaths 时以声明全量面为交集基准
|
|
176
|
+
const localEnabled = hasCatalog ? hasLocal : true;
|
|
177
|
+
const ragScope = localEnabled
|
|
178
|
+
? mergeLocalDirs(hasLocal, req.ragScope?.dirPaths !== undefined ? localDirsAll : localDirs, req.ragScope)
|
|
179
|
+
: undefined;
|
|
180
|
+
// 内层工具表优先用本轮 loadedTools(请求级,含会话勾选后的完整注册面);
|
|
181
|
+
// 剥掉 rag_search 自身防递归;缺省回退构造期 registryTools 快照
|
|
182
|
+
const reqTools = req.loadedTools;
|
|
183
|
+
const innerTools = reqTools && RAG_SEARCH_TOOL_NAME in reqTools
|
|
184
|
+
? Object.fromEntries(Object.entries(reqTools).filter(([n]) => n !== RAG_SEARCH_TOOL_NAME))
|
|
185
|
+
: (reqTools ?? this.registryTools);
|
|
186
|
+
const { apiTools, kbToolNames, missingToolNames, excludedConfirmToolNames } = buildRagTools(config, innerTools, localEnabled ? this.deps.retrievers : undefined, { toolScope, sourceCatalog, localEnabled });
|
|
187
|
+
if (missingToolNames.length > 0 || excludedConfirmToolNames.length > 0) {
|
|
188
|
+
return {
|
|
189
|
+
toolCallId: req.toolCallId,
|
|
190
|
+
toolName: req.toolName,
|
|
191
|
+
content: `[Tool Error] rag_search 检索源 tools 引用了不可用工具: ${[
|
|
192
|
+
...missingToolNames,
|
|
193
|
+
...excludedConfirmToolNames,
|
|
194
|
+
].join(', ')}`,
|
|
195
|
+
success: false,
|
|
196
|
+
error: `rag_search 检索源 tools 引用了不可用工具: ${[...missingToolNames, ...excludedConfirmToolNames].join(', ')}`,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
// 已知限制(与图级工具派发的差异):tool 节点/llm 链路把 state.executionContext
|
|
200
|
+
// (含 delegationToken)透传给 ToolOrchestrator.executeAll/executeSingle,治理断言
|
|
201
|
+
// (assertToolPermission)可命中;工具形态的内层 kb 派发只能从 ToolCallRequest 取参,
|
|
202
|
+
// 而该结构无执行上下文转递位,此处未传 executionContext → orchestrator 因
|
|
203
|
+
// delegationToken 缺失跳过治理断言。后续 ToolCallRequest 增加执行上下文转递后此处透传。
|
|
204
|
+
const loop = await runReactLoop({
|
|
205
|
+
nodeId: `rag-search:${req.toolCallId}`,
|
|
206
|
+
query,
|
|
207
|
+
history: [], // 主 LLM 已整定 query,无需对话上下文(§5.4)
|
|
208
|
+
config,
|
|
209
|
+
apiTools,
|
|
210
|
+
kbToolNames,
|
|
211
|
+
llmProvider: this.deps.llmProvider,
|
|
212
|
+
toolOrchestrator: this.resolveOrchestrator(),
|
|
213
|
+
retrievers: this.deps.retrievers,
|
|
214
|
+
loadedTools: innerTools,
|
|
215
|
+
authContext: req.authContext ?? {},
|
|
216
|
+
userId: req.authContext?.userId ?? '',
|
|
217
|
+
ragScope,
|
|
218
|
+
emitEvent: this.deps.emitEvent,
|
|
219
|
+
});
|
|
220
|
+
return {
|
|
221
|
+
toolCallId: req.toolCallId,
|
|
222
|
+
toolName: req.toolName,
|
|
223
|
+
// 空结果是合法业务结果("查了,没查到"),不是执行失败:success 恒 true,
|
|
224
|
+
// 空手体现在 content 文案。此前 success:!loop.empty 且无 error 字段,会被
|
|
225
|
+
// tool-node 渲染成 "[Tool Error] unknown error",误导主 LLM 判定服务故障。
|
|
226
|
+
content: loop.contextText || `[rag] 未找到高相关结果(query: ${query})。可换个关键词重试,或确认目标内容已入库。`,
|
|
227
|
+
success: true,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* react-loop — RagNode 内部 ReAct 循环(纯逻辑,不依赖 LangGraph)
|
|
3
|
+
*
|
|
4
|
+
* 输入输出均为普通对象,可脱离图引擎单独单测。
|
|
5
|
+
* 循环:LLM 决策(原生 function-calling)→ 三路派发 → 累积 perSource →
|
|
6
|
+
* 达终止条件后 fuse + denoise(近重去重 + LLM 判定 + 句子抽取)→ 输出;
|
|
7
|
+
* 判定存活集为空且未重写过 → QUERY_REWRITE 重写 query 清空重查(仅一次,§5.4)。
|
|
8
|
+
* 空转换源反馈:上一轮零产出 / 产出全被滤除的工具,下一轮决策上下文注入换源提示
|
|
9
|
+
* (只进决策输入,不落消息历史与最终输出),配合 RAG_REACT 行为规则防同源反复重查。
|
|
10
|
+
* LLM 永远只"点名"(name + arguments),执行全在代码侧:
|
|
11
|
+
* 路 A local_search → 进程内直连 IRetriever(结构化 RetrievalDoc[],零转换)
|
|
12
|
+
* 路 B 注册工具 → ToolOrchestrator(权限 → 路由 → 执行器),字符串结果归一化
|
|
13
|
+
* 路 C 未知工具 → 错误 tool 消息回给 LLM(不中断循环)
|
|
14
|
+
*
|
|
15
|
+
* @see design-v2 §5.4 / §6
|
|
16
|
+
*/
|
|
17
|
+
import type { ILLMProvider, LLMToolDefinition } from '../llm-node.js';
|
|
18
|
+
import type { GraphMessage } from '../../contracts/executable-graph.js';
|
|
19
|
+
import type { AuthContext, ToolOrchestrator } from '../../../tool/tool-orchestrator.js';
|
|
20
|
+
import type { LoadedToolMap } from '../../../tool/loaded-tool-definition.js';
|
|
21
|
+
import type { ExecutionContext } from '@gt-fe/eap-contracts';
|
|
22
|
+
import type { ITraceCollector } from '../../../contracts/trace-collector.js';
|
|
23
|
+
import type { IRetriever, RagEventSink, RagNodeConfig, RagScope, RagTokenUsage } from './types.js';
|
|
24
|
+
export interface RagLoopInput {
|
|
25
|
+
nodeId: string;
|
|
26
|
+
query: string;
|
|
27
|
+
/** 对话上下文(首轮整定指代/省略用) */
|
|
28
|
+
history: GraphMessage[];
|
|
29
|
+
config: RagNodeConfig;
|
|
30
|
+
/** 壳已圈定好的工具表(①注册工具 + ②local_search + ③rag_finish) */
|
|
31
|
+
apiTools: LLMToolDefinition[];
|
|
32
|
+
kbToolNames: Set<string>;
|
|
33
|
+
llmProvider: ILLMProvider;
|
|
34
|
+
toolOrchestrator?: ToolOrchestrator;
|
|
35
|
+
retrievers?: IRetriever[];
|
|
36
|
+
loadedTools?: LoadedToolMap;
|
|
37
|
+
authContext: AuthContext;
|
|
38
|
+
executionContext?: ExecutionContext;
|
|
39
|
+
forceToolServer?: string[];
|
|
40
|
+
userId: string;
|
|
41
|
+
/** 请求级检索范围(前端圈定 fileIds/dirPaths 并集;缺省不限)——只作用于本地检索源 */
|
|
42
|
+
ragScope?: RagScope;
|
|
43
|
+
/** rag.* 事件出口(SSE 旁路,缺省静默;adapter 接线 streamSink) */
|
|
44
|
+
emitEvent?: RagEventSink;
|
|
45
|
+
/** Trace 采集器 + 执行流 ID(缺省不建 span,照 ToolNode 模式:resolveTraceId) */
|
|
46
|
+
traceCollector?: ITraceCollector;
|
|
47
|
+
traceId?: string;
|
|
48
|
+
}
|
|
49
|
+
export interface RagLoopOutput {
|
|
50
|
+
/** 降噪上下文(近重去重 + LLM 判定 + 句子抽取后的拼装结果) */
|
|
51
|
+
contextText: string;
|
|
52
|
+
/** 空手标识(检索全失败/全被滤,含重查后仍空) */
|
|
53
|
+
empty: boolean;
|
|
54
|
+
iterations: number;
|
|
55
|
+
tokenUsage: RagTokenUsage[];
|
|
56
|
+
}
|
|
57
|
+
export declare function runReactLoop(input: RagLoopInput): Promise<RagLoopOutput>;
|