@agent-native/core 0.114.16 → 0.115.3

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 (476) hide show
  1. package/agent-native.eject.json +2 -0
  2. package/corpus/README.md +3 -3
  3. package/corpus/core/CHANGELOG.md +41 -0
  4. package/corpus/core/agent-native.eject.json +2 -0
  5. package/corpus/core/docs/content/agent-native-toolkit.mdx +16 -0
  6. package/corpus/core/docs/content/recurring-jobs.mdx +35 -6
  7. package/corpus/core/export-snapshot.json +4 -0
  8. package/corpus/core/package.json +5 -1
  9. package/corpus/core/src/action.ts +22 -1
  10. package/corpus/core/src/agent/production-agent.ts +122 -3
  11. package/corpus/core/src/cli/skills-content/visual-plan-skill.ts +19 -2
  12. package/corpus/core/src/cli/templates-meta.ts +12 -0
  13. package/corpus/core/src/client/AssistantChat.tsx +53 -26
  14. package/corpus/core/src/client/agent-page/AgentJobsTab.tsx +19 -0
  15. package/corpus/core/src/client/agent-page/use-jobs.ts +1 -0
  16. package/corpus/core/src/client/blocks/library/wireframe.tsx +3 -1
  17. package/corpus/core/src/client/chat/message-components.tsx +35 -1
  18. package/corpus/core/src/client/chat/tool-call-display.tsx +38 -3
  19. package/corpus/core/src/connections/catalog.ts +20 -1
  20. package/corpus/core/src/connections/reader.ts +65 -0
  21. package/corpus/core/src/dashboard-storage/index.ts +27 -0
  22. package/corpus/core/src/dashboard-storage/panel-source.ts +168 -0
  23. package/corpus/core/src/dashboard-storage/schema.ts +62 -0
  24. package/corpus/core/src/dashboard-storage/store.ts +333 -0
  25. package/corpus/core/src/deploy/build.ts +95 -16
  26. package/corpus/core/src/eject/provider-api-definitions.ts +1 -0
  27. package/corpus/core/src/eject/workspace-connections.ts +1 -0
  28. package/corpus/core/src/extensions/actions.ts +199 -73
  29. package/corpus/core/src/jobs/actions/list-recurring-jobs.ts +2 -0
  30. package/corpus/core/src/jobs/scheduler.ts +71 -4
  31. package/corpus/core/src/jobs/tools.ts +31 -1
  32. package/corpus/core/src/localization/default-messages.ts +1 -0
  33. package/corpus/core/src/mcp-client/index.ts +6 -0
  34. package/corpus/core/src/provider-api/actions/provider-api.ts +1 -1
  35. package/corpus/core/src/provider-api/index.ts +190 -5
  36. package/corpus/core/src/secrets/register-framework-secrets.ts +8 -0
  37. package/corpus/core/src/server/agent-chat/context-tools.ts +9 -0
  38. package/corpus/core/src/server/agent-chat/framework-prompts.ts +2 -2
  39. package/corpus/core/src/server/agent-chat-plugin.ts +22 -2
  40. package/corpus/core/src/server/core-routes-plugin.ts +1 -0
  41. package/corpus/core/src/server/credential-provider.ts +9 -3
  42. package/corpus/core/src/server/workspace-provider-oauth.ts +181 -4
  43. package/corpus/core/src/styles/agent-native.css +45 -2
  44. package/corpus/core/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +27 -0
  45. package/corpus/core/src/templates/default/.agents/skills/app-branding/SKILL.md +159 -0
  46. package/corpus/core/src/templates/default/.agents/skills/app-permissions/SKILL.md +155 -0
  47. package/corpus/core/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +27 -0
  48. package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +27 -0
  49. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +31 -18
  50. package/corpus/core/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +15 -0
  51. package/corpus/core/src/triggers/actions.ts +11 -2
  52. package/corpus/core/src/triggers/dispatcher.ts +20 -1
  53. package/corpus/core/src/triggers/types.ts +5 -0
  54. package/corpus/core/src/vite/action-types-plugin.ts +9 -1
  55. package/corpus/templates/analytics/.agents/skills/agent-native-docs/SKILL.md +115 -0
  56. package/corpus/templates/analytics/AGENTS.md +11 -11
  57. package/corpus/templates/analytics/_gitignore +39 -0
  58. package/corpus/templates/analytics/actions/query-dashboard-panel.ts +30 -0
  59. package/corpus/templates/analytics/actions/update-dashboard.ts +2 -1
  60. package/corpus/templates/analytics/app/lib/sql-query.ts +11 -25
  61. package/corpus/templates/analytics/changelog/2026-07-21-fixed-extension-updates-failing-before-changes-could-be-appl.md +6 -0
  62. package/corpus/templates/analytics/server/lib/dashboard-panel-query.ts +1 -0
  63. package/corpus/templates/analytics/server/lib/dashboard-panel-source-resolver.ts +51 -0
  64. package/corpus/templates/analytics/server/lib/prometheus.ts +1 -1
  65. package/corpus/templates/analytics/server/plugins/agent-chat.ts +1 -1
  66. package/corpus/templates/assets/.agents/skills/agent-native-docs/SKILL.md +115 -0
  67. package/corpus/templates/brain/.agents/skills/agent-native-docs/SKILL.md +115 -0
  68. package/corpus/templates/calendar/.agents/skills/agent-native-docs/SKILL.md +115 -0
  69. package/corpus/templates/calendar/_gitignore +39 -0
  70. package/corpus/templates/chat/.agents/skills/agent-native-docs/SKILL.md +27 -0
  71. package/corpus/templates/chat/AGENTS.md +1 -1
  72. package/corpus/templates/clips/.agents/skills/agent-native-docs/SKILL.md +115 -0
  73. package/corpus/templates/clips/AGENTS.md +7 -0
  74. package/corpus/templates/clips/actions/prepare-crm-call-evidence.ts +58 -0
  75. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +88 -11
  76. package/corpus/templates/clips/changelog/2026-07-21-crm-call-evidence-handoff.md +6 -0
  77. package/corpus/templates/clips/changelog/2026-07-21-recording-retries-and-restarts-keep-their-upload-session-so-.md +6 -0
  78. package/corpus/templates/clips/chrome-extension/src/background.ts +20 -5
  79. package/corpus/templates/clips/chrome-extension/src/native-recording-state.ts +19 -0
  80. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +8 -0
  81. package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +9 -0
  82. package/corpus/templates/clips/desktop/src-tauri/src/recording_indicator.rs +54 -28
  83. package/corpus/templates/clips/server/plugins/agent-chat.ts +1 -0
  84. package/corpus/templates/content/.agents/skills/agent-native-docs/SKILL.md +115 -0
  85. package/corpus/templates/content/_gitignore +39 -0
  86. package/corpus/templates/content/learnings.defaults.md +5 -0
  87. package/corpus/templates/crm/.agents/skills/agent-native-docs/SKILL.md +115 -0
  88. package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +133 -0
  89. package/corpus/templates/crm/.agents/skills/crm/SKILL.md +128 -0
  90. package/corpus/templates/crm/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  91. package/corpus/templates/crm/.agents/skills/feature-flags/SKILL.md +169 -0
  92. package/corpus/templates/crm/.agents/skills/upgrade-agent-native/SKILL.md +100 -0
  93. package/corpus/templates/crm/.env.example +5 -0
  94. package/corpus/templates/crm/AGENTS.md +120 -0
  95. package/corpus/templates/crm/CHANGELOG.md +1 -0
  96. package/corpus/templates/crm/DEVELOPING.md +66 -0
  97. package/corpus/templates/crm/README.md +106 -0
  98. package/corpus/templates/crm/_gitignore +12 -0
  99. package/corpus/templates/crm/actions/_crm-action-utils.ts +87 -0
  100. package/corpus/templates/crm/actions/_crm-dashboard.ts +69 -0
  101. package/corpus/templates/crm/actions/_crm-signal-utils.ts +79 -0
  102. package/corpus/templates/crm/actions/apply-crm-proposals.ts +203 -0
  103. package/corpus/templates/crm/actions/attach-call-evidence.ts +170 -0
  104. package/corpus/templates/crm/actions/configure-crm-connection.ts +126 -0
  105. package/corpus/templates/crm/actions/configure-native-crm.ts +44 -0
  106. package/corpus/templates/crm/actions/create-crm-record.ts +148 -0
  107. package/corpus/templates/crm/actions/create-crm-signal-tracker.ts +58 -0
  108. package/corpus/templates/crm/actions/delete-staged-dataset.ts +14 -0
  109. package/corpus/templates/crm/actions/get-crm-automation-recipe.ts +36 -0
  110. package/corpus/templates/crm/actions/get-crm-dashboard-panel.ts +33 -0
  111. package/corpus/templates/crm/actions/get-crm-dashboard.ts +14 -0
  112. package/corpus/templates/crm/actions/get-crm-overview.ts +13 -0
  113. package/corpus/templates/crm/actions/get-crm-pipeline-data.ts +61 -0
  114. package/corpus/templates/crm/actions/get-crm-record.ts +75 -0
  115. package/corpus/templates/crm/actions/install-crm-pipeline-dashboard.ts +81 -0
  116. package/corpus/templates/crm/actions/list-crm-dashboard-revisions.ts +15 -0
  117. package/corpus/templates/crm/actions/list-crm-dashboards.ts +15 -0
  118. package/corpus/templates/crm/actions/list-crm-proposals.ts +31 -0
  119. package/corpus/templates/crm/actions/list-crm-records.ts +79 -0
  120. package/corpus/templates/crm/actions/list-crm-saved-views.ts +15 -0
  121. package/corpus/templates/crm/actions/list-crm-signal-hits.ts +43 -0
  122. package/corpus/templates/crm/actions/list-crm-signal-trackers.ts +32 -0
  123. package/corpus/templates/crm/actions/list-crm-tasks.ts +22 -0
  124. package/corpus/templates/crm/actions/list-staged-datasets.ts +14 -0
  125. package/corpus/templates/crm/actions/list-workspace-connections.ts +47 -0
  126. package/corpus/templates/crm/actions/manage-crm-signal-tracker.ts +87 -0
  127. package/corpus/templates/crm/actions/manage-crm-task.ts +132 -0
  128. package/corpus/templates/crm/actions/navigate.ts +63 -0
  129. package/corpus/templates/crm/actions/provider-api-catalog.ts +22 -0
  130. package/corpus/templates/crm/actions/provider-api-docs.ts +54 -0
  131. package/corpus/templates/crm/actions/provider-api-request.ts +92 -0
  132. package/corpus/templates/crm/actions/query-staged-dataset.ts +44 -0
  133. package/corpus/templates/crm/actions/record-crm-call-insight.ts +160 -0
  134. package/corpus/templates/crm/actions/record-crm-smart-signal.ts +150 -0
  135. package/corpus/templates/crm/actions/restore-crm-dashboard-revision.ts +23 -0
  136. package/corpus/templates/crm/actions/review-crm-signal.ts +31 -0
  137. package/corpus/templates/crm/actions/run-crm-saved-view-program.ts +103 -0
  138. package/corpus/templates/crm/actions/run-crm-signal-trackers.ts +275 -0
  139. package/corpus/templates/crm/actions/run.ts +11 -0
  140. package/corpus/templates/crm/actions/save-crm-dashboard.ts +51 -0
  141. package/corpus/templates/crm/actions/save-crm-saved-view.ts +119 -0
  142. package/corpus/templates/crm/actions/sync-crm.ts +146 -0
  143. package/corpus/templates/crm/actions/update-crm-record.ts +508 -0
  144. package/corpus/templates/crm/actions/view-screen.ts +218 -0
  145. package/corpus/templates/crm/agent-native.app-skill.json +58 -0
  146. package/corpus/templates/crm/app/components/crm/CreateCrmRecordDialog.tsx +158 -0
  147. package/corpus/templates/crm/app/components/crm/CrmDashboardPanel.tsx +83 -0
  148. package/corpus/templates/crm/app/components/crm/CrmSignalsPanel.tsx +225 -0
  149. package/corpus/templates/crm/app/components/crm/IntelligenceSettings.tsx +413 -0
  150. package/corpus/templates/crm/app/components/crm/RecordActions.tsx +510 -0
  151. package/corpus/templates/crm/app/components/crm/RecordGrid.tsx +134 -0
  152. package/corpus/templates/crm/app/components/crm/RecordWorkspace.tsx +367 -0
  153. package/corpus/templates/crm/app/components/crm/SavedViewDataProgram.tsx +92 -0
  154. package/corpus/templates/crm/app/components/crm/Surface.tsx +96 -0
  155. package/corpus/templates/crm/app/components/crm/WorkOverview.tsx +180 -0
  156. package/corpus/templates/crm/app/components/layout/CrmLayout.tsx +106 -0
  157. package/corpus/templates/crm/app/components/layout/CrmSidebar.tsx +84 -0
  158. package/corpus/templates/crm/app/entry.client.tsx +16 -0
  159. package/corpus/templates/crm/app/entry.server.tsx +10 -0
  160. package/corpus/templates/crm/app/global.css +167 -0
  161. package/corpus/templates/crm/app/hooks/use-navigation-state.ts +60 -0
  162. package/corpus/templates/crm/app/i18n/en-US.ts +89 -0
  163. package/corpus/templates/crm/app/i18n/index.ts +34 -0
  164. package/corpus/templates/crm/app/lib/dashboard.ts +13 -0
  165. package/corpus/templates/crm/app/lib/navigation.ts +54 -0
  166. package/corpus/templates/crm/app/lib/tab-id.ts +1 -0
  167. package/corpus/templates/crm/app/lib/types.ts +172 -0
  168. package/corpus/templates/crm/app/lib/utils.ts +1 -0
  169. package/corpus/templates/crm/app/root.tsx +88 -0
  170. package/corpus/templates/crm/app/routes/_index.tsx +26 -0
  171. package/corpus/templates/crm/app/routes/accounts.tsx +41 -0
  172. package/corpus/templates/crm/app/routes/agent.tsx +5 -0
  173. package/corpus/templates/crm/app/routes/ask.tsx +53 -0
  174. package/corpus/templates/crm/app/routes/dashboard.tsx +118 -0
  175. package/corpus/templates/crm/app/routes/opportunities.tsx +41 -0
  176. package/corpus/templates/crm/app/routes/people.tsx +41 -0
  177. package/corpus/templates/crm/app/routes/proposals.tsx +266 -0
  178. package/corpus/templates/crm/app/routes/records.$recordId.tsx +35 -0
  179. package/corpus/templates/crm/app/routes/settings.tsx +63 -0
  180. package/corpus/templates/crm/app/routes/setup.tsx +308 -0
  181. package/corpus/templates/crm/app/routes/tasks.tsx +252 -0
  182. package/corpus/templates/crm/app/routes/views.tsx +333 -0
  183. package/corpus/templates/crm/app/routes.ts +17 -0
  184. package/corpus/templates/crm/app/vite-env.d.ts +6 -0
  185. package/corpus/templates/crm/changelog/2026-07-21-agent-native-crm.md +6 -0
  186. package/corpus/templates/crm/changelog/2026-07-21-clips-call-evidence-review-recipe.md +6 -0
  187. package/corpus/templates/crm/changelog/2026-07-21-crm-can-now-find-and-review-evidence-grounded-call-signals-w.md +6 -0
  188. package/corpus/templates/crm/changelog/2026-07-21-crm-can-now-manage-keyword-and-smart-call-signal-trackers-fr.md +6 -0
  189. package/corpus/templates/crm/changelog/2026-07-21-delegated-local-crm-automation.md +6 -0
  190. package/corpus/templates/crm/changelog/2026-07-21-native-sql.md +6 -0
  191. package/corpus/templates/crm/changelog/2026-07-21-pipeline-dashboard.md +6 -0
  192. package/corpus/templates/crm/changelog/2026-07-21-pipeline-dashboards-now-install-correctly-from-the-crm-actio.md +6 -0
  193. package/corpus/templates/crm/changelog/2026-07-21-salesforce-connection.md +6 -0
  194. package/corpus/templates/crm/components.json +20 -0
  195. package/corpus/templates/crm/docs/architecture/crm-contract.md +180 -0
  196. package/corpus/templates/crm/learnings.defaults.md +5 -0
  197. package/corpus/templates/crm/package.json +59 -0
  198. package/corpus/templates/crm/public/favicon.svg +1 -0
  199. package/corpus/templates/crm/public/icon-180.svg +1 -0
  200. package/corpus/templates/crm/public/manifest.json +11 -0
  201. package/corpus/templates/crm/react-router.config.ts +7 -0
  202. package/corpus/templates/crm/server/crm/adapter.ts +32 -0
  203. package/corpus/templates/crm/server/crm/crm-field-firewall.ts +64 -0
  204. package/corpus/templates/crm/server/crm/crm-mirror.ts +711 -0
  205. package/corpus/templates/crm/server/crm/hubspot-adapter.ts +1143 -0
  206. package/corpus/templates/crm/server/crm/native-adapter.ts +1715 -0
  207. package/corpus/templates/crm/server/crm/read-through.ts +207 -0
  208. package/corpus/templates/crm/server/crm/salesforce-adapter.ts +1255 -0
  209. package/corpus/templates/crm/server/db/crm-store.ts +1170 -0
  210. package/corpus/templates/crm/server/db/index.ts +169 -0
  211. package/corpus/templates/crm/server/db/schema.ts +441 -0
  212. package/corpus/templates/crm/server/lib/intelligence/default-detectors.ts +65 -0
  213. package/corpus/templates/crm/server/lib/intelligence/evidence.ts +105 -0
  214. package/corpus/templates/crm/server/lib/intelligence/keyword-detector.ts +100 -0
  215. package/corpus/templates/crm/server/lib/intelligence/smart-detector.ts +144 -0
  216. package/corpus/templates/crm/server/lib/intelligence/summary.ts +141 -0
  217. package/corpus/templates/crm/server/lib/provider-api.ts +64 -0
  218. package/corpus/templates/crm/server/middleware/auth.ts +4 -0
  219. package/corpus/templates/crm/server/plugins/agent-chat.ts +68 -0
  220. package/corpus/templates/crm/server/plugins/auth.ts +14 -0
  221. package/corpus/templates/crm/server/plugins/core-routes.ts +17 -0
  222. package/corpus/templates/crm/server/plugins/db.ts +454 -0
  223. package/corpus/templates/crm/server/routes/[...page].get.ts +5 -0
  224. package/corpus/templates/crm/shared/crm-automation-recipes.ts +132 -0
  225. package/corpus/templates/crm/shared/crm-contract.ts +254 -0
  226. package/corpus/templates/crm/shared/crm-sales-config.ts +63 -0
  227. package/corpus/templates/crm/ssr-entry.ts +11 -0
  228. package/corpus/templates/crm/tsconfig.json +24 -0
  229. package/corpus/templates/crm/vite.config.ts +15 -0
  230. package/corpus/templates/crm/vitest.config.ts +5 -0
  231. package/corpus/templates/design/.agents/skills/agent-native-docs/SKILL.md +115 -0
  232. package/corpus/templates/dispatch/.agents/skills/agent-native-docs/SKILL.md +115 -0
  233. package/corpus/templates/forms/.agents/skills/agent-native-docs/SKILL.md +115 -0
  234. package/corpus/templates/forms/_gitignore +39 -0
  235. package/corpus/templates/forms/learnings.defaults.md +5 -0
  236. package/corpus/templates/macros/.agents/skills/agent-native-docs/SKILL.md +115 -0
  237. package/corpus/templates/macros/_gitignore +39 -0
  238. package/corpus/templates/macros/learnings.defaults.md +5 -0
  239. package/corpus/templates/mail/.agents/skills/agent-native-docs/SKILL.md +115 -0
  240. package/corpus/templates/mail/_gitignore +39 -0
  241. package/corpus/templates/plan/.agents/skills/agent-native-docs/SKILL.md +115 -0
  242. package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +19 -2
  243. package/corpus/templates/plan/AGENTS.md +10 -0
  244. package/corpus/templates/plan/actions/create-prototype-plan.ts +27 -3
  245. package/corpus/templates/plan/actions/get-plan-blocks.ts +1 -1
  246. package/corpus/templates/plan/actions/update-visual-plan.ts +3 -2
  247. package/corpus/templates/plan/app/components/plan/PlanContentRenderer.tsx +18 -4
  248. package/corpus/templates/plan/app/components/plan/PlanVisualSurface.tsx +10 -3
  249. package/corpus/templates/plan/app/components/plan/wireframe/Wireframe.tsx +3 -1
  250. package/corpus/templates/plan/app/i18n/en-US.ts +6 -0
  251. package/corpus/templates/plan/app/lib/create-plan-routing.ts +39 -0
  252. package/corpus/templates/plan/app/pages/PlansPage.tsx +31 -107
  253. package/corpus/templates/plan/changelog/2026-07-22-high-fidelity-mockup-requests-now-preserve-branded-css-use-d.md +6 -0
  254. package/corpus/templates/plan/shared/plan-content.ts +110 -2
  255. package/corpus/templates/slides/.agents/skills/agent-native-docs/SKILL.md +115 -0
  256. package/corpus/templates/slides/_gitignore +39 -0
  257. package/corpus/templates/tasks/.agents/skills/agent-native-docs/SKILL.md +27 -0
  258. package/corpus/templates/tasks/_gitignore +39 -0
  259. package/corpus/toolkit/CHANGELOG.md +12 -0
  260. package/corpus/toolkit/README.md +30 -0
  261. package/corpus/toolkit/agent-native.eject.json +33 -0
  262. package/corpus/toolkit/package.json +15 -1
  263. package/corpus/toolkit/src/dashboard/DataTable.tsx +273 -0
  264. package/corpus/toolkit/src/dashboard/DateRangePicker.tsx +57 -0
  265. package/corpus/toolkit/src/dashboard/GenericChartPanel.tsx +461 -0
  266. package/corpus/toolkit/src/dashboard/MetricCard.tsx +54 -0
  267. package/corpus/toolkit/src/dashboard/StatsCard.tsx +49 -0
  268. package/corpus/toolkit/src/dashboard/dashboard-layout.ts +329 -0
  269. package/corpus/toolkit/src/dashboard/index.ts +6 -0
  270. package/corpus/toolkit/src/index.ts +1 -0
  271. package/corpus/toolkit/src/ui/calendar.tsx +8 -8
  272. package/corpus/toolkit/src/ui/date-picker.tsx +4 -1
  273. package/dist/action.d.ts +14 -1
  274. package/dist/action.d.ts.map +1 -1
  275. package/dist/action.js.map +1 -1
  276. package/dist/agent/production-agent.d.ts +3 -1
  277. package/dist/agent/production-agent.d.ts.map +1 -1
  278. package/dist/agent/production-agent.js +97 -3
  279. package/dist/agent/production-agent.js.map +1 -1
  280. package/dist/cli/skills-content/visual-plan-skill.d.ts +1 -1
  281. package/dist/cli/skills-content/visual-plan-skill.d.ts.map +1 -1
  282. package/dist/cli/skills-content/visual-plan-skill.js +19 -2
  283. package/dist/cli/skills-content/visual-plan-skill.js.map +1 -1
  284. package/dist/cli/templates-meta.d.ts.map +1 -1
  285. package/dist/cli/templates-meta.js +12 -0
  286. package/dist/cli/templates-meta.js.map +1 -1
  287. package/dist/client/AssistantChat.d.ts +4 -0
  288. package/dist/client/AssistantChat.d.ts.map +1 -1
  289. package/dist/client/AssistantChat.js +30 -17
  290. package/dist/client/AssistantChat.js.map +1 -1
  291. package/dist/client/agent-page/AgentJobsTab.d.ts.map +1 -1
  292. package/dist/client/agent-page/AgentJobsTab.js +3 -1
  293. package/dist/client/agent-page/AgentJobsTab.js.map +1 -1
  294. package/dist/client/agent-page/use-jobs.d.ts +1 -0
  295. package/dist/client/agent-page/use-jobs.d.ts.map +1 -1
  296. package/dist/client/agent-page/use-jobs.js.map +1 -1
  297. package/dist/client/blocks/library/wireframe.d.ts.map +1 -1
  298. package/dist/client/blocks/library/wireframe.js +3 -2
  299. package/dist/client/blocks/library/wireframe.js.map +1 -1
  300. package/dist/client/chat/message-components.d.ts +5 -0
  301. package/dist/client/chat/message-components.d.ts.map +1 -1
  302. package/dist/client/chat/message-components.js +17 -1
  303. package/dist/client/chat/message-components.js.map +1 -1
  304. package/dist/client/chat/tool-call-display.d.ts +3 -1
  305. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  306. package/dist/client/chat/tool-call-display.js +17 -7
  307. package/dist/client/chat/tool-call-display.js.map +1 -1
  308. package/dist/collab/routes.d.ts +1 -1
  309. package/dist/collab/struct-routes.d.ts +1 -1
  310. package/dist/connections/catalog.d.ts +17 -3
  311. package/dist/connections/catalog.d.ts.map +1 -1
  312. package/dist/connections/catalog.js +16 -1
  313. package/dist/connections/catalog.js.map +1 -1
  314. package/dist/connections/reader.d.ts +18 -0
  315. package/dist/connections/reader.d.ts.map +1 -1
  316. package/dist/connections/reader.js +41 -0
  317. package/dist/connections/reader.js.map +1 -1
  318. package/dist/dashboard-storage/index.d.ts +4 -0
  319. package/dist/dashboard-storage/index.d.ts.map +1 -0
  320. package/dist/dashboard-storage/index.js +4 -0
  321. package/dist/dashboard-storage/index.js.map +1 -0
  322. package/dist/dashboard-storage/panel-source.d.ts +68 -0
  323. package/dist/dashboard-storage/panel-source.d.ts.map +1 -0
  324. package/dist/dashboard-storage/panel-source.js +76 -0
  325. package/dist/dashboard-storage/panel-source.js.map +1 -0
  326. package/dist/dashboard-storage/schema.d.ts +562 -0
  327. package/dist/dashboard-storage/schema.d.ts.map +1 -0
  328. package/dist/dashboard-storage/schema.js +32 -0
  329. package/dist/dashboard-storage/schema.js.map +1 -0
  330. package/dist/dashboard-storage/store.d.ts +62 -0
  331. package/dist/dashboard-storage/store.d.ts.map +1 -0
  332. package/dist/dashboard-storage/store.js +227 -0
  333. package/dist/dashboard-storage/store.js.map +1 -0
  334. package/dist/deploy/build.d.ts +7 -0
  335. package/dist/deploy/build.d.ts.map +1 -1
  336. package/dist/deploy/build.js +78 -14
  337. package/dist/deploy/build.js.map +1 -1
  338. package/dist/eject/provider-api-definitions.d.ts +2 -1
  339. package/dist/eject/provider-api-definitions.d.ts.map +1 -1
  340. package/dist/eject/provider-api-definitions.js +1 -0
  341. package/dist/eject/provider-api-definitions.js.map +1 -1
  342. package/dist/eject/workspace-connections.d.ts.map +1 -1
  343. package/dist/eject/workspace-connections.js +1 -0
  344. package/dist/eject/workspace-connections.js.map +1 -1
  345. package/dist/extensions/actions.d.ts.map +1 -1
  346. package/dist/extensions/actions.js +165 -67
  347. package/dist/extensions/actions.js.map +1 -1
  348. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  349. package/dist/jobs/actions/list-recurring-jobs.d.ts +1 -0
  350. package/dist/jobs/actions/list-recurring-jobs.d.ts.map +1 -1
  351. package/dist/jobs/actions/list-recurring-jobs.js +1 -0
  352. package/dist/jobs/actions/list-recurring-jobs.js.map +1 -1
  353. package/dist/jobs/scheduler.d.ts +17 -2
  354. package/dist/jobs/scheduler.d.ts.map +1 -1
  355. package/dist/jobs/scheduler.js +51 -2
  356. package/dist/jobs/scheduler.js.map +1 -1
  357. package/dist/jobs/tools.d.ts.map +1 -1
  358. package/dist/jobs/tools.js +32 -2
  359. package/dist/jobs/tools.js.map +1 -1
  360. package/dist/localization/default-messages.d.ts +1 -0
  361. package/dist/localization/default-messages.d.ts.map +1 -1
  362. package/dist/localization/default-messages.js +1 -0
  363. package/dist/localization/default-messages.js.map +1 -1
  364. package/dist/mcp-client/index.d.ts +2 -0
  365. package/dist/mcp-client/index.d.ts.map +1 -1
  366. package/dist/mcp-client/index.js +5 -0
  367. package/dist/mcp-client/index.js.map +1 -1
  368. package/dist/notifications/routes.d.ts +3 -3
  369. package/dist/progress/routes.d.ts +1 -1
  370. package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
  371. package/dist/provider-api/actions/provider-api.d.ts +8 -6
  372. package/dist/provider-api/actions/provider-api.d.ts.map +1 -1
  373. package/dist/provider-api/actions/provider-api.js +1 -1
  374. package/dist/provider-api/actions/provider-api.js.map +1 -1
  375. package/dist/provider-api/index.d.ts +11 -7
  376. package/dist/provider-api/index.d.ts.map +1 -1
  377. package/dist/provider-api/index.js +143 -5
  378. package/dist/provider-api/index.js.map +1 -1
  379. package/dist/resources/handlers.d.ts +1 -1
  380. package/dist/secrets/register-framework-secrets.d.ts.map +1 -1
  381. package/dist/secrets/register-framework-secrets.js +7 -0
  382. package/dist/secrets/register-framework-secrets.js.map +1 -1
  383. package/dist/server/agent-chat/context-tools.d.ts.map +1 -1
  384. package/dist/server/agent-chat/context-tools.js +9 -0
  385. package/dist/server/agent-chat/context-tools.js.map +1 -1
  386. package/dist/server/agent-chat/framework-prompts.js +2 -2
  387. package/dist/server/agent-chat/framework-prompts.js.map +1 -1
  388. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  389. package/dist/server/agent-chat-plugin.js +18 -2
  390. package/dist/server/agent-chat-plugin.js.map +1 -1
  391. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  392. package/dist/server/core-routes-plugin.js +1 -0
  393. package/dist/server/core-routes-plugin.js.map +1 -1
  394. package/dist/server/credential-provider.d.ts +4 -3
  395. package/dist/server/credential-provider.d.ts.map +1 -1
  396. package/dist/server/credential-provider.js +9 -3
  397. package/dist/server/credential-provider.js.map +1 -1
  398. package/dist/server/workspace-provider-oauth.d.ts +6 -1
  399. package/dist/server/workspace-provider-oauth.d.ts.map +1 -1
  400. package/dist/server/workspace-provider-oauth.js +141 -4
  401. package/dist/server/workspace-provider-oauth.js.map +1 -1
  402. package/dist/styles/agent-native.css +45 -2
  403. package/dist/templates/chat/.agents/skills/agent-native-docs/SKILL.md +27 -0
  404. package/dist/templates/chat/AGENTS.md +1 -1
  405. package/dist/templates/default/.agents/skills/agent-native-docs/SKILL.md +27 -0
  406. package/dist/templates/default/.agents/skills/app-branding/SKILL.md +159 -0
  407. package/dist/templates/default/.agents/skills/app-permissions/SKILL.md +155 -0
  408. package/dist/templates/headless/.agents/skills/agent-native-docs/SKILL.md +27 -0
  409. package/dist/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +27 -0
  410. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +31 -18
  411. package/dist/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +15 -0
  412. package/dist/triggers/actions.d.ts.map +1 -1
  413. package/dist/triggers/actions.js +10 -2
  414. package/dist/triggers/actions.js.map +1 -1
  415. package/dist/triggers/dispatcher.d.ts.map +1 -1
  416. package/dist/triggers/dispatcher.js +15 -0
  417. package/dist/triggers/dispatcher.js.map +1 -1
  418. package/dist/triggers/types.d.ts +5 -0
  419. package/dist/triggers/types.d.ts.map +1 -1
  420. package/dist/triggers/types.js.map +1 -1
  421. package/dist/vite/action-types-plugin.d.ts.map +1 -1
  422. package/dist/vite/action-types-plugin.js +4 -1
  423. package/dist/vite/action-types-plugin.js.map +1 -1
  424. package/docs/content/agent-native-toolkit.mdx +16 -0
  425. package/docs/content/recurring-jobs.mdx +35 -6
  426. package/package.json +7 -3
  427. package/src/action.ts +22 -1
  428. package/src/agent/production-agent.ts +122 -3
  429. package/src/cli/skills-content/visual-plan-skill.ts +19 -2
  430. package/src/cli/templates-meta.ts +12 -0
  431. package/src/client/AssistantChat.tsx +53 -26
  432. package/src/client/agent-page/AgentJobsTab.tsx +19 -0
  433. package/src/client/agent-page/use-jobs.ts +1 -0
  434. package/src/client/blocks/library/wireframe.tsx +3 -1
  435. package/src/client/chat/message-components.tsx +35 -1
  436. package/src/client/chat/tool-call-display.tsx +38 -3
  437. package/src/connections/catalog.ts +20 -1
  438. package/src/connections/reader.ts +65 -0
  439. package/src/dashboard-storage/index.ts +27 -0
  440. package/src/dashboard-storage/panel-source.ts +168 -0
  441. package/src/dashboard-storage/schema.ts +62 -0
  442. package/src/dashboard-storage/store.ts +333 -0
  443. package/src/deploy/build.ts +95 -16
  444. package/src/eject/provider-api-definitions.ts +1 -0
  445. package/src/eject/workspace-connections.ts +1 -0
  446. package/src/extensions/actions.ts +199 -73
  447. package/src/jobs/actions/list-recurring-jobs.ts +2 -0
  448. package/src/jobs/scheduler.ts +71 -4
  449. package/src/jobs/tools.ts +31 -1
  450. package/src/localization/default-messages.ts +1 -0
  451. package/src/mcp-client/index.ts +6 -0
  452. package/src/provider-api/actions/provider-api.ts +1 -1
  453. package/src/provider-api/index.ts +190 -5
  454. package/src/secrets/register-framework-secrets.ts +8 -0
  455. package/src/server/agent-chat/context-tools.ts +9 -0
  456. package/src/server/agent-chat/framework-prompts.ts +2 -2
  457. package/src/server/agent-chat-plugin.ts +22 -2
  458. package/src/server/core-routes-plugin.ts +1 -0
  459. package/src/server/credential-provider.ts +9 -3
  460. package/src/server/workspace-provider-oauth.ts +181 -4
  461. package/src/styles/agent-native.css +45 -2
  462. package/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +27 -0
  463. package/src/templates/chat/AGENTS.md +1 -1
  464. package/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +27 -0
  465. package/src/templates/default/.agents/skills/app-branding/SKILL.md +159 -0
  466. package/src/templates/default/.agents/skills/app-permissions/SKILL.md +155 -0
  467. package/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +27 -0
  468. package/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +27 -0
  469. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +31 -18
  470. package/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +15 -0
  471. package/src/triggers/actions.ts +11 -2
  472. package/src/triggers/dispatcher.ts +20 -1
  473. package/src/triggers/types.ts +5 -0
  474. package/src/vite/action-types-plugin.ts +9 -1
  475. package/corpus/templates/analytics/server/handlers/sql-query.ts +0 -36
  476. package/corpus/templates/analytics/server/routes/api/sql-query.post.ts +0 -1
