@agent-native/core 0.98.0 → 0.98.1

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 (243) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +24 -0
  3. package/corpus/core/package.json +2 -2
  4. package/corpus/core/src/action-change-marker.ts +8 -1
  5. package/corpus/core/src/changelog/parse.ts +8 -3
  6. package/corpus/core/src/client/AgentPanel.tsx +2 -3
  7. package/corpus/core/src/client/AssistantChat.tsx +83 -39
  8. package/corpus/core/src/client/analytics.ts +29 -0
  9. package/corpus/core/src/client/blocks/library/wireframe-kit.tsx +16 -2
  10. package/corpus/core/src/client/chat-model-groups.ts +28 -0
  11. package/corpus/core/src/client/composer/RealtimeVoiceMode.tsx +442 -85
  12. package/corpus/core/src/client/composer/TiptapComposer.tsx +46 -29
  13. package/corpus/core/src/client/composer/VoiceButton.tsx +2 -1
  14. package/corpus/core/src/client/composer/index.ts +5 -0
  15. package/corpus/core/src/client/composer/useRealtimeVoiceMode.tsx +1206 -67
  16. package/corpus/core/src/client/index.ts +5 -0
  17. package/corpus/core/src/client/progress/RunsTray.tsx +13 -1
  18. package/corpus/core/src/client/settings/SecretsSection.tsx +387 -266
  19. package/corpus/core/src/client/settings/SettingsPanel.tsx +117 -38
  20. package/corpus/core/src/client/use-action.ts +12 -0
  21. package/corpus/core/src/client/use-agent-chat-home-handoff.ts +8 -1
  22. package/corpus/core/src/client/use-agent-engine-configured.ts +17 -3
  23. package/corpus/core/src/client/use-db-sync.ts +84 -34
  24. package/corpus/core/src/client/use-pausing-interval.ts +14 -4
  25. package/corpus/core/src/integrations/scope-store.ts +1 -1
  26. package/corpus/core/src/integrations/usage-budget-store.ts +1 -1
  27. package/corpus/core/src/localization/default-messages.ts +44 -1
  28. package/corpus/core/src/mcp-client/workspace-servers.ts +4 -4
  29. package/corpus/core/src/secrets/crypto.ts +28 -8
  30. package/corpus/core/src/server/action-change.ts +5 -1
  31. package/corpus/core/src/server/action-routes.ts +8 -0
  32. package/corpus/core/src/server/poll.ts +1 -0
  33. package/corpus/core/src/server/realtime-voice.ts +299 -13
  34. package/corpus/core/src/styles/agent-native.css +2 -2
  35. package/corpus/core/src/templates/default/.agents/skills/real-time-sync/SKILL.md +2 -2
  36. package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +2 -2
  37. package/corpus/core/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +7 -3
  38. package/corpus/core/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +39 -9
  39. package/corpus/core/src/vite/client.ts +9 -1
  40. package/corpus/templates/analytics/.agents/skills/real-time-sync/SKILL.md +2 -2
  41. package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +10 -5
  42. package/corpus/templates/analytics/AGENTS.md +9 -13
  43. package/corpus/templates/analytics/actions/navigate.ts +59 -5
  44. package/corpus/templates/analytics/actions/view-screen.ts +3 -6
  45. package/corpus/templates/analytics/app/components/ProviderCorpusJobNotifier.tsx +20 -3
  46. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +2 -1
  47. package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -1
  48. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +21 -6
  49. package/corpus/templates/analytics/app/global.css +19 -20
  50. package/corpus/templates/analytics/app/lib/provider-corpus-job-sync.ts +26 -0
  51. package/corpus/templates/analytics/app/pages/Settings.tsx +35 -341
  52. package/corpus/templates/analytics/app/pages/monitoring/ErrorsPanel.tsx +38 -7
  53. package/corpus/templates/analytics/app/pages/monitoring/MonitoringPage.tsx +1 -1
  54. package/corpus/templates/analytics/app/pages/monitoring/errors/i18n.ts +3 -0
  55. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +333 -272
  56. package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +72 -17
  57. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +297 -108
  58. package/corpus/templates/analytics/app/root.tsx +28 -8
  59. package/corpus/templates/analytics/changelog/2026-06-24-first-party-signup-and-pageview-panels-now-honor-dashboard-filters.md +2 -1
  60. package/corpus/templates/analytics/changelog/2026-06-25-referrer-dashboard-panels-show-external-domains.md +2 -1
  61. package/corpus/templates/analytics/changelog/2026-07-06-mobile-chat-header-is-more-compact-and-the-menu-button-opens-navigation.md +1 -0
  62. package/corpus/templates/analytics/changelog/2026-07-08-dashboard-history-and-chat-context.md +1 -0
  63. package/corpus/templates/analytics/changelog/2026-07-08-settings-are-cleaner-searchable-and-alerts-have-their-own-tab.md +1 -0
  64. package/corpus/templates/analytics/changelog/2026-07-08-sidebar-sections-stay-collapsed-until-opened.md +1 -0
  65. package/corpus/templates/analytics/changelog/2026-07-11-analytics-no-longer-repeatedly-restarts-background-requests-.md +6 -0
  66. package/corpus/templates/analytics/changelog/2026-07-11-analytics-only-asks-for-replay-storage-when-you-enable-sessi.md +6 -0
  67. package/corpus/templates/analytics/changelog/2026-07-11-charts-now-show-their-loading-skeleton-while-refreshing.md +6 -0
  68. package/corpus/templates/analytics/changelog/2026-07-11-realtime-voice-now-shows-a-clear-connection-indicator-comple.md +6 -0
  69. package/corpus/templates/analytics/changelog/2026-07-11-replay-event-counts-stay-hidden-until-recordings-finish-load.md +6 -0
  70. package/corpus/templates/analytics/changelog/2026-07-11-replay-storage-key-mismatches-show-actionable-setup-guidance.md +6 -0
  71. package/corpus/templates/analytics/changelog/2026-07-11-replay-timelines-group-continuous-scrolling-and-dev-tools-co.md +6 -0
  72. package/corpus/templates/analytics/changelog/2026-07-11-session-filters-now-stay-compact-in-a-settings-menu-at-mediu.md +6 -0
  73. package/corpus/templates/analytics/changelog/2026-07-11-session-replay-console-errors-now-link-to-matching-issues-or.md +6 -0
  74. package/corpus/templates/analytics/changelog/2026-07-11-session-replays-load-large-recordings-faster-and-surface-fai.md +6 -0
  75. package/corpus/templates/analytics/changelog/2026-07-11-session-replays-preserve-recorded-styles-and-viewport-layout.md +6 -0
  76. package/corpus/templates/analytics/changelog/2026-07-11-session-replays-stay-centered-instead-of-clipping-wide-recor.md +6 -0
  77. package/corpus/templates/analytics/package.json +1 -1
  78. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +1 -303
  79. package/corpus/templates/analytics/server/handlers/session-replay.ts +57 -0
  80. package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +1 -1
  81. package/corpus/templates/analytics/server/lib/demo-dashboards.ts +16 -3
  82. package/corpus/templates/analytics/server/lib/session-replay-agent-context.ts +12 -0
  83. package/corpus/templates/analytics/server/lib/session-replay.ts +208 -2
  84. package/corpus/templates/analytics/server/plugins/onboarding.ts +7 -79
  85. package/corpus/templates/analytics/server/routes/api/session-replay/recordings/[recordingId]/chunks.get.ts +1 -0
  86. package/corpus/templates/assets/.agents/skills/real-time-sync/SKILL.md +2 -2
  87. package/corpus/templates/assets/app/global.css +4 -4
  88. package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +0 -1
  89. package/corpus/templates/assets/app/routes/library.tsx +0 -1
  90. package/corpus/templates/brain/.agents/skills/real-time-sync/SKILL.md +2 -2
  91. package/corpus/templates/brain/app/global.css +5 -5
  92. package/corpus/templates/brain/app/root.tsx +0 -3
  93. package/corpus/templates/calendar/.agents/skills/real-time-sync/SKILL.md +2 -2
  94. package/corpus/templates/calendar/app/root.tsx +1 -0
  95. package/corpus/templates/chat/.agents/skills/real-time-sync/SKILL.md +2 -2
  96. package/corpus/templates/clips/app/hooks/use-auto-title.ts +74 -8
  97. package/corpus/templates/clips/app/hooks/use-library.ts +12 -25
  98. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +20 -22
  99. package/corpus/templates/clips/changelog/2026-07-11-generated-titles-no-longer-cause-continuous-background-refreshes.md +6 -0
  100. package/corpus/templates/clips/changelog/2026-07-11-s3-storage-setup-stays-collapsed-until-you-choose-it-as-the-.md +6 -0
  101. package/corpus/templates/content/.agents/skills/real-time-sync/SKILL.md +2 -2
  102. package/corpus/templates/content/app/hooks/use-comments.ts +0 -1
  103. package/corpus/templates/content/changelog/2026-07-11-comments-now-update-from-live-collaboration-events-without-c.md +6 -0
  104. package/corpus/templates/design/app/components/layout/Header.tsx +1 -1
  105. package/corpus/templates/forms/.agents/skills/real-time-sync/SKILL.md +2 -2
  106. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +1 -2
  107. package/corpus/templates/macros/app/root.tsx +0 -3
  108. package/corpus/templates/mail/.agents/skills/real-time-sync/SKILL.md +2 -2
  109. package/corpus/templates/mail/app/hooks/use-compose-state.ts +1 -0
  110. package/corpus/templates/mail/app/root.tsx +1 -12
  111. package/corpus/templates/plan/.agents/skills/real-time-sync/SKILL.md +2 -2
  112. package/corpus/templates/plan/app/hooks/use-navigation-state.ts +5 -2
  113. package/corpus/templates/plan/app/hooks/use-plans.ts +6 -13
  114. package/corpus/templates/plan/app/pages/PlansPage.tsx +5 -27
  115. package/corpus/templates/plan/changelog/2026-07-11-plan-refreshes-only-when-content-changes.md +6 -0
  116. package/corpus/templates/slides/app/components/comments/SlideCommentsPanel.tsx +4 -1
  117. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +1 -1
  118. package/corpus/templates/slides/app/components/layout/Header.tsx +1 -1
  119. package/corpus/templates/slides/app/context/DeckContext.tsx +1 -0
  120. package/corpus/templates/slides/app/hooks/use-slide-comments.ts +7 -31
  121. package/corpus/templates/slides/changelog/2026-07-11-comments-now-update-from-live-collaboration-events-without-c.md +6 -0
  122. package/dist/action-change-marker.d.ts +1 -0
  123. package/dist/action-change-marker.d.ts.map +1 -1
  124. package/dist/action-change-marker.js +7 -1
  125. package/dist/action-change-marker.js.map +1 -1
  126. package/dist/changelog/parse.d.ts +4 -2
  127. package/dist/changelog/parse.d.ts.map +1 -1
  128. package/dist/changelog/parse.js +5 -3
  129. package/dist/changelog/parse.js.map +1 -1
  130. package/dist/client/AgentPanel.d.ts.map +1 -1
  131. package/dist/client/AgentPanel.js +2 -3
  132. package/dist/client/AgentPanel.js.map +1 -1
  133. package/dist/client/AssistantChat.d.ts +7 -0
  134. package/dist/client/AssistantChat.d.ts.map +1 -1
  135. package/dist/client/AssistantChat.js +62 -40
  136. package/dist/client/AssistantChat.js.map +1 -1
  137. package/dist/client/analytics.d.ts.map +1 -1
  138. package/dist/client/analytics.js +26 -0
  139. package/dist/client/analytics.js.map +1 -1
  140. package/dist/client/blocks/library/wireframe-kit.d.ts +2 -0
  141. package/dist/client/blocks/library/wireframe-kit.d.ts.map +1 -1
  142. package/dist/client/blocks/library/wireframe-kit.js +9 -2
  143. package/dist/client/blocks/library/wireframe-kit.js.map +1 -1
  144. package/dist/client/chat-model-groups.d.ts.map +1 -1
  145. package/dist/client/chat-model-groups.js +24 -0
  146. package/dist/client/chat-model-groups.js.map +1 -1
  147. package/dist/client/composer/RealtimeVoiceMode.d.ts +40 -4
  148. package/dist/client/composer/RealtimeVoiceMode.d.ts.map +1 -1
  149. package/dist/client/composer/RealtimeVoiceMode.js +172 -42
  150. package/dist/client/composer/RealtimeVoiceMode.js.map +1 -1
  151. package/dist/client/composer/TiptapComposer.d.ts +4 -0
  152. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  153. package/dist/client/composer/TiptapComposer.js +47 -29
  154. package/dist/client/composer/TiptapComposer.js.map +1 -1
  155. package/dist/client/composer/VoiceButton.d.ts.map +1 -1
  156. package/dist/client/composer/VoiceButton.js +2 -2
  157. package/dist/client/composer/VoiceButton.js.map +1 -1
  158. package/dist/client/composer/index.d.ts +2 -2
  159. package/dist/client/composer/index.d.ts.map +1 -1
  160. package/dist/client/composer/index.js +1 -1
  161. package/dist/client/composer/index.js.map +1 -1
  162. package/dist/client/composer/useRealtimeVoiceMode.d.ts +100 -3
  163. package/dist/client/composer/useRealtimeVoiceMode.d.ts.map +1 -1
  164. package/dist/client/composer/useRealtimeVoiceMode.js +952 -51
  165. package/dist/client/composer/useRealtimeVoiceMode.js.map +1 -1
  166. package/dist/client/index.d.ts +1 -1
  167. package/dist/client/index.d.ts.map +1 -1
  168. package/dist/client/index.js +1 -1
  169. package/dist/client/index.js.map +1 -1
  170. package/dist/client/progress/RunsTray.d.ts.map +1 -1
  171. package/dist/client/progress/RunsTray.js +10 -1
  172. package/dist/client/progress/RunsTray.js.map +1 -1
  173. package/dist/client/settings/SecretsSection.d.ts +2 -3
  174. package/dist/client/settings/SecretsSection.d.ts.map +1 -1
  175. package/dist/client/settings/SecretsSection.js +46 -22
  176. package/dist/client/settings/SecretsSection.js.map +1 -1
  177. package/dist/client/settings/SettingsPanel.d.ts +9 -0
  178. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  179. package/dist/client/settings/SettingsPanel.js +46 -12
  180. package/dist/client/settings/SettingsPanel.js.map +1 -1
  181. package/dist/client/use-action.d.ts +2 -0
  182. package/dist/client/use-action.d.ts.map +1 -1
  183. package/dist/client/use-action.js +10 -0
  184. package/dist/client/use-action.js.map +1 -1
  185. package/dist/client/use-agent-chat-home-handoff.d.ts +2 -0
  186. package/dist/client/use-agent-chat-home-handoff.d.ts.map +1 -1
  187. package/dist/client/use-agent-chat-home-handoff.js +7 -1
  188. package/dist/client/use-agent-chat-home-handoff.js.map +1 -1
  189. package/dist/client/use-agent-engine-configured.d.ts.map +1 -1
  190. package/dist/client/use-agent-engine-configured.js +17 -3
  191. package/dist/client/use-agent-engine-configured.js.map +1 -1
  192. package/dist/client/use-db-sync.d.ts +8 -2
  193. package/dist/client/use-db-sync.d.ts.map +1 -1
  194. package/dist/client/use-db-sync.js +57 -32
  195. package/dist/client/use-db-sync.js.map +1 -1
  196. package/dist/client/use-pausing-interval.d.ts.map +1 -1
  197. package/dist/client/use-pausing-interval.js +16 -4
  198. package/dist/client/use-pausing-interval.js.map +1 -1
  199. package/dist/integrations/scope-store.js +1 -1
  200. package/dist/integrations/scope-store.js.map +1 -1
  201. package/dist/integrations/usage-budget-store.js +1 -1
  202. package/dist/integrations/usage-budget-store.js.map +1 -1
  203. package/dist/localization/default-messages.d.ts +41 -1
  204. package/dist/localization/default-messages.d.ts.map +1 -1
  205. package/dist/localization/default-messages.js +41 -1
  206. package/dist/localization/default-messages.js.map +1 -1
  207. package/dist/mcp-client/workspace-servers.js +4 -4
  208. package/dist/mcp-client/workspace-servers.js.map +1 -1
  209. package/dist/observability/routes.d.ts +5 -5
  210. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  211. package/dist/secrets/crypto.d.ts +7 -6
  212. package/dist/secrets/crypto.d.ts.map +1 -1
  213. package/dist/secrets/crypto.js +30 -11
  214. package/dist/secrets/crypto.js.map +1 -1
  215. package/dist/secrets/routes.d.ts +9 -9
  216. package/dist/server/action-change.d.ts +1 -0
  217. package/dist/server/action-change.d.ts.map +1 -1
  218. package/dist/server/action-change.js +4 -1
  219. package/dist/server/action-change.js.map +1 -1
  220. package/dist/server/action-routes.d.ts.map +1 -1
  221. package/dist/server/action-routes.js +5 -0
  222. package/dist/server/action-routes.js.map +1 -1
  223. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  224. package/dist/server/poll.d.ts.map +1 -1
  225. package/dist/server/poll.js +1 -0
  226. package/dist/server/poll.js.map +1 -1
  227. package/dist/server/realtime-voice.d.ts +7 -0
  228. package/dist/server/realtime-voice.d.ts.map +1 -1
  229. package/dist/server/realtime-voice.js +222 -12
  230. package/dist/server/realtime-voice.js.map +1 -1
  231. package/dist/styles/agent-native.css +2 -2
  232. package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +2 -2
  233. package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +2 -2
  234. package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +7 -3
  235. package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +39 -9
  236. package/dist/vite/client.d.ts.map +1 -1
  237. package/dist/vite/client.js +6 -1
  238. package/dist/vite/client.js.map +1 -1
  239. package/package.json +2 -2
  240. package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +2 -2
  241. package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +2 -2
  242. package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +7 -3
  243. package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +39 -9
