@agent-native/core 0.99.3 → 0.100.1

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 (382) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +21 -0
  3. package/corpus/core/docs/content/agent-surfaces.mdx +43 -0
  4. package/corpus/core/docs/content/external-agents.mdx +11 -0
  5. package/corpus/core/docs/content/locales/ar-SA/agent-surfaces.mdx +30 -0
  6. package/corpus/core/docs/content/locales/ar-SA/external-agents.mdx +9 -0
  7. package/corpus/core/docs/content/locales/de-DE/agent-surfaces.mdx +34 -0
  8. package/corpus/core/docs/content/locales/de-DE/external-agents.mdx +10 -0
  9. package/corpus/core/docs/content/locales/es-ES/agent-surfaces.mdx +34 -0
  10. package/corpus/core/docs/content/locales/es-ES/external-agents.mdx +10 -0
  11. package/corpus/core/docs/content/locales/fr-FR/agent-surfaces.mdx +34 -0
  12. package/corpus/core/docs/content/locales/fr-FR/external-agents.mdx +11 -0
  13. package/corpus/core/docs/content/locales/hi-IN/agent-surfaces.mdx +31 -0
  14. package/corpus/core/docs/content/locales/hi-IN/external-agents.mdx +9 -0
  15. package/corpus/core/docs/content/locales/ja-JP/agent-surfaces.mdx +32 -0
  16. package/corpus/core/docs/content/locales/ja-JP/external-agents.mdx +10 -0
  17. package/corpus/core/docs/content/locales/ko-KR/agent-surfaces.mdx +32 -0
  18. package/corpus/core/docs/content/locales/ko-KR/external-agents.mdx +9 -0
  19. package/corpus/core/docs/content/locales/pt-BR/agent-surfaces.mdx +33 -0
  20. package/corpus/core/docs/content/locales/pt-BR/external-agents.mdx +10 -0
  21. package/corpus/core/docs/content/locales/zh-CN/agent-surfaces.mdx +29 -0
  22. package/corpus/core/docs/content/locales/zh-CN/external-agents.mdx +8 -0
  23. package/corpus/core/docs/content/locales/zh-TW/agent-surfaces.mdx +29 -0
  24. package/corpus/core/docs/content/locales/zh-TW/external-agents.mdx +8 -0
  25. package/corpus/core/package.json +1 -1
  26. package/corpus/core/src/agent/context-xray/actions/context-evict.ts +11 -0
  27. package/corpus/core/src/agent/context-xray/actions/context-pin.ts +11 -0
  28. package/corpus/core/src/agent/context-xray/actions/context-preview-get.ts +134 -0
  29. package/corpus/core/src/agent/context-xray/actions/context-restore.ts +11 -0
  30. package/corpus/core/src/agent/context-xray/actions/errors.ts +20 -0
  31. package/corpus/core/src/agent/context-xray/manifest.ts +106 -7
  32. package/corpus/core/src/agent/engine/context-directives-transform.ts +5 -1
  33. package/corpus/core/src/agent/production-agent.ts +100 -38
  34. package/corpus/core/src/agent/run-loop-with-resume.ts +7 -2
  35. package/corpus/core/src/client/AgentPanel.tsx +35 -8
  36. package/corpus/core/src/client/agent-page/AgentContextTab.tsx +501 -0
  37. package/corpus/core/src/client/agent-page/AgentJobsTab.tsx +370 -0
  38. package/corpus/core/src/client/agent-page/AgentTabsPage.tsx +1084 -0
  39. package/corpus/core/src/client/agent-page/types.ts +18 -0
  40. package/corpus/core/src/client/agent-page/use-jobs.ts +150 -0
  41. package/corpus/core/src/client/context-xray/ContextMeter.tsx +22 -5
  42. package/corpus/core/src/client/context-xray/ContextTreemap.tsx +16 -1
  43. package/corpus/core/src/client/context-xray/ContextXRayPanel.tsx +168 -3
  44. package/corpus/core/src/client/context-xray/format.ts +6 -0
  45. package/corpus/core/src/client/index.ts +6 -0
  46. package/corpus/core/src/client/resources/ResourcesPanel.tsx +51 -23
  47. package/corpus/core/src/client/settings/AutomationsSection.tsx +407 -387
  48. package/corpus/core/src/jobs/actions/list-recurring-jobs.ts +105 -0
  49. package/corpus/core/src/jobs/actions/manage-recurring-job.ts +85 -0
  50. package/corpus/core/src/jobs/tools.ts +1 -1
  51. package/corpus/core/src/localization/default-messages.ts +110 -0
  52. package/corpus/core/src/mcp/build-server.ts +1 -0
  53. package/corpus/core/src/mcp/connect-route.ts +62 -65
  54. package/corpus/core/src/server/action-discovery.ts +23 -0
  55. package/corpus/core/src/server/agent-chat/prompt-resources.ts +174 -2
  56. package/corpus/core/src/server/agent-chat-plugin.ts +175 -2
  57. package/corpus/core/src/server/auth.ts +1 -7
  58. package/corpus/core/src/server/google-oauth.ts +1 -7
  59. package/corpus/core/src/server/workspace-oauth.ts +31 -0
  60. package/corpus/core/src/shared/context-xray.ts +84 -1
  61. package/corpus/core/src/shared/mcp-connect-content.ts +130 -0
  62. package/corpus/core/src/templates/default/app/routes/_index.tsx +11 -0
  63. package/corpus/core/src/templates/default/app/routes/agent.tsx +33 -0
  64. package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  65. package/corpus/core/src/templates/workspace-core/.agents/skills/agent-page/SKILL.md +59 -0
  66. package/corpus/core/src/templates/workspace-core/.agents/skills/context-xray/SKILL.md +25 -0
  67. package/corpus/core/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +7 -0
  68. package/corpus/core/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +9 -0
  69. package/corpus/core/src/triggers/actions/list-automations.ts +99 -0
  70. package/corpus/core/src/triggers/actions/manage-automation.ts +78 -0
  71. package/corpus/templates/analytics/actions/data-source-status.ts +33 -15
  72. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +1 -1
  73. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +149 -24
  74. package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +17 -0
  75. package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -0
  76. package/corpus/templates/analytics/app/components/layout/Layout.tsx +1 -0
  77. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +8 -0
  78. package/corpus/templates/analytics/app/i18n/zh-TW.ts +1 -0
  79. package/corpus/templates/analytics/app/i18n-data.ts +1 -0
  80. package/corpus/templates/analytics/app/routes/agent.tsx +5 -0
  81. package/corpus/templates/analytics/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +6 -0
  82. package/corpus/templates/analytics/changelog/2026-07-13-analytics-answers-can-use-built-in-first-party-event-data.md +6 -0
  83. package/corpus/templates/analytics/changelog/2026-07-13-chart-legends-can-filter-to-one-series-or-hide-a-series-on-h.md +6 -0
  84. package/corpus/templates/analytics/changelog/2026-07-13-gpt-5-6-luna-answers-now-recover-normally-instead-of-showing.md +6 -0
  85. package/corpus/templates/analytics/server/plugins/agent-chat.ts +11 -2
  86. package/corpus/templates/assets/app/components/layout/Header.tsx +1 -0
  87. package/corpus/templates/assets/app/components/layout/Layout.tsx +1 -0
  88. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +2 -0
  89. package/corpus/templates/assets/app/routes/agent.tsx +5 -0
  90. package/corpus/templates/assets/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +6 -0
  91. package/corpus/templates/brain/app/components/layout/Layout.tsx +1 -0
  92. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +4 -1
  93. package/corpus/templates/brain/app/lib/brain.ts +11 -0
  94. package/corpus/templates/brain/app/root.tsx +15 -1
  95. package/corpus/templates/brain/app/routes/agent.tsx +11 -0
  96. package/corpus/templates/brain/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +6 -0
  97. package/corpus/templates/calendar/AGENTS.md +9 -0
  98. package/corpus/templates/calendar/actions/list-events.ts +659 -44
  99. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +1 -0
  100. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +2 -0
  101. package/corpus/templates/calendar/app/root.tsx +17 -1
  102. package/corpus/templates/calendar/app/routes/_app.agent.tsx +25 -0
  103. package/corpus/templates/calendar/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +6 -0
  104. package/corpus/templates/calendar/changelog/2026-07-13-calendar-inventory-reads-report-source-coverage.md +6 -0
  105. package/corpus/templates/calendar/server/lib/calendar-connector-catalog.ts +8 -0
  106. package/corpus/templates/calendar/server/lib/google-calendar.ts +173 -51
  107. package/corpus/templates/calendar/server/lib/ical-fetcher.ts +13 -2
  108. package/corpus/templates/calendar/server/plugins/agent-chat.ts +5 -3
  109. package/corpus/templates/calendar/shared/api.ts +2 -0
  110. package/corpus/templates/chat/app/components/layout/Header.tsx +1 -0
  111. package/corpus/templates/chat/app/components/layout/Layout.tsx +1 -0
  112. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +7 -0
  113. package/corpus/templates/chat/app/hooks/use-navigation-state.ts +3 -0
  114. package/corpus/templates/chat/app/root.tsx +24 -2
  115. package/corpus/templates/chat/app/routes/agent.tsx +15 -0
  116. package/corpus/templates/chat/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +6 -0
  117. package/corpus/templates/clips/app/components/library/library-layout.tsx +8 -0
  118. package/corpus/templates/clips/app/i18n/ar-SA.ts +2 -0
  119. package/corpus/templates/clips/app/i18n/de-DE.ts +2 -0
  120. package/corpus/templates/clips/app/i18n/en-US.ts +2 -0
  121. package/corpus/templates/clips/app/i18n/es-ES.ts +2 -0
  122. package/corpus/templates/clips/app/i18n/fr-FR.ts +2 -0
  123. package/corpus/templates/clips/app/i18n/hi-IN.ts +2 -0
  124. package/corpus/templates/clips/app/i18n/ja-JP.ts +2 -0
  125. package/corpus/templates/clips/app/i18n/ko-KR.ts +2 -0
  126. package/corpus/templates/clips/app/i18n/pt-BR.ts +2 -0
  127. package/corpus/templates/clips/app/i18n/zh-CN.ts +2 -0
  128. package/corpus/templates/clips/app/i18n/zh-TW.ts +2 -0
  129. package/corpus/templates/clips/app/root.tsx +7 -1
  130. package/corpus/templates/clips/app/routes/_app.agent.tsx +15 -0
  131. package/corpus/templates/clips/changelog/2026-07-13-new-agent-page-see-and-manage-your-agent-s-context-files-con.md +6 -0
  132. package/corpus/templates/content/app/components/layout/Layout.tsx +1 -0
  133. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +36 -0
  134. package/corpus/templates/content/app/i18n/zh-TW.ts +2 -0
  135. package/corpus/templates/content/app/i18n-data.ts +44 -6
  136. package/corpus/templates/content/app/root.tsx +8 -0
  137. package/corpus/templates/content/app/routes/_app.agent.tsx +15 -0
  138. package/corpus/templates/content/changelog/2026-07-13-new-agent-page-see-and-manage-your-agent-s-context-files-con.md +6 -0
  139. package/corpus/templates/design/app/components/layout/Layout.tsx +1 -0
  140. package/corpus/templates/design/app/components/layout/Sidebar.tsx +2 -0
  141. package/corpus/templates/design/app/i18n/zh-TW.ts +2 -0
  142. package/corpus/templates/design/app/i18n-data.ts +20 -0
  143. package/corpus/templates/design/app/root.tsx +7 -1
  144. package/corpus/templates/design/app/routes/agent.tsx +15 -0
  145. package/corpus/templates/design/changelog/2026-07-13-new-agent-page-see-and-manage-your-agent-s-context-files-con.md +6 -0
  146. package/corpus/templates/dispatch/app/dispatch-extensions.tsx +10 -1
  147. package/corpus/templates/dispatch/app/i18n/zh-TW.ts +2 -0
  148. package/corpus/templates/dispatch/app/i18n-data.ts +20 -0
  149. package/corpus/templates/dispatch/app/root.tsx +7 -2
  150. package/corpus/templates/dispatch/app/routes/agent.tsx +18 -0
  151. package/corpus/templates/dispatch/changelog/2026-07-13-new-agent-page-see-and-manage-your-agent-s-context-files-con.md +6 -0
  152. package/corpus/templates/forms/app/components/layout/Layout.tsx +1 -0
  153. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +35 -0
  154. package/corpus/templates/forms/app/i18n/ar-SA.ts +2 -0
  155. package/corpus/templates/forms/app/i18n/de-DE.ts +2 -0
  156. package/corpus/templates/forms/app/i18n/en-US.ts +2 -0
  157. package/corpus/templates/forms/app/i18n/es-ES.ts +2 -0
  158. package/corpus/templates/forms/app/i18n/fr-FR.ts +2 -0
  159. package/corpus/templates/forms/app/i18n/hi-IN.ts +2 -0
  160. package/corpus/templates/forms/app/i18n/ja-JP.ts +2 -0
  161. package/corpus/templates/forms/app/i18n/ko-KR.ts +2 -0
  162. package/corpus/templates/forms/app/i18n/pt-BR.ts +2 -0
  163. package/corpus/templates/forms/app/i18n/zh-CN.ts +2 -0
  164. package/corpus/templates/forms/app/i18n/zh-TW.ts +2 -0
  165. package/corpus/templates/forms/app/root.tsx +6 -1
  166. package/corpus/templates/forms/app/routes/_app.agent.tsx +15 -0
  167. package/corpus/templates/forms/changelog/2026-07-13-new-agent-page-see-and-manage-your-agent-s-context-files-con.md +6 -0
  168. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +14 -2
  169. package/corpus/templates/macros/app/components/layout/Header.tsx +1 -0
  170. package/corpus/templates/macros/app/root.tsx +17 -2
  171. package/corpus/templates/macros/app/routes/agent.tsx +15 -0
  172. package/corpus/templates/macros/changelog/2026-07-13-new-agent-page-see-and-manage-your-agent-s-context-files-con.md +6 -0
  173. package/corpus/templates/mail/AGENTS.md +12 -0
  174. package/corpus/templates/mail/actions/list-emails.ts +486 -4
  175. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +42 -0
  176. package/corpus/templates/mail/app/components/layout/CommandPalette.tsx +6 -0
  177. package/corpus/templates/mail/app/routes/agent.tsx +15 -0
  178. package/corpus/templates/mail/changelog/2026-07-13-coverage-aware-connected-inbox-inventory.md +6 -0
  179. package/corpus/templates/mail/changelog/2026-07-13-new-agent-page-see-and-manage-your-agent-s-context-files-con.md +6 -0
  180. package/corpus/templates/mail/server/db/schema.ts +17 -0
  181. package/corpus/templates/mail/server/lib/google-auth.ts +33 -5
  182. package/corpus/templates/mail/server/lib/inventory-cursor.ts +406 -0
  183. package/corpus/templates/mail/server/lib/list-inbox-emails.ts +21 -2
  184. package/corpus/templates/mail/server/lib/mail-connector-catalog.ts +8 -0
  185. package/corpus/templates/mail/server/plugins/agent-chat.ts +4 -9
  186. package/corpus/templates/mail/server/plugins/db.ts +20 -0
  187. package/corpus/templates/plan/app/components/layout/Header.tsx +1 -0
  188. package/corpus/templates/plan/app/components/layout/Layout.tsx +1 -0
  189. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +2 -0
  190. package/corpus/templates/plan/app/root.tsx +8 -0
  191. package/corpus/templates/plan/app/routes/agent.tsx +15 -0
  192. package/corpus/templates/plan/changelog/2026-07-13-new-agent-page-see-and-manage-your-agent-s-context-files-con.md +6 -0
  193. package/corpus/templates/slides/app/components/layout/Header.tsx +1 -0
  194. package/corpus/templates/slides/app/components/layout/Layout.tsx +1 -0
  195. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +2 -0
  196. package/corpus/templates/slides/app/root.tsx +10 -1
  197. package/corpus/templates/slides/app/routes/agent.tsx +15 -0
  198. package/corpus/templates/slides/changelog/2026-07-13-new-agent-page-see-and-manage-your-agent-s-context-files-con.md +6 -0
  199. package/dist/agent/context-xray/actions/context-evict.js +5 -2
  200. package/dist/agent/context-xray/actions/context-evict.js.map +1 -1
  201. package/dist/agent/context-xray/actions/context-pin.js +5 -2
  202. package/dist/agent/context-xray/actions/context-pin.js.map +1 -1
  203. package/dist/agent/context-xray/actions/context-preview-get.d.ts +17 -0
  204. package/dist/agent/context-xray/actions/context-preview-get.d.ts.map +1 -0
  205. package/dist/agent/context-xray/actions/context-preview-get.js +94 -0
  206. package/dist/agent/context-xray/actions/context-preview-get.js.map +1 -0
  207. package/dist/agent/context-xray/actions/context-restore.js +5 -2
  208. package/dist/agent/context-xray/actions/context-restore.js.map +1 -1
  209. package/dist/agent/context-xray/actions/errors.d.ts +3 -0
  210. package/dist/agent/context-xray/actions/errors.d.ts.map +1 -1
  211. package/dist/agent/context-xray/actions/errors.js +6 -0
  212. package/dist/agent/context-xray/actions/errors.js.map +1 -1
  213. package/dist/agent/context-xray/manifest.d.ts +18 -1
  214. package/dist/agent/context-xray/manifest.d.ts.map +1 -1
  215. package/dist/agent/context-xray/manifest.js +68 -6
  216. package/dist/agent/context-xray/manifest.js.map +1 -1
  217. package/dist/agent/engine/context-directives-transform.d.ts +2 -0
  218. package/dist/agent/engine/context-directives-transform.d.ts.map +1 -1
  219. package/dist/agent/engine/context-directives-transform.js +2 -1
  220. package/dist/agent/engine/context-directives-transform.js.map +1 -1
  221. package/dist/agent/production-agent.d.ts +15 -0
  222. package/dist/agent/production-agent.d.ts.map +1 -1
  223. package/dist/agent/production-agent.js +74 -36
  224. package/dist/agent/production-agent.js.map +1 -1
  225. package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
  226. package/dist/agent/run-loop-with-resume.js +6 -3
  227. package/dist/agent/run-loop-with-resume.js.map +1 -1
  228. package/dist/client/AgentPanel.d.ts +5 -1
  229. package/dist/client/AgentPanel.d.ts.map +1 -1
  230. package/dist/client/AgentPanel.js +9 -11
  231. package/dist/client/AgentPanel.js.map +1 -1
  232. package/dist/client/agent-page/AgentContextTab.d.ts +5 -0
  233. package/dist/client/agent-page/AgentContextTab.d.ts.map +1 -0
  234. package/dist/client/agent-page/AgentContextTab.js +202 -0
  235. package/dist/client/agent-page/AgentContextTab.js.map +1 -0
  236. package/dist/client/agent-page/AgentJobsTab.d.ts +3 -0
  237. package/dist/client/agent-page/AgentJobsTab.d.ts.map +1 -0
  238. package/dist/client/agent-page/AgentJobsTab.js +98 -0
  239. package/dist/client/agent-page/AgentJobsTab.js.map +1 -0
  240. package/dist/client/agent-page/AgentTabsPage.d.ts +20 -0
  241. package/dist/client/agent-page/AgentTabsPage.d.ts.map +1 -0
  242. package/dist/client/agent-page/AgentTabsPage.js +420 -0
  243. package/dist/client/agent-page/AgentTabsPage.js.map +1 -0
  244. package/dist/client/agent-page/types.d.ts +17 -0
  245. package/dist/client/agent-page/types.d.ts.map +1 -0
  246. package/dist/client/agent-page/types.js +9 -0
  247. package/dist/client/agent-page/types.js.map +1 -0
  248. package/dist/client/agent-page/use-jobs.d.ts +61 -0
  249. package/dist/client/agent-page/use-jobs.d.ts.map +1 -0
  250. package/dist/client/agent-page/use-jobs.js +71 -0
  251. package/dist/client/agent-page/use-jobs.js.map +1 -0
  252. package/dist/client/context-xray/ContextMeter.d.ts +3 -1
  253. package/dist/client/context-xray/ContextMeter.d.ts.map +1 -1
  254. package/dist/client/context-xray/ContextMeter.js +14 -5
  255. package/dist/client/context-xray/ContextMeter.js.map +1 -1
  256. package/dist/client/context-xray/ContextTreemap.d.ts +3 -2
  257. package/dist/client/context-xray/ContextTreemap.d.ts.map +1 -1
  258. package/dist/client/context-xray/ContextTreemap.js +9 -1
  259. package/dist/client/context-xray/ContextTreemap.js.map +1 -1
  260. package/dist/client/context-xray/ContextXRayPanel.d.ts.map +1 -1
  261. package/dist/client/context-xray/ContextXRayPanel.js +95 -20
  262. package/dist/client/context-xray/ContextXRayPanel.js.map +1 -1
  263. package/dist/client/context-xray/format.d.ts.map +1 -1
  264. package/dist/client/context-xray/format.js +12 -0
  265. package/dist/client/context-xray/format.js.map +1 -1
  266. package/dist/client/index.d.ts +3 -0
  267. package/dist/client/index.d.ts.map +1 -1
  268. package/dist/client/index.js +1 -0
  269. package/dist/client/index.js.map +1 -1
  270. package/dist/client/resources/ResourcesPanel.d.ts +9 -1
  271. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  272. package/dist/client/resources/ResourcesPanel.js +26 -10
  273. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  274. package/dist/client/settings/AutomationsSection.d.ts +9 -0
  275. package/dist/client/settings/AutomationsSection.d.ts.map +1 -1
  276. package/dist/client/settings/AutomationsSection.js +128 -147
  277. package/dist/client/settings/AutomationsSection.js.map +1 -1
  278. package/dist/collab/routes.d.ts +1 -1
  279. package/dist/collab/struct-routes.d.ts +1 -1
  280. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  281. package/dist/jobs/actions/list-recurring-jobs.d.ts +21 -0
  282. package/dist/jobs/actions/list-recurring-jobs.d.ts.map +1 -0
  283. package/dist/jobs/actions/list-recurring-jobs.js +74 -0
  284. package/dist/jobs/actions/list-recurring-jobs.js.map +1 -0
  285. package/dist/jobs/actions/manage-recurring-job.d.ts +18 -0
  286. package/dist/jobs/actions/manage-recurring-job.d.ts.map +1 -0
  287. package/dist/jobs/actions/manage-recurring-job.js +68 -0
  288. package/dist/jobs/actions/manage-recurring-job.js.map +1 -0
  289. package/dist/jobs/tools.d.ts +13 -0
  290. package/dist/jobs/tools.d.ts.map +1 -1
  291. package/dist/jobs/tools.js +1 -1
  292. package/dist/jobs/tools.js.map +1 -1
  293. package/dist/localization/default-messages.d.ts +96 -0
  294. package/dist/localization/default-messages.d.ts.map +1 -1
  295. package/dist/localization/default-messages.js +96 -0
  296. package/dist/localization/default-messages.js.map +1 -1
  297. package/dist/mcp/build-server.d.ts.map +1 -1
  298. package/dist/mcp/build-server.js +1 -0
  299. package/dist/mcp/build-server.js.map +1 -1
  300. package/dist/mcp/connect-route.d.ts.map +1 -1
  301. package/dist/mcp/connect-route.js +44 -59
  302. package/dist/mcp/connect-route.js.map +1 -1
  303. package/dist/notifications/routes.d.ts +1 -1
  304. package/dist/observability/routes.d.ts +5 -5
  305. package/dist/progress/routes.d.ts +1 -1
  306. package/dist/resources/handlers.d.ts +3 -3
  307. package/dist/secrets/routes.d.ts +9 -9
  308. package/dist/server/action-discovery.d.ts.map +1 -1
  309. package/dist/server/action-discovery.js +23 -0
  310. package/dist/server/action-discovery.js.map +1 -1
  311. package/dist/server/agent-chat/prompt-resources.d.ts +14 -0
  312. package/dist/server/agent-chat/prompt-resources.d.ts.map +1 -1
  313. package/dist/server/agent-chat/prompt-resources.js +139 -2
  314. package/dist/server/agent-chat/prompt-resources.js.map +1 -1
  315. package/dist/server/agent-chat-plugin.d.ts +1 -0
  316. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  317. package/dist/server/agent-chat-plugin.js +136 -3
  318. package/dist/server/agent-chat-plugin.js.map +1 -1
  319. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  320. package/dist/server/auth.d.ts.map +1 -1
  321. package/dist/server/auth.js +1 -4
  322. package/dist/server/auth.js.map +1 -1
  323. package/dist/server/google-oauth.d.ts.map +1 -1
  324. package/dist/server/google-oauth.js +1 -4
  325. package/dist/server/google-oauth.js.map +1 -1
  326. package/dist/server/workspace-oauth.d.ts +11 -0
  327. package/dist/server/workspace-oauth.d.ts.map +1 -0
  328. package/dist/server/workspace-oauth.js +25 -0
  329. package/dist/server/workspace-oauth.js.map +1 -0
  330. package/dist/shared/context-xray.d.ts +45 -1
  331. package/dist/shared/context-xray.d.ts.map +1 -1
  332. package/dist/shared/context-xray.js +12 -0
  333. package/dist/shared/context-xray.js.map +1 -1
  334. package/dist/shared/mcp-connect-content.d.ts +37 -0
  335. package/dist/shared/mcp-connect-content.d.ts.map +1 -0
  336. package/dist/shared/mcp-connect-content.js +92 -0
  337. package/dist/shared/mcp-connect-content.js.map +1 -0
  338. package/dist/templates/default/app/routes/_index.tsx +11 -0
  339. package/dist/templates/default/app/routes/agent.tsx +33 -0
  340. package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  341. package/dist/templates/workspace-core/.agents/skills/agent-page/SKILL.md +59 -0
  342. package/dist/templates/workspace-core/.agents/skills/context-xray/SKILL.md +25 -0
  343. package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +7 -0
  344. package/dist/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +9 -0
  345. package/dist/triggers/actions/list-automations.d.ts +24 -0
  346. package/dist/triggers/actions/list-automations.d.ts.map +1 -0
  347. package/dist/triggers/actions/list-automations.js +72 -0
  348. package/dist/triggers/actions/list-automations.js.map +1 -0
  349. package/dist/triggers/actions/manage-automation.d.ts +18 -0
  350. package/dist/triggers/actions/manage-automation.d.ts.map +1 -0
  351. package/dist/triggers/actions/manage-automation.js +60 -0
  352. package/dist/triggers/actions/manage-automation.js.map +1 -0
  353. package/docs/content/agent-surfaces.mdx +43 -0
  354. package/docs/content/external-agents.mdx +11 -0
  355. package/docs/content/locales/ar-SA/agent-surfaces.mdx +30 -0
  356. package/docs/content/locales/ar-SA/external-agents.mdx +9 -0
  357. package/docs/content/locales/de-DE/agent-surfaces.mdx +34 -0
  358. package/docs/content/locales/de-DE/external-agents.mdx +10 -0
  359. package/docs/content/locales/es-ES/agent-surfaces.mdx +34 -0
  360. package/docs/content/locales/es-ES/external-agents.mdx +10 -0
  361. package/docs/content/locales/fr-FR/agent-surfaces.mdx +34 -0
  362. package/docs/content/locales/fr-FR/external-agents.mdx +11 -0
  363. package/docs/content/locales/hi-IN/agent-surfaces.mdx +31 -0
  364. package/docs/content/locales/hi-IN/external-agents.mdx +9 -0
  365. package/docs/content/locales/ja-JP/agent-surfaces.mdx +32 -0
  366. package/docs/content/locales/ja-JP/external-agents.mdx +10 -0
  367. package/docs/content/locales/ko-KR/agent-surfaces.mdx +32 -0
  368. package/docs/content/locales/ko-KR/external-agents.mdx +9 -0
  369. package/docs/content/locales/pt-BR/agent-surfaces.mdx +33 -0
  370. package/docs/content/locales/pt-BR/external-agents.mdx +10 -0
  371. package/docs/content/locales/zh-CN/agent-surfaces.mdx +29 -0
  372. package/docs/content/locales/zh-CN/external-agents.mdx +8 -0
  373. package/docs/content/locales/zh-TW/agent-surfaces.mdx +29 -0
  374. package/docs/content/locales/zh-TW/external-agents.mdx +8 -0
  375. package/package.json +1 -1
  376. package/src/templates/default/app/routes/_index.tsx +11 -0
  377. package/src/templates/default/app/routes/agent.tsx +33 -0
  378. package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  379. package/src/templates/workspace-core/.agents/skills/agent-page/SKILL.md +59 -0
  380. package/src/templates/workspace-core/.agents/skills/context-xray/SKILL.md +25 -0
  381. package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +7 -0
  382. package/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +9 -0
