@jsonstudio/llms 0.6.3238 → 0.6.3275

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.
Files changed (27) hide show
  1. package/dist/conversion/bridge-actions.js +37 -322
  2. package/dist/conversion/bridge-instructions.js +12 -109
  3. package/dist/conversion/codecs/anthropic-openai-codec.js +1 -1
  4. package/dist/conversion/compat/actions/anthropic-claude-code-system-prompt.js +38 -0
  5. package/dist/conversion/compat/actions/deepseek-web-request.js +43 -110
  6. package/dist/conversion/compat/actions/deepseek-web-response.d.ts +3 -0
  7. package/dist/conversion/compat/actions/deepseek-web-response.js +150 -11
  8. package/dist/conversion/hub/response/response-runtime.d.ts +1 -0
  9. package/dist/conversion/hub/response/response-runtime.js +26 -0
  10. package/dist/conversion/shared/anthropic-message-utils.d.ts +3 -1
  11. package/dist/conversion/shared/anthropic-message-utils.js +23 -15
  12. package/dist/conversion/shared/openai-finalizer.d.ts +0 -3
  13. package/dist/conversion/shared/openai-finalizer.js +11 -169
  14. package/dist/conversion/shared/openai-message-normalize.js +11 -72
  15. package/dist/conversion/shared/tool-mapping.js +5 -0
  16. package/dist/native/router_hotpath_napi.node +0 -0
  17. package/dist/router/virtual-router/bootstrap/provider-normalization.js +11 -3
  18. package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.d.ts +20 -0
  19. package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.js +71 -0
  20. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.d.ts +1 -0
  21. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-inbound-semantics.js +30 -0
  22. package/dist/router/virtual-router/engine-selection/native-router-hotpath-loader.js +6 -0
  23. package/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.d.ts +2 -0
  24. package/dist/router/virtual-router/engine-selection/native-shared-conversion-semantics.js +61 -0
  25. package/dist/router/virtual-router/engine.js +58 -1
  26. package/dist/router/virtual-router/types.d.ts +1 -1
  27. package/package.json +1 -1
@@ -1,180 +1,22 @@
1
1
  // OpenAI Chat finalizer: enforce canonical shapes without the legacy hook system.
2
2
  // - Ensures tool_calls use stringified JSON arguments and sets finish_reason='tool_calls' when applicable
3
3
  // - Normalizes potential tool messages (role:'tool') content to strict strings (JSON-stringify for objects)
4
- import { sanitizeReasoningTaggedTextWithNative } from '../../router/virtual-router/engine-selection/native-shared-conversion-semantics.js';
4
+ import { finalizeRespProcessChatResponseWithNative } from '../../router/virtual-router/engine-selection/native-chat-process-governance-semantics.js';
5
5
  function asObject(v) {
6
6
  return v && typeof v === 'object' && !Array.isArray(v) ? v : null;
7
7
  }
