@jsonstudio/llms 0.6.1164 → 0.6.1354
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/conversion/codecs/gemini-openai-codec.d.ts +3 -1
- package/dist/conversion/codecs/gemini-openai-codec.js +10 -4
- package/dist/conversion/compat/actions/gemini-web-search.d.ts +1 -1
- package/dist/conversion/compat/actions/gemini-web-search.js +5 -2
- package/dist/conversion/compat/actions/iflow-tool-text-fallback.d.ts +12 -0
- package/dist/conversion/compat/actions/iflow-tool-text-fallback.js +199 -0
- package/dist/conversion/compat/actions/iflow-web-search.d.ts +1 -1
- package/dist/conversion/compat/actions/iflow-web-search.js +5 -2
- package/dist/conversion/hub/operation-table/semantic-mappers/anthropic-mapper.js +47 -56
- package/dist/conversion/hub/operation-table/semantic-mappers/chat-mapper.js +1 -13
- package/dist/conversion/hub/operation-table/semantic-mappers/gemini-mapper.js +523 -50
- package/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper.js +18 -38
- package/dist/conversion/hub/pipeline/compat/compat-pipeline-executor.js +6 -0
- package/dist/conversion/hub/pipeline/compat/compat-types.d.ts +3 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/adapter-context.d.ts +10 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/adapter-context.js +134 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/anthropic-alias-map.d.ts +6 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/anthropic-alias-map.js +79 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/apply-patch-tool-mode.d.ts +3 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/apply-patch-tool-mode.js +46 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/execute-chat-process-entry.d.ts +8 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/execute-chat-process-entry.js +366 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/execute-request-stage.d.ts +9 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/execute-request-stage.js +384 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/node-results.d.ts +3 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/node-results.js +14 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/payload-normalize.d.ts +2 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/payload-normalize.js +144 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/policy.d.ts +4 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/policy.js +32 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/protocol.d.ts +8 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/protocol.js +63 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/resolve-protocol-hooks.d.ts +2 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/resolve-protocol-hooks.js +43 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/semantic-gate.d.ts +1 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/semantic-gate.js +29 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/servertool-runtime-config.d.ts +2 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/servertool-runtime-config.js +16 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/types.d.ts +116 -0
- package/dist/conversion/hub/pipeline/hub-pipeline/types.js +1 -0
- package/dist/conversion/hub/pipeline/hub-pipeline.d.ts +3 -95
- package/dist/conversion/hub/pipeline/hub-pipeline.js +19 -1281
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage1_format_parse/index.js +1 -1
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.d.ts +7 -0
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.js +65 -1
- package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/index.js +25 -22
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/index.js +1 -1
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage2_format_build/index.d.ts +1 -1
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage2_format_build/index.js +2 -2
- package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage3_compat/index.js +2 -2
- package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage1_tool_governance/index.js +1 -1
- package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage2_route_select/index.js +1 -1
- package/dist/conversion/hub/pipeline/stages/resp_inbound/resp_inbound_stage1_sse_decode/index.js +11 -11
- package/dist/conversion/hub/pipeline/stages/resp_inbound/resp_inbound_stage2_format_parse/index.js +1 -1
- package/dist/conversion/hub/pipeline/stages/resp_inbound/resp_inbound_stage3_semantic_map/index.d.ts +1 -0
- package/dist/conversion/hub/pipeline/stages/resp_inbound/resp_inbound_stage3_semantic_map/index.js +4 -2
- package/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/index.d.ts +1 -0
- package/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/index.js +17 -9
- package/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage2_sse_stream/index.js +2 -2
- package/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage1_tool_governance/index.js +40 -2
- package/dist/conversion/hub/pipeline/stages/resp_process/resp_process_stage2_finalize/index.js +1 -1
- package/dist/conversion/hub/pipeline/target-utils.js +9 -5
- package/dist/conversion/hub/process/chat-process.js +256 -16
- package/dist/conversion/hub/response/provider-response.d.ts +8 -0
- package/dist/conversion/hub/response/provider-response.js +85 -27
- package/dist/conversion/hub/response/response-mappers.d.ts +10 -3
- package/dist/conversion/hub/response/response-mappers.js +30 -6
- package/dist/conversion/hub/response/response-runtime.js +4 -38
- package/dist/conversion/hub/snapshot-recorder.js +5 -1
- package/dist/conversion/hub/standardized-bridge.js +23 -15
- package/dist/conversion/pipeline/codecs/v2/anthropic-openai-pipeline.js +36 -5
- package/dist/conversion/responses/responses-openai-bridge.js +20 -4
- package/dist/conversion/shared/gemini-tool-utils.d.ts +8 -1
- package/dist/conversion/shared/gemini-tool-utils.js +580 -108
- package/dist/conversion/shared/jsonish.js +1 -1
- package/dist/conversion/shared/mcp-injection.js +67 -33
- package/dist/conversion/shared/openai-finalizer.js +2 -1
- package/dist/conversion/shared/openai-message-normalize.js +76 -21
- package/dist/conversion/shared/responses-output-builder.js +6 -0
- package/dist/conversion/shared/runtime-metadata.d.ts +7 -0
- package/dist/conversion/shared/runtime-metadata.js +23 -0
- package/dist/conversion/shared/text-markup-normalizer.d.ts +2 -0
- package/dist/conversion/shared/text-markup-normalizer.js +284 -4
- package/dist/conversion/shared/tool-canonicalizer.js +2 -1
- package/dist/conversion/shared/tool-governor.js +3 -3
- package/dist/filters/engine.js +5 -5
- package/dist/filters/special/request-tool-list-filter.js +194 -60
- package/dist/filters/special/request-tools-normalize.js +1 -1
- package/dist/filters/special/response-tool-text-canonicalize.d.ts +4 -7
- package/dist/filters/special/response-tool-text-canonicalize.js +7 -35
- package/dist/filters/special/tool-filter-hooks.js +58 -62
- package/dist/guidance/index.js +5 -1
- package/dist/http/sse-response.js +6 -6
- package/dist/router/virtual-router/bootstrap.js +65 -5
- package/dist/router/virtual-router/context-advisor.d.ts +4 -0
- package/dist/router/virtual-router/context-advisor.js +3 -0
- package/dist/router/virtual-router/context-weighted.d.ts +31 -0
- package/dist/router/virtual-router/context-weighted.js +54 -0
- package/dist/router/virtual-router/engine-health.d.ts +1 -1
- package/dist/router/virtual-router/engine-health.js +11 -110
- package/dist/router/virtual-router/engine-selection/alias-selection.d.ts +15 -0
- package/dist/router/virtual-router/engine-selection/alias-selection.js +156 -0
- package/dist/router/virtual-router/engine-selection/context-weight-multipliers.d.ts +11 -0
- package/dist/router/virtual-router/engine-selection/context-weight-multipliers.js +23 -0
- package/dist/router/virtual-router/engine-selection/direct-provider-model.d.ts +9 -0
- package/dist/router/virtual-router/engine-selection/direct-provider-model.js +49 -0
- package/dist/router/virtual-router/engine-selection/instruction-target.d.ts +6 -0
- package/dist/router/virtual-router/engine-selection/instruction-target.js +54 -0
- package/dist/router/virtual-router/engine-selection/key-parsing.d.ts +8 -0
- package/dist/router/virtual-router/engine-selection/key-parsing.js +64 -0
- package/dist/router/virtual-router/engine-selection/route-utils.d.ts +12 -0
- package/dist/router/virtual-router/engine-selection/route-utils.js +150 -0
- package/dist/router/virtual-router/engine-selection/routing-state-filter.d.ts +4 -0
- package/dist/router/virtual-router/engine-selection/routing-state-filter.js +50 -0
- package/dist/router/virtual-router/engine-selection/selection-deps.d.ts +39 -0
- package/dist/router/virtual-router/engine-selection/selection-deps.js +1 -0
- package/dist/router/virtual-router/engine-selection/sticky-pool.d.ts +11 -0
- package/dist/router/virtual-router/engine-selection/sticky-pool.js +109 -0
- package/dist/router/virtual-router/engine-selection/tier-priority.d.ts +12 -0
- package/dist/router/virtual-router/engine-selection/tier-priority.js +55 -0
- package/dist/router/virtual-router/engine-selection/tier-selection-select.d.ts +22 -0
- package/dist/router/virtual-router/engine-selection/tier-selection-select.js +400 -0
- package/dist/router/virtual-router/engine-selection/tier-selection.d.ts +3 -0
- package/dist/router/virtual-router/engine-selection/tier-selection.js +225 -0
- package/dist/router/virtual-router/engine-selection.d.ts +4 -30
- package/dist/router/virtual-router/engine-selection.js +10 -815
- package/dist/router/virtual-router/engine.d.ts +1 -0
- package/dist/router/virtual-router/engine.js +55 -10
- package/dist/router/virtual-router/routing-instructions.js +6 -1
- package/dist/router/virtual-router/stop-message-state-sync.d.ts +5 -0
- package/dist/router/virtual-router/stop-message-state-sync.js +6 -14
- package/dist/router/virtual-router/types.d.ts +53 -1
- package/dist/servertool/clock/config.d.ts +8 -0
- package/dist/servertool/clock/config.js +22 -0
- package/dist/servertool/clock/log.d.ts +3 -0
- package/dist/servertool/clock/log.js +13 -0
- package/dist/servertool/clock/task-store.d.ts +1 -1
- package/dist/servertool/clock/task-store.js +1 -1
- package/dist/servertool/clock/tasks.js +1 -1
- package/dist/servertool/engine.js +146 -21
- package/dist/servertool/handlers/clock-auto.js +11 -6
- package/dist/servertool/handlers/clock.js +36 -10
- package/dist/servertool/handlers/followup-request-builder.js +8 -2
- package/dist/servertool/handlers/gemini-empty-reply-continue.js +15 -9
- package/dist/servertool/handlers/iflow-model-error-retry.js +6 -4
- package/dist/servertool/handlers/recursive-detection-guard.js +4 -2
- package/dist/servertool/handlers/stop-message-auto.js +100 -10
- package/dist/servertool/handlers/vision.js +4 -1
- package/dist/servertool/handlers/web-search.js +3 -1
- package/dist/servertool/pending-session.d.ts +19 -0
- package/dist/servertool/pending-session.js +97 -0
- package/dist/servertool/reenter-backend.js +5 -3
- package/dist/servertool/server-side-tools.js +235 -6
- package/dist/servertool/types.d.ts +13 -0
- package/dist/sse/json-to-sse/event-generators/responses.js +1 -1
- package/dist/sse/shared/chat-serializer.js +2 -2
- package/dist/sse/shared/constants.js +1 -1
- package/dist/sse/sse-to-json/anthropic-sse-to-json-converter.d.ts +7 -1
- package/dist/sse/sse-to-json/builders/response-builder.js +16 -0
- package/dist/sse/sse-to-json/responses-sse-to-json-converter.d.ts +1 -1
- package/dist/tools/apply-patch/execution-capturer.js +1 -1
- package/dist/tools/exec-command/normalize.js +4 -0
- package/dist/tools/exec-command/regression-capturer.js +1 -1
- package/package.json +10 -5
|
@@ -55,11 +55,7 @@ function mapToolOutputs(entries, missing) {
|
|
|
55
55
|
});
|
|
56
56
|
return outputs.length ? outputs : undefined;
|
|
57
57
|
}
|
|
58
|
-
function
|
|
59
|
-
if (!ctx || typeof ctx !== 'object') {
|
|
60
|
-
return undefined;
|
|
61
|
-
}
|
|
62
|
-
const resume = ctx.responsesResume;
|
|
58
|
+
function deriveResumeToolOutputsFromResume(resume) {
|
|
63
59
|
if (!resume || typeof resume !== 'object') {
|
|
64
60
|
return undefined;
|
|
65
61
|
}
|
|
@@ -252,12 +248,7 @@ function readResponsesResumeFromSemantics(chat) {
|
|
|
252
248
|
}
|
|
253
249
|
function selectResponsesContextSnapshot(chat, envelopeMetadata) {
|
|
254
250
|
const semanticsContext = readResponsesContextFromSemantics(chat);
|
|
255
|
-
const metadataContextCandidate = chat.metadata?.responsesContext;
|
|
256
|
-
const metadataContext = metadataContextCandidate && isJsonObject(metadataContextCandidate)
|
|
257
|
-
? jsonClone(metadataContextCandidate)
|
|
258
|
-
: undefined;
|
|
259
251
|
const context = semanticsContext ??
|
|
260
|
-
metadataContext ??
|
|
261
252
|
{
|
|
262
253
|
metadata: envelopeMetadata
|
|
263
254
|
};
|
|
@@ -267,10 +258,7 @@ function selectResponsesContextSnapshot(chat, envelopeMetadata) {
|
|
|
267
258
|
}
|
|
268
259
|
return context;
|
|
269
260
|
}
|
|
270
|
-
function resolveSubmitResponseId(
|
|
271
|
-
const resumeMeta = ctx.responsesResume && typeof ctx.responsesResume === 'object'
|
|
272
|
-
? ctx.responsesResume
|
|
273
|
-
: undefined;
|
|
261
|
+
function resolveSubmitResponseId(resumeMeta, responsesContext) {
|
|
274
262
|
const resumeId = typeof resumeMeta?.restoredFromResponseId === 'string'
|
|
275
263
|
? resumeMeta.restoredFromResponseId.trim()
|
|
276
264
|
: undefined;
|
|
@@ -342,7 +330,7 @@ function extractCapturedToolOutputs(responsesContext) {
|
|
|
342
330
|
});
|
|
343
331
|
return entries;
|
|
344
332
|
}
|
|
345
|
-
function collectSubmitToolOutputs(chat,
|
|
333
|
+
function collectSubmitToolOutputs(chat, responsesContext) {
|
|
346
334
|
const outputs = [];
|
|
347
335
|
const seen = new Set();
|
|
348
336
|
const append = (idSeed, outputSeed, name) => {
|
|
@@ -369,11 +357,9 @@ function collectSubmitToolOutputs(chat, ctx, responsesContext) {
|
|
|
369
357
|
captured.forEach((entry) => append(entry.tool_call_id ?? entry.id, entry.output, entry.name));
|
|
370
358
|
}
|
|
371
359
|
if (!outputs.length) {
|
|
372
|
-
const resume =
|
|
373
|
-
? ctx.responsesResume
|
|
374
|
-
: undefined;
|
|
360
|
+
const resume = readResponsesResumeFromSemantics(chat);
|
|
375
361
|
const detailed = Array.isArray(resume?.toolOutputsDetailed)
|
|
376
|
-
? resume
|
|
362
|
+
? (resume.toolOutputsDetailed ?? undefined)
|
|
377
363
|
: undefined;
|
|
378
364
|
if (detailed) {
|
|
379
365
|
detailed.forEach((entry, index) => {
|
|
@@ -417,17 +403,23 @@ function resolveSubmitModel(chat, responsesContext) {
|
|
|
417
403
|
return undefined;
|
|
418
404
|
}
|
|
419
405
|
function buildSubmitToolOutputsPayload(chat, ctx, responsesContext) {
|
|
420
|
-
const
|
|
406
|
+
const resumeMeta = (() => {
|
|
407
|
+
try {
|
|
408
|
+
const resume = readResponsesResumeFromSemantics(chat);
|
|
409
|
+
return resume && typeof resume === 'object' && !Array.isArray(resume) ? resume : undefined;
|
|
410
|
+
}
|
|
411
|
+
catch {
|
|
412
|
+
return undefined;
|
|
413
|
+
}
|
|
414
|
+
})();
|
|
415
|
+
const responseId = resolveSubmitResponseId(resumeMeta, responsesContext);
|
|
421
416
|
if (!responseId) {
|
|
422
417
|
throw new Error('Submit tool outputs requires response_id from Responses resume context');
|
|
423
418
|
}
|
|
424
|
-
const toolOutputs = collectSubmitToolOutputs(chat,
|
|
419
|
+
const toolOutputs = collectSubmitToolOutputs(chat, responsesContext);
|
|
425
420
|
if (!toolOutputs.length) {
|
|
426
421
|
throw new Error('Submit tool outputs requires at least one tool output entry');
|
|
427
422
|
}
|
|
428
|
-
const resumeMeta = ctx.responsesResume && typeof ctx.responsesResume === 'object'
|
|
429
|
-
? ctx.responsesResume
|
|
430
|
-
: undefined;
|
|
431
423
|
const payload = {
|
|
432
424
|
response_id: responseId,
|
|
433
425
|
tool_outputs: toolOutputs
|
|
@@ -454,25 +446,13 @@ export class ResponsesSemanticMapper {
|
|
|
454
446
|
const missingFields = [];
|
|
455
447
|
const messages = normalizeMessages(request.messages, missingFields);
|
|
456
448
|
let toolOutputs = mapToolOutputs(payload.tool_outputs, missingFields);
|
|
457
|
-
if (!toolOutputs || toolOutputs.length === 0) {
|
|
458
|
-
const resumeToolOutputs = deriveResumeToolOutputs(ctx);
|
|
459
|
-
if (resumeToolOutputs && resumeToolOutputs.length) {
|
|
460
|
-
toolOutputs = resumeToolOutputs;
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
449
|
const parameters = collectParameters(payload, responsesContext.stream);
|
|
464
450
|
const metadata = { context: ctx };
|
|
465
451
|
if (missingFields.length) {
|
|
466
452
|
metadata.missingFields = missingFields;
|
|
467
453
|
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
}
|
|
471
|
-
metadata.responsesContext = jsonClone(responsesContext);
|
|
472
|
-
const resumeNode = ctx.responsesResume && isJsonObject(ctx.responsesResume)
|
|
473
|
-
? ctx.responsesResume
|
|
474
|
-
: undefined;
|
|
475
|
-
const semantics = attachResponsesSemantics(undefined, responsesContext, resumeNode);
|
|
454
|
+
// Keep responses protocol semantics in chat.semantics (not metadata).
|
|
455
|
+
const semantics = attachResponsesSemantics(undefined, responsesContext, undefined);
|
|
476
456
|
return {
|
|
477
457
|
messages,
|
|
478
458
|
tools: normalizeTools(toolsNormalized, missingFields),
|
|
@@ -13,6 +13,7 @@ import { extractGlmToolMarkup } from '../../../compat/actions/glm-tool-extractio
|
|
|
13
13
|
import { applyGlmWebSearchRequestTransform } from '../../../compat/actions/glm-web-search.js';
|
|
14
14
|
import { applyGeminiWebSearchCompat } from '../../../compat/actions/gemini-web-search.js';
|
|
15
15
|
import { applyIflowWebSearchRequestTransform } from '../../../compat/actions/iflow-web-search.js';
|
|
16
|
+
import { applyIflowToolTextFallback } from '../../../compat/actions/iflow-tool-text-fallback.js';
|
|
16
17
|
import { applyGlmImageContentTransform } from '../../../compat/actions/glm-image-content.js';
|
|
17
18
|
import { applyGlmVisionPromptTransform } from '../../../compat/actions/glm-vision-prompt.js';
|
|
18
19
|
import { applyClaudeThinkingToolSchemaCompat } from '../../../compat/actions/claude-thinking-tools.js';
|
|
@@ -189,6 +190,11 @@ function applyMapping(root, mapping, state) {
|
|
|
189
190
|
replaceRoot(root, applyIflowWebSearchRequestTransform(root, state.adapterContext));
|
|
190
191
|
}
|
|
191
192
|
break;
|
|
193
|
+
case 'iflow_tool_text_fallback':
|
|
194
|
+
if (state.direction === 'request') {
|
|
195
|
+
replaceRoot(root, applyIflowToolTextFallback(root, { models: mapping.models }));
|
|
196
|
+
}
|
|
197
|
+
break;
|
|
192
198
|
case 'claude_thinking_tool_schema':
|
|
193
199
|
if (state.direction === 'request') {
|
|
194
200
|
replaceRoot(root, applyClaudeThinkingToolSchemaCompat(root, state.adapterContext));
|
|
@@ -111,6 +111,9 @@ export type MappingInstruction = {
|
|
|
111
111
|
action: 'gemini_web_search_request';
|
|
112
112
|
} | {
|
|
113
113
|
action: 'iflow_web_search_request';
|
|
114
|
+
} | {
|
|
115
|
+
action: 'iflow_tool_text_fallback';
|
|
116
|
+
models?: string[];
|
|
114
117
|
} | {
|
|
115
118
|
action: 'claude_thinking_tool_schema';
|
|
116
119
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { StandardizedRequest, ProcessedRequest } from '../../types/standardized.js';
|
|
2
|
+
import type { AdapterContext } from '../../types/chat-envelope.js';
|
|
3
|
+
import type { StageRecorder } from '../../format-adapters/index.js';
|
|
4
|
+
import type { NormalizedRequest, TargetMetadata } from './types.js';
|
|
5
|
+
export declare function buildAdapterContext(normalized: NormalizedRequest, target?: TargetMetadata): AdapterContext;
|
|
6
|
+
export declare function maybeCreateStageRecorder(context: AdapterContext, endpoint?: string, options?: {
|
|
7
|
+
disableSnapshots?: boolean;
|
|
8
|
+
}): StageRecorder | undefined;
|
|
9
|
+
export declare function resolveOutboundStreamIntent(providerPreference?: TargetMetadata['streaming']): boolean | undefined;
|
|
10
|
+
export declare function applyOutboundStreamPreference(request: StandardizedRequest | ProcessedRequest, stream: boolean | undefined): StandardizedRequest | ProcessedRequest;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { jsonClone } from '../../types/json.js';
|
|
2
|
+
import { applyHubOperations } from '../../ops/operations.js';
|
|
3
|
+
import { createSnapshotRecorder } from '../../snapshot-recorder.js';
|
|
4
|
+
import { shouldRecordSnapshots } from '../../../shared/snapshot-utils.js';
|
|
5
|
+
import { cloneRuntimeMetadata } from '../../../shared/runtime-metadata.js';
|
|
6
|
+
function normalizeToolCallIdStyleCandidate(value) {
|
|
7
|
+
if (typeof value !== 'string') {
|
|
8
|
+
return undefined;
|
|
9
|
+
}
|
|
10
|
+
const normalized = value.trim().toLowerCase();
|
|
11
|
+
if (normalized === 'fc') {
|
|
12
|
+
return 'fc';
|
|
13
|
+
}
|
|
14
|
+
if (normalized === 'preserve') {
|
|
15
|
+
return 'preserve';
|
|
16
|
+
}
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
export function buildAdapterContext(normalized, target) {
|
|
20
|
+
const metadata = normalized.metadata || {};
|
|
21
|
+
const providerProtocol = target?.outboundProfile || normalized.providerProtocol;
|
|
22
|
+
const providerId = (target?.providerKey || metadata.providerKey);
|
|
23
|
+
const routeId = metadata.routeName;
|
|
24
|
+
const profileId = (target?.providerKey || metadata.pipelineId);
|
|
25
|
+
const streamingHint = normalized.stream === true ? 'force' : normalized.stream === false ? 'disable' : 'auto';
|
|
26
|
+
const toolCallIdStyle = normalizeToolCallIdStyleCandidate(metadata.toolCallIdStyle);
|
|
27
|
+
const adapterContext = {
|
|
28
|
+
requestId: normalized.id,
|
|
29
|
+
entryEndpoint: normalized.entryEndpoint || '/v1/chat/completions',
|
|
30
|
+
providerProtocol,
|
|
31
|
+
providerId,
|
|
32
|
+
routeId,
|
|
33
|
+
profileId,
|
|
34
|
+
streamingHint,
|
|
35
|
+
toolCallIdStyle
|
|
36
|
+
};
|
|
37
|
+
const runtime = metadata.runtime;
|
|
38
|
+
if (runtime && typeof runtime === 'object' && !Array.isArray(runtime)) {
|
|
39
|
+
adapterContext.runtime = jsonClone(runtime);
|
|
40
|
+
}
|
|
41
|
+
const clientRequestId = typeof metadata.clientRequestId === 'string'
|
|
42
|
+
? metadata.clientRequestId.trim()
|
|
43
|
+
: '';
|
|
44
|
+
if (clientRequestId) {
|
|
45
|
+
adapterContext.clientRequestId = clientRequestId;
|
|
46
|
+
}
|
|
47
|
+
const groupRequestId = typeof metadata.groupRequestId === 'string'
|
|
48
|
+
? metadata.groupRequestId.trim()
|
|
49
|
+
: '';
|
|
50
|
+
if (groupRequestId) {
|
|
51
|
+
adapterContext.groupRequestId = groupRequestId;
|
|
52
|
+
}
|
|
53
|
+
if (typeof metadata.originalModelId === 'string') {
|
|
54
|
+
adapterContext.originalModelId = metadata.originalModelId;
|
|
55
|
+
}
|
|
56
|
+
if (typeof metadata.clientModelId === 'string') {
|
|
57
|
+
adapterContext.clientModelId = metadata.clientModelId;
|
|
58
|
+
}
|
|
59
|
+
if (typeof metadata.assignedModelId === 'string') {
|
|
60
|
+
adapterContext.modelId = metadata.assignedModelId;
|
|
61
|
+
}
|
|
62
|
+
const rt = cloneRuntimeMetadata(metadata);
|
|
63
|
+
if (rt) {
|
|
64
|
+
adapterContext.__rt = rt;
|
|
65
|
+
}
|
|
66
|
+
const sessionId = typeof metadata.sessionId === 'string'
|
|
67
|
+
? metadata.sessionId.trim()
|
|
68
|
+
: '';
|
|
69
|
+
if (sessionId) {
|
|
70
|
+
adapterContext.sessionId = sessionId;
|
|
71
|
+
}
|
|
72
|
+
const conversationId = typeof metadata.conversationId === 'string'
|
|
73
|
+
? metadata.conversationId.trim()
|
|
74
|
+
: '';
|
|
75
|
+
if (conversationId) {
|
|
76
|
+
adapterContext.conversationId = conversationId;
|
|
77
|
+
}
|
|
78
|
+
const clientConnectionState = metadata.clientConnectionState;
|
|
79
|
+
if (clientConnectionState && typeof clientConnectionState === 'object' && !Array.isArray(clientConnectionState)) {
|
|
80
|
+
const stateRecord = clientConnectionState;
|
|
81
|
+
adapterContext.clientConnectionState = clientConnectionState;
|
|
82
|
+
if (typeof stateRecord.disconnected === 'boolean') {
|
|
83
|
+
adapterContext.clientDisconnected = stateRecord.disconnected;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const clientDisconnectedRaw = metadata.clientDisconnected;
|
|
87
|
+
if (clientDisconnectedRaw === true ||
|
|
88
|
+
(typeof clientDisconnectedRaw === 'string' && clientDisconnectedRaw.trim().toLowerCase() === 'true')) {
|
|
89
|
+
adapterContext.clientDisconnected = true;
|
|
90
|
+
}
|
|
91
|
+
if (target?.compatibilityProfile && typeof target.compatibilityProfile === 'string') {
|
|
92
|
+
adapterContext.compatibilityProfile = target.compatibilityProfile;
|
|
93
|
+
}
|
|
94
|
+
return adapterContext;
|
|
95
|
+
}
|
|
96
|
+
export function maybeCreateStageRecorder(context, endpoint, options) {
|
|
97
|
+
if (options?.disableSnapshots === true) {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
if (!shouldRecordSnapshots()) {
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
const effectiveEndpoint = endpoint || context.entryEndpoint || '/v1/chat/completions';
|
|
104
|
+
try {
|
|
105
|
+
return createSnapshotRecorder(context, effectiveEndpoint);
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export function resolveOutboundStreamIntent(providerPreference) {
|
|
112
|
+
if (providerPreference === 'always') {
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
if (providerPreference === 'never') {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
export function applyOutboundStreamPreference(request, stream) {
|
|
121
|
+
if (!request || typeof request !== 'object') {
|
|
122
|
+
return request;
|
|
123
|
+
}
|
|
124
|
+
const ops = [];
|
|
125
|
+
if (typeof stream === 'boolean') {
|
|
126
|
+
ops.push({ op: 'set_request_parameter_fields', fields: { stream } });
|
|
127
|
+
ops.push({ op: 'set_request_metadata_fields', fields: { outboundStream: stream } });
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
ops.push({ op: 'unset_request_parameter_keys', keys: ['stream'] });
|
|
131
|
+
ops.push({ op: 'unset_request_metadata_keys', keys: ['outboundStream'] });
|
|
132
|
+
}
|
|
133
|
+
return applyHubOperations(request, ops);
|
|
134
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { isJsonObject, jsonClone } from '../../types/json.js';
|
|
2
|
+
function coerceAliasMap(candidate) {
|
|
3
|
+
if (!candidate || typeof candidate !== 'object' || Array.isArray(candidate)) {
|
|
4
|
+
return undefined;
|
|
5
|
+
}
|
|
6
|
+
const normalized = {};
|
|
7
|
+
for (const [key, value] of Object.entries(candidate)) {
|
|
8
|
+
if (typeof key !== 'string' || typeof value !== 'string') {
|
|
9
|
+
continue;
|
|
10
|
+
}
|
|
11
|
+
const trimmedKey = key.trim();
|
|
12
|
+
const trimmedValue = value.trim();
|
|
13
|
+
if (!trimmedKey.length || !trimmedValue.length) {
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
normalized[trimmedKey] = trimmedValue;
|
|
17
|
+
}
|
|
18
|
+
return Object.keys(normalized).length ? normalized : undefined;
|
|
19
|
+
}
|
|
20
|
+
function readAliasMapFromSemantics(chatEnvelope) {
|
|
21
|
+
if (!chatEnvelope?.semantics || typeof chatEnvelope.semantics !== 'object') {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
const node = chatEnvelope.semantics.tools;
|
|
25
|
+
if (!node || !isJsonObject(node)) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
const candidate = node.toolNameAliasMap ?? node.toolAliasMap;
|
|
29
|
+
return coerceAliasMap(candidate);
|
|
30
|
+
}
|
|
31
|
+
function shouldCapture(entryEndpoint) {
|
|
32
|
+
return typeof entryEndpoint === 'string' && entryEndpoint.toLowerCase().includes('/v1/messages');
|
|
33
|
+
}
|
|
34
|
+
function resolveAliasMapFromSources(adapterContext, chatEnvelope) {
|
|
35
|
+
const fromContext = coerceAliasMap(adapterContext.anthropicToolNameMap);
|
|
36
|
+
if (fromContext) {
|
|
37
|
+
return fromContext;
|
|
38
|
+
}
|
|
39
|
+
const metadataNode = chatEnvelope.metadata;
|
|
40
|
+
const direct = metadataNode ? coerceAliasMap(metadataNode.anthropicToolNameMap) : undefined;
|
|
41
|
+
if (direct) {
|
|
42
|
+
return direct;
|
|
43
|
+
}
|
|
44
|
+
const contextNode = metadataNode && metadataNode.context && typeof metadataNode.context === 'object'
|
|
45
|
+
? metadataNode.context
|
|
46
|
+
: undefined;
|
|
47
|
+
const fromContextNode = coerceAliasMap(contextNode?.anthropicToolNameMap);
|
|
48
|
+
if (fromContextNode) {
|
|
49
|
+
return fromContextNode;
|
|
50
|
+
}
|
|
51
|
+
return readAliasMapFromSemantics(chatEnvelope);
|
|
52
|
+
}
|
|
53
|
+
export function captureAnthropicToolNameAliasMap(options) {
|
|
54
|
+
if (!shouldCapture(options.entryEndpoint)) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const aliasMap = resolveAliasMapFromSources(options.adapterContext, options.chatEnvelope);
|
|
58
|
+
if (!aliasMap) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
// Tool name alias map is mappable semantics and must live in chat.semantics (never metadata).
|
|
62
|
+
try {
|
|
63
|
+
const chatEnvelope = options.chatEnvelope;
|
|
64
|
+
if (!chatEnvelope.semantics || typeof chatEnvelope.semantics !== 'object' || Array.isArray(chatEnvelope.semantics)) {
|
|
65
|
+
chatEnvelope.semantics = {};
|
|
66
|
+
}
|
|
67
|
+
const semantics = chatEnvelope.semantics;
|
|
68
|
+
if (!semantics.tools || !isJsonObject(semantics.tools)) {
|
|
69
|
+
semantics.tools = {};
|
|
70
|
+
}
|
|
71
|
+
const toolsNode = semantics.tools;
|
|
72
|
+
if (!isJsonObject(toolsNode.toolNameAliasMap) && !isJsonObject(toolsNode.toolAliasMap)) {
|
|
73
|
+
toolsNode.toolNameAliasMap = jsonClone(aliasMap);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// best-effort: never block request handling due to alias map propagation failures
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
function isTruthyEnv(value) {
|
|
2
|
+
const v = typeof value === 'string' ? value.trim().toLowerCase() : '';
|
|
3
|
+
return v === '1' || v === 'true' || v === 'yes' || v === 'on';
|
|
4
|
+
}
|
|
5
|
+
export function resolveApplyPatchToolModeFromEnv() {
|
|
6
|
+
const rawMode = String(process.env.RCC_APPLY_PATCH_TOOL_MODE || process.env.ROUTECODEX_APPLY_PATCH_TOOL_MODE || '')
|
|
7
|
+
.trim()
|
|
8
|
+
.toLowerCase();
|
|
9
|
+
if (rawMode === 'freeform')
|
|
10
|
+
return 'freeform';
|
|
11
|
+
if (rawMode === 'schema' || rawMode === 'json_schema')
|
|
12
|
+
return 'schema';
|
|
13
|
+
const freeformFlag = process.env.RCC_APPLY_PATCH_FREEFORM || process.env.ROUTECODEX_APPLY_PATCH_FREEFORM;
|
|
14
|
+
if (isTruthyEnv(freeformFlag))
|
|
15
|
+
return 'freeform';
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
export function resolveApplyPatchToolModeFromTools(toolsRaw) {
|
|
19
|
+
if (!Array.isArray(toolsRaw) || toolsRaw.length === 0) {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
for (const entry of toolsRaw) {
|
|
23
|
+
if (!entry || typeof entry !== 'object' || Array.isArray(entry))
|
|
24
|
+
continue;
|
|
25
|
+
const record = entry;
|
|
26
|
+
const type = typeof record.type === 'string' ? record.type.trim().toLowerCase() : '';
|
|
27
|
+
if (type && type !== 'function')
|
|
28
|
+
continue;
|
|
29
|
+
const fn = record.function && typeof record.function === 'object' && !Array.isArray(record.function)
|
|
30
|
+
? record.function
|
|
31
|
+
: undefined;
|
|
32
|
+
const name = typeof fn?.name === 'string' ? fn.name.trim().toLowerCase() : '';
|
|
33
|
+
if (name !== 'apply_patch')
|
|
34
|
+
continue;
|
|
35
|
+
const format = typeof record.format === 'string'
|
|
36
|
+
? record.format.trim().toLowerCase()
|
|
37
|
+
: typeof fn?.format === 'string'
|
|
38
|
+
? String(fn.format).trim().toLowerCase()
|
|
39
|
+
: '';
|
|
40
|
+
if (format === 'freeform')
|
|
41
|
+
return 'freeform';
|
|
42
|
+
// If apply_patch is present without explicit freeform marker, default to schema mode.
|
|
43
|
+
return 'schema';
|
|
44
|
+
}
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { VirtualRouterEngine } from '../../../../router/virtual-router/engine.js';
|
|
2
|
+
import type { HubPipelineConfig, HubPipelineResult, NormalizedRequest, ProviderProtocol, RequestStageHooks } from './types.js';
|
|
3
|
+
export declare function executeChatProcessEntryPipeline(options: {
|
|
4
|
+
config: HubPipelineConfig;
|
|
5
|
+
routerEngine: VirtualRouterEngine;
|
|
6
|
+
normalized: NormalizedRequest;
|
|
7
|
+
resolveProtocolHooks: (protocol: ProviderProtocol) => RequestStageHooks<Record<string, unknown>> | undefined;
|
|
8
|
+
}): Promise<HubPipelineResult>;
|