@agent-native/core 0.102.2 → 0.103.1
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/core/CHANGELOG.md +12 -0
- package/corpus/core/docs/content/local-file-mode.mdx +99 -489
- package/corpus/core/docs/content/locales/ar-SA/local-file-mode.mdx +35 -490
- package/corpus/core/docs/content/locales/ar-SA/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/de-DE/local-file-mode.mdx +37 -491
- package/corpus/core/docs/content/locales/de-DE/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/es-ES/local-file-mode.mdx +35 -493
- package/corpus/core/docs/content/locales/es-ES/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/fr-FR/local-file-mode.mdx +38 -491
- package/corpus/core/docs/content/locales/fr-FR/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/hi-IN/local-file-mode.mdx +33 -492
- package/corpus/core/docs/content/locales/hi-IN/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/ja-JP/local-file-mode.mdx +36 -492
- package/corpus/core/docs/content/locales/ja-JP/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/ko-KR/local-file-mode.mdx +35 -490
- package/corpus/core/docs/content/locales/ko-KR/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/pt-BR/local-file-mode.mdx +35 -493
- package/corpus/core/docs/content/locales/pt-BR/template-content.mdx +10 -24
- package/corpus/core/docs/content/locales/zh-CN/local-file-mode.mdx +31 -489
- package/corpus/core/docs/content/locales/zh-CN/template-content.mdx +9 -24
- package/corpus/core/docs/content/locales/zh-TW/local-file-mode.mdx +31 -489
- package/corpus/core/docs/content/locales/zh-TW/template-content.mdx +9 -24
- package/corpus/core/docs/content/template-content.mdx +26 -42
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/cli/content-local.ts +86 -18
- package/corpus/core/src/cli/index.ts +2 -2
- package/corpus/core/src/cli/skills-content/content-skill.ts +36 -25
- package/corpus/core/src/cli/skills.ts +47 -13
- package/corpus/core/src/local-artifacts/index.ts +65 -0
- package/corpus/core/src/vite/client.ts +2 -0
- package/corpus/templates/assets/app/components/library/GenerationPresetsPanel.tsx +325 -0
- package/corpus/templates/assets/app/hooks/use-navigation-state.ts +12 -0
- package/corpus/templates/assets/app/i18n/zh-TW.ts +21 -0
- package/corpus/templates/assets/app/i18n-data.ts +215 -0
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +19 -479
- package/corpus/templates/assets/app/routes/brand-kits.$id_.presets.$presetId.tsx +1 -1
- package/corpus/templates/assets/app/routes/brand-kits.$id_.settings.tsx +446 -0
- package/corpus/templates/clips/app/components/editor/editor-layout.tsx +12 -2
- package/corpus/templates/clips/app/components/player/settings-panel.tsx +30 -12
- package/corpus/templates/clips/app/components/player/video-player.tsx +5 -1
- package/corpus/templates/clips/app/components/recorder/microphone-visualizer.tsx +22 -3
- package/corpus/templates/clips/app/i18n/ar-SA.ts +3 -2
- package/corpus/templates/clips/app/i18n/de-DE.ts +4 -2
- package/corpus/templates/clips/app/i18n/en-US.ts +3 -2
- package/corpus/templates/clips/app/i18n/es-ES.ts +4 -2
- package/corpus/templates/clips/app/i18n/fr-FR.ts +3 -2
- package/corpus/templates/clips/app/i18n/hi-IN.ts +3 -2
- package/corpus/templates/clips/app/i18n/ja-JP.ts +4 -1
- package/corpus/templates/clips/app/i18n/ko-KR.ts +3 -2
- package/corpus/templates/clips/app/i18n/pt-BR.ts +4 -2
- package/corpus/templates/clips/app/i18n/zh-CN.ts +3 -2
- package/corpus/templates/clips/app/i18n/zh-TW.ts +3 -2
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +27 -1
- package/corpus/templates/clips/server/lib/share-password.ts +6 -3
- package/corpus/templates/content/.agents/skills/content/SKILL.md +26 -39
- package/corpus/templates/content/AGENTS.md +25 -30
- package/corpus/templates/content/actions/_builder-docs-client.ts +23 -0
- package/corpus/templates/content/actions/_content-database-source-adapters.ts +21 -3
- package/corpus/templates/content/actions/_content-files.ts +338 -0
- package/corpus/templates/content/actions/_content-space-access.ts +135 -0
- package/corpus/templates/content/actions/_content-spaces.ts +640 -0
- package/corpus/templates/content/actions/_database-source-utils.ts +90 -7
- package/corpus/templates/content/actions/_database-utils.ts +7 -1
- package/corpus/templates/content/actions/_local-file-documents.ts +0 -9
- package/corpus/templates/content/actions/_local-folder-source.ts +53 -0
- package/corpus/templates/content/actions/_property-utils.ts +9 -4
- package/corpus/templates/content/actions/add-database-item.ts +108 -65
- package/corpus/templates/content/actions/backfill-content-files.ts +22 -0
- package/corpus/templates/content/actions/connect-local-folder-source.ts +221 -0
- package/corpus/templates/content/actions/create-content-database.ts +129 -3
- package/corpus/templates/content/actions/create-document.ts +65 -55
- package/corpus/templates/content/actions/create-inline-content-database.ts +6 -1
- package/corpus/templates/content/actions/delete-content-database.ts +3 -0
- package/corpus/templates/content/actions/delete-document.ts +7 -11
- package/corpus/templates/content/actions/disconnect-local-folder-source.ts +175 -0
- package/corpus/templates/content/actions/duplicate-database-item.ts +10 -0
- package/corpus/templates/content/actions/duplicate-database-items.ts +13 -0
- package/corpus/templates/content/actions/edit-document.ts +2 -28
- package/corpus/templates/content/actions/ensure-content-spaces.ts +26 -0
- package/corpus/templates/content/actions/export-content-source.ts +47 -9
- package/corpus/templates/content/actions/get-document.ts +0 -14
- package/corpus/templates/content/actions/import-content-source.ts +43 -3
- package/corpus/templates/content/actions/list-content-spaces.ts +103 -0
- package/corpus/templates/content/actions/list-documents.ts +12 -9
- package/corpus/templates/content/actions/move-document.ts +3 -14
- package/corpus/templates/content/actions/pull-document.ts +0 -23
- package/corpus/templates/content/actions/remove-local-file-source.ts +50 -29
- package/corpus/templates/content/actions/resolve-local-folder-conflict.ts +442 -0
- package/corpus/templates/content/actions/reveal-local-source-file.ts +6 -17
- package/corpus/templates/content/actions/search-documents.ts +0 -34
- package/corpus/templates/content/actions/share-local-file-document.ts +25 -1
- package/corpus/templates/content/actions/submit-content-database-form.ts +12 -0
- package/corpus/templates/content/actions/sync-local-folder-source.ts +731 -0
- package/corpus/templates/content/actions/sync-manifest-local-folder-source.ts +123 -0
- package/corpus/templates/content/actions/update-content-database-view.ts +10 -1
- package/corpus/templates/content/actions/update-document.ts +0 -15
- package/corpus/templates/content/actions/view-screen.ts +2 -50
- package/corpus/templates/content/app/components/editor/SlashCommandMenu.tsx +76 -62
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +70 -22
- package/corpus/templates/content/app/components/editor/database/grouping.ts +2 -1
- package/corpus/templates/content/app/components/editor/database/settings.tsx +23 -20
- package/corpus/templates/content/app/components/editor/database/shared.tsx +2 -0
- package/corpus/templates/content/app/components/editor/database/sidebar.tsx +330 -0
- package/corpus/templates/content/app/components/editor/database/types.ts +1 -0
- package/corpus/templates/content/app/components/editor/database/view-config.ts +3 -1
- package/corpus/templates/content/app/components/layout/Layout.tsx +25 -1
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +209 -113
- package/corpus/templates/content/app/components/sidebar/select-content-space.ts +31 -0
- package/corpus/templates/content/app/hooks/use-content-database.ts +16 -0
- package/corpus/templates/content/app/hooks/use-content-spaces.ts +39 -0
- package/corpus/templates/content/app/i18n/zh-TW.ts +11 -0
- package/corpus/templates/content/app/i18n-data.ts +75 -0
- package/corpus/templates/content/app/routes/_app.local-files.tsx +174 -65
- package/corpus/templates/content/changelog/2026-07-16-content-callouts-can-now-be-reviewed-and-published-to-builder.md +6 -0
- package/corpus/templates/content/changelog/2026-07-16-heading-5-and-heading-6-are-available-from-the-editor-slash-.md +6 -0
- package/corpus/templates/content/changelog/2026-07-16-organize-every-workspace-through-a-customizable-files-databa.md +6 -0
- package/corpus/templates/content/parity/matrix.md +2 -1
- package/corpus/templates/content/parity/matrix.ts +37 -1
- package/corpus/templates/content/scripts/dev-database.mjs +7 -5
- package/corpus/templates/content/server/db/schema.ts +113 -40
- package/corpus/templates/content/server/lib/document-context.ts +15 -1
- package/corpus/templates/content/server/lib/notion-sync.ts +6 -0
- package/corpus/templates/content/server/plugins/db.ts +153 -0
- package/corpus/templates/content/shared/api.ts +17 -3
- package/corpus/templates/content/shared/builder-mdx.ts +163 -16
- package/corpus/templates/design/.agents/skills/design-templates/SKILL.md +59 -0
- package/corpus/templates/design/AGENTS.md +6 -1
- package/corpus/templates/design/actions/create-design-from-template.ts +19 -7
- package/corpus/templates/design/actions/list-design-templates.ts +69 -21
- package/corpus/templates/design/actions/navigate.ts +2 -2
- package/corpus/templates/design/actions/view-screen.ts +15 -2
- package/corpus/templates/design/agent-native.app-skill.json +5 -0
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +281 -56
- package/corpus/templates/design/app/components/templates/TemplatePreview.tsx +14 -2
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +3 -2
- package/corpus/templates/design/app/i18n/zh-TW.ts +3 -3
- package/corpus/templates/design/app/i18n-data.ts +21 -2
- package/corpus/templates/design/app/i18n-template-feature.ts +218 -10
- package/corpus/templates/design/app/pages/Index.tsx +195 -24
- package/corpus/templates/design/app/pages/Templates.tsx +144 -55
- package/corpus/templates/design/app/pages/design-editor/generation-prompt-directives.ts +12 -1
- package/corpus/templates/design/changelog/2026-07-14-templates-now-appear-in-the-new-design-picker-with-previews-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-15-templates-now-open-immediately-after-copying-even-while-the-.md +6 -0
- package/corpus/templates/design/server/plugins/agent-chat.ts +1 -1
- package/corpus/templates/mail/AGENTS.md +23 -18
- package/corpus/templates/mail/actions/bulk-archive.ts +32 -28
- package/corpus/templates/mail/actions/mark-read.ts +131 -20
- package/corpus/templates/mail/actions/mark-thread-read.ts +1 -1
- package/corpus/templates/mail/actions/move-email.ts +30 -24
- package/corpus/templates/mail/actions/send-email.ts +73 -68
- package/corpus/templates/mail/changelog/2026-07-15-unread-inbox-cleanup-now-completes-reliably.md +6 -0
- package/corpus/templates/mail/server/handlers/emails.ts +218 -209
- package/corpus/templates/mail/server/lib/bulk-mark-read.ts +30 -0
- package/corpus/templates/mail/server/lib/email-state.ts +198 -113
- package/corpus/templates/mail/server/lib/google-auth.ts +218 -25
- package/corpus/templates/mail/server/lib/jobs.ts +69 -74
- package/corpus/templates/mail/server/lib/local-email-store.ts +265 -0
- package/corpus/templates/mail/server/plugins/agent-chat.ts +6 -0
- package/dist/cli/content-local.d.ts +1 -0
- package/dist/cli/content-local.d.ts.map +1 -1
- package/dist/cli/content-local.js +75 -17
- package/dist/cli/content-local.js.map +1 -1
- package/dist/cli/index.js +2 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/skills-content/content-skill.d.ts +1 -1
- package/dist/cli/skills-content/content-skill.d.ts.map +1 -1
- package/dist/cli/skills-content/content-skill.js +36 -25
- package/dist/cli/skills-content/content-skill.js.map +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +47 -14
- package/dist/cli/skills.js.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/local-artifacts/index.d.ts +10 -0
- package/dist/local-artifacts/index.d.ts.map +1 -1
- package/dist/local-artifacts/index.js +39 -0
- package/dist/local-artifacts/index.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +2 -0
- package/dist/vite/client.js.map +1 -1
- package/docs/content/local-file-mode.mdx +99 -489
- package/docs/content/locales/ar-SA/local-file-mode.mdx +35 -490
- package/docs/content/locales/ar-SA/template-content.mdx +10 -24
- package/docs/content/locales/de-DE/local-file-mode.mdx +37 -491
- package/docs/content/locales/de-DE/template-content.mdx +10 -24
- package/docs/content/locales/es-ES/local-file-mode.mdx +35 -493
- package/docs/content/locales/es-ES/template-content.mdx +10 -24
- package/docs/content/locales/fr-FR/local-file-mode.mdx +38 -491
- package/docs/content/locales/fr-FR/template-content.mdx +10 -24
- package/docs/content/locales/hi-IN/local-file-mode.mdx +33 -492
- package/docs/content/locales/hi-IN/template-content.mdx +10 -24
- package/docs/content/locales/ja-JP/local-file-mode.mdx +36 -492
- package/docs/content/locales/ja-JP/template-content.mdx +10 -24
- package/docs/content/locales/ko-KR/local-file-mode.mdx +35 -490
- package/docs/content/locales/ko-KR/template-content.mdx +10 -24
- package/docs/content/locales/pt-BR/local-file-mode.mdx +35 -493
- package/docs/content/locales/pt-BR/template-content.mdx +10 -24
- package/docs/content/locales/zh-CN/local-file-mode.mdx +31 -489
- package/docs/content/locales/zh-CN/template-content.mdx +9 -24
- package/docs/content/locales/zh-TW/local-file-mode.mdx +31 -489
- package/docs/content/locales/zh-TW/template-content.mdx +9 -24
- package/docs/content/template-content.mdx +26 -42
- package/package.json +1 -1
- package/corpus/templates/assets/app/components/library/EditLibraryDialog.tsx +0 -126
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
AlertDialogHeader,
|
|
37
37
|
AlertDialogTitle,
|
|
38
38
|
} from "@/components/ui/alert-dialog";
|
|
39
|
+
import { Badge } from "@/components/ui/badge";
|
|
39
40
|
import { Button } from "@/components/ui/button";
|
|
40
41
|
import {
|
|
41
42
|
DropdownMenu,
|
|
@@ -45,6 +46,7 @@ import {
|
|
|
45
46
|
} from "@/components/ui/dropdown-menu";
|
|
46
47
|
import { Input } from "@/components/ui/input";
|
|
47
48
|
import { Spinner } from "@/components/ui/spinner";
|
|
49
|
+
import { useDesignSystems } from "@/hooks/use-design-systems";
|
|
48
50
|
import { writePendingGeneration } from "@/lib/pending-generation";
|
|
49
51
|
|
|
50
52
|
type TemplateCategory =
|
|
@@ -63,28 +65,26 @@ interface DesignTemplateSummary {
|
|
|
63
65
|
width?: number | null;
|
|
64
66
|
height?: number | null;
|
|
65
67
|
lockedLayerCount: number;
|
|
68
|
+
designSystemId?: string | null;
|
|
66
69
|
visibility: "private" | "org" | "public";
|
|
67
70
|
isOwner: boolean;
|
|
71
|
+
isBuiltIn: boolean;
|
|
68
72
|
source: "starter" | "saved";
|
|
69
73
|
previewHtml?: string | null;
|
|
70
74
|
}
|
|
71
75
|
|
|
72
|
-
interface TemplatesResult {
|
|
73
|
-
count: number;
|
|
74
|
-
starterCount: number;
|
|
75
|
-
savedCount: number;
|
|
76
|
-
templates: DesignTemplateSummary[];
|
|
77
|
-
}
|
|
78
|
-
|
|
79
76
|
export default function Templates() {
|
|
80
77
|
const t = useT();
|
|
81
78
|
const navigate = useNavigate();
|
|
82
|
-
const [searchParams] = useSearchParams();
|
|
79
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
83
80
|
const queryClient = useQueryClient();
|
|
84
81
|
const [search, setSearch] = useState("");
|
|
85
82
|
const [selected, setSelected] = useState<DesignTemplateSummary | null>(null);
|
|
86
83
|
const [promptOpen, setPromptOpen] = useState(false);
|
|
87
84
|
const [creating, setCreating] = useState(false);
|
|
85
|
+
const [selectedDesignSystemId, setSelectedDesignSystemId] = useState<
|
|
86
|
+
string | null | undefined
|
|
87
|
+
>(undefined);
|
|
88
88
|
const [deleteTemplate, setDeleteTemplate] =
|
|
89
89
|
useState<DesignTemplateSummary | null>(null);
|
|
90
90
|
const anchorElRef = useRef<HTMLElement | null>(null);
|
|
@@ -92,12 +92,19 @@ export default function Templates() {
|
|
|
92
92
|
const anchorRef = useRef<HTMLElement | null>(null);
|
|
93
93
|
anchorRef.current = anchorElRef.current;
|
|
94
94
|
|
|
95
|
-
const { data, isLoading, isError, isFetching, refetch } =
|
|
96
|
-
|
|
95
|
+
const { data, isLoading, isError, isFetching, refetch } = useActionQuery(
|
|
96
|
+
"list-design-templates",
|
|
97
|
+
{
|
|
97
98
|
includePreview: "true",
|
|
98
|
-
}
|
|
99
|
+
},
|
|
100
|
+
);
|
|
99
101
|
const createMutation = useActionMutation("create-design-from-template");
|
|
100
102
|
const deleteMutation = useActionMutation("delete-design-template");
|
|
103
|
+
const {
|
|
104
|
+
designSystems,
|
|
105
|
+
defaultSystem,
|
|
106
|
+
isLoading: designSystemsLoading,
|
|
107
|
+
} = useDesignSystems();
|
|
101
108
|
|
|
102
109
|
const templates = data?.templates ?? [];
|
|
103
110
|
const linkedTemplateId = searchParams.get("templateId");
|
|
@@ -112,8 +119,27 @@ export default function Templates() {
|
|
|
112
119
|
)
|
|
113
120
|
: templates;
|
|
114
121
|
}, [search, templates]);
|
|
115
|
-
const
|
|
116
|
-
const
|
|
122
|
+
const builtIns = filtered.filter((template) => template.isBuiltIn);
|
|
123
|
+
const userTemplates = filtered.filter((template) => !template.isBuiltIn);
|
|
124
|
+
|
|
125
|
+
const resolveTemplateDesignSystemId = (
|
|
126
|
+
template: DesignTemplateSummary,
|
|
127
|
+
): string | null => {
|
|
128
|
+
if (
|
|
129
|
+
template.designSystemId &&
|
|
130
|
+
designSystems.some((system) => system.id === template.designSystemId)
|
|
131
|
+
) {
|
|
132
|
+
return template.designSystemId;
|
|
133
|
+
}
|
|
134
|
+
return defaultSystem?.id ?? designSystems[0]?.id ?? null;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const setSelectedTemplateParam = (templateId: string | null) => {
|
|
138
|
+
const next = new URLSearchParams(searchParams);
|
|
139
|
+
if (templateId) next.set("templateId", templateId);
|
|
140
|
+
else next.delete("templateId");
|
|
141
|
+
setSearchParams(next, { replace: true });
|
|
142
|
+
};
|
|
117
143
|
|
|
118
144
|
useEffect(() => {
|
|
119
145
|
if (
|
|
@@ -125,7 +151,7 @@ export default function Templates() {
|
|
|
125
151
|
const template = templates.find(
|
|
126
152
|
(candidate) => candidate.id === linkedTemplateId,
|
|
127
153
|
);
|
|
128
|
-
if (!template) return;
|
|
154
|
+
if (!template || designSystemsLoading) return;
|
|
129
155
|
|
|
130
156
|
const card = document.getElementById(`design-template-${linkedTemplateId}`);
|
|
131
157
|
const useButton = card?.querySelector<HTMLElement>(
|
|
@@ -135,17 +161,21 @@ export default function Templates() {
|
|
|
135
161
|
handledTemplateIdRef.current = linkedTemplateId;
|
|
136
162
|
setSearch("");
|
|
137
163
|
setSelected(template);
|
|
164
|
+
setSelectedDesignSystemId(resolveTemplateDesignSystemId(template));
|
|
138
165
|
setPromptOpen(true);
|
|
139
166
|
card?.scrollIntoView({ block: "center", behavior: "smooth" });
|
|
140
167
|
useButton?.focus();
|
|
141
|
-
}, [linkedTemplateId, templates]);
|
|
168
|
+
}, [designSystemsLoading, linkedTemplateId, templates]);
|
|
142
169
|
|
|
143
170
|
const openTemplatePrompt = (
|
|
144
171
|
template: DesignTemplateSummary,
|
|
145
172
|
element: HTMLElement,
|
|
146
173
|
) => {
|
|
147
174
|
anchorElRef.current = element;
|
|
175
|
+
handledTemplateIdRef.current = template.id;
|
|
176
|
+
setSelectedTemplateParam(template.id);
|
|
148
177
|
setSelected(template);
|
|
178
|
+
setSelectedDesignSystemId(resolveTemplateDesignSystemId(template));
|
|
149
179
|
setPromptOpen(true);
|
|
150
180
|
};
|
|
151
181
|
|
|
@@ -156,40 +186,58 @@ export default function Templates() {
|
|
|
156
186
|
) => {
|
|
157
187
|
setCreating(true);
|
|
158
188
|
try {
|
|
159
|
-
const
|
|
189
|
+
const trimmedPrompt = prompt?.trim() ?? "";
|
|
190
|
+
const title = trimmedPrompt
|
|
191
|
+
? derivePromptTitle(trimmedPrompt)
|
|
192
|
+
: template.title;
|
|
193
|
+
const designSystemId =
|
|
194
|
+
selectedDesignSystemId === undefined
|
|
195
|
+
? resolveTemplateDesignSystemId(template)
|
|
196
|
+
: selectedDesignSystemId;
|
|
160
197
|
const result = (await createMutation.mutateAsync({
|
|
161
198
|
templateId: template.id,
|
|
162
199
|
title,
|
|
163
|
-
|
|
200
|
+
designSystemId,
|
|
201
|
+
...(trimmedPrompt ? { prompt: trimmedPrompt } : {}),
|
|
164
202
|
})) as {
|
|
165
|
-
id
|
|
203
|
+
id: string;
|
|
166
204
|
title?: string;
|
|
205
|
+
designSystemId?: string | null;
|
|
206
|
+
adaptationPending?: boolean;
|
|
167
207
|
templateBaselineFiles?: Array<{ id: string; contentHash: string }>;
|
|
168
208
|
};
|
|
169
209
|
if (!result.id)
|
|
170
210
|
throw new Error("Template copy did not return a design ID");
|
|
171
|
-
if (
|
|
211
|
+
if (result.adaptationPending) {
|
|
212
|
+
const effectiveDesignSystemId = result.designSystemId ?? null;
|
|
213
|
+
const effectiveSystemTitle =
|
|
214
|
+
designSystems.find((system) => system.id === effectiveDesignSystemId)
|
|
215
|
+
?.title ?? t("promptDialog.designSystem");
|
|
172
216
|
writePendingGeneration(result.id, {
|
|
173
|
-
prompt:
|
|
217
|
+
prompt:
|
|
218
|
+
trimmedPrompt ||
|
|
219
|
+
t("promptDialog.reskinTemplatePrompt", {
|
|
220
|
+
title: template.title,
|
|
221
|
+
system: effectiveSystemTitle,
|
|
222
|
+
}),
|
|
174
223
|
title: result.title ?? title,
|
|
175
224
|
source: template.title,
|
|
176
225
|
templateId: template.id,
|
|
177
226
|
templateBaselineFiles: result.templateBaselineFiles,
|
|
227
|
+
designSystemId: effectiveDesignSystemId,
|
|
178
228
|
skipQuestions: true,
|
|
179
229
|
...options,
|
|
180
230
|
});
|
|
181
231
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
232
|
+
void queryClient
|
|
233
|
+
.invalidateQueries({
|
|
234
|
+
queryKey: ["action", "list-designs"],
|
|
235
|
+
})
|
|
236
|
+
.catch(() => {});
|
|
185
237
|
navigate(`/design/${result.id}`);
|
|
186
238
|
} catch (error) {
|
|
187
239
|
setCreating(false);
|
|
188
|
-
|
|
189
|
-
error instanceof Error
|
|
190
|
-
? error.message
|
|
191
|
-
: t("templatesPage.createFailed"),
|
|
192
|
-
);
|
|
240
|
+
throw error;
|
|
193
241
|
}
|
|
194
242
|
};
|
|
195
243
|
|
|
@@ -199,7 +247,7 @@ export default function Templates() {
|
|
|
199
247
|
options: PromptComposerSubmitOptions,
|
|
200
248
|
) => {
|
|
201
249
|
if (!selected) return;
|
|
202
|
-
|
|
250
|
+
return createFromTemplate(selected, prompt, options);
|
|
203
251
|
};
|
|
204
252
|
|
|
205
253
|
const handleDelete = async () => {
|
|
@@ -254,6 +302,16 @@ export default function Templates() {
|
|
|
254
302
|
</p>
|
|
255
303
|
</div>
|
|
256
304
|
|
|
305
|
+
<div className="relative mb-6 md:hidden">
|
|
306
|
+
<IconSearch className="absolute start-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground/70" />
|
|
307
|
+
<Input
|
|
308
|
+
value={search}
|
|
309
|
+
onChange={(event) => setSearch(event.target.value)}
|
|
310
|
+
placeholder={t("templatesPage.searchPlaceholder")}
|
|
311
|
+
className="h-9 w-full bg-accent/50 ps-8 text-sm"
|
|
312
|
+
/>
|
|
313
|
+
</div>
|
|
314
|
+
|
|
257
315
|
{isLoading ? (
|
|
258
316
|
<TemplateGridSkeleton />
|
|
259
317
|
) : isError ? (
|
|
@@ -264,19 +322,19 @@ export default function Templates() {
|
|
|
264
322
|
) : (
|
|
265
323
|
<div className="flex flex-col gap-10">
|
|
266
324
|
<TemplateSection
|
|
267
|
-
title={t("templatesPage.
|
|
268
|
-
|
|
325
|
+
title={t("templatesPage.yourTemplates")}
|
|
326
|
+
description={t("templatesPage.yourTemplatesDescription")}
|
|
327
|
+
templates={userTemplates}
|
|
269
328
|
linkedTemplateId={linkedTemplateId}
|
|
329
|
+
empty={t("templatesPage.yourTemplatesEmpty")}
|
|
270
330
|
onUse={openTemplatePrompt}
|
|
331
|
+
onDelete={setDeleteTemplate}
|
|
271
332
|
/>
|
|
272
333
|
<TemplateSection
|
|
273
|
-
title={t("templatesPage.
|
|
274
|
-
|
|
275
|
-
templates={saved}
|
|
334
|
+
title={t("templatesPage.builtInTemplates")}
|
|
335
|
+
templates={builtIns}
|
|
276
336
|
linkedTemplateId={linkedTemplateId}
|
|
277
|
-
empty={t("templatesPage.savedEmpty")}
|
|
278
337
|
onUse={openTemplatePrompt}
|
|
279
|
-
onDelete={setDeleteTemplate}
|
|
280
338
|
/>
|
|
281
339
|
</div>
|
|
282
340
|
)}
|
|
@@ -286,17 +344,40 @@ export default function Templates() {
|
|
|
286
344
|
open={promptOpen}
|
|
287
345
|
onOpenChange={(open) => {
|
|
288
346
|
setPromptOpen(open);
|
|
289
|
-
if (!open)
|
|
347
|
+
if (!open) {
|
|
348
|
+
setSelected(null);
|
|
349
|
+
setSelectedDesignSystemId(undefined);
|
|
350
|
+
setSelectedTemplateParam(null);
|
|
351
|
+
}
|
|
290
352
|
}}
|
|
291
353
|
title={selected?.title ?? t("templatesPage.useTemplate")}
|
|
292
354
|
placeholder={t("templatesPage.promptPlaceholder")}
|
|
293
|
-
onSkip={() => {
|
|
294
|
-
if (selected)
|
|
355
|
+
onSkip={async () => {
|
|
356
|
+
if (!selected) return;
|
|
357
|
+
try {
|
|
358
|
+
await createFromTemplate(selected);
|
|
359
|
+
return false;
|
|
360
|
+
} catch (error) {
|
|
361
|
+
toast.error(
|
|
362
|
+
error instanceof Error
|
|
363
|
+
? error.message
|
|
364
|
+
: t("templatesPage.createFailed"),
|
|
365
|
+
);
|
|
366
|
+
throw error;
|
|
367
|
+
}
|
|
295
368
|
}}
|
|
296
369
|
skipLabel={t("templatesPage.useAsIs")}
|
|
297
370
|
onSubmit={handleSubmit}
|
|
298
371
|
anchorRef={anchorRef}
|
|
299
372
|
loading={creating}
|
|
373
|
+
designSystems={designSystems}
|
|
374
|
+
designSystemsLoading={designSystemsLoading}
|
|
375
|
+
selectedDesignSystemId={selectedDesignSystemId ?? null}
|
|
376
|
+
onDesignSystemChange={setSelectedDesignSystemId}
|
|
377
|
+
onCreateDesignSystem={() => {
|
|
378
|
+
setPromptOpen(false);
|
|
379
|
+
navigate("/design-systems/setup");
|
|
380
|
+
}}
|
|
300
381
|
/>
|
|
301
382
|
|
|
302
383
|
<AlertDialog
|
|
@@ -407,14 +488,24 @@ function TemplateCard({
|
|
|
407
488
|
<div className="flex min-h-40 flex-col p-4">
|
|
408
489
|
<div className="flex items-start gap-2">
|
|
409
490
|
<div className="min-w-0 flex-1">
|
|
410
|
-
<
|
|
411
|
-
|
|
412
|
-
|
|
491
|
+
<div className="flex min-w-0 items-center gap-2">
|
|
492
|
+
<h3 className="truncate text-sm font-medium text-foreground/90">
|
|
493
|
+
{template.title}
|
|
494
|
+
</h3>
|
|
495
|
+
{template.isBuiltIn ? (
|
|
496
|
+
<Badge
|
|
497
|
+
variant="secondary"
|
|
498
|
+
className="h-5 shrink-0 px-1.5 text-[10px] font-medium"
|
|
499
|
+
>
|
|
500
|
+
{t("templatesPage.builtIn")}
|
|
501
|
+
</Badge>
|
|
502
|
+
) : null}
|
|
503
|
+
</div>
|
|
413
504
|
<p className="mt-1 line-clamp-2 text-xs leading-relaxed text-muted-foreground">
|
|
414
505
|
{template.description}
|
|
415
506
|
</p>
|
|
416
507
|
</div>
|
|
417
|
-
{template.
|
|
508
|
+
{!template.isBuiltIn && template.isOwner ? (
|
|
418
509
|
<DropdownMenu>
|
|
419
510
|
<DropdownMenuTrigger asChild>
|
|
420
511
|
<Button
|
|
@@ -429,18 +520,16 @@ function TemplateCard({
|
|
|
429
520
|
</Button>
|
|
430
521
|
</DropdownMenuTrigger>
|
|
431
522
|
<DropdownMenuContent align="end">
|
|
432
|
-
|
|
433
|
-
<
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
) : null}
|
|
443
|
-
{template.isOwner && onDelete ? (
|
|
523
|
+
<div className="p-1">
|
|
524
|
+
<ShareButton
|
|
525
|
+
resourceType="design-template"
|
|
526
|
+
resourceId={template.id}
|
|
527
|
+
resourceTitle={template.title}
|
|
528
|
+
trigger="label"
|
|
529
|
+
triggerClassName="w-full justify-start"
|
|
530
|
+
/>
|
|
531
|
+
</div>
|
|
532
|
+
{onDelete ? (
|
|
444
533
|
<DropdownMenuItem
|
|
445
534
|
onClick={() => onDelete(template)}
|
|
446
535
|
className="text-destructive focus:text-destructive"
|
|
@@ -66,6 +66,17 @@ export function designSystemGenerationDirectives(
|
|
|
66
66
|
];
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
export function designSystemTemplateEditDirectives(
|
|
70
|
+
designSystemId?: string | null,
|
|
71
|
+
): string[] {
|
|
72
|
+
if (!designSystemId) return [];
|
|
73
|
+
return [
|
|
74
|
+
`Use design system id "${designSystemId}" while adapting the copied template.`,
|
|
75
|
+
"Use the selected design system context in this message as mandatory edit input. If details are missing or conflict, call `get-design-system` for that id before editing.",
|
|
76
|
+
"Apply the system through `edit-design` while preserving the copied structure and every locked subtree. Do not call `generate-design`.",
|
|
77
|
+
];
|
|
78
|
+
}
|
|
79
|
+
|
|
69
80
|
interface DesignSystemGenerationContextResult {
|
|
70
81
|
title?: string;
|
|
71
82
|
agentContext?: string;
|
|
@@ -169,7 +180,7 @@ export function designTemplateRefinementDirectives(
|
|
|
169
180
|
): string[] {
|
|
170
181
|
return [
|
|
171
182
|
`This design was copied from template "${templateId}". Its files, canvas dimensions, defaults, and locked layers already exist.`,
|
|
172
|
-
...
|
|
183
|
+
...designSystemTemplateEditDirectives(designSystemId),
|
|
173
184
|
`Call \`get-design-snapshot --designId="${designId}"\` exactly once before editing.`,
|
|
174
185
|
"Refine the existing template with `edit-design`; do not call `generate-design`, `delete-file`, or create a replacement screen.",
|
|
175
186
|
'Layers marked `data-agent-native-locked="true"` and everything inside them must remain byte-for-byte unchanged. The server rejects changes to locked backgrounds, logos, and other fixed template layers.',
|
|
@@ -64,7 +64,7 @@ When the user asks for a new design and the current navigation view is list, set
|
|
|
64
64
|
|
|
65
65
|
Every web design must be responsive. Use mobile-first CSS, a viewport meta tag, and responsive layout changes for narrow widths; never ship a fixed-width desktop shell. Desktop is the default primary artboard: use a 1440×1024 canvas frame (or primaryViewport "desktop") unless the user explicitly asks for a mobile- or tablet-primary design. After generation, inspect desktop and mobile screenshots and correct overflow or broken reflow before reporting completion.
|
|
66
66
|
|
|
67
|
-
When the user asks to start from a template, call list-design-templates and
|
|
67
|
+
When the user asks to start from a template or references a prior design/past work as the starting point, call both list-design-templates and list-designs before generating so you resolve the existing resource instead of recreating it. For a template, call create-design-from-template. The copied files and canvas dimensions are already the starting point. If the user also supplied a prompt or selected a different linked design system, call get-design-snapshot once and refine unlocked content with edit-design; do not call generate-design or replace the template with a fresh screen. Layers marked data-agent-native-locked="true" and their descendants must remain byte-for-byte unchanged. Ask the user to unlock one explicitly if they want it changed.
|
|
68
68
|
|
|
69
69
|
When the user asks you to refine an existing design, call view-screen if the open design is unclear, then read the live current file with get-design-snapshot before editing. For small localized changes, call edit-design with exact search/replace edits. For broad copy-only changes such as translating all visible text, call edit-design in replace-file mode with the complete updated file content from the snapshot so the HTML structure, scripts, styles, and tweaks are preserved without dozens of fragile search blocks. Do not claim the design is updated until the mutating action succeeds.
|
|
70
70
|
|
|
@@ -84,6 +84,11 @@ needed.
|
|
|
84
84
|
call `refresh-list` so the UI refetches. Actions that already write
|
|
85
85
|
`refresh-signal` internally (e.g. `mark-thread-read`, `move-email`,
|
|
86
86
|
`respond-calendar-invite`) don't need a second call.
|
|
87
|
+
- For broad unread cleanup in one account, call `mark-read` once with
|
|
88
|
+
`scope: "all-unread"`, the exact `accountEmail`, and any protected
|
|
89
|
+
conversation IDs in `excludeThreadIds`. Do not loop `mark-thread-read` over
|
|
90
|
+
many conversations. The bulk result's matched, excluded, changed, failure,
|
|
91
|
+
and remaining-unread counts are the proof of completion.
|
|
87
92
|
- Use `view-screen` when the active thread, selected message, draft, or queue
|
|
88
93
|
item is unclear.
|
|
89
94
|
- Aliases (Settings → Aliases) and provider API-key connections (Gong, Pylon,
|
|
@@ -94,24 +99,24 @@ needed.
|
|
|
94
99
|
|
|
95
100
|
## Action Map
|
|
96
101
|
|
|
97
|
-
| Action | Purpose
|
|
98
|
-
| -------------------------------------------------------------------------------------------------------------------------------------- |
|
|
99
|
-
| `search-emails` / `list-emails` | Query across Gmail or local-fallback data by view/query.
|
|
100
|
-
| `get-email` / `get-thread` | Full body/metadata for one message or thread.
|
|
101
|
-
| `find-contact` | Resolve a name/partial address to a real email.
|
|
102
|
-
| `get-hubspot-contact` | CRM contact + deals + tickets by email (HubSpot only).
|
|
103
|
-
| `create-attachment-upload` | Mint a five-minute, owner-bound raw-byte upload URL for one local attachment.
|
|
104
|
-
| `manage-draft` | Create/update/delete a `compose-{id}` draft (signature-aware).
|
|
105
|
-
| `send-email` | Real send. `needsApproval: true`; exact authenticated chat grants run once, otherwise it pauses for approval.
|
|
106
|
-
| `queue-email-draft` / `list-queued-drafts` / `update-queued-draft` / `open-queued-draft` / `send-queued-drafts` | Teammate/Slack draft-review workflow — see `draft-queue`.
|
|
107
|
-
| `mark-read` / `mark-thread-read` / `star-email` / `archive-email` / `unarchive-email` / `trash-email` / `untrash-email` / `move-email` | Per-message or per-thread state changes; most call `refresh-list` internally.
|
|
108
|
-
| `manage-gmail-filters` | Provider-native Gmail filters (create/replace/delete).
|
|
109
|
-
| `manage-automations` / `trigger-automations` | Natural-language inbox automation rules.
|
|
110
|
-
| `respond-calendar-invite` | Accept/decline/tentative an invite found in Mail.
|
|
111
|
-
| `get-mail-settings` / `update-mail-settings` / `import-gmail-signature` | Signature and writing-style settings.
|
|
112
|
-
| `manage-snippets` | List/create/update/delete saved reply snippets insertable from the compose slash menu.
|
|
113
|
-
| `get-tracking` | Open/click stats for a previously sent, tracked message.
|
|
114
|
-
| `provider-api-catalog` / `provider-api-docs` / `provider-api-request` | Raw Gmail, Calendar, or HubSpot API calls beyond the canned actions.
|
|
102
|
+
| Action | Purpose |
|
|
103
|
+
| -------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
104
|
+
| `search-emails` / `list-emails` | Query across Gmail or local-fallback data by view/query. |
|
|
105
|
+
| `get-email` / `get-thread` | Full body/metadata for one message or thread. |
|
|
106
|
+
| `find-contact` | Resolve a name/partial address to a real email. |
|
|
107
|
+
| `get-hubspot-contact` | CRM contact + deals + tickets by email (HubSpot only). |
|
|
108
|
+
| `create-attachment-upload` | Mint a five-minute, owner-bound raw-byte upload URL for one local attachment. |
|
|
109
|
+
| `manage-draft` | Create/update/delete a `compose-{id}` draft (signature-aware). |
|
|
110
|
+
| `send-email` | Real send. `needsApproval: true`; exact authenticated chat grants run once, otherwise it pauses for approval. |
|
|
111
|
+
| `queue-email-draft` / `list-queued-drafts` / `update-queued-draft` / `open-queued-draft` / `send-queued-drafts` | Teammate/Slack draft-review workflow — see `draft-queue`. |
|
|
112
|
+
| `mark-read` / `mark-thread-read` / `star-email` / `archive-email` / `unarchive-email` / `trash-email` / `untrash-email` / `move-email` | Per-message or per-thread state changes. `mark-read` also supports one-account verified bulk unread cleanup with protected-thread exclusions; most call `refresh-list` internally. |
|
|
113
|
+
| `manage-gmail-filters` | Provider-native Gmail filters (create/replace/delete). |
|
|
114
|
+
| `manage-automations` / `trigger-automations` | Natural-language inbox automation rules. |
|
|
115
|
+
| `respond-calendar-invite` | Accept/decline/tentative an invite found in Mail. |
|
|
116
|
+
| `get-mail-settings` / `update-mail-settings` / `import-gmail-signature` | Signature and writing-style settings. |
|
|
117
|
+
| `manage-snippets` | List/create/update/delete saved reply snippets insertable from the compose slash menu. |
|
|
118
|
+
| `get-tracking` | Open/click stats for a previously sent, tracked message. |
|
|
119
|
+
| `provider-api-catalog` / `provider-api-docs` / `provider-api-request` | Raw Gmail, Calendar, or HubSpot API calls beyond the canned actions. |
|
|
115
120
|
|
|
116
121
|
## Application State
|
|
117
122
|
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { defineAction } from "@agent-native/core";
|
|
2
|
-
import {
|
|
2
|
+
import { getRequestUserEmail } from "@agent-native/core/server";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
|
|
5
|
+
import {
|
|
6
|
+
readLocalEmails,
|
|
7
|
+
withLocalEmailMutationLock,
|
|
8
|
+
writeLocalEmails,
|
|
9
|
+
} from "../server/lib/local-email-store.js";
|
|
10
|
+
|
|
5
11
|
export default defineAction({
|
|
6
12
|
description:
|
|
7
13
|
"Archive emails older than N days from inbox (local data only — use archive-email for Gmail-connected accounts).",
|
|
@@ -19,34 +25,32 @@ export default defineAction({
|
|
|
19
25
|
if (isNaN(days) || days < 1)
|
|
20
26
|
throw new Error("--older-than must be a positive integer (days)");
|
|
21
27
|
|
|
22
|
-
const
|
|
23
|
-
if (!
|
|
24
|
-
throw new Error(
|
|
25
|
-
"No local emails data found. This tool only works with local data.",
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
+
const ownerEmail = getRequestUserEmail();
|
|
29
|
+
if (!ownerEmail) throw new Error("no authenticated user");
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
31
|
+
return withLocalEmailMutationLock(ownerEmail, async () => {
|
|
32
|
+
const emails = await readLocalEmails(ownerEmail);
|
|
33
|
+
const cutoff = Date.now() - days * 24 * 60 * 60 * 1000;
|
|
34
|
+
let archived = 0;
|
|
35
|
+
const updated = emails.map((email) => {
|
|
36
|
+
if (
|
|
37
|
+
!email.isArchived &&
|
|
38
|
+
!email.isTrashed &&
|
|
39
|
+
!email.isDraft &&
|
|
40
|
+
new Date(email.date).getTime() < cutoff
|
|
41
|
+
) {
|
|
42
|
+
archived++;
|
|
43
|
+
return {
|
|
44
|
+
...email,
|
|
45
|
+
isArchived: true,
|
|
46
|
+
labelIds: email.labelIds.filter((label) => label !== "inbox"),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return email;
|
|
50
|
+
});
|
|
48
51
|
|
|
49
|
-
|
|
50
|
-
|
|
52
|
+
await writeLocalEmails(ownerEmail, updated);
|
|
53
|
+
return `Archived ${archived} email(s) older than ${days} days (${emails.length} total)`;
|
|
54
|
+
});
|
|
51
55
|
},
|
|
52
56
|
});
|