@agent-native/core 0.137.2 → 0.137.4

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 (176) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  3. package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +53 -1
  4. package/corpus/templates/analytics/actions/gong-calls.ts +37 -17
  5. package/corpus/templates/analytics/app/lib/data-sources.ts +1 -1
  6. package/corpus/templates/analytics/server/lib/gong.ts +51 -2
  7. package/corpus/templates/assets/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  8. package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +53 -1
  9. package/corpus/templates/brain/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  10. package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +53 -1
  11. package/corpus/templates/brain/app/routes/settings.tsx +1 -1
  12. package/corpus/templates/brain/server/register-secrets.ts +1 -1
  13. package/corpus/templates/calendar/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  14. package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +53 -1
  15. package/corpus/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  16. package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +53 -1
  17. package/corpus/templates/chat/AGENTS.md +11 -0
  18. package/corpus/templates/chat/app/components/layout/Layout.tsx +1 -1
  19. package/corpus/templates/chat/app/root.tsx +1 -1
  20. package/corpus/templates/chat/app/routes/agent.tsx +29 -13
  21. package/corpus/templates/chat/vite.config.ts +42 -0
  22. package/corpus/templates/clips/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  23. package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +53 -1
  24. package/corpus/templates/clips/app/components/library/empty-state.tsx +1 -3
  25. package/corpus/templates/clips/app/components/library/library-grid.tsx +2 -6
  26. package/corpus/templates/clips/app/components/library/library-layout.tsx +2 -6
  27. package/corpus/templates/clips/app/components/recorder/pre-record-panel.tsx +1 -3
  28. package/corpus/templates/clips/app/routes/bug-report.tsx +1 -8
  29. package/corpus/templates/clips/app/routes/import.tsx +1 -3
  30. package/corpus/templates/clips/changelog/2026-08-04-recording-buttons-are-now-text-only-for-a-cleaner-clips-inte.md +6 -0
  31. package/corpus/templates/clips/changelog/2026-08-04-save-settings-now-matches-the-other-clips-settings-buttons.md +6 -0
  32. package/corpus/templates/clips/chrome-extension/src/styles.css +1 -0
  33. package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  34. package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +53 -1
  35. package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  36. package/corpus/templates/crm/app/routes/settings.tsx +2 -2
  37. package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  38. package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +53 -1
  39. package/corpus/templates/design/actions/import-figma-clipboard.ts +1 -1
  40. package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  41. package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +53 -1
  42. package/corpus/templates/dispatch/changelog/2026-08-04-dispatch-keeps-connected-chats-out-of-local-history-by-defau.md +6 -0
  43. package/corpus/templates/factory/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  44. package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +53 -1
  45. package/corpus/templates/factory/README.md +1 -1
  46. package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  47. package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +53 -1
  48. package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  49. package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +53 -1
  50. package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  51. package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +53 -1
  52. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +0 -2
  53. package/corpus/templates/mail/app/pages/SettingsPage.tsx +1 -1
  54. package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  55. package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +53 -1
  56. package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  57. package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +53 -1
  58. package/corpus/templates/slides/actions/generate-image-api.ts +15 -4
  59. package/corpus/templates/slides/actions/import-google-slides-reference.ts +83 -0
  60. package/corpus/templates/slides/actions/import-pptx.ts +134 -117
  61. package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +387 -0
  62. package/corpus/templates/slides/app/components/editor/ImageGenPanel.tsx +78 -48
  63. package/corpus/templates/slides/app/components/editor/NewDeckReferenceStep.tsx +377 -187
  64. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +0 -1
  65. package/corpus/templates/slides/app/hooks/use-deck-design-system.ts +20 -1
  66. package/corpus/templates/slides/app/i18n/en-US.ts +15 -0
  67. package/corpus/templates/slides/app/lib/new-deck-reference-selection.ts +22 -0
  68. package/corpus/templates/slides/app/pages/DeckEditor.tsx +4 -1
  69. package/corpus/templates/slides/app/pages/Index.tsx +172 -85
  70. package/corpus/templates/slides/server/lib/assets-image-delegation.ts +4 -2
  71. package/corpus/templates/slides/shared/api.ts +14 -1
  72. package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  73. package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +53 -1
  74. package/dist/chat-threads/schema.d.ts +57 -0
  75. package/dist/chat-threads/schema.js +3 -0
  76. package/dist/chat-threads/store.d.ts +26 -0
  77. package/dist/chat-threads/store.js +84 -6
  78. package/dist/client/AgentPanel.js +11 -5
  79. package/dist/client/ConnectBuilderCard.js +1 -1
  80. package/dist/client/agent-page/AgentEmptyState.d.ts +2 -1
  81. package/dist/client/agent-page/AgentEmptyState.js +6 -2
  82. package/dist/client/agent-page/AgentJobsTab.d.ts +3 -1
  83. package/dist/client/agent-page/AgentJobsTab.js +55 -44
  84. package/dist/client/agent-page/AgentTabFrame.d.ts +2 -1
  85. package/dist/client/agent-page/AgentTabFrame.js +4 -2
  86. package/dist/client/agent-page/AgentTabsPage.js +12 -8
  87. package/dist/client/agent-page/AgentWorkspaceContent.d.ts +10 -0
  88. package/dist/client/agent-page/AgentWorkspaceContent.js +110 -0
  89. package/dist/client/agent-page/AutomationDetailsDialog.js +1 -1
  90. package/dist/client/chat/run-recovery.js +3 -3
  91. package/dist/client/error-format.js +1 -1
  92. package/dist/client/integrations/IntegrationsPanel.d.ts +1 -0
  93. package/dist/client/integrations/IntegrationsPanel.js +149 -5
  94. package/dist/client/onboarding/FirstRunOnboarding.js +130 -15
  95. package/dist/client/onboarding/index.d.ts +1 -1
  96. package/dist/client/onboarding/index.js +1 -1
  97. package/dist/client/onboarding/use-onboarding.js +12 -2
  98. package/dist/client/onboarding/use-preview-mode.d.ts +4 -0
  99. package/dist/client/onboarding/use-preview-mode.js +9 -0
  100. package/dist/client/resources/BuiltinCapabilityDetail.js +2 -2
  101. package/dist/client/resources/ResourceTree.d.ts +4 -1
  102. package/dist/client/resources/ResourceTree.js +13 -8
  103. package/dist/client/resources/ResourcesPanel.js +7 -3
  104. package/dist/client/resources/mcp-integration-catalog.js +4 -4
  105. package/dist/client/resources/use-mcp-servers.js +6 -6
  106. package/dist/client/settings/AgentsSection.js +15 -16
  107. package/dist/client/settings/AutomationsSection.js +1 -1
  108. package/dist/client/settings/DemoModeSection.js +1 -1
  109. package/dist/client/settings/SettingsPanel.d.ts +3 -1
  110. package/dist/client/settings/SettingsPanel.js +284 -88
  111. package/dist/client/settings/SettingsRow.js +1 -1
  112. package/dist/client/settings/SettingsSection.d.ts +6 -4
  113. package/dist/client/settings/SettingsSection.js +6 -6
  114. package/dist/client/settings/SettingsTabsPage.js +47 -25
  115. package/dist/client/settings/VoiceTranscriptionSection.d.ts +3 -1
  116. package/dist/client/settings/VoiceTranscriptionSection.js +20 -8
  117. package/dist/client/settings/agent-settings-search.d.ts +1 -1
  118. package/dist/client/settings/agent-settings-search.js +8 -8
  119. package/dist/client/transcription/BuilderTranscriptionCta.js +2 -2
  120. package/dist/client/use-chat-threads.d.ts +9 -0
  121. package/dist/client/use-chat-threads.js +22 -6
  122. package/dist/collab/routes.d.ts +1 -1
  123. package/dist/integrations/google-docs-poller.js +9 -1
  124. package/dist/integrations/webhook-handler.js +11 -1
  125. package/dist/jobs/scheduler.d.ts +4 -1
  126. package/dist/jobs/scheduler.js +34 -9
  127. package/dist/localization/default-messages.js +40 -40
  128. package/dist/mcp-client/oauth-routes.js +1 -1
  129. package/dist/notifications/routes.d.ts +1 -1
  130. package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
  131. package/dist/provider-api/actions/provider-api.d.ts +15 -15
  132. package/dist/resources/handlers.d.ts +1 -1
  133. package/dist/secrets/onboarding.js +1 -1
  134. package/dist/secrets/routes.d.ts +9 -9
  135. package/dist/server/agent-chat/browser-team-tools.d.ts +1 -0
  136. package/dist/server/agent-chat/browser-team-tools.js +1 -0
  137. package/dist/server/agent-chat-plugin.js +14 -1
  138. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  139. package/dist/server/agent-teams.d.ts +2 -0
  140. package/dist/server/agent-teams.js +2 -0
  141. package/dist/server/workspace-provider-oauth.js +1 -1
  142. package/dist/setup-connections/onboarding.js +2 -2
  143. package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  144. package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +53 -1
  145. package/dist/templates/chat/AGENTS.md +11 -0
  146. package/dist/templates/chat/app/components/layout/Layout.tsx +1 -1
  147. package/dist/templates/chat/app/root.tsx +1 -1
  148. package/dist/templates/chat/app/routes/agent.tsx +29 -13
  149. package/dist/templates/chat/vite.config.ts +42 -0
  150. package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  151. package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +53 -1
  152. package/dist/templates/default/AGENTS.md +11 -0
  153. package/dist/templates/default/vite.config.ts +42 -0
  154. package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  155. package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  156. package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +53 -1
  157. package/dist/templates/workspace-core/AGENTS.md +11 -0
  158. package/dist/templates/workspace-root/AGENTS.md +14 -0
  159. package/dist/vite/client.js +56 -0
  160. package/package.json +2 -2
  161. package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  162. package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +53 -1
  163. package/src/templates/chat/AGENTS.md +11 -0
  164. package/src/templates/chat/app/components/layout/Layout.tsx +1 -1
  165. package/src/templates/chat/app/root.tsx +1 -1
  166. package/src/templates/chat/app/routes/agent.tsx +29 -13
  167. package/src/templates/chat/vite.config.ts +42 -0
  168. package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  169. package/src/templates/default/.agents/skills/frontend-design/SKILL.md +53 -1
  170. package/src/templates/default/AGENTS.md +11 -0
  171. package/src/templates/default/vite.config.ts +42 -0
  172. package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  173. package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
  174. package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +53 -1
  175. package/src/templates/workspace-core/AGENTS.md +11 -0
  176. package/src/templates/workspace-root/AGENTS.md +14 -0