@@ -1,219 +1,381 @@
1
+ import { Button } from "@agent-native/toolkit/ui/button";
1
2
  import {
2
3
  IconBolt,
3
4
  IconClock,
5
+ IconEye,
4
6
  IconLoader2,
7
+ IconPlayerPause,
5
8
  IconPlayerPlay,
6
9
  IconPlus,
7
10
  IconTrash,
8
11
  } from "@tabler/icons-react";
9
- import { useEffect, useState, useCallback } from "react";
12
+ import { useCallback, useState } from "react";
10
13
 
11
14
  import { sendToAgentChat } from "../agent-chat.js";
15
+ import {
16
+ useAutomations,
17
+ useManageAutomation,
18
+ type Automation,
19
+ type JobsScope,
20
+ } from "../agent-page/use-jobs.js";
12
21
  import { agentNativePath } from "../api-path.js";
22
+ import {
23
+ Dialog,
24
+ DialogContent,
25
+ DialogDescription,
26
+ DialogFooter,
27
+ DialogHeader,
28
+ DialogTitle,
29
+ } from "../components/ui/dialog.js";
13
30
  import {
14
31
  Popover,
15
32
  PopoverContent,
16
33
  PopoverTrigger,
17
34
  } from "../components/ui/popover.js";
18
- import {
19
- Tooltip,
20
- TooltipContent,
21
- TooltipTrigger,
22
- } from "../components/ui/tooltip.js";
23
35
  import { PromptComposer } from "../composer/PromptComposer.js";
