@jsonstudio/llms 0.6.3551 → 0.6.3686

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 (66) hide show
  1. package/dist/conversion/compat/actions/antigravity-thought-signature-cache.js +4 -115
  2. package/dist/conversion/compat/actions/auto-thinking.js +3 -2
  3. package/dist/conversion/compat/actions/deepseek-web-response.js +15 -49
  4. package/dist/conversion/compat/actions/gemini-cli-request.d.ts +2 -0
  5. package/dist/conversion/compat/actions/gemini-cli-request.js +1 -1
  6. package/dist/conversion/compat/actions/glm-history-image-trim.js +3 -37
  7. package/dist/conversion/compat/actions/glm-image-content.js +3 -32
  8. package/dist/conversion/compat/actions/glm-native-compat.d.ts +6 -0
  9. package/dist/conversion/compat/actions/glm-native-compat.js +34 -0
  10. package/dist/conversion/compat/actions/glm-vision-prompt.js +3 -76
  11. package/dist/conversion/compat/actions/glm-web-search.js +10 -43
  12. package/dist/conversion/compat/actions/iflow-kimi-cli-defaults.js +4 -53
  13. package/dist/conversion/compat/actions/iflow-kimi-history-media-placeholder.js +5 -141
  14. package/dist/conversion/compat/actions/iflow-kimi-thinking-reasoning-fill.js +7 -28
  15. package/dist/conversion/compat/actions/iflow-native-compat.d.ts +6 -0
  16. package/dist/conversion/compat/actions/iflow-native-compat.js +36 -0
  17. package/dist/conversion/compat/actions/iflow-response-body-unwrap.js +4 -119
  18. package/dist/conversion/compat/actions/iflow-web-search.js +14 -55
  19. package/dist/conversion/hub/operation-table/semantic-mappers/archive/chat-mapper.archive.js +5 -0
  20. package/dist/conversion/hub/operation-table/semantic-mappers/responses-mapper.js +31 -18
  21. package/dist/conversion/hub/pipeline/hub-pipeline.js +163 -163
  22. package/dist/conversion/hub/pipeline/hub-stage-timing.d.ts +6 -0
  23. package/dist/conversion/hub/pipeline/hub-stage-timing.js +178 -0
  24. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage1_format_parse/index.d.ts +4 -4
  25. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage1_format_parse/index.js +33 -14
  26. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.d.ts +7 -6
  27. package/dist/conversion/hub/pipeline/stages/req_inbound/req_inbound_stage2_semantic_map/index.js +41 -23
  28. package/dist/conversion/hub/pipeline/stages/req_outbound/req_outbound_stage1_semantic_map/index.js +44 -1
  29. package/dist/conversion/hub/pipeline/stages/req_process/req_process_stage1_tool_governance/index.js +4 -1
  30. package/dist/conversion/hub/process/chat-process-continue-execution.js +5 -4
  31. package/dist/conversion/hub/process/chat-process-governance-orchestration.js +3 -1
  32. package/dist/conversion/hub/process/chat-process-media.d.ts +3 -1
  33. package/dist/conversion/hub/process/chat-process-media.js +92 -2
  34. package/dist/conversion/hub/process/chat-process-session-usage.d.ts +7 -0
  35. package/dist/conversion/hub/process/chat-process-session-usage.js +147 -0
  36. package/dist/conversion/hub/response/provider-response.js +13 -0
  37. package/dist/conversion/responses/responses-openai-bridge/response-payload.js +0 -12
  38. package/dist/conversion/responses/responses-openai-bridge/types.d.ts +1 -9
  39. package/dist/conversion/responses/responses-openai-bridge.js +77 -44
  40. package/dist/conversion/shared/reasoning-normalizer.js +42 -0
  41. package/dist/conversion/shared/responses-tool-utils.js +2 -3
  42. package/dist/native/router_hotpath_napi.node +0 -0
  43. package/dist/router/virtual-router/bootstrap/profile-builder.js +1 -0
  44. package/dist/router/virtual-router/bootstrap/provider-normalization.d.ts +1 -0
  45. package/dist/router/virtual-router/bootstrap/provider-normalization.js +6 -0
  46. package/dist/router/virtual-router/bootstrap.js +1 -6
  47. package/dist/router/virtual-router/engine-legacy.js +43 -0
  48. package/dist/router/virtual-router/engine-logging.d.ts +3 -0
  49. package/dist/router/virtual-router/engine-logging.js +29 -3
  50. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-edge-stage-semantics.d.ts +2 -2
  51. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-edge-stage-semantics.js +96 -80
  52. package/dist/router/virtual-router/engine-selection/native-hub-pipeline-req-process-semantics.d.ts +1 -0
  53. package/dist/router/virtual-router/engine.js +34 -22
  54. package/dist/router/virtual-router/provider-registry.js +1 -0
  55. package/dist/router/virtual-router/routing-instructions/state.js +35 -3
  56. package/dist/router/virtual-router/routing-instructions/types.d.ts +4 -0
  57. package/dist/router/virtual-router/types.d.ts +7 -0
  58. package/dist/servertool/engine.js +3 -34
  59. package/dist/servertool/handlers/followup-request-builder.js +0 -6
  60. package/dist/servertool/handlers/gemini-empty-reply-continue.js +3 -274
  61. package/dist/servertool/handlers/stop-message-auto/runtime-utils.d.ts +0 -3
  62. package/dist/servertool/handlers/stop-message-auto/runtime-utils.js +0 -29
  63. package/dist/servertool/handlers/stop-message-auto.js +2 -10
  64. package/dist/servertool/handlers/vision.js +4 -1
  65. package/dist/servertool/server-side-tools.js +66 -3
  66. package/package.json +1 -1
