@agent-native/dispatch 0.15.1 → 0.15.2

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 (154) hide show
  1. package/dist/components/action-query-error.js +1 -1
  2. package/dist/components/action-query-error.js.map +1 -1
  3. package/dist/components/agents-panel.js +1 -1
  4. package/dist/components/agents-panel.js.map +1 -1
  5. package/dist/components/app-keys-popover.d.ts.map +1 -1
  6. package/dist/components/app-keys-popover.js +1 -1
  7. package/dist/components/app-keys-popover.js.map +1 -1
  8. package/dist/components/create-app-popover.js +5 -1
  9. package/dist/components/create-app-popover.js.map +1 -1
  10. package/dist/components/dispatch-control-plane.js +5 -1
  11. package/dist/components/dispatch-control-plane.js.map +1 -1
  12. package/dist/components/dispatch-shell.js +1 -1
  13. package/dist/components/dispatch-shell.js.map +1 -1
  14. package/dist/components/layout/Header.d.ts.map +1 -1
  15. package/dist/components/layout/Header.js +2 -1
  16. package/dist/components/layout/Header.js.map +1 -1
  17. package/dist/components/layout/Layout.d.ts.map +1 -1
  18. package/dist/components/layout/Layout.js +5 -1
  19. package/dist/components/layout/Layout.js.map +1 -1
  20. package/dist/components/messaging-setup-panel.d.ts.map +1 -1
  21. package/dist/components/messaging-setup-panel.js +2 -1
  22. package/dist/components/messaging-setup-panel.js.map +1 -1
  23. package/dist/components/task-queue-health.d.ts.map +1 -1
  24. package/dist/components/task-queue-health.js +2 -1
  25. package/dist/components/task-queue-health.js.map +1 -1
  26. package/dist/components/workspace-app-card.d.ts.map +1 -1
  27. package/dist/components/workspace-app-card.js +1 -1
  28. package/dist/components/workspace-app-card.js.map +1 -1
  29. package/dist/components/workspace-resource-effective-stack.js +1 -1
  30. package/dist/components/workspace-resource-effective-stack.js.map +1 -1
  31. package/dist/components/workspace-resource-impact-preview.js +1 -1
  32. package/dist/components/workspace-resource-impact-preview.js.map +1 -1
  33. package/dist/components/workspace-template-card.js +1 -1
  34. package/dist/components/workspace-template-card.js.map +1 -1
  35. package/dist/hooks/use-navigation-state.d.ts.map +1 -1
  36. package/dist/hooks/use-navigation-state.js +2 -1
  37. package/dist/hooks/use-navigation-state.js.map +1 -1
  38. package/dist/lib/automations.js +1 -1
  39. package/dist/lib/automations.js.map +1 -1
  40. package/dist/lib/overview-chat.d.ts.map +1 -1
  41. package/dist/lib/overview-chat.js +2 -1
  42. package/dist/lib/overview-chat.js.map +1 -1
  43. package/dist/lib/task-queue.js +1 -1
  44. package/dist/lib/task-queue.js.map +1 -1
  45. package/dist/routes/pages/$appId.d.ts.map +1 -1
  46. package/dist/routes/pages/$appId.js +3 -1
  47. package/dist/routes/pages/$appId.js.map +1 -1
  48. package/dist/routes/pages/_index.js +1 -1
  49. package/dist/routes/pages/_index.js.map +1 -1
  50. package/dist/routes/pages/agents.js +2 -1
  51. package/dist/routes/pages/agents.js.map +1 -1
  52. package/dist/routes/pages/approval.d.ts.map +1 -1
  53. package/dist/routes/pages/approval.js +3 -1
  54. package/dist/routes/pages/approval.js.map +1 -1
  55. package/dist/routes/pages/approvals.d.ts.map +1 -1
  56. package/dist/routes/pages/approvals.js +1 -1
  57. package/dist/routes/pages/approvals.js.map +1 -1
  58. package/dist/routes/pages/apps.$appId.d.ts.map +1 -1
  59. package/dist/routes/pages/apps.$appId.js +2 -1
  60. package/dist/routes/pages/apps.$appId.js.map +1 -1
  61. package/dist/routes/pages/apps.d.ts.map +1 -1
  62. package/dist/routes/pages/apps.js +2 -1
  63. package/dist/routes/pages/apps.js.map +1 -1
  64. package/dist/routes/pages/audit.js +1 -1
  65. package/dist/routes/pages/audit.js.map +1 -1
  66. package/dist/routes/pages/automations.d.ts.map +1 -1
  67. package/dist/routes/pages/automations.js +3 -1
  68. package/dist/routes/pages/automations.js.map +1 -1
  69. package/dist/routes/pages/chat.d.ts.map +1 -1
  70. package/dist/routes/pages/chat.js +3 -1
  71. package/dist/routes/pages/chat.js.map +1 -1
  72. package/dist/routes/pages/destinations.js +2 -1
  73. package/dist/routes/pages/destinations.js.map +1 -1
  74. package/dist/routes/pages/dreams.d.ts.map +1 -1
  75. package/dist/routes/pages/dreams.js +1 -1
  76. package/dist/routes/pages/dreams.js.map +1 -1
  77. package/dist/routes/pages/identities.d.ts.map +1 -1
  78. package/dist/routes/pages/identities.js +1 -1
  79. package/dist/routes/pages/identities.js.map +1 -1
  80. package/dist/routes/pages/integrations.d.ts.map +1 -1
  81. package/dist/routes/pages/integrations.js +1 -1
  82. package/dist/routes/pages/integrations.js.map +1 -1
  83. package/dist/routes/pages/metrics.d.ts.map +1 -1
  84. package/dist/routes/pages/metrics.js +2 -1
  85. package/dist/routes/pages/metrics.js.map +1 -1
  86. package/dist/routes/pages/new-app.d.ts.map +1 -1
  87. package/dist/routes/pages/new-app.js +2 -1
  88. package/dist/routes/pages/new-app.js.map +1 -1
  89. package/dist/routes/pages/operations.d.ts.map +1 -1
  90. package/dist/routes/pages/operations.js +3 -1
  91. package/dist/routes/pages/operations.js.map +1 -1
  92. package/dist/routes/pages/settings.d.ts.map +1 -1
  93. package/dist/routes/pages/settings.js +3 -1
  94. package/dist/routes/pages/settings.js.map +1 -1
  95. package/dist/routes/pages/thread-debug.d.ts.map +1 -1
  96. package/dist/routes/pages/thread-debug.js +2 -1
  97. package/dist/routes/pages/thread-debug.js.map +1 -1
  98. package/dist/routes/pages/vault.d.ts.map +1 -1
  99. package/dist/routes/pages/vault.js +1 -1
  100. package/dist/routes/pages/vault.js.map +1 -1
  101. package/dist/routes/pages/workspace.d.ts.map +1 -1
  102. package/dist/routes/pages/workspace.js +1 -1
  103. package/dist/routes/pages/workspace.js.map +1 -1
  104. package/package.json +2 -2
  105. package/src/components/action-query-error.spec.tsx +1 -1
  106. package/src/components/action-query-error.tsx +1 -1
  107. package/src/components/agents-panel.tsx +1 -1
  108. package/src/components/app-keys-popover.spec.tsx +4 -1
  109. package/src/components/app-keys-popover.tsx +4 -1
  110. package/src/components/create-app-popover.tsx +5 -5
  111. package/src/components/dispatch-control-plane.spec.tsx +20 -8
  112. package/src/components/dispatch-control-plane.tsx +5 -5
  113. package/src/components/dispatch-shell.tsx +1 -1
  114. package/src/components/layout/Header.tsx +2 -1
  115. package/src/components/layout/Layout.spec.tsx +17 -8
  116. package/src/components/layout/Layout.tsx +5 -6
  117. package/src/components/messaging-setup-panel.spec.tsx +4 -1
  118. package/src/components/messaging-setup-panel.tsx +2 -3
  119. package/src/components/task-queue-health.tsx +2 -1
  120. package/src/components/workspace-app-card.spec.tsx +1 -1
  121. package/src/components/workspace-app-card.tsx +4 -1
  122. package/src/components/workspace-resource-effective-stack.spec.tsx +1 -1
  123. package/src/components/workspace-resource-effective-stack.tsx +1 -1
  124. package/src/components/workspace-resource-impact-preview.spec.tsx +1 -1
  125. package/src/components/workspace-resource-impact-preview.tsx +1 -1
  126. package/src/components/workspace-template-card.spec.tsx +1 -1
  127. package/src/components/workspace-template-card.tsx +1 -1
  128. package/src/hooks/use-navigation-state.ts +5 -3
  129. package/src/lib/automations.ts +1 -1
  130. package/src/lib/overview-chat.spec.ts +5 -2
  131. package/src/lib/overview-chat.ts +2 -1
  132. package/src/lib/task-queue.ts +1 -1
  133. package/src/routes/pages/$appId.tsx +3 -1
  134. package/src/routes/pages/_index.tsx +1 -1
  135. package/src/routes/pages/agents.tsx +2 -2
  136. package/src/routes/pages/approval.tsx +4 -2
  137. package/src/routes/pages/approvals.tsx +4 -1
  138. package/src/routes/pages/apps.$appId.tsx +2 -1
  139. package/src/routes/pages/apps.tsx +2 -1
  140. package/src/routes/pages/audit.tsx +1 -1
  141. package/src/routes/pages/automations.tsx +3 -5
  142. package/src/routes/pages/chat.spec.tsx +15 -4
  143. package/src/routes/pages/chat.tsx +3 -4
  144. package/src/routes/pages/destinations.tsx +2 -2
  145. package/src/routes/pages/dreams.tsx +4 -1
  146. package/src/routes/pages/identities.tsx +4 -1
  147. package/src/routes/pages/integrations.tsx +4 -1
  148. package/src/routes/pages/metrics.tsx +2 -1
  149. package/src/routes/pages/new-app.tsx +2 -1
  150. package/src/routes/pages/operations.tsx +3 -5
  151. package/src/routes/pages/settings.tsx +4 -5
  152. package/src/routes/pages/thread-debug.tsx +2 -1
  153. package/src/routes/pages/vault.tsx +4 -1
  154. package/src/routes/pages/workspace.tsx +4 -1
