@agent-native/core 0.155.0 → 0.157.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/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +19 -4
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +7 -2
- package/corpus/templates/assets/app/components/asset/AssetPreviewDialog.tsx +3 -1
- package/corpus/templates/assets/app/global.css +4 -0
- package/corpus/templates/assets/app/i18n-data.ts +21 -1
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +18 -15
- package/corpus/templates/brain/app/routes/sources.tsx +1 -2
- package/corpus/templates/calendar/app/hooks/use-bookings.ts +12 -2
- package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +64 -2
- package/corpus/templates/calendar/server/handlers/bookings.ts +219 -93
- package/corpus/templates/calendar/server/plugins/auth.ts +0 -2
- package/corpus/templates/clips/actions/create-folder.ts +7 -1
- package/corpus/templates/clips/actions/create-meeting.ts +6 -2
- package/corpus/templates/clips/actions/create-recording.ts +5 -3
- package/corpus/templates/clips/actions/finalize-recording.ts +97 -65
- package/corpus/templates/clips/actions/import-loom-recording.ts +5 -3
- package/corpus/templates/clips/actions/request-recording-access.ts +272 -0
- package/corpus/templates/clips/actions/stitch-recordings.ts +5 -3
- package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +38 -63
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +177 -134
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +3 -21
- package/corpus/templates/clips/app/components/sharing/share-ui.tsx +13 -30
- package/corpus/templates/clips/app/i18n/en-US.ts +10 -0
- package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +5 -5
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +24 -17
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +151 -20
- package/corpus/templates/clips/changelog/2026-08-14-long-resumable-uploads-now-abort-cleanly-and-show-errors.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-14-standardized-share-popovers.md +6 -0
- package/corpus/templates/clips/chrome-extension/public/manifest.json +11 -3
- package/corpus/templates/clips/chrome-extension/src/github-preview-content.ts +37 -8
- package/corpus/templates/clips/chrome-extension/src/github-preview.ts +3 -3
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +8 -25
- package/corpus/templates/clips/desktop/src/app.tsx +24 -0
- package/corpus/templates/clips/desktop/src/lib/media-capture-constraints.ts +42 -13
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +11 -18
- package/corpus/templates/clips/desktop/src/overlays/onboarding.tsx +1 -0
- package/corpus/templates/clips/desktop/src/shared/config.ts +1 -0
- package/corpus/templates/clips/desktop/src/styles.css +24 -9
- package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +3 -0
- package/corpus/templates/clips/desktop/src-tauri/src/config.rs +8 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +154 -176
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +115 -31
- package/corpus/templates/clips/desktop/src-tauri/src/rewind_clip.rs +7 -0
- package/corpus/templates/clips/server/db/index.ts +1 -0
- package/corpus/templates/clips/server/db/schema.ts +1 -0
- package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +6 -1
- package/corpus/templates/clips/server/lib/emails.ts +23 -0
- package/corpus/templates/clips/server/lib/public-agent-context.ts +55 -0
- package/corpus/templates/clips/server/lib/recordings.ts +2 -1
- package/corpus/templates/clips/server/lib/resumable-upload-cleanup.ts +49 -0
- package/corpus/templates/clips/server/lib/s3-upload-provider.ts +34 -7
- package/corpus/templates/clips/server/lib/upload-interruption.ts +15 -1
- package/corpus/templates/clips/server/lib/upload-lease.ts +94 -9
- package/corpus/templates/clips/server/routes/api/agent-context.json.get.ts +82 -7
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +1 -0
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +71 -12
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/interrupt.post.ts +4 -3
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/reset-chunks.post.ts +19 -0
- package/corpus/templates/clips/server/routes/api/uploads/reap.post.ts +8 -1
- package/corpus/templates/clips/shared/recording-link.ts +4 -0
- package/corpus/templates/clips/shared/share-loader-response.ts +2 -1
- package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +7 -16
- package/corpus/templates/factory/AGENTS.md +5 -1
- package/corpus/templates/factory/README.md +6 -2
- package/corpus/templates/factory/actions/view-screen.ts +15 -0
- package/corpus/templates/factory/app/components/factory/FactoryAgentsView.tsx +58 -189
- package/corpus/templates/factory/app/components/layout/Header.tsx +1 -0
- package/corpus/templates/factory/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/factory/app/components/layout/Sidebar.tsx +7 -0
- package/corpus/templates/factory/app/hooks/use-navigation-state.ts +3 -0
- package/corpus/templates/factory/app/i18n/en-US.ts +3 -1
- package/corpus/templates/factory/app/routes/agents.tsx +9 -0
- package/corpus/templates/mail/server/plugins/auth.ts +0 -2
- package/corpus/templates/plan/app/components/plan/LocalCodebasePicker.tsx +50 -14
- package/corpus/templates/plan/app/pages/PlansPage.tsx +9 -19
- package/corpus/templates/slides/app/components/editor/AddSlidePopover.tsx +98 -29
- package/corpus/templates/slides/app/components/editor/EditorActionCluster.tsx +45 -91
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +94 -2
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +17 -29
- package/corpus/templates/slides/app/components/editor/HistoryPanel.tsx +7 -1
- package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +1 -1
- package/corpus/templates/slides/app/context/DeckContext.tsx +108 -19
- package/corpus/templates/slides/app/global.css +7 -40
- package/corpus/templates/slides/app/i18n/en-US.ts +4 -0
- package/corpus/templates/slides/app/lib/editor-shortcuts.ts +46 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +143 -45
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/production-agent.d.ts +30 -0
- package/dist/agent/production-agent.js +100 -8
- package/dist/agent/types.d.ts +9 -0
- package/dist/client/AgentPanel.d.ts +13 -1
- package/dist/client/AgentPanel.js +22 -17
- package/dist/client/AssistantChat.d.ts +15 -1
- package/dist/client/AssistantChat.js +135 -48
- package/dist/client/HighlightedCodeBlock.js +12 -2
- package/dist/client/MultiTabAssistantChat.js +44 -27
- package/dist/client/agent-chat/index.d.ts +1 -0
- package/dist/client/agent-chat/index.js +1 -0
- package/dist/client/chat/markdown-renderer.js +20 -5
- package/dist/client/chat/message-components.d.ts +2 -2
- package/dist/client/chat/message-components.js +69 -35
- package/dist/client/chat/run-recovery.d.ts +4 -1
- package/dist/client/chat/run-recovery.js +62 -30
- package/dist/client/chat/tool-call-display.d.ts +12 -3
- package/dist/client/chat/tool-call-display.js +79 -40
- package/dist/client/chat/widgets/DataChartRenderer.js +3 -1
- package/dist/client/chat/widgets/DataChartWidget.js +8 -2
- package/dist/client/chat/widgets/DataInsightsWidget.js +3 -1
- package/dist/client/chat/widgets/DataTableWidget.js +23 -9
- package/dist/client/chat/widgets/builtin-tool-renderers.js +3 -1
- package/dist/client/chat-first/apps-rail.js +1 -1
- package/dist/client/components/ui/message-scroller.d.ts +1 -1
- package/dist/client/components/ui/message-scroller.js +7 -3
- package/dist/client/composer/runtime-adapters.js +3 -2
- package/dist/client/context-xray/ContextMeter.js +5 -1
- package/dist/client/context-xray/ContextXRayPanel.js +5 -5
- package/dist/client/error-format.d.ts +4 -0
- package/dist/client/error-format.js +93 -5
- package/dist/client/i18n.js +83 -17
- package/dist/client/observability/ThumbsFeedback.js +10 -8
- package/dist/client/settings/AccountSettingsCard.js +48 -19
- package/dist/client/sharing/ShareButton.d.ts +1 -2
- package/dist/client/sharing/ShareButton.js +151 -81
- package/dist/client/sharing/ShareDialog.js +5 -4
- package/dist/client/use-chat-threads.js +10 -14
- package/dist/coding-tools/run-code.js +2 -1
- package/dist/coding-tools/sandbox/background.d.ts +1 -0
- package/dist/coding-tools/sandbox/background.js +8 -1
- package/dist/coding-tools/sandbox/executions-store.d.ts +2 -0
- package/dist/coding-tools/sandbox/executions-store.js +41 -3
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/localization/core-messages/ar-SA.d.ts +3 -0
- package/dist/localization/core-messages/ar-SA.js +541 -0
- package/dist/localization/core-messages/de-DE.d.ts +3 -0
- package/dist/localization/core-messages/de-DE.js +513 -0
- package/dist/localization/core-messages/en-US.d.ts +513 -0
- package/dist/localization/core-messages/en-US.js +513 -0
- package/dist/localization/core-messages/es-ES.d.ts +3 -0
- package/dist/localization/core-messages/es-ES.js +520 -0
- package/dist/localization/core-messages/fr-FR.d.ts +3 -0
- package/dist/localization/core-messages/fr-FR.js +520 -0
- package/dist/localization/core-messages/hi-IN.d.ts +3 -0
- package/dist/localization/core-messages/hi-IN.js +513 -0
- package/dist/localization/core-messages/ja-JP.d.ts +3 -0
- package/dist/localization/core-messages/ja-JP.js +506 -0
- package/dist/localization/core-messages/ko-KR.d.ts +3 -0
- package/dist/localization/core-messages/ko-KR.js +506 -0
- package/dist/localization/core-messages/pt-BR.d.ts +3 -0
- package/dist/localization/core-messages/pt-BR.js +520 -0
- package/dist/localization/core-messages/zh-CN.d.ts +3 -0
- package/dist/localization/core-messages/zh-CN.js +506 -0
- package/dist/localization/core-messages/zh-TW.d.ts +3 -0
- package/dist/localization/core-messages/zh-TW.js +506 -0
- package/dist/localization/core-messages.d.ts +524 -0
- package/dist/localization/core-messages.js +124 -0
- package/dist/localization/default-messages.d.ts +3 -0
- package/dist/localization/default-messages.js +3 -0
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +5 -5
- 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/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-chat/plugin-options.d.ts +7 -2
- package/dist/server/agent-chat-plugin.d.ts +10 -0
- package/dist/server/agent-chat-plugin.js +144 -41
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-run-context.d.ts +7 -1
- package/dist/server/agent-run-context.js +9 -2
- package/dist/server/agent-teams-run-queue.d.ts +3 -0
- package/dist/server/agent-teams.js +38 -9
- package/dist/server/auth-marketing.d.ts +1 -0
- package/dist/server/auth-marketing.js +0 -2
- package/dist/server/auth.d.ts +1 -0
- package/dist/server/auth.js +18 -0
- package/dist/server/index.d.ts +1 -1
- package/dist/server/onboarding-html.d.ts +1 -0
- package/dist/server/onboarding-html.js +2 -88
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/request-context.d.ts +7 -0
- package/dist/server/request-context.js +15 -0
- package/dist/shared/markdown-block-split.d.ts +16 -0
- package/dist/shared/markdown-block-split.js +81 -5
- package/dist/styles/agent-native.css +13 -0
- package/dist/voice/voice-cleanup-prompt.js +1 -0
- package/docs/content/agent-surfaces.mdx +30 -0
- package/package.json +2 -2
- package/corpus/templates/clips/shared/mic-audio-cleanup.ts +0 -350
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
useSession,
|
|
7
7
|
} from "@agent-native/core/client/hooks";
|
|
8
8
|
import { useT } from "@agent-native/core/client/i18n";
|
|
9
|
+
import { ShareAgentsSection } from "@agent-native/toolkit/sharing";
|
|
9
10
|
import {
|
|
10
|
-
IconChevronDown,
|
|
11
11
|
IconCode,
|
|
12
12
|
IconExternalLink,
|
|
13
13
|
IconLink,
|
|
@@ -35,11 +35,6 @@ import {
|
|
|
35
35
|
type Visibility,
|
|
36
36
|
} from "@/components/sharing/share-ui";
|
|
37
37
|
import { Button } from "@/components/ui/button";
|
|
38
|
-
import {
|
|
39
|
-
Collapsible,
|
|
40
|
-
CollapsibleContent,
|
|
41
|
-
CollapsibleTrigger,
|
|
42
|
-
} from "@/components/ui/collapsible";
|
|
43
38
|
import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
|
|
44
39
|
import { Input } from "@/components/ui/input";
|
|
45
40
|
import { Label } from "@/components/ui/label";
|
|
@@ -52,6 +47,7 @@ import { Switch } from "@/components/ui/switch";
|
|
|
52
47
|
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
|
|
53
48
|
import { cn } from "@/lib/utils";
|
|
54
49
|
|
|
50
|
+
import { buildAgentApiUrls } from "../../../shared/agent-context";
|
|
55
51
|
import { buildEmailPreviewMarkup } from "../../../shared/email-preview";
|
|
56
52
|
import { isLoomEmbedUrl } from "../../../shared/loom";
|
|
57
53
|
import { withShareAttribution } from "../../../shared/share-attribution";
|
|
@@ -62,6 +58,14 @@ function absoluteAppUrl(path: string): string {
|
|
|
62
58
|
return new URL(appPath(path), window.location.origin).toString();
|
|
63
59
|
}
|
|
64
60
|
|
|
61
|
+
function absolutePublicAgentContextUrl(recordingId: string): string {
|
|
62
|
+
if (typeof window === "undefined") return "";
|
|
63
|
+
return buildAgentApiUrls(recordingId, {
|
|
64
|
+
origin: window.location.origin,
|
|
65
|
+
basePath: appPath("/").replace(/\/$/, ""),
|
|
66
|
+
}).contextUrl;
|
|
67
|
+
}
|
|
68
|
+
|
|
65
69
|
export interface ShareRecordingPopoverProps {
|
|
66
70
|
recordingId: string;
|
|
67
71
|
recordingTitle?: string;
|
|
@@ -72,6 +76,13 @@ export interface ShareRecordingPopoverProps {
|
|
|
72
76
|
animatedThumbnailUrl?: string | null;
|
|
73
77
|
isLoomRecording?: boolean;
|
|
74
78
|
hasPassword?: boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Restricts the dialog to a bare copy-link control for viewers who can
|
|
81
|
+
* reshare a public/org clip's link but have no edit access: it skips
|
|
82
|
+
* `list-resource-shares` (which returns every individually-shared
|
|
83
|
+
* principal's email to any reader) and hides the Invite tab entirely.
|
|
84
|
+
*/
|
|
85
|
+
viewerReshareOnly?: boolean;
|
|
75
86
|
/** Trigger element rendered as the popover anchor (usually the Share button). */
|
|
76
87
|
children: ReactNode;
|
|
77
88
|
open?: boolean;
|
|
@@ -103,6 +114,7 @@ export function ShareRecordingPopover({
|
|
|
103
114
|
animatedThumbnailUrl,
|
|
104
115
|
isLoomRecording = false,
|
|
105
116
|
hasPassword,
|
|
117
|
+
viewerReshareOnly = false,
|
|
106
118
|
children,
|
|
107
119
|
open,
|
|
108
120
|
onOpenChange,
|
|
@@ -125,6 +137,7 @@ export function ShareRecordingPopover({
|
|
|
125
137
|
animatedThumbnailUrl={animatedThumbnailUrl}
|
|
126
138
|
isLoomRecording={isLoomRecording}
|
|
127
139
|
hasPassword={hasPassword}
|
|
140
|
+
viewerReshareOnly={viewerReshareOnly}
|
|
128
141
|
/>
|
|
129
142
|
</PopoverContent>
|
|
130
143
|
</Popover>
|
|
@@ -148,6 +161,7 @@ export function ShareRecordingDialog({
|
|
|
148
161
|
open,
|
|
149
162
|
onOpenChange,
|
|
150
163
|
hasPassword,
|
|
164
|
+
viewerReshareOnly = false,
|
|
151
165
|
}: ShareRecordingDialogProps) {
|
|
152
166
|
const t = useT();
|
|
153
167
|
return (
|
|
@@ -168,6 +182,7 @@ export function ShareRecordingDialog({
|
|
|
168
182
|
animatedThumbnailUrl={animatedThumbnailUrl}
|
|
169
183
|
isLoomRecording={isLoomRecording}
|
|
170
184
|
hasPassword={hasPassword}
|
|
185
|
+
viewerReshareOnly={viewerReshareOnly}
|
|
171
186
|
reserveCloseButton
|
|
172
187
|
/>
|
|
173
188
|
</DialogContent>
|
|
@@ -186,6 +201,7 @@ function ShareRecordingContent({
|
|
|
186
201
|
isLoomRecording = false,
|
|
187
202
|
reserveCloseButton = false,
|
|
188
203
|
hasPassword,
|
|
204
|
+
viewerReshareOnly = false,
|
|
189
205
|
}: {
|
|
190
206
|
recordingId: string;
|
|
191
207
|
recordingTitle?: string;
|
|
@@ -197,20 +213,34 @@ function ShareRecordingContent({
|
|
|
197
213
|
isLoomRecording?: boolean;
|
|
198
214
|
reserveCloseButton?: boolean;
|
|
199
215
|
hasPassword?: boolean;
|
|
216
|
+
viewerReshareOnly?: boolean;
|
|
200
217
|
}) {
|
|
201
218
|
const t = useT();
|
|
202
|
-
const sharesQuery = useActionQuery<SharesResponse>(
|
|
203
|
-
|
|
204
|
-
resourceId: recordingId,
|
|
205
|
-
|
|
219
|
+
const sharesQuery = useActionQuery<SharesResponse>(
|
|
220
|
+
"list-resource-shares",
|
|
221
|
+
{ resourceType: "recording", resourceId: recordingId },
|
|
222
|
+
{ enabled: !viewerReshareOnly },
|
|
223
|
+
);
|
|
206
224
|
|
|
207
|
-
const data = sharesQuery.data;
|
|
225
|
+
const data = viewerReshareOnly ? undefined : sharesQuery.data;
|
|
208
226
|
const role = data?.role ?? initialRole;
|
|
209
227
|
const canManage = role === "owner" || role === "admin";
|
|
228
|
+
// Editors could always see (read-only) who a clip is shared with; only
|
|
229
|
+
// gate the Invite tab's mutation controls behind canManage. Commenters are
|
|
230
|
+
// grouped with plain viewers here -- neither can manage shares.
|
|
231
|
+
const canViewShares =
|
|
232
|
+
role === "owner" || role === "admin" || role === "editor";
|
|
210
233
|
const visibility =
|
|
211
234
|
(data?.visibility as Visibility | null | undefined) ??
|
|
212
235
|
initialVisibility ??
|
|
213
236
|
null;
|
|
237
|
+
// A plain viewer/commenter can't produce a working embed for a non-public
|
|
238
|
+
// clip (they have no way to make it public), so don't dangle the tab in
|
|
239
|
+
// front of them only to show an "ask the owner" dead end. Owner/admin/
|
|
240
|
+
// editor keep it regardless of visibility since they can flip to public
|
|
241
|
+
// from inside it.
|
|
242
|
+
const canEmbed = canViewShares || visibility === "public";
|
|
243
|
+
const tabCount = 1 + (canViewShares ? 1 : 0) + (canEmbed ? 1 : 0);
|
|
214
244
|
|
|
215
245
|
// Attribution `via` must be a stable non-PII id, never an email. The only
|
|
216
246
|
// owner id available client-side is the *current* session's userId, which is
|
|
@@ -234,20 +264,28 @@ function ShareRecordingContent({
|
|
|
234
264
|
defaultValue="link"
|
|
235
265
|
className={cn("min-w-0 px-4 py-3", reserveCloseButton && "pe-12")}
|
|
236
266
|
>
|
|
237
|
-
|
|
238
|
-
<
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
267
|
+
{tabCount > 1 ? (
|
|
268
|
+
<TabsList
|
|
269
|
+
className={`grid w-full ${tabCount === 3 ? "grid-cols-3" : "grid-cols-2"}`}
|
|
270
|
+
>
|
|
271
|
+
<TabsTrigger value="link" className="gap-1.5">
|
|
272
|
+
<IconLink size={14} />
|
|
273
|
+
{t("shareDialog.link")}
|
|
274
|
+
</TabsTrigger>
|
|
275
|
+
{canViewShares ? (
|
|
276
|
+
<TabsTrigger value="invite" className="gap-1.5">
|
|
277
|
+
<IconMail size={14} />
|
|
278
|
+
{t("shareDialog.invite")}
|
|
279
|
+
</TabsTrigger>
|
|
280
|
+
) : null}
|
|
281
|
+
{canEmbed ? (
|
|
282
|
+
<TabsTrigger value="embed" className="gap-1.5">
|
|
283
|
+
<IconCode size={14} />
|
|
284
|
+
{t("shareDialog.embed")}
|
|
285
|
+
</TabsTrigger>
|
|
286
|
+
) : null}
|
|
287
|
+
</TabsList>
|
|
288
|
+
) : null}
|
|
251
289
|
|
|
252
290
|
<TabsContent value="link" className="mt-3">
|
|
253
291
|
<LinkTab
|
|
@@ -262,34 +300,39 @@ function ShareRecordingContent({
|
|
|
262
300
|
animatedThumbnailUrl={animatedThumbnailUrl}
|
|
263
301
|
isLoomRecording={isLoomRecording}
|
|
264
302
|
hasPassword={hasPassword}
|
|
303
|
+
canViewShares={canViewShares}
|
|
265
304
|
/>
|
|
266
305
|
</TabsContent>
|
|
267
306
|
|
|
268
|
-
|
|
269
|
-
<
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
307
|
+
{canViewShares ? (
|
|
308
|
+
<TabsContent value="invite" className="mt-3">
|
|
309
|
+
<SharePeopleTab
|
|
310
|
+
resourceType="recording"
|
|
311
|
+
resourceId={recordingId}
|
|
312
|
+
resourceUrl={absoluteAppUrl(`/r/${recordingId}`)}
|
|
313
|
+
sharesQuery={sharesQuery}
|
|
314
|
+
canManage={canManage}
|
|
315
|
+
roleCopy={{
|
|
316
|
+
commenter: {
|
|
317
|
+
label: t("shareUi.recordingCommenter.label"),
|
|
318
|
+
description: t("shareUi.recordingCommenter.description"),
|
|
319
|
+
},
|
|
320
|
+
}}
|
|
321
|
+
/>
|
|
322
|
+
</TabsContent>
|
|
323
|
+
) : null}
|
|
324
|
+
|
|
325
|
+
{canEmbed ? (
|
|
326
|
+
<TabsContent value="embed" className="mt-3">
|
|
327
|
+
<ClipsEmbedConfigurator
|
|
328
|
+
recordingId={recordingId}
|
|
329
|
+
sharesQuery={sharesQuery}
|
|
330
|
+
visibility={visibility}
|
|
331
|
+
canManage={canManage}
|
|
332
|
+
ownerViaId={ownerViaId}
|
|
333
|
+
/>
|
|
334
|
+
</TabsContent>
|
|
335
|
+
) : null}
|
|
293
336
|
</Tabs>
|
|
294
337
|
</>
|
|
295
338
|
);
|
|
@@ -311,6 +354,7 @@ function LinkTab({
|
|
|
311
354
|
animatedThumbnailUrl,
|
|
312
355
|
isLoomRecording: isLoomRecordingProp,
|
|
313
356
|
hasPassword,
|
|
357
|
+
canViewShares,
|
|
314
358
|
}: {
|
|
315
359
|
recordingId: string;
|
|
316
360
|
recordingTitle?: string;
|
|
@@ -323,6 +367,7 @@ function LinkTab({
|
|
|
323
367
|
animatedThumbnailUrl?: string | null;
|
|
324
368
|
isLoomRecording?: boolean;
|
|
325
369
|
hasPassword?: boolean;
|
|
370
|
+
canViewShares: boolean;
|
|
326
371
|
}) {
|
|
327
372
|
const t = useT();
|
|
328
373
|
const { setResourceVisibility, isPending } = useResourceVisibilityMutation(
|
|
@@ -334,6 +379,14 @@ function LinkTab({
|
|
|
334
379
|
const sharesLoaded = visibility !== null;
|
|
335
380
|
const visibilityPending = isPending || sharesQuery.isLoading;
|
|
336
381
|
const isLoomRecording = isLoomRecordingProp || isLoomEmbedUrl(videoUrl);
|
|
382
|
+
const needsScopedAgentContext = !isPublic || hasPassword !== false;
|
|
383
|
+
const publicAgentContextUrl = useMemo(
|
|
384
|
+
() =>
|
|
385
|
+
isPublic && hasPassword === false
|
|
386
|
+
? absolutePublicAgentContextUrl(recordingId)
|
|
387
|
+
: "",
|
|
388
|
+
[hasPassword, isPublic, recordingId],
|
|
389
|
+
);
|
|
337
390
|
const emailPreviewThumbnailUrl = useMemo(() => {
|
|
338
391
|
if (!isPublic || hasPassword !== false || !sharesLoaded) return null;
|
|
339
392
|
const variant = preferredThumbnailVariant({
|
|
@@ -397,10 +450,10 @@ function LinkTab({
|
|
|
397
450
|
try {
|
|
398
451
|
const result = (await createAgentLinkAsyncRef.current({
|
|
399
452
|
recordingId,
|
|
400
|
-
})) as {
|
|
453
|
+
})) as { contextUrl?: string };
|
|
401
454
|
if (agentLinkRequestIdRef.current !== requestId) return;
|
|
402
|
-
if (result?.
|
|
403
|
-
setAgentContextUrl(result.
|
|
455
|
+
if (result?.contextUrl) {
|
|
456
|
+
setAgentContextUrl(result.contextUrl);
|
|
404
457
|
} else {
|
|
405
458
|
setAgentLinkError(true);
|
|
406
459
|
}
|
|
@@ -416,20 +469,30 @@ function LinkTab({
|
|
|
416
469
|
setAgentLinkError(false);
|
|
417
470
|
if (!sharesLoaded) return;
|
|
418
471
|
|
|
419
|
-
if (
|
|
472
|
+
if (needsScopedAgentContext) {
|
|
420
473
|
void loadAgentContextUrl();
|
|
421
474
|
}
|
|
422
475
|
|
|
423
476
|
return () => {
|
|
424
477
|
agentLinkRequestIdRef.current += 1;
|
|
425
478
|
};
|
|
426
|
-
}, [
|
|
479
|
+
}, [
|
|
480
|
+
loadAgentContextUrl,
|
|
481
|
+
needsScopedAgentContext,
|
|
482
|
+
recordingId,
|
|
483
|
+
sharesLoaded,
|
|
484
|
+
visibility,
|
|
485
|
+
]);
|
|
427
486
|
|
|
428
|
-
const agentLink = isPublic
|
|
487
|
+
const agentLink = isPublic
|
|
488
|
+
? publicAgentContextUrl || agentContextUrl
|
|
489
|
+
: agentContextUrl;
|
|
429
490
|
const agentShareDisabled =
|
|
430
491
|
visibilityPending ||
|
|
431
492
|
!sharesLoaded ||
|
|
432
|
-
|
|
493
|
+
!agentLink ||
|
|
494
|
+
(needsScopedAgentContext &&
|
|
495
|
+
(isPending || createAgentLink.isPending || !agentContextUrl));
|
|
433
496
|
const agentPrompt = agentLink
|
|
434
497
|
? t("shareDialog.agentPrompt", { agentContextUrl: agentLink })
|
|
435
498
|
: "";
|
|
@@ -460,21 +523,23 @@ function LinkTab({
|
|
|
460
523
|
|
|
461
524
|
return (
|
|
462
525
|
<div className="space-y-4">
|
|
463
|
-
{
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
<div className="
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
526
|
+
{canViewShares ? (
|
|
527
|
+
visibility ? (
|
|
528
|
+
<GeneralAccessSelect
|
|
529
|
+
visibility={visibility}
|
|
530
|
+
canManage={canManage}
|
|
531
|
+
isPending={visibilityPending}
|
|
532
|
+
onChange={(next) => setResourceVisibility(next)}
|
|
533
|
+
publicDescription={t("shareDialog.publicDescription")}
|
|
534
|
+
showDescription={false}
|
|
535
|
+
/>
|
|
536
|
+
) : (
|
|
537
|
+
<div className="space-y-2" aria-hidden>
|
|
538
|
+
<div className="h-3 w-24 animate-pulse rounded bg-muted" />
|
|
539
|
+
<div className="h-12 w-full animate-pulse rounded bg-muted" />
|
|
540
|
+
</div>
|
|
541
|
+
)
|
|
542
|
+
) : null}
|
|
478
543
|
|
|
479
544
|
<CopyField
|
|
480
545
|
label={
|
|
@@ -486,71 +551,49 @@ function LinkTab({
|
|
|
486
551
|
disabled={visibilityPending || !sharesLoaded}
|
|
487
552
|
/>
|
|
488
553
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
<IconChevronDown
|
|
509
|
-
aria-hidden="true"
|
|
510
|
-
className={`size-4 shrink-0 text-muted-foreground transition-transform ${agentDetailsOpen ? "rotate-180" : ""}`}
|
|
511
|
-
/>
|
|
512
|
-
</button>
|
|
513
|
-
</CollapsibleTrigger>
|
|
514
|
-
<CollapsibleContent className="clips-collapsible-content border-t border-border px-3 py-3">
|
|
515
|
-
<div className="space-y-2">
|
|
516
|
-
<CopyField
|
|
517
|
-
label={t("shareDialog.shareWithAgents")}
|
|
518
|
-
value={agentLink}
|
|
519
|
-
disabled={agentShareDisabled}
|
|
520
|
-
/>
|
|
521
|
-
{sharesLoaded ? (
|
|
522
|
-
<>
|
|
554
|
+
<ShareAgentsSection
|
|
555
|
+
label={t("shareDialog.shareWithAgents")}
|
|
556
|
+
open={agentDetailsOpen}
|
|
557
|
+
onOpenChange={setAgentDetailsOpen}
|
|
558
|
+
contentClassName="clips-collapsible-content"
|
|
559
|
+
>
|
|
560
|
+
<div className="space-y-2">
|
|
561
|
+
<CopyField
|
|
562
|
+
label={t("shareDialog.shareLink")}
|
|
563
|
+
value={agentLink}
|
|
564
|
+
disabled={agentShareDisabled}
|
|
565
|
+
/>
|
|
566
|
+
{sharesLoaded ? (
|
|
567
|
+
<>
|
|
568
|
+
<p className="text-xs text-muted-foreground">
|
|
569
|
+
{t("shareDialog.agentTokenDescription")}
|
|
570
|
+
</p>
|
|
571
|
+
{agentLinkError ? (
|
|
572
|
+
<div className="flex items-center justify-between gap-2 rounded-md border border-border bg-muted/30 px-3 py-2">
|
|
523
573
|
<p className="text-xs text-muted-foreground">
|
|
524
|
-
{t("shareDialog.
|
|
574
|
+
{t("shareDialog.agentLinkUnavailable")}
|
|
525
575
|
</p>
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
disabled={createAgentLink.isPending}
|
|
538
|
-
>
|
|
539
|
-
{t("shareDialog.retryAgentLink")}
|
|
540
|
-
</Button>
|
|
541
|
-
</div>
|
|
542
|
-
) : null}
|
|
543
|
-
<CopyField
|
|
544
|
-
label={t("shareDialog.copyAgentPrompt")}
|
|
545
|
-
value={agentPrompt}
|
|
546
|
-
disabled={agentShareDisabled}
|
|
547
|
-
/>
|
|
548
|
-
</>
|
|
576
|
+
<Button
|
|
577
|
+
type="button"
|
|
578
|
+
variant="ghost"
|
|
579
|
+
size="sm"
|
|
580
|
+
className="h-7"
|
|
581
|
+
onClick={() => void loadAgentContextUrl()}
|
|
582
|
+
disabled={createAgentLink.isPending}
|
|
583
|
+
>
|
|
584
|
+
{t("shareDialog.retryAgentLink")}
|
|
585
|
+
</Button>
|
|
586
|
+
</div>
|
|
549
587
|
) : null}
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
588
|
+
<CopyField
|
|
589
|
+
label={t("shareDialog.copyAgentPrompt")}
|
|
590
|
+
value={agentPrompt}
|
|
591
|
+
disabled={agentShareDisabled}
|
|
592
|
+
/>
|
|
593
|
+
</>
|
|
594
|
+
) : null}
|
|
595
|
+
</div>
|
|
596
|
+
</ShareAgentsSection>
|
|
554
597
|
|
|
555
598
|
{showMakePublic ? (
|
|
556
599
|
<MakePublicCard
|
|
@@ -8,10 +8,6 @@ import {
|
|
|
8
8
|
isLikelyPhoneMicLabel,
|
|
9
9
|
type AudioInputFallback,
|
|
10
10
|
} from "@shared/media-device-selection";
|
|
11
|
-
import {
|
|
12
|
-
createMicAudioCleanup,
|
|
13
|
-
type MicAudioCleanupHandle,
|
|
14
|
-
} from "@shared/mic-audio-cleanup";
|
|
15
11
|
import {
|
|
16
12
|
SCREEN_CAPTURE_FRAME_RATE,
|
|
17
13
|
screenCaptureDisplayOptions,
|
|
@@ -509,7 +505,6 @@ export class RecorderEngine {
|
|
|
509
505
|
private cameraComposite: CameraCompositeHandle | null = null;
|
|
510
506
|
private audioMixCtx: AudioContext | null = null;
|
|
511
507
|
private audioMixSources: MediaStreamAudioSourceNode[] = [];
|
|
512
|
-
private micAudioCleanup: MicAudioCleanupHandle[] = [];
|
|
513
508
|
private recorder: MediaRecorder | null = null;
|
|
514
509
|
private mimeType: string = "video/webm";
|
|
515
510
|
|
|
@@ -1360,7 +1355,6 @@ export class RecorderEngine {
|
|
|
1360
1355
|
// Full stream teardown happens in the finally block below.
|
|
1361
1356
|
this.cameraLive = false;
|
|
1362
1357
|
this.audioMixSources = [];
|
|
1363
|
-
this.stopMicAudioCleanup();
|
|
1364
1358
|
this.audioMixCtx?.close().catch(() => {});
|
|
1365
1359
|
this.audioMixCtx = null;
|
|
1366
1360
|
for (const s of [this.cameraStream, this.rawCameraStream, this.micStream]) {
|
|
@@ -1828,26 +1822,15 @@ export class RecorderEngine {
|
|
|
1828
1822
|
this.audioMixSources = [];
|
|
1829
1823
|
const dest = ctx.createMediaStreamDestination();
|
|
1830
1824
|
for (const input of audioInputs) {
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
audioContext: ctx,
|
|
1835
|
-
});
|
|
1836
|
-
this.micAudioCleanup.push(cleanup);
|
|
1837
|
-
track = cleanup.stream.getAudioTracks()[0] ?? track;
|
|
1838
|
-
}
|
|
1839
|
-
const source = ctx.createMediaStreamSource(new MediaStream([track]));
|
|
1825
|
+
const source = ctx.createMediaStreamSource(
|
|
1826
|
+
new MediaStream([input.track]),
|
|
1827
|
+
);
|
|
1840
1828
|
source.connect(dest);
|
|
1841
1829
|
this.audioMixSources.push(source);
|
|
1842
1830
|
}
|
|
1843
1831
|
return dest.stream.getAudioTracks()[0];
|
|
1844
1832
|
}
|
|
1845
1833
|
|
|
1846
|
-
private stopMicAudioCleanup(): void {
|
|
1847
|
-
for (const cleanup of this.micAudioCleanup) cleanup.stop();
|
|
1848
|
-
this.micAudioCleanup = [];
|
|
1849
|
-
}
|
|
1850
|
-
|
|
1851
1834
|
private buildCombinedStream(): MediaStream {
|
|
1852
1835
|
if (this.opts.mode === "screen") {
|
|
1853
1836
|
return this.buildDisplayRecordingStream();
|
|
@@ -2382,7 +2365,6 @@ export class RecorderEngine {
|
|
|
2382
2365
|
// aren't mistaken for a disconnect.
|
|
2383
2366
|
this.cameraLive = false;
|
|
2384
2367
|
this.audioMixSources = [];
|
|
2385
|
-
this.stopMicAudioCleanup();
|
|
2386
2368
|
this.audioMixCtx?.close().catch(() => {});
|
|
2387
2369
|
this.audioMixCtx = null;
|
|
2388
2370
|
this.cameraComposite?.cleanup();
|
|
@@ -4,9 +4,8 @@ import {
|
|
|
4
4
|
useActionQuery,
|
|
5
5
|
} from "@agent-native/core/client/hooks";
|
|
6
6
|
import { useT } from "@agent-native/core/client/i18n";
|
|
7
|
+
import { ShareCopyRow } from "@agent-native/toolkit/sharing";
|
|
7
8
|
import {
|
|
8
|
-
IconCheck,
|
|
9
|
-
IconLink,
|
|
10
9
|
IconLock,
|
|
11
10
|
IconSend2,
|
|
12
11
|
IconTrash,
|
|
@@ -281,35 +280,19 @@ export function CopyField({
|
|
|
281
280
|
description?: string;
|
|
282
281
|
}) {
|
|
283
282
|
const t = useT();
|
|
284
|
-
const [copied, setCopied] = useState(false);
|
|
285
|
-
const copy = () => {
|
|
286
|
-
if (disabled) return;
|
|
287
|
-
copyToClipboard(value);
|
|
288
|
-
setCopied(true);
|
|
289
|
-
setTimeout(() => setCopied(false), 1400);
|
|
290
|
-
};
|
|
291
283
|
return (
|
|
292
|
-
<
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
onClick={copy}
|
|
305
|
-
disabled={disabled}
|
|
306
|
-
className="h-9"
|
|
307
|
-
>
|
|
308
|
-
{copied ? <IconCheck size={14} /> : <IconLink size={14} />}
|
|
309
|
-
{copied ? t("recordRoute.linkCopied") : t("shareUi.copy")}
|
|
310
|
-
</Button>
|
|
311
|
-
</div>
|
|
312
|
-
</div>
|
|
284
|
+
<ShareCopyRow
|
|
285
|
+
label={label}
|
|
286
|
+
value={value}
|
|
287
|
+
description={description}
|
|
288
|
+
disabled={disabled}
|
|
289
|
+
copyLabel={t("shareUi.copy")}
|
|
290
|
+
copiedLabel={t("recordRoute.linkCopied")}
|
|
291
|
+
onCopy={(nextValue) => {
|
|
292
|
+
copyToClipboard(nextValue);
|
|
293
|
+
return true;
|
|
294
|
+
}}
|
|
295
|
+
/>
|
|
313
296
|
);
|
|
314
297
|
}
|
|
315
298
|
|
|
@@ -256,6 +256,16 @@ const messages = {
|
|
|
256
256
|
passwordProtected: "This clip is password-protected",
|
|
257
257
|
linkExpired: "Link expired",
|
|
258
258
|
linkExpiredMessage: "The creator set an expiry on this share link.",
|
|
259
|
+
privateClip: "Private clip",
|
|
260
|
+
privateClipMessage:
|
|
261
|
+
"This clip is private. Request access and the owner will be notified.",
|
|
262
|
+
privateClipSignedOutMessage:
|
|
263
|
+
"This clip is private. Sign in to request access from the owner.",
|
|
264
|
+
requestAccess: "Request access",
|
|
265
|
+
requestingAccess: "Requesting access...",
|
|
266
|
+
accessRequested: "Access requested",
|
|
267
|
+
accessRequestSent: "The clip owner was notified.",
|
|
268
|
+
accessRequestFailed: "Couldn't request access. Try again.",
|
|
259
269
|
clipUnavailable: "Clip unavailable",
|
|
260
270
|
clipUnavailableMessage:
|
|
261
271
|
"This recording isn't public, or the link is invalid. If it's your clip, sign in to check access.",
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
useActionQuery,
|
|
6
6
|
} from "@agent-native/core/client/hooks";
|
|
7
7
|
import { useT } from "@agent-native/core/client/i18n";
|
|
8
|
+
import { ShareTrigger } from "@agent-native/toolkit/sharing";
|
|
8
9
|
import {
|
|
9
10
|
IconArrowLeft,
|
|
10
11
|
IconCheck,
|
|
@@ -18,7 +19,6 @@ import {
|
|
|
18
19
|
IconNotes,
|
|
19
20
|
IconPlayerStop,
|
|
20
21
|
IconRefresh,
|
|
21
|
-
IconShare3,
|
|
22
22
|
IconTrash,
|
|
23
23
|
IconUsers,
|
|
24
24
|
} from "@tabler/icons-react";
|
|
@@ -711,10 +711,10 @@ export default function MeetingDetailRoute() {
|
|
|
711
711
|
Boolean(data?.transcript?.fullText?.trim()))
|
|
712
712
|
}
|
|
713
713
|
>
|
|
714
|
-
<
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
714
|
+
<ShareTrigger
|
|
715
|
+
label={t("meetingDetail.share")}
|
|
716
|
+
className="shrink-0"
|
|
717
|
+
/>
|
|
718
718
|
</ShareMeetingPopover>
|
|
719
719
|
{canEdit && (
|
|
720
720
|
<AlertDialog open={deleteOpen} onOpenChange={setDeleteOpen}>
|