@agent-native/core 0.37.3 → 0.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (377) hide show
  1. package/README.md +19 -6
  2. package/dist/action.d.ts +60 -2
  3. package/dist/action.d.ts.map +1 -1
  4. package/dist/action.js +6 -2
  5. package/dist/action.js.map +1 -1
  6. package/dist/agent/production-agent.d.ts +12 -6
  7. package/dist/agent/production-agent.d.ts.map +1 -1
  8. package/dist/agent/production-agent.js +161 -11
  9. package/dist/agent/production-agent.js.map +1 -1
  10. package/dist/agent/types.d.ts +2 -0
  11. package/dist/agent/types.d.ts.map +1 -1
  12. package/dist/agent/types.js.map +1 -1
  13. package/dist/catalog.json +2 -2
  14. package/dist/cli/connect.d.ts.map +1 -1
  15. package/dist/cli/connect.js +15 -0
  16. package/dist/cli/connect.js.map +1 -1
  17. package/dist/cli/index.js +10 -6
  18. package/dist/cli/index.js.map +1 -1
  19. package/dist/cli/plan-publish-store.d.ts +52 -0
  20. package/dist/cli/plan-publish-store.d.ts.map +1 -0
  21. package/dist/cli/plan-publish-store.js +103 -0
  22. package/dist/cli/plan-publish-store.js.map +1 -0
  23. package/dist/cli/skills.d.ts +29 -4
  24. package/dist/cli/skills.d.ts.map +1 -1
  25. package/dist/cli/skills.js +851 -275
  26. package/dist/cli/skills.js.map +1 -1
  27. package/dist/cli/templates-meta.js +12 -12
  28. package/dist/cli/templates-meta.js.map +1 -1
  29. package/dist/client/AssistantChat.d.ts +3 -1
  30. package/dist/client/AssistantChat.d.ts.map +1 -1
  31. package/dist/client/AssistantChat.js +65 -15
  32. package/dist/client/AssistantChat.js.map +1 -1
  33. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  34. package/dist/client/MultiTabAssistantChat.js +20 -2
  35. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  36. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  37. package/dist/client/agent-chat-adapter.js +12 -0
  38. package/dist/client/agent-chat-adapter.js.map +1 -1
  39. package/dist/client/agent-engine-key.d.ts +24 -0
  40. package/dist/client/agent-engine-key.d.ts.map +1 -0
  41. package/dist/client/agent-engine-key.js +49 -0
  42. package/dist/client/agent-engine-key.js.map +1 -0
  43. package/dist/client/analytics.d.ts.map +1 -1
  44. package/dist/client/analytics.js +34 -0
  45. package/dist/client/analytics.js.map +1 -1
  46. package/dist/client/blocks/BlockView.d.ts +26 -0
  47. package/dist/client/blocks/BlockView.d.ts.map +1 -0
  48. package/dist/client/blocks/BlockView.js +24 -0
  49. package/dist/client/blocks/BlockView.js.map +1 -0
  50. package/dist/client/blocks/SchemaBlockEditor.d.ts +25 -0
  51. package/dist/client/blocks/SchemaBlockEditor.d.ts.map +1 -0
  52. package/dist/client/blocks/SchemaBlockEditor.js +72 -0
  53. package/dist/client/blocks/SchemaBlockEditor.js.map +1 -0
  54. package/dist/client/blocks/agent.d.ts +30 -0
  55. package/dist/client/blocks/agent.d.ts.map +1 -0
  56. package/dist/client/blocks/agent.js +61 -0
  57. package/dist/client/blocks/agent.js.map +1 -0
  58. package/dist/client/blocks/index.d.ts +34 -0
  59. package/dist/client/blocks/index.d.ts.map +1 -0
  60. package/dist/client/blocks/index.js +42 -0
  61. package/dist/client/blocks/index.js.map +1 -0
  62. package/dist/client/blocks/library/checklist.config.d.ts +36 -0
  63. package/dist/client/blocks/library/checklist.config.d.ts.map +1 -0
  64. package/dist/client/blocks/library/checklist.config.js +25 -0
  65. package/dist/client/blocks/library/checklist.config.js.map +1 -0
  66. package/dist/client/blocks/library/checklist.d.ts +26 -0
  67. package/dist/client/blocks/library/checklist.d.ts.map +1 -0
  68. package/dist/client/blocks/library/checklist.js +76 -0
  69. package/dist/client/blocks/library/checklist.js.map +1 -0
  70. package/dist/client/blocks/library/code-tabs.config.d.ts +36 -0
  71. package/dist/client/blocks/library/code-tabs.config.d.ts.map +1 -0
  72. package/dist/client/blocks/library/code-tabs.config.js +30 -0
  73. package/dist/client/blocks/library/code-tabs.config.js.map +1 -0
  74. package/dist/client/blocks/library/code-tabs.d.ts +3 -0
  75. package/dist/client/blocks/library/code-tabs.d.ts.map +1 -0
  76. package/dist/client/blocks/library/code-tabs.js +165 -0
  77. package/dist/client/blocks/library/code-tabs.js.map +1 -0
  78. package/dist/client/blocks/library/html.config.d.ts +37 -0
  79. package/dist/client/blocks/library/html.config.d.ts.map +1 -0
  80. package/dist/client/blocks/library/html.config.js +46 -0
  81. package/dist/client/blocks/library/html.config.js.map +1 -0
  82. package/dist/client/blocks/library/html.d.ts +21 -0
  83. package/dist/client/blocks/library/html.d.ts.map +1 -0
  84. package/dist/client/blocks/library/html.js +69 -0
  85. package/dist/client/blocks/library/html.js.map +1 -0
  86. package/dist/client/blocks/library/table.config.d.ts +30 -0
  87. package/dist/client/blocks/library/table.config.d.ts.map +1 -0
  88. package/dist/client/blocks/library/table.config.js +22 -0
  89. package/dist/client/blocks/library/table.config.js.map +1 -0
  90. package/dist/client/blocks/library/table.d.ts +8 -0
  91. package/dist/client/blocks/library/table.d.ts.map +1 -0
  92. package/dist/client/blocks/library/table.js +107 -0
  93. package/dist/client/blocks/library/table.js.map +1 -0
  94. package/dist/client/blocks/library/tabs.config.d.ts +56 -0
  95. package/dist/client/blocks/library/tabs.config.d.ts.map +1 -0
  96. package/dist/client/blocks/library/tabs.config.js +36 -0
  97. package/dist/client/blocks/library/tabs.config.js.map +1 -0
  98. package/dist/client/blocks/library/tabs.d.ts +20 -0
  99. package/dist/client/blocks/library/tabs.d.ts.map +1 -0
  100. package/dist/client/blocks/library/tabs.js +123 -0
  101. package/dist/client/blocks/library/tabs.js.map +1 -0
  102. package/dist/client/blocks/mdx.d.ts +74 -0
  103. package/dist/client/blocks/mdx.d.ts.map +1 -0
  104. package/dist/client/blocks/mdx.js +205 -0
  105. package/dist/client/blocks/mdx.js.map +1 -0
  106. package/dist/client/blocks/provider.d.ts +25 -0
  107. package/dist/client/blocks/provider.d.ts.map +1 -0
  108. package/dist/client/blocks/provider.js +19 -0
  109. package/dist/client/blocks/provider.js.map +1 -0
  110. package/dist/client/blocks/registry.d.ts +24 -0
  111. package/dist/client/blocks/registry.d.ts.map +1 -0
  112. package/dist/client/blocks/registry.js +50 -0
  113. package/dist/client/blocks/registry.js.map +1 -0
  114. package/dist/client/blocks/schema-form/introspect.d.ts +31 -0
  115. package/dist/client/blocks/schema-form/introspect.d.ts.map +1 -0
  116. package/dist/client/blocks/schema-form/introspect.js +164 -0
  117. package/dist/client/blocks/schema-form/introspect.js.map +1 -0
  118. package/dist/client/blocks/server.d.ts +22 -0
  119. package/dist/client/blocks/server.d.ts.map +1 -0
  120. package/dist/client/blocks/server.js +25 -0
  121. package/dist/client/blocks/server.js.map +1 -0
  122. package/dist/client/blocks/types.d.ts +212 -0
  123. package/dist/client/blocks/types.d.ts.map +1 -0
  124. package/dist/client/blocks/types.js +5 -0
  125. package/dist/client/blocks/types.js.map +1 -0
  126. package/dist/client/composer/ComposerPlusMenu.js +10 -1
  127. package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
  128. package/dist/client/guided-questions.d.ts +68 -0
  129. package/dist/client/guided-questions.d.ts.map +1 -1
  130. package/dist/client/guided-questions.js +158 -3
  131. package/dist/client/guided-questions.js.map +1 -1
  132. package/dist/client/index.d.ts +5 -1
  133. package/dist/client/index.d.ts.map +1 -1
  134. package/dist/client/index.js +15 -1
  135. package/dist/client/index.js.map +1 -1
  136. package/dist/client/rich-markdown-editor/BubbleToolbar.d.ts +37 -0
  137. package/dist/client/rich-markdown-editor/BubbleToolbar.d.ts.map +1 -0
  138. package/dist/client/rich-markdown-editor/BubbleToolbar.js +161 -0
  139. package/dist/client/rich-markdown-editor/BubbleToolbar.js.map +1 -0
  140. package/dist/client/rich-markdown-editor/ImageExtension.d.ts +63 -0
  141. package/dist/client/rich-markdown-editor/ImageExtension.d.ts.map +1 -0
  142. package/dist/client/rich-markdown-editor/ImageExtension.js +242 -0
  143. package/dist/client/rich-markdown-editor/ImageExtension.js.map +1 -0
  144. package/dist/client/rich-markdown-editor/RichMarkdownEditor.d.ts +51 -0
  145. package/dist/client/rich-markdown-editor/RichMarkdownEditor.d.ts.map +1 -0
  146. package/dist/client/rich-markdown-editor/RichMarkdownEditor.js +37 -0
  147. package/dist/client/rich-markdown-editor/RichMarkdownEditor.js.map +1 -0
  148. package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts +61 -0
  149. package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts.map +1 -0
  150. package/dist/client/rich-markdown-editor/SharedRichEditor.js +121 -0
  151. package/dist/client/rich-markdown-editor/SharedRichEditor.js.map +1 -0
  152. package/dist/client/rich-markdown-editor/SlashCommandMenu.d.ts +36 -0
  153. package/dist/client/rich-markdown-editor/SlashCommandMenu.d.ts.map +1 -0
  154. package/dist/client/rich-markdown-editor/SlashCommandMenu.js +193 -0
  155. package/dist/client/rich-markdown-editor/SlashCommandMenu.js.map +1 -0
  156. package/dist/client/rich-markdown-editor/extensions.d.ts +166 -0
  157. package/dist/client/rich-markdown-editor/extensions.d.ts.map +1 -0
  158. package/dist/client/rich-markdown-editor/extensions.js +222 -0
  159. package/dist/client/rich-markdown-editor/extensions.js.map +1 -0
  160. package/dist/client/rich-markdown-editor/index.d.ts +9 -0
  161. package/dist/client/rich-markdown-editor/index.d.ts.map +1 -0
  162. package/dist/client/rich-markdown-editor/index.js +9 -0
  163. package/dist/client/rich-markdown-editor/index.js.map +1 -0
  164. package/dist/client/rich-markdown-editor/uploadEditorImage.d.ts +18 -0
  165. package/dist/client/rich-markdown-editor/uploadEditorImage.d.ts.map +1 -0
  166. package/dist/client/rich-markdown-editor/uploadEditorImage.js +57 -0
  167. package/dist/client/rich-markdown-editor/uploadEditorImage.js.map +1 -0
  168. package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts +91 -0
  169. package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts.map +1 -0
  170. package/dist/client/rich-markdown-editor/useCollabReconcile.js +342 -0
  171. package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +1 -0
  172. package/dist/client/track.d.ts +25 -0
  173. package/dist/client/track.d.ts.map +1 -0
  174. package/dist/client/track.js +53 -0
  175. package/dist/client/track.js.map +1 -0
  176. package/dist/client/use-action.d.ts.map +1 -1
  177. package/dist/client/use-action.js +6 -0
  178. package/dist/client/use-action.js.map +1 -1
  179. package/dist/client/use-session.d.ts +3 -2
  180. package/dist/client/use-session.d.ts.map +1 -1
  181. package/dist/client/use-session.js +3 -2
  182. package/dist/client/use-session.js.map +1 -1
  183. package/dist/deploy/build.d.ts +5 -0
  184. package/dist/deploy/build.d.ts.map +1 -1
  185. package/dist/deploy/build.js +67 -1
  186. package/dist/deploy/build.js.map +1 -1
  187. package/dist/extensions/schema.d.ts +1 -1
  188. package/dist/mcp/build-server.d.ts.map +1 -1
  189. package/dist/mcp/build-server.js +9 -2
  190. package/dist/mcp/build-server.js.map +1 -1
  191. package/dist/mcp/server.d.ts +1 -1
  192. package/dist/mcp/server.d.ts.map +1 -1
  193. package/dist/mcp/server.js +35 -2
  194. package/dist/mcp/server.js.map +1 -1
  195. package/dist/provider-api/index.d.ts +1 -1
  196. package/dist/provider-api/index.d.ts.map +1 -1
  197. package/dist/scripts/docs/search.d.ts.map +1 -1
  198. package/dist/scripts/docs/search.js +5 -2
  199. package/dist/scripts/docs/search.js.map +1 -1
  200. package/dist/scripts/runner.d.ts.map +1 -1
  201. package/dist/scripts/runner.js +16 -3
  202. package/dist/scripts/runner.js.map +1 -1
  203. package/dist/server/action-discovery.d.ts.map +1 -1
  204. package/dist/server/action-discovery.js +2 -0
  205. package/dist/server/action-discovery.js.map +1 -1
  206. package/dist/server/action-routes.d.ts.map +1 -1
  207. package/dist/server/action-routes.js +30 -4
  208. package/dist/server/action-routes.js.map +1 -1
  209. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  210. package/dist/server/agent-chat-plugin.js +65 -19
  211. package/dist/server/agent-chat-plugin.js.map +1 -1
  212. package/dist/server/agent-teams.d.ts.map +1 -1
  213. package/dist/server/agent-teams.js +8 -1
  214. package/dist/server/agent-teams.js.map +1 -1
  215. package/dist/server/agents-bundle.d.ts +27 -1
  216. package/dist/server/agents-bundle.d.ts.map +1 -1
  217. package/dist/server/agents-bundle.js +41 -3
  218. package/dist/server/agents-bundle.js.map +1 -1
  219. package/dist/server/auth.d.ts.map +1 -1
  220. package/dist/server/auth.js +76 -3
  221. package/dist/server/auth.js.map +1 -1
  222. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  223. package/dist/server/core-routes-plugin.js +60 -0
  224. package/dist/server/core-routes-plugin.js.map +1 -1
  225. package/dist/server/onboarding-html.d.ts.map +1 -1
  226. package/dist/server/onboarding-html.js +160 -22
  227. package/dist/server/onboarding-html.js.map +1 -1
  228. package/dist/server/sentry.d.ts.map +1 -1
  229. package/dist/server/sentry.js +6 -0
  230. package/dist/server/sentry.js.map +1 -1
  231. package/dist/server/social-og-image.d.ts +2 -1
  232. package/dist/server/social-og-image.d.ts.map +1 -1
  233. package/dist/server/social-og-image.js +24 -4
  234. package/dist/server/social-og-image.js.map +1 -1
  235. package/dist/sharing/schema.d.ts +1 -1
  236. package/dist/styles/agent-native.css +1 -0
  237. package/dist/styles/rich-markdown-editor.css +439 -0
  238. package/dist/templates/default/.agents/skills/actions/SKILL.md +4 -1
  239. package/dist/templates/default/.agents/skills/security/SKILL.md +13 -4
  240. package/dist/templates/default/.agents/skills/storing-data/SKILL.md +15 -3
  241. package/dist/templates/default/AGENTS.md +1 -0
  242. package/dist/templates/default/DEVELOPING.md +2 -0
  243. package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +10 -3
  244. package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +98 -10
  245. package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +45 -3
  246. package/dist/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +2 -0
  247. package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +37 -4
  248. package/dist/templates/workspace-core/.agents/skills/automations/SKILL.md +9 -4
  249. package/dist/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +2 -0
  250. package/dist/templates/workspace-core/.agents/skills/client-methods/SKILL.md +106 -0
  251. package/dist/templates/workspace-core/.agents/skills/client-methods/references/legacy-client-fetch-audit-2026-06-03.md +53 -0
  252. package/dist/templates/workspace-core/.agents/skills/client-side-routing/SKILL.md +2 -0
  253. package/dist/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +62 -61
  254. package/dist/templates/workspace-core/.agents/skills/context-xray/SKILL.md +47 -0
  255. package/dist/templates/workspace-core/.agents/skills/create-skill/SKILL.md +28 -0
  256. package/dist/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +52 -1
  257. package/dist/templates/workspace-core/.agents/skills/extension-points/SKILL.md +2 -0
  258. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +95 -433
  259. package/dist/templates/workspace-core/.agents/skills/extensions/references/api.md +285 -0
  260. package/dist/templates/workspace-core/.agents/skills/extensions/references/examples.md +259 -0
  261. package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +398 -0
  262. package/dist/templates/workspace-core/.agents/skills/external-agents/references/mcp-apps-embedding.md +157 -0
  263. package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +17 -0
  264. package/dist/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +13 -2
  265. package/dist/templates/workspace-core/.agents/skills/mvp-followup/SKILL.md +51 -0
  266. package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +14 -4
  267. package/dist/templates/workspace-core/.agents/skills/onboarding/SKILL.md +13 -1
  268. package/dist/templates/workspace-core/.agents/skills/portability/SKILL.md +27 -5
  269. package/dist/templates/workspace-core/.agents/skills/qa/SKILL.md +24 -8
  270. package/dist/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +53 -7
  271. package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +43 -10
  272. package/dist/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +2 -0
  273. package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +43 -14
  274. package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +50 -1
  275. package/dist/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +4 -2
  276. package/dist/templates/workspace-core/.agents/skills/server-plugins/SKILL.md +11 -1
  277. package/dist/templates/workspace-core/.agents/skills/shadcn-ui/SKILL.md +15 -0
  278. package/dist/templates/workspace-core/.agents/skills/sharing/SKILL.md +5 -1
  279. package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +48 -19
  280. package/dist/templates/workspace-core/.agents/skills/tracking/SKILL.md +7 -3
  281. package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +13 -6
  282. package/dist/templates/workspace-core/.agents/skills/writing-agent-instructions/SKILL.md +236 -0
  283. package/dist/templates/workspace-core/AGENTS.md +5 -1
  284. package/dist/templates/workspace-root/AGENTS.md +5 -2
  285. package/dist/tracking/route.d.ts +43 -0
  286. package/dist/tracking/route.d.ts.map +1 -0
  287. package/dist/tracking/route.js +85 -0
  288. package/dist/tracking/route.js.map +1 -0
  289. package/dist/vite/client.d.ts.map +1 -1
  290. package/dist/vite/client.js +15 -0
  291. package/dist/vite/client.js.map +1 -1
  292. package/docs/content/a2a-protocol.md +18 -4
  293. package/docs/content/actions.md +87 -0
  294. package/docs/content/agent-mentions.md +2 -1
  295. package/docs/content/authentication.md +2 -1
  296. package/docs/content/client.md +64 -13
  297. package/docs/content/cloneable-saas.md +1 -1
  298. package/docs/content/code-agents-ui.md +17 -11
  299. package/docs/content/context-awareness.md +23 -28
  300. package/docs/content/creating-templates.md +1 -1
  301. package/docs/content/drop-in-agent.md +2 -0
  302. package/docs/content/getting-started.md +2 -2
  303. package/docs/content/key-concepts.md +2 -2
  304. package/docs/content/messaging.md +57 -15
  305. package/docs/content/migration-workbench.md +1 -1
  306. package/docs/content/multi-app-workspace.md +1 -1
  307. package/docs/content/multi-tenancy.md +17 -15
  308. package/docs/content/real-time-collaboration.md +1 -1
  309. package/docs/content/recurring-jobs.md +1 -1
  310. package/docs/content/security.md +2 -2
  311. package/docs/content/server.md +4 -4
  312. package/docs/content/skills-guide.md +30 -0
  313. package/docs/content/template-analytics.md +2 -2
  314. package/docs/content/template-assets.md +17 -1
  315. package/docs/content/template-brain.md +2 -2
  316. package/docs/content/template-calendar.md +1 -1
  317. package/docs/content/template-clips.md +3 -3
  318. package/docs/content/template-content.md +2 -2
  319. package/docs/content/template-design.md +2 -2
  320. package/docs/content/template-dispatch.md +3 -3
  321. package/docs/content/template-forms.md +14 -2
  322. package/docs/content/template-mail.md +1 -3
  323. package/docs/content/template-plan.md +118 -0
  324. package/docs/content/template-slides.md +5 -4
  325. package/docs/content/template-starter.md +4 -4
  326. package/docs/content/template-videos.md +6 -11
  327. package/docs/content/tracking.md +21 -1
  328. package/docs/content/visual-plans.md +72 -0
  329. package/docs/content/workspace.md +9 -9
  330. package/package.json +26 -11
  331. package/src/templates/default/.agents/skills/actions/SKILL.md +4 -1
  332. package/src/templates/default/.agents/skills/security/SKILL.md +13 -4
  333. package/src/templates/default/.agents/skills/storing-data/SKILL.md +15 -3
  334. package/src/templates/default/AGENTS.md +1 -0
  335. package/src/templates/default/DEVELOPING.md +2 -0
  336. package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +10 -3
  337. package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +98 -10
  338. package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +45 -3
  339. package/src/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +2 -0
  340. package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +37 -4
  341. package/src/templates/workspace-core/.agents/skills/automations/SKILL.md +9 -4
  342. package/src/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +2 -0
  343. package/src/templates/workspace-core/.agents/skills/client-methods/SKILL.md +106 -0
  344. package/src/templates/workspace-core/.agents/skills/client-methods/references/legacy-client-fetch-audit-2026-06-03.md +53 -0
  345. package/src/templates/workspace-core/.agents/skills/client-side-routing/SKILL.md +2 -0
  346. package/src/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +62 -61
  347. package/src/templates/workspace-core/.agents/skills/context-xray/SKILL.md +47 -0
  348. package/src/templates/workspace-core/.agents/skills/create-skill/SKILL.md +28 -0
  349. package/src/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +52 -1
  350. package/src/templates/workspace-core/.agents/skills/extension-points/SKILL.md +2 -0
  351. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +95 -433
  352. package/src/templates/workspace-core/.agents/skills/extensions/references/api.md +285 -0
  353. package/src/templates/workspace-core/.agents/skills/extensions/references/examples.md +259 -0
  354. package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +398 -0
  355. package/src/templates/workspace-core/.agents/skills/external-agents/references/mcp-apps-embedding.md +157 -0
  356. package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +17 -0
  357. package/src/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +13 -2
  358. package/src/templates/workspace-core/.agents/skills/mvp-followup/SKILL.md +51 -0
  359. package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +14 -4
  360. package/src/templates/workspace-core/.agents/skills/onboarding/SKILL.md +13 -1
  361. package/src/templates/workspace-core/.agents/skills/portability/SKILL.md +27 -5
  362. package/src/templates/workspace-core/.agents/skills/qa/SKILL.md +24 -8
  363. package/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +53 -7
  364. package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +43 -10
  365. package/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +2 -0
  366. package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +43 -14
  367. package/src/templates/workspace-core/.agents/skills/security/SKILL.md +50 -1
  368. package/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +4 -2
  369. package/src/templates/workspace-core/.agents/skills/server-plugins/SKILL.md +11 -1
  370. package/src/templates/workspace-core/.agents/skills/shadcn-ui/SKILL.md +15 -0
  371. package/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +5 -1
  372. package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +48 -19
  373. package/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +7 -3
  374. package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +13 -6
  375. package/src/templates/workspace-core/.agents/skills/writing-agent-instructions/SKILL.md +236 -0
  376. package/src/templates/workspace-core/AGENTS.md +5 -1
  377. package/src/templates/workspace-root/AGENTS.md +5 -2
