@staticeng/opencode-litellm 0.3.2 → 0.3.3
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/LICENSE +0 -0
- package/README.md +4 -0
- package/dist/helpers.d.ts +0 -0
- package/dist/helpers.js +0 -0
- package/dist/index.d.ts +0 -0
- package/dist/index.js +0 -0
- package/dist/litellm.d.ts +0 -0
- package/dist/litellm.js +0 -0
- package/dist/mapping.d.ts +3 -2
- package/dist/mapping.js +22 -7
- package/dist/merge.d.ts +0 -0
- package/dist/merge.js +0 -0
- package/dist/model-contracts.d.ts +0 -0
- package/dist/model-contracts.js +0 -0
- package/dist/options.d.ts +0 -0
- package/dist/options.js +0 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.js +0 -0
- package/dist/v2.d.ts +0 -0
- package/dist/v2.js +9 -1
- package/package.json +1 -1
package/LICENSE
CHANGED
|
File without changes
|
package/README.md
CHANGED
|
@@ -188,3 +188,7 @@ publisher for package `@staticeng/opencode-litellm` with this repository, workfl
|
|
|
188
188
|
The exact discovered aliases `5090-local-model` and `5090-local-model-codex` use the Qwen3.8 Flash Next Strata contract: text/image input, text output, reasoning, tools, and 262144 tokens of shared context. The output ceiling is 262144 within that shared window; it is not an additional output budget. Pricing continues to come from LiteLLM metadata.
|
|
189
189
|
|
|
190
190
|
Both aliases preserve their routable IDs and use Chat Completions in OpenCode. Their public variants are `off`, `low`, `medium`, and `xhigh` (default `xhigh`): `off` sends `reasoning_effort: "none"`; the other variants send their named effort. Strata accepts `high` and `max` as aliases of native `xhigh`; they are not distinct variants. This differs from the cloud Qwen contract and does not alter it. The `-codex` alias remains available to Codex via LiteLLM's separate Responses adapter. No alias is fabricated when discovery omits it; explicit model/provider overrides still win.
|
|
191
|
+
|
|
192
|
+
## Native image models (OpenCode 2.2+)
|
|
193
|
+
|
|
194
|
+
Current V2 discovery includes LiteLLM `image_generation` deployments as `type: "image"` using the native OpenAI-compatible Images driver. They are available to OpenCode image generation and OpenChamber image model settings, separately from conversation models. Explicit `includeModes` and model filters still apply. Legacy and transitional catalogs omit image deployments. Generation uses `/images/generations`; reference images use `/images/edits`.
|
package/dist/helpers.d.ts
CHANGED
|
File without changes
|
package/dist/helpers.js
CHANGED
|
File without changes
|
package/dist/index.d.ts
CHANGED
|
File without changes
|
package/dist/index.js
CHANGED
|
File without changes
|
package/dist/litellm.d.ts
CHANGED
|
File without changes
|
package/dist/litellm.js
CHANGED
|
File without changes
|
package/dist/mapping.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export declare function mapModels(response: unknown, options?: LiteLLMPluginOpti
|
|
|
18
18
|
[k: string]: OpenCodeModel;
|
|
19
19
|
};
|
|
20
20
|
export declare function buildProvider(models: unknown, options?: LiteLLMPluginOptions): OpenCodeProvider;
|
|
21
|
-
export declare function mapModelsV2(models: unknown, options?: LiteLLMPluginOptions): {
|
|
21
|
+
export declare function mapModelsV2(models: unknown, options?: LiteLLMPluginOptions, nativeImages?: boolean): {
|
|
22
22
|
[k: string]: OpenCodeModelV2 | {
|
|
23
23
|
variants: {
|
|
24
24
|
id: string;
|
|
@@ -26,6 +26,7 @@ export declare function mapModelsV2(models: unknown, options?: LiteLLMPluginOpti
|
|
|
26
26
|
[x: string]: unknown;
|
|
27
27
|
};
|
|
28
28
|
}[];
|
|
29
|
+
type?: "image";
|
|
29
30
|
family?: string;
|
|
30
31
|
name?: string;
|
|
31
32
|
api?: {
|
|
@@ -63,4 +64,4 @@ export declare function mapModelsV2(models: unknown, options?: LiteLLMPluginOpti
|
|
|
63
64
|
};
|
|
64
65
|
};
|
|
65
66
|
};
|
|
66
|
-
export declare function buildProviderV2(models: unknown, options?: LiteLLMPluginOptions): OpenCodeProviderV2;
|
|
67
|
+
export declare function buildProviderV2(models: unknown, options?: LiteLLMPluginOptions, nativeImages?: boolean): OpenCodeProviderV2;
|
package/dist/mapping.js
CHANGED
|
@@ -167,7 +167,7 @@ export function normalizeModelListResponse(response) {
|
|
|
167
167
|
function mode(model) {
|
|
168
168
|
return asString(model.model_info?.mode) ?? "chat";
|
|
169
169
|
}
|
|
170
|
-
function allowedByFilters(model, options) {
|
|
170
|
+
function allowedByFilters(model, options, nativeImages = false) {
|
|
171
171
|
const name = modelName(model);
|
|
172
172
|
if (!name)
|
|
173
173
|
return false;
|
|
@@ -186,8 +186,13 @@ function allowedByFilters(model, options) {
|
|
|
186
186
|
if (options.excludeModels?.includes(name))
|
|
187
187
|
return false;
|
|
188
188
|
const modelMode = mode(model);
|
|
189
|
+
// Images require the typed catalog and media resolver introduced in current V2.
|
|
190
|
+
if (modelMode === "image_generation" && !nativeImages)
|
|
191
|
+
return false;
|
|
189
192
|
if (options.includeModes?.length)
|
|
190
193
|
return options.includeModes.includes(modelMode);
|
|
194
|
+
if (modelMode === "image_generation")
|
|
195
|
+
return nativeImages;
|
|
191
196
|
return DEFAULT_MODES.has(modelMode) && !NON_CHAT_MODES.has(modelMode);
|
|
192
197
|
}
|
|
193
198
|
function cost(model) {
|
|
@@ -330,6 +335,15 @@ function generatedModel(model, tombstones = false) {
|
|
|
330
335
|
const name = modelName(model);
|
|
331
336
|
if (!name)
|
|
332
337
|
return undefined;
|
|
338
|
+
if (mode(model) === "image_generation")
|
|
339
|
+
return {
|
|
340
|
+
id: name,
|
|
341
|
+
name,
|
|
342
|
+
type: "image",
|
|
343
|
+
provider: { npm: "@opencode/ai/providers/openai-compatible/images" },
|
|
344
|
+
modalities: { input: supportedModalities(["text", ...(model.model_info?.supported_modalities ?? [])]), output: ["image"] },
|
|
345
|
+
tool_call: false,
|
|
346
|
+
};
|
|
333
347
|
const mappedModalities = modalities(model);
|
|
334
348
|
const discoveredVariants = supportsReasoning(model) ? reasoningVariants(model) : undefined;
|
|
335
349
|
const suppressDiscoveredVariants = modelContract(name)?.suppressDiscoveredVariants === true;
|
|
@@ -403,6 +417,7 @@ function v2Model(model, baseURL) {
|
|
|
403
417
|
const name = asString(model.name);
|
|
404
418
|
const family = asString(model.family);
|
|
405
419
|
return {
|
|
420
|
+
...(model.type === "image" ? { type: "image" } : {}),
|
|
406
421
|
...(family ? { family } : {}),
|
|
407
422
|
...(name ? { name } : {}),
|
|
408
423
|
api: {
|
|
@@ -425,10 +440,10 @@ function v2Model(model, baseURL) {
|
|
|
425
440
|
...(v2Variants(model) ? { variants: v2Variants(model) } : {}),
|
|
426
441
|
};
|
|
427
442
|
}
|
|
428
|
-
function mapModelsInternal(response, options, tombstones) {
|
|
443
|
+
function mapModelsInternal(response, options, tombstones, nativeImages = false) {
|
|
429
444
|
const models = normalizeModelListResponse(response);
|
|
430
445
|
return Object.fromEntries(models
|
|
431
|
-
.filter((model) => allowedByFilters(model, options))
|
|
446
|
+
.filter((model) => allowedByFilters(model, options, nativeImages))
|
|
432
447
|
.map((model) => {
|
|
433
448
|
const name = modelName(model);
|
|
434
449
|
const generated = generatedModel(model, tombstones);
|
|
@@ -458,8 +473,8 @@ export function buildProvider(models, options = {}) {
|
|
|
458
473
|
models: mapModelsInternal(models, options, true),
|
|
459
474
|
}, options.providerOverrides);
|
|
460
475
|
}
|
|
461
|
-
export function mapModelsV2(models, options = {}) {
|
|
462
|
-
const legacy =
|
|
476
|
+
export function mapModelsV2(models, options = {}, nativeImages = false) {
|
|
477
|
+
const legacy = mapModelsInternal(models, options, false, nativeImages);
|
|
463
478
|
return Object.fromEntries(Object.entries(legacy).map(([name, model]) => {
|
|
464
479
|
const mapped = v2Model(model, options.baseURL);
|
|
465
480
|
const variants = contractV2Variants(name, model, options.overrides?.[name]);
|
|
@@ -504,7 +519,7 @@ function responsesBody(options) {
|
|
|
504
519
|
}
|
|
505
520
|
return body;
|
|
506
521
|
}
|
|
507
|
-
export function buildProviderV2(models, options = {}) {
|
|
522
|
+
export function buildProviderV2(models, options = {}, nativeImages = false) {
|
|
508
523
|
return deepMerge({
|
|
509
524
|
name: options.providerName ?? "LiteLLM",
|
|
510
525
|
api: {
|
|
@@ -518,6 +533,6 @@ export function buildProviderV2(models, options = {}) {
|
|
|
518
533
|
...(options.apiKey ? { apiKey: options.apiKey } : {}),
|
|
519
534
|
},
|
|
520
535
|
},
|
|
521
|
-
models: mapModelsV2(models, options),
|
|
536
|
+
models: mapModelsV2(models, options, nativeImages),
|
|
522
537
|
}, options.providerOverrides);
|
|
523
538
|
}
|
package/dist/merge.d.ts
CHANGED
|
File without changes
|
package/dist/merge.js
CHANGED
|
File without changes
|
|
File without changes
|
package/dist/model-contracts.js
CHANGED
|
File without changes
|
package/dist/options.d.ts
CHANGED
|
File without changes
|
package/dist/options.js
CHANGED
|
File without changes
|
package/dist/types.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ export type ModelContract = Readonly<{
|
|
|
27
27
|
metadata?: ModelContractMetadata;
|
|
28
28
|
}>;
|
|
29
29
|
export type OpenCodeModel = JsonObject & {
|
|
30
|
+
type?: "image";
|
|
30
31
|
provider?: {
|
|
31
32
|
npm?: string;
|
|
32
33
|
api?: string;
|
|
@@ -54,6 +55,7 @@ export type OpenCodeModel = JsonObject & {
|
|
|
54
55
|
variants?: Record<string, JsonObject>;
|
|
55
56
|
};
|
|
56
57
|
export type OpenCodeModelV2 = JsonObject & {
|
|
58
|
+
type?: "image";
|
|
57
59
|
family?: string;
|
|
58
60
|
name?: string;
|
|
59
61
|
api?: {
|
package/dist/types.js
CHANGED
|
File without changes
|
package/dist/v2.d.ts
CHANGED
|
File without changes
|
package/dist/v2.js
CHANGED
|
@@ -5,6 +5,13 @@ import { resolveOptions } from "./options.js";
|
|
|
5
5
|
const CHAT_PACKAGE = "@opencode/ai/providers/openai-compatible";
|
|
6
6
|
// The 2.0.16 binary bundles this driver, but not openai-compatible/responses.
|
|
7
7
|
const RESPONSES_PACKAGE = "@opencode/ai/providers/openai/responses";
|
|
8
|
+
/** Image catalog types and their resolver are available in OpenCode 2.2+. */
|
|
9
|
+
function supportsNativeImages(ctx) {
|
|
10
|
+
const version = ctx.app?.version?.match(/^v?(\d+)\.(\d+)\.(\d+)(?:$|[-+])/);
|
|
11
|
+
if (!version)
|
|
12
|
+
return false;
|
|
13
|
+
return Number(version[1]) > 2 || (Number(version[1]) === 2 && Number(version[2]) >= 2);
|
|
14
|
+
}
|
|
8
15
|
function packageName(name) {
|
|
9
16
|
if (name === "@ai-sdk/openai" || name === "@opencode/ai/providers/openai-compatible/responses")
|
|
10
17
|
return RESPONSES_PACKAGE;
|
|
@@ -49,6 +56,7 @@ function currentModel(providerID, id, config, providerPackage) {
|
|
|
49
56
|
}
|
|
50
57
|
return {
|
|
51
58
|
id,
|
|
59
|
+
...(config.type === "image" ? { type: "image" } : {}),
|
|
52
60
|
modelID: config.api?.id ?? id,
|
|
53
61
|
providerID,
|
|
54
62
|
name: config.name ?? id,
|
|
@@ -250,7 +258,7 @@ const LiteLLMPluginV2 = {
|
|
|
250
258
|
// Opaque Responses aliases need the same transport as GPT-named models.
|
|
251
259
|
overrides[id] = deepMerge({ provider: { npm: "@ai-sdk/openai" } }, overrides[id]);
|
|
252
260
|
}
|
|
253
|
-
provider = buildProviderV2(models, { ...options, overrides });
|
|
261
|
+
provider = buildProviderV2(models, { ...options, overrides }, supportsNativeImages(ctx));
|
|
254
262
|
for (const model of models) {
|
|
255
263
|
if (model.model_info?.use_responses_lite !== true)
|
|
256
264
|
continue;
|