@agent-native/core 0.6.1 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (598) hide show
  1. package/README.md +43 -3
  2. package/dist/action.d.ts +8 -0
  3. package/dist/action.d.ts.map +1 -1
  4. package/dist/action.js +18 -0
  5. package/dist/action.js.map +1 -1
  6. package/dist/agent/production-agent.d.ts +9 -0
  7. package/dist/agent/production-agent.d.ts.map +1 -1
  8. package/dist/agent/production-agent.js +301 -39
  9. package/dist/agent/production-agent.js.map +1 -1
  10. package/dist/agent/run-manager.d.ts.map +1 -1
  11. package/dist/agent/run-manager.js +20 -1
  12. package/dist/agent/run-manager.js.map +1 -1
  13. package/dist/agent/run-store.d.ts +14 -0
  14. package/dist/agent/run-store.d.ts.map +1 -1
  15. package/dist/agent/run-store.js +63 -6
  16. package/dist/agent/run-store.js.map +1 -1
  17. package/dist/agent/types.d.ts +3 -1
  18. package/dist/agent/types.d.ts.map +1 -1
  19. package/dist/cli/create-workspace.d.ts +8 -0
  20. package/dist/cli/create-workspace.d.ts.map +1 -0
  21. package/dist/cli/create-workspace.js +18 -0
  22. package/dist/cli/create-workspace.js.map +1 -0
  23. package/dist/cli/create.d.ts +35 -7
  24. package/dist/cli/create.d.ts.map +1 -1
  25. package/dist/cli/create.js +444 -251
  26. package/dist/cli/create.js.map +1 -1
  27. package/dist/cli/index.js +59 -5
  28. package/dist/cli/index.js.map +1 -1
  29. package/dist/cli/setup-agents.d.ts.map +1 -1
  30. package/dist/cli/setup-agents.js +0 -2
  31. package/dist/cli/setup-agents.js.map +1 -1
  32. package/dist/cli/templates-meta.d.ts +52 -0
  33. package/dist/cli/templates-meta.d.ts.map +1 -0
  34. package/dist/cli/templates-meta.js +165 -0
  35. package/dist/cli/templates-meta.js.map +1 -0
  36. package/dist/cli/workspacify.d.ts +18 -0
  37. package/dist/cli/workspacify.d.ts.map +1 -0
  38. package/dist/cli/workspacify.js +74 -0
  39. package/dist/cli/workspacify.js.map +1 -0
  40. package/dist/client/AgentPanel.d.ts +6 -2
  41. package/dist/client/AgentPanel.d.ts.map +1 -1
  42. package/dist/client/AgentPanel.js +328 -241
  43. package/dist/client/AgentPanel.js.map +1 -1
  44. package/dist/client/AssistantChat.d.ts +2 -1
  45. package/dist/client/AssistantChat.d.ts.map +1 -1
  46. package/dist/client/AssistantChat.js +172 -40
  47. package/dist/client/AssistantChat.js.map +1 -1
  48. package/dist/client/ConnectBuilderCard.d.ts +21 -0
  49. package/dist/client/ConnectBuilderCard.d.ts.map +1 -0
  50. package/dist/client/ConnectBuilderCard.js +196 -0
  51. package/dist/client/ConnectBuilderCard.js.map +1 -0
  52. package/dist/client/FeedbackButton.d.ts +15 -0
  53. package/dist/client/FeedbackButton.d.ts.map +1 -0
  54. package/dist/client/FeedbackButton.js +72 -0
  55. package/dist/client/FeedbackButton.js.map +1 -0
  56. package/dist/client/IframeEmbed.d.ts +17 -0
  57. package/dist/client/IframeEmbed.d.ts.map +1 -0
  58. package/dist/client/IframeEmbed.js +108 -0
  59. package/dist/client/IframeEmbed.js.map +1 -0
  60. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  61. package/dist/client/MultiTabAssistantChat.js +34 -7
  62. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  63. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  64. package/dist/client/agent-chat-adapter.js +34 -15
  65. package/dist/client/agent-chat-adapter.js.map +1 -1
  66. package/dist/client/agent-chat.d.ts +6 -0
  67. package/dist/client/agent-chat.d.ts.map +1 -1
  68. package/dist/client/agent-chat.js +7 -0
  69. package/dist/client/agent-chat.js.map +1 -1
  70. package/dist/client/components/CodeRequiredDialog.d.ts.map +1 -1
  71. package/dist/client/components/CodeRequiredDialog.js +86 -5
  72. package/dist/client/components/CodeRequiredDialog.js.map +1 -1
  73. package/dist/client/composer/MentionPopover.d.ts.map +1 -1
  74. package/dist/client/composer/MentionPopover.js +42 -26
  75. package/dist/client/composer/MentionPopover.js.map +1 -1
  76. package/dist/client/composer/TiptapComposer.d.ts +3 -1
  77. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  78. package/dist/client/composer/TiptapComposer.js +24 -5
  79. package/dist/client/composer/TiptapComposer.js.map +1 -1
  80. package/dist/client/composer/types.d.ts +1 -1
  81. package/dist/client/composer/types.d.ts.map +1 -1
  82. package/dist/client/embed.d.ts +28 -0
  83. package/dist/client/embed.d.ts.map +1 -0
  84. package/dist/client/embed.js +50 -0
  85. package/dist/client/embed.js.map +1 -0
  86. package/dist/client/index.d.ts +4 -1
  87. package/dist/client/index.d.ts.map +1 -1
  88. package/dist/client/index.js +4 -1
  89. package/dist/client/index.js.map +1 -1
  90. package/dist/client/integrations/IntegrationsPanel.d.ts.map +1 -1
  91. package/dist/client/integrations/IntegrationsPanel.js +22 -9
  92. package/dist/client/integrations/IntegrationsPanel.js.map +1 -1
  93. package/dist/client/onboarding/OnboardingBanner.d.ts +13 -0
  94. package/dist/client/onboarding/OnboardingBanner.d.ts.map +1 -0
  95. package/dist/client/onboarding/OnboardingBanner.js +36 -0
  96. package/dist/client/onboarding/OnboardingBanner.js.map +1 -0
  97. package/dist/client/onboarding/OnboardingPanel.d.ts +16 -0
  98. package/dist/client/onboarding/OnboardingPanel.d.ts.map +1 -0
  99. package/dist/client/onboarding/OnboardingPanel.js +447 -0
  100. package/dist/client/onboarding/OnboardingPanel.js.map +1 -0
  101. package/dist/client/onboarding/SetupButton.d.ts +10 -0
  102. package/dist/client/onboarding/SetupButton.d.ts.map +1 -0
  103. package/dist/client/onboarding/SetupButton.js +36 -0
  104. package/dist/client/onboarding/SetupButton.js.map +1 -0
  105. package/dist/client/onboarding/index.d.ts +12 -0
  106. package/dist/client/onboarding/index.d.ts.map +1 -0
  107. package/dist/client/onboarding/index.js +11 -0
  108. package/dist/client/onboarding/index.js.map +1 -0
  109. package/dist/client/onboarding/use-onboarding.d.ts +34 -0
  110. package/dist/client/onboarding/use-onboarding.d.ts.map +1 -0
  111. package/dist/client/onboarding/use-onboarding.js +101 -0
  112. package/dist/client/onboarding/use-onboarding.js.map +1 -0
  113. package/dist/client/org/TeamPage.d.ts +6 -1
  114. package/dist/client/org/TeamPage.d.ts.map +1 -1
  115. package/dist/client/org/TeamPage.js +97 -21
  116. package/dist/client/org/TeamPage.js.map +1 -1
  117. package/dist/client/resources/ResourceEditor.d.ts.map +1 -1
  118. package/dist/client/resources/ResourceEditor.js +104 -78
  119. package/dist/client/resources/ResourceEditor.js.map +1 -1
  120. package/dist/client/resources/ResourceTree.d.ts +5 -1
  121. package/dist/client/resources/ResourceTree.d.ts.map +1 -1
  122. package/dist/client/resources/ResourceTree.js +31 -11
  123. package/dist/client/resources/ResourceTree.js.map +1 -1
  124. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  125. package/dist/client/resources/ResourcesPanel.js +142 -14
  126. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  127. package/dist/client/resources/use-resources.d.ts +5 -0
  128. package/dist/client/resources/use-resources.d.ts.map +1 -1
  129. package/dist/client/resources/use-resources.js.map +1 -1
  130. package/dist/client/settings/AgentsSection.d.ts +2 -0
  131. package/dist/client/settings/AgentsSection.d.ts.map +1 -0
  132. package/dist/client/settings/AgentsSection.js +201 -0
  133. package/dist/client/settings/AgentsSection.js.map +1 -0
  134. package/dist/client/settings/BackgroundAgentSection.d.ts +2 -0
  135. package/dist/client/settings/BackgroundAgentSection.d.ts.map +1 -0
  136. package/dist/client/settings/BackgroundAgentSection.js +46 -0
  137. package/dist/client/settings/BackgroundAgentSection.js.map +1 -0
  138. package/dist/client/settings/BrowserSection.d.ts +2 -0
  139. package/dist/client/settings/BrowserSection.d.ts.map +1 -0
  140. package/dist/client/settings/BrowserSection.js +10 -0
  141. package/dist/client/settings/BrowserSection.js.map +1 -0
  142. package/dist/client/settings/ComingSoonSection.d.ts +13 -0
  143. package/dist/client/settings/ComingSoonSection.d.ts.map +1 -0
  144. package/dist/client/settings/ComingSoonSection.js +9 -0
  145. package/dist/client/settings/ComingSoonSection.js.map +1 -0
  146. package/dist/client/settings/LLMSection.d.ts +2 -0
  147. package/dist/client/settings/LLMSection.d.ts.map +1 -0
  148. package/dist/client/settings/LLMSection.js +64 -0
  149. package/dist/client/settings/LLMSection.js.map +1 -0
  150. package/dist/client/settings/SettingsPanel.d.ts +8 -0
  151. package/dist/client/settings/SettingsPanel.d.ts.map +1 -0
  152. package/dist/client/settings/SettingsPanel.js +111 -0
  153. package/dist/client/settings/SettingsPanel.js.map +1 -0
  154. package/dist/client/settings/SettingsSection.d.ts +19 -0
  155. package/dist/client/settings/SettingsSection.d.ts.map +1 -0
  156. package/dist/client/settings/SettingsSection.js +10 -0
  157. package/dist/client/settings/SettingsSection.js.map +1 -0
  158. package/dist/client/settings/UsageSection.d.ts +2 -0
  159. package/dist/client/settings/UsageSection.d.ts.map +1 -0
  160. package/dist/client/settings/UsageSection.js +70 -0
  161. package/dist/client/settings/UsageSection.js.map +1 -0
  162. package/dist/client/settings/index.d.ts +3 -0
  163. package/dist/client/settings/index.d.ts.map +1 -0
  164. package/dist/client/settings/index.js +3 -0
  165. package/dist/client/settings/index.js.map +1 -0
  166. package/dist/client/settings/useBuilderStatus.d.ts +22 -0
  167. package/dist/client/settings/useBuilderStatus.d.ts.map +1 -0
  168. package/dist/client/settings/useBuilderStatus.js +41 -0
  169. package/dist/client/settings/useBuilderStatus.js.map +1 -0
  170. package/dist/client/use-action.d.ts.map +1 -1
  171. package/dist/client/use-action.js +67 -4
  172. package/dist/client/use-action.js.map +1 -1
  173. package/dist/client/use-db-sync.d.ts +25 -2
  174. package/dist/client/use-db-sync.d.ts.map +1 -1
  175. package/dist/client/use-db-sync.js +62 -1
  176. package/dist/client/use-db-sync.js.map +1 -1
  177. package/dist/client/use-dev-mode.d.ts.map +1 -1
  178. package/dist/client/use-dev-mode.js +16 -1
  179. package/dist/client/use-dev-mode.js.map +1 -1
  180. package/dist/db/client.d.ts +12 -0
  181. package/dist/db/client.d.ts.map +1 -1
  182. package/dist/db/client.js +89 -2
  183. package/dist/db/client.js.map +1 -1
  184. package/dist/db/create-get-db.d.ts +11 -0
  185. package/dist/db/create-get-db.d.ts.map +1 -1
  186. package/dist/db/create-get-db.js +47 -3
  187. package/dist/db/create-get-db.js.map +1 -1
  188. package/dist/db/migrations.d.ts.map +1 -1
  189. package/dist/db/migrations.js +62 -5
  190. package/dist/db/migrations.js.map +1 -1
  191. package/dist/deploy/build.js +198 -54
  192. package/dist/deploy/build.js.map +1 -1
  193. package/dist/deploy/route-discovery.d.ts +5 -0
  194. package/dist/deploy/route-discovery.d.ts.map +1 -1
  195. package/dist/deploy/route-discovery.js +38 -7
  196. package/dist/deploy/route-discovery.js.map +1 -1
  197. package/dist/deploy/workspace-core.d.ts +28 -0
  198. package/dist/deploy/workspace-core.d.ts.map +1 -0
  199. package/dist/deploy/workspace-core.js +223 -0
  200. package/dist/deploy/workspace-core.js.map +1 -0
  201. package/dist/deploy/workspace-deploy.d.ts +11 -0
  202. package/dist/deploy/workspace-deploy.d.ts.map +1 -0
  203. package/dist/deploy/workspace-deploy.js +148 -0
  204. package/dist/deploy/workspace-deploy.js.map +1 -0
  205. package/dist/file-upload/builder.d.ts +11 -0
  206. package/dist/file-upload/builder.d.ts.map +1 -0
  207. package/dist/file-upload/builder.js +53 -0
  208. package/dist/file-upload/builder.js.map +1 -0
  209. package/dist/file-upload/index.d.ts +4 -0
  210. package/dist/file-upload/index.d.ts.map +1 -0
  211. package/dist/file-upload/index.js +3 -0
  212. package/dist/file-upload/index.js.map +1 -0
  213. package/dist/file-upload/registry.d.ts +23 -0
  214. package/dist/file-upload/registry.d.ts.map +1 -0
  215. package/dist/file-upload/registry.js +52 -0
  216. package/dist/file-upload/registry.js.map +1 -0
  217. package/dist/file-upload/types.d.ts +37 -0
  218. package/dist/file-upload/types.d.ts.map +1 -0
  219. package/dist/file-upload/types.js +10 -0
  220. package/dist/file-upload/types.js.map +1 -0
  221. package/dist/index.d.ts +1 -0
  222. package/dist/index.d.ts.map +1 -1
  223. package/dist/index.js +2 -0
  224. package/dist/index.js.map +1 -1
  225. package/dist/integrations/adapters/google-docs.d.ts +89 -0
  226. package/dist/integrations/adapters/google-docs.d.ts.map +1 -0
  227. package/dist/integrations/adapters/google-docs.js +261 -0
  228. package/dist/integrations/adapters/google-docs.js.map +1 -0
  229. package/dist/integrations/adapters/slack.d.ts.map +1 -1
  230. package/dist/integrations/adapters/slack.js +34 -0
  231. package/dist/integrations/adapters/slack.js.map +1 -1
  232. package/dist/integrations/adapters/telegram.d.ts.map +1 -1
  233. package/dist/integrations/adapters/telegram.js +32 -0
  234. package/dist/integrations/adapters/telegram.js.map +1 -1
  235. package/dist/integrations/google-docs-poller.d.ts +54 -0
  236. package/dist/integrations/google-docs-poller.d.ts.map +1 -0
  237. package/dist/integrations/google-docs-poller.js +442 -0
  238. package/dist/integrations/google-docs-poller.js.map +1 -0
  239. package/dist/integrations/index.d.ts +2 -0
  240. package/dist/integrations/index.d.ts.map +1 -1
  241. package/dist/integrations/index.js +3 -0
  242. package/dist/integrations/index.js.map +1 -1
  243. package/dist/integrations/plugin.d.ts.map +1 -1
  244. package/dist/integrations/plugin.js +49 -2
  245. package/dist/integrations/plugin.js.map +1 -1
  246. package/dist/integrations/types.d.ts +33 -0
  247. package/dist/integrations/types.d.ts.map +1 -1
  248. package/dist/integrations/webhook-handler.d.ts +10 -1
  249. package/dist/integrations/webhook-handler.d.ts.map +1 -1
  250. package/dist/integrations/webhook-handler.js +13 -3
  251. package/dist/integrations/webhook-handler.js.map +1 -1
  252. package/dist/jobs/scheduler.d.ts +3 -0
  253. package/dist/jobs/scheduler.d.ts.map +1 -1
  254. package/dist/jobs/scheduler.js +87 -61
  255. package/dist/jobs/scheduler.js.map +1 -1
  256. package/dist/jobs/tools.d.ts.map +1 -1
  257. package/dist/jobs/tools.js +20 -3
  258. package/dist/jobs/tools.js.map +1 -1
  259. package/dist/mcp-client/config.d.ts +46 -0
  260. package/dist/mcp-client/config.d.ts.map +1 -0
  261. package/dist/mcp-client/config.js +152 -0
  262. package/dist/mcp-client/config.js.map +1 -0
  263. package/dist/mcp-client/index.d.ts +17 -0
  264. package/dist/mcp-client/index.d.ts.map +1 -0
  265. package/dist/mcp-client/index.js +53 -0
  266. package/dist/mcp-client/index.js.map +1 -0
  267. package/dist/mcp-client/manager.d.ts +76 -0
  268. package/dist/mcp-client/manager.d.ts.map +1 -0
  269. package/dist/mcp-client/manager.js +212 -0
  270. package/dist/mcp-client/manager.js.map +1 -0
  271. package/dist/oauth-tokens/google-refresh.d.ts +31 -0
  272. package/dist/oauth-tokens/google-refresh.d.ts.map +1 -0
  273. package/dist/oauth-tokens/google-refresh.js +115 -0
  274. package/dist/oauth-tokens/google-refresh.js.map +1 -0
  275. package/dist/oauth-tokens/index.d.ts +1 -0
  276. package/dist/oauth-tokens/index.d.ts.map +1 -1
  277. package/dist/oauth-tokens/index.js +1 -0
  278. package/dist/oauth-tokens/index.js.map +1 -1
  279. package/dist/oauth-tokens/store.d.ts.map +1 -1
  280. package/dist/oauth-tokens/store.js +3 -1
  281. package/dist/oauth-tokens/store.js.map +1 -1
  282. package/dist/onboarding/default-steps.d.ts +10 -0
  283. package/dist/onboarding/default-steps.d.ts.map +1 -0
  284. package/dist/onboarding/default-steps.js +203 -0
  285. package/dist/onboarding/default-steps.js.map +1 -0
  286. package/dist/onboarding/index.d.ts +12 -0
  287. package/dist/onboarding/index.d.ts.map +1 -0
  288. package/dist/onboarding/index.js +11 -0
  289. package/dist/onboarding/index.js.map +1 -0
  290. package/dist/onboarding/plugin.d.ts +19 -0
  291. package/dist/onboarding/plugin.d.ts.map +1 -0
  292. package/dist/onboarding/plugin.js +147 -0
  293. package/dist/onboarding/plugin.js.map +1 -0
  294. package/dist/onboarding/registry.d.ts +24 -0
  295. package/dist/onboarding/registry.d.ts.map +1 -0
  296. package/dist/onboarding/registry.js +40 -0
  297. package/dist/onboarding/registry.js.map +1 -0
  298. package/dist/onboarding/types.d.ts +71 -0
  299. package/dist/onboarding/types.d.ts.map +1 -0
  300. package/dist/onboarding/types.js +10 -0
  301. package/dist/onboarding/types.js.map +1 -0
  302. package/dist/org/context.js +1 -1
  303. package/dist/org/handlers.d.ts.map +1 -1
  304. package/dist/org/handlers.js +35 -10
  305. package/dist/org/handlers.js.map +1 -1
  306. package/dist/org/plugin.d.ts.map +1 -1
  307. package/dist/org/plugin.js +37 -22
  308. package/dist/org/plugin.js.map +1 -1
  309. package/dist/resources/agents.d.ts +4 -0
  310. package/dist/resources/agents.d.ts.map +1 -0
  311. package/dist/resources/agents.js +44 -0
  312. package/dist/resources/agents.js.map +1 -0
  313. package/dist/resources/handlers.d.ts +17 -0
  314. package/dist/resources/handlers.d.ts.map +1 -1
  315. package/dist/resources/handlers.js +49 -12
  316. package/dist/resources/handlers.js.map +1 -1
  317. package/dist/resources/metadata.d.ts +48 -0
  318. package/dist/resources/metadata.d.ts.map +1 -0
  319. package/dist/resources/metadata.js +150 -0
  320. package/dist/resources/metadata.js.map +1 -0
  321. package/dist/resources/script-helpers.d.ts.map +1 -1
  322. package/dist/resources/script-helpers.js +3 -2
  323. package/dist/resources/script-helpers.js.map +1 -1
  324. package/dist/resources/store.d.ts.map +1 -1
  325. package/dist/resources/store.js +59 -18
  326. package/dist/resources/store.js.map +1 -1
  327. package/dist/scripts/call-agent.d.ts.map +1 -1
  328. package/dist/scripts/call-agent.js +3 -2
  329. package/dist/scripts/call-agent.js.map +1 -1
  330. package/dist/scripts/chat/search-chats.d.ts.map +1 -1
  331. package/dist/scripts/chat/search-chats.js +2 -1
  332. package/dist/scripts/chat/search-chats.js.map +1 -1
  333. package/dist/scripts/core-scripts.d.ts.map +1 -1
  334. package/dist/scripts/core-scripts.js +2 -0
  335. package/dist/scripts/core-scripts.js.map +1 -1
  336. package/dist/scripts/db/patch.d.ts.map +1 -1
  337. package/dist/scripts/db/patch.js +273 -11
  338. package/dist/scripts/db/patch.js.map +1 -1
  339. package/dist/scripts/db/scoping.d.ts.map +1 -1
  340. package/dist/scripts/db/scoping.js +3 -2
  341. package/dist/scripts/db/scoping.js.map +1 -1
  342. package/dist/scripts/docs/index.d.ts +2 -0
  343. package/dist/scripts/docs/index.d.ts.map +1 -0
  344. package/dist/scripts/docs/index.js +4 -0
  345. package/dist/scripts/docs/index.js.map +1 -0
  346. package/dist/scripts/docs/search.d.ts +13 -0
  347. package/dist/scripts/docs/search.d.ts.map +1 -0
  348. package/dist/scripts/docs/search.js +130 -0
  349. package/dist/scripts/docs/search.js.map +1 -0
  350. package/dist/scripts/resources/delete-memory.d.ts +7 -0
  351. package/dist/scripts/resources/delete-memory.d.ts.map +1 -0
  352. package/dist/scripts/resources/delete-memory.js +49 -0
  353. package/dist/scripts/resources/delete-memory.js.map +1 -0
  354. package/dist/scripts/resources/delete.d.ts.map +1 -1
  355. package/dist/scripts/resources/delete.js +2 -1
  356. package/dist/scripts/resources/delete.js.map +1 -1
  357. package/dist/scripts/resources/index.d.ts.map +1 -1
  358. package/dist/scripts/resources/index.js +2 -0
  359. package/dist/scripts/resources/index.js.map +1 -1
  360. package/dist/scripts/resources/list.d.ts.map +1 -1
  361. package/dist/scripts/resources/list.js +2 -1
  362. package/dist/scripts/resources/list.js.map +1 -1
  363. package/dist/scripts/resources/migrate-learnings.d.ts.map +1 -1
  364. package/dist/scripts/resources/migrate-learnings.js +2 -1
  365. package/dist/scripts/resources/migrate-learnings.js.map +1 -1
  366. package/dist/scripts/resources/read.d.ts.map +1 -1
  367. package/dist/scripts/resources/read.js +2 -1
  368. package/dist/scripts/resources/read.js.map +1 -1
  369. package/dist/scripts/resources/save-memory.d.ts +9 -0
  370. package/dist/scripts/resources/save-memory.d.ts.map +1 -0
  371. package/dist/scripts/resources/save-memory.js +78 -0
  372. package/dist/scripts/resources/save-memory.js.map +1 -0
  373. package/dist/scripts/resources/write.d.ts.map +1 -1
  374. package/dist/scripts/resources/write.js +2 -1
  375. package/dist/scripts/resources/write.js.map +1 -1
  376. package/dist/scripts/utils.d.ts +10 -1
  377. package/dist/scripts/utils.d.ts.map +1 -1
  378. package/dist/scripts/utils.js +45 -2
  379. package/dist/scripts/utils.js.map +1 -1
  380. package/dist/server/action-discovery.d.ts +5 -0
  381. package/dist/server/action-discovery.d.ts.map +1 -1
  382. package/dist/server/action-discovery.js +53 -20
  383. package/dist/server/action-discovery.js.map +1 -1
  384. package/dist/server/action-routes.d.ts.map +1 -1
  385. package/dist/server/action-routes.js +88 -56
  386. package/dist/server/action-routes.js.map +1 -1
  387. package/dist/server/agent-chat-plugin.d.ts +15 -0
  388. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  389. package/dist/server/agent-chat-plugin.js +853 -91
  390. package/dist/server/agent-chat-plugin.js.map +1 -1
  391. package/dist/server/agent-discovery.d.ts.map +1 -1
  392. package/dist/server/agent-discovery.js +13 -25
  393. package/dist/server/agent-discovery.js.map +1 -1
  394. package/dist/server/agent-teams.d.ts.map +1 -1
  395. package/dist/server/agent-teams.js +23 -59
  396. package/dist/server/agent-teams.js.map +1 -1
  397. package/dist/server/agents-bundle.d.ts +33 -5
  398. package/dist/server/agents-bundle.d.ts.map +1 -1
  399. package/dist/server/agents-bundle.js +108 -64
  400. package/dist/server/agents-bundle.js.map +1 -1
  401. package/dist/server/auth.d.ts +7 -0
  402. package/dist/server/auth.d.ts.map +1 -1
  403. package/dist/server/auth.js +448 -93
  404. package/dist/server/auth.js.map +1 -1
  405. package/dist/server/better-auth-instance.d.ts +1 -1
  406. package/dist/server/better-auth-instance.d.ts.map +1 -1
  407. package/dist/server/better-auth-instance.js +272 -10
  408. package/dist/server/better-auth-instance.js.map +1 -1
  409. package/dist/server/builder-browser.d.ts +61 -0
  410. package/dist/server/builder-browser.d.ts.map +1 -0
  411. package/dist/server/builder-browser.js +229 -0
  412. package/dist/server/builder-browser.js.map +1 -0
  413. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  414. package/dist/server/core-routes-plugin.js +273 -9
  415. package/dist/server/core-routes-plugin.js.map +1 -1
  416. package/dist/server/credential-provider.d.ts +37 -0
  417. package/dist/server/credential-provider.d.ts.map +1 -0
  418. package/dist/server/credential-provider.js +49 -0
  419. package/dist/server/credential-provider.js.map +1 -0
  420. package/dist/server/desktop-sso.d.ts +30 -0
  421. package/dist/server/desktop-sso.d.ts.map +1 -0
  422. package/dist/server/desktop-sso.js +74 -0
  423. package/dist/server/desktop-sso.js.map +1 -0
  424. package/dist/server/email.d.ts +23 -0
  425. package/dist/server/email.d.ts.map +1 -0
  426. package/dist/server/email.js +105 -0
  427. package/dist/server/email.js.map +1 -0
  428. package/dist/server/framework-request-handler.d.ts.map +1 -1
  429. package/dist/server/framework-request-handler.js +71 -3
  430. package/dist/server/framework-request-handler.js.map +1 -1
  431. package/dist/server/google-auth-plugin.js +1 -1
  432. package/dist/server/google-oauth.d.ts +1 -1
  433. package/dist/server/google-oauth.d.ts.map +1 -1
  434. package/dist/server/google-oauth.js +34 -13
  435. package/dist/server/google-oauth.js.map +1 -1
  436. package/dist/server/index.d.ts +3 -0
  437. package/dist/server/index.d.ts.map +1 -1
  438. package/dist/server/index.js +3 -0
  439. package/dist/server/index.js.map +1 -1
  440. package/dist/server/local-migration.d.ts +9 -0
  441. package/dist/server/local-migration.d.ts.map +1 -1
  442. package/dist/server/local-migration.js +44 -14
  443. package/dist/server/local-migration.js.map +1 -1
  444. package/dist/server/oauth-helpers.d.ts +3 -0
  445. package/dist/server/oauth-helpers.d.ts.map +1 -1
  446. package/dist/server/oauth-helpers.js +7 -4
  447. package/dist/server/oauth-helpers.js.map +1 -1
  448. package/dist/server/onboarding-html.d.ts +6 -0
  449. package/dist/server/onboarding-html.d.ts.map +1 -1
  450. package/dist/server/onboarding-html.js +323 -28
  451. package/dist/server/onboarding-html.js.map +1 -1
  452. package/dist/server/poll.d.ts.map +1 -1
  453. package/dist/server/poll.js +48 -0
  454. package/dist/server/poll.js.map +1 -1
  455. package/dist/server/request-context.d.ts +20 -0
  456. package/dist/server/request-context.d.ts.map +1 -0
  457. package/dist/server/request-context.js +41 -0
  458. package/dist/server/request-context.js.map +1 -0
  459. package/dist/templates/default/.agents/skills/actions/SKILL.md +2 -1
  460. package/dist/templates/default/.agents/skills/inline-embeds/SKILL.md +88 -0
  461. package/dist/templates/default/.agents/skills/security/SKILL.md +145 -40
  462. package/dist/templates/default/.agents/skills/storing-data/SKILL.md +7 -1
  463. package/dist/templates/default/_gitignore +1 -0
  464. package/dist/templates/default/app/root.tsx +4 -1
  465. package/dist/templates/workspace-core/.agents/skills/company-policies/SKILL.md +42 -0
  466. package/dist/templates/workspace-core/AGENTS.md +62 -0
  467. package/dist/templates/workspace-core/actions/company-directory.ts +38 -0
  468. package/dist/templates/workspace-core/package.json +39 -0
  469. package/dist/templates/workspace-core/src/client/AuthenticatedLayout.tsx +37 -0
  470. package/dist/templates/workspace-core/src/client/index.ts +26 -0
  471. package/dist/templates/workspace-core/src/credentials.ts +29 -0
  472. package/dist/templates/workspace-core/src/index.ts +21 -0
  473. package/dist/templates/workspace-core/src/server/agent-chat-plugin.ts +30 -0
  474. package/dist/templates/workspace-core/src/server/auth-plugin.ts +35 -0
  475. package/dist/templates/workspace-core/src/server/index.ts +22 -0
  476. package/dist/templates/workspace-core/tailwind.preset.ts +34 -0
  477. package/dist/templates/workspace-core/tsconfig.json +9 -0
  478. package/dist/templates/workspace-root/.env.example +37 -0
  479. package/dist/templates/workspace-root/README.md +62 -0
  480. package/dist/templates/workspace-root/_gitignore +23 -0
  481. package/dist/templates/workspace-root/package.json +18 -0
  482. package/dist/templates/workspace-root/pnpm-workspace.yaml +3 -0
  483. package/dist/templates/workspace-root/tsconfig.base.json +21 -0
  484. package/dist/usage/store.d.ts +74 -12
  485. package/dist/usage/store.d.ts.map +1 -1
  486. package/dist/usage/store.js +210 -44
  487. package/dist/usage/store.js.map +1 -1
  488. package/dist/vite/agents-bundle-plugin.d.ts.map +1 -1
  489. package/dist/vite/agents-bundle-plugin.js +65 -15
  490. package/dist/vite/agents-bundle-plugin.js.map +1 -1
  491. package/dist/vite/client.d.ts +16 -0
  492. package/dist/vite/client.d.ts.map +1 -1
  493. package/dist/vite/client.js +130 -0
  494. package/dist/vite/client.js.map +1 -1
  495. package/docs/content/a2a-protocol.md +223 -0
  496. package/docs/content/actions.md +129 -0
  497. package/docs/content/agent-mentions.md +171 -0
  498. package/docs/content/authentication.md +155 -0
  499. package/docs/content/cli-adapters.md +244 -0
  500. package/docs/content/client.md +175 -0
  501. package/docs/content/context-awareness.md +168 -0
  502. package/docs/content/creating-templates.md +311 -0
  503. package/docs/content/database.md +82 -0
  504. package/docs/content/deployment.md +237 -0
  505. package/docs/content/enterprise-workspace.md +235 -0
  506. package/docs/content/faq.md +101 -0
  507. package/docs/content/file-uploads.md +102 -0
  508. package/docs/content/frames.md +47 -0
  509. package/docs/content/getting-started.md +104 -0
  510. package/docs/content/integrations.md +198 -0
  511. package/docs/content/key-concepts.md +246 -0
  512. package/docs/content/mcp-clients.md +110 -0
  513. package/docs/content/mcp-protocol.md +168 -0
  514. package/docs/content/onboarding.md +107 -0
  515. package/docs/content/real-time-collaboration.md +185 -0
  516. package/docs/content/resources.md +277 -0
  517. package/docs/content/security.md +158 -0
  518. package/docs/content/server.md +200 -0
  519. package/docs/content/skills-guide.md +107 -0
  520. package/docs/content/what-is-agent-native.md +100 -0
  521. package/docs/content/workspace-management.md +224 -0
  522. package/package.json +13 -3
  523. package/src/templates/default/.agents/skills/actions/SKILL.md +2 -1
  524. package/src/templates/default/.agents/skills/inline-embeds/SKILL.md +88 -0
  525. package/src/templates/default/.agents/skills/security/SKILL.md +145 -40
  526. package/src/templates/default/.agents/skills/storing-data/SKILL.md +7 -1
  527. package/src/templates/default/_gitignore +1 -0
  528. package/src/templates/default/app/root.tsx +4 -1
  529. package/src/templates/workspace-core/.agents/skills/company-policies/SKILL.md +42 -0
  530. package/src/templates/workspace-core/AGENTS.md +62 -0
  531. package/src/templates/workspace-core/actions/company-directory.ts +38 -0
  532. package/src/templates/workspace-core/package.json +39 -0
  533. package/src/templates/workspace-core/src/client/AuthenticatedLayout.tsx +37 -0
  534. package/src/templates/workspace-core/src/client/index.ts +26 -0
  535. package/src/templates/workspace-core/src/credentials.ts +29 -0
  536. package/src/templates/workspace-core/src/index.ts +21 -0
  537. package/src/templates/workspace-core/src/server/agent-chat-plugin.ts +30 -0
  538. package/src/templates/workspace-core/src/server/auth-plugin.ts +35 -0
  539. package/src/templates/workspace-core/src/server/index.ts +22 -0
  540. package/src/templates/workspace-core/tailwind.preset.ts +34 -0
  541. package/src/templates/workspace-core/tsconfig.json +9 -0
  542. package/src/templates/workspace-root/.env.example +37 -0
  543. package/src/templates/workspace-root/README.md +62 -0
  544. package/src/templates/workspace-root/_gitignore +23 -0
  545. package/src/templates/workspace-root/package.json +18 -0
  546. package/src/templates/workspace-root/pnpm-workspace.yaml +3 -0
  547. package/src/templates/workspace-root/tsconfig.base.json +21 -0
  548. package/dist/templates/templates/default/.agents/skills/actions/SKILL.md +0 -142
  549. package/dist/templates/templates/default/.agents/skills/agent-engines/SKILL.md +0 -127
  550. package/dist/templates/templates/default/.agents/skills/capture-learnings/SKILL.md +0 -50
  551. package/dist/templates/templates/default/.agents/skills/create-skill/SKILL.md +0 -167
  552. package/dist/templates/templates/default/.agents/skills/delegate-to-agent/SKILL.md +0 -90
  553. package/dist/templates/templates/default/.agents/skills/frontend-design/SKILL.md +0 -69
  554. package/dist/templates/templates/default/.agents/skills/real-time-collab/SKILL.md +0 -183
  555. package/dist/templates/templates/default/.agents/skills/real-time-sync/SKILL.md +0 -112
  556. package/dist/templates/templates/default/.agents/skills/security/SKILL.md +0 -108
  557. package/dist/templates/templates/default/.agents/skills/self-modifying-code/SKILL.md +0 -79
  558. package/dist/templates/templates/default/.agents/skills/storing-data/SKILL.md +0 -110
  559. package/dist/templates/templates/default/.claude/settings.json +0 -100
  560. package/dist/templates/templates/default/.env.example +0 -5
  561. package/dist/templates/templates/default/.ignore +0 -0
  562. package/dist/templates/templates/default/.prettierrc +0 -5
  563. package/dist/templates/templates/default/AGENTS.md +0 -110
  564. package/dist/templates/templates/default/DEVELOPING.md +0 -117
  565. package/dist/templates/templates/default/_gitignore +0 -37
  566. package/dist/templates/templates/default/actions/hello.ts +0 -20
  567. package/dist/templates/templates/default/actions/navigate.ts +0 -53
  568. package/dist/templates/templates/default/actions/run.ts +0 -2
  569. package/dist/templates/templates/default/actions/view-screen.ts +0 -39
  570. package/dist/templates/templates/default/app/entry.client.tsx +0 -4
  571. package/dist/templates/templates/default/app/entry.server.tsx +0 -56
  572. package/dist/templates/templates/default/app/global.css +0 -95
  573. package/dist/templates/templates/default/app/lib/utils.ts +0 -1
  574. package/dist/templates/templates/default/app/root.tsx +0 -107
  575. package/dist/templates/templates/default/app/routes/_index.tsx +0 -62
  576. package/dist/templates/templates/default/app/routes.ts +0 -4
  577. package/dist/templates/templates/default/app/vite-env.d.ts +0 -6
  578. package/dist/templates/templates/default/components.json +0 -20
  579. package/dist/templates/templates/default/data/.gitkeep +0 -0
  580. package/dist/templates/templates/default/data/sync-config.json +0 -1
  581. package/dist/templates/templates/default/learnings.defaults.md +0 -5
  582. package/dist/templates/templates/default/learnings.md +0 -0
  583. package/dist/templates/templates/default/package.json +0 -46
  584. package/dist/templates/templates/default/postcss.config.js +0 -6
  585. package/dist/templates/templates/default/public/icon-180.svg +0 -4
  586. package/dist/templates/templates/default/public/icon-192.svg +0 -4
  587. package/dist/templates/templates/default/public/icon-512.svg +0 -4
  588. package/dist/templates/templates/default/public/manifest.json +0 -13
  589. package/dist/templates/templates/default/react-router.config.ts +0 -6
  590. package/dist/templates/templates/default/server/middleware/auth.ts +0 -15
  591. package/dist/templates/templates/default/server/plugins/.gitkeep +0 -0
  592. package/dist/templates/templates/default/server/routes/[...page].get.ts +0 -5
  593. package/dist/templates/templates/default/server/routes/api/hello.get.ts +0 -5
  594. package/dist/templates/templates/default/shared/api.ts +0 -6
  595. package/dist/templates/templates/default/ssr-entry.ts +0 -20
  596. package/dist/templates/templates/default/tailwind.config.ts +0 -7
  597. package/dist/templates/templates/default/tsconfig.json +0 -11
  598. package/dist/templates/templates/default/vite.config.ts +0 -6
