@agent-native/core 0.80.4 → 0.80.5
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 +2 -2
- package/corpus/core/CHANGELOG.md +21 -2
- package/corpus/core/docs/content/locales/ar-SA/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/de-DE/real-time-collaboration.mdx +3 -3
- package/corpus/core/docs/content/locales/de-DE/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/es-ES/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/es-ES/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/fr-FR/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/ja-JP/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/ko-KR/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/pt-BR/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-CN/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-TW/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +1 -1
- package/corpus/core/docs/content/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/template-design.mdx +1 -1
- package/corpus/core/package.json +3 -7
- package/corpus/core/src/action.ts +21 -0
- package/corpus/core/src/agent/durable-background.ts +32 -11
- package/corpus/core/src/agent/production-agent.ts +11 -1
- package/corpus/core/src/agent/run-loop-with-resume.ts +3 -1
- package/corpus/core/src/brand-kit/fig/index.ts +17 -37
- package/corpus/core/src/cli/index.ts +1 -1
- package/corpus/core/src/cli/mcp-config-writers.ts +187 -51
- package/corpus/core/src/cli/skills.ts +18 -3
- package/corpus/core/src/client/AssistantChat.tsx +11 -1
- package/corpus/core/src/client/agent-chat.ts +12 -1
- package/corpus/core/src/client/composer/PromptComposer.tsx +100 -41
- package/corpus/core/src/client/org/OrgSwitcher.tsx +1 -1
- package/corpus/core/src/client/sharing/ShareButton.tsx +3 -27
- package/corpus/core/src/collab/presence.ts +1 -1
- package/corpus/core/src/mcp/connect-route.ts +34 -5
- package/corpus/core/src/server/action-discovery.ts +4 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +20 -0
- package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +2 -0
- package/corpus/templates/analytics/actions/update-dashboard.ts +8 -0
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +117 -33
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +4 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +7 -0
- package/corpus/templates/analytics/changelog/2026-06-27-dashboards-can-now-nest-under-a-parent-in-the-sidebar-via-a-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-29-analytics-pages-now-sit-closer-under-the-header-with-tighter.md +6 -0
- package/corpus/templates/assets/actions/generate-image-batch.ts +3 -0
- package/corpus/templates/assets/actions/generate-image.ts +3 -0
- package/corpus/templates/assets/changelog/2026-06-29-longer-agent-generation-window.md +6 -0
- package/corpus/templates/assets/netlify.toml +3 -3
- package/corpus/templates/assets/server/plugins/agent-chat.ts +4 -1
- package/corpus/templates/clips/app/components/capture-install-options.tsx +7 -8
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +1 -1
- package/corpus/templates/content/AGENTS.md +12 -0
- package/corpus/templates/content/app/blocks/BuilderDocsBlocks.tsx +10 -0
- package/corpus/templates/content/app/components/editor/BubbleToolbar.tsx +1 -0
- package/corpus/templates/content/app/components/editor/ContentReferencePreview.tsx +185 -0
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +3 -0
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +19 -0
- package/corpus/templates/content/app/components/editor/extensions/ContentReferenceNode.tsx +82 -0
- package/corpus/templates/content/app/global.css +9 -0
- package/corpus/templates/content/app/i18n/zh-TW.ts +12 -0
- package/corpus/templates/content/app/i18n-data.ts +140 -0
- package/corpus/templates/content/changelog/2026-06-29-reusable-mdx-references-now-preview-linked-local-documents-i.md +6 -0
- package/corpus/templates/content/shared/builder-docs-blocks.ts +8 -0
- package/corpus/templates/content/shared/builder-mdx.ts +141 -4
- package/corpus/templates/content/shared/nfm.ts +62 -0
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +10 -11
- package/corpus/templates/design/AGENTS.md +5 -0
- package/corpus/templates/design/_gitignore +7 -0
- package/corpus/templates/design/actions/apply-visual-edit.ts +22 -12
- package/corpus/templates/design/actions/create-design-system.ts +15 -4
- package/corpus/templates/design/actions/create-file.ts +20 -1
- package/corpus/templates/design/actions/delete-design-system.ts +2 -2
- package/corpus/templates/design/actions/duplicate-design.ts +35 -9
- package/corpus/templates/design/actions/generate-design.ts +146 -69
- package/corpus/templates/design/actions/generate-screens.ts +51 -19
- package/corpus/templates/design/actions/get-design-snapshot.ts +5 -1
- package/corpus/templates/design/actions/get-design.ts +2 -0
- package/corpus/templates/design/actions/import-design-project.ts +28 -9
- package/corpus/templates/design/actions/import-document.ts +22 -8
- package/corpus/templates/design/actions/index-design-system-with-builder.ts +6 -153
- package/corpus/templates/design/actions/navigate.ts +105 -54
- package/corpus/templates/design/actions/set-default-design-system.ts +17 -3
- package/corpus/templates/design/actions/show-design-questions.ts +2 -0
- package/corpus/templates/design/actions/update-design.ts +2 -1
- package/corpus/templates/design/actions/view-screen.ts +12 -6
- package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +4 -4
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +159 -41
- package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +8 -4
- package/corpus/templates/design/app/components/design/DrawOverlay.tsx +37 -42
- package/corpus/templates/design/app/components/design/EditPanel.tsx +336 -183
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +153 -34
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +135 -33
- package/corpus/templates/design/app/components/design/QuestionFlow.tsx +6 -0
- package/corpus/templates/design/app/components/design/TweaksPanel.tsx +2 -1
- package/corpus/templates/design/app/components/design/inspector/AlignmentMatrix.tsx +4 -10
- package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +84 -43
- package/corpus/templates/design/app/components/design/inspector/ConstraintsWidget.tsx +4 -4
- package/corpus/templates/design/app/components/design/inspector/{FigmaColorPicker.tsx → DesignColorPicker.tsx} +89 -62
- package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +14 -26
- package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +40 -12
- package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +13 -4
- package/corpus/templates/design/app/components/design/inspector/SHADER_INTEGRATION.md +13 -13
- package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +13 -9
- package/corpus/templates/design/app/components/design/inspector/ShaderControls.tsx +13 -4
- package/corpus/templates/design/app/components/design/inspector/ShaderFillsPanel.tsx +6 -6
- package/corpus/templates/design/app/components/design/inspector/{figma-icons.tsx → design-icons.tsx} +2 -2
- package/corpus/templates/design/app/components/design/inspector/index.ts +12 -12
- package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +5 -2
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +3 -3
- package/corpus/templates/design/app/components/layout/Layout.tsx +5 -2
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +1 -1
- package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +167 -91
- package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +16 -3
- package/corpus/templates/design/app/components/visual-editor/SaveStatusIndicator.tsx +15 -0
- package/corpus/templates/design/app/global.css +4 -0
- package/corpus/templates/design/app/hooks/use-design-system.ts +4 -1
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +38 -3
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +9 -2
- package/corpus/templates/design/app/i18n/zh-TW.ts +22 -0
- package/corpus/templates/design/app/i18n-data.ts +527 -0
- package/corpus/templates/design/app/lib/design-systems.ts +6 -4
- package/corpus/templates/design/app/lib/design-templates.ts +15 -3
- package/corpus/templates/design/app/pages/DesignEditor.tsx +641 -158
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +42 -34
- package/corpus/templates/design/app/pages/VisualEdit.tsx +100 -0
- package/corpus/templates/design/app/root.tsx +42 -9
- package/corpus/templates/design/app/routes/visual-edit.tsx +7 -0
- package/corpus/templates/design/changelog/2026-06-28-live-cursors-now-keep-names-beside-a-cleaner-pointer-marker.md +1 -1
- package/corpus/templates/design/changelog/2026-06-28-mode-switching-now-lives-in-a-compact-bottom-right-icon-dock.md +1 -1
- package/corpus/templates/design/changelog/2026-06-28-visual-code-design-mode.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-design-generation-prompts-now-show-connect-ai-before-sending.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-design-mode-top-chrome-now-groups-collaborators-preview-shar.md +1 -1
- package/corpus/templates/design/changelog/2026-06-29-fixed-design-editor-exports-and-gradient-edits-so-multi-scre.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-longer-hosted-agent-turns.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-png-export-handles-modern-css-color-functions-more-reliably.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-png-export-now-ignores-duplicate-clicks-while-a-download-is-.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-public-visual-edit-and-shared-design-links-now-invite-visito.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-visual-edit-actions-now-reject-missing-design-targets-before.md +6 -0
- package/corpus/templates/design/e2e/README.md +71 -0
- package/corpus/templates/design/e2e/global-setup.ts +157 -0
- package/corpus/templates/design/e2e/helpers.ts +148 -0
- package/corpus/templates/design/netlify.toml +3 -4
- package/corpus/templates/design/package.json +5 -1
- package/corpus/templates/design/playwright.config.ts +51 -0
- package/corpus/templates/design/server/handlers/index-design-system-with-builder.ts +121 -0
- package/corpus/templates/design/server/handlers/uploads.ts +89 -38
- package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +181 -0
- package/corpus/templates/design/server/lib/coding-handoff.ts +33 -4
- package/corpus/templates/design/server/lib/design-export.ts +35 -8
- package/corpus/templates/design/server/plugins/agent-chat.ts +4 -0
- package/corpus/templates/design/server/plugins/auth.ts +10 -1
- package/corpus/templates/design/server/routes/api/index-design-system-with-builder.post.ts +1 -0
- package/corpus/templates/design/shared/api.ts +2 -0
- package/corpus/templates/design/shared/apply-edits.ts +12 -8
- package/corpus/templates/design/shared/canvas-math.ts +19 -1
- package/corpus/templates/design/shared/code-layer.ts +87 -28
- package/corpus/templates/design/shared/generation-session.ts +1 -0
- package/corpus/templates/design/shared/resolve-tweaks.ts +4 -3
- package/corpus/templates/design/shared/shader-presets.ts +10 -0
- package/corpus/templates/design/shared/source-mode.ts +9 -0
- package/corpus/templates/design/vitest.config.ts +2 -1
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +1 -1
- package/corpus/templates/plan/.agents/skills/visual-plan/references/canvas.md +1 -1
- package/corpus/templates/plan/AGENTS.md +1 -1
- package/corpus/templates/plan/actions/create-plan-design.ts +1 -1
- package/corpus/templates/plan/actions/validate-local-plan-source.ts +2 -10
- package/corpus/templates/plan/app/pages/PlansPage.tsx +1 -0
- package/corpus/templates/plan/docs/commenting-ux-plan.md +2 -2
- package/corpus/templates/plan/server/plan-content.ts +1 -1
- package/corpus/templates/plan/server/ui-plan-html.ts +2 -2
- package/corpus/templates/slides/actions/index-design-system-with-builder.ts +6 -153
- package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +53 -38
- package/corpus/templates/slides/app/components/design-system/{fig-import-response.ts → builder-index-response.ts} +9 -6
- package/corpus/templates/slides/app/components/visual-editor/MultiSelectChip.tsx +1 -1
- package/corpus/templates/slides/changelog/2026-06-29-design-system-setup-now-indexes-uploaded-design-files-throug.md +6 -0
- package/corpus/templates/slides/changelog/2026-06-29-longer-hosted-agent-turns.md +6 -0
- package/corpus/templates/slides/netlify.toml +3 -6
- package/corpus/templates/slides/server/handlers/index-design-system-with-builder.ts +116 -0
- package/corpus/templates/slides/server/lib/builder-design-system-proxy.ts +179 -0
- package/corpus/templates/slides/server/plugins/agent-chat.ts +4 -1
- package/corpus/templates/slides/server/routes/api/index-design-system-with-builder.post.ts +1 -0
- package/dist/action.d.ts +15 -0
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js +6 -0
- package/dist/action.js.map +1 -1
- package/dist/agent/durable-background.d.ts +9 -7
- package/dist/agent/durable-background.d.ts.map +1 -1
- package/dist/agent/durable-background.js +27 -11
- package/dist/agent/durable-background.js.map +1 -1
- package/dist/agent/production-agent.d.ts +7 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +4 -1
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-loop-with-resume.d.ts +2 -1
- package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
- package/dist/agent/run-loop-with-resume.js +2 -2
- package/dist/agent/run-loop-with-resume.js.map +1 -1
- package/dist/brand-kit/fig/index.d.ts +4 -4
- package/dist/brand-kit/fig/index.d.ts.map +1 -1
- package/dist/brand-kit/fig/index.js +14 -27
- package/dist/brand-kit/fig/index.js.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-config-writers.d.ts +15 -7
- package/dist/cli/mcp-config-writers.d.ts.map +1 -1
- package/dist/cli/mcp-config-writers.js +198 -45
- package/dist/cli/mcp-config-writers.js.map +1 -1
- package/dist/cli/skills.d.ts +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +18 -3
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +11 -1
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +15 -2
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/composer/PromptComposer.d.ts.map +1 -1
- package/dist/client/composer/PromptComposer.js +35 -1
- package/dist/client/composer/PromptComposer.js.map +1 -1
- package/dist/client/org/OrgSwitcher.js +1 -1
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/sharing/ShareButton.d.ts +1 -1
- package/dist/client/sharing/ShareButton.d.ts.map +1 -1
- package/dist/client/sharing/ShareButton.js +2 -15
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/collab/presence.d.ts +1 -1
- package/dist/collab/presence.js +1 -1
- package/dist/collab/presence.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/mcp/connect-route.d.ts.map +1 -1
- package/dist/mcp/connect-route.js +34 -5
- package/dist/mcp/connect-route.js.map +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +3 -3
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +5 -0
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +6 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +12 -3
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/docs/content/locales/ar-SA/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/ar-SA/template-design.mdx +1 -1
- package/docs/content/locales/de-DE/real-time-collaboration.mdx +3 -3
- package/docs/content/locales/de-DE/template-design.mdx +1 -1
- package/docs/content/locales/es-ES/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/es-ES/template-design.mdx +1 -1
- package/docs/content/locales/fr-FR/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/fr-FR/template-design.mdx +1 -1
- package/docs/content/locales/hi-IN/template-design.mdx +1 -1
- package/docs/content/locales/ja-JP/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/ja-JP/template-design.mdx +1 -1
- package/docs/content/locales/ko-KR/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/ko-KR/template-design.mdx +1 -1
- package/docs/content/locales/pt-BR/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/pt-BR/template-design.mdx +1 -1
- package/docs/content/locales/zh-CN/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/zh-CN/template-design.mdx +1 -1
- package/docs/content/locales/zh-TW/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/zh-TW/template-design.mdx +1 -1
- package/docs/content/real-time-collaboration.mdx +2 -2
- package/docs/content/template-design.mdx +1 -1
- package/package.json +3 -7
- package/corpus/core/src/brand-kit/fig/decode.ts +0 -410
- package/corpus/core/src/brand-kit/fig/extract-design-system.ts +0 -947
- package/corpus/core/src/brand-kit/fig/fig-to-html.ts +0 -1906
- package/corpus/templates/design/actions/import-figma.ts +0 -55
- package/corpus/templates/design/changelog/2026-06-28-figma-style-code-design-mode.md +0 -6
- package/corpus/templates/design/server/handlers/import-figma-system.ts +0 -86
- package/corpus/templates/design/server/routes/api/import-figma-system.post.ts +0 -1
- package/corpus/templates/slides/server/handlers/import-figma-system.ts +0 -101
- package/corpus/templates/slides/server/routes/api/import-figma-system.post.ts +0 -1
- package/dist/brand-kit/fig/decode.d.ts +0 -33
- package/dist/brand-kit/fig/decode.d.ts.map +0 -1
- package/dist/brand-kit/fig/decode.js +0 -358
- package/dist/brand-kit/fig/decode.js.map +0 -1
- package/dist/brand-kit/fig/extract-design-system.d.ts +0 -44
- package/dist/brand-kit/fig/extract-design-system.d.ts.map +0 -1
- package/dist/brand-kit/fig/extract-design-system.js +0 -752
- package/dist/brand-kit/fig/extract-design-system.js.map +0 -1
- package/dist/brand-kit/fig/fig-to-html.d.ts +0 -246
- package/dist/brand-kit/fig/fig-to-html.d.ts.map +0 -1
- package/dist/brand-kit/fig/fig-to-html.js +0 -1506
- package/dist/brand-kit/fig/fig-to-html.js.map +0 -1
|
@@ -765,6 +765,16 @@ export function validateDescriptor(descriptor: ShaderDescriptor): {
|
|
|
765
765
|
if (def.max !== undefined && num > def.max) {
|
|
766
766
|
errors.push(`Param "${key}" value ${num} is above maximum ${def.max}`);
|
|
767
767
|
}
|
|
768
|
+
} else if (def.kind === "enum") {
|
|
769
|
+
if (def.options && !def.options.includes(value as string)) {
|
|
770
|
+
errors.push(
|
|
771
|
+
`Param "${key}" value "${value}" is not in allowed options: ${def.options.join(", ")}`,
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
} else if (def.kind === "bool") {
|
|
775
|
+
if (typeof value !== "boolean") {
|
|
776
|
+
errors.push(`Param "${key}" must be a boolean`);
|
|
777
|
+
}
|
|
768
778
|
}
|
|
769
779
|
}
|
|
770
780
|
|
|
@@ -213,8 +213,17 @@ export function normalizeDesignSourceType(
|
|
|
213
213
|
export function makeLocalhostRouteId(path: string): string {
|
|
214
214
|
const normalized = path.trim() || "/";
|
|
215
215
|
if (normalized === "/") return "route-root";
|
|
216
|
+
// Pure wildcard routes ("/*", "/**") collapse to a single id.
|
|
217
|
+
if (/^\/\*+$/.test(normalized)) return "route-wildcard";
|
|
218
|
+
// Encode structural characters distinctly BEFORE collapsing non-alphanumerics,
|
|
219
|
+
// otherwise paths like "/design/:id" and "/design-id", or "/users" and
|
|
220
|
+
// "/users/*", produce identical ids and silently overwrite each other in the
|
|
221
|
+
// route manifest map.
|
|
216
222
|
const slug = normalized
|
|
217
223
|
.replace(/^\/+/, "")
|
|
224
|
+
.replace(/\*/g, "w") // wildcard segment
|
|
225
|
+
.replace(/:/g, "p") // route param prefix (":id" -> "pid")
|
|
226
|
+
.replace(/[[\]]/g, "") // strip [id] bracket syntax
|
|
218
227
|
.replace(/[^a-zA-Z0-9]+/g, "-")
|
|
219
228
|
.replace(/^-+|-+$/g, "")
|
|
220
229
|
.toLowerCase();
|
|
@@ -9,6 +9,7 @@ export default {
|
|
|
9
9
|
},
|
|
10
10
|
test: {
|
|
11
11
|
include: ["**/*.{test,spec}.?(c|m)[jt]s?(x)"],
|
|
12
|
-
|
|
12
|
+
// e2e/ holds Playwright (@playwright/test) specs; run via `pnpm e2e`, not vitest.
|
|
13
|
+
exclude: ["**/node_modules/**", "**/.git/**", "**/dist/**", "**/e2e/**"],
|
|
13
14
|
},
|
|
14
15
|
};
|
|
@@ -1317,7 +1317,7 @@ function AppLayoutInner({ children }: AppLayoutProps) {
|
|
|
1317
1317
|
<TooltipContent>{t("mail.toolbar.composeShortcut")}</TooltipContent>
|
|
1318
1318
|
</Tooltip>
|
|
1319
1319
|
|
|
1320
|
-
{/* Account avatars — overlapping stack
|
|
1320
|
+
{/* Account avatars — overlapping stack */}
|
|
1321
1321
|
{googleStatus.isLoading && (
|
|
1322
1322
|
<div className="flex items-center ms-1">
|
|
1323
1323
|
<Skeleton className="h-7 w-7 rounded-full ring-2 ring-card" />
|
|
@@ -35,7 +35,7 @@ and move any frame whose label, connector, or annotation crosses another frame.
|
|
|
35
35
|
When in doubt, use larger values — the canvas auto-zooms to fit everything.
|
|
36
36
|
|
|
37
37
|
**Canvas annotations are designer notes on the artboard.** When a top canvas is
|
|
38
|
-
present, sprinkle
|
|
38
|
+
present, sprinkle design-review notes near the frames they explain: a short
|
|
39
39
|
heading, supporting text, and bullets — plain text layers, never bordered or
|
|
40
40
|
shadowed cards, and never a box around a frame. The renderer spaces notes away
|
|
41
41
|
from frames, so place each note by the frame it describes. Use an arrow only to
|
|
@@ -225,7 +225,7 @@ elementId, styles }]`. Elements must have `data-design-id` or
|
|
|
225
225
|
`data-plan-design-id`; use `patch-wireframe-html` / `patch-prototype-html` for
|
|
226
226
|
structural or text changes.
|
|
227
227
|
- Plan comments include reviewer identity, @mentions, resolver intent
|
|
228
|
-
(`agent` or `human`), exact anchors, and
|
|
228
|
+
(`agent` or `human`), exact anchors, and design-review threads. When adding
|
|
229
229
|
human feedback through `update-visual-plan`, preserve `authorEmail` and
|
|
230
230
|
`authorName` when known; pass `parentCommentId` to reply inline to an
|
|
231
231
|
existing comment thread. Text feedback should anchor to the nearest prose
|
|
@@ -102,7 +102,7 @@ const designContextRecordSchema = z.record(z.string(), z.unknown()).refine(
|
|
|
102
102
|
|
|
103
103
|
export default defineAction({
|
|
104
104
|
description:
|
|
105
|
-
"Create a full-fidelity branded design plan with a Design tab (
|
|
105
|
+
"Create a full-fidelity branded design plan with a Design tab (editable design canvas) and optional Prototype tab. For a document-first plan use create-visual-plan; for a wireframe-canvas plan use create-ui-plan; for a recap of an existing diff use create-visual-recap; for a functional prototype use create-prototype-plan. Use design.md, .fig brand kits, and codebase CSS/Tailwind/token evidence when available. Design screens are bounded HTML/CSS fragments with data-design-id targets. Publish via this tool; never deliver the plan as inline chat text.",
|
|
106
106
|
schema: z
|
|
107
107
|
.object({
|
|
108
108
|
title: z.string().optional().describe("Short design plan title"),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineAction } from "@agent-native/core";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
|
|
4
|
-
import { parsePlanMdxFolder,
|
|
4
|
+
import { parsePlanMdxFolder, planMdxFileSchema } from "../server/plan-mdx.js";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Authoritative validation for a local plan MDX folder.
|
|
@@ -21,14 +21,6 @@ import { parsePlanMdxFolder, type PlanMdxFolder } from "../server/plan-mdx.js";
|
|
|
21
21
|
// large-but-valid plans still get authoritative validation instead of the lint.
|
|
22
22
|
const MAX_MDX_BYTES = 16 * 1024 * 1024;
|
|
23
23
|
|
|
24
|
-
const mdxFolderSchema = z.object({
|
|
25
|
-
"plan.mdx": z.string().min(1),
|
|
26
|
-
"canvas.mdx": z.string().optional(),
|
|
27
|
-
"prototype.mdx": z.string().optional(),
|
|
28
|
-
".plan-state.json": z.string().optional(),
|
|
29
|
-
"assets/": z.record(z.string(), z.string()).optional(),
|
|
30
|
-
}) satisfies z.ZodType<PlanMdxFolder>;
|
|
31
|
-
|
|
32
24
|
type ValidationIssue = { path: string; message: string };
|
|
33
25
|
|
|
34
26
|
function formatZodPath(segments: Array<string | number>): string {
|
|
@@ -73,7 +65,7 @@ export default defineAction({
|
|
|
73
65
|
description:
|
|
74
66
|
"Validate a local plan MDX folder against the live Plan renderer schema (parsePlanMdxFolder + planContentSchema). Returns { valid, issues } where issues carry the renderer's exact schema path (e.g. blocks[1].data.items[0].id). Use this to confirm a plan will render before handing it off — it is the authoritative check behind `plan local verify`. Pure parse: no database, filesystem, or schema.plans access.",
|
|
75
67
|
schema: z.object({
|
|
76
|
-
mdx:
|
|
68
|
+
mdx: planMdxFileSchema.describe(
|
|
77
69
|
"The plan MDX folder: plan.mdx plus optional canvas.mdx, prototype.mdx, .plan-state.json, and assets/.",
|
|
78
70
|
),
|
|
79
71
|
}),
|
|
@@ -9083,6 +9083,7 @@ function CreatePlanDialog({
|
|
|
9083
9083
|
disabled={composerLocked}
|
|
9084
9084
|
attachmentsEnabled={false}
|
|
9085
9085
|
showModelSelector={false}
|
|
9086
|
+
modelStatusChecksEnabled={false}
|
|
9086
9087
|
placeholder={t("plansPage.create.placeholder")}
|
|
9087
9088
|
draftScope="plans:create-plan"
|
|
9088
9089
|
initialText={promptSeed}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
> clarity** on (a) exactly what is commented on — which text, which part of an
|
|
6
6
|
> image / wireframe / canvas, with a focused marked screenshot for visual
|
|
7
7
|
> comments, (b) the diff of edits, (c) whether each comment is for a **human** or
|
|
8
|
-
> the **agent** to resolve — plus
|
|
8
|
+
> the **agent** to resolve — plus collaboration-grade `@mention` tagging.
|
|
9
9
|
>
|
|
10
10
|
> This plan is written to be merged into an already-in-progress implementation.
|
|
11
11
|
> It is framed as **what already ships → the real holes → the fixes**, with
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
| Question | Today | Verdict |
|
|
19
19
|
| ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
|
|
20
20
|
| Is it clear when a comment should be resolved by a **human vs the agent**? | A `resolutionTarget` (`'agent' \| 'human'`) toggle exists in the draft UI (`PlansPage.tsx:4587`) and is surfaced to the agent as an `Expected resolver:` line (`comment-context.ts:198`) — but it lives **only inside the anchor JSON blob**, is not a DB column, and the handoff doesn't partition the agent's queue by it. | **Partly. Make it queryable + partition the handoff.** |
|
|
21
|
-
| Can you `@tag` org members with
|
|
21
|
+
| Can you `@tag` org members with design-editor autocomplete + inline chips? | Yes — `CommentMentionEditor` (`:4320`) + `useOrgMemberMentionSearch` → `/_agent-native/org/members` (`:433/:451`) + `@[label](mailto:email)` token grammar (`comment-context.ts:55`). | **Yes, already built. Harden, don't rebuild.** |
|
|
22
22
|
| When you comment on a location and pass to the agent, is it **fully clear**? | For **text**: yes-ish — quote + section, with `contextBefore/After` fields that exist but are **unevenly populated**. For **visual/canvas**: **no** — the agent gets coordinates + a label only, and the screenshot path that does exist is **bound to the wrong DOM surface** so canvas pins capture garbage. | **Text: tighten. Visual: broken — this is the #1 fix.** |
|
|
23
23
|
| Do agents get a **screenshot** of the visual location? | An in-app capture path exists (`captureFocusedFeedbackImages`, `:2289`, html2canvas + red-ring marker) but: (1) it rasterizes the **prose reader**, not the canvas world, so canvas/wireframe/diagram pins produce empty crops; (2) crops reach **only** the in-app inline agent — external/MCP agents get text-only. | **No, not reliably. Fix the surface + deliver via the handoff.** |
|
|
24
24
|
| Does text-by-location attach to the **nearest text**? | It stores `textQuote` + `sectionTitle`; `contextBefore/After` (prefix/suffix) exist in the type but aren't reliably filled, and `resolveAnchorTarget` silently picks the first match for duplicate phrases. | **Mostly — guarantee prefix/suffix + nearest blockId + ambiguity flag.** |
|
|
@@ -1502,7 +1502,7 @@ export function createPlanDesignContent(
|
|
|
1502
1502
|
data: {
|
|
1503
1503
|
markdown: [
|
|
1504
1504
|
`## Objective\n${input.brief}`,
|
|
1505
|
-
"## Design Review\nUse the Design tab as the full-fidelity source of truth. It should contain detailed, on-brand HTML/CSS screens on the
|
|
1505
|
+
"## Design Review\nUse the Design tab as the full-fidelity source of truth. It should contain detailed, on-brand HTML/CSS screens on the editable design canvas, with editable `data-design-id` targets for focused style changes. Use the Prototype tab only when interaction, flow, or state needs to be felt before implementation.",
|
|
1506
1506
|
sourceLines.length
|
|
1507
1507
|
? `## Style Sources\n${sourceLines.join("\n")}`
|
|
1508
1508
|
: "## Style Sources\nNo external brand kit was provided; infer the smallest useful design system from the inspected codebase and document the assumptions here.",
|
|
@@ -58,7 +58,7 @@ const DEFAULT_COMPONENTS: UiPlanComponent[] = [
|
|
|
58
58
|
{
|
|
59
59
|
name: "Comment popover",
|
|
60
60
|
description:
|
|
61
|
-
"One-field
|
|
61
|
+
"One-field compact comment composer with no category picker or coordinate metadata in the user-facing bubble.",
|
|
62
62
|
},
|
|
63
63
|
{
|
|
64
64
|
name: "Drawing controls",
|
|
@@ -209,7 +209,7 @@ function renderCanvasAnnotationLayers(
|
|
|
209
209
|
? Math.min(board.width - 380, lastState.x + lastState.width + 96)
|
|
210
210
|
: 1760;
|
|
211
211
|
return `<div class="canvas-annotation handoff-note" style="${frameStyle(handoffX, 118, 340, 176)}">
|
|
212
|
-
<h4>Read this like a
|
|
212
|
+
<h4>Read this like a design handoff.</h4>
|
|
213
213
|
<ul>
|
|
214
214
|
<li>Pan and zoom to compare frames.</li>
|
|
215
215
|
<li>Leave comments directly on artboards.</li>
|
|
@@ -7,11 +7,9 @@ import {
|
|
|
7
7
|
getRequestOrgId,
|
|
8
8
|
getRequestUserEmail,
|
|
9
9
|
} from "@agent-native/core/server/request-context";
|
|
10
|
-
import { eq } from "drizzle-orm";
|
|
11
|
-
import { nanoid } from "nanoid";
|
|
12
10
|
import { z } from "zod";
|
|
13
11
|
|
|
14
|
-
import {
|
|
12
|
+
import { upsertBuilderProxyDesignSystem } from "../server/lib/builder-design-system-proxy.js";
|
|
15
13
|
|
|
16
14
|
const MAX_CODE_FILES = 50;
|
|
17
15
|
const MAX_TOTAL_CODE_BYTES = 2 * 1024 * 1024;
|
|
@@ -52,83 +50,6 @@ function makeFiles(
|
|
|
52
50
|
return files;
|
|
53
51
|
}
|
|
54
52
|
|
|
55
|
-
function localBuilderDesignSystemId(builderDesignSystemId: string): string {
|
|
56
|
-
const slug = builderDesignSystemId
|
|
57
|
-
.replace(/[^a-zA-Z0-9_-]+/g, "-")
|
|
58
|
-
.replace(/^-+|-+$/g, "")
|
|
59
|
-
.slice(0, 96);
|
|
60
|
-
return `builder-${slug || "design-system"}`;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function builderProxyData({
|
|
64
|
-
builderDesignSystemId,
|
|
65
|
-
jobId,
|
|
66
|
-
builderUrl,
|
|
67
|
-
projectName,
|
|
68
|
-
description,
|
|
69
|
-
}: {
|
|
70
|
-
builderDesignSystemId: string;
|
|
71
|
-
jobId: string;
|
|
72
|
-
builderUrl: string;
|
|
73
|
-
projectName?: string;
|
|
74
|
-
description?: string;
|
|
75
|
-
}) {
|
|
76
|
-
return JSON.stringify({
|
|
77
|
-
source: "builder",
|
|
78
|
-
builderDesignSystemId,
|
|
79
|
-
builderJobId: jobId,
|
|
80
|
-
builderUrl,
|
|
81
|
-
colors: {
|
|
82
|
-
primary: "var(--primary)",
|
|
83
|
-
secondary: "var(--secondary)",
|
|
84
|
-
accent: "var(--accent)",
|
|
85
|
-
background: "var(--background)",
|
|
86
|
-
surface: "var(--card)",
|
|
87
|
-
text: "var(--foreground)",
|
|
88
|
-
textMuted: "var(--muted-foreground)",
|
|
89
|
-
},
|
|
90
|
-
typography: {
|
|
91
|
-
headingFont: "inherit",
|
|
92
|
-
bodyFont: "inherit",
|
|
93
|
-
headingWeight: "700",
|
|
94
|
-
bodyWeight: "400",
|
|
95
|
-
headingSizes: { h1: "48px", h2: "32px", h3: "24px" },
|
|
96
|
-
},
|
|
97
|
-
spacing: { elementGap: "24px", slidePadding: "48px" },
|
|
98
|
-
borders: { radius: "12px", accentWidth: "1px" },
|
|
99
|
-
logos: [],
|
|
100
|
-
notes: [
|
|
101
|
-
"This is a local proxy for a Builder-indexed design system.",
|
|
102
|
-
`Builder design system id: ${builderDesignSystemId}`,
|
|
103
|
-
`Builder indexing job id: ${jobId}`,
|
|
104
|
-
`Builder URL: ${builderUrl}`,
|
|
105
|
-
projectName ? `Requested name: ${projectName}` : "",
|
|
106
|
-
description ? `Context: ${description}` : "",
|
|
107
|
-
"Use Builder as the source of truth for extracted tokens and guidance.",
|
|
108
|
-
]
|
|
109
|
-
.filter(Boolean)
|
|
110
|
-
.join("\n"),
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function builderProxyInstructions({
|
|
115
|
-
builderDesignSystemId,
|
|
116
|
-
jobId,
|
|
117
|
-
builderUrl,
|
|
118
|
-
}: {
|
|
119
|
-
builderDesignSystemId: string;
|
|
120
|
-
jobId: string;
|
|
121
|
-
builderUrl: string;
|
|
122
|
-
}) {
|
|
123
|
-
return [
|
|
124
|
-
"This design system is indexed and owned by Builder.",
|
|
125
|
-
`Builder design system id: ${builderDesignSystemId}`,
|
|
126
|
-
`Builder job id: ${jobId}`,
|
|
127
|
-
`Builder URL: ${builderUrl}`,
|
|
128
|
-
"When generating slides, treat Builder as the source of truth for the final extracted tokens, assets, and guidance.",
|
|
129
|
-
].join("\n");
|
|
130
|
-
}
|
|
131
|
-
|
|
132
53
|
export default defineAction({
|
|
133
54
|
description:
|
|
134
55
|
"Start Builder design-system indexing from a GitHub repository and/or code files. " +
|
|
@@ -174,86 +95,18 @@ export default defineAction({
|
|
|
174
95
|
const ownerEmail = getRequestUserEmail();
|
|
175
96
|
if (!ownerEmail) throw new Error("no authenticated user");
|
|
176
97
|
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
result.designSystemId,
|
|
182
|
-
);
|
|
183
|
-
const title = projectName?.trim() || "Builder indexed design system";
|
|
184
|
-
const localData = builderProxyData({
|
|
185
|
-
builderDesignSystemId: result.designSystemId,
|
|
186
|
-
jobId: result.jobId,
|
|
187
|
-
builderUrl: result.builderUrl,
|
|
98
|
+
const proxy = await upsertBuilderProxyDesignSystem({
|
|
99
|
+
result,
|
|
100
|
+
ownerEmail,
|
|
101
|
+
orgId: getRequestOrgId(),
|
|
188
102
|
projectName,
|
|
189
103
|
description,
|
|
190
104
|
});
|
|
191
|
-
const customInstructions = builderProxyInstructions({
|
|
192
|
-
builderDesignSystemId: result.designSystemId,
|
|
193
|
-
jobId: result.jobId,
|
|
194
|
-
builderUrl: result.builderUrl,
|
|
195
|
-
});
|
|
196
|
-
const [existing] = await db
|
|
197
|
-
.select({
|
|
198
|
-
id: schema.designSystems.id,
|
|
199
|
-
ownerEmail: schema.designSystems.ownerEmail,
|
|
200
|
-
})
|
|
201
|
-
.from(schema.designSystems)
|
|
202
|
-
.where(eq(schema.designSystems.id, baseLocalDesignSystemId))
|
|
203
|
-
.limit(1);
|
|
204
|
-
const localDesignSystemId =
|
|
205
|
-
existing && existing.ownerEmail !== ownerEmail
|
|
206
|
-
? `${baseLocalDesignSystemId}-${nanoid(8)}`
|
|
207
|
-
: baseLocalDesignSystemId;
|
|
208
|
-
if (existing && existing.ownerEmail === ownerEmail) {
|
|
209
|
-
await db
|
|
210
|
-
.update(schema.designSystems)
|
|
211
|
-
.set({
|
|
212
|
-
title,
|
|
213
|
-
description:
|
|
214
|
-
description ??
|
|
215
|
-
`Builder indexed design system ${result.designSystemId}`,
|
|
216
|
-
data: localData,
|
|
217
|
-
assets: "[]",
|
|
218
|
-
customInstructions,
|
|
219
|
-
updatedAt: now,
|
|
220
|
-
})
|
|
221
|
-
.where(eq(schema.designSystems.id, existing.id));
|
|
222
|
-
} else {
|
|
223
|
-
const [ownedSystem] = await db
|
|
224
|
-
.select({ id: schema.designSystems.id })
|
|
225
|
-
.from(schema.designSystems)
|
|
226
|
-
.where(eq(schema.designSystems.ownerEmail, ownerEmail))
|
|
227
|
-
.limit(1);
|
|
228
|
-
await db.insert(schema.designSystems).values({
|
|
229
|
-
id: localDesignSystemId,
|
|
230
|
-
title,
|
|
231
|
-
description:
|
|
232
|
-
description ??
|
|
233
|
-
`Builder indexed design system ${result.designSystemId}`,
|
|
234
|
-
data: localData,
|
|
235
|
-
assets: "[]",
|
|
236
|
-
customInstructions,
|
|
237
|
-
isDefault: !ownedSystem,
|
|
238
|
-
ownerEmail,
|
|
239
|
-
orgId,
|
|
240
|
-
createdAt: now,
|
|
241
|
-
updatedAt: now,
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
105
|
|
|
245
106
|
return {
|
|
246
107
|
...result,
|
|
247
|
-
|
|
108
|
+
...proxy,
|
|
248
109
|
uploadedFileCount: files.length,
|
|
249
|
-
instructions: [
|
|
250
|
-
"Builder design-system indexing has started.",
|
|
251
|
-
`Builder design system: ${result.designSystemId}`,
|
|
252
|
-
`Local selectable design system: ${localDesignSystemId}`,
|
|
253
|
-
`Builder job: ${result.jobId}`,
|
|
254
|
-
`Open: ${result.builderUrl}`,
|
|
255
|
-
"Use the local design system id in Slides flows; Builder remains the source of truth for the indexed brand kit.",
|
|
256
|
-
].join("\n"),
|
|
257
110
|
};
|
|
258
111
|
},
|
|
259
112
|
});
|
|
@@ -36,11 +36,11 @@ import { Textarea } from "@/components/ui/textarea";
|
|
|
36
36
|
import { toast } from "@/hooks/use-toast";
|
|
37
37
|
|
|
38
38
|
import {
|
|
39
|
-
|
|
39
|
+
MAX_BUILDER_INDEX_UPLOAD_BYTES,
|
|
40
|
+
readBuilderIndexResponse,
|
|
40
41
|
formatFileSize,
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
} from "./fig-import-response";
|
|
42
|
+
type BuilderIndexResult,
|
|
43
|
+
} from "./builder-index-response";
|
|
44
44
|
|
|
45
45
|
interface DesignSystemSetupProps {
|
|
46
46
|
open: boolean;
|
|
@@ -105,9 +105,12 @@ export function DesignSystemSetup({
|
|
|
105
105
|
const [brandNotes, setBrandNotes] = useState("");
|
|
106
106
|
const [customInstructions, setCustomInstructions] = useState("");
|
|
107
107
|
const [generating, setGenerating] = useState(false);
|
|
108
|
-
const [
|
|
109
|
-
const [
|
|
110
|
-
|
|
108
|
+
const [builderIndexing, setBuilderIndexing] = useState(false);
|
|
109
|
+
const [builderIndexResult, setBuilderIndexResult] =
|
|
110
|
+
useState<BuilderIndexResult | null>(null);
|
|
111
|
+
const [builderIndexError, setBuilderIndexError] = useState<string | null>(
|
|
112
|
+
null,
|
|
113
|
+
);
|
|
111
114
|
|
|
112
115
|
const codeInputRef = useRef<HTMLInputElement>(null);
|
|
113
116
|
const docInputRef = useRef<HTMLInputElement>(null);
|
|
@@ -158,9 +161,9 @@ export function DesignSystemSetup({
|
|
|
158
161
|
setBrandNotes("");
|
|
159
162
|
setCustomInstructions("");
|
|
160
163
|
setSelectedSystemId("");
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
+
setBuilderIndexing(false);
|
|
165
|
+
setBuilderIndexResult(null);
|
|
166
|
+
setBuilderIndexError(null);
|
|
164
167
|
}
|
|
165
168
|
}, [open]);
|
|
166
169
|
|
|
@@ -170,6 +173,7 @@ export function DesignSystemSetup({
|
|
|
170
173
|
websiteUrls.length > 0 ||
|
|
171
174
|
githubLinks.length > 0 ||
|
|
172
175
|
codeFiles.length > 0 ||
|
|
176
|
+
builderIndexResult ||
|
|
173
177
|
docFiles.length > 0 ||
|
|
174
178
|
imageFiles.length > 0 ||
|
|
175
179
|
selectedSystemId ||
|
|
@@ -181,6 +185,7 @@ export function DesignSystemSetup({
|
|
|
181
185
|
websiteUrls,
|
|
182
186
|
githubLinks,
|
|
183
187
|
codeFiles,
|
|
188
|
+
builderIndexResult,
|
|
184
189
|
docFiles,
|
|
185
190
|
imageFiles,
|
|
186
191
|
selectedSystemId,
|
|
@@ -238,44 +243,47 @@ export function DesignSystemSetup({
|
|
|
238
243
|
[t],
|
|
239
244
|
);
|
|
240
245
|
|
|
241
|
-
const
|
|
246
|
+
const handleBuilderIndexUpload = useCallback(
|
|
242
247
|
async (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
243
248
|
const file = event.target.files?.[0];
|
|
244
249
|
event.target.value = "";
|
|
245
250
|
if (!file) return;
|
|
246
251
|
if (!file.name.toLowerCase().endsWith(".fig")) {
|
|
247
|
-
|
|
252
|
+
setBuilderIndexError(t("designSystemSetup.figFileRequired"));
|
|
248
253
|
return;
|
|
249
254
|
}
|
|
250
|
-
if (file.size >
|
|
251
|
-
|
|
255
|
+
if (file.size > MAX_BUILDER_INDEX_UPLOAD_BYTES) {
|
|
256
|
+
setBuilderIndexError(
|
|
252
257
|
t("designSystemSetup.figFileTooLarge", {
|
|
253
|
-
maxSize: formatFileSize(
|
|
258
|
+
maxSize: formatFileSize(MAX_BUILDER_INDEX_UPLOAD_BYTES),
|
|
254
259
|
}),
|
|
255
260
|
);
|
|
256
261
|
return;
|
|
257
262
|
}
|
|
258
263
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
264
|
+
setBuilderIndexError(null);
|
|
265
|
+
setBuilderIndexResult(null);
|
|
266
|
+
setBuilderIndexing(true);
|
|
262
267
|
try {
|
|
263
268
|
const body = new FormData();
|
|
264
269
|
body.append("file", file);
|
|
265
|
-
const res = await fetch(
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
270
|
+
const res = await fetch(
|
|
271
|
+
appApiPath("/api/index-design-system-with-builder"),
|
|
272
|
+
{
|
|
273
|
+
method: "POST",
|
|
274
|
+
body,
|
|
275
|
+
},
|
|
276
|
+
);
|
|
277
|
+
const parsed = await readBuilderIndexResponse(res);
|
|
278
|
+
setBuilderIndexResult(parsed);
|
|
271
279
|
} catch (err) {
|
|
272
|
-
|
|
280
|
+
setBuilderIndexError(
|
|
273
281
|
err instanceof Error
|
|
274
282
|
? err.message
|
|
275
283
|
: t("designSystemSetup.figParseFailed"),
|
|
276
284
|
);
|
|
277
285
|
} finally {
|
|
278
|
-
|
|
286
|
+
setBuilderIndexing(false);
|
|
279
287
|
}
|
|
280
288
|
},
|
|
281
289
|
[t],
|
|
@@ -353,6 +361,12 @@ export function DesignSystemSetup({
|
|
|
353
361
|
}
|
|
354
362
|
}
|
|
355
363
|
|
|
364
|
+
if (builderIndexResult) {
|
|
365
|
+
parts.push(
|
|
366
|
+
`\n## Builder-Indexed Figma File\nBuilder design-system indexing has already started.\n- Design system: ${builderIndexResult.designSystemId}\n- Local selectable design system: ${builderIndexResult.localDesignSystemId ?? "(not returned)"}\n- Project: ${builderIndexResult.projectId}\n- Job: ${builderIndexResult.jobId}\n- URL: ${builderIndexResult.builderUrl}\n\nUse Builder as the source of truth for extracted tokens, assets, and guidance. Do not call \`create-design-system\` again for this Builder-indexed source.`,
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
356
370
|
if (docFiles.length > 0) {
|
|
357
371
|
const inlined = docFiles.filter((f) => f.textContent);
|
|
358
372
|
const binary = docFiles.filter((f) => !f.textContent);
|
|
@@ -419,6 +433,7 @@ export function DesignSystemSetup({
|
|
|
419
433
|
websiteUrls,
|
|
420
434
|
githubLinks,
|
|
421
435
|
codeFiles,
|
|
436
|
+
builderIndexResult,
|
|
422
437
|
docFiles,
|
|
423
438
|
imageFiles,
|
|
424
439
|
selectedSystemId,
|
|
@@ -469,15 +484,15 @@ export function DesignSystemSetup({
|
|
|
469
484
|
<IconBrandFigma className="w-3.5 h-3.5" />
|
|
470
485
|
{t("designSystemSetup.figmaFile")}
|
|
471
486
|
</Label>
|
|
472
|
-
{!
|
|
487
|
+
{!builderIndexResult ? (
|
|
473
488
|
<>
|
|
474
489
|
<button
|
|
475
490
|
type="button"
|
|
476
491
|
onClick={() => figInputRef.current?.click()}
|
|
477
|
-
disabled={
|
|
492
|
+
disabled={builderIndexing}
|
|
478
493
|
className="w-full border border-dashed border-border rounded-lg p-4 text-center hover:border-foreground/20 cursor-pointer disabled:cursor-wait disabled:opacity-70"
|
|
479
494
|
>
|
|
480
|
-
{
|
|
495
|
+
{builderIndexing ? (
|
|
481
496
|
<span className="inline-flex items-center gap-2 text-xs text-muted-foreground">
|
|
482
497
|
<IconLoader2 className="w-3.5 h-3.5 animate-spin" />
|
|
483
498
|
{t("designSystemSetup.parsingFigmaFile")}
|
|
@@ -492,24 +507,24 @@ export function DesignSystemSetup({
|
|
|
492
507
|
ref={figInputRef}
|
|
493
508
|
type="file"
|
|
494
509
|
accept=".fig"
|
|
495
|
-
onChange={
|
|
510
|
+
onChange={handleBuilderIndexUpload}
|
|
496
511
|
className="hidden"
|
|
497
512
|
/>
|
|
498
|
-
{
|
|
513
|
+
{builderIndexError && (
|
|
499
514
|
<div
|
|
500
515
|
role="alert"
|
|
501
516
|
className="rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive"
|
|
502
517
|
>
|
|
503
|
-
{
|
|
518
|
+
{builderIndexError}
|
|
504
519
|
</div>
|
|
505
520
|
)}
|
|
506
521
|
</>
|
|
507
522
|
) : (
|
|
508
|
-
<
|
|
509
|
-
result={
|
|
523
|
+
<BuilderIndexPreview
|
|
524
|
+
result={builderIndexResult}
|
|
510
525
|
onReset={() => {
|
|
511
|
-
|
|
512
|
-
|
|
526
|
+
setBuilderIndexResult(null);
|
|
527
|
+
setBuilderIndexError(null);
|
|
513
528
|
}}
|
|
514
529
|
/>
|
|
515
530
|
)}
|
|
@@ -842,11 +857,11 @@ function TagList({
|
|
|
842
857
|
);
|
|
843
858
|
}
|
|
844
859
|
|
|
845
|
-
function
|
|
860
|
+
function BuilderIndexPreview({
|
|
846
861
|
result,
|
|
847
862
|
onReset,
|
|
848
863
|
}: {
|
|
849
|
-
result:
|
|
864
|
+
result: BuilderIndexResult;
|
|
850
865
|
onReset: () => void;
|
|
851
866
|
}) {
|
|
852
867
|
const t = useT();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export interface
|
|
1
|
+
export interface BuilderIndexResult {
|
|
2
2
|
ok: boolean;
|
|
3
3
|
source: "builder";
|
|
4
4
|
suggestedTitle: string;
|
|
@@ -7,10 +7,13 @@ export interface FigImportResult {
|
|
|
7
7
|
designSystemId: string;
|
|
8
8
|
builderUrl: string;
|
|
9
9
|
status: "in-progress";
|
|
10
|
+
localDesignSystemId?: string;
|
|
11
|
+
uploadedFileCount?: number;
|
|
12
|
+
instructions?: string;
|
|
10
13
|
builderConnectUrl?: string;
|
|
11
14
|
}
|
|
12
15
|
|
|
13
|
-
export const
|
|
16
|
+
export const MAX_BUILDER_INDEX_UPLOAD_BYTES = 200 * 1024 * 1024;
|
|
14
17
|
|
|
15
18
|
export function formatFileSize(bytes: number): string {
|
|
16
19
|
return `${Math.round(bytes / 1024 / 1024)} MB`;
|
|
@@ -18,7 +21,7 @@ export function formatFileSize(bytes: number): string {
|
|
|
18
21
|
|
|
19
22
|
function summarizeUploadFailure(status: number, bodyText: string): string {
|
|
20
23
|
if (status === 413) {
|
|
21
|
-
return `File too large (max ${formatFileSize(
|
|
24
|
+
return `File too large (max ${formatFileSize(MAX_BUILDER_INDEX_UPLOAD_BYTES)}).`;
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
const trimmed = bodyText
|
|
@@ -31,9 +34,9 @@ function summarizeUploadFailure(status: number, bodyText: string): string {
|
|
|
31
34
|
return `Upload failed (${status})`;
|
|
32
35
|
}
|
|
33
36
|
|
|
34
|
-
export async function
|
|
37
|
+
export async function readBuilderIndexResponse(
|
|
35
38
|
res: Response,
|
|
36
|
-
): Promise<
|
|
39
|
+
): Promise<BuilderIndexResult> {
|
|
37
40
|
const bodyText = await res.text();
|
|
38
41
|
let json: unknown = null;
|
|
39
42
|
|
|
@@ -59,5 +62,5 @@ export async function readFigImportResponse(
|
|
|
59
62
|
throw new Error(summarizeUploadFailure(res.status, bodyText));
|
|
60
63
|
}
|
|
61
64
|
|
|
62
|
-
return json as
|
|
65
|
+
return json as BuilderIndexResult;
|
|
63
66
|
}
|
|
@@ -17,7 +17,7 @@ interface MultiSelectChipProps {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* Floating chip that hovers above a multi-select selection (
|
|
20
|
+
* Floating chip that hovers above a multi-select selection (design-editor style).
|
|
21
21
|
* Rendered via portal so it isn't constrained by the slide canvas's stacking
|
|
22
22
|
* context. Reusable across the slides editor and the design template.
|
|
23
23
|
*/
|