@agent-native/dispatch 0.14.3 → 0.14.4

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 (127) hide show
  1. package/README.md +114 -128
  2. package/dist/actions/list_apps.d.ts +1 -0
  3. package/dist/actions/list_apps.js +16 -8
  4. package/dist/actions/list_apps.js.map +1 -1
  5. package/dist/actions/set-mcp-app-access.js +1 -4
  6. package/dist/actions/set-mcp-app-access.js.map +1 -1
  7. package/dist/components/action-query-error.d.ts +8 -0
  8. package/dist/components/action-query-error.d.ts.map +1 -0
  9. package/dist/components/action-query-error.js +10 -0
  10. package/dist/components/action-query-error.js.map +1 -0
  11. package/dist/components/app-keys-popover.d.ts +4 -0
  12. package/dist/components/app-keys-popover.d.ts.map +1 -1
  13. package/dist/components/app-keys-popover.js +26 -14
  14. package/dist/components/app-keys-popover.js.map +1 -1
  15. package/dist/components/dispatch-control-plane.d.ts.map +1 -1
  16. package/dist/components/dispatch-control-plane.js +31 -27
  17. package/dist/components/dispatch-control-plane.js.map +1 -1
  18. package/dist/components/index.d.ts +1 -0
  19. package/dist/components/index.d.ts.map +1 -1
  20. package/dist/components/index.js +1 -0
  21. package/dist/components/index.js.map +1 -1
  22. package/dist/components/layout/Layout.d.ts +1 -0
  23. package/dist/components/layout/Layout.d.ts.map +1 -1
  24. package/dist/components/layout/Layout.js +19 -21
  25. package/dist/components/layout/Layout.js.map +1 -1
  26. package/dist/components/ui/sheet.js +1 -1
  27. package/dist/components/ui/sheet.js.map +1 -1
  28. package/dist/components/ui/toast.js +1 -1
  29. package/dist/components/ui/toast.js.map +1 -1
  30. package/dist/components/workspace-app-card.d.ts.map +1 -1
  31. package/dist/components/workspace-app-card.js +8 -5
  32. package/dist/components/workspace-app-card.js.map +1 -1
  33. package/dist/components/workspace-resource-effective-stack.d.ts.map +1 -1
  34. package/dist/components/workspace-resource-effective-stack.js +6 -1
  35. package/dist/components/workspace-resource-effective-stack.js.map +1 -1
  36. package/dist/components/workspace-resource-impact-preview.d.ts.map +1 -1
  37. package/dist/components/workspace-resource-impact-preview.js +6 -1
  38. package/dist/components/workspace-resource-impact-preview.js.map +1 -1
  39. package/dist/routes/pages/$appId.d.ts.map +1 -1
  40. package/dist/routes/pages/$appId.js +6 -1
  41. package/dist/routes/pages/$appId.js.map +1 -1
  42. package/dist/routes/pages/agents.d.ts.map +1 -1
  43. package/dist/routes/pages/agents.js +5 -8
  44. package/dist/routes/pages/agents.js.map +1 -1
  45. package/dist/routes/pages/approval.d.ts.map +1 -1
  46. package/dist/routes/pages/approval.js +6 -1
  47. package/dist/routes/pages/approval.js.map +1 -1
  48. package/dist/routes/pages/approvals.d.ts.map +1 -1
  49. package/dist/routes/pages/approvals.js +8 -5
  50. package/dist/routes/pages/approvals.js.map +1 -1
  51. package/dist/routes/pages/apps.$appId.d.ts.map +1 -1
  52. package/dist/routes/pages/apps.$appId.js +4 -2
  53. package/dist/routes/pages/apps.$appId.js.map +1 -1
  54. package/dist/routes/pages/apps.d.ts.map +1 -1
  55. package/dist/routes/pages/apps.js +9 -3
  56. package/dist/routes/pages/apps.js.map +1 -1
  57. package/dist/routes/pages/audit.d.ts.map +1 -1
  58. package/dist/routes/pages/audit.js +4 -2
  59. package/dist/routes/pages/audit.js.map +1 -1
  60. package/dist/routes/pages/chat.d.ts.map +1 -1
  61. package/dist/routes/pages/chat.js +16 -2
  62. package/dist/routes/pages/chat.js.map +1 -1
  63. package/dist/routes/pages/destinations.d.ts.map +1 -1
  64. package/dist/routes/pages/destinations.js +5 -3
  65. package/dist/routes/pages/destinations.js.map +1 -1
  66. package/dist/routes/pages/identities.d.ts.map +1 -1
  67. package/dist/routes/pages/identities.js +5 -3
  68. package/dist/routes/pages/identities.js.map +1 -1
  69. package/dist/routes/pages/integrations.d.ts.map +1 -1
  70. package/dist/routes/pages/integrations.js +9 -3
  71. package/dist/routes/pages/integrations.js.map +1 -1
  72. package/dist/routes/pages/thread-debug.d.ts.map +1 -1
  73. package/dist/routes/pages/thread-debug.js +7 -6
  74. package/dist/routes/pages/thread-debug.js.map +1 -1
  75. package/dist/routes/pages/vault.d.ts.map +1 -1
  76. package/dist/routes/pages/vault.js +23 -7
  77. package/dist/routes/pages/vault.js.map +1 -1
  78. package/dist/routes/pages/workspace.d.ts.map +1 -1
  79. package/dist/routes/pages/workspace.js +9 -3
  80. package/dist/routes/pages/workspace.js.map +1 -1
  81. package/dist/server/lib/dispatch-store.d.ts.map +1 -1
  82. package/dist/server/lib/dispatch-store.js +2 -2
  83. package/dist/server/lib/dispatch-store.js.map +1 -1
  84. package/dist/server/lib/mcp-access-store.d.ts.map +1 -1
  85. package/dist/server/lib/mcp-access-store.js +30 -2
  86. package/dist/server/lib/mcp-access-store.js.map +1 -1
  87. package/dist/server/plugins/agent-chat.d.ts +1 -1
  88. package/package.json +2 -2
  89. package/src/actions/list_apps.spec.ts +52 -0
  90. package/src/actions/list_apps.ts +16 -8
  91. package/src/actions/set-mcp-app-access.spec.ts +73 -0
  92. package/src/actions/set-mcp-app-access.ts +1 -5
  93. package/src/components/action-query-error.spec.tsx +56 -0
  94. package/src/components/action-query-error.tsx +32 -0
  95. package/src/components/app-keys-popover.spec.tsx +85 -0
  96. package/src/components/app-keys-popover.tsx +76 -50
  97. package/src/components/dispatch-control-plane.spec.tsx +106 -0
  98. package/src/components/dispatch-control-plane.tsx +71 -115
  99. package/src/components/index.ts +1 -0
  100. package/src/components/layout/Layout.spec.tsx +42 -2
  101. package/src/components/layout/Layout.tsx +22 -27
  102. package/src/components/ui/sheet.tsx +1 -1
  103. package/src/components/ui/toast.tsx +1 -1
  104. package/src/components/workspace-app-card.spec.tsx +80 -0
  105. package/src/components/workspace-app-card.tsx +36 -25
  106. package/src/components/workspace-resource-effective-stack.tsx +13 -1
  107. package/src/components/workspace-resource-impact-preview.tsx +12 -1
  108. package/src/routes/pages/$appId.tsx +17 -1
  109. package/src/routes/pages/agents.tsx +24 -11
  110. package/src/routes/pages/approval.tsx +16 -4
  111. package/src/routes/pages/approvals.tsx +108 -89
  112. package/src/routes/pages/apps.$appId.tsx +9 -2
  113. package/src/routes/pages/apps.tsx +20 -7
  114. package/src/routes/pages/audit.tsx +29 -20
  115. package/src/routes/pages/chat.spec.tsx +94 -0
  116. package/src/routes/pages/chat.tsx +30 -10
  117. package/src/routes/pages/destinations.tsx +75 -62
  118. package/src/routes/pages/identities.tsx +74 -63
  119. package/src/routes/pages/integrations.tsx +17 -10
  120. package/src/routes/pages/thread-debug.tsx +18 -12
  121. package/src/routes/pages/vault.tsx +59 -26
  122. package/src/routes/pages/workspace.tsx +69 -55
  123. package/src/server/lib/approval-fencing.spec.ts +113 -2
  124. package/src/server/lib/dispatch-store.ts +2 -0
  125. package/src/server/lib/mcp-access-store.spec.ts +116 -4
  126. package/src/server/lib/mcp-access-store.ts +37 -2
  127. package/src/server/lib/mcp-gateway.spec.ts +79 -3