@@ -1 +1 @@
1
- {"version":3,"file":"identities.js","sourceRoot":"","sources":["../../../src/routes/pages/identities.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useActionMutation, useActionQuery } from \"@agent-native/core/client\";\nimport { toast } from \"sonner\";\n\nimport { ActionQueryError } from \"../../components/action-query-error\";\nimport { DispatchShell } from \"../../components/dispatch-shell\";\nimport { Button } from \"../../components/ui/button\";\n\nexport function meta() {\n return [{ title: \"Identities — Dispatch\" }];\n}\n\nexport default function IdentitiesRoute() {\n const query = useActionQuery(\"list-linked-identities\", {});\n const { data } = query;\n const createToken = useActionMutation(\"create-link-token\", {\n onSuccess: () => toast.success(\"Link token created\"),\n });\n\n return (\n <DispatchShell\n title=\"Identities\"\n description=\"Link external senders to workspace users.\"\n >\n {query.isError ? (\n <ActionQueryError\n error={query.error}\n onRetry={() => void query.refetch()}\n />\n ) : (\n <div className=\"grid gap-4 xl:grid-cols-2\">\n <section className=\"rounded-2xl border bg-card p-5\">\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <h2 className=\"text-lg font-semibold text-foreground\">\n Active links\n </h2>\n <div className=\"flex shrink-0 gap-2\">\n <Button\n variant=\"outline\"\n onClick={() => createToken.mutate({ platform: \"slack\" })}\n >\n New Slack token\n </Button>\n <Button\n onClick={() => createToken.mutate({ platform: \"telegram\" })}\n >\n New Telegram token\n </Button>\n </div>\n </div>\n <div className=\"mt-4 space-y-3\">\n {(data?.links || []).map((link: any) => (\n <div\n key={link.id}\n className=\"rounded-xl border bg-muted/30 px-4 py-3\"\n >\n <div className=\"text-sm font-medium text-foreground\">\n {link.externalUserName || link.externalUserId}\n </div>\n <div className=\"mt-1 text-xs text-muted-foreground\">\n {link.platform} → {link.ownerEmail}\n </div>\n </div>\n ))}\n {(data?.links?.length || 0) === 0 && (\n <div className=\"rounded-xl border border-dashed px-4 py-8 text-sm text-muted-foreground\">\n No linked identities yet. Generate a token and ask the user to\n send <code>/link TOKEN</code> from Slack or Telegram.\n </div>\n )}\n </div>\n </section>\n\n <section className=\"rounded-2xl border bg-card p-5\">\n <h2 className=\"text-lg font-semibold text-foreground\">\n Link tokens\n </h2>\n <div className=\"mt-4 space-y-3\">\n {(data?.tokens || []).map((token: any) => (\n <div key={token.id} className=\"rounded-xl border px-4 py-3\">\n <div className=\"text-sm font-medium text-foreground\">\n /link {token.token}\n </div>\n <div className=\"mt-1 text-xs text-muted-foreground\">\n {token.platform} · expires{\" \"}\n {new Date(token.expiresAt).toLocaleString()}\n {token.claimedAt\n ? ` · claimed by ${token.claimedByExternalUserName || token.claimedByExternalUserId}`\n : \" · waiting to be claimed\"}\n </div>\n </div>\n ))}\n {(data?.tokens?.length || 0) === 0 && (\n <div className=\"rounded-xl border border-dashed px-4 py-8 text-sm text-muted-foreground\">\n No active link tokens.\n </div>\n )}\n </div>\n </section>\n </div>\n )}\n </DispatchShell>\n );\n}\n"]}
1
+ {"version":3,"file":"identities.js","sourceRoot":"","sources":["../../../src/routes/pages/identities.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useActionMutation,\n useActionQuery,\n} from \"@agent-native/core/client/hooks\";\nimport { toast } from \"sonner\";\n\nimport { ActionQueryError } from \"../../components/action-query-error\";\nimport { DispatchShell } from \"../../components/dispatch-shell\";\nimport { Button } from \"../../components/ui/button\";\n\nexport function meta() {\n return [{ title: \"Identities — Dispatch\" }];\n}\n\nexport default function IdentitiesRoute() {\n const query = useActionQuery(\"list-linked-identities\", {});\n const { data } = query;\n const createToken = useActionMutation(\"create-link-token\", {\n onSuccess: () => toast.success(\"Link token created\"),\n });\n\n return (\n <DispatchShell\n title=\"Identities\"\n description=\"Link external senders to workspace users.\"\n >\n {query.isError ? (\n <ActionQueryError\n error={query.error}\n onRetry={() => void query.refetch()}\n />\n ) : (\n <div className=\"grid gap-4 xl:grid-cols-2\">\n <section className=\"rounded-2xl border bg-card p-5\">\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <h2 className=\"text-lg font-semibold text-foreground\">\n Active links\n </h2>\n <div className=\"flex shrink-0 gap-2\">\n <Button\n variant=\"outline\"\n onClick={() => createToken.mutate({ platform: \"slack\" })}\n >\n New Slack token\n </Button>\n <Button\n onClick={() => createToken.mutate({ platform: \"telegram\" })}\n >\n New Telegram token\n </Button>\n </div>\n </div>\n <div className=\"mt-4 space-y-3\">\n {(data?.links || []).map((link: any) => (\n <div\n key={link.id}\n className=\"rounded-xl border bg-muted/30 px-4 py-3\"\n >\n <div className=\"text-sm font-medium text-foreground\">\n {link.externalUserName || link.externalUserId}\n </div>\n <div className=\"mt-1 text-xs text-muted-foreground\">\n {link.platform} → {link.ownerEmail}\n </div>\n </div>\n ))}\n {(data?.links?.length || 0) === 0 && (\n <div className=\"rounded-xl border border-dashed px-4 py-8 text-sm text-muted-foreground\">\n No linked identities yet. Generate a token and ask the user to\n send <code>/link TOKEN</code> from Slack or Telegram.\n </div>\n )}\n </div>\n </section>\n\n <section className=\"rounded-2xl border bg-card p-5\">\n <h2 className=\"text-lg font-semibold text-foreground\">\n Link tokens\n </h2>\n <div className=\"mt-4 space-y-3\">\n {(data?.tokens || []).map((token: any) => (\n <div key={token.id} className=\"rounded-xl border px-4 py-3\">\n <div className=\"text-sm font-medium text-foreground\">\n /link {token.token}\n </div>\n <div className=\"mt-1 text-xs text-muted-foreground\">\n {token.platform} · expires{\" \"}\n {new Date(token.expiresAt).toLocaleString()}\n {token.claimedAt\n ? ` · claimed by ${token.claimedByExternalUserName || token.claimedByExternalUserId}`\n : \" · waiting to be claimed\"}\n </div>\n </div>\n ))}\n {(data?.tokens?.length || 0) === 0 && (\n <div className=\"rounded-xl border border-dashed px-4 py-8 text-sm text-muted-foreground\">\n No active link tokens.\n </div>\n )}\n </div>\n </section>\n </div>\n )}\n </DispatchShell>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"integrations.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/integrations.tsx"],"names":[],"mappings":"AAsCA,wBAAgB,IAAI;;IAEnB;AAyRD,MAAM,CAAC,OAAO,UAAU,gBAAgB,oDAwIvC"}
1
+ {"version":3,"file":"integrations.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/integrations.tsx"],"names":[],"mappings":"AAyCA,wBAAgB,IAAI;;IAEnB;AAyRD,MAAM,CAAC,OAAO,UAAU,gBAAgB,oDAwIvC"}
@@ -1,5 +1,5 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useActionMutation, useActionQuery } from "@agent-native/core/client";
2
+ import { useActionMutation, useActionQuery, } from "@agent-native/core/client/hooks";
3
3
  import { IconCheck, IconChevronRight, IconCircleDashed, IconKey, IconLink, IconPlugConnected, } from "@tabler/icons-react";
