hazo_llm_api 1.2.12 → 1.3.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 (204) hide show
  1. package/README.md +321 -8
  2. package/config/hazo_llm_api_config.ini +33 -0
  3. package/dist/components/index.d.ts +2 -0
  4. package/dist/components/index.d.ts.map +1 -1
  5. package/dist/components/index.js +2 -0
  6. package/dist/components/index.js.map +1 -1
  7. package/dist/components/llm_call_inspector/index.d.ts +6 -0
  8. package/dist/components/llm_call_inspector/index.d.ts.map +1 -0
  9. package/dist/components/llm_call_inspector/index.js +5 -0
  10. package/dist/components/llm_call_inspector/index.js.map +1 -0
  11. package/dist/components/llm_call_inspector/llm_call_inspector.d.ts +18 -0
  12. package/dist/components/llm_call_inspector/llm_call_inspector.d.ts.map +1 -0
  13. package/dist/components/llm_call_inspector/llm_call_inspector.js +103 -0
  14. package/dist/components/llm_call_inspector/llm_call_inspector.js.map +1 -0
  15. package/dist/components/llm_cost_dashboard/index.d.ts +6 -0
  16. package/dist/components/llm_cost_dashboard/index.d.ts.map +1 -0
  17. package/dist/components/llm_cost_dashboard/index.js +5 -0
  18. package/dist/components/llm_cost_dashboard/index.js.map +1 -0
  19. package/dist/components/llm_cost_dashboard/llm_cost_dashboard.d.ts +16 -0
  20. package/dist/components/llm_cost_dashboard/llm_cost_dashboard.d.ts.map +1 -0
  21. package/dist/components/llm_cost_dashboard/llm_cost_dashboard.js +154 -0
  22. package/dist/components/llm_cost_dashboard/llm_cost_dashboard.js.map +1 -0
  23. package/dist/index.d.ts +2 -1
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/lib/cascade/cascade_runner.d.ts +50 -0
  26. package/dist/lib/cascade/cascade_runner.d.ts.map +1 -0
  27. package/dist/lib/cascade/cascade_runner.js +115 -0
  28. package/dist/lib/cascade/cascade_runner.js.map +1 -0
  29. package/dist/lib/cascade/index.d.ts +5 -0
  30. package/dist/lib/cascade/index.d.ts.map +1 -0
  31. package/dist/lib/cascade/index.js +4 -0
  32. package/dist/lib/cascade/index.js.map +1 -0
  33. package/dist/lib/cascade/types.d.ts +35 -0
  34. package/dist/lib/cascade/types.d.ts.map +1 -0
  35. package/dist/lib/cascade/types.js +14 -0
  36. package/dist/lib/cascade/types.js.map +1 -0
  37. package/dist/lib/cost_cap/cost_cap.d.ts +40 -0
  38. package/dist/lib/cost_cap/cost_cap.d.ts.map +1 -0
  39. package/dist/lib/cost_cap/cost_cap.js +150 -0
  40. package/dist/lib/cost_cap/cost_cap.js.map +1 -0
  41. package/dist/lib/cost_cap/index.d.ts +3 -0
  42. package/dist/lib/cost_cap/index.d.ts.map +1 -0
  43. package/dist/lib/cost_cap/index.js +2 -0
  44. package/dist/lib/cost_cap/index.js.map +1 -0
  45. package/dist/lib/database/init_api_log.d.ts +10 -0
  46. package/dist/lib/database/init_api_log.d.ts.map +1 -0
  47. package/dist/lib/database/init_api_log.js +91 -0
  48. package/dist/lib/database/init_api_log.js.map +1 -0
  49. package/dist/lib/hazo_connect/direct_db_connect.d.ts +11 -7
  50. package/dist/lib/hazo_connect/direct_db_connect.d.ts.map +1 -1
  51. package/dist/lib/hazo_connect/direct_db_connect.js +59 -6
  52. package/dist/lib/hazo_connect/direct_db_connect.js.map +1 -1
  53. package/dist/lib/hazo_connect/types.d.ts +35 -3
  54. package/dist/lib/hazo_connect/types.d.ts.map +1 -1
  55. package/dist/lib/llm_api/embed_cache.d.ts +15 -0
  56. package/dist/lib/llm_api/embed_cache.d.ts.map +1 -0
  57. package/dist/lib/llm_api/embed_cache.js +53 -0
  58. package/dist/lib/llm_api/embed_cache.js.map +1 -0
  59. package/dist/lib/llm_api/hazo_llm_document_text.d.ts.map +1 -1
  60. package/dist/lib/llm_api/hazo_llm_document_text.js +56 -14
  61. package/dist/lib/llm_api/hazo_llm_document_text.js.map +1 -1
  62. package/dist/lib/llm_api/hazo_llm_dynamic_data_extract.d.ts.map +1 -1
  63. package/dist/lib/llm_api/hazo_llm_dynamic_data_extract.js +19 -1
  64. package/dist/lib/llm_api/hazo_llm_dynamic_data_extract.js.map +1 -1
  65. package/dist/lib/llm_api/hazo_llm_embed.d.ts +10 -0
  66. package/dist/lib/llm_api/hazo_llm_embed.d.ts.map +1 -0
  67. package/dist/lib/llm_api/hazo_llm_embed.js +80 -0
  68. package/dist/lib/llm_api/hazo_llm_embed.js.map +1 -0
  69. package/dist/lib/llm_api/hazo_llm_image_image.d.ts.map +1 -1
  70. package/dist/lib/llm_api/hazo_llm_image_image.js +56 -14
  71. package/dist/lib/llm_api/hazo_llm_image_image.js.map +1 -1
  72. package/dist/lib/llm_api/hazo_llm_image_text.d.ts.map +1 -1
  73. package/dist/lib/llm_api/hazo_llm_image_text.js +56 -14
  74. package/dist/lib/llm_api/hazo_llm_image_text.js.map +1 -1
  75. package/dist/lib/llm_api/hazo_llm_prompt_chain.d.ts.map +1 -1
  76. package/dist/lib/llm_api/hazo_llm_prompt_chain.js +17 -1
  77. package/dist/lib/llm_api/hazo_llm_prompt_chain.js.map +1 -1
  78. package/dist/lib/llm_api/hazo_llm_text_image.d.ts.map +1 -1
  79. package/dist/lib/llm_api/hazo_llm_text_image.js +56 -14
  80. package/dist/lib/llm_api/hazo_llm_text_image.js.map +1 -1
  81. package/dist/lib/llm_api/hazo_llm_text_text.d.ts.map +1 -1
  82. package/dist/lib/llm_api/hazo_llm_text_text.js +90 -15
  83. package/dist/lib/llm_api/hazo_llm_text_text.js.map +1 -1
  84. package/dist/lib/llm_api/index.d.ts +29 -1
  85. package/dist/lib/llm_api/index.d.ts.map +1 -1
  86. package/dist/lib/llm_api/index.js +433 -6
  87. package/dist/lib/llm_api/index.js.map +1 -1
  88. package/dist/lib/llm_api/prompt_parts_helper.d.ts +15 -0
  89. package/dist/lib/llm_api/prompt_parts_helper.d.ts.map +1 -0
  90. package/dist/lib/llm_api/prompt_parts_helper.js +9 -0
  91. package/dist/lib/llm_api/prompt_parts_helper.js.map +1 -0
  92. package/dist/lib/llm_api/types.d.ts +187 -2
  93. package/dist/lib/llm_api/types.d.ts.map +1 -1
  94. package/dist/lib/llm_api/types.js +4 -0
  95. package/dist/lib/llm_api/types.js.map +1 -1
  96. package/dist/lib/maintenance/purge_log_job.d.ts +23 -0
  97. package/dist/lib/maintenance/purge_log_job.d.ts.map +1 -0
  98. package/dist/lib/maintenance/purge_log_job.js +42 -0
  99. package/dist/lib/maintenance/purge_log_job.js.map +1 -0
  100. package/dist/lib/observability/log_context.d.ts +15 -0
  101. package/dist/lib/observability/log_context.d.ts.map +1 -0
  102. package/dist/lib/observability/log_context.js +32 -0
  103. package/dist/lib/observability/log_context.js.map +1 -0
  104. package/dist/lib/observability/log_writer.d.ts +35 -0
  105. package/dist/lib/observability/log_writer.d.ts.map +1 -0
  106. package/dist/lib/observability/log_writer.js +106 -0
  107. package/dist/lib/observability/log_writer.js.map +1 -0
  108. package/dist/lib/observability/queries.d.ts +15 -0
  109. package/dist/lib/observability/queries.d.ts.map +1 -0
  110. package/dist/lib/observability/queries.js +78 -0
  111. package/dist/lib/observability/queries.js.map +1 -0
  112. package/dist/lib/observability/types.d.ts +77 -0
  113. package/dist/lib/observability/types.d.ts.map +1 -0
  114. package/dist/lib/observability/types.js +8 -0
  115. package/dist/lib/observability/types.js.map +1 -0
  116. package/dist/lib/pricing/pricing.d.ts +49 -0
  117. package/dist/lib/pricing/pricing.d.ts.map +1 -0
  118. package/dist/lib/pricing/pricing.js +153 -0
  119. package/dist/lib/pricing/pricing.js.map +1 -0
  120. package/dist/lib/pricing/pricing.json +75 -0
  121. package/dist/lib/pricing/types.d.ts +58 -0
  122. package/dist/lib/pricing/types.d.ts.map +1 -0
  123. package/dist/lib/pricing/types.js +8 -0
  124. package/dist/lib/pricing/types.js.map +1 -0
  125. package/dist/lib/providers/anthropic/anthropic_client.d.ts +71 -0
  126. package/dist/lib/providers/anthropic/anthropic_client.d.ts.map +1 -0
  127. package/dist/lib/providers/anthropic/anthropic_client.js +134 -0
  128. package/dist/lib/providers/anthropic/anthropic_client.js.map +1 -0
  129. package/dist/lib/providers/anthropic/anthropic_provider.d.ts +60 -0
  130. package/dist/lib/providers/anthropic/anthropic_provider.d.ts.map +1 -0
  131. package/dist/lib/providers/anthropic/anthropic_provider.js +273 -0
  132. package/dist/lib/providers/anthropic/anthropic_provider.js.map +1 -0
  133. package/dist/lib/providers/anthropic/anthropic_response_to_usage.d.ts +21 -0
  134. package/dist/lib/providers/anthropic/anthropic_response_to_usage.d.ts.map +1 -0
  135. package/dist/lib/providers/anthropic/anthropic_response_to_usage.js +46 -0
  136. package/dist/lib/providers/anthropic/anthropic_response_to_usage.js.map +1 -0
  137. package/dist/lib/providers/anthropic/index.d.ts +3 -0
  138. package/dist/lib/providers/anthropic/index.d.ts.map +1 -0
  139. package/dist/lib/providers/anthropic/index.js +2 -0
  140. package/dist/lib/providers/anthropic/index.js.map +1 -0
  141. package/dist/lib/providers/deepseek/deepseek_client.d.ts +55 -0
  142. package/dist/lib/providers/deepseek/deepseek_client.d.ts.map +1 -0
  143. package/dist/lib/providers/deepseek/deepseek_client.js +129 -0
  144. package/dist/lib/providers/deepseek/deepseek_client.js.map +1 -0
  145. package/dist/lib/providers/deepseek/deepseek_provider.d.ts +50 -0
  146. package/dist/lib/providers/deepseek/deepseek_provider.d.ts.map +1 -0
  147. package/dist/lib/providers/deepseek/deepseek_provider.js +147 -0
  148. package/dist/lib/providers/deepseek/deepseek_provider.js.map +1 -0
  149. package/dist/lib/providers/deepseek/deepseek_response_to_usage.d.ts +21 -0
  150. package/dist/lib/providers/deepseek/deepseek_response_to_usage.d.ts.map +1 -0
  151. package/dist/lib/providers/deepseek/deepseek_response_to_usage.js +40 -0
  152. package/dist/lib/providers/deepseek/deepseek_response_to_usage.js.map +1 -0
  153. package/dist/lib/providers/deepseek/index.d.ts +3 -0
  154. package/dist/lib/providers/deepseek/index.d.ts.map +1 -0
  155. package/dist/lib/providers/deepseek/index.js +2 -0
  156. package/dist/lib/providers/deepseek/index.js.map +1 -0
  157. package/dist/lib/providers/gemini/gemini_provider.d.ts.map +1 -1
  158. package/dist/lib/providers/gemini/gemini_provider.js +40 -4
  159. package/dist/lib/providers/gemini/gemini_provider.js.map +1 -1
  160. package/dist/lib/providers/gemini/gemini_response_to_usage.d.ts +37 -0
  161. package/dist/lib/providers/gemini/gemini_response_to_usage.d.ts.map +1 -0
  162. package/dist/lib/providers/gemini/gemini_response_to_usage.js +49 -0
  163. package/dist/lib/providers/gemini/gemini_response_to_usage.js.map +1 -0
  164. package/dist/lib/providers/index.d.ts +3 -0
  165. package/dist/lib/providers/index.d.ts.map +1 -1
  166. package/dist/lib/providers/index.js +3 -0
  167. package/dist/lib/providers/index.js.map +1 -1
  168. package/dist/lib/providers/openai/index.d.ts +3 -0
  169. package/dist/lib/providers/openai/index.d.ts.map +1 -0
  170. package/dist/lib/providers/openai/index.js +2 -0
  171. package/dist/lib/providers/openai/index.js.map +1 -0
  172. package/dist/lib/providers/openai/openai_client.d.ts +99 -0
  173. package/dist/lib/providers/openai/openai_client.d.ts.map +1 -0
  174. package/dist/lib/providers/openai/openai_client.js +187 -0
  175. package/dist/lib/providers/openai/openai_client.js.map +1 -0
  176. package/dist/lib/providers/openai/openai_provider.d.ts +66 -0
  177. package/dist/lib/providers/openai/openai_provider.d.ts.map +1 -0
  178. package/dist/lib/providers/openai/openai_provider.js +297 -0
  179. package/dist/lib/providers/openai/openai_provider.js.map +1 -0
  180. package/dist/lib/providers/openai/openai_response_to_usage.d.ts +21 -0
  181. package/dist/lib/providers/openai/openai_response_to_usage.d.ts.map +1 -0
  182. package/dist/lib/providers/openai/openai_response_to_usage.js +50 -0
  183. package/dist/lib/providers/openai/openai_response_to_usage.js.map +1 -0
  184. package/dist/lib/providers/qwen/qwen_provider.d.ts.map +1 -1
  185. package/dist/lib/providers/qwen/qwen_provider.js +52 -5
  186. package/dist/lib/providers/qwen/qwen_provider.js.map +1 -1
  187. package/dist/lib/providers/qwen/qwen_response_to_usage.d.ts +36 -0
  188. package/dist/lib/providers/qwen/qwen_response_to_usage.d.ts.map +1 -0
  189. package/dist/lib/providers/qwen/qwen_response_to_usage.js +50 -0
  190. package/dist/lib/providers/qwen/qwen_response_to_usage.js.map +1 -0
  191. package/dist/lib/providers/types.d.ts +16 -6
  192. package/dist/lib/providers/types.d.ts.map +1 -1
  193. package/dist/lib/providers/types.js +1 -0
  194. package/dist/lib/providers/types.js.map +1 -1
  195. package/dist/lib/utils.d.ts +13 -0
  196. package/dist/lib/utils.d.ts.map +1 -0
  197. package/dist/lib/utils.js +16 -0
  198. package/dist/lib/utils.js.map +1 -0
  199. package/dist/server.d.ts +16 -2
  200. package/dist/server.d.ts.map +1 -1
  201. package/dist/server.js +29 -2
  202. package/dist/server.js.map +1 -1
  203. package/migrations/hazo_llm_api_log.sql +69 -0
  204. package/package.json +26 -11
