@jsonstudio/llms 0.6.3685 → 0.6.3686
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/compat/actions/antigravity-thought-signature-cache.js +2 -22
- package/dist/conversion/compat/actions/deepseek-web-response.js +7 -0
- package/dist/conversion/compat/actions/field-mapping.js +153 -2
- package/dist/conversion/compat/actions/lmstudio-responses-input-stringify.js +104 -3
- package/dist/conversion/hub/node-support.js +1 -1
- package/dist/conversion/hub/operation-table/semantic-mappers/anthropic-mapper.js +1 -9
- package/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper.js +28 -35
- package/dist/conversion/hub/pipeline/hub-pipeline.js +121 -197
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage1_format_parse/index.d.ts +4 -4
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage1_format_parse/index.js +37 -20
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.d.ts +7 -6
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.js +41 -69
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/context-capture-orchestration.d.ts +0 -3
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/context-capture-orchestration.js +1 -2
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/context-factories.js +0 -2
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/index.js +0 -1
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/responses-context-snapshot.d.ts +2 -3
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/responses-context-snapshot.js +5 -18
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/context-merge.d.ts +2 -1
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/context-merge.js +16 -0
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/index.d.ts +1 -1
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/index.js +52 -27
- package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage1_tool_governance/index.d.ts +0 -1
- 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.d.ts +1 -1
- package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage2_route_select/index.js +5 -9
- package/dist/conversion/hub/process/chat-process-continue-execution.js +3 -0
- package/dist/conversion/hub/process/chat-process-media.d.ts +2 -1
- package/dist/conversion/hub/process/chat-process-media.js +63 -9
- package/dist/conversion/hub/process/chat-process-session-usage.d.ts +6 -24
- package/dist/conversion/hub/process/chat-process-session-usage.js +101 -200
- package/dist/conversion/hub/response/provider-response.js +13 -13
- package/dist/conversion/hub/types/chat-envelope.d.ts +0 -1
- package/dist/conversion/pipeline/codecs/v2/openai-openai-pipeline.js +4 -0
- package/dist/conversion/responses/responses-openai-bridge.d.ts +0 -1
- package/dist/conversion/responses/responses-openai-bridge.js +34 -28
- package/dist/conversion/shared/anthropic-message-utils.js +1 -14
- package/dist/conversion/shared/reasoning-normalizer.js +22 -41
- package/dist/conversion/shared/responses-tool-utils.js +2 -3
- package/dist/conversion/shared/tool-governor.js +4 -2
- package/dist/native/router_hotpath_napi.node +0 -0
- package/dist/router/virtual-router/engine/routing-state/store.js +2 -21
- package/dist/router/virtual-router/engine-selection/native-chat-process-governed-filter-semantics.d.ts +0 -1
- package/dist/router/virtual-router/engine-selection/native-chat-process-governed-filter-semantics.js +0 -1
- package/dist/router/virtual-router/engine-selection/native-compat-action-semantics.d.ts +0 -3
- package/dist/router/virtual-router/engine-selection/native-compat-action-semantics.js +0 -72
- package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.d.ts +1 -1
- package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.js +1 -1
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-edge-stage-semantics.d.ts +2 -2
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-edge-stage-semantics.js +96 -80
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-inbound-outbound-semantics.d.ts +1 -0
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-inbound-outbound-semantics.js +29 -0
- package/dist/router/virtual-router/engine-selection/native-router-hotpath-loader.js +2 -6
- package/dist/router/virtual-router/engine.js +6 -9
- package/dist/router/virtual-router/routing-instructions/state.js +27 -37
- package/dist/router/virtual-router/routing-instructions/types.d.ts +4 -6
- package/dist/router/virtual-router/token-estimator.js +0 -21
- package/dist/servertool/handlers/stop-message-auto.js +1 -11
- package/dist/tools/apply-patch/execution-capturer.d.ts +1 -1
- package/dist/tools/apply-patch/execution-capturer.js +2 -1
- package/dist/tools/apply-patch/regression-capturer.js +1 -2
- package/dist/tools/tool-registry.js +2 -1
- package/package.json +1 -1
|
@@ -1,28 +1,8 @@
|
|
|
1
1
|
import { runRespInboundStage3CompatWithNative } from '../../../router/virtual-router/engine-selection/native-hub-pipeline-req-outbound-semantics.js';
|
|
2
|
-
import {
|
|
3
|
-
const PROFILE = 'chat:gemini-cli';
|
|
4
|
-
const DEFAULT_PROVIDER_PROTOCOL = 'gemini-chat';
|
|
5
|
-
const DEFAULT_ENTRY_ENDPOINT = '/v1/chat/completions';
|
|
6
|
-
function buildGeminiCliResponseCompatInput(payload, adapterContext) {
|
|
7
|
-
const nativeContext = buildNativeReqOutboundCompatAdapterContext(adapterContext);
|
|
8
|
-
return {
|
|
9
|
-
payload,
|
|
10
|
-
adapterContext: {
|
|
11
|
-
...nativeContext,
|
|
12
|
-
compatibilityProfile: PROFILE,
|
|
13
|
-
providerProtocol: nativeContext.providerProtocol ??
|
|
14
|
-
adapterContext?.providerProtocol ??
|
|
15
|
-
DEFAULT_PROVIDER_PROTOCOL,
|
|
16
|
-
entryEndpoint: nativeContext.entryEndpoint ??
|
|
17
|
-
adapterContext?.entryEndpoint ??
|
|
18
|
-
DEFAULT_ENTRY_ENDPOINT,
|
|
19
|
-
},
|
|
20
|
-
explicitProfile: PROFILE,
|
|
21
|
-
};
|
|
22
|
-
}
|
|
2
|
+
import { buildGeminiCliCompatInput } from './gemini-cli-request.js';
|
|
23
3
|
export function cacheAntigravityThoughtSignatureFromGeminiResponse(payload, adapterContext) {
|
|
24
4
|
if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
|
|
25
5
|
return payload;
|
|
26
6
|
}
|
|
27
|
-
return runRespInboundStage3CompatWithNative(
|
|
7
|
+
return runRespInboundStage3CompatWithNative(buildGeminiCliCompatInput(payload, adapterContext)).payload;
|
|
28
8
|
}
|
|
@@ -103,6 +103,13 @@ export function applyDeepSeekWebResponseTransform(payload, adapterContext, confi
|
|
|
103
103
|
reason: 'payload is not an object'
|
|
104
104
|
});
|
|
105
105
|
}
|
|
106
|
+
// Fail fast if response is missing required shape (choices array)
|
|
107
|
+
if (!Array.isArray(payload.choices)) {
|
|
108
|
+
// Allow business error format (code + msg) to pass through for separate handling
|
|
109
|
+
if (!('code' in payload && 'msg' in payload)) {
|
|
110
|
+
emitCompatError(new Error('[deepseek-web] invalid response: missing required "choices" array'), adapterContext, payload, { reason: 'missing required response shape' });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
106
113
|
if (isNativeDisabledByEnv()) {
|
|
107
114
|
emitCompatError(makeNativeRequiredError('runRespInboundStage3CompatJson', 'native disabled'), adapterContext, payload, { reason: 'native disabled' });
|
|
108
115
|
}
|
|
@@ -1,4 +1,155 @@
|
|
|
1
|
-
|
|
1
|
+
const MODEL_PREFIX_NORMALIZATION = {
|
|
2
|
+
'gpt-': 'glm-'
|
|
3
|
+
};
|
|
4
|
+
const FINISH_REASON_MAP = {
|
|
5
|
+
tool_calls: 'tool_calls',
|
|
6
|
+
stop: 'stop',
|
|
7
|
+
length: 'length',
|
|
8
|
+
sensitive: 'content_filter',
|
|
9
|
+
network_error: 'error'
|
|
10
|
+
};
|
|
11
|
+
function isRecord(value) {
|
|
12
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
13
|
+
}
|
|
2
14
|
export function applyFieldMappings(payload, mappings) {
|
|
3
|
-
|
|
15
|
+
const result = { ...payload };
|
|
16
|
+
for (const mapping of mappings) {
|
|
17
|
+
applySingleMapping(result, mapping);
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
function applySingleMapping(root, mapping) {
|
|
22
|
+
const sourceValue = getNestedProperty(root, mapping.sourcePath);
|
|
23
|
+
if (sourceValue === undefined) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const transformed = convertType(applyTransform(sourceValue, mapping.transform), mapping.type);
|
|
27
|
+
setNestedProperty(root, mapping.targetPath, transformed);
|
|
28
|
+
}
|
|
29
|
+
function applyTransform(value, transform) {
|
|
30
|
+
if (!transform) {
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
switch (transform) {
|
|
34
|
+
case 'timestamp':
|
|
35
|
+
return typeof value === 'number' ? value : Date.now();
|
|
36
|
+
case 'lowercase':
|
|
37
|
+
return typeof value === 'string' ? value.toLowerCase() : value;
|
|
38
|
+
case 'uppercase':
|
|
39
|
+
return typeof value === 'string' ? value.toUpperCase() : value;
|
|
40
|
+
case 'normalizeModelName':
|
|
41
|
+
if (typeof value === 'string') {
|
|
42
|
+
for (const [prefix, replacement] of Object.entries(MODEL_PREFIX_NORMALIZATION)) {
|
|
43
|
+
if (value.startsWith(prefix)) {
|
|
44
|
+
return value.replace(prefix, replacement);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return value;
|
|
49
|
+
case 'normalizeFinishReason':
|
|
50
|
+
if (typeof value === 'string') {
|
|
51
|
+
return FINISH_REASON_MAP[value] ?? value;
|
|
52
|
+
}
|
|
53
|
+
return value;
|
|
54
|
+
default:
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function convertType(value, targetType) {
|
|
59
|
+
if (value === null || value === undefined) {
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
switch (targetType) {
|
|
63
|
+
case 'string':
|
|
64
|
+
return String(value);
|
|
65
|
+
case 'number': {
|
|
66
|
+
const num = Number(value);
|
|
67
|
+
return Number.isNaN(num) ? 0 : num;
|
|
68
|
+
}
|
|
69
|
+
case 'boolean':
|
|
70
|
+
return Boolean(value);
|
|
71
|
+
case 'object':
|
|
72
|
+
return isRecord(value) ? value : {};
|
|
73
|
+
case 'array':
|
|
74
|
+
return Array.isArray(value) ? value : [value];
|
|
75
|
+
default:
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function getNestedProperty(obj, pathExpression) {
|
|
80
|
+
const keys = pathExpression.split('.');
|
|
81
|
+
if (pathExpression.includes('[*]')) {
|
|
82
|
+
return getWildcardProperty(obj, keys);
|
|
83
|
+
}
|
|
84
|
+
return keys.reduce((current, key) => {
|
|
85
|
+
if (!isRecord(current)) {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
return current[key];
|
|
89
|
+
}, obj);
|
|
90
|
+
}
|
|
91
|
+
function getWildcardProperty(obj, keys) {
|
|
92
|
+
const results = [];
|
|
93
|
+
const processWildcard = (current, keyIndex) => {
|
|
94
|
+
if (keyIndex >= keys.length) {
|
|
95
|
+
results.push(current);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const key = keys[keyIndex];
|
|
99
|
+
if (key === '[*]') {
|
|
100
|
+
if (Array.isArray(current)) {
|
|
101
|
+
current.forEach(item => processWildcard(item, keyIndex + 1));
|
|
102
|
+
}
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (isRecord(current) && current[key] !== undefined) {
|
|
106
|
+
processWildcard(current[key], keyIndex + 1);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
processWildcard(obj, 0);
|
|
110
|
+
return results;
|
|
111
|
+
}
|
|
112
|
+
function setNestedProperty(obj, pathExpression, value) {
|
|
113
|
+
const keys = pathExpression.split('.');
|
|
114
|
+
if (pathExpression.includes('[*]')) {
|
|
115
|
+
setWildcardProperty(obj, keys, value);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const lastKey = keys.pop();
|
|
119
|
+
if (!lastKey) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const target = keys.reduce((current, key) => {
|
|
123
|
+
if (!isRecord(current[key])) {
|
|
124
|
+
current[key] = {};
|
|
125
|
+
}
|
|
126
|
+
return current[key];
|
|
127
|
+
}, obj);
|
|
128
|
+
target[lastKey] = value;
|
|
129
|
+
}
|
|
130
|
+
function setWildcardProperty(obj, keys, value) {
|
|
131
|
+
const processSetWildcard = (current, keyIndex) => {
|
|
132
|
+
if (keyIndex >= keys.length - 1) {
|
|
133
|
+
const lastKey = keys[keys.length - 1].replace('[*]', '');
|
|
134
|
+
if (Array.isArray(current)) {
|
|
135
|
+
current.forEach(item => {
|
|
136
|
+
if (isRecord(item)) {
|
|
137
|
+
item[lastKey] = value;
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const key = keys[keyIndex];
|
|
144
|
+
if (key === '[*]') {
|
|
145
|
+
if (Array.isArray(current)) {
|
|
146
|
+
current.forEach(item => processSetWildcard(item, keyIndex + 1));
|
|
147
|
+
}
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (isRecord(current)) {
|
|
151
|
+
processSetWildcard(current[key], keyIndex + 1);
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
processSetWildcard(obj, 0);
|
|
4
155
|
}
|
|
@@ -1,5 +1,95 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
function isRecord(value) {
|
|
2
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
3
|
+
}
|
|
4
|
+
function extractTextParts(content) {
|
|
5
|
+
const out = [];
|
|
6
|
+
if (typeof content === 'string' && content.trim().length) {
|
|
7
|
+
out.push(content.trim());
|
|
8
|
+
return out;
|
|
9
|
+
}
|
|
10
|
+
if (!Array.isArray(content)) {
|
|
11
|
+
return out;
|
|
12
|
+
}
|
|
13
|
+
for (const part of content) {
|
|
14
|
+
if (!isRecord(part))
|
|
15
|
+
continue;
|
|
16
|
+
const type = typeof part.type === 'string' ? String(part.type).trim().toLowerCase() : '';
|
|
17
|
+
const text = typeof part.text === 'string'
|
|
18
|
+
? part.text
|
|
19
|
+
: typeof part.content === 'string'
|
|
20
|
+
? String(part.content)
|
|
21
|
+
: undefined;
|
|
22
|
+
if (typeof text === 'string' && text.trim().length) {
|
|
23
|
+
out.push(text.trim());
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
// OpenAI Responses content parts often use { type: 'input_text'|'output_text', text: '...' }.
|
|
27
|
+
if ((type === 'input_text' || type === 'output_text') && typeof part.text === 'string') {
|
|
28
|
+
const t = String(part.text).trim();
|
|
29
|
+
if (t.length)
|
|
30
|
+
out.push(t);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
35
|
+
function stringifyInputItems(input) {
|
|
36
|
+
if (!Array.isArray(input))
|
|
37
|
+
return null;
|
|
38
|
+
const chunks = [];
|
|
39
|
+
for (const item of input) {
|
|
40
|
+
if (!isRecord(item))
|
|
41
|
+
continue;
|
|
42
|
+
const type = typeof item.type === 'string' ? String(item.type).trim().toLowerCase() : '';
|
|
43
|
+
const roleCandidate = typeof item.role === 'string' ? String(item.role).trim() : '';
|
|
44
|
+
const messageNode = isRecord(item.message) ? item.message : undefined;
|
|
45
|
+
const nestedRoleCandidate = messageNode && typeof messageNode.role === 'string' ? String(messageNode.role).trim() : '';
|
|
46
|
+
// OpenAI Responses supports message-like items without an explicit `type` field:
|
|
47
|
+
// { role: 'user'|'assistant'|'system', content: [...] }
|
|
48
|
+
if (type === 'message' || (!type && (roleCandidate || nestedRoleCandidate))) {
|
|
49
|
+
const role = roleCandidate ||
|
|
50
|
+
nestedRoleCandidate ||
|
|
51
|
+
'user';
|
|
52
|
+
const contentNode = item.content !== undefined ? item.content : messageNode?.content;
|
|
53
|
+
const parts = extractTextParts(contentNode);
|
|
54
|
+
if (parts.length) {
|
|
55
|
+
chunks.push(`${role}: ${parts.join('\n')}`);
|
|
56
|
+
}
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (type === 'function_call') {
|
|
60
|
+
const name = typeof item.name === 'string' ? String(item.name).trim() : 'tool';
|
|
61
|
+
const args = typeof item.arguments === 'string'
|
|
62
|
+
? String(item.arguments)
|
|
63
|
+
: (() => {
|
|
64
|
+
try {
|
|
65
|
+
return JSON.stringify(item.arguments ?? null);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return String(item.arguments ?? '');
|
|
69
|
+
}
|
|
70
|
+
})();
|
|
71
|
+
chunks.push(`assistant tool_call ${name}: ${args}`);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (type === 'function_call_output') {
|
|
75
|
+
const output = typeof item.output === 'string'
|
|
76
|
+
? String(item.output)
|
|
77
|
+
: (() => {
|
|
78
|
+
try {
|
|
79
|
+
return JSON.stringify(item.output ?? null);
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return String(item.output ?? '');
|
|
83
|
+
}
|
|
84
|
+
})();
|
|
85
|
+
chunks.push(`tool_output: ${output}`);
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (!chunks.length)
|
|
90
|
+
return '';
|
|
91
|
+
return chunks.join('\n\n');
|
|
92
|
+
}
|
|
3
93
|
/**
|
|
4
94
|
* Legacy compatibility shim:
|
|
5
95
|
* Some older LM Studio builds rejected the array form of `input` ("Invalid type for 'input'").
|
|
@@ -20,5 +110,16 @@ export function stringifyLmstudioResponsesInput(payload, adapterContext) {
|
|
|
20
110
|
if (!adapterContext || adapterContext.providerProtocol !== 'openai-responses') {
|
|
21
111
|
return payload;
|
|
22
112
|
}
|
|
23
|
-
|
|
113
|
+
const record = payload;
|
|
114
|
+
const input = record.input;
|
|
115
|
+
if (!Array.isArray(input)) {
|
|
116
|
+
return payload;
|
|
117
|
+
}
|
|
118
|
+
const flattened = stringifyInputItems(input);
|
|
119
|
+
if (flattened === null) {
|
|
120
|
+
return payload;
|
|
121
|
+
}
|
|
122
|
+
const instructions = typeof record.instructions === 'string' ? record.instructions.trim() : '';
|
|
123
|
+
record.input = instructions.length ? `${instructions}\n\n${flattened}`.trim() : flattened;
|
|
124
|
+
return payload;
|
|
24
125
|
}
|
|
@@ -108,7 +108,7 @@ function deriveAdapterContext(context, fallbackProtocol) {
|
|
|
108
108
|
(typeof metadata.providerProtocol === 'string' ? metadata.providerProtocol : undefined) ||
|
|
109
109
|
fallbackProtocol;
|
|
110
110
|
const streamingHint = metadata.stream === true ? 'force' : metadata.stream === false ? 'disable' : 'auto';
|
|
111
|
-
const toolCallIdStyle = normalizeToolCallIdStyleCandidate(
|
|
111
|
+
const toolCallIdStyle = normalizeToolCallIdStyleCandidate(metadata.toolCallIdStyle);
|
|
112
112
|
return {
|
|
113
113
|
requestId: context.request.id,
|
|
114
114
|
entryEndpoint: (typeof requestContext.entryEndpoint === 'string' ? requestContext.entryEndpoint : context.request.endpoint) ||
|
|
@@ -29,8 +29,7 @@ const ANTHROPIC_TOP_LEVEL_FIELDS = new Set([
|
|
|
29
29
|
'metadata',
|
|
30
30
|
'stream',
|
|
31
31
|
'tool_choice',
|
|
32
|
-
'thinking'
|
|
33
|
-
'disable_parallel_tool_use'
|
|
32
|
+
'thinking'
|
|
34
33
|
]);
|
|
35
34
|
const PASSTHROUGH_METADATA_PREFIX = 'rcc_passthrough_';
|
|
36
35
|
const PASSTHROUGH_PARAMETERS = ['tool_choice'];
|
|
@@ -95,9 +94,6 @@ function collectParameters(payload) {
|
|
|
95
94
|
params[key] = payload[key];
|
|
96
95
|
}
|
|
97
96
|
}
|
|
98
|
-
if (typeof payload.disable_parallel_tool_use === 'boolean') {
|
|
99
|
-
params.parallel_tool_calls = !payload.disable_parallel_tool_use;
|
|
100
|
-
}
|
|
101
97
|
if (Array.isArray(payload.stop_sequences)) {
|
|
102
98
|
params.stop = payload.stop_sequences;
|
|
103
99
|
}
|
|
@@ -388,10 +384,6 @@ export class AnthropicSemanticMapper {
|
|
|
388
384
|
}
|
|
389
385
|
if (trimmedParameters) {
|
|
390
386
|
for (const [key, value] of Object.entries(trimmedParameters)) {
|
|
391
|
-
if (key === 'parallel_tool_calls') {
|
|
392
|
-
baseRequest.parallel_tool_calls = value;
|
|
393
|
-
continue;
|
|
394
|
-
}
|
|
395
387
|
if (ANTHROPIC_TOP_LEVEL_FIELDS.has(key) || key === 'stop') {
|
|
396
388
|
if (key === 'messages' || key === 'tools') {
|
|
397
389
|
continue;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { isJsonObject, jsonClone } from '../../types/json.js';
|
|
2
2
|
import { captureResponsesContext, buildChatRequestFromResponses, buildResponsesRequestFromChat } from '../../../responses/responses-openai-bridge.js';
|
|
3
|
+
import { logHubStageTiming } from '../../pipeline/hub-stage-timing.js';
|
|
3
4
|
import { maybeAugmentApplyPatchErrorContent } from './chat-mapper.js';
|
|
4
5
|
import { mapReqInboundBridgeToolsToChatWithNative, mapReqInboundResumeToolOutputsDetailedWithNative } from '../../../../router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.js';
|
|
5
|
-
import { mapOpenaiChatToChatWithNative } from '../../../../router/virtual-router/engine-selection/native-hub-pipeline-semantic-mappers.js';
|
|
6
|
-
import { runResponsesOpenAIRequestCodecWithNative } from '../../../../router/virtual-router/engine-selection/native-compat-action-semantics.js';
|
|
7
6
|
const RESPONSES_PARAMETER_KEYS = [
|
|
8
7
|
'model',
|
|
9
8
|
'temperature',
|
|
@@ -392,35 +391,22 @@ function buildSubmitToolOutputsPayload(chat, ctx, responsesContext) {
|
|
|
392
391
|
}
|
|
393
392
|
export class ResponsesSemanticMapper {
|
|
394
393
|
async toChat(format, ctx) {
|
|
394
|
+
const requestId = typeof ctx.requestId === 'string' && ctx.requestId.trim().length ? ctx.requestId : 'unknown';
|
|
395
395
|
const payload = format.payload || {};
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
const request = isJsonObject(codecResult.request)
|
|
399
|
-
? codecResult.request
|
|
400
|
-
: undefined;
|
|
401
|
-
const responsesContext = isJsonObject(codecResult.context)
|
|
402
|
-
? codecResult.context
|
|
403
|
-
: undefined;
|
|
404
|
-
if (request && responsesContext) {
|
|
405
|
-
const chatEnvelope = mapOpenaiChatToChatWithNative(request, ctx);
|
|
406
|
-
const missingFields = [];
|
|
407
|
-
const toolOutputs = mapToolOutputs(payload.tool_outputs, missingFields);
|
|
408
|
-
if (toolOutputs?.length) {
|
|
409
|
-
chatEnvelope.toolOutputs = toolOutputs;
|
|
410
|
-
}
|
|
411
|
-
if (missingFields.length) {
|
|
412
|
-
const metadata = chatEnvelope.metadata && typeof chatEnvelope.metadata === 'object'
|
|
413
|
-
? chatEnvelope.metadata
|
|
414
|
-
: { context: ctx };
|
|
415
|
-
metadata.missingFields = missingFields;
|
|
416
|
-
chatEnvelope.metadata = metadata;
|
|
417
|
-
}
|
|
418
|
-
chatEnvelope.semantics = attachResponsesSemantics(chatEnvelope.semantics, responsesContext, undefined);
|
|
419
|
-
return chatEnvelope;
|
|
420
|
-
}
|
|
421
|
-
}
|
|
396
|
+
logHubStageTiming(requestId, 'req_inbound.responses.capture_context', 'start');
|
|
397
|
+
const captureStart = Date.now();
|
|
422
398
|
const responsesContext = captureResponsesContext(payload, { route: { requestId: ctx.requestId } });
|
|
399
|
+
logHubStageTiming(requestId, 'req_inbound.responses.capture_context', 'completed', {
|
|
400
|
+
elapsedMs: Date.now() - captureStart,
|
|
401
|
+
forceLog: true
|
|
402
|
+
});
|
|
403
|
+
logHubStageTiming(requestId, 'req_inbound.responses.build_chat_request', 'start');
|
|
404
|
+
const buildChatStart = Date.now();
|
|
423
405
|
const { request, toolsNormalized } = buildChatRequestFromResponses(payload, responsesContext);
|
|
406
|
+
logHubStageTiming(requestId, 'req_inbound.responses.build_chat_request', 'completed', {
|
|
407
|
+
elapsedMs: Date.now() - buildChatStart,
|
|
408
|
+
forceLog: true
|
|
409
|
+
});
|
|
424
410
|
const missingFields = [];
|
|
425
411
|
const messages = normalizeMessages(request.messages, missingFields);
|
|
426
412
|
let toolOutputs = mapToolOutputs(payload.tool_outputs, missingFields);
|
|
@@ -441,6 +427,7 @@ export class ResponsesSemanticMapper {
|
|
|
441
427
|
};
|
|
442
428
|
}
|
|
443
429
|
async fromChat(chat, ctx) {
|
|
430
|
+
const requestId = typeof ctx.requestId === 'string' && ctx.requestId.trim().length ? ctx.requestId : 'unknown';
|
|
444
431
|
const envelopeMetadata = chat.metadata && isJsonObject(chat.metadata) ? chat.metadata : undefined;
|
|
445
432
|
const responsesContext = selectResponsesContextSnapshot(chat, envelopeMetadata);
|
|
446
433
|
if (isSubmitToolOutputsEndpoint(ctx)) {
|
|
@@ -465,13 +452,19 @@ export class ResponsesSemanticMapper {
|
|
|
465
452
|
messages: chat.messages,
|
|
466
453
|
tools: chat.tools
|
|
467
454
|
};
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
455
|
+
if (!Array.isArray(responsesContext.originalSystemMessages) || responsesContext.originalSystemMessages.length === 0) {
|
|
456
|
+
const originalSystemMessages = (chat.messages || [])
|
|
457
|
+
.filter((message) => Boolean(message && typeof message === 'object' && message.role === 'system'))
|
|
458
|
+
.map(message => serializeSystemContent(message))
|
|
459
|
+
.filter((content) => typeof content === 'string' && content.length > 0);
|
|
460
|
+
responsesContext.originalSystemMessages = originalSystemMessages;
|
|
461
|
+
}
|
|
462
|
+
logHubStageTiming(requestId, 'req_outbound.responses.build_request', 'start');
|
|
463
|
+
const buildRequestStart = Date.now();
|
|
464
|
+
const responsesResult = buildResponsesRequestFromChat(requestShape, responsesContext);
|
|
465
|
+
logHubStageTiming(requestId, 'req_outbound.responses.build_request', 'completed', {
|
|
466
|
+
elapsedMs: Date.now() - buildRequestStart,
|
|
467
|
+
forceLog: true
|
|
475
468
|
});
|
|
476
469
|
const responses = responsesResult.request;
|
|
477
470
|
if (chat.parameters && chat.parameters.stream !== undefined) {
|