@effect/ai-openai 4.0.0-beta.7 → 4.0.0-beta.70
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.
- package/dist/Generated.d.ts +66734 -37723
- package/dist/Generated.d.ts.map +1 -1
- package/dist/Generated.js +1 -1
- package/dist/Generated.js.map +1 -1
- package/dist/OpenAiClient.d.ts +81 -25
- package/dist/OpenAiClient.d.ts.map +1 -1
- package/dist/OpenAiClient.js +220 -39
- package/dist/OpenAiClient.js.map +1 -1
- package/dist/OpenAiClientGenerated.d.ts +91 -0
- package/dist/OpenAiClientGenerated.d.ts.map +1 -0
- package/dist/OpenAiClientGenerated.js +84 -0
- package/dist/OpenAiClientGenerated.js.map +1 -0
- package/dist/OpenAiConfig.d.ts +45 -10
- package/dist/OpenAiConfig.d.ts.map +1 -1
- package/dist/OpenAiConfig.js +31 -7
- package/dist/OpenAiConfig.js.map +1 -1
- package/dist/OpenAiEmbeddingModel.d.ts +89 -0
- package/dist/OpenAiEmbeddingModel.d.ts.map +1 -0
- package/dist/OpenAiEmbeddingModel.js +121 -0
- package/dist/OpenAiEmbeddingModel.js.map +1 -0
- package/dist/OpenAiError.d.ts +168 -35
- package/dist/OpenAiError.d.ts.map +1 -1
- package/dist/OpenAiError.js +1 -1
- package/dist/OpenAiLanguageModel.d.ts +250 -57
- package/dist/OpenAiLanguageModel.d.ts.map +1 -1
- package/dist/OpenAiLanguageModel.js +311 -160
- package/dist/OpenAiLanguageModel.js.map +1 -1
- package/dist/OpenAiSchema.d.ts +2029 -0
- package/dist/OpenAiSchema.d.ts.map +1 -0
- package/dist/OpenAiSchema.js +591 -0
- package/dist/OpenAiSchema.js.map +1 -0
- package/dist/OpenAiTelemetry.d.ts +31 -18
- package/dist/OpenAiTelemetry.d.ts.map +1 -1
- package/dist/OpenAiTelemetry.js +6 -4
- package/dist/OpenAiTelemetry.js.map +1 -1
- package/dist/OpenAiTool.d.ts +56 -67
- package/dist/OpenAiTool.d.ts.map +1 -1
- package/dist/OpenAiTool.js +33 -44
- package/dist/OpenAiTool.js.map +1 -1
- package/dist/index.d.ts +42 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +42 -8
- package/dist/index.js.map +1 -1
- package/dist/internal/errors.js +4 -4
- package/dist/internal/errors.js.map +1 -1
- package/package.json +3 -3
- package/src/Generated.ts +9858 -5044
- package/src/OpenAiClient.ts +396 -90
- package/src/OpenAiClientGenerated.ts +202 -0
- package/src/OpenAiConfig.ts +46 -11
- package/src/OpenAiEmbeddingModel.ts +207 -0
- package/src/OpenAiError.ts +170 -35
- package/src/OpenAiLanguageModel.ts +633 -157
- package/src/OpenAiSchema.ts +984 -0
- package/src/OpenAiTelemetry.ts +32 -19
- package/src/OpenAiTool.ts +34 -45
- package/src/index.ts +45 -8
- package/src/internal/errors.ts +6 -4
|
@@ -4,23 +4,25 @@
|
|
|
4
4
|
* Provides a LanguageModel implementation for OpenAI's responses API,
|
|
5
5
|
* supporting text generation, structured output, tool calling, and streaming.
|
|
6
6
|
*
|
|
7
|
-
* @since
|
|
7
|
+
* @since 4.0.0
|
|
8
8
|
*/
|
|
9
|
+
import * as Context from "effect/Context";
|
|
9
10
|
import * as DateTime from "effect/DateTime";
|
|
10
11
|
import * as Effect from "effect/Effect";
|
|
11
12
|
import * as Encoding from "effect/Encoding";
|
|
12
13
|
import { dual } from "effect/Function";
|
|
13
14
|
import * as Layer from "effect/Layer";
|
|
15
|
+
import * as Option from "effect/Option";
|
|
14
16
|
import * as Predicate from "effect/Predicate";
|
|
15
17
|
import * as Redactable from "effect/Redactable";
|
|
16
18
|
import * as Schema from "effect/Schema";
|
|
17
19
|
import * as AST from "effect/SchemaAST";
|
|
18
|
-
import * as ServiceMap from "effect/ServiceMap";
|
|
19
20
|
import * as Stream from "effect/Stream";
|
|
20
21
|
import * as AiError from "effect/unstable/ai/AiError";
|
|
21
22
|
import * as IdGenerator from "effect/unstable/ai/IdGenerator";
|
|
22
23
|
import * as LanguageModel from "effect/unstable/ai/LanguageModel";
|
|
23
24
|
import * as AiModel from "effect/unstable/ai/Model";
|
|
25
|
+
import { toCodecOpenAI } from "effect/unstable/ai/OpenAiStructuredOutput";
|
|
24
26
|
import * as Tool from "effect/unstable/ai/Tool";
|
|
25
27
|
import * as Generated from "./Generated.js";
|
|
26
28
|
import * as InternalUtilities from "./internal/utilities.js";
|
|
@@ -34,36 +36,38 @@ const SharedModelIds = Generated.ModelIdsShared.members[1];
|
|
|
34
36
|
/**
|
|
35
37
|
* Service definition for OpenAI language model configuration.
|
|
36
38
|
*
|
|
37
|
-
* @since 1.0.0
|
|
38
39
|
* @category services
|
|
40
|
+
* @since 4.0.0
|
|
39
41
|
*/
|
|
40
|
-
export class Config extends /*#__PURE__*/
|
|
42
|
+
export class Config extends /*#__PURE__*/Context.Service()("@effect/ai-openai/OpenAiLanguageModel/Config") {}
|
|
41
43
|
// =============================================================================
|
|
42
44
|
// Language Model
|
|
43
45
|
// =============================================================================
|
|
44
46
|
/**
|
|
45
|
-
*
|
|
47
|
+
* Creates an OpenAI language model that can be used with `AiModel.provide`.
|
|
48
|
+
*
|
|
46
49
|
* @category constructors
|
|
50
|
+
* @since 4.0.0
|
|
47
51
|
*/
|
|
48
|
-
export const model = (model, config) => AiModel.make("openai", layer({
|
|
52
|
+
export const model = (model, config) => AiModel.make("openai", model, layer({
|
|
49
53
|
model,
|
|
50
54
|
config
|
|
51
55
|
}));
|
|
52
56
|
// TODO
|
|
53
57
|
// /**
|
|
54
|
-
// * @since
|
|
58
|
+
// * @since 4.0.0
|
|
55
59
|
// * @category constructors
|
|
56
60
|
// */
|
|
57
61
|
// export const modelWithTokenizer = (
|
|
58
62
|
// model: (string & {}) | Model,
|
|
59
63
|
// config?: Omit<typeof Config.Service, "model">
|
|
60
64
|
// ): AiModel.Model<"openai", LanguageModel.LanguageModel | Tokenizer.Tokenizer, OpenAiClient> =>
|
|
61
|
-
// AiModel.make("openai", layerWithTokenizer({ model, config }))
|
|
65
|
+
// AiModel.make("openai", model, layerWithTokenizer({ model, config }))
|
|
62
66
|
/**
|
|
63
67
|
* Creates an OpenAI language model service.
|
|
64
68
|
*
|
|
65
|
-
* @since 1.0.0
|
|
66
69
|
* @category constructors
|
|
70
|
+
* @since 4.0.0
|
|
67
71
|
*/
|
|
68
72
|
export const make = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
69
73
|
model,
|
|
@@ -71,7 +75,7 @@ export const make = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
71
75
|
}) {
|
|
72
76
|
const client = yield* OpenAiClient;
|
|
73
77
|
const makeConfig = Effect.gen(function* () {
|
|
74
|
-
const services = yield* Effect.
|
|
78
|
+
const services = yield* Effect.context();
|
|
75
79
|
return {
|
|
76
80
|
model,
|
|
77
81
|
...providerConfig,
|
|
@@ -100,28 +104,31 @@ export const make = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
100
104
|
options,
|
|
101
105
|
toolNameMapper
|
|
102
106
|
});
|
|
103
|
-
const responseFormat = prepareResponseFormat({
|
|
107
|
+
const responseFormat = yield* prepareResponseFormat({
|
|
104
108
|
config,
|
|
105
109
|
options
|
|
106
110
|
});
|
|
111
|
+
const {
|
|
112
|
+
fileIdPrefixes: _fip,
|
|
113
|
+
strictJsonSchema: _sjs,
|
|
114
|
+
...apiConfig
|
|
115
|
+
} = config;
|
|
107
116
|
const request = {
|
|
108
|
-
...
|
|
117
|
+
...apiConfig,
|
|
109
118
|
input: messages,
|
|
110
|
-
include: include.size > 0 ? Array.from(include) :
|
|
119
|
+
include: include.size > 0 ? Array.from(include) : undefined,
|
|
111
120
|
text: {
|
|
112
|
-
verbosity: config.text?.verbosity ??
|
|
121
|
+
verbosity: config.text?.verbosity ?? undefined,
|
|
113
122
|
format: responseFormat
|
|
114
|
-
}
|
|
115
|
-
...(Predicate.isNotUndefined(tools) ? {
|
|
116
|
-
tools
|
|
117
|
-
} : undefined),
|
|
118
|
-
...(Predicate.isNotUndefined(toolChoice) ? {
|
|
119
|
-
tool_choice: toolChoice
|
|
120
|
-
} : undefined)
|
|
123
|
+
}
|
|
121
124
|
};
|
|
125
|
+
if (tools) request.tools = tools;
|
|
126
|
+
if (toolChoice) request.tool_choice = toolChoice;
|
|
127
|
+
if (options.previousResponseId) request.previous_response_id = options.previousResponseId;
|
|
122
128
|
return request;
|
|
123
129
|
});
|
|
124
130
|
return yield* LanguageModel.make({
|
|
131
|
+
codecTransformer: toCodecOpenAI,
|
|
125
132
|
generateText: Effect.fnUntraced(function* (options) {
|
|
126
133
|
const config = yield* makeConfig;
|
|
127
134
|
const toolNameMapper = new Tool.NameMapper(options.tools);
|
|
@@ -166,15 +173,15 @@ export const make = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
166
173
|
/**
|
|
167
174
|
* Creates a layer for the OpenAI language model.
|
|
168
175
|
*
|
|
169
|
-
* @since 1.0.0
|
|
170
176
|
* @category layers
|
|
177
|
+
* @since 4.0.0
|
|
171
178
|
*/
|
|
172
179
|
export const layer = options => Layer.effect(LanguageModel.LanguageModel, make(options));
|
|
173
180
|
/**
|
|
174
181
|
* Provides config overrides for OpenAI language model operations.
|
|
175
182
|
*
|
|
176
|
-
* @since 1.0.0
|
|
177
183
|
* @category configuration
|
|
184
|
+
* @since 4.0.0
|
|
178
185
|
*/
|
|
179
186
|
export const withConfigOverride = /*#__PURE__*/dual(2, (self, overrides) => Effect.flatMap(Effect.serviceOption(Config), config => Effect.provideService(self, Config, {
|
|
180
187
|
...(config._tag === "Some" ? config.value : {}),
|
|
@@ -207,14 +214,15 @@ const prepareMessages = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
207
214
|
if (config.store === false && capabilities.isReasoningModel) {
|
|
208
215
|
include.add("reasoning.encrypted_content");
|
|
209
216
|
}
|
|
210
|
-
if (
|
|
217
|
+
if (codeInterpreterTool) {
|
|
211
218
|
include.add("code_interpreter_call.outputs");
|
|
212
219
|
}
|
|
213
|
-
if (
|
|
220
|
+
if (webSearchTool || webSearchPreviewTool) {
|
|
214
221
|
include.add("web_search_call.action.sources");
|
|
215
222
|
}
|
|
216
223
|
const messages = [];
|
|
217
|
-
|
|
224
|
+
const prompt = options.incrementalPrompt ?? options.prompt;
|
|
225
|
+
for (const message of prompt.content) {
|
|
218
226
|
switch (message.role) {
|
|
219
227
|
case "system":
|
|
220
228
|
{
|
|
@@ -378,7 +386,9 @@ const prepareMessages = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
378
386
|
type: "reasoning",
|
|
379
387
|
id,
|
|
380
388
|
summary: summaryParts,
|
|
381
|
-
|
|
389
|
+
...(Predicate.isNotNull(encryptedContent) ? {
|
|
390
|
+
encrypted_content: encryptedContent
|
|
391
|
+
} : undefined)
|
|
382
392
|
};
|
|
383
393
|
messages.push(reasoningMessages[id]);
|
|
384
394
|
} else {
|
|
@@ -569,13 +579,15 @@ const buildHttpRequestDetails = request => ({
|
|
|
569
579
|
method: request.method,
|
|
570
580
|
url: request.url,
|
|
571
581
|
urlParams: Array.from(request.urlParams),
|
|
572
|
-
hash: request.hash,
|
|
582
|
+
hash: Option.getOrUndefined(request.hash),
|
|
573
583
|
headers: Redactable.redact(request.headers)
|
|
574
584
|
});
|
|
575
585
|
const buildHttpResponseDetails = response => ({
|
|
576
586
|
status: response.status,
|
|
577
587
|
headers: Redactable.redact(response.headers)
|
|
578
588
|
});
|
|
589
|
+
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"]);
|
|
590
|
+
const isKnownResponseStreamEvent = event => knownResponseStreamEventTypes.has(event.type);
|
|
579
591
|
const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
580
592
|
options,
|
|
581
593
|
rawResponse,
|
|
@@ -609,9 +621,7 @@ const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
609
621
|
operation: part.operation
|
|
610
622
|
},
|
|
611
623
|
metadata: {
|
|
612
|
-
openai:
|
|
613
|
-
...makeItemIdMetadata(part.id)
|
|
614
|
-
}
|
|
624
|
+
openai: makeItemIdMetadata(part.id)
|
|
615
625
|
}
|
|
616
626
|
});
|
|
617
627
|
break;
|
|
@@ -669,9 +679,8 @@ const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
669
679
|
{
|
|
670
680
|
hasToolCalls = true;
|
|
671
681
|
const toolName = part.name;
|
|
672
|
-
const toolParams =
|
|
673
|
-
|
|
674
|
-
try: () => Tool.unsafeSecureJsonParse(toolParams),
|
|
682
|
+
const toolParams = yield* Effect.try({
|
|
683
|
+
try: () => Tool.unsafeSecureJsonParse(part.arguments),
|
|
675
684
|
catch: cause => AiError.make({
|
|
676
685
|
module: "OpenAiLanguageModel",
|
|
677
686
|
method: "makeResponse",
|
|
@@ -682,15 +691,14 @@ const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
682
691
|
})
|
|
683
692
|
})
|
|
684
693
|
});
|
|
694
|
+
const params = yield* transformToolCallParams(options.tools, part.name, toolParams);
|
|
685
695
|
parts.push({
|
|
686
696
|
type: "tool-call",
|
|
687
697
|
id: part.call_id,
|
|
688
698
|
name: toolName,
|
|
689
699
|
params,
|
|
690
700
|
metadata: {
|
|
691
|
-
openai:
|
|
692
|
-
...makeItemIdMetadata(part.id)
|
|
693
|
-
}
|
|
701
|
+
openai: makeItemIdMetadata(part.id)
|
|
694
702
|
}
|
|
695
703
|
});
|
|
696
704
|
break;
|
|
@@ -727,9 +735,7 @@ const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
727
735
|
action: part.action
|
|
728
736
|
},
|
|
729
737
|
metadata: {
|
|
730
|
-
openai:
|
|
731
|
-
...makeItemIdMetadata(part.id)
|
|
732
|
-
}
|
|
738
|
+
openai: makeItemIdMetadata(part.id)
|
|
733
739
|
}
|
|
734
740
|
});
|
|
735
741
|
break;
|
|
@@ -737,12 +743,19 @@ const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
737
743
|
case "mcp_call":
|
|
738
744
|
{
|
|
739
745
|
const toolId = Predicate.isNotNullish(part.approval_request_id) ? approvalRequests.get(part.approval_request_id) ?? part.id : part.id;
|
|
740
|
-
const
|
|
746
|
+
const {
|
|
747
|
+
toolName,
|
|
748
|
+
params
|
|
749
|
+
} = yield* normalizeMcpToolCall({
|
|
750
|
+
toolNameMapper,
|
|
751
|
+
toolParams: part.arguments,
|
|
752
|
+
method: "makeResponse"
|
|
753
|
+
});
|
|
741
754
|
parts.push({
|
|
742
755
|
type: "tool-call",
|
|
743
756
|
id: toolId,
|
|
744
757
|
name: toolName,
|
|
745
|
-
params
|
|
758
|
+
params,
|
|
746
759
|
providerExecuted: true
|
|
747
760
|
});
|
|
748
761
|
parts.push({
|
|
@@ -752,7 +765,7 @@ const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
752
765
|
isFailure: false,
|
|
753
766
|
providerExecuted: true,
|
|
754
767
|
result: {
|
|
755
|
-
type: "
|
|
768
|
+
type: "mcp_call",
|
|
756
769
|
name: part.name,
|
|
757
770
|
arguments: part.arguments,
|
|
758
771
|
server_label: part.server_label,
|
|
@@ -764,9 +777,7 @@ const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
764
777
|
} : undefined)
|
|
765
778
|
},
|
|
766
779
|
metadata: {
|
|
767
|
-
openai:
|
|
768
|
-
...makeItemIdMetadata(part.id)
|
|
769
|
-
}
|
|
780
|
+
openai: makeItemIdMetadata(part.id)
|
|
770
781
|
}
|
|
771
782
|
});
|
|
772
783
|
break;
|
|
@@ -780,18 +791,13 @@ const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
780
791
|
{
|
|
781
792
|
const approvalRequestId = part.approval_request_id ?? part.id;
|
|
782
793
|
const toolId = yield* idGenerator.generateId();
|
|
783
|
-
const
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
toolName,
|
|
791
|
-
toolParams: {},
|
|
792
|
-
description: `Failed securely JSON parse tool parameters: ${cause}`
|
|
793
|
-
})
|
|
794
|
-
})
|
|
794
|
+
const {
|
|
795
|
+
toolName,
|
|
796
|
+
params
|
|
797
|
+
} = yield* normalizeMcpToolCall({
|
|
798
|
+
toolNameMapper,
|
|
799
|
+
toolParams: part.arguments,
|
|
800
|
+
method: "makeResponse"
|
|
795
801
|
});
|
|
796
802
|
parts.push({
|
|
797
803
|
type: "tool-call",
|
|
@@ -952,9 +958,7 @@ const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
952
958
|
action: part.action
|
|
953
959
|
},
|
|
954
960
|
metadata: {
|
|
955
|
-
openai:
|
|
956
|
-
...makeItemIdMetadata(part.id)
|
|
957
|
-
}
|
|
961
|
+
openai: makeItemIdMetadata(part.id)
|
|
958
962
|
}
|
|
959
963
|
});
|
|
960
964
|
break;
|
|
@@ -990,13 +994,7 @@ const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
990
994
|
reason: finishReason,
|
|
991
995
|
usage: getUsage(rawResponse.usage),
|
|
992
996
|
response: buildHttpResponseDetails(response),
|
|
993
|
-
...(rawResponse.service_tier
|
|
994
|
-
metadata: {
|
|
995
|
-
openai: {
|
|
996
|
-
serviceTier: rawResponse.service_tier
|
|
997
|
-
}
|
|
998
|
-
}
|
|
999
|
-
})
|
|
997
|
+
...toServiceTier(rawResponse.service_tier)
|
|
1000
998
|
});
|
|
1001
999
|
return parts;
|
|
1002
1000
|
});
|
|
@@ -1015,11 +1013,29 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
1015
1013
|
const activeAnnotations = [];
|
|
1016
1014
|
// Track active reasoning items with state machine for proper concluding logic
|
|
1017
1015
|
const activeReasoning = {};
|
|
1016
|
+
const getOrCreateReasoningPart = (itemId, encryptedContent) => {
|
|
1017
|
+
const activePart = activeReasoning[itemId];
|
|
1018
|
+
if (Predicate.isNotUndefined(activePart)) {
|
|
1019
|
+
if (Predicate.isNotNullish(encryptedContent)) {
|
|
1020
|
+
activePart.encryptedContent = encryptedContent;
|
|
1021
|
+
}
|
|
1022
|
+
return activePart;
|
|
1023
|
+
}
|
|
1024
|
+
const reasoningPart = {
|
|
1025
|
+
encryptedContent: Predicate.isNotNullish(encryptedContent) ? encryptedContent : undefined,
|
|
1026
|
+
summaryParts: {}
|
|
1027
|
+
};
|
|
1028
|
+
activeReasoning[itemId] = reasoningPart;
|
|
1029
|
+
return reasoningPart;
|
|
1030
|
+
};
|
|
1018
1031
|
// Track active tool calls with optional provider-specific state
|
|
1019
1032
|
const activeToolCalls = {};
|
|
1020
1033
|
const webSearchTool = options.tools.find(tool => Tool.isProviderDefined(tool) && (tool.name === "OpenAiWebSearch" || tool.name === "OpenAiWebSearchPreview"));
|
|
1021
1034
|
return stream.pipe(Stream.mapEffect(Effect.fnUntraced(function* (event) {
|
|
1022
1035
|
const parts = [];
|
|
1036
|
+
if (!isKnownResponseStreamEvent(event)) {
|
|
1037
|
+
return parts;
|
|
1038
|
+
}
|
|
1023
1039
|
switch (event.type) {
|
|
1024
1040
|
case "response.created":
|
|
1025
1041
|
{
|
|
@@ -1050,13 +1066,7 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
1050
1066
|
reason: InternalUtilities.resolveFinishReason(event.response.incomplete_details?.reason, hasToolCalls),
|
|
1051
1067
|
usage: getUsage(event.response.usage),
|
|
1052
1068
|
response: buildHttpResponseDetails(response),
|
|
1053
|
-
...(event.response.service_tier
|
|
1054
|
-
metadata: {
|
|
1055
|
-
openai: {
|
|
1056
|
-
serviceTier: event.response.service_tier
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
})
|
|
1069
|
+
...toServiceTier(event.response.service_tier)
|
|
1060
1070
|
});
|
|
1061
1071
|
break;
|
|
1062
1072
|
}
|
|
@@ -1157,7 +1167,10 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
1157
1167
|
{
|
|
1158
1168
|
activeToolCalls[event.output_index] = {
|
|
1159
1169
|
id: event.item.call_id,
|
|
1160
|
-
name: event.item.name
|
|
1170
|
+
name: event.item.name,
|
|
1171
|
+
functionCall: {
|
|
1172
|
+
emitted: false
|
|
1173
|
+
}
|
|
1161
1174
|
};
|
|
1162
1175
|
parts.push({
|
|
1163
1176
|
type: "tool-params-start",
|
|
@@ -1195,39 +1208,34 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
1195
1208
|
type: "text-start",
|
|
1196
1209
|
id: event.item.id,
|
|
1197
1210
|
metadata: {
|
|
1198
|
-
openai:
|
|
1199
|
-
...makeItemIdMetadata(event.item.id)
|
|
1200
|
-
}
|
|
1211
|
+
openai: makeItemIdMetadata(event.item.id)
|
|
1201
1212
|
}
|
|
1202
1213
|
});
|
|
1203
1214
|
break;
|
|
1204
1215
|
}
|
|
1205
1216
|
case "reasoning":
|
|
1206
1217
|
{
|
|
1207
|
-
const
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
openai: {
|
|
1219
|
-
...makeItemIdMetadata(event.item.id),
|
|
1220
|
-
...makeEncryptedContentMetadata(event.item.encrypted_content)
|
|
1218
|
+
const reasoningPart = getOrCreateReasoningPart(event.item.id, event.item.encrypted_content);
|
|
1219
|
+
if (Predicate.isUndefined(reasoningPart.summaryParts[0])) {
|
|
1220
|
+
reasoningPart.summaryParts[0] = "active";
|
|
1221
|
+
parts.push({
|
|
1222
|
+
type: "reasoning-start",
|
|
1223
|
+
id: `${event.item.id}:0`,
|
|
1224
|
+
metadata: {
|
|
1225
|
+
openai: {
|
|
1226
|
+
...makeItemIdMetadata(event.item.id),
|
|
1227
|
+
...makeEncryptedContentMetadata(reasoningPart.encryptedContent)
|
|
1228
|
+
}
|
|
1221
1229
|
}
|
|
1222
|
-
}
|
|
1223
|
-
}
|
|
1230
|
+
});
|
|
1231
|
+
}
|
|
1224
1232
|
break;
|
|
1225
1233
|
}
|
|
1226
1234
|
case "shell_call":
|
|
1227
1235
|
{
|
|
1228
1236
|
const toolName = toolNameMapper.getCustomName("shell");
|
|
1229
1237
|
activeToolCalls[event.output_index] = {
|
|
1230
|
-
id: event.item.id,
|
|
1238
|
+
id: event.item.id ?? event.item.call_id,
|
|
1231
1239
|
name: toolName
|
|
1232
1240
|
};
|
|
1233
1241
|
break;
|
|
@@ -1272,7 +1280,7 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
1272
1280
|
parts.push({
|
|
1273
1281
|
type: "tool-params-delta",
|
|
1274
1282
|
id: toolCall.id,
|
|
1275
|
-
delta: InternalUtilities.escapeJSONDelta(event.item.operation.diff)
|
|
1283
|
+
delta: InternalUtilities.escapeJSONDelta(event.item.operation.diff ?? "")
|
|
1276
1284
|
});
|
|
1277
1285
|
}
|
|
1278
1286
|
parts.push({
|
|
@@ -1298,9 +1306,7 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
1298
1306
|
operation: event.item.operation
|
|
1299
1307
|
},
|
|
1300
1308
|
metadata: {
|
|
1301
|
-
openai:
|
|
1302
|
-
...makeItemIdMetadata(event.item.id)
|
|
1303
|
-
}
|
|
1309
|
+
openai: makeItemIdMetadata(event.item.id)
|
|
1304
1310
|
}
|
|
1305
1311
|
});
|
|
1306
1312
|
}
|
|
@@ -1372,12 +1378,17 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
1372
1378
|
}
|
|
1373
1379
|
case "function_call":
|
|
1374
1380
|
{
|
|
1381
|
+
const toolCall = activeToolCalls[event.output_index];
|
|
1382
|
+
if (Predicate.isNotUndefined(toolCall?.functionCall?.emitted) && toolCall.functionCall.emitted) {
|
|
1383
|
+
delete activeToolCalls[event.output_index];
|
|
1384
|
+
break;
|
|
1385
|
+
}
|
|
1375
1386
|
delete activeToolCalls[event.output_index];
|
|
1376
1387
|
hasToolCalls = true;
|
|
1377
1388
|
const toolName = event.item.name;
|
|
1378
|
-
const
|
|
1379
|
-
const
|
|
1380
|
-
try: () => Tool.unsafeSecureJsonParse(
|
|
1389
|
+
const toolArgs = event.item.arguments;
|
|
1390
|
+
const toolParams = yield* Effect.try({
|
|
1391
|
+
try: () => Tool.unsafeSecureJsonParse(toolArgs),
|
|
1381
1392
|
catch: cause => AiError.make({
|
|
1382
1393
|
module: "OpenAiLanguageModel",
|
|
1383
1394
|
method: "makeStreamResponse",
|
|
@@ -1388,6 +1399,7 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
1388
1399
|
})
|
|
1389
1400
|
})
|
|
1390
1401
|
});
|
|
1402
|
+
const params = yield* transformToolCallParams(options.tools, toolName, toolParams);
|
|
1391
1403
|
parts.push({
|
|
1392
1404
|
type: "tool-params-end",
|
|
1393
1405
|
id: event.item.call_id
|
|
@@ -1398,9 +1410,7 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
1398
1410
|
name: toolName,
|
|
1399
1411
|
params,
|
|
1400
1412
|
metadata: {
|
|
1401
|
-
openai:
|
|
1402
|
-
...makeItemIdMetadata(event.item.id)
|
|
1403
|
-
}
|
|
1413
|
+
openai: makeItemIdMetadata(event.item.id)
|
|
1404
1414
|
}
|
|
1405
1415
|
});
|
|
1406
1416
|
break;
|
|
@@ -1431,9 +1441,7 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
1431
1441
|
action: event.item.action
|
|
1432
1442
|
},
|
|
1433
1443
|
metadata: {
|
|
1434
|
-
openai:
|
|
1435
|
-
...makeItemIdMetadata(event.item.id)
|
|
1436
|
-
}
|
|
1444
|
+
openai: makeItemIdMetadata(event.item.id)
|
|
1437
1445
|
}
|
|
1438
1446
|
});
|
|
1439
1447
|
break;
|
|
@@ -1443,12 +1451,19 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
1443
1451
|
const approvalRequestId = event.item.approval_request_id;
|
|
1444
1452
|
// Track approval with our own tool call identifiers
|
|
1445
1453
|
const toolId = Predicate.isNotNullish(approvalRequestId) ? streamApprovalRequests.get(approvalRequestId) ?? approvalRequests.get(approvalRequestId) ?? event.item.id : event.item.id;
|
|
1446
|
-
const
|
|
1454
|
+
const {
|
|
1455
|
+
toolName,
|
|
1456
|
+
params
|
|
1457
|
+
} = yield* normalizeMcpToolCall({
|
|
1458
|
+
toolNameMapper,
|
|
1459
|
+
toolParams: event.item.arguments,
|
|
1460
|
+
method: "makeStreamResponse"
|
|
1461
|
+
});
|
|
1447
1462
|
parts.push({
|
|
1448
1463
|
type: "tool-call",
|
|
1449
1464
|
id: toolId,
|
|
1450
1465
|
name: toolName,
|
|
1451
|
-
params
|
|
1466
|
+
params,
|
|
1452
1467
|
providerExecuted: true
|
|
1453
1468
|
});
|
|
1454
1469
|
parts.push({
|
|
@@ -1458,7 +1473,7 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
1458
1473
|
isFailure: false,
|
|
1459
1474
|
providerExecuted: true,
|
|
1460
1475
|
result: {
|
|
1461
|
-
type: "
|
|
1476
|
+
type: "mcp_call",
|
|
1462
1477
|
name: event.item.name,
|
|
1463
1478
|
arguments: event.item.arguments,
|
|
1464
1479
|
server_label: event.item.server_label,
|
|
@@ -1470,9 +1485,7 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
1470
1485
|
} : undefined)
|
|
1471
1486
|
},
|
|
1472
1487
|
metadata: {
|
|
1473
|
-
openai:
|
|
1474
|
-
...makeItemIdMetadata(event.item.id)
|
|
1475
|
-
}
|
|
1488
|
+
openai: makeItemIdMetadata(event.item.id)
|
|
1476
1489
|
}
|
|
1477
1490
|
});
|
|
1478
1491
|
break;
|
|
@@ -1487,12 +1500,19 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
1487
1500
|
const toolId = yield* idGenerator.generateId();
|
|
1488
1501
|
const approvalRequestId = event.item.approval_request_id ?? event.item.id;
|
|
1489
1502
|
streamApprovalRequests.set(approvalRequestId, toolId);
|
|
1490
|
-
const
|
|
1503
|
+
const {
|
|
1504
|
+
toolName,
|
|
1505
|
+
params
|
|
1506
|
+
} = yield* normalizeMcpToolCall({
|
|
1507
|
+
toolNameMapper,
|
|
1508
|
+
toolParams: event.item.arguments,
|
|
1509
|
+
method: "makeStreamResponse"
|
|
1510
|
+
});
|
|
1491
1511
|
parts.push({
|
|
1492
1512
|
type: "tool-call",
|
|
1493
1513
|
id: toolId,
|
|
1494
1514
|
name: toolName,
|
|
1495
|
-
params
|
|
1515
|
+
params,
|
|
1496
1516
|
providerExecuted: true
|
|
1497
1517
|
});
|
|
1498
1518
|
parts.push({
|
|
@@ -1521,7 +1541,7 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
1521
1541
|
}
|
|
1522
1542
|
case "reasoning":
|
|
1523
1543
|
{
|
|
1524
|
-
const reasoningPart =
|
|
1544
|
+
const reasoningPart = getOrCreateReasoningPart(event.item.id, event.item.encrypted_content);
|
|
1525
1545
|
for (const [summaryIndex, status] of Object.entries(reasoningPart.summaryParts)) {
|
|
1526
1546
|
if (status === "active" || status === "can-conclude") {
|
|
1527
1547
|
parts.push({
|
|
@@ -1530,7 +1550,7 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
1530
1550
|
metadata: {
|
|
1531
1551
|
openai: {
|
|
1532
1552
|
...makeItemIdMetadata(event.item.id),
|
|
1533
|
-
...makeEncryptedContentMetadata(
|
|
1553
|
+
...makeEncryptedContentMetadata(reasoningPart.encryptedContent)
|
|
1534
1554
|
}
|
|
1535
1555
|
}
|
|
1536
1556
|
});
|
|
@@ -1545,15 +1565,13 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
1545
1565
|
const toolName = toolNameMapper.getCustomName("shell");
|
|
1546
1566
|
parts.push({
|
|
1547
1567
|
type: "tool-call",
|
|
1548
|
-
id: event.item.id,
|
|
1568
|
+
id: event.item.id ?? event.item.call_id,
|
|
1549
1569
|
name: toolName,
|
|
1550
1570
|
params: {
|
|
1551
1571
|
action: event.item.action
|
|
1552
1572
|
},
|
|
1553
1573
|
metadata: {
|
|
1554
|
-
openai:
|
|
1555
|
-
...makeItemIdMetadata(event.item.id)
|
|
1556
|
-
}
|
|
1574
|
+
openai: makeItemIdMetadata(event.item.id)
|
|
1557
1575
|
}
|
|
1558
1576
|
});
|
|
1559
1577
|
break;
|
|
@@ -1670,6 +1688,41 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
1670
1688
|
}
|
|
1671
1689
|
break;
|
|
1672
1690
|
}
|
|
1691
|
+
case "response.function_call_arguments.done":
|
|
1692
|
+
{
|
|
1693
|
+
const toolCall = activeToolCalls[event.output_index];
|
|
1694
|
+
if (Predicate.isNotUndefined(toolCall?.functionCall) && !toolCall.functionCall.emitted) {
|
|
1695
|
+
hasToolCalls = true;
|
|
1696
|
+
const toolParams = yield* Effect.try({
|
|
1697
|
+
try: () => Tool.unsafeSecureJsonParse(event.arguments),
|
|
1698
|
+
catch: cause => AiError.make({
|
|
1699
|
+
module: "OpenAiLanguageModel",
|
|
1700
|
+
method: "makeStreamResponse",
|
|
1701
|
+
reason: new AiError.ToolParameterValidationError({
|
|
1702
|
+
toolName: toolCall.name,
|
|
1703
|
+
toolParams: {},
|
|
1704
|
+
description: `Failed securely JSON parse tool parameters: ${cause}`
|
|
1705
|
+
})
|
|
1706
|
+
})
|
|
1707
|
+
});
|
|
1708
|
+
const params = yield* transformToolCallParams(options.tools, toolCall.name, toolParams);
|
|
1709
|
+
parts.push({
|
|
1710
|
+
type: "tool-params-end",
|
|
1711
|
+
id: toolCall.id
|
|
1712
|
+
});
|
|
1713
|
+
parts.push({
|
|
1714
|
+
type: "tool-call",
|
|
1715
|
+
id: toolCall.id,
|
|
1716
|
+
name: toolCall.name,
|
|
1717
|
+
params,
|
|
1718
|
+
metadata: {
|
|
1719
|
+
openai: makeItemIdMetadata(event.item_id)
|
|
1720
|
+
}
|
|
1721
|
+
});
|
|
1722
|
+
toolCall.functionCall.emitted = true;
|
|
1723
|
+
}
|
|
1724
|
+
break;
|
|
1725
|
+
}
|
|
1673
1726
|
case "response.apply_patch_call_operation_diff.delta":
|
|
1674
1727
|
{
|
|
1675
1728
|
const toolCall = activeToolCalls[event.output_index];
|
|
@@ -1765,28 +1818,27 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
1765
1818
|
}
|
|
1766
1819
|
case "response.reasoning_summary_part.added":
|
|
1767
1820
|
{
|
|
1768
|
-
|
|
1821
|
+
const reasoningPart = getOrCreateReasoningPart(event.item_id);
|
|
1769
1822
|
if (event.summary_index > 0) {
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
...makeItemIdMetadata(event.item_id),
|
|
1781
|
-
...makeEncryptedContentMetadata(reasoningPart.encryptedContent)
|
|
1782
|
-
}
|
|
1823
|
+
// Conclude all can-conclude parts before starting new one
|
|
1824
|
+
for (const [summaryIndex, status] of Object.entries(reasoningPart.summaryParts)) {
|
|
1825
|
+
if (status === "can-conclude") {
|
|
1826
|
+
parts.push({
|
|
1827
|
+
type: "reasoning-end",
|
|
1828
|
+
id: `${event.item_id}:${summaryIndex}`,
|
|
1829
|
+
metadata: {
|
|
1830
|
+
openai: {
|
|
1831
|
+
...makeItemIdMetadata(event.item_id),
|
|
1832
|
+
...makeEncryptedContentMetadata(reasoningPart.encryptedContent)
|
|
1783
1833
|
}
|
|
1784
|
-
}
|
|
1785
|
-
|
|
1786
|
-
|
|
1834
|
+
}
|
|
1835
|
+
});
|
|
1836
|
+
reasoningPart.summaryParts[Number(summaryIndex)] = "concluded";
|
|
1787
1837
|
}
|
|
1788
|
-
reasoningPart.summaryParts[event.summary_index] = "active";
|
|
1789
1838
|
}
|
|
1839
|
+
}
|
|
1840
|
+
if (Predicate.isUndefined(reasoningPart.summaryParts[event.summary_index])) {
|
|
1841
|
+
reasoningPart.summaryParts[event.summary_index] = "active";
|
|
1790
1842
|
parts.push({
|
|
1791
1843
|
type: "reasoning-start",
|
|
1792
1844
|
id: `${event.item_id}:${event.summary_index}`,
|
|
@@ -1807,15 +1859,14 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
1807
1859
|
id: `${event.item_id}:${event.summary_index}`,
|
|
1808
1860
|
delta: event.delta,
|
|
1809
1861
|
metadata: {
|
|
1810
|
-
openai:
|
|
1811
|
-
...makeItemIdMetadata(event.item_id)
|
|
1812
|
-
}
|
|
1862
|
+
openai: makeItemIdMetadata(event.item_id)
|
|
1813
1863
|
}
|
|
1814
1864
|
});
|
|
1815
1865
|
break;
|
|
1816
1866
|
}
|
|
1817
1867
|
case "response.reasoning_summary_part.done":
|
|
1818
1868
|
{
|
|
1869
|
+
const reasoningPart = getOrCreateReasoningPart(event.item_id);
|
|
1819
1870
|
// When OpenAI stores message data, we can immediately conclude the
|
|
1820
1871
|
// reasoning part given that we do not need the encrypted content
|
|
1821
1872
|
if (config.store === true) {
|
|
@@ -1823,17 +1874,15 @@ const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
1823
1874
|
type: "reasoning-end",
|
|
1824
1875
|
id: `${event.item_id}:${event.summary_index}`,
|
|
1825
1876
|
metadata: {
|
|
1826
|
-
openai:
|
|
1827
|
-
...makeItemIdMetadata(event.item_id)
|
|
1828
|
-
}
|
|
1877
|
+
openai: makeItemIdMetadata(event.item_id)
|
|
1829
1878
|
}
|
|
1830
1879
|
});
|
|
1831
1880
|
// Mark the summary part concluded
|
|
1832
|
-
|
|
1881
|
+
reasoningPart.summaryParts[event.summary_index] = "concluded";
|
|
1833
1882
|
} else {
|
|
1834
1883
|
// Mark the summary part as can-conclude given we still need a
|
|
1835
1884
|
// final summary part with the encrypted content
|
|
1836
|
-
|
|
1885
|
+
reasoningPart.summaryParts[event.summary_index] = "can-conclude";
|
|
1837
1886
|
}
|
|
1838
1887
|
break;
|
|
1839
1888
|
}
|
|
@@ -1936,14 +1985,18 @@ const prepareTools = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
|
1936
1985
|
}
|
|
1937
1986
|
// Convert the tools in the toolkit to the provider-defined format
|
|
1938
1987
|
for (const tool of allowedTools) {
|
|
1939
|
-
if (Tool.isUserDefined(tool)) {
|
|
1988
|
+
if (Tool.isUserDefined(tool) || Tool.isDynamic(tool)) {
|
|
1940
1989
|
const strict = Tool.getStrictMode(tool) ?? config.strictJsonSchema ?? true;
|
|
1990
|
+
const description = Tool.getDescription(tool);
|
|
1991
|
+
const parameters = yield* tryToolJsonSchema(tool, "prepareTools");
|
|
1941
1992
|
tools.push({
|
|
1942
1993
|
type: "function",
|
|
1943
1994
|
name: tool.name,
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1995
|
+
parameters,
|
|
1996
|
+
strict,
|
|
1997
|
+
...(Predicate.isNotUndefined(description) ? {
|
|
1998
|
+
description
|
|
1999
|
+
} : undefined)
|
|
1947
2000
|
});
|
|
1948
2001
|
}
|
|
1949
2002
|
if (Tool.isProviderDefined(tool)) {
|
|
@@ -2111,29 +2164,53 @@ const getEncryptedContent = part => part.options.openai?.encryptedContent ?? nul
|
|
|
2111
2164
|
const getImageDetail = part => part.options.openai?.imageDetail ?? "auto";
|
|
2112
2165
|
const makeItemIdMetadata = itemId => Predicate.isNotUndefined(itemId) ? {
|
|
2113
2166
|
itemId
|
|
2114
|
-
} :
|
|
2167
|
+
} : {};
|
|
2115
2168
|
const makeEncryptedContentMetadata = encryptedContent => Predicate.isNotNullish(encryptedContent) ? {
|
|
2116
2169
|
encryptedContent
|
|
2117
2170
|
} : undefined;
|
|
2118
|
-
const
|
|
2171
|
+
const unsupportedSchemaError = (error, method) => AiError.make({
|
|
2172
|
+
module: "OpenAiLanguageModel",
|
|
2173
|
+
method,
|
|
2174
|
+
reason: new AiError.UnsupportedSchemaError({
|
|
2175
|
+
description: error instanceof Error ? error.message : String(error)
|
|
2176
|
+
})
|
|
2177
|
+
});
|
|
2178
|
+
const tryCodecTransform = (schema, method) => Effect.try({
|
|
2179
|
+
try: () => toCodecOpenAI(schema),
|
|
2180
|
+
catch: error => unsupportedSchemaError(error, method)
|
|
2181
|
+
});
|
|
2182
|
+
const tryJsonSchema = (schema, method) => Effect.try({
|
|
2183
|
+
try: () => Tool.getJsonSchemaFromSchema(schema, {
|
|
2184
|
+
transformer: toCodecOpenAI
|
|
2185
|
+
}),
|
|
2186
|
+
catch: error => unsupportedSchemaError(error, method)
|
|
2187
|
+
});
|
|
2188
|
+
const tryToolJsonSchema = (tool, method) => Effect.try({
|
|
2189
|
+
try: () => Tool.getJsonSchema(tool, {
|
|
2190
|
+
transformer: toCodecOpenAI
|
|
2191
|
+
}),
|
|
2192
|
+
catch: error => unsupportedSchemaError(error, method)
|
|
2193
|
+
});
|
|
2194
|
+
const prepareResponseFormat = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
2119
2195
|
config,
|
|
2120
2196
|
options
|
|
2121
|
-
})
|
|
2197
|
+
}) {
|
|
2122
2198
|
if (options.responseFormat.type === "json") {
|
|
2123
2199
|
const name = options.responseFormat.objectName;
|
|
2124
2200
|
const schema = options.responseFormat.schema;
|
|
2201
|
+
const jsonSchema = yield* tryJsonSchema(schema, "prepareResponseFormat");
|
|
2125
2202
|
return {
|
|
2126
2203
|
type: "json_schema",
|
|
2127
2204
|
name,
|
|
2128
2205
|
description: AST.resolveDescription(schema.ast) ?? "Response with a JSON object",
|
|
2129
|
-
schema:
|
|
2206
|
+
schema: jsonSchema,
|
|
2130
2207
|
strict: config.strictJsonSchema ?? true
|
|
2131
2208
|
};
|
|
2132
2209
|
}
|
|
2133
2210
|
return {
|
|
2134
2211
|
type: "text"
|
|
2135
2212
|
};
|
|
2136
|
-
};
|
|
2213
|
+
});
|
|
2137
2214
|
const getModelCapabilities = modelId => {
|
|
2138
2215
|
const supportsFlexProcessing = modelId.startsWith("o3") || modelId.startsWith("o4-mini") || modelId.startsWith("gpt-5") && !modelId.startsWith("gpt-5-chat");
|
|
2139
2216
|
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 +2247,35 @@ const getApprovalRequestIdMapping = prompt => {
|
|
|
2170
2247
|
}
|
|
2171
2248
|
return mapping;
|
|
2172
2249
|
};
|
|
2250
|
+
const normalizeMcpToolCall = /*#__PURE__*/Effect.fnUntraced(function* ({
|
|
2251
|
+
toolNameMapper,
|
|
2252
|
+
toolParams,
|
|
2253
|
+
method
|
|
2254
|
+
}) {
|
|
2255
|
+
const toolName = toolNameMapper.getCustomName("mcp");
|
|
2256
|
+
if (typeof toolParams !== "string") {
|
|
2257
|
+
return {
|
|
2258
|
+
toolName,
|
|
2259
|
+
params: toolParams
|
|
2260
|
+
};
|
|
2261
|
+
}
|
|
2262
|
+
const params = yield* Effect.try({
|
|
2263
|
+
try: () => Tool.unsafeSecureJsonParse(toolParams),
|
|
2264
|
+
catch: cause => AiError.make({
|
|
2265
|
+
module: "OpenAiLanguageModel",
|
|
2266
|
+
method,
|
|
2267
|
+
reason: new AiError.ToolParameterValidationError({
|
|
2268
|
+
toolName,
|
|
2269
|
+
toolParams,
|
|
2270
|
+
description: `Failed to securely JSON parse tool parameters: ${cause}`
|
|
2271
|
+
})
|
|
2272
|
+
})
|
|
2273
|
+
});
|
|
2274
|
+
return {
|
|
2275
|
+
toolName,
|
|
2276
|
+
params
|
|
2277
|
+
};
|
|
2278
|
+
});
|
|
2173
2279
|
const getUsage = usage => {
|
|
2174
2280
|
if (Predicate.isNullish(usage)) {
|
|
2175
2281
|
return {
|
|
@@ -2188,8 +2294,8 @@ const getUsage = usage => {
|
|
|
2188
2294
|
}
|
|
2189
2295
|
const inputTokens = usage.input_tokens;
|
|
2190
2296
|
const outputTokens = usage.output_tokens;
|
|
2191
|
-
const cachedTokens = usage.input_tokens_details
|
|
2192
|
-
const reasoningTokens = usage.output_tokens_details
|
|
2297
|
+
const cachedTokens = getUsageTokenDetail(usage.input_tokens_details, "cached_tokens");
|
|
2298
|
+
const reasoningTokens = getUsageTokenDetail(usage.output_tokens_details, "reasoning_tokens");
|
|
2193
2299
|
return {
|
|
2194
2300
|
inputTokens: {
|
|
2195
2301
|
uncached: inputTokens - cachedTokens,
|
|
@@ -2204,4 +2310,49 @@ const getUsage = usage => {
|
|
|
2204
2310
|
}
|
|
2205
2311
|
};
|
|
2206
2312
|
};
|
|
2313
|
+
const toServiceTier = value => {
|
|
2314
|
+
switch (value) {
|
|
2315
|
+
case "default":
|
|
2316
|
+
case "auto":
|
|
2317
|
+
case "flex":
|
|
2318
|
+
case "scale":
|
|
2319
|
+
case "priority":
|
|
2320
|
+
return {
|
|
2321
|
+
metadata: {
|
|
2322
|
+
openai: {
|
|
2323
|
+
serviceTier: value
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2326
|
+
};
|
|
2327
|
+
default:
|
|
2328
|
+
return undefined;
|
|
2329
|
+
}
|
|
2330
|
+
};
|
|
2331
|
+
const getUsageTokenDetail = (details, key) => Predicate.hasProperty(details, key) && typeof details[key] === "number" ? details[key] : 0;
|
|
2332
|
+
const transformToolCallParams = /*#__PURE__*/Effect.fnUntraced(function* (tools, toolName, toolParams) {
|
|
2333
|
+
const tool = tools.find(tool => tool.name === toolName);
|
|
2334
|
+
if (Predicate.isUndefined(tool)) {
|
|
2335
|
+
return yield* AiError.make({
|
|
2336
|
+
module: "OpenAiLanguageModel",
|
|
2337
|
+
method: "makeResponse",
|
|
2338
|
+
reason: new AiError.ToolNotFoundError({
|
|
2339
|
+
toolName,
|
|
2340
|
+
availableTools: tools.map(tool => tool.name)
|
|
2341
|
+
})
|
|
2342
|
+
});
|
|
2343
|
+
}
|
|
2344
|
+
const {
|
|
2345
|
+
codec
|
|
2346
|
+
} = yield* tryCodecTransform(tool.parametersSchema, "makeResponse");
|
|
2347
|
+
const transform = Schema.decodeEffect(codec);
|
|
2348
|
+
return yield* transform(toolParams).pipe(Effect.mapError(error => AiError.make({
|
|
2349
|
+
module: "OpenAiLanguageModel",
|
|
2350
|
+
method: "makeResponse",
|
|
2351
|
+
reason: new AiError.ToolParameterValidationError({
|
|
2352
|
+
toolName,
|
|
2353
|
+
toolParams,
|
|
2354
|
+
description: error.issue.toString()
|
|
2355
|
+
})
|
|
2356
|
+
})));
|
|
2357
|
+
});
|
|
2207
2358
|
//# sourceMappingURL=OpenAiLanguageModel.js.map
|