@agent-native/core 0.149.5 → 0.151.0
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/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +83 -45
- package/corpus/templates/analytics/changelog/2026-08-11-analytics-dashboards-keep-the-selected-tab-when-reopened.md +6 -0
- package/corpus/templates/assets/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/brain/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/calendar/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/clips/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/clips/changelog/2026-08-11-clips-recovers-from-transient-updates-and-avoids-macos-priva.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +32 -176
- package/corpus/templates/clips/desktop/src/lib/updater.ts +52 -37
- package/corpus/templates/clips/desktop/src/styles.css +1 -166
- package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +2 -0
- package/corpus/templates/clips/desktop/src-tauri/Info.plist +4 -0
- package/corpus/templates/clips/desktop/src-tauri/src/eventkit.rs +28 -1
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +2 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_speech.rs +48 -1
- package/corpus/templates/clips/desktop/src-tauri/src/permission_status.rs +3 -0
- package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +5 -0
- package/corpus/templates/clips/server/plugins/auth.ts +3 -0
- package/corpus/templates/content/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/content/actions/_document-discovery-query.ts +127 -0
- package/corpus/templates/content/actions/list-documents.ts +189 -198
- package/corpus/templates/content/actions/search-documents.ts +95 -24
- package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +2 -1
- package/corpus/templates/content/app/hooks/use-documents.ts +84 -6
- package/corpus/templates/content/shared/api.ts +10 -0
- package/corpus/templates/design/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +5 -1
- package/corpus/templates/design/changelog/2026-08-11-design-agent-prompts-copy-successfully-in-the-desktop-app.md +6 -0
- package/corpus/templates/dispatch/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/dispatch/app/global.css +2 -2
- package/corpus/templates/dispatch/changelog/2026-08-10-desktop-workspace-sign-in.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-08-11-dispatch-no-longer-shows-the-generic-chat-starter-among-defa.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-08-11-integrations-and-scheduled-work-open-as-first-class-electron-pages.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-08-11-sidebar-text-is-slightly-easier-to-read-in-light-and-dark-mo.md +6 -0
- package/corpus/templates/dispatch/server/lib/identity-sso.ts +57 -31
- package/corpus/templates/dispatch/server/plugins/feature-flags.ts +5 -0
- package/corpus/templates/dispatch/server/plugins/identity-sso.ts +82 -33
- package/corpus/templates/dispatch/server/plugins/org-apps-directory.ts +7 -15
- package/corpus/templates/dispatch/server/plugins/setup-dispatch.ts +9 -1
- package/corpus/templates/dispatch/shared/feature-flags.ts +15 -0
- package/corpus/templates/factory/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/forms/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/forms/.agents/skills/form-responses/SKILL.md +8 -7
- package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/forms/app/hooks/use-forms.ts +8 -1
- package/corpus/templates/forms/changelog/2026-08-11-fixed-public-forms-so-conditional-questions-stay-hidden-unti.md +6 -0
- package/corpus/templates/forms/server/handlers/submissions.ts +2 -1
- package/corpus/templates/forms/server/lib/public-form-ssr.ts +37 -2
- package/corpus/templates/forms/shared/page-url.ts +54 -0
- package/corpus/templates/forms/shared/types.ts +4 -4
- package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/mail/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/plan/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/slides/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +5 -0
- package/corpus/templates/slides/actions/add-slide.ts +0 -27
- package/corpus/templates/slides/actions/import-file.ts +28 -9
- package/corpus/templates/slides/actions/view-screen.ts +4 -4
- package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +8 -1
- package/corpus/templates/slides/app/components/editor/AiEditingMarker.tsx +25 -0
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +43 -48
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +9 -6
- package/corpus/templates/slides/app/components/editor/GeneratingSlidePreview.tsx +1 -9
- package/corpus/templates/slides/app/components/editor/ImageDropPromptPopover.tsx +2 -0
- package/corpus/templates/slides/app/components/editor/ImageOverlay.tsx +0 -26
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +904 -217
- package/corpus/templates/slides/app/components/editor/canvas-interactions/index.ts +1 -0
- package/corpus/templates/slides/app/components/editor/canvas-interactions/slides-canvas-adapter.ts +11 -0
- package/corpus/templates/slides/app/components/editor/inline-edit-session.ts +16 -0
- package/corpus/templates/slides/app/components/editor/slide-object-interactions.ts +22 -6
- package/corpus/templates/slides/app/components/editor/style-clipboard.ts +61 -0
- package/corpus/templates/slides/app/components/layout/Layout.tsx +26 -2
- package/corpus/templates/slides/app/components/ui/context-menu.tsx +1 -0
- package/corpus/templates/slides/app/context/DeckContext.tsx +75 -25
- package/corpus/templates/slides/app/global.css +1 -1
- package/corpus/templates/slides/app/i18n/en-US.ts +6 -1
- package/corpus/templates/slides/app/lib/create-deck-generation.ts +1 -1
- package/corpus/templates/slides/app/lib/image-drop-to-agent.ts +12 -12
- package/corpus/templates/slides/app/lib/slide-agent-context.ts +52 -0
- package/corpus/templates/slides/app/lib/slide-image-replacement.ts +61 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +55 -116
- package/corpus/templates/slides/app/pages/Index.tsx +28 -3
- package/corpus/templates/slides/changelog/2026-08-11-agent-chat-now-follows-the-current-slide-and-selection.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-deck-titles-now-use-slide-content-instead-of-placeholder-filenames.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-history-now-opens-from-the-deck-overflow-menu.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-images-can-be-dropped-directly-onto-slides-and-resized-or-re.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-new-decks-now-transition-directly-to-a-full-page-editor-load.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-selected-slide-layers-can-be-nudged-precisely-with-arrow-key.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-slides-can-copy-and-paste-element-styles-with-cmd-option-c-v.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-slides-shows-one-compact-ai-marker-and-keeps-your-current-sl.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-text-edits-preserve-slide-layout-when-no-changes-are-made.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-the-style-toolbar-now-uses-the-full-available-width.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-11-undo-and-redo-now-move-one-visible-slide-state-at-a-time.md +6 -0
- package/corpus/templates/slides/server/lib/chat-attachments.ts +6 -2
- package/corpus/templates/slides/shared/deck-title.ts +56 -0
- package/corpus/templates/tasks/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +5 -0
- package/dist/agent/run-store.js +6 -1
- package/dist/agent/thread-data-builder.js +19 -44
- package/dist/agent/types.d.ts +13 -0
- package/dist/catalog.json +1 -0
- package/dist/cli/create.js +1 -1
- package/dist/client/AssistantChat.js +58 -10
- package/dist/client/FileStorageSetupCard.d.ts +6 -0
- package/dist/client/FileStorageSetupCard.js +18 -0
- package/dist/client/NewWorkspaceAppFlow.js +10 -0
- package/dist/client/agent-chat-adapter.js +87 -11
- package/dist/client/agent-chat.d.ts +1 -1
- package/dist/client/agent-chat.js +8 -3
- package/dist/client/chat/attachment-adapters.js +10 -0
- package/dist/client/chat/message-components.d.ts +4 -1
- package/dist/client/chat/message-components.js +37 -13
- package/dist/client/chat/tool-call-display.js +14 -0
- package/dist/client/chat-first/apps-rail.d.ts +1 -1
- package/dist/client/chat-first/apps-rail.js +6 -6
- package/dist/client/chat-first/copy.js +1 -0
- package/dist/client/chat-first/types.d.ts +1 -0
- package/dist/client/extensions/EmbeddedExtension.js +1 -1
- package/dist/client/extensions/ExtensionViewer.js +1 -1
- package/dist/client/extensions/InlineExtensionFrame.js +1 -1
- package/dist/client/onboarding/FirstRunOnboarding.js +17 -2
- package/dist/client/settings/FileStorageSettingsForm.d.ts +2 -0
- package/dist/client/settings/FileStorageSettingsForm.js +113 -0
- package/dist/client/settings/SettingsPanel.js +2 -1
- package/dist/client/sse-event-processor.js +21 -0
- package/dist/extensions/actions.js +2 -2
- package/dist/extensions/html-shell.js +3 -1
- package/dist/file-upload/pre-upload-attachments.d.ts +15 -10
- package/dist/file-upload/pre-upload-attachments.js +68 -24
- package/dist/file-upload/registry.d.ts +4 -5
- package/dist/file-upload/registry.js +7 -14
- package/dist/file-upload/s3.d.ts +9 -0
- package/dist/file-upload/s3.js +168 -0
- package/dist/file-upload/types.d.ts +3 -3
- package/dist/file-upload/types.js +2 -2
- package/dist/onboarding/app-profile.js +23 -1
- package/dist/onboarding/default-steps.js +69 -0
- package/dist/onboarding/types.d.ts +2 -0
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
- package/dist/provider-api/actions/provider-api.d.ts +8 -8
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/agent-chat/browser-team-tools.js +20 -0
- package/dist/server/agent-chat-plugin.js +12 -3
- package/dist/server/auth.js +45 -21
- package/dist/server/better-auth-instance.d.ts +2 -0
- package/dist/server/better-auth-instance.js +2 -2
- package/dist/server/core-routes-plugin.d.ts +1 -0
- package/dist/server/core-routes-plugin.js +26 -16
- package/dist/server/identity-sso-store.d.ts +3 -0
- package/dist/server/identity-sso-store.js +45 -0
- package/dist/server/identity-sso.d.ts +20 -10
- package/dist/server/identity-sso.js +79 -31
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -1
- package/dist/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +5 -0
- package/dist/templates/default/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +5 -0
- package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +24 -1
- package/dist/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -2
- package/dist/templates/workspace-core/.agents/skills/extensions/references/api.md +1 -1
- package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +5 -0
- package/dist/templates/workspace-core/.agents/skills/generative-ui/SKILL.md +3 -1
- package/docs/content/authentication.mdx +27 -0
- package/docs/content/cross-app-sso.mdx +38 -8
- package/docs/content/extensions.mdx +15 -15
- package/docs/content/file-uploads.mdx +10 -12
- package/docs/content/generative-ui.mdx +6 -1
- package/package.json +2 -2
- package/src/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +5 -0
- package/src/templates/default/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/src/templates/default/.agents/skills/frontend-design/SKILL.md +5 -0
- package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +24 -1
- package/src/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +28 -0
- package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -2
- package/src/templates/workspace-core/.agents/skills/extensions/references/api.md +1 -1
- package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +5 -0
- package/src/templates/workspace-core/.agents/skills/generative-ui/SKILL.md +3 -1
|
@@ -28,7 +28,10 @@ import {
|
|
|
28
28
|
DEFAULT_ASPECT_RATIO,
|
|
29
29
|
type AspectRatio,
|
|
30
30
|
} from "../shared/aspect-ratios.js";
|
|
31
|
-
import {
|
|
31
|
+
import {
|
|
32
|
+
isOpaqueDeckTitle,
|
|
33
|
+
resolveImportedDeckTitle,
|
|
34
|
+
} from "../shared/deck-title.js";
|
|
32
35
|
import { readUserUploadedFile } from "./_uploaded-files.js";
|
|
33
36
|
import { withDeckLock } from "./patch-deck.js";
|
|
34
37
|
|
|
@@ -182,17 +185,18 @@ export default defineAction({
|
|
|
182
185
|
presentation.slides[0].heightEmu,
|
|
183
186
|
)
|
|
184
187
|
: undefined;
|
|
185
|
-
await appendDeckSlides(
|
|
188
|
+
const importedTitle = await appendDeckSlides(
|
|
186
189
|
deckId,
|
|
187
190
|
title,
|
|
188
191
|
slides,
|
|
189
192
|
"import-file:pptx",
|
|
190
193
|
aspectRatio,
|
|
191
194
|
sourceImport,
|
|
195
|
+
pptxResults[0]?.sourceText,
|
|
192
196
|
);
|
|
193
197
|
return {
|
|
194
198
|
format: "pptx",
|
|
195
|
-
title,
|
|
199
|
+
title: importedTitle,
|
|
196
200
|
slideCount: slides.length,
|
|
197
201
|
theme: presentation.theme,
|
|
198
202
|
deckId,
|
|
@@ -241,10 +245,18 @@ export default defineAction({
|
|
|
241
245
|
layout: "content",
|
|
242
246
|
notes: "",
|
|
243
247
|
}));
|
|
244
|
-
await appendDeckSlides(
|
|
248
|
+
const importedTitle = await appendDeckSlides(
|
|
249
|
+
deckId,
|
|
250
|
+
title,
|
|
251
|
+
slides,
|
|
252
|
+
"import-file:docx",
|
|
253
|
+
undefined,
|
|
254
|
+
undefined,
|
|
255
|
+
doc.text,
|
|
256
|
+
);
|
|
245
257
|
return {
|
|
246
258
|
format: "docx",
|
|
247
|
-
title,
|
|
259
|
+
title: importedTitle,
|
|
248
260
|
sectionCount: doc.sections.length,
|
|
249
261
|
slideCount: slides.length,
|
|
250
262
|
textLength: doc.text.length,
|
|
@@ -520,18 +532,19 @@ async function importPdfPagesWithFidelity(args: {
|
|
|
520
532
|
slides: imported.map((entry) => entry.snapshot),
|
|
521
533
|
});
|
|
522
534
|
|
|
523
|
-
await appendDeckSlides(
|
|
535
|
+
const importedTitle = await appendDeckSlides(
|
|
524
536
|
deckId,
|
|
525
537
|
title,
|
|
526
538
|
slides,
|
|
527
539
|
"import-file:pdf",
|
|
528
540
|
aspectRatio,
|
|
529
541
|
sourceImport,
|
|
542
|
+
imported[0]?.snapshot.text,
|
|
530
543
|
);
|
|
531
544
|
|
|
532
545
|
return {
|
|
533
546
|
format: "pdf",
|
|
534
|
-
title,
|
|
547
|
+
title: importedTitle,
|
|
535
548
|
pageCount: slides.length,
|
|
536
549
|
slideCount: slides.length,
|
|
537
550
|
aspectRatio,
|
|
@@ -674,7 +687,8 @@ async function appendDeckSlides(
|
|
|
674
687
|
source: string,
|
|
675
688
|
aspectRatio?: AspectRatio,
|
|
676
689
|
sourceImport?: ReturnType<typeof buildSourceImportMetadata>,
|
|
677
|
-
|
|
690
|
+
titleSource?: unknown,
|
|
691
|
+
): Promise<string> {
|
|
678
692
|
await assertAccess("deck", deckId, "editor");
|
|
679
693
|
|
|
680
694
|
// Read-modify-write under the shared per-deck lock used by patch-deck /
|
|
@@ -682,6 +696,7 @@ async function appendDeckSlides(
|
|
|
682
696
|
// with another import or an editor/agent slide mutation on the same deck
|
|
683
697
|
// could read stale data and clobber the other write when both save the
|
|
684
698
|
// whole decks.data blob back.
|
|
699
|
+
let resolvedTitle = title;
|
|
685
700
|
const now = await withDeckLock(deckId, async () => {
|
|
686
701
|
const db = getDb();
|
|
687
702
|
const existing = await db
|
|
@@ -706,7 +721,10 @@ async function appendDeckSlides(
|
|
|
706
721
|
// had no slides yet, otherwise resizing the canvas mid-deck would distort
|
|
707
722
|
// every slide already on it.
|
|
708
723
|
const hadExistingSlides = previousSlides.length > 0;
|
|
709
|
-
const nextTitle = hadExistingSlides
|
|
724
|
+
const nextTitle = hadExistingSlides
|
|
725
|
+
? (existing[0].title ?? title)
|
|
726
|
+
: resolveImportedDeckTitle(title, titleSource ?? slides[0]?.content);
|
|
727
|
+
resolvedTitle = nextTitle;
|
|
710
728
|
const nextSourceImport = sourceImport
|
|
711
729
|
? mergeSourceImportMetadata(
|
|
712
730
|
sourceImportForDeck(previousData.sourceImport),
|
|
@@ -736,6 +754,7 @@ async function appendDeckSlides(
|
|
|
736
754
|
|
|
737
755
|
notifyClients(deckId);
|
|
738
756
|
await writeAppState("refresh-signal", { ts: now, source });
|
|
757
|
+
return resolvedTitle;
|
|
739
758
|
}
|
|
740
759
|
|
|
741
760
|
function safeParseDeckData(raw: string): Record<string, unknown> {
|
|
@@ -162,12 +162,12 @@ export default defineAction({
|
|
|
162
162
|
style?: Record<string, unknown>;
|
|
163
163
|
}>;
|
|
164
164
|
} | null;
|
|
165
|
-
if (
|
|
166
|
-
selection &&
|
|
167
|
-
(!selection.slideId || selection.slideId === currentSlide?.id)
|
|
168
|
-
) {
|
|
165
|
+
if (selection && currentSlide && selection.slideId === currentSlide.id) {
|
|
169
166
|
lines.push(``);
|
|
170
167
|
lines.push(`### Current visual selection`);
|
|
168
|
+
lines.push(
|
|
169
|
+
`selectionSlideId: ${selection.slideId} (matches currentSlideId)`,
|
|
170
|
+
);
|
|
171
171
|
lines.push(`mode: ${selection.mode ?? "unknown"}`);
|
|
172
172
|
lines.push(`activeTool: ${selection.activeTool ?? "select"}`);
|
|
173
173
|
if (Array.isArray(selection.items) && selection.items.length > 0) {
|
|
@@ -581,8 +581,15 @@ export function DesignSystemSetup({
|
|
|
581
581
|
}. Present a summary for review.`,
|
|
582
582
|
);
|
|
583
583
|
|
|
584
|
+
const message =
|
|
585
|
+
parts[0] ?? "Set up a design system from the selected sources.";
|
|
586
|
+
const contextParts = parts.slice(1);
|
|
584
587
|
openAgentSidebar();
|
|
585
|
-
sendToAgentChat({
|
|
588
|
+
sendToAgentChat({
|
|
589
|
+
message,
|
|
590
|
+
context: contextParts.join("\n"),
|
|
591
|
+
submit: true,
|
|
592
|
+
});
|
|
586
593
|
toast(t("designSystemSetup.generationStarted"), {
|
|
587
594
|
description: t("designSystemSetup.generationStartedDescription"),
|
|
588
595
|
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useT } from "@agent-native/core/client/i18n";
|
|
2
|
+
import { DEFAULT_AGENT_IDENTITY } from "@agent-native/toolkit/collab-ui";
|
|
3
|
+
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
5
|
+
|
|
6
|
+
/** The single compact marker used for every AI-editing state in Slides. */
|
|
7
|
+
export function AiEditingMarker({ className }: { className?: string }) {
|
|
8
|
+
const t = useT();
|
|
9
|
+
const label = t("raw.aiEditing");
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<span
|
|
13
|
+
aria-label={label}
|
|
14
|
+
className={cn(
|
|
15
|
+
"inline-flex size-5 shrink-0 items-center justify-center rounded-full text-[9px] font-semibold leading-none text-primary-foreground",
|
|
16
|
+
className,
|
|
17
|
+
)}
|
|
18
|
+
role="img"
|
|
19
|
+
style={{ backgroundColor: DEFAULT_AGENT_IDENTITY.color }}
|
|
20
|
+
title={label}
|
|
21
|
+
>
|
|
22
|
+
AI
|
|
23
|
+
</span>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -2,13 +2,13 @@ import {
|
|
|
2
2
|
agentNativePath,
|
|
3
3
|
appBasePath,
|
|
4
4
|
} from "@agent-native/core/client/api-path";
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
import type {
|
|
6
|
+
AttributedRecentEdit,
|
|
7
|
+
CollabUser,
|
|
8
8
|
} from "@agent-native/core/client/collab";
|
|
9
9
|
import { useAvatarUrl } from "@agent-native/core/client/hooks";
|
|
10
10
|
import { useT } from "@agent-native/core/client/i18n";
|
|
11
|
-
import {
|
|
11
|
+
import { DEFAULT_AGENT_IDENTITY } from "@agent-native/toolkit/collab-ui";
|
|
12
12
|
import {
|
|
13
13
|
useSortable,
|
|
14
14
|
SortableContext,
|
|
@@ -22,6 +22,7 @@ import { useCallback } from "react";
|
|
|
22
22
|
|
|
23
23
|
import SlideRenderer from "@/components/deck/SlideRenderer";
|
|
24
24
|
import type { SlideOverflowInfo } from "@/components/deck/SlideRenderer";
|
|
25
|
+
import { AiEditingMarker } from "@/components/editor/AiEditingMarker";
|
|
25
26
|
import GeneratingSlidePreview from "@/components/editor/GeneratingSlidePreview";
|
|
26
27
|
import {
|
|
27
28
|
Tooltip,
|
|
@@ -43,14 +44,14 @@ interface EditorSidebarProps {
|
|
|
43
44
|
readOnly?: boolean;
|
|
44
45
|
/** Presence map: slideId → list of users currently viewing that slide */
|
|
45
46
|
slidePresence?: Map<string, CollabUser[]>;
|
|
46
|
-
/** Lingering recent edits
|
|
47
|
+
/** Lingering recent edits used to show the compact AI marker. */
|
|
47
48
|
recentEdits?: AttributedRecentEdit[];
|
|
48
49
|
/** Deck aspect ratio (defaults to 16:9 when omitted) */
|
|
49
50
|
aspectRatio?: AspectRatio;
|
|
50
51
|
/** Active deck design system used by slide content tokens. */
|
|
51
52
|
designSystem?: DesignSystemData;
|
|
52
53
|
/** The next slide while the agent is preparing its HTML. */
|
|
53
|
-
generatingSlide?: { index: number
|
|
54
|
+
generatingSlide?: { index: number };
|
|
54
55
|
generatingSlideSelected?: boolean;
|
|
55
56
|
onSelectGeneratingSlide?: () => void;
|
|
56
57
|
}
|
|
@@ -72,6 +73,13 @@ function slideIdFromEdit(edit: AttributedRecentEdit): string | null {
|
|
|
72
73
|
return null;
|
|
73
74
|
}
|
|
74
75
|
|
|
76
|
+
function isAgentPresenceUser(user: CollabUser): boolean {
|
|
77
|
+
return (
|
|
78
|
+
user.email.trim().toLowerCase() ===
|
|
79
|
+
DEFAULT_AGENT_IDENTITY.email.trim().toLowerCase()
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
75
83
|
/** Small presence avatar circle with hover card showing name + email */
|
|
76
84
|
function PresenceAvatarTip({
|
|
77
85
|
user,
|
|
@@ -143,6 +151,7 @@ function SortableSlideThumb({
|
|
|
143
151
|
designSystem,
|
|
144
152
|
onOverflowChange,
|
|
145
153
|
readOnly = false,
|
|
154
|
+
aiEditing = false,
|
|
146
155
|
}: {
|
|
147
156
|
slide: Slide;
|
|
148
157
|
index: number;
|
|
@@ -154,6 +163,7 @@ function SortableSlideThumb({
|
|
|
154
163
|
aspectRatio?: AspectRatio;
|
|
155
164
|
designSystem?: DesignSystemData;
|
|
156
165
|
onOverflowChange: (info: SlideOverflowInfo) => void;
|
|
166
|
+
aiEditing?: boolean;
|
|
157
167
|
}) {
|
|
158
168
|
const t = useT();
|
|
159
169
|
const {
|
|
@@ -175,6 +185,11 @@ function SortableSlideThumb({
|
|
|
175
185
|
};
|
|
176
186
|
|
|
177
187
|
const thumbDims = getAspectRatioDims(aspectRatio);
|
|
188
|
+
const agentPresent = presenceUsers.some(isAgentPresenceUser);
|
|
189
|
+
const humanPresenceUsers = presenceUsers.filter(
|
|
190
|
+
(user) => !isAgentPresenceUser(user),
|
|
191
|
+
);
|
|
192
|
+
const showAiMarker = aiEditing || agentPresent;
|
|
178
193
|
|
|
179
194
|
return (
|
|
180
195
|
<div ref={setNodeRef} style={style}>
|
|
@@ -189,7 +204,7 @@ function SortableSlideThumb({
|
|
|
189
204
|
aria-current={isActive ? "true" : undefined}
|
|
190
205
|
data-slide-thumbnail-id={slide.id}
|
|
191
206
|
className={`w-full text-left flex items-start gap-1.5 p-1.5 rounded-lg transition-[background-color,box-shadow] duration-150 ${
|
|
192
|
-
isActive ? "bg-accent
|
|
207
|
+
isActive ? "bg-accent" : ""
|
|
193
208
|
} ${
|
|
194
209
|
readOnly ? "" : "cursor-grab active:cursor-grabbing"
|
|
195
210
|
} focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1`}
|
|
@@ -199,14 +214,17 @@ function SortableSlideThumb({
|
|
|
199
214
|
<span className="block text-center text-[10px] font-medium leading-5 text-muted-foreground/70">
|
|
200
215
|
{index + 1}
|
|
201
216
|
</span>
|
|
202
|
-
{
|
|
217
|
+
{(showAiMarker || humanPresenceUsers.length > 0) && (
|
|
203
218
|
<div className="absolute left-1/2 top-5 z-10 flex -translate-x-1/2 flex-col items-center gap-1">
|
|
204
|
-
{
|
|
219
|
+
{showAiMarker && (
|
|
220
|
+
<AiEditingMarker className="size-4 text-[8px]" />
|
|
221
|
+
)}
|
|
222
|
+
{humanPresenceUsers.slice(0, 4).map((u, i) => (
|
|
205
223
|
<PresenceAvatarTip key={i} user={u} size={14} />
|
|
206
224
|
))}
|
|
207
|
-
{
|
|
225
|
+
{humanPresenceUsers.length > 4 && (
|
|
208
226
|
<span className="flex h-4 min-w-4 items-center justify-center rounded-full bg-muted px-1 text-[8px] font-medium leading-none text-muted-foreground ring-1 ring-black/40">
|
|
209
|
-
+{
|
|
227
|
+
+{humanPresenceUsers.length - 4}
|
|
210
228
|
</span>
|
|
211
229
|
)}
|
|
212
230
|
</div>
|
|
@@ -224,8 +242,8 @@ function SortableSlideThumb({
|
|
|
224
242
|
className="w-full overflow-hidden rounded border"
|
|
225
243
|
style={{
|
|
226
244
|
borderColor:
|
|
227
|
-
|
|
228
|
-
?
|
|
245
|
+
humanPresenceUsers.length > 0
|
|
246
|
+
? humanPresenceUsers[0].color + "66"
|
|
229
247
|
: "rgba(255,255,255,0.06)",
|
|
230
248
|
aspectRatio: `${thumbDims.width} / ${thumbDims.height}`,
|
|
231
249
|
contentVisibility: "auto",
|
|
@@ -248,14 +266,12 @@ function GeneratingSlideSkeleton({
|
|
|
248
266
|
index,
|
|
249
267
|
aspectRatio,
|
|
250
268
|
designSystem,
|
|
251
|
-
content,
|
|
252
269
|
selected,
|
|
253
270
|
onSelect,
|
|
254
271
|
}: {
|
|
255
272
|
index: number;
|
|
256
273
|
aspectRatio?: AspectRatio;
|
|
257
274
|
designSystem?: DesignSystemData;
|
|
258
|
-
content?: string | null;
|
|
259
275
|
selected?: boolean;
|
|
260
276
|
onSelect?: () => void;
|
|
261
277
|
}) {
|
|
@@ -263,20 +279,20 @@ function GeneratingSlideSkeleton({
|
|
|
263
279
|
return (
|
|
264
280
|
<button
|
|
265
281
|
type="button"
|
|
266
|
-
className={`relative block w-full rounded-lg text-left transition-
|
|
267
|
-
selected ? "
|
|
282
|
+
className={`relative block w-full rounded-lg text-left transition-colors ${
|
|
283
|
+
selected ? "bg-accent" : ""
|
|
268
284
|
}`}
|
|
269
285
|
aria-label={t("editorSidebar.generatingSlide")}
|
|
270
286
|
aria-current={selected ? "true" : undefined}
|
|
271
287
|
onClick={onSelect}
|
|
272
288
|
>
|
|
273
289
|
<div className="flex w-full items-start gap-1.5 rounded-lg p-1.5">
|
|
274
|
-
<span className="flex-shrink-0
|
|
290
|
+
<span className="flex flex-shrink-0 flex-col items-center gap-1 text-center text-[10px] font-medium leading-5 text-muted-foreground/70">
|
|
275
291
|
{index + 1}
|
|
292
|
+
<AiEditingMarker className="size-4 text-[8px]" />
|
|
276
293
|
</span>
|
|
277
294
|
<div className="flex-1 min-w-0">
|
|
278
295
|
<GeneratingSlidePreview
|
|
279
|
-
content={content}
|
|
280
296
|
aspectRatio={aspectRatio}
|
|
281
297
|
designSystem={designSystem}
|
|
282
298
|
thumbnail
|
|
@@ -302,7 +318,6 @@ export default function EditorSidebar({
|
|
|
302
318
|
onSelectGeneratingSlide,
|
|
303
319
|
}: EditorSidebarProps) {
|
|
304
320
|
const slideButtonRefs = useRef(new Map<string, HTMLButtonElement>());
|
|
305
|
-
const thumbScrollRef = useRef<HTMLDivElement>(null);
|
|
306
321
|
const measurementsRef = useRef(
|
|
307
322
|
new Map<
|
|
308
323
|
string,
|
|
@@ -310,6 +325,12 @@ export default function EditorSidebar({
|
|
|
310
325
|
>(),
|
|
311
326
|
);
|
|
312
327
|
const writeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
328
|
+
const aiEditedSlideIds = new Set(
|
|
329
|
+
(recentEdits ?? [])
|
|
330
|
+
.filter((edit) => edit.isAgent)
|
|
331
|
+
.map(slideIdFromEdit)
|
|
332
|
+
.filter((slideId): slideId is string => Boolean(slideId)),
|
|
333
|
+
);
|
|
313
334
|
|
|
314
335
|
const writeDeckFitState = useCallback(() => {
|
|
315
336
|
const currentSlideIds = new Set(slides.map((slide) => slide.id));
|
|
@@ -383,19 +404,6 @@ export default function EditorSidebar({
|
|
|
383
404
|
};
|
|
384
405
|
}, []);
|
|
385
406
|
|
|
386
|
-
// Resolve a recent-edit descriptor (`slides.<id>`) to the on-screen rect of
|
|
387
|
-
// that slide's thumbnail button, relative to the scroll container, so the
|
|
388
|
-
// shared RecentEditHighlights overlay can draw a fading "AI edited" ring.
|
|
389
|
-
const resolveThumbRect = useCallback(
|
|
390
|
-
(edit: AttributedRecentEdit): DOMRect | null => {
|
|
391
|
-
const slideId = slideIdFromEdit(edit);
|
|
392
|
-
if (!slideId) return null;
|
|
393
|
-
const node = slideButtonRefs.current.get(slideId);
|
|
394
|
-
if (!node) return null;
|
|
395
|
-
return node.getBoundingClientRect();
|
|
396
|
-
},
|
|
397
|
-
[],
|
|
398
|
-
);
|
|
399
407
|
const registerSlideButton = useCallback(
|
|
400
408
|
(slideId: string, node: HTMLButtonElement | null) => {
|
|
401
409
|
if (node) {
|
|
@@ -446,10 +454,7 @@ export default function EditorSidebar({
|
|
|
446
454
|
|
|
447
455
|
return (
|
|
448
456
|
<div className="flex h-full min-h-0 w-48 flex-shrink-0 flex-col bg-background sm:w-52">
|
|
449
|
-
<div
|
|
450
|
-
ref={thumbScrollRef}
|
|
451
|
-
className="relative min-h-0 flex-1 space-y-1 overflow-y-auto overscroll-contain p-2"
|
|
452
|
-
>
|
|
457
|
+
<div className="relative min-h-0 flex-1 space-y-1 overflow-y-auto overscroll-contain p-2">
|
|
453
458
|
<SortableContext
|
|
454
459
|
items={slides.map((s) => s.id)}
|
|
455
460
|
strategy={verticalListSortingStrategy}
|
|
@@ -466,6 +471,7 @@ export default function EditorSidebar({
|
|
|
466
471
|
presenceUsers={slidePresence?.get(slide.id) ?? []}
|
|
467
472
|
aspectRatio={aspectRatio}
|
|
468
473
|
designSystem={designSystem}
|
|
474
|
+
aiEditing={aiEditedSlideIds.has(slide.id)}
|
|
469
475
|
onOverflowChange={(info) =>
|
|
470
476
|
handleSlideOverflowChange(slide, info)
|
|
471
477
|
}
|
|
@@ -477,21 +483,10 @@ export default function EditorSidebar({
|
|
|
477
483
|
index={generatingSlide.index}
|
|
478
484
|
aspectRatio={aspectRatio}
|
|
479
485
|
designSystem={designSystem}
|
|
480
|
-
content={generatingSlide.content}
|
|
481
486
|
selected={generatingSlideSelected}
|
|
482
487
|
onSelect={onSelectGeneratingSlide}
|
|
483
488
|
/>
|
|
484
489
|
)}
|
|
485
|
-
{/* Fading "AI edited" highlights over the thumbnails of just-edited
|
|
486
|
-
slides (the component handles the fade + name/color tag). */}
|
|
487
|
-
{recentEdits && recentEdits.length > 0 && (
|
|
488
|
-
<RecentEditHighlights
|
|
489
|
-
edits={recentEdits}
|
|
490
|
-
resolveRect={resolveThumbRect}
|
|
491
|
-
containerRef={thumbScrollRef}
|
|
492
|
-
outlineOnly
|
|
493
|
-
/>
|
|
494
|
-
)}
|
|
495
490
|
</div>
|
|
496
491
|
</div>
|
|
497
492
|
);
|
|
@@ -590,12 +590,12 @@ export default function EditorToolbar({
|
|
|
590
590
|
value={deckTitle}
|
|
591
591
|
onChange={(e) => onTitleChange(e.target.value)}
|
|
592
592
|
style={{ width: `${titleInputWidth}px` }}
|
|
593
|
-
className="min-w-0 max-w-[500px]
|
|
593
|
+
className="min-w-0 max-w-[500px] shrink-0 bg-transparent text-sm font-medium text-foreground/90 outline-none focus:text-foreground"
|
|
594
594
|
spellCheck={false}
|
|
595
595
|
/>
|
|
596
596
|
|
|
597
597
|
{/* Spacer */}
|
|
598
|
-
<div className="
|
|
598
|
+
<div className="w-2 shrink-0" />
|
|
599
599
|
|
|
600
600
|
<div
|
|
601
601
|
ref={onWideContextToolbarSlotChange}
|
|
@@ -769,6 +769,13 @@ export default function EditorToolbar({
|
|
|
769
769
|
</>
|
|
770
770
|
)}
|
|
771
771
|
|
|
772
|
+
<DropdownMenuSeparator />
|
|
773
|
+
<DropdownMenuGroup>
|
|
774
|
+
<DropdownMenuItem onSelect={onShowHistory}>
|
|
775
|
+
<IconHistory className="size-4" />
|
|
776
|
+
{t("editorToolbar.savedVersions")}
|
|
777
|
+
</DropdownMenuItem>
|
|
778
|
+
</DropdownMenuGroup>
|
|
772
779
|
<DropdownMenuSeparator />
|
|
773
780
|
<ExportMenu
|
|
774
781
|
ref={exportMenuRef}
|
|
@@ -794,10 +801,6 @@ export default function EditorToolbar({
|
|
|
794
801
|
? t("editorToolbar.importing")
|
|
795
802
|
: t("editorToolbar.importFile")}
|
|
796
803
|
</DropdownMenuItem>
|
|
797
|
-
<DropdownMenuItem onSelect={onShowHistory}>
|
|
798
|
-
<IconHistory className="size-4" />
|
|
799
|
-
{t("editorToolbar.savedVersions")}
|
|
800
|
-
</DropdownMenuItem>
|
|
801
804
|
<DropdownMenuSeparator />
|
|
802
805
|
<DropdownMenuItem
|
|
803
806
|
onSelect={() => setTheme(isDark ? "light" : "dark")}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { useT } from "@agent-native/core/client/i18n";
|
|
2
|
-
import { IconLoader2 } from "@tabler/icons-react";
|
|
3
2
|
|
|
4
3
|
import SlideRenderer from "@/components/deck/SlideRenderer";
|
|
5
4
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
@@ -47,7 +46,7 @@ export default function GeneratingSlidePreview({
|
|
|
47
46
|
return (
|
|
48
47
|
<div
|
|
49
48
|
className={cn(
|
|
50
|
-
"relative w-full overflow-hidden rounded-lg border border-
|
|
49
|
+
"relative w-full overflow-hidden rounded-lg border border-border bg-muted/20",
|
|
51
50
|
className,
|
|
52
51
|
)}
|
|
53
52
|
style={{ aspectRatio: cssRatio }}
|
|
@@ -65,13 +64,6 @@ export default function GeneratingSlidePreview({
|
|
|
65
64
|
) : (
|
|
66
65
|
<SlideLoadingArtwork />
|
|
67
66
|
)}
|
|
68
|
-
<div className="pointer-events-none absolute left-2 top-2 inline-flex items-center gap-1.5 rounded-full border border-primary/70 px-2 py-1 text-[11px] font-medium text-primary">
|
|
69
|
-
<span className="size-1.5 rounded-full bg-primary" aria-hidden="true" />
|
|
70
|
-
{t("raw.aiEditing")}
|
|
71
|
-
</div>
|
|
72
|
-
<div className="absolute right-2 top-2 rounded-full bg-background/80 p-1.5 text-muted-foreground shadow-sm">
|
|
73
|
-
<IconLoader2 className="size-3.5 animate-spin" aria-hidden="true" />
|
|
74
|
-
</div>
|
|
75
67
|
</div>
|
|
76
68
|
);
|
|
77
69
|
}
|
|
@@ -159,12 +159,14 @@ export default function ImageDropPromptPopover({
|
|
|
159
159
|
if (payload.kind === "hosted") {
|
|
160
160
|
sendToAgentChat({
|
|
161
161
|
message: payload.message,
|
|
162
|
+
context: payload.context,
|
|
162
163
|
submit: true,
|
|
163
164
|
referenceImagePaths: payload.referenceImagePaths,
|
|
164
165
|
});
|
|
165
166
|
} else {
|
|
166
167
|
sendToAgentChat({
|
|
167
168
|
message: payload.message,
|
|
169
|
+
context: payload.context,
|
|
168
170
|
submit: true,
|
|
169
171
|
images: payload.images,
|
|
170
172
|
});
|
|
@@ -3,10 +3,8 @@ import {
|
|
|
3
3
|
IconPhoto,
|
|
4
4
|
IconFolderOpen,
|
|
5
5
|
IconUpload,
|
|
6
|
-
IconSearch,
|
|
7
6
|
IconMaximize,
|
|
8
7
|
IconMinimize,
|
|
9
|
-
IconGlobe,
|
|
10
8
|
} from "@tabler/icons-react";
|
|
11
9
|
import { useEffect, useRef } from "react";
|
|
12
10
|
import { createPortal } from "react-dom";
|
|
@@ -17,8 +15,6 @@ interface ImageOverlayProps {
|
|
|
17
15
|
onGenerate: () => void;
|
|
18
16
|
onLibrary: () => void;
|
|
19
17
|
onUpload: () => void;
|
|
20
|
-
onSearch: () => void;
|
|
21
|
-
onLogo: () => void;
|
|
22
18
|
onToggleObjectFit: () => void;
|
|
23
19
|
onClose: () => void;
|
|
24
20
|
}
|
|
@@ -29,8 +25,6 @@ export default function ImageOverlay({
|
|
|
29
25
|
onGenerate,
|
|
30
26
|
onLibrary,
|
|
31
27
|
onUpload,
|
|
32
|
-
onSearch,
|
|
33
|
-
onLogo,
|
|
34
28
|
onToggleObjectFit,
|
|
35
29
|
onClose,
|
|
36
30
|
}: ImageOverlayProps) {
|
|
@@ -106,26 +100,6 @@ export default function ImageOverlay({
|
|
|
106
100
|
<IconUpload className="w-3.5 h-3.5 text-muted-foreground" />
|
|
107
101
|
Upload
|
|
108
102
|
</button>
|
|
109
|
-
<button
|
|
110
|
-
onClick={() => {
|
|
111
|
-
onSearch();
|
|
112
|
-
onClose();
|
|
113
|
-
}}
|
|
114
|
-
className="image-overlay-btn"
|
|
115
|
-
>
|
|
116
|
-
<IconSearch className="w-3.5 h-3.5 text-muted-foreground" />
|
|
117
|
-
Search
|
|
118
|
-
</button>
|
|
119
|
-
<button
|
|
120
|
-
onClick={() => {
|
|
121
|
-
onLogo();
|
|
122
|
-
onClose();
|
|
123
|
-
}}
|
|
124
|
-
className="image-overlay-btn"
|
|
125
|
-
>
|
|
126
|
-
<IconGlobe className="w-3.5 h-3.5 text-muted-foreground" />
|
|
127
|
-
Logo
|
|
128
|
-
</button>
|
|
129
103
|
<div className="mx-1.5 border-t border-border" />
|
|
130
104
|
<button onClick={onToggleObjectFit} className="image-overlay-btn">
|
|
131
105
|
{objectFit === "cover" ? (
|