@agent-native/core 0.80.9 → 0.80.11

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 (148) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +13 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/agent/production-agent.ts +108 -15
  5. package/corpus/core/src/cli/design-connect.ts +28 -2
  6. package/corpus/core/src/cli/skills.ts +45 -24
  7. package/corpus/core/src/client/AssistantChat.tsx +123 -26
  8. package/corpus/core/src/client/sse-event-processor.ts +9 -0
  9. package/corpus/templates/assets/.agents/skills/image-generation/SKILL.md +9 -2
  10. package/corpus/templates/assets/AGENTS.md +4 -0
  11. package/corpus/templates/assets/actions/_tool-activity.ts +46 -0
  12. package/corpus/templates/assets/actions/generate-image-batch.ts +26 -5
  13. package/corpus/templates/assets/actions/generate-image.ts +118 -67
  14. package/corpus/templates/assets/actions/list-draft-assets.ts +50 -0
  15. package/corpus/templates/assets/actions/rerun-generation-run.ts +52 -31
  16. package/corpus/templates/assets/app/components/create/RecentDraftsSection.tsx +100 -0
  17. package/corpus/templates/assets/app/i18n/zh-TW.ts +7 -0
  18. package/corpus/templates/assets/app/i18n-data.ts +61 -0
  19. package/corpus/templates/assets/app/routes/_index.tsx +4 -0
  20. package/corpus/templates/assets/app/routes/library.tsx +145 -38
  21. package/corpus/templates/assets/changelog/2026-06-29-image-generation-can-now-render-requested-text-and-respect-b.md +6 -0
  22. package/corpus/templates/assets/changelog/2026-06-30-image-generation-no-longer-looks-stuck-while-the-provider-is-still-working.md +6 -0
  23. package/corpus/templates/assets/changelog/2026-06-30-tagged-presets-now-control-the-image-aspect-ratio.md +6 -0
  24. package/corpus/templates/assets/server/lib/generation.ts +135 -11
  25. package/corpus/templates/assets/shared/api.ts +4 -0
  26. package/corpus/templates/clips/actions/list-ai-requests.ts +60 -0
  27. package/corpus/templates/clips/app/hooks/use-auto-title.ts +24 -25
  28. package/corpus/templates/design/DESIGN-STUDIO-PLAN.md +717 -0
  29. package/corpus/templates/design/actions/add-breakpoint.ts +143 -0
  30. package/corpus/templates/design/actions/add-localhost-screens.ts +5 -0
  31. package/corpus/templates/design/actions/apply-a11y-fix.ts +317 -0
  32. package/corpus/templates/design/actions/apply-component-prop-edit.ts +441 -0
  33. package/corpus/templates/design/actions/apply-design-state.ts +213 -0
  34. package/corpus/templates/design/actions/apply-design-token-edit.ts +202 -0
  35. package/corpus/templates/design/actions/apply-motion-edit.ts +413 -0
  36. package/corpus/templates/design/actions/apply-shader-fill.ts +404 -0
  37. package/corpus/templates/design/actions/apply-visual-edit.ts +191 -5
  38. package/corpus/templates/design/actions/capture-design-state.ts +224 -0
  39. package/corpus/templates/design/actions/connect-builder-app.ts +162 -0
  40. package/corpus/templates/design/actions/create-component.ts +447 -0
  41. package/corpus/templates/design/actions/create-design-branch.ts +263 -0
  42. package/corpus/templates/design/actions/create-design-state.ts +162 -0
  43. package/corpus/templates/design/actions/delete-design-state.ts +55 -0
  44. package/corpus/templates/design/actions/delete-design.ts +20 -0
  45. package/corpus/templates/design/actions/deploy-design-preview.ts +275 -0
  46. package/corpus/templates/design/actions/get-component-details.ts +251 -0
  47. package/corpus/templates/design/actions/get-design-branch-diff.ts +362 -0
  48. package/corpus/templates/design/actions/get-design-review.ts +314 -0
  49. package/corpus/templates/design/actions/get-design-surface-index.ts +582 -0
  50. package/corpus/templates/design/actions/get-motion-timeline.ts +99 -0
  51. package/corpus/templates/design/actions/index-components.ts +258 -0
  52. package/corpus/templates/design/actions/index-design-tokens.ts +277 -0
  53. package/corpus/templates/design/actions/list-design-extensions.ts +309 -0
  54. package/corpus/templates/design/actions/list-design-source-capabilities.ts +153 -0
  55. package/corpus/templates/design/actions/list-design-states.ts +90 -0
  56. package/corpus/templates/design/actions/migrate-inline-design-to-app.ts +298 -0
  57. package/corpus/templates/design/actions/open-component-source.ts +242 -0
  58. package/corpus/templates/design/actions/preview-component-prop-edit.ts +260 -0
  59. package/corpus/templates/design/actions/preview-design-token-edit.ts +113 -0
  60. package/corpus/templates/design/actions/preview-shader-fill.ts +187 -0
  61. package/corpus/templates/design/actions/remove-breakpoint.ts +103 -0
  62. package/corpus/templates/design/actions/remove-motion-timeline.ts +196 -0
  63. package/corpus/templates/design/actions/run-design-audit.ts +436 -0
  64. package/corpus/templates/design/actions/run-design-extension-action.ts +284 -0
  65. package/corpus/templates/design/actions/set-active-breakpoint.ts +39 -0
  66. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +1550 -82
  67. package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +649 -43
  68. package/corpus/templates/design/app/components/design/DrawOverlay.tsx +1 -1
  69. package/corpus/templates/design/app/components/design/EditPanel.tsx +1788 -52
  70. package/corpus/templates/design/app/components/design/LayersPanel.tsx +114 -33
  71. package/corpus/templates/design/app/components/design/LocalSourceEditBanner.tsx +157 -0
  72. package/corpus/templates/design/app/components/design/MotionDock.tsx +1071 -0
  73. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +1053 -99
  74. package/corpus/templates/design/app/components/design/ReviewPanel.tsx +766 -0
  75. package/corpus/templates/design/app/components/design/StatesPanel.tsx +581 -0
  76. package/corpus/templates/design/app/components/design/TokensPanel.tsx +578 -0
  77. package/corpus/templates/design/app/components/design/canvas-primitive-style.ts +241 -0
  78. package/corpus/templates/design/app/components/design/index.ts +16 -0
  79. package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +15 -6
  80. package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +66 -3
  81. package/corpus/templates/design/app/components/design/inspector/InspectorAiActions.tsx +145 -0
  82. package/corpus/templates/design/app/components/design/inspector/SHADER_INTEGRATION.md +42 -12
  83. package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +1 -1
  84. package/corpus/templates/design/app/hooks/useAgentEditRequest.ts +131 -0
  85. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +3 -1
  86. package/corpus/templates/design/app/i18n/zh-TW.ts +32 -0
  87. package/corpus/templates/design/app/i18n-data.ts +280 -0
  88. package/corpus/templates/design/app/pages/DesignEditor.tsx +3087 -490
  89. package/corpus/templates/design/changelog/2026-06-29-added-a-review-panel-in-the-design-editor-s-inspector-with-a.md +6 -0
  90. package/corpus/templates/design/changelog/2026-06-29-copying-and-pasting-layers-no-longer-shows-success-notificat.md +6 -0
  91. package/corpus/templates/design/changelog/2026-06-29-device-presets-in-all-screens-view-resize-the-selected-previ.md +6 -0
  92. package/corpus/templates/design/changelog/2026-06-29-layer-and-canvas-drags-keep-the-layer-list-stable-while-chan.md +6 -0
  93. package/corpus/templates/design/changelog/2026-06-29-layer-moves-can-be-undone-and-redone-without-flashing-the-ca.md +6 -0
  94. package/corpus/templates/design/changelog/2026-06-29-screen-previews-use-a-single-blue-hover-border-in-all-screen.md +6 -0
  95. package/corpus/templates/design/changelog/2026-06-29-selected-containers-show-draggable-padding-and-gap-guides-on.md +6 -0
  96. package/corpus/templates/design/changelog/2026-06-29-the-design-editor-adds-a-studio-layer-with-tokens-respon.md +6 -0
  97. package/corpus/templates/design/changelog/2026-06-30-accessibility-findings-now-offer-a-one-click-fix.md +6 -0
  98. package/corpus/templates/design/changelog/2026-06-30-component-instances-now-have-editable-props-in-the-inspe.md +6 -0
  99. package/corpus/templates/design/changelog/2026-06-30-design-token-edits-now-stay-visible-in-previews-and-token-li.md +6 -0
  100. package/corpus/templates/design/changelog/2026-06-30-inspect-code-now-shows-the-elements-opening-tag-at-a-gla.md +6 -0
  101. package/corpus/templates/design/changelog/2026-06-30-shader-fill-presets-can-now-be-applied-to-an-element.md +6 -0
  102. package/corpus/templates/design/changelog/2026-06-30-the-motion-timeline-can-now-add-a-track-to-any-element-a.md +6 -0
  103. package/corpus/templates/design/changelog/2026-06-30-visual-editor-selection-layer-paint-and-drawing-controls-are-more-reliable.md +6 -0
  104. package/corpus/templates/design/e2e/global-setup.ts +94 -2
  105. package/corpus/templates/design/e2e/helpers.ts +10 -4
  106. package/corpus/templates/design/server/db/schema.ts +123 -0
  107. package/corpus/templates/design/server/plugins/db.ts +90 -0
  108. package/corpus/templates/design/shared/builder-app.ts +297 -0
  109. package/corpus/templates/design/shared/capability-resolver.ts +123 -0
  110. package/corpus/templates/design/shared/capture-sanitize.ts +70 -0
  111. package/corpus/templates/design/shared/code-layer.ts +1016 -71
  112. package/corpus/templates/design/shared/component-model.ts +274 -0
  113. package/corpus/templates/design/shared/design-review.ts +275 -0
  114. package/corpus/templates/design/shared/design-source-capabilities.ts +286 -0
  115. package/corpus/templates/design/shared/design-state.ts +112 -0
  116. package/corpus/templates/design/shared/design-surface-index.ts +258 -0
  117. package/corpus/templates/design/shared/motion-compiler.ts +349 -0
  118. package/corpus/templates/design/shared/motion-timeline.ts +193 -0
  119. package/corpus/templates/design/shared/resolve-tweaks.ts +32 -9
  120. package/corpus/templates/design/shared/responsive-classes.ts +452 -0
  121. package/corpus/templates/design/shared/shader-fill.ts +323 -0
  122. package/corpus/templates/design/shared/source-mode.ts +245 -0
  123. package/corpus/templates/plan/app/components/plan/CanvasArea.tsx +6 -2
  124. package/corpus/templates/plan/changelog/2026-06-29-plan-canvases-open-without-an-initial-pan-and-zoom-flicker.md +6 -0
  125. package/dist/agent/production-agent.d.ts.map +1 -1
  126. package/dist/agent/production-agent.js +94 -10
  127. package/dist/agent/production-agent.js.map +1 -1
  128. package/dist/cli/design-connect.d.ts.map +1 -1
  129. package/dist/cli/design-connect.js +28 -2
  130. package/dist/cli/design-connect.js.map +1 -1
  131. package/dist/cli/skills.d.ts.map +1 -1
  132. package/dist/cli/skills.js +37 -21
  133. package/dist/cli/skills.js.map +1 -1
  134. package/dist/client/AssistantChat.d.ts +14 -0
  135. package/dist/client/AssistantChat.d.ts.map +1 -1
  136. package/dist/client/AssistantChat.js +115 -22
  137. package/dist/client/AssistantChat.js.map +1 -1
  138. package/dist/client/sse-event-processor.d.ts.map +1 -1
  139. package/dist/client/sse-event-processor.js +10 -0
  140. package/dist/client/sse-event-processor.js.map +1 -1
  141. package/dist/collab/routes.d.ts +1 -1
  142. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  143. package/dist/notifications/routes.d.ts +2 -2
  144. package/dist/observability/routes.d.ts +8 -8
  145. package/dist/resources/handlers.d.ts +2 -2
  146. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  147. package/dist/server/transcribe-voice.d.ts +1 -1
  148. package/package.json +1 -1