@@ -17,12 +17,12 @@ declare const _default: import("../../action.js").ActionDefinition<{
17
17
  id?: undefined;
18
18
  provider?: undefined;
19
19
  } | {
20
+ error?: undefined;
20
21
  configured?: undefined;
21
22
  connectPath?: undefined;
22
23
  url: string;
23
24
  id: string;
24
25
  provider: string;
25
- error?: undefined;
26
26
  }>;
27
27
  export default _default;
28
28
  //# sourceMappingURL=upload-image.d.ts.map
@@ -12,6 +12,7 @@ export interface RecurringJobActionItem {
12
12
  lastError: string | null;
13
13
  nextRun: string | null;
14
14
  createdBy: string | null;
15
+ mcpTools: string[];
15
16
  canUpdate: boolean;
16
17
  }
17
18
  declare const _default: import("../../action.js").ActionDefinition<{
@@ -1 +1 @@
1
- {"version":3,"file":"list-recurring-jobs.d.ts","sourceRoot":"","sources":["../../../src/jobs/actions/list-recurring-jobs.ts"],"names":[],"mappings":"AAkCA,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,UAAU,GAAG,cAAc,CAAC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;CACpB"}
1
+ {"version":3,"file":"list-recurring-jobs.d.ts","sourceRoot":"","sources":["../../../src/jobs/actions/list-recurring-jobs.ts"],"names":[],"mappings":"AAkCA,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,UAAU,GAAG,cAAc,CAAC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;CACpB"}
@@ -65,6 +65,7 @@ export default defineAction({
65
65
  lastError: meta.lastError ?? null,
66
66
  nextRun: nextRun(meta),
67
67
  createdBy: meta.createdBy ?? null,
68
+ mcpTools: meta.mcpTools ?? [],
68
69
  canUpdate,
69
70
  });
70
71
  }
