@opencode/ai 2.0.26 → 2.0.27
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/README.md +7 -1
- package/dist/experimental/system-one.js +1 -1
- package/dist/media.js +7 -6
- package/dist/protocols/anthropic-messages.js +1 -1
- package/dist/protocols/bedrock-converse.js +4 -3
- package/dist/protocols/bedrock-event-stream.js +4 -3
- package/dist/protocols/meta-responses.js +3 -2
- package/dist/protocols/mistral-chat.d.ts +1 -1
- package/dist/protocols/mistral-chat.js +1 -1
- package/dist/protocols/open-responses-channel.d.ts +1 -1
- package/dist/protocols/open-responses-channel.js +1 -1
- package/dist/protocols/openai-responses.d.ts +5 -5
- package/dist/protocols/openai-responses.js +4 -3
- package/dist/protocols/shared.d.ts +1 -1
- package/dist/protocols/shared.js +1 -1
- package/dist/protocols/utils/bedrock-auth.js +1 -1
- package/dist/protocols/utils/bedrock-media.js +4 -3
- package/dist/protocols/utils/fal-queue.d.ts +1 -1
- package/dist/protocols/utils/media-input.js +4 -3
- package/dist/protocols/utils/tool-schema.js +8 -2
- package/dist/providers/amazon-bedrock-mantle.js +2 -2
- package/dist/providers/anthropic-compatible.js +2 -2
- package/dist/providers/anthropic.js +2 -2
- package/dist/providers/azure.d.ts +2 -2
- package/dist/providers/azure.js +3 -3
- package/dist/providers/baseten.js +2 -2
- package/dist/providers/cerebras.js +2 -2
- package/dist/providers/cloudflare-ai-gateway.d.ts +2 -2
- package/dist/providers/cloudflare-ai-gateway.js +2 -2
- package/dist/providers/cloudflare-workers-ai.js +2 -2
- package/dist/providers/cohere/chat.js +1 -1
- package/dist/providers/cohere.js +1 -1
- package/dist/providers/deepinfra.js +2 -2
- package/dist/providers/deepseek.js +2 -2
- package/dist/providers/fireworks.js +2 -2
- package/dist/providers/google/interactions.js +2 -2
- package/dist/providers/google-vertex/interactions.d.ts +2 -0
- package/dist/providers/google-vertex/interactions.js +1 -0
- package/dist/providers/google-vertex/mistral.d.ts +2 -0
- package/dist/providers/google-vertex/mistral.js +1 -0
- package/dist/providers/google-vertex-chat.js +3 -3
- package/dist/providers/google-vertex-interactions.d.ts +112 -0
- package/dist/providers/google-vertex-interactions.js +64 -0
- package/dist/providers/google-vertex-messages.js +3 -3
- package/dist/providers/google-vertex-mistral.d.ts +124 -0
- package/dist/providers/google-vertex-mistral.js +69 -0
- package/dist/providers/google-vertex-responses.js +3 -3
- package/dist/providers/google-vertex-shared.d.ts +3 -1
- package/dist/providers/google-vertex-shared.js +29 -3
- package/dist/providers/google-vertex.js +3 -3
- package/dist/providers/google.js +2 -2
- package/dist/providers/groq.js +2 -2
- package/dist/providers/index.d.ts +2 -0
- package/dist/providers/index.js +2 -0
- package/dist/providers/meta.js +1 -1
- package/dist/providers/minimax/chat.js +1 -1
- package/dist/providers/minimax/responses.js +1 -1
- package/dist/providers/minimax.js +1 -1
- package/dist/providers/mistral.js +2 -2
- package/dist/providers/moonshot/messages.js +1 -1
- package/dist/providers/moonshot/responses.js +1 -1
- package/dist/providers/moonshot.js +1 -1
- package/dist/providers/openai-compatible-responses.js +2 -2
- package/dist/providers/openai-compatible.js +2 -2
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openai.js +2 -2
- package/dist/providers/openrouter.js +1 -1
- package/dist/providers/togetherai.js +2 -2
- package/dist/providers/venice.js +1 -1
- package/dist/providers/vercel-ai-gateway.js +2 -2
- package/dist/providers/xai.js +1 -1
- package/dist/providers/zai-coding-plan/messages.js +1 -1
- package/dist/providers/zai-coding-plan/responses.js +1 -1
- package/dist/providers/zai-coding-plan.js +1 -1
- package/dist/providers/zai.js +1 -1
- package/dist/route/auth.d.ts +1 -1
- package/dist/route/auth.js +2 -2
- package/dist/route/executor-service.d.ts +1 -1
- package/dist/route/executor.d.ts +1 -1
- package/dist/route/executor.js +1 -1
- package/dist/route/framing.js +1 -1
- package/dist/route/media-protocol.d.ts +1 -1
- package/dist/route/media-protocol.js +1 -1
- package/dist/route/media.js +1 -1
- package/dist/route/transport/http.d.ts +1 -1
- package/dist/route/transport/http.js +1 -1
- package/dist/route/transport/websocket-channel.d.ts +1 -1
- package/dist/route/transport/websocket.d.ts +4 -4
- package/dist/route/transport/websocket.js +4 -9
- package/dist/schema/messages.js +9 -8
- package/dist/tool.d.ts +10 -0
- package/dist/tool.js +21 -2
- package/package.json +5 -5
|
@@ -275,7 +275,7 @@ export declare const routes: (Route<{
|
|
|
275
275
|
} | {
|
|
276
276
|
readonly type: "image_generation";
|
|
277
277
|
readonly size?: string | undefined;
|
|
278
|
-
readonly action?: "
|
|
278
|
+
readonly action?: "auto" | "generate" | "edit" | undefined;
|
|
279
279
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
280
280
|
readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
|
|
281
281
|
readonly background?: "auto" | "opaque" | "transparent" | undefined;
|
package/dist/providers/openai.js
CHANGED
|
@@ -77,9 +77,9 @@ const config = ({ apiKey, baseURL, body, headers: given, organization, project,
|
|
|
77
77
|
apiKey,
|
|
78
78
|
baseURL,
|
|
79
79
|
headers: Object.keys(headers).length === 0 ? undefined : headers,
|
|
80
|
-
http: body === undefined ? undefined : { body
|
|
80
|
+
http: body === undefined ? undefined : { body },
|
|
81
81
|
providerOptions,
|
|
82
|
-
queryParams
|
|
82
|
+
queryParams,
|
|
83
83
|
};
|
|
84
84
|
};
|
|
85
85
|
export const model = (modelID, settings) => {
|
|
@@ -114,6 +114,6 @@ export const model = (modelID, { apiKey, baseURL, body, headers, ...providerOpti
|
|
|
114
114
|
apiKey,
|
|
115
115
|
baseURL,
|
|
116
116
|
headers,
|
|
117
|
-
http: body === undefined ? undefined : { body
|
|
117
|
+
http: body === undefined ? undefined : { body },
|
|
118
118
|
providerOptions,
|
|
119
119
|
}).model(modelID);
|
|
@@ -34,7 +34,7 @@ export const provider = configure();
|
|
|
34
34
|
export const model = (modelID, { apiKey, baseURL, body, headers, ...providerOptions }) => configure({
|
|
35
35
|
apiKey,
|
|
36
36
|
baseURL,
|
|
37
|
-
headers
|
|
38
|
-
http: body === undefined ? undefined : { body
|
|
37
|
+
headers,
|
|
38
|
+
http: body === undefined ? undefined : { body },
|
|
39
39
|
providerOptions,
|
|
40
40
|
}).model(modelID);
|
package/dist/providers/venice.js
CHANGED
|
@@ -32,7 +32,7 @@ export const model = (modelID, { apiKey, baseURL, queryParams, body, headers, ..
|
|
|
32
32
|
baseURL,
|
|
33
33
|
queryParams,
|
|
34
34
|
headers,
|
|
35
|
-
http: body === undefined ? undefined : { body
|
|
35
|
+
http: body === undefined ? undefined : { body },
|
|
36
36
|
providerOptions,
|
|
37
37
|
}).model(modelID);
|
|
38
38
|
export * as Venice from "./venice.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect, Schema } from "effect";
|
|
2
|
-
import { Headers, HttpClientRequest } from "effect/
|
|
2
|
+
import { Headers, HttpClientRequest } from "effect/http";
|
|
3
3
|
import { EvaluationAnswer, EvaluationInput, EvaluationModel, EvaluationQuestion, EvaluationResponse, EvaluationRounding, } from "../experimental/evaluation.js";
|
|
4
4
|
import { AnthropicMessages } from "../protocols/anthropic-messages.js";
|
|
5
5
|
import { OpenAIChat } from "../protocols/openai-chat.js";
|
|
@@ -218,7 +218,7 @@ function fromSettings({ apiKey, baseURL, headers, body, ...providerOptions }) {
|
|
|
218
218
|
apiKey,
|
|
219
219
|
baseURL,
|
|
220
220
|
headers,
|
|
221
|
-
http: body === undefined ? undefined : { body
|
|
221
|
+
http: body === undefined ? undefined : { body },
|
|
222
222
|
providerOptions,
|
|
223
223
|
});
|
|
224
224
|
}
|
package/dist/providers/xai.js
CHANGED
|
@@ -77,7 +77,7 @@ export const model = (modelID, { apiKey, baseURL, body, headers, ...providerOpti
|
|
|
77
77
|
apiKey,
|
|
78
78
|
baseURL,
|
|
79
79
|
headers,
|
|
80
|
-
http: body === undefined ? undefined : { body
|
|
80
|
+
http: body === undefined ? undefined : { body },
|
|
81
81
|
providerOptions,
|
|
82
82
|
}).model(modelID);
|
|
83
83
|
export const responses = provider.responses;
|
|
@@ -3,6 +3,6 @@ export const model = (modelID, { apiKey, baseURL, body, headers, ...providerOpti
|
|
|
3
3
|
apiKey,
|
|
4
4
|
baseURL,
|
|
5
5
|
headers,
|
|
6
|
-
http: body === undefined ? undefined : { body
|
|
6
|
+
http: body === undefined ? undefined : { body },
|
|
7
7
|
providerOptions,
|
|
8
8
|
}).messages(modelID);
|
|
@@ -3,6 +3,6 @@ export const model = (modelID, { apiKey, baseURL, body, headers, ...providerOpti
|
|
|
3
3
|
apiKey,
|
|
4
4
|
baseURL,
|
|
5
5
|
headers,
|
|
6
|
-
http: body === undefined ? undefined : { body
|
|
6
|
+
http: body === undefined ? undefined : { body },
|
|
7
7
|
providerOptions,
|
|
8
8
|
}).responses(modelID);
|
|
@@ -57,7 +57,7 @@ export const model = (modelID, { apiKey, baseURL, body, headers, ...providerOpti
|
|
|
57
57
|
apiKey,
|
|
58
58
|
baseURL,
|
|
59
59
|
headers,
|
|
60
|
-
http: body === undefined ? undefined : { body
|
|
60
|
+
http: body === undefined ? undefined : { body },
|
|
61
61
|
providerOptions,
|
|
62
62
|
}).model(modelID);
|
|
63
63
|
export * as ZAICodingPlan from "./zai-coding-plan.js";
|
package/dist/providers/zai.js
CHANGED
|
@@ -43,7 +43,7 @@ export const model = (modelID, { apiKey, baseURL, body, headers, ...providerOpti
|
|
|
43
43
|
apiKey,
|
|
44
44
|
baseURL,
|
|
45
45
|
headers,
|
|
46
|
-
http: body === undefined ? undefined : { body
|
|
46
|
+
http: body === undefined ? undefined : { body },
|
|
47
47
|
providerOptions,
|
|
48
48
|
}).model(modelID);
|
|
49
49
|
export * as ZAI from "./zai.js";
|
package/dist/route/auth.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Config, Effect, Redacted } from "effect";
|
|
2
|
-
import { Headers } from "effect/
|
|
2
|
+
import { Headers } from "effect/http";
|
|
3
3
|
import { AIError, type HttpOptions } from "../schema/index.js";
|
|
4
4
|
export declare class MissingCredentialError extends Error {
|
|
5
5
|
readonly source: string;
|
package/dist/route/auth.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Config, Effect, Option, Redacted } from "effect";
|
|
2
|
-
import { Headers } from "effect/
|
|
2
|
+
import { Headers } from "effect/http";
|
|
3
3
|
import { AuthenticationError, AIError } from "../schema/index.js";
|
|
4
4
|
export class MissingCredentialError extends Error {
|
|
5
5
|
source;
|
|
@@ -48,7 +48,7 @@ export const optional = (secret, source = "optional value") => secret === undefi
|
|
|
48
48
|
? credential(Effect.fail(new MissingCredentialError(source)))
|
|
49
49
|
: credentialFromSecret(secret, source);
|
|
50
50
|
export const config = (name) => credential(Effect.gen(function* () {
|
|
51
|
-
const secret = yield* Config.option(Config.
|
|
51
|
+
const secret = yield* Config.option(Config.Redacted(name));
|
|
52
52
|
if (Option.isSome(secret) && Redacted.value(secret.value) !== "")
|
|
53
53
|
return secret.value;
|
|
54
54
|
return yield* Effect.fail(new MissingCredentialError(name, `${name} is not set`));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Context, type Effect } from "effect";
|
|
2
|
-
import type { HttpClientRequest, HttpClientResponse } from "effect/
|
|
2
|
+
import type { HttpClientRequest, HttpClientResponse } from "effect/http";
|
|
3
3
|
import 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>;
|
package/dist/route/executor.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Layer, Stream } from "effect";
|
|
2
|
-
import { HttpClient, HttpClientRequest, HttpClientResponse } from "effect/
|
|
2
|
+
import { HttpClient, HttpClientRequest, HttpClientResponse } from "effect/http";
|
|
3
3
|
import { HttpContext, AIError } from "../schema/index.js";
|
|
4
4
|
import { Service, type HttpMiddleware, type Interface } from "./executor-service.js";
|
|
5
5
|
export { Service } from "./executor-service.js";
|
package/dist/route/executor.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Cause, Effect, Layer, Option, Schema, Stream } from "effect";
|
|
2
|
-
import { FetchHttpClient, Headers, HttpClient, HttpClientError, HttpClientRequest, HttpClientResponse, } from "effect/
|
|
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
5
|
import { Service } from "./executor-service.js";
|
package/dist/route/framing.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect, Stream } from "effect";
|
|
2
|
-
import { makeParser } from "effect/
|
|
2
|
+
import { makeParser } from "effect/encoding/Sse";
|
|
3
3
|
import { AIError, InvalidProviderOutputError } from "../schema/index.js";
|
|
4
4
|
/**
|
|
5
5
|
* `framing` step for Server-Sent Events. Decodes UTF-8, runs the SSE channel
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Duration, Effect, Schema, type Stream } from "effect";
|
|
2
|
-
import { HttpClientResponse } from "effect/
|
|
2
|
+
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";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Clock, Duration, Effect, Schema } from "effect";
|
|
2
|
-
import { HttpClientResponse } from "effect/
|
|
2
|
+
import { HttpClientResponse } from "effect/http";
|
|
3
3
|
import { Media } from "../media.js";
|
|
4
4
|
import { AIError, AuthenticationError, ContentPolicyError, HttpContext, InvalidProviderOutputError, InvalidRequestError, ProviderID, ProviderInternalError, RateLimitError, UnsupportedOperationError, } from "../schema/index.js";
|
|
5
5
|
export const json = (value, query) => ({
|
package/dist/route/media.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Duration, Effect, Schedule, Schema, Stream } from "effect";
|
|
2
|
-
import { Headers, HttpClientRequest } from "effect/
|
|
2
|
+
import { Headers, HttpClientRequest } from "effect/http";
|
|
3
3
|
import { Auth } from "./auth.js";
|
|
4
4
|
import { Endpoint } from "./endpoint.js";
|
|
5
5
|
import { RequestExecutorService } from "./executor-service.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
|
-
import { Headers, HttpClientRequest } from "effect/
|
|
2
|
+
import { Headers, HttpClientRequest } from "effect/http";
|
|
3
3
|
import { Framing } from "../framing.js";
|
|
4
4
|
import type { HttpMiddleware, Transport, TransportPrepareInput } from "./index.js";
|
|
5
5
|
import { AIError } from "../../schema/index.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Clock, Duration, Effect, Stream } from "effect";
|
|
2
|
-
import { Headers, HttpClientRequest } from "effect/
|
|
2
|
+
import { Headers, HttpClientRequest } from "effect/http";
|
|
3
3
|
import { Auth } from "../auth.js";
|
|
4
4
|
import { render as renderEndpoint } from "../endpoint.js";
|
|
5
5
|
import { Framing } from "../framing.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Effect, Scope, Stream } from "effect";
|
|
2
|
-
import type { Headers } from "effect/
|
|
2
|
+
import type { Headers } from "effect/http";
|
|
3
3
|
import type { AIError, HttpContext } from "../../schema/index.js";
|
|
4
4
|
export interface WebSocketChannelExecutor {
|
|
5
5
|
readonly execute: (exchange: WebSocketChannelExchange) => Effect.Effect<WebSocketChannelExecution, AIError, Scope.Scope>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Effect, Stream } from "effect";
|
|
2
|
-
import { Headers } from "effect/
|
|
3
|
-
import { Socket } from "effect/
|
|
2
|
+
import { Headers } from "effect/http";
|
|
3
|
+
import { Socket } from "effect/socket";
|
|
4
4
|
import { AIError, type HttpContext } from "../../schema/index.js";
|
|
5
5
|
import type { Transport } from "./index.js";
|
|
6
6
|
import type { WebSocketChannelExecutor } from "./websocket-channel.js";
|
|
@@ -19,7 +19,7 @@ export interface WebSocketConnector {
|
|
|
19
19
|
}
|
|
20
20
|
export declare const toWebSocketUrl: (value: string) => Effect.Effect<string, AIError, never>;
|
|
21
21
|
export declare const open: (input: WebSocketRequest) => Effect.Effect<WebSocketConnection, AIError, Socket.WebSocketConstructor>;
|
|
22
|
-
export declare const fromWebSocket: (ws:
|
|
22
|
+
export declare const fromWebSocket: (ws: Socket.WebSocketLike, input: WebSocketRequest) => Effect.Effect<WebSocketConnection, AIError>;
|
|
23
23
|
export declare const messageText: (message: string | Uint8Array, decoder: TextDecoder) => string;
|
|
24
24
|
export declare const makeDirect: (connector: WebSocketConnector) => WebSocketChannelExecutor;
|
|
25
25
|
export declare const direct: Effect.Effect<WebSocketChannelExecutor, never, Socket.WebSocketConstructor>;
|
|
@@ -50,7 +50,7 @@ export declare const WebSocketTransport: {
|
|
|
50
50
|
readonly direct: Effect.Effect<WebSocketChannelExecutor, never, Socket.WebSocketConstructor>;
|
|
51
51
|
readonly makeDirect: (connector: WebSocketConnector) => WebSocketChannelExecutor;
|
|
52
52
|
readonly open: (input: WebSocketRequest) => Effect.Effect<WebSocketConnection, AIError, Socket.WebSocketConstructor>;
|
|
53
|
-
readonly fromWebSocket: (ws:
|
|
53
|
+
readonly fromWebSocket: (ws: Socket.WebSocketLike, input: WebSocketRequest) => Effect.Effect<WebSocketConnection, AIError>;
|
|
54
54
|
readonly messageText: (message: string | Uint8Array, decoder: TextDecoder) => string;
|
|
55
55
|
readonly toWebSocketUrl: (value: string) => Effect.Effect<string, AIError, never>;
|
|
56
56
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Cause, Effect, Queue, Stream } from "effect";
|
|
2
|
-
import { Headers } from "effect/
|
|
3
|
-
import { Socket } from "effect/
|
|
2
|
+
import { Headers } from "effect/http";
|
|
3
|
+
import { Socket } from "effect/socket";
|
|
4
4
|
import { AIError, AIErrorReason, TransportError, } from "../../schema/index.js";
|
|
5
5
|
import * as HttpTransport from "./http.js";
|
|
6
6
|
const MAX_FRAME_BYTES = 16 * 1024 * 1024;
|
|
@@ -31,7 +31,7 @@ const annotateTransportError = (error, input) => error.reason._tag === "Transpor
|
|
|
31
31
|
const eventMessage = (event) => {
|
|
32
32
|
if ("message" in event && typeof event.message === "string")
|
|
33
33
|
return event.message;
|
|
34
|
-
return event.type;
|
|
34
|
+
return event.type ?? "error";
|
|
35
35
|
};
|
|
36
36
|
const binaryMessage = (data) => {
|
|
37
37
|
if (data instanceof Uint8Array)
|
|
@@ -127,12 +127,7 @@ export const toWebSocketUrl = (value) => Effect.try({
|
|
|
127
127
|
export const open = (input) => Effect.gen(function* () {
|
|
128
128
|
const constructor = yield* Socket.WebSocketConstructor;
|
|
129
129
|
const ws = yield* Effect.try({
|
|
130
|
-
try: () =>
|
|
131
|
-
// Platform implementations may extend Effect's browser-compatible constructor with handshake options.
|
|
132
|
-
// oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion
|
|
133
|
-
constructor(input.url, {
|
|
134
|
-
headers: input.headers,
|
|
135
|
-
}),
|
|
130
|
+
try: () => constructor(input.url, { headers: input.headers }),
|
|
136
131
|
catch: (error) => transportError(error instanceof Error ? error.message : "Failed to construct WebSocket", {
|
|
137
132
|
cause: error,
|
|
138
133
|
url: input.url,
|
package/dist/schema/messages.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
|
+
import { withStatics } from "@opencode/schema/schema";
|
|
2
3
|
import { Tool } from "@opencode/schema/tool";
|
|
3
4
|
import { CacheHint, CachePolicy, GenerationOptions, HttpOptions, JsonSchema, LanguageModelSchema, ProviderMetadata, ProviderOptions, ReasoningEffort, } from "./options.js";
|
|
4
5
|
import { ProviderID } from "./ids.js";
|
|
@@ -11,7 +12,7 @@ const systemPartSchema = Schema.Struct({
|
|
|
11
12
|
metadata: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),
|
|
12
13
|
}).annotate({ identifier: "LLM.SystemPart" });
|
|
13
14
|
const makeSystemPart = (text) => ({ type: "text", text });
|
|
14
|
-
export const SystemPart =
|
|
15
|
+
export const SystemPart = withStatics(systemPartSchema, {
|
|
15
16
|
make: makeSystemPart,
|
|
16
17
|
content: (input) => {
|
|
17
18
|
if (input === undefined)
|
|
@@ -53,7 +54,7 @@ const toolResultValueSchema = Schema.Union([
|
|
|
53
54
|
}),
|
|
54
55
|
]).annotate({ identifier: "LLM.ToolResult" });
|
|
55
56
|
const isToolResultValue = Schema.is(toolResultValueSchema);
|
|
56
|
-
export const ToolResultValue =
|
|
57
|
+
export const ToolResultValue = withStatics(toolResultValueSchema, {
|
|
57
58
|
is: isToolResultValue,
|
|
58
59
|
make: (value, type = "json") => {
|
|
59
60
|
if (isToolResultValue(value))
|
|
@@ -63,7 +64,7 @@ export const ToolResultValue = Object.assign(toolResultValueSchema, {
|
|
|
63
64
|
return { type, value };
|
|
64
65
|
},
|
|
65
66
|
});
|
|
66
|
-
export const ToolOutput =
|
|
67
|
+
export const ToolOutput = withStatics(Schema.Struct({
|
|
67
68
|
structured: Schema.Unknown,
|
|
68
69
|
content: Schema.Array(Tool.Content),
|
|
69
70
|
}).annotate({ identifier: "LLM.ToolOutput" }), {
|
|
@@ -98,7 +99,7 @@ const toolResultText = (value) => {
|
|
|
98
99
|
return String(value);
|
|
99
100
|
}
|
|
100
101
|
};
|
|
101
|
-
export const ToolCallPart =
|
|
102
|
+
export const ToolCallPart = withStatics(Schema.Struct({
|
|
102
103
|
type: Schema.Literal("tool-call"),
|
|
103
104
|
id: Schema.String,
|
|
104
105
|
name: Schema.String,
|
|
@@ -111,7 +112,7 @@ export const ToolCallPart = Object.assign(Schema.Struct({
|
|
|
111
112
|
}).annotate({ identifier: "LLM.Content.ToolCall" }), {
|
|
112
113
|
make: (input) => ({ type: "tool-call", ...input }),
|
|
113
114
|
});
|
|
114
|
-
export const ToolResultPart =
|
|
115
|
+
export const ToolResultPart = withStatics(Schema.Struct({
|
|
115
116
|
type: Schema.Literal("tool-result"),
|
|
116
117
|
id: Schema.String,
|
|
117
118
|
name: Schema.String,
|
|
@@ -152,7 +153,7 @@ const compactionPartSchema = Schema.Struct({
|
|
|
152
153
|
})
|
|
153
154
|
.pipe(Schema.refine((part) => (part.encrypted !== undefined) !== (part.text !== undefined), { message: "Compaction requires either encrypted content or a summary" }))
|
|
154
155
|
.annotate({ identifier: "LLM.Content.Compaction" });
|
|
155
|
-
export const CompactionPart =
|
|
156
|
+
export const CompactionPart = withStatics(compactionPartSchema, {
|
|
156
157
|
make: (input) => Schema.decodeUnknownSync(compactionPartSchema)({ type: "compaction", ...input }),
|
|
157
158
|
});
|
|
158
159
|
/** Reasoning effort changed here, from `previous` to `effort`; `undefined` is the model default. */
|
|
@@ -225,7 +226,7 @@ export class ToolDefinition extends Schema.Class("LLM.ToolDefinition")({
|
|
|
225
226
|
/** Normalize tool definition input into the canonical `ToolDefinition` class. */
|
|
226
227
|
ToolDefinition.make = (input) => (input instanceof ToolDefinition ? input : new ToolDefinition(input));
|
|
227
228
|
})(ToolDefinition || (ToolDefinition = {}));
|
|
228
|
-
export const ToolNamespace =
|
|
229
|
+
export const ToolNamespace = withStatics(Schema.Struct({
|
|
229
230
|
type: Schema.Literal("namespace"),
|
|
230
231
|
name: Schema.String,
|
|
231
232
|
description: Schema.optional(Schema.UndefinedOr(Schema.String)),
|
|
@@ -237,7 +238,7 @@ export const ToolNamespace = Object.assign(Schema.Struct({
|
|
|
237
238
|
tools: input.tools.map(ToolEntry.make),
|
|
238
239
|
}),
|
|
239
240
|
});
|
|
240
|
-
export const ToolEntry =
|
|
241
|
+
export const ToolEntry = withStatics(Schema.Union([ToolDefinition, ToolNamespace]).pipe(Schema.toTaggedUnion("type"), Schema.annotate({ identifier: "LLM.ToolEntry" })), {
|
|
241
242
|
make: (input) => "type" in input && input.type === "namespace" ? ToolNamespace.make(input) : ToolDefinition.make(input),
|
|
242
243
|
});
|
|
243
244
|
export class ToolChoice extends Schema.Class("LLM.ToolChoice")({
|
package/dist/tool.d.ts
CHANGED
|
@@ -132,5 +132,15 @@ export type Tools = Record<string, AnyTool>;
|
|
|
132
132
|
* is reused.
|
|
133
133
|
*/
|
|
134
134
|
export declare const toDefinitions: (tools: Tools) => ReadonlyArray<ToolDefinitionClass>;
|
|
135
|
+
/**
|
|
136
|
+
* Describes a no-argument Effect tool input as an empty object, or returns
|
|
137
|
+
* `undefined` when the input takes arguments.
|
|
138
|
+
*
|
|
139
|
+
* Effect emits `{ not: { type: "null" } }` only for an encoded struct with no
|
|
140
|
+
* properties or index signatures, but providers require tool parameters to
|
|
141
|
+
* describe an object. Annotations are kept; any other keyword, such as a
|
|
142
|
+
* check's `minProperties`, leaves the schema as Effect emitted it.
|
|
143
|
+
*/
|
|
144
|
+
export declare const emptyInputJsonSchema: (schema: Schema.Top) => JsonSchema.JsonSchema | undefined;
|
|
135
145
|
export { ToolFailure };
|
|
136
146
|
export * as Tool from "./tool.js";
|
package/dist/tool.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Effect, JsonSchema, Schema } from "effect";
|
|
2
2
|
import { Tool } from "@opencode/schema/tool";
|
|
3
3
|
import { ToolDefinition, ToolFailure, ToolOutput } from "./schema/index.js";
|
|
4
|
+
import { isRecord } from "./utils/record.js";
|
|
4
5
|
export function make(config) {
|
|
5
6
|
if ("jsonSchema" in config) {
|
|
6
7
|
return {
|
|
@@ -36,7 +37,7 @@ export function make(config) {
|
|
|
36
37
|
_definition: new ToolDefinition({
|
|
37
38
|
name: "",
|
|
38
39
|
description: config.description,
|
|
39
|
-
inputSchema: toJsonSchema(config.parameters),
|
|
40
|
+
inputSchema: emptyInputJsonSchema(config.parameters) ?? toJsonSchema(config.parameters),
|
|
40
41
|
outputSchema: toJsonSchema(config.success),
|
|
41
42
|
}),
|
|
42
43
|
};
|
|
@@ -55,8 +56,26 @@ export const toDefinitions = (tools) => Object.entries(tools).map(([name, item])
|
|
|
55
56
|
inputSchema: item._definition.inputSchema,
|
|
56
57
|
outputSchema: item._definition.outputSchema,
|
|
57
58
|
}));
|
|
59
|
+
/**
|
|
60
|
+
* Describes a no-argument Effect tool input as an empty object, or returns
|
|
61
|
+
* `undefined` when the input takes arguments.
|
|
62
|
+
*
|
|
63
|
+
* Effect emits `{ not: { type: "null" } }` only for an encoded struct with no
|
|
64
|
+
* properties or index signatures, but providers require tool parameters to
|
|
65
|
+
* describe an object. Annotations are kept; any other keyword, such as a
|
|
66
|
+
* check's `minProperties`, leaves the schema as Effect emitted it.
|
|
67
|
+
*/
|
|
68
|
+
export const emptyInputJsonSchema = (schema) => {
|
|
69
|
+
const { not, ...rest } = Schema.toJsonSchemaDocument(schema, { referencePolicy: () => undefined }).schema;
|
|
70
|
+
if (!isRecord(not) || not.type !== "null" || Object.keys(not).length !== 1)
|
|
71
|
+
return undefined;
|
|
72
|
+
if (!Object.keys(rest).every((key) => annotationKeywords.has(key)))
|
|
73
|
+
return undefined;
|
|
74
|
+
return { ...rest, type: "object", properties: {}, additionalProperties: false };
|
|
75
|
+
};
|
|
76
|
+
const annotationKeywords = new Set(["title", "description", "default", "examples", "readOnly", "writeOnly"]);
|
|
58
77
|
const toJsonSchema = (schema) => {
|
|
59
|
-
const document = Schema.toJsonSchemaDocument(schema);
|
|
78
|
+
const document = Schema.toJsonSchemaDocument(schema, { onExcessProperty: "error" });
|
|
60
79
|
if (Object.keys(document.definitions).length === 0)
|
|
61
80
|
return document.schema;
|
|
62
81
|
return { ...document.schema, $defs: document.definitions };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.27",
|
|
4
4
|
"name": "@opencode/ai",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@clack/prompts": "1.0.0-alpha.1",
|
|
36
|
-
"@effect/platform-node": "4.0.
|
|
37
|
-
"@opencode/http-recorder": "2.0.
|
|
36
|
+
"@effect/platform-node": "4.0.1",
|
|
37
|
+
"@opencode/http-recorder": "2.0.27",
|
|
38
38
|
"@tsconfig/bun": "1.0.9",
|
|
39
39
|
"@types/bun": "1.4.0",
|
|
40
40
|
"@typescript/native-preview": "7.0.0-dev.20251207.1",
|
|
@@ -44,9 +44,9 @@
|
|
|
44
44
|
"@aws-sdk/credential-providers": "3.1057.0",
|
|
45
45
|
"@smithy/eventstream-codec": "4.2.14",
|
|
46
46
|
"@smithy/util-utf8": "4.2.2",
|
|
47
|
-
"@opencode/schema": "2.0.
|
|
47
|
+
"@opencode/schema": "2.0.27",
|
|
48
48
|
"aws4fetch": "1.0.20",
|
|
49
|
-
"effect": "4.0.
|
|
49
|
+
"effect": "4.0.1",
|
|
50
50
|
"google-auth-library": "10.5.0"
|
|
51
51
|
}
|
|
52
52
|
}
|