@effect-uai/responses 0.11.0 → 0.12.1
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/OpenAIDeepResearch.d.mts +6 -5
- package/dist/OpenAIDeepResearch.d.mts.map +1 -1
- package/dist/OpenAIDeepResearch.mjs +8 -4
- package/dist/OpenAIDeepResearch.mjs.map +1 -1
- package/dist/OpenAIEmbedding.d.mts +2 -3
- package/dist/OpenAIEmbedding.d.mts.map +1 -1
- package/dist/OpenAIEmbedding.mjs +1 -1
- package/dist/OpenAIEmbedding.mjs.map +1 -1
- package/dist/Responses.d.mts +20 -2
- package/dist/Responses.d.mts.map +1 -1
- package/dist/Responses.mjs +9 -6
- package/dist/Responses.mjs.map +1 -1
- package/dist/ResponsesTools.d.mts +0 -2
- package/dist/ResponsesTools.d.mts.map +1 -1
- package/dist/ResponsesTools.mjs +1 -1
- package/dist/ResponsesTools.mjs.map +1 -1
- package/dist/codec.d.mts +0 -2
- package/dist/codec.d.mts.map +1 -1
- package/dist/codec.mjs +31 -9
- package/dist/codec.mjs.map +1 -1
- package/dist/codec.test.d.mts +1 -0
- package/dist/codec.test.mjs +94 -0
- package/dist/codec.test.mjs.map +1 -0
- package/dist/{magic-string.es-CaWgF-3p.mjs → magic-string.es-CUAnjKYC.mjs} +14 -13
- package/dist/{magic-string.es-CaWgF-3p.mjs.map → magic-string.es-CUAnjKYC.mjs.map} +1 -1
- package/dist/models.d.mts.map +1 -1
- package/dist/region.d.mts.map +1 -1
- package/dist/region.mjs.map +1 -1
- package/dist/region.test.d.mts +1 -1
- package/dist/region.test.mjs +1 -1
- package/dist/region.test.mjs.map +1 -1
- package/dist/responsesTools.test.d.mts +1 -1
- package/dist/responsesTools.test.mjs +7 -5
- package/dist/responsesTools.test.mjs.map +1 -1
- package/dist/streamEvents.d.mts +0 -2
- package/dist/streamEvents.d.mts.map +1 -1
- package/dist/streamEvents.mjs +1 -1
- package/dist/streamEvents.mjs.map +1 -1
- package/dist/{test.DNmyFkvJ-CPKukVWS.mjs → test.DNmyFkvJ-N3QqMRwZ.mjs} +247 -222
- package/dist/test.DNmyFkvJ-N3QqMRwZ.mjs.map +1 -0
- package/package.json +9 -5
- package/src/OpenAIDeepResearch.ts +9 -14
- package/src/OpenAIEmbedding.ts +24 -29
- package/src/Responses.ts +28 -8
- package/src/ResponsesTools.ts +4 -6
- package/src/codec.test.ts +87 -0
- package/src/codec.ts +33 -13
- package/dist/test.DNmyFkvJ-CPKukVWS.mjs.map +0 -1
- /package/dist/{chunk-CfYAbeIz.mjs → rolldown-runtime-D7D4PA-g.mjs} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect-uai/responses",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"description": "OpenAI Responses API provider for @effect-uai/core.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -38,6 +38,10 @@
|
|
|
38
38
|
"types": "./dist/Responses.d.mts",
|
|
39
39
|
"import": "./dist/Responses.mjs"
|
|
40
40
|
},
|
|
41
|
+
"./ResponsesTools": {
|
|
42
|
+
"types": "./dist/ResponsesTools.d.mts",
|
|
43
|
+
"import": "./dist/ResponsesTools.mjs"
|
|
44
|
+
},
|
|
41
45
|
"./OpenAIDeepResearch": {
|
|
42
46
|
"types": "./dist/OpenAIDeepResearch.d.mts",
|
|
43
47
|
"import": "./dist/OpenAIDeepResearch.mjs"
|
|
@@ -51,13 +55,13 @@
|
|
|
51
55
|
"access": "public"
|
|
52
56
|
},
|
|
53
57
|
"devDependencies": {
|
|
54
|
-
"effect": "4.0.0-
|
|
55
|
-
"typescript": "^
|
|
56
|
-
"@effect-uai/core": "0.
|
|
58
|
+
"effect": "4.0.0-rc.111",
|
|
59
|
+
"typescript": "^7.0.2",
|
|
60
|
+
"@effect-uai/core": "0.12.1"
|
|
57
61
|
},
|
|
58
62
|
"peerDependencies": {
|
|
59
63
|
"@effect-uai/core": ">=0.2.0 <1",
|
|
60
|
-
"effect": ">=4.0.0-
|
|
64
|
+
"effect": ">=4.0.0-rc.111 <5.0.0"
|
|
61
65
|
},
|
|
62
66
|
"scripts": {
|
|
63
67
|
"build": "tsdown",
|
|
@@ -87,20 +87,15 @@ export const jobStateOf = (wire: WireResponseCompleted): ResearchState =>
|
|
|
87
87
|
Match.value(wire.status ?? "").pipe(
|
|
88
88
|
Match.when("queued", (): ResearchState => ({ _tag: "Pending" })),
|
|
89
89
|
Match.when("in_progress", (): ResearchState => ({ _tag: "Running" })),
|
|
90
|
-
Match.whenOr(
|
|
91
|
-
"
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
_tag: "Failed",
|
|
100
|
-
...(wire.error?.message != null && { reason: wire.error.message }),
|
|
101
|
-
raw: wire,
|
|
102
|
-
}),
|
|
103
|
-
),
|
|
90
|
+
Match.whenOr("completed", "incomplete", (): ResearchState => ({
|
|
91
|
+
_tag: "Succeeded",
|
|
92
|
+
result: turnFromCompleted(wire),
|
|
93
|
+
})),
|
|
94
|
+
Match.whenOr("failed", "cancelled", (): ResearchState => ({
|
|
95
|
+
_tag: "Failed",
|
|
96
|
+
...(wire.error?.message != null && { reason: wire.error.message }),
|
|
97
|
+
raw: wire,
|
|
98
|
+
})),
|
|
104
99
|
Match.orElse((): ResearchState => ({ _tag: "Running" })),
|
|
105
100
|
)
|
|
106
101
|
|
package/src/OpenAIEmbedding.ts
CHANGED
|
@@ -241,12 +241,10 @@ const embedManyImpl =
|
|
|
241
241
|
): Effect.Effect<EmbedManyResponse, AiError.AiError, HttpClient.HttpClient> =>
|
|
242
242
|
buildBatchBody(request).pipe(
|
|
243
243
|
Effect.flatMap((body) => postEmbed(cfg, body)),
|
|
244
|
-
Effect.map(
|
|
245
|
-
(decoded)
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
}),
|
|
249
|
-
),
|
|
244
|
+
Effect.map((decoded): EmbedManyResponse => ({
|
|
245
|
+
embeddings: orderedEmbeddings(decoded.data),
|
|
246
|
+
usage: usageOf(decoded.usage),
|
|
247
|
+
})),
|
|
250
248
|
)
|
|
251
249
|
|
|
252
250
|
// ---------------------------------------------------------------------------
|
|
@@ -279,29 +277,26 @@ export const layer = (
|
|
|
279
277
|
const typed = Layer.effect(OpenAIEmbedding, make(cfg))
|
|
280
278
|
const generic = Layer.effect(
|
|
281
279
|
EmbeddingModel,
|
|
282
|
-
Effect.map(
|
|
283
|
-
|
|
284
|
-
(
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
) as Effect.Effect<EmbedManyResponse<E>, AiError.AiError>,
|
|
303
|
-
}),
|
|
304
|
-
),
|
|
280
|
+
Effect.map(make(cfg), (s): EmbeddingModelService => ({
|
|
281
|
+
// OpenAI emits float32 only and has no task parameter. Reject a
|
|
282
|
+
// non-float32 `encoding` (bucket 1, else a float32 vector comes back
|
|
283
|
+
// mislabeled as the requested type) and warn on a dropped `task`
|
|
284
|
+
// (bucket 2).
|
|
285
|
+
embed: <E extends EmbedEncoding | undefined = undefined>(
|
|
286
|
+
req: Omit<CommonEmbedRequest, "encoding"> & { readonly encoding?: E },
|
|
287
|
+
) =>
|
|
288
|
+
assertEncoding(req.encoding, ["float32"], "openai").pipe(
|
|
289
|
+
Effect.andThen(warnTaskDropped(req.task)),
|
|
290
|
+
Effect.andThen(s.embed(req as OpenAIEmbedRequest)),
|
|
291
|
+
) as Effect.Effect<EmbedResponse<E>, AiError.AiError>,
|
|
292
|
+
embedMany: <E extends EmbedEncoding | undefined = undefined>(
|
|
293
|
+
req: Omit<CommonEmbedManyRequest, "encoding"> & { readonly encoding?: E },
|
|
294
|
+
) =>
|
|
295
|
+
assertEncoding(req.encoding, ["float32"], "openai").pipe(
|
|
296
|
+
Effect.andThen(warnTaskDropped(req.task)),
|
|
297
|
+
Effect.andThen(s.embedMany(req as OpenAIEmbedManyRequest)),
|
|
298
|
+
) as Effect.Effect<EmbedManyResponse<E>, AiError.AiError>,
|
|
299
|
+
})),
|
|
305
300
|
)
|
|
306
301
|
return Layer.merge(typed, generic)
|
|
307
302
|
}
|
package/src/Responses.ts
CHANGED
|
@@ -51,6 +51,20 @@ export type ResponsesRequest = Omit<CommonRequest, "model"> & {
|
|
|
51
51
|
readonly safetyIdentifier?: string
|
|
52
52
|
readonly promptCacheKey?: string
|
|
53
53
|
readonly truncation?: "auto" | "disabled"
|
|
54
|
+
/**
|
|
55
|
+
* Vendor-specific body fields merged into the request as-is.
|
|
56
|
+
*
|
|
57
|
+
* The Responses dialect is spoken by gateways as well as by OpenAI, and a
|
|
58
|
+
* gateway carries its own parameters — Requesty's `{ requesty: { auto_cache:
|
|
59
|
+
* true } }`, for example. Modelling each one would tie this provider to a
|
|
60
|
+
* catalogue of gateways it cannot see; passing them through keeps the typed
|
|
61
|
+
* surface OpenAI's and the untyped surface open.
|
|
62
|
+
*
|
|
63
|
+
* Merged over the built body, so a field named here wins over the one this
|
|
64
|
+
* provider would have sent. Per-request keys win over the layer's
|
|
65
|
+
* {@link Config.extraBody}.
|
|
66
|
+
*/
|
|
67
|
+
readonly extraBody?: Readonly<Record<string, unknown>>
|
|
54
68
|
/**
|
|
55
69
|
* Free-form JSON output: model emits valid JSON without schema
|
|
56
70
|
* constraints. Mutually exclusive with `structured` (schema wins if
|
|
@@ -108,6 +122,12 @@ export type Config = {
|
|
|
108
122
|
readonly apiKey: Redacted.Redacted
|
|
109
123
|
readonly baseUrl?: string
|
|
110
124
|
readonly region?: OpenAiRegion
|
|
125
|
+
/**
|
|
126
|
+
* Vendor-specific body fields sent on every request from this layer — the
|
|
127
|
+
* place for a gateway's standing configuration, so call sites do not repeat
|
|
128
|
+
* it. Overridden per request by {@link ResponsesRequest.extraBody}.
|
|
129
|
+
*/
|
|
130
|
+
readonly extraBody?: Readonly<Record<string, unknown>>
|
|
111
131
|
}
|
|
112
132
|
|
|
113
133
|
// ---------------------------------------------------------------------------
|
|
@@ -136,6 +156,7 @@ const buildText = (request: ResponsesRequest): Record<string, unknown> | undefin
|
|
|
136
156
|
const buildBody = (
|
|
137
157
|
request: ResponsesRequest,
|
|
138
158
|
providerToolWire: ReadonlyArray<Record<string, unknown>>,
|
|
159
|
+
cfg: Config,
|
|
139
160
|
): Record<string, unknown> => {
|
|
140
161
|
const text = buildText(request)
|
|
141
162
|
const functionTools = descriptorsOf(request.tools).map((t) => ({
|
|
@@ -176,6 +197,8 @@ const buildBody = (
|
|
|
176
197
|
}),
|
|
177
198
|
...(request.truncation !== undefined && { truncation: request.truncation }),
|
|
178
199
|
...(text !== undefined && { text }),
|
|
200
|
+
...cfg.extraBody,
|
|
201
|
+
...request.extraBody,
|
|
179
202
|
}
|
|
180
203
|
}
|
|
181
204
|
|
|
@@ -309,7 +332,7 @@ const buildNativeStream = (cfg: Config) => {
|
|
|
309
332
|
)
|
|
310
333
|
const httpRequest = HttpClientRequest.post(url).pipe(
|
|
311
334
|
HttpClientRequest.bearerToken(cfg.apiKey),
|
|
312
|
-
HttpClientRequest.bodyJsonUnsafe(buildBody(request, providerToolWire)),
|
|
335
|
+
HttpClientRequest.bodyJsonUnsafe(buildBody(request, providerToolWire, cfg)),
|
|
313
336
|
HttpClientRequest.accept("text/event-stream"),
|
|
314
337
|
)
|
|
315
338
|
const response = yield* client
|
|
@@ -373,13 +396,10 @@ export const layer = (
|
|
|
373
396
|
const typed = Layer.effect(Responses, make(cfg))
|
|
374
397
|
const generic = Layer.effect(
|
|
375
398
|
LanguageModel,
|
|
376
|
-
Effect.map(
|
|
377
|
-
|
|
378
|
-
(
|
|
379
|
-
|
|
380
|
-
turn: (request) => s.turn(request as ResponsesRequest),
|
|
381
|
-
}),
|
|
382
|
-
),
|
|
399
|
+
Effect.map(make(cfg), (s): LanguageModelService => ({
|
|
400
|
+
streamTurn: (request) => s.streamTurn(request as ResponsesRequest),
|
|
401
|
+
turn: (request) => s.turn(request as ResponsesRequest),
|
|
402
|
+
})),
|
|
383
403
|
)
|
|
384
404
|
return Layer.merge(typed, generic)
|
|
385
405
|
}
|
package/src/ResponsesTools.ts
CHANGED
|
@@ -139,12 +139,10 @@ const renderOne = (
|
|
|
139
139
|
})
|
|
140
140
|
: decodeConfig(tool.config).pipe(
|
|
141
141
|
Result.map(configToWire),
|
|
142
|
-
Result.mapError(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}),
|
|
147
|
-
),
|
|
142
|
+
Result.mapError((): ToolRenderError => ({
|
|
143
|
+
capability: "providerTool",
|
|
144
|
+
reason: `unrecognized Responses provider tool config on "${tool.name}"`,
|
|
145
|
+
})),
|
|
148
146
|
)
|
|
149
147
|
|
|
150
148
|
/**
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { HistoryItem } from "@effect-uai/core/Items"
|
|
2
|
+
import { describe, expect, it } from "vitest"
|
|
3
|
+
import { itemsToInput, wireItemToItem } from "./codec.js"
|
|
4
|
+
|
|
5
|
+
describe("providerData round-trip", () => {
|
|
6
|
+
it("re-emits a stashed item verbatim, preserving fields our shape drops", () => {
|
|
7
|
+
// `id` and `encrypted_content` cannot be reconstructed from a Reasoning
|
|
8
|
+
// item, so the round-trip has to go through the stash.
|
|
9
|
+
const items = wireItemToItem({
|
|
10
|
+
type: "reasoning",
|
|
11
|
+
id: "rs_1",
|
|
12
|
+
encrypted_content: "opaque-state",
|
|
13
|
+
})
|
|
14
|
+
expect(itemsToInput(items)).toEqual([
|
|
15
|
+
{ type: "reasoning", id: "rs_1", encrypted_content: "opaque-state" },
|
|
16
|
+
])
|
|
17
|
+
})
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
describe("providerData is a shared slot", () => {
|
|
21
|
+
// Regression: the passthrough used to re-emit the whole `providerData`
|
|
22
|
+
// object as the wire item. An item that had been through another provider
|
|
23
|
+
// first was sent as that provider's data, losing the real content.
|
|
24
|
+
it("ignores another provider's data and encodes the item normally", () => {
|
|
25
|
+
const history: ReadonlyArray<HistoryItem> = [
|
|
26
|
+
{
|
|
27
|
+
type: "message",
|
|
28
|
+
role: "user",
|
|
29
|
+
content: [{ type: "input_text", text: "hello world" }],
|
|
30
|
+
providerData: { gemini: { thoughtSignature: "sig-abc" } },
|
|
31
|
+
},
|
|
32
|
+
]
|
|
33
|
+
expect(itemsToInput(history)).toEqual([
|
|
34
|
+
{ type: "message", role: "user", content: [{ type: "input_text", text: "hello world" }] },
|
|
35
|
+
])
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it("does not send a foreign function_call as junk", () => {
|
|
39
|
+
const history: ReadonlyArray<HistoryItem> = [
|
|
40
|
+
{
|
|
41
|
+
type: "function_call",
|
|
42
|
+
call_id: "c1",
|
|
43
|
+
name: "get_weather",
|
|
44
|
+
arguments: '{"city":"Lisbon"}',
|
|
45
|
+
providerData: { gemini: { id: "g1", thoughtSignature: "sig-abc" } },
|
|
46
|
+
},
|
|
47
|
+
]
|
|
48
|
+
expect(itemsToInput(history)).toEqual([
|
|
49
|
+
{
|
|
50
|
+
type: "function_call",
|
|
51
|
+
call_id: "c1",
|
|
52
|
+
name: "get_weather",
|
|
53
|
+
arguments: '{"city":"Lisbon"}',
|
|
54
|
+
},
|
|
55
|
+
])
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
it("re-emits only our key when an item carries several providers' data", () => {
|
|
59
|
+
const history: ReadonlyArray<HistoryItem> = [
|
|
60
|
+
{
|
|
61
|
+
type: "reasoning",
|
|
62
|
+
signature: "opaque-state",
|
|
63
|
+
providerData: {
|
|
64
|
+
responses: { type: "reasoning", id: "rs_1", encrypted_content: "opaque-state" },
|
|
65
|
+
gemini: { thoughtSignature: "sig-abc" },
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
]
|
|
69
|
+
expect(itemsToInput(history)).toEqual([
|
|
70
|
+
{ type: "reasoning", id: "rs_1", encrypted_content: "opaque-state" },
|
|
71
|
+
])
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
it("falls back to a normal encode when the stashed value is not one of ours", () => {
|
|
75
|
+
const history: ReadonlyArray<HistoryItem> = [
|
|
76
|
+
{
|
|
77
|
+
type: "message",
|
|
78
|
+
role: "user",
|
|
79
|
+
content: [{ type: "input_text", text: "hi" }],
|
|
80
|
+
providerData: { responses: { type: "not_an_item_we_model" } },
|
|
81
|
+
},
|
|
82
|
+
]
|
|
83
|
+
expect(itemsToInput(history)).toEqual([
|
|
84
|
+
{ type: "message", role: "user", content: [{ type: "input_text", text: "hi" }] },
|
|
85
|
+
])
|
|
86
|
+
})
|
|
87
|
+
})
|
package/src/codec.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Encoding, Match, Option, Schema } from "effect"
|
|
1
|
+
import { Encoding, Match, Option, Result, Schema, pipe } from "effect"
|
|
2
2
|
import type { ContentBlock, InputImage, HistoryItem } from "@effect-uai/core/Items"
|
|
3
3
|
import type { Turn } from "@effect-uai/core/Turn"
|
|
4
4
|
|
|
@@ -159,16 +159,36 @@ export type WireResponseCompleted = typeof WireResponseCompleted.Type
|
|
|
159
159
|
// ---------------------------------------------------------------------------
|
|
160
160
|
|
|
161
161
|
/**
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
162
|
+
* The item shapes we stash for round-tripping. Narrower than
|
|
163
|
+
* `WireOutputItem`: the provider-hosted call variants are dropped from the
|
|
164
|
+
* turn, so they are never stored. Composed from the internal `Wire*` structs,
|
|
165
|
+
* which keeps the wire model out of the package's public surface.
|
|
165
166
|
*/
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
167
|
+
const StoredItem = Schema.Union([WireMessage, WireFunctionCall, WireReasoning])
|
|
168
|
+
type StoredItem = typeof StoredItem.Type
|
|
169
|
+
|
|
170
|
+
const ProviderDataResponses = Schema.Struct({ responses: StoredItem })
|
|
171
|
+
const decodeResponsesData = Schema.decodeUnknownResult(ProviderDataResponses)
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* If an item carries `providerData.responses` from a prior turn on this API,
|
|
175
|
+
* re-emit it verbatim - preserves `encrypted_content` and item ids, which a
|
|
176
|
+
* fresh encode from our `HistoryItem` shape cannot reconstruct.
|
|
177
|
+
*
|
|
178
|
+
* Namespaced because `providerData` is a shared slot: an item routed through
|
|
179
|
+
* another provider first (dynamic fallback) carries that provider's key, and
|
|
180
|
+
* re-emitting the whole object would send that provider's data as the wire
|
|
181
|
+
* item and drop the real content. Anything that fails to decode is not ours,
|
|
182
|
+
* so we fall back to encoding the item normally.
|
|
183
|
+
*/
|
|
184
|
+
const passthrough = (item: HistoryItem): StoredItem | undefined =>
|
|
185
|
+
pipe(
|
|
186
|
+
decodeResponsesData(item.providerData),
|
|
187
|
+
Result.match({
|
|
188
|
+
onSuccess: (data) => data.responses,
|
|
189
|
+
onFailure: (): StoredItem | undefined => undefined,
|
|
190
|
+
}),
|
|
191
|
+
)
|
|
172
192
|
|
|
173
193
|
/**
|
|
174
194
|
* OpenAI's `input_image` content block carries a single `image_url` field;
|
|
@@ -253,7 +273,7 @@ export const wireItemToItem = (wire: WireOutputItem): ReadonlyArray<HistoryItem>
|
|
|
253
273
|
type: "message" as const,
|
|
254
274
|
role: m.role,
|
|
255
275
|
content: m.content.map(wireMessageContentToBlock),
|
|
256
|
-
providerData: m,
|
|
276
|
+
providerData: { responses: m },
|
|
257
277
|
},
|
|
258
278
|
],
|
|
259
279
|
function_call: (f): ReadonlyArray<HistoryItem> => [
|
|
@@ -262,7 +282,7 @@ export const wireItemToItem = (wire: WireOutputItem): ReadonlyArray<HistoryItem>
|
|
|
262
282
|
call_id: f.call_id,
|
|
263
283
|
name: f.name,
|
|
264
284
|
arguments: f.arguments,
|
|
265
|
-
providerData: f,
|
|
285
|
+
providerData: { responses: f },
|
|
266
286
|
},
|
|
267
287
|
],
|
|
268
288
|
reasoning: (r): ReadonlyArray<HistoryItem> => [
|
|
@@ -273,7 +293,7 @@ export const wireItemToItem = (wire: WireOutputItem): ReadonlyArray<HistoryItem>
|
|
|
273
293
|
summary: r.summary.map((s) => s.text).join("\n"),
|
|
274
294
|
}),
|
|
275
295
|
...(r.encrypted_content !== undefined && { signature: r.encrypted_content }),
|
|
276
|
-
providerData: r,
|
|
296
|
+
providerData: { responses: r },
|
|
277
297
|
},
|
|
278
298
|
],
|
|
279
299
|
// Hosted-tool calls are provider-executed; drop from the turn (Phase 1).
|