8
- function stringifyArgs(argVal) {
9
- if (typeof argVal === 'string')
10
- return argVal;
11
- try {
12
- return JSON.stringify(argVal ?? {});
13
- }
14
- catch {
15
- return '{}';
16
- }
17
- }
18
- function toStringContent(val, emptyFallback = 'Command succeeded (no output).') {
19
- if (val == null)
20
- return emptyFallback;
21
- if (typeof val === 'string') {
22
- const s = val.trim();
23
- return s.length ? s : emptyFallback;
24
- }
25
- if (Array.isArray(val) || typeof val === 'object') {
26
- try {
27
- const s = JSON.stringify(val);
28
- return s && s.trim().length ? s : emptyFallback;
29
- }
30
- catch {
31
- return emptyFallback;
32
- }
33
- }
34
- try {
35
- const s = String(val);
36
- return s.trim().length ? s : emptyFallback;
37
- }
38
- catch {
39
- return emptyFallback;
40
- }
41
- }
8
+ // Canonicalization handled by native finalizeChatResponseJson.
42
9
  export async function finalizeOpenAIChatResponse(chatLike, opts) {
43
- const streamingIntent = opts?.stream === true;
44
10
  const obj = asObject(chatLike);
45
11
  if (!obj)
46
12
  return chatLike;
47
- try {
48
- // Case A: OpenAI Chat completion response ({ id, object, choices[0].message })
49
- if ('choices' in obj && Array.isArray(obj.choices)) {
50
- const first = obj.choices[0];
51
- if (first && typeof first === 'object' && first.message && typeof first.message === 'object') {
52
- const msg = first.message;
53
- if (Array.isArray(msg.tool_calls)) {
54
- for (const tc of msg.tool_calls) {
55
- try {
56
- const fn = tc?.function || {};
57
- if (fn && typeof fn === 'object') {
58
- fn.arguments = stringifyArgs(fn.arguments);
59
- }
60
- }
61
- catch { /* ignore */ }
62
- }
63
- if (String(first.finish_reason || '').toLowerCase() !== 'tool_calls') {
64
- first.finish_reason = 'tool_calls';
65
- }
66
- }
67
- }
68
- // nothing more to do for Chat completion response
69
- }
70
- // Case B: Chat-style messages array ({ messages: [...] })
71
- if (Array.isArray(obj.messages)) {
72
- const msgs = obj.messages;
73
- // Build latest assistant tool_call id->name map
74
- const idToName = new Map();
75
- for (let i = msgs.length - 1; i >= 0; i--) {
76
- const m = msgs[i];
77
- if (m && m.role === 'assistant' && Array.isArray(m.tool_calls) && m.tool_calls.length) {
78
- for (const tc of m.tool_calls) {
79
- const id = typeof tc?.id === 'string' ? tc.id : undefined;
80
- const nm = typeof tc?.function?.name === 'string' ? tc.function.name : undefined;
81
- if (id && nm)
82
- idToName.set(id, nm);
83
- if (tc?.function)
84
- tc.function.arguments = stringifyArgs(tc.function.arguments);
85
- }
86
- break;
87
- }
88
- }
89
- // Normalize tool role messages: ensure string content + name (if known)
90
- for (const m of msgs) {
91
- if (!m || typeof m !== 'object')
92
- continue;
93
- if (String(m.role || '').toLowerCase() !== 'tool')
94
- continue;
95
- const cid = typeof m.tool_call_id === 'string' ? m.tool_call_id : undefined;
96
- // add name when available
97
- const nm = cid ? idToName.get(cid) : undefined;
98
- if (nm && typeof m.name !== 'string')
99
- m.name = nm;
100
- m.content = toStringContent(m.content);
101
- }
102
- }
103
- }
104
- catch { /* ignore normalization errors */ }
105
- applyChatReasoningPolicy(obj, opts?.reasoningMode);
106
- return obj;
107
- }
108
- function applyChatReasoningPolicy(target, mode) {
109
- if (!mode || mode === 'keep') {
110
- return;
111
- }
112
- const containers = [];
113
- if (Array.isArray(target.messages)) {
114
- target.messages.forEach(entry => {
115
- if (entry && typeof entry === 'object') {
116
- containers.push(entry);
117
- }
118
- });
119
- }
120
- if (Array.isArray(target.choices)) {
121
- target.choices.forEach(choice => {
122
- if (!choice || typeof choice !== 'object') {
123
- return;
124
- }
125
- const record = choice;
126
- if (record.message && typeof record.message === 'object') {
127
- containers.push(record.message);
128
- }
129
- if (record.delta && typeof record.delta === 'object') {
130
- containers.push(record.delta);
131
- }
132
- });
133
- }
134
- containers.forEach(container => normalizeReasoningField(container, mode));
135
- }
136
- function normalizeReasoningField(container, mode) {
137
- const bag = container;
138
- const rawValue = typeof bag.reasoning_content === 'string' ? bag.reasoning_content : '';
139
- const trimmed = sanitizeReasoningTaggedTextWithNative(rawValue).trim();
140
- if (!trimmed && Object.prototype.hasOwnProperty.call(bag, 'reasoning_content')) {
141
- delete bag.reasoning_content;
142
- return;
143
- }
144
- if (!trimmed) {
145
- return;
146
- }
147
- if (mode === 'drop') {
148
- delete bag.reasoning_content;
149
- return;
150
- }
151
- if (mode === 'append_to_content') {
152
- appendReasoningToContent(bag, trimmed);
153
- delete bag.reasoning_content;
154
- return;
155
- }
156
- }
157
- function appendReasoningToContent(container, reasoning) {
158
- const separator = reasoning.startsWith('\n') ? '' : '\n';
159
- if (typeof container.content === 'string') {
160
- const base = container.content.trim().length ? container.content : '';
161
- container.content = base ? `${base}${separator}${reasoning}` : reasoning;
162
- return;
163
- }
164
- if (Array.isArray(container.content)) {
165
- const list = container.content;
166
- list.push({ type: 'text', text: reasoning });
167
- return;
168
- }
169
- if (container.content && typeof container.content === 'object') {
170
- try {
171
- const serialized = JSON.stringify(container.content);
172
- container.content = serialized ? `${serialized}${separator}${reasoning}` : reasoning;
173
- }
174
- catch {
175
- container.content = reasoning;
176
- }
177
- return;
178
- }
179
- container.content = reasoning;
13
+ const finalized = await finalizeRespProcessChatResponseWithNative({
14
+ payload: obj,
15
+ stream: opts?.stream === true,
16
+ reasoningMode: opts?.reasoningMode,
17
+ endpoint: opts?.endpoint,
18
+ requestId: opts?.requestId
19
+ });
20
+ return finalized;
180
21
  }