@@ -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 { 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 { data: catalog, isLoading } = useActionQuery(\n \"list-integrations-catalog\",\n {},\n );\n const { data: accessSettings } = useActionQuery(\n \"get-vault-access-settings\",\n {},\n );\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 {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 {!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":";AAAA,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EACL,SAAS,EACT,gBAAgB,EAChB,gBAAgB,EAChB,OAAO,EACP,QAAQ,EACR,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAE/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,MAAM,EACN,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,WAAW,GACZ,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EACL,OAAO,EACP,cAAc,EACd,cAAc,GACf,MAAM,6BAA6B,CAAC;AAErC,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAC,CAAC;AAC/C,CAAC;AAoCD,SAAS,oBAAoB,CAAC,GAAW,EAAE,KAAa;IACtD,MAAM,QAAQ,GAAG,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC,WAAW,EAAE,CAAC;IACjD,KAAK,MAAM,QAAQ,IAAI;QACrB,QAAQ;QACR,OAAO;QACP,UAAU;QACV,QAAQ;QACR,QAAQ;QACR,SAAS;QACT,MAAM;QACN,UAAU;QACV,WAAW;QACX,QAAQ;KACT,EAAE,CAAC;QACF,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,OAAO,QAAQ,CAAC;IACnD,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,aAAa,CAAC,EACrB,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,UAAU,GAMX;IACC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACvC,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAE5B,MAAM,YAAY,GAAG,iBAAiB,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC;IAClE,MAAM,WAAW,GAAG,iBAAiB,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC;IAChE,MAAM,SAAS,GAAG,iBAAiB,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;IAE7D,SAAS,KAAK;QACZ,QAAQ,CAAC,EAAE,CAAC,CAAC;IACf,CAAC;IAED,KAAK,UAAU,UAAU;QACvB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,KAAK,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;YACrC,OAAO;QACT,CAAC;QACD,IAAI,CAAC;YACH,uEAAuE;YACvE,sEAAsE;YACtE,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC;gBAC7C,aAAa,EAAE,OAAO,CAAC,GAAG;gBAC1B,IAAI,EAAE,OAAO,CAAC,KAAK;gBACnB,KAAK,EAAE,OAAO;gBACd,QAAQ,EAAE,oBAAoB,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC;aAC3D,CAAC,CAAC;YACH,MAAM,QAAQ,GACX,OAAwC,EAAE,MAAM,EAAE,EAAE;gBACpD,OAA2B,EAAE,EAAE,CAAC;YACnC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;YACnD,CAAC;YAED,8DAA8D;YAC9D,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;gBAC5B,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;gBAC5D,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;oBAC1B,IAAI,CAAC;wBACH,MAAM,WAAW,CAAC,WAAW,CAAC;4BAC5B,QAAQ;4BACR,KAAK,EAAE,GAAG,CAAC,KAAK;yBACjB,CAAC,CAAC;oBACL,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACb,OAAO,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,KAAK,SAAS,EAAE,GAAG,CAAC,CAAC;oBACpD,CAAC;gBACH,CAAC;YACH,CAAC;YACD,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;gBAC/B,IAAI,CAAC;oBACH,MAAM,SAAS,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;gBACpD,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,KAAK,SAAS,EAAE,GAAG,CAAC,CAAC;gBACnD,CAAC;YACH,CAAC;YAED,EAAE,CAAC,iBAAiB,CAAC;gBACnB,QAAQ,EAAE,CAAC,QAAQ,EAAE,2BAA2B,CAAC;aAClD,CAAC,CAAC;YACH,KAAK,CAAC,OAAO,CAAC,aAAa,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;YAC5C,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,KAAK,EAAE,CAAC;QACV,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,IAAI,2BAA2B,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GACX,YAAY,CAAC,SAAS,IAAI,WAAW,CAAC,SAAS,IAAI,SAAS,CAAC,SAAS,CAAC;IAEzE,OAAO,CACL,KAAC,MAAM,IACL,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE;YACrB,IAAI,CAAC,IAAI;gBAAE,KAAK,EAAE,CAAC;YACnB,YAAY,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC,YAED,MAAC,aAAa,eACZ,MAAC,YAAY,eACX,MAAC,WAAW,2BAAU,OAAO,CAAC,KAAK,IAAe,EAClD,MAAC,iBAAiB,0BACR,GAAG,EACV,OAAO,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;oCACxB,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO;oCACzB,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,OAAO,6EAGf,IACP,EACf,eAAK,SAAS,EAAC,WAAW,aACxB,0BACE,KAAC,KAAK,IAAC,SAAS,EAAC,+BAA+B,oBAAY,EAC5D,cAAK,SAAS,EAAC,mBAAmB,YAAE,OAAO,CAAC,GAAG,GAAO,IAClD,EACN,0BACE,KAAC,KAAK,IAAC,OAAO,EAAC,iBAAiB,sBAAc,EAC9C,KAAC,KAAK,IACJ,EAAE,EAAC,iBAAiB,EACpB,IAAI,EAAC,UAAU,EACf,YAAY,EAAC,KAAK,EAClB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACzC,WAAW,EAAE,cAAc,OAAO,CAAC,KAAK,OAAO,EAC/C,SAAS,SACT,IACE,IACF,EACN,MAAC,YAAY,eACX,KAAC,MAAM,IACL,OAAO,EAAC,SAAS,EACjB,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,EAClC,QAAQ,EAAE,OAAO,uBAGV,EACT,KAAC,MAAM,IAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,YAC5D,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,GACzB,IACI,IACD,GACT,CACV,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,EACrB,OAAO,EACP,UAAU,GAIX;IACC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAC3D,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;IAErC,OAAO,CACL,8BACE,kBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAC5B,SAAS,EAAC,sJAAsJ,aAEhK,eAAK,SAAS,EAAC,+CAA+C,aAC5D,cAAK,SAAS,EAAC,8DAA8D,YAC3E,KAAC,OAAO,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,uBAAuB,GAAG,GACnD,EACL,WAAW,CAAC,CAAC,CAAC,CACb,MAAC,KAAK,IACJ,OAAO,EAAC,WAAW,EACnB,SAAS,EAAC,0DAA0D,aAEpE,KAAC,SAAS,IAAC,IAAI,EAAE,EAAE,GAAI,iBAEjB,CACT,CAAC,CAAC,CAAC,CACF,MAAC,KAAK,IACJ,OAAO,EAAC,WAAW,EACnB,SAAS,EAAC,0DAA0D,aAEpE,KAAC,gBAAgB,IAAC,IAAI,EAAE,EAAE,GAAI,eAExB,CACT,IACG,EACN,eAAK,SAAS,EAAC,gBAAgB,aAC7B,MAAC,OAAO,eACN,KAAC,cAAc,IAAC,OAAO,kBACrB,cAAK,SAAS,EAAC,gDAAgD,YAC5D,OAAO,CAAC,KAAK,GACV,GACS,EACjB,KAAC,cAAc,cAAE,OAAO,CAAC,KAAK,GAAkB,IACxC,EACV,cAAK,SAAS,EAAC,qDAAqD,YACjE,OAAO,CAAC,GAAG,GACR,IACF,EACN,eAAK,SAAS,EAAC,+BAA+B,yBACnC,QAAQ,OAAG,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,IAC/C,IACC,EACT,KAAC,aAAa,IACZ,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,OAAO,EACrB,UAAU,EAAE,UAAU,GACtB,IACD,CACJ,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,EAAE,GAAG,EAAuB;IACnD,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;IAC9C,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC;IACvE,OAAO,CACL,eAAK,SAAS,EAAC,yEAAyE,aACtF,eAAK,SAAS,EAAC,iCAAiC,aAC9C,cACE,SAAS,EAAC,4FAA4F,EACtG,KAAK,EAAE,EAAE,eAAe,EAAE,GAAG,CAAC,KAAK,EAAE,YAEpC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAChC,EACN,eAAM,SAAS,EAAC,kBAAkB,YAAE,GAAG,CAAC,OAAO,GAAQ,EACtD,CAAC,GAAG,CAAC,SAAS,IAAI,CACjB,eAAM,SAAS,EAAC,+BAA+B,wBAAe,CAC/D,IACG,EACN,eAAM,SAAS,EAAC,+BAA+B,YAC5C,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,KAAK,EAAE,GAC9C,IACH,CACP,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,gBAAgB;IACtC,MAAM,YAAY,GAAG,cAAc,CAAC,2BAA2B,EAAE,EAAE,CAAC,CAAC;IACrE,MAAM,WAAW,GAAG,cAAc,CAAC,2BAA2B,EAAE,EAAE,CAAC,CAAC;IACpE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,YAAY,CAAC;IAClD,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,WAAW,CAAC;IAC7C,MAAM,IAAI,GAAI,OAAwB,IAAI,EAAE,CAAC;IAC7C,MAAM,UAAU,GACb,cAAsB,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;IAErE,MAAM,QAAQ,GAAG,OAAO,CAAY,GAAG,EAAE;QACvC,MAAM,GAAG,GAAG,IAAI,GAAG,EAAmB,CAAC;QACvC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,YAAY,IAAI,EAAE,EAAE,CAAC;gBAC1C,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;oBACvB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE;wBAChB,GAAG,EAAE,IAAI,CAAC,GAAG;wBACb,KAAK,EAAE,IAAI,CAAC,KAAK;wBACjB,IAAI,EAAE,EAAE;qBACT,CAAC,CAAC;gBACL,CAAC;gBACD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAE,CAAC,IAAI,CAAC,IAAI,CAAC;oBAC3B,KAAK,EAAE,GAAG,CAAC,KAAK;oBAChB,OAAO,EAAE,GAAG,CAAC,OAAO;oBACpB,KAAK,EAAE,GAAG,CAAC,KAAK;oBAChB,UAAU,EAAE,IAAI,CAAC,UAAU;oBAC3B,YAAY,EAAE,IAAI,CAAC,YAAY;oBAC/B,aAAa,EAAE,IAAI,CAAC,aAAa;iBAClC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAC5C,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAC/B,CAAC;IACJ,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;IAC5E,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;IAE3E,OAAO,CACL,MAAC,aAAa,IACZ,KAAK,EAAC,aAAa,EACnB,WAAW,EAAC,2EAA2E,aAEtF,YAAY,CAAC,OAAO,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAC7C,KAAC,gBAAgB,IACf,KAAK,EAAE,YAAY,CAAC,KAAK,IAAI,WAAW,CAAC,KAAK,EAC9C,OAAO,EAAE,GAAG,EAAE;oBACZ,KAAK,YAAY,CAAC,OAAO,EAAE,CAAC;oBAC5B,KAAK,WAAW,CAAC,OAAO,EAAE,CAAC;gBAC7B,CAAC,GACD,CACH,CAAC,CAAC,CAAC,IAAI,EAEP,CAAC,YAAY,CAAC,OAAO,IAAI,SAAS,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAC9D,cAAK,SAAS,EAAC,uFAAuF,uDAEhG,CACP,EAEA,CAAC,YAAY,CAAC,OAAO,IAAI,CAAC,SAAS,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAC/D,cAAK,SAAS,EAAC,uFAAuF,sEAEhG,CACP,EAEA,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,CACvB,8BACE,eAAK,SAAS,EAAC,0CAA0C,aACvD,aAAI,SAAS,EAAC,qCAAqC,qCAE9C,EACL,eAAM,SAAS,EAAC,+BAA+B,YAC5C,SAAS,CAAC,MAAM,GACZ,IACH,EACN,cAAK,SAAS,EAAC,0CAA0C,YACtD,SAAS,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAC1B,KAAC,aAAa,IAEZ,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,UAAU,IAFjB,OAAO,CAAC,GAAG,CAGhB,CACH,CAAC,GACE,IACE,CACX,EAEA,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,CACvB,8BACE,eAAK,SAAS,EAAC,+CAA+C,aAC5D,aAAI,SAAS,EAAC,qCAAqC,0BAAe,EAClE,eAAM,SAAS,EAAC,+BAA+B,YAC5C,SAAS,CAAC,MAAM,GACZ,IACH,EACN,cAAK,SAAS,EAAC,0CAA0C,YACtD,SAAS,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAC1B,KAAC,aAAa,IAEZ,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,UAAU,IAFjB,OAAO,CAAC,GAAG,CAGhB,CACH,CAAC,GACE,IACE,CACX,EAEA,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,CAClB,MAAC,WAAW,IAAC,SAAS,EAAC,iCAAiC,aACtD,MAAC,kBAAkB,IAAC,SAAS,EAAC,kEAAkE,aAC9F,gBAAM,SAAS,EAAC,+CAA+C,aAC7D,KAAC,iBAAiB,IAAC,IAAI,EAAE,EAAE,GAAI,sBAE1B,EACP,KAAC,gBAAgB,IACf,IAAI,EAAE,EAAE,EACR,SAAS,EAAC,oEAAoE,GAC9E,IACiB,EACrB,MAAC,kBAAkB,eACjB,cAAK,SAAS,EAAC,UAAU,YACtB,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACjB,KAAC,eAAe,IAAiB,GAAG,EAAE,GAAG,IAAnB,GAAG,CAAC,KAAK,CAAc,CAC9C,CAAC,GACE,EACN,eAAK,SAAS,EAAC,0FAA0F,aACvG,KAAC,QAAQ,IAAC,IAAI,EAAE,EAAE,GAAI,EACtB,YAAG,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAC,iBAAiB,gDAExC,IACA,IACa,IACT,CACf,IACa,CACjB,CAAC;AACJ,CAAC","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 +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,oDAiRvC"}
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"}
@@ -2,8 +2,8 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
2
2
  import { agentNativePath, useActionQuery } from "@agent-native/core/client";
3
3
  import { IconDatabase, IconFileSearch, IconRefresh, IconSearch, } from "@tabler/icons-react";
4
4
  import { useEffect, useMemo, useState } from "react";
5
+ import { ActionQueryError } from "../../components/action-query-error.js";
5
6
  import { DispatchShell } from "../../components/dispatch-shell.js";
6
- import { Alert, AlertDescription, AlertTitle } from "../../components/ui/alert.js";
7
7
  import { Badge } from "../../components/ui/badge.js";
8
8
  import { Button } from "../../components/ui/button.js";
9
9
  import { Input } from "../../components/ui/input.js";
@@ -100,7 +100,8 @@ export default function ThreadDebugRoute() {
100
100
  ownerEmail: "",
101
101
  });
