@jeffusion/bungee-core 5.18.0 → 5.20.0

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 (41) hide show
  1. package/dist/gateway/contracts.d.ts +31 -2
  2. package/dist/gateway/dispatch-plugin.d.ts +7 -0
  3. package/dist/gateway/dispatch-targets.d.ts +4 -0
  4. package/dist/gateway/plugin.js +2 -0
  5. package/dist/gateway/routing-plugin.d.ts +3 -1
  6. package/dist/hooks/plugin-hooks.d.ts +6 -1
  7. package/dist/main.js +182 -50
  8. package/dist/plugin-extensions.d.ts +2 -0
  9. package/dist/plugins/ai-transformer/index.js +11 -1
  10. package/dist/plugins/ai-transformer/index.js.map +6 -4
  11. package/dist/plugins/anthropic-request-sanitizer/index.js.map +1 -1
  12. package/dist/plugins/anthropic-tool-name-transformer/index.js.map +1 -1
  13. package/dist/plugins/chatgpt-oauth/control.js.map +1 -1
  14. package/dist/plugins/chatgpt-oauth/index.js.map +1 -1
  15. package/dist/plugins/codex-router/control.js +673 -2
  16. package/dist/plugins/codex-router/control.js.map +19 -4
  17. package/dist/plugins/codex-router/index.js +3938 -4
  18. package/dist/plugins/codex-router/index.js.map +24 -7
  19. package/dist/plugins/codex-router/manifest.json +15 -1
  20. package/dist/plugins/deepseek-reasoning-fix/index.js.map +1 -1
  21. package/dist/plugins/key-access/control.js.map +2 -2
  22. package/dist/plugins/key-access/index.js +14 -10
  23. package/dist/plugins/key-access/index.js.map +4 -4
  24. package/dist/plugins/key-access/ingress.js +14 -10
  25. package/dist/plugins/key-access/ingress.js.map +4 -4
  26. package/dist/plugins/key-rate-limit/index.js.map +1 -1
  27. package/dist/plugins/local-accounts/control.js.map +1 -1
  28. package/dist/plugins/local-accounts/index.js.map +1 -1
  29. package/dist/plugins/model-mapping/index.js.map +1 -1
  30. package/dist/plugins/models-dev/index.js.map +1 -1
  31. package/dist/plugins/openai-messages-to-chat/index.js +691 -543
  32. package/dist/plugins/openai-messages-to-chat/index.js.map +9 -5
  33. package/dist/plugins/signature-repair/index.js.map +1 -1
  34. package/dist/plugins/token-budget/control.js.map +1 -1
  35. package/dist/plugins/token-budget/index.js.map +1 -1
  36. package/dist/plugins/token-metering/index.js +652 -71
  37. package/dist/plugins/token-metering/index.js.map +6 -4
  38. package/dist/plugins/token-stats/control.js.map +1 -1
  39. package/dist/plugins/token-stats/index.js.map +1 -1
  40. package/dist/scoped-plugin-registry.d.ts +5 -2
  41. package/package.json +2 -2
@@ -163,12 +163,583 @@ class ProtocolTransformerRegistry {
163
163
  }
164
164
  }
165
165
  // packages/llms/src/providers/openai/protocol-conversion.ts
166
+ var THINKING_TAG_PATTERN = /<thinking>([\s\S]*?)<\/thinking>/gi;
166
167
  var TOOL_CALL_CONTENT_TYPES = new Set([
167
168
  "tool_use",
168
169
  "tool_call",
169
170
  "function_call",
170
171
  "output_tool_call"
171
172
  ]);
