@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,21 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import type { AdapterContext, ChatEnvelope } from '../types/chat-envelope.js';
|
|
3
|
-
import type { FormatEnvelope } from '../types/format-envelope.js';
|
|
4
|
-
import { type JsonObject, type JsonValue } from '../types/json.js';
|
|
5
|
-
interface ResponsesToolOutputEntry extends JsonObject {
|
|
6
|
-
tool_call_id?: string;
|
|
7
|
-
call_id?: string;
|
|
8
|
-
id?: string;
|
|
9
|
-
output?: JsonValue;
|
|
10
|
-
name?: string;
|
|
11
|
-
}
|
|
12
|
-
interface ResponsesPayload extends JsonObject {
|
|
13
|
-
input?: JsonValue[];
|
|
14
|
-
tools?: JsonValue[];
|
|
15
|
-
tool_outputs?: ResponsesToolOutputEntry[];
|
|
16
|
-
}
|
|
17
|
-
export declare class ResponsesSemanticMapper implements SemanticMapper {
|
|
18
|
-
toChat(format: FormatEnvelope<ResponsesPayload>, ctx: AdapterContext): Promise<ChatEnvelope>;
|
|
19
|
-
fromChat(chat: ChatEnvelope, ctx: AdapterContext): Promise<FormatEnvelope>;
|
|
20
|
-
}
|
|
21
|
-
export {};
|
|
1
|
+
export { ResponsesSemanticMapper } from '../operation-table/semantic-mappers/responses-mapper.js';
|
|
@@ -1,593 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { createBridgeActionState, runBridgeActionPipeline } from '../../shared/bridge-actions.js';
|
|
3
|
-
import { resolveBridgePolicy, resolvePolicyActions } from '../../shared/bridge-policies.js';
|
|
4
|
-
import { captureResponsesContext, buildChatRequestFromResponses, buildResponsesRequestFromChat } from '../../responses/responses-openai-bridge.js';
|
|
5
|
-
import { maybeAugmentApplyPatchErrorContent } from './chat-mapper.js';
|
|
6
|
-
const RESPONSES_PARAMETER_KEYS = [
|
|
7
|
-
'model',
|
|
8
|
-
'temperature',
|
|
9
|
-
'top_p',
|
|
10
|
-
'top_k',
|
|
11
|
-
'max_tokens',
|
|
12
|
-
'max_output_tokens',
|
|
13
|
-
'response_format',
|
|
14
|
-
'tool_choice',
|
|
15
|
-
'parallel_tool_calls',
|
|
16
|
-
'user',
|
|
17
|
-
'logit_bias',
|
|
18
|
-
'seed',
|
|
19
|
-
'stop',
|
|
20
|
-
'stop_sequences',
|
|
21
|
-
'modalities'
|
|
22
|
-
];
|
|
23
|
-
const RESPONSES_SUBMIT_ENDPOINT = '/v1/responses.submit_tool_outputs';
|
|
24
|
-
function mapToolOutputs(entries, missing) {
|
|
25
|
-
if (!entries || !entries.length)
|
|
26
|
-
return undefined;
|
|
27
|
-
const outputs = [];
|
|
28
|
-
entries.forEach((entry, index) => {
|
|
29
|
-
if (!isJsonObject(entry)) {
|
|
30
|
-
missing.push({ path: `tool_outputs[${index}]`, reason: 'invalid_entry', originalValue: jsonClone(entry) });
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
const callId = entry.tool_call_id || entry.call_id || entry.id;
|
|
34
|
-
if (!callId) {
|
|
35
|
-
missing.push({ path: `tool_outputs[${index}].tool_call_id`, reason: 'missing_tool_call_id' });
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
let content = '';
|
|
39
|
-
if (typeof entry.output === 'string') {
|
|
40
|
-
content = entry.output;
|
|
41
|
-
}
|
|
42
|
-
else if (entry.output != null) {
|
|
43
|
-
try {
|
|
44
|
-
content = JSON.stringify(entry.output);
|
|
45
|
-
}
|
|
46
|
-
catch {
|
|
47
|
-
content = String(entry.output);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
const nameValue = typeof entry.name === 'string' ? entry.name : undefined;
|
|
51
|
-
const augmented = maybeAugmentApplyPatchErrorContent(content, nameValue);
|
|
52
|
-
outputs.push({
|
|
53
|
-
tool_call_id: String(callId),
|
|
54
|
-
content: augmented,
|
|
55
|
-
name: nameValue
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
return outputs.length ? outputs : undefined;
|
|
59
|
-
}
|
|
60
|
-
function deriveResumeToolOutputs(ctx) {
|
|
61
|
-
if (!ctx || typeof ctx !== 'object') {
|
|
62
|
-
return undefined;
|
|
63
|
-
}
|
|
64
|
-
const resume = ctx.responsesResume;
|
|
65
|
-
if (!resume || typeof resume !== 'object') {
|
|
66
|
-
return undefined;
|
|
67
|
-
}
|
|
68
|
-
const detailed = Array.isArray(resume.toolOutputsDetailed)
|
|
69
|
-
? resume.toolOutputsDetailed
|
|
70
|
-
: undefined;
|
|
71
|
-
if (!detailed || detailed.length === 0) {
|
|
72
|
-
return undefined;
|
|
73
|
-
}
|
|
74
|
-
const outputs = [];
|
|
75
|
-
detailed.forEach((entry, index) => {
|
|
76
|
-
if (!entry || typeof entry !== 'object') {
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
const callIdRaw = typeof entry.callId === 'string' && entry.callId.trim().length
|
|
80
|
-
? entry.callId.trim()
|
|
81
|
-
: typeof entry.originalId === 'string' && entry.originalId.trim().length
|
|
82
|
-
? entry.originalId.trim()
|
|
83
|
-
: `resume_tool_${index}`;
|
|
84
|
-
if (!callIdRaw) {
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
const outputText = typeof entry.outputText === 'string' ? entry.outputText : '';
|
|
88
|
-
outputs.push({
|
|
89
|
-
tool_call_id: callIdRaw,
|
|
90
|
-
content: outputText
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
return outputs.length ? outputs : undefined;
|
|
94
|
-
}
|
|
95
|
-
function collectParameters(payload, streamHint) {
|
|
96
|
-
const params = {};
|
|
97
|
-
for (const key of RESPONSES_PARAMETER_KEYS) {
|
|
98
|
-
if (payload[key] !== undefined) {
|
|
99
|
-
params[key] = payload[key];
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
if (streamHint !== undefined) {
|
|
103
|
-
params.stream = streamHint;
|
|
104
|
-
}
|
|
105
|
-
return Object.keys(params).length ? params : undefined;
|
|
106
|
-
}
|
|
107
|
-
function normalizeTools(rawTools, missing) {
|
|
108
|
-
if (!rawTools || rawTools.length === 0)
|
|
109
|
-
return undefined;
|
|
110
|
-
const tools = [];
|
|
111
|
-
rawTools.forEach((tool, index) => {
|
|
112
|
-
if (!tool || typeof tool !== 'object' || Array.isArray(tool)) {
|
|
113
|
-
missing.push({ path: `tools[${index}]`, reason: 'invalid_entry', originalValue: jsonClone(tool) });
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
const fn = tool.function;
|
|
117
|
-
if (!fn || typeof fn !== 'object' || Array.isArray(fn))
|
|
118
|
-
return;
|
|
119
|
-
const name = fn.name;
|
|
120
|
-
const nameValue = typeof name === 'string' ? name : undefined;
|
|
121
|
-
if (!nameValue)
|
|
122
|
-
return;
|
|
123
|
-
const descriptionValue = fn.description;
|
|
124
|
-
const parametersValue = fn.parameters;
|
|
125
|
-
const strictValue = fn.strict;
|
|
126
|
-
const definition = {
|
|
127
|
-
type: 'function',
|
|
128
|
-
function: {
|
|
129
|
-
name: nameValue,
|
|
130
|
-
description: typeof descriptionValue === 'string' ? descriptionValue : undefined,
|
|
131
|
-
parameters: parametersValue,
|
|
132
|
-
strict: typeof strictValue === 'boolean' ? strictValue : undefined
|
|
133
|
-
}
|
|
134
|
-
};
|
|
135
|
-
tools.push(definition);
|
|
136
|
-
});
|
|
137
|
-
return tools.length ? tools : undefined;
|
|
138
|
-
}
|
|
139
|
-
function normalizeMessages(value, missing) {
|
|
140
|
-
if (!Array.isArray(value)) {
|
|
141
|
-
if (value !== undefined) {
|
|
142
|
-
missing.push({ path: 'messages', reason: 'invalid_type', originalValue: jsonClone(value) });
|
|
143
|
-
}
|
|
144
|
-
else {
|
|
145
|
-
missing.push({ path: 'messages', reason: 'absent' });
|
|
146
|
-
}
|
|
147
|
-
return [];
|
|
148
|
-
}
|
|
149
|
-
const messages = [];
|
|
150
|
-
value.forEach((item, index) => {
|
|
151
|
-
if (!item || typeof item !== 'object' || Array.isArray(item)) {
|
|
152
|
-
missing.push({ path: `messages[${index}]`, reason: 'invalid_entry', originalValue: jsonClone(item) });
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
messages.push(item);
|
|
156
|
-
});
|
|
157
|
-
return messages;
|
|
158
|
-
}
|
|
159
|
-
function serializeSystemContent(message) {
|
|
160
|
-
if (!message)
|
|
161
|
-
return undefined;
|
|
162
|
-
const content = message.content;
|
|
163
|
-
if (typeof content === 'string')
|
|
164
|
-
return content;
|
|
165
|
-
if (Array.isArray(content)) {
|
|
166
|
-
const parts = [];
|
|
167
|
-
content.forEach(part => {
|
|
168
|
-
if (typeof part === 'string') {
|
|
169
|
-
parts.push(part);
|
|
170
|
-
}
|
|
171
|
-
else if (part && typeof part === 'object') {
|
|
172
|
-
const text = part.text;
|
|
173
|
-
if (typeof text === 'string') {
|
|
174
|
-
parts.push(text);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
return parts.join('');
|
|
179
|
-
}
|
|
180
|
-
if (content != null) {
|
|
181
|
-
try {
|
|
182
|
-
return JSON.stringify(content);
|
|
183
|
-
}
|
|
184
|
-
catch {
|
|
185
|
-
return String(content);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
return undefined;
|
|
189
|
-
}
|
|
190
|
-
function mergeMetadata(a, b) {
|
|
191
|
-
if (!a && !b) {
|
|
192
|
-
return undefined;
|
|
193
|
-
}
|
|
194
|
-
if (!a && b) {
|
|
195
|
-
return jsonClone(b);
|
|
196
|
-
}
|
|
197
|
-
if (a && !b) {
|
|
198
|
-
return jsonClone(a);
|
|
199
|
-
}
|
|
200
|
-
const left = jsonClone(a);
|
|
201
|
-
const right = jsonClone(b);
|
|
202
|
-
return { ...left, ...right };
|
|
203
|
-
}
|
|
204
|
-
function isSubmitToolOutputsEndpoint(ctx) {
|
|
205
|
-
if (!ctx || typeof ctx !== 'object') {
|
|
206
|
-
return false;
|
|
207
|
-
}
|
|
208
|
-
const entry = typeof ctx.entryEndpoint === 'string' ? ctx.entryEndpoint.trim().toLowerCase() : '';
|
|
209
|
-
return entry === RESPONSES_SUBMIT_ENDPOINT;
|
|
210
|
-
}
|
|
211
|
-
function attachResponsesSemantics(existing, context, resume) {
|
|
212
|
-
if (!context && !resume) {
|
|
213
|
-
return existing;
|
|
214
|
-
}
|
|
215
|
-
const next = existing ? { ...existing } : {};
|
|
216
|
-
const currentNode = next.responses && isJsonObject(next.responses) ? { ...next.responses } : {};
|
|
217
|
-
if (context) {
|
|
218
|
-
currentNode.context = jsonClone(context);
|
|
219
|
-
}
|
|
220
|
-
if (resume) {
|
|
221
|
-
currentNode.resume = jsonClone(resume);
|
|
222
|
-
}
|
|
223
|
-
next.responses = currentNode;
|
|
224
|
-
return next;
|
|
225
|
-
}
|
|
226
|
-
function extractResponsesSemanticsNode(chat) {
|
|
227
|
-
if (!chat?.semantics || typeof chat.semantics !== 'object') {
|
|
228
|
-
return undefined;
|
|
229
|
-
}
|
|
230
|
-
const node = chat.semantics.responses;
|
|
231
|
-
return node && isJsonObject(node) ? node : undefined;
|
|
232
|
-
}
|
|
233
|
-
function readResponsesContextFromSemantics(chat) {
|
|
234
|
-
const node = extractResponsesSemanticsNode(chat);
|
|
235
|
-
if (!node) {
|
|
236
|
-
return undefined;
|
|
237
|
-
}
|
|
238
|
-
const contextNode = node.context;
|
|
239
|
-
if (!contextNode || !isJsonObject(contextNode)) {
|
|
240
|
-
return undefined;
|
|
241
|
-
}
|
|
242
|
-
return jsonClone(contextNode);
|
|
243
|
-
}
|
|
244
|
-
function readResponsesResumeFromSemantics(chat) {
|
|
245
|
-
const node = extractResponsesSemanticsNode(chat);
|
|
246
|
-
if (!node) {
|
|
247
|
-
return undefined;
|
|
248
|
-
}
|
|
249
|
-
const resumeNode = node.resume;
|
|
250
|
-
if (!resumeNode || !isJsonObject(resumeNode)) {
|
|
251
|
-
return undefined;
|
|
252
|
-
}
|
|
253
|
-
return jsonClone(resumeNode);
|
|
254
|
-
}
|
|
255
|
-
function selectResponsesContextSnapshot(chat, envelopeMetadata) {
|
|
256
|
-
const semanticsContext = readResponsesContextFromSemantics(chat);
|
|
257
|
-
const metadataContextCandidate = chat.metadata?.responsesContext;
|
|
258
|
-
const metadataContext = metadataContextCandidate && isJsonObject(metadataContextCandidate)
|
|
259
|
-
? jsonClone(metadataContextCandidate)
|
|
260
|
-
: undefined;
|
|
261
|
-
const context = semanticsContext ??
|
|
262
|
-
metadataContext ??
|
|
263
|
-
{
|
|
264
|
-
metadata: envelopeMetadata
|
|
265
|
-
};
|
|
266
|
-
const mergedMetadata = mergeMetadata(context.metadata ?? undefined, envelopeMetadata);
|
|
267
|
-
if (mergedMetadata) {
|
|
268
|
-
context.metadata = mergedMetadata;
|
|
269
|
-
}
|
|
270
|
-
return context;
|
|
271
|
-
}
|
|
272
|
-
function resolveSubmitResponseId(ctx, responsesContext) {
|
|
273
|
-
const resumeMeta = ctx.responsesResume && typeof ctx.responsesResume === 'object'
|
|
274
|
-
? ctx.responsesResume
|
|
275
|
-
: undefined;
|
|
276
|
-
const resumeId = typeof resumeMeta?.restoredFromResponseId === 'string'
|
|
277
|
-
? resumeMeta.restoredFromResponseId.trim()
|
|
278
|
-
: undefined;
|
|
279
|
-
if (resumeId) {
|
|
280
|
-
return resumeId;
|
|
281
|
-
}
|
|
282
|
-
const contextRecord = responsesContext && typeof responsesContext === 'object'
|
|
283
|
-
? responsesContext
|
|
284
|
-
: undefined;
|
|
285
|
-
const previousId = typeof contextRecord?.previous_response_id === 'string'
|
|
286
|
-
? contextRecord.previous_response_id.trim()
|
|
287
|
-
: undefined;
|
|
288
|
-
if (previousId) {
|
|
289
|
-
return previousId;
|
|
290
|
-
}
|
|
291
|
-
return undefined;
|
|
292
|
-
}
|
|
293
|
-
function extractSubmitMetadata(responsesContext, resumeMeta) {
|
|
294
|
-
if (responsesContext && responsesContext.metadata && isJsonObject(responsesContext.metadata)) {
|
|
295
|
-
return jsonClone(responsesContext.metadata);
|
|
296
|
-
}
|
|
297
|
-
if (resumeMeta && resumeMeta.metadata && isJsonObject(resumeMeta.metadata)) {
|
|
298
|
-
return jsonClone(resumeMeta.metadata);
|
|
299
|
-
}
|
|
300
|
-
return undefined;
|
|
301
|
-
}
|
|
302
|
-
function coerceOutputText(value) {
|
|
303
|
-
if (typeof value === 'string') {
|
|
304
|
-
return value;
|
|
305
|
-
}
|
|
306
|
-
if (value === undefined || value === null) {
|
|
307
|
-
return '';
|
|
308
|
-
}
|
|
309
|
-
try {
|
|
310
|
-
return JSON.stringify(value);
|
|
311
|
-
}
|
|
312
|
-
catch {
|
|
313
|
-
return String(value);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
function extractCapturedToolOutputs(responsesContext) {
|
|
317
|
-
if (!responsesContext || typeof responsesContext !== 'object') {
|
|
318
|
-
return [];
|
|
319
|
-
}
|
|
320
|
-
const snapshot = responsesContext.__captured_tool_results;
|
|
321
|
-
if (!Array.isArray(snapshot) || !snapshot.length) {
|
|
322
|
-
return [];
|
|
323
|
-
}
|
|
324
|
-
const entries = [];
|
|
325
|
-
snapshot.forEach((entry) => {
|
|
326
|
-
if (!entry || typeof entry !== 'object') {
|
|
327
|
-
return;
|
|
328
|
-
}
|
|
329
|
-
const record = entry;
|
|
330
|
-
const toolId = typeof record.tool_call_id === 'string' && record.tool_call_id.trim().length
|
|
331
|
-
? record.tool_call_id.trim()
|
|
332
|
-
: typeof record.call_id === 'string' && record.call_id.trim().length
|
|
333
|
-
? record.call_id.trim()
|
|
334
|
-
: undefined;
|
|
335
|
-
if (!toolId) {
|
|
336
|
-
return;
|
|
337
|
-
}
|
|
338
|
-
entries.push({
|
|
339
|
-
tool_call_id: toolId,
|
|
340
|
-
id: toolId,
|
|
341
|
-
output: typeof record.output === 'string' ? record.output : coerceOutputText(record.output),
|
|
342
|
-
name: typeof record.name === 'string' ? record.name : undefined
|
|
343
|
-
});
|
|
344
|
-
});
|
|
345
|
-
return entries;
|
|
346
|
-
}
|
|
347
|
-
function collectSubmitToolOutputs(chat, ctx, responsesContext) {
|
|
348
|
-
const outputs = [];
|
|
349
|
-
const seen = new Set();
|
|
350
|
-
const append = (idSeed, outputSeed, name) => {
|
|
351
|
-
const trimmed = typeof idSeed === 'string' && idSeed.trim().length ? idSeed.trim() : '';
|
|
352
|
-
const fallbackId = trimmed || `submit_tool_${outputs.length + 1}`;
|
|
353
|
-
if (seen.has(fallbackId)) {
|
|
354
|
-
return;
|
|
355
|
-
}
|
|
356
|
-
seen.add(fallbackId);
|
|
357
|
-
outputs.push({
|
|
358
|
-
tool_call_id: fallbackId,
|
|
359
|
-
id: fallbackId,
|
|
360
|
-
output: coerceOutputText(outputSeed),
|
|
361
|
-
name
|
|
362
|
-
});
|
|
363
|
-
};
|
|
364
|
-
if (Array.isArray(chat.toolOutputs) && chat.toolOutputs.length) {
|
|
365
|
-
chat.toolOutputs.forEach((entry) => {
|
|
366
|
-
append(entry.tool_call_id ?? entry.call_id, entry.content, entry.name);
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
if (!outputs.length) {
|
|
370
|
-
const captured = extractCapturedToolOutputs(responsesContext);
|
|
371
|
-
captured.forEach((entry) => append(entry.tool_call_id ?? entry.id, entry.output, entry.name));
|
|
372
|
-
}
|
|
373
|
-
if (!outputs.length) {
|
|
374
|
-
const resume = ctx.responsesResume && typeof ctx.responsesResume === 'object'
|
|
375
|
-
? ctx.responsesResume
|
|
376
|
-
: undefined;
|
|
377
|
-
const detailed = Array.isArray(resume?.toolOutputsDetailed)
|
|
378
|
-
? resume?.toolOutputsDetailed
|
|
379
|
-
: undefined;
|
|
380
|
-
if (detailed) {
|
|
381
|
-
detailed.forEach((entry, index) => {
|
|
382
|
-
if (!entry || typeof entry !== 'object') {
|
|
383
|
-
return;
|
|
384
|
-
}
|
|
385
|
-
const callId = typeof entry.callId === 'string' && entry.callId.trim().length
|
|
386
|
-
? entry.callId.trim()
|
|
387
|
-
: typeof entry.originalId === 'string' && entry.originalId.trim().length
|
|
388
|
-
? entry.originalId.trim()
|
|
389
|
-
: `resume_tool_${index + 1}`;
|
|
390
|
-
append(callId, typeof entry.outputText === 'string' ? entry.outputText : entry.outputText ?? '');
|
|
391
|
-
});
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
return outputs;
|
|
395
|
-
}
|
|
396
|
-
function resolveSubmitStreamFlag(chat, ctx, responsesContext) {
|
|
397
|
-
if (chat.parameters && typeof chat.parameters.stream === 'boolean') {
|
|
398
|
-
return chat.parameters.stream;
|
|
399
|
-
}
|
|
400
|
-
if (responsesContext && typeof responsesContext.stream === 'boolean') {
|
|
401
|
-
return responsesContext.stream;
|
|
402
|
-
}
|
|
403
|
-
if (ctx.streamingHint === 'force') {
|
|
404
|
-
return true;
|
|
405
|
-
}
|
|
406
|
-
if (ctx.streamingHint === 'disable') {
|
|
407
|
-
return false;
|
|
408
|
-
}
|
|
409
|
-
return undefined;
|
|
410
|
-
}
|
|
411
|
-
function resolveSubmitModel(chat, responsesContext) {
|
|
412
|
-
const direct = chat.parameters && typeof chat.parameters.model === 'string'
|
|
413
|
-
? chat.parameters.model.trim()
|
|
414
|
-
: undefined;
|
|
415
|
-
if (direct) {
|
|
416
|
-
return direct;
|
|
417
|
-
}
|
|
418
|
-
if (responsesContext && typeof responsesContext.parameters === 'object') {
|
|
419
|
-
const params = responsesContext.parameters;
|
|
420
|
-
const model = typeof params.model === 'string' ? params.model.trim() : undefined;
|
|
421
|
-
if (model) {
|
|
422
|
-
return model;
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
return undefined;
|
|
426
|
-
}
|
|
427
|
-
function buildSubmitToolOutputsPayload(chat, ctx, responsesContext) {
|
|
428
|
-
const responseId = resolveSubmitResponseId(ctx, responsesContext);
|
|
429
|
-
if (!responseId) {
|
|
430
|
-
throw new Error('Submit tool outputs requires response_id from Responses resume context');
|
|
431
|
-
}
|
|
432
|
-
const toolOutputs = collectSubmitToolOutputs(chat, ctx, responsesContext);
|
|
433
|
-
if (!toolOutputs.length) {
|
|
434
|
-
throw new Error('Submit tool outputs requires at least one tool output entry');
|
|
435
|
-
}
|
|
436
|
-
const resumeMeta = ctx.responsesResume && typeof ctx.responsesResume === 'object'
|
|
437
|
-
? ctx.responsesResume
|
|
438
|
-
: undefined;
|
|
439
|
-
const payload = {
|
|
440
|
-
response_id: responseId,
|
|
441
|
-
tool_outputs: toolOutputs
|
|
442
|
-
};
|
|
443
|
-
const modelValue = resolveSubmitModel(chat, responsesContext);
|
|
444
|
-
if (modelValue) {
|
|
445
|
-
payload.model = modelValue;
|
|
446
|
-
}
|
|
447
|
-
const streamValue = resolveSubmitStreamFlag(chat, ctx, responsesContext);
|
|
448
|
-
if (typeof streamValue === 'boolean') {
|
|
449
|
-
payload.stream = streamValue;
|
|
450
|
-
}
|
|
451
|
-
const metadata = extractSubmitMetadata(responsesContext, resumeMeta);
|
|
452
|
-
if (metadata) {
|
|
453
|
-
payload.metadata = metadata;
|
|
454
|
-
}
|
|
455
|
-
return payload;
|
|
456
|
-
}
|
|
457
|
-
export class ResponsesSemanticMapper {
|
|
458
|
-
async toChat(format, ctx) {
|
|
459
|
-
const payload = format.payload || {};
|
|
460
|
-
const responsesContext = captureResponsesContext(payload, { route: { requestId: ctx.requestId } });
|
|
461
|
-
const { request, toolsNormalized } = buildChatRequestFromResponses(payload, responsesContext);
|
|
462
|
-
const missingFields = [];
|
|
463
|
-
const messages = normalizeMessages(request.messages, missingFields);
|
|
464
|
-
let toolOutputs = mapToolOutputs(payload.tool_outputs, missingFields);
|
|
465
|
-
if (!toolOutputs || toolOutputs.length === 0) {
|
|
466
|
-
const resumeToolOutputs = deriveResumeToolOutputs(ctx);
|
|
467
|
-
if (resumeToolOutputs && resumeToolOutputs.length) {
|
|
468
|
-
toolOutputs = resumeToolOutputs;
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
const parameters = collectParameters(payload, responsesContext.stream);
|
|
472
|
-
const metadata = { context: ctx };
|
|
473
|
-
try {
|
|
474
|
-
const bridgePolicy = resolveBridgePolicy({ protocol: 'openai-responses', moduleType: 'openai-responses' });
|
|
475
|
-
const actions = resolvePolicyActions(bridgePolicy, 'request_inbound');
|
|
476
|
-
if (actions?.length) {
|
|
477
|
-
const capturedToolResults = Array.isArray(toolOutputs)
|
|
478
|
-
? toolOutputs.map((entry) => ({
|
|
479
|
-
tool_call_id: entry.tool_call_id,
|
|
480
|
-
output: entry.content,
|
|
481
|
-
name: entry.name
|
|
482
|
-
}))
|
|
483
|
-
: undefined;
|
|
484
|
-
const actionState = createBridgeActionState({
|
|
485
|
-
rawRequest: payload,
|
|
486
|
-
metadata: metadata,
|
|
487
|
-
capturedToolResults
|
|
488
|
-
});
|
|
489
|
-
runBridgeActionPipeline({
|
|
490
|
-
stage: 'request_inbound',
|
|
491
|
-
actions,
|
|
492
|
-
protocol: bridgePolicy?.protocol ?? 'openai-responses',
|
|
493
|
-
moduleType: bridgePolicy?.moduleType ?? 'openai-responses',
|
|
494
|
-
requestId: ctx.requestId,
|
|
495
|
-
state: actionState
|
|
496
|
-
});
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
catch {
|
|
500
|
-
// ignore policy hook failures
|
|
501
|
-
}
|
|
502
|
-
if (missingFields.length) {
|
|
503
|
-
metadata.missingFields = missingFields;
|
|
504
|
-
}
|
|
505
|
-
if (responsesContext.responseFormat) {
|
|
506
|
-
metadata.responseFormat = jsonClone(responsesContext.responseFormat);
|
|
507
|
-
}
|
|
508
|
-
metadata.responsesContext = jsonClone(responsesContext);
|
|
509
|
-
const resumeNode = ctx.responsesResume && isJsonObject(ctx.responsesResume)
|
|
510
|
-
? ctx.responsesResume
|
|
511
|
-
: undefined;
|
|
512
|
-
const semantics = attachResponsesSemantics(undefined, responsesContext, resumeNode);
|
|
513
|
-
return {
|
|
514
|
-
messages,
|
|
515
|
-
tools: normalizeTools(toolsNormalized, missingFields),
|
|
516
|
-
toolOutputs,
|
|
517
|
-
parameters,
|
|
518
|
-
semantics,
|
|
519
|
-
metadata
|
|
520
|
-
};
|
|
521
|
-
}
|
|
522
|
-
async fromChat(chat, ctx) {
|
|
523
|
-
const envelopeMetadata = chat.metadata && isJsonObject(chat.metadata) ? chat.metadata : undefined;
|
|
524
|
-
const responsesContext = selectResponsesContextSnapshot(chat, envelopeMetadata);
|
|
525
|
-
if (isSubmitToolOutputsEndpoint(ctx)) {
|
|
526
|
-
const submitPayload = buildSubmitToolOutputsPayload(chat, ctx, responsesContext);
|
|
527
|
-
return {
|
|
528
|
-
protocol: 'openai-responses',
|
|
529
|
-
direction: 'response',
|
|
530
|
-
payload: submitPayload,
|
|
531
|
-
meta: {
|
|
532
|
-
context: ctx,
|
|
533
|
-
submitToolOutputs: true
|
|
534
|
-
}
|
|
535
|
-
};
|
|
536
|
-
}
|
|
537
|
-
const modelValue = chat.parameters?.model;
|
|
538
|
-
if (typeof modelValue !== 'string' || !modelValue.trim()) {
|
|
539
|
-
throw new Error('ChatEnvelope.parameters.model is required for openai-responses outbound conversion');
|
|
540
|
-
}
|
|
541
|
-
const requestShape = {
|
|
542
|
-
...(chat.parameters || {}),
|
|
543
|
-
model: modelValue,
|
|
544
|
-
messages: chat.messages,
|
|
545
|
-
tools: chat.tools
|
|
546
|
-
};
|
|
547
|
-
const originalSystemMessages = (chat.messages || [])
|
|
548
|
-
.filter((message) => Boolean(message && typeof message === 'object' && message.role === 'system'))
|
|
549
|
-
.map(message => serializeSystemContent(message))
|
|
550
|
-
.filter((content) => typeof content === 'string' && content.length > 0);
|
|
551
|
-
responsesContext.originalSystemMessages = originalSystemMessages;
|
|
552
|
-
const responsesResult = buildResponsesRequestFromChat(requestShape, responsesContext);
|
|
553
|
-
const responses = responsesResult.request;
|
|
554
|
-
if (chat.parameters && chat.parameters.stream !== undefined) {
|
|
555
|
-
responses.stream = chat.parameters.stream;
|
|
556
|
-
}
|
|
557
|
-
// Do not forward ChatEnvelope.toolOutputs to OpenAI Responses create requests.
|
|
558
|
-
// Upstream expects historical tool results to remain inside input[] as
|
|
559
|
-
// tool role messages; sending the legacy top-level `tool_outputs` field
|
|
560
|
-
// causes providers like FAI to reject the request (HTTP 400). Any actual
|
|
561
|
-
// submit_tool_outputs call should be issued via the dedicated endpoint
|
|
562
|
-
// upstream, not through this mapper.
|
|
563
|
-
try {
|
|
564
|
-
const bridgePolicy = resolveBridgePolicy({ protocol: 'openai-responses', moduleType: 'openai-responses' });
|
|
565
|
-
const actions = resolvePolicyActions(bridgePolicy, 'request_outbound');
|
|
566
|
-
if (actions?.length) {
|
|
567
|
-
const actionState = createBridgeActionState({
|
|
568
|
-
rawRequest: responses,
|
|
569
|
-
metadata: chat.metadata
|
|
570
|
-
});
|
|
571
|
-
runBridgeActionPipeline({
|
|
572
|
-
stage: 'request_outbound',
|
|
573
|
-
actions,
|
|
574
|
-
protocol: bridgePolicy?.protocol ?? 'openai-responses',
|
|
575
|
-
moduleType: bridgePolicy?.moduleType ?? 'openai-responses',
|
|
576
|
-
requestId: ctx.requestId,
|
|
577
|
-
state: actionState
|
|
578
|
-
});
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
catch {
|
|
582
|
-
// ignore metadata propagation failures
|
|
583
|
-
}
|
|
584
|
-
return {
|
|
585
|
-
protocol: 'openai-responses',
|
|
586
|
-
direction: 'response',
|
|
587
|
-
payload: responses,
|
|
588
|
-
meta: {
|
|
589
|
-
context: ctx
|
|
590
|
-
}
|
|
591
|
-
};
|
|
592
|
-
}
|
|
593
|
-
}
|
|
1
|
+
export { ResponsesSemanticMapper } from '../operation-table/semantic-mappers/responses-mapper.js';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { StageRecorder } from '../format-adapters/index.js';
|
|
2
|
+
import type { JsonObject } from '../types/json.js';
|
|
3
|
+
export type HubToolSurfaceMode = 'off' | 'observe' | 'shadow' | 'enforce';
|
|
4
|
+
export interface HubToolSurfaceConfig {
|
|
5
|
+
mode: HubToolSurfaceMode;
|
|
6
|
+
/**
|
|
7
|
+
* Range: 0..1. When omitted, defaults to 1 (always on for the selected mode).
|
|
8
|
+
* Sampling is request-id stable to avoid non-deterministic diffs.
|
|
9
|
+
*/
|
|
10
|
+
sampleRate?: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function applyProviderOutboundToolSurface(args: {
|
|
13
|
+
config?: HubToolSurfaceConfig;
|
|
14
|
+
providerProtocol: string;
|
|
15
|
+
payload: JsonObject;
|
|
16
|
+
stageRecorder?: StageRecorder;
|
|
17
|
+
requestId?: string;
|
|
18
|
+
}): JsonObject;
|