@agent-native/dispatch 0.24.0 → 0.24.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/dist/actions/provider-api-register.d.ts +12 -12
  2. package/dist/components/admin-navigation.d.ts.map +1 -1
  3. package/dist/components/admin-navigation.js +21 -5
  4. package/dist/components/admin-navigation.js.map +1 -1
  5. package/dist/components/agents-panel.d.ts.map +1 -1
  6. package/dist/components/agents-panel.js +7 -2
  7. package/dist/components/agents-panel.js.map +1 -1
  8. package/dist/components/app-list-row.d.ts +1 -1
  9. package/dist/components/app-list-row.d.ts.map +1 -1
  10. package/dist/components/app-list-row.js +1 -1
  11. package/dist/components/app-list-row.js.map +1 -1
  12. package/dist/components/app-open-actions.d.ts +1 -17
  13. package/dist/components/app-open-actions.d.ts.map +1 -1
  14. package/dist/components/app-open-actions.js +1 -20
  15. package/dist/components/app-open-actions.js.map +1 -1
  16. package/dist/components/app-row-settings.d.ts +6 -0
  17. package/dist/components/app-row-settings.d.ts.map +1 -0
  18. package/dist/components/app-row-settings.js +11 -0
  19. package/dist/components/app-row-settings.js.map +1 -0
  20. package/dist/components/automation-run-history-dialog.d.ts.map +1 -1
  21. package/dist/components/automation-run-history-dialog.js +3 -2
  22. package/dist/components/automation-run-history-dialog.js.map +1 -1
  23. package/dist/components/connected-app-card.d.ts.map +1 -1
  24. package/dist/components/connected-app-card.js +1 -1
  25. package/dist/components/connected-app-card.js.map +1 -1
  26. package/dist/components/create-app-popover.js +2 -2
  27. package/dist/components/create-app-popover.js.map +1 -1
  28. package/dist/components/dispatch-control-plane.d.ts.map +1 -1
  29. package/dist/components/dispatch-control-plane.js +23 -7
  30. package/dist/components/dispatch-control-plane.js.map +1 -1
  31. package/dist/components/dispatch-shell.d.ts.map +1 -1
  32. package/dist/components/dispatch-shell.js +5 -1
  33. package/dist/components/dispatch-shell.js.map +1 -1
  34. package/dist/components/docs-link.d.ts +16 -0
  35. package/dist/components/docs-link.d.ts.map +1 -0
  36. package/dist/components/docs-link.js +34 -0
  37. package/dist/components/docs-link.js.map +1 -0
  38. package/dist/components/layout/Layout.d.ts +1 -0
  39. package/dist/components/layout/Layout.d.ts.map +1 -1
  40. package/dist/components/layout/Layout.js +37 -28
  41. package/dist/components/layout/Layout.js.map +1 -1
  42. package/dist/components/messaging-setup-panel.d.ts.map +1 -1
  43. package/dist/components/messaging-setup-panel.js +3 -2
  44. package/dist/components/messaging-setup-panel.js.map +1 -1
  45. package/dist/components/usage-alerts-panel.d.ts +11 -0
  46. package/dist/components/usage-alerts-panel.d.ts.map +1 -0
  47. package/dist/components/usage-alerts-panel.js +125 -0
  48. package/dist/components/usage-alerts-panel.js.map +1 -0
  49. package/dist/components/workspace-app-card.d.ts +3 -1
  50. package/dist/components/workspace-app-card.d.ts.map +1 -1
  51. package/dist/components/workspace-app-card.js +70 -29
  52. package/dist/components/workspace-app-card.js.map +1 -1
  53. package/dist/components/workspace-app-search.d.ts +10 -0
  54. package/dist/components/workspace-app-search.d.ts.map +1 -0
  55. package/dist/components/workspace-app-search.js +27 -0
  56. package/dist/components/workspace-app-search.js.map +1 -0
  57. package/dist/components/workspace-resource-effective-stack.d.ts.map +1 -1
  58. package/dist/components/workspace-resource-effective-stack.js +3 -2
  59. package/dist/components/workspace-resource-effective-stack.js.map +1 -1
  60. package/dist/components/workspace-template-card.d.ts.map +1 -1
  61. package/dist/components/workspace-template-card.js +2 -1
  62. package/dist/components/workspace-template-card.js.map +1 -1
  63. package/dist/lib/workspace-app-layout.d.ts +19 -0
  64. package/dist/lib/workspace-app-layout.d.ts.map +1 -0
  65. package/dist/lib/workspace-app-layout.js +75 -0
  66. package/dist/lib/workspace-app-layout.js.map +1 -0
  67. package/dist/lib/workspace-apps.d.ts +10 -0
  68. package/dist/lib/workspace-apps.d.ts.map +1 -1
  69. package/dist/lib/workspace-apps.js +59 -0
  70. package/dist/lib/workspace-apps.js.map +1 -1
  71. package/dist/lib/workspace-apps.test.js +18 -1
  72. package/dist/lib/workspace-apps.test.js.map +1 -1
  73. package/dist/routes/pages/$appId.d.ts.map +1 -1
  74. package/dist/routes/pages/$appId.js +4 -2
  75. package/dist/routes/pages/$appId.js.map +1 -1
  76. package/dist/routes/pages/agents.d.ts.map +1 -1
  77. package/dist/routes/pages/agents.js +2 -3
  78. package/dist/routes/pages/agents.js.map +1 -1
  79. package/dist/routes/pages/apps.$appId.d.ts.map +1 -1
  80. package/dist/routes/pages/apps.$appId.js +8 -3
  81. package/dist/routes/pages/apps.$appId.js.map +1 -1
  82. package/dist/routes/pages/apps.d.ts.map +1 -1
  83. package/dist/routes/pages/apps.js +31 -16
  84. package/dist/routes/pages/apps.js.map +1 -1
  85. package/dist/routes/pages/audit.d.ts.map +1 -1
  86. package/dist/routes/pages/audit.js +2 -1
  87. package/dist/routes/pages/audit.js.map +1 -1
  88. package/dist/routes/pages/dreams.d.ts.map +1 -1
  89. package/dist/routes/pages/dreams.js +14 -18
  90. package/dist/routes/pages/dreams.js.map +1 -1
  91. package/dist/routes/pages/integrations.d.ts.map +1 -1
  92. package/dist/routes/pages/integrations.js +51 -14
  93. package/dist/routes/pages/integrations.js.map +1 -1
  94. package/dist/routes/pages/metrics.d.ts.map +1 -1
  95. package/dist/routes/pages/metrics.js +4 -1
  96. package/dist/routes/pages/metrics.js.map +1 -1
  97. package/dist/routes/pages/operations.js +1 -1
  98. package/dist/routes/pages/operations.js.map +1 -1
  99. package/dist/routes/pages/settings.d.ts.map +1 -1
  100. package/dist/routes/pages/settings.js +7 -2
  101. package/dist/routes/pages/settings.js.map +1 -1
  102. package/dist/routes/pages/thread-debug.d.ts.map +1 -1
  103. package/dist/routes/pages/thread-debug.js +5 -8
  104. package/dist/routes/pages/thread-debug.js.map +1 -1
  105. package/dist/routes/pages/vault.d.ts.map +1 -1
  106. package/dist/routes/pages/vault.js +1 -1
  107. package/dist/routes/pages/vault.js.map +1 -1
  108. package/dist/routes/pages/workspace.d.ts.map +1 -1
  109. package/dist/routes/pages/workspace.js +13 -10
  110. package/dist/routes/pages/workspace.js.map +1 -1
  111. package/dist/server/index.d.ts.map +1 -1
  112. package/dist/server/index.js +3 -0
  113. package/dist/server/index.js.map +1 -1
  114. package/dist/server/lib/app-creation-store.d.ts.map +1 -1
  115. package/dist/server/lib/app-creation-store.js +12 -52
  116. package/dist/server/lib/app-creation-store.js.map +1 -1
  117. package/dist/shared/app-roles.d.ts +9 -0
  118. package/dist/shared/app-roles.d.ts.map +1 -0
  119. package/dist/shared/app-roles.js +7 -0
  120. package/dist/shared/app-roles.js.map +1 -0
  121. package/package.json +4 -3
  122. package/src/components/admin-navigation.tsx +57 -11
  123. package/src/components/agents-panel.tsx +54 -29
  124. package/src/components/app-list-row.tsx +1 -2
  125. package/src/components/app-open-actions.tsx +5 -114
  126. package/src/components/app-row-settings.tsx +54 -0
  127. package/src/components/automation-run-history-dialog.tsx +8 -4
  128. package/src/components/connected-app-card.tsx +0 -1
  129. package/src/components/create-app-popover.spec.tsx +1 -1
  130. package/src/components/create-app-popover.tsx +2 -2
  131. package/src/components/dispatch-control-plane.spec.tsx +36 -2
  132. package/src/components/dispatch-control-plane.tsx +83 -27
  133. package/src/components/dispatch-shell.tsx +7 -1
  134. package/src/components/docs-link.tsx +52 -0
  135. package/src/components/layout/Layout.spec.tsx +10 -0
  136. package/src/components/layout/Layout.tsx +50 -23
  137. package/src/components/messaging-setup-panel.tsx +10 -3
  138. package/src/components/usage-alerts-panel.tsx +445 -0
  139. package/src/components/workspace-app-card.spec.tsx +130 -9
  140. package/src/components/workspace-app-card.tsx +128 -71
  141. package/src/components/workspace-app-search.tsx +96 -0
  142. package/src/components/workspace-resource-effective-stack.tsx +10 -5
  143. package/src/components/workspace-template-card.spec.tsx +52 -23
  144. package/src/components/workspace-template-card.tsx +7 -10
  145. package/src/lib/workspace-app-layout.spec.ts +47 -0
  146. package/src/lib/workspace-app-layout.ts +121 -0
  147. package/src/lib/workspace-apps.test.ts +45 -1
  148. package/src/lib/workspace-apps.ts +72 -0
  149. package/src/routes/pages/$appId.tsx +3 -6
  150. package/src/routes/pages/agents.tsx +6 -3
  151. package/src/routes/pages/apps.$appId.tsx +6 -6
  152. package/src/routes/pages/apps.tsx +116 -62
  153. package/src/routes/pages/audit.tsx +28 -8
  154. package/src/routes/pages/dreams.tsx +92 -142
  155. package/src/routes/pages/integrations.tsx +147 -68
  156. package/src/routes/pages/metrics.tsx +8 -0
  157. package/src/routes/pages/operations.tsx +2 -2
  158. package/src/routes/pages/settings.tsx +14 -9
  159. package/src/routes/pages/thread-debug.tsx +18 -36
  160. package/src/routes/pages/vault.tsx +7 -2
  161. package/src/routes/pages/workspace.tsx +92 -56
  162. package/src/server/index.ts +4 -0
  163. package/src/server/lib/app-creation-store.spec.ts +90 -43
  164. package/src/server/lib/app-creation-store.ts +15 -61
  165. package/src/shared/app-roles.ts +8 -0
