@agent-native/core 0.154.5 → 0.155.0
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/templates/analytics/.agents/skills/account-health/SKILL.md +76 -0
- package/corpus/templates/analytics/.agents/skills/bigquery/SKILL.md +3 -0
- package/corpus/templates/analytics/.agents/skills/cross-source-analysis/SKILL.md +2 -1
- package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +6 -5
- package/corpus/templates/analytics/AGENTS.md +3 -0
- package/corpus/templates/analytics/actions/account-deep-dive.ts +3 -2
- package/corpus/templates/analytics/actions/bigquery.ts +1 -1
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +4 -1
- package/corpus/templates/analytics/app/components/layout/NewDashboardDialog.tsx +1 -0
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/PropertyCombobox.tsx +12 -4
- package/corpus/templates/analytics/app/pages/adhoc/explorer/components/PropertyValueCombobox.tsx +5 -2
- package/corpus/templates/analytics/app/pages/adhoc/explorer/property-label.ts +32 -0
- package/corpus/templates/analytics/changelog/2026-08-13-account-health-readouts-verify-customer-scope-and-contract-metrics.md +7 -0
- package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +43 -17
- package/corpus/templates/analytics/server/lib/analytics-query-catalog.ts +17 -0
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +4 -0
- package/corpus/templates/calendar/AGENTS.md +2 -0
- package/corpus/templates/calendar/DEVELOPING.md +4 -4
- package/corpus/templates/calendar/actions/get-settings.ts +4 -11
- package/corpus/templates/calendar/actions/update-availability.ts +15 -4
- package/corpus/templates/calendar/actions/update-settings.ts +15 -4
- package/corpus/templates/calendar/app/components/booking/DatePicker.tsx +9 -3
- package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +21 -19
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +9 -6
- package/corpus/templates/calendar/app/components/calendar/FindTimePanel.tsx +25 -3
- package/corpus/templates/calendar/app/components/calendar/InlineEventPickers.tsx +10 -3
- package/corpus/templates/calendar/app/components/calendar/MonthView.tsx +9 -9
- package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +11 -3
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +10 -4
- package/corpus/templates/calendar/app/i18n-data.ts +30 -0
- package/corpus/templates/calendar/app/lib/availability-schedule.ts +53 -0
- package/corpus/templates/calendar/app/lib/event-form-utils.ts +5 -0
- package/corpus/templates/calendar/app/pages/AvailabilitySettings.tsx +90 -28
- package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +135 -61
- package/corpus/templates/calendar/app/pages/BookingPage.tsx +2 -0
- package/corpus/templates/calendar/app/pages/CalendarView.tsx +30 -15
- package/corpus/templates/calendar/app/pages/Settings.tsx +60 -1
- package/corpus/templates/calendar/changelog/2026-08-13-find-a-time-now-closes-from-a-clear-header-action.md +6 -0
- package/corpus/templates/calendar/server/handlers/bookings.ts +2 -1
- package/corpus/templates/calendar/server/handlers/settings.ts +12 -16
- package/corpus/templates/calendar/shared/api.ts +1 -0
- package/corpus/templates/calendar/shared/availability-schedule.ts +64 -0
- package/corpus/templates/calendar/shared/calendar-week.ts +21 -0
- package/corpus/templates/calendar/shared/settings.ts +44 -0
- package/corpus/templates/clips/AGENTS.md +2 -0
- package/corpus/templates/clips/actions/add-comment.ts +5 -2
- package/corpus/templates/clips/actions/finalize-recording.ts +31 -1
- package/corpus/templates/clips/actions/get-recording-player-data.ts +9 -0
- package/corpus/templates/clips/actions/lib/ensure-seekable-video.ts +21 -1
- package/corpus/templates/clips/actions/reply-to-comment.ts +5 -2
- package/corpus/templates/clips/actions/update-comment.ts +9 -2
- package/corpus/templates/clips/app/components/library/search-bar.tsx +26 -13
- package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +135 -3
- package/corpus/templates/clips/app/components/player/comments-panel.tsx +5 -99
- package/corpus/templates/clips/app/components/player/playback-comment-overlay.tsx +7 -3
- package/corpus/templates/clips/app/components/player/video-player.tsx +84 -24
- package/corpus/templates/clips/app/components/workspace/notifications-list.tsx +11 -3
- package/corpus/templates/clips/app/i18n/en-US.ts +12 -0
- package/corpus/templates/clips/app/lib/public-meeting.ts +11 -3
- package/corpus/templates/clips/app/lib/search-focus.ts +15 -0
- package/corpus/templates/clips/app/root.tsx +2 -1
- package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +94 -26
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +24 -7
- package/corpus/templates/clips/app/routes/embed.$shareId.tsx +8 -4
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +14 -7
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +8 -4
- package/corpus/templates/clips/app/routes/share.meeting.$meetingId.tsx +72 -26
- package/corpus/templates/clips/changelog/2026-08-13-inline-markdown-comments.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-13-private-meeting-agent-links.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +116 -19
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +13 -29
- package/corpus/templates/clips/desktop/src/lib/recording-request.ts +39 -0
- package/corpus/templates/clips/desktop/src/lib/settings-navigation.ts +11 -0
- package/corpus/templates/clips/desktop/src/lib/whisper-model-picker.ts +7 -0
- package/corpus/templates/clips/desktop/src/styles.css +117 -0
- package/corpus/templates/clips/server/db/index.ts +10 -0
- package/corpus/templates/clips/server/db/schema.ts +1 -0
- package/corpus/templates/clips/server/lib/recordings.ts +3 -1
- package/corpus/templates/clips/server/lib/seekable-media-state.ts +90 -0
- package/corpus/templates/clips/server/plugins/db.ts +5 -0
- package/corpus/templates/clips/server/routes/api/public-meeting.get.ts +37 -4
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +16 -5
- package/corpus/templates/clips/shared/clips-ai-prefs.ts +3 -0
- package/corpus/templates/clips/shared/meeting-agent-access.ts +5 -0
- package/corpus/templates/content/actions/add-comment.ts +2 -1
- package/corpus/templates/content/actions/update-comment.ts +1 -1
- package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +24 -15
- package/corpus/templates/design/actions/generate-design.ts +10 -7
- package/corpus/templates/design/actions/present-design-variants.ts +35 -6
- package/corpus/templates/design/actions/run-design-audit.ts +33 -0
- package/corpus/templates/design/changelog/2026-08-13-the-design-audit-now-catches-a-screen-that-renders-behind-an.md +6 -0
- package/corpus/templates/design/shared/design-review.ts +1 -0
- package/corpus/templates/design/shared/html-integrity.ts +66 -0
- package/corpus/templates/dispatch/.env.example +5 -0
- package/corpus/templates/dispatch/AGENTS.md +24 -19
- package/corpus/templates/dispatch/app/i18n-data.ts +20 -0
- package/corpus/templates/dispatch/server/lib/identity-sso.ts +21 -90
- package/corpus/templates/dispatch/server/plugins/identity-sso.ts +3 -12
- package/corpus/templates/dispatch/shared/feature-flags.ts +4 -0
- package/corpus/templates/factory/AGENTS.md +5 -1
- package/corpus/templates/factory/README.md +23 -0
- package/corpus/templates/factory/actions/view-screen.ts +17 -0
- package/corpus/templates/factory/app/components/factory/FactoryAgentsView.tsx +239 -0
- package/corpus/templates/factory/app/components/factory/FactoryCanvas.tsx +2 -0
- package/corpus/templates/factory/app/components/factory/FactoryInspector.tsx +130 -7
- package/corpus/templates/factory/app/i18n/en-US.ts +20 -0
- package/corpus/templates/factory/app/routes/factory.tsx +41 -0
- package/corpus/templates/factory/package.json +1 -0
- package/corpus/templates/factory/server/factory-graph/contracts.ts +2 -0
- package/corpus/templates/factory/server/plugins/agent-chat.ts +9 -0
- package/corpus/templates/factory/server/plugins/dispatch-db.ts +1 -0
- package/corpus/templates/factory/server/plugins/setup-dispatch.ts +3 -0
- package/corpus/templates/mail/app/lib/native-mcp-exclusions.ts +3 -0
- package/corpus/templates/mail/vite.config.ts +7 -0
- package/corpus/templates/plan/actions/reply-to-plan-comment.ts +7 -2
- package/corpus/templates/plan/actions/resolve-plan-comment.ts +2 -2
- package/corpus/templates/plan/actions/update-visual-plan.ts +1 -1
- package/corpus/templates/plan/app/pages/PlansPage.tsx +29 -20
- package/corpus/templates/slides/actions/add-slide-comment.ts +1 -1
- package/corpus/templates/slides/actions/update-slide-comment.ts +1 -1
- package/corpus/templates/slides/app/components/comments/SlideCommentsPanel.tsx +9 -6
- package/dist/agent/production-agent.js +5 -1
- package/dist/agent/thread-data-builder.js +17 -1
- package/dist/cli/skills-content/help.js +6 -4
- package/dist/cli/skills.js +17 -2
- package/dist/cli/workspacify.d.ts +5 -0
- package/dist/cli/workspacify.js +65 -8
- package/dist/client/AgentPanel.d.ts +5 -0
- package/dist/client/AgentPanel.js +20 -4
- package/dist/client/AssistantChat.d.ts +21 -0
- package/dist/client/AssistantChat.js +66 -68
- package/dist/client/active-run-state.d.ts +14 -1
- package/dist/client/active-run-state.js +0 -0
- package/dist/client/agent-chat-adapter.js +107 -5
- package/dist/client/analytics.js +9 -2
- package/dist/client/chat/tool-call-display.js +4 -4
- package/dist/client/chat-first/apps-rail.js +9 -4
- package/dist/client/chat-first/primary-nav.d.ts +2 -1
- package/dist/client/chat-first/primary-nav.js +3 -3
- package/dist/client/chat-first/types.d.ts +5 -1
- package/dist/client/markdown/InlineMarkdown.d.ts +23 -0
- package/dist/client/markdown/InlineMarkdown.js +65 -0
- package/dist/client/markdown/index.d.ts +1 -0
- package/dist/client/markdown/index.js +1 -0
- package/dist/client/review/ReviewThreadPanel.js +2 -1
- package/dist/client/run-stream-ownership.d.ts +39 -0
- package/dist/client/run-stream-ownership.js +65 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/feature-flags/index.d.ts +1 -1
- package/dist/feature-flags/index.js +1 -1
- package/dist/feature-flags/store.d.ts +10 -0
- package/dist/feature-flags/store.js +112 -1
- package/dist/guards/no-env-credentials.js +4 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/integrations/adapters/slack.js +5 -1
- package/dist/localization/default-messages.d.ts +1 -0
- package/dist/localization/default-messages.js +1 -0
- package/dist/observability/routes.d.ts +6 -6
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
- package/dist/provider-api/actions/provider-api.d.ts +15 -15
- package/dist/resources/agents.js +40 -5
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/resources/metadata.d.ts +10 -0
- package/dist/resources/metadata.js +7 -3
- package/dist/review/actions/create-review-comment.js +1 -1
- package/dist/review/actions/reply-review-comment.js +1 -1
- package/dist/review/actions/resolve-review-thread.js +1 -1
- package/dist/secrets/routes.d.ts +3 -3
- package/dist/server/action-routes.js +32 -6
- package/dist/server/agent-discovery.js +14 -3
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/core-routes-plugin.js +1 -1
- package/dist/server/identity-sso-migrations.d.ts +7 -0
- package/dist/server/identity-sso-migrations.js +36 -0
- package/dist/server/identity-sso-store.d.ts +3 -2
- package/dist/server/identity-sso-store.js +8 -3
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/release-migrations.js +4 -0
- package/dist/tracking/providers.js +13 -3
- package/dist/workspace-files/tool.js +1 -1
- package/package.json +3 -2
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
IconNotes,
|
|
13
13
|
IconPlugConnected,
|
|
14
14
|
IconPlugOff,
|
|
15
|
+
IconPlus,
|
|
15
16
|
IconSearch,
|
|
16
17
|
IconSettings,
|
|
17
18
|
IconX,
|
|
@@ -530,17 +531,11 @@ function CalendarAccountMenu({
|
|
|
530
531
|
const [disconnectTarget, setDisconnectTarget] =
|
|
531
532
|
useState<CalendarAccount | null>(null);
|
|
532
533
|
|
|
533
|
-
const
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
? "Disconnected"
|
|
537
|
-
: primaryAccount?.status === "needs-reauth"
|
|
538
|
-
? "Needs reconnect"
|
|
539
|
-
: primaryAccount
|
|
540
|
-
? "Connected"
|
|
541
|
-
: "Not connected";
|
|
534
|
+
const hasNeedsReconnect = accounts.some(
|
|
535
|
+
(account) => account.status === "needs-reauth",
|
|
536
|
+
);
|
|
542
537
|
|
|
543
|
-
const
|
|
538
|
+
const handleConnect = () => {
|
|
544
539
|
setConnectPending(true);
|
|
545
540
|
startCalendarOAuth()
|
|
546
541
|
.then(() => onConnected?.())
|
|
@@ -586,48 +581,121 @@ function CalendarAccountMenu({
|
|
|
586
581
|
aria-label={t("meetingsRoute.calendarSettings")}
|
|
587
582
|
>
|
|
588
583
|
<IconSettings className="h-4 w-4" />
|
|
589
|
-
|
|
584
|
+
{t("meetingsRoute.calendarAccountsButton", {
|
|
585
|
+
defaultValue: "Calendars",
|
|
586
|
+
})}
|
|
590
587
|
</Button>
|
|
591
588
|
</DropdownMenuTrigger>
|
|
592
589
|
<DropdownMenuContent align="end" className="w-72">
|
|
593
590
|
<DropdownMenuLabel className="flex items-center gap-2">
|
|
594
|
-
{
|
|
591
|
+
{accounts.length > 0 ? (
|
|
595
592
|
<IconPlugConnected className="h-4 w-4 text-muted-foreground" />
|
|
596
593
|
) : (
|
|
597
594
|
<IconPlugOff className="h-4 w-4 text-muted-foreground" />
|
|
598
595
|
)}
|
|
599
596
|
Google Calendar
|
|
600
597
|
</DropdownMenuLabel>
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
598
|
+
{accounts.length > 0 ? (
|
|
599
|
+
<div className="space-y-1.5 px-2 pb-1">
|
|
600
|
+
<div className="text-[11px] font-medium uppercase tracking-wide text-muted-foreground">
|
|
601
|
+
{t("meetingsRoute.connectedAccounts", {
|
|
602
|
+
defaultValue: "Connected accounts",
|
|
603
|
+
})}
|
|
604
|
+
</div>
|
|
605
|
+
{accounts.map((account) => (
|
|
606
|
+
<div
|
|
607
|
+
key={account.id}
|
|
608
|
+
className="flex min-w-0 items-center gap-2 text-xs"
|
|
609
|
+
>
|
|
610
|
+
{account.status === "needs-reauth" ? (
|
|
611
|
+
<IconAlertTriangle className="h-3.5 w-3.5 shrink-0 text-destructive" />
|
|
612
|
+
) : account.status === "disconnected" ? (
|
|
613
|
+
<IconPlugOff className="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
|
|
614
|
+
) : (
|
|
615
|
+
<IconPlugConnected className="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
|
|
616
|
+
)}
|
|
617
|
+
<span className="min-w-0 flex-1 truncate">
|
|
618
|
+
{calendarAccountLabel(account)}
|
|
619
|
+
</span>
|
|
620
|
+
<span
|
|
621
|
+
className={
|
|
622
|
+
account.status === "needs-reauth" ||
|
|
623
|
+
account.status === "disconnected"
|
|
624
|
+
? "shrink-0 text-[11px] text-destructive"
|
|
625
|
+
: "shrink-0 text-[11px] text-muted-foreground"
|
|
626
|
+
}
|
|
627
|
+
>
|
|
628
|
+
{account.status === "needs-reauth"
|
|
629
|
+
? t("meetingsRoute.calendarNeedsReconnectLabel", {
|
|
630
|
+
defaultValue: "Needs reconnect",
|
|
631
|
+
})
|
|
632
|
+
: account.status === "disconnected"
|
|
633
|
+
? t("meetingsRoute.calendarDisconnectedLabel", {
|
|
634
|
+
defaultValue: "Disconnected",
|
|
635
|
+
})
|
|
636
|
+
: account.status && account.status !== "connected"
|
|
637
|
+
? t("meetingsRoute.calendarStatusUnavailable", {
|
|
638
|
+
defaultValue: "Status unavailable",
|
|
639
|
+
})
|
|
640
|
+
: t("meetingsRoute.calendarConnectedLabel", {
|
|
641
|
+
defaultValue: "Connected",
|
|
642
|
+
})}
|
|
643
|
+
</span>
|
|
606
644
|
</div>
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
645
|
+
))}
|
|
646
|
+
</div>
|
|
647
|
+
) : (
|
|
648
|
+
<div className="px-2 pb-1 text-xs text-muted-foreground">
|
|
649
|
+
{t("meetingsRoute.connectCalendarReminder")}
|
|
650
|
+
</div>
|
|
651
|
+
)}
|
|
613
652
|
<DropdownMenuSeparator />
|
|
653
|
+
{hasNeedsReconnect && (
|
|
654
|
+
<DropdownMenuItem
|
|
655
|
+
onSelect={(event) => {
|
|
656
|
+
event.preventDefault();
|
|
657
|
+
handleConnect();
|
|
658
|
+
}}
|
|
659
|
+
disabled={connectPending}
|
|
660
|
+
>
|
|
661
|
+
{connectPending ? (
|
|
662
|
+
<IconLoader2 className="me-2 h-4 w-4 animate-spin" />
|
|
663
|
+
) : (
|
|
664
|
+
<IconExternalLink className="me-2 h-4 w-4" />
|
|
665
|
+
)}
|
|
666
|
+
{t("meetingsRoute.reconnectCalendar", {
|
|
667
|
+
defaultValue: "Reconnect calendar",
|
|
668
|
+
})}
|
|
669
|
+
</DropdownMenuItem>
|
|
670
|
+
)}
|
|
614
671
|
<DropdownMenuItem
|
|
615
672
|
onSelect={(event) => {
|
|
616
673
|
event.preventDefault();
|
|
617
|
-
|
|
674
|
+
handleConnect();
|
|
618
675
|
}}
|
|
619
676
|
disabled={connectPending}
|
|
620
677
|
>
|
|
621
678
|
{connectPending ? (
|
|
622
679
|
<IconLoader2 className="me-2 h-4 w-4 animate-spin" />
|
|
623
680
|
) : (
|
|
624
|
-
<
|
|
681
|
+
<IconPlus className="me-2 h-4 w-4" />
|
|
625
682
|
)}
|
|
626
|
-
{
|
|
683
|
+
{accounts.length > 0
|
|
684
|
+
? t("meetingsRoute.addAnotherCalendarAccount", {
|
|
685
|
+
defaultValue: "Add another account",
|
|
686
|
+
})
|
|
687
|
+
: t("meetingsRoute.connectCalendar", {
|
|
688
|
+
defaultValue: "Connect calendar",
|
|
689
|
+
})}
|
|
627
690
|
</DropdownMenuItem>
|
|
628
691
|
{accounts.length > 0 && (
|
|
629
692
|
<>
|
|
630
693
|
<DropdownMenuSeparator />
|
|
694
|
+
<DropdownMenuLabel className="text-[11px] text-muted-foreground">
|
|
695
|
+
{t("meetingsRoute.disconnectCalendarAccount", {
|
|
696
|
+
defaultValue: "Disconnect an account",
|
|
697
|
+
})}
|
|
698
|
+
</DropdownMenuLabel>
|
|
631
699
|
{accounts.map((account) => (
|
|
632
700
|
<DropdownMenuItem
|
|
633
701
|
key={account.id}
|
|
@@ -12,8 +12,11 @@ import {
|
|
|
12
12
|
useBuilderStatus,
|
|
13
13
|
type SettingsSearchEntry,
|
|
14
14
|
} from "@agent-native/core/client/settings";
|
|
15
|
-
import
|
|
16
|
-
|
|
15
|
+
import {
|
|
16
|
+
DEFAULT_CLIPS_RECORDING_VISIBILITY,
|
|
17
|
+
type ClipsDefaultVisibility,
|
|
18
|
+
} from "@shared/clips-ai-prefs";
|
|
19
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
17
20
|
import { toast } from "sonner";
|
|
18
21
|
|
|
19
22
|
import { PageHeader } from "@/components/library/page-header";
|
|
@@ -101,22 +104,34 @@ export default function SettingsIndexRoute() {
|
|
|
101
104
|
const storageStatus = useVideoStorageStatus();
|
|
102
105
|
const secrets = useSecretStatus();
|
|
103
106
|
const builderStatus = useBuilderStatus();
|
|
107
|
+
const connectRequestedRef = useRef(false);
|
|
104
108
|
const builderConnect = useBuilderConnectFlow({
|
|
105
109
|
popupUrl:
|
|
106
110
|
builderStatus.status?.cliAuthUrl ?? builderStatus.status?.connectUrl,
|
|
107
111
|
trackingSource: "clips_settings",
|
|
108
112
|
trackingFlow: "clips_setup",
|
|
109
113
|
onConnected: async () => {
|
|
114
|
+
const shouldShowConnectedToast = connectRequestedRef.current;
|
|
115
|
+
connectRequestedRef.current = false;
|
|
110
116
|
await Promise.all([storageStatus.refetch(), builderStatus.refetch()]);
|
|
111
|
-
|
|
117
|
+
if (shouldShowConnectedToast) {
|
|
118
|
+
toast.success(t("settings.builderConnectedToast"));
|
|
119
|
+
}
|
|
112
120
|
},
|
|
113
121
|
});
|
|
122
|
+
const startBuilderConnect = useCallback(
|
|
123
|
+
(options?: Parameters<typeof builderConnect.start>[0]) => {
|
|
124
|
+
connectRequestedRef.current = true;
|
|
125
|
+
builderConnect.start(options);
|
|
126
|
+
},
|
|
127
|
+
[builderConnect.start],
|
|
128
|
+
);
|
|
114
129
|
const [loading, setLoading] = useState(true);
|
|
115
130
|
const [saving, setSaving] = useState(false);
|
|
116
131
|
const [defaultSpeed, setDefaultSpeed] = useState("1.2");
|
|
117
132
|
const [emailNotifications, setEmailNotifications] = useState(true);
|
|
118
133
|
const [defaultVisibility, setDefaultVisibility] =
|
|
119
|
-
useState<ClipsDefaultVisibility>(
|
|
134
|
+
useState<ClipsDefaultVisibility>(DEFAULT_CLIPS_RECORDING_VISIBILITY);
|
|
120
135
|
const [transcriptCleanupEnabled, setTranscriptCleanupEnabled] =
|
|
121
136
|
useState(true);
|
|
122
137
|
|
|
@@ -126,7 +141,9 @@ export default function SettingsIndexRoute() {
|
|
|
126
141
|
if (cancelled) return;
|
|
127
142
|
setDefaultSpeed(v.defaultPlaybackSpeed ?? "1.2");
|
|
128
143
|
setEmailNotifications(v.emailNotifications ?? true);
|
|
129
|
-
setDefaultVisibility(
|
|
144
|
+
setDefaultVisibility(
|
|
145
|
+
v.defaultRecordingVisibility ?? DEFAULT_CLIPS_RECORDING_VISIBILITY,
|
|
146
|
+
);
|
|
130
147
|
setTranscriptCleanupEnabled(v.transcriptCleanupEnabled !== false);
|
|
131
148
|
setLoading(false);
|
|
132
149
|
});
|
|
@@ -151,9 +168,9 @@ export default function SettingsIndexRoute() {
|
|
|
151
168
|
!builderConnect.hasFetchedStatus,
|
|
152
169
|
connecting: builderConnect.connecting,
|
|
153
170
|
orgName: builderConnect.orgName ?? builderStatus.status?.orgName ?? null,
|
|
154
|
-
start:
|
|
171
|
+
start: startBuilderConnect,
|
|
155
172
|
}),
|
|
156
|
-
[builderConnect, builderStatus, storageStatus],
|
|
173
|
+
[builderConnect, builderStatus, startBuilderConnect, storageStatus],
|
|
157
174
|
);
|
|
158
175
|
|
|
159
176
|
async function handleUploadWorkspaceChange(organizationId: string) {
|
|
@@ -132,11 +132,16 @@ export default function EmbedRoute() {
|
|
|
132
132
|
readyMediaPollRef.current = null;
|
|
133
133
|
return 2000;
|
|
134
134
|
}
|
|
135
|
+
if (rec.seekableRepairPending === true) {
|
|
136
|
+
readyMediaPollRef.current = null;
|
|
137
|
+
return READY_MEDIA_SETTLE_POLL_INTERVAL_MS;
|
|
138
|
+
}
|
|
135
139
|
const mediaKey = [
|
|
136
140
|
rec.id,
|
|
137
141
|
rec.durationMs ?? "",
|
|
138
142
|
rec.videoSizeBytes ?? "",
|
|
139
143
|
rec.videoFormat ?? "",
|
|
144
|
+
rec.updatedAt ?? "",
|
|
140
145
|
].join(":");
|
|
141
146
|
const now = Date.now();
|
|
142
147
|
if (readyMediaPollRef.current?.key !== mediaKey) {
|
|
@@ -225,10 +230,9 @@ export default function EmbedRoute() {
|
|
|
225
230
|
onVideoElementChange={setTrackedVideoEl}
|
|
226
231
|
recordingId={recording.id}
|
|
227
232
|
videoUrl={recording.videoUrl}
|
|
228
|
-
mediaVersion={
|
|
229
|
-
recording.videoSizeBytes ??
|
|
230
|
-
|
|
231
|
-
].join(":")}
|
|
233
|
+
mediaVersion={
|
|
234
|
+
recording.mediaUpdatedAt ?? recording.videoSizeBytes ?? null
|
|
235
|
+
}
|
|
232
236
|
videoFormat={recording.videoFormat}
|
|
233
237
|
embedProvider={isLoomEmbedBacked ? "loom" : null}
|
|
234
238
|
durationMs={recording.durationMs}
|
|
@@ -310,6 +310,10 @@ export default function RecordingPage() {
|
|
|
310
310
|
readyMediaPollRef.current = null;
|
|
311
311
|
return 1000;
|
|
312
312
|
}
|
|
313
|
+
if (rec.seekableRepairPending === true) {
|
|
314
|
+
readyMediaPollRef.current = null;
|
|
315
|
+
return READY_MEDIA_SETTLE_POLL_INTERVAL_MS;
|
|
316
|
+
}
|
|
313
317
|
// Fresh streaming uploads can become `ready` before the background
|
|
314
318
|
// seekable/faststart repair swaps in the final player URL. Keep polling
|
|
315
319
|
// briefly so the first post-recording page catches that URL update
|
|
@@ -319,6 +323,7 @@ export default function RecordingPage() {
|
|
|
319
323
|
rec.durationMs ?? "",
|
|
320
324
|
rec.videoSizeBytes ?? "",
|
|
321
325
|
rec.videoFormat ?? "",
|
|
326
|
+
rec.updatedAt ?? "",
|
|
322
327
|
].join(":");
|
|
323
328
|
const now = Date.now();
|
|
324
329
|
if (readyMediaPollRef.current?.key !== mediaKey) {
|
|
@@ -962,7 +967,7 @@ export default function RecordingPage() {
|
|
|
962
967
|
variant="ghost"
|
|
963
968
|
size="icon"
|
|
964
969
|
className="shrink-0"
|
|
965
|
-
aria-label={t("recordingPage.
|
|
970
|
+
aria-label={t("recordingPage.backToLibrary")}
|
|
966
971
|
>
|
|
967
972
|
<Link to="/library" replace>
|
|
968
973
|
<IconArrowLeft className="h-4 w-4 rtl:-scale-x-100" />
|
|
@@ -1305,11 +1310,14 @@ export default function RecordingPage() {
|
|
|
1305
1310
|
asChild
|
|
1306
1311
|
variant="ghost"
|
|
1307
1312
|
size="icon"
|
|
1308
|
-
className="shrink-0"
|
|
1309
|
-
aria-label={t("recordingPage.
|
|
1313
|
+
className="shrink-0 sm:w-auto sm:px-2"
|
|
1314
|
+
aria-label={t("recordingPage.backToLibrary")}
|
|
1310
1315
|
>
|
|
1311
1316
|
<Link to="/library" replace>
|
|
1312
1317
|
<IconArrowLeft className="h-4 w-4 rtl:-scale-x-100" />
|
|
1318
|
+
<span className="hidden sm:inline">
|
|
1319
|
+
{t("recordingPage.backToLibrary")}
|
|
1320
|
+
</span>
|
|
1313
1321
|
</Link>
|
|
1314
1322
|
</Button>
|
|
1315
1323
|
<div className="flex-1 min-w-0">
|
|
@@ -1592,10 +1600,9 @@ export default function RecordingPage() {
|
|
|
1592
1600
|
onVideoElementChange={setTrackedVideoEl}
|
|
1593
1601
|
recordingId={recording.id}
|
|
1594
1602
|
videoUrl={recording.videoUrl}
|
|
1595
|
-
mediaVersion={
|
|
1596
|
-
recording.videoSizeBytes ??
|
|
1597
|
-
|
|
1598
|
-
].join(":")}
|
|
1603
|
+
mediaVersion={
|
|
1604
|
+
recording.mediaUpdatedAt ?? recording.videoSizeBytes ?? null
|
|
1605
|
+
}
|
|
1599
1606
|
videoFormat={recording.videoFormat}
|
|
1600
1607
|
embedProvider={isLoomEmbedBacked ? "loom" : null}
|
|
1601
1608
|
durationMs={recording.durationMs}
|
|
@@ -470,11 +470,16 @@ export default function ShareRoute() {
|
|
|
470
470
|
readyMediaPollRef.current = null;
|
|
471
471
|
return 2000;
|
|
472
472
|
}
|
|
473
|
+
if (rec.seekableRepairPending === true) {
|
|
474
|
+
readyMediaPollRef.current = null;
|
|
475
|
+
return READY_MEDIA_SETTLE_POLL_INTERVAL_MS;
|
|
476
|
+
}
|
|
473
477
|
const mediaKey = [
|
|
474
478
|
rec.id,
|
|
475
479
|
rec.durationMs ?? "",
|
|
476
480
|
rec.videoSizeBytes ?? "",
|
|
477
481
|
rec.videoFormat ?? "",
|
|
482
|
+
rec.updatedAt ?? "",
|
|
478
483
|
].join(":");
|
|
479
484
|
const now = Date.now();
|
|
480
485
|
if (readyMediaPollRef.current?.key !== mediaKey) {
|
|
@@ -1020,10 +1025,9 @@ export default function ShareRoute() {
|
|
|
1020
1025
|
onVideoElementChange={setTrackedVideoEl}
|
|
1021
1026
|
recordingId={recording.id}
|
|
1022
1027
|
videoUrl={recording.videoUrl}
|
|
1023
|
-
mediaVersion={
|
|
1024
|
-
recording.videoSizeBytes ??
|
|
1025
|
-
|
|
1026
|
-
].join(":")}
|
|
1028
|
+
mediaVersion={
|
|
1029
|
+
recording.mediaUpdatedAt ?? recording.videoSizeBytes ?? null
|
|
1030
|
+
}
|
|
1027
1031
|
videoFormat={recording.videoFormat}
|
|
1028
1032
|
embedProvider={isLoomEmbedBacked ? "loom" : null}
|
|
1029
1033
|
durationMs={recording.durationMs}
|
|
@@ -2,7 +2,10 @@ import { appPath } from "@agent-native/core/client/api-path";
|
|
|
2
2
|
import { useSession } from "@agent-native/core/client/hooks";
|
|
3
3
|
import { useT } from "@agent-native/core/client/i18n";
|
|
4
4
|
import { PoweredByBadge } from "@agent-native/core/client/ui";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
AGENT_ACCESS_PARAM,
|
|
7
|
+
normalizeDocumentTitle,
|
|
8
|
+
} from "@agent-native/core/shared";
|
|
6
9
|
import {
|
|
7
10
|
IconCalendar,
|
|
8
11
|
IconCheck,
|
|
@@ -16,8 +19,12 @@ import {
|
|
|
16
19
|
import { useQuery } from "@tanstack/react-query";
|
|
17
20
|
import { and, eq, isNull } from "drizzle-orm";
|
|
18
21
|
import { useEffect, useRef, useState } from "react";
|
|
19
|
-
import type {
|
|
20
|
-
|
|
22
|
+
import type {
|
|
23
|
+
HeadersArgs,
|
|
24
|
+
LoaderFunctionArgs,
|
|
25
|
+
MetaFunction,
|
|
26
|
+
} from "react-router";
|
|
27
|
+
import { useLoaderData, useParams, useSearchParams } from "react-router";
|
|
21
28
|
import { toast } from "sonner";
|
|
22
29
|
|
|
23
30
|
import {
|
|
@@ -36,15 +43,37 @@ import {
|
|
|
36
43
|
} from "@/lib/public-meeting";
|
|
37
44
|
|
|
38
45
|
import { getDb, schema } from "../../server/db";
|
|
46
|
+
import { CLIPS_MEETING_AGENT_RESOURCE_KIND } from "../../shared/meeting-agent-access";
|
|
47
|
+
import { privateShareLoaderData } from "../../shared/share-loader-response";
|
|
39
48
|
|
|
40
49
|
type LoaderData = { meeting: PublicMeeting | null };
|
|
41
50
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
51
|
+
function shareMeetingLoaderData(
|
|
52
|
+
payload: LoaderData,
|
|
53
|
+
privateAgentAccess = false,
|
|
54
|
+
) {
|
|
55
|
+
return privateAgentAccess ? privateShareLoaderData(payload) : payload;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function headers({ loaderHeaders }: HeadersArgs) {
|
|
59
|
+
return loaderHeaders;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export async function loader({ params, url }: LoaderFunctionArgs) {
|
|
45
63
|
const meetingId = params.meetingId;
|
|
46
64
|
if (!meetingId) return { meeting: null };
|
|
47
65
|
|
|
66
|
+
const { verifyScopedAgentAccessToken } =
|
|
67
|
+
await import("@agent-native/core/server");
|
|
68
|
+
const agentAccessToken = url.searchParams.get(AGENT_ACCESS_PARAM) ?? "";
|
|
69
|
+
const hasAgentAccessToken = Boolean(agentAccessToken);
|
|
70
|
+
const tokenGrantsAgentAccess = agentAccessToken
|
|
71
|
+
? verifyScopedAgentAccessToken(agentAccessToken, {
|
|
72
|
+
resourceKind: CLIPS_MEETING_AGENT_RESOURCE_KIND,
|
|
73
|
+
resourceId: meetingId,
|
|
74
|
+
}).ok
|
|
75
|
+
: false;
|
|
76
|
+
|
|
48
77
|
const [meeting] = await getDb()
|
|
49
78
|
.select({
|
|
50
79
|
id: schema.meetings.id,
|
|
@@ -59,14 +88,21 @@ export async function loader({
|
|
|
59
88
|
})
|
|
60
89
|
.from(schema.meetings)
|
|
61
90
|
.where(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
91
|
+
tokenGrantsAgentAccess
|
|
92
|
+
? and(
|
|
93
|
+
eq(schema.meetings.id, meetingId),
|
|
94
|
+
isNull(schema.meetings.trashedAt),
|
|
95
|
+
)
|
|
96
|
+
: and(
|
|
97
|
+
eq(schema.meetings.id, meetingId),
|
|
98
|
+
eq(schema.meetings.visibility, "public"),
|
|
99
|
+
isNull(schema.meetings.trashedAt),
|
|
100
|
+
),
|
|
67
101
|
)
|
|
68
102
|
.limit(1);
|
|
69
|
-
if (!meeting)
|
|
103
|
+
if (!meeting) {
|
|
104
|
+
return shareMeetingLoaderData({ meeting: null }, hasAgentAccessToken);
|
|
105
|
+
}
|
|
70
106
|
|
|
71
107
|
const [participants, actionItems] = await Promise.all([
|
|
72
108
|
getDb()
|
|
@@ -101,20 +137,23 @@ export async function loader({
|
|
|
101
137
|
}
|
|
102
138
|
} catch {}
|
|
103
139
|
|
|
104
|
-
return
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
140
|
+
return shareMeetingLoaderData(
|
|
141
|
+
{
|
|
142
|
+
meeting: {
|
|
143
|
+
id: meeting.id,
|
|
144
|
+
title: meeting.title,
|
|
145
|
+
scheduledStart: meeting.scheduledStart,
|
|
146
|
+
summaryMd: meeting.summaryMd,
|
|
147
|
+
bullets,
|
|
148
|
+
participants,
|
|
149
|
+
actionItems,
|
|
150
|
+
actualStart: meeting.actualStart,
|
|
151
|
+
actualEnd: meeting.actualEnd,
|
|
152
|
+
transcriptStatus: meeting.transcriptStatus,
|
|
153
|
+
},
|
|
116
154
|
},
|
|
117
|
-
|
|
155
|
+
hasAgentAccessToken,
|
|
156
|
+
);
|
|
118
157
|
}
|
|
119
158
|
|
|
120
159
|
export const meta: MetaFunction<typeof loader> = ({ loaderData }) => {
|
|
@@ -197,7 +236,9 @@ export default function ShareMeetingRoute() {
|
|
|
197
236
|
const t = useT();
|
|
198
237
|
const loaderData = useLoaderData<LoaderData>();
|
|
199
238
|
const { meetingId } = useParams<{ meetingId: string }>();
|
|
239
|
+
const [searchParams] = useSearchParams();
|
|
200
240
|
const { session, isLoading: sessionLoading } = useSession();
|
|
241
|
+
const agentAccessToken = searchParams.get(AGENT_ACCESS_PARAM) ?? "";
|
|
201
242
|
const pollingStartedAtRef = useRef<number | null>(null);
|
|
202
243
|
const [transcriptCopied, setTranscriptCopied] = useState(false);
|
|
203
244
|
const initialMeetingResult: PublicMeetingResult | undefined =
|
|
@@ -215,8 +256,13 @@ export default function ShareMeetingRoute() {
|
|
|
215
256
|
meetingId,
|
|
216
257
|
session?.email ?? null,
|
|
217
258
|
session?.orgId ?? null,
|
|
259
|
+
agentAccessToken,
|
|
218
260
|
],
|
|
219
|
-
queryFn: ({ signal }) =>
|
|
261
|
+
queryFn: ({ signal }) =>
|
|
262
|
+
fetchPublicMeeting(meetingId ?? "", {
|
|
263
|
+
signal,
|
|
264
|
+
agentAccessToken,
|
|
265
|
+
}),
|
|
220
266
|
enabled: !!meetingId && !sessionLoading,
|
|
221
267
|
initialData: initialMeetingResult,
|
|
222
268
|
refetchInterval: (query) => {
|