@jsonstudio/llms 0.6.3541 → 0.6.3685

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 (100) hide show
  1. package/dist/conversion/compat/actions/antigravity-thought-signature-cache.js +23 -114
  2. package/dist/conversion/compat/actions/auto-thinking.js +3 -2
  3. package/dist/conversion/compat/actions/deepseek-web-response.js +9 -50
  4. package/dist/conversion/compat/actions/field-mapping.js +2 -153
  5. package/dist/conversion/compat/actions/gemini-cli-request.d.ts +2 -0
  6. package/dist/conversion/compat/actions/gemini-cli-request.js +1 -1
  7. package/dist/conversion/compat/actions/glm-history-image-trim.js +3 -37
  8. package/dist/conversion/compat/actions/glm-image-content.js +3 -32
  9. package/dist/conversion/compat/actions/glm-native-compat.d.ts +6 -0
  10. package/dist/conversion/compat/actions/glm-native-compat.js +34 -0
  11. package/dist/conversion/compat/actions/glm-vision-prompt.js +3 -76
  12. package/dist/conversion/compat/actions/glm-web-search.js +10 -43
  13. package/dist/conversion/compat/actions/iflow-kimi-cli-defaults.js +4 -53
  14. package/dist/conversion/compat/actions/iflow-kimi-history-media-placeholder.js +5 -141
  15. package/dist/conversion/compat/actions/iflow-kimi-thinking-reasoning-fill.js +7 -28
  16. package/dist/conversion/compat/actions/iflow-native-compat.d.ts +6 -0
  17. package/dist/conversion/compat/actions/iflow-native-compat.js +36 -0
  18. package/dist/conversion/compat/actions/iflow-response-body-unwrap.js +4 -119
  19. package/dist/conversion/compat/actions/iflow-web-search.js +14 -55
  20. package/dist/conversion/compat/actions/lmstudio-responses-input-stringify.js +3 -104
  21. package/dist/conversion/hub/node-support.js +1 -1
  22. package/dist/conversion/hub/operation-table/semantic-mappers/anthropic-mapper.js +9 -1
  23. package/dist/conversion/hub/operation-table/semantic-mappers/archive/chat-mapper.archive.js +5 -0
  24. package/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper.js +34 -14
  25. package/dist/conversion/hub/pipeline/hub-pipeline.d.ts +14 -14
  26. package/dist/conversion/hub/pipeline/hub-pipeline.js +838 -524
  27. package/dist/conversion/hub/pipeline/hub-stage-timing.d.ts +6 -0
  28. package/dist/conversion/hub/pipeline/hub-stage-timing.js +178 -0
  29. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage1_format_parse/index.js +6 -4
  30. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.js +46 -0
  31. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/context-capture-orchestration.d.ts +3 -0
  32. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/context-capture-orchestration.js +2 -1
  33. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/context-factories.js +2 -0
  34. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/index.js +1 -0
  35. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/responses-context-snapshot.d.ts +3 -2
  36. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage3_context_capture/responses-context-snapshot.js +18 -5
  37. package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/context-merge.d.ts +1 -2
  38. package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/context-merge.js +0 -16
  39. package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/index.d.ts +1 -1
  40. package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/index.js +30 -12
  41. package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage1_tool_governance/index.d.ts +1 -0
  42. package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage1_tool_governance/index.js +5 -2
  43. package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage2_route_select/index.d.ts +1 -1
  44. package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage2_route_select/index.js +9 -5
  45. package/dist/conversion/hub/process/chat-process-continue-execution.js +2 -4
  46. package/dist/conversion/hub/process/chat-process-governance-orchestration.js +3 -1
  47. package/dist/conversion/hub/process/chat-process-media.d.ts +1 -0
  48. package/dist/conversion/hub/process/chat-process-media.js +36 -0
  49. package/dist/conversion/hub/process/chat-process-session-usage.d.ts +25 -0
  50. package/dist/conversion/hub/process/chat-process-session-usage.js +246 -0
  51. package/dist/conversion/hub/response/provider-response.js +13 -0
  52. package/dist/conversion/hub/types/chat-envelope.d.ts +1 -0
  53. package/dist/conversion/pipeline/codecs/v2/openai-openai-pipeline.js +0 -4
  54. package/dist/conversion/responses/responses-openai-bridge/response-payload.js +0 -12
  55. package/dist/conversion/responses/responses-openai-bridge/types.d.ts +1 -9
  56. package/dist/conversion/responses/responses-openai-bridge.d.ts +1 -0
  57. package/dist/conversion/responses/responses-openai-bridge.js +51 -24
  58. package/dist/conversion/shared/anthropic-message-utils.js +14 -1
  59. package/dist/conversion/shared/reasoning-normalizer.js +61 -0
  60. package/dist/conversion/shared/tool-governor.js +2 -4
  61. package/dist/native/router_hotpath_napi.node +0 -0
  62. package/dist/quota/quota-state.js +1 -6
  63. package/dist/router/virtual-router/bootstrap/profile-builder.js +1 -0
  64. package/dist/router/virtual-router/bootstrap/provider-normalization.d.ts +1 -0
  65. package/dist/router/virtual-router/bootstrap/provider-normalization.js +6 -0
  66. package/dist/router/virtual-router/bootstrap.js +1 -6
  67. package/dist/router/virtual-router/engine/routing-state/store.js +21 -2
  68. package/dist/router/virtual-router/engine-legacy.js +43 -0
  69. package/dist/router/virtual-router/engine-logging.d.ts +3 -0
  70. package/dist/router/virtual-router/engine-logging.js +29 -3
  71. package/dist/router/virtual-router/engine-selection/native-chat-process-governed-filter-semantics.d.ts +1 -0
  72. package/dist/router/virtual-router/engine-selection/native-chat-process-governed-filter-semantics.js +1 -0
  73. package/dist/router/virtual-router/engine-selection/native-compat-action-semantics.d.ts +3 -0
  74. package/dist/router/virtual-router/engine-selection/native-compat-action-semantics.js +72 -0
  75. package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.d.ts +1 -1
  76. package/dist/router/virtual-router/engine-selection/native-hub-bridge-action-semantics.js +1 -1
  77. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-inbound-outbound-semantics.d.ts +0 -1
  78. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-inbound-outbound-semantics.js +0 -29
  79. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-process-semantics.d.ts +1 -0
  80. package/dist/router/virtual-router/engine-selection/native-router-hotpath-loader.js +6 -2
  81. package/dist/router/virtual-router/engine.js +28 -13
  82. package/dist/router/virtual-router/provider-registry.js +1 -0
  83. package/dist/router/virtual-router/routing-instructions/state.js +44 -2
  84. package/dist/router/virtual-router/routing-instructions/types.d.ts +6 -0
  85. package/dist/router/virtual-router/token-estimator.js +21 -0
  86. package/dist/router/virtual-router/types.d.ts +7 -0
  87. package/dist/servertool/engine.js +3 -34
  88. package/dist/servertool/handlers/followup-request-builder.js +0 -6
  89. package/dist/servertool/handlers/gemini-empty-reply-continue.js +3 -274
  90. package/dist/servertool/handlers/stop-message-auto/runtime-utils.d.ts +0 -3
  91. package/dist/servertool/handlers/stop-message-auto/runtime-utils.js +0 -29
  92. package/dist/servertool/handlers/stop-message-auto.js +11 -9
  93. package/dist/servertool/handlers/vision.js +4 -1
  94. package/dist/servertool/server-side-tools.d.ts +0 -1
  95. package/dist/servertool/server-side-tools.js +67 -5
  96. package/dist/tools/apply-patch/execution-capturer.d.ts +1 -1
  97. package/dist/tools/apply-patch/execution-capturer.js +1 -2
  98. package/dist/tools/apply-patch/regression-capturer.js +2 -1
  99. package/dist/tools/tool-registry.js +1 -2
  100. package/package.json +1 -1