@@ -286,7 +286,6 @@ export function Sidebar({ collapsed, onToggleCollapsed }: SidebarProps) {
286
286
  feedback={feedbackButton}
287
287
  search={searchButton}
288
288
  collapse={collapseButton}
289
- className="px-0 py-0"
290
289
  />
291
290
  </div>
292
291
  </div>
@@ -1,6 +1,9 @@
1
1
  import { useActionQuery } from "@agent-native/core/client/hooks";
2
2
 
3
- import type { DesignSystemData } from "../../shared/api";
3
+ import {
4
+ normalizeReferenceUrls,
5
+ type DesignSystemData,
6
+ } from "../../shared/api";
4
7
 
5
8
  const DEFAULT_DESIGN_SYSTEM: DesignSystemData = {
6
9
  colors: {
@@ -54,10 +57,23 @@ function mergeWithDefaults<T>(defaults: T, value: unknown): T {
54
57
  return (value === undefined || value === null ? defaults : value) as T;
55
58
  }
56
59
 
60
+ export function getDesignSystemImageStyleReferenceUrls(
61
+ designSystem?: Pick<DesignSystemData, "imageStyle"> | null,
62
+ ): string[] {
63
+ return normalizeReferenceUrls(designSystem?.imageStyle?.referenceUrls);
64
+ }
65
+
57
66
  export function mergeDesignSystemData(value: unknown): DesignSystemData {
58
67
  return mergeWithDefaults(DEFAULT_DESIGN_SYSTEM, value);
59
68
  }
60
69
 
70
+ export interface DeckDesignSystemResult {
71
+ designSystem: DesignSystemData;
72
+ designSystemTitle: string | null;
73
+ imageStyleReferenceUrls: string[];
74
+ isLoading: boolean;
75
+ }
76
+
61
77
  export function useDeckDesignSystem(designSystemId?: string | null) {
62
78
  const { data, isLoading } = useActionQuery<{
63
79
  id: string;
@@ -71,6 +87,7 @@ export function useDeckDesignSystem(designSystemId?: string | null) {
71
87
  return {
72
88
  designSystem: DEFAULT_DESIGN_SYSTEM,
73
89
  designSystemTitle: null,
90
+ imageStyleReferenceUrls: [],
74
91
  isLoading: false,
75
92
  };
76
93
  }
@@ -80,12 +97,14 @@ export function useDeckDesignSystem(designSystemId?: string | null) {
80
97
  return {
81
98
  designSystem: parsed,
82
99
  designSystemTitle: data.title ?? null,
100
+ imageStyleReferenceUrls: getDesignSystemImageStyleReferenceUrls(parsed),
83
101
  isLoading,
84
102
  };
85
103
  } catch {
86
104
  return {
87
105
  designSystem: DEFAULT_DESIGN_SYSTEM,
88
106
  designSystemTitle: data.title ?? null,
107
+ imageStyleReferenceUrls: [],
89
108
  isLoading,
90
109
  };
91
110
  }
@@ -670,6 +670,21 @@ const messages = {
670
670
  referenceDeckNone: "Don't use one",
671
671
  referenceDeckStarredGroup: "Starred",
672
672
  referenceDeckOtherGroup: "Other decks",
673
+ referenceReviewTitle: "Review references",
674
+ referenceReviewDescription:
675
+ "Keep the default design system and reference deck unless you remove them. Search for another deck, import a file, or continue when you're ready.",
676
+ chooseAnotherDeck: "Choose another deck",
677
+ noMatchingDecks: "No matching decks found.",
678
+ googleSlidesReferenceTitle: "Google Slides",
679
+ googleSlidesReferenceConnect:
680
+ "Connect Google Drive to import a Slides deck.",
681
+ googleSlidesReferenceChoose: "Choose Google Slides deck",
682
+ googleSlidesReferencePicking: "Working...",
683
+ googleSlidesReferenceConnected:
684
+ "Connected. Choose a Google Slides deck to import as a reusable reference.",
685
+ googleSlidesReferenceUnavailable:
686
+ "Connect Google Drive and configure Picker to import a Google Slides deck.",
687
+ skipReferences: "Skip references",
673
688
  workspaceDefaultBadge: "Workspace default",
674
689
  setWorkspaceDefault: "Set as workspace default",
675
690
  clearWorkspaceDefault: "Clear workspace default",
@@ -0,0 +1,22 @@
1
+ export interface NewDeckReferenceSelection {
2
+ designSystemId: string | null;
3
+ referenceDeckId: string | null;
4
+ }
5
+
6
+ export function resolveNewDeckReferenceSelection(args: {
7
+ designSystemAuto: boolean;
8
+ selectedDesignSystemId: string | null;
9
+ defaultDesignSystemId: string | null;
10
+ referenceDeckAuto: boolean;
11
+ selectedReferenceDeckId: string | null;
12
+ defaultReferenceDeckId: string | null;
13
+ }): NewDeckReferenceSelection {
14
+ return {
15
+ designSystemId: args.designSystemAuto
16
+ ? args.defaultDesignSystemId
17
+ : args.selectedDesignSystemId,
18
+ referenceDeckId: args.referenceDeckAuto
19
+ ? args.defaultReferenceDeckId
20
+ : args.selectedReferenceDeckId,
21
+ };
22
+ }
@@ -286,7 +286,9 @@ export default function DeckEditor() {
286
286
  isNewDeckCreation: wasNewDeckCreation.current,
287
287
  slideCount,
288
288
  });
289
- const { designSystem } = useDeckDesignSystem(deck?.designSystemId);
289
+ const { designSystem, imageStyleReferenceUrls } = useDeckDesignSystem(
290
+ deck?.designSystemId,
291
+ );
290
292
  const commentsOpen = sidePanel === "comments";
291
293
 
292
294
  const {
@@ -1313,6 +1315,7 @@ export default function DeckEditor() {
1313
1315
  open={imageGenOpen}
1314
1316
  onOpenChange={setImageGenOpen}
1315
1317
  anchorRef={imageGenButtonRef}
1318
+ referenceImageUrls={imageStyleReferenceUrls}
1316
1319
  slideContext={
1317
1320
  currentSlide
1318
1321
  ? {
@@ -20,10 +20,7 @@ import { useLocation, useNavigate, useSearchParams } from "react-router";
20
20
  import { toast } from "sonner";
21
21
 
22
22
  import DeckCard from "@/components/deck/DeckCard";
23
- import {
24
- NewDeckReferenceStep,
25
- type NewDeckReferenceSelection,
26
- } from "@/components/editor/NewDeckReferenceStep";
23
+ import { NewDeckReferenceStep } from "@/components/editor/NewDeckReferenceStep";
27
24
  import PromptPopover, {
28
25
  uploadPromptFiles,
29
26
  type UploadedFile,
@@ -48,10 +45,10 @@ import { useWorkspaceDefaults } from "@/hooks/use-workspace-defaults";
48
45
  import { createDeckAgentMessage } from "@/lib/agent-visible-message";
49
46
  import { savePromptToComposerDraft } from "@/lib/composer-draft";
50
47
  import {
51
- readRecentReferences,
52
- rememberRecentReference,
53
- type RecentReference,
54
- } from "@/lib/recent-references";
48
+ resolveNewDeckReferenceSelection,
49
+ type NewDeckReferenceSelection,
50
+ } from "@/lib/new-deck-reference-selection";
51
+ import { rememberRecentReference } from "@/lib/recent-references";
55
52
 
56
53
  const NEW_DECK_DRAFT_SCOPE = "slides-new-deck";
57
54
  const PENDING_PROMPT_KEY = "slides:pending-deck-prompt";
@@ -239,18 +236,19 @@ export default function Index() {
239
236
  } | null>(null);
240
237
  const [showNewDeckReferenceStep, setShowNewDeckReferenceStep] =
241
238
  useState(false);
242
- const [recentReferences, setRecentReferences] = useState<RecentReference[]>(
243
- [],
244
- );
245
239
  const [referenceImporting, setReferenceImporting] = useState(false);
246
240
  const initialPromptConsumedRef = useRef(false);
247
241
  const [signInPromptHadFiles, setSignInPromptHadFiles] = useState(false);
248
- const [selectedDesignSystemId, setSelectedDesignSystemId] = useState("");
249
- const [selectedReferenceDeckId, setSelectedReferenceDeckId] = useState("");
242
+ const [selectedDesignSystemId, setSelectedDesignSystemId] = useState<
243
+ string | null
244
+ >(null);
245
+ const [selectedReferenceDeckId, setSelectedReferenceDeckId] = useState<
246
+ string | null
247
+ >(null);
250
248
  // True while the picker still reflects an auto-applied default rather than
251
249
  // an explicit user choice. `useWorkspaceDefaults()`/`useDesignSystems()`
252
250
  // resolve asynchronously, so the initial value set on dialog open can be a
253
- // placeholder ("none", or the first-loaded design system) these stay
251
+ // placeholder ("none", or the first-loaded design system) - these stay
254
252
  // true so the hydration effects below can overwrite it once the real
255
253
  // default arrives, and flip to false the moment the user picks explicitly.
256
254
  const designSystemAutoRef = useRef(true);
@@ -293,18 +291,11 @@ export default function Index() {
293
291
  [deckFilter, decks],
294
292
  );
295
293
  const rememberReference = useCallback(
296
- (reference: Omit<RecentReference, "lastUsedAt">) => {
297
- const result = rememberRecentReference(reference);
298
- if (result.readable) setRecentReferences(result.items);
299
- },
294
+ (reference: Parameters<typeof rememberRecentReference>[0]) =>
295
+ rememberRecentReference(reference),
300
296
  [],
301
297
  );
302
298
 
303
- useEffect(() => {
304
- const result = readRecentReferences();
305
- if (result.readable) setRecentReferences(result.items);
306
- }, []);
307
-
308
299
  useEffect(() => {
309
300
  if (initialDesignSystemId) {
310
301
  rememberReference({
@@ -322,6 +313,10 @@ export default function Index() {
322
313
  if (!initialPrompt || initialPromptConsumedRef.current) return;
323
314
  initialPromptConsumedRef.current = true;
324
315
  setPendingDeck({ prompt: initialPrompt, files: [] });
316
+ designSystemAutoRef.current = true;
317
+ referenceDeckAutoRef.current = true;
318
+ setSelectedDesignSystemId(initialDesignSystemId ?? null);
319
+ setSelectedReferenceDeckId(workspaceReferenceDeckId ?? null);
325
320
  setShowNewDeckReferenceStep(true);
326
321
  setSearchParams(
327
322
  (previous) => {
@@ -377,8 +372,8 @@ export default function Index() {
377
372
  anchorElRef.current = e.currentTarget;
378
373
  designSystemAutoRef.current = true;
379
374
  referenceDeckAutoRef.current = true;
380
- setSelectedDesignSystemId(initialDesignSystemId ?? "");
381
- setSelectedReferenceDeckId(workspaceReferenceDeckId ?? "none");
375
+ setSelectedDesignSystemId(initialDesignSystemId ?? null);
376
+ setSelectedReferenceDeckId(workspaceReferenceDeckId ?? null);
382
377
  setShowNewDeckPrompt(true);
383
378
  },
384
379
  [initialDesignSystemId, workspaceReferenceDeckId],
@@ -388,12 +383,10 @@ export default function Index() {
388
383
  (open: boolean, options: { clearInitialPrompt?: boolean } = {}) => {
389
384
  setShowNewDeckPrompt(open);
390
385
  if (!open) {
391
- setSelectedDesignSystemId("");
392
386
  if (options.clearInitialPrompt !== false) {
393
387
  setNewDeckInitialPrompt(null);
394
388
  setNewDeckRetryFiles([]);
395
389
  }
396
- setSelectedReferenceDeckId("none");
397
390
  }
398
391
  },
399
392
  [],
@@ -424,15 +417,15 @@ export default function Index() {
424
417
  // `useWorkspaceDefaults()` and `useDesignSystems()` load asynchronously and
425
418
  // can settle in either order, so `initialDesignSystemId` may go from a
426
419
  // provisional value to the real one after the picker already has a
427
- // selection guarding on `designSystemAutoRef` (instead of on whether
420
+ // selection - guarding on `designSystemAutoRef` (instead of on whether
428
421
  // `selectedDesignSystemId` is already set) lets that later value win as
429
422
  // long as the user hasn't explicitly chosen something.
430
423
  useEffect(() => {
431
424
  if (!showNewDeckPrompt || !designSystemAutoRef.current) return;
432
425
  if (initialDesignSystemId) {
433
426
  setSelectedDesignSystemId(initialDesignSystemId);
434
- } else if (designSystems.length > 0) {
435
- setSelectedDesignSystemId("none");
427
+ } else {
428
+ setSelectedDesignSystemId(null);
436
429
  }
437
430
  }, [initialDesignSystemId, designSystems.length, showNewDeckPrompt]);
438
431
 
@@ -441,7 +434,7 @@ export default function Index() {
441
434
  // resolves unless the user already picked a reference deck.
442
435
  useEffect(() => {
443
436
  if (!showNewDeckPrompt || !referenceDeckAutoRef.current) return;
444
- setSelectedReferenceDeckId(workspaceReferenceDeckId ?? "none");
437
+ setSelectedReferenceDeckId(workspaceReferenceDeckId ?? null);
445
438
  }, [workspaceReferenceDeckId, showNewDeckPrompt]);
446
439
 
447
440
  // Restore a prompt that was held back when the user wasn't signed in:
@@ -465,8 +458,8 @@ export default function Index() {
465
458
  }
466
459
  designSystemAutoRef.current = true;
467
460
  referenceDeckAutoRef.current = true;
468
- setSelectedDesignSystemId(initialDesignSystemId ?? "none");
469
- setSelectedReferenceDeckId(workspaceReferenceDeckId ?? "none");
461
+ setSelectedDesignSystemId(initialDesignSystemId ?? null);
462
+ setSelectedReferenceDeckId(workspaceReferenceDeckId ?? null);
470
463
  setShowNewDeckPrompt(true);
471
464
  }, [initialDesignSystemId, workspaceReferenceDeckId, session]);
472
465
 
@@ -490,10 +483,9 @@ export default function Index() {
490
483
  }, [location.state, navigate]);
491
484
 
492
485
  const handleCreateDeckBlank = () => {
493
- const selectedDesignSystem =
494
- selectedDesignSystemId && selectedDesignSystemId !== "none"
495
- ? designSystems.find((ds) => ds.id === selectedDesignSystemId)
496
- : undefined;
486
+ const selectedDesignSystem = selectedDesignSystemId
487
+ ? designSystems.find((ds) => ds.id === selectedDesignSystemId)
488
+ : undefined;
497
489
  let deck: ReturnType<typeof createDeck> | undefined;
498
490
  flushSync(() => {
499
491
  deck = createDeck(undefined, {
@@ -507,7 +499,7 @@ export default function Index() {
507
499
  const handleCreateDeckWithPrompt = async (
508
500
  prompt: string,
509
501
  files: UploadedFile[],
510
- referenceSelection: NewDeckReferenceSelection = {},
502
+ referenceSelection: Partial<NewDeckReferenceSelection> = {},
511
503
  ) => {
512
504
  // Pre-flight auth check. The add-deck action returns 403 silently
513
505
  // when unauthenticated, leaving the user stuck on a deck page that
@@ -523,18 +515,22 @@ export default function Index() {
523
515
  newDeckRetryFiles,
524
516
  files,
525
517
  );
518
+ const resolvedSelection = resolveNewDeckReferenceSelection({
519
+ designSystemAuto: designSystemAutoRef.current,
520
+ selectedDesignSystemId,
521
+ defaultDesignSystemId: initialDesignSystemId,
522
+ referenceDeckAuto: referenceDeckAutoRef.current,
523
+ selectedReferenceDeckId,
524
+ defaultReferenceDeckId: workspaceReferenceDeckId,
525
+ });
526
526
  const designSystemId =
527
527
  referenceSelection.designSystemId !== undefined
528
528
  ? referenceSelection.designSystemId
529
- : selectedDesignSystemId && selectedDesignSystemId !== "none"
530
- ? selectedDesignSystemId
531
- : null;
529
+ : resolvedSelection.designSystemId;
532
530
  const referenceDeckId =
533
531
  referenceSelection.referenceDeckId !== undefined
534
532
  ? referenceSelection.referenceDeckId
535
- : selectedReferenceDeckId && selectedReferenceDeckId !== "none"
536
- ? selectedReferenceDeckId
537
- : null;
533
+ : resolvedSelection.referenceDeckId;
538
534
  const selectedDesignSystem = designSystemId
539
535
  ? designSystems.find((ds) => ds.id === designSystemId)
540
536
  : undefined;
@@ -651,30 +647,64 @@ export default function Index() {
651
647
  [setNewDeckPromptOpen],
652
648
  );
653
649
 
654
- const handleReferenceSelect = useCallback(
655
- async (selection: NewDeckReferenceSelection) => {
656
- const pending = pendingDeck;
657
- if (!pending) return;
658
- if (selection.designSystemId) {
659
- rememberReference({
660
- id: selection.designSystemId,
661
- kind: "design-system",
662
- });
650
+ const handleReferenceDesignSystemSelect = useCallback(
651
+ (designSystemId: string | null) => {
652
+ designSystemAutoRef.current = false;
653
+ setSelectedDesignSystemId(designSystemId);
654
+ if (designSystemId) {
655
+ rememberReference({ id: designSystemId, kind: "design-system" });
663
656
  }
664
- if (selection.referenceDeckId) {
665
- rememberReference({ id: selection.referenceDeckId, kind: "deck" });
657
+ },
658
+ [rememberReference],
659
+ );
660
+
661
+ const handleReferenceDeckSelect = useCallback(
662
+ (referenceDeckId: string | null) => {
663
+ referenceDeckAutoRef.current = false;
664
+ setSelectedReferenceDeckId(referenceDeckId);
665
+ if (referenceDeckId) {
666
+ rememberReference({ id: referenceDeckId, kind: "deck" });
666
667
  }
667
- setShowNewDeckReferenceStep(false);
668
- setPendingDeck(null);
669
- await handleCreateDeckWithPrompt(
670
- pending.prompt,
671
- pending.files,
672
- selection,
673
- );
674
668
  },
675
- [handleCreateDeckWithPrompt, pendingDeck, rememberReference],
669
+ [rememberReference],
670
+ );
671
+
672
+ const handleGoogleSlidesImported = useCallback(
673
+ async ({ id, title }: { id: string; title: string }) => {
674
+ await reloadDecks();
675
+ rememberReference({ id, kind: "deck" });
676
+ referenceDeckAutoRef.current = false;
677
+ setSelectedReferenceDeckId(id);
678
+ toast.success(t("editorToolbar.importComplete"), {
679
+ description: title,
680
+ });
681
+ },
682
+ [reloadDecks, rememberReference, t],
676
683
  );
677
684
 
685
+ const handleReferenceContinue = useCallback(() => {
686
+ const pending = pendingDeck;
687
+ if (!pending) return;
688
+ setShowNewDeckReferenceStep(false);
689
+ setPendingDeck(null);
690
+ const selection = resolveNewDeckReferenceSelection({
691
+ designSystemAuto: designSystemAutoRef.current,
692
+ selectedDesignSystemId,
693
+ defaultDesignSystemId: initialDesignSystemId,
694
+ referenceDeckAuto: referenceDeckAutoRef.current,
695
+ selectedReferenceDeckId,
696
+ defaultReferenceDeckId: workspaceReferenceDeckId,
697
+ });
698
+ void handleCreateDeckWithPrompt(pending.prompt, pending.files, selection);
699
+ }, [
700
+ handleCreateDeckWithPrompt,
701
+ initialDesignSystemId,
702
+ pendingDeck,
703
+ selectedDesignSystemId,
704
+ selectedReferenceDeckId,
705
+ workspaceReferenceDeckId,
706
+ ]);
707
+
678
708
  const handleReferenceImport = useCallback(
679
709
  async (files: File[]) => {
680
710
  const pending = pendingDeck;
@@ -685,8 +715,9 @@ export default function Index() {
685
715
  const pptxReference = uploaded.find((file) =>
686
716
  file.originalName.toLowerCase().endsWith(".pptx"),
687
717
  );
688
- let referenceSelection: NewDeckReferenceSelection = {};
689
- let generationFiles = uploaded;
718
+ const pdfReference = uploaded.find((file) =>
719
+ file.originalName.toLowerCase().endsWith(".pdf"),
720
+ );
690
721
  if (pptxReference) {
691
722
  const imported = (await callAction("import-pptx", {
692
723
  filePath: pptxReference.path,
@@ -696,19 +727,57 @@ export default function Index() {
696
727
  }
697
728
  await reloadDecks();
698
729
  rememberReference({ id: imported.id, kind: "deck" });
699
- referenceSelection = {
700
- designSystemId: null,
701
- referenceDeckId: imported.id,
702
- };
703
- generationFiles = uploaded.filter((file) => file !== pptxReference);
730
+ referenceDeckAutoRef.current = false;
731
+ setSelectedReferenceDeckId(imported.id);
704
732
  }
705
- setShowNewDeckReferenceStep(false);
706
- setPendingDeck(null);
707
- await handleCreateDeckWithPrompt(
708
- pending.prompt,
709
- [...pending.files, ...generationFiles],
710
- referenceSelection,
733
+ if (!pptxReference && pdfReference) {
734
+ const referenceDeck = createDeck(undefined, {
735
+ noDefaultSlides: true,
736
+ });
737
+ const persisted = await ensureDeckPersisted(referenceDeck.id);
738
+ if (!persisted) {
739
+ deleteDeck(referenceDeck.id);
740
+ throw new Error("The PDF reference deck could not be saved.");
741
+ }
742
+ try {
743
+ const imported = (await callAction("import-file", {
744
+ filePath: pdfReference.path,
745
+ format: "pdf",
746
+ deckId: referenceDeck.id,
747
+ importIntoDeck: true,
748
+ })) as { imported?: unknown; deckId?: unknown };
749
+ if (
750
+ imported.imported !== true ||
751
+ imported.deckId !== referenceDeck.id
752
+ ) {
753
+ throw new Error("The PDF reference deck could not be imported.");
754
+ }
755
+ await reloadDecks();
756
+ rememberReference({ id: referenceDeck.id, kind: "deck" });
757
+ referenceDeckAutoRef.current = false;
758
+ setSelectedReferenceDeckId(referenceDeck.id);
759
+ } catch (error) {
760
+ deleteDeck(referenceDeck.id);
761
+ throw error;
762
+ }
763
+ }
764
+ const importedReference = pptxReference ?? pdfReference;
765
+ const generationFiles = uploaded.filter(
766
+ (file) => file !== importedReference,
711
767
  );
768
+ if (generationFiles.length > 0) {
769
+ setPendingDeck((current) =>
770
+ current
771
+ ? {
772
+ ...current,
773
+ files: mergeUploadedFilesForRetry(
774
+ current.files,
775
+ generationFiles,
776
+ ),
777
+ }
778
+ : current,
779
+ );
780
+ }
712
781
  } catch (error) {
713
782
  toast.error(t("editorToolbar.uploadFailed"), {
714
783
  description:
@@ -722,7 +791,9 @@ export default function Index() {
722
791
  },
723
792
  [
724
793
  callAction,
725
- handleCreateDeckWithPrompt,
794
+ createDeck,
795
+ deleteDeck,
796
+ ensureDeckPersisted,
726
797
  pendingDeck,
727
798
  reloadDecks,
728
799
  rememberReference,
@@ -769,7 +840,7 @@ export default function Index() {
769
840
  async (deck: Deck) => {
770
841
  try {
771
842
  // A private deck is unreadable to everyone else, so share it through
772
- // the audited sharing action first it owns org binding and collab
843
+ // the audited sharing action first - it owns org binding and collab
773
844
  // cache invalidation, which a direct visibility write here would skip.
774
845
  if (deck.visibility === "private") {
775
846
  await callAction("set-resource-visibility", {
@@ -1080,27 +1151,43 @@ export default function Index() {
1080
1151
  decks={decks}
1081
1152
  defaultDesignSystemId={initialDesignSystemId}
1082
1153
  defaultReferenceDeckId={workspaceReferenceDeckId}
1083
- recentReferences={recentReferences}
1084
- onSelect={(selection) => void handleReferenceSelect(selection)}
1154
+ selectedDesignSystemId={selectedDesignSystemId}
1155
+ selectedReferenceDeckId={selectedReferenceDeckId}
1156
+ onSelectDesignSystem={handleReferenceDesignSystemSelect}
1157
+ onSelectReferenceDeck={handleReferenceDeckSelect}
1085
1158
  onImport={handleReferenceImport}
1159
+ onGoogleSlidesImported={handleGoogleSlidesImported}
1160
+ onContinue={handleReferenceContinue}
1086
1161
  onSkip={handleReferenceSkip}
1087
1162
  importing={referenceImporting}
1088
- title={t("home.newDeckPromptTitle")}
1089
- description={t("home.referenceDeckPlaceholder")}
1163
+ title={t("home.referenceReviewTitle")}
1164
+ description={t("home.referenceReviewDescription")}
1090
1165
  designSystemLabel={t("home.designSystem")}
1091
1166
  referenceDeckLabel={t("home.referenceDeck")}
1092
- chooseDeckLabel={t("home.referenceDeckPlaceholder")}
1167
+ noneLabel={t("home.none")}
1093
1168
  importFileLabel={t("editorToolbar.importFile")}
1094
1169
  importingLabel={t("editorToolbar.importing")}
1095
- skipLabel={t("home.referenceDeckNone")}
1170
+ continueLabel={t("designSystemSetup.continueToGeneration")}
1171
+ skipLabel={t("home.skipReferences")}
1096
1172
  defaultSuffix={t("home.defaultSuffix")}
1097
1173
  starredLabel={t("home.referenceDeckStarredGroup")}
1098
1174
  otherDecksLabel={t("home.referenceDeckOtherGroup")}
1175
+ searchDecksLabel={t("root.searchDecks")}
1176
+ chooseAnotherDeckLabel={t("home.chooseAnotherDeck")}
1177
+ noMatchingDecksLabel={t("home.noMatchingDecks")}
1178
+ googleSlidesTitle={t("home.googleSlidesReferenceTitle")}
1179
+ googleSlidesConnectLabel={t("home.googleSlidesReferenceConnect")}
1180
+ googleSlidesChooseLabel={t("home.googleSlidesReferenceChoose")}
1181
+ googleSlidesPickingLabel={t("home.googleSlidesReferencePicking")}
1182
+ googleSlidesConnectedLabel={t("home.googleSlidesReferenceConnected")}
1183
+ googleSlidesUnavailableLabel={t(
1184
+ "home.googleSlidesReferenceUnavailable",
1185
+ )}
1099
1186
  promptNote={pendingDeck?.prompt}
1100
1187
  />
1101
1188
 
1102
1189
  {/* Sign-in required to create a deck. Shown when an unauthenticated
1103
- user submits a prompt the typed prompt is preserved in
1190
+ user submits a prompt - the typed prompt is preserved in
1104
1191
  sessionStorage and replayed into the composer after sign-in. */}
1105
1192
  <AlertDialog open={showSignInDialog} onOpenChange={setSignInDialogOpen}>
1106
1193
  <AlertDialogContent>
@@ -10,6 +10,8 @@ import {
10
10
  type Task,
11
11
  } from "@agent-native/core/a2a";
12
12
 
13
+ import { normalizeReferenceUrls } from "../../shared/api.js";
14
+
13
15
  /**
14
16
  * Slides never calls an image-generation API itself when the Assets app is
15
17
  * reachable: Assets owns brand libraries, presets, provenance, and the
@@ -92,7 +94,7 @@ function buildDelegationMessage(request: AssetsImageRequest): string {
92
94
  );
93
95
  }
94
96
 
95
- const references = request.referenceImageUrls?.filter(Boolean) ?? [];
97
+ const references = normalizeReferenceUrls(request.referenceImageUrls);
96
98
 
97
99
  return (
98
100
  `Generate ${request.count ?? 1} brand-consistent image candidate(s) ` +
@@ -101,7 +103,7 @@ function buildDelegationMessage(request: AssetsImageRequest): string {
101
103
  `Aspect ratio: ${request.aspectRatio ?? "16:9"}\n` +
102
104
  (hints.length ? `Slide context: ${hints.join(", ")}\n` : "") +
103
105
  (references.length
104
- ? `Condition the generation on these style reference images: ` +
106
+ ? `Condition the generation on these referenceImageUrls: ` +
105
107
  `${references.join(", ")}\n`
106
108
  : "") +
107
109
  `\nPick the best matching library via match-library if no libraryId is ` +
@@ -10,6 +10,19 @@ export interface DemoResponse {
10
10
 
11
11
  export const DEFAULT_STYLE_REFERENCE_URLS: string[] = [];
12
12
 
13
+ export function normalizeReferenceUrls(
14
+ urls: readonly string[] | null | undefined,
15
+ ): string[] {
16
+ const normalized: string[] = [];
17
+ for (const url of urls ?? []) {
18
+ if (typeof url !== "string") continue;
19
+ const trimmed = url.trim();
20
+ if (!trimmed || normalized.includes(trimmed)) continue;
21
+ normalized.push(trimmed);
22
+ }
23
+ return normalized;
24
+ }
25
+
13
26
  // --- Image Generation ---
14
27
 
15
28
  export type ImageGenModel = "gemini" | "openai" | "auto";
@@ -155,7 +168,7 @@ function normalizeSlideAnimation(
155
168
  : "slide-up";
156
169
 
157
170
  // When an explicit `elementIndex` is present, trust it. Otherwise derive
158
- // from the last segment of `elementPath` keeps the index correlated
171
+ // from the last segment of `elementPath` - keeps the index correlated
159
172
  // with the path's actual leaf so consumers that fall back to
160
173
  // `elementIndex` target the right element instead of silently defaulting
161
174
  // to slide-element 0 (which created an ambiguity between 'animation
@@ -32,6 +32,39 @@ Move behavior into shared toolkit primitives when it is:
32
32
  Keep behavior app-local when the abstraction would hide important domain
33
33
  language or make a simple app-specific workflow harder to understand.
34
34
 
35
+ ## Agent Surface Contract
36
+
37
+ The repeated app shell has two distinct navigation surfaces:
38
+
39
+ - The left rail owns domain destinations, settings, and chat history when the
40
+ app has a full-page chat route. Do not label a domain workflow as `Chat` just
41
+ because the app was scaffolded from the chat template.
42
+ - The right `AgentSidebar` owns contextual agent work. Domain buttons that call
43
+ `sendToAgentChat` should open it (`openSidebar: true`) so the user can see,
44
+ steer, and review the agent without losing the page they were using.
45
+ - Keep `/` or `/chat/*` as the full-page chat surface when the starter provides
46
+ one. Put domain workflows on named routes and wire the shell's route checks,
47
+ navigation labels, and handoffs to those routes together.
48
+ - Use familiar message or neutral action icons for agent affordances. Never use
49
+ sparkle, wand, magic, or robot icons as an AI label; the copy should carry the
50
+ meaning.
51
+ - Give the right rail a quiet visual boundary with a subtle surface shift,
52
+ divider, or both. The domain page and AgentSidebar should not collapse into a
53
+ single undifferentiated background.
54
+ - Any button labeled as agent work must use `sendToAgentChat` with bounded
55
+ context and `openSidebar: true`; local deterministic analysis should be
56
+ labeled as local, preview, or analyze. For original/generated review, stack
57
+ the source above the result by default and use side-by-side only for short,
58
+ highly scannable content.
59
+ - Standalone apps with `AgentSidebar` must resolve one assistant-ui runtime
60
+ context. Match direct assistant-ui pins to the installed core/toolkit peer
61
+ graph, use Vite dedupe/aliases when linked dependencies can split contexts,
62
+ and verify an AI handoff produces no stale-index console error.
63
+
64
+ Contextual agent UI is not a reason to expose every option at once. Start with
65
+ the domain task's primary action, reveal review or configuration only when the
66
+ current state needs it, and let the sidebar carry conversational depth.
67
+
35
68
  ## Discover Before Building
36
69
 
37
70
  Before creating an app-local version of repeated workspace or agent UI: