@agent-native/core 0.146.8 → 0.148.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (317) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +115 -68
  3. package/corpus/templates/analytics/.agents/skills/turn-into-app/SKILL.md +18 -6
  4. package/corpus/templates/analytics/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  5. package/corpus/templates/analytics/DEVELOPING.md +50 -3
  6. package/corpus/templates/analytics/actions/purge-first-party-analytics-postgres.ts +190 -0
  7. package/corpus/templates/analytics/app/i18n/index.ts +14 -29
  8. package/corpus/templates/analytics/app/i18n-data.ts +10 -10
  9. package/corpus/templates/analytics/app/pages/Settings.tsx +5 -21
  10. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +1 -3
  11. package/corpus/templates/analytics/app/routes/status.$slug.tsx +4 -2
  12. package/corpus/templates/analytics/scripts/first-party-analytics-bigquery-backfill.ts +253 -24
  13. package/corpus/templates/analytics/server/db/schema.ts +23 -0
  14. package/corpus/templates/analytics/server/handlers/first-party-analytics.ts +3 -1
  15. package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +1 -1
  16. package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +113 -13
  17. package/corpus/templates/analytics/server/lib/first-party-analytics-purge.ts +140 -0
  18. package/corpus/templates/analytics/server/lib/first-party-analytics-volume.ts +207 -0
  19. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +40 -9
  20. package/corpus/templates/analytics/server/lib/gcloud.ts +148 -20
  21. package/corpus/templates/analytics/server/plugins/db.ts +42 -0
  22. package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +115 -68
  23. package/corpus/templates/assets/.agents/skills/turn-into-app/SKILL.md +18 -6
  24. package/corpus/templates/assets/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  25. package/corpus/templates/assets/app/i18n/index.ts +14 -29
  26. package/corpus/templates/brain/.agents/skills/adding-a-feature/SKILL.md +9 -0
  27. package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +115 -68
  28. package/corpus/templates/brain/.agents/skills/turn-into-app/SKILL.md +18 -6
  29. package/corpus/templates/brain/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  30. package/corpus/templates/brain/app/i18n/index.ts +14 -29
  31. package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +115 -68
  32. package/corpus/templates/calendar/.agents/skills/turn-into-app/SKILL.md +18 -6
  33. package/corpus/templates/calendar/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  34. package/corpus/templates/chat/.agents/skills/adding-a-feature/SKILL.md +9 -0
  35. package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
  36. package/corpus/templates/chat/.agents/skills/turn-into-app/SKILL.md +18 -6
  37. package/corpus/templates/chat/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  38. package/corpus/templates/chat/app/i18n/index.ts +14 -29
  39. package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +115 -68
  40. package/corpus/templates/clips/.agents/skills/turn-into-app/SKILL.md +18 -6
  41. package/corpus/templates/clips/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  42. package/corpus/templates/clips/app/components/player/transcript-panel.tsx +2 -7
  43. package/corpus/templates/clips/app/components/recorder/storage-setup-card.tsx +18 -13
  44. package/corpus/templates/clips/app/components/settings/ai-setup-section.tsx +87 -370
  45. package/corpus/templates/clips/app/components/settings/slack-section.tsx +59 -101
  46. package/corpus/templates/clips/app/components/settings/video-storage-section.tsx +136 -213
  47. package/corpus/templates/clips/app/i18n/en-US.ts +11 -8
  48. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +16 -4
  49. package/corpus/templates/clips/app/routes/share.meeting.$meetingId.tsx +14 -5
  50. package/corpus/templates/clips/desktop/src/app.tsx +1 -1
  51. package/corpus/templates/clips/package.json +1 -0
  52. package/corpus/templates/clips/react-router.config.ts +7 -0
  53. package/corpus/templates/clips/server/plugins/auth.ts +6 -1
  54. package/corpus/templates/clips/shared/prerendered-public-paths.ts +21 -0
  55. package/corpus/templates/clips/shared/share-meta.ts +8 -3
  56. package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +115 -68
  57. package/corpus/templates/content/.agents/skills/turn-into-app/SKILL.md +18 -6
  58. package/corpus/templates/content/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  59. package/corpus/templates/content/app/i18n/index.ts +14 -29
  60. package/corpus/templates/crm/.agents/skills/turn-into-app/SKILL.md +18 -6
  61. package/corpus/templates/crm/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  62. package/corpus/templates/crm/app/i18n/index.ts +14 -29
  63. package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +115 -68
  64. package/corpus/templates/design/.agents/skills/turn-into-app/SKILL.md +18 -6
  65. package/corpus/templates/design/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  66. package/corpus/templates/design/actions/analyze-brand-assets.ts +15 -15
  67. package/corpus/templates/design/actions/import-code.ts +2 -43
  68. package/corpus/templates/design/app/i18n/index.ts +14 -29
  69. package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +115 -68
  70. package/corpus/templates/dispatch/.agents/skills/turn-into-app/SKILL.md +18 -6
  71. package/corpus/templates/dispatch/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  72. package/corpus/templates/dispatch/app/chat-first-pages.ts +747 -0
  73. package/corpus/templates/dispatch/app/i18n-data.ts +182 -1
  74. package/corpus/templates/dispatch/app/routes/settings.tsx +62 -1
  75. package/corpus/templates/dispatch/changelog/2026-08-08-chat-first-navigation-keeps-conversations-central-while-open.md +6 -0
  76. package/corpus/templates/factory/.agents/skills/adding-a-feature/SKILL.md +9 -0
  77. package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +115 -68
  78. package/corpus/templates/factory/.agents/skills/turn-into-app/SKILL.md +18 -6
  79. package/corpus/templates/factory/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  80. package/corpus/templates/factory/AGENTS.md +40 -49
  81. package/corpus/templates/factory/actions/babysit-agent-native-pull-request.ts +66 -0
  82. package/corpus/templates/factory/actions/evaluate-triage-item.ts +37 -0
  83. package/corpus/templates/factory/actions/get-slack-feedback-context.ts +20 -0
  84. package/corpus/templates/factory/actions/get-triage-item.ts +25 -4
  85. package/corpus/templates/factory/actions/govern-agent-native-pull-request.ts +55 -0
  86. package/corpus/templates/factory/actions/ingest-github-observation.ts +21 -0
  87. package/corpus/templates/factory/actions/list-factory-audit.ts +118 -0
  88. package/corpus/templates/factory/actions/list-factory-automations.ts +2 -1
  89. package/corpus/templates/factory/actions/list-triage-items.ts +24 -2
  90. package/corpus/templates/factory/actions/poll-github-sources.ts +60 -0
  91. package/corpus/templates/factory/actions/poll-sentry-errors.ts +39 -0
  92. package/corpus/templates/factory/actions/poll-slack-channel.ts +45 -1
  93. package/corpus/templates/factory/actions/run-factory-automation.ts +1 -1
  94. package/corpus/templates/factory/actions/save-factory-automation.ts +2 -2
  95. package/corpus/templates/factory/actions/start-builder-for-item.ts +51 -0
  96. package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +685 -0
  97. package/corpus/templates/factory/app/hooks/use-navigation-state.ts +6 -0
  98. package/corpus/templates/factory/app/i18n/en-US.ts +25 -0
  99. package/corpus/templates/factory/app/routes/factory.tsx +203 -118
  100. package/corpus/templates/factory/changelog/2026-08-08-scheduler-health-moves-to-settings.md +6 -0
  101. package/corpus/templates/factory/server/db/schema.ts +37 -0
  102. package/corpus/templates/factory/server/lib/require-factory-automation.ts +5 -1
  103. package/corpus/templates/factory/server/plugins/factory-migrations.ts +29 -0
  104. package/corpus/templates/factory/server/triage/audit.ts +79 -0
  105. package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +115 -68
  106. package/corpus/templates/forms/.agents/skills/turn-into-app/SKILL.md +18 -6
  107. package/corpus/templates/forms/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  108. package/corpus/templates/forms/app/i18n/index.ts +14 -29
  109. package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +115 -68
  110. package/corpus/templates/macros/.agents/skills/turn-into-app/SKILL.md +18 -6
  111. package/corpus/templates/macros/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  112. package/corpus/templates/macros/app/i18n/index.ts +14 -29
  113. package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +115 -68
  114. package/corpus/templates/mail/.agents/skills/turn-into-app/SKILL.md +18 -6
  115. package/corpus/templates/mail/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  116. package/corpus/templates/mail/app/i18n/index.ts +14 -29
  117. package/corpus/templates/plan/.agents/skills/adding-a-feature/SKILL.md +9 -0
  118. package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +115 -68
  119. package/corpus/templates/plan/.agents/skills/turn-into-app/SKILL.md +18 -6
  120. package/corpus/templates/plan/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  121. package/corpus/templates/plan/app/components/plan/wireframe/Wireframe.tsx +7 -7
  122. package/corpus/templates/plan/app/i18n/index.ts +14 -29
  123. package/corpus/templates/plan/app/lib/plan-document-title.ts +3 -1
  124. package/corpus/templates/plan/app/root.tsx +1 -0
  125. package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +115 -68
  126. package/corpus/templates/slides/.agents/skills/turn-into-app/SKILL.md +18 -6
  127. package/corpus/templates/slides/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  128. package/corpus/templates/slides/actions/analyze-brand-assets.ts +15 -15
  129. package/corpus/templates/slides/actions/import-code.ts +2 -43
  130. package/corpus/templates/slides/app/i18n/index.ts +14 -29
  131. package/corpus/templates/slides/server/routes/api/preview-images.get.ts +4 -1
  132. package/corpus/templates/tasks/.agents/skills/adding-a-feature/SKILL.md +9 -0
  133. package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +115 -68
  134. package/corpus/templates/tasks/.agents/skills/turn-into-app/SKILL.md +18 -6
  135. package/corpus/templates/tasks/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  136. package/corpus/templates/tasks/app/components/layout/HeaderActions.tsx +1 -84
  137. package/corpus/templates/tasks/app/hooks/use-mobile.tsx +1 -21
  138. package/corpus/templates/tasks/app/i18n/index.ts +14 -29
  139. package/dist/agent/engine/ai-sdk-engine.js +2 -1
  140. package/dist/agent/engine/builder-engine.d.ts +11 -1
  141. package/dist/agent/engine/builder-engine.js +11 -4
  142. package/dist/agent/engine/openai-compatible-endpoint.d.ts +2 -0
  143. package/dist/agent/engine/openai-compatible-endpoint.js +5 -1
  144. package/dist/agent/engine/provider-endpoint-validation.d.ts +9 -0
  145. package/dist/agent/engine/provider-endpoint-validation.js +26 -0
  146. package/dist/agent/engine/provider-env-vars.d.ts +1 -1
  147. package/dist/agent/engine/provider-env-vars.js +1 -1
  148. package/dist/agent/engine/registry.d.ts +8 -6
  149. package/dist/agent/engine/registry.js +37 -24
  150. package/dist/agent/tool-search.d.ts +1 -0
  151. package/dist/agent/tool-search.js +17 -1
  152. package/dist/automations/service.js +4 -10
  153. package/dist/brand-kit/brand-signals.d.ts +13 -0
  154. package/dist/brand-kit/brand-signals.js +15 -0
  155. package/dist/brand-kit/index.d.ts +2 -2
  156. package/dist/brand-kit/index.js +1 -1
  157. package/dist/chat-threads/store.d.ts +2 -0
  158. package/dist/chat-threads/store.js +1 -1
  159. package/dist/cli/agent-plugin.d.ts +5 -2
  160. package/dist/cli/agent-plugin.js +17 -9
  161. package/dist/cli/code-agent-executor.js +25 -5
  162. package/dist/cli/code-agent-mcp-config.d.ts +21 -0
  163. package/dist/cli/code-agent-mcp-config.js +103 -0
  164. package/dist/cli/plan-blocks.d.ts +3 -18
  165. package/dist/cli/plan-blocks.js +2 -95
  166. package/dist/cli/plan-publish-store.d.ts +2 -61
  167. package/dist/cli/plan-publish-store.js +2 -127
  168. package/dist/cli/skills-content/connection.d.ts +1 -1
  169. package/dist/cli/skills-content/connection.js +1 -52
  170. package/dist/cli/skills-content/visual-recap-skill.d.ts +1 -1
  171. package/dist/cli/skills-content/visual-recap-skill.js +1 -553
  172. package/dist/client/NewWorkspaceAppFlow.js +4 -1
  173. package/dist/client/agent-chat/index.d.ts +4 -1
  174. package/dist/client/agent-chat/index.js +4 -1
  175. package/dist/client/agent-engine-key.d.ts +14 -4
  176. package/dist/client/agent-engine-key.js +51 -5
  177. package/dist/client/agent-page/AgentTabsPage.d.ts +1 -0
  178. package/dist/client/agent-page/AgentTabsPage.js +4 -3
  179. package/dist/client/agent-provider-catalog.d.ts +20 -0
  180. package/dist/client/agent-provider-catalog.js +100 -0
  181. package/dist/client/app-providers.d.ts +3 -1
  182. package/dist/client/app-providers.js +50 -5
  183. package/dist/client/blocks/index.d.ts +1 -0
  184. package/dist/client/blocks/index.js +1 -0
  185. package/dist/client/chat/run-recovery.js +4 -48
  186. package/dist/client/chat/runtime.js +63 -0
  187. package/dist/client/chat-first/agents-pane.d.ts +2 -0
  188. package/dist/client/chat-first/agents-pane.js +6 -0
  189. package/dist/client/chat-first/app-pane.d.ts +2 -0
  190. package/dist/client/chat-first/app-pane.js +6 -0
  191. package/dist/client/chat-first/apps-rail.d.ts +2 -0
  192. package/dist/client/chat-first/apps-rail.js +103 -0
  193. package/dist/client/chat-first/browser-pane.d.ts +2 -0
  194. package/dist/client/chat-first/browser-pane.js +64 -0
  195. package/dist/client/chat-first/chat-history.d.ts +12 -0
  196. package/dist/client/chat-first/chat-history.js +10 -0
  197. package/dist/client/chat-first/copy.d.ts +2 -0
  198. package/dist/client/chat-first/copy.js +117 -0
  199. package/dist/client/chat-first/index.d.ts +13 -0
  200. package/dist/client/chat-first/index.js +12 -0
  201. package/dist/client/chat-first/primary-nav.d.ts +8 -0
  202. package/dist/client/chat-first/primary-nav.js +6 -0
  203. package/dist/client/chat-first/session-watch-pane.d.ts +2 -0
  204. package/dist/client/chat-first/session-watch-pane.js +9 -0
  205. package/dist/client/chat-first/surface-panel.d.ts +9 -0
  206. package/dist/client/chat-first/surface-panel.js +9 -0
  207. package/dist/client/chat-first/surface-tabs.d.ts +9 -0
  208. package/dist/client/chat-first/surface-tabs.js +74 -0
  209. package/dist/client/chat-first/types.d.ts +74 -0
  210. package/dist/client/chat-first/types.js +1 -0
  211. package/dist/client/chat-first-agent-activity.d.ts +11 -0
  212. package/dist/client/chat-first-agent-activity.js +51 -0
  213. package/dist/client/chat-first-surface-panel-toggle.d.ts +5 -0
  214. package/dist/client/chat-first-surface-panel-toggle.js +6 -0
  215. package/dist/client/chat-first.d.ts +208 -0
  216. package/dist/client/chat-first.js +817 -0
  217. package/dist/client/extensions/ExtensionViewer.js +8 -1
  218. package/dist/client/i18n.d.ts +14 -0
  219. package/dist/client/i18n.js +18 -0
  220. package/dist/client/resources/McpIntegrationDialog.js +3 -2
  221. package/dist/client/resources/McpServerDetail.js +6 -11
  222. package/dist/client/resources/index.d.ts +1 -0
  223. package/dist/client/resources/index.js +1 -0
  224. package/dist/client/resources/use-mcp-servers.d.ts +20 -0
  225. package/dist/client/resources/use-mcp-servers.js +82 -46
  226. package/dist/client/settings/ProviderSetupForm.d.ts +21 -0
  227. package/dist/client/settings/ProviderSetupForm.js +145 -0
  228. package/dist/client/settings/SettingsPanel.js +52 -49
  229. package/dist/client/settings/index.d.ts +3 -0
  230. package/dist/client/settings/index.js +3 -0
  231. package/dist/coding-tools/run-code.d.ts +5 -0
  232. package/dist/coding-tools/run-code.js +196 -36
  233. package/dist/coding-tools/tool-orchestration.d.ts +10 -0
  234. package/dist/coding-tools/tool-orchestration.js +107 -0
  235. package/dist/collab/routes.d.ts +1 -1
  236. package/dist/collab/struct-routes.d.ts +1 -1
  237. package/dist/jobs/background-automation-runner.js +19 -2
  238. package/dist/jobs/frontmatter.d.ts +9 -0
  239. package/dist/jobs/frontmatter.js +16 -0
  240. package/dist/jobs/scheduler-health.d.ts +20 -0
  241. package/dist/jobs/scheduler-health.js +86 -1
  242. package/dist/jobs/scheduler.js +46 -9
  243. package/dist/jobs/tools.d.ts +1 -1
  244. package/dist/jobs/tools.js +2 -7
  245. package/dist/localization/default-messages.d.ts +20 -0
  246. package/dist/localization/default-messages.js +25 -5
  247. package/dist/mcp-client/routes.d.ts +3 -0
  248. package/dist/mcp-client/routes.js +14 -0
  249. package/dist/notifications/routes.d.ts +1 -1
  250. package/dist/observability/routes.d.ts +3 -3
  251. package/dist/onboarding/app-profile.js +1 -1
  252. package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
  253. package/dist/provider-api/actions/provider-api.d.ts +11 -11
  254. package/dist/scripts/agent-engines/test-agent-engine.js +34 -10
  255. package/dist/secrets/routes.d.ts +6 -6
  256. package/dist/server/agent-chat/run-code-tools.d.ts +1 -1
  257. package/dist/server/agent-chat/run-code-tools.js +3 -1
  258. package/dist/server/agent-chat-plugin.js +6 -6
  259. package/dist/server/agent-engine-api-key-route.js +43 -12
  260. package/dist/server/agents-bundle.d.ts +2 -0
  261. package/dist/server/agents-bundle.js +32 -2
  262. package/dist/server/auth.js +21 -5
  263. package/dist/server/credential-provider.d.ts +8 -2
  264. package/dist/server/credential-provider.js +14 -9
  265. package/dist/server/design-token-utils.d.ts +18 -0
  266. package/dist/server/design-token-utils.js +31 -0
  267. package/dist/server/onboarding-html.js +22 -2
  268. package/dist/server/transcribe-voice.d.ts +1 -1
  269. package/dist/shared/chat-first-app-creation.d.ts +19 -0
  270. package/dist/shared/chat-first-app-creation.js +75 -0
  271. package/dist/shared/document-title.d.ts +7 -0
  272. package/dist/shared/document-title.js +29 -0
  273. package/dist/shared/index.d.ts +2 -0
  274. package/dist/shared/index.js +2 -0
  275. package/dist/styles/chat-history-list.css +16 -0
  276. package/dist/templates/chat/.agents/skills/adding-a-feature/SKILL.md +9 -0
  277. package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
  278. package/dist/templates/chat/.agents/skills/turn-into-app/SKILL.md +18 -6
  279. package/dist/templates/chat/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  280. package/dist/templates/chat/app/i18n/index.ts +14 -29
  281. package/dist/templates/default/.agents/skills/adding-a-feature/SKILL.md +9 -0
  282. package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +115 -68
  283. package/dist/templates/default/.agents/skills/turn-into-app/SKILL.md +18 -6
  284. package/dist/templates/default/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  285. package/dist/templates/default/app/i18n/index.ts +14 -29
  286. package/dist/templates/default/react-router.config.ts +18 -0
  287. package/dist/templates/headless/.agents/skills/turn-into-app/SKILL.md +18 -6
  288. package/dist/templates/headless/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  289. package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +9 -0
  290. package/dist/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +22 -9
  291. package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +115 -68
  292. package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +18 -6
  293. package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  294. package/dist/templates/workspace-core/.agents/skills/workspace-conventions/SKILL.md +7 -0
  295. package/dist/triggers/dispatcher.js +1 -8
  296. package/docs/content/environment-variables.mdx +39 -38
  297. package/package.json +5 -4
  298. package/src/templates/chat/.agents/skills/adding-a-feature/SKILL.md +9 -0
  299. package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
  300. package/src/templates/chat/.agents/skills/turn-into-app/SKILL.md +18 -6
  301. package/src/templates/chat/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  302. package/src/templates/chat/app/i18n/index.ts +14 -29
  303. package/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +9 -0
  304. package/src/templates/default/.agents/skills/frontend-design/SKILL.md +115 -68
  305. package/src/templates/default/.agents/skills/turn-into-app/SKILL.md +18 -6
  306. package/src/templates/default/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  307. package/src/templates/default/app/i18n/index.ts +14 -29
  308. package/src/templates/default/react-router.config.ts +18 -0
  309. package/src/templates/headless/.agents/skills/turn-into-app/SKILL.md +18 -6
  310. package/src/templates/headless/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  311. package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +9 -0
  312. package/src/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +22 -9
  313. package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +115 -68
  314. package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +18 -6
  315. package/src/templates/workspace-core/.agents/skills/turn-into-app/references/fresh-project.md +8 -1
  316. package/src/templates/workspace-core/.agents/skills/workspace-conventions/SKILL.md +7 -0
  317. package/corpus/templates/plan/app/components/plan/wireframe/sanitize-html.ts +0 -343