@@ -1,9 +1,11 @@
1
- import { failNativeRequired, isNativeDisabledByEnv } from './native-router-hotpath-policy.js';
2
- import { loadNativeRouterHotpathBindingForInternalUse } from './native-router-hotpath.js';
1
+ import { failNativeRequired, isNativeDisabledByEnv, } from "./native-router-hotpath-policy.js";
2
+ import { loadNativeRouterHotpathBindingForInternalUse } from "./native-router-hotpath.js";
3
3
  function readNativeFunction(name) {
4
4
  const binding = loadNativeRouterHotpathBindingForInternalUse();
5
5
  const fn = binding?.[name];
6
- return typeof fn === 'function' ? fn : null;
6
+ return typeof fn === "function"
7
+ ? fn
8
+ : null;
7
9
  }
8
10
  function safeStringify(value) {
9
11
  try {
@@ -16,7 +18,7 @@ function safeStringify(value) {
16
18
  function parseRecord(raw) {
17
19
  try {
18
20
  const parsed = JSON.parse(raw);
19
- if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
21
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
20
22
  return null;
21
23
  }
22
24
  return parsed;
@@ -28,27 +30,31 @@ function parseRecord(raw) {
28
30
  function parseFormatEnvelopePayload(raw, direction, fallbackProtocol, fallbackPayload) {
29
31
  try {
30
32
  const parsed = JSON.parse(raw);
31
- if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
33
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
32
34
  return null;
33
35
  }
34
36
  const row = parsed;
35
37
  const envelope = row.envelope;
36
- if (!envelope || typeof envelope !== 'object' || Array.isArray(envelope)) {
38
+ if (!envelope || typeof envelope !== "object" || Array.isArray(envelope)) {
37
39
  return null;
38
40
  }
39
41
  const env = envelope;
40
- const protocol = typeof env.format === 'string' && env.format.trim().length
42
+ const protocol = typeof env.format === "string" && env.format.trim().length
41
43
  ? env.format.trim()
42
44
  : fallbackProtocol;
43
- const payload = env.payload && typeof env.payload === 'object' && !Array.isArray(env.payload)
45
+ const payload = env.payload &&
46
+ typeof env.payload === "object" &&
47
+ !Array.isArray(env.payload)
44
48
  ? env.payload
45
49
  : fallbackPayload;
46
50
  const out = {
47
51
  protocol,
48
52
  direction,
49
- payload
53
+ payload,
50
54
  };
51
- if (env.metadata && typeof env.metadata === 'object' && !Array.isArray(env.metadata)) {
55
+ if (env.metadata &&
56
+ typeof env.metadata === "object" &&
57
+ !Array.isArray(env.metadata)) {
52
58
  out.meta = env.metadata;
53
59
  }
54
60
  return out;
@@ -63,7 +69,7 @@ function parseOptionalString(raw) {
63
69
  if (parsed === null) {
64
70
  return undefined;
65
71
  }
66
- if (typeof parsed !== 'string') {
72
+ if (typeof parsed !== "string") {
67
73
  return null;
68
74
  }
69
75
  const trimmed = parsed.trim();
@@ -76,149 +82,149 @@ function parseOptionalString(raw) {
76
82
  function parseBoolean(raw) {
77
83
  try {
78
84
  const parsed = JSON.parse(raw);
79
- return typeof parsed === 'boolean' ? parsed : null;
85
+ return typeof parsed === "boolean" ? parsed : null;
80
86
  }
81
87
  catch {
82
88
  return null;
83
89
  }
84
90
  }
85
91
  export function sanitizeFormatEnvelopeWithNative(candidate) {
86
- const capability = 'sanitizeFormatEnvelopeJson';
92
+ const capability = "sanitizeFormatEnvelopeJson";
87
93
  const fail = (reason) => failNativeRequired(capability, reason);
88
94
  if (isNativeDisabledByEnv()) {
89
- return fail('native disabled');
95
+ return fail("native disabled");
90
96
  }
91
- const fn = readNativeFunction('sanitizeFormatEnvelopeJson');
97
+ const fn = readNativeFunction("sanitizeFormatEnvelopeJson");
92
98
  if (!fn) {
93
99
  return fail();
94
100
  }
95
101
  const candidateJson = safeStringify(candidate);
96
102
  if (!candidateJson) {
97
- return fail('json stringify failed');
103
+ return fail("json stringify failed");
98
104
  }
99
105
  try {
100
106
  const raw = fn(candidateJson);
101
- if (typeof raw !== 'string' || !raw) {
102
- return fail('empty result');
107
+ if (typeof raw !== "string" || !raw) {
108
+ return fail("empty result");
103
109
  }
104
110
  const parsed = parseRecord(raw);
105
- return parsed ?? fail('invalid payload');
111
+ return parsed ?? fail("invalid payload");
106
112
  }
107
113
  catch (error) {
108
- const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
114
+ const reason = error instanceof Error ? error.message : String(error ?? "unknown");
109
115
  return fail(reason);
110
116
  }
111
117
  }
112
118
  export function sanitizeChatCompletionLikeWithNative(candidate) {
113
- const capability = 'sanitizeChatCompletionLikeJson';
119
+ const capability = "sanitizeChatCompletionLikeJson";
114
120
  const fail = (reason) => failNativeRequired(capability, reason);
115
121
  if (isNativeDisabledByEnv()) {
116
- return fail('native disabled');
122
+ return fail("native disabled");
117
123
  }
118
- const fn = readNativeFunction('sanitizeChatCompletionLikeJson');
124
+ const fn = readNativeFunction("sanitizeChatCompletionLikeJson");
119
125
  if (!fn) {
120
126
  return fail();
121
127
  }
122
128
  const candidateJson = safeStringify(candidate);
123
129
  if (!candidateJson) {
124
- return fail('json stringify failed');
130
+ return fail("json stringify failed");
125
131
  }
126
132
  try {
127
133
  const raw = fn(candidateJson);
128
- if (typeof raw !== 'string' || !raw) {
129
- return fail('empty result');
134
+ if (typeof raw !== "string" || !raw) {
135
+ return fail("empty result");
130
136
  }
131
137
  const parsed = parseRecord(raw);
132
- return parsed ?? fail('invalid payload');
138
+ return parsed ?? fail("invalid payload");
133
139
  }
134
140
  catch (error) {
135
- const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
141
+ const reason = error instanceof Error ? error.message : String(error ?? "unknown");
136
142
  return fail(reason);
137
143
  }
138
144
  }
139
145
  export function stripPrivateFieldsWithNative(payload) {
140
- const capability = 'stripPrivateFieldsJson';
146
+ const capability = "stripPrivateFieldsJson";
141
147
  const fail = (reason) => failNativeRequired(capability, reason);
142
148
  if (isNativeDisabledByEnv()) {
143
- return fail('native disabled');
149
+ return fail("native disabled");
144
150
  }
145
- const fn = readNativeFunction('stripPrivateFieldsJson');
151
+ const fn = readNativeFunction("stripPrivateFieldsJson");
146
152
  if (!fn) {
147
153
  return fail();
148
154
  }
149
155
  const payloadJson = safeStringify(payload);
150
156
  if (!payloadJson) {
151
- return fail('json stringify failed');
157
+ return fail("json stringify failed");
152
158
  }
153
159
  try {
154
160
  const raw = fn(payloadJson);
155
- if (typeof raw !== 'string' || !raw) {
156
- return fail('empty result');
161
+ if (typeof raw !== "string" || !raw) {
162
+ return fail("empty result");
157
163
  }
158
164
  const parsed = parseRecord(raw);
159
- return parsed ?? fail('invalid payload');
165
+ return parsed ?? fail("invalid payload");
160
166
  }
161
167
  catch (error) {
162
- const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
168
+ const reason = error instanceof Error ? error.message : String(error ?? "unknown");
163
169
  return fail(reason);
164
170
  }
165
171
  }
166
172
  export function resolveCompatProfileWithNative(adapterContext, explicitProfile) {
167
- const capability = 'resolveCompatProfileJson';
173
+ const capability = "resolveCompatProfileJson";
168
174
  const fail = (reason) => failNativeRequired(capability, reason);
169
175
  if (isNativeDisabledByEnv()) {
170
- return fail('native disabled');
176
+ return fail("native disabled");
171
177
  }
172
- const fn = readNativeFunction('resolveCompatProfileJson');
178
+ const fn = readNativeFunction("resolveCompatProfileJson");
173
179
  if (!fn) {
174
180
  return fail();
175
181
  }
176
182
  const adapterContextJson = safeStringify(adapterContext);
177
183
  const explicitJson = safeStringify(explicitProfile ?? null);
178
184
  if (!adapterContextJson || !explicitJson) {
179
- return fail('json stringify failed');
185
+ return fail("json stringify failed");
180
186
  }
181
187
  try {
182
188
  const raw = fn(adapterContextJson, explicitJson);
183
- if (typeof raw !== 'string' || !raw) {
184
- return fail('empty result');
189
+ if (typeof raw !== "string" || !raw) {
190
+ return fail("empty result");
185
191
  }
186
192
  const parsed = parseOptionalString(raw);
187
- return parsed === null ? fail('invalid payload') : parsed;
193
+ return parsed === null ? fail("invalid payload") : parsed;
188
194
  }
189
195
  catch (error) {
190
- const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
196
+ const reason = error instanceof Error ? error.message : String(error ?? "unknown");
191
197
  return fail(reason);
192
198
  }
193
199
  }
194
200
  export function resolveSseStreamModeWithNative(wantsStream, clientProtocol) {
195
- const capability = 'resolveSseStreamModeJson';
201
+ const capability = "resolveSseStreamModeJson";
196
202
  const fail = (reason) => failNativeRequired(capability, reason);
197
203
  if (isNativeDisabledByEnv()) {
198
- return fail('native disabled');
204
+ return fail("native disabled");
199
205
  }
200
- const fn = readNativeFunction('resolveSseStreamModeJson');
206
+ const fn = readNativeFunction("resolveSseStreamModeJson");
201
207
  if (!fn) {
202
208
  return fail();
203
209
  }
204
210
  try {
205
- const raw = fn(Boolean(wantsStream), String(clientProtocol || ''));
206
- if (typeof raw !== 'string' || !raw) {
207
- return fail('empty result');
211
+ const raw = fn(Boolean(wantsStream), String(clientProtocol || ""));
212
+ if (typeof raw !== "string" || !raw) {
213
+ return fail("empty result");
208
214
  }
209
215
  const parsed = parseBoolean(raw);
210
- return parsed === null ? fail('invalid payload') : parsed;
216
+ return parsed === null ? fail("invalid payload") : parsed;
211
217
  }
212
218
  catch (error) {
213
- const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
219
+ const reason = error instanceof Error ? error.message : String(error ?? "unknown");
214
220
  return fail(reason);
215
221
  }
216
222
  }
217
223
  export function parseReqInboundFormatEnvelopeWithNative(input) {
218
- const capability = 'parseFormatEnvelopeJson';
224
+ const capability = "parseFormatEnvelopeJson";
219
225
  const fail = (reason) => failNativeRequired(capability, reason);
220
226
  if (isNativeDisabledByEnv()) {
221
- return fail('native disabled');
227
+ return fail("native disabled");
222
228
  }
223
229
  const fn = readNativeFunction(capability);
224
230
  if (!fn) {
@@ -226,26 +232,33 @@ export function parseReqInboundFormatEnvelopeWithNative(input) {
226
232
  }
227
233
  const inputJson = safeStringify(input);
228
234
  if (!inputJson) {
229
- return fail('json stringify failed');
235
+ return fail("json stringify failed");
230
236
  }
231
237
  try {
232
238
  const raw = fn(inputJson);
233
- if (typeof raw !== 'string' || !raw) {
234
- return fail('empty result');
239
+ if (typeof raw !== "string" || !raw) {
240
+ return fail("empty result");
235
241
  }
236
- const parsed = parseFormatEnvelopePayload(raw, 'request', input.protocol, input.rawRequest);
237
- return parsed ?? fail('invalid payload');
242
+ const parsed = JSON.parse(raw);
243
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
244
+ return fail("invalid envelope structure");
245
+ }
246
+ const result = parsed;
247
+ if (!result.envelope || typeof result.envelope !== "object") {
248
+ return fail("missing envelope in result");
249
+ }
250
+ return result.envelope;
238
251
  }
239
252
  catch (error) {
240
- const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
253
+ const reason = error instanceof Error ? error.message : String(error ?? "unknown");
241
254
  return fail(reason);
242
255
  }
243
256
  }
244
257
  export function parseRespInboundFormatEnvelopeWithNative(input) {
245
- const capability = 'parseRespFormatEnvelopeJson';
258
+ const capability = "parseRespFormatEnvelopeJson";
246
259
  const fail = (reason) => failNativeRequired(capability, reason);
247
260
  if (isNativeDisabledByEnv()) {
248
- return fail('native disabled');
261
+ return fail("native disabled");
249
262
  }
250
263
  const fn = readNativeFunction(capability);
251
264
  if (!fn) {
@@ -253,26 +266,26 @@ export function parseRespInboundFormatEnvelopeWithNative(input) {
253
266
  }
254
267
  const inputJson = safeStringify(input);
255
268
  if (!inputJson) {
256
- return fail('json stringify failed');
269
+ return fail("json stringify failed");
257
270
  }
258
271
  try {
259
272
  const raw = fn(inputJson);
260
- if (typeof raw !== 'string' || !raw) {
261
- return fail('empty result');
273
+ if (typeof raw !== "string" || !raw) {
274
+ return fail("empty result");
262
275
  }
263
- const parsed = parseFormatEnvelopePayload(raw, 'response', input.protocol, input.payload);
264
- return parsed ?? fail('invalid payload');
276
+ const parsed = parseFormatEnvelopePayload(raw, "response", input.protocol, input.payload);
277
+ return parsed ?? fail("invalid payload");
265
278
  }
266
279
  catch (error) {
267
- const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
280
+ const reason = error instanceof Error ? error.message : String(error ?? "unknown");
268
281
  return fail(reason);
269
282
  }
270
283
  }
271
284
  export function validateChatEnvelopeWithNative(chatEnvelope, options) {
272
- const capability = 'validateChatEnvelopeJson';
285
+ const capability = "validateChatEnvelopeJson";
273
286
  const fail = (reason) => failNativeRequired(capability, reason);
274
287
  if (isNativeDisabledByEnv()) {
275
- return fail('native disabled');
288
+ return fail("native disabled");
276
289
  }
277
290
  const fn = readNativeFunction(capability);
278
291
  if (!fn) {
@@ -280,35 +293,38 @@ export function validateChatEnvelopeWithNative(chatEnvelope, options) {
280
293
  }
281
294
  const envelopeJson = safeStringify(chatEnvelope);
282
295
  if (!envelopeJson) {
283
- return fail('json stringify failed');
296
+ return fail("json stringify failed");
284
297
  }
285
- const isChatEnvelopeValidationError = (message) => typeof message === 'string' && message.includes('ChatEnvelopeValidationError(');
298
+ const isChatEnvelopeValidationError = (message) => typeof message === "string" &&
299
+ message.includes("ChatEnvelopeValidationError(");
286
300
  try {
287
- const raw = fn(envelopeJson, String(options.stage || ''), String(options.direction || ''), options.source);
301
+ const raw = fn(envelopeJson, String(options.stage || ""), String(options.direction || ""), options.source);
288
302
  const nativeErrorMessage = raw instanceof Error
289
303
  ? raw.message
290
- : raw && typeof raw === 'object' && 'message' in raw
304
+ : raw &&
305
+ typeof raw === "object" &&
306
+ "message" in raw
291
307
  ? (() => {
292
308
  const candidate = raw.message;
293
- return typeof candidate === 'string' ? candidate : '';
309
+ return typeof candidate === "string" ? candidate : "";
294
310
  })()
295
- : '';
311
+ : "";
296
312
  if (nativeErrorMessage) {
297
313
  if (isChatEnvelopeValidationError(nativeErrorMessage)) {
298
314
  throw new Error(nativeErrorMessage);
299
315
  }
300
316
  return fail(nativeErrorMessage);
301
317
  }
302
- if (typeof raw !== 'string' || !raw) {
303
- return fail('empty result');
318
+ if (typeof raw !== "string" || !raw) {
319
+ return fail("empty result");
304
320
  }
305
321
  const parsed = parseBoolean(raw);
306
322
  if (parsed !== true) {
307
- return fail('invalid payload');
323
+ return fail("invalid payload");
308
324
  }
309
325
  }
310
326
  catch (error) {
311
- const reason = error instanceof Error ? error.message : String(error ?? 'unknown');
327
+ const reason = error instanceof Error ? error.message : String(error ?? "unknown");
312
328
  if (isChatEnvelopeValidationError(reason)) {
313
329
  throw error instanceof Error ? error : new Error(reason);
314
330
  }
@@ -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>;
@@ -6,6 +6,7 @@ import { ProviderRegistry } from './provider-registry.js';
6
6
  import { resolveStopMessageScope } from './engine/routing-state/store.js';
7
7
  import { loadRoutingInstructionStateSync } from './sticky-session-store.js';
8
8
  import { mergeStopMessageFromPersisted } from './stop-message-state-sync.js';
9
+ import { resolveSessionColor } from './engine-logging.js';
9
10
  export class VirtualRouterEngine {
10
11
  nativeProxy;
11
12
  registry;
@@ -72,6 +73,7 @@ export class VirtualRouterEngine {
72
73
  parseLog?.scopedTypes.some((type) => type === 'stopMessageSet' || type === 'stopMessageMode' || type === 'stopMessageClear'));
73
74
  emitVirtualRouterHitLog(parsed, {
74
75
  requestId: metadata.requestId,
76
+ sessionId: resolveVirtualRouterLogSessionId(metadata),
75
77
  stopScope,
76
78
  stopState,
77
79
  forceStopStatusLabel
@@ -176,6 +178,12 @@ function extractNativeErrorMessage(error) {
176
178
  if (error instanceof Error) {
177
179
  return error.message;
178
180
  }
181
+ if (error && typeof error === 'object') {
182
+ const message = error.message;
183
+ if (typeof message === 'string') {
184
+ return message;
185
+ }
186
+ }
179
187
  return '';
180
188
  }
181
189
  function parseVirtualRouterErrorMessage(message) {
@@ -225,6 +233,11 @@ function buildRoutingInstructionParseLog(request, metadata) {
225
233
  }
226
234
  const latest = getLatestUserMessage(messages);
227
235
  const latestText = latest ? extractMessageText(latest).trim() : '';
236
+ const latestHasMarker = /<\*\*[\s\S]*?\*\*>/.test(latestText);
237
+ const hasStopKeyword = /stopmessage/i.test(latestText);
238
+ if (!hasStopKeyword && !latestHasMarker) {
239
+ return null;
240
+ }
228
241
  const parsedKinds = parseRoutingInstructionKindsWithNative(request);
229
242
  const stopMessageTypes = parsedKinds.filter((type) => type === 'stopMessageSet' || type === 'stopMessageMode' || type === 'stopMessageClear');
230
243
  const scopedTypes = parsedKinds.filter((type) => type === 'stopMessageSet' ||
@@ -232,20 +245,12 @@ function buildRoutingInstructionParseLog(request, metadata) {
232
245
  type === 'stopMessageClear' ||
233
246
  type === 'preCommandSet' ||
234
247
  type === 'preCommandClear');
235
- const markerDetected = messages.some((message) => {
236
- if (!message || typeof message !== 'object') {
237
- return false;
238
- }
239
- const record = message;
240
- return record.role === 'user' && typeof record.content === 'string' && /<\*\*[\s\S]*?\*\*>/.test(record.content);
241
- });
242
- const hasStopKeyword = /stopmessage/i.test(latestText);
243
248
  if (!hasStopKeyword && stopMessageTypes.length === 0 && scopedTypes.length === 0) {
244
249
  return null;
245
250
  }
246
251
  return {
247
252
  requestId: metadata.requestId || 'n/a',
248
- markerDetected,
253
+ markerDetected: latestHasMarker,
249
254
  preview: latestText.replace(/\s+/g, ' ').slice(0, 120),
250
255
  stopMessageTypes,
251
256
  scopedTypes,
@@ -274,30 +279,37 @@ function emitVirtualRouterHitLog(result, options) {
274
279
  const prefixColor = '\x1b[38;5;208m';
275
280
  const timeColor = '\x1b[90m';
276
281
  const stopColor = '\x1b[38;5;214m';
277
- const routeColorMap = {
278
- multimodal: '\x1b[38;5;45m',
279
- tools: '\x1b[38;5;214m',
280
- thinking: '\x1b[34m',
281
- coding: '\x1b[35m',
282
- longcontext: '\x1b[38;5;141m',
283
- web_search: '\x1b[32m',
284
- search: '\x1b[38;5;34m',
285
- vision: '\x1b[38;5;207m',
286
- background: '\x1b[90m'
287
- };
288
282
  const now = new Date();
289
283
  const timestamp = `${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`;
290
284
  const routeLabel = result.decision.poolId
291
285
  ? `${result.decision.routeName}/${result.decision.poolId}`
292
286
  : result.decision.routeName;
293
- const routeColor = routeColorMap[result.decision.routeName] ?? '\x1b[36m';
287
+ const routeColor = resolveSessionColor(options?.sessionId);
294
288
  const providerKey = result.decision.providerKey || result.target.providerKey;
295
289
  const modelSuffix = result.target.modelId ? `.${result.target.modelId}` : '';
296
290
  const reason = result.decision.reasoning ? ` reason=${result.decision.reasoning}` : '';
297
291
  const stopStatusLabel = formatStopMessageStatusLabel(options?.stopState ?? null, options?.stopScope, Boolean(options?.forceStopStatusLabel));
298
292
  const requestId = typeof options?.requestId === 'string' ? options.requestId : '';
299
293
  const requestLabel = requestId && !requestId.includes('unknown') ? ` req=${requestId}` : '';
300
- console.log(`${prefixColor}[virtual-router-hit]${reset} ${timeColor}${timestamp}${reset}${requestLabel} ${routeColor}${routeLabel} -> ${providerKey}${modelSuffix}${reason}${reset}${stopStatusLabel ? ` ${stopColor}${stopStatusLabel}${reset}` : ''}`);
294
+ const sessionId = typeof options?.sessionId === 'string' ? options.sessionId.trim() : '';
295
+ const sessionLabel = sessionId ? ` sid=${sessionId}` : '';
296
+ console.log(`${prefixColor}[virtual-router-hit]${reset} ${timeColor}${timestamp}${reset}${requestLabel}${sessionLabel} ${routeColor}${routeLabel} -> ${providerKey}${modelSuffix}${reason}${reset}${stopStatusLabel ? ` ${stopColor}${stopStatusLabel}${reset}` : ''}`);
297
+ }
298
+ function resolveVirtualRouterLogSessionId(metadata) {
299
+ const candidates = [
300
+ metadata.sessionId,
301
+ metadata.clientTmuxSessionId,
302
+ metadata.client_tmux_session_id,
303
+ metadata.tmuxSessionId,
304
+ metadata.tmux_session_id,
305
+ metadata.conversationId
306
+ ];
307
+ for (const value of candidates) {
308
+ if (typeof value === 'string' && value.trim()) {
309
+ return value.trim();
310
+ }
311
+ }
312
+ return undefined;
301
313
  }
302
314
  function formatStopMessageStatusLabel(snapshot, scope, forceShow) {
303
315
  const scopeLabel = scope && scope.trim() ? scope.trim() : 'none';
@@ -97,6 +97,7 @@ export class ProviderRegistry {
97
97
  providerType: profile.providerType,
98
98
  endpoint: profile.endpoint,
99
99
  auth: profile.auth,
100
+ ...(profile.enabled !== undefined ? { enabled: profile.enabled } : {}),
100
101
  outboundProfile: profile.outboundProfile,
101
102
  compatibilityProfile: profile.compatibilityProfile,
102
103
  runtimeKey: profile.runtimeKey,
@@ -27,7 +27,11 @@ export function applyRoutingInstructions(instructions, currentState) {
27
27
  : undefined,
28
28
  preCommandSource: currentState.preCommandSource,
29
29
  preCommandScriptPath: currentState.preCommandScriptPath,
30
- preCommandUpdatedAt: currentState.preCommandUpdatedAt
30
+ preCommandUpdatedAt: currentState.preCommandUpdatedAt,
31
+ chatProcessLastTotalTokens: currentState.chatProcessLastTotalTokens,
32
+ chatProcessLastInputTokens: currentState.chatProcessLastInputTokens,
33
+ chatProcessLastMessageCount: currentState.chatProcessLastMessageCount,
34
+ chatProcessLastUpdatedAt: currentState.chatProcessLastUpdatedAt
31
35
  };
32
36
  let allowReset = false;
33
37
  let disableReset = false;
@@ -186,7 +190,19 @@ export function serializeRoutingInstructionState(state) {
186
190
  models: Array.from(models)
187
191
  })),
188
192
  ...serializeStopMessageState(state),
189
- ...serializePreCommandState(state)
193
+ ...serializePreCommandState(state),
194
+ ...(typeof state.chatProcessLastTotalTokens === 'number'
195
+ ? { chatProcessLastTotalTokens: state.chatProcessLastTotalTokens }
196
+ : {}),
197
+ ...(typeof state.chatProcessLastInputTokens === 'number'
198
+ ? { chatProcessLastInputTokens: state.chatProcessLastInputTokens }
199
+ : {}),
200
+ ...(typeof state.chatProcessLastMessageCount === 'number'
201
+ ? { chatProcessLastMessageCount: state.chatProcessLastMessageCount }
202
+ : {}),
203
+ ...(typeof state.chatProcessLastUpdatedAt === 'number'
204
+ ? { chatProcessLastUpdatedAt: state.chatProcessLastUpdatedAt }
205
+ : {})
190
206
  };
191
207
  }
192
208
  export function deserializeRoutingInstructionState(data) {
@@ -208,7 +224,11 @@ export function deserializeRoutingInstructionState(data) {
208
224
  stopMessageAiHistory: undefined,
209
225
  preCommandSource: undefined,
210
226
  preCommandScriptPath: undefined,
211
- preCommandUpdatedAt: undefined
227
+ preCommandUpdatedAt: undefined,
228
+ chatProcessLastTotalTokens: undefined,
229
+ chatProcessLastInputTokens: undefined,
230
+ chatProcessLastMessageCount: undefined,
231
+ chatProcessLastUpdatedAt: undefined
212
232
  };
213
233
  if (data.forcedTarget && typeof data.forcedTarget === 'object') {
214
234
  state.forcedTarget = data.forcedTarget;
@@ -241,5 +261,17 @@ export function deserializeRoutingInstructionState(data) {
241
261
  }
242
262
  deserializeStopMessageState(data, state);
243
263
  deserializePreCommandState(data, state);
264
+ if (typeof data.chatProcessLastTotalTokens === 'number' && Number.isFinite(data.chatProcessLastTotalTokens)) {
265
+ state.chatProcessLastTotalTokens = Math.max(0, Math.round(data.chatProcessLastTotalTokens));
266
+ }
267
+ if (typeof data.chatProcessLastInputTokens === 'number' && Number.isFinite(data.chatProcessLastInputTokens)) {
268
+ state.chatProcessLastInputTokens = Math.max(0, Math.round(data.chatProcessLastInputTokens));
269
+ }
270
+ if (typeof data.chatProcessLastMessageCount === 'number' && Number.isFinite(data.chatProcessLastMessageCount)) {
271
+ state.chatProcessLastMessageCount = Math.max(0, Math.round(data.chatProcessLastMessageCount));
272
+ }
273
+ if (typeof data.chatProcessLastUpdatedAt === 'number' && Number.isFinite(data.chatProcessLastUpdatedAt)) {
274
+ state.chatProcessLastUpdatedAt = Math.max(0, Math.round(data.chatProcessLastUpdatedAt));
275
+ }
244
276
  return state;
245
277
  }
@@ -67,4 +67,8 @@ export interface RoutingInstructionState {
67
67
  preCommandSource?: string;
68
68
  preCommandScriptPath?: string;
69
69
  preCommandUpdatedAt?: number;
70
+ chatProcessLastTotalTokens?: number;
71
+ chatProcessLastInputTokens?: number;
72
+ chatProcessLastMessageCount?: number;
73
+ chatProcessLastUpdatedAt?: number;
70
74
  }
@@ -17,6 +17,11 @@ export interface RoutePoolLoadBalancingPolicy {
17
17
  * Optional pool-local weights. Keys may target runtime keys, provider.model groups, or provider ids.
18
18
  */
19
19
  weights?: Record<string, number>;
20
+ responsesResume?: {
21
+ previousRequestId?: string;
22
+ restoredFromResponseId?: string;
23
+ [key: string]: unknown;
24
+ };
20
25
  }
21
26
  export interface RoutePoolTier {
22
27
  id: string;
@@ -69,6 +74,7 @@ export interface ProviderProfile {
69
74
  providerType: string;
70
75
  endpoint: string;
71
76
  auth: ProviderAuthConfig;
77
+ enabled?: boolean;
72
78
  outboundProfile: string;
73
79
  compatibilityProfile?: string;
74
80
  runtimeKey?: string;
@@ -95,6 +101,7 @@ export interface ProviderRuntimeProfile {
95
101
  endpoint: string;
96
102
  headers?: Record<string, string>;
97
103
  auth: ProviderAuthConfig;
104
+ enabled?: boolean;
98
105
  outboundProfile: string;
99
106
  compatibilityProfile?: string;
100
107
  modelId?: string;