102
102
  const [selected, setSelected] = useState(null);
103
- const { data: sourcesData, isLoading: sourcesLoading } = useActionQuery("list-agent-thread-sources", {});
103
+ const sourcesQuery = useActionQuery("list-agent-thread-sources", {});
104
+ const { data: sourcesData, isLoading: sourcesLoading } = sourcesQuery;
104
105
  const sources = sourcesData?.sources ?? [];
105
106
  const searchParams = useMemo(() => ({
106
107
  sourceId: submittedSearch.sourceId,
@@ -118,7 +119,7 @@ export default function ThreadDebugRoute() {
118
119
  maxEvents: 800,
119
120
  maxTraceSpans: 600,
120
121
  }), [selected]);
121
- const { data: detail, isLoading: detailLoading, error: detailError, } = useActionQuery("get-agent-thread-debug", detailParams, {
122
+ const { data: detail, isLoading: detailLoading, error: detailError, refetch: refetchDetail, } = useActionQuery("get-agent-thread-debug", detailParams, {
122
123
  enabled: Boolean(selected?.threadId),
123
124
  });
124
125
  const selectedSource = sources.find((source) => source.id === sourceId);
@@ -139,7 +140,7 @@ export default function ThreadDebugRoute() {
139
140
  }),
140
141
  }).catch(() => { });
141
142
  }, [ownerEmail, query, selected?.threadId, sourceId, threadId]);
142
- return (_jsx(DispatchShell, { title: "Thread Debug", description: "Inspect persisted agent chat threads, run events, and AI internals.", children: _jsxs("div", { className: "space-y-4", children: [_jsxs("section", { className: "rounded-lg border bg-card p-4", children: [_jsxs("div", { className: "grid gap-3 lg:grid-cols-[220px_1fr_260px_auto]", children: [_jsxs(Select, { value: sourceId, onValueChange: setSourceId, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: "Source" }) }), _jsxs(SelectContent, { children: [sources.map((source) => (_jsx(SelectItem, { value: source.id, children: source.label }, source.id))), sources.length === 0 ? (_jsx(SelectItem, { value: "current", children: "Current Dispatch DB" })) : null] })] }), _jsx(Input, { value: query, onChange: (event) => setQuery(event.target.value), placeholder: "Search title, preview, messages, tools" }), _jsx(Input, { value: ownerEmail, onChange: (event) => setOwnerEmail(event.target.value), placeholder: "Owner email" }), _jsxs(Button, { type: "button", onClick: () => setSubmittedSearch({
143
+ return (_jsx(DispatchShell, { title: "Thread Debug", description: "Inspect persisted agent chat threads, run events, and AI internals.", children: _jsxs("div", { className: "space-y-4", children: [sourcesQuery.isError ? (_jsx(ActionQueryError, { error: sourcesQuery.error, onRetry: () => void sourcesQuery.refetch() })) : null, _jsxs("section", { className: "rounded-lg border bg-card p-4", children: [_jsxs("div", { className: "grid gap-3 lg:grid-cols-[220px_1fr_260px_auto]", children: [_jsxs(Select, { value: sourceId, onValueChange: setSourceId, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: "Source" }) }), _jsxs(SelectContent, { children: [sources.map((source) => (_jsx(SelectItem, { value: source.id, children: source.label }, source.id))), sources.length === 0 ? (_jsx(SelectItem, { value: "current", children: "Current Dispatch DB" })) : null] })] }), _jsx(Input, { value: query, onChange: (event) => setQuery(event.target.value), placeholder: "Search title, preview, messages, tools" }), _jsx(Input, { value: ownerEmail, onChange: (event) => setOwnerEmail(event.target.value), placeholder: "Owner email" }), _jsxs(Button, { type: "button", onClick: () => setSubmittedSearch({
143
144
  sourceId,
144
145
  query: query.trim(),
145
146
  ownerEmail: ownerEmail.trim(),
@@ -152,10 +153,10 @@ export default function ThreadDebugRoute() {
152
153
  threadId: trimmed,
153
154
  ownerEmail: ownerEmail.trim() || undefined,
154
155
  });
155
- }, children: [_jsx(IconFileSearch, { size: 16 }), "Inspect"] })] }), _jsxs("div", { className: "mt-3 flex flex-wrap items-center gap-2 text-xs text-muted-foreground", children: [sourcesLoading ? _jsx(Skeleton, { className: "h-5 w-32" }) : null, selectedSource ? _jsx(SourceBadge, { source: selectedSource }) : null, selectedSource?.databaseUrlEnv ? (_jsx(Badge, { variant: "outline", className: "font-mono", children: selectedSource.databaseUrlEnv })) : null, sourcesData?.access ? (_jsxs("span", { children: [sourcesData.access.viewerEmail, " \u00B7", " ", sourcesData.access.canInspectAll ? "admin scope" : "own scope"] })) : null] })] }), searchError ? (_jsxs(Alert, { variant: "destructive", children: [_jsx(AlertTitle, { children: "Search failed" }), _jsx(AlertDescription, { children: String(searchError.message) })] })) : null, _jsxs("div", { className: "grid gap-4 xl:grid-cols-[380px_1fr]", children: [_jsxs("section", { className: "min-h-[520px] rounded-lg border bg-card", children: [_jsxs("div", { className: "flex items-center justify-between border-b px-4 py-3", children: [_jsxs("div", { children: [_jsx("div", { className: "text-sm font-semibold text-foreground", children: "Threads" }), _jsxs("div", { className: "text-xs text-muted-foreground", children: [searchData?.count ?? 0, " results \u00B7", " ", searchData?.access?.scope ?? "current scope"] })] }), _jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => refetchSearch(), "aria-label": "Refresh threads", children: _jsx(IconRefresh, { size: 16 }) })] }), _jsxs("div", { className: "max-h-[760px] space-y-2 overflow-auto p-3", children: [searchLoading ? (_jsxs(_Fragment, { children: [_jsx(Skeleton, { className: "h-28 w-full rounded-lg" }), _jsx(Skeleton, { className: "h-28 w-full rounded-lg" }), _jsx(Skeleton, { className: "h-28 w-full rounded-lg" })] })) : null, !searchLoading && searchThreads.length === 0 ? (_jsxs("div", { className: "flex min-h-64 flex-col items-center justify-center rounded-lg border border-dashed px-4 text-center text-sm text-muted-foreground", children: [_jsx(IconDatabase, { className: "mb-2 h-5 w-5" }), "No threads found."] })) : null, searchThreads.map((result) => (_jsx(ResultCard, { result: result, selected: selected?.threadId === result.id, onSelect: () => setSelected({
156
+ }, children: [_jsx(IconFileSearch, { size: 16 }), "Inspect"] })] }), _jsxs("div", { className: "mt-3 flex flex-wrap items-center gap-2 text-xs text-muted-foreground", children: [sourcesLoading ? _jsx(Skeleton, { className: "h-5 w-32" }) : null, selectedSource ? _jsx(SourceBadge, { source: selectedSource }) : null, selectedSource?.databaseUrlEnv ? (_jsx(Badge, { variant: "outline", className: "font-mono", children: selectedSource.databaseUrlEnv })) : null, sourcesData?.access ? (_jsxs("span", { children: [sourcesData.access.viewerEmail, " \u00B7", " ", sourcesData.access.canInspectAll ? "admin scope" : "own scope"] })) : null] })] }), searchError ? (_jsx(ActionQueryError, { error: searchError, onRetry: () => void refetchSearch() })) : null, _jsxs("div", { className: "grid gap-4 xl:grid-cols-[380px_1fr]", children: [_jsxs("section", { className: "min-h-[520px] rounded-lg border bg-card", children: [_jsxs("div", { className: "flex items-center justify-between border-b px-4 py-3", children: [_jsxs("div", { children: [_jsx("div", { className: "text-sm font-semibold text-foreground", children: "Threads" }), _jsxs("div", { className: "text-xs text-muted-foreground", children: [searchData?.count ?? 0, " results \u00B7", " ", searchData?.access?.scope ?? "current scope"] })] }), _jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: () => refetchSearch(), "aria-label": "Refresh threads", children: _jsx(IconRefresh, { size: 16 }) })] }), _jsxs("div", { className: "max-h-[760px] space-y-2 overflow-auto p-3", children: [searchLoading ? (_jsxs(_Fragment, { children: [_jsx(Skeleton, { className: "h-28 w-full rounded-lg" }), _jsx(Skeleton, { className: "h-28 w-full rounded-lg" }), _jsx(Skeleton, { className: "h-28 w-full rounded-lg" })] })) : null, !searchLoading && searchThreads.length === 0 ? (_jsxs("div", { className: "flex min-h-64 flex-col items-center justify-center rounded-lg border border-dashed px-4 text-center text-sm text-muted-foreground", children: [_jsx(IconDatabase, { className: "mb-2 h-5 w-5" }), "No threads found."] })) : null, searchThreads.map((result) => (_jsx(ResultCard, { result: result, selected: selected?.threadId === result.id, onSelect: () => setSelected({
156
157
  sourceId: submittedSearch.sourceId,
157
158
  threadId: result.id,
158
159
  ownerEmail: submittedSearch.ownerEmail || undefined,
159
- }) }, result.id)))] })] }), _jsxs("section", { className: "min-w-0", children: [detailError ? (_jsxs(Alert, { variant: "destructive", children: [_jsx(AlertTitle, { children: "Thread lookup failed" }), _jsx(AlertDescription, { children: String(detailError.message) })] })) : null, detailLoading ? (_jsxs("div", { className: "rounded-lg border bg-card p-4", children: [_jsx(Skeleton, { className: "h-6 w-72" }), _jsx(Skeleton, { className: "mt-3 h-4 w-96" }), _jsx(Skeleton, { className: "mt-6 h-[520px] w-full" })] })) : detail ? (_jsx(ThreadDetail, { detail: detail })) : (_jsxs("div", { className: "flex min-h-[520px] flex-col items-center justify-center rounded-lg border border-dashed bg-card px-4 text-center text-sm text-muted-foreground", children: [_jsx(IconFileSearch, { className: "mb-2 h-5 w-5" }), "Select or inspect a thread."] }))] })] })] }) }));
160
+ }) }, result.id)))] })] }), _jsxs("section", { className: "min-w-0", children: [detailError ? (_jsx(ActionQueryError, { error: detailError, onRetry: () => void refetchDetail() })) : null, detailLoading ? (_jsxs("div", { className: "rounded-lg border bg-card p-4", children: [_jsx(Skeleton, { className: "h-6 w-72" }), _jsx(Skeleton, { className: "mt-3 h-4 w-96" }), _jsx(Skeleton, { className: "mt-6 h-[520px] w-full" })] })) : detail ? (_jsx(ThreadDetail, { detail: detail })) : (_jsxs("div", { className: "flex min-h-[520px] flex-col items-center justify-center rounded-lg border border-dashed bg-card px-4 text-center text-sm text-muted-foreground", children: [_jsx(IconFileSearch, { className: "mb-2 h-5 w-5" }), "Select or inspect a thread."] }))] })] })] }) }));
160
161
  }