@@ -1 +1 @@
1
- {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../../src/routes/pages/metrics.tsx"],"names":[],"mappings":"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","sourcesContent":["import { sendToAgentChat } from \"@agent-native/core/client/agent-chat\";\nimport { useActionQuery } from \"@agent-native/core/client/hooks\";\nimport { useT } from \"@agent-native/core/client/i18n\";\nimport {\n IconActivity,\n IconAlertTriangle,\n IconArrowUpRight,\n IconApps,\n IconChartBar,\n IconCoin,\n IconMessages,\n IconUsersGroup,\n} from \"@tabler/icons-react\";\nimport { useMemo, useState, type ReactNode } from \"react\";\nimport { Link, useSearchParams } from \"react-router\";\nimport { Area, AreaChart, CartesianGrid, XAxis, YAxis } from \"recharts\";\n\nimport { DispatchShell } from \"../../components/dispatch-shell\";\nimport { Alert, AlertDescription, AlertTitle } from \"../../components/ui/alert\";\nimport { Badge } from \"../../components/ui/badge\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n} from \"../../components/ui/chart\";\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../components/ui/select\";\nimport { Skeleton } from \"../../components/ui/skeleton\";\nimport { cn } from \"../../lib/utils\";\n\nexport function meta() {\n return [{ title: \"Metrics — Dispatch\" }];\n}\n\ninterface UsageMetricBucket {\n key: string;\n label: string;\n costCents: number;\n calls: number;\n chatCalls: number;\n inputTokens: number;\n outputTokens: number;\n activeUsers: number;\n lastActiveAt: number | null;\n}\n\ninterface UserUsageMetric extends UsageMetricBucket {\n ownerEmail: string;\n chatThreads: number;\n chatMessages: number;\n lastChatAt: number | null;\n topApp: string | null;\n role: string | null;\n}\n\ninterface UsageUserOption {\n email: string;\n role: string | null;\n}\n\ninterface AppAccessMetric {\n id: string;\n name: string;\n path: string;\n status?: \"ready\" | \"pending\";\n statusLabel?: string;\n isDispatch: boolean;\n accessLabel: string;\n accessUsers: number;\n usersWithUsage: number;\n usageCalls: number;\n chatCalls: number;\n costCents: number;\n lastActiveAt: number | null;\n}\n\ninterface DailyUsageMetric {\n date: string;\n costCents: number;\n calls: number;\n chatCalls: number;\n activeUsers: number;\n}\n\ninterface RecentUsageMetric {\n id: number;\n createdAt: number;\n ownerEmail: string;\n app: string;\n label: string;\n model: string;\n inputTokens: number;\n outputTokens: number;\n costCents: number;\n prompt: string | null;\n promptSource: \"thread\" | \"thread-preview\" | \"not-captured\" | \"unavailable\";\n threadId: string | null;\n runId: string | null;\n taskId: string | null;\n sourcePlatform: string | null;\n sourceId: string | null;\n}\n\ninterface UsageBillingMode {\n unit: \"usd\" | \"builder-credits\";\n label: string;\n shortLabel: string;\n source: \"estimated-provider-cost\" | \"builder-agent-credits\";\n hardCostMarginMultiplier?: number;\n creditsPerUsd?: number;\n}\n\ninterface DispatchUsageMetrics {\n billing?: UsageBillingMode;\n viewScope?: \"me\" | \"workspace\";\n selectedUserEmail?: string | null;\n availableUsers?: UsageUserOption[];\n sinceDays: number;\n access: {\n viewerEmail: string;\n orgId: string | null;\n role: string | null;\n scope: \"organization\" | \"solo\";\n totalUsers: number;\n };\n totals: {\n costCents: number;\n calls: number;\n chatCalls: number;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n activeUsers: number;\n chatThreads: number;\n chatMessages: number;\n workspaceApps: number;\n };\n byApp: UsageMetricBucket[];\n byUser: UserUsageMetric[];\n byLabel: UsageMetricBucket[];\n byModel: UsageMetricBucket[];\n daily: DailyUsageMetric[];\n appAccess: AppAccessMetric[];\n recent: RecentUsageMetric[];\n}\n\nconst RANGES = [7, 30, 90] as const;\n\nconst USD_BILLING: UsageBillingMode = {\n unit: \"usd\",\n label: \"Estimated spend\",\n shortLabel: \"Cost\",\n source: \"estimated-provider-cost\",\n};\n\nfunction displayAmountFromCostCents(\n cents: number,\n billing: UsageBillingMode,\n): number {\n if (billing.unit !== \"builder-credits\") return cents;\n const margin = billing.hardCostMarginMultiplier ?? 1.25;\n const creditsPerUsd = billing.creditsPerUsd ?? 20;\n const credits = (cents / 100) * margin * creditsPerUsd;\n return credits <= 0 ? 0 : Math.ceil(credits * 1000) / 1000;\n}\n\nfunction formatCredits(credits: number): string {\n if (!Number.isFinite(credits) || credits === 0) return \"0 credits\";\n const maximumFractionDigits = credits < 1 ? 3 : credits < 10 ? 2 : 1;\n const value = credits.toLocaleString(undefined, {\n maximumFractionDigits,\n });\n return `${value} ${credits === 1 ? \"credit\" : \"credits\"}`;\n}\n\nfunction formatSpend(cents: number, billing: UsageBillingMode): string {\n if (billing.unit === \"builder-credits\") {\n return formatCredits(displayAmountFromCostCents(cents, billing));\n }\n if (!Number.isFinite(cents) || cents === 0) return \"$0.00\";\n if (Math.abs(cents) < 1) return `${cents.toFixed(3)}¢`;\n if (Math.abs(cents) < 100) return `${cents.toFixed(2)}¢`;\n return (cents / 100).toLocaleString(undefined, {\n style: \"currency\",\n currency: \"USD\",\n maximumFractionDigits: 2,\n });\n}\n\nfunction formatNumber(value: number): string {\n return new Intl.NumberFormat(undefined, {\n notation: value >= 10_000 ? \"compact\" : \"standard\",\n maximumFractionDigits: value >= 10_000 ? 1 : 0,\n }).format(value);\n}\n\nfunction formatTokens(value: number): string {\n return new Intl.NumberFormat(undefined, {\n notation: \"compact\",\n maximumFractionDigits: 1,\n }).format(value);\n}\n\nfunction timeAgo(timestamp: number | null): string {\n if (!timestamp) return \"No activity\";\n const diff = Date.now() - timestamp;\n if (diff < 60_000) return \"just now\";\n if (diff < 3_600_000) return `${Math.floor(diff / 60_000)}m ago`;\n if (diff < 86_400_000) return `${Math.floor(diff / 3_600_000)}h ago`;\n return `${Math.floor(diff / 86_400_000)}d ago`;\n}\n\nfunction formatTrendDate(value: string): string {\n const date = new Date(`${value}T12:00:00`);\n return date.toLocaleDateString(undefined, {\n month: \"short\",\n day: \"numeric\",\n });\n}\n\nfunction completeTrendRows(rows: DailyUsageMetric[]): DailyUsageMetric[] {\n if (rows.length < 2) return rows;\n const byDate = new Map(rows.map((row) => [row.date, row]));\n const start = new Date(`${rows[0].date}T12:00:00`);\n const end = new Date(`${rows[rows.length - 1].date}T12:00:00`);\n const completed: DailyUsageMetric[] = [];\n for (\n const cursor = start;\n cursor <= end;\n cursor.setDate(cursor.getDate() + 1)\n ) {\n const date = cursor.toISOString().slice(0, 10);\n completed.push(\n byDate.get(date) ?? {\n date,\n costCents: 0,\n calls: 0,\n chatCalls: 0,\n activeUsers: 0,\n },\n );\n }\n return completed;\n}\n\nfunction displayApp(value: string | null | undefined): string {\n const trimmed = value?.trim();\n if (!trimmed || trimmed === \"unattributed\") return \"Unattributed\";\n return trimmed;\n}\n\nfunction maxSpend(\n rows: Array<{ costCents: number }>,\n billing: UsageBillingMode,\n): number {\n return rows.reduce(\n (max, row) =>\n Math.max(max, displayAmountFromCostCents(row.costCents, billing)),\n 0,\n );\n}\n\nfunction barWidth(value: number, max: number): string {\n if (max <= 0 || value <= 0) return \"0%\";\n return `${Math.max(4, Math.round((value / max) * 100))}%`;\n}\n\nfunction RangeSelector({\n value,\n onChange,\n}: {\n value: number;\n onChange: (value: number) => void;\n}) {\n return (\n <div className=\"flex rounded-md bg-card p-0.5\">\n {RANGES.map((range) => (\n <Button\n key={range}\n type=\"button\"\n variant={value === range ? \"secondary\" : \"ghost\"}\n size=\"sm\"\n className=\"h-7 px-3 text-xs\"\n onClick={() => onChange(range)}\n >\n {range}d\n </Button>\n ))}\n </div>\n );\n}\n\nfunction MetricCard({\n label,\n value,\n detail,\n icon,\n}: {\n label: string;\n value: string;\n detail: string;\n icon: ReactNode;\n}) {\n return (\n <div className=\"rounded-lg bg-card p-4\">\n <div className=\"mb-3 flex items-center justify-between gap-3\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n {label}\n </span>\n <span className=\"text-muted-foreground\">{icon}</span>\n </div>\n <div className=\"text-2xl font-semibold tabular-nums text-foreground\">\n {value}\n </div>\n <div className=\"mt-1 truncate text-xs text-muted-foreground\">\n {detail}\n </div>\n </div>\n );\n}\n\nfunction Panel({\n title,\n icon,\n children,\n action,\n}: {\n title: string;\n icon: ReactNode;\n children: ReactNode;\n action?: ReactNode;\n}) {\n return (\n <section className=\"rounded-lg bg-card\">\n <div className=\"flex items-center justify-between gap-3 border-b px-4 py-3\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <span className=\"text-muted-foreground\">{icon}</span>\n <h2 className=\"truncate text-sm font-semibold text-foreground\">\n {title}\n </h2>\n </div>\n {action}\n </div>\n <div className=\"p-4\">{children}</div>\n </section>\n );\n}\n\nfunction LoadingMetrics() {\n return (\n <div className=\"space-y-4\">\n <div className=\"grid gap-3 md:grid-cols-2 xl:grid-cols-5\">\n {Array.from({ length: 5 }).map((_, index) => (\n <div key={index} className=\"rounded-lg bg-card p-4\">\n <Skeleton className=\"mb-4 h-4 w-24\" />\n <Skeleton className=\"h-7 w-20\" />\n <Skeleton className=\"mt-3 h-3 w-28\" />\n </div>\n ))}\n </div>\n <Skeleton className=\"h-80 rounded-lg\" />\n </div>\n );\n}\n\nfunction ScopeSelector({\n value,\n onChange,\n}: {\n value: \"me\" | \"workspace\";\n onChange: (value: \"me\" | \"workspace\") => void;\n}) {\n return (\n <div className=\"flex rounded-md bg-card p-0.5\" aria-label=\"Usage scope\">\n {(\n [\n [\"me\", \"My usage\"],\n [\"workspace\", \"Workspace\"],\n ] as const\n ).map(([scope, label]) => (\n <Button\n key={scope}\n type=\"button\"\n variant={value === scope ? \"secondary\" : \"ghost\"}\n size=\"sm\"\n className=\"h-7 px-3 text-xs\"\n aria-pressed={value === scope}\n onClick={() => onChange(scope)}\n >\n {label}\n </Button>\n ))}\n </div>\n );\n}\n\nfunction UserSelector({\n value,\n users,\n onChange,\n}: {\n value: string | null;\n users: UsageUserOption[];\n onChange: (value: string | null) => void;\n}) {\n return (\n <Select\n value={value ?? \"all\"}\n onValueChange={(nextValue) =>\n onChange(nextValue === \"all\" ? null : nextValue)\n }\n >\n <SelectTrigger\n className=\"h-8 w-[210px] text-xs\"\n aria-label=\"Filter usage by user\"\n >\n <SelectValue placeholder=\"All users\" />\n </SelectTrigger>\n <SelectContent>\n <SelectGroup>\n <SelectItem value=\"all\">All users</SelectItem>\n {users.map((user) => (\n <SelectItem key={user.email} value={user.email}>\n {user.email}\n </SelectItem>\n ))}\n </SelectGroup>\n </SelectContent>\n </Select>\n );\n}\n\nfunction UsageTrend({\n rows,\n billing,\n}: {\n rows: DailyUsageMetric[];\n billing: UsageBillingMode;\n}) {\n const chartData = completeTrendRows(rows).map((row) => ({\n ...row,\n spend: displayAmountFromCostCents(row.costCents, billing),\n }));\n\n return (\n <Panel\n title={\n billing.unit === \"builder-credits\"\n ? \"Credit usage trend\"\n : \"Usage trend\"\n }\n icon={<IconChartBar size={16} />}\n action={\n <div className=\"hidden items-center gap-3 text-[11px] text-muted-foreground sm:flex\">\n <span className=\"flex items-center gap-1.5\">\n <span className=\"size-2 rounded-full bg-[hsl(var(--dispatch-brand-blue))]\" />\n {billing.shortLabel}\n </span>\n <span className=\"flex items-center gap-1.5\">\n <span className=\"size-2 rounded-full bg-muted-foreground\" />\n Calls\n </span>\n </div>\n }\n >\n {chartData.length === 0 ? (\n <div className=\"flex min-h-56 items-center justify-center rounded-md border border-dashed px-4 text-sm text-muted-foreground\">\n No usage in this window yet.\n </div>\n ) : (\n <ChartContainer\n config={{\n spend: {\n label: billing.shortLabel,\n color: \"hsl(var(--dispatch-brand-blue))\",\n },\n calls: {\n label: \"Calls\",\n color: \"hsl(var(--muted-foreground))\",\n },\n }}\n className=\"h-[280px] w-full aspect-auto\"\n >\n <AreaChart\n data={chartData}\n margin={{ top: 8, right: 8, left: 12, bottom: 0 }}\n >\n <defs>\n <linearGradient id=\"usage-trend-fill\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop\n offset=\"0%\"\n stopColor=\"var(--color-spend)\"\n stopOpacity={0.24}\n />\n <stop\n offset=\"100%\"\n stopColor=\"var(--color-spend)\"\n stopOpacity={0}\n />\n </linearGradient>\n </defs>\n <CartesianGrid\n vertical={false}\n stroke=\"hsl(var(--border))\"\n strokeDasharray=\"3 3\"\n />\n <XAxis\n dataKey=\"date\"\n stroke=\"hsl(var(--muted-foreground))\"\n fontSize={11}\n axisLine={false}\n tickLine={false}\n tickMargin={8}\n minTickGap={28}\n tickFormatter={formatTrendDate}\n />\n <YAxis\n yAxisId=\"spend\"\n stroke=\"hsl(var(--muted-foreground))\"\n fontSize={11}\n axisLine={false}\n tickLine={false}\n tickMargin={8}\n width={50}\n tickFormatter={(value) =>\n billing.unit === \"builder-credits\"\n ? formatCredits(Number(value))\n : formatSpend(Number(value), billing)\n }\n />\n <YAxis yAxisId=\"calls\" orientation=\"right\" hide />\n <ChartTooltip\n cursor={false}\n content={\n <ChartTooltipContent\n labelFormatter={(value) => formatTrendDate(String(value))}\n formatter={(value, name) => [\n name === \"spend\"\n ? billing.unit === \"builder-credits\"\n ? formatCredits(Number(value))\n : formatSpend(Number(value), billing)\n : `${formatNumber(Number(value))} calls`,\n name === \"spend\" ? billing.shortLabel : \"Calls\",\n ]}\n />\n }\n />\n <Area\n yAxisId=\"spend\"\n dataKey=\"spend\"\n type=\"monotone\"\n stroke=\"var(--color-spend)\"\n strokeWidth={2}\n fill=\"url(#usage-trend-fill)\"\n fillOpacity={1}\n dot={false}\n activeDot={{ r: 4, strokeWidth: 2 }}\n isAnimationActive={false}\n />\n <Area\n yAxisId=\"calls\"\n dataKey=\"calls\"\n type=\"monotone\"\n stroke=\"var(--color-calls)\"\n strokeWidth={1.5}\n fill=\"none\"\n dot={false}\n activeDot={{ r: 3, strokeWidth: 2 }}\n isAnimationActive={false}\n />\n </AreaChart>\n </ChartContainer>\n )}\n </Panel>\n );\n}\n\nfunction ReviewUsageButton({\n metrics,\n billing,\n}: {\n metrics: DispatchUsageMetrics;\n billing: UsageBillingMode;\n}) {\n function reviewUsage() {\n const topApps = metrics.byApp\n .slice(0, 5)\n .map(\n (row) =>\n `${displayApp(row.key)}: ${formatSpend(row.costCents, billing)} / ${row.calls} calls`,\n )\n .join(\"; \");\n const topLabels = metrics.byLabel\n .slice(0, 5)\n .map(\n (row) =>\n `${row.label}: ${formatSpend(row.costCents, billing)} / ${row.calls} calls`,\n )\n .join(\"; \");\n const recentPrompts = metrics.recent\n .slice(0, 8)\n .map((row) => {\n const prompt = row.prompt\n ? row.prompt.slice(0, 180)\n : \"prompt not captured\";\n return `${timeAgo(row.createdAt)} | ${displayApp(row.app)} | ${row.label} | ${prompt}`;\n })\n .join(\"\\n\");\n\n sendToAgentChat({\n message:\n \"Review this LLM usage and explain where the spend is going. Identify repeated, background, or unexpectedly expensive work, cite the strongest evidence, and suggest concrete fixes. Call out missing attribution instead of guessing.\",\n context: [\n `Dispatch usage scope: ${metrics.viewScope === \"workspace\" ? \"workspace\" : \"my account\"}.`,\n `Lookback: ${metrics.sinceDays} days. Viewer: ${metrics.access.viewerEmail}.`,\n `Total: ${formatSpend(metrics.totals.costCents, billing)}, ${metrics.totals.calls} calls, ${metrics.totals.chatCalls} chat calls, ${formatTokens(metrics.totals.inputTokens + metrics.totals.outputTokens)} input/output tokens.`,\n `Top apps: ${topApps || \"none\"}.`,\n `Top work types: ${topLabels || \"none\"}.`,\n `Recent prompt evidence (bounded to the latest 8 rows):\\n${recentPrompts || \"none\"}`,\n ].join(\"\\n\"),\n submit: true,\n openSidebar: true,\n chatTarget: \"local\",\n });\n }\n\n return (\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={reviewUsage}>\n Ask agent\n </Button>\n );\n}\n\nfunction AppSpendRows({\n rows,\n billing,\n}: {\n rows: UsageMetricBucket[];\n billing: UsageBillingMode;\n}) {\n const max = maxSpend(rows, billing);\n if (rows.length === 0) {\n return (\n <div className=\"rounded-lg border border-dashed px-4 py-8 text-sm text-muted-foreground\">\n No LLM usage recorded for this window.\n </div>\n );\n }\n return (\n <div className=\"space-y-3\">\n {rows.map((row) => (\n <div key={row.key} className=\"space-y-1.5\">\n <div className=\"flex items-center justify-between gap-3 text-sm\">\n <div className=\"min-w-0\">\n <div className=\"truncate font-medium text-foreground\">\n {displayApp(row.key)}\n </div>\n <div className=\"text-xs text-muted-foreground\">\n {formatNumber(row.chatCalls)} chats ·{\" \"}\n {formatNumber(row.activeUsers)} users\n </div>\n </div>\n <div className=\"shrink-0 text-right\">\n <div className=\"font-medium tabular-nums text-foreground\">\n {formatSpend(row.costCents, billing)}\n </div>\n <div className=\"text-xs text-muted-foreground\">\n {formatNumber(row.calls)} calls\n </div>\n </div>\n </div>\n <div className=\"h-2 overflow-hidden rounded-full bg-muted\">\n <div\n className=\"h-full rounded-full bg-foreground\"\n style={{\n width: barWidth(\n displayAmountFromCostCents(row.costCents, billing),\n max,\n ),\n }}\n />\n </div>\n </div>\n ))}\n </div>\n );\n}\n\nfunction AppAccessTable({\n rows,\n billing,\n}: {\n rows: AppAccessMetric[];\n billing: UsageBillingMode;\n}) {\n const visibleRows = rows.filter((row) => !row.isDispatch);\n if (visibleRows.length === 0) {\n return (\n <div className=\"rounded-lg border border-dashed px-4 py-8 text-sm text-muted-foreground\">\n No workspace apps discovered yet.\n </div>\n );\n }\n return (\n <div className=\"overflow-x-auto\">\n <table className=\"w-full min-w-[720px] text-left text-xs\">\n <thead>\n <tr className=\"border-b text-muted-foreground\">\n <th className=\"px-2 py-2 font-medium\">App</th>\n <th className=\"px-2 py-2 font-medium\">Access</th>\n <th className=\"px-2 py-2 text-right font-medium\">Users</th>\n <th className=\"px-2 py-2 text-right font-medium\">Chats</th>\n <th className=\"px-2 py-2 text-right font-medium\">\n {billing.shortLabel}\n </th>\n <th className=\"px-2 py-2 text-right font-medium\">Last activity</th>\n </tr>\n </thead>\n <tbody>\n {visibleRows.map((row) => (\n <tr key={row.id} className=\"border-b last:border-0\">\n <td className=\"px-2 py-3\">\n <div className=\"font-medium text-foreground\">{row.name}</div>\n <div className=\"font-mono text-[11px] text-muted-foreground\">\n {row.path}\n </div>\n </td>\n <td className=\"px-2 py-3\">\n <Badge\n variant=\"outline\"\n className={cn(\n row.status === \"pending\" &&\n \"border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300\",\n )}\n >\n {row.status === \"pending\"\n ? row.statusLabel || \"Builder branch\"\n : row.accessLabel}\n </Badge>\n </td>\n <td className=\"px-2 py-3 text-right tabular-nums\">\n {formatNumber(row.usersWithUsage)} /{\" \"}\n {formatNumber(row.accessUsers)}\n </td>\n <td className=\"px-2 py-3 text-right tabular-nums\">\n {formatNumber(row.chatCalls)}\n </td>\n <td className=\"px-2 py-3 text-right tabular-nums\">\n {formatSpend(row.costCents, billing)}\n </td>\n <td className=\"px-2 py-3 text-right text-muted-foreground\">\n {timeAgo(row.lastActiveAt)}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\nfunction UserTable({\n rows,\n billing,\n}: {\n rows: UserUsageMetric[];\n billing: UsageBillingMode;\n}) {\n if (rows.length === 0) {\n return (\n <div className=\"rounded-lg border border-dashed px-4 py-8 text-sm text-muted-foreground\">\n No users have triggered LLM usage in this window.\n </div>\n );\n }\n return (\n <div className=\"overflow-x-auto\">\n <table className=\"w-full min-w-[760px] text-left text-xs\">\n <thead>\n <tr className=\"border-b text-muted-foreground\">\n <th className=\"px-2 py-2 font-medium\">User</th>\n <th className=\"px-2 py-2 font-medium\">Role</th>\n <th className=\"px-2 py-2 font-medium\">Top app</th>\n <th className=\"px-2 py-2 text-right font-medium\">Chats</th>\n <th className=\"px-2 py-2 text-right font-medium\">Threads</th>\n <th className=\"px-2 py-2 text-right font-medium\">Tokens</th>\n <th className=\"px-2 py-2 text-right font-medium\">\n {billing.shortLabel}\n </th>\n </tr>\n </thead>\n <tbody>\n {rows.slice(0, 12).map((row) => (\n <tr key={row.ownerEmail} className=\"border-b last:border-0\">\n <td className=\"max-w-64 px-2 py-3\">\n <div className=\"truncate font-medium text-foreground\">\n {row.ownerEmail}\n </div>\n <div className=\"text-muted-foreground\">\n {timeAgo(row.lastActiveAt ?? row.lastChatAt)}\n </div>\n </td>\n <td className=\"px-2 py-3\">\n <Badge variant=\"secondary\">{row.role ?? \"user\"}</Badge>\n </td>\n <td className=\"px-2 py-3 text-muted-foreground\">\n {displayApp(row.topApp)}\n </td>\n <td className=\"px-2 py-3 text-right tabular-nums\">\n {formatNumber(row.chatCalls)}\n </td>\n <td className=\"px-2 py-3 text-right tabular-nums\">\n {formatNumber(row.chatThreads)}\n </td>\n <td className=\"px-2 py-3 text-right tabular-nums\">\n {formatTokens(row.inputTokens + row.outputTokens)}\n </td>\n <td className=\"px-2 py-3 text-right tabular-nums\">\n {formatSpend(row.costCents, billing)}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\nfunction CompactBreakdown({\n rows,\n empty,\n billing,\n}: {\n rows: UsageMetricBucket[];\n empty: string;\n billing: UsageBillingMode;\n}) {\n const max = maxSpend(rows, billing);\n if (rows.length === 0) {\n return <div className=\"text-sm text-muted-foreground\">{empty}</div>;\n }\n return (\n <div className=\"space-y-3\">\n {rows.slice(0, 6).map((row) => (\n <div key={row.key} className=\"space-y-1\">\n <div className=\"flex items-center justify-between gap-3 text-xs\">\n <span className=\"truncate font-medium text-foreground\">\n {row.label}\n </span>\n <span className=\"shrink-0 tabular-nums text-muted-foreground\">\n {formatSpend(row.costCents, billing)}\n </span>\n </div>\n <div className=\"h-1.5 overflow-hidden rounded-full bg-muted\">\n <div\n className=\"h-full rounded-full bg-muted-foreground\"\n style={{\n width: barWidth(\n displayAmountFromCostCents(row.costCents, billing),\n max,\n ),\n }}\n />\n </div>\n </div>\n ))}\n </div>\n );\n}\n\nfunction RecentTable({\n rows,\n billing,\n}: {\n rows: RecentUsageMetric[];\n billing: UsageBillingMode;\n}) {\n if (rows.length === 0) {\n return (\n <div className=\"rounded-lg border border-dashed px-4 py-8 text-sm text-muted-foreground\">\n No prompts or LLM calls in this window.\n </div>\n );\n }\n return (\n <div className=\"divide-y\">\n {rows.slice(0, 10).map((row) => (\n <article key={row.id} className=\"-mx-1 px-1 py-3 first:pt-0 last:pb-0\">\n <div className=\"flex items-start justify-between gap-4\">\n <p className=\"min-w-0 whitespace-pre-wrap text-sm leading-6 text-foreground\">\n {row.prompt ||\n (row.promptSource === \"unavailable\"\n ? \"Prompt unavailable - linked thread data could not be read.\"\n : \"Prompt not captured for this call.\")}\n </p>\n <span className=\"shrink-0 text-xs text-muted-foreground\">\n {timeAgo(row.createdAt)}\n </span>\n </div>\n <div className=\"mt-2 flex flex-wrap items-center gap-1.5 text-xs text-muted-foreground\">\n <Badge variant=\"outline\">{displayApp(row.app)}</Badge>\n <Badge variant=\"secondary\">{row.label}</Badge>\n <span>{row.model}</span>\n <span aria-hidden=\"true\">·</span>\n <span>{formatSpend(row.costCents, billing)}</span>\n {row.ownerEmail ? (\n <>\n <span aria-hidden=\"true\">·</span>\n <span className=\"max-w-64 truncate\">{row.ownerEmail}</span>\n </>\n ) : null}\n {row.threadId ? (\n <Link\n to={`/admin/thread-debug?threadId=${encodeURIComponent(row.threadId)}`}\n className=\"inline-flex items-center gap-1 rounded-md border px-2 py-0.5 font-medium text-foreground transition-colors hover:bg-muted\"\n >\n Inspect thread\n <IconArrowUpRight size={12} />\n </Link>\n ) : null}\n </div>\n </article>\n ))}\n </div>\n );\n}\n\nexport default function MetricsRoute() {\n const t = useT();\n const [sinceDays, setSinceDays] = useState(30);\n const [searchParams, setSearchParams] = useSearchParams();\n const scope: \"me\" | \"workspace\" =\n searchParams.get(\"scope\") === \"workspace\" ? \"workspace\" : \"me\";\n const userEmail =\n scope === \"workspace\" ? searchParams.get(\"user\") || null : null;\n\n function setScope(nextScope: \"me\" | \"workspace\") {\n const next = new URLSearchParams(searchParams);\n if (nextScope === \"me\") next.delete(\"scope\");\n else next.set(\"scope\", nextScope);\n if (nextScope === \"me\") next.delete(\"user\");\n setSearchParams(next, { replace: true });\n }\n\n function setUserEmail(nextUserEmail: string | null) {\n const next = new URLSearchParams(searchParams);\n if (nextUserEmail) next.set(\"user\", nextUserEmail);\n else next.delete(\"user\");\n setSearchParams(next, { replace: true });\n }\n\n const { data, isLoading, error } = useActionQuery(\n \"list-dispatch-usage-metrics\",\n { sinceDays, scope, userEmail: userEmail ?? undefined },\n );\n const metrics = data as DispatchUsageMetrics | undefined;\n const billing = metrics?.billing ?? USD_BILLING;\n const totalTokens = useMemo(() => {\n if (!metrics) return 0;\n return (\n metrics.totals.inputTokens +\n metrics.totals.outputTokens +\n metrics.totals.cacheReadTokens +\n metrics.totals.cacheWriteTokens\n );\n }, [metrics]);\n\n return (\n <DispatchShell\n title={t(\"dispatch.nav.metrics\")}\n description={\n billing.unit === \"builder-credits\"\n ? t(\"dispatch.pages.metricsDescriptionBuilder\")\n : t(\"dispatch.pages.metricsDescriptionLlm\")\n }\n >\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div>\n <div className=\"text-sm font-medium text-foreground\">\n {metrics?.selectedUserEmail\n ? `${metrics.selectedUserEmail}'s usage`\n : scope === \"workspace\"\n ? \"Workspace usage\"\n : \"Your usage\"}\n </div>\n <div className=\"mt-0.5 text-xs text-muted-foreground\">\n {metrics?.selectedUserEmail\n ? \"Filtered to this workspace member\"\n : scope === \"workspace\"\n ? `${metrics?.access.totalUsers ?? 0} users with access`\n : metrics?.access.viewerEmail || \"Signed-in account\"}\n </div>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <ScopeSelector value={scope} onChange={setScope} />\n {scope === \"workspace\" && metrics ? (\n <UserSelector\n value={metrics.selectedUserEmail ?? userEmail}\n users={metrics.availableUsers ?? []}\n onChange={setUserEmail}\n />\n ) : null}\n <RangeSelector value={sinceDays} onChange={setSinceDays} />\n </div>\n </div>\n\n {error ? (\n <Alert variant=\"destructive\">\n <IconAlertTriangle className=\"h-4 w-4\" />\n <AlertTitle>{t(\"dispatch.pages.metricsUnavailable\")}</AlertTitle>\n <AlertDescription>\n {error instanceof Error\n ? error.message\n : t(\"dispatch.pages.unableToLoadUsage\")}\n </AlertDescription>\n </Alert>\n ) : null}\n\n {isLoading && !metrics ? <LoadingMetrics /> : null}\n\n {metrics ? (\n <>\n <UsageTrend rows={metrics.daily} billing={billing} />\n\n <div className=\"flex items-center justify-between gap-3 border-y py-3\">\n <span className=\"text-sm text-muted-foreground\">\n Review this usage with the agent\n </span>\n <ReviewUsageButton metrics={metrics} billing={billing} />\n </div>\n\n <div className=\"grid gap-3 md:grid-cols-2 xl:grid-cols-5\">\n <MetricCard\n label={billing.label}\n value={formatSpend(metrics.totals.costCents, billing)}\n detail={`${formatTokens(totalTokens)} total tokens`}\n icon={<IconCoin size={17} />}\n />\n <MetricCard\n label={t(\"dispatch.pages.llmCalls\")}\n value={formatNumber(metrics.totals.calls)}\n detail={`${formatNumber(metrics.totals.chatCalls)} chat turns`}\n icon={<IconActivity size={17} />}\n />\n <MetricCard\n label={t(\"dispatch.pages.activeUsers\")}\n value={formatNumber(metrics.totals.activeUsers)}\n detail={`${formatNumber(metrics.access.totalUsers)} users with access`}\n icon={<IconUsersGroup size={17} />}\n />\n <MetricCard\n label={t(\"dispatch.pages.workspaceAppsStat\")}\n value={formatNumber(metrics.totals.workspaceApps)}\n detail={`${formatNumber(metrics.byApp.length)} with usage`}\n icon={<IconApps size={17} />}\n />\n <MetricCard\n label={t(\"dispatch.pages.chatThreads\")}\n value={formatNumber(metrics.totals.chatThreads)}\n detail={`${formatNumber(metrics.totals.chatMessages)} messages`}\n icon={<IconMessages size={17} />}\n />\n </div>\n\n <Panel\n title={\n billing.unit === \"builder-credits\"\n ? \"Credit spend by app\"\n : \"Spend by app\"\n }\n icon={<IconApps size={16} />}\n >\n <AppSpendRows rows={metrics.byApp} billing={billing} />\n </Panel>\n\n <Panel\n title=\"Recent prompts\"\n icon={<IconMessages size={16} />}\n action={\n <span className=\"text-xs text-muted-foreground\">\n Latest {Math.min(metrics.recent.length, 10)} of{\" \"}\n {metrics.recent.length}\n </span>\n }\n >\n <RecentTable rows={metrics.recent} billing={billing} />\n </Panel>\n\n <Panel title=\"Access By App\" icon={<IconApps size={16} />}>\n <AppAccessTable rows={metrics.appAccess} billing={billing} />\n </Panel>\n\n <Panel title=\"Users\" icon={<IconUsersGroup size={16} />}>\n <UserTable rows={metrics.byUser} billing={billing} />\n </Panel>\n\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <Panel title=\"Models\" icon={<IconChartBar size={16} />}>\n <CompactBreakdown\n rows={metrics.byModel}\n empty=\"No model usage in this window.\"\n billing={billing}\n />\n </Panel>\n <Panel title=\"Work Types\" icon={<IconActivity size={16} />}>\n <CompactBreakdown\n rows={metrics.byLabel}\n empty=\"No labeled usage in this window.\"\n billing={billing}\n />\n </Panel>\n </div>\n </>\n ) : null}\n </div>\n </DispatchShell>\n );\n}\n"]}
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../../src/routes/pages/metrics.tsx"],"names":[],"mappings":"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","sourcesContent":["import { sendToAgentChat } from \"@agent-native/core/client/agent-chat\";\nimport { useActionQuery } from \"@agent-native/core/client/hooks\";\nimport { useT } from \"@agent-native/core/client/i18n\";\nimport {\n IconActivity,\n IconAlertTriangle,\n IconArrowUpRight,\n IconApps,\n IconChartBar,\n IconCoin,\n IconMessages,\n IconUsersGroup,\n} from \"@tabler/icons-react\";\nimport { useMemo, useState, type ReactNode } from \"react\";\nimport { Link, useSearchParams } from \"react-router\";\nimport { Area, AreaChart, CartesianGrid, XAxis, YAxis } from \"recharts\";\n\nimport { DispatchShell } from \"../../components/dispatch-shell\";\nimport { Alert, AlertDescription, AlertTitle } from \"../../components/ui/alert\";\nimport { Badge } from \"../../components/ui/badge\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n} from \"../../components/ui/chart\";\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../components/ui/select\";\nimport { Skeleton } from \"../../components/ui/skeleton\";\nimport { UsageAlertsPanel } from \"../../components/usage-alerts-panel\";\nimport { cn } from \"../../lib/utils\";\n\nexport function meta() {\n return [{ title: \"Metrics — Dispatch\" }];\n}\n\ninterface UsageMetricBucket {\n key: string;\n label: string;\n costCents: number;\n calls: number;\n chatCalls: number;\n inputTokens: number;\n outputTokens: number;\n activeUsers: number;\n lastActiveAt: number | null;\n}\n\ninterface UserUsageMetric extends UsageMetricBucket {\n ownerEmail: string;\n chatThreads: number;\n chatMessages: number;\n lastChatAt: number | null;\n topApp: string | null;\n role: string | null;\n}\n\ninterface UsageUserOption {\n email: string;\n role: string | null;\n}\n\ninterface AppAccessMetric {\n id: string;\n name: string;\n path: string;\n status?: \"ready\" | \"pending\";\n statusLabel?: string;\n isDispatch: boolean;\n accessLabel: string;\n accessUsers: number;\n usersWithUsage: number;\n usageCalls: number;\n chatCalls: number;\n costCents: number;\n lastActiveAt: number | null;\n}\n\ninterface DailyUsageMetric {\n date: string;\n costCents: number;\n calls: number;\n chatCalls: number;\n activeUsers: number;\n}\n\ninterface RecentUsageMetric {\n id: number;\n createdAt: number;\n ownerEmail: string;\n app: string;\n label: string;\n model: string;\n inputTokens: number;\n outputTokens: number;\n costCents: number;\n prompt: string | null;\n promptSource: \"thread\" | \"thread-preview\" | \"not-captured\" | \"unavailable\";\n threadId: string | null;\n runId: string | null;\n taskId: string | null;\n sourcePlatform: string | null;\n sourceId: string | null;\n}\n\ninterface UsageBillingMode {\n unit: \"usd\" | \"builder-credits\";\n label: string;\n shortLabel: string;\n source: \"estimated-provider-cost\" | \"builder-agent-credits\";\n hardCostMarginMultiplier?: number;\n creditsPerUsd?: number;\n}\n\ninterface DispatchUsageMetrics {\n billing?: UsageBillingMode;\n viewScope?: \"me\" | \"workspace\";\n selectedUserEmail?: string | null;\n availableUsers?: UsageUserOption[];\n sinceDays: number;\n access: {\n viewerEmail: string;\n orgId: string | null;\n role: string | null;\n scope: \"organization\" | \"solo\";\n totalUsers: number;\n };\n totals: {\n costCents: number;\n calls: number;\n chatCalls: number;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n activeUsers: number;\n chatThreads: number;\n chatMessages: number;\n workspaceApps: number;\n };\n byApp: UsageMetricBucket[];\n byUser: UserUsageMetric[];\n byLabel: UsageMetricBucket[];\n byModel: UsageMetricBucket[];\n daily: DailyUsageMetric[];\n appAccess: AppAccessMetric[];\n recent: RecentUsageMetric[];\n}\n\nconst RANGES = [7, 30, 90] as const;\n\nconst USD_BILLING: UsageBillingMode = {\n unit: \"usd\",\n label: \"Estimated spend\",\n shortLabel: \"Cost\",\n source: \"estimated-provider-cost\",\n};\n\nfunction displayAmountFromCostCents(\n cents: number,\n billing: UsageBillingMode,\n): number {\n if (billing.unit !== \"builder-credits\") return cents;\n const margin = billing.hardCostMarginMultiplier ?? 1.25;\n const creditsPerUsd = billing.creditsPerUsd ?? 20;\n const credits = (cents / 100) * margin * creditsPerUsd;\n return credits <= 0 ? 0 : Math.ceil(credits * 1000) / 1000;\n}\n\nfunction formatCredits(credits: number): string {\n if (!Number.isFinite(credits) || credits === 0) return \"0 credits\";\n const maximumFractionDigits = credits < 1 ? 3 : credits < 10 ? 2 : 1;\n const value = credits.toLocaleString(undefined, {\n maximumFractionDigits,\n });\n return `${value} ${credits === 1 ? \"credit\" : \"credits\"}`;\n}\n\nfunction formatSpend(cents: number, billing: UsageBillingMode): string {\n if (billing.unit === \"builder-credits\") {\n return formatCredits(displayAmountFromCostCents(cents, billing));\n }\n if (!Number.isFinite(cents) || cents === 0) return \"$0.00\";\n if (Math.abs(cents) < 1) return `${cents.toFixed(3)}¢`;\n if (Math.abs(cents) < 100) return `${cents.toFixed(2)}¢`;\n return (cents / 100).toLocaleString(undefined, {\n style: \"currency\",\n currency: \"USD\",\n maximumFractionDigits: 2,\n });\n}\n\nfunction formatNumber(value: number): string {\n return new Intl.NumberFormat(undefined, {\n notation: value >= 10_000 ? \"compact\" : \"standard\",\n maximumFractionDigits: value >= 10_000 ? 1 : 0,\n }).format(value);\n}\n\nfunction formatTokens(value: number): string {\n return new Intl.NumberFormat(undefined, {\n notation: \"compact\",\n maximumFractionDigits: 1,\n }).format(value);\n}\n\nfunction timeAgo(timestamp: number | null): string {\n if (!timestamp) return \"No activity\";\n const diff = Date.now() - timestamp;\n if (diff < 60_000) return \"just now\";\n if (diff < 3_600_000) return `${Math.floor(diff / 60_000)}m ago`;\n if (diff < 86_400_000) return `${Math.floor(diff / 3_600_000)}h ago`;\n return `${Math.floor(diff / 86_400_000)}d ago`;\n}\n\nfunction formatTrendDate(value: string): string {\n const date = new Date(`${value}T12:00:00`);\n return date.toLocaleDateString(undefined, {\n month: \"short\",\n day: \"numeric\",\n });\n}\n\nfunction completeTrendRows(rows: DailyUsageMetric[]): DailyUsageMetric[] {\n if (rows.length < 2) return rows;\n const byDate = new Map(rows.map((row) => [row.date, row]));\n const start = new Date(`${rows[0].date}T12:00:00`);\n const end = new Date(`${rows[rows.length - 1].date}T12:00:00`);\n const completed: DailyUsageMetric[] = [];\n for (\n const cursor = start;\n cursor <= end;\n cursor.setDate(cursor.getDate() + 1)\n ) {\n const date = cursor.toISOString().slice(0, 10);\n completed.push(\n byDate.get(date) ?? {\n date,\n costCents: 0,\n calls: 0,\n chatCalls: 0,\n activeUsers: 0,\n },\n );\n }\n return completed;\n}\n\nfunction displayApp(value: string | null | undefined): string {\n const trimmed = value?.trim();\n if (!trimmed || trimmed === \"unattributed\") return \"Unattributed\";\n return trimmed;\n}\n\nfunction maxSpend(\n rows: Array<{ costCents: number }>,\n billing: UsageBillingMode,\n): number {\n return rows.reduce(\n (max, row) =>\n Math.max(max, displayAmountFromCostCents(row.costCents, billing)),\n 0,\n );\n}\n\nfunction barWidth(value: number, max: number): string {\n if (max <= 0 || value <= 0) return \"0%\";\n return `${Math.max(4, Math.round((value / max) * 100))}%`;\n}\n\nfunction RangeSelector({\n value,\n onChange,\n}: {\n value: number;\n onChange: (value: number) => void;\n}) {\n return (\n <div className=\"flex rounded-md bg-card p-0.5\">\n {RANGES.map((range) => (\n <Button\n key={range}\n type=\"button\"\n variant={value === range ? \"secondary\" : \"ghost\"}\n size=\"sm\"\n className=\"h-7 px-3 text-xs\"\n onClick={() => onChange(range)}\n >\n {range}d\n </Button>\n ))}\n </div>\n );\n}\n\nfunction MetricCard({\n label,\n value,\n detail,\n icon,\n}: {\n label: string;\n value: string;\n detail: string;\n icon: ReactNode;\n}) {\n return (\n <div className=\"rounded-lg bg-card p-4\">\n <div className=\"mb-3 flex items-center justify-between gap-3\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n {label}\n </span>\n <span className=\"text-muted-foreground\">{icon}</span>\n </div>\n <div className=\"text-2xl font-semibold tabular-nums text-foreground\">\n {value}\n </div>\n <div className=\"mt-1 truncate text-xs text-muted-foreground\">\n {detail}\n </div>\n </div>\n );\n}\n\nfunction Panel({\n title,\n icon,\n children,\n action,\n}: {\n title: string;\n icon: ReactNode;\n children: ReactNode;\n action?: ReactNode;\n}) {\n return (\n <section className=\"rounded-lg bg-card\">\n <div className=\"flex items-center justify-between gap-3 border-b px-4 py-3\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <span className=\"text-muted-foreground\">{icon}</span>\n <h2 className=\"truncate text-sm font-semibold text-foreground\">\n {title}\n </h2>\n </div>\n {action}\n </div>\n <div className=\"p-4\">{children}</div>\n </section>\n );\n}\n\nfunction LoadingMetrics() {\n return (\n <div className=\"space-y-4\">\n <div className=\"grid gap-3 md:grid-cols-2 xl:grid-cols-5\">\n {Array.from({ length: 5 }).map((_, index) => (\n <div key={index} className=\"rounded-lg bg-card p-4\">\n <Skeleton className=\"mb-4 h-4 w-24\" />\n <Skeleton className=\"h-7 w-20\" />\n <Skeleton className=\"mt-3 h-3 w-28\" />\n </div>\n ))}\n </div>\n <Skeleton className=\"h-80 rounded-lg\" />\n </div>\n );\n}\n\nfunction ScopeSelector({\n value,\n onChange,\n}: {\n value: \"me\" | \"workspace\";\n onChange: (value: \"me\" | \"workspace\") => void;\n}) {\n return (\n <div className=\"flex rounded-md bg-card p-0.5\" aria-label=\"Usage scope\">\n {(\n [\n [\"me\", \"My usage\"],\n [\"workspace\", \"Workspace\"],\n ] as const\n ).map(([scope, label]) => (\n <Button\n key={scope}\n type=\"button\"\n variant={value === scope ? \"secondary\" : \"ghost\"}\n size=\"sm\"\n className=\"h-7 px-3 text-xs\"\n aria-pressed={value === scope}\n onClick={() => onChange(scope)}\n >\n {label}\n </Button>\n ))}\n </div>\n );\n}\n\nfunction UserSelector({\n value,\n users,\n onChange,\n}: {\n value: string | null;\n users: UsageUserOption[];\n onChange: (value: string | null) => void;\n}) {\n return (\n <Select\n value={value ?? \"all\"}\n onValueChange={(nextValue) =>\n onChange(nextValue === \"all\" ? null : nextValue)\n }\n >\n <SelectTrigger\n className=\"h-8 w-[210px] text-xs\"\n aria-label=\"Filter usage by user\"\n >\n <SelectValue placeholder=\"All users\" />\n </SelectTrigger>\n <SelectContent>\n <SelectGroup>\n <SelectItem value=\"all\">All users</SelectItem>\n {users.map((user) => (\n <SelectItem key={user.email} value={user.email}>\n {user.email}\n </SelectItem>\n ))}\n </SelectGroup>\n </SelectContent>\n </Select>\n );\n}\n\nfunction UsageTrend({\n rows,\n billing,\n}: {\n rows: DailyUsageMetric[];\n billing: UsageBillingMode;\n}) {\n const chartData = completeTrendRows(rows).map((row) => ({\n ...row,\n spend: displayAmountFromCostCents(row.costCents, billing),\n }));\n\n return (\n <Panel\n title={\n billing.unit === \"builder-credits\"\n ? \"Credit usage trend\"\n : \"Usage trend\"\n }\n icon={<IconChartBar size={16} />}\n action={\n <div className=\"hidden items-center gap-3 text-[11px] text-muted-foreground sm:flex\">\n <span className=\"flex items-center gap-1.5\">\n <span className=\"size-2 rounded-full bg-[hsl(var(--dispatch-brand-blue))]\" />\n {billing.shortLabel}\n </span>\n <span className=\"flex items-center gap-1.5\">\n <span className=\"size-2 rounded-full bg-muted-foreground\" />\n Calls\n </span>\n </div>\n }\n >\n {chartData.length === 0 ? (\n <div className=\"flex min-h-56 items-center justify-center rounded-md border border-dashed px-4 text-sm text-muted-foreground\">\n No usage in this window yet.\n </div>\n ) : (\n <ChartContainer\n config={{\n spend: {\n label: billing.shortLabel,\n color: \"hsl(var(--dispatch-brand-blue))\",\n },\n calls: {\n label: \"Calls\",\n color: \"hsl(var(--muted-foreground))\",\n },\n }}\n className=\"h-[280px] w-full aspect-auto\"\n >\n <AreaChart\n data={chartData}\n margin={{ top: 8, right: 8, left: 12, bottom: 0 }}\n >\n <defs>\n <linearGradient id=\"usage-trend-fill\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop\n offset=\"0%\"\n stopColor=\"var(--color-spend)\"\n stopOpacity={0.24}\n />\n <stop\n offset=\"100%\"\n stopColor=\"var(--color-spend)\"\n stopOpacity={0}\n />\n </linearGradient>\n </defs>\n <CartesianGrid\n vertical={false}\n stroke=\"hsl(var(--border))\"\n strokeDasharray=\"3 3\"\n />\n <XAxis\n dataKey=\"date\"\n stroke=\"hsl(var(--muted-foreground))\"\n fontSize={11}\n axisLine={false}\n tickLine={false}\n tickMargin={8}\n minTickGap={28}\n tickFormatter={formatTrendDate}\n />\n <YAxis\n yAxisId=\"spend\"\n stroke=\"hsl(var(--muted-foreground))\"\n fontSize={11}\n axisLine={false}\n tickLine={false}\n tickMargin={8}\n width={50}\n tickFormatter={(value) =>\n billing.unit === \"builder-credits\"\n ? formatCredits(Number(value))\n : formatSpend(Number(value), billing)\n }\n />\n <YAxis yAxisId=\"calls\" orientation=\"right\" hide />\n <ChartTooltip\n cursor={false}\n content={\n <ChartTooltipContent\n labelFormatter={(value) => formatTrendDate(String(value))}\n formatter={(value, name) => [\n name === \"spend\"\n ? billing.unit === \"builder-credits\"\n ? formatCredits(Number(value))\n : formatSpend(Number(value), billing)\n : `${formatNumber(Number(value))} calls`,\n name === \"spend\" ? billing.shortLabel : \"Calls\",\n ]}\n />\n }\n />\n <Area\n yAxisId=\"spend\"\n dataKey=\"spend\"\n type=\"monotone\"\n stroke=\"var(--color-spend)\"\n strokeWidth={2}\n fill=\"url(#usage-trend-fill)\"\n fillOpacity={1}\n dot={false}\n activeDot={{ r: 4, strokeWidth: 2 }}\n isAnimationActive={false}\n />\n <Area\n yAxisId=\"calls\"\n dataKey=\"calls\"\n type=\"monotone\"\n stroke=\"var(--color-calls)\"\n strokeWidth={1.5}\n fill=\"none\"\n dot={false}\n activeDot={{ r: 3, strokeWidth: 2 }}\n isAnimationActive={false}\n />\n </AreaChart>\n </ChartContainer>\n )}\n </Panel>\n );\n}\n\nfunction ReviewUsageButton({\n metrics,\n billing,\n}: {\n metrics: DispatchUsageMetrics;\n billing: UsageBillingMode;\n}) {\n function reviewUsage() {\n const topApps = metrics.byApp\n .slice(0, 5)\n .map(\n (row) =>\n `${displayApp(row.key)}: ${formatSpend(row.costCents, billing)} / ${row.calls} calls`,\n )\n .join(\"; \");\n const topLabels = metrics.byLabel\n .slice(0, 5)\n .map(\n (row) =>\n `${row.label}: ${formatSpend(row.costCents, billing)} / ${row.calls} calls`,\n )\n .join(\"; \");\n const recentPrompts = metrics.recent\n .slice(0, 8)\n .map((row) => {\n const prompt = row.prompt\n ? row.prompt.slice(0, 180)\n : \"prompt not captured\";\n return `${timeAgo(row.createdAt)} | ${displayApp(row.app)} | ${row.label} | ${prompt}`;\n })\n .join(\"\\n\");\n\n sendToAgentChat({\n message:\n \"Review this LLM usage and explain where the spend is going. Identify repeated, background, or unexpectedly expensive work, cite the strongest evidence, and suggest concrete fixes. Call out missing attribution instead of guessing.\",\n context: [\n `Dispatch usage scope: ${metrics.viewScope === \"workspace\" ? \"workspace\" : \"my account\"}.`,\n `Lookback: ${metrics.sinceDays} days. Viewer: ${metrics.access.viewerEmail}.`,\n `Total: ${formatSpend(metrics.totals.costCents, billing)}, ${metrics.totals.calls} calls, ${metrics.totals.chatCalls} chat calls, ${formatTokens(metrics.totals.inputTokens + metrics.totals.outputTokens)} input/output tokens.`,\n `Top apps: ${topApps || \"none\"}.`,\n `Top work types: ${topLabels || \"none\"}.`,\n `Recent prompt evidence (bounded to the latest 8 rows):\\n${recentPrompts || \"none\"}`,\n ].join(\"\\n\"),\n submit: true,\n openSidebar: true,\n chatTarget: \"local\",\n });\n }\n\n return (\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={reviewUsage}>\n Ask agent\n </Button>\n );\n}\n\nfunction AppSpendRows({\n rows,\n billing,\n}: {\n rows: UsageMetricBucket[];\n billing: UsageBillingMode;\n}) {\n const max = maxSpend(rows, billing);\n if (rows.length === 0) {\n return (\n <div className=\"rounded-lg border border-dashed px-4 py-8 text-sm text-muted-foreground\">\n No LLM usage recorded for this window.\n </div>\n );\n }\n return (\n <div className=\"space-y-3\">\n {rows.map((row) => (\n <div key={row.key} className=\"space-y-1.5\">\n <div className=\"flex items-center justify-between gap-3 text-sm\">\n <div className=\"min-w-0\">\n <div className=\"truncate font-medium text-foreground\">\n {displayApp(row.key)}\n </div>\n <div className=\"text-xs text-muted-foreground\">\n {formatNumber(row.chatCalls)} chats ·{\" \"}\n {formatNumber(row.activeUsers)} users\n </div>\n </div>\n <div className=\"shrink-0 text-right\">\n <div className=\"font-medium tabular-nums text-foreground\">\n {formatSpend(row.costCents, billing)}\n </div>\n <div className=\"text-xs text-muted-foreground\">\n {formatNumber(row.calls)} calls\n </div>\n </div>\n </div>\n <div className=\"h-2 overflow-hidden rounded-full bg-muted\">\n <div\n className=\"h-full rounded-full bg-foreground\"\n style={{\n width: barWidth(\n displayAmountFromCostCents(row.costCents, billing),\n max,\n ),\n }}\n />\n </div>\n </div>\n ))}\n </div>\n );\n}\n\nfunction AppAccessTable({\n rows,\n billing,\n}: {\n rows: AppAccessMetric[];\n billing: UsageBillingMode;\n}) {\n const visibleRows = rows.filter((row) => !row.isDispatch);\n if (visibleRows.length === 0) {\n return (\n <div className=\"rounded-lg border border-dashed px-4 py-8 text-sm text-muted-foreground\">\n No workspace apps discovered yet.\n </div>\n );\n }\n return (\n <div className=\"overflow-x-auto\">\n <table className=\"w-full min-w-[720px] text-left text-xs\">\n <thead>\n <tr className=\"border-b text-muted-foreground\">\n <th className=\"px-2 py-2 font-medium\">App</th>\n <th className=\"px-2 py-2 font-medium\">Access</th>\n <th className=\"px-2 py-2 text-right font-medium\">Users</th>\n <th className=\"px-2 py-2 text-right font-medium\">Chats</th>\n <th className=\"px-2 py-2 text-right font-medium\">\n {billing.shortLabel}\n </th>\n <th className=\"px-2 py-2 text-right font-medium\">Last activity</th>\n </tr>\n </thead>\n <tbody>\n {visibleRows.map((row) => (\n <tr key={row.id} className=\"border-b last:border-0\">\n <td className=\"px-2 py-3\">\n <div className=\"font-medium text-foreground\">{row.name}</div>\n <div className=\"font-mono text-[11px] text-muted-foreground\">\n {row.path}\n </div>\n </td>\n <td className=\"px-2 py-3\">\n <Badge\n variant=\"outline\"\n className={cn(\n row.status === \"pending\" &&\n \"border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300\",\n )}\n >\n {row.status === \"pending\"\n ? row.statusLabel || \"Builder branch\"\n : row.accessLabel}\n </Badge>\n </td>\n <td className=\"px-2 py-3 text-right tabular-nums\">\n {formatNumber(row.usersWithUsage)} /{\" \"}\n {formatNumber(row.accessUsers)}\n </td>\n <td className=\"px-2 py-3 text-right tabular-nums\">\n {formatNumber(row.chatCalls)}\n </td>\n <td className=\"px-2 py-3 text-right tabular-nums\">\n {formatSpend(row.costCents, billing)}\n </td>\n <td className=\"px-2 py-3 text-right text-muted-foreground\">\n {timeAgo(row.lastActiveAt)}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\nfunction UserTable({\n rows,\n billing,\n}: {\n rows: UserUsageMetric[];\n billing: UsageBillingMode;\n}) {\n if (rows.length === 0) {\n return (\n <div className=\"rounded-lg border border-dashed px-4 py-8 text-sm text-muted-foreground\">\n No users have triggered LLM usage in this window.\n </div>\n );\n }\n return (\n <div className=\"overflow-x-auto\">\n <table className=\"w-full min-w-[760px] text-left text-xs\">\n <thead>\n <tr className=\"border-b text-muted-foreground\">\n <th className=\"px-2 py-2 font-medium\">User</th>\n <th className=\"px-2 py-2 font-medium\">Role</th>\n <th className=\"px-2 py-2 font-medium\">Top app</th>\n <th className=\"px-2 py-2 text-right font-medium\">Chats</th>\n <th className=\"px-2 py-2 text-right font-medium\">Threads</th>\n <th className=\"px-2 py-2 text-right font-medium\">Tokens</th>\n <th className=\"px-2 py-2 text-right font-medium\">\n {billing.shortLabel}\n </th>\n </tr>\n </thead>\n <tbody>\n {rows.slice(0, 12).map((row) => (\n <tr key={row.ownerEmail} className=\"border-b last:border-0\">\n <td className=\"max-w-64 px-2 py-3\">\n <div className=\"truncate font-medium text-foreground\">\n {row.ownerEmail}\n </div>\n <div className=\"text-muted-foreground\">\n {timeAgo(row.lastActiveAt ?? row.lastChatAt)}\n </div>\n </td>\n <td className=\"px-2 py-3\">\n <Badge variant=\"secondary\">{row.role ?? \"user\"}</Badge>\n </td>\n <td className=\"px-2 py-3 text-muted-foreground\">\n {displayApp(row.topApp)}\n </td>\n <td className=\"px-2 py-3 text-right tabular-nums\">\n {formatNumber(row.chatCalls)}\n </td>\n <td className=\"px-2 py-3 text-right tabular-nums\">\n {formatNumber(row.chatThreads)}\n </td>\n <td className=\"px-2 py-3 text-right tabular-nums\">\n {formatTokens(row.inputTokens + row.outputTokens)}\n </td>\n <td className=\"px-2 py-3 text-right tabular-nums\">\n {formatSpend(row.costCents, billing)}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\nfunction CompactBreakdown({\n rows,\n empty,\n billing,\n}: {\n rows: UsageMetricBucket[];\n empty: string;\n billing: UsageBillingMode;\n}) {\n const max = maxSpend(rows, billing);\n if (rows.length === 0) {\n return <div className=\"text-sm text-muted-foreground\">{empty}</div>;\n }\n return (\n <div className=\"space-y-3\">\n {rows.slice(0, 6).map((row) => (\n <div key={row.key} className=\"space-y-1\">\n <div className=\"flex items-center justify-between gap-3 text-xs\">\n <span className=\"truncate font-medium text-foreground\">\n {row.label}\n </span>\n <span className=\"shrink-0 tabular-nums text-muted-foreground\">\n {formatSpend(row.costCents, billing)}\n </span>\n </div>\n <div className=\"h-1.5 overflow-hidden rounded-full bg-muted\">\n <div\n className=\"h-full rounded-full bg-muted-foreground\"\n style={{\n width: barWidth(\n displayAmountFromCostCents(row.costCents, billing),\n max,\n ),\n }}\n />\n </div>\n </div>\n ))}\n </div>\n );\n}\n\nfunction RecentTable({\n rows,\n billing,\n}: {\n rows: RecentUsageMetric[];\n billing: UsageBillingMode;\n}) {\n if (rows.length === 0) {\n return (\n <div className=\"rounded-lg border border-dashed px-4 py-8 text-sm text-muted-foreground\">\n No prompts or LLM calls in this window.\n </div>\n );\n }\n return (\n <div className=\"divide-y\">\n {rows.slice(0, 10).map((row) => (\n <article key={row.id} className=\"-mx-1 px-1 py-3 first:pt-0 last:pb-0\">\n <div className=\"flex items-start justify-between gap-4\">\n <p className=\"min-w-0 whitespace-pre-wrap text-sm leading-6 text-foreground\">\n {row.prompt ||\n (row.promptSource === \"unavailable\"\n ? \"Prompt unavailable - linked thread data could not be read.\"\n : \"Prompt not captured for this call.\")}\n </p>\n <span className=\"shrink-0 text-xs text-muted-foreground\">\n {timeAgo(row.createdAt)}\n </span>\n </div>\n <div className=\"mt-2 flex flex-wrap items-center gap-1.5 text-xs text-muted-foreground\">\n <Badge variant=\"outline\">{displayApp(row.app)}</Badge>\n <Badge variant=\"secondary\">{row.label}</Badge>\n <span>{row.model}</span>\n <span aria-hidden=\"true\">·</span>\n <span>{formatSpend(row.costCents, billing)}</span>\n {row.ownerEmail ? (\n <>\n <span aria-hidden=\"true\">·</span>\n <span className=\"max-w-64 truncate\">{row.ownerEmail}</span>\n </>\n ) : null}\n {row.threadId ? (\n <Link\n to={`/admin/thread-debug?threadId=${encodeURIComponent(row.threadId)}`}\n className=\"inline-flex items-center gap-1 rounded-md border px-2 py-0.5 font-medium text-foreground transition-colors hover:bg-muted\"\n >\n Inspect thread\n <IconArrowUpRight size={12} />\n </Link>\n ) : null}\n </div>\n </article>\n ))}\n </div>\n );\n}\n\nexport default function MetricsRoute() {\n const t = useT();\n const [sinceDays, setSinceDays] = useState(30);\n const [searchParams, setSearchParams] = useSearchParams();\n const scope: \"me\" | \"workspace\" =\n searchParams.get(\"scope\") === \"workspace\" ? \"workspace\" : \"me\";\n const userEmail =\n scope === \"workspace\" ? searchParams.get(\"user\") || null : null;\n\n function setScope(nextScope: \"me\" | \"workspace\") {\n const next = new URLSearchParams(searchParams);\n if (nextScope === \"me\") next.delete(\"scope\");\n else next.set(\"scope\", nextScope);\n if (nextScope === \"me\") next.delete(\"user\");\n setSearchParams(next, { replace: true });\n }\n\n function setUserEmail(nextUserEmail: string | null) {\n const next = new URLSearchParams(searchParams);\n if (nextUserEmail) next.set(\"user\", nextUserEmail);\n else next.delete(\"user\");\n setSearchParams(next, { replace: true });\n }\n\n const { data, isLoading, error } = useActionQuery(\n \"list-dispatch-usage-metrics\",\n { sinceDays, scope, userEmail: userEmail ?? undefined },\n );\n const metrics = data as DispatchUsageMetrics | undefined;\n const billing = metrics?.billing ?? USD_BILLING;\n const totalTokens = useMemo(() => {\n if (!metrics) return 0;\n return (\n metrics.totals.inputTokens +\n metrics.totals.outputTokens +\n metrics.totals.cacheReadTokens +\n metrics.totals.cacheWriteTokens\n );\n }, [metrics]);\n\n return (\n <DispatchShell\n title={t(\"dispatch.nav.metrics\")}\n description={\n billing.unit === \"builder-credits\"\n ? t(\"dispatch.pages.metricsDescriptionBuilder\")\n : t(\"dispatch.pages.metricsDescriptionLlm\")\n }\n >\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div>\n <div className=\"text-sm font-medium text-foreground\">\n {metrics?.selectedUserEmail\n ? `${metrics.selectedUserEmail}'s usage`\n : scope === \"workspace\"\n ? \"Workspace usage\"\n : \"Your usage\"}\n </div>\n <div className=\"mt-0.5 text-xs text-muted-foreground\">\n {metrics?.selectedUserEmail\n ? \"Filtered to this workspace member\"\n : scope === \"workspace\"\n ? `${metrics?.access.totalUsers ?? 0} users with access`\n : metrics?.access.viewerEmail || \"Signed-in account\"}\n </div>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <ScopeSelector value={scope} onChange={setScope} />\n {scope === \"workspace\" && metrics ? (\n <UserSelector\n value={metrics.selectedUserEmail ?? userEmail}\n users={metrics.availableUsers ?? []}\n onChange={setUserEmail}\n />\n ) : null}\n <RangeSelector value={sinceDays} onChange={setSinceDays} />\n </div>\n </div>\n\n {error ? (\n <Alert variant=\"destructive\">\n <IconAlertTriangle className=\"h-4 w-4\" />\n <AlertTitle>{t(\"dispatch.pages.metricsUnavailable\")}</AlertTitle>\n <AlertDescription>\n {error instanceof Error\n ? error.message\n : t(\"dispatch.pages.unableToLoadUsage\")}\n </AlertDescription>\n </Alert>\n ) : null}\n\n {isLoading && !metrics ? <LoadingMetrics /> : null}\n\n {metrics ? (\n <>\n <UsageTrend rows={metrics.daily} billing={billing} />\n\n <div className=\"flex items-center justify-between gap-3 border-y py-3\">\n <span className=\"text-sm text-muted-foreground\">\n Review this usage with the agent\n </span>\n <ReviewUsageButton metrics={metrics} billing={billing} />\n </div>\n\n <UsageAlertsPanel\n scope={scope === \"workspace\" ? \"workspace\" : \"user\"}\n appOptions={metrics.byApp\n .filter((row) => row.key && row.key !== \"unattributed\")\n .map((row) => ({ id: row.key, label: displayApp(row.key) }))}\n />\n\n <div className=\"grid gap-3 md:grid-cols-2 xl:grid-cols-5\">\n <MetricCard\n label={billing.label}\n value={formatSpend(metrics.totals.costCents, billing)}\n detail={`${formatTokens(totalTokens)} total tokens`}\n icon={<IconCoin size={17} />}\n />\n <MetricCard\n label={t(\"dispatch.pages.llmCalls\")}\n value={formatNumber(metrics.totals.calls)}\n detail={`${formatNumber(metrics.totals.chatCalls)} chat turns`}\n icon={<IconActivity size={17} />}\n />\n <MetricCard\n label={t(\"dispatch.pages.activeUsers\")}\n value={formatNumber(metrics.totals.activeUsers)}\n detail={`${formatNumber(metrics.access.totalUsers)} users with access`}\n icon={<IconUsersGroup size={17} />}\n />\n <MetricCard\n label={t(\"dispatch.pages.workspaceAppsStat\")}\n value={formatNumber(metrics.totals.workspaceApps)}\n detail={`${formatNumber(metrics.byApp.length)} with usage`}\n icon={<IconApps size={17} />}\n />\n <MetricCard\n label={t(\"dispatch.pages.chatThreads\")}\n value={formatNumber(metrics.totals.chatThreads)}\n detail={`${formatNumber(metrics.totals.chatMessages)} messages`}\n icon={<IconMessages size={17} />}\n />\n </div>\n\n <Panel\n title={\n billing.unit === \"builder-credits\"\n ? \"Credit spend by app\"\n : \"Spend by app\"\n }\n icon={<IconApps size={16} />}\n >\n <AppSpendRows rows={metrics.byApp} billing={billing} />\n </Panel>\n\n <Panel\n title=\"Recent prompts\"\n icon={<IconMessages size={16} />}\n action={\n <span className=\"text-xs text-muted-foreground\">\n Latest {Math.min(metrics.recent.length, 10)} of{\" \"}\n {metrics.recent.length}\n </span>\n }\n >\n <RecentTable rows={metrics.recent} billing={billing} />\n </Panel>\n\n <Panel title=\"Access By App\" icon={<IconApps size={16} />}>\n <AppAccessTable rows={metrics.appAccess} billing={billing} />\n </Panel>\n\n <Panel title=\"Users\" icon={<IconUsersGroup size={16} />}>\n <UserTable rows={metrics.byUser} billing={billing} />\n </Panel>\n\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <Panel title=\"Models\" icon={<IconChartBar size={16} />}>\n <CompactBreakdown\n rows={metrics.byModel}\n empty=\"No model usage in this window.\"\n billing={billing}\n />\n </Panel>\n <Panel title=\"Work Types\" icon={<IconActivity size={16} />}>\n <CompactBreakdown\n rows={metrics.byLabel}\n empty=\"No labeled usage in this window.\"\n billing={billing}\n />\n </Panel>\n </div>\n </>\n ) : null}\n </div>\n </DispatchShell>\n );\n}\n"]}
@@ -48,6 +48,6 @@ export default function OperationsRoute() {
48
48
  return (_jsx(DispatchShell, { title: t("dispatch.nav.operations"), children: _jsxs(Tabs, { value: view, onValueChange: (value) => {
49
49
  if (value === "monitoring" || value === "database")
50
50
  setView(value);
51
- }, className: "flex min-w-0 flex-col gap-5", children: [_jsxs(TabsList, { className: "w-fit", children: [_jsxs(TabsTrigger, { value: "monitoring", children: [_jsx(IconActivity, { size: 15 }), t("dispatch.pages.monitoring")] }), _jsxs(TabsTrigger, { value: "database", children: [_jsx(IconDatabase, { size: 15 }), t("dispatch.pages.database")] })] }), _jsxs(TabsContent, { value: "monitoring", className: "mt-0 min-w-0", children: [_jsx(ObservabilityDashboard, {}), _jsx("div", { className: "mt-8", children: _jsx(OperationsShortcuts, {}) })] }), _jsx(TabsContent, { value: "database", className: "mt-0 min-w-0", children: _jsx("div", { className: "min-h-[620px] overflow-hidden rounded-lg border bg-background", children: _jsx(DbAdminPage, { title: t("dispatch.pages.database") }) }) })] }) }));
51
+ }, className: "flex min-w-0 flex-col gap-5", children: [_jsxs(TabsList, { className: "w-fit", children: [_jsxs(TabsTrigger, { value: "monitoring", children: [_jsx(IconActivity, { size: 15, className: "mr-1.5" }), t("dispatch.pages.monitoring")] }), _jsxs(TabsTrigger, { value: "database", children: [_jsx(IconDatabase, { size: 15, className: "mr-1.5" }), t("dispatch.pages.database")] })] }), _jsxs(TabsContent, { value: "monitoring", className: "mt-0 min-w-0", children: [_jsx(ObservabilityDashboard, {}), _jsx("div", { className: "mt-8", children: _jsx(OperationsShortcuts, {}) })] }), _jsx(TabsContent, { value: "database", className: "mt-0 min-w-0", children: _jsx("div", { className: "min-h-[620px] overflow-hidden rounded-lg border bg-background", children: _jsx(DbAdminPage, { title: t("dispatch.pages.database") }) }) })] }) }));
52
52
  }
