@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.
- package/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +24 -0
- package/corpus/core/package.json +2 -2
- package/corpus/core/src/action-change-marker.ts +8 -1
- package/corpus/core/src/changelog/parse.ts +8 -3
- package/corpus/core/src/client/AgentPanel.tsx +2 -3
- package/corpus/core/src/client/AssistantChat.tsx +83 -39
- package/corpus/core/src/client/analytics.ts +29 -0
- package/corpus/core/src/client/blocks/library/wireframe-kit.tsx +16 -2
- package/corpus/core/src/client/chat-model-groups.ts +28 -0
- package/corpus/core/src/client/composer/RealtimeVoiceMode.tsx +442 -85
- package/corpus/core/src/client/composer/TiptapComposer.tsx +46 -29
- package/corpus/core/src/client/composer/VoiceButton.tsx +2 -1
- package/corpus/core/src/client/composer/index.ts +5 -0
- package/corpus/core/src/client/composer/useRealtimeVoiceMode.tsx +1206 -67
- package/corpus/core/src/client/index.ts +5 -0
- package/corpus/core/src/client/progress/RunsTray.tsx +13 -1
- package/corpus/core/src/client/settings/SecretsSection.tsx +387 -266
- package/corpus/core/src/client/settings/SettingsPanel.tsx +117 -38
- package/corpus/core/src/client/use-action.ts +12 -0
- package/corpus/core/src/client/use-agent-chat-home-handoff.ts +8 -1
- package/corpus/core/src/client/use-agent-engine-configured.ts +17 -3
- package/corpus/core/src/client/use-db-sync.ts +84 -34
- package/corpus/core/src/client/use-pausing-interval.ts +14 -4
- package/corpus/core/src/integrations/scope-store.ts +1 -1
- package/corpus/core/src/integrations/usage-budget-store.ts +1 -1
- package/corpus/core/src/localization/default-messages.ts +44 -1
- package/corpus/core/src/mcp-client/workspace-servers.ts +4 -4
- package/corpus/core/src/secrets/crypto.ts +28 -8
- package/corpus/core/src/server/action-change.ts +5 -1
- package/corpus/core/src/server/action-routes.ts +8 -0
- package/corpus/core/src/server/poll.ts +1 -0
- package/corpus/core/src/server/realtime-voice.ts +299 -13
- package/corpus/core/src/styles/agent-native.css +2 -2
- package/corpus/core/src/templates/default/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/corpus/core/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +7 -3
- package/corpus/core/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +39 -9
- package/corpus/core/src/vite/client.ts +9 -1
- package/corpus/templates/analytics/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +10 -5
- package/corpus/templates/analytics/AGENTS.md +9 -13
- package/corpus/templates/analytics/actions/navigate.ts +59 -5
- package/corpus/templates/analytics/actions/view-screen.ts +3 -6
- package/corpus/templates/analytics/app/components/ProviderCorpusJobNotifier.tsx +20 -3
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +2 -1
- package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -1
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +21 -6
- package/corpus/templates/analytics/app/global.css +19 -20
- package/corpus/templates/analytics/app/lib/provider-corpus-job-sync.ts +26 -0
- package/corpus/templates/analytics/app/pages/Settings.tsx +35 -341
- package/corpus/templates/analytics/app/pages/monitoring/ErrorsPanel.tsx +38 -7
- package/corpus/templates/analytics/app/pages/monitoring/MonitoringPage.tsx +1 -1
- package/corpus/templates/analytics/app/pages/monitoring/errors/i18n.ts +3 -0
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +333 -272
- package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +72 -17
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +297 -108
- package/corpus/templates/analytics/app/root.tsx +28 -8
- package/corpus/templates/analytics/changelog/2026-06-24-first-party-signup-and-pageview-panels-now-honor-dashboard-filters.md +2 -1
- package/corpus/templates/analytics/changelog/2026-06-25-referrer-dashboard-panels-show-external-domains.md +2 -1
- package/corpus/templates/analytics/changelog/2026-07-06-mobile-chat-header-is-more-compact-and-the-menu-button-opens-navigation.md +1 -0
- package/corpus/templates/analytics/changelog/2026-07-08-dashboard-history-and-chat-context.md +1 -0
- package/corpus/templates/analytics/changelog/2026-07-08-settings-are-cleaner-searchable-and-alerts-have-their-own-tab.md +1 -0
- package/corpus/templates/analytics/changelog/2026-07-08-sidebar-sections-stay-collapsed-until-opened.md +1 -0
- package/corpus/templates/analytics/changelog/2026-07-11-analytics-no-longer-repeatedly-restarts-background-requests-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-11-analytics-only-asks-for-replay-storage-when-you-enable-sessi.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-11-charts-now-show-their-loading-skeleton-while-refreshing.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-11-realtime-voice-now-shows-a-clear-connection-indicator-comple.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-11-replay-event-counts-stay-hidden-until-recordings-finish-load.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-11-replay-storage-key-mismatches-show-actionable-setup-guidance.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-11-replay-timelines-group-continuous-scrolling-and-dev-tools-co.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-11-session-filters-now-stay-compact-in-a-settings-menu-at-mediu.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-11-session-replay-console-errors-now-link-to-matching-issues-or.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-11-session-replays-load-large-recordings-faster-and-surface-fai.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-11-session-replays-preserve-recorded-styles-and-viewport-layout.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-11-session-replays-stay-centered-instead-of-clipping-wide-recor.md +6 -0
- package/corpus/templates/analytics/package.json +1 -1
- package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +1 -303
- package/corpus/templates/analytics/server/handlers/session-replay.ts +57 -0
- package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +1 -1
- package/corpus/templates/analytics/server/lib/demo-dashboards.ts +16 -3
- package/corpus/templates/analytics/server/lib/session-replay-agent-context.ts +12 -0
- package/corpus/templates/analytics/server/lib/session-replay.ts +208 -2
- package/corpus/templates/analytics/server/plugins/onboarding.ts +7 -79
- package/corpus/templates/analytics/server/routes/api/session-replay/recordings/[recordingId]/chunks.get.ts +1 -0
- package/corpus/templates/assets/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/corpus/templates/assets/app/global.css +4 -4
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +0 -1
- package/corpus/templates/assets/app/routes/library.tsx +0 -1
- package/corpus/templates/brain/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/corpus/templates/brain/app/global.css +5 -5
- package/corpus/templates/brain/app/root.tsx +0 -3
- package/corpus/templates/calendar/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/corpus/templates/calendar/app/root.tsx +1 -0
- package/corpus/templates/chat/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/corpus/templates/clips/app/hooks/use-auto-title.ts +74 -8
- package/corpus/templates/clips/app/hooks/use-library.ts +12 -25
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +20 -22
- package/corpus/templates/clips/changelog/2026-07-11-generated-titles-no-longer-cause-continuous-background-refreshes.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-11-s3-storage-setup-stays-collapsed-until-you-choose-it-as-the-.md +6 -0
- package/corpus/templates/content/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/corpus/templates/content/app/hooks/use-comments.ts +0 -1
- package/corpus/templates/content/changelog/2026-07-11-comments-now-update-from-live-collaboration-events-without-c.md +6 -0
- package/corpus/templates/design/app/components/layout/Header.tsx +1 -1
- package/corpus/templates/forms/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/corpus/templates/macros/app/components/layout/AppLayout.tsx +1 -2
- package/corpus/templates/macros/app/root.tsx +0 -3
- package/corpus/templates/mail/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/corpus/templates/mail/app/hooks/use-compose-state.ts +1 -0
- package/corpus/templates/mail/app/root.tsx +1 -12
- package/corpus/templates/plan/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/corpus/templates/plan/app/hooks/use-navigation-state.ts +5 -2
- package/corpus/templates/plan/app/hooks/use-plans.ts +6 -13
- package/corpus/templates/plan/app/pages/PlansPage.tsx +5 -27
- package/corpus/templates/plan/changelog/2026-07-11-plan-refreshes-only-when-content-changes.md +6 -0
- package/corpus/templates/slides/app/components/comments/SlideCommentsPanel.tsx +4 -1
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +1 -1
- package/corpus/templates/slides/app/components/layout/Header.tsx +1 -1
- package/corpus/templates/slides/app/context/DeckContext.tsx +1 -0
- package/corpus/templates/slides/app/hooks/use-slide-comments.ts +7 -31
- package/corpus/templates/slides/changelog/2026-07-11-comments-now-update-from-live-collaboration-events-without-c.md +6 -0
- package/dist/action-change-marker.d.ts +1 -0
- package/dist/action-change-marker.d.ts.map +1 -1
- package/dist/action-change-marker.js +7 -1
- package/dist/action-change-marker.js.map +1 -1
- package/dist/changelog/parse.d.ts +4 -2
- package/dist/changelog/parse.d.ts.map +1 -1
- package/dist/changelog/parse.js +5 -3
- package/dist/changelog/parse.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +2 -3
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +7 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +62 -40
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +26 -0
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/blocks/library/wireframe-kit.d.ts +2 -0
- package/dist/client/blocks/library/wireframe-kit.d.ts.map +1 -1
- package/dist/client/blocks/library/wireframe-kit.js +9 -2
- package/dist/client/blocks/library/wireframe-kit.js.map +1 -1
- package/dist/client/chat-model-groups.d.ts.map +1 -1
- package/dist/client/chat-model-groups.js +24 -0
- package/dist/client/chat-model-groups.js.map +1 -1
- package/dist/client/composer/RealtimeVoiceMode.d.ts +40 -4
- package/dist/client/composer/RealtimeVoiceMode.d.ts.map +1 -1
- package/dist/client/composer/RealtimeVoiceMode.js +172 -42
- package/dist/client/composer/RealtimeVoiceMode.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts +4 -0
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +47 -29
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/composer/VoiceButton.d.ts.map +1 -1
- package/dist/client/composer/VoiceButton.js +2 -2
- package/dist/client/composer/VoiceButton.js.map +1 -1
- package/dist/client/composer/index.d.ts +2 -2
- package/dist/client/composer/index.d.ts.map +1 -1
- package/dist/client/composer/index.js +1 -1
- package/dist/client/composer/index.js.map +1 -1
- package/dist/client/composer/useRealtimeVoiceMode.d.ts +100 -3
- package/dist/client/composer/useRealtimeVoiceMode.d.ts.map +1 -1
- package/dist/client/composer/useRealtimeVoiceMode.js +952 -51
- package/dist/client/composer/useRealtimeVoiceMode.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/progress/RunsTray.d.ts.map +1 -1
- package/dist/client/progress/RunsTray.js +10 -1
- package/dist/client/progress/RunsTray.js.map +1 -1
- package/dist/client/settings/SecretsSection.d.ts +2 -3
- package/dist/client/settings/SecretsSection.d.ts.map +1 -1
- package/dist/client/settings/SecretsSection.js +46 -22
- package/dist/client/settings/SecretsSection.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts +9 -0
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +46 -12
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/use-action.d.ts +2 -0
- package/dist/client/use-action.d.ts.map +1 -1
- package/dist/client/use-action.js +10 -0
- package/dist/client/use-action.js.map +1 -1
- package/dist/client/use-agent-chat-home-handoff.d.ts +2 -0
- package/dist/client/use-agent-chat-home-handoff.d.ts.map +1 -1
- package/dist/client/use-agent-chat-home-handoff.js +7 -1
- package/dist/client/use-agent-chat-home-handoff.js.map +1 -1
- package/dist/client/use-agent-engine-configured.d.ts.map +1 -1
- package/dist/client/use-agent-engine-configured.js +17 -3
- package/dist/client/use-agent-engine-configured.js.map +1 -1
- package/dist/client/use-db-sync.d.ts +8 -2
- package/dist/client/use-db-sync.d.ts.map +1 -1
- package/dist/client/use-db-sync.js +57 -32
- package/dist/client/use-db-sync.js.map +1 -1
- package/dist/client/use-pausing-interval.d.ts.map +1 -1
- package/dist/client/use-pausing-interval.js +16 -4
- package/dist/client/use-pausing-interval.js.map +1 -1
- package/dist/integrations/scope-store.js +1 -1
- package/dist/integrations/scope-store.js.map +1 -1
- package/dist/integrations/usage-budget-store.js +1 -1
- package/dist/integrations/usage-budget-store.js.map +1 -1
- package/dist/localization/default-messages.d.ts +41 -1
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +41 -1
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/mcp-client/workspace-servers.js +4 -4
- package/dist/mcp-client/workspace-servers.js.map +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/secrets/crypto.d.ts +7 -6
- package/dist/secrets/crypto.d.ts.map +1 -1
- package/dist/secrets/crypto.js +30 -11
- package/dist/secrets/crypto.js.map +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/action-change.d.ts +1 -0
- package/dist/server/action-change.d.ts.map +1 -1
- package/dist/server/action-change.js +4 -1
- package/dist/server/action-change.js.map +1 -1
- package/dist/server/action-routes.d.ts.map +1 -1
- package/dist/server/action-routes.js +5 -0
- package/dist/server/action-routes.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/poll.d.ts.map +1 -1
- package/dist/server/poll.js +1 -0
- package/dist/server/poll.js.map +1 -1
- package/dist/server/realtime-voice.d.ts +7 -0
- package/dist/server/realtime-voice.d.ts.map +1 -1
- package/dist/server/realtime-voice.js +222 -12
- package/dist/server/realtime-voice.js.map +1 -1
- package/dist/styles/agent-native.css +2 -2
- package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +7 -3
- package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +39 -9
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +6 -1
- package/dist/vite/client.js.map +1 -1
- package/package.json +2 -2
- package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +2 -2
- package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +7 -3
- 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
|
-
|
|
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
|
|
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
|
-
: {
|
|
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={
|
|
213
|
+
onStatusChange={(nextStatus) => updateFilters({ status: nextStatus })}
|
|
192
214
|
search={search}
|
|
193
|
-
onSearchChange={
|
|
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
|
+
}
|
|
@@ -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.",
|