@@ -0,0 +1,165 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
3
+ import { IconCode, IconPlus, IconX } from "@tabler/icons-react";
4
+ import { cn } from "../../utils.js";
5
+ import { defineBlock } from "../types.js";
6
+ import { codeTabsSchema, codeTabsMdx, } from "./code-tabs.config.js";
7
+ /**
8
+ * Standard `code-tabs` block (STANDARD core library): a vertical file tab rail
9
+ * with Shiki-highlighted code panes. Moved verbatim from the plan
10
+ * `CodeTabsBlock` (`DocumentArea.tsx`) so its rendered output is unchanged, then
11
+ * generalized to the registry `Read`/`Edit` contract. Shareable by any app that
12
+ * registers the core block library.
13
+ *
14
+ * `Edit` is schema-driven in spirit: each tab's `code` field renders as a
15
+ * code-style monospace text area (the plain auto-editor can't descend into the
16
+ * `tabs` array), plus label/language/caption inputs. The component owns no app
17
+ * services, so it stays portable across apps.
18
+ */
19
+ /* ── Read (vertical tab rail + Shiki) ──────────────────────────────────────── */
20
+ function CodeTabsRead({ data, blockId, title }) {
21
+ const [activeId, setActiveId] = useState(data.tabs[0]?.id ?? "");
22
+ const active = data.tabs.find((tab) => tab.id === activeId) ?? data.tabs[0];
23
+ return (_jsxs("section", { className: "plan-block", "data-block-id": blockId, children: [title && _jsx("h2", { children: title }), _jsxs("div", { className: "grid overflow-hidden border-y border-plan-line md:grid-cols-[300px_minmax(0,1fr)]", children: [_jsx("div", { className: "border-plan-line md:border-r", children: data.tabs.map((tab) => (_jsxs("button", { type: "button", "data-plan-interactive": true, className: cn("flex w-full items-start gap-3 border-b border-plan-line px-4 py-4 text-left", tab.id === active?.id
24
+ ? "bg-plan-block text-plan-text shadow-[inset_3px_0_0_hsl(var(--ring))]"
25
+ : "text-plan-muted hover:bg-accent/30"), onClick: () => setActiveId(tab.id), children: [_jsx(IconCode, { className: "mt-0.5 size-4 shrink-0" }), _jsxs("span", { className: "min-w-0", children: [_jsx("span", { className: "block truncate font-mono text-sm font-semibold", children: tab.label }), tab.caption && (_jsx("span", { className: "mt-1 block text-xs leading-5", children: tab.caption }))] })] }, tab.id))) }), _jsx("div", { className: "min-w-0 p-5", children: active && (_jsxs(_Fragment, { children: [_jsx("h3", { className: "text-2xl font-semibold tracking-tight", children: active.label }), active.caption && (_jsx("p", { className: "mt-2 text-plan-muted", children: active.caption })), _jsx(CodeSurface, { code: active.code, language: active.language })] })) })] })] }));
26
+ }
27
+ function CodeSurface({ code, language, className, }) {
28
+ return (_jsx("div", { className: cn("plan-code-surface", className ?? "mt-5"), children: _jsx(HighlightedCode, { code: code, language: language }) }));
29
+ }
30
+ /* ── Edit (code text areas per tab) ────────────────────────────────────────── */
31
+ const inputClass = "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50";
32
+ const codeAreaClass = "flex min-h-[140px] w-full rounded-md border border-input bg-transparent px-3 py-2 font-mono text-xs leading-5 shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50";
33
+ /** Mint a reasonably-unique code-tab id without pulling a dep into core. */
34
+ function newCodeTabId() {
35
+ return `code-tab-${Math.random().toString(36).slice(2, 10)}`;
36
+ }
37
+ /**
38
+ * Editor: a file-tab strip (one tab active at a time) whose active tab exposes
39
+ * label/language/caption/code fields — mirroring the read renderer's tabbed
40
+ * layout and the standard `tabs` block editor instead of stacking every tab's
41
+ * full form vertically. Add/remove/rename keep the schema's 1..12 bounds.
42
+ */
43
+ function CodeTabsEdit({ data, onChange, editable, }) {
44
+ const [activeId, setActiveId] = useState(data.tabs[0]?.id ?? "");
45
+ const active = data.tabs.find((tab) => tab.id === activeId) ?? data.tabs[0];
46
+ const commit = (tabs) => onChange({ tabs });
47
+ const updateTab = (id, patch) => commit(data.tabs.map((tab) => (tab.id === id ? { ...tab, ...patch } : tab)));
48
+ const removeTab = (id) => {
49
+ const next = data.tabs.filter((tab) => tab.id !== id);
50
+ if (next.length === 0)
51
+ return; // tabs must keep at least one (schema min 1)
52
+ commit(next);
53
+ if (activeId === id)
54
+ setActiveId(next[0]?.id ?? "");
55
+ };
56
+ const addTab = () => {
57
+ if (data.tabs.length >= 12)
58
+ return; // schema max
59
+ const id = newCodeTabId();
60
+ commit([
61
+ ...data.tabs,
62
+ { id, label: `file-${data.tabs.length + 1}.ts`, code: "" },
63
+ ]);
64
+ setActiveId(id);
65
+ };
66
+ return (_jsxs("div", { className: "an-code-tabs-editor flex flex-col gap-4", children: [_jsxs("div", { className: "flex max-w-full flex-wrap items-center gap-1 overflow-x-auto", role: "tablist", "data-plan-interactive": true, children: [data.tabs.map((tab) => {
67
+ const selected = tab.id === active?.id;
68
+ return (_jsxs("div", { className: cn("group flex items-center gap-1 rounded-lg pr-1 transition-colors", selected ? "bg-plan-block shadow-sm" : "hover:bg-plan-block/60"), children: [_jsxs("button", { type: "button", role: "tab", "aria-selected": selected, onClick: () => setActiveId(tab.id), className: cn("flex items-center gap-2 rounded-lg px-3 py-2 font-mono text-sm font-semibold transition-colors", selected ? "text-plan-text" : "text-plan-muted"), children: [_jsx(IconCode, { className: "size-4 shrink-0" }), tab.label] }), editable && data.tabs.length > 1 && (_jsx("button", { type: "button", "data-plan-interactive": true, "aria-label": `Remove ${tab.label}`, className: cn("flex size-6 shrink-0 items-center justify-center rounded text-plan-muted transition-opacity", "opacity-0 group-hover:opacity-100 group-focus-within:opacity-100", "hover:bg-muted hover:text-foreground"), onClick: () => removeTab(tab.id), children: _jsx(IconX, { className: "size-3.5 shrink-0" }) }))] }, tab.id));
69
+ }), editable && data.tabs.length < 12 && (_jsxs("button", { type: "button", "data-plan-interactive": true, "aria-label": "Add tab", className: "flex items-center gap-1.5 rounded-md px-2 py-2 text-sm text-plan-muted hover:bg-plan-block/60 hover:text-plan-text", onClick: addTab, children: [_jsx(IconPlus, { className: "size-4" }), "Add tab"] }))] }), active && (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("div", { className: "grid gap-2 md:grid-cols-2", children: [_jsxs("label", { className: "flex flex-col gap-1.5", children: [_jsx("span", { className: "text-xs font-medium text-muted-foreground", children: "Label" }), _jsx("input", { type: "text", "data-plan-interactive": true, className: inputClass, value: active.label, disabled: !editable, onChange: (event) => updateTab(active.id, { label: event.target.value }) })] }), _jsxs("label", { className: "flex flex-col gap-1.5", children: [_jsx("span", { className: "text-xs font-medium text-muted-foreground", children: "Language" }), _jsx("input", { type: "text", "data-plan-interactive": true, className: inputClass, value: active.language ?? "", disabled: !editable, onChange: (event) => updateTab(active.id, {
70
+ language: event.target.value || undefined,
71
+ }) })] })] }), _jsxs("label", { className: "flex flex-col gap-1.5", children: [_jsx("span", { className: "text-xs font-medium text-muted-foreground", children: "Caption" }), _jsx("input", { type: "text", "data-plan-interactive": true, className: inputClass, value: active.caption ?? "", disabled: !editable, onChange: (event) => updateTab(active.id, {
72
+ caption: event.target.value || undefined,
73
+ }) })] }), _jsxs("label", { className: "flex flex-col gap-1.5", children: [_jsx("span", { className: "text-xs font-medium text-muted-foreground", children: "Code" }), _jsx("textarea", { "data-plan-interactive": true, spellCheck: false, className: codeAreaClass, value: active.code, disabled: !editable, onChange: (event) => updateTab(active.id, { code: event.target.value }) })] })] }))] }));
74
+ }
75
+ let highlighterLoader = null;
76
+ function loadHighlighter() {
77
+ if (!highlighterLoader) {
78
+ highlighterLoader = (async () => {
79
+ const [{ createHighlighterCore }, { createOnigurumaEngine }] = await Promise.all([
80
+ import("shiki/core"),
81
+ import("shiki/engine/oniguruma"),
82
+ ]);
83
+ return createHighlighterCore({
84
+ themes: [import("shiki/themes/github-dark-default.mjs")],
85
+ langs: [
86
+ import("shiki/langs/javascript.mjs"),
87
+ import("shiki/langs/typescript.mjs"),
88
+ import("shiki/langs/jsx.mjs"),
89
+ import("shiki/langs/tsx.mjs"),
90
+ import("shiki/langs/json.mjs"),
91
+ import("shiki/langs/css.mjs"),
92
+ import("shiki/langs/html.mjs"),
93
+ import("shiki/langs/markdown.mjs"),
94
+ import("shiki/langs/bash.mjs"),
95
+ import("shiki/langs/shellscript.mjs"),
96
+ import("shiki/langs/python.mjs"),
97
+ import("shiki/langs/yaml.mjs"),
98
+ import("shiki/langs/sql.mjs"),
99
+ ],
100
+ engine: createOnigurumaEngine(import("shiki/wasm")),
101
+ });
102
+ })().catch((error) => {
103
+ highlighterLoader = null;
104
+ throw error;
105
+ });
106
+ }
107
+ return highlighterLoader;
108
+ }
109
+ const LANG_ALIASES = {
110
+ js: "javascript",
111
+ ts: "typescript",
112
+ sh: "bash",
113
+ shell: "bash",
114
+ zsh: "bash",
115
+ py: "python",
116
+ yml: "yaml",
117
+ md: "markdown",
118
+ };
119
+ function HighlightedCode({ code, language, }) {
120
+ const [html, setHtml] = useState(null);
121
+ useEffect(() => {
122
+ let cancelled = false;
123
+ loadHighlighter()
124
+ .then((highlighter) => {
125
+ const requested = (language || "text").toLowerCase();
126
+ const resolved = LANG_ALIASES[requested] ?? requested;
127
+ const loaded = highlighter.getLoadedLanguages();
128
+ const lang = loaded.includes(resolved) ? resolved : "text";
129
+ return highlighter.codeToHtml(code, {
130
+ lang,
131
+ theme: "github-dark-default",
132
+ });
133
+ })
134
+ .then((out) => {
135
+ if (!cancelled)
136
+ setHtml(out);
137
+ })
138
+ .catch(() => {
139
+ if (!cancelled)
140
+ setHtml(null);
141
+ });
142
+ return () => {
143
+ cancelled = true;
144
+ };
145
+ }, [code, language]);
146
+ if (html) {
147
+ // Shiki output is generated from plain text by the highlighter itself —
148
+ // it is NOT agent-authored HTML, so this is safe (mirrors core chat).
149
+ return (_jsx("div", { className: "plan-shiki", dangerouslySetInnerHTML: { __html: html } }));
150
+ }
151
+ return (_jsx("pre", { children: _jsx("code", { className: language ? `language-${language}` : undefined, children: code }) }));
152
+ }
153
+ /* ── Spec ──────────────────────────────────────────────────────────────────── */
154
+ export const codeTabsBlock = defineBlock({
155
+ type: "code-tabs",
156
+ schema: codeTabsSchema,
157
+ mdx: codeTabsMdx,
158
+ Read: CodeTabsRead,
159
+ Edit: CodeTabsEdit,
160
+ placement: ["block"],
161
+ label: "Code tabs",
162
+ icon: IconCode,
163
+ description: "A vertical file tab rail of syntax-highlighted code snippets, one tab per file with an optional language and caption.",
164
+ });
165
+ //# sourceMappingURL=code-tabs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-tabs.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/code-tabs.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useState } from \"react\";\nimport { IconCode, IconPlus, IconX } from \"@tabler/icons-react\";\nimport { cn } from \"../../utils.js\";\nimport { defineBlock } from \"../types.js\";\nimport type { BlockReadProps, BlockEditProps } from \"../types.js\";\nimport {\n codeTabsSchema,\n codeTabsMdx,\n type CodeTabsData,\n type CodeTabsTab,\n} from \"./code-tabs.config.js\";\n\n/**\n * Standard `code-tabs` block (STANDARD core library): a vertical file tab rail\n * with Shiki-highlighted code panes. Moved verbatim from the plan\n * `CodeTabsBlock` (`DocumentArea.tsx`) so its rendered output is unchanged, then\n * generalized to the registry `Read`/`Edit` contract. Shareable by any app that\n * registers the core block library.\n *\n * `Edit` is schema-driven in spirit: each tab's `code` field renders as a\n * code-style monospace text area (the plain auto-editor can't descend into the\n * `tabs` array), plus label/language/caption inputs. The component owns no app\n * services, so it stays portable across apps.\n */\n\n/* ── Read (vertical tab rail + Shiki) ──────────────────────────────────────── */\n\nfunction CodeTabsRead({ data, blockId, title }: BlockReadProps<CodeTabsData>) {\n const [activeId, setActiveId] = useState(data.tabs[0]?.id ?? \"\");\n const active = data.tabs.find((tab) => tab.id === activeId) ?? data.tabs[0];\n return (\n <section className=\"plan-block\" data-block-id={blockId}>\n {title && <h2>{title}</h2>}\n <div className=\"grid overflow-hidden border-y border-plan-line md:grid-cols-[300px_minmax(0,1fr)]\">\n <div className=\"border-plan-line md:border-r\">\n {data.tabs.map((tab) => (\n <button\n key={tab.id}\n type=\"button\"\n data-plan-interactive\n className={cn(\n \"flex w-full items-start gap-3 border-b border-plan-line px-4 py-4 text-left\",\n tab.id === active?.id\n ? \"bg-plan-block text-plan-text shadow-[inset_3px_0_0_hsl(var(--ring))]\"\n : \"text-plan-muted hover:bg-accent/30\",\n )}\n onClick={() => setActiveId(tab.id)}\n >\n <IconCode className=\"mt-0.5 size-4 shrink-0\" />\n <span className=\"min-w-0\">\n <span className=\"block truncate font-mono text-sm font-semibold\">\n {tab.label}\n </span>\n {tab.caption && (\n <span className=\"mt-1 block text-xs leading-5\">\n {tab.caption}\n </span>\n )}\n </span>\n </button>\n ))}\n </div>\n <div className=\"min-w-0 p-5\">\n {active && (\n <>\n <h3 className=\"text-2xl font-semibold tracking-tight\">\n {active.label}\n </h3>\n {active.caption && (\n <p className=\"mt-2 text-plan-muted\">{active.caption}</p>\n )}\n <CodeSurface code={active.code} language={active.language} />\n </>\n )}\n </div>\n </div>\n </section>\n );\n}\n\nfunction CodeSurface({\n code,\n language,\n className,\n}: {\n code: string;\n language?: string;\n className?: string;\n}) {\n return (\n <div className={cn(\"plan-code-surface\", className ?? \"mt-5\")}>\n <HighlightedCode code={code} language={language} />\n </div>\n );\n}\n\n/* ── Edit (code text areas per tab) ────────────────────────────────────────── */\n\nconst inputClass =\n \"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\";\n\nconst codeAreaClass =\n \"flex min-h-[140px] w-full rounded-md border border-input bg-transparent px-3 py-2 font-mono text-xs leading-5 shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\";\n\n/** Mint a reasonably-unique code-tab id without pulling a dep into core. */\nfunction newCodeTabId(): string {\n return `code-tab-${Math.random().toString(36).slice(2, 10)}`;\n}\n\n/**\n * Editor: a file-tab strip (one tab active at a time) whose active tab exposes\n * label/language/caption/code fields — mirroring the read renderer's tabbed\n * layout and the standard `tabs` block editor instead of stacking every tab's\n * full form vertically. Add/remove/rename keep the schema's 1..12 bounds.\n */\nfunction CodeTabsEdit({\n data,\n onChange,\n editable,\n}: BlockEditProps<CodeTabsData>) {\n const [activeId, setActiveId] = useState(data.tabs[0]?.id ?? \"\");\n const active = data.tabs.find((tab) => tab.id === activeId) ?? data.tabs[0];\n\n const commit = (tabs: CodeTabsTab[]) => onChange({ tabs });\n\n const updateTab = (id: string, patch: Partial<CodeTabsTab>) =>\n commit(\n data.tabs.map((tab) => (tab.id === id ? { ...tab, ...patch } : tab)),\n );\n\n const removeTab = (id: string) => {\n const next = data.tabs.filter((tab) => tab.id !== id);\n if (next.length === 0) return; // tabs must keep at least one (schema min 1)\n commit(next);\n if (activeId === id) setActiveId(next[0]?.id ?? \"\");\n };\n\n const addTab = () => {\n if (data.tabs.length >= 12) return; // schema max\n const id = newCodeTabId();\n commit([\n ...data.tabs,\n { id, label: `file-${data.tabs.length + 1}.ts`, code: \"\" },\n ]);\n setActiveId(id);\n };\n\n return (\n <div className=\"an-code-tabs-editor flex flex-col gap-4\">\n <div\n className=\"flex max-w-full flex-wrap items-center gap-1 overflow-x-auto\"\n role=\"tablist\"\n data-plan-interactive\n >\n {data.tabs.map((tab) => {\n const selected = tab.id === active?.id;\n return (\n <div\n key={tab.id}\n className={cn(\n \"group flex items-center gap-1 rounded-lg pr-1 transition-colors\",\n selected ? \"bg-plan-block shadow-sm\" : \"hover:bg-plan-block/60\",\n )}\n >\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={selected}\n onClick={() => setActiveId(tab.id)}\n className={cn(\n \"flex items-center gap-2 rounded-lg px-3 py-2 font-mono text-sm font-semibold transition-colors\",\n selected ? \"text-plan-text\" : \"text-plan-muted\",\n )}\n >\n <IconCode className=\"size-4 shrink-0\" />\n {tab.label}\n </button>\n {editable && data.tabs.length > 1 && (\n <button\n type=\"button\"\n data-plan-interactive\n aria-label={`Remove ${tab.label}`}\n className={cn(\n \"flex size-6 shrink-0 items-center justify-center rounded text-plan-muted transition-opacity\",\n \"opacity-0 group-hover:opacity-100 group-focus-within:opacity-100\",\n \"hover:bg-muted hover:text-foreground\",\n )}\n onClick={() => removeTab(tab.id)}\n >\n <IconX className=\"size-3.5 shrink-0\" />\n </button>\n )}\n </div>\n );\n })}\n {editable && data.tabs.length < 12 && (\n <button\n type=\"button\"\n data-plan-interactive\n aria-label=\"Add tab\"\n className=\"flex items-center gap-1.5 rounded-md px-2 py-2 text-sm text-plan-muted hover:bg-plan-block/60 hover:text-plan-text\"\n onClick={addTab}\n >\n <IconPlus className=\"size-4\" />\n Add tab\n </button>\n )}\n </div>\n {active && (\n <div className=\"flex flex-col gap-2\">\n <div className=\"grid gap-2 md:grid-cols-2\">\n <label className=\"flex flex-col gap-1.5\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n Label\n </span>\n <input\n type=\"text\"\n data-plan-interactive\n className={inputClass}\n value={active.label}\n disabled={!editable}\n onChange={(event) =>\n updateTab(active.id, { label: event.target.value })\n }\n />\n </label>\n <label className=\"flex flex-col gap-1.5\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n Language\n </span>\n <input\n type=\"text\"\n data-plan-interactive\n className={inputClass}\n value={active.language ?? \"\"}\n disabled={!editable}\n onChange={(event) =>\n updateTab(active.id, {\n language: event.target.value || undefined,\n })\n }\n />\n </label>\n </div>\n <label className=\"flex flex-col gap-1.5\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n Caption\n </span>\n <input\n type=\"text\"\n data-plan-interactive\n className={inputClass}\n value={active.caption ?? \"\"}\n disabled={!editable}\n onChange={(event) =>\n updateTab(active.id, {\n caption: event.target.value || undefined,\n })\n }\n />\n </label>\n <label className=\"flex flex-col gap-1.5\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n Code\n </span>\n <textarea\n data-plan-interactive\n spellCheck={false}\n className={codeAreaClass}\n value={active.code}\n disabled={!editable}\n onChange={(event) =>\n updateTab(active.id, { code: event.target.value })\n }\n />\n </label>\n </div>\n )}\n </div>\n );\n}\n\n/* ── Shiki syntax highlighting (lazy-loaded, single dark theme) ────────────── */\ntype ShikiHighlighter = {\n codeToHtml: (\n code: string,\n options: { lang: string; theme: string },\n ) => string | Promise<string>;\n getLoadedLanguages: () => string[];\n};\n\nlet highlighterLoader: Promise<ShikiHighlighter> | null = null;\nfunction loadHighlighter(): Promise<ShikiHighlighter> {\n if (!highlighterLoader) {\n highlighterLoader = (async () => {\n const [{ createHighlighterCore }, { createOnigurumaEngine }] =\n await Promise.all([\n import(\"shiki/core\"),\n import(\"shiki/engine/oniguruma\"),\n ]);\n return createHighlighterCore({\n themes: [import(\"shiki/themes/github-dark-default.mjs\")],\n langs: [\n import(\"shiki/langs/javascript.mjs\"),\n import(\"shiki/langs/typescript.mjs\"),\n import(\"shiki/langs/jsx.mjs\"),\n import(\"shiki/langs/tsx.mjs\"),\n import(\"shiki/langs/json.mjs\"),\n import(\"shiki/langs/css.mjs\"),\n import(\"shiki/langs/html.mjs\"),\n import(\"shiki/langs/markdown.mjs\"),\n import(\"shiki/langs/bash.mjs\"),\n import(\"shiki/langs/shellscript.mjs\"),\n import(\"shiki/langs/python.mjs\"),\n import(\"shiki/langs/yaml.mjs\"),\n import(\"shiki/langs/sql.mjs\"),\n ],\n engine: createOnigurumaEngine(import(\"shiki/wasm\")),\n }) as unknown as Promise<ShikiHighlighter>;\n })().catch((error) => {\n highlighterLoader = null;\n throw error;\n });\n }\n return highlighterLoader;\n}\n\nconst LANG_ALIASES: Record<string, string> = {\n js: \"javascript\",\n ts: \"typescript\",\n sh: \"bash\",\n shell: \"bash\",\n zsh: \"bash\",\n py: \"python\",\n yml: \"yaml\",\n md: \"markdown\",\n};\n\nfunction HighlightedCode({\n code,\n language,\n}: {\n code: string;\n language?: string;\n}) {\n const [html, setHtml] = useState<string | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n loadHighlighter()\n .then((highlighter) => {\n const requested = (language || \"text\").toLowerCase();\n const resolved = LANG_ALIASES[requested] ?? requested;\n const loaded = highlighter.getLoadedLanguages();\n const lang = loaded.includes(resolved) ? resolved : \"text\";\n return highlighter.codeToHtml(code, {\n lang,\n theme: \"github-dark-default\",\n });\n })\n .then((out) => {\n if (!cancelled) setHtml(out as string);\n })\n .catch(() => {\n if (!cancelled) setHtml(null);\n });\n return () => {\n cancelled = true;\n };\n }, [code, language]);\n\n if (html) {\n // Shiki output is generated from plain text by the highlighter itself —\n // it is NOT agent-authored HTML, so this is safe (mirrors core chat).\n return (\n <div className=\"plan-shiki\" dangerouslySetInnerHTML={{ __html: html }} />\n );\n }\n return (\n <pre>\n <code className={language ? `language-${language}` : undefined}>\n {code}\n </code>\n </pre>\n );\n}\n\n/* ── Spec ──────────────────────────────────────────────────────────────────── */\n\nexport const codeTabsBlock = defineBlock<CodeTabsData>({\n type: \"code-tabs\",\n schema: codeTabsSchema,\n mdx: codeTabsMdx,\n Read: CodeTabsRead,\n Edit: CodeTabsEdit,\n placement: [\"block\"],\n label: \"Code tabs\",\n icon: IconCode,\n description:\n \"A vertical file tab rail of syntax-highlighted code snippets, one tab per file with an optional language and caption.\",\n});\n"]}
@@ -0,0 +1,37 @@
1
+ import { z } from "zod";
2
+ import type { BlockMdxConfig } from "../types.js";
3
+ /**
4
+ * Pure (React-free) part of the standard HTML / Tailwind block: its data schema
5
+ * and MDX round-trip config. Shared by the React spec (`html.tsx`) and any
6
+ * server-side / agent registry (e.g. the plan app's `plan-block-registry.ts`),
7
+ * so importing it into a server module never pulls React in.
8
+ *
9
+ * This is the registry form of the plan `custom-html` block. The schema MUST
10
+ * stay data-compatible with the `custom-html` branch of the plan
11
+ * `planBlockSchema` (bounded `html`, optional bounded `css`, optional trimmed
12
+ * `caption`, all rejecting full-document / script markup) so a registered block
13
+ * still validates through the app's generic `update-block` re-validation. The
14
+ * MDX `tag` (`HtmlBlock`) + flat `html`/`css`/`caption` attribute shape MUST
15
+ * match the legacy `<HtmlBlock … html css caption />` encoding
16
+ * (`plan-mdx.ts` `serializeBlock`/`parseBlock`) so stored `.mdx` round-trips
17
+ * byte-compatibly.
18
+ */
19
+ export interface HtmlBlockData {
20
+ /** Bounded HTML fragment (no html/head/body/script/style document markup). */
21
+ html: string;
22
+ /** Optional bounded CSS, scoped into the sandboxed iframe. */
23
+ css?: string;
24
+ /** Optional short caption rendered under the rendered fragment. */
25
+ caption?: string;
26
+ }
27
+ export declare const htmlSchema: z.ZodType<HtmlBlockData>;
28
+ /**
29
+ * MDX config: `html`, `css`, and `caption` are flat attributes (no children) —
30
+ * exactly the legacy `<HtmlBlock id … html css caption />` self-closing form.
31
+ * Insertion order of `toAttrs` is the on-disk attribute order, so it stays
32
+ * `html` → `css` → `caption` to match `plan-mdx.ts:serializeBlock`. `fromAttrs`
33
+ * mirrors the legacy parse defaults (`html ?? ""`, `css`/`caption` undefined
34
+ * when absent).
35
+ */
36
+ export declare const htmlMdx: BlockMdxConfig<HtmlBlockData>;
37
+ //# sourceMappingURL=html.config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.config.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/html.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,aAAa;IAC5B,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAaD,eAAO,MAAM,UAAU,EAeG,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;AAEnD;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,EAAE,cAAc,CAAC,aAAa,CAYjD,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Rejects full HTML documents, executable/structural tags, and JS/data URLs.
4
+ * Kept byte-identical to the plan `noFullHtmlDocument` refine so the registry
5
+ * schema accepts exactly what `planBlockSchema` accepts (and nothing it would
6
+ * reject). Defense in depth — the block also renders inside a sandboxed iframe.
7
+ */
8
+ const unsafeHtmlPattern = /(?:<!doctype|<\/?(?:html|head|body|script|style|iframe|object|embed|link|meta|base|form)[\s>/]|\b(?:javascript|data:text\/html)\s*:|\bsrcdoc\s*=|\bon[a-z][\w:-]*\s*=)/i;
9
+ const noFullHtmlDocument = (value) => !unsafeHtmlPattern.test(value);
10
+ export const htmlSchema = z
11
+ .object({
12
+ html: z.string().max(100_000).refine(noFullHtmlDocument, {
13
+ message: "Custom HTML blocks must be bounded fragments without html/head/body/script/style tags.",
14
+ }),
15
+ css: z
16
+ .string()
17
+ .max(50_000)
18
+ .refine(noFullHtmlDocument, {
19
+ message: "Custom CSS blocks must not include document or script tags.",
20
+ })
21
+ .optional(),
22
+ caption: z.string().trim().max(400).optional(),
23
+ })
24
+ .strict();
25
+ /**
26
+ * MDX config: `html`, `css`, and `caption` are flat attributes (no children) —
27
+ * exactly the legacy `<HtmlBlock id … html css caption />` self-closing form.
28
+ * Insertion order of `toAttrs` is the on-disk attribute order, so it stays
29
+ * `html` → `css` → `caption` to match `plan-mdx.ts:serializeBlock`. `fromAttrs`
30
+ * mirrors the legacy parse defaults (`html ?? ""`, `css`/`caption` undefined
31
+ * when absent).
32
+ */
33
+ export const htmlMdx = {
34
+ tag: "HtmlBlock",
35
+ toAttrs: (data) => ({
36
+ html: data.html,
37
+ css: data.css,
38
+ caption: data.caption,
39
+ }),
40
+ fromAttrs: (attrs) => ({
41
+ html: attrs.string("html") ?? "",
42
+ css: attrs.string("css"),
43
+ caption: attrs.string("caption"),
44
+ }),
45
+ };
46
+ //# sourceMappingURL=html.config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.config.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/html.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA6BxB;;;;;GAKG;AACH,MAAM,iBAAiB,GACrB,yKAAyK,CAAC;AAE5K,MAAM,kBAAkB,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAE7E,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC;KACxB,MAAM,CAAC;IACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,kBAAkB,EAAE;QACvD,OAAO,EACL,wFAAwF;KAC3F,CAAC;IACF,GAAG,EAAE,CAAC;SACH,MAAM,EAAE;SACR,GAAG,CAAC,MAAM,CAAC;SACX,MAAM,CAAC,kBAAkB,EAAE;QAC1B,OAAO,EAAE,6DAA6D;KACvE,CAAC;SACD,QAAQ,EAAE;IACb,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;CAC/C,CAAC;KACD,MAAM,EAAyC,CAAC;AAEnD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,OAAO,GAAkC;IACpD,GAAG,EAAE,WAAW;IAChB,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAClB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,OAAO,EAAE,IAAI,CAAC,OAAO;KACtB,CAAC;IACF,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACrB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;QAChC,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC;QACxB,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC;KACjC,CAAC;CACH,CAAC","sourcesContent":["import { z } from \"zod\";\nimport type { BlockMdxConfig } from \"../types.js\";\n\n/**\n * Pure (React-free) part of the standard HTML / Tailwind block: its data schema\n * and MDX round-trip config. Shared by the React spec (`html.tsx`) and any\n * server-side / agent registry (e.g. the plan app's `plan-block-registry.ts`),\n * so importing it into a server module never pulls React in.\n *\n * This is the registry form of the plan `custom-html` block. The schema MUST\n * stay data-compatible with the `custom-html` branch of the plan\n * `planBlockSchema` (bounded `html`, optional bounded `css`, optional trimmed\n * `caption`, all rejecting full-document / script markup) so a registered block\n * still validates through the app's generic `update-block` re-validation. The\n * MDX `tag` (`HtmlBlock`) + flat `html`/`css`/`caption` attribute shape MUST\n * match the legacy `<HtmlBlock … html css caption />` encoding\n * (`plan-mdx.ts` `serializeBlock`/`parseBlock`) so stored `.mdx` round-trips\n * byte-compatibly.\n */\n\nexport interface HtmlBlockData {\n /** Bounded HTML fragment (no html/head/body/script/style document markup). */\n html: string;\n /** Optional bounded CSS, scoped into the sandboxed iframe. */\n css?: string;\n /** Optional short caption rendered under the rendered fragment. */\n caption?: string;\n}\n\n/**\n * Rejects full HTML documents, executable/structural tags, and JS/data URLs.\n * Kept byte-identical to the plan `noFullHtmlDocument` refine so the registry\n * schema accepts exactly what `planBlockSchema` accepts (and nothing it would\n * reject). Defense in depth — the block also renders inside a sandboxed iframe.\n */\nconst unsafeHtmlPattern =\n /(?:<!doctype|<\\/?(?:html|head|body|script|style|iframe|object|embed|link|meta|base|form)[\\s>/]|\\b(?:javascript|data:text\\/html)\\s*:|\\bsrcdoc\\s*=|\\bon[a-z][\\w:-]*\\s*=)/i;\n\nconst noFullHtmlDocument = (value: string) => !unsafeHtmlPattern.test(value);\n\nexport const htmlSchema = z\n .object({\n html: z.string().max(100_000).refine(noFullHtmlDocument, {\n message:\n \"Custom HTML blocks must be bounded fragments without html/head/body/script/style tags.\",\n }),\n css: z\n .string()\n .max(50_000)\n .refine(noFullHtmlDocument, {\n message: \"Custom CSS blocks must not include document or script tags.\",\n })\n .optional(),\n caption: z.string().trim().max(400).optional(),\n })\n .strict() as unknown as z.ZodType<HtmlBlockData>;\n\n/**\n * MDX config: `html`, `css`, and `caption` are flat attributes (no children) —\n * exactly the legacy `<HtmlBlock id … html css caption />` self-closing form.\n * Insertion order of `toAttrs` is the on-disk attribute order, so it stays\n * `html` → `css` → `caption` to match `plan-mdx.ts:serializeBlock`. `fromAttrs`\n * mirrors the legacy parse defaults (`html ?? \"\"`, `css`/`caption` undefined\n * when absent).\n */\nexport const htmlMdx: BlockMdxConfig<HtmlBlockData> = {\n tag: \"HtmlBlock\",\n toAttrs: (data) => ({\n html: data.html,\n css: data.css,\n caption: data.caption,\n }),\n fromAttrs: (attrs) => ({\n html: attrs.string(\"html\") ?? \"\",\n css: attrs.string(\"css\"),\n caption: attrs.string(\"caption\"),\n }),\n};\n"]}
@@ -0,0 +1,21 @@
1
+ import type { BlockReadProps, BlockEditProps } from "../types.js";
2
+ import { type HtmlBlockData } from "./html.config.js";
3
+ /** Read-only renderer: the sandboxed iframe preview plus an optional caption. */
4
+ export declare function HtmlReadBlock({ data, blockId, title, ctx, }: BlockReadProps<HtmlBlockData>): import("react/jsx-runtime").JSX.Element;
5
+ /**
6
+ * Custom editor: an "Edit source" toggle that flips between the live preview and
7
+ * inline HTML + CSS textareas (ported from the plan `CustomHtmlBlock`). The
8
+ * title is rendered by the registry's edit-mode section wrapper, so this only
9
+ * renders the toggle + content. Edits commit the merged data via `onChange`,
10
+ * which the app routes through its generic `update-block` patch (re-validated by
11
+ * the app schema).
12
+ */
13
+ export declare function HtmlEditBlock({ data, onChange, editable, title, ctx, }: BlockEditProps<HtmlBlockData>): import("react/jsx-runtime").JSX.Element;
14
+ /**
15
+ * The standard HTML / Tailwind block spec. Both apps register this; the plan app
16
+ * registers the matching React-free `{ schema, mdx }` server-side via
17
+ * `html.config.ts`. `empty()` seeds a friendly starter fragment for slash
18
+ * insertion.
19
+ */
20
+ export declare const htmlBlock: import("../types.js").BlockSpec<HtmlBlockData>;
21
+ //# sourceMappingURL=html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/html.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAqD3E,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,OAAO,EACP,KAAK,EACL,GAAG,GACJ,EAAE,cAAc,CAAC,aAAa,CAAC,2CAO/B;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,KAAK,EACL,GAAG,GACJ,EAAE,cAAc,CAAC,aAAa,CAAC,2CAiE/B;AAED;;;;;GAKG;AACH,eAAO,MAAM,SAAS,gDAYpB,CAAC"}
@@ -0,0 +1,69 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { IconCode, IconEdit, IconX } from "@tabler/icons-react";
4
+ import { defineBlock } from "../types.js";
5
+ import { htmlSchema, htmlMdx } from "./html.config.js";
6
+ /**
7
+ * Standard library HTML / Tailwind block. The registry form of the plan
8
+ * `custom-html` block: an author-supplied HTML (+ optional CSS) fragment
9
+ * rendered inside a sandboxed iframe, with an inline source editor.
10
+ *
11
+ * Security: the fragment is rendered in a `sandbox="allow-same-origin"` iframe
12
+ * with `referrerPolicy="no-referrer"` — no scripts execute — and the schema's
13
+ * `noFullHtmlDocument` refine rejects document/script/handler markup before it
14
+ * is ever stored. When the app injects `ctx.sanitizeHtml`, the fragment + CSS
15
+ * are additionally sanitized before being placed in the iframe `srcDoc`.
16
+ *
17
+ * Styling uses app-agnostic shadcn utility classes (`border`, `bg-muted`,
18
+ * `text-muted-foreground`) so the block renders cleanly in any template, not
19
+ * just the plan app.
20
+ */
21
+ /** Build the iframe document for a fragment, applying app sanitization if given. */
22
+ function buildSrcDoc(data, sanitize) {
23
+ const css = data.css ?? "";
24
+ const body = sanitize ? sanitize(data.html, data.css) : data.html;
25
+ return `<!doctype html><html><head><style>body{margin:0;min-height:100%;font-family:Inter,system-ui,sans-serif;color:#1f1f1d;background:transparent;}*{box-sizing:border-box}${css}</style></head><body>${body}</body></html>`;
26
+ }
27
+ function HtmlPreview({ data, title, sanitize, }) {
28
+ return (_jsxs(_Fragment, { children: [_jsx("iframe", { title: title || "Custom HTML block", srcDoc: buildSrcDoc(data, sanitize), sandbox: "allow-same-origin", referrerPolicy: "no-referrer", className: "mt-4 h-[360px] w-full rounded-xl border bg-muted" }), data.caption && (_jsx("p", { className: "mt-3 text-sm text-muted-foreground", children: data.caption }))] }));
29
+ }
30
+ /** Read-only renderer: the sandboxed iframe preview plus an optional caption. */
31
+ export function HtmlReadBlock({ data, blockId, title, ctx, }) {
32
+ return (_jsxs("section", { className: "plan-block group", "data-block-id": blockId, children: [title && _jsx("h2", { children: title }), _jsx(HtmlPreview, { data: data, title: title, sanitize: ctx.sanitizeHtml })] }));
33
+ }
34
+ /**
35
+ * Custom editor: an "Edit source" toggle that flips between the live preview and
36
+ * inline HTML + CSS textareas (ported from the plan `CustomHtmlBlock`). The
37
+ * title is rendered by the registry's edit-mode section wrapper, so this only
38
+ * renders the toggle + content. Edits commit the merged data via `onChange`,
39
+ * which the app routes through its generic `update-block` patch (re-validated by
40
+ * the app schema).
41
+ */
42
+ export function HtmlEditBlock({ data, onChange, editable, title, ctx, }) {
43
+ const [editing, setEditing] = useState(false);
44
+ const [html, setHtml] = useState(data.html);
45
+ const [css, setCss] = useState(data.css ?? "");
46
+ return (_jsxs("div", { className: "plan-html-block group", "data-an-block-edit": true, children: [_jsx("div", { className: "flex items-start justify-end gap-4", children: editable && (_jsxs("button", { type: "button", "data-plan-interactive": true, className: "inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-sm font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground", onClick: () => setEditing((value) => !value), children: [editing ? (_jsx(IconX, { className: "size-4" })) : (_jsx(IconEdit, { className: "size-4" })), editing ? "Cancel" : "Edit source"] })) }), editing ? (_jsxs("div", { className: "mt-2 grid gap-3", "data-plan-interactive": true, children: [_jsx("textarea", { value: html, onChange: (event) => setHtml(event.target.value), className: "flex min-h-48 w-full rounded-md border border-input bg-transparent px-3 py-2 font-mono text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", placeholder: "HTML fragment" }), _jsx("textarea", { value: css, onChange: (event) => setCss(event.target.value), className: "flex min-h-32 w-full rounded-md border border-input bg-transparent px-3 py-2 font-mono text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", placeholder: "Optional CSS" }), _jsxs("div", { className: "flex justify-end gap-2", children: [_jsx("button", { type: "button", "data-plan-interactive": true, className: "inline-flex h-9 items-center rounded-md px-4 text-sm font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground", onClick: () => setEditing(false), children: "Cancel" }), _jsx("button", { type: "button", "data-plan-interactive": true, className: "inline-flex h-9 items-center rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground shadow transition-colors hover:bg-primary/90", onClick: () => {
47
+ onChange({ ...data, html, css: css || undefined });
48
+ setEditing(false);
49
+ }, children: "Save" })] })] })) : (_jsx(HtmlPreview, { data: data, title: title, sanitize: ctx.sanitizeHtml }))] }));
50
+ }
51
+ /**
52
+ * The standard HTML / Tailwind block spec. Both apps register this; the plan app
53
+ * registers the matching React-free `{ schema, mdx }` server-side via
54
+ * `html.config.ts`. `empty()` seeds a friendly starter fragment for slash
55
+ * insertion.
56
+ */
57
+ export const htmlBlock = defineBlock({
58
+ type: "custom-html",
59
+ schema: htmlSchema,
60
+ mdx: htmlMdx,
61
+ Read: HtmlReadBlock,
62
+ Edit: HtmlEditBlock,
63
+ placement: ["block"],
64
+ label: "HTML / Tailwind",
65
+ icon: IconCode,
66
+ description: "An author-supplied HTML (with optional CSS) fragment rendered in a sandboxed iframe, with inline source editing.",
67
+ empty: () => ({ html: '<div class="p-6">Edit this HTML fragment…</div>' }),
68
+ });
69
+ //# sourceMappingURL=html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/html.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,UAAU,EAAE,OAAO,EAAsB,MAAM,kBAAkB,CAAC;AAE3E;;;;;;;;;;;;;;GAcG;AAEH,oFAAoF;AACpF,SAAS,WAAW,CAClB,IAAmB,EACnB,QAAiD;IAEjD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;IAClE,OAAO,wKAAwK,GAAG,wBAAwB,IAAI,gBAAgB,CAAC;AACjO,CAAC;AAED,SAAS,WAAW,CAAC,EACnB,IAAI,EACJ,KAAK,EACL,QAAQ,GAKT;IACC,OAAO,CACL,8BACE,iBACE,KAAK,EAAE,KAAK,IAAI,mBAAmB,EACnC,MAAM,EAAE,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC,EACnC,OAAO,EAAC,mBAAmB,EAC3B,cAAc,EAAC,aAAa,EAC5B,SAAS,EAAC,kDAAkD,GAC5D,EACD,IAAI,CAAC,OAAO,IAAI,CACf,YAAG,SAAS,EAAC,oCAAoC,YAAE,IAAI,CAAC,OAAO,GAAK,CACrE,IACA,CACJ,CAAC;AACJ,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,aAAa,CAAC,EAC5B,IAAI,EACJ,OAAO,EACP,KAAK,EACL,GAAG,GAC2B;IAC9B,OAAO,CACL,mBAAS,SAAS,EAAC,kBAAkB,mBAAgB,OAAO,aACzD,KAAK,IAAI,uBAAK,KAAK,GAAM,EAC1B,KAAC,WAAW,IAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,YAAY,GAAI,IAC7D,CACX,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,EAC5B,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,KAAK,EACL,GAAG,GAC2B;IAC9B,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;IAE/C,OAAO,CACL,eAAK,SAAS,EAAC,uBAAuB,yCACpC,cAAK,SAAS,EAAC,oCAAoC,YAChD,QAAQ,IAAI,CACX,kBACE,IAAI,EAAC,QAAQ,iCAEb,SAAS,EAAC,yJAAyJ,EACnK,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,aAE3C,OAAO,CAAC,CAAC,CAAC,CACT,KAAC,KAAK,IAAC,SAAS,EAAC,QAAQ,GAAG,CAC7B,CAAC,CAAC,CAAC,CACF,KAAC,QAAQ,IAAC,SAAS,EAAC,QAAQ,GAAG,CAChC,EACA,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,IAC5B,CACV,GACG,EACL,OAAO,CAAC,CAAC,CAAC,CACT,eAAK,SAAS,EAAC,iBAAiB,4CAC9B,mBACE,KAAK,EAAE,IAAI,EACX,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAChD,SAAS,EAAC,oNAAoN,EAC9N,WAAW,EAAC,eAAe,GAC3B,EACF,mBACE,KAAK,EAAE,GAAG,EACV,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAC/C,SAAS,EAAC,oNAAoN,EAC9N,WAAW,EAAC,cAAc,GAC1B,EACF,eAAK,SAAS,EAAC,wBAAwB,aACrC,iBACE,IAAI,EAAC,QAAQ,iCAEb,SAAS,EAAC,+IAA+I,EACzJ,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,uBAGzB,EACT,iBACE,IAAI,EAAC,QAAQ,iCAEb,SAAS,EAAC,kJAAkJ,EAC5J,OAAO,EAAE,GAAG,EAAE;oCACZ,QAAQ,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,SAAS,EAAE,CAAC,CAAC;oCACnD,UAAU,CAAC,KAAK,CAAC,CAAC;gCACpB,CAAC,qBAGM,IACL,IACF,CACP,CAAC,CAAC,CAAC,CACF,KAAC,WAAW,IAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,YAAY,GAAI,CACtE,IACG,CACP,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,WAAW,CAAgB;IAClD,IAAI,EAAE,aAAa;IACnB,MAAM,EAAE,UAAU;IAClB,GAAG,EAAE,OAAO;IACZ,IAAI,EAAE,aAAa;IACnB,IAAI,EAAE,aAAa;IACnB,SAAS,EAAE,CAAC,OAAO,CAAC;IACpB,KAAK,EAAE,iBAAiB;IACxB,IAAI,EAAE,QAAQ;IACd,WAAW,EACT,kHAAkH;IACpH,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,iDAAiD,EAAE,CAAC;CAC3E,CAAC,CAAC","sourcesContent":["import { useState } from \"react\";\nimport { IconCode, IconEdit, IconX } from \"@tabler/icons-react\";\nimport { defineBlock } from \"../types.js\";\nimport type { BlockReadProps, BlockEditProps } from \"../types.js\";\nimport { htmlSchema, htmlMdx, type HtmlBlockData } from \"./html.config.js\";\n\n/**\n * Standard library HTML / Tailwind block. The registry form of the plan\n * `custom-html` block: an author-supplied HTML (+ optional CSS) fragment\n * rendered inside a sandboxed iframe, with an inline source editor.\n *\n * Security: the fragment is rendered in a `sandbox=\"allow-same-origin\"` iframe\n * with `referrerPolicy=\"no-referrer\"` — no scripts execute — and the schema's\n * `noFullHtmlDocument` refine rejects document/script/handler markup before it\n * is ever stored. When the app injects `ctx.sanitizeHtml`, the fragment + CSS\n * are additionally sanitized before being placed in the iframe `srcDoc`.\n *\n * Styling uses app-agnostic shadcn utility classes (`border`, `bg-muted`,\n * `text-muted-foreground`) so the block renders cleanly in any template, not\n * just the plan app.\n */\n\n/** Build the iframe document for a fragment, applying app sanitization if given. */\nfunction buildSrcDoc(\n data: HtmlBlockData,\n sanitize?: (html: string, css?: string) => string,\n): string {\n const css = data.css ?? \"\";\n const body = sanitize ? sanitize(data.html, data.css) : data.html;\n return `<!doctype html><html><head><style>body{margin:0;min-height:100%;font-family:Inter,system-ui,sans-serif;color:#1f1f1d;background:transparent;}*{box-sizing:border-box}${css}</style></head><body>${body}</body></html>`;\n}\n\nfunction HtmlPreview({\n data,\n title,\n sanitize,\n}: {\n data: HtmlBlockData;\n title?: string;\n sanitize?: (html: string, css?: string) => string;\n}) {\n return (\n <>\n <iframe\n title={title || \"Custom HTML block\"}\n srcDoc={buildSrcDoc(data, sanitize)}\n sandbox=\"allow-same-origin\"\n referrerPolicy=\"no-referrer\"\n className=\"mt-4 h-[360px] w-full rounded-xl border bg-muted\"\n />\n {data.caption && (\n <p className=\"mt-3 text-sm text-muted-foreground\">{data.caption}</p>\n )}\n </>\n );\n}\n\n/** Read-only renderer: the sandboxed iframe preview plus an optional caption. */\nexport function HtmlReadBlock({\n data,\n blockId,\n title,\n ctx,\n}: BlockReadProps<HtmlBlockData>) {\n return (\n <section className=\"plan-block group\" data-block-id={blockId}>\n {title && <h2>{title}</h2>}\n <HtmlPreview data={data} title={title} sanitize={ctx.sanitizeHtml} />\n </section>\n );\n}\n\n/**\n * Custom editor: an \"Edit source\" toggle that flips between the live preview and\n * inline HTML + CSS textareas (ported from the plan `CustomHtmlBlock`). The\n * title is rendered by the registry's edit-mode section wrapper, so this only\n * renders the toggle + content. Edits commit the merged data via `onChange`,\n * which the app routes through its generic `update-block` patch (re-validated by\n * the app schema).\n */\nexport function HtmlEditBlock({\n data,\n onChange,\n editable,\n title,\n ctx,\n}: BlockEditProps<HtmlBlockData>) {\n const [editing, setEditing] = useState(false);\n const [html, setHtml] = useState(data.html);\n const [css, setCss] = useState(data.css ?? \"\");\n\n return (\n <div className=\"plan-html-block group\" data-an-block-edit>\n <div className=\"flex items-start justify-end gap-4\">\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n className=\"inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-sm font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\"\n onClick={() => setEditing((value) => !value)}\n >\n {editing ? (\n <IconX className=\"size-4\" />\n ) : (\n <IconEdit className=\"size-4\" />\n )}\n {editing ? \"Cancel\" : \"Edit source\"}\n </button>\n )}\n </div>\n {editing ? (\n <div className=\"mt-2 grid gap-3\" data-plan-interactive>\n <textarea\n value={html}\n onChange={(event) => setHtml(event.target.value)}\n className=\"flex min-h-48 w-full rounded-md border border-input bg-transparent px-3 py-2 font-mono text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n placeholder=\"HTML fragment\"\n />\n <textarea\n value={css}\n onChange={(event) => setCss(event.target.value)}\n className=\"flex min-h-32 w-full rounded-md border border-input bg-transparent px-3 py-2 font-mono text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring\"\n placeholder=\"Optional CSS\"\n />\n <div className=\"flex justify-end gap-2\">\n <button\n type=\"button\"\n data-plan-interactive\n className=\"inline-flex h-9 items-center rounded-md px-4 text-sm font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\"\n onClick={() => setEditing(false)}\n >\n Cancel\n </button>\n <button\n type=\"button\"\n data-plan-interactive\n className=\"inline-flex h-9 items-center rounded-md bg-primary px-4 text-sm font-medium text-primary-foreground shadow transition-colors hover:bg-primary/90\"\n onClick={() => {\n onChange({ ...data, html, css: css || undefined });\n setEditing(false);\n }}\n >\n Save\n </button>\n </div>\n </div>\n ) : (\n <HtmlPreview data={data} title={title} sanitize={ctx.sanitizeHtml} />\n )}\n </div>\n );\n}\n\n/**\n * The standard HTML / Tailwind block spec. Both apps register this; the plan app\n * registers the matching React-free `{ schema, mdx }` server-side via\n * `html.config.ts`. `empty()` seeds a friendly starter fragment for slash\n * insertion.\n */\nexport const htmlBlock = defineBlock<HtmlBlockData>({\n type: \"custom-html\",\n schema: htmlSchema,\n mdx: htmlMdx,\n Read: HtmlReadBlock,\n Edit: HtmlEditBlock,\n placement: [\"block\"],\n label: \"HTML / Tailwind\",\n icon: IconCode,\n description:\n \"An author-supplied HTML (with optional CSS) fragment rendered in a sandboxed iframe, with inline source editing.\",\n empty: () => ({ html: '<div class=\"p-6\">Edit this HTML fragment…</div>' }),\n});\n"]}
@@ -0,0 +1,30 @@
1
+ import { z } from "zod";
2
+ import type { BlockMdxConfig } from "../types.js";
3
+ /**
4
+ * Pure (React-free) part of the standard `table` block: its data schema and MDX
5
+ * round-trip config. Shared by the server MDX adapter (the plan
6
+ * `plan-block-registry.ts` → `plan-mdx.ts`) and the client spec
7
+ * (`table.tsx`). Keeping it React-free means a server module that imports it
8
+ * never pulls React into the Nitro/SSR bundle.
9
+ *
10
+ * The schema MUST stay data-compatible with the legacy `table` branch of the
11
+ * plan `planBlockSchema` (`{ columns: string[]; rows: string[][] }`), and the
12
+ * MDX `tag` + attribute shape MUST match the legacy self-closing
13
+ * `<Table … columns={…} rows={…} />` encoding (`plan-mdx.ts`
14
+ * `serializeBlock`/`parseBlock`) so stored `.mdx` round-trips byte-compatibly.
15
+ */
16
+ export interface TableData {
17
+ columns: string[];
18
+ rows: string[][];
19
+ }
20
+ export declare const tableSchema: z.ZodType<TableData>;
21
+ /**
22
+ * MDX config: `columns` and `rows` are JSON attributes (no children) — exactly
23
+ * the legacy self-closing `<Table id title summary editable columns={…} rows={…} />`
24
+ * form. The legacy serializer emits `columns` before `rows`; `toAttrs` returns
25
+ * the keys in that exact insertion order because `serializeSpecBlock` preserves
26
+ * `Object.entries` order. `fromAttrs` mirrors the legacy parser's `?? []`
27
+ * defaults so partial/older nodes stay tolerant.
28
+ */
29
+ export declare const tableMdx: BlockMdxConfig<TableData>;
30
+ //# sourceMappingURL=table.config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.config.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/table.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC;CAClB;AAED,eAAO,MAAM,WAAW,EAGP,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAEtC;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,EAAE,cAAc,CAAC,SAAS,CAO9C,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { z } from "zod";
2
+ export const tableSchema = z.object({
3
+ columns: z.array(z.string()),
4
+ rows: z.array(z.array(z.string())),
5
+ });
6
+ /**
7
+ * MDX config: `columns` and `rows` are JSON attributes (no children) — exactly
8
+ * the legacy self-closing `<Table id title summary editable columns={…} rows={…} />`
9
+ * form. The legacy serializer emits `columns` before `rows`; `toAttrs` returns
10
+ * the keys in that exact insertion order because `serializeSpecBlock` preserves
11
+ * `Object.entries` order. `fromAttrs` mirrors the legacy parser's `?? []`
12
+ * defaults so partial/older nodes stay tolerant.
13
+ */
14
+ export const tableMdx = {
15
+ tag: "Table",
16
+ toAttrs: (data) => ({ columns: data.columns, rows: data.rows }),
17
+ fromAttrs: (attrs) => ({
18
+ columns: attrs.array("columns") ?? [],
19
+ rows: attrs.array("rows") ?? [],
20
+ }),
21
+ };
22
+ //# sourceMappingURL=table.config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.config.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/table.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAsBxB,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC5B,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;CACnC,CAAoC,CAAC;AAEtC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAA8B;IACjD,GAAG,EAAE,OAAO;IACZ,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;IAC/D,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACrB,OAAO,EAAE,KAAK,CAAC,KAAK,CAAS,SAAS,CAAC,IAAI,EAAE;QAC7C,IAAI,EAAE,KAAK,CAAC,KAAK,CAAW,MAAM,CAAC,IAAI,EAAE;KAC1C,CAAC;CACH,CAAC","sourcesContent":["import { z } from \"zod\";\nimport type { BlockMdxConfig } from \"../types.js\";\n\n/**\n * Pure (React-free) part of the standard `table` block: its data schema and MDX\n * round-trip config. Shared by the server MDX adapter (the plan\n * `plan-block-registry.ts` → `plan-mdx.ts`) and the client spec\n * (`table.tsx`). Keeping it React-free means a server module that imports it\n * never pulls React into the Nitro/SSR bundle.\n *\n * The schema MUST stay data-compatible with the legacy `table` branch of the\n * plan `planBlockSchema` (`{ columns: string[]; rows: string[][] }`), and the\n * MDX `tag` + attribute shape MUST match the legacy self-closing\n * `<Table … columns={…} rows={…} />` encoding (`plan-mdx.ts`\n * `serializeBlock`/`parseBlock`) so stored `.mdx` round-trips byte-compatibly.\n */\n\nexport interface TableData {\n columns: string[];\n rows: string[][];\n}\n\nexport const tableSchema = z.object({\n columns: z.array(z.string()),\n rows: z.array(z.array(z.string())),\n}) as unknown as z.ZodType<TableData>;\n\n/**\n * MDX config: `columns` and `rows` are JSON attributes (no children) — exactly\n * the legacy self-closing `<Table id title summary editable columns={…} rows={…} />`\n * form. The legacy serializer emits `columns` before `rows`; `toAttrs` returns\n * the keys in that exact insertion order because `serializeSpecBlock` preserves\n * `Object.entries` order. `fromAttrs` mirrors the legacy parser's `?? []`\n * defaults so partial/older nodes stay tolerant.\n */\nexport const tableMdx: BlockMdxConfig<TableData> = {\n tag: \"Table\",\n toAttrs: (data) => ({ columns: data.columns, rows: data.rows }),\n fromAttrs: (attrs) => ({\n columns: attrs.array<string>(\"columns\") ?? [],\n rows: attrs.array<string[]>(\"rows\") ?? [],\n }),\n};\n"]}
@@ -0,0 +1,8 @@
1
+ import { type TableData } from "./table.config.js";
2
+ /**
3
+ * The full standard `table` `BlockSpec`. Pairs the React-free
4
+ * {@link tableSchema}/{@link tableMdx} config (also used by the server registry)
5
+ * with the React `Read`/`Edit`. `empty()` seeds a 2×2 grid for slash insertion.
6
+ */
7
+ export declare const tableBlock: import("../types.js").BlockSpec<TableData>;
8
+ //# sourceMappingURL=table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/table.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAyB,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAyO1E;;;;GAIG;AACH,eAAO,MAAM,UAAU,4CAoBrB,CAAC"}