161
162
  //# sourceMappingURL=thread-debug.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"thread-debug.js","sourceRoot":"","sources":["../../../src/routes/pages/thread-debug.tsx"],"names":[],"mappings":"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","sourcesContent":["import { agentNativePath, useActionQuery } from \"@agent-native/core/client\";\nimport {\n IconDatabase,\n IconFileSearch,\n IconRefresh,\n IconSearch,\n} from \"@tabler/icons-react\";\nimport { useEffect, useMemo, useState } 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 { Input } from \"../../components/ui/input\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../components/ui/select\";\nimport { Skeleton } from \"../../components/ui/skeleton\";\nimport {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"../../components/ui/tabs\";\nimport { cn } from \"../../lib/utils\";\n\nexport function meta() {\n return [{ title: \"Thread Debug — Dispatch\" }];\n}\n\ninterface ThreadDebugSource {\n id: string;\n label: string;\n kind: \"current\" | \"env\" | \"configured\";\n current: boolean;\n connected: boolean;\n databaseUrlEnv: string | null;\n databaseAuthTokenEnv: string | null;\n canInspectAll: boolean;\n}\n\ninterface ThreadSearchResult {\n id: string;\n ownerEmail: string;\n title: string;\n preview: string;\n messageCount: number;\n createdAt: number;\n updatedAt: number;\n snippet: string;\n}\n\ninterface ThreadMessage {\n index: number;\n id: string | null;\n role: string;\n createdAt: string | number | null;\n status: unknown;\n text: string;\n contentParts: any[];\n attachments: any[];\n metadata: unknown;\n}\n\ninterface ThreadRun {\n id: string;\n status: string;\n abortReason: string | null;\n startedAt: number;\n completedAt: number | null;\n heartbeatAt: number | null;\n events: Array<{ seq: number; event: any; rawEventData: string }>;\n}\n\ninterface ThreadDebugResponse {\n source: {\n id: string;\n label: string;\n kind: string;\n databaseUrlEnv: string | null;\n };\n access: { viewerEmail: string; scope: string; canInspectAll: boolean };\n thread: ThreadSearchResult;\n messages: ThreadMessage[];\n debug: any;\n debugRuns: any[];\n queuedMessages: any[];\n threadData: any;\n rawThreadData: string;\n runs: ThreadRun[];\n traces: { summaries: any[]; spans: any[] };\n feedback: any[];\n satisfaction: any[];\n evals: any[];\n checkpoints: any[];\n}\n\nfunction formatDate(value: number | string | null | undefined): string {\n if (value == null || value === \"\") return \"n/a\";\n const numeric = Number(value);\n const date = Number.isFinite(numeric) ? new Date(numeric) : new Date(value);\n if (Number.isNaN(date.getTime())) return \"n/a\";\n return date.toLocaleString();\n}\n\nfunction json(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n\nfunction eventLabel(event: any): string {\n if (!event || typeof event !== \"object\") return \"event\";\n if (event.type === \"tool_start\") return `tool_start · ${event.tool}`;\n if (event.type === \"tool_done\") return `tool_done · ${event.tool}`;\n if (event.type === \"text\") return \"text\";\n if (event.type === \"error\") return `error · ${event.errorCode ?? \"agent\"}`;\n return String(event.type ?? \"event\");\n}\n\nfunction messageTitle(message: ThreadMessage): string {\n const role = message.role || \"unknown\";\n return `${role.charAt(0).toUpperCase()}${role.slice(1)} ${message.index + 1}`;\n}\n\nfunction toolParts(message: ThreadMessage): any[] {\n return message.contentParts.filter((part) => part?.type === \"tool-call\");\n}\n\nfunction RawBlock({\n value,\n className,\n}: {\n value: unknown;\n className?: string;\n}) {\n return (\n <pre\n className={cn(\n \"max-h-[520px] overflow-auto rounded-lg border bg-muted/30 p-3 text-xs leading-relaxed text-foreground\",\n \"whitespace-pre-wrap break-words\",\n className,\n )}\n >\n {typeof value === \"string\" ? value : json(value)}\n </pre>\n );\n}\n\nfunction SourceBadge({ source }: { source: ThreadDebugSource }) {\n return (\n <Badge variant={source.current ? \"default\" : \"secondary\"}>\n {source.current ? \"current\" : source.kind}\n </Badge>\n );\n}\n\nfunction ResultCard({\n result,\n selected,\n onSelect,\n}: {\n result: ThreadSearchResult;\n selected: boolean;\n onSelect: () => void;\n}) {\n return (\n <button\n type=\"button\"\n onClick={onSelect}\n className={cn(\n \"w-full rounded-lg border px-3 py-3 text-left transition-colors\",\n selected\n ? \"border-foreground bg-muted\"\n : \"bg-card hover:border-foreground/30 hover:bg-muted/40\",\n )}\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"truncate text-sm font-medium text-foreground\">\n {result.title || result.preview || result.id}\n </div>\n <div className=\"mt-1 truncate font-mono text-[11px] text-muted-foreground\">\n {result.id}\n </div>\n </div>\n <Badge variant=\"outline\" className=\"shrink-0\">\n {result.messageCount}\n </Badge>\n </div>\n <div className=\"mt-2 line-clamp-3 text-xs leading-relaxed text-muted-foreground\">\n {result.snippet || result.preview || \"No preview\"}\n </div>\n <div className=\"mt-2 flex items-center justify-between gap-3 text-[11px] text-muted-foreground\">\n <span className=\"truncate\">{result.ownerEmail}</span>\n <span className=\"shrink-0\">{formatDate(result.updatedAt)}</span>\n </div>\n </button>\n );\n}\n\nfunction MessageBlock({ message }: { message: ThreadMessage }) {\n const tools = toolParts(message);\n return (\n <div className=\"rounded-lg border bg-card\">\n <div className=\"flex flex-wrap items-center justify-between gap-2 border-b px-3 py-2\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <Badge\n variant={message.role === \"assistant\" ? \"default\" : \"secondary\"}\n >\n {message.role}\n </Badge>\n <span className=\"truncate text-sm font-medium text-foreground\">\n {messageTitle(message)}\n </span>\n </div>\n <div className=\"flex items-center gap-2 text-[11px] text-muted-foreground\">\n {message.attachments.length > 0 ? (\n <Badge variant=\"outline\">{message.attachments.length} files</Badge>\n ) : null}\n <span>{formatDate(message.createdAt)}</span>\n </div>\n </div>\n <div className=\"space-y-3 px-3 py-3\">\n {message.text ? (\n <div className=\"whitespace-pre-wrap break-words text-sm leading-relaxed text-foreground\">\n {message.text}\n </div>\n ) : (\n <div className=\"text-sm text-muted-foreground\">No text content</div>\n )}\n {tools.length > 0 ? (\n <div className=\"space-y-2\">\n {tools.map((tool, index) => (\n <details\n key={`${message.id ?? message.index}-tool-${index}`}\n className=\"rounded-md border bg-muted/30 px-3 py-2\"\n >\n <summary className=\"cursor-pointer text-xs font-medium text-foreground\">\n {tool.toolName ?? tool.name ?? \"tool-call\"}\n </summary>\n <RawBlock value={tool} className=\"mt-2 max-h-72\" />\n </details>\n ))}\n </div>\n ) : null}\n </div>\n </div>\n );\n}\n\nfunction ThreadDetail({ detail }: { detail: ThreadDebugResponse }) {\n const rawBundle = useMemo(\n () => ({\n thread: detail.thread,\n debug: detail.debug,\n debugRuns: detail.debugRuns,\n queuedMessages: detail.queuedMessages,\n threadData: detail.threadData,\n runs: detail.runs,\n traces: detail.traces,\n feedback: detail.feedback,\n satisfaction: detail.satisfaction,\n evals: detail.evals,\n checkpoints: detail.checkpoints,\n }),\n [detail],\n );\n\n return (\n <div className=\"rounded-lg border bg-card\">\n <div className=\"border-b px-4 py-3\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"truncate text-base font-semibold text-foreground\">\n {detail.thread.title || detail.thread.preview || detail.thread.id}\n </div>\n <div className=\"mt-1 truncate font-mono text-xs text-muted-foreground\">\n {detail.thread.id}\n </div>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant=\"secondary\">{detail.messages.length} messages</Badge>\n <Badge variant=\"secondary\">{detail.runs.length} runs</Badge>\n <Badge variant=\"outline\">{detail.source.label}</Badge>\n </div>\n </div>\n <div className=\"mt-3 grid gap-2 text-xs text-muted-foreground sm:grid-cols-3\">\n <div className=\"truncate\">Owner: {detail.thread.ownerEmail}</div>\n <div>Created: {formatDate(detail.thread.createdAt)}</div>\n <div>Updated: {formatDate(detail.thread.updatedAt)}</div>\n </div>\n </div>\n\n <Tabs defaultValue=\"transcript\" className=\"p-4\">\n <TabsList>\n <TabsTrigger value=\"transcript\">Transcript</TabsTrigger>\n <TabsTrigger value=\"runs\">Runs</TabsTrigger>\n <TabsTrigger value=\"internals\">Internals</TabsTrigger>\n <TabsTrigger value=\"raw\">Raw</TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"transcript\" className=\"mt-4 space-y-3\">\n {detail.messages.length > 0 ? (\n detail.messages.map((message) => (\n <MessageBlock\n key={message.id ?? `message-${message.index}`}\n message={message}\n />\n ))\n ) : (\n <div className=\"rounded-lg border border-dashed px-4 py-8 text-center text-sm text-muted-foreground\">\n No persisted messages.\n </div>\n )}\n </TabsContent>\n\n <TabsContent value=\"runs\" className=\"mt-4 space-y-3\">\n {detail.runs.length > 0 ? (\n detail.runs.map((run) => (\n <details key={run.id} className=\"rounded-lg border bg-card\">\n <summary className=\"cursor-pointer px-4 py-3\">\n <div className=\"inline-flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\">{run.status}</Badge>\n <span className=\"font-mono text-xs text-foreground\">\n {run.id}\n </span>\n <span className=\"text-xs text-muted-foreground\">\n {formatDate(run.startedAt)}\n </span>\n </div>\n </summary>\n <div className=\"space-y-2 border-t px-4 py-3\">\n {run.events.map((event) => (\n <details\n key={`${run.id}-${event.seq}`}\n className=\"rounded-md border bg-muted/30 px-3 py-2\"\n >\n <summary className=\"cursor-pointer text-xs font-medium text-foreground\">\n #{event.seq} {eventLabel(event.event)}\n </summary>\n <RawBlock value={event.event} className=\"mt-2 max-h-72\" />\n </details>\n ))}\n {run.events.length === 0 ? (\n <div className=\"text-sm text-muted-foreground\">\n No retained run events.\n </div>\n ) : null}\n </div>\n </details>\n ))\n ) : (\n <div className=\"rounded-lg border border-dashed px-4 py-8 text-center text-sm text-muted-foreground\">\n No retained runs.\n </div>\n )}\n </TabsContent>\n\n <TabsContent value=\"internals\" className=\"mt-4 space-y-4\">\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <div>\n <div className=\"mb-2 text-sm font-medium text-foreground\">\n Debug Runs\n </div>\n <RawBlock\n value={\n detail.debugRuns.length > 0\n ? detail.debugRuns\n : (detail.debug ?? {})\n }\n />\n </div>\n <div>\n <div className=\"mb-2 text-sm font-medium text-foreground\">\n Trace Summaries\n </div>\n <RawBlock value={detail.traces.summaries} />\n </div>\n <div>\n <div className=\"mb-2 text-sm font-medium text-foreground\">\n Trace Spans\n </div>\n <RawBlock value={detail.traces.spans} />\n </div>\n <div>\n <div className=\"mb-2 text-sm font-medium text-foreground\">\n Feedback And Evals\n </div>\n <RawBlock\n value={{\n feedback: detail.feedback,\n satisfaction: detail.satisfaction,\n evals: detail.evals,\n checkpoints: detail.checkpoints,\n }}\n />\n </div>\n </div>\n </TabsContent>\n\n <TabsContent value=\"raw\" className=\"mt-4 space-y-4\">\n <RawBlock value={rawBundle} />\n <RawBlock value={detail.rawThreadData} />\n </TabsContent>\n </Tabs>\n </div>\n );\n}\n\nexport default function ThreadDebugRoute() {\n const [sourceId, setSourceId] = useState(\"current\");\n const [query, setQuery] = useState(\"\");\n const [ownerEmail, setOwnerEmail] = useState(\"\");\n const [threadId, setThreadId] = useState(\"\");\n const [submittedSearch, setSubmittedSearch] = useState({\n sourceId: \"current\",\n query: \"\",\n ownerEmail: \"\",\n });\n const [selected, setSelected] = useState<{\n sourceId: string;\n threadId: string;\n ownerEmail?: string;\n } | null>(null);\n\n const { data: sourcesData, isLoading: sourcesLoading } = useActionQuery<{\n access: {\n viewerEmail: string;\n orgId: string | null;\n role: string | null;\n envAdmin: boolean;\n canInspectAll: boolean;\n memberCount: number;\n };\n sources: ThreadDebugSource[];\n }>(\"list-agent-thread-sources\", {});\n\n const sources: ThreadDebugSource[] = sourcesData?.sources ?? [];\n const searchParams = useMemo(\n () => ({\n sourceId: submittedSearch.sourceId,\n query: submittedSearch.query || undefined,\n ownerEmail: submittedSearch.ownerEmail || undefined,\n limit: 25,\n }),\n [submittedSearch],\n );\n const {\n data: searchData,\n isLoading: searchLoading,\n error: searchError,\n refetch: refetchSearch,\n } = useActionQuery<{\n count: number;\n threads: ThreadSearchResult[];\n access: { scope: string; canInspectAll: boolean };\n source: { id: string; label: string };\n }>(\"search-agent-threads\", searchParams);\n const searchThreads: ThreadSearchResult[] = searchData?.threads ?? [];\n\n const detailParams = useMemo(\n () => ({\n sourceId: selected?.sourceId ?? \"current\",\n threadId: selected?.threadId ?? \"\",\n ownerEmail: selected?.ownerEmail,\n maxRuns: 20,\n maxEvents: 800,\n maxTraceSpans: 600,\n }),\n [selected],\n );\n const {\n data: detail,\n isLoading: detailLoading,\n error: detailError,\n } = useActionQuery<ThreadDebugResponse>(\n \"get-agent-thread-debug\",\n detailParams,\n {\n enabled: Boolean(selected?.threadId),\n },\n );\n\n const selectedSource = sources.find((source) => source.id === sourceId);\n\n useEffect(() => {\n fetch(agentNativePath(\"/_agent-native/application-state/navigation\"), {\n method: \"PUT\",\n keepalive: true,\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n view: \"thread-debug\",\n path:\n typeof window === \"undefined\"\n ? \"/thread-debug\"\n : window.location.pathname,\n sourceId,\n query,\n ownerEmail: ownerEmail.trim() || undefined,\n threadId: selected?.threadId ?? (threadId.trim() || undefined),\n }),\n }).catch(() => {});\n }, [ownerEmail, query, selected?.threadId, sourceId, threadId]);\n\n return (\n <DispatchShell\n title=\"Thread Debug\"\n description=\"Inspect persisted agent chat threads, run events, and AI internals.\"\n >\n <div className=\"space-y-4\">\n <section className=\"rounded-lg border bg-card p-4\">\n <div className=\"grid gap-3 lg:grid-cols-[220px_1fr_260px_auto]\">\n <Select value={sourceId} onValueChange={setSourceId}>\n <SelectTrigger>\n <SelectValue placeholder=\"Source\" />\n </SelectTrigger>\n <SelectContent>\n {sources.map((source) => (\n <SelectItem key={source.id} value={source.id}>\n {source.label}\n </SelectItem>\n ))}\n {sources.length === 0 ? (\n <SelectItem value=\"current\">Current Dispatch DB</SelectItem>\n ) : null}\n </SelectContent>\n </Select>\n <Input\n value={query}\n onChange={(event) => setQuery(event.target.value)}\n placeholder=\"Search title, preview, messages, tools\"\n />\n <Input\n value={ownerEmail}\n onChange={(event) => setOwnerEmail(event.target.value)}\n placeholder=\"Owner email\"\n />\n <Button\n type=\"button\"\n onClick={() =>\n setSubmittedSearch({\n sourceId,\n query: query.trim(),\n ownerEmail: ownerEmail.trim(),\n })\n }\n >\n <IconSearch size={16} />\n Search\n </Button>\n </div>\n\n <div className=\"mt-3 grid gap-3 lg:grid-cols-[1fr_auto]\">\n <Input\n value={threadId}\n onChange={(event) => setThreadId(event.target.value)}\n placeholder=\"Paste thread ID\"\n className=\"font-mono\"\n />\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => {\n const trimmed = threadId.trim();\n if (!trimmed) return;\n setSelected({\n sourceId,\n threadId: trimmed,\n ownerEmail: ownerEmail.trim() || undefined,\n });\n }}\n >\n <IconFileSearch size={16} />\n Inspect\n </Button>\n </div>\n\n <div className=\"mt-3 flex flex-wrap items-center gap-2 text-xs text-muted-foreground\">\n {sourcesLoading ? <Skeleton className=\"h-5 w-32\" /> : null}\n {selectedSource ? <SourceBadge source={selectedSource} /> : null}\n {selectedSource?.databaseUrlEnv ? (\n <Badge variant=\"outline\" className=\"font-mono\">\n {selectedSource.databaseUrlEnv}\n </Badge>\n ) : null}\n {sourcesData?.access ? (\n <span>\n {sourcesData.access.viewerEmail} ·{\" \"}\n {sourcesData.access.canInspectAll ? \"admin scope\" : \"own scope\"}\n </span>\n ) : null}\n </div>\n </section>\n\n {searchError ? (\n <Alert variant=\"destructive\">\n <AlertTitle>Search failed</AlertTitle>\n <AlertDescription>{String(searchError.message)}</AlertDescription>\n </Alert>\n ) : null}\n\n <div className=\"grid gap-4 xl:grid-cols-[380px_1fr]\">\n <section className=\"min-h-[520px] rounded-lg border bg-card\">\n <div className=\"flex items-center justify-between border-b px-4 py-3\">\n <div>\n <div className=\"text-sm font-semibold text-foreground\">\n Threads\n </div>\n <div className=\"text-xs text-muted-foreground\">\n {searchData?.count ?? 0} results ·{\" \"}\n {searchData?.access?.scope ?? \"current scope\"}\n </div>\n </div>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => refetchSearch()}\n aria-label=\"Refresh threads\"\n >\n <IconRefresh size={16} />\n </Button>\n </div>\n <div className=\"max-h-[760px] space-y-2 overflow-auto p-3\">\n {searchLoading ? (\n <>\n <Skeleton className=\"h-28 w-full rounded-lg\" />\n <Skeleton className=\"h-28 w-full rounded-lg\" />\n <Skeleton className=\"h-28 w-full rounded-lg\" />\n </>\n ) : null}\n {!searchLoading && searchThreads.length === 0 ? (\n <div className=\"flex min-h-64 flex-col items-center justify-center rounded-lg border border-dashed px-4 text-center text-sm text-muted-foreground\">\n <IconDatabase className=\"mb-2 h-5 w-5\" />\n No threads found.\n </div>\n ) : null}\n {searchThreads.map((result) => (\n <ResultCard\n key={result.id}\n result={result}\n selected={selected?.threadId === result.id}\n onSelect={() =>\n setSelected({\n sourceId: submittedSearch.sourceId,\n threadId: result.id,\n ownerEmail: submittedSearch.ownerEmail || undefined,\n })\n }\n />\n ))}\n </div>\n </section>\n\n <section className=\"min-w-0\">\n {detailError ? (\n <Alert variant=\"destructive\">\n <AlertTitle>Thread lookup failed</AlertTitle>\n <AlertDescription>\n {String(detailError.message)}\n </AlertDescription>\n </Alert>\n ) : null}\n {detailLoading ? (\n <div className=\"rounded-lg border bg-card p-4\">\n <Skeleton className=\"h-6 w-72\" />\n <Skeleton className=\"mt-3 h-4 w-96\" />\n <Skeleton className=\"mt-6 h-[520px] w-full\" />\n </div>\n ) : detail ? (\n <ThreadDetail detail={detail} />\n ) : (\n <div className=\"flex min-h-[520px] flex-col items-center justify-center rounded-lg border border-dashed bg-card px-4 text-center text-sm text-muted-foreground\">\n <IconFileSearch className=\"mb-2 h-5 w-5\" />\n Select or inspect a thread.\n </div>\n )}\n </section>\n </div>\n </div>\n </DispatchShell>\n );\n}\n"]}