4
4
  import { useQueryClient } from "@tanstack/react-query";
5
5
  import { useMemo, useState } from "react";
@@ -1 +1 @@
1
- {"version":3,"file":"integrations.js","sourceRoot":"","sources":["../../../src/routes/pages/integrations.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useActionMutation, useActionQuery } from \"@agent-native/core/client\";\nimport {\n IconCheck,\n IconChevronRight,\n IconCircleDashed,\n IconKey,\n IconLink,\n IconPlugConnected,\n} from \"@tabler/icons-react\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport { useMemo, useState } from \"react\";\nimport { toast } from \"sonner\";\n\nimport { ActionQueryError } from \"../../components/action-query-error\";\nimport { DispatchShell } from \"../../components/dispatch-shell\";\nimport { Badge } from \"../../components/ui/badge\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"../../components/ui/collapsible\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"../../components/ui/dialog\";\nimport { Input } from \"../../components/ui/input\";\nimport { Label } from \"../../components/ui/label\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"../../components/ui/tooltip\";\n\nexport function meta() {\n return [{ title: \"Connections — Dispatch\" }];\n}\n\ninterface AppRef {\n appId: string;\n appName: string;\n color: string;\n configured: boolean;\n vaultGranted: boolean;\n vaultSecretId?: string;\n}\n\ninterface Service {\n /** Credential key shared across apps (e.g. `OPENAI_API_KEY`). */\n key: string;\n /** Human label from the first app that declares it (`\"OpenAI\"`, `\"Stripe\"`). */\n label: string;\n /** Apps in the workspace that declare this credential. */\n apps: AppRef[];\n}\n\ninterface CatalogApp {\n appId: string;\n appName: string;\n color: string;\n url: string;\n reachable: boolean;\n integrations?: Array<{\n key: string;\n label: string;\n required: boolean;\n configured: boolean;\n vaultGranted: boolean;\n vaultSecretId?: string;\n }>;\n}\n\nfunction inferProviderFromKey(key: string, label: string): string {\n const haystack = `${key} ${label}`.toLowerCase();\n for (const provider of [\n \"google\",\n \"slack\",\n \"sendgrid\",\n \"github\",\n \"stripe\",\n \"hubspot\",\n \"jira\",\n \"bigquery\",\n \"anthropic\",\n \"openai\",\n ]) {\n if (haystack.includes(provider)) return provider;\n }\n return \"other\";\n}\n\nfunction ConnectDialog({\n service,\n open,\n onOpenChange,\n accessMode,\n}: {\n service: Service;\n open: boolean;\n onOpenChange: (next: boolean) => void;\n accessMode: \"all-apps\" | \"manual\";\n}) {\n const [value, setValue] = useState(\"\");\n const qc = useQueryClient();\n\n const createSecret = useActionMutation(\"create-vault-secret\", {});\n const createGrant = useActionMutation(\"create-vault-grant\", {});\n const syncToApp = useActionMutation(\"sync-vault-to-app\", {});\n\n function reset() {\n setValue(\"\");\n }\n\n async function handleSave() {\n const trimmed = value.trim();\n if (!trimmed) {\n toast.error(\"Enter a value to save\");\n return;\n }\n try {\n // 1. Create the secret (or get the existing one — server treats key as\n // the unique identifier). The server returns { secret: { id, ... } }.\n const created = await createSecret.mutateAsync({\n credentialKey: service.key,\n name: service.label,\n value: trimmed,\n provider: inferProviderFromKey(service.key, service.label),\n });\n const secretId =\n (created as { secret?: { id?: string } })?.secret?.id ??\n (created as { id?: string })?.id;\n if (!secretId) {\n throw new Error(\"Secret created but id missing\");\n }\n\n // 2. Manual mode needs grants; all-apps mode only needs sync.\n if (accessMode === \"manual\") {\n const targets = service.apps.filter((a) => !a.vaultGranted);\n for (const app of targets) {\n try {\n await createGrant.mutateAsync({\n secretId,\n appId: app.appId,\n });\n } catch (err) {\n console.warn(`grant to ${app.appId} failed`, err);\n }\n }\n }\n for (const app of service.apps) {\n try {\n await syncToApp.mutateAsync({ appId: app.appId });\n } catch (err) {\n console.warn(`sync to ${app.appId} failed`, err);\n }\n }\n\n qc.invalidateQueries({\n queryKey: [\"action\", \"list-integrations-catalog\"],\n });\n toast.success(`Connected ${service.label}`);\n onOpenChange(false);\n reset();\n } catch (err: any) {\n toast.error(err?.message ?? \"Failed to save credential\");\n }\n }\n\n const pending =\n createSecret.isPending || createGrant.isPending || syncToApp.isPending;\n\n return (\n <Dialog\n open={open}\n onOpenChange={(next) => {\n if (!next) reset();\n onOpenChange(next);\n }}\n >\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Connect {service.label}</DialogTitle>\n <DialogDescription>\n Used by{\" \"}\n {service.apps.length === 1\n ? service.apps[0].appName\n : `${service.apps.length} apps`}\n . Saved to the workspace vault and synced to every app that needs\n it.\n </DialogDescription>\n </DialogHeader>\n <div className=\"space-y-3\">\n <div>\n <Label className=\"text-xs text-muted-foreground\">Key</Label>\n <div className=\"font-mono text-sm\">{service.key}</div>\n </div>\n <div>\n <Label htmlFor=\"connector-value\">Value</Label>\n <Input\n id=\"connector-value\"\n type=\"password\"\n autoComplete=\"off\"\n value={value}\n onChange={(e) => setValue(e.target.value)}\n placeholder={`Paste your ${service.label} key…`}\n autoFocus\n />\n </div>\n </div>\n <DialogFooter>\n <Button\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n disabled={pending}\n >\n Cancel\n </Button>\n <Button onClick={handleSave} disabled={pending || !value.trim()}>\n {pending ? \"Saving…\" : \"Connect\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n\nfunction ConnectorCard({\n service,\n accessMode,\n}: {\n service: Service;\n accessMode: \"all-apps\" | \"manual\";\n}) {\n const [open, setOpen] = useState(false);\n const isConnected = service.apps.some((a) => a.configured);\n const appCount = service.apps.length;\n\n return (\n <>\n <button\n type=\"button\"\n onClick={() => setOpen(true)}\n className=\"group flex flex-col items-start gap-2 rounded-2xl border bg-card p-5 text-left transition hover:border-foreground/20 hover:bg-card/80 cursor-pointer\"\n >\n <div className=\"flex w-full items-start justify-between gap-2\">\n <div className=\"flex h-9 w-9 items-center justify-center rounded-xl bg-muted\">\n <IconKey size={16} className=\"text-muted-foreground\" />\n </div>\n {isConnected ? (\n <Badge\n variant=\"secondary\"\n className=\"bg-green-500/10 text-green-700 dark:text-green-400 gap-1\"\n >\n <IconCheck size={12} />\n Connected\n </Badge>\n ) : (\n <Badge\n variant=\"secondary\"\n className=\"bg-amber-500/10 text-amber-700 dark:text-amber-400 gap-1\"\n >\n <IconCircleDashed size={12} />\n Connect\n </Badge>\n )}\n </div>\n <div className=\"w-full min-w-0\">\n <Tooltip>\n <TooltipTrigger asChild>\n <div className=\"text-sm font-semibold text-foreground truncate\">\n {service.label}\n </div>\n </TooltipTrigger>\n <TooltipContent>{service.label}</TooltipContent>\n </Tooltip>\n <div className=\"font-mono text-xs text-muted-foreground/80 truncate\">\n {service.key}\n </div>\n </div>\n <div className=\"text-xs text-muted-foreground\">\n Used by {appCount} {appCount === 1 ? \"app\" : \"apps\"}\n </div>\n </button>\n <ConnectDialog\n service={service}\n open={open}\n onOpenChange={setOpen}\n accessMode={accessMode}\n />\n </>\n );\n}\n\nfunction PerAppDetailRow({ app }: { app: CatalogApp }) {\n const total = (app.integrations ?? []).length;\n const ok = (app.integrations ?? []).filter((i) => i.configured).length;\n return (\n <div className=\"flex items-center justify-between border-t px-4 py-2.5 first:border-t-0\">\n <div className=\"flex items-center gap-2 min-w-0\">\n <div\n className=\"h-5 w-5 rounded text-[10px] font-bold text-white flex items-center justify-center shrink-0\"\n style={{ backgroundColor: app.color }}\n >\n {app.appName.charAt(0).toUpperCase()}\n </div>\n <span className=\"text-sm truncate\">{app.appName}</span>\n {!app.reachable && (\n <span className=\"text-xs text-muted-foreground\">offline</span>\n )}\n </div>\n <span className=\"text-xs text-muted-foreground\">\n {total === 0 ? \"no integrations\" : `${ok}/${total}`}\n </span>\n </div>\n );\n}\n\nexport default function ConnectionsRoute() {\n const catalogQuery = useActionQuery(\"list-integrations-catalog\", {});\n const accessQuery = useActionQuery(\"get-vault-access-settings\", {});\n const { data: catalog, isLoading } = catalogQuery;\n const { data: accessSettings } = accessQuery;\n const apps = (catalog as CatalogApp[]) || [];\n const accessMode =\n (accessSettings as any)?.mode === \"manual\" ? \"manual\" : \"all-apps\";\n\n const services = useMemo<Service[]>(() => {\n const map = new Map<string, Service>();\n for (const app of apps) {\n for (const intg of app.integrations ?? []) {\n if (!map.has(intg.key)) {\n map.set(intg.key, {\n key: intg.key,\n label: intg.label,\n apps: [],\n });\n }\n map.get(intg.key)!.apps.push({\n appId: app.appId,\n appName: app.appName,\n color: app.color,\n configured: intg.configured,\n vaultGranted: intg.vaultGranted,\n vaultSecretId: intg.vaultSecretId,\n });\n }\n }\n return Array.from(map.values()).sort((a, b) =>\n a.label.localeCompare(b.label),\n );\n }, [apps]);\n\n const available = services.filter((s) => !s.apps.some((a) => a.configured));\n const connected = services.filter((s) => s.apps.some((a) => a.configured));\n\n return (\n <DispatchShell\n title=\"Connections\"\n description=\"Connect services once. Apps that need them pick up the key automatically.\"\n >\n {catalogQuery.isError || accessQuery.isError ? (\n <ActionQueryError\n error={catalogQuery.error ?? accessQuery.error}\n onRetry={() => {\n void catalogQuery.refetch();\n void accessQuery.refetch();\n }}\n />\n ) : null}\n\n {!catalogQuery.isError && isLoading && services.length === 0 && (\n <div className=\"rounded-2xl border border-dashed px-6 py-12 text-center text-sm text-muted-foreground\">\n Discovering apps and credentials…\n </div>\n )}\n\n {!catalogQuery.isError && !isLoading && services.length === 0 && (\n <div className=\"rounded-2xl border border-dashed px-6 py-12 text-center text-sm text-muted-foreground\">\n No apps with declared integrations are reachable yet.\n </div>\n )}\n\n {available.length > 0 && (\n <section>\n <div className=\"mb-3 flex items-baseline justify-between\">\n <h2 className=\"text-sm font-medium text-foreground\">\n Available to connect\n </h2>\n <span className=\"text-xs text-muted-foreground\">\n {available.length}\n </span>\n </div>\n <div className=\"grid gap-3 sm:grid-cols-2 xl:grid-cols-3\">\n {available.map((service) => (\n <ConnectorCard\n key={service.key}\n service={service}\n accessMode={accessMode}\n />\n ))}\n </div>\n </section>\n )}\n\n {connected.length > 0 && (\n <section>\n <div className=\"mb-3 mt-2 flex items-baseline justify-between\">\n <h2 className=\"text-sm font-medium text-foreground\">Connected</h2>\n <span className=\"text-xs text-muted-foreground\">\n {connected.length}\n </span>\n </div>\n <div className=\"grid gap-3 sm:grid-cols-2 xl:grid-cols-3\">\n {connected.map((service) => (\n <ConnectorCard\n key={service.key}\n service={service}\n accessMode={accessMode}\n />\n ))}\n </div>\n </section>\n )}\n\n {apps.length > 0 && (\n <Collapsible className=\"mt-6 rounded-2xl border bg-card\">\n <CollapsibleTrigger className=\"group flex w-full items-center justify-between px-4 py-3 text-sm\">\n <span className=\"flex items-center gap-2 text-muted-foreground\">\n <IconPlugConnected size={14} />\n Per-app status\n </span>\n <IconChevronRight\n size={14}\n className=\"text-muted-foreground transition group-data-[state=open]:rotate-90\"\n />\n </CollapsibleTrigger>\n <CollapsibleContent>\n <div className=\"border-t\">\n {apps.map((app) => (\n <PerAppDetailRow key={app.appId} app={app} />\n ))}\n </div>\n <div className=\"flex items-center justify-end gap-1.5 border-t px-4 py-2.5 text-xs text-muted-foreground\">\n <IconLink size={12} />\n <a href=\"/vault\" className=\"hover:underline\">\n Open vault for advanced sharing\n </a>\n </div>\n </CollapsibleContent>\n </Collapsible>\n )}\n </DispatchShell>\n );\n}\n"]}
1
+ {"version":3,"file":"integrations.js","sourceRoot":"","sources":["../../../src/routes/pages/integrations.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n useActionMutation,\n useActionQuery,\n} from \"@agent-native/core/client/hooks\";\nimport {\n IconCheck,\n IconChevronRight,\n IconCircleDashed,\n IconKey,\n IconLink,\n IconPlugConnected,\n} from \"@tabler/icons-react\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport { useMemo, useState } from \"react\";\nimport { toast } from \"sonner\";\n\nimport { ActionQueryError } from \"../../components/action-query-error\";\nimport { DispatchShell } from \"../../components/dispatch-shell\";\nimport { Badge } from \"../../components/ui/badge\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"../../components/ui/collapsible\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"../../components/ui/dialog\";\nimport { Input } from \"../../components/ui/input\";\nimport { Label } from \"../../components/ui/label\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"../../components/ui/tooltip\";\n\nexport function meta() {\n return [{ title: \"Connections — Dispatch\" }];\n}\n\ninterface AppRef {\n appId: string;\n appName: string;\n color: string;\n configured: boolean;\n vaultGranted: boolean;\n vaultSecretId?: string;\n}\n\ninterface Service {\n /** Credential key shared across apps (e.g. `OPENAI_API_KEY`). */\n key: string;\n /** Human label from the first app that declares it (`\"OpenAI\"`, `\"Stripe\"`). */\n label: string;\n /** Apps in the workspace that declare this credential. */\n apps: AppRef[];\n}\n\ninterface CatalogApp {\n appId: string;\n appName: string;\n color: string;\n url: string;\n reachable: boolean;\n integrations?: Array<{\n key: string;\n label: string;\n required: boolean;\n configured: boolean;\n vaultGranted: boolean;\n vaultSecretId?: string;\n }>;\n}\n\nfunction inferProviderFromKey(key: string, label: string): string {\n const haystack = `${key} ${label}`.toLowerCase();\n for (const provider of [\n \"google\",\n \"slack\",\n \"sendgrid\",\n \"github\",\n \"stripe\",\n \"hubspot\",\n \"jira\",\n \"bigquery\",\n \"anthropic\",\n \"openai\",\n ]) {\n if (haystack.includes(provider)) return provider;\n }\n return \"other\";\n}\n\nfunction ConnectDialog({\n service,\n open,\n onOpenChange,\n accessMode,\n}: {\n service: Service;\n open: boolean;\n onOpenChange: (next: boolean) => void;\n accessMode: \"all-apps\" | \"manual\";\n}) {\n const [value, setValue] = useState(\"\");\n const qc = useQueryClient();\n\n const createSecret = useActionMutation(\"create-vault-secret\", {});\n const createGrant = useActionMutation(\"create-vault-grant\", {});\n const syncToApp = useActionMutation(\"sync-vault-to-app\", {});\n\n function reset() {\n setValue(\"\");\n }\n\n async function handleSave() {\n const trimmed = value.trim();\n if (!trimmed) {\n toast.error(\"Enter a value to save\");\n return;\n }\n try {\n // 1. Create the secret (or get the existing one — server treats key as\n // the unique identifier). The server returns { secret: { id, ... } }.\n const created = await createSecret.mutateAsync({\n credentialKey: service.key,\n name: service.label,\n value: trimmed,\n provider: inferProviderFromKey(service.key, service.label),\n });\n const secretId =\n (created as { secret?: { id?: string } })?.secret?.id ??\n (created as { id?: string })?.id;\n if (!secretId) {\n throw new Error(\"Secret created but id missing\");\n }\n\n // 2. Manual mode needs grants; all-apps mode only needs sync.\n if (accessMode === \"manual\") {\n const targets = service.apps.filter((a) => !a.vaultGranted);\n for (const app of targets) {\n try {\n await createGrant.mutateAsync({\n secretId,\n appId: app.appId,\n });\n } catch (err) {\n console.warn(`grant to ${app.appId} failed`, err);\n }\n }\n }\n for (const app of service.apps) {\n try {\n await syncToApp.mutateAsync({ appId: app.appId });\n } catch (err) {\n console.warn(`sync to ${app.appId} failed`, err);\n }\n }\n\n qc.invalidateQueries({\n queryKey: [\"action\", \"list-integrations-catalog\"],\n });\n toast.success(`Connected ${service.label}`);\n onOpenChange(false);\n reset();\n } catch (err: any) {\n toast.error(err?.message ?? \"Failed to save credential\");\n }\n }\n\n const pending =\n createSecret.isPending || createGrant.isPending || syncToApp.isPending;\n\n return (\n <Dialog\n open={open}\n onOpenChange={(next) => {\n if (!next) reset();\n onOpenChange(next);\n }}\n >\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Connect {service.label}</DialogTitle>\n <DialogDescription>\n Used by{\" \"}\n {service.apps.length === 1\n ? service.apps[0].appName\n : `${service.apps.length} apps`}\n . Saved to the workspace vault and synced to every app that needs\n it.\n </DialogDescription>\n </DialogHeader>\n <div className=\"space-y-3\">\n <div>\n <Label className=\"text-xs text-muted-foreground\">Key</Label>\n <div className=\"font-mono text-sm\">{service.key}</div>\n </div>\n <div>\n <Label htmlFor=\"connector-value\">Value</Label>\n <Input\n id=\"connector-value\"\n type=\"password\"\n autoComplete=\"off\"\n value={value}\n onChange={(e) => setValue(e.target.value)}\n placeholder={`Paste your ${service.label} key…`}\n autoFocus\n />\n </div>\n </div>\n <DialogFooter>\n <Button\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n disabled={pending}\n >\n Cancel\n </Button>\n <Button onClick={handleSave} disabled={pending || !value.trim()}>\n {pending ? \"Saving…\" : \"Connect\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n\nfunction ConnectorCard({\n service,\n accessMode,\n}: {\n service: Service;\n accessMode: \"all-apps\" | \"manual\";\n}) {\n const [open, setOpen] = useState(false);\n const isConnected = service.apps.some((a) => a.configured);\n const appCount = service.apps.length;\n\n return (\n <>\n <button\n type=\"button\"\n onClick={() => setOpen(true)}\n className=\"group flex flex-col items-start gap-2 rounded-2xl border bg-card p-5 text-left transition hover:border-foreground/20 hover:bg-card/80 cursor-pointer\"\n >\n <div className=\"flex w-full items-start justify-between gap-2\">\n <div className=\"flex h-9 w-9 items-center justify-center rounded-xl bg-muted\">\n <IconKey size={16} className=\"text-muted-foreground\" />\n </div>\n {isConnected ? (\n <Badge\n variant=\"secondary\"\n className=\"bg-green-500/10 text-green-700 dark:text-green-400 gap-1\"\n >\n <IconCheck size={12} />\n Connected\n </Badge>\n ) : (\n <Badge\n variant=\"secondary\"\n className=\"bg-amber-500/10 text-amber-700 dark:text-amber-400 gap-1\"\n >\n <IconCircleDashed size={12} />\n Connect\n </Badge>\n )}\n </div>\n <div className=\"w-full min-w-0\">\n <Tooltip>\n <TooltipTrigger asChild>\n <div className=\"text-sm font-semibold text-foreground truncate\">\n {service.label}\n </div>\n </TooltipTrigger>\n <TooltipContent>{service.label}</TooltipContent>\n </Tooltip>\n <div className=\"font-mono text-xs text-muted-foreground/80 truncate\">\n {service.key}\n </div>\n </div>\n <div className=\"text-xs text-muted-foreground\">\n Used by {appCount} {appCount === 1 ? \"app\" : \"apps\"}\n </div>\n </button>\n <ConnectDialog\n service={service}\n open={open}\n onOpenChange={setOpen}\n accessMode={accessMode}\n />\n </>\n );\n}\n\nfunction PerAppDetailRow({ app }: { app: CatalogApp }) {\n const total = (app.integrations ?? []).length;\n const ok = (app.integrations ?? []).filter((i) => i.configured).length;\n return (\n <div className=\"flex items-center justify-between border-t px-4 py-2.5 first:border-t-0\">\n <div className=\"flex items-center gap-2 min-w-0\">\n <div\n className=\"h-5 w-5 rounded text-[10px] font-bold text-white flex items-center justify-center shrink-0\"\n style={{ backgroundColor: app.color }}\n >\n {app.appName.charAt(0).toUpperCase()}\n </div>\n <span className=\"text-sm truncate\">{app.appName}</span>\n {!app.reachable && (\n <span className=\"text-xs text-muted-foreground\">offline</span>\n )}\n </div>\n <span className=\"text-xs text-muted-foreground\">\n {total === 0 ? \"no integrations\" : `${ok}/${total}`}\n </span>\n </div>\n );\n}\n\nexport default function ConnectionsRoute() {\n const catalogQuery = useActionQuery(\"list-integrations-catalog\", {});\n const accessQuery = useActionQuery(\"get-vault-access-settings\", {});\n const { data: catalog, isLoading } = catalogQuery;\n const { data: accessSettings } = accessQuery;\n const apps = (catalog as CatalogApp[]) || [];\n const accessMode =\n (accessSettings as any)?.mode === \"manual\" ? \"manual\" : \"all-apps\";\n\n const services = useMemo<Service[]>(() => {\n const map = new Map<string, Service>();\n for (const app of apps) {\n for (const intg of app.integrations ?? []) {\n if (!map.has(intg.key)) {\n map.set(intg.key, {\n key: intg.key,\n label: intg.label,\n apps: [],\n });\n }\n map.get(intg.key)!.apps.push({\n appId: app.appId,\n appName: app.appName,\n color: app.color,\n configured: intg.configured,\n vaultGranted: intg.vaultGranted,\n vaultSecretId: intg.vaultSecretId,\n });\n }\n }\n return Array.from(map.values()).sort((a, b) =>\n a.label.localeCompare(b.label),\n );\n }, [apps]);\n\n const available = services.filter((s) => !s.apps.some((a) => a.configured));\n const connected = services.filter((s) => s.apps.some((a) => a.configured));\n\n return (\n <DispatchShell\n title=\"Connections\"\n description=\"Connect services once. Apps that need them pick up the key automatically.\"\n >\n {catalogQuery.isError || accessQuery.isError ? (\n <ActionQueryError\n error={catalogQuery.error ?? accessQuery.error}\n onRetry={() => {\n void catalogQuery.refetch();\n void accessQuery.refetch();\n }}\n />\n ) : null}\n\n {!catalogQuery.isError && isLoading && services.length === 0 && (\n <div className=\"rounded-2xl border border-dashed px-6 py-12 text-center text-sm text-muted-foreground\">\n Discovering apps and credentials…\n </div>\n )}\n\n {!catalogQuery.isError && !isLoading && services.length === 0 && (\n <div className=\"rounded-2xl border border-dashed px-6 py-12 text-center text-sm text-muted-foreground\">\n No apps with declared integrations are reachable yet.\n </div>\n )}\n\n {available.length > 0 && (\n <section>\n <div className=\"mb-3 flex items-baseline justify-between\">\n <h2 className=\"text-sm font-medium text-foreground\">\n Available to connect\n </h2>\n <span className=\"text-xs text-muted-foreground\">\n {available.length}\n </span>\n </div>\n <div className=\"grid gap-3 sm:grid-cols-2 xl:grid-cols-3\">\n {available.map((service) => (\n <ConnectorCard\n key={service.key}\n service={service}\n accessMode={accessMode}\n />\n ))}\n </div>\n </section>\n )}\n\n {connected.length > 0 && (\n <section>\n <div className=\"mb-3 mt-2 flex items-baseline justify-between\">\n <h2 className=\"text-sm font-medium text-foreground\">Connected</h2>\n <span className=\"text-xs text-muted-foreground\">\n {connected.length}\n </span>\n </div>\n <div className=\"grid gap-3 sm:grid-cols-2 xl:grid-cols-3\">\n {connected.map((service) => (\n <ConnectorCard\n key={service.key}\n service={service}\n accessMode={accessMode}\n />\n ))}\n </div>\n </section>\n )}\n\n {apps.length > 0 && (\n <Collapsible className=\"mt-6 rounded-2xl border bg-card\">\n <CollapsibleTrigger className=\"group flex w-full items-center justify-between px-4 py-3 text-sm\">\n <span className=\"flex items-center gap-2 text-muted-foreground\">\n <IconPlugConnected size={14} />\n Per-app status\n </span>\n <IconChevronRight\n size={14}\n className=\"text-muted-foreground transition group-data-[state=open]:rotate-90\"\n />\n </CollapsibleTrigger>\n <CollapsibleContent>\n <div className=\"border-t\">\n {apps.map((app) => (\n <PerAppDetailRow key={app.appId} app={app} />\n ))}\n </div>\n <div className=\"flex items-center justify-end gap-1.5 border-t px-4 py-2.5 text-xs text-muted-foreground\">\n <IconLink size={12} />\n <a href=\"/vault\" className=\"hover:underline\">\n Open vault for advanced sharing\n </a>\n </div>\n </CollapsibleContent>\n </Collapsible>\n )}\n </DispatchShell>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/metrics.tsx"],"names":[],"mappings":"AAoBA,wBAAgB,IAAI;;IAEnB;AAymBD,MAAM,CAAC,OAAO,UAAU,YAAY,oDAwInC"}
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/metrics.tsx"],"names":[],"mappings":"AAqBA,wBAAgB,IAAI;;IAEnB;AAymBD,MAAM,CAAC,OAAO,UAAU,YAAY,oDAwInC"}
@@ -1,5 +1,6 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useActionQuery, useT } from "@agent-native/core/client";
2
+ import { useActionQuery } from "@agent-native/core/client/hooks";
3
+ import { useT } from "@agent-native/core/client/i18n";
3
4
  import { IconActivity, IconAlertTriangle, IconApps, IconChartBar, IconClockHour4, IconCoin, IconMessages, IconUsersGroup, } from "@tabler/icons-react";
