@opencode/ai 2.1.1 → 2.1.3
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/cache-policy.js +6 -5
- package/dist/experimental/evaluation.d.ts +7 -6
- package/dist/experimental/evaluation.js +2 -3
- package/dist/experimental/realtime.d.ts +59 -0
- package/dist/experimental/realtime.js +32 -19
- package/dist/experimental/system-one.js +8 -8
- package/dist/experimental.d.ts +1 -1
- package/dist/generation.js +1 -1
- package/dist/image-client.d.ts +3 -1
- package/dist/image.d.ts +10 -2
- package/dist/image.js +2 -2
- package/dist/llm.d.ts +2 -4
- package/dist/llm.js +2 -2
- package/dist/media-model.d.ts +2 -2
- package/dist/media-model.js +1 -1
- package/dist/media.js +3 -3
- package/dist/promise.d.ts +1 -1
- package/dist/promise.js +3 -5
- package/dist/protocols/alibaba-chat.d.ts +6 -6
- package/dist/protocols/alibaba-chat.js +3 -3
- package/dist/protocols/alibaba-messages.d.ts +1 -1
- package/dist/protocols/alibaba-messages.js +1 -1
- package/dist/protocols/alibaba-responses.d.ts +3 -3
- package/dist/protocols/anthropic-messages.js +10 -12
- package/dist/protocols/bedrock-converse.d.ts +6 -53
- package/dist/protocols/bedrock-converse.js +4 -3
- package/dist/protocols/bedrock-event-stream.d.ts +6 -1
- package/dist/protocols/bedrock-event-stream.js +9 -8
- package/dist/protocols/cohere-chat.d.ts +6 -2
- package/dist/protocols/cohere-chat.js +2 -2
- package/dist/protocols/gemini.d.ts +12 -2
- package/dist/protocols/gemini.js +10 -13
- package/dist/protocols/google-interactions.d.ts +2 -1
- package/dist/protocols/google-interactions.js +14 -9
- package/dist/protocols/meta-responses.d.ts +6 -6
- package/dist/protocols/mistral-chat.js +1 -4
- package/dist/protocols/open-responses.d.ts +21 -21
- package/dist/protocols/open-responses.js +3 -3
- package/dist/protocols/openai-chat.d.ts +8 -7
- package/dist/protocols/openai-chat.js +4 -5
- package/dist/protocols/openai-compatible-responses.d.ts +3 -3
- package/dist/protocols/openai-responses.d.ts +18 -18
- package/dist/protocols/utils/open-responses-options.d.ts +8 -8
- package/dist/protocols/utils/open-responses-options.js +4 -6
- package/dist/protocols/utils/partial-json.js +5 -4
- package/dist/protocols/utils/tool-schema.d.ts +0 -3
- package/dist/protocols/utils/tool-schema.js +0 -4
- package/dist/protocols/venice-chat.js +6 -6
- package/dist/protocols/xai-images.js +3 -4
- package/dist/protocols/xai-responses.d.ts +3 -3
- package/dist/provider-error.js +4 -5
- package/dist/providers/alibaba.d.ts +30 -30
- package/dist/providers/amazon-bedrock-mantle.d.ts +3 -3
- package/dist/providers/amazon-bedrock.d.ts +11 -8
- package/dist/providers/azure.d.ts +6 -6
- package/dist/providers/cloudflare-ai-gateway.d.ts +7 -7
- package/dist/providers/cloudflare-ai-gateway.js +2 -4
- package/dist/providers/cohere.d.ts +6 -2
- package/dist/providers/google-vertex-interactions.d.ts +3 -3
- package/dist/providers/google-vertex-messages.d.ts +18 -18
- package/dist/providers/google-vertex-mistral.d.ts +3 -3
- package/dist/providers/google-vertex-responses.d.ts +3 -3
- package/dist/providers/google.d.ts +66 -66
- package/dist/providers/meta.d.ts +21 -21
- package/dist/providers/minimax.d.ts +195 -195
- package/dist/providers/moonshot.d.ts +3 -3
- package/dist/providers/openai-compatible-responses.d.ts +3 -3
- package/dist/providers/openai-options.d.ts +3 -3
- package/dist/providers/openai.d.ts +3 -3
- package/dist/providers/openrouter.d.ts +135 -76
- package/dist/providers/openrouter.js +40 -33
- package/dist/providers/vercel-ai-gateway.js +7 -6
- package/dist/providers/zai-coding-plan.d.ts +3 -3
- package/dist/route/client.d.ts +0 -216
- package/dist/route/client.js +1 -5
- package/dist/route/executor-service.d.ts +6 -2
- package/dist/route/executor-service.js +7 -0
- package/dist/route/executor.d.ts +2 -3
- package/dist/route/executor.js +6 -11
- package/dist/route/media-protocol.d.ts +1 -1
- package/dist/route/media-protocol.js +3 -3
- package/dist/route/transport/http.js +5 -8
- package/dist/route/transport/websocket.d.ts +0 -24
- package/dist/route/transport/websocket.js +0 -50
- package/dist/schema/errors.d.ts +9 -8
- package/dist/schema/errors.js +9 -5
- package/dist/schema/messages.js +4 -7
- package/dist/speech-client.d.ts +3 -1
- package/dist/speech.d.ts +10 -2
- package/dist/speech.js +2 -2
- package/dist/transcription-client.d.ts +3 -1
- package/dist/transcription.d.ts +10 -2
- package/dist/transcription.js +2 -2
- package/dist/video-client.d.ts +3 -1
- package/dist/video.d.ts +10 -2
- package/dist/video.js +2 -2
- package/package.json +4 -4
- package/dist/protocols/utils/openai-options.d.ts +0 -16
- package/dist/protocols/utils/openai-options.js +0 -15
package/dist/route/client.d.ts
CHANGED
|
@@ -214,222 +214,6 @@ export declare function stream(request: LLMRequest, options?: StreamOptions): St
|
|
|
214
214
|
export declare function generate(request: LLMRequest, options?: StreamOptions): Effect.Effect<LLMResponse, AIError, Service>;
|
|
215
215
|
export declare function compact(request: CheckpointRequest, options: TriggerCompactOptions): Effect.Effect<CompactionCheckpointResponse, AIError, Service>;
|
|
216
216
|
export declare function compact(request: CompactionRequest, options?: EndpointCompactOptions): Effect.Effect<CompactionResponse, AIError, Service>;
|
|
217
|
-
export declare const streamRequest: (request: LLMRequest, options?: StreamOptions) => Stream.Stream<{
|
|
218
|
-
readonly type: "step-start";
|
|
219
|
-
readonly index: number;
|
|
220
|
-
} | {
|
|
221
|
-
readonly type: "text-start";
|
|
222
|
-
readonly id: string;
|
|
223
|
-
readonly providerMetadata?: {
|
|
224
|
-
readonly [x: string]: {
|
|
225
|
-
readonly [x: string]: unknown;
|
|
226
|
-
};
|
|
227
|
-
} | undefined;
|
|
228
|
-
} | {
|
|
229
|
-
readonly type: "text-delta";
|
|
230
|
-
readonly id: string;
|
|
231
|
-
readonly text: string;
|
|
232
|
-
readonly providerMetadata?: {
|
|
233
|
-
readonly [x: string]: {
|
|
234
|
-
readonly [x: string]: unknown;
|
|
235
|
-
};
|
|
236
|
-
} | undefined;
|
|
237
|
-
} | {
|
|
238
|
-
readonly type: "text-end";
|
|
239
|
-
readonly id: string;
|
|
240
|
-
readonly text?: string | undefined;
|
|
241
|
-
readonly providerMetadata?: {
|
|
242
|
-
readonly [x: string]: {
|
|
243
|
-
readonly [x: string]: unknown;
|
|
244
|
-
};
|
|
245
|
-
} | undefined;
|
|
246
|
-
} | {
|
|
247
|
-
readonly type: "reasoning-start";
|
|
248
|
-
readonly id: string;
|
|
249
|
-
readonly providerMetadata?: {
|
|
250
|
-
readonly [x: string]: {
|
|
251
|
-
readonly [x: string]: unknown;
|
|
252
|
-
};
|
|
253
|
-
} | undefined;
|
|
254
|
-
} | {
|
|
255
|
-
readonly type: "reasoning-delta";
|
|
256
|
-
readonly id: string;
|
|
257
|
-
readonly text: string;
|
|
258
|
-
readonly providerMetadata?: {
|
|
259
|
-
readonly [x: string]: {
|
|
260
|
-
readonly [x: string]: unknown;
|
|
261
|
-
};
|
|
262
|
-
} | undefined;
|
|
263
|
-
} | {
|
|
264
|
-
readonly type: "reasoning-end";
|
|
265
|
-
readonly id: string;
|
|
266
|
-
readonly text?: string | undefined;
|
|
267
|
-
readonly providerMetadata?: {
|
|
268
|
-
readonly [x: string]: {
|
|
269
|
-
readonly [x: string]: unknown;
|
|
270
|
-
};
|
|
271
|
-
} | undefined;
|
|
272
|
-
} | {
|
|
273
|
-
readonly type: "tool-input-start";
|
|
274
|
-
readonly id: string;
|
|
275
|
-
readonly name: string;
|
|
276
|
-
readonly namespace?: string | undefined;
|
|
277
|
-
readonly providerExecuted?: boolean | undefined;
|
|
278
|
-
readonly providerMetadata?: {
|
|
279
|
-
readonly [x: string]: {
|
|
280
|
-
readonly [x: string]: unknown;
|
|
281
|
-
};
|
|
282
|
-
} | undefined;
|
|
283
|
-
} | {
|
|
284
|
-
readonly type: "tool-input-delta";
|
|
285
|
-
readonly id: string;
|
|
286
|
-
readonly name: string;
|
|
287
|
-
readonly namespace?: string | undefined;
|
|
288
|
-
readonly text: string;
|
|
289
|
-
readonly input?: unknown;
|
|
290
|
-
} | {
|
|
291
|
-
readonly type: "tool-input-end";
|
|
292
|
-
readonly id: string;
|
|
293
|
-
readonly name: string;
|
|
294
|
-
readonly namespace?: string | undefined;
|
|
295
|
-
readonly providerMetadata?: {
|
|
296
|
-
readonly [x: string]: {
|
|
297
|
-
readonly [x: string]: unknown;
|
|
298
|
-
};
|
|
299
|
-
} | undefined;
|
|
300
|
-
} | {
|
|
301
|
-
readonly type: "tool-input-error";
|
|
302
|
-
readonly id: string;
|
|
303
|
-
readonly name: string;
|
|
304
|
-
readonly namespace?: string | undefined;
|
|
305
|
-
readonly raw: string;
|
|
306
|
-
} | {
|
|
307
|
-
readonly type: "tool-call";
|
|
308
|
-
readonly id: string;
|
|
309
|
-
readonly name: string;
|
|
310
|
-
readonly namespace?: string | undefined;
|
|
311
|
-
readonly input: unknown;
|
|
312
|
-
readonly providerExecuted?: boolean | undefined;
|
|
313
|
-
readonly providerMetadata?: {
|
|
314
|
-
readonly [x: string]: {
|
|
315
|
-
readonly [x: string]: unknown;
|
|
316
|
-
};
|
|
317
|
-
} | undefined;
|
|
318
|
-
} | {
|
|
319
|
-
readonly type: "tool-result";
|
|
320
|
-
readonly id: string;
|
|
321
|
-
readonly name: string;
|
|
322
|
-
readonly namespace?: string | undefined;
|
|
323
|
-
readonly result: {
|
|
324
|
-
readonly type: "json";
|
|
325
|
-
readonly value: unknown;
|
|
326
|
-
} | {
|
|
327
|
-
readonly type: "text";
|
|
328
|
-
readonly value: unknown;
|
|
329
|
-
} | {
|
|
330
|
-
readonly type: "error";
|
|
331
|
-
readonly value: unknown;
|
|
332
|
-
} | {
|
|
333
|
-
readonly type: "content";
|
|
334
|
-
readonly value: readonly ({
|
|
335
|
-
readonly type: "text";
|
|
336
|
-
readonly text: string;
|
|
337
|
-
} | {
|
|
338
|
-
readonly type: "file";
|
|
339
|
-
readonly uri: string;
|
|
340
|
-
readonly mime: string;
|
|
341
|
-
readonly name?: string | undefined;
|
|
342
|
-
})[];
|
|
343
|
-
};
|
|
344
|
-
readonly output?: {
|
|
345
|
-
readonly structured: unknown;
|
|
346
|
-
readonly content: readonly ({
|
|
347
|
-
readonly type: "text";
|
|
348
|
-
readonly text: string;
|
|
349
|
-
} | {
|
|
350
|
-
readonly type: "file";
|
|
351
|
-
readonly uri: string;
|
|
352
|
-
readonly mime: string;
|
|
353
|
-
readonly name?: string | undefined;
|
|
354
|
-
})[];
|
|
355
|
-
} | undefined;
|
|
356
|
-
readonly providerExecuted?: boolean | undefined;
|
|
357
|
-
readonly providerMetadata?: {
|
|
358
|
-
readonly [x: string]: {
|
|
359
|
-
readonly [x: string]: unknown;
|
|
360
|
-
};
|
|
361
|
-
} | undefined;
|
|
362
|
-
} | {
|
|
363
|
-
readonly type: "tool-error";
|
|
364
|
-
readonly id: string;
|
|
365
|
-
readonly name: string;
|
|
366
|
-
readonly namespace?: string | undefined;
|
|
367
|
-
readonly message: string;
|
|
368
|
-
readonly error?: unknown;
|
|
369
|
-
readonly providerMetadata?: {
|
|
370
|
-
readonly [x: string]: {
|
|
371
|
-
readonly [x: string]: unknown;
|
|
372
|
-
};
|
|
373
|
-
} | undefined;
|
|
374
|
-
} | {
|
|
375
|
-
readonly type: "step-finish";
|
|
376
|
-
readonly index: number;
|
|
377
|
-
readonly reason: {
|
|
378
|
-
readonly normalized: "content-filter" | "error" | "length" | "stop" | "tool-calls" | "unknown";
|
|
379
|
-
readonly raw?: string | undefined;
|
|
380
|
-
readonly category?: string | undefined;
|
|
381
|
-
readonly explanation?: string | undefined;
|
|
382
|
-
};
|
|
383
|
-
readonly usage?: import("../schema/events.js").Usage | undefined;
|
|
384
|
-
readonly providerMetadata?: {
|
|
385
|
-
readonly [x: string]: {
|
|
386
|
-
readonly [x: string]: unknown;
|
|
387
|
-
};
|
|
388
|
-
} | undefined;
|
|
389
|
-
} | {
|
|
390
|
-
readonly type: "finish";
|
|
391
|
-
readonly reason: {
|
|
392
|
-
readonly normalized: "content-filter" | "error" | "length" | "stop" | "tool-calls" | "unknown";
|
|
393
|
-
readonly raw?: string | undefined;
|
|
394
|
-
readonly category?: string | undefined;
|
|
395
|
-
readonly explanation?: string | undefined;
|
|
396
|
-
};
|
|
397
|
-
readonly usage?: import("../schema/events.js").Usage | undefined;
|
|
398
|
-
readonly providerMetadata?: {
|
|
399
|
-
readonly [x: string]: {
|
|
400
|
-
readonly [x: string]: unknown;
|
|
401
|
-
};
|
|
402
|
-
} | undefined;
|
|
403
|
-
} | {
|
|
404
|
-
readonly type: "media";
|
|
405
|
-
readonly media: import("../media.js").Asset;
|
|
406
|
-
readonly providerMetadata?: {
|
|
407
|
-
readonly [x: string]: {
|
|
408
|
-
readonly [x: string]: unknown;
|
|
409
|
-
};
|
|
410
|
-
} | undefined;
|
|
411
|
-
} | {
|
|
412
|
-
readonly type: "provider-error";
|
|
413
|
-
readonly message: string;
|
|
414
|
-
readonly classification?: "context-overflow" | "payload-too-large" | undefined;
|
|
415
|
-
readonly providerMetadata?: {
|
|
416
|
-
readonly [x: string]: {
|
|
417
|
-
readonly [x: string]: unknown;
|
|
418
|
-
};
|
|
419
|
-
} | undefined;
|
|
420
|
-
} | ({
|
|
421
|
-
readonly type: "compaction";
|
|
422
|
-
readonly provider: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
423
|
-
readonly id?: string | undefined;
|
|
424
|
-
readonly encrypted?: string | undefined;
|
|
425
|
-
readonly text?: string | null | undefined;
|
|
426
|
-
} & ({
|
|
427
|
-
readonly encrypted: string;
|
|
428
|
-
readonly text?: never;
|
|
429
|
-
} | {
|
|
430
|
-
readonly text: string | null;
|
|
431
|
-
readonly encrypted?: never;
|
|
432
|
-
})), AIError, LLMClientService>;
|
|
433
217
|
export declare const layer: Layer.Layer<Service, never, RequestExecutor.Service>;
|
|
434
218
|
export declare const Route: {
|
|
435
219
|
readonly make: typeof make;
|
package/dist/route/client.js
CHANGED
|
@@ -15,7 +15,7 @@ const makeRouteLanguageModel = (route, mapped) => {
|
|
|
15
15
|
const provider = route.provider ?? ("provider" in mapped ? mapped.provider : undefined);
|
|
16
16
|
if (!provider)
|
|
17
17
|
throw new Error(`Route.model(${route.id}) requires a provider`);
|
|
18
|
-
if (!
|
|
18
|
+
if (!route.endpoint.baseURL)
|
|
19
19
|
throw new ProviderConfigurationError({
|
|
20
20
|
provider: ProviderID.make(provider),
|
|
21
21
|
message: `Route.model(${route.id}) requires an endpoint baseURL — configure it on the route first`,
|
|
@@ -37,7 +37,6 @@ const mergeRouteDefaults = (base, patch) => {
|
|
|
37
37
|
http: mergeHttpOptions(base?.http, HttpOptions.make(patch.http), headers === undefined ? undefined : new HttpOptions({ headers })),
|
|
38
38
|
};
|
|
39
39
|
};
|
|
40
|
-
const endpointBaseURL = (endpoint) => typeof endpoint.baseURL === "string" ? endpoint.baseURL : undefined;
|
|
41
40
|
const mergeHeaders = (...items) => {
|
|
42
41
|
const entries = items.flatMap((item) => item === undefined ? [] : Object.entries(item).filter((entry) => entry[1] !== undefined));
|
|
43
42
|
if (entries.length === 0)
|
|
@@ -272,9 +271,6 @@ export function compact(request, options) {
|
|
|
272
271
|
return yield* unsupportedCompaction(request, options?.mechanism);
|
|
273
272
|
});
|
|
274
273
|
}
|
|
275
|
-
export const streamRequest = (request, options) => Stream.unwrap(Effect.gen(function* () {
|
|
276
|
-
return (yield* Service).stream(request, options);
|
|
277
|
-
}));
|
|
278
274
|
export const layer = Layer.effect(Service, Effect.gen(function* () {
|
|
279
275
|
const executor = yield* RequestExecutor.Service;
|
|
280
276
|
const stream = streamRequestWith({ http: executor });
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Context, type Effect } from "effect";
|
|
2
|
-
import type { HttpClientRequest, HttpClientResponse } from "effect/http";
|
|
3
|
-
import type
|
|
2
|
+
import type { Headers, HttpClientRequest, HttpClientResponse } from "effect/http";
|
|
3
|
+
import { HttpContext, type AIError } from "../schema/errors.js";
|
|
4
4
|
export interface Interface {
|
|
5
5
|
readonly execute: (request: HttpClientRequest.HttpClientRequest, middleware?: HttpMiddleware) => Effect.Effect<HttpClientResponse.HttpClientResponse, AIError>;
|
|
6
6
|
}
|
|
@@ -11,4 +11,8 @@ export declare class RequestExecutorService extends RequestExecutorService_base
|
|
|
11
11
|
}
|
|
12
12
|
export declare const Service: typeof RequestExecutorService;
|
|
13
13
|
export type Service = RequestExecutorService;
|
|
14
|
+
export declare const headerDetails: (headers: Headers.Headers) => {
|
|
15
|
+
[k: string]: string;
|
|
16
|
+
};
|
|
17
|
+
export declare const responseHttp: (response: HttpClientResponse.HttpClientResponse) => HttpContext;
|
|
14
18
|
export {};
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import { Context } from "effect";
|
|
2
|
+
import { HttpContext } from "../schema/errors.js";
|
|
2
3
|
export class RequestExecutorService extends Context.Service()("@opencode/AI/RequestExecutor") {
|
|
3
4
|
}
|
|
4
5
|
export const Service = RequestExecutorService;
|
|
6
|
+
export const headerDetails = (headers) => Object.fromEntries(Object.entries(headers).map(([name, value]) => [name, String(value)]));
|
|
7
|
+
export const responseHttp = (response) => new HttpContext({
|
|
8
|
+
url: response.request.url,
|
|
9
|
+
status: response.status,
|
|
10
|
+
headers: headerDetails(response.headers),
|
|
11
|
+
});
|
package/dist/route/executor.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { Layer, Stream } from "effect";
|
|
2
2
|
import { HttpClient, HttpClientRequest, HttpClientResponse } from "effect/http";
|
|
3
|
-
import {
|
|
3
|
+
import { AIError } from "../schema/index.js";
|
|
4
4
|
import { Service, type HttpMiddleware, type Interface } from "./executor-service.js";
|
|
5
|
-
export { Service } from "./executor-service.js";
|
|
5
|
+
export { responseHttp, Service } from "./executor-service.js";
|
|
6
6
|
export type { HttpHandler, HttpMiddleware, Interface } from "./executor-service.js";
|
|
7
|
-
export declare const responseHttp: (response: HttpClientResponse.HttpClientResponse) => HttpContext;
|
|
8
7
|
/** Preserve HTTP diagnostics for executor and externally captured failures alike. */
|
|
9
8
|
export declare const httpFailure: (input: {
|
|
10
9
|
readonly message: string;
|
package/dist/route/executor.js
CHANGED
|
@@ -2,23 +2,23 @@ import { Cause, Effect, Layer, Option, Schema, Stream } from "effect";
|
|
|
2
2
|
import { FetchHttpClient, Headers, HttpClient, HttpClientError, HttpClientRequest, HttpClientResponse, } from "effect/http";
|
|
3
3
|
import { HttpContext, HttpRateLimitDetails, AIError, TransportError } from "../schema/index.js";
|
|
4
4
|
import { classifyProviderFailure, providerErrorMessage } from "../provider-error.js";
|
|
5
|
-
import { Service } from "./executor-service.js";
|
|
6
|
-
export { Service } from "./executor-service.js";
|
|
7
|
-
const headerDetails = (headers) => Object.fromEntries(Object.entries(headers).map(([name, value]) => [name, String(value)]));
|
|
5
|
+
import { headerDetails, responseHttp, Service } from "./executor-service.js";
|
|
6
|
+
export { responseHttp, Service } from "./executor-service.js";
|
|
8
7
|
const normalizedHeaders = (headers) => Object.fromEntries(Object.entries(headers).map(([key, value]) => [key.toLowerCase(), value]));
|
|
8
|
+
const clampRetryAfterMs = (millis) => Math.min(Number.MAX_SAFE_INTEGER, Math.max(0, Math.ceil(millis)));
|
|
9
9
|
const retryAfterMs = (headers) => {
|
|
10
10
|
const millis = Number(headers["retry-after-ms"]);
|
|
11
11
|
if (Number.isFinite(millis))
|
|
12
|
-
return
|
|
12
|
+
return clampRetryAfterMs(millis);
|
|
13
13
|
const value = headers["retry-after"];
|
|
14
14
|
if (!value)
|
|
15
15
|
return undefined;
|
|
16
16
|
const seconds = Number(value);
|
|
17
17
|
if (Number.isFinite(seconds))
|
|
18
|
-
return
|
|
18
|
+
return clampRetryAfterMs(seconds * 1000);
|
|
19
19
|
const date = Date.parse(value);
|
|
20
20
|
if (!Number.isNaN(date))
|
|
21
|
-
return
|
|
21
|
+
return clampRetryAfterMs(date - Date.now());
|
|
22
22
|
return undefined;
|
|
23
23
|
};
|
|
24
24
|
const addRateLimitValue = (target, key, value) => {
|
|
@@ -60,11 +60,6 @@ const rateLimitDetails = (headers, retryAfter) => {
|
|
|
60
60
|
reset: Object.keys(reset).length === 0 ? undefined : reset,
|
|
61
61
|
});
|
|
62
62
|
};
|
|
63
|
-
export const responseHttp = (response) => new HttpContext({
|
|
64
|
-
url: response.request.url,
|
|
65
|
-
status: response.status,
|
|
66
|
-
headers: headerDetails(response.headers),
|
|
67
|
-
});
|
|
68
63
|
const MAX_BODY_CHARS = 2000;
|
|
69
64
|
// Without a recognized message, show the raw body so the provider's explanation is never dropped.
|
|
70
65
|
const providerMessage = (status, body) => {
|
|
@@ -3,7 +3,7 @@ import { HttpClientResponse } from "effect/http";
|
|
|
3
3
|
import type { Snapshot, Status } from "../generation.js";
|
|
4
4
|
import { Media } from "../media.js";
|
|
5
5
|
import type { AuthInput } from "./auth.js";
|
|
6
|
-
import { AIError, AuthenticationError, HttpContext, InvalidRequestError, ProviderID, ProviderInternalError, RateLimitError } from "../schema/index.js";
|
|
6
|
+
import { AIError, AuthenticationError, type HttpContext, InvalidRequestError, ProviderID, ProviderInternalError, RateLimitError } from "../schema/index.js";
|
|
7
7
|
/** Array values become repeated parameters (`keyterm=a&keyterm=b`). */
|
|
8
8
|
export type Query = Readonly<Record<string, string | ReadonlyArray<string>>>;
|
|
9
9
|
/** `query` is appended to the endpoint URL before the route and caller `http.query` overlays. */
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Clock, Duration, Effect, Schema } from "effect";
|
|
2
2
|
import { HttpClientResponse } from "effect/http";
|
|
3
3
|
import { Media } from "../media.js";
|
|
4
|
-
import {
|
|
4
|
+
import { RequestExecutor } from "./executor.js";
|
|
5
|
+
import { AIError, AuthenticationError, ContentPolicyError, InvalidProviderOutputError, InvalidRequestError, ProviderID, ProviderInternalError, RateLimitError, UnsupportedOperationError, } from "../schema/index.js";
|
|
5
6
|
export const json = (value, query) => ({
|
|
6
7
|
type: "json",
|
|
7
8
|
value,
|
|
@@ -27,7 +28,6 @@ const FAILURES = {
|
|
|
27
28
|
RateLimit: RateLimitError,
|
|
28
29
|
ProviderInternal: ProviderInternalError,
|
|
29
30
|
};
|
|
30
|
-
const context = (response) => new HttpContext({ url: response.request.url, status: response.status, headers: response.headers });
|
|
31
31
|
/** One protocol's route id, display name, and provider, with the decoders and errors that carry them. */
|
|
32
32
|
export const identity = (input) => {
|
|
33
33
|
const provider = ProviderID.make(input.provider);
|
|
@@ -40,7 +40,7 @@ export const identity = (input) => {
|
|
|
40
40
|
* `contentPolicy` is a moderated result.
|
|
41
41
|
*/
|
|
42
42
|
const text = Effect.fn("MediaProtocol.text")(function* (response) {
|
|
43
|
-
const http =
|
|
43
|
+
const http = RequestExecutor.responseHttp(response);
|
|
44
44
|
const body = yield* response.text.pipe(Effect.mapError((cause) => new AIError({
|
|
45
45
|
reason: new InvalidProviderOutputError({
|
|
46
46
|
route: input.id,
|
|
@@ -6,13 +6,6 @@ import { Framing } from "../framing.js";
|
|
|
6
6
|
import * as ProviderShared from "../../protocols/shared.js";
|
|
7
7
|
import { AIError, DEFAULT_CHUNK_TIMEOUT_MS, DEFAULT_HTTP_TIMEOUT_MS, mergeJsonRecords, TransportError, } from "../../schema/index.js";
|
|
8
8
|
import { RequestExecutor } from "../executor.js";
|
|
9
|
-
const applyQuery = (url, query) => {
|
|
10
|
-
if (!query)
|
|
11
|
-
return url;
|
|
12
|
-
const next = new URL(url);
|
|
13
|
-
Object.entries(query).forEach(([key, value]) => next.searchParams.set(key, value));
|
|
14
|
-
return next.toString();
|
|
15
|
-
};
|
|
16
9
|
const bodyWithOverlay = (body, request, encodeBody) => Effect.gen(function* () {
|
|
17
10
|
if (request.http?.body === undefined)
|
|
18
11
|
return { jsonBody: body, bodyText: encodeBody(body) };
|
|
@@ -23,7 +16,11 @@ const bodyWithOverlay = (body, request, encodeBody) => Effect.gen(function* () {
|
|
|
23
16
|
return yield* ProviderShared.invalidRequest("http.body can only overlay JSON object request bodies");
|
|
24
17
|
});
|
|
25
18
|
export const jsonRequestParts = (input) => Effect.gen(function* () {
|
|
26
|
-
const
|
|
19
|
+
const endpoint = renderEndpoint(input.endpoint, { request: input.request, body: input.body });
|
|
20
|
+
if (input.request.http?.query) {
|
|
21
|
+
Object.entries(input.request.http.query).forEach(([key, value]) => endpoint.searchParams.set(key, value));
|
|
22
|
+
}
|
|
23
|
+
const url = endpoint.toString();
|
|
27
24
|
const body = yield* bodyWithOverlay(input.body, input.request, input.encodeBody);
|
|
28
25
|
const headers = yield* Auth.toEffect(input.auth)({
|
|
29
26
|
request: input.request,
|
|
@@ -2,7 +2,6 @@ import { Effect, Stream } from "effect";
|
|
|
2
2
|
import { Headers } from "effect/http";
|
|
3
3
|
import { Socket } from "effect/socket";
|
|
4
4
|
import { AIError, type HttpContext } from "../../schema/index.js";
|
|
5
|
-
import type { Transport } from "./index.js";
|
|
6
5
|
import type { WebSocketChannelExecutor } from "./websocket-channel.js";
|
|
7
6
|
export interface WebSocketRequest {
|
|
8
7
|
readonly url: string;
|
|
@@ -23,30 +22,7 @@ export declare const fromWebSocket: (ws: Socket.WebSocketLike, input: WebSocketR
|
|
|
23
22
|
export declare const messageText: (message: string | Uint8Array, decoder: TextDecoder) => string;
|
|
24
23
|
export declare const makeDirect: (connector: WebSocketConnector) => WebSocketChannelExecutor;
|
|
25
24
|
export declare const direct: Effect.Effect<WebSocketChannelExecutor, never, Socket.WebSocketConstructor>;
|
|
26
|
-
export interface JsonPrepared {
|
|
27
|
-
readonly url: string;
|
|
28
|
-
readonly headers: Headers.Headers;
|
|
29
|
-
readonly message: string;
|
|
30
|
-
}
|
|
31
|
-
export interface JsonInput<Body, Message> {
|
|
32
|
-
readonly toMessage: (body: Body | Record<string, unknown>) => Effect.Effect<Message, AIError>;
|
|
33
|
-
readonly encodeMessage: (message: Message) => string;
|
|
34
|
-
}
|
|
35
|
-
export type JsonPatch<Body, Message> = Partial<JsonInput<Body, Message>>;
|
|
36
|
-
export interface JsonTransport<Body, Message> extends Transport<Body, JsonPrepared, string> {
|
|
37
|
-
readonly with: (patch: JsonPatch<Body, Message>) => JsonTransport<Body, Message>;
|
|
38
|
-
}
|
|
39
|
-
export declare const json: <Body, Message>(input: JsonInput<Body, Message>) => JsonTransport<Body, Message>;
|
|
40
|
-
export declare const jsonTransport: {
|
|
41
|
-
readonly id: "websocket-json";
|
|
42
|
-
readonly with: typeof json;
|
|
43
|
-
};
|
|
44
25
|
export declare const WebSocketTransport: {
|
|
45
|
-
readonly json: typeof json;
|
|
46
|
-
readonly jsonTransport: {
|
|
47
|
-
readonly id: "websocket-json";
|
|
48
|
-
readonly with: typeof json;
|
|
49
|
-
};
|
|
50
26
|
readonly direct: Effect.Effect<WebSocketChannelExecutor, never, Socket.WebSocketConstructor>;
|
|
51
27
|
readonly makeDirect: typeof makeDirect;
|
|
52
28
|
readonly open: typeof open;
|
|
@@ -2,7 +2,6 @@ import { Cause, Effect, Queue, Stream } from "effect";
|
|
|
2
2
|
import { Headers } from "effect/http";
|
|
3
3
|
import { Socket } from "effect/socket";
|
|
4
4
|
import { AIError, AIErrorReason, TransportError, } from "../../schema/index.js";
|
|
5
|
-
import * as HttpTransport from "./http.js";
|
|
6
5
|
const MAX_FRAME_BYTES = 16 * 1024 * 1024;
|
|
7
6
|
const transportError = (message, input) => new AIError({
|
|
8
7
|
reason: new TransportError({
|
|
@@ -300,56 +299,7 @@ export const direct = Effect.gen(function* () {
|
|
|
300
299
|
open: (input) => open(input).pipe(Effect.provideService(Socket.WebSocketConstructor, constructor)),
|
|
301
300
|
});
|
|
302
301
|
});
|
|
303
|
-
export const json = (input) => ({
|
|
304
|
-
id: "websocket-json",
|
|
305
|
-
with: (patch) => json({ ...input, ...patch }),
|
|
306
|
-
prepare: (prepareInput) => Effect.gen(function* () {
|
|
307
|
-
const parts = yield* HttpTransport.jsonRequestParts({
|
|
308
|
-
...prepareInput,
|
|
309
|
-
});
|
|
310
|
-
return {
|
|
311
|
-
url: yield* toWebSocketUrl(parts.url),
|
|
312
|
-
headers: parts.headers,
|
|
313
|
-
message: input.encodeMessage(yield* input.toMessage(parts.jsonBody)),
|
|
314
|
-
};
|
|
315
|
-
}),
|
|
316
|
-
execute: (prepared, request, _runtime, options) => {
|
|
317
|
-
const webSocket = options?.webSocket;
|
|
318
|
-
if (!webSocket) {
|
|
319
|
-
return Effect.fail(transportError("WebSocket JSON transport requires StreamOptions.webSocket", {
|
|
320
|
-
url: prepared.url,
|
|
321
|
-
operation: "request",
|
|
322
|
-
code: "unavailable",
|
|
323
|
-
phase: "prepare",
|
|
324
|
-
delivery: "not-sent",
|
|
325
|
-
}));
|
|
326
|
-
}
|
|
327
|
-
const driver = {
|
|
328
|
-
create: () => Effect.succeed({ message: prepared.message, mode: "full" }),
|
|
329
|
-
observe: (_create, frame) => Effect.succeed({ type: "frame", frame }),
|
|
330
|
-
};
|
|
331
|
-
const exchange = {
|
|
332
|
-
id: request.id ?? "request",
|
|
333
|
-
connect: { url: prepared.url, headers: prepared.headers },
|
|
334
|
-
fallback: () => Stream.fail(transportError("WebSocket JSON transport does not provide HTTP fallback", {
|
|
335
|
-
url: prepared.url,
|
|
336
|
-
operation: "request",
|
|
337
|
-
code: "websocket",
|
|
338
|
-
phase: "fallback",
|
|
339
|
-
delivery: "not-sent",
|
|
340
|
-
})),
|
|
341
|
-
driver,
|
|
342
|
-
};
|
|
343
|
-
return webSocket.execute(exchange);
|
|
344
|
-
},
|
|
345
|
-
});
|
|
346
|
-
export const jsonTransport = {
|
|
347
|
-
id: "websocket-json",
|
|
348
|
-
with: json,
|
|
349
|
-
};
|
|
350
302
|
export const WebSocketTransport = {
|
|
351
|
-
json,
|
|
352
|
-
jsonTransport,
|
|
353
303
|
direct,
|
|
354
304
|
makeDirect,
|
|
355
305
|
open,
|
package/dist/schema/errors.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ declare const HttpContext_base: Schema.Class<HttpContext, Schema.Struct<{
|
|
|
10
10
|
export declare class HttpContext extends HttpContext_base {
|
|
11
11
|
}
|
|
12
12
|
declare const HttpRateLimitDetails_base: Schema.Class<HttpRateLimitDetails, Schema.Struct<{
|
|
13
|
-
readonly retryAfterMs: Schema.optional<Schema.
|
|
13
|
+
readonly retryAfterMs: Schema.optional<Schema.Int>;
|
|
14
14
|
readonly limit: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
|
|
15
15
|
readonly remaining: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
|
|
16
16
|
readonly reset: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
|
|
@@ -80,16 +80,17 @@ declare const RateLimitError_base: Schema.Class<RateLimitError, Schema.TaggedStr
|
|
|
80
80
|
readonly body: Schema.optional<Schema.String>;
|
|
81
81
|
readonly http: Schema.optional<typeof HttpContext>;
|
|
82
82
|
readonly cause: Schema.optional<Schema.Defect>;
|
|
83
|
-
readonly retryAfterMs: Schema.optional<Schema.
|
|
83
|
+
readonly retryAfterMs: Schema.optional<Schema.Int>;
|
|
84
84
|
readonly rateLimit: Schema.optional<typeof HttpRateLimitDetails>;
|
|
85
85
|
}>, import("effect/Cause").YieldableError>;
|
|
86
86
|
export declare class RateLimitError extends RateLimitError_base {
|
|
87
87
|
}
|
|
88
88
|
declare const QuotaExceededError_base: Schema.Class<QuotaExceededError, Schema.TaggedStruct<"QuotaExceeded", {
|
|
89
|
-
message: Schema.String;
|
|
90
|
-
body: Schema.optional<Schema.String>;
|
|
91
|
-
http: Schema.optional<typeof HttpContext>;
|
|
92
|
-
cause: Schema.optional<Schema.Defect>;
|
|
89
|
+
readonly message: Schema.String;
|
|
90
|
+
readonly body: Schema.optional<Schema.String>;
|
|
91
|
+
readonly http: Schema.optional<typeof HttpContext>;
|
|
92
|
+
readonly cause: Schema.optional<Schema.Defect>;
|
|
93
|
+
readonly retryAfterMs: Schema.optional<Schema.Int>;
|
|
93
94
|
}>, import("effect/Cause").YieldableError>;
|
|
94
95
|
export declare class QuotaExceededError extends QuotaExceededError_base {
|
|
95
96
|
}
|
|
@@ -106,7 +107,7 @@ declare const ProviderInternalError_base: Schema.Class<ProviderInternalError, Sc
|
|
|
106
107
|
readonly body: Schema.optional<Schema.String>;
|
|
107
108
|
readonly http: Schema.optional<typeof HttpContext>;
|
|
108
109
|
readonly cause: Schema.optional<Schema.Defect>;
|
|
109
|
-
readonly retryAfterMs: Schema.optional<Schema.
|
|
110
|
+
readonly retryAfterMs: Schema.optional<Schema.Int>;
|
|
110
111
|
}>, import("effect/Cause").YieldableError>;
|
|
111
112
|
export declare class ProviderInternalError extends ProviderInternalError_base {
|
|
112
113
|
}
|
|
@@ -152,7 +153,7 @@ declare const TimeoutError_base: Schema.Class<TimeoutError, Schema.TaggedStruct<
|
|
|
152
153
|
readonly body: Schema.optional<Schema.String>;
|
|
153
154
|
readonly http: Schema.optional<typeof HttpContext>;
|
|
154
155
|
readonly cause: Schema.optional<Schema.Defect>;
|
|
155
|
-
readonly timeoutMs: Schema.optional<Schema.
|
|
156
|
+
readonly timeoutMs: Schema.optional<Schema.Int>;
|
|
156
157
|
}>, import("effect/Cause").YieldableError>;
|
|
157
158
|
/** A caller-supplied deadline elapsed, such as `Generation.await` polling past its `Poll.timeout`. */
|
|
158
159
|
export declare class TimeoutError extends TimeoutError_base {
|
package/dist/schema/errors.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
|
+
import { NonNegativeInt } from "@opencode/schema";
|
|
2
3
|
import { Tool } from "@opencode/schema/tool";
|
|
3
4
|
import { ModelID, ProviderID, RouteID } from "./ids.js";
|
|
4
5
|
export const ProviderFailureClassification = Schema.Literals(["context-overflow", "payload-too-large"]);
|
|
@@ -9,7 +10,7 @@ export class HttpContext extends Schema.Class("AI.HttpContext")({
|
|
|
9
10
|
}) {
|
|
10
11
|
}
|
|
11
12
|
export class HttpRateLimitDetails extends Schema.Class("AI.HttpRateLimitDetails")({
|
|
12
|
-
retryAfterMs: Schema.optional(
|
|
13
|
+
retryAfterMs: Schema.optional(NonNegativeInt),
|
|
13
14
|
limit: Schema.optional(Schema.Record(Schema.String, Schema.String)),
|
|
14
15
|
remaining: Schema.optional(Schema.Record(Schema.String, Schema.String)),
|
|
15
16
|
reset: Schema.optional(Schema.Record(Schema.String, Schema.String)),
|
|
@@ -63,17 +64,20 @@ export class AuthenticationError extends Schema.TaggedError("AI.Error.Authentica
|
|
|
63
64
|
}
|
|
64
65
|
export class RateLimitError extends Schema.TaggedError("AI.Error.RateLimit")("RateLimit", {
|
|
65
66
|
...ReasonFields,
|
|
66
|
-
retryAfterMs: Schema.optional(
|
|
67
|
+
retryAfterMs: Schema.optional(NonNegativeInt),
|
|
67
68
|
rateLimit: Schema.optional(HttpRateLimitDetails),
|
|
68
69
|
}) {
|
|
69
70
|
}
|
|
70
|
-
export class QuotaExceededError extends Schema.TaggedError("AI.Error.QuotaExceeded")("QuotaExceeded",
|
|
71
|
+
export class QuotaExceededError extends Schema.TaggedError("AI.Error.QuotaExceeded")("QuotaExceeded", {
|
|
72
|
+
...ReasonFields,
|
|
73
|
+
retryAfterMs: Schema.optional(NonNegativeInt),
|
|
74
|
+
}) {
|
|
71
75
|
}
|
|
72
76
|
export class ContentPolicyError extends Schema.TaggedError("AI.Error.ContentPolicy")("ContentPolicy", ReasonFields) {
|
|
73
77
|
}
|
|
74
78
|
export class ProviderInternalError extends Schema.TaggedError("AI.Error.ProviderInternal")("ProviderInternal", {
|
|
75
79
|
...ReasonFields,
|
|
76
|
-
retryAfterMs: Schema.optional(
|
|
80
|
+
retryAfterMs: Schema.optional(NonNegativeInt),
|
|
77
81
|
}) {
|
|
78
82
|
}
|
|
79
83
|
export const TransportType = Schema.Literals(["http", "websocket"]);
|
|
@@ -100,7 +104,7 @@ export class UnknownProviderError extends Schema.TaggedError("AI.Error.UnknownPr
|
|
|
100
104
|
/** A caller-supplied deadline elapsed, such as `Generation.await` polling past its `Poll.timeout`. */
|
|
101
105
|
export class TimeoutError extends Schema.TaggedError("AI.Error.Timeout")("Timeout", {
|
|
102
106
|
...ReasonFields,
|
|
103
|
-
timeoutMs: Schema.optional(
|
|
107
|
+
timeoutMs: Schema.optional(NonNegativeInt),
|
|
104
108
|
}) {
|
|
105
109
|
}
|
|
106
110
|
export const AIErrorReason = Schema.Union([
|
package/dist/schema/messages.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { Schema } from "effect";
|
|
1
|
+
import { Option, Schema } from "effect";
|
|
2
2
|
import { withStatics } from "@opencode/schema/schema";
|
|
3
3
|
import { Tool } from "@opencode/schema/tool";
|
|
4
4
|
import { CacheHint, CachePolicy, GenerationOptions, HttpOptions, JsonSchema, LanguageModelSchema, ProviderMetadata, ProviderOptions, ReasoningEffort, } from "./options.js";
|
|
5
5
|
import { ProviderID } from "./ids.js";
|
|
6
6
|
import { Media } from "../media.js";
|
|
7
|
+
import { Json } from "../utils/json.js";
|
|
7
8
|
export const MessageRole = Schema.Literals(["system", "user", "assistant", "tool"]);
|
|
8
9
|
const systemPartSchema = Schema.Struct({
|
|
9
10
|
type: Schema.Literal("text"),
|
|
@@ -89,15 +90,11 @@ export const ToolOutput = withStatics(Schema.Struct({
|
|
|
89
90
|
return { type: "content", value: output.content };
|
|
90
91
|
},
|
|
91
92
|
});
|
|
93
|
+
const encodeJsonOption = Schema.encodeUnknownOption(Json);
|
|
92
94
|
const toolResultText = (value) => {
|
|
93
95
|
if (typeof value === "string")
|
|
94
96
|
return value;
|
|
95
|
-
|
|
96
|
-
return JSON.stringify(value) ?? String(value);
|
|
97
|
-
}
|
|
98
|
-
catch {
|
|
99
|
-
return String(value);
|
|
100
|
-
}
|
|
97
|
+
return Option.getOrElse(encodeJsonOption(value), () => String(value));
|
|
101
98
|
};
|
|
102
99
|
export const ToolCallPart = withStatics(Schema.Struct({
|
|
103
100
|
type: Schema.Literal("tool-call"),
|
package/dist/speech-client.d.ts
CHANGED
|
@@ -60,7 +60,9 @@ export declare const SpeechClient: {
|
|
|
60
60
|
} | undefined;
|
|
61
61
|
} | import("./generation.js").Observation, import("./index.js").AIError, SpeechClientService>;
|
|
62
62
|
readonly start: (request: SpeechRequestFor) => import("effect/Effect").Effect<import("./generation.js").Generation<SpeechResponse>, import("./index.js").AIError, SpeechClientService>;
|
|
63
|
-
readonly resume: (model: import("./speech.js").SpeechModel<
|
|
63
|
+
readonly resume: (model: import("./speech.js").SpeechModel<{
|
|
64
|
+
readonly [x: string]: unknown;
|
|
65
|
+
}>, token: unknown) => import("effect/Effect").Effect<import("./generation.js").Generation<SpeechResponse>, import("./index.js").AIError, SpeechClientService>;
|
|
64
66
|
readonly Service: typeof SpeechClientService;
|
|
65
67
|
};
|
|
66
68
|
export {};
|