diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ba763be40..d206d02ddc 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ## [Windows] Unreleased +- Settings providers: show the FLORA Workspace ID and Fireworks account slug fields, which were defined but never displayed, so they no longer need the `FLORA_WORKSPACE_ID` / `FIREWORKS_ACCOUNT_SLUG` environment variables. - OpenAI API: each Admin refresh also reads the last hour of 1-minute usage from the Admin Usage API (input plus output tokens, cached input included, Batch API traffic kept out of limit headroom) and carries a Tokens/min grid with a reporting frontier, so buckets that arrive late show as pending instead of zero. The backend can also load 15-minute, 1-hour or 6-hour windows, read per-project rate-limit caps, and measure headroom against manual per-model organization limits stored in settings. The per-refresh request can be turned off, and a failure never affects the daily usage. The menu bar token comes in a later release (upstream #4495). - OpenAI API: the card shows the last-hour Tokens/min grid (latest, peak, 5-minute average, reporting frontier, and pending minutes drawn as outlines), and Settings > Providers > OpenAI adds a Live Usage section with a refresh switch, a per-model organization limits editor, a 15-minute / 1-hour / 6-hour window with per-model rows, and the organization caps list, which stays hidden when a project id is saved (upstream #4495). - Tray: add a **Progress bars stacked** menu bar style that draws the session and weekly meters as two equal-height rows on the single tray icon, with the same windows and pace tint as **Meter bars**; older settings files keep their style (upstream #4436). diff --git a/apps/desktop-tauri/src/surfaces/settings/providers/sections/CredentialsDispatcher.test.tsx b/apps/desktop-tauri/src/surfaces/settings/providers/sections/CredentialsDispatcher.test.tsx new file mode 100644 index 0000000000..7c9d6aa4e4 --- /dev/null +++ b/apps/desktop-tauri/src/surfaces/settings/providers/sections/CredentialsDispatcher.test.tsx @@ -0,0 +1,36 @@ +import { render, screen } from "@testing-library/react"; +import { beforeEach, describe, expect, it, vi } from "vitest"; +import type { LocaleKey } from "../../../../i18n/keys"; +import { getProviderWorkspaceId } from "../../../../lib/tauri"; +import { CredentialsDispatcher } from "./CredentialsDispatcher"; + +vi.mock("../../../../lib/tauri", async (importOriginal) => ({ + ...(await importOriginal()), + getProviderWorkspaceId: vi.fn(), + setProviderWorkspaceId: vi.fn(), +})); + +const t = (key: LocaleKey) => key as string; + +describe("CredentialsDispatcher", () => { + beforeEach(() => { + vi.clearAllMocks(); + vi.mocked(getProviderWorkspaceId).mockResolvedValue(null); + }); + + it.each([ + ["flora", "FLORA workspace"], + ["fireworks", "Fireworks account"], + ["cosmic", "CosmicProjectIdTitle"], + ["openaiapi", "OpenAiAdminApiTitle"], + ])("shows the workspace field for %s", async (providerId, title) => { + render(); + expect(await screen.findByText(title)).toBeInTheDocument(); + expect(screen.getByRole("textbox")).toBeInTheDocument(); + }); + + it("renders nothing for providers without a credentials extra", () => { + const { container } = render(); + expect(container).toBeEmptyDOMElement(); + }); +}); diff --git a/apps/desktop-tauri/src/surfaces/settings/providers/sections/CredentialsDispatcher.tsx b/apps/desktop-tauri/src/surfaces/settings/providers/sections/CredentialsDispatcher.tsx index bf0eb4de3e..8a6cd322da 100644 --- a/apps/desktop-tauri/src/surfaces/settings/providers/sections/CredentialsDispatcher.tsx +++ b/apps/desktop-tauri/src/surfaces/settings/providers/sections/CredentialsDispatcher.tsx @@ -3,7 +3,7 @@ import { GeminiCliCreds } from "./credentials/GeminiCliCreds"; import { VertexAiCreds } from "./credentials/VertexAiCreds"; import { JetBrainsCreds } from "./credentials/JetBrainsCreds"; import { KiroCreds } from "./credentials/KiroCreds"; -import { OpenAiExtras } from "./credentials/OpenAiExtras"; +import { hasWorkspaceExtra, OpenAiExtras } from "./credentials/OpenAiExtras"; import { OpenRouterManagementCreds } from "./credentials/OpenRouterManagementCreds"; interface Props { @@ -26,23 +26,11 @@ export function CredentialsDispatcher({ providerId, t }: Props) { return ; case "kiro": return ; - case "openaiapi": - return ; - case "litellm": - case "llmman": - case "devin": - case "opencodego": - case "zed": - case "sub2api": - case "llmproxy": - case "xai": - case "gitkraken": - case "exa": - case "cosmic": - return ; case "openrouter": return ; default: - return null; + return hasWorkspaceExtra(providerId) ? ( + + ) : null; } } diff --git a/apps/desktop-tauri/src/surfaces/settings/providers/sections/credentials/OpenAiExtras.tsx b/apps/desktop-tauri/src/surfaces/settings/providers/sections/credentials/OpenAiExtras.tsx index 3891aa065b..4161384a51 100644 --- a/apps/desktop-tauri/src/surfaces/settings/providers/sections/credentials/OpenAiExtras.tsx +++ b/apps/desktop-tauri/src/surfaces/settings/providers/sections/credentials/OpenAiExtras.tsx @@ -97,6 +97,11 @@ export function OpenAiExtras({ providerId = "openaiapi", t }: Props) { return null; } +/** Providers that show a workspace, organization or base-URL field next to their key. */ +export function hasWorkspaceExtra(providerId: string): boolean { + return WORKSPACE_EXTRA_IDS[providerId] === true; +} + const WORKSPACE_EXTRA_IDS: Record = { openaiapi: true, litellm: true,