@agent-native/core 0.80.0 → 0.80.2

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.
Files changed (228) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +28 -0
  3. package/corpus/core/docs/content/locales/ar-SA/skills-guide.mdx +5 -0
  4. package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +14 -1
  5. package/corpus/core/docs/content/locales/de-DE/skills-guide.mdx +5 -0
  6. package/corpus/core/docs/content/locales/de-DE/template-design.mdx +15 -1
  7. package/corpus/core/docs/content/locales/es-ES/skills-guide.mdx +5 -0
  8. package/corpus/core/docs/content/locales/es-ES/template-design.mdx +15 -1
  9. package/corpus/core/docs/content/locales/fr-FR/skills-guide.mdx +5 -0
  10. package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +15 -1
  11. package/corpus/core/docs/content/locales/hi-IN/skills-guide.mdx +5 -0
  12. package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +15 -1
  13. package/corpus/core/docs/content/locales/ja-JP/skills-guide.mdx +5 -0
  14. package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +16 -1
  15. package/corpus/core/docs/content/locales/ko-KR/skills-guide.mdx +5 -0
  16. package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +14 -1
  17. package/corpus/core/docs/content/locales/pt-BR/skills-guide.mdx +5 -0
  18. package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +14 -1
  19. package/corpus/core/docs/content/locales/zh-CN/skills-guide.mdx +5 -0
  20. package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +14 -1
  21. package/corpus/core/docs/content/locales/zh-TW/skills-guide.mdx +5 -0
  22. package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +14 -1
  23. package/corpus/core/docs/content/skills-guide.mdx +5 -0
  24. package/corpus/core/docs/content/template-design.mdx +14 -1
  25. package/corpus/core/package.json +1 -1
  26. package/corpus/core/src/application-state/handlers.ts +1 -1
  27. package/corpus/core/src/brand-kit/index.ts +1 -1
  28. package/corpus/core/src/cli/skills.ts +18 -0
  29. package/corpus/core/src/client/AgentPanel.tsx +1 -1
  30. package/corpus/core/src/client/MultiTabAssistantChat.tsx +1 -1
  31. package/corpus/core/src/client/extensions/portable-extension.ts +1 -1
  32. package/corpus/core/src/code-agents/transcript-normalizer.ts +1 -1
  33. package/corpus/core/src/extensions/path.ts +1 -4
  34. package/corpus/core/src/integrations/a2a-continuation-processor.ts +1 -1
  35. package/corpus/core/src/mcp/build-server.ts +2 -2
  36. package/corpus/core/src/mcp/embed-app.ts +35 -1
  37. package/corpus/core/src/org/handlers.ts +5 -5
  38. package/corpus/core/src/org/plugin.ts +2 -2
  39. package/corpus/core/src/scripts/call-agent.ts +1 -1
  40. package/corpus/core/src/scripts/db/safety.ts +1 -1
  41. package/corpus/core/src/server/auth.ts +3 -0
  42. package/corpus/core/src/server/builder-design-systems.ts +308 -0
  43. package/corpus/core/src/server/core-routes-plugin.ts +29 -3
  44. package/corpus/core/src/server/index.ts +8 -0
  45. package/corpus/core/src/styles/agent-native.css +14 -7
  46. package/corpus/core/src/usage/store.ts +2 -2
  47. package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +298 -15
  48. package/corpus/templates/analytics/actions/get-sql-dashboard.ts +9 -4
  49. package/corpus/templates/analytics/actions/mutate-dashboard.ts +18 -2
  50. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +12 -2
  51. package/corpus/templates/analytics/app/hooks/use-replay-storage-status.ts +66 -0
  52. package/corpus/templates/analytics/app/i18n/zh-TW.ts +37 -0
  53. package/corpus/templates/analytics/app/i18n-data.ts +404 -0
  54. package/corpus/templates/analytics/app/pages/Settings.tsx +333 -0
  55. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +2 -1
  56. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/dashboard-layout.ts +121 -3
  57. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +49 -26
  58. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +137 -36
  59. package/corpus/templates/analytics/changelog/2026-06-29-analytics-agents-can-now-place-new-charts-into-requested-das.md +6 -0
  60. package/corpus/templates/analytics/changelog/2026-06-29-analytics-queries-now-report-failed-source-query-errors-inst.md +6 -0
  61. package/corpus/templates/analytics/changelog/2026-06-29-charts-can-now-be-dropped-between-full-dashboard-rows-to-cre.md +6 -0
  62. package/corpus/templates/analytics/changelog/2026-06-29-dashboard-email-reports-include-the-full-dashboard-image-wit.md +6 -0
  63. package/corpus/templates/analytics/changelog/2026-06-29-main-surface-border-reaches-the-top.md +6 -0
  64. package/corpus/templates/analytics/changelog/2026-06-29-session-replay-now-records-playable-sessions-in-production-a.md +6 -0
  65. package/corpus/templates/analytics/changelog/2026-06-29-set-up-session-replay-storage-from-settings-connect-builder-.md +6 -0
  66. package/corpus/templates/analytics/scripts/cleanup-empty-session-recordings.ts +102 -0
  67. package/corpus/templates/analytics/server/lib/dashboard-report.ts +49 -26
  68. package/corpus/templates/analytics/server/lib/real-data-actions.ts +81 -20
  69. package/corpus/templates/analytics/server/lib/replay-storage.ts +79 -0
  70. package/corpus/templates/analytics/server/lib/s3-upload-provider.ts +255 -0
  71. package/corpus/templates/analytics/server/lib/session-replay.ts +29 -8
  72. package/corpus/templates/analytics/server/plugins/agent-chat.ts +11 -2
  73. package/corpus/templates/analytics/server/plugins/onboarding.ts +97 -0
  74. package/corpus/templates/clips/desktop/src/lib/recorder.ts +24 -0
  75. package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +105 -5
  76. package/corpus/templates/content/actions/set-image-alt-text.ts +1 -1
  77. package/corpus/templates/content/shared/document-export.ts +1 -1
  78. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +8 -18
  79. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +17 -0
  80. package/corpus/templates/design/actions/add-localhost-screens.ts +32 -5
  81. package/corpus/templates/design/actions/index-design-system-with-builder.ts +259 -0
  82. package/corpus/templates/design/actions/update-file.ts +9 -2
  83. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +33 -75
  84. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +72 -9
  85. package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +41 -39
  86. package/corpus/templates/design/app/components/design/EditPanel.tsx +1029 -249
  87. package/corpus/templates/design/app/components/design/LayersPanel.tsx +450 -101
  88. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +978 -154
  89. package/corpus/templates/design/app/components/design/TweaksPanel.tsx +7 -9
  90. package/corpus/templates/design/app/components/design/inspector/AlignmentMatrix.tsx +133 -66
  91. package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +1234 -344
  92. package/corpus/templates/design/app/components/design/inspector/ConstraintsWidget.tsx +144 -94
  93. package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +301 -72
  94. package/corpus/templates/design/app/components/design/inspector/FigmaColorPicker.tsx +876 -286
  95. package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +601 -0
  96. package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +242 -0
  97. package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +30 -7
  98. package/corpus/templates/design/app/components/design/inspector/ShaderControls.tsx +212 -155
  99. package/corpus/templates/design/app/components/design/inspector/ShaderFillsPanel.tsx +423 -0
  100. package/corpus/templates/design/app/components/design/inspector/figma-icons.tsx +487 -107
  101. package/corpus/templates/design/app/components/design/inspector/index.ts +27 -0
  102. package/corpus/templates/design/app/global.css +29 -3
  103. package/corpus/templates/design/app/i18n/zh-TW.ts +13 -0
  104. package/corpus/templates/design/app/i18n-data.ts +239 -1
  105. package/corpus/templates/design/app/pages/DesignEditor.tsx +1023 -353
  106. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +57 -221
  107. package/corpus/templates/design/changelog/2026-06-29-canvas-selection-no-longer-flashes-broken-prototype-html-whe.md +6 -0
  108. package/corpus/templates/design/changelog/2026-06-29-command-menu-selections-are-clearer-in-dark-mode.md +6 -0
  109. package/corpus/templates/design/changelog/2026-06-29-design-mode-top-chrome-now-groups-collaborators-preview-shar.md +6 -0
  110. package/corpus/templates/design/changelog/2026-06-29-element-selection-now-stays-on-the-intended-layer-after-sele.md +6 -0
  111. package/corpus/templates/design/changelog/2026-06-29-screen-overview-full-view-controls-now-sit-above-frames-inst.md +6 -0
  112. package/corpus/templates/design/changelog/2026-06-29-screen-overview-tools-can-draw-shapes-create-screens-and-kee.md +6 -0
  113. package/corpus/templates/design/changelog/2026-06-29-the-pen-tool-now-creates-anchor-based-bezier-vectors-with-ha.md +6 -0
  114. package/corpus/templates/design/server/handlers/import-figma-system.ts +38 -85
  115. package/corpus/templates/design/server/lib/design-snapshot.ts +9 -1
  116. package/corpus/templates/design/shared/code-layer.ts +209 -9
  117. package/corpus/templates/design/shared/html-content.ts +21 -0
  118. package/corpus/templates/design/shared/pen-path.ts +207 -0
  119. package/corpus/templates/mail/app/lib/utils.ts +2 -2
  120. package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +9 -10
  121. package/corpus/templates/slides/AGENTS.md +3 -2
  122. package/corpus/templates/slides/actions/import-file.ts +26 -17
  123. package/corpus/templates/slides/actions/index-design-system-with-builder.ts +259 -0
  124. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +35 -167
  125. package/corpus/templates/slides/app/components/design-system/fig-import-response.ts +9 -13
  126. package/corpus/templates/slides/app/context/DeckContext.tsx +1 -1
  127. package/corpus/templates/slides/app/i18n/ar-SA.ts +9 -37
  128. package/corpus/templates/slides/app/i18n/de-DE.ts +10 -25
  129. package/corpus/templates/slides/app/i18n/en-US.ts +9 -26
  130. package/corpus/templates/slides/app/i18n/es-ES.ts +10 -28
  131. package/corpus/templates/slides/app/i18n/fr-FR.ts +10 -28
  132. package/corpus/templates/slides/app/i18n/hi-IN.ts +9 -26
  133. package/corpus/templates/slides/app/i18n/ja-JP.ts +10 -22
  134. package/corpus/templates/slides/app/i18n/ko-KR.ts +9 -23
  135. package/corpus/templates/slides/app/i18n/pt-BR.ts +10 -28
  136. package/corpus/templates/slides/app/i18n/zh-CN.ts +9 -22
  137. package/corpus/templates/slides/app/i18n/zh-TW.ts +9 -22
  138. package/corpus/templates/slides/server/handlers/import-figma-system.ts +44 -12
  139. package/corpus/templates/slides/server/lib/chat-attachments.ts +1 -1
  140. package/corpus/templates/videos/app/components/NewCompositionPopover.tsx +1 -1
  141. package/dist/application-state/handlers.js +1 -1
  142. package/dist/application-state/handlers.js.map +1 -1
  143. package/dist/brand-kit/index.d.ts +1 -1
  144. package/dist/brand-kit/index.js +1 -1
  145. package/dist/brand-kit/index.js.map +1 -1
  146. package/dist/cli/skills.d.ts.map +1 -1
  147. package/dist/cli/skills.js +18 -0
  148. package/dist/cli/skills.js.map +1 -1
  149. package/dist/client/AgentPanel.js +1 -1
  150. package/dist/client/AgentPanel.js.map +1 -1
  151. package/dist/client/MultiTabAssistantChat.js +1 -1
  152. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  153. package/dist/client/extensions/portable-extension.d.ts +1 -1
  154. package/dist/client/extensions/portable-extension.d.ts.map +1 -1
  155. package/dist/client/extensions/portable-extension.js.map +1 -1
  156. package/dist/code-agents/transcript-normalizer.js +1 -1
  157. package/dist/code-agents/transcript-normalizer.js.map +1 -1
  158. package/dist/collab/awareness.d.ts +2 -2
  159. package/dist/collab/awareness.d.ts.map +1 -1
  160. package/dist/collab/routes.d.ts +1 -1
  161. package/dist/extensions/path.d.ts +1 -1
  162. package/dist/extensions/path.d.ts.map +1 -1
  163. package/dist/extensions/path.js.map +1 -1
  164. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  165. package/dist/integrations/a2a-continuation-processor.js +1 -1
  166. package/dist/integrations/a2a-continuation-processor.js.map +1 -1
  167. package/dist/mcp/build-server.d.ts +1 -1
  168. package/dist/mcp/build-server.d.ts.map +1 -1
  169. package/dist/mcp/build-server.js +1 -1
  170. package/dist/mcp/build-server.js.map +1 -1
  171. package/dist/mcp/embed-app.d.ts.map +1 -1
  172. package/dist/mcp/embed-app.js +35 -1
  173. package/dist/mcp/embed-app.js.map +1 -1
  174. package/dist/notifications/routes.d.ts +3 -3
  175. package/dist/observability/routes.d.ts +8 -8
  176. package/dist/org/handlers.js +5 -5
  177. package/dist/org/handlers.js.map +1 -1
  178. package/dist/org/plugin.js +2 -2
  179. package/dist/org/plugin.js.map +1 -1
  180. package/dist/resources/handlers.d.ts +1 -1
  181. package/dist/scripts/call-agent.js +1 -1
  182. package/dist/scripts/call-agent.js.map +1 -1
  183. package/dist/scripts/db/safety.js +1 -1
  184. package/dist/scripts/db/safety.js.map +1 -1
  185. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  186. package/dist/server/auth.d.ts.map +1 -1
  187. package/dist/server/auth.js +3 -0
  188. package/dist/server/auth.js.map +1 -1
  189. package/dist/server/builder-design-systems.d.ts +28 -0
  190. package/dist/server/builder-design-systems.d.ts.map +1 -0
  191. package/dist/server/builder-design-systems.js +217 -0
  192. package/dist/server/builder-design-systems.js.map +1 -0
  193. package/dist/server/core-routes-plugin.d.ts +1 -0
  194. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  195. package/dist/server/core-routes-plugin.js +20 -3
  196. package/dist/server/core-routes-plugin.js.map +1 -1
  197. package/dist/server/index.d.ts +1 -0
  198. package/dist/server/index.d.ts.map +1 -1
  199. package/dist/server/index.js +1 -0
  200. package/dist/server/index.js.map +1 -1
  201. package/dist/styles/agent-native.css +14 -7
  202. package/dist/usage/store.js +2 -2
  203. package/dist/usage/store.js.map +1 -1
  204. package/docs/content/locales/ar-SA/skills-guide.mdx +5 -0
  205. package/docs/content/locales/ar-SA/template-design.mdx +14 -1
  206. package/docs/content/locales/de-DE/skills-guide.mdx +5 -0
  207. package/docs/content/locales/de-DE/template-design.mdx +15 -1
  208. package/docs/content/locales/es-ES/skills-guide.mdx +5 -0
  209. package/docs/content/locales/es-ES/template-design.mdx +15 -1
  210. package/docs/content/locales/fr-FR/skills-guide.mdx +5 -0
  211. package/docs/content/locales/fr-FR/template-design.mdx +15 -1
  212. package/docs/content/locales/hi-IN/skills-guide.mdx +5 -0
  213. package/docs/content/locales/hi-IN/template-design.mdx +15 -1
  214. package/docs/content/locales/ja-JP/skills-guide.mdx +5 -0
  215. package/docs/content/locales/ja-JP/template-design.mdx +16 -1
  216. package/docs/content/locales/ko-KR/skills-guide.mdx +5 -0
  217. package/docs/content/locales/ko-KR/template-design.mdx +14 -1
  218. package/docs/content/locales/pt-BR/skills-guide.mdx +5 -0
  219. package/docs/content/locales/pt-BR/template-design.mdx +14 -1
  220. package/docs/content/locales/zh-CN/skills-guide.mdx +5 -0
  221. package/docs/content/locales/zh-CN/template-design.mdx +14 -1
  222. package/docs/content/locales/zh-TW/skills-guide.mdx +5 -0
  223. package/docs/content/locales/zh-TW/template-design.mdx +14 -1
  224. package/docs/content/skills-guide.mdx +5 -0
  225. package/docs/content/template-design.mdx +14 -1
  226. package/package.json +1 -1
  227. package/corpus/templates/design/actions/import-figma-file.ts +0 -166
  228. package/corpus/templates/slides/server/lib/fig-design-system.ts +0 -110
