From d3ee0e5913a04031405264c8fc5fcc94d4911dfa Mon Sep 17 00:00:00 2001 From: Griko Nibras Date: Sat, 1 Aug 2026 12:21:43 +0700 Subject: [PATCH] Update Poolside Laguna model metadata --- .changeset/update-laguna-limits.md | 5 +++++ README.md | 16 +++++++++------- src/constants.ts | 6 ++++-- src/models.ts | 17 +++++++++-------- test/models.test.ts | 29 +++++++++++++++++++++++++++++ 5 files changed, 56 insertions(+), 17 deletions(-) create mode 100644 .changeset/update-laguna-limits.md diff --git a/.changeset/update-laguna-limits.md b/.changeset/update-laguna-limits.md new file mode 100644 index 0000000..f4740a6 --- /dev/null +++ b/.changeset/update-laguna-limits.md @@ -0,0 +1,5 @@ +--- +"opencode-provider-poolside": patch +--- + +Update Laguna model limits to the verified Poolside metadata and preserve those limits when live discovery reports stale values. diff --git a/README.md b/README.md index 73cc355..c974bb1 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ - **Live model discovery** — fetches the current model catalog from the Poolside API at startup, with sensible Laguna fallbacks when the API is unreachable. - **OpenAI-compatible** — uses [`@ai-sdk/openai-compatible`](https://ai-sdk.dev/providers/open-source-providers/openai-compatible) under the hood, so streaming, tool calls, and JSON mode work out of the box. - **API key management** — built-in auth hook for storing and loading your Poolside API key via OpenCode's `/connect` command. -- **Reasoning support** — Laguna models expose `none`, `minimal`, `low`, `medium`, `high`, and `xhigh` reasoning effort levels through OpenCode's variant picker. +- **Reasoning support** — Laguna M.1 and XS 2.1 expose `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`; Laguna S 2.1 exposes its supported `none` and `xhigh` modes through OpenCode's variant picker. - **Zero config** — add the plugin to your `opencode.json` and you're ready to go. ## Quick start @@ -73,11 +73,13 @@ Or set a default model in your config: ## Available models -| Model | Description | Reasoning | -|---|---|---| -| `poolside/laguna-m.1` | Poolside's most capable coding agent model | ✅ | -| `poolside/laguna-xs-2.1` | Second-generation coding agent model (XS) | ✅ | -| `poolside/laguna-s-2.1` | Second-generation coding agent model (S) | ✅ | +| Model | Context | Max output | Reasoning | +|---|---:|---:|---| +| `poolside/laguna-m.1` | 262,144 | 32,768 | `none`–`xhigh` | +| `poolside/laguna-xs-2.1` | 262,144 | 32,768 | `none`–`xhigh` | +| `poolside/laguna-s-2.1` | 1,048,576 | 131,072 | `none`, `xhigh` | + +The static catalog uses these verified Poolside limits. Authenticated model discovery enriches the catalog with live capabilities, while preserving these limits when the Poolside `/models` response is incomplete or stale. ## Configuration @@ -125,7 +127,7 @@ export POOLSIDE_API_KEY="your-api-key" ## How it works 1. **Config hook** — On startup, the plugin registers the `poolside` provider with `@ai-sdk/openai-compatible`, sets the base URL and environment variable, and populates the model catalog. -2. **Model discovery** — If `POOLSIDE_API_KEY` is available, the plugin fetches the live model list from `https://inference.poolside.ai/v1/models`. If the API is unreachable, it falls back to a static catalog of known Laguna models. +2. **Model discovery** — If `POOLSIDE_API_KEY` is available, the plugin fetches the live model list from `https://inference.poolside.ai/v1/models`. If the API is unreachable, it falls back to a static catalog of known Laguna models; verified limits remain in place if the endpoint reports stale values. 3. **Model aliases** — OpenCode exposes models as `poolside/laguna-*` while sending Poolside's required `poolside/laguna-*` upstream IDs without duplicating the provider prefix. 4. **Auth hook** — The plugin provides an API key auth method so you can manage your key with OpenCode's `/connect poolside` command. diff --git a/src/constants.ts b/src/constants.ts index 55a6d39..429e30d 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -93,10 +93,12 @@ export const MAX_ONLY_VARIANTS = { const ZERO_COST = { input: 0, output: 0, cache_read: 0, cache_write: 0 } as const; /** - * Default context window and output token limits for Poolside models. + * Default context window and output token limits for Laguna M.1 and XS 2.1. */ const DEFAULT_CONTEXT_WINDOW = 262_144; const DEFAULT_MAX_TOKENS = 32_768; +const LAGUNA_S_CONTEXT_WINDOW = 1_048_576; +const LAGUNA_S_MAX_TOKENS = 131_072; /** * Current Poolside Platform models, available before authenticated refresh. @@ -130,7 +132,7 @@ export const FALLBACK_MODELS = [ reasoning: true, tool_call: true, cost: ZERO_COST, - limit: { context: DEFAULT_CONTEXT_WINDOW, output: DEFAULT_MAX_TOKENS }, + limit: { context: LAGUNA_S_CONTEXT_WINDOW, output: LAGUNA_S_MAX_TOKENS }, variants: MAX_ONLY_VARIANTS, }, ]; diff --git a/src/models.ts b/src/models.ts index 801f9ff..cdf1b2f 100644 --- a/src/models.ts +++ b/src/models.ts @@ -95,15 +95,16 @@ export function parseModelsResponse( fallback?.cost.cache_write ?? 0 ), }, + // The verified Laguna catalog is authoritative for known models. + // Poolside's /models endpoint can expose stale limits for Laguna S + // 2.1, so live metadata must not shrink its advertised capacity. limit: { - context: positiveNumber( - item.context_length, - fallback?.limit.context ?? 262_144 - ), - output: positiveNumber( - item.max_completion_tokens, - fallback?.limit.output ?? 32_768 - ), + context: + fallback?.limit.context ?? + positiveNumber(item.context_length, 262_144), + output: + fallback?.limit.output ?? + positiveNumber(item.max_completion_tokens, 32_768), }, variants, modalities: { diff --git a/test/models.test.ts b/test/models.test.ts index c23885d..75f7b80 100644 --- a/test/models.test.ts +++ b/test/models.test.ts @@ -192,6 +192,24 @@ describe("parseModelsResponse", () => { assert.equal(result[1]!.id, "poolside/laguna-xs-2.1"); assert.equal(result[2]!.id, "poolside/laguna-s-2.1"); }); + + test("preserves verified Laguna limits when the API reports stale values", () => { + const payload: PoolsideModelsResponse = { + data: [ + { + id: "poolside/laguna-s-2.1", + context_length: 262_144, + max_completion_tokens: 32_768, + }, + ], + }; + const result = parseModelsResponse(payload); + + assert.deepEqual(result[0]!.limit, { + context: 1_048_576, + output: 131_072, + }); + }); }); describe("modelsToConfigMap", () => { @@ -242,4 +260,15 @@ describe("FALLBACK_MODELS", () => { assert.ok(Object.keys(model.variants).length > 0); } }); + + test("uses the verified context and output limits", () => { + const limits = Object.fromEntries( + FALLBACK_MODELS.map((model) => [model.id, model.limit]) + ); + assert.deepEqual(limits, { + "poolside/laguna-m.1": { context: 262_144, output: 32_768 }, + "poolside/laguna-xs-2.1": { context: 262_144, output: 32_768 }, + "poolside/laguna-s-2.1": { context: 1_048_576, output: 131_072 }, + }); + }); });