@agent-native/core-corpus 0.203.1 → 0.204.0-nightly-20261008011018

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 (92) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/app/pages/sessions/session-replay-screenshot.ts +107 -12
  3. package/corpus/templates/analytics/changelog/2026-10-07-session-replay-screenshot-export-captures-readable-video-fra.md +6 -0
  4. package/corpus/templates/clips/app/i18n/en-US.ts +1 -1
  5. package/corpus/templates/clips/changelog/2026-10-07-builder-io-setup-choices-now-say-use-builder-io.md +6 -0
  6. package/corpus/templates/clips/changelog/2026-10-07-clips-keeps-settings-at-its-full-size-while-a-recording-is-a.md +6 -0
  7. package/corpus/templates/clips/desktop/src/app.tsx +17 -10
  8. package/corpus/templates/clips/desktop/src/lib/popover-sizing.ts +17 -0
  9. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +0 -3
  10. package/corpus/templates/content/app/components/editor/DocumentBlockFields.tsx +13 -6
  11. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +281 -178
  12. package/corpus/templates/content/app/components/editor/DocumentEditorSkeleton.tsx +15 -2
  13. package/corpus/templates/content/app/components/editor/PageDraftRecovery.tsx +16 -4
  14. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +16 -1
  15. package/corpus/templates/content/app/components/editor/WidgetLoadDiagnostic.tsx +103 -0
  16. package/corpus/templates/content/app/hooks/use-content-spaces.ts +4 -3
  17. package/corpus/templates/content/app/hooks/use-document-properties.ts +5 -2
  18. package/corpus/templates/content/app/hooks/use-documents.ts +3 -0
  19. package/corpus/templates/content/app/i18n-data.ts +8 -0
  20. package/corpus/templates/content/changelog/2026-10-07-chatgpt-widgets-identify-a-stalled-content-editor-instead-of.md +6 -0
  21. package/corpus/templates/content/changelog/2026-10-07-chatgpt-widgets-open-document-content-without-a-cookie-sessi.md +6 -0
  22. package/corpus/templates/content/changelog/2026-10-07-content-documents-now-open-in-chatgpt-widgets-with-their-ful.md +6 -0
  23. package/corpus/templates/content/changelog/2026-10-07-text-two-people-type-at-the-same-spot-now-reaches-the-saved-.md +6 -0
  24. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +24 -6
  25. package/corpus/templates/design/CHANGELOG.md +1 -0
  26. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +26 -3
  27. package/corpus/templates/design/app/pages/design-editor/editor-helpers.ts +40 -11
  28. package/corpus/templates/design/app/pages/design-editor/position-coordinate-context.ts +21 -8
  29. package/corpus/templates/design/changelog/2026-10-07-canvas-layers-now-stay-positioned-and-selected-correctly-whe.md +6 -0
  30. package/corpus/templates/design/changelog/2026-10-07-design-waitlist-signups-work-from-make-real-and-design-systems.md +6 -0
  31. package/corpus/templates/design/changelog/2026-10-07-fixed-position-readouts-inside-transformed-containers-and-ke.md +6 -0
  32. package/corpus/templates/design/e2e/helpers.ts +5 -3
  33. package/corpus/templates/design/vite.config.ts +50 -0
  34. package/corpus/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +59 -70
  35. package/corpus/templates/factory/.agents/skills/review-latest-feedback/references/reproduction-and-verification.md +46 -0
  36. package/corpus/templates/factory/.agents/skills/review-latest-feedback/references/slack-reaction-replies.md +33 -0
  37. package/corpus/templates/factory/.agents/skills/review-prs/SKILL.md +5 -3
  38. package/corpus/templates/plan/actions/seed-plan-collab.ts +4 -3
  39. package/corpus/templates/plan/app/components/plan/PlanContentRenderer.tsx +8 -14
  40. package/corpus/templates/plan/app/components/plan/PlanMarkdownEditor.tsx +56 -0
  41. package/corpus/templates/plan/shared/plan-autosave-retry.ts +20 -0
  42. package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +24 -0
  43. package/corpus/templates/slides/AGENTS.md +1 -1
  44. package/corpus/templates/slides/actions/add-slide.ts +10 -0
  45. package/corpus/templates/slides/actions/create-deck.ts +16 -4
  46. package/corpus/templates/slides/actions/export-html.ts +29 -16
  47. package/corpus/templates/slides/actions/update-slide.ts +4 -0
  48. package/corpus/templates/slides/actions/view-screen.ts +8 -0
  49. package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +18 -2
  50. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +20 -2
  51. package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +56 -0
  52. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +69 -14
  53. package/corpus/templates/slides/app/components/editor/SlidesLayersPanel.tsx +4 -0
  54. package/corpus/templates/slides/app/components/editor/bullet-editing.ts +1 -1
  55. package/corpus/templates/slides/app/components/editor/in-place-text-session.ts +226 -11
  56. package/corpus/templates/slides/app/components/editor/rich-text-selection.ts +32 -21
  57. package/corpus/templates/slides/app/components/presentation/PresentationView.tsx +10 -1
  58. package/corpus/templates/slides/app/components/presentation/PresenterView.tsx +2 -0
  59. package/corpus/templates/slides/app/components/visual-editor/SaveStatusIndicator.tsx +20 -7
  60. package/corpus/templates/slides/app/context/DeckContext.tsx +84 -2
  61. package/corpus/templates/slides/app/hooks/use-deck-access-reload.ts +70 -0
  62. package/corpus/templates/slides/app/i18n/en-US.ts +13 -0
  63. package/corpus/templates/slides/app/lib/create-deck-generation.ts +1 -0
  64. package/corpus/templates/slides/app/lib/deck-access-lost.ts +4 -0
  65. package/corpus/templates/slides/app/lib/generation-lifecycle.ts +24 -0
  66. package/corpus/templates/slides/app/lib/sanitize-slide-html.ts +229 -62
  67. package/corpus/templates/slides/app/lib/slide-image-replacement.ts +30 -0
  68. package/corpus/templates/slides/app/lib/slide-source-map.ts +13 -1
  69. package/corpus/templates/slides/app/lib/slide-video.ts +163 -0
  70. package/corpus/templates/slides/app/lib/video-upload.ts +40 -0
  71. package/corpus/templates/slides/app/pages/DeckEditor.tsx +124 -70
  72. package/corpus/templates/slides/app/pages/Index.tsx +9 -0
  73. package/corpus/templates/slides/changelog/2026-10-02-opening-a-deck-you-no-longer-have-access-to-no-longer-floods.md +6 -0
  74. package/corpus/templates/slides/changelog/2026-10-06-deleting-between-slide-paragraphs-now-preserves-inline-forma.md +6 -0
  75. package/corpus/templates/slides/changelog/2026-10-07-a-deck-whose-access-is-revoked-while-it-is-open-now-says-acc.md +6 -0
  76. package/corpus/templates/slides/changelog/2026-10-07-forward-delete-keeps-the-caret-on-the-correct-line-when-join.md +6 -0
  77. package/corpus/templates/slides/changelog/2026-10-07-long-slide-text-editing-sessions-can-be-undone-without-losin.md +6 -0
  78. package/corpus/templates/slides/changelog/2026-10-07-markdown-divider-shortcuts-and-autocorrect-replacements-rema.md +6 -0
  79. package/corpus/templates/slides/changelog/2026-10-07-pasted-images-stay-inside-their-crop-frame-while-uploads-fin.md +6 -0
  80. package/corpus/templates/slides/changelog/2026-10-07-right-click-slide-images-to-open-the-custom-menu-with-arrang.md +6 -0
  81. package/corpus/templates/slides/changelog/2026-10-07-svgs-exported-with-a-standard-svg-1-1-declaration-now-upload.md +6 -0
  82. package/corpus/templates/slides/changelog/2026-10-07-underline-styling-stays-consistent-when-formatting-nested-sl.md +6 -0
  83. package/corpus/templates/slides/changelog/2026-10-07-videos-can-be-added-to-slides-and-played-on-click-or-automat.md +6 -0
  84. package/corpus/templates/slides/scripts/edit-fidelity/README.md +8 -0
  85. package/corpus/templates/slides/scripts/edit-fidelity/authoring-fuzz.ts +556 -54
  86. package/corpus/templates/slides/scripts/edit-fidelity/run.ts +281 -14
  87. package/corpus/templates/slides/server/handlers/assets.ts +1356 -8
  88. package/corpus/templates/slides/server/handlers/uploads.ts +13 -7
  89. package/corpus/templates/slides/server/lib/generation-completion.ts +13 -1
  90. package/corpus/templates/slides/server/routes/api/assets/upload-video.post.ts +1 -0
  91. package/corpus/templates/slides/shared/generation-timing.ts +19 -0
  92. package/package.json +1 -1
