@agent-native/core 0.80.11 → 0.81.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 +53 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/cli/design-connect.ts +419 -19
- package/corpus/core/src/client/AgentPanel.tsx +33 -1
- package/corpus/core/src/client/ConnectBuilderCard.tsx +1 -0
- package/corpus/core/src/client/chat/index.ts +1 -0
- package/corpus/core/src/client/chat/run-recovery.tsx +9 -7
- package/corpus/core/src/client/chat-view-transition.ts +33 -2
- package/corpus/core/src/client/composer/PromptComposer.tsx +21 -2
- package/corpus/core/src/client/index.ts +1 -0
- package/corpus/core/src/client/org/OrgSwitcher.tsx +26 -4
- package/corpus/core/src/client/sharing/ShareButton.tsx +3 -3
- package/corpus/core/src/client/use-agent-chat-home-handoff.ts +31 -3
- package/corpus/core/src/db/client.ts +29 -2
- package/corpus/core/src/provider-api/index.ts +29 -0
- package/corpus/core/src/server/core-routes-plugin.ts +58 -20
- package/corpus/core/src/styles/agent-native.css +54 -0
- package/corpus/core/src/usage/store.ts +2 -2
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +118 -10
- package/corpus/templates/analytics/app/components/layout/layout-route-policy.ts +7 -0
- package/corpus/templates/analytics/app/global.css +8 -0
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +7 -1
- package/corpus/templates/analytics/app/lib/chat-handoff.ts +34 -0
- package/corpus/templates/analytics/app/pages/Ask.tsx +9 -18
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +2 -2
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +109 -21
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +4 -6
- package/corpus/templates/analytics/changelog/2026-06-30-ask-opens-a-fresh-chat-unless-you-were-just-chatting-and-das.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-30-dashboard-email-reports-are-more-reliable-and-use-cleaner.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-30-dashboard-toolbar-controls-use-a-quieter-share-button-and-ve.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-30-session-replay-rows-show-whole-minute-durations-in-the-playl.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-30-session-replays-now-render-captured-styling-and-keep-the-eve.md +6 -0
- package/corpus/templates/analytics/server/jobs/dashboard-report.ts +16 -3
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +31 -14
- package/corpus/templates/assets/actions/open-asset-picker.ts +9 -0
- package/corpus/templates/assets/app/global.css +15 -0
- package/corpus/templates/assets/app/hooks/use-navigation-state.ts +4 -0
- package/corpus/templates/assets/app/routes/library.tsx +90 -16
- package/corpus/templates/assets/changelog/2026-06-30-the-assets-picker-now-supports-a-vertical-embedded-layout-fo.md +6 -0
- package/corpus/templates/clips/actions/finalize-recording.ts +1 -12
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +10 -5
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +6 -8
- package/corpus/templates/clips/changelog/2026-06-30-extension-save-recovery-avoids-false-upload-failures.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-30-longer-chrome-extension-recordings-now-keep-saving-reliably-.md +6 -0
- package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
- package/corpus/templates/clips/chrome-extension/src/background.ts +19 -10
- package/corpus/templates/clips/chrome-extension/src/content-script.ts +38 -12
- package/corpus/templates/clips/chrome-extension/src/finalize-recovery.ts +224 -0
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +119 -16
- package/corpus/templates/clips/chrome-extension/src/overlay.ts +16 -0
- package/corpus/templates/clips/server/lib/recording-upload-state.ts +48 -0
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +9 -1
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +63 -13
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/status.get.ts +74 -0
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +32 -0
- package/corpus/templates/design/AGENTS.md +27 -0
- package/corpus/templates/design/CODE_NATIVE_DESIGN_STUDIO_IMPLEMENTATION_PLAN.md +1 -1
- package/corpus/templates/design/DESIGN-STUDIO-PLAN.md +5 -5
- package/corpus/templates/design/actions/apply-component-prop-edit.ts +63 -20
- package/corpus/templates/design/actions/apply-motion-edit.ts +67 -69
- package/corpus/templates/design/actions/apply-shader-fill.ts +148 -56
- package/corpus/templates/design/actions/capture-design-state.ts +27 -4
- package/corpus/templates/design/actions/connect-localhost.ts +59 -22
- package/corpus/templates/design/actions/export-zip.ts +23 -8
- package/corpus/templates/design/actions/generate-design.ts +53 -1
- package/corpus/templates/design/actions/get-component-details.ts +5 -19
- package/corpus/templates/design/actions/get-motion-timeline.ts +135 -10
- package/corpus/templates/design/actions/grant-localhost-write-consent.ts +116 -0
- package/corpus/templates/design/actions/import-design-tokens.ts +521 -0
- package/corpus/templates/design/actions/index-design-tokens.ts +10 -1
- package/corpus/templates/design/actions/insert-design-native-asset.ts +268 -0
- package/corpus/templates/design/actions/insert-figma-library-asset.ts +233 -0
- package/corpus/templates/design/actions/list-design-extensions.ts +32 -10
- package/corpus/templates/design/actions/list-design-native-assets.ts +105 -0
- package/corpus/templates/design/actions/list-figma-library-assets.ts +292 -0
- package/corpus/templates/design/actions/migrate-board-objects-to-file.ts +238 -0
- package/corpus/templates/design/actions/navigate.ts +18 -3
- package/corpus/templates/design/actions/provider-api-catalog.ts +2 -2
- package/corpus/templates/design/actions/provider-api-docs.ts +1 -1
- package/corpus/templates/design/actions/provider-api-request.ts +3 -3
- package/corpus/templates/design/actions/revoke-localhost-write-consent.ts +48 -0
- package/corpus/templates/design/actions/run-design-audit.ts +53 -4
- package/corpus/templates/design/actions/run-design-extension-action.ts +1 -1
- package/corpus/templates/design/actions/view-screen.ts +1 -1
- package/corpus/templates/design/actions/write-local-file.ts +213 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +230 -3308
- package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +30 -20
- package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +776 -287
- package/corpus/templates/design/app/components/design/EditPanel.tsx +212 -208
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +14 -2
- package/corpus/templates/design/app/components/design/LocalhostWriteConsentDialog.tsx +161 -0
- package/corpus/templates/design/app/components/design/MotionDock.tsx +235 -266
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +490 -55
- package/corpus/templates/design/app/components/design/ReviewPanel.tsx +43 -62
- package/corpus/templates/design/app/components/design/StatesPanel.tsx +34 -61
- package/corpus/templates/design/app/components/design/TokensPanel.tsx +251 -0
- package/corpus/templates/design/app/components/design/bridge/codegen.ts +125 -0
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +4037 -0
- package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +62 -0
- package/corpus/templates/design/app/components/design/bridge/hit-test.bridge.ts +272 -0
- package/corpus/templates/design/app/components/design/bridge/nav.bridge.ts +116 -0
- package/corpus/templates/design/app/components/design/bridge/sample.bridge.ts +24 -0
- package/corpus/templates/design/app/components/design/bridge/shader-fill-preview.bridge.ts +78 -0
- package/corpus/templates/design/app/components/design/bridge/tsconfig.json +17 -0
- package/corpus/templates/design/app/components/design/bridge/tweak.bridge.ts +28 -0
- package/corpus/templates/design/app/components/design/bridge/zoom.bridge.ts +43 -0
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +45 -16
- package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +88 -9
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +94 -9
- package/corpus/templates/design/app/components/layout/Layout.tsx +19 -3
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +1 -1
- package/corpus/templates/design/app/global.css +7 -0
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +23 -0
- package/corpus/templates/design/app/i18n/zh-TW.ts +21 -0
- package/corpus/templates/design/app/i18n-data.ts +358 -0
- package/corpus/templates/design/app/lib/pending-generation.ts +1 -0
- package/corpus/templates/design/app/pages/DesignEditor.tsx +2402 -499
- package/corpus/templates/design/app/pages/Index.tsx +5 -1
- package/corpus/templates/design/changelog/2026-06-30-applying-the-one-click-fix-for-a-small-tap-target-accessibil.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-canvas-creation-screen-dragging-undo-redo-and-image-fill-edi.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-component-prop-edits-and-shader-fills-now-preserve-rapid-sam.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-can-browse-figma-library-components-and-insert-them-i.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-now-has-a-figma-style-left-rail-for-file-agent-assets.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-now-has-native-components-embedded-media-and-figma-im.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-preview-now-includes-a-publish-app-waitlist-option-fr.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-s-left-rail-now-matches-the-sidebar-chrome-and-uses-t.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-s-tools-create-menu-now-stays-compact-instead-of-rend.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-starter-prompts-now-begin-generating-immediately-and-.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-tools-now-use-a-quieter-figma-style-list-layout.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-drawing-rectangles-on-the-all-screens-canvas-no-longer-flash.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-fixed-code-native-design-studio-edits-so-component-props-mot.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-fixed-visual-editing-hover-overlays-and-spacing-handles-so-s.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-motion-edits-now-save-automatically-without-a-separate-css-a.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-motion-timelines-now-reopen-as-editable-tracks-after-writing.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-new-design-prompts-with-uploaded-screenshots-work-reliably-o.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-screen-previews-in-all-screens-view-now-keep-rounded-outline.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-selection-outlines-now-sit-flush-on-rectangles-drawn-directl.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-share-options-use-a-tighter-design-editor-popover-with-compa.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-the-collapsed-motion-panel-now-stays-tucked-under-the-left-s.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-the-design-inspector-now-shows-states-and-review-in-a-tighte.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-the-sidebar-keeps-the-organization-picker-space-stable-while.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-tokens-can-now-be-imported-from-pasted-notes-code-files-fold.md +6 -0
- package/corpus/templates/design/e2e/helpers.ts +168 -65
- package/corpus/templates/design/package.json +3 -1
- package/corpus/templates/design/server/db/schema.ts +23 -0
- package/corpus/templates/design/server/handlers/uploads.ts +22 -1
- package/corpus/templates/design/server/lib/provider-api.ts +7 -4
- package/corpus/templates/design/server/lib/verify-write-grant.ts +108 -0
- package/corpus/templates/design/server/plugins/db.ts +39 -0
- package/corpus/templates/design/server/register-secrets.ts +38 -0
- package/corpus/templates/design/shared/board-file.ts +228 -0
- package/corpus/templates/design/shared/board-objects.ts +288 -0
- package/corpus/templates/design/shared/code-layer.ts +52 -0
- package/corpus/templates/design/shared/motion-compiler.ts +58 -7
- package/corpus/templates/design/shared/motion-timeline.ts +2 -2
- package/corpus/templates/design/tsconfig.json +2 -1
- package/corpus/templates/slides/AGENTS.md +9 -0
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +4 -0
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +4 -24
- package/corpus/templates/slides/app/lib/export-pdf-client.ts +29 -20
- package/corpus/templates/slides/app/lib/export-pptx-client.ts +365 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +12 -9
- package/corpus/templates/slides/app/vite-env.d.ts +18 -0
- package/corpus/templates/slides/changelog/2026-06-30-powerpoint-downloads-now-preserve-the-rendered-slide-layout-.md +6 -0
- package/corpus/templates/slides/changelog/2026-06-30-unavailable-decks-open-in-a-cleaner-full-height-centered-sta.md +6 -0
- package/corpus/templates/slides/package.json +1 -0
- package/corpus/templates/slides/vite.config.ts +1 -0
- package/dist/cli/design-connect.d.ts +25 -0
- package/dist/cli/design-connect.d.ts.map +1 -1
- package/dist/cli/design-connect.js +357 -18
- package/dist/cli/design-connect.js.map +1 -1
- package/dist/client/AgentPanel.d.ts +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +18 -3
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/ConnectBuilderCard.d.ts.map +1 -1
- package/dist/client/ConnectBuilderCard.js +1 -0
- package/dist/client/ConnectBuilderCard.js.map +1 -1
- package/dist/client/chat/index.d.ts +1 -1
- package/dist/client/chat/index.d.ts.map +1 -1
- package/dist/client/chat/index.js +1 -1
- package/dist/client/chat/index.js.map +1 -1
- package/dist/client/chat/run-recovery.d.ts.map +1 -1
- package/dist/client/chat/run-recovery.js +5 -5
- package/dist/client/chat/run-recovery.js.map +1 -1
- package/dist/client/chat-view-transition.d.ts +6 -0
- package/dist/client/chat-view-transition.d.ts.map +1 -1
- package/dist/client/chat-view-transition.js +23 -2
- package/dist/client/chat-view-transition.js.map +1 -1
- package/dist/client/composer/PromptComposer.d.ts.map +1 -1
- package/dist/client/composer/PromptComposer.js +3 -2
- package/dist/client/composer/PromptComposer.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/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +11 -4
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/sharing/ShareButton.js +3 -3
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/client/use-agent-chat-home-handoff.d.ts +8 -2
- package/dist/client/use-agent-chat-home-handoff.d.ts.map +1 -1
- package/dist/client/use-agent-chat-home-handoff.js +20 -6
- package/dist/client/use-agent-chat-home-handoff.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/db/client.d.ts +1 -0
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +28 -2
- package/dist/db/client.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +8 -8
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/index.d.ts +5 -4
- package/dist/provider-api/index.d.ts.map +1 -1
- package/dist/provider-api/index.js +28 -0
- package/dist/provider-api/index.js.map +1 -1
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/core-routes-plugin.d.ts +25 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +43 -18
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/styles/agent-native.css +54 -0
- package/dist/usage/store.js +2 -2
- package/dist/usage/store.js.map +1 -1
- package/package.json +1 -1
|
@@ -42,8 +42,8 @@ const DASHBOARD_REPORT_SCREENSHOT_PARAM = "reportScreenshot";
|
|
|
42
42
|
const DASHBOARD_REPORT_SETTINGS_PARAM = "reportSettings";
|
|
43
43
|
const DASHBOARD_REPORT_CID = "dashboard-report-snapshot";
|
|
44
44
|
const LOCAL_SCREENSHOT_TIMEOUT_MS = 90_000;
|
|
45
|
-
const SERVERLESS_SCREENSHOT_TIMEOUT_MS =
|
|
46
|
-
const SERVERLESS_SECOND_READY_TIMEOUT_MS =
|
|
45
|
+
const SERVERLESS_SCREENSHOT_TIMEOUT_MS = 60_000;
|
|
46
|
+
const SERVERLESS_SECOND_READY_TIMEOUT_MS = 30_000;
|
|
47
47
|
const MAX_SCREENSHOT_VIEWPORT_HEIGHT = 30_000;
|
|
48
48
|
const SCREENSHOT_VIEWPORT_PADDING = 64;
|
|
49
49
|
|
|
@@ -249,11 +249,28 @@ async function launchScreenshotBrowser() {
|
|
|
249
249
|
}
|
|
250
250
|
|
|
251
251
|
function screenshotTimeoutMs(): number {
|
|
252
|
+
const configured = positiveIntEnv("DASHBOARD_REPORT_SCREENSHOT_TIMEOUT_MS");
|
|
253
|
+
if (configured) return configured;
|
|
252
254
|
return isServerlessBrowserRuntime()
|
|
253
255
|
? SERVERLESS_SCREENSHOT_TIMEOUT_MS
|
|
254
256
|
: LOCAL_SCREENSHOT_TIMEOUT_MS;
|
|
255
257
|
}
|
|
256
258
|
|
|
259
|
+
function secondReadyTimeoutMs(): number {
|
|
260
|
+
const configured = positiveIntEnv("DASHBOARD_REPORT_SECOND_READY_TIMEOUT_MS");
|
|
261
|
+
if (configured) return configured;
|
|
262
|
+
return isServerlessBrowserRuntime()
|
|
263
|
+
? SERVERLESS_SECOND_READY_TIMEOUT_MS
|
|
264
|
+
: screenshotTimeoutMs();
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function positiveIntEnv(name: string): number | null {
|
|
268
|
+
const raw = process.env[name]?.trim();
|
|
269
|
+
if (!raw) return null;
|
|
270
|
+
const parsed = Number.parseInt(raw, 10);
|
|
271
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
272
|
+
}
|
|
273
|
+
|
|
257
274
|
async function waitForDashboardReportReady(
|
|
258
275
|
page: any,
|
|
259
276
|
timeout: number,
|
|
@@ -393,12 +410,7 @@ async function captureDashboardPng(
|
|
|
393
410
|
await capture.waitFor({ state: "visible", timeout });
|
|
394
411
|
await waitForDashboardReportReady(page, timeout);
|
|
395
412
|
await scrollDashboardForLazyRendering(page);
|
|
396
|
-
await waitForDashboardReportReady(
|
|
397
|
-
page,
|
|
398
|
-
isServerlessBrowserRuntime()
|
|
399
|
-
? SERVERLESS_SECOND_READY_TIMEOUT_MS
|
|
400
|
-
: timeout,
|
|
401
|
-
);
|
|
413
|
+
await waitForDashboardReportReady(page, secondReadyTimeoutMs());
|
|
402
414
|
|
|
403
415
|
await fitViewportToDashboardCapture(page, capture, attempt.viewport);
|
|
404
416
|
await capture.scrollIntoViewIfNeeded();
|
|
@@ -478,18 +490,15 @@ function renderReportEmailHtml(
|
|
|
478
490
|
return `<!doctype html>
|
|
479
491
|
<html>
|
|
480
492
|
<body style="margin:0;padding:24px;background:#ffffff;color:#171717;font-family:Inter,Arial,sans-serif;">
|
|
481
|
-
<
|
|
482
|
-
Here's
|
|
483
|
-
</
|
|
493
|
+
<p style="margin:0 0 12px;font-size:15px;line-height:1.4;font-weight:600;">
|
|
494
|
+
Here's your report of <a href="${dashboardUrl}" style="color:#2563eb;text-decoration:none;">${title}</a> for ${date}
|
|
495
|
+
</p>
|
|
484
496
|
${screenshotBlock}
|
|
485
497
|
<p style="margin:18px 0 0;color:#525866;font-size:13px;line-height:1.45;">
|
|
486
498
|
<a href="${dashboardUrl}" style="color:#2563eb;text-decoration:none;">Open dashboard</a>
|
|
487
499
|
<span style="color:#9ca3af;"> · </span>
|
|
488
500
|
<a href="${reportSettingsUrl}" style="color:#2563eb;text-decoration:none;">Edit subscription settings</a>
|
|
489
501
|
</p>
|
|
490
|
-
<p style="margin:6px 0 0;color:#6b7280;font-size:12px;line-height:1.45;">
|
|
491
|
-
Change recipients, delivery time, filters, or turn this report on/off.
|
|
492
|
-
</p>
|
|
493
502
|
</body>
|
|
494
503
|
</html>`;
|
|
495
504
|
}
|
|
@@ -521,6 +530,7 @@ function reportFilename(title: string): string {
|
|
|
521
530
|
|
|
522
531
|
export async function sendDashboardReportSubscription(
|
|
523
532
|
sub: DashboardReportSubscription,
|
|
533
|
+
options: { requireScreenshot?: boolean } = {},
|
|
524
534
|
): Promise<{
|
|
525
535
|
dashboardUrl: string;
|
|
526
536
|
recipientCount: number;
|
|
@@ -530,6 +540,13 @@ export async function sendDashboardReportSubscription(
|
|
|
530
540
|
}> {
|
|
531
541
|
const snapshot = await collectReportSnapshot(sub);
|
|
532
542
|
const capture = await captureDashboardPngWithFallback(sub, snapshot);
|
|
543
|
+
if (!capture.png && options.requireScreenshot) {
|
|
544
|
+
throw new Error(
|
|
545
|
+
capture.error
|
|
546
|
+
? `Dashboard screenshot unavailable: ${capture.error}`
|
|
547
|
+
: "Dashboard screenshot unavailable",
|
|
548
|
+
);
|
|
549
|
+
}
|
|
533
550
|
const screenshotAttached = Boolean(capture.png);
|
|
534
551
|
const html = renderReportEmailHtml(snapshot, { screenshotAttached });
|
|
535
552
|
const text = renderReportText(snapshot, { screenshotAttached });
|
|
@@ -7,6 +7,7 @@ import { z } from "zod";
|
|
|
7
7
|
import { IMAGE_QUALITY_TIERS, STYLE_STRENGTHS } from "../shared/api.js";
|
|
8
8
|
|
|
9
9
|
const mediaTypeSchema = z.enum(["image", "video"]);
|
|
10
|
+
const layoutSchema = z.enum(["default", "vertical"]);
|
|
10
11
|
const booleanParam = z.preprocess((value) => {
|
|
11
12
|
if (typeof value === "boolean") return value;
|
|
12
13
|
if (typeof value !== "string") return value;
|
|
@@ -77,6 +78,11 @@ const schema = z.object({
|
|
|
77
78
|
.string()
|
|
78
79
|
.optional()
|
|
79
80
|
.describe("Calling app id, for audit grouping, e.g. design."),
|
|
81
|
+
layout: layoutSchema
|
|
82
|
+
.default("default")
|
|
83
|
+
.describe(
|
|
84
|
+
"Picker layout density. Use vertical when embedding in a narrow sidebar.",
|
|
85
|
+
),
|
|
80
86
|
});
|
|
81
87
|
|
|
82
88
|
type OpenAssetPickerArgs = z.infer<typeof schema>;
|
|
@@ -132,6 +138,7 @@ function pickerPath(args: Partial<OpenAssetPickerArgs>): string {
|
|
|
132
138
|
}
|
|
133
139
|
if (args.includeLogo) params.set("includeLogo", "1");
|
|
134
140
|
if (args.callerAppId?.trim()) params.set("callerAppId", args.callerAppId);
|
|
141
|
+
if (args.layout === "vertical") params.set("layout", "vertical");
|
|
135
142
|
for (const runId of args.candidateRunIds ?? []) {
|
|
136
143
|
if (runId.trim()) params.append("candidateRunIds", runId.trim());
|
|
137
144
|
}
|
|
@@ -206,6 +213,7 @@ const action = defineAction({
|
|
|
206
213
|
prompt: args.prompt ?? null,
|
|
207
214
|
aspectRatio: args.aspectRatio ?? null,
|
|
208
215
|
presetId: args.presetId ?? null,
|
|
216
|
+
layout: args.layout,
|
|
209
217
|
_writeId: `open-asset-picker-${Date.now()}-${Math.random()
|
|
210
218
|
.toString(36)
|
|
211
219
|
.slice(2, 8)}`,
|
|
@@ -219,6 +227,7 @@ const action = defineAction({
|
|
|
219
227
|
path,
|
|
220
228
|
url: path,
|
|
221
229
|
embed: true,
|
|
230
|
+
layout: args.layout,
|
|
222
231
|
title:
|
|
223
232
|
args.mediaType === "video"
|
|
224
233
|
? "Select a video asset"
|
|
@@ -191,6 +191,21 @@
|
|
|
191
191
|
}
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
+
.assets-picker-vertical .assets-library-dense-grid,
|
|
195
|
+
.assets-picker-vertical .assets-library-grid {
|
|
196
|
+
grid-template-columns: minmax(0, 1fr);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.assets-picker-vertical [role="tablist"] {
|
|
200
|
+
width: 100%;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.assets-picker-vertical [role="tab"] {
|
|
204
|
+
min-width: 0;
|
|
205
|
+
flex: 1 1 0;
|
|
206
|
+
padding-inline: 0.5rem;
|
|
207
|
+
}
|
|
208
|
+
|
|
194
209
|
@container agent-native-main (min-width: 980px) {
|
|
195
210
|
.assets-brand-kit-preview-grid {
|
|
196
211
|
grid-template-columns: minmax(0, 1fr) 284px;
|
|
@@ -73,6 +73,7 @@ function navigationFromPath(pathname: string, search = "") {
|
|
|
73
73
|
query: optionalParam(params, "q"),
|
|
74
74
|
prompt: optionalParam(params, "prompt"),
|
|
75
75
|
aspectRatio: optionalParam(params, "aspectRatio"),
|
|
76
|
+
layout: params.get("layout") === "vertical" ? "vertical" : undefined,
|
|
76
77
|
};
|
|
77
78
|
}
|
|
78
79
|
const queryLibraryId = optionalParam(params, "libraryId");
|
|
@@ -153,6 +154,9 @@ function pathFromCommand(command: any): string | null {
|
|
|
153
154
|
if (typeof command.aspectRatio === "string" && command.aspectRatio.trim()) {
|
|
154
155
|
params.set("aspectRatio", command.aspectRatio.trim());
|
|
155
156
|
}
|
|
157
|
+
if (command.layout === "vertical") {
|
|
158
|
+
params.set("layout", "vertical");
|
|
159
|
+
}
|
|
156
160
|
const query = params.toString();
|
|
157
161
|
return query ? `/library?${query}` : "/library";
|
|
158
162
|
}
|
|
@@ -129,6 +129,7 @@ const MCP_APP_CHAT_BRIDGE_QUERY_PARAM = "__an_mcp_chat_bridge";
|
|
|
129
129
|
const PICKER_INLINE_SELECT_CLASS =
|
|
130
130
|
"h-7 w-auto min-w-0 max-w-full rounded-md border-0 bg-transparent px-1.5 py-1 text-xs font-medium text-muted-foreground shadow-none ring-offset-transparent transition hover:bg-accent/50 hover:text-foreground focus:ring-0 focus:ring-offset-0 sm:px-2 [&>svg]:ms-1 [&>svg]:size-3.5 [&>svg]:opacity-60";
|
|
131
131
|
type PickerMediaType = "image" | "video";
|
|
132
|
+
type PickerLayout = "default" | "vertical";
|
|
132
133
|
|
|
133
134
|
type Asset = {
|
|
134
135
|
id: string;
|
|
@@ -193,6 +194,7 @@ type HostConfig = {
|
|
|
193
194
|
styleStrength?: StyleStrength;
|
|
194
195
|
includeLogo?: boolean;
|
|
195
196
|
callerAppId?: string;
|
|
197
|
+
layout?: PickerLayout;
|
|
196
198
|
autoGenerate?: boolean;
|
|
197
199
|
candidateRunIds?: string[];
|
|
198
200
|
};
|
|
@@ -244,6 +246,10 @@ function normalizeMediaType(value: unknown): PickerMediaType {
|
|
|
244
246
|
return value === "video" ? "video" : "image";
|
|
245
247
|
}
|
|
246
248
|
|
|
249
|
+
function normalizePickerLayout(value: unknown): PickerLayout | undefined {
|
|
250
|
+
return value === "vertical" ? "vertical" : undefined;
|
|
251
|
+
}
|
|
252
|
+
|
|
247
253
|
function normalizeBoolean(value: unknown): boolean | undefined {
|
|
248
254
|
if (typeof value === "boolean") return value;
|
|
249
255
|
if (typeof value !== "string") return undefined;
|
|
@@ -320,6 +326,7 @@ function normalizeHostConfig(value: unknown): HostConfig {
|
|
|
320
326
|
includeLogo: normalizeBoolean(record.includeLogo),
|
|
321
327
|
callerAppId:
|
|
322
328
|
typeof record.callerAppId === "string" ? record.callerAppId : undefined,
|
|
329
|
+
layout: normalizePickerLayout(record.layout),
|
|
323
330
|
candidateRunIds: normalizeCandidateRunIds(record.candidateRunIds),
|
|
324
331
|
};
|
|
325
332
|
if (Object.prototype.hasOwnProperty.call(record, "autoGenerate")) {
|
|
@@ -1999,6 +2006,7 @@ export function AssetPickerSurface() {
|
|
|
1999
2006
|
styleStrength: normalizeStyleStrength(params.get("styleStrength")),
|
|
2000
2007
|
includeLogo: normalizeBoolean(params.get("includeLogo")),
|
|
2001
2008
|
callerAppId: params.get("callerAppId") ?? undefined,
|
|
2009
|
+
layout: normalizePickerLayout(params.get("layout")),
|
|
2002
2010
|
candidateRunIds: normalizeCandidateRunIds(
|
|
2003
2011
|
params.getAll("candidateRunIds").length > 0
|
|
2004
2012
|
? params.getAll("candidateRunIds")
|
|
@@ -2024,6 +2032,9 @@ export function AssetPickerSurface() {
|
|
|
2024
2032
|
const [mediaType, setMediaType] = useState<PickerMediaType>(
|
|
2025
2033
|
() => hostConfig.mediaType ?? "image",
|
|
2026
2034
|
);
|
|
2035
|
+
const [pickerLayout, setPickerLayout] = useState<PickerLayout>(
|
|
2036
|
+
() => hostConfig.layout ?? "default",
|
|
2037
|
+
);
|
|
2027
2038
|
const [query, setQuery] = useState(() => hostConfig.query ?? "");
|
|
2028
2039
|
const [prompt, setPrompt] = useState(() => hostConfig.prompt ?? "");
|
|
2029
2040
|
const [aspectRatio, setAspectRatio] = useState<string>(
|
|
@@ -2046,6 +2057,7 @@ export function AssetPickerSurface() {
|
|
|
2046
2057
|
useEffect(() => {
|
|
2047
2058
|
setHostConfig((current) => ({ ...current, ...urlHostConfig }));
|
|
2048
2059
|
setMediaType(urlHostConfig.mediaType ?? "image");
|
|
2060
|
+
setPickerLayout(urlHostConfig.layout ?? "default");
|
|
2049
2061
|
setQuery(urlHostConfig.query ?? "");
|
|
2050
2062
|
setPrompt(urlHostConfig.prompt ?? "");
|
|
2051
2063
|
setSelectedLibraryId(urlHostConfig.libraryId ?? "");
|
|
@@ -2504,6 +2516,7 @@ export function AssetPickerSurface() {
|
|
|
2504
2516
|
const next = normalizeHostConfig(payload);
|
|
2505
2517
|
setHostConfig((current) => ({ ...current, ...next }));
|
|
2506
2518
|
if (next.mediaType !== undefined) setMediaType(next.mediaType);
|
|
2519
|
+
if (next.layout !== undefined) setPickerLayout(next.layout);
|
|
2507
2520
|
if (next.query !== undefined) setQuery(next.query);
|
|
2508
2521
|
if (next.prompt !== undefined) setPrompt(next.prompt);
|
|
2509
2522
|
if (next.libraryId !== undefined) setSelectedLibraryId(next.libraryId);
|
|
@@ -2533,10 +2546,11 @@ export function AssetPickerSurface() {
|
|
|
2533
2546
|
query,
|
|
2534
2547
|
prompt,
|
|
2535
2548
|
aspectRatio,
|
|
2549
|
+
layout: pickerLayout,
|
|
2536
2550
|
},
|
|
2537
2551
|
{ requestSource: "assets-picker-ui" },
|
|
2538
2552
|
).catch(() => {});
|
|
2539
|
-
}, [aspectRatio, mediaType, prompt, query, selectedLibraryId]);
|
|
2553
|
+
}, [aspectRatio, mediaType, pickerLayout, prompt, query, selectedLibraryId]);
|
|
2540
2554
|
|
|
2541
2555
|
const canGenerate =
|
|
2542
2556
|
mediaType === "image" &&
|
|
@@ -2652,14 +2666,22 @@ export function AssetPickerSurface() {
|
|
|
2652
2666
|
waitingForRequestedPreset,
|
|
2653
2667
|
]);
|
|
2654
2668
|
|
|
2669
|
+
const verticalLayout = pickerLayout === "vertical";
|
|
2670
|
+
|
|
2655
2671
|
return (
|
|
2656
2672
|
<div
|
|
2657
2673
|
className={cn(
|
|
2658
2674
|
"flex flex-col overflow-hidden bg-background text-foreground",
|
|
2659
2675
|
embedded ? "h-screen w-screen" : "h-full w-full",
|
|
2676
|
+
verticalLayout && "assets-picker-vertical",
|
|
2660
2677
|
)}
|
|
2661
2678
|
>
|
|
2662
|
-
<header
|
|
2679
|
+
<header
|
|
2680
|
+
className={cn(
|
|
2681
|
+
"flex shrink-0 items-center justify-between gap-3 border-b border-border",
|
|
2682
|
+
verticalLayout ? "h-10 px-2" : "h-12 px-3",
|
|
2683
|
+
)}
|
|
2684
|
+
>
|
|
2663
2685
|
<div className="min-w-0 truncate text-sm font-semibold">
|
|
2664
2686
|
{embedded ? t("navigation.brand") : t("library.library")}
|
|
2665
2687
|
</div>
|
|
@@ -2668,7 +2690,7 @@ export function AssetPickerSurface() {
|
|
|
2668
2690
|
<Button
|
|
2669
2691
|
variant={showCreatePane ? "secondary" : "default"}
|
|
2670
2692
|
size="sm"
|
|
2671
|
-
className="
|
|
2693
|
+
className={cn("gap-1.5", verticalLayout ? "h-7 px-2" : "h-8")}
|
|
2672
2694
|
onClick={() => setShowCreatePane((open) => !open)}
|
|
2673
2695
|
>
|
|
2674
2696
|
{showCreatePane ? (
|
|
@@ -2676,7 +2698,9 @@ export function AssetPickerSurface() {
|
|
|
2676
2698
|
) : (
|
|
2677
2699
|
<IconPhotoPlus className="h-3.5 w-3.5" />
|
|
2678
2700
|
)}
|
|
2679
|
-
{
|
|
2701
|
+
<span className={verticalLayout ? "sr-only" : undefined}>
|
|
2702
|
+
{showCreatePane ? t("library.close") : t("library.createPane")}
|
|
2703
|
+
</span>
|
|
2680
2704
|
</Button>
|
|
2681
2705
|
)}
|
|
2682
2706
|
{embedded && (
|
|
@@ -2705,9 +2729,14 @@ export function AssetPickerSurface() {
|
|
|
2705
2729
|
</header>
|
|
2706
2730
|
|
|
2707
2731
|
{showCreatePane && mediaType === "image" && (
|
|
2708
|
-
<section
|
|
2732
|
+
<section
|
|
2733
|
+
className={cn(
|
|
2734
|
+
"shrink-0 border-b border-border",
|
|
2735
|
+
verticalLayout ? "px-2 py-2" : "px-3 py-3",
|
|
2736
|
+
)}
|
|
2737
|
+
>
|
|
2709
2738
|
{mediaType === "image" ? (
|
|
2710
|
-
<div className="
|
|
2739
|
+
<div className="rounded-lg border border-border/80 bg-background focus-within:ring-1 focus-within:ring-ring">
|
|
2711
2740
|
<Input
|
|
2712
2741
|
type="text"
|
|
2713
2742
|
value={prompt}
|
|
@@ -2724,10 +2753,23 @@ export function AssetPickerSurface() {
|
|
|
2724
2753
|
if (canGenerate) runGenerate();
|
|
2725
2754
|
}}
|
|
2726
2755
|
placeholder={t("library.generateImagePlaceholder")}
|
|
2727
|
-
className=
|
|
2756
|
+
className={cn(
|
|
2757
|
+
"border-0 bg-transparent px-3 leading-6 shadow-none focus-visible:ring-0 focus-visible:ring-offset-0",
|
|
2758
|
+
verticalLayout ? "h-9 py-2 text-xs" : "h-11 py-2.5",
|
|
2759
|
+
)}
|
|
2728
2760
|
/>
|
|
2729
|
-
<div
|
|
2730
|
-
|
|
2761
|
+
<div
|
|
2762
|
+
className={cn(
|
|
2763
|
+
"flex gap-1 px-2 pb-2",
|
|
2764
|
+
verticalLayout ? "flex-col items-stretch" : "items-center",
|
|
2765
|
+
)}
|
|
2766
|
+
>
|
|
2767
|
+
<div
|
|
2768
|
+
className={cn(
|
|
2769
|
+
"flex min-w-0 flex-1 items-center gap-0.5 sm:gap-1",
|
|
2770
|
+
verticalLayout ? "justify-between" : "justify-end",
|
|
2771
|
+
)}
|
|
2772
|
+
>
|
|
2731
2773
|
<Select value={aspectRatio} onValueChange={setAspectRatio}>
|
|
2732
2774
|
<SelectTrigger
|
|
2733
2775
|
aria-label={t("brandKitDetail.aspectRatio")}
|
|
@@ -2792,7 +2834,10 @@ export function AssetPickerSurface() {
|
|
|
2792
2834
|
) : null}
|
|
2793
2835
|
</div>
|
|
2794
2836
|
<Button
|
|
2795
|
-
className=
|
|
2837
|
+
className={cn(
|
|
2838
|
+
"h-7 shrink-0 px-3 text-xs",
|
|
2839
|
+
!verticalLayout && "min-w-[5.75rem]",
|
|
2840
|
+
)}
|
|
2796
2841
|
disabled={!canGenerate}
|
|
2797
2842
|
onClick={runGenerate}
|
|
2798
2843
|
>
|
|
@@ -2932,12 +2977,33 @@ export function AssetPickerSurface() {
|
|
|
2932
2977
|
</section>
|
|
2933
2978
|
)}
|
|
2934
2979
|
|
|
2935
|
-
<main
|
|
2980
|
+
<main
|
|
2981
|
+
className={cn(
|
|
2982
|
+
"min-h-0 flex-1 overflow-y-auto",
|
|
2983
|
+
verticalLayout ? "p-2" : "p-3",
|
|
2984
|
+
)}
|
|
2985
|
+
>
|
|
2936
2986
|
{displayLibraries.length > 0 && (
|
|
2937
|
-
<div
|
|
2938
|
-
|
|
2987
|
+
<div
|
|
2988
|
+
className={cn(
|
|
2989
|
+
"mb-3 flex flex-col gap-2",
|
|
2990
|
+
!verticalLayout &&
|
|
2991
|
+
"sm:flex-row sm:items-center sm:justify-between",
|
|
2992
|
+
)}
|
|
2993
|
+
>
|
|
2994
|
+
<div
|
|
2995
|
+
className={cn(
|
|
2996
|
+
"flex flex-col gap-2",
|
|
2997
|
+
!verticalLayout && "sm:flex-row sm:items-center",
|
|
2998
|
+
)}
|
|
2999
|
+
>
|
|
2939
3000
|
{draftsGlobalView ? (
|
|
2940
|
-
<div
|
|
3001
|
+
<div
|
|
3002
|
+
className={cn(
|
|
3003
|
+
"flex h-9 items-center rounded-md border border-border/70 bg-background px-3 text-sm text-muted-foreground",
|
|
3004
|
+
!verticalLayout && "sm:w-48",
|
|
3005
|
+
)}
|
|
3006
|
+
>
|
|
2941
3007
|
{t("library.allLibraries")}
|
|
2942
3008
|
</div>
|
|
2943
3009
|
) : (
|
|
@@ -2945,7 +3011,12 @@ export function AssetPickerSurface() {
|
|
|
2945
3011
|
value={selectedLibraryId}
|
|
2946
3012
|
onValueChange={setSelectedLibraryId}
|
|
2947
3013
|
>
|
|
2948
|
-
<SelectTrigger
|
|
3014
|
+
<SelectTrigger
|
|
3015
|
+
className={cn(
|
|
3016
|
+
"h-9 w-full border-border/70 bg-background",
|
|
3017
|
+
!verticalLayout && "sm:w-48",
|
|
3018
|
+
)}
|
|
3019
|
+
>
|
|
2949
3020
|
<SelectValue placeholder={t("library.library")} />
|
|
2950
3021
|
</SelectTrigger>
|
|
2951
3022
|
<SelectContent>
|
|
@@ -2990,7 +3061,10 @@ export function AssetPickerSurface() {
|
|
|
2990
3061
|
onInput={(event) => setQuery(event.currentTarget.value)}
|
|
2991
3062
|
onChange={(event) => setQuery(event.target.value)}
|
|
2992
3063
|
placeholder={t("library.searchMedia", { mediaLabel })}
|
|
2993
|
-
className=
|
|
3064
|
+
className={cn(
|
|
3065
|
+
"h-9 border-border/70 bg-background",
|
|
3066
|
+
!verticalLayout && "sm:max-w-xs",
|
|
3067
|
+
)}
|
|
2994
3068
|
/>
|
|
2995
3069
|
)}
|
|
2996
3070
|
</div>
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
|
|
11
11
|
import { defineAction } from "@agent-native/core";
|
|
12
12
|
import {
|
|
13
|
-
appStateList,
|
|
14
13
|
readAppState,
|
|
15
14
|
writeAppState,
|
|
16
15
|
deleteAppState,
|
|
@@ -28,6 +27,7 @@ import {
|
|
|
28
27
|
applyFaststart,
|
|
29
28
|
hasPlayableMp4Metadata,
|
|
30
29
|
} from "../server/lib/faststart.js";
|
|
30
|
+
import { listRecordingChunkKeys } from "../server/lib/recording-upload-state.js";
|
|
31
31
|
import {
|
|
32
32
|
getCurrentOwnerEmail,
|
|
33
33
|
ownerEmailMatches,
|
|
@@ -66,17 +66,6 @@ function concatBytes(parts: Uint8Array[]): Uint8Array {
|
|
|
66
66
|
return out;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
async function listRecordingChunkKeys(
|
|
70
|
-
ownerEmail: string,
|
|
71
|
-
recordingId: string,
|
|
72
|
-
): Promise<string[]> {
|
|
73
|
-
const rows = await appStateList(
|
|
74
|
-
ownerEmail,
|
|
75
|
-
`recording-chunks-${recordingId}-`,
|
|
76
|
-
);
|
|
77
|
-
return rows.map((row) => row.key);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
69
|
function chunkIndexFromKey(key: string): number {
|
|
81
70
|
return Number(key.split("-").pop() || 0);
|
|
82
71
|
}
|
|
@@ -86,6 +86,9 @@ import { parsePlaybackSpeed } from "@/lib/playback-speed";
|
|
|
86
86
|
import { isStorageSetupFailureReason } from "@/lib/storage-failures";
|
|
87
87
|
import { cn } from "@/lib/utils";
|
|
88
88
|
|
|
89
|
+
const UPLOAD_STUCK_TIMEOUT_MS = 5 * 60 * 1000;
|
|
90
|
+
const PROCESSING_STUCK_TIMEOUT_MS = 2 * 60 * 1000;
|
|
91
|
+
|
|
89
92
|
export function meta() {
|
|
90
93
|
return [{ title: enMessages.recordingRoute.pageTitle }];
|
|
91
94
|
}
|
|
@@ -562,10 +565,8 @@ export default function RecordingPage() {
|
|
|
562
565
|
.finally(() => playerDataQ.refetch());
|
|
563
566
|
}, [recording?.id, recording?.status, transcriptStatus, role, playerDataQ]);
|
|
564
567
|
|
|
565
|
-
//
|
|
566
|
-
//
|
|
567
|
-
// Even a 10-minute recording's finalize completes in a few seconds with
|
|
568
|
-
// the SQL fallback, so anything past 30s means something is wrong.
|
|
568
|
+
// Long browser-extension clips can still be uploading chunks or assembling
|
|
569
|
+
// for more than 30s. Keep polling before surfacing a stuck-state fallback.
|
|
569
570
|
useEffect(() => {
|
|
570
571
|
if (!recording) {
|
|
571
572
|
setProcessingTimeout(false);
|
|
@@ -579,7 +580,11 @@ export default function RecordingPage() {
|
|
|
579
580
|
setProcessingTimeout(false);
|
|
580
581
|
return;
|
|
581
582
|
}
|
|
582
|
-
const
|
|
583
|
+
const timeoutMs =
|
|
584
|
+
recording.status === "processing"
|
|
585
|
+
? PROCESSING_STUCK_TIMEOUT_MS
|
|
586
|
+
: UPLOAD_STUCK_TIMEOUT_MS;
|
|
587
|
+
const handle = setTimeout(() => setProcessingTimeout(true), timeoutMs);
|
|
583
588
|
return () => clearTimeout(handle);
|
|
584
589
|
}, [recording?.status, recording?.videoUrl, recordingId]);
|
|
585
590
|
|
|
@@ -229,6 +229,8 @@ const CLIPS_SOURCE_URL =
|
|
|
229
229
|
const CLIPS_TEMPLATE_URL = "https://www.agent-native.com/templates/clips";
|
|
230
230
|
const CLIPS_AGENT_DOCS_URL =
|
|
231
231
|
"https://www.agent-native.com/docs/template-clips#agent-readable-clips";
|
|
232
|
+
const UPLOAD_STUCK_TIMEOUT_MS = 5 * 60 * 1000;
|
|
233
|
+
const PROCESSING_STUCK_TIMEOUT_MS = 2 * 60 * 1000;
|
|
232
234
|
|
|
233
235
|
type ViewerPlatform = "mac" | "windows";
|
|
234
236
|
|
|
@@ -453,17 +455,13 @@ export default function ShareRoute() {
|
|
|
453
455
|
return;
|
|
454
456
|
}
|
|
455
457
|
|
|
456
|
-
const progress = Number(recording.uploadProgress ?? 0);
|
|
457
458
|
const timeoutMs =
|
|
458
|
-
recording.status === "processing"
|
|
459
|
+
recording.status === "processing"
|
|
460
|
+
? PROCESSING_STUCK_TIMEOUT_MS
|
|
461
|
+
: UPLOAD_STUCK_TIMEOUT_MS;
|
|
459
462
|
const handle = setTimeout(() => setProcessingTimeout(true), timeoutMs);
|
|
460
463
|
return () => clearTimeout(handle);
|
|
461
|
-
}, [
|
|
462
|
-
recording?.id,
|
|
463
|
-
recording?.status,
|
|
464
|
-
recording?.videoUrl,
|
|
465
|
-
recording?.uploadProgress,
|
|
466
|
-
]);
|
|
464
|
+
}, [recording?.id, recording?.status, recording?.videoUrl]);
|
|
467
465
|
|
|
468
466
|
usePlayerShortcuts({ playerRef });
|
|
469
467
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"manifest_version": 3,
|
|
3
3
|
"name": "Agent-Native Clips",
|
|
4
4
|
"short_name": "Clips",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.7",
|
|
6
6
|
"description": "Start Clips recordings from Chrome, capture optional diagnostics, and preview Clips links on GitHub.",
|
|
7
7
|
"minimum_chrome_version": "116",
|
|
8
8
|
"action": {
|
|
@@ -261,6 +261,7 @@ const CROSS_TAB_FOLLOW: boolean = false;
|
|
|
261
261
|
// The tab the recording was launched from — the only tab activeTab lets us touch.
|
|
262
262
|
let overlayTabId: number | null = null;
|
|
263
263
|
let countdownEndsAtMs = 0;
|
|
264
|
+
let armingNativeRecordingSessionId: string | null = null;
|
|
264
265
|
|
|
265
266
|
function desiredParts(): OverlayPart[] {
|
|
266
267
|
// The on-page controls match the desktop app: a left-edge vertical pill plus
|
|
@@ -950,15 +951,7 @@ function createSession(
|
|
|
950
951
|
}
|
|
951
952
|
|
|
952
953
|
async function handlePopupStart(message: PopupStartMessage) {
|
|
953
|
-
|
|
954
|
-
if (!tab || typeof tab.id !== "number") {
|
|
955
|
-
return { ok: false, error: "No active tab is available to record." };
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
const settings = await readSettings(message.settings);
|
|
959
|
-
await storageSet(settings);
|
|
960
|
-
|
|
961
|
-
if (activeNativeRecording) {
|
|
954
|
+
if (activeNativeRecording || armingNativeRecordingSessionId) {
|
|
962
955
|
return {
|
|
963
956
|
ok: false,
|
|
964
957
|
error: "Clips is already recording. Stop the active clip first.",
|
|
@@ -966,7 +959,22 @@ async function handlePopupStart(message: PopupStartMessage) {
|
|
|
966
959
|
}
|
|
967
960
|
|
|
968
961
|
const sessionId = crypto.randomUUID();
|
|
969
|
-
|
|
962
|
+
armingNativeRecordingSessionId = sessionId;
|
|
963
|
+
try {
|
|
964
|
+
const tab = await queryActiveTab();
|
|
965
|
+
if (!tab || typeof tab.id !== "number") {
|
|
966
|
+
return { ok: false, error: "No active tab is available to record." };
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
const settings = await readSettings(message.settings);
|
|
970
|
+
await storageSet(settings);
|
|
971
|
+
|
|
972
|
+
return await armRecording({ sessionId, tab, settings });
|
|
973
|
+
} finally {
|
|
974
|
+
if (armingNativeRecordingSessionId === sessionId) {
|
|
975
|
+
armingNativeRecordingSessionId = null;
|
|
976
|
+
}
|
|
977
|
+
}
|
|
970
978
|
}
|
|
971
979
|
|
|
972
980
|
// Arm a Loom-style in-page recording: show the native picker, create the row,
|
|
@@ -1474,6 +1482,7 @@ async function handlePopupStatus() {
|
|
|
1474
1482
|
return {
|
|
1475
1483
|
ok: true,
|
|
1476
1484
|
activeRecording: activeNativeRecording,
|
|
1485
|
+
arming: Boolean(armingNativeRecordingSessionId),
|
|
1477
1486
|
};
|
|
1478
1487
|
}
|
|
1479
1488
|
|