@opencode-ai/ai 0.0.0-dev-17929 → 0.0.0-dev-17944
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/protocols/index.d.ts +1 -0
- package/dist/protocols/index.js +1 -0
- package/dist/protocols/open-responses-channel.d.ts +0 -5
- package/dist/protocols/open-responses-channel.js +8 -1
- package/dist/protocols/{openai-responses-channel.d.ts → open-responses-continuation.d.ts} +1 -1
- package/dist/protocols/{openai-responses-channel.js → open-responses-continuation.js} +2 -2
- package/dist/protocols/open-responses.d.ts +51 -35
- package/dist/protocols/open-responses.js +62 -58
- package/dist/protocols/openai-compatible-responses.d.ts +8 -5
- package/dist/protocols/openai-responses.d.ts +80 -117
- package/dist/protocols/openai-responses.js +21 -68
- package/dist/protocols/utils/responses-hosted-tools.d.ts +27 -0
- package/dist/protocols/utils/responses-hosted-tools.js +32 -0
- package/dist/protocols/xai-responses.d.ts +174 -0
- package/dist/protocols/xai-responses.js +49 -0
- package/dist/provider-error.d.ts +1 -0
- package/dist/provider-error.js +4 -2
- package/dist/providers/amazon-bedrock-mantle.d.ts +8 -14
- package/dist/providers/azure.d.ts +8 -14
- package/dist/providers/google-vertex-responses.d.ts +8 -5
- package/dist/providers/openai-compatible-responses.d.ts +8 -5
- package/dist/providers/openai.d.ts +8 -14
- package/dist/providers/xai.d.ts +1 -135
- package/dist/providers/xai.js +4 -3
- package/dist/schema/errors.d.ts +1 -0
- package/dist/schema/errors.js +3 -0
- package/package.json +3 -3
|
@@ -8,3 +8,4 @@ export * as OpenAICompatibleResponses from "./openai-compatible-responses.js";
|
|
|
8
8
|
export * as OpenAIResponses from "./openai-responses.js";
|
|
9
9
|
export * as OpenResponses from "./open-responses.js";
|
|
10
10
|
export * as OpenResponsesChannel from "./open-responses-channel.js";
|
|
11
|
+
export * as XAIResponses from "./xai-responses.js";
|
package/dist/protocols/index.js
CHANGED
|
@@ -8,3 +8,4 @@ export * as OpenAICompatibleResponses from "./openai-compatible-responses.js";
|
|
|
8
8
|
export * as OpenAIResponses from "./openai-responses.js";
|
|
9
9
|
export * as OpenResponses from "./open-responses.js";
|
|
10
10
|
export * as OpenResponsesChannel from "./open-responses-channel.js";
|
|
11
|
+
export * as XAIResponses from "./xai-responses.js";
|
|
@@ -7,11 +7,6 @@ export interface Options {
|
|
|
7
7
|
readonly enabled?: (url: string) => boolean;
|
|
8
8
|
readonly url?: (url: string) => string;
|
|
9
9
|
readonly headers?: (headers: Headers.Headers) => Headers.Headers;
|
|
10
|
-
readonly driver?: (input: {
|
|
11
|
-
readonly request: Readonly<Record<string, unknown>>;
|
|
12
|
-
readonly message: string;
|
|
13
|
-
readonly base: WebSocketChannelDriver;
|
|
14
|
-
}) => WebSocketChannelDriver;
|
|
15
10
|
}
|
|
16
11
|
export interface Prepared {
|
|
17
12
|
readonly http: HttpTransport.HttpPrepared<string>;
|
|
@@ -4,6 +4,7 @@ import { Framing } from "../route/framing.js";
|
|
|
4
4
|
import { HttpTransport, WebSocketTransport, } from "../route/transport/index.js";
|
|
5
5
|
import * as ProviderShared from "./shared.js";
|
|
6
6
|
import { OpenResponses } from "./open-responses.js";
|
|
7
|
+
import { OpenResponsesContinuation } from "./open-responses-continuation.js";
|
|
7
8
|
const WebSocketResponseCreate = Schema.StructWithRest(Schema.Struct({ type: Schema.tag("response.create") }), [
|
|
8
9
|
Schema.Record(Schema.String, Schema.Unknown),
|
|
9
10
|
]);
|
|
@@ -87,7 +88,13 @@ export const transport = (options) => {
|
|
|
87
88
|
url: yield* WebSocketTransport.toWebSocketUrl(options.url?.(parts.url) ?? parts.url),
|
|
88
89
|
headers,
|
|
89
90
|
rotateAfterMs: options.rotateAfterMs,
|
|
90
|
-
driver:
|
|
91
|
+
driver: OpenResponsesContinuation.driver({
|
|
92
|
+
id: options.id,
|
|
93
|
+
name: options.name,
|
|
94
|
+
request: create.request,
|
|
95
|
+
message: create.message,
|
|
96
|
+
base,
|
|
97
|
+
}),
|
|
91
98
|
};
|
|
92
99
|
})
|
|
93
100
|
: undefined;
|
|
@@ -7,6 +7,6 @@ export interface DriverInput {
|
|
|
7
7
|
readonly base: WebSocketChannelDriver;
|
|
8
8
|
}
|
|
9
9
|
export declare const driver: (input: DriverInput) => WebSocketChannelDriver;
|
|
10
|
-
export declare const
|
|
10
|
+
export declare const OpenResponsesContinuation: {
|
|
11
11
|
readonly driver: (input: DriverInput) => WebSocketChannelDriver;
|
|
12
12
|
};
|
|
@@ -2,7 +2,7 @@ import { AIError, TransportReason } from "../schema/index.js";
|
|
|
2
2
|
import { Effect, Option, Schema } from "effect";
|
|
3
3
|
import * as ProviderShared from "./shared.js";
|
|
4
4
|
import { OpenResponses } from "./open-responses.js";
|
|
5
|
-
const PROTOCOL = "
|
|
5
|
+
const PROTOCOL = "open-responses.websocket.v1";
|
|
6
6
|
const VERSION = 1;
|
|
7
7
|
const decodeEvent = Schema.decodeUnknownEffect(OpenResponses.protocol.stream.event);
|
|
8
8
|
const checkpointValue = (checkpoint) => {
|
|
@@ -139,4 +139,4 @@ export const driver = (input) => {
|
|
|
139
139
|
}),
|
|
140
140
|
};
|
|
141
141
|
};
|
|
142
|
-
export const
|
|
142
|
+
export const OpenResponsesContinuation = { driver };
|
|
@@ -13,11 +13,11 @@ declare const MediaInput: Schema.Union<readonly [Schema.Struct<{
|
|
|
13
13
|
}>, Schema.Struct<{
|
|
14
14
|
readonly type: Schema.tag<"input_file">;
|
|
15
15
|
readonly filename: Schema.String;
|
|
16
|
-
readonly file_data: Schema.String
|
|
17
|
-
readonly
|
|
16
|
+
readonly file_data: Schema.optional<Schema.String>;
|
|
17
|
+
readonly file_url: Schema.optional<Schema.String>;
|
|
18
18
|
}>]>;
|
|
19
19
|
export type MediaInput = Schema.Schema.Type<typeof MediaInput>;
|
|
20
|
-
export declare const MessagePhase: Schema.Literals<readonly ["commentary", "final_answer"]
|
|
20
|
+
export declare const MessagePhase: Schema.NullOr<Schema.Literals<readonly ["commentary", "final_answer"]>>;
|
|
21
21
|
type MessagePhase = Schema.Schema.Type<typeof MessagePhase>;
|
|
22
22
|
export declare const InputItem: Schema.Union<readonly [Schema.Struct<{
|
|
23
23
|
readonly role: Schema.tag<"system">;
|
|
@@ -36,8 +36,8 @@ export declare const InputItem: Schema.Union<readonly [Schema.Struct<{
|
|
|
36
36
|
}>, Schema.Struct<{
|
|
37
37
|
readonly type: Schema.tag<"input_file">;
|
|
38
38
|
readonly filename: Schema.String;
|
|
39
|
-
readonly file_data: Schema.String
|
|
40
|
-
readonly
|
|
39
|
+
readonly file_data: Schema.optional<Schema.String>;
|
|
40
|
+
readonly file_url: Schema.optional<Schema.String>;
|
|
41
41
|
}>]>]>>;
|
|
42
42
|
}>, Schema.Struct<{
|
|
43
43
|
readonly type: Schema.tag<"message">;
|
|
@@ -47,7 +47,7 @@ export declare const InputItem: Schema.Union<readonly [Schema.Struct<{
|
|
|
47
47
|
readonly type: Schema.tag<"output_text">;
|
|
48
48
|
readonly text: Schema.String;
|
|
49
49
|
}>>;
|
|
50
|
-
readonly phase: Schema.optionalKey<Schema.Literals<readonly ["commentary", "final_answer"]
|
|
50
|
+
readonly phase: Schema.optionalKey<Schema.NullOr<Schema.Literals<readonly ["commentary", "final_answer"]>>>;
|
|
51
51
|
}>, Schema.Struct<{
|
|
52
52
|
readonly type: Schema.tag<"reasoning">;
|
|
53
53
|
readonly id: Schema.optionalKey<Schema.String>;
|
|
@@ -77,8 +77,11 @@ export declare const InputItem: Schema.Union<readonly [Schema.Struct<{
|
|
|
77
77
|
}>, Schema.Struct<{
|
|
78
78
|
readonly type: Schema.tag<"input_file">;
|
|
79
79
|
readonly filename: Schema.String;
|
|
80
|
-
readonly file_data: Schema.String
|
|
81
|
-
readonly
|
|
80
|
+
readonly file_data: Schema.optional<Schema.String>;
|
|
81
|
+
readonly file_url: Schema.optional<Schema.String>;
|
|
82
|
+
}>, Schema.Struct<{
|
|
83
|
+
readonly type: Schema.tag<"input_video">;
|
|
84
|
+
readonly video_url: Schema.String;
|
|
82
85
|
}>]>>]>;
|
|
83
86
|
}>]>;
|
|
84
87
|
type OpenResponsesInputItem = Schema.Schema.Type<typeof InputItem>;
|
|
@@ -129,8 +132,8 @@ export declare const coreFields: {
|
|
|
129
132
|
}>, Schema.Struct<{
|
|
130
133
|
readonly type: Schema.tag<"input_file">;
|
|
131
134
|
readonly filename: Schema.String;
|
|
132
|
-
readonly file_data: Schema.String
|
|
133
|
-
readonly
|
|
135
|
+
readonly file_data: Schema.optional<Schema.String>;
|
|
136
|
+
readonly file_url: Schema.optional<Schema.String>;
|
|
134
137
|
}>]>]>>;
|
|
135
138
|
}>, Schema.Struct<{
|
|
136
139
|
readonly type: Schema.tag<"message">;
|
|
@@ -140,7 +143,7 @@ export declare const coreFields: {
|
|
|
140
143
|
readonly type: Schema.tag<"output_text">;
|
|
141
144
|
readonly text: Schema.String;
|
|
142
145
|
}>>;
|
|
143
|
-
readonly phase: Schema.optionalKey<Schema.Literals<readonly ["commentary", "final_answer"]
|
|
146
|
+
readonly phase: Schema.optionalKey<Schema.NullOr<Schema.Literals<readonly ["commentary", "final_answer"]>>>;
|
|
144
147
|
}>, Schema.Struct<{
|
|
145
148
|
readonly type: Schema.tag<"reasoning">;
|
|
146
149
|
readonly id: Schema.optionalKey<Schema.String>;
|
|
@@ -170,8 +173,11 @@ export declare const coreFields: {
|
|
|
170
173
|
}>, Schema.Struct<{
|
|
171
174
|
readonly type: Schema.tag<"input_file">;
|
|
172
175
|
readonly filename: Schema.String;
|
|
173
|
-
readonly file_data: Schema.String
|
|
174
|
-
readonly
|
|
176
|
+
readonly file_data: Schema.optional<Schema.String>;
|
|
177
|
+
readonly file_url: Schema.optional<Schema.String>;
|
|
178
|
+
}>, Schema.Struct<{
|
|
179
|
+
readonly type: Schema.tag<"input_video">;
|
|
180
|
+
readonly video_url: Schema.String;
|
|
175
181
|
}>]>>]>;
|
|
176
182
|
}>]>>;
|
|
177
183
|
instructions: Schema.optional<Schema.String>;
|
|
@@ -239,8 +245,8 @@ declare const OpenResponsesBody: Schema.Struct<{
|
|
|
239
245
|
}>, Schema.Struct<{
|
|
240
246
|
readonly type: Schema.tag<"input_file">;
|
|
241
247
|
readonly filename: Schema.String;
|
|
242
|
-
readonly file_data: Schema.String
|
|
243
|
-
readonly
|
|
248
|
+
readonly file_data: Schema.optional<Schema.String>;
|
|
249
|
+
readonly file_url: Schema.optional<Schema.String>;
|
|
244
250
|
}>]>]>>;
|
|
245
251
|
}>, Schema.Struct<{
|
|
246
252
|
readonly type: Schema.tag<"message">;
|
|
@@ -250,7 +256,7 @@ declare const OpenResponsesBody: Schema.Struct<{
|
|
|
250
256
|
readonly type: Schema.tag<"output_text">;
|
|
251
257
|
readonly text: Schema.String;
|
|
252
258
|
}>>;
|
|
253
|
-
readonly phase: Schema.optionalKey<Schema.Literals<readonly ["commentary", "final_answer"]
|
|
259
|
+
readonly phase: Schema.optionalKey<Schema.NullOr<Schema.Literals<readonly ["commentary", "final_answer"]>>>;
|
|
254
260
|
}>, Schema.Struct<{
|
|
255
261
|
readonly type: Schema.tag<"reasoning">;
|
|
256
262
|
readonly id: Schema.optionalKey<Schema.String>;
|
|
@@ -280,8 +286,11 @@ declare const OpenResponsesBody: Schema.Struct<{
|
|
|
280
286
|
}>, Schema.Struct<{
|
|
281
287
|
readonly type: Schema.tag<"input_file">;
|
|
282
288
|
readonly filename: Schema.String;
|
|
283
|
-
readonly file_data: Schema.String
|
|
284
|
-
readonly
|
|
289
|
+
readonly file_data: Schema.optional<Schema.String>;
|
|
290
|
+
readonly file_url: Schema.optional<Schema.String>;
|
|
291
|
+
}>, Schema.Struct<{
|
|
292
|
+
readonly type: Schema.tag<"input_video">;
|
|
293
|
+
readonly video_url: Schema.String;
|
|
285
294
|
}>]>>]>;
|
|
286
295
|
}>]>>;
|
|
287
296
|
readonly instructions: Schema.optional<Schema.String>;
|
|
@@ -433,7 +442,6 @@ export interface Extension {
|
|
|
433
442
|
readonly media: ProviderShared.NormalizedMedia;
|
|
434
443
|
readonly request: LLMRequest;
|
|
435
444
|
}) => MediaInput | undefined;
|
|
436
|
-
readonly messagePhase?: (value: unknown) => MessagePhase | null | undefined;
|
|
437
445
|
}
|
|
438
446
|
export interface ParserState {
|
|
439
447
|
readonly id: string;
|
|
@@ -443,7 +451,6 @@ export interface ParserState {
|
|
|
443
451
|
readonly hasFunctionCall: boolean;
|
|
444
452
|
readonly lifecycle: Lifecycle.State;
|
|
445
453
|
readonly messageItems: ReadonlySet<string>;
|
|
446
|
-
readonly messagePhase: (value: unknown) => MessagePhase | null | undefined;
|
|
447
454
|
readonly messagePhases: Readonly<Record<string, MessagePhase | null>>;
|
|
448
455
|
readonly reasoningItems: Readonly<Record<string, ReasoningStreamItem>>;
|
|
449
456
|
readonly store: boolean | undefined;
|
|
@@ -547,8 +554,8 @@ export declare const fromRequest: (request: LLMRequest) => Effect.Effect<{
|
|
|
547
554
|
} | {
|
|
548
555
|
readonly type: "input_file";
|
|
549
556
|
readonly filename: string;
|
|
550
|
-
readonly file_data
|
|
551
|
-
readonly
|
|
557
|
+
readonly file_data?: string | undefined;
|
|
558
|
+
readonly file_url?: string | undefined;
|
|
552
559
|
} | {
|
|
553
560
|
readonly type: "input_text";
|
|
554
561
|
readonly text: string;
|
|
@@ -561,7 +568,7 @@ export declare const fromRequest: (request: LLMRequest) => Effect.Effect<{
|
|
|
561
568
|
}[];
|
|
562
569
|
readonly role: "assistant";
|
|
563
570
|
readonly id?: string | undefined;
|
|
564
|
-
readonly phase?: "commentary" | "final_answer" | undefined;
|
|
571
|
+
readonly phase?: "commentary" | "final_answer" | null | undefined;
|
|
565
572
|
} | {
|
|
566
573
|
readonly type: "function_call";
|
|
567
574
|
readonly name: string;
|
|
@@ -577,11 +584,14 @@ export declare const fromRequest: (request: LLMRequest) => Effect.Effect<{
|
|
|
577
584
|
} | {
|
|
578
585
|
readonly type: "input_file";
|
|
579
586
|
readonly filename: string;
|
|
580
|
-
readonly file_data
|
|
581
|
-
readonly
|
|
587
|
+
readonly file_data?: string | undefined;
|
|
588
|
+
readonly file_url?: string | undefined;
|
|
582
589
|
} | {
|
|
583
590
|
readonly type: "input_text";
|
|
584
591
|
readonly text: string;
|
|
592
|
+
} | {
|
|
593
|
+
readonly type: "input_video";
|
|
594
|
+
readonly video_url: string;
|
|
585
595
|
})[];
|
|
586
596
|
})[];
|
|
587
597
|
readonly model: string;
|
|
@@ -854,8 +864,8 @@ export declare const protocol: Protocol<{
|
|
|
854
864
|
} | {
|
|
855
865
|
readonly type: "input_file";
|
|
856
866
|
readonly filename: string;
|
|
857
|
-
readonly file_data
|
|
858
|
-
readonly
|
|
867
|
+
readonly file_data?: string | undefined;
|
|
868
|
+
readonly file_url?: string | undefined;
|
|
859
869
|
} | {
|
|
860
870
|
readonly type: "input_text";
|
|
861
871
|
readonly text: string;
|
|
@@ -868,7 +878,7 @@ export declare const protocol: Protocol<{
|
|
|
868
878
|
}[];
|
|
869
879
|
readonly role: "assistant";
|
|
870
880
|
readonly id?: string | undefined;
|
|
871
|
-
readonly phase?: "commentary" | "final_answer" | undefined;
|
|
881
|
+
readonly phase?: "commentary" | "final_answer" | null | undefined;
|
|
872
882
|
} | {
|
|
873
883
|
readonly type: "function_call";
|
|
874
884
|
readonly name: string;
|
|
@@ -884,11 +894,14 @@ export declare const protocol: Protocol<{
|
|
|
884
894
|
} | {
|
|
885
895
|
readonly type: "input_file";
|
|
886
896
|
readonly filename: string;
|
|
887
|
-
readonly file_data
|
|
888
|
-
readonly
|
|
897
|
+
readonly file_data?: string | undefined;
|
|
898
|
+
readonly file_url?: string | undefined;
|
|
889
899
|
} | {
|
|
890
900
|
readonly type: "input_text";
|
|
891
901
|
readonly text: string;
|
|
902
|
+
} | {
|
|
903
|
+
readonly type: "input_video";
|
|
904
|
+
readonly video_url: string;
|
|
892
905
|
})[];
|
|
893
906
|
})[];
|
|
894
907
|
readonly model: string;
|
|
@@ -1022,8 +1035,8 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
|
|
|
1022
1035
|
} | {
|
|
1023
1036
|
readonly type: "input_file";
|
|
1024
1037
|
readonly filename: string;
|
|
1025
|
-
readonly file_data
|
|
1026
|
-
readonly
|
|
1038
|
+
readonly file_data?: string | undefined;
|
|
1039
|
+
readonly file_url?: string | undefined;
|
|
1027
1040
|
} | {
|
|
1028
1041
|
readonly type: "input_text";
|
|
1029
1042
|
readonly text: string;
|
|
@@ -1036,7 +1049,7 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
|
|
|
1036
1049
|
}[];
|
|
1037
1050
|
readonly role: "assistant";
|
|
1038
1051
|
readonly id?: string | undefined;
|
|
1039
|
-
readonly phase?: "commentary" | "final_answer" | undefined;
|
|
1052
|
+
readonly phase?: "commentary" | "final_answer" | null | undefined;
|
|
1040
1053
|
} | {
|
|
1041
1054
|
readonly type: "function_call";
|
|
1042
1055
|
readonly name: string;
|
|
@@ -1052,11 +1065,14 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
|
|
|
1052
1065
|
} | {
|
|
1053
1066
|
readonly type: "input_file";
|
|
1054
1067
|
readonly filename: string;
|
|
1055
|
-
readonly file_data
|
|
1056
|
-
readonly
|
|
1068
|
+
readonly file_data?: string | undefined;
|
|
1069
|
+
readonly file_url?: string | undefined;
|
|
1057
1070
|
} | {
|
|
1058
1071
|
readonly type: "input_text";
|
|
1059
1072
|
readonly text: string;
|
|
1073
|
+
} | {
|
|
1074
|
+
readonly type: "input_video";
|
|
1075
|
+
readonly video_url: string;
|
|
1060
1076
|
})[];
|
|
1061
1077
|
})[];
|
|
1062
1078
|
readonly model: string;
|
|
@@ -25,8 +25,12 @@ const OpenResponsesInputImage = Schema.Struct({
|
|
|
25
25
|
const OpenResponsesInputFile = Schema.Struct({
|
|
26
26
|
type: Schema.tag("input_file"),
|
|
27
27
|
filename: Schema.String,
|
|
28
|
-
file_data: Schema.String,
|
|
29
|
-
|
|
28
|
+
file_data: Schema.optional(Schema.String),
|
|
29
|
+
file_url: Schema.optional(Schema.String),
|
|
30
|
+
});
|
|
31
|
+
const OpenResponsesInputVideo = Schema.Struct({
|
|
32
|
+
type: Schema.tag("input_video"),
|
|
33
|
+
video_url: Schema.String,
|
|
30
34
|
});
|
|
31
35
|
const MediaInput = Schema.Union([OpenResponsesInputImage, OpenResponsesInputFile]);
|
|
32
36
|
const OpenResponsesInputContent = Schema.Union([OpenResponsesInputText, MediaInput]);
|
|
@@ -34,7 +38,12 @@ const OpenResponsesOutputText = Schema.Struct({
|
|
|
34
38
|
type: Schema.tag("output_text"),
|
|
35
39
|
text: Schema.String,
|
|
36
40
|
});
|
|
37
|
-
export const MessagePhase = Schema.Literals(["commentary", "final_answer"]);
|
|
41
|
+
export const MessagePhase = Schema.NullOr(Schema.Literals(["commentary", "final_answer"]));
|
|
42
|
+
const messagePhase = (value) => {
|
|
43
|
+
if (value === null || value === "commentary" || value === "final_answer")
|
|
44
|
+
return value;
|
|
45
|
+
return undefined;
|
|
46
|
+
};
|
|
38
47
|
const OpenResponsesReasoningSummaryText = Schema.Struct({
|
|
39
48
|
type: Schema.tag("summary_text"),
|
|
40
49
|
text: Schema.String,
|
|
@@ -56,6 +65,7 @@ const OpenResponsesFunctionCallOutputContent = Schema.Union([
|
|
|
56
65
|
OpenResponsesInputText,
|
|
57
66
|
OpenResponsesInputImage,
|
|
58
67
|
OpenResponsesInputFile,
|
|
68
|
+
OpenResponsesInputVideo,
|
|
59
69
|
]);
|
|
60
70
|
const OpenResponsesFunctionCallOutput = Schema.Union([
|
|
61
71
|
Schema.String,
|
|
@@ -213,19 +223,6 @@ export const Event = Schema.StructWithRest(Schema.Struct({
|
|
|
213
223
|
status_code: Schema.optional(Schema.Unknown),
|
|
214
224
|
headers: Schema.optional(Schema.Unknown),
|
|
215
225
|
}), [Schema.Record(Schema.String, Schema.Unknown)]);
|
|
216
|
-
const RefusalEvent = Schema.Union([
|
|
217
|
-
Schema.Struct({
|
|
218
|
-
type: Schema.tag("response.refusal.delta"),
|
|
219
|
-
item_id: Schema.String,
|
|
220
|
-
delta: Schema.String,
|
|
221
|
-
}),
|
|
222
|
-
Schema.Struct({
|
|
223
|
-
type: Schema.tag("response.refusal.done"),
|
|
224
|
-
item_id: Schema.String,
|
|
225
|
-
refusal: Schema.String,
|
|
226
|
-
}),
|
|
227
|
-
]);
|
|
228
|
-
const isRefusalEvent = Schema.is(RefusalEvent);
|
|
229
226
|
const BASE = { id: ADAPTER, name: NAME };
|
|
230
227
|
// =============================================================================
|
|
231
228
|
// Request Lowering
|
|
@@ -279,36 +276,49 @@ const lowerReasoning = (part, providerMetadataKey) => {
|
|
|
279
276
|
encrypted_content: encryptedContent,
|
|
280
277
|
};
|
|
281
278
|
};
|
|
282
|
-
const
|
|
283
|
-
return itemID(part.providerMetadata, providerMetadataKey);
|
|
284
|
-
};
|
|
285
|
-
const lowerMedia = Effect.fn("OpenResponses.lowerMedia")(function* (part, request, extension) {
|
|
279
|
+
const lowerMedia = Effect.fn("OpenResponses.lowerMedia")(function* (part, request, extension, target) {
|
|
286
280
|
const media = ProviderShared.normalizeMedia(part);
|
|
287
281
|
const extended = extension.lowerMedia?.({ part, media, request });
|
|
288
282
|
if (extended)
|
|
289
283
|
return extended;
|
|
284
|
+
const url = typeof part.data === "string" && (part.data.startsWith("https://") || part.data.startsWith("http://"))
|
|
285
|
+
? part.data
|
|
286
|
+
: undefined;
|
|
290
287
|
if (!media.mime.startsWith("image/")) {
|
|
288
|
+
if (target === "tool-result" && media.mime.startsWith("video/"))
|
|
289
|
+
return { type: "input_video", video_url: url ?? media.dataUrl };
|
|
291
290
|
return {
|
|
292
291
|
type: "input_file",
|
|
293
292
|
filename: part.filename ?? (media.mime === "application/pdf" ? "document.pdf" : "file"),
|
|
294
|
-
file_data: media.
|
|
293
|
+
...(url ? { file_url: url } : { file_data: media.base64 }),
|
|
295
294
|
};
|
|
296
295
|
}
|
|
297
|
-
return { type: "input_image", image_url: media.dataUrl };
|
|
296
|
+
return { type: "input_image", image_url: url ?? media.dataUrl };
|
|
298
297
|
});
|
|
299
298
|
const lowerUserContent = Effect.fnUntraced(function* (part, request, extension) {
|
|
300
299
|
if (part.type === "text")
|
|
301
300
|
return { type: "input_text", text: part.text };
|
|
302
301
|
if (part.type === "media")
|
|
303
|
-
return yield*
|
|
302
|
+
return yield* lowerMessageMedia(part, request, extension);
|
|
304
303
|
return yield* ProviderShared.unsupportedContent(extension.name, "user", ["text", "media"]);
|
|
305
304
|
});
|
|
305
|
+
const lowerMessageMedia = Effect.fnUntraced(function* (part, request, extension) {
|
|
306
|
+
const lowered = yield* lowerMedia(part, request, extension, "message");
|
|
307
|
+
if (lowered.type === "input_video")
|
|
308
|
+
return yield* ProviderShared.invalidRequest(`${extension.name} user messages do not support input_video`);
|
|
309
|
+
return lowered;
|
|
310
|
+
});
|
|
306
311
|
// Tool results may carry structured text, images, and files. Keep media as provider-native
|
|
307
312
|
// content instead of JSON-stringifying base64 into a prompt string.
|
|
308
313
|
const lowerToolResultContentItem = Effect.fnUntraced(function* (item, request, extension) {
|
|
309
314
|
if (item.type === "text")
|
|
310
315
|
return { type: "input_text", text: item.text };
|
|
311
|
-
return yield* lowerMedia({ type: "media", mediaType: item.mime, data: item.uri, filename: item.name }, request, extension);
|
|
316
|
+
return yield* lowerMedia({ type: "media", mediaType: item.mime, data: item.uri, filename: item.name }, request, extension, "tool-result");
|
|
317
|
+
});
|
|
318
|
+
const lowerHostedToolResultContentItem = Effect.fnUntraced(function* (item, request, extension) {
|
|
319
|
+
if (item.type === "text")
|
|
320
|
+
return { type: "input_text", text: item.text };
|
|
321
|
+
return yield* lowerMessageMedia({ type: "media", mediaType: item.mime, data: item.uri, filename: item.name }, request, extension);
|
|
312
322
|
});
|
|
313
323
|
const lowerToolResultOutput = Effect.fnUntraced(function* (part, request, extension) {
|
|
314
324
|
// Text/json/error results are encoded as a plain string for backward
|
|
@@ -350,7 +360,7 @@ const lowerMessages = Effect.fn("OpenResponses.lowerMessages")(function* (reques
|
|
|
350
360
|
const groups = content.reduce((groups, part) => {
|
|
351
361
|
const metadata = part.providerMetadata?.[providerMetadataKey];
|
|
352
362
|
const id = itemID(part.providerMetadata, providerMetadataKey);
|
|
353
|
-
const phase = ProviderShared.isRecord(metadata) ? messagePhase(metadata.phase
|
|
363
|
+
const phase = ProviderShared.isRecord(metadata) ? messagePhase(metadata.phase) : undefined;
|
|
354
364
|
const group = groups.at(-1);
|
|
355
365
|
if (group && group.id === id && group.phase === phase)
|
|
356
366
|
group.parts.push(part);
|
|
@@ -403,18 +413,18 @@ const lowerMessages = Effect.fn("OpenResponses.lowerMessages")(function* (reques
|
|
|
403
413
|
}
|
|
404
414
|
if (part.type === "tool-result" && part.providerExecuted === true) {
|
|
405
415
|
flushText();
|
|
406
|
-
const
|
|
407
|
-
if (store !== false &&
|
|
408
|
-
input.push({ type: "item_reference", id
|
|
416
|
+
const id = itemID(part.providerMetadata, providerMetadataKey);
|
|
417
|
+
if (store !== false && id && !hostedToolReferences.has(id))
|
|
418
|
+
input.push({ type: "item_reference", id });
|
|
409
419
|
if (store === false && part.result.type === "content") {
|
|
410
420
|
const content = part.result.value;
|
|
411
421
|
input.push({
|
|
412
422
|
role: "user",
|
|
413
|
-
content: yield* Effect.forEach(content, (item) =>
|
|
423
|
+
content: yield* Effect.forEach(content, (item) => lowerHostedToolResultContentItem(item, request, extension)),
|
|
414
424
|
});
|
|
415
425
|
}
|
|
416
|
-
if (
|
|
417
|
-
hostedToolReferences.add(
|
|
426
|
+
if (id)
|
|
427
|
+
hostedToolReferences.add(id);
|
|
418
428
|
continue;
|
|
419
429
|
}
|
|
420
430
|
return yield* ProviderShared.unsupportedContent(extension.name, "assistant", [
|
|
@@ -598,18 +608,17 @@ const reasoningMetadata = (state, item) => providerMetadata(state, { itemId: ite
|
|
|
598
608
|
// best-effort, not guaranteed.
|
|
599
609
|
const onOutputItemAdded = (state, event) => {
|
|
600
610
|
const item = event.item;
|
|
601
|
-
if (item?.type === "message" && item.id)
|
|
611
|
+
if (item?.type === "message" && item.id) {
|
|
612
|
+
const phase = messagePhase(item.phase);
|
|
602
613
|
return [
|
|
603
614
|
{
|
|
604
615
|
...state,
|
|
605
616
|
messageItems: new Set([...state.messageItems, item.id]),
|
|
606
|
-
messagePhases:
|
|
607
|
-
const phase = state.messagePhase(item.phase);
|
|
608
|
-
return phase === undefined ? state.messagePhases : { ...state.messagePhases, [item.id]: phase };
|
|
609
|
-
})(),
|
|
617
|
+
messagePhases: phase === undefined ? state.messagePhases : { ...state.messagePhases, [item.id]: phase },
|
|
610
618
|
},
|
|
611
619
|
NO_EVENTS,
|
|
612
620
|
];
|
|
621
|
+
}
|
|
613
622
|
if (item && isReasoningItem(item)) {
|
|
614
623
|
const events = [];
|
|
615
624
|
return [
|
|
@@ -731,7 +740,7 @@ const onOutputItemDone = Effect.fn("OpenResponses.onOutputItemDone")(function* (
|
|
|
731
740
|
if (!item)
|
|
732
741
|
return [state, NO_EVENTS];
|
|
733
742
|
if (item.type === "message" && item.id) {
|
|
734
|
-
const itemPhase =
|
|
743
|
+
const itemPhase = messagePhase(item.phase);
|
|
735
744
|
const phase = itemPhase === undefined ? state.messagePhases[item.id] : itemPhase;
|
|
736
745
|
const events = [];
|
|
737
746
|
const messageItems = new Set(state.messageItems);
|
|
@@ -822,22 +831,26 @@ const onResponseFinish = Effect.fn("OpenResponses.onResponseFinish")(function* (
|
|
|
822
831
|
});
|
|
823
832
|
return [{ ...state, lifecycle, hasFunctionCall, tools: pending.tools }, events];
|
|
824
833
|
});
|
|
825
|
-
// Build
|
|
834
|
+
// Build the prettiest summary available from whatever the provider supplied.
|
|
826
835
|
// When both code and message are present, prefix the code so consumers see
|
|
827
836
|
// the failure mode (e.g. `rate_limit_exceeded: Slow down`) instead of just
|
|
828
837
|
// the bare message — production rate limits and context-length failures used
|
|
829
|
-
// to be indistinguishable from generic stream drops.
|
|
830
|
-
|
|
831
|
-
|
|
838
|
+
// to be indistinguishable from generic stream drops. Returns undefined when
|
|
839
|
+
// the payload carries no usable summary.
|
|
840
|
+
const providerErrorMessage = (event, nested) => {
|
|
832
841
|
const message = event.message || nested?.message || undefined;
|
|
833
842
|
const code = event.code || nested?.code || undefined;
|
|
834
843
|
if (message && code)
|
|
835
844
|
return `${code}: ${message}`;
|
|
836
|
-
return message || code
|
|
845
|
+
return message || code;
|
|
837
846
|
};
|
|
838
847
|
export const providerFailure = (id, event, fallback) => {
|
|
839
|
-
const
|
|
840
|
-
const
|
|
848
|
+
const nested = event.error ?? event.response?.error ?? undefined;
|
|
849
|
+
const code = event.code || nested?.code || undefined;
|
|
850
|
+
// Keep the full raw payload on the error even when the message is a summary.
|
|
851
|
+
const body = JSON.stringify(nested ?? event) ?? "";
|
|
852
|
+
const summary = providerErrorMessage(event, nested);
|
|
853
|
+
const message = summary ?? (body === "{}" ? fallback : body);
|
|
841
854
|
const status = typeof event.status === "number"
|
|
842
855
|
? event.status
|
|
843
856
|
: typeof event.status_code === "number"
|
|
@@ -846,7 +859,8 @@ export const providerFailure = (id, event, fallback) => {
|
|
|
846
859
|
return new AIError({
|
|
847
860
|
module: id,
|
|
848
861
|
method: "stream",
|
|
849
|
-
|
|
862
|
+
body,
|
|
863
|
+
reason: classifyProviderFailure({ message, code, status, rawBody: body }),
|
|
850
864
|
});
|
|
851
865
|
};
|
|
852
866
|
const providerError = (state, event, fallback) => providerFailure(state.id, event, fallback);
|
|
@@ -859,22 +873,18 @@ export const step = (state, event) => {
|
|
|
859
873
|
: onOutputTextDone(state, event, event.item_id));
|
|
860
874
|
}
|
|
861
875
|
if (event.type === "response.refusal.delta" || event.type === "response.refusal.done") {
|
|
862
|
-
|
|
876
|
+
const value = event.type === "response.refusal.delta" ? event.delta : event.refusal;
|
|
877
|
+
if (!event.item_id || typeof value !== "string")
|
|
863
878
|
return ProviderShared.eventError(state.id, `${event.type} is malformed`);
|
|
864
879
|
return Effect.succeed(event.type === "response.refusal.delta"
|
|
865
880
|
? onOutputTextDelta(state, event, event.item_id)
|
|
866
|
-
: onOutputTextDone(state, { ...event, text:
|
|
881
|
+
: onOutputTextDone(state, { ...event, text: value }, event.item_id));
|
|
867
882
|
}
|
|
868
883
|
if (event.type === "response.reasoning.delta" || event.type === "response.reasoning_summary_text.delta") {
|
|
869
884
|
if (!event.item_id)
|
|
870
885
|
return ProviderShared.eventError(state.id, `${event.type} is missing item_id`);
|
|
871
886
|
return Effect.succeed(onReasoningDelta(state, event, event.item_id));
|
|
872
887
|
}
|
|
873
|
-
if (event.type === "response.reasoning.done" || event.type === "response.reasoning_summary_text.done") {
|
|
874
|
-
if (!event.item_id)
|
|
875
|
-
return ProviderShared.eventError(state.id, `${event.type} is missing item_id`);
|
|
876
|
-
return Effect.succeed(onReasoningDone(state, event));
|
|
877
|
-
}
|
|
878
888
|
if (event.type === "response.reasoning_summary_part.added")
|
|
879
889
|
return event.item_id
|
|
880
890
|
? Effect.succeed(onReasoningSummaryPartAdded(state, event))
|
|
@@ -918,16 +928,10 @@ export const initial = (request, extension = BASE) => ({
|
|
|
918
928
|
tools: ToolStream.empty(),
|
|
919
929
|
lifecycle: Lifecycle.initial(),
|
|
920
930
|
messageItems: new Set(),
|
|
921
|
-
messagePhase: (value) => messagePhase(value, extension),
|
|
922
931
|
messagePhases: {},
|
|
923
932
|
reasoningItems: {},
|
|
924
933
|
store: OpenResponsesOptions.resolve(request).store,
|
|
925
934
|
});
|
|
926
|
-
const messagePhase = (value, extension) => {
|
|
927
|
-
if (value === "commentary" || value === "final_answer")
|
|
928
|
-
return value;
|
|
929
|
-
return extension.messagePhase?.(value);
|
|
930
|
-
};
|
|
931
935
|
export const protocol = Protocol.make({
|
|
932
936
|
id: ADAPTER,
|
|
933
937
|
body: {
|
|
@@ -31,8 +31,8 @@ export declare const route: Route<{
|
|
|
31
31
|
} | {
|
|
32
32
|
readonly type: "input_file";
|
|
33
33
|
readonly filename: string;
|
|
34
|
-
readonly file_data
|
|
35
|
-
readonly
|
|
34
|
+
readonly file_data?: string | undefined;
|
|
35
|
+
readonly file_url?: string | undefined;
|
|
36
36
|
} | {
|
|
37
37
|
readonly type: "input_text";
|
|
38
38
|
readonly text: string;
|
|
@@ -45,7 +45,7 @@ export declare const route: Route<{
|
|
|
45
45
|
}[];
|
|
46
46
|
readonly role: "assistant";
|
|
47
47
|
readonly id?: string | undefined;
|
|
48
|
-
readonly phase?: "commentary" | "final_answer" | undefined;
|
|
48
|
+
readonly phase?: "commentary" | "final_answer" | null | undefined;
|
|
49
49
|
} | {
|
|
50
50
|
readonly type: "function_call";
|
|
51
51
|
readonly name: string;
|
|
@@ -61,11 +61,14 @@ export declare const route: Route<{
|
|
|
61
61
|
} | {
|
|
62
62
|
readonly type: "input_file";
|
|
63
63
|
readonly filename: string;
|
|
64
|
-
readonly file_data
|
|
65
|
-
readonly
|
|
64
|
+
readonly file_data?: string | undefined;
|
|
65
|
+
readonly file_url?: string | undefined;
|
|
66
66
|
} | {
|
|
67
67
|
readonly type: "input_text";
|
|
68
68
|
readonly text: string;
|
|
69
|
+
} | {
|
|
70
|
+
readonly type: "input_video";
|
|
71
|
+
readonly video_url: string;
|
|
69
72
|
})[];
|
|
70
73
|
})[];
|
|
71
74
|
readonly model: string;
|