@@ -374,8 +374,7 @@ export function normalizeApplyPatchToolCallsOnResponse(chat) {
374
374
  originalArgs: rawArgs,
375
375
  normalizedArgs: argsStr,
376
376
  validationError: reason,
377
- source: 'tool-governor.response',
378
- meta: { applyPatchToolMode: 'freeform' }
377
+ source: 'tool-governor.response'
379
378
  });
380
379
  const snippet = typeof argsStr === 'string' && argsStr.trim().length
381
380
  ? argsStr.trim().slice(0, 200).replace(/\s+/g, ' ')
@@ -455,8 +454,7 @@ function normalizeSpecialToolCallsOnRequest(request) {
455
454
  originalArgs: rawArgs,
456
455
  normalizedArgs: argsStr,
457
456
  validationError: reason,
458
- source: 'tool-governor.request',
459
- meta: { applyPatchToolMode: 'freeform' }
457
+ source: 'tool-governor.request'
460
458
  });
461
459
  const snippet = typeof argsStr === 'string' && argsStr.trim().length
462
460
  ? argsStr.trim().slice(0, 200).replace(/\s+/g, ' ')
@@ -91,9 +91,6 @@ function shouldKeepProviderInPoolDuringCooldown(series, consecutive) {
91
91
  }
92
92
  return (series === 'ENET' || series === 'E5XX' || series === 'EOTHER') && consecutive <= 2;
93
93
  }
