Files
fusion/packages/dashboard/app/api/planning/models-usage.ts
gsxdsm cb57093d03 refactor: domain folder layout (types, API, core, engine) (#2398)
## Summary

Wave 17 organizes Fusion into **domain folders** (stacks on #2397).

### Layout
- **core/types/** — board, task, agents, settings, merge, workflow,
mesh, …
- **core/src/** — agents, ai, async-stores, workflows, tasks, config,
db, …
- **dashboard/app/api/** — client, tasks, agents, git, missions,
planning, …
- **engine/src/** — agents, auth, execution, merge, missions, overseer,
worktree, …

Root keepers retained for large entrypoints (`store.ts`, `executor.ts`,
`merger.ts`, …).

Public barrels (`@fusion/core`, `@fusion/engine`, `app/api.ts` → legacy)
stay stable.

## Test plan
- [x] `@fusion/core` typecheck
- [x] `@fusion/engine` typecheck (pre-existing playwright-core noise
only)
- [ ] CI merge gate

**Stack:** #2394 → #2397 → **this PR**
2026-08-03 00:20:53 -07:00

95 lines
3.1 KiB
TypeScript

/**
* FNXC:CodeOrganization 2026-07-20-14:00:
* Models registry and usage client API peeled from legacy.ts.
*/
import { api } from "../client/client.js";
// --- Models API ---
/** Available AI model info returned by the models endpoint */
export interface ModelInfo {
provider: string;
id: string;
name: string;
reasoning: boolean;
contextWindow: number;
/** Provider-wide public instance metadata, attached by fetchModels for picker consumers. */
credentialInstances?: ProviderCredentialInstanceSummary[];
}
/** Response from the models endpoint */
/** Public metadata for a configured provider credential; it never contains credential material. */
export interface ProviderCredentialInstanceSummary {
id: string;
isDefault: boolean;
unavailableModelIds?: string[];
}
export interface ModelsResponse {
models: ModelInfo[];
favoriteProviders: string[];
favoriteModels: string[];
defaultProvider?: string;
/** Configured credential instances keyed by provider, omitted by older servers. */
providerInstances?: Record<string, { instances: ProviderCredentialInstanceSummary[] }>;
defaultModelId?: string;
resolvedPlanningProvider?: string;
resolvedPlanningModelId?: string;
}
/** Fetch available AI models from the model registry along with favoriteProviders */
export async function fetchModels(): Promise<ModelsResponse> {
const response = await api<ModelsResponse>("/models");
/*
FNXC:ModelDropdown 2026-08-01-09:49:
Every existing model picker already receives the catalog returned by this client. Attach public provider-instance summaries to those rows so callers that only retain `models` still receive the optional picker availability without a parallel endpoint or a second dropdown implementation.
*/
return {
...response,
models: (response.models ?? []).map((model) => ({
...model,
credentialInstances: response.providerInstances?.[model.provider]?.instances,
})),
};
}
// --- Usage API ---
/** Pace information for weekly usage windows */
export interface UsagePace {
status: "ahead" | "on-track" | "behind";
percentElapsed: number; // 0-100, how much of the window time has passed
message: string; // e.g., "Using 15% over your limit pace"
}
/** Usage window for a provider (e.g., "Session (5h)", "Weekly") */
export interface UsageWindow {
label: string;
percentUsed: number; // 0-100
percentLeft: number; // 0-100
resetText: string | null; // e.g., "resets in 2h"
resetMs?: number; // ms until reset
resetAt?: string; // ISO 8601 timestamp of when the window resets (machine-readable)
windowDurationMs?: number; // total window length
pace?: UsagePace; // pace indicator for weekly windows
}
/** Provider usage data */
export interface ProviderUsage {
name: string;
icon: string; // emoji
status: "ok" | "error" | "no-auth";
error?: string;
plan?: string | null;
email?: string | null;
windows: UsageWindow[];
}
/** Fetch usage data from all configured AI providers */
export function fetchUsageData(): Promise<{ providers: ProviderUsage[] }> {
return api<{ providers: ProviderUsage[] }>("/usage");
}