@happyvertical/ai 0.96.1 → 0.98.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 (87) hide show
  1. package/README.md +123 -3
  2. package/dist/chunks/{anthropic-CD9Ud7a5.js → anthropic-6ZDF32jo.js} +181 -27
  3. package/dist/chunks/anthropic-6ZDF32jo.js.map +1 -0
  4. package/dist/chunks/{bedrock-Bv1qCquH.js → bedrock-BQi3Z9jR.js} +71 -21
  5. package/dist/chunks/bedrock-BQi3Z9jR.js.map +1 -0
  6. package/dist/chunks/{bifrost-DzT2J0Lq.js → bifrost-DsI2I4ka.js} +9 -6
  7. package/dist/chunks/bifrost-DsI2I4ka.js.map +1 -0
  8. package/dist/chunks/{byteplus-modelark-BIEXaTWw.js → byteplus-modelark-Dq8AgCQD.js} +7 -5
  9. package/dist/chunks/byteplus-modelark-Dq8AgCQD.js.map +1 -0
  10. package/dist/chunks/{claude-cli-Chfnckyj.js → claude-cli-DIFxvG3c.js} +7 -5
  11. package/dist/chunks/claude-cli-DIFxvG3c.js.map +1 -0
  12. package/dist/chunks/continuation-D0NisZA1.js +209 -0
  13. package/dist/chunks/continuation-D0NisZA1.js.map +1 -0
  14. package/dist/chunks/{gateway-admin-04mvbDHC.js → gateway-audio-models-Dn7Wrc6P.js} +53 -3
  15. package/dist/chunks/gateway-audio-models-Dn7Wrc6P.js.map +1 -0
  16. package/dist/chunks/{gemini-BGwrHeGc.js → gemini-BLFwWN90.js} +131 -13
  17. package/dist/chunks/gemini-BLFwWN90.js.map +1 -0
  18. package/dist/chunks/{huggingface-mthYVbLR.js → huggingface-BuRwlABZ.js} +8 -6
  19. package/dist/chunks/huggingface-BuRwlABZ.js.map +1 -0
  20. package/dist/chunks/{litellm-xCO8QlGI.js → litellm-CpfCT6jN.js} +9 -6
  21. package/dist/chunks/litellm-CpfCT6jN.js.map +1 -0
  22. package/dist/chunks/{ollama-Bedt8Agy.js → ollama-CnrskTUg.js} +38 -7
  23. package/dist/chunks/ollama-CnrskTUg.js.map +1 -0
  24. package/dist/chunks/{openai-compat-video-B-xVe9bW.js → openai-compat-video-CJIDdkUO.js} +7 -5
  25. package/dist/chunks/openai-compat-video-CJIDdkUO.js.map +1 -0
  26. package/dist/chunks/{qwen-tts-D-UmiMMy.js → qwen-tts-PzEkWcEb.js} +2 -2
  27. package/dist/chunks/{qwen-tts-D-UmiMMy.js.map → qwen-tts-PzEkWcEb.js.map} +1 -1
  28. package/dist/chunks/rate-limit-BzWfHA0e.js +713 -0
  29. package/dist/chunks/rate-limit-BzWfHA0e.js.map +1 -0
  30. package/dist/chunks/{seevio-BJRiguLc.js → seevio-D2y5Io7C.js} +4 -5
  31. package/dist/chunks/seevio-D2y5Io7C.js.map +1 -0
  32. package/dist/chunks/{src-BUQUZK2M.js → src-CLT6r1W0.js} +36 -23
  33. package/dist/chunks/src-CLT6r1W0.js.map +1 -0
  34. package/dist/chunks/tool-messages-0ND35mYX.js +57 -0
  35. package/dist/chunks/tool-messages-0ND35mYX.js.map +1 -0
  36. package/dist/chunks/{types-BpnNcTU1.js → types-DB5W6_F-.js} +37 -5
  37. package/dist/chunks/types-DB5W6_F-.js.map +1 -0
  38. package/dist/chunks/{typesafe-B0gPZQJg.js → typesafe-CVUqQ8N1.js} +7 -5
  39. package/dist/chunks/typesafe-CVUqQ8N1.js.map +1 -0
  40. package/dist/index.js +4 -4
  41. package/dist/node.js +5 -5
  42. package/dist/shared/continuation.d.ts +51 -0
  43. package/dist/shared/continuation.d.ts.map +1 -0
  44. package/dist/shared/factory.d.ts.map +1 -1
  45. package/dist/shared/providers/anthropic.d.ts +53 -0
  46. package/dist/shared/providers/anthropic.d.ts.map +1 -1
  47. package/dist/shared/providers/bedrock.d.ts +13 -0
  48. package/dist/shared/providers/bedrock.d.ts.map +1 -1
  49. package/dist/shared/providers/bifrost.d.ts.map +1 -1
  50. package/dist/shared/providers/claude-cli.d.ts.map +1 -1
  51. package/dist/shared/providers/gateway-audio-models.d.ts +24 -0
  52. package/dist/shared/providers/gateway-audio-models.d.ts.map +1 -0
  53. package/dist/shared/providers/gemini.d.ts +28 -0
  54. package/dist/shared/providers/gemini.d.ts.map +1 -1
  55. package/dist/shared/providers/huggingface.d.ts.map +1 -1
  56. package/dist/shared/providers/litellm.d.ts.map +1 -1
  57. package/dist/shared/providers/ollama.d.ts.map +1 -1
  58. package/dist/shared/providers/openai.d.ts.map +1 -1
  59. package/dist/shared/providers/seevio.d.ts.map +1 -1
  60. package/dist/shared/providers/typesafe.d.ts.map +1 -1
  61. package/dist/shared/rate-limit.d.ts +19 -1
  62. package/dist/shared/rate-limit.d.ts.map +1 -1
  63. package/dist/shared/safety.d.ts.map +1 -1
  64. package/dist/shared/tool-messages.d.ts +27 -0
  65. package/dist/shared/tool-messages.d.ts.map +1 -0
  66. package/dist/shared/types.d.ts +191 -22
  67. package/dist/shared/types.d.ts.map +1 -1
  68. package/package.json +3 -3
  69. package/dist/chunks/anthropic-CD9Ud7a5.js.map +0 -1
  70. package/dist/chunks/bedrock-Bv1qCquH.js.map +0 -1
  71. package/dist/chunks/bifrost-DzT2J0Lq.js.map +0 -1
  72. package/dist/chunks/byteplus-modelark-BIEXaTWw.js.map +0 -1
  73. package/dist/chunks/claude-cli-Chfnckyj.js.map +0 -1
  74. package/dist/chunks/gateway-admin-04mvbDHC.js.map +0 -1
  75. package/dist/chunks/gemini-BGwrHeGc.js.map +0 -1
  76. package/dist/chunks/huggingface-mthYVbLR.js.map +0 -1
  77. package/dist/chunks/litellm-xCO8QlGI.js.map +0 -1
  78. package/dist/chunks/ollama-Bedt8Agy.js.map +0 -1
  79. package/dist/chunks/openai-compat-video-B-xVe9bW.js.map +0 -1
  80. package/dist/chunks/rate-limit-BVW_1Tey.js +0 -202
  81. package/dist/chunks/rate-limit-BVW_1Tey.js.map +0 -1
  82. package/dist/chunks/safety-BKswBoqy.js +0 -279
  83. package/dist/chunks/safety-BKswBoqy.js.map +0 -1
  84. package/dist/chunks/seevio-BJRiguLc.js.map +0 -1
  85. package/dist/chunks/src-BUQUZK2M.js.map +0 -1
  86. package/dist/chunks/types-BpnNcTU1.js.map +0 -1
  87. package/dist/chunks/typesafe-B0gPZQJg.js.map +0 -1
@@ -1,5 +1,5 @@
1
- import { a as ContextLengthError, c as extractTextContent, o as ModelNotFoundError, r as AuthenticationError, s as RateLimitError, t as AIError } from "./types-BpnNcTU1.js";
2
- import { a as normalizeBaseAIOptions, c as prepareRequestControls, o as normalizeChatOptions, s as normalizeImageGenerationOptions } from "./safety-BKswBoqy.js";
1
+ import { a as ContextLengthError, l as extractTextContent, r as AuthenticationError, s as ModelNotFoundError, t as AIError } from "./types-DB5W6_F-.js";
2
+ import { c as normalizeChatOptions, l as normalizeImageGenerationOptions, n as rateLimitErrorFrom, s as normalizeBaseAIOptions, u as prepareRequestControls } from "./rate-limit-BzWfHA0e.js";
3
3
  import { t as emitUsage } from "./usage-C1Y1Nlg4.js";
4
4
  //#region src/shared/providers/bedrock.ts
5
5
  /**
@@ -9,6 +9,11 @@ var BEDROCK_DEFAULT_CHAT_MODEL = "anthropic.claude-3-5-sonnet-20241022-v2:0";
9
9
  var BEDROCK_TEXT_EMBEDDING_MODEL = "amazon.titan-embed-text-v2:0";
10
10
  var BEDROCK_IMAGE_EMBEDDING_MODEL = "amazon.titan-embed-image-v1";
11
11
  var BEDROCK_IMAGE_GENERATION_MODEL = "amazon.titan-image-generator-v2:0";
12
+ /**
13
+ * System instruction standing in for a "none" tool choice, which Converse
14
+ * lacks, when tools must still be declared (see `mapToolConfig`).
15
+ */
16
+ var NO_TOOL_CALLS_INSTRUCTION = "Do not call any tools in this response. Answer in text using the information already in the conversation.";
12
17
  var BedrockProvider = class {
13
18
  options;
14
19
  client;
@@ -79,7 +84,8 @@ var BedrockProvider = class {
79
84
  signal: options.signal,
80
85
  timeout: options.timeout,
81
86
  reasoning: options.reasoning,
82
- usageTags: options.usageTags
87
+ usageTags: options.usageTags,
88
+ continueOnLength: options.continueOnLength
83
89
  });
84
90
  }
