@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
@@ -5,6 +5,8 @@ description: >-
5
5
  that run inside iframes. Use when a user asks for a dashboard, widget,
6
6
  calculator, or any interactive mini-app that calls external APIs. Distinct
7
7
  from LLM "tools" (function calls) — see note below.
8
+ metadata:
9
+ internal: true
8
10
  ---
9
11
 
10
12
  # Extensions
@@ -21,7 +23,18 @@ description: >-
21
23
  > Historical naming: extensions were previously called "tools". The physical
22
24
  > SQL table names (`tools`, `tool_data`, `tool_shares`) and a few legacy
23
25
  > in-iframe globals (`toolFetch`, `toolData`) are kept for back-compat — see
24
- > the relevant sections below.
26
+ > the back-compat table in `references/api.md`.
27
+
28
+ ## References
29
+
30
+ - **`references/api.md`** — the exhaustive helper/global tables (`appAction`,
31
+ `appFetch`, `dbQuery`, `dbExec`, `extensionFetch`, `extensionData`), secrets,
32
+ Tailwind classes, sharing, navigation, routes, and the full back-compat
33
+ naming table. Read this when you need the precise signature, scope option, or
34
+ route for any helper.
35
+ - **`references/examples.md`** — five worked HTML extensions (API status
36
+ dashboard, weather widget, todo list with `extensionData`, quick notes).
37
+ Read this when you want a complete copy-pasteable starting point.
25
38
 
26
39
  ## CRITICAL: What Extensions Are (and Are Not)
27
40
 
@@ -45,7 +58,8 @@ a ... extension" (or the older phrasings "make a tool" / "create a tool"):**
45
58
  2. Call `create-extension` with the HTML as `content`
46
59
  3. That's it — no files to create, no schema changes, no actions
47
60
 
48
- Extensions have full access to app data via helpers injected into the iframe:
61
+ Extensions have full access to app data via helpers injected into the iframe
62
+ (full signatures in `references/api.md`):
49
63
 
50
64
  - `appAction(name, params)` — call any app action
51
65
  - `appFetch(path, options)` — call allowed framework endpoints under
