@opencode-ai/ai 0.0.0-beta-17639 → 0.0.0-beta-17727
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 +17 -6
- package/dist/cache-policy.js +3 -5
- package/dist/protocols/anthropic-messages.d.ts +26 -28
- package/dist/protocols/anthropic-messages.js +5 -5
- package/dist/protocols/gemini.d.ts +5 -9
- package/dist/protocols/gemini.js +5 -4
- package/dist/protocols/open-responses.d.ts +176 -38
- package/dist/protocols/open-responses.js +108 -33
- package/dist/protocols/openai-chat.d.ts +17 -15
- package/dist/protocols/openai-chat.js +8 -2
- package/dist/protocols/openai-compatible-chat.d.ts +3 -3
- package/dist/protocols/openai-compatible-responses.d.ts +27 -5
- package/dist/protocols/openai-responses.d.ts +151 -33
- package/dist/protocols/openai-responses.js +4 -2
- package/dist/protocols/shared.d.ts +8 -14
- package/dist/protocols/shared.js +8 -14
- package/dist/protocols/utils/bedrock-cache.js +3 -4
- package/dist/protocols/utils/cache.js +3 -6
- package/dist/protocols/utils/open-responses-options.d.ts +46 -15
- package/dist/protocols/utils/open-responses-options.js +38 -25
- package/dist/protocols/utils/openai-options.d.ts +7 -5
- package/dist/protocols/utils/openai-options.js +3 -3
- package/dist/provider-package.d.ts +0 -5
- package/dist/providers/amazon-bedrock-mantle.d.ts +43 -19
- package/dist/providers/amazon-bedrock-mantle.js +0 -1
- package/dist/providers/amazon-bedrock.d.ts +3 -9
- package/dist/providers/amazon-bedrock.js +0 -1
- package/dist/providers/anthropic-compatible.d.ts +11 -11
- package/dist/providers/anthropic-compatible.js +0 -1
- package/dist/providers/anthropic.d.ts +12 -12
- package/dist/providers/anthropic.js +0 -1
- package/dist/providers/azure.d.ts +40 -16
- package/dist/providers/azure.js +0 -1
- package/dist/providers/cloudflare.d.ts +11 -11
- package/dist/providers/google-vertex-chat.d.ts +5 -5
- package/dist/providers/google-vertex-chat.js +0 -1
- package/dist/providers/google-vertex-messages.d.ts +11 -11
- package/dist/providers/google-vertex-messages.js +0 -1
- package/dist/providers/google-vertex-responses.d.ts +29 -7
- package/dist/providers/google-vertex-responses.js +1 -2
- package/dist/providers/google-vertex.d.ts +5 -7
- package/dist/providers/google-vertex.js +1 -2
- package/dist/providers/google.d.ts +4 -4
- package/dist/providers/google.js +0 -1
- package/dist/providers/open-responses-options.d.ts +3 -14
- package/dist/providers/openai-compatible-responses.d.ts +29 -7
- package/dist/providers/openai-compatible-responses.js +0 -1
- package/dist/providers/openai-compatible.d.ts +13 -12
- package/dist/providers/openai-compatible.js +1 -1
- package/dist/providers/openai-options.d.ts +2 -4
- package/dist/providers/openai-options.js +3 -3
- package/dist/providers/openai.d.ts +44 -20
- package/dist/providers/openai.js +0 -1
- package/dist/providers/openrouter.d.ts +16 -17
- package/dist/providers/openrouter.js +1 -2
- package/dist/providers/xai.d.ts +46 -24
- package/dist/providers/xai.js +1 -2
- package/dist/route/client.d.ts +2 -6
- package/dist/route/client.js +1 -2
- package/dist/route/framing.d.ts +2 -2
- package/dist/route/protocol.d.ts +1 -2
- package/dist/route/protocol.js +1 -2
- package/dist/schema/errors.js +2 -1
- package/dist/schema/events.d.ts +5 -3
- package/dist/schema/events.js +5 -2
- package/dist/schema/ids.d.ts +0 -13
- package/dist/schema/ids.js +0 -9
- package/dist/schema/messages.d.ts +7 -7
- package/dist/schema/messages.js +5 -2
- package/dist/schema/options.d.ts +6 -22
- package/dist/schema/options.js +6 -30
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -237,11 +237,11 @@ Prompt caching is **on by default**. Every `LLMRequest` resolves to `cache: "aut
|
|
|
237
237
|
|
|
238
238
|
### Auto placement
|
|
239
239
|
|
|
240
|
-
`"auto"` places up to four breakpoints — the last tool definition, the first system part, the last system part when distinct, and the final message boundary. These expose successively larger reusable prefixes for tools, the base agent, project instructions, and the active conversation. The rolling final-message boundary
|
|
240
|
+
`"auto"` places up to four breakpoints — the last tool definition, the first system part, the last system part when distinct, and the final message boundary. These expose successively larger reusable prefixes for tools, the base agent, project instructions, and the active conversation. The rolling final-message boundary advances on every request so recent conversation prefixes remain reusable during tool loops.
|
|
241
241
|
|
|
242
242
|
Tools precede every system and conversation block in the provider prefix, so tool definitions must remain byte-stable and deterministically ordered for downstream breakpoints to remain reusable.
|
|
243
243
|
|
|
244
|
-
|
|
244
|
+
Requests below a provider's minimum cacheable size simply do not produce a reusable cache entry.
|
|
245
245
|
|
|
246
246
|
### Opting out
|
|
247
247
|
|
|
@@ -285,6 +285,7 @@ LLM.request({
|
|
|
285
285
|
| ----------------------- | ------------------------------------------------------------------------- |
|
|
286
286
|
| Anthropic Messages | emits up to 4 `cache_control` markers (4-breakpoint cap enforced) |
|
|
287
287
|
| Bedrock Converse | emits up to 4 `cachePoint` blocks (4-breakpoint cap enforced) |
|
|
288
|
+
| OpenRouter | emits up to 4 `cache_control` markers |
|
|
288
289
|
| OpenAI Chat / Responses | no-op (implicit caching above 1024 tokens) |
|
|
289
290
|
| Gemini | no-op (implicit caching on 2.5+; explicit `CachedContent` is out-of-band) |
|
|
290
291
|
|
|
@@ -308,7 +309,7 @@ Included providers: OpenAI, Anthropic, Google (Gemini), Google Vertex Gemini and
|
|
|
308
309
|
|
|
309
310
|
### Package-like entrypoints
|
|
310
311
|
|
|
311
|
-
Native catalog integrations load provider behavior through package-like entrypoints. These are export paths from the same `@opencode-ai/ai` npm package, not independently published packages. Each entrypoint exports the same `model(modelID, settings)` contract, and `settings` contains serializable provider configuration plus common `headers
|
|
312
|
+
Native catalog integrations load provider behavior through package-like entrypoints. These are export paths from the same `@opencode-ai/ai` npm package, not independently published packages. Each entrypoint exports the same `model(modelID, settings)` contract, and `settings` contains serializable provider configuration plus common `headers` and `body` overlays.
|
|
312
313
|
|
|
313
314
|
```ts
|
|
314
315
|
import { model } from "@opencode-ai/ai/providers/openai/responses"
|
|
@@ -316,7 +317,6 @@ import { model } from "@opencode-ai/ai/providers/openai/responses"
|
|
|
316
317
|
const selected = model("gpt-5", {
|
|
317
318
|
apiKey: process.env.OPENAI_API_KEY,
|
|
318
319
|
headers: { "x-application": "opencode" },
|
|
319
|
-
limits: { context: 200_000, output: 64_000 },
|
|
320
320
|
})
|
|
321
321
|
```
|
|
322
322
|
|
|
@@ -371,11 +371,23 @@ Request options in order of stability:
|
|
|
371
371
|
|
|
372
372
|
1. **`generation`** — portable knobs (`maxTokens`, `temperature`, `topP`, `topK`, penalties, seed, stop).
|
|
373
373
|
2. **`promptCacheKey`** — stable cache affinity lowered by every protocol that supports it.
|
|
374
|
-
3. **`providerOptions: {
|
|
374
|
+
3. **`providerOptions: { ... }`** — flat options inferred from the selected model (OpenAI `store`, Anthropic `thinking`, Gemini `thinkingConfig`, OpenRouter routing).
|
|
375
375
|
4. **`http: { body, headers, query }`** — last-resort serializable overlays merged into the final HTTP request. Reach for this only when a stable typed path doesn't yet exist.
|
|
376
376
|
|
|
377
377
|
Route/provider defaults are overridden by request-level values for each axis.
|
|
378
378
|
|
|
379
|
+
The selected model supplies the provider-specific option type, so per-request overrides stay flat while the canonical runtime request remains provider-neutral:
|
|
380
|
+
|
|
381
|
+
```ts
|
|
382
|
+
LLM.request({
|
|
383
|
+
model,
|
|
384
|
+
prompt,
|
|
385
|
+
providerOptions: {
|
|
386
|
+
reasoningEffort: "low",
|
|
387
|
+
},
|
|
388
|
+
})
|
|
389
|
+
```
|
|
390
|
+
|
|
379
391
|
## Routes
|
|
380
392
|
|
|
381
393
|
Adding a new model or deployment is usually 5-15 lines using `Route.make({ protocol, endpoint, auth, framing, ... })`. The route owns endpoint/auth/framing and the protocol owns body construction plus stream parsing. Transports are reusable IO templates that receive route endpoint/auth at compile time. Capability/catalog metadata lives outside this low-level package; unsupported request shapes fail during protocol lowering. See `AGENTS.md` for the architectural detail.
|
|
@@ -387,6 +399,5 @@ This package is built on Effect. Public methods return `Effect` or `Stream`; pro
|
|
|
387
399
|
## See also
|
|
388
400
|
|
|
389
401
|
- `AGENTS.md` — architecture, route construction, contributor guide
|
|
390
|
-
- `STATUS.md` — native provider parity status and AI SDK migration gaps
|
|
391
402
|
- `example/tutorial.ts` — runnable end-to-end walkthrough
|
|
392
403
|
- `test/provider/*.test.ts` — fixture-first protocol tests; `*.recorded.test.ts` files cover live cassettes
|
package/dist/cache-policy.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
// The default `"auto"` shape places breakpoints at the last tool definition,
|
|
6
6
|
// the first and last distinct system parts, and the conversation tail. This
|
|
7
7
|
// exposes reusable tool, base-agent, project, and session prefixes while
|
|
8
|
-
// advancing the tail after each tool result keeps
|
|
9
|
-
//
|
|
8
|
+
// advancing the tail after each tool result keeps recent conversation prefixes
|
|
9
|
+
// reusable during long agent runs.
|
|
10
10
|
//
|
|
11
11
|
// Manual `cache: CacheHint` placements on individual parts are preserved and
|
|
12
12
|
// count against the four-breakpoint budget; auto only fills remaining slots.
|
|
@@ -20,9 +20,7 @@ const AUTO = {
|
|
|
20
20
|
const NONE = {};
|
|
21
21
|
const BREAKPOINT_CAP = 4;
|
|
22
22
|
// Resolution rules:
|
|
23
|
-
// - undefined → "auto" — caching is on by default.
|
|
24
|
-
// Anthropic 5m-cache write is 1.25x base, read is 0.1x,
|
|
25
|
-
// so a single reuse within 5 minutes already wins.
|
|
23
|
+
// - undefined → "auto" — caching is on by default.
|
|
26
24
|
// - "auto" → tools + first/last system + final message boundary.
|
|
27
25
|
// - "none" → no auto placement; manual `CacheHint`s still flow.
|
|
28
26
|
// - object form → exactly what the caller asked for.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
2
|
import { Route } from "../route/client.js";
|
|
3
3
|
import { Protocol } from "../route/protocol.js";
|
|
4
|
-
import { type ProviderOptions } from "../schema/index.js";
|
|
5
4
|
import { Lifecycle } from "./utils/lifecycle.js";
|
|
6
5
|
import { ToolStream } from "./utils/tool-stream.js";
|
|
7
6
|
export declare const DEFAULT_BASE_URL = "https://api.anthropic.com/v1";
|
|
8
7
|
export declare const PATH = "/messages";
|
|
8
|
+
export declare const DEFAULT_MAX_TOKENS = 32000;
|
|
9
9
|
export type ThinkingInput = {
|
|
10
10
|
readonly type: "adaptive";
|
|
11
11
|
readonly display?: "summarized" | "omitted";
|
|
@@ -25,9 +25,7 @@ export interface OptionsInput {
|
|
|
25
25
|
readonly thinking?: ThinkingInput;
|
|
26
26
|
readonly effort?: string;
|
|
27
27
|
}
|
|
28
|
-
export type ProviderOptionsInput =
|
|
29
|
-
readonly anthropic?: OptionsInput;
|
|
30
|
-
};
|
|
28
|
+
export type ProviderOptionsInput = OptionsInput;
|
|
31
29
|
export declare const AnthropicMessagesBody: Schema.Struct<{
|
|
32
30
|
model: Schema.String;
|
|
33
31
|
system: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
@@ -207,8 +205,8 @@ export declare const AnthropicMessagesBody: Schema.Struct<{
|
|
|
207
205
|
export type AnthropicMessagesBody = Schema.Schema.Type<typeof AnthropicMessagesBody>;
|
|
208
206
|
/**
|
|
209
207
|
* The Anthropic Messages protocol — request body construction, body schema,
|
|
210
|
-
* and the streaming-event state machine
|
|
211
|
-
*
|
|
208
|
+
* and the streaming-event state machine shared by Anthropic-compatible and
|
|
209
|
+
* Vertex-hosted Messages routes.
|
|
212
210
|
*/
|
|
213
211
|
export declare const protocol: Protocol<{
|
|
214
212
|
readonly max_tokens: number;
|
|
@@ -346,14 +344,6 @@ export declare const protocol: Protocol<{
|
|
|
346
344
|
}[];
|
|
347
345
|
})[];
|
|
348
346
|
readonly stream: true;
|
|
349
|
-
readonly system?: readonly {
|
|
350
|
-
readonly type: "text";
|
|
351
|
-
readonly text: string;
|
|
352
|
-
readonly cache_control?: {
|
|
353
|
-
readonly type: "ephemeral";
|
|
354
|
-
readonly ttl?: "1h" | "5m" | undefined;
|
|
355
|
-
} | undefined;
|
|
356
|
-
}[] | undefined;
|
|
357
347
|
readonly tools?: readonly {
|
|
358
348
|
readonly description: string;
|
|
359
349
|
readonly name: string;
|
|
@@ -365,6 +355,14 @@ export declare const protocol: Protocol<{
|
|
|
365
355
|
readonly ttl?: "1h" | "5m" | undefined;
|
|
366
356
|
} | undefined;
|
|
367
357
|
}[] | undefined;
|
|
358
|
+
readonly system?: readonly {
|
|
359
|
+
readonly type: "text";
|
|
360
|
+
readonly text: string;
|
|
361
|
+
readonly cache_control?: {
|
|
362
|
+
readonly type: "ephemeral";
|
|
363
|
+
readonly ttl?: "1h" | "5m" | undefined;
|
|
364
|
+
} | undefined;
|
|
365
|
+
}[] | undefined;
|
|
368
366
|
readonly temperature?: number | undefined;
|
|
369
367
|
readonly thinking?: {
|
|
370
368
|
readonly type: "enabled";
|
|
@@ -376,7 +374,7 @@ export declare const protocol: Protocol<{
|
|
|
376
374
|
readonly type: "disabled";
|
|
377
375
|
} | undefined;
|
|
378
376
|
readonly tool_choice?: {
|
|
379
|
-
readonly type: "
|
|
377
|
+
readonly type: "auto" | "none" | "any";
|
|
380
378
|
} | {
|
|
381
379
|
readonly type: "tool";
|
|
382
380
|
readonly name: string;
|
|
@@ -389,10 +387,6 @@ export declare const protocol: Protocol<{
|
|
|
389
387
|
} | undefined;
|
|
390
388
|
}, string, {
|
|
391
389
|
readonly type: string;
|
|
392
|
-
readonly error?: {
|
|
393
|
-
readonly type?: string | undefined;
|
|
394
|
-
readonly message?: string | undefined;
|
|
395
|
-
} | undefined;
|
|
396
390
|
readonly message?: {
|
|
397
391
|
readonly usage?: {
|
|
398
392
|
readonly [x: string]: unknown;
|
|
@@ -410,6 +404,10 @@ export declare const protocol: Protocol<{
|
|
|
410
404
|
} | null | undefined;
|
|
411
405
|
} | undefined;
|
|
412
406
|
} | undefined;
|
|
407
|
+
readonly error?: {
|
|
408
|
+
readonly type?: string | undefined;
|
|
409
|
+
readonly message?: string | undefined;
|
|
410
|
+
} | undefined;
|
|
413
411
|
readonly delta?: {
|
|
414
412
|
readonly type?: string | undefined;
|
|
415
413
|
readonly text?: string | undefined;
|
|
@@ -588,14 +586,6 @@ export declare const route: Route<{
|
|
|
588
586
|
}[];
|
|
589
587
|
})[];
|
|
590
588
|
readonly stream: true;
|
|
591
|
-
readonly system?: readonly {
|
|
592
|
-
readonly type: "text";
|
|
593
|
-
readonly text: string;
|
|
594
|
-
readonly cache_control?: {
|
|
595
|
-
readonly type: "ephemeral";
|
|
596
|
-
readonly ttl?: "1h" | "5m" | undefined;
|
|
597
|
-
} | undefined;
|
|
598
|
-
}[] | undefined;
|
|
599
589
|
readonly tools?: readonly {
|
|
600
590
|
readonly description: string;
|
|
601
591
|
readonly name: string;
|
|
@@ -607,6 +597,14 @@ export declare const route: Route<{
|
|
|
607
597
|
readonly ttl?: "1h" | "5m" | undefined;
|
|
608
598
|
} | undefined;
|
|
609
599
|
}[] | undefined;
|
|
600
|
+
readonly system?: readonly {
|
|
601
|
+
readonly type: "text";
|
|
602
|
+
readonly text: string;
|
|
603
|
+
readonly cache_control?: {
|
|
604
|
+
readonly type: "ephemeral";
|
|
605
|
+
readonly ttl?: "1h" | "5m" | undefined;
|
|
606
|
+
} | undefined;
|
|
607
|
+
}[] | undefined;
|
|
610
608
|
readonly temperature?: number | undefined;
|
|
611
609
|
readonly thinking?: {
|
|
612
610
|
readonly type: "enabled";
|
|
@@ -618,7 +616,7 @@ export declare const route: Route<{
|
|
|
618
616
|
readonly type: "disabled";
|
|
619
617
|
} | undefined;
|
|
620
618
|
readonly tool_choice?: {
|
|
621
|
-
readonly type: "
|
|
619
|
+
readonly type: "auto" | "none" | "any";
|
|
622
620
|
} | {
|
|
623
621
|
readonly type: "tool";
|
|
624
622
|
readonly name: string;
|
|
@@ -15,6 +15,7 @@ import { ToolStream } from "./utils/tool-stream.js";
|
|
|
15
15
|
const ADAPTER = "anthropic-messages";
|
|
16
16
|
export const DEFAULT_BASE_URL = "https://api.anthropic.com/v1";
|
|
17
17
|
export const PATH = "/messages";
|
|
18
|
+
export const DEFAULT_MAX_TOKENS = 32_000;
|
|
18
19
|
// =============================================================================
|
|
19
20
|
// Request Body Schema
|
|
20
21
|
// =============================================================================
|
|
@@ -468,7 +469,7 @@ const lowerMessages = Effect.fn("AnthropicMessages.lowerMessages")(function* (re
|
|
|
468
469
|
return messages;
|
|
469
470
|
});
|
|
470
471
|
const resolveOptions = Effect.fn("AnthropicMessages.resolveOptions")(function* (request) {
|
|
471
|
-
const input = request.providerOptions
|
|
472
|
+
const input = request.providerOptions;
|
|
472
473
|
return {
|
|
473
474
|
thinking: yield* resolveThinking(input?.thinking),
|
|
474
475
|
effort: typeof input?.effort === "string" ? input.effort : undefined,
|
|
@@ -501,7 +502,6 @@ const resolveThinking = Effect.fn("AnthropicMessages.resolveThinking")(function*
|
|
|
501
502
|
const fromRequest = Effect.fn("AnthropicMessages.fromRequest")(function* (request) {
|
|
502
503
|
const generation = request.generation;
|
|
503
504
|
const toolSchemaCompatibility = request.model.compatibility?.toolSchema;
|
|
504
|
-
const outputLimit = request.model.defaults?.limits?.output ?? request.model.route.defaults.limits?.output ?? 4096;
|
|
505
505
|
// Allocate the 4-breakpoint budget in invalidation order: tools → system →
|
|
506
506
|
// messages. Tools live highest in the cache hierarchy, so when callers
|
|
507
507
|
// over-mark we keep their tool hints and shed the message-tail ones first.
|
|
@@ -530,7 +530,7 @@ const fromRequest = Effect.fn("AnthropicMessages.fromRequest")(function* (reques
|
|
|
530
530
|
tools,
|
|
531
531
|
tool_choice: toolChoice,
|
|
532
532
|
stream: true,
|
|
533
|
-
max_tokens: generation?.maxTokens ??
|
|
533
|
+
max_tokens: generation?.maxTokens ?? DEFAULT_MAX_TOKENS,
|
|
534
534
|
temperature: generation?.temperature,
|
|
535
535
|
top_p: generation?.topP,
|
|
536
536
|
top_k: generation?.topK,
|
|
@@ -844,8 +844,8 @@ const step = (state, event) => {
|
|
|
844
844
|
// =============================================================================
|
|
845
845
|
/**
|
|
846
846
|
* The Anthropic Messages protocol — request body construction, body schema,
|
|
847
|
-
* and the streaming-event state machine
|
|
848
|
-
*
|
|
847
|
+
* and the streaming-event state machine shared by Anthropic-compatible and
|
|
848
|
+
* Vertex-hosted Messages routes.
|
|
849
849
|
*/
|
|
850
850
|
export const protocol = Protocol.make({
|
|
851
851
|
id: ADAPTER,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
2
|
import { Route } from "../route/client.js";
|
|
3
3
|
import { Protocol } from "../route/protocol.js";
|
|
4
|
-
import { type ProviderOptions } from "../schema/index.js";
|
|
5
4
|
import { Lifecycle } from "./utils/lifecycle.js";
|
|
6
5
|
export declare const DEFAULT_BASE_URL = "https://generativelanguage.googleapis.com/v1beta";
|
|
7
6
|
export interface OptionsInput {
|
|
@@ -18,9 +17,7 @@ export interface OptionsInput {
|
|
|
18
17
|
readonly thinkingLevel?: "minimal" | "low" | "medium" | "high" | (string & {});
|
|
19
18
|
};
|
|
20
19
|
}
|
|
21
|
-
export type ProviderOptionsInput =
|
|
22
|
-
readonly gemini?: OptionsInput;
|
|
23
|
-
};
|
|
20
|
+
export type ProviderOptionsInput = OptionsInput;
|
|
24
21
|
declare const GeminiBody: Schema.Struct<{
|
|
25
22
|
cachedContent: Schema.optional<Schema.String>;
|
|
26
23
|
contents: Schema.$Array<Schema.Struct<{
|
|
@@ -98,12 +95,11 @@ declare const GeminiBody: Schema.Struct<{
|
|
|
98
95
|
export type GeminiBody = Schema.Schema.Type<typeof GeminiBody>;
|
|
99
96
|
/**
|
|
100
97
|
* The Gemini protocol — request body construction, body schema, and the
|
|
101
|
-
* streaming-event state machine
|
|
102
|
-
* registered) Vertex Gemini.
|
|
98
|
+
* streaming-event state machine shared by Google AI Studio and Vertex Gemini.
|
|
103
99
|
*/
|
|
104
100
|
export declare const protocol: Protocol<{
|
|
105
101
|
readonly contents: readonly {
|
|
106
|
-
readonly role: "
|
|
102
|
+
readonly role: "model" | "user";
|
|
107
103
|
readonly parts: readonly ({
|
|
108
104
|
readonly inlineData: {
|
|
109
105
|
readonly mimeType: string;
|
|
@@ -181,7 +177,7 @@ export declare const protocol: Protocol<{
|
|
|
181
177
|
}, string, {
|
|
182
178
|
readonly candidates?: readonly {
|
|
183
179
|
readonly content?: {
|
|
184
|
-
readonly role: "
|
|
180
|
+
readonly role: "model" | "user";
|
|
185
181
|
readonly parts: readonly ({
|
|
186
182
|
readonly inlineData: {
|
|
187
183
|
readonly mimeType: string;
|
|
@@ -234,7 +230,7 @@ export declare const protocol: Protocol<{
|
|
|
234
230
|
}>;
|
|
235
231
|
export declare const route: Route<{
|
|
236
232
|
readonly contents: readonly {
|
|
237
|
-
readonly role: "
|
|
233
|
+
readonly role: "model" | "user";
|
|
238
234
|
readonly parts: readonly ({
|
|
239
235
|
readonly inlineData: {
|
|
240
236
|
readonly mimeType: string;
|
package/dist/protocols/gemini.js
CHANGED
|
@@ -201,7 +201,9 @@ const lowerMessages = Effect.fn("Gemini.lowerMessages")(function* (request) {
|
|
|
201
201
|
if (message.role === "system") {
|
|
202
202
|
const part = yield* ProviderShared.wrappedSystemUpdate("Gemini", message);
|
|
203
203
|
const previous = contents.at(-1);
|
|
204
|
-
|
|
204
|
+
// Gemini rejects a continuation whose function-response turn carries extra
|
|
205
|
+
// parts, so an update after a tool result starts its own user turn.
|
|
206
|
+
if (previous?.role === "user" && !previous.parts.some((item) => "functionResponse" in item))
|
|
205
207
|
contents[contents.length - 1] = { role: "user", parts: [...previous.parts, { text: part.text }] };
|
|
206
208
|
else
|
|
207
209
|
contents.push({ role: "user", parts: [{ text: part.text }] });
|
|
@@ -293,7 +295,7 @@ const lowerMessages = Effect.fn("Gemini.lowerMessages")(function* (request) {
|
|
|
293
295
|
return contents;
|
|
294
296
|
});
|
|
295
297
|
const resolveOptions = (request) => {
|
|
296
|
-
const input = request.providerOptions
|
|
298
|
+
const input = request.providerOptions;
|
|
297
299
|
const value = input?.thinkingConfig;
|
|
298
300
|
const thinkingConfig = {
|
|
299
301
|
thinkingBudget: ProviderShared.isRecord(value) && typeof value.thinkingBudget === "number" ? value.thinkingBudget : undefined,
|
|
@@ -491,8 +493,7 @@ const step = (state, event) => {
|
|
|
491
493
|
// =============================================================================
|
|
492
494
|
/**
|
|
493
495
|
* The Gemini protocol — request body construction, body schema, and the
|
|
494
|
-
* streaming-event state machine
|
|
495
|
-
* registered) Vertex Gemini.
|
|
496
|
+
* streaming-event state machine shared by Google AI Studio and Vertex Gemini.
|
|
496
497
|
*/
|
|
497
498
|
export const protocol = Protocol.make({
|
|
498
499
|
id: ADAPTER,
|