53
53
  //# sourceMappingURL=operations.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"operations.js","sourceRoot":"","sources":["../../../src/routes/pages/operations.tsx"],"names":[],"mappings":"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","sourcesContent":["import { DbAdminPage } from \"@agent-native/core/client/db-admin\";\nimport { useT } from \"@agent-native/core/client/i18n\";\nimport { ObservabilityDashboard } from \"@agent-native/core/client/observability\";\nimport {\n IconActivity,\n IconArrowUpRight,\n IconDatabase,\n IconHistory,\n IconMessages,\n IconSend,\n} from \"@tabler/icons-react\";\nimport { Link, useSearchParams } from \"react-router\";\n\nimport { DispatchShell } from \"../../components/dispatch-shell\";\nimport {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"../../components/ui/tabs\";\n\ntype OperationsView = \"monitoring\" | \"database\";\n\nfunction selectedView(value: string | null): OperationsView {\n return value === \"database\" ? \"database\" : \"monitoring\";\n}\n\nfunction OperationsShortcuts() {\n const t = useT();\n\n const tools = [\n {\n to: \"/admin/thread-debug\",\n icon: IconMessages,\n title: t(\"dispatch.nav.threadDebug\", { defaultValue: \"Thread debug\" }),\n },\n {\n to: \"/admin/audit\",\n icon: IconHistory,\n title: t(\"dispatch.nav.audit\"),\n },\n {\n to: \"/admin/destinations\",\n icon: IconSend,\n title: t(\"dispatch.pages.deliveryQueue\"),\n },\n ];\n\n return (\n <section className=\"border-t pt-5\">\n <h2 className=\"text-sm font-semibold text-foreground\">\n {t(\"dispatch.nav.advanced\", { defaultValue: \"Related tools\" })}\n </h2>\n <div className=\"mt-2 grid gap-x-6 gap-y-1 lg:grid-cols-3\">\n {tools.map(({ to, icon: Icon, title }) => (\n <Link\n key={to}\n to={to}\n className=\"group flex min-w-0 items-start gap-2 rounded-md px-2 py-2 text-sm transition-colors hover:bg-muted\"\n >\n <Icon\n size={16}\n className=\"mt-0.5 shrink-0 text-muted-foreground transition-colors group-hover:text-foreground\"\n />\n <span className=\"min-w-0\">\n <span className=\"flex items-center gap-1 font-medium text-foreground\">\n <span className=\"truncate\">{title}</span>\n <IconArrowUpRight\n size={13}\n className=\"shrink-0 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100\"\n />\n </span>\n </span>\n </Link>\n ))}\n </div>\n </section>\n );\n}\n\nexport function meta() {\n return [{ title: \"Operations — Dispatch\" }];\n}\n\nexport default function OperationsRoute() {\n const t = useT();\n const [searchParams, setSearchParams] = useSearchParams();\n const view = selectedView(searchParams.get(\"view\"));\n\n function setView(nextView: OperationsView) {\n const next = new URLSearchParams(searchParams);\n if (nextView === \"monitoring\") next.delete(\"view\");\n else next.set(\"view\", nextView);\n setSearchParams(next, { replace: true });\n }\n\n return (\n <DispatchShell title={t(\"dispatch.nav.operations\")}>\n <Tabs\n value={view}\n onValueChange={(value) => {\n if (value === \"monitoring\" || value === \"database\") setView(value);\n }}\n className=\"flex min-w-0 flex-col gap-5\"\n >\n <TabsList className=\"w-fit\">\n <TabsTrigger value=\"monitoring\">\n <IconActivity size={15} />\n {t(\"dispatch.pages.monitoring\")}\n </TabsTrigger>\n <TabsTrigger value=\"database\">\n <IconDatabase size={15} />\n {t(\"dispatch.pages.database\")}\n </TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"monitoring\" className=\"mt-0 min-w-0\">\n <ObservabilityDashboard />\n <div className=\"mt-8\">\n <OperationsShortcuts />\n </div>\n </TabsContent>\n\n <TabsContent value=\"database\" className=\"mt-0 min-w-0\">\n <div className=\"min-h-[620px] overflow-hidden rounded-lg border bg-background\">\n <DbAdminPage title={t(\"dispatch.pages.database\")} />\n </div>\n </TabsContent>\n </Tabs>\n </DispatchShell>\n );\n}\n"]}
