@gt-fe/eap-runtime 0.0.22 → 0.0.24
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/dist/api/handlers/invoke.handler.d.ts +4 -0
- package/dist/api/handlers/invoke.handler.js +38 -19
- package/dist/api/handlers/stream.handler.d.ts +4 -0
- package/dist/api/handlers/stream.handler.js +24 -15
- package/dist/api/routes/agent.routes.js +6 -5
- package/dist/checkpoint/checkpoint-ref-notify.js +1 -1
- package/dist/common/types.d.ts +6 -2
- package/dist/common/types.js +3 -1
- package/dist/graph/adapters/langgraph.adapter.d.ts +6 -4
- package/dist/graph/adapters/langgraph.adapter.js +103 -18
- package/dist/graph/contracts/executable-graph.d.ts +9 -0
- package/dist/graph/execution-trace-context.d.ts +4 -0
- package/dist/graph/execution-trace-context.js +3 -1
- package/dist/graph/nodes/rag/types.d.ts +4 -1
- package/dist/graph/nodes/tool-node.js +10 -1
- package/dist/providers/http-llm-provider.js +25 -0
- package/dist/registry/graph-loader.js +65 -9
- package/dist/runtime/agent-runtime.d.ts +3 -0
- package/dist/runtime/agent-runtime.js +95 -15
- package/dist/runtime/dev-runtime.js +9 -2
- package/dist/runtime/types.d.ts +1 -1
- package/dist/sse/events/response-events.d.ts +2 -2
- package/dist/sse/events/response-events.js +1 -1
- package/dist/task/contracts/task-manager.contract.d.ts +2 -0
- package/dist/task/index.d.ts +1 -0
- package/dist/task/index.js +1 -0
- package/dist/task/resolve-task-timeout.d.ts +6 -0
- package/dist/task/resolve-task-timeout.js +16 -0
- package/dist/task/task-timeout.d.ts +1 -1
- package/dist/task/task-timeout.js +3 -2
- package/dist/task/task.service.js +1 -0
- package/dist/tool/http-tool-executor.js +7 -3
- package/dist/tool/index.d.ts +2 -1
- package/dist/tool/index.js +2 -1
- package/dist/tool/loaded-tool-definition.d.ts +1 -1
- package/dist/tool/local-mcp-client.d.ts +1 -1
- package/dist/tool/local-mcp-client.js +2 -39
- package/dist/tool/local-tool-executor.js +32 -5
- package/dist/tool/mcp-list.d.ts +21 -0
- package/dist/tool/mcp-list.js +49 -3
- package/dist/tool/mcp-tool-executor.d.ts +1 -1
- package/dist/tool/mcp-tool-executor.js +58 -22
- package/dist/tool/model-visible-tool-content.d.ts +16 -0
- package/dist/tool/model-visible-tool-content.js +266 -0
- package/dist/tool/timeout.d.ts +5 -12
- package/dist/tool/timeout.js +12 -34
- package/dist/tool/tool-executor.interface.d.ts +7 -1
- package/dist/tool/tool-orchestrator.js +6 -1
- package/dist/tool/tool-result-injector.js +2 -1
- package/package.json +2 -2
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 模型可见 Tool 结果:MCP / Code 成功正文在写入 GraphState 前统一裁到最多 200 行,并写 recordCount / previewCount / truncated。
|
|
3
|
+
*
|
|
4
|
+
* 假设:模型看到的永远可能是预览;全量条数与是否裁过只在这一处写。
|
|
5
|
+
* 不按工具名分支。fileReference 路径仍由 format 阶段剔除,下载走 result.file。
|
|
6
|
+
*
|
|
7
|
+
* 预览行数按 DeepSeek V4 Pro(约 1M 上下文)估:单次工具结果要够看列和分布,
|
|
8
|
+
* 又不能看起来像全表。200 行约 3–8 万 token(视列宽);多轮 5–6 次查询仍远低于窗口。
|
|
9
|
+
* 50 行只够看样例。1000 行接近聚合工具自己的预览上限,模型容易拿来排名。
|
|
10
|
+
* 超宽表先按行裁,再按体积把行数压到整段 JSON 仍合法。
|
|
11
|
+
*/
|
|
12
|
+
export const MAX_MODEL_RESULT_ROWS = 200;
|
|
13
|
+
export const MAX_MODEL_CONTENT_CHARS = 64_000;
|
|
14
|
+
export const MAX_MODEL_RESULT_CHARS = 120_000;
|
|
15
|
+
const PRIMARY_ARRAY_KEYS = ['rows', 'data', 'records', 'result', 'dataset', 'items', 'results'];
|
|
16
|
+
const TEXT_CLIP_SUFFIX = '...[文本已截断]';
|
|
17
|
+
export function formatMcpOutput(result) {
|
|
18
|
+
const r = result;
|
|
19
|
+
const count = finiteCount(r?._meta?.recordCount) ?? finiteCount(r?._meta?.totalCount);
|
|
20
|
+
if (r?.structuredContent !== undefined) {
|
|
21
|
+
return JSON.stringify(attachCount(redactFileLocators(r.structuredContent), count));
|
|
22
|
+
}
|
|
23
|
+
const text = r?.content?.[0]?.text;
|
|
24
|
+
if (text) {
|
|
25
|
+
try {
|
|
26
|
+
return JSON.stringify(attachCount(redactFileLocators(JSON.parse(text)), count));
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
if (count == null)
|
|
30
|
+
return text;
|
|
31
|
+
return JSON.stringify({ recordCount: count, content: text });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return JSON.stringify(attachCount(redactFileLocators(result), count));
|
|
35
|
+
}
|
|
36
|
+
export function toModelVisibleToolContent(content) {
|
|
37
|
+
if (content === '')
|
|
38
|
+
return content;
|
|
39
|
+
const parsed = parseJson(content);
|
|
40
|
+
if (parsed === undefined) {
|
|
41
|
+
if (content.length <= MAX_MODEL_CONTENT_CHARS)
|
|
42
|
+
return content;
|
|
43
|
+
return `${content.slice(0, MAX_MODEL_CONTENT_CHARS)}${TEXT_CLIP_SUFFIX}`;
|
|
44
|
+
}
|
|
45
|
+
const clipped = clipParsed(parsed);
|
|
46
|
+
if (!clipped.needEnvelope)
|
|
47
|
+
return content;
|
|
48
|
+
let out = clipped.value;
|
|
49
|
+
if (isPlainObject(clipped.value)) {
|
|
50
|
+
out = {
|
|
51
|
+
...clipped.value,
|
|
52
|
+
recordCount: clipped.recordCount,
|
|
53
|
+
previewCount: clipped.previewCount,
|
|
54
|
+
truncated: clipped.truncated,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
else if (Array.isArray(clipped.value)) {
|
|
58
|
+
out = {
|
|
59
|
+
truncated: clipped.truncated,
|
|
60
|
+
recordCount: clipped.recordCount,
|
|
61
|
+
previewCount: clipped.previewCount,
|
|
62
|
+
data: clipped.value,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (typeof out === 'string') {
|
|
66
|
+
if (out.length <= MAX_MODEL_CONTENT_CHARS)
|
|
67
|
+
return JSON.stringify(out);
|
|
68
|
+
return JSON.stringify(`${out.slice(0, MAX_MODEL_CONTENT_CHARS)}${TEXT_CLIP_SUFFIX}`);
|
|
69
|
+
}
|
|
70
|
+
return stringifyWithinLimit(out, clipped.recordCount);
|
|
71
|
+
}
|
|
72
|
+
function clipParsed(value) {
|
|
73
|
+
if (Array.isArray(value)) {
|
|
74
|
+
const recordCount = value.length;
|
|
75
|
+
const clipped = value.length > MAX_MODEL_RESULT_ROWS;
|
|
76
|
+
const next = clipped ? value.slice(0, MAX_MODEL_RESULT_ROWS) : value;
|
|
77
|
+
return {
|
|
78
|
+
value: next,
|
|
79
|
+
needEnvelope: clipped,
|
|
80
|
+
recordCount,
|
|
81
|
+
previewCount: next.length,
|
|
82
|
+
truncated: clipped,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (isPlainObject(value)) {
|
|
86
|
+
const obj = value;
|
|
87
|
+
const next = {};
|
|
88
|
+
let didClip = false;
|
|
89
|
+
for (const [key, child] of Object.entries(obj)) {
|
|
90
|
+
if (typeof child === 'string' && child.length > MAX_MODEL_CONTENT_CHARS) {
|
|
91
|
+
next[key] = `${child.slice(0, MAX_MODEL_CONTENT_CHARS)}${TEXT_CLIP_SUFFIX}`;
|
|
92
|
+
didClip = true;
|
|
93
|
+
}
|
|
94
|
+
else if (Array.isArray(child) && isPrimaryArrayKey(key) && child.length > MAX_MODEL_RESULT_ROWS) {
|
|
95
|
+
next[key] = child.slice(0, MAX_MODEL_RESULT_ROWS);
|
|
96
|
+
didClip = true;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
next[key] = child;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const prePrimary = primaryArrayLength(obj);
|
|
103
|
+
const recordCount = finiteCount(obj.recordCount) ?? finiteCount(obj.rowCount) ?? prePrimary;
|
|
104
|
+
const previewCount = primaryArrayLength(next);
|
|
105
|
+
const truncated = didClip
|
|
106
|
+
|| obj.truncated === true
|
|
107
|
+
|| (recordCount != null && previewCount != null && previewCount < recordCount);
|
|
108
|
+
const needEnvelope = didClip
|
|
109
|
+
|| truncated
|
|
110
|
+
|| finiteCount(obj.recordCount) != null
|
|
111
|
+
|| finiteCount(obj.rowCount) != null;
|
|
112
|
+
return {
|
|
113
|
+
value: next,
|
|
114
|
+
needEnvelope,
|
|
115
|
+
recordCount,
|
|
116
|
+
previewCount,
|
|
117
|
+
truncated,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
if (typeof value === 'string' && value.length > MAX_MODEL_CONTENT_CHARS) {
|
|
121
|
+
return {
|
|
122
|
+
value: `${value.slice(0, MAX_MODEL_CONTENT_CHARS)}${TEXT_CLIP_SUFFIX}`,
|
|
123
|
+
needEnvelope: false,
|
|
124
|
+
truncated: true,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
return { value, needEnvelope: false, truncated: false };
|
|
128
|
+
}
|
|
129
|
+
function stringifyWithinLimit(value, recordCount) {
|
|
130
|
+
let current = value;
|
|
131
|
+
let json = JSON.stringify(current);
|
|
132
|
+
if (json.length <= MAX_MODEL_RESULT_CHARS)
|
|
133
|
+
return json;
|
|
134
|
+
if (isPlainObject(current)) {
|
|
135
|
+
current = shrinkPrimaryArray(current, recordCount);
|
|
136
|
+
json = JSON.stringify(current);
|
|
137
|
+
if (json.length <= MAX_MODEL_RESULT_CHARS)
|
|
138
|
+
return json;
|
|
139
|
+
const shortened = clipLongStrings(current, 256);
|
|
140
|
+
json = JSON.stringify(shortened);
|
|
141
|
+
if (json.length <= MAX_MODEL_RESULT_CHARS)
|
|
142
|
+
return json;
|
|
143
|
+
const count = isPlainObject(shortened)
|
|
144
|
+
? (finiteCount(shortened.recordCount) ?? recordCount)
|
|
145
|
+
: recordCount;
|
|
146
|
+
json = JSON.stringify({
|
|
147
|
+
truncated: true,
|
|
148
|
+
recordCount: count,
|
|
149
|
+
previewCount: 0,
|
|
150
|
+
message: '结果过大,模型侧不返回行数据;请用 aggregate_dataset_data / export_dataset_data 处理全量',
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
if (json.length <= MAX_MODEL_RESULT_CHARS)
|
|
154
|
+
return json;
|
|
155
|
+
return JSON.stringify({ truncated: true, previewCount: 0, message: '结果过大' });
|
|
156
|
+
}
|
|
157
|
+
function clipLongStrings(value, maxChars) {
|
|
158
|
+
if (typeof value === 'string') {
|
|
159
|
+
return value.length > maxChars ? `${value.slice(0, maxChars)}${TEXT_CLIP_SUFFIX}` : value;
|
|
160
|
+
}
|
|
161
|
+
if (Array.isArray(value))
|
|
162
|
+
return value.map((item) => clipLongStrings(item, maxChars));
|
|
163
|
+
if (!isPlainObject(value))
|
|
164
|
+
return value;
|
|
165
|
+
const out = {};
|
|
166
|
+
for (const [key, child] of Object.entries(value)) {
|
|
167
|
+
out[key] = clipLongStrings(child, maxChars);
|
|
168
|
+
}
|
|
169
|
+
return out;
|
|
170
|
+
}
|
|
171
|
+
function isPrimaryArrayKey(key) {
|
|
172
|
+
return PRIMARY_ARRAY_KEYS.includes(key);
|
|
173
|
+
}
|
|
174
|
+
function shrinkPrimaryArray(obj, recordCount) {
|
|
175
|
+
const key = primaryArrayKey(obj);
|
|
176
|
+
const rows = key ? obj[key] : undefined;
|
|
177
|
+
if (!key || !Array.isArray(rows) || rows.length <= 1)
|
|
178
|
+
return obj;
|
|
179
|
+
let low = 1;
|
|
180
|
+
let high = rows.length;
|
|
181
|
+
let best = 1;
|
|
182
|
+
while (low <= high) {
|
|
183
|
+
const mid = Math.floor((low + high) / 2);
|
|
184
|
+
const candidate = withPreview(obj, key, rows.slice(0, mid), recordCount);
|
|
185
|
+
if (JSON.stringify(candidate).length <= MAX_MODEL_RESULT_CHARS) {
|
|
186
|
+
best = mid;
|
|
187
|
+
low = mid + 1;
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
high = mid - 1;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return withPreview(obj, key, rows.slice(0, best), recordCount);
|
|
194
|
+
}
|
|
195
|
+
function withPreview(obj, key, rows, recordCount) {
|
|
196
|
+
const full = recordCount ?? finiteCount(obj.recordCount) ?? finiteCount(obj.rowCount) ?? rows.length;
|
|
197
|
+
return {
|
|
198
|
+
...obj,
|
|
199
|
+
[key]: rows,
|
|
200
|
+
recordCount: full,
|
|
201
|
+
previewCount: rows.length,
|
|
202
|
+
truncated: true,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
function primaryArrayKey(obj) {
|
|
206
|
+
for (const key of PRIMARY_ARRAY_KEYS) {
|
|
207
|
+
if (Array.isArray(obj[key]))
|
|
208
|
+
return key;
|
|
209
|
+
}
|
|
210
|
+
return undefined;
|
|
211
|
+
}
|
|
212
|
+
function attachCount(value, count) {
|
|
213
|
+
if (count == null || !isPlainObject(value))
|
|
214
|
+
return value;
|
|
215
|
+
const obj = value;
|
|
216
|
+
if (finiteCount(obj.recordCount) != null || finiteCount(obj.rowCount) != null)
|
|
217
|
+
return value;
|
|
218
|
+
return { ...obj, recordCount: count };
|
|
219
|
+
}
|
|
220
|
+
function primaryArrayLength(obj) {
|
|
221
|
+
for (const key of PRIMARY_ARRAY_KEYS) {
|
|
222
|
+
const child = obj[key];
|
|
223
|
+
if (Array.isArray(child))
|
|
224
|
+
return child.length;
|
|
225
|
+
}
|
|
226
|
+
return undefined;
|
|
227
|
+
}
|
|
228
|
+
function finiteCount(value) {
|
|
229
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
|
230
|
+
}
|
|
231
|
+
function parseJson(text) {
|
|
232
|
+
const trimmed = text.trim();
|
|
233
|
+
if (!trimmed.startsWith('{') && !trimmed.startsWith('['))
|
|
234
|
+
return undefined;
|
|
235
|
+
try {
|
|
236
|
+
return JSON.parse(trimmed);
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
return undefined;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
function isPlainObject(value) {
|
|
243
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
244
|
+
}
|
|
245
|
+
function redactFileLocators(value) {
|
|
246
|
+
if (Array.isArray(value))
|
|
247
|
+
return value.map(redactFileLocators);
|
|
248
|
+
if (!isPlainObject(value))
|
|
249
|
+
return value;
|
|
250
|
+
const obj = value;
|
|
251
|
+
const fileShaped = typeof obj.fileName === 'string'
|
|
252
|
+
&& (typeof obj.url === 'string' || typeof obj.relativePath === 'string');
|
|
253
|
+
const out = {};
|
|
254
|
+
for (const [key, child] of Object.entries(obj)) {
|
|
255
|
+
if (key === 'fileReference' && isPlainObject(child)) {
|
|
256
|
+
const ref = { ...child };
|
|
257
|
+
delete ref.url;
|
|
258
|
+
out[key] = ref;
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
if (fileShaped && key === 'url')
|
|
262
|
+
continue;
|
|
263
|
+
out[key] = redactFileLocators(child);
|
|
264
|
+
}
|
|
265
|
+
return out;
|
|
266
|
+
}
|
package/dist/tool/timeout.d.ts
CHANGED
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* 尚未含这些导出。发版 contracts 后改为从 `@gt-fe/eap-contracts` 引用。
|
|
2
|
+
* 秒钳制与 abort 识别从 `@gt-fe/eap-contracts` 来。
|
|
3
|
+
* 本文件保留:本次工具 execution.timeout → 毫秒。
|
|
5
4
|
*/
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
export declare
|
|
9
|
-
export declare const MAX_TOOL_TIMEOUT_SEC = 300;
|
|
10
|
-
export declare function resolveToolTimeoutSec(timeoutSec: unknown, fallbackSec?: number): number;
|
|
11
|
-
export declare function toToolTimeoutMs(timeoutSec: unknown, fallbackSec?: number): number;
|
|
12
|
-
export declare function isAbortError(error: unknown): boolean;
|
|
13
|
-
export declare function toolTimeoutErrorMessage(timeoutSec: number): string;
|
|
14
|
-
export declare function abortOrTimeoutMessage(error: unknown, timeoutSec: number): string;
|
|
5
|
+
export { DEFAULT_HTTP_TOOL_TIMEOUT_SEC, DEFAULT_TOOL_TIMEOUT_SEC, MAX_TOOL_TIMEOUT_SEC, MIN_TOOL_TIMEOUT_SEC, abortOrTimeoutMessage, isAbortError, resolveToolTimeoutSec, toToolTimeoutMs, toolTimeoutErrorMessage, } from '@gt-fe/eap-contracts';
|
|
6
|
+
/** 清单 tools[].timeout / 展开后 execution.timeout(秒)→ 本次调用毫秒;没有则用装配默认。 */
|
|
7
|
+
export declare function timeoutMsFromExecution(execution: unknown, fallbackMs: number): number;
|
package/dist/tool/timeout.js
CHANGED
|
@@ -1,39 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* 尚未含这些导出。发版 contracts 后改为从 `@gt-fe/eap-contracts` 引用。
|
|
2
|
+
* 秒钳制与 abort 识别从 `@gt-fe/eap-contracts` 来。
|
|
3
|
+
* 本文件保留:本次工具 execution.timeout → 毫秒。
|
|
5
4
|
*/
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
return fallbackSec;
|
|
5
|
+
export { DEFAULT_HTTP_TOOL_TIMEOUT_SEC, DEFAULT_TOOL_TIMEOUT_SEC, MAX_TOOL_TIMEOUT_SEC, MIN_TOOL_TIMEOUT_SEC, abortOrTimeoutMessage, isAbortError, resolveToolTimeoutSec, toToolTimeoutMs, toolTimeoutErrorMessage, } from '@gt-fe/eap-contracts';
|
|
6
|
+
import { toToolTimeoutMs } from '@gt-fe/eap-contracts';
|
|
7
|
+
/** 清单 tools[].timeout / 展开后 execution.timeout(秒)→ 本次调用毫秒;没有则用装配默认。 */
|
|
8
|
+
export function timeoutMsFromExecution(execution, fallbackMs) {
|
|
9
|
+
if (!execution || typeof execution !== 'object' || Array.isArray(execution)) {
|
|
10
|
+
return fallbackMs;
|
|
13
11
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
return resolveToolTimeoutSec(timeoutSec, fallbackSec) * 1000;
|
|
18
|
-
}
|
|
19
|
-
export function isAbortError(error) {
|
|
20
|
-
if (!error || typeof error !== 'object')
|
|
21
|
-
return false;
|
|
22
|
-
const err = error;
|
|
23
|
-
if (err.name === 'AbortError' || err.name === 'TimeoutError' || err.code === 'ABORT_ERR') {
|
|
24
|
-
return true;
|
|
12
|
+
const timeout = execution.timeout;
|
|
13
|
+
if (typeof timeout !== 'number' || !Number.isFinite(timeout) || timeout <= 0) {
|
|
14
|
+
return fallbackMs;
|
|
25
15
|
}
|
|
26
|
-
|
|
27
|
-
return (msg === 'this operation was aborted'
|
|
28
|
-
|| msg === 'the operation was aborted'
|
|
29
|
-
|| msg.includes('this operation was aborted')
|
|
30
|
-
|| msg.includes('the operation was aborted'));
|
|
31
|
-
}
|
|
32
|
-
export function toolTimeoutErrorMessage(timeoutSec) {
|
|
33
|
-
return `timeout after ${resolveToolTimeoutSec(timeoutSec)}s`;
|
|
34
|
-
}
|
|
35
|
-
export function abortOrTimeoutMessage(error, timeoutSec) {
|
|
36
|
-
if (isAbortError(error))
|
|
37
|
-
return toolTimeoutErrorMessage(timeoutSec);
|
|
38
|
-
return error instanceof Error ? error.message : String(error);
|
|
16
|
+
return toToolTimeoutMs(timeout);
|
|
39
17
|
}
|
|
@@ -12,6 +12,8 @@ export interface AuthContext {
|
|
|
12
12
|
delegationToken: string;
|
|
13
13
|
/** Agent 对外主键 */
|
|
14
14
|
agentCode: string;
|
|
15
|
+
/** 本次请求的 Agent 预装版本(目录名);Gateway 写根用 */
|
|
16
|
+
agentVersion?: string;
|
|
15
17
|
}
|
|
16
18
|
/**
|
|
17
19
|
* ToolCallRequest — Tool 调用请求
|
|
@@ -22,9 +24,13 @@ export interface ToolCallRequest {
|
|
|
22
24
|
arguments: Record<string, unknown>;
|
|
23
25
|
/**
|
|
24
26
|
* 工具语义化版本(来自 LoadedToolDefinition.manifest.version)。
|
|
25
|
-
* McpToolExecutor
|
|
27
|
+
* McpToolExecutor 只放进 Gateway `params._meta.version`,不写 params 顶层。
|
|
26
28
|
*/
|
|
27
29
|
toolVersion?: string;
|
|
30
|
+
/**
|
|
31
|
+
* MCP 工具集编码。McpToolExecutor 只放进 Gateway `params._meta.toolsetCode`。
|
|
32
|
+
*/
|
|
33
|
+
toolsetCode?: string;
|
|
28
34
|
authContext: AuthContext;
|
|
29
35
|
dataScope?: 'user-bound' | 'department-bound' | 'global';
|
|
30
36
|
resourceOwnerId?: string;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { isBuiltinToolExecution } from '@gt-fe/eap-contracts';
|
|
8
8
|
import { assertToolPermission, GovernanceUnavailableError, PermissionDeniedError, } from '../governance/permission-guard.js';
|
|
9
|
+
import { toModelVisibleToolContent } from './model-visible-tool-content.js';
|
|
9
10
|
/**
|
|
10
11
|
* ToolOrchestrator — Tool 调用编排主服务
|
|
11
12
|
*/
|
|
@@ -70,7 +71,11 @@ export class ToolOrchestrator {
|
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
73
|
try {
|
|
73
|
-
|
|
74
|
+
const result = await this.toolExecutor.execute(request);
|
|
75
|
+
if (result.success && result.content) {
|
|
76
|
+
return { ...result, content: toModelVisibleToolContent(result.content) };
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
74
79
|
}
|
|
75
80
|
catch (error) {
|
|
76
81
|
const message = error instanceof Error ? error.message : 'Unknown execution error';
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* @see design.md §1.2 Tool结果注入State → 回到LLM节点(ReAct循环)
|
|
11
11
|
* @see requirements.md Requirement 8 AC4
|
|
12
12
|
*/
|
|
13
|
+
import { toModelVisibleToolContent } from './model-visible-tool-content.js';
|
|
13
14
|
// ─────────────────────────────────────────────
|
|
14
15
|
// ToolResultInjector
|
|
15
16
|
// ─────────────────────────────────────────────
|
|
@@ -51,7 +52,7 @@ export class ToolResultInjector {
|
|
|
51
52
|
*/
|
|
52
53
|
buildToolMessage(result) {
|
|
53
54
|
const content = result.success
|
|
54
|
-
? result.content
|
|
55
|
+
? toModelVisibleToolContent(result.content)
|
|
55
56
|
: `[Tool Error] ${result.error ?? 'Unknown error'}`;
|
|
56
57
|
return {
|
|
57
58
|
role: 'tool',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gt-fe/eap-runtime",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.24",
|
|
4
4
|
"description": "Enterprise Agent Platform — Runtime核心:Graph执行引擎、Task生命周期、Session管理、Checkpoint持久化",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"ioredis": "^5.4.0",
|
|
21
21
|
"pg": "^8.13.0",
|
|
22
22
|
"yaml": "^2.6.1",
|
|
23
|
-
"@gt-fe/eap-contracts": "0.0.
|
|
23
|
+
"@gt-fe/eap-contracts": "0.0.14"
|
|
24
24
|
},
|
|
25
25
|
"publishConfig": {
|
|
26
26
|
"registry": "https://registry.npmjs.org/",
|