diff --git a/open-sse/handlers/systemoneCore.js b/open-sse/handlers/systemoneCore.js index 82da570d..4fcb3004 100644 --- a/open-sse/handlers/systemoneCore.js +++ b/open-sse/handlers/systemoneCore.js @@ -19,7 +19,8 @@ export async function handleSystemoneCore({ }) { const { provider, model } = modelInfo; const cfg = PROVIDER_MEDIA[provider]?.systemoneConfig; - if (!cfg?.baseUrl) { + const targetUrl = credentials?.providerSpecificData?.baseUrl || cfg?.baseUrl; + if (!targetUrl) { return createErrorResult( HTTP_STATUS.BAD_REQUEST, `Provider '${provider}' does not support System One.` @@ -49,7 +50,7 @@ export async function handleSystemoneCore({ let providerResponse; try { - providerResponse = await fetch(cfg.baseUrl, { + providerResponse = await fetch(targetUrl, { method: "POST", headers, body: JSON.stringify(requestBody), diff --git a/open-sse/providers/registry/index.js b/open-sse/providers/registry/index.js index 6c9d1f41..17d1fea9 100644 --- a/open-sse/providers/registry/index.js +++ b/open-sse/providers/registry/index.js @@ -131,6 +131,7 @@ import p127 from "./atria.js"; import p129 from "./agnes.js"; import p130 from "./bai.js"; import p131 from "./tinyfish.js"; +import p132 from "./v1m.js"; export default [ p0, p1, @@ -262,4 +263,5 @@ export default [ p129, p130, p131, + p132, ]; diff --git a/open-sse/providers/registry/v1m.js b/open-sse/providers/registry/v1m.js new file mode 100644 index 00000000..9028785c --- /dev/null +++ b/open-sse/providers/registry/v1m.js @@ -0,0 +1,31 @@ +export default { + id: "v1m", + priority: 45, + alias: "v1m", + aliases: ["systemone", "jev"], + uiAlias: "v1m", + display: { + name: "v1m (System One)", + icon: "psychology", + color: "#6366F1", + textIcon: "V1", + website: "https://v1m.ir", + notice: { + text: "v1m System One calibrated decision engine. Fast probabilistic evaluations over state and questions.", + apiKeyUrl: "https://v1m.ir", + }, + }, + category: "apikey", + authType: "apikey", + hasProviderSpecificData: true, + models: [ + { id: "rev-latest", name: "v1m Rev Latest (Calibrated)", kind: "systemone" }, + { id: "v1m-decision-engine", name: "v1m Decision Engine", kind: "systemone" }, + ], + serviceKinds: ["systemone"], + systemoneConfig: { + baseUrl: "https://v1m.ir/v1/systemone", + authType: "apikey", + authHeader: "bearer", + }, +}; diff --git a/public/providers/v1m.png b/public/providers/v1m.png new file mode 100644 index 00000000..5bfda742 Binary files /dev/null and b/public/providers/v1m.png differ diff --git a/src/shared/constants/providers.js b/src/shared/constants/providers.js index 1e5f30f0..fa289469 100644 --- a/src/shared/constants/providers.js +++ b/src/shared/constants/providers.js @@ -1,6 +1,6 @@ // Provider definitions import REGISTRY from "open-sse/providers/registry/index.js"; -import { RISK_NOTICE } from "@/shared/constants/providersDisplay"; +import { RISK_NOTICE } from "@/shared/constants/providersDisplay.js"; const MEDIA_ENTRY_KEYS = [ "serviceKinds", "ttsConfig", "sttConfig", "embeddingConfig", diff --git a/tests/unit/v1m-systemone-provider.test.js b/tests/unit/v1m-systemone-provider.test.js new file mode 100644 index 00000000..39a44d46 --- /dev/null +++ b/tests/unit/v1m-systemone-provider.test.js @@ -0,0 +1,29 @@ +import { describe, expect, it } from "vitest"; +import REGISTRY from "../../open-sse/providers/registry/index.js"; +import { PROVIDER_MEDIA } from "../../open-sse/providers/index.js"; +import { AI_PROVIDERS, getProvidersByKind } from "@/shared/constants/providers"; + +describe("v1m System One provider", () => { + const entry = REGISTRY.find((e) => e.id === "v1m"); + + it("is registered as a System One apikey provider", () => { + expect(entry).toBeDefined(); + expect(entry.category).toBe("apikey"); + expect(entry.serviceKinds).toEqual(["systemone"]); + expect(PROVIDER_MEDIA["v1m"]?.systemoneConfig?.baseUrl).toBe("https://v1m.ir/v1/systemone"); + }); + + it("appears in getProvidersByKind('systemone')", () => { + const list = getProvidersByKind("systemone"); + const found = list.find((p) => p.id === "v1m"); + expect(found).toBeDefined(); + expect(found.alias).toBe("v1m"); + expect(found.systemoneConfig?.baseUrl).toBe("https://v1m.ir/v1/systemone"); + }); + + it("exposes calibrated models", () => { + const ids = (entry.models || []).map((m) => m.id); + expect(ids).toContain("rev-latest"); + expect(ids).toContain("v1m-decision-engine"); + }); +});