@@ -1 +1 @@
1
- {"version":3,"file":"list-recurring-jobs.js","sourceRoot":"","sources":["../../../src/jobs/actions/list-recurring-jobs.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\n\nimport { defineAction } from \"../../action.js\";\nimport {\n organizationResourceOwner,\n resourceGetByPath,\n resourceList,\n} from \"../../resources/store.js\";\nimport { describeCron, isValidCron, nextOccurrence } from \"../cron.js\";\nimport { parseJobFrontmatter } from \"../scheduler.js\";\nimport { authorizeJobMutation } from \"../tools.js\";\n\nconst scopeSchema = z.enum([\"personal\", \"organization\"]);\n\nfunction hasTriggerFrontmatter(content: string): boolean {\n const header = content.match(/^---\\n([\\s\\S]*?)\\n---/m)?.[1] ?? \"\";\n return /^triggerType\\s*:/m.test(header);\n}\n\nfunction jobName(path: string): string {\n return path.replace(/^jobs\\//, \"\").replace(/\\.md$/, \"\");\n}\n\nfunction nextRun(\n meta: ReturnType<typeof parseJobFrontmatter>[\"meta\"],\n): string | null {\n if (!meta.enabled) return null;\n if (meta.nextRun) return meta.nextRun;\n if (meta.schedule && isValidCron(meta.schedule)) {\n return nextOccurrence(meta.schedule).toISOString();\n }\n return null;\n}\n\nexport interface RecurringJobActionItem {\n id: string;\n name: string;\n path: string;\n scope: \"personal\" | \"organization\";\n schedule: string;\n scheduleDescription: string;\n instructions: string;\n enabled: boolean;\n lastRun: string | null;\n lastStatus: string | null;\n lastError: string | null;\n nextRun: string | null;\n createdBy: string | null;\n canUpdate: boolean;\n}\n\nexport default defineAction({\n description:\n \"List recurring cron jobs visible in the selected personal or organization scope. This read surface is used by the Agent Jobs page.\",\n agentTool: false,\n schema: z.object({\n scope: scopeSchema.default(\"personal\"),\n }),\n http: { method: \"GET\" },\n readOnly: true,\n parallelSafe: true,\n run: async ({ scope }, ctx): Promise<RecurringJobActionItem[]> => {\n const userEmail = ctx?.userEmail;\n if (!userEmail) throw new Error(\"Not authenticated.\");\n\n if (scope === \"organization\" && !ctx?.orgId) return [];\n\n const owner =\n scope === \"organization\"\n ? organizationResourceOwner(ctx.orgId as string)\n : userEmail;\n const resources = await resourceList(owner, \"jobs/\");\n const jobs: RecurringJobActionItem[] = [];\n\n for (const resource of resources) {\n if (!resource.path.endsWith(\".md\") || resource.path.endsWith(\".keep\")) {\n continue;\n }\n const full = await resourceGetByPath(owner, resource.path);\n if (!full || hasTriggerFrontmatter(full.content)) continue;\n\n const { meta, body } = parseJobFrontmatter(full.content);\n const canUpdate =\n scope === \"personal\" || !(await authorizeJobMutation(owner, meta));\n jobs.push({\n id: full.id,\n name: jobName(full.path),\n path: full.path,\n scope,\n schedule: meta.schedule,\n scheduleDescription: meta.schedule ? describeCron(meta.schedule) : \"\",\n instructions: body,\n enabled: meta.enabled,\n lastRun: meta.lastRun ?? null,\n lastStatus: meta.lastStatus ?? null,\n lastError: meta.lastError ?? null,\n nextRun: nextRun(meta),\n createdBy: meta.createdBy ?? null,\n canUpdate,\n });\n }\n\n return jobs;\n },\n});\n"]}
1
+ {"version":3,"file":"list-recurring-jobs.js","sourceRoot":"","sources":["../../../src/jobs/actions/list-recurring-jobs.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\n\nimport { defineAction } from \"../../action.js\";\nimport {\n organizationResourceOwner,\n resourceGetByPath,\n resourceList,\n} from \"../../resources/store.js\";\nimport { describeCron, isValidCron, nextOccurrence } from \"../cron.js\";\nimport { parseJobFrontmatter } from \"../scheduler.js\";\nimport { authorizeJobMutation } from \"../tools.js\";\n\nconst scopeSchema = z.enum([\"personal\", \"organization\"]);\n\nfunction hasTriggerFrontmatter(content: string): boolean {\n const header = content.match(/^---\\n([\\s\\S]*?)\\n---/m)?.[1] ?? \"\";\n return /^triggerType\\s*:/m.test(header);\n}\n\nfunction jobName(path: string): string {\n return path.replace(/^jobs\\//, \"\").replace(/\\.md$/, \"\");\n}\n\nfunction nextRun(\n meta: ReturnType<typeof parseJobFrontmatter>[\"meta\"],\n): string | null {\n if (!meta.enabled) return null;\n if (meta.nextRun) return meta.nextRun;\n if (meta.schedule && isValidCron(meta.schedule)) {\n return nextOccurrence(meta.schedule).toISOString();\n }\n return null;\n}\n\nexport interface RecurringJobActionItem {\n id: string;\n name: string;\n path: string;\n scope: \"personal\" | \"organization\";\n schedule: string;\n scheduleDescription: string;\n instructions: string;\n enabled: boolean;\n lastRun: string | null;\n lastStatus: string | null;\n lastError: string | null;\n nextRun: string | null;\n createdBy: string | null;\n mcpTools: string[];\n canUpdate: boolean;\n}\n\nexport default defineAction({\n description:\n \"List recurring cron jobs visible in the selected personal or organization scope. This read surface is used by the Agent Jobs page.\",\n agentTool: false,\n schema: z.object({\n scope: scopeSchema.default(\"personal\"),\n }),\n http: { method: \"GET\" },\n readOnly: true,\n parallelSafe: true,\n run: async ({ scope }, ctx): Promise<RecurringJobActionItem[]> => {\n const userEmail = ctx?.userEmail;\n if (!userEmail) throw new Error(\"Not authenticated.\");\n\n if (scope === \"organization\" && !ctx?.orgId) return [];\n\n const owner =\n scope === \"organization\"\n ? organizationResourceOwner(ctx.orgId as string)\n : userEmail;\n const resources = await resourceList(owner, \"jobs/\");\n const jobs: RecurringJobActionItem[] = [];\n\n for (const resource of resources) {\n if (!resource.path.endsWith(\".md\") || resource.path.endsWith(\".keep\")) {\n continue;\n }\n const full = await resourceGetByPath(owner, resource.path);\n if (!full || hasTriggerFrontmatter(full.content)) continue;\n\n const { meta, body } = parseJobFrontmatter(full.content);\n const canUpdate =\n scope === \"personal\" || !(await authorizeJobMutation(owner, meta));\n jobs.push({\n id: full.id,\n name: jobName(full.path),\n path: full.path,\n scope,\n schedule: meta.schedule,\n scheduleDescription: meta.schedule ? describeCron(meta.schedule) : \"\",\n instructions: body,\n enabled: meta.enabled,\n lastRun: meta.lastRun ?? null,\n lastStatus: meta.lastStatus ?? null,\n lastError: meta.lastError ?? null,\n nextRun: nextRun(meta),\n createdBy: meta.createdBy ?? null,\n mcpTools: meta.mcpTools ?? [],\n canUpdate,\n });\n }\n\n return jobs;\n },\n});\n"]}
@@ -1,5 +1,6 @@
1
1
  import type { AgentEngine } from "../agent/engine/types.js";