@@ -0,0 +1,259 @@
1
+ import { defineAction } from "@agent-native/core";
2
+ import {
3
+ startBuilderDesignSystemIndex,
4
+ type BuilderDesignSystemIndexFile,
5
+ } from "@agent-native/core/server";
6
+ import {
7
+ getRequestOrgId,
8
+ getRequestUserEmail,
9
+ } from "@agent-native/core/server/request-context";
10
+ import { eq } from "drizzle-orm";
11
+ import { nanoid } from "nanoid";
12
+ import { z } from "zod";
13
+
14
+ import { getDb, schema } from "../server/db/index.js";
15
+
16
+ const MAX_CODE_FILES = 50;
17
+ const MAX_TOTAL_CODE_BYTES = 2 * 1024 * 1024;
18
+
19
+ const codeFileSchema = z.object({
20
+ filename: z.string().trim().min(1).describe("File name or relative path"),
21
+ content: z.string().describe("Raw text content of the code/design file"),
22
+ mimeType: z.string().trim().optional().describe("Optional MIME type"),
23
+ });
24
+
25
+ function mimeTypeForFilename(filename: string, explicit?: string): string {
26
+ if (explicit?.trim()) return explicit.trim();
27
+ const lower = filename.toLowerCase();
28
+ if (lower.endsWith(".css")) return "text/css";
29
+ if (lower.endsWith(".json")) return "application/json";
30
+ if (lower.endsWith(".md") || lower.endsWith(".mdx")) return "text/markdown";
31
+ if (lower.endsWith(".html")) return "text/html";
32
+ if (lower.endsWith(".svg")) return "image/svg+xml";
33
+ return "text/plain";
34
+ }
35
+
36
+ function makeFiles(
37
+ codeFiles: Array<z.infer<typeof codeFileSchema>> | undefined,
38
+ ): BuilderDesignSystemIndexFile[] {
39
+ const encoder = new TextEncoder();
40
+ const files: BuilderDesignSystemIndexFile[] = [];
41
+ let totalBytes = 0;
42
+ for (const file of (codeFiles ?? []).slice(0, MAX_CODE_FILES)) {
43
+ const data = encoder.encode(file.content);
44
+ if (totalBytes + data.byteLength > MAX_TOTAL_CODE_BYTES) break;
45
+ totalBytes += data.byteLength;
46
+ files.push({
47
+ name: file.filename.replace(/^\/+/, "") || "code.txt",
48
+ data,
49
+ mimeType: mimeTypeForFilename(file.filename, file.mimeType),
50
+ });
51
+ }
52
+ return files;
53
+ }
54
+
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", pagePadding: "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 designs, treat Builder as the source of truth for the final extracted tokens, assets, and guidance.",
129
+ ].join("\n");
130
+ }
131
+
132
+ export default defineAction({
133
+ description:
134
+ "Start Builder design-system indexing from a GitHub repository and/or code files. " +
135
+ "Use this instead of local import-code/import-github when the user wants a reusable brand kit or design system. " +
136
+ "Requires Builder.io to be connected; Builder owns the indexed design-system docs, generated guidance, and job state.",
137
+ schema: z.object({
138
+ projectName: z
139
+ .string()
140
+ .optional()
141
+ .describe("Optional Builder project/design-system name"),
142
+ description: z
143
+ .string()
144
+ .optional()
145
+ .describe("Additional brand context or instructions for Builder"),
146
+ githubRepoUrl: z
147
+ .string()
148
+ .optional()
149
+ .describe("GitHub repository URL to index with Builder"),
150
+ connectedProjectId: z
151
+ .string()
152
+ .optional()
153
+ .describe("Optional existing Builder project id to attach indexing to"),
154
+ codeFiles: z
155
+ .array(codeFileSchema)
156
+ .optional()
157
+ .describe("Optional inlined code/design files to upload to Builder"),
158
+ }),
159
+ run: async ({
160
+ projectName,
161
+ description,
162
+ githubRepoUrl,
163
+ connectedProjectId,
164
+ codeFiles,
165
+ }) => {
166
+ const files = makeFiles(codeFiles);
167
+ const result = await startBuilderDesignSystemIndex({
168
+ projectName,
169
+ description,
170
+ githubRepoUrl,
171
+ connectedProjectId,
172
+ files,
173
+ });
174
+ const ownerEmail = getRequestUserEmail();
175
+ if (!ownerEmail) throw new Error("no authenticated user");
176
+
177
+ const db = getDb();
178
+ const now = new Date().toISOString();
179
+ const orgId = getRequestOrgId();
180
+ const baseLocalDesignSystemId = localBuilderDesignSystemId(
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,
188
+ projectName,
189
+ description,
190
+ });
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
+
245
+ return {
246
+ ...result,
247
+ localDesignSystemId,
248
+ 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 Design flows; Builder remains the source of truth for the indexed brand kit.",
256
+ ].join("\n"),
257
+ };
258
+ },
259
+ });
@@ -23,8 +23,15 @@ export default defineAction({
23
23
  .enum(["html", "css", "jsx", "asset"])
24
24
  .optional()
25
25
  .describe("Updated file type"),
26
+ syncCollab: z
27
+ .boolean()
28
+ .optional()
29
+ .default(true)
30
+ .describe(
31
+ "Whether to mirror content updates into the live collaboration document.",
32
+ ),
26
33
  }),
