@billjr99/pi-openai-compat 1.1.30 → 1.1.32

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 CHANGED
@@ -67,6 +67,11 @@ If pi is already running when you install, type `/reload` first.
67
67
  | **GMI Cloud** | `https://api.gmi-serving.com/v1` | API key from console.gmicloud.ai → Organization Settings → API Keys |
68
68
  | **Token Harbor** | `https://tokenharbor.ai/v1` | `thk_live_...` Universal Key from tokenharbor.ai/dashboard/api-keys |
69
69
  | **Atria ASI** | `https://api.atria-asi.ai/v1` | `atr_...` key from api.atria-asi.ai/console/keys (Google sign-in) |
70
+ | **Unbiased AI** | `https://api.unbiased.ai/v1` | `sk_...` key from platform.unbiased.ai (signup reviewed by hand) |
71
+ | **Kilo AI** | `https://api.kilo.ai/api/gateway` | API key from app.kilo.ai → Your Profile (personal account), at the bottom of the page; needs account credits |
72
+ | **ModelScope** | `https://api-inference.modelscope.cn/v1` | `ms-...` SDK token from modelscope.cn/my/myaccesstoken |
73
+ | **Aion Labs** | `https://api.aionlabs.ai/v1` | API key from aionlabs.ai/app/api-keys (aionlabs.ai/docs) |
74
+ | **Agnes AI** | `https://apihub.agnes-ai.com/v1` | `sk-...` key from the Agnes console at platform.agnes-ai.com (wiki.agnes-ai.com) |
70
75
  | **Ollama (local)** | `http://localhost:11434/v1` (editable) | Optional bearer token; leave blank for a default local install |
71
76
  | **Ollama Cloud** | `https://ollama.com/v1` | Ollama Cloud API key from ollama.com |
72
77
  | **llmproxy** | `http://localhost:8080/v1` (editable) | Keyless by default; bearer token if your instance requires one |
package/add-provider.sh CHANGED
@@ -66,6 +66,36 @@ const BUILTIN = {
66
66
  keyless: false,
67
67
  keyHint: "api.atria-asi.ai/console/keys (Google sign-in; keys look like atr_...; docs at api.atria-asi.ai/docs)",
68
68
  },
69
+ unbiased_ai: {
70
+ displayName: "Unbiased AI",
71
+ baseUrl: "https://api.unbiased.ai/v1",
72
+ keyless: false,
73
+ keyHint: "platform.unbiased.ai (signup is reviewed by hand; keys look like sk_...)",
74
+ },
75
+ kilo: {
76
+ displayName: "Kilo AI",
77
+ baseUrl: "https://api.kilo.ai/api/gateway",
78
+ keyless: false,
79
+ keyHint: "app.kilo.ai → Your Profile on your personal account (not an organization), at the bottom of the page; needs account credits (docs at kilo.ai/docs/gateway)",
80
+ },
81
+ modelscope: {
82
+ displayName: "ModelScope",
83
+ baseUrl: "https://api-inference.modelscope.cn/v1",
84
+ keyless: false,
85
+ keyHint: "modelscope.cn/my/myaccesstoken (SDK token, format ms-...; docs at modelscope.cn/docs/model-service/API-Inference/intro)",
86
+ },
87
+ aion_labs: {
88
+ displayName: "Aion Labs",
89
+ baseUrl: "https://api.aionlabs.ai/v1",
90
+ keyless: false,
91
+ keyHint: "aionlabs.ai/app/api-keys (docs at aionlabs.ai/docs/api-reference)",
92
+ },
93
+ agnes_ai: {
94
+ displayName: "Agnes AI",
95
+ baseUrl: "https://apihub.agnes-ai.com/v1",
96
+ keyless: false,
97
+ keyHint: "platform.agnes-ai.com → API Key management (keys look like sk-...; docs at wiki.agnes-ai.com)",
98
+ },
69
99
  };