@@ -1,15 +1,20 @@
1
+ import { runWithRequestContext, getRequestOrgId } from "./request-context.js";
2
+ import { getSetting, putSetting } from "../settings/store.js";
1
3
  import { getH3App } from "./framework-request-handler.js";
2
4
  import { createProductionAgentHandler, runAgentLoop, actionsToEngineTools, getActiveRunForThreadAsync, abortRun, subscribeToRun, } from "../agent/production-agent.js";
3
5
  import { resolveEngine, createAnthropicEngine } from "../agent/engine/index.js";
6
+ import { McpClientManager, loadMcpConfig, autoDetectMcpConfig, mcpToolsToActionEntries, } from "../mcp-client/index.js";
4
7
  import { discoverAgents } from "./agent-discovery.js";
5
8
  import { loadSchemaPromptBlock } from "./schema-prompt.js";
6
9
  import { buildAssistantMessage, extractThreadMeta, } from "../agent/thread-data-builder.js";
7
10
  import { defineEventHandler, setResponseStatus, setResponseHeader, getMethod, getQuery, } from "h3";
8
11
  import { getSession } from "./auth.js";
12
+ import { getOrigin } from "./google-oauth.js";
9
13
  import { createThread, getThread, listThreads, searchThreads, updateThreadData, deleteThread, } from "../chat-threads/store.js";