@@ -3,7 +3,7 @@ const LLM_CAPABILITY = {
3
3
  label: "AI model",
4
4
  required: true,
5
5
  builderIncluded: true,
6
- keySummary: "One model key: Anthropic, OpenAI, Gemini, Groq, Mistral, or Cohere",
6
+ keySummary: "One model key or local connection: Anthropic, OpenAI, OpenRouter, Gemini, Groq, Mistral, Cohere, or Ollama",
7
7
  why: "The agent uses a language model to understand requests and produce answers.",
8
8
  };
9
9
  const DESIGN_SYSTEM_INTELLIGENCE_CAPABILITY = {
@@ -75,8 +75,9 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
75
75
  user: "user";
76
76
  }>>;
77
77
  }, z.core.$strip>>, {
78
- deleted?: undefined;
79
78
  id?: undefined;
79
+ provider?: undefined;
80
+ deleted?: undefined;
80
81
  providers: {
81
82
  id: string;
82
83
  label: string;
@@ -87,15 +88,14 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
87
88
  updatedAt: number;
88
89
  }[];
89
90
  count: number;
90
- provider?: undefined;
91
91
  found?: undefined;
92
92
  registered?: undefined;
93
93
  label?: undefined;
94
94
  message?: undefined;
95
95
  } | {
96
- deleted?: undefined;
97
96
  count?: undefined;
98
97
  id?: undefined;
98
+ deleted?: undefined;
99
99
  providers?: undefined;
100
100
  found: boolean;
101
101
  provider: import("../custom-registry.js").CustomProviderConfig;
@@ -103,10 +103,10 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
103
103
  label?: undefined;
104
104
  message?: undefined;
105
105
  } | {
106
- deleted?: undefined;
107
106
  count?: undefined;
108
- providers?: undefined;
109
107
  provider?: undefined;
108
+ deleted?: undefined;
109
+ providers?: undefined;
110
110
  found: boolean;
111
111
  id: string;
112
112
  registered?: undefined;
@@ -114,8 +114,8 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
114
114
  message?: undefined;
115
115
  } | {
116
116
  count?: undefined;
117
- providers?: undefined;
118
117
  provider?: undefined;
118
+ providers?: undefined;
119
119
  found?: undefined;
120
120
  deleted: boolean;
121
121
  id: string;
@@ -123,10 +123,10 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
123
123
  label?: undefined;
124
124
  message?: undefined;
125
125
  } | {
126
- deleted?: undefined;
127
126
  count?: undefined;
128
- providers?: undefined;
129
127
  provider?: undefined;
128
+ deleted?: undefined;
129
+ providers?: undefined;
130
130
  found?: undefined;
131
131
  registered: boolean;
132
132
  id: string;
@@ -311,9 +311,7 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
311
311
  notes?: string | undefined;
312
312
  scope?: "org" | "user" | undefined;
313
313
  }, {
314
- message?: undefined;
315
314
  id?: undefined;
316
- provider?: undefined;
317
315
  deleted?: undefined;
318
316
  providers: {
319
317
  id: string;
@@ -325,44 +323,46 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
325
323
  updatedAt: number;
326
324
  }[];
327
325
  count: number;
326
+ provider?: undefined;
328
327
  found?: undefined;
329
328
  registered?: undefined;
330
329
  label?: undefined;
331
- } | {
332
330
  message?: undefined;
333
- count?: undefined;
331
+ } | {
334
332
  id?: undefined;
335
333
  deleted?: undefined;
334
+ count?: undefined;
336
335
  providers?: undefined;
337
336
  found: boolean;
338
337
  provider: import("../custom-registry.js").CustomProviderConfig;
339
338
  registered?: undefined;
340
339
  label?: undefined;
341
- } | {
342
340
  message?: undefined;
343
- count?: undefined;
344
- provider?: undefined;
341
+ } | {
345
342
  deleted?: undefined;
343
+ count?: undefined;
346
344
  providers?: undefined;
345
+ provider?: undefined;
347
346
  found: boolean;
348
347
  id: string;
349
348
  registered?: undefined;
350
349
  label?: undefined;
351
- } | {
352
350
  message?: undefined;
351
+ } | {
353
352
  count?: undefined;
354
- provider?: undefined;
355
353
  providers?: undefined;
354
+ provider?: undefined;
356
355
  found?: undefined;
357
356
  deleted: boolean;
358
357
  id: string;
359
358
  registered?: undefined;
360
359
  label?: undefined;
360
+ message?: undefined;
361
361
  } | {
362
- count?: undefined;
363
- provider?: undefined;
364
362
  deleted?: undefined;
363
+ count?: undefined;
365
364
  providers?: undefined;
365
+ provider?: undefined;
366
366
  found?: undefined;
367
367
  registered: boolean;
368
368
  id: string;
@@ -2,7 +2,8 @@
2
2
  * test-agent-engine — sends a trivial prompt to verify the engine is working.
3
3
  */
4
4
  import { getAgentEngineEntry, registerBuiltinEngines, } from "../../agent/engine/index.js";
5
- import { normalizeOpenAiBaseUrl, OPENAI_BASE_URL_ENV_VAR, } from "../../agent/engine/openai-compatible-endpoint.js";
5
+ import { OLLAMA_BASE_URL_ENV_VAR, OPENAI_BASE_URL_ENV_VAR, } from "../../agent/engine/openai-compatible-endpoint.js";
6
+ import { validateProviderBaseUrl } from "../../agent/engine/provider-endpoint-validation.js";
6
7
  import { canUseDeployCredentialFallbackForRequest, readDeployCredentialEnv, resolveSecret, } from "../../server/credential-provider.js";
7
8
  export const tool = {
8
9
  description: "Test an agent engine by sending a trivial prompt and measuring latency. Useful for verifying API keys and connectivity before switching engines.",
@@ -31,13 +32,30 @@ async function resolveAgentEngineSecret(key) {
31
32
  if (value)
32
33
  return value;
33
34
  }
34
- catch {
35
- // Fall through to deploy env when this request is allowed to use it.
35
+ catch (error) {
36
+ if (!canUseDeployCredentialFallbackForRequest(key))
37
+ throw error;
38
+ console.warn("[test-agent-engine] Saved provider secret unavailable; using deploy configuration.", { key, error });
36
39
  }
37
40
  return canUseDeployCredentialFallbackForRequest(key)
38
41
  ? readDeployCredentialEnv(key)
39
42
  : undefined;
40
43
  }
44
+ async function resolveAgentEngineEndpoint(key) {
45
+ const value = await resolveSecret(key);
46
+ if (value) {
47
+ return validateProviderBaseUrl(value, {
48
+ allowLocalOllama: key === OLLAMA_BASE_URL_ENV_VAR &&
49
+ process.env.NODE_ENV === "development",
50
+ });
51
+ }
52
+ if (!canUseDeployCredentialFallbackForRequest(key))
53
+ return undefined;
54
+ const deployValue = readDeployCredentialEnv(key);
55
+ return deployValue
56
+ ? validateProviderBaseUrl(deployValue, { allowPrivate: true })
57
+ : undefined;
58
+ }
41
59
  function canUseDeployEnvForEntry(entry) {
42
60
  if (entry.requiredEnvVars.length === 0)
43
61
  return true;
@@ -50,13 +68,19 @@ async function createEngineConfig(entry, args) {
50
68
  : undefined,
51
69
  allowEnvFallback: canUseDeployEnvForEntry(entry),
52
70
  };
53
- if (entry.name === "ai-sdk:openai") {
54
- const rawBaseUrl = args.baseUrl?.trim()
55
- ? args.baseUrl
56
- : await resolveAgentEngineSecret(OPENAI_BASE_URL_ENV_VAR);
57
- if (rawBaseUrl) {
58
- config.baseUrl = normalizeOpenAiBaseUrl(rawBaseUrl);
59
- }
71
+ if (entry.name === "ai-sdk:openai" || entry.name === "ai-sdk:ollama") {
72
+ const endpointKey = entry.name === "ai-sdk:ollama"
73
+ ? OLLAMA_BASE_URL_ENV_VAR
74
+ : OPENAI_BASE_URL_ENV_VAR;
75
+ const explicitBaseUrl = args.baseUrl?.trim();
76
+ const baseUrl = explicitBaseUrl
77
+ ? await validateProviderBaseUrl(explicitBaseUrl, {
78
+ allowLocalOllama: entry.name === "ai-sdk:ollama" &&
79
+ process.env.NODE_ENV === "development",
80
+ })
81
+ : await resolveAgentEngineEndpoint(endpointKey);
82
+ if (baseUrl)
83
+ config.baseUrl = baseUrl;
60
84
  }
61
85
  return config;
62
86
  }
@@ -37,17 +37,17 @@ export declare function createWriteSecretHandler(): import("h3").EventHandlerWit
37
37
  ok?: undefined;
38
38
  status?: undefined;
39
39
  } | {
40
+ error?: undefined;
40
41
  ok: boolean;
41
42
  status: string;
42
- error?: undefined;
43
43
  } | {
44
44
  ok?: undefined;
45
45
  error: string;
46
46
  removed?: undefined;
47
47
  } | {
48
+ error?: undefined;
48
49
  ok: boolean;
49
50
  removed: boolean;
50
- error?: undefined;
51
51
  }>>;
52
52
  /**
53
53
  * POST /_agent-native/secrets/:key/test — validate an optional candidate value
@@ -58,13 +58,13 @@ export declare function createTestSecretHandler(): import("h3").EventHandlerWith
58
58
  error: string;
59
59
  note?: undefined;
60
60
  } | {
61
+ error?: undefined;
61
62
  ok: boolean;
62
63
  note?: undefined;
63
- error?: undefined;
64
64
  } | {
65
+ error?: undefined;
65
66
  ok: boolean;
66
67
  note: string;
67
- error?: undefined;
68
68
  } | {
69
69
  note?: undefined;
70
70
  ok: boolean;
@@ -95,11 +95,11 @@ export interface AdHocSecretPayload {
95
95
  export declare function createAdHocSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<AdHocSecretPayload[] | {
96
96
  error: string;
97
97
  } | {
98
+ error?: undefined;
98
99
  ok: boolean;
99
100
  key: string;
100
- error?: undefined;
101
101
  } | {
102
+ error?: undefined;
102
103
  ok: boolean;
103
104
  removed: boolean;
104
- error?: undefined;
105
105
  }>>;
@@ -1,7 +1,7 @@
1
1
  import type { ActionEntry } from "../../agent/production-agent.js";
2
2
  /**
3
3
  * Load the sandboxed code-execution tool entries for one action registry:
4
- * `run-code` plus its `get-code-execution` poll companion. The poll tool is
4
+ * `run-code`, bounded `tool-orchestration`, plus its `get-code-execution` poll companion. The poll tool is
5
5
  * registered ALONGSIDE run-code everywhere run-code appears, so the durable
6
6
  * background-execution guidance run-code emits ("check it with
7
7
  * get-code-execution") always points at a callable tool. Returns an empty
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Load the sandboxed code-execution tool entries for one action registry:
3
- * `run-code` plus its `get-code-execution` poll companion. The poll tool is
3
+ * `run-code`, bounded `tool-orchestration`, plus its `get-code-execution` poll companion. The poll tool is
4
4
  * registered ALONGSIDE run-code everywhere run-code appears, so the durable
5
5
  * background-execution guidance run-code emits ("check it with
6
6
  * get-code-execution") always points at a callable tool. Returns an empty
@@ -13,8 +13,10 @@
13
13
  export async function loadRunCodeToolEntries(supplier, runCodeOptions) {
14
14
  try {
15
15
  const { createRunCodeEntry, createGetCodeExecutionEntry } = await import("../../coding-tools/run-code.js");
16
+ const { createToolOrchestrationEntry } = await import("../../coding-tools/tool-orchestration.js");
16
17
  const entries = {
17
18
  "run-code": createRunCodeEntry(supplier, runCodeOptions),
19
+ "tool-orchestration": createToolOrchestrationEntry(supplier),
18
20
  "get-code-execution": createGetCodeExecutionEntry(),
19
21
  };
20
22
  // Data programs: stored JS scripts executed through this same run-code
@@ -876,11 +876,11 @@ export function createAgentChatPlugin(options) {
876
876
  : rawEnvCodeExec === "off"
877
877
  ? "off"
878
878
  : (options?.codeExecution?.production ?? "off");
879
- // Forward-declaration for the production run-code bridge supplier.
880
- // Must come before createRunCodeEntry so the closure can capture it.
879
+ // Forward-declaration for the production code-execution bridge supplier.
880
+ // Must come before the code entries are created so their closures can capture it.
881
881
  let prodRunCodeToolActions = {};
882
882
  let leanRunCodeToolActions = {};
883
- // Sandboxed run-code tool (+ its get-code-execution poll companion):
883
+ // Sandboxed run-code, bounded tool-orchestration, and get-code-execution:
884
884
  // available in "sandboxed" or "trusted" prod modes and always in dev
885
885
  // mode. See loadRunCodeToolEntries for the registration contract.
886
886
  const runCodeTool = await loadRunCodeToolEntries(
@@ -914,7 +914,7 @@ export function createAgentChatPlugin(options) {
914
914
  // Forward-declaration: populated after devActions is assembled below.
915
915
  // Must be declared before devRunCodeTool so the closure can close over it.
916
916
  let devRunCodeToolActions = {};
917
- // Always register run-code (+ get-code-execution) in dev mode (when the
917
+ // Always register code execution (+ get-code-execution) in dev mode (when the
918
918
  // coding module loads). devActions is not yet defined at this point; we
919
919
  // use a late-binding supplier so devRunCodeTool can reference the
920
920
  // devActions registry once it is built below (see devHandler block).
@@ -2551,8 +2551,8 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
2551
2551
  // System-prompt note appended when production code execution is enabled.
2552
2552
  const prodCodeExecPromptNote = !canToggle && resolvedProdCodeExec !== "off"
2553
2553
  ? resolvedProdCodeExec === "trusted"
2554
- ? "\n\n<code-execution-mode>Full shell access is enabled (trusted mode). You have bash, read, edit, write, and run-code tools available. Use bash for file discovery, running tests and builds, and project CLIs. Use run-code for sandboxed JavaScript data processing: provider/API pagination, joins, classification, aggregation, and large-response reduction. Use `pnpm action <name>` in bash to invoke registered app actions from the shell.</code-execution-mode>"
2555
- : "\n\n<code-execution-mode>Sandboxed code execution is enabled. The run-code tool lets you execute isolated JavaScript (ESM, top-level await) to fetch, aggregate, and reduce data. Use providerFetch(), providerFetchAll(), providerRequest(), webRead(), and webFetch() inside run-code for authenticated provider calls and compact web/document reduction.</code-execution-mode>"
2554
+ ? "\n\n<code-execution-mode>Full shell access is enabled (trusted mode). You have bash, read, edit, write, and run-code tools available. Use bash for file discovery, running tests and builds, and project CLIs. Use run-code for sandboxed JavaScript data processing: provider/API pagination, joins, classification, aggregation, and large-response reduction. Use tool-orchestration for short bounded fan-out or reduction over read-only tools. Use `pnpm action <name>` in bash to invoke registered app actions from the shell.</code-execution-mode>"
2555
+ : "\n\n<code-execution-mode>Sandboxed code execution is enabled. Use tool-orchestration for short bounded fan-out, joins, and reduction over read-only tools. Use run-code when you need its broader provider/web helpers, workspace staging, or durable background execution. In either tool, authenticated calls go through the provided host globals and results should be reduced before printing.</code-execution-mode>"
2556
2556
  : "";
2557
2557
  const prodHandler = createProductionAgentHandler({
2558
2558
  actions: leanPrompt ? leanActions : prodActions,
@@ -1,6 +1,7 @@
1
1
  import { defineEventHandler, getMethod, setResponseStatus, } from "h3";
2
2
  import { normalizeOpenAiBaseUrl } from "../agent/engine/openai-compatible-endpoint.js";
3
- import { OPENAI_BASE_URL_ENV_VAR, PROVIDER_ENV_META, } from "../agent/engine/provider-env-vars.js";
3
+ import { validateProviderBaseUrl } from "../agent/engine/provider-endpoint-validation.js";
4
+ import { OLLAMA_BASE_URL_ENV_VAR, OPENAI_BASE_URL_ENV_VAR, PROVIDER_ENV_META, } from "../agent/engine/provider-env-vars.js";
4
5
  import { getOrgContext } from "../org/context.js";
5
6
  import { deleteAppSecret, writeAppSecret } from "../secrets/storage.js";
6
7
  import { getSession } from "./auth.js";
@@ -11,15 +12,23 @@ const PROVIDER_TO_ENV_VAR = new Map(Object.entries(PROVIDER_ENV_META).map(([prov
11
12
  meta.envVar,
12
13
  ]));
13
14
  const PROVIDER_ENV_VAR_KEYS = new Set(PROVIDER_TO_ENV_VAR.values());
15
+ const BASE_URL_KEYS = new Set([
16
+ OPENAI_BASE_URL_ENV_VAR,
17
+ OLLAMA_BASE_URL_ENV_VAR,
18
+ ]);
19
+ const OPENAI_PROVIDER_KEY = PROVIDER_TO_ENV_VAR.get("openai") ?? "";
14
20
  export function normalizeAgentEngineApiKeyPayload(body) {
15
21
  const payload = body && typeof body === "object" ? body : {};
16
22
  const raw = payload;
23
+ const provider = typeof raw.provider === "string" ? raw.provider.trim() : "";
17
24
  const key = typeof raw.key === "string"
18
25
  ? raw.key.trim()
19
- : typeof raw.provider === "string"
20
- ? (PROVIDER_TO_ENV_VAR.get(raw.provider.trim()) ?? "")
21
- : "";
22
- if (!key || !PROVIDER_ENV_VAR_KEYS.has(key)) {
26
+ : provider === "ollama"
27
+ ? OLLAMA_BASE_URL_ENV_VAR
28
+ : provider
29
+ ? (PROVIDER_TO_ENV_VAR.get(provider) ?? "")
30
+ : "";
31
+ if (!key || (!PROVIDER_ENV_VAR_KEYS.has(key) && !BASE_URL_KEYS.has(key))) {
23
32
  return {
24
33
  ok: false,
25
34
  statusCode: 400,
@@ -38,11 +47,11 @@ export function normalizeAgentEngineApiKeyPayload(body) {
38
47
  : "";
39
48
  let baseUrl;
40
49
  if (rawBaseUrl.trim()) {
41
- if (key !== PROVIDER_TO_ENV_VAR.get("openai")) {
50
+ if (key !== OPENAI_PROVIDER_KEY && !BASE_URL_KEYS.has(key)) {
42
51
  return {
43
52
  ok: false,
44
53
  statusCode: 400,
45
- error: "Endpoint URL is only supported for OpenAI.",
54
+ error: "Endpoint URL is only supported for OpenAI or Ollama.",
46
55
  };
47
56
  }
48
57
  try {
@@ -57,11 +66,11 @@ export function normalizeAgentEngineApiKeyPayload(body) {
57
66
  }
58
67
  }
59
68
  const clearBaseUrl = raw.clearBaseUrl === true && baseUrl == null;
60
- if (clearBaseUrl && key !== PROVIDER_TO_ENV_VAR.get("openai")) {
69
+ if (clearBaseUrl && key !== OPENAI_PROVIDER_KEY && !BASE_URL_KEYS.has(key)) {
61
70
  return {
62
71
  ok: false,
63
72
  statusCode: 400,
64
- error: "Endpoint URL is only supported for OpenAI.",
73
+ error: "Endpoint URL is only supported for OpenAI or Ollama.",
65
74
  };
66
75
  }
67
76
  if (!value && !baseUrl && !clearBaseUrl) {
@@ -130,6 +139,20 @@ export function createAgentEngineApiKeyHandler() {
130
139
  setResponseStatus(event, resolved.statusCode);
131
140
  return { error: resolved.error };
132
141
  }
142
+ if (payload.baseUrl) {
143
+ try {
144
+ await validateProviderBaseUrl(payload.baseUrl, {
145
+ allowLocalOllama: payload.key === OLLAMA_BASE_URL_ENV_VAR &&
146
+ process.env.NODE_ENV === "development",
147
+ });
148
+ }
149
+ catch (err) {
150
+ setResponseStatus(event, 400);
151
+ return {
152
+ error: err instanceof Error ? err.message : String(err),
153
+ };
154
+ }
155
+ }
133
156
  if (payload.value) {
134
157
  await writeAppSecret({
135
158
  key: payload.key,
@@ -144,7 +167,9 @@ export function createAgentEngineApiKeyHandler() {
144
167
  }
145
168
  if (payload.baseUrl) {
146
169
  await writeAppSecret({
147
- key: OPENAI_BASE_URL_ENV_VAR,
170
+ key: payload.key === OLLAMA_BASE_URL_ENV_VAR
171
+ ? OLLAMA_BASE_URL_ENV_VAR
172
+ : OPENAI_BASE_URL_ENV_VAR,
148
173
  value: payload.baseUrl,
149
174
  scope: resolved.target.scope,
150
175
  scopeId: resolved.target.scopeId,
@@ -152,7 +177,9 @@ export function createAgentEngineApiKeyHandler() {
152
177
  }
153
178
  else if (payload.clearBaseUrl) {
154
179
  await deleteAppSecret({
155
- key: OPENAI_BASE_URL_ENV_VAR,
180
+ key: payload.key === OLLAMA_BASE_URL_ENV_VAR
181
+ ? OLLAMA_BASE_URL_ENV_VAR
182
+ : OPENAI_BASE_URL_ENV_VAR,
156
183
  scope: resolved.target.scope,
157
184
  scopeId: resolved.target.scopeId,
158
185
  });
@@ -161,7 +188,11 @@ export function createAgentEngineApiKeyHandler() {
161
188
  ok: true,
162
189
  key: payload.key,
163
190
  ...(payload.baseUrl || payload.clearBaseUrl
164
- ? { baseUrlKey: OPENAI_BASE_URL_ENV_VAR }
191
+ ? {
192
+ baseUrlKey: payload.key === OLLAMA_BASE_URL_ENV_VAR
193
+ ? OLLAMA_BASE_URL_ENV_VAR
194
+ : OPENAI_BASE_URL_ENV_VAR,
195
+ }
165
196
  : {}),
166
197
  scope: resolved.target.scope,
167
198
  };
@@ -96,6 +96,8 @@ export interface AgentsBundle {
96
96
  }
97
97
  export interface AgentsBundleReadOptions {
98
98
  instructions?: AgentNativeInstructionsConfig;
99
+ /** Additional skill roots supplied by a local host, such as installed plugins. */
100
+ additionalSkillDirs?: string[];
99
101
  }
100
102
  export interface AgentInstructionPaths {
101
103
  runtime: string;
@@ -230,6 +230,27 @@ function readSkillsDir(skillsDir, rootForRelative, out, skipExistingNames) {
230
230
  }
231
231
  }
232
232
  }