173
+ function isRecord(value) {
174
+ return typeof value === "object" && value !== null && !Array.isArray(value);
175
+ }
176
+ function asString(value, trimWhitespace) {
177
+ if (typeof value !== "string") {
178
+ return;
179
+ }
180
+ return trimWhitespace ? value.trim() : value;
181
+ }
182
+ function normalizePath(pathname) {
183
+ if (pathname.length > 1 && pathname.endsWith("/")) {
184
+ return pathname.slice(0, -1);
185
+ }
186
+ return pathname;
187
+ }
188
+ function isEnabledLike(value) {
189
+ if (value === true) {
190
+ return true;
191
+ }
192
+ if (typeof value === "string") {
193
+ const normalized = value.trim().toLowerCase();
194
+ return normalized === "enabled" || normalized === "enable" || normalized === "true" || normalized === "on" || normalized === "1";
195
+ }
196
+ if (!isRecord(value)) {
197
+ return false;
198
+ }
199
+ const type = typeof value.type === "string" ? value.type.trim().toLowerCase() : "";
200
+ if (type === "disabled" || type === "disable" || type === "off") {
201
+ return false;
202
+ }
203
+ if (value.enabled === false) {
204
+ return false;
205
+ }
206
+ if (value.enabled === true) {
207
+ return true;
208
+ }
209
+ if (type === "enabled" || type === "enable") {
210
+ return true;
211
+ }
212
+ return Object.keys(value).length > 0;
213
+ }
214
+ function isToolCallContentBlock(item) {
215
+ const itemType = typeof item.type === "string" ? item.type.trim().toLowerCase() : "";
216
+ if (TOOL_CALL_CONTENT_TYPES.has(itemType) || itemType.endsWith("_call")) {
217
+ return true;
218
+ }
219
+ const hasCallIdentifier = typeof item.id === "string" || typeof item.call_id === "string" || typeof item.name === "string";
220
+ const hasCallPayload = item.input !== undefined || item.arguments !== undefined || item.function !== undefined;
221
+ return hasCallIdentifier && hasCallPayload;
222
+ }
223
+ function hasToolCalls(value) {
224
+ if (Array.isArray(value)) {
225
+ return value.length > 0;
226
+ }
227
+ if (isRecord(value)) {
228
+ return Object.keys(value).length > 0;
229
+ }
230
+ if (typeof value !== "string") {
231
+ return false;
232
+ }
233
+ const trimmed = value.trim();
234
+ if (trimmed.length === 0) {
235
+ return false;
236
+ }
237
+ try {
238
+ const parsed = JSON.parse(trimmed);
239
+ if (Array.isArray(parsed)) {
240
+ return parsed.length > 0;
241
+ }
242
+ return isRecord(parsed);
243
+ } catch {
244
+ return true;
245
+ }
246
+ }
247
+ function hasToolCallLikeContent(content) {
248
+ if (!Array.isArray(content)) {
249
+ return false;
250
+ }
251
+ for (const item of content) {
252
+ if (!isRecord(item)) {
253
+ continue;
254
+ }
255
+ if (isToolCallContentBlock(item)) {
256
+ return true;
257
+ }
258
+ }
259
+ return false;
260
+ }
261
+ function isAssistantToolCallMessage(message) {
262
+ if (message.role !== "assistant") {
263
+ return false;
264
+ }
265
+ return hasToolCalls(message.tool_calls) || hasToolCallLikeContent(message.content);
266
+ }
267
+ function extractThinkingTagContent(content, trimWhitespace) {
268
+ THINKING_TAG_PATTERN.lastIndex = 0;
269
+ const extracted = [];
270
+ let matched = THINKING_TAG_PATTERN.exec(content);
271
+ while (matched !== null) {
272
+ const block = asString(matched[1], trimWhitespace);
273
+ if (block) {
274
+ extracted.push(block);
275
+ }
276
+ matched = THINKING_TAG_PATTERN.exec(content);
277
+ }
278
+ if (extracted.length === 0) {
279
+ return "";
280
+ }
281
+ return extracted.join(`
282
+
283
+ `);
284
+ }
285
+ function extractReasoningFromArrayContent(content, trimWhitespace) {
286
+ const reasoningTexts = [];
287
+ for (const item of content) {
288
+ if (!isRecord(item)) {
289
+ continue;
290
+ }
291
+ const type = typeof item.type === "string" ? item.type : "";
292
+ if (type !== "reasoning" && type !== "thinking" && type !== "reasoning_content") {
293
+ continue;
294
+ }
295
+ const candidates = [
296
+ item.text,
297
+ item.content,
298
+ item.reasoning,
299
+ item.thinking
300
+ ];
301
+ for (const candidate of candidates) {
302
+ const text = asString(candidate, trimWhitespace);
303
+ if (text && text.length > 0) {
304
+ reasoningTexts.push(text);
305
+ break;
306
+ }
307
+ }
308
+ }
309
+ if (reasoningTexts.length === 0) {
310
+ return "";
311
+ }
312
+ return reasoningTexts.join(`
313
+
314
+ `);
315
+ }
316
+ function extractReasoningContent(content, trimWhitespace) {
317
+ if (typeof content === "string") {
318
+ return extractThinkingTagContent(content, trimWhitespace);
319
+ }
320
+ if (Array.isArray(content)) {
321
+ return extractReasoningFromArrayContent(content, trimWhitespace);
322
+ }
323
+ return "";
324
+ }
325
+ function normalizeAnthropicUsage(usage) {
326
+ if (!isRecord(usage)) {
327
+ return {
328
+ input_tokens: 0,
329
+ output_tokens: 0
330
+ };
331
+ }
332
+ return {
333
+ input_tokens: typeof usage.input_tokens === "number" ? usage.input_tokens : 0,
334
+ output_tokens: typeof usage.output_tokens === "number" ? usage.output_tokens : 0
335
+ };
336
+ }
337
+ function normalizeAssistantToolCallMessage(message, trimWhitespace) {
338
+ if (typeof message.reasoning_content === "string") {
339
+ const normalized = trimWhitespace ? message.reasoning_content.trim() : message.reasoning_content;
340
+ if (normalized === message.reasoning_content) {
341
+ return message;
342
+ }
343
+ return {
344
+ ...message,
345
+ reasoning_content: normalized
346
+ };
347
+ }
348
+ return {
349
+ ...message,
350
+ reasoning_content: extractReasoningContent(message.content, trimWhitespace)
351
+ };
352
+ }
353
+ function convertChatUserContentToResponsesContent(content) {
354
+ if (typeof content === "string") {
355
+ const text = content.trim();
356
+ return text ? [{ type: "input_text", text }] : [{ type: "input_text", text: "" }];
357
+ }
358
+ if (!Array.isArray(content)) {
359
+ return [{ type: "input_text", text: "" }];
360
+ }
361
+ const converted = [];
362
+ for (const part of content) {
363
+ if (typeof part === "string") {
364
+ const text = part.trim();
365
+ if (text) {
366
+ converted.push({ type: "input_text", text });
367
+ }
368
+ continue;
369
+ }
370
+ if (!isRecord(part)) {
371
+ continue;
372
+ }
373
+ if (part.type === "text" && typeof part.text === "string") {
374
+ converted.push({ type: "input_text", text: part.text });
375
+ continue;
376
+ }
377
+ if (part.type === "image_url" && isRecord(part.image_url) && typeof part.image_url.url === "string") {
378
+ converted.push({ type: "input_image", image_url: part.image_url.url });
379
+ }
380
+ }
381
+ return converted.length > 0 ? converted : [{ type: "input_text", text: "" }];
382
+ }
383
+
384
+ class OpenAIProtocolConversion {
385
+ trimWhitespace;
386
+ constructor(options) {
387
+ this.trimWhitespace = options?.trimWhitespace !== false;
388
+ }
389
+ isResponsesPath(pathname) {
390
+ const normalizedPath = normalizePath(pathname);
391
+ return normalizedPath === "/v1/responses" || normalizedPath === "/responses";
392
+ }
393
+ isReasoningContext(body) {
394
+ if (body.reasoning !== undefined && body.reasoning !== null) {
395
+ return true;
396
+ }
397
+ if (typeof body.reasoning_effort === "string" && body.reasoning_effort.trim().length > 0) {
398
+ return true;
399
+ }
400
+ if (isEnabledLike(body.enable_thinking)) {
401
+ return true;
402
+ }
403
+ return isEnabledLike(body.thinking);
404
+ }
405
+ normalizeResponsesReasoningBody(body) {
406
+ let changed = false;
407
+ let normalizedBody = body;
408
+ for (const key of ["input", "messages"]) {
409
+ const normalizedCollection = this.normalizeMessageCollection(normalizedBody, key);
410
+ if (normalizedCollection.changed) {
411
+ normalizedBody = normalizedCollection.body;
412
+ changed = true;
413
+ }
414
+ }
415
+ if (!changed) {
416
+ return body;
417
+ }
418
+ return normalizedBody;
419
+ }
420
+ ensureAssistantToolUseReasoningContent(body) {
421
+ if (!isRecord(body) || body.type !== "message" || body.role !== "assistant" || !Array.isArray(body.content)) {
422
+ return body;
423
+ }
424
+ if (!body.content.some((block) => isRecord(block) && block.type === "tool_use") || typeof body.reasoning_content === "string") {
425
+ return body;
426
+ }
427
+ return {
428
+ ...body,
429
+ reasoning_content: this.extractThinkingTextFromAnthropicContent(body.content)
430
+ };
431
+ }
432
+ ensureMessagesStreamCompatibility(events, ctx) {
433
+ const withUsage = this.ensureMessageDeltaUsage(events, ctx);
434
+ return this.ensureMessageStartReasoningContent(withUsage);
435
+ }
436
+ convertChatMessagesToResponsesInput(messages) {
437
+ if (!Array.isArray(messages)) {
438
+ return { input: [] };
439
+ }
440
+ const input = [];
441
+ const instructionParts = [];
442
+ for (const msg of messages) {
443
+ if (!isRecord(msg)) {
444
+ continue;
445
+ }
446
+ if (msg.role === "system") {
447
+ const text = typeof msg.content === "string" ? msg.content.trim() : "";
448
+ if (text)
449
+ instructionParts.push(text);
450
+ continue;
451
+ }
452
+ if (msg.role === "user") {
453
+ input.push({
454
+ role: "user",
455
+ content: convertChatUserContentToResponsesContent(msg.content)
456
+ });
457
+ continue;
458
+ }
459
+ if (msg.role === "assistant") {
460
+ const assistantText = typeof msg.content === "string" ? msg.content.trim() : "";
461
+ if (assistantText) {
462
+ input.push({
463
+ role: "assistant",
464
+ content: [{ type: "output_text", text: assistantText }]
465
+ });
466
+ }
467
+ if (Array.isArray(msg.tool_calls)) {
468
+ for (const toolCall of msg.tool_calls) {
469
+ if (!isRecord(toolCall)) {
470
+ continue;
471
+ }
472
+ const callId = typeof toolCall.id === "string" ? toolCall.id : "";
473
+ const functionObject = isRecord(toolCall.function) ? toolCall.function : undefined;
474
+ if (!functionObject) {
475
+ continue;
476
+ }
477
+ const functionName = typeof functionObject?.name === "string" ? functionObject.name : "";
478
+ if (!callId || !functionName) {
479
+ continue;
480
+ }
481
+ input.push({
482
+ type: "function_call",
483
+ call_id: callId,
484
+ name: functionName,
485
+ arguments: functionObject.arguments || "{}"
486
+ });
487
+ }
488
+ }
489
+ continue;
490
+ }
491
+ if (msg.role === "tool") {
492
+ const callId = typeof msg.tool_call_id === "string" ? msg.tool_call_id : "";
493
+ if (!callId) {
494
+ continue;
495
+ }
496
+ input.push({
497
+ type: "function_call_output",
498
+ call_id: callId,
499
+ output: msg.content ?? ""
500
+ });
501
+ }
502
+ }
503
+ const instructions = instructionParts.length > 0 ? instructionParts.join(`
504
+ `) : undefined;
505
+ return { input, instructions };
506
+ }
507
+ mapChatToolsToResponsesTools(chatTools) {
508
+ if (!Array.isArray(chatTools)) {
509
+ return [];
510
+ }
511
+ const mapped = [];
512
+ for (const tool of chatTools) {
513
+ if (!isRecord(tool) || tool.type !== "function" || !isRecord(tool.function)) {
514
+ continue;
515
+ }
516
+ const name = typeof tool.function.name === "string" ? tool.function.name : "";
517
+ if (!name) {
518
+ continue;
519
+ }
520
+ const parameters = isRecord(tool.function.parameters) ? tool.function.parameters : { type: "object", properties: {} };
521
+ mapped.push({
522
+ type: "function",
523
+ name,
524
+ description: typeof tool.function.description === "string" ? tool.function.description : "",
525
+ parameters
526
+ });
527
+ }
528
+ return mapped;
529
+ }
530
+ convertResponsesInputToMessages(input) {
531
+ if (typeof input === "string") {
532
+ const text = input.trim();
533
+ return text ? [{ role: "user", content: text }] : [];
534
+ }
535
+ if (!Array.isArray(input)) {
536
+ return [];
537
+ }
538
+ const messages = [];
539
+ const pendingTopLevelInputParts = [];
540
+ const flushPendingTopLevelInputParts = () => {
541
+ if (pendingTopLevelInputParts.length === 0) {
542
+ return;
543
+ }
544
+ messages.push({
545
+ role: "user",
546
+ content: this.normalizeResponsesMessageContent([...pendingTopLevelInputParts])
547
+ });
548
+ pendingTopLevelInputParts.length = 0;
549
+ };
550
+ for (const item of input) {
551
+ if (typeof item === "string") {
552
+ if (item.trim()) {
553
+ pendingTopLevelInputParts.push({ type: "input_text", text: item });
554
+ }
555
+ continue;
556
+ }
557
+ if (!isRecord(item)) {
558
+ continue;
559
+ }
560
+ const itemType = item.type;
561
+ if (itemType === "input_text" || itemType === "output_text" || itemType === "input_image" || itemType === "text" || itemType === "image_url") {
562
+ pendingTopLevelInputParts.push(item);
563
+ continue;
564
+ }
565
+ if (itemType === "function_call") {
566
+ flushPendingTopLevelInputParts();
567
+ const rawArgs = item.arguments;
568
+ const argumentsString = typeof rawArgs === "string" ? rawArgs : JSON.stringify(rawArgs || {});
569
+ messages.push({
570
+ role: "assistant",
571
+ content: null,
572
+ tool_calls: [{
573
+ id: item.call_id || item.id || "",
574
+ type: "function",
575
+ function: {
576
+ name: item.name || "",
577
+ arguments: argumentsString
578
+ }
579
+ }]
580
+ });
581
+ continue;
582
+ }
583
+ if (itemType === "function_call_output") {
584
+ flushPendingTopLevelInputParts();
585
+ messages.push({
586
+ role: "tool",
587
+ tool_call_id: item.call_id || "",
588
+ content: item.output ?? "",
589
+ is_error: item.is_error === true || item.status === "error" || item.status === "failed"
590
+ });
591
+ continue;
592
+ }
593
+ if (itemType === "message") {
594
+ flushPendingTopLevelInputParts();
595
+ const role = item.role || "user";
596
+ if (typeof role === "string") {
597
+ messages.push({
598
+ role,
599
+ content: this.normalizeResponsesMessageContent(item.content)
600
+ });
601
+ }
602
+ continue;
603
+ }
604
+ if (typeof item.role === "string") {
605
+ flushPendingTopLevelInputParts();
606
+ messages.push({
607
+ role: item.role,
608
+ content: this.normalizeResponsesMessageContent(item.content)
609
+ });
610
+ }
611
+ }
612
+ flushPendingTopLevelInputParts();
613
+ return messages;
614
+ }
615
+ normalizeResponsesMessageContent(content) {
616
+ if (typeof content === "string") {
617
+ return content;
618
+ }
619
+ if (!Array.isArray(content)) {
620
+ return content;
621
+ }
622
+ const converted = content.map((part) => {
623
+ if (typeof part === "string") {
624
+ return { type: "text", text: part };
625
+ }
626
+ if (!isRecord(part)) {
627
+ return null;
628
+ }
629
+ if (part.type === "input_text" || part.type === "output_text") {
630
+ return { type: "text", text: part.text || "" };
631
+ }
632
+ if (part.type === "input_image") {
633
+ const imageUrl = typeof part.image_url === "string" ? part.image_url : isRecord(part.image_url) ? part.image_url.url : undefined;
634
+ if (typeof imageUrl === "string" && imageUrl) {
635
+ return {
636
+ type: "image_url",
637
+ image_url: { url: imageUrl }
638
+ };
639
+ }
640
+ }
641
+ return part;
642
+ }).filter((part) => part !== null);
643
+ return converted;
644
+ }
645
+ normalizeMessageCollection(body, key) {
646
+ const collection = body[key];
647
+ if (!Array.isArray(collection)) {
648
+ return { body, changed: false };
649
+ }
650
+ let changed = false;
651
+ const normalizedCollection = collection.map((item) => {
652
+ const normalizedItem = this.normalizeAssistantToolCallCandidate(item);
653
+ if (normalizedItem.changed) {
654
+ changed = true;
655
+ }
656
+ return normalizedItem.normalized;
657
+ });
658
+ if (!changed) {
659
+ return { body, changed: false };
660
+ }
661
+ return {
662
+ body: {
663
+ ...body,
664
+ [key]: normalizedCollection
665
+ },
666
+ changed: true
667
+ };
668
+ }
669
+ normalizeAssistantToolCallCandidate(value) {
670
+ if (!isRecord(value)) {
671
+ return { normalized: value, changed: false };
672
+ }
673
+ let changed = false;
674
+ let current = value;
675
+ if (isRecord(current.message)) {
676
+ const nested = this.normalizeAssistantToolCallCandidate(current.message);
677
+ if (nested.changed) {
678
+ current = {
679
+ ...current,
680
+ message: nested.normalized
681
+ };
682
+ changed = true;
683
+ }
684
+ }
685
+ if (!isAssistantToolCallMessage(current)) {
686
+ return { normalized: current, changed };
687
+ }
688
+ const normalizedMessage = normalizeAssistantToolCallMessage(current, this.trimWhitespace);
689
+ if (normalizedMessage !== current) {
690
+ current = normalizedMessage;
691
+ changed = true;
692
+ }
693
+ return { normalized: current, changed };
694
+ }
695
+ extractThinkingTextFromAnthropicContent(content) {
696
+ const segments = [];
697
+ for (const block of content) {
698
+ if (!isRecord(block) || block.type !== "thinking") {
699
+ continue;
700
+ }
701
+ if (typeof block.thinking === "string" && block.thinking.trim().length > 0) {
702
+ segments.push(block.thinking.trim());
703
+ }
704
+ }
705
+ return segments.join(`
706
+
707
+ `);
708
+ }
709
+ ensureMessageStartReasoningContent(events) {
710
+ return events.map((event) => {
711
+ if (!isRecord(event) || event.type !== "message_start" || !isRecord(event.message)) {
712
+ return event;
713
+ }
714
+ const existingReasoningContent = event.message.reasoning_content;
715
+ if (typeof existingReasoningContent === "string") {
716
+ return event;
717
+ }
718
+ return {
719
+ ...event,
720
+ message: {
721
+ ...event.message,
722
+ reasoning_content: ""
723
+ }
724
+ };
725
+ });
726
+ }
727
+ ensureMessageDeltaUsage(events, ctx) {
728
+ const lastUsageKey = "messages_compat_last_usage";
729
+ const cachedUsage = normalizeAnthropicUsage(ctx.streamState.get(lastUsageKey));
730
+ return events.map((event) => {
731
+ if (!isRecord(event) || event.type !== "message_delta") {
732
+ return event;
733
+ }
734
+ const normalizedUsage = normalizeAnthropicUsage(event.usage ?? cachedUsage);
735
+ ctx.streamState.set(lastUsageKey, normalizedUsage);
736
+ return {
737
+ ...event,
738
+ usage: normalizedUsage
739
+ };
740
+ });
741
+ }
742
+ }
172
743
  // packages/llms/src/providers/openai/messages-compat-normalization.ts