4
5
  import { useMemo, useState } from "react";
5
6
  import { DispatchShell } from "../../components/dispatch-shell.js";
@@ -1 +1 @@
1
- {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../../src/routes/pages/metrics.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useActionQuery, useT } from \"@agent-native/core/client\";\nimport {\n IconActivity,\n IconAlertTriangle,\n IconApps,\n IconChartBar,\n IconClockHour4,\n IconCoin,\n IconMessages,\n IconUsersGroup,\n} from \"@tabler/icons-react\";\nimport { useMemo, useState, type ReactNode } from \"react\";\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 { 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 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}\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 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 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 border 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 border 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 border 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 border 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 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 DailyActivity({ rows }: { rows: DailyUsageMetric[] }) {\n const max = Math.max(\n 1,\n rows.reduce((value, row) => Math.max(value, row.calls), 0),\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 activity in this window.\n </div>\n );\n }\n return (\n <div className=\"flex h-44 items-end gap-1\">\n {rows.map((row) => (\n <div\n key={row.date}\n className=\"group flex min-w-0 flex-1 flex-col items-center gap-2\"\n >\n <div className=\"relative flex h-36 w-full items-end rounded-sm bg-muted/60\">\n <div\n className=\"w-full rounded-sm bg-foreground transition group-hover:bg-primary\"\n style={{ height: `${Math.max(4, (row.calls / max) * 100)}%` }}\n />\n </div>\n <div className=\"hidden text-[10px] text-muted-foreground sm:block\">\n {row.date.slice(5)}\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 recent LLM calls.\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\">When</th>\n <th className=\"px-2 py-2 font-medium\">User</th>\n <th className=\"px-2 py-2 font-medium\">App</th>\n <th className=\"px-2 py-2 font-medium\">Label</th>\n <th className=\"px-2 py-2 font-medium\">Model</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, 10).map((row) => (\n <tr key={row.id} className=\"border-b last:border-0\">\n <td className=\"px-2 py-3 text-muted-foreground\">\n {timeAgo(row.createdAt)}\n </td>\n <td className=\"max-w-56 px-2 py-3\">\n <div className=\"truncate text-foreground\">{row.ownerEmail}</div>\n </td>\n <td className=\"px-2 py-3 text-muted-foreground\">\n {displayApp(row.app)}\n </td>\n <td className=\"px-2 py-3\">\n <Badge variant=\"outline\">{row.label}</Badge>\n </td>\n <td className=\"max-w-48 px-2 py-3\">\n <div className=\"truncate text-muted-foreground\">\n {row.model}\n </div>\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\nexport default function MetricsRoute() {\n const t = useT();\n const [sinceDays, setSinceDays] = useState(30);\n const { data, isLoading, error } = useActionQuery(\n \"list-dispatch-usage-metrics\",\n { sinceDays },\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 className=\"text-sm text-muted-foreground\">\n {metrics?.access.scope === \"organization\"\n ? `${metrics.access.totalUsers} workspace users`\n : `${metrics?.access.totalUsers ?? 0} signed-in users`}\n </div>\n <RangeSelector value={sinceDays} onChange={setSinceDays} />\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 <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 <div className=\"grid gap-4 xl:grid-cols-[minmax(0,1.35fr)_minmax(320px,0.65fr)]\">\n <Panel\n title={\n billing.unit === \"builder-credits\"\n ? \"Credit Spend By App\"\n : \"Spend By App\"\n }\n icon={<IconChartBar size={16} />}\n >\n <AppSpendRows rows={metrics.byApp} billing={billing} />\n </Panel>\n <Panel title=\"Daily Activity\" icon={<IconClockHour4 size={16} />}>\n <DailyActivity rows={metrics.daily} />\n </Panel>\n </div>\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 <Panel title=\"Recent LLM Calls\" icon={<IconActivity size={16} />}>\n <RecentTable rows={metrics.recent} billing={billing} />\n </Panel>\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 { useActionQuery } from \"@agent-native/core/client/hooks\";\nimport { useT } from \"@agent-native/core/client/i18n\";\nimport {\n IconActivity,\n IconAlertTriangle,\n IconApps,\n IconChartBar,\n IconClockHour4,\n IconCoin,\n IconMessages,\n IconUsersGroup,\n} from \"@tabler/icons-react\";\nimport { useMemo, useState, type ReactNode } from \"react\";\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 { 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 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}\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 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 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 border 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 border 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 border 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 border 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 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 DailyActivity({ rows }: { rows: DailyUsageMetric[] }) {\n const max = Math.max(\n 1,\n rows.reduce((value, row) => Math.max(value, row.calls), 0),\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 activity in this window.\n </div>\n );\n }\n return (\n <div className=\"flex h-44 items-end gap-1\">\n {rows.map((row) => (\n <div\n key={row.date}\n className=\"group flex min-w-0 flex-1 flex-col items-center gap-2\"\n >\n <div className=\"relative flex h-36 w-full items-end rounded-sm bg-muted/60\">\n <div\n className=\"w-full rounded-sm bg-foreground transition group-hover:bg-primary\"\n style={{ height: `${Math.max(4, (row.calls / max) * 100)}%` }}\n />\n </div>\n <div className=\"hidden text-[10px] text-muted-foreground sm:block\">\n {row.date.slice(5)}\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 recent LLM calls.\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\">When</th>\n <th className=\"px-2 py-2 font-medium\">User</th>\n <th className=\"px-2 py-2 font-medium\">App</th>\n <th className=\"px-2 py-2 font-medium\">Label</th>\n <th className=\"px-2 py-2 font-medium\">Model</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, 10).map((row) => (\n <tr key={row.id} className=\"border-b last:border-0\">\n <td className=\"px-2 py-3 text-muted-foreground\">\n {timeAgo(row.createdAt)}\n </td>\n <td className=\"max-w-56 px-2 py-3\">\n <div className=\"truncate text-foreground\">{row.ownerEmail}</div>\n </td>\n <td className=\"px-2 py-3 text-muted-foreground\">\n {displayApp(row.app)}\n </td>\n <td className=\"px-2 py-3\">\n <Badge variant=\"outline\">{row.label}</Badge>\n </td>\n <td className=\"max-w-48 px-2 py-3\">\n <div className=\"truncate text-muted-foreground\">\n {row.model}\n </div>\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\nexport default function MetricsRoute() {\n const t = useT();\n const [sinceDays, setSinceDays] = useState(30);\n const { data, isLoading, error } = useActionQuery(\n \"list-dispatch-usage-metrics\",\n { sinceDays },\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 className=\"text-sm text-muted-foreground\">\n {metrics?.access.scope === \"organization\"\n ? `${metrics.access.totalUsers} workspace users`\n : `${metrics?.access.totalUsers ?? 0} signed-in users`}\n </div>\n <RangeSelector value={sinceDays} onChange={setSinceDays} />\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 <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 <div className=\"grid gap-4 xl:grid-cols-[minmax(0,1.35fr)_minmax(320px,0.65fr)]\">\n <Panel\n title={\n billing.unit === \"builder-credits\"\n ? \"Credit Spend By App\"\n : \"Spend By App\"\n }\n icon={<IconChartBar size={16} />}\n >\n <AppSpendRows rows={metrics.byApp} billing={billing} />\n </Panel>\n <Panel title=\"Daily Activity\" icon={<IconClockHour4 size={16} />}>\n <DailyActivity rows={metrics.daily} />\n </Panel>\n </div>\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 <Panel title=\"Recent LLM Calls\" icon={<IconActivity size={16} />}>\n <RecentTable rows={metrics.recent} billing={billing} />\n </Panel>\n </>\n ) : null}\n </div>\n </DispatchShell>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"new-app.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/new-app.tsx"],"names":[],"mappings":"AAIA,wBAAgB,IAAI;;IAEnB;AAED,MAAM,CAAC,OAAO,UAAU,WAAW,oDAUlC"}
1
+ {"version":3,"file":"new-app.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/new-app.tsx"],"names":[],"mappings":"AAKA,wBAAgB,IAAI;;IAEnB;AAED,MAAM,CAAC,OAAO,UAAU,WAAW,oDAUlC"}
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { NewWorkspaceAppFlow, useT } from "@agent-native/core/client";
2
+ import { useT } from "@agent-native/core/client/i18n";
3
+ import { NewWorkspaceAppFlow } from "@agent-native/core/client/ui";
3
4
  import { DispatchShell } from "../../components/dispatch-shell.js";