233
+ function readNestedSkillsDir(skillsDir, rootForRelative, out) {
234
+ if (!fs.existsSync(skillsDir))
235
+ return;
236
+ readSkillsDir(skillsDir, rootForRelative, out, true);
237
+ let entries;
238
+ try {
239
+ entries = fs.readdirSync(skillsDir, { withFileTypes: true });
240
+ }
241
+ catch {
242
+ return;
243
+ }
244
+ for (const entry of entries) {
245
+ if (!entry.isDirectory() || entry.name === "." || entry.name === "..") {
246
+ continue;
247
+ }
248
+ const nestedDir = path.join(skillsDir, entry.name);
249
+ if (fs.existsSync(path.join(nestedDir, "SKILL.md")))
250
+ continue;
251
+ readSkillsDir(nestedDir, rootForRelative, out, true);
252
+ }
253
+ }
233
254
  /**
234
255
  * Read AGENTS.md + all skills directly from the filesystem rooted at `cwd`.
235
256
  * Optionally also reads a workspace-core's AGENTS.md and skills directory
@@ -256,9 +277,9 @@ export function readAgentsBundleFromFs(cwd, workspaceSource = null, options = {}
256
277
  // overwrite the template's. `.agents/skills` is canonical; `.agent/skills`
257
278
  // is accepted as a legacy alias and does not override canonical skills.
258
279
  const skills = {};
259
- for (const [index, relSkillsDir] of TEMPLATE_SKILLS_DIRS.entries()) {
280
+ for (const relSkillsDir of TEMPLATE_SKILLS_DIRS) {
260
281
  try {
261
- readSkillsDir(path.join(cwd, relSkillsDir), cwd, skills, index > 0);
282
+ readNestedSkillsDir(path.join(cwd, relSkillsDir), cwd, skills);
262
283
  }
263
284
  catch { }
264
285
  }
@@ -268,6 +289,15 @@ export function readAgentsBundleFromFs(cwd, workspaceSource = null, options = {}
268
289
  }
269
290
  catch { }
270
291
  }
292
+ for (const skillsDir of options.additionalSkillDirs ?? []) {
293
+ try {
294
+ readNestedSkillsDir(skillsDir, cwd, skills);
295
+ }
296
+ catch (error) {
297
+ // Optional host-provided skills must not make the coding session fail.
298
+ console.warn("[agents-bundle] Failed to load optional host-provided skills", { skillsDir, error });
299
+ }
300
+ }
271
301
  return {
272
302
  // Keep the old field useful for callers that only know about the runtime
273
303
  // bundle. Audience-aware consumers should use the explicit fields.
@@ -1678,11 +1678,27 @@ async function createAutoDevAccountForSession(auth, db) {
1678
1678
  function isHostedPreviewRequest(event) {
1679
1679
  const host = getRequestHost(event)?.split(",")[0]?.trim().toLowerCase() ?? "";
1680
1680
  return (host.endsWith(".agent-native.com") ||
1681
- host.endsWith(".builderio.xyz") ||
1681
+ isBuilderPreviewHost(host) ||
1682
+ host.includes("deploy-preview"));
1683
+ }
1684
+ const BUILDER_PREVIEW_LOCAL_DEV_ENV = "AGENT_NATIVE_ALLOW_BUILDER_PREVIEW_LOCAL_DEV";
1685
+ function isBuilderPreviewHost(host) {
1686
+ return (host.endsWith(".builderio.xyz") ||
1682
1687
  host.endsWith(".builderio.dev") ||
1683
1688
  host.endsWith(".builder.codes") ||
1684
- host.endsWith(".builder.my") ||
1685
- host.includes("deploy-preview"));
1689
+ host.endsWith(".builder.my"));
1690
+ }
1691
+ function isBuilderPreviewLocalDevEnabled() {
1692
+ const value = process.env[BUILDER_PREVIEW_LOCAL_DEV_ENV]
1693
+ ?.trim()
1694
+ .toLowerCase();
1695
+ return value === "1" || value === "true";
1696
+ }
1697
+ function isBuilderPreviewLocalDevRequest(event) {
1698
+ if (!isBuilderPreviewLocalDevEnabled())
1699
+ return false;
1700
+ const host = getRequestHost(event)?.split(",")[0]?.trim().toLowerCase() ?? "";
1701
+ return isBuilderPreviewHost(host);
1686
1702
  }
1687
1703
  export function isLocalDevAuthAllowed(event) {
1688
1704
  const deployPreview = typeof isDeployPreview === "function" && isDeployPreview();
@@ -1690,8 +1706,8 @@ export function isLocalDevAuthAllowed(event) {
1690
1706
  !deployPreview &&
1691
1707
  !isAuthDisabled() &&
1692
1708
  process.env.AGENT_NATIVE_DISABLE_AUTO_DEV_ACCOUNT !== "1" &&
1693
- !isHostedPreviewRequest(event) &&
1694
- isLoopbackRequest(event));
1709
+ ((!isHostedPreviewRequest(event) && isLoopbackRequest(event)) ||
1710
+ isBuilderPreviewLocalDevRequest(event)));
1695
1711
  }
1696
1712
  async function createOrReuseAutoDevSession(auth, config) {
1697
1713
  let session = await createBetterAuthSessionForEmail(AUTO_DEV_ACCOUNT_EMAIL, config);
@@ -85,6 +85,12 @@ export declare function isDeployCredentialFallbackAllowed(): boolean;
85
85
  export declare function canUseDeployCredentialFallbackForRequest(key?: string): boolean;
86
86
  type BuilderCredentialSource = "user" | "org" | "workspace" | "env";
87
87
  export declare function isBuilderPrivateKey(value: string | null | undefined): boolean;
88
+ export interface BuilderCredentialLookupIdentity {
89
+ /** The verified owner of a background run, when it has no browser request. */
90
+ userEmail?: string | null;
91
+ /** The verified organization attached to that run, when one exists. */
92
+ orgId?: string | null;
93
+ }
88
94
  /**
89
95
  * Resolve a Builder credential for the current request. User/org credentials
90
96
  * win; deployment env is only a fallback. This lets local/root .env keys keep
@@ -153,13 +159,13 @@ export interface BuilderCredentialsDetailed {
153
159
  * Callers that only need the plain credential bundle (the historical shape)
154
160
  * should use `resolveBuilderCredentials()` instead.
155
161
  */
