@opencode-ai/ai 0.0.0-next-16691 → 0.0.0-next-16719

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 CHANGED
@@ -3,8 +3,9 @@
3
3
  Schema-first AI primitives for opencode. Provider quirks live in adapters, not in calling code.
4
4
 
5
5
  ```ts
6
- import { Effect } from "effect"
6
+ import { Effect, Layer } from "effect"
7
7
  import { LLM, LLMClient } from "@opencode-ai/ai"
8
+ import { RequestExecutor } from "@opencode-ai/ai/route"
8
9
  import { OpenAI } from "@opencode-ai/ai/providers"
9
10
 
10
11
  const model = OpenAI.configure({ apiKey: process.env.OPENAI_API_KEY }).responses("gpt-4o-mini")
@@ -20,6 +21,10 @@ const program = Effect.gen(function* () {
20
21
  const response = yield* LLMClient.generate(request)
21
22
  console.log(response.text)
22
23
  })
24
+
25
+ const llmLayer = LLMClient.layer.pipe(Layer.provide(RequestExecutor.fetchLayer))
26
+
27
+ await Effect.runPromise(program.pipe(Effect.provide(llmLayer)))
23
28
  ```
24
29
 
25
30
  Run `LLMClient.stream(request)` instead of `generate` when you want incremental `LLMEvent`s. The event stream is provider-neutral — same shape across OpenAI Chat, OpenAI Responses, Anthropic Messages, Gemini, Bedrock Converse, and any OpenAI-compatible deployment.
@@ -200,6 +205,32 @@ The hosted result is represented as a provider-executed tool call and tool resul
200
205
  - **`Image.generate({...})`** — generate images through a provider-neutral image request and response model.
201
206
  - **`ImageClient`** — Effect service and layer for image execution, parallel to `LLMClient`.
202
207
 
208
+ ## Testing
209
+
210
+ Use the deterministic test client from `@opencode-ai/ai/testing` to script provider-neutral responses and inspect
211
+ the requests sent by code under test:
212
+
213
+ ```ts
214
+ import { Effect } from "effect"
215
+ import { TestLLM } from "@opencode-ai/ai/testing"
216
+
217
+ const testLLM = TestLLM.layer({
218
+ fallback: TestLLM.text("Hello from the test model", "text-1"),
219
+ })
220
+
221
+ // TestLLM.clientLayer provides LLMClient.Service and consumes TestLLM.Service.
222
+ const programWithTestClient = Effect.gen(function* () {
223
+ const result = yield* program
224
+ const test = yield* TestLLM.Service
225
+ console.log(test.requests)
226
+ return result
227
+ }).pipe(Effect.provide(TestLLM.clientLayer), Effect.provide(testLLM))
228
+ ```
229
+
230
+ `TestLLM.push(...)` scripts one-shot responses, `TestLLM.always(...)` changes the fallback, and
231
+ `TestLLM.wait(...)` lets concurrent tests wait until a request has arrived. Every received canonical request is
232
+ available on the yielded `TestLLM.Service`.
233
+
203
234
  ## Caching
204
235
 