70
100
 
71
101
  // README "Auth" column text for the built-in providers, used only by patchreadme.
@@ -75,6 +105,11 @@ const BUILTIN_AUTH = {
75
105
  gmi: "API key from console.gmicloud.ai → Organization Settings → API Keys",
76
106
  tokenharbor: "`thk_live_...` Universal Key from tokenharbor.ai/dashboard/api-keys",
77
107
  atria_asi: "`atr_...` key from api.atria-asi.ai/console/keys (Google sign-in)",
108
+ unbiased_ai: "`sk_...` key from platform.unbiased.ai (signup reviewed by hand)",
109
+ kilo: "API key from app.kilo.ai → Your Profile (personal account), at the bottom of the page; needs account credits",
110
+ modelscope: "`ms-...` SDK token from modelscope.cn/my/myaccesstoken",
111
+ aion_labs: "API key from aionlabs.ai/app/api-keys (aionlabs.ai/docs)",
112
+ agnes_ai: "`sk-...` key from the Agnes console at platform.agnes-ai.com (wiki.agnes-ai.com)",
78
113
  };
79
114
 
80
115
  /**
@@ -151,8 +186,9 @@ function normalizeModels(body, idField, keepTask) {
151
186
  else if (json && typeof json === "object") {
152
187
  if (Array.isArray(json.data)) raw = json.data;
153
188
  else if (Array.isArray(json.result)) raw = json.result;
189
+ else if (Array.isArray(json.models)) raw = json.models;
154
190
  }
155
- if (!raw) throw new Error('expected an array or an object with a "data" or "result" array');
191
+ if (!raw) throw new Error('expected an array or an object with a "data", "result" or "models" array');
156
192
  const field = idField || "id";
157
193
  return raw
158
194
  .filter((m) => {
package/index.ts CHANGED
@@ -405,6 +405,65 @@ export const TEMPLATES: Record<string, {
405
405
  // already sends, so no modelsUrl or fallbackModels override is needed.
406
406
  keyHint: "api.atria-asi.ai/console/keys (Google sign-in; keys look like atr_...; docs at api.atria-asi.ai/docs)",
407
407
  },
408
+ unbiased_ai: {
409
+ displayName: "Unbiased AI",
410
+ baseUrl: "https://api.unbiased.ai/v1",
411
+ keyless: false,
412
+ // One model, "pareto", a blend of frontier and open models. The endpoint
413
+ // answers both /v1/chat/completions and Anthropic's /v1/messages and takes
414
+ // either Authorization: Bearer or x-api-key; pi is registered with the
415
+ // OpenAI pair, which is what registerProvider and fetchModels already send.
416
+ // GET /v1/models is registered and key-gated (a well-formed sk_ key gets
417
+ // "Invalid API key" rather than a format complaint), so no modelsUrl or
418
+ // fallbackModels override is needed.
419
+ keyHint: "platform.unbiased.ai (signup is reviewed by hand; keys look like sk_...)",
420
+ },
421
+ kilo: {
422
+ displayName: "Kilo AI",
423
+ baseUrl: "https://api.kilo.ai/api/gateway",
424
+ keyless: false,
425
+ // Multi-vendor gateway; the base path is /api/gateway, not /v1. GET
426
+ // /api/gateway/models answers 200 without a key and returns an
427
+ // OpenRouter-shaped {"data": [...]} catalog (~380 models, ids like
428
+ // anthropic/claude-sonnet-5), so no modelsUrl or fallbackModels override
429
+ // is needed. Inference itself needs a key and account credits.
430
+ keyHint: "app.kilo.ai → Your Profile on your personal account (not an organization), at the bottom of the page; needs account credits (docs at kilo.ai/docs/gateway)",
431
+ },
432
+ modelscope: {
433
+ displayName: "ModelScope",
434
+ baseUrl: "https://api-inference.modelscope.cn/v1",
435
+ keyless: false,
436
+ // Alibaba's API-Inference service. GET /v1/models answers 200 without a
437
+ // key in the plain OpenAI {"data": [...]} shape, so the default discovery
438
+ // path works as is. Free tier is an account-wide 2,000 requests/day.
439
+ keyHint: "modelscope.cn/my/myaccesstoken (SDK token, format ms-...; docs at modelscope.cn/docs/model-service/API-Inference/intro)",
440
+ },
441
+ aion_labs: {
442
+ displayName: "Aion Labs",
443
+ baseUrl: "https://api.aionlabs.ai/v1",
444
+ keyless: false,
445
+ // Aion's own API reference documents GET /v1/models as needing no
446
+ // authentication and returning its array under a top-level "models" key
447
+ // rather than "data". fetchModels normalizes that shape, so no modelsUrl
448
+ // or fallbackModels override is needed. Four models as of
449
+ // September 2026 (aion-2.0, aion-3.0, aion-3.0-mini, aion-rp-llama-3.1-8b).
450
+ keyHint: "aionlabs.ai/app/api-keys (docs at aionlabs.ai/docs/api-reference)",
451
+ },
452
+ agnes_ai: {
453
+ displayName: "Agnes AI",
454
+ baseUrl: "https://apihub.agnes-ai.com/v1",
455
+ keyless: false,
456
+ // Multimodal gateway. GET /v1/models is key-gated (it answers 401 "Token
457
+ // not provided", where an unknown /v1 path answers 404), which is exactly
458
+ // what fetchModels already sends, so no override is needed. The catalog
459
+ // also carries image and video model ids (agnes-image-*, agnes-video-*);
460
+ // they are registered too and will show up in /model, but only the text
461
+ // models serve chat/completions: the free flash tier (agnes-3.0-flash,
462
+ // agnes-2.5-flash, agnes-2.0-flash) and the paid agnes-2.5-pro pair. No
463
+ // modelFilter is set because the live id list could not be confirmed
464
+ // without a key, and a filter that misses would register nothing.
465
+ keyHint: "platform.agnes-ai.com → API Key management (keys look like sk-...; docs at wiki.agnes-ai.com)",
466
+ },
408
467
  custom: {
409
468
  displayName: "Custom Endpoint",
410
469
  baseUrl: "",
@@ -639,22 +698,24 @@ export async function fetchModels(
639
698
  // Normalize the various shapes /models can return:
640
699
  // - OpenAI style: {"data": [...]}
641
700
  // - Cloudflare / some gateways: {"result": [...]}
701
+ // - Aion Labs: {"models": [...]}
642
702
  // - Together (and a few others): [...] (bare JSON array)
643
703
  const json = (await resp.json()) as unknown;
644
704
  let raw: RawModel[] | undefined;
645
705
  if (Array.isArray(json)) {
646
706
  raw = json as RawModel[];
647
707
  } else if (json && typeof json === "object") {
648
- const obj = json as { data?: unknown; result?: unknown };
708
+ const obj = json as { data?: unknown; result?: unknown; models?: unknown };
649
709
  if (Array.isArray(obj.data)) raw = obj.data as RawModel[];
650
710
  else if (Array.isArray(obj.result)) raw = obj.result as RawModel[];
711
+ else if (Array.isArray(obj.models)) raw = obj.models as RawModel[];
651
712
  }
652
713
  if (!raw) {
653
714
  // `url` may be an override (e.g. /catalog/models, /ai/models/search), so
654
715
  // keep the wording generic rather than referring specifically to /models.
655
716
  throw new Error(
656
717
  `Unexpected model catalog payload shape from ${url} ` +
657
- `(expected an array or an object with a "data" or "result" array).`
718
+ `(expected an array or an object with a "data", "result" or "models" array).`
658
719
  );
659
720
  }
660
721
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@billjr99/pi-openai-compat",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
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",