@jsonstudio/llms 0.6.3214 → 0.6.3271
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/bridge-actions.js +37 -322
- package/dist/conversion/bridge-instructions.js +12 -109
- package/dist/conversion/codecs/anthropic-openai-codec.js +1 -1
- package/dist/conversion/compat/actions/deepseek-web-request.js +43 -110
- package/dist/conversion/compat/actions/deepseek-web-response.d.ts +3 -0
- package/dist/conversion/compat/actions/deepseek-web-response.js +150 -11
- package/dist/conversion/hub/operation-table/semantic-mappers/archive/chat-mapper.archive.d.ts +8 -0
- package/dist/conversion/hub/operation-table/semantic-mappers/archive/chat-mapper.archive.js +404 -0
- package/dist/conversion/hub/operation-table/semantic-mappers/chat-mapper.js +5 -384
- package/dist/conversion/hub/response/response-runtime.d.ts +1 -0
- package/dist/conversion/hub/response/response-runtime.js +26 -0
- package/dist/conversion/hub/snapshot-recorder.js +2 -91
- package/dist/conversion/hub/tool-governance/engine.d.ts +1 -1
- package/dist/conversion/hub/tool-governance/engine.js +17 -127
- package/dist/conversion/shared/anthropic-message-utils.d.ts +3 -1
- package/dist/conversion/shared/anthropic-message-utils.js +23 -15
- package/dist/conversion/shared/openai-finalizer.d.ts +0 -3
- package/dist/conversion/shared/openai-finalizer.js +11 -169
- package/dist/conversion/shared/openai-message-normalize.js +11 -72
- package/dist/conversion/shared/tool-mapping.js +5 -0
- package/dist/native/router_hotpath_napi.node +0 -0
- package/dist/router/virtual-router/bootstrap/provider-normalization.js +11 -3
- package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.d.ts +20 -0
- package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.js +71 -0
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-governance-semantics.d.ts +8 -0
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-governance-semantics.js +48 -0
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.d.ts +1 -0
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.js +30 -0
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-semantic-mappers.d.ts +2 -0
- package/dist/router/virtual-router/engine-selection/native-hub-pipeline-semantic-mappers.js +83 -0
- package/dist/router/virtual-router/engine-selection/native-router-hotpath-loader.js +11 -0
- package/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.d.ts +2 -0
- package/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.js +61 -0
- package/dist/router/virtual-router/engine-selection/native-snapshot-hooks.d.ts +1 -0
- package/dist/router/virtual-router/engine-selection/native-snapshot-hooks.js +40 -0
- package/dist/router/virtual-router/engine.js +58 -1
- package/dist/router/virtual-router/types.d.ts +1 -1
- package/package.json +1 -1
|
@@ -68,6 +68,40 @@ function parseBridgeHistoryOutput(raw) {
|
|
|
68
68
|
return null;
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
+
function parseBridgeActionState(raw) {
|
|
72
|
+
try {
|
|
73
|
+
const parsed = JSON.parse(raw);
|
|
74
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
const row = parsed;
|
|
78
|
+
if (!Array.isArray(row.messages)) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
const output = {
|
|
82
|
+
messages: row.messages
|
|
83
|
+
};
|
|
84
|
+
if (row.requiredAction && typeof row.requiredAction === 'object' && !Array.isArray(row.requiredAction)) {
|
|
85
|
+
output.requiredAction = row.requiredAction;
|
|
86
|
+
}
|
|
87
|
+
if (Array.isArray(row.capturedToolResults)) {
|
|
88
|
+
output.capturedToolResults = row.capturedToolResults.filter((entry) => Boolean(entry) && typeof entry === 'object' && !Array.isArray(entry));
|
|
89
|
+
}
|
|
90
|
+
if (row.rawRequest && typeof row.rawRequest === 'object' && !Array.isArray(row.rawRequest)) {
|
|
91
|
+
output.rawRequest = row.rawRequest;
|
|
92
|
+
}
|
|
93
|
+
if (row.rawResponse && typeof row.rawResponse === 'object' && !Array.isArray(row.rawResponse)) {
|
|
94
|
+
output.rawResponse = row.rawResponse;
|
|
95
|
+
}
|
|
96
|
+
if (row.metadata && typeof row.metadata === 'object' && !Array.isArray(row.metadata)) {
|
|
97
|
+
output.metadata = row.metadata;
|
|
98
|
+
}
|
|
99
|
+
return output;
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
71
105
|
function parseApplyBridgeNormalizeHistoryOutput(raw) {
|
|
72
106
|
try {
|
|
73
107
|
const parsed = JSON.parse(raw);
|
|
@@ -673,6 +707,43 @@ export function applyBridgeEnsureSystemInstructionWithNative(input) {
|
|
|
673
707
|
return fail(reason);
|
|
674
708
|
}
|
|
675
709
|
}
|
|
710
|
+
export function runBridgeActionPipelineWithNative(input) {
|
|
711
|
+
const capability = 'runBridgeActionPipelineJson';
|
|
712
|
+
const fail = (reason) => failNativeRequired(capability, reason);
|
|
713
|
+
if (isNativeDisabledByEnv()) {
|
|
714
|
+
return fail('native disabled');
|
|
715
|
+
}
|
|
716
|
+
const fn = readNativeFunction(capability);
|
|
717
|
+
if (!fn) {
|
|
718
|
+
return fail();
|
|
719
|
+
}
|
|
720
|
+
const payloadJson = safeStringify({
|
|
721
|
+
stage: input.stage,
|
|
722
|
+
actions: input.actions,
|
|
723
|
+
protocol: input.protocol,
|
|
724
|
+
moduleType: input.moduleType,
|
|
725
|
+
requestId: input.requestId,
|
|
726
|
+
state: input.state
|
|
727
|
+
});
|
|
728
|
+
if (!payloadJson) {
|
|
729
|
+
return fail('json stringify failed');
|
|
730
|
+
}
|
|
731
|
+
try {
|
|
732
|
+
const raw = fn(payloadJson);
|
|
733
|
+
if (typeof raw !== 'string' || !raw) {
|
|
734
|
+
return fail('empty result');
|
|
735
|
+
}
|
|
736
|
+
const parsed = parseBridgeActionState(raw);
|
|
737
|
+
if (!parsed) {
|
|
738
|
+
return null;
|
|
739
|
+
}
|
|
740
|
+
return parsed;
|
|
741
|
+
}
|
|
742
|
+
catch (error) {
|
|
743
|
+
const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
|
|
744
|
+
return fail(reason);
|
|
745
|
+
}
|
|
746
|
+
}
|
|
676
747
|
export function normalizeMessageReasoningToolsWithNative(message, idPrefix) {
|
|
677
748
|
const capability = 'normalizeMessageReasoningToolsJson';
|
|
678
749
|
const fail = (reason) => failNativeRequired(capability, reason);
|
package/dist/router/virtual-router/engine-selection/native-hub-pipeline-governance-semantics.d.ts
CHANGED
|
@@ -20,3 +20,11 @@ export declare function governRequestWithNative(input: {
|
|
|
20
20
|
request: Record<string, unknown>;
|
|
21
21
|
summary: Record<string, unknown>;
|
|
22
22
|
};
|
|
23
|
+
export declare function governResponseWithNative(input: {
|
|
24
|
+
payload: Record<string, unknown>;
|
|
25
|
+
protocol?: string;
|
|
26
|
+
registry?: NativeToolGovernanceRegistry;
|
|
27
|
+
}): {
|
|
28
|
+
payload: Record<string, unknown>;
|
|
29
|
+
summary: Record<string, unknown>;
|
|
30
|
+
};
|
package/dist/router/virtual-router/engine-selection/native-hub-pipeline-governance-semantics.js
CHANGED
|
@@ -152,3 +152,51 @@ export function governRequestWithNative(input) {
|
|
|
152
152
|
return fail(reason);
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
|
+
export function governResponseWithNative(input) {
|
|
156
|
+
const capability = 'governToolNameResponseJson';
|
|
157
|
+
const fail = (reason) => failNativeRequired(capability, reason);
|
|
158
|
+
if (isNativeDisabledByEnv()) {
|
|
159
|
+
return fail('native disabled');
|
|
160
|
+
}
|
|
161
|
+
const fn = readNativeFunction(capability);
|
|
162
|
+
if (!fn) {
|
|
163
|
+
return fail();
|
|
164
|
+
}
|
|
165
|
+
const normalizedInput = {
|
|
166
|
+
...input,
|
|
167
|
+
registry: normalizeRegistryForNative(input.registry)
|
|
168
|
+
};
|
|
169
|
+
const inputJson = safeStringify(normalizedInput);
|
|
170
|
+
if (!inputJson) {
|
|
171
|
+
return fail('json stringify failed');
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
const raw = fn(inputJson);
|
|
175
|
+
const errorReason = readNativeErrorReason(raw);
|
|
176
|
+
if (errorReason) {
|
|
177
|
+
return fail(errorReason);
|
|
178
|
+
}
|
|
179
|
+
if (typeof raw !== 'string' || !raw) {
|
|
180
|
+
return fail('empty result');
|
|
181
|
+
}
|
|
182
|
+
const parsed = JSON.parse(raw);
|
|
183
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
184
|
+
return fail('invalid payload');
|
|
185
|
+
}
|
|
186
|
+
const row = parsed;
|
|
187
|
+
if (!row.payload || typeof row.payload !== 'object' || Array.isArray(row.payload)) {
|
|
188
|
+
return fail('invalid response payload');
|
|
189
|
+
}
|
|
190
|
+
if (!row.summary || typeof row.summary !== 'object' || Array.isArray(row.summary)) {
|
|
191
|
+
return fail('invalid summary payload');
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
payload: row.payload,
|
|
195
|
+
summary: row.summary
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
|
|
200
|
+
return fail(reason);
|
|
201
|
+
}
|
|
202
|
+
}
|
package/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ export declare function resolveReqInboundServerToolFollowupSnapshotWithNative(ad
|
|
|
29
29
|
export declare function augmentReqInboundContextSnapshotWithNative(context: Record<string, unknown>, fallbackSnapshot: Record<string, unknown>): Record<string, unknown>;
|
|
30
30
|
export declare function normalizeReqInboundToolCallIdStyleWithNative(value: unknown): 'fc' | 'preserve' | undefined;
|
|
31
31
|
export declare function mapReqInboundBridgeToolsToChatWithNative(rawTools: unknown): Array<Record<string, unknown>>;
|
|
32
|
+
export declare function mapChatToolsToBridgeWithNative(rawTools: unknown): Array<Record<string, unknown>>;
|
|
32
33
|
export declare function captureReqInboundResponsesContextSnapshotWithNative(input: {
|
|
33
34
|
rawRequest: Record<string, unknown>;
|
|
34
35
|
requestId?: string;
|
package/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.js
CHANGED
|
@@ -339,6 +339,36 @@ export function mapReqInboundBridgeToolsToChatWithNative(rawTools) {
|
|
|
339
339
|
return fail(reason);
|
|
340
340
|
}
|
|
341
341
|
}
|
|
342
|
+
export function mapChatToolsToBridgeWithNative(rawTools) {
|
|
343
|
+
const capability = 'mapChatToolsToBridgeJson';
|
|
344
|
+
const fail = (reason) => failNativeRequired(capability, reason);
|
|
345
|
+
if (isNativeDisabledByEnv()) {
|
|
346
|
+
return fail('native disabled');
|
|
347
|
+
}
|
|
348
|
+
const fn = readNativeFunction(capability);
|
|
349
|
+
if (!fn) {
|
|
350
|
+
return fail();
|
|
351
|
+
}
|
|
352
|
+
const payloadJson = safeStringify(Array.isArray(rawTools) ? rawTools : []);
|
|
353
|
+
if (!payloadJson) {
|
|
354
|
+
return fail('json stringify failed');
|
|
355
|
+
}
|
|
356
|
+
try {
|
|
357
|
+
const raw = fn(payloadJson);
|
|
358
|
+
if (typeof raw !== 'string' || !raw) {
|
|
359
|
+
return fail('empty result');
|
|
360
|
+
}
|
|
361
|
+
const parsed = parseArray(raw);
|
|
362
|
+
if (!parsed) {
|
|
363
|
+
return fail('invalid payload');
|
|
364
|
+
}
|
|
365
|
+
return parsed.filter((entry) => Boolean(entry) && typeof entry === 'object' && !Array.isArray(entry));
|
|
366
|
+
}
|
|
367
|
+
catch (error) {
|
|
368
|
+
const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
|
|
369
|
+
return fail(reason);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
342
372
|
export function captureReqInboundResponsesContextSnapshotWithNative(input) {
|
|
343
373
|
const capability = 'captureReqInboundResponsesContextSnapshotJson';
|
|
344
374
|
const fail = (reason) => failNativeRequired(capability, reason);
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare function mapOpenaiChatToChatWithNative(payload: Record<string, unknown> | null | undefined, adapterContext: Record<string, unknown> | null | undefined): Record<string, unknown>;
|
|
2
|
+
export declare function mapOpenaiChatFromChatWithNative(chatEnvelope: Record<string, unknown> | null | undefined, adapterContext: Record<string, unknown> | null | undefined): Record<string, unknown>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { failNativeRequired, isNativeDisabledByEnv } from './native-router-hotpath-policy.js';
|
|
2
|
+
import { loadNativeRouterHotpathBindingForInternalUse } from './native-router-hotpath.js';
|
|
3
|
+
function readNativeFunction(name) {
|
|
4
|
+
const binding = loadNativeRouterHotpathBindingForInternalUse();
|
|
5
|
+
const fn = binding?.[name];
|
|
6
|
+
return typeof fn === 'function' ? fn : null;
|
|
7
|
+
}
|
|
8
|
+
function safeStringify(value) {
|
|
9
|
+
try {
|
|
10
|
+
return JSON.stringify(value);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function parseRecord(raw) {
|
|
17
|
+
try {
|
|
18
|
+
const parsed = JSON.parse(raw);
|
|
19
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
return parsed;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export function mapOpenaiChatToChatWithNative(payload, adapterContext) {
|
|
29
|
+
const capability = 'mapOpenaiChatToChatJson';
|
|
30
|
+
const fail = (reason) => failNativeRequired(capability, reason);
|
|
31
|
+
if (isNativeDisabledByEnv()) {
|
|
32
|
+
return fail('native disabled');
|
|
33
|
+
}
|
|
34
|
+
const fn = readNativeFunction(capability);
|
|
35
|
+
if (!fn) {
|
|
36
|
+
return fail();
|
|
37
|
+
}
|
|
38
|
+
const payloadJson = safeStringify(payload ?? {});
|
|
39
|
+
const contextJson = safeStringify(adapterContext ?? {});
|
|
40
|
+
if (!payloadJson || !contextJson) {
|
|
41
|
+
return fail('json stringify failed');
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const raw = fn(payloadJson, contextJson);
|
|
45
|
+
if (typeof raw !== 'string' || !raw) {
|
|
46
|
+
return fail('empty result');
|
|
47
|
+
}
|
|
48
|
+
const parsed = parseRecord(raw);
|
|
49
|
+
return parsed ?? fail('invalid payload');
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
|
|
53
|
+
return fail(reason);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export function mapOpenaiChatFromChatWithNative(chatEnvelope, adapterContext) {
|
|
57
|
+
const capability = 'mapOpenaiChatFromChatJson';
|
|
58
|
+
const fail = (reason) => failNativeRequired(capability, reason);
|
|
59
|
+
if (isNativeDisabledByEnv()) {
|
|
60
|
+
return fail('native disabled');
|
|
61
|
+
}
|
|
62
|
+
const fn = readNativeFunction(capability);
|
|
63
|
+
if (!fn) {
|
|
64
|
+
return fail();
|
|
65
|
+
}
|
|
66
|
+
const chatJson = safeStringify(chatEnvelope ?? {});
|
|
67
|
+
const contextJson = safeStringify(adapterContext ?? {});
|
|
68
|
+
if (!chatJson || !contextJson) {
|
|
69
|
+
return fail('json stringify failed');
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
const raw = fn(chatJson, contextJson);
|
|
73
|
+
if (typeof raw !== 'string' || !raw) {
|
|
74
|
+
return fail('empty result');
|
|
75
|
+
}
|
|
76
|
+
const parsed = parseRecord(raw);
|
|
77
|
+
return parsed ?? fail('invalid payload');
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
|
|
81
|
+
return fail(reason);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -29,6 +29,7 @@ const REQUIRED_NATIVE_EXPORTS = [
|
|
|
29
29
|
'augmentContextSnapshotJson',
|
|
30
30
|
'annotatePassthroughGovernanceSkipJson',
|
|
31
31
|
'buildAnthropicToolAliasMapJson',
|
|
32
|
+
'buildAnthropicResponseFromChatJson',
|
|
32
33
|
'buildChatNodeResultMetadataJson',
|
|
33
34
|
'buildProcessedRequestFromChatResponseJson',
|
|
34
35
|
'applyChatProcessedRequestJson',
|
|
@@ -63,6 +64,9 @@ const REQUIRED_NATIVE_EXPORTS = [
|
|
|
63
64
|
'collectToolOutputsJson',
|
|
64
65
|
'buildReqInboundToolOutputSnapshotJson',
|
|
65
66
|
'mapBridgeToolsToChatJson',
|
|
67
|
+
'mapOpenaiChatToChatJson',
|
|
68
|
+
'mapOpenaiChatFromChatJson',
|
|
69
|
+
'mapChatToolsToBridgeJson',
|
|
66
70
|
'captureReqInboundResponsesContextSnapshotJson',
|
|
67
71
|
'computeQuotaBucketsJson',
|
|
68
72
|
'deserializeStopMessageStateJson',
|
|
@@ -103,11 +107,15 @@ const REQUIRED_NATIVE_EXPORTS = [
|
|
|
103
107
|
'enforceChatBudgetJson',
|
|
104
108
|
'resolveBudgetForModelJson',
|
|
105
109
|
'finalizeGovernedRequestJson',
|
|
110
|
+
'governResponseJson',
|
|
111
|
+
'governToolNameResponseJson',
|
|
106
112
|
'findLastUserMessageIndexJson',
|
|
107
113
|
'injectContinueExecutionDirectiveJson',
|
|
108
114
|
'injectTimeTagIntoMessagesJson',
|
|
109
115
|
'injectMcpToolsForChatJson',
|
|
110
116
|
'injectMcpToolsForResponsesJson',
|
|
117
|
+
'mapOpenaiChatToChatJson',
|
|
118
|
+
'mapOpenaiChatFromChatJson',
|
|
111
119
|
'isStopMessageStateActiveJson',
|
|
112
120
|
'isContextLengthExceededSignalJson',
|
|
113
121
|
'isCompactionRequestJson',
|
|
@@ -137,6 +145,7 @@ const REQUIRED_NATIVE_EXPORTS = [
|
|
|
137
145
|
'normalizeToolSessionMessagesJson',
|
|
138
146
|
'updateToolSessionHistoryJson',
|
|
139
147
|
'normalizeContextCaptureLabelJson',
|
|
148
|
+
'normalizeSnapshotStagePayloadJson',
|
|
140
149
|
'normalizeContextToolsJson',
|
|
141
150
|
'normalizeDueInjectTextJson',
|
|
142
151
|
'normalizeProviderProtocolTokenJson',
|
|
@@ -202,9 +211,11 @@ const REQUIRED_NATIVE_EXPORTS = [
|
|
|
202
211
|
'resolveSseStreamModeJson',
|
|
203
212
|
'resolveSseProtocolFromMetadataJson',
|
|
204
213
|
'repairArgumentsToStringJsonishJson',
|
|
214
|
+
'runBridgeActionPipelineJson',
|
|
205
215
|
'sanitizeChatCompletionLikeJson',
|
|
206
216
|
'sanitizeFormatEnvelopeJson',
|
|
207
217
|
'sanitizeReasoningTaggedTextJson',
|
|
218
|
+
'ensureBridgeInstructionsJson',
|
|
208
219
|
'sanitizeResponsesFunctionNameJson',
|
|
209
220
|
'shouldRecordSnapshotsJson',
|
|
210
221
|
'writeSnapshotViaHooksJson',
|
|
@@ -4,7 +4,9 @@ export declare function extractToolCallsFromReasoningTextWithNative(text: string
|
|
|
4
4
|
cleanedText: string;
|
|
5
5
|
toolCalls: Array<Record<string, unknown>>;
|
|
6
6
|
};
|
|
7
|
+
export declare function mapChatToolsToBridgeWithNative(rawTools: unknown): Array<Record<string, unknown>>;
|
|
7
8
|
export declare function sanitizeReasoningTaggedTextWithNative(text: string): string;
|
|
9
|
+
export declare function ensureBridgeInstructionsWithNative(payload: Record<string, unknown>): Record<string, unknown>;
|
|
8
10
|
export declare function deriveToolCallKeyWithNative(call: Record<string, unknown> | null | undefined): string | null;
|
|
9
11
|
export declare function buildProviderProtocolErrorWithNative(input: {
|
|
10
12
|
message: string;
|
|
@@ -80,6 +80,10 @@ function parseToolCallLiteArray(raw) {
|
|
|
80
80
|
}
|
|
81
81
|
return out;
|
|
82
82
|
}
|
|
83
|
+
function parseArray(raw) {
|
|
84
|
+
const parsed = parseJson(raw);
|
|
85
|
+
return Array.isArray(parsed) ? parsed : null;
|
|
86
|
+
}
|
|
83
87
|
export function parseLenientJsonishWithNative(value) {
|
|
84
88
|
const capability = 'parseLenientJsonishJson';
|
|
85
89
|
const fail = (reason) => failNativeRequired(capability, reason);
|
|
@@ -156,6 +160,36 @@ export function extractToolCallsFromReasoningTextWithNative(text, idPrefix) {
|
|
|
156
160
|
return fail(reason);
|
|
157
161
|
}
|
|
158
162
|
}
|
|
163
|
+
export function mapChatToolsToBridgeWithNative(rawTools) {
|
|
164
|
+
const capability = 'mapChatToolsToBridgeJson';
|
|
165
|
+
const fail = (reason) => failNativeRequired(capability, reason);
|
|
166
|
+
if (isNativeDisabledByEnv()) {
|
|
167
|
+
return fail('native disabled');
|
|
168
|
+
}
|
|
169
|
+
const fn = readNativeFunction(capability);
|
|
170
|
+
if (!fn) {
|
|
171
|
+
return fail();
|
|
172
|
+
}
|
|
173
|
+
const payloadJson = safeStringify(Array.isArray(rawTools) ? rawTools : []);
|
|
174
|
+
if (!payloadJson) {
|
|
175
|
+
return fail('json stringify failed');
|
|
176
|
+
}
|
|
177
|
+
try {
|
|
178
|
+
const raw = fn(payloadJson);
|
|
179
|
+
if (typeof raw !== 'string' || !raw) {
|
|
180
|
+
return fail('empty result');
|
|
181
|
+
}
|
|
182
|
+
const parsed = parseArray(raw);
|
|
183
|
+
if (!parsed) {
|
|
184
|
+
return fail('invalid payload');
|
|
185
|
+
}
|
|
186
|
+
return parsed.filter((entry) => !!entry && typeof entry === 'object' && !Array.isArray(entry));
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
|
|
190
|
+
return fail(reason);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
159
193
|
export function sanitizeReasoningTaggedTextWithNative(text) {
|
|
160
194
|
const capability = 'sanitizeReasoningTaggedTextJson';
|
|
161
195
|
const fail = (reason) => failNativeRequired(capability, reason);
|
|
@@ -178,6 +212,33 @@ export function sanitizeReasoningTaggedTextWithNative(text) {
|
|
|
178
212
|
return fail(reason);
|
|
179
213
|
}
|
|
180
214
|
}
|
|
215
|
+
export function ensureBridgeInstructionsWithNative(payload) {
|
|
216
|
+
const capability = 'ensureBridgeInstructionsJson';
|
|
217
|
+
const fail = (reason) => failNativeRequired(capability, reason);
|
|
218
|
+
if (isNativeDisabledByEnv()) {
|
|
219
|
+
return fail('native disabled');
|
|
220
|
+
}
|
|
221
|
+
const fn = readNativeFunction(capability);
|
|
222
|
+
if (!fn) {
|
|
223
|
+
return fail();
|
|
224
|
+
}
|
|
225
|
+
const payloadJson = safeStringify(payload ?? {});
|
|
226
|
+
if (!payloadJson) {
|
|
227
|
+
return fail('json stringify failed');
|
|
228
|
+
}
|
|
229
|
+
try {
|
|
230
|
+
const raw = fn(payloadJson);
|
|
231
|
+
if (typeof raw !== 'string' || !raw) {
|
|
232
|
+
return fail('empty result');
|
|
233
|
+
}
|
|
234
|
+
const parsed = parseRecord(raw);
|
|
235
|
+
return parsed ?? fail('invalid payload');
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
|
|
239
|
+
return fail(reason);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
181
242
|
export function deriveToolCallKeyWithNative(call) {
|
|
182
243
|
const capability = 'deriveToolCallKeyJson';
|
|
183
244
|
const fail = (reason) => failNativeRequired(capability, reason);
|
|
@@ -22,6 +22,14 @@ function parseBoolean(raw) {
|
|
|
22
22
|
return null;
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
+
function parseJsonValue(raw) {
|
|
26
|
+
try {
|
|
27
|
+
return JSON.parse(raw);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
25
33
|
export function shouldRecordSnapshotsWithNative() {
|
|
26
34
|
const capability = 'shouldRecordSnapshotsJson';
|
|
27
35
|
const fail = (reason) => failNativeRequired(capability, reason);
|
|
@@ -67,3 +75,35 @@ export function writeSnapshotViaHooksWithNative(options) {
|
|
|
67
75
|
return fail(reason);
|
|
68
76
|
}
|
|
69
77
|
}
|
|
78
|
+
export function normalizeSnapshotStagePayloadWithNative(stage, payload) {
|
|
79
|
+
if (payload === undefined || payload === null) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
const capability = 'normalizeSnapshotStagePayloadJson';
|
|
83
|
+
const fail = (reason) => failNativeRequired(capability, reason);
|
|
84
|
+
if (isNativeDisabledByEnv()) {
|
|
85
|
+
return fail('native disabled');
|
|
86
|
+
}
|
|
87
|
+
const fn = readNativeFunction(capability);
|
|
88
|
+
if (!fn) {
|
|
89
|
+
return fail();
|
|
90
|
+
}
|
|
91
|
+
const payloadJson = safeStringify(payload);
|
|
92
|
+
if (!payloadJson) {
|
|
93
|
+
// Preserve non-JSON payloads (e.g. circular structures).
|
|
94
|
+
return payload;
|
|
95
|
+
}
|
|
96
|
+
const stageToken = typeof stage === 'string' ? stage : '';
|
|
97
|
+
try {
|
|
98
|
+
const raw = fn(stageToken, payloadJson);
|
|
99
|
+
if (typeof raw !== 'string' || !raw) {
|
|
100
|
+
return fail('empty result');
|
|
101
|
+
}
|
|
102
|
+
const parsed = parseJsonValue(raw);
|
|
103
|
+
return parsed === null ? fail('invalid payload') : parsed;
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
|
|
107
|
+
return fail(reason);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -6,6 +6,8 @@ import { cleanRoutingInstructionMarkersWithNative, parseRoutingInstructionKindsW
|
|
|
6
6
|
import { getLatestUserTextFromResponsesContext, hasLatestUserRoutingInstructionMarker, hasRoutingInstructionMarkerInResponsesContext } from './engine-legacy/helpers.js';
|
|
7
7
|
import { ProviderRegistry } from './provider-registry.js';
|
|
8
8
|
import { resolveStopMessageScope } from './engine/routing-state/store.js';
|
|
9
|
+
import { loadRoutingInstructionStateSync } from './sticky-session-store.js';
|
|
10
|
+
import { mergeStopMessageFromPersisted } from './stop-message-state-sync.js';
|
|
9
11
|
export class VirtualRouterEngine {
|
|
10
12
|
nativeProxy;
|
|
11
13
|
registry;
|
|
@@ -80,7 +82,9 @@ export class VirtualRouterEngine {
|
|
|
80
82
|
}
|
|
81
83
|
getStopMessageState(metadata) {
|
|
82
84
|
const raw = this.nativeProxy.getStopMessageState(JSON.stringify(metadata));
|
|
83
|
-
|
|
85
|
+
const snapshot = JSON.parse(raw);
|
|
86
|
+
const scope = resolveStopMessageScope(metadata);
|
|
87
|
+
return mergeStopMessageSnapshotWithPersisted(snapshot, scope);
|
|
84
88
|
}
|
|
85
89
|
getPreCommandState(metadata) {
|
|
86
90
|
const raw = this.nativeProxy.getPreCommandState(JSON.stringify(metadata));
|
|
@@ -114,6 +118,59 @@ function normalizeNativeVirtualRouterError(error) {
|
|
|
114
118
|
}
|
|
115
119
|
return error instanceof Error ? error : new Error(message || 'Virtual router error');
|
|
116
120
|
}
|
|
121
|
+
function mergeStopMessageSnapshotWithPersisted(snapshot, scope) {
|
|
122
|
+
if (!scope) {
|
|
123
|
+
return snapshot;
|
|
124
|
+
}
|
|
125
|
+
let persisted = null;
|
|
126
|
+
try {
|
|
127
|
+
persisted = loadRoutingInstructionStateSync(scope);
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
return snapshot;
|
|
131
|
+
}
|
|
132
|
+
if (!persisted) {
|
|
133
|
+
return snapshot;
|
|
134
|
+
}
|
|
135
|
+
const persistedText = typeof persisted.stopMessageText === 'string' ? persisted.stopMessageText.trim() : '';
|
|
136
|
+
if (!snapshot && !persistedText) {
|
|
137
|
+
return snapshot;
|
|
138
|
+
}
|
|
139
|
+
const existing = {
|
|
140
|
+
stopMessageSource: snapshot?.stopMessageSource,
|
|
141
|
+
stopMessageText: snapshot?.stopMessageText,
|
|
142
|
+
stopMessageMaxRepeats: snapshot?.stopMessageMaxRepeats,
|
|
143
|
+
stopMessageUsed: snapshot?.stopMessageUsed,
|
|
144
|
+
stopMessageUpdatedAt: snapshot?.stopMessageUpdatedAt,
|
|
145
|
+
stopMessageLastUsedAt: snapshot?.stopMessageLastUsedAt,
|
|
146
|
+
stopMessageStageMode: snapshot?.stopMessageStageMode,
|
|
147
|
+
stopMessageAiMode: snapshot?.stopMessageAiMode,
|
|
148
|
+
stopMessageAiSeedPrompt: snapshot?.stopMessageAiSeedPrompt,
|
|
149
|
+
stopMessageAiHistory: snapshot?.stopMessageAiHistory
|
|
150
|
+
};
|
|
151
|
+
const merged = mergeStopMessageFromPersisted(existing, persisted);
|
|
152
|
+
const base = snapshot ?? {
|
|
153
|
+
stopMessageMaxRepeats: typeof merged.stopMessageMaxRepeats === 'number' && Number.isFinite(merged.stopMessageMaxRepeats)
|
|
154
|
+
? merged.stopMessageMaxRepeats
|
|
155
|
+
: 0
|
|
156
|
+
};
|
|
157
|
+
const mergedMaxRepeats = typeof merged.stopMessageMaxRepeats === 'number' && Number.isFinite(merged.stopMessageMaxRepeats)
|
|
158
|
+
? merged.stopMessageMaxRepeats
|
|
159
|
+
: base.stopMessageMaxRepeats;
|
|
160
|
+
return {
|
|
161
|
+
...base,
|
|
162
|
+
stopMessageSource: merged.stopMessageSource,
|
|
163
|
+
stopMessageText: merged.stopMessageText,
|
|
164
|
+
stopMessageMaxRepeats: mergedMaxRepeats,
|
|
165
|
+
stopMessageUsed: merged.stopMessageUsed,
|
|
166
|
+
stopMessageUpdatedAt: merged.stopMessageUpdatedAt,
|
|
167
|
+
stopMessageLastUsedAt: merged.stopMessageLastUsedAt,
|
|
168
|
+
stopMessageStageMode: merged.stopMessageStageMode,
|
|
169
|
+
stopMessageAiMode: merged.stopMessageAiMode,
|
|
170
|
+
stopMessageAiSeedPrompt: merged.stopMessageAiSeedPrompt,
|
|
171
|
+
stopMessageAiHistory: merged.stopMessageAiHistory
|
|
172
|
+
};
|
|
173
|
+
}
|
|
117
174
|
function extractNativeErrorMessage(error) {
|
|
118
175
|
if (typeof error === 'string') {
|
|
119
176
|
return error;
|
|
@@ -46,7 +46,7 @@ export interface ProviderAuthConfig {
|
|
|
46
46
|
}
|
|
47
47
|
export interface DeepSeekCompatRuntimeOptions {
|
|
48
48
|
strictToolRequired?: boolean;
|
|
49
|
-
|
|
49
|
+
toolProtocol?: 'native' | 'text';
|
|
50
50
|
}
|
|
51
51
|
export interface ProviderProfile {
|
|
52
52
|
providerKey: string;
|