@jsonstudio/llms 0.6.1172 → 0.6.1354
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/conversion/codecs/gemini-openai-codec.d.ts +3 -1
- package/dist/conversion/codecs/gemini-openai-codec.js +10 -4
- package/dist/conversion/compat/actions/gemini-web-search.d.ts +1 -1
- package/dist/conversion/compat/actions/gemini-web-search.js +5 -2
- package/dist/conversion/compat/actions/iflow-tool-text-fallback.d.ts +12 -0
- package/dist/conversion/compat/actions/iflow-tool-text-fallback.js +199 -0
- package/dist/conversion/compat/actions/iflow-web-search.d.ts +1 -1
- package/dist/conversion/compat/actions/iflow-web-search.js +5 -2
- package/dist/conversion/hub/operation-table/semantic-mappers/anthropic-mapper.js +47 -56
- package/dist/conversion/hub/operation-table/semantic-mappers/chat-mapper.js +1 -13
- package/dist/conversion/hub/operation-table/semantic-mappers/gemini-mapper.js +523 -50
- package/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper.js +18 -38
- package/dist/conversion/hub/pipeline/compat/compat-pipeline-executor.js +6 -0
- package/dist/conversion/hub/pipeline/compat/compat-types.d.ts +3 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/adapter-context.d.ts +10 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/adapter-context.js +134 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/anthropic-alias-map.d.ts +6 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/anthropic-alias-map.js +79 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/apply-patch-tool-mode.d.ts +3 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/apply-patch-tool-mode.js +46 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/execute-chat-process-entry.d.ts +8 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/execute-chat-process-entry.js +366 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/execute-request-stage.d.ts +9 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/execute-request-stage.js +384 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/node-results.d.ts +3 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/node-results.js +14 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/payload-normalize.d.ts +2 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/payload-normalize.js +144 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/policy.d.ts +4 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/policy.js +32 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/protocol.d.ts +8 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/protocol.js +63 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/resolve-protocol-hooks.d.ts +2 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/resolve-protocol-hooks.js +43 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/semantic-gate.d.ts +1 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/semantic-gate.js +29 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/servertool-runtime-config.d.ts +2 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/servertool-runtime-config.js +16 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/types.d.ts +116 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/types.js +1 -0
- package/dist/conversion/hub/pipeline/hub-pipeline.d.ts +3 -95
- package/dist/conversion/hub/pipeline/hub-pipeline.js +19 -1281
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage1_format_parse/index.js +1 -1
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.d.ts +7 -0
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.js +65 -1
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/index.js +25 -22
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/index.js +1 -1
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage2_format_build/index.d.ts +1 -1
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage2_format_build/index.js +2 -2
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage3_compat/index.js +2 -2
- package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage1_tool_governance/index.js +1 -1
- package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage2_route_select/index.js +1 -1
- package/dist/conversion/hub/pipeline/stages/resp_inbound/resp_inbound_stage1_sse_decode/index.js +11 -11
- package/dist/conversion/hub/pipeline/stages/resp_inbound/resp_inbound_stage2_format_parse/index.js +1 -1
- package/dist/conversion/hub/pipeline/stages/resp_inbound/resp_inbound_stage3_semantic_map/index.d.ts +1 -0
- package/dist/conversion/hub/pipeline/stages/resp_inbound/resp_inbound_stage3_semantic_map/index.js +4 -2
- package/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/index.d.ts +1 -0
- package/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/index.js +17 -9
- package/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage2_sse_stream/index.js +2 -2
- package/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage1_tool_governance/index.js +40 -2
- package/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage2_finalize/index.js +1 -1
- package/dist/conversion/hub/pipeline/target-utils.js +9 -5
- package/dist/conversion/hub/process/chat-process.js +256 -16
- package/dist/conversion/hub/response/provider-response.d.ts +8 -0
- package/dist/conversion/hub/response/provider-response.js +85 -27
- package/dist/conversion/hub/response/response-mappers.d.ts +10 -3
- package/dist/conversion/hub/response/response-mappers.js +30 -6
- package/dist/conversion/hub/response/response-runtime.js +4 -38
- package/dist/conversion/hub/snapshot-recorder.js +5 -1
- package/dist/conversion/hub/standardized-bridge.js +23 -15
- package/dist/conversion/pipeline/codecs/v2/anthropic-openai-pipeline.js +36 -5
- package/dist/conversion/responses/responses-openai-bridge.js +20 -4
- package/dist/conversion/shared/gemini-tool-utils.d.ts +8 -1
- package/dist/conversion/shared/gemini-tool-utils.js +580 -108
- package/dist/conversion/shared/jsonish.js +1 -1
- package/dist/conversion/shared/mcp-injection.js +67 -33
- package/dist/conversion/shared/openai-finalizer.js +2 -1
- package/dist/conversion/shared/openai-message-normalize.js +76 -21
- package/dist/conversion/shared/responses-output-builder.js +6 -0
- package/dist/conversion/shared/runtime-metadata.d.ts +7 -0
- package/dist/conversion/shared/runtime-metadata.js +23 -0
- package/dist/conversion/shared/text-markup-normalizer.d.ts +2 -0
- package/dist/conversion/shared/text-markup-normalizer.js +284 -4
- package/dist/conversion/shared/tool-canonicalizer.js +2 -1
- package/dist/conversion/shared/tool-governor.js +3 -3
- package/dist/filters/engine.js +5 -5
- package/dist/filters/special/request-tool-list-filter.js +194 -60
- package/dist/filters/special/request-tools-normalize.js +1 -1
- package/dist/filters/special/response-tool-text-canonicalize.d.ts +4 -7
- package/dist/filters/special/response-tool-text-canonicalize.js +7 -35
- package/dist/filters/special/tool-filter-hooks.js +58 -62
- package/dist/guidance/index.js +5 -1
- package/dist/http/sse-response.js +6 -6
- package/dist/router/virtual-router/bootstrap.js +48 -4
- package/dist/router/virtual-router/engine-health.d.ts +1 -1
- package/dist/router/virtual-router/engine-health.js +11 -110
- package/dist/router/virtual-router/engine-selection/alias-selection.d.ts +15 -0
- package/dist/router/virtual-router/engine-selection/alias-selection.js +156 -0
- package/dist/router/virtual-router/engine-selection/context-weight-multipliers.d.ts +11 -0
- package/dist/router/virtual-router/engine-selection/context-weight-multipliers.js +23 -0
- package/dist/router/virtual-router/engine-selection/direct-provider-model.d.ts +9 -0
- package/dist/router/virtual-router/engine-selection/direct-provider-model.js +49 -0
- package/dist/router/virtual-router/engine-selection/instruction-target.d.ts +6 -0
- package/dist/router/virtual-router/engine-selection/instruction-target.js +54 -0
- package/dist/router/virtual-router/engine-selection/key-parsing.d.ts +8 -0
- package/dist/router/virtual-router/engine-selection/key-parsing.js +64 -0
- package/dist/router/virtual-router/engine-selection/route-utils.d.ts +12 -0
- package/dist/router/virtual-router/engine-selection/route-utils.js +150 -0
- package/dist/router/virtual-router/engine-selection/routing-state-filter.d.ts +4 -0
- package/dist/router/virtual-router/engine-selection/routing-state-filter.js +50 -0
- package/dist/router/virtual-router/engine-selection/selection-deps.d.ts +39 -0
- package/dist/router/virtual-router/engine-selection/selection-deps.js +1 -0
- package/dist/router/virtual-router/engine-selection/sticky-pool.d.ts +11 -0
- package/dist/router/virtual-router/engine-selection/sticky-pool.js +109 -0
- package/dist/router/virtual-router/engine-selection/tier-priority.d.ts +12 -0
- package/dist/router/virtual-router/engine-selection/tier-priority.js +55 -0
- package/dist/router/virtual-router/engine-selection/tier-selection-select.d.ts +22 -0
- package/dist/router/virtual-router/engine-selection/tier-selection-select.js +400 -0
- package/dist/router/virtual-router/engine-selection/tier-selection.d.ts +3 -0
- package/dist/router/virtual-router/engine-selection/tier-selection.js +225 -0
- package/dist/router/virtual-router/engine-selection.d.ts +4 -30
- package/dist/router/virtual-router/engine-selection.js +10 -962
- package/dist/router/virtual-router/engine.d.ts +1 -0
- package/dist/router/virtual-router/engine.js +55 -10
- package/dist/router/virtual-router/routing-instructions.js +6 -1
- package/dist/router/virtual-router/stop-message-state-sync.d.ts +5 -0
- package/dist/router/virtual-router/stop-message-state-sync.js +6 -14
- package/dist/router/virtual-router/types.d.ts +25 -1
- package/dist/servertool/clock/config.d.ts +8 -0
- package/dist/servertool/clock/config.js +22 -0
- package/dist/servertool/clock/log.d.ts +3 -0
- package/dist/servertool/clock/log.js +13 -0
- package/dist/servertool/clock/task-store.d.ts +1 -1
- package/dist/servertool/clock/task-store.js +1 -1
- package/dist/servertool/clock/tasks.js +1 -1
- package/dist/servertool/engine.js +146 -21
- package/dist/servertool/handlers/clock-auto.js +11 -6
- package/dist/servertool/handlers/clock.js +36 -10
- package/dist/servertool/handlers/followup-request-builder.js +8 -2
- package/dist/servertool/handlers/gemini-empty-reply-continue.js +15 -9
- package/dist/servertool/handlers/iflow-model-error-retry.js +6 -4
- package/dist/servertool/handlers/recursive-detection-guard.js +4 -2
- package/dist/servertool/handlers/stop-message-auto.js +100 -10
- package/dist/servertool/handlers/vision.js +4 -1
- package/dist/servertool/handlers/web-search.js +3 -1
- package/dist/servertool/pending-session.d.ts +19 -0
- package/dist/servertool/pending-session.js +97 -0
- package/dist/servertool/reenter-backend.js +5 -3
- package/dist/servertool/server-side-tools.js +235 -6
- package/dist/servertool/types.d.ts +13 -0
- package/dist/sse/json-to-sse/event-generators/responses.js +1 -1
- package/dist/sse/shared/chat-serializer.js +2 -2
- package/dist/sse/shared/constants.js +1 -1
- package/dist/sse/sse-to-json/anthropic-sse-to-json-converter.d.ts +7 -1
- package/dist/sse/sse-to-json/builders/response-builder.js +16 -0
- package/dist/sse/sse-to-json/responses-sse-to-json-converter.d.ts +1 -1
- package/dist/tools/apply-patch/execution-capturer.js +1 -1
- package/dist/tools/exec-command/normalize.js +4 -0
- package/dist/tools/exec-command/regression-capturer.js +1 -1
- package/package.json +10 -5
|
@@ -132,7 +132,7 @@ export function repairArgumentsToString(value) {
|
|
|
132
132
|
catch { /* ignore */ }
|
|
133
133
|
// 6) quote unquoted keys
|
|
134
134
|
try {
|
|
135
|
-
s = s.replace(/([
|
|
135
|
+
s = s.replace(/([{,\s])([A-Za-z_][A-Za-z0-9_-]*)\s*:/g, '$1"$2":');
|
|
136
136
|
}
|
|
137
137
|
catch { /* ignore */ }
|
|
138
138
|
// 7) try parse after cleanup
|
|
@@ -11,10 +11,48 @@ const obj = (props, req = []) => {
|
|
|
11
11
|
return schema;
|
|
12
12
|
};
|
|
13
13
|
function uniq(arr) { return Array.from(new Set(arr)); }
|
|
14
|
+
function buildKnownServersLine(discoveredServers) {
|
|
15
|
+
if (!Array.isArray(discoveredServers) || discoveredServers.length === 0)
|
|
16
|
+
return '';
|
|
17
|
+
const list = uniq(discoveredServers).slice(0, 8);
|
|
18
|
+
const suffix = discoveredServers.length > list.length ? ` (+${discoveredServers.length - list.length} more)` : '';
|
|
19
|
+
return `Known MCP servers: ${list.join(', ')}${suffix}.`;
|
|
20
|
+
}
|
|
21
|
+
function buildMcpServerReminder() {
|
|
22
|
+
return 'Note: arguments.server is an MCP server label (NOT a tool name like shell/exec_command/apply_patch).';
|
|
23
|
+
}
|
|
24
|
+
function buildListResourcesDescription(discoveredServers) {
|
|
25
|
+
return [
|
|
26
|
+
'List resources exposed by MCP servers.',
|
|
27
|
+
'Only use this for MCP resources (not MCP tools). Many MCP servers expose tools only; if the result is empty, do not retry.',
|
|
28
|
+
'If you do not know the MCP server name yet, call this tool with {} once; then reuse the returned server names for subsequent calls.',
|
|
29
|
+
buildMcpServerReminder(),
|
|
30
|
+
buildKnownServersLine(discoveredServers)
|
|
31
|
+
].filter(Boolean).join('\n');
|
|
32
|
+
}
|
|
33
|
+
function buildListTemplatesDescription(discoveredServers) {
|
|
34
|
+
return [
|
|
35
|
+
'List resource templates exposed by MCP servers.',
|
|
36
|
+
'Only use this for MCP resources (not MCP tools). If list_mcp_resources returns empty, do not retry.',
|
|
37
|
+
'If you do not know the MCP server name yet, call list_mcp_resources({}) once first.',
|
|
38
|
+
buildMcpServerReminder(),
|
|
39
|
+
buildKnownServersLine(discoveredServers)
|
|
40
|
+
].filter(Boolean).join('\n');
|
|
41
|
+
}
|
|
42
|
+
function buildReadResourceDescription(discoveredServers) {
|
|
43
|
+
return [
|
|
44
|
+
'Read a specific MCP resource by { server, uri }.',
|
|
45
|
+
'Only use this for MCP resources (not MCP tools). If list_mcp_resources returns empty, do not retry.',
|
|
46
|
+
'If you do not know the MCP server name yet, call list_mcp_resources({}) once first.',
|
|
47
|
+
buildMcpServerReminder(),
|
|
48
|
+
buildKnownServersLine(discoveredServers)
|
|
49
|
+
].filter(Boolean).join('\n');
|
|
50
|
+
}
|
|
14
51
|
export function injectMcpToolsForChat(tools, discoveredServers) {
|
|
15
52
|
const out = [];
|
|
16
53
|
const keep = new Set();
|
|
17
|
-
const listServers = discoveredServers && discoveredServers.length ? { type: 'string', enum: uniq(discoveredServers) } : { type: 'string' };
|
|
54
|
+
const listServers = discoveredServers && discoveredServers.length ? { type: 'string', enum: uniq(discoveredServers), minLength: 1 } : { type: 'string', minLength: 1 };
|
|
55
|
+
const templateServer = discoveredServers && discoveredServers.length ? { type: 'string', enum: uniq(discoveredServers), minLength: 1 } : { type: 'string', minLength: 1 };
|
|
18
56
|
const ensure = (name, def) => { if (!keep.has(name)) {
|
|
19
57
|
out.push(def);
|
|
20
58
|
keep.add(name);
|
|
@@ -28,35 +66,45 @@ export function injectMcpToolsForChat(tools, discoveredServers) {
|
|
|
28
66
|
continue;
|
|
29
67
|
}
|
|
30
68
|
if (lower === 'list_mcp_resources') {
|
|
31
|
-
ensure('list_mcp_resources', { type: 'function', function: { name: 'list_mcp_resources', description: t.function?.description
|
|
69
|
+
ensure('list_mcp_resources', { type: 'function', function: { name: 'list_mcp_resources', description: (t.function?.description && String(t.function.description).trim()) ? t.function.description : buildListResourcesDescription(discoveredServers), parameters: obj({ server: listServers, filter: { type: 'string' }, root: { type: 'string' } }) } });
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (lower === 'list_mcp_resource_templates') {
|
|
73
|
+
ensure('list_mcp_resource_templates', {
|
|
74
|
+
type: 'function',
|
|
75
|
+
function: {
|
|
76
|
+
name: 'list_mcp_resource_templates',
|
|
77
|
+
description: (t.function?.description && String(t.function.description).trim()) ? t.function.description : buildListTemplatesDescription(discoveredServers),
|
|
78
|
+
parameters: obj({ server: templateServer, cursor: { type: 'string' } })
|
|
79
|
+
}
|
|
80
|
+
});
|
|
32
81
|
continue;
|
|
33
82
|
}
|
|
34
|
-
if (lower === 'read_mcp_resource'
|
|
83
|
+
if (lower === 'read_mcp_resource') {
|
|
84
|
+
// Phase gating: do not expose read until we have known server labels.
|
|
35
85
|
if (discoveredServers.length > 0) {
|
|
36
86
|
const srv = { type: 'string', enum: uniq(discoveredServers) };
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
87
|
+
ensure('read_mcp_resource', {
|
|
88
|
+
type: 'function',
|
|
89
|
+
function: {
|
|
90
|
+
name: 'read_mcp_resource',
|
|
91
|
+
description: (t.function?.description && String(t.function.description).trim()) ? t.function.description : buildReadResourceDescription(discoveredServers),
|
|
92
|
+
parameters: obj({ server: srv, uri: { type: 'string' } }, ['server', 'uri'])
|
|
93
|
+
}
|
|
94
|
+
});
|
|
44
95
|
}
|
|
96
|
+
continue;
|
|
45
97
|
}
|
|
46
98
|
out.push(t);
|
|
47
99
|
keep.add(lower);
|
|
48
100
|
}
|
|
49
|
-
// Ensure list exists when user did not provide it
|
|
50
|
-
if (!keep.has('list_mcp_resources')) {
|
|
51
|
-
out.push({ type: 'function', function: { name: 'list_mcp_resources', description: 'List resources from a given MCP server (arguments.server = server label).', parameters: obj({ server: listServers, filter: { type: 'string' }, root: { type: 'string' } }) } });
|
|
52
|
-
}
|
|
53
101
|
return out;
|
|
54
102
|
}
|
|
55
103
|
export function injectMcpToolsForResponses(tools, discoveredServers) {
|
|
56
104
|
const out = [];
|
|
57
105
|
const keep = new Set();
|
|
58
|
-
const listServers = { type: 'string' };
|
|
59
|
-
const templateServer = discoveredServers && discoveredServers.length ? { type: 'string', enum: uniq(discoveredServers) } : { type: 'string' };
|
|
106
|
+
const listServers = { type: 'string', minLength: 1 };
|
|
107
|
+
const templateServer = discoveredServers && discoveredServers.length ? { type: 'string', enum: uniq(discoveredServers), minLength: 1 } : { type: 'string', minLength: 1 };
|
|
60
108
|
const ensure = (name, def) => { if (!keep.has(name)) {
|
|
61
109
|
out.push(def);
|
|
62
110
|
keep.add(name);
|
|
@@ -70,7 +118,7 @@ export function injectMcpToolsForResponses(tools, discoveredServers) {
|
|
|
70
118
|
continue;
|
|
71
119
|
}
|
|
72
120
|
if (lower === 'list_mcp_resources') {
|
|
73
|
-
ensure('list_mcp_resources', { type: 'function', function: { name: 'list_mcp_resources', description: t.function?.description
|
|
121
|
+
ensure('list_mcp_resources', { type: 'function', function: { name: 'list_mcp_resources', description: (t.function?.description && String(t.function.description).trim()) ? t.function.description : buildListResourcesDescription(discoveredServers), parameters: obj({ server: listServers, filter: { type: 'string' }, root: { type: 'string' } }) } });
|
|
74
122
|
continue;
|
|
75
123
|
}
|
|
76
124
|
if (lower === 'list_mcp_resource_templates') {
|
|
@@ -78,7 +126,7 @@ export function injectMcpToolsForResponses(tools, discoveredServers) {
|
|
|
78
126
|
type: 'function',
|
|
79
127
|
function: {
|
|
80
128
|
name: 'list_mcp_resource_templates',
|
|
81
|
-
description: t.function?.description
|
|
129
|
+
description: (t.function?.description && String(t.function.description).trim()) ? t.function.description : buildListTemplatesDescription(discoveredServers),
|
|
82
130
|
parameters: obj({ server: templateServer, cursor: { type: 'string' } })
|
|
83
131
|
}
|
|
84
132
|
});
|
|
@@ -86,25 +134,11 @@ export function injectMcpToolsForResponses(tools, discoveredServers) {
|
|
|
86
134
|
}
|
|
87
135
|
if (lower === 'read_mcp_resource' && discoveredServers.length > 0) {
|
|
88
136
|
const srv = { type: 'string', enum: uniq(discoveredServers) };
|
|
89
|
-
ensure('read_mcp_resource', { type: 'function', function: { name: 'read_mcp_resource', description: t.function?.description
|
|
137
|
+
ensure('read_mcp_resource', { type: 'function', function: { name: 'read_mcp_resource', description: (t.function?.description && String(t.function.description).trim()) ? t.function.description : buildReadResourceDescription(discoveredServers), parameters: obj({ server: srv, uri: { type: 'string' } }, ['server', 'uri']) } });
|
|
90
138
|
continue;
|
|
91
139
|
}
|
|
92
140
|
out.push(t);
|
|
93
141
|
keep.add(lower);
|
|
94
142
|
}
|
|
95
|
-
if (!keep.has('list_mcp_resources')) {
|
|
96
|
-
out.push({ type: 'function', function: { name: 'list_mcp_resources', description: 'List resources from a given MCP server (arguments.server = server label).', parameters: obj({ server: listServers, filter: { type: 'string' }, root: { type: 'string' } }) } });
|
|
97
|
-
keep.add('list_mcp_resources');
|
|
98
|
-
}
|
|
99
|
-
if (!keep.has('list_mcp_resource_templates')) {
|
|
100
|
-
out.push({
|
|
101
|
-
type: 'function',
|
|
102
|
-
function: {
|
|
103
|
-
name: 'list_mcp_resource_templates',
|
|
104
|
-
description: 'List resource templates from MCP servers.',
|
|
105
|
-
parameters: obj({ server: templateServer, cursor: { type: 'string' } })
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
143
|
return out;
|
|
110
144
|
}
|
|
@@ -59,8 +59,9 @@ export async function finalizeOpenAIChatResponse(chatLike, opts) {
|
|
|
59
59
|
}
|
|
60
60
|
catch { /* ignore */ }
|
|
61
61
|
}
|
|
62
|
-
if (first.finish_reason
|
|
62
|
+
if (String(first.finish_reason || '').toLowerCase() !== 'tool_calls') {
|
|
63
63
|
first.finish_reason = 'tool_calls';
|
|
64
|
+
}
|
|
64
65
|
}
|
|
65
66
|
}
|
|
66
67
|
// nothing more to do for Chat completion response
|
|
@@ -3,6 +3,14 @@ import { injectMcpToolsForChat } from './mcp-injection.js';
|
|
|
3
3
|
// with the deprecated "openai-normalizer" module entry). This file contains the
|
|
4
4
|
// previously-implemented logic from openai-normalize.ts.
|
|
5
5
|
// Legacy tooling stage removed for Chat; tool canonicalization lives in codecs
|
|
6
|
+
function isMcpToolName(name) {
|
|
7
|
+
if (typeof name !== 'string')
|
|
8
|
+
return false;
|
|
9
|
+
const lowered = name.trim().toLowerCase();
|
|
10
|
+
return (lowered === 'list_mcp_resources' ||
|
|
11
|
+
lowered === 'list_mcp_resource_templates' ||
|
|
12
|
+
lowered === 'read_mcp_resource');
|
|
13
|
+
}
|
|
6
14
|
export function normalizeChatRequest(request) {
|
|
7
15
|
if (!request || typeof request !== 'object')
|
|
8
16
|
return request;
|
|
@@ -54,38 +62,85 @@ export function normalizeChatRequest(request) {
|
|
|
54
62
|
const enableMcp = String(process?.env?.ROUTECODEX_MCP_ENABLE ?? '1') !== '0';
|
|
55
63
|
if (enableMcp) {
|
|
56
64
|
const known = new Set();
|
|
65
|
+
const fromEnv = String(process?.env?.RCC_MCP_SERVERS || '').trim();
|
|
66
|
+
if (fromEnv) {
|
|
67
|
+
for (const s of fromEnv.split(',').map((x) => x.trim()).filter(Boolean))
|
|
68
|
+
known.add(s);
|
|
69
|
+
}
|
|
70
|
+
const addServer = (v) => {
|
|
71
|
+
if (typeof v === 'string') {
|
|
72
|
+
const s = v.trim();
|
|
73
|
+
if (s)
|
|
74
|
+
known.add(s);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
const extractFromOutput = (output) => {
|
|
78
|
+
try {
|
|
79
|
+
if (Array.isArray(output)) {
|
|
80
|
+
for (const item of output) {
|
|
81
|
+
if (typeof item === 'string')
|
|
82
|
+
addServer(item);
|
|
83
|
+
else if (item && typeof item === 'object' && !Array.isArray(item))
|
|
84
|
+
addServer(item.server);
|
|
85
|
+
}
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (!output || typeof output !== 'object' || Array.isArray(output))
|
|
89
|
+
return;
|
|
90
|
+
const o = output;
|
|
91
|
+
if (Array.isArray(o.servers))
|
|
92
|
+
for (const s of o.servers)
|
|
93
|
+
addServer(s);
|
|
94
|
+
if (Array.isArray(o.resources))
|
|
95
|
+
for (const r of o.resources)
|
|
96
|
+
addServer(r?.server ?? r?.source?.server);
|
|
97
|
+
if (Array.isArray(o.resourceTemplates))
|
|
98
|
+
for (const t of o.resourceTemplates)
|
|
99
|
+
addServer(t?.server ?? t?.source?.server);
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// best-effort
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
// IMPORTANT: do NOT treat assistant tool_calls as authoritative for MCP server labels
|
|
106
|
+
// (the model may guess "shell"/"exec_command"/etc). Only trust tool results.
|
|
57
107
|
try {
|
|
58
108
|
const msgs = Array.isArray(normalized.messages) ? normalized.messages : [];
|
|
59
109
|
for (const m of msgs) {
|
|
60
110
|
if (!m || typeof m !== 'object')
|
|
61
111
|
continue;
|
|
62
|
-
if (m.role
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
try {
|
|
74
|
-
const argStr = String(tc?.function?.arguments ?? '');
|
|
75
|
-
const parsed = JSON.parse(argStr);
|
|
76
|
-
const sv = parsed?.server;
|
|
77
|
-
if (typeof sv === 'string' && sv.trim())
|
|
78
|
-
known.add(sv.trim());
|
|
112
|
+
if (String(m.role || '').toLowerCase() !== 'tool')
|
|
113
|
+
continue;
|
|
114
|
+
const content = m.content;
|
|
115
|
+
if (typeof content !== 'string' || content.trim().length === 0)
|
|
116
|
+
continue;
|
|
117
|
+
try {
|
|
118
|
+
const parsed = JSON.parse(content);
|
|
119
|
+
if (parsed && typeof parsed === 'object' && parsed.version === 'rcc.tool.v1' && parsed.tool?.name) {
|
|
120
|
+
const toolName = String(parsed.tool.name).toLowerCase();
|
|
121
|
+
if (toolName === 'list_mcp_resources') {
|
|
122
|
+
extractFromOutput(parsed.result?.output);
|
|
79
123
|
}
|
|
80
|
-
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
extractFromOutput(parsed?.output ?? parsed);
|
|
81
127
|
}
|
|
82
128
|
}
|
|
129
|
+
catch {
|
|
130
|
+
// ignore
|
|
131
|
+
}
|
|
83
132
|
}
|
|
84
133
|
}
|
|
85
134
|
catch { /* ignore */ }
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
135
|
+
const currentTools = Array.isArray(normalized.tools)
|
|
136
|
+
? normalized.tools
|
|
137
|
+
: undefined;
|
|
138
|
+
// IMPORTANT: Do not force-inject MCP tools. If the inbound request doesn't include MCP tools,
|
|
139
|
+
// keep tools untouched (and do not create a tools=[] placeholder).
|
|
140
|
+
if (currentTools && currentTools.some((t) => isMcpToolName(t?.function?.name))) {
|
|
141
|
+
const discovered = Array.from(known);
|
|
142
|
+
normalized.tools = injectMcpToolsForChat(currentTools, discovered);
|
|
143
|
+
}
|
|
89
144
|
}
|
|
90
145
|
}
|
|
91
146
|
catch { /* ignore MCP injection */ }
|
|
@@ -243,8 +243,14 @@ function buildRequiredActionFromNormalized(calls) {
|
|
|
243
243
|
if (!calls.length)
|
|
244
244
|
return undefined;
|
|
245
245
|
const submitCalls = calls.map((entry) => ({
|
|
246
|
+
// Internal + client compat:
|
|
247
|
+
// - keep OpenAI-style `id` + `function`
|
|
248
|
+
// - also expose `tool_call_id` + top-level `name` for legacy/bridge clients
|
|
246
249
|
id: entry.id,
|
|
250
|
+
tool_call_id: entry.id,
|
|
247
251
|
type: 'function',
|
|
252
|
+
name: entry.name,
|
|
253
|
+
arguments: entry.args,
|
|
248
254
|
function: {
|
|
249
255
|
name: entry.name,
|
|
250
256
|
arguments: entry.args
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type JsonObject } from '../hub/types/json.js';
|
|
2
|
+
export type RuntimeMetadataCarrier = Record<string, unknown> & {
|
|
3
|
+
__rt?: JsonObject;
|
|
4
|
+
};
|
|
5
|
+
export declare function readRuntimeMetadata(carrier?: Record<string, unknown> | null): JsonObject | undefined;
|
|
6
|
+
export declare function ensureRuntimeMetadata(carrier: Record<string, unknown>): JsonObject;
|
|
7
|
+
export declare function cloneRuntimeMetadata(carrier?: Record<string, unknown> | null): JsonObject | undefined;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { isJsonObject, jsonClone } from '../hub/types/json.js';
|
|
2
|
+
export function readRuntimeMetadata(carrier) {
|
|
3
|
+
if (!carrier || typeof carrier !== 'object') {
|
|
4
|
+
return undefined;
|
|
5
|
+
}
|
|
6
|
+
const candidate = carrier.__rt;
|
|
7
|
+
return candidate && isJsonObject(candidate) ? candidate : undefined;
|
|
8
|
+
}
|
|
9
|
+
export function ensureRuntimeMetadata(carrier) {
|
|
10
|
+
if (!carrier || typeof carrier !== 'object') {
|
|
11
|
+
throw new Error('ensureRuntimeMetadata requires object carrier');
|
|
12
|
+
}
|
|
13
|
+
const existing = readRuntimeMetadata(carrier);
|
|
14
|
+
if (existing) {
|
|
15
|
+
return existing;
|
|
16
|
+
}
|
|
17
|
+
carrier.__rt = {};
|
|
18
|
+
return carrier.__rt;
|
|
19
|
+
}
|
|
20
|
+
export function cloneRuntimeMetadata(carrier) {
|
|
21
|
+
const rt = readRuntimeMetadata(carrier);
|
|
22
|
+
return rt ? jsonClone(rt) : undefined;
|
|
23
|
+
}
|
|
@@ -3,7 +3,9 @@ export type ToolCallLite = {
|
|
|
3
3
|
name: string;
|
|
4
4
|
args: string;
|
|
5
5
|
};
|
|
6
|
+
export declare function extractToolNamespaceXmlBlocksFromText(text: string): ToolCallLite[] | null;
|
|
6
7
|
export declare function extractParameterXmlToolsFromText(text: string): ToolCallLite[] | null;
|
|
8
|
+
export declare function extractInvokeToolsFromText(text: string): ToolCallLite[] | null;
|
|
7
9
|
export declare function extractBareExecCommandFromText(text: string): ToolCallLite[] | null;
|
|
8
10
|
export declare function extractApplyPatchCallsFromText(text: string): ToolCallLite[] | null;
|
|
9
11
|
export declare function extractExecuteBlocksFromText(text: string): ToolCallLite[] | null;
|