1
+ {"version":3,"file":"thread-debug.js","sourceRoot":"","sources":["../../../src/routes/pages/thread-debug.tsx"],"names":[],"mappings":"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","sourcesContent":["import { agentNativePath, useActionQuery } from \"@agent-native/core/client\";\nimport {\n IconDatabase,\n IconFileSearch,\n IconRefresh,\n IconSearch,\n} from \"@tabler/icons-react\";\nimport { useEffect, useMemo, useState } from \"react\";\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 { Input } from \"../../components/ui/input\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../components/ui/select\";\nimport { Skeleton } from \"../../components/ui/skeleton\";\nimport {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"../../components/ui/tabs\";\nimport { cn } from \"../../lib/utils\";\n\nexport function meta() {\n return [{ title: \"Thread Debug — Dispatch\" }];\n}\n\ninterface ThreadDebugSource {\n id: string;\n label: string;\n kind: \"current\" | \"env\" | \"configured\";\n current: boolean;\n connected: boolean;\n databaseUrlEnv: string | null;\n databaseAuthTokenEnv: string | null;\n canInspectAll: boolean;\n}\n\ninterface ThreadSearchResult {\n id: string;\n ownerEmail: string;\n title: string;\n preview: string;\n messageCount: number;\n createdAt: number;\n updatedAt: number;\n snippet: string;\n}\n\ninterface ThreadMessage {\n index: number;\n id: string | null;\n role: string;\n createdAt: string | number | null;\n status: unknown;\n text: string;\n contentParts: any[];\n attachments: any[];\n metadata: unknown;\n}\n\ninterface ThreadRun {\n id: string;\n status: string;\n abortReason: string | null;\n startedAt: number;\n completedAt: number | null;\n heartbeatAt: number | null;\n events: Array<{ seq: number; event: any; rawEventData: string }>;\n}\n\ninterface ThreadDebugResponse {\n source: {\n id: string;\n label: string;\n kind: string;\n databaseUrlEnv: string | null;\n };\n access: { viewerEmail: string; scope: string; canInspectAll: boolean };\n thread: ThreadSearchResult;\n messages: ThreadMessage[];\n debug: any;\n debugRuns: any[];\n queuedMessages: any[];\n threadData: any;\n rawThreadData: string;\n runs: ThreadRun[];\n traces: { summaries: any[]; spans: any[] };\n feedback: any[];\n satisfaction: any[];\n evals: any[];\n checkpoints: any[];\n}\n\nfunction formatDate(value: number | string | null | undefined): string {\n if (value == null || value === \"\") return \"n/a\";\n const numeric = Number(value);\n const date = Number.isFinite(numeric) ? new Date(numeric) : new Date(value);\n if (Number.isNaN(date.getTime())) return \"n/a\";\n return date.toLocaleString();\n}\n\nfunction json(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n\nfunction eventLabel(event: any): string {\n if (!event || typeof event !== \"object\") return \"event\";\n if (event.type === \"tool_start\") return `tool_start · ${event.tool}`;\n if (event.type === \"tool_done\") return `tool_done · ${event.tool}`;\n if (event.type === \"text\") return \"text\";\n if (event.type === \"error\") return `error · ${event.errorCode ?? \"agent\"}`;\n return String(event.type ?? \"event\");\n}\n\nfunction messageTitle(message: ThreadMessage): string {\n const role = message.role || \"unknown\";\n return `${role.charAt(0).toUpperCase()}${role.slice(1)} ${message.index + 1}`;\n}\n\nfunction toolParts(message: ThreadMessage): any[] {\n return message.contentParts.filter((part) => part?.type === \"tool-call\");\n}\n\nfunction RawBlock({\n value,\n className,\n}: {\n value: unknown;\n className?: string;\n}) {\n return (\n <pre\n className={cn(\n \"max-h-[520px] overflow-auto rounded-lg border bg-muted/30 p-3 text-xs leading-relaxed text-foreground\",\n \"whitespace-pre-wrap break-words\",\n className,\n )}\n >\n {typeof value === \"string\" ? value : json(value)}\n </pre>\n );\n}\n\nfunction SourceBadge({ source }: { source: ThreadDebugSource }) {\n return (\n <Badge variant={source.current ? \"default\" : \"secondary\"}>\n {source.current ? \"current\" : source.kind}\n </Badge>\n );\n}\n\nfunction ResultCard({\n result,\n selected,\n onSelect,\n}: {\n result: ThreadSearchResult;\n selected: boolean;\n onSelect: () => void;\n}) {\n return (\n <button\n type=\"button\"\n onClick={onSelect}\n className={cn(\n \"w-full rounded-lg border px-3 py-3 text-left transition-colors\",\n selected\n ? \"border-foreground bg-muted\"\n : \"bg-card hover:border-foreground/30 hover:bg-muted/40\",\n )}\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"truncate text-sm font-medium text-foreground\">\n {result.title || result.preview || result.id}\n </div>\n <div className=\"mt-1 truncate font-mono text-[11px] text-muted-foreground\">\n {result.id}\n </div>\n </div>\n <Badge variant=\"outline\" className=\"shrink-0\">\n {result.messageCount}\n </Badge>\n </div>\n <div className=\"mt-2 line-clamp-3 text-xs leading-relaxed text-muted-foreground\">\n {result.snippet || result.preview || \"No preview\"}\n </div>\n <div className=\"mt-2 flex items-center justify-between gap-3 text-[11px] text-muted-foreground\">\n <span className=\"truncate\">{result.ownerEmail}</span>\n <span className=\"shrink-0\">{formatDate(result.updatedAt)}</span>\n </div>\n </button>\n );\n}\n\nfunction MessageBlock({ message }: { message: ThreadMessage }) {\n const tools = toolParts(message);\n return (\n <div className=\"rounded-lg border bg-card\">\n <div className=\"flex flex-wrap items-center justify-between gap-2 border-b px-3 py-2\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <Badge\n variant={message.role === \"assistant\" ? \"default\" : \"secondary\"}\n >\n {message.role}\n </Badge>\n <span className=\"truncate text-sm font-medium text-foreground\">\n {messageTitle(message)}\n </span>\n </div>\n <div className=\"flex items-center gap-2 text-[11px] text-muted-foreground\">\n {message.attachments.length > 0 ? (\n <Badge variant=\"outline\">{message.attachments.length} files</Badge>\n ) : null}\n <span>{formatDate(message.createdAt)}</span>\n </div>\n </div>\n <div className=\"space-y-3 px-3 py-3\">\n {message.text ? (\n <div className=\"whitespace-pre-wrap break-words text-sm leading-relaxed text-foreground\">\n {message.text}\n </div>\n ) : (\n <div className=\"text-sm text-muted-foreground\">No text content</div>\n )}\n {tools.length > 0 ? (\n <div className=\"space-y-2\">\n {tools.map((tool, index) => (\n <details\n key={`${message.id ?? message.index}-tool-${index}`}\n className=\"rounded-md border bg-muted/30 px-3 py-2\"\n >\n <summary className=\"cursor-pointer text-xs font-medium text-foreground\">\n {tool.toolName ?? tool.name ?? \"tool-call\"}\n </summary>\n <RawBlock value={tool} className=\"mt-2 max-h-72\" />\n </details>\n ))}\n </div>\n ) : null}\n </div>\n </div>\n );\n}\n\nfunction ThreadDetail({ detail }: { detail: ThreadDebugResponse }) {\n const rawBundle = useMemo(\n () => ({\n thread: detail.thread,\n debug: detail.debug,\n debugRuns: detail.debugRuns,\n queuedMessages: detail.queuedMessages,\n threadData: detail.threadData,\n runs: detail.runs,\n traces: detail.traces,\n feedback: detail.feedback,\n satisfaction: detail.satisfaction,\n evals: detail.evals,\n checkpoints: detail.checkpoints,\n }),\n [detail],\n );\n\n return (\n <div className=\"rounded-lg border bg-card\">\n <div className=\"border-b px-4 py-3\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"truncate text-base font-semibold text-foreground\">\n {detail.thread.title || detail.thread.preview || detail.thread.id}\n </div>\n <div className=\"mt-1 truncate font-mono text-xs text-muted-foreground\">\n {detail.thread.id}\n </div>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant=\"secondary\">{detail.messages.length} messages</Badge>\n <Badge variant=\"secondary\">{detail.runs.length} runs</Badge>\n <Badge variant=\"outline\">{detail.source.label}</Badge>\n </div>\n </div>\n <div className=\"mt-3 grid gap-2 text-xs text-muted-foreground sm:grid-cols-3\">\n <div className=\"truncate\">Owner: {detail.thread.ownerEmail}</div>\n <div>Created: {formatDate(detail.thread.createdAt)}</div>\n <div>Updated: {formatDate(detail.thread.updatedAt)}</div>\n </div>\n </div>\n\n <Tabs defaultValue=\"transcript\" className=\"p-4\">\n <TabsList>\n <TabsTrigger value=\"transcript\">Transcript</TabsTrigger>\n <TabsTrigger value=\"runs\">Runs</TabsTrigger>\n <TabsTrigger value=\"internals\">Internals</TabsTrigger>\n <TabsTrigger value=\"raw\">Raw</TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"transcript\" className=\"mt-4 space-y-3\">\n {detail.messages.length > 0 ? (\n detail.messages.map((message) => (\n <MessageBlock\n key={message.id ?? `message-${message.index}`}\n message={message}\n />\n ))\n ) : (\n <div className=\"rounded-lg border border-dashed px-4 py-8 text-center text-sm text-muted-foreground\">\n No persisted messages.\n </div>\n )}\n </TabsContent>\n\n <TabsContent value=\"runs\" className=\"mt-4 space-y-3\">\n {detail.runs.length > 0 ? (\n detail.runs.map((run) => (\n <details key={run.id} className=\"rounded-lg border bg-card\">\n <summary className=\"cursor-pointer px-4 py-3\">\n <div className=\"inline-flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\">{run.status}</Badge>\n <span className=\"font-mono text-xs text-foreground\">\n {run.id}\n </span>\n <span className=\"text-xs text-muted-foreground\">\n {formatDate(run.startedAt)}\n </span>\n </div>\n </summary>\n <div className=\"space-y-2 border-t px-4 py-3\">\n {run.events.map((event) => (\n <details\n key={`${run.id}-${event.seq}`}\n className=\"rounded-md border bg-muted/30 px-3 py-2\"\n >\n <summary className=\"cursor-pointer text-xs font-medium text-foreground\">\n #{event.seq} {eventLabel(event.event)}\n </summary>\n <RawBlock value={event.event} className=\"mt-2 max-h-72\" />\n </details>\n ))}\n {run.events.length === 0 ? (\n <div className=\"text-sm text-muted-foreground\">\n No retained run events.\n </div>\n ) : null}\n </div>\n </details>\n ))\n ) : (\n <div className=\"rounded-lg border border-dashed px-4 py-8 text-center text-sm text-muted-foreground\">\n No retained runs.\n </div>\n )}\n </TabsContent>\n\n <TabsContent value=\"internals\" className=\"mt-4 space-y-4\">\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <div>\n <div className=\"mb-2 text-sm font-medium text-foreground\">\n Debug Runs\n </div>\n <RawBlock\n value={\n detail.debugRuns.length > 0\n ? detail.debugRuns\n : (detail.debug ?? {})\n }\n />\n </div>\n <div>\n <div className=\"mb-2 text-sm font-medium text-foreground\">\n Trace Summaries\n </div>\n <RawBlock value={detail.traces.summaries} />\n </div>\n <div>\n <div className=\"mb-2 text-sm font-medium text-foreground\">\n Trace Spans\n </div>\n <RawBlock value={detail.traces.spans} />\n </div>\n <div>\n <div className=\"mb-2 text-sm font-medium text-foreground\">\n Feedback And Evals\n </div>\n <RawBlock\n value={{\n feedback: detail.feedback,\n satisfaction: detail.satisfaction,\n evals: detail.evals,\n checkpoints: detail.checkpoints,\n }}\n />\n </div>\n </div>\n </TabsContent>\n\n <TabsContent value=\"raw\" className=\"mt-4 space-y-4\">\n <RawBlock value={rawBundle} />\n <RawBlock value={detail.rawThreadData} />\n </TabsContent>\n </Tabs>\n </div>\n );\n}\n\nexport default function ThreadDebugRoute() {\n const [sourceId, setSourceId] = useState(\"current\");\n const [query, setQuery] = useState(\"\");\n const [ownerEmail, setOwnerEmail] = useState(\"\");\n const [threadId, setThreadId] = useState(\"\");\n const [submittedSearch, setSubmittedSearch] = useState({\n sourceId: \"current\",\n query: \"\",\n ownerEmail: \"\",\n });\n const [selected, setSelected] = useState<{\n sourceId: string;\n threadId: string;\n ownerEmail?: string;\n } | null>(null);\n\n const sourcesQuery = useActionQuery<{\n access: {\n viewerEmail: string;\n orgId: string | null;\n role: string | null;\n envAdmin: boolean;\n canInspectAll: boolean;\n memberCount: number;\n };\n sources: ThreadDebugSource[];\n }>(\"list-agent-thread-sources\", {});\n const { data: sourcesData, isLoading: sourcesLoading } = sourcesQuery;\n\n const sources: ThreadDebugSource[] = sourcesData?.sources ?? [];\n const searchParams = useMemo(\n () => ({\n sourceId: submittedSearch.sourceId,\n query: submittedSearch.query || undefined,\n ownerEmail: submittedSearch.ownerEmail || undefined,\n limit: 25,\n }),\n [submittedSearch],\n );\n const {\n data: searchData,\n isLoading: searchLoading,\n error: searchError,\n refetch: refetchSearch,\n } = useActionQuery<{\n count: number;\n threads: ThreadSearchResult[];\n access: { scope: string; canInspectAll: boolean };\n source: { id: string; label: string };\n }>(\"search-agent-threads\", searchParams);\n const searchThreads: ThreadSearchResult[] = searchData?.threads ?? [];\n\n const detailParams = useMemo(\n () => ({\n sourceId: selected?.sourceId ?? \"current\",\n threadId: selected?.threadId ?? \"\",\n ownerEmail: selected?.ownerEmail,\n maxRuns: 20,\n maxEvents: 800,\n maxTraceSpans: 600,\n }),\n [selected],\n );\n const {\n data: detail,\n isLoading: detailLoading,\n error: detailError,\n refetch: refetchDetail,\n } = useActionQuery<ThreadDebugResponse>(\n \"get-agent-thread-debug\",\n detailParams,\n {\n enabled: Boolean(selected?.threadId),\n },\n );\n\n const selectedSource = sources.find((source) => source.id === sourceId);\n\n useEffect(() => {\n fetch(agentNativePath(\"/_agent-native/application-state/navigation\"), {\n method: \"PUT\",\n keepalive: true,\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n view: \"thread-debug\",\n path:\n typeof window === \"undefined\"\n ? \"/thread-debug\"\n : window.location.pathname,\n sourceId,\n query,\n ownerEmail: ownerEmail.trim() || undefined,\n threadId: selected?.threadId ?? (threadId.trim() || undefined),\n }),\n }).catch(() => {});\n }, [ownerEmail, query, selected?.threadId, sourceId, threadId]);\n\n return (\n <DispatchShell\n title=\"Thread Debug\"\n description=\"Inspect persisted agent chat threads, run events, and AI internals.\"\n >\n <div className=\"space-y-4\">\n {sourcesQuery.isError ? (\n <ActionQueryError\n error={sourcesQuery.error}\n onRetry={() => void sourcesQuery.refetch()}\n />\n ) : null}\n <section className=\"rounded-lg border bg-card p-4\">\n <div className=\"grid gap-3 lg:grid-cols-[220px_1fr_260px_auto]\">\n <Select value={sourceId} onValueChange={setSourceId}>\n <SelectTrigger>\n <SelectValue placeholder=\"Source\" />\n </SelectTrigger>\n <SelectContent>\n {sources.map((source) => (\n <SelectItem key={source.id} value={source.id}>\n {source.label}\n </SelectItem>\n ))}\n {sources.length === 0 ? (\n <SelectItem value=\"current\">Current Dispatch DB</SelectItem>\n ) : null}\n </SelectContent>\n </Select>\n <Input\n value={query}\n onChange={(event) => setQuery(event.target.value)}\n placeholder=\"Search title, preview, messages, tools\"\n />\n <Input\n value={ownerEmail}\n onChange={(event) => setOwnerEmail(event.target.value)}\n placeholder=\"Owner email\"\n />\n <Button\n type=\"button\"\n onClick={() =>\n setSubmittedSearch({\n sourceId,\n query: query.trim(),\n ownerEmail: ownerEmail.trim(),\n })\n }\n >\n <IconSearch size={16} />\n Search\n </Button>\n </div>\n\n <div className=\"mt-3 grid gap-3 lg:grid-cols-[1fr_auto]\">\n <Input\n value={threadId}\n onChange={(event) => setThreadId(event.target.value)}\n placeholder=\"Paste thread ID\"\n className=\"font-mono\"\n />\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => {\n const trimmed = threadId.trim();\n if (!trimmed) return;\n setSelected({\n sourceId,\n threadId: trimmed,\n ownerEmail: ownerEmail.trim() || undefined,\n });\n }}\n >\n <IconFileSearch size={16} />\n Inspect\n </Button>\n </div>\n\n <div className=\"mt-3 flex flex-wrap items-center gap-2 text-xs text-muted-foreground\">\n {sourcesLoading ? <Skeleton className=\"h-5 w-32\" /> : null}\n {selectedSource ? <SourceBadge source={selectedSource} /> : null}\n {selectedSource?.databaseUrlEnv ? (\n <Badge variant=\"outline\" className=\"font-mono\">\n {selectedSource.databaseUrlEnv}\n </Badge>\n ) : null}\n {sourcesData?.access ? (\n <span>\n {sourcesData.access.viewerEmail} ·{\" \"}\n {sourcesData.access.canInspectAll ? \"admin scope\" : \"own scope\"}\n </span>\n ) : null}\n </div>\n </section>\n\n {searchError ? (\n <ActionQueryError\n error={searchError}\n onRetry={() => void refetchSearch()}\n />\n ) : null}\n\n <div className=\"grid gap-4 xl:grid-cols-[380px_1fr]\">\n <section className=\"min-h-[520px] rounded-lg border bg-card\">\n <div className=\"flex items-center justify-between border-b px-4 py-3\">\n <div>\n <div className=\"text-sm font-semibold text-foreground\">\n Threads\n </div>\n <div className=\"text-xs text-muted-foreground\">\n {searchData?.count ?? 0} results ·{\" \"}\n {searchData?.access?.scope ?? \"current scope\"}\n </div>\n </div>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => refetchSearch()}\n aria-label=\"Refresh threads\"\n >\n <IconRefresh size={16} />\n </Button>\n </div>\n <div className=\"max-h-[760px] space-y-2 overflow-auto p-3\">\n {searchLoading ? (\n <>\n <Skeleton className=\"h-28 w-full rounded-lg\" />\n <Skeleton className=\"h-28 w-full rounded-lg\" />\n <Skeleton className=\"h-28 w-full rounded-lg\" />\n </>\n ) : null}\n {!searchLoading && searchThreads.length === 0 ? (\n <div className=\"flex min-h-64 flex-col items-center justify-center rounded-lg border border-dashed px-4 text-center text-sm text-muted-foreground\">\n <IconDatabase className=\"mb-2 h-5 w-5\" />\n No threads found.\n </div>\n ) : null}\n {searchThreads.map((result) => (\n <ResultCard\n key={result.id}\n result={result}\n selected={selected?.threadId === result.id}\n onSelect={() =>\n setSelected({\n sourceId: submittedSearch.sourceId,\n threadId: result.id,\n ownerEmail: submittedSearch.ownerEmail || undefined,\n })\n }\n />\n ))}\n </div>\n </section>\n\n <section className=\"min-w-0\">\n {detailError ? (\n <ActionQueryError\n error={detailError}\n onRetry={() => void refetchDetail()}\n />\n ) : null}\n {detailLoading ? (\n <div className=\"rounded-lg border bg-card p-4\">\n <Skeleton className=\"h-6 w-72\" />\n <Skeleton className=\"mt-3 h-4 w-96\" />\n <Skeleton className=\"mt-6 h-[520px] w-full\" />\n </div>\n ) : detail ? (\n <ThreadDetail detail={detail} />\n ) : (\n <div className=\"flex min-h-[520px] flex-col items-center justify-center rounded-lg border border-dashed bg-card px-4 text-center text-sm text-muted-foreground\">\n <IconFileSearch className=\"mb-2 h-5 w-5\" />\n Select or inspect a thread.\n </div>\n )}\n </section>\n </div>\n </div>\n </DispatchShell>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/vault.tsx"],"names":[],"mappings":"AA0EA,wBAAgB,IAAI;;IAEnB;AAqpBD,MAAM,CAAC,OAAO,UAAU,UAAU,oDAwIjC"}
1
+ {"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../../../src/routes/pages/vault.tsx"],"names":[],"mappings":"AA2EA,wBAAgB,IAAI;;IAEnB;AAqpBD,MAAM,CAAC,OAAO,UAAU,UAAU,oDAwKjC"}
@@ -3,6 +3,7 @@ import { useActionMutation, useActionQuery } from "@agent-native/core/client";
3
3
  import { IconChevronDown, IconChevronRight, IconEdit, IconEye, IconEyeOff, IconKey, IconPlus, IconRefresh, IconTrash, IconX, } from "@tabler/icons-react";
