@darknesskiller/opencode-cliproxyapi 0.3.0 → 0.4.0

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/CHANGELOG.md CHANGED
@@ -5,7 +5,38 @@ All notable changes to this project are documented here.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
6
6
  and this project follows [Semantic Versioning](https://semver.org/).
7
7
 
8
- ## [0.3.0] - Unreleased
8
+ ## [0.4.0] - 2026-11-13
9
+
10
+ ### Added
11
+
12
+ - Discovered models now carry token limits parsed from the CLIProxyAPI
13
+ codex-client catalog, resolving the V1/V2 alignment gap. Context window
14
+ comes from `context_window`, falling back to `max_context_window` and
15
+ then 128,000; output comes from `max_tokens`, falling back to 32,000,
16
+ OpenCode V1's effective default (`0` breaks Anthropic-routed models and
17
+ V2 has no default of its own). Both plugin versions resolve limits
18
+ through the same shared code.
19
+ - User config now wins per field over discovered models in both versions:
20
+ non-empty strings for `name`/`package`/`provider.npm`, booleans for the
21
+ capability flags, and `limit` merged key-by-key (raising and lowering
22
+ both win; `0` keeps the default policy). `variants` and other nested
23
+ objects keep whole-object override semantics, models configured in user
24
+ config alone are preserved, and invalid values no longer erase what
25
+ discovery found.
26
+
27
+ ## [0.3.1] - 2026-11-13
28
+
29
+ ### Fixed
30
+
31
+ - Image attachments now reach discovered Claude, Gemini, and GPT models.
32
+ OpenCode only forwards image parts to models that declare image input, and
33
+ the plugin previously declared it only for `*-image-*` generation models, so
34
+ other models received a `Cannot read "<file>"` placeholder instead. V1 now
35
+ sets `modalities: { input: ["text", "image"], output: ["text"] }` and V2
36
+ sets the matching `capabilities.input`, both from one shared policy.
37
+ Text-only `gpt-oss-*` models are no longer marked as attachment-capable.
38
+
39
+ ## [0.3.0] - 2026-10-06
9
40
 
10
41
  ### Added
11
42
 