36
+ import { useFormatters, useT } from "../i18n.js";
24
37
 
25
- interface TreeNode {
26
- name: string;
27
- path: string;
28
- type: "file" | "folder";
29
- kind?: string;
30
- children?: TreeNode[];
31
- resource?: {
32
- id: string;
33
- path: string;
34
- owner: string;
35
- mimeType: string;
36
- size: number;
37
- createdAt: number;
38
- updatedAt: number;
39
- };
40
- jobMeta?: {
41
- schedule?: string;
42
- scheduleDescription?: string;
43
- enabled?: boolean;
44
- lastStatus?: string;
45
- lastRun?: string;
46
- nextRun?: string;
47
- };
38
+ export interface AutomationsListProps {
39
+ scope?: JobsScope;
40
+ compact?: boolean;
41
+ emptyMessage?: string;
48
42
  }
49
43
 
50
- interface AutomationItem {
51
- id: string;
52
- name: string;
53
- path: string;
54
- schedule?: string;
55
- scheduleDescription?: string;
56
- enabled: boolean;
57
- lastStatus?: string;
58
- lastRun?: string;
59
- nextRun?: string;
44
+ export const AUTOMATION_CREATION_SCOPE = "personal" as const;
45
+
46
+ export function automationCreationContext(): string {
47
+ return `The user wants to create a new ${AUTOMATION_CREATION_SCOPE} automation. Use manage-automations with action=define to create it. Ask clarifying questions if needed about what event to trigger on, conditions, and what actions to take.`;
60
48
  }
61
49
 
62
- function flattenJobs(nodes: TreeNode[]): AutomationItem[] {
63
- const items: AutomationItem[] = [];
64
- for (const node of nodes) {
65
- if (node.type === "folder" && node.children) {
66
- items.push(...flattenJobs(node.children));
67
- }
68
- if (
69
- node.type === "file" &&
70
- node.kind === "job" &&
71
- node.resource &&
72
- node.jobMeta
73
- ) {
74
- const name = node.name.replace(/\.md$/, "").replace(/-/g, " ");
75
- items.push({
76
- id: node.resource.id,
77
- name,
78
- path: node.resource.path,
79
- schedule: node.jobMeta.schedule,
80
- scheduleDescription: node.jobMeta.scheduleDescription,
81
- enabled: node.jobMeta.enabled ?? false,
82
- lastStatus: node.jobMeta.lastStatus,
83
- lastRun: node.jobMeta.lastRun,
84
- nextRun: node.jobMeta.nextRun,
85
- });
86
- }
50
+ export function AutomationsList({
51
+ scope = "user",
52
+ compact = false,
53
+ emptyMessage,
54
+ }: AutomationsListProps) {
55
+ const t = useT();
56
+ const { formatDate } = useFormatters();
57
+ const query = useAutomations(scope);
58
+ const mutation = useManageAutomation(scope);
59
+ const [deleteTarget, setDeleteTarget] = useState<Automation | null>(null);
60
+ const [detailsTarget, setDetailsTarget] = useState<Automation | null>(null);
61
+
62
+ const formatDateTime = (value: string | null) => {
63
+ if (!value || Number.isNaN(new Date(value).getTime())) return null;
64
+ return formatDate(value, {
65
+ month: "short",
66
+ day: "numeric",
67
+ hour: "numeric",
68
+ minute: "2-digit",
69
+ });
70
+ };
71
+
72
+ if (query.isLoading) {
73
+ return (
74
+ <div
75
+ className="flex items-center gap-2 text-sm text-muted-foreground"
76
+ aria-busy="true"
77
+ >
78
+ <IconLoader2 className="size-4 animate-spin" />
79
+ {t("jobs.loading", { defaultValue: "Loading…" })}
80
+ </div>
81
+ );
82
+ }
83
+
84
+ if (query.error) {
85
+ return (
86
+ <p className="text-sm text-destructive">
87
+ {t("jobs.automationsLoadError", {
88
+ defaultValue: "Could not load automations.",
89
+ })}
90
+ </p>
91
+ );
87
92
  }
88
- return items;
93
+
94
+ const automations = query.data ?? [];
95
+ if (automations.length === 0) {
96
+ return (
97
+ <p className="text-sm text-muted-foreground">
98
+ {emptyMessage ??
99
+ t("jobs.automationsEmpty", {
100
+ defaultValue:
101
+ "No automations yet. Ask the agent to set up an event-triggered or scheduled task.",
102
+ })}
103
+ </p>
104
+ );
105
+ }
106
+
107
+ return (
108
+ <div className={compact ? "space-y-2" : "space-y-3"}>
109
+ {automations.map((automation) => {
110
+ const lastRun = formatDateTime(automation.lastRun);
111
+ const nextRun = formatDateTime(automation.nextRun);
112
+ const trigger =
113
+ automation.triggerType === "event"
114
+ ? t("jobs.automationEventTrigger", {
115
+ defaultValue: "On {{event}}",
116
+ event: automation.event ?? "event",
117
+ })
118
+ : (automation.scheduleDescription ??
119
+ automation.schedule ??
120
+ t("jobs.automationScheduleTrigger", {
121
+ defaultValue: "Scheduled task",
122
+ }));
123
+
124
+ return (
125
+ <article
126
+ key={automation.id}
127
+ className="rounded-lg border border-border bg-card p-3"
128
+ >
129
+ <div className="flex items-start gap-3">
130
+ <div className="mt-0.5 text-muted-foreground">
131
+ {automation.triggerType === "event" ? (
132
+ <IconBolt className="size-4" />
133
+ ) : (
134
+ <IconClock className="size-4" />
135
+ )}
136
+ </div>
137
+ <div className="min-w-0 flex-1">
138
+ <div className="flex flex-wrap items-center gap-2">
139
+ <h3 className="truncate text-sm font-medium text-foreground">
140
+ {automation.name.replace(/-/g, " ")}
141
+ </h3>
142
+ <span
143
+ className={
144
+ automation.enabled
145
+ ? "rounded-full bg-emerald-500/15 px-2 py-0.5 text-[10px] font-medium text-emerald-600 dark:text-emerald-400"
146
+ : "rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground"
147
+ }
148
+ >
149
+ {automation.enabled
150
+ ? t("jobs.enabled", { defaultValue: "Enabled" })
151
+ : t("jobs.disabled", { defaultValue: "Disabled" })}
152
+ </span>
153
+ {automation.lastStatus ? (
154
+ <span className="rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground">
155
+ {automation.lastStatus}
156
+ </span>
157
+ ) : null}
158
+ </div>
159
+ <p className="mt-1 text-xs text-muted-foreground">{trigger}</p>
160
+ <p className="mt-1 line-clamp-2 text-xs text-muted-foreground/80">
161
+ {automation.body}
162
+ </p>
163
+ {lastRun || nextRun ? (
164
+ <div className="mt-2 flex flex-wrap gap-x-4 gap-y-1 text-[11px] text-muted-foreground">
165
+ {lastRun ? (
166
+ <span>
167
+ {t("jobs.lastRun", { defaultValue: "Last run" })}:{" "}
168
+ {lastRun}
169
+ </span>
170
+ ) : null}
171
+ {nextRun ? (
172
+ <span>
173
+ {t("jobs.nextRun", { defaultValue: "Next run" })}:{" "}
174
+ {nextRun}
175
+ </span>
176
+ ) : null}
177
+ </div>
178
+ ) : null}
179
+ </div>
180
+ <div className="flex shrink-0 items-center gap-1">
181
+ <Button
182
+ type="button"
183
+ variant="ghost"
184
+ size="sm"
185
+ className="cursor-pointer px-2 text-xs"
186
+ onClick={() => setDetailsTarget(automation)}
187
+ >
188
+ <IconEye className="size-3.5" />
189
+ {t("jobs.details", { defaultValue: "Details" })}
190
+ </Button>
191
+ {automation.canUpdate ? (
192
+ <>
193
+ <Button
194
+ type="button"
195
+ variant="ghost"
196
+ size="sm"
197
+ className="cursor-pointer px-2 text-xs"
198
+ disabled={mutation.isPending}
199
+ onClick={() =>
200
+ mutation.mutate({
201
+ operation: "update",
202
+ name: automation.name,
203
+ scope: automation.scope,
204
+ enabled: !automation.enabled,
205
+ })
206
+ }
207
+ >
208
+ {automation.enabled ? (
209
+ <IconPlayerPause className="size-3.5" />
210
+ ) : (
211
+ <IconPlayerPlay className="size-3.5" />
212
+ )}
213
+ {automation.enabled
214
+ ? t("jobs.pause", { defaultValue: "Pause" })
215
+ : t("jobs.resume", { defaultValue: "Resume" })}
216
+ </Button>
217
+ <Button
218
+ type="button"
219
+ variant="ghost"
220
+ size="icon"
221
+ className="size-8 cursor-pointer text-muted-foreground hover:text-destructive"
222
+ aria-label={t("jobs.delete", { defaultValue: "Delete" })}
223
+ onClick={() => setDeleteTarget(automation)}
224
+ >
225
+ <IconTrash className="size-3.5" />
226
+ </Button>
227
+ </>
228
+ ) : null}
229
+ </div>
230
+ </div>
231
+ </article>
232
+ );
233
+ })}
234
+
235
+ {mutation.error ? (
236
+ <p className="text-sm text-destructive">
237
+ {mutation.error.message ||
238
+ t("jobs.automationUpdateError", {
239
+ defaultValue: "Could not update automation.",
240
+ })}
241
+ </p>
242
+ ) : null}
243
+
244
+ <Dialog
245
+ open={deleteTarget !== null}
246
+ onOpenChange={(open) => {
247
+ if (!open && !mutation.isPending) setDeleteTarget(null);
248
+ }}
249
+ >
250
+ <DialogContent>
251
+ <DialogHeader>
252
+ <DialogTitle>
253
+ {t("jobs.deleteAutomationTitle", {
254
+ defaultValue: "Delete automation?",
255
+ })}
256
+ </DialogTitle>
257
+ <DialogDescription>
258
+ {t("jobs.deleteAutomationDescription", {
259
+ defaultValue:
260
+ "This permanently removes the automation and cannot be undone.",
261
+ })}
262
+ </DialogDescription>
263
+ </DialogHeader>
264
+ <DialogFooter>
265
+ <Button
266
+ type="button"
267
+ variant="outline"
268
+ className="cursor-pointer"
269
+ disabled={mutation.isPending}
270
+ onClick={() => setDeleteTarget(null)}
271
+ >
272
+ {t("jobs.cancel", { defaultValue: "Cancel" })}
273
+ </Button>
274
+ <Button
275
+ type="button"
276
+ variant="destructive"
277
+ className="cursor-pointer"
278
+ disabled={mutation.isPending}
279
+ onClick={() => {
280
+ if (!deleteTarget) return;
281
+ mutation.mutate(
282
+ {
283
+ operation: "delete",
284
+ name: deleteTarget.name,
285
+ scope: deleteTarget.scope,
286
+ },
287
+ { onSuccess: () => setDeleteTarget(null) },
288
+ );
289
+ }}
290
+ >
291
+ {mutation.isPending ? (
292
+ <IconLoader2 className="size-4 animate-spin" />
293
+ ) : null}
294
+ {t("jobs.delete", { defaultValue: "Delete" })}
295
+ </Button>
296
+ </DialogFooter>
297
+ </DialogContent>
298
+ </Dialog>
299
+
300
+ <Dialog
301
+ open={detailsTarget !== null}
302
+ onOpenChange={(open) => {
303
+ if (!open) setDetailsTarget(null);
304
+ }}
305
+ >
306
+ <DialogContent className="max-w-2xl">
307
+ <DialogHeader>
308
+ <DialogTitle>
309
+ {detailsTarget?.name.replace(/-/g, " ") ??
310
+ t("jobs.automationDetails", {
311
+ defaultValue: "Automation details",
312
+ })}
313
+ </DialogTitle>
314
+ <DialogDescription>
315
+ {detailsTarget
316
+ ? detailsTarget.triggerType === "event"
317
+ ? t("jobs.automationEventDetails", {
318
+ defaultValue: "Runs when {{event}}.",
319
+ event: detailsTarget.event ?? "an event fires",
320
+ })
321
+ : (detailsTarget.scheduleDescription ??
322
+ detailsTarget.schedule ??
323
+ t("jobs.automationScheduleTrigger", {
324
+ defaultValue: "Scheduled task",
325
+ }))
326
+ : null}
327
+ </DialogDescription>
328
+ </DialogHeader>
329
+ {detailsTarget ? (
330
+ <div className="space-y-3">
331
+ {detailsTarget.condition ? (
332
+ <div>
333
+ <p className="text-xs font-medium text-foreground">
334
+ {t("jobs.condition", { defaultValue: "Condition" })}
335
+ </p>
336
+ <p className="mt-1 text-sm text-muted-foreground">
337
+ {detailsTarget.condition}
338
+ </p>
339
+ </div>
340
+ ) : null}
341
+ <div>
342
+ <p className="text-xs font-medium text-foreground">
343
+ {t("jobs.instructions", { defaultValue: "Instructions" })}
344
+ </p>
345
+ <p className="mt-1 whitespace-pre-wrap text-sm text-muted-foreground">
346
+ {detailsTarget.body}
347
+ </p>
348
+ </div>
349
+ </div>
350
+ ) : null}
351
+ </DialogContent>
352
+ </Dialog>
353
+ </div>
354
+ );
89
355
  }
90
356
 
91
357
  export function AutomationsSection() {
92
- const [automations, setAutomations] = useState<AutomationItem[]>([]);
93
- const [loading, setLoading] = useState(true);
94
- const [error, setError] = useState<string | null>(null);
95
- const [togglingId, setTogglingId] = useState<string | null>(null);
96
- const [deletingId, setDeletingId] = useState<string | null>(null);
97
- const [confirmDeleteId, setConfirmDeleteId] = useState<string | null>(null);
358
+ const t = useT();
359
+ const { data: automations = [] } = useAutomations("user");
360
+ const [newOpen, setNewOpen] = useState(false);
98
361
  const [toast, setToast] = useState<{
99
362
  kind: "ok" | "err";
100
363
  text: string;
101
364
  } | null>(null);
102
- const [reloadToken, setReloadToken] = useState(0);
103
365
 
104
366
  const showToast = useCallback(
105
367
  (kind: "ok" | "err", text: string, ms = 2500) => {
106
368
  setToast({ kind, text });
107
- setTimeout(() => setToast(null), ms);
369
+ window.setTimeout(() => setToast(null), ms);
108
370
  },
109
371
  [],
110
372
  );
111
373
 
112
- useEffect(() => {
113
- let cancelled = false;
114
- setLoading(true);
115
- fetch(agentNativePath("/_agent-native/resources/tree"))
116
- .then(async (r) => {
117
- if (!r.ok) throw new Error(`Failed to load (${r.status})`);
118
- return (await r.json()) as { tree: TreeNode[] };
119
- })
120
- .then(({ tree }) => {
121
- if (cancelled) return;
122
- const jobsFolder = tree.find(
123
- (n) => n.name === "jobs" && n.type === "folder",
124
- );
125
- const items = jobsFolder?.children
126
- ? flattenJobs(jobsFolder.children)
127
- : [];
128
- setAutomations(items);
129
- setLoading(false);
130
- })
131
- .catch((err) => {
132
- if (cancelled) return;
133
- setError(err?.message ?? "Failed to load");
134
- setLoading(false);
135
- });
136
- return () => {
137
- cancelled = true;
138
- };
139
- }, [reloadToken]);
140
-
141
- const reload = useCallback(() => setReloadToken((t) => t + 1), []);
142
-
143
- const handleToggle = useCallback(
144
- async (item: AutomationItem) => {
145
- setTogglingId(item.id);
146
- try {
147
- const res = await fetch(
148
- agentNativePath(
149
- `/_agent-native/resources/${encodeURIComponent(item.id)}`,
150
- ),
151
- );
152
- if (!res.ok) {
153
- showToast("err", "Failed to read automation");
154
- return;
155
- }
156
- const resource = await res.json();
157
- const content: string = resource.content ?? "";
158
-
159
- const newEnabled = !item.enabled;
160
- const updated = content.replace(
161
- /^(enabled:\s*)(true|false)/m,
162
- `$1${newEnabled}`,
163
- );
164
-
165
- const putRes = await fetch(
166
- agentNativePath(
167
- `/_agent-native/resources/${encodeURIComponent(item.id)}`,
168
- ),
169
- {
170
- method: "PUT",
171
- headers: { "Content-Type": "application/json" },
172
- body: JSON.stringify({ content: updated }),
173
- },
174
- );
175
- if (!putRes.ok) {
176
- showToast("err", "Failed to update automation");
177
- return;
178
- }
179
- showToast("ok", newEnabled ? "Enabled" : "Disabled");
180
- reload();
181
- } finally {
182
- setTogglingId(null);
183
- }
184
- },
185
- [reload, showToast],
186
- );
187
-
188
- const handleDelete = useCallback(
189
- async (item: AutomationItem) => {
190
- setDeletingId(item.id);
191
- try {
192
- const res = await fetch(
193
- agentNativePath(
194
- `/_agent-native/resources/${encodeURIComponent(item.id)}`,
195
- ),
196
- {
197
- method: "DELETE",
198
- headers: { "Content-Type": "application/json" },
199
- },
200
- );
201
- if (!res.ok) {
202
- showToast("err", "Failed to delete automation");
203
- return;
204
- }
205
- showToast("ok", "Deleted");
206
- setConfirmDeleteId(null);
207
- reload();
208
- } finally {
209
- setDeletingId(null);
210
- }
211
- },
212
- [reload, showToast],
213
- );
214
-
215
374
  const handleFireTestEvent = useCallback(async () => {
216
- showToast("ok", "Firing test event...");
375
+ showToast(
376
+ "ok",
377
+ t("jobs.firingTestEvent", { defaultValue: "Firing test event…" }),
378
+ );
217
379
  try {
218
380
  const res = await fetch(
219
381
  agentNativePath("/_agent-native/automations/fire-test"),
@@ -224,69 +386,59 @@ export function AutomationsSection() {
224
386
  },
225
387
  );
226
388
  if (!res.ok) {
227
- showToast("err", `Failed to fire event (${res.status})`);
389
+ showToast(
390
+ "err",
391
+ t("jobs.fireEventError", {
392
+ defaultValue: "Failed to fire event ({{status}})",
393
+ status: res.status,
394
+ }),
395
+ );
228
396
  return;
229
397
  }
230
- showToast("ok", "Event fired");
231
- } catch (err: any) {
232
- showToast("err", err?.message ?? "Failed to fire event");
233
- }
234
- }, [showToast]);
235
-
236
- const [newOpen, setNewOpen] = useState(false);
237
- const [newScope, setNewScope] = useState<"personal" | "organization">(
238
- "personal",
239
- );
240
-
241
- const handleNewSubmit = useCallback(
242
- (text: string) => {
243
- const trimmed = text.trim();
244
- if (!trimmed) return;
245
- window.dispatchEvent(
246
- new CustomEvent("agent-panel:set-mode", {
247
- detail: { mode: "chat" },
248
- }),
398
+ showToast("ok", t("jobs.eventFired", { defaultValue: "Event fired" }));
399
+ } catch (err: unknown) {
400
+ showToast(
401
+ "err",
402
+ err instanceof Error
403
+ ? err.message
404
+ : t("jobs.fireEventErrorGeneric", {
405
+ defaultValue: "Failed to fire event.",
406
+ }),
249
407
  );
250
- sendToAgentChat({
251
- message: trimmed,
252
- context: `The user wants to create a new automation. Scope: ${newScope}. Use manage-automations with action=define to create it. Ask clarifying questions if needed about what event to trigger on, conditions, and what actions to take.`,
253
- submit: true,
254
- newTab: true,
255
- });
256
- setNewOpen(false);
257
- },
258
- [newScope],
259
- );
260
-
261
- if (error) {
262
- return (
263
- <p className="text-[10px] text-red-500">
264
- Failed to load automations: {error}
265
- </p>
266
- );
267
- }
408
+ }
409
+ }, [showToast, t]);
268
410
 
269
- if (loading) {
270
- return (
271
- <div className="flex items-center gap-1.5 text-[10px] text-muted-foreground">
272
- <IconLoader2 size={10} className="animate-spin" />
273
- Loading...
274
- </div>
411
+ const handleNewSubmit = useCallback((text: string) => {
412
+ const trimmed = text.trim();
413
+ if (!trimmed) return;
414
+ window.dispatchEvent(
415
+ new CustomEvent("agent-panel:set-mode", {
416
+ detail: { mode: "chat" },
417
+ }),
275
418
  );
276
- }
419
+ sendToAgentChat({
420
+ message: trimmed,
421
+ context: automationCreationContext(),
422
+ submit: true,
423
+ newTab: true,
424
+ });
425
+ setNewOpen(false);
426
+ }, []);
277
427
 
278
428
  return (
279
429
  <div className="space-y-2">
280
430
  <div className="flex items-center gap-1.5">
281
431
  <Popover open={newOpen} onOpenChange={setNewOpen}>
282
432
  <PopoverTrigger asChild>
283
- <button
433
+ <Button
284
434
  type="button"
285
- className="inline-flex items-center gap-1 rounded border border-border px-2 py-1 text-[10px] font-medium text-muted-foreground hover:text-foreground hover:bg-accent/40"
435
+ variant="outline"
436
+ size="sm"
437
+ className="cursor-pointer"
286
438
  >
287
- <IconPlus size={10} />
288
- New Automation
289
- </button>
439
+ <IconPlus className="size-3.5" />
440
+ {t("jobs.newAutomation", { defaultValue: "New automation" })}
441
+ </Button>
290
442
  </PopoverTrigger>
291
443
  <PopoverContent
292
444
  align="start"
@@ -295,182 +447,50 @@ export function AutomationsSection() {
295
447
  className="z-[260] w-[calc(100vw-24px)] max-w-[380px] p-3"
296
448
  >
297
449
  <p className="px-1 pb-2 text-sm font-semibold text-foreground">
298
- New automation
450
+ {t("jobs.newAutomation", { defaultValue: "New automation" })}
299
451
  </p>
300
452
  <PromptComposer
301
453
  autoFocus
302
- placeholder="Describe what you want to automate..."
454
+ placeholder={t("jobs.automationPlaceholder", {
455
+ defaultValue: "Describe what you want to automate…",
456
+ })}
303
457
  draftScope="automations:create"
304
458
  onSubmit={handleNewSubmit}
305
459
  />
306
- <div className="mt-2">
307
- <select
308
- value={newScope}
309
- onChange={(e) =>
310
- setNewScope(e.target.value as "personal" | "organization")
311
- }
312
- className="w-full cursor-pointer rounded-md border border-input bg-background px-3 py-1.5 text-[12px] text-foreground"
313
- >
314
- <option value="personal">Personal</option>
315
- <option value="organization">Organization</option>
316
- </select>
317
- </div>
318
460
  </PopoverContent>
319
461
  </Popover>
320
- {automations.length > 0 && (
321
- <button
462
+ {automations.length > 0 ? (
463
+ <Button
322
464
  type="button"
465
+ variant="outline"
466
+ size="sm"
467
+ className="cursor-pointer"
323
468
  onClick={handleFireTestEvent}
324
- className="inline-flex items-center gap-1 rounded border border-border px-2 py-1 text-[10px] font-medium text-muted-foreground hover:text-foreground hover:bg-accent/40"
325
469
  >
326
- <IconPlayerPlay size={10} />
327
- Fire Test Event
328
- </button>
329
- )}
470
+ <IconPlayerPlay className="size-3.5" />
471
+ {t("jobs.fireTestEvent", { defaultValue: "Fire test event" })}
472
+ </Button>
473
+ ) : null}
330
474
  </div>
331
-
332
- {automations.length === 0 ? (
333
- <p className="text-[10px] text-muted-foreground">
334
- No automations yet. Click "New Automation" to create one, or ask the
335
- agent to set up a scheduled or event-triggered task.
336
- </p>
337
- ) : (
338
- automations.map((item) => (
339
- <div
340
- key={item.id}
341
- className="rounded-md border border-border px-2.5 py-2 bg-accent/30"
342
- >
343
- <div className="flex items-center justify-between gap-2">
344
- <div className="min-w-0 flex-1">
345
- <div className="flex items-center gap-1.5">
346
- <span className="text-muted-foreground shrink-0">
347
- {item.schedule ? (
348
- <IconClock size={11} />
349
- ) : (
350
- <IconBolt size={11} />
351
- )}
352
- </span>
353
- <span className="text-[11px] font-medium text-foreground truncate capitalize">
354
- {item.name}
355
- </span>
356
- </div>
357
- {item.scheduleDescription && (
358
- <p className="text-[10px] text-muted-foreground mt-0.5 ms-[17px]">
359
- {item.scheduleDescription}
360
- </p>
361
- )}
362
- {item.schedule && !item.scheduleDescription && (
363
- <p className="text-[10px] text-muted-foreground mt-0.5 ms-[17px] font-mono">
364
- {item.schedule}
365
- </p>
366
- )}
367
- </div>
368
- <div className="flex items-center gap-1.5 shrink-0">
369
- <StatusBadge status={item.lastStatus} />
370
- <Tooltip>
371
- <TooltipTrigger asChild>
372
- <button
373
- type="button"
374
- onClick={() => handleToggle(item)}
375
- disabled={togglingId === item.id}
376
- className={`rounded px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide ${
377
- item.enabled
378
- ? "bg-green-500/15 text-green-500"
379
- : "bg-accent/60 text-muted-foreground"
380
- } hover:opacity-80 disabled:opacity-40`}
381
- >
382
- {togglingId === item.id ? (
383
- <IconLoader2 size={10} className="animate-spin" />
384
- ) : item.enabled ? (
385
- "On"
386
- ) : (
387
- "Off"
388
- )}
389
- </button>
390
- </TooltipTrigger>
391
- <TooltipContent>
392
- {item.enabled ? "Disable" : "Enable"}
393
- </TooltipContent>
394
- </Tooltip>
395
- {confirmDeleteId === item.id ? (
396
- <div className="flex items-center gap-1">
397
- <button
398
- type="button"
399
- onClick={() => handleDelete(item)}
400
- disabled={deletingId === item.id}
401
- className="rounded px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide bg-red-500/15 text-red-500 hover:bg-red-500/25 disabled:opacity-40"
402
- >
403
- {deletingId === item.id ? (
404
- <IconLoader2 size={10} className="animate-spin" />
405
- ) : (
406
- "Confirm"
407
- )}
408
- </button>
409
- <button
410
- type="button"
411
- onClick={() => setConfirmDeleteId(null)}
412
- className="rounded px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide bg-accent/60 text-muted-foreground hover:text-foreground"
413
- >
414
- Cancel
415
- </button>
416
- </div>
417
- ) : (
418
- <Tooltip>
419
- <TooltipTrigger asChild>
420
- <button
421
- type="button"
422
- onClick={() => setConfirmDeleteId(item.id)}
423
- className="text-muted-foreground hover:text-red-500 disabled:opacity-40"
424
- >
425
- <IconTrash size={12} />
426
- </button>
427
- </TooltipTrigger>
428
- <TooltipContent>Delete</TooltipContent>
429
- </Tooltip>
430
- )}
431
- </div>
432
- </div>
433
- {item.lastRun && (
434
- <p className="text-[10px] text-muted-foreground mt-1 ms-[17px]">
435
- Last run:{" "}
436
- {new Date(item.lastRun).toLocaleString(undefined, {
437
- month: "short",
438
- day: "numeric",
439
- hour: "numeric",
440
- minute: "2-digit",
441
- })}
442
- </p>
443
- )}
444
- </div>
445
- ))
446
- )}
447
-
448
- {toast && (
475
+ {toast ? (
449
476
  <p
450
- className={`text-[10px] ${toast.kind === "ok" ? "text-green-500" : "text-red-500"}`}
477
+ className={
478
+ toast.kind === "ok"
479
+ ? "text-xs text-emerald-600"
480
+ : "text-xs text-destructive"
481
+ }
451
482
  >
452
483
  {toast.text}
453
484
  </p>
454
- )}
485
+ ) : null}
486
+ <AutomationsList
487
+ scope="user"
488
+ compact
489
+ emptyMessage={t("jobs.automationsEmptySettings", {
490
+ defaultValue:
491
+ 'No automations yet. Click "New automation" or ask the agent to set one up.',
492
+ })}
493
+ />
455
494
  </div>
456
495
  );
457
496
  }
458
-
459
- function StatusBadge({ status }: { status?: string }) {
460
- if (!status) return null;
461
-
462
- const styles: Record<string, string> = {
463
- success: "bg-green-500/15 text-green-500",
464
- error: "bg-red-500/15 text-red-500",
465
- running: "bg-blue-500/15 text-blue-500",
466
- skipped: "bg-accent/60 text-muted-foreground",
467
- };
468
-
469
- return (
470
- <span
471
- className={`rounded-full px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide ${styles[status] ?? styles.skipped}`}
472
- >
473
- {status}
474
- </span>
475
- );
476
- }