@ai-sdk/open-responses 2.0.54 → 2.0.55
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/CHANGELOG.md +10 -0
- package/dist/index.d.ts +97 -40
- package/dist/index.js +154 -40
- package/dist/index.js.map +1 -1
- package/docs/06-open-responses.mdx +55 -4
- package/package.json +3 -3
- package/src/index.ts +1 -0
- package/src/open-responses-extension.ts +299 -67
- package/src/open-responses-provider.ts +2 -2
- package/src/responses/convert-to-open-responses-input.ts +12 -9
- package/src/responses/open-responses-language-model.ts +20 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @ai-sdk/open-responses
|
|
2
2
|
|
|
3
|
+
## 2.0.55
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 8cf3f5b: Allow extension codecs to explicitly opt in to exact bare tool, item, and event discriminator registration.
|
|
8
|
+
- Updated dependencies [e3605f6]
|
|
9
|
+
- Updated dependencies [525efc5]
|
|
10
|
+
- @ai-sdk/provider-utils@5.0.50
|
|
11
|
+
- @ai-sdk/provider@4.0.19
|
|
12
|
+
|
|
3
13
|
## 2.0.54
|
|
4
14
|
|
|
5
15
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -5,14 +5,14 @@ import { MaybePromiseLike, FetchFunction, ResponseHandler, InferSchema } from '@
|
|
|
5
5
|
declare const VERSION: string;
|
|
6
6
|
|
|
7
7
|
type OpenResponsesNamespacedType = `${string}:${string}`;
|
|
8
|
-
type OpenResponsesExtensionRecord = JSONObject & {
|
|
9
|
-
type:
|
|
8
|
+
type OpenResponsesExtensionRecord<Type extends string = OpenResponsesNamespacedType> = JSONObject & {
|
|
9
|
+
type: Type;
|
|
10
10
|
};
|
|
11
|
-
type OpenResponsesExtensionItem = OpenResponsesExtensionRecord & {
|
|
11
|
+
type OpenResponsesExtensionItem<Type extends string = OpenResponsesNamespacedType> = OpenResponsesExtensionRecord<Type> & {
|
|
12
12
|
id: string;
|
|
13
13
|
status: string;
|
|
14
14
|
};
|
|
15
|
-
type OpenResponsesExtensionEvent = OpenResponsesExtensionRecord & {
|
|
15
|
+
type OpenResponsesExtensionEvent<Type extends string = OpenResponsesNamespacedType> = OpenResponsesExtensionRecord<Type> & {
|
|
16
16
|
sequence_number: number;
|
|
17
17
|
};
|
|
18
18
|
type OpenResponsesExtensionInputPart = LanguageModelV4ToolCallPart | LanguageModelV4ToolResultPart;
|
|
@@ -25,7 +25,7 @@ type OpenResponsesExtensionStreamPart = Exclude<LanguageModelV4StreamPart, {
|
|
|
25
25
|
*
|
|
26
26
|
* Tool, item, and event codecs can be registered independently.
|
|
27
27
|
*/
|
|
28
|
-
interface
|
|
28
|
+
interface OpenResponsesExtensionBase {
|
|
29
29
|
/**
|
|
30
30
|
* Extension ID in `<implementor>.<extension>` format. For extensions that
|
|
31
31
|
* encode a provider tool, this is also the AI SDK provider-tool ID.
|
|
@@ -36,78 +36,135 @@ interface OpenResponsesExtension {
|
|
|
36
36
|
* Must be provided together with `encodeTool`.
|
|
37
37
|
*/
|
|
38
38
|
toolType?: OpenResponsesNamespacedType;
|
|
39
|
-
/**
|
|
40
|
-
* Namespaced item types decoded by this extension. Must be provided together
|
|
41
|
-
* with `decodeItem`.
|
|
42
|
-
*/
|
|
43
|
-
itemTypes?: readonly OpenResponsesNamespacedType[];
|
|
44
|
-
/**
|
|
45
|
-
* Namespaced streaming event types decoded by this extension. Must be
|
|
46
|
-
* provided together with `decodeEvent`.
|
|
47
|
-
*/
|
|
48
|
-
eventTypes?: readonly OpenResponsesNamespacedType[];
|
|
49
39
|
/**
|
|
50
40
|
* Encodes an AI SDK provider tool. Return `undefined` when its arguments
|
|
51
|
-
* cannot be encoded. The adapter adds
|
|
52
|
-
* choice that selects the omitted tool.
|
|
41
|
+
* cannot be encoded. The adapter adds the registered tool type and omits a
|
|
42
|
+
* specific tool choice that selects the omitted tool.
|
|
53
43
|
*/
|
|
54
44
|
encodeTool?(options: {
|
|
55
45
|
name: string;
|
|
56
46
|
args: Record<string, unknown>;
|
|
57
47
|
}): MaybePromiseLike<JSONObject | undefined>;
|
|
58
48
|
/**
|
|
59
|
-
* Encodes a specific `toolChoice`. The adapter adds
|
|
60
|
-
* is an object containing only
|
|
49
|
+
* Encodes a specific `toolChoice`. The adapter adds the registered tool type.
|
|
50
|
+
* The default is an object containing only that type.
|
|
61
51
|
*/
|
|
62
52
|
encodeToolChoice?(options: {
|
|
63
53
|
name: string;
|
|
64
54
|
args: Record<string, unknown>;
|
|
65
55
|
}): MaybePromiseLike<JSONObject | undefined>;
|
|
56
|
+
}
|
|
57
|
+
type OpenResponsesExtensionItemCodec<Type extends string> = {
|
|
66
58
|
/**
|
|
67
|
-
*
|
|
59
|
+
* Namespaced item types decoded by this extension. Must be provided together
|
|
60
|
+
* with `decodeItem`.
|
|
61
|
+
*/
|
|
62
|
+
itemTypes?: readonly OpenResponsesNamespacedType[];
|
|
63
|
+
/**
|
|
64
|
+
* Decodes a completed registered item into AI SDK content parts. The adapter
|
|
68
65
|
* adds a custom replay part containing the original item and reference
|
|
69
66
|
* metadata to the returned parts.
|
|
70
67
|
*/
|
|
71
68
|
decodeItem?(options: {
|
|
72
|
-
item: OpenResponsesExtensionItem
|
|
69
|
+
item: OpenResponsesExtensionItem<Type>;
|
|
73
70
|
mode: 'generate' | 'stream';
|
|
74
71
|
}): MaybePromiseLike<OpenResponsesExtensionContentPart[] | undefined>;
|
|
75
72
|
/**
|
|
76
73
|
* Encodes an AI SDK history part when no original wire item is available.
|
|
77
|
-
* Every returned item must use one of
|
|
74
|
+
* Every returned item must use one of the registered item types.
|
|
78
75
|
*/
|
|
79
76
|
encodeInputItem?(options: {
|
|
80
77
|
part: OpenResponsesExtensionInputPart;
|
|
81
78
|
tool: LanguageModelV4ProviderTool;
|
|
82
|
-
}): MaybePromiseLike<OpenResponsesExtensionItem | OpenResponsesExtensionItem[] | undefined>;
|
|
79
|
+
}): MaybePromiseLike<OpenResponsesExtensionItem<Type> | OpenResponsesExtensionItem<Type>[] | undefined>;
|
|
80
|
+
};
|
|
81
|
+
type OpenResponsesExtensionEventCodec<Type extends string> = {
|
|
82
|
+
/**
|
|
83
|
+
* Namespaced streaming event types decoded by this extension. Must be
|
|
84
|
+
* provided together with `decodeEvent`.
|
|
85
|
+
*/
|
|
86
|
+
eventTypes?: readonly OpenResponsesNamespacedType[];
|
|
83
87
|
/**
|
|
84
|
-
* Decodes a
|
|
88
|
+
* Decodes a registered streaming event.
|
|
85
89
|
*
|
|
86
90
|
* `state` persists for the lifetime of one response stream.
|
|
87
91
|
*/
|
|
88
92
|
decodeEvent?(options: {
|
|
89
|
-
event: OpenResponsesExtensionEvent
|
|
93
|
+
event: OpenResponsesExtensionEvent<Type>;
|
|
90
94
|
state: Map<string, unknown>;
|
|
91
95
|
}): MaybePromiseLike<OpenResponsesExtensionStreamPart[] | undefined>;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Defines a portable Open Responses extension using namespaced wire types.
|
|
99
|
+
*
|
|
100
|
+
* This remains an interface so existing consumers can extend it from their own
|
|
101
|
+
* interfaces and implement it in classes.
|
|
102
|
+
*/
|
|
103
|
+
interface OpenResponsesExtension extends OpenResponsesExtensionBase, OpenResponsesExtensionItemCodec<OpenResponsesNamespacedType>, OpenResponsesExtensionEventCodec<OpenResponsesNamespacedType> {
|
|
104
|
+
allowBareTypes?: false;
|
|
105
|
+
bareToolType?: undefined;
|
|
106
|
+
bareItemTypes?: undefined;
|
|
107
|
+
bareEventTypes?: undefined;
|
|
92
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Defines a non-portable Open Responses extension that explicitly registers
|
|
111
|
+
* exact bare wire types.
|
|
112
|
+
*/
|
|
113
|
+
type OpenResponsesBareExtension = OpenResponsesExtensionBase & OpenResponsesExtensionItemCodec<string> & OpenResponsesExtensionEventCodec<string> & {
|
|
114
|
+
/**
|
|
115
|
+
* Explicitly enables non-portable bare discriminator registration for this
|
|
116
|
+
* extension.
|
|
117
|
+
*/
|
|
118
|
+
allowBareTypes: true;
|
|
119
|
+
/**
|
|
120
|
+
* Exact non-namespaced tool type used by a documented implementation
|
|
121
|
+
* extension. Must be provided together with `encodeTool` and cannot be used
|
|
122
|
+
* together with `toolType`.
|
|
123
|
+
*/
|
|
124
|
+
bareToolType?: string;
|
|
125
|
+
/**
|
|
126
|
+
* Exact non-namespaced item types decoded by a documented implementation
|
|
127
|
+
* extension. Must be provided together with `decodeItem`.
|
|
128
|
+
*/
|
|
129
|
+
bareItemTypes?: readonly string[];
|
|
130
|
+
/**
|
|
131
|
+
* Exact non-namespaced streaming event types decoded by this extension.
|
|
132
|
+
* Must be provided together with `decodeEvent`.
|
|
133
|
+
*/
|
|
134
|
+
bareEventTypes?: readonly string[];
|
|
135
|
+
} & ({
|
|
136
|
+
bareToolType: string;
|
|
137
|
+
} | {
|
|
138
|
+
bareItemTypes: readonly string[];
|
|
139
|
+
} | {
|
|
140
|
+
bareEventTypes: readonly string[];
|
|
141
|
+
});
|
|
142
|
+
type OpenResponsesExtensionRegistration = OpenResponsesExtension | OpenResponsesBareExtension;
|
|
93
143
|
type OpenResponsesExtensionRegistry = {
|
|
94
|
-
byEventType: Map<
|
|
95
|
-
byExtensionId: Map<LanguageModelV4ProviderTool['id'],
|
|
96
|
-
byItemType: Map<
|
|
144
|
+
byEventType: Map<string, OpenResponsesEventExtension>;
|
|
145
|
+
byExtensionId: Map<LanguageModelV4ProviderTool['id'], OpenResponsesExtensionRegistration>;
|
|
146
|
+
byItemType: Map<string, OpenResponsesItemExtension>;
|
|
97
147
|
byProviderToolId: Map<LanguageModelV4ProviderTool['id'], OpenResponsesToolExtension>;
|
|
98
|
-
byToolType: Map<
|
|
148
|
+
byToolType: Map<string, OpenResponsesToolExtension>;
|
|
99
149
|
};
|
|
100
|
-
type OpenResponsesToolExtension =
|
|
101
|
-
|
|
102
|
-
|
|
150
|
+
type OpenResponsesToolExtension = OpenResponsesExtensionRegistration & {
|
|
151
|
+
encodeTool: NonNullable<OpenResponsesExtensionRegistration['encodeTool']>;
|
|
152
|
+
encodeInputItem?: (options: {
|
|
153
|
+
part: OpenResponsesExtensionInputPart;
|
|
154
|
+
tool: LanguageModelV4ProviderTool;
|
|
155
|
+
}) => MaybePromiseLike<OpenResponsesExtensionItem<string> | OpenResponsesExtensionItem<string>[] | undefined>;
|
|
103
156
|
};
|
|
104
|
-
type OpenResponsesItemExtension =
|
|
105
|
-
|
|
106
|
-
|
|
157
|
+
type OpenResponsesItemExtension = OpenResponsesExtensionRegistration & {
|
|
158
|
+
decodeItem(options: {
|
|
159
|
+
item: OpenResponsesExtensionItem<string>;
|
|
160
|
+
mode: 'generate' | 'stream';
|
|
161
|
+
}): MaybePromiseLike<OpenResponsesExtensionContentPart[] | undefined>;
|
|
107
162
|
};
|
|
108
|
-
type OpenResponsesEventExtension =
|
|
109
|
-
|
|
110
|
-
|
|
163
|
+
type OpenResponsesEventExtension = OpenResponsesExtensionRegistration & {
|
|
164
|
+
decodeEvent(options: {
|
|
165
|
+
event: OpenResponsesExtensionEvent<string>;
|
|
166
|
+
state: Map<string, unknown>;
|
|
167
|
+
}): MaybePromiseLike<OpenResponsesExtensionStreamPart[] | undefined>;
|
|
111
168
|
};
|
|
112
169
|
|
|
113
170
|
type OpenResponsesCustomToolOptions = {
|
|
@@ -230,7 +287,7 @@ interface OpenResponsesProviderSettings {
|
|
|
230
287
|
*
|
|
231
288
|
* @experimental This API may change in a future release.
|
|
232
289
|
*/
|
|
233
|
-
experimental_extensions?: readonly
|
|
290
|
+
experimental_extensions?: readonly OpenResponsesExtensionRegistration[];
|
|
234
291
|
}
|
|
235
292
|
declare function createOpenResponses(options: OpenResponsesProviderSettings): OpenResponsesProvider;
|
|
236
293
|
|
|
@@ -240,4 +297,4 @@ declare const openResponsesLanguageModelOptions: _ai_sdk_provider_utils.LazySche
|
|
|
240
297
|
}>;
|
|
241
298
|
type OpenResponsesLanguageModelOptions = InferSchema<typeof openResponsesLanguageModelOptions>;
|
|
242
299
|
|
|
243
|
-
export { type OpenResponsesExtension as Experimental_OpenResponsesExtension, type OpenResponsesExtensionContentPart as Experimental_OpenResponsesExtensionContentPart, type OpenResponsesExtensionEvent as Experimental_OpenResponsesExtensionEvent, type OpenResponsesExtensionInputPart as Experimental_OpenResponsesExtensionInputPart, type OpenResponsesExtensionItem as Experimental_OpenResponsesExtensionItem, type OpenResponsesExtensionRecord as Experimental_OpenResponsesExtensionRecord, type OpenResponsesExtensionStreamPart as Experimental_OpenResponsesExtensionStreamPart, type OpenResponsesNamespacedType as Experimental_OpenResponsesNamespacedType, type OpenResponsesCustomToolOptions, type OpenResponsesLanguageModelOptions, type OpenResponsesLanguageModelOptions as OpenResponsesOptions, type OpenResponsesProvider, type OpenResponsesProviderSettings, VERSION, createOpenResponses };
|
|
300
|
+
export { type OpenResponsesBareExtension as Experimental_OpenResponsesBareExtension, type OpenResponsesExtension as Experimental_OpenResponsesExtension, type OpenResponsesExtensionContentPart as Experimental_OpenResponsesExtensionContentPart, type OpenResponsesExtensionEvent as Experimental_OpenResponsesExtensionEvent, type OpenResponsesExtensionInputPart as Experimental_OpenResponsesExtensionInputPart, type OpenResponsesExtensionItem as Experimental_OpenResponsesExtensionItem, type OpenResponsesExtensionRecord as Experimental_OpenResponsesExtensionRecord, type OpenResponsesExtensionStreamPart as Experimental_OpenResponsesExtensionStreamPart, type OpenResponsesNamespacedType as Experimental_OpenResponsesNamespacedType, type OpenResponsesCustomToolOptions, type OpenResponsesLanguageModelOptions, type OpenResponsesLanguageModelOptions as OpenResponsesOptions, type OpenResponsesProvider, type OpenResponsesProviderSettings, VERSION, createOpenResponses };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/version.ts
|
|
2
|
-
var VERSION = true ? "2.0.
|
|
2
|
+
var VERSION = true ? "2.0.55" : "0.0.0-test";
|
|
3
3
|
|
|
4
4
|
// src/open-responses-provider.ts
|
|
5
5
|
import {
|
|
@@ -11,6 +11,37 @@ import {
|
|
|
11
11
|
} from "@ai-sdk/provider-utils";
|
|
12
12
|
|
|
13
13
|
// src/open-responses-extension.ts
|
|
14
|
+
var coreToolTypes = /* @__PURE__ */ new Set(["allowed_tools", "function"]);
|
|
15
|
+
var coreItemTypes = /* @__PURE__ */ new Set([
|
|
16
|
+
"function_call",
|
|
17
|
+
"function_call_output",
|
|
18
|
+
"item_reference",
|
|
19
|
+
"message",
|
|
20
|
+
"reasoning"
|
|
21
|
+
]);
|
|
22
|
+
var coreEventTypes = /* @__PURE__ */ new Set([
|
|
23
|
+
"error",
|
|
24
|
+
"response.completed",
|
|
25
|
+
"response.content_part.added",
|
|
26
|
+
"response.content_part.done",
|
|
27
|
+
"response.created",
|
|
28
|
+
"response.failed",
|
|
29
|
+
"response.function_call_arguments.delta",
|
|
30
|
+
"response.function_call_arguments.done",
|
|
31
|
+
"response.in_progress",
|
|
32
|
+
"response.incomplete",
|
|
33
|
+
"response.output_item.added",
|
|
34
|
+
"response.output_item.done",
|
|
35
|
+
"response.output_text.delta",
|
|
36
|
+
"response.output_text.done",
|
|
37
|
+
"response.reasoning_summary_part.added",
|
|
38
|
+
"response.reasoning_summary_part.done",
|
|
39
|
+
"response.reasoning_summary_text.delta",
|
|
40
|
+
"response.reasoning_summary_text.done",
|
|
41
|
+
"response.reasoning_text.delta",
|
|
42
|
+
"response.refusal.delta",
|
|
43
|
+
"response.refusal.done"
|
|
44
|
+
]);
|
|
14
45
|
function createOpenResponsesExtensionRegistry(extensions) {
|
|
15
46
|
const registry = {
|
|
16
47
|
byEventType: /* @__PURE__ */ new Map(),
|
|
@@ -33,26 +64,48 @@ function createOpenResponsesExtensionRegistry(extensions) {
|
|
|
33
64
|
extension,
|
|
34
65
|
field: "id"
|
|
35
66
|
});
|
|
36
|
-
const
|
|
67
|
+
const hasBareTypes = extension.bareToolType != null || extension.bareItemTypes != null || extension.bareEventTypes != null;
|
|
68
|
+
if (hasBareTypes !== (extension.allowBareTypes === true)) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
`Open Responses extension ${extension.id} must set allowBareTypes to true exactly when registering bare types.`
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
if (extension.toolType != null && extension.bareToolType != null) {
|
|
74
|
+
throw new Error(
|
|
75
|
+
`Open Responses extension ${extension.id} cannot provide toolType and bareToolType together.`
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
const toolType = extension.toolType ?? extension.bareToolType;
|
|
79
|
+
const hasToolType = toolType != null;
|
|
37
80
|
const hasToolEncoder = extension.encodeTool != null;
|
|
38
81
|
if (hasToolType !== hasToolEncoder) {
|
|
82
|
+
const typeField = extension.bareToolType != null ? "bareToolType" : "toolType";
|
|
39
83
|
throw new Error(
|
|
40
|
-
`Open Responses extension ${extension.id} must provide
|
|
84
|
+
`Open Responses extension ${extension.id} must provide ${typeField} and encodeTool together.`
|
|
41
85
|
);
|
|
42
86
|
}
|
|
43
87
|
if (extension.encodeToolChoice != null && !hasToolEncoder) {
|
|
44
88
|
throw new Error(
|
|
45
|
-
`Open Responses extension ${extension.id} cannot provide encodeToolChoice without
|
|
89
|
+
`Open Responses extension ${extension.id} cannot provide encodeToolChoice without a tool type and encodeTool.`
|
|
46
90
|
);
|
|
47
91
|
}
|
|
48
92
|
if (hasToolType && hasToolEncoder) {
|
|
49
93
|
const toolExtension = extension;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
94
|
+
if (extension.toolType != null) {
|
|
95
|
+
assertNamespacedType({
|
|
96
|
+
extensionId: extension.id,
|
|
97
|
+
namespace,
|
|
98
|
+
type: extension.toolType,
|
|
99
|
+
field: "toolType"
|
|
100
|
+
});
|
|
101
|
+
} else {
|
|
102
|
+
assertBareType({
|
|
103
|
+
coreTypes: coreToolTypes,
|
|
104
|
+
extensionId: extension.id,
|
|
105
|
+
type: extension.bareToolType,
|
|
106
|
+
field: "bareToolType"
|
|
107
|
+
});
|
|
108
|
+
}
|
|
56
109
|
registerUnique({
|
|
57
110
|
map: registry.byProviderToolId,
|
|
58
111
|
key: extension.id,
|
|
@@ -61,31 +114,35 @@ function createOpenResponsesExtensionRegistry(extensions) {
|
|
|
61
114
|
});
|
|
62
115
|
registerUnique({
|
|
63
116
|
map: registry.byToolType,
|
|
64
|
-
key:
|
|
117
|
+
key: toolType,
|
|
65
118
|
extension: toolExtension,
|
|
66
|
-
field: "
|
|
119
|
+
field: "tool type"
|
|
67
120
|
});
|
|
68
121
|
}
|
|
69
|
-
const
|
|
122
|
+
const itemTypes = [
|
|
123
|
+
...extension.itemTypes ?? [],
|
|
124
|
+
...extension.bareItemTypes ?? []
|
|
125
|
+
];
|
|
126
|
+
const hasItemTypes = extension.itemTypes != null || extension.bareItemTypes != null;
|
|
70
127
|
const hasItemDecoder = extension.decodeItem != null;
|
|
71
128
|
if (hasItemTypes !== hasItemDecoder) {
|
|
72
129
|
throw new Error(
|
|
73
|
-
`Open Responses extension ${extension.id} must provide itemTypes
|
|
130
|
+
`Open Responses extension ${extension.id} must provide itemTypes or bareItemTypes together with decodeItem.`
|
|
74
131
|
);
|
|
75
132
|
}
|
|
76
133
|
if (extension.encodeInputItem != null && !hasItemDecoder) {
|
|
77
134
|
throw new Error(
|
|
78
|
-
`Open Responses extension ${extension.id} cannot provide encodeInputItem without itemTypes and decodeItem.`
|
|
135
|
+
`Open Responses extension ${extension.id} cannot provide encodeInputItem without itemTypes or bareItemTypes and decodeItem.`
|
|
79
136
|
);
|
|
80
137
|
}
|
|
81
138
|
if (hasItemTypes && hasItemDecoder) {
|
|
82
139
|
const itemExtension = extension;
|
|
83
|
-
if (
|
|
140
|
+
if (itemTypes.length === 0) {
|
|
84
141
|
throw new Error(
|
|
85
142
|
`Open Responses extension ${extension.id} must register at least one item type.`
|
|
86
143
|
);
|
|
87
144
|
}
|
|
88
|
-
for (const itemType of
|
|
145
|
+
for (const itemType of extension.itemTypes ?? []) {
|
|
89
146
|
assertNamespacedType({
|
|
90
147
|
extensionId: extension.id,
|
|
91
148
|
namespace,
|
|
@@ -99,22 +156,40 @@ function createOpenResponsesExtensionRegistry(extensions) {
|
|
|
99
156
|
field: "item type"
|
|
100
157
|
});
|
|
101
158
|
}
|
|
159
|
+
for (const itemType of extension.bareItemTypes ?? []) {
|
|
160
|
+
assertBareType({
|
|
161
|
+
coreTypes: coreItemTypes,
|
|
162
|
+
extensionId: extension.id,
|
|
163
|
+
type: itemType,
|
|
164
|
+
field: "bareItemTypes"
|
|
165
|
+
});
|
|
166
|
+
registerUnique({
|
|
167
|
+
map: registry.byItemType,
|
|
168
|
+
key: itemType,
|
|
169
|
+
extension: itemExtension,
|
|
170
|
+
field: "item type"
|
|
171
|
+
});
|
|
172
|
+
}
|
|
102
173
|
}
|
|
103
|
-
const
|
|
174
|
+
const eventTypes = [
|
|
175
|
+
...extension.eventTypes ?? [],
|
|
176
|
+
...extension.bareEventTypes ?? []
|
|
177
|
+
];
|
|
178
|
+
const hasEventTypes = extension.eventTypes != null || extension.bareEventTypes != null;
|
|
104
179
|
const hasEventDecoder = extension.decodeEvent != null;
|
|
105
180
|
if (hasEventTypes !== hasEventDecoder) {
|
|
106
181
|
throw new Error(
|
|
107
|
-
`Open Responses extension ${extension.id} must provide eventTypes
|
|
182
|
+
`Open Responses extension ${extension.id} must provide eventTypes or bareEventTypes together with decodeEvent.`
|
|
108
183
|
);
|
|
109
184
|
}
|
|
110
185
|
if (hasEventTypes && hasEventDecoder) {
|
|
111
186
|
const eventExtension = extension;
|
|
112
|
-
if (
|
|
187
|
+
if (eventTypes.length === 0) {
|
|
113
188
|
throw new Error(
|
|
114
189
|
`Open Responses extension ${extension.id} must register at least one event type.`
|
|
115
190
|
);
|
|
116
191
|
}
|
|
117
|
-
for (const eventType of
|
|
192
|
+
for (const eventType of extension.eventTypes ?? []) {
|
|
118
193
|
assertNamespacedType({
|
|
119
194
|
extensionId: extension.id,
|
|
120
195
|
namespace,
|
|
@@ -128,6 +203,20 @@ function createOpenResponsesExtensionRegistry(extensions) {
|
|
|
128
203
|
field: "event type"
|
|
129
204
|
});
|
|
130
205
|
}
|
|
206
|
+
for (const eventType of extension.bareEventTypes ?? []) {
|
|
207
|
+
assertBareType({
|
|
208
|
+
coreTypes: coreEventTypes,
|
|
209
|
+
extensionId: extension.id,
|
|
210
|
+
type: eventType,
|
|
211
|
+
field: "bareEventTypes"
|
|
212
|
+
});
|
|
213
|
+
registerUnique({
|
|
214
|
+
map: registry.byEventType,
|
|
215
|
+
key: eventType,
|
|
216
|
+
extension: eventExtension,
|
|
217
|
+
field: "event type"
|
|
218
|
+
});
|
|
219
|
+
}
|
|
131
220
|
}
|
|
132
221
|
if (!hasToolEncoder && !hasItemDecoder && !hasEventDecoder) {
|
|
133
222
|
throw new Error(
|
|
@@ -143,12 +232,39 @@ function assertNamespacedType({
|
|
|
143
232
|
type,
|
|
144
233
|
field
|
|
145
234
|
}) {
|
|
146
|
-
|
|
235
|
+
const separatorIndex = type.indexOf(":");
|
|
236
|
+
if (separatorIndex <= 0 || type.slice(0, separatorIndex) !== namespace) {
|
|
147
237
|
throw new Error(
|
|
148
238
|
`Open Responses extension ${extensionId} has invalid ${field} value ${type}. Extension wire types must use the ${namespace}: namespace.`
|
|
149
239
|
);
|
|
150
240
|
}
|
|
151
241
|
}
|
|
242
|
+
function assertBareType({
|
|
243
|
+
coreTypes,
|
|
244
|
+
extensionId,
|
|
245
|
+
type,
|
|
246
|
+
field
|
|
247
|
+
}) {
|
|
248
|
+
if (type.length === 0 || type.includes(":")) {
|
|
249
|
+
throw new Error(
|
|
250
|
+
`Open Responses extension ${extensionId} has invalid ${field} value ${type}. Bare extension wire types must be non-empty and must not contain a colon.`
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
if (coreTypes.has(type)) {
|
|
254
|
+
throw new Error(
|
|
255
|
+
`Open Responses extension ${extensionId} cannot register core ${field} value ${type}.`
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
function getOpenResponsesExtensionItemTypes(extension) {
|
|
260
|
+
return [...extension.itemTypes ?? [], ...extension.bareItemTypes ?? []];
|
|
261
|
+
}
|
|
262
|
+
function getOpenResponsesExtensionToolType(extension) {
|
|
263
|
+
return extension.toolType ?? extension.bareToolType;
|
|
264
|
+
}
|
|
265
|
+
function asOpenResponsesExtensionRecord(value) {
|
|
266
|
+
return value;
|
|
267
|
+
}
|
|
152
268
|
function registerUnique({
|
|
153
269
|
map,
|
|
154
270
|
key,
|
|
@@ -163,11 +279,8 @@ function registerUnique({
|
|
|
163
279
|
}
|
|
164
280
|
map.set(key, extension);
|
|
165
281
|
}
|
|
166
|
-
function isOpenResponsesNamespacedType(value) {
|
|
167
|
-
return typeof value === "string" && value.includes(":");
|
|
168
|
-
}
|
|
169
282
|
function isOpenResponsesExtensionRecord(value) {
|
|
170
|
-
return isOpenResponsesJSONObject(value) &&
|
|
283
|
+
return isOpenResponsesJSONObject(value) && typeof value.type === "string";
|
|
171
284
|
}
|
|
172
285
|
function isOpenResponsesJSONObject(value) {
|
|
173
286
|
return value != null && typeof value === "object" && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype && Object.values(value).every(isOpenResponsesJSONValue);
|
|
@@ -367,7 +480,7 @@ async function convertToOpenResponsesInput({
|
|
|
367
480
|
if (replayItem != null) {
|
|
368
481
|
const replayKey = `${replayItem.type}:${replayItem.id}`;
|
|
369
482
|
if (!replayedExtensionItems.has(replayKey)) {
|
|
370
|
-
input.push(replayItem);
|
|
483
|
+
input.push(asOpenResponsesExtensionRecord(replayItem));
|
|
371
484
|
replayedExtensionItems.add(replayKey);
|
|
372
485
|
}
|
|
373
486
|
}
|
|
@@ -389,7 +502,7 @@ async function convertToOpenResponsesInput({
|
|
|
389
502
|
feature: `provider-defined tool ${providerTool.id} ${part.type} history`
|
|
390
503
|
});
|
|
391
504
|
} else {
|
|
392
|
-
input.push(...encoded);
|
|
505
|
+
input.push(...encoded.map(asOpenResponsesExtensionRecord));
|
|
393
506
|
}
|
|
394
507
|
continue;
|
|
395
508
|
}
|
|
@@ -496,7 +609,7 @@ async function convertToOpenResponsesInput({
|
|
|
496
609
|
if (replayItem != null) {
|
|
497
610
|
const replayKey = `${replayItem.type}:${replayItem.id}`;
|
|
498
611
|
if (!replayedExtensionItems.has(replayKey)) {
|
|
499
|
-
input.push(replayItem);
|
|
612
|
+
input.push(asOpenResponsesExtensionRecord(replayItem));
|
|
500
613
|
replayedExtensionItems.add(replayKey);
|
|
501
614
|
}
|
|
502
615
|
}
|
|
@@ -516,7 +629,7 @@ async function convertToOpenResponsesInput({
|
|
|
516
629
|
feature: `provider-defined tool ${providerTool.id} tool-result history`
|
|
517
630
|
});
|
|
518
631
|
} else {
|
|
519
|
-
input.push(...encoded);
|
|
632
|
+
input.push(...encoded.map(asOpenResponsesExtensionRecord));
|
|
520
633
|
}
|
|
521
634
|
continue;
|
|
522
635
|
}
|
|
@@ -622,8 +735,8 @@ async function encodeExtensionInputPart({
|
|
|
622
735
|
}) {
|
|
623
736
|
const extension = extensionRegistry?.byProviderToolId.get(providerTool.id);
|
|
624
737
|
const encodeInputItem = extension?.encodeInputItem;
|
|
625
|
-
const itemTypes = extension
|
|
626
|
-
if (encodeInputItem == null || itemTypes
|
|
738
|
+
const itemTypes = extension == null ? [] : getOpenResponsesExtensionItemTypes(extension);
|
|
739
|
+
if (encodeInputItem == null || itemTypes.length === 0) {
|
|
627
740
|
return void 0;
|
|
628
741
|
}
|
|
629
742
|
try {
|
|
@@ -664,7 +777,7 @@ function getExtensionReplay({
|
|
|
664
777
|
if (extension == null) {
|
|
665
778
|
return void 0;
|
|
666
779
|
}
|
|
667
|
-
if (isOpenResponsesExtensionItem(item) && extension.
|
|
780
|
+
if (isOpenResponsesExtensionItem(item) && getOpenResponsesExtensionItemTypes(extension).includes(item.type)) {
|
|
668
781
|
return { item };
|
|
669
782
|
}
|
|
670
783
|
return typeof itemId === "string" ? {} : void 0;
|
|
@@ -866,6 +979,7 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
|
|
|
866
979
|
const extension = this.extensionRegistry.byProviderToolId.get(tool.id);
|
|
867
980
|
let encoded;
|
|
868
981
|
if (extension != null) {
|
|
982
|
+
const toolType = getOpenResponsesExtensionToolType(extension);
|
|
869
983
|
try {
|
|
870
984
|
const fields = await extension.encodeTool({
|
|
871
985
|
name: tool.name,
|
|
@@ -874,7 +988,7 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
|
|
|
874
988
|
if (isOpenResponsesJSONObject(fields)) {
|
|
875
989
|
encoded = {
|
|
876
990
|
...fields,
|
|
877
|
-
type:
|
|
991
|
+
type: toolType
|
|
878
992
|
};
|
|
879
993
|
}
|
|
880
994
|
} catch {
|
|
@@ -886,9 +1000,9 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
|
|
|
886
1000
|
feature: `provider-defined tool ${tool.id}`
|
|
887
1001
|
});
|
|
888
1002
|
} else if (extension != null) {
|
|
889
|
-
convertedTools.push(encoded);
|
|
1003
|
+
convertedTools.push(asOpenResponsesExtensionRecord(encoded));
|
|
890
1004
|
encodedProviderToolsByName.set(tool.name, {
|
|
891
|
-
toolType: extension
|
|
1005
|
+
toolType: getOpenResponsesExtensionToolType(extension),
|
|
892
1006
|
encodeToolChoice: extension.encodeToolChoice,
|
|
893
1007
|
tool
|
|
894
1008
|
});
|
|
@@ -937,10 +1051,10 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
|
|
|
937
1051
|
feature: `tool choice for provider-defined tool ${tool.id}`
|
|
938
1052
|
});
|
|
939
1053
|
} else {
|
|
940
|
-
convertedToolChoice = {
|
|
1054
|
+
convertedToolChoice = asOpenResponsesExtensionRecord({
|
|
941
1055
|
...isOpenResponsesJSONObject(fields) ? fields : {},
|
|
942
1056
|
type: toolType
|
|
943
|
-
};
|
|
1057
|
+
});
|
|
944
1058
|
}
|
|
945
1059
|
}
|
|
946
1060
|
} else {
|
|
@@ -1269,8 +1383,8 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
|
|
|
1269
1383
|
} catch (error) {
|
|
1270
1384
|
controller.enqueue({ type: "error", error });
|
|
1271
1385
|
}
|
|
1386
|
+
return;
|
|
1272
1387
|
}
|
|
1273
|
-
return;
|
|
1274
1388
|
}
|
|
1275
1389
|
if (chunk.type === "response.output_item.added" && chunk.item.type === "function_call") {
|
|
1276
1390
|
toolCallsByItemId.set(chunk.item.id, {
|
|
@@ -1366,7 +1480,7 @@ var OpenResponsesLanguageModel = class _OpenResponsesLanguageModel {
|
|
|
1366
1480
|
});
|
|
1367
1481
|
hasToolCalls = true;
|
|
1368
1482
|
customToolCallsByItemId.delete(chunk.item.id);
|
|
1369
|
-
} else if (chunk.type === "response.output_item.done" && isOpenResponsesExtensionItem(chunk.item)) {
|
|
1483
|
+
} else if (chunk.type === "response.output_item.done" && isOpenResponsesExtensionItem(chunk.item) && extensionRegistry.byItemType.has(chunk.item.type)) {
|
|
1370
1484
|
try {
|
|
1371
1485
|
const decoded = await decodeExtensionItem({
|
|
1372
1486
|
extensionRegistry,
|