@jsonstudio/llms 0.6.938 → 0.6.1164
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/hub/operation-table/operation-table-runner.d.ts +18 -0
- package/dist/conversion/hub/operation-table/operation-table-runner.js +158 -0
- package/dist/conversion/hub/operation-table/semantic-mappers/anthropic-mapper.d.ts +8 -0
- package/dist/conversion/hub/operation-table/semantic-mappers/anthropic-mapper.js +303 -0
- package/dist/conversion/hub/operation-table/semantic-mappers/chat-mapper.d.ts +8 -0
- package/dist/conversion/hub/operation-table/semantic-mappers/chat-mapper.js +413 -0
- package/dist/conversion/hub/operation-table/semantic-mappers/gemini-mapper.d.ts +7 -0
- package/dist/conversion/hub/operation-table/semantic-mappers/gemini-mapper.js +841 -0
- package/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper.d.ts +21 -0
- package/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper.js +535 -0
- package/dist/conversion/hub/ops/operations.d.ts +19 -0
- package/dist/conversion/hub/ops/operations.js +126 -0
- package/dist/conversion/hub/pipeline/hub-pipeline.d.ts +9 -0
- package/dist/conversion/hub/pipeline/hub-pipeline.js +533 -24
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.js +6 -0
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/index.js +6 -3
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/index.js +11 -0
- package/dist/conversion/hub/policy/policy-engine.js +41 -9
- package/dist/conversion/hub/policy/protocol-spec.d.ts +25 -0
- package/dist/conversion/hub/policy/protocol-spec.js +73 -23
- package/dist/conversion/hub/process/chat-process.js +252 -41
- package/dist/conversion/hub/response/provider-response.js +175 -2
- package/dist/conversion/hub/response/response-runtime.js +1 -1
- package/dist/conversion/hub/semantic-mappers/anthropic-mapper.d.ts +1 -8
- package/dist/conversion/hub/semantic-mappers/anthropic-mapper.js +1 -365
- package/dist/conversion/hub/semantic-mappers/chat-mapper.d.ts +1 -8
- package/dist/conversion/hub/semantic-mappers/chat-mapper.js +1 -436
- package/dist/conversion/hub/semantic-mappers/gemini-mapper.d.ts +1 -7
- package/dist/conversion/hub/semantic-mappers/gemini-mapper.js +1 -894
- package/dist/conversion/hub/semantic-mappers/responses-mapper.d.ts +1 -21
- package/dist/conversion/hub/semantic-mappers/responses-mapper.js +1 -593
- package/dist/conversion/hub/tool-surface/tool-surface-engine.d.ts +18 -0
- package/dist/conversion/hub/tool-surface/tool-surface-engine.js +571 -0
- package/dist/conversion/responses/responses-openai-bridge.js +14 -2
- package/dist/conversion/shared/bridge-message-utils.js +2 -8
- package/dist/conversion/shared/bridge-policies.js +5 -105
- package/dist/conversion/shared/gemini-tool-utils.js +121 -4
- package/dist/conversion/shared/protocol-field-allowlists.d.ts +7 -0
- package/dist/conversion/shared/protocol-field-allowlists.js +145 -0
- package/dist/conversion/shared/reasoning-tool-normalizer.js +4 -2
- package/dist/conversion/shared/snapshot-hooks.js +166 -3
- package/dist/conversion/shared/text-markup-normalizer.d.ts +2 -0
- package/dist/conversion/shared/text-markup-normalizer.js +345 -9
- package/dist/conversion/shared/thought-signature-validator.d.ts +52 -0
- package/dist/conversion/shared/thought-signature-validator.js +170 -0
- package/dist/conversion/shared/tool-argument-repairer.d.ts +39 -0
- package/dist/conversion/shared/tool-argument-repairer.js +56 -0
- package/dist/conversion/shared/tool-call-id-manager.d.ts +113 -0
- package/dist/conversion/shared/tool-call-id-manager.js +231 -0
- package/dist/conversion/shared/tool-canonicalizer.js +2 -11
- package/dist/router/virtual-router/bootstrap.js +54 -5
- package/dist/router/virtual-router/engine-selection.js +132 -42
- package/dist/router/virtual-router/engine.d.ts +3 -0
- package/dist/router/virtual-router/engine.js +142 -33
- package/dist/router/virtual-router/health-weighted.d.ts +25 -0
- package/dist/router/virtual-router/health-weighted.js +63 -0
- package/dist/router/virtual-router/load-balancer.d.ts +2 -0
- package/dist/router/virtual-router/load-balancer.js +45 -16
- package/dist/router/virtual-router/routing-instructions.js +17 -1
- package/dist/router/virtual-router/sticky-session-store.js +136 -24
- package/dist/router/virtual-router/stop-message-file-resolver.d.ts +1 -0
- package/dist/router/virtual-router/stop-message-file-resolver.js +74 -0
- package/dist/router/virtual-router/stop-message-state-sync.d.ts +15 -0
- package/dist/router/virtual-router/stop-message-state-sync.js +57 -0
- package/dist/router/virtual-router/types.d.ts +70 -0
- package/dist/servertool/clock/config.d.ts +7 -0
- package/dist/servertool/clock/config.js +27 -0
- package/dist/servertool/clock/daemon.d.ts +3 -0
- package/dist/servertool/clock/daemon.js +79 -0
- package/dist/servertool/clock/io.d.ts +2 -0
- package/dist/servertool/clock/io.js +13 -0
- package/dist/servertool/clock/paths.d.ts +4 -0
- package/dist/servertool/clock/paths.js +25 -0
- package/dist/servertool/clock/session-store.d.ts +3 -0
- package/dist/servertool/clock/session-store.js +56 -0
- package/dist/servertool/clock/state.d.ts +5 -0
- package/dist/servertool/clock/state.js +62 -0
- package/dist/servertool/clock/task-store.d.ts +5 -0
- package/dist/servertool/clock/task-store.js +4 -0
- package/dist/servertool/clock/tasks.d.ts +17 -0
- package/dist/servertool/clock/tasks.js +221 -0
- package/dist/servertool/clock/types.d.ts +36 -0
- package/dist/servertool/clock/types.js +1 -0
- package/dist/servertool/engine.d.ts +2 -0
- package/dist/servertool/engine.js +164 -8
- package/dist/servertool/followup-shadow.d.ts +16 -0
- package/dist/servertool/followup-shadow.js +145 -0
- package/dist/servertool/handlers/apply-patch-guard.js +1 -265
- package/dist/servertool/handlers/clock-auto.d.ts +1 -0
- package/dist/servertool/handlers/clock-auto.js +160 -0
- package/dist/servertool/handlers/clock.d.ts +1 -0
- package/dist/servertool/handlers/clock.js +197 -0
- package/dist/servertool/handlers/exec-command-guard.js +7 -555
- package/dist/servertool/handlers/followup-request-builder.d.ts +15 -7
- package/dist/servertool/handlers/followup-request-builder.js +248 -28
- package/dist/servertool/handlers/gemini-empty-reply-continue.js +62 -169
- package/dist/servertool/handlers/iflow-model-error-retry.js +18 -28
- package/dist/servertool/handlers/recursive-detection-guard.d.ts +1 -0
- package/dist/servertool/handlers/recursive-detection-guard.js +333 -0
- package/dist/servertool/handlers/stop-message-auto.js +47 -175
- package/dist/servertool/handlers/vision.d.ts +7 -1
- package/dist/servertool/handlers/vision.js +61 -117
- package/dist/servertool/handlers/web-search.d.ts +7 -1
- package/dist/servertool/handlers/web-search.js +122 -105
- package/dist/servertool/reenter-backend.d.ts +23 -0
- package/dist/servertool/reenter-backend.js +18 -0
- package/dist/servertool/server-side-tools.d.ts +3 -2
- package/dist/servertool/server-side-tools.js +64 -10
- package/dist/servertool/types.d.ts +92 -3
- package/dist/sse/json-to-sse/event-generators/responses.js +3 -21
- package/dist/sse/shared/serializers/responses-event-serializer.d.ts +8 -0
- package/dist/sse/shared/serializers/responses-event-serializer.js +19 -0
- package/dist/sse/shared/writer.js +24 -7
- package/dist/tools/apply-patch/execution-capturer.js +3 -1
- package/dist/tools/apply-patch/json/parse-loose.d.ts +3 -0
- package/dist/tools/apply-patch/json/parse-loose.js +139 -0
- package/dist/tools/apply-patch/patch-text/context-diff.d.ts +1 -0
- package/dist/tools/apply-patch/patch-text/context-diff.js +173 -0
- package/dist/tools/apply-patch/patch-text/git-diff.d.ts +1 -0
- package/dist/tools/apply-patch/patch-text/git-diff.js +138 -0
- package/dist/tools/apply-patch/patch-text/looks-like-patch.d.ts +1 -0
- package/dist/tools/apply-patch/patch-text/looks-like-patch.js +13 -0
- package/dist/tools/apply-patch/patch-text/normalize.d.ts +3 -0
- package/dist/tools/apply-patch/patch-text/normalize.js +262 -0
- package/dist/tools/apply-patch/structured/coercion.d.ts +3 -0
- package/dist/tools/apply-patch/structured/coercion.js +82 -0
- package/dist/tools/apply-patch/validation/shared.d.ts +3 -0
- package/dist/tools/apply-patch/validation/shared.js +6 -0
- package/dist/tools/apply-patch/validator.d.ts +2 -2
- package/dist/tools/apply-patch/validator.js +6 -556
- package/package.json +1 -1
|
@@ -1,436 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { createBridgeActionState, runBridgeActionPipeline } from '../../shared/bridge-actions.js';
|
|
3
|
-
import { resolveBridgePolicy, resolvePolicyActions } from '../../shared/bridge-policies.js';
|
|
4
|
-
import { normalizeChatMessageContent } from '../../shared/chat-output-normalizer.js';
|
|
5
|
-
import { ensureProtocolState } from '../../shared/protocol-state.js';
|
|
6
|
-
const CHAT_PARAMETER_KEYS = [
|
|
7
|
-
'model',
|
|
8
|
-
'temperature',
|
|
9
|
-
'top_p',
|
|
10
|
-
'top_k',
|
|
11
|
-
'max_tokens',
|
|
12
|
-
'frequency_penalty',
|
|
13
|
-
'presence_penalty',
|
|
14
|
-
'logit_bias',
|
|
15
|
-
'response_format',
|
|
16
|
-
'parallel_tool_calls',
|
|
17
|
-
'tool_choice',
|
|
18
|
-
'seed',
|
|
19
|
-
'user',
|
|
20
|
-
'metadata',
|
|
21
|
-
'stop',
|
|
22
|
-
'stop_sequences',
|
|
23
|
-
'stream'
|
|
24
|
-
];
|
|
25
|
-
const KNOWN_TOP_LEVEL_FIELDS = new Set([
|
|
26
|
-
'messages',
|
|
27
|
-
'tools',
|
|
28
|
-
'tool_outputs',
|
|
29
|
-
...CHAT_PARAMETER_KEYS,
|
|
30
|
-
'stageExpectations',
|
|
31
|
-
'stages'
|
|
32
|
-
]);
|
|
33
|
-
function flattenSystemContent(content) {
|
|
34
|
-
if (typeof content === 'string')
|
|
35
|
-
return content;
|
|
36
|
-
if (Array.isArray(content)) {
|
|
37
|
-
return content.map(flattenSystemContent).filter(Boolean).join('\n');
|
|
38
|
-
}
|
|
39
|
-
if (content && typeof content === 'object') {
|
|
40
|
-
const obj = content;
|
|
41
|
-
if (typeof obj.text === 'string')
|
|
42
|
-
return obj.text;
|
|
43
|
-
if (typeof obj.content === 'string')
|
|
44
|
-
return obj.content;
|
|
45
|
-
if (Array.isArray(obj.content))
|
|
46
|
-
return obj.content.map(flattenSystemContent).join('\n');
|
|
47
|
-
}
|
|
48
|
-
return '';
|
|
49
|
-
}
|
|
50
|
-
function normalizeToolContent(content) {
|
|
51
|
-
if (typeof content === 'string')
|
|
52
|
-
return content;
|
|
53
|
-
if (content === null || content === undefined)
|
|
54
|
-
return '';
|
|
55
|
-
try {
|
|
56
|
-
return JSON.stringify(content);
|
|
57
|
-
}
|
|
58
|
-
catch {
|
|
59
|
-
return String(content ?? '');
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
export function maybeAugmentApplyPatchErrorContent(content, toolName) {
|
|
63
|
-
if (!content)
|
|
64
|
-
return content;
|
|
65
|
-
const lower = content.toLowerCase();
|
|
66
|
-
const isApplyPatch = (typeof toolName === 'string' && toolName.trim() === 'apply_patch') ||
|
|
67
|
-
lower.includes('apply_patch verification failed');
|
|
68
|
-
if (!isApplyPatch) {
|
|
69
|
-
return content;
|
|
70
|
-
}
|
|
71
|
-
// 避免重复追加提示。
|
|
72
|
-
if (content.includes('[apply_patch hint]')) {
|
|
73
|
-
return content;
|
|
74
|
-
}
|
|
75
|
-
const hint = '\n\n[apply_patch hint] 在使用 apply_patch 之前,请先读取目标文件的最新内容,并基于该内容生成补丁;同时确保补丁格式符合工具规范(统一补丁格式或结构化参数),避免上下文不匹配或语法错误。';
|
|
76
|
-
return content + hint;
|
|
77
|
-
}
|
|
78
|
-
function recordToolCallIssues(message, messageIndex, missing) {
|
|
79
|
-
const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : undefined;
|
|
80
|
-
if (!toolCalls?.length)
|
|
81
|
-
return;
|
|
82
|
-
toolCalls.forEach((entry, callIndex) => {
|
|
83
|
-
if (!isJsonObject(entry)) {
|
|
84
|
-
missing.push({
|
|
85
|
-
path: `messages[${messageIndex}].tool_calls[${callIndex}]`,
|
|
86
|
-
reason: 'invalid_tool_call_entry',
|
|
87
|
-
originalValue: jsonClone(entry)
|
|
88
|
-
});
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
const fnBlock = entry.function;
|
|
92
|
-
if (!isJsonObject(fnBlock)) {
|
|
93
|
-
missing.push({
|
|
94
|
-
path: `messages[${messageIndex}].tool_calls[${callIndex}].function`,
|
|
95
|
-
reason: 'missing_tool_function',
|
|
96
|
-
originalValue: jsonClone(fnBlock)
|
|
97
|
-
});
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
const fnName = fnBlock.name;
|
|
101
|
-
if (typeof fnName !== 'string' || !fnName.trim().length) {
|
|
102
|
-
missing.push({
|
|
103
|
-
path: `messages[${messageIndex}].tool_calls[${callIndex}].function.name`,
|
|
104
|
-
reason: 'missing_tool_name'
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
function collectSystemRawBlocks(raw) {
|
|
110
|
-
if (!Array.isArray(raw))
|
|
111
|
-
return undefined;
|
|
112
|
-
const blocks = [];
|
|
113
|
-
raw.forEach((entry) => {
|
|
114
|
-
if (!isJsonObject(entry))
|
|
115
|
-
return;
|
|
116
|
-
if (String(entry.role ?? '').toLowerCase() !== 'system')
|
|
117
|
-
return;
|
|
118
|
-
blocks.push(jsonClone(entry));
|
|
119
|
-
});
|
|
120
|
-
return blocks.length ? blocks : undefined;
|
|
121
|
-
}
|
|
122
|
-
function normalizeChatMessages(raw) {
|
|
123
|
-
const norm = {
|
|
124
|
-
messages: [],
|
|
125
|
-
systemSegments: [],
|
|
126
|
-
toolOutputs: [],
|
|
127
|
-
missingFields: []
|
|
128
|
-
};
|
|
129
|
-
if (raw === undefined) {
|
|
130
|
-
norm.missingFields.push({ path: 'messages', reason: 'absent' });
|
|
131
|
-
return norm;
|
|
132
|
-
}
|
|
133
|
-
if (!Array.isArray(raw)) {
|
|
134
|
-
norm.missingFields.push({ path: 'messages', reason: 'invalid_type', originalValue: jsonClone(raw) });
|
|
135
|
-
return norm;
|
|
136
|
-
}
|
|
137
|
-
raw.forEach((value, index) => {
|
|
138
|
-
if (!isJsonObject(value)) {
|
|
139
|
-
norm.missingFields.push({ path: `messages[${index}]`, reason: 'invalid_entry', originalValue: jsonClone(value) });
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
const roleValue = value.role;
|
|
143
|
-
if (typeof roleValue !== 'string') {
|
|
144
|
-
norm.missingFields.push({ path: `messages[${index}].role`, reason: 'missing_role' });
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
const chatMessage = value;
|
|
148
|
-
if (roleValue !== 'system' && roleValue !== 'tool') {
|
|
149
|
-
const normalizedContent = normalizeChatMessageContent(chatMessage.content);
|
|
150
|
-
const shouldOverwriteContent = !Array.isArray(chatMessage.content);
|
|
151
|
-
if (shouldOverwriteContent && normalizedContent.contentText !== undefined) {
|
|
152
|
-
chatMessage.content = normalizedContent.contentText;
|
|
153
|
-
}
|
|
154
|
-
if (typeof normalizedContent.reasoningText === 'string' && normalizedContent.reasoningText.trim().length) {
|
|
155
|
-
chatMessage.reasoning_content = normalizedContent.reasoningText.trim();
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
norm.messages.push(chatMessage);
|
|
159
|
-
const toolCallCandidate = value.tool_calls;
|
|
160
|
-
if (Array.isArray(toolCallCandidate) && toolCallCandidate.length) {
|
|
161
|
-
recordToolCallIssues(value, index, norm.missingFields);
|
|
162
|
-
}
|
|
163
|
-
if (roleValue === 'system') {
|
|
164
|
-
const segment = flattenSystemContent(chatMessage.content);
|
|
165
|
-
if (segment.trim().length) {
|
|
166
|
-
norm.systemSegments.push(segment);
|
|
167
|
-
}
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
if (roleValue === 'tool') {
|
|
171
|
-
const rawCallId = (value.tool_call_id ?? value.call_id ?? value.id);
|
|
172
|
-
const toolCallId = typeof rawCallId === 'string' && rawCallId.trim().length ? rawCallId.trim() : undefined;
|
|
173
|
-
if (!toolCallId) {
|
|
174
|
-
norm.missingFields.push({ path: `messages[${index}].tool_call_id`, reason: 'missing_tool_call_id' });
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
const nameValue = typeof value.name === 'string' && value.name.trim().length ? value.name : undefined;
|
|
178
|
-
const outputEntry = {
|
|
179
|
-
tool_call_id: toolCallId,
|
|
180
|
-
content: normalizeToolContent(value.content ?? value.output),
|
|
181
|
-
name: nameValue
|
|
182
|
-
};
|
|
183
|
-
outputEntry.content = maybeAugmentApplyPatchErrorContent(outputEntry.content, outputEntry.name);
|
|
184
|
-
norm.toolOutputs.push(outputEntry);
|
|
185
|
-
}
|
|
186
|
-
});
|
|
187
|
-
return norm;
|
|
188
|
-
}
|
|
189
|
-
function normalizeStandaloneToolOutputs(raw, missing) {
|
|
190
|
-
if (!Array.isArray(raw) || raw.length === 0)
|
|
191
|
-
return [];
|
|
192
|
-
const outputs = [];
|
|
193
|
-
raw.forEach((entry, index) => {
|
|
194
|
-
if (!isJsonObject(entry)) {
|
|
195
|
-
missing.push({ path: `tool_outputs[${index}]`, reason: 'invalid_entry', originalValue: jsonClone(entry) });
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
const rawCallId = entry.tool_call_id ?? entry.call_id ?? entry.id;
|
|
199
|
-
const toolCallId = typeof rawCallId === 'string' && rawCallId.trim().length ? rawCallId.trim() : undefined;
|
|
200
|
-
if (!toolCallId) {
|
|
201
|
-
missing.push({ path: `tool_outputs[${index}].tool_call_id`, reason: 'missing_tool_call_id' });
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
const nameValue = typeof entry.name === 'string' && entry.name.trim().length ? entry.name : undefined;
|
|
205
|
-
const rawContent = normalizeToolContent(entry.content ?? entry.output);
|
|
206
|
-
const content = maybeAugmentApplyPatchErrorContent(rawContent, nameValue);
|
|
207
|
-
outputs.push({
|
|
208
|
-
tool_call_id: toolCallId,
|
|
209
|
-
content,
|
|
210
|
-
name: nameValue
|
|
211
|
-
});
|
|
212
|
-
});
|
|
213
|
-
return outputs;
|
|
214
|
-
}
|
|
215
|
-
function normalizeTools(raw, missing) {
|
|
216
|
-
if (!Array.isArray(raw) || raw.length === 0)
|
|
217
|
-
return undefined;
|
|
218
|
-
const tools = [];
|
|
219
|
-
raw.forEach((entry, index) => {
|
|
220
|
-
if (!isJsonObject(entry)) {
|
|
221
|
-
missing.push({ path: `tools[${index}]`, reason: 'invalid_entry', originalValue: jsonClone(entry) });
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
tools.push(entry);
|
|
225
|
-
});
|
|
226
|
-
return tools.length ? tools : undefined;
|
|
227
|
-
}
|
|
228
|
-
function extractParameters(body) {
|
|
229
|
-
const params = {};
|
|
230
|
-
for (const key of CHAT_PARAMETER_KEYS) {
|
|
231
|
-
if (body[key] !== undefined) {
|
|
232
|
-
params[key] = body[key];
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
return Object.keys(params).length ? params : undefined;
|
|
236
|
-
}
|
|
237
|
-
function collectExtraFields(body) {
|
|
238
|
-
const extras = {};
|
|
239
|
-
for (const [key, value] of Object.entries(body)) {
|
|
240
|
-
if (KNOWN_TOP_LEVEL_FIELDS.has(key)) {
|
|
241
|
-
continue;
|
|
242
|
-
}
|
|
243
|
-
if (value !== undefined) {
|
|
244
|
-
extras[key] = jsonClone(value);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
return Object.keys(extras).length ? extras : undefined;
|
|
248
|
-
}
|
|
249
|
-
function extractOpenAIExtraFieldsFromSemantics(semantics) {
|
|
250
|
-
if (!semantics || !semantics.providerExtras || !isJsonObject(semantics.providerExtras)) {
|
|
251
|
-
return undefined;
|
|
252
|
-
}
|
|
253
|
-
const openaiExtras = semantics.providerExtras.openaiChat;
|
|
254
|
-
if (!openaiExtras || !isJsonObject(openaiExtras)) {
|
|
255
|
-
return undefined;
|
|
256
|
-
}
|
|
257
|
-
const stored = openaiExtras.extraFields;
|
|
258
|
-
if (!stored || !isJsonObject(stored)) {
|
|
259
|
-
return undefined;
|
|
260
|
-
}
|
|
261
|
-
return stored;
|
|
262
|
-
}
|
|
263
|
-
function hasExplicitEmptyToolsSemantics(semantics) {
|
|
264
|
-
if (!semantics || !semantics.tools || !isJsonObject(semantics.tools)) {
|
|
265
|
-
return false;
|
|
266
|
-
}
|
|
267
|
-
const flag = semantics.tools.explicitEmpty;
|
|
268
|
-
return flag === true;
|
|
269
|
-
}
|
|
270
|
-
function buildOpenAISemantics(options) {
|
|
271
|
-
const semantics = {};
|
|
272
|
-
if (options.systemSegments && options.systemSegments.length) {
|
|
273
|
-
semantics.system = {
|
|
274
|
-
textBlocks: options.systemSegments.map((segment) => segment)
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
if (options.extraFields && Object.keys(options.extraFields).length) {
|
|
278
|
-
semantics.providerExtras = {
|
|
279
|
-
openaiChat: {
|
|
280
|
-
extraFields: jsonClone(options.extraFields)
|
|
281
|
-
}
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
if (options.explicitEmptyTools) {
|
|
285
|
-
semantics.tools = {
|
|
286
|
-
explicitEmpty: true
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
return Object.keys(semantics).length ? semantics : undefined;
|
|
290
|
-
}
|
|
291
|
-
function applyExtraFields(body, metadata, semantics) {
|
|
292
|
-
const sources = [];
|
|
293
|
-
const semanticsExtras = extractOpenAIExtraFieldsFromSemantics(semantics);
|
|
294
|
-
if (semanticsExtras) {
|
|
295
|
-
sources.push(semanticsExtras);
|
|
296
|
-
}
|
|
297
|
-
if (metadata?.extraFields && isJsonObject(metadata.extraFields)) {
|
|
298
|
-
sources.push(metadata.extraFields);
|
|
299
|
-
}
|
|
300
|
-
if (!sources.length) {
|
|
301
|
-
return;
|
|
302
|
-
}
|
|
303
|
-
for (const source of sources) {
|
|
304
|
-
for (const [key, value] of Object.entries(source)) {
|
|
305
|
-
if (body[key] !== undefined) {
|
|
306
|
-
continue;
|
|
307
|
-
}
|
|
308
|
-
body[key] = jsonClone(value);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
export class ChatSemanticMapper {
|
|
313
|
-
async toChat(format, ctx) {
|
|
314
|
-
const payload = (format.payload ?? {});
|
|
315
|
-
const normalized = normalizeChatMessages(payload.messages);
|
|
316
|
-
const topLevelOutputs = normalizeStandaloneToolOutputs(payload.tool_outputs, normalized.missingFields);
|
|
317
|
-
const toolOutputs = [...normalized.toolOutputs];
|
|
318
|
-
for (const entry of topLevelOutputs) {
|
|
319
|
-
if (!toolOutputs.find(item => item.tool_call_id === entry.tool_call_id)) {
|
|
320
|
-
toolOutputs.push(entry);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
const metadata = { context: ctx };
|
|
324
|
-
if (normalized.systemSegments.length) {
|
|
325
|
-
metadata.systemInstructions = normalized.systemSegments;
|
|
326
|
-
}
|
|
327
|
-
const rawSystemBlocks = collectSystemRawBlocks(payload.messages);
|
|
328
|
-
if (rawSystemBlocks) {
|
|
329
|
-
const protocolState = ensureProtocolState(metadata, 'openai');
|
|
330
|
-
protocolState.systemMessages = jsonClone(rawSystemBlocks);
|
|
331
|
-
}
|
|
332
|
-
if (normalized.missingFields.length) {
|
|
333
|
-
metadata.missingFields = normalized.missingFields;
|
|
334
|
-
}
|
|
335
|
-
const extraFields = collectExtraFields(payload);
|
|
336
|
-
if (extraFields) {
|
|
337
|
-
metadata.extraFields = extraFields;
|
|
338
|
-
}
|
|
339
|
-
try {
|
|
340
|
-
const bridgePolicy = resolveBridgePolicy({ protocol: 'openai-chat' });
|
|
341
|
-
const actions = resolvePolicyActions(bridgePolicy, 'request_inbound');
|
|
342
|
-
if (actions?.length) {
|
|
343
|
-
const actionState = createBridgeActionState({
|
|
344
|
-
messages: normalized.messages,
|
|
345
|
-
rawRequest: payload,
|
|
346
|
-
metadata: metadata
|
|
347
|
-
});
|
|
348
|
-
runBridgeActionPipeline({
|
|
349
|
-
stage: 'request_inbound',
|
|
350
|
-
actions,
|
|
351
|
-
protocol: bridgePolicy?.protocol ?? 'openai-chat',
|
|
352
|
-
moduleType: bridgePolicy?.moduleType ?? 'openai-chat',
|
|
353
|
-
requestId: ctx.requestId,
|
|
354
|
-
state: actionState
|
|
355
|
-
});
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
catch {
|
|
359
|
-
// noop: best-effort policy application
|
|
360
|
-
}
|
|
361
|
-
const explicitEmptyTools = Array.isArray(payload.tools) && payload.tools.length === 0;
|
|
362
|
-
if (explicitEmptyTools) {
|
|
363
|
-
metadata.toolsFieldPresent = true;
|
|
364
|
-
}
|
|
365
|
-
const semantics = buildOpenAISemantics({
|
|
366
|
-
systemSegments: normalized.systemSegments,
|
|
367
|
-
extraFields,
|
|
368
|
-
explicitEmptyTools
|
|
369
|
-
});
|
|
370
|
-
return {
|
|
371
|
-
messages: normalized.messages,
|
|
372
|
-
tools: normalizeTools(payload.tools, normalized.missingFields),
|
|
373
|
-
toolOutputs: toolOutputs.length ? toolOutputs : undefined,
|
|
374
|
-
parameters: extractParameters(payload),
|
|
375
|
-
semantics,
|
|
376
|
-
metadata
|
|
377
|
-
};
|
|
378
|
-
}
|
|
379
|
-
async fromChat(chat, ctx) {
|
|
380
|
-
const shouldEmitEmptyTools = hasExplicitEmptyToolsSemantics(chat.semantics) || chat.metadata?.toolsFieldPresent === true;
|
|
381
|
-
const payload = {
|
|
382
|
-
messages: chat.messages,
|
|
383
|
-
tools: chat.tools ?? (shouldEmitEmptyTools ? [] : undefined),
|
|
384
|
-
...(chat.parameters || {})
|
|
385
|
-
};
|
|
386
|
-
applyExtraFields(payload, chat.metadata, chat.semantics);
|
|
387
|
-
try {
|
|
388
|
-
const bridgePolicy = resolveBridgePolicy({ protocol: 'openai-chat' });
|
|
389
|
-
const actions = resolvePolicyActions(bridgePolicy, 'request_outbound');
|
|
390
|
-
if (actions?.length && Array.isArray(payload.messages)) {
|
|
391
|
-
const capturedToolResults = Array.isArray(chat.toolOutputs)
|
|
392
|
-
? chat.toolOutputs.map((entry) => ({
|
|
393
|
-
tool_call_id: entry.tool_call_id,
|
|
394
|
-
output: entry.content,
|
|
395
|
-
name: entry.name
|
|
396
|
-
}))
|
|
397
|
-
: undefined;
|
|
398
|
-
const actionState = createBridgeActionState({
|
|
399
|
-
messages: payload.messages,
|
|
400
|
-
rawRequest: payload,
|
|
401
|
-
metadata: chat.metadata,
|
|
402
|
-
capturedToolResults
|
|
403
|
-
});
|
|
404
|
-
runBridgeActionPipeline({
|
|
405
|
-
stage: 'request_outbound',
|
|
406
|
-
actions,
|
|
407
|
-
protocol: bridgePolicy?.protocol ?? 'openai-chat',
|
|
408
|
-
moduleType: bridgePolicy?.moduleType ?? 'openai-chat',
|
|
409
|
-
requestId: ctx.requestId,
|
|
410
|
-
state: actionState
|
|
411
|
-
});
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
catch {
|
|
415
|
-
// ignore policy failures
|
|
416
|
-
}
|
|
417
|
-
// Do not forward tool_outputs to provider wire formats. OpenAI Chat
|
|
418
|
-
// endpoints expect tool results to appear as tool role messages, and
|
|
419
|
-
// sending the legacy top-level field causes upstream HTTP 400 responses.
|
|
420
|
-
// Concrete translation happens earlier when responses input is unfolded
|
|
421
|
-
// into ChatEnvelope.messages, so the provider request only needs the
|
|
422
|
-
// canonical message list.
|
|
423
|
-
if (payload.max_tokens === undefined && typeof payload.max_output_tokens === 'number') {
|
|
424
|
-
payload.max_tokens = payload.max_output_tokens;
|
|
425
|
-
delete payload.max_output_tokens;
|
|
426
|
-
}
|
|
427
|
-
return {
|
|
428
|
-
protocol: 'openai-chat',
|
|
429
|
-
direction: 'response',
|
|
430
|
-
payload,
|
|
431
|
-
meta: {
|
|
432
|
-
context: ctx
|
|
433
|
-
}
|
|
434
|
-
};
|
|
435
|
-
}
|
|
436
|
-
}
|
|
1
|
+
export { ChatSemanticMapper, maybeAugmentApplyPatchErrorContent } from '../operation-table/semantic-mappers/chat-mapper.js';
|
|
@@ -1,7 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import type { AdapterContext, ChatEnvelope } from '../types/chat-envelope.js';
|
|
3
|
-
import type { FormatEnvelope } from '../types/format-envelope.js';
|
|
4
|
-
export declare class GeminiSemanticMapper implements SemanticMapper {
|
|
5
|
-
toChat(format: FormatEnvelope, ctx: AdapterContext): Promise<ChatEnvelope>;
|
|
6
|
-
fromChat(chat: ChatEnvelope, ctx: AdapterContext): Promise<FormatEnvelope>;
|
|
7
|
-
}
|
|
1
|
+
export { GeminiSemanticMapper } from '../operation-table/semantic-mappers/gemini-mapper.js';
|