1
+ {"version":3,"file":"operations.js","sourceRoot":"","sources":["../../../src/routes/pages/operations.tsx"],"names":[],"mappings":"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","sourcesContent":["import { DbAdminPage } from \"@agent-native/core/client/db-admin\";\nimport { useT } from \"@agent-native/core/client/i18n\";\nimport { ObservabilityDashboard } from \"@agent-native/core/client/observability\";\nimport {\n IconActivity,\n IconArrowUpRight,\n IconDatabase,\n IconHistory,\n IconMessages,\n IconSend,\n} from \"@tabler/icons-react\";\nimport { Link, useSearchParams } from \"react-router\";\n\nimport { DispatchShell } from \"../../components/dispatch-shell\";\nimport {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"../../components/ui/tabs\";\n\ntype OperationsView = \"monitoring\" | \"database\";\n\nfunction selectedView(value: string | null): OperationsView {\n return value === \"database\" ? \"database\" : \"monitoring\";\n}\n\nfunction OperationsShortcuts() {\n const t = useT();\n\n const tools = [\n {\n to: \"/admin/thread-debug\",\n icon: IconMessages,\n title: t(\"dispatch.nav.threadDebug\", { defaultValue: \"Thread debug\" }),\n },\n {\n to: \"/admin/audit\",\n icon: IconHistory,\n title: t(\"dispatch.nav.audit\"),\n },\n {\n to: \"/admin/destinations\",\n icon: IconSend,\n title: t(\"dispatch.pages.deliveryQueue\"),\n },\n ];\n\n return (\n <section className=\"border-t pt-5\">\n <h2 className=\"text-sm font-semibold text-foreground\">\n {t(\"dispatch.nav.advanced\", { defaultValue: \"Related tools\" })}\n </h2>\n <div className=\"mt-2 grid gap-x-6 gap-y-1 lg:grid-cols-3\">\n {tools.map(({ to, icon: Icon, title }) => (\n <Link\n key={to}\n to={to}\n className=\"group flex min-w-0 items-start gap-2 rounded-md px-2 py-2 text-sm transition-colors hover:bg-muted\"\n >\n <Icon\n size={16}\n className=\"mt-0.5 shrink-0 text-muted-foreground transition-colors group-hover:text-foreground\"\n />\n <span className=\"min-w-0\">\n <span className=\"flex items-center gap-1 font-medium text-foreground\">\n <span className=\"truncate\">{title}</span>\n <IconArrowUpRight\n size={13}\n className=\"shrink-0 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100\"\n />\n </span>\n </span>\n </Link>\n ))}\n </div>\n </section>\n );\n}\n\nexport function meta() {\n return [{ title: \"Operations — Dispatch\" }];\n}\n\nexport default function OperationsRoute() {\n const t = useT();\n const [searchParams, setSearchParams] = useSearchParams();\n const view = selectedView(searchParams.get(\"view\"));\n\n function setView(nextView: OperationsView) {\n const next = new URLSearchParams(searchParams);\n if (nextView === \"monitoring\") next.delete(\"view\");\n else next.set(\"view\", nextView);\n setSearchParams(next, { replace: true });\n }\n\n return (\n <DispatchShell title={t(\"dispatch.nav.operations\")}>\n <Tabs\n value={view}\n onValueChange={(value) => {\n if (value === \"monitoring\" || value === \"database\") setView(value);\n }}\n className=\"flex min-w-0 flex-col gap-5\"\n >\n <TabsList className=\"w-fit\">\n <TabsTrigger value=\"monitoring\">\n <IconActivity size={15} className=\"mr-1.5\" />\n {t(\"dispatch.pages.monitoring\")}\n </TabsTrigger>\n <TabsTrigger value=\"database\">\n <IconDatabase size={15} className=\"mr-1.5\" />\n {t(\"dispatch.pages.database\")}\n </TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"monitoring\" className=\"mt-0 min-w-0\">\n <ObservabilityDashboard />\n <div className=\"mt-8\">\n <OperationsShortcuts />\n </div>\n </TabsContent>\n\n <TabsContent value=\"database\" className=\"mt-0 min-w-0\">\n <div className=\"min-h-[620px] overflow-hidden rounded-lg border bg-background\">\n <DbAdminPage title={t(\"dispatch.pages.database\")} />\n </div>\n </TabsContent>\n </Tabs>\n </DispatchShell>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/settings.tsx"],"names":[],"mappings":"AA6BA,wBAAgB,IAAI;;IAEnB;AAED,MAAM,CAAC,OAAO,UAAU,aAAa,oDA6JpC"}
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/settings.tsx"],"names":[],"mappings":"AA8BA,wBAAgB,IAAI;;IAEnB;AAED,MAAM,CAAC,OAAO,UAAU,aAAa,oDAiKpC"}
@@ -13,12 +13,17 @@ import { Button } from "../../components/ui/button.js";
13
13
  import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "../../components/ui/card.js";