2
2
  import { type ActionEntry } from "../agent/production-agent.js";
3
+ import { type Resource } from "../resources/store.js";
3
4
  export interface JobFrontmatter {
4
5
  schedule: string;
5
6
  enabled: boolean;
@@ -16,14 +17,28 @@ export interface JobFrontmatter {
16
17
  deliveryThreadRef?: string;
17
18
  deliveryTenantId?: string;
18
19
  model?: string;
20
+ /** Explicit MCP tool capabilities available to this background run. */
21
+ mcpTools?: string[];
19
22
  }
23
+ /**
24
+ * Normalize the non-secret MCP capability references persisted with a job.
25
+ * Tool names are opaque framework identifiers; URLs and credentials never
26
+ * belong in job frontmatter.
27
+ */
28
+ export declare function normalizeJobMcpTools(value: unknown): string[] | undefined;
20
29
  export declare function parseJobFrontmatter(content: string): {
21
30
  meta: JobFrontmatter;
22
31
  body: string;
23
32
  };
24
33
  export declare function buildJobContent(meta: JobFrontmatter, body: string): string;
34
+ export interface RecurringJobContext {
35
+ name: string;
36
+ meta: JobFrontmatter;
37
+ body: string;
38
+ resource: Resource;
39
+ }
25
40
  export interface SchedulerDeps {
26
- getActions: () => Record<string, ActionEntry>;
41
+ getActions: (job?: RecurringJobContext) => Record<string, ActionEntry>;
27
42
  getSystemPrompt: (owner: string) => Promise<string>;
28
43
  /**
29
44
  * Tool names to expose on the FIRST engine request for a job run. When
@@ -36,7 +51,7 @@ export interface SchedulerDeps {
36
51
  * merged actions are the app's own vs. framework additions, so this must
37
52
  * be supplied explicitly rather than inferred here.
38
53
  */
39
- getInitialToolNames?: () => string[] | undefined;
54
+ getInitialToolNames?: (job?: RecurringJobContext) => string[] | undefined;
40
55
  /** Optional engine override. Defaults to the resolved request engine. */
41
56
  engine?: AgentEngine;
42
57
  apiKey?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../src/jobs/scheduler.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAKL,KAAK,WAAW,EACjB,MAAM,8BAA8B,CAAC;AAetC,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAID,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG;IACpD,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd,CAoFA;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAmC1E;AAID,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC9C,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD;;;;;;;;;;OAUG;IACH,mBAAmB,CAAC,EAAE,MAAM,MAAM,EAAE,GAAG,SAAS,CAAC;IACjD,yEAAyE;IACzE,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAgCD;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAgG7E"}
1
+ {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../src/jobs/scheduler.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAKL,KAAK,WAAW,EACjB,MAAM,8BAA8B,CAAC;AAItC,OAAO,EAIL,KAAK,QAAQ,EACd,MAAM,uBAAuB,CAAC;AAM/B,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAKD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,GAAG,SAAS,CAgCzE;AAID,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG;IACpD,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd,CA4FA;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAqC1E;AAID,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,CAAC,GAAG,CAAC,EAAE,mBAAmB,KAAK,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACvE,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD;;;;;;;;;;OAUG;IACH,mBAAmB,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,mBAAmB,KAAK,MAAM,EAAE,GAAG,SAAS,CAAC;IAC1E,yEAAyE;IACzE,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAgCD;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAgG7E"}
@@ -7,6 +7,38 @@ import { createThread } from "../chat-threads/store.js";
7
7
  import { organizationIdFromResourceOwner, resourceListAllOwners, resourcePut, } from "../resources/store.js";
8
8
  import { runWithRequestContext } from "../server/request-context.js";
9
9
  import { nextOccurrence, isValidCron, describeCron } from "./cron.js";
10
+ const MAX_JOB_MCP_TOOLS = 64;
11
+ const JOB_MCP_TOOL_NAME_RE = /^mcp__[^\s]+__[^\s]+$/;
12
+ /**
13
+ * Normalize the non-secret MCP capability references persisted with a job.
14
+ * Tool names are opaque framework identifiers; URLs and credentials never
15
+ * belong in job frontmatter.
16
+ */
17
+ export function normalizeJobMcpTools(value) {
18
+ if (value === undefined || value === null)
19
+ return undefined;
20
+ const parsed = typeof value === "string"
21
+ ? (() => {
22
+ try {
23
+ return JSON.parse(value);
24
+ }
25
+ catch {
26
+ throw new Error("mcpTools must be a JSON array of tool names.");
27
+ }
28
+ })()
29
+ : value;
30
+ if (!Array.isArray(parsed)) {
31
+ throw new Error("mcpTools must be an array of MCP tool names.");
32
+ }
33
+ if (parsed.length > MAX_JOB_MCP_TOOLS) {
34
+ throw new Error(`mcpTools may contain at most ${MAX_JOB_MCP_TOOLS} tool names.`);
35
+ }
36
+ const normalized = [...new Set(parsed)];
37
+ if (normalized.some((toolName) => typeof toolName !== "string" || !JOB_MCP_TOOL_NAME_RE.test(toolName))) {
38
+ throw new Error("mcpTools must contain only framework MCP tool names such as mcp__server__tool.");
39
+ }
40
+ return normalized;
41
+ }
10
42
  const FRONTMATTER_RE = /^---\n([\s\S]*?)\n---\n?([\s\S]*)$/;
11
43
  export function parseJobFrontmatter(content) {
12
44
  const match = content.match(FRONTMATTER_RE);
@@ -82,6 +114,15 @@ export function parseJobFrontmatter(content) {
82
114
  case "model":
83
115
  meta.model = value;
84
116
  break;
117
+ case "mcpTools":
118
+ try {
119
+ meta.mcpTools = normalizeJobMcpTools(value);
120
+ }
121
+ catch {
122
+ // Ignore malformed optional capability metadata and keep the job
123
+ // readable; newly-created jobs are validated before persistence.
124
+ }
125
+ break;
85
126
  }
86
127
  }
87
128
  return { meta, body };
@@ -125,6 +166,8 @@ export function buildJobContent(meta, body) {
125
166
  lines.push(`deliveryTenantId: ${meta.deliveryTenantId}`);
126
167
  if (meta.model)
127
168
  lines.push(`model: ${meta.model}`);
169
+ if (meta.mcpTools?.length)
170
+ lines.push(`mcpTools: ${JSON.stringify(meta.mcpTools)}`);
128
171
  lines.push(`---`);
129
172
  lines.push("");
130
173
  lines.push(body);
@@ -372,9 +415,15 @@ async function executeJob(resource, meta, body, deps, now) {
372
415
  : {}),
373
416
  }, async () => {
374
417
  try {
375
- const baseActions = deps.getActions();
418
+ const jobContext = {
419
+ name: jobName,
420
+ meta,
421
+ body,
422
+ resource,
423
+ };
424
+ const baseActions = deps.getActions(jobContext);
376
425
  const systemPrompt = await deps.getSystemPrompt(jobUserEmail);
377
- const initialToolNames = deps.getInitialToolNames?.();
426
+ const initialToolNames = deps.getInitialToolNames?.(jobContext);
378
427
  // Only attach tool-search (and pay its schema cost) when the caller
379
428
  // actually supplied an initial subset to filter down to — otherwise
380
429
  // this is byte-for-byte the prior unfiltered behavior.
@@ -1 +1 @@
1
- {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/jobs/scheduler.ts"],"names":[],"mappings":"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","sourcesContent":["import { collectFinalResponseTextFromAgentEvents } from \"../a2a/response-text.js\";\nimport {\n getStoredModelForEngine,\n normalizeModelForEngine,\n resolveEngine,\n} from \"../agent/engine/index.js\";\nimport type { AgentEngine } from \"../agent/engine/types.js\";\nimport {\n runAgentLoop,\n actionsToEngineTools,\n filterInitialEngineTools,\n getOwnerActiveApiKey,\n type ActionEntry,\n} from \"../agent/production-agent.js\";\nimport { startRun, resolveRunSoftTimeoutMs } from \"../agent/run-manager.js\";\nimport { attachToolSearch } from \"../agent/tool-search.js\";\nimport { createThread } from \"../chat-threads/store.js\";\nimport {\n organizationIdFromResourceOwner,\n resourceListAllOwners,\n resourcePut,\n type Resource,\n} from \"../resources/store.js\";\nimport { runWithRequestContext } from \"../server/request-context.js\";\nimport { nextOccurrence, isValidCron, describeCron } from \"./cron.js\";\n\n// ─── Frontmatter parsing ────────────────────────────────────────────────────\n\nexport interface JobFrontmatter {\n schedule: string;\n enabled: boolean;\n createdBy?: string;\n orgId?: string;\n runAs?: \"creator\" | \"shared\";\n lastRun?: string;\n lastStatus?: \"success\" | \"error\" | \"running\" | \"skipped\";\n lastError?: string;\n nextRun?: string;\n originScopeId?: string;\n deliveryPlatform?: string;\n deliveryDestination?: string;\n deliveryThreadRef?: string;\n deliveryTenantId?: string;\n model?: string;\n}\n\nconst FRONTMATTER_RE = /^---\\n([\\s\\S]*?)\\n---\\n?([\\s\\S]*)$/;\n\nexport function parseJobFrontmatter(content: string): {\n meta: JobFrontmatter;\n body: string;\n} {\n const match = content.match(FRONTMATTER_RE);\n if (!match) {\n return {\n meta: { schedule: \"\", enabled: false },\n body: content,\n };\n }\n\n const yamlBlock = match[1];\n const body = match[2].trim();\n\n const meta: JobFrontmatter = { schedule: \"\", enabled: true };\n\n for (const line of yamlBlock.split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n const key = line.slice(0, colonIdx).trim();\n let value = line.slice(colonIdx + 1).trim();\n\n // Strip quotes\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n\n switch (key) {\n case \"schedule\":\n meta.schedule = value;\n break;\n case \"enabled\":\n meta.enabled = value !== \"false\";\n break;\n case \"createdBy\":\n meta.createdBy = value;\n break;\n case \"orgId\":\n meta.orgId = value;\n break;\n case \"runAs\":\n meta.runAs =\n value === \"shared\" || value === \"creator\" ? value : undefined;\n break;\n case \"lastRun\":\n meta.lastRun = value;\n break;\n case \"lastStatus\":\n meta.lastStatus = value as JobFrontmatter[\"lastStatus\"];\n break;\n case \"lastError\":\n // Reverse the escaping applied in buildJobContent.\n meta.lastError = value\n .replace(/\\\\n/g, \"\\n\")\n .replace(/\\\\r/g, \"\\r\")\n .replace(/\\\\\"/g, '\"')\n .replace(/\\\\\\\\/g, \"\\\\\");\n break;\n case \"nextRun\":\n meta.nextRun = value;\n break;\n case \"originScopeId\":\n meta.originScopeId = value;\n break;\n case \"deliveryPlatform\":\n meta.deliveryPlatform = value;\n break;\n case \"deliveryDestination\":\n meta.deliveryDestination = value;\n break;\n case \"deliveryThreadRef\":\n meta.deliveryThreadRef = value;\n break;\n case \"deliveryTenantId\":\n meta.deliveryTenantId = value;\n break;\n case \"model\":\n meta.model = value;\n break;\n }\n }\n\n return { meta, body };\n}\n\nexport function buildJobContent(meta: JobFrontmatter, body: string): string {\n const lines = [`---`];\n lines.push(`schedule: \"${meta.schedule}\"`);\n lines.push(`enabled: ${meta.enabled}`);\n if (meta.createdBy) lines.push(`createdBy: ${meta.createdBy}`);\n if (meta.orgId) lines.push(`orgId: ${meta.orgId}`);\n if (meta.runAs) lines.push(`runAs: ${meta.runAs}`);\n if (meta.lastRun) lines.push(`lastRun: ${meta.lastRun}`);\n if (meta.lastStatus) lines.push(`lastStatus: ${meta.lastStatus}`);\n if (meta.lastError) {\n // Escape backslash, quote, then CR/LF. The frontmatter parser splits on\n // \"\\n\", so an un-escaped newline (common in stack traces) would otherwise\n // split the value across lines and corrupt/truncate the stored error.\n const escaped = meta.lastError\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/\"/g, '\\\\\"')\n .replace(/\\r/g, \"\\\\r\")\n .replace(/\\n/g, \"\\\\n\");\n lines.push(`lastError: \"${escaped}\"`);\n }\n if (meta.nextRun) lines.push(`nextRun: ${meta.nextRun}`);\n if (meta.originScopeId) lines.push(`originScopeId: ${meta.originScopeId}`);\n if (meta.deliveryPlatform)\n lines.push(`deliveryPlatform: ${meta.deliveryPlatform}`);\n if (meta.deliveryDestination)\n lines.push(`deliveryDestination: ${meta.deliveryDestination}`);\n if (meta.deliveryThreadRef)\n lines.push(`deliveryThreadRef: ${meta.deliveryThreadRef}`);\n if (meta.deliveryTenantId)\n lines.push(`deliveryTenantId: ${meta.deliveryTenantId}`);\n if (meta.model) lines.push(`model: ${meta.model}`);\n lines.push(`---`);\n lines.push(\"\");\n lines.push(body);\n return lines.join(\"\\n\");\n}\n\n// ─── Job execution ──────────────────────────────────────────────────────────\n\nexport interface SchedulerDeps {\n getActions: () => Record<string, ActionEntry>;\n getSystemPrompt: (owner: string) => Promise<string>;\n /**\n * Tool names to expose on the FIRST engine request for a job run. When\n * provided, every other action returned by `getActions()` is deferred\n * behind an attached `tool-search` entry instead of being serialized on\n * every scheduled tick — `runAgentLoop`'s mid-run tool expansion\n * (`expandActiveTools`) still lets the model discover and call them after\n * a search. Omit to keep the full `getActions()` set visible up front\n * (current behavior). The caller (not this module) knows which of the\n * merged actions are the app's own vs. framework additions, so this must\n * be supplied explicitly rather than inferred here.\n */\n getInitialToolNames?: () => string[] | undefined;\n /** Optional engine override. Defaults to the resolved request engine. */\n engine?: AgentEngine;\n apiKey?: string;\n model?: string;\n /** App/template id used for org-scoped per-app model defaults. */\n appId?: string;\n}\n\nlet _isRunning = false;\n\n// Skip the DB query on every tick if we recently confirmed no jobs exist.\n// `_hasJobsCache` is invalidated whenever a `jobs/*` resource is written or\n// deleted (subscribed below), and refreshed at most every 5 minutes.\nlet _hasJobsCache: boolean | undefined;\nlet _lastJobsCheck = 0;\nconst JOBS_CHECK_INTERVAL_MS = 5 * 60_000;\nlet _emitterSubscribed = false;\n\nfunction subscribeToJobsResourceEvents(): void {\n if (_emitterSubscribed) return;\n _emitterSubscribed = true;\n // Lazy import to avoid circular deps at module load\n import(\"../resources/emitter.js\")\n .then(({ getResourcesEmitter }) => {\n getResourcesEmitter().on(\"resources\", (event: any) => {\n if (typeof event?.path === \"string\" && event.path.startsWith(\"jobs/\")) {\n _hasJobsCache = undefined;\n }\n });\n })\n .catch((err) => {\n console.warn(\n \"[jobs] resource-event subscription failed:\",\n err instanceof Error ? err.message : err,\n );\n });\n}\n\n/**\n * Process all due recurring jobs. Called every 60 seconds.\n * Sequential execution with 5-minute timeout per job.\n */\nexport async function processRecurringJobs(deps: SchedulerDeps): Promise<void> {\n // Prevent concurrent runs\n if (_isRunning) return;\n\n subscribeToJobsResourceEvents();\n\n // Skip if we recently confirmed there are no job resources to run.\n const nowMs = Date.now();\n if (\n _hasJobsCache === false &&\n nowMs - _lastJobsCheck < JOBS_CHECK_INTERVAL_MS\n ) {\n return;\n }\n\n _isRunning = true;\n\n try {\n const jobResources = await resourceListAllOwners(\"jobs/\");\n _hasJobsCache = jobResources.some(\n (r) => r.path.endsWith(\".md\") && !r.path.endsWith(\".keep\"),\n );\n _lastJobsCheck = nowMs;\n if (!_hasJobsCache) return;\n const now = new Date();\n\n for (const resource of jobResources) {\n // Skip non-markdown or .keep files\n if (!resource.path.endsWith(\".md\")) continue;\n if (resource.path.endsWith(\".keep\")) continue;\n\n const { meta, body } = parseJobFrontmatter(resource.content);\n\n // Skip disabled or missing schedule\n if (!meta.enabled || !meta.schedule) continue;\n if (!isValidCron(meta.schedule)) continue;\n\n // Skip if currently running, unless it has been stuck for more than 10 minutes\n // (server crash mid-job leaves lastStatus=running forever without this guard)\n if (meta.lastStatus === \"running\") {\n const stuckCutoff = 10 * 60 * 1000;\n if (\n meta.lastRun &&\n now.getTime() - new Date(meta.lastRun).getTime() < stuckCutoff\n ) {\n continue;\n }\n // Stuck — reset so the next check can re-run it\n meta.lastStatus = \"error\";\n meta.lastError = \"Job timed out or server crashed mid-run\";\n const next = nextOccurrence(meta.schedule, now);\n meta.nextRun = next.toISOString();\n await updateResource(resource, meta, body);\n continue;\n }\n\n // Check if due\n if (meta.nextRun) {\n const nextRunDate = new Date(meta.nextRun);\n if (nextRunDate > now) continue;\n } else {\n // No nextRun computed yet — seed it from `now` so the job waits for its\n // real next occurrence. Computing from new Date(0) (the epoch) always\n // returns a 1970 date, which is < now, so the job would fire\n // immediately on first sight regardless of its schedule.\n const next = nextOccurrence(meta.schedule, now);\n meta.nextRun = next.toISOString();\n await updateResource(resource, meta, body);\n continue;\n }\n\n // Skip if body is empty\n if (!body.trim()) continue;\n\n // Execute the job\n await executeJob(resource, meta, body, deps, now);\n }\n } catch (err) {\n // Transient WS / connection drops (Neon serverless): silently retry next\n // tick instead of spamming stderr — `retryOnConnectionError` already did\n // its retry budget at the driver level.\n const { isConnectionError } = await import(\"../db/client.js\");\n if (isConnectionError(err)) {\n _hasJobsCache = undefined; // force re-check on next successful tick\n _lastJobsCheck = 0;\n return;\n }\n // Unwrap ErrorEvent (Neon WS driver emits these on network failure) so logs show the real cause\n const detail =\n err instanceof Error\n ? err\n : ((err as any)?.error ?? (err as any)?.message ?? err);\n console.error(\"[recurring-jobs] Error processing jobs:\", detail);\n } finally {\n _isRunning = false;\n }\n}\n\n/**\n * Validate that the run-as user still exists and (if scoped to an org) is\n * still a member of that org. Skips the check for the dev-mode bypass\n * identity and the shared-owner sentinel, neither of which map to a real\n * user row.\n *\n * SECURITY: without this check the scheduler keeps running jobs as\n * `meta.createdBy` indefinitely — even after the user has been deleted,\n * removed from the org, or had their account disabled. The cron entry\n * itself is left intact so an admin can purge it manually after the\n * underlying user-state issue is investigated. See audit 12 #10.\n */\nasync function isJobRunAsStillValid(\n jobUserEmail: string,\n jobOrgId: string | undefined,\n): Promise<{ ok: boolean; reason?: string }> {\n // Shared-owner sentinel isn't a real user (used by jobs run as the\n // workspace identity).\n if (\n jobUserEmail === \"__shared__\" ||\n organizationIdFromResourceOwner(jobUserEmail)\n ) {\n return { ok: true };\n }\n try {\n const { getDbExec } = await import(\"../db/client.js\");\n const db = getDbExec();\n // Better Auth's user table is named \"user\" (singular). The reserved\n // word is quoted to avoid ambiguity in Postgres.\n const userResult = await db.execute({\n sql: `SELECT 1 FROM \"user\" WHERE email = ? LIMIT 1`,\n args: [jobUserEmail],\n });\n if (!userResult.rows || userResult.rows.length === 0) {\n return { ok: false, reason: `user \"${jobUserEmail}\" no longer exists` };\n }\n if (jobOrgId) {\n const memberResult = await db.execute({\n sql: `SELECT 1 FROM org_members WHERE org_id = ? AND LOWER(email) = LOWER(?) LIMIT 1`,\n args: [jobOrgId, jobUserEmail],\n });\n if (!memberResult.rows || memberResult.rows.length === 0) {\n return {\n ok: false,\n reason: `user \"${jobUserEmail}\" is no longer a member of org \"${jobOrgId}\"`,\n };\n }\n }\n return { ok: true };\n } catch (err: any) {\n // Tables may not exist on a brand-new install (no auth tables yet).\n // Treat that as \"valid\" rather than blocking every job. The check is\n // only meaningful once the auth tables exist.\n const msg = err?.message?.toLowerCase() ?? \"\";\n if (\n msg.includes(\"does not exist\") ||\n msg.includes(\"no such table\") ||\n msg.includes(\"undefined table\")\n ) {\n return { ok: true };\n }\n // Any other DB error: be conservative and let the job run rather than\n // blocking on an unexpected failure mode (e.g. transient connection\n // issue). We log so it's visible.\n console.warn(\n `[recurring-jobs] User/membership validation failed for \"${jobUserEmail}\":`,\n err?.message,\n );\n return { ok: true };\n }\n}\n\nasync function executeJob(\n resource: Resource,\n meta: JobFrontmatter,\n body: string,\n deps: SchedulerDeps,\n now: Date,\n): Promise<void> {\n const jobName = resource.path.replace(/^jobs\\//, \"\").replace(/\\.md$/, \"\");\n\n // Set owner context so all scoped operations (app-state, resources, etc.)\n // operate on the correct user's data\n const effectiveRunAs = meta.runAs ?? \"creator\";\n const jobUserEmail =\n effectiveRunAs === \"creator\"\n ? meta.createdBy || resource.owner\n : resource.owner;\n const jobOrgId = meta.orgId ?? undefined;\n\n // SECURITY (audit 12 #10): re-validate the run-as user/membership on\n // every tick. Sharing revocation, user deletion, and org-member removal\n // must take effect for already-scheduled jobs. Skip the tick on\n // failure; leave the cron entry alone so an admin can purge after\n // investigation.\n const validity = await isJobRunAsStillValid(jobUserEmail, jobOrgId);\n if (!validity.ok) {\n console.warn(\n `[recurring-jobs] Skipping job \"${jobName}\": ${validity.reason}. ` +\n `User/membership no longer valid — leaving cron entry for admin review.`,\n );\n // Mark as skipped without resetting nextRun so an admin can find it.\n meta.lastRun = now.toISOString();\n meta.lastStatus = \"skipped\";\n meta.lastError = validity.reason;\n await updateResource(resource, meta, body);\n return;\n }\n\n // Mark as running\n meta.lastRun = now.toISOString();\n meta.lastStatus = \"running\";\n meta.lastError = undefined;\n await updateResource(resource, meta, body);\n\n await runWithRequestContext(\n {\n userEmail: jobUserEmail,\n orgId: jobOrgId,\n ...(meta.originScopeId &&\n meta.deliveryPlatform &&\n meta.deliveryDestination\n ? {\n isIntegrationCaller: true,\n integration: {\n taskId: `job:${jobName}:${now.getTime()}`,\n scopeId: meta.originScopeId,\n principalType: \"service\" as const,\n incoming: {\n platform: meta.deliveryPlatform,\n externalThreadId: `${meta.deliveryTenantId || \"unknown\"}:${meta.deliveryDestination}:${meta.deliveryThreadRef || \"root\"}`,\n text: \"\",\n tenantId: meta.deliveryTenantId,\n integrationScopeId: meta.originScopeId,\n platformContext: {\n channelId: meta.deliveryDestination,\n threadTs: meta.deliveryThreadRef,\n teamId: meta.deliveryTenantId,\n },\n threadRef: meta.deliveryThreadRef,\n timestamp: now.getTime(),\n },\n },\n }\n : {}),\n },\n async () => {\n try {\n const baseActions = deps.getActions();\n const systemPrompt = await deps.getSystemPrompt(jobUserEmail);\n const initialToolNames = deps.getInitialToolNames?.();\n // Only attach tool-search (and pay its schema cost) when the caller\n // actually supplied an initial subset to filter down to — otherwise\n // this is byte-for-byte the prior unfiltered behavior.\n const actions = initialToolNames\n ? attachToolSearch({ ...baseActions })\n : baseActions;\n const availableTools = actionsToEngineTools(actions);\n const tools = filterInitialEngineTools(\n availableTools,\n initialToolNames,\n );\n\n // Prefer the job runner's saved Anthropic key so recurring jobs\n // don't silently bill the shared platform key once a user has\n // brought their own. Falls back to the platform key when absent.\n const userApiKey = await getOwnerActiveApiKey(jobUserEmail);\n const engine =\n deps.engine ??\n (await resolveEngine({\n apiKey: userApiKey ?? deps.apiKey,\n appId: deps.appId,\n }));\n const modelCandidate =\n meta.model ??\n deps.model ??\n (await getStoredModelForEngine(engine, { appId: deps.appId })) ??\n engine.defaultModel;\n const model = normalizeModelForEngine(engine, modelCandidate);\n\n // Create a chat thread for this run\n const threadTitle = `Job: ${jobName} — ${now.toLocaleDateString()}`;\n const thread = await createThread(jobUserEmail, { title: threadTitle });\n\n const jobText = `[Recurring Job: ${jobName}]\\nSchedule: ${describeCron(meta.schedule)}\\n\\nExecute the following job instructions:\\n\\n${body}`;\n const messages = [\n {\n role: \"user\" as const,\n content: [{ type: \"text\" as const, text: jobText }],\n },\n ];\n\n // Route through startRun (from run-manager) instead of calling\n // runAgentLoop directly. This adds:\n // 1. A heartbeat row in agent_runs so a serverless kill is detected\n // by reapAllStaleRuns on the next startup and the row is flipped\n // to 'errored' — no more stranded lastStatus:\"running\" in the job\n // frontmatter after the next tick resets it via the stuck-guard.\n // 2. The soft-timeout infrastructure so the job checkpoints cleanly\n // before serverless hard-kill rather than dying mid-flight.\n // 3. SQL abort checks so a displaced/reaped run self-aborts instead\n // of completing invisibly and potentially overwriting newer state.\n const runId = `job-${jobName.replace(/[^a-zA-Z0-9._-]/g, \"-\")}-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;\n\n // Use the same soft-timeout logic as interactive runs. On hosted\n // runtimes this clamps to 40s (under the gateway wall); locally it\n // defaults to 0 (no framework timeout). The 5-minute hard-abort\n // below is still provided as a backstop via the startRun signal.\n const softTimeoutMs = resolveRunSoftTimeoutMs(undefined, {\n useHostedDefault: true,\n });\n\n let jobError: Error | null = null;\n // Hard-abort backstop: 5 minutes. On hosted runtimes the soft-timeout\n // will fire first; locally this is the only guard. Cleared when the\n // run completes so finished jobs don't leave a live timer keeping the\n // process/event loop alive for the remainder of the window.\n let hardAbortTimer: ReturnType<typeof setTimeout> | null = null;\n const jobUsageRef: {\n current: Awaited<ReturnType<typeof runAgentLoop>> | null;\n } = { current: null };\n let responseText = \"\";\n await new Promise<void>((resolve, reject) => {\n const activeRun = startRun(\n runId,\n thread.id,\n async (send, signal) => {\n try {\n jobUsageRef.current = await runAgentLoop({\n engine,\n model,\n systemPrompt,\n tools,\n availableTools,\n messages,\n actions,\n send,\n signal,\n threadId: thread.id,\n });\n } catch (err) {\n throw err;\n }\n },\n // onComplete: run finished (completed or aborted)\n async (run) => {\n if (hardAbortTimer) {\n clearTimeout(hardAbortTimer);\n hardAbortTimer = null;\n }\n if (run.status === \"completed\") {\n responseText = collectFinalResponseTextFromAgentEvents(\n (run.events ?? []).map((event) => event.event),\n );\n resolve();\n } else {\n reject(new Error(`Job run ended with status: ${run.status}`));\n }\n },\n {\n softTimeoutMs,\n // turnId defaults to runId — fine for single-turn jobs\n },\n );\n\n // Abort the run-manager's own controller after 5 minutes if the\n // run hasn't finished naturally.\n hardAbortTimer = setTimeout(\n () => {\n hardAbortTimer = null;\n if (activeRun.status === \"running\") {\n activeRun.abort.abort(\"job_hard_timeout\");\n reject(new Error(\"Job timed out after 5 minutes\"));\n }\n },\n 5 * 60 * 1000,\n );\n }).catch((err: any) => {\n jobError = err;\n });\n if (hardAbortTimer) {\n clearTimeout(hardAbortTimer);\n hardAbortTimer = null;\n }\n\n if (jobError) throw jobError;\n\n if (\n responseText.trim() &&\n meta.deliveryPlatform &&\n meta.deliveryDestination\n ) {\n const { getDefaultAdapter } =\n await import(\"../integrations/adapters/index.js\");\n const adapter = getDefaultAdapter(meta.deliveryPlatform);\n if (!adapter?.sendMessageToTarget) {\n throw new Error(\n `Recurring job delivery is not supported for ${meta.deliveryPlatform}`,\n );\n }\n await adapter.sendMessageToTarget(\n adapter.formatAgentResponse(responseText),\n {\n destination: meta.deliveryDestination,\n threadRef: meta.deliveryThreadRef ?? null,\n tenantId: meta.deliveryTenantId,\n },\n );\n }\n\n const jobUsage = jobUsageRef.current;\n if (\n jobUsage &&\n (jobUsage.inputTokens > 0 ||\n jobUsage.outputTokens > 0 ||\n jobUsage.cacheReadTokens > 0 ||\n jobUsage.cacheWriteTokens > 0)\n ) {\n try {\n const { recordUsage } = await import(\"../usage/store.js\");\n await recordUsage({\n ownerEmail: jobUserEmail,\n inputTokens: jobUsage.inputTokens,\n outputTokens: jobUsage.outputTokens,\n cacheReadTokens: jobUsage.cacheReadTokens,\n cacheWriteTokens: jobUsage.cacheWriteTokens,\n model: jobUsage.model,\n label: `recurring-job:${jobName}`,\n app: deps.appId,\n refId: runId,\n });\n } catch {\n // Usage attribution must not break the scheduled task.\n }\n }\n\n // Success — update status. Compute the next run from completion time,\n // not the job's start time `now`: a long run could otherwise schedule a\n // nextRun that's already in the past and re-fire immediately next tick.\n const next = nextOccurrence(meta.schedule, new Date());\n meta.lastStatus = \"success\";\n meta.nextRun = next.toISOString();\n await updateResource(resource, meta, body);\n\n console.log(\n `[recurring-jobs] Job \"${jobName}\" completed. Next run: ${meta.nextRun}`,\n );\n } catch (err: any) {\n // Error — update status. Use completion time (see success path).\n const next = nextOccurrence(meta.schedule, new Date());\n meta.lastStatus = \"error\";\n meta.lastError = err?.message?.slice(0, 200) || \"Unknown error\";\n meta.nextRun = next.toISOString();\n await updateResource(resource, meta, body);\n\n console.error(\n `[recurring-jobs] Job \"${jobName}\" failed:`,\n err?.message,\n );\n }\n },\n ); // end runWithRequestContext\n}\n\nasync function updateResource(\n resource: Resource,\n meta: JobFrontmatter,\n body: string,\n): Promise<void> {\n const content = buildJobContent(meta, body);\n await resourcePut(resource.owner, resource.path, content);\n}\n"]}
1
+ {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/jobs/scheduler.ts"],"names":[],"mappings":"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","sourcesContent":["import { collectFinalResponseTextFromAgentEvents } from \"../a2a/response-text.js\";\nimport {\n getStoredModelForEngine,\n normalizeModelForEngine,\n resolveEngine,\n} from \"../agent/engine/index.js\";\nimport type { AgentEngine } from \"../agent/engine/types.js\";\nimport {\n runAgentLoop,\n actionsToEngineTools,\n filterInitialEngineTools,\n getOwnerActiveApiKey,\n type ActionEntry,\n} from \"../agent/production-agent.js\";\nimport { startRun, resolveRunSoftTimeoutMs } from \"../agent/run-manager.js\";\nimport { attachToolSearch } from \"../agent/tool-search.js\";\nimport { createThread } from \"../chat-threads/store.js\";\nimport {\n organizationIdFromResourceOwner,\n resourceListAllOwners,\n resourcePut,\n type Resource,\n} from \"../resources/store.js\";\nimport { runWithRequestContext } from \"../server/request-context.js\";\nimport { nextOccurrence, isValidCron, describeCron } from \"./cron.js\";\n\n// ─── Frontmatter parsing ────────────────────────────────────────────────────\n\nexport interface JobFrontmatter {\n schedule: string;\n enabled: boolean;\n createdBy?: string;\n orgId?: string;\n runAs?: \"creator\" | \"shared\";\n lastRun?: string;\n lastStatus?: \"success\" | \"error\" | \"running\" | \"skipped\";\n lastError?: string;\n nextRun?: string;\n originScopeId?: string;\n deliveryPlatform?: string;\n deliveryDestination?: string;\n deliveryThreadRef?: string;\n deliveryTenantId?: string;\n model?: string;\n /** Explicit MCP tool capabilities available to this background run. */\n mcpTools?: string[];\n}\n\nconst MAX_JOB_MCP_TOOLS = 64;\nconst JOB_MCP_TOOL_NAME_RE = /^mcp__[^\\s]+__[^\\s]+$/;\n\n/**\n * Normalize the non-secret MCP capability references persisted with a job.\n * Tool names are opaque framework identifiers; URLs and credentials never\n * belong in job frontmatter.\n */\nexport function normalizeJobMcpTools(value: unknown): string[] | undefined {\n if (value === undefined || value === null) return undefined;\n const parsed =\n typeof value === \"string\"\n ? (() => {\n try {\n return JSON.parse(value);\n } catch {\n throw new Error(\"mcpTools must be a JSON array of tool names.\");\n }\n })()\n : value;\n if (!Array.isArray(parsed)) {\n throw new Error(\"mcpTools must be an array of MCP tool names.\");\n }\n if (parsed.length > MAX_JOB_MCP_TOOLS) {\n throw new Error(\n `mcpTools may contain at most ${MAX_JOB_MCP_TOOLS} tool names.`,\n );\n }\n const normalized = [...new Set(parsed)];\n if (\n normalized.some(\n (toolName) =>\n typeof toolName !== \"string\" || !JOB_MCP_TOOL_NAME_RE.test(toolName),\n )\n ) {\n throw new Error(\n \"mcpTools must contain only framework MCP tool names such as mcp__server__tool.\",\n );\n }\n return normalized;\n}\n\nconst FRONTMATTER_RE = /^---\\n([\\s\\S]*?)\\n---\\n?([\\s\\S]*)$/;\n\nexport function parseJobFrontmatter(content: string): {\n meta: JobFrontmatter;\n body: string;\n} {\n const match = content.match(FRONTMATTER_RE);\n if (!match) {\n return {\n meta: { schedule: \"\", enabled: false },\n body: content,\n };\n }\n\n const yamlBlock = match[1];\n const body = match[2].trim();\n\n const meta: JobFrontmatter = { schedule: \"\", enabled: true };\n\n for (const line of yamlBlock.split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n const key = line.slice(0, colonIdx).trim();\n let value = line.slice(colonIdx + 1).trim();\n\n // Strip quotes\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n\n switch (key) {\n case \"schedule\":\n meta.schedule = value;\n break;\n case \"enabled\":\n meta.enabled = value !== \"false\";\n break;\n case \"createdBy\":\n meta.createdBy = value;\n break;\n case \"orgId\":\n meta.orgId = value;\n break;\n case \"runAs\":\n meta.runAs =\n value === \"shared\" || value === \"creator\" ? value : undefined;\n break;\n case \"lastRun\":\n meta.lastRun = value;\n break;\n case \"lastStatus\":\n meta.lastStatus = value as JobFrontmatter[\"lastStatus\"];\n break;\n case \"lastError\":\n // Reverse the escaping applied in buildJobContent.\n meta.lastError = value\n .replace(/\\\\n/g, \"\\n\")\n .replace(/\\\\r/g, \"\\r\")\n .replace(/\\\\\"/g, '\"')\n .replace(/\\\\\\\\/g, \"\\\\\");\n break;\n case \"nextRun\":\n meta.nextRun = value;\n break;\n case \"originScopeId\":\n meta.originScopeId = value;\n break;\n case \"deliveryPlatform\":\n meta.deliveryPlatform = value;\n break;\n case \"deliveryDestination\":\n meta.deliveryDestination = value;\n break;\n case \"deliveryThreadRef\":\n meta.deliveryThreadRef = value;\n break;\n case \"deliveryTenantId\":\n meta.deliveryTenantId = value;\n break;\n case \"model\":\n meta.model = value;\n break;\n case \"mcpTools\":\n try {\n meta.mcpTools = normalizeJobMcpTools(value);\n } catch {\n // Ignore malformed optional capability metadata and keep the job\n // readable; newly-created jobs are validated before persistence.\n }\n break;\n }\n }\n\n return { meta, body };\n}\n\nexport function buildJobContent(meta: JobFrontmatter, body: string): string {\n const lines = [`---`];\n lines.push(`schedule: \"${meta.schedule}\"`);\n lines.push(`enabled: ${meta.enabled}`);\n if (meta.createdBy) lines.push(`createdBy: ${meta.createdBy}`);\n if (meta.orgId) lines.push(`orgId: ${meta.orgId}`);\n if (meta.runAs) lines.push(`runAs: ${meta.runAs}`);\n if (meta.lastRun) lines.push(`lastRun: ${meta.lastRun}`);\n if (meta.lastStatus) lines.push(`lastStatus: ${meta.lastStatus}`);\n if (meta.lastError) {\n // Escape backslash, quote, then CR/LF. The frontmatter parser splits on\n // \"\\n\", so an un-escaped newline (common in stack traces) would otherwise\n // split the value across lines and corrupt/truncate the stored error.\n const escaped = meta.lastError\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/\"/g, '\\\\\"')\n .replace(/\\r/g, \"\\\\r\")\n .replace(/\\n/g, \"\\\\n\");\n lines.push(`lastError: \"${escaped}\"`);\n }\n if (meta.nextRun) lines.push(`nextRun: ${meta.nextRun}`);\n if (meta.originScopeId) lines.push(`originScopeId: ${meta.originScopeId}`);\n if (meta.deliveryPlatform)\n lines.push(`deliveryPlatform: ${meta.deliveryPlatform}`);\n if (meta.deliveryDestination)\n lines.push(`deliveryDestination: ${meta.deliveryDestination}`);\n if (meta.deliveryThreadRef)\n lines.push(`deliveryThreadRef: ${meta.deliveryThreadRef}`);\n if (meta.deliveryTenantId)\n lines.push(`deliveryTenantId: ${meta.deliveryTenantId}`);\n if (meta.model) lines.push(`model: ${meta.model}`);\n if (meta.mcpTools?.length)\n lines.push(`mcpTools: ${JSON.stringify(meta.mcpTools)}`);\n lines.push(`---`);\n lines.push(\"\");\n lines.push(body);\n return lines.join(\"\\n\");\n}\n\n// ─── Job execution ──────────────────────────────────────────────────────────\n\nexport interface RecurringJobContext {\n name: string;\n meta: JobFrontmatter;\n body: string;\n resource: Resource;\n}\n\nexport interface SchedulerDeps {\n getActions: (job?: RecurringJobContext) => Record<string, ActionEntry>;\n getSystemPrompt: (owner: string) => Promise<string>;\n /**\n * Tool names to expose on the FIRST engine request for a job run. When\n * provided, every other action returned by `getActions()` is deferred\n * behind an attached `tool-search` entry instead of being serialized on\n * every scheduled tick — `runAgentLoop`'s mid-run tool expansion\n * (`expandActiveTools`) still lets the model discover and call them after\n * a search. Omit to keep the full `getActions()` set visible up front\n * (current behavior). The caller (not this module) knows which of the\n * merged actions are the app's own vs. framework additions, so this must\n * be supplied explicitly rather than inferred here.\n */\n getInitialToolNames?: (job?: RecurringJobContext) => string[] | undefined;\n /** Optional engine override. Defaults to the resolved request engine. */\n engine?: AgentEngine;\n apiKey?: string;\n model?: string;\n /** App/template id used for org-scoped per-app model defaults. */\n appId?: string;\n}\n\nlet _isRunning = false;\n\n// Skip the DB query on every tick if we recently confirmed no jobs exist.\n// `_hasJobsCache` is invalidated whenever a `jobs/*` resource is written or\n// deleted (subscribed below), and refreshed at most every 5 minutes.\nlet _hasJobsCache: boolean | undefined;\nlet _lastJobsCheck = 0;\nconst JOBS_CHECK_INTERVAL_MS = 5 * 60_000;\nlet _emitterSubscribed = false;\n\nfunction subscribeToJobsResourceEvents(): void {\n if (_emitterSubscribed) return;\n _emitterSubscribed = true;\n // Lazy import to avoid circular deps at module load\n import(\"../resources/emitter.js\")\n .then(({ getResourcesEmitter }) => {\n getResourcesEmitter().on(\"resources\", (event: any) => {\n if (typeof event?.path === \"string\" && event.path.startsWith(\"jobs/\")) {\n _hasJobsCache = undefined;\n }\n });\n })\n .catch((err) => {\n console.warn(\n \"[jobs] resource-event subscription failed:\",\n err instanceof Error ? err.message : err,\n );\n });\n}\n\n/**\n * Process all due recurring jobs. Called every 60 seconds.\n * Sequential execution with 5-minute timeout per job.\n */\nexport async function processRecurringJobs(deps: SchedulerDeps): Promise<void> {\n // Prevent concurrent runs\n if (_isRunning) return;\n\n subscribeToJobsResourceEvents();\n\n // Skip if we recently confirmed there are no job resources to run.\n const nowMs = Date.now();\n if (\n _hasJobsCache === false &&\n nowMs - _lastJobsCheck < JOBS_CHECK_INTERVAL_MS\n ) {\n return;\n }\n\n _isRunning = true;\n\n try {\n const jobResources = await resourceListAllOwners(\"jobs/\");\n _hasJobsCache = jobResources.some(\n (r) => r.path.endsWith(\".md\") && !r.path.endsWith(\".keep\"),\n );\n _lastJobsCheck = nowMs;\n if (!_hasJobsCache) return;\n const now = new Date();\n\n for (const resource of jobResources) {\n // Skip non-markdown or .keep files\n if (!resource.path.endsWith(\".md\")) continue;\n if (resource.path.endsWith(\".keep\")) continue;\n\n const { meta, body } = parseJobFrontmatter(resource.content);\n\n // Skip disabled or missing schedule\n if (!meta.enabled || !meta.schedule) continue;\n if (!isValidCron(meta.schedule)) continue;\n\n // Skip if currently running, unless it has been stuck for more than 10 minutes\n // (server crash mid-job leaves lastStatus=running forever without this guard)\n if (meta.lastStatus === \"running\") {\n const stuckCutoff = 10 * 60 * 1000;\n if (\n meta.lastRun &&\n now.getTime() - new Date(meta.lastRun).getTime() < stuckCutoff\n ) {\n continue;\n }\n // Stuck — reset so the next check can re-run it\n meta.lastStatus = \"error\";\n meta.lastError = \"Job timed out or server crashed mid-run\";\n const next = nextOccurrence(meta.schedule, now);\n meta.nextRun = next.toISOString();\n await updateResource(resource, meta, body);\n continue;\n }\n\n // Check if due\n if (meta.nextRun) {\n const nextRunDate = new Date(meta.nextRun);\n if (nextRunDate > now) continue;\n } else {\n // No nextRun computed yet — seed it from `now` so the job waits for its\n // real next occurrence. Computing from new Date(0) (the epoch) always\n // returns a 1970 date, which is < now, so the job would fire\n // immediately on first sight regardless of its schedule.\n const next = nextOccurrence(meta.schedule, now);\n meta.nextRun = next.toISOString();\n await updateResource(resource, meta, body);\n continue;\n }\n\n // Skip if body is empty\n if (!body.trim()) continue;\n\n // Execute the job\n await executeJob(resource, meta, body, deps, now);\n }\n } catch (err) {\n // Transient WS / connection drops (Neon serverless): silently retry next\n // tick instead of spamming stderr — `retryOnConnectionError` already did\n // its retry budget at the driver level.\n const { isConnectionError } = await import(\"../db/client.js\");\n if (isConnectionError(err)) {\n _hasJobsCache = undefined; // force re-check on next successful tick\n _lastJobsCheck = 0;\n return;\n }\n // Unwrap ErrorEvent (Neon WS driver emits these on network failure) so logs show the real cause\n const detail =\n err instanceof Error\n ? err\n : ((err as any)?.error ?? (err as any)?.message ?? err);\n console.error(\"[recurring-jobs] Error processing jobs:\", detail);\n } finally {\n _isRunning = false;\n }\n}\n\n/**\n * Validate that the run-as user still exists and (if scoped to an org) is\n * still a member of that org. Skips the check for the dev-mode bypass\n * identity and the shared-owner sentinel, neither of which map to a real\n * user row.\n *\n * SECURITY: without this check the scheduler keeps running jobs as\n * `meta.createdBy` indefinitely — even after the user has been deleted,\n * removed from the org, or had their account disabled. The cron entry\n * itself is left intact so an admin can purge it manually after the\n * underlying user-state issue is investigated. See audit 12 #10.\n */\nasync function isJobRunAsStillValid(\n jobUserEmail: string,\n jobOrgId: string | undefined,\n): Promise<{ ok: boolean; reason?: string }> {\n // Shared-owner sentinel isn't a real user (used by jobs run as the\n // workspace identity).\n if (\n jobUserEmail === \"__shared__\" ||\n organizationIdFromResourceOwner(jobUserEmail)\n ) {\n return { ok: true };\n }\n try {\n const { getDbExec } = await import(\"../db/client.js\");\n const db = getDbExec();\n // Better Auth's user table is named \"user\" (singular). The reserved\n // word is quoted to avoid ambiguity in Postgres.\n const userResult = await db.execute({\n sql: `SELECT 1 FROM \"user\" WHERE email = ? LIMIT 1`,\n args: [jobUserEmail],\n });\n if (!userResult.rows || userResult.rows.length === 0) {\n return { ok: false, reason: `user \"${jobUserEmail}\" no longer exists` };\n }\n if (jobOrgId) {\n const memberResult = await db.execute({\n sql: `SELECT 1 FROM org_members WHERE org_id = ? AND LOWER(email) = LOWER(?) LIMIT 1`,\n args: [jobOrgId, jobUserEmail],\n });\n if (!memberResult.rows || memberResult.rows.length === 0) {\n return {\n ok: false,\n reason: `user \"${jobUserEmail}\" is no longer a member of org \"${jobOrgId}\"`,\n };\n }\n }\n return { ok: true };\n } catch (err: any) {\n // Tables may not exist on a brand-new install (no auth tables yet).\n // Treat that as \"valid\" rather than blocking every job. The check is\n // only meaningful once the auth tables exist.\n const msg = err?.message?.toLowerCase() ?? \"\";\n if (\n msg.includes(\"does not exist\") ||\n msg.includes(\"no such table\") ||\n msg.includes(\"undefined table\")\n ) {\n return { ok: true };\n }\n // Any other DB error: be conservative and let the job run rather than\n // blocking on an unexpected failure mode (e.g. transient connection\n // issue). We log so it's visible.\n console.warn(\n `[recurring-jobs] User/membership validation failed for \"${jobUserEmail}\":`,\n err?.message,\n );\n return { ok: true };\n }\n}\n\nasync function executeJob(\n resource: Resource,\n meta: JobFrontmatter,\n body: string,\n deps: SchedulerDeps,\n now: Date,\n): Promise<void> {\n const jobName = resource.path.replace(/^jobs\\//, \"\").replace(/\\.md$/, \"\");\n\n // Set owner context so all scoped operations (app-state, resources, etc.)\n // operate on the correct user's data\n const effectiveRunAs = meta.runAs ?? \"creator\";\n const jobUserEmail =\n effectiveRunAs === \"creator\"\n ? meta.createdBy || resource.owner\n : resource.owner;\n const jobOrgId = meta.orgId ?? undefined;\n\n // SECURITY (audit 12 #10): re-validate the run-as user/membership on\n // every tick. Sharing revocation, user deletion, and org-member removal\n // must take effect for already-scheduled jobs. Skip the tick on\n // failure; leave the cron entry alone so an admin can purge after\n // investigation.\n const validity = await isJobRunAsStillValid(jobUserEmail, jobOrgId);\n if (!validity.ok) {\n console.warn(\n `[recurring-jobs] Skipping job \"${jobName}\": ${validity.reason}. ` +\n `User/membership no longer valid — leaving cron entry for admin review.`,\n );\n // Mark as skipped without resetting nextRun so an admin can find it.\n meta.lastRun = now.toISOString();\n meta.lastStatus = \"skipped\";\n meta.lastError = validity.reason;\n await updateResource(resource, meta, body);\n return;\n }\n\n // Mark as running\n meta.lastRun = now.toISOString();\n meta.lastStatus = \"running\";\n meta.lastError = undefined;\n await updateResource(resource, meta, body);\n\n await runWithRequestContext(\n {\n userEmail: jobUserEmail,\n orgId: jobOrgId,\n ...(meta.originScopeId &&\n meta.deliveryPlatform &&\n meta.deliveryDestination\n ? {\n isIntegrationCaller: true,\n integration: {\n taskId: `job:${jobName}:${now.getTime()}`,\n scopeId: meta.originScopeId,\n principalType: \"service\" as const,\n incoming: {\n platform: meta.deliveryPlatform,\n externalThreadId: `${meta.deliveryTenantId || \"unknown\"}:${meta.deliveryDestination}:${meta.deliveryThreadRef || \"root\"}`,\n text: \"\",\n tenantId: meta.deliveryTenantId,\n integrationScopeId: meta.originScopeId,\n platformContext: {\n channelId: meta.deliveryDestination,\n threadTs: meta.deliveryThreadRef,\n teamId: meta.deliveryTenantId,\n },\n threadRef: meta.deliveryThreadRef,\n timestamp: now.getTime(),\n },\n },\n }\n : {}),\n },\n async () => {\n try {\n const jobContext: RecurringJobContext = {\n name: jobName,\n meta,\n body,\n resource,\n };\n const baseActions = deps.getActions(jobContext);\n const systemPrompt = await deps.getSystemPrompt(jobUserEmail);\n const initialToolNames = deps.getInitialToolNames?.(jobContext);\n // Only attach tool-search (and pay its schema cost) when the caller\n // actually supplied an initial subset to filter down to — otherwise\n // this is byte-for-byte the prior unfiltered behavior.\n const actions = initialToolNames\n ? attachToolSearch({ ...baseActions })\n : baseActions;\n const availableTools = actionsToEngineTools(actions);\n const tools = filterInitialEngineTools(\n availableTools,\n initialToolNames,\n );\n\n // Prefer the job runner's saved Anthropic key so recurring jobs\n // don't silently bill the shared platform key once a user has\n // brought their own. Falls back to the platform key when absent.\n const userApiKey = await getOwnerActiveApiKey(jobUserEmail);\n const engine =\n deps.engine ??\n (await resolveEngine({\n apiKey: userApiKey ?? deps.apiKey,\n appId: deps.appId,\n }));\n const modelCandidate =\n meta.model ??\n deps.model ??\n (await getStoredModelForEngine(engine, { appId: deps.appId })) ??\n engine.defaultModel;\n const model = normalizeModelForEngine(engine, modelCandidate);\n\n // Create a chat thread for this run\n const threadTitle = `Job: ${jobName} — ${now.toLocaleDateString()}`;\n const thread = await createThread(jobUserEmail, { title: threadTitle });\n\n const jobText = `[Recurring Job: ${jobName}]\\nSchedule: ${describeCron(meta.schedule)}\\n\\nExecute the following job instructions:\\n\\n${body}`;\n const messages = [\n {\n role: \"user\" as const,\n content: [{ type: \"text\" as const, text: jobText }],\n },\n ];\n\n // Route through startRun (from run-manager) instead of calling\n // runAgentLoop directly. This adds:\n // 1. A heartbeat row in agent_runs so a serverless kill is detected\n // by reapAllStaleRuns on the next startup and the row is flipped\n // to 'errored' — no more stranded lastStatus:\"running\" in the job\n // frontmatter after the next tick resets it via the stuck-guard.\n // 2. The soft-timeout infrastructure so the job checkpoints cleanly\n // before serverless hard-kill rather than dying mid-flight.\n // 3. SQL abort checks so a displaced/reaped run self-aborts instead\n // of completing invisibly and potentially overwriting newer state.\n const runId = `job-${jobName.replace(/[^a-zA-Z0-9._-]/g, \"-\")}-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;\n\n // Use the same soft-timeout logic as interactive runs. On hosted\n // runtimes this clamps to 40s (under the gateway wall); locally it\n // defaults to 0 (no framework timeout). The 5-minute hard-abort\n // below is still provided as a backstop via the startRun signal.\n const softTimeoutMs = resolveRunSoftTimeoutMs(undefined, {\n useHostedDefault: true,\n });\n\n let jobError: Error | null = null;\n // Hard-abort backstop: 5 minutes. On hosted runtimes the soft-timeout\n // will fire first; locally this is the only guard. Cleared when the\n // run completes so finished jobs don't leave a live timer keeping the\n // process/event loop alive for the remainder of the window.\n let hardAbortTimer: ReturnType<typeof setTimeout> | null = null;\n const jobUsageRef: {\n current: Awaited<ReturnType<typeof runAgentLoop>> | null;\n } = { current: null };\n let responseText = \"\";\n await new Promise<void>((resolve, reject) => {\n const activeRun = startRun(\n runId,\n thread.id,\n async (send, signal) => {\n try {\n jobUsageRef.current = await runAgentLoop({\n engine,\n model,\n systemPrompt,\n tools,\n availableTools,\n messages,\n actions,\n send,\n signal,\n threadId: thread.id,\n });\n } catch (err) {\n throw err;\n }\n },\n // onComplete: run finished (completed or aborted)\n async (run) => {\n if (hardAbortTimer) {\n clearTimeout(hardAbortTimer);\n hardAbortTimer = null;\n }\n if (run.status === \"completed\") {\n responseText = collectFinalResponseTextFromAgentEvents(\n (run.events ?? []).map((event) => event.event),\n );\n resolve();\n } else {\n reject(new Error(`Job run ended with status: ${run.status}`));\n }\n },\n {\n softTimeoutMs,\n // turnId defaults to runId — fine for single-turn jobs\n },\n );\n\n // Abort the run-manager's own controller after 5 minutes if the\n // run hasn't finished naturally.\n hardAbortTimer = setTimeout(\n () => {\n hardAbortTimer = null;\n if (activeRun.status === \"running\") {\n activeRun.abort.abort(\"job_hard_timeout\");\n reject(new Error(\"Job timed out after 5 minutes\"));\n }\n },\n 5 * 60 * 1000,\n );\n }).catch((err: any) => {\n jobError = err;\n });\n if (hardAbortTimer) {\n clearTimeout(hardAbortTimer);\n hardAbortTimer = null;\n }\n\n if (jobError) throw jobError;\n\n if (\n responseText.trim() &&\n meta.deliveryPlatform &&\n meta.deliveryDestination\n ) {\n const { getDefaultAdapter } =\n await import(\"../integrations/adapters/index.js\");\n const adapter = getDefaultAdapter(meta.deliveryPlatform);\n if (!adapter?.sendMessageToTarget) {\n throw new Error(\n `Recurring job delivery is not supported for ${meta.deliveryPlatform}`,\n );\n }\n await adapter.sendMessageToTarget(\n adapter.formatAgentResponse(responseText),\n {\n destination: meta.deliveryDestination,\n threadRef: meta.deliveryThreadRef ?? null,\n tenantId: meta.deliveryTenantId,\n },\n );\n }\n\n const jobUsage = jobUsageRef.current;\n if (\n jobUsage &&\n (jobUsage.inputTokens > 0 ||\n jobUsage.outputTokens > 0 ||\n jobUsage.cacheReadTokens > 0 ||\n jobUsage.cacheWriteTokens > 0)\n ) {\n try {\n const { recordUsage } = await import(\"../usage/store.js\");\n await recordUsage({\n ownerEmail: jobUserEmail,\n inputTokens: jobUsage.inputTokens,\n outputTokens: jobUsage.outputTokens,\n cacheReadTokens: jobUsage.cacheReadTokens,\n cacheWriteTokens: jobUsage.cacheWriteTokens,\n model: jobUsage.model,\n label: `recurring-job:${jobName}`,\n app: deps.appId,\n refId: runId,\n });\n } catch {\n // Usage attribution must not break the scheduled task.\n }\n }\n\n // Success — update status. Compute the next run from completion time,\n // not the job's start time `now`: a long run could otherwise schedule a\n // nextRun that's already in the past and re-fire immediately next tick.\n const next = nextOccurrence(meta.schedule, new Date());\n meta.lastStatus = \"success\";\n meta.nextRun = next.toISOString();\n await updateResource(resource, meta, body);\n\n console.log(\n `[recurring-jobs] Job \"${jobName}\" completed. Next run: ${meta.nextRun}`,\n );\n } catch (err: any) {\n // Error — update status. Use completion time (see success path).\n const next = nextOccurrence(meta.schedule, new Date());\n meta.lastStatus = \"error\";\n meta.lastError = err?.message?.slice(0, 200) || \"Unknown error\";\n meta.nextRun = next.toISOString();\n await updateResource(resource, meta, body);\n\n console.error(\n `[recurring-jobs] Job \"${jobName}\" failed:`,\n err?.message,\n );\n }\n },\n ); // end runWithRequestContext\n}\n\nasync function updateResource(\n resource: Resource,\n meta: JobFrontmatter,\n body: string,\n): Promise<void> {\n const content = buildJobContent(meta, body);\n await resourcePut(resource.owner, resource.path, content);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/jobs/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAiBhE,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,gBAAgB,CAAC;AAsCxB;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,CACxC,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAkBxB;AAkMD,wBAAgB,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAiF5D"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/jobs/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAiBhE,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,gBAAgB,CAAC;AAsCxB;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,CACxC,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAkBxB;AAuND,wBAAgB,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAyF5D"}
@@ -2,7 +2,7 @@ import { getDbExec } from "../db/client.js";
2
2
  import { resourcePut, resourceGetByPath, resourceList, resourceDelete, organizationIdFromResourceOwner, sharedResourceOwner, SHARED_OWNER, } from "../resources/store.js";
3
3
  import { getRequestUserEmail, getRequestOrgId, getIntegrationRequestContext, } from "../server/request-context.js";
4
4
  import { isValidCron, nextOccurrence, describeCron } from "./cron.js";
5
- import { parseJobFrontmatter, buildJobContent, } from "./scheduler.js";
5
+ import { parseJobFrontmatter, buildJobContent, normalizeJobMcpTools, } from "./scheduler.js";
6
6
  function getOwner() {
7
7
  const email = getRequestUserEmail();
8
8
  if (!email)
@@ -79,6 +79,13 @@ async function runCreate(args) {
79
79
  error: `Invalid cron expression: "${schedule}". Use 5 fields: minute hour day-of-month month day-of-week.`,
80
80
  });
81
81
  }
82
+ let mcpTools;
83
+ try {
84
+ mcpTools = normalizeJobMcpTools(args.mcpTools);
85
+ }
86
+ catch (err) {
87
+ return JSON.stringify({ error: err.message });
88
+ }
82
89
  const owner = scope === "personal" ? getOwner() : getSharedOwner();
83
90
  const path = `jobs/${name}.md`;
84
91
  const now = new Date();
@@ -107,6 +114,7 @@ async function runCreate(args) {
107
114
  ...(typeof model === "string" && model.trim()
108
115
  ? { model: model.trim() }
109
116
  : {}),
117
+ ...(mcpTools?.length ? { mcpTools } : {}),
110
118
  };
111
119
  const content = buildJobContent(meta, instructions);
112
120
  await resourcePut(owner, path, content);
@@ -118,6 +126,7 @@ async function runCreate(args) {
118
126
  scheduleDescription: describeCron(schedule),
119
127
  nextRun: next.toISOString(),
120
128
  scope: scope || "shared",
129
+ ...(mcpTools?.length ? { mcpTools } : {}),
121
130
  });
122
131
  }
123
132
  async function runList(args) {
@@ -152,6 +161,7 @@ async function runList(args) {
152
161
  deliveryPlatform: meta.deliveryPlatform || null,
153
162
  deliveryDestination: meta.deliveryDestination || null,
154
163
  model: meta.model || null,
164
+ mcpTools: meta.mcpTools || [],
155
165
  };
156
166
  }));
