@jsonstudio/llms 0.6.802 → 0.6.938
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/bridge/routecodex-adapter.d.ts +74 -0
- package/dist/config-unified/enhanced-path-resolver.d.ts +5 -0
- package/dist/config-unified/unified-config.d.ts +26 -0
- package/dist/conversion/codec-registry.d.ts +10 -0
- package/dist/conversion/codecs/gemini-openai-codec.d.ts +16 -0
- package/dist/conversion/codecs/openai-openai-codec.d.ts +12 -0
- package/dist/conversion/codecs/responses-openai-codec.d.ts +12 -0
- package/dist/conversion/compat/profiles/chat-gemini.json +12 -0
- package/dist/conversion/config/config-manager.d.ts +212 -0
- package/dist/conversion/hub/config/types.d.ts +26 -0
- package/dist/conversion/hub/core/detour-registry.d.ts +9 -0
- package/dist/conversion/hub/core/hub-context.d.ts +21 -0
- package/dist/conversion/hub/core/index.d.ts +3 -0
- package/dist/conversion/hub/core/stage-driver.d.ts +30 -0
- package/dist/conversion/hub/format-adapters/anthropic-format-adapter.d.ts +16 -0
- package/dist/conversion/hub/format-adapters/chat-format-adapter.d.ts +17 -0
- package/dist/conversion/hub/format-adapters/gemini-format-adapter.d.ts +16 -0
- package/dist/conversion/hub/format-adapters/index.d.ts +21 -0
- package/dist/conversion/hub/hub-feature.d.ts +1 -0
- package/dist/conversion/hub/node-support.d.ts +19 -0
- package/dist/conversion/hub/pipeline/compat/compat-pipeline-executor.js +11 -0
- package/dist/conversion/hub/pipeline/compat/compat-types.d.ts +3 -0
- package/dist/conversion/hub/pipeline/hub-pipeline.d.ts +7 -0
- package/dist/conversion/hub/pipeline/hub-pipeline.js +71 -14
- package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage1_tool_governance/index.js +4 -0
- package/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/index.js +23 -1
- package/dist/conversion/hub/pipelines/inbound.d.ts +22 -0
- package/dist/conversion/hub/pipelines/outbound.d.ts +22 -0
- package/dist/conversion/hub/policy/policy-engine.d.ts +46 -0
- package/dist/conversion/hub/policy/policy-engine.js +176 -0
- package/dist/conversion/hub/policy/protocol-spec.d.ts +50 -0
- package/dist/conversion/hub/policy/protocol-spec.js +105 -0
- package/dist/conversion/hub/process/chat-process.d.ts +32 -0
- package/dist/conversion/hub/registry.d.ts +28 -0
- package/dist/conversion/hub/response/chat-response-utils.d.ts +6 -0
- package/dist/conversion/hub/response/provider-response.js +31 -0
- package/dist/conversion/hub/semantic-mappers/gemini-mapper.d.ts +7 -0
- package/dist/conversion/hub/semantic-mappers/gemini-mapper.js +87 -1
- package/dist/conversion/hub/semantic-mappers/index.d.ts +4 -0
- package/dist/conversion/hub/semantic-mappers/responses-mapper.d.ts +21 -0
- package/dist/conversion/hub/standardized-bridge.d.ts +12 -0
- package/dist/conversion/hub/types/chat-schema.d.ts +112 -0
- package/dist/conversion/hub/types/errors.d.ts +5 -0
- package/dist/conversion/hub/types/format-envelope.d.ts +7 -0
- package/dist/conversion/hub/types/index.d.ts +6 -0
- package/dist/conversion/hub/types/json.d.ts +9 -0
- package/dist/conversion/hub/types/node.d.ts +31 -0
- package/dist/conversion/responses/responses-openai-bridge.js +263 -10
- package/dist/conversion/schema-validator.d.ts +7 -0
- package/dist/conversion/shared/args-mapping.d.ts +18 -0
- package/dist/conversion/shared/chat-request-filters.d.ts +9 -0
- package/dist/conversion/shared/errors.d.ts +1 -1
- package/dist/conversion/shared/gemini-tool-utils.js +61 -0
- package/dist/conversion/shared/jsonish.d.ts +3 -0
- package/dist/conversion/shared/mcp-injection.d.ts +2 -0
- package/dist/conversion/shared/media.d.ts +1 -0
- package/dist/conversion/shared/openai-message-normalize.d.ts +1 -0
- package/dist/conversion/shared/payload-budget.d.ts +13 -0
- package/dist/conversion/shared/reasoning-mapping.d.ts +5 -0
- package/dist/conversion/shared/responses-request-adapter.d.ts +1 -28
- package/dist/conversion/shared/responses-request-adapter.js +1 -430
- package/dist/conversion/shared/snapshot-hooks.js +58 -3
- package/dist/conversion/shared/tool-governor.js +8 -2
- package/dist/conversion/shared/tool-harvester.d.ts +31 -0
- package/dist/conversion/shared/tool-mapping.js +10 -29
- package/dist/conversion/types.d.ts +33 -0
- package/dist/filters/builtin/add-fields-filter.d.ts +8 -0
- package/dist/filters/builtin/blacklist-filter.d.ts +8 -0
- package/dist/filters/builtin/whitelist-filter.d.ts +8 -0
- package/dist/filters/engine.d.ts +16 -0
- package/dist/filters/special/request-tool-choice-policy.d.ts +11 -0
- package/dist/filters/special/response-finish-invariants.d.ts +11 -0
- package/dist/filters/special/response-openai-to-responses-bridge.d.ts +13 -0
- package/dist/filters/special/response-tool-arguments-blacklist.d.ts +12 -0
- package/dist/filters/special/response-tool-arguments-schema-converge.d.ts +13 -0
- package/dist/filters/special/response-tool-arguments-stringify.d.ts +9 -0
- package/dist/filters/special/response-tool-arguments-whitelist.d.ts +11 -0
- package/dist/filters/special/tool-filter-hooks.d.ts +19 -0
- package/dist/filters/special/tool-post-constraints.d.ts +31 -0
- package/dist/filters/types.d.ts +68 -0
- package/dist/filters/utils/fieldmap-loader.d.ts +2 -0
- package/dist/filters/utils/snapshot-writer.d.ts +10 -0
- package/dist/guidance/index.d.ts +3 -0
- package/dist/guidance/index.js +78 -83
- package/dist/http/sse-response.d.ts +22 -0
- package/dist/router/virtual-router/bootstrap.d.ts +6 -0
- package/dist/router/virtual-router/bootstrap.js +49 -5
- package/dist/router/virtual-router/classifier.d.ts +10 -0
- package/dist/router/virtual-router/engine-selection.js +98 -11
- package/dist/router/virtual-router/engine.js +177 -31
- package/dist/router/virtual-router/error-center.d.ts +10 -0
- package/dist/router/virtual-router/features.d.ts +3 -0
- package/dist/router/virtual-router/routing-instructions.d.ts +23 -1
- package/dist/router/virtual-router/routing-instructions.js +120 -30
- package/dist/router/virtual-router/types.d.ts +11 -0
- package/dist/servertool/engine.js +189 -16
- package/dist/servertool/handlers/apply-patch-guard.js +269 -0
- package/dist/servertool/handlers/exec-command-guard.js +558 -0
- package/dist/servertool/handlers/followup-message-trimmer.d.ts +16 -0
- package/dist/servertool/handlers/followup-message-trimmer.js +198 -0
- package/dist/servertool/handlers/followup-request-builder.d.ts +17 -0
- package/dist/servertool/handlers/followup-request-builder.js +122 -0
- package/dist/servertool/handlers/gemini-empty-reply-continue.js +252 -51
- package/dist/servertool/handlers/iflow-model-error-retry.js +12 -22
- package/dist/servertool/handlers/stop-message-auto.js +237 -75
- package/dist/servertool/handlers/vision.js +15 -27
- package/dist/servertool/handlers/web-search.js +17 -43
- package/dist/servertool/server-side-tools.d.ts +3 -0
- package/dist/servertool/server-side-tools.js +3 -0
- package/dist/sse/json-to-sse/anthropic-json-to-sse-converter.d.ts +2 -1
- package/dist/sse/json-to-sse/chat-json-to-sse-converter.d.ts +80 -0
- package/dist/sse/json-to-sse/event-generators/chat.d.ts +55 -0
- package/dist/sse/json-to-sse/event-generators/responses.d.ts +99 -0
- package/dist/sse/json-to-sse/gemini-json-to-sse-converter.d.ts +2 -1
- package/dist/sse/json-to-sse/responses-json-to-sse-converter.d.ts +80 -0
- package/dist/sse/json-to-sse/sequencers/anthropic-sequencer.d.ts +1 -1
- package/dist/sse/json-to-sse/sequencers/chat-sequencer.d.ts +2 -2
- package/dist/sse/json-to-sse/sequencers/gemini-sequencer.d.ts +1 -1
- package/dist/sse/json-to-sse/sequencers/responses-sequencer.d.ts +40 -0
- package/dist/sse/shared/chat-serializer.d.ts +4 -0
- package/dist/sse/shared/constants.d.ts +272 -0
- package/dist/sse/shared/serializers/anthropic-event-serializer.d.ts +1 -1
- package/dist/sse/shared/serializers/base-serializer.d.ts +158 -0
- package/dist/sse/shared/serializers/chat-event-serializer.d.ts +82 -0
- package/dist/sse/shared/serializers/gemini-event-serializer.d.ts +1 -1
- package/dist/sse/shared/serializers/index.d.ts +2 -1
- package/dist/sse/shared/serializers/responses-event-serializer.d.ts +123 -0
- package/dist/sse/shared/serializers/types.d.ts +51 -0
- package/dist/sse/shared/utils.d.ts +254 -0
- package/dist/sse/shared/writer.d.ts +2 -2
- package/dist/sse/sse-to-json/anthropic-sse-to-json-converter.d.ts +1 -1
- package/dist/sse/sse-to-json/builders/anthropic-response-builder.d.ts +1 -1
- package/dist/sse/sse-to-json/builders/response-builder.d.ts +1 -1
- package/dist/sse/sse-to-json/chat-sse-to-json-converter.d.ts +2 -1
- package/dist/sse/sse-to-json/gemini-sse-to-json-converter.d.ts +2 -1
- package/dist/sse/sse-to-json/parsers/sse-parser.d.ts +73 -0
- package/dist/sse/sse-to-json/responses-sse-to-json-converter.d.ts +1 -1
- package/dist/sse/types/chat-types.d.ts +1 -1
- package/dist/sse/types/responses-types.d.ts +1 -1
- package/dist/tools/apply-patch/execution-capturer.d.ts +13 -0
- package/dist/tools/apply-patch/execution-capturer.js +158 -0
- package/dist/tools/apply-patch/regression-capturer.d.ts +1 -0
- package/dist/tools/apply-patch/regression-capturer.js +5 -4
- package/dist/tools/apply-patch/structured.js +109 -13
- package/dist/tools/apply-patch/validator.js +112 -18
- package/dist/tools/tool-registry.d.ts +8 -0
- package/dist/tools/tool-registry.js +2 -1
- package/package.json +4 -4
- package/dist/conversion/compat/actions/apply-patch-format-fixer.js +0 -233
- package/dist/conversion/config/compat-profiles.json +0 -38
- package/dist/conversion/hub/pipeline/context-limit.d.ts +0 -13
- package/dist/conversion/hub/pipeline/context-limit.js +0 -55
- package/dist/conversion/hub/response/server-side-tools.d.ts +0 -26
- package/dist/conversion/hub/response/server-side-tools.js +0 -383
- package/dist/conversion/shared/bridge-conversation-store.d.ts +0 -41
- package/dist/conversion/shared/bridge-conversation-store.js +0 -279
- package/dist/conversion/shared/bridge-request-adapter.d.ts +0 -28
- package/dist/conversion/shared/bridge-request-adapter.js +0 -430
- package/dist/conversion/shared/responses-id-utils.js +0 -42
- package/dist/conversion/shared/responses-instructions.js +0 -113
- package/dist/conversion/shared/responses-message-utils.d.ts +0 -15
- package/dist/conversion/shared/responses-message-utils.js +0 -206
- package/dist/conversion/shared/responses-metadata.js +0 -1
- package/dist/conversion/shared/responses-output-utils.d.ts +0 -7
- package/dist/conversion/shared/responses-output-utils.js +0 -108
- package/dist/conversion/shared/responses-types.d.ts +0 -33
- package/dist/conversion/shared/tool-normalizers.d.ts +0 -4
- package/dist/conversion/shared/tool-normalizers.js +0 -84
- package/dist/filters/special/request-streaming-to-nonstreaming.d.ts +0 -13
- package/dist/filters/special/request-streaming-to-nonstreaming.js +0 -39
- package/dist/filters/special/response-apply-patch-toon-decode.d.ts +0 -23
- package/dist/filters/special/response-apply-patch-toon-decode.js +0 -460
- package/dist/filters/special/response-tool-arguments-toon-decode.d.ts +0 -10
- package/dist/filters/special/response-tool-arguments-toon-decode.js +0 -154
- package/dist/servertool/flow-types.d.ts +0 -40
- package/dist/servertool/flow-types.js +0 -1
- package/dist/servertool/orchestration-types.d.ts +0 -33
- package/dist/servertool/orchestration-types.js +0 -1
- package/dist/servertool/vision-tool.d.ts +0 -2
- package/dist/servertool/vision-tool.js +0 -185
- package/dist/tools/patch-args-normalizer.d.ts +0 -15
- package/dist/tools/patch-args-normalizer.js +0 -472
- package/dist/utils/toon.d.ts +0 -4
- package/dist/utils/toon.js +0 -75
- /package/dist/{conversion/compat/actions/apply-patch-format-fixer.d.ts → servertool/handlers/apply-patch-guard.d.ts} +0 -0
- /package/dist/{conversion/shared/responses-types.js → servertool/handlers/exec-command-guard.d.ts} +0 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
function isMessageRecord(value) {
|
|
2
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
3
|
+
}
|
|
4
|
+
function normalizeRole(role) {
|
|
5
|
+
return typeof role === 'string' ? role.trim().toLowerCase() : '';
|
|
6
|
+
}
|
|
7
|
+
function isSystemRole(role) {
|
|
8
|
+
const normalized = role.trim().toLowerCase();
|
|
9
|
+
return normalized === 'system' || normalized === 'developer';
|
|
10
|
+
}
|
|
11
|
+
function isUserMessage(msg) {
|
|
12
|
+
return normalizeRole(msg.role) === 'user';
|
|
13
|
+
}
|
|
14
|
+
function isToolResponseMessage(msg) {
|
|
15
|
+
const role = normalizeRole(msg.role);
|
|
16
|
+
return role === 'tool' || role === 'function';
|
|
17
|
+
}
|
|
18
|
+
function isAssistantToolCallMessage(msg) {
|
|
19
|
+
const role = normalizeRole(msg.role);
|
|
20
|
+
if (role !== 'assistant' && role !== 'model') {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
const toolCalls = Array.isArray(msg.tool_calls)
|
|
24
|
+
? (msg.tool_calls)
|
|
25
|
+
: [];
|
|
26
|
+
if (toolCalls.length > 0) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
const fnCall = msg.function_call;
|
|
30
|
+
if (fnCall && typeof fnCall === 'object' && !Array.isArray(fnCall)) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
function findPrevIndex(messages, startIndexExclusive, predicate) {
|
|
36
|
+
for (let i = startIndexExclusive - 1; i >= 0; i -= 1) {
|
|
37
|
+
const msg = messages[i];
|
|
38
|
+
if (!msg)
|
|
39
|
+
continue;
|
|
40
|
+
if (predicate(msg))
|
|
41
|
+
return i;
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Trim OpenAI-style messages for internal servertool followups.
|
|
47
|
+
*
|
|
48
|
+
* Goal: avoid sending a massive chat history on auto-followup requests (e.g. stop_message_flow),
|
|
49
|
+
* which can push Gemini/Antigravity into empty/malformed responses under long-context loads.
|
|
50
|
+
*
|
|
51
|
+
* Strategy:
|
|
52
|
+
* - Always keep system/developer messages (regardless of position).
|
|
53
|
+
* - Keep only the tail of non-system messages (maxNonSystemMessages), preserving original order.
|
|
54
|
+
*/
|
|
55
|
+
export function trimOpenAiMessagesForFollowup(rawMessages, options) {
|
|
56
|
+
const maxNonSystemMessages = typeof options?.maxNonSystemMessages === 'number' && Number.isFinite(options.maxNonSystemMessages)
|
|
57
|
+
? Math.max(1, Math.floor(options.maxNonSystemMessages))
|
|
58
|
+
: 16;
|
|
59
|
+
const messages = Array.isArray(rawMessages) ? rawMessages : [];
|
|
60
|
+
if (!messages.length) {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
const messageRecords = messages.filter(isMessageRecord);
|
|
64
|
+
if (!messageRecords.length) {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
const nonSystemIndices = [];
|
|
68
|
+
for (let i = 0; i < messageRecords.length; i += 1) {
|
|
69
|
+
const entry = messageRecords[i];
|
|
70
|
+
const role = typeof entry.role === 'string' ? entry.role : '';
|
|
71
|
+
if (!role || isSystemRole(role)) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
nonSystemIndices.push(i);
|
|
75
|
+
}
|
|
76
|
+
if (nonSystemIndices.length <= maxNonSystemMessages) {
|
|
77
|
+
return messageRecords;
|
|
78
|
+
}
|
|
79
|
+
const keepSet = new Set(nonSystemIndices.slice(nonSystemIndices.length - maxNonSystemMessages));
|
|
80
|
+
// Expand keepSet to preserve tool-call adjacency:
|
|
81
|
+
// - If we keep tool responses, keep their preceding tool call + its anchor.
|
|
82
|
+
// - If we keep tool calls, keep their anchor + following tool responses.
|
|
83
|
+
//
|
|
84
|
+
// Gemini tool-calling constraint: functionCall turn must come immediately after a user turn
|
|
85
|
+
// or after a functionResponse turn. When trimming, we must not cut away the user anchor.
|
|
86
|
+
let changed = true;
|
|
87
|
+
let guard = 0;
|
|
88
|
+
while (changed && guard < 8) {
|
|
89
|
+
changed = false;
|
|
90
|
+
guard += 1;
|
|
91
|
+
const sorted = Array.from(keepSet).sort((a, b) => a - b);
|
|
92
|
+
for (const idx of sorted) {
|
|
93
|
+
const msg = messageRecords[idx];
|
|
94
|
+
if (!msg)
|
|
95
|
+
continue;
|
|
96
|
+
if (isToolResponseMessage(msg)) {
|
|
97
|
+
const toolCallIndex = findPrevIndex(messageRecords, idx, isAssistantToolCallMessage);
|
|
98
|
+
if (toolCallIndex !== null && !keepSet.has(toolCallIndex)) {
|
|
99
|
+
keepSet.add(toolCallIndex);
|
|
100
|
+
changed = true;
|
|
101
|
+
}
|
|
102
|
+
if (toolCallIndex !== null) {
|
|
103
|
+
const anchorIndex = findPrevIndex(messageRecords, toolCallIndex, (m) => isUserMessage(m) || isToolResponseMessage(m));
|
|
104
|
+
if (anchorIndex !== null && !keepSet.has(anchorIndex)) {
|
|
105
|
+
keepSet.add(anchorIndex);
|
|
106
|
+
changed = true;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
if (isAssistantToolCallMessage(msg)) {
|
|
112
|
+
const anchorIndex = findPrevIndex(messageRecords, idx, (m) => isUserMessage(m) || isToolResponseMessage(m));
|
|
113
|
+
if (anchorIndex !== null && !keepSet.has(anchorIndex)) {
|
|
114
|
+
keepSet.add(anchorIndex);
|
|
115
|
+
changed = true;
|
|
116
|
+
}
|
|
117
|
+
for (let i = idx + 1; i < messageRecords.length; i += 1) {
|
|
118
|
+
const next = messageRecords[i];
|
|
119
|
+
if (!next)
|
|
120
|
+
continue;
|
|
121
|
+
if (!isToolResponseMessage(next)) {
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
if (!keepSet.has(i)) {
|
|
125
|
+
keepSet.add(i);
|
|
126
|
+
changed = true;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Ensure the first kept non-system message is a user turn (do not drop history; add an anchor).
|
|
133
|
+
const firstKeptNonSystem = (() => {
|
|
134
|
+
for (let i = 0; i < messageRecords.length; i += 1) {
|
|
135
|
+
const role = normalizeRole(messageRecords[i]?.role);
|
|
136
|
+
if (!role || isSystemRole(role))
|
|
137
|
+
continue;
|
|
138
|
+
if (keepSet.has(i))
|
|
139
|
+
return i;
|
|
140
|
+
}
|
|
141
|
+
return null;
|
|
142
|
+
})();
|
|
143
|
+
if (firstKeptNonSystem !== null && !isUserMessage(messageRecords[firstKeptNonSystem])) {
|
|
144
|
+
const userAnchor = findPrevIndex(messageRecords, firstKeptNonSystem, isUserMessage);
|
|
145
|
+
if (userAnchor !== null) {
|
|
146
|
+
keepSet.add(userAnchor);
|
|
147
|
+
// One more pass to ensure tool adjacency around the newly added anchor.
|
|
148
|
+
for (const idx of Array.from(keepSet).sort((a, b) => a - b)) {
|
|
149
|
+
const msg = messageRecords[idx];
|
|
150
|
+
if (!msg)
|
|
151
|
+
continue;
|
|
152
|
+
if (isToolResponseMessage(msg)) {
|
|
153
|
+
const toolCallIndex = findPrevIndex(messageRecords, idx, isAssistantToolCallMessage);
|
|
154
|
+
if (toolCallIndex !== null)
|
|
155
|
+
keepSet.add(toolCallIndex);
|
|
156
|
+
}
|
|
157
|
+
else if (isAssistantToolCallMessage(msg)) {
|
|
158
|
+
const anchorIndex = findPrevIndex(messageRecords, idx, (m) => isUserMessage(m) || isToolResponseMessage(m));
|
|
159
|
+
if (anchorIndex !== null)
|
|
160
|
+
keepSet.add(anchorIndex);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
// If there is no user message before the kept window, the history prefix is already invalid
|
|
166
|
+
// for Gemini tool-calling (tool_calls/functionCall must be preceded by user or tool response).
|
|
167
|
+
// In this case, preserve system/developer messages and start the followup from the first user
|
|
168
|
+
// message that exists inside the kept window.
|
|
169
|
+
let firstUserAfter = null;
|
|
170
|
+
for (let i = firstKeptNonSystem; i < messageRecords.length; i += 1) {
|
|
171
|
+
if (keepSet.has(i) && isUserMessage(messageRecords[i])) {
|
|
172
|
+
firstUserAfter = i;
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (firstUserAfter !== null) {
|
|
177
|
+
for (const idx of Array.from(keepSet)) {
|
|
178
|
+
if (idx < firstUserAfter) {
|
|
179
|
+
keepSet.delete(idx);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
const trimmed = [];
|
|
186
|
+
for (let i = 0; i < messageRecords.length; i += 1) {
|
|
187
|
+
const entry = messageRecords[i];
|
|
188
|
+
const role = typeof entry.role === 'string' ? entry.role : '';
|
|
189
|
+
if (role && isSystemRole(role)) {
|
|
190
|
+
trimmed.push(entry);
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
if (keepSet.has(i)) {
|
|
194
|
+
trimmed.push(entry);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return trimmed;
|
|
198
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { JsonObject } from '../../conversion/hub/types/json.js';
|
|
2
|
+
export type CapturedChatSeed = {
|
|
3
|
+
model?: string;
|
|
4
|
+
messages: JsonObject[];
|
|
5
|
+
tools?: JsonObject[];
|
|
6
|
+
parameters?: Record<string, unknown>;
|
|
7
|
+
};
|
|
8
|
+
export declare function extractCapturedChatSeed(source: unknown): CapturedChatSeed | null;
|
|
9
|
+
export declare function normalizeFollowupParameters(value: unknown): Record<string, unknown> | undefined;
|
|
10
|
+
export declare function buildEntryAwareFollowupPayload(args: {
|
|
11
|
+
entryEndpoint: string;
|
|
12
|
+
model?: string;
|
|
13
|
+
messages: JsonObject[];
|
|
14
|
+
tools?: JsonObject[];
|
|
15
|
+
parameters?: Record<string, unknown>;
|
|
16
|
+
}): JsonObject;
|
|
17
|
+
export declare function dropToolByFunctionName(tools: JsonObject[] | undefined, dropName: string): JsonObject[] | undefined;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { buildAnthropicRequestFromOpenAIChat } from '../../conversion/codecs/anthropic-openai-codec.js';
|
|
2
|
+
import { buildChatRequestFromResponses, buildResponsesRequestFromChat, captureResponsesContext } from '../../conversion/responses/responses-openai-bridge.js';
|
|
3
|
+
import { cloneJson } from '../server-side-tools.js';
|
|
4
|
+
function extractResponsesTopLevelParameters(record) {
|
|
5
|
+
const allowed = new Set([
|
|
6
|
+
'temperature',
|
|
7
|
+
'top_p',
|
|
8
|
+
'max_output_tokens',
|
|
9
|
+
'seed',
|
|
10
|
+
'logit_bias',
|
|
11
|
+
'user',
|
|
12
|
+
'parallel_tool_calls',
|
|
13
|
+
'tool_choice',
|
|
14
|
+
'response_format',
|
|
15
|
+
'stream'
|
|
16
|
+
]);
|
|
17
|
+
const out = {};
|
|
18
|
+
// Back-compat: StandardizedRequest uses max_tokens; map to Responses max_output_tokens.
|
|
19
|
+
if (record.max_output_tokens === undefined && record.max_tokens !== undefined) {
|
|
20
|
+
out.max_output_tokens = record.max_tokens;
|
|
21
|
+
}
|
|
22
|
+
for (const key of Object.keys(record)) {
|
|
23
|
+
if (!allowed.has(key))
|
|
24
|
+
continue;
|
|
25
|
+
out[key] = record[key];
|
|
26
|
+
}
|
|
27
|
+
return Object.keys(out).length ? out : undefined;
|
|
28
|
+
}
|
|
29
|
+
export function extractCapturedChatSeed(source) {
|
|
30
|
+
if (!source || typeof source !== 'object' || Array.isArray(source)) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const record = source;
|
|
34
|
+
const model = typeof record.model === 'string' && record.model.trim().length ? record.model.trim() : undefined;
|
|
35
|
+
const rawMessages = Array.isArray(record.messages) ? record.messages : null;
|
|
36
|
+
if (rawMessages) {
|
|
37
|
+
const tools = Array.isArray(record.tools) ? cloneJson(record.tools) : undefined;
|
|
38
|
+
const parameters = normalizeFollowupParameters(record.parameters ?? extractResponsesTopLevelParameters(record));
|
|
39
|
+
return {
|
|
40
|
+
...(model ? { model } : {}),
|
|
41
|
+
messages: cloneJson(rawMessages),
|
|
42
|
+
...(tools ? { tools } : {}),
|
|
43
|
+
...(parameters ? { parameters } : {})
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
// Backward/compat: some hosts may have captured the raw /v1/responses payload.
|
|
47
|
+
const rawInput = Array.isArray(record.input) ? record.input : null;
|
|
48
|
+
if (rawInput) {
|
|
49
|
+
try {
|
|
50
|
+
const ctx = captureResponsesContext(record);
|
|
51
|
+
if (!ctx.isResponsesPayload) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const rebuilt = buildChatRequestFromResponses(record, ctx).request;
|
|
55
|
+
const rebuiltModel = typeof rebuilt.model === 'string' && rebuilt.model.trim().length ? String(rebuilt.model).trim() : model;
|
|
56
|
+
const rebuiltMessages = Array.isArray(rebuilt.messages) ? rebuilt.messages : [];
|
|
57
|
+
const rebuiltTools = Array.isArray(rebuilt.tools) ? rebuilt.tools : undefined;
|
|
58
|
+
const parameters = normalizeFollowupParameters(record.parameters ?? rebuilt.parameters ?? extractResponsesTopLevelParameters(record));
|
|
59
|
+
return {
|
|
60
|
+
...(rebuiltModel ? { model: rebuiltModel } : {}),
|
|
61
|
+
messages: cloneJson(rebuiltMessages),
|
|
62
|
+
...(rebuiltTools ? { tools: cloneJson(rebuiltTools) } : {}),
|
|
63
|
+
...(parameters ? { parameters } : {})
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
export function normalizeFollowupParameters(value) {
|
|
73
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
const cloned = cloneJson(value);
|
|
77
|
+
// Followup requests are always non-streaming (servertool orchestration enforces this),
|
|
78
|
+
// so remove any inherited stream hints to avoid conflicting flags.
|
|
79
|
+
delete cloned.stream;
|
|
80
|
+
return Object.keys(cloned).length ? cloned : undefined;
|
|
81
|
+
}
|
|
82
|
+
export function buildEntryAwareFollowupPayload(args) {
|
|
83
|
+
const chatPayload = {
|
|
84
|
+
...(args.model ? { model: args.model } : {}),
|
|
85
|
+
messages: args.messages,
|
|
86
|
+
...(args.tools ? { tools: args.tools } : {})
|
|
87
|
+
};
|
|
88
|
+
const normalizedEntry = typeof args.entryEndpoint === 'string' ? args.entryEndpoint.trim().toLowerCase() : '';
|
|
89
|
+
if (normalizedEntry.includes('/v1/responses')) {
|
|
90
|
+
return buildResponsesRequestFromChat(chatPayload, {
|
|
91
|
+
stream: false,
|
|
92
|
+
...(args.parameters ? { parameters: args.parameters } : {})
|
|
93
|
+
}).request;
|
|
94
|
+
}
|
|
95
|
+
if (normalizedEntry.includes('/v1/messages')) {
|
|
96
|
+
const anthropicChatPayload = {
|
|
97
|
+
...chatPayload,
|
|
98
|
+
...(args.parameters ? args.parameters : {})
|
|
99
|
+
};
|
|
100
|
+
return buildAnthropicRequestFromOpenAIChat(anthropicChatPayload);
|
|
101
|
+
}
|
|
102
|
+
const openaiChatPayload = {
|
|
103
|
+
...chatPayload,
|
|
104
|
+
...(args.parameters ? args.parameters : {})
|
|
105
|
+
};
|
|
106
|
+
return openaiChatPayload;
|
|
107
|
+
}
|
|
108
|
+
export function dropToolByFunctionName(tools, dropName) {
|
|
109
|
+
const name = typeof dropName === 'string' ? dropName.trim() : '';
|
|
110
|
+
if (!tools || !tools.length || !name) {
|
|
111
|
+
return tools;
|
|
112
|
+
}
|
|
113
|
+
return tools.filter((tool) => {
|
|
114
|
+
if (!tool || typeof tool !== 'object')
|
|
115
|
+
return false;
|
|
116
|
+
const fn = tool.function;
|
|
117
|
+
const toolName = fn && typeof fn.name === 'string' ? fn.name : '';
|
|
118
|
+
if (!toolName)
|
|
119
|
+
return true;
|
|
120
|
+
return toolName !== name;
|
|
121
|
+
});
|
|
122
|
+
}
|