14
14
  import { Label } from "../../components/ui/label.js";
15
15
  import { Switch } from "../../components/ui/switch.js";
16
+ import { dispatchAccessDescriptor } from "../../shared/app-roles.js";
16
17
  export function meta() {
17
18
  return [{ title: "Settings - Dispatch" }];
18
19
  }
19
20
  export default function SettingsRoute() {
20
21
  const t = useT();
21
- const agentSettingsTabs = useAgentSettingsTabs();
22
+ const agentSettingsTabs = useAgentSettingsTabs({
23
+ usageAppId: "dispatch",
24
+ usageViewAllHref: "/admin/metrics",
25
+ organizationContent: (_jsx("div", { className: "mx-auto w-full max-w-3xl", children: _jsx(TeamPage, { showTitle: false, appRoles: dispatchAccessDescriptor, createOrgDescription: "Set up a team to share dispatch destinations and approvals with your colleagues." }) })),
26
+ });
22
27
  const settingsTabs = [
23
28
  ...agentSettingsTabs.filter((tab) => tab.id !== "integrations"),
24
29
  {
@@ -47,6 +52,6 @@ export default function SettingsRoute() {
47
52
  detail: { enabled },
48
53
  }));
49
54
  }
50
- return (_jsx(DispatchShell, { title: t("settings.title"), description: t("settings.description"), children: _jsx(SettingsTabsPage, { extraTabs: settingsTabs, general: _jsxs("div", { className: "mx-auto w-full max-w-3xl space-y-6", children: [_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { className: "text-base", children: t("settings.languageTitle") }), _jsx(CardDescription, { children: t("settings.languageDescription") })] }), _jsxs(CardContent, { className: "max-w-xs space-y-1.5", children: [_jsx(Label, { children: t("settings.languageLabel") }), _jsx(LanguagePicker, { label: t("settings.languageLabel") })] })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { className: "text-base", children: "Chat-first workspace" }), _jsx(CardDescription, { children: "Keep chats at the center and open workspace apps in a contextual pane beside them." })] }), _jsxs(CardContent, { className: "flex items-center justify-between gap-4", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "dispatch-chat-first-mode", children: "Use chat-first navigation" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "This preference only changes your local Dispatch shell." }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Session watch and follow-up messaging work in this browser pane too. Local CLI subscription detection stays in the Electron app; Dispatch uses workspace/provider credentials." })] }), _jsx(Switch, { id: "dispatch-chat-first-mode", checked: chatFirstMode, onCheckedChange: updateChatFirstMode })] }), chatFirstStorageNotice ? (_jsx("p", { className: "px-6 pb-4 text-sm text-destructive", role: "alert", children: chatFirstStorageNotice })) : null] }), _jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { className: "text-base", children: t("settings.workspaceTitle") }), _jsx(CardDescription, { children: t("settings.workspaceDescription") })] }), _jsx(CardContent, { children: _jsx(Button, { variant: "outline", asChild: true, children: _jsx(Link, { to: "/admin/workspace", children: t("settings.openResourceSettings") }) }) })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { className: "text-base", children: t("settings.deliveryTitle") }), _jsx(CardDescription, { children: t("settings.deliveryDescription") })] }), _jsx(CardContent, { children: _jsx(Button, { variant: "outline", asChild: true, children: _jsx(Link, { to: "/admin/destinations", children: t("settings.openDelivery") }) }) })] })] }), team: _jsx("div", { className: "mx-auto w-full max-w-3xl", children: _jsx(TeamPage, { showTitle: false, createOrgDescription: "Set up a team to share dispatch destinations and approvals with your colleagues." }) }), whatsNew: _jsx("div", { className: "mx-auto w-full max-w-3xl", children: _jsx(ChangelogSettingsCard, { markdown: changelog }) }) }) }));
55
+ return (_jsx(DispatchShell, { title: t("settings.title"), description: t("settings.description"), children: _jsx(SettingsTabsPage, { extraTabs: settingsTabs, general: _jsxs("div", { className: "mx-auto w-full max-w-3xl space-y-6", children: [_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { className: "text-base", children: t("settings.languageTitle") }), _jsx(CardDescription, { children: t("settings.languageDescription") })] }), _jsxs(CardContent, { className: "max-w-xs space-y-1.5", children: [_jsx(Label, { children: t("settings.languageLabel") }), _jsx(LanguagePicker, { label: t("settings.languageLabel") })] })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { className: "text-base", children: "Chat-first workspace" }), _jsx(CardDescription, { children: "Keep chats at the center and open workspace apps in a contextual pane beside them." })] }), _jsxs(CardContent, { className: "flex items-center justify-between gap-4", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "dispatch-chat-first-mode", children: "Use chat-first navigation" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "This preference only changes your local Dispatch shell." }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Session watch and follow-up messaging work in this browser pane too. Local CLI subscription detection stays in the Electron app; Dispatch uses workspace/provider credentials." })] }), _jsx(Switch, { id: "dispatch-chat-first-mode", checked: chatFirstMode, onCheckedChange: updateChatFirstMode })] }), chatFirstStorageNotice ? (_jsx("p", { className: "px-6 pb-4 text-sm text-destructive", role: "alert", children: chatFirstStorageNotice })) : null] }), _jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { className: "text-base", children: t("settings.workspaceTitle") }), _jsx(CardDescription, { children: t("settings.workspaceDescription") })] }), _jsx(CardContent, { children: _jsx(Button, { variant: "outline", asChild: true, children: _jsx(Link, { to: "/admin/workspace", children: t("settings.openResourceSettings") }) }) })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { className: "text-base", children: t("settings.deliveryTitle") }), _jsx(CardDescription, { children: t("settings.deliveryDescription") })] }), _jsx(CardContent, { children: _jsx(Button, { variant: "outline", asChild: true, children: _jsx(Link, { to: "/admin/destinations", children: t("settings.openDelivery") }) }) })] })] }), whatsNew: _jsx("div", { className: "mx-auto w-full max-w-3xl", children: _jsx(ChangelogSettingsCard, { markdown: changelog }) }) }) }));
51
56
  }
52
57
  //# sourceMappingURL=settings.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../src/routes/pages/settings.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n CHAT_FIRST_MODE_CHANGED_EVENT,\n readChatFirstModeState,\n writeChatFirstMode,\n} from \"@agent-native/core/client/agent-chat\";\nimport { ChangelogSettingsCard } from \"@agent-native/core/client/changelog\";\nimport { LanguagePicker, useT } from \"@agent-native/core/client/i18n\";\nimport { TeamPage } from \"@agent-native/core/client/org\";\nimport {\n SettingsTabsPage,\n useAgentSettingsTabs,\n} from \"@agent-native/core/client/settings\";\nimport { IconShield } from \"@tabler/icons-react\";\nimport { useState } from \"react\";\nimport { Link } from \"react-router\";\n\nimport changelog from \"../../../CHANGELOG.md?raw\";\nimport { DispatchShell } from \"../../components/dispatch-shell\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"../../components/ui/card\";\nimport { Label } from \"../../components/ui/label\";\nimport { Switch } from \"../../components/ui/switch\";\n\nexport function meta() {\n return [{ title: \"Settings - Dispatch\" }];\n}\n\nexport default function SettingsRoute() {\n const t = useT();\n const agentSettingsTabs = useAgentSettingsTabs();\n const settingsTabs = [\n ...agentSettingsTabs.filter((tab) => tab.id !== \"integrations\"),\n {\n id: \"admin\",\n label: t(\"dispatch.nav.admin\", { defaultValue: \"Admin\" }),\n icon: IconShield,\n group: \"Admin\",\n href: \"/admin\",\n content: null,\n },\n ];\n const [chatFirstModeState] = useState(() => readChatFirstModeState());\n const [chatFirstMode, setChatFirstMode] = useState(\n () => chatFirstModeState.enabled,\n );\n const [chatFirstStorageNotice, setChatFirstStorageNotice] = useState<\n string | null\n >(\n chatFirstModeState.availability === \"unavailable\"\n ? \"This browser is not allowing local preferences, so Chat-first mode cannot be persisted.\"\n : null,\n );\n\n function updateChatFirstMode(enabled: boolean) {\n const result = writeChatFirstMode(enabled);\n if (!result.ok) {\n setChatFirstStorageNotice(\n \"This browser blocked local preferences, so Chat-first mode was not changed.\",\n );\n return;\n }\n setChatFirstStorageNotice(null);\n setChatFirstMode(enabled);\n window.dispatchEvent(\n new CustomEvent(CHAT_FIRST_MODE_CHANGED_EVENT, {\n detail: { enabled },\n }),\n );\n }\n\n return (\n <DispatchShell\n title={t(\"settings.title\")}\n description={t(\"settings.description\")}\n >\n <SettingsTabsPage\n extraTabs={settingsTabs}\n general={\n <div className=\"mx-auto w-full max-w-3xl space-y-6\">\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">\n {t(\"settings.languageTitle\")}\n </CardTitle>\n <CardDescription>\n {t(\"settings.languageDescription\")}\n </CardDescription>\n </CardHeader>\n <CardContent className=\"max-w-xs space-y-1.5\">\n <Label>{t(\"settings.languageLabel\")}</Label>\n <LanguagePicker label={t(\"settings.languageLabel\")} />\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">\n Chat-first workspace\n </CardTitle>\n <CardDescription>\n Keep chats at the center and open workspace apps in a\n contextual pane beside them.\n </CardDescription>\n </CardHeader>\n <CardContent className=\"flex items-center justify-between gap-4\">\n <div className=\"space-y-1\">\n <Label htmlFor=\"dispatch-chat-first-mode\">\n Use chat-first navigation\n </Label>\n <p className=\"text-sm text-muted-foreground\">\n This preference only changes your local Dispatch shell.\n </p>\n <p className=\"text-sm text-muted-foreground\">\n Session watch and follow-up messaging work in this browser\n pane too. Local CLI subscription detection stays in the\n Electron app; Dispatch uses workspace/provider credentials.\n </p>\n </div>\n <Switch\n id=\"dispatch-chat-first-mode\"\n checked={chatFirstMode}\n onCheckedChange={updateChatFirstMode}\n />\n </CardContent>\n {chatFirstStorageNotice ? (\n <p className=\"px-6 pb-4 text-sm text-destructive\" role=\"alert\">\n {chatFirstStorageNotice}\n </p>\n ) : null}\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">\n {t(\"settings.workspaceTitle\")}\n </CardTitle>\n <CardDescription>\n {t(\"settings.workspaceDescription\")}\n </CardDescription>\n </CardHeader>\n <CardContent>\n <Button variant=\"outline\" asChild>\n <Link to=\"/admin/workspace\">\n {t(\"settings.openResourceSettings\")}\n </Link>\n </Button>\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">\n {t(\"settings.deliveryTitle\")}\n </CardTitle>\n <CardDescription>\n {t(\"settings.deliveryDescription\")}\n </CardDescription>\n </CardHeader>\n <CardContent>\n <Button variant=\"outline\" asChild>\n <Link to=\"/admin/destinations\">\n {t(\"settings.openDelivery\")}\n </Link>\n </Button>\n </CardContent>\n </Card>\n </div>\n }\n team={\n <div className=\"mx-auto w-full max-w-3xl\">\n <TeamPage\n showTitle={false}\n createOrgDescription=\"Set up a team to share dispatch destinations and approvals with your colleagues.\"\n />\n </div>\n }\n whatsNew={\n <div className=\"mx-auto w-full max-w-3xl\">\n <ChangelogSettingsCard markdown={changelog} />\n </div>\n }\n />\n </DispatchShell>\n );\n}\n"]}
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../src/routes/pages/settings.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n CHAT_FIRST_MODE_CHANGED_EVENT,\n readChatFirstModeState,\n writeChatFirstMode,\n} from \"@agent-native/core/client/agent-chat\";\nimport { ChangelogSettingsCard } from \"@agent-native/core/client/changelog\";\nimport { LanguagePicker, useT } from \"@agent-native/core/client/i18n\";\nimport { TeamPage } from \"@agent-native/core/client/org\";\nimport {\n SettingsTabsPage,\n useAgentSettingsTabs,\n} from \"@agent-native/core/client/settings\";\nimport { IconShield } from \"@tabler/icons-react\";\nimport { useState } from \"react\";\nimport { Link } from \"react-router\";\n\nimport changelog from \"../../../CHANGELOG.md?raw\";\nimport { DispatchShell } from \"../../components/dispatch-shell\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n} from \"../../components/ui/card\";\nimport { Label } from \"../../components/ui/label\";\nimport { Switch } from \"../../components/ui/switch\";\nimport { dispatchAccessDescriptor } from \"../../shared/app-roles.js\";\n\nexport function meta() {\n return [{ title: \"Settings - Dispatch\" }];\n}\n\nexport default function SettingsRoute() {\n const t = useT();\n const agentSettingsTabs = useAgentSettingsTabs({\n usageAppId: \"dispatch\",\n usageViewAllHref: \"/admin/metrics\",\n organizationContent: (\n <div className=\"mx-auto w-full max-w-3xl\">\n <TeamPage\n showTitle={false}\n appRoles={dispatchAccessDescriptor}\n createOrgDescription=\"Set up a team to share dispatch destinations and approvals with your colleagues.\"\n />\n </div>\n ),\n });\n const settingsTabs = [\n ...agentSettingsTabs.filter((tab) => tab.id !== \"integrations\"),\n {\n id: \"admin\",\n label: t(\"dispatch.nav.admin\", { defaultValue: \"Admin\" }),\n icon: IconShield,\n group: \"Admin\",\n href: \"/admin\",\n content: null,\n },\n ];\n const [chatFirstModeState] = useState(() => readChatFirstModeState());\n const [chatFirstMode, setChatFirstMode] = useState(\n () => chatFirstModeState.enabled,\n );\n const [chatFirstStorageNotice, setChatFirstStorageNotice] = useState<\n string | null\n >(\n chatFirstModeState.availability === \"unavailable\"\n ? \"This browser is not allowing local preferences, so Chat-first mode cannot be persisted.\"\n : null,\n );\n\n function updateChatFirstMode(enabled: boolean) {\n const result = writeChatFirstMode(enabled);\n if (!result.ok) {\n setChatFirstStorageNotice(\n \"This browser blocked local preferences, so Chat-first mode was not changed.\",\n );\n return;\n }\n setChatFirstStorageNotice(null);\n setChatFirstMode(enabled);\n window.dispatchEvent(\n new CustomEvent(CHAT_FIRST_MODE_CHANGED_EVENT, {\n detail: { enabled },\n }),\n );\n }\n\n return (\n <DispatchShell\n title={t(\"settings.title\")}\n description={t(\"settings.description\")}\n >\n <SettingsTabsPage\n extraTabs={settingsTabs}\n general={\n <div className=\"mx-auto w-full max-w-3xl space-y-6\">\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">\n {t(\"settings.languageTitle\")}\n </CardTitle>\n <CardDescription>\n {t(\"settings.languageDescription\")}\n </CardDescription>\n </CardHeader>\n <CardContent className=\"max-w-xs space-y-1.5\">\n <Label>{t(\"settings.languageLabel\")}</Label>\n <LanguagePicker label={t(\"settings.languageLabel\")} />\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">\n Chat-first workspace\n </CardTitle>\n <CardDescription>\n Keep chats at the center and open workspace apps in a\n contextual pane beside them.\n </CardDescription>\n </CardHeader>\n <CardContent className=\"flex items-center justify-between gap-4\">\n <div className=\"space-y-1\">\n <Label htmlFor=\"dispatch-chat-first-mode\">\n Use chat-first navigation\n </Label>\n <p className=\"text-sm text-muted-foreground\">\n This preference only changes your local Dispatch shell.\n </p>\n <p className=\"text-sm text-muted-foreground\">\n Session watch and follow-up messaging work in this browser\n pane too. Local CLI subscription detection stays in the\n Electron app; Dispatch uses workspace/provider credentials.\n </p>\n </div>\n <Switch\n id=\"dispatch-chat-first-mode\"\n checked={chatFirstMode}\n onCheckedChange={updateChatFirstMode}\n />\n </CardContent>\n {chatFirstStorageNotice ? (\n <p className=\"px-6 pb-4 text-sm text-destructive\" role=\"alert\">\n {chatFirstStorageNotice}\n </p>\n ) : null}\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">\n {t(\"settings.workspaceTitle\")}\n </CardTitle>\n <CardDescription>\n {t(\"settings.workspaceDescription\")}\n </CardDescription>\n </CardHeader>\n <CardContent>\n <Button variant=\"outline\" asChild>\n <Link to=\"/admin/workspace\">\n {t(\"settings.openResourceSettings\")}\n </Link>\n </Button>\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">\n {t(\"settings.deliveryTitle\")}\n </CardTitle>\n <CardDescription>\n {t(\"settings.deliveryDescription\")}\n </CardDescription>\n </CardHeader>\n <CardContent>\n <Button variant=\"outline\" asChild>\n <Link to=\"/admin/destinations\">\n {t(\"settings.openDelivery\")}\n </Link>\n </Button>\n </CardContent>\n </Card>\n </div>\n }\n whatsNew={\n <div className=\"mx-auto w-full max-w-3xl\">\n <ChangelogSettingsCard markdown={changelog} />\n </div>\n }\n />\n </DispatchShell>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"thread-debug.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/thread-debug.tsx"],"names":[],"mappings":"AA2CA,wBAAgB,IAAI;;IAEnB;AAmqCD,MAAM,CAAC,OAAO,UAAU,gBAAgB,oDAosBvC"}
1
+ {"version":3,"file":"thread-debug.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/thread-debug.tsx"],"names":[],"mappings":"AA2CA,wBAAgB,IAAI;;IAEnB;AAiqCD,MAAM,CAAC,OAAO,UAAU,gBAAgB,oDAorBvC"}
@@ -262,7 +262,7 @@ function RawBlock({ value, className, }) {
262
262
  }
263
263
  function ResultCard({ result, selected, onSelect, }) {
264
264
  const title = displayListTitle(result.title, result.preview, "Untitled thread");
265
- return (_jsxs("button", { type: "button", onClick: onSelect, "aria-current": selected ? "true" : undefined, className: cn("group w-full border-b px-4 py-3 text-left transition-colors last:border-b-0", selected ? "bg-accent/70" : "hover:bg-muted/50"), children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsx("div", { className: "min-w-0", children: _jsx("div", { className: "truncate text-sm font-medium text-foreground", children: title }) }), _jsxs(Badge, { variant: "outline", className: "shrink-0", children: [result.messageCount, " ", result.messageCount === 1 ? "message" : "messages"] })] }), _jsxs("div", { className: "mt-2 flex items-center justify-between gap-3 text-[11px] text-muted-foreground", children: [_jsx("span", { className: "min-w-0 truncate", children: result.ownerEmail }), _jsx("span", { className: "shrink-0", children: formatRelativeDate(result.updatedAt) })] })] }));
265
+ return (_jsxs("button", { type: "button", onClick: onSelect, "aria-current": selected ? "true" : undefined, className: cn("group w-full border-b px-4 py-3 text-left transition-colors last:border-b-0", selected ? "bg-accent/70" : "hover:bg-muted/50"), children: [_jsx("div", { className: "truncate text-sm font-medium text-foreground", children: title }), _jsxs("div", { className: "mt-1 flex flex-wrap items-center gap-x-2 gap-y-1 text-[11px] text-muted-foreground", children: [_jsxs("span", { children: [result.messageCount, " ", result.messageCount === 1 ? "message" : "messages"] }), _jsx("span", { "aria-hidden": "true", children: "\u00B7" }), _jsx("span", { className: "min-w-0 truncate", children: result.ownerEmail }), _jsx("span", { "aria-hidden": "true", children: "\u00B7" }), _jsx("span", { children: formatRelativeDate(result.updatedAt) })] })] }));
266
266
  }
267
267
  function FailureCard({ failure, selected, onSelect, }) {
268
268
  const t = useT();
@@ -502,16 +502,13 @@ export default function ThreadDebugRoute() {
502
502
  defaultValue: "Last 7 days",
503
503
  }) }), _jsx(SelectItem, { value: "30d", children: t("dispatch.pages.threadDebugRange30d", {
504
504
  defaultValue: "Last 30 days",
505
- }) })] })] })] }), _jsxs("div", { className: "mt-3 flex flex-wrap items-center gap-2 text-xs text-muted-foreground", children: [_jsxs("span", { className: "font-medium text-foreground", children: [failures.length, " loaded", " ", failures.length === 1 ? "run" : "runs"] }), _jsx("span", { children: "\u00B7" }), _jsx("span", { children: failuresData?.access?.scope ??
506
- t("dispatch.pages.threadDebugCurrentScope", {
507
- defaultValue: "current scope",
508
- }) }), failurePatterns.slice(0, 3).map((pattern) => (_jsxs(Badge, { variant: "outline", children: [pattern.count, " ", pattern.label] }, pattern.label))), failuresData?.partial ? (_jsx(Badge, { variant: "outline", children: t("dispatch.pages.threadDebugPartialResults", {
509
- defaultValue: "Partial results",
510
- }) })) : null] }), unavailableFailureSources.length > 0 ? (_jsxs("div", { className: "mt-2 flex items-start gap-1.5 text-xs text-muted-foreground", children: [_jsx(IconAlertTriangle, { className: "mt-0.5 size-3.5 shrink-0" }), _jsxs("span", { children: [t("dispatch.pages.threadDebugUnavailableSources", {
505
+ }) })] })] })] }), unavailableFailureSources.length > 0 ? (_jsxs("div", { className: "mt-2 flex items-start gap-1.5 text-xs text-muted-foreground", children: [_jsx(IconAlertTriangle, { className: "mt-0.5 size-3.5 shrink-0" }), _jsxs("span", { children: [t("dispatch.pages.threadDebugUnavailableSources", {
511
506
  defaultValue: "Unavailable sources:",
512
507
  }), " ", unavailableFailureSources
513
508
  .map(({ source, status: sourceStatus }) => `${source.label} (${failureSourceStatusLabels[sourceStatus]})`)
514
- .join(", ")] })] })) : null] }), failuresError ? (_jsx(ActionQueryError, { error: failuresError, onRetry: () => void refetchFailures() })) : null, _jsx("div", { className: "overflow-hidden rounded-xl border bg-card", children: _jsxs("div", { className: "grid xl:grid-cols-[360px_minmax(0,1fr)]", children: [_jsxs("section", { className: "min-h-[560px] border-b xl:border-b-0 xl:border-r", children: [_jsxs("div", { className: "flex items-center justify-between border-b px-4 py-3", children: [_jsxs("div", { children: [_jsx("div", { className: "text-sm font-semibold text-foreground", children: "Needs attention" }), _jsx("div", { className: "mt-0.5 text-xs text-muted-foreground", children: failurePatterns[0]
509
+ .join(", ")] })] })) : null, failuresData?.partial ? (_jsx("div", { className: "mt-2", children: _jsx(Badge, { variant: "outline", children: t("dispatch.pages.threadDebugPartialResults", {
510
+ defaultValue: "Partial results",
511
+ }) }) })) : null] }), failuresError ? (_jsx(ActionQueryError, { error: failuresError, onRetry: () => void refetchFailures() })) : null, _jsx("div", { className: "overflow-hidden rounded-xl border bg-card", children: _jsxs("div", { className: "grid xl:grid-cols-[360px_minmax(0,1fr)]", children: [_jsxs("section", { className: "min-h-[560px] border-b xl:border-b-0 xl:border-r", children: [_jsxs("div", { className: "flex items-center justify-between border-b px-4 py-3", children: [_jsxs("div", { children: [_jsx("div", { className: "text-sm font-semibold text-foreground", children: "Needs attention" }), _jsx("div", { className: "mt-0.5 text-xs text-muted-foreground", children: failurePatterns[0]
515
512
  ? `${failurePatterns[0].count} ${failurePatterns[0].label.toLowerCase()}`
516
513
  : "No active failure pattern" })] }), _jsx("span", { className: "text-xs text-muted-foreground", children: failures.length })] }), _jsxs("div", { className: "max-h-[760px] overflow-auto", children: [failuresLoading ? (_jsxs(_Fragment, { children: [_jsx(Skeleton, { className: "mx-4 mt-4 h-16 w-[calc(100%-2rem)]" }), _jsx(Skeleton, { className: "mx-4 mt-2 h-16 w-[calc(100%-2rem)]" }), _jsx(Skeleton, { className: "mx-4 mt-2 h-16 w-[calc(100%-2rem)]" })] })) : null, !failuresLoading && failures.length === 0 ? (_jsxs("div", { className: "flex min-h-64 flex-col items-center justify-center px-4 text-center text-sm text-muted-foreground", children: [_jsx(IconDatabase, { className: "mb-2 size-5" }), t("dispatch.pages.threadDebugNoFailures", {
517
514
  defaultValue: "No failed runs found.",