156
- export declare function resolveBuilderCredentialsDetailed(): Promise<BuilderCredentialsDetailed>;
162
+ export declare function resolveBuilderCredentialsDetailed(identity?: BuilderCredentialLookupIdentity): Promise<BuilderCredentialsDetailed>;
157
163
  /**
158
164
  * Resolve the Builder assistant credential bundle from one complete scope.
159
165
  * Kept to its original return shape (no `source`/`lookupFailed`) for existing
160
166
  * callers; use `resolveBuilderCredentialsDetailed()` for those fields.
161
167
  */
162
- export declare function resolveBuilderCredentials(): Promise<{
168
+ export declare function resolveBuilderCredentials(identity?: BuilderCredentialLookupIdentity): Promise<{
163
169
  privateKey: string | null;
164
170
  publicKey: string | null;
165
171
  userId: string | null;
@@ -134,6 +134,7 @@ const APP_PROVIDED_DEPLOY_CREDENTIAL_KEYS = new Set([
134
134
  "EMAIL_AGENT_ADDRESS",
135
135
  "OPENAI_API_KEY",
136
136
  "OPENAI_BASE_URL",
137
+ "OLLAMA_BASE_URL",
137
138
  "OPENROUTER_API_KEY",
138
139
  "GOOGLE_CLIENT_ID",
139
140
  "GOOGLE_CLIENT_SECRET",
@@ -444,8 +445,8 @@ async function resolveScopedBuilderCredential(key) {
444
445
  cause: orgLookupCause,
445
446
  };
446
447
  }
447
- async function resolveScopedBuilderCredentials() {
448
- const email = getRequestUserEmail();
448
+ async function resolveScopedBuilderCredentials(identity) {
449
+ const email = identity?.userEmail?.trim() || getRequestUserEmail();
449
450
  if (!email)
450
451
  return { creds: null, lookupFailed: false };
451
452
  const traceLookup = shouldTraceCredentialResolve();
@@ -463,7 +464,7 @@ async function resolveScopedBuilderCredentials() {
463
464
  if (await isCompleteBuilderConnection(userCreds)) {
464
465
  return { creds: userCreds, lookupFailed: false };
465
466
  }
466
- let orgId = getRequestOrgId();
467
+ let orgId = identity?.orgId?.trim() || getRequestOrgId();
467
468
  let orgSource = orgId
468
469
  ? "request"
469
470
  : "none";
@@ -527,8 +528,12 @@ export async function resolveBuilderCredential(key) {
527
528
  const envValue = canUseBuilderDeployCredentialFallbackForRequest()
528
529
  ? (readDeployCredentialEnv(key) ?? null)
529
530
  : null;
530
- if (envValue)
531
+ if (envValue) {
532
+ // A deploy fallback is still useful, but it must not turn a transient
533
+ // credential-store failure into a clean connected result for Builder.
534
+ assertCredentialStoreReadable(scoped);
531
535
  return envValue;
536
+ }
532
537
  // Nothing answered AND the store never gave a real answer: that is not
533
538
  // "not connected", it is "we could not look".
534
539
  assertCredentialStoreReadable(scoped);
@@ -589,8 +594,8 @@ export async function resolveBuilderCredentialSource() {
589
594
  * Callers that only need the plain credential bundle (the historical shape)
590
595
  * should use `resolveBuilderCredentials()` instead.
591
596
  */
592
- export async function resolveBuilderCredentialsDetailed() {
593
- const { creds: scoped, lookupFailed, cause, } = await resolveScopedBuilderCredentials();
597
+ export async function resolveBuilderCredentialsDetailed(identity) {
598
+ const { creds: scoped, lookupFailed, cause, } = await resolveScopedBuilderCredentials(identity);
594
599
  if (scoped) {
595
600
  const { privateKey, publicKey, userId, orgName, orgKind, subscription, subscriptionLevel, subscriptionName, isEnterprise, isFreeAccount, source, } = scoped;
596
601
  return {
@@ -683,8 +688,8 @@ export async function resolveBuilderCredentialsDetailed() {
683
688
  * Kept to its original return shape (no `source`/`lookupFailed`) for existing
684
689
  * callers; use `resolveBuilderCredentialsDetailed()` for those fields.
685
690
  */
686
- export async function resolveBuilderCredentials() {
687
- const { privateKey, publicKey, userId, orgName, orgKind, subscription, subscriptionLevel, subscriptionName, isEnterprise, isFreeAccount, } = await resolveBuilderCredentialsDetailed();
691
+ export async function resolveBuilderCredentials(identity) {
692
+ const { privateKey, publicKey, userId, orgName, orgKind, subscription, subscriptionLevel, subscriptionName, isEnterprise, isFreeAccount, } = await resolveBuilderCredentialsDetailed(identity);
688
693
  return {
689
694
  privateKey,
690
695
  publicKey,
@@ -1210,7 +1215,7 @@ export async function resolveSecretDetailed(key) {
1210
1215
  }
1211
1216
  return {
1212
1217
  value: envFallback,
1213
- lookupFailed: lookupFailed && !envFallback,
1218
+ lookupFailed,
1214
1219
  cause,
1215
1220
  };
1216
1221
  }