@agent-native/core 0.102.0 → 0.102.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +15 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/client/AgentPanel.tsx +7 -0
  5. package/corpus/core/src/client/AssistantChat.tsx +7 -0
  6. package/corpus/core/src/client/agent-chat-adapter.ts +7 -1
  7. package/corpus/core/src/client/agent-page/AgentTabsPage.tsx +1 -1
  8. package/corpus/core/src/client/chat/message-components.tsx +17 -3
  9. package/corpus/core/src/client/composer/ComposerPlusMenu.tsx +96 -6
  10. package/corpus/core/src/client/composer/asset-picker-url.ts +80 -0
  11. package/corpus/core/src/client/error-format.ts +24 -0
  12. package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +8 -1
  13. package/corpus/templates/analytics/changelog/2026-07-15-fixed-the-agent-discarding-a-successful-dashboard-edit-and-r.md +6 -0
  14. package/corpus/templates/analytics/server/lib/real-data-actions.ts +30 -1
  15. package/corpus/templates/analytics/server/plugins/agent-chat.ts +15 -0
  16. package/corpus/templates/assets/app/routes/library.tsx +69 -0
  17. package/corpus/templates/assets/changelog/2026-07-15-fixed-top-level-image-picker-selections-returning-to-the-com.md +6 -0
  18. package/corpus/templates/clips/actions/disconnect-calendar.ts +57 -9
  19. package/corpus/templates/clips/actions/generate-workflow.ts +102 -59
  20. package/corpus/templates/clips/actions/get-recording-player-data.ts +64 -1
  21. package/corpus/templates/clips/actions/regenerate-summary.ts +7 -0
  22. package/corpus/templates/clips/actions/regenerate-title.ts +29 -11
  23. package/corpus/templates/clips/app/components/editor/editor-layout.tsx +22 -11
  24. package/corpus/templates/clips/app/components/editor/thumbnail-picker.tsx +87 -9
  25. package/corpus/templates/clips/app/components/editor/trim-handles.tsx +15 -0
  26. package/corpus/templates/clips/app/components/editor/waveform.tsx +21 -8
  27. package/corpus/templates/clips/app/components/library/folder-tree.tsx +52 -0
  28. package/corpus/templates/clips/app/components/player/settings-panel.tsx +86 -46
  29. package/corpus/templates/clips/app/components/player/share-dialog.tsx +43 -37
  30. package/corpus/templates/clips/app/components/player/video-player.tsx +45 -1
  31. package/corpus/templates/clips/app/i18n/ar-SA.ts +2 -0
  32. package/corpus/templates/clips/app/i18n/de-DE.ts +2 -0
  33. package/corpus/templates/clips/app/i18n/en-US.ts +2 -0
  34. package/corpus/templates/clips/app/i18n/es-ES.ts +2 -0
  35. package/corpus/templates/clips/app/i18n/fr-FR.ts +2 -0
  36. package/corpus/templates/clips/app/i18n/hi-IN.ts +2 -0
  37. package/corpus/templates/clips/app/i18n/ja-JP.ts +2 -0
  38. package/corpus/templates/clips/app/i18n/ko-KR.ts +2 -0
  39. package/corpus/templates/clips/app/i18n/pt-BR.ts +2 -0
  40. package/corpus/templates/clips/app/i18n/zh-CN.ts +2 -0
  41. package/corpus/templates/clips/app/i18n/zh-TW.ts +2 -0
  42. package/corpus/templates/clips/app/lib/timestamp-mapping.ts +14 -0
  43. package/corpus/templates/clips/app/routes/_app.library._index.tsx +1 -2
  44. package/corpus/templates/clips/app/routes/_index.tsx +1 -2
  45. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +71 -31
  46. package/corpus/templates/clips/app/routes/share.$shareId.tsx +4 -1
  47. package/corpus/templates/clips/changelog/2026-07-15-ai-workflow-generation-now-stays-visible-avoids-duplicate-re.md +6 -0
  48. package/corpus/templates/clips/changelog/2026-07-15-clip-playback-and-cta-controls-remain-interactive-through-ed.md +6 -0
  49. package/corpus/templates/clips/changelog/2026-07-15-clip-titles-no-longer-describe-the-product-as-a-loom-alterna.md +6 -0
  50. package/corpus/templates/clips/changelog/2026-07-15-description-regeneration-now-opens-the-agent-chat-so-progres.md +6 -0
  51. package/corpus/templates/clips/changelog/2026-07-15-direct-recording-urls-now-respect-share-link-and-password-ac.md +6 -0
  52. package/corpus/templates/clips/changelog/2026-07-15-disconnecting-a-calendar-now-clears-unrecorded-synced-meetin.md +6 -0
  53. package/corpus/templates/clips/changelog/2026-07-15-folders-now-expose-rename-and-delete-actions-directly-in-the.md +6 -0
  54. package/corpus/templates/clips/changelog/2026-07-15-recording-pages-now-explain-sign-in-access-and-avoid-showing.md +6 -0
  55. package/corpus/templates/clips/changelog/2026-07-15-the-clips-extension-quick-actions-toolbar-can-be-moved-out-o.md +6 -0
  56. package/corpus/templates/clips/changelog/2026-07-15-the-editor-now-skips-cut-sections-during-preview-and-keeps-t.md +6 -0
  57. package/corpus/templates/clips/changelog/2026-07-15-thumbnail-capture-now-updates-previews-while-scrubbing-and-l.md +6 -0
  58. package/corpus/templates/clips/changelog/2026-07-15-windows-permission-links-open-the-matching-settings-page.md +6 -0
  59. package/corpus/templates/clips/chrome-extension/src/content-script.ts +117 -2
  60. package/corpus/templates/clips/chrome-extension/src/overlay.ts +27 -0
  61. package/corpus/templates/clips/desktop/src-tauri/tauri.conf.json +1 -1
  62. package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +139 -101
  63. package/corpus/templates/clips/server/lib/recording-page-access.ts +35 -0
  64. package/corpus/templates/content/app/components/editor/DescriptionField.tsx +10 -2
  65. package/corpus/templates/content/changelog/2026-07-15-page-and-database-descriptions-now-use-a-clean-single-line-f.md +6 -0
  66. package/corpus/templates/design/app/components/design/design-canvas/external-preview.ts +7 -3
  67. package/corpus/templates/design/changelog/2026-07-15-prototype-print-and-download-buttons-now-work-in-preview.md +6 -0
  68. package/corpus/templates/slides/actions/extract-pdf.ts +1 -1
  69. package/corpus/templates/slides/actions/import-file.ts +4 -1
  70. package/corpus/templates/slides/app/components/editor/ImageGenPanel.tsx +1 -1
  71. package/corpus/templates/slides/app/components/editor/ImageSearchPanel.tsx +9 -12
  72. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +29 -21
  73. package/corpus/templates/slides/app/i18n/ar-SA.ts +1 -0
  74. package/corpus/templates/slides/app/i18n/de-DE.ts +1 -0
  75. package/corpus/templates/slides/app/i18n/en-US.ts +1 -0
  76. package/corpus/templates/slides/app/i18n/es-ES.ts +1 -0
  77. package/corpus/templates/slides/app/i18n/fr-FR.ts +1 -0
  78. package/corpus/templates/slides/app/i18n/hi-IN.ts +1 -0
  79. package/corpus/templates/slides/app/i18n/ja-JP.ts +1 -0
  80. package/corpus/templates/slides/app/i18n/ko-KR.ts +1 -0
  81. package/corpus/templates/slides/app/i18n/pt-BR.ts +1 -0
  82. package/corpus/templates/slides/app/i18n/zh-CN.ts +1 -0
  83. package/corpus/templates/slides/app/i18n/zh-TW.ts +1 -0
  84. package/corpus/templates/slides/changelog/2026-07-15-image-search-and-generation-controls-now-use-the-registered-.md +6 -0
  85. package/corpus/templates/slides/changelog/2026-07-15-pdf-deck-references-can-be-imported-for-slide-inspiration-ag.md +6 -0
  86. package/corpus/templates/slides/changelog/2026-07-15-stable-style-inspector-dock.md +6 -0
  87. package/dist/client/AgentPanel.d.ts.map +1 -1
  88. package/dist/client/AgentPanel.js +5 -0
  89. package/dist/client/AgentPanel.js.map +1 -1
  90. package/dist/client/AssistantChat.d.ts.map +1 -1
  91. package/dist/client/AssistantChat.js +7 -0
  92. package/dist/client/AssistantChat.js.map +1 -1
  93. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  94. package/dist/client/agent-chat-adapter.js +8 -1
  95. package/dist/client/agent-chat-adapter.js.map +1 -1
  96. package/dist/client/agent-page/AgentTabsPage.js +1 -1
  97. package/dist/client/agent-page/AgentTabsPage.js.map +1 -1
  98. package/dist/client/chat/message-components.d.ts +4 -0
  99. package/dist/client/chat/message-components.d.ts.map +1 -1
  100. package/dist/client/chat/message-components.js +10 -3
  101. package/dist/client/chat/message-components.js.map +1 -1
  102. package/dist/client/composer/ComposerPlusMenu.d.ts.map +1 -1
  103. package/dist/client/composer/ComposerPlusMenu.js +58 -6
  104. package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
  105. package/dist/client/composer/asset-picker-url.d.ts +16 -0
  106. package/dist/client/composer/asset-picker-url.d.ts.map +1 -0
  107. package/dist/client/composer/asset-picker-url.js +64 -0
  108. package/dist/client/composer/asset-picker-url.js.map +1 -0
  109. package/dist/client/error-format.d.ts.map +1 -1
  110. package/dist/client/error-format.js +17 -0
  111. package/dist/client/error-format.js.map +1 -1
  112. package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
  113. package/dist/client/resources/McpIntegrationDialog.js +6 -1
  114. package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
  115. package/dist/collab/routes.d.ts +1 -1
  116. package/dist/observability/routes.d.ts +1 -1
  117. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  118. package/package.json +1 -1
