@agent-native/core-corpus 0.201.0-nightly-20261005153421 → 0.201.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/security/SKILL.md +9 -2
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +14 -4
- package/corpus/templates/analytics/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/analytics/CHANGELOG.md +6 -0
- package/corpus/templates/analytics/README.md +2 -2
- package/corpus/templates/analytics/changelog/2026-10-02-events-with-a-very-long-name-app-or-page-path-no-longer-caus.md +6 -0
- package/corpus/templates/analytics/package.json +1 -0
- package/corpus/templates/analytics/server/handlers/first-party-analytics.ts +9 -19
- package/corpus/templates/analytics/server/handlers/session-replay.ts +34 -47
- package/corpus/templates/analytics/server/lib/first-party-analytics-rollups.ts +9 -6
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +57 -36
- package/corpus/templates/analytics/server/lib/indexed-text.ts +53 -0
- package/corpus/templates/analytics/server/lib/request-errors.ts +73 -0
- package/corpus/templates/analytics/server/lib/session-event-index.ts +6 -16
- package/corpus/templates/analytics/server/lib/session-replay.ts +12 -2
- package/corpus/templates/analytics/server/plugins/auth.ts +2 -1
- package/corpus/templates/analytics/server/plugins/otel.ts +6 -0
- package/corpus/templates/assets/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/assets/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/assets/CHANGELOG.md +7 -0
- package/corpus/templates/assets/README.md +2 -2
- package/corpus/templates/assets/package.json +1 -0
- package/corpus/templates/assets/server/plugins/auth.ts +2 -1
- package/corpus/templates/assets/server/plugins/otel.ts +6 -0
- package/corpus/templates/brain/.agents/skills/brain/RUNBOOK.md +2 -1
- package/corpus/templates/brain/.agents/skills/brain/SKILL.md +5 -4
- package/corpus/templates/brain/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/brain/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/brain/CHANGELOG.md +6 -0
- package/corpus/templates/brain/README.md +12 -8
- package/corpus/templates/brain/changelog/2026-10-05-private-slack-channels-are-searchable-org-wide.md +6 -0
- package/corpus/templates/brain/package.json +1 -0
- package/corpus/templates/brain/server/lib/audiences.ts +1 -98
- package/corpus/templates/brain/server/lib/connectors.ts +2 -166
- package/corpus/templates/brain/server/plugins/otel.ts +6 -0
- package/corpus/templates/calendar/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/calendar/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/calendar/CHANGELOG.md +7 -0
- package/corpus/templates/calendar/README.md +2 -2
- package/corpus/templates/calendar/package.json +1 -0
- package/corpus/templates/calendar/server/plugins/auth.ts +2 -1
- package/corpus/templates/calendar/server/plugins/otel.ts +6 -0
- package/corpus/templates/chat/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/chat/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/chat/README.md +2 -2
- package/corpus/templates/clips/.agents/skills/ai-video-tools/SKILL.md +9 -0
- package/corpus/templates/clips/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/clips/CHANGELOG.md +24 -0
- package/corpus/templates/clips/README.md +2 -2
- package/corpus/templates/clips/actions/lib/audio-chunk-list.ts +23 -0
- package/corpus/templates/clips/actions/lib/audio-only-transcription.ts +187 -292
- package/corpus/templates/clips/actions/lib/chunked-transcription.ts +151 -0
- package/corpus/templates/clips/actions/lib/recording-audio-source.ts +191 -0
- package/corpus/templates/clips/actions/request-transcript.ts +81 -135
- package/corpus/templates/clips/actions/search-recordings.ts +19 -5
- package/corpus/templates/clips/app/components/clips-command-menu.tsx +5 -0
- package/corpus/templates/clips/app/components/library/library-layout.tsx +3 -1
- package/corpus/templates/clips/app/components/library/search-bar.tsx +5 -0
- package/corpus/templates/clips/app/hooks/use-library.ts +1 -0
- package/corpus/templates/clips/app/lib/local-recording-upload.ts +13 -6
- package/corpus/templates/clips/app/lib/recording-section.ts +1 -1
- package/corpus/templates/clips/app/routes/_app.r.$recordingId.tsx +7 -5
- package/corpus/templates/clips/app/routes/record.tsx +16 -6
- package/corpus/templates/clips/changelog/2026-10-02-long-uploads-an-hour-or-more-now-transcribe-reliably-instead.md +6 -0
- package/corpus/templates/clips/changelog/2026-10-05-confirming-discard-recording-now-returns-you-to-your-library.md +6 -0
- package/corpus/templates/clips/changelog/2026-10-05-discarding-a-recording-now-removes-its-failed-upload-card-fr.md +6 -0
- package/corpus/templates/clips/changelog/2026-10-05-discarding-a-recovered-recording-no-longer-warns-that-it-s-o.md +6 -0
- package/corpus/templates/clips/changelog/2026-10-05-search-results-identify-recordings-in-trash-and-open-them-wi.md +6 -0
- package/corpus/templates/clips/package.json +1 -0
- package/corpus/templates/clips/server/lib/builder-cdn.ts +5 -0
- package/corpus/templates/clips/server/lib/builder-media-compression.ts +2 -2
- package/corpus/templates/clips/server/plugins/auth.ts +2 -1
- package/corpus/templates/clips/server/plugins/otel.ts +6 -0
- package/corpus/templates/clips/shared/transcript-failure.ts +5 -0
- package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +8 -2
- package/corpus/templates/content/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/content/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/content/CHANGELOG.md +41 -0
- package/corpus/templates/content/README.md +2 -2
- package/corpus/templates/content/actions/_database-navigation.ts +523 -344
- package/corpus/templates/content/actions/_database-row-mutation.ts +44 -10
- package/corpus/templates/content/actions/_database-setup-discovery.ts +9 -3
- package/corpus/templates/content/actions/_database-utils.ts +299 -271
- package/corpus/templates/content/actions/_property-utils.ts +293 -190
- package/corpus/templates/content/actions/_relation-values.ts +3 -1
- package/corpus/templates/content/actions/get-content-database.ts +1 -0
- package/corpus/templates/content/actions/query-content-database-items.ts +32 -5
- package/corpus/templates/content/actions/set-document-property.ts +17 -11
- package/corpus/templates/content/app/components/editor/DocumentBlockFields.tsx +21 -6
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +127 -43
- package/corpus/templates/content/app/components/editor/DocumentEditorSkeleton.tsx +159 -50
- package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +12 -28
- package/corpus/templates/content/app/components/editor/PageDraftRecovery.tsx +6 -1
- package/corpus/templates/content/app/components/editor/TableHoverControls.tsx +139 -70
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +16 -1
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +180 -75
- package/corpus/templates/content/app/components/editor/database/DatabaseViewSkeleton.tsx +76 -0
- package/corpus/templates/content/app/components/editor/database/navigation-state.ts +60 -2
- package/corpus/templates/content/app/components/editor/database/sidebar.tsx +41 -42
- package/corpus/templates/content/app/components/editor/document-editor-layout.ts +18 -0
- package/corpus/templates/content/app/components/editor/extensions/NotionExtensions.tsx +11 -3
- package/corpus/templates/content/app/components/editor/suggestions/draft-session.ts +15 -7
- package/corpus/templates/content/app/components/editor/suggestions/model.ts +13 -0
- package/corpus/templates/content/app/components/editor/suggestions/read-only-blocks.ts +136 -0
- package/corpus/templates/content/app/components/editor/table-view.ts +73 -0
- package/corpus/templates/content/app/components/layout/ContentStartupShell.tsx +1 -1
- package/corpus/templates/content/app/components/layout/Layout.tsx +5 -1
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +57 -16
- package/corpus/templates/content/app/components/sidebar/MovePageDialog.tsx +4 -4
- package/corpus/templates/content/app/components/sidebar/SidebarNavigationRow.tsx +34 -10
- package/corpus/templates/content/app/global.css +16 -8
- package/corpus/templates/content/app/hooks/content-action-refresh.ts +14 -13
- package/corpus/templates/content/app/hooks/use-content-database.ts +72 -9
- package/corpus/templates/content/app/hooks/use-content-personal-navigation.ts +7 -3
- package/corpus/templates/content/app/hooks/use-documents.ts +27 -0
- package/corpus/templates/content/app/i18n-data.ts +3 -2
- package/corpus/templates/content/app/lib/content-landing.ts +3 -31
- package/corpus/templates/content/app/lib/files-navigation.ts +182 -10
- package/corpus/templates/content/app/lib/files-root-hint.ts +20 -32
- package/corpus/templates/content/app/lib/page-startup-hints.ts +108 -0
- package/corpus/templates/content/app/lib/private-link-redirect.ts +25 -0
- package/corpus/templates/content/app/lib/sidebar-layout-hint.ts +34 -1
- package/corpus/templates/content/app/lib/startup-timing.ts +2 -0
- package/corpus/templates/content/app/root.tsx +3 -1
- package/corpus/templates/content/app/routes/_app.home.tsx +10 -19
- package/corpus/templates/content/app/routes/p.$id.tsx +23 -5
- package/corpus/templates/content/changelog/2026-10-02-a-page-link-you-cant-open-now-says-so-instead-of-opening-an.md +6 -0
- package/corpus/templates/content/changelog/2026-10-02-after-a-refresh-the-files-sidebar-shows-the-open-page-s-fold.md +6 -0
- package/corpus/templates/content/changelog/2026-10-02-large-collections-open-faster.md +6 -0
- package/corpus/templates/content/changelog/2026-10-02-pages-stay-inside-the-window-at-every-width-long-inline-code.md +6 -0
- package/corpus/templates/content/changelog/2026-10-02-pages-with-open-comments-and-collections-with-sorted-or-filt.md +6 -0
- package/corpus/templates/content/changelog/2026-10-02-suggest-edits-works-on-pages-written-by-agents-including-pag.md +6 -0
- package/corpus/templates/content/changelog/2026-10-02-while-you-suggest-edits-tables-and-other-blocks-that-suggest.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-collection-view-context-now-survives-quick-page-changes-when.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-collection-views-keep-their-saved-rows-accurate-during-refre.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-exact-saved-view-links-keep-collection-retry-available.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-expanding-a-files-folder-now-shares-one-navigation-read-acro.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-files-navigation-retries-temporary-failures-consistently.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-shared-page-owners-keep-edit-and-manage-controls-in-files-an.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-tagging-an-ai-in-a-comment-works-again-instead-of-failing-ri.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-the-home-loading-shell-keeps-the-layout-of-your-last-opened-.md +6 -0
- package/corpus/templates/content/changelog/2026-10-05-typing-and-a-space-or-inserting-a-toggle-or-callout-no-longe.md +6 -0
- package/corpus/templates/content/docs/product/capabilities/content.workspace.session-restore.md +4 -1
- package/corpus/templates/content/e2e/playwright.config.ts +1 -1
- package/corpus/templates/content/package.json +2 -1
- package/corpus/templates/content/scripts/seed-perf-database.mjs +600 -0
- package/corpus/templates/content/scripts/trace-startup.mjs +25 -3
- package/corpus/templates/content/server/db/index.ts +1 -1
- package/corpus/templates/content/server/lib/suggested-edits.ts +23 -26
- package/corpus/templates/content/server/plugins/auth.ts +2 -1
- package/corpus/templates/content/server/plugins/otel.ts +6 -0
- package/corpus/templates/content/shared/api.ts +17 -0
- package/corpus/templates/content/shared/suggestion-diff.ts +124 -38
- package/corpus/templates/content/shared/suggestion-formatting.ts +134 -3
- package/corpus/templates/crm/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/crm/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/crm/package.json +1 -0
- package/corpus/templates/crm/server/plugins/otel.ts +6 -0
- package/corpus/templates/design/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/design/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/design/CHANGELOG.md +41 -0
- package/corpus/templates/design/README.md +2 -2
- package/corpus/templates/design/actions/list-designs.ts +11 -4
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +110 -32
- package/corpus/templates/design/app/components/design/multi-screen/cross-screen-drop.ts +28 -0
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +1 -0
- package/corpus/templates/design/app/components/home/DesignHomeLibrary.tsx +79 -0
- package/corpus/templates/design/app/components/layout/Header.tsx +2 -4
- package/corpus/templates/design/app/components/ui/tabs.tsx +59 -1
- package/corpus/templates/design/app/global.css +1 -34
- package/corpus/templates/design/app/i18n/en-US.ts +4 -0
- package/corpus/templates/design/app/lib/design-filter.ts +4 -2
- package/corpus/templates/design/app/pages/Index.tsx +91 -59
- package/corpus/templates/design/app/pages/design-editor/commands/cross-screen-element-drop.ts +58 -17
- package/corpus/templates/design/changelog/2026-10-01-filter-designs-by-owner.md +6 -0
- package/corpus/templates/design/changelog/2026-10-03-layers-dropped-into-visible-canvas-space-beyond-a-screen-now.md +6 -0
- package/corpus/templates/design/changelog/2026-10-03-visible-screen-overflow-no-longer-routes-drops-to-the-canvas.md +6 -0
- package/corpus/templates/design/changelog/2026-10-05-the-recent-tab-shows-loading-placeholders-until-your-designs.md +6 -0
- package/corpus/templates/design/package.json +1 -0
- package/corpus/templates/design/server/plugins/auth.ts +2 -1
- package/corpus/templates/design/server/plugins/otel.ts +6 -0
- package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/dispatch/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/dispatch/README.md +2 -2
- package/corpus/templates/dispatch/package.json +1 -0
- package/corpus/templates/dispatch/server/plugins/otel.ts +6 -0
- package/corpus/templates/dispatch/server/plugins/setup-dispatch.ts +2 -1
- package/corpus/templates/factory/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/factory/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/factory/package.json +1 -0
- package/corpus/templates/factory/server/plugins/otel.ts +6 -0
- package/corpus/templates/forms/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/forms/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/forms/README.md +2 -2
- package/corpus/templates/forms/package.json +1 -0
- package/corpus/templates/forms/server/plugins/auth.ts +2 -1
- package/corpus/templates/forms/server/plugins/otel.ts +6 -0
- package/corpus/templates/mail/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/mail/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/mail/CHANGELOG.md +6 -0
- package/corpus/templates/mail/README.md +2 -2
- package/corpus/templates/mail/package.json +1 -0
- package/corpus/templates/mail/server/plugins/auth.ts +2 -1
- package/corpus/templates/mail/server/plugins/otel.ts +6 -0
- package/corpus/templates/plan/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/plan/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/plan/CHANGELOG.md +1 -0
- package/corpus/templates/plan/README.md +2 -2
- package/corpus/templates/plan/package.json +1 -0
- package/corpus/templates/plan/server/plugins/auth.ts +2 -1
- package/corpus/templates/plan/server/plugins/otel.ts +6 -0
- package/corpus/templates/slides/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/slides/.agents/skills/storing-data/SKILL.md +12 -7
- package/corpus/templates/slides/CHANGELOG.md +23 -0
- package/corpus/templates/slides/README.md +2 -2
- package/corpus/templates/slides/actions/list-decks.ts +11 -4
- package/corpus/templates/slides/app/components/deck/DeckFilterMenu.tsx +44 -36
- package/corpus/templates/slides/app/components/home/SlidesHomeLibrary.tsx +79 -0
- package/corpus/templates/slides/app/components/layout/Header.tsx +2 -15
- package/corpus/templates/slides/app/components/ui/tabs.tsx +59 -0
- package/corpus/templates/slides/app/global.css +3 -54
- package/corpus/templates/slides/app/i18n/en-US.ts +4 -0
- package/corpus/templates/slides/app/lib/deck-filter.ts +5 -2
- package/corpus/templates/slides/app/pages/Index.tsx +102 -88
- package/corpus/templates/slides/changelog/2026-10-01-filter-decks-by-owner.md +6 -0
- package/corpus/templates/slides/changelog/2026-10-02-hide-recent-until-decks-available.md +6 -0
- package/corpus/templates/slides/changelog/2026-10-05-the-recent-tab-shows-loading-placeholders-until-your-decks-a.md +6 -0
- package/corpus/templates/slides/package.json +1 -0
- package/corpus/templates/slides/server/handlers/request-auth-context.ts +8 -0
- package/corpus/templates/slides/server/plugins/auth.ts +2 -1
- package/corpus/templates/slides/server/plugins/otel.ts +6 -0
- package/corpus/templates/tasks/.agents/skills/security/SKILL.md +9 -2
- package/corpus/templates/tasks/.agents/skills/storing-data/SKILL.md +12 -7
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const DESIGN_FILTER_STORAGE_KEY = "design:design-filter";
|
|
2
2
|
|
|
3
|
-
export type DesignFilter = "all" | "mine";
|
|
3
|
+
export type DesignFilter = "all" | "mine" | "not-mine";
|
|
4
4
|
|
|
5
5
|
function getLocalStorage(): Pick<Storage, "getItem" | "setItem"> | null {
|
|
6
6
|
if (typeof window === "undefined") return null;
|
|
@@ -20,7 +20,9 @@ export function readStoredDesignFilter(
|
|
|
20
20
|
|
|
21
21
|
try {
|
|
22
22
|
const stored = storage.getItem(DESIGN_FILTER_STORAGE_KEY);
|
|
23
|
-
return stored === "all" || stored === "mine"
|
|
23
|
+
return stored === "all" || stored === "mine" || stored === "not-mine"
|
|
24
|
+
? stored
|
|
25
|
+
: undefined;
|
|
24
26
|
} catch {
|
|
25
27
|
// coercion-ok: localStorage failures intentionally fall back to the default filter.
|
|
26
28
|
return undefined;
|
|
@@ -24,11 +24,8 @@ import {
|
|
|
24
24
|
} from "@agent-native/toolkit/agentkit";
|
|
25
25
|
import {
|
|
26
26
|
PromptHome,
|
|
27
|
-
PromptHomeLibrary,
|
|
28
27
|
TemplateLibraryGrid,
|
|
29
|
-
type PromptHomeLibraryTab,
|
|
30
28
|
useHomeSearchShortcut,
|
|
31
|
-
useSetHeaderActions,
|
|
32
29
|
useSetPageTitle,
|
|
33
30
|
} from "@agent-native/toolkit/app-shell";
|
|
34
31
|
import { BuilderSetupCard } from "@agent-native/toolkit/app/chat/chat/run-recovery";
|
|
@@ -46,8 +43,8 @@ import { FULL_APP_BUILDING_LAB } from "@shared/labs";
|
|
|
46
43
|
import { derivePromptTitle } from "@shared/prompt-title";
|
|
47
44
|
import {
|
|
48
45
|
IconArrowRight,
|
|
49
|
-
IconFilter,
|
|
50
46
|
IconChecks,
|
|
47
|
+
IconChevronDown,
|
|
51
48
|
IconChevronLeft,
|
|
52
49
|
IconChevronRight,
|
|
53
50
|
IconPlus,
|
|
@@ -73,6 +70,10 @@ import type {
|
|
|
73
70
|
PromptTemplateOption,
|
|
74
71
|
UploadedFile,
|
|
75
72
|
} from "@/components/editor/PromptDialog";
|
|
73
|
+
import {
|
|
74
|
+
DesignHomeLibrary,
|
|
75
|
+
type DesignHomeLibraryTab,
|
|
76
|
+
} from "@/components/home/DesignHomeLibrary";
|
|
76
77
|
import { QueryErrorState } from "@/components/QueryErrorState";
|
|
77
78
|
import { DesignTemplateLibrary } from "@/components/templates/DesignTemplateLibrary";
|
|
78
79
|
import {
|
|
@@ -142,25 +143,6 @@ interface DesignListResult {
|
|
|
142
143
|
}
|
|
143
144
|
|
|
144
145
|
const DESIGN_PAGE_SIZE = 50;
|
|
145
|
-
const HOME_LIBRARY_TAB_STORAGE_KEY = "design:home-library-tab";
|
|
146
|
-
|
|
147
|
-
function readStoredHomeLibraryTab(): PromptHomeLibraryTab | undefined {
|
|
148
|
-
try {
|
|
149
|
-
const tab = window.localStorage.getItem(HOME_LIBRARY_TAB_STORAGE_KEY);
|
|
150
|
-
return tab === "templates" || tab === "recent" ? tab : undefined;
|
|
151
|
-
} catch {
|
|
152
|
-
// coercion-ok: the tab preference is optional when browser storage is unavailable.
|
|
153
|
-
return undefined;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
function writeStoredHomeLibraryTab(tab: PromptHomeLibraryTab): void {
|
|
158
|
-
try {
|
|
159
|
-
window.localStorage.setItem(HOME_LIBRARY_TAB_STORAGE_KEY, tab);
|
|
160
|
-
} catch {
|
|
161
|
-
// coercion-ok: an unavailable preference store preserves the in-memory selection.
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
146
|
|
|
165
147
|
interface HomeSuggestion {
|
|
166
148
|
id?: string;
|
|
@@ -178,7 +160,6 @@ type HomeSuggestionsResult =
|
|
|
178
160
|
|
|
179
161
|
export default function Index() {
|
|
180
162
|
const t = useT();
|
|
181
|
-
useHomeSearchShortcut(true);
|
|
182
163
|
const navigate = useNavigate();
|
|
183
164
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
184
165
|
const queryClient = useQueryClient();
|
|
@@ -192,13 +173,9 @@ export default function Index() {
|
|
|
192
173
|
const [selectedDesignIds, setSelectedDesignIds] = useState<Set<string>>(
|
|
193
174
|
() => new Set(),
|
|
194
175
|
);
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
);
|
|
199
|
-
const homeLibraryTabWasSelectedRef = useRef(
|
|
200
|
-
storedHomeLibraryTab !== undefined,
|
|
201
|
-
);
|
|
176
|
+
const [homeSection, setHomeSection] =
|
|
177
|
+
useState<DesignHomeLibraryTab>("templates");
|
|
178
|
+
const homeLibraryTabWasSelectedRef = useRef(false);
|
|
202
179
|
const designFilterWasSelectedRef = useRef(false);
|
|
203
180
|
const composerRef = useRef<TiptapComposerHandle>(null);
|
|
204
181
|
const [quickStartPending, setQuickStartPending] = useState(false);
|
|
@@ -229,7 +206,12 @@ export default function Index() {
|
|
|
229
206
|
() => ({
|
|
230
207
|
page,
|
|
231
208
|
pageSize: DESIGN_PAGE_SIZE,
|
|
232
|
-
createdBy:
|
|
209
|
+
createdBy:
|
|
210
|
+
designFilter === "mine"
|
|
211
|
+
? "me"
|
|
212
|
+
: designFilter === "not-mine"
|
|
213
|
+
? "not-me"
|
|
214
|
+
: "all",
|
|
233
215
|
search: normalizedSearch || undefined,
|
|
234
216
|
includePreview: "true",
|
|
235
217
|
}),
|
|
@@ -262,16 +244,30 @@ export default function Index() {
|
|
|
262
244
|
includePreview: "false",
|
|
263
245
|
});
|
|
264
246
|
const hasSearchResultsSection = normalizedSearch.length > 0;
|
|
247
|
+
const recentVisible =
|
|
248
|
+
accessibleDesignsSummary.isSuccess &&
|
|
249
|
+
(accessibleDesignsSummary.data?.totalCount ?? 0) > 0;
|
|
250
|
+
const revealRecentSearch = useCallback(() => {
|
|
251
|
+
if (!recentVisible) return false;
|
|
252
|
+
homeLibraryTabWasSelectedRef.current = true;
|
|
253
|
+
setHomeSection("recent");
|
|
254
|
+
return true;
|
|
255
|
+
}, [recentVisible]);
|
|
256
|
+
useHomeSearchShortcut(true, revealRecentSearch);
|
|
265
257
|
useEffect(() => {
|
|
266
|
-
if (
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
) {
|
|
271
|
-
setHomeSection("
|
|
272
|
-
|
|
273
|
-
|
|
258
|
+
if (!accessibleDesignsSummary.isSuccess) return;
|
|
259
|
+
|
|
260
|
+
const hasAccessibleDesigns =
|
|
261
|
+
(accessibleDesignsSummary.data?.totalCount ?? 0) > 0;
|
|
262
|
+
if (!hasAccessibleDesigns) {
|
|
263
|
+
setHomeSection("templates");
|
|
264
|
+
homeLibraryTabWasSelectedRef.current = false;
|
|
265
|
+
return;
|
|
274
266
|
}
|
|
267
|
+
if (homeLibraryTabWasSelectedRef.current) return;
|
|
268
|
+
|
|
269
|
+
setHomeSection("recent");
|
|
270
|
+
homeLibraryTabWasSelectedRef.current = true;
|
|
275
271
|
}, [
|
|
276
272
|
accessibleDesignsSummary.data?.totalCount,
|
|
277
273
|
accessibleDesignsSummary.isSuccess,
|
|
@@ -460,7 +456,12 @@ export default function Index() {
|
|
|
460
456
|
? chosenDesignSystemId
|
|
461
457
|
: templateDesignSystemId;
|
|
462
458
|
|
|
463
|
-
const
|
|
459
|
+
const ownerFilterLabels: Record<DesignFilter, string> = {
|
|
460
|
+
all: t("home.ownedByAnyone"),
|
|
461
|
+
mine: t("home.ownedByMe"),
|
|
462
|
+
"not-mine": t("home.sharedWithMe"),
|
|
463
|
+
};
|
|
464
|
+
const showAuthors = designFilter !== "mine";
|
|
464
465
|
const selectedDesignCount = selectedDesignIds.size;
|
|
465
466
|
const isSelectingDesigns = selectedDesignCount > 0;
|
|
466
467
|
const allVisibleSelected =
|
|
@@ -583,7 +584,7 @@ export default function Index() {
|
|
|
583
584
|
}, []);
|
|
584
585
|
|
|
585
586
|
const handleDesignFilterChange = useCallback((next: string) => {
|
|
586
|
-
if (next !== "all" && next !== "mine") return;
|
|
587
|
+
if (next !== "all" && next !== "mine" && next !== "not-mine") return;
|
|
587
588
|
designFilterWasSelectedRef.current = true;
|
|
588
589
|
const nextFilter: DesignFilter = next;
|
|
589
590
|
setDesignFilter(nextFilter);
|
|
@@ -1141,8 +1142,8 @@ export default function Index() {
|
|
|
1141
1142
|
|
|
1142
1143
|
useSetPageTitle(t("home.pageTitle"));
|
|
1143
1144
|
|
|
1144
|
-
|
|
1145
|
-
<div className="relative w-full">
|
|
1145
|
+
const searchInput = (
|
|
1146
|
+
<div className="relative w-full min-w-0 sm:w-64 sm:shrink-0">
|
|
1146
1147
|
<IconSearch className="pointer-events-none absolute start-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" />
|
|
1147
1148
|
<Input
|
|
1148
1149
|
size="sm"
|
|
@@ -1151,9 +1152,9 @@ export default function Index() {
|
|
|
1151
1152
|
placeholder={t("home.searchPlaceholder")}
|
|
1152
1153
|
aria-label={t("home.searchPlaceholder")}
|
|
1153
1154
|
data-home-search="true"
|
|
1154
|
-
className="w-full pe-3 ps-8"
|
|
1155
|
+
className="h-9 w-full pe-3 ps-8"
|
|
1155
1156
|
/>
|
|
1156
|
-
</div
|
|
1157
|
+
</div>
|
|
1157
1158
|
);
|
|
1158
1159
|
|
|
1159
1160
|
return (
|
|
@@ -1307,11 +1308,15 @@ export default function Index() {
|
|
|
1307
1308
|
/>
|
|
1308
1309
|
) : null}
|
|
1309
1310
|
<ClientOnly>
|
|
1310
|
-
<
|
|
1311
|
-
|
|
1311
|
+
<DesignHomeLibrary
|
|
1312
|
+
recentVisible={recentVisible}
|
|
1313
|
+
value={
|
|
1314
|
+
recentVisible && !homeLibraryTabWasSelectedRef.current
|
|
1315
|
+
? "recent"
|
|
1316
|
+
: homeSection
|
|
1317
|
+
}
|
|
1312
1318
|
onValueChange={(value) => {
|
|
1313
1319
|
homeLibraryTabWasSelectedRef.current = true;
|
|
1314
|
-
writeStoredHomeLibraryTab(value);
|
|
1315
1320
|
setHomeSection(value);
|
|
1316
1321
|
}}
|
|
1317
1322
|
labels={{
|
|
@@ -1326,28 +1331,49 @@ export default function Index() {
|
|
|
1326
1331
|
</Link>
|
|
1327
1332
|
</Button>
|
|
1328
1333
|
}
|
|
1334
|
+
search={searchInput}
|
|
1329
1335
|
recentActions={
|
|
1330
1336
|
<DropdownMenu>
|
|
1331
1337
|
<DropdownMenuTrigger asChild>
|
|
1332
1338
|
<Button
|
|
1339
|
+
type="button"
|
|
1333
1340
|
variant="outline"
|
|
1334
1341
|
size="sm"
|
|
1335
|
-
aria-label={
|
|
1342
|
+
aria-label={ownerFilterLabels[designFilter]}
|
|
1343
|
+
className="h-9 shrink-0 gap-2"
|
|
1336
1344
|
>
|
|
1337
|
-
<
|
|
1338
|
-
|
|
1345
|
+
<span className="grid">
|
|
1346
|
+
{Object.entries(ownerFilterLabels).map(
|
|
1347
|
+
([filter, label]) => (
|
|
1348
|
+
<span
|
|
1349
|
+
key={filter}
|
|
1350
|
+
aria-hidden="true"
|
|
1351
|
+
className="invisible col-start-1 row-start-1 whitespace-nowrap"
|
|
1352
|
+
>
|
|
1353
|
+
{label}
|
|
1354
|
+
</span>
|
|
1355
|
+
),
|
|
1356
|
+
)}
|
|
1357
|
+
<span className="col-start-1 row-start-1 whitespace-nowrap">
|
|
1358
|
+
{ownerFilterLabels[designFilter]}
|
|
1359
|
+
</span>
|
|
1360
|
+
</span>
|
|
1361
|
+
<IconChevronDown className="size-4" aria-hidden="true" />
|
|
1339
1362
|
</Button>
|
|
1340
1363
|
</DropdownMenuTrigger>
|
|
1341
|
-
<DropdownMenuContent align="
|
|
1364
|
+
<DropdownMenuContent align="start">
|
|
1342
1365
|
<DropdownMenuRadioGroup
|
|
1343
1366
|
value={designFilter}
|
|
1344
1367
|
onValueChange={handleDesignFilterChange}
|
|
1345
1368
|
>
|
|
1346
|
-
<DropdownMenuRadioItem value="
|
|
1347
|
-
{
|
|
1369
|
+
<DropdownMenuRadioItem value="all" indicator="check">
|
|
1370
|
+
{ownerFilterLabels.all}
|
|
1371
|
+
</DropdownMenuRadioItem>
|
|
1372
|
+
<DropdownMenuRadioItem value="mine" indicator="check">
|
|
1373
|
+
{ownerFilterLabels.mine}
|
|
1348
1374
|
</DropdownMenuRadioItem>
|
|
1349
|
-
<DropdownMenuRadioItem value="
|
|
1350
|
-
{
|
|
1375
|
+
<DropdownMenuRadioItem value="not-mine" indicator="check">
|
|
1376
|
+
{ownerFilterLabels["not-mine"]}
|
|
1351
1377
|
</DropdownMenuRadioItem>
|
|
1352
1378
|
</DropdownMenuRadioGroup>
|
|
1353
1379
|
</DropdownMenuContent>
|
|
@@ -1370,7 +1396,7 @@ export default function Index() {
|
|
|
1370
1396
|
}
|
|
1371
1397
|
recent={
|
|
1372
1398
|
<>
|
|
1373
|
-
{isLoading ? (
|
|
1399
|
+
{isLoading || (isFetching && designs.length === 0) ? (
|
|
1374
1400
|
<LoadingSkeleton />
|
|
1375
1401
|
) : isError ? (
|
|
1376
1402
|
<QueryErrorState
|
|
@@ -1378,7 +1404,13 @@ export default function Index() {
|
|
|
1378
1404
|
retrying={isFetching}
|
|
1379
1405
|
/>
|
|
1380
1406
|
) : designs.length === 0 ? (
|
|
1381
|
-
|
|
1407
|
+
normalizedSearch ? (
|
|
1408
|
+
<SearchEmptyState />
|
|
1409
|
+
) : (
|
|
1410
|
+
<div className="rounded-xl bg-card p-6 text-center text-sm text-muted-foreground">
|
|
1411
|
+
{t("home.noDesignsMatchFilter")}
|
|
1412
|
+
</div>
|
|
1413
|
+
)
|
|
1382
1414
|
) : (
|
|
1383
1415
|
<>
|
|
1384
1416
|
{isSelectingDesigns ? (
|
package/corpus/templates/design/app/pages/design-editor/commands/cross-screen-element-drop.ts
CHANGED
|
@@ -122,6 +122,33 @@ export function absolutePlacePointForDrop(args: {
|
|
|
122
122
|
return absoluteDropPoint(args.targetLocalPoint, args.targetAnchorRect);
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
export function authoredTargetPointForDrop(args: {
|
|
126
|
+
boardFileId?: string;
|
|
127
|
+
targetScreenId: string;
|
|
128
|
+
targetOutsideBoardRenderGeometry?: boolean;
|
|
129
|
+
targetAnchorNodeId?: string;
|
|
130
|
+
targetAnchorPendingNodeId?: string;
|
|
131
|
+
targetAnchorSelector?: string;
|
|
132
|
+
targetCanvasPoint?: { x: number; y: number };
|
|
133
|
+
targetLocalPoint?: { x: number; y: number };
|
|
134
|
+
}): { x: number; y: number } | undefined {
|
|
135
|
+
const hasAnchor = Boolean(
|
|
136
|
+
args.targetAnchorNodeId ||
|
|
137
|
+
args.targetAnchorPendingNodeId ||
|
|
138
|
+
args.targetAnchorSelector,
|
|
139
|
+
);
|
|
140
|
+
if (
|
|
141
|
+
!hasAnchor &&
|
|
142
|
+
args.boardFileId &&
|
|
143
|
+
args.targetScreenId === args.boardFileId &&
|
|
144
|
+
args.targetOutsideBoardRenderGeometry === true &&
|
|
145
|
+
args.targetCanvasPoint
|
|
146
|
+
) {
|
|
147
|
+
return args.targetCanvasPoint;
|
|
148
|
+
}
|
|
149
|
+
return args.targetLocalPoint;
|
|
150
|
+
}
|
|
151
|
+
|
|
125
152
|
export function releaseCrossScreenDropAdmission(
|
|
126
153
|
pendingTransactionRef: RefObject<string | null> | undefined,
|
|
127
154
|
transactionId: string | undefined,
|
|
@@ -348,6 +375,8 @@ export function runCrossScreenElementDrop(
|
|
|
348
375
|
targetDropMode,
|
|
349
376
|
targetGridPlacement,
|
|
350
377
|
targetAnchorRect,
|
|
378
|
+
targetCanvasPoint,
|
|
379
|
+
targetOutsideBoardRenderGeometry,
|
|
351
380
|
targetLocalPoint,
|
|
352
381
|
sourcePointerOffset,
|
|
353
382
|
sourceComputedSize,
|
|
@@ -382,6 +411,7 @@ export function runCrossScreenElementDrop(
|
|
|
382
411
|
height: number;
|
|
383
412
|
};
|
|
384
413
|
targetCanvasPoint?: { x: number; y: number };
|
|
414
|
+
targetOutsideBoardRenderGeometry?: boolean;
|
|
385
415
|
targetLocalPoint?: { x: number; y: number };
|
|
386
416
|
sourcePointerOffset?: { x: number; y: number };
|
|
387
417
|
sourceComputedSize?: { width?: number; height?: number };
|
|
@@ -400,6 +430,16 @@ export function runCrossScreenElementDrop(
|
|
|
400
430
|
targetAnchorPlacement,
|
|
401
431
|
targetDropMode,
|
|
402
432
|
});
|
|
433
|
+
const targetPositionPoint = authoredTargetPointForDrop({
|
|
434
|
+
boardFileId,
|
|
435
|
+
targetScreenId,
|
|
436
|
+
targetAnchorNodeId,
|
|
437
|
+
targetAnchorPendingNodeId,
|
|
438
|
+
targetAnchorSelector,
|
|
439
|
+
targetCanvasPoint,
|
|
440
|
+
targetOutsideBoardRenderGeometry,
|
|
441
|
+
targetLocalPoint,
|
|
442
|
+
});
|
|
403
443
|
if (styleSnapshotCaptureFailed) {
|
|
404
444
|
trace("drop", "refused", {
|
|
405
445
|
reason:
|
|
@@ -575,14 +615,14 @@ export function runCrossScreenElementDrop(
|
|
|
575
615
|
targetAnchorNodeId || targetAnchorPendingNodeId || targetAnchorSelector,
|
|
576
616
|
);
|
|
577
617
|
const placeAbsolute =
|
|
578
|
-
Boolean(
|
|
618
|
+
Boolean(targetPositionPoint) &&
|
|
579
619
|
(!hasAnchor || targetDropMode === "absolute-container");
|
|
580
620
|
const absolutePosition =
|
|
581
|
-
placeAbsolute &&
|
|
621
|
+
placeAbsolute && targetPositionPoint
|
|
582
622
|
? absolutePlacePointForDrop({
|
|
583
623
|
placeAbsoluteOnEmptyScreen: false,
|
|
584
624
|
targetAnchorRect,
|
|
585
|
-
targetLocalPoint,
|
|
625
|
+
targetLocalPoint: targetPositionPoint,
|
|
586
626
|
})
|
|
587
627
|
: undefined;
|
|
588
628
|
const prepared = prepareClonedHtmlLayersForLiveInsert(
|
|
@@ -666,14 +706,14 @@ export function runCrossScreenElementDrop(
|
|
|
666
706
|
targetAnchorNodeId || targetAnchorPendingNodeId || targetAnchorSelector,
|
|
667
707
|
);
|
|
668
708
|
const placeAbsolute =
|
|
669
|
-
Boolean(
|
|
709
|
+
Boolean(targetPositionPoint) &&
|
|
670
710
|
(!hasAnchor || targetDropMode === "absolute-container");
|
|
671
711
|
const absolutePosition =
|
|
672
|
-
placeAbsolute &&
|
|
712
|
+
placeAbsolute && targetPositionPoint
|
|
673
713
|
? absolutePlacePointForDrop({
|
|
674
714
|
placeAbsoluteOnEmptyScreen: false,
|
|
675
715
|
targetAnchorRect,
|
|
676
|
-
targetLocalPoint,
|
|
716
|
+
targetLocalPoint: targetPositionPoint,
|
|
677
717
|
})
|
|
678
718
|
: undefined;
|
|
679
719
|
const prepared = prepareClonedHtmlLayersForLiveInsert(
|
|
@@ -784,14 +824,14 @@ export function runCrossScreenElementDrop(
|
|
|
784
824
|
];
|
|
785
825
|
const hasAnchor = anchorSelectors.length > 0;
|
|
786
826
|
const placeAbsolute =
|
|
787
|
-
Boolean(
|
|
827
|
+
Boolean(targetPositionPoint) &&
|
|
788
828
|
(!hasAnchor || targetDropMode === "absolute-container");
|
|
789
829
|
const absolutePosition =
|
|
790
|
-
placeAbsolute &&
|
|
830
|
+
placeAbsolute && targetPositionPoint
|
|
791
831
|
? absolutePlacePointForDrop({
|
|
792
832
|
placeAbsoluteOnEmptyScreen: false,
|
|
793
833
|
targetAnchorRect,
|
|
794
|
-
targetLocalPoint,
|
|
834
|
+
targetLocalPoint: targetPositionPoint,
|
|
795
835
|
})
|
|
796
836
|
: undefined;
|
|
797
837
|
const nextContent = insertClonedHtmlLayers(
|
|
@@ -942,10 +982,10 @@ export function runCrossScreenElementDrop(
|
|
|
942
982
|
const destHtml = getScreenContent(targetScreenId);
|
|
943
983
|
const placeAbsoluteOnEmptyScreen = shouldAbsolutePlaceOnEmptyScreen({
|
|
944
984
|
destHtml,
|
|
945
|
-
targetLocalPoint,
|
|
985
|
+
targetLocalPoint: targetPositionPoint,
|
|
946
986
|
});
|
|
947
987
|
const positioned =
|
|
948
|
-
|
|
988
|
+
targetPositionPoint &&
|
|
949
989
|
(placeAbsoluteOnEmptyScreen ||
|
|
950
990
|
(targetDropMode === "absolute-container" && targetAnchorRect))
|
|
951
991
|
? setAbsolutePositioningForNodeInHtml(
|
|
@@ -954,7 +994,7 @@ export function runCrossScreenElementDrop(
|
|
|
954
994
|
absolutePlacePointForDrop({
|
|
955
995
|
placeAbsoluteOnEmptyScreen,
|
|
956
996
|
targetAnchorRect,
|
|
957
|
-
targetLocalPoint,
|
|
997
|
+
targetLocalPoint: targetPositionPoint,
|
|
958
998
|
}),
|
|
959
999
|
sourcePointerOffset,
|
|
960
1000
|
sourceComputedSize,
|
|
@@ -1179,7 +1219,7 @@ export function runCrossScreenElementDrop(
|
|
|
1179
1219
|
);
|
|
1180
1220
|
const placeAbsoluteOnEmptyScreen = shouldAbsolutePlaceOnEmptyScreen({
|
|
1181
1221
|
destHtml: destContent,
|
|
1182
|
-
targetLocalPoint,
|
|
1222
|
+
targetLocalPoint: targetPositionPoint,
|
|
1183
1223
|
});
|
|
1184
1224
|
const placed = ((): { content: string; branch: string } => {
|
|
1185
1225
|
const absolute = (point: { x: number; y: number }, branch: string) => ({
|
|
@@ -1199,17 +1239,17 @@ export function runCrossScreenElementDrop(
|
|
|
1199
1239
|
),
|
|
1200
1240
|
branch: "anchored-flow-insert",
|
|
1201
1241
|
};
|
|
1202
|
-
if (!
|
|
1242
|
+
if (!targetPositionPoint) {
|
|
1203
1243
|
if (targetAnchorAttrId && targetDropMode !== "absolute-container") {
|
|
1204
1244
|
return flowInsert;
|
|
1205
1245
|
}
|
|
1206
1246
|
return { content: stylePreservedDest, branch: "rooted-no-point" };
|
|
1207
1247
|
}
|
|
1208
1248
|
if (placeAbsoluteOnEmptyScreen) {
|
|
1209
|
-
return absolute(
|
|
1249
|
+
return absolute(targetPositionPoint, "empty-screen-absolute");
|
|
1210
1250
|
}
|
|
1211
1251
|
if (!targetAnchorAttrId) {
|
|
1212
|
-
return absolute(
|
|
1252
|
+
return absolute(targetPositionPoint, "rooted-absolute");
|
|
1213
1253
|
}
|
|
1214
1254
|
if (targetDropMode === "absolute-container") {
|
|
1215
1255
|
if (!targetAnchorRect) {
|
|
@@ -1222,7 +1262,7 @@ export function runCrossScreenElementDrop(
|
|
|
1222
1262
|
absolutePlacePointForDrop({
|
|
1223
1263
|
placeAbsoluteOnEmptyScreen,
|
|
1224
1264
|
targetAnchorRect,
|
|
1225
|
-
targetLocalPoint,
|
|
1265
|
+
targetLocalPoint: targetPositionPoint,
|
|
1226
1266
|
}),
|
|
1227
1267
|
"anchored-absolute",
|
|
1228
1268
|
);
|
|
@@ -1237,6 +1277,7 @@ export function runCrossScreenElementDrop(
|
|
|
1237
1277
|
`${placed.branch} node=${destNodeAttrId} target=${targetScreenId}` +
|
|
1238
1278
|
` anchor=${targetAnchorAttrId ?? "none"} mode=${targetDropMode ?? "none"}` +
|
|
1239
1279
|
` local=${point(targetLocalPoint)}` +
|
|
1280
|
+
` authored=${point(targetPositionPoint)}` +
|
|
1240
1281
|
` anchorRect=${targetAnchorRect ? `${Math.round(targetAnchorRect.left)},${Math.round(targetAnchorRect.top)}` : "none"}` +
|
|
1241
1282
|
` grab=${point(sourcePointerOffset)}`,
|
|
1242
1283
|
);
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@agent-native/core": "workspace:*",
|
|
30
30
|
"@agent-native/creative-context": "workspace:*",
|
|
31
|
+
"@agent-native/otel": "workspace:*",
|
|
31
32
|
"@agent-native/toolkit": "workspace:*",
|
|
32
33
|
"@electric-sql/pglite": "^0.5.8",
|
|
33
34
|
"@fontsource-variable/inter": "^5.2.8",
|
|
@@ -7,7 +7,8 @@ export default createAuthPlugin({
|
|
|
7
7
|
workspaceAppPublicPaths: ["/", "/visual-edit", "/design", "/present"],
|
|
8
8
|
marketing: {
|
|
9
9
|
appName: "Design",
|
|
10
|
-
learnMoreUrl:
|
|
10
|
+
learnMoreUrl:
|
|
11
|
+
"https://agent-native.com/apps/design?utm_source=app&utm_medium=product&utm_content=onboarding-learn-more",
|
|
11
12
|
tagline:
|
|
12
13
|
"Design and prototype by describing what you want. The AI agent turns your ideas into interactive, fully responsive designs in seconds.",
|
|
13
14
|
features: [
|
|
@@ -290,9 +290,16 @@ export default defineEventHandler(async (event) => {
|
|
|
290
290
|
|
|
291
291
|
## Data Scoping
|
|
292
292
|
|
|
293
|
-
In production, the framework automatically restricts all agent SQL queries to the current user's data using temporary views
|
|
293
|
+
In production, the framework automatically restricts all agent SQL queries to the current user's data using temporary views, and checks every statement before it runs so it can only reach those views.
|
|
294
294
|
|
|
295
|
-
The `db-query` / `db-exec` tools (and the extension SQL bridge, which shares the same path)
|
|
295
|
+
The `db-query` / `db-exec` / `db-patch` tools (and the extension SQL bridge, which shares the same path) read each statement the way Postgres does and refuse anything that could reach data around the temp views:
|
|
296
|
+
|
|
297
|
+
- schema- or database-qualified names like `public.<table>`, which resolve to the base table;
|
|
298
|
+
- names that resolve to anything other than the current user's temp views, such as materialized views or tables the scoping does not cover;
|
|
299
|
+
- app-defined SQL or PL/pgSQL functions and operators, whose bodies read tables without the views;
|
|
300
|
+
- built-ins that run SQL text, change session settings, or reach outside the database (`query_to_xml`, `set_config`, `dblink`, most `pg_*` functions).
|
|
301
|
+
|
|
302
|
+
`db-query` runs in a read-only transaction, and an `INSERT` must list its columns when the table has access-control columns. Use bare table names and plain expressions; scoping is applied automatically. When the agent needs data the views do not expose, add an app action with its own access checks.
|
|
296
303
|
|
|
297
304
|
### Per-User Scoping (`owner_email`)
|
|
298
305
|
|
|
@@ -75,10 +75,11 @@ state their PostgreSQL types directly.
|
|
|
75
75
|
|
|
76
76
|
Member offboarding and email changes refuse to run while any column named
|
|
77
77
|
`email`, `*_email`, `*scope_id`, `created_by`, `updated_by`, `invited_by`,
|
|
78
|
-
`owner`, `principal_id`, `session_id`, or `user_id` has no policy.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
`owner`, `principal_id`, `session_id`, or `user_id` has no policy.
|
|
79
|
+
`createSharesTable()` tables are handled for you, and undeclared `owner_email`
|
|
80
|
+
columns transfer to the successor, which is right only for owned content.
|
|
81
|
+
Declare every other one, including columns that are not member identities, from
|
|
82
|
+
the app's database plugin graph (Clips does it in `server/db/index.ts`):
|
|
82
83
|
|
|
83
84
|
```ts
|
|
84
85
|
import { registerIdentityColumns } from "@agent-native/core/org";
|
|
@@ -88,13 +89,17 @@ registerIdentityColumns([
|
|
|
88
89
|
{ table: "space_members", column: "email", emailChange: "rekey", offboard: "delete", orgScope: { column: "space_id", references: { table: "spaces", column: "id", orgColumn: "org_id" } }, reason: "Space membership grants access." },
|
|
89
90
|
// Someone else's address: never rewritten.
|
|
90
91
|
{ table: "meeting_participants", column: "email", emailChange: "retain", offboard: "retain", reason: "Attendee address from the calendar provider." },
|
|
92
|
+
// A credential in an owner_email table: never handed to the successor.
|
|
93
|
+
{ table: "api_keys", column: "owner_email", emailChange: "rekey", offboard: "revoke", reason: "Bearer keys act as their owner." },
|
|
91
94
|
]);
|
|
92
95
|
```
|
|
93
96
|
|
|
94
|
-
Choose `delete` for grants, credentials, and pending tokens
|
|
97
|
+
Choose `delete` for grants, credentials, and pending tokens, or `revoke` (sets
|
|
98
|
+
`revoked_at`) when a reader treats a missing row as "not revoked"; `retain` for
|
|
95
99
|
attribution, history, and third-party addresses; `transfer` only for owned
|
|
96
|
-
data.
|
|
97
|
-
|
|
100
|
+
data. Declare `owner_email` tables that hold credentials or grants, or
|
|
101
|
+
offboarding hands them to the successor. A table without `org_id` needs
|
|
102
|
+
`orgScope` or an organization-scoped removal leaves its rows alone.
|
|
98
103
|
|
|
99
104
|
| Template | Tables |
|
|
100
105
|
| ------------ | --------------------------------------------- |
|
|
@@ -4,7 +4,7 @@ The agent-native workspace control plane — a central Slack/Telegram inbox, a
|
|
|
4
4
|
secrets vault, scheduled jobs, approvals, and an orchestrator agent that delegates
|
|
5
5
|
work to the right specialist app over A2A.
|
|
6
6
|
|
|
7
|
-
**Live app: [dispatch.agent-native.com](https://dispatch.agent-native.com)**
|
|
7
|
+
**Live app: [dispatch.agent-native.com](https://dispatch.agent-native.com?utm_source=github&utm_medium=referral&utm_content=dispatch-readme)**
|
|
8
8
|
|
|
9
9
|
Where other templates are domain apps (Mail, Calendar, Analytics, Brain),
|
|
10
10
|
Dispatch is the app you run _alongside_ them to coordinate everything. It routes
|
|
@@ -31,4 +31,4 @@ pnpm install
|
|
|
31
31
|
pnpm dev
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
Full docs: [agent-native.com/docs/template-dispatch](https://agent-native.com/docs/template-dispatch).
|
|
34
|
+
Full docs: [agent-native.com/docs/template-dispatch](https://agent-native.com/docs/template-dispatch?utm_source=github&utm_medium=referral&utm_content=dispatch-readme).
|
|
@@ -3,7 +3,8 @@ import { setupDispatch } from "@agent-native/dispatch/server";
|
|
|
3
3
|
export default setupDispatch({
|
|
4
4
|
auth: {
|
|
5
5
|
marketing: {
|
|
6
|
-
learnMoreUrl:
|
|
6
|
+
learnMoreUrl:
|
|
7
|
+
"https://agent-native.com/apps/dispatch?utm_source=app&utm_medium=product&utm_content=onboarding-learn-more",
|
|
7
8
|
},
|
|
8
9
|
publicPaths: [
|
|
9
10
|
"/_agent-native/identity/availability",
|