@@ -81,14 +95,6 @@ await extensionData.set('notes', 'note-1', { title: 'Team Note', body: 'Hello' }
81
95
  const myNotes = await extensionData.list('notes'); // user-scoped (default)
82
96
  const orgNotes = await extensionData.list('notes', { scope: 'org' }); // org-scoped only
83
97
  const allNotes = await extensionData.list('notes', { scope: 'all' }); // both user + org
84
-
85
- // Get one item
86
- const note = await extensionData.get('notes', 'note-1'); // user-scoped
87
- const orgNote = await extensionData.get('notes', 'note-1', { scope: 'org' }); // org-scoped
88
-
89
- // Delete an item
90
- await extensionData.remove('notes', 'note-1'); // user-scoped
91
- await extensionData.remove('notes', 'note-1', { scope: 'org' }); // org-scoped
92
98
  ```
93
99
 
94
100
  > The legacy global `toolData` is still injected and points at the same
@@ -97,7 +103,8 @@ await extensionData.remove('notes', 'note-1', { scope: 'org' });
97
103
 
98
104
  **Prefer `extensionData` over raw `dbExec` for extension-specific
99
105
  persistence** — it handles everything automatically. Only use
100
- `dbQuery`/`dbExec` when querying the app's existing tables.
106
+ `dbQuery`/`dbExec` when querying the app's existing tables. See
107
+ `references/api.md` for the full `get`/`remove`/scope reference.
101
108
 
102
109
  ## What extensions are
103
110
 
@@ -114,7 +121,7 @@ Call the `create-extension` action:
114
121
  pnpm action create-extension \
115
122
  --name "GitHub PR Dashboard" \
116
123
  --description "Shows open PRs for the repo" \
117
- --content '<div x-data="{ prs: [], loading: true }" x-init="extensionFetch('"'"'https://api.github.com/repos/OWNER/REPO/pulls'"'"', { headers: { '"'"'Authorization'"'"': '"'"'Bearer ${keys.GITHUB_TOKEN}'"'"' }}).then(r => r.json()).then(d => { prs = d; loading = false })"><template x-if="loading"><p>Loading...</p></template><div class="space-y-2"><template x-for="pr in prs" :key="pr.id"><a :href="pr.html_url" target="_blank" class="block rounded-lg border p-3 hover:bg-accent"><p class="font-medium" x-text="pr.title"></p><p class="text-sm text-muted-foreground" x-text="'"'"'#'"'"' + pr.number + '"'"' by '"'"' + pr.user.login"></p></a></template></div></div>'
124
+ --content '<div x-data="...">...</div>'
118
125
  ```
119
126
 
120
127
  Or via the HTTP API:
@@ -132,10 +139,50 @@ The action accepts:
132
139
  | `description` | `string` | no | Short summary |
133
140
  | `content` | `string` | yes | Alpine.js HTML body |
134
141
 
142
+ See `references/examples.md` for full, runnable `content` bodies.
143
+
135
144
  ## Editing an extension
136
145
 
137
- Use the `update-extension` action. Prefer `patches` for surgical edits
138
- instead of regenerating the full HTML:
146
+ Use the `update-extension` action. Prefer granular `edits` for surgical
147
+ changes instead of regenerating the full HTML. For medium/large extensions,
148
+ add stable section comments around major blocks so future agents can target
149
+ them without touching unrelated indentation:
150
+
151
+ ```html
152
+ <!-- agent-native:section npm-daily-chart -->
153
+ <section>...</section>
154
+ <!-- /agent-native:section npm-daily-chart -->
155
+ ```
156
+
157
+ Then update just that section:
158
+
159
+ ```json
160
+ {
161
+ "id": "EXTENSION_ID",
162
+ "edits": "[{\"op\":\"replace-section\",\"section\":\"npm-daily-chart\",\"content\":\"<section>...</section>\"}]",
163
+ "format": true
164
+ }
165
+ ```
166
+
167
+ Supported `edits` operations:
168
+
169
+ | Operation | Use for |
170
+ | ----------------- | -------------------------------------------- |
171
+ | `replace` | Literal find/replace; defaults to one match |
172
+ | `insert-before` | Insert content before an exact marker |
173
+ | `insert-after` | Insert content after an exact marker |
174
+ | `replace-between` | Replace content between two exact markers |
175
+ | `replace-section` | Replace a named comment section |
176
+ | `wrap-section` | Add a wrapper around a named section |
177
+ | `remove-section` | Remove a named section |
178
+ | `regex-replace` | Carefully scoped regex replacement |
179
+
180
+ Use `expectedMatches` when ambiguity would be dangerous. Missing required
181
+ targets fail instead of silently doing nothing. Pass `format: true` to run
182
+ Prettier on the final HTML after the patch. Full `content` replacement is
183
+ still available for broad rewrites.
184
+
185
+ Legacy `patches` still work for simple literal replacements:
139
186
 
140
187
  ```
141
188
  PUT /_agent-native/extensions/:id
@@ -157,6 +204,26 @@ PUT /_agent-native/extensions/:id
157
204
  { "content": "full new HTML" }
158
205
  ```
159
206
 
207
+ ## History and rollback
208
+
209
+ Extensions keep a snapshot history in SQL. A version is recorded when an
210
+ extension is created, when metadata or HTML content changes, and when a prior
211
+ version is restored. Existing extensions that predate history get their current
212
+ state saved as a baseline the first time they are edited.
213
+
214
+ Use these actions when the user asks what changed, wants a changelog/diff, or
215
+ wants to go back in time:
216
+
217
+ | Action | Purpose |
218
+ | ----------------------------------- | ------------------------------------------------------------- |
219
+ | `list-extension-history` | List saved versions for one extension |
220
+ | `get-extension-history-version` | Read one version with a previous-version diff |
221
+ | `restore-extension-history-version` | Restore name, description, icon, and HTML content from a version |
222
+
223
+ Restoring a version does **not** restore sharing/ownership; access stays as it
224
+ is now. In the UI, use the History button in the extension viewer to inspect
225
+ versions, see diffs, and restore older content.
226
+
160
227
  ## Alpine.js patterns
161
228
 
162
229
  Extension HTML uses Alpine.js directives for reactivity. No build step, no
@@ -277,392 +344,19 @@ end up rendering nonsense like the literal text `true`.
277
344
  If you're not sure a key is configured, ask the user before generating an
278
345
  extension whose primary value is the AI step.
279
346
 
280
- ## Accessing app data
281
-
282
- Extensions can call the host app's actions and API endpoints directly. The
283
- iframe shares the session cookie, so authentication is automatic.
284
-
285
- ### `appAction(name, params)` — Call app actions
286
-
287
- Call any action defined in the app's `actions/` directory. Actions are
288
- auto-mounted at `/_agent-native/actions/:name`.
289
-
290
- ```html
291
- <div x-data="{ emails: [], loading: true }" x-init="
292
- appAction('list-emails', { view: 'inbox', limit: 10 })
293
- .then(d => { emails = d.emails || d; loading = false })
294
- .catch(e => { console.error(e); loading = false })
295
- ">
296
- <h2 class='text-lg font-semibold mb-4'>My Inbox</h2>
297
- <template x-for='email in emails' :key='email.id'>
298
- <div class='rounded-lg border p-3 mb-2'>
299
- <p class='font-medium text-sm' x-text='email.subject'></p>
300
- <p class='text-xs text-muted-foreground' x-text='email.from?.name || email.from?.email'></p>
301
- </div>
302
- </template>
303
- </div>
304
- ```
305
-
306
- ### `appFetch(path, options)` — Call allowed framework endpoints
307
-
308
- General-purpose fetch to allowed framework endpoints (for example,
309
- `/_agent-native/application-state/navigation`). Automatically adds credentials
310
- and JSON content type. Template `/api/*` routes are intentionally blocked by
311
- the extension bridge; use `appAction(name, params)` for app data instead.
312
-
313
- ```javascript
314
- // Read application state
315
- const nav = await appFetch('/_agent-native/application-state/navigation');
316
-
317
- // Call a framework route
318
- const nav = await appFetch('/_agent-native/application-state/navigation');
319
- ```
320
-
321
- ### `dbQuery(sql)` — Read from the app's database
322
-
323
- Run a read-only SELECT query against the app's SQL database. Results are
324
- auto-scoped to the current user/org.
325
-
326
- ```html
327
- <div x-data="{ rows: [] }" x-init="
328
- dbQuery('SELECT id, name FROM tools ORDER BY created_at DESC LIMIT 10')
329
- .then(d => rows = d.rows || d)
330
- ">
331
- <template x-for="row in rows" :key="row.id">
332
- <div class="border-b p-2 text-sm" x-text="row.name"></div>
333
- </template>
334
- </div>
335
- ```
336
-
337
- > The physical SQL table is still named `tools` (and `tool_data`,
338
- > `tool_shares`) for back-compat. The Drizzle exports are `extensions`,
339
- > `extensionData`, and `extensionShares` — use those when you query via the
340
- > ORM. When writing raw SQL inside an extension (as above), use the
341
- > physical names.
342
-
343
- ### `dbExec(sql)` — Write to the app's database
344
-
345
- Run an INSERT, UPDATE, or DELETE statement. Writes are auto-scoped to the
346
- current user/org, and `owner_email` / `org_id` are auto-injected on INSERT.
347
-
348
- ```javascript
349
- // Insert a new record
350
- await dbExec("INSERT INTO notes (id, title, body) VALUES ('abc', 'My Note', 'Hello world')");
351
-
352
- // Update an existing record
353
- await dbExec("UPDATE notes SET title = 'Updated Title' WHERE id = 'abc'");
354
- ```
355
-
356
- ### All helpers summary
357
-
358
- | Helper | Use for | Example |
359
- |--------|---------|---------|
360
- | `appAction(name, params)` | Call app actions (CRUD, queries) | `appAction('list-emails', { view: 'inbox' })` |
361
- | `appFetch(path, options)` | Call allowed framework endpoints | `appFetch('/_agent-native/application-state/navigation')` |
362
- | `dbQuery(sql)` | Read from the app's SQL database | `dbQuery('SELECT * FROM notes LIMIT 10')` |
363
- | `dbExec(sql)` | Write to the app's SQL database | `dbExec("INSERT INTO notes ...")` |
364
- | `extensionFetch(url, options)` | Call external APIs via proxy (alias `toolFetch`) | `extensionFetch('https://api.github.com/user', { headers: { 'Authorization': 'Bearer ${keys.GITHUB_TOKEN}' } })` |
365
- | `extensionData.set(collection, id, data, opts?)` | Save an item to extension storage (alias `toolData.set`) | `extensionData.set('todos', 'todo-1', { title: 'Buy milk' })` |
366
- | `extensionData.list(collection, opts?)` | List items in a collection | `extensionData.list('todos', { scope: 'all' })` |
367
- | `extensionData.get(collection, id, opts?)` | Get a single item by id | `extensionData.get('todos', 'todo-1')` |
368
- | `extensionData.remove(collection, id, opts?)` | Delete an item | `extensionData.remove('todos', 'todo-1')` |
369
-
370
- ## Persisting Custom Data
371
-
372
- Extensions have a built-in key-value store via `extensionData` (legacy alias:
373
- `toolData`). Each extension gets its own isolated storage, organized into
374
- collections. Every method accepts an optional `{ scope }` option:
375
-
376
- - `'user'` (default) — private to the current user
377
- - `'org'` — visible to everyone in the user's org
378
- - `'all'` (list/get only) — returns both user and org items
379
-
380
- ```javascript
381
- // Save a private item (default scope: 'user')
382
- await extensionData.set('todos', 'todo-1', { title: 'Buy milk', done: false });
383
-
384
- // Save an org-shared item
385
- await extensionData.set('todos', 'team-todo-1', { title: 'Ship v2', done: false }, { scope: 'org' });
386
-
387
- // List user items (default)
388
- const myTodos = await extensionData.list('todos');
389
-
390
- // List org items
391
- const orgTodos = await extensionData.list('todos', { scope: 'org' });
392
-
393
- // List both user + org items
394
- const allTodos = await extensionData.list('todos', { scope: 'all' });
395
- // Returns: [{ id, toolId, collection, data (JSON string), ownerEmail, scope, orgId, createdAt, updatedAt }]
396
- // (the row column is still named `toolId` for back-compat — it's the extension id)
397
-
398
- // Parse the JSON data
399
- const parsed = allTodos.map(t => ({ ...JSON.parse(t.data), id: t.id, scope: t.scope }));
400
-
401
- // Get/delete with scope
402
- const item = await extensionData.get('todos', 'team-todo-1', { scope: 'org' });
403
- await extensionData.remove('todos', 'team-todo-1', { scope: 'org' });
404
- ```
405
-
406
- Data is scoped per-extension. User-scoped items are private per-user;
407
- org-scoped items are shared across the org. Any org member can read,
408
- update, or delete org-scoped items. **Prefer `extensionData` over raw
409
- `dbExec` for extension-specific persistence** — it handles table creation,
410
- scoping, and upserts automatically.
411
-
412
- ## Using `extensionFetch()` for API calls
413
-
414
- `extensionFetch()` (legacy alias `toolFetch()`) is a drop-in replacement for
415
- `fetch()` that proxies requests through the server. The server injects
416
- secret values before the request leaves.
417
-
418
- ```javascript
419
- // Basic GET
420
- const res = await extensionFetch('https://api.example.com/data');
421
- const data = await res.json();
422
-
423
- // With secret injection
424
- const res = await extensionFetch('https://api.openai.com/v1/models', {
425
- headers: {
426
- 'Authorization': 'Bearer ${keys.OPENAI_API_KEY}'
427
- }
428
- });
429
-
430
- // POST with body
431
- const res = await extensionFetch('https://api.example.com/items', {
432
- method: 'POST',
433
- headers: { 'Content-Type': 'application/json' },
434
- body: JSON.stringify({ name: 'New Item' })
435
- });
436
- ```
437
-
438
- **Important:** Use single quotes around strings containing `${keys.NAME}`
439
- to prevent JavaScript template literal evaluation. The substitution
440
- happens server-side, not in the browser.
441
-
442
- ## Tailwind classes
443
-
444
- Extensions inherit the main app's Tailwind v4 theme. Use the same utility
445
- classes:
446
-
447
- - **Colors:** `bg-background`, `text-foreground`, `bg-primary`, `text-primary-foreground`, `text-muted-foreground`, `border-border`, `bg-accent`, `bg-destructive`
448
- - **Layout:** `flex`, `grid`, `space-y-2`, `gap-4`, `p-4`, `m-2`
449
- - **Typography:** `text-sm`, `text-lg`, `font-medium`, `font-bold`
450
- - **Borders:** `border`, `rounded-lg`, `rounded-md`, `rounded-sm`
451
- - **Dark mode:** automatic via `.dark` class on the html element
452
-
453
- ## Managing secrets
454
-
455
- Extensions reference secrets via `${keys.NAME}` inside `extensionFetch()`
456
- calls. Create secrets via:
457
-
458
- ```
459
- POST /_agent-native/secrets/adhoc
460
- { "name": "GITHUB_TOKEN", "value": "ghp_xxxx", "description": "GitHub PAT", "urlAllowlist": ["https://api.github.com"] }
461
- ```
462
-
463
- Or the user can add them in the settings UI. If an extension needs an API
464
- key that isn't configured yet, tell the user what key is needed and where
465
- to get it.
466
-
467
- See the `secrets` skill for the full secrets API.
468
-
469
- ## Sharing
470
-
471
- Use the framework sharing actions:
472
-
473
- ```bash
474
- # Make an extension visible to the org
475
- pnpm action set-resource-visibility --resourceType=tool --resourceId=EXTENSION_ID --visibility=org
476
-
477
- # Share with a specific user
478
- pnpm action share-resource --resourceType=tool --resourceId=EXTENSION_ID --principalType=user --principalId=user@example.com --role=editor
479
-
480
- # List current shares
481
- pnpm action list-resource-shares --resourceType=tool --resourceId=EXTENSION_ID
482
- ```
483
-
484
- > The `resourceType` value is still `tool` for back-compat with the
485
- > `tool_shares` table. The variable name `EXTENSION_ID` is the canonical
486
- > name for the value going into the call.
487
-
488
- See the `sharing` skill for visibility levels and roles.
489
-
490
- ## Navigation
491
-
492
- ```bash
493
- # Navigate to the extensions list
494
- pnpm action navigate --view=extensions
495
-
496
- # Navigate to a specific extension
497
- pnpm action navigate --view=extensions --extensionId=EXTENSION_ID
498
-
499
- # Or directly:
500
- set-url-path({ "pathname": "/extensions/EXTENSION_ID" })
501
- ```
502
-
503
- ## Example extensions
504
-
505
- ### API Status Dashboard
506
-
507
- Checks the health of multiple endpoints and shows green/red status:
508
-
509
- ```html
510
- <div class="p-6" x-data="{
511
- endpoints: [
512
- { name: 'API', url: 'https://api.example.com/health' },
513
- { name: 'Auth', url: 'https://auth.example.com/health' },
514
- { name: 'CDN', url: 'https://cdn.example.com/health' }
515
- ],
516
- results: [],
517
- loading: true
518
- }" x-init="
519
- Promise.all(endpoints.map(ep =>
520
- extensionFetch(ep.url).then(r => ({ ...ep, ok: r.ok })).catch(() => ({ ...ep, ok: false }))
521
- )).then(r => { results = r; loading = false })
522
- ">
523
- <h2 class="text-lg font-bold mb-4">Service Status</h2>
524
- <template x-if="loading"><p class="text-muted-foreground">Checking...</p></template>
525
- <div class="space-y-2">
526
- <template x-for="r in results" :key="r.name">
527
- <div class="flex items-center justify-between rounded-lg border p-3">
528
- <span class="font-medium" x-text="r.name"></span>
529
- <span x-bind:class="r.ok ? 'text-green-600' : 'text-red-600'" x-text="r.ok ? 'Healthy' : 'Down'"></span>
530
- </div>
531
- </template>
532
- </div>
533
- </div>
534
- ```
535
-
536
- ### Weather Widget
537
-
538
- Fetches current weather for a city:
539
-
540
- ```html
541
- <div class="p-6" x-data="{ city: 'San Francisco', weather: null, loading: false }" x-init="
542
- loading = true;
543
- extensionFetch('https://api.weatherapi.com/v1/current.json?q=' + encodeURIComponent(city) + '&key=${keys.WEATHER_API_KEY}')
544
- .then(r => r.json()).then(d => { weather = d; loading = false })
545
- ">
546
- <div class="space-y-4">
547
- <div class="flex gap-2">
548
- <input type="text" x-model="city" class="flex-1 rounded-md border bg-background px-3 py-2 text-sm" placeholder="City name" />
549
- <button x-on:click="loading = true; extensionFetch('https://api.weatherapi.com/v1/current.json?q=' + encodeURIComponent(city) + '&key=${keys.WEATHER_API_KEY}').then(r => r.json()).then(d => { weather = d; loading = false })" class="rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground cursor-pointer">Search</button>
550
- </div>
551
- <template x-if="loading"><p class="text-muted-foreground">Loading...</p></template>
552
- <template x-if="weather && !loading">
553
- <div class="rounded-lg border p-4">
554
- <p class="text-2xl font-bold" x-text="weather.current.temp_f + '°F'"></p>
555
- <p class="text-muted-foreground" x-text="weather.current.condition.text"></p>
556
- <p class="text-sm text-muted-foreground" x-text="weather.location.name + ', ' + weather.location.region"></p>
557
- </div>
558
- </template>
559
- </div>
560
- </div>
561
- ```
562
-
563
- ### Todo List (using extensionData)
564
-
565
- Full CRUD app using the built-in `extensionData` store — no SQL, no schema
566
- files, no actions. Data is automatically scoped per-extension and per-user:
567
-
568
- ```html
569
- <div class="p-6" x-data="{
570
- todos: [],
571
- newTodo: '',
572
- loading: true,
573
- async init() {
574
- const items = await extensionData.list('todos');
575
- this.todos = items.map(i => ({ id: i.id, ...JSON.parse(i.data) }));
576
- this.loading = false;
577
- },
578
- async addTodo() {
579
- if (!this.newTodo.trim()) return;
580
- const id = crypto.randomUUID();
581
- const data = { title: this.newTodo.trim(), completed: false };
582
- await extensionData.set('todos', id, data);
583
- this.todos.unshift({ id, ...data });
584
- this.newTodo = '';
585
- },
586
- async toggle(todo) {
587
- todo.completed = !todo.completed;
588
- await extensionData.set('todos', todo.id, { title: todo.title, completed: todo.completed });
589
- },
590
- async remove(id) {
591
- await extensionData.remove('todos', id);
592
- this.todos = this.todos.filter(t => t.id !== id);
593
- }
594
- }">
595
- <h2 class="text-lg font-semibold mb-4">Todo List</h2>
596
- <div class="flex gap-2 mb-4">
597
- <input x-model="newTodo" type="text" placeholder="What needs to be done?"
598
- class="flex-1 rounded-md border border-input bg-background px-3 py-2 text-sm"
599
- @keydown.enter="addTodo()">
600
- <button @click="addTodo()"
601
- class="rounded-md bg-primary px-4 py-2 text-sm text-primary-foreground cursor-pointer hover:bg-primary/90">
602
- Add
603
- </button>
604
- </div>
605
- <div x-show="loading" class="text-sm text-muted-foreground">Loading...</div>
606
- <div class="space-y-2">
607
- <template x-for="todo in todos" :key="todo.id">
608
- <div class="flex items-center gap-3 rounded-md border p-3">
609
- <button @click="toggle(todo)" class="cursor-pointer"
610
- :class="todo.completed ? 'text-green-500' : 'text-muted-foreground'">
611
- <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
612
- <template x-if="todo.completed"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14M22 4 12 14.01l-3-3"/></template>
613
- <template x-if="!todo.completed"><circle cx="12" cy="12" r="10"/></template>
614
- </svg>
615
- </button>
616
- <span class="flex-1 text-sm" :class="todo.completed && 'line-through text-muted-foreground'" x-text="todo.title"></span>
617
- <button @click="remove(todo.id)" class="text-muted-foreground hover:text-destructive cursor-pointer text-xs">Remove</button>
618
- </div>
619
- </template>
620
- </div>
621
- <p x-show="!loading && todos.length === 0" class="text-sm text-muted-foreground text-center py-8">No todos yet. Add one above!</p>
622
- </div>
623
- ```
347
+ ## Secrets and sensitive data in extensions
624
348
 
625
- ### Quick Notes
349
+ Never put a real API key, token, webhook URL, signing secret, private
350
+ Builder/internal data, customer data, or credential-looking literal into
351
+ extension HTML, inline scripts, docs, examples, or extension seed content.
352
+ Extensions are stored in SQL and rendered in the browser; anything written into
353
+ the extension body should be treated as visible.
626
354
 
627
- Persistent notes using localStorage -- no API key needed:
628
-
629
- ```html
630
- <div class="p-6" x-data="{
631
- notes: JSON.parse(localStorage.getItem('quick-notes') || '[]'),
632
- draft: '',
633
- save() {
634
- if (!this.draft.trim()) return;
635
- this.notes.unshift({ id: Date.now(), text: this.draft, date: new Date().toLocaleDateString() });
636
- this.draft = '';
637
- localStorage.setItem('quick-notes', JSON.stringify(this.notes));
638
- },
639
- remove(id) {
640
- this.notes = this.notes.filter(n => n.id !== id);
641
- localStorage.setItem('quick-notes', JSON.stringify(this.notes));
642
- }
643
- }">
644
- <div class="space-y-4">
645
- <div class="flex gap-2">
646
- <input type="text" x-model="draft" x-on:keydown.enter="save()" class="flex-1 rounded-md border bg-background px-3 py-2 text-sm" placeholder="Add a note..." />
647
- <button x-on:click="save()" class="rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground cursor-pointer">Add</button>
648
- </div>
649
- <div class="space-y-2">
650
- <template x-for="note in notes" :key="note.id">
651
- <div class="flex items-start justify-between rounded-lg border p-3">
652
- <div>
653
- <p class="text-sm" x-text="note.text"></p>
654
- <p class="text-xs text-muted-foreground" x-text="note.date"></p>
655
- </div>
656
- <button x-on:click="remove(note.id)" class="text-muted-foreground hover:text-destructive text-sm cursor-pointer">Remove</button>
657
- </div>
658
- </template>
659
- <template x-if="notes.length === 0">
660
- <p class="text-sm text-muted-foreground">No notes yet.</p>
661
- </template>
662
- </div>
663
- </div>
664
- </div>
665
- ```
355
+ For external API calls, use `extensionFetch()` with `${keys.NAME}` placeholders
356
+ inside single-quoted strings, for example
357
+ `Authorization: 'Bearer ${keys.GITHUB_TOKEN}'`. The proxy resolves the value
358
+ server-side. If the user has not configured the key, surface a setup error
359
+ instead of substituting a copied key or demo value.
666
360
 
667
361
  ## Guidelines
668
362
 
@@ -673,48 +367,16 @@ Persistent notes using localStorage -- no API key needed:
673
367
  - **All functions referenced in Alpine expressions must be defined in `x-data`.** If you use `@click="add()"`, there must be an `add()` method in the component's `x-data` object. Undefined references cause runtime errors.
674
368
  - **For non-trivial components, use a `<script>` + `Alpine.data('name', () => ({...}))` block and reference it with `x-data="name"`.** Inline `x-data="{ ...big object... }"` is brittle: stuffing many methods, branching logic, or any backtick template literal into an HTML attribute leads to half-parsed expressions and `ReferenceError` failures. See the "Component shape" section above.
675
369
  - **Don't ship a stubbed AI step.** If the extension's value is "AI analysis" and no LLM key is configured, either route the work to the agent chat or tell the user which key to add — never render a placeholder/boolean as the result.
370
+ - **Never hardcode secrets or private data.** Use `${keys.NAME}` placeholders
371
+ for external credentials and synthetic example data for demos.
676
372
  - **Use the right fetch helper.** `appAction()` for app actions and app data, `appFetch()` for allowed framework `/_agent-native/*` endpoints, and `extensionFetch()` for external APIs. Never call template `/api/*` routes from an extension and never use raw `fetch()` -- secrets won't be injected and CORS will block external APIs.
677
373
  - **Single quotes around `${keys.*}`** to prevent browser-side template literal evaluation.
678
374
  - **Prefer patches over full rewrites** when editing existing extensions. Smaller diffs are less error-prone.
679
375
 
680
- ## Routes
681
-
682
- | Method | Path | Purpose |
683
- | ------ | -------------------------------------- | --------------------------------------------- |
684
- | GET | `/_agent-native/extensions` | List extensions (filtered by ownership/share) |
685
- | POST | `/_agent-native/extensions` | Create an extension |
686
- | GET | `/_agent-native/extensions/:id` | Get an extension |
687
- | PUT | `/_agent-native/extensions/:id` | Update (supports `patches` for diffing) |
688
- | DELETE | `/_agent-native/extensions/:id` | Delete an extension |
689
- | GET | `/_agent-native/extensions/:id/render` | Render HTML for iframe |
690
- | POST | `/_agent-native/extensions/proxy` | Authenticated proxy with secret injection |
691
-
692
- ## Database & API names — back-compat reference
693
-
694
- The rename from "tools" to "extensions" is mostly user-facing. Several
695
- under-the-hood names are kept to avoid breaking existing data and code:
696
-
697
- | Surface | Stays as | Rationale |
698
- | ------------------------------------ | --------------------- | ------------------------------------------------------ |
699
- | SQL table for extensions | `tools` | Renaming a table = drop+create; data must not move |
700
- | SQL table for per-ext data | `tool_data` | Same |
701
- | SQL table for ext shares | `tool_shares` | Same |
702
- | Drizzle schema export | `extensions` | Code-side rename — no data migration needed |
703
- | Drizzle schema export | `extensionData` | Same |
704
- | Drizzle schema export | `extensionShares` | Same |
705
- | Iframe global (legacy alias) | `toolFetch` | Kept so older extension bodies keep working |
706
- | Iframe global (legacy alias) | `toolData` | Same |
707
- | Iframe global (canonical) | `extensionFetch` | Use this in new extensions |
708
- | Iframe global (canonical) | `extensionData` | Same |
709
- | `data-tool-layout` HTML attribute | unchanged | Runtime contract; not worth churning |
710
- | `resourceType` for sharing | `tool` | Matches `tool_shares` table |
711
- | Slot-system table | `tool_slots` | Drizzle export is `extensionSlots` (see `extension-points`) |
712
- | Slot-installs table | `tool_slot_installs` | Drizzle export is `extensionSlotInstalls` |
713
-
714
376
  ## Related skills
715
377
 
716
378
  - `extension-points` -- how an extension renders as a widget inside another app via named UI slots.
717
379
  - `secrets` -- creating and managing API keys for `${keys.NAME}` substitution.
718
380
  - `sharing` -- visibility and access control for extensions.
719
- - `actions` -- the `create-extension` and `update-extension` actions that back extension CRUD.
381
+ - `actions` -- the `create-extension`, `update-extension`, and extension history actions that back extension CRUD and rollback.
720
382
  - `frontend-design` -- design guidance when styling extension HTML.