@jsonstudio/llms 0.6.147 → 0.6.187
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.js +15 -1
- package/dist/conversion/compat/actions/auto-thinking.d.ts +6 -0
- package/dist/conversion/compat/actions/auto-thinking.js +25 -0
- package/dist/conversion/compat/actions/field-mapping.d.ts +14 -0
- package/dist/conversion/compat/actions/field-mapping.js +155 -0
- package/dist/conversion/compat/actions/qwen-transform.d.ts +3 -0
- package/dist/conversion/compat/actions/qwen-transform.js +209 -0
- package/dist/conversion/compat/actions/request-rules.d.ts +24 -0
- package/dist/conversion/compat/actions/request-rules.js +63 -0
- package/dist/conversion/compat/actions/response-blacklist.d.ts +14 -0
- package/dist/conversion/compat/actions/response-blacklist.js +85 -0
- package/dist/conversion/compat/actions/response-normalize.d.ts +5 -0
- package/dist/conversion/compat/actions/response-normalize.js +121 -0
- package/dist/conversion/compat/actions/response-validate.d.ts +5 -0
- package/dist/conversion/compat/actions/response-validate.js +76 -0
- package/dist/conversion/compat/actions/snapshot.d.ts +8 -0
- package/dist/conversion/compat/actions/snapshot.js +21 -0
- package/dist/conversion/compat/actions/tool-schema.d.ts +6 -0
- package/dist/conversion/compat/actions/tool-schema.js +91 -0
- package/dist/conversion/compat/actions/universal-shape-filter.d.ts +74 -0
- package/dist/conversion/compat/actions/universal-shape-filter.js +382 -0
- package/dist/conversion/compat/profiles/chat-glm.json +187 -13
- package/dist/conversion/compat/profiles/chat-iflow.json +177 -9
- package/dist/conversion/compat/profiles/chat-lmstudio.json +10 -2
- package/dist/conversion/compat/profiles/chat-qwen.json +14 -10
- package/dist/conversion/hub/pipeline/compat/compat-engine.d.ts +7 -2
- package/dist/conversion/hub/pipeline/compat/compat-engine.js +409 -5
- package/dist/conversion/hub/pipeline/compat/compat-types.d.ts +47 -0
- package/dist/conversion/hub/pipeline/hub-pipeline.d.ts +2 -0
- package/dist/conversion/hub/pipeline/hub-pipeline.js +35 -1
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage3_compat/index.js +2 -2
- package/dist/conversion/hub/pipeline/target-utils.js +3 -0
- package/dist/conversion/hub/response/response-runtime.js +23 -15
- package/dist/conversion/responses/responses-host-policy.d.ts +6 -0
- package/dist/conversion/responses/responses-host-policy.js +14 -0
- package/dist/conversion/responses/responses-openai-bridge.js +51 -2
- package/dist/conversion/shared/anthropic-message-utils.js +6 -0
- package/dist/conversion/shared/bridge-actions.js +1 -1
- package/dist/conversion/shared/bridge-policies.js +0 -1
- package/dist/conversion/shared/responses-conversation-store.js +3 -26
- package/dist/conversion/shared/responses-reasoning-registry.d.ts +4 -0
- package/dist/conversion/shared/responses-reasoning-registry.js +62 -1
- package/dist/conversion/shared/responses-response-utils.js +23 -1
- package/dist/conversion/shared/tool-canonicalizer.d.ts +2 -0
- package/dist/conversion/shared/tool-filter-pipeline.js +11 -0
- package/dist/router/virtual-router/bootstrap.js +218 -39
- package/dist/router/virtual-router/classifier.js +19 -51
- package/dist/router/virtual-router/context-advisor.d.ts +21 -0
- package/dist/router/virtual-router/context-advisor.js +76 -0
- package/dist/router/virtual-router/engine.d.ts +11 -27
- package/dist/router/virtual-router/engine.js +191 -396
- package/dist/router/virtual-router/features.js +24 -607
- package/dist/router/virtual-router/health-manager.js +2 -7
- package/dist/router/virtual-router/message-utils.d.ts +7 -0
- package/dist/router/virtual-router/message-utils.js +66 -0
- package/dist/router/virtual-router/provider-registry.js +6 -2
- package/dist/router/virtual-router/token-estimator.d.ts +2 -0
- package/dist/router/virtual-router/token-estimator.js +16 -0
- package/dist/router/virtual-router/tool-signals.d.ts +13 -0
- package/dist/router/virtual-router/tool-signals.js +403 -0
- package/dist/router/virtual-router/types.d.ts +21 -7
- package/dist/router/virtual-router/types.js +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ResponsesRequestContext } from './responses-openai-bridge.js';
|
|
2
|
+
export interface ResponsesHostPolicyResult {
|
|
3
|
+
shouldStripHostManagedFields: boolean;
|
|
4
|
+
targetProtocol: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function evaluateResponsesHostPolicy(context?: ResponsesRequestContext, targetProtocol?: string): ResponsesHostPolicyResult;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function evaluateResponsesHostPolicy(context, targetProtocol) {
|
|
2
|
+
const protocol = typeof targetProtocol === 'string' && targetProtocol.trim()
|
|
3
|
+
? targetProtocol
|
|
4
|
+
: (typeof context?.targetProtocol === 'string' && context.targetProtocol.trim()
|
|
5
|
+
? context.targetProtocol
|
|
6
|
+
: 'responses');
|
|
7
|
+
const normalized = protocol.toLowerCase();
|
|
8
|
+
const shouldStrip = normalized !== 'openai-responses' &&
|
|
9
|
+
normalized !== 'responses';
|
|
10
|
+
return {
|
|
11
|
+
shouldStripHostManagedFields: shouldStrip,
|
|
12
|
+
targetProtocol: normalized
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ensureBridgeInstructions } from '../shared/bridge-instructions.js';
|
|
2
|
+
import { evaluateResponsesHostPolicy } from './responses-host-policy.js';
|
|
2
3
|
import { convertMessagesToBridgeInput, convertBridgeInputToChatMessages } from '../shared/bridge-message-utils.js';
|
|
3
4
|
import { createToolCallIdTransformer, enforceToolCallIdStyle, resolveToolCallIdStyle, stripInternalToolingMetadata, sanitizeResponsesFunctionName } from '../shared/responses-tool-utils.js';
|
|
4
5
|
import { mapBridgeToolsToChat, mapChatToolsToBridge } from '../shared/tool-mapping.js';
|
|
@@ -8,6 +9,7 @@ import { normalizeMessageReasoningTools } from '../shared/reasoning-tool-normali
|
|
|
8
9
|
import { createBridgeActionState, runBridgeActionPipeline } from '../shared/bridge-actions.js';
|
|
9
10
|
import { resolveBridgePolicy, resolvePolicyActions } from '../shared/bridge-policies.js';
|
|
10
11
|
import { buildResponsesOutputFromChat } from '../shared/responses-output-builder.js';
|
|
12
|
+
import { consumeResponsesPayloadSnapshot, consumeResponsesPassthrough } from '../shared/responses-reasoning-registry.js';
|
|
11
13
|
function isObject(v) {
|
|
12
14
|
return !!v && typeof v === 'object' && !Array.isArray(v);
|
|
13
15
|
}
|
|
@@ -257,12 +259,20 @@ export function buildResponsesRequestFromChat(payload, ctx, extras) {
|
|
|
257
259
|
else if (metadataExtraFields?.include !== undefined && out.include === undefined) {
|
|
258
260
|
out.include = metadataExtraFields.include;
|
|
259
261
|
}
|
|
260
|
-
|
|
262
|
+
const stripHostFields = shouldStripHostManagedFields(ctx);
|
|
263
|
+
if (stripHostFields) {
|
|
264
|
+
delete out.store;
|
|
265
|
+
}
|
|
266
|
+
else if (ctx?.store !== undefined && out.store === undefined) {
|
|
261
267
|
out.store = ctx.store;
|
|
262
268
|
}
|
|
263
269
|
else if (metadataExtraFields?.store !== undefined && out.store === undefined) {
|
|
264
270
|
out.store = metadataExtraFields.store;
|
|
265
271
|
}
|
|
272
|
+
else if (out.store === undefined) {
|
|
273
|
+
// Chat 入口无 store 概念,但 Responses provider 仍要求显式声明。
|
|
274
|
+
out.store = false;
|
|
275
|
+
}
|
|
266
276
|
if (ctx?.toolChoice !== undefined && out.tool_choice === undefined) {
|
|
267
277
|
out.tool_choice = ctx.toolChoice;
|
|
268
278
|
}
|
|
@@ -433,6 +443,17 @@ export function buildResponsesPayloadFromChat(payload, context) {
|
|
|
433
443
|
const response = unwrapData(payload);
|
|
434
444
|
if (!response || typeof response !== 'object')
|
|
435
445
|
return payload;
|
|
446
|
+
const snapshotKey = resolveSnapshotLookupKey(response, context);
|
|
447
|
+
if (snapshotKey) {
|
|
448
|
+
const passthrough = consumeResponsesPassthrough(snapshotKey);
|
|
449
|
+
if (passthrough) {
|
|
450
|
+
return passthrough;
|
|
451
|
+
}
|
|
452
|
+
const snapshot = consumeResponsesPayloadSnapshot(snapshotKey);
|
|
453
|
+
if (snapshot) {
|
|
454
|
+
return snapshot;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
436
457
|
if (response.object === 'response' && Array.isArray(response.output)) {
|
|
437
458
|
return response;
|
|
438
459
|
}
|
|
@@ -499,10 +520,22 @@ export function buildResponsesPayloadFromChat(payload, context) {
|
|
|
499
520
|
out.required_action = outputBuild.requiredAction;
|
|
500
521
|
// Do not inject captured tool results here; keep Chat back-half behavior standard.
|
|
501
522
|
if (context) {
|
|
502
|
-
for (const k of ['metadata', 'parallel_tool_calls', 'tool_choice', 'include'
|
|
523
|
+
for (const k of ['metadata', 'parallel_tool_calls', 'tool_choice', 'include']) {
|
|
503
524
|
if (context[k] !== undefined)
|
|
504
525
|
out[k] = context[k];
|
|
505
526
|
}
|
|
527
|
+
if (!shouldStripHostManagedFields(context) && context.store !== undefined) {
|
|
528
|
+
out.store = context.store;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
if (typeof response.request_id === 'string') {
|
|
532
|
+
out.request_id = response.request_id;
|
|
533
|
+
}
|
|
534
|
+
else if (typeof response.id === 'string') {
|
|
535
|
+
out.request_id = response.id;
|
|
536
|
+
}
|
|
537
|
+
else if (typeof context?.requestId === 'string') {
|
|
538
|
+
out.request_id = context.requestId;
|
|
506
539
|
}
|
|
507
540
|
if (out.metadata) {
|
|
508
541
|
stripInternalToolingMetadata(out.metadata);
|
|
@@ -524,6 +557,22 @@ function unwrapData(value) {
|
|
|
524
557
|
}
|
|
525
558
|
return current;
|
|
526
559
|
}
|
|
560
|
+
function resolveSnapshotLookupKey(response, context) {
|
|
561
|
+
if (typeof response?.request_id === 'string') {
|
|
562
|
+
return response.request_id;
|
|
563
|
+
}
|
|
564
|
+
if (typeof context?.requestId === 'string') {
|
|
565
|
+
return context.requestId;
|
|
566
|
+
}
|
|
567
|
+
if (typeof response?.id === 'string') {
|
|
568
|
+
return response.id;
|
|
569
|
+
}
|
|
570
|
+
return undefined;
|
|
571
|
+
}
|
|
572
|
+
function shouldStripHostManagedFields(context) {
|
|
573
|
+
const result = evaluateResponsesHostPolicy(context, typeof context?.targetProtocol === 'string' ? context?.targetProtocol : undefined);
|
|
574
|
+
return result.shouldStripHostManagedFields;
|
|
575
|
+
}
|
|
527
576
|
export function extractRequestIdFromResponse(response) {
|
|
528
577
|
if (response && typeof response === 'object' && 'metadata' in response && response.metadata && typeof response.metadata === 'object') {
|
|
529
578
|
const meta = response.metadata;
|
|
@@ -336,6 +336,12 @@ export function buildOpenAIChatFromAnthropic(payload) {
|
|
|
336
336
|
request.top_p = body.top_p;
|
|
337
337
|
if (typeof body.stream === 'boolean')
|
|
338
338
|
request.stream = body.stream;
|
|
339
|
+
if (typeof body.id === 'string') {
|
|
340
|
+
request.request_id = body.id;
|
|
341
|
+
}
|
|
342
|
+
else if (typeof body.request_id === 'string') {
|
|
343
|
+
request.request_id = body.request_id;
|
|
344
|
+
}
|
|
339
345
|
if ('tool_choice' in body)
|
|
340
346
|
request.tool_choice = body.tool_choice;
|
|
341
347
|
const normalizedTools = mapAnthropicToolsToChat(body.tools);
|
|
@@ -540,7 +540,7 @@ const captureToolResultsAction = (ctx) => {
|
|
|
540
540
|
name: typeof entry?.name === 'string' ? entry.name : undefined
|
|
541
541
|
}));
|
|
542
542
|
}
|
|
543
|
-
if (
|
|
543
|
+
if (ctx.stage === 'request_outbound' &&
|
|
544
544
|
Array.isArray(ctx.state.capturedToolResults) &&
|
|
545
545
|
ctx.state.capturedToolResults.length) {
|
|
546
546
|
const metadata = ensureMetadataRecord(ctx.state);
|
|
@@ -232,7 +232,6 @@ const ANTHROPIC_POLICY = {
|
|
|
232
232
|
],
|
|
233
233
|
outbound: [
|
|
234
234
|
reasoningAction('anthropic_reasoning'),
|
|
235
|
-
{ name: 'tools.capture-results' },
|
|
236
235
|
toolCallNormalizationAction('anthropic_tool_call'),
|
|
237
236
|
{ name: 'metadata.extra-fields', options: { allowedKeys: ANTHROPIC_ALLOWED_FIELDS } }
|
|
238
237
|
]
|
|
@@ -205,29 +205,16 @@ class ResponsesConversationStore {
|
|
|
205
205
|
}
|
|
206
206
|
resumeConversation(responseId, submitPayload, options) {
|
|
207
207
|
if (typeof responseId !== 'string' || !responseId.trim()) {
|
|
208
|
-
|
|
209
|
-
code: 'RESPONSES_RESUME_MISSING_ID',
|
|
210
|
-
status: 422,
|
|
211
|
-
origin: 'client'
|
|
212
|
-
});
|
|
208
|
+
throw new Error('Responses conversation requires valid response_id');
|
|
213
209
|
}
|
|
214
210
|
this.prune();
|
|
215
211
|
const entry = this.responseIndex.get(responseId);
|
|
216
212
|
if (!entry) {
|
|
217
|
-
|
|
218
|
-
code: 'RESPONSES_RESUME_NOT_FOUND',
|
|
219
|
-
status: 500,
|
|
220
|
-
origin: 'server',
|
|
221
|
-
details: { responseId }
|
|
222
|
-
});
|
|
213
|
+
throw new Error('Responses conversation expired or not found');
|
|
223
214
|
}
|
|
224
215
|
const toolOutputs = Array.isArray(submitPayload.tool_outputs) ? submitPayload.tool_outputs : [];
|
|
225
216
|
if (!toolOutputs.length) {
|
|
226
|
-
|
|
227
|
-
code: 'RESPONSES_RESUME_MISSING_OUTPUTS',
|
|
228
|
-
status: 422,
|
|
229
|
-
origin: 'client'
|
|
230
|
-
});
|
|
217
|
+
throw new Error('tool_outputs array is required when submitting Responses tool results');
|
|
231
218
|
}
|
|
232
219
|
const mergedInput = coerceInputArray(entry.input);
|
|
233
220
|
const normalizedOutputs = normalizeSubmittedToolOutputs(toolOutputs);
|
|
@@ -294,16 +281,6 @@ class ResponsesConversationStore {
|
|
|
294
281
|
}
|
|
295
282
|
const store = new ResponsesConversationStore();
|
|
296
283
|
const RESPONSES_DEBUG = (process.env.ROUTECODEX_RESPONSES_DEBUG || '').trim() === '1';
|
|
297
|
-
function raiseResumeError(message, options) {
|
|
298
|
-
const err = new Error(message);
|
|
299
|
-
err.code = options?.code ?? 'RESPONSES_RESUME_ERROR';
|
|
300
|
-
err.status = options?.status;
|
|
301
|
-
err.origin = options?.origin;
|
|
302
|
-
if (options?.details) {
|
|
303
|
-
err.details = options.details;
|
|
304
|
-
}
|
|
305
|
-
throw err;
|
|
306
|
-
}
|
|
307
284
|
export function captureResponsesRequestContext(args) {
|
|
308
285
|
try {
|
|
309
286
|
if (RESPONSES_DEBUG) {
|
|
@@ -6,3 +6,7 @@ export declare function registerResponsesReasoning(id: unknown, segments: string
|
|
|
6
6
|
export declare function consumeResponsesReasoning(id: unknown): string[] | undefined;
|
|
7
7
|
export declare function registerResponsesOutputTextMeta(id: unknown, meta: ResponsesOutputTextMeta | undefined): void;
|
|
8
8
|
export declare function consumeResponsesOutputTextMeta(id: unknown): ResponsesOutputTextMeta | undefined;
|
|
9
|
+
export declare function registerResponsesPayloadSnapshot(id: unknown, snapshot: Record<string, unknown> | undefined): void;
|
|
10
|
+
export declare function consumeResponsesPayloadSnapshot(id: unknown): Record<string, unknown> | undefined;
|
|
11
|
+
export declare function registerResponsesPassthrough(id: unknown, payload: Record<string, unknown> | undefined): void;
|
|
12
|
+
export declare function consumeResponsesPassthrough(id: unknown): Record<string, unknown> | undefined;
|
|
@@ -11,10 +11,27 @@ function pruneEntry(id) {
|
|
|
11
11
|
const entry = registry.get(id);
|
|
12
12
|
if (!entry)
|
|
13
13
|
return;
|
|
14
|
-
if (!entry.reasoning && !entry.outputText) {
|
|
14
|
+
if (!entry.reasoning && !entry.outputText && !entry.payloadSnapshot && !entry.passthroughPayload) {
|
|
15
15
|
registry.delete(id);
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
|
+
function cloneSnapshot(snapshot) {
|
|
19
|
+
try {
|
|
20
|
+
const structuredCloneImpl = globalThis.structuredClone;
|
|
21
|
+
if (typeof structuredCloneImpl === 'function') {
|
|
22
|
+
return structuredCloneImpl(snapshot);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
/* ignore structuredClone failures */
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
return JSON.parse(JSON.stringify(snapshot));
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
18
35
|
export function registerResponsesReasoning(id, segments) {
|
|
19
36
|
if (typeof id !== 'string')
|
|
20
37
|
return;
|
|
@@ -59,3 +76,47 @@ export function consumeResponsesOutputTextMeta(id) {
|
|
|
59
76
|
pruneEntry(id);
|
|
60
77
|
return value;
|
|
61
78
|
}
|
|
79
|
+
export function registerResponsesPayloadSnapshot(id, snapshot) {
|
|
80
|
+
if (typeof id !== 'string')
|
|
81
|
+
return;
|
|
82
|
+
if (!snapshot || typeof snapshot !== 'object')
|
|
83
|
+
return;
|
|
84
|
+
const clone = cloneSnapshot(snapshot);
|
|
85
|
+
if (!clone)
|
|
86
|
+
return;
|
|
87
|
+
const entry = ensureEntry(id);
|
|
88
|
+
entry.payloadSnapshot = clone;
|
|
89
|
+
}
|
|
90
|
+
export function consumeResponsesPayloadSnapshot(id) {
|
|
91
|
+
if (typeof id !== 'string')
|
|
92
|
+
return undefined;
|
|
93
|
+
const entry = registry.get(id);
|
|
94
|
+
if (!entry?.payloadSnapshot)
|
|
95
|
+
return undefined;
|
|
96
|
+
const clone = cloneSnapshot(entry.payloadSnapshot) ?? entry.payloadSnapshot;
|
|
97
|
+
entry.payloadSnapshot = undefined;
|
|
98
|
+
pruneEntry(id);
|
|
99
|
+
return clone;
|
|
100
|
+
}
|
|
101
|
+
export function registerResponsesPassthrough(id, payload) {
|
|
102
|
+
if (typeof id !== 'string')
|
|
103
|
+
return;
|
|
104
|
+
if (!payload || typeof payload !== 'object')
|
|
105
|
+
return;
|
|
106
|
+
const clone = cloneSnapshot(payload);
|
|
107
|
+
if (!clone)
|
|
108
|
+
return;
|
|
109
|
+
const entry = ensureEntry(id);
|
|
110
|
+
entry.passthroughPayload = clone;
|
|
111
|
+
}
|
|
112
|
+
export function consumeResponsesPassthrough(id) {
|
|
113
|
+
if (typeof id !== 'string')
|
|
114
|
+
return undefined;
|
|
115
|
+
const entry = registry.get(id);
|
|
116
|
+
if (!entry?.passthroughPayload)
|
|
117
|
+
return undefined;
|
|
118
|
+
const clone = cloneSnapshot(entry.passthroughPayload) ?? entry.passthroughPayload;
|
|
119
|
+
entry.passthroughPayload = undefined;
|
|
120
|
+
pruneEntry(id);
|
|
121
|
+
return clone;
|
|
122
|
+
}
|
|
@@ -4,6 +4,7 @@ import { extractOutputSegments } from './output-content-normalizer.js';
|
|
|
4
4
|
import { sanitizeReasoningTaggedText } from './reasoning-utils.js';
|
|
5
5
|
import { createBridgeActionState, runBridgeActionPipeline } from './bridge-actions.js';
|
|
6
6
|
import { resolveBridgePolicy, resolvePolicyActions } from './bridge-policies.js';
|
|
7
|
+
import { registerResponsesPayloadSnapshot, registerResponsesPassthrough } from './responses-reasoning-registry.js';
|
|
7
8
|
function selectCallId(entry) {
|
|
8
9
|
const candidates = [
|
|
9
10
|
entry?.call_id,
|
|
@@ -153,13 +154,27 @@ function collectRawReasoningSegments(response) {
|
|
|
153
154
|
}
|
|
154
155
|
return segments;
|
|
155
156
|
}
|
|
157
|
+
function registerPassthroughSnapshot(payload) {
|
|
158
|
+
const ids = new Set();
|
|
159
|
+
const requestId = typeof payload?.request_id === 'string' ? payload.request_id.trim() : '';
|
|
160
|
+
const id = typeof payload?.id === 'string' ? payload.id.trim() : '';
|
|
161
|
+
if (requestId.length)
|
|
162
|
+
ids.add(requestId);
|
|
163
|
+
if (id.length)
|
|
164
|
+
ids.add(id);
|
|
165
|
+
for (const candidate of ids) {
|
|
166
|
+
registerResponsesPassthrough(candidate, payload);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
156
169
|
export function buildChatResponseFromResponses(payload) {
|
|
157
170
|
if (!payload || typeof payload !== 'object')
|
|
158
171
|
return payload;
|
|
159
172
|
const response = unwrapResponsesResponse(payload);
|
|
160
173
|
if (!response) {
|
|
161
|
-
if (Array.isArray(payload.choices))
|
|
174
|
+
if (Array.isArray(payload.choices)) {
|
|
175
|
+
registerPassthroughSnapshot(payload);
|
|
162
176
|
return payload;
|
|
177
|
+
}
|
|
163
178
|
return payload;
|
|
164
179
|
}
|
|
165
180
|
const id = typeof response.id === 'string' ? response.id : `resp_${Date.now()}`;
|
|
@@ -235,5 +250,12 @@ export function buildChatResponseFromResponses(payload) {
|
|
|
235
250
|
if (usage !== undefined) {
|
|
236
251
|
chat.usage = usage;
|
|
237
252
|
}
|
|
253
|
+
const requestId = typeof response.request_id === 'string'
|
|
254
|
+
? response.request_id
|
|
255
|
+
: (typeof response.id === 'string' ? response.id : undefined);
|
|
256
|
+
if (requestId) {
|
|
257
|
+
chat.request_id = requestId;
|
|
258
|
+
}
|
|
259
|
+
registerResponsesPayloadSnapshot(id, response);
|
|
238
260
|
return chat;
|
|
239
261
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FilterEngine } from '../../filters/index.js';
|
|
2
2
|
import { loadFieldMapConfig } from '../../filters/utils/fieldmap-loader.js';
|
|
3
|
+
import { normalizeChatResponseReasoningTools } from './reasoning-tool-normalizer.js';
|
|
3
4
|
import { createSnapshotWriter } from './snapshot-utils.js';
|
|
4
5
|
const REQUEST_FILTER_STAGES = [
|
|
5
6
|
'request_pre',
|
|
@@ -191,6 +192,16 @@ export async function runChatResponseToolFilters(chatJson, options = {}) {
|
|
|
191
192
|
snapshot(stage, payload);
|
|
192
193
|
};
|
|
193
194
|
recordStage('resp_process_tool_filters_input', chatJson);
|
|
195
|
+
try {
|
|
196
|
+
if (chatJson && typeof chatJson === 'object') {
|
|
197
|
+
normalizeChatResponseReasoningTools(chatJson, {
|
|
198
|
+
idPrefixBase: 'reasoning_choice'
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
// best-effort; do not block response flow on reasoning parsing issues
|
|
204
|
+
}
|
|
194
205
|
const engine = new FilterEngine();
|
|
195
206
|
const registeredStages = new Set();
|
|
196
207
|
const register = (filter) => {
|