@node-llm/core 1.15.2 → 1.16.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 (112) hide show
  1. package/dist/aliases.d.ts +315 -26
  2. package/dist/aliases.d.ts.map +1 -1
  3. package/dist/aliases.js +334 -45
  4. package/dist/chat/Chat.d.ts +22 -2
  5. package/dist/chat/Chat.d.ts.map +1 -1
  6. package/dist/chat/Chat.js +45 -3
  7. package/dist/chat/ChatOptions.d.ts +3 -1
  8. package/dist/chat/ChatOptions.d.ts.map +1 -1
  9. package/dist/chat/ChatResponse.d.ts +8 -2
  10. package/dist/chat/ChatResponse.d.ts.map +1 -1
  11. package/dist/chat/ChatResponse.js +9 -3
  12. package/dist/chat/ChatStream.d.ts.map +1 -1
  13. package/dist/chat/ChatStream.js +2 -0
  14. package/dist/chat/Tool.d.ts.map +1 -1
  15. package/dist/chat/Tool.js +21 -11
  16. package/dist/chat/ToolHandler.d.ts.map +1 -1
  17. package/dist/chat/ToolHandler.js +9 -2
  18. package/dist/chat/Validation.d.ts +1 -0
  19. package/dist/chat/Validation.d.ts.map +1 -1
  20. package/dist/chat/Validation.js +10 -0
  21. package/dist/index.d.ts +1 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/llm.d.ts +4 -0
  24. package/dist/llm.d.ts.map +1 -1
  25. package/dist/models/ModelRegistry.d.ts +3 -0
  26. package/dist/models/ModelRegistry.d.ts.map +1 -1
  27. package/dist/models/ModelRegistry.js +53 -16
  28. package/dist/models/PricingRegistry.d.ts.map +1 -1
  29. package/dist/models/PricingRegistry.js +14 -0
  30. package/dist/models/models.json +15118 -8614
  31. package/dist/providers/BaseProvider.d.ts.map +1 -1
  32. package/dist/providers/BaseProvider.js +1 -0
  33. package/dist/providers/Provider.d.ts +33 -0
  34. package/dist/providers/Provider.d.ts.map +1 -1
  35. package/dist/providers/anthropic/AnthropicProvider.js +1 -1
  36. package/dist/providers/anthropic/Capabilities.d.ts +1 -0
  37. package/dist/providers/anthropic/Capabilities.d.ts.map +1 -1
  38. package/dist/providers/anthropic/Capabilities.js +15 -34
  39. package/dist/providers/anthropic/Chat.d.ts.map +1 -1
  40. package/dist/providers/anthropic/Chat.js +16 -2
  41. package/dist/providers/anthropic/Streaming.d.ts.map +1 -1
  42. package/dist/providers/anthropic/Streaming.js +15 -1
  43. package/dist/providers/bedrock/BedrockProvider.d.ts +1 -1
  44. package/dist/providers/bedrock/BedrockProvider.js +1 -1
  45. package/dist/providers/bedrock/Capabilities.d.ts +3 -28
  46. package/dist/providers/bedrock/Capabilities.d.ts.map +1 -1
  47. package/dist/providers/bedrock/Capabilities.js +62 -183
  48. package/dist/providers/bedrock/Chat.d.ts.map +1 -1
  49. package/dist/providers/bedrock/Chat.js +1 -0
  50. package/dist/providers/bedrock/Streaming.d.ts.map +1 -1
  51. package/dist/providers/bedrock/Streaming.js +1 -0
  52. package/dist/providers/bedrock/mapper.d.ts +4 -3
  53. package/dist/providers/bedrock/mapper.d.ts.map +1 -1
  54. package/dist/providers/bedrock/mapper.js +19 -4
  55. package/dist/providers/deepseek/Capabilities.d.ts +2 -1
  56. package/dist/providers/deepseek/Capabilities.d.ts.map +1 -1
  57. package/dist/providers/deepseek/Capabilities.js +21 -30
  58. package/dist/providers/deepseek/DeepSeekProvider.d.ts +1 -1
  59. package/dist/providers/gemini/Capabilities.d.ts +1 -1
  60. package/dist/providers/gemini/Capabilities.d.ts.map +1 -1
  61. package/dist/providers/gemini/Capabilities.js +33 -87
  62. package/dist/providers/gemini/Chat.d.ts.map +1 -1
  63. package/dist/providers/gemini/Chat.js +44 -9
  64. package/dist/providers/gemini/ChatUtils.d.ts.map +1 -1
  65. package/dist/providers/gemini/ChatUtils.js +59 -49
  66. package/dist/providers/gemini/GeminiProvider.js +1 -1
  67. package/dist/providers/gemini/Image.d.ts.map +1 -1
  68. package/dist/providers/gemini/Image.js +17 -5
  69. package/dist/providers/gemini/Streaming.d.ts.map +1 -1
  70. package/dist/providers/gemini/Streaming.js +41 -1
  71. package/dist/providers/gemini/types.d.ts +1 -0
  72. package/dist/providers/gemini/types.d.ts.map +1 -1
  73. package/dist/providers/mistral/Capabilities.d.ts +1 -0
  74. package/dist/providers/mistral/Capabilities.d.ts.map +1 -1
  75. package/dist/providers/mistral/Capabilities.js +30 -59
  76. package/dist/providers/mistral/Chat.d.ts.map +1 -1
  77. package/dist/providers/mistral/Chat.js +13 -1
  78. package/dist/providers/mistral/Streaming.d.ts.map +1 -1
  79. package/dist/providers/mistral/Streaming.js +13 -1
  80. package/dist/providers/mistral/Transcription.d.ts.map +1 -1
  81. package/dist/providers/mistral/Transcription.js +3 -1
  82. package/dist/providers/ollama/Capabilities.d.ts +1 -0
  83. package/dist/providers/ollama/Capabilities.d.ts.map +1 -1
  84. package/dist/providers/ollama/Capabilities.js +17 -27
  85. package/dist/providers/openai/Capabilities.d.ts +2 -1
  86. package/dist/providers/openai/Capabilities.d.ts.map +1 -1
  87. package/dist/providers/openai/Capabilities.js +35 -71
  88. package/dist/providers/openai/Chat.d.ts.map +1 -1
  89. package/dist/providers/openai/Chat.js +4 -1
  90. package/dist/providers/openai/Image.d.ts +1 -0
  91. package/dist/providers/openai/Image.d.ts.map +1 -1
  92. package/dist/providers/openai/Image.js +61 -2
  93. package/dist/providers/openai/Streaming.d.ts.map +1 -1
  94. package/dist/providers/openai/Streaming.js +7 -1
  95. package/dist/providers/openai/Transcription.d.ts.map +1 -1
  96. package/dist/providers/openai/Transcription.js +7 -2
  97. package/dist/providers/openrouter/Capabilities.d.ts +10 -9
  98. package/dist/providers/openrouter/Capabilities.d.ts.map +1 -1
  99. package/dist/providers/openrouter/Capabilities.js +25 -48
  100. package/dist/providers/utils.d.ts +4 -0
  101. package/dist/providers/utils.d.ts.map +1 -1
  102. package/dist/providers/utils.js +11 -0
  103. package/dist/providers/xai/Capabilities.d.ts +13 -9
  104. package/dist/providers/xai/Capabilities.d.ts.map +1 -1
  105. package/dist/providers/xai/Capabilities.js +34 -65
  106. package/dist/transcription/Transcription.d.ts +23 -1
  107. package/dist/transcription/Transcription.d.ts.map +1 -1
  108. package/dist/transcription/Transcription.js +22 -0
  109. package/dist/utils/Binary.d.ts +8 -0
  110. package/dist/utils/Binary.d.ts.map +1 -1
  111. package/dist/utils/Binary.js +12 -0
  112. package/package.json +1 -1