@@ -826,6 +826,13 @@ const enUS = {
826
826
  noMatchingAssets: "No matching assets across your kits.",
827
827
  noMatchingLibraryAssets:
828
828
  "No matching {{mediaLabel}} assets in this library.",
829
+ drafts: "Drafts",
830
+ allLibraries: "All libraries",
831
+ noDrafts: "No drafts yet.",
832
+ noMatchingDrafts: "No matching drafts.",
833
+ recentDrafts: "Recent Drafts",
834
+ viewAllDrafts: "View all drafts",
835
+ draftAsset: "Draft asset",
829
836
  noReusableAssets:
830
837
  "No reusable assets yet. Select a kit to upload references or generate assets.",
831
838
  noNewAssetsUploaded: "No new assets were uploaded.",
@@ -2762,6 +2769,12 @@ export const messagesByLocale = {
2762
2769
  "zh-TW": mergeMessages(zhTW),
2763
2770
  "zh-CN": mergeMessages({
2764
2771
  library: {
2772
+ allLibraries: "所有库",
2773
+ noDrafts: "暂无草稿。",
2774
+ noMatchingDrafts: "没有匹配的草稿。",
2775
+ recentDrafts: "最近草稿",
2776
+ viewAllDrafts: "查看所有草稿",
2777
+ draftAsset: "草稿资产",
2765
2778
  addAssets: "添加资产",
2766
2779
  addAssetsDescription:
2767
2780
  "上传源素材或生成候选项,然后只将应指导未来生成的资产标记为参考。",
@@ -3500,6 +3513,12 @@ export const messagesByLocale = {
3500
3513
  }),
3501
3514
  "es-ES": mergeMessages({
3502
3515
  library: {
3516
+ allLibraries: "Todas las bibliotecas",
3517
+ noDrafts: "Aún no hay borradores.",
3518
+ noMatchingDrafts: "No hay borradores coincidentes.",
3519
+ recentDrafts: "Borradores recientes",
3520
+ viewAllDrafts: "Ver todos los borradores",
3521
+ draftAsset: "Borrador",
3503
3522
  addAssets: "Agregar activos",
3504
3523
  addAssetsDescription:
3505
3524
  "Cargue material fuente o genere candidatos, luego marque solo los activos que deberían guiar a las generaciones futuras como referencias.",
@@ -3963,6 +3982,12 @@ export const messagesByLocale = {
3963
3982
  }),
3964
3983
  "fr-FR": mergeMessages({
3965
3984
  library: {
3985
+ allLibraries: "Toutes les bibliothèques",
3986
+ noDrafts: "Aucun brouillon pour l'instant.",
3987
+ noMatchingDrafts: "Aucun brouillon correspondant.",
3988
+ recentDrafts: "Brouillons récents",
3989
+ viewAllDrafts: "Voir tous les brouillons",
3990
+ draftAsset: "Brouillon",
3966
3991
  addAssets: "Ajouter des éléments",
3967
3992
  addAssetsDescription:
3968
3993
  "Téléchargez le matériel source ou générez des candidats, puis marquez uniquement les atouts qui devraient guider les générations futures comme références.",
@@ -4404,6 +4429,12 @@ export const messagesByLocale = {
4404
4429
  }),
4405
4430
  "de-DE": mergeMessages({
4406
4431
  library: {
4432
+ allLibraries: "Alle Bibliotheken",
4433
+ noDrafts: "Noch keine Entwürfe.",
4434
+ noMatchingDrafts: "Keine passenden Entwürfe.",
4435
+ recentDrafts: "Letzte Entwürfe",
4436
+ viewAllDrafts: "Alle Entwürfe anzeigen",
4437
+ draftAsset: "Entwurf",
4407
4438
  addAssets: "Assets hinzufügen",
4408
4439
  addAssetsDescription:
4409
4440
  "Laden Sie Quellmaterial hoch oder generieren Sie Kandidaten und markieren Sie dann nur die Assets, die künftigen Generationen als Referenz dienen sollen.",
@@ -4753,6 +4784,12 @@ export const messagesByLocale = {
4753
4784
  }),
4754
4785
  "ja-JP": mergeMessages({
4755
4786
  library: {
4787
+ allLibraries: "すべてのライブラリ",
4788
+ noDrafts: "下書きはまだありません。",
4789
+ noMatchingDrafts: "一致する下書きはありません。",
4790
+ recentDrafts: "最近の下書き",
4791
+ viewAllDrafts: "すべての下書きを表示",
4792
+ draftAsset: "下書きアセット",
4756
4793
  addAssets: "アセットの追加",
4757
4794
  addAssetsDescription:
4758
4795
  "ソース素材をアップロードするか候補を生成し、将来の世代を導く必要がある資産のみを参照としてマークします。",
@@ -5092,6 +5129,12 @@ export const messagesByLocale = {
5092
5129
  }),
5093
5130
  "ko-KR": mergeMessages({
5094
5131
  library: {
5132
+ allLibraries: "모든 라이브러리",
5133
+ noDrafts: "아직 초안이 없습니다.",
5134
+ noMatchingDrafts: "일치하는 초안이 없습니다.",
5135
+ recentDrafts: "최근 초안",
5136
+ viewAllDrafts: "모든 초안 보기",
5137
+ draftAsset: "초안 자산",
5095
5138
  addAssets: "자산 추가",
5096
5139
  addAssetsDescription:
5097
5140
  "원본 자료를 업로드하거나 후보를 생성한 후, 미래 세대를 이끌어야 할 자산만 참고 자료로 표시하세요.",
@@ -5430,6 +5473,12 @@ export const messagesByLocale = {
5430
5473
  }),
5431
5474
  "pt-BR": mergeMessages({
5432
5475
  library: {
5476
+ allLibraries: "Todas as bibliotecas",
5477
+ noDrafts: "Ainda não há rascunhos.",
5478
+ noMatchingDrafts: "Nenhum rascunho correspondente.",
5479
+ recentDrafts: "Rascunhos recentes",
5480
+ viewAllDrafts: "Ver todos os rascunhos",
5481
+ draftAsset: "Rascunho",
5433
5482
  addAssets: "Adicionar recursos",
5434
5483
  addAssetsDescription:
5435
5484
  "Carregue o material de origem ou gere candidatos e marque apenas os ativos que devem orientar as gerações futuras como referências.",
@@ -5870,6 +5919,12 @@ export const messagesByLocale = {
5870
5919
  }),
5871
5920
  "hi-IN": mergeMessages({
5872
5921
  library: {
5922
+ allLibraries: "सभी लाइब्रेरी",
5923
+ noDrafts: "अभी तक कोई ड्राफ़्ट नहीं।",
5924
+ noMatchingDrafts: "कोई मिलान वाला ड्राफ़्ट नहीं।",
5925
+ recentDrafts: "हाल के ड्राफ़्ट",
5926
+ viewAllDrafts: "सभी ड्राफ़्ट देखें",
5927
+ draftAsset: "ड्राफ़्ट एसेट",
5873
5928
  addAssets: "संपत्तियां जोड़ें",
5874
5929
  addAssetsDescription:
5875
5930
  "स्रोत सामग्री अपलोड करें या उम्मीदवार तैयार करें, फिर केवल उन संपत्तियों को चिह्नित करें जो भविष्य की पीढ़ियों को संदर्भ के रूप में मार्गदर्शन करें।",
@@ -6206,6 +6261,12 @@ export const messagesByLocale = {
6206
6261
  }),
6207
6262
  "ar-SA": mergeMessages({
6208
6263
  library: {
6264
+ allLibraries: "جميع المكتبات",
6265
+ noDrafts: "لا توجد مسودات بعد.",
6266
+ noMatchingDrafts: "لا توجد مسودات مطابقة.",
6267
+ recentDrafts: "المسودات الأخيرة",
6268
+ viewAllDrafts: "عرض جميع المسودات",
6269
+ draftAsset: "مسودة",
6209
6270
  addAssets: "أضف الأصول",
6210
6271
  addAssetsDescription:
6211
6272
  "قم بتحميل المواد المصدرية أو قم بإنشاء مرشحين، ثم حدد فقط الأصول التي يجب أن توجه الأجيال القادمة كمراجع.",
@@ -9,6 +9,7 @@ import { IconPhoto, IconSparkles, IconVideo } from "@tabler/icons-react";
9
9
  import { useEffect } from "react";
10
10
  import { useNavigate, useParams } from "react-router";
11
11
 
12
+ import { RecentDraftsSection } from "@/components/create/RecentDraftsSection";
12
13
  import { GenerationResults } from "@/components/generation/GenerationResults";
13
14
  import { useImageModelMenu } from "@/hooks/use-image-model-menu";
14
15
  import { ASSETS_CHAT_STORAGE_KEY } from "@/lib/chat";
@@ -122,6 +123,9 @@ export default function CreatePage() {
122
123
  </button>
123
124
  ))}
124
125
  </div>
126
+ <div className="mt-8 w-full text-left">
127
+ <RecentDraftsSection />
128
+ </div>
125
129
  </div>
126
130
  }
127
131
  />
@@ -102,16 +102,22 @@ import {
102
102
  type VariantSlot,
103
103
  } from "./brand-kits.$id";
104
104
 
105
- type AssetTab = "all" | "generated" | "references";
105
+ type AssetTab = "all" | "generated" | "drafts" | "references";
106
106
 
107
107
  function isGeneratedAsset(asset: Asset) {
108
108
  const role = asset.role ?? "";
109
109
  return role === "generated" || role === "active" || role === "candidate";
110
110
  }
111
111
 
112
+ function isDraftAsset(asset: Asset) {
113
+ return asset.role === "generated" && asset.status === "candidate";
114
+ }
115
+
112
116
  function assetMatchesTab(asset: Asset, tab: AssetTab) {
113
117
  if (tab === "all") return true;
114
- if (tab === "generated") return isGeneratedAsset(asset);
118
+ if (tab === "drafts") return isDraftAsset(asset);
119
+ if (tab === "generated")
120
+ return isGeneratedAsset(asset) && !isDraftAsset(asset);
115
121
  return !isGeneratedAsset(asset);
116
122
  }
117
123
 
@@ -1957,12 +1963,29 @@ export function LibraryWorkspace({
1957
1963
 
1958
1964
  export function AssetPickerSurface() {
1959
1965
  const t = useT();
1960
- const [searchParams] = useSearchParams();
1966
+ const [searchParams, setSearchParams] = useSearchParams();
1961
1967
  const searchParamsKey = searchParams.toString();
1968
+ const urlAssetTab = useMemo<AssetTab | null>(() => {
1969
+ const tab = new URLSearchParams(searchParamsKey).get("tab");
1970
+ return tab === "all" ||
1971
+ tab === "generated" ||
1972
+ tab === "drafts" ||
1973
+ tab === "references"
1974
+ ? tab
1975
+ : null;
1976
+ }, [searchParamsKey]);
1977
+ // The active tab is the only host-irrelevant search param. Exclude it from the
1978
+ // host-config key so toggling tabs (which writes `?tab=`) doesn't retrigger the
1979
+ // effect that resets media type / query / library from the URL.
1980
+ const hostParamsKey = useMemo(() => {
1981
+ const params = new URLSearchParams(searchParamsKey);
1982
+ params.delete("tab");
1983
+ return params.toString();
1984
+ }, [searchParamsKey]);
1962
1985
  const mcpChatBridgeActive =
1963
1986
  searchParamsRequestPicker(searchParams) || isEmbedMcpChatBridgeActive();
1964
1987
  const urlHostConfig = useMemo(() => {
1965
- const params = new URLSearchParams(searchParamsKey);
1988
+ const params = new URLSearchParams(hostParamsKey);
1966
1989
  return {
1967
1990
  mediaType: normalizeMediaType(params.get("mediaType")),
1968
1991
  prompt: params.get("prompt") ?? undefined,
@@ -1983,7 +2006,7 @@ export function AssetPickerSurface() {
1983
2006
  ),
1984
2007
  autoGenerate: normalizeBoolean(params.get("autoGenerate")) ?? false,
1985
2008
  } satisfies HostConfig;
1986
- }, [searchParamsKey]);
2009
+ }, [hostParamsKey]);
1987
2010
  const bridgeRef = useRef<EmbeddedAppBridge | null>(null);
1988
2011
  const embedded = useMemo(
1989
2012
  () =>
@@ -2008,7 +2031,7 @@ export function AssetPickerSurface() {
2008
2031
  );
2009
2032
  const [presetId, setPresetId] = useState(() => hostConfig.presetId ?? "none");
2010
2033
  const [count, setCount] = useState(() => hostConfig.count ?? 3);
2011
- const [assetTab, setAssetTab] = useState<AssetTab>("all");
2034
+ const [assetTab, setAssetTab] = useState<AssetTab>(urlAssetTab ?? "all");
2012
2035
  const [selectedLibraryId, setSelectedLibraryId] = useState(
2013
2036
  () => hostConfig.libraryId ?? "",
2014
2037
  );
@@ -2032,6 +2055,30 @@ export function AssetPickerSurface() {
2032
2055
  setVisibleCandidateRunIds(urlHostConfig.candidateRunIds ?? []);
2033
2056
  }, [urlHostConfig]);
2034
2057
 
2058
+ useEffect(() => {
2059
+ // Reset to "all" when the tab param is removed (e.g. back/forward nav)
2060
+ // since the component stays mounted across search-param changes.
2061
+ setAssetTab(urlAssetTab ?? "all");
2062
+ }, [urlAssetTab]);
2063
+
2064
+ const handleAssetTabChange = useCallback(
2065
+ (value: AssetTab) => {
2066
+ setAssetTab(value);
2067
+ // Keep the tab reflected in the URL so it survives refresh/share and
2068
+ // stays consistent with the `?tab=` deep link from the home page.
2069
+ setSearchParams(
2070
+ (prev) => {
2071
+ const next = new URLSearchParams(prev);
2072
+ if (value === "all") next.delete("tab");
2073
+ else next.set("tab", value);
2074
+ return next;
2075
+ },
2076
+ { replace: true },
2077
+ );
2078
+ },
2079
+ [setSearchParams],
2080
+ );
2081
+
2035
2082
  const librariesQuery = useActionQuery("list-libraries", {
2036
2083
  compact: true,
2037
2084
  } as any) as {
@@ -2116,23 +2163,54 @@ export function AssetPickerSurface() {
2116
2163
  !selectedPreset &&
2117
2164
  Boolean(waitingForPresetData);
2118
2165
  const mediaLabel = mediaType === "video" ? "video" : "image";
2166
+ const viewingDrafts = assetTab === "drafts";
2167
+ // The standalone Library "Drafts" tab mirrors the home Recent Drafts section:
2168
+ // every unsaved draft across all accessible libraries, regardless of media
2169
+ // type. The embedded picker keeps its library + media-type scope so an
2170
+ // image-only picker never surfaces video drafts.
2171
+ const draftsGlobalView = viewingDrafts && !embedded;
2119
2172
  const assetsParams = useMemo(
2120
2173
  () => ({
2121
2174
  libraryId: selectedLibraryId,
2122
2175
  mediaType,
2176
+ // Drafts are exactly generated candidates — filter them server-side
2177
+ // instead of fetching the whole library and filtering on the client.
2178
+ role: viewingDrafts ? "generated" : undefined,
2179
+ status: viewingDrafts ? "candidate" : undefined,
2123
2180
  query: query.trim() || undefined,
2124
2181
  includeCandidates:
2125
- mediaType === "image" && visibleCandidateRunIds.length > 0,
2182
+ viewingDrafts ||
2183
+ (mediaType === "image" && visibleCandidateRunIds.length > 0),
2184
+ // The Drafts tab shows every unsaved draft, not just the latest run batch.
2126
2185
  candidateRunIds:
2127
- visibleCandidateRunIds.length > 0 ? visibleCandidateRunIds : undefined,
2186
+ !viewingDrafts && visibleCandidateRunIds.length > 0
2187
+ ? visibleCandidateRunIds
2188
+ : undefined,
2128
2189
  }),
2129
- [mediaType, query, selectedLibraryId, visibleCandidateRunIds],
2190
+ [
2191
+ viewingDrafts,
2192
+ mediaType,
2193
+ query,
2194
+ selectedLibraryId,
2195
+ visibleCandidateRunIds,
2196
+ ],
2130
2197
  );
2131
2198
  const { data: assetData, isLoading: assetsLoading } = useActionQuery(
2132
2199
  "list-assets",
2133
2200
  assetsParams as any,
2134
- { enabled: Boolean(selectedLibraryId) && !usingStarterLibrary } as any,
2201
+ {
2202
+ enabled:
2203
+ Boolean(selectedLibraryId) && !usingStarterLibrary && !draftsGlobalView,
2204
+ } as any,
2135
2205
  ) as { data?: { assets?: Asset[] }; isLoading: boolean };
2206
+ const { data: globalDraftsData, isLoading: globalDraftsLoading } =
2207
+ useActionQuery(
2208
+ "list-draft-assets",
2209
+ { limit: 500 } as any,
2210
+ {
2211
+ enabled: draftsGlobalView,
2212
+ } as any,
2213
+ ) as { data?: { assets?: Asset[] }; isLoading: boolean };
2136
2214
  const starterAssets: Asset[] = useMemo(
2137
2215
  () =>
2138
2216
  STARTER_PRESET.referenceImages.map((reference) => ({
@@ -2159,11 +2237,23 @@ export function AssetPickerSurface() {
2159
2237
  .some((value) => String(value).toLowerCase().includes(needle)),
2160
2238
  );
2161
2239
  }, [query, starterAssets]);
2162
- const allAssets = usingStarterLibrary
2163
- ? mediaType === "image"
2164
- ? visibleStarterAssets
2165
- : []
2166
- : (assetData?.assets ?? []);
2240
+ const globalDrafts = useMemo(() => {
2241
+ const drafts = globalDraftsData?.assets ?? [];
2242
+ const needle = query.trim().toLowerCase();
2243
+ if (!needle) return drafts;
2244
+ return drafts.filter((asset) =>
2245
+ [asset.title, asset.description, asset.prompt]
2246
+ .filter(Boolean)
2247
+ .some((value) => String(value).toLowerCase().includes(needle)),
2248
+ );
2249
+ }, [globalDraftsData, query]);
2250
+ const allAssets = draftsGlobalView
2251
+ ? globalDrafts
2252
+ : usingStarterLibrary
2253
+ ? mediaType === "image"
2254
+ ? visibleStarterAssets
2255
+ : []
2256
+ : (assetData?.assets ?? []);
2167
2257
  const currentLibrary = useMemo(
2168
2258
  () =>
2169
2259
  displayLibraries.find((library) => library.id === selectedLibraryId) ??
@@ -2174,6 +2264,7 @@ export function AssetPickerSurface() {
2174
2264
  () => allAssets.filter((asset) => assetMatchesTab(asset, assetTab)),
2175
2265
  [allAssets, assetTab],
2176
2266
  );
2267
+ const listLoading = draftsGlobalView ? globalDraftsLoading : assetsLoading;
2177
2268
  const [previewAsset, setPreviewAsset] = useState<Asset | null>(null);
2178
2269
  const [standaloneSelection, setStandaloneSelection] = useState<ReturnType<
2179
2270
  typeof assetPayload
@@ -2845,27 +2936,35 @@ export function AssetPickerSurface() {
2845
2936
  {displayLibraries.length > 0 && (
2846
2937
  <div className="mb-3 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
2847
2938
  <div className="flex flex-col gap-2 sm:flex-row sm:items-center">
2848
- <Select
2849
- value={selectedLibraryId}
2850
- onValueChange={setSelectedLibraryId}
2851
- >
2852
- <SelectTrigger className="h-9 w-full border-border/70 bg-background sm:w-48">
2853
- <SelectValue placeholder={t("library.library")} />
2854
- </SelectTrigger>
2855
- <SelectContent>
2856
- <SelectGroup>
2857
- {displayLibraries.map((library) => (
2858
- <SelectItem key={library.id} value={library.id}>
2859
- {library.title}
2860
- </SelectItem>
2861
- ))}
2862
- </SelectGroup>
2863
- </SelectContent>
2864
- </Select>
2939
+ {draftsGlobalView ? (
2940
+ <div className="flex h-9 items-center rounded-md border border-border/70 bg-background px-3 text-sm text-muted-foreground sm:w-48">
2941
+ {t("library.allLibraries")}
2942
+ </div>
2943
+ ) : (
2944
+ <Select
2945
+ value={selectedLibraryId}
2946
+ onValueChange={setSelectedLibraryId}
2947
+ >
2948
+ <SelectTrigger className="h-9 w-full border-border/70 bg-background sm:w-48">
2949
+ <SelectValue placeholder={t("library.library")} />
2950
+ </SelectTrigger>
2951
+ <SelectContent>
2952
+ <SelectGroup>
2953
+ {displayLibraries.map((library) => (
2954
+ <SelectItem key={library.id} value={library.id}>
2955
+ {library.title}
2956
+ </SelectItem>
2957
+ ))}
2958
+ </SelectGroup>
2959
+ </SelectContent>
2960
+ </Select>
2961
+ )}
2865
2962
  {selectedLibraryId && (
2866
2963
  <Tabs
2867
2964
  value={assetTab}
2868
- onValueChange={(value) => setAssetTab(value as AssetTab)}
2965
+ onValueChange={(value) =>
2966
+ handleAssetTabChange(value as AssetTab)
2967
+ }
2869
2968
  >
2870
2969
  <TabsList>
2871
2970
  <TabsTrigger value="all">
@@ -2874,6 +2973,9 @@ export function AssetPickerSurface() {
2874
2973
  <TabsTrigger value="generated">
2875
2974
  {t("library.generated")}
2876
2975
  </TabsTrigger>
2976
+ <TabsTrigger value="drafts">
2977
+ {t("library.drafts")}
2978
+ </TabsTrigger>
2877
2979
  <TabsTrigger value="references">
2878
2980
  {t("library.references")}
2879
2981
  </TabsTrigger>
@@ -2897,6 +2999,7 @@ export function AssetPickerSurface() {
2897
2999
  {mediaType === "image" &&
2898
3000
  selectedLibraryId &&
2899
3001
  !usingStarterLibrary &&
3002
+ !viewingDrafts &&
2900
3003
  pickerVariantScopeId && (
2901
3004
  <LibraryCandidateStage
2902
3005
  activeLibraryId={selectedLibraryId}
@@ -2914,7 +3017,7 @@ export function AssetPickerSurface() {
2914
3017
  </div>
2915
3018
  )}
2916
3019
 
2917
- {selectedLibraryId && assetsLoading && (
3020
+ {selectedLibraryId && listLoading && (
2918
3021
  <div className="assets-library-dense-grid grid grid-cols-2 gap-3">
2919
3022
  {Array.from({ length: 8 }).map((_, index) => (
2920
3023
  <Skeleton key={index} className="aspect-square rounded-md" />
@@ -2922,12 +3025,16 @@ export function AssetPickerSurface() {
2922
3025
  </div>
2923
3026
  )}
2924
3027
 
2925
- {selectedLibraryId && !assetsLoading && assets.length === 0 && (
3028
+ {selectedLibraryId && !listLoading && assets.length === 0 && (
2926
3029
  <div className="flex h-full items-center justify-center text-center">
2927
3030
  <div className="max-w-sm text-sm text-muted-foreground">
2928
- {query
2929
- ? t("library.noMatchingLibraryAssets", { mediaLabel })
2930
- : t("library.noAssetsInLibrary", { mediaLabel })}
3031
+ {draftsGlobalView
3032
+ ? query
3033
+ ? t("library.noMatchingDrafts")
3034
+ : t("library.noDrafts")
3035
+ : query
3036
+ ? t("library.noMatchingLibraryAssets", { mediaLabel })
3037
+ : t("library.noAssetsInLibrary", { mediaLabel })}
2931
3038
  </div>
2932
3039
  </div>
2933
3040
  )}
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-06-29
4
+ ---
5
+
6
+ Image generation can now render requested text and respect brand fonts
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-06-30
4
+ ---
5
+
6
+ Image generation no longer looks stuck while the provider is still creating and saving the asset.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-06-30
4
+ ---
5
+
6
+ Tagging a @preset now reliably uses its aspect ratio and other saved settings instead of a guessed one