4
4
  import { useState } from "react";
5
5
  import { toast } from "sonner";
6
+ import { ActionQueryError } from "../../components/action-query-error.js";
6
7
  import { DispatchShell } from "../../components/dispatch-shell.js";
7
8
  import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from "../../components/ui/alert-dialog.js";
8
9
  import { Badge } from "../../components/ui/badge.js";
@@ -174,11 +175,16 @@ function RequestRow({ request }) {
174
175
  : `Denied by ${request.reviewedBy}`, " ", "\u00B7 ", new Date(request.createdAt).toLocaleString()] })] }), request.status === "pending" && (_jsx(Badge, { variant: "outline", className: "whitespace-nowrap", children: "Pending" })), request.status === "approved" && (_jsx(Badge, { variant: "secondary", className: "whitespace-nowrap bg-green-500/10 text-green-700 dark:text-green-400", children: "Approved" })), request.status === "denied" && (_jsx(Badge, { variant: "secondary", className: "whitespace-nowrap bg-red-500/10 text-red-700 dark:text-red-400", children: "Denied" }))] }), request.status === "pending" && (_jsxs("div", { className: "mt-3 flex items-end gap-2 border-t pt-3", children: [_jsxs("div", { className: "flex-1 space-y-1", children: [_jsx(Label, { className: "text-xs", children: "Secret value to provision" }), _jsx(Input, { type: "password", placeholder: "Enter the secret value", value: secretValue, onChange: (e) => setSecretValue(e.target.value), className: "h-8 text-sm" })] }), _jsx(Button, { size: "sm", onClick: () => approve.mutate({ id: request.id, secretValue }), disabled: !secretValue || approve.isPending, children: "Approve" }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => deny.mutate({ id: request.id }), disabled: deny.isPending, children: "Deny" })] }))] }));
