diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index 2380f8725d..40dd6d56b6 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -4632,9 +4632,9 @@ "perplexitySearchSharedKeyInfo": "Perplexity Search Shared Key Info", "perplexityWebCookieHint": "Perplexity Web Cookie Hint", "perplexityWebCookiePlaceholder": "Perplexity Web Cookie Placeholder", - "personalAccessTokenLabel": "Personal Access Token Label", - "qoderPatHint": "Qoder Pat Hint", - "qoderPatPlaceholder": "Qoder Pat Placeholder", + "personalAccessTokenLabel": "Personal Access Token", + "qoderPatHint": "Paste your Qoder Personal Access Token (PAT). Generate one from Qoder → Settings → Personal Access Tokens.", + "qoderPatPlaceholder": "Your Qoder personal access token", "rateLimitOverridesSection": "Rate Limit Overrides", "rateLimitOverridesMaxConcurrentHint": "Max concurrent requests override for this connection. Overrides the account-level cap.", "rateLimitOverridesMaxConcurrentLabel": "Max Concurrent (Rate Limit)", diff --git a/src/shared/constants/providers/apikey/enterprise-cloud.ts b/src/shared/constants/providers/apikey/enterprise-cloud.ts index 614ca9e49c..66fa154f95 100644 --- a/src/shared/constants/providers/apikey/enterprise-cloud.ts +++ b/src/shared/constants/providers/apikey/enterprise-cloud.ts @@ -143,7 +143,7 @@ export const APIKEY_PROVIDERS_ENTERPRISE = { icon: "cloud", color: "#4F0599", textIcon: "SCW", - website: "https://www.scaleway.com/en/ai/generative-apis", + website: "https://www.scaleway.com/en/docs/ai-data/generative-apis/", hasFree: true, freeNote: "1M free tokens for new accounts — EU/GDPR compliant (Paris), Qwen3 235B & Llama 70B", }, diff --git a/src/shared/constants/providers/apikey/inference-hosts.ts b/src/shared/constants/providers/apikey/inference-hosts.ts index a4c17494ff..f019501590 100644 --- a/src/shared/constants/providers/apikey/inference-hosts.ts +++ b/src/shared/constants/providers/apikey/inference-hosts.ts @@ -11,9 +11,11 @@ export const APIKEY_PROVIDERS_INFERENCE = { color: "#0F6FFF", textIcon: "TG", website: "https://www.together.ai", - hasFree: true, - freeNote: - "$25 signup credits + 3 permanently free models: Llama 3.3 70B, Vision, DeepSeek-R1 distill", + hasFree: false, + notice: { + text: "No free tier — Together AI is fully prepaid and requires a minimum $5 credit purchase (valid payment method) before API calls work. The former $25 signup credit was retired.", + apiKeyUrl: "https://api.together.ai/settings/api-keys", + }, }, fireworks: { id: "fireworks", diff --git a/src/shared/constants/providers/web-cookie.ts b/src/shared/constants/providers/web-cookie.ts index 43a9ec0e33..337d53e23f 100644 --- a/src/shared/constants/providers/web-cookie.ts +++ b/src/shared/constants/providers/web-cookie.ts @@ -125,7 +125,7 @@ export const WEB_COOKIE_PROVIDERS = { textIcon: "M365", website: "https://m365.cloud.microsoft/chat", authHint: - "Paste the access_token and account-specific Chathub path from the Microsoft 365 Copilot WebSocket URL.", + "Sign in at m365.cloud.microsoft/chat, then open DevTools → Network → filter 'WS' → click the Chathub WebSocket connection. Copy both the access_token query parameter AND the account-specific Chathub path segment from its request URL (wss://…/Chathub/?…&access_token=…). It is NOT an Authorization: Bearer header on an XHR/Fetch request. The token is short-lived; this is an unofficial integration.", subscriptionRisk: true, riskNoticeVariant: "webCookie", }, diff --git a/tests/unit/provider-add-ux-i18n-import-warning.test.ts b/tests/unit/provider-add-ux-i18n-import-warning.test.ts index 13add5ce32..43a4dbfe86 100644 --- a/tests/unit/provider-add-ux-i18n-import-warning.test.ts +++ b/tests/unit/provider-add-ux-i18n-import-warning.test.ts @@ -26,6 +26,10 @@ const STUB_KEYS: Array<[string, string]> = [ ["accountIdLabel", "Account Id Label"], ["accountIdPlaceholder", "Account Id Placeholder"], ["accountIdHint", "Account Id Hint"], + // #5487 — Qoder PAT form keys shipped the same auto-generated stub placeholders. + ["personalAccessTokenLabel", "Personal Access Token Label"], + ["qoderPatHint", "Qoder Pat Hint"], + ["qoderPatPlaceholder", "Qoder Pat Placeholder"], ]; for (const [key, stub] of STUB_KEYS) { diff --git a/tests/unit/provider-metadata-5461-5470-5534.test.ts b/tests/unit/provider-metadata-5461-5470-5534.test.ts new file mode 100644 index 0000000000..18fe042846 --- /dev/null +++ b/tests/unit/provider-metadata-5461-5470-5534.test.ts @@ -0,0 +1,46 @@ +import test from "node:test"; +import assert from "node:assert/strict"; + +const { APIKEY_PROVIDERS_ENTERPRISE } = await import( + "../../src/shared/constants/providers/apikey/enterprise-cloud.ts" +); +const { APIKEY_PROVIDERS_INFERENCE } = await import( + "../../src/shared/constants/providers/apikey/inference-hosts.ts" +); +const { WEB_COOKIE_PROVIDERS } = await import("../../src/shared/constants/providers/web-cookie.ts"); + +// #5461 — Scaleway's `website` pointed at https://www.scaleway.com/en/ai/generative-apis +// which returns HTTP 404. The live docs page is /en/docs/ai-data/generative-apis/. +test("#5461 Scaleway website points at a live docs URL, not the 404 marketing path", () => { + const scaleway = (APIKEY_PROVIDERS_ENTERPRISE as Record).scaleway; + assert.ok(scaleway, "scaleway provider must exist"); + assert.equal(scaleway.website, "https://www.scaleway.com/en/docs/ai-data/generative-apis/"); + assert.ok( + !scaleway.website.includes("/en/ai/generative-apis"), + "must not keep the 404 marketing URL" + ); +}); + +// #5470 — Together AI retired its $25 signup credit and is now fully prepaid +// (minimum $5 purchase). The catalog claimed a free tier, so the "Free" badge lied. +test("#5470 Together AI no longer advertises a free tier and warns about the prepaid minimum", () => { + const together = (APIKEY_PROVIDERS_INFERENCE as Record).together; + assert.ok(together, "together provider must exist"); + assert.equal(together.hasFree, false, "Together is prepaid-only — hasFree must be false"); + assert.ok(!together.freeNote, "the stale $25/free-models freeNote must be gone"); + const noticeText: string = together.notice?.text || ""; + assert.ok(noticeText.length > 0, "a prepaid notice must be present"); + assert.ok(!noticeText.includes("$25 signup credits"), "must not repeat the retired $25 claim"); + assert.ok(/prepaid|\$5/i.test(noticeText), "notice must mention the prepaid / $5 minimum"); +}); + +// #5534 — the M365 Copilot authHint gave no concrete steps and the reporter's guessed +// method (Authorization header) is wrong; the credential lives on the Chathub WS URL. +test("#5534 M365 Copilot authHint gives concrete DevTools WebSocket steps", () => { + const m365 = (WEB_COOKIE_PROVIDERS as Record)["copilot-m365-web"]; + assert.ok(m365, "copilot-m365-web provider must exist"); + const hint: string = m365.authHint || ""; + assert.ok(/websocket|\bWS\b/i.test(hint), "hint must point at the WebSocket (WS) tab"); + assert.ok(/DevTools/i.test(hint), "hint must reference DevTools"); + assert.ok(/access_token/.test(hint), "hint must name the access_token"); +});