@effect/ai-openai 4.0.0-beta.8 → 4.0.0-beta.80

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 (58) hide show
  1. package/dist/Generated.d.ts +66675 -37672
  2. package/dist/Generated.d.ts.map +1 -1
  3. package/dist/Generated.js +1 -1
  4. package/dist/Generated.js.map +1 -1
  5. package/dist/OpenAiClient.d.ts +170 -29
  6. package/dist/OpenAiClient.d.ts.map +1 -1
  7. package/dist/OpenAiClient.js +321 -46
  8. package/dist/OpenAiClient.js.map +1 -1
  9. package/dist/OpenAiClientGenerated.d.ts +91 -0
  10. package/dist/OpenAiClientGenerated.d.ts.map +1 -0
  11. package/dist/OpenAiClientGenerated.js +84 -0
  12. package/dist/OpenAiClientGenerated.js.map +1 -0
  13. package/dist/OpenAiConfig.d.ts +88 -10
  14. package/dist/OpenAiConfig.d.ts.map +1 -1
  15. package/dist/OpenAiConfig.js +42 -7
  16. package/dist/OpenAiConfig.js.map +1 -1
  17. package/dist/OpenAiEmbeddingModel.d.ts +188 -0
  18. package/dist/OpenAiEmbeddingModel.d.ts.map +1 -0
  19. package/dist/OpenAiEmbeddingModel.js +194 -0
  20. package/dist/OpenAiEmbeddingModel.js.map +1 -0
  21. package/dist/OpenAiError.d.ts +168 -35
  22. package/dist/OpenAiError.d.ts.map +1 -1
  23. package/dist/OpenAiError.js +1 -1
  24. package/dist/OpenAiLanguageModel.d.ts +357 -63
  25. package/dist/OpenAiLanguageModel.d.ts.map +1 -1
  26. package/dist/OpenAiLanguageModel.js +390 -168
  27. package/dist/OpenAiLanguageModel.js.map +1 -1
  28. package/dist/OpenAiSchema.d.ts +2325 -0
  29. package/dist/OpenAiSchema.d.ts.map +1 -0
  30. package/dist/OpenAiSchema.js +811 -0
  31. package/dist/OpenAiSchema.js.map +1 -0
  32. package/dist/OpenAiTelemetry.d.ts +63 -22
  33. package/dist/OpenAiTelemetry.d.ts.map +1 -1
  34. package/dist/OpenAiTelemetry.js +20 -10
  35. package/dist/OpenAiTelemetry.js.map +1 -1
  36. package/dist/OpenAiTool.d.ts +148 -62
  37. package/dist/OpenAiTool.d.ts.map +1 -1
  38. package/dist/OpenAiTool.js +125 -39
  39. package/dist/OpenAiTool.js.map +1 -1
  40. package/dist/index.d.ts +19 -33
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +19 -33
  43. package/dist/index.js.map +1 -1
  44. package/dist/internal/errors.js +4 -4
  45. package/dist/internal/errors.js.map +1 -1
  46. package/package.json +3 -3
  47. package/src/Generated.ts +9717 -4887
  48. package/src/OpenAiClient.ts +499 -98
  49. package/src/OpenAiClientGenerated.ts +202 -0
  50. package/src/OpenAiConfig.ts +89 -11
  51. package/src/OpenAiEmbeddingModel.ts +332 -0
  52. package/src/OpenAiError.ts +170 -35
  53. package/src/OpenAiLanguageModel.ts +776 -169
  54. package/src/OpenAiSchema.ts +1286 -0
  55. package/src/OpenAiTelemetry.ts +69 -28
  56. package/src/OpenAiTool.ts +126 -40
  57. package/src/index.ts +22 -33
  58. package/src/internal/errors.ts +6 -4
@@ -1,26 +1,30 @@
1
1
  /**
2
- * OpenAI Language Model implementation.
2
+ * The `OpenAiLanguageModel` module provides the OpenAI Responses API
3
+ * implementation of Effect AI's `LanguageModel` service. It translates Effect
4
+ * AI prompts, files, tools, structured output requests, reasoning metadata, and
5
+ * provider options into OpenAI response requests, then converts OpenAI
6
+ * non-streaming or streaming response results back into Effect AI response
7
+ * content and metadata.
3
8
  *
4
- * Provides a LanguageModel implementation for OpenAI's responses API,
5
- * supporting text generation, structured output, tool calling, and streaming.
6
- *
7
- * @since 1.0.0
9
+ * @since 4.0.0
8
10
  */
11
+ import * as Context from "effect/Context";
9
12
  import * as DateTime from "effect/DateTime";
10
13
  import * as Effect from "effect/Effect";
11
14
  import * as Encoding from "effect/Encoding";
12
15
  import { dual } from "effect/Function";
13
16
  import * as Layer from "effect/Layer";
17
+ import * as Option from "effect/Option";
14
18
  import * as Predicate from "effect/Predicate";
15
19
  import * as Redactable from "effect/Redactable";
16
20
  import * as Schema from "effect/Schema";
17
21
  import * as AST from "effect/SchemaAST";
18
- import * as ServiceMap from "effect/ServiceMap";
19
22
  import * as Stream from "effect/Stream";
20
23
  import * as AiError from "effect/unstable/ai/AiError";
21
24
  import * as IdGenerator from "effect/unstable/ai/IdGenerator";
22
25
  import * as LanguageModel from "effect/unstable/ai/LanguageModel";
23
26
  import * as AiModel from "effect/unstable/ai/Model";
27
+ import { toCodecOpenAI } from "effect/unstable/ai/OpenAiStructuredOutput";
24
28
  import * as Tool from "effect/unstable/ai/Tool";
25
29
  import * as Generated from "./Generated.js";
26
30
  import * as InternalUtilities from "./internal/utilities.js";
@@ -32,38 +36,77 @@ const SharedModelIds = Generated.ModelIdsShared.members[1];
32
36
  // Configuration
33
37
  // =============================================================================
