@effect/ai-openai 0.37.2 → 4.0.0-beta.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/Generated.d.ts +70887 -0
- package/dist/Generated.d.ts.map +1 -0
- package/dist/Generated.js +4 -0
- package/dist/Generated.js.map +1 -0
- package/dist/OpenAiClient.d.ts +124 -0
- package/dist/OpenAiClient.d.ts.map +1 -0
- package/dist/OpenAiClient.js +128 -0
- package/dist/OpenAiClient.js.map +1 -0
- package/dist/{dts/OpenAiConfig.d.ts → OpenAiConfig.d.ts} +9 -9
- package/dist/OpenAiConfig.d.ts.map +1 -0
- package/dist/{esm/OpenAiConfig.js → OpenAiConfig.js} +8 -5
- package/dist/OpenAiConfig.js.map +1 -0
- package/dist/OpenAiError.d.ts +98 -0
- package/dist/OpenAiError.d.ts.map +1 -0
- package/dist/OpenAiError.js +10 -0
- package/dist/OpenAiError.js.map +1 -0
- package/dist/OpenAiLanguageModel.d.ts +318 -0
- package/dist/OpenAiLanguageModel.d.ts.map +1 -0
- package/dist/OpenAiLanguageModel.js +2207 -0
- package/dist/OpenAiLanguageModel.js.map +1 -0
- package/dist/{dts/OpenAiTelemetry.d.ts → OpenAiTelemetry.d.ts} +31 -13
- package/dist/OpenAiTelemetry.d.ts.map +1 -0
- package/dist/{esm/OpenAiTelemetry.js → OpenAiTelemetry.js} +11 -6
- package/dist/OpenAiTelemetry.js.map +1 -0
- package/dist/OpenAiTool.d.ts +479 -0
- package/dist/OpenAiTool.d.ts.map +1 -0
- package/dist/OpenAiTool.js +231 -0
- package/dist/OpenAiTool.js.map +1 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/errors.d.ts +2 -0
- package/dist/internal/errors.d.ts.map +1 -0
- package/dist/internal/errors.js +316 -0
- package/dist/internal/errors.js.map +1 -0
- package/dist/{dts/internal → internal}/utilities.d.ts.map +1 -1
- package/dist/{esm/internal → internal}/utilities.js +4 -3
- package/dist/internal/utilities.js.map +1 -0
- package/package.json +45 -97
- package/src/Generated.ts +28521 -20036
- package/src/OpenAiClient.ts +220 -1816
- package/src/OpenAiConfig.ts +20 -34
- package/src/OpenAiError.ts +107 -0
- package/src/OpenAiLanguageModel.ts +1807 -638
- package/src/OpenAiTelemetry.ts +24 -19
- package/src/OpenAiTool.ts +216 -70
- package/src/index.ts +35 -8
- package/src/internal/errors.ts +347 -0
- package/src/internal/utilities.ts +7 -5
- package/Generated/package.json +0 -6
- package/OpenAiClient/package.json +0 -6
- package/OpenAiConfig/package.json +0 -6
- package/OpenAiEmbeddingModel/package.json +0 -6
- package/OpenAiLanguageModel/package.json +0 -6
- package/OpenAiTelemetry/package.json +0 -6
- package/OpenAiTokenizer/package.json +0 -6
- package/OpenAiTool/package.json +0 -6
- package/README.md +0 -5
- package/dist/cjs/Generated.js +0 -7150
- package/dist/cjs/Generated.js.map +0 -1
- package/dist/cjs/OpenAiClient.js +0 -1567
- package/dist/cjs/OpenAiClient.js.map +0 -1
- package/dist/cjs/OpenAiConfig.js +0 -30
- package/dist/cjs/OpenAiConfig.js.map +0 -1
- package/dist/cjs/OpenAiEmbeddingModel.js +0 -155
- package/dist/cjs/OpenAiEmbeddingModel.js.map +0 -1
- package/dist/cjs/OpenAiLanguageModel.js +0 -1147
- package/dist/cjs/OpenAiLanguageModel.js.map +0 -1
- package/dist/cjs/OpenAiTelemetry.js +0 -38
- package/dist/cjs/OpenAiTelemetry.js.map +0 -1
- package/dist/cjs/OpenAiTokenizer.js +0 -83
- package/dist/cjs/OpenAiTokenizer.js.map +0 -1
- package/dist/cjs/OpenAiTool.js +0 -93
- package/dist/cjs/OpenAiTool.js.map +0 -1
- package/dist/cjs/index.js +0 -24
- package/dist/cjs/index.js.map +0 -1
- package/dist/cjs/internal/utilities.js +0 -32
- package/dist/cjs/internal/utilities.js.map +0 -1
- package/dist/dts/Generated.d.ts +0 -40661
- package/dist/dts/Generated.d.ts.map +0 -1
- package/dist/dts/OpenAiClient.d.ts +0 -3120
- package/dist/dts/OpenAiClient.d.ts.map +0 -1
- package/dist/dts/OpenAiConfig.d.ts.map +0 -1
- package/dist/dts/OpenAiEmbeddingModel.d.ts +0 -109
- package/dist/dts/OpenAiEmbeddingModel.d.ts.map +0 -1
- package/dist/dts/OpenAiLanguageModel.d.ts +0 -235
- package/dist/dts/OpenAiLanguageModel.d.ts.map +0 -1
- package/dist/dts/OpenAiTelemetry.d.ts.map +0 -1
- package/dist/dts/OpenAiTokenizer.d.ts +0 -17
- package/dist/dts/OpenAiTokenizer.d.ts.map +0 -1
- package/dist/dts/OpenAiTool.d.ts +0 -200
- package/dist/dts/OpenAiTool.d.ts.map +0 -1
- package/dist/dts/index.d.ts +0 -33
- package/dist/dts/index.d.ts.map +0 -1
- package/dist/esm/Generated.js +0 -7150
- package/dist/esm/Generated.js.map +0 -1
- package/dist/esm/OpenAiClient.js +0 -1504
- package/dist/esm/OpenAiClient.js.map +0 -1
- package/dist/esm/OpenAiConfig.js.map +0 -1
- package/dist/esm/OpenAiEmbeddingModel.js +0 -143
- package/dist/esm/OpenAiEmbeddingModel.js.map +0 -1
- package/dist/esm/OpenAiLanguageModel.js +0 -1134
- package/dist/esm/OpenAiLanguageModel.js.map +0 -1
- package/dist/esm/OpenAiTelemetry.js.map +0 -1
- package/dist/esm/OpenAiTokenizer.js +0 -73
- package/dist/esm/OpenAiTokenizer.js.map +0 -1
- package/dist/esm/OpenAiTool.js +0 -84
- package/dist/esm/OpenAiTool.js.map +0 -1
- package/dist/esm/index.js +0 -33
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/internal/utilities.js.map +0 -1
- package/dist/esm/package.json +0 -4
- package/index/package.json +0 -6
- package/src/OpenAiEmbeddingModel.ts +0 -243
- package/src/OpenAiTokenizer.ts +0 -70
- /package/dist/{dts/internal → internal}/utilities.d.ts +0 -0
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
import * as Duration from "effect/Duration"
|
|
2
|
+
import * as Effect from "effect/Effect"
|
|
3
|
+
import { dual } from "effect/Function"
|
|
4
|
+
import * as Number from "effect/Number"
|
|
5
|
+
import * as Option from "effect/Option"
|
|
6
|
+
import * as Predicate from "effect/Predicate"
|
|
7
|
+
import * as Redactable from "effect/Redactable"
|
|
8
|
+
import * as Schema from "effect/Schema"
|
|
9
|
+
import * as AiError from "effect/unstable/ai/AiError"
|
|
10
|
+
import type * as Response from "effect/unstable/ai/Response"
|
|
11
|
+
import type * as HttpClientError from "effect/unstable/http/HttpClientError"
|
|
12
|
+
import type * as HttpClientRequest from "effect/unstable/http/HttpClientRequest"
|
|
13
|
+
import type * as HttpClientResponse from "effect/unstable/http/HttpClientResponse"
|
|
14
|
+
import type { OpenAiErrorMetadata } from "../OpenAiError.ts"
|
|
15
|
+
|
|
16
|
+
// =============================================================================
|
|
17
|
+
// OpenAI Error Body Schema
|
|
18
|
+
// =============================================================================
|
|
19
|
+
|
|
20
|
+
/** @internal */
|
|
21
|
+
export const OpenAiErrorBody = Schema.Struct({
|
|
22
|
+
error: Schema.Struct({
|
|
23
|
+
message: Schema.String,
|
|
24
|
+
type: Schema.optional(Schema.NullOr(Schema.String)),
|
|
25
|
+
param: Schema.optional(Schema.NullOr(Schema.String)),
|
|
26
|
+
code: Schema.optional(Schema.NullOr(Schema.String))
|
|
27
|
+
})
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
// =============================================================================
|
|
31
|
+
// Error Mappers
|
|
32
|
+
// =============================================================================
|
|
33
|
+
|
|
34
|
+
/** @internal */
|
|
35
|
+
export const mapSchemaError = dual<
|
|
36
|
+
(method: string) => (error: Schema.SchemaError) => AiError.AiError,
|
|
37
|
+
(error: Schema.SchemaError, method: string) => AiError.AiError
|
|
38
|
+
>(2, (error, method) =>
|
|
39
|
+
AiError.make({
|
|
40
|
+
module: "OpenAiClient",
|
|
41
|
+
method,
|
|
42
|
+
reason: AiError.InvalidOutputError.fromSchemaError(error)
|
|
43
|
+
}))
|
|
44
|
+
|
|
45
|
+
/** @internal */
|
|
46
|
+
export const mapHttpClientError = dual<
|
|
47
|
+
(method: string) => (error: HttpClientError.HttpClientError) => Effect.Effect<never, AiError.AiError>,
|
|
48
|
+
(error: HttpClientError.HttpClientError, method: string) => Effect.Effect<never, AiError.AiError>
|
|
49
|
+
>(2, (error, method) => {
|
|
50
|
+
const reason = error.reason
|
|
51
|
+
switch (reason._tag) {
|
|
52
|
+
case "TransportError": {
|
|
53
|
+
return Effect.fail(AiError.make({
|
|
54
|
+
module: "OpenAiClient",
|
|
55
|
+
method,
|
|
56
|
+
reason: new AiError.NetworkError({
|
|
57
|
+
reason: "TransportError",
|
|
58
|
+
description: reason.description,
|
|
59
|
+
request: buildHttpRequestDetails(reason.request)
|
|
60
|
+
})
|
|
61
|
+
}))
|
|
62
|
+
}
|
|
63
|
+
case "EncodeError": {
|
|
64
|
+
return Effect.fail(AiError.make({
|
|
65
|
+
module: "OpenAiClient",
|
|
66
|
+
method,
|
|
67
|
+
reason: new AiError.NetworkError({
|
|
68
|
+
reason: "EncodeError",
|
|
69
|
+
description: reason.description,
|
|
70
|
+
request: buildHttpRequestDetails(reason.request)
|
|
71
|
+
})
|
|
72
|
+
}))
|
|
73
|
+
}
|
|
74
|
+
case "InvalidUrlError": {
|
|
75
|
+
return Effect.fail(AiError.make({
|
|
76
|
+
module: "OpenAiClient",
|
|
77
|
+
method,
|
|
78
|
+
reason: new AiError.NetworkError({
|
|
79
|
+
reason: "InvalidUrlError",
|
|
80
|
+
description: reason.description,
|
|
81
|
+
request: buildHttpRequestDetails(reason.request)
|
|
82
|
+
})
|
|
83
|
+
}))
|
|
84
|
+
}
|
|
85
|
+
case "StatusCodeError": {
|
|
86
|
+
return mapStatusCodeError(reason, method)
|
|
87
|
+
}
|
|
88
|
+
case "DecodeError": {
|
|
89
|
+
return Effect.fail(AiError.make({
|
|
90
|
+
module: "OpenAiClient",
|
|
91
|
+
method,
|
|
92
|
+
reason: new AiError.InvalidOutputError({
|
|
93
|
+
description: reason.description ?? "Failed to decode response"
|
|
94
|
+
})
|
|
95
|
+
}))
|
|
96
|
+
}
|
|
97
|
+
case "EmptyBodyError": {
|
|
98
|
+
return Effect.fail(AiError.make({
|
|
99
|
+
module: "OpenAiClient",
|
|
100
|
+
method,
|
|
101
|
+
reason: new AiError.InvalidOutputError({
|
|
102
|
+
description: reason.description ?? "Response body was empty"
|
|
103
|
+
})
|
|
104
|
+
}))
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
/** @internal */
|
|
110
|
+
const mapStatusCodeError = Effect.fnUntraced(function*(
|
|
111
|
+
error: HttpClientError.StatusCodeError,
|
|
112
|
+
method: string
|
|
113
|
+
) {
|
|
114
|
+
const { request, response, description } = error
|
|
115
|
+
const status = response.status
|
|
116
|
+
const headers = response.headers as Record<string, string>
|
|
117
|
+
const requestId = headers["x-request-id"]
|
|
118
|
+
|
|
119
|
+
// Try to get the actual response body. The description from filterStatusOk
|
|
120
|
+
// is often just "non 2xx status code", so try reading from response.text
|
|
121
|
+
let body: string | undefined = description
|
|
122
|
+
if (!description || !description.startsWith("{")) {
|
|
123
|
+
const responseBody = yield* Effect.option(response.text)
|
|
124
|
+
if (Option.isSome(responseBody) && responseBody.value) {
|
|
125
|
+
body = responseBody.value
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Try to parse the body as JSON to extract error details
|
|
130
|
+
let json: unknown = undefined
|
|
131
|
+
// @effect-diagnostics effect/tryCatchInEffectGen:off
|
|
132
|
+
try {
|
|
133
|
+
json = Predicate.isNotUndefined(body) ? JSON.parse(body) : undefined
|
|
134
|
+
} catch {
|
|
135
|
+
json = undefined
|
|
136
|
+
}
|
|
137
|
+
const decoded = Schema.decodeUnknownOption(OpenAiErrorBody)(json)
|
|
138
|
+
|
|
139
|
+
const reason = mapStatusCodeToReason({
|
|
140
|
+
status,
|
|
141
|
+
headers,
|
|
142
|
+
message: Option.isSome(decoded) ? decoded.value.error.message : undefined,
|
|
143
|
+
http: buildHttpContext({ request, response, body }),
|
|
144
|
+
metadata: {
|
|
145
|
+
errorCode: Option.isSome(decoded) ? decoded.value.error.code ?? null : null,
|
|
146
|
+
errorType: Option.isSome(decoded) ? decoded.value.error.type ?? null : null,
|
|
147
|
+
requestId: requestId ?? null
|
|
148
|
+
}
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
return yield* AiError.make({ module: "OpenAiClient", method, reason })
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
// =============================================================================
|
|
155
|
+
// Rate Limits
|
|
156
|
+
// =============================================================================
|
|
157
|
+
|
|
158
|
+
/** @internal */
|
|
159
|
+
export const parseRateLimitHeaders = (headers: Record<string, string>) => {
|
|
160
|
+
const retryAfterRaw = headers["retry-after"]
|
|
161
|
+
let retryAfter: Duration.Duration | undefined
|
|
162
|
+
if (Predicate.isNotUndefined(retryAfterRaw)) {
|
|
163
|
+
const parsed = Number.parse(retryAfterRaw)
|
|
164
|
+
if (Predicate.isNotUndefined(parsed)) {
|
|
165
|
+
retryAfter = Duration.seconds(parsed)
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const remainingRaw = headers["x-ratelimit-remaining-requests"]
|
|
169
|
+
const remaining = Predicate.isNotUndefined(remainingRaw) ? Number.parse(remainingRaw) ?? null : null
|
|
170
|
+
return {
|
|
171
|
+
retryAfter,
|
|
172
|
+
limit: headers["x-ratelimit-limit-requests"] ?? null,
|
|
173
|
+
remaining,
|
|
174
|
+
resetRequests: headers["x-ratelimit-reset-requests"] ?? null,
|
|
175
|
+
resetTokens: headers["x-ratelimit-reset-tokens"] ?? null
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// =============================================================================
|
|
180
|
+
// HTTP Context
|
|
181
|
+
// =============================================================================
|
|
182
|
+
|
|
183
|
+
/** @internal */
|
|
184
|
+
export const buildHttpRequestDetails = (
|
|
185
|
+
request: HttpClientRequest.HttpClientRequest
|
|
186
|
+
): typeof Response.HttpRequestDetails.Type => ({
|
|
187
|
+
method: request.method,
|
|
188
|
+
url: request.url,
|
|
189
|
+
urlParams: Array.from(request.urlParams),
|
|
190
|
+
hash: request.hash,
|
|
191
|
+
headers: Redactable.redact(request.headers) as Record<string, string>
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
/** @internal */
|
|
195
|
+
export const buildHttpContext = (params: {
|
|
196
|
+
readonly request: HttpClientRequest.HttpClientRequest
|
|
197
|
+
readonly response?: HttpClientResponse.HttpClientResponse
|
|
198
|
+
readonly body?: string | undefined
|
|
199
|
+
}): typeof AiError.HttpContext.Type => ({
|
|
200
|
+
request: buildHttpRequestDetails(params.request),
|
|
201
|
+
response: Predicate.isNotUndefined(params.response)
|
|
202
|
+
? {
|
|
203
|
+
status: params.response.status,
|
|
204
|
+
headers: Redactable.redact(params.response.headers) as Record<string, string>
|
|
205
|
+
}
|
|
206
|
+
: undefined,
|
|
207
|
+
body: params.body
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
// =============================================================================
|
|
211
|
+
// HTTP Status Code
|
|
212
|
+
// =============================================================================
|
|
213
|
+
|
|
214
|
+
const buildInvalidRequestDescription = (params: {
|
|
215
|
+
readonly status: number
|
|
216
|
+
readonly message: string | undefined
|
|
217
|
+
readonly method: string
|
|
218
|
+
readonly url: string
|
|
219
|
+
readonly errorCode: string | null
|
|
220
|
+
readonly errorType: string | null
|
|
221
|
+
readonly requestId: string | null
|
|
222
|
+
readonly body: string | undefined
|
|
223
|
+
}): string => {
|
|
224
|
+
const parts: Array<string> = []
|
|
225
|
+
|
|
226
|
+
// Primary message or status description
|
|
227
|
+
if (params.message) {
|
|
228
|
+
parts.push(params.message)
|
|
229
|
+
} else {
|
|
230
|
+
parts.push(`HTTP ${params.status}`)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Request context
|
|
234
|
+
parts.push(`(${params.method} ${params.url})`)
|
|
235
|
+
|
|
236
|
+
// Error code/type if available
|
|
237
|
+
if (params.errorCode) {
|
|
238
|
+
parts.push(`[code: ${params.errorCode}]`)
|
|
239
|
+
} else if (params.errorType) {
|
|
240
|
+
parts.push(`[type: ${params.errorType}]`)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Request ID for debugging
|
|
244
|
+
if (params.requestId) {
|
|
245
|
+
parts.push(`[requestId: ${params.requestId}]`)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// If no message and we have body, show truncated body
|
|
249
|
+
if (!params.message && params.body) {
|
|
250
|
+
const truncated = params.body.length > 200
|
|
251
|
+
? params.body.slice(0, 200) + "..."
|
|
252
|
+
: params.body
|
|
253
|
+
parts.push(`Response: ${truncated}`)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return parts.join(" ")
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/** @internal */
|
|
260
|
+
export const mapStatusCodeToReason = ({ status, headers, message, metadata, http }: {
|
|
261
|
+
readonly status: number
|
|
262
|
+
readonly headers: Record<string, string>
|
|
263
|
+
readonly message: string | undefined
|
|
264
|
+
readonly metadata: OpenAiErrorMetadata
|
|
265
|
+
readonly http: typeof AiError.HttpContext.Type
|
|
266
|
+
}): AiError.AiErrorReason => {
|
|
267
|
+
const invalidRequestDescription = buildInvalidRequestDescription({
|
|
268
|
+
status,
|
|
269
|
+
message,
|
|
270
|
+
method: http.request.method,
|
|
271
|
+
url: http.request.url,
|
|
272
|
+
errorCode: metadata.errorCode,
|
|
273
|
+
errorType: metadata.errorType,
|
|
274
|
+
requestId: metadata.requestId,
|
|
275
|
+
body: http.body
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
switch (status) {
|
|
279
|
+
case 400:
|
|
280
|
+
return new AiError.InvalidRequestError({
|
|
281
|
+
description: invalidRequestDescription,
|
|
282
|
+
metadata: { openai: metadata },
|
|
283
|
+
http
|
|
284
|
+
})
|
|
285
|
+
case 401:
|
|
286
|
+
return new AiError.AuthenticationError({
|
|
287
|
+
kind: "InvalidKey",
|
|
288
|
+
metadata,
|
|
289
|
+
http
|
|
290
|
+
})
|
|
291
|
+
case 403:
|
|
292
|
+
return new AiError.AuthenticationError({
|
|
293
|
+
kind: "InsufficientPermissions",
|
|
294
|
+
metadata,
|
|
295
|
+
http
|
|
296
|
+
})
|
|
297
|
+
case 404:
|
|
298
|
+
return new AiError.InvalidRequestError({
|
|
299
|
+
description: invalidRequestDescription,
|
|
300
|
+
metadata: { openai: metadata },
|
|
301
|
+
http
|
|
302
|
+
})
|
|
303
|
+
case 409:
|
|
304
|
+
case 422:
|
|
305
|
+
return new AiError.InvalidRequestError({
|
|
306
|
+
description: invalidRequestDescription,
|
|
307
|
+
metadata: { openai: metadata },
|
|
308
|
+
http
|
|
309
|
+
})
|
|
310
|
+
case 429: {
|
|
311
|
+
// Best-effort detection: OpenAI returns insufficient_quota for billing/quota issues
|
|
312
|
+
if (
|
|
313
|
+
metadata.errorCode === "insufficient_quota" ||
|
|
314
|
+
metadata.errorType === "insufficient_quota"
|
|
315
|
+
) {
|
|
316
|
+
return new AiError.QuotaExhaustedError({
|
|
317
|
+
metadata: { openai: metadata },
|
|
318
|
+
http
|
|
319
|
+
})
|
|
320
|
+
}
|
|
321
|
+
const { retryAfter, ...rateLimitMetadata } = parseRateLimitHeaders(headers)
|
|
322
|
+
return new AiError.RateLimitError({
|
|
323
|
+
retryAfter,
|
|
324
|
+
metadata: {
|
|
325
|
+
openai: {
|
|
326
|
+
...metadata,
|
|
327
|
+
...rateLimitMetadata
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
http
|
|
331
|
+
})
|
|
332
|
+
}
|
|
333
|
+
default:
|
|
334
|
+
if (status >= 500) {
|
|
335
|
+
return new AiError.InternalProviderError({
|
|
336
|
+
description: message ?? "Server error",
|
|
337
|
+
metadata,
|
|
338
|
+
http
|
|
339
|
+
})
|
|
340
|
+
}
|
|
341
|
+
return new AiError.UnknownError({
|
|
342
|
+
description: message,
|
|
343
|
+
metadata,
|
|
344
|
+
http
|
|
345
|
+
})
|
|
346
|
+
}
|
|
347
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type * as Response from "
|
|
2
|
-
import * as Predicate from "effect/Predicate"
|
|
1
|
+
import type * as Response from "effect/unstable/ai/Response"
|
|
3
2
|
|
|
4
3
|
/** @internal */
|
|
5
4
|
export const ProviderOptionsKey = "@effect/ai-openai/OpenAiLanguageModel/ProviderOptions"
|
|
@@ -15,16 +14,19 @@ const finishReasonMap: Record<string, Response.FinishReason> = {
|
|
|
15
14
|
tool_calls: "tool-calls"
|
|
16
15
|
}
|
|
17
16
|
|
|
17
|
+
/** @internal */
|
|
18
|
+
export const escapeJSONDelta = (delta: string): string => JSON.stringify(delta).slice(1, -1)
|
|
19
|
+
|
|
18
20
|
/** @internal */
|
|
19
21
|
export const resolveFinishReason = (
|
|
20
|
-
finishReason: string | undefined,
|
|
22
|
+
finishReason: string | null | undefined,
|
|
21
23
|
hasToolCalls: boolean
|
|
22
24
|
): Response.FinishReason => {
|
|
23
|
-
if (
|
|
25
|
+
if (finishReason == null) {
|
|
24
26
|
return hasToolCalls ? "tool-calls" : "stop"
|
|
25
27
|
}
|
|
26
28
|
const reason = finishReasonMap[finishReason]
|
|
27
|
-
if (
|
|
29
|
+
if (reason == null) {
|
|
28
30
|
return hasToolCalls ? "tool-calls" : "unknown"
|
|
29
31
|
}
|
|
30
32
|
return reason
|
package/Generated/package.json
DELETED
package/OpenAiTool/package.json
DELETED