27
- run: async ({ id, content, filename, fileType }) => {
34
+ run: async ({ id, content, filename, fileType, syncCollab }) => {
28
35
  // Path traversal guard on filename
29
36
  if (
30
37
  filename &&
@@ -74,7 +81,7 @@ export default defineAction({
74
81
  .where(eq(schema.designFiles.id, id));
75
82
 
76
83
  // Push content through the collab layer so live editors see the change
77
- if (content !== undefined) {
84
+ if (content !== undefined && syncCollab) {
78
85
  const collabExists = await hasCollabState(id);
79
86
  if (collabExists) {
80
87
  await applyText(id, content, "content", "agent");
@@ -1,25 +1,3 @@
1
- import {
2
- IconArrowBarToDown,
3
- IconArrowBarToUp,
4
- IconArrowDown,
5
- IconArrowUp,
6
- IconClipboard,
7
- IconClipboardCopy,
8
- IconCode,
9
- IconCopy,
10
- IconEye,
11
- IconEyeOff,
12
- IconHierarchy,
13
- IconLayersSubtract,
14
- IconLock,
15
- IconLockOpen,
16
- IconPencil,
17
- IconSelectAll,
18
- IconTrash,
19
- IconZoomInArea,
20
- IconZoomScan,
21
- type Icon,
22
- } from "@tabler/icons-react";
23
1
  import {
24
2
  forwardRef,
25
3
  useCallback,
@@ -231,42 +209,46 @@ const DEFAULT_LABELS: CanvasContextMenuLabels = {
231
209
  };
232
210
 
233
211
  const DEFAULT_SHORTCUTS: CanvasContextMenuShortcuts = {
234
- pasteHere: "Cmd+V",
235
- selectAll: "Cmd+A",
236
- zoomToFit: "Shift+1",
237
- zoomToSelection: "Shift+2",
238
- copy: "Cmd+C",
239
- paste: "Cmd+V",
240
- pasteOver: "Shift+Cmd+V",
241
- duplicate: "Cmd+D",
242
- delete: "Del",
243
- bringForward: "Cmd+]",
244
- bringToFront: "Opt+Cmd+]",
245
- sendBackward: "Cmd+[",
246
- sendToBack: "Opt+Cmd+[",
247
- group: "Cmd+G",
248
- ungroup: "Shift+Cmd+G",
249
- rename: "Cmd+R",
250
- copyProps: "Opt+Cmd+C",
251
- pasteProps: "Opt+Cmd+V",
252
- copyAsCode: "Shift+Cmd+C",
212
+ pasteHere: "V",
213
+ selectAll: "A",
214
+ zoomToFit: "1",
215
+ zoomToSelection: "2",
216
+ copy: "C",
217
+ paste: "V",
218
+ pasteOver: "⇧⌘V",
219
+ duplicate: "D",
220
+ delete: "",
221
+ bringForward: "]",
222
+ bringToFront: "⌥⌘]",
223
+ sendBackward: "[",
224
+ sendToBack: "⌥⌘[",
225
+ group: "G",
226
+ ungroup: "⇧⌘G",
227
+ rename: "R",
228
+ copyProps: "⌥⌘C",
229
+ pasteProps: "⌥⌘V",
230
+ copyAsCode: "⇧⌘C",
253
231
  };
254
232
 
255
233
  type ActionCallbackMap = Partial<
256
234
  Record<CanvasContextMenuAction, CanvasContextMenuActionHandler>
257
235
  >;
258
236
 
237
+ // Figma-style menu chrome: compact, dark-border, subtle shadow, no animation jitter
259
238
  const MENU_CONTENT_CLASS =
260
- "w-60 rounded-md border border-[var(--design-editor-control-border)] bg-[var(--design-editor-panel-bg)] p-1 text-[11px] text-foreground shadow-[0_8px_28px_rgba(0,0,0,0.18)] outline-none animate-none data-[state=open]:animate-none data-[state=closed]:animate-none data-[side=bottom]:slide-in-from-top-0 data-[side=left]:slide-in-from-right-0 data-[side=right]:slide-in-from-left-0 data-[side=top]:slide-in-from-bottom-0";
239
+ "w-52 min-w-[200px] rounded-[6px] border border-[var(--design-editor-control-border)] bg-[var(--design-editor-panel-bg)] py-[3px] px-[3px] text-[12px] text-foreground shadow-[0_4px_16px_rgba(0,0,0,0.16),0_0_0_0.5px_rgba(0,0,0,0.08)] outline-none data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-[0.97] data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 duration-100";
240
+ // Figma row height ~28px, full-width highlight on hover, no icon gap waste
261
241
  const MENU_ITEM_CLASS =
262
- "h-6 gap-2 rounded-[3px] px-1.5 py-0 text-[11px] leading-none focus:bg-[var(--design-editor-selection-color)] focus:text-foreground data-[disabled]:opacity-40";
263
- const MENU_ICON_CLASS = "mr-0 size-3.5 shrink-0 text-muted-foreground";
242
+ "flex h-7 cursor-default select-none items-center rounded-[4px] px-2 py-0 text-[12px] leading-none gap-0 focus:bg-[var(--design-editor-selection-color)] focus:text-white data-[disabled]:pointer-events-none data-[disabled]:opacity-35";
243
+ // Submenu trigger mirrors item styles + chevron sizing
264
244
  const MENU_SUB_TRIGGER_CLASS =
265
- "h-6 rounded-[3px] px-1.5 py-0 text-[11px] leading-none focus:bg-[var(--design-editor-selection-color)] focus:text-foreground data-[state=open]:bg-[var(--design-editor-selection-color)] data-[state=open]:text-foreground [&>svg:last-child]:size-3.5 [&>svg:last-child]:text-muted-foreground";
245
+ "flex h-7 cursor-default select-none items-center rounded-[4px] px-2 py-0 text-[12px] leading-none focus:bg-[var(--design-editor-selection-color)] focus:text-white data-[state=open]:bg-[var(--design-editor-selection-color)] data-[state=open]:text-white [&>svg:last-child]:ms-auto [&>svg:last-child]:size-3 [&>svg:last-child]:opacity-50";
246
+ // Separator: 1px, full-width flush, Figma-like muted line
266
247
  const MENU_SEPARATOR_CLASS =
267
- "-mx-1 my-1 bg-[var(--design-editor-control-border)]";
248
+ "mx-0 my-[3px] h-px bg-[var(--design-editor-control-border)] opacity-80";
249
+ // Shortcut: right-aligned, muted, use system UI for symbol rendering
268
250
  const MENU_SHORTCUT_CLASS =
269
- "ml-auto pl-6 text-[10px] tracking-normal text-muted-foreground";
251
+ "ms-auto ps-4 font-normal text-[11px] tracking-normal text-muted-foreground/70 tabular-nums";
270
252
 
271
253
  export const CanvasContextMenu = forwardRef<
272
254
  CanvasContextMenuHandle,
@@ -496,7 +478,6 @@ export const CanvasContextMenu = forwardRef<
496
478
  <CanvasMenuItem
497
479
  hidden={isHiddenAction("paste-here")}
498
480
  disabled={!canRun("paste-here", canPasteHere)}
499
- icon={IconClipboard}
500
481
  label={labels.pasteHere}
501
482
  shortcut={shortcuts.pasteHere}
502
483
  onSelect={(event) => runAction("paste-here", event)}
@@ -504,7 +485,6 @@ export const CanvasContextMenu = forwardRef<
504
485
  <CanvasMenuItem
505
486
  hidden={isHiddenAction("select-all")}
506
487
  disabled={!canRun("select-all", canSelectAll)}
507
- icon={IconSelectAll}
508
488
  label={labels.selectAll}
509
489
  shortcut={shortcuts.selectAll}
510
490
  onSelect={(event) => runAction("select-all", event)}
@@ -517,7 +497,6 @@ export const CanvasContextMenu = forwardRef<
517
497
  <CanvasMenuItem
518
498
  hidden={isHiddenAction("zoom-to-fit")}
519
499
  disabled={!canRun("zoom-to-fit", canZoomToFit)}
520
- icon={IconZoomScan}
521
500
  label={labels.zoomToFit}
522
501
  shortcut={shortcuts.zoomToFit}
523
502
  onSelect={(event) => runAction("zoom-to-fit", event)}
@@ -525,7 +504,6 @@ export const CanvasContextMenu = forwardRef<
525
504
  <CanvasMenuItem
526
505
  hidden={isHiddenAction("zoom-to-selection")}
527
506
  disabled={!canRun("zoom-to-selection", canZoomToSelection)}
528
- icon={IconZoomInArea}
529
507
  label={labels.zoomToSelection}
530
508
  shortcut={shortcuts.zoomToSelection}
531
509
  onSelect={(event) => runAction("zoom-to-selection", event)}
@@ -538,7 +516,6 @@ export const CanvasContextMenu = forwardRef<
538
516
  <CanvasMenuItem
539
517
  hidden={isHiddenAction("copy")}
540
518
  disabled={!canRun("copy", canCopy)}
541
- icon={IconCopy}
542
519
  label={labels.copy}
543
520
  shortcut={shortcuts.copy}
544
521
  onSelect={(event) => runAction("copy", event)}
@@ -546,7 +523,6 @@ export const CanvasContextMenu = forwardRef<
546
523
  <CanvasMenuItem
547
524
  hidden={isHiddenAction("paste")}
548
525
  disabled={!canRun("paste", canPaste)}
549
- icon={IconClipboard}
550
526
  label={labels.paste}
551
527
  shortcut={shortcuts.paste}
552
528
  onSelect={(event) => runAction("paste", event)}
@@ -554,7 +530,6 @@ export const CanvasContextMenu = forwardRef<
554
530
  <CanvasMenuItem
555
531
  hidden={isHiddenAction("paste-over")}
556
532
  disabled={!canRun("paste-over", canPasteOver)}
557
- icon={IconClipboardCopy}
558
533
  label={labels.pasteOver}
559
534
  shortcut={shortcuts.pasteOver}
560
535
  onSelect={(event) => runAction("paste-over", event)}
@@ -562,7 +537,6 @@ export const CanvasContextMenu = forwardRef<
562
537
  <CanvasMenuItem
563
538
  hidden={isHiddenAction("duplicate")}
564
539
  disabled={!canRun("duplicate", canDuplicate)}
565
- icon={IconCopy}
566
540
  label={labels.duplicate}
567
541
  shortcut={shortcuts.duplicate}
568
542
  onSelect={(event) => runAction("duplicate", event)}
@@ -588,14 +562,12 @@ export const CanvasContextMenu = forwardRef<
588
562
  }
589
563
  className={MENU_SUB_TRIGGER_CLASS}
590
564
  >
591
- <IconArrowUp className={MENU_ICON_CLASS} />
592
565
  {labels.order}
593
566
  </ContextMenuSubTrigger>
594
- <ContextMenuSubContent className={cn(MENU_CONTENT_CLASS, "w-56")}>
567
+ <ContextMenuSubContent className={cn(MENU_CONTENT_CLASS, "w-52")}>
595
568
  <CanvasMenuItem
596
569
  hidden={isHiddenAction("bring-forward")}
597
570
  disabled={!canRun("bring-forward", canReorder)}
598
- icon={IconArrowUp}
599
571
  label={labels.bringForward}
600
572
  shortcut={shortcuts.bringForward}
601
573
  onSelect={(event) => runAction("bring-forward", event)}
@@ -603,7 +575,6 @@ export const CanvasContextMenu = forwardRef<
603
575
  <CanvasMenuItem
604
576
  hidden={isHiddenAction("bring-to-front")}
605
577
  disabled={!canRun("bring-to-front", canReorder)}
606
- icon={IconArrowBarToUp}
607
578
  label={labels.bringToFront}
608
579
  shortcut={shortcuts.bringToFront}
609
580
  onSelect={(event) => runAction("bring-to-front", event)}
@@ -611,7 +582,6 @@ export const CanvasContextMenu = forwardRef<
611
582
  <CanvasMenuItem
612
583
  hidden={isHiddenAction("send-backward")}
613
584
  disabled={!canRun("send-backward", canReorder)}
614
- icon={IconArrowDown}
615
585
  label={labels.sendBackward}
616
586
  shortcut={shortcuts.sendBackward}
617
587
  onSelect={(event) => runAction("send-backward", event)}
@@ -619,7 +589,6 @@ export const CanvasContextMenu = forwardRef<
619
589
  <CanvasMenuItem
620
590
  hidden={isHiddenAction("send-to-back")}
621
591
  disabled={!canRun("send-to-back", canReorder)}
622
- icon={IconArrowBarToDown}
623
592
  label={labels.sendToBack}
624
593
  shortcut={shortcuts.sendToBack}
625
594
  onSelect={(event) => runAction("send-to-back", event)}
@@ -630,7 +599,6 @@ export const CanvasContextMenu = forwardRef<
630
599
  <CanvasMenuItem
631
600
  hidden={isHiddenAction("group")}
632
601
  disabled={!canRun("group", canGroup)}
633
- icon={IconHierarchy}
634
602
  label={labels.group}
635
603
  shortcut={shortcuts.group}
636
604
  onSelect={(event) => runAction("group", event)}
@@ -638,7 +606,6 @@ export const CanvasContextMenu = forwardRef<
638
606
  <CanvasMenuItem
639
607
  hidden={isHiddenAction("ungroup")}
640
608
  disabled={!canRun("ungroup", canUngroup)}
641
- icon={IconLayersSubtract}
642
609
  label={labels.ungroup}
643
610
  shortcut={shortcuts.ungroup}
644
611
  onSelect={(event) => runAction("ungroup", event)}
@@ -651,7 +618,6 @@ export const CanvasContextMenu = forwardRef<
651
618
  <CanvasMenuItem
652
619
  hidden={isHiddenAction("rename")}
653
620
  disabled={!canRun("rename", canRename)}
654
- icon={IconPencil}
655
621
  label={labels.rename}
656
622
  shortcut={shortcuts.rename}
657
623
  onSelect={(event) => runAction("rename", event)}
@@ -659,14 +625,12 @@ export const CanvasContextMenu = forwardRef<
659
625
  <CanvasMenuItem
660
626
  hidden={isHiddenAction("toggle-lock")}
661
627
  disabled={!canRun("toggle-lock", canToggleLocked)}
662
- icon={isLocked ? IconLockOpen : IconLock}
663
628
  label={isLocked ? labels.unlock : labels.lock}
664
629
  onSelect={(event) => runAction("toggle-lock", event)}
665
630
  />
666
631
  <CanvasMenuItem
667
632
  hidden={isHiddenAction("toggle-hide")}
668
633
  disabled={!canRun("toggle-hide", canToggleHidden)}
669
- icon={isHidden ? IconEye : IconEyeOff}
670
634
  label={isHidden ? labels.show : labels.hide}
671
635
  onSelect={(event) => runAction("toggle-hide", event)}
672
636
  />
@@ -678,7 +642,6 @@ export const CanvasContextMenu = forwardRef<
678
642
  <CanvasMenuItem
679
643
  hidden={isHiddenAction("copy-props")}
680
644
  disabled={!canRun("copy-props", canCopyProps)}
681
- icon={IconClipboardCopy}
682
645
  label={labels.copyProps}
683
646
  shortcut={shortcuts.copyProps}
684
647
  onSelect={(event) => runAction("copy-props", event)}
@@ -686,7 +649,6 @@ export const CanvasContextMenu = forwardRef<
686
649
  <CanvasMenuItem
687
650
  hidden={isHiddenAction("paste-props")}
688
651
  disabled={!canRun("paste-props", canPasteProps)}
689
- icon={IconClipboard}
690
652
  label={labels.pasteProps}
691
653
  shortcut={shortcuts.pasteProps}
692
654
  onSelect={(event) => runAction("paste-props", event)}
@@ -694,7 +656,6 @@ export const CanvasContextMenu = forwardRef<
694
656
  <CanvasMenuItem
695
657
  hidden={isHiddenAction("copy-as-code")}
696
658
  disabled={!canRun("copy-as-code", canCopyAsCode)}
697
- icon={IconCode}
698
659
  label={labels.copyAsCode}
699
660
  shortcut={shortcuts.copyAsCode}
700
661
  onSelect={(event) => runAction("copy-as-code", event)}
@@ -706,7 +667,6 @@ export const CanvasContextMenu = forwardRef<
706
667
  <CanvasMenuItem
707
668
  hidden={isHiddenAction("delete")}
708
669
  disabled={!canRun("delete", canDelete)}
709
- icon={IconTrash}
710
670
  label={labels.delete}
711
671
  shortcut={shortcuts.delete}
712
672
  destructive
@@ -721,7 +681,6 @@ function CanvasMenuItem({
721
681
  hidden,
722
682
  disabled,
723
683
  destructive,
724
- icon: Icon,
725
684
  label,
726
685
  shortcut,
727
686
  onSelect,
@@ -729,7 +688,6 @@ function CanvasMenuItem({
729
688
  hidden?: boolean;
730
689
  disabled?: boolean;
731
690
  destructive?: boolean;
732
- icon: Icon;
733
691
  label: string;
734
692
  shortcut?: string;
735
693
  onSelect: (event: Event) => void;
@@ -742,11 +700,11 @@ function CanvasMenuItem({
742
700
  onSelect={onSelect}
743
701
  className={cn(
744
702
  MENU_ITEM_CLASS,
745
- destructive && "text-destructive focus:text-destructive",
703
+ destructive &&
704
+ "text-destructive focus:bg-destructive/10 focus:text-destructive",
746
705
  )}
747
706
  >
748
- <Icon className={MENU_ICON_CLASS} />
749
- <span className="truncate">{label}</span>
707
+ <span className="flex-1 truncate">{label}</span>
750
708
  {shortcut ? (
751
709
  <ContextMenuShortcut className={MENU_SHORTCUT_CLASS}>
752
710
  {shortcut}