10
14
  import { resourceListAccessible, resourceList, resourceGet, resourceGetByPath, ensurePersonalDefaults, SHARED_OWNER, } from "../resources/store.js";
11
15
  import nodePath from "node:path";
12
16
  import { readBody } from "./h3-helpers.js";
17
+ import { getBuilderBrowserConnectUrl, requestBuilderBrowserConnection, } from "./builder-browser.js";
13
18
  // Lazy fs — loaded via dynamic import() on first use.
14
19
  // This avoids require() which bundlers convert to createRequire(import.meta.url)
15
20
  // that crashes on CF Workers where import.meta.url is undefined.
@@ -24,9 +29,10 @@ async function lazyFs() {
24
29
  * Wraps a core CLI script (that writes to console.log) as a ActionEntry
25
30
  * by capturing stdout.
26
31
  */
27
- function wrapCliScript(tool, cliDefault) {
32
+ function wrapCliScript(tool, cliDefault, opts) {
28
33
  return {
29
34
  tool,
35
+ ...(opts?.readOnly ? { readOnly: true } : {}),
30
36
  run: async (args) => {
31
37
  const cliArgs = [];
32
38
  for (const [k, v] of Object.entries(args)) {
@@ -68,16 +74,301 @@ function wrapCliScript(tool, cliDefault) {
68
74
  },
69
75
  };
70
76
  }
77
+ /**
78
+ * Creates the `refresh-screen` tool. Writes a bump to `application_state`
79
+ * under a well-known key; the client's `useDbSync` watches for this and
80
+ * invalidates react-query caches so the on-screen UI re-fetches its data
81
+ * without a full page reload.
82
+ *
83
+ * This is the standard way for the agent to say "the data on the screen
84
+ * just changed, please refresh it" — e.g. after editing a dashboard config,
85
+ * updating a form schema, or mutating a row that the current view renders.
86
+ */
87
+ function createRefreshScreenEntry() {
88
+ return {
89
+ "refresh-screen": {
90
+ // Writes __screen_refresh__ to application_state, which emits its own
91
+ // distinct `screen-refresh` poll event. Don't double-emit a generic
92
+ // `action` event on top of that.
93
+ readOnly: true,
94
+ tool: {
95
+ description: "Manually refresh the user's current screen. The framework ALREADY auto-refreshes after any successful mutating action tool call (template actions, db-exec, db-patch) — you do NOT need to call this after a normal action. Use it only when (a) you mutated data via a path the framework can't detect (e.g. a direct write to an external system the app mirrors), or (b) you want to pass a `scope` hint so the UI narrows which queries to refetch. The UI re-fetches its queries without a full page reload.",
96
+ parameters: {
97
+ type: "object",
98
+ properties: {
99
+ scope: {
100
+ type: "string",
101
+ description: "Optional hint describing what changed (e.g. 'dashboard', 'form', 'settings'). Templates may use it to narrow which queries to invalidate; if omitted, all queries are invalidated.",
102
+ },
103
+ },
104
+ },
105
+ },
106
+ run: async (args) => {
107
+ const { writeAppState } = await import("../application-state/script-helpers.js");
108
+ const nonce = Date.now();
109
+ const scope = typeof args?.scope === "string" ? args.scope : undefined;
110
+ await writeAppState(SCREEN_REFRESH_KEY, {
111
+ nonce,
112
+ ...(scope ? { scope } : {}),
113
+ });
114
+ return `refreshed${scope ? ` (scope: ${scope})` : ""}`;
115
+ },
116
+ },
117
+ };
118
+ }
119
+ /** Well-known application-state key used by the refresh-screen tool. */
120
+ const SCREEN_REFRESH_KEY = "__screen_refresh__";
121
+ /**
122
+ * Creates the `set-search-params` / `set-url-path` tools. Writes a one-shot
123
+ * URL command to application_state; the client's URLSync component applies
124
+ * it via react-router (no full page reload) and then deletes the command.
125
+ *
126
+ * This is how the agent edits URL state — filter query params, route
127
+ * changes, hash — without needing a per-template navigate action. The
128
+ * current URL is visible to the agent via the auto-injected `<current-url>`
129
+ * block, which includes parsed search params.
130
+ */
131
+ function createUrlTools() {
132
+ return {
133
+ "set-search-params": {
134
+ // Writes __set_url__ to application_state, which the app-state watcher
135
+ // already surfaces as a poll event. No need to double-emit.
136
+ readOnly: true,
137
+ tool: {
138
+ description: "Update the URL query string on the user's current page. Use this to change dashboard/list filters, search terms, or any other state the app stores in `?foo=bar` style query params. One-shot — the UI applies it in ~1s without a page reload. See the current URL + parsed search params in the auto-injected `<current-url>` block. Keys are the exact query param names as they appear in the URL (e.g. `f_pubDateStart`, not just `pubDateStart`). Set a value to null or empty string to clear that param. By default merges over existing params — pass `merge: false` to replace them all.",
139
+ parameters: {
140
+ type: "object",
141
+ properties: {
142
+ params: {
143
+ type: "object",
144
+ description: 'Map of query param → value. Each value is a string, or null/"" to clear. Example: {"f_pubDateStart": null, "f_cadence": "MONTH"}.',
145
+ },
146
+ merge: {
147
+ type: "string",
148
+ description: '"true" (default) merges over existing params; "false" replaces them entirely.',
149
+ enum: ["true", "false"],
150
+ },
151
+ },
152
+ required: ["params"],
153
+ },
154
+ },
155
+ run: async (args) => {
156
+ const params = (args?.params ?? {});
157
+ const merge = args?.merge !== "false";
158
+ const { writeAppState } = await import("../application-state/script-helpers.js");
159
+ await writeAppState("__set_url__", {
160
+ searchParams: params,
161
+ mergeSearchParams: merge,
162
+ });
163
+ const keys = Object.keys(params);
164
+ return `set-search-params: ${keys.length} key${keys.length === 1 ? "" : "s"}${merge ? "" : " (replace)"}`;
165
+ },
166
+ },
167
+ "set-url-path": {
168
+ // Same as set-search-params — writes application_state, already emits
169
+ // via the app-state watcher.
170
+ readOnly: true,
171
+ tool: {
172
+ description: "Navigate the user to a different pathname, optionally also setting search params. For most template-specific routing prefer the template's `navigate` action if it exists — this is the generic fallback. One-shot, applied by the client without a page reload.",
173
+ parameters: {
174
+ type: "object",
175
+ properties: {
176
+ pathname: {
177
+ type: "string",
178
+ description: "New URL pathname (e.g. '/adhoc/weekly').",
179
+ },
180
+ params: {
181
+ type: "object",
182
+ description: 'Optional query params to set alongside the path change. String values set, null/"" clears.',
183
+ },
184
+ merge: {
185
+ type: "string",
186
+ description: '"true" (default) merges over existing params; "false" starts fresh.',
187
+ enum: ["true", "false"],
188
+ },
189
+ },
190
+ required: ["pathname"],
191
+ },
192
+ },
193
+ run: async (args) => {
194
+ const pathname = String(args?.pathname ?? "");
195
+ if (!pathname.startsWith("/")) {
196
+ return "Error: pathname must start with '/'.";
197
+ }
198
+ const params = (args?.params ?? {});
199
+ const merge = args?.merge !== "false";
200
+ const { writeAppState } = await import("../application-state/script-helpers.js");
201
+ await writeAppState("__set_url__", {
202
+ pathname,
203
+ searchParams: params,
204
+ mergeSearchParams: merge,
205
+ });
206
+ return `set-url-path: ${pathname}`;
207
+ },
208
+ },
209
+ };
210
+ }
211
+ /**
212
+ * Creates db-* tools (db-query, db-exec, db-patch, db-schema) as native tools.
213
+ * These let the agent read and write the app's own SQL database. Scoping to
214
+ * the current user/org is enforced automatically in production via temp views.
215
+ *
216
+ * In dev mode template actions are invoked via shell and the agent can call
217
+ * `pnpm action db-query ...` — but in production there is no shell, so these
218
+ * must be registered as native tools for the agent to reach the app DB at all.
219
+ */
220
+ async function createDbScriptEntries() {
221
+ try {
222
+ const [schemaMod, queryMod, execMod, patchMod] = await Promise.all([
223
+ import("../scripts/db/schema.js"),
224
+ import("../scripts/db/query.js"),
225
+ import("../scripts/db/exec.js"),
226
+ import("../scripts/db/patch.js"),
227
+ ]);
228
+ return {
229
+ "db-schema": wrapCliScript({
230
+ description: "Show the app's SQL schema — all tables, columns, types, indexes, and foreign keys. Use this to understand the data model before querying.",
231
+ parameters: {
232
+ type: "object",
233
+ properties: {
234
+ format: {
235
+ type: "string",
236
+ description: 'Output format: "json" or "text" (default: text)',
237
+ enum: ["json", "text"],
238
+ },
239
+ },
240
+ },
241
+ }, schemaMod.default, { readOnly: true }),
242
+ "db-query": wrapCliScript({
243
+ description: "Read from the app's SQL database. Runs a SELECT (or WITH/EXPLAIN/PRAGMA) against the app's own tables — settings, application_state, and all template tables. Results are automatically scoped to the current user/org; DO NOT add `WHERE owner_email = ...` yourself. This queries the APP DATABASE — not any external data source.",
244
+ parameters: {
245
+ type: "object",
246
+ properties: {
247
+ sql: {
248
+ type: "string",
249
+ description: "SELECT query to run, e.g. \"SELECT key, value FROM settings WHERE key LIKE 'sql-dashboard-%'\"",
250
+ },
251
+ format: {
252
+ type: "string",
253
+ description: 'Output format: "json" or "text" (default: text)',
254
+ enum: ["json", "text"],
255
+ },
256
+ limit: {
257
+ type: "string",
258
+ description: "Append LIMIT N if the query doesn't already have one",
259
+ },
260
+ },
261
+ required: ["sql"],
262
+ },
263
+ }, queryMod.default, { readOnly: true }),
264
+ "db-exec": wrapCliScript({
265
+ description: "Write to the app's SQL database. Runs INSERT / UPDATE / DELETE against the app's own tables. Writes are automatically scoped to the current user/org, and `owner_email` / `org_id` are auto-injected on INSERT. Use this to update rows in the settings table (e.g. edit a dashboard config stored under `o:<orgId>:sql-dashboard-<id>`). This writes to the APP DATABASE — not any external data source.",
266
+ parameters: {
267
+ type: "object",
268
+ properties: {
269
+ sql: {
270
+ type: "string",
271
+ description: "INSERT / UPDATE / DELETE statement. Use parameterized placeholders (?) if possible.",
272
+ },
273
+ },
274
+ required: ["sql"],
275
+ },
276
+ }, execMod.default),
277
+ "db-patch": wrapCliScript({
278
+ description: "Surgical patch on a large text/JSON column in the app's SQL database. Two modes: (1) text find/replace via `find`/`replace`/`edits` — best for small edits to documents, slide HTML, etc. (2) structural JSON ops via `json-ops` — STRONGLY PREFERRED when the column is JSON (dashboard configs, form schemas, slide decks) because it avoids all the brace/quote/comma surgery that text find/replace requires. Use `json-ops` to set/remove values at a JSON Pointer path, or to move/insert array items — e.g. reorder dashboard panels, add a filter, rename a field. Targets exactly one row (narrow `where` by primary key). Same per-user/org scoping as db-exec.",
279
+ parameters: {
280
+ type: "object",
281
+ properties: {
282
+ table: {
283
+ type: "string",
284
+ description: "Table name (e.g. 'settings')",
285
+ },
286
+ column: {
287
+ type: "string",
288
+ description: "Text/JSON column to patch (e.g. 'value' for settings)",
289
+ },
290
+ where: {
291
+ type: "string",
292
+ description: "WHERE clause that matches exactly one row (e.g. \"key = 'o:org1:sql-dashboard-foo'\")",
293
+ },
294
+ find: {
295
+ type: "string",
296
+ description: "Text mode: substring to find. Must match EXACTLY ONE occurrence by default (like Claude Code's Edit tool). If 0 matches, you get 'NOT FOUND'. If >1 matches, you get surrounding context for each match — widen `find` with unique context and retry. Use `all: \"true\"` to replace every occurrence.",
297
+ },
298
+ replace: {
299
+ type: "string",
300
+ description: "Text mode: replacement substring",
301
+ },
302
+ edits: {
303
+ type: "string",
304
+ description: 'Text mode batch: JSON array of {find, replace} pairs. Same uniqueness rule applies to each `find`. Example: \'[{"find":"a","replace":"b"}]\'',
305
+ },
306
+ "json-ops": {
307
+ type: "string",
308
+ description: 'JSON mode: JSON array of structural ops. Each op is {op, path, value?, from?}. `op` is one of "set", "remove", "insert", "move", "move-before". `path` / `from` use JSON Pointer ("/panels/3/title"). Examples — reorder: \'[{"op":"move","from":"/panels/7","path":"/panels/1"}]\'; edit field: \'[{"op":"set","path":"/panels/0/title","value":"New"}]\'; delete filter: \'[{"op":"remove","path":"/filters/2"}]\'; add panel: \'[{"op":"insert","path":"/panels/0","value":{"id":"p","title":"..."}}]\'. Much safer than text find/replace for JSON columns.',
309
+ },
310
+ all: {
311
+ type: "string",
312
+ description: 'Text mode: set to "true" to replace every occurrence of each `find` (default requires exactly one match)',
313
+ enum: ["true"],
314
+ },
315
+ },
316
+ required: ["table", "column", "where"],
317
+ },
318
+ }, patchMod.default),
319
+ };
320
+ }
321
+ catch {
322
+ return {};
323
+ }
324
+ }
325
+ /**
326
+ * Creates the docs-search tool so agents can look up framework documentation.
327
+ * Docs are bundled in @agent-native/core and read via fs at runtime.
328
+ */
329
+ async function createDocsScriptEntries() {
330
+ try {
331
+ const mod = await import("../scripts/docs/search.js");
332
+ return {
333
+ "docs-search": wrapCliScript({
334
+ description: "Search and read agent-native framework documentation. Use --list to see all pages, --query to search, --slug to read a specific page.",
335
+ parameters: {
336
+ type: "object",
337
+ properties: {
338
+ query: {
339
+ type: "string",
340
+ description: "Search term to find relevant docs (e.g. 'actions', 'authentication', 'database')",
341
+ },
342
+ slug: {
343
+ type: "string",
344
+ description: "Read a specific doc page by slug (e.g. 'actions', 'authentication', 'database')",
345
+ },
346
+ list: {
347
+ type: "string",
348
+ description: 'Set to "true" to list all available doc pages',
349
+ enum: ["true"],
350
+ },
351
+ },
352
+ },
353
+ }, mod.default, { readOnly: true }),
354
+ };
355
+ }
356
+ catch {
357
+ return {};
358
+ }
359
+ }
71
360
  /**
72
361
  * Creates resource ScriptEntries available in both prod and dev modes.
73
362
  */
74
363
  async function createResourceScriptEntries() {
75
364
  try {
76
- const [list, read, write, del] = await Promise.all([
365
+ const [list, read, write, del, saveMem, delMem] = await Promise.all([
77
366
  import("../scripts/resources/list.js"),
78
367
  import("../scripts/resources/read.js"),
79
368
  import("../scripts/resources/write.js"),
80
369
  import("../scripts/resources/delete.js"),
370
+ import("../scripts/resources/save-memory.js"),
371
+ import("../scripts/resources/delete-memory.js"),
81
372
  ]);
82
373
  return {
83
374
  "resource-list": wrapCliScript({
@@ -164,6 +455,45 @@ async function createResourceScriptEntries() {
164
455
  required: ["path"],
165
456
  },
166
457
  }, del.default),
458
+ "save-memory": wrapCliScript({
459
+ description: "Save a memory for future conversations. Creates or updates a memory file and its index entry. Use proactively when you learn preferences, corrections, project context, or references.",
460
+ parameters: {
461
+ type: "object",
462
+ properties: {
463
+ name: {
464
+ type: "string",
465
+ description: "Short kebab-case identifier (e.g. 'coding-style', 'deploy-process'). Used as the filename.",
466
+ },
467
+ type: {
468
+ type: "string",
469
+ description: "Memory category",
470
+ enum: ["user", "feedback", "project", "reference"],
471
+ },
472
+ description: {
473
+ type: "string",
474
+ description: "One-line summary shown in the memory index (keep under 80 chars)",
475
+ },
476
+ content: {
477
+ type: "string",
478
+ description: "The memory content in markdown. For updates, read first and provide full updated content.",
479
+ },
480
+ },
481
+ required: ["name", "type", "description", "content"],
482
+ },
483
+ }, saveMem.default),
484
+ "delete-memory": wrapCliScript({
485
+ description: "Delete a memory entry and remove it from the memory index.",
486
+ parameters: {
487
+ type: "object",
488
+ properties: {
489
+ name: {
490
+ type: "string",
491
+ description: "The memory name to delete (e.g. 'coding-style')",
492
+ },
493
+ },
494
+ required: ["name"],
495
+ },
496
+ }, delMem.default),
167
497
  };
168
498
  }
169
499
  catch {
@@ -260,6 +590,94 @@ async function createCallAgentScriptEntry(selfAppId) {
260
590
  return {};
261
591
  }
262
592
  }
593
+ function createBuilderBrowserTool(deps) {
594
+ return {
595
+ "connect-builder": {
596
+ tool: {
597
+ description: "Render a Builder.io card inline in the chat. Call this IMMEDIATELY — no exploration, no planning — whenever (a) the user asks to add a feature, change the UI, edit code, create a component, add a route, add an integration, fix a bug in the app itself, or anything else that requires source-file edits while in hosted/production mode, OR (b) the user needs Builder for LLM access, browser automation, or any other Builder-gated capability. If Builder is already connected, the card shows a 'Send to Builder' button that hands the work off to Builder's cloud agent and returns a branch URL. When you call this for a code-change request, pass the user's request verbatim as the `prompt` arg so the card can forward it to Builder unchanged.",
598
+ parameters: {
599
+ type: "object",
600
+ properties: {
601
+ prompt: {
602
+ type: "string",
603
+ description: "The user's feature / change request, verbatim. Forwarded to Builder's cloud agent when the user clicks Send. Omit only for generic 'connect Builder' requests that aren't tied to a specific code change.",
604
+ },
605
+ },
606
+ },
607
+ },
608
+ run: async (args) => {
609
+ const configured = !!(process.env.BUILDER_PRIVATE_KEY && process.env.BUILDER_PUBLIC_KEY);
610
+ const prompt = typeof args?.prompt === "string" ? args.prompt : "";
611
+ return JSON.stringify({
612
+ kind: "connect-builder-card",
613
+ configured,
614
+ builderEnabled: !!process.env.ENABLE_BUILDER,
615
+ connectUrl: getBuilderBrowserConnectUrl(deps.getOrigin()),
616
+ orgName: process.env.BUILDER_ORG_NAME || null,
617
+ prompt,
618
+ });
619
+ },
620
+ },
621
+ "get-browser-connection": {
622
+ tool: {
623
+ description: "Provision a Builder-backed browser session and return browser websocket connection details. If Builder browser access is not configured yet, this returns setup guidance instead.",
624
+ parameters: {
625
+ type: "object",
626
+ properties: {
627
+ sessionId: {
628
+ type: "string",
629
+ description: "Stable browser session identifier. Reuse it to reconnect to the same browser session.",
630
+ },
631
+ projectId: {
632
+ type: "string",
633
+ description: "Optional Builder project or space identifier to scope the session.",
634
+ },
635
+ branchName: {
636
+ type: "string",
637
+ description: "Optional branch name for Builder preview sessions.",
638
+ },
639
+ proxyOrigin: {
640
+ type: "string",
641
+ description: "Optional source origin to proxy from when browsing a local app.",
642
+ },
643
+ proxyDefaultOrigin: {
644
+ type: "string",
645
+ description: "Optional default origin that the browser should use for proxied requests.",
646
+ },
647
+ proxyDestination: {
648
+ type: "string",
649
+ description: "Optional destination origin for proxying local development traffic.",
650
+ },
651
+ },
652
+ required: ["sessionId"],
653
+ },
654
+ },
655
+ run: async (args) => {
656
+ if (!process.env.BUILDER_PRIVATE_KEY ||
657
+ !process.env.BUILDER_PUBLIC_KEY) {
658
+ return JSON.stringify({
659
+ configured: false,
660
+ message: "Builder browser access is not configured. Connect Builder from the workspace Resources panel before requesting a browser session.",
661
+ connectUrl: getBuilderBrowserConnectUrl(deps.getOrigin()),
662
+ });
663
+ }
664
+ const connection = await requestBuilderBrowserConnection({
665
+ sessionId: args.sessionId,
666
+ projectId: args.projectId,
667
+ branchName: args.branchName,
668
+ proxyOrigin: args.proxyOrigin,
669
+ proxyDefaultOrigin: args.proxyDefaultOrigin,
670
+ proxyDestination: args.proxyDestination,
671
+ });
672
+ return JSON.stringify({
673
+ configured: true,
674
+ sessionId: args.sessionId,
675
+ ...connection,
676
+ });
677
+ },
678
+ },
679
+ };
680
+ }
263
681
  /**
264
682
  * Creates agent team orchestration tools (spawn-task, task-status, read-task-result).
265
683
  * These let the main agent spawn sub-agents and coordinate work.
@@ -284,6 +702,10 @@ function createTeamTools(deps) {
284
702
  type: "string",
285
703
  description: "Short name for the sub-agent tab (e.g. 'Research', 'Draft email'). If omitted, derived from the task.",
286
704
  },
705
+ agent: {
706
+ type: "string",
707
+ description: "Optional custom agent profile from agents/*.md to use for this task.",
708
+ },
287
709
  },
288
710
  required: ["task"],
289
711
  },
@@ -302,14 +724,32 @@ function createTeamTools(deps) {
302
724
  "list-tasks",
303
725
  ]);
304
726
  const subAgentActions = Object.fromEntries(Object.entries(deps.getActions()).filter(([name]) => !teamToolNames.has(name)));
727
+ let instructions = args.instructions;
728
+ let selectedModel = deps.getModel();
729
+ let selectedName = args.name || "";
730
+ if (args.agent) {
731
+ const { findAccessibleCustomAgent } = await import("../resources/agents.js");
732
+ const profile = await findAccessibleCustomAgent(deps.getOwner(), args.agent);
733
+ if (!profile) {
734
+ throw new Error(`Custom agent not found: ${args.agent}`);
735
+ }
736
+ const profileInstructions = `## Custom Agent Profile: ${profile.name}\n\n` +
737
+ (profile.description ? `${profile.description}\n\n` : "") +
738
+ profile.instructions;
739
+ instructions = instructions
740
+ ? `${profileInstructions}\n\n## Extra Task Context\n\n${instructions}`
741
+ : profileInstructions;
742
+ selectedModel = profile.model ?? selectedModel;
743
+ selectedName = selectedName || profile.name;
744
+ }
305
745
  const task = await spawnTask({
306
746
  description: args.task,
307
- instructions: args.instructions,
747
+ instructions,
308
748
  ownerEmail: deps.getOwner(),
309
749
  systemPrompt: deps.getSystemPrompt(),
310
750
  actions: subAgentActions,
311
751
  engine: deps.getEngine(),
312
- model: deps.getModel(),
752
+ model: selectedModel,
313
753
  parentThreadId: deps.getParentThreadId(),
314
754
  parentSend: (event) => {
315
755
  if (capturedSend)
@@ -321,7 +761,7 @@ function createTeamTools(deps) {
321
761
  threadId: task.threadId,
322
762
  status: task.status,
323
763
  description: task.description,
324
- name: args.name || "",
764
+ name: selectedName,
325
765
  });
326
766
  },
327
767
  },
@@ -452,24 +892,56 @@ const FRAMEWORK_CORE = `
452
892
  ### Core Rules
453
893
 
454
894
  1. **Data lives in SQL** — All app state is in a SQL database (could be SQLite, Postgres, Turso, or Cloudflare D1 — never assume which). Use the available database tools.
455
- 2. **Context awareness** — The user's current screen state is automatically included in each message as a \`<current-screen>\` block. Use it to understand what the user is looking at. You can still call \`view-screen\` for a more detailed snapshot if needed, but you should NOT need to call it before every action.
895
+ 2. **Context awareness** — The user's current screen state is automatically included in each message as a \`<current-screen>\` block, and the current URL (path + search params) as a \`<current-url>\` block. Use both to understand what the user is looking at filters, search terms, and other URL-driven state live in \`<current-url>\`'s \`searchParams\`, NOT in the settings table. To change URL state (e.g. toggle a filter, clear a query string), use the \`set-search-params\` or \`set-url-path\` tools — never try to edit URL state by writing to settings or application_state directly.
456
896
  3. **Navigate the UI** — Use the \`navigate\` tool to switch views, open items, or focus elements for the user.
457
897
  4. **Application state** — Ephemeral UI state (drafts, selections, navigation) lives in \`application_state\`. Use \`readAppState\`/\`writeAppState\` to read and write it. When you write state, the UI updates automatically.
458
- 5. **Resources for memory** — Use the Resources system for persistent notes and context. Update LEARNINGS.md when you learn user preferences or corrections. Update the shared AGENTS.md for instructions that should apply to all users.
898
+ 5. **Screen refresh is automatic after action calls** — The framework auto-emits a refresh event after any successful mutating tool call (template actions like \`log-meal\`, \`update-form\`, \`edit-document\`, and the \`db-exec\` / \`db-patch\` tools). The UI re-fetches its queries without a full page reload. You do NOT need to call \`refresh-screen\` after an action — it's already handled. Only call \`refresh-screen\` explicitly when (a) you mutated data via a path the framework can't detect (e.g. writing directly to an external system whose results the app mirrors), or (b) you want to pass a \`scope\` hint so the UI narrows which queries to refetch. Do NOT tell the user to reload the page.
899
+ 6. **Memory** — Use the structured memory system to persist knowledge across sessions. Use \`save-memory\` proactively when you learn preferences, corrections, or project context. Update shared AGENTS.md for instructions that should apply to all users.
900
+ 7. **Security** — Always use \`defineAction\` with a Zod \`schema:\` for input validation. Never construct SQL with string concatenation — use parameterized queries via db-query/db-exec. Never use \`dangerouslySetInnerHTML\`, \`innerHTML\`, or \`eval()\`. Never expose secrets in responses or source code. Every table with user data must have \`owner_email\`.
459
901
 
460
902
  ### Resources
461
903
 
462
- You have access to a Resources system for persistent notes, learnings, and context files.
904
+ You have access to a Resources system for persistent notes and context files.
463
905
  Use resource-list, resource-read, resource-write, and resource-delete to manage resources.
464
906
  Resources can be personal (per-user) or shared (team-wide). By default, resources are personal.
465
907
 
466
- When you learn something important (user corrections, preferences, patterns), update the "LEARNINGS.md" resource. Keep it tidy — revise, consolidate, and remove outdated entries rather than only appending.
467
- When the user gives instructions that should apply to all users/sessions, update the shared "AGENTS.md" resource instead.
908
+ When the user gives instructions that should apply to all users/sessions, update the shared "AGENTS.md" resource.
468
909
 
469
910
  ### Navigation Rule
470
911
 
471
912
  When the user says "show me", "go to", "open", "switch to", or similar navigation language, ALWAYS use the \`navigate\` action to update the UI. The user expects to SEE the result in the main app, not just read it in chat. Navigate first, then fetch/display data.
472
913
 
914
+ ### Inline Embeds
915
+
916
+ You can embed an interactive view inline in your chat reply by writing an \`embed\` fenced code block. The chat renderer swaps the fence for a sandboxed iframe pointing at a route inside this app.
917
+
918
+ Syntax:
919
+
920
+ \`\`\`\`
921
+ \`\`\`embed
922
+ src: /some/path?param=value
923
+ aspect: 16/9
924
+ title: Optional label
925
+ \`\`\`
926
+ \`\`\`\`
927
+
928
+ Keys:
929
+ - \`src\` (required) — **must be a same-origin path starting with \`/\`**. Cross-origin URLs are blocked by the renderer. No \`javascript:\` or \`data:\` URLs.
930
+ - \`aspect\` (optional) — one of \`16/9\` (default), \`4/3\`, \`3/2\`, \`2/1\`, \`21/9\`, \`1/1\`.
931
+ - \`title\` (optional) — accessible label / hover tooltip.
932
+ - \`height\` (optional) — fixed pixel height when aspect ratio isn't a good fit.
933
+
934
+ **When to reach for it:**
935
+ - Showing a chart, visualization, or map that benefits from being live/interactive.
936
+ - Previewing a specific item (a thread, a doc, a record) inline with your explanation.
937
+ - Anything where a screenshot-sized static image would undersell the result.
938
+
939
+ **When NOT to use it:**
940
+ - For simple prose answers, tables, or plain data — those should stay as markdown.
941
+ - For external sites — the renderer blocks cross-origin iframes.
942
+
943
+ Which routes are renderable as embeds is template-specific — the app's \`AGENTS.md\` will list them. If no embeddable routes exist in this template, don't emit \`embed\` fences.
944
+
473
945
  ### Chat History
474
946
 
475
947
  You can search and restore previous chat conversations:
@@ -481,7 +953,7 @@ When the user asks to find a previous conversation, use \`search-chats\` first t
481
953
  ### Agent Teams — Orchestration
482
954
 
483
955
  You are an orchestrator. For complex or multi-step tasks, delegate to sub-agents:
484
- - \`spawn-task\` — Spawn a sub-agent for a task. It runs in its own thread while you stay available. A live preview card appears in the chat.
956
+ - \`spawn-task\` — Spawn a sub-agent for a task. It runs in its own thread while you stay available. A live preview card appears in the chat. You can optionally choose a custom agent profile from \`agents/*.md\`.
485
957
  - \`task-status\` — Check the progress of a running sub-agent.
486
958
  - \`read-task-result\` — Read the result when a sub-agent finishes.
487
959
 
@@ -497,7 +969,7 @@ You are an orchestrator. For complex or multi-step tasks, delegate to sub-agents
497
969
  4. Use \`read-task-result\` to check results when needed, or the user can see live progress in the card.
498
970
  5. If the user's request has multiple steps, you can spawn one sub-agent per step, or chain them.
499
971
 
500
- Sub-agents have access to all template tools but **cannot spawn sub-agents themselves** — only you (the orchestrator) can do that. Give the sub-agent a specific, actionable task description — it will figure out which tools to use.
972
+ Sub-agents have access to all template tools but **cannot spawn sub-agents themselves** — only you (the orchestrator) can do that. Give the sub-agent a specific, actionable task description — it will figure out which tools to use. If a matching custom agent profile exists, pass it via the \`agent\` parameter on \`spawn-task\`.
501
973
 
502
974
  ### Recurring Jobs
503
975
 
@@ -518,6 +990,18 @@ When the user asks for something recurring ("every morning", "daily at 9am", "we
518
990
 
519
991
  Job instructions should be self-contained — include which actions to call, what conditions to check, and what to do with results. The agent executing the job has access to all the same tools you do.
520
992
 
993
+ ### Connecting Builder.io
994
+
995
+ When the user asks to connect Builder.io, needs Builder for LLM access / browser automation, or you hit a "Builder not configured" error, call the \`connect-builder\` tool. It renders a one-click Connect card inline in the chat — do NOT write out multi-step setup instructions yourself (no "Option 1 / Option 2", no terminal commands). Just call the tool and let the card handle the rest.
996
+
997
+ ### Browser Access
998
+
999
+ Use \`get-browser-connection\` when you need a real browser session backed by Builder. It returns websocket connection details for a provisioned browser session.
1000
+
1001
+ - If the tool says Builder is not configured, call \`connect-builder\` to show the user a Connect card.
1002
+ - Reuse a stable \`sessionId\` when you want to reconnect to the same browser session.
1003
+ - Include proxy parameters when you need the browser to reach a local dev server through Builder's browser connection flow.
1004
+
521
1005
  ### call-agent — External Apps Only
522
1006
 
523
1007
  The \`call-agent\` tool sends a message to a DIFFERENT, separately-deployed app's agent (A2A protocol). It is **not** for calling actions within the current app.
@@ -534,15 +1018,34 @@ The \`call-agent\` tool sends a message to a DIFFERENT, separately-deployed app'
534
1018
 
535
1019
  If \`call-agent\` returns an error saying the agent is yourself — stop and use your own tools instead.
536
1020
 
537
- ### Auto-Memory
1021
+ ### Structured Memory
538
1022
 
539
- Proactively update \`LEARNINGS.md\` when you learn something important during conversations:
540
- - User corrects your approach → capture the correct way
541
- - User shares preferences (tone, style, workflow) → capture them
542
- - You discover a non-obvious pattern or gotcha → capture it
543
- - User provides personal context (contacts, team info, domain knowledge) → capture it
1023
+ You have a structured memory system. Your memory index (\`memory/MEMORY.md\`) is loaded at the start of every conversation (shown above). Individual memories are stored as separate files under \`memory/\`.
544
1024
 
545
- **Don't ask permission — just save it.** Keep entries concise (one line each, grouped by category). Don't save things that are obvious from reading the code or that are temporary.
1025
+ **Tools:**
1026
+ - \`save-memory\` — Create or update a memory. Provide name, type, description, and content. Atomically updates both the memory file and the index.
1027
+ - \`delete-memory\` — Remove a memory and its index entry.
1028
+ - \`resource-read --path memory/<name>.md\` — Read the full content of a specific memory when you need details beyond the index.
1029
+
1030
+ **Memory types:**
1031
+ - \`user\` — Preferences, role, personal context, contacts
1032
+ - \`feedback\` — Corrections ("don't do X, do Y instead"), confirmed approaches
1033
+ - \`project\` — Ongoing work context, decisions, status
1034
+ - \`reference\` — Pointers to external systems, URLs, API details
1035
+
1036
+ **When to save (do it proactively, don't ask permission):**
1037
+ - User corrects your approach → save as \`feedback\`
1038
+ - User shares preferences (tone, style, workflow) → save as \`user\`
1039
+ - You discover a non-obvious pattern or gotcha → save as \`feedback\`
1040
+ - User provides personal context (contacts, team, domain) → save as \`user\`
1041
+ - A project gains enough context to track → save as \`project\`
1042
+
1043
+ **Rules:**
1044
+ - Don't save things obvious from the code or standard framework behavior
1045
+ - When updating an existing memory, read it first and merge — don't overwrite blindly
1046
+ - Keep descriptions concise — the index is loaded every message
1047
+ - One memory per logical topic (e.g. 'coding-style', 'project-alpha')
1048
+ - Don't save temporary debugging notes or ephemeral task details
546
1049
  `;
547
1050
  const PROD_FRAMEWORK_PROMPT = `## Agent-Native Framework — Production Mode
548
1051
 
@@ -552,20 +1055,22 @@ The agent and the UI are equal partners — everything the UI can do, you can do
552
1055
 
553
1056
  **In production mode, you operate through registered actions exposed as tools.** These are your capabilities — use them to read data, take actions, and help the user. You cannot edit source code or access the filesystem directly. Your tools are the app's API.
554
1057
 
555
- ### Code Changes Not Available
1058
+ ### Code Changes Not Available — Call \`connect-builder\` Immediately
1059
+
1060
+ When the user asks you to change the UI, modify code, add a feature, fix a bug in the app itself, change styles, add a hook, create a component, add a route, add an integration, or anything else that requires editing source files — you MUST take exactly these steps, in order:
556
1061
 
557
- When the user asks you to change the UI, modify code, add features, fix bugs in the app itself, change styles, or do anything that requires editing source files you MUST respond with this exact message (replacing APP_NAME with the current app name from the URL hostname):
1062
+ 1. Call the \`connect-builder\` tool, passing the user's full request verbatim as the \`prompt\` argument. This renders an inline card. If Builder is connected, the card hands the prompt off to Builder's cloud agent on one click and returns a branch URL; otherwise it shows a connect / waitlist flow. Either way, Builder writes the code no local setup, no clone, no install.
1063
+ 2. After the card renders, write a single short sentence telling the user to click Connect Builder to have this built for them in the cloud, and mention they can also clone the app locally with \`npx agent-native create <app-name>\` if they'd rather work offline.
558
1064
 
559
- > This app is running in hosted mode and I can't make code changes here. To customize this app:
560
- >
561
- > **Option 1:** Connect to [Builder.io](https://www.builder.io/m/agent-native) for a full development environment
562
- >
563
- > **Option 2:** Clone and run locally:
564
- > \`\`\`
565
- > npx agent-native create APP_NAME
566
- > \`\`\`
1065
+ **Hard rules do NOT break these:**
1066
+ - Do NOT read source files, list directories, or explore the codebase. You have no filesystem tools and don't need to look at code to recommend Builder.
1067
+ - Do NOT write an implementation plan. Do NOT write code in your response. Do NOT describe which files to create or modify. Builder will figure that out in its sandbox.
1068
+ - Do NOT save plans, specs, or code to \`resource-write\`. Resources are for app data, not implementation plans the user didn't ask for.
1069
+ - Do NOT spawn sub-agents (\`spawn-task\`) to design, plan, or research the feature. The answer is always: call \`connect-builder\`, say one sentence, stop. Sub-agents inherit these same rules and have no code-editing tools either.
1070
+ - Do NOT say "I don't have a request-code-change tool" or list what tools you lack. Just call \`connect-builder\`.
1071
+ - Do NOT wait for the user to ask "how" — call \`connect-builder\` the moment a code change is requested.
567
1072
 
568
- Do NOT attempt to work around this limitation. Do NOT say "I can't do that" without providing the options above. Always include both the Builder.io link and the CLI command.
1073
+ Builder.io is the recommended path because it's one-click and runs in the cloud. Local dev is a fallback for users who want to work offline.
569
1074
  ${FRAMEWORK_CORE}`;
570
1075
  const DEV_FRAMEWORK_PROMPT = `## Agent-Native Framework — Development Mode
571
1076
 
@@ -594,19 +1099,17 @@ ${FRAMEWORK_CORE}`;
594
1099
  const DEFAULT_SYSTEM_PROMPT = PROD_FRAMEWORK_PROMPT;
595
1100
  /**
596
1101
  * Pre-load the agent's context: AGENTS.md (template instructions), the skills
597
- * index, and LEARNINGS.md (user notes). These all get appended to the system
598
- * prompt so the agent has everything it needs from the first turn — no tool
599
- * calls required to figure out "what is this app".
1102
+ * index, shared LEARNINGS.md (team notes), and memory/MEMORY.md (personal
1103
+ * structured memory index). These all get appended to the system prompt so
1104
+ * the agent has everything it needs from the first turn.
600
1105
  *
601
- * Three sources are layered:
1106
+ * Four sources are layered:
602
1107
  *
603
- * 1. `<template>` — AGENTS.md + skills index from the `virtual:agents-bundle`
604
- * module (inlined at build time by the Vite plugin, falls back to a
605
- * filesystem read from `process.cwd()` in dev). Canonical source for
606
- * "what is this app, what can it do, what skills are available".
607
- * 2. `<shared>` LEARNINGS.md from the SQL shared scope. Team-level notes.
608
- * 3. `<personal>` — LEARNINGS.md from the SQL personal scope. The current
609
- * user's own notes.
1108
+ * 1. `<workspace>` — AGENTS.md from the enterprise workspace core.
1109
+ * 2. `<template>` AGENTS.md + skills index from the Vite plugin bundle.
1110
+ * 3. `<shared>` LEARNINGS.md from the SQL shared scope. Team-level notes.
1111
+ * 4. `<personal>` memory/MEMORY.md from the SQL personal scope. The
1112
+ * current user's structured memory index.
610
1113
  *
611
1114
  * Each source is read independently — no copying between them. Editing
612
1115
  * AGENTS.md and restarting the server is all it takes; Vite HMR invalidates
@@ -615,10 +1118,15 @@ const DEFAULT_SYSTEM_PROMPT = PROD_FRAMEWORK_PROMPT;
615
1118
  async function loadResourcesForPrompt(owner) {
616
1119
  await ensurePersonalDefaults(owner);
617
1120
  const sections = [];
618
- // 1. Template AGENTS.md + skills index from the virtual bundle.
1121
+ // 1. Workspace AGENTS.md + skills merged into the template bundle.
619
1122
  try {
620
1123
  const { loadAgentsBundle, generateSkillsPromptBlock } = await import("./agents-bundle.js");
621
1124
  const bundle = await loadAgentsBundle();
1125
+ // Workspace-core AGENTS.md (enterprise-wide instructions), if present.
1126
+ if (bundle.workspaceAgentsMd && bundle.workspaceAgentsMd.trim()) {
1127
+ sections.push(`<resource name="AGENTS.md" scope="workspace">\n${bundle.workspaceAgentsMd.trim()}\n</resource>`);
1128
+ }
1129
+ // 2. Template AGENTS.md.
622
1130
  if (bundle.agentsMd.trim()) {
623
1131
  sections.push(`<resource name="AGENTS.md" scope="template">\n${bundle.agentsMd.trim()}\n</resource>`);
624
1132
  }
@@ -636,12 +1144,12 @@ async function loadResourcesForPrompt(owner) {
636
1144
  }
637
1145
  }
638
1146
  catch { }
639
- // 3. Personal SQL scope (skip if owner is the shared sentinel)
1147
+ // 3. Personal memory index (skip if owner is the shared sentinel)
640
1148
  if (owner !== SHARED_OWNER) {
641
1149
  try {
642
- const personal = await resourceGetByPath(owner, "LEARNINGS.md");
643
- if (personal?.content?.trim()) {
644
- sections.push(`<resource name="LEARNINGS.md" scope="personal">\n${personal.content.trim()}\n</resource>`);
1150
+ const memoryIndex = await resourceGetByPath(owner, "memory/MEMORY.md");
1151
+ if (memoryIndex?.content?.trim()) {
1152
+ sections.push(`<resource name="memory/MEMORY.md" scope="personal">\n${memoryIndex.content.trim()}\n</resource>`);
645
1153
  }
646
1154
  }
647
1155
  catch { }
@@ -656,12 +1164,15 @@ async function loadResourcesForPrompt(owner) {
656
1164
  * from the environment so scheduler/A2A/HTTP call sites all see whatever
657
1165
  * org was just resolved for this request.
658
1166
  */
659
- async function buildSchemaBlock(owner, hasRawDbTools) {
1167
+ async function buildSchemaBlock(owner, _legacyHasRawDbTools) {
1168
+ // db-* tools are always registered (see createDbScriptEntries), in both dev
1169
+ // and prod. The legacy boolean is kept for call-site compatibility but
1170
+ // ignored — always advertise the tools to the agent.
660
1171
  try {
661
1172
  return await loadSchemaPromptBlock({
662
1173
  owner,
663
- orgId: process.env.AGENT_ORG_ID ?? null,
664
- hasRawDbTools,
1174
+ orgId: getRequestOrgId() ?? null,
1175
+ hasRawDbTools: true,
665
1176
  });
666
1177
  }
667
1178
  catch {
@@ -851,19 +1362,92 @@ export function createAgentChatPlugin(options) {
851
1362
  const canToggle = (env === "development" || env === "test") &&
852
1363
  process.env.AGENT_MODE !== "production";
853
1364
  const routePath = options?.path ?? "/_agent-native/agent-chat";
1365
+ // Mutable mode flag — persisted to the `settings` table so a user who
1366
+ // toggles to "Production" stays in prod mode across server restarts.
1367
+ // Hoisted here (before any tool-registry / handler closures are built)
1368
+ // so every runtime decision point can close over it and see live changes
1369
+ // when the user toggles the Environment dropdown.
1370
+ const AGENT_MODE_SETTING_KEY = "agent-chat.mode";
1371
+ let currentDevMode = canToggle;
1372
+ if (canToggle) {
1373
+ try {
1374
+ const persisted = await getSetting(AGENT_MODE_SETTING_KEY);
1375
+ if (persisted && typeof persisted.devMode === "boolean") {
1376
+ currentDevMode = persisted.devMode;
1377
+ }
1378
+ }
1379
+ catch {
1380
+ // Settings table may not be ready yet — fall back to default.
1381
+ }
1382
+ }
1383
+ // Every closure that picks between dev/prod tools, prompts, or handlers
1384
+ // at request time should call this getter instead of reading `canToggle`.
1385
+ // `canToggle` means "this environment allows toggling" (static); this
1386
+ // function means "the user currently has dev mode ON" (live).
1387
+ const isDevMode = () => currentDevMode;
1388
+ // Initialize MCP client (connects to user-configured local MCP servers).
1389
+ // Graceful-degrade: any failure yields zero MCP tools and agent-chat keeps
1390
+ // working as before. No-op outside Node runtimes.
1391
+ let mcpConfig = loadMcpConfig();
1392
+ if (!mcpConfig) {
1393
+ mcpConfig = autoDetectMcpConfig();
1394
+ if (mcpConfig) {
1395
+ const detected = Object.keys(mcpConfig.servers).join(", ");
1396
+ console.log(`[mcp-client] auto-detected ${detected}, registering as MCP server — set AGENT_NATIVE_DISABLE_MCP_AUTODETECT=1 to opt out`);
1397
+ }
1398
+ else {
1399
+ console.log("[mcp-client] no mcp.config.json and no auto-detectable servers — skipping MCP tools");
1400
+ }
1401
+ }
1402
+ else if (mcpConfig.source) {
1403
+ console.log(`[mcp-client] loaded config from ${mcpConfig.source} (${Object.keys(mcpConfig.servers).length} server(s))`);
1404
+ }
1405
+ const mcpManager = new McpClientManager(mcpConfig);
1406
+ try {
1407
+ await mcpManager.start();
1408
+ }
1409
+ catch (err) {
1410
+ console.warn(`[mcp-client] start() failed: ${err?.message ?? err}. Continuing without MCP tools.`);
1411
+ }
1412
+ setGlobalMcpManager(mcpManager);
1413
+ const mcpActionEntries = mcpToolsToActionEntries(mcpManager);
1414
+ // Mount status route so tooling/onboarding can inspect MCP state.
1415
+ mountMcpStatusRoute(nitroApp, mcpManager);
1416
+ // Ensure we tear down child processes if the host shuts down cleanly.
1417
+ if (typeof process !== "undefined" &&
1418
+ typeof process.once === "function" &&
1419
+ !globalThis.__agentNativeMcpExitHooked) {
1420
+ globalThis.__agentNativeMcpExitHooked = true;
1421
+ const stop = () => {
1422
+ const mgr = getGlobalMcpManager();
1423
+ if (mgr)
1424
+ void mgr.stop();
1425
+ };
1426
+ process.once("exit", stop);
1427
+ process.once("SIGTERM", stop);
1428
+ process.once("SIGINT", stop);
1429
+ }
854
1430
  // Resolve actions — prefer `actions`, fall back to deprecated `scripts`
855
1431
  const rawActions = options?.actions ?? options?.scripts;
856
1432
  const templateScripts = typeof rawActions === "function"
857
1433
  ? await rawActions()
858
1434
  : (rawActions ?? {});
859
- // Resource, chat, and cross-agent scripts are available in both prod and dev modes
1435
+ // Resource, chat, docs, db, and cross-agent scripts are available in both prod and dev modes
860
1436
  const resourceScripts = await createResourceScriptEntries();
1437
+ const docsScripts = await createDocsScriptEntries();
1438
+ const dbScripts = await createDbScriptEntries();
1439
+ const refreshScreenTool = createRefreshScreenEntry();
1440
+ const urlTools = createUrlTools();
861
1441
  const engineScripts = await createAgentEngineScriptEntries();
862
1442
  const chatScripts = {
863
1443
  ...(await createChatScriptEntries()),
864
1444
  ...engineScripts,
865
1445
  };
866
1446
  const callAgentScript = await createCallAgentScriptEntry(options?.appId);
1447
+ let _currentRequestOrigin = "http://localhost:3000";
1448
+ const browserTools = createBuilderBrowserTool({
1449
+ getOrigin: () => _currentRequestOrigin,
1450
+ });
867
1451
  // Auto-mount A2A protocol endpoints so every app is discoverable
868
1452
  // and callable by other agents via the standard protocol.
869
1453
  // In dev mode, include dev scripts (filesystem-discovered) so the A2A agent
@@ -1001,16 +1585,23 @@ export function createAgentChatPlugin(options) {
1001
1585
  const allScripts = canToggle
1002
1586
  ? {
1003
1587
  ...resourceScripts,
1588
+ ...docsScripts,
1004
1589
  ...chatScripts,
1005
1590
  ...callAgentScript,
1591
+ ...browserTools,
1006
1592
  ...devScriptsForA2A,
1007
1593
  }
1008
1594
  : {
1009
1595
  ...discoveredActions,
1010
1596
  ...templateScripts,
1011
1597
  ...resourceScripts,
1598
+ ...docsScripts,
1599
+ ...dbScripts,
1600
+ ...refreshScreenTool,
1601
+ ...urlTools,
1012
1602
  ...chatScripts,
1013
1603
  ...callAgentScript,
1604
+ ...browserTools,
1014
1605
  ...devScriptsForA2A,
1015
1606
  };
1016
1607
  const { mountA2A } = await import("../a2a/server.js");
@@ -1083,12 +1674,13 @@ export function createAgentChatPlugin(options) {
1083
1674
  apiKey: options?.apiKey,
1084
1675
  });
1085
1676
  // Use the same handler (dev or prod) that the interactive chat uses
1086
- const handler = canToggle && devHandler ? devHandler : prodHandler;
1677
+ const devActive = isDevMode();
1678
+ const handler = devActive && devHandler ? devHandler : prodHandler;
1087
1679
  // Build the same system prompt the interactive agent uses
1088
1680
  const owner = userEmail || "local@localhost";
1089
1681
  const resources = await loadResourcesForPrompt(owner);
1090
- const schemaBlock = await buildSchemaBlock(owner, canToggle);
1091
- const systemPrompt = canToggle
1682
+ const schemaBlock = await buildSchemaBlock(owner, devActive);
1683
+ const systemPrompt = devActive
1092
1684
  ? devPrompt + resources + schemaBlock
1093
1685
  : basePrompt + resources + schemaBlock;
1094
1686
  const model = options?.model ??
@@ -1097,16 +1689,23 @@ export function createAgentChatPlugin(options) {
1097
1689
  // to prevent infinite recursive A2A loops (agent calling itself).
1098
1690
  // In dev mode, template actions are invoked via shell (not native tools),
1099
1691
  // so they're omitted from the tool registry — see allScripts comment.
1100
- const a2aActions = canToggle
1692
+ const a2aActions = devActive
1101
1693
  ? {
1102
1694
  ...resourceScripts,
1695
+ ...docsScripts,
1103
1696
  ...chatScripts,
1697
+ ...browserTools,
1104
1698
  ...devScriptsForA2A,
1105
1699
  }
1106
1700
  : {
1107
1701
  ...templateScripts,
1108
1702
  ...resourceScripts,
1703
+ ...docsScripts,
1704
+ ...dbScripts,
1705
+ ...refreshScreenTool,
1706
+ ...urlTools,
1109
1707
  ...chatScripts,
1708
+ ...browserTools,
1110
1709
  };
1111
1710
  const a2aTools = actionsToEngineTools(a2aActions);
1112
1711
  const a2aMessages = [
@@ -1189,21 +1788,27 @@ export function createAgentChatPlugin(options) {
1189
1788
  (canToggle ? "claude-sonnet-4-6" : "claude-haiku-4-5-20251001");
1190
1789
  // Same actions as A2A — without call-agent to prevent loops.
1191
1790
  // In dev mode, template actions go through shell, not native tools.
1192
- const mcpActions = canToggle
1791
+ const devActiveMcp = isDevMode();
1792
+ const mcpActions = devActiveMcp
1193
1793
  ? {
1194
1794
  ...resourceScripts,
1795
+ ...docsScripts,
1195
1796
  ...chatScripts,
1196
1797
  ...devScriptsForA2A,
1197
1798
  }
1198
1799
  : {
1199
1800
  ...templateScripts,
1200
1801
  ...resourceScripts,
1802
+ ...docsScripts,
1803
+ ...dbScripts,
1804
+ ...refreshScreenTool,
1805
+ ...urlTools,
1201
1806
  ...chatScripts,
1202
1807
  };
1203
1808
  const mcpTools = actionsToEngineTools(mcpActions);
1204
1809
  const resources = await loadResourcesForPrompt("local@localhost");
1205
- const schemaBlock = await buildSchemaBlock("local@localhost", canToggle);
1206
- const systemPrompt = canToggle
1810
+ const schemaBlock = await buildSchemaBlock("local@localhost", devActiveMcp);
1811
+ const systemPrompt = devActiveMcp
1207
1812
  ? devPrompt + resources + schemaBlock
1208
1813
  : basePrompt + resources + schemaBlock;
1209
1814
  let accumulatedText = "";
@@ -1309,6 +1914,7 @@ export function createAgentChatPlugin(options) {
1309
1914
  // requests for different threads don't clobber each other.
1310
1915
  const _runSendByThread = new Map();
1311
1916
  let _currentRunOwner = "local@localhost";
1917
+ let _currentRunUserApiKey;
1312
1918
  let _currentRunThreadId = "";
1313
1919
  let _currentRunSystemPrompt = basePrompt;
1314
1920
  // Default to Haiku in production mode to manage costs for hosted apps
@@ -1317,21 +1923,31 @@ export function createAgentChatPlugin(options) {
1317
1923
  const teamTools = createTeamTools({
1318
1924
  getOwner: () => _currentRunOwner,
1319
1925
  getSystemPrompt: () => _currentRunSystemPrompt,
1320
- getActions: () => canToggle
1926
+ getActions: () => isDevMode()
1321
1927
  ? {
1322
1928
  // Sub-agents spawned in dev mode also invoke template actions
1323
1929
  // via shell, so omit them from the native tool registry.
1324
1930
  ...resourceScripts,
1931
+ ...docsScripts,
1325
1932
  ...chatScripts,
1326
1933
  ...devScriptsForA2A,
1327
1934
  }
1328
1935
  : {
1329
1936
  ...templateScripts,
1330
1937
  ...resourceScripts,
1938
+ ...docsScripts,
1939
+ ...dbScripts,
1940
+ ...refreshScreenTool,
1941
+ ...urlTools,
1331
1942
  ...chatScripts,
1332
1943
  },
1333
1944
  getEngine: () => createAnthropicEngine({
1334
- apiKey: options?.apiKey ?? process.env.ANTHROPIC_API_KEY,
1945
+ // Sub-agents must inherit the parent run's resolved key so a
1946
+ // BYO-key user can't bypass the free-tier check on the parent
1947
+ // run and then have spawn-task delegations bill the platform key.
1948
+ apiKey: _currentRunUserApiKey ??
1949
+ options?.apiKey ??
1950
+ process.env.ANTHROPIC_API_KEY,
1335
1951
  }),
1336
1952
  getModel: () => resolvedModel,
1337
1953
  getParentThreadId: () => _currentRunThreadId,
@@ -1352,22 +1968,44 @@ export function createAgentChatPlugin(options) {
1352
1968
  const prodActions = {
1353
1969
  ...templateScripts,
1354
1970
  ...resourceScripts,
1971
+ ...docsScripts,
1972
+ ...dbScripts,
1973
+ ...refreshScreenTool,
1974
+ ...urlTools,
1355
1975
  ...chatScripts,
1356
1976
  ...callAgentScript,
1357
1977
  ...teamTools,
1358
1978
  ...jobTools,
1979
+ ...browserTools,
1980
+ ...mcpActionEntries,
1359
1981
  };
1360
1982
  // Always build the production handler (includes resource tools + call-agent + team tools)
1361
1983
  // In production mode (!canToggle), enable usage tracking and limits
1362
1984
  const isHostedProd = !canToggle;
1985
+ const resolveExtraContext = async (event, owner) => {
1986
+ if (!options?.extraContext)
1987
+ return "";
1988
+ try {
1989
+ const extra = await options.extraContext(event, owner);
1990
+ return extra ? `\n\n${extra}` : "";
1991
+ }
1992
+ catch (err) {
1993
+ console.warn("[agent-chat] extraContext threw:", err instanceof Error ? err.message : err);
1994
+ return "";
1995
+ }
1996
+ };
1363
1997
  const prodHandler = createProductionAgentHandler({
1364
1998
  actions: prodActions,
1365
1999
  systemPrompt: async (event) => {
2000
+ _currentRequestOrigin = getOrigin(event);
1366
2001
  const owner = await getOwnerFromEvent(event);
1367
2002
  _currentRunOwner = owner;
2003
+ const { getOwnerAnthropicApiKey } = await import("../agent/production-agent.js");
2004
+ _currentRunUserApiKey = await getOwnerAnthropicApiKey(owner);
1368
2005
  const resources = await loadResourcesForPrompt(owner);
1369
2006
  const schemaBlock = await buildSchemaBlock(owner, false);
1370
- _currentRunSystemPrompt = basePrompt + resources + schemaBlock;
2007
+ const extra = await resolveExtraContext(event, owner);
2008
+ _currentRunSystemPrompt = basePrompt + resources + schemaBlock + extra;
1371
2009
  return _currentRunSystemPrompt;
1372
2010
  },
1373
2011
  model: options?.model ??
@@ -1398,20 +2036,27 @@ export function createAgentChatPlugin(options) {
1398
2036
  // listed in the dev system prompt's "Available Actions" section.
1399
2037
  const devActions = {
1400
2038
  ...resourceScripts,
2039
+ ...docsScripts,
1401
2040
  ...chatScripts,
1402
2041
  ...callAgentScript,
1403
2042
  ...teamTools,
1404
2043
  ...jobTools,
2044
+ ...browserTools,
2045
+ ...mcpActionEntries,
1405
2046
  ...(await createDevScriptRegistry()),
1406
2047
  };
1407
2048
  devHandler = createProductionAgentHandler({
1408
2049
  actions: devActions,
1409
2050
  systemPrompt: async (event) => {
2051
+ _currentRequestOrigin = getOrigin(event);
1410
2052
  const owner = await getOwnerFromEvent(event);
1411
2053
  _currentRunOwner = owner;
2054
+ const { getOwnerAnthropicApiKey } = await import("../agent/production-agent.js");
2055
+ _currentRunUserApiKey = await getOwnerAnthropicApiKey(owner);
1412
2056
  const resources = await loadResourcesForPrompt(owner);
1413
2057
  const schemaBlock = await buildSchemaBlock(owner, true);
1414
- _currentRunSystemPrompt = devPrompt + resources + schemaBlock;
2058
+ const extra = await resolveExtraContext(event, owner);
2059
+ _currentRunSystemPrompt = devPrompt + resources + schemaBlock + extra;
1415
2060
  return _currentRunSystemPrompt;
1416
2061
  },
1417
2062
  model: options?.model,
@@ -1432,8 +2077,8 @@ export function createAgentChatPlugin(options) {
1432
2077
  const mentionProviders = typeof rawProviders === "function"
1433
2078
  ? await rawProviders()
1434
2079
  : (rawProviders ?? {});
1435
- // Mutable mode flag starts in dev if environment allows
1436
- let currentDevMode = canToggle;
2080
+ // currentDevMode + persistence were hoisted to the top of this function
2081
+ // so every closure built below can close over the live flag.
1437
2082
  // Mount mode endpoint — GET returns current mode, POST toggles it (localhost only)
1438
2083
  getH3App(nitroApp).use(`${routePath}/mode`, defineEventHandler(async (event) => {
1439
2084
  if (getMethod(event) === "POST") {
@@ -1452,12 +2097,24 @@ export function createAgentChatPlugin(options) {
1452
2097
  else {
1453
2098
  currentDevMode = !currentDevMode;
1454
2099
  }
2100
+ try {
2101
+ await putSetting(AGENT_MODE_SETTING_KEY, {
2102
+ devMode: currentDevMode,
2103
+ });
2104
+ }
2105
+ catch {
2106
+ // Persistence is best-effort — in-memory flag still applies for
2107
+ // the lifetime of this process even if the settings write fails.
2108
+ }
1455
2109
  return { devMode: currentDevMode, canToggle };
1456
2110
  }
1457
2111
  return { devMode: currentDevMode, canToggle };
1458
2112
  }));
1459
- // Mount save-key BEFORE the prefix handler so it isn't shadowed
1460
- // Only functional in Node.js environments (writes to .env file)
2113
+ // Mount save-key BEFORE the prefix handler so it isn't shadowed.
2114
+ // Persists the user's key per-owner in the SQL settings table so it
2115
+ // survives across serverless invocations (where mutating process.env
2116
+ // and writing .env are both no-ops). Also updates process.env and
2117
+ // .env when running locally for fast pickup by other handlers.
1461
2118
  getH3App(nitroApp).use(`${routePath}/save-key`, defineEventHandler(async (event) => {
1462
2119
  if (getMethod(event) !== "POST") {
1463
2120
  setResponseStatus(event, 405);
@@ -1470,19 +2127,66 @@ export function createAgentChatPlugin(options) {
1470
2127
  return { error: "API key is required" };
1471
2128
  }
1472
2129
  const trimmedKey = key.trim();
1473
- try {
1474
- const path = await import("path");
1475
- const { upsertEnvFile } = await import("./create-server.js");
1476
- const envPath = path.join(process.cwd(), ".env");
1477
- await upsertEnvFile(envPath, [
1478
- { key: "ANTHROPIC_API_KEY", value: trimmedKey },
1479
- ]);
2130
+ // Persist per-owner so the key survives cold starts in serverless
2131
+ // and so the user's key isn't shared across users on multi-tenant
2132
+ // hosted deployments. We require a real authenticated owner here —
2133
+ // `local@localhost` is the unauthenticated fallback and must never
2134
+ // become the shared key bucket on hosted deployments.
2135
+ const ownerEmail = await getOwnerFromEvent(event);
2136
+ if (isHostedProd && (!ownerEmail || ownerEmail === "local@localhost")) {
2137
+ setResponseStatus(event, 401);
2138
+ return { error: "Authentication required" };
1480
2139
  }
1481
- catch {
1482
- // Edge runtime — can't write .env, but can still update process.env
2140
+ if (ownerEmail && ownerEmail !== "local@localhost") {
2141
+ try {
2142
+ await putSetting(`user-anthropic-api-key:${ownerEmail}`, {
2143
+ key: trimmedKey,
2144
+ });
2145
+ // Verify the write actually landed — some managed DB drivers
2146
+ // swallow errors on degraded connections. Without this the
2147
+ // client sees "saved", reloads, and the usage-limit card
2148
+ // re-appears on the next message because the key isn't
2149
+ // really persisted.
2150
+ const check = await getSetting(`user-anthropic-api-key:${ownerEmail}`);
2151
+ if (!check ||
2152
+ typeof check.key !== "string" ||
2153
+ check.key !== trimmedKey) {
2154
+ throw new Error("settings write did not persist");
2155
+ }
2156
+ }
2157
+ catch (err) {
2158
+ if (isHostedProd) {
2159
+ console.error("[agent-chat] save-key persistence failed:", err instanceof Error ? err.message : err);
2160
+ setResponseStatus(event, 500);
2161
+ return {
2162
+ error: "Failed to persist API key. Please try again or contact support.",
2163
+ };
2164
+ }
2165
+ // Local dev falls through to the env-file path below.
2166
+ }
2167
+ }
2168
+ // In hosted/multi-tenant mode we deliberately do NOT touch
2169
+ // process.env or .env: the per-owner SQL lookup above is the
2170
+ // single source of truth, and overwriting the shared env key
2171
+ // would leak one tenant's credentials into every subsequent
2172
+ // request that hit the same warm instance without its own key.
2173
+ if (!isHostedProd) {
2174
+ try {
2175
+ const path = await import("path");
2176
+ const { upsertEnvFile } = await import("./create-server.js");
2177
+ const envPath = path.join(process.cwd(), ".env");
2178
+ await upsertEnvFile(envPath, [
2179
+ { key: "ANTHROPIC_API_KEY", value: trimmedKey },
2180
+ ]);
2181
+ }
2182
+ catch {
2183
+ // Edge runtime — can't write .env, but can still update process.env
2184
+ }
2185
+ // Update process.env so the agent works immediately in the
2186
+ // current local-dev invocation; the SQL persist above covers
2187
+ // future invocations.
2188
+ process.env.ANTHROPIC_API_KEY = trimmedKey;
1483
2189
  }
1484
- // Update process.env so the agent works immediately
1485
- process.env.ANTHROPIC_API_KEY = trimmedKey;
1486
2190
  return { ok: true };
1487
2191
  }));
1488
2192
  // Mount file search endpoint
@@ -1750,7 +2454,29 @@ export function createAgentChatPlugin(options) {
1750
2454
  }
1751
2455
  })());
1752
2456
  }
1753
- // 4. Peer agent discovery (network call — often slowest)
2457
+ // 4. Custom workspace agents
2458
+ sources.push((async () => {
2459
+ try {
2460
+ const owner = await getOwnerFromEvent(event);
2461
+ const { listAccessibleCustomAgents } = await import("../resources/agents.js");
2462
+ const agents = await listAccessibleCustomAgents(owner);
2463
+ flush(agents.map((agent) => ({
2464
+ id: `custom-agent:${agent.id}`,
2465
+ label: agent.name,
2466
+ description: agent.description || agent.path,
2467
+ icon: "agent",
2468
+ source: "agent:custom",
2469
+ refType: "custom-agent",
2470
+ refPath: agent.path,
2471
+ refId: agent.id,
2472
+ section: "Agents",
2473
+ })));
2474
+ }
2475
+ catch (e) {
2476
+ console.error("[agent-native] Custom agent discovery failed:", e);
2477
+ }
2478
+ })());
2479
+ // 5. Peer agent discovery (network call — often slowest)
1754
2480
  sources.push((async () => {
1755
2481
  try {
1756
2482
  const agents = await discoverAgents(options?.appId);
@@ -1763,7 +2489,7 @@ export function createAgentChatPlugin(options) {
1763
2489
  refType: "agent",
1764
2490
  refPath: agent.url,
1765
2491
  refId: agent.id,
1766
- section: "Agents",
2492
+ section: "Connected Agents",
1767
2493
  })));
1768
2494
  }
1769
2495
  catch (e) {
@@ -1786,7 +2512,7 @@ export function createAgentChatPlugin(options) {
1786
2512
  setResponseStatus(event, 405);
1787
2513
  return { error: "Method not allowed" };
1788
2514
  }
1789
- await getOwnerFromEvent(event);
2515
+ const ownerEmail = await getOwnerFromEvent(event);
1790
2516
  const body = await readBody(event);
1791
2517
  const message = body?.message;
1792
2518
  if (!message || typeof message !== "string") {
@@ -1795,7 +2521,11 @@ export function createAgentChatPlugin(options) {
1795
2521
  }
1796
2522
  // Strip mention markup: @[Name|type] → @Name
1797
2523
  const cleanMessage = message.replace(/@\[([^\]|]+)\|[^\]]*\]/g, "@$1");
1798
- const apiKey = process.env.ANTHROPIC_API_KEY;
2524
+ // Mirror the chat-run resolution so BYO-key users have title
2525
+ // generation billed to their own key instead of the platform key.
2526
+ const { getOwnerAnthropicApiKey } = await import("../agent/production-agent.js");
2527
+ const userApiKey = await getOwnerAnthropicApiKey(ownerEmail);
2528
+ const apiKey = userApiKey ?? process.env.ANTHROPIC_API_KEY;
1799
2529
  if (!apiKey) {
1800
2530
  // Fallback: truncate the message
1801
2531
  return { title: cleanMessage.trim().slice(0, 60) };
@@ -1973,34 +2703,34 @@ export function createAgentChatPlugin(options) {
1973
2703
  setResponseStatus(event, 404);
1974
2704
  return { error: "Not found" };
1975
2705
  }
1976
- // Set AGENT_USER_EMAIL so scripts resolve the same owner as the session.
1977
- // Without this, scripts default to "local@localhost" and miss resources
1978
- // created by users who authenticated via OAuth (e.g., Gmail).
2706
+ // Resolve per-request auth context
1979
2707
  const owner = await getOwnerFromEvent(event);
1980
- process.env.AGENT_USER_EMAIL = owner;
1981
- // Set AGENT_ORG_ID so db-query/db-exec scope by org_id when applicable.
1982
- // Priority: explicit resolveOrgId callback > session.orgId from Better Auth
1983
- let resolvedOrgId = null;
2708
+ // Resolve org ID: explicit callback > session.orgId from Better Auth
2709
+ let resolvedOrgId;
1984
2710
  if (options?.resolveOrgId) {
1985
- resolvedOrgId = await options.resolveOrgId(event);
2711
+ resolvedOrgId = (await options.resolveOrgId(event)) ?? undefined;
1986
2712
  }
1987
2713
  else {
1988
2714
  try {
1989
2715
  const session = await getSession(event);
1990
- resolvedOrgId = session?.orgId ?? null;
2716
+ resolvedOrgId = session?.orgId ?? undefined;
1991
2717
  }
1992
2718
  catch {
1993
2719
  // Session not available
1994
2720
  }
1995
2721
  }
2722
+ // Also set process.env for backwards compat (CLI scripts, legacy readers)
2723
+ process.env.AGENT_USER_EMAIL = owner;
1996
2724
  if (resolvedOrgId) {
1997
2725
  process.env.AGENT_ORG_ID = resolvedOrgId;
1998
2726
  }
1999
2727
  else {
2000
2728
  delete process.env.AGENT_ORG_ID;
2001
2729
  }
2002
- const handler = currentDevMode && devHandler ? devHandler : prodHandler;
2003
- return handler(event);
2730
+ return runWithRequestContext({ userEmail: owner, orgId: resolvedOrgId }, () => {
2731
+ const handler = currentDevMode && devHandler ? devHandler : prodHandler;
2732
+ return handler(event);
2733
+ });
2004
2734
  }));
2005
2735
  // ─── Recurring Jobs Scheduler ──────────────────────────────────────
2006
2736
  // Poll every 60 seconds for due recurring jobs and execute them.
@@ -2012,6 +2742,7 @@ export function createAgentChatPlugin(options) {
2012
2742
  getActions: () => ({
2013
2743
  ...templateScripts,
2014
2744
  ...resourceScripts,
2745
+ ...docsScripts,
2015
2746
  ...chatScripts,
2016
2747
  ...jobTools,
2017
2748
  }),
@@ -2045,4 +2776,35 @@ export function createAgentChatPlugin(options) {
2045
2776
  * In production, provides only the default system prompt.
2046
2777
  */
2047
2778
  export const defaultAgentChatPlugin = createAgentChatPlugin();
2779
+ // ---------------------------------------------------------------------------
2780
+ // MCP client glue — a shared manager reference + a /_agent-native/mcp/status
2781
+ // route so onboarding / settings UIs can see which MCP servers are live.
2782
+ // ---------------------------------------------------------------------------
2783
+ let _globalMcpManager = null;
2784
+ function setGlobalMcpManager(manager) {
2785
+ _globalMcpManager = manager;
2786
+ }
2787
+ /** Internal: access the current process's MCP client manager, if any. */
2788
+ export function getGlobalMcpManager() {
2789
+ return _globalMcpManager;
2790
+ }
2791
+ function mountMcpStatusRoute(nitroApp, manager) {
2792
+ // Idempotent — agent-chat-plugin can be invoked once per process; guard anyway.
2793
+ if (globalThis.__agentNativeMcpStatusMounted)
2794
+ return;
2795
+ globalThis.__agentNativeMcpStatusMounted = true;
2796
+ try {
2797
+ getH3App(nitroApp).use("/_agent-native/mcp/status", defineEventHandler(async (event) => {
2798
+ if (getMethod(event) !== "GET") {
2799
+ setResponseStatus(event, 405);
2800
+ return { error: "Method not allowed" };
2801
+ }
2802
+ setResponseHeader(event, "Content-Type", "application/json");
2803
+ return manager.getStatus();
2804
+ }));
2805
+ }
2806
+ catch (err) {
2807
+ console.warn(`[mcp-client] Failed to mount /_agent-native/mcp/status: ${err?.message ?? err}`);
2808
+ }
2809
+ }
2048
2810
  //# sourceMappingURL=agent-chat-plugin.js.map