@@ -2,95 +2,66 @@ import { ModelRegistry } from "../../models/ModelRegistry.js";
2
2
  import { PricingRegistry } from "../../models/PricingRegistry.js";
3
3
  export class MistralCapabilities {
4
4
  static getCapabilities(modelId) {
5
- const caps = ["streaming", "chat"];
6
- if (this.supportsTools(modelId)) {
7
- caps.push("function_calling", "tools");
5
+ const model = this.findModel(modelId);
6
+ if (model?.capabilities) {
7
+ const caps = [...model.capabilities];
8
+ if (!caps.includes("streaming"))
9
+ caps.push("streaming");
10
+ return caps;
8
11
  }
9
- if (this.supportsVision(modelId)) {
12
+ const caps = ["streaming", "chat"];
13
+ if (this.supportsTools(modelId))
14
+ caps.push("function_calling");
15
+ if (this.supportsReasoning(modelId))
16
+ caps.push("reasoning");
17
+ if (this.supportsVision(modelId))
10
18
  caps.push("vision");
11
- }
12
- if (this.supportsStructuredOutput(modelId)) {
13
- caps.push("structured_output", "json_mode");
14
- }
19
+ if (this.supportsStructuredOutput(modelId))
20
+ caps.push("structured_output");
15
21
  return caps;
16
22
  }
17
23
  static getContextWindow(modelId) {
18
- const val = ModelRegistry.getContextWindow(modelId, "mistral");
19
- if (val)
20
- return val;
21
- // Mistral models typically have 32K-128K context
22
- if (/mistral-large|codestral/.test(modelId)) {
23
- return 128_000;
24
- }
25
- if (/mistral-medium|mistral-small|pixtral/.test(modelId)) {
26
- return 32_000;
27
- }
28
- return 32_000;
24
+ return ModelRegistry.getContextWindow(modelId, "mistral") ?? 32_768;
29
25
  }
30
26
  static getMaxOutputTokens(modelId) {
31
- const model = this.findModel(modelId);
32
- if (model?.max_output_tokens)
33
- return model.max_output_tokens;
34
- // Default max output for Mistral models
35
- return 8_192;
27
+ return ModelRegistry.getMaxOutputTokens(modelId, "mistral") ?? 8_192;
36
28
  }
37
29
  static supportsVision(modelId) {
38
- const model = this.findModel(modelId);
39
- if (model?.modalities?.input?.includes("image"))
40
- return true;
41
- // Pixtral models support vision
42
- return /pixtral/.test(modelId.toLowerCase());
30
+ return ModelRegistry.supports(modelId, "vision", "mistral") || modelId.includes("pixtral");
43
31
  }
44
32
  static supportsTools(modelId) {
45
- const model = this.findModel(modelId);
46
- if (model?.capabilities?.includes("function_calling") || model?.capabilities?.includes("tools"))
47
- return true;
48
- // Most Mistral models support tools except embedding models
49
- return !/embed/.test(modelId.toLowerCase());
33
+ return (ModelRegistry.supports(modelId, "tools", "mistral") ||
34
+ ModelRegistry.supports(modelId, "function_calling", "mistral") ||
35
+ !modelId.includes("embed"));
50
36
  }
51
37
  static supportsStructuredOutput(modelId) {
52
- const model = this.findModel(modelId);
53
- if (model?.capabilities?.includes("structured_output"))
54
- return true;
55
- // Most Mistral chat models support JSON mode
56
- return !/embed/.test(modelId.toLowerCase());
38
+ return (ModelRegistry.supports(modelId, "structured_output", "mistral") ||
39
+ ModelRegistry.supports(modelId, "json_mode", "mistral") ||
40
+ !modelId.includes("embed"));
57
41
  }
58
42
  static supportsEmbeddings(modelId) {
59
43
  const model = this.findModel(modelId);
60
- if (model?.modalities?.output?.includes("embeddings"))
61
- return true;
62
- return /embed/.test(modelId.toLowerCase());
44
+ return model?.modalities?.output?.includes("embeddings") ?? modelId.includes("embed");
63
45
  }
64
46
  static supportsImageGeneration(_modelId) {
65
47
  return false;
66
48
  }
67
49
  static supportsTranscription(modelId) {
68
- const model = this.findModel(modelId);
69
- if (model?.modalities?.input?.includes("audio"))
70
- return true;
71
- // Voxtral models support transcription
72
- return /voxtral/.test(modelId.toLowerCase());
50
+ return (ModelRegistry.supports(modelId, "transcription", "mistral") || modelId.includes("voxtral"));
73
51
  }
74
52
  static supportsModeration(modelId) {
75
- const model = this.findModel(modelId);
76
- if (model?.capabilities?.includes("moderation"))
77
- return true;
78
- return /moderation/.test(modelId.toLowerCase());
53
+ return (ModelRegistry.supports(modelId, "moderation", "mistral") || modelId.includes("moderation"));
79
54
  }
80
55
  static supportsReasoning(modelId) {
81
- const model = this.findModel(modelId);
82
- if (model?.capabilities?.includes("reasoning"))
83
- return true;
84
- // Magistral models support reasoning
85
- return /magistral/.test(modelId.toLowerCase());
56
+ return ModelRegistry.supports(modelId, "reasoning", "mistral") || modelId.includes("magistral");
57
+ }
58
+ static supportsToolChoice(_modelId) {
59
+ return true;
86
60
  }
87
61
  static findModel(modelId) {
88
62
  return ModelRegistry.find(modelId, "mistral");
89
63
  }
90
64
  static getPricing(modelId) {
91
- const model = this.findModel(modelId);
92
- if (model?.pricing)
93
- return model.pricing;
94
65
  return PricingRegistry.getPricing(modelId, "mistral");
95
66
  }
96
67
  static getInputModalities(modelId) {
@@ -1 +1 @@
1
- {"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../../src/providers/mistral/Chat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAS,MAAM,gBAAgB,CAAC;AAgDlE,qBAAa,WAAW;IAEpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;CAmK3D"}
1
+ {"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../../src/providers/mistral/Chat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAS,MAAM,gBAAgB,CAAC;AAgDlE,qBAAa,WAAW;IAEpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;CAkL3D"}
@@ -11,7 +11,7 @@ export class MistralChat {
11
11
  this.apiKey = apiKey;
12
12
  }
13
13
  async execute(request) {
14
- const { model, messages, tools, max_tokens, response_format, thinking: _thinking, headers: _headers, requestTimeout, signal: _signal, ...rest } = request;
14
+ const { model, messages, tools, max_tokens, response_format, thinking: _thinking, headers: _headers, tool_choice: _choice, parallel_tool_calls: _parallel, requestTimeout, signal: _signal, ...rest } = request;
15
15
  const mappedMessages = mapSystemMessages(messages, false);
16
16
  // Sanitize messages - remove internal properties that Mistral API doesn't accept
17
17
  const sanitizedMessages = mappedMessages.map((msg) => {
@@ -35,6 +35,18 @@ export class MistralChat {
35
35
  body.max_tokens = max_tokens;
36
36
  if (tools && tools.length > 0)
37
37
  body.tools = tools;
38
+ if (request.tool_choice) {
39
+ if (request.tool_choice === "required") {
40
+ body.tool_choice = "any";
41
+ }
42
+ else if (typeof request.tool_choice === "string" &&
43
+ !["auto", "none", "any"].includes(request.tool_choice)) {
44
+ body.tool_choice = { type: "function", function: { name: request.tool_choice } };
45
+ }
46
+ else {
47
+ body.tool_choice = request.tool_choice;
48
+ }
49
+ }
38
50
  // Handle structured output for Mistral
39
51
  if (response_format) {
40
52
  if (response_format.type === "json_schema") {
@@ -1 +1 @@
1
- {"version":3,"file":"Streaming.d.ts","sourceRoot":"","sources":["../../../src/providers/mistral/Streaming.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAOxD,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG1B,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,eAAe,GAAG,cAAc,CAAC,SAAS,CAAC;CAgO9F"}
1
+ {"version":3,"file":"Streaming.d.ts","sourceRoot":"","sources":["../../../src/providers/mistral/Streaming.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAOxD,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG1B,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,eAAe,GAAG,cAAc,CAAC,SAAS,CAAC;CA6O9F"}
@@ -35,10 +35,22 @@ export class MistralStreaming {
35
35
  };
36
36
  if (max_tokens)
37
37
  body.max_tokens = max_tokens;
38
- if (tools && tools.length > 0)
38
+ if (tools && tools.length > 0 && request.tool_choice !== "none")
39
39
  body.tools = tools;
40
40
  if (response_format)
41
41
  body.response_format = response_format;
42
+ if (request.tool_choice && request.tool_choice !== "none") {
43
+ if (request.tool_choice === "required") {
44
+ body.tool_choice = "any";
45
+ }
46
+ else if (typeof request.tool_choice === "string" &&
47
+ !["auto", "none", "any"].includes(request.tool_choice)) {
48
+ body.tool_choice = { type: "function", function: { name: request.tool_choice } };
49
+ }
50
+ else {
51
+ body.tool_choice = request.tool_choice;
52
+ }
53
+ }
42
54
  let done = false;
43
55
  // Track tool calls being built across chunks
44
56
  const toolCallsMap = new Map();
@@ -1 +1 @@
1
- {"version":3,"file":"Transcription.d.ts","sourceRoot":"","sources":["../../../src/providers/mistral/Transcription.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAwB,MAAM,gBAAgB,CAAC;AAqBnG,qBAAa,oBAAoB;IAE7B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IA2D5E,OAAO,CAAC,WAAW;CAmBpB"}
1
+ {"version":3,"file":"Transcription.d.ts","sourceRoot":"","sources":["../../../src/providers/mistral/Transcription.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAwB,MAAM,gBAAgB,CAAC;AAqBnG,qBAAa,oBAAoB;IAE7B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IA6D5E,OAAO,CAAC,WAAW;CAmBpB"}
@@ -45,7 +45,9 @@ export class MistralTranscription {
45
45
  id: s.id,
46
46
  start: s.start,
47
47
  end: s.end,
48
- text: s.text
48
+ text: s.text,
49
+ speaker: s.speaker,
50
+ words: s.words
49
51
  }));
50
52
  return {
51
53
  text: json.text,
@@ -9,5 +9,6 @@ export declare class OllamaCapabilities {
9
9
  static supportsImageGeneration(modelId: string): boolean;
10
10
  static supportsTranscription(modelId: string): boolean;
11
11
  static supportsModeration(modelId: string): boolean;
12
+ static supportsToolChoice(_modelId: string): boolean;
12
13
  }
13
14
  //# sourceMappingURL=Capabilities.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Capabilities.d.ts","sourceRoot":"","sources":["../../../src/providers/ollama/Capabilities.ts"],"names":[],"mappings":"AAEA,qBAAa,kBAAkB;IAC7B,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM;IAYhC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKvD,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAc/C,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAQ9C,MAAM,CAAC,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAKzD,MAAM,CAAC,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IASnD,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAKlD,MAAM,CAAC,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAKxD,MAAM,CAAC,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAKtD,MAAM,CAAC,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;CAIpD"}
1
+ {"version":3,"file":"Capabilities.d.ts","sourceRoot":"","sources":["../../../src/providers/ollama/Capabilities.ts"],"names":[],"mappings":"AAEA,qBAAa,kBAAkB;IAC7B,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM;IAYhC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKvD,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAQ/C,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAO9C,MAAM,CAAC,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIzD,MAAM,CAAC,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAKnD,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAQlD,MAAM,CAAC,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIxD,MAAM,CAAC,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAItD,MAAM,CAAC,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAInD,MAAM,CAAC,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;CAGrD"}
@@ -13,49 +13,39 @@ export class OllamaCapabilities {
13
13
  }
14
14
  static getContextWindow(modelId) {
15
15
  const model = this.findModel(modelId);
16
- return model?.context_window || 8192;
16
+ return model?.context_window || 32_768;
17
17
  }
18
18
  static supportsVision(modelId) {
19
- const model = this.findModel(modelId);
20
- if (model) {
21
- return (model.modalities?.input?.includes("image") ||
22
- model.capabilities?.includes("vision") ||
23
- false);
24
- }
25
- // Fallback for custom models not in registry
26
- return /vision|llava|moondream|bakllava/.test(modelId.toLowerCase());
19
+ return (ModelRegistry.supports(modelId, "vision", "ollama") ||
20
+ modelId.includes("vision") ||
21
+ modelId.includes("llava"));
27
22
  }
28
23
  static supportsTools(modelId) {
29
- const model = this.findModel(modelId);
30
- if (model?.capabilities?.includes("tools"))
31
- return true;
32
- // Fallback heuristics for models not in registry
33
- return /gpt-|claude|gemini|deepseek|llama/.test(modelId.toLowerCase());
24
+ return (ModelRegistry.supports(modelId, "tools", "ollama") ||
25
+ ModelRegistry.supports(modelId, "function_calling", "ollama"));
34
26
  }
35
27
  static supportsStructuredOutput(modelId) {
36
- const model = this.findModel(modelId);
37
- return model?.capabilities?.includes("structured_output") || false;
28
+ return ModelRegistry.supports(modelId, "structured_output", "ollama");
38
29
  }
39
30
  static supportsEmbeddings(modelId) {
40
31
  const model = this.findModel(modelId);
41
- return (model?.modalities?.output?.includes("embeddings") ||
42
- model?.capabilities?.includes("embeddings") ||
43
- false);
32
+ return model?.modalities?.output?.includes("embeddings") ?? modelId.includes("embed");
44
33
  }
45
34
  static supportsReasoning(modelId) {
46
- const model = this.findModel(modelId);
47
- return model?.capabilities?.includes("reasoning") || false;
35
+ return (ModelRegistry.supports(modelId, "reasoning", "ollama") ||
36
+ modelId.includes("reason") ||
37
+ modelId.includes("thought"));
48
38
  }
49
39
  static supportsImageGeneration(modelId) {
50
- const model = this.findModel(modelId);
51
- return model?.modalities?.output?.includes("image") || false;
40
+ return false;
52
41
  }
53
42
  static supportsTranscription(modelId) {
54
- const model = this.findModel(modelId);
55
- return model?.modalities?.input?.includes("audio") || false;
43
+ return false;
56
44
  }
57
45
  static supportsModeration(modelId) {
58
- const model = this.findModel(modelId);
59
- return model?.modalities?.output?.includes("moderation") || false;
46
+ return false;
47
+ }
48
+ static supportsToolChoice(_modelId) {
49
+ return true;
60
50
  }
61
51
  }
@@ -12,9 +12,10 @@ export declare class Capabilities {
12
12
  static supportsModeration(modelId: string): boolean;
13
13
  static supportsReasoning(modelId: string): boolean;
14
14
  static supportsDeveloperRole(modelId: string): boolean;
15
+ static supportsToolChoice(_modelId: string): boolean;
15
16
  static supportsPrediction(modelId: string): boolean;
16
17
  static needsMaxCompletionTokens(modelId: string): boolean;
17
- static getModelType(modelId: string): "embeddings" | "audio" | "moderation" | "image" | "chat" | "audio_transcription" | "audio_speech";
18
+ static getModelType(modelId: string): string;
18
19
  static getModalities(modelId: string): {
19
20
  input: string[];
20
21
  output: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"Capabilities.d.ts","sourceRoot":"","sources":["../../../src/providers/openai/Capabilities.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD,qBAAa,YAAY;IACvB,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAUvD,MAAM,CAAC,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IASzD,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAO/C,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAQ9C,MAAM,CAAC,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAOzD,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIjD,MAAM,CAAC,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAOnD,MAAM,CAAC,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAWxD,MAAM,CAAC,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAOtD,MAAM,CAAC,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAOnD,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAOlD,MAAM,CAAC,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAItD,MAAM,CAAC,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAInD,MAAM,CAAC,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIzD,MAAM,CAAC,YAAY,CACjB,OAAO,EAAE,MAAM,GAEb,YAAY,GACZ,OAAO,GACP,YAAY,GACZ,OAAO,GACP,MAAM,GACN,qBAAqB,GACrB,cAAc;IAWlB,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;IAiB5E,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE;IAsBjD,MAAM,CAAC,oBAAoB,CACzB,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,OAAO,EAAE,MAAM,GACd,MAAM,GAAG,SAAS,GAAG,IAAI;IAM5B,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAOjD,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAI5D,OAAO,CAAC,MAAM,CAAC,SAAS;CAGzB"}
1
+ {"version":3,"file":"Capabilities.d.ts","sourceRoot":"","sources":["../../../src/providers/openai/Capabilities.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD,qBAAa,YAAY;IACvB,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIvD,MAAM,CAAC,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIzD,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAI/C,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAO9C,MAAM,CAAC,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIzD,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAOjD,MAAM,CAAC,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAKnD,MAAM,CAAC,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAQxD,MAAM,CAAC,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAKtD,MAAM,CAAC,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAKnD,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIlD,MAAM,CAAC,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAItD,MAAM,CAAC,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAIpD,MAAM,CAAC,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAInD,MAAM,CAAC,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIzD,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAU5C,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;IAgB5E,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE;IAkBjD,MAAM,CAAC,oBAAoB,CACzB,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,OAAO,EAAE,MAAM,GACd,MAAM,GAAG,SAAS,GAAG,IAAI;IAM5B,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAMjD,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAI5D,OAAO,CAAC,MAAM,CAAC,SAAS;CAGzB"}
@@ -2,111 +2,78 @@ import { ModelRegistry } from "../../models/ModelRegistry.js";
2
2
  import { PricingRegistry } from "../../models/PricingRegistry.js";
3
3
  export class Capabilities {
4
4
  static getContextWindow(modelId) {
5
- const val = ModelRegistry.getContextWindow(modelId, "openai");
6
- if (val)
7
- return val;
8
- if (/gpt-4.*(preview|turbo|vision|o)/.test(modelId) || /o1|o3/.test(modelId))
9
- return 128_000;
10
- if (/gpt-4/.test(modelId))
11
- return 8_192;
12
- if (/gpt-3\.5/.test(modelId))
13
- return 16_385;
14
- return 128_000;
5
+ return ModelRegistry.getContextWindow(modelId, "openai") ?? 128_000;
15
6
  }
16
7
  static getMaxOutputTokens(modelId) {
17
- const val = ModelRegistry.getMaxOutputTokens(modelId, "openai");
18
- if (val)
19
- return val;
20
- if (/o1.*(pro|mini)|o3/.test(modelId))
21
- return 65_536;
22
- if (/gpt-4o/.test(modelId))
23
- return 16_384;
24
- return 4_096;
8
+ return ModelRegistry.getMaxOutputTokens(modelId, "openai") ?? 4_096;
25
9
  }
26
10
  static supportsVision(modelId) {
27
- const model = this.findModel(modelId);
28
- if (model?.modalities?.input?.includes("image"))
29
- return true;
30
- return /gpt-4(?!-3)|o1/.test(modelId) && !/audio|realtime|voice/.test(modelId);
11
+ return ModelRegistry.supports(modelId, "vision", "openai");
31
12
  }
32
13
  static supportsTools(modelId) {
33
- const model = this.findModel(modelId);
34
- if (model?.capabilities?.includes("function_calling") || model?.capabilities?.includes("tools"))
35
- return true;
36
- return !/embedding|moderation|dall-e|tts|whisper/.test(modelId);
14
+ return (ModelRegistry.supports(modelId, "tools", "openai") ||
15
+ ModelRegistry.supports(modelId, "function_calling", "openai"));
37
16
  }
38
17
  static supportsStructuredOutput(modelId) {
39
- const model = this.findModel(modelId);
40
- if (model?.capabilities?.includes("structured_output"))
41
- return true;
42
- return /gpt-4|o1|o3/.test(modelId);
18
+ return ModelRegistry.supports(modelId, "structured_output", "openai");
43
19
  }
44
20
  static supportsJsonMode(modelId) {
45
- return this.supportsStructuredOutput(modelId);
21
+ return (ModelRegistry.supports(modelId, "json_mode", "openai") ||
22
+ this.supportsStructuredOutput(modelId));
46
23
  }
47
24
  static supportsEmbeddings(modelId) {
48
25
  const model = this.findModel(modelId);
49
- if (model?.modalities?.output?.includes("embeddings"))
50
- return true;
51
- return /embedding/.test(modelId);
26
+ return model?.modalities?.output?.includes("embeddings") ?? modelId.includes("embedding");
52
27
  }
53
28
  static supportsImageGeneration(modelId) {
54
- const model = this.findModel(modelId);
55
- if (model?.capabilities?.includes("image_generation") ||
56
- model?.modalities?.output?.includes("image"))
57
- return true;
58
- return /dall-e|image/.test(modelId);
29
+ return (ModelRegistry.supports(modelId, "image_generation", "openai") ||
30
+ modelId.includes("dall-e") ||
31
+ modelId === "gpt-image-1");
59
32
  }
60
33
  static supportsTranscription(modelId) {
61
34
  const model = this.findModel(modelId);
62
- if (model?.modalities?.input?.includes("audio"))
63
- return true;
64
- return /whisper|audio|transcribe/.test(modelId);
35
+ return model?.modalities?.input?.includes("audio") ?? modelId.includes("whisper");
65
36
  }
66
37
  static supportsModeration(modelId) {
67
38
  const model = this.findModel(modelId);
68
- if (model?.modalities?.output?.includes("moderation"))
69
- return true;
70
- return /moderation/.test(modelId);
39
+ return model?.modalities?.output?.includes("moderation") ?? modelId.includes("moderation");
71
40
  }
72
41
  static supportsReasoning(modelId) {
73
- const model = this.findModel(modelId);
74
- if (model?.capabilities?.includes("reasoning"))
75
- return true;
76
- return /o\d|gpt-5/.test(modelId);
42
+ return ModelRegistry.supports(modelId, "reasoning", "openai");
77
43
  }
78
44
  static supportsDeveloperRole(modelId) {
79
45
  return /gpt-4o|o1|o3|gpt-5/.test(modelId);
80
46
  }
47
+ static supportsToolChoice(_modelId) {
48
+ return true;
49
+ }
81
50
  static supportsPrediction(modelId) {
82
- return /gpt-4o/.test(modelId) || /gpt-4-/.test(modelId);
51
+ return /gpt-4o|gpt-4-/.test(modelId);
83
52
  }
84
53
  static needsMaxCompletionTokens(modelId) {
85
- return /o1|o3|gpt-5/.test(modelId);
54
+ return this.supportsReasoning(modelId);
86
55
  }
87
56
  static getModelType(modelId) {
88
57
  if (this.supportsEmbeddings(modelId))
89
58
  return "embeddings";
90
- if (/moderation/.test(modelId))
59
+ if (this.supportsModeration(modelId))
91
60
  return "moderation";
92
- if (/embedding/.test(modelId))
93
- return "embeddings";
94
- if (/dall-e|image/.test(modelId))
61
+ if (this.supportsImageGeneration(modelId))
95
62
  return "image";
96
- if (/whisper|transcribe/.test(modelId))
63
+ if (this.supportsTranscription(modelId))
97
64
  return "audio_transcription";
98
- if (/tts|speech/.test(modelId))
65
+ if (modelId.includes("tts") || modelId.includes("speech"))
99
66
  return "audio_speech";
100
- if (/audio/.test(modelId))
67
+ if (modelId.includes("audio"))
101
68
  return "audio";
102
69
  return "chat";
103
70
  }
104
71
  static getModalities(modelId) {
105
- const input = ["text"];
106
- const output = ["text"];
107
72
  const model = this.findModel(modelId);
108
73
  if (model?.modalities)
109
74
  return model.modalities;
75
+ const input = ["text"];
76
+ const output = ["text"];
110
77
  if (this.supportsVision(modelId))
111
78
  input.push("image", "pdf");
112
79
  if (this.supportsTranscription(modelId))
@@ -120,22 +87,19 @@ export class Capabilities {
120
87
  return { input, output };
121
88
  }
122
89
  static getCapabilities(modelId) {
123
- const caps = ["streaming"];
124
90
  const model = this.findModel(modelId);
125
- if (model) {
126
- model.capabilities.forEach((c) => {
127
- if (!caps.includes(c))
128
- caps.push(c);
129
- });
91
+ if (model?.capabilities) {
92
+ const caps = [...model.capabilities];
93
+ if (!caps.includes("streaming"))
94
+ caps.push("streaming");
130
95
  return caps;
131
96
  }
97
+ const caps = ["streaming"];
132
98
  if (this.supportsTools(modelId))
133
99
  caps.push("function_calling");
134
100
  if (this.supportsStructuredOutput(modelId))
135
101
  caps.push("structured_output");
136
- if (this.supportsEmbeddings(modelId))
137
- caps.push("batch");
138
- if (/o\d|gpt-5/.test(modelId))
102
+ if (this.supportsReasoning(modelId))
139
103
  caps.push("reasoning");
140
104
  if (this.supportsImageGeneration(modelId))
141
105
  caps.push("image_generation");
@@ -144,9 +108,9 @@ export class Capabilities {
144
108
  return caps;
145
109
  }
146
110
  static normalizeTemperature(temperature, modelId) {
147
- if (/^(o\d|gpt-5)/.test(modelId))
111
+ if (this.supportsReasoning(modelId))
148
112
  return 1.0;
149
- if (/-search/.test(modelId))
113
+ if (modelId.includes("-search"))
150
114
  return null;
151
115
  return temperature;
152
116
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../../src/providers/openai/Chat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAS3D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAIrD,qBAAa,UAAU;IAInB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAGd,aAAa,EAAE,cAAc,GAAG,MAAM,EACtC,MAAM,EAAE,MAAM;IAK3B,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;CAuJ3D"}
1
+ {"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../../src/providers/openai/Chat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAS3D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAIrD,qBAAa,UAAU;IAInB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAGd,aAAa,EAAE,cAAc,GAAG,MAAM,EACtC,MAAM,EAAE,MAAM;IAK3B,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;CA2J3D"}
@@ -4,7 +4,7 @@ import { ModelRegistry } from "../../models/ModelRegistry.js";
4
4
  import { buildUrl } from "./utils.js";
5
5
  import { logger } from "../../utils/logger.js";
6
6
  import { fetchWithTimeout } from "../../utils/fetch.js";
7
- import { mapSystemMessages } from "../utils.js";
7
+ import { mapSystemMessages, normalizeOpenAIToolChoice } from "../utils.js";
8
8
  import { enforceStrictSchema } from "../../schema/strict.js";
9
9
  export class OpenAIChat {
10
10
  providerOrUrl;
@@ -53,6 +53,9 @@ export class OpenAIChat {
53
53
  return tool;
54
54
  });
55
55
  }
56
+ if (request.tool_choice) {
57
+ body.tool_choice = normalizeOpenAIToolChoice(request.tool_choice);
58
+ }
56
59
  if (prediction) {
57
60
  body.prediction = {
58
61
  type: "content",
@@ -4,5 +4,6 @@ export declare class OpenAIImage {
4
4
  private readonly apiKey;
5
5
  constructor(baseUrl: string, apiKey: string);
6
6
  execute(request: ImageRequest): Promise<ImageResponse>;
7
+ private executeEdit;
7
8
  }
8
9
  //# sourceMappingURL=Image.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Image.d.ts","sourceRoot":"","sources":["../../../src/providers/openai/Image.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAM7D,qBAAa,WAAW;IAEpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;CA2C7D"}
1
+ {"version":3,"file":"Image.d.ts","sourceRoot":"","sources":["../../../src/providers/openai/Image.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAO7D,qBAAa,WAAW;IAEpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;YAqD9C,WAAW;CAgE1B"}
@@ -2,6 +2,7 @@ import { handleOpenAIError } from "./Errors.js";
2
2
  import { buildUrl } from "./utils.js";
3
3
  import { logger } from "../../utils/logger.js";
4
4
  import { fetchWithTimeout } from "../../utils/fetch.js";
5
+ import { BinaryUtils } from "../../utils/Binary.js";
5
6
  export class OpenAIImage {
6
7
  baseUrl;
7
8
  apiKey;
@@ -10,8 +11,13 @@ export class OpenAIImage {
10
11
  this.apiKey = apiKey;
11
12
  }
12
13
  async execute(request) {
14
+ const isEdit = !!(request.images && request.images.length > 0);
15
+ const model = request.model || (isEdit ? "gpt-image-1" : "dall-e-3");
16
+ if (isEdit) {
17
+ return this.executeEdit(request, model);
18
+ }
13
19
  const body = {
14
- model: request.model || "dall-e-3",
20
+ model,
15
21
  prompt: request.prompt,
16
22
  size: request.size || "1024x1024",
17
23
  quality: request.quality || "standard",
@@ -28,16 +34,69 @@ export class OpenAIImage {
28
34
  body: JSON.stringify(body)
29
35
  }, request.requestTimeout);
30
36
  if (!response.ok) {
31
- await handleOpenAIError(response, request.model);
37
+ await handleOpenAIError(response, model);
38
+ }
39
+ const json = await response.json();
40
+ logger.logResponse("OpenAI", response.status, response.statusText, json);
41
+ const data = json.data?.[0];
42
+ if (!data) {
43
+ logger.debug("OpenAI Response missing data array:", json);
44
+ throw new Error("OpenAI returned empty image response");
45
+ }
46
+ return {
47
+ url: data.url,
48
+ data: data.b64_json,
49
+ revised_prompt: data.revised_prompt,
50
+ mime_type: "image/png"
51
+ };
52
+ }
53
+ async executeEdit(request, model) {
54
+ const formData = new FormData();
55
+ formData.append("model", model);
56
+ formData.append("prompt", request.prompt);
57
+ if (request.size)
58
+ formData.append("size", request.size);
59
+ if (request.n)
60
+ formData.append("n", String(request.n));
61
+ if (request.images && request.images[0]) {
62
+ const imageFile = request.images[0];
63
+ // Download/Read the image
64
+ const imageBinary = await BinaryUtils.toBase64(imageFile);
65
+ if (imageBinary) {
66
+ const imageBlob = BinaryUtils.base64ToBlob(imageBinary);
67
+ formData.append("image", imageBlob, "image.png");
68
+ }
69
+ if (request.mask) {
70
+ const maskBinary = await BinaryUtils.toBase64(request.mask);
71
+ if (maskBinary) {
72
+ const maskBlob = BinaryUtils.base64ToBlob(maskBinary);
73
+ formData.append("mask", maskBlob, "mask.png");
74
+ }
75
+ }
76
+ }
77
+ const endpoint = request.prompt ? "/images/edits" : "/images/variations";
78
+ const url = buildUrl(this.baseUrl, endpoint);
79
+ logger.logRequest("OpenAI", "POST", url, { model, prompt: request.prompt });
80
+ const response = await fetchWithTimeout(url, {
81
+ method: "POST",
82
+ headers: {
83
+ Authorization: `Bearer ${this.apiKey}`
84
+ },
85
+ body: formData
86
+ }, request.requestTimeout);
87
+ if (!response.ok) {
88
+ await handleOpenAIError(response, model);
32
89
  }
33
90
  const json = await response.json();
34
91
  logger.logResponse("OpenAI", response.status, response.statusText, json);
35
92
  const data = json.data?.[0];
36
93
  if (!data) {
94
+ logger.debug("OpenAI Response missing data array:", json);
37
95
  throw new Error("OpenAI returned empty image response");
38
96
  }
39
97
  return {
40
98
  url: data.url,
99
+ data: data.b64_json,
41
100
  revised_prompt: data.revised_prompt,
42
101
  mime_type: "image/png"
43
102
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Streaming.d.ts","sourceRoot":"","sources":["../../../src/providers/openai/Streaming.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAQxD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAIrD,qBAAa,eAAe;IAIxB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAGd,aAAa,EAAE,cAAc,GAAG,MAAM,EACtC,MAAM,EAAE,MAAM;IAK1B,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,eAAe,GAAG,cAAc,CAAC,SAAS,CAAC;CAkP9F"}
1
+ {"version":3,"file":"Streaming.d.ts","sourceRoot":"","sources":["../../../src/providers/openai/Streaming.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAQxD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAIrD,qBAAa,eAAe;IAIxB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAGd,aAAa,EAAE,cAAc,GAAG,MAAM,EACtC,MAAM,EAAE,MAAM;IAK1B,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,eAAe,GAAG,cAAc,CAAC,SAAS,CAAC;CAyP9F"}