85
91
  /**
@@ -111,7 +117,8 @@ var BedrockProvider = class {
111
117
  signal: options.signal,
112
118
  timeout: options.timeout,
113
119
  reasoning: options.reasoning,
114
- usageTags: options.usageTags
120
+ usageTags: options.usageTags,
121
+ continueOnLength: options.continueOnLength
115
122
  })).content;
116
123
  }
117
124
  async embed(text, options = {}) {
@@ -261,7 +268,9 @@ var BedrockProvider = class {
261
268
  controls = prepareRequestControls(this.options, options);
262
269
  const response = await this.client.converseStream(await this.buildConverseRequest(messages, options, modelId, controls.signal), { abortSignal: controls.signal });
263
270
  let usage;
271
+ let streamStopReason;
264
272
  for await (const event of response.stream || []) {
273
+ if (event.messageStop?.stopReason) streamStopReason = event.messageStop.stopReason;
265
274
  const text = event.contentBlockDelta?.delta?.text;
266
275
  if (text) {
267
276
  if (options.onProgress) options.onProgress(text);
@@ -273,6 +282,7 @@ var BedrockProvider = class {
273
282
  totalTokens: event.metadata.usage.totalTokens || 0
274
283
  };
275
284
  }
285
+ options.onFinishReason?.(this.mapBedrockFinishReason(streamStopReason) ?? "stop");
276
286
  emitUsage(this.options, "bedrock", "stream", modelId || "unknown", usage, startTime, options.usageTags);
277
287
  } catch (error) {
278
288
  if (controls?.didTimeout()) throw new AIError(`AI request timed out after ${controls.timeout}ms`, "AI_TIMEOUT", "bedrock", options.model);
@@ -456,7 +466,12 @@ var BedrockProvider = class {
456
466
  }
457
467
  async buildConverseRequest(messages, options, modelId, signal) {
458
468
  const { system, bedrockMessages } = await this.mapMessagesToBedrock(messages, signal);
459
- const systemPrompt = options.responseFormat?.type === "json_object" ? [system, "Respond with valid JSON only. Do not include explanatory text outside the JSON object."].filter(Boolean).join("\n\n") : system;
469
+ const toolConfig = this.mapToolConfig(options, bedrockMessages);
470
+ const systemPrompt = [
471
+ system,
472
+ options.responseFormat?.type === "json_object" ? "Respond with valid JSON only. Do not include explanatory text outside the JSON object." : void 0,
473
+ toolConfig && (options.toolChoice === "none" || !options.tools?.length) ? NO_TOOL_CALLS_INSTRUCTION : void 0
474
+ ].filter(Boolean).join("\n\n");
460
475
  const inferenceConfig = Object.fromEntries(Object.entries({
461
476
  maxTokens: options.maxTokens,
462
477
  temperature: options.temperature,
@@ -473,7 +488,6 @@ var BedrockProvider = class {
473
488
  type: "enabled",
474
489
  budget_tokens: options.reasoning?.maxTokens
475
490
  } };
476
- const toolConfig = this.mapToolConfig(options);
477
491
  if (toolConfig) request.toolConfig = toolConfig;
478
492
  return request;
479
493
  }
@@ -486,9 +500,23 @@ var BedrockProvider = class {
486
500
  system = system ? `${system}\n\n${textContent}` : textContent;
487
501
  continue;
488
502
  }
503
+ if (message.role === "tool" && message.tool_call_id) {
504
+ const block = { toolResult: {
505
+ toolUseId: message.tool_call_id,
506
+ content: [{ text: textContent }]
507
+ } };
508
+ const previous = bedrockMessages[bedrockMessages.length - 1];
509
+ if (previous?.role === "user" && previous.content.every((part) => part.toolResult)) previous.content.push(block);
510
+ else bedrockMessages.push({
511
+ role: "user",
512
+ content: [block]
513
+ });
514
+ continue;
515
+ }
489
516
  const content = [];
490
- if (typeof message.content === "string") content.push({ text: message.content });
491
- else for (const part of message.content) {
517
+ if (typeof message.content === "string") {
518
+ if (message.content) content.push({ text: message.content });
519
+ } else for (const part of message.content) {
492
520
  if (part.type === "text") {
493
521
  content.push({ text: part.text });
494
522
  continue;
@@ -545,17 +573,39 @@ var BedrockProvider = class {
545
573
  default: return "stop";
546
574
  }
547
575
  }
548
- mapToolConfig(options) {
549
- if (!options.tools || options.tools.length === 0) return;
550
- if (options.toolChoice === "none") return;
551
- return {
552
- tools: options.tools.map((tool) => ({ toolSpec: {
553
- name: tool.function.name,
554
- description: tool.function.description || "",
555
- inputSchema: { json: tool.function.parameters || { type: "object" } }
556
- } })),
557
- ...options.toolChoice && { toolChoice: this.mapToolChoice(options.toolChoice) }
558
- };
576
+ /**
577
+ * Builds the Converse `toolConfig`.
578
+ *
579
+ * Converse rejects a request whose history contains `toolUse` or
580
+ * `toolResult` blocks unless `toolConfig` is present, and it has no "none"
581
+ * tool choice. So:
582
+ * - declared tools are always sent; `toolChoice: 'none'` omits the
583
+ * `toolChoice` field and the caller adds {@link NO_TOOL_CALLS_INSTRUCTION}
584
+ * to the system prompt (an instruction, not a hard guarantee);
585
+ * - with no declared tools, a history that uses tools (a tool loop's final,
586
+ * tool-less round) gets a minimal spec for each tool it references, so
587
+ * the request is valid, again with the no-tool-calls instruction.
588
+ */
589
+ mapToolConfig(options, bedrockMessages) {
590
+ if (options.tools && options.tools.length > 0) {
591
+ const toolChoice = options.toolChoice && options.toolChoice !== "none" ? this.mapToolChoice(options.toolChoice) : void 0;
592
+ return {
593
+ tools: options.tools.map((tool) => ({ toolSpec: {
594
+ name: tool.function.name,
595
+ description: tool.function.description || "",
596
+ inputSchema: { json: tool.function.parameters || { type: "object" } }
597
+ } })),
598
+ ...toolChoice && { toolChoice }
599
+ };
600
+ }
601
+ const historyToolNames = /* @__PURE__ */ new Set();
602
+ for (const message of bedrockMessages) for (const block of message.content) if (block.toolUse?.name) historyToolNames.add(block.toolUse.name);
603
+ if (historyToolNames.size === 0) return;
604
+ return { tools: [...historyToolNames].map((name) => ({ toolSpec: {
605
+ name,
606
+ description: "Used earlier in this conversation; not available for this turn.",
607
+ inputSchema: { json: { type: "object" } }
608
+ } })) };
559
609
  }