34
38
  /**
35
- * Service definition for OpenAI language model configuration.
39
+ * Context service for OpenAI language model configuration.
40
+ *
41
+ * **When to use**
42
+ *
43
+ * Use when you need to provide OpenAI Responses API request defaults through
44
+ * Effect context for language model operations.
45
+ *
46
+ * **Details**
47
+ *
48
+ * Config values are merged with the config object passed to `model`, `make`, or
49
+ * `layer`, with scoped context values taking precedence.
50
+ *
51
+ * @see {@link withConfigOverride} for scoping language model request overrides
36
52
  *
37
- * @since 1.0.0
38
53
  * @category services
54
+ * @since 4.0.0
39
55
  */
40
- export class Config extends /*#__PURE__*/ServiceMap.Service()("@effect/ai-openai/OpenAiLanguageModel/Config") {}
56
+ export class Config extends /*#__PURE__*/Context.Service()("@effect/ai-openai/OpenAiLanguageModel/Config") {}
41
57
  // =============================================================================
42
58
  // Language Model
43
59
  // =============================================================================
44
60
  /**
45
- * @since 1.0.0
61
+ * Creates an OpenAI model descriptor that can be provided with
62
+ * `Effect.provide`.
63
+ *
64
+ * **When to use**
65
+ *
66
+ * Use when you want an OpenAI language model value that carries provider and
67
+ * model metadata and can be supplied directly to an Effect program.
68
+ *
69
+ * @see {@link layer} for creating a `LanguageModel.LanguageModel` layer directly
70
+ * @see {@link make} for constructing the language model service effectfully
71
+ *
46
72
  * @category constructors
73
+ * @since 4.0.0
47
74
  */
