mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-06 07:12:12 +03:00
feat(providers): add Pioneer AI (Fastino Labs) provider (#4909)
Integrated into release/v3.8.37 — providers.ts apikey block re-homed onto god-file-split src/shared/constants/providers/apikey/frontier-labs.ts (inline APIKEY_PROVIDERS no longer exists); registry/pioneer + providers/index.ts applied clean; 6/6 green.
This commit is contained in:
committed by
GitHub
parent
ddee9a2ac2
commit
4a0ee5d2e9
@@ -10,6 +10,8 @@ _In development — bullets added per PR; finalized at release._
|
||||
|
||||
### 🔧 Bug Fixes
|
||||
|
||||
- **feat(providers):** add Pioneer AI (Fastino Labs) provider — OpenAI-compatible chat completions at `api.pioneer.ai/v1`. Registered with alias `pn`, `X-API-Key` auth, and a catalog of 10 open-tier serverless models (Qwen3, Llama 3.1/3.2, Gemma 3, SmolLM3). Free $75 credits, no credit card required. Gated enterprise models (Claude/GPT/Gemini) require prior fine-tuning on the Pioneer platform and are intentionally excluded from the catalog. (thanks @HikiNarou)
|
||||
|
||||
- **feat(sse): auto-promote successful combo model**: a new opt-in `comboAutoPromoteEnabled` setting reorders a combo's persisted model list so that, when a combo model responds successfully, it is moved to position #1 for future requests. (thanks @arssnndr)
|
||||
|
||||
- **fix(sse):** dense, deterministic `response.output` ordering in `response.completed` — items are now sorted by their actual `output_index` (via a recorded-as-emitted accumulator + stable sort) instead of being rebuilt from unordered state dicts; `normalizeOutputIndex` replaces fragile `parseInt` calls for robust index coercion; superseded tool calls (replaced at the same index mid-stream) are excluded from the final output array. (thanks @Marco9113)
|
||||
|
||||
@@ -167,6 +167,7 @@ import { openadapterProvider } from "./registry/openadapter/index.ts";
|
||||
import { ditProvider } from "./registry/dit/index.ts";
|
||||
import { tokenrouterProvider } from "./registry/tokenrouter/index.ts";
|
||||
import { codebuddy_cnProvider } from "./registry/codebuddy-cn/index.ts";
|
||||
import { pioneerProvider } from "./registry/pioneer/index.ts";
|
||||
|
||||
export const REGISTRY: Record<string, RegistryEntry> = {
|
||||
aimlapi: aimlapiProvider,
|
||||
@@ -336,4 +337,5 @@ export const REGISTRY: Record<string, RegistryEntry> = {
|
||||
dit: ditProvider,
|
||||
tokenrouter: tokenrouterProvider,
|
||||
"codebuddy-cn": codebuddy_cnProvider,
|
||||
pioneer: pioneerProvider,
|
||||
};
|
||||
|
||||
41
open-sse/config/providers/registry/pioneer/index.ts
Normal file
41
open-sse/config/providers/registry/pioneer/index.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import type { RegistryEntry } from "../../shared.ts";
|
||||
|
||||
/**
|
||||
* Pioneer AI by Fastino Labs — OpenAI-compatible chat completions.
|
||||
*
|
||||
* Endpoint: https://api.pioneer.ai/v1/chat/completions
|
||||
* Auth: X-API-Key header with a pio_sk_... key (Bearer also accepted upstream).
|
||||
*
|
||||
* Only models with supports_on_demand_inference=true work directly with a bare
|
||||
* pio_sk_ key. Gated/enterprise models (Claude/GPT/Gemini etc.) require a prior
|
||||
* fine-tuning job and are called via the resulting job id, not the base model id.
|
||||
*
|
||||
* Source of truth for models: GET https://api.pioneer.ai/base-models
|
||||
* ?supports_inference=true&task_type=decoder
|
||||
* filter: supports_on_demand_inference=true
|
||||
*/
|
||||
export const pioneerProvider: RegistryEntry = {
|
||||
id: "pioneer",
|
||||
alias: "pn",
|
||||
format: "openai",
|
||||
executor: "default",
|
||||
baseUrl: "https://api.pioneer.ai/v1/chat/completions",
|
||||
authType: "apikey",
|
||||
// Pioneer standardises on X-API-Key (preferred over Bearer).
|
||||
// The default executor resolves "x-api-key" to the X-API-Key header.
|
||||
authHeader: "x-api-key",
|
||||
models: [
|
||||
// === Open-tier serverless inference ===
|
||||
// These models support on-demand inference with any pio_sk_ key.
|
||||
{ id: "Qwen/Qwen3-32B", name: "Qwen3 32B" },
|
||||
{ id: "Qwen/Qwen3.6-27B", name: "Qwen3.6 27B" },
|
||||
{ id: "Qwen/Qwen3.5-9B", name: "Qwen3.5 9B" },
|
||||
{ id: "Qwen/Qwen3-8B", name: "Qwen3 8B" },
|
||||
{ id: "Qwen/Qwen3-4B-Base", name: "Qwen3 4B Base" },
|
||||
{ id: "Qwen/Qwen3-1.7B-Base", name: "Qwen3 1.7B Base" },
|
||||
{ id: "meta-llama/Llama-3.1-8B-Instruct", name: "Llama 3.1 8B Instruct" },
|
||||
{ id: "meta-llama/Llama-3.2-1B-Instruct", name: "Llama 3.2 1B Instruct" },
|
||||
{ id: "google/gemma-3-4b-pt", name: "Gemma 3 4B (Pretrained)" },
|
||||
{ id: "HuggingFaceTB/SmolLM3-3B-Base", name: "SmolLM3 3B Base" },
|
||||
],
|
||||
};
|
||||
@@ -27,6 +27,23 @@ export const APIKEY_PROVIDERS_FRONTIER = {
|
||||
hasFree: true,
|
||||
freeNote: "$10/month recurring free API credits",
|
||||
},
|
||||
pioneer: {
|
||||
id: "pioneer",
|
||||
alias: "pn",
|
||||
name: "Pioneer AI",
|
||||
icon: "rocket_launch",
|
||||
color: "#7C5CFF",
|
||||
textIcon: "PN",
|
||||
website: "https://pioneer.ai",
|
||||
notice: {
|
||||
text: "Pioneer AI by Fastino Labs. Free $75 usage credits, no credit card required. Use API key auth with a pio_sk_... key. Only open-tier models (Qwen3, Llama, Gemma, SmolLM) work directly — gated models (Claude/GPT/Gemini) require prior fine-tuning via the Pioneer platform.",
|
||||
apiKeyUrl: "https://agent.pioneer.ai/settings/api-keys",
|
||||
signupUrl: "https://agent.pioneer.ai/auth",
|
||||
},
|
||||
hasFree: true,
|
||||
freeNote: "$75 free usage credits — no credit card required",
|
||||
serviceKinds: ["llm"],
|
||||
},
|
||||
anthropic: {
|
||||
id: "anthropic",
|
||||
alias: "anthropic",
|
||||
|
||||
83
tests/unit/pioneer-provider.test.ts
Normal file
83
tests/unit/pioneer-provider.test.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import { APIKEY_PROVIDERS, AI_PROVIDERS } from "../../src/shared/constants/providers.ts";
|
||||
import { REGISTRY } from "../../open-sse/config/providerRegistry.ts";
|
||||
import { PROVIDERS as LEGACY_PROVIDERS } from "../../open-sse/config/constants.ts";
|
||||
|
||||
test("pioneer is registered as an API-key provider in the UI catalog", () => {
|
||||
const pioneer = APIKEY_PROVIDERS.pioneer;
|
||||
assert.ok(pioneer, "APIKEY_PROVIDERS.pioneer must exist");
|
||||
assert.equal(pioneer.id, "pioneer");
|
||||
assert.equal(pioneer.alias, "pn");
|
||||
assert.equal(pioneer.name, "Pioneer AI");
|
||||
assert.equal(pioneer.color, "#7C5CFF");
|
||||
});
|
||||
|
||||
test("pioneer appears in AI_PROVIDERS (composed view)", () => {
|
||||
const pioneer = AI_PROVIDERS.pioneer;
|
||||
assert.ok(pioneer, "AI_PROVIDERS.pioneer must exist");
|
||||
assert.equal(pioneer.id, "pioneer");
|
||||
});
|
||||
|
||||
test("pioneer registry entry is correct (format, auth, executor)", () => {
|
||||
const pioneer = REGISTRY.pioneer;
|
||||
assert.ok(pioneer, "REGISTRY.pioneer must exist");
|
||||
assert.equal(pioneer.format, "openai");
|
||||
assert.equal(pioneer.executor, "default");
|
||||
assert.equal(pioneer.authType, "apikey");
|
||||
// X-API-Key auth (not Bearer) — matches upstream preference
|
||||
assert.equal(pioneer.authHeader, "x-api-key");
|
||||
assert.equal(pioneer.baseUrl, "https://api.pioneer.ai/v1/chat/completions");
|
||||
assert.equal(pioneer.alias, "pn");
|
||||
});
|
||||
|
||||
test("pioneer has open-tier models with supports_on_demand_inference", () => {
|
||||
const pioneer = REGISTRY.pioneer;
|
||||
const ids = pioneer.models.map((m) => m.id);
|
||||
// Qwen3 models
|
||||
assert.ok(ids.includes("Qwen/Qwen3-32B"), "must include Qwen3 32B");
|
||||
assert.ok(ids.includes("Qwen/Qwen3-8B"), "must include Qwen3 8B");
|
||||
// Llama models
|
||||
assert.ok(ids.includes("meta-llama/Llama-3.1-8B-Instruct"), "must include Llama 3.1 8B Instruct");
|
||||
assert.ok(ids.includes("meta-llama/Llama-3.2-1B-Instruct"), "must include Llama 3.2 1B Instruct");
|
||||
// At least 10 models total (open-tier catalog)
|
||||
assert.ok(pioneer.models.length >= 10, `expected >= 10 models, got ${pioneer.models.length}`);
|
||||
// Gated models (Claude/GPT/Gemini) must NOT appear — they require fine-tuning first
|
||||
assert.ok(
|
||||
!ids.some((id) => id.toLowerCase().includes("claude")),
|
||||
"gated Claude models must not be in catalog"
|
||||
);
|
||||
assert.ok(
|
||||
!ids.some((id) => id.toLowerCase().includes("gpt")),
|
||||
"gated GPT models must not be in catalog"
|
||||
);
|
||||
assert.ok(
|
||||
!ids.some((id) => id.toLowerCase().includes("gemini")),
|
||||
"gated Gemini models must not be in catalog"
|
||||
);
|
||||
});
|
||||
|
||||
test("pioneer legacy PROVIDERS entry resolves from generated map", () => {
|
||||
const legacy = LEGACY_PROVIDERS.pioneer;
|
||||
assert.ok(legacy, "LEGACY_PROVIDERS.pioneer must exist (generated from REGISTRY)");
|
||||
assert.equal(legacy.format, "openai");
|
||||
// Should not have OAuth fields — pioneer is API-key only
|
||||
assert.equal(legacy.clientId, undefined);
|
||||
assert.equal(legacy.clientSecret, undefined);
|
||||
assert.equal(legacy.tokenUrl, undefined);
|
||||
});
|
||||
|
||||
test("pioneer has hasFree flag and free signup notice", () => {
|
||||
const pioneer = APIKEY_PROVIDERS.pioneer;
|
||||
assert.equal(pioneer.hasFree, true, "pioneer should advertise free tier");
|
||||
assert.ok(pioneer.freeNote?.includes("$75"), "freeNote should mention $75 credits");
|
||||
assert.ok(
|
||||
pioneer.notice?.signupUrl?.includes("pioneer.ai"),
|
||||
"signupUrl should point to pioneer.ai"
|
||||
);
|
||||
assert.ok(
|
||||
pioneer.notice?.apiKeyUrl?.includes("pioneer.ai"),
|
||||
"apiKeyUrl should point to pioneer.ai"
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user