@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.
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/analytics/actions/gong-calls.ts +37 -17
- package/corpus/templates/analytics/app/lib/data-sources.ts +1 -1
- package/corpus/templates/analytics/server/lib/gong.ts +51 -2
- package/corpus/templates/assets/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/brain/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/brain/app/routes/settings.tsx +1 -1
- package/corpus/templates/brain/server/register-secrets.ts +1 -1
- package/corpus/templates/calendar/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/chat/AGENTS.md +11 -0
- package/corpus/templates/chat/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/chat/app/root.tsx +1 -1
- package/corpus/templates/chat/app/routes/agent.tsx +29 -13
- package/corpus/templates/chat/vite.config.ts +42 -0
- package/corpus/templates/clips/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/clips/app/components/library/empty-state.tsx +1 -3
- package/corpus/templates/clips/app/components/library/library-grid.tsx +2 -6
- package/corpus/templates/clips/app/components/library/library-layout.tsx +2 -6
- package/corpus/templates/clips/app/components/recorder/pre-record-panel.tsx +1 -3
- package/corpus/templates/clips/app/routes/bug-report.tsx +1 -8
- package/corpus/templates/clips/app/routes/import.tsx +1 -3
- package/corpus/templates/clips/changelog/2026-08-04-recording-buttons-are-now-text-only-for-a-cleaner-clips-inte.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-04-save-settings-now-matches-the-other-clips-settings-buttons.md +6 -0
- package/corpus/templates/clips/chrome-extension/src/styles.css +1 -0
- package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/crm/app/routes/settings.tsx +2 -2
- package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/design/actions/import-figma-clipboard.ts +1 -1
- package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/dispatch/changelog/2026-08-04-dispatch-keeps-connected-chats-out-of-local-history-by-defau.md +6 -0
- package/corpus/templates/factory/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/factory/README.md +1 -1
- package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +0 -2
- package/corpus/templates/mail/app/pages/SettingsPage.tsx +1 -1
- package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/slides/actions/generate-image-api.ts +15 -4
- package/corpus/templates/slides/actions/import-google-slides-reference.ts +83 -0
- package/corpus/templates/slides/actions/import-pptx.ts +134 -117
- package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +387 -0
- package/corpus/templates/slides/app/components/editor/ImageGenPanel.tsx +78 -48
- package/corpus/templates/slides/app/components/editor/NewDeckReferenceStep.tsx +377 -187
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +0 -1
- package/corpus/templates/slides/app/hooks/use-deck-design-system.ts +20 -1
- package/corpus/templates/slides/app/i18n/en-US.ts +15 -0
- package/corpus/templates/slides/app/lib/new-deck-reference-selection.ts +22 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +4 -1
- package/corpus/templates/slides/app/pages/Index.tsx +172 -85
- package/corpus/templates/slides/server/lib/assets-image-delegation.ts +4 -2
- package/corpus/templates/slides/shared/api.ts +14 -1
- package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +53 -1
- package/dist/chat-threads/schema.d.ts +57 -0
- package/dist/chat-threads/schema.js +3 -0
- package/dist/chat-threads/store.d.ts +26 -0
- package/dist/chat-threads/store.js +84 -6
- package/dist/client/AgentPanel.js +11 -5
- package/dist/client/ConnectBuilderCard.js +1 -1
- package/dist/client/agent-page/AgentEmptyState.d.ts +2 -1
- package/dist/client/agent-page/AgentEmptyState.js +6 -2
- package/dist/client/agent-page/AgentJobsTab.d.ts +3 -1
- package/dist/client/agent-page/AgentJobsTab.js +55 -44
- package/dist/client/agent-page/AgentTabFrame.d.ts +2 -1
- package/dist/client/agent-page/AgentTabFrame.js +4 -2
- package/dist/client/agent-page/AgentTabsPage.js +12 -8
- package/dist/client/agent-page/AgentWorkspaceContent.d.ts +10 -0
- package/dist/client/agent-page/AgentWorkspaceContent.js +110 -0
- package/dist/client/agent-page/AutomationDetailsDialog.js +1 -1
- package/dist/client/chat/run-recovery.js +3 -3
- package/dist/client/error-format.js +1 -1
- package/dist/client/integrations/IntegrationsPanel.d.ts +1 -0
- package/dist/client/integrations/IntegrationsPanel.js +149 -5
- package/dist/client/onboarding/FirstRunOnboarding.js +130 -15
- package/dist/client/onboarding/index.d.ts +1 -1
- package/dist/client/onboarding/index.js +1 -1
- package/dist/client/onboarding/use-onboarding.js +12 -2
- package/dist/client/onboarding/use-preview-mode.d.ts +4 -0
- package/dist/client/onboarding/use-preview-mode.js +9 -0
- package/dist/client/resources/BuiltinCapabilityDetail.js +2 -2
- package/dist/client/resources/ResourceTree.d.ts +4 -1
- package/dist/client/resources/ResourceTree.js +13 -8
- package/dist/client/resources/ResourcesPanel.js +7 -3
- package/dist/client/resources/mcp-integration-catalog.js +4 -4
- package/dist/client/resources/use-mcp-servers.js +6 -6
- package/dist/client/settings/AgentsSection.js +15 -16
- package/dist/client/settings/AutomationsSection.js +1 -1
- package/dist/client/settings/DemoModeSection.js +1 -1
- package/dist/client/settings/SettingsPanel.d.ts +3 -1
- package/dist/client/settings/SettingsPanel.js +284 -88
- package/dist/client/settings/SettingsRow.js +1 -1
- package/dist/client/settings/SettingsSection.d.ts +6 -4
- package/dist/client/settings/SettingsSection.js +6 -6
- package/dist/client/settings/SettingsTabsPage.js +47 -25
- package/dist/client/settings/VoiceTranscriptionSection.d.ts +3 -1
- package/dist/client/settings/VoiceTranscriptionSection.js +20 -8
- package/dist/client/settings/agent-settings-search.d.ts +1 -1
- package/dist/client/settings/agent-settings-search.js +8 -8
- package/dist/client/transcription/BuilderTranscriptionCta.js +2 -2
- package/dist/client/use-chat-threads.d.ts +9 -0
- package/dist/client/use-chat-threads.js +22 -6
- package/dist/collab/routes.d.ts +1 -1
- package/dist/integrations/google-docs-poller.js +9 -1
- package/dist/integrations/webhook-handler.js +11 -1
- package/dist/jobs/scheduler.d.ts +4 -1
- package/dist/jobs/scheduler.js +34 -9
- package/dist/localization/default-messages.js +40 -40
- package/dist/mcp-client/oauth-routes.js +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
- package/dist/provider-api/actions/provider-api.d.ts +15 -15
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/onboarding.js +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-chat/browser-team-tools.d.ts +1 -0
- package/dist/server/agent-chat/browser-team-tools.js +1 -0
- package/dist/server/agent-chat-plugin.js +14 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-teams.d.ts +2 -0
- package/dist/server/agent-teams.js +2 -0
- package/dist/server/workspace-provider-oauth.js +1 -1
- package/dist/setup-connections/onboarding.js +2 -2
- package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +53 -1
- package/dist/templates/chat/AGENTS.md +11 -0
- package/dist/templates/chat/app/components/layout/Layout.tsx +1 -1
- package/dist/templates/chat/app/root.tsx +1 -1
- package/dist/templates/chat/app/routes/agent.tsx +29 -13
- package/dist/templates/chat/vite.config.ts +42 -0
- package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +53 -1
- package/dist/templates/default/AGENTS.md +11 -0
- package/dist/templates/default/vite.config.ts +42 -0
- package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +53 -1
- package/dist/templates/workspace-core/AGENTS.md +11 -0
- package/dist/templates/workspace-root/AGENTS.md +14 -0
- package/dist/vite/client.js +56 -0
- package/package.json +2 -2
- package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +53 -1
- package/src/templates/chat/AGENTS.md +11 -0
- package/src/templates/chat/app/components/layout/Layout.tsx +1 -1
- package/src/templates/chat/app/root.tsx +1 -1
- package/src/templates/chat/app/routes/agent.tsx +29 -13
- package/src/templates/chat/vite.config.ts +42 -0
- package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/src/templates/default/.agents/skills/frontend-design/SKILL.md +53 -1
- package/src/templates/default/AGENTS.md +11 -0
- package/src/templates/default/vite.config.ts +42 -0
- package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +53 -1
- package/src/templates/workspace-core/AGENTS.md +11 -0
- package/src/templates/workspace-root/AGENTS.md +14 -0
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { useActionQuery } from "@agent-native/core/client/hooks";
|
|
2
2
|
|
|
3
|
-
import
|
|
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(
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
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)
|
|
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:
|
|
297
|
-
|
|
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 ??
|
|
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
|
|
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
|
|
435
|
-
setSelectedDesignSystemId(
|
|
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 ??
|
|
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 ??
|
|
469
|
-
setSelectedReferenceDeckId(workspaceReferenceDeckId ??
|
|
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
|
-
|
|
495
|
-
|
|
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
|
-
:
|
|
530
|
-
? selectedDesignSystemId
|
|
531
|
-
: null;
|
|
529
|
+
: resolvedSelection.designSystemId;
|
|
532
530
|
const referenceDeckId =
|
|
533
531
|
referenceSelection.referenceDeckId !== undefined
|
|
534
532
|
? referenceSelection.referenceDeckId
|
|
535
|
-
:
|
|
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
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
if (
|
|
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
|
-
|
|
665
|
-
|
|
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
|
-
[
|
|
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
|
-
|
|
689
|
-
|
|
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
|
-
|
|
700
|
-
|
|
701
|
-
referenceDeckId: imported.id,
|
|
702
|
-
};
|
|
703
|
-
generationFiles = uploaded.filter((file) => file !== pptxReference);
|
|
730
|
+
referenceDeckAutoRef.current = false;
|
|
731
|
+
setSelectedReferenceDeckId(imported.id);
|
|
704
732
|
}
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
1084
|
-
|
|
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.
|
|
1089
|
-
description={t("home.
|
|
1163
|
+
title={t("home.referenceReviewTitle")}
|
|
1164
|
+
description={t("home.referenceReviewDescription")}
|
|
1090
1165
|
designSystemLabel={t("home.designSystem")}
|
|
1091
1166
|
referenceDeckLabel={t("home.referenceDeck")}
|
|
1092
|
-
|
|
1167
|
+
noneLabel={t("home.none")}
|
|
1093
1168
|
importFileLabel={t("editorToolbar.importFile")}
|
|
1094
1169
|
importingLabel={t("editorToolbar.importing")}
|
|
1095
|
-
|
|
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
|
|
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
|
|
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
|
|
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`
|
|
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:
|