@billjr99/pi-openai-compat 1.0.0 → 1.0.2
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/index.ts +129 -16
- package/package.json +1 -1
package/index.ts
CHANGED
|
@@ -56,36 +56,127 @@ const TEMPLATES: Record<string, {
|
|
|
56
56
|
displayName: string;
|
|
57
57
|
baseUrl: string;
|
|
58
58
|
keyless: boolean;
|
|
59
|
-
|
|
59
|
+
/** If set, only models whose id appears in this list are kept after fetching. */
|
|
60
|
+
modelFilter?: string[];
|
|
61
|
+
/** If true, prompt the user to confirm/edit the base URL (like ollama/custom). */
|
|
62
|
+
promptUrl?: boolean;
|
|
60
63
|
}> = {
|
|
61
64
|
openrouter: {
|
|
62
65
|
displayName: "OpenRouter",
|
|
63
66
|
baseUrl: "https://openrouter.ai/api/v1",
|
|
64
67
|
keyless: false,
|
|
65
|
-
keyHint: "sk-or-... from openrouter.ai/keys",
|
|
66
68
|
},
|
|
67
69
|
nvidia_nim: {
|
|
68
70
|
displayName: "NVIDIA NIM",
|
|
69
71
|
baseUrl: "https://integrate.api.nvidia.com/v1",
|
|
70
72
|
keyless: false,
|
|
71
|
-
keyHint: "nvapi-... from build.nvidia.com",
|
|
72
73
|
},
|
|
73
74
|
nous: {
|
|
74
75
|
displayName: "Nous Research Portal",
|
|
75
76
|
baseUrl: "https://inference-api.nousresearch.com/v1",
|
|
76
77
|
keyless: false,
|
|
77
|
-
|
|
78
|
+
},
|
|
79
|
+
google: {
|
|
80
|
+
displayName: "Google Gemini",
|
|
81
|
+
baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai",
|
|
82
|
+
keyless: false,
|
|
83
|
+
modelFilter: [
|
|
84
|
+
"gemini-2.5-flash",
|
|
85
|
+
"gemini-2.5-flash-lite",
|
|
86
|
+
"gemini-3-flash-preview",
|
|
87
|
+
"gemini-3.1-flash-lite-preview",
|
|
88
|
+
"gemini-3.1-pro-preview",
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
cerebras: {
|
|
92
|
+
displayName: "Cerebras",
|
|
93
|
+
baseUrl: "https://api.cerebras.ai/v1",
|
|
94
|
+
keyless: false,
|
|
95
|
+
modelFilter: ["qwen3-235b"],
|
|
96
|
+
},
|
|
97
|
+
github_models: {
|
|
98
|
+
displayName: "GitHub Models",
|
|
99
|
+
baseUrl: "https://models.inference.ai.azure.com",
|
|
100
|
+
keyless: false,
|
|
101
|
+
modelFilter: ["gpt-4o", "openai/gpt-4.1"],
|
|
102
|
+
},
|
|
103
|
+
sambanova: {
|
|
104
|
+
displayName: "SambaNova",
|
|
105
|
+
baseUrl: "https://api.sambanova.ai/v1",
|
|
106
|
+
keyless: false,
|
|
107
|
+
modelFilter: [
|
|
108
|
+
"Meta-Llama-3.3-70B-Instruct",
|
|
109
|
+
"DeepSeek-V3.1",
|
|
110
|
+
"DeepSeek-V3.2",
|
|
111
|
+
"gpt-oss-120b",
|
|
112
|
+
"Llama-4-Maverick-17B-128E-Instruct",
|
|
113
|
+
"gemma-3-12b-it",
|
|
114
|
+
],
|
|
115
|
+
},
|
|
116
|
+
mistral: {
|
|
117
|
+
displayName: "Mistral",
|
|
118
|
+
baseUrl: "https://api.mistral.ai/v1",
|
|
119
|
+
keyless: false,
|
|
120
|
+
modelFilter: [
|
|
121
|
+
"mistral-large-latest",
|
|
122
|
+
"mistral-medium-latest",
|
|
123
|
+
"magistral-medium-latest",
|
|
124
|
+
"codestral-latest",
|
|
125
|
+
"devstral-latest",
|
|
126
|
+
],
|
|
127
|
+
},
|
|
128
|
+
groq: {
|
|
129
|
+
displayName: "Groq",
|
|
130
|
+
baseUrl: "https://api.groq.com/openai/v1",
|
|
131
|
+
keyless: false,
|
|
132
|
+
modelFilter: [
|
|
133
|
+
"llama-3.3-70b-versatile",
|
|
134
|
+
"meta-llama/llama-4-scout-17b-16e-instruct",
|
|
135
|
+
"openai/gpt-oss-120b",
|
|
136
|
+
"openai/gpt-oss-20b",
|
|
137
|
+
"qwen/qwen3-32b",
|
|
138
|
+
"llama-3.1-8b-instant",
|
|
139
|
+
],
|
|
140
|
+
},
|
|
141
|
+
cloudflare: {
|
|
142
|
+
displayName: "Cloudflare Workers AI",
|
|
143
|
+
baseUrl: "https://api.cloudflare.com/client/v4/accounts/YOUR_ACCOUNT_ID/ai/v1",
|
|
144
|
+
keyless: false,
|
|
145
|
+
promptUrl: true,
|
|
146
|
+
modelFilter: [
|
|
147
|
+
"@cf/meta/llama-3.3-70b-instruct-fp8-fast",
|
|
148
|
+
"@cf/meta/llama-4-scout-17b-16e-instruct",
|
|
149
|
+
"@cf/openai/gpt-oss-120b",
|
|
150
|
+
"@cf/zai-org/glm-4.7-flash",
|
|
151
|
+
"@cf/moonshotai/kimi-k2.5",
|
|
152
|
+
"@cf/moonshotai/kimi-k2.6",
|
|
153
|
+
"@cf/qwen/qwen3-30b-a3b-fp8",
|
|
154
|
+
"@cf/deepseek-ai/deepseek-r1-distill-qwen-32b",
|
|
155
|
+
"@cf/ibm-granite/granite-4.0-h-micro",
|
|
156
|
+
],
|
|
157
|
+
},
|
|
158
|
+
zhipu: {
|
|
159
|
+
displayName: "Zhipu (Z.ai / BigModel)",
|
|
160
|
+
baseUrl: "https://open.bigmodel.cn/api/paas/v4",
|
|
161
|
+
keyless: false,
|
|
162
|
+
modelFilter: ["glm-4.5-flash", "glm-4.7-flash"],
|
|
163
|
+
},
|
|
164
|
+
cohere: {
|
|
165
|
+
displayName: "Cohere",
|
|
166
|
+
baseUrl: "https://api.cohere.com/compatibility/v1",
|
|
167
|
+
keyless: false,
|
|
78
168
|
},
|
|
79
169
|
ollama: {
|
|
80
170
|
displayName: "Ollama (local, keyless)",
|
|
81
171
|
baseUrl: "http://localhost:11434/v1",
|
|
82
172
|
keyless: true,
|
|
173
|
+
promptUrl: true,
|
|
83
174
|
},
|
|
84
175
|
custom: {
|
|
85
176
|
displayName: "Custom Endpoint",
|
|
86
177
|
baseUrl: "",
|
|
87
178
|
keyless: false,
|
|
88
|
-
|
|
179
|
+
promptUrl: true,
|
|
89
180
|
},
|
|
90
181
|
};
|
|
91
182
|
|
|
@@ -266,18 +357,26 @@ export default async function (pi: ExtensionAPI) {
|
|
|
266
357
|
const key = keys[labels.indexOf(selectedLabel)];
|
|
267
358
|
const tpl = TEMPLATES[key];
|
|
268
359
|
|
|
269
|
-
// Step 2 — base URL
|
|
360
|
+
// Step 2 — base URL
|
|
270
361
|
let baseUrl = tpl.baseUrl;
|
|
271
|
-
if (key === "
|
|
272
|
-
|
|
362
|
+
if (key === "cloudflare") {
|
|
363
|
+
// Ask for just the account ID and splice it into the template URL.
|
|
273
364
|
const entered = await ctx.ui.input(
|
|
274
|
-
"
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
: "Base URL of your endpoint (e.g. https://api.example.com/v1):",
|
|
278
|
-
defaultUrl
|
|
365
|
+
"Account ID",
|
|
366
|
+
"Your Cloudflare Account ID (find it on the Cloudflare dashboard overview page):",
|
|
367
|
+
""
|
|
279
368
|
);
|
|
280
|
-
if (entered
|
|
369
|
+
if (entered == null) { ctx.ui.notify("Login cancelled.", "info"); return; }
|
|
370
|
+
const accountId = entered.trim();
|
|
371
|
+
if (!accountId) { ctx.ui.notify("Account ID cannot be empty.", "error"); return; }
|
|
372
|
+
baseUrl = tpl.baseUrl.replace("YOUR_ACCOUNT_ID", accountId);
|
|
373
|
+
} else if (tpl.promptUrl) {
|
|
374
|
+
const defaultUrl = tpl.baseUrl;
|
|
375
|
+
const prompt = key === "ollama"
|
|
376
|
+
? `Ollama base URL — press Enter for default (${defaultUrl}):`
|
|
377
|
+
: "Base URL of your endpoint (e.g. https://api.example.com/v1):";
|
|
378
|
+
const entered = await ctx.ui.input("Base URL", prompt, defaultUrl);
|
|
379
|
+
if (entered == null) { ctx.ui.notify("Login cancelled.", "info"); return; }
|
|
281
380
|
baseUrl = (entered.trim() || defaultUrl).replace(/\/+$/, "");
|
|
282
381
|
if (!baseUrl) { ctx.ui.notify("Base URL cannot be empty.", "error"); return; }
|
|
283
382
|
}
|
|
@@ -287,10 +386,10 @@ export default async function (pi: ExtensionAPI) {
|
|
|
287
386
|
if (!tpl.keyless) {
|
|
288
387
|
const entered = await ctx.ui.input(
|
|
289
388
|
"API Key",
|
|
290
|
-
|
|
389
|
+
"Your API key — leave blank if keyless:",
|
|
291
390
|
""
|
|
292
391
|
);
|
|
293
|
-
if (entered
|
|
392
|
+
if (entered == null) { ctx.ui.notify("Login cancelled.", "info"); return; }
|
|
294
393
|
apiKey = entered.trim() || null;
|
|
295
394
|
}
|
|
296
395
|
|
|
@@ -308,6 +407,20 @@ export default async function (pi: ExtensionAPI) {
|
|
|
308
407
|
return;
|
|
309
408
|
}
|
|
310
409
|
|
|
410
|
+
// Apply model filter if the template defines one (keeps only free/known models).
|
|
411
|
+
if (tpl.modelFilter && tpl.modelFilter.length > 0) {
|
|
412
|
+
const filterSet = new Set(tpl.modelFilter);
|
|
413
|
+
const filtered = models.filter((m) => filterSet.has(m.id));
|
|
414
|
+
if (filtered.length > 0) {
|
|
415
|
+
models = filtered;
|
|
416
|
+
} else {
|
|
417
|
+
ctx.ui.notify(
|
|
418
|
+
`None of the expected free models were found — registering all ${models.length} model(s) returned by the provider. The provider may have renamed their models.`,
|
|
419
|
+
"warning"
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
311
424
|
// Step 5 — save to config and register with pi
|
|
312
425
|
config.providers[key] = {
|
|
313
426
|
displayName: tpl.displayName,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@billjr99/pi-openai-compat",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
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",
|