4
5
  export function meta() {
5
6
  return [{ title: "New App — Dispatch" }];
@@ -1 +1 @@
1
- {"version":3,"file":"new-app.js","sourceRoot":"","sources":["../../../src/routes/pages/new-app.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,mBAAmB,EAAE,IAAI,EAAE,MAAM,2BAA2B,CAAC;AAEtE,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAEhE,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,WAAW;IACjC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,OAAO,CACL,KAAC,aAAa,IACZ,KAAK,EAAE,CAAC,CAAC,uBAAuB,CAAC,EACjC,WAAW,EAAE,CAAC,CAAC,kCAAkC,CAAC,YAElD,KAAC,mBAAmB,IAAC,SAAS,EAAC,UAAU,EAAC,SAAS,EAAC,WAAW,GAAG,GACpD,CACjB,CAAC;AACJ,CAAC","sourcesContent":["import { NewWorkspaceAppFlow, useT } from \"@agent-native/core/client\";\n\nimport { DispatchShell } from \"../../components/dispatch-shell\";\n\nexport function meta() {\n return [{ title: \"New App — Dispatch\" }];\n}\n\nexport default function NewAppRoute() {\n const t = useT();\n return (\n <DispatchShell\n title={t(\"dispatch.pages.newApp\")}\n description={t(\"dispatch.pages.newAppDescription\")}\n >\n <NewWorkspaceAppFlow sourceApp=\"dispatch\" className=\"px-0 py-0\" />\n </DispatchShell>\n );\n}\n"]}
1
+ {"version":3,"file":"new-app.js","sourceRoot":"","sources":["../../../src/routes/pages/new-app.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnE,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAEhE,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,WAAW;IACjC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,OAAO,CACL,KAAC,aAAa,IACZ,KAAK,EAAE,CAAC,CAAC,uBAAuB,CAAC,EACjC,WAAW,EAAE,CAAC,CAAC,kCAAkC,CAAC,YAElD,KAAC,mBAAmB,IAAC,SAAS,EAAC,UAAU,EAAC,SAAS,EAAC,WAAW,GAAG,GACpD,CACjB,CAAC;AACJ,CAAC","sourcesContent":["import { useT } from \"@agent-native/core/client/i18n\";\nimport { NewWorkspaceAppFlow } from \"@agent-native/core/client/ui\";\n\nimport { DispatchShell } from \"../../components/dispatch-shell\";\n\nexport function meta() {\n return [{ title: \"New App — Dispatch\" }];\n}\n\nexport default function NewAppRoute() {\n const t = useT();\n return (\n <DispatchShell\n title={t(\"dispatch.pages.newApp\")}\n description={t(\"dispatch.pages.newAppDescription\")}\n >\n <NewWorkspaceAppFlow sourceApp=\"dispatch\" className=\"px-0 py-0\" />\n </DispatchShell>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/operations.tsx"],"names":[],"mappings":"AAkFA,wBAAgB,IAAI;;IAEnB;AAED,MAAM,CAAC,OAAO,UAAU,eAAe,oDA+CtC"}
1
+ {"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/operations.tsx"],"names":[],"mappings":"AAgFA,wBAAgB,IAAI;;IAEnB;AAED,MAAM,CAAC,OAAO,UAAU,eAAe,oDA+CtC"}
@@ -1,5 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { DbAdminPage, ObservabilityDashboard, useT, } from "@agent-native/core/client";
2
+ import { DbAdminPage } from "@agent-native/core/client/db-admin";
3
+ import { useT } from "@agent-native/core/client/i18n";
4
+ import { ObservabilityDashboard } from "@agent-native/core/client/observability";
3
5
  import { IconActivity, IconArrowUpRight, IconDatabase, IconHistory, IconMessages, IconSend, } from "@tabler/icons-react";
4
6
  import { Link, useSearchParams } from "react-router";
5
7
  import { DispatchShell } from "../../components/dispatch-shell.js";
@@ -1 +1 @@
1
- {"version":3,"file":"operations.js","sourceRoot":"","sources":["../../../src/routes/pages/operations.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n DbAdminPage,\n ObservabilityDashboard,\n useT,\n} from \"@agent-native/core/client\";\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: \"/thread-debug\",\n icon: IconMessages,\n title: t(\"dispatch.nav.threadDebug\", { defaultValue: \"Thread debug\" }),\n },\n {\n to: \"/audit\",\n icon: IconHistory,\n title: t(\"dispatch.nav.audit\"),\n },\n {\n to: \"/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: \"/thread-debug\",\n icon: IconMessages,\n title: t(\"dispatch.nav.threadDebug\", { defaultValue: \"Thread debug\" }),\n },\n {\n to: \"/audit\",\n icon: IconHistory,\n title: t(\"dispatch.nav.audit\"),\n },\n {\n to: \"/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 +1 @@
1
- {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/settings.tsx"],"names":[],"mappings":"AAsBA,wBAAgB,IAAI;;IAEnB;AAED,MAAM,CAAC,OAAO,UAAU,aAAa,oDA+FpC"}
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/settings.tsx"],"names":[],"mappings":"AAqBA,wBAAgB,IAAI;;IAEnB;AAED,MAAM,CAAC,OAAO,UAAU,aAAa,oDA+FpC"}
@@ -1,6 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { ChangelogSettingsCard, LanguagePicker, SettingsTabsPage, useAgentSettingsTabs, useT, } from "@agent-native/core/client";
2
+ import { ChangelogSettingsCard } from "@agent-native/core/client/changelog";
3
+ import { LanguagePicker, useT } from "@agent-native/core/client/i18n";
3
4
  import { TeamPage } from "@agent-native/core/client/org";
5
+ import { SettingsTabsPage, useAgentSettingsTabs, } from "@agent-native/core/client/settings";
4
6
  import { Link } from "react-router";
5
7
  import changelog from "../../../CHANGELOG.md?raw";
6
8
  import { DispatchShell } from "../../components/dispatch-shell.js";
@@ -1 +1 @@
1
- {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../src/routes/pages/settings.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n ChangelogSettingsCard,\n LanguagePicker,\n SettingsTabsPage,\n useAgentSettingsTabs,\n useT,\n} from \"@agent-native/core/client\";\nimport { TeamPage } from \"@agent-native/core/client/org\";\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\";\n\nexport function meta() {\n return [{ title: \"Settings - Dispatch\" }];\n}\n\nexport default function SettingsRoute() {\n const t = useT();\n const agentSettingsTabs = useAgentSettingsTabs();\n\n return (\n <DispatchShell\n title={t(\"settings.title\")}\n description={t(\"settings.description\")}\n >\n <SettingsTabsPage\n extraTabs={agentSettingsTabs}\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 {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=\"/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.automationsTitle\")}\n </CardTitle>\n <CardDescription>\n {t(\"settings.automationsDescription\")}\n </CardDescription>\n </CardHeader>\n <CardContent>\n <Button variant=\"outline\" asChild>\n <Link to=\"/automations\">{t(\"settings.openAutomations\")}</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=\"/destinations\">{t(\"settings.openDelivery\")}</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 { 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 { 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\";\n\nexport function meta() {\n return [{ title: \"Settings - Dispatch\" }];\n}\n\nexport default function SettingsRoute() {\n const t = useT();\n const agentSettingsTabs = useAgentSettingsTabs();\n\n return (\n <DispatchShell\n title={t(\"settings.title\")}\n description={t(\"settings.description\")}\n >\n <SettingsTabsPage\n extraTabs={agentSettingsTabs}\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 {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=\"/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.automationsTitle\")}\n </CardTitle>\n <CardDescription>\n {t(\"settings.automationsDescription\")}\n </CardDescription>\n </CardHeader>\n <CardContent>\n <Button variant=\"outline\" asChild>\n <Link to=\"/automations\">{t(\"settings.openAutomations\")}</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=\"/destinations\">{t(\"settings.openDelivery\")}</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 +1 @@
1
- {"version":3,"file":"thread-debug.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/thread-debug.tsx"],"names":[],"mappings":"AA8BA,wBAAgB,IAAI;;IAEnB;AAgYD,MAAM,CAAC,OAAO,UAAU,gBAAgB,oDAuRvC"}
1
+ {"version":3,"file":"thread-debug.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/thread-debug.tsx"],"names":[],"mappings":"AA+BA,wBAAgB,IAAI;;IAEnB;AAgYD,MAAM,CAAC,OAAO,UAAU,gBAAgB,oDAuRvC"}
@@ -1,5 +1,6 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { agentNativePath, useActionQuery } from "@agent-native/core/client";
2
+ import { agentNativePath } from "@agent-native/core/client/api-path";
3
+ import { useActionQuery } from "@agent-native/core/client/hooks";
3
4
  import { IconDatabase, IconFileSearch, IconRefresh, IconSearch, } from "@tabler/icons-react";
4
5
  import { useEffect, useMemo, useState } from "react";
5
6
  import { ActionQueryError } from "../../components/action-query-error.js";