@billjr99/pi-openai-compat 1.1.22 → 1.1.23
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 +36 -1
- package/index.ts +48 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -129,7 +129,10 @@ dropped) since you logged in, without restarting your session.
|
|
|
129
129
|
If you have multiple providers registered, you are asked which one to refresh
|
|
130
130
|
(or choose **All providers**); with a single provider it refreshes directly.
|
|
131
131
|
A failed or empty refresh leaves the existing model list untouched, so a flaky
|
|
132
|
-
network call can't blank out a working provider.
|
|
132
|
+
network call can't blank out a working provider. Capability metadata you have
|
|
133
|
+
hand-edited into `cachedModels` (see [Config file](#config-file)) survives a
|
|
134
|
+
refresh: the fetched list decides which model IDs exist, and any field the
|
|
135
|
+
provider's catalog omits is carried forward from the previous cache.
|
|
133
136
|
|
|
134
137
|
### `/compat-logout`
|
|
135
138
|
|
|
@@ -199,6 +202,38 @@ Credentials and cached model lists are stored at:
|
|
|
199
202
|
API keys are stored in plaintext. Protect the file with `chmod 600` if
|
|
200
203
|
needed, or delete it to clear all saved credentials.
|
|
201
204
|
|
|
205
|
+
Each provider's `cachedModels` array holds one entry per model. Only `id` is
|
|
206
|
+
required; the rest are optional and fall back to conservative defaults when the
|
|
207
|
+
provider's `/models` catalog does not report them:
|
|
208
|
+
|
|
209
|
+
| Field | Type | Default | Notes |
|
|
210
|
+
|---|---|---|---|
|
|
211
|
+
| `id` | string | required | Model ID as sent in requests. |
|
|
212
|
+
| `contextWindow` | number | `128000` | Context window in tokens. |
|
|
213
|
+
| `maxTokens` | number | `4096` | Maximum output tokens per response. |
|
|
214
|
+
| `reasoning` | boolean | `false` | Enables pi's thinking mode for the model. |
|
|
215
|
+
| `input` | `["text"]` or `["text","image"]` | `["text"]` | Modalities pi may send; `image` lets pi attach image blocks. Any other value is ignored. |
|
|
216
|
+
|
|
217
|
+
Most catalogs report none of these beyond the ID, so aggregators and proxies
|
|
218
|
+
(CLIProxyAPI, for example) register every model as a 128K, text-only,
|
|
219
|
+
non-reasoning model. To correct that, edit the entry by hand and `/reload`:
|
|
220
|
+
|
|
221
|
+
```json
|
|
222
|
+
{
|
|
223
|
+
"providers": {
|
|
224
|
+
"cpa": {
|
|
225
|
+
"cachedModels": [
|
|
226
|
+
{ "id": "claude-sonnet-4-6", "contextWindow": 1000000, "maxTokens": 128000,
|
|
227
|
+
"reasoning": true, "input": ["text", "image"] }
|
|
228
|
+
]
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
`/compat-refresh` keeps these hand-edited fields for any model ID that is still
|
|
235
|
+
present in the refreshed catalog; a field the provider does report always wins.
|
|
236
|
+
|
|
202
237
|
### Adding a provider without pi — `add-provider.sh`
|
|
203
238
|
|
|
204
239
|
`/compat-login` is the normal path, but the repo also ships a standalone script
|
package/index.ts
CHANGED
|
@@ -25,12 +25,18 @@ import * as os from "node:os";
|
|
|
25
25
|
// Types
|
|
26
26
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
27
27
|
|
|
28
|
+
/** Input modalities pi understands; anything else is dropped at fetch time. */
|
|
29
|
+
type ModelInput = "text" | "image";
|
|
30
|
+
|
|
28
31
|
interface CachedModel {
|
|
29
32
|
id: string;
|
|
30
33
|
contextWindow?: number;
|
|
31
34
|
maxTokens?: number;
|
|
35
|
+
// Optional capability metadata. Rarely present in a /models payload, but a
|
|
36
|
+
// user may hand-edit them into cachedModels for providers whose catalog
|
|
37
|
+
// omits them (see README "Config file"); /compat-refresh preserves them.
|
|
32
38
|
reasoning?: boolean;
|
|
33
|
-
input?:
|
|
39
|
+
input?: ModelInput[];
|
|
34
40
|
}
|
|
35
41
|
|
|
36
42
|
interface ProviderConfig {
|
|
@@ -69,9 +75,25 @@ type RawModel = {
|
|
|
69
75
|
name?: string;
|
|
70
76
|
context_window?: number;
|
|
71
77
|
max_tokens?: number;
|
|
78
|
+
reasoning?: unknown;
|
|
79
|
+
input?: unknown;
|
|
72
80
|
task?: { name?: string };
|
|
73
81
|
};
|
|
74
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Coerce an upstream `input` value into pi's modality list. Unknown or
|
|
85
|
+
* malformed values yield undefined so buildProviderModels falls back to the
|
|
86
|
+
* default, rather than caching something pi would choke on (it calls
|
|
87
|
+
* `model.input.includes("image")` at tool time).
|
|
88
|
+
*/
|
|
89
|
+
function normalizeInput(value: unknown): ModelInput[] | undefined {
|
|
90
|
+
if (!Array.isArray(value)) return undefined;
|
|
91
|
+
const kept = value.filter(
|
|
92
|
+
(v): v is ModelInput => v === "text" || v === "image",
|
|
93
|
+
);
|
|
94
|
+
return kept.length > 0 ? kept : undefined;
|
|
95
|
+
}
|
|
96
|
+
|
|
75
97
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
76
98
|
// Provider templates
|
|
77
99
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -557,8 +579,8 @@ async function fetchModels(
|
|
|
557
579
|
id,
|
|
558
580
|
contextWindow: m.context_window,
|
|
559
581
|
maxTokens: m.max_tokens,
|
|
560
|
-
reasoning: m.reasoning,
|
|
561
|
-
input: m.input,
|
|
582
|
+
reasoning: typeof m.reasoning === "boolean" ? m.reasoning : undefined,
|
|
583
|
+
input: normalizeInput(m.input),
|
|
562
584
|
};
|
|
563
585
|
})
|
|
564
586
|
.filter((m) => Boolean(m.id))
|
|
@@ -576,7 +598,7 @@ function buildProviderModels(models: CachedModel[]) {
|
|
|
576
598
|
id,
|
|
577
599
|
name: id,
|
|
578
600
|
reasoning: m.reasoning ?? false,
|
|
579
|
-
input: m.input ?? (["text"] as
|
|
601
|
+
input: m.input ?? (["text"] as ModelInput[]),
|
|
580
602
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
581
603
|
contextWindow: m.contextWindow ?? 128_000,
|
|
582
604
|
maxTokens: m.maxTokens ?? 4_096,
|
|
@@ -584,6 +606,27 @@ function buildProviderModels(models: CachedModel[]) {
|
|
|
584
606
|
});
|
|
585
607
|
}
|
|
586
608
|
|
|
609
|
+
/**
|
|
610
|
+
* Carry hand-edited capability metadata (reasoning / input / contextWindow /
|
|
611
|
+
* maxTokens) forward from the previous cache when a fresh /models fetch omits
|
|
612
|
+
* it. The fetched list decides which ids exist; the old cache only fills gaps,
|
|
613
|
+
* so a provider that does report a field always wins.
|
|
614
|
+
*/
|
|
615
|
+
function mergeModelMetadata(previous: CachedModel[], fetched: CachedModel[]): CachedModel[] {
|
|
616
|
+
const prior = new Map(previous.map((m) => [m.id, m]));
|
|
617
|
+
return fetched.map((m) => {
|
|
618
|
+
const old = prior.get(m.id);
|
|
619
|
+
if (!old) return m;
|
|
620
|
+
return {
|
|
621
|
+
...m,
|
|
622
|
+
contextWindow: m.contextWindow ?? old.contextWindow,
|
|
623
|
+
maxTokens: m.maxTokens ?? old.maxTokens,
|
|
624
|
+
reasoning: m.reasoning ?? old.reasoning,
|
|
625
|
+
input: m.input ?? old.input,
|
|
626
|
+
};
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
|
|
587
630
|
function compatKey(key: string): string {
|
|
588
631
|
return `compat-${key}`;
|
|
589
632
|
}
|
|
@@ -896,7 +939,7 @@ export default async function (pi: ExtensionAPI) {
|
|
|
896
939
|
if (models.length > 0) {
|
|
897
940
|
// Only overwrite the cache on a successful, non-empty fetch — a
|
|
898
941
|
// flaky refresh must never blank out a working provider's models.
|
|
899
|
-
p.cachedModels = models;
|
|
942
|
+
p.cachedModels = mergeModelMetadata(p.cachedModels, models);
|
|
900
943
|
saveConfig(config);
|
|
901
944
|
registerProvider(pi, key, p);
|
|
902
945
|
refreshed.push(`${p.displayName} (${models.length})`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@billjr99/pi-openai-compat",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.23",
|
|
4
4
|
"description": "pi-coding-agent extension: OpenAI-compatible endpoint support (OpenRouter, NVIDIA NIM, Nous Portal, Ollama, custom)",
|
|
5
5
|
"author": "Bill Mongan <https://github.com/BillJr99>",
|
|
6
6
|
"license": "MIT",
|