@@ -0,0 +1,99 @@
1
+ /**
2
+ * OpenAI API Client Module
3
+ *
4
+ * Handles communication with the OpenAI Chat Completions API and Image Generation API.
5
+ * Uses the standard OpenAI API format (also compatible with many other providers).
6
+ */
7
+ import type { LLMStreamChunk } from '../../llm_api/types.js';
8
+ /**
9
+ * OpenAI message role
10
+ */
11
+ export interface OpenAIMessage {
12
+ role: 'user' | 'assistant' | 'system';
13
+ content: string | OpenAIContentItem[];
14
+ }
15
+ /**
16
+ * OpenAI content item for multimodal messages
17
+ */
18
+ export type OpenAIContentItem = {
19
+ type: 'text';
20
+ text: string;
21
+ } | {
22
+ type: 'image_url';
23
+ image_url: {
24
+ url: string;
25
+ };
26
+ };
27
+ /**
28
+ * OpenAI generation configuration parameters
29
+ */
30
+ export interface OpenAIGenerationConfig {
31
+ /** Controls randomness in output (0.0-2.0). Lower = more deterministic */
32
+ temperature?: number;
33
+ /** Nucleus sampling probability (0.0-1.0) */
34
+ top_p?: number;
35
+ /** Maximum number of tokens in the response */
36
+ max_tokens?: number;
37
+ /** Penalizes new tokens based on whether they appear in the text so far */
38
+ frequency_penalty?: number;
39
+ /** Penalizes new tokens based on whether they appear in the text at all */
40
+ presence_penalty?: number;
41
+ }
42
+ /**
43
+ * Call the OpenAI Chat Completions API (non-streaming)
44
+ * @param opts - API call options
45
+ * @returns Raw API response and HTTP status code
46
+ */
47
+ export declare function call_openai_api(opts: {
48
+ api_key: string;
49
+ api_url: string;
50
+ model: string;
51
+ messages: OpenAIMessage[];
52
+ generation_config?: OpenAIGenerationConfig;
53
+ }): Promise<{
54
+ raw: Record<string, unknown>;
55
+ status: number;
56
+ }>;
57
+ /**
58
+ * Call the OpenAI Image Generation API
59
+ * @param opts - API call options
60
+ * @returns Raw API response and HTTP status code
61
+ */
62
+ export declare function call_openai_image_api(opts: {
63
+ api_key: string;
64
+ api_url_image: string;
65
+ model: string;
66
+ prompt: string;
67
+ }): Promise<{
68
+ raw: Record<string, unknown>;
69
+ status: number;
70
+ }>;
71
+ /**
72
+ * Call the OpenAI Embeddings API
73
+ * @param opts - API call options
74
+ * @returns Raw API response and HTTP status code
75
+ */
76
+ export declare function call_openai_embed_api(opts: {
77
+ api_key: string;
78
+ api_url_embed: string;
79
+ model: string;
80
+ input: string | string[];
81
+ }): Promise<{
82
+ raw: Record<string, unknown>;
83
+ status: number;
84
+ }>;
85
+ /**
86
+ * Call the OpenAI Chat Completions API with streaming enabled.
87
+ * Yields LLMStreamChunk objects as SSE events arrive.
88
+ *
89
+ * @param opts - API call options
90
+ * @yields LLMStreamChunk objects with text deltas or done/error signals
91
+ */
92
+ export declare function call_openai_api_stream(opts: {
93
+ api_key: string;
94
+ api_url: string;
95
+ model: string;
96
+ messages: OpenAIMessage[];
97
+ generation_config?: OpenAIGenerationConfig;
98
+ }): AsyncGenerator<LLMStreamChunk, void, unknown>;
99
+ //# sourceMappingURL=openai_client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai_client.d.ts","sourceRoot":"","sources":["../../../../src/lib/providers/openai/openai_client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAM7D;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACtC,OAAO,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAAC;CACvC;AAED;;GAEG;AACH,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAEtD;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,2EAA2E;IAC3E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAMD;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,iBAAiB,CAAC,EAAE,sBAAsB,CAAC;CAC5C,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAmC5D;AAMD;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAkB5D;AAMD;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC1B,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAa5D;AAMD;;;;;;GAMG;AACH,wBAAuB,sBAAsB,CAAC,IAAI,EAAE;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,iBAAiB,CAAC,EAAE,sBAAsB,CAAC;CAC5C,GAAG,cAAc,CAAC,cAAc,EAAE,IAAI,EAAE,OAAO,CAAC,CAuFhD"}
@@ -0,0 +1,187 @@
1
+ /**
2
+ * OpenAI API Client Module
3
+ *
4
+ * Handles communication with the OpenAI Chat Completions API and Image Generation API.
5
+ * Uses the standard OpenAI API format (also compatible with many other providers).
6
+ */
7
+ // =============================================================================
8
+ // OpenAI Chat Completions API Client
9
+ // =============================================================================
10
+ /**
11
+ * Call the OpenAI Chat Completions API (non-streaming)
12
+ * @param opts - API call options
13
+ * @returns Raw API response and HTTP status code
14
+ */
15
+ export async function call_openai_api(opts) {
16
+ const body = {
17
+ model: opts.model,
18
+ messages: opts.messages,
19
+ };
20
+ if (opts.generation_config) {
21
+ if (opts.generation_config.temperature !== undefined) {
22
+ body.temperature = opts.generation_config.temperature;
23
+ }
24
+ if (opts.generation_config.top_p !== undefined) {
25
+ body.top_p = opts.generation_config.top_p;
26
+ }
27
+ if (opts.generation_config.max_tokens !== undefined) {
28
+ body.max_tokens = opts.generation_config.max_tokens;
29
+ }
30
+ if (opts.generation_config.frequency_penalty !== undefined) {
31
+ body.frequency_penalty = opts.generation_config.frequency_penalty;
32
+ }
33
+ if (opts.generation_config.presence_penalty !== undefined) {
34
+ body.presence_penalty = opts.generation_config.presence_penalty;
35
+ }
36
+ }
37
+ const response = await fetch(opts.api_url, {
38
+ method: 'POST',
39
+ headers: {
40
+ 'Authorization': `Bearer ${opts.api_key}`,
41
+ 'Content-Type': 'application/json',
42
+ },
43
+ body: JSON.stringify(body),
44
+ });
45
+ const raw = (await response.json());
46
+ return { raw, status: response.status };
47
+ }
48
+ // =============================================================================
49
+ // OpenAI Image Generation API Client
50
+ // =============================================================================
51
+ /**
52
+ * Call the OpenAI Image Generation API
53
+ * @param opts - API call options
54
+ * @returns Raw API response and HTTP status code
55
+ */
56
+ export async function call_openai_image_api(opts) {
57
+ const body = {
58
+ model: opts.model,
59
+ prompt: opts.prompt,
60
+ response_format: 'b64_json',
61
+ };
62
+ const response = await fetch(opts.api_url_image, {
63
+ method: 'POST',
64
+ headers: {
65
+ 'Authorization': `Bearer ${opts.api_key}`,
66
+ 'Content-Type': 'application/json',
67
+ },
68
+ body: JSON.stringify(body),
69
+ });
70
+ const raw = (await response.json());
71
+ return { raw, status: response.status };
72
+ }
73
+ // =============================================================================
74
+ // OpenAI Streaming API Client
75
+ // =============================================================================
76
+ /**
77
+ * Call the OpenAI Embeddings API
78
+ * @param opts - API call options
79
+ * @returns Raw API response and HTTP status code
80
+ */
81
+ export async function call_openai_embed_api(opts) {
82
+ const { api_key, api_url_embed, model, input } = opts;
83
+ const response = await fetch(api_url_embed, {
84
+ method: 'POST',
85
+ headers: {
86
+ 'Authorization': `Bearer ${api_key}`,
87
+ 'Content-Type': 'application/json',
88
+ },
89
+ body: JSON.stringify({ model, input }),
90
+ });
91
+ const raw = (await response.json());
92
+ return { raw, status: response.status };
93
+ }
94
+ // =============================================================================
95
+ // OpenAI Streaming API Client
96
+ // =============================================================================
97
+ /**
98
+ * Call the OpenAI Chat Completions API with streaming enabled.
99
+ * Yields LLMStreamChunk objects as SSE events arrive.
100
+ *
101
+ * @param opts - API call options
102
+ * @yields LLMStreamChunk objects with text deltas or done/error signals
103
+ */
104
+ export async function* call_openai_api_stream(opts) {
105
+ const body = {
106
+ model: opts.model,
107
+ messages: opts.messages,
108
+ stream: true,
109
+ };
110
+ if (opts.generation_config) {
111
+ if (opts.generation_config.temperature !== undefined) {
112
+ body.temperature = opts.generation_config.temperature;
113
+ }
114
+ if (opts.generation_config.top_p !== undefined) {
115
+ body.top_p = opts.generation_config.top_p;
116
+ }
117
+ if (opts.generation_config.max_tokens !== undefined) {
118
+ body.max_tokens = opts.generation_config.max_tokens;
119
+ }
120
+ if (opts.generation_config.frequency_penalty !== undefined) {
121
+ body.frequency_penalty = opts.generation_config.frequency_penalty;
122
+ }
123
+ if (opts.generation_config.presence_penalty !== undefined) {
124
+ body.presence_penalty = opts.generation_config.presence_penalty;
125
+ }
126
+ }
127
+ let response;
128
+ try {
129
+ response = await fetch(opts.api_url, {
130
+ method: 'POST',
131
+ headers: {
132
+ 'Authorization': `Bearer ${opts.api_key}`,
133
+ 'Content-Type': 'application/json',
134
+ },
135
+ body: JSON.stringify(body),
136
+ });
137
+ }
138
+ catch (err) {
139
+ const msg = err instanceof Error ? err.message : String(err);
140
+ yield { text: '', done: false, error: `OpenAI network error: ${msg}` };
141
+ return;
142
+ }
143
+ if (!response.ok || !response.body) {
144
+ yield { text: '', done: false, error: `OpenAI API error: ${response.status}` };
145
+ return;
146
+ }
147
+ const reader = response.body.getReader();
148
+ const decoder = new TextDecoder();
149
+ let buffer = '';
150
+ try {
151
+ while (true) {
152
+ const { done, value } = await reader.read();
153
+ if (done)
154
+ break;
155
+ buffer += decoder.decode(value, { stream: true });
156
+ const lines = buffer.split('\n');
157
+ buffer = lines.pop() ?? '';
158
+ for (const line of lines) {
159
+ if (!line.startsWith('data: '))
160
+ continue;
161
+ const data_str = line.slice(6).trim();
162
+ if (!data_str)
163
+ continue;
164
+ if (data_str === '[DONE]') {
165
+ yield { text: '', done: true };
166
+ return;
167
+ }
168
+ try {
169
+ const data = JSON.parse(data_str);
170
+ const choices = data.choices;
171
+ const delta = choices?.[0]?.delta;
172
+ const content = delta?.content;
173
+ if (content !== null && content !== undefined) {
174
+ yield { text: content, done: false };
175
+ }
176
+ }
177
+ catch {
178
+ // Ignore malformed SSE data lines
179
+ }
180
+ }
181
+ }
182
+ }
183
+ finally {
184
+ reader.releaseLock();
185
+ }
186
+ }
187
+ //# sourceMappingURL=openai_client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai_client.js","sourceRoot":"","sources":["../../../../src/lib/providers/openai/openai_client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * OpenAI Provider Implementation
3
+ *
4
+ * Implements the LLMProvider interface for the OpenAI API.
5
+ * Handles text generation, image understanding, image generation, and streaming.
6
+ */
7
+ import type { LLMProvider, LLMCapabilities, ServiceType } from '../types.js';
8
+ import type { TextTextParams, ImageTextParams, TextImageParams, ImageImageParams, DocumentTextParams, EmbedParams, EmbedResponse, LLMResponse, LLMStreamResponse, Logger } from '../../llm_api/types.js';
9
+ import { type OpenAIGenerationConfig } from './openai_client.js';
10
+ /**
11
+ * Configuration for the OpenAI provider
12
+ */
13
+ export interface OpenAIProviderConfig {
14
+ /** API key from .env.local (OPENAI_API_KEY) */
15
+ api_key: string;
16
+ /** Chat completions API URL (default: 'https://api.openai.com/v1/chat/completions') */
17
+ api_url?: string;
18
+ /** Image generation API URL (default: 'https://api.openai.com/v1/images/generations') */
19
+ api_url_image?: string;
20
+ /** Embeddings API URL (default: 'https://api.openai.com/v1/embeddings') */
21
+ api_url_embed?: string;
22
+ /** Model for text_text service (default: 'gpt-4o') */
23
+ model_text_text?: string;
24
+ /** Model for image_text service (default: 'gpt-4o') */
25
+ model_image_text?: string;
26
+ /** Model for text_image service (default: 'gpt-image-1') */
27
+ model_text_image?: string;
28
+ /** Model for embed service (default: 'text-embedding-3-small') */
29
+ model_embed?: string;
30
+ /** Generation parameters applied to text calls */
31
+ generation_config?: OpenAIGenerationConfig;
32
+ /** Capabilities this provider supports (overrides defaults when specified) */
33
+ capabilities?: ServiceType[];
34
+ /** Logger instance */
35
+ logger: Logger;
36
+ }
37
+ /**
38
+ * OpenAI LLM Provider
39
+ * Implements the LLMProvider interface for the OpenAI API
40
+ */
41
+ export declare class OpenAIProvider implements LLMProvider {
42
+ private readonly name;
43
+ private readonly api_key;
44
+ private readonly api_url;
45
+ private readonly api_url_image;
46
+ private readonly api_url_embed;
47
+ private readonly model_text_text;
48
+ private readonly model_image_text;
49
+ private readonly model_text_image;
50
+ private readonly model_embed;
51
+ private readonly generation_config;
52
+ private readonly capabilities;
53
+ private readonly logger;
54
+ constructor(config: OpenAIProviderConfig);
55
+ get_name(): string;
56
+ get_capabilities(): LLMCapabilities;
57
+ get_model_for_service(service_type: ServiceType): string | undefined;
58
+ text_text(params: TextTextParams, _logger: Logger): Promise<LLMResponse>;
59
+ image_text(params: ImageTextParams, _logger: Logger): Promise<LLMResponse>;
60
+ text_image(params: TextImageParams, _logger: Logger): Promise<LLMResponse>;
61
+ text_text_stream(params: TextTextParams, _logger: Logger): Promise<LLMStreamResponse>;
62
+ embed(params: EmbedParams, _logger: Logger): Promise<EmbedResponse>;
63
+ image_image(_params: ImageImageParams, _logger: Logger): Promise<LLMResponse>;
64
+ document_text(_params: DocumentTextParams, _logger: Logger): Promise<LLMResponse>;
65
+ }
66
+ //# sourceMappingURL=openai_provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai_provider.d.ts","sourceRoot":"","sources":["../../../../src/lib/providers/openai/openai_provider.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,eAAe,EACf,WAAW,EACZ,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,MAAM,EACP,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAML,KAAK,sBAAsB,EAC5B,MAAM,oBAAoB,CAAC;AAmB5B;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAC;IAEhB,uFAAuF;IACvF,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,yFAAyF;IACzF,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,2EAA2E;IAC3E,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,sDAAsD;IACtD,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,uDAAuD;IACvD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,4DAA4D;IAC5D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,kDAAkD;IAClD,iBAAiB,CAAC,EAAE,sBAAsB,CAAC;IAE3C,8EAA8E;IAC9E,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;IAE7B,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB;AAMD;;;GAGG;AACH,qBAAa,cAAe,YAAW,WAAW;IAChD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAY;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAqC;IACvE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkB;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,MAAM,EAAE,oBAAoB;IA6BxC,QAAQ,IAAI,MAAM;IAIlB,gBAAgB,IAAI,eAAe;IAInC,qBAAqB,CAAC,YAAY,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS;IAmB9D,SAAS,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAqDxE,UAAU,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IA6D1E,UAAU,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAqD1E,gBAAgB,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAmBrF,KAAK,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAqDnE,WAAW,CAAC,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAO7E,aAAa,CAAC,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;CAMxF"}
@@ -0,0 +1,297 @@
1
+ /**
2
+ * OpenAI Provider Implementation
3
+ *
4
+ * Implements the LLMProvider interface for the OpenAI API.
5
+ * Handles text generation, image understanding, image generation, and streaming.
6
+ */
7
+ import { SERVICE_TYPES } from '../types.js';
8
+ import { call_openai_api, call_openai_image_api, call_openai_api_stream, call_openai_embed_api, } from './openai_client.js';
9
+ import { openai_response_to_usage } from './openai_response_to_usage.js';
10
+ // =============================================================================
11
+ // Default constants
12
+ // =============================================================================
13
+ const DEFAULT_API_URL = 'https://api.openai.com/v1/chat/completions';
14
+ const DEFAULT_API_URL_IMAGE = 'https://api.openai.com/v1/images/generations';
15
+ const DEFAULT_API_URL_EMBED = 'https://api.openai.com/v1/embeddings';
16
+ const DEFAULT_MODEL_TEXT_TEXT = 'gpt-4o';
17
+ const DEFAULT_MODEL_IMAGE_TEXT = 'gpt-4o';
18
+ const DEFAULT_MODEL_TEXT_IMAGE = 'gpt-image-1';
19
+ const DEFAULT_MODEL_EMBED = 'text-embedding-3-small';
20
+ // =============================================================================
21
+ // OpenAI Provider Class
22
+ // =============================================================================
23
+ /**
24
+ * OpenAI LLM Provider
25
+ * Implements the LLMProvider interface for the OpenAI API
26
+ */
27
+ export class OpenAIProvider {
28
+ constructor(config) {
29
+ this.name = 'openai';
30
+ this.api_key = config.api_key;
31
+ this.api_url = config.api_url ?? DEFAULT_API_URL;
32
+ this.api_url_image = config.api_url_image ?? DEFAULT_API_URL_IMAGE;
33
+ this.api_url_embed = config.api_url_embed ?? DEFAULT_API_URL_EMBED;
34
+ this.model_text_text = config.model_text_text ?? DEFAULT_MODEL_TEXT_TEXT;
35
+ this.model_image_text = config.model_image_text ?? DEFAULT_MODEL_IMAGE_TEXT;
36
+ this.model_text_image = config.model_text_image ?? DEFAULT_MODEL_TEXT_IMAGE;
37
+ this.model_embed = config.model_embed ?? DEFAULT_MODEL_EMBED;
38
+ this.generation_config = config.generation_config;
39
+ this.logger = config.logger;
40
+ if (config.capabilities && config.capabilities.length > 0) {
41
+ this.capabilities = new Set(config.capabilities);
42
+ }
43
+ else {
44
+ this.capabilities = new Set([
45
+ SERVICE_TYPES.TEXT_TEXT,
46
+ SERVICE_TYPES.IMAGE_TEXT,
47
+ SERVICE_TYPES.TEXT_IMAGE,
48
+ SERVICE_TYPES.EMBED,
49
+ 'text_text_stream',
50
+ ]);
51
+ }
52
+ }
53
+ // =========================================================================
54
+ // LLMProvider interface — identity & introspection
55
+ // =========================================================================
56
+ get_name() {
57
+ return this.name;
58
+ }
59
+ get_capabilities() {
60
+ return new Set(this.capabilities);
61
+ }
62
+ get_model_for_service(service_type) {
63
+ switch (service_type) {
64
+ case SERVICE_TYPES.TEXT_TEXT:
65
+ return this.model_text_text;
66
+ case SERVICE_TYPES.IMAGE_TEXT:
67
+ return this.model_image_text;
68
+ case SERVICE_TYPES.TEXT_IMAGE:
69
+ return this.model_text_image;
70
+ case SERVICE_TYPES.EMBED:
71
+ return this.model_embed;
72
+ default:
73
+ return undefined;
74
+ }
75
+ }
76
+ // =========================================================================
77
+ // text_text — Text input → Text output
78
+ // =========================================================================
79
+ async text_text(params, _logger) {
80
+ const model = this.model_text_text;
81
+ const messages = [
82
+ { role: 'user', content: params.prompt ?? '' },
83
+ ];
84
+ const start_time = Date.now();
85
+ let raw;
86
+ let status;
87
+ try {
88
+ ({ raw, status } = await call_openai_api({
89
+ api_key: this.api_key,
90
+ api_url: this.api_url,
91
+ model,
92
+ messages,
93
+ generation_config: this.generation_config,
94
+ }));
95
+ }
96
+ catch (err) {
97
+ const error = err instanceof Error ? err.message : String(err);
98
+ return { success: false, error, error_code: 'NETWORK_ERROR', retryable: true };
99
+ }
100
+ const latency_ms = Date.now() - start_time;
101
+ if (status >= 400) {
102
+ const error_code = status === 429 ? 'RATE_LIMITED' : 'API_ERROR';
103
+ return {
104
+ success: false,
105
+ error: `OpenAI API error: ${status}`,
106
+ error_code,
107
+ retryable: error_code === 'RATE_LIMITED',
108
+ };
109
+ }
110
+ const choices = raw.choices;
111
+ const message = choices?.[0]?.message;
112
+ const data = message?.content;
113
+ const usage = openai_response_to_usage({ raw, model_fallback: model, latency_ms });
114
+ return {
115
+ success: true,
116
+ data,
117
+ text: data,
118
+ raw_response: raw,
119
+ usage,
120
+ };
121
+ }
122
+ // =========================================================================
123
+ // image_text — Image input → Text output
124
+ // =========================================================================
125
+ async image_text(params, _logger) {
126
+ const model = this.model_image_text;
127
+ const url = `data:${params.image_mime_type};base64,${params.image_b64}`;
128
+ const messages = [
129
+ {
130
+ role: 'user',
131
+ content: [
132
+ { type: 'image_url', image_url: { url } },
133
+ { type: 'text', text: params.prompt },
134
+ ],
135
+ },
136
+ ];
137
+ const start_time = Date.now();
138
+ let raw;
139
+ let status;
140
+ try {
141
+ ({ raw, status } = await call_openai_api({
142
+ api_key: this.api_key,
143
+ api_url: this.api_url,
144
+ model,
145
+ messages,
146
+ generation_config: this.generation_config,
147
+ }));
148
+ }
149
+ catch (err) {
150
+ const error = err instanceof Error ? err.message : String(err);
151
+ return { success: false, error, error_code: 'NETWORK_ERROR', retryable: true };
152
+ }
153
+ const latency_ms = Date.now() - start_time;
154
+ if (status >= 400) {
155
+ const error_code = status === 429 ? 'RATE_LIMITED' : 'API_ERROR';
156
+ return {
157
+ success: false,
158
+ error: `OpenAI API error: ${status}`,
159
+ error_code,
160
+ retryable: error_code === 'RATE_LIMITED',
161
+ };
162
+ }
163
+ const choices = raw.choices;
164
+ const message = choices?.[0]?.message;
165
+ const data = message?.content;
166
+ const usage = openai_response_to_usage({ raw, model_fallback: model, latency_ms });
167
+ return {
168
+ success: true,
169
+ data,
170
+ text: data,
171
+ raw_response: raw,
172
+ usage,
173
+ };
174
+ }
175
+ // =========================================================================
176
+ // text_image — Text input → Image output
177
+ // =========================================================================
178
+ async text_image(params, _logger) {
179
+ const model = this.model_text_image;
180
+ const start_time = Date.now();
181
+ let raw;
182
+ let status;
183
+ try {
184
+ ({ raw, status } = await call_openai_image_api({
185
+ api_key: this.api_key,
186
+ api_url_image: this.api_url_image,
187
+ model,
188
+ prompt: params.prompt,
189
+ }));
190
+ }
191
+ catch (err) {
192
+ const error = err instanceof Error ? err.message : String(err);
193
+ return { success: false, error, error_code: 'NETWORK_ERROR', retryable: true };
194
+ }
195
+ const latency_ms = Date.now() - start_time;
196
+ if (status >= 400) {
197
+ const error_code = status === 429 ? 'RATE_LIMITED' : 'API_ERROR';
198
+ return {
199
+ success: false,
200
+ error: `OpenAI API error: ${status}`,
201
+ error_code,
202
+ retryable: error_code === 'RATE_LIMITED',
203
+ };
204
+ }
205
+ const image_data_arr = raw.data;
206
+ const data = image_data_arr?.[0]?.b64_json;
207
+ return {
208
+ success: true,
209
+ data,
210
+ image_b64: data,
211
+ image_mime_type: 'image/png',
212
+ raw_response: raw,
213
+ usage: {
214
+ provider: 'openai',
215
+ model,
216
+ tokens: { input: 0, output: 0, total: 0 },
217
+ latency_ms,
218
+ },
219
+ };
220
+ }
221
+ // =========================================================================
222
+ // text_text_stream — Text input → streaming Text output
223
+ // =========================================================================
224
+ async text_text_stream(params, _logger) {
225
+ const model = this.model_text_text;
226
+ const messages = [
227
+ { role: 'user', content: params.prompt ?? '' },
228
+ ];
229
+ return call_openai_api_stream({
230
+ api_key: this.api_key,
231
+ api_url: this.api_url,
232
+ model,
233
+ messages,
234
+ generation_config: this.generation_config,
235
+ });
236
+ }
237
+ // =========================================================================
238
+ // embed — Text input → Vector embeddings output
239
+ // =========================================================================
240
+ async embed(params, _logger) {
241
+ const api_url_embed = this.api_url_embed;
242
+ const model = params.model ?? this.model_embed;
243
+ const start_time = Date.now();
244
+ const { raw, status } = await call_openai_embed_api({
245
+ api_key: this.api_key,
246
+ api_url_embed,
247
+ model,
248
+ input: params.text,
249
+ });
250
+ const latency_ms = Date.now() - start_time;
251
+ if (status >= 400) {
252
+ const error_code = status === 429 ? 'RATE_LIMITED' : 'API_ERROR';
253
+ return {
254
+ success: false,
255
+ error: `OpenAI Embeddings API error: ${status}`,
256
+ error_code,
257
+ };
258
+ }
259
+ // Sort data by index (OpenAI guarantees order but let's be safe)
260
+ const data = raw.data
261
+ .sort((a, b) => a.index - b.index);
262
+ const vectors = data.map(d => d.embedding);
263
+ const dimensions = vectors[0]?.length;
264
+ const usage_raw = raw.usage;
265
+ const input_tokens = usage_raw?.prompt_tokens ?? 0;
266
+ const total_tokens = usage_raw?.total_tokens ?? 0;
267
+ const response_model = typeof raw.model === 'string' ? raw.model : model;
268
+ return {
269
+ success: true,
270
+ vectors,
271
+ dimensions,
272
+ model: response_model,
273
+ usage: {
274
+ provider: 'openai',
275
+ model: response_model,
276
+ tokens: { input: input_tokens, output: 0, total: total_tokens },
277
+ latency_ms,
278
+ },
279
+ };
280
+ }
281
+ // =========================================================================
282
+ // Unsupported methods (satisfy LLMProvider interface completeness)
283
+ // =========================================================================
284
+ async image_image(_params, _logger) {
285
+ return {
286
+ success: false,
287
+ error: 'OpenAI provider does not support image_image via this implementation',
288
+ };
289
+ }
290
+ async document_text(_params, _logger) {
291
+ return {
292
+ success: false,
293
+ error: 'OpenAI provider does not support document_text via this implementation',
294
+ };
295
+ }
296
+ }
297
+ //# sourceMappingURL=openai_provider.js.map