205
236
  Prompt caching is **on by default**. Every `LLMRequest` resolves to `cache: "auto"` unless the caller opts out with `cache: "none"`. Each protocol translates `CacheHint`s to its wire format (`cache_control` on Anthropic, `cachePoint` on Bedrock; OpenAI and Gemini do implicit caching server-side and don't need inline markers — auto is a no-op there).
@@ -9,11 +9,11 @@ export interface Interface {
9
9
  declare const Service_base: Context.ServiceClass<Service, "@opencode/ImageClient", Interface>;
10
10
  export declare class Service extends Service_base {
11
11
  }
12
- export declare const generate: <Options extends ImageOptions>(request: ImageRequestFor<Options>) => Effect.Effect<ImageResponse, AIError>;
12
+ export declare const generate: <Options extends ImageOptions>(request: ImageRequestFor<Options>) => Effect.Effect<ImageResponse, AIError, Service>;
13
13
  export declare const layer: Layer.Layer<Service, never, RequestExecutor.Service>;
14
14
  export declare const ImageClient: {
15
15
  readonly Service: typeof Service;
16
16
  readonly layer: Layer.Layer<Service, never, RequestExecutor.Service>;
17
- readonly generate: <Options extends ImageOptions>(request: ImageRequestFor<Options>) => Effect.Effect<ImageResponse, AIError>;
17
+ readonly generate: <Options extends ImageOptions>(request: ImageRequestFor<Options>) => Effect.Effect<ImageResponse, AIError, Service>;
18
18
  };
19
19
  export {};
package/dist/llm.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Effect, JsonSchema, Schema } from "effect";
2
+ import { Service } from "./route/client";
2
3
  import { GenerationOptions, HttpOptions, AIError, LLMRequest, LLMResponse, Message, LanguageModel, SystemPart, ToolChoice, ToolDefinition, type ContentPart, type LanguageModelProviderOptions } from "./schema";
3
4
  import { type ToolSchema } from "./tool";
4
5
  /** Input accepted by `LLM.request`, normalized into the canonical `LLMRequest` class. */
@@ -224,6 +225,6 @@ export interface GenerateObjectDynamicOptions<SelectedLanguageModel extends Lang
224
225
  * 2. `jsonSchema: JsonSchema.JsonSchema` — `.object` is `unknown`. Use when
225
226
  * the schema is only available at runtime (MCP, plugin manifests). Caller validates.
226
227
  */
227
- export declare function generateObject<const SelectedLanguageModel extends LanguageModel, S extends ToolSchema<any>>(options: GenerateObjectOptions<S, SelectedLanguageModel>): Effect.Effect<GenerateObjectResponse<Schema.Schema.Type<S>>, AIError>;
228
- export declare function generateObject<const SelectedLanguageModel extends LanguageModel>(options: GenerateObjectDynamicOptions<SelectedLanguageModel>): Effect.Effect<GenerateObjectResponse<unknown>, AIError>;
228
+ export declare function generateObject<const SelectedLanguageModel extends LanguageModel, S extends ToolSchema<any>>(options: GenerateObjectOptions<S, SelectedLanguageModel>): Effect.Effect<GenerateObjectResponse<Schema.Schema.Type<S>>, AIError, Service>;
229
+ export declare function generateObject<const SelectedLanguageModel extends LanguageModel>(options: GenerateObjectDynamicOptions<SelectedLanguageModel>): Effect.Effect<GenerateObjectResponse<unknown>, AIError, Service>;
229
230
  export {};
package/dist/llm.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Effect, JsonSchema, Schema } from "effect";
2
- import { LLMClient } from "./route/client";
2
+ import { LLMClient, Service } from "./route/client";
3
3
  import { GenerationOptions, HttpOptions, InvalidProviderOutputReason, AIError, LLMEvent, LLMRequest, LLMResponse, Message, LanguageModel, SystemPart, ToolChoice, ToolDefinition, } from "./schema";
4
4
  import { make as makeTool, toDefinitions } from "./tool";
5
5
  export const generate = LLMClient.generate;
@@ -150,8 +150,8 @@ export declare const compileRequest: (request: LLMRequest) => Effect.Effect<{
150
150
  transport: string;
151
151
  };
152
152
  }, AIError, never>;
153
- export declare function stream(request: LLMRequest, options?: StreamOptions): Stream.Stream<LLMEvent, AIError>;
154
- export declare function generate(request: LLMRequest, options?: StreamOptions): Effect.Effect<LLMResponse, AIError>;
153
+ export declare function stream(request: LLMRequest, options?: StreamOptions): Stream.Stream<LLMEvent, AIError, Service>;
154
+ export declare function generate(request: LLMRequest, options?: StreamOptions): Effect.Effect<LLMResponse, AIError, Service>;
155
155
  export declare const streamRequest: (request: LLMRequest, options?: StreamOptions) => Stream.Stream<{
156
156
  readonly type: "step-start";
157
157
  readonly index: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
- "version": "0.0.0-next-16691",
3
+ "version": "0.0.0-next-16719",
4
4
  "name": "@opencode-ai/ai",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -30,7 +30,7 @@
30
30
  "devDependencies": {
31
31
  "@clack/prompts": "1.0.0-alpha.1",
32
32
  "@effect/platform-node": "4.0.0-beta.101",
33
- "@opencode-ai/http-recorder": "0.0.0-next-16691",
33
+ "@opencode-ai/http-recorder": "0.0.0-next-16719",
34
34
  "@tsconfig/bun": "1.0.9",
35
35
  "@types/bun": "1.3.13",
36
36
  "@typescript/native-preview": "7.0.0-dev.20251207.1",
@@ -39,7 +39,7 @@
39
39
  "dependencies": {
40
40
  "@smithy/eventstream-codec": "4.2.14",
41
41
  "@smithy/util-utf8": "4.2.2",
42
- "@opencode-ai/schema": "0.0.0-next-16691",
42
+ "@opencode-ai/schema": "0.0.0-next-16719",
43
43
  "aws4fetch": "1.0.20",
44
44
  "effect": "4.0.0-beta.101",
45
45
  "google-auth-library": "10.5.0"