@opencode/ai 0.0.0-dev-20127 → 0.0.0-dev-20131
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 +3 -2
- package/dist/llm.d.ts +1 -0
- package/dist/llm.js +1 -0
- package/dist/promise.d.ts +8 -8
- package/dist/promise.js +3 -5
- package/dist/providers/openrouter.js +9 -4
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -72,10 +72,11 @@ helpers; `ai.file` and `ai.write` load `node:fs/promises` on first use, so no Ef
|
|
|
72
72
|
import { AI } from "@opencode/ai/promise"
|
|
73
73
|
|
|
74
74
|
const ai = AI.make()
|
|
75
|
-
const
|
|
75
|
+
const request = ai.llm.request({ model: openai.responses("gpt-4o-mini"), prompt: "Say hello." })
|
|
76
|
+
const text = await ai.llm.generate(request)
|
|
76
77
|
const generated = await ai.image.generate({ model: openai.image("gpt-image-2"), prompt: "A lighthouse" })
|
|
77
78
|
await ai.write(generated.image, "./lighthouse.png") // also ai.file(path), ai.bytes(asset), ai.base64(asset), ai.materialize(asset)
|
|
78
|
-
for await (const event of ai.llm.stream(
|
|
79
|
+
for await (const event of ai.llm.stream(request)) {
|
|
79
80
|
// LLMEvent
|
|
80
81
|
}
|
|
81
82
|
await ai.dispose()
|
package/dist/llm.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export type RequestInput<SelectedLanguageModel extends LanguageModel = LanguageM
|
|
|
14
14
|
readonly providerOptions?: NoInfer<LanguageModelProviderOptions<SelectedLanguageModel>>;
|
|
15
15
|
readonly http?: HttpOptions.Input;
|
|
16
16
|
};
|
|
17
|
+
/** Run an `LLMRequest` built with `LLM.request(...)`. */
|
|
17
18
|
export declare const generate: typeof import("./route/client.js").generate;
|
|
18
19
|
export declare const stream: typeof import("./route/client.js").stream;
|
|
19
20
|
export declare const request: <const SelectedLanguageModel extends LanguageModel>(input: RequestInput<SelectedLanguageModel>) => LLMRequest<SelectedLanguageModel>;
|
package/dist/llm.js
CHANGED
|
@@ -2,6 +2,7 @@ import { Effect, JsonSchema, Schema } from "effect";
|
|
|
2
2
|
import { LLMClient, Service } from "./route/client.js";
|
|
3
3
|
import { GenerationOptions, HttpOptions, InvalidProviderOutputError, AIError, LLMEvent, LLMRequest, LLMResponse, Message, LanguageModel, SystemPart, ToolChoice, ToolEntry, } from "./schema/index.js";
|
|
4
4
|
import { make as makeTool, toDefinitions } from "./tool.js";
|
|
5
|
+
/** Run an `LLMRequest` built with `LLM.request(...)`. */
|
|
5
6
|
export const generate = LLMClient.generate;
|
|
6
7
|
export const stream = LLMClient.stream;
|
|
7
8
|
export const request = (input) => {
|
package/dist/promise.d.ts
CHANGED
|
@@ -2,10 +2,10 @@ import { Effect, Layer } from "effect";
|
|
|
2
2
|
import { AIClient } from "./ai-client.js";
|
|
3
3
|
import type { AwaitOptions, Event, Snapshot } from "./generation.js";
|
|
4
4
|
import { ImageModel, ImageRequest, type ImageOptions, type ImageRequestInput } from "./image.js";
|
|
5
|
+
import { LLM } from "./index.js";
|
|
5
6
|
import { Media } from "./media.js";
|
|
6
7
|
import { RequestExecutor } from "./route/executor.js";
|
|
7
|
-
import {
|
|
8
|
-
import type { RequestInput } from "./llm.js";
|
|
8
|
+
import { type LLMRequest } from "./schema/index.js";
|
|
9
9
|
import { SpeechModel, SpeechRequest, type SpeechRequestInput } from "./speech.js";
|
|
10
10
|
import { TranscriptionModel, TranscriptionRequest, type TranscriptionOptions, type TranscriptionRequestInput } from "./transcription.js";
|
|
11
11
|
import { VideoModel, VideoRequest, type VideoOptions, type VideoRequestInput } from "./video.js";
|
|
@@ -49,9 +49,9 @@ export declare const make: (options?: Options) => {
|
|
|
49
49
|
/** Write an asset's bytes like `Media.write`, downloading `url` sources through the executor. */
|
|
50
50
|
write: (asset: Media.Asset, path: string, options?: RunOptions) => Promise<void>;
|
|
51
51
|
llm: {
|
|
52
|
-
request: <const SelectedLanguageModel extends LanguageModel>(input: RequestInput<SelectedLanguageModel>) => LLMRequest<SelectedLanguageModel>;
|
|
53
|
-
generate:
|
|
54
|
-
stream:
|
|
52
|
+
request: <const SelectedLanguageModel extends import("./index.js").LanguageModel>(input: LLM.RequestInput<SelectedLanguageModel>) => LLMRequest<SelectedLanguageModel>;
|
|
53
|
+
generate: (request: LLMRequest, options?: RunOptions) => Promise<import("./index.js").LLMResponse>;
|
|
54
|
+
stream: (request: LLMRequest, options?: RunOptions) => AsyncIterable<({
|
|
55
55
|
readonly type: "compaction";
|
|
56
56
|
readonly provider: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
57
57
|
readonly id?: string | undefined;
|
|
@@ -528,9 +528,9 @@ export declare const ai: {
|
|
|
528
528
|
/** Write an asset's bytes like `Media.write`, downloading `url` sources through the executor. */
|
|
529
529
|
write: (asset: Media.Asset, path: string, options?: RunOptions) => Promise<void>;
|
|
530
530
|
llm: {
|
|
531
|
-
request: <const SelectedLanguageModel extends LanguageModel>(input: RequestInput<SelectedLanguageModel>) => LLMRequest<SelectedLanguageModel>;
|
|
532
|
-
generate:
|
|
533
|
-
stream:
|
|
531
|
+
request: <const SelectedLanguageModel extends import("./index.js").LanguageModel>(input: LLM.RequestInput<SelectedLanguageModel>) => LLMRequest<SelectedLanguageModel>;
|
|
532
|
+
generate: (request: LLMRequest, options?: RunOptions) => Promise<import("./index.js").LLMResponse>;
|
|
533
|
+
stream: (request: LLMRequest, options?: RunOptions) => AsyncIterable<({
|
|
534
534
|
readonly type: "compaction";
|
|
535
535
|
readonly provider: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
536
536
|
readonly id?: string | undefined;
|
package/dist/promise.js
CHANGED
|
@@ -3,9 +3,8 @@ import { AIClient } from "./ai-client.js";
|
|
|
3
3
|
import { Image, ImageModel, ImageRequest } from "./image.js";
|
|
4
4
|
import { LLM } from "./index.js";
|
|
5
5
|
import { Media } from "./media.js";
|
|
6
|
-
import { tryRequest } from "./media-model.js";
|
|
7
6
|
import { RequestExecutor } from "./route/executor.js";
|
|
8
|
-
import { AIError, InvalidRequestError
|
|
7
|
+
import { AIError, InvalidRequestError } from "./schema/index.js";
|
|
9
8
|
import { Speech, SpeechModel, SpeechRequest } from "./speech.js";
|
|
10
9
|
import { Transcription, TranscriptionModel, TranscriptionRequest, } from "./transcription.js";
|
|
11
10
|
import { fileMediaType } from "./utils/media-type.js";
|
|
@@ -36,7 +35,6 @@ export const make = (options = {}) => {
|
|
|
36
35
|
cancel: (options) => run(generation.cancel(), options),
|
|
37
36
|
});
|
|
38
37
|
// The typed `generate`/`stream` overloads take a concrete input or a request, not the union; normalize once here.
|
|
39
|
-
const llmRequest = (input) => input instanceof LLMRequest ? Effect.succeed(input) : tryRequest(() => LLM.request(input));
|
|
40
38
|
const imageRequest = (input) => input instanceof ImageRequest ? input : Image.request(input);
|
|
41
39
|
const videoRequest = (input) => input instanceof VideoRequest ? input : Video.request(input);
|
|
42
40
|
const speechRequest = (input) => input instanceof SpeechRequest ? input : Speech.request(input);
|
|
@@ -69,8 +67,8 @@ export const make = (options = {}) => {
|
|
|
69
67
|
},
|
|
70
68
|
llm: {
|
|
71
69
|
request: LLM.request,
|
|
72
|
-
generate: (
|
|
73
|
-
stream: (
|
|
70
|
+
generate: (request, options) => run(LLM.generate(request), options),
|
|
71
|
+
stream: (request, options) => iterate(LLM.stream(request), options),
|
|
74
72
|
},
|
|
75
73
|
image: {
|
|
76
74
|
request: Image.request,
|
|
@@ -7,7 +7,7 @@ import { HttpOptions, ProviderID } from "../schema/index.js";
|
|
|
7
7
|
import { SystemOne } from "../experimental/system-one.js";
|
|
8
8
|
import { OpenAIChat } from "../protocols/openai-chat.js";
|
|
9
9
|
import { newBreakpoints, ttlBucket } from "../protocols/utils/cache.js";
|
|
10
|
-
import { isRecord } from "../protocols/shared.js";
|
|
10
|
+
import { isRecord, ProviderShared } from "../protocols/shared.js";
|
|
11
11
|
export const id = ProviderID.make("openrouter");
|
|
12
12
|
const baseURL = "https://openrouter.ai/api/v1";
|
|
13
13
|
const ADAPTER = "openrouter";
|
|
@@ -41,7 +41,7 @@ export const protocol = Protocol.make({
|
|
|
41
41
|
return {
|
|
42
42
|
...body,
|
|
43
43
|
messages,
|
|
44
|
-
...bodyOptions(request.providerOptions),
|
|
44
|
+
...bodyOptions(request.providerOptions, request.generation?.maxTokens),
|
|
45
45
|
};
|
|
46
46
|
})),
|
|
47
47
|
},
|
|
@@ -59,7 +59,12 @@ const cacheControl = () => {
|
|
|
59
59
|
};
|
|
60
60
|
};
|
|
61
61
|
};
|
|
62
|
-
|
|
62
|
+
// OpenRouter forwards `reasoning.max_tokens` as the upstream thinking budget. Upstreams such as Anthropic and Alibaba
|
|
63
|
+
// reject one that is not below the output limit; 1,024 is Anthropic's minimum budget.
|
|
64
|
+
const fitReasoning = (reasoning, maxTokens) => typeof reasoning.max_tokens === "number"
|
|
65
|
+
? { ...reasoning, max_tokens: ProviderShared.fitThinkingBudget(reasoning.max_tokens, maxTokens, 1_024) }
|
|
66
|
+
: reasoning;
|
|
67
|
+
const bodyOptions = (input, maxTokens) => {
|
|
63
68
|
const openrouter = isRecord(input) ? input : {};
|
|
64
69
|
const { usage, models, provider, plugins, web_search_options, debug, user, reasoning, promptCacheKey, ...options } = openrouter;
|
|
65
70
|
return {
|
|
@@ -77,7 +82,7 @@ const bodyOptions = (input) => {
|
|
|
77
82
|
...(isRecord(web_search_options) ? { web_search_options } : {}),
|
|
78
83
|
...(isRecord(debug) ? { debug } : {}),
|
|
79
84
|
...(typeof user === "string" ? { user } : {}),
|
|
80
|
-
...(isRecord(reasoning) ? { reasoning } : {}),
|
|
85
|
+
...(isRecord(reasoning) ? { reasoning: fitReasoning(reasoning, maxTokens) } : {}),
|
|
81
86
|
};
|
|
82
87
|
};
|
|
83
88
|
export const route = Route.make({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
|
-
"version": "0.0.0-dev-
|
|
3
|
+
"version": "0.0.0-dev-20131",
|
|
4
4
|
"name": "@opencode/ai",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@clack/prompts": "1.0.0-alpha.1",
|
|
36
36
|
"@effect/platform-node": "4.0.0-rc.112",
|
|
37
|
-
"@opencode/http-recorder": "0.0.0-dev-
|
|
37
|
+
"@opencode/http-recorder": "0.0.0-dev-20131",
|
|
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,7 +44,7 @@
|
|
|
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": "0.0.0-dev-
|
|
47
|
+
"@opencode/schema": "0.0.0-dev-20131",
|
|
48
48
|
"aws4fetch": "1.0.20",
|
|
49
49
|
"effect": "4.0.0-rc.112",
|
|
50
50
|
"google-auth-library": "10.5.0"
|