@jsonstudio/llms 0.6.3541 → 0.6.3685
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 +23 -114
- package/dist/conversion/compat/actions/auto-thinking.js +3 -2
- package/dist/conversion/compat/actions/deepseek-web-response.js +9 -50
- package/dist/conversion/compat/actions/field-mapping.js +2 -153
- package/dist/conversion/compat/actions/gemini-cli-request.d.ts +2 -0
- package/dist/conversion/compat/actions/gemini-cli-request.js +1 -1
- package/dist/conversion/compat/actions/glm-history-image-trim.js +3 -37
- package/dist/conversion/compat/actions/glm-image-content.js +3 -32
- package/dist/conversion/compat/actions/glm-native-compat.d.ts +6 -0
- package/dist/conversion/compat/actions/glm-native-compat.js +34 -0
- package/dist/conversion/compat/actions/glm-vision-prompt.js +3 -76
- package/dist/conversion/compat/actions/glm-web-search.js +10 -43
- package/dist/conversion/compat/actions/iflow-kimi-cli-defaults.js +4 -53
- package/dist/conversion/compat/actions/iflow-kimi-history-media-placeholder.js +5 -141
- package/dist/conversion/compat/actions/iflow-kimi-thinking-reasoning-fill.js +7 -28
- package/dist/conversion/compat/actions/iflow-native-compat.d.ts +6 -0
- package/dist/conversion/compat/actions/iflow-native-compat.js +36 -0
- package/dist/conversion/compat/actions/iflow-response-body-unwrap.js +4 -119
- package/dist/conversion/compat/actions/iflow-web-search.js +14 -55
- package/dist/conversion/compat/actions/lmstudio-responses-input-stringify.js +3 -104
- package/dist/conversion/hub/node-support.js +1 -1
- package/dist/conversion/hub/operation-table/semantic-mappers/anthropic-mapper.js +9 -1
- package/dist/conversion/hub/operation-table/semantic-mappers/archive/chat-mapper.archive.js +5 -0
- package/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper.js +34 -14
- package/dist/conversion/hub/pipeline/hub-pipeline.d.ts +14 -14
- package/dist/conversion/hub/pipeline/hub-pipeline.js +838 -524
- package/dist/conversion/hub/pipeline/hub-stage-timing.d.ts +6 -0
- package/dist/conversion/hub/pipeline/hub-stage-timing.js +178 -0
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage1_format_parse/index.js +6 -4
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.js +46 -0
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/context-capture-orchestration.d.ts +3 -0
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/context-capture-orchestration.js +2 -1
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/context-factories.js +2 -0
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/index.js +1 -0
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/responses-context-snapshot.d.ts +3 -2
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/responses-context-snapshot.js +18 -5
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/context-merge.d.ts +1 -2
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/context-merge.js +0 -16
- 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 +30 -12
- package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage1_tool_governance/index.d.ts +1 -0
- package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage1_tool_governance/index.js +5 -2
- 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 +9 -5
- package/dist/conversion/hub/process/chat-process-continue-execution.js +2 -4
- package/dist/conversion/hub/process/chat-process-governance-orchestration.js +3 -1
- package/dist/conversion/hub/process/chat-process-media.d.ts +1 -0
- package/dist/conversion/hub/process/chat-process-media.js +36 -0
- package/dist/conversion/hub/process/chat-process-session-usage.d.ts +25 -0
- package/dist/conversion/hub/process/chat-process-session-usage.js +246 -0
- package/dist/conversion/hub/response/provider-response.js +13 -0
- package/dist/conversion/hub/types/chat-envelope.d.ts +1 -0
- package/dist/conversion/pipeline/codecs/v2/openai-openai-pipeline.js +0 -4
- package/dist/conversion/responses/responses-openai-bridge/response-payload.js +0 -12
- package/dist/conversion/responses/responses-openai-bridge/types.d.ts +1 -9
- package/dist/conversion/responses/responses-openai-bridge.d.ts +1 -0
- package/dist/conversion/responses/responses-openai-bridge.js +51 -24
- package/dist/conversion/shared/anthropic-message-utils.js +14 -1
- package/dist/conversion/shared/reasoning-normalizer.js +61 -0
- package/dist/conversion/shared/tool-governor.js +2 -4
- package/dist/native/router_hotpath_napi.node +0 -0
- package/dist/quota/quota-state.js +1 -6
- package/dist/router/virtual-router/bootstrap/profile-builder.js +1 -0
- package/dist/router/virtual-router/bootstrap/provider-normalization.d.ts +1 -0
- package/dist/router/virtual-router/bootstrap/provider-normalization.js +6 -0
- package/dist/router/virtual-router/bootstrap.js +1 -6
- package/dist/router/virtual-router/engine/routing-state/store.js +21 -2
- package/dist/router/virtual-router/engine-legacy.js +43 -0
- package/dist/router/virtual-router/engine-logging.d.ts +3 -0
- package/dist/router/virtual-router/engine-logging.js +29 -3
- package/dist/router/virtual-router/engine-selection/native-chat-process-governed-filter-semantics.d.ts +1 -0
- package/dist/router/virtual-router/engine-selection/native-chat-process-governed-filter-semantics.js +1 -0
- package/dist/router/virtual-router/engine-selection/native-compat-action-semantics.d.ts +3 -0
- package/dist/router/virtual-router/engine-selection/native-compat-action-semantics.js +72 -0
- 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-inbound-outbound-semantics.d.ts +0 -1
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-inbound-outbound-semantics.js +0 -29
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-process-semantics.d.ts +1 -0
- package/dist/router/virtual-router/engine-selection/native-router-hotpath-loader.js +6 -2
- package/dist/router/virtual-router/engine.js +28 -13
- package/dist/router/virtual-router/provider-registry.js +1 -0
- package/dist/router/virtual-router/routing-instructions/state.js +44 -2
- package/dist/router/virtual-router/routing-instructions/types.d.ts +6 -0
- package/dist/router/virtual-router/token-estimator.js +21 -0
- package/dist/router/virtual-router/types.d.ts +7 -0
- package/dist/servertool/engine.js +3 -34
- package/dist/servertool/handlers/followup-request-builder.js +0 -6
- package/dist/servertool/handlers/gemini-empty-reply-continue.js +3 -274
- package/dist/servertool/handlers/stop-message-auto/runtime-utils.d.ts +0 -3
- package/dist/servertool/handlers/stop-message-auto/runtime-utils.js +0 -29
- package/dist/servertool/handlers/stop-message-auto.js +11 -9
- package/dist/servertool/handlers/vision.js +4 -1
- package/dist/servertool/server-side-tools.d.ts +0 -1
- package/dist/servertool/server-side-tools.js +67 -5
- package/dist/tools/apply-patch/execution-capturer.d.ts +1 -1
- package/dist/tools/apply-patch/execution-capturer.js +1 -2
- package/dist/tools/apply-patch/regression-capturer.js +2 -1
- package/dist/tools/tool-registry.js +1 -2
- package/package.json +1 -1
|
@@ -10,6 +10,42 @@ export function stripHistoricalImageAttachments(messages) {
|
|
|
10
10
|
}
|
|
11
11
|
return stripped.messages;
|
|
12
12
|
}
|
|
13
|
+
const INLINE_MEDIA_DATA_RE = /data:(image|video)\/[a-z0-9.+-]+;base64,[a-z0-9+/=\s]+/i;
|
|
14
|
+
function isVisualToolMessage(message) {
|
|
15
|
+
if (!message || typeof message !== 'object') {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
if (message.role !== 'tool') {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
const name = typeof message.name === 'string' ? message.name.trim().toLowerCase() : '';
|
|
22
|
+
if (name === 'view_image') {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
const content = typeof message.content === 'string' ? message.content : '';
|
|
26
|
+
return INLINE_MEDIA_DATA_RE.test(content);
|
|
27
|
+
}
|
|
28
|
+
export function stripHistoricalVisualToolOutputs(messages) {
|
|
29
|
+
if (!Array.isArray(messages) || messages.length === 0) {
|
|
30
|
+
return messages;
|
|
31
|
+
}
|
|
32
|
+
let changed = false;
|
|
33
|
+
const next = messages.map((message) => {
|
|
34
|
+
if (!isVisualToolMessage(message)) {
|
|
35
|
+
return message;
|
|
36
|
+
}
|
|
37
|
+
const content = typeof message.content === 'string' ? message.content : '';
|
|
38
|
+
if (!INLINE_MEDIA_DATA_RE.test(content)) {
|
|
39
|
+
return message;
|
|
40
|
+
}
|
|
41
|
+
changed = true;
|
|
42
|
+
return {
|
|
43
|
+
...message,
|
|
44
|
+
content: '[Image omitted]'
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
return changed ? next : messages;
|
|
48
|
+
}
|
|
13
49
|
export function containsImageAttachment(messages) {
|
|
14
50
|
if (!Array.isArray(messages) || !messages.length) {
|
|
15
51
|
return false;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ProcessedRequest, StandardizedRequest } from '../types/standardized.js';
|
|
2
|
+
type SessionScopeMetadata = {
|
|
3
|
+
sessionId?: string;
|
|
4
|
+
conversationId?: string;
|
|
5
|
+
};
|
|
6
|
+
type ChatProcessSessionRequestSnapshot = Pick<StandardizedRequest | ProcessedRequest, 'messages' | 'tools' | 'parameters'>;
|
|
7
|
+
export interface ChatProcessSessionInputEstimateResult {
|
|
8
|
+
tokens?: number;
|
|
9
|
+
scope?: string;
|
|
10
|
+
mode: 'session_reuse' | 'session_delta' | 'unavailable';
|
|
11
|
+
reason?: 'missing_scope' | 'missing_state' | 'missing_previous_usage' | 'tools_signature_changed' | 'parameters_signature_changed' | 'message_count_regressed' | 'boundary_mismatch';
|
|
12
|
+
previousMessageCount?: number;
|
|
13
|
+
appendedMessageCount?: number;
|
|
14
|
+
hasPreviousTokens?: boolean;
|
|
15
|
+
hasPreviousMessageCount?: boolean;
|
|
16
|
+
hasToolsSignature?: boolean;
|
|
17
|
+
hasParametersSignature?: boolean;
|
|
18
|
+
previousParametersSignatureDigest?: string;
|
|
19
|
+
currentParametersSignatureDigest?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function estimateChatProcessSessionInputTokens(metadata: SessionScopeMetadata, request: StandardizedRequest | ProcessedRequest): number | undefined;
|
|
22
|
+
export declare function estimateChatProcessSessionInputTokensDetailed(metadata: SessionScopeMetadata, request: StandardizedRequest | ProcessedRequest): ChatProcessSessionInputEstimateResult;
|
|
23
|
+
export declare function saveChatProcessSessionInputEstimate(metadata: SessionScopeMetadata, request: StandardizedRequest | ProcessedRequest, estimatedInputTokens: number): void;
|
|
24
|
+
export declare function saveChatProcessSessionActualUsage(metadata: SessionScopeMetadata, usageRaw: unknown, requestSnapshot?: ChatProcessSessionRequestSnapshot): void;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { loadRoutingInstructionStateSync, saveRoutingInstructionStateSync } from '../../../router/virtual-router/sticky-session-store.js';
|
|
2
|
+
import { countRequestTokens } from '../../../router/virtual-router/token-counter.js';
|
|
3
|
+
function buildEmptyRoutingInstructionState() {
|
|
4
|
+
return {
|
|
5
|
+
forcedTarget: undefined,
|
|
6
|
+
stickyTarget: undefined,
|
|
7
|
+
preferTarget: undefined,
|
|
8
|
+
allowedProviders: new Set(),
|
|
9
|
+
disabledProviders: new Set(),
|
|
10
|
+
disabledKeys: new Map(),
|
|
11
|
+
disabledModels: new Map(),
|
|
12
|
+
stopMessageSource: undefined,
|
|
13
|
+
stopMessageText: undefined,
|
|
14
|
+
stopMessageMaxRepeats: undefined,
|
|
15
|
+
stopMessageUsed: undefined,
|
|
16
|
+
stopMessageUpdatedAt: undefined,
|
|
17
|
+
stopMessageLastUsedAt: undefined,
|
|
18
|
+
stopMessageStageMode: undefined,
|
|
19
|
+
stopMessageAiMode: undefined,
|
|
20
|
+
stopMessageAiSeedPrompt: undefined,
|
|
21
|
+
stopMessageAiHistory: undefined,
|
|
22
|
+
preCommandSource: undefined,
|
|
23
|
+
preCommandScriptPath: undefined,
|
|
24
|
+
preCommandUpdatedAt: undefined,
|
|
25
|
+
chatProcessInputTokens: undefined,
|
|
26
|
+
chatProcessMessageCount: undefined,
|
|
27
|
+
chatProcessToolsSignature: undefined,
|
|
28
|
+
chatProcessParametersSignature: undefined,
|
|
29
|
+
chatProcessBoundarySignature: undefined,
|
|
30
|
+
chatProcessUpdatedAt: undefined
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function readScope(metadata) {
|
|
34
|
+
const sessionId = typeof metadata.sessionId === 'string' ? metadata.sessionId.trim() : '';
|
|
35
|
+
if (sessionId) {
|
|
36
|
+
return `session:${sessionId}`;
|
|
37
|
+
}
|
|
38
|
+
const conversationId = typeof metadata.conversationId === 'string' ? metadata.conversationId.trim() : '';
|
|
39
|
+
if (conversationId) {
|
|
40
|
+
return `conversation:${conversationId}`;
|
|
41
|
+
}
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
function stableSignature(value) {
|
|
45
|
+
try {
|
|
46
|
+
return JSON.stringify(value ?? null) || 'null';
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return 'unserializable';
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function messageBoundarySignature(message) {
|
|
53
|
+
if (!message) {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
return stableSignature({
|
|
57
|
+
role: message.role,
|
|
58
|
+
content: message.content ?? null,
|
|
59
|
+
tool_calls: Array.isArray(message.tool_calls) ? message.tool_calls : [],
|
|
60
|
+
tool_call_id: message.tool_call_id ?? null,
|
|
61
|
+
name: message.name ?? null
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function coercePositiveInteger(value) {
|
|
65
|
+
return typeof value === 'number' && Number.isFinite(value) && value > 0
|
|
66
|
+
? Math.max(1, Math.round(value))
|
|
67
|
+
: undefined;
|
|
68
|
+
}
|
|
69
|
+
function digestSignature(value) {
|
|
70
|
+
if (!value) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
let hash = 2166136261;
|
|
74
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
75
|
+
hash ^= value.charCodeAt(i);
|
|
76
|
+
hash = Math.imul(hash, 16777619);
|
|
77
|
+
}
|
|
78
|
+
return `${value.length}:${(hash >>> 0).toString(16)}`;
|
|
79
|
+
}
|
|
80
|
+
function hasReusableSessionUsageShape(state) {
|
|
81
|
+
if (!state) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
const previousTokens = coercePositiveInteger(state.chatProcessInputTokens);
|
|
85
|
+
const previousMessageCount = typeof state.chatProcessMessageCount === 'number' &&
|
|
86
|
+
Number.isFinite(state.chatProcessMessageCount) &&
|
|
87
|
+
state.chatProcessMessageCount >= 0;
|
|
88
|
+
const toolsSignature = typeof state.chatProcessToolsSignature === 'string' && state.chatProcessToolsSignature.trim().length > 0;
|
|
89
|
+
const parametersSignature = typeof state.chatProcessParametersSignature === 'string' &&
|
|
90
|
+
state.chatProcessParametersSignature.trim().length > 0;
|
|
91
|
+
return previousTokens !== undefined && previousMessageCount && toolsSignature && parametersSignature;
|
|
92
|
+
}
|
|
93
|
+
function applyRequestSnapshotToState(state, request) {
|
|
94
|
+
if (!request || typeof request !== 'object') {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
const messages = Array.isArray(request.messages) ? request.messages : null;
|
|
98
|
+
if (!messages) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
state.chatProcessMessageCount = messages.length;
|
|
102
|
+
state.chatProcessToolsSignature = stableSignature(request.tools ?? null);
|
|
103
|
+
state.chatProcessParametersSignature = stableSignature(request.parameters ?? null);
|
|
104
|
+
state.chatProcessBoundarySignature = messageBoundarySignature(messages[messages.length - 1]);
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
export function estimateChatProcessSessionInputTokens(metadata, request) {
|
|
108
|
+
return estimateChatProcessSessionInputTokensDetailed(metadata, request).tokens;
|
|
109
|
+
}
|
|
110
|
+
export function estimateChatProcessSessionInputTokensDetailed(metadata, request) {
|
|
111
|
+
const scope = readScope(metadata);
|
|
112
|
+
if (!scope) {
|
|
113
|
+
return {
|
|
114
|
+
scope,
|
|
115
|
+
mode: 'unavailable',
|
|
116
|
+
reason: 'missing_scope'
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
const state = loadRoutingInstructionStateSync(scope);
|
|
120
|
+
if (!state) {
|
|
121
|
+
return {
|
|
122
|
+
scope,
|
|
123
|
+
mode: 'unavailable',
|
|
124
|
+
reason: 'missing_state'
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const previousTokens = coercePositiveInteger(state.chatProcessInputTokens);
|
|
128
|
+
const previousMessageCount = typeof state.chatProcessMessageCount === 'number' &&
|
|
129
|
+
Number.isFinite(state.chatProcessMessageCount) &&
|
|
130
|
+
state.chatProcessMessageCount >= 0
|
|
131
|
+
? Math.max(0, Math.floor(state.chatProcessMessageCount))
|
|
132
|
+
: undefined;
|
|
133
|
+
if (previousTokens === undefined || previousMessageCount === undefined) {
|
|
134
|
+
return {
|
|
135
|
+
scope,
|
|
136
|
+
mode: 'unavailable',
|
|
137
|
+
reason: 'missing_previous_usage',
|
|
138
|
+
hasPreviousTokens: previousTokens !== undefined,
|
|
139
|
+
hasPreviousMessageCount: previousMessageCount !== undefined,
|
|
140
|
+
hasToolsSignature: Boolean(state.chatProcessToolsSignature),
|
|
141
|
+
hasParametersSignature: Boolean(state.chatProcessParametersSignature)
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
const currentToolsSignature = stableSignature(request.tools ?? null);
|
|
145
|
+
const currentParametersSignature = stableSignature(request.parameters ?? null);
|
|
146
|
+
if (state.chatProcessToolsSignature !== currentToolsSignature) {
|
|
147
|
+
return {
|
|
148
|
+
scope,
|
|
149
|
+
mode: 'unavailable',
|
|
150
|
+
reason: 'tools_signature_changed',
|
|
151
|
+
previousMessageCount,
|
|
152
|
+
hasPreviousTokens: true,
|
|
153
|
+
hasPreviousMessageCount: true
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
if (state.chatProcessParametersSignature !== currentParametersSignature) {
|
|
157
|
+
return {
|
|
158
|
+
scope,
|
|
159
|
+
mode: 'unavailable',
|
|
160
|
+
reason: 'parameters_signature_changed',
|
|
161
|
+
previousMessageCount,
|
|
162
|
+
hasPreviousTokens: true,
|
|
163
|
+
hasPreviousMessageCount: true,
|
|
164
|
+
previousParametersSignatureDigest: digestSignature(state.chatProcessParametersSignature),
|
|
165
|
+
currentParametersSignatureDigest: digestSignature(currentParametersSignature)
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
const messages = Array.isArray(request.messages) ? request.messages : [];
|
|
169
|
+
if (previousMessageCount > messages.length) {
|
|
170
|
+
return {
|
|
171
|
+
scope,
|
|
172
|
+
mode: 'unavailable',
|
|
173
|
+
reason: 'message_count_regressed',
|
|
174
|
+
previousMessageCount
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
if (previousMessageCount > 0) {
|
|
178
|
+
const boundary = messageBoundarySignature(messages[previousMessageCount - 1]);
|
|
179
|
+
if ((state.chatProcessBoundarySignature || undefined) !== boundary) {
|
|
180
|
+
return {
|
|
181
|
+
scope,
|
|
182
|
+
mode: 'unavailable',
|
|
183
|
+
reason: 'boundary_mismatch',
|
|
184
|
+
previousMessageCount
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
const appendedMessages = messages.slice(previousMessageCount);
|
|
189
|
+
if (appendedMessages.length === 0) {
|
|
190
|
+
return {
|
|
191
|
+
tokens: previousTokens,
|
|
192
|
+
scope,
|
|
193
|
+
mode: 'session_reuse',
|
|
194
|
+
previousMessageCount,
|
|
195
|
+
appendedMessageCount: 0
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
const delta = countRequestTokens({
|
|
199
|
+
model: request.model,
|
|
200
|
+
messages: appendedMessages,
|
|
201
|
+
tools: undefined,
|
|
202
|
+
parameters: {},
|
|
203
|
+
metadata: request.metadata ?? { originalEndpoint: '' }
|
|
204
|
+
});
|
|
205
|
+
return {
|
|
206
|
+
tokens: previousTokens + delta,
|
|
207
|
+
scope,
|
|
208
|
+
mode: 'session_delta',
|
|
209
|
+
previousMessageCount,
|
|
210
|
+
appendedMessageCount: appendedMessages.length
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
export function saveChatProcessSessionInputEstimate(metadata, request, estimatedInputTokens) {
|
|
214
|
+
const scope = readScope(metadata);
|
|
215
|
+
const normalized = coercePositiveInteger(estimatedInputTokens);
|
|
216
|
+
if (!scope || normalized === undefined) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
const state = loadRoutingInstructionStateSync(scope) ?? buildEmptyRoutingInstructionState();
|
|
220
|
+
const messages = Array.isArray(request.messages) ? request.messages : [];
|
|
221
|
+
state.chatProcessInputTokens = normalized;
|
|
222
|
+
state.chatProcessMessageCount = messages.length;
|
|
223
|
+
state.chatProcessToolsSignature = stableSignature(request.tools ?? null);
|
|
224
|
+
state.chatProcessParametersSignature = stableSignature(request.parameters ?? null);
|
|
225
|
+
state.chatProcessBoundarySignature = messageBoundarySignature(messages[messages.length - 1]);
|
|
226
|
+
state.chatProcessUpdatedAt = Date.now();
|
|
227
|
+
saveRoutingInstructionStateSync(scope, state);
|
|
228
|
+
}
|
|
229
|
+
export function saveChatProcessSessionActualUsage(metadata, usageRaw, requestSnapshot) {
|
|
230
|
+
const scope = readScope(metadata);
|
|
231
|
+
if (!scope || !usageRaw || typeof usageRaw !== 'object' || Array.isArray(usageRaw)) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
const usage = usageRaw;
|
|
235
|
+
const actualInputTokens = coercePositiveInteger(usage.prompt_tokens ?? usage.input_tokens ?? usage.total_input_tokens);
|
|
236
|
+
if (actualInputTokens === undefined) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
const state = loadRoutingInstructionStateSync(scope) ?? buildEmptyRoutingInstructionState();
|
|
240
|
+
if (!hasReusableSessionUsageShape(state) && !applyRequestSnapshotToState(state, requestSnapshot)) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
state.chatProcessInputTokens = actualInputTokens;
|
|
244
|
+
state.chatProcessUpdatedAt = Date.now();
|
|
245
|
+
saveRoutingInstructionStateSync(scope, state);
|
|
246
|
+
}
|
|
@@ -15,6 +15,7 @@ import { runRespProcessStage3ServerToolOrchestration } from '../pipeline/stages/
|
|
|
15
15
|
import { runRespOutboundStage1ClientRemap } from '../pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/index.js';
|
|
16
16
|
import { runRespOutboundStage2SseStream } from '../pipeline/stages/resp_outbound/resp_outbound_stage2_sse_stream/index.js';
|
|
17
17
|
import { recordResponsesResponse } from '../../shared/responses-conversation-store.js';
|
|
18
|
+
import { saveChatProcessSessionActualUsage } from '../process/chat-process-session-usage.js';
|
|
18
19
|
import { ProviderProtocolError } from '../../provider-protocol-error.js';
|
|
19
20
|
import { readRuntimeMetadata } from '../../runtime-metadata.js';
|
|
20
21
|
import { commitClockReservation, resolveClockConfig } from '../../../servertool/clock/task-store.js';
|
|
@@ -397,6 +398,18 @@ export async function convertProviderResponse(options) {
|
|
|
397
398
|
});
|
|
398
399
|
applyModelOverride(clientPayload, displayModel);
|
|
399
400
|
stripInternalPolicyDebugFields(clientPayload);
|
|
401
|
+
try {
|
|
402
|
+
const usage = clientPayload && typeof clientPayload === 'object' && !Array.isArray(clientPayload)
|
|
403
|
+
? clientPayload.usage
|
|
404
|
+
: undefined;
|
|
405
|
+
saveChatProcessSessionActualUsage({
|
|
406
|
+
sessionId: typeof options.context.sessionId === 'string' ? options.context.sessionId : undefined,
|
|
407
|
+
conversationId: typeof options.context.conversationId === 'string' ? options.context.conversationId : undefined
|
|
408
|
+
}, usage, isJsonRecord(options.context.capturedChatRequest) ? options.context.capturedChatRequest : undefined);
|
|
409
|
+
}
|
|
410
|
+
catch {
|
|
411
|
+
// best-effort: usage backfill must not break response conversion
|
|
412
|
+
}
|
|
400
413
|
if (clientProtocol === 'openai-responses') {
|
|
401
414
|
try {
|
|
402
415
|
recordResponsesResponse({
|
|
@@ -142,10 +142,6 @@ export class OpenAIOpenAIPipelineCodec {
|
|
|
142
142
|
if (!Array.isArray(openaiPayload.tools) && Array.isArray(inboundPayload.tools)) {
|
|
143
143
|
openaiPayload.tools = inboundPayload.tools;
|
|
144
144
|
}
|
|
145
|
-
if (openaiPayload.tool_choice === undefined &&
|
|
146
|
-
inboundPayload.tool_choice !== undefined) {
|
|
147
|
-
openaiPayload.tool_choice = inboundPayload.tool_choice;
|
|
148
|
-
}
|
|
149
145
|
const filterContext = {
|
|
150
146
|
...context,
|
|
151
147
|
requestId,
|
|
@@ -55,10 +55,6 @@ function collectRetentionContext(context) {
|
|
|
55
55
|
const stripHostManagedFields = shouldStripHostManagedFields(context);
|
|
56
56
|
return {
|
|
57
57
|
metadata: context?.metadata,
|
|
58
|
-
parallelToolCalls: context?.parallel_tool_calls,
|
|
59
|
-
toolChoice: context?.tool_choice,
|
|
60
|
-
include: context?.include,
|
|
61
|
-
store: context?.store,
|
|
62
58
|
stripHostManagedFields
|
|
63
59
|
};
|
|
64
60
|
}
|
|
@@ -103,10 +99,6 @@ export function buildResponsesPayloadFromChat(payload, context) {
|
|
|
103
99
|
requestId: context?.requestId,
|
|
104
100
|
toolsRaw: Array.isArray(context?.toolsRaw) ? context?.toolsRaw : [],
|
|
105
101
|
metadata: retentionContext.metadata,
|
|
106
|
-
parallelToolCalls: retentionContext.parallelToolCalls,
|
|
107
|
-
toolChoice: retentionContext.toolChoice,
|
|
108
|
-
include: retentionContext.include,
|
|
109
|
-
store: retentionContext.store,
|
|
110
102
|
stripHostManagedFields: retentionContext.stripHostManagedFields,
|
|
111
103
|
sourceForRetention: sourceForRetention
|
|
112
104
|
});
|
|
@@ -176,10 +168,6 @@ export function buildResponsesPayloadFromChat(payload, context) {
|
|
|
176
168
|
requestId: context?.requestId,
|
|
177
169
|
toolsRaw: Array.isArray(context?.toolsRaw) ? context?.toolsRaw : [],
|
|
178
170
|
metadata: retentionContext.metadata,
|
|
179
|
-
parallelToolCalls: retentionContext.parallelToolCalls,
|
|
180
|
-
toolChoice: retentionContext.toolChoice,
|
|
181
|
-
include: retentionContext.include,
|
|
182
|
-
store: retentionContext.store,
|
|
183
171
|
stripHostManagedFields: retentionContext.stripHostManagedFields,
|
|
184
172
|
sourceForRetention: sourceForRetention
|
|
185
173
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BridgeInputItem, BridgeToolDefinition } from '../../types/bridge-message-types.js';
|
|
2
2
|
import type { ChatToolDefinition } from '../../hub/types/chat-envelope.js';
|
|
3
|
-
import type { JsonObject
|
|
3
|
+
import type { JsonObject } from '../../hub/types/json.js';
|
|
4
4
|
import type { ToolCallIdStyle } from '../../shared/responses-tool-utils.js';
|
|
5
5
|
export type Unknown = Record<string, unknown>;
|
|
6
6
|
export interface ResponsesRequestContext extends Unknown {
|
|
@@ -8,15 +8,7 @@ export interface ResponsesRequestContext extends Unknown {
|
|
|
8
8
|
targetProtocol?: string;
|
|
9
9
|
originalSystemMessages?: string[];
|
|
10
10
|
input?: BridgeInputItem[];
|
|
11
|
-
include?: unknown;
|
|
12
|
-
store?: unknown;
|
|
13
|
-
serviceTier?: unknown;
|
|
14
|
-
truncation?: unknown;
|
|
15
|
-
toolChoice?: unknown;
|
|
16
|
-
parallelToolCalls?: boolean;
|
|
17
11
|
metadata?: JsonObject;
|
|
18
|
-
responseFormat?: JsonValue;
|
|
19
|
-
stream?: boolean;
|
|
20
12
|
isChatPayload?: boolean;
|
|
21
13
|
isResponsesPayload?: boolean;
|
|
22
14
|
historyMessages?: Array<{
|
|
@@ -10,6 +10,7 @@ export declare function buildChatRequestFromResponses(payload: Record<string, un
|
|
|
10
10
|
export declare function buildResponsesRequestFromChat(payload: Record<string, unknown>, ctx?: ResponsesRequestContext, extras?: {
|
|
11
11
|
bridgeHistory?: BridgeInputBuildResult;
|
|
12
12
|
systemInstruction?: string;
|
|
13
|
+
routeToolCallIdStyle?: 'fc' | 'preserve';
|
|
13
14
|
}): BuildResponsesRequestResult;
|
|
14
15
|
export { buildResponsesPayloadFromChat, extractRequestIdFromResponse } from './responses-openai-bridge/response-payload.js';
|
|
15
16
|
export { buildChatResponseFromResponses } from '../shared/responses-response-utils.js';
|
|
@@ -4,6 +4,7 @@ import { convertBridgeInputToChatMessages } from '../bridge-message-utils.js';
|
|
|
4
4
|
import { createToolCallIdTransformer, enforceToolCallIdStyle, sanitizeResponsesFunctionName } from '../shared/responses-tool-utils.js';
|
|
5
5
|
import { mapChatToolsToBridge } from '../shared/tool-mapping.js';
|
|
6
6
|
import { ProviderProtocolError } from '../provider-protocol-error.js';
|
|
7
|
+
import { isJsonObject, jsonClone } from '../hub/types/json.js';
|
|
7
8
|
import { captureReqInboundResponsesContextSnapshotWithNative, mapReqInboundBridgeToolsToChatWithNative } from '../../router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.js';
|
|
8
9
|
import { appendLocalImageBlockOnLatestUserInputWithNative, buildBridgeHistoryWithNative, filterBridgeInputForUpstreamWithNative, normalizeBridgeHistorySeedWithNative, prepareResponsesRequestEnvelopeWithNative, resolveResponsesRequestBridgeDecisionsWithNative, resolveResponsesBridgeToolsWithNative, runBridgeActionPipelineWithNative } from '../../router/virtual-router/engine-selection/native-hub-bridge-action-semantics.js';
|
|
9
10
|
// --- Utilities (ported strictly) ---
|
|
@@ -50,7 +51,7 @@ export function captureResponsesContext(payload, dto) {
|
|
|
50
51
|
const captured = captureReqInboundResponsesContextSnapshotWithNative({
|
|
51
52
|
rawRequest: requestForCapture,
|
|
52
53
|
requestId: dto?.route?.requestId,
|
|
53
|
-
toolCallIdStyle: payload?.toolCallIdStyle
|
|
54
|
+
toolCallIdStyle: payload?.toolCallIdStyle
|
|
54
55
|
});
|
|
55
56
|
const instructionReasoning = payload?.__rcc_reasoning_instructions;
|
|
56
57
|
if (instructionReasoning !== undefined && instructionReasoning !== null) {
|
|
@@ -68,6 +69,12 @@ export function captureResponsesContext(payload, dto) {
|
|
|
68
69
|
if (!captured.systemInstruction && typeof payload.instructions === 'string' && payload.instructions.trim().length) {
|
|
69
70
|
captured.systemInstruction = payload.instructions;
|
|
70
71
|
}
|
|
72
|
+
if (captured.metadata && isJsonObject(captured.metadata)) {
|
|
73
|
+
const cloned = jsonClone(captured.metadata);
|
|
74
|
+
delete cloned.toolCallIdStyle;
|
|
75
|
+
delete cloned.extraFields;
|
|
76
|
+
captured.metadata = cloned;
|
|
77
|
+
}
|
|
71
78
|
return captured;
|
|
72
79
|
}
|
|
73
80
|
export function buildChatRequestFromResponses(payload, context) {
|
|
@@ -165,9 +172,6 @@ export function buildResponsesRequestFromChat(payload, ctx, extras) {
|
|
|
165
172
|
const chat = unwrapData(payload);
|
|
166
173
|
const out = {};
|
|
167
174
|
const envelopeMetadata = ctx?.metadata && typeof ctx.metadata === 'object' ? ctx.metadata : undefined;
|
|
168
|
-
const requestMetadata = chat && typeof chat === 'object' && chat.metadata && typeof chat.metadata === 'object'
|
|
169
|
-
? chat.metadata
|
|
170
|
-
: undefined;
|
|
171
175
|
// 基本字段
|
|
172
176
|
out.model = chat.model;
|
|
173
177
|
let messages = Array.isArray(chat.messages) ? chat.messages : [];
|
|
@@ -197,7 +201,7 @@ export function buildResponsesRequestFromChat(payload, ctx, extras) {
|
|
|
197
201
|
const metadataExtraFields = extractMetadataExtraFields(envelopeMetadata);
|
|
198
202
|
const bridgeDecisions = resolveResponsesRequestBridgeDecisionsWithNative({
|
|
199
203
|
context: ctx && typeof ctx === 'object' ? ctx : undefined,
|
|
200
|
-
|
|
204
|
+
routeToolCallIdStyle: extras?.routeToolCallIdStyle,
|
|
201
205
|
envelopeMetadata,
|
|
202
206
|
bridgeMetadata,
|
|
203
207
|
extraBridgeHistory: extras?.bridgeHistory
|
|
@@ -270,29 +274,27 @@ export function buildResponsesRequestFromChat(payload, ctx, extras) {
|
|
|
270
274
|
metadataSystemInstruction: envelopeMetadata?.systemInstruction,
|
|
271
275
|
combinedSystemInstruction,
|
|
272
276
|
reasoningInstructionSegments: ctx?.__rcc_reasoning_instructions_segments,
|
|
273
|
-
contextParameters:
|
|
277
|
+
contextParameters: undefined,
|
|
274
278
|
chatParameters: chat.parameters,
|
|
275
|
-
metadataParameters: metadataExtraFields?.parameters,
|
|
276
|
-
contextStream:
|
|
277
|
-
metadataStream:
|
|
279
|
+
metadataParameters: stripToolControlFieldsFromParameterObject(metadataExtraFields?.parameters),
|
|
280
|
+
contextStream: undefined,
|
|
281
|
+
metadataStream: undefined,
|
|
278
282
|
chatStream: streamFromChat,
|
|
279
283
|
chatParametersStream: streamFromParameters,
|
|
280
|
-
contextInclude:
|
|
281
|
-
metadataInclude:
|
|
282
|
-
contextStore:
|
|
283
|
-
metadataStore:
|
|
284
|
+
contextInclude: undefined,
|
|
285
|
+
metadataInclude: undefined,
|
|
286
|
+
contextStore: undefined,
|
|
287
|
+
metadataStore: undefined,
|
|
284
288
|
stripHostFields,
|
|
285
|
-
contextToolChoice:
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
metadataTruncation: metadataExtraFields?.truncation,
|
|
295
|
-
contextMetadata: ctx?.metadata,
|
|
289
|
+
contextToolChoice: undefined,
|
|
290
|
+
contextParallelToolCalls: undefined,
|
|
291
|
+
contextResponseFormat: undefined,
|
|
292
|
+
metadataResponseFormat: undefined,
|
|
293
|
+
contextServiceTier: undefined,
|
|
294
|
+
metadataServiceTier: undefined,
|
|
295
|
+
contextTruncation: undefined,
|
|
296
|
+
metadataTruncation: undefined,
|
|
297
|
+
contextMetadata: stripToolControlFieldsFromContextMetadata(ctx?.metadata),
|
|
296
298
|
metadataMetadata: metadataExtraFields?.metadata
|
|
297
299
|
});
|
|
298
300
|
Object.assign(out, preparedEnvelope.request);
|
|
@@ -326,6 +328,31 @@ function extractMetadataExtraFields(metadata) {
|
|
|
326
328
|
}
|
|
327
329
|
return undefined;
|
|
328
330
|
}
|
|
331
|
+
function stripToolControlFieldsFromContextMetadata(metadata) {
|
|
332
|
+
if (!metadata) {
|
|
333
|
+
return undefined;
|
|
334
|
+
}
|
|
335
|
+
const cloned = jsonClone(metadata);
|
|
336
|
+
const extras = cloned.extraFields;
|
|
337
|
+
if (!extras || !isPlainObject(extras)) {
|
|
338
|
+
return cloned;
|
|
339
|
+
}
|
|
340
|
+
delete extras.tool_choice;
|
|
341
|
+
delete extras.parallel_tool_calls;
|
|
342
|
+
if (Object.keys(extras).length === 0) {
|
|
343
|
+
delete cloned.extraFields;
|
|
344
|
+
}
|
|
345
|
+
return cloned;
|
|
346
|
+
}
|
|
347
|
+
function stripToolControlFieldsFromParameterObject(value) {
|
|
348
|
+
if (!value) {
|
|
349
|
+
return undefined;
|
|
350
|
+
}
|
|
351
|
+
const cloned = jsonClone(value);
|
|
352
|
+
delete cloned.tool_choice;
|
|
353
|
+
delete cloned.parallel_tool_calls;
|
|
354
|
+
return Object.keys(cloned).length ? cloned : undefined;
|
|
355
|
+
}
|
|
329
356
|
function isPlainObject(value) {
|
|
330
357
|
return Boolean(value && typeof value === 'object' && !Array.isArray(value));
|
|
331
358
|
}
|
|
@@ -16,6 +16,9 @@ function safeJson(v) {
|
|
|
16
16
|
return '{}';
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
+
function pickBoolean(value) {
|
|
20
|
+
return typeof value === 'boolean' ? value : undefined;
|
|
21
|
+
}
|
|
19
22
|
function stripOpenAIChatToolAliasFields(messages) {
|
|
20
23
|
// No-op: preserve tool_call_id/call_id for downstream consumers and regression parity.
|
|
21
24
|
void messages;
|
|
@@ -202,7 +205,8 @@ const ANTHROPIC_TOP_LEVEL_FIELDS = new Set([
|
|
|
202
205
|
'metadata',
|
|
203
206
|
'stream',
|
|
204
207
|
'tool_choice',
|
|
205
|
-
'thinking'
|
|
208
|
+
'thinking',
|
|
209
|
+
'disable_parallel_tool_use'
|
|
206
210
|
]);
|
|
207
211
|
const ANTHROPIC_STABLE_TOOL_SCHEMA_NAMES = new Set([
|
|
208
212
|
'exec_command',
|
|
@@ -526,6 +530,10 @@ export function buildOpenAIChatFromAnthropic(payload, options) {
|
|
|
526
530
|
}
|
|
527
531
|
if ('tool_choice' in body)
|
|
528
532
|
request.tool_choice = body.tool_choice;
|
|
533
|
+
const disableParallelToolUse = pickBoolean(body.disable_parallel_tool_use ?? body.disableParallelToolUse);
|
|
534
|
+
if (disableParallelToolUse !== undefined) {
|
|
535
|
+
request.parallel_tool_calls = !disableParallelToolUse;
|
|
536
|
+
}
|
|
529
537
|
const normalizedTools = mapAnthropicToolsToChat(body.tools);
|
|
530
538
|
if (normalizedTools !== undefined) {
|
|
531
539
|
request.tools = normalizedTools;
|
|
@@ -1077,6 +1085,11 @@ export function buildAnthropicRequestFromOpenAIChat(chatReq) {
|
|
|
1077
1085
|
if (normalizedToolChoice !== undefined) {
|
|
1078
1086
|
out.tool_choice = normalizedToolChoice;
|
|
1079
1087
|
}
|
|
1088
|
+
const parallelToolCalls = pickBoolean(requestBody.parallel_tool_calls
|
|
1089
|
+
?? requestBody.parallelToolCalls);
|
|
1090
|
+
if (parallelToolCalls !== undefined) {
|
|
1091
|
+
out.disable_parallel_tool_use = !parallelToolCalls;
|
|
1092
|
+
}
|
|
1080
1093
|
if (requestBody.thinking !== undefined) {
|
|
1081
1094
|
try {
|
|
1082
1095
|
out.thinking = JSON.parse(JSON.stringify(requestBody.thinking));
|
|
@@ -1,5 +1,63 @@
|
|
|
1
1
|
import { normalizeReasoningInAnthropicPayloadWithNative, normalizeReasoningInChatPayloadWithNative, normalizeReasoningInGeminiPayloadWithNative, normalizeReasoningInOpenAIPayloadWithNative, normalizeReasoningInResponsesPayloadWithNative } from '../../router/virtual-router/engine-selection/native-shared-conversion-semantics.js';
|
|
2
2
|
export const RESPONSES_INSTRUCTIONS_REASONING_FIELD = '__rcc_reasoning_instructions';
|
|
3
|
+
function textMayContainReasoningMarkup(text) {
|
|
4
|
+
if (!text || (text.indexOf('<') === -1 && text.indexOf('`') === -1)) {
|
|
5
|
+
return false;
|
|
6
|
+
}
|
|
7
|
+
const lower = text.toLowerCase();
|
|
8
|
+
return (lower.includes('<think') ||
|
|
9
|
+
lower.includes('<reflection') ||
|
|
10
|
+
lower.includes('</think>') ||
|
|
11
|
+
lower.includes('</reflection>') ||
|
|
12
|
+
lower.includes('```think') ||
|
|
13
|
+
lower.includes('```reflection') ||
|
|
14
|
+
lower.includes('``` think') ||
|
|
15
|
+
lower.includes('``` reflection'));
|
|
16
|
+
}
|
|
17
|
+
function valueMayContainReasoningMarkup(value) {
|
|
18
|
+
if (typeof value === 'string') {
|
|
19
|
+
return textMayContainReasoningMarkup(value);
|
|
20
|
+
}
|
|
21
|
+
if (Array.isArray(value)) {
|
|
22
|
+
for (const entry of value) {
|
|
23
|
+
if (valueMayContainReasoningMarkup(entry)) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
if (!value || typeof value !== 'object') {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
for (const entry of Object.values(value)) {
|
|
33
|
+
if (valueMayContainReasoningMarkup(entry)) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
function responsesPayloadMayNeedReasoningNormalization(payload, options) {
|
|
40
|
+
if (!payload || typeof payload !== 'object') {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
const includeOutput = options.includeOutput ?? true;
|
|
44
|
+
const includeInput = options.includeInput ?? false;
|
|
45
|
+
const includeRequiredAction = options.includeRequiredAction ?? false;
|
|
46
|
+
const includeInstructions = options.includeInstructions ?? false;
|
|
47
|
+
if (includeOutput && valueMayContainReasoningMarkup(payload.output)) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
if (includeInput && valueMayContainReasoningMarkup(payload.input)) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
if (includeInstructions && valueMayContainReasoningMarkup(payload.instructions)) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
if (includeRequiredAction && valueMayContainReasoningMarkup(payload.required_action)) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
3
61
|
function assertReasoningNormalizerNativeAvailable() {
|
|
4
62
|
if (typeof normalizeReasoningInChatPayloadWithNative !== 'function' ||
|
|
5
63
|
typeof normalizeReasoningInResponsesPayloadWithNative !== 'function' ||
|
|
@@ -22,6 +80,9 @@ export function normalizeReasoningInResponsesPayload(payload, options = { includ
|
|
|
22
80
|
assertReasoningNormalizerNativeAvailable();
|
|
23
81
|
if (!payload)
|
|
24
82
|
return;
|
|
83
|
+
if (!responsesPayloadMayNeedReasoningNormalization(payload, options)) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
25
86
|
const normalized = normalizeReasoningInResponsesPayloadWithNative(payload, options);
|
|
26
87
|
if (normalized && typeof normalized === 'object') {
|
|
27
88
|
Object.assign(payload, normalized);
|