diff --git a/apps/frontend/src/renderer/App.tsx b/apps/frontend/src/renderer/App.tsx
index 7e47904f7..c4ef9b405 100644
--- a/apps/frontend/src/renderer/App.tsx
+++ b/apps/frontend/src/renderer/App.tsx
@@ -77,6 +77,7 @@ import { PatternsPilotView } from './components/PatternsPilotView';
import { AnalyticsPilotView } from './components/AnalyticsPilotView';
import { ProductivityPilotView } from './components/ProductivityPilotView';
import { MergeAnalyticsPilotView } from './components/MergeAnalyticsPilotView';
+import { ModelUsagePilotView } from './components/ModelUsagePilotView';
import { useSettingsStore, loadSettings, loadProfiles, saveSettings } from './stores/settings-store';
import { useClaudeProfileStore } from './stores/claude-profile-store';
import { useTerminalStore, restoreTerminalSessions } from './stores/terminal-store';
@@ -1151,6 +1152,9 @@ export function App() {
{activeView === 'model-usage' && (activeProjectId || selectedProjectId) && (
)}
+ {activeView === 'model-usage-next' && (activeProjectId || selectedProjectId) && (
+
+ )}
{activeView === 'merge-analytics' && (activeProjectId || selectedProjectId) && (
)}
diff --git a/apps/frontend/src/renderer/__tests__/model-usage-ui.test.ts b/apps/frontend/src/renderer/__tests__/model-usage-ui.test.ts
new file mode 100644
index 000000000..f84cd68e6
--- /dev/null
+++ b/apps/frontend/src/renderer/__tests__/model-usage-ui.test.ts
@@ -0,0 +1,145 @@
+/**
+ * Tests for the ModelUsage{Summary,Trends} → AnalyticsDashboard mappers.
+ */
+
+import { describe, expect, it } from 'vitest';
+import {
+ buildModelBarLists,
+ buildModelCharts,
+ buildModelKpis,
+ buildModelSections,
+ shortModelName,
+} from '../lib/model-usage-ui';
+import type {
+ ModelMetrics,
+ ModelUsageSummary,
+ ModelUsageTrendPoint,
+} from '../../shared/types';
+
+function makeModel(overrides: Partial = {}): ModelMetrics {
+ return {
+ model: 'anthropic/claude-sonnet-4-5-20250929',
+ provider: 'anthropic',
+ total_input_tokens: 800_000,
+ total_output_tokens: 200_000,
+ usage_by_agent: {},
+ total_usage_count: 40,
+ total_tokens: 1_000_000,
+ total_cost: 12.5,
+ first_used: null,
+ last_used: null,
+ ...overrides,
+ };
+}
+
+function makeSummary(overrides: Partial = {}): ModelUsageSummary {
+ return {
+ period_start: '2026-05-01T00:00:00Z',
+ period_end: '2026-05-22T00:00:00Z',
+ total_usage_count: 64,
+ total_tokens: 1_680_000,
+ total_cost: 18.7,
+ models: [
+ makeModel(),
+ makeModel({
+ model: 'anthropic/claude-haiku-4-5-20251001',
+ total_tokens: 680_000,
+ total_input_tokens: 500_000,
+ total_output_tokens: 180_000,
+ total_cost: 6.2,
+ }),
+ ],
+ agents: [],
+ top_models: [],
+ ...overrides,
+ } as ModelUsageSummary;
+}
+
+const TRENDS: ModelUsageTrendPoint[] = [
+ { date: '2026-05-01', total_tokens: 400_000, total_cost: 4, usage_count: 12, unique_models: 2 },
+ { date: '2026-05-08', total_tokens: 620_000, total_cost: 7, usage_count: 20, unique_models: 2 },
+ { date: '2026-05-15', total_tokens: 660_000, total_cost: 8, usage_count: 22, unique_models: 3 },
+];
+
+describe('shortModelName', () => {
+ it('drops the provider prefix and date suffix', () => {
+ expect(shortModelName('anthropic/claude-sonnet-4-5-20250929')).toBe('claude-sonnet-4-5');
+ expect(shortModelName('gpt-4o')).toBe('gpt-4o');
+ });
+});
+
+describe('buildModelKpis', () => {
+ const labels = {
+ calls: 'calls',
+ callsSub: 'all',
+ tokens: 'tokens',
+ cost: 'cost',
+ models: 'models',
+ modelsSub: 'distinct',
+ };
+
+ it('maps the summary + trend sparklines onto four tiles', () => {
+ const kpis = buildModelKpis(makeSummary(), TRENDS, labels);
+ expect(kpis.map((k) => k.value)).toEqual(['64', '1.7M', '$18.70', '2']);
+ expect(kpis[0].trend).toEqual([12, 20, 22]);
+ expect(kpis[2].trend).toEqual([4, 7, 8]);
+ });
+
+ it('omits sparklines when trends are too short', () => {
+ const kpis = buildModelKpis(makeSummary(), [TRENDS[0]], labels);
+ expect(kpis[0].trend).toBeUndefined();
+ });
+});
+
+describe('buildModelCharts', () => {
+ const labels = {
+ tokensTitle: 'Tokens',
+ tokensAria: 't',
+ tokensSeries: 'Tokens',
+ costTitle: 'Cost',
+ costAria: 'c',
+ costSeries: 'Cost',
+ };
+
+ it('builds token + cost trend charts with UTC labels', () => {
+ const charts = buildModelCharts(TRENDS, labels, 'en-US');
+ expect(charts.map((c) => c.title)).toEqual(['Tokens', 'Cost']);
+ expect(charts[0].series[0].values).toEqual([400_000, 620_000, 660_000]);
+ expect(charts[0].xLabels).toEqual(['May 1', 'May 8', 'May 15']);
+ });
+
+ it('returns no charts without at least two trend points', () => {
+ expect(buildModelCharts([TRENDS[0]], labels)).toEqual([]);
+ });
+});
+
+describe('buildModelBarLists', () => {
+ it('ranks models by tokens with formatted value labels', () => {
+ const lists = buildModelBarLists(makeSummary().models, 'Tokens by model', 'aria');
+ expect(lists).toHaveLength(1);
+ expect(lists[0].items).toEqual([
+ { label: 'claude-sonnet-4-5', value: 1_000_000, valueLabel: '1.0M', tone: 'info' },
+ { label: 'claude-haiku-4-5', value: 680_000, valueLabel: '680.0k', tone: 'info' },
+ ]);
+ });
+
+ it('returns no card when there are no models', () => {
+ expect(buildModelBarLists([], 't', 'a')).toEqual([]);
+ });
+});
+
+describe('buildModelSections', () => {
+ it('sums the input/output token split and counts providers', () => {
+ const sections = buildModelSections(makeSummary(), {
+ splitTitle: 'Split',
+ inputTokens: 'Input',
+ outputTokens: 'Output',
+ providers: 'Providers',
+ });
+ expect(sections[0].rows).toEqual([
+ { label: 'Input', value: '1.3M' },
+ { label: 'Output', value: '380.0k' },
+ { label: 'Providers', value: '1' },
+ ]);
+ });
+});
diff --git a/apps/frontend/src/renderer/components/ModelUsagePilotView.tsx b/apps/frontend/src/renderer/components/ModelUsagePilotView.tsx
new file mode 100644
index 000000000..3ca09f38c
--- /dev/null
+++ b/apps/frontend/src/renderer/components/ModelUsagePilotView.tsx
@@ -0,0 +1,170 @@
+/**
+ * Model Usage pilot on the shared design system (U5 B2).
+ *
+ * Renders `libs/ui`'s AnalyticsDashboard from the existing
+ * `getModelUsageSummary` + `getModelUsageTrends` IPC, mapped with the pure
+ * `model-usage-ui` helpers. KPIs + token/cost trend charts + a per-model
+ * BarList. Read-only — the legacy Model Usage view keeps its export flow.
+ * Reachable via the "Model Usage (new UI)" sidebar item.
+ */
+
+import { useCallback, useEffect, useMemo, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { AnalyticsDashboard } from '@auto-code/ui';
+import type {
+ UiBarListCard,
+ UiChartCard,
+ UiKpi,
+ UiMetaSection,
+} from '@auto-code/ui';
+import type {
+ ModelUsageSummary,
+ ModelUsageTrendPoint,
+} from '../../shared/types';
+import {
+ buildModelBarLists,
+ buildModelCharts,
+ buildModelKpis,
+ buildModelSections,
+} from '../lib/model-usage-ui';
+
+interface ModelUsagePilotViewProps {
+ projectId: string;
+}
+
+interface PilotState {
+ summary: ModelUsageSummary | null;
+ trends: ModelUsageTrendPoint[];
+ loading: boolean;
+ error: Error | null;
+}
+
+export function ModelUsagePilotView({
+ projectId,
+}: Readonly) {
+ const { t, i18n } = useTranslation(['model-usage']);
+ const [state, setState] = useState({
+ summary: null,
+ trends: [],
+ loading: true,
+ error: null,
+ });
+ const [reloadKey, setReloadKey] = useState(0);
+
+ useEffect(() => {
+ let active = true;
+ setState({ summary: null, trends: [], loading: true, error: null });
+ Promise.all([
+ window.electronAPI.getModelUsageSummary(projectId),
+ window.electronAPI.getModelUsageTrends(projectId),
+ ])
+ .then(([summaryResult, trendsResult]) => {
+ if (!active) return;
+ if (!summaryResult.success || summaryResult.data == null) {
+ console.error(
+ '[ModelUsagePilotView] Failed to load summary:',
+ summaryResult.success ? 'no data' : summaryResult.error,
+ );
+ setState({
+ summary: null,
+ trends: [],
+ loading: false,
+ error: new Error(t('model-usage:modelUsagePilot.error')),
+ });
+ return;
+ }
+ setState({
+ summary: summaryResult.data,
+ trends: trendsResult.success ? (trendsResult.data ?? []) : [],
+ loading: false,
+ error: null,
+ });
+ })
+ .catch((err: unknown) => {
+ if (!active) return;
+ console.error('[ModelUsagePilotView] Failed to load model usage:', err);
+ setState({
+ summary: null,
+ trends: [],
+ loading: false,
+ error: new Error(t('model-usage:modelUsagePilot.error')),
+ });
+ });
+ return () => {
+ active = false;
+ };
+ }, [projectId, reloadKey, t]);
+
+ const reload = useCallback(() => setReloadKey((key) => key + 1), []);
+
+ const kpis = useMemo(() => {
+ if (state.summary == null) return null;
+ return buildModelKpis(state.summary, state.trends, {
+ calls: t('model-usage:modelUsagePilot.kpis.calls'),
+ callsSub: t('model-usage:modelUsagePilot.kpis.callsSub'),
+ tokens: t('model-usage:modelUsagePilot.kpis.tokens'),
+ cost: t('model-usage:modelUsagePilot.kpis.cost'),
+ models: t('model-usage:modelUsagePilot.kpis.models'),
+ modelsSub: t('model-usage:modelUsagePilot.kpis.modelsSub'),
+ });
+ }, [state.summary, state.trends, t]);
+
+ const charts = useMemo(() => {
+ if (state.summary == null) return undefined;
+ return buildModelCharts(
+ state.trends,
+ {
+ tokensTitle: t('model-usage:modelUsagePilot.charts.tokensTitle'),
+ tokensAria: t('model-usage:modelUsagePilot.charts.tokensAria'),
+ tokensSeries: t('model-usage:modelUsagePilot.charts.tokensSeries'),
+ costTitle: t('model-usage:modelUsagePilot.charts.costTitle'),
+ costAria: t('model-usage:modelUsagePilot.charts.costAria'),
+ costSeries: t('model-usage:modelUsagePilot.charts.costSeries'),
+ },
+ i18n.language,
+ );
+ }, [state.summary, state.trends, t, i18n.language]);
+
+ const barLists = useMemo(() => {
+ if (state.summary == null) return undefined;
+ return buildModelBarLists(
+ state.summary.models,
+ t('model-usage:modelUsagePilot.models.title'),
+ t('model-usage:modelUsagePilot.models.aria'),
+ );
+ }, [state.summary, t]);
+
+ const sections = useMemo(() => {
+ if (state.summary == null) return undefined;
+ return buildModelSections(state.summary, {
+ splitTitle: t('model-usage:modelUsagePilot.sections.splitTitle'),
+ inputTokens: t('model-usage:modelUsagePilot.sections.inputTokens'),
+ outputTokens: t('model-usage:modelUsagePilot.sections.outputTokens'),
+ providers: t('model-usage:modelUsagePilot.sections.providers'),
+ });
+ }, [state.summary, t]);
+
+ const stateLabels = useMemo(
+ () => ({
+ loading: t('model-usage:modelUsagePilot.states.loading'),
+ retry: t('model-usage:modelUsagePilot.states.retry'),
+ empty: t('model-usage:modelUsagePilot.states.empty'),
+ }),
+ [t],
+ );
+
+ return (
+
+ );
+}
diff --git a/apps/frontend/src/renderer/components/Sidebar.tsx b/apps/frontend/src/renderer/components/Sidebar.tsx
index ac230e314..e36fb20bc 100644
--- a/apps/frontend/src/renderer/components/Sidebar.tsx
+++ b/apps/frontend/src/renderer/components/Sidebar.tsx
@@ -34,7 +34,8 @@ import {
MessageSquare,
Code,
Brain,
- LayoutDashboard
+ LayoutDashboard,
+ Cpu
} from 'lucide-react';
import { Button } from './ui/button';
import { ScrollArea } from './ui/scroll-area';
@@ -71,7 +72,7 @@ import { SessionContextIndicator } from './SessionContextIndicator';
import { NavIndicator } from './NavIndicator';
import type { Project, AutoBuildVersionInfo, GitStatus, ProjectEnvConfig } from '../../shared/types';
-export type SidebarView = 'kanban' | 'kanban-next' | 'terminals' | 'roadmap' | 'context' | 'ideation' | 'webhooks' | 'github-issues' | 'github-issues-next' | 'gitlab-issues' | 'github-prs' | 'github-prs-next' | 'gitlab-merge-requests' | 'changelog' | 'changelog-next' | 'insights' | 'worktrees' | 'agent-tools' | 'plugins' | 'analytics' | 'analytics-next' | 'productivity' | 'productivity-next' | 'merge-analytics' | 'merge-analytics-next' | 'sessions' | 'scheduler' | 'feedback' | 'patterns' | 'patterns-next' | 'model-usage' | 'agent-inspector';
+export type SidebarView = 'kanban' | 'kanban-next' | 'terminals' | 'roadmap' | 'context' | 'ideation' | 'webhooks' | 'github-issues' | 'github-issues-next' | 'gitlab-issues' | 'github-prs' | 'github-prs-next' | 'gitlab-merge-requests' | 'changelog' | 'changelog-next' | 'insights' | 'worktrees' | 'agent-tools' | 'plugins' | 'analytics' | 'analytics-next' | 'productivity' | 'productivity-next' | 'merge-analytics' | 'merge-analytics-next' | 'sessions' | 'scheduler' | 'feedback' | 'patterns' | 'patterns-next' | 'model-usage' | 'model-usage-next' | 'agent-inspector';
interface SidebarProps {
onSettingsClick: () => void;
@@ -114,7 +115,8 @@ const baseNavItems: NavItem[] = [
{ id: 'sessions', labelKey: 'navigation:items.sessions', icon: Play },
{ id: 'agent-inspector', labelKey: 'navigation:items.agentInspector', icon: Brain },
{ id: 'feedback', labelKey: 'navigation:items.feedback', icon: MessageSquare, shortcut: 'F' },
- { id: 'model-usage', labelKey: 'navigation:items.modelUsage', icon: Database, shortcut: 'O' }
+ { id: 'model-usage', labelKey: 'navigation:items.modelUsage', icon: Database, shortcut: 'O' },
+ { id: 'model-usage-next', labelKey: 'navigation:items.modelUsageNext', icon: Cpu },
];
// GitHub nav items shown when GitHub is enabled
diff --git a/apps/frontend/src/renderer/lib/model-usage-ui.ts b/apps/frontend/src/renderer/lib/model-usage-ui.ts
new file mode 100644
index 000000000..8a4c44d35
--- /dev/null
+++ b/apps/frontend/src/renderer/lib/model-usage-ui.ts
@@ -0,0 +1,168 @@
+/**
+ * Pure mapping helpers between the ModelUsageSummary/Trends IPC shapes and the
+ * shared AnalyticsDashboard. Model Usage is line/sparkline + a per-model
+ * distribution, so it exercises KPIs, trend charts, a BarList, and a rail card.
+ */
+
+import type {
+ UiBarListCard,
+ UiChartCard,
+ UiKpi,
+ UiMetaSection,
+} from '@auto-code/ui';
+import type {
+ ModelMetrics,
+ ModelUsageSummary,
+ ModelUsageTrendPoint,
+} from '../../shared/types';
+import {
+ formatCost,
+ formatCount,
+ sampleLabels,
+ shortDate,
+} from './analytics-ui';
+
+/** Drop a provider prefix and date suffix so bars read as short model names. */
+export function shortModelName(model: string): string {
+ return model.replace(/^[^/]+\//, '').replace(/-\d{6,8}$/, '');
+}
+
+export interface ModelKpiLabels {
+ calls: string;
+ callsSub: string;
+ tokens: string;
+ cost: string;
+ models: string;
+ modelsSub: string;
+}
+
+export function buildModelKpis(
+ summary: ModelUsageSummary,
+ trends: readonly ModelUsageTrendPoint[],
+ labels: ModelKpiLabels,
+): UiKpi[] {
+ const usageSeries = trends.map((point) => point.usage_count);
+ const tokenSeries = trends.map((point) => point.total_tokens);
+ const costSeries = trends.map((point) => point.total_cost);
+ return [
+ {
+ value: String(summary.total_usage_count),
+ label: labels.calls,
+ sub: labels.callsSub,
+ trend: usageSeries.length >= 2 ? usageSeries : undefined,
+ trendTone: 'info',
+ },
+ {
+ value: formatCount(summary.total_tokens),
+ label: labels.tokens,
+ trend: tokenSeries.length >= 2 ? tokenSeries : undefined,
+ trendTone: 'info',
+ },
+ {
+ value: formatCost(summary.total_cost),
+ label: labels.cost,
+ trend: costSeries.length >= 2 ? costSeries : undefined,
+ trendTone: 'warn',
+ },
+ {
+ value: String(summary.models.length),
+ label: labels.models,
+ sub: labels.modelsSub,
+ },
+ ];
+}
+
+export interface ModelChartLabels {
+ tokensTitle: string;
+ tokensAria: string;
+ tokensSeries: string;
+ costTitle: string;
+ costAria: string;
+ costSeries: string;
+}
+
+export function buildModelCharts(
+ trends: readonly ModelUsageTrendPoint[],
+ labels: ModelChartLabels,
+ locale?: string,
+): UiChartCard[] {
+ if (trends.length < 2) return [];
+ const xLabels = sampleLabels(trends.map((p) => shortDate(p.date, locale)));
+ return [
+ {
+ title: labels.tokensTitle,
+ ariaLabel: labels.tokensAria,
+ xLabels,
+ series: [
+ {
+ label: labels.tokensSeries,
+ tone: 'info',
+ values: trends.map((p) => p.total_tokens),
+ },
+ ],
+ },
+ {
+ title: labels.costTitle,
+ ariaLabel: labels.costAria,
+ xLabels,
+ series: [
+ {
+ label: labels.costSeries,
+ tone: 'warn',
+ values: trends.map((p) => p.total_cost),
+ },
+ ],
+ },
+ ];
+}
+
+/** Top models ranked by token usage, rendered as a BarList distribution. */
+export function buildModelBarLists(
+ models: readonly ModelMetrics[],
+ title: string,
+ ariaLabel: string,
+ limit = 8,
+): UiBarListCard[] {
+ if (models.length === 0) return [];
+ const top = [...models]
+ .sort((a, b) => b.total_tokens - a.total_tokens)
+ .slice(0, limit);
+ return [
+ {
+ title,
+ ariaLabel,
+ items: top.map((model) => ({
+ label: shortModelName(model.model),
+ value: model.total_tokens,
+ valueLabel: formatCount(model.total_tokens),
+ tone: 'info',
+ })),
+ },
+ ];
+}
+
+export interface ModelSectionLabels {
+ splitTitle: string;
+ inputTokens: string;
+ outputTokens: string;
+ providers: string;
+}
+
+export function buildModelSections(
+ summary: ModelUsageSummary,
+ labels: ModelSectionLabels,
+): UiMetaSection[] {
+ const input = summary.models.reduce((sum, m) => sum + m.total_input_tokens, 0);
+ const output = summary.models.reduce((sum, m) => sum + m.total_output_tokens, 0);
+ const providers = new Set(summary.models.map((m) => m.provider)).size;
+ return [
+ {
+ title: labels.splitTitle,
+ rows: [
+ { label: labels.inputTokens, value: formatCount(input) },
+ { label: labels.outputTokens, value: formatCount(output) },
+ { label: labels.providers, value: String(providers) },
+ ],
+ },
+ ];
+}
diff --git a/apps/frontend/src/shared/i18n/locales/en/model-usage.json b/apps/frontend/src/shared/i18n/locales/en/model-usage.json
index c3a14d816..5db2f1785 100644
--- a/apps/frontend/src/shared/i18n/locales/en/model-usage.json
+++ b/apps/frontend/src/shared/i18n/locales/en/model-usage.json
@@ -108,5 +108,39 @@
"emptyTitle": "No data available",
"emptySubtitle": "Run more tasks to see trends over time",
"rangeLatest": "Range"
+ },
+ "modelUsagePilot": {
+ "error": "Failed to load model usage.",
+ "states": {
+ "loading": "Loading model usage…",
+ "retry": "Retry",
+ "empty": "No model usage yet."
+ },
+ "kpis": {
+ "calls": "AI calls",
+ "callsSub": "all time",
+ "tokens": "tokens",
+ "cost": "total cost",
+ "models": "models used",
+ "modelsSub": "distinct"
+ },
+ "charts": {
+ "tokensTitle": "Tokens over time",
+ "tokensAria": "Total tokens per day over the period",
+ "tokensSeries": "Tokens",
+ "costTitle": "Cost over time",
+ "costAria": "Total cost per day over the period",
+ "costSeries": "Cost"
+ },
+ "models": {
+ "title": "Tokens by model",
+ "aria": "Models ranked by total token usage"
+ },
+ "sections": {
+ "splitTitle": "Token split",
+ "inputTokens": "Input",
+ "outputTokens": "Output",
+ "providers": "Providers"
+ }
}
}
diff --git a/apps/frontend/src/shared/i18n/locales/en/navigation.json b/apps/frontend/src/shared/i18n/locales/en/navigation.json
index 07b3b66ac..87ec3a50d 100644
--- a/apps/frontend/src/shared/i18n/locales/en/navigation.json
+++ b/apps/frontend/src/shared/i18n/locales/en/navigation.json
@@ -36,7 +36,8 @@
"patternsNext": "Patterns (New UI)",
"analyticsNext": "Analytics (New UI)",
"productivityNext": "Productivity (New UI)",
- "mergeAnalyticsNext": "Merge Analytics (New UI)"
+ "mergeAnalyticsNext": "Merge Analytics (New UI)",
+ "modelUsageNext": "Model Usage (New UI)"
},
"actions": {
"settings": "Settings",
diff --git a/apps/frontend/src/shared/i18n/locales/fr/model-usage.json b/apps/frontend/src/shared/i18n/locales/fr/model-usage.json
index c7cb4e4d6..fdfe3b8c7 100644
--- a/apps/frontend/src/shared/i18n/locales/fr/model-usage.json
+++ b/apps/frontend/src/shared/i18n/locales/fr/model-usage.json
@@ -108,5 +108,39 @@
"emptyTitle": "Aucune donnée disponible",
"emptySubtitle": "Exécutez plus de tâches pour voir les tendances",
"rangeLatest": "Plage"
+ },
+ "modelUsagePilot": {
+ "error": "Échec du chargement de l'utilisation des modèles.",
+ "states": {
+ "loading": "Chargement de l'utilisation des modèles…",
+ "retry": "Réessayer",
+ "empty": "Aucune utilisation de modèle pour le moment."
+ },
+ "kpis": {
+ "calls": "appels IA",
+ "callsSub": "depuis le début",
+ "tokens": "tokens",
+ "cost": "coût total",
+ "models": "modèles utilisés",
+ "modelsSub": "distincts"
+ },
+ "charts": {
+ "tokensTitle": "Tokens au fil du temps",
+ "tokensAria": "Total de tokens par jour sur la période",
+ "tokensSeries": "Tokens",
+ "costTitle": "Coût au fil du temps",
+ "costAria": "Coût total par jour sur la période",
+ "costSeries": "Coût"
+ },
+ "models": {
+ "title": "Tokens par modèle",
+ "aria": "Modèles classés par utilisation totale de tokens"
+ },
+ "sections": {
+ "splitTitle": "Répartition des tokens",
+ "inputTokens": "Entrée",
+ "outputTokens": "Sortie",
+ "providers": "Fournisseurs"
+ }
}
}
diff --git a/apps/frontend/src/shared/i18n/locales/fr/navigation.json b/apps/frontend/src/shared/i18n/locales/fr/navigation.json
index 113970652..f4b40db55 100644
--- a/apps/frontend/src/shared/i18n/locales/fr/navigation.json
+++ b/apps/frontend/src/shared/i18n/locales/fr/navigation.json
@@ -36,7 +36,8 @@
"patternsNext": "Patterns (nouvelle interface)",
"analyticsNext": "Analytique (nouvelle interface)",
"productivityNext": "Productivité (nouvelle interface)",
- "mergeAnalyticsNext": "Analytique de fusion (nouvelle interface)"
+ "mergeAnalyticsNext": "Analytique de fusion (nouvelle interface)",
+ "modelUsageNext": "Utilisation des modèles (nouvelle interface)"
},
"actions": {
"settings": "Paramètres",