22
+ // All canonicalization + reasoning policy handled by native finalizeChatResponseJson.
@@ -1,5 +1,6 @@
1
1
  import { injectMcpToolsForChat } from '../mcp-injection.js';
2
2
  import { normalizeOpenaiChatMessagesWithNative, normalizeOpenaiMessageWithNative, normalizeOpenaiToolCallWithNative, normalizeOpenaiToolWithNative } from '../../router/virtual-router/engine-selection/native-shared-conversion-semantics.js';
3
+ import { enforceChatBudgetWithNative } from '../../router/virtual-router/engine-selection/native-shared-conversion-semantics.js';
3
4
  // Message normalization utilities for OpenAI chat payloads (renamed to avoid confusion
4
5
  // with the deprecated "openai-normalizer" module entry). This file contains the
5
6
  // previously-implemented logic from openai-normalize.ts.
@@ -7,47 +8,14 @@ import { normalizeOpenaiChatMessagesWithNative, normalizeOpenaiMessageWithNative
7
8
  export function normalizeChatRequest(request) {
8
9
  if (!request || typeof request !== 'object')
9
10
  return request;
10
- const normalized = { ...request };
11
+ let normalized = { ...request };
11
12
  if (Array.isArray(normalized.messages)) {
12
13
  normalized.messages = normalized.messages.map((msg) => normalizeMessage(msg));
13
14
  }
14
15
  if (Array.isArray(normalized.tools)) {
15
16
  normalized.tools = normalized.tools.map((tool) => normalizeTool(tool));
16
17
  }
17
- // Limit handling: keep structure without truncating tool outputs or adding markers.
18
- // - Do not remove messages; avoid truncating tool output content.
19
- try {
20
- const msgs = Array.isArray(normalized.messages) ? normalized.messages : [];
21
- if (msgs.length) {
22
- const asstLimitRaw = process?.env?.RCC_ASSISTANT_TEXT_LIMIT;
23
- const ASST_LIMIT = (asstLimitRaw === '0') ? 0 : Math.max(0, Number(asstLimitRaw ?? 8192));
24
- const clamp = (s, n) => {
25
- try {
26
- const t = String(s);
27
- return (n > 0 && t.length > n) ? (t.slice(0, n) + '...(truncated)') : t;
28
- }
29
- catch {
30
- return s;
31
- }
32
- };
33
- for (let i = 0; i < msgs.length; i++) {
34
- const m = msgs[i];
35
- if (!m || typeof m !== 'object')
36
- continue;
37
- const role = String(m.role || '').toLowerCase();
38
- if (role === 'assistant') {
39
- if (ASST_LIMIT > 0) {
40
- if (typeof m.content === 'string')
41
- m.content = clamp(m.content, ASST_LIMIT);
42
- else if (Array.isArray(m.content)) {
43
- m.content = m.content.map((p) => (p && typeof p.text === 'string') ? { ...p, text: clamp(p.text, ASST_LIMIT) } : p);
44
- }
45
- }
46
- }
47
- }
48
- }
49
- }
50
- catch { /* ignore limit errors */ }
18
+ // Assistant text limit handling has been moved into native budget enforcement.
51
19
  // MCP 注入(两步法)统一走共享实现,避免路径分叉
52
20
  const disableMcpTools = Boolean(normalized.__rcc_disable_mcp_tools);
53
21
  if (!disableMcpTools) {
@@ -141,48 +109,19 @@ export function normalizeChatRequest(request) {
141
109
  }
142
110
  catch { /* ignore message normalization */ }
143
111
  // 注意:不合并/删除多条 system(与 统一标准,避免高风险修改)。
144
- // 基于“载荷预算”(配置驱动)进行分层裁剪,避免整体载荷超限导致上游 500
112
+ // 基于“载荷预算”(配置驱动)进行裁剪,统一走 native
145
113
  try {
146
114
  const msgs = Array.isArray(normalized.messages) ? normalized.messages : [];
147
115
  if (msgs.length) {
148
116
  const modelId = String(normalized?.model || '').trim();
149
117
  const budget = resolveBudgetForModelSync(modelId);
150
- const allowed = Math.max(32 * 1024, Math.floor(budget.allowedBytes)); // 最低 32KB
151
- const sizeBytes = (obj) => { try {
152
- return Buffer.byteLength(JSON.stringify(obj), 'utf8');
153
- }
154
- catch {
155
- return 0;
156
- } };
157
- let total = sizeBytes(normalized.messages);
158
- if (total > allowed) {
159
- // 分层裁剪:最近 3 条工具消息额度更大,其余更严格;若仍超限,再统一降到最小额度。
160
- const toolIdx = [];
161
- for (let i = 0; i < msgs.length; i++) {
162
- const m = msgs[i];
163
- if (m && m.role === 'tool' && typeof m.content === 'string')
164
- toolIdx.push(i);
165
- }
166
- if (toolIdx.length) {
167
- // Disable shrinking/truncation of tool outputs to avoid altering content
168
- const shrinkTo = (_idx, _limit) => { };
169
- const recentLimitChars = Number(process?.env?.RCC_TOOL_TEXT_RECENT || 1024);
170
- const olderLimitChars = Number(process?.env?.RCC_TOOL_TEXT_OLDER || 256);
171
- const minimalLimitChars = Number(process?.env?.RCC_TOOL_TEXT_MIN || 128);
172
- const recent = toolIdx.slice(-3);
173
- const older = toolIdx.slice(0, Math.max(0, toolIdx.length - recent.length));
174
- // No-op shrink to keep content intact
175
- for (const i of older)
176
- shrinkTo(i, olderLimitChars);
177
- for (const i of recent)
178
- shrinkTo(i, recentLimitChars);
179
- total = sizeBytes(normalized.messages);
180
- if (total > allowed) {
181
- for (const i of toolIdx)
182
- shrinkTo(i, minimalLimitChars);
183
- }
184
- }
185
- }
118
+ const allowed = Math.max(32 * 1024, Math.floor(budget.allowedBytes));
119
+ const sysLimit = (() => {
120
+ const raw = process?.env?.RCC_SYSTEM_TEXT_LIMIT;
121
+ const n = Number(raw);
122
+ return Number.isFinite(n) && n >= 0 ? n : 8192;
123
+ })();
124
+ normalized = enforceChatBudgetWithNative(normalized, allowed, sysLimit);
186
125
  }
187
126
  }
188
127
  catch { /* ignore budget enforcement */ }
@@ -1,4 +1,5 @@
1
1
  import { sanitizeResponsesFunctionNameWithNative } from '../../router/virtual-router/engine-selection/native-hub-pipeline-resp-semantics.js';
2
+ import { mapChatToolsToBridgeWithNative } from '../../router/virtual-router/engine-selection/native-shared-conversion-semantics.js';
2
3
  export function stringifyArgs(args) {
3
4
  if (typeof args === 'string')
4
5
  return args;
@@ -209,6 +210,10 @@ export function mapChatToolsToBridge(rawTools, options) {
209
210
  if (!Array.isArray(rawTools) || rawTools.length === 0) {
210
211
  return undefined;
211
212
  }
213
+ if (!options?.sanitizeName) {
214
+ const mapped = mapChatToolsToBridgeWithNative(rawTools);
215
+ return mapped && mapped.length ? mapped : undefined;
216
+ }
212
217
  const mapped = rawTools
213
218
  .map((entry) => chatToolToBridgeDefinition(entry, options))
214
219
  .filter((entry) => !!entry);
@@ -116,17 +116,25 @@ function normalizeDeepSeekOptions(provider) {
116
116
  : typeof source.strictToolRequired === 'string'
117
117
  ? source.strictToolRequired.trim().toLowerCase() === 'true'
118
118
  : undefined;
119
- const textToolFallback = typeof source.textToolFallback === 'boolean'
119
+ const toolProtocolRaw = typeof source.toolProtocol === 'string' ? source.toolProtocol.trim().toLowerCase() : '';
120
+ let toolProtocol;
121
+ if (toolProtocolRaw === 'text' || toolProtocolRaw === 'native') {
122
+ toolProtocol = toolProtocolRaw;
123
+ }
124
+ const legacyTextToolFallback = typeof source.textToolFallback === 'boolean'
120
125
  ? source.textToolFallback
121
126
  : typeof source.textToolFallback === 'string'
122
127
  ? source.textToolFallback.trim().toLowerCase() === 'true'
123
128
  : undefined;
124
- if (strictToolRequired === undefined && textToolFallback === undefined) {
129
+ if (toolProtocol === undefined && legacyTextToolFallback !== undefined) {
130
+ toolProtocol = legacyTextToolFallback ? 'text' : 'native';
131
+ }
132
+ if (strictToolRequired === undefined && toolProtocol === undefined) {
125
133
  return undefined;
126
134
  }
127
135
  return {
128
136
  ...(strictToolRequired !== undefined ? { strictToolRequired } : {}),
129
- ...(textToolFallback !== undefined ? { textToolFallback } : {})
137
+ ...(toolProtocol !== undefined ? { toolProtocol } : {})
130
138
  };
131
139
  }
132
140
  function resolveCompatibilityProfile(providerId, provider) {
@@ -113,6 +113,25 @@ export interface NativeApplyBridgeEnsureSystemInstructionOutput {
113
113
  messages: unknown[];
114
114
  metadata?: Record<string, unknown>;
115
115
  }
116
+ export interface NativeBridgeActionPipelineInput {
117
+ stage: 'request_inbound' | 'request_outbound' | 'response_inbound' | 'response_outbound';
118
+ actions?: Array<{
119
+ name: string;
120
+ options?: Record<string, unknown>;
121
+ }>;
122
+ protocol?: string;
123
+ moduleType?: string;
124
+ requestId?: string;
125
+ state: NativeBridgeActionState;
126
+ }
127
+ export interface NativeBridgeActionState {
128
+ messages: unknown[];
129
+ requiredAction?: Record<string, unknown>;
130
+ capturedToolResults?: Array<Record<string, unknown>>;
131
+ rawRequest?: Record<string, unknown>;
132
+ rawResponse?: Record<string, unknown>;
133
+ metadata?: Record<string, unknown>;
134
+ }
116
135
  export interface NativeNormalizeMessageReasoningToolsOutput {
117
136
  message: Record<string, unknown>;
118
137
  toolCallsAdded: number;
@@ -130,5 +149,6 @@ export declare function applyBridgeReasoningExtractWithNative(input: NativeApply
130
149
  export declare function applyBridgeResponsesOutputReasoningWithNative(input: NativeApplyBridgeResponsesOutputReasoningInput): NativeApplyBridgeResponsesOutputReasoningOutput;
131
150
  export declare function applyBridgeInjectSystemInstructionWithNative(input: NativeApplyBridgeInjectSystemInstructionInput): NativeApplyBridgeInjectSystemInstructionOutput;
132
151
  export declare function applyBridgeEnsureSystemInstructionWithNative(input: NativeApplyBridgeEnsureSystemInstructionInput): NativeApplyBridgeEnsureSystemInstructionOutput;
152
+ export declare function runBridgeActionPipelineWithNative(input: NativeBridgeActionPipelineInput): NativeBridgeActionState | null;
133
153
  export declare function normalizeMessageReasoningToolsWithNative(message: Record<string, unknown>, idPrefix?: string): NativeNormalizeMessageReasoningToolsOutput;
134
154
  export declare function normalizeChatResponseReasoningToolsWithNative(response: Record<string, unknown>, idPrefixBase?: string): Record<string, unknown>;
@@ -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);
@@ -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;
@@ -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);
@@ -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',
@@ -65,6 +66,7 @@ const REQUIRED_NATIVE_EXPORTS = [
65
66
  'mapBridgeToolsToChatJson',
66
67
  'mapOpenaiChatToChatJson',
67
68
  'mapOpenaiChatFromChatJson',
69
+ 'mapChatToolsToBridgeJson',
68
70
  'captureReqInboundResponsesContextSnapshotJson',
69
71
  'computeQuotaBucketsJson',
70
72
  'deserializeStopMessageStateJson',
@@ -112,6 +114,8 @@ const REQUIRED_NATIVE_EXPORTS = [
112
114
  'injectTimeTagIntoMessagesJson',
113
115
  'injectMcpToolsForChatJson',
114
116
  'injectMcpToolsForResponsesJson',
117
+ 'mapOpenaiChatToChatJson',
118
+ 'mapOpenaiChatFromChatJson',
115
119
  'isStopMessageStateActiveJson',
116
120
  'isContextLengthExceededSignalJson',
117
121
  'isCompactionRequestJson',
@@ -207,9 +211,11 @@ const REQUIRED_NATIVE_EXPORTS = [
207
211
  'resolveSseStreamModeJson',
208
212
  'resolveSseProtocolFromMetadataJson',
209
213
  'repairArgumentsToStringJsonishJson',
214
+ 'runBridgeActionPipelineJson',
210
215
  'sanitizeChatCompletionLikeJson',
211
216
  'sanitizeFormatEnvelopeJson',
212
217
  'sanitizeReasoningTaggedTextJson',
218
+ 'ensureBridgeInstructionsJson',
213
219
  'sanitizeResponsesFunctionNameJson',
214
220
  'shouldRecordSnapshotsJson',
215
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);