@@ -78,7 +109,9 @@ and this project follows [Semantic Versioning](https://semver.org/).
78
109
  - Automatic model names and capability hints in OpenCode's model picker.
79
110
  - Local plugin and npm package installation flows.
80
111
 
81
- [Unreleased]: https://github.com/DarknessKiller/opencode-cliproxyapi/compare/v0.2.1...HEAD
112
+ [Unreleased]: https://github.com/DarknessKiller/opencode-cliproxyapi/compare/v0.4.0...HEAD
113
+ [0.4.0]: https://github.com/DarknessKiller/opencode-cliproxyapi/compare/v0.3.1...v0.4.0
114
+ [0.3.0]: https://github.com/DarknessKiller/opencode-cliproxyapi/compare/v0.2.1...v0.3.0
82
115
  [0.2.1]: https://github.com/DarknessKiller/opencode-cliproxyapi/compare/v0.2.0...v0.2.1
83
116
  [0.2.0]: https://github.com/DarknessKiller/opencode-cliproxyapi/compare/v0.1.2...v0.2.0
84
117
  [0.1.2]: https://github.com/DarknessKiller/opencode-cliproxyapi/compare/v0.1.1...v0.1.2
package/README.md CHANGED
@@ -240,6 +240,28 @@ Then restart OpenCode and run:
240
240
  opencode models cliproxyapi
241
241
  ```
242
242
 
243
+ ### The model says it cannot read an attached image
244
+
245
+ CLIProxyAPI's `/v1/models` only reports model ids, so image input is inferred
246
+ from the model family: discovered models whose id starts with `claude`,
247
+ `gemini`, or `gpt` (except text-only `gpt-oss-*`) accept images, and
248
+ `*-image-*` models are treated as image generators. New releases in those
249
+ families are covered automatically. On OpenCode v1, declare the modalities of
250
+ a vision model outside these families under the provider's `models` in
251
+ `opencode.json`; user entries override the discovered metadata:
252
+
253
+ ```jsonc
254
+ {
255
+ "provider": {
256
+ "cliproxyapi": {
257
+ "models": {
258
+ "your-vision-model": { "attachment": true, "modalities": { "input": ["text", "image"], "output": ["text"] } }
259
+ }
260
+ }
261
+ }
262
+ }
263
+ ```
264
+
243
265
  ### Environment configuration works in one terminal but not another
244
266
 
245
267
  Move the connection to the recommended global OpenCode config, or add the
package/dist/catalog.d.ts CHANGED
@@ -7,8 +7,12 @@ export type ModelProtocolCatalog = Record<string, {
7
7
  models: Record<string, string>;
8
8
  }>;
9
9
  export type ReasoningEffortLevels = {
10
- levels: string[];
10
+ levels?: string[];
11
11
  defaultLevel?: string;
12
+ limit?: {
13
+ context?: number;
14
+ output?: number;
15
+ };
12
16
  };
13
17
  export type ReasoningEffortCatalog = Record<string, ReasoningEffortLevels>;
14
18
  export declare function normalizeBaseURL(value: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG,MAAM,CACvC,MAAM,EACN;IACE,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC/B,CACF,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAGD,MAAM,MAAM,sBAAsB,GAAG,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAA;AAW1E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,UAK7C;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,EAAE,CAuB3D;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,CAqBlF;AAED,wBAAsB,wBAAwB,CAAC,KAAK,EAAE;IACpD,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,OAAO,KAAK,CAAA;CACvB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAiBlC;AAED,wBAAsB,cAAc,CAAC,KAAK,EAAE;IAC1C,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,OAAO,KAAK,CAAA;CACvB,2BAcA;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,oBAAoB,CAsB9E;AAED,wBAAsB,sBAAsB,CAAC,KAAK,EAAE;IAClD,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,OAAO,KAAK,CAAA;CACvB,iCAaA"}
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG,MAAM,CACvC,MAAM,EACN;IACE,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC/B,CACF,CAAA;AAID,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAC9C,CAAA;AAGD,MAAM,MAAM,sBAAsB,GAAG,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAA;AAW1E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,UAK7C;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,EAAE,CAuB3D;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,CAiClF;AAED,wBAAsB,wBAAwB,CAAC,KAAK,EAAE;IACpD,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,OAAO,KAAK,CAAA;CACvB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAiBlC;AAED,wBAAsB,cAAc,CAAC,KAAK,EAAE;IAC1C,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,OAAO,KAAK,CAAA;CACvB,2BAcA;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,oBAAoB,CAsB9E;AAED,wBAAsB,sBAAsB,CAAC,KAAK,EAAE;IAClD,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,OAAO,KAAK,CAAA;CACvB,iCAaA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAU,MAAM,EAAgB,MAAM,qBAAqB,CAAA;AAuBvE,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAWtC,eAAO,MAAM,iBAAiB,EAAE,MAiE/B,CAAA;AAED;;;GAGG;;;;;;AACH,wBAIkD;AAClD,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,wBAAwB,EACxB,gBAAgB,EAChB,YAAY,EACZ,yBAAyB,EACzB,2BAA2B,GAC5B,MAAM,cAAc,CAAA;AACrB,YAAY,EAAE,YAAY,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAU,MAAM,EAAgB,MAAM,qBAAqB,CAAA;AA6BvE,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAWtC,eAAO,MAAM,iBAAiB,EAAE,MAiE/B,CAAA;AAED;;;GAGG;;;;;;AACH,wBAIkD;AAClD,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,wBAAwB,EACxB,gBAAgB,EAChB,YAAY,EACZ,yBAAyB,EACzB,2BAA2B,GAC5B,MAAM,cAAc,CAAA;AACrB,YAAY,EAAE,YAAY,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAA"}
package/dist/index.js CHANGED
@@ -38,15 +38,19 @@ function parseReasoningEffortCatalog(input) {
38
38
  if (!isRecord(item) || typeof item.slug !== "string" || item.slug.trim() === "")
39
39
  continue;
40
40
  const rawLevels = item.supported_reasoning_levels;
41
- if (!Array.isArray(rawLevels))
42
- continue;
43
- const levels = rawLevels.map((entry) => isRecord(entry) && typeof entry.effort === "string" ? entry.effort : undefined).filter((level) => level !== undefined);
44
- if (levels.length === 0)
45
- continue;
46
- const defaultLevel = typeof item.default_reasoning_level === "string" ? item.default_reasoning_level : undefined;
41
+ const levels = Array.isArray(rawLevels) ? rawLevels.map((entry) => isRecord(entry) && typeof entry.effort === "string" ? entry.effort : undefined).filter((level) => level !== undefined) : undefined;
42
+ const limit = {};
43
+ const context = [item.context_window, item.max_context_window].find(isPositiveNumber);
44
+ const output = isPositiveNumber(item.max_tokens) ? item.max_tokens : undefined;
45
+ if (context !== undefined)
46
+ limit.context = context;
47
+ if (output !== undefined)
48
+ limit.output = output;
49
+ const defaultLevel = levels && typeof item.default_reasoning_level === "string" ? item.default_reasoning_level : undefined;
47
50
  catalog[item.slug] = {
48
- levels: [...new Set(levels)],
49
- ...defaultLevel ? { defaultLevel } : {}
51
+ ...levels ? { levels: [...new Set(levels)] } : {},
52
+ ...defaultLevel ? { defaultLevel } : {},
53
+ ...Object.keys(limit).length > 0 ? { limit } : {}
50
54
  };
51
55
  }
52
56
  return catalog;
@@ -99,6 +103,9 @@ async function discoverModelProtocols(input) {
99
103
  }
100
104
  return parseModelProtocolCatalog(await response.json());
101
105
  }
106
+ function isPositiveNumber(value) {
107
+ return typeof value === "number" && Number.isFinite(value) && value > 0;
108
+ }
102
109
  function isRecord(value) {
103
110
  return typeof value === "object" && value !== null && !Array.isArray(value);
104
111
  }
@@ -109,6 +116,8 @@ var DEFAULT_PROVIDER_ID = "cliproxyapi";
109
116
  var DEFAULT_PROVIDER_NAME = "CLIProxyAPI";
110
117
  var DEFAULT_DISCOVERY_TIMEOUT_MS = 1e4;
111
118
  var DEFAULT_MODEL_METADATA_URL = "https://models.dev/api.json";
119
+ var DEFAULT_CONTEXT_LIMIT = 128000;
120
+ var DEFAULT_OUTPUT_LIMIT = 32000;
112
121
  var V1_CHAT_PACKAGE = "@ai-sdk/openai-compatible";
113
122
  var V1_RESPONSES_PACKAGE = "@ai-sdk/openai";
114
123
  var V1_ANTHROPIC_PACKAGE = "@ai-sdk/anthropic";
@@ -131,6 +140,35 @@ function readOptions(input) {
131
140
  function stringOption(value) {
132
141
  return typeof value === "string" && value.trim() !== "" ? value : undefined;
133
142
  }
143
+ function resolveModelLimits(model, effortCatalog) {
144
+ const limit = effortCatalog[model.id]?.limit;
145
+ return {
146
+ context: limit?.context ?? DEFAULT_CONTEXT_LIMIT,
147
+ output: limit?.output ?? DEFAULT_OUTPUT_LIMIT
148
+ };
149
+ }
150
+ function isProperString(value) {
151
+ return typeof value === "string" && value.trim() !== "";
152
+ }
153
+ function isProperBoolean(value) {
154
+ return typeof value === "boolean";
155
+ }
156
+ function isProperContextLimit(value) {
157
+ return Number.isInteger(value) && value > 0;
158
+ }
159
+ function isProperOutputLimit(value) {
160
+ return Number.isInteger(value) && value > 0;
161
+ }
162
+ function properLimitOverrides(userLimit) {
163
+ const input = typeof userLimit === "object" && userLimit !== null ? userLimit : {};
164
+ return {
165
+ ...isProperContextLimit(input.context) ? { context: input.context } : {},
166
+ ...isProperOutputLimit(input.output) ? { output: input.output } : {}
167
+ };
168
+ }
169
+ function definedKeys(value) {
170
+ return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined));
171
+ }
134
172
  function displayName(modelID) {
135
173
  return modelID.split("-").map((part) => {
136
174
  const lower = part.toLowerCase();
@@ -147,12 +185,19 @@ function isImageModel(modelID) {
147
185
  return /(?:^|-)image(?:-|$)/i.test(modelID);
148
186
  }
149
187
  function isReasoningModel(modelID, efforts) {
150
- if (efforts?.levels.length)
188
+ if (efforts?.levels?.length)
151
189
  return efforts.levels.some((level) => level !== "none");
152
190
  return /thinking|reasoning|codex|gpt-(?:5|oss)/i.test(modelID);
153
191
  }
154
192
  function supportsAttachments(modelID) {
155
- return /^(?:claude|gemini|gpt)/i.test(modelID);
193
+ return /^(?:claude|gemini|gpt)/i.test(modelID) && !/^gpt-oss(?:-|$)/i.test(modelID);
194
+ }
195
+ function modelModalities(modelID) {
196
+ const imageOutput = isImageModel(modelID);
197
+ return {
198
+ input: imageOutput || supportsAttachments(modelID) ? ["text", "image"] : ["text"],
199
+ output: imageOutput ? ["image"] : ["text"]
200
+ };
156
201
  }
157
202
  function resolveModelNpm(catalog, providerID, modelID) {
158
203
  const provider = catalog[providerID];
@@ -167,7 +212,7 @@ function supportedEffortLevels(model, input) {
167
212
  return;
168
213
  if (isAnthropicRouted(model, input.protocolCatalog))
169
214
  return;
170
- const levels = efforts.levels.filter((level) => level !== "none");
215
+ const levels = efforts.levels?.filter((level) => level !== "none") ?? [];
171
216
  return levels.length > 0 ? levels : undefined;
172
217
  }
173
218
  async function discoverCatalog(input) {
@@ -202,10 +247,9 @@ function discoverEffortLevels(input) {
202
247
  }
203
248
 
204
249
  // src/plugin-v2.ts
205
- var DEFAULT_CONTEXT_LIMIT = 128000;
206
- var DEFAULT_OUTPUT_LIMIT = 4096;
207
250
  function toV2Model(model, input) {
208
251
  const image = isImageModel(model.id);
252
+ const modalities = modelModalities(model.id);
209
253
  const levels = supportedEffortLevels(model, input.discovery);
210
254
  const anthropic = isAnthropicRouted(model, input.discovery.protocolCatalog);
211
255
  return {
@@ -216,8 +260,8 @@ function toV2Model(model, input) {
216
260
  ...anthropic ? { package: V2_ANTHROPIC_PACKAGE } : {},
217
261
  capabilities: {
218
262
  tools: !image,
219
- input: image ? ["text", "image"] : ["text"],
220
- output: image ? ["image"] : ["text"]
263
+ input: modalities.input,
264
+ output: modalities.output
221
265
  },
222
266
  variants: (levels ?? []).map((level) => ({
223
267
  id: level,
@@ -227,12 +271,39 @@ function toV2Model(model, input) {
227
271
  cost: [{ input: 0, output: 0, cache: { read: 0, write: 0 } }],
228
272
  status: "active",
229
273
  enabled: true,
230
- limit: { context: DEFAULT_CONTEXT_LIMIT, output: DEFAULT_OUTPUT_LIMIT }
274
+ limit: resolveModelLimits(model, input.discovery.effortCatalog)
231
275
  };
232
276
  }
233
277
  function toV2Models(input) {
234
278
  return input.discovery.catalog.map((model) => toV2Model(model, { providerID: input.providerID, discovery: input.discovery }));
235
279
  }
280
+ function mergeV2Models(discovered, userModels) {
281
+ const merged = discovered.map((base) => {
282
+ const userModel = userModels?.get(base.id);
283
+ return isRecord2(userModel) ? mergeV2Model(base, userModel) : base;
284
+ });
285
+ if (userModels) {
286
+ const discoveredIDs = new Set(discovered.map((model) => model.id));
287
+ for (const [id, userModel] of userModels) {
288
+ if (!discoveredIDs.has(id) && isRecord2(userModel))
289
+ merged.push(userModel);
290
+ }
291
+ }
292
+ return merged;
293
+ }
294
+ function mergeV2Model(base, userModel) {
295
+ return {
296
+ ...base,
297
+ ...definedKeys(userModel),
298
+ name: isProperString(userModel.name) ? userModel.name : base.name,
299
+ package: isProperString(userModel.package) ? userModel.package : base.package,
300
+ enabled: isProperBoolean(userModel.enabled) ? userModel.enabled : base.enabled,
301
+ limit: { ...base.limit, ...properLimitOverrides(userModel.limit) }
302
+ };
303
+ }
304
+ function isRecord2(value) {
305
+ return typeof value === "object" && value !== null && !Array.isArray(value);
306
+ }
236
307
  async function setup(ctx) {
237
308
  const options = readOptions(ctx.options);
238
309
  const providerID = options.providerID ?? DEFAULT_PROVIDER_ID;
@@ -244,13 +315,14 @@ async function setup(ctx) {
244
315
  for (const error of discovery.errors) {
245
316
  console.warn(`[cliproxyapi] ${error}`);
246
317
  }
247
- const models = toV2Models({ providerID, discovery });
318
+ const discovered = toV2Models({ providerID, discovery });
248
319
  const providerPackage = options.protocol === "responses" ? V2_RESPONSES_PACKAGE : V2_CHAT_PACKAGE;
249
320
  await ctx.provider.transform((editor) => {
250
321
  const settings = { baseURL };
251
322
  if (apiKey)
252
323
  settings.apiKey = apiKey;
253
324
  const existing = editor.get(providerID);
325
+ const models = mergeV2Models(discovered, existing?.models);
254
326
  if (existing) {
255
327
  editor.update(providerID, (provider) => {
256
328
  provider.name = provider.name || options.providerName || DEFAULT_PROVIDER_NAME;
@@ -343,17 +415,13 @@ function addProvider(config, input) {
343
415
  tool_call: !isImageModel(model.id),
344
416
  reasoning: isReasoningModel(model.id, input.effortCatalog[model.id]),
345
417
  attachment: supportsAttachments(model.id),
418
+ limit: resolveModelLimits(model, input.effortCatalog),
346
419
  ...model.ownedBy && resolveModelNpm(input.protocolCatalog, model.ownedBy, model.id) === V1_ANTHROPIC_PACKAGE ? {
347
420
  provider: {
348
421
  npm: V1_ANTHROPIC_PACKAGE
349
422
  }
350
423
  } : {},
351
- ...isImageModel(model.id) ? {
352
- modalities: {
353
- input: ["text", "image"],
354
- output: ["image"]
355
- }
356
- } : {},
424
+ ...imageModalities(model.id),
357
425
  ...reasoningEffortConfig(model, input)
358
426
  }
359
427
  ]));
@@ -373,6 +441,12 @@ function addProvider(config, input) {
373
441
  }
374
442
  };
375
443
  }
444
+ function imageModalities(modelID) {
445
+ const modalities = modelModalities(modelID);
446
+ if (!modalities.input.includes("image") && !modalities.output.includes("image"))
447
+ return {};
448
+ return { modalities };
449
+ }
376
450
  function reasoningEffortConfig(model, input) {
377
451
  const efforts = input.effortCatalog[model.id];
378
452
  if (!efforts)
@@ -380,12 +454,12 @@ function reasoningEffortConfig(model, input) {
380
454
  const levels = supportedEffortLevels(model, input);
381
455
  if (!levels)
382
456
  return {};
383
- const defaultLevel = efforts.defaultLevel !== undefined && efforts.levels.includes(efforts.defaultLevel) ? efforts.defaultLevel : undefined;
457
+ const defaultLevel = efforts.defaultLevel !== undefined && efforts.levels?.includes(efforts.defaultLevel) ? efforts.defaultLevel : undefined;
384
458
  return {
385
459
  ...defaultLevel ? { options: { reasoningEffort: defaultLevel } } : {},
386
460
  variants: {
387
- ...Object.fromEntries(efforts.levels.map((level) => [level, { reasoningEffort: level }])),
388
- ...disabledVariants(efforts.levels)
461
+ ...Object.fromEntries((efforts.levels ?? []).map((level) => [level, { reasoningEffort: level }])),
462
+ ...disabledVariants(efforts.levels ?? [])
389
463
  }
390
464
  };
391
465
  }
@@ -399,25 +473,50 @@ function disabledVariants(supported) {
399
473
  }
400
474
  function mergeModels(discovered, existing) {
401
475
  const merged = { ...discovered };
402
- for (const [modelID, model] of Object.entries(existing ?? {})) {
403
- const discoveredModel = merged[modelID];
404
- const providerNpm = model.provider?.npm ?? discoveredModel?.provider?.npm;
405
- merged[modelID] = {
406
- ...discoveredModel,
407
- ...model,
408
- ...providerNpm ? { provider: { npm: providerNpm } } : {}
409
- };
476
+ for (const [modelID, userModel] of Object.entries(existing ?? {})) {
477
+ const base = merged[modelID];
478
+ if (!base) {
479
+ if (isRecord3(userModel))
480
+ merged[modelID] = { ...userModel };
481
+ continue;
482
+ }
483
+ if (isRecord3(userModel))
484
+ merged[modelID] = mergeDiscoveredModel(base, userModel);
410
485
  }
411
486
  return merged;
412
487
  }
488
+ function mergeDiscoveredModel(base, userModel) {
489
+ const limits = { ...base.limit, ...properLimitOverrides(userModel.limit) };
490
+ const merged = {
491
+ ...base,
492
+ ...definedKeys(userModel),
493
+ name: isProperString(userModel.name) ? userModel.name : base.name,
494
+ tool_call: isProperBoolean(userModel.tool_call) ? userModel.tool_call : base.tool_call,
495
+ reasoning: isProperBoolean(userModel.reasoning) ? userModel.reasoning : base.reasoning,
496
+ attachment: isProperBoolean(userModel.attachment) ? userModel.attachment : base.attachment,
497
+ limit: limits
498
+ };
499
+ const userProvider = userModel.provider;
500
+ if (typeof userProvider === "object" && userProvider !== null) {
501
+ const { npm, ...rest } = userProvider;
502
+ const providerNpm = isProperString(npm) ? npm : base.provider?.npm;
503
+ const provider = providerNpm ? { npm: providerNpm, ...rest } : rest;
504
+ if (Object.keys(provider ?? {}).length > 0)
505
+ merged.provider = provider;
506
+ }
507
+ return merged;
508
+ }
509
+ function isRecord3(value) {
510
+ return typeof value === "object" && value !== null && !Array.isArray(value);
511
+ }
413
512
  export {
414
- parseReasoningEffortCatalog,
415
- parseModelProtocolCatalog,
416
- parseCatalog,
417
- normalizeBaseURL,
418
- discoverReasoningEfforts,
419
- discoverModels,
420
- discoverModelProtocols,
513
+ CLIProxyAPIPlugin,
421
514
  src_default as default,
422
- CLIProxyAPIPlugin
515
+ discoverModelProtocols,
516
+ discoverModels,
517
+ discoverReasoningEfforts,
518
+ normalizeBaseURL,
519
+ parseCatalog,
520
+ parseModelProtocolCatalog,
521
+ parseReasoningEffortCatalog
423
522
  };
@@ -55,6 +55,12 @@ export declare function toV2Models(input: {
55
55
  providerID: string;
56
56
  discovery: CatalogDiscovery;
57
57
  }): V2ModelInfo[];
58
+ /**
59
+ * Overlays the user's configured models on the discovered list. Discovery
60
+ * provides the defaults; a user value wins only where it is a value V2 can
61
+ * use, and a model the user configured alone is preserved verbatim.
62
+ */
63
+ export declare function mergeV2Models(discovered: V2ModelInfo[], userModels?: ReadonlyMap<string, unknown>): V2ModelInfo[];
58
64
  /**
59
65
  * V2 setup. Registers the provider from the discovered catalog and returns a
60
66
  * no-op cleanup (V2 keeps no timers or subscriptions for this plugin).
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-v2.d.ts","sourceRoot":"","sources":["../src/plugin-v2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAS,MAAM,EAAY,MAAM,kBAAkB,CAAA;AAE/D,OAAO,EAeL,KAAK,gBAAgB,EAEtB,MAAM,aAAa,CAAA;AAEpB,KAAK,OAAO,GAAG,MAAM,CAAC,OAAO,CAAA;AAK7B,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE;QACZ,KAAK,EAAE,OAAO,CAAA;QACd,KAAK,EAAE,MAAM,EAAE,CAAA;QACf,MAAM,EAAE,MAAM,EAAE,CAAA;KACjB,CAAA;IACD,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,IAAI,EAAE;QACJ,QAAQ,EAAE,MAAM,CAAA;KACjB,CAAA;IACD,IAAI,EAAE,KAAK,CAAC;QACV,KAAK,EAAE,MAAM,CAAA;QACb,MAAM,EAAE,MAAM,CAAA;QACd,KAAK,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAA;KACvC,CAAC,CAAA;IACF,MAAM,EAAE,QAAQ,CAAA;IAChB,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAA;QACf,MAAM,EAAE,MAAM,CAAA;KACf,CAAA;CACF;AAED,wBAAgB,SAAS,CACvB,KAAK,EAAE,gBAAgB,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,EAC1C,KAAK,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,gBAAgB,CAAA;CAAE,GACzD,WAAW,CA4Bb;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAChC,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,gBAAgB,CAAA;CAC5B,GAAG,WAAW,EAAE,CAIhB;AAED;;;GAGG;AACH,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CA8CtE;AAED,eAAO,MAAM,YAAY;;;CAGxB,CAAA"}
1
+ {"version":3,"file":"plugin-v2.d.ts","sourceRoot":"","sources":["../src/plugin-v2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAS,MAAM,EAAY,MAAM,kBAAkB,CAAA;AAE/D,OAAO,EAqBL,KAAK,gBAAgB,EAEtB,MAAM,aAAa,CAAA;AAEpB,KAAK,OAAO,GAAG,MAAM,CAAC,OAAO,CAAA;AAE7B,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE;QACZ,KAAK,EAAE,OAAO,CAAA;QACd,KAAK,EAAE,MAAM,EAAE,CAAA;QACf,MAAM,EAAE,MAAM,EAAE,CAAA;KACjB,CAAA;IACD,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,IAAI,EAAE;QACJ,QAAQ,EAAE,MAAM,CAAA;KACjB,CAAA;IACD,IAAI,EAAE,KAAK,CAAC;QACV,KAAK,EAAE,MAAM,CAAA;QACb,MAAM,EAAE,MAAM,CAAA;QACd,KAAK,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAA;KACvC,CAAC,CAAA;IACF,MAAM,EAAE,QAAQ,CAAA;IAChB,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAA;QACf,MAAM,EAAE,MAAM,CAAA;KACf,CAAA;CACF;AAED,wBAAgB,SAAS,CACvB,KAAK,EAAE,gBAAgB,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,EAC1C,KAAK,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,gBAAgB,CAAA;CAAE,GACzD,WAAW,CA6Bb;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAChC,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,gBAAgB,CAAA;CAC5B,GAAG,WAAW,EAAE,CAIhB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE,WAAW,EAAE,EACzB,UAAU,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GACxC,WAAW,EAAE,CAgBf;AAkBD;;;GAGG;AACH,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CA+CtE;AAED,eAAO,MAAM,YAAY;;;CAGxB,CAAA"}
package/dist/shared.d.ts CHANGED
@@ -1,10 +1,12 @@
1
1
  import type { PluginOptions } from "@opencode-ai/plugin";
2
- import { type CatalogModel, type ModelProtocolCatalog, type ReasoningEffortCatalog } from "./catalog.js";
2
+ import { type CatalogModel, type ModelProtocolCatalog, type ReasoningEffortCatalog, type ReasoningEffortLevels } from "./catalog.js";
3
3
  export declare const DEFAULT_BASE_URL = "http://localhost:8317/v1";
4
4
  export declare const DEFAULT_PROVIDER_ID = "cliproxyapi";
5
5
  export declare const DEFAULT_PROVIDER_NAME = "CLIProxyAPI";
6
6
  export declare const DEFAULT_DISCOVERY_TIMEOUT_MS = 10000;
7
7
  export declare const DEFAULT_MODEL_METADATA_URL = "https://models.dev/api.json";
8
+ export declare const DEFAULT_CONTEXT_LIMIT = 128000;
9
+ export declare const DEFAULT_OUTPUT_LIMIT = 32000;
8
10
  export declare const V1_CHAT_PACKAGE = "@ai-sdk/openai-compatible";
9
11
  export declare const V1_RESPONSES_PACKAGE = "@ai-sdk/openai";
10
12
  export declare const V1_ANTHROPIC_PACKAGE = "@ai-sdk/anthropic";
@@ -28,13 +30,28 @@ export type CatalogDiscovery = {
28
30
  };
29
31
  export declare function readOptions(input?: PluginOptions): ConnectorOptions;
30
32
  export declare function stringOption(value: unknown): string | undefined;
33
+ export declare function resolveModelLimits(model: CatalogModel, effortCatalog: ReasoningEffortCatalog): {
34
+ context: number;
35
+ output: number;
36
+ };
37
+ export declare function isProperString(value: unknown): value is string;
38
+ export declare function isProperBoolean(value: unknown): value is boolean;
39
+ export declare function isProperContextLimit(value: unknown): value is number;
40
+ export declare function isProperOutputLimit(value: unknown): value is number;
41
+ export declare function properLimitOverrides(userLimit: unknown): {
42
+ context?: number;
43
+ output?: number;
44
+ };
45
+ export declare function definedKeys<T extends object>(value: T): Partial<T>;
31
46
  export declare function displayName(modelID: string): string;
32
47
  export declare function isImageModel(modelID: string): boolean;
33
- export declare function isReasoningModel(modelID: string, efforts?: {
34
- levels: string[];
35
- defaultLevel?: string;
36
- }): boolean;
48
+ export declare function isReasoningModel(modelID: string, efforts?: ReasoningEffortLevels): boolean;
37
49
  export declare function supportsAttachments(modelID: string): boolean;
50
+ export type ModelModalities = {
51
+ input: Array<"text" | "image">;
52
+ output: Array<"text" | "image">;
53
+ };
54
+ export declare function modelModalities(modelID: string): ModelModalities;
38
55
  export declare function resolveModelNpm(catalog: ModelProtocolCatalog, providerID: string, modelID: string): string | undefined;
39
56
  export declare function isAnthropicRouted(model: CatalogModel, protocolCatalog: ModelProtocolCatalog): boolean;
40
57
  export declare function supportedEffortLevels(model: CatalogModel, input: {
@@ -1 +1 @@
1
- {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../src/shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC5B,MAAM,cAAc,CAAA;AAErB,eAAO,MAAM,gBAAgB,6BAA6B,CAAA;AAC1D,eAAO,MAAM,mBAAmB,gBAAgB,CAAA;AAChD,eAAO,MAAM,qBAAqB,gBAAgB,CAAA;AAClD,eAAO,MAAM,4BAA4B,QAAS,CAAA;AAClD,eAAO,MAAM,0BAA0B,gCAAgC,CAAA;AAGvE,eAAO,MAAM,eAAe,8BAA8B,CAAA;AAC1D,eAAO,MAAM,oBAAoB,mBAAmB,CAAA;AACpD,eAAO,MAAM,oBAAoB,sBAAsB,CAAA;AACvD,eAAO,MAAM,eAAe,6CAA6C,CAAA;AACzE,eAAO,MAAM,oBAAoB,kCAAkC,CAAA;AACnE,eAAO,MAAM,oBAAoB,qCAAqC,CAAA;AAEtE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,MAAM,GAAG,WAAW,CAAA;IAC/B,gBAAgB,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;IACjC,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,eAAe,EAAE,oBAAoB,CAAA;IACrC,aAAa,EAAE,sBAAsB,CAAA;IACrC,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB,CAAA;AAED,wBAAgB,WAAW,CAAC,KAAK,CAAC,EAAE,aAAa,GAAG,gBAAgB,CAiBnE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,sBAE1C;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,UAW1C;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,WAE3C;AAID,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;IAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,WAItD;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,WAElD;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,oBAAoB,EAC7B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACd,MAAM,GAAG,SAAS,CAGpB;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,YAAY,EACnB,eAAe,EAAE,oBAAoB,GACpC,OAAO,CAKT;AAMD,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE;IAAE,eAAe,EAAE,oBAAoB,CAAC;IAAC,aAAa,EAAE,sBAAsB,CAAA;CAAE,GACtF,MAAM,EAAE,GAAG,SAAS,CAOtB;AAKD,wBAAsB,eAAe,CAAC,KAAK,EAAE;IAC3C,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,gBAAgB,EAAE,MAAM,GAAG,KAAK,CAAA;IAChC,SAAS,EAAE,MAAM,CAAA;CAClB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAe5B"}
1
+ {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../src/shared.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@darknesskiller/opencode-cliproxyapi",
4
- "version": "0.3.0",
4
+ "version": "0.4.0",
5
5
  "description": "Fork of opencode-cliproxyapi that discovers CLIProxyAPI models and auto-configures reasoning-effort variants in OpenCode.",
6
6
  "type": "module",
7
7
  "license": "MIT",