@staticeng/opencode-litellm 0.2.5 → 0.2.6
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 +25 -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 +0 -0
- package/dist/mapping.js +31 -3
- 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 +4 -0
- package/dist/types.js +0 -0
- package/package.json +3 -1
package/LICENSE
CHANGED
|
File without changes
|
package/README.md
CHANGED
|
@@ -93,6 +93,31 @@ When LiteLLM publishes `model_info.supported_reasoning_efforts`, the plugin maps
|
|
|
93
93
|
|
|
94
94
|
Overrides win over built-in contracts and generated values through a recursive deep merge. Model overrides are applied first and provider overrides last. Arrays and scalar values are replaced rather than concatenated.
|
|
95
95
|
|
|
96
|
+
### GPT Transport
|
|
97
|
+
|
|
98
|
+
GPT models use `@ai-sdk/openai` and the Responses API through the configured
|
|
99
|
+
LiteLLM base URL (for example, `/v1/responses`). Other models retain
|
|
100
|
+
`@ai-sdk/openai-compatible` and Chat Completions. No OpenAI OAuth endpoint or
|
|
101
|
+
direct upstream URL is introduced.
|
|
102
|
+
|
|
103
|
+
Selection matches a final `gpt-` plus digit segment (case-insensitive), including
|
|
104
|
+
namespaced aliases, in the routable model name, `base_model`, or
|
|
105
|
+
`litellm_params.model`. Opaque deployment IDs do not override a named alias.
|
|
106
|
+
The routable ID is preserved. O-series and non-GPT models are not migrated merely
|
|
107
|
+
because discovery reports `mode: responses`. Explicit model `provider.npm`
|
|
108
|
+
overrides still win; V2 uses the corresponding `api.package`.
|
|
109
|
+
|
|
110
|
+
Legacy reasoning options remain `reasoningEffort` (OpenCode places them under
|
|
111
|
+
`providerOptions.openai` for this SDK). V2 GPT request defaults and variants use
|
|
112
|
+
Responses wire bodies: `reasoning: { effort }`, not `reasoning_effort`.
|
|
113
|
+
Use an OpenCode release with AI SDK 5 or newer, where the OpenAI SDK's
|
|
114
|
+
`languageModel()` defaults to Responses. Tests pin the SDK versions used by
|
|
115
|
+
OpenCode at qualification time; these are development dependencies only.
|
|
116
|
+
|
|
117
|
+
After upgrading, pin the exact plugin version and restart only when active
|
|
118
|
+
sessions can safely stop. Existing processes retain their loaded plugin; do not
|
|
119
|
+
clear global caches to upgrade one plugin.
|
|
120
|
+
|
|
96
121
|
The built-in mode matrix is:
|
|
97
122
|
|
|
98
123
|
| Contract | Modes in order | Default |
|
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
|
File without changes
|
package/dist/mapping.js
CHANGED
|
@@ -111,6 +111,10 @@ function enrichMetadata(existing, incoming, key) {
|
|
|
111
111
|
function modelName(model) {
|
|
112
112
|
return asString(model.model_name) ?? asString(model.litellm_params?.model) ?? asString(model.model_info?.id);
|
|
113
113
|
}
|
|
114
|
+
function usesGPTResponses(model) {
|
|
115
|
+
// Match a GPT family segment, not an incidental substring or an opaque deployment ID.
|
|
116
|
+
return [modelName(model), model.model_info?.base_model, model.litellm_params?.model].some((name) => typeof name === "string" && /(?:^|\/)gpt-\d[^/]*$/i.test(name));
|
|
117
|
+
}
|
|
114
118
|
export function mergeModelInfo(deployments, groups) {
|
|
115
119
|
const byName = new Map();
|
|
116
120
|
for (const model of [...deployments, ...groups]) {
|
|
@@ -332,6 +336,7 @@ function generatedModel(model, tombstones = false) {
|
|
|
332
336
|
const generated = {
|
|
333
337
|
id: name,
|
|
334
338
|
name,
|
|
339
|
+
...(usesGPTResponses(model) ? { provider: { npm: "@ai-sdk/openai" } } : {}),
|
|
335
340
|
...(asString(model.model_info?.base_model) ? { family: asString(model.model_info?.base_model) } : {}),
|
|
336
341
|
...(cost(model) ? { cost: cost(model) } : {}),
|
|
337
342
|
...(limit(model) ? { limit: limit(model) } : {}),
|
|
@@ -403,8 +408,8 @@ function v2Model(model, baseURL) {
|
|
|
403
408
|
api: {
|
|
404
409
|
...(id ? { id } : {}),
|
|
405
410
|
type: "aisdk",
|
|
406
|
-
package: "@ai-sdk/openai-compatible",
|
|
407
|
-
...(baseURL ? { url: baseURL } : {}),
|
|
411
|
+
package: model.provider?.npm ?? "@ai-sdk/openai-compatible",
|
|
412
|
+
...(model.provider?.api ?? baseURL ? { url: model.provider?.api ?? baseURL } : {}),
|
|
408
413
|
settings: {},
|
|
409
414
|
},
|
|
410
415
|
capabilities: {
|
|
@@ -458,9 +463,32 @@ export function mapModelsV2(models, options = {}) {
|
|
|
458
463
|
return Object.fromEntries(Object.entries(legacy).map(([name, model]) => {
|
|
459
464
|
const mapped = v2Model(model, options.baseURL);
|
|
460
465
|
const variants = contractV2Variants(name, model, options.overrides?.[name]);
|
|
461
|
-
|
|
466
|
+
const result = variants ? { ...mapped, variants } : mapped;
|
|
467
|
+
if (mapped.api?.package === "@ai-sdk/openai") {
|
|
468
|
+
const body = responsesBody(isRecord(model.options) ? model.options : {});
|
|
469
|
+
result.request = { body };
|
|
470
|
+
result.variants = result.variants?.map((variant) => ({ ...variant, body: responsesBody(variant.body ?? {}) }));
|
|
471
|
+
}
|
|
472
|
+
return [name, result];
|
|
462
473
|
}));
|
|
463
474
|
}
|
|
475
|
+
function responsesBody(options) {
|
|
476
|
+
const body = { ...options };
|
|
477
|
+
const effort = body.reasoningEffort ?? body.reasoning_effort;
|
|
478
|
+
const summary = body.reasoningSummary;
|
|
479
|
+
delete body.reasoningEffort;
|
|
480
|
+
delete body.reasoning_effort;
|
|
481
|
+
delete body.reasoningSummary;
|
|
482
|
+
delete body.variantDefault;
|
|
483
|
+
if (effort !== undefined || summary !== undefined) {
|
|
484
|
+
body.reasoning = {
|
|
485
|
+
...(isRecord(body.reasoning) ? body.reasoning : {}),
|
|
486
|
+
...(effort !== undefined ? { effort } : {}),
|
|
487
|
+
...(summary !== undefined ? { summary } : {}),
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
return body;
|
|
491
|
+
}
|
|
464
492
|
export function buildProviderV2(models, options = {}) {
|
|
465
493
|
return deepMerge({
|
|
466
494
|
name: options.providerName ?? "LiteLLM",
|
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
package/dist/types.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@staticeng/opencode-litellm",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
4
4
|
"description": "OpenCode plugin that discovers LiteLLM models at runtime.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -30,6 +30,8 @@
|
|
|
30
30
|
"@opencode-ai/plugin": "*"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
+
"@ai-sdk/openai": "3.0.84",
|
|
34
|
+
"@ai-sdk/openai-compatible": "2.0.41",
|
|
33
35
|
"@opencode-ai/plugin": "latest",
|
|
34
36
|
"@types/node": "^24.10.1",
|
|
35
37
|
"typescript": "^5.9.3"
|