@@ -1,32 +1,18 @@
1
1
  import {
2
- agentNativePath,
3
2
  ChangelogSettingsCard,
4
3
  LanguagePicker,
5
4
  SettingsTabsPage,
6
5
  useAgentSettingsTabs,
7
- useBuilderConnectFlow,
8
- useBuilderStatus,
9
6
  useSession,
10
7
  useT,
11
8
  type SettingsSearchEntry,
12
9
  type SettingsTabItem,
13
10
  } from "@agent-native/core/client";
14
11
  import { TeamPage } from "@agent-native/core/client/org";
15
- import {
16
- IconBell,
17
- IconCheck,
18
- IconChevronDown,
19
- IconCloud,
20
- IconExternalLink,
21
- IconKey,
22
- IconLoader2,
23
- IconServer,
24
- } from "@tabler/icons-react";
25
- import { useMemo, useState } from "react";
12
+ import { IconBell } from "@tabler/icons-react";
13
+ import { useMemo } from "react";
26
14
  import { Link } from "react-router";
27
- import { toast } from "sonner";
28
15
 
29
- import { Badge } from "@/components/ui/badge";
30
16
  import { Button } from "@/components/ui/button";
31
17
  import {
32
18
  Card,
@@ -35,90 +21,13 @@ import {
35
21
  CardHeader,
36
22
  CardTitle,
37
23
  } from "@/components/ui/card";
38
- import {
39
- Collapsible,
40
- CollapsibleContent,
41
- CollapsibleTrigger,
42
- } from "@/components/ui/collapsible";
43
- import { Input } from "@/components/ui/input";
44
24
  import { Label } from "@/components/ui/label";
45
- import { useReplayStorageStatus } from "@/hooks/use-replay-storage-status";
46
- import { cn } from "@/lib/utils";
47
25
 
48
26
  import changelog from "../../CHANGELOG.md?raw";
27
+ import { useReplayStorageStatus } from "../hooks/use-replay-storage-status";
28
+ import { ReplayStorageHint } from "./sessions/SessionsPage";
49
29
  import { AlertRulesSettingsCard } from "./settings/AlertRulesSettingsCard";
50
30
 
51
- const S3_STORAGE_FIELDS = [
52
- {
53
- key: "S3_ENDPOINT",
54
- labelKey: "settings.s3EndpointLabel",
55
- placeholder: "https://s3.us-east-1.amazonaws.com",
56
- required: true,
57
- },
58
- {
59
- key: "S3_BUCKET",
60
- labelKey: "settings.s3BucketLabel",
61
- placeholder: "my-replays-bucket",
62
- required: true,
63
- },
64
- {
65
- key: "S3_ACCESS_KEY_ID",
66
- labelKey: "settings.s3AccessKeyLabel",
67
- placeholder: "AKIA...",
68
- required: true,
69
- },
70
- {
71
- key: "S3_SECRET_ACCESS_KEY",
72
- labelKey: "settings.s3SecretAccessKeyLabel",
73
- placeholder: "••••••••",
74
- required: true,
75
- secret: true,
76
- },
77
- {
78
- key: "S3_REGION",
79
- labelKey: "settings.s3RegionLabel",
80
- placeholder: "us-east-1",
81
- },
82
- {
83
- key: "S3_PUBLIC_BASE_URL",
84
- labelKey: "settings.s3PublicBaseUrlLabel",
85
- placeholder: "https://cdn.example.com",
86
- },
87
- ] as const;
88
-
89
- async function saveS3StorageSettings(
90
- values: Record<string, string>,
91
- ): Promise<void> {
92
- const vars = S3_STORAGE_FIELDS.map((field) => ({
93
- key: field.key,
94
- value: (values[field.key] ?? "").trim(),
95
- })).filter((entry) => entry.value.length > 0);
96
-
97
- if (vars.length === 0) {
98
- throw new Error("Enter at least one storage value.");
99
- }
100
-
101
- for (const { key, value } of vars) {
102
- const res = await fetch(agentNativePath("/_agent-native/secrets/adhoc"), {
103
- method: "POST",
104
- headers: { "Content-Type": "application/json" },
105
- body: JSON.stringify({
106
- name: key,
107
- value,
108
- scope: "workspace",
109
- description: "Analytics S3-compatible replay storage", // i18n-ignore -- secret metadata description, not visible UI
110
- }),
111
- });
112
-
113
- if (!res.ok) {
114
- const body = (await res.json().catch(() => null)) as {
115
- error?: string;
116
- } | null;
117
- throw new Error(body?.error ?? `Save failed (${res.status})`);
118
- }
119
- }
120
- }
121
-
122
31
  export default function Settings() {
123
32
  // Settings is also reachable directly from the full-page agent surface.
124
33
  // Read the session from the framework's owning AppProviders boundary rather
@@ -127,73 +36,7 @@ export default function Settings() {
127
36
  const { session: auth } = useSession();
128
37
  const t = useT();
129
38
  const agentSettingsTabs = useAgentSettingsTabs();
130
-
131
- const storageStatus = useReplayStorageStatus();
132
- const builderStatus = useBuilderStatus();
133
- const builderConnect = useBuilderConnectFlow({
134
- popupUrl:
135
- builderStatus.status?.cliAuthUrl ?? builderStatus.status?.connectUrl,
136
- trackingSource: "analytics_settings",
137
- trackingFlow: "replay_storage",
138
- onConnected: async () => {
139
- await Promise.all([storageStatus.refetch(), builderStatus.refetch()]);
140
- toast.success(t("settings.builderConnectedToast"));
141
- },
142
- });
143
-
144
- const [savingStorage, setSavingStorage] = useState(false);
145
- const [s3Values, setS3Values] = useState<Record<string, string>>({});
146
- const [s3Expanded, setS3Expanded] = useState(false);
147
-
148
- const storageConfigured = !!storageStatus.data?.configured;
149
- const activeProviderName = storageStatus.data?.activeProvider?.name ?? null;
150
- const activeProviderId = storageStatus.data?.activeProvider?.id ?? null;
151
- const builderConnected = Boolean(
152
- builderConnect.configured ||
153
- builderStatus.status?.configured ||
154
- storageStatus.data?.builderConfigured ||
155
- activeProviderId === "builder",
156
- );
157
- const builderOrgName =
158
- builderConnect.orgName ?? builderStatus.status?.orgName ?? null;
159
- const builderStatusLoading =
160
- storageStatus.isLoading ||
161
- builderStatus.loading ||
162
- !builderConnect.hasFetchedStatus;
163
- const s3Configured = activeProviderId === "s3";
164
- const s3Collapsed = builderConnected && !s3Expanded;
165
-
166
- async function handleSaveS3Storage() {
167
- const missing = s3Configured
168
- ? []
169
- : S3_STORAGE_FIELDS.filter(
170
- (field) =>
171
- "required" in field &&
172
- field.required &&
173
- !(s3Values[field.key] ?? "").trim(),
174
- );
175
- if (missing.length > 0) {
176
- toast.error(t("settings.storageRequired"));
177
- return;
178
- }
179
-
180
- setSavingStorage(true);
181
- try {
182
- await saveS3StorageSettings(s3Values);
183
- setS3Values((current) => ({
184
- ...current,
185
- S3_SECRET_ACCESS_KEY: "",
186
- }));
187
- await storageStatus.refetch();
188
- toast.success(t("settings.storageSaved"));
189
- } catch (err) {
190
- toast.error(
191
- err instanceof Error ? err.message : t("settings.storageSaveFailed"),
192
- );
193
- } finally {
194
- setSavingStorage(false);
195
- }
196
- }
39
+ const replayStorageStatus = useReplayStorageStatus();
197
40
 
198
41
  const extraTabs = useMemo<SettingsTabItem[]>(
199
42
  () => [
@@ -227,18 +70,22 @@ export default function Settings() {
227
70
  keywords: "data sources api keys manage credentials",
228
71
  hash: "credentials",
229
72
  },
230
- {
231
- id: "analytics-replay-storage",
232
- label: t("settings.replayStorage"),
233
- keywords: "storage s3 builder replay bucket cloud",
234
- hash: "replay-storage",
235
- },
236
73
  {
237
74
  id: "analytics-dashboard-templates",
238
75
  label: t("settings.dashboardTemplates"),
239
76
  keywords: "templates catalog dashboards",
240
77
  hash: "dashboard-templates",
241
78
  },
79
+ ...(replayStorageStatus.data?.configured
80
+ ? [
81
+ {
82
+ id: "analytics-replay-storage",
83
+ label: t("sessions.storageSetupTitle"),
84
+ keywords: "session replay recording storage s3 bucket builder",
85
+ hash: "replay-storage",
86
+ },
87
+ ]
88
+ : []),
242
89
  {
243
90
  id: "analytics-language",
244
91
  label: t("settings.languageTitle"),
@@ -252,7 +99,7 @@ export default function Settings() {
252
99
  hash: "about",
253
100
  },
254
101
  ],
255
- [t],
102
+ [replayStorageStatus.data?.configured, t],
256
103
  );
257
104
 
258
105
  return (
@@ -302,178 +149,6 @@ export default function Settings() {
302
149
  </CardContent>
303
150
  </Card>
304
151
 
305
- <Card
306
- id="replay-storage"
307
- className="bg-card border-border/50 scroll-mt-16"
308
- >
309
- <CardHeader>
310
- <CardTitle className="text-base flex items-center gap-2">
311
- <IconCloud className="size-4 text-primary" />
312
- {t("settings.replayStorage")}
313
- </CardTitle>
314
- <CardDescription>
315
- {t("settings.replayStorageDescription")}
316
- </CardDescription>
317
- </CardHeader>
318
- <CardContent className="space-y-4">
319
- <div
320
- className={cn(
321
- "flex flex-col gap-3 rounded-md border px-3 py-3 sm:flex-row sm:items-center sm:justify-between",
322
- builderConnected
323
- ? "border-primary/35 bg-primary/5"
324
- : "border-border bg-accent/30",
325
- )}
326
- >
327
- <div className="min-w-0">
328
- <div className="flex items-center gap-2 text-sm font-medium">
329
- {builderConnected ? (
330
- <IconCheck className="h-4 w-4 text-primary" />
331
- ) : (
332
- <IconKey className="h-4 w-4 text-muted-foreground" />
333
- )}
334
- {builderStatusLoading
335
- ? t("settings.checkingBuilder")
336
- : builderConnected
337
- ? t("settings.builderConnected")
338
- : t("settings.connectBuilder")}
339
- </div>
340
- <p className="mt-0.5 text-xs text-muted-foreground">
341
- {builderConnected
342
- ? builderOrgName
343
- ? t("settings.builderConnectedFor", {
344
- orgName: builderOrgName,
345
- })
346
- : t("settings.builderConnectedGeneric")
347
- : t("settings.builderIncludes")}
348
- </p>
349
- </div>
350
- {builderConnected ? (
351
- <Badge variant="secondary" className="shrink-0">
352
- {t("settings.connected")}
353
- </Badge>
354
- ) : (
355
- <Button
356
- type="button"
357
- variant="outline"
358
- size="sm"
359
- className="shrink-0"
360
- onClick={() =>
361
- builderConnect.start({
362
- trackingSource: "analytics_settings_replay_storage",
363
- trackingFlow: "replay_storage",
364
- })
365
- }
366
- disabled={builderConnect.connecting || builderStatusLoading}
367
- >
368
- {builderConnect.connecting ? (
369
- <IconLoader2 className="h-4 w-4 animate-spin" />
370
- ) : (
371
- <IconExternalLink className="h-4 w-4" />
372
- )}
373
- {t("settings.connectBuilder")}
374
- </Button>
375
- )}
376
- </div>
377
-
378
- <Collapsible
379
- open={builderConnected ? !s3Collapsed : true}
380
- onOpenChange={(open) => setS3Expanded(open)}
381
- >
382
- <div className="rounded-md border border-border">
383
- <div className="flex flex-col gap-3 px-3 py-3 sm:flex-row sm:items-center sm:justify-between">
384
- <div className="min-w-0">
385
- <div className="flex flex-wrap items-center gap-2 text-sm font-medium">
386
- <IconServer className="h-4 w-4 text-muted-foreground" />
387
- {t("settings.s3Title")}
388
- <Badge variant="outline" className="text-[10px]">
389
- {t("settings.secondary")}
390
- </Badge>
391
- {s3Configured ? (
392
- <Badge variant="secondary" className="text-[10px]">
393
- {t("settings.active")}
394
- </Badge>
395
- ) : null}
396
- </div>
397
- <p className="mt-0.5 text-xs text-muted-foreground">
398
- {builderConnected
399
- ? t("settings.s3BuilderConnectedDescription")
400
- : storageConfigured && activeProviderName
401
- ? t("settings.s3CurrentProvider", {
402
- providerName: activeProviderName,
403
- })
404
- : t("settings.s3OwnBucketDescription")}
405
- </p>
406
- </div>
407
- {builderConnected ? (
408
- <CollapsibleTrigger asChild>
409
- <Button
410
- type="button"
411
- variant="ghost"
412
- size="sm"
413
- className="shrink-0"
414
- >
415
- {s3Collapsed
416
- ? t("settings.configureS3")
417
- : t("settings.hideS3")}
418
- <IconChevronDown
419
- className={cn(
420
- "h-4 w-4 transition-transform",
421
- !s3Collapsed && "rotate-180",
422
- )}
423
- />
424
- </Button>
425
- </CollapsibleTrigger>
426
- ) : null}
427
- </div>
428
-
429
- <CollapsibleContent>
430
- <div className="space-y-4 border-t border-border px-3 py-4">
431
- <div className="grid gap-4 sm:grid-cols-2">
432
- {S3_STORAGE_FIELDS.map((field) => (
433
- <div key={field.key} className="space-y-1.5">
434
- <Label htmlFor={field.key}>
435
- {t(field.labelKey)}
436
- </Label>
437
- <Input
438
- id={field.key}
439
- type={
440
- "secret" in field && field.secret
441
- ? "password"
442
- : "text"
443
- }
444
- value={s3Values[field.key] ?? ""}
445
- onChange={(event) =>
446
- setS3Values((current) => ({
447
- ...current,
448
- [field.key]: event.target.value,
449
- }))
450
- }
451
- placeholder={field.placeholder}
452
- autoComplete="off"
453
- disabled={savingStorage}
454
- />
455
- </div>
456
- ))}
457
- </div>
458
-
459
- <div className="flex justify-end">
460
- <Button
461
- onClick={handleSaveS3Storage}
462
- disabled={savingStorage || storageStatus.isLoading}
463
- >
464
- {savingStorage && (
465
- <IconLoader2 className="h-4 w-4 animate-spin" />
466
- )}
467
- {t("settings.saveStorage")}
468
- </Button>
469
- </div>
470
- </div>
471
- </CollapsibleContent>
472
- </div>
473
- </Collapsible>
474
- </CardContent>
475
- </Card>
476
-
477
152
  <Card
478
153
  id="dashboard-templates"
479
154
  className="bg-card border-border/50 scroll-mt-16"
@@ -495,6 +170,25 @@ export default function Settings() {
495
170
  </CardContent>
496
171
  </Card>
497
172
 
173
+ {replayStorageStatus.data?.configured ? (
174
+ <Card
175
+ id="replay-storage"
176
+ className="bg-card border-border/50 scroll-mt-16"
177
+ >
178
+ <CardHeader>
179
+ <CardTitle className="text-base">
180
+ {t("sessions.storageSetupTitle")}
181
+ </CardTitle>
182
+ <CardDescription>
183
+ {t("sessions.storageSetupDescription")}
184
+ </CardDescription>
185
+ </CardHeader>
186
+ <CardContent>
187
+ <ReplayStorageHint />
188
+ </CardContent>
189
+ </Card>
190
+ ) : null}
191
+
498
192
  <Card id="language" className="bg-card border-border/50 scroll-mt-16">
499
193
  <CardHeader>
500
194
  <CardTitle className="text-base">
@@ -43,9 +43,8 @@ export function ErrorsPanel() {
43
43
  const queryClient = useQueryClient();
44
44
  const [searchParams, setSearchParams] = useSearchParams();
45
45
  const selectedId = searchParams.get("issue");
46
-
47
- const [status, setStatus] = useState<StatusFilter>("unresolved");
48
- const [search, setSearch] = useState("");
46
+ const status = errorStatusFromSearchParams(searchParams);
47
+ const search = searchParams.get("q") ?? "";
49
48
  const debouncedSearch = useDebouncedValue(search, 250);
50
49
 
51
50
  const sync = useChangeVersions(["error-issues", "action"]);
@@ -96,9 +95,32 @@ export function ErrorsPanel() {
96
95
  }
97
96
  : selectedId
98
97
  ? { view: "errors", issueId: selectedId }
99
- : { view: "errors" };
98
+ : {
99
+ view: "errors",
100
+ status,
101
+ ...(search.trim() ? { query: search.trim() } : {}),
102
+ };
100
103
  void setClientAppState("monitoring", value).catch(() => {});
101
- }, [selectedIssue, selectedId]);
104
+ }, [search, selectedIssue, selectedId, status]);
105
+
106
+ const updateFilters = (next: { status?: StatusFilter; search?: string }) => {
107
+ setSearchParams(
108
+ (prev) => {
109
+ const params = new URLSearchParams(prev);
110
+ if (next.status) {
111
+ if (next.status === "unresolved") params.delete("status");
112
+ else params.set("status", next.status);
113
+ }
114
+ if (next.search !== undefined) {
115
+ const query = next.search.trim();
116
+ if (query) params.set("q", next.search);
117
+ else params.delete("q");
118
+ }
119
+ return params;
120
+ },
121
+ { replace: true },
122
+ );
123
+ };
102
124
 
103
125
  const selectIssue = (id: string | null) => {
104
126
  setSearchParams(
@@ -188,9 +210,9 @@ export function ErrorsPanel() {
188
210
  issues={issues}
189
211
  isLoading={isLoading}
190
212
  status={status}
191
- onStatusChange={setStatus}
213
+ onStatusChange={(nextStatus) => updateFilters({ status: nextStatus })}
192
214
  search={search}
193
- onSearchChange={setSearch}
215
+ onSearchChange={(nextSearch) => updateFilters({ search: nextSearch })}
194
216
  onRefresh={() => void refetch()}
195
217
  isFetching={isFetching}
196
218
  onSelect={selectIssue}
@@ -200,3 +222,12 @@ export function ErrorsPanel() {
200
222
  />
201
223
  );
202
224
  }
225
+
226
+ export function errorStatusFromSearchParams(
227
+ searchParams: URLSearchParams,
228
+ ): StatusFilter {
229
+ const status = searchParams.get("status");
230
+ return status === "resolved" || status === "ignored" || status === "all"
231
+ ? status
232
+ : "unresolved";
233
+ }
@@ -55,7 +55,7 @@ export default function MonitoringPage() {
55
55
 
56
56
  const toggles = (
57
57
  <div className="flex shrink-0 items-center gap-2">
58
- <RunsTray />
58
+ <RunsTray pollMs={0} />
59
59
  <AgentToggleButton />
60
60
  </div>
61
61
  );
@@ -86,6 +86,9 @@ const MESSAGES = {
86
86
  viewIssue: "View issue",
87
87
  viewIssueTooltip:
88
88
  "Open this error's issue — how many users hit it, the stack trace, and recent occurrences",
89
+ searchIssues: "Find similar",
90
+ searchIssuesTooltip:
91
+ "Search Monitoring for all captured issues matching this console error",
89
92
  // Toasts
90
93
  resolvedToast: "Issue resolved.",
91
94
  reopenedToast: "Issue reopened.",