560
610
  mapToolChoice(toolChoice) {
561
611
  if (!toolChoice || toolChoice === "auto") return { auto: {} };
@@ -702,7 +752,7 @@ var BedrockProvider = class {
702
752
  if (typeof error === "object" && error !== null) {
703
753
  const awsError = error;
704
754
  if (awsError.name === "AccessDeniedException") return new AuthenticationError("bedrock");
705
- if (awsError.name === "ThrottlingException") return new RateLimitError("bedrock");
755
+ if (awsError.name === "ThrottlingException") return rateLimitErrorFrom("bedrock", error);
706
756
  if (awsError.name === "ResourceNotFoundException") return new ModelNotFoundError(awsError.message || "Model not found", "bedrock");
707
757
  if (awsError.name === "ValidationException" && awsError.message?.includes("input is too long")) return new ContextLengthError("bedrock");
708
758
  }
@@ -712,4 +762,4 @@ var BedrockProvider = class {
712
762
  //#endregion
713
763
  export { BedrockProvider };
714
764
 
715
- //# sourceMappingURL=bedrock-Bv1qCquH.js.map
765
+ //# sourceMappingURL=bedrock-BQi3Z9jR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bedrock-BQi3Z9jR.js","names":[],"sources":["../../src/shared/providers/bedrock.ts"],"sourcesContent":["/**\n * AWS Bedrock provider implementation\n */\n\nimport { rateLimitErrorFrom } from '../rate-limit';\nimport {\n normalizeBaseAIOptions,\n normalizeChatOptions,\n normalizeImageGenerationOptions,\n type PreparedRequestControls,\n prepareRequestControls,\n} from '../safety';\nimport type {\n AICapabilities,\n AIInterface,\n AIMessage,\n AIModel,\n AIResponse,\n BedrockOptions,\n ChatOptions,\n CompletionOptions,\n EmbeddingOptions,\n EmbeddingResponse,\n ImageDescriptionOptions,\n ImageEmbeddingOptions,\n ImageGenerationOptions,\n ImageGenerationResponse,\n MessageOptions,\n TokenUsage,\n TTSOptions,\n TTSResponse,\n VideoGenerationJob,\n VideoGenerationOptions,\n VideoGenerationResult,\n VideoGenerationStatusResult,\n Voice,\n VoiceCloneOptions,\n VoiceDesignOptions,\n VoiceListOptions,\n} from '../types';\nimport {\n AIError,\n AuthenticationError,\n ContextLengthError,\n extractTextContent,\n ModelNotFoundError,\n} from '../types';\nimport { emitUsage } from './usage';\n\nconst BEDROCK_DEFAULT_CHAT_MODEL = 'anthropic.claude-3-5-sonnet-20241022-v2:0';\nconst BEDROCK_TEXT_EMBEDDING_MODEL = 'amazon.titan-embed-text-v2:0';\nconst BEDROCK_IMAGE_EMBEDDING_MODEL = 'amazon.titan-embed-image-v1';\nconst BEDROCK_IMAGE_GENERATION_MODEL = 'amazon.titan-image-generator-v2:0';\n\n/**\n * System instruction standing in for a \"none\" tool choice, which Converse\n * lacks, when tools must still be declared (see `mapToolConfig`).\n */\nconst NO_TOOL_CALLS_INSTRUCTION =\n 'Do not call any tools in this response. Answer in text using the information already in the conversation.';\n\nexport class BedrockProvider implements AIInterface {\n private options: BedrockOptions;\n private client: any; // Will be BedrockRuntimeClient instance from @aws-sdk/client-bedrock-runtime\n\n constructor(options: BedrockOptions) {\n this.options = normalizeBaseAIOptions({\n defaultModel: BEDROCK_DEFAULT_CHAT_MODEL,\n ...options,\n });\n\n // Initialize AWS Bedrock client\n this.initializeClientSync();\n }\n\n private initializeClientSync() {\n try {\n // Dynamic import in constructor - this will work if the package is installed\n import('@aws-sdk/client-bedrock-runtime')\n .then(({ BedrockRuntimeClient }) => {\n this.client = new BedrockRuntimeClient({\n region: this.options.region,\n credentials: this.options.credentials,\n endpoint: this.options.endpoint,\n maxAttempts: (this.options.maxRetries || 0) + 1,\n });\n })\n .catch(() => {\n // Client will be null and we'll handle it in methods\n });\n } catch (_error) {\n // Client will be null and we'll handle it in methods\n }\n }\n\n private async ensureClient() {\n if (!this.client) {\n try {\n const { BedrockRuntimeClient } = await import(\n '@aws-sdk/client-bedrock-runtime'\n );\n this.client = new BedrockRuntimeClient({\n region: this.options.region,\n credentials: this.options.credentials,\n endpoint: this.options.endpoint,\n maxAttempts: (this.options.maxRetries || 0) + 1,\n });\n } catch (_error) {\n throw new AIError(\n 'Failed to initialize Bedrock client. Make sure @aws-sdk/client-bedrock-runtime is installed.',\n 'INITIALIZATION_ERROR',\n 'bedrock',\n );\n }\n }\n }\n\n async chat(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): Promise<AIResponse> {\n const startTime = Date.now();\n let controls: PreparedRequestControls | undefined;\n try {\n await this.ensureClient();\n\n const modelId = options.model || this.options.defaultModel;\n options = normalizeChatOptions(this.options, options, 'bedrock', modelId);\n controls = prepareRequestControls(this.options, options);\n const response = this.mapConverseResponse(\n await this.client.converse(\n await this.buildConverseRequest(\n messages,\n options,\n modelId!,\n controls.signal,\n ),\n { abortSignal: controls.signal },\n ),\n modelId!,\n );\n\n emitUsage(\n this.options,\n 'bedrock',\n 'chat',\n response.model || modelId || 'unknown',\n response.usage,\n startTime,\n options.usageTags,\n );\n return response;\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'bedrock',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'bedrock',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n async complete(\n prompt: string,\n options: CompletionOptions = {},\n ): Promise<AIResponse> {\n return this.chat([{ role: 'user', content: prompt }], {\n model: options.model,\n maxTokens: options.maxTokens,\n temperature: options.temperature,\n topP: options.topP,\n n: options.n,\n stop: options.stop,\n stream: options.stream,\n onProgress: options.onProgress,\n signal: options.signal,\n timeout: options.timeout,\n reasoning: options.reasoning,\n usageTags: options.usageTags,\n continueOnLength: options.continueOnLength,\n });\n }\n\n /**\n * Simple message interface for single-turn interactions with optional history\n *\n * @param text - The message text to send\n * @param options - Configuration options including history, model, etc.\n * @returns Promise resolving to the response content string\n */\n async message(text: string, options: MessageOptions = {}): Promise<string> {\n // Build messages array from history + current message\n const messages: AIMessage[] = [\n ...(options.history || []),\n { role: options.role || 'user', content: text },\n ];\n\n const response = await this.chat(messages, {\n model: options.model,\n maxTokens: options.maxTokens,\n temperature: options.temperature,\n topP: options.topP,\n stop: options.stop,\n stream: options.stream,\n frequencyPenalty: options.frequencyPenalty,\n presencePenalty: options.presencePenalty,\n responseFormat: options.responseFormat,\n seed: options.seed,\n tools: options.tools,\n toolChoice: options.toolChoice,\n onProgress: options.onProgress,\n signal: options.signal,\n timeout: options.timeout,\n reasoning: options.reasoning,\n usageTags: options.usageTags,\n continueOnLength: options.continueOnLength,\n });\n\n return response.content;\n }\n\n async embed(\n text: string | string[],\n options: EmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n const startTime = Date.now();\n try {\n await this.ensureClient();\n\n const model = options.model || BEDROCK_TEXT_EMBEDDING_MODEL;\n const inputs = Array.isArray(text) ? text : [text];\n const embeddings: number[][] = [];\n let totalTokens = 0;\n\n for (const inputText of inputs) {\n const response = await this.client.invokeModel({\n modelId: model,\n contentType: 'application/json',\n accept: 'application/json',\n body: JSON.stringify({\n inputText,\n ...(options.dimensions && { dimensions: options.dimensions }),\n normalize: true,\n }),\n });\n\n const payload = await this.parseInvokeModelBody(response.body);\n const embedding = this.extractEmbeddingVector(payload);\n if (embedding) {\n embeddings.push(embedding);\n }\n\n totalTokens +=\n payload.inputTextTokenCount ||\n payload.inputTokenCount ||\n payload.tokenCount ||\n 0;\n }\n\n const usage: TokenUsage | undefined =\n totalTokens > 0\n ? {\n promptTokens: totalTokens,\n completionTokens: 0,\n totalTokens,\n }\n : undefined;\n\n emitUsage(\n this.options,\n 'bedrock',\n 'embed',\n model,\n usage,\n startTime,\n options.usageTags,\n );\n\n return {\n embeddings,\n model,\n usage,\n };\n } catch (error) {\n throw this.mapError(error);\n }\n }\n\n async embedImage(\n image: string | Buffer,\n options: ImageEmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n const startTime = Date.now();\n try {\n await this.ensureClient();\n\n const model = options.model || BEDROCK_IMAGE_EMBEDDING_MODEL;\n const response = await this.client.invokeModel({\n modelId: model,\n contentType: 'application/json',\n accept: 'application/json',\n body: JSON.stringify({\n inputImage: await this.imageToBase64(image),\n ...(options.dimensions && {\n embeddingConfig: {\n outputEmbeddingLength: options.dimensions,\n },\n }),\n }),\n });\n\n const payload = await this.parseInvokeModelBody(response.body);\n const embedding = this.extractEmbeddingVector(payload);\n\n emitUsage(\n this.options,\n 'bedrock',\n 'embedImage',\n model,\n undefined,\n startTime,\n );\n\n return {\n embeddings: embedding ? [embedding] : [],\n model,\n };\n } catch (error) {\n throw this.mapError(error);\n }\n }\n\n async describeImage(\n image: string | Buffer,\n prompt?: string,\n options: ImageDescriptionOptions = {},\n ): Promise<string> {\n const imageUrl = await this.imageToDataUrl(image, options.signal);\n const response = await this.chat(\n [\n {\n role: 'user',\n content: [\n {\n type: 'text',\n text:\n prompt ||\n 'Describe this image for a search index. Include objects, mood, lighting, and any visible text.',\n },\n {\n type: 'image_url',\n image_url: { url: imageUrl },\n },\n ],\n },\n ],\n {\n model: options.model || this.options.defaultModel,\n maxTokens: options.maxTokens ?? 500,\n signal: options.signal,\n timeout: options.timeout,\n reasoning: options.reasoning,\n usageTags: options.usageTags,\n },\n );\n\n return response.content;\n }\n\n async generateImage(\n prompt: string,\n options: ImageGenerationOptions = {},\n ): Promise<ImageGenerationResponse> {\n let controls: PreparedRequestControls | undefined;\n try {\n await this.ensureClient();\n\n const model = options.model || BEDROCK_IMAGE_GENERATION_MODEL;\n options = normalizeImageGenerationOptions(\n this.options,\n options,\n 'bedrock',\n model,\n );\n controls = prepareRequestControls(this.options, options);\n const size = this.resolveImageSize(options);\n const response = await this.client.invokeModel(\n {\n modelId: model,\n contentType: 'application/json',\n accept: 'application/json',\n body: JSON.stringify({\n taskType: 'TEXT_IMAGE',\n textToImageParams: {\n text: prompt,\n ...(options.imageInput && {\n conditionImage: await this.imageToBase64(\n options.imageInput,\n controls.signal,\n ),\n }),\n },\n imageGenerationConfig: {\n numberOfImages: options.n,\n quality: this.mapImageQuality(options.quality),\n ...size,\n },\n }),\n },\n { abortSignal: controls.signal },\n );\n\n const payload = await this.parseInvokeModelBody(response.body);\n if (payload.error) {\n throw new AIError(payload.error, 'API_ERROR', 'bedrock');\n }\n\n const images = (payload.images || []).map((encoded: string) => {\n const mimeType = 'image/png';\n if (options.outputFormat === 'base64') {\n return { data: encoded, mimeType };\n }\n if (options.outputFormat === 'url') {\n return { data: `data:${mimeType};base64,${encoded}`, mimeType };\n }\n return {\n data: Buffer.from(encoded, 'base64'),\n mimeType,\n };\n });\n\n return {\n images,\n model,\n };\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'bedrock',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'bedrock',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n async *stream(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): AsyncIterable<string> {\n const startTime = Date.now();\n let controls: PreparedRequestControls | undefined;\n try {\n await this.ensureClient();\n\n const modelId = options.model || this.options.defaultModel;\n options = normalizeChatOptions(this.options, options, 'bedrock', modelId);\n controls = prepareRequestControls(this.options, options);\n const response = await this.client.converseStream(\n await this.buildConverseRequest(\n messages,\n options,\n modelId!,\n controls.signal,\n ),\n { abortSignal: controls.signal },\n );\n\n let usage: TokenUsage | undefined;\n let streamStopReason: string | null | undefined;\n\n for await (const event of response.stream || []) {\n if (event.messageStop?.stopReason) {\n streamStopReason = event.messageStop.stopReason;\n }\n const text = event.contentBlockDelta?.delta?.text;\n if (text) {\n if (options.onProgress) {\n options.onProgress(text);\n }\n yield text;\n }\n\n if (event.metadata?.usage) {\n usage = {\n promptTokens: event.metadata.usage.inputTokens || 0,\n completionTokens: event.metadata.usage.outputTokens || 0,\n totalTokens: event.metadata.usage.totalTokens || 0,\n };\n }\n }\n\n options.onFinishReason?.(\n this.mapBedrockFinishReason(streamStopReason) ?? 'stop',\n );\n\n emitUsage(\n this.options,\n 'bedrock',\n 'stream',\n modelId || 'unknown',\n usage,\n startTime,\n options.usageTags,\n );\n } catch (error) {\n if (controls?.didTimeout()) {\n throw new AIError(\n `AI request timed out after ${controls.timeout}ms`,\n 'AI_TIMEOUT',\n 'bedrock',\n options.model,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'AI request aborted by caller',\n 'AI_ABORTED',\n 'bedrock',\n options.model,\n );\n }\n throw this.mapError(error);\n } finally {\n controls?.cleanup();\n }\n }\n\n async countTokens(text: string): Promise<number> {\n try {\n await this.ensureClient();\n\n const modelId = this.options.defaultModel || BEDROCK_DEFAULT_CHAT_MODEL;\n const response = await this.client.countTokens({\n modelId,\n input: {\n converse: {\n messages: [\n {\n role: 'user',\n content: [{ text }],\n },\n ],\n },\n },\n });\n\n return response.inputTokens || Math.ceil(text.length / 4);\n } catch (error) {\n throw this.mapError(error);\n }\n }\n\n async getModels(): Promise<AIModel[]> {\n // Return static list of popular Bedrock models\n return [\n // Anthropic Claude models\n {\n id: 'anthropic.claude-3-5-sonnet-20241022-v2:0',\n name: 'Claude 3.5 Sonnet v2',\n description: 'Latest Claude 3.5 Sonnet model on Bedrock',\n contextLength: 200000,\n capabilities: ['text', 'chat', 'vision', 'functions'],\n supportsFunctions: true,\n supportsVision: true,\n },\n {\n id: 'anthropic.claude-3-opus-20240229-v1:0',\n name: 'Claude 3 Opus',\n description: 'Most powerful Claude model on Bedrock',\n contextLength: 200000,\n capabilities: ['text', 'chat', 'vision'],\n supportsFunctions: false,\n supportsVision: true,\n },\n // Amazon Titan models\n {\n id: 'amazon.titan-text-premier-v1:0',\n name: 'Titan Text Premier',\n description: 'Premier Amazon Titan text model',\n contextLength: 32000,\n capabilities: ['text', 'chat'],\n supportsFunctions: false,\n supportsVision: false,\n },\n {\n id: 'amazon.titan-embed-text-v1',\n name: 'Titan Embeddings Text',\n description: 'Amazon Titan text embeddings model',\n contextLength: 8192,\n capabilities: ['embeddings'],\n supportsFunctions: false,\n supportsVision: false,\n },\n {\n id: BEDROCK_TEXT_EMBEDDING_MODEL,\n name: 'Titan Embeddings Text V2',\n description: 'Amazon Titan text embeddings v2 model',\n contextLength: 8192,\n capabilities: ['embeddings'],\n supportsFunctions: false,\n supportsVision: false,\n },\n {\n id: BEDROCK_IMAGE_EMBEDDING_MODEL,\n name: 'Titan Multimodal Embeddings G1',\n description:\n 'Amazon Titan multimodal embeddings model for image similarity',\n contextLength: 256,\n capabilities: ['embeddings', 'image_embedding'],\n supportsFunctions: false,\n supportsVision: false,\n },\n {\n id: BEDROCK_IMAGE_GENERATION_MODEL,\n name: 'Titan Image Generator V2',\n description: 'Amazon Titan image generation model',\n contextLength: 0,\n capabilities: ['image_generation'],\n supportsFunctions: false,\n supportsVision: false,\n },\n // Cohere models\n {\n id: 'cohere.command-r-plus-v1:0',\n name: 'Command R+',\n description: 'Cohere Command R+ model with advanced capabilities',\n contextLength: 128000,\n capabilities: ['text', 'chat', 'functions'],\n supportsFunctions: true,\n supportsVision: false,\n },\n // Meta Llama models\n {\n id: 'meta.llama3-1-405b-instruct-v1:0',\n name: 'Llama 3.1 405B Instruct',\n description: 'Meta Llama 3.1 405B instruction-tuned model',\n contextLength: 128000,\n capabilities: ['text', 'chat'],\n supportsFunctions: false,\n supportsVision: false,\n },\n ];\n }\n\n async getCapabilities(): Promise<AICapabilities> {\n return {\n chat: true,\n completion: true,\n embeddings: true,\n streaming: true,\n functions: true, // Some models support function calling\n vision: true, // Some models support vision\n fineTuning: true, // Via Bedrock fine-tuning\n imageEmbeddings: true,\n imageGeneration: true,\n videoGeneration: false,\n tts: false,\n voiceCloning: false,\n voiceDesign: false,\n maxContextLength: 200000,\n supportedOperations: [\n 'chat',\n 'completion',\n 'embedding',\n 'streaming',\n 'functions',\n 'vision',\n 'image_embedding',\n 'image_generation',\n ],\n };\n }\n\n // ============================================================================\n // Video Generation Methods (Not supported - use gemini, byteplus-modelark,\n // or openai-compat-video provider)\n // ============================================================================\n\n async submitVideoGenerationJob(\n _options: VideoGenerationOptions,\n ): Promise<VideoGenerationJob> {\n throw new AIError(\n 'Video generation is not supported by Bedrock provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'bedrock',\n );\n }\n\n async getVideoGenerationJob(\n _handle: VideoGenerationJob,\n ): Promise<VideoGenerationStatusResult> {\n throw new AIError(\n 'Video generation is not supported by Bedrock provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'bedrock',\n );\n }\n\n async fetchVideoGenerationResult(\n _handle: VideoGenerationJob,\n ): Promise<VideoGenerationResult> {\n throw new AIError(\n 'Video generation is not supported by Bedrock provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'bedrock',\n );\n }\n\n async cancelVideoGenerationJob(_handle: VideoGenerationJob): Promise<void> {\n throw new AIError(\n 'Video generation is not supported by Bedrock provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'bedrock',\n );\n }\n\n async validateVideoGenerationAccess(): Promise<boolean> {\n throw new AIError(\n 'Video generation is not supported by Bedrock provider. Use gemini, byteplus-modelark, or openai-compat-video provider.',\n 'NOT_IMPLEMENTED',\n 'bedrock',\n );\n }\n\n // ============================================================================\n // TTS Methods (Not supported - use Qwen3-TTS provider)\n // ============================================================================\n\n async synthesizeSpeech(\n _text: string,\n _options?: TTSOptions,\n ): Promise<TTSResponse> {\n throw new AIError(\n 'TTS is not supported by Bedrock provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'bedrock',\n );\n }\n\n streamSpeech(_text: string, _options?: TTSOptions): AsyncIterable<Buffer> {\n const error = new AIError(\n 'TTS streaming is not supported by Bedrock provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'bedrock',\n );\n return {\n [Symbol.asyncIterator]: () => ({\n next: () => Promise.reject(error),\n }),\n };\n }\n\n async cloneVoice(_options: VoiceCloneOptions): Promise<Voice> {\n throw new AIError(\n 'Voice cloning is not supported by Bedrock provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'bedrock',\n );\n }\n\n async designVoice(_options: VoiceDesignOptions): Promise<Voice> {\n throw new AIError(\n 'Voice design is not supported by Bedrock provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'bedrock',\n );\n }\n\n async getVoices(_options?: VoiceListOptions): Promise<Voice[]> {\n throw new AIError(\n 'Voice listing is not supported by Bedrock provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'bedrock',\n );\n }\n\n private async buildConverseRequest(\n messages: AIMessage[],\n options: ChatOptions,\n modelId: string,\n signal?: AbortSignal,\n ): Promise<Record<string, any>> {\n const { system, bedrockMessages } = await this.mapMessagesToBedrock(\n messages,\n signal,\n );\n const toolConfig = this.mapToolConfig(options, bedrockMessages);\n const systemPrompt = [\n system,\n options.responseFormat?.type === 'json_object'\n ? 'Respond with valid JSON only. Do not include explanatory text outside the JSON object.'\n : undefined,\n toolConfig && (options.toolChoice === 'none' || !options.tools?.length)\n ? NO_TOOL_CALLS_INSTRUCTION\n : undefined,\n ]\n .filter(Boolean)\n .join('\\n\\n');\n\n const inferenceConfig = Object.fromEntries(\n Object.entries({\n maxTokens: options.maxTokens,\n temperature: options.temperature,\n topP: options.topP,\n stopSequences: Array.isArray(options.stop)\n ? options.stop\n : options.stop\n ? [options.stop]\n : undefined,\n }).filter(([, value]) => value !== undefined),\n );\n\n const request: Record<string, any> = {\n modelId,\n messages: bedrockMessages,\n ...(Object.keys(inferenceConfig).length > 0 && { inferenceConfig }),\n ...(systemPrompt && { system: [{ text: systemPrompt }] }),\n };\n if ((options.reasoning?.maxTokens || 0) > 0) {\n request.additionalModelRequestFields = {\n thinking: {\n type: 'enabled',\n budget_tokens: options.reasoning?.maxTokens,\n },\n };\n }\n\n if (toolConfig) {\n request.toolConfig = toolConfig;\n }\n\n return request;\n }\n\n private async mapMessagesToBedrock(\n messages: AIMessage[],\n signal?: AbortSignal,\n ): Promise<{\n system?: string;\n bedrockMessages: Array<{ role: 'user' | 'assistant'; content: any[] }>;\n }> {\n let system: string | undefined;\n const bedrockMessages: Array<{\n role: 'user' | 'assistant';\n content: any[];\n }> = [];\n\n for (const message of messages) {\n const textContent = extractTextContent(message.content);\n if (message.role === 'system') {\n system = system ? `${system}\\n\\n${textContent}` : textContent;\n continue;\n }\n\n if (message.role === 'tool' && message.tool_call_id) {\n // Converse pairs results with calls by toolUseId, and all results\n // for one assistant turn must share the following user turn.\n const block = {\n toolResult: {\n toolUseId: message.tool_call_id,\n content: [{ text: textContent }],\n },\n };\n const previous = bedrockMessages[bedrockMessages.length - 1];\n if (\n previous?.role === 'user' &&\n previous.content.every((part) => part.toolResult)\n ) {\n previous.content.push(block);\n } else {\n bedrockMessages.push({ role: 'user', content: [block] });\n }\n continue;\n }\n\n const content: any[] = [];\n if (typeof message.content === 'string') {\n // Converse rejects empty text blocks (e.g. tool-call-only turns).\n if (message.content) content.push({ text: message.content });\n } else {\n for (const part of message.content) {\n if (part.type === 'text') {\n content.push({ text: part.text });\n continue;\n }\n\n const image = await this.imageUrlToBedrockImage(\n part.image_url.url,\n signal,\n );\n content.push({ image });\n }\n }\n\n if (message.role === 'assistant' && message.tool_calls) {\n for (const toolCall of message.tool_calls) {\n content.push({\n toolUse: {\n toolUseId: toolCall.id,\n name: toolCall.function.name,\n input: this.safeJsonParse(toolCall.function.arguments),\n },\n });\n }\n }\n\n if (content.length === 0 && textContent) {\n content.push({ text: textContent });\n }\n\n bedrockMessages.push({\n role: message.role === 'assistant' ? 'assistant' : 'user',\n content,\n });\n }\n\n return { system, bedrockMessages };\n }\n\n private mapConverseResponse(response: any, modelId: string): AIResponse {\n const contentBlocks = response.output?.message?.content || [];\n const textContent = contentBlocks\n .filter((block: any) => typeof block.text === 'string')\n .map((block: any) => block.text)\n .join('');\n\n const toolCalls = contentBlocks\n .filter((block: any) => block.toolUse)\n .map((block: any) => ({\n id: block.toolUse.toolUseId,\n type: 'function' as const,\n function: {\n name: block.toolUse.name,\n arguments: JSON.stringify(block.toolUse.input || {}),\n },\n }));\n\n const usage =\n response.usage &&\n ({\n promptTokens: response.usage.inputTokens || 0,\n completionTokens: response.usage.outputTokens || 0,\n totalTokens: response.usage.totalTokens || 0,\n } satisfies TokenUsage);\n\n return {\n content: textContent,\n model: modelId,\n finishReason: this.mapBedrockFinishReason(response.stopReason),\n usage,\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n };\n }\n\n private mapBedrockFinishReason(\n reason: string | null | undefined,\n ): AIResponse['finishReason'] {\n switch (reason) {\n case 'end_turn':\n return 'stop';\n case 'max_tokens':\n return 'length';\n case 'stop_sequence':\n return 'stop';\n case 'tool_use':\n return 'tool_calls';\n default:\n return 'stop';\n }\n }\n\n /**\n * Builds the Converse `toolConfig`.\n *\n * Converse rejects a request whose history contains `toolUse` or\n * `toolResult` blocks unless `toolConfig` is present, and it has no \"none\"\n * tool choice. So:\n * - declared tools are always sent; `toolChoice: 'none'` omits the\n * `toolChoice` field and the caller adds {@link NO_TOOL_CALLS_INSTRUCTION}\n * to the system prompt (an instruction, not a hard guarantee);\n * - with no declared tools, a history that uses tools (a tool loop's final,\n * tool-less round) gets a minimal spec for each tool it references, so\n * the request is valid, again with the no-tool-calls instruction.\n */\n private mapToolConfig(\n options: ChatOptions,\n bedrockMessages: Array<{ role: 'user' | 'assistant'; content: any[] }>,\n ): Record<string, any> | undefined {\n if (options.tools && options.tools.length > 0) {\n const toolChoice =\n options.toolChoice && options.toolChoice !== 'none'\n ? this.mapToolChoice(options.toolChoice)\n : undefined;\n return {\n tools: options.tools.map((tool) => ({\n toolSpec: {\n name: tool.function.name,\n description: tool.function.description || '',\n inputSchema: {\n json: tool.function.parameters || { type: 'object' },\n },\n },\n })),\n ...(toolChoice && { toolChoice }),\n };\n }\n\n const historyToolNames = new Set<string>();\n for (const message of bedrockMessages) {\n for (const block of message.content) {\n if (block.toolUse?.name) historyToolNames.add(block.toolUse.name);\n }\n }\n if (historyToolNames.size === 0) {\n return undefined;\n }\n\n return {\n tools: [...historyToolNames].map((name) => ({\n toolSpec: {\n name,\n description:\n 'Used earlier in this conversation; not available for this turn.',\n inputSchema: { json: { type: 'object' } },\n },\n })),\n };\n }\n\n private mapToolChoice(\n toolChoice?:\n | 'auto'\n | 'none'\n | { type: 'function'; function: { name: string } },\n ): Record<string, any> | undefined {\n if (!toolChoice || toolChoice === 'auto') {\n return { auto: {} };\n }\n\n if (toolChoice === 'none') {\n return undefined;\n }\n\n return {\n tool: {\n name: toolChoice.function.name,\n },\n };\n }\n\n private async parseInvokeModelBody(body: unknown): Promise<any> {\n const bytes =\n typeof (body as any)?.transformToByteArray === 'function'\n ? await (body as any).transformToByteArray()\n : body instanceof Uint8Array\n ? body\n : Buffer.isBuffer(body)\n ? body\n : new Uint8Array(body as ArrayBuffer);\n return JSON.parse(new TextDecoder().decode(bytes));\n }\n\n private extractEmbeddingVector(payload: any): number[] | undefined {\n if (Array.isArray(payload.embedding)) {\n return payload.embedding;\n }\n\n if (Array.isArray(payload.embeddings?.[0])) {\n return payload.embeddings[0];\n }\n\n if (Array.isArray(payload.embeddingsByType?.float)) {\n return payload.embeddingsByType.float;\n }\n\n if (Array.isArray(payload.vector)) {\n return payload.vector;\n }\n\n return undefined;\n }\n\n private async imageUrlToBedrockImage(\n imageUrl: string,\n signal?: AbortSignal,\n ): Promise<any> {\n const { bytes, mimeType } = await this.imageToBytes(imageUrl, signal);\n return {\n format: this.mimeTypeToBedrockImageFormat(mimeType),\n source: { bytes },\n };\n }\n\n private async imageToDataUrl(\n image: string | Buffer,\n signal?: AbortSignal,\n ): Promise<string> {\n if (Buffer.isBuffer(image)) {\n return `data:image/png;base64,${image.toString('base64')}`;\n }\n if (image.startsWith('data:')) {\n return image;\n }\n\n const { bytes, mimeType } = await this.imageToBytes(image, signal);\n return `data:${mimeType};base64,${Buffer.from(bytes).toString('base64')}`;\n }\n\n private async imageToBase64(\n image: string | Buffer,\n signal?: AbortSignal,\n ): Promise<string> {\n if (Buffer.isBuffer(image)) {\n return image.toString('base64');\n }\n if (image.startsWith('data:')) {\n const match = image.match(/^data:([^;]+);base64,(.+)$/);\n if (!match) {\n throw new AIError(\n 'Invalid base64 data URL format',\n 'INVALID_INPUT',\n 'bedrock',\n );\n }\n return match[2];\n }\n\n const { bytes } = await this.imageToBytes(image, signal);\n return Buffer.from(bytes).toString('base64');\n }\n\n private async imageToBytes(\n image: string,\n signal?: AbortSignal,\n ): Promise<{ bytes: Uint8Array; mimeType: string }> {\n if (image.startsWith('data:')) {\n const match = image.match(/^data:([^;]+);base64,(.+)$/);\n if (!match) {\n throw new AIError(\n 'Invalid base64 data URL format',\n 'INVALID_INPUT',\n 'bedrock',\n );\n }\n\n return {\n bytes: Uint8Array.from(Buffer.from(match[2], 'base64')),\n mimeType: match[1],\n };\n }\n\n const response = await fetch(image, { signal });\n if (!response.ok) {\n throw new AIError(\n `Failed to fetch image: ${response.status} ${response.statusText}`,\n 'IMAGE_FETCH_ERROR',\n 'bedrock',\n );\n }\n\n const arrayBuffer = await response.arrayBuffer();\n return {\n bytes: new Uint8Array(arrayBuffer),\n mimeType: response.headers.get('content-type') || 'image/png',\n };\n }\n\n private mimeTypeToBedrockImageFormat(mimeType: string): string {\n if (mimeType.includes('png')) return 'png';\n if (mimeType.includes('jpeg') || mimeType.includes('jpg')) return 'jpeg';\n if (mimeType.includes('gif')) return 'gif';\n if (mimeType.includes('webp')) return 'webp';\n\n throw new AIError(\n `Unsupported image format for Bedrock: ${mimeType}`,\n 'INVALID_INPUT',\n 'bedrock',\n );\n }\n\n private resolveImageSize(options: ImageGenerationOptions): {\n width: number;\n height: number;\n } {\n if (options.size) {\n const [width, height] = options.size.split('x').map(Number);\n if (Number.isFinite(width) && Number.isFinite(height)) {\n return { width, height };\n }\n }\n\n const aspectRatioSizes: Record<string, { width: number; height: number }> =\n {\n '1:1': { width: 1024, height: 1024 },\n '2:3': { width: 768, height: 1152 },\n '3:2': { width: 1152, height: 768 },\n '3:5': { width: 768, height: 1280 },\n '5:3': { width: 1280, height: 768 },\n '7:9': { width: 896, height: 1152 },\n '9:7': { width: 1152, height: 896 },\n '6:11': { width: 768, height: 1408 },\n '11:6': { width: 1408, height: 768 },\n '5:11': { width: 640, height: 1408 },\n '11:5': { width: 1408, height: 640 },\n '9:5': { width: 1152, height: 640 },\n '16:9': { width: 1173, height: 640 },\n };\n\n return (\n aspectRatioSizes[options.aspectRatio || ''] || {\n width: 1024,\n height: 1024,\n }\n );\n }\n\n private mapImageQuality(quality?: string): string {\n if (!quality || quality === 'standard') {\n return 'standard';\n }\n\n if (quality === 'hd') {\n return 'premium';\n }\n\n return quality;\n }\n\n private safeJsonParse(input: string): any {\n try {\n return JSON.parse(input);\n } catch {\n return { rawArguments: input };\n }\n }\n\n private mapError(error: unknown): AIError {\n if (error instanceof AIError) {\n return error;\n }\n\n // Map common AWS error codes\n if (typeof error === 'object' && error !== null) {\n const awsError = error as { name?: string; message?: string };\n\n if (awsError.name === 'AccessDeniedException') {\n return new AuthenticationError('bedrock');\n }\n\n if (awsError.name === 'ThrottlingException') {\n return rateLimitErrorFrom('bedrock', error);\n }\n\n if (awsError.name === 'ResourceNotFoundException') {\n return new ModelNotFoundError(\n awsError.message || 'Model not found',\n 'bedrock',\n );\n }\n\n if (\n awsError.name === 'ValidationException' &&\n awsError.message?.includes('input is too long')\n ) {\n return new ContextLengthError('bedrock');\n }\n }\n\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown Bedrock error occurred';\n return new AIError(errorMessage, 'UNKNOWN_ERROR', 'bedrock');\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { d as OpenAIProvider } from "./src-BUQUZK2M.js";
2
- import { o as normalizeChatOptions, s as normalizeImageGenerationOptions } from "./safety-BKswBoqy.js";
3
- import { i as resolveGatewayAdminBaseUrl, r as normalizeGatewayBaseUrl, t as BifrostAdmin } from "./gateway-admin-04mvbDHC.js";
1
+ import { d as OpenAIProvider } from "./src-CLT6r1W0.js";
2
+ import { c as normalizeChatOptions, l as normalizeImageGenerationOptions } from "./rate-limit-BzWfHA0e.js";
3
+ import { i as BifrostAdmin, n as isSpeechModel, o as normalizeGatewayBaseUrl, r as isTranscriptionModel, s as resolveGatewayAdminBaseUrl, t as isAudioModel } from "./gateway-audio-models-Dn7Wrc6P.js";
4
4
  import { ValidationError } from "@happyvertical/utils";
5
5
  //#region src/shared/providers/bifrost.ts
6
6
  var BIFROST_CAPABILITIES = {
@@ -39,7 +39,7 @@ function isImageGenerationModel(modelId) {
39
39
  return /gpt-image|dall-e|imagen|stable[-_ ]diffusion|sdxl|flux|titan-image|image-generator/i.test(modelId);
40
40
  }
41
41
  function isFilteredBifrostModel(modelId) {
42
- return /moderation|transcrib|whisper|speech|tts|rerank/i.test(modelId);
42
+ return /moderation|rerank/i.test(modelId);
43
43
  }
44
44
  function inferBifrostContextLength(modelId) {
45
45
  if (isEmbeddingModel(modelId)) return 8192;
@@ -49,13 +49,16 @@ function inferBifrostContextLength(modelId) {
49
49
  return 32768;
50
50
  }
51
51
  function inferBifrostFunctions(modelId) {
52
- if (isEmbeddingModel(modelId)) return false;
52
+ if (isEmbeddingModel(modelId) || isAudioModel(modelId)) return false;
53
53
  return /gpt|claude|gemini|command|llama|mistral|qwen|deepseek|o1|o3|o4/i.test(modelId);
54
54
  }
55
55
  function inferBifrostVision(modelId) {
56
+ if (isAudioModel(modelId)) return false;
56
57
  return /gpt-4o|gpt-4\.1|vision|claude-3|gemini|pixtral|llava|qwen.*vl|vl-/i.test(modelId);
57
58
  }
58
59
  function inferBifrostCapabilities(modelId) {
60
+ if (isTranscriptionModel(modelId)) return ["transcription"];
61
+ if (isSpeechModel(modelId)) return ["speech"];
59
62
  if (isImageGenerationModel(modelId)) return ["image_generation"];
60
63
  if (isImageEmbeddingModel(modelId)) return ["embeddings", "image_embedding"];
61
64
  if (isEmbeddingModel(modelId)) return ["embeddings"];
@@ -196,4 +199,4 @@ var BifrostProvider = class extends OpenAIProvider {
196
199
  //#endregion
197
200
  export { BifrostProvider };
198
201
 
199
- //# sourceMappingURL=bifrost-DzT2J0Lq.js.map
202
+ //# sourceMappingURL=bifrost-DsI2I4ka.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bifrost-DsI2I4ka.js","names":[],"sources":["../../src/shared/providers/bifrost.ts"],"sourcesContent":["import { ValidationError } from '@happyvertical/utils';\n\nimport {\n normalizeChatOptions,\n normalizeImageGenerationOptions,\n} from '../safety';\nimport type {\n AICapabilities,\n AIMessage,\n AIModel,\n AIResponse,\n BifrostOptions,\n ChatOptions,\n EmbeddingOptions,\n EmbeddingResponse,\n ImageDescriptionOptions,\n ImageEmbeddingOptions,\n ImageGenerationOptions,\n ImageGenerationResponse,\n} from '../types';\nimport {\n BifrostAdmin,\n normalizeGatewayBaseUrl,\n resolveGatewayAdminBaseUrl,\n} from './gateway-admin';\nimport {\n isAudioModel,\n isSpeechModel,\n isTranscriptionModel,\n} from './gateway-audio-models';\nimport { type OpenAICompatibleProfile, OpenAIProvider } from './openai';\n\nconst BIFROST_CAPABILITIES: AICapabilities = {\n chat: true,\n completion: true,\n embeddings: true,\n streaming: true,\n functions: true,\n vision: true,\n fineTuning: false,\n imageEmbeddings: true,\n imageGeneration: true,\n videoGeneration: false,\n tts: false,\n voiceCloning: false,\n voiceDesign: false,\n maxContextLength: 128000,\n supportedOperations: [\n 'chat',\n 'completion',\n 'embedding',\n 'streaming',\n 'functions',\n 'vision',\n 'image_embedding',\n 'image_generation',\n ],\n};\n\nfunction isEmbeddingModel(modelId: string): boolean {\n return /embed/i.test(modelId);\n}\n\nfunction isImageEmbeddingModel(modelId: string): boolean {\n return /titan-embed-image|multimodalembedding|image[-_]?embed|clip/i.test(\n modelId,\n );\n}\n\nfunction isImageGenerationModel(modelId: string): boolean {\n return /gpt-image|dall-e|imagen|stable[-_ ]diffusion|sdxl|flux|titan-image|image-generator/i.test(\n modelId,\n );\n}\n\nfunction isFilteredBifrostModel(modelId: string): boolean {\n return /moderation|rerank/i.test(modelId);\n}\n\nfunction inferBifrostContextLength(modelId: string): number {\n if (isEmbeddingModel(modelId)) return 8192;\n if (/gemini-1\\.5|gemini-2\\.0|gemini-2\\.5|gemini-3/i.test(modelId)) {\n return 1000000;\n }\n if (/claude/i.test(modelId)) return 200000;\n if (/gpt-4o|gpt-4\\.1|o1|o3|o4|llama|mistral|qwen|deepseek/i.test(modelId)) {\n return 128000;\n }\n return 32768;\n}\n\nfunction inferBifrostFunctions(modelId: string): boolean {\n if (isEmbeddingModel(modelId) || isAudioModel(modelId)) return false;\n return /gpt|claude|gemini|command|llama|mistral|qwen|deepseek|o1|o3|o4/i.test(\n modelId,\n );\n}\n\nfunction inferBifrostVision(modelId: string): boolean {\n if (isAudioModel(modelId)) return false;\n return /gpt-4o|gpt-4\\.1|vision|claude-3|gemini|pixtral|llava|qwen.*vl|vl-/i.test(\n modelId,\n );\n}\n\nfunction inferBifrostCapabilities(modelId: string): string[] {\n if (isTranscriptionModel(modelId)) {\n return ['transcription'];\n }\n\n if (isSpeechModel(modelId)) {\n return ['speech'];\n }\n\n if (isImageGenerationModel(modelId)) {\n return ['image_generation'];\n }\n\n if (isImageEmbeddingModel(modelId)) {\n return ['embeddings', 'image_embedding'];\n }\n\n if (isEmbeddingModel(modelId)) {\n return ['embeddings'];\n }\n\n const capabilities = ['text', 'chat'];\n\n if (inferBifrostFunctions(modelId)) {\n capabilities.push('functions');\n }\n\n if (inferBifrostVision(modelId)) {\n capabilities.push('vision');\n }\n\n return capabilities;\n}\n\nfunction ensureBifrostOptions(options: BifrostOptions): BifrostOptions {\n if (!options.baseUrl?.trim()) {\n throw new ValidationError('Bifrost baseUrl is required', {\n provider: 'bifrost',\n hint: 'Pass baseUrl like http://localhost:8080, http://localhost:8080/openai, or http://localhost:8080/v1 and optionally adminBaseUrl for governance endpoints',\n });\n }\n\n const baseUrl = normalizeGatewayBaseUrl(options.baseUrl);\n const inferenceBaseUrl = /\\/(?:openai|v1|pydanticai\\/v1)$/.test(baseUrl)\n ? baseUrl\n : `${baseUrl}/openai`;\n const headers = options.apiKey\n ? {\n ...options.headers,\n 'x-bf-vk': options.apiKey,\n 'x-api-key': options.apiKey,\n }\n : options.headers;\n\n return {\n ...options,\n baseUrl: inferenceBaseUrl,\n headers,\n };\n}\n\nconst BIFROST_PROFILE: OpenAICompatibleProfile = {\n providerLabel: 'Bifrost',\n providerName: 'bifrost',\n defaultModel: 'openai/gpt-4o-mini',\n capabilities: BIFROST_CAPABILITIES,\n describeModel: (modelId) => `Bifrost model: ${modelId}`,\n getContextLength: inferBifrostContextLength,\n getModelCapabilities: inferBifrostCapabilities,\n shouldIncludeModel: (modelId) => !isFilteredBifrostModel(modelId),\n supportsFunctions: inferBifrostFunctions,\n supportsVision: inferBifrostVision,\n};\n\ntype BifrostResolvedCapability =\n | 'chat'\n | 'vision'\n | 'embeddings'\n | 'image_generation';\n\nfunction supportsCapability(\n model: AIModel,\n capability: BifrostResolvedCapability,\n): boolean {\n if (capability === 'vision') {\n return (\n model.capabilities.includes('vision') || model.supportsVision === true\n );\n }\n\n if (capability === 'embeddings') {\n return model.capabilities.includes('embeddings');\n }\n\n if (capability === 'image_generation') {\n return model.capabilities.includes('image_generation');\n }\n\n return model.capabilities.includes('chat');\n}\n\n/**\n * Bifrost provider implementation.\n *\n * Bifrost exposes OpenAI-compatible inference and governance admin APIs. This\n * provider reuses the OpenAI-compatible transport for inference and exposes\n * `admin` for tenant project and virtual-key provisioning.\n */\nexport class BifrostProvider extends OpenAIProvider {\n readonly admin: BifrostAdmin;\n private readonly configuredDefaultModel?: string;\n private readonly resolvedModelCache = new Map<\n BifrostResolvedCapability,\n Promise<string>\n >();\n\n constructor(options: BifrostOptions) {\n const normalized = ensureBifrostOptions(options);\n super(normalized, BIFROST_PROFILE);\n const adminKey = normalized.adminApiKey || normalized.apiKey;\n const adminUsername = normalized.adminUser || normalized.adminUsername;\n this.admin = new BifrostAdmin({\n provider: 'bifrost',\n baseUrl: resolveGatewayAdminBaseUrl(\n normalized.baseUrl,\n normalized.adminUrl || normalized.adminBaseUrl,\n 'bifrost',\n ),\n apiKey: adminKey,\n username: adminUsername,\n password: normalized.adminPassword,\n headers:\n adminKey && !(adminUsername && normalized.adminPassword)\n ? {\n ...normalized.adminHeaders,\n 'x-bf-vk': adminKey,\n 'x-api-key': adminKey,\n }\n : normalized.adminHeaders,\n timeout: normalized.timeout,\n });\n this.configuredDefaultModel = normalized.defaultModel;\n }\n\n private async resolveModel(\n capability: BifrostResolvedCapability,\n explicitModel?: string,\n ): Promise<string> {\n if (explicitModel) {\n return explicitModel;\n }\n\n if (\n this.configuredDefaultModel &&\n (capability === 'chat' || capability === 'vision')\n ) {\n return this.configuredDefaultModel;\n }\n\n const cached = this.resolvedModelCache.get(capability);\n if (cached) {\n return cached;\n }\n\n const pending = this.selectModel(capability).catch((error) => {\n this.resolvedModelCache.delete(capability);\n throw error;\n });\n this.resolvedModelCache.set(capability, pending);\n return pending;\n }\n\n private async selectModel(\n capability: BifrostResolvedCapability,\n ): Promise<string> {\n const models = await super.getModels();\n const model = models.find((candidate) =>\n supportsCapability(candidate, capability),\n );\n\n if (!model) {\n throw new ValidationError(\n `No ${capability} model is available from the Bifrost gateway`,\n {\n provider: 'bifrost',\n capability,\n hint: 'Pass defaultModel explicitly or ensure the gateway returns a compatible model for this key',\n },\n );\n }\n\n return model.id;\n }\n\n async chat(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): Promise<AIResponse> {\n const safe = normalizeChatOptions(\n this.options,\n options,\n 'bifrost',\n options.model || this.options.defaultModel,\n );\n return super.chat(messages, {\n ...safe,\n model: await this.resolveModel('chat', safe.model),\n });\n }\n\n async *stream(\n messages: AIMessage[],\n options: ChatOptions = {},\n ): AsyncIterable<string> {\n const safe = normalizeChatOptions(\n this.options,\n options,\n 'bifrost',\n options.model || this.options.defaultModel,\n );\n yield* super.stream(messages, {\n ...safe,\n model: await this.resolveModel('chat', safe.model),\n });\n }\n\n async describeImage(\n image: string | Buffer,\n prompt?: string,\n options: ImageDescriptionOptions = {},\n ): Promise<string> {\n const safe = normalizeChatOptions(\n this.options,\n options,\n 'bifrost',\n options.model || this.options.defaultModel,\n );\n return super.describeImage(image, prompt, {\n ...safe,\n model: await this.resolveModel('vision', safe.model),\n });\n }\n\n async embed(\n text: string | string[],\n options: EmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n return super.embed(text, {\n ...options,\n model: await this.resolveModel('embeddings', options.model),\n });\n }\n\n async embedImage(\n image: string | Buffer,\n options: ImageEmbeddingOptions = {},\n ): Promise<EmbeddingResponse> {\n return super.embedImage(image, {\n ...options,\n model: await this.resolveModel('embeddings', options.model),\n });\n }\n\n async generateImage(\n prompt: string,\n options: ImageGenerationOptions = {},\n ): Promise<ImageGenerationResponse> {\n const safe = normalizeImageGenerationOptions(\n this.options,\n options,\n 'bifrost',\n options.model,\n );\n return super.generateImage(prompt, {\n ...safe,\n model: await this.resolveModel('image_generation', safe.model),\n });\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,5 @@
1
- import { r as AuthenticationError, s as RateLimitError, t as AIError } from "./types-BpnNcTU1.js";
2
- import { n as extractRetryAfterSeconds } from "./rate-limit-BVW_1Tey.js";
3
- import { a as normalizeBaseAIOptions } from "./safety-BKswBoqy.js";
1
+ import { r as AuthenticationError, t as AIError } from "./types-DB5W6_F-.js";
2
+ import { n as rateLimitErrorFrom, s as normalizeBaseAIOptions } from "./rate-limit-BzWfHA0e.js";
4
3
  import { t as emitUsage } from "./usage-C1Y1Nlg4.js";
5
4
  //#region src/shared/providers/byteplus-modelark.ts
6
5
  /**
@@ -237,7 +236,10 @@ var ByteplusModelArkProvider = class {
237
236
  if (!response.ok) {
238
237
  const errorText = await response.text();
239
238
  if (response.status === 401 || response.status === 403) throw new AuthenticationError("byteplus-modelark");
240
- if (response.status === 429) throw new RateLimitError("byteplus-modelark", extractRetryAfterSeconds({ headers: response.headers }));
239
+ if (response.status === 429) throw rateLimitErrorFrom("byteplus-modelark", {
240
+ headers: response.headers,
241
+ message: errorText
242
+ });
241
243
  throw new AIError(`ModelArk request to ${path} failed: ${response.status} ${errorText}`, "MODELARK_REQUEST_FAILED", "byteplus-modelark");
242
244
  }
243
245
  if (response.status === 204) return {};
@@ -470,4 +472,4 @@ var ByteplusModelArkProvider = class {
470
472
  //#endregion
471
473
  export { ByteplusModelArkProvider };
472
474
 
473
- //# sourceMappingURL=byteplus-modelark-BIEXaTWw.js.map
475
+ //# sourceMappingURL=byteplus-modelark-Dq8AgCQD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"byteplus-modelark-Dq8AgCQD.js","names":[],"sources":["../../src/shared/providers/byteplus-modelark.ts"],"sourcesContent":["/**\n * BytePlus ModelArk (Seedance) video-generation provider implementation\n *\n * Raw-HTTP provider following the `qwen3-tts` precedent: no vendor SDK, just\n * the ModelArk video-generation task API (create task / poll / fetch /\n * cancel). This provider is video-generation only; it throws\n * `NOT_IMPLEMENTED` for chat, embeddings, and other text/TTS operations.\n *\n * The base URL, endpoint paths (`/contents/generations/tasks`), request/\n * response field names, and the `queued|running|cancelled|succeeded|failed|\n * expired` status enum were confirmed directly against BytePlus's own\n * published docs and blog examples at the time this was written (see the\n * link below). The `expired` status, the `page_num`/`page_size`/`filter.*`\n * list query params, and the DELETE-as-cancel-or-delete semantics\n * (`queued` → cancelled, `running` → rejected, terminal → deleted) are\n * corroborated from that same documentation but have not been exercised\n * against a live ModelArk account by this package's test suite — see\n * `packages/ai/src/byteplus-modelark.integration.test.ts` for an opt-in\n * check (skipped unless `MODELARK_API_KEY` is set) that exercises those\n * specifics against the real API.\n *\n * @see https://docs.byteplus.com/en/docs/ModelArk/Video_Generation_API\n */\n\nimport { rateLimitErrorFrom } from '../rate-limit';\nimport { normalizeBaseAIOptions } from '../safety';\nimport type {\n AICapabilities,\n AIInterface,\n AIMessage,\n AIModel,\n AIResponse,\n ByteplusModelArkOptions,\n ChatOptions,\n CompletionOptions,\n EmbeddingOptions,\n EmbeddingResponse,\n ImageDescriptionOptions,\n ImageEmbeddingOptions,\n ImageGenerationOptions,\n ImageGenerationResponse,\n MessageOptions,\n TTSOptions,\n TTSResponse,\n VideoGenerationJob,\n VideoGenerationOptions,\n VideoGenerationReferenceImage,\n VideoGenerationResult,\n VideoGenerationStatusResult,\n Voice,\n VoiceCloneOptions,\n VoiceDesignOptions,\n VoiceListOptions,\n} from '../types';\nimport { AIError, AuthenticationError } from '../types';\nimport { emitUsage } from './usage';\n\nconst DEFAULT_MODELARK_BASE_URL =\n 'https://ark.ap-southeast.bytepluses.com/api/v3';\nconst DEFAULT_MODELARK_MODEL = 'seedance-1-0-lite-t2v-250428';\nconst DEFAULT_MODELARK_I2V_MODEL = 'seedance-1-0-lite-i2v-250428';\n/** Burst capacity for the submit token bucket — see {@link SubmitRateLimiter}. */\nconst SUBMIT_BURST_CAPACITY = 2;\n\ntype ModelArkTaskStatus =\n | 'queued'\n | 'running'\n | 'cancelled'\n | 'succeeded'\n | 'failed'\n | 'expired';\n\ninterface ModelArkContentItem {\n type: 'text' | 'image_url';\n text?: string;\n image_url?: { url: string };\n role?: string;\n}\n\ninterface ModelArkCreateTaskRequest {\n model: string;\n content: ModelArkContentItem[];\n resolution?: string;\n ratio?: string;\n duration?: number;\n seed?: number;\n}\n\ninterface ModelArkCreateTaskResponse {\n id: string;\n}\n\ninterface ModelArkTaskResponse {\n id: string;\n model: string;\n status: ModelArkTaskStatus;\n content?: { video_url?: string; last_frame_url?: string };\n error?: { code: string; message: string } | null;\n created_at: number;\n updated_at: number;\n seed?: number;\n resolution?: string;\n ratio?: string;\n duration?: number;\n}\n\n/**\n * Resolve after `ms` milliseconds, or as soon as `signal` aborts —\n * whichever comes first. Never rejects; callers re-check `signal.aborted`\n * themselves immediately after, so a single check covers both \"timed out\n * normally\" and \"woke up early because of an abort.\"\n */\nfunction delayOrAbort(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n if (signal?.aborted) {\n resolve();\n return;\n }\n const timer = setTimeout(resolve, ms);\n signal?.addEventListener(\n 'abort',\n () => {\n clearTimeout(timer);\n resolve();\n },\n { once: true },\n );\n });\n}\n\n/**\n * Local token-bucket + concurrency limiter for submit-time throttling.\n *\n * ModelArk documents Seedance account limits of QPS 2 / 3 *concurrent\n * submissions*; this only gates `submitVideoGenerationJob` (task creation\n * HTTP calls), matching the \"submit-time throttling\" requirement — polling\n * and cancellation are not subject to the same account-level task-creation\n * limits. `maxConcurrent` bounds concurrent in-flight *submit HTTP\n * requests*, not the lifetime of the provider-side render tasks those\n * submissions create — this limiter has no way to observe when a task\n * actually finishes rendering on ModelArk's infrastructure, so\n * task-lifetime concurrency is not, and cannot be, tracked here.\n *\n * The bucket's burst capacity is capped at {@link SUBMIT_BURST_CAPACITY}\n * (independent of `requestsPerMinute`) so the bucket doesn't start full —\n * without this cap, a bucket sized to `requestsPerMinute` (e.g. 120) would\n * start with 120 tokens and let the first 120 submits through instantly,\n * defeating the QPS limit entirely.\n */\nclass SubmitRateLimiter {\n private tokens: number;\n private lastRefill: number;\n private readonly maxTokens: number;\n private readonly refillRate: number; // tokens per second\n private activeRequests = 0;\n private readonly maxConcurrent: number;\n\n constructor(options: { requestsPerMinute?: number; maxConcurrent?: number }) {\n const requestsPerMinute = options.requestsPerMinute ?? 120; // ~QPS 2\n this.refillRate = requestsPerMinute / 60;\n this.maxTokens = SUBMIT_BURST_CAPACITY;\n this.tokens = this.maxTokens;\n this.lastRefill = Date.now();\n this.maxConcurrent = options.maxConcurrent ?? 3;\n }\n\n /**\n * Acquire a submit slot + token, honoring `signal` throughout the wait.\n *\n * The concurrency slot and the token are checked and committed together\n * in one synchronous section (no `await` between the check and the\n * `tokens -=`/`activeRequests +=` mutations below), so a waiter can never\n * observe a stale \"slot available\" snapshot from before another waiter's\n * own commit — closing the TOCTOU window where two callers could both\n * pass the checks and push `activeRequests` past `maxConcurrent`.\n *\n * An aborted `signal` — whether already aborted at entry or aborted\n * while waiting for a slot/token — throws before any token is consumed\n * or `activeRequests` is incremented, so an aborted submission never\n * silently proceeds to create a billable job.\n */\n async acquire(signal?: AbortSignal): Promise<void> {\n const throwIfAborted = () => {\n if (signal?.aborted) {\n throw new AIError(\n 'ModelArk submission aborted by caller while waiting for the rate limiter',\n 'AI_ABORTED',\n 'byteplus-modelark',\n );\n }\n };\n\n throwIfAborted();\n\n const now = Date.now();\n const elapsed = (now - this.lastRefill) / 1000;\n this.tokens = Math.min(\n this.maxTokens,\n this.tokens + elapsed * this.refillRate,\n );\n this.lastRefill = now;\n\n for (;;) {\n throwIfAborted();\n\n if (this.activeRequests < this.maxConcurrent && this.tokens >= 1) {\n this.tokens -= 1;\n this.activeRequests += 1;\n return;\n }\n\n if (this.activeRequests >= this.maxConcurrent) {\n await delayOrAbort(100, signal);\n } else {\n const waitTime = Math.max(\n 1,\n ((1 - this.tokens) / this.refillRate) * 1000,\n );\n await delayOrAbort(waitTime, signal);\n const elapsedNow = (Date.now() - this.lastRefill) / 1000;\n this.tokens = Math.min(\n this.maxTokens,\n this.tokens + elapsedNow * this.refillRate,\n );\n this.lastRefill = Date.now();\n }\n }\n }\n\n release(): void {\n this.activeRequests = Math.max(0, this.activeRequests - 1);\n }\n}\n\n/**\n * FNV-1a hash, used only to avoid retaining raw API keys as in-memory Map\n * keys in {@link sharedSubmitLimiters}. Not cryptographic — collisions just\n * mean two distinct keys share a rate-limit bucket, which is a pacing\n * inefficiency, not a security issue.\n */\nfunction hashKey(value: string): string {\n let hash = 2166136261;\n for (let index = 0; index < value.length; index += 1) {\n hash ^= value.charCodeAt(index);\n hash = Math.imul(hash, 16777619);\n }\n return (hash >>> 0).toString(36);\n}\n\n/**\n * Submit-time limiters keyed by credential/config, shared module-wide.\n *\n * Provider instances are frequently constructed per pipeline step (a fresh\n * `getAI({ type: 'byteplus-modelark', ... })` per job), so a limiter owned\n * by a single provider instance would reset on every construction and never\n * actually enforce the account-wide QPS/concurrency limits. Keying by the\n * resolved credentials (or an explicit `rateLimit.key`) lets independently\n * constructed instances that target the same ModelArk account share one\n * bucket, mirroring how {@link createRateLimitedAI}'s budget coordinators\n * are shared by `rateLimit.key`.\n */\nconst sharedSubmitLimiters = new Map<string, SubmitRateLimiter>();\n\nfunction getSharedSubmitLimiter(\n options: ByteplusModelArkOptions,\n): SubmitRateLimiter {\n const key =\n options.rateLimit?.key?.trim() ||\n `byteplus-modelark:${hashKey(options.apiKey || 'default')}`;\n\n let limiter = sharedSubmitLimiters.get(key);\n if (!limiter) {\n limiter = new SubmitRateLimiter({\n requestsPerMinute: options.rateLimit?.requestsPerMinute,\n maxConcurrent: options.rateLimit?.maxConcurrent,\n });\n sharedSubmitLimiters.set(key, limiter);\n }\n return limiter;\n}\n\n/** @internal Test-only: clear shared submit limiters between test cases. */\nexport function __resetByteplusModelArkRateLimitersForTests(): void {\n sharedSubmitLimiters.clear();\n}\n\n/**\n * BytePlus ModelArk provider implementation for asynchronous video\n * generation (Seedance). Focuses on video-generation capabilities and\n * throws `NOT_IMPLEMENTED` for text generation methods.\n *\n * @example\n * ```typescript\n * import { getAI } from '@happyvertical/ai';\n *\n * const modelark = await getAI({\n * type: 'byteplus-modelark',\n * apiKey: process.env.MODELARK_API_KEY!,\n * });\n *\n * const job = await modelark.submitVideoGenerationJob({\n * prompt: 'A drone shot flying over a coastal cliff at sunrise',\n * durationSeconds: 5,\n * resolution: '720p',\n * aspectRatio: '16:9',\n * });\n *\n * // Persist `job`, poll later (even after a restart):\n * const status = await modelark.getVideoGenerationJob(job);\n * ```\n */\nexport class ByteplusModelArkProvider implements AIInterface {\n private options: ByteplusModelArkOptions;\n private readonly submitLimiter: SubmitRateLimiter;\n\n constructor(options: ByteplusModelArkOptions) {\n // Note: deliberately no `defaultModel` fallback baked in here — the\n // model-selection logic in submitVideoGenerationJob picks between the\n // t2v and i2v defaults based on whether referenceImages are present,\n // and an unconditional default here would always shadow that.\n this.options = normalizeBaseAIOptions({ ...options });\n\n this.submitLimiter = getSharedSubmitLimiter(this.options);\n }\n\n private get baseUrl(): string {\n return (this.options.baseUrl || DEFAULT_MODELARK_BASE_URL).replace(\n /\\/+$/,\n '',\n );\n }\n\n private async request<T>(\n path: string,\n options: {\n method?: 'GET' | 'POST' | 'DELETE';\n body?: unknown;\n query?: Record<string, string | number>;\n signal?: AbortSignal;\n timeout?: number;\n } = {},\n ): Promise<T> {\n if (options.signal?.aborted) {\n throw new AIError(\n 'ModelArk request aborted by caller',\n 'AI_ABORTED',\n 'byteplus-modelark',\n );\n }\n\n const url = new URL(`${this.baseUrl}${path}`);\n for (const [key, value] of Object.entries(options.query ?? {})) {\n url.searchParams.set(key, String(value));\n }\n\n const controller = new AbortController();\n const timeoutMs = options.timeout ?? this.options.timeout;\n let timedOut = false;\n const timer = timeoutMs\n ? setTimeout(() => {\n timedOut = true;\n controller.abort();\n }, timeoutMs)\n : undefined;\n // Mirrors `prepareRequestControls`'s pattern (packages/ai/src/shared/safety.ts):\n // addEventListener on an already-aborted signal never fires, so an\n // already-aborted `signal` must invoke the abort immediately instead of\n // only listening for a future 'abort' event.\n const onExternalAbort = () => controller.abort(options.signal?.reason);\n if (options.signal?.aborted) {\n onExternalAbort();\n } else {\n options.signal?.addEventListener('abort', onExternalAbort, {\n once: true,\n });\n }\n\n try {\n let response: Response;\n try {\n response = await fetch(url, {\n method: options.method || 'GET',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.options.apiKey ?? ''}`,\n ...(this.options.headers || {}),\n },\n body: options.body ? JSON.stringify(options.body) : undefined,\n signal: controller.signal,\n });\n } catch (error) {\n // The fetch() call itself failed (network error, DNS failure,\n // timeout/abort) — wrap it into the AIError taxonomy so callers get\n // a consistent, retryable-vs-terminal-distinguishable error rather\n // than a raw TypeError/DOMException.\n if (timedOut) {\n throw new AIError(\n `ModelArk request to ${path} timed out after ${timeoutMs}ms`,\n 'AI_TIMEOUT',\n 'byteplus-modelark',\n undefined,\n true,\n );\n }\n if (options.signal?.aborted) {\n throw new AIError(\n 'ModelArk request aborted by caller',\n 'AI_ABORTED',\n 'byteplus-modelark',\n );\n }\n throw new AIError(\n `Network error calling ModelArk ${path}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n 'NETWORK_ERROR',\n 'byteplus-modelark',\n undefined,\n true,\n );\n }\n\n if (!response.ok) {\n const errorText = await response.text();\n\n if (response.status === 401 || response.status === 403) {\n throw new AuthenticationError('byteplus-modelark');\n }\n if (response.status === 429) {\n throw rateLimitErrorFrom('byteplus-modelark', {\n headers: response.headers,\n message: errorText,\n });\n }\n\n throw new AIError(\n `ModelArk request to ${path} failed: ${response.status} ${errorText}`,\n 'MODELARK_REQUEST_FAILED',\n 'byteplus-modelark',\n );\n }\n\n if (response.status === 204) {\n return {} as T;\n }\n\n const text = await response.text();\n return text ? (JSON.parse(text) as T) : ({} as T);\n } finally {\n if (timer) clearTimeout(timer);\n options.signal?.removeEventListener('abort', onExternalAbort);\n }\n }\n\n private toImageUrl(reference: VideoGenerationReferenceImage): string {\n if (typeof reference.image === 'string') {\n return reference.image;\n }\n const mimeType = reference.mimeType || 'image/png';\n return `data:${mimeType};base64,${reference.image.toString('base64')}`;\n }\n\n // ============================================================================\n // Video Generation Methods (Implemented)\n // ============================================================================\n\n /**\n * Submit an asynchronous Seedance video-generation task.\n *\n * Submission is locally throttled to approximate ModelArk's documented\n * Seedance account limits (QPS 2, capped at {@link SUBMIT_BURST_CAPACITY}\n * burst / 3 concurrent *submissions* — task-lifetime concurrency on\n * ModelArk's infrastructure is not tracked; see {@link SubmitRateLimiter}).\n *\n * When `referenceImages` are supplied and no explicit `model` is chosen,\n * this selects the image-to-video default model rather than silently\n * generating text-to-video with the image ignored.\n */\n async submitVideoGenerationJob(\n options: VideoGenerationOptions,\n ): Promise<VideoGenerationJob> {\n const startTime = Date.now();\n await this.submitLimiter.acquire(options.signal);\n\n try {\n const hasReferenceImages = (options.referenceImages?.length ?? 0) > 0;\n const model =\n options.model ||\n this.options.defaultModel ||\n (hasReferenceImages\n ? DEFAULT_MODELARK_I2V_MODEL\n : DEFAULT_MODELARK_MODEL);\n\n const content: ModelArkContentItem[] = [];\n if (options.prompt) {\n content.push({ type: 'text', text: options.prompt });\n }\n for (const reference of options.referenceImages ?? []) {\n content.push({\n type: 'image_url',\n image_url: { url: this.toImageUrl(reference) },\n role: reference.role || 'reference_image',\n });\n }\n\n if (content.length === 0) {\n throw new AIError(\n 'submitVideoGenerationJob requires a prompt or at least one reference image',\n 'INVALID_INPUT',\n 'byteplus-modelark',\n );\n }\n\n const body: ModelArkCreateTaskRequest = {\n model,\n content,\n resolution: options.resolution,\n ratio: options.aspectRatio,\n duration: options.durationSeconds,\n seed: options.seed,\n };\n // Note: ModelArk's documented create-task schema has no negative_prompt\n // or fps fields, so those VideoGenerationOptions are intentionally not\n // forwarded for this provider.\n\n const response = await this.request<ModelArkCreateTaskResponse>(\n '/contents/generations/tasks',\n {\n method: 'POST',\n body,\n signal: options.signal,\n timeout: options.timeout,\n },\n );\n\n emitUsage(\n this.options,\n 'byteplus-modelark',\n 'submitVideoGenerationJob',\n model,\n undefined,\n startTime,\n {\n ...(options.durationSeconds !== undefined\n ? { durationSeconds: String(options.durationSeconds) }\n : {}),\n ...(options.resolution ? { resolution: options.resolution } : {}),\n ...(options.aspectRatio ? { aspectRatio: options.aspectRatio } : {}),\n ...options.usageTags,\n },\n );\n\n return {\n jobId: response.id,\n provider: 'byteplus-modelark',\n model,\n createdAt: new Date().toISOString(),\n };\n } finally {\n this.submitLimiter.release();\n }\n }\n\n /**\n * Poll the status of a ModelArk video-generation task.\n */\n async getVideoGenerationJob(\n handle: VideoGenerationJob,\n ): Promise<VideoGenerationStatusResult> {\n const task = await this.request<ModelArkTaskResponse>(\n `/contents/generations/tasks/${handle.jobId}`,\n );\n return this.mapTask(task);\n }\n\n /**\n * Fetch the result of a completed ModelArk video-generation task.\n *\n * @throws {AIError} When the job has not succeeded yet\n */\n async fetchVideoGenerationResult(\n handle: VideoGenerationJob,\n ): Promise<VideoGenerationResult> {\n const status = await this.getVideoGenerationJob(handle);\n if (status.status !== 'succeeded' || !status.result) {\n throw new AIError(\n `ModelArk video-generation job ${handle.jobId} has not succeeded (status: ${status.status})`,\n 'VIDEO_JOB_NOT_READY',\n 'byteplus-modelark',\n handle.model,\n );\n }\n return status.result;\n }\n\n /**\n * Cancel a ModelArk video-generation task.\n *\n * ModelArk's DELETE endpoint only transitions a `queued` task to\n * `cancelled`; a task that is already `running` cannot be cancelled and\n * the request fails with an {@link AIError} describing why. Terminal\n * tasks (`succeeded`/`failed`/`expired`) are deleted instead.\n */\n async cancelVideoGenerationJob(handle: VideoGenerationJob): Promise<void> {\n await this.request(`/contents/generations/tasks/${handle.jobId}`, {\n method: 'DELETE',\n });\n }\n\n /**\n * Cheap auth-shaped check for ModelArk access: lists tasks with a page\n * size of 1. Callers on a hot path must cache the result themselves.\n */\n async validateVideoGenerationAccess(): Promise<boolean> {\n await this.request('/contents/generations/tasks', {\n query: { page_size: 1 },\n });\n return true;\n }\n\n private mapTask(task: ModelArkTaskResponse): VideoGenerationStatusResult {\n switch (task.status) {\n case 'queued':\n return { status: 'queued' };\n case 'running':\n return { status: 'running' };\n case 'cancelled':\n return { status: 'cancelled' };\n case 'expired':\n return {\n status: 'failed',\n error: 'ModelArk task expired before the result was retrieved',\n };\n case 'failed':\n return {\n status: 'failed',\n error: task.error?.message || 'ModelArk video generation failed',\n };\n case 'succeeded': {\n if (!task.content?.video_url) {\n return {\n status: 'failed',\n error: 'ModelArk reported success with no video_url',\n };\n }\n return {\n status: 'succeeded',\n result: {\n url: task.content.video_url,\n mimeType: 'video/mp4',\n durationSeconds: task.duration,\n },\n };\n }\n default:\n // Never invent a terminal state for a status this package doesn't\n // recognize (e.g. a future ModelArk status addition) — treat it as\n // still in flight so a caller doesn't misread a mid-render job as\n // failed, resubmit, and double-bill. The raw value is preserved for\n // diagnostics.\n return { status: 'running', rawStatus: task.status };\n }\n }\n\n async getModels(): Promise<AIModel[]> {\n return [\n {\n id: 'seedance-1-0-lite-t2v-250428',\n name: 'Seedance 1.0 Lite (text-to-video)',\n description: 'ModelArk Seedance 1.0 Lite text-to-video model',\n contextLength: 0,\n capabilities: ['video_generation'],\n supportsFunctions: false,\n supportsVision: false,\n },\n {\n id: 'seedance-1-0-lite-i2v-250428',\n name: 'Seedance 1.0 Lite (image-to-video)',\n description: 'ModelArk Seedance 1.0 Lite image-to-video model',\n contextLength: 0,\n capabilities: ['video_generation'],\n supportsFunctions: false,\n supportsVision: true,\n },\n ];\n }\n\n async getCapabilities(): Promise<AICapabilities> {\n return {\n chat: false,\n completion: false,\n embeddings: false,\n streaming: false,\n functions: false,\n vision: false,\n fineTuning: false,\n imageEmbeddings: false,\n imageGeneration: false,\n videoGeneration: true,\n tts: false,\n voiceCloning: false,\n voiceDesign: false,\n maxContextLength: 0,\n supportedOperations: [\n 'submitVideoGenerationJob',\n 'getVideoGenerationJob',\n 'fetchVideoGenerationResult',\n 'cancelVideoGenerationJob',\n ],\n };\n }\n\n // ============================================================================\n // Text Generation / TTS Methods (Not Implemented - Use another provider)\n // ============================================================================\n\n async chat(\n _messages: AIMessage[],\n _options?: ChatOptions,\n ): Promise<AIResponse> {\n throw new AIError(\n 'Chat is not supported by the BytePlus ModelArk provider. Use OpenAI, Anthropic, or another provider for text generation.',\n 'NOT_IMPLEMENTED',\n 'byteplus-modelark',\n );\n }\n\n async complete(\n _prompt: string,\n _options?: CompletionOptions,\n ): Promise<AIResponse> {\n throw new AIError(\n 'Complete is not supported by the BytePlus ModelArk provider.',\n 'NOT_IMPLEMENTED',\n 'byteplus-modelark',\n );\n }\n\n async message(_text: string, _options?: MessageOptions): Promise<string> {\n throw new AIError(\n 'Message is not supported by the BytePlus ModelArk provider.',\n 'NOT_IMPLEMENTED',\n 'byteplus-modelark',\n );\n }\n\n async embed(\n _text: string | string[],\n _options?: EmbeddingOptions,\n ): Promise<EmbeddingResponse> {\n throw new AIError(\n 'Embeddings are not supported by the BytePlus ModelArk provider.',\n 'NOT_IMPLEMENTED',\n 'byteplus-modelark',\n );\n }\n\n async embedImage(\n _image: string | Buffer,\n _options?: ImageEmbeddingOptions,\n ): Promise<EmbeddingResponse> {\n throw new AIError(\n 'Image embeddings are not supported by the BytePlus ModelArk provider.',\n 'NOT_IMPLEMENTED',\n 'byteplus-modelark',\n );\n }\n\n async describeImage(\n _image: string | Buffer,\n _prompt?: string,\n _options?: ImageDescriptionOptions,\n ): Promise<string> {\n throw new AIError(\n 'Image description is not supported by the BytePlus ModelArk provider.',\n 'NOT_IMPLEMENTED',\n 'byteplus-modelark',\n );\n }\n\n async generateImage(\n _prompt: string,\n _options?: ImageGenerationOptions,\n ): Promise<ImageGenerationResponse> {\n throw new AIError(\n 'Synchronous image generation is not yet implemented by the BytePlus ModelArk provider.',\n 'NOT_IMPLEMENTED',\n 'byteplus-modelark',\n );\n }\n\n stream(\n _messages: AIMessage[],\n _options?: ChatOptions,\n ): AsyncIterable<string> {\n const error = new AIError(\n 'Chat streaming is not supported by the BytePlus ModelArk provider.',\n 'NOT_IMPLEMENTED',\n 'byteplus-modelark',\n );\n return {\n [Symbol.asyncIterator]: () => ({\n next: () => Promise.reject(error),\n }),\n };\n }\n\n async countTokens(_text: string): Promise<number> {\n throw new AIError(\n 'Token counting is not supported by the BytePlus ModelArk provider.',\n 'NOT_IMPLEMENTED',\n 'byteplus-modelark',\n );\n }\n\n async synthesizeSpeech(\n _text: string,\n _options?: TTSOptions,\n ): Promise<TTSResponse> {\n throw new AIError(\n 'TTS is not supported by the BytePlus ModelArk provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'byteplus-modelark',\n );\n }\n\n streamSpeech(_text: string, _options?: TTSOptions): AsyncIterable<Buffer> {\n const error = new AIError(\n 'TTS streaming is not supported by the BytePlus ModelArk provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'byteplus-modelark',\n );\n return {\n [Symbol.asyncIterator]: () => ({\n next: () => Promise.reject(error),\n }),\n };\n }\n\n async cloneVoice(_options: VoiceCloneOptions): Promise<Voice> {\n throw new AIError(\n 'Voice cloning is not supported by the BytePlus ModelArk provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'byteplus-modelark',\n );\n }\n\n async designVoice(_options: VoiceDesignOptions): Promise<Voice> {\n throw new AIError(\n 'Voice design is not supported by the BytePlus ModelArk provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'byteplus-modelark',\n );\n }\n\n async getVoices(_options?: VoiceListOptions): Promise<Voice[]> {\n throw new AIError(\n 'Voice listing is not supported by the BytePlus ModelArk provider. Use Qwen3-TTS provider.',\n 'NOT_IMPLEMENTED',\n 'byteplus-modelark',\n );\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { a as ContextLengthError, c as extractTextContent, r as AuthenticationError, s as RateLimitError, t as AIError } from "./types-BpnNcTU1.js";
1
+ import { a as ContextLengthError, c as RateLimitError, l as extractTextContent, r as AuthenticationError, t as AIError } from "./types-DB5W6_F-.js";
2
2
  import { t as emitUsage } from "./usage-C1Y1Nlg4.js";
3
3
  import { exec, spawn } from "node:child_process";
4
4
  import { promisify } from "node:util";
@@ -47,7 +47,7 @@ var ClaudeCliProvider = class {
47
47
  if (this.anthropicFallback !== null) return;
48
48
  const apiKey = process.env.ANTHROPIC_API_KEY;
49
49
  if (!apiKey) return;
50
- const { AnthropicProvider } = await import("./anthropic-CD9Ud7a5.js");
50
+ const { AnthropicProvider } = await import("./anthropic-6ZDF32jo.js");
51
51
  const defaultModel = {
52
52
  sonnet: "claude-3-5-sonnet-20241022",
53
53
  opus: "claude-3-opus-20240229",
@@ -304,7 +304,8 @@ var ClaudeCliProvider = class {
304
304
  stop: options.stop,
305
305
  stream: options.stream,
306
306
  onProgress: options.onProgress,
307
- usageTags: options.usageTags
307
+ usageTags: options.usageTags,
308
+ continueOnLength: options.continueOnLength
308
309
  });
309
310
  }
310
311
  /**
@@ -349,7 +350,8 @@ var ClaudeCliProvider = class {
349
350
  tools: options.tools,
350
351
  toolChoice: options.toolChoice,
351
352
  onProgress: options.onProgress,
352
- usageTags: options.usageTags
353
+ usageTags: options.usageTags,
354
+ continueOnLength: options.continueOnLength
353
355
  })).content;
354
356
  }
355
357
  /**
@@ -511,4 +513,4 @@ var ClaudeCliProvider = class {
511
513
  //#endregion
512
514
  export { ClaudeCliProvider };
513
515
 
514
- //# sourceMappingURL=claude-cli-Chfnckyj.js.map
516
+ //# sourceMappingURL=claude-cli-DIFxvG3c.js.map