@opencode/ai 0.0.0-dev-20136 → 0.0.0-dev-20138
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 +12 -13
- package/dist/llm.d.ts +7 -6
- package/dist/llm.js +9 -4
- package/dist/promise.d.ts +8 -8
- package/dist/promise.js +5 -3
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -9,15 +9,13 @@ import { OpenAI } from "@opencode/ai/providers"
|
|
|
9
9
|
|
|
10
10
|
const openai = OpenAI.configure({ apiKey: process.env.OPENAI_API_KEY })
|
|
11
11
|
|
|
12
|
-
const request = LLM.request({
|
|
13
|
-
model: openai.responses("gpt-4o-mini"), // `.chat(...)` selects the Chat Completions API instead
|
|
14
|
-
system: "You are concise.",
|
|
15
|
-
prompt: "Say hello in one short sentence.",
|
|
16
|
-
generation: { maxTokens: 40 },
|
|
17
|
-
})
|
|
18
|
-
|
|
19
12
|
const program = Effect.gen(function* () {
|
|
20
|
-
const response = yield* LLM.generate(
|
|
13
|
+
const response = yield* LLM.generate({
|
|
14
|
+
model: openai.responses("gpt-4o-mini"), // `.chat(...)` selects the Chat Completions API instead
|
|
15
|
+
system: "You are concise.",
|
|
16
|
+
prompt: "Say hello in one short sentence.",
|
|
17
|
+
generation: { maxTokens: 40 },
|
|
18
|
+
})
|
|
21
19
|
console.log(response.text)
|
|
22
20
|
})
|
|
23
21
|
|
|
@@ -25,7 +23,8 @@ const program = Effect.gen(function* () {
|
|
|
25
23
|
await Effect.runPromise(program.pipe(Effect.provide(AIClient.layer)))
|
|
26
24
|
```
|
|
27
25
|
|
|
28
|
-
Run `LLM.stream(
|
|
26
|
+
Run `LLM.stream(...)` instead of `generate` when you want incremental `LLMEvent`s. Both accept input or a prebuilt
|
|
27
|
+
`LLM.request(...)`. The event stream is provider-neutral — same shape across OpenAI Chat, OpenAI Responses,
|
|
29
28
|
Anthropic Messages, Gemini, Bedrock Converse, and any OpenAI-compatible deployment.
|
|
30
29
|
|
|
31
30
|
The same configured facade names image, video, speech, and transcription models. `Image.generate` resolves the
|
|
@@ -72,11 +71,11 @@ helpers; `ai.file` and `ai.write` load `node:fs/promises` on first use, so no Ef
|
|
|
72
71
|
import { AI } from "@opencode/ai/promise"
|
|
73
72
|
|
|
74
73
|
const ai = AI.make()
|
|
75
|
-
const
|
|
76
|
-
const text = await ai.llm.generate(
|
|
74
|
+
const input = { model: openai.responses("gpt-4o-mini"), prompt: "Say hello." }
|
|
75
|
+
const text = await ai.llm.generate(input)
|
|
77
76
|
const generated = await ai.image.generate({ model: openai.image("gpt-image-2"), prompt: "A lighthouse" })
|
|
78
77
|
await ai.write(generated.image, "./lighthouse.png") // also ai.file(path), ai.bytes(asset), ai.base64(asset), ai.materialize(asset)
|
|
79
|
-
for await (const event of ai.llm.stream(request)) {
|
|
78
|
+
for await (const event of ai.llm.stream(ai.llm.request(input))) {
|
|
80
79
|
// LLMEvent
|
|
81
80
|
}
|
|
82
81
|
await ai.dispose()
|
|
@@ -937,7 +936,7 @@ const transcript = await generation.await({ poll: { interval: 3_000 } })
|
|
|
937
936
|
## Public API
|
|
938
937
|
|
|
939
938
|
- **`LLM.request({...})`** — build a provider-neutral `LLMRequest`. Accepts ergonomic inputs (`system: string`, `prompt: string`) that normalize into the canonical Schema classes.
|
|
940
|
-
- **`LLM.generate` / `LLM.stream`** —
|
|
939
|
+
- **`LLM.generate` / `LLM.stream`** — run direct input or an `LLMRequest` through `LLMClient` for one-import use.
|
|
941
940
|
- **`Message.user(...)` / `Message.assistant(...)` / `Message.tool(...)`** — message constructors from the canonical schema model.
|
|
942
941
|
- **`LanguageModel.make(...)` / `ToolCallPart.make(...)` / `ToolResultPart.make(...)` / `ToolDefinition.make(...)`** — model and tool-related constructors from the canonical schema model.
|
|
943
942
|
- **`LLMEvent.is.*`** — typed guards (`is.textDelta`, `is.toolCall`, `is.finish`, …) for filtering streams.
|
package/dist/llm.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Effect, JsonSchema, Schema } from "effect";
|
|
2
|
-
import { Service } from "./route/client.js";
|
|
3
|
-
import { GenerationOptions, HttpOptions, AIError, LLMRequest, LLMResponse, Message, LanguageModel, SystemPart, ToolChoice, type ContentPart, type LanguageModelProviderOptions, type ToolEntryInput } from "./schema/index.js";
|
|
1
|
+
import { Effect, JsonSchema, Schema, Stream } from "effect";
|
|
2
|
+
import { Service, type StreamOptions } from "./route/client.js";
|
|
3
|
+
import { GenerationOptions, HttpOptions, AIError, LLMEvent, LLMRequest, LLMResponse, Message, LanguageModel, SystemPart, ToolChoice, type ContentPart, type LanguageModelProviderOptions, type ToolEntryInput } from "./schema/index.js";
|
|
4
4
|
import { type ToolSchema } from "./tool.js";
|
|
5
5
|
/** Input accepted by `LLM.request`, normalized into the canonical `LLMRequest` class. */
|
|
6
6
|
export type RequestInput<SelectedLanguageModel extends LanguageModel = LanguageModel> = Omit<ConstructorParameters<typeof LLMRequest>[0], "model" | "system" | "messages" | "tools" | "toolChoice" | "generation" | "http" | "providerOptions"> & {
|
|
@@ -14,9 +14,10 @@ export type RequestInput<SelectedLanguageModel extends LanguageModel = LanguageM
|
|
|
14
14
|
readonly providerOptions?: NoInfer<LanguageModelProviderOptions<SelectedLanguageModel>>;
|
|
15
15
|
readonly http?: HttpOptions.Input;
|
|
16
16
|
};
|
|
17
|
-
|
|
18
|
-
export declare
|
|
19
|
-
export declare const
|
|
17
|
+
export declare function generate<const Model extends LanguageModel>(input: RequestInput<Model>, options?: StreamOptions): Effect.Effect<LLMResponse, AIError, Service>;
|
|
18
|
+
export declare function generate(input: LLMRequest, options?: StreamOptions): Effect.Effect<LLMResponse, AIError, Service>;
|
|
19
|
+
export declare function stream<const Model extends LanguageModel>(input: RequestInput<Model>, options?: StreamOptions): Stream.Stream<LLMEvent, AIError, Service>;
|
|
20
|
+
export declare function stream(input: LLMRequest, options?: StreamOptions): Stream.Stream<LLMEvent, AIError, Service>;
|
|
20
21
|
export declare const request: <const SelectedLanguageModel extends LanguageModel>(input: RequestInput<SelectedLanguageModel>) => LLMRequest<SelectedLanguageModel>;
|
|
21
22
|
type GenerateObjectBase<SelectedLanguageModel extends LanguageModel = LanguageModel> = Omit<RequestInput<SelectedLanguageModel>, "tools" | "toolChoice">;
|
|
22
23
|
export declare class GenerateObjectResponse<T> {
|
package/dist/llm.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { Effect, JsonSchema, Schema } from "effect";
|
|
1
|
+
import { Effect, JsonSchema, Schema, Stream } from "effect";
|
|
2
|
+
import { tryRequest } from "./media-model.js";
|
|
2
3
|
import { LLMClient, Service } from "./route/client.js";
|
|
3
4
|
import { GenerationOptions, HttpOptions, InvalidProviderOutputError, AIError, LLMEvent, LLMRequest, LLMResponse, Message, LanguageModel, SystemPart, ToolChoice, ToolEntry, } from "./schema/index.js";
|
|
4
5
|
import { make as makeTool, toDefinitions } from "./tool.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
export function generate(input, options) {
|
|
7
|
+
return requestEffect(input).pipe(Effect.flatMap((request) => LLMClient.generate(request, options)));
|
|
8
|
+
}
|
|
9
|
+
export function stream(input, options) {
|
|
10
|
+
return Stream.unwrap(requestEffect(input).pipe(Effect.map((request) => LLMClient.stream(request, options))));
|
|
11
|
+
}
|
|
12
|
+
const requestEffect = (input) => input instanceof LLMRequest ? Effect.succeed(input) : tryRequest(() => request(input));
|
|
8
13
|
export const request = (input) => {
|
|
9
14
|
const { system: requestSystem, prompt, messages, tools, toolChoice: requestToolChoice, generation: requestGeneration, providerOptions: requestProviderOptions, http: requestHttp, ...rest } = input;
|
|
10
15
|
return new LLMRequest({
|
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";
|
|
6
5
|
import { Media } from "./media.js";
|
|
7
6
|
import { RequestExecutor } from "./route/executor.js";
|
|
8
|
-
import {
|
|
7
|
+
import { LanguageModel, LLMRequest } from "./schema/index.js";
|
|
8
|
+
import type { RequestInput } from "./llm.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
|
|
53
|
-
generate: (
|
|
54
|
-
stream: (
|
|
52
|
+
request: <const SelectedLanguageModel extends LanguageModel>(input: RequestInput<SelectedLanguageModel>) => LLMRequest<SelectedLanguageModel>;
|
|
53
|
+
generate: <const Model extends LanguageModel>(input: RequestInput<Model> | LLMRequest, options?: RunOptions) => Promise<import("./index.js").LLMResponse>;
|
|
54
|
+
stream: <const Model extends LanguageModel>(input: RequestInput<Model> | 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
|
|
532
|
-
generate: (
|
|
533
|
-
stream: (
|
|
531
|
+
request: <const SelectedLanguageModel extends LanguageModel>(input: RequestInput<SelectedLanguageModel>) => LLMRequest<SelectedLanguageModel>;
|
|
532
|
+
generate: <const Model extends LanguageModel>(input: RequestInput<Model> | LLMRequest, options?: RunOptions) => Promise<import("./index.js").LLMResponse>;
|
|
533
|
+
stream: <const Model extends LanguageModel>(input: RequestInput<Model> | 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,8 +3,9 @@ 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";
|
|
6
7
|
import { RequestExecutor } from "./route/executor.js";
|
|
7
|
-
import { AIError, InvalidRequestError } from "./schema/index.js";
|
|
8
|
+
import { AIError, InvalidRequestError, LanguageModel, LLMRequest } from "./schema/index.js";
|
|
8
9
|
import { Speech, SpeechModel, SpeechRequest } from "./speech.js";
|
|
9
10
|
import { Transcription, TranscriptionModel, TranscriptionRequest, } from "./transcription.js";
|
|
10
11
|
import { fileMediaType } from "./utils/media-type.js";
|
|
@@ -35,6 +36,7 @@ export const make = (options = {}) => {
|
|
|
35
36
|
cancel: (options) => run(generation.cancel(), options),
|
|
36
37
|
});
|
|
37
38
|
// 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));
|
|
38
40
|
const imageRequest = (input) => input instanceof ImageRequest ? input : Image.request(input);
|
|
39
41
|
const videoRequest = (input) => input instanceof VideoRequest ? input : Video.request(input);
|
|
40
42
|
const speechRequest = (input) => input instanceof SpeechRequest ? input : Speech.request(input);
|
|
@@ -67,8 +69,8 @@ export const make = (options = {}) => {
|
|
|
67
69
|
},
|
|
68
70
|
llm: {
|
|
69
71
|
request: LLM.request,
|
|
70
|
-
generate: (
|
|
71
|
-
stream: (
|
|
72
|
+
generate: (input, options) => run(Effect.flatMap(llmRequest(input), LLM.generate), options),
|
|
73
|
+
stream: (input, options) => iterate(Stream.unwrap(Effect.map(llmRequest(input), LLM.stream)), options),
|
|
72
74
|
},
|
|
73
75
|
image: {
|
|
74
76
|
request: Image.request,
|
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-20138",
|
|
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-20138",
|
|
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-20138",
|
|
48
48
|
"aws4fetch": "1.0.20",
|
|
49
49
|
"effect": "4.0.0-rc.112",
|
|
50
50
|
"google-auth-library": "10.5.0"
|