175
176
  }
176
177
  export default function VaultRoute() {
177
- const { data: secrets, isLoading: secretsLoading } = useActionQuery("list-vault-secrets", {});
178
- const { data: grants } = useActionQuery("list-vault-grants", {});
179
- const { data: requests } = useActionQuery("list-vault-requests", {});
180
- const { data: audit } = useActionQuery("list-vault-audit", { limit: 20 });
181
- const { data: accessSettings } = useActionQuery("get-vault-access-settings", {});
178
+ const secretsQuery = useActionQuery("list-vault-secrets", {});
179
+ const grantsQuery = useActionQuery("list-vault-grants", {});
180
+ const requestsQuery = useActionQuery("list-vault-requests", {});
181
+ const auditQuery = useActionQuery("list-vault-audit", { limit: 20 });
182
+ const accessQuery = useActionQuery("get-vault-access-settings", {});
183
+ const { data: secrets, isLoading: secretsLoading } = secretsQuery;
184
+ const { data: grants } = grantsQuery;
185
+ const { data: requests } = requestsQuery;
186
+ const { data: audit } = auditQuery;
187
+ const { data: accessSettings } = accessQuery;
182
188
  const accessMode = accessSettings?.mode === "manual" ? "manual" : "all-apps";
183
189
  const grantsBySecret = (grants || []).reduce((acc, g) => {
184
190
  if (!acc[g.secretId])
@@ -187,8 +193,18 @@ export default function VaultRoute() {
187
193
  return acc;
188
194
  }, {});
189
195
  const pendingRequests = (requests || []).filter((r) => r.status === "pending");
190
- return (_jsx(DispatchShell, { title: "Vault", description: "Centralized secret management for your workspace. Store credentials once and sync them to apps.", children: _jsxs(Tabs, { defaultValue: "secrets", children: [_jsxs(TabsList, { children: [_jsxs(TabsTrigger, { value: "secrets", children: ["Secrets ", (secrets?.length || 0) > 0 && `(${secrets?.length})`] }), _jsxs(TabsTrigger, { value: "requests", children: ["Requests", " ", pendingRequests.length > 0 && (_jsx(Badge, { variant: "secondary", className: "ml-1.5 h-5 px-1.5 text-xs bg-amber-500/10 text-amber-700 dark:text-amber-400", children: pendingRequests.length }))] }), _jsx(TabsTrigger, { value: "audit", children: "Audit" })] }), _jsxs(TabsContent, { value: "secrets", className: "mt-4 space-y-3", children: [_jsx(VaultAccessSettingsCard, { mode: accessMode }), _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [_jsx(IconKey, { size: 16 }), secretsLoading ? (_jsx(Skeleton, { className: "h-4 w-20" })) : (_jsx("span", { children: `${secrets?.length || 0} secret${(secrets?.length || 0) !== 1 ? "s" : ""}` }))] }), _jsx(AddSecretDialog, {})] }), secretsLoading && (secrets ?? []).length === 0
196
+ return (_jsx(DispatchShell, { title: "Vault", description: "Centralized secret management for your workspace. Store credentials once and sync them to apps.", children: _jsxs(Tabs, { defaultValue: "secrets", children: [_jsxs(TabsList, { children: [_jsxs(TabsTrigger, { value: "secrets", children: ["Secrets ", (secrets?.length || 0) > 0 && `(${secrets?.length})`] }), _jsxs(TabsTrigger, { value: "requests", children: ["Requests", " ", pendingRequests.length > 0 && (_jsx(Badge, { variant: "secondary", className: "ml-1.5 h-5 px-1.5 text-xs bg-amber-500/10 text-amber-700 dark:text-amber-400", children: pendingRequests.length }))] }), _jsx(TabsTrigger, { value: "audit", children: "Audit" })] }), _jsxs(TabsContent, { value: "secrets", className: "mt-4 space-y-3", children: [secretsQuery.isError ||
197
+ grantsQuery.isError ||
198
+ accessQuery.isError ? (_jsx(ActionQueryError, { error: secretsQuery.error ?? grantsQuery.error ?? accessQuery.error, onRetry: () => {
199
+ void secretsQuery.refetch();
200
+ void grantsQuery.refetch();
201
+ void accessQuery.refetch();
202
+ } })) : null, _jsx(VaultAccessSettingsCard, { mode: accessMode }), _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [_jsx(IconKey, { size: 16 }), secretsLoading ? (_jsx(Skeleton, { className: "h-4 w-20" })) : (_jsx("span", { children: `${secrets?.length || 0} secret${(secrets?.length || 0) !== 1 ? "s" : ""}` }))] }), _jsx(AddSecretDialog, {})] }), !secretsQuery.isError &&
203
+ secretsLoading &&
204
+ (secrets ?? []).length === 0
191
205
  ? Array.from({ length: 3 }).map((_, index) => (_jsxs("div", { className: "rounded-2xl border bg-card px-5 py-4 space-y-2", children: [_jsx(Skeleton, { className: "h-4 w-1/3" }), _jsx(Skeleton, { className: "h-3 w-2/3" })] }, index)))
192
- : (secrets || []).map((secret) => (_jsx(SecretRow, { secret: secret, grants: grantsBySecret[secret.id] || [], accessMode: accessMode }, secret.id))), !secretsLoading && (secrets?.length || 0) === 0 && (_jsxs("div", { className: "rounded-2xl border border-dashed px-6 py-12 text-center", children: [_jsx(IconKey, { size: 32, className: "mx-auto text-muted-foreground/50" }), _jsx("h3", { className: "mt-3 text-sm font-medium text-foreground", children: "No secrets yet" }), _jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: "Add your first secret to start sharing credentials across workspace apps." })] }))] }), _jsxs(TabsContent, { value: "requests", className: "mt-4 space-y-3", children: [(requests || []).map((request) => (_jsx(RequestRow, { request: request }, request.id))), (requests?.length || 0) === 0 && (_jsx("div", { className: "rounded-2xl border border-dashed px-6 py-12 text-center text-sm text-muted-foreground", children: "No secret requests yet." }))] }), _jsxs(TabsContent, { value: "audit", className: "mt-4 space-y-2", children: [(audit || []).map((event) => (_jsxs("div", { className: "rounded-xl border bg-muted/30 px-4 py-3", children: [_jsx("div", { className: "text-sm font-medium text-foreground", children: event.summary }), _jsxs("div", { className: "mt-1 text-xs text-muted-foreground", children: [event.actor, " \u00B7 ", new Date(event.createdAt).toLocaleString()] })] }, event.id))), (audit?.length || 0) === 0 && (_jsx("div", { className: "rounded-2xl border border-dashed px-6 py-12 text-center text-sm text-muted-foreground", children: "No vault activity yet." }))] })] }) }));
206
+ : (secrets || []).map((secret) => (_jsx(SecretRow, { secret: secret, grants: grantsBySecret[secret.id] || [], accessMode: accessMode }, secret.id))), !secretsQuery.isError &&
207
+ !secretsLoading &&
208
+ (secrets?.length || 0) === 0 && (_jsxs("div", { className: "rounded-2xl border border-dashed px-6 py-12 text-center", children: [_jsx(IconKey, { size: 32, className: "mx-auto text-muted-foreground/50" }), _jsx("h3", { className: "mt-3 text-sm font-medium text-foreground", children: "No secrets yet" }), _jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: "Add your first secret to start sharing credentials across workspace apps." })] }))] }), _jsxs(TabsContent, { value: "requests", className: "mt-4 space-y-3", children: [requestsQuery.isError ? (_jsx(ActionQueryError, { error: requestsQuery.error, onRetry: () => void requestsQuery.refetch() })) : null, (requests || []).map((request) => (_jsx(RequestRow, { request: request }, request.id))), !requestsQuery.isError && (requests?.length || 0) === 0 && (_jsx("div", { className: "rounded-2xl border border-dashed px-6 py-12 text-center text-sm text-muted-foreground", children: "No secret requests yet." }))] }), _jsxs(TabsContent, { value: "audit", className: "mt-4 space-y-2", children: [auditQuery.isError ? (_jsx(ActionQueryError, { error: auditQuery.error, onRetry: () => void auditQuery.refetch() })) : null, (audit || []).map((event) => (_jsxs("div", { className: "rounded-xl border bg-muted/30 px-4 py-3", children: [_jsx("div", { className: "text-sm font-medium text-foreground", children: event.summary }), _jsxs("div", { className: "mt-1 text-xs text-muted-foreground", children: [event.actor, " \u00B7 ", new Date(event.createdAt).toLocaleString()] })] }, event.id))), !auditQuery.isError && (audit?.length || 0) === 0 && (_jsx("div", { className: "rounded-2xl border border-dashed px-6 py-12 text-center text-sm text-muted-foreground", children: "No vault activity yet." }))] })] }) }));
193
209
  }
194
210
  //# sourceMappingURL=vault.js.map