157
167
  if (jobs.length === 0) {
@@ -200,6 +210,18 @@ async function runUpdate(args) {
200
210
  }
201
211
  if (typeof model === "string" && model.trim())
202
212
  meta.model = model.trim();
213
+ if (args.mcpTools !== undefined) {
214
+ try {
215
+ const mcpTools = normalizeJobMcpTools(args.mcpTools) ?? [];
216
+ if (mcpTools.length)
217
+ meta.mcpTools = mcpTools;
218
+ else
219
+ delete meta.mcpTools;
220
+ }
221
+ catch (err) {
222
+ return JSON.stringify({ error: err.message });
223
+ }
224
+ }
203
225
  const newBody = instructions || body;
204
226
  const content = buildJobContent(meta, newBody);
205
227
  await resourcePut(resource.owner, resource.path, content);
@@ -210,6 +232,7 @@ async function runUpdate(args) {
210
232
  scheduleDescription: describeCron(meta.schedule),
211
233
  enabled: meta.enabled,
212
234
  nextRun: meta.nextRun,
235
+ mcpTools: meta.mcpTools || [],
213
236
  });
214
237
  }
215
238
  async function runDelete(args) {
@@ -245,7 +268,9 @@ Actions:
245
268
  - "update": Update a job's schedule, instructions, or enabled state. Requires name.
246
269
  - "delete": Delete a recurring job. Requires name. Always confirm with the user first.
247
270
 
248
- Cron format is 5 fields: minute hour day-of-month month day-of-week. Common patterns: '0 9 * * *' (daily 9am), '0 9 * * 1-5' (weekdays 9am), '0 * * * *' (every hour), '0 9 * * 1' (Mondays 9am), '*/30 * * * *' (every 30 min).`,
271
+ Cron format is 5 fields: minute hour day-of-month month day-of-week. Common patterns: '0 9 * * *' (daily 9am), '0 9 * * 1-5' (weekdays 9am), '0 * * * *' (every hour), '0 9 * * 1' (Mondays 9am), '*/30 * * * *' (every 30 min).
272
+
273
+ For jobs that use a connected MCP, pass the exact tool names in mcpTools. This binds only those tools to the background run; OAuth credentials remain in the connector and are resolved for the job's user/org context.`,
249
274
  parameters: {
250
275
  type: "object",
251
276
  properties: {
@@ -285,6 +310,11 @@ Cron format is 5 fields: minute hour day-of-month month day-of-week. Common patt
285
310
  type: "string",
286
311
  description: "Optional model id for this routine. The channel/app/engine default is used when omitted.",
287
312
  },
313
+ mcpTools: {
314
+ type: "array",
315
+ items: { type: "string" },
316
+ description: 'Optional explicit MCP capabilities for this job. Use the connected tool names exactly as advertised, for example ["mcp__meeting-notes__list_meetings", "mcp__meeting-notes__get_transcript"]. The job runs only with these tools; credentials remain in the connector.',
317
+ },
288
318
  },
289
319
  required: ["action"],
290
320
  },