package/corpus/README.md CHANGED
@@ -32,4 +32,4 @@ rg -n "defineAction|useActionQuery" node_modules/@agent-native/core-corpus/corpu
32
32
 
33
33
  ## Generated Counts
34
34
 
35
- - template files: 11341
35
+ - template files: 11374
@@ -16,6 +16,7 @@ const MAX_IMAGE_RESPONSE_BYTES = 12_000_000;
16
16
  const MAX_SCREENSHOT_DIMENSION = 8_192;
17
17
  const MAX_SCREENSHOT_PIXELS = 16_000_000;
18
18
  const MAX_REPLAY_IFRAME_DEPTH = 8;
19
+ const VIDEO_READY_STATE_HAVE_CURRENT_DATA = 2;
19
20
  const REPLAY_SCREENSHOT_MARKER = "data-replay-screenshot-map";
20
21
 
21
22
  type ReplayImageResource = { document: Document; url: string };
@@ -567,8 +568,12 @@ function imageResourcesInDocuments(
567
568
  (element): element is HTMLVideoElement => element.tagName === "VIDEO",
568
569
  )) {
569
570
  if (!isElementRendered(video, current)) continue;
570
- if (
571
- video.poster ||
571
+ if (video.controls) throw new ReplayScreenshotAssetError();
572
+ if (hasCurrentVideoFrame(video)) {
573
+ assertVideoFrameReadable(video);
574
+ } else if (video.poster) {
575
+ addUrl(video.poster, current.baseURI, current);
576
+ } else if (
572
577
  video.currentSrc ||
573
578
  video.hasAttribute("src") ||
574
579
  video.srcObject ||
@@ -631,6 +636,68 @@ function imageResourcesInDocuments(
631
636
  );
632
637
  }
633
638
 
639
+ function hasCurrentVideoFrame(video: HTMLVideoElement): boolean {
640
+ return (
641
+ video.readyState >= VIDEO_READY_STATE_HAVE_CURRENT_DATA &&
642
+ video.videoWidth > 0 &&
643
+ video.videoHeight > 0
644
+ );
645
+ }
646
+
647
+ function assertVideoFrameReadable(video: HTMLVideoElement): void {
648
+ const probe = video.ownerDocument.createElement("canvas");
649
+ probe.width = 1;
650
+ probe.height = 1;
651
+ const context = probe.getContext("2d");
652
+ if (!context) throw new ReplayScreenshotAssetError();
653
+ try {
654
+ context.drawImage(video, 0, 0, 1, 1);
655
+ context.getImageData(0, 0, 1, 1);
656
+ } catch {
657
+ throw new ReplayScreenshotAssetError();
658
+ }
659
+ }
660
+
661
+ function copyComputedStyles(
662
+ source: Element,
663
+ target: HTMLElement,
664
+ view: Window,
665
+ ): void {
666
+ const styles = view.getComputedStyle(source);
667
+ for (let index = 0; index < styles.length; index += 1) {
668
+ const property = styles.item(index);
669
+ target.style.setProperty(
670
+ property,
671
+ styles.getPropertyValue(property),
672
+ styles.getPropertyPriority(property),
673
+ );
674
+ }
675
+ }
676
+
677
+ function html2CanvasVideoClone(
678
+ video: HTMLVideoElement,
679
+ clonesByMarker: Map<string, Element>,
680
+ ): Element | undefined {
681
+ const parent = video.parentElement;
682
+ const parentMarker = parent?.getAttribute(REPLAY_SCREENSHOT_MARKER);
683
+ const clonedParent = parentMarker ? clonesByMarker.get(parentMarker) : null;
684
+ if (!parent || !clonedParent) return undefined;
685
+
686
+ const originalChildren = Array.from(parent.children).filter(
687
+ (element) => element.tagName !== "SCRIPT",
688
+ );
689
+ const videoIndex = originalChildren.indexOf(video);
690
+ if (videoIndex === -1) return undefined;
691
+
692
+ const clonedChildren = Array.from(clonedParent.children).filter(
693
+ (element) =>
694
+ element.tagName !== "SCRIPT" &&
695
+ element.localName !== "html2canvaspseudoelement",
696
+ );
697
+ const clone = clonedChildren[videoIndex];
698
+ return clone?.tagName === "CANVAS" ? clone : undefined;
699
+ }
700
+
634
701
  function imageUrlsInDocuments(documents: Document[]): string[] {
635
702
  return [
636
703
  ...new Set(imageResourcesInDocuments(documents).map(({ url }) => url)),
@@ -859,6 +926,17 @@ export function inlineReplayAssets(
859
926
  }
860
927
  }
861
928
 
929
+ for (const originalElement of originalElements) {
930
+ if (originalElement.tagName !== "VIDEO") continue;
931
+ const marker = originalElement.getAttribute(REPLAY_SCREENSHOT_MARKER);
932
+ if (!marker || clonesByMarker.has(marker)) continue;
933
+ const clone = html2CanvasVideoClone(
934
+ originalElement as HTMLVideoElement,
935
+ clonesByMarker,
936
+ );
937
+ if (clone) clonesByMarker.set(marker, clone);
938
+ }
939
+
862
940
  for (const [documentIndex, original] of originalDocuments.entries()) {
863
941
  const rootMarker = original.documentElement.getAttribute(
864
942
  REPLAY_SCREENSHOT_MARKER,
@@ -878,9 +956,13 @@ export function inlineReplayAssets(
878
956
  if (originalElement.tagName === "SCRIPT") continue;
879
957
  const marker = originalElement.getAttribute(REPLAY_SCREENSHOT_MARKER);
880
958
  let clonedElement = marker ? clonesByMarker.get(marker) : undefined;
959
+ const isHtml2CanvasVideoClone =
960
+ originalElement.tagName === "VIDEO" &&
961
+ clonedElement?.tagName === "CANVAS";
881
962
  if (
882
963
  !clonedElement ||
883
- (originalElement.tagName !== clonedElement.tagName &&
964
+ (!isHtml2CanvasVideoClone &&
965
+ originalElement.tagName !== clonedElement.tagName &&
884
966
  !originalElement.localName.includes("-"))
885
967
  ) {
886
968
  throw new ReplayScreenshotAssetError();
@@ -894,21 +976,34 @@ export function inlineReplayAssets(
894
976
  const image = cloned.createElement("img");
895
977
  image.alt = "";
896
978
  image.src = screenshot;
897
- const frameStyles = view.getComputedStyle(originalElement);
898
- for (let index = 0; index < frameStyles.length; index += 1) {
899
- const property = frameStyles.item(index);
900
- image.style.setProperty(
901
- property,
902
- frameStyles.getPropertyValue(property),
903
- frameStyles.getPropertyPriority(property),
904
- );
905
- }
979
+ copyComputedStyles(originalElement, image, view);
906
980
  image.style.setProperty("object-fit", "fill", "important");
907
981
  clonedElement.replaceWith(image);
908
982
  clonedElement = image;
909
983
  if (marker) clonesByMarker.set(marker, image);
910
984
  }
911
985
  }
986
+ if (originalElement.tagName === "VIDEO") {
987
+ const video = originalElement as HTMLVideoElement;
988
+ if (!hasCurrentVideoFrame(video) && video.poster) {
989
+ const posterUrl = new URL(video.poster, original.baseURI).href;
990
+ const poster = documentAssets.get(posterUrl);
991
+ if (!poster) throw new ReplayScreenshotAssetError();
992
+ const image = cloned.createElement("img");
993
+ image.alt = "";
994
+ image.src = poster;
995
+ const videoStyles = view.getComputedStyle(video);
996
+ copyComputedStyles(video, image, view);
997
+ image.style.setProperty(
998
+ "object-fit",
999
+ videoStyles.objectFit || "contain",
1000
+ "important",
1001
+ );
1002
+ clonedElement.replaceWith(image);
1003
+ clonedElement = image;
1004
+ if (marker) clonesByMarker.set(marker, image);
1005
+ }
1006
+ }
912
1007
  if (originalElement instanceof view.HTMLImageElement) {
913
1008
  const source = originalElement.currentSrc || originalElement.src;
914
1009
  const dataUrl = documentAssets.get(source);
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-10-07
4
+ ---
5
+
6
+ Session replay screenshot export captures readable video frames and safe poster images.
@@ -1395,7 +1395,7 @@ const messages = {
1395
1395
  waitingForBuilder: "Waiting for Builder...",
1396
1396
  description:
1397
1397
  "Store recorded videos with Builder.io or S3-compatible storage. Builder.io includes free hosting and AI credits.",
1398
- createBuilderAccount: "Create Builder.io account",
1398
+ createBuilderAccount: "Use Builder.io",
1399
1399
  signInWithBuilderAccount: "Sign in with Builder.io account",
1400
1400
  free: "Free",
1401
1401
  whyPrompt: "Why am I seeing this?",
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-10-07
4
+ ---
5
+
6
+ Builder.io setup choices now say “Use Builder.io”.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-10-07
4
+ ---
5
+
6
+ Clips sizes Settings and recording views correctly while a recording is active.
@@ -137,6 +137,7 @@ import {
137
137
  MACOS_UPDATE_RESTART_MESSAGE,
138
138
  } from "./lib/permissions";
139
139
  import { isMacPlatform, isWindowsPlatform } from "./lib/platform";
140
+ import { getPopoverAutoSizeOptions } from "./lib/popover-sizing";
140
141
  import {
141
142
  changeRecordFirstFiles,
142
143
  effectiveLocalRecordingMode,
@@ -939,7 +940,10 @@ function measurePopoverHeight(el: HTMLElement): number {
939
940
 
940
941
  function usePopoverAutoSize(
941
942
  ref: RefObject<HTMLElement | null>,
942
- options: { disabled: boolean; width: number },
943
+ options: {
944
+ disabled: boolean;
945
+ width: number;
946
+ },
943
947
  ): void {
944
948
  const { disabled, width } = options;
945
949
 
@@ -2928,15 +2932,18 @@ export function App({
2928
2932
  setPopoverView,
2929
2933
  appRef,
2930
2934
  );
2931
- usePopoverAutoSize(appRef, {
2932
- disabled:
2933
- (popoverView !== "settings" && !popoverVisible) ||
2934
- isRecording ||
2935
- recordingFlowActive ||
2936
- recordingStartPending,
2937
- width:
2938
- popoverView === "settings" ? 720 : popoverView === "memory" ? 440 : 320,
2939
- });
2935
+ const popoverLayoutView =
2936
+ popoverView === "settings"
2937
+ ? "settings"
2938
+ : popoverView === "memory"
2939
+ ? "memory"
2940
+ : "recorder";
2941
+ const popoverAutoSizeOptions = getPopoverAutoSizeOptions(
2942
+ popoverLayoutView,
2943
+ popoverVisible,
2944
+ recordingStartPending,
2945
+ );
2946
+ usePopoverAutoSize(appRef, popoverAutoSizeOptions);
2940
2947
 
2941
2948
  const loadPendingUploads = useCallback(async () => {
2942
2949
  const sequence = ++recoveryLookupSequence.current;
@@ -0,0 +1,17 @@
1
+ export type PopoverAutoSizeView = "recorder" | "memory" | "settings";
2
+
3
+ export function getPopoverAutoSizeOptions(
4
+ view: PopoverAutoSizeView,
5
+ popoverVisible: boolean,
6
+ recordingStartPending: boolean,
7
+ ): {
8
+ disabled: boolean;
9
+ width: number;
10
+ } {
11
+ const isSettings = view === "settings";
12
+
13
+ return {
14
+ disabled: !isSettings && (!popoverVisible || recordingStartPending),
15
+ width: isSettings ? 720 : view === "memory" ? 440 : 320,
16
+ };
17
+ }
@@ -1458,9 +1458,6 @@ pub async fn resize_popover(app: AppHandle, height: f64, width: Option<f64>) ->
1458
1458
  if voice_woken {
1459
1459
  return Ok(());
1460
1460
  }
1461
- if is_recording_active(&app) {
1462
- return Ok(());
1463
- }
1464
1461
  if let Some(w) = app.get_webview_window("popover") {
1465
1462
  let tray_center = app
1466
1463
  .try_state::<TrayAnchor>()
@@ -51,6 +51,7 @@ interface DocumentBlockFieldsProps {
51
51
  databaseId: string | null;
52
52
  databaseDocumentId: string | null;
53
53
  canEdit: boolean;
54
+ usePagePropertiesOnly?: boolean;
54
55
  suggesting?: boolean;
55
56
  enteringSuggestion?: boolean;
56
57
  onPrimaryFieldAvailabilityChange?: (
@@ -276,6 +277,7 @@ export function DocumentBlockFields({
276
277
  databaseId,
277
278
  databaseDocumentId,
278
279
  canEdit,
280
+ usePagePropertiesOnly = false,
279
281
  suggesting = false,
280
282
  enteringSuggestion = false,
281
283
  onPrimaryFieldAvailabilityChange,
@@ -288,21 +290,26 @@ export function DocumentBlockFields({
288
290
  () => documentPropertiesPlaceholder(documentId, databaseId, pageProperties),
289
291
  [databaseId, documentId, pageProperties],
290
292
  );
291
- const query = useDocumentProperties(documentId, databaseId, { placeholder });
293
+ const query = useDocumentProperties(documentId, databaseId, {
294
+ enabled: !usePagePropertiesOnly,
295
+ placeholder,
296
+ });
297
+ const propertiesData = usePagePropertiesOnly ? placeholder : query.data;
298
+ const hasQueryError = !usePagePropertiesOnly && query.isError;
292
299
  const canEditFields =
293
300
  canEdit &&
294
- query.data?.canEditValues === true &&
301
+ propertiesData?.canEditValues === true &&
295
302
  databaseId !== null &&
296
303
  databaseDocumentId !== null;
297
- const properties = query.data?.properties ?? [];
304
+ const properties = propertiesData?.properties ?? [];
298
305
  const blockFields = useMemo(
299
306
  () => blockFieldsFromProperties(properties),
300
307
  [properties],
301
308
  );
302
309
 
303
- const loaded = isLoadedForDocument(documentId, databaseId, query.data);
310
+ const loaded = isLoadedForDocument(documentId, databaseId, propertiesData);
304
311
  const state = blockFieldsRenderState({ loaded, blockFields });
305
- const primaryAvailable = !query.isError && primaryBlocksFieldAvailable(state);
312
+ const primaryAvailable = !hasQueryError && primaryBlocksFieldAvailable(state);
306
313
  const scope = `${documentId}:${databaseId ?? ""}:${databaseDocumentId ?? ""}`;
307
314
  useLayoutEffect(() => {
308
315
  onPrimaryFieldAvailabilityChange?.(scope, primaryAvailable);
@@ -310,7 +317,7 @@ export function DocumentBlockFields({
310
317
 
311
318
  // A failed property read is not an empty field list. Rendering the editor in
312
319
  // that state could bind the body before we know which storage target owns it.
313
- if (query.isError) {
320
+ if (hasQueryError) {
314
321
  return (
315
322
  <div
316
323
  className={cn(BLOCK_FIELDS_GRID, "gap-1")}