48
- export const model = (model, config) => AiModel.make("openai", layer({
75
+ export const model = (model, config) => AiModel.make("openai", model, layer({
49
76
  model,
50
77
  config
51
78
  }));
52
79
  // TODO
53
80
  // /**
54
- // * @since 1.0.0
81
+ // * @since 4.0.0
55
82
  // * @category constructors
56
83
  // */
57
84
  // export const modelWithTokenizer = (
58
85
  // model: (string & {}) | Model,
59
86
  // config?: Omit<typeof Config.Service, "model">
60
87
  // ): AiModel.Model<"openai", LanguageModel.LanguageModel | Tokenizer.Tokenizer, OpenAiClient> =>
61
- // AiModel.make("openai", layerWithTokenizer({ model, config }))
88
+ // AiModel.make("openai", model, layerWithTokenizer({ model, config }))
62
89
  /**
63
- * Creates an OpenAI language model service.
90
+ * Creates an OpenAI `LanguageModel` service from a model identifier and
91
+ * optional request defaults.
92
+ *
93
+ * **When to use**
94
+ *
95
+ * Use to construct an OpenAI Responses API language model service backed by
96
+ * `OpenAiClient`.
97
+ *
98
+ * **Details**
99
+ *
100
+ * The returned effect requires `OpenAiClient`. Request defaults from the
101
+ * `config` option are merged with any `Config` service in the context, with
102
+ * context values taking precedence. The service supports both `generateText`
103
+ * and `streamText`.
104
+ *
105
+ * @see {@link layer} for providing the service as a `Layer`
106
+ * @see {@link model} for creating a model descriptor for `Effect.provide`
64
107
  *
65
- * @since 1.0.0
66
108
  * @category constructors
109
+ * @since 4.0.0
67
110
  */
68
111
  export const make = /*#__PURE__*/Effect.fnUntraced(function* ({
69
112
  model,
@@ -71,7 +114,7 @@ export const make = /*#__PURE__*/Effect.fnUntraced(function* ({
71
114
  }) {
72
115
  const client = yield* OpenAiClient;
73
116
  const makeConfig = Effect.gen(function* () {
74
- const services = yield* Effect.services();
117
+ const services = yield* Effect.context();
75
118
  return {
76
119
  model,
77
120
  ...providerConfig,
@@ -100,28 +143,31 @@ export const make = /*#__PURE__*/Effect.fnUntraced(function* ({
100
143
  options,
101
144
  toolNameMapper
102
145
  });
103
- const responseFormat = prepareResponseFormat({
146
+ const responseFormat = yield* prepareResponseFormat({
104
147
  config,
105
148
  options
106
149
  });
150
+ const {
151
+ fileIdPrefixes: _fip,
152
+ strictJsonSchema: _sjs,
153
+ ...apiConfig
154
+ } = config;
107
155
  const request = {
108
- ...config,
156
+ ...apiConfig,
109
157
  input: messages,
110
- include: include.size > 0 ? Array.from(include) : null,
158
+ include: include.size > 0 ? Array.from(include) : undefined,
111
159
  text: {
112
- verbosity: config.text?.verbosity ?? null,
160
+ verbosity: config.text?.verbosity ?? undefined,
113
161
  format: responseFormat
114
- },
115
- ...(Predicate.isNotUndefined(tools) ? {
116
- tools
117
- } : undefined),
118
- ...(Predicate.isNotUndefined(toolChoice) ? {
119
- tool_choice: toolChoice
120
- } : undefined)
162
+ }
121
163
  };
164
+ if (tools) request.tools = tools;
165
+ if (toolChoice) request.tool_choice = toolChoice;
166
+ if (options.previousResponseId) request.previous_response_id = options.previousResponseId;
122
167
  return request;
123
168
  });
124
169
  return yield* LanguageModel.make({
170
+ codecTransformer: toCodecOpenAI,
125
171
  generateText: Effect.fnUntraced(function* (options) {
126
172
  const config = yield* makeConfig;
127
173
  const toolNameMapper = new Tool.NameMapper(options.tools);
@@ -164,17 +210,49 @@ export const make = /*#__PURE__*/Effect.fnUntraced(function* ({
164
210
  });
165
211
  });
166
212
  /**
167
- * Creates a layer for the OpenAI language model.
213
+ * Creates a layer that provides the OpenAI `LanguageModel.LanguageModel`
214
+ * service.
215
+ *
216
+ * **When to use**
217
+ *
218
+ * Use when composing application layers and you want OpenAI to satisfy
219
+ * `LanguageModel.LanguageModel` while supplying `OpenAiClient` from another
220
+ * layer.
221
+ *
222
+ * **Details**
223
+ *
224
+ * The `config` option supplies request defaults for the selected model. Scoped
225
+ * values from `withConfigOverride` are merged when each request is built and
226
+ * take precedence over these defaults.
227
+ *
228
+ * @see {@link make} for constructing the language model service effectfully
229
+ * @see {@link model} for creating a model descriptor for `Effect.provide`
230
+ * @see {@link withConfigOverride} for scoped request configuration overrides
168
231
  *
169
- * @since 1.0.0
170
232
  * @category layers
233
+ * @since 4.0.0
171
234
  */
172
235
  export const layer = options => Layer.effect(LanguageModel.LanguageModel, make(options));
173
236
  /**
174
- * Provides config overrides for OpenAI language model operations.
237
+ * Provides scoped config overrides for OpenAI language model operations.
238
+ *
239
+ * **When to use**
240
+ *
241
+ * Use to apply OpenAI Responses API config overrides around one or more
242
+ * language model operations without changing the defaults passed to `model`,
243
+ * `make`, or `layer`.
244
+ *
245
+ * **Details**
246
+ *
247
+ * The override is dual, so it can be used in pipe form or as
248
+ * `withConfigOverride(effect, overrides)`. Overrides are merged with any
249
+ * existing `Config` service in the current context, and the override values take
250
+ * precedence.
251
+ *
252
+ * @see {@link Config} for the scoped configuration service consumed by this function
175
253
  *
176
- * @since 1.0.0
177
254
  * @category configuration
255
+ * @since 4.0.0
178
256
  */
179
257
  export const withConfigOverride = /*#__PURE__*/dual(2, (self, overrides) => Effect.flatMap(Effect.serviceOption(Config), config => Effect.provideService(self, Config, {
180
258
  ...(config._tag === "Some" ? config.value : {}),
@@ -207,14 +285,15 @@ const prepareMessages = /*#__PURE__*/Effect.fnUntraced(function* ({
207
285
  if (config.store === false && capabilities.isReasoningModel) {
208
286
  include.add("reasoning.encrypted_content");
209
287
  }
210
- if (Predicate.isNotUndefined(codeInterpreterTool)) {
288
+ if (codeInterpreterTool) {
211
289
  include.add("code_interpreter_call.outputs");
212
290
  }
213
- if (Predicate.isNotUndefined(webSearchTool) || Predicate.isNotUndefined(webSearchPreviewTool)) {
291
+ if (webSearchTool || webSearchPreviewTool) {
214
292
  include.add("web_search_call.action.sources");
215
293
  }
216
294
  const messages = [];
217
- for (const message of options.prompt.content) {
295
+ const prompt = options.incrementalPrompt ?? options.prompt;
296
+ for (const message of prompt.content) {
218
297
  switch (message.role) {
219
298
  case "system":
220
299
  {
@@ -378,7 +457,9 @@ const prepareMessages = /*#__PURE__*/Effect.fnUntraced(function* ({
378
457
  type: "reasoning",
379
458
  id,
380
459
  summary: summaryParts,
381
- encrypted_content: encryptedContent ?? null
460
+ ...(Predicate.isNotNull(encryptedContent) ? {
461
+ encrypted_content: encryptedContent
462
+ } : undefined)
382
463
  };
383
464
  messages.push(reasoningMessages[id]);
384
465
  } else {
@@ -569,13 +650,15 @@ const buildHttpRequestDetails = request => ({
569
650
  method: request.method,
570
651
  url: request.url,
571
652
  urlParams: Array.from(request.urlParams),
572
- hash: request.hash,
653
+ hash: Option.getOrUndefined(request.hash),
573
654
  headers: Redactable.redact(request.headers)
574
655
  });
575
656
  const buildHttpResponseDetails = response => ({
576
657
  status: response.status,
577
658
  headers: Redactable.redact(response.headers)
578
659
  });
660
+ const knownResponseStreamEventTypes = /*#__PURE__*/new Set(["response.created", "response.completed", "response.incomplete", "response.failed", "response.output_item.added", "response.output_item.done", "response.output_text.delta", "response.output_text.annotation.added", "response.reasoning_summary_part.added", "response.reasoning_summary_part.done", "response.reasoning_summary_text.delta", "response.function_call_arguments.delta", "response.function_call_arguments.done", "response.code_interpreter_call_code.delta", "response.code_interpreter_call_code.done", "response.apply_patch_call_operation_diff.delta", "response.apply_patch_call_operation_diff.done", "response.image_generation_call.partial_image", "error"]);
661
+ const isKnownResponseStreamEvent = event => knownResponseStreamEventTypes.has(event.type);
579
662
  const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
580
663
  options,
581
664
  rawResponse,
@@ -609,9 +692,7 @@ const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
609
692
  operation: part.operation
610
693
  },
611
694
  metadata: {
612
- openai: {
613
- ...makeItemIdMetadata(part.id)
614
- }
695
+ openai: makeItemIdMetadata(part.id)
615
696
  }
616
697
  });
617
698
  break;
@@ -669,9 +750,8 @@ const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
669
750
  {
670
751
  hasToolCalls = true;
671
752
  const toolName = part.name;
672
- const toolParams = part.arguments;
673
- const params = yield* Effect.try({
674
- try: () => Tool.unsafeSecureJsonParse(toolParams),
753
+ const toolParams = yield* Effect.try({
754
+ try: () => Tool.unsafeSecureJsonParse(part.arguments),
675
755
  catch: cause => AiError.make({
676
756
  module: "OpenAiLanguageModel",
677
757
  method: "makeResponse",
@@ -682,15 +762,14 @@ const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
682
762
  })
683
763
  })
684
764
  });
765
+ const params = yield* transformToolCallParams(options.tools, part.name, toolParams);
685
766
  parts.push({
686
767
  type: "tool-call",
687
768
  id: part.call_id,
688
769
  name: toolName,
689
770
  params,
690
771
  metadata: {
691
- openai: {
692
- ...makeItemIdMetadata(part.id)
693
- }
772
+ openai: makeItemIdMetadata(part.id)
694
773
  }
695
774
  });
696
775
  break;
@@ -727,9 +806,7 @@ const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
727
806
  action: part.action
728
807
  },
729
808
  metadata: {
730
- openai: {
731
- ...makeItemIdMetadata(part.id)
732
- }
809
+ openai: makeItemIdMetadata(part.id)
733
810
  }
734
811
  });
735
812
  break;
@@ -737,12 +814,19 @@ const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
737
814
  case "mcp_call":
738
815
  {
739
816
  const toolId = Predicate.isNotNullish(part.approval_request_id) ? approvalRequests.get(part.approval_request_id) ?? part.id : part.id;
740
- const toolName = `mcp.${part.name}`;
817
+ const {
818
+ toolName,
819
+ params
820
+ } = yield* normalizeMcpToolCall({
821
+ toolNameMapper,
822
+ toolParams: part.arguments,
823
+ method: "makeResponse"
824
+ });
741
825
  parts.push({
742
826
  type: "tool-call",
743
827
  id: toolId,
744
828
  name: toolName,
745
- params: part.arguments,
829
+ params,
746
830
  providerExecuted: true
747
831
  });
748
832
  parts.push({
@@ -752,7 +836,7 @@ const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
752
836
  isFailure: false,
753
837
  providerExecuted: true,
754
838
  result: {
755
- type: "call",
839
+ type: "mcp_call",
756
840
  name: part.name,
757
841
  arguments: part.arguments,
758
842
  server_label: part.server_label,
@@ -764,9 +848,7 @@ const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
764
848
  } : undefined)
765
849
  },
766
850
  metadata: {
767
- openai: {
768
- ...makeItemIdMetadata(part.id)
769
- }
851
+ openai: makeItemIdMetadata(part.id)
770
852
  }
771
853
  });
772
854
  break;
@@ -780,18 +862,13 @@ const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
780
862
  {
781
863
  const approvalRequestId = part.approval_request_id ?? part.id;
782
864
  const toolId = yield* idGenerator.generateId();
783
- const toolName = `mcp.${part.name}`;
784
- const params = yield* Effect.try({
785
- try: () => Tool.unsafeSecureJsonParse(part.arguments),
786
- catch: cause => AiError.make({
787
- module: "OpenAiLanguageModel",
788
- method: "makeResponse",
789
- reason: new AiError.ToolParameterValidationError({
790
- toolName,
791
- toolParams: {},
792
- description: `Failed securely JSON parse tool parameters: ${cause}`
793
- })
794
- })
865
+ const {
866
+ toolName,
867
+ params
868
+ } = yield* normalizeMcpToolCall({
869
+ toolNameMapper,
870
+ toolParams: part.arguments,
871
+ method: "makeResponse"
795
872
  });
796
873
  parts.push({
797
874
  type: "tool-call",
@@ -952,9 +1029,7 @@ const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
952
1029
  action: part.action
953
1030
  },
954
1031
  metadata: {
955
- openai: {
956
- ...makeItemIdMetadata(part.id)
957
- }
1032
+ openai: makeItemIdMetadata(part.id)
958
1033
  }
959
1034
  });
960
1035
  break;
@@ -990,13 +1065,7 @@ const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
990
1065
  reason: finishReason,
991
1066
  usage: getUsage(rawResponse.usage),
992
1067
  response: buildHttpResponseDetails(response),
993
- ...(rawResponse.service_tier && {
994
- metadata: {
995
- openai: {
996
- serviceTier: rawResponse.service_tier
997
- }
998
- }
999
- })
1068
+ ...toServiceTier(rawResponse.service_tier)
1000
1069
  });
1001
1070
  return parts;
1002
1071
  });
@@ -1015,11 +1084,29 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
1015
1084
  const activeAnnotations = [];
1016
1085
  // Track active reasoning items with state machine for proper concluding logic
1017
1086
  const activeReasoning = {};
1087
+ const getOrCreateReasoningPart = (itemId, encryptedContent) => {
1088
+ const activePart = activeReasoning[itemId];
1089
+ if (Predicate.isNotUndefined(activePart)) {
1090
+ if (Predicate.isNotNullish(encryptedContent)) {
1091
+ activePart.encryptedContent = encryptedContent;
1092
+ }
1093
+ return activePart;
1094
+ }
1095
+ const reasoningPart = {
1096
+ encryptedContent: Predicate.isNotNullish(encryptedContent) ? encryptedContent : undefined,
1097
+ summaryParts: {}
1098
+ };
1099
+ activeReasoning[itemId] = reasoningPart;
1100
+ return reasoningPart;
1101
+ };
1018
1102
  // Track active tool calls with optional provider-specific state
1019
1103
  const activeToolCalls = {};
1020
1104
  const webSearchTool = options.tools.find(tool => Tool.isProviderDefined(tool) && (tool.name === "OpenAiWebSearch" || tool.name === "OpenAiWebSearchPreview"));
1021
1105
  return stream.pipe(Stream.mapEffect(Effect.fnUntraced(function* (event) {
1022
1106
  const parts = [];
1107
+ if (!isKnownResponseStreamEvent(event)) {
1108
+ return parts;
1109
+ }
1023
1110
  switch (event.type) {
1024
1111
  case "response.created":
1025
1112
  {
@@ -1050,13 +1137,7 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
1050
1137
  reason: InternalUtilities.resolveFinishReason(event.response.incomplete_details?.reason, hasToolCalls),
1051
1138
  usage: getUsage(event.response.usage),
1052
1139
  response: buildHttpResponseDetails(response),
1053
- ...(event.response.service_tier && {
1054
- metadata: {
1055
- openai: {
1056
- serviceTier: event.response.service_tier
1057
- }
1058
- }
1059
- })
1140
+ ...toServiceTier(event.response.service_tier)
1060
1141
  });
1061
1142
  break;
1062
1143
  }
@@ -1157,7 +1238,10 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
1157
1238
  {
1158
1239
  activeToolCalls[event.output_index] = {
1159
1240
  id: event.item.call_id,
1160
- name: event.item.name
1241
+ name: event.item.name,
1242
+ functionCall: {
1243
+ emitted: false
1244
+ }
1161
1245
  };
1162
1246
  parts.push({
1163
1247
  type: "tool-params-start",
@@ -1195,39 +1279,34 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
1195
1279
  type: "text-start",
1196
1280
  id: event.item.id,
1197
1281
  metadata: {
1198
- openai: {
1199
- ...makeItemIdMetadata(event.item.id)
1200
- }
1282
+ openai: makeItemIdMetadata(event.item.id)
1201
1283
  }
1202
1284
  });
1203
1285
  break;
1204
1286
  }
1205
1287
  case "reasoning":
1206
1288
  {
1207
- const encryptedContent = event.item.encrypted_content ?? undefined;
1208
- activeReasoning[event.item.id] = {
1209
- encryptedContent,
1210
- summaryParts: {
1211
- 0: "active"
1212
- }
1213
- };
1214
- parts.push({
1215
- type: "reasoning-start",
1216
- id: `${event.item.id}:0`,
1217
- metadata: {
1218
- openai: {
1219
- ...makeItemIdMetadata(event.item.id),
1220
- ...makeEncryptedContentMetadata(event.item.encrypted_content)
1289
+ const reasoningPart = getOrCreateReasoningPart(event.item.id, event.item.encrypted_content);
1290
+ if (Predicate.isUndefined(reasoningPart.summaryParts[0])) {
1291
+ reasoningPart.summaryParts[0] = "active";
1292
+ parts.push({
1293
+ type: "reasoning-start",
1294
+ id: `${event.item.id}:0`,
1295
+ metadata: {
1296
+ openai: {
1297
+ ...makeItemIdMetadata(event.item.id),
1298
+ ...makeEncryptedContentMetadata(reasoningPart.encryptedContent)
1299
+ }
1221
1300
  }
1222
- }
1223
- });
1301
+ });
1302
+ }
1224
1303
  break;
1225
1304
  }
1226
1305
  case "shell_call":
1227
1306
  {
1228
1307
  const toolName = toolNameMapper.getCustomName("shell");
1229
1308
  activeToolCalls[event.output_index] = {
1230
- id: event.item.id,
1309
+ id: event.item.id ?? event.item.call_id,
1231
1310
  name: toolName
1232
1311
  };
1233
1312
  break;
@@ -1272,7 +1351,7 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
1272
1351
  parts.push({
1273
1352
  type: "tool-params-delta",
1274
1353
  id: toolCall.id,
1275
- delta: InternalUtilities.escapeJSONDelta(event.item.operation.diff)
1354
+ delta: InternalUtilities.escapeJSONDelta(event.item.operation.diff ?? "")
1276
1355
  });
1277
1356
  }
1278
1357
  parts.push({
@@ -1298,9 +1377,7 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
1298
1377
  operation: event.item.operation
1299
1378
  },
1300
1379
  metadata: {
1301
- openai: {
1302
- ...makeItemIdMetadata(event.item.id)
1303
- }
1380
+ openai: makeItemIdMetadata(event.item.id)
1304
1381
  }
1305
1382
  });
1306
1383
  }
@@ -1372,12 +1449,17 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
1372
1449
  }
1373
1450
  case "function_call":
1374
1451
  {
1452
+ const toolCall = activeToolCalls[event.output_index];
1453
+ if (Predicate.isNotUndefined(toolCall?.functionCall?.emitted) && toolCall.functionCall.emitted) {
1454
+ delete activeToolCalls[event.output_index];
1455
+ break;
1456
+ }
1375
1457
  delete activeToolCalls[event.output_index];
1376
1458
  hasToolCalls = true;
1377
1459
  const toolName = event.item.name;
1378
- const toolParams = event.item.arguments;
1379
- const params = yield* Effect.try({
1380
- try: () => Tool.unsafeSecureJsonParse(toolParams),
1460
+ const toolArgs = event.item.arguments;
1461
+ const toolParams = yield* Effect.try({
1462
+ try: () => Tool.unsafeSecureJsonParse(toolArgs),
1381
1463
  catch: cause => AiError.make({
1382
1464
  module: "OpenAiLanguageModel",
1383
1465
  method: "makeStreamResponse",
@@ -1388,6 +1470,7 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
1388
1470
  })
1389
1471
  })
1390
1472
  });
1473
+ const params = yield* transformToolCallParams(options.tools, toolName, toolParams);
1391
1474
  parts.push({
1392
1475
  type: "tool-params-end",
1393
1476
  id: event.item.call_id
@@ -1398,9 +1481,7 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
1398
1481
  name: toolName,
1399
1482
  params,
1400
1483
  metadata: {
1401
- openai: {
1402
- ...makeItemIdMetadata(event.item.id)
1403
- }
1484
+ openai: makeItemIdMetadata(event.item.id)
1404
1485
  }
1405
1486
  });
1406
1487
  break;
@@ -1431,9 +1512,7 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
1431
1512
  action: event.item.action
1432
1513
  },
1433
1514
  metadata: {
1434
- openai: {
1435
- ...makeItemIdMetadata(event.item.id)
1436
- }
1515
+ openai: makeItemIdMetadata(event.item.id)
1437
1516
  }
1438
1517
  });
1439
1518
  break;
@@ -1443,12 +1522,19 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
1443
1522
  const approvalRequestId = event.item.approval_request_id;
1444
1523
  // Track approval with our own tool call identifiers
1445
1524
  const toolId = Predicate.isNotNullish(approvalRequestId) ? streamApprovalRequests.get(approvalRequestId) ?? approvalRequests.get(approvalRequestId) ?? event.item.id : event.item.id;
1446
- const toolName = `mcp.${event.item.name}`;
1525
+ const {
1526
+ toolName,
1527
+ params
1528
+ } = yield* normalizeMcpToolCall({
1529
+ toolNameMapper,
1530
+ toolParams: event.item.arguments,
1531
+ method: "makeStreamResponse"
1532
+ });
1447
1533
  parts.push({
1448
1534
  type: "tool-call",
1449
1535
  id: toolId,
1450
1536
  name: toolName,
1451
- params: event.item.arguments,
1537
+ params,
1452
1538
  providerExecuted: true
1453
1539
  });
1454
1540
  parts.push({
@@ -1458,7 +1544,7 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
1458
1544
  isFailure: false,
1459
1545
  providerExecuted: true,
1460
1546
  result: {
1461
- type: "call",
1547
+ type: "mcp_call",
1462
1548
  name: event.item.name,
1463
1549
  arguments: event.item.arguments,
1464
1550
  server_label: event.item.server_label,
@@ -1470,9 +1556,7 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
1470
1556
  } : undefined)
1471
1557
  },
1472
1558
  metadata: {
1473
- openai: {
1474
- ...makeItemIdMetadata(event.item.id)
1475
- }
1559
+ openai: makeItemIdMetadata(event.item.id)
1476
1560
  }
1477
1561
  });
1478
1562
  break;
@@ -1487,12 +1571,19 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
1487
1571
  const toolId = yield* idGenerator.generateId();
1488
1572
  const approvalRequestId = event.item.approval_request_id ?? event.item.id;
1489
1573
  streamApprovalRequests.set(approvalRequestId, toolId);
1490
- const toolName = `mcp.${event.item.name}`;
1574
+ const {
1575
+ toolName,
1576
+ params
1577
+ } = yield* normalizeMcpToolCall({
1578
+ toolNameMapper,
1579
+ toolParams: event.item.arguments,
1580
+ method: "makeStreamResponse"
1581
+ });
1491
1582
  parts.push({
1492
1583
  type: "tool-call",
1493
1584
  id: toolId,
1494
1585
  name: toolName,
1495
- params: event.item.arguments,
1586
+ params,
1496
1587
  providerExecuted: true
1497
1588
  });
1498
1589
  parts.push({
@@ -1521,7 +1612,7 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
1521
1612
  }
1522
1613
  case "reasoning":
1523
1614
  {
1524
- const reasoningPart = activeReasoning[event.item.id];
1615
+ const reasoningPart = getOrCreateReasoningPart(event.item.id, event.item.encrypted_content);
1525
1616
  for (const [summaryIndex, status] of Object.entries(reasoningPart.summaryParts)) {
1526
1617
  if (status === "active" || status === "can-conclude") {
1527
1618
  parts.push({
@@ -1530,7 +1621,7 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
1530
1621
  metadata: {
1531
1622
  openai: {
1532
1623
  ...makeItemIdMetadata(event.item.id),
1533
- ...makeEncryptedContentMetadata(event.item.encrypted_content)
1624
+ ...makeEncryptedContentMetadata(reasoningPart.encryptedContent)
1534
1625
  }
1535
1626
  }
1536
1627
  });
@@ -1545,15 +1636,13 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
1545
1636
  const toolName = toolNameMapper.getCustomName("shell");
1546
1637
  parts.push({
1547
1638
  type: "tool-call",
1548
- id: event.item.id,
1639
+ id: event.item.id ?? event.item.call_id,
1549
1640
  name: toolName,
1550
1641
  params: {
1551
1642
  action: event.item.action
1552
1643
  },
1553
1644
  metadata: {
1554
- openai: {
1555
- ...makeItemIdMetadata(event.item.id)
1556
- }
1645
+ openai: makeItemIdMetadata(event.item.id)
1557
1646
  }
1558
1647
  });
1559
1648
  break;
@@ -1670,6 +1759,41 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
1670
1759
  }
1671
1760
  break;
1672
1761
  }
1762
+ case "response.function_call_arguments.done":
1763
+ {
1764
+ const toolCall = activeToolCalls[event.output_index];
1765
+ if (Predicate.isNotUndefined(toolCall?.functionCall) && !toolCall.functionCall.emitted) {
1766
+ hasToolCalls = true;
1767
+ const toolParams = yield* Effect.try({
1768
+ try: () => Tool.unsafeSecureJsonParse(event.arguments),
1769
+ catch: cause => AiError.make({
1770
+ module: "OpenAiLanguageModel",
1771
+ method: "makeStreamResponse",
1772
+ reason: new AiError.ToolParameterValidationError({
1773
+ toolName: toolCall.name,
1774
+ toolParams: {},
1775
+ description: `Failed securely JSON parse tool parameters: ${cause}`
1776
+ })
1777
+ })
1778
+ });
1779
+ const params = yield* transformToolCallParams(options.tools, toolCall.name, toolParams);
1780
+ parts.push({
1781
+ type: "tool-params-end",
1782
+ id: toolCall.id
1783
+ });
1784
+ parts.push({
1785
+ type: "tool-call",
1786
+ id: toolCall.id,
1787
+ name: toolCall.name,
1788
+ params,
1789
+ metadata: {
1790
+ openai: makeItemIdMetadata(event.item_id)
1791
+ }
1792
+ });
1793
+ toolCall.functionCall.emitted = true;
1794
+ }
1795
+ break;
1796
+ }
1673
1797
  case "response.apply_patch_call_operation_diff.delta":
1674
1798
  {
1675
1799
  const toolCall = activeToolCalls[event.output_index];
@@ -1765,28 +1889,27 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
1765
1889
  }
1766
1890
  case "response.reasoning_summary_part.added":
1767
1891
  {
1768
- // The first reasoning start is pushed in the `response.output_item.added` block
1892
+ const reasoningPart = getOrCreateReasoningPart(event.item_id);
1769
1893
  if (event.summary_index > 0) {
1770
- const reasoningPart = activeReasoning[event.item_id];
1771
- if (Predicate.isNotUndefined(reasoningPart)) {
1772
- // Conclude all can-conclude parts before starting new one
1773
- for (const [summaryIndex, status] of Object.entries(reasoningPart.summaryParts)) {
1774
- if (status === "can-conclude") {
1775
- parts.push({
1776
- type: "reasoning-end",
1777
- id: `${event.item_id}:${summaryIndex}`,
1778
- metadata: {
1779
- openai: {
1780
- ...makeItemIdMetadata(event.item_id),
1781
- ...makeEncryptedContentMetadata(reasoningPart.encryptedContent)
1782
- }
1894
+ // Conclude all can-conclude parts before starting new one
1895
+ for (const [summaryIndex, status] of Object.entries(reasoningPart.summaryParts)) {
1896
+ if (status === "can-conclude") {
1897
+ parts.push({
1898
+ type: "reasoning-end",
1899
+ id: `${event.item_id}:${summaryIndex}`,
1900
+ metadata: {
1901
+ openai: {
1902
+ ...makeItemIdMetadata(event.item_id),
1903
+ ...makeEncryptedContentMetadata(reasoningPart.encryptedContent)
1783
1904
  }
1784
- });
1785
- reasoningPart.summaryParts[Number(summaryIndex)] = "concluded";
1786
- }
1905
+ }
1906
+ });
1907
+ reasoningPart.summaryParts[Number(summaryIndex)] = "concluded";
1787
1908
  }
1788
- reasoningPart.summaryParts[event.summary_index] = "active";
1789
1909
  }
1910
+ }
1911
+ if (Predicate.isUndefined(reasoningPart.summaryParts[event.summary_index])) {
1912
+ reasoningPart.summaryParts[event.summary_index] = "active";
1790
1913
  parts.push({
1791
1914
  type: "reasoning-start",
1792
1915
  id: `${event.item_id}:${event.summary_index}`,
@@ -1807,15 +1930,14 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
1807
1930
  id: `${event.item_id}:${event.summary_index}`,
1808
1931
  delta: event.delta,
1809
1932
  metadata: {
1810
- openai: {
1811
- ...makeItemIdMetadata(event.item_id)
1812
- }
1933
+ openai: makeItemIdMetadata(event.item_id)
1813
1934
  }
1814
1935
  });
1815
1936
  break;
1816
1937
  }
1817
1938
  case "response.reasoning_summary_part.done":
1818
1939
  {
1940
+ const reasoningPart = getOrCreateReasoningPart(event.item_id);
1819
1941
  // When OpenAI stores message data, we can immediately conclude the
1820
1942
  // reasoning part given that we do not need the encrypted content
1821
1943
  if (config.store === true) {
@@ -1823,17 +1945,15 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
1823
1945
  type: "reasoning-end",
1824
1946
  id: `${event.item_id}:${event.summary_index}`,
1825
1947
  metadata: {
1826
- openai: {
1827
- ...makeItemIdMetadata(event.item_id)
1828
- }
1948
+ openai: makeItemIdMetadata(event.item_id)
1829
1949
  }
1830
1950
  });
1831
1951
  // Mark the summary part concluded
1832
- activeReasoning[event.item_id].summaryParts[event.summary_index] = "concluded";
1952
+ reasoningPart.summaryParts[event.summary_index] = "concluded";
1833
1953
  } else {
1834
1954
  // Mark the summary part as can-conclude given we still need a
1835
1955
  // final summary part with the encrypted content
1836
- activeReasoning[event.item_id].summaryParts[event.summary_index] = "can-conclude";
1956
+ reasoningPart.summaryParts[event.summary_index] = "can-conclude";
1837
1957
  }
1838
1958
  break;
1839
1959
  }
@@ -1936,14 +2056,18 @@ const prepareTools = /*#__PURE__*/Effect.fnUntraced(function* ({
1936
2056
  }
1937
2057
  // Convert the tools in the toolkit to the provider-defined format
1938
2058
  for (const tool of allowedTools) {
1939
- if (Tool.isUserDefined(tool)) {
2059
+ if (Tool.isUserDefined(tool) || Tool.isDynamic(tool)) {
1940
2060
  const strict = Tool.getStrictMode(tool) ?? config.strictJsonSchema ?? true;
2061
+ const description = Tool.getDescription(tool);
2062
+ const parameters = yield* tryToolJsonSchema(tool, "prepareTools");
1941
2063
  tools.push({
1942
2064
  type: "function",
1943
2065
  name: tool.name,
1944
- description: Tool.getDescription(tool) ?? null,
1945
- parameters: Tool.getJsonSchema(tool),
1946
- strict
2066
+ parameters,
2067
+ strict,
2068
+ ...(Predicate.isNotUndefined(description) ? {
2069
+ description
2070
+ } : undefined)
1947
2071
  });
1948
2072
  }
1949
2073
  if (Tool.isProviderDefined(tool)) {
@@ -2111,29 +2235,53 @@ const getEncryptedContent = part => part.options.openai?.encryptedContent ?? nul
2111
2235
  const getImageDetail = part => part.options.openai?.imageDetail ?? "auto";
2112
2236
  const makeItemIdMetadata = itemId => Predicate.isNotUndefined(itemId) ? {
2113
2237
  itemId
2114
- } : undefined;
2238
+ } : {};
2115
2239
  const makeEncryptedContentMetadata = encryptedContent => Predicate.isNotNullish(encryptedContent) ? {
2116
2240
  encryptedContent
2117
2241
  } : undefined;
2118
- const prepareResponseFormat = ({
2242
+ const unsupportedSchemaError = (error, method) => AiError.make({
2243
+ module: "OpenAiLanguageModel",
2244
+ method,
2245
+ reason: new AiError.UnsupportedSchemaError({
2246
+ description: error instanceof Error ? error.message : String(error)
2247
+ })
2248
+ });
2249
+ const tryCodecTransform = (schema, method) => Effect.try({
2250
+ try: () => toCodecOpenAI(schema),
2251
+ catch: error => unsupportedSchemaError(error, method)
2252
+ });
2253
+ const tryJsonSchema = (schema, method) => Effect.try({
2254
+ try: () => Tool.getJsonSchemaFromSchema(schema, {
2255
+ transformer: toCodecOpenAI
2256
+ }),
2257
+ catch: error => unsupportedSchemaError(error, method)
2258
+ });
2259
+ const tryToolJsonSchema = (tool, method) => Effect.try({
2260
+ try: () => Tool.getJsonSchema(tool, {
2261
+ transformer: toCodecOpenAI
2262
+ }),
2263
+ catch: error => unsupportedSchemaError(error, method)
2264
+ });
2265
+ const prepareResponseFormat = /*#__PURE__*/Effect.fnUntraced(function* ({
2119
2266
  config,
2120
2267
  options
2121
- }) => {
2268
+ }) {
2122
2269
  if (options.responseFormat.type === "json") {
2123
2270
  const name = options.responseFormat.objectName;
2124
2271
  const schema = options.responseFormat.schema;
2272
+ const jsonSchema = yield* tryJsonSchema(schema, "prepareResponseFormat");
2125
2273
  return {
2126
2274
  type: "json_schema",
2127
2275
  name,
2128
2276
  description: AST.resolveDescription(schema.ast) ?? "Response with a JSON object",
2129
- schema: Tool.getJsonSchemaFromSchema(schema),
2277
+ schema: jsonSchema,
2130
2278
  strict: config.strictJsonSchema ?? true
2131
2279
  };
2132
2280
  }
2133
2281
  return {
2134
2282
  type: "text"
2135
2283
  };
2136
- };
2284
+ });
2137
2285
  const getModelCapabilities = modelId => {
2138
2286
  const supportsFlexProcessing = modelId.startsWith("o3") || modelId.startsWith("o4-mini") || modelId.startsWith("gpt-5") && !modelId.startsWith("gpt-5-chat");
2139
2287
  const supportsPriorityProcessing = modelId.startsWith("gpt-4") || modelId.startsWith("gpt-5-mini") || modelId.startsWith("gpt-5") && !modelId.startsWith("gpt-5-nano") && !modelId.startsWith("gpt-5-chat") || modelId.startsWith("o3") || modelId.startsWith("o4-mini");
@@ -2170,6 +2318,35 @@ const getApprovalRequestIdMapping = prompt => {
2170
2318
  }
2171
2319
  return mapping;
2172
2320
  };
2321
+ const normalizeMcpToolCall = /*#__PURE__*/Effect.fnUntraced(function* ({
2322
+ toolNameMapper,
2323
+ toolParams,
2324
+ method
2325
+ }) {
2326
+ const toolName = toolNameMapper.getCustomName("mcp");
2327
+ if (typeof toolParams !== "string") {
2328
+ return {
2329
+ toolName,
2330
+ params: toolParams
2331
+ };
2332
+ }
2333
+ const params = yield* Effect.try({
2334
+ try: () => Tool.unsafeSecureJsonParse(toolParams),
2335
+ catch: cause => AiError.make({
2336
+ module: "OpenAiLanguageModel",
2337
+ method,
2338
+ reason: new AiError.ToolParameterValidationError({
2339
+ toolName,
2340
+ toolParams,
2341
+ description: `Failed to securely JSON parse tool parameters: ${cause}`
2342
+ })
2343
+ })
2344
+ });
2345
+ return {
2346
+ toolName,
2347
+ params
2348
+ };
2349
+ });
2173
2350
  const getUsage = usage => {
2174
2351
  if (Predicate.isNullish(usage)) {
2175
2352
  return {
@@ -2188,8 +2365,8 @@ const getUsage = usage => {
2188
2365
  }
2189
2366
  const inputTokens = usage.input_tokens;
2190
2367
  const outputTokens = usage.output_tokens;
2191
- const cachedTokens = usage.input_tokens_details.cached_tokens;
2192
- const reasoningTokens = usage.output_tokens_details.reasoning_tokens;
2368
+ const cachedTokens = getUsageTokenDetail(usage.input_tokens_details, "cached_tokens");
2369
+ const reasoningTokens = getUsageTokenDetail(usage.output_tokens_details, "reasoning_tokens");
2193
2370
  return {
2194
2371
  inputTokens: {
2195
2372
  uncached: inputTokens - cachedTokens,
@@ -2204,4 +2381,49 @@ const getUsage = usage => {
2204
2381
  }
2205
2382
  };
2206
2383
  };
2384
+ const toServiceTier = value => {
2385
+ switch (value) {
2386
+ case "default":
2387
+ case "auto":
2388
+ case "flex":
2389
+ case "scale":
2390
+ case "priority":
2391
+ return {
2392
+ metadata: {
2393
+ openai: {
2394
+ serviceTier: value
2395
+ }
2396
+ }
2397
+ };
2398
+ default:
2399
+ return undefined;
2400
+ }
2401
+ };
2402
+ const getUsageTokenDetail = (details, key) => Predicate.hasProperty(details, key) && typeof details[key] === "number" ? details[key] : 0;
2403
+ const transformToolCallParams = /*#__PURE__*/Effect.fnUntraced(function* (tools, toolName, toolParams) {
2404
+ const tool = tools.find(tool => tool.name === toolName);
2405
+ if (Predicate.isUndefined(tool)) {
2406
+ return yield* AiError.make({
2407
+ module: "OpenAiLanguageModel",
2408
+ method: "makeResponse",
2409
+ reason: new AiError.ToolNotFoundError({
2410
+ toolName,
2411
+ availableTools: tools.map(tool => tool.name)
2412
+ })
2413
+ });
2414
+ }
2415
+ const {
2416
+ codec
2417
+ } = yield* tryCodecTransform(tool.parametersSchema, "makeResponse");
2418
+ const transform = Schema.decodeEffect(codec);
2419
+ return yield* transform(toolParams).pipe(Effect.mapError(error => AiError.make({
2420
+ module: "OpenAiLanguageModel",
2421
+ method: "makeResponse",
2422
+ reason: new AiError.ToolParameterValidationError({
2423
+ toolName,
2424
+ toolParams,
2425
+ description: error.issue.toString()
2426
+ })
2427
+ })));
2428
+ });
2207
2429
  //# sourceMappingURL=OpenAiLanguageModel.js.map