@@ -455,6 +455,8 @@ const messages = {
455
455
  retryAgentLink: "إعادة المحاولة",
456
456
  gifPreview: "معاينة GIF",
457
457
  openPlayer: "مشغل مفتوح",
458
+ chooseFile: "اختيار ملف",
459
+ remove: "إزالة",
458
460
  downloadMp4: "تحميل MP4",
459
461
  embedsNeedPublic: "التضمينات تحتاج إلى مقطع عام",
460
462
  embedPublicDescription:
@@ -468,6 +468,8 @@ const messages = {
468
468
  retryAgentLink: "Erneut versuchen",
469
469
  gifPreview: "GIF-Vorschau",
470
470
  openPlayer: "Spieler öffnen",
471
+ chooseFile: "Datei auswählen",
472
+ remove: "Entfernen",
471
473
  downloadMp4: "Laden Sie MP4 herunter",
472
474
  embedsNeedPublic: "Für Einbettungen ist ein öffentlicher Clip erforderlich",
473
475
  embedPublicDescription:
@@ -451,6 +451,8 @@ const messages = {
451
451
  retryAgentLink: "Retry",
452
452
  gifPreview: "GIF preview",
453
453
  openPlayer: "Open player",
454
+ chooseFile: "Choose file",
455
+ remove: "Remove",
454
456
  downloadMp4: "Download MP4",
455
457
  embedsNeedPublic: "Embeds need a public clip",
456
458
  embedPublicDescription:
@@ -465,6 +465,8 @@ const messages = {
465
465
  retryAgentLink: "Reintentar",
466
466
  gifPreview: "vista previa de GIF",
467
467
  openPlayer: "jugador abierto",
468
+ chooseFile: "Elige el archivo",
469
+ remove: "Eliminar",
468
470
  downloadMp4: "Descargar MP4",
469
471
  embedsNeedPublic: "Los elementos insertados necesitan un clip público",
470
472
  embedPublicDescription:
@@ -465,6 +465,8 @@ const messages = {
465
465
  retryAgentLink: "Réessayer",
466
466
  gifPreview: "aperçu de GIF",
467
467
  openPlayer: "Joueur ouvert",
468
+ chooseFile: "Choisir un fichier",
469
+ remove: "Retirer",
468
470
  downloadMp4: "Télécharger MP4",
469
471
  embedsNeedPublic: "Les intégrations nécessitent un clip public",
470
472
  embedPublicDescription:
@@ -448,6 +448,8 @@ const messages = {
448
448
  retryAgentLink: "फिर से प्रयास करें",
449
449
  gifPreview: "GIF पूर्वावलोकन",
450
450
  openPlayer: "खुला खिलाड़ी",
451
+ chooseFile: "फ़ाइल चुनें",
452
+ remove: "हटाएं",
451
453
  downloadMp4: "MP4 डाउनलोड करें",
452
454
  embedsNeedPublic: "एंबेड को एक सार्वजनिक क्लिप की आवश्यकता है",
453
455
  embedPublicDescription:
@@ -460,6 +460,8 @@ const messages = {
460
460
  retryAgentLink: "再試行",
461
461
  gifPreview: "GIF プレビュー",
462
462
  openPlayer: "プレーヤーを開く",
463
+ chooseFile: "ファイルを選択してください",
464
+ remove: "取り除く",
463
465
  downloadMp4: "ダウンロード",
464
466
  embedsNeedPublic: "埋め込みにはパブリッククリップが必要です",
465
467
  embedPublicDescription:
@@ -453,6 +453,8 @@ const messages = {
453
453
  retryAgentLink: "다시 시도",
454
454
  gifPreview: "GIF 미리보기",
455
455
  openPlayer: "플레이어 열기",
456
+ chooseFile: "파일 선택",
457
+ remove: "제거",
456
458
  downloadMp4: "MP4 다운로드",
457
459
  embedsNeedPublic: "퍼가기에는 공개 클립이 필요합니다",
458
460
  embedPublicDescription:
@@ -462,6 +462,8 @@ const messages = {
462
462
  retryAgentLink: "Tentar novamente",
463
463
  gifPreview: "visualização de GIF",
464
464
  openPlayer: "Jogador aberto",
465
+ chooseFile: "Escolher arquivo",
466
+ remove: "Remover",
465
467
  downloadMp4: "Baixar MP4",
466
468
  embedsNeedPublic: "As incorporações precisam de um clipe público",
467
469
  embedPublicDescription:
@@ -435,6 +435,8 @@ const messages = {
435
435
  retryAgentLink: "重试",
436
436
  gifPreview: "GIF 预览",
437
437
  openPlayer: "开放玩家",
438
+ chooseFile: "选择文件",
439
+ remove: "消除",
438
440
  downloadMp4: "下载MP4",
439
441
  embedsNeedPublic: "嵌入需要公共剪辑",
440
442
  embedPublicDescription:
@@ -435,6 +435,8 @@ const messages = {
435
435
  retryAgentLink: "重試",
436
436
  gifPreview: "GIF 預覽",
437
437
  openPlayer: "開啟播放器",
438
+ chooseFile: "選取檔案",
439
+ remove: "消除",
438
440
  downloadMp4: "下載 MP4",
439
441
  embedsNeedPublic: "嵌入需要公開剪輯",
440
442
  embedPublicDescription:
@@ -198,6 +198,20 @@ export function getKeptRanges(
198
198
  return out;
199
199
  }
200
200
 
201
+ /** Move a source timestamp to the first visible timestamp after a cut. */
202
+ export function skipExcludedRange(
203
+ ms: number,
204
+ excludedRanges: Pick<TrimRange, "startMs" | "endMs">[],
205
+ durationMs: number,
206
+ ): number {
207
+ const range = excludedRanges.find(
208
+ (candidate) => ms >= candidate.startMs && ms < candidate.endMs,
209
+ );
210
+ if (!range) return ms;
211
+ const next = Math.max(ms, range.endMs);
212
+ return durationMs > 0 ? Math.min(next, durationMs) : next;
213
+ }
214
+
201
215
  /**
202
216
  * Merge a new excluded range into the edits, collapsing adjacent/overlapping
203
217
  * entries. Preserves existing non-excluded (split) markers as-is.
@@ -6,8 +6,7 @@ import { NavLink } from "react-router";
6
6
  import { LibraryGrid } from "@/components/library/library-grid";
7
7
  import { usePageHeaderLayout } from "@/components/library/page-header";
8
8
 
9
- const SEO_TITLE =
10
- "Agent-Native Clips - Open Source, agent-friendly Loom alternative";
9
+ const SEO_TITLE = "Agent-Native Clips - Open Source screen recorder";
11
10
  const SEO_DESCRIPTION =
12
11
  "Open Source screen recorder and meeting-notes app with AI transcripts, summaries, search, dictation, and agent-readable share links.";
13
12
 
@@ -1,8 +1,7 @@
1
1
  import { DefaultSpinner } from "@agent-native/core/client";
2
2
  import { redirect, type LoaderFunctionArgs } from "react-router";
3
3
 
4
- const SEO_TITLE =
5
- "Agent-Native Clips - Open Source, agent-friendly Loom alternative";
4
+ const SEO_TITLE = "Agent-Native Clips - Open Source screen recorder";
6
5
  const SEO_DESCRIPTION =
7
6
  "Open Source screen recorder and meeting-notes app with AI transcripts, summaries, search, dictation, and agent-readable share links.";
8
7
 
@@ -205,6 +205,10 @@ function parseTimeParam(raw: string | null): number {
205
205
  return (hours * 3600 + minutes * 60 + seconds) * 1000;
206
206
  }
207
207
 
208
+ function buildSignInHref(returnTo: string): string {
209
+ return `${agentNativePath("/_agent-native/sign-in")}?return=${encodeURIComponent(returnTo)}`;
210
+ }
211
+
208
212
  export default function RecordingPage() {
209
213
  const t = useT();
210
214
  useAutoTitleBridge();
@@ -256,6 +260,7 @@ export default function RecordingPage() {
256
260
  );
257
261
  const lastPlayerStateWriteRef = useRef(0);
258
262
  const readyMediaPollRef = useRef<{ key: string; until: number } | null>(null);
263
+ const [metadataRefreshUntil, setMetadataRefreshUntil] = useState(0);
259
264
 
260
265
  useEffect(() => {
261
266
  if (
@@ -325,6 +330,7 @@ export default function RecordingPage() {
325
330
  // `update-recording` and we want the skeleton to swap in promptly.
326
331
  if (shouldShowGeneratedTitleSkeleton(rec, data?.transcript?.status))
327
332
  return 3000;
333
+ if (Date.now() < metadataRefreshUntil) return 2000;
328
334
  return false;
329
335
  },
330
336
  },
@@ -542,6 +548,8 @@ export default function RecordingPage() {
542
548
  });
543
549
  const regenerateTitle = useActionMutation("regenerate-title" as any, {
544
550
  onSuccess: (result: any) => {
551
+ setMetadataRefreshUntil(Date.now() + 60_000);
552
+ void playerDataQ.refetch();
545
553
  if (result?.updated) {
546
554
  toast.success(t("recordingPage.titleUpdated"));
547
555
  } else if (result?.reason === "builder_credits_paused") {
@@ -559,7 +567,11 @@ export default function RecordingPage() {
559
567
  onError: handleAiError,
560
568
  });
561
569
  const regenerateSummary = useActionMutation("regenerate-summary" as any, {
562
- onSuccess: () => toast.success(t("recordingPage.descriptionQueued")),
570
+ onSuccess: () => {
571
+ setMetadataRefreshUntil(Date.now() + 60_000);
572
+ void playerDataQ.refetch();
573
+ toast.success(t("recordingPage.descriptionQueued"));
574
+ },
563
575
  onError: handleAiError,
564
576
  });
565
577
  const regenerateChapters = useActionMutation("regenerate-chapters" as any, {
@@ -614,17 +626,22 @@ export default function RecordingPage() {
614
626
  }
615
627
  function handleGenerateWorkflow(kind: WorkflowKind) {
616
628
  if (!recording) return;
629
+ if (generatedWorkflow?.status === "generating") return;
617
630
  setEditing(false);
618
631
  setPanel("agent");
619
632
  window.dispatchEvent(
620
633
  new CustomEvent("agent-panel:set-mode", { detail: { mode: "chat" } }),
621
634
  );
635
+ window.dispatchEvent(new Event("agent-panel:open"));
622
636
  generateWorkflow.mutate({
623
637
  recordingId: recording.id,
624
638
  kind,
625
639
  } as any);
626
640
  }
627
641
 
642
+ const workflowBusy =
643
+ generateWorkflow.isPending || generatedWorkflow?.status === "generating";
644
+
628
645
  useEffect(() => {
629
646
  if (recording && panel === "settings" && !canEdit) setPanel("agent");
630
647
  }, [canEdit, panel, recording]);
@@ -709,18 +726,36 @@ export default function RecordingPage() {
709
726
  }
710
727
 
711
728
  if (playerDataQ.isError || !recording) {
729
+ const needsSignIn = !session;
730
+ const returnTo =
731
+ typeof window === "undefined"
732
+ ? `/r/${recordingId}`
733
+ : window.location.pathname + window.location.search;
712
734
  return (
713
735
  <div className="flex flex-col items-center justify-center h-screen w-full bg-background px-6">
714
736
  <h1 className="text-xl font-semibold mb-2">
715
- {t("recordingPage.recordingNotFound")}
737
+ {needsSignIn
738
+ ? t("sharePage.clipUnavailable")
739
+ : t("recordingPage.recordingNotFound")}
716
740
  </h1>
717
741
  <p className="text-sm text-muted-foreground mb-4">
718
- {(playerDataQ.error as Error | undefined)?.message ??
719
- t("recordingPage.noAccess")}
742
+ {needsSignIn
743
+ ? t("sharePage.clipUnavailableMessage")
744
+ : ((playerDataQ.error as Error | undefined)?.message ??
745
+ t("recordingPage.noAccess"))}
720
746
  </p>
721
- <Button asChild variant="outline">
722
- <Link to="/">{t("recordingPage.backToLibrary")}</Link>
723
- </Button>
747
+ <div className="flex flex-wrap items-center justify-center gap-2">
748
+ {needsSignIn ? (
749
+ <Button asChild>
750
+ <a href={buildSignInHref(returnTo)}>{t("sharePage.signIn")}</a>
751
+ </Button>
752
+ ) : null}
753
+ <Button asChild variant="outline">
754
+ <Link to="/library" replace>
755
+ {t("recordingPage.backToLibrary")}
756
+ </Link>
757
+ </Button>
758
+ </div>
724
759
  </div>
725
760
  );
726
761
  }
@@ -784,7 +819,7 @@ export default function RecordingPage() {
784
819
  className="shrink-0"
785
820
  aria-label={t("recordingPage.back")}
786
821
  >
787
- <Link to="/">
822
+ <Link to="/library" replace>
788
823
  <IconArrowLeft className="h-4 w-4 rtl:-scale-x-100" />
789
824
  </Link>
790
825
  </Button>
@@ -956,7 +991,9 @@ export default function RecordingPage() {
956
991
  : t("recordingPage.checkAgain")}
957
992
  </Button>
958
993
  <Button asChild variant="ghost" size="sm">
959
- <Link to="/">{t("recordingPage.backToLibrary")}</Link>
994
+ <Link to="/library" replace>
995
+ {t("recordingPage.backToLibrary")}
996
+ </Link>
960
997
  </Button>
961
998
  </div>
962
999
  </div>
@@ -1136,7 +1173,7 @@ export default function RecordingPage() {
1136
1173
  className="shrink-0"
1137
1174
  aria-label={t("recordingPage.back")}
1138
1175
  >
1139
- <Link to="/">
1176
+ <Link to="/library" replace>
1140
1177
  <IconArrowLeft className="h-4 w-4 rtl:-scale-x-100" />
1141
1178
  </Link>
1142
1179
  </Button>
@@ -1174,7 +1211,7 @@ export default function RecordingPage() {
1174
1211
  </Button>
1175
1212
  ) : null}
1176
1213
 
1177
- {canEdit ? (
1214
+ {canEdit && !editing ? (
1178
1215
  <DropdownMenu>
1179
1216
  <DropdownMenuTrigger asChild>
1180
1217
  <Button
@@ -1221,6 +1258,7 @@ export default function RecordingPage() {
1221
1258
  onSelect={() =>
1222
1259
  regenerateSummary.mutate({
1223
1260
  recordingId: recording.id,
1261
+ openInChat: true,
1224
1262
  } as any)
1225
1263
  }
1226
1264
  >
@@ -1264,7 +1302,7 @@ export default function RecordingPage() {
1264
1302
  const menuItem = (
1265
1303
  <DropdownMenuItem
1266
1304
  key={item.kind}
1267
- disabled={generateWorkflow.isPending}
1305
+ disabled={workflowBusy}
1268
1306
  onSelect={() => handleGenerateWorkflow(item.kind)}
1269
1307
  className={
1270
1308
  item.tooltipKey ? "justify-between gap-3" : undefined
@@ -1319,24 +1357,26 @@ export default function RecordingPage() {
1319
1357
  </DropdownMenu>
1320
1358
  ) : null}
1321
1359
 
1322
- <ShareRecordingPopover
1323
- recordingId={recording.id}
1324
- recordingTitle={recording.title}
1325
- initialVisibility={recording.visibility}
1326
- initialRole={role}
1327
- videoUrl={recording.videoUrl}
1328
- animatedThumbnailUrl={recording.animatedThumbnailUrl}
1329
- isLoomRecording={isLoomEmbedBacked}
1330
- hasPassword={Boolean(recording.hasPassword)}
1331
- >
1332
- <Button
1333
- className="shrink-0 gap-1.5 bg-primary text-primary-foreground hover:bg-primary/90"
1334
- size="sm"
1360
+ {!editing ? (
1361
+ <ShareRecordingPopover
1362
+ recordingId={recording.id}
1363
+ recordingTitle={recording.title}
1364
+ initialVisibility={recording.visibility}
1365
+ initialRole={role}
1366
+ videoUrl={recording.videoUrl}
1367
+ animatedThumbnailUrl={recording.animatedThumbnailUrl}
1368
+ isLoomRecording={isLoomEmbedBacked}
1369
+ hasPassword={Boolean(recording.hasPassword)}
1335
1370
  >
1336
- <IconShare3 className="h-4 w-4" />
1337
- {t("recordingPage.share")}
1338
- </Button>
1339
- </ShareRecordingPopover>
1371
+ <Button
1372
+ className="shrink-0 gap-1.5 bg-primary text-primary-foreground hover:bg-primary/90"
1373
+ size="sm"
1374
+ >
1375
+ <IconShare3 className="h-4 w-4" />
1376
+ {t("recordingPage.share")}
1377
+ </Button>
1378
+ </ShareRecordingPopover>
1379
+ ) : null}
1340
1380
 
1341
1381
  {canDelete || canDownloadRecording ? (
1342
1382
  <RecordingOptionsMenu
@@ -1486,7 +1526,7 @@ export default function RecordingPage() {
1486
1526
  ) : null}
1487
1527
  </div>
1488
1528
  {recording.description ? (
1489
- <p className="mt-3 line-clamp-2 text-sm text-muted-foreground">
1529
+ <p className="mt-3 whitespace-pre-wrap break-words text-sm text-muted-foreground">
1490
1530
  {recording.description}
1491
1531
  </p>
1492
1532
  ) : null}
@@ -1528,7 +1568,7 @@ function GeneratedWorkflowNotice({
1528
1568
  const status = workflow.status ?? (workflow.content ? "ready" : "generating");
1529
1569
  const content =
1530
1570
  typeof workflow.content === "string" ? workflow.content.trim() : "";
1531
- const isReady = status === "ready" && content.length > 0;
1571
+ const isReady = status !== "failed" && content.length > 0;
1532
1572
  const isFailed = status === "failed";
1533
1573
  const title = workflowTitle(workflow.kind);
1534
1574
 
@@ -855,6 +855,8 @@ export default function ShareRoute() {
855
855
  <Button variant="ghost" size="sm" asChild>
856
856
  <a
857
857
  href={appPath("/")}
858
+ target="_blank"
859
+ rel="noopener noreferrer"
858
860
  className="gap-1.5"
859
861
  onClick={() => fireShareCtaClick("try_clips")}
860
862
  >
@@ -965,7 +967,7 @@ export default function ShareRoute() {
965
967
  </h2>
966
968
  )}
967
969
  {recording.description ? (
968
- <p className="text-sm text-muted-foreground line-clamp-2">
970
+ <p className="whitespace-pre-wrap break-words text-sm text-muted-foreground">
969
971
  {recording.description}
970
972
  </p>
971
973
  ) : null}
@@ -1063,6 +1065,7 @@ export default function ShareRoute() {
1063
1065
  t("recordingPage.draftQuestions"),
1064
1066
  ]}
1065
1067
  browserTabId={getBrowserTabId()}
1068
+ showHeader={false}
1066
1069
  />
1067
1070
  ) : (
1068
1071
  <PublicAgentEmptyState
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-15
4
+ ---
5
+
6
+ AI workflow generation now stays visible, avoids duplicate requests, and reports completion correctly.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-15
4
+ ---
5
+
6
+ Clip playback and CTA controls remain interactive through editing and replay.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-15
4
+ ---
5
+
6
+ Clip titles no longer describe the product as a Loom alternative.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-15
4
+ ---
5
+
6
+ Description regeneration now opens the agent chat so progress is easy to follow.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: security
3
+ date: 2026-07-15
4
+ ---
5
+
6
+ Direct recording URLs now respect share-link and password access controls
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-15
4
+ ---
5
+
6
+ Disconnecting a calendar now clears unrecorded synced meeting placeholders.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-15
4
+ ---
5
+
6
+ Folders now expose rename and delete actions directly in the library sidebar
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-15
4
+ ---
5
+
6
+ Recording pages now explain sign-in access and avoid showing the same public link twice.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-15
4
+ ---
5
+
6
+ The Clips extension quick-actions toolbar can be moved out of the way.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-15
4
+ ---
5
+
6
+ The editor now skips cut sections during preview and keeps the full clip selection visible.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-15
4
+ ---
5
+
6
+ Thumbnail capture now updates previews while scrubbing and lets uploaded files be removed.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-15
4
+ ---
5
+
6
+ Windows permission links now open the matching system settings page.