173
744
  var SUPPORTED_ROLES = new Set(["system", "developer", "user", "assistant", "tool"]);
174
745
  // packages/llms/src/token-accounting/types.ts
@@ -441,10 +1012,10 @@ var CANONICAL_EVENT_KEYS = new Set([
441
1012
  "outcome",
442
1013
  "countedAt"
443
1014
  ]);
444
- function isRecord(value) {
1015
+ function isRecord2(value) {
445
1016
  return typeof value === "object" && value !== null && !Array.isArray(value);
446
1017
  }
447
- function asString(value) {
1018
+ function asString2(value) {
448
1019
  return typeof value === "string" && value.length > 0 ? value : undefined;
449
1020
  }
450
1021
  function readNumber(record, key) {
@@ -459,7 +1030,7 @@ function readRecord(record, key) {
459
1030
  return;
460
1031
  }
461
1032
  const value = record[key];
462
- return isRecord(value) ? value : undefined;
1033
+ return isRecord2(value) ? value : undefined;
463
1034
  }
464
1035
  function countTextTokens(text) {
465
1036
  if (!text) {
@@ -514,7 +1085,7 @@ function countJsonLikeTokens(value) {
514
1085
  if (Array.isArray(value)) {
515
1086
  return value.reduce((sum, entry) => sum + countJsonLikeTokens(entry), 0);
516
1087
  }
517
- if (isRecord(value)) {
1088
+ if (isRecord2(value)) {
518
1089
  return Object.entries(value).reduce((sum, [key, entry]) => {
519
1090
  return sum + countTextTokens(key) + countJsonLikeTokens(entry);
520
1091
  }, 0);
@@ -560,7 +1131,7 @@ function finalizeTokenAccountingEvent(state, overrides = {}, outcome = "complete
560
1131
  });
561
1132
  }
562
1133
  function assertCanonicalTokenAccountingEventV2(event) {
563
- if (!isRecord(event)) {
1134
+ if (!isRecord2(event)) {
564
1135
  throw new Error("Canonical token accounting event must be an object.");
565
1136
  }
566
1137
  for (const key of Object.keys(event)) {
@@ -719,7 +1290,7 @@ function isDeferred(state) {
719
1290
  return state.deferFinalization === true;
720
1291
  }
721
1292
  function setSessionModel(state, value) {
722
- const model = asString(value) ?? state.model ?? "unknown";
1293
+ const model = asString2(value) ?? state.model ?? "unknown";
723
1294
  if (isDeferred(state) && model.length > MAX_DEFERRED_MODEL_CHARS) {
724
1295
  state.model = model.slice(0, MAX_DEFERRED_MODEL_CHARS);
725
1296
  state.requestEstimateTruncated = true;
@@ -814,11 +1385,11 @@ function stripDeferredMedia(value, key = "") {
814
1385
  }
815
1386
  return { value: result, sawMedia, hasContent };
816
1387
  }
817
- if (!isRecord(value))
1388
+ if (!isRecord2(value))
818
1389
  return { value, sawMedia: false, hasContent: false };
819
- if (asString(value.type) === "tool_use" || asString(value.type) === "function_call")
1390
+ if (asString2(value.type) === "tool_use" || asString2(value.type) === "function_call")
820
1391
  return { value, sawMedia: false, hasContent: true };
821
- if (DEFERRED_MEDIA_TYPES.has(asString(value.type) ?? ""))
1392
+ if (DEFERRED_MEDIA_TYPES.has(asString2(value.type) ?? ""))
822
1393
  return { value: undefined, sawMedia: true, hasContent: false };
823
1394
  const result = {};
824
1395
  let sawMedia = false;
@@ -894,7 +1465,7 @@ function boundedRequestSnapshot(body, maxNodes = MAX_INPUT_ESTIMATE_NODES) {
894
1465
  truncated = true;
895
1466
  return result;
896
1467
  }
897
- if (!isRecord(value))
1468
+ if (!isRecord2(value))
898
1469
  return;
899
1470
  const result = {};
900
1471
  for (const key in value) {
@@ -962,7 +1533,7 @@ function hasOpenAIOutput(body) {
962
1533
  if (Array.isArray(body.output) && body.output.length > 0)
963
1534
  return true;
964
1535
  return Array.isArray(body.choices) && body.choices.some((choice) => {
965
- if (!isRecord(choice))
1536
+ if (!isRecord2(choice))
966
1537
  return false;
967
1538
  const message = readRecord(choice, "message") ?? readRecord(choice, "delta");
968
1539
  return !!message && (message.content !== undefined && message.content !== null || Array.isArray(message.tool_calls) && message.tool_calls.length > 0);
@@ -986,13 +1557,13 @@ function hasGeminiOutput(body) {
986
1557
  });
987
1558
  }
988
1559
  function isErrorResponse(body) {
989
- const status = asString(body.status)?.toLowerCase();
990
- const type = asString(body.type)?.toLowerCase();
1560
+ const status = asString2(body.status)?.toLowerCase();
1561
+ const type = asString2(body.type)?.toLowerCase();
991
1562
  return body.error !== undefined || status === "error" || status === "failed" || type === "error" || type?.endsWith(".error") === true || type?.endsWith(".failed") === true;
992
1563
  }
993
1564
  function isDeferredFailure(body) {
994
- const status = asString(body.status)?.toLowerCase();
995
- const type = asString(body.type)?.toLowerCase();
1565
+ const status = asString2(body.status)?.toLowerCase();
1566
+ const type = asString2(body.type)?.toLowerCase();
996
1567
  return isErrorResponse(body) || status === "incomplete" || type === "incomplete" || type?.endsWith(".incomplete") === true;
997
1568
  }
998
1569
  function observeOpenAIOutput(state, chunk, includeResponseSnapshot = true, event) {
@@ -1003,7 +1574,7 @@ function observeOpenAIOutput(state, chunk, includeResponseSnapshot = true, event
1003
1574
  if (isDeferred(state))
1004
1575
  state.estimateTruncated = true;
1005
1576
  };
1006
- const type = event ?? asString(chunk.type);
1577
+ const type = event ?? asString2(chunk.type);
1007
1578
  if (type === "response.output_text.delta") {
1008
1579
  if (isDeferred(state))
1009
1580
  observeBoundedOutput(state, chunk.delta);
@@ -1035,7 +1606,7 @@ function observeOpenAIOutput(state, chunk, includeResponseSnapshot = true, event
1035
1606
  const choiceLimit = Math.min(choices.length, nodes);
1036
1607
  for (let index = 0;index < choiceLimit; index += 1, nodes -= 1) {
1037
1608
  const choice = choices[index];
1038
- if (!isRecord(choice))
1609
+ if (!isRecord2(choice))
1039
1610
  continue;
1040
1611
  const delta = readRecord(choice, "delta") ?? (isDeferred(state) ? readRecord(choice, "message") : undefined);
1041
1612
  if (delta?.content !== undefined) {
@@ -1081,7 +1652,7 @@ function observeGeminiOutput(state, chunk) {
1081
1652
  const partLimit = Math.min(parts.length, nodes);
1082
1653
  for (let partIndex = 0;partIndex < partLimit; partIndex += 1, nodes -= 1) {
1083
1654
  const part = parts[partIndex];
1084
- if (!isRecord(part))
1655
+ if (!isRecord2(part))
1085
1656
  continue;
1086
1657
  if (isDeferred(state) && (part.inlineData !== undefined || part.inline_data !== undefined || part.fileData !== undefined || part.file_data !== undefined)) {
1087
1658
  state.estimateMediaSeen = true;
@@ -1106,7 +1677,7 @@ function observeGeminiOutput(state, chunk) {
1106
1677
  state.estimateTruncated = true;
1107
1678
  }
1108
1679
  function countOpenAIStringTokens(value, model) {
1109
- return countModelTextTokens(asString(value) ?? "", model);
1680
+ return countModelTextTokens(asString2(value) ?? "", model);
1110
1681
  }
1111
1682
  function countOpenAIJsonLikeTokens(value, model) {
1112
1683
  if (typeof value === "string") {
@@ -1121,7 +1692,7 @@ function countOpenAIJsonLikeTokens(value, model) {
1121
1692
  if (Array.isArray(value)) {
1122
1693
  return value.reduce((total, item) => total + countOpenAIJsonLikeTokens(item, model), 0);
1123
1694
  }
1124
- if (isRecord(value)) {
1695
+ if (isRecord2(value)) {
1125
1696
  return Object.entries(value).reduce((total, [key, item]) => {
1126
1697
  return total + countOpenAIStringTokens(key, model) + countOpenAIJsonLikeTokens(item, model);
1127
1698
  }, 0);
@@ -1130,21 +1701,21 @@ function countOpenAIJsonLikeTokens(value, model) {
1130
1701
  }
1131
1702
  function estimateOpenAIImageTokens(part) {
1132
1703
  const imageUrl = readRecord(part, "image_url");
1133
- const detail = asString(part.detail) ?? asString(imageUrl?.detail);
1704
+ const detail = asString2(part.detail) ?? asString2(imageUrl?.detail);
1134
1705
  if (detail === "low") {
1135
1706
  return 85;
1136
1707
  }
1137
1708
  return 170;
1138
1709
  }
1139
1710
  function estimateOpenAIToolCallTokens(toolCall, model) {
1140
- if (!isRecord(toolCall)) {
1711
+ if (!isRecord2(toolCall)) {
1141
1712
  return countOpenAIJsonLikeTokens(toolCall, model);
1142
1713
  }
1143
1714
  const toolFunction = readRecord(toolCall, "function");
1144
1715
  return 12 + countOpenAIStringTokens(toolCall.id, model) + countOpenAIStringTokens(toolCall.type, model) + countOpenAIStringTokens(toolFunction?.name, model) + countOpenAIStringTokens(toolFunction?.arguments, model) + countOpenAIJsonLikeTokens(toolCall, model);
1145
1716
  }
1146
1717
  function estimateOpenAIMessageTokens(message, model) {
1147
- if (!isRecord(message)) {
1718
+ if (!isRecord2(message)) {
1148
1719
  return countOpenAIJsonLikeTokens(message, model);
1149
1720
  }
1150
1721
  const content = message.content;
@@ -1156,7 +1727,7 @@ function safeTokenSum(...values) {
1156
1727
  return Number.isSafeInteger(total) && total >= 0 ? total : undefined;
1157
1728
  }
1158
1729
  function estimateGeminiInlineDataTokens(inlineData) {
1159
- const mimeType = asString(inlineData.mimeType)?.toLowerCase() ?? "";
1730
+ const mimeType = asString2(inlineData.mimeType)?.toLowerCase() ?? "";
1160
1731
  if (mimeType.startsWith("image/")) {
1161
1732
  return 224;
1162
1733
  }
@@ -1169,10 +1740,10 @@ function estimateGeminiInlineDataTokens(inlineData) {
1169
1740
  return 96;
1170
1741
  }
1171
1742
  function estimateGeminiFunctionCallTokens(functionCall) {
1172
- return 12 + countTextTokens(asString(functionCall.name) ?? "") + countJsonLikeTokens(functionCall.args);
1743
+ return 12 + countTextTokens(asString2(functionCall.name) ?? "") + countJsonLikeTokens(functionCall.args);
1173
1744
  }
1174
1745
  function estimateGeminiFunctionResponseTokens(functionResponse) {
1175
- return 12 + countTextTokens(asString(functionResponse.name) ?? "") + countJsonLikeTokens(functionResponse.response);
1746
+ return 12 + countTextTokens(asString2(functionResponse.name) ?? "") + countJsonLikeTokens(functionResponse.response);
1176
1747
  }
1177
1748
  function buildAnthropicStreamingEvent(state, overrides = {}) {
1178
1749
  return createPartialTokenAccountingEvent(state, {
@@ -1193,10 +1764,10 @@ function estimateOpenAIMessageContent(content, model) {
1193
1764
  return countOpenAIJsonLikeTokens(content, model);
1194
1765
  }
1195
1766
  return content.reduce((total, part) => {
1196
- if (!isRecord(part)) {
1767
+ if (!isRecord2(part)) {
1197
1768
  return total + countOpenAIJsonLikeTokens(part, model);
1198
1769
  }
1199
- const type = asString(part.type);
1770
+ const type = asString2(part.type);
1200
1771
  if (type === "text") {
1201
1772
  return total + countOpenAIStringTokens(part.text, model);
1202
1773
  }
@@ -1207,7 +1778,7 @@ function estimateOpenAIMessageContent(content, model) {
1207
1778
  }, 0);
1208
1779
  }
1209
1780
  function estimateOpenAIInputTokens(body) {
1210
- const model = asString(body.model);
1781
+ const model = asString2(body.model);
1211
1782
  if (body.input !== undefined) {
1212
1783
  return clampTokens(countOpenAIJsonLikeTokens(body.input, model) + 8) ?? 0;
1213
1784
  }
@@ -1220,13 +1791,13 @@ function estimateOpenAIInputTokens(body) {
1220
1791
  function estimateOpenAIResponseOutputTokens(body, model) {
1221
1792
  const choices = Array.isArray(body.choices) ? body.choices : [];
1222
1793
  return clampTokens(choices.reduce((total, choice) => {
1223
- if (!isRecord(choice)) {
1794
+ if (!isRecord2(choice)) {
1224
1795
  return total + countOpenAIJsonLikeTokens(choice, model);
1225
1796
  }
1226
1797
  const message = readRecord(choice, "message");
1227
1798
  const delta = readRecord(choice, "delta");
1228
1799
  const toolCalls = Array.isArray(message?.tool_calls) ? message.tool_calls : Array.isArray(delta?.tool_calls) ? delta.tool_calls : [];
1229
- return total + countOpenAIStringTokens(message?.role ?? delta?.role, model) + countOpenAIStringTokens(message?.tool_call_id, model) + estimateOpenAIMessageContent(message?.content ?? delta?.content, model) + toolCalls.reduce((toolTotal, toolCall) => toolTotal + estimateOpenAIToolCallTokens(toolCall, model), 0) + (asString(choice.finish_reason) === "tool_calls" ? 4 : 0);
1800
+ return total + countOpenAIStringTokens(message?.role ?? delta?.role, model) + countOpenAIStringTokens(message?.tool_call_id, model) + estimateOpenAIMessageContent(message?.content ?? delta?.content, model) + toolCalls.reduce((toolTotal, toolCall) => toolTotal + estimateOpenAIToolCallTokens(toolCall, model), 0) + (asString2(choice.finish_reason) === "tool_calls" ? 4 : 0);
1230
1801
  }, 0)) ?? 0;
1231
1802
  }
1232
1803
  function openAIUsage(body) {
@@ -1235,11 +1806,11 @@ function openAIUsage(body) {
1235
1806
  function estimateOpenAIResponsesOutputTokens(response, model) {
1236
1807
  const output = Array.isArray(response.output) ? response.output : [];
1237
1808
  return clampTokens(output.reduce((total, item) => {
1238
- if (!isRecord(item))
1809
+ if (!isRecord2(item))
1239
1810
  return total + countOpenAIJsonLikeTokens(item, model);
1240
1811
  const content = Array.isArray(item.content) ? item.content : [];
1241
1812
  return total + content.reduce((contentTotal, part) => {
1242
- if (isRecord(part) && typeof part.text === "string")
1813
+ if (isRecord2(part) && typeof part.text === "string")
1243
1814
  return contentTotal + countOpenAIStringTokens(part.text, model);
1244
1815
  return contentTotal + countOpenAIJsonLikeTokens(part, model);
1245
1816
  }, 0) + countOpenAIStringTokens(item.arguments, model);
@@ -1249,7 +1820,7 @@ function isDoneSentinel(chunk) {
1249
1820
  return chunk.data === "[DONE]" || chunk.type === "[DONE]";
1250
1821
  }
1251
1822
  function estimateAnthropicInputTokens(body) {
1252
- const system = asString(body.system) ?? "";
1823
+ const system = asString2(body.system) ?? "";
1253
1824
  const messages = Array.isArray(body.messages) ? body.messages : [];
1254
1825
  const tools = Array.isArray(body.tools) ? body.tools : [];
1255
1826
  return clampTokens(countTextTokens(system) + messages.reduce((total, message) => total + countJsonLikeTokens(message), 0) + tools.reduce((total, tool) => total + 16 + countJsonLikeTokens(tool), 0) + 8) ?? 0;
@@ -1259,19 +1830,19 @@ function estimateAnthropicOutputTokens(body) {
1259
1830
  return clampTokens(content.reduce((total, block) => total + countJsonLikeTokens(block), 0)) ?? 0;
1260
1831
  }
1261
1832
  function estimateGeminiPartTokens(part) {
1262
- if (!isRecord(part)) {
1833
+ if (!isRecord2(part)) {
1263
1834
  return countJsonLikeTokens(part);
1264
1835
  }
1265
1836
  if (typeof part.text === "string") {
1266
1837
  return countTextTokens(part.text);
1267
1838
  }
1268
- if (isRecord(part.inlineData)) {
1839
+ if (isRecord2(part.inlineData)) {
1269
1840
  return estimateGeminiInlineDataTokens(part.inlineData);
1270
1841
  }
1271
- if (isRecord(part.functionCall)) {
1842
+ if (isRecord2(part.functionCall)) {
1272
1843
  return estimateGeminiFunctionCallTokens(part.functionCall);
1273
1844
  }
1274
- if (isRecord(part.functionResponse)) {
1845
+ if (isRecord2(part.functionResponse)) {
1275
1846
  return estimateGeminiFunctionResponseTokens(part.functionResponse);
1276
1847
  }
1277
1848
  return countJsonLikeTokens(part);
@@ -1281,7 +1852,7 @@ function estimateGeminiInputTokens(body) {
1281
1852
  const systemParts = Array.isArray(systemInstruction?.parts) ? systemInstruction.parts : [];
1282
1853
  const contents = Array.isArray(body.contents) ? body.contents : [];
1283
1854
  return clampTokens(systemParts.reduce((total, part) => total + estimateGeminiPartTokens(part), 0) + contents.reduce((total, item) => {
1284
- if (!isRecord(item)) {
1855
+ if (!isRecord2(item)) {
1285
1856
  return total + countJsonLikeTokens(item);
1286
1857
  }
1287
1858
  const parts = Array.isArray(item.parts) ? item.parts : [];
@@ -1291,7 +1862,7 @@ function estimateGeminiInputTokens(body) {
1291
1862
  function estimateGeminiOutputTokens(body) {
1292
1863
  const candidates = Array.isArray(body.candidates) ? body.candidates : [];
1293
1864
  return clampTokens(candidates.reduce((total, candidate) => {
1294
- if (!isRecord(candidate)) {
1865
+ if (!isRecord2(candidate)) {
1295
1866
  return total + countJsonLikeTokens(candidate);
1296
1867
  }
1297
1868
  const content = readRecord(candidate, "content");
@@ -1311,9 +1882,9 @@ function createOpenAIAdapter() {
1311
1882
  const usage = openAIUsage(body);
1312
1883
  const promptTokens = readNumber(usage, "prompt_tokens") ?? readNumber(usage, "input_tokens");
1313
1884
  const completionTokens = readNumber(usage, "completion_tokens") ?? readNumber(usage, "output_tokens");
1314
- const responseStatus = asString(readRecord(body, "response")?.status) ?? asString(body.status);
1315
- const isIncomplete = responseStatus === "incomplete" || asString(body.type) === "response.incomplete";
1316
- const isFailed = responseStatus === "failed" || asString(body.type) === "response.failed";
1885
+ const responseStatus = asString2(readRecord(body, "response")?.status) ?? asString2(body.status);
1886
+ const isIncomplete = responseStatus === "incomplete" || asString2(body.type) === "response.incomplete";
1887
+ const isFailed = responseStatus === "failed" || asString2(body.type) === "response.failed";
1317
1888
  const promptDetails = readRecord(usage, "prompt_tokens_details") ?? readRecord(usage, "input_tokens_details");
1318
1889
  const cacheReadTokens = readNumber(promptDetails, "cached_tokens");
1319
1890
  if (isDeferred(state)) {
@@ -1387,12 +1958,12 @@ function createOpenAIAdapter() {
1387
1958
  const reportedCache = readNumber(promptDetails, "cached_tokens");
1388
1959
  if (reportedCache !== undefined)
1389
1960
  state.cacheReadTokens = reportedCache;
1390
- const responseType = event ?? asString(chunk.type);
1391
- const responseStatus = asString(response?.status);
1961
+ const responseType = event ?? asString2(chunk.type);
1962
+ const responseStatus = asString2(response?.status);
1392
1963
  const responseCompleted = responseType === "response.completed" || responseStatus === "completed";
1393
1964
  observeOpenAIOutput(state, chunk, !responseCompleted, event);
1394
1965
  const choices = Array.isArray(chunk.choices) ? chunk.choices : [];
1395
- if (choices.some((choice) => isRecord(choice) && asString(choice.finish_reason) !== undefined && choice.finish_reason !== null)) {
1966
+ if (choices.some((choice) => isRecord2(choice) && asString2(choice.finish_reason) !== undefined && choice.finish_reason !== null)) {
1396
1967
  state.protocolTerminalSeen = true;
1397
1968
  if (isDeferred(state))
1398
1969
  state.deferredOutcome = "completed";
@@ -1561,7 +2132,7 @@ function createAnthropicAdapter() {
1561
2132
  consumeStreamChunk(state, chunk, event) {
1562
2133
  if (state.finalReceived || isDoneSentinel(chunk))
1563
2134
  return null;
1564
- const type = event ?? asString(chunk.type);
2135
+ const type = event ?? asString2(chunk.type);
1565
2136
  if (isDeferred(state) && type === "error") {
1566
2137
  state.protocolTerminalSeen = true;
1567
2138
  state.deferredOutcome = "failed";
@@ -1607,7 +2178,7 @@ function createAnthropicAdapter() {
1607
2178
  }
1608
2179
  if (type === "content_block_delta") {
1609
2180
  const delta = readRecord(chunk, "delta");
1610
- const deltaType = asString(delta?.type);
2181
+ const deltaType = asString2(delta?.type);
1611
2182
  if (deltaType === "text_delta") {
1612
2183
  if (isDeferred(state))
1613
2184
  observeBoundedOutput(state, delta?.text);
@@ -1782,7 +2353,7 @@ function createGeminiAdapter() {
1782
2353
  const toolUsePromptTokenCount = readNumber(usageMetadata, "toolUsePromptTokenCount") ?? 0;
1783
2354
  const reportedCacheRead = readNumber(usageMetadata, "cachedContentTokenCount");
1784
2355
  const candidates = Array.isArray(chunk.candidates) ? chunk.candidates : [];
1785
- if (candidates.some((candidate) => isRecord(candidate) && asString(candidate.finishReason) !== undefined)) {
2356
+ if (candidates.some((candidate) => isRecord2(candidate) && asString2(candidate.finishReason) !== undefined)) {
1786
2357
  state.protocolTerminalSeen = true;
1787
2358
  if (isDeferred(state))
1788
2359
  state.deferredOutcome ??= "completed";
@@ -1924,18 +2495,28 @@ function createTokenAccountingSession(input, options = {}) {
1924
2495
  }
1925
2496
  };
1926
2497
  }
2498
+ // packages/llms/src/responses-codec/common.ts
2499
+ var DEFAULT_RESPONSES_CODEC_LIMITS = Object.freeze({
2500
+ maxRequestBytes: 8 * 1024 * 1024,
2501
+ maxOutputBytes: 8 * 1024 * 1024,
2502
+ maxArgumentBytes: 1024 * 1024,
2503
+ maxItems: 1024
2504
+ });
2505
+
2506
+ // packages/llms/src/responses-codec/request.ts
2507
+ var contentNormalizer = new OpenAIProtocolConversion({ trimWhitespace: false });
1927
2508
  // plugins/token-metering/server/classifier.ts
1928
- function record(value) {
2509
+ function record2(value) {
1929
2510
  return typeof value === "object" && value !== null && !Array.isArray(value);
1930
2511
  }
1931
2512
  function messages(value) {
1932
- return Array.isArray(value) && value.length > 0 && value.every((message) => record(message) && typeof message.role === "string" && ["system", "developer", "user", "assistant", "tool", "function"].includes(message.role) && (typeof message.content === "string" || Array.isArray(message.content) || message.role === "assistant" && (message.content === null || Array.isArray(message.tool_calls))));
2513
+ return Array.isArray(value) && value.length > 0 && value.every((message) => record2(message) && typeof message.role === "string" && ["system", "developer", "user", "assistant", "tool", "function"].includes(message.role) && (typeof message.content === "string" || Array.isArray(message.content) || message.role === "assistant" && (message.content === null || Array.isArray(message.tool_calls))));
1933
2514
  }
1934
2515
  function input(value) {
1935
- return typeof value === "string" || Array.isArray(value) && value.every((item) => typeof item === "string" || record(item) && (typeof item.type === "string" || typeof item.role === "string" && (typeof item.content === "string" || Array.isArray(item.content))));
2516
+ return typeof value === "string" || Array.isArray(value) && value.every((item) => typeof item === "string" || record2(item) && (typeof item.type === "string" || typeof item.role === "string" && (typeof item.content === "string" || Array.isArray(item.content))));
1936
2517
  }
1937
2518
  function contents(value) {
1938
- return Array.isArray(value) && value.length > 0 && value.every((content) => record(content) && Array.isArray(content.parts));
2519
+ return Array.isArray(value) && value.length > 0 && value.every((content) => record2(content) && Array.isArray(content.parts));
1939
2520
  }
1940
2521
  function classifyRequest(url, body) {
1941
2522
  const path = url.pathname.toLowerCase().replace(/\/+$/, "");
@@ -1944,7 +2525,7 @@ function classifyRequest(url, body) {
1944
2525
  const hasInput = input(body.input);
1945
2526
  const hasPrompt = typeof body.prompt === "string" || Array.isArray(body.prompt) && body.prompt.length > 0 && body.prompt.every((item) => typeof item === "string");
1946
2527
  const hasContents = contents(body.contents);
1947
- if (hasContents && (/\/models\/[^/]+:(?:stream)?generatecontent$/.test(path) || hasModel || record(body.generationConfig))) {
2528
+ if (hasContents && (/\/models\/[^/]+:(?:stream)?generatecontent$/.test(path) || hasModel || record2(body.generationConfig))) {
1948
2529
  return { llm: true, provider: "gemini" };
1949
2530
  }
1950
2531
  if (hasModel && hasMessages && (path.endsWith("/messages") || typeof body.anthropic_version === "string")) {
@@ -1960,25 +2541,25 @@ function classifyRequest(url, body) {
1960
2541
  }
1961
2542
  function classifyResponse(body, knownLlmRequest, event) {
1962
2543
  const eventType = event ?? (typeof body.type === "string" ? body.type : "");
1963
- if (Array.isArray(body.candidates) && body.candidates.some((candidate) => record(candidate) && record(candidate.content) && Array.isArray(candidate.content.parts)))
2544
+ if (Array.isArray(body.candidates) && body.candidates.some((candidate) => record2(candidate) && record2(candidate.content) && Array.isArray(candidate.content.parts)))
1964
2545
  return "gemini";
1965
2546
  if (eventType === "message" && body.role === "assistant" && Array.isArray(body.content))
1966
2547
  return "anthropic";
1967
- if (eventType === "message_start" && record(body.message) && body.message.type === "message" && Array.isArray(body.message.content))
2548
+ if (eventType === "message_start" && record2(body.message) && body.message.type === "message" && Array.isArray(body.message.content))
1968
2549
  return "anthropic";
1969
- if (eventType === "content_block_delta" && record(body.delta) && ["text_delta", "input_json_delta", "thinking_delta", "signature_delta"].includes(String(body.delta.type)))
2550
+ if (eventType === "content_block_delta" && record2(body.delta) && ["text_delta", "input_json_delta", "thinking_delta", "signature_delta"].includes(String(body.delta.type)))
1970
2551
  return "anthropic";
1971
- if (Array.isArray(body.choices) && (body.object === "chat.completion" || body.object === "chat.completion.chunk" || body.object === "text_completion" || body.choices.some((choice) => record(choice) && (record(choice.message) && choice.message.role === "assistant" && (typeof choice.message.content === "string" || Array.isArray(choice.message.content) || Array.isArray(choice.message.tool_calls)) || record(choice.delta) && (choice.delta.role === "assistant" || typeof choice.delta.content === "string" || typeof choice.delta.reasoning_content === "string" || Array.isArray(choice.delta.tool_calls) || record(choice.delta.function_call)) || typeof choice.text === "string" && typeof choice.index === "number"))))
2552
+ if (Array.isArray(body.choices) && (body.object === "chat.completion" || body.object === "chat.completion.chunk" || body.object === "text_completion" || body.choices.some((choice) => record2(choice) && (record2(choice.message) && choice.message.role === "assistant" && (typeof choice.message.content === "string" || Array.isArray(choice.message.content) || Array.isArray(choice.message.tool_calls)) || record2(choice.delta) && (choice.delta.role === "assistant" || typeof choice.delta.content === "string" || typeof choice.delta.reasoning_content === "string" || Array.isArray(choice.delta.tool_calls) || record2(choice.delta.function_call)) || typeof choice.text === "string" && typeof choice.index === "number"))))
1972
2553
  return "openai";
1973
2554
  if (body.object === "response" && Array.isArray(body.output))
1974
2555
  return "openai";
1975
- if (eventType.startsWith("response.") && (record(body.response) || record(body.item) || typeof body.delta === "string" || typeof body.output_index === "number"))
2556
+ if (eventType.startsWith("response.") && (record2(body.response) || record2(body.item) || typeof body.delta === "string" || typeof body.output_index === "number"))
1976
2557
  return "openai";
1977
2558
  if (!knownLlmRequest)
1978
2559
  return;
1979
- if (record(body.usageMetadata))
2560
+ if (record2(body.usageMetadata))
1980
2561
  return "gemini";
1981
- const usage = record(body.usage) ? body.usage : undefined;
2562
+ const usage = record2(body.usage) ? body.usage : undefined;
1982
2563
  if (eventType.startsWith("message_") || eventType.startsWith("content_block_") || usage && (("cache_creation_input_tokens" in usage) || ("cache_read_input_tokens" in usage)))
1983
2564
  return "anthropic";
1984
2565
  if (usage && (("prompt_tokens" in usage) || ("completion_tokens" in usage)))
@@ -1992,7 +2573,7 @@ var MAX_CONNECTIONS = 128;
1992
2573
  var MAX_RESPONSES = 1024;
1993
2574
  var MAX_CONNECTION_RESPONSES = 64;
1994
2575
  var MAX_TOMBSTONES = 256;
1995
- var record2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
2576
+ var record3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
1996
2577
  var identifier = (value) => typeof value === "string" && value.length > 0 && value.length <= 256 ? value : undefined;
1997
2578
  var count = (value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
1998
2579
  function metadata(event) {
@@ -2006,7 +2587,7 @@ function responsesUrl(value) {
2006
2587
  }
2007
2588
  }
2008
2589
  function stream(body) {
2009
- return identifier(body.stream_id) ?? (record2(body.response) ? identifier(body.response.stream_id) : undefined);
2590
+ return identifier(body.stream_id) ?? (record3(body.response) ? identifier(body.response.stream_id) : undefined);
2010
2591
  }
2011
2592
 
2012
2593
  class ResponsesWebSocketMetering {
@@ -2056,7 +2637,7 @@ class ResponsesWebSocketMetering {
2056
2637
  if (connection.disabled || event.phase !== "message" || event.message.kind !== "text")
2057
2638
  return;
2058
2639
  const body = event.message.json();
2059
- if (!record2(body))
2640
+ if (!record3(body))
2060
2641
  return;
2061
2642
  if (event.direction === "client") {
2062
2643
  if (body.type !== "response.create" || !(typeof body.input === "string" || Array.isArray(body.input) || identifier(body.previous_response_id) || identifier(body.model)))
@@ -2073,7 +2654,7 @@ class ResponsesWebSocketMetering {
2073
2654
  const type = identifier(body.type);
2074
2655
  if (!type?.startsWith("response."))
2075
2656
  return;
2076
- const envelope = record2(body.response) ? body.response : undefined;
2657
+ const envelope = record3(body.response) ? body.response : undefined;
2077
2658
  const terminal = ["response.completed", "response.failed", "response.incomplete"].includes(type);
2078
2659
  if (terminal && (!envelope || envelope.object !== "response" || !Array.isArray(envelope.output)))
2079
2660
  return;
@@ -2101,7 +2682,7 @@ class ResponsesWebSocketMetering {
2101
2682
  return;
2102
2683
  connection.active.set(responseId, response);
2103
2684
  }
2104
- const usage = record2(envelope?.usage) ? envelope.usage : undefined;
2685
+ const usage = record3(envelope?.usage) ? envelope.usage : undefined;
2105
2686
  if (!response.bound && !await this.bind(response, event, responseId))
2106
2687
  return;
2107
2688
  if (!await this.emit(response, event, { phase: "response", status: 200, protocol: "sse", body }))
@@ -2193,11 +2774,11 @@ class ResponsesWebSocketMetering {
2193
2774
  var MAX_ACTIVE_ATTEMPTS = 1024;
2194
2775
  var LOG_INTERVAL_MS = 60000;
2195
2776
  var lastCapacityWarningAt = 0;
2196
- function isRecord2(value) {
2777
+ function isRecord3(value) {
2197
2778
  return typeof value === "object" && value !== null && !Array.isArray(value);
2198
2779
  }
2199
2780
  function parseRequestBody(value) {
2200
- return isRecord2(value) ? value : undefined;
2781
+ return isRecord3(value) ? value : undefined;
2201
2782
  }
2202
2783
  function detectModel(body, url) {
2203
2784
  if (typeof body.model === "string" && body.model.length > 0)
@@ -2567,7 +3148,7 @@ var TokenMeteringPlugin = definePlugin(class {
2567
3148
  if (event.phase === "response") {
2568
3149
  attempt.responseSeen = true;
2569
3150
  const body = event.body;
2570
- if (websocket && isRecord2(body.response)) {
3151
+ if (websocket && isRecord3(body.response)) {
2571
3152
  const model = detectModel(body.response);
2572
3153
  if (model) {
2573
3154
  attempt.model = model;
@@ -2579,7 +3160,7 @@ var TokenMeteringPlugin = definePlugin(class {
2579
3160
  if (!provider)
2580
3161
  return;
2581
3162
  if (!attempt.llm) {
2582
- attempt.model = detectModel(body) ?? (isRecord2(body.response) ? detectModel(body.response) : undefined);
3163
+ attempt.model = detectModel(body) ?? (isRecord3(body.response) ? detectModel(body.response) : undefined);
2583
3164
  }
2584
3165
  attempt.llm = true;
2585
3166
  if (!attempt.session) {
@@ -2664,4 +3245,4 @@ export {
2664
3245
  server_default as default
2665
3246
  };
2666
3247
 
2667
- //# debugId=E40F8525D6A44D4364756E2164756E21
3248
+ //# debugId=BE427C2BCB66F77664756E2164756E21