@jsonstudio/llms 0.6.3405 → 0.6.3539
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/anthropic-openai-codec.d.ts +12 -3
- package/dist/conversion/codecs/anthropic-openai-codec.js +32 -92
- package/dist/conversion/codecs/gemini-openai-codec.d.ts +6 -5
- package/dist/conversion/codecs/gemini-openai-codec.js +48 -685
- package/dist/conversion/codecs/openai-openai-codec.d.ts +1 -1
- package/dist/conversion/codecs/openai-openai-codec.js +34 -100
- package/dist/conversion/codecs/responses-openai-codec.d.ts +1 -1
- package/dist/conversion/codecs/responses-openai-codec.js +47 -159
- package/dist/conversion/compat/actions/anthropic-claude-code-system-prompt.d.ts +2 -6
- package/dist/conversion/compat/actions/anthropic-claude-code-system-prompt.js +29 -245
- package/dist/conversion/compat/actions/anthropic-claude-code-user-id.d.ts +3 -0
- package/dist/conversion/compat/actions/anthropic-claude-code-user-id.js +30 -0
- package/dist/conversion/compat/actions/antigravity-thought-signature-prepare.js +21 -232
- package/dist/conversion/compat/actions/deepseek-web-request.js +41 -276
- package/dist/conversion/compat/actions/deepseek-web-response.js +64 -859
- package/dist/conversion/compat/actions/gemini-cli-request.d.ts +1 -1
- package/dist/conversion/compat/actions/gemini-cli-request.js +20 -613
- package/dist/conversion/compat/actions/gemini-web-search.d.ts +1 -15
- package/dist/conversion/compat/actions/gemini-web-search.js +22 -69
- package/dist/conversion/compat/actions/glm-tool-extraction.d.ts +3 -2
- package/dist/conversion/compat/actions/glm-tool-extraction.js +28 -257
- package/dist/conversion/compat/actions/iflow-tool-text-fallback.d.ts +0 -8
- package/dist/conversion/compat/actions/iflow-tool-text-fallback.js +24 -206
- package/dist/conversion/compat/actions/qwen-transform.d.ts +3 -2
- package/dist/conversion/compat/actions/qwen-transform.js +30 -271
- package/dist/conversion/compat/actions/tool-text-request-guidance.js +3 -173
- package/dist/conversion/compat/actions/universal-shape-filter.d.ts +6 -23
- package/dist/conversion/compat/actions/universal-shape-filter.js +4 -383
- package/dist/conversion/hub/pipeline/compat/native-adapter-context.js +1 -0
- package/dist/conversion/pipeline/codecs/v2/anthropic-openai-pipeline.d.ts +1 -2
- package/dist/conversion/pipeline/codecs/v2/anthropic-openai-pipeline.js +50 -104
- package/dist/conversion/pipeline/codecs/v2/openai-openai-pipeline.js +12 -10
- package/dist/conversion/pipeline/codecs/v2/responses-openai-pipeline.d.ts +0 -2
- package/dist/conversion/pipeline/codecs/v2/responses-openai-pipeline.js +46 -67
- package/dist/conversion/pipeline/codecs/v2/shared/openai-chat-helpers.js +15 -40
- package/dist/conversion/responses/responses-openai-bridge/response-payload.js +47 -348
- package/dist/conversion/responses/responses-openai-bridge.js +129 -611
- package/dist/conversion/shared/chat-output-normalizer.js +6 -0
- package/dist/conversion/shared/chat-request-filters.js +1 -1
- package/dist/conversion/shared/output-content-normalizer.js +10 -0
- package/dist/conversion/shared/responses-conversation-store.js +22 -135
- package/dist/conversion/shared/responses-output-builder.d.ts +0 -2
- package/dist/conversion/shared/responses-output-builder.js +28 -318
- package/dist/conversion/shared/responses-response-utils.js +35 -86
- package/dist/conversion/shared/streaming-text-extractor.d.ts +1 -2
- package/dist/conversion/shared/streaming-text-extractor.js +13 -14
- package/dist/conversion/shared/tool-call-id-manager.js +18 -21
- package/dist/native/router_hotpath_napi.node +0 -0
- package/dist/router/virtual-router/bootstrap/routing-config.d.ts +2 -1
- package/dist/router/virtual-router/bootstrap/routing-config.js +57 -4
- package/dist/router/virtual-router/engine-legacy.d.ts +3 -3
- package/dist/router/virtual-router/engine-legacy.js +15 -7
- package/dist/router/virtual-router/engine-selection/native-compat-action-semantics.d.ts +16 -0
- package/dist/router/virtual-router/engine-selection/native-compat-action-semantics.js +434 -46
- package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.d.ts +83 -0
- package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.js +295 -0
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-outbound-semantics.d.ts +1 -0
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-resp-semantics.d.ts +7 -0
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-resp-semantics.js +8 -1
- package/dist/router/virtual-router/engine-selection/native-router-hotpath-loader.js +383 -298
- package/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.d.ts +20 -0
- package/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.js +201 -0
- package/dist/router/virtual-router/engine-selection/native-virtual-router-routing-instructions-semantics.d.ts +1 -0
- package/dist/router/virtual-router/engine-selection/native-virtual-router-routing-instructions-semantics.js +37 -0
- package/dist/router/virtual-router/engine-selection/tier-load-balancing.d.ts +16 -0
- package/dist/router/virtual-router/engine-selection/tier-load-balancing.js +120 -0
- package/dist/router/virtual-router/engine-selection/tier-selection-quota-integration.d.ts +2 -0
- package/dist/router/virtual-router/engine-selection/tier-selection-quota-integration.js +44 -66
- package/dist/router/virtual-router/engine-selection/tier-selection-select.js +53 -84
- package/dist/router/virtual-router/engine.js +0 -38
- package/dist/router/virtual-router/features.js +44 -3
- package/dist/router/virtual-router/routing-instructions/parse.d.ts +0 -12
- package/dist/router/virtual-router/routing-instructions/parse.js +9 -389
- package/dist/router/virtual-router/stop-message-state-sync.d.ts +3 -6
- package/dist/router/virtual-router/stop-message-state-sync.js +50 -21
- package/dist/router/virtual-router/types.d.ts +16 -0
- package/dist/sse/sse-to-json/anthropic-sse-to-json-converter.d.ts +1 -0
- package/dist/sse/sse-to-json/anthropic-sse-to-json-converter.js +26 -0
- package/dist/sse/sse-to-json/builders/anthropic-response-builder.js +12 -2
- package/package.json +1 -1
- package/dist/router/virtual-router/engine-legacy/route-finalize.d.ts +0 -9
- package/dist/router/virtual-router/engine-legacy/route-finalize.js +0 -84
- package/dist/router/virtual-router/engine-legacy/route-selection.d.ts +0 -17
- package/dist/router/virtual-router/engine-legacy/route-selection.js +0 -205
- package/dist/router/virtual-router/engine-legacy/route-state-allowlist.d.ts +0 -3
- package/dist/router/virtual-router/engine-legacy/route-state-allowlist.js +0 -36
- package/dist/router/virtual-router/engine-legacy/route-state.d.ts +0 -12
- package/dist/router/virtual-router/engine-legacy/route-state.js +0 -386
- package/dist/router/virtual-router/engine-legacy/routing.d.ts +0 -8
- package/dist/router/virtual-router/engine-legacy/routing.js +0 -8
|
@@ -6,7 +6,7 @@ export declare class OpenAIOpenAIConversionCodec implements ConversionCodec {
|
|
|
6
6
|
private ctxMap;
|
|
7
7
|
constructor(dependencies: any);
|
|
8
8
|
initialize(): Promise<void>;
|
|
9
|
-
convertRequest(payload: any,
|
|
9
|
+
convertRequest(payload: any, _profile: ConversionProfile, context: ConversionContext): Promise<any>;
|
|
10
10
|
convertResponse(payload: any, _profile: ConversionProfile, context: ConversionContext): Promise<any>;
|
|
11
11
|
private ensureInit;
|
|
12
12
|
}
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { FilterEngine, ResponseToolTextCanonicalizeFilter, ResponseToolArgumentsStringifyFilter, ResponseFinishInvariantsFilter } from '../../filters/index.js';
|
|
3
|
-
import { loadFieldMapConfig } from '../../filters/utils/fieldmap-loader.js';
|
|
4
|
-
// processChatRequestTools/processChatResponseTools removed in favor of Filter pipeline
|
|
5
|
-
import { finalizeOpenAIChatResponse } from '../shared/openai-finalizer.js';
|
|
6
|
-
// Ported from root package (no behavior changes). Types relaxed to avoid root coupling.
|
|
1
|
+
import { runOpenAIRequestCodecWithNative, runOpenAIResponseCodecWithNative } from '../../router/virtual-router/engine-selection/native-compat-action-semantics.js';
|
|
7
2
|
export class OpenAIOpenAIConversionCodec {
|
|
8
3
|
dependencies;
|
|
9
4
|
id = 'openai-openai';
|
|
@@ -13,108 +8,47 @@ export class OpenAIOpenAIConversionCodec {
|
|
|
13
8
|
constructor(dependencies) {
|
|
14
9
|
this.dependencies = dependencies;
|
|
15
10
|
}
|
|
16
|
-
async initialize() {
|
|
17
|
-
|
|
11
|
+
async initialize() {
|
|
12
|
+
this.initialized = true;
|
|
13
|
+
}
|
|
14
|
+
async convertRequest(payload, _profile, context) {
|
|
18
15
|
await this.ensureInit();
|
|
19
|
-
const
|
|
20
|
-
data: payload,
|
|
21
|
-
route: {
|
|
22
|
-
providerId: 'unknown',
|
|
23
|
-
modelId: (payload && typeof payload === 'object' && payload.model) ? String(payload.model) : 'unknown',
|
|
24
|
-
requestId: context.requestId ?? `req_${Date.now()}`,
|
|
25
|
-
timestamp: Date.now()
|
|
26
|
-
},
|
|
27
|
-
metadata: {
|
|
28
|
-
endpoint: context.endpoint ?? context.entryEndpoint,
|
|
29
|
-
entryEndpoint: context.entryEndpoint,
|
|
30
|
-
targetProtocol: profile.outgoingProtocol
|
|
31
|
-
},
|
|
32
|
-
debug: { enabled: false, stages: {} }
|
|
33
|
-
};
|
|
34
|
-
// Persist inbound streaming intent per requestId for response-side SSE decision
|
|
16
|
+
const requestId = context.requestId ?? `req_${Date.now()}`;
|
|
35
17
|
try {
|
|
36
|
-
const wantsStream = !!((
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
18
|
+
const wantsStream = !!((payload && typeof payload === 'object' && payload.stream === true) ||
|
|
19
|
+
context?.stream === true ||
|
|
20
|
+
(context?.metadata && context.metadata.stream === true));
|
|
21
|
+
const entryEndpoint = String(context.entryEndpoint || context.endpoint || '');
|
|
22
|
+
this.ctxMap.set(requestId, { stream: wantsStream, entryEndpoint });
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// ignore context capture failures
|
|
40
26
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
};
|
|
49
|
-
return runStandardChatRequestFilters(dto.data, profile, ctxForFilters);
|
|
27
|
+
return runOpenAIRequestCodecWithNative((payload ?? {}), {
|
|
28
|
+
preserveStreamField: true,
|
|
29
|
+
requestId,
|
|
30
|
+
entryEndpoint: context.entryEndpoint ?? context.endpoint,
|
|
31
|
+
endpoint: context.endpoint,
|
|
32
|
+
stream: context.stream,
|
|
33
|
+
metadata: context.metadata ?? {}
|
|
34
|
+
});
|
|
50
35
|
}
|
|
51
36
|
async convertResponse(payload, _profile, context) {
|
|
52
37
|
await this.ensureInit();
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const guard = new Set();
|
|
57
|
-
while (cur && typeof cur === 'object' && !Array.isArray(cur) && !guard.has(cur)) {
|
|
58
|
-
guard.add(cur);
|
|
59
|
-
if ('choices' in cur || 'id' in cur || 'object' in cur) {
|
|
60
|
-
break;
|
|
61
|
-
}
|
|
62
|
-
if ('data' in cur && cur.data && typeof cur.data === 'object') {
|
|
63
|
-
cur = cur.data;
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
break;
|
|
67
|
-
}
|
|
68
|
-
return cur;
|
|
69
|
-
};
|
|
70
|
-
const unwrapped = unwrap(payload);
|
|
71
|
-
const dto = {
|
|
72
|
-
data: unwrapped,
|
|
73
|
-
metadata: {
|
|
74
|
-
requestId: context.requestId ?? `req_${Date.now()}`,
|
|
75
|
-
pipelineId: context.metadata?.pipelineId ?? 'conversion-router',
|
|
76
|
-
processingTime: 0,
|
|
77
|
-
stages: []
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
// Run filter pipeline (no-op initially). Will be populated during migration.
|
|
81
|
-
const resCtxBase = {
|
|
82
|
-
requestId: context.requestId ?? dto.metadata.requestId,
|
|
83
|
-
model: undefined,
|
|
84
|
-
endpoint: context.entryEndpoint || context.endpoint,
|
|
85
|
-
profile: 'openai-chat',
|
|
86
|
-
debug: { emit: () => { } }
|
|
87
|
-
};
|
|
88
|
-
const engine = new FilterEngine();
|
|
89
|
-
// Response-side filters (idempotent w.r.t existing logic)
|
|
90
|
-
engine.registerFilter(new ResponseToolTextCanonicalizeFilter()); // response_pre
|
|
91
|
-
engine.registerFilter(new ResponseToolArgumentsStringifyFilter()); // response_post
|
|
92
|
-
engine.registerFilter(new ResponseFinishInvariantsFilter()); // response_post
|
|
93
|
-
// Load field map config (if present) and register transforms
|
|
94
|
-
try {
|
|
95
|
-
const cfg = await loadFieldMapConfig('openai-openai.fieldmap.json');
|
|
96
|
-
if (cfg)
|
|
97
|
-
engine.setFieldMap(cfg);
|
|
98
|
-
engine.registerTransform('stringifyJson', (v) => (typeof v === 'string') ? v : (() => { try {
|
|
99
|
-
return JSON.stringify(v ?? {});
|
|
100
|
-
}
|
|
101
|
-
catch {
|
|
102
|
-
return '{}';
|
|
103
|
-
} })());
|
|
38
|
+
const ctx = context.requestId ? this.ctxMap.get(context.requestId) : undefined;
|
|
39
|
+
if (context.requestId) {
|
|
40
|
+
this.ctxMap.delete(context.requestId);
|
|
104
41
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
staged = await engine.run('response_post', staged, resCtxBase);
|
|
109
|
-
// Canonicalization handled by filters (staged)
|
|
110
|
-
const canonical = staged;
|
|
111
|
-
// Finalize + hooks (pre/post snapshots)
|
|
112
|
-
const finalized = await finalizeOpenAIChatResponse(canonical, {
|
|
42
|
+
return runOpenAIResponseCodecWithNative((payload ?? {}), {
|
|
43
|
+
stream: ctx?.stream === true,
|
|
44
|
+
endpoint: context.entryEndpoint || context.endpoint || ctx?.entryEndpoint,
|
|
113
45
|
requestId: context.requestId,
|
|
114
|
-
|
|
46
|
+
reasoningMode: context.metadata?.reasoningMode,
|
|
47
|
+
idPrefixBase: 'reasoning_choice'
|
|
115
48
|
});
|
|
116
|
-
return finalized;
|
|
117
49
|
}
|
|
118
|
-
async ensureInit() {
|
|
119
|
-
|
|
50
|
+
async ensureInit() {
|
|
51
|
+
if (!this.initialized)
|
|
52
|
+
await this.initialize();
|
|
53
|
+
}
|
|
120
54
|
}
|
|
@@ -6,7 +6,7 @@ export declare class ResponsesOpenAIConversionCodec implements ConversionCodec {
|
|
|
6
6
|
private ctxMap;
|
|
7
7
|
constructor(dependencies: any);
|
|
8
8
|
initialize(): Promise<void>;
|
|
9
|
-
convertRequest(payload: any,
|
|
9
|
+
convertRequest(payload: any, _profile: ConversionProfile, context: ConversionContext): Promise<any>;
|
|
10
10
|
convertResponse(payload: any, _profile: ConversionProfile, context: ConversionContext): Promise<any>;
|
|
11
11
|
private ensureInit;
|
|
12
12
|
}
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { captureResponsesContext, buildChatRequestFromResponses, buildResponsesRequestFromChat } from '../responses/responses-openai-bridge.js';
|
|
3
|
-
import { captureResponsesRequestContext } from '../shared/responses-conversation-store.js';
|
|
4
|
-
import { FilterEngine, ResponseToolTextCanonicalizeFilter, ResponseToolArgumentsStringifyFilter, ResponseFinishInvariantsFilter } from '../../filters/index.js';
|
|
5
|
-
// Ported from root package (no behavior change). Types relaxed.
|
|
1
|
+
import { runResponsesOpenAIRequestCodecWithNative, runResponsesOpenAIResponseCodecWithNative } from '../../router/virtual-router/engine-selection/native-compat-action-semantics.js';
|
|
6
2
|
export class ResponsesOpenAIConversionCodec {
|
|
7
3
|
dependencies;
|
|
8
4
|
id = 'responses-openai';
|
|
@@ -12,167 +8,59 @@ export class ResponsesOpenAIConversionCodec {
|
|
|
12
8
|
constructor(dependencies) {
|
|
13
9
|
this.dependencies = dependencies;
|
|
14
10
|
}
|
|
15
|
-
async initialize() {
|
|
16
|
-
|
|
11
|
+
async initialize() {
|
|
12
|
+
this.initialized = true;
|
|
13
|
+
}
|
|
14
|
+
async convertRequest(payload, _profile, context) {
|
|
17
15
|
await this.ensureInit();
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
const requestId = context.requestId ?? `req_${Date.now()}`;
|
|
17
|
+
const native = runResponsesOpenAIRequestCodecWithNative((payload ?? {}), { requestId });
|
|
18
|
+
const request = native.request && typeof native.request === 'object' && !Array.isArray(native.request)
|
|
19
|
+
? native.request
|
|
20
|
+
: {};
|
|
21
|
+
const capturedContext = native.context && typeof native.context === 'object' && !Array.isArray(native.context)
|
|
22
|
+
? {
|
|
23
|
+
...native.context,
|
|
24
|
+
requestId,
|
|
27
25
|
endpoint: context.endpoint ?? context.entryEndpoint,
|
|
28
26
|
entryEndpoint: context.entryEndpoint,
|
|
29
|
-
targetProtocol:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
let { request: chatRequest, toolsNormalized } = buildChatRequestFromResponses(dto.data, ctx);
|
|
36
|
-
// V3 专用:确保进入下游 Provider 的是“非流式 Chat”形状。
|
|
37
|
-
// Responses 入口的流式语义由 llmswitch-core/上层 SSE 合成处理;
|
|
38
|
-
// 这里显式移除 Chat 请求上的顶层 stream 标记,避免部分上游 Provider
|
|
39
|
-
// 因为 stream=true 直接切换到 SSE,而下游仍按 JSON 客户端解析。
|
|
40
|
-
try {
|
|
41
|
-
if (chatRequest && typeof chatRequest === 'object' && 'stream' in chatRequest) {
|
|
42
|
-
delete chatRequest.stream;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
catch {
|
|
46
|
-
// best-effort:失败时保留原样,但不会阻断请求
|
|
47
|
-
}
|
|
48
|
-
if (toolsNormalized)
|
|
49
|
-
ctx.toolsNormalized = toolsNormalized;
|
|
50
|
-
// Capture tool results from Responses request input for pairing on response mapping
|
|
51
|
-
try {
|
|
52
|
-
const inputArr = Array.isArray(dto.data?.input) ? dto.data.input : [];
|
|
53
|
-
const results = [];
|
|
54
|
-
for (const it of inputArr) {
|
|
55
|
-
if (!it || typeof it !== 'object')
|
|
56
|
-
continue;
|
|
57
|
-
const t = String(it.type || '').toLowerCase();
|
|
58
|
-
if (t === 'tool_result' || t === 'tool_message' || t === 'function_call_output') {
|
|
59
|
-
const tool_call_id = it.tool_call_id || it.call_id || it.tool_use_id;
|
|
60
|
-
let output = undefined;
|
|
61
|
-
const rawOut = it.output;
|
|
62
|
-
if (typeof rawOut === 'string')
|
|
63
|
-
output = rawOut;
|
|
64
|
-
else if (rawOut && typeof rawOut === 'object') {
|
|
65
|
-
try {
|
|
66
|
-
output = JSON.stringify(rawOut);
|
|
67
|
-
}
|
|
68
|
-
catch { /* ignore */ }
|
|
69
|
-
}
|
|
70
|
-
results.push({ tool_call_id, output });
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
if (results.length > 0)
|
|
74
|
-
ctx.__captured_tool_results = results;
|
|
75
|
-
}
|
|
76
|
-
catch { /* ignore */ }
|
|
77
|
-
if (context.requestId)
|
|
78
|
-
this.ctxMap.set(context.requestId, ctx);
|
|
79
|
-
// 统一走 Chat 请求过滤链路,保证 /v1/responses 与 /v1/chat 在工具治理上的一致性
|
|
80
|
-
const ctxForFilters = {
|
|
81
|
-
...context,
|
|
82
|
-
requestId: dto.route.requestId,
|
|
83
|
-
entryEndpoint: context.entryEndpoint ?? dto.metadata?.entryEndpoint ?? context.endpoint,
|
|
84
|
-
endpoint: context.endpoint ?? dto.metadata?.endpoint
|
|
85
|
-
};
|
|
86
|
-
const filtered = await runStandardChatRequestFilters(chatRequest, profile, ctxForFilters);
|
|
87
|
-
try {
|
|
88
|
-
const rebuilt = buildResponsesRequestFromChat(filtered, ctx);
|
|
89
|
-
const payloadForStore = rebuilt?.request;
|
|
90
|
-
if (payloadForStore && typeof payloadForStore === 'object') {
|
|
91
|
-
captureResponsesRequestContext({
|
|
92
|
-
requestId: dto.route.requestId,
|
|
93
|
-
payload: payloadForStore,
|
|
94
|
-
context: ctx
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
catch {
|
|
99
|
-
// best-effort capture
|
|
100
|
-
}
|
|
101
|
-
if (filtered && typeof filtered === 'object') {
|
|
102
|
-
const maybe = filtered;
|
|
103
|
-
if (maybe.max_tokens === undefined && typeof maybe.max_output_tokens === 'number') {
|
|
104
|
-
maybe.max_tokens = maybe.max_output_tokens;
|
|
27
|
+
targetProtocol: _profile.outgoingProtocol,
|
|
28
|
+
metadata: native.context &&
|
|
29
|
+
typeof native.context.metadata === 'object' &&
|
|
30
|
+
!Array.isArray(native.context.metadata)
|
|
31
|
+
? native.context.metadata
|
|
32
|
+
: (context.metadata ?? {})
|
|
105
33
|
}
|
|
106
|
-
|
|
107
|
-
|
|
34
|
+
: {
|
|
35
|
+
requestId,
|
|
36
|
+
endpoint: context.endpoint ?? context.entryEndpoint,
|
|
37
|
+
entryEndpoint: context.entryEndpoint,
|
|
38
|
+
targetProtocol: _profile.outgoingProtocol,
|
|
39
|
+
metadata: context.metadata ?? {}
|
|
40
|
+
};
|
|
41
|
+
this.ctxMap.set(requestId, capturedContext);
|
|
42
|
+
return request;
|
|
108
43
|
}
|
|
109
44
|
async convertResponse(payload, _profile, context) {
|
|
110
45
|
await this.ensureInit();
|
|
111
|
-
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
while (cur && typeof cur === 'object' && !Array.isArray(cur) && !guard.has(cur)) {
|
|
116
|
-
guard.add(cur);
|
|
117
|
-
if ('choices' in cur || 'id' in cur || 'object' in cur) {
|
|
118
|
-
break;
|
|
119
|
-
}
|
|
120
|
-
if ('data' in cur && cur.data && typeof cur.data === 'object') {
|
|
121
|
-
cur = cur.data;
|
|
122
|
-
continue;
|
|
123
|
-
}
|
|
124
|
-
break;
|
|
125
|
-
}
|
|
126
|
-
return cur;
|
|
127
|
-
};
|
|
128
|
-
const unwrapped = unwrap(payload);
|
|
129
|
-
const dto = {
|
|
130
|
-
data: unwrapped,
|
|
131
|
-
metadata: {
|
|
132
|
-
requestId: context.requestId ?? `req_${Date.now()}`,
|
|
133
|
-
pipelineId: context.metadata?.pipelineId ?? 'conversion-router',
|
|
134
|
-
processingTime: 0,
|
|
135
|
-
stages: []
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
const ctx = context.requestId ? this.ctxMap.get(context.requestId) : undefined;
|
|
139
|
-
if (context.requestId)
|
|
140
|
-
this.ctxMap.delete(context.requestId);
|
|
141
|
-
// Run response-side filter pipeline与 Chat 通路保持一致(工具治理统一在 Chat canonical 上完成)
|
|
142
|
-
const resCtxBase = {
|
|
143
|
-
requestId: context.requestId ?? dto.metadata.requestId,
|
|
144
|
-
model: undefined,
|
|
145
|
-
endpoint: context.entryEndpoint || context.endpoint,
|
|
146
|
-
profile: 'openai-chat',
|
|
147
|
-
debug: { emit: () => { } }
|
|
148
|
-
};
|
|
149
|
-
const engine = new FilterEngine();
|
|
150
|
-
// Response-side filters:文本标准化 → apply_patch 结构化补丁规范化 → shell/basics → finish_reason 不变式
|
|
151
|
-
engine.registerFilter(new ResponseToolTextCanonicalizeFilter()); // response_pre
|
|
152
|
-
engine.registerFilter(new ResponseToolArgumentsStringifyFilter()); // response_post
|
|
153
|
-
engine.registerFilter(new ResponseFinishInvariantsFilter()); // response_post
|
|
154
|
-
let staged = await engine.run('response_pre', dto.data, resCtxBase);
|
|
155
|
-
staged = await engine.run('response_map', staged, resCtxBase);
|
|
156
|
-
staged = await engine.run('response_post', staged, resCtxBase);
|
|
157
|
-
const governedChat = staged;
|
|
158
|
-
// Convert provider chat response back to Responses payload using captured context(仅做形状映射)
|
|
159
|
-
const responsesJson = buildResponsesPayloadFromChat(governedChat, ctx);
|
|
160
|
-
// No fallback append here: pairing must be produced upstream or by standard bridge mapping.
|
|
161
|
-
// Debug snapshot after mapping to Responses JSON (non-stream)
|
|
162
|
-
try {
|
|
163
|
-
const { writeSnapshotViaHooks } = await import('../snapshot-utils.js');
|
|
164
|
-
await writeSnapshotViaHooks({
|
|
165
|
-
endpoint: '/v1/responses',
|
|
166
|
-
stage: 'response_mapped_json',
|
|
167
|
-
requestId: context.requestId || `req_${Date.now()}`,
|
|
168
|
-
data: responsesJson,
|
|
169
|
-
channel: 'responses',
|
|
170
|
-
verbosity: 'verbose'
|
|
171
|
-
});
|
|
46
|
+
const requestId = context.requestId;
|
|
47
|
+
const stored = requestId ? this.ctxMap.get(requestId) : undefined;
|
|
48
|
+
if (requestId) {
|
|
49
|
+
this.ctxMap.delete(requestId);
|
|
172
50
|
}
|
|
173
|
-
|
|
174
|
-
|
|
51
|
+
const nativeContext = {
|
|
52
|
+
...(stored ?? {}),
|
|
53
|
+
requestId: requestId ?? stored?.requestId,
|
|
54
|
+
endpoint: context.endpoint ?? stored?.endpoint,
|
|
55
|
+
entryEndpoint: context.entryEndpoint ?? context.endpoint ?? stored?.entryEndpoint,
|
|
56
|
+
metadata: (stored?.metadata && typeof stored.metadata === 'object' && !Array.isArray(stored.metadata)
|
|
57
|
+
? stored.metadata
|
|
58
|
+
: context.metadata) ?? {}
|
|
59
|
+
};
|
|
60
|
+
return runResponsesOpenAIResponseCodecWithNative((payload ?? {}), nativeContext);
|
|
61
|
+
}
|
|
62
|
+
async ensureInit() {
|
|
63
|
+
if (!this.initialized)
|
|
64
|
+
await this.initialize();
|
|
175
65
|
}
|
|
176
|
-
async ensureInit() { if (!this.initialized)
|
|
177
|
-
await this.initialize(); }
|
|
178
66
|
}
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
+
import type { AdapterContext } from '../../hub/types/chat-envelope.js';
|
|
1
2
|
import type { JsonObject } from '../../hub/types/json.js';
|
|
2
3
|
import type { AnthropicClaudeCodeSystemPromptConfig } from '../../hub/pipeline/compat/compat-types.js';
|
|
3
|
-
|
|
4
|
-
* Canonicalizes the Anthropic `system` prompt into a single text block.
|
|
5
|
-
* Optionally preserves previous system blocks by prepending them to the first user message,
|
|
6
|
-
* so request semantics are preserved after normalization.
|
|
7
|
-
*/
|
|
8
|
-
export declare function applyAnthropicClaudeCodeSystemPromptCompat(payload: JsonObject, config?: AnthropicClaudeCodeSystemPromptConfig, adapterContext?: unknown): JsonObject;
|
|
4
|
+
export declare function applyAnthropicClaudeCodeSystemPromptCompat(payload: JsonObject, config?: AnthropicClaudeCodeSystemPromptConfig, adapterContext?: AdapterContext): JsonObject;
|