94
- function shouldAccumulateBySeries(series) {
95
- return series === 'ENET' || series === 'E5XX' || series === 'EOTHER';
96
- }
97
94
  function computeTransientKeepPoolCooldownMs(series, consecutive) {
98
95
  if (!shouldKeepProviderInPoolDuringCooldown(series, consecutive)) {
99
96
  return null;
@@ -149,9 +146,7 @@ export function applyErrorEvent(state, event, nowMs = event.timestampMs ?? Date.
149
146
  const withinChainWindow = typeof lastAt === 'number' &&
150
147
  nowMs - lastAt >= 0 &&
151
148
  nowMs - lastAt <= ERROR_CHAIN_WINDOW_MS;
152
- const sameErrorKey = withinChainWindow &&
153
- (state.lastErrorCode === errorKey ||
154
- (shouldAccumulateBySeries(series) && state.lastErrorSeries === series));
149
+ const sameErrorKey = withinChainWindow && state.lastErrorCode === errorKey;
155
150
  const schedule = series === 'E429'
156
151
  ? COOLDOWN_SCHEDULE_429_MS
157
152
  : series === 'EFATAL'
@@ -22,6 +22,7 @@ export function buildProviderProfiles(targetKeys, runtimeEntries) {
22
22
  providerType: runtime.providerType,
23
23
  endpoint: runtime.endpoint,
24
24
  auth: { ...runtime.auth },
25
+ ...(runtime.enabled !== undefined ? { enabled: runtime.enabled } : {}),
25
26
  outboundProfile: runtime.outboundProfile,
26
27
  compatibilityProfile: runtime.compatibilityProfile,
27
28
  runtimeKey,
@@ -12,6 +12,7 @@ export interface NormalizedProvider {
12
12
  providerType: string;
13
13
  endpoint: string;
14
14
  headers?: Record<string, string>;
15
+ enabled?: boolean;
15
16
  outboundProfile: string;
16
17
  compatibilityProfile: string;
17
18
  processMode: 'chat' | 'passthrough';
@@ -11,6 +11,11 @@ import { normalizeModelStreaming, normalizeModelContextTokens, normalizeModelOut
11
11
  */
12
12
  export function normalizeProvider(providerId, raw) {
13
13
  const provider = asRecord(raw);
14
+ const enabled = typeof provider.enabled === 'boolean'
15
+ ? provider.enabled
16
+ : typeof provider.enabled === 'string'
17
+ ? provider.enabled.trim().toLowerCase() !== 'false'
18
+ : undefined;
14
19
  const providerType = detectProviderType(provider);
15
20
  const endpoint = typeof provider.endpoint === 'string' && provider.endpoint.trim()
16
21
  ? provider.endpoint.trim()
@@ -46,6 +51,7 @@ export function normalizeProvider(providerId, raw) {
46
51
  providerType,
47
52
  endpoint,
48
53
  headers,
54
+ ...(enabled !== undefined ? { enabled } : {}),
49
55
  outboundProfile: mapOutboundProfile(providerType),
50
56
  compatibilityProfile,
51
57
  processMode,
@@ -14,18 +14,12 @@ export function bootstrapVirtualRouterConfig(input) {
14
14
  throw new VirtualRouterError('Virtual Router requires at least one provider in configuration', VirtualRouterErrorCode.CONFIG_ERROR);
15
15
  }
16
16
  const routingSource = normalizeRouting(section.routing);
17
- if (!Object.keys(routingSource).length) {
18
- throw new VirtualRouterError('Virtual Router routing table cannot be empty', VirtualRouterErrorCode.CONFIG_ERROR);
19
- }
20
17
  const webSearch = normalizeWebSearch(section.webSearch, routingSource);
21
18
  validateWebSearchRouting(webSearch, routingSource);
22
19
  const execCommandGuard = normalizeExecCommandGuard(section.execCommandGuard);
23
20
  const clock = normalizeClock(section.clock);
24
21
  const { runtimeEntries, aliasIndex, modelIndex } = buildProviderRuntimeEntries(providersSource);
25
22
  const { routing, targetKeys } = expandRoutingTable(routingSource, aliasIndex, modelIndex);
26
- if (!routing.default || routing.default.length === 0) {
27
- throw new VirtualRouterError('Virtual Router default route must contain at least one provider target', VirtualRouterErrorCode.CONFIG_ERROR);
28
- }
29
23
  const expandedTargetKeys = new Set(targetKeys);
30
24
  for (const [providerId, aliases] of aliasIndex.entries()) {
31
25
  const models = modelIndex.get(providerId)?.models ?? [];
@@ -123,6 +117,7 @@ function buildProviderRuntimeEntries(providers) {
123
117
  endpoint: normalizedProvider.endpoint,
124
118
  headers: normalizedProvider.headers,
125
119
  auth: runtimeAuth,
120
+ ...(normalizedProvider.enabled !== undefined ? { enabled: normalizedProvider.enabled } : {}),
126
121
  outboundProfile: normalizedProvider.outboundProfile,
127
122
  compatibilityProfile: normalizedProvider.compatibilityProfile,
128
123
  processMode: normalizedProvider.processMode,
@@ -49,6 +49,12 @@ export function getRoutingInstructionState(stickyKey, routingInstructionState, r
49
49
  existing.stopMessageAiMode = merged.stopMessageAiMode;
50
50
  existing.stopMessageAiSeedPrompt = merged.stopMessageAiSeedPrompt;
51
51
  existing.stopMessageAiHistory = merged.stopMessageAiHistory;
52
+ existing.chatProcessInputTokens = persisted?.chatProcessInputTokens;
53
+ existing.chatProcessMessageCount = persisted?.chatProcessMessageCount;
54
+ existing.chatProcessToolsSignature = persisted?.chatProcessToolsSignature;
55
+ existing.chatProcessParametersSignature = persisted?.chatProcessParametersSignature;
56
+ existing.chatProcessBoundarySignature = persisted?.chatProcessBoundarySignature;
57
+ existing.chatProcessUpdatedAt = persisted?.chatProcessUpdatedAt;
52
58
  if (persisted) {
53
59
  existing.preCommandSource = persisted.preCommandSource;
54
60
  existing.preCommandScriptPath = persisted.preCommandScriptPath;
@@ -85,7 +91,13 @@ export function getRoutingInstructionState(stickyKey, routingInstructionState, r
85
91
  stopMessageAiHistory: undefined,
86
92
  preCommandSource: undefined,
87
93
  preCommandScriptPath: undefined,
88
- preCommandUpdatedAt: undefined
94
+ preCommandUpdatedAt: undefined,
95
+ chatProcessInputTokens: undefined,
96
+ chatProcessMessageCount: undefined,
97
+ chatProcessToolsSignature: undefined,
98
+ chatProcessParametersSignature: undefined,
99
+ chatProcessBoundarySignature: undefined,
100
+ chatProcessUpdatedAt: undefined
89
101
  };
90
102
  }
91
103
  routingInstructionState.set(key, initial);
@@ -109,6 +121,12 @@ function isRoutingStateEmpty(state) {
109
121
  (typeof state.stopMessageAiMode !== 'string' || !state.stopMessageAiMode.trim());
110
122
  const noPreCommand = (!state.preCommandScriptPath || !state.preCommandScriptPath.trim()) &&
111
123
  (typeof state.preCommandUpdatedAt !== 'number' || !Number.isFinite(state.preCommandUpdatedAt));
124
+ const noChatProcessUsage = (typeof state.chatProcessInputTokens !== 'number' || !Number.isFinite(state.chatProcessInputTokens)) &&
125
+ (typeof state.chatProcessMessageCount !== 'number' || !Number.isFinite(state.chatProcessMessageCount)) &&
126
+ (!state.chatProcessToolsSignature || !state.chatProcessToolsSignature.trim()) &&
127
+ (!state.chatProcessParametersSignature || !state.chatProcessParametersSignature.trim()) &&
128
+ (!state.chatProcessBoundarySignature || !state.chatProcessBoundarySignature.trim()) &&
129
+ (typeof state.chatProcessUpdatedAt !== 'number' || !Number.isFinite(state.chatProcessUpdatedAt));
112
130
  return (noForced &&
113
131
  noSticky &&
114
132
  noPrefer &&
@@ -117,7 +135,8 @@ function isRoutingStateEmpty(state) {
117
135
  noDisabledKeys &&
118
136
  noDisabledModels &&
119
137
  noStopMessage &&
120
- noPreCommand);
138
+ noPreCommand &&
139
+ noChatProcessUsage);
121
140
  }
122
141
  export function persistRoutingInstructionState(key, state, routingStateStore) {
123
142
  if (!isPersistentScopeKey(key)) {
@@ -16,6 +16,25 @@ import { selectProvider as selectProviderImpl, selectFromCandidates as selectFro
16
16
  import { parseDirectProviderModel as parseDirectProviderModelImpl, shouldFallbackDirectModelForMedia as shouldFallbackDirectModelForMediaImpl } from './engine-legacy/direct-model.js';
17
17
  import { normalizeRouteAlias as normalizeRouteAliasImpl, buildRouteCandidates as buildRouteCandidatesImpl, reorderForInlineVision as reorderForInlineVisionImpl, reorderForPreferredModel as reorderForPreferredModelImpl, routeSupportsModel as routeSupportsModelImpl, routeSupportsInlineVision as routeSupportsInlineVisionImpl, sortByPriority as sortByPriorityImpl, routeWeight as routeWeightImpl, routeHasForceFlag as routeHasForceFlagImpl, routeHasTargets as routeHasTargetsImpl, hasPrimaryPool as hasPrimaryPoolImpl, sortRoutePools as sortRoutePoolsImpl, flattenPoolTargets as flattenPoolTargetsImpl } from './engine-legacy/route-utils.js';
18
18
  import { resolveSelectionPenalty as resolveSelectionPenaltyImpl, resolveInstructionProcessModeForSelection as resolveInstructionProcessModeForSelectionImpl, resolveInstructionTarget as resolveInstructionTargetImpl, filterCandidatesByRoutingState as filterCandidatesByRoutingStateImpl, buildStickyRouteCandidatesFromFiltered as buildStickyRouteCandidatesFromFilteredImpl } from './engine-legacy/selection-state.js';
19
+ const ALLOW_ENGINE_LEGACY_IMPORTS = process.env.LLMSWITCH_ALLOW_ENGINE_LEGACY_IMPORTS === '1' ||
20
+ process.env.ROUTECODEX_ALLOW_ENGINE_LEGACY_IMPORTS === '1';
21
+ if (!ALLOW_ENGINE_LEGACY_IMPORTS) {
22
+ throw new Error('[engine-legacy] import is fail-closed. Set LLMSWITCH_ALLOW_ENGINE_LEGACY_IMPORTS=1 only for explicit compatibility/debug work.');
23
+ }
24
+ function warnLegacyCompatibilitySurface(method) {
25
+ const enabled = process.env.LLMSWITCH_WARN_LEGACY_SURFACES === '1' ||
26
+ process.env.ROUTECODEX_WARN_LEGACY_SURFACES === '1';
27
+ if (!enabled) {
28
+ return;
29
+ }
30
+ try {
31
+ // eslint-disable-next-line no-console
32
+ console.warn(`[engine-legacy] compatibility surface invoked: ${method}. Do not add new runtime logic to engine-legacy helpers.`);
33
+ }
34
+ catch {
35
+ // best-effort only
36
+ }
37
+ }
19
38
  export class VirtualRouterEngine {
20
39
  routing = {};
21
40
  providerRegistry = new ProviderRegistry();
@@ -99,42 +118,55 @@ export class VirtualRouterEngine {
99
118
  return this.nativeEngine.getStatus();
100
119
  }
101
120
  normalizeRouteAlias(routeName) {
121
+ warnLegacyCompatibilitySurface('normalizeRouteAlias');
102
122
  return normalizeRouteAliasImpl(routeName);
103
123
  }
104
124
  buildRouteCandidates(requestedRoute, classificationCandidates, features) {
125
+ warnLegacyCompatibilitySurface('buildRouteCandidates');
105
126
  return buildRouteCandidatesImpl(this, requestedRoute, classificationCandidates, features);
106
127
  }
107
128
  reorderForInlineVision(routeNames) {
129
+ warnLegacyCompatibilitySurface('reorderForInlineVision');
108
130
  return reorderForInlineVisionImpl(this, routeNames);
109
131
  }
110
132
  reorderForPreferredModel(routeNames, modelId) {
133
+ warnLegacyCompatibilitySurface('reorderForPreferredModel');
111
134
  return reorderForPreferredModelImpl(this, routeNames, modelId);
112
135
  }
113
136
  routeSupportsModel(routeName, modelId) {
137
+ warnLegacyCompatibilitySurface('routeSupportsModel');
114
138
  return routeSupportsModelImpl(this, routeName, modelId);
115
139
  }
116
140
  routeSupportsInlineVision(routeName) {
141
+ warnLegacyCompatibilitySurface('routeSupportsInlineVision');
117
142
  return routeSupportsInlineVisionImpl(this, routeName);
118
143
  }
119
144
  sortByPriority(routeNames) {
145
+ warnLegacyCompatibilitySurface('sortByPriority');
120
146
  return sortByPriorityImpl(routeNames);
121
147
  }
122
148
  routeWeight(routeName) {
149
+ warnLegacyCompatibilitySurface('routeWeight');
123
150
  return routeWeightImpl(routeName);
124
151
  }
125
152
  routeHasForceFlag(routeName) {
153
+ warnLegacyCompatibilitySurface('routeHasForceFlag');
126
154
  return routeHasForceFlagImpl(this, routeName);
127
155
  }
128
156
  routeHasTargets(pools) {
157
+ warnLegacyCompatibilitySurface('routeHasTargets');
129
158
  return routeHasTargetsImpl(this, pools);
130
159
  }
131
160
  hasPrimaryPool(pools) {
161
+ warnLegacyCompatibilitySurface('hasPrimaryPool');
132
162
  return hasPrimaryPoolImpl(this, pools);
133
163
  }
134
164
  sortRoutePools(pools) {
165
+ warnLegacyCompatibilitySurface('sortRoutePools');
135
166
  return sortRoutePoolsImpl(this, pools);
136
167
  }
137
168
  flattenPoolTargets(pools) {
169
+ warnLegacyCompatibilitySurface('flattenPoolTargets');
138
170
  return flattenPoolTargetsImpl(this, pools);
139
171
  }
140
172
  markProviderCooldown(providerKey, cooldownMs) {
@@ -167,36 +199,47 @@ export class VirtualRouterEngine {
167
199
  return shouldFallbackDirectModelForMediaImpl(this, direct, features);
168
200
  }
169
201
  selectProvider(requestedRoute, metadata, classification, features, routingState) {
202
+ warnLegacyCompatibilitySurface('selectProvider');
170
203
  return selectProviderImpl(this, requestedRoute, metadata, classification, features, routingState);
171
204
  }
172
205
  selectFromCandidates(routes, metadata, classification, features, state, requiredProviderKeys, allowAliasRotation) {
206
+ warnLegacyCompatibilitySurface('selectFromCandidates');
173
207
  return selectFromCandidatesImpl(this, routes, metadata, classification, features, state, requiredProviderKeys, allowAliasRotation);
174
208
  }
175
209
  selectFromStickyPool(stickyKeySet, metadata, features, state, allowAliasRotation) {
210
+ warnLegacyCompatibilitySurface('selectFromStickyPool');
176
211
  return selectFromStickyPoolImpl(this, stickyKeySet, metadata, features, state, allowAliasRotation);
177
212
  }
178
213
  extractExcludedProviderKeySet(metadata) {
214
+ warnLegacyCompatibilitySurface('extractExcludedProviderKeySet');
179
215
  return extractExcludedProviderKeySetImpl(this, metadata);
180
216
  }
181
217
  resolveSelectionPenalty(providerKey) {
218
+ warnLegacyCompatibilitySurface('resolveSelectionPenalty');
182
219
  return resolveSelectionPenaltyImpl(this, providerKey);
183
220
  }
184
221
  resolveInstructionProcessModeForSelection(providerKey, routingState) {
222
+ warnLegacyCompatibilitySurface('resolveInstructionProcessModeForSelection');
185
223
  return resolveInstructionProcessModeForSelectionImpl(this, providerKey, routingState);
186
224
  }
187
225
  resolveInstructionTarget(target) {
226
+ warnLegacyCompatibilitySurface('resolveInstructionTarget');
188
227
  return resolveInstructionTargetImpl(this, target);
189
228
  }
190
229
  buildStickyRouteCandidatesFromFiltered(filteredCandidates, stickyKeySet) {
230
+ warnLegacyCompatibilitySurface('buildStickyRouteCandidatesFromFiltered');
191
231
  return buildStickyRouteCandidatesFromFilteredImpl(this, filteredCandidates, stickyKeySet);
192
232
  }
193
233
  filterCandidatesByRoutingState(routes, state) {
234
+ warnLegacyCompatibilitySurface('filterCandidatesByRoutingState');
194
235
  return filterCandidatesByRoutingStateImpl(this, routes, state);
195
236
  }
196
237
  resolveStickyKey(metadata) {
238
+ warnLegacyCompatibilitySurface('resolveStickyKey');
197
239
  return resolveStickyKeyImpl(metadata);
198
240
  }
199
241
  resolveSessionScope(metadata) {
242
+ warnLegacyCompatibilitySurface('resolveSessionScope');
200
243
  return resolveSessionScopeImpl(metadata);
201
244
  }
202
245
  }
@@ -20,6 +20,7 @@ export type StopMessageRuntimeSummary = {
20
20
  export type VirtualRouterHitRecord = {
21
21
  timestampMs: number;
22
22
  requestId?: string;
23
+ sessionId?: string;
23
24
  routeName: string;
24
25
  poolId?: string;
25
26
  providerKey: string;
@@ -36,6 +37,7 @@ export type VirtualRouterHitEventMeta = {
36
37
  };
37
38
  export declare function createVirtualRouterHitRecord(input: {
38
39
  requestId?: string;
40
+ sessionId?: string;
39
41
  routeName: string;
40
42
  poolId?: string;
41
43
  providerKey: string;
@@ -58,6 +60,7 @@ export declare function describeTargetProvider(providerKey: string, fallbackMode
58
60
  providerLabel: string;
59
61
  resolvedModel?: string;
60
62
  };
63
+ export declare function resolveSessionColor(sessionId?: string): string;
61
64
  export declare function buildHitReason(routeUsed: string, providerKey: string, classification: ClassificationResult, features: RoutingFeatures, mode: RoutingInstructionMode | undefined, deps: LoggingDeps): string;
62
65
  export declare function formatVirtualRouterHit(record: VirtualRouterHitRecord): string;
63
66
  export {};
@@ -66,6 +66,7 @@ export function createVirtualRouterHitRecord(input) {
66
66
  ? input.timestampMs
67
67
  : Date.now(),
68
68
  ...(input.requestId ? { requestId: input.requestId } : {}),
69
+ ...(input.sessionId ? { sessionId: input.sessionId } : {}),
69
70
  routeName: input.routeName,
70
71
  ...(input.poolId ? { poolId: input.poolId } : {}),
71
72
  providerKey: input.providerKey,
@@ -156,6 +157,27 @@ function resolveRouteColor(routeName) {
156
157
  };
157
158
  return map[routeName] ?? '\x1b[36m';
158
159
  }
160
+ export function resolveSessionColor(sessionId) {
161
+ const palette = [
162
+ '\x1b[31m',
163
+ '\x1b[32m',
164
+ '\x1b[33m',
165
+ '\x1b[34m',
166
+ '\x1b[35m',
167
+ '\x1b[36m',
168
+ '\x1b[38;5;208m',
169
+ '\x1b[38;5;141m'
170
+ ];
171
+ const normalized = typeof sessionId === 'string' ? sessionId.trim() : '';
172
+ if (!normalized) {
173
+ return '\x1b[36m';
174
+ }
175
+ let hash = 0;
176
+ for (let i = 0; i < normalized.length; i += 1) {
177
+ hash = ((hash * 31) + normalized.charCodeAt(i)) >>> 0;
178
+ }
179
+ return palette[hash % palette.length];
180
+ }
159
181
  function describeContextUsage(providerKey, estimatedTokens, deps) {
160
182
  if (typeof estimatedTokens !== 'number' || !Number.isFinite(estimatedTokens) || estimatedTokens <= 0) {
161
183
  return undefined;
@@ -243,7 +265,7 @@ export function formatVirtualRouterHit(record) {
243
265
  const reset = '\x1b[0m';
244
266
  const timeColor = '\x1b[90m';
245
267
  const stickyColor = '\x1b[33m';
246
- const routeColor = resolveRouteColor(record.routeName);
268
+ const routeColor = resolveSessionColor(record.sessionId);
247
269
  const stopColor = '\x1b[38;5;214m';
248
270
  const prefix = `${prefixColor}[virtual-router-hit]${reset}`;
249
271
  const timeLabel = `${timeColor}${timestamp}${reset}`;
@@ -252,6 +274,8 @@ export function formatVirtualRouterHit(record) {
252
274
  const targetLabel = `${routeLabel} -> ${providerLabel}${resolvedModel ? '.' + resolvedModel : ''}`;
253
275
  const requestId = typeof record.requestId === 'string' ? record.requestId : '';
254
276
  const requestLabel = requestId && !requestId.includes('unknown') ? ` req=${requestId}` : '';
277
+ const sessionId = typeof record.sessionId === 'string' ? record.sessionId.trim() : '';
278
+ const sessionLabel = sessionId ? ` sid=${sessionId}` : '';
255
279
  const stickyText = formatStickyScope(record.stickyScope);
256
280
  const stickyLabel = stickyText ? ` ${stickyColor}[sticky:${stickyText}]${reset}` : '';
257
281
  const reasonLabel = record.hitReason ? ` reason=${record.hitReason}` : '';
@@ -279,7 +303,7 @@ export function formatVirtualRouterHit(record) {
279
303
  }
280
304
  stopLabel = ` ${stopColor}[stopMessage:${parts.join(' ')}]${reset}`;
281
305
  }
282
- return `${prefix} ${timeLabel}${requestLabel} ${routeColor}${targetLabel}${stickyLabel}${reasonLabel}${requestTokenLabel}${penaltyLabel}${stopLabel}${reset}`;
306
+ return `${prefix} ${timeLabel}${requestLabel}${sessionLabel} ${routeColor}${targetLabel}${stickyLabel}${reasonLabel}${requestTokenLabel}${penaltyLabel}${stopLabel}${reset}`;
283
307
  }
284
308
  catch {
285
309
  const now = new Date(record.timestampMs);
@@ -289,6 +313,8 @@ export function formatVirtualRouterHit(record) {
289
313
  const stickyLabel = stickyText ? ` [sticky:${stickyText}]` : '';
290
314
  const requestId = typeof record.requestId === 'string' ? record.requestId : '';
291
315
  const requestLabel = requestId && !requestId.includes('unknown') ? ` req=${requestId}` : '';
316
+ const sessionId = typeof record.sessionId === 'string' ? record.sessionId.trim() : '';
317
+ const sessionLabel = sessionId ? ` sid=${sessionId}` : '';
292
318
  const requestTokenLabel = typeof record.requestTokens === 'number' && Number.isFinite(record.requestTokens)
293
319
  ? ` reqTokens=${Math.max(0, Math.round(record.requestTokens))}`
294
320
  : '';
@@ -303,6 +329,6 @@ export function formatVirtualRouterHit(record) {
303
329
  const left = stop.remaining >= 0 ? String(stop.remaining) : 'n/a';
304
330
  stopLabel = ` [stopMessage:${safeText} mode=${stop.mode} round=${rounds} active=${stop.active ? 'yes' : 'no'} left=${left}]`;
305
331
  }
306
- return `[virtual-router-hit] ${timestamp}${requestLabel} ${routeLabel} -> ${record.providerKey}${record.modelId ? '.' + record.modelId : ''}${stickyLabel}${record.hitReason ? ` reason=${record.hitReason}` : ''}${requestTokenLabel}${penaltyLabel}${stopLabel}`;
332
+ return `[virtual-router-hit] ${timestamp}${requestLabel}${sessionLabel} ${routeLabel} -> ${record.providerKey}${record.modelId ? '.' + record.modelId : ''}${stickyLabel}${record.hitReason ? ` reason=${record.hitReason}` : ''}${requestTokenLabel}${penaltyLabel}${stopLabel}`;
307
333
  }
308
334
  }
@@ -3,6 +3,7 @@ export type NativeGovernedFilterPayload = {
3
3
  messages: unknown[];
4
4
  tools?: unknown;
5
5
  tool_choice?: unknown;
6
+ parallel_tool_calls?: unknown;
6
7
  stream: boolean;
7
8
  parameters: Record<string, unknown>;
8
9
  };
@@ -19,6 +19,7 @@ function parsePayload(raw) {
19
19
  messages,
20
20
  ...(row.tools !== undefined ? { tools: row.tools } : {}),
21
21
  ...(row.tool_choice !== undefined ? { tool_choice: row.tool_choice } : {}),
22
+ ...(row.parallel_tool_calls !== undefined ? { parallel_tool_calls: row.parallel_tool_calls } : {}),
22
23
  stream: row.stream,
23
24
  parameters
24
25
  };
@@ -1,6 +1,8 @@
1
1
  export declare function normalizeResponsePayloadWithNative(payload: Record<string, unknown>, config?: Record<string, unknown>): Record<string, unknown>;
2
2
  export declare function validateResponsePayloadWithNative(payload: Record<string, unknown>): void;
3
3
  export declare function applyRequestRulesWithNative(payload: Record<string, unknown>, config?: Record<string, unknown>): Record<string, unknown>;
4
+ export declare function applyFieldMappingsWithNative(payload: Record<string, unknown>, mappings: Record<string, unknown>[]): Record<string, unknown>;
5
+ export declare function stringifyLmstudioResponsesInputWithNative(payload: Record<string, unknown>, adapterContext?: Record<string, unknown>): Record<string, unknown>;
4
6
  export declare function applyResponseBlacklistWithNative(payload: Record<string, unknown>, config?: Record<string, unknown>): Record<string, unknown>;
5
7
  export declare function normalizeToolCallIdsWithNative(payload: Record<string, unknown>): Record<string, unknown>;
6
8
  export declare function enforceLmstudioResponsesFcToolCallIdsWithNative(payload: Record<string, unknown>): Record<string, unknown>;
@@ -16,6 +18,7 @@ export declare function buildAnthropicFromOpenAIChatWithNative(payload: Record<s
16
18
  export declare function runOpenAIRequestCodecWithNative(payload: Record<string, unknown>, options?: Record<string, unknown>): Record<string, unknown>;
17
19
  export declare function runOpenAIResponseCodecWithNative(payload: Record<string, unknown>, options?: Record<string, unknown>): Record<string, unknown>;
18
20
  export declare function runResponsesOpenAIRequestCodecWithNative(payload: Record<string, unknown>, options?: Record<string, unknown>): Record<string, unknown>;
21
+ export declare function runResponsesOpenAIReqInboundSemanticMapWithNative(payload: Record<string, unknown>, options?: Record<string, unknown>): Record<string, unknown>;
19
22
  export declare function runResponsesOpenAIResponseCodecWithNative(payload: Record<string, unknown>, context: Record<string, unknown>): Record<string, unknown>;
20
23
  export declare function runGeminiOpenAIRequestCodecWithNative(payload: Record<string, unknown>, options?: Record<string, unknown>): Record<string, unknown>;
21
24
  export declare function runGeminiOpenAIResponseCodecWithNative(payload: Record<string, unknown>, options?: Record<string, unknown>): Record<string, unknown>;
@@ -101,6 +101,54 @@ export function applyRequestRulesWithNative(payload, config) {
101
101
  return fail(reason);
102
102
  }
103
103
  }
104
+ export function applyFieldMappingsWithNative(payload, mappings) {
105
+ const capability = "applyFieldMappingsJson";
106
+ const fail = (reason) => failNativeRequired(capability, reason);
107
+ if (isNativeDisabledByEnv())
108
+ return fail("native disabled");
109
+ const fn = readNativeFunction(capability);
110
+ if (!fn)
111
+ return fail();
112
+ const payloadJson = safeStringify(payload);
113
+ const mappingsJson = safeStringify(Array.isArray(mappings) ? mappings : []);
114
+ if (!payloadJson || !mappingsJson)
115
+ return fail("json stringify failed");
116
+ try {
117
+ const raw = fn(payloadJson, mappingsJson);
118
+ if (typeof raw !== "string" || !raw)
119
+ return fail("empty result");
120
+ const parsed = parseRecord(raw);
121
+ return parsed ?? fail("invalid payload");
122
+ }
123
+ catch (error) {
124
+ const reason = error instanceof Error ? error.message : String(error ?? "unknown");
125
+ return fail(reason);
126
+ }
127
+ }
128
+ export function stringifyLmstudioResponsesInputWithNative(payload, adapterContext) {
129
+ const capability = "stringifyLmstudioResponsesInputJson";
130
+ const fail = (reason) => failNativeRequired(capability, reason);
131
+ if (isNativeDisabledByEnv())
132
+ return fail("native disabled");
133
+ const fn = readNativeFunction(capability);
134
+ if (!fn)
135
+ return fail();
136
+ const payloadJson = safeStringify(payload);
137
+ const contextJson = adapterContext ? safeStringify(adapterContext) : "{}";
138
+ if (!payloadJson || !contextJson)
139
+ return fail("json stringify failed");
140
+ try {
141
+ const raw = fn(payloadJson, contextJson);
142
+ if (typeof raw !== "string" || !raw)
143
+ return fail("empty result");
144
+ const parsed = parseRecord(raw);
145
+ return parsed ?? fail("invalid payload");
146
+ }
147
+ catch (error) {
148
+ const reason = error instanceof Error ? error.message : String(error ?? "unknown");
149
+ return fail(reason);
150
+ }
151
+ }
104
152
  export function applyResponseBlacklistWithNative(payload, config) {
105
153
  const capability = "applyResponseBlacklistJson";
106
154
  const fail = (reason) => failNativeRequired(capability, reason);
@@ -461,6 +509,30 @@ export function runResponsesOpenAIRequestCodecWithNative(payload, options) {
461
509
  return fail(reason);
462
510
  }
463
511
  }
512
+ export function runResponsesOpenAIReqInboundSemanticMapWithNative(payload, options) {
513
+ const capability = "runResponsesOpenaiReqInboundSemanticMapJson";
514
+ const fail = (reason) => failNativeRequired(capability, reason);
515
+ if (isNativeDisabledByEnv())
516
+ return fail("native disabled");
517
+ const fn = readNativeFunction(capability);
518
+ if (!fn)
519
+ return fail();
520
+ const payloadJson = safeStringify(payload);
521
+ const optionsJson = options ? safeStringify(options) : "{}";
522
+ if (!payloadJson || !optionsJson)
523
+ return fail("json stringify failed");
524
+ try {
525
+ const raw = fn(payloadJson, optionsJson);
526
+ if (typeof raw !== "string" || !raw)
527
+ return fail("empty result");
528
+ const parsed = parseRecord(raw);
529
+ return parsed ?? fail("invalid payload");
530
+ }
531
+ catch (error) {
532
+ const reason = error instanceof Error ? error.message : String(error ?? "unknown");
533
+ return fail(reason);
534
+ }
535
+ }
464
536
  export function runResponsesOpenAIResponseCodecWithNative(payload, context) {
465
537
  const capability = "runResponsesOpenaiResponseCodecJson";
466
538
  const fail = (reason) => failNativeRequired(capability, reason);
@@ -47,7 +47,7 @@ export interface NativeResolveResponsesBridgeToolsOutput {
47
47
  }
48
48
  export interface NativeResolveResponsesRequestBridgeDecisionsInput {
49
49
  context?: Record<string, unknown>;
50
- requestMetadata?: Record<string, unknown>;
50
+ routeToolCallIdStyle?: 'fc' | 'preserve';
51
51
  envelopeMetadata?: Record<string, unknown>;
52
52
  bridgeMetadata?: Record<string, unknown>;
53
53
  extraBridgeHistory?: Record<string, unknown>;
@@ -600,7 +600,7 @@ export function resolveResponsesRequestBridgeDecisionsWithNative(input) {
600
600
  }
601
601
  const payloadJson = safeStringify({
602
602
  context: input.context,
603
- requestMetadata: input.requestMetadata,
603
+ routeToolCallIdStyle: input.routeToolCallIdStyle,
604
604
  envelopeMetadata: input.envelopeMetadata,
605
605
  bridgeMetadata: input.bridgeMetadata,
606
606
  extraBridgeHistory: input.extraBridgeHistory
@@ -19,4 +19,3 @@ export declare function mergeContextToolOutputsWithNative(existing: unknown, sna
19
19
  name?: string;
20
20
  }> | undefined;
21
21
  export declare function normalizeContextToolsWithNative(snapshot: Record<string, unknown>): unknown[] | undefined;
22
- export declare function selectToolCallIdStyleWithNative(adapterContext: unknown, snapshot: Record<string, unknown>, current: string | undefined): string | undefined;
@@ -395,32 +395,3 @@ export function normalizeContextToolsWithNative(snapshot) {
395
395
  return fail(reason);
396
396
  }
397
397
  }
398
- export function selectToolCallIdStyleWithNative(adapterContext, snapshot, current) {
399
- const capability = 'selectToolCallIdStyleJson';
400
- const fail = (reason) => failNativeRequired(capability, reason);
401
- if (isNativeDisabledByEnv()) {
402
- return fail('native disabled');
403
- }
404
- const fn = readNativeFunction('selectToolCallIdStyleJson');
405
- if (!fn) {
406
- return fail();
407
- }
408
- const adapterContextJson = safeStringify(adapterContext);
409
- const snapshotJson = safeStringify(snapshot);
410
- const currentJson = safeStringify(current ?? null);
411
- if (!adapterContextJson || !snapshotJson || !currentJson) {
412
- return fail('json stringify failed');
413
- }
414
- try {
415
- const raw = fn(adapterContextJson, snapshotJson, currentJson);
416
- if (typeof raw !== 'string' || !raw) {
417
- return fail('empty result');
418
- }
419
- const parsed = parseStyle(raw);
420
- return parsed === null ? fail('invalid payload') : parsed;
421
- }
422
- catch (error) {
423
- const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
424
- return fail(reason);
425
- }
426
- }
@@ -4,6 +4,7 @@ export interface NativeReqProcessToolGovernanceInput {
4
4
  metadata: Record<string, unknown>;
5
5
  entryEndpoint: string;
6
6
  requestId: string;
7
+ hasActiveStopMessageForContinueExecution?: boolean;
7
8
  }
8
9
  export interface NativeReqProcessToolGovernanceOutput {
9
10
  processedRequest: Record<string, unknown>;
@@ -4,7 +4,9 @@ import { pathToFileURL } from "node:url";
4
4
  import { createRequire } from "node:module";
5
5
  import { hasCompleteNativeBinding } from "./native-router-hotpath-policy.js";
6
6
  function resolveLoaderModulePath() {
7
- if (typeof __filename === "string" && __filename.length > 0) {
7
+ if (typeof __filename === "string" &&
8
+ __filename.length > 0 &&
9
+ __filename !== "[stdin]") {
8
10
  return __filename;
9
11
  }
10
12
  const stack = String(new Error().stack || "");
@@ -216,6 +218,8 @@ const REQUIRED_NATIVE_EXPORTS = [
216
218
  "stripInternalToolingMetadataJson",
217
219
  "enforceLmstudioResponsesFcToolCallIdsJson",
218
220
  "applyRequestRulesJson",
221
+ "applyFieldMappingsJson",
222
+ "stringifyLmstudioResponsesInputJson",
219
223
  "applyAnthropicClaudeCodeUserIdJson",
220
224
  "applyGeminiWebSearchRequestCompatJson",
221
225
  "prepareAntigravityThoughtSignatureForGeminiRequestJson",
@@ -226,6 +230,7 @@ const REQUIRED_NATIVE_EXPORTS = [
226
230
  "runOpenaiOpenaiRequestCodecJson",
227
231
  "runOpenaiOpenaiResponseCodecJson",
228
232
  "runResponsesOpenaiRequestCodecJson",
233
+ "runResponsesOpenaiReqInboundSemanticMapJson",
229
234
  "runResponsesOpenaiResponseCodecJson",
230
235
  "runGeminiOpenaiRequestCodecJson",
231
236
  "runGeminiOpenaiResponseCodecJson",
@@ -317,7 +322,6 @@ const REQUIRED_NATIVE_EXPORTS = [
317
322
  "sanitizeResponsesFunctionNameJson",
318
323
  "shouldRecordSnapshotsJson",
319
324
  "writeSnapshotViaHooksJson",
320
- "selectToolCallIdStyleJson",
321
325
  "serializeStopMessageStateJson",
322
326
  "shouldAttachReqOutboundContextSnapshotJson",
323
327
  "shouldReserveClockDueReminderJson",