@gt-fe/eap-runtime 0.0.19 → 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 +57 -24
- package/dist/api/handlers/stream.handler.d.ts +6 -0
- package/dist/api/handlers/stream.handler.js +59 -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/contracts/index.d.ts +1 -1
- package/dist/contracts/trace-collector.d.ts +16 -8
- 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 +26 -11
- package/dist/graph/adapters/langgraph.adapter.js +178 -83
- package/dist/graph/adapters/skill-entry-span.d.ts +37 -0
- package/dist/graph/adapters/skill-entry-span.js +78 -0
- package/dist/graph/adapters/skill-isolate.d.ts +17 -0
- package/dist/graph/adapters/skill-isolate.js +50 -0
- package/dist/graph/adapters/skill-read.d.ts +10 -0
- package/dist/graph/adapters/skill-read.js +33 -0
- package/dist/graph/adapters/subgraph-compiler.d.ts +7 -2
- package/dist/graph/adapters/subgraph-compiler.js +81 -35
- 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 +25 -1
- package/dist/graph/nodes/tool-node.js +193 -35
- package/dist/graph/skill-audit-recorder.d.ts +4 -4
- package/dist/graph/skill-audit-recorder.js +3 -3
- package/dist/graph/trace-span.d.ts +2 -9
- package/dist/graph/trace-span.js +1 -0
- package/dist/index.d.ts +3 -1
- 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 +105 -63
- 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/sse/trace-collector.d.ts +2 -9
- package/dist/token/index.d.ts +3 -0
- package/dist/token/index.js +2 -0
- package/dist/token/record-task-token-usage.d.ts +23 -0
- package/dist/token/record-task-token-usage.js +76 -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 +4 -2
- package/dist/token/token-stats.service.js +5 -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 +3 -2
- package/dist/tool/index.js +3 -2
- package/dist/tool/mcp-list.d.ts +12 -0
- package/dist/tool/mcp-list.js +15 -0
- 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
|
@@ -9,11 +9,13 @@
|
|
|
9
9
|
* @see design.md §1.4 ToolNode: LangGraph的ToolNode封装
|
|
10
10
|
* @see requirements.md Requirement 8 AC1, AC3, AC5
|
|
11
11
|
*/
|
|
12
|
+
import type { NodeRetryConfig } from '../contracts/executable-graph.js';
|
|
12
13
|
import type { AuthContext } from '../../tool/tool-executor.interface.js';
|
|
13
14
|
import type { ToolOrchestrator } from '../../tool/tool-orchestrator.js';
|
|
14
15
|
import type { ToolResultInjector } from '../../tool/tool-result-injector.js';
|
|
15
16
|
import type { SkillDirRef } from '../adapters/skill-read.js';
|
|
16
17
|
import type { HitlHandler } from '../hitl/hitl-handler.js';
|
|
18
|
+
import { type ExecutionInterceptors } from '../../execution/interceptors.js';
|
|
17
19
|
/**
|
|
18
20
|
* LangGraphState — LangGraph 内部状态(与 LLMNode 对齐)
|
|
19
21
|
*/
|
|
@@ -43,6 +45,14 @@ export interface ToolNodeProgress {
|
|
|
43
45
|
node?: string;
|
|
44
46
|
skillId?: string;
|
|
45
47
|
skillDirs?: SkillDirRef[];
|
|
48
|
+
/** 已在 Skill 子图内(state.skillSpanId);读 SKILL.md 不再发 skill.started */
|
|
49
|
+
inSkillSubgraph?: boolean;
|
|
50
|
+
skillSpace?: 'agent' | 'user' | 'local';
|
|
51
|
+
skillVersion?: string;
|
|
52
|
+
skillName?: string;
|
|
53
|
+
toolVersion?: string;
|
|
54
|
+
/** 本失败后是否还会再试。缺省 false */
|
|
55
|
+
willRetry?: boolean;
|
|
46
56
|
}
|
|
47
57
|
export declare class ToolNode {
|
|
48
58
|
private readonly orchestrator;
|
|
@@ -51,7 +61,20 @@ export declare class ToolNode {
|
|
|
51
61
|
private readonly onProgress?;
|
|
52
62
|
private readonly hitlHandler?;
|
|
53
63
|
private readonly nodeId?;
|
|
54
|
-
|
|
64
|
+
private readonly interceptors?;
|
|
65
|
+
/** 图声明的 rag 检索面(config.retrievalSources,工具形态声明位)——随请求转递给 rag_search 装饰器 */
|
|
66
|
+
private readonly ragSourcesConfig?;
|
|
67
|
+
/** 图声明的融合总条数(config.totalK,工具形态声明位)——同路转递 */
|
|
68
|
+
private readonly ragTotalK?;
|
|
69
|
+
/** 节点 `retry`;未设则只试一次 */
|
|
70
|
+
private readonly retry?;
|
|
71
|
+
constructor(orchestrator: ToolOrchestrator, injector: ToolResultInjector, defaultAuthContext: AuthContext, onProgress?: ((data: ToolNodeProgress) => void) | undefined, hitlHandler?: HitlHandler | undefined, nodeId?: string | undefined, interceptors?: ExecutionInterceptors | undefined,
|
|
72
|
+
/** 图声明的 rag 检索面(config.retrievalSources,工具形态声明位)——随请求转递给 rag_search 装饰器 */
|
|
73
|
+
ragSourcesConfig?: import("../nodes/rag/types.js").RagRetrievalSources | undefined,
|
|
74
|
+
/** 图声明的融合总条数(config.totalK,工具形态声明位)——同路转递 */
|
|
75
|
+
ragTotalK?: number | undefined,
|
|
76
|
+
/** 节点 `retry`;未设则只试一次 */
|
|
77
|
+
retry?: NodeRetryConfig | undefined);
|
|
55
78
|
/**
|
|
56
79
|
* execute — StateGraph 节点函数
|
|
57
80
|
*
|
|
@@ -65,6 +88,7 @@ export declare class ToolNode {
|
|
|
65
88
|
* 从 state 中提取 messages 数组
|
|
66
89
|
*/
|
|
67
90
|
private extractMessages;
|
|
91
|
+
private executeSingleWithRetry;
|
|
68
92
|
/**
|
|
69
93
|
* 从 messages 中找到最后一条 assistant 消息
|
|
70
94
|
*/
|
|
@@ -9,13 +9,19 @@
|
|
|
9
9
|
* @see design.md §1.4 ToolNode: LangGraph的ToolNode封装
|
|
10
10
|
* @see requirements.md Requirement 8 AC1, AC3, AC5
|
|
11
11
|
*/
|
|
12
|
+
import { AppError, ErrorCodes } from '@gt-fe/eap-contracts';
|
|
12
13
|
import { resolveJailFromState } from '../../tool/harness-primitives.js';
|
|
14
|
+
import { recordSkillEntrySpan, skillEntryInvocationFromTool, skillTraceIdentity } from '../adapters/skill-entry-span.js';
|
|
13
15
|
import { inferHarnessSkillDir } from '../../tool/skill-dir-infer.js';
|
|
14
16
|
import { isHitlDecision, unwrapHitlPaused } from '../hitl/hitl-handler.js';
|
|
15
17
|
import { ToolConfirmationInterceptor } from '../../tool/tool-confirmation.js';
|
|
16
18
|
import { resolveCheckpointThreadId } from '../../session/persist-turn-messages.js';
|
|
17
|
-
import {
|
|
19
|
+
import { toolTraceIdentity } from '../../tool/mcp-list.js';
|
|
18
20
|
import { resolveExecutionTrace, warnTraceSpanFailure, } from '../execution-trace-context.js';
|
|
21
|
+
import { emitRuntimeLog } from '../../common/logger.js';
|
|
22
|
+
import { decideBeforeTool, } from '../../execution/interceptors.js';
|
|
23
|
+
import { isRetryableToolFailure, resolveToolRetryConfig, sleepToolRetry, toolRetryDelayMs, } from '../../tool/tool-retry.js';
|
|
24
|
+
import { assertIsolatedSkillAllowsHitl, isIsolatedSkillState } from '../adapters/skill-isolate.js';
|
|
19
25
|
function skillDirsFromState(state) {
|
|
20
26
|
const defs = state['skillDefinitions'];
|
|
21
27
|
return Object.values(defs ?? {})
|
|
@@ -29,13 +35,27 @@ export class ToolNode {
|
|
|
29
35
|
onProgress;
|
|
30
36
|
hitlHandler;
|
|
31
37
|
nodeId;
|
|
32
|
-
|
|
38
|
+
interceptors;
|
|
39
|
+
ragSourcesConfig;
|
|
40
|
+
ragTotalK;
|
|
41
|
+
retry;
|
|
42
|
+
constructor(orchestrator, injector, defaultAuthContext, onProgress, hitlHandler, nodeId, interceptors,
|
|
43
|
+
/** 图声明的 rag 检索面(config.retrievalSources,工具形态声明位)——随请求转递给 rag_search 装饰器 */
|
|
44
|
+
ragSourcesConfig,
|
|
45
|
+
/** 图声明的融合总条数(config.totalK,工具形态声明位)——同路转递 */
|
|
46
|
+
ragTotalK,
|
|
47
|
+
/** 节点 `retry`;未设则只试一次 */
|
|
48
|
+
retry) {
|
|
33
49
|
this.orchestrator = orchestrator;
|
|
34
50
|
this.injector = injector;
|
|
35
51
|
this.defaultAuthContext = defaultAuthContext;
|
|
36
52
|
this.onProgress = onProgress;
|
|
37
53
|
this.hitlHandler = hitlHandler;
|
|
38
54
|
this.nodeId = nodeId;
|
|
55
|
+
this.interceptors = interceptors;
|
|
56
|
+
this.ragSourcesConfig = ragSourcesConfig;
|
|
57
|
+
this.ragTotalK = ragTotalK;
|
|
58
|
+
this.retry = retry;
|
|
39
59
|
}
|
|
40
60
|
/**
|
|
41
61
|
* execute — StateGraph 节点函数
|
|
@@ -99,6 +119,12 @@ export class ToolNode {
|
|
|
99
119
|
...(jail.workdir ? { jailWorkdir: jail.workdir } : {}),
|
|
100
120
|
...(jailExtraRoots.length > 0 ? { jailExtraRoots } : {}),
|
|
101
121
|
...(skillDir ? { skillDir } : {}),
|
|
122
|
+
// rag 会话级控制与工具表快照(rag_search 装饰器消费;普通工具执行器忽略)
|
|
123
|
+
...(state['ragSources'] ? { ragSources: state['ragSources'] } : {}),
|
|
124
|
+
...(state['ragScope'] ? { ragScope: state['ragScope'] } : {}),
|
|
125
|
+
...(this.ragSourcesConfig ? { ragSourcesConfig: this.ragSourcesConfig } : {}),
|
|
126
|
+
...(this.ragTotalK !== undefined ? { ragTotalK: this.ragTotalK } : {}),
|
|
127
|
+
...(loadedTools ? { loadedTools } : {}),
|
|
102
128
|
};
|
|
103
129
|
});
|
|
104
130
|
const executionContext = state['executionContext'];
|
|
@@ -109,22 +135,48 @@ export class ToolNode {
|
|
|
109
135
|
const skillId = typeof state['activatedSkill'] === 'string' && state['activatedSkill']
|
|
110
136
|
? state['activatedSkill']
|
|
111
137
|
: undefined;
|
|
138
|
+
const inSkillSubgraph = typeof state['skillSpanId'] === 'string' && Boolean(state['skillSpanId']);
|
|
112
139
|
const emitProgress = (data) => {
|
|
113
140
|
this.onProgress?.({
|
|
114
141
|
...data,
|
|
115
142
|
node: nodeId,
|
|
116
143
|
...(skillId ? { skillId } : {}),
|
|
117
144
|
...(skillDirs.length > 0 ? { skillDirs } : {}),
|
|
145
|
+
...(inSkillSubgraph ? { inSkillSubgraph: true } : {}),
|
|
118
146
|
});
|
|
119
147
|
};
|
|
148
|
+
// require_confirmation 工具走 HITL 拦截:改为顺序执行,thread_id 与 Checkpoint 对齐
|
|
149
|
+
const confirmationTools = new Set(Object.entries(loadedTools ?? {})
|
|
150
|
+
.filter(([, def]) => Boolean(def?.manifest.requireConfirmation))
|
|
151
|
+
.map(([name]) => name));
|
|
152
|
+
const needsHitl = Boolean(this.hitlHandler) &&
|
|
153
|
+
(requests.some((req) => confirmationTools.has(req.toolName)) ||
|
|
154
|
+
Boolean(this.interceptors?.beforeTool));
|
|
155
|
+
const resumingHitl = isHitlDecision(state['hitlChoice']);
|
|
156
|
+
const resumeToolSpanId = resumingHitl && typeof state['toolSpanId'] === 'string' && state['toolSpanId']
|
|
157
|
+
? state['toolSpanId']
|
|
158
|
+
: undefined;
|
|
159
|
+
const resumeToolCallId = typeof state['hitlToolCallId'] === 'string' && state['hitlToolCallId']
|
|
160
|
+
? state['hitlToolCallId']
|
|
161
|
+
: undefined;
|
|
162
|
+
const confirmationCount = requests.filter((req) => confirmationTools.has(req.toolName)).length;
|
|
120
163
|
// 5. 并行执行所有 Tool 调用(附 Trace span)
|
|
121
164
|
const spanIds = await Promise.all(requests.map(async (req) => {
|
|
165
|
+
const reusePausedSpan = Boolean(resumeToolSpanId) &&
|
|
166
|
+
((resumeToolCallId && req.toolCallId === resumeToolCallId) ||
|
|
167
|
+
(!resumeToolCallId &&
|
|
168
|
+
confirmationTools.has(req.toolName) &&
|
|
169
|
+
confirmationCount === 1));
|
|
170
|
+
if (reusePausedSpan) {
|
|
171
|
+
return resumeToolSpanId ?? null;
|
|
172
|
+
}
|
|
122
173
|
if (!traceCollector || !traceId)
|
|
123
174
|
return null;
|
|
124
175
|
try {
|
|
125
176
|
const parentNodeId = typeof state['skillSpanId'] === 'string' && state['skillSpanId']
|
|
126
177
|
? state['skillSpanId']
|
|
127
178
|
: undefined;
|
|
179
|
+
const identity = toolTraceIdentity(loadedTools?.[req.toolName], req.toolName);
|
|
128
180
|
return await traceCollector.createNode({
|
|
129
181
|
traceId,
|
|
130
182
|
name: req.toolName,
|
|
@@ -132,6 +184,7 @@ export class ToolNode {
|
|
|
132
184
|
parentNodeId,
|
|
133
185
|
toolRuntime: req.toolRuntime === 'both' ? 'both' : req.toolRuntime,
|
|
134
186
|
agentCode: agentCode || undefined,
|
|
187
|
+
...(identity.toolVersion ? { version: identity.toolVersion } : {}),
|
|
135
188
|
input: req.arguments,
|
|
136
189
|
metadata: {
|
|
137
190
|
toolCallId: req.toolCallId,
|
|
@@ -139,6 +192,7 @@ export class ToolNode {
|
|
|
139
192
|
taskId: req.taskId,
|
|
140
193
|
correlationId: req.correlationId,
|
|
141
194
|
skillId,
|
|
195
|
+
...(identity.toolset ? { toolset: identity.toolset } : {}),
|
|
142
196
|
},
|
|
143
197
|
});
|
|
144
198
|
}
|
|
@@ -147,21 +201,15 @@ export class ToolNode {
|
|
|
147
201
|
return null;
|
|
148
202
|
}
|
|
149
203
|
}));
|
|
150
|
-
// 并行执行,但各自独立计时(避免共用 startedAt 导致时长不准/看起来像“写死”)
|
|
151
|
-
// require_confirmation 工具走 HITL 拦截:改为顺序执行,thread_id 与 Checkpoint 对齐
|
|
152
|
-
const confirmationTools = new Set(Object.entries(loadedTools ?? {})
|
|
153
|
-
.filter(([, def]) => Boolean(def?.manifest.requireConfirmation))
|
|
154
|
-
.map(([name]) => name));
|
|
155
|
-
const needsHitl = Boolean(this.hitlHandler) &&
|
|
156
|
-
requests.some((req) => confirmationTools.has(req.toolName));
|
|
157
204
|
const runOne = async (req, i) => {
|
|
158
|
-
const
|
|
159
|
-
const
|
|
205
|
+
const toolIdentity = toolTraceIdentity(loadedTools?.[req.toolName], req.toolName);
|
|
206
|
+
const toolset = toolIdentity.toolset;
|
|
160
207
|
if (!resumingHitl) {
|
|
161
208
|
emitProgress({
|
|
162
209
|
toolCallId: req.toolCallId,
|
|
163
210
|
toolName: req.toolName,
|
|
164
211
|
...(toolset ? { toolset } : {}),
|
|
212
|
+
...(toolIdentity.toolVersion ? { toolVersion: toolIdentity.toolVersion } : {}),
|
|
165
213
|
status: 'started',
|
|
166
214
|
arguments: req.arguments,
|
|
167
215
|
});
|
|
@@ -169,43 +217,97 @@ export class ToolNode {
|
|
|
169
217
|
const startedAt = Date.now();
|
|
170
218
|
try {
|
|
171
219
|
let result;
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
toolSpanId: spanIds[i] ?? undefined,
|
|
183
|
-
skillSpanId: typeof state['skillSpanId'] === 'string' ? state['skillSpanId'] : undefined,
|
|
184
|
-
});
|
|
185
|
-
result =
|
|
186
|
-
confirmed ??
|
|
187
|
-
{
|
|
188
|
-
toolCallId: req.toolCallId,
|
|
189
|
-
toolName: req.toolName,
|
|
190
|
-
content: `用户拒绝执行工具 ${req.toolName}`,
|
|
191
|
-
success: false,
|
|
192
|
-
error: `用户拒绝执行工具 ${req.toolName}`,
|
|
193
|
-
errorCode: 'hitl_rejected',
|
|
194
|
-
};
|
|
220
|
+
const gate = await decideBeforeTool(this.interceptors?.beforeTool, req, executionContext);
|
|
221
|
+
if (gate.action === 'deny') {
|
|
222
|
+
result = {
|
|
223
|
+
toolCallId: req.toolCallId,
|
|
224
|
+
toolName: req.toolName,
|
|
225
|
+
content: '',
|
|
226
|
+
success: false,
|
|
227
|
+
error: gate.reason,
|
|
228
|
+
errorCode: 'interceptor_denied',
|
|
229
|
+
};
|
|
195
230
|
}
|
|
196
231
|
else {
|
|
197
|
-
|
|
232
|
+
const askHitl = gate.action === 'ask' || (needsHitl && confirmationTools.has(req.toolName));
|
|
233
|
+
if (askHitl && this.hitlHandler) {
|
|
234
|
+
// 隔离子图未按独立 HITL 线程设计;interrupt 前拒绝,避免写错父 Checkpoint。
|
|
235
|
+
if (!resumingHitl) {
|
|
236
|
+
assertIsolatedSkillAllowsHitl(state);
|
|
237
|
+
}
|
|
238
|
+
const confirmSet = new Set(confirmationTools);
|
|
239
|
+
if (gate.action === 'ask')
|
|
240
|
+
confirmSet.add(req.toolName);
|
|
241
|
+
const interceptor = new ToolConfirmationInterceptor(confirmSet, this.hitlHandler, {
|
|
242
|
+
execute: (r) => this.orchestrator.executeSingle(r, executionContext),
|
|
243
|
+
});
|
|
244
|
+
const graphState = this.toGraphState(state);
|
|
245
|
+
const threadId = resolveCheckpointThreadId({
|
|
246
|
+
sessionId: typeof state['sessionId'] === 'string' ? state['sessionId'] : undefined,
|
|
247
|
+
taskId: req.taskId,
|
|
248
|
+
});
|
|
249
|
+
const confirmed = await interceptor.executeWithConfirmation(req, graphState, req.taskId ?? String(state['taskId'] ?? req.toolCallId), threadId, {
|
|
250
|
+
toolSpanId: spanIds[i] ?? undefined,
|
|
251
|
+
skillSpanId: typeof state['skillSpanId'] === 'string' ? state['skillSpanId'] : undefined,
|
|
252
|
+
});
|
|
253
|
+
result =
|
|
254
|
+
confirmed ??
|
|
255
|
+
{
|
|
256
|
+
toolCallId: req.toolCallId,
|
|
257
|
+
toolName: req.toolName,
|
|
258
|
+
content: `用户拒绝执行工具 ${req.toolName}`,
|
|
259
|
+
success: false,
|
|
260
|
+
error: `用户拒绝执行工具 ${req.toolName}`,
|
|
261
|
+
errorCode: 'hitl_rejected',
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
else if (gate.action === 'ask') {
|
|
265
|
+
result = {
|
|
266
|
+
toolCallId: req.toolCallId,
|
|
267
|
+
toolName: req.toolName,
|
|
268
|
+
content: '',
|
|
269
|
+
success: false,
|
|
270
|
+
error: '需要人工确认',
|
|
271
|
+
errorCode: 'interceptor_ask',
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
result = await this.executeSingleWithRetry(req, executionContext, emitProgress, toolset, toolIdentity);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
try {
|
|
279
|
+
await this.interceptors?.afterTool?.(req, result);
|
|
280
|
+
}
|
|
281
|
+
catch (err) {
|
|
282
|
+
emitRuntimeLog('warn', 'runtime.intercept', 'afterTool failed', {
|
|
283
|
+
event: 'runtime.intercept.after_tool_failed',
|
|
284
|
+
toolName: req.toolName,
|
|
285
|
+
error: err instanceof Error ? err.message : String(err),
|
|
286
|
+
});
|
|
198
287
|
}
|
|
199
288
|
const executionTime = Date.now() - startedAt;
|
|
200
289
|
if (result.success) {
|
|
290
|
+
const catalog = skillEntryInvocationFromTool({
|
|
291
|
+
toolName: req.toolName,
|
|
292
|
+
arguments: req.arguments,
|
|
293
|
+
skillDirs,
|
|
294
|
+
alreadyInSkillSpan: inSkillSubgraph,
|
|
295
|
+
});
|
|
296
|
+
const skillIdentity = catalog
|
|
297
|
+
? skillTraceIdentity(state, catalog.skillId, catalog.path)
|
|
298
|
+
: undefined;
|
|
201
299
|
emitProgress({
|
|
202
300
|
toolCallId: result.toolCallId,
|
|
203
301
|
toolName: result.toolName,
|
|
204
302
|
...(toolset ? { toolset } : {}),
|
|
303
|
+
...(toolIdentity.toolVersion ? { toolVersion: toolIdentity.toolVersion } : {}),
|
|
205
304
|
status: 'completed',
|
|
206
305
|
arguments: req.arguments,
|
|
207
306
|
content: result.content,
|
|
208
307
|
executionTime,
|
|
308
|
+
...(skillIdentity?.skillSpace ? { skillSpace: skillIdentity.skillSpace } : {}),
|
|
309
|
+
...(skillIdentity?.skillVersion ? { skillVersion: skillIdentity.skillVersion } : {}),
|
|
310
|
+
...(skillIdentity?.skillName ? { skillName: skillIdentity.skillName } : {}),
|
|
209
311
|
});
|
|
210
312
|
}
|
|
211
313
|
else {
|
|
@@ -213,6 +315,7 @@ export class ToolNode {
|
|
|
213
315
|
toolCallId: result.toolCallId,
|
|
214
316
|
toolName: result.toolName,
|
|
215
317
|
...(toolset ? { toolset } : {}),
|
|
318
|
+
...(toolIdentity.toolVersion ? { toolVersion: toolIdentity.toolVersion } : {}),
|
|
216
319
|
status: 'error',
|
|
217
320
|
arguments: req.arguments,
|
|
218
321
|
error: result.error ?? 'unknown error',
|
|
@@ -232,6 +335,13 @@ export class ToolNode {
|
|
|
232
335
|
warnTraceSpanFailure('completeNode', { type: 'tool', name: req.toolName, traceId, spanId: nodeId }, err);
|
|
233
336
|
}
|
|
234
337
|
}
|
|
338
|
+
if (result.success) {
|
|
339
|
+
await recordSkillEntrySpan(state, {
|
|
340
|
+
toolName: req.toolName,
|
|
341
|
+
arguments: req.arguments,
|
|
342
|
+
skillDirs,
|
|
343
|
+
});
|
|
344
|
+
}
|
|
235
345
|
return result;
|
|
236
346
|
}
|
|
237
347
|
catch (err) {
|
|
@@ -245,6 +355,23 @@ export class ToolNode {
|
|
|
245
355
|
(typeof state['skillSpanId'] === 'string' ? state['skillSpanId'] : undefined);
|
|
246
356
|
throw hitlPaused;
|
|
247
357
|
}
|
|
358
|
+
if (err instanceof AppError &&
|
|
359
|
+
err.code === ErrorCodes.GRAPH_EXECUTION_ERROR &&
|
|
360
|
+
isIsolatedSkillState(state)) {
|
|
361
|
+
const failedSpanId = spanIds[i];
|
|
362
|
+
if (traceCollector && failedSpanId) {
|
|
363
|
+
try {
|
|
364
|
+
await traceCollector.completeNode(failedSpanId, {
|
|
365
|
+
status: 'failed',
|
|
366
|
+
error: err.message,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
catch (completeErr) {
|
|
370
|
+
warnTraceSpanFailure('completeNode', { type: 'tool', name: req.toolName, traceId, spanId: failedSpanId }, completeErr);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
throw err;
|
|
374
|
+
}
|
|
248
375
|
const executionTime = Date.now() - startedAt;
|
|
249
376
|
const message = err instanceof Error ? err.message : String(err);
|
|
250
377
|
emitProgress({
|
|
@@ -333,6 +460,37 @@ export class ToolNode {
|
|
|
333
460
|
return { role: 'user', content: String(msg) };
|
|
334
461
|
});
|
|
335
462
|
}
|
|
463
|
+
async executeSingleWithRetry(req, executionContext, emitProgress, toolset, toolIdentity) {
|
|
464
|
+
const retry = resolveToolRetryConfig(this.retry);
|
|
465
|
+
const maxRetries = retry?.maxRetries ?? 0;
|
|
466
|
+
let last;
|
|
467
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
468
|
+
last = await this.orchestrator.executeSingle(req, executionContext);
|
|
469
|
+
if (last.success)
|
|
470
|
+
return last;
|
|
471
|
+
const willRetry = attempt < maxRetries && isRetryableToolFailure(last);
|
|
472
|
+
if (!willRetry)
|
|
473
|
+
return last;
|
|
474
|
+
emitProgress({
|
|
475
|
+
toolCallId: req.toolCallId,
|
|
476
|
+
toolName: req.toolName,
|
|
477
|
+
...(toolset ? { toolset } : {}),
|
|
478
|
+
...(toolIdentity.toolVersion ? { toolVersion: toolIdentity.toolVersion } : {}),
|
|
479
|
+
status: 'error',
|
|
480
|
+
arguments: req.arguments,
|
|
481
|
+
error: last.error ?? 'unknown error',
|
|
482
|
+
willRetry: true,
|
|
483
|
+
});
|
|
484
|
+
await sleepToolRetry(toolRetryDelayMs(attempt, retry.backoff));
|
|
485
|
+
}
|
|
486
|
+
return last ?? {
|
|
487
|
+
toolCallId: req.toolCallId,
|
|
488
|
+
toolName: req.toolName,
|
|
489
|
+
content: '',
|
|
490
|
+
success: false,
|
|
491
|
+
error: 'unknown error',
|
|
492
|
+
};
|
|
493
|
+
}
|
|
336
494
|
/**
|
|
337
495
|
* 从 messages 中找到最后一条 assistant 消息
|
|
338
496
|
*/
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* SkillAuditRecorder — Skill
|
|
2
|
+
* SkillAuditRecorder — 进程内 Skill 调用记录(调试用)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* 生产记录是 Trace 上的 skill Span(子图激活,或成功读 SKILL.md)。
|
|
5
|
+
* 本记录器默认内存、不对外查询;分析从 Span 聚合,不读这里。
|
|
6
6
|
*
|
|
7
7
|
* @see docs/status/module-status-and-backlog.md RT-6
|
|
8
8
|
*/
|
|
@@ -48,7 +48,7 @@ export interface SkillInvocationRecord {
|
|
|
48
48
|
/**
|
|
49
49
|
* ISkillAuditStore — Skill 审计存储接口
|
|
50
50
|
*
|
|
51
|
-
*
|
|
51
|
+
* 默认内存存储。生产不依赖本接口;Skill 调用记录以 Trace skill Span 为准。
|
|
52
52
|
*/
|
|
53
53
|
export interface ISkillAuditStore {
|
|
54
54
|
/** 写入审计记录 */
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* SkillAuditRecorder — Skill
|
|
2
|
+
* SkillAuditRecorder — 进程内 Skill 调用记录(调试用)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* 生产记录是 Trace 上的 skill Span(子图激活,或成功读 SKILL.md)。
|
|
5
|
+
* 本记录器默认内存、不对外查询;分析从 Span 聚合,不读这里。
|
|
6
6
|
*
|
|
7
7
|
* @see docs/status/module-status-and-backlog.md RT-6
|
|
8
8
|
*/
|
|
@@ -1,21 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Graph 节点 Span 辅助:createNode / completeNode 失败不挡主路径。
|
|
3
3
|
*/
|
|
4
|
-
import type { ITraceCollector, ExecutionNodeEvent } from '../contracts/trace-collector.js';
|
|
4
|
+
import type { ITraceCollector, ExecutionNodeEvent, CompleteNodeParams } from '../contracts/trace-collector.js';
|
|
5
5
|
export declare function startGraphSpan(state: Record<string, unknown>, input: {
|
|
6
6
|
name: string;
|
|
7
7
|
type: ExecutionNodeEvent['type'];
|
|
8
8
|
parentSpanId?: string;
|
|
9
9
|
extra?: Partial<Omit<ExecutionNodeEvent, 'traceId' | 'name' | 'type' | 'parentNodeId'>>;
|
|
10
10
|
}): Promise<string | undefined>;
|
|
11
|
-
export declare function completeGraphSpan(state: Record<string, unknown>, spanId: string | undefined, params:
|
|
12
|
-
status: 'completed' | 'failed';
|
|
13
|
-
output?: unknown;
|
|
14
|
-
error?: string;
|
|
15
|
-
inputTokens?: number;
|
|
16
|
-
outputTokens?: number;
|
|
17
|
-
totalTokens?: number;
|
|
18
|
-
}, collectorOverride?: ITraceCollector): Promise<void>;
|
|
11
|
+
export declare function completeGraphSpan(state: Record<string, unknown>, spanId: string | undefined, params: CompleteNodeParams, collectorOverride?: ITraceCollector): Promise<void>;
|
|
19
12
|
export declare function withGraphSpan(state: Record<string, unknown>, spec: {
|
|
20
13
|
name: string;
|
|
21
14
|
type: ExecutionNodeEvent['type'];
|
package/dist/graph/trace-span.js
CHANGED
|
@@ -57,6 +57,7 @@ export async function withGraphSpan(state, spec, run) {
|
|
|
57
57
|
totalTokens: usage?.inputTokens != null || usage?.outputTokens != null
|
|
58
58
|
? (usage?.inputTokens ?? 0) + (usage?.outputTokens ?? 0)
|
|
59
59
|
: undefined,
|
|
60
|
+
...(typeof usage?.model === 'string' && usage.model ? { model: usage.model } : {}),
|
|
60
61
|
});
|
|
61
62
|
return spanId ? { ...result, lastSpanId: spanId } : result;
|
|
62
63
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -15,10 +15,12 @@ export * from './memory/index.js';
|
|
|
15
15
|
export * from './common/index.js';
|
|
16
16
|
export * from './registry/index.js';
|
|
17
17
|
export * from './providers/index.js';
|
|
18
|
-
export type { ITraceCollector, TraceEvent, TraceSession, ExecutionFlowEvent, ExecutionNodeEvent, TraceLinkEvent, TraceLinkNodeEvent, } from './contracts/trace-collector.js';
|
|
18
|
+
export type { ITraceCollector, CompleteNodeParams, TraceEvent, TraceSession, ExecutionFlowEvent, ExecutionNodeEvent, TraceLinkEvent, TraceLinkNodeEvent, } from './contracts/trace-collector.js';
|
|
19
19
|
export type { ExecutionContext, CallerType, GovernancePermissionCheckParams, GovernancePermissionCheckResult, PermissionDenyReason, } from '@gt-fe/eap-contracts';
|
|
20
20
|
export { HttpGovernanceClient, AllowAllGovernanceClient, resolveExecutionContext, assertToolPermission, assertSkillPermission, permissionMessage, PermissionDeniedError, GovernanceUnavailableError, } from './governance/index.js';
|
|
21
21
|
export type { IGovernanceClient } from './governance/index.js';
|
|
22
|
+
export { decideBeforeModel, decideBeforeTool, } from './execution/index.js';
|
|
23
|
+
export type { AfterModelInterceptor, AfterToolInterceptor, BeforeModelInput, BeforeModelInterceptor, BeforeToolInterceptor, ExecutionInterceptors, ModelInterceptorDecision, ToolInterceptorDecision, } from './execution/index.js';
|
|
22
24
|
export { FileLlmTurnLog, InMemoryLlmTurnLog, createFileLlmTurnLogFromEnv, maskApiKey, resolveLlmTurnDir, } from './debug/llm-turn-log.js';
|
|
23
25
|
export { PostgresLlmTurnLog } from './debug/pg-llm-turn-log.js';
|
|
24
26
|
export type { ILlmTurnLog, LlmTurnRecord, LlmTurnIndexEntry, LlmTurnContext, LlmTurnLogKind, } from './debug/llm-turn-log.js';
|
package/dist/index.js
CHANGED
|
@@ -30,5 +30,6 @@ export * from './registry/index.js';
|
|
|
30
30
|
// LLM Providers
|
|
31
31
|
export * from './providers/index.js';
|
|
32
32
|
export { HttpGovernanceClient, AllowAllGovernanceClient, resolveExecutionContext, assertToolPermission, assertSkillPermission, permissionMessage, PermissionDeniedError, GovernanceUnavailableError, } from './governance/index.js';
|
|
33
|
+
export { decideBeforeModel, decideBeforeTool, } from './execution/index.js';
|
|
33
34
|
export { FileLlmTurnLog, InMemoryLlmTurnLog, createFileLlmTurnLogFromEnv, maskApiKey, resolveLlmTurnDir, } from './debug/llm-turn-log.js';
|
|
34
35
|
export { PostgresLlmTurnLog } from './debug/pg-llm-turn-log.js';
|
|
@@ -98,7 +98,7 @@ export type EmbeddingFunction = (text: string) => Promise<number[]>;
|
|
|
98
98
|
export declare class SemanticRetrievalService {
|
|
99
99
|
private readonly config;
|
|
100
100
|
private readonly vectorStore?;
|
|
101
|
-
private readonly embedding
|
|
101
|
+
private readonly embedding?;
|
|
102
102
|
constructor(config?: Partial<RetrievalConfig>, vectorStore?: IVectorStore, embedding?: EmbeddingFunction);
|
|
103
103
|
/**
|
|
104
104
|
* 检索相关记忆
|
|
@@ -20,21 +20,6 @@ export const DEFAULT_RETRIEVAL_CONFIG = {
|
|
|
20
20
|
keywordWeight: 0.3,
|
|
21
21
|
vectorWeight: 0.7,
|
|
22
22
|
};
|
|
23
|
-
/**
|
|
24
|
-
* 默认 Embedding 函数(占位)
|
|
25
|
-
*
|
|
26
|
-
* 实际使用时应注入真实的 Embedding 函数(如 OpenAI Embedding)。
|
|
27
|
-
*/
|
|
28
|
-
async function defaultEmbedding(text) {
|
|
29
|
-
// 简单的哈希向量(占位,实际应使用真实的 Embedding 模型)
|
|
30
|
-
const vector = new Array(128).fill(0);
|
|
31
|
-
for (let i = 0; i < text.length; i++) {
|
|
32
|
-
vector[i % 128] += text.charCodeAt(i) / 1000;
|
|
33
|
-
}
|
|
34
|
-
// 归一化
|
|
35
|
-
const norm = Math.sqrt(vector.reduce((sum, v) => sum + v * v, 0));
|
|
36
|
-
return vector.map((v) => v / norm);
|
|
37
|
-
}
|
|
38
23
|
// ─────────────────────────────────────────────
|
|
39
24
|
// 语义检索服务
|
|
40
25
|
// ─────────────────────────────────────────────
|
|
@@ -48,7 +33,7 @@ export class SemanticRetrievalService {
|
|
|
48
33
|
constructor(config, vectorStore, embedding) {
|
|
49
34
|
this.config = { ...DEFAULT_RETRIEVAL_CONFIG, ...config };
|
|
50
35
|
this.vectorStore = vectorStore;
|
|
51
|
-
this.embedding = embedding
|
|
36
|
+
this.embedding = embedding;
|
|
52
37
|
}
|
|
53
38
|
/**
|
|
54
39
|
* 检索相关记忆
|
|
@@ -106,11 +91,9 @@ export class SemanticRetrievalService {
|
|
|
106
91
|
* 基于向量相似度的检索。
|
|
107
92
|
*/
|
|
108
93
|
async vectorRetrieve(query, memories) {
|
|
109
|
-
if (!this.vectorStore) {
|
|
110
|
-
// 如果没有向量存储,回退到关键词检索
|
|
94
|
+
if (!this.vectorStore || !this.embedding) {
|
|
111
95
|
return this.keywordRetrieve(query, memories);
|
|
112
96
|
}
|
|
113
|
-
// 生成查询向量
|
|
114
97
|
const queryVector = await this.embedding(query);
|
|
115
98
|
// 查询相似向量
|
|
116
99
|
const vectorResults = await this.vectorStore.query(queryVector, this.config.limit, this.config.similarityThreshold);
|
|
@@ -183,12 +166,19 @@ export class SemanticRetrievalService {
|
|
|
183
166
|
'under', 'again', 'further', 'then', 'once',
|
|
184
167
|
]);
|
|
185
168
|
// 分词(简单按空格和标点分割)
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
.replace(/[^\w\u4e00-\u9fff]/g, ' ')
|
|
169
|
+
const cleaned = text.toLowerCase().replace(/[^\w\u4e00-\u9fff]/g, ' ');
|
|
170
|
+
const words = cleaned
|
|
189
171
|
.split(/\s+/)
|
|
190
172
|
.filter((word) => word.length > 1 && !stopWords.has(word));
|
|
191
|
-
|
|
173
|
+
const grams = [];
|
|
174
|
+
for (const word of words) {
|
|
175
|
+
if (/[\u4e00-\u9fff]/.test(word) && word.length > 2) {
|
|
176
|
+
for (let i = 0; i < word.length - 1; i++) {
|
|
177
|
+
grams.push(word.slice(i, i + 2));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return [...new Set([...words, ...grams])];
|
|
192
182
|
}
|
|
193
183
|
}
|
|
194
184
|
// ─────────────────────────────────────────────
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { EchoLLMProvider, createDefaultLLMProvider } from './echo-llm-provider.js';
|
|
2
2
|
export { HttpLLMProvider, DEFAULT_LLM_HTTP_TIMEOUT_MS, type HttpLLMProviderConfig } from './http-llm-provider.js';
|
|
3
|
-
export { RoutingLLMProvider, type RoutingLLMProviderConfig } from './routing-llm-provider.js';
|
|
3
|
+
export { RoutingLLMProvider, type RoutingLLMProviderConfig, assertFoundationModelsInvokeAllowsStream, isFoundationModelsInvokeEnabled, MODELS_INVOKE_STREAM_MESSAGE, } from './routing-llm-provider.js';
|
|
4
4
|
export { resolveLlmModelName, canOverrideGraphModel } from './resolve-llm-model.js';
|
|
5
5
|
export { createLocalLlmProvider, requireLocalLlmConnections, resolveLocalLlmConnection, parseLocalLlmConnectionRefs, hydrateLocalLlmConnections, LLM_CONNECTIONS_ENV, } from './local-llm-provider.js';
|
|
6
6
|
export type { LocalLlmConnection, LocalLlmConnectionRef, LocalLlmConnectionRefs, LocalLlmConnections, } from './local-llm-provider.js';
|
package/dist/providers/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { EchoLLMProvider, createDefaultLLMProvider } from './echo-llm-provider.js';
|
|
2
2
|
export { HttpLLMProvider, DEFAULT_LLM_HTTP_TIMEOUT_MS } from './http-llm-provider.js';
|
|
3
|
-
export { RoutingLLMProvider } from './routing-llm-provider.js';
|
|
3
|
+
export { RoutingLLMProvider, assertFoundationModelsInvokeAllowsStream, isFoundationModelsInvokeEnabled, MODELS_INVOKE_STREAM_MESSAGE, } from './routing-llm-provider.js';
|
|
4
4
|
export { resolveLlmModelName, canOverrideGraphModel } from './resolve-llm-model.js';
|
|
5
5
|
export { createLocalLlmProvider, requireLocalLlmConnections, resolveLocalLlmConnection, parseLocalLlmConnectionRefs, hydrateLocalLlmConnections, LLM_CONNECTIONS_ENV, } from './local-llm-provider.js';
|
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
import type { GraphMessage } from '../graph/contracts/executable-graph.js';
|
|
15
15
|
import type { ILLMProvider, LLMNodeConfig, LLMResponse, LLMChunk } from '../graph/nodes/llm-node.js';
|
|
16
16
|
import type { ILlmTurnLog } from '../debug/llm-turn-log.js';
|
|
17
|
+
export declare const MODELS_INVOKE_STREAM_MESSAGE = "EAP_RUNTIME_MODELS_INVOKE \u5B9E\u9A8C\u53E3\u53EA\u652F\u6301\u540C\u6B65 invoke\uFF08POST /models/invoke\uFF09\uFF0C\u4E0D\u652F\u6301 stream\u3002\u5173\u6389\u8BE5\u5F00\u5173\uFF0C\u6216\u6539\u8D70 Foundation /models/select + \u672C\u673A HTTP\u3002";
|
|
18
|
+
export declare function isFoundationModelsInvokeEnabled(env?: NodeJS.ProcessEnv): boolean;
|
|
19
|
+
/** `/models/invoke` 无真流式;开了该开关时 RoutingLLMProvider.stream 必须失败。 */
|
|
20
|
+
export declare function assertFoundationModelsInvokeAllowsStream(env?: NodeJS.ProcessEnv): void;
|
|
17
21
|
export interface RoutingLLMProviderConfig {
|
|
18
22
|
foundationUrl: string;
|
|
19
23
|
fallbackProvider?: ILLMProvider;
|
|
@@ -28,5 +32,6 @@ export declare class RoutingLLMProvider implements ILLMProvider {
|
|
|
28
32
|
stream(messages: GraphMessage[], config: LLMNodeConfig): AsyncIterableIterator<LLMChunk>;
|
|
29
33
|
private withCallDefaults;
|
|
30
34
|
private selectModel;
|
|
35
|
+
private useFoundationInvoke;
|
|
31
36
|
private createProviderForModel;
|
|
32
37
|
}
|