@agent-native/core 0.96.0 → 0.97.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (450) hide show
  1. package/README.md +6 -0
  2. package/corpus/README.md +2 -2
  3. package/corpus/core/CHANGELOG.md +39 -0
  4. package/corpus/core/docs/content/audit-log.mdx +2 -1
  5. package/corpus/core/docs/content/automations.mdx +7 -7
  6. package/corpus/core/docs/content/creating-templates.mdx +1 -1
  7. package/corpus/core/docs/content/internationalization.mdx +2 -1
  8. package/corpus/core/docs/content/locales/ar-SA/audit-log.mdx +2 -1
  9. package/corpus/core/docs/content/locales/ar-SA/automations.mdx +7 -7
  10. package/corpus/core/docs/content/locales/ar-SA/getting-started.mdx +7 -1
  11. package/corpus/core/docs/content/locales/ar-SA/internationalization.mdx +1 -1
  12. package/corpus/core/docs/content/locales/ar-SA/package-lifecycle.mdx +19 -0
  13. package/corpus/core/docs/content/locales/ar-SA/sandbox-adapters.mdx +18 -7
  14. package/corpus/core/docs/content/locales/ar-SA/security.mdx +8 -0
  15. package/corpus/core/docs/content/locales/de-DE/audit-log.mdx +2 -1
  16. package/corpus/core/docs/content/locales/de-DE/automations.mdx +7 -7
  17. package/corpus/core/docs/content/locales/de-DE/getting-started.mdx +7 -1
  18. package/corpus/core/docs/content/locales/de-DE/internationalization.mdx +1 -1
  19. package/corpus/core/docs/content/locales/de-DE/package-lifecycle.mdx +22 -0
  20. package/corpus/core/docs/content/locales/de-DE/sandbox-adapters.mdx +18 -7
  21. package/corpus/core/docs/content/locales/de-DE/security.mdx +8 -0
  22. package/corpus/core/docs/content/locales/es-ES/audit-log.mdx +2 -1
  23. package/corpus/core/docs/content/locales/es-ES/automations.mdx +7 -7
  24. package/corpus/core/docs/content/locales/es-ES/getting-started.mdx +7 -1
  25. package/corpus/core/docs/content/locales/es-ES/internationalization.mdx +1 -1
  26. package/corpus/core/docs/content/locales/es-ES/package-lifecycle.mdx +22 -0
  27. package/corpus/core/docs/content/locales/es-ES/sandbox-adapters.mdx +18 -7
  28. package/corpus/core/docs/content/locales/es-ES/security.mdx +8 -0
  29. package/corpus/core/docs/content/locales/fr-FR/audit-log.mdx +2 -1
  30. package/corpus/core/docs/content/locales/fr-FR/automations.mdx +7 -7
  31. package/corpus/core/docs/content/locales/fr-FR/getting-started.mdx +7 -1
  32. package/corpus/core/docs/content/locales/fr-FR/internationalization.mdx +1 -1
  33. package/corpus/core/docs/content/locales/fr-FR/package-lifecycle.mdx +21 -0
  34. package/corpus/core/docs/content/locales/fr-FR/sandbox-adapters.mdx +19 -8
  35. package/corpus/core/docs/content/locales/fr-FR/security.mdx +8 -0
  36. package/corpus/core/docs/content/locales/hi-IN/audit-log.mdx +2 -1
  37. package/corpus/core/docs/content/locales/hi-IN/automations.mdx +7 -7
  38. package/corpus/core/docs/content/locales/hi-IN/getting-started.mdx +7 -1
  39. package/corpus/core/docs/content/locales/hi-IN/internationalization.mdx +1 -1
  40. package/corpus/core/docs/content/locales/hi-IN/package-lifecycle.mdx +20 -0
  41. package/corpus/core/docs/content/locales/hi-IN/sandbox-adapters.mdx +18 -7
  42. package/corpus/core/docs/content/locales/hi-IN/security.mdx +8 -0
  43. package/corpus/core/docs/content/locales/ja-JP/audit-log.mdx +2 -1
  44. package/corpus/core/docs/content/locales/ja-JP/automations.mdx +7 -7
  45. package/corpus/core/docs/content/locales/ja-JP/getting-started.mdx +7 -1
  46. package/corpus/core/docs/content/locales/ja-JP/internationalization.mdx +1 -1
  47. package/corpus/core/docs/content/locales/ja-JP/package-lifecycle.mdx +21 -0
  48. package/corpus/core/docs/content/locales/ja-JP/sandbox-adapters.mdx +17 -6
  49. package/corpus/core/docs/content/locales/ja-JP/security.mdx +8 -0
  50. package/corpus/core/docs/content/locales/ko-KR/audit-log.mdx +2 -1
  51. package/corpus/core/docs/content/locales/ko-KR/automations.mdx +7 -7
  52. package/corpus/core/docs/content/locales/ko-KR/getting-started.mdx +7 -1
  53. package/corpus/core/docs/content/locales/ko-KR/internationalization.mdx +1 -1
  54. package/corpus/core/docs/content/locales/ko-KR/package-lifecycle.mdx +20 -0
  55. package/corpus/core/docs/content/locales/ko-KR/sandbox-adapters.mdx +17 -6
  56. package/corpus/core/docs/content/locales/ko-KR/security.mdx +8 -0
  57. package/corpus/core/docs/content/locales/pt-BR/audit-log.mdx +2 -1
  58. package/corpus/core/docs/content/locales/pt-BR/automations.mdx +7 -7
  59. package/corpus/core/docs/content/locales/pt-BR/getting-started.mdx +7 -1
  60. package/corpus/core/docs/content/locales/pt-BR/internationalization.mdx +1 -1
  61. package/corpus/core/docs/content/locales/pt-BR/package-lifecycle.mdx +21 -0
  62. package/corpus/core/docs/content/locales/pt-BR/sandbox-adapters.mdx +18 -7
  63. package/corpus/core/docs/content/locales/pt-BR/security.mdx +8 -0
  64. package/corpus/core/docs/content/locales/zh-CN/audit-log.mdx +2 -1
  65. package/corpus/core/docs/content/locales/zh-CN/automations.mdx +7 -7
  66. package/corpus/core/docs/content/locales/zh-CN/getting-started.mdx +6 -4
  67. package/corpus/core/docs/content/locales/zh-CN/internationalization.mdx +1 -1
  68. package/corpus/core/docs/content/locales/zh-CN/package-lifecycle.mdx +19 -0
  69. package/corpus/core/docs/content/locales/zh-CN/sandbox-adapters.mdx +17 -6
  70. package/corpus/core/docs/content/locales/zh-CN/security.mdx +8 -0
  71. package/corpus/core/docs/content/locales/zh-TW/audit-log.mdx +2 -1
  72. package/corpus/core/docs/content/locales/zh-TW/automations.mdx +7 -7
  73. package/corpus/core/docs/content/locales/zh-TW/getting-started.mdx +6 -4
  74. package/corpus/core/docs/content/locales/zh-TW/internationalization.mdx +1 -1
  75. package/corpus/core/docs/content/locales/zh-TW/package-lifecycle.mdx +19 -0
  76. package/corpus/core/docs/content/locales/zh-TW/sandbox-adapters.mdx +18 -7
  77. package/corpus/core/docs/content/locales/zh-TW/security.mdx +8 -0
  78. package/corpus/core/docs/content/package-lifecycle.mdx +51 -0
  79. package/corpus/core/docs/content/sandbox-adapters.mdx +16 -5
  80. package/corpus/core/package.json +9 -2
  81. package/corpus/core/src/a2a/auth-policy.ts +33 -0
  82. package/corpus/core/src/agent/durable-background.ts +15 -7
  83. package/corpus/core/src/agent/run-store.ts +13 -4
  84. package/corpus/core/src/audit/actions/export-audit-events.ts +162 -0
  85. package/corpus/core/src/audit/store.ts +8 -3
  86. package/corpus/core/src/audit/types.ts +3 -0
  87. package/corpus/core/src/cli/doctor.ts +396 -0
  88. package/corpus/core/src/cli/index.ts +56 -0
  89. package/corpus/core/src/cli/info.ts +3 -3
  90. package/corpus/core/src/cli/package-lifecycle.ts +821 -0
  91. package/corpus/core/src/client/agent-chat-adapter.ts +9 -9
  92. package/corpus/core/src/guards/db-tool-scoping.ts +129 -0
  93. package/corpus/core/src/guards/index.ts +23 -0
  94. package/corpus/core/src/guards/no-drizzle-push.ts +116 -0
  95. package/corpus/core/src/guards/no-env-credentials.ts +229 -0
  96. package/corpus/core/src/guards/no-env-mutation.ts +114 -0
  97. package/corpus/core/src/guards/no-localhost-fallback.ts +124 -0
  98. package/corpus/core/src/guards/no-unscoped-credentials.ts +227 -0
  99. package/corpus/core/src/guards/no-unscoped-queries.ts +834 -0
  100. package/corpus/core/src/guards/scan-utils.ts +105 -0
  101. package/corpus/core/src/guards/types.ts +30 -0
  102. package/corpus/core/src/org/accept-pending.ts +9 -1
  103. package/corpus/core/src/org/migrations.ts +41 -0
  104. package/corpus/core/src/package-lifecycle/index.ts +1 -0
  105. package/corpus/core/src/package-lifecycle/manifest.ts +120 -0
  106. package/corpus/core/src/provider-api/custom-registry.ts +56 -0
  107. package/corpus/core/src/provider-api/index.ts +2 -0
  108. package/corpus/core/src/secrets/storage.ts +47 -27
  109. package/corpus/core/src/server/action-discovery.ts +4 -0
  110. package/corpus/core/src/server/agent-chat-plugin.ts +54 -12
  111. package/corpus/core/src/server/core-routes-plugin.ts +30 -14
  112. package/corpus/core/src/server/csrf.ts +24 -5
  113. package/corpus/core/src/server/framework-request-handler.ts +34 -0
  114. package/corpus/core/src/server/google-realtime-session.ts +1 -36
  115. package/corpus/core/src/server/poll.ts +24 -2
  116. package/corpus/core/src/server/realtime-voice.ts +9 -0
  117. package/corpus/core/src/server/request-origin.ts +63 -0
  118. package/corpus/core/src/server/transcribe-voice.ts +1 -50
  119. package/corpus/core/src/templates/default/package.json +2 -2
  120. package/corpus/core/src/templates/headless/package.json +0 -1
  121. package/corpus/core/src/templates/workspace-core/.agents/skills/audit-log/SKILL.md +3 -0
  122. package/corpus/core/src/templates/workspace-core/.agents/skills/automations/SKILL.md +1 -1
  123. package/corpus/core/src/templates/workspace-core/package.json +0 -1
  124. package/corpus/core/src/templates/workspace-root/package.json +0 -1
  125. package/corpus/core/src/triggers/actions.ts +11 -3
  126. package/corpus/core/src/triggers/types.ts +7 -1
  127. package/corpus/templates/analytics/actions/compose-dashboard.ts +65 -37
  128. package/corpus/templates/analytics/actions/mutate-dashboard.ts +73 -24
  129. package/corpus/templates/analytics/actions/reorder-dashboard-panels.ts +16 -13
  130. package/corpus/templates/analytics/actions/update-dashboard.ts +53 -42
  131. package/corpus/templates/analytics/changelog/2026-07-10-dashboard-edits-from-the-agent-and-the-ui-at-the-same-time-n.md +6 -0
  132. package/corpus/templates/analytics/changelog/2026-07-10-timed-out-bigquery-jobs-are-now-cancelled-so-they-stop-consu.md +6 -0
  133. package/corpus/templates/analytics/package.json +1 -2
  134. package/corpus/templates/analytics/server/lib/bigquery.ts +3 -2
  135. package/corpus/templates/analytics/server/lib/dashboards-store.ts +154 -11
  136. package/corpus/templates/assets/package.json +1 -2
  137. package/corpus/templates/brain/package.json +1 -2
  138. package/corpus/templates/calendar/package.json +1 -2
  139. package/corpus/templates/chat/package.json +1 -2
  140. package/corpus/templates/clips/changelog/2026-07-10-atomic-view-tracking.md +6 -0
  141. package/corpus/templates/clips/chrome-extension/package.json +3 -2
  142. package/corpus/templates/clips/desktop/package.json +6 -4
  143. package/corpus/templates/clips/desktop/src/lib/recorder.ts +26 -13
  144. package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +4 -1
  145. package/corpus/templates/clips/package.json +1 -2
  146. package/corpus/templates/clips/server/db/schema.ts +29 -17
  147. package/corpus/templates/clips/server/plugins/db.ts +8 -0
  148. package/corpus/templates/clips/server/routes/api/view-event.post.ts +260 -105
  149. package/corpus/templates/content/.agents/skills/notion-integration/SKILL.md +16 -0
  150. package/corpus/templates/content/AGENTS.md +72 -62
  151. package/corpus/templates/content/actions/_content-database-source-adapters.ts +84 -0
  152. package/corpus/templates/content/actions/_database-source-utils.ts +206 -96
  153. package/corpus/templates/content/actions/_notion-database-source-adapter.ts +216 -0
  154. package/corpus/templates/content/actions/_position-utils.ts +76 -0
  155. package/corpus/templates/content/actions/_property-utils.ts +31 -20
  156. package/corpus/templates/content/actions/add-database-item.ts +52 -39
  157. package/corpus/templates/content/actions/attach-content-database-source.ts +95 -11
  158. package/corpus/templates/content/actions/change-content-database-source-role.ts +24 -1
  159. package/corpus/templates/content/actions/configure-document-property.ts +36 -27
  160. package/corpus/templates/content/actions/create-content-database.ts +40 -30
  161. package/corpus/templates/content/actions/create-document.ts +39 -32
  162. package/corpus/templates/content/actions/duplicate-document-property.ts +37 -28
  163. package/corpus/templates/content/actions/list-notion-database-sources.ts +80 -0
  164. package/corpus/templates/content/actions/move-document.ts +64 -48
  165. package/corpus/templates/content/actions/refresh-content-database-source.ts +42 -3
  166. package/corpus/templates/content/actions/share-local-file-document.ts +36 -27
  167. package/corpus/templates/content/actions/suggest-source-join-key.ts +39 -16
  168. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +89 -23
  169. package/corpus/templates/content/app/components/editor/database/settings.tsx +1 -1
  170. package/corpus/templates/content/app/hooks/use-content-database.ts +18 -1
  171. package/corpus/templates/content/app/i18n/zh-TW.ts +4 -0
  172. package/corpus/templates/content/app/i18n-data.ts +40 -0
  173. package/corpus/templates/content/changelog/2026-07-10-failed-row-creation-and-source-attach-now-show-an-error-inst.md +6 -0
  174. package/corpus/templates/content/changelog/2026-07-10-items-added-at-the-same-time-no-longer-end-up-with-identical.md +6 -0
  175. package/corpus/templates/content/changelog/2026-07-10-notion-databases-can-add-read-only-details-to-content-tables.md +6 -0
  176. package/corpus/templates/content/package.json +1 -2
  177. package/corpus/templates/content/parity/matrix.md +25 -25
  178. package/corpus/templates/content/parity/matrix.ts +1 -0
  179. package/corpus/templates/content/server/routes/api/documents/[id]/move.patch.ts +43 -26
  180. package/corpus/templates/content/shared/api.ts +16 -1
  181. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +8 -4
  182. package/corpus/templates/design/AGENTS.md +12 -2
  183. package/corpus/templates/design/DEVELOPING.md +10 -6
  184. package/corpus/templates/design/actions/apply-visual-edit.ts +191 -6
  185. package/corpus/templates/design/actions/duplicate-design.ts +31 -25
  186. package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +5 -1
  187. package/corpus/templates/design/changelog/2026-07-10-duplicating-a-design-can-no-longer-produce-a-copy-with-missi.md +6 -0
  188. package/corpus/templates/design/changelog/2026-07-10-local-visual-edits-can-now-save-safe-leaf-text-class-and.md +6 -0
  189. package/corpus/templates/design/package.json +1 -1
  190. package/corpus/templates/design/shared/local-jsx-visual-edit.ts +388 -0
  191. package/corpus/templates/dispatch/package.json +1 -2
  192. package/corpus/templates/forms/actions/patch-form-fields.ts +82 -44
  193. package/corpus/templates/forms/changelog/2026-07-10-simultaneous-edits-to-different-form-fields-no-longer-overwr.md +6 -0
  194. package/corpus/templates/forms/package.json +1 -2
  195. package/corpus/templates/macros/package.json +1 -2
  196. package/corpus/templates/mail/app/components/email/EmailThread.tsx +3 -1
  197. package/corpus/templates/mail/changelog/2026-07-10-fixed-calendar-rsvp-buttons-in-emails-firing-duplicate-respo.md +6 -0
  198. package/corpus/templates/mail/package.json +1 -2
  199. package/corpus/templates/plan/actions/restore-plan-version.ts +126 -96
  200. package/corpus/templates/plan/changelog/2026-07-10-restoring-a-plan-version-can-no-longer-leave-a-plan-half-res.md +6 -0
  201. package/corpus/templates/plan/package.json +1 -2
  202. package/corpus/templates/plan/server/plans.ts +9 -2
  203. package/corpus/templates/slides/actions/list-decks.ts +28 -0
  204. package/corpus/templates/slides/app/components/deck/MermaidRenderer.tsx +41 -26
  205. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +4 -8
  206. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +2 -4
  207. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +4 -8
  208. package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +5 -12
  209. package/corpus/templates/slides/app/components/editor/HistoryPanel.tsx +3 -6
  210. package/corpus/templates/slides/app/components/editor/ImageDropPromptPopover.tsx +3 -6
  211. package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +2 -5
  212. package/corpus/templates/slides/app/context/DeckContext.tsx +47 -4
  213. package/corpus/templates/slides/app/pages/DeckEditor.tsx +11 -30
  214. package/corpus/templates/slides/app/pages/Index.tsx +2 -3
  215. package/corpus/templates/slides/app/root.tsx +0 -5
  216. package/corpus/templates/slides/changelog/2026-07-10-deck-lists-load-much-faster-and-no-longer-re-download-slide-.md +6 -0
  217. package/corpus/templates/slides/package.json +1 -2
  218. package/dist/a2a/auth-policy.d.ts +19 -0
  219. package/dist/a2a/auth-policy.d.ts.map +1 -1
  220. package/dist/a2a/auth-policy.js +32 -0
  221. package/dist/a2a/auth-policy.js.map +1 -1
  222. package/dist/agent/durable-background.d.ts +8 -5
  223. package/dist/agent/durable-background.d.ts.map +1 -1
  224. package/dist/agent/durable-background.js +15 -8
  225. package/dist/agent/durable-background.js.map +1 -1
  226. package/dist/agent/run-store.d.ts.map +1 -1
  227. package/dist/agent/run-store.js +9 -4
  228. package/dist/agent/run-store.js.map +1 -1
  229. package/dist/audit/actions/export-audit-events.d.ts +27 -0
  230. package/dist/audit/actions/export-audit-events.d.ts.map +1 -0
  231. package/dist/audit/actions/export-audit-events.js +144 -0
  232. package/dist/audit/actions/export-audit-events.js.map +1 -0
  233. package/dist/audit/store.d.ts +1 -0
  234. package/dist/audit/store.d.ts.map +1 -1
  235. package/dist/audit/store.js +8 -3
  236. package/dist/audit/store.js.map +1 -1
  237. package/dist/audit/types.d.ts +3 -0
  238. package/dist/audit/types.d.ts.map +1 -1
  239. package/dist/audit/types.js.map +1 -1
  240. package/dist/cli/doctor.d.ts +83 -0
  241. package/dist/cli/doctor.d.ts.map +1 -0
  242. package/dist/cli/doctor.js +277 -0
  243. package/dist/cli/doctor.js.map +1 -0
  244. package/dist/cli/index.js +50 -0
  245. package/dist/cli/index.js.map +1 -1
  246. package/dist/cli/info.js +3 -3
  247. package/dist/cli/info.js.map +1 -1
  248. package/dist/cli/package-lifecycle.d.ts +50 -0
  249. package/dist/cli/package-lifecycle.d.ts.map +1 -0
  250. package/dist/cli/package-lifecycle.js +560 -0
  251. package/dist/cli/package-lifecycle.js.map +1 -0
  252. package/dist/client/agent-chat-adapter.js +7 -3
  253. package/dist/client/agent-chat-adapter.js.map +1 -1
  254. package/dist/collab/struct-routes.d.ts +1 -1
  255. package/dist/guards/db-tool-scoping.d.ts +38 -0
  256. package/dist/guards/db-tool-scoping.d.ts.map +1 -0
  257. package/dist/guards/db-tool-scoping.js +114 -0
  258. package/dist/guards/db-tool-scoping.js.map +1 -0
  259. package/dist/guards/index.d.ts +23 -0
  260. package/dist/guards/index.d.ts.map +1 -0
  261. package/dist/guards/index.js +19 -0
  262. package/dist/guards/index.js.map +1 -0
  263. package/dist/guards/no-drizzle-push.d.ts +14 -0
  264. package/dist/guards/no-drizzle-push.d.ts.map +1 -0
  265. package/dist/guards/no-drizzle-push.js +97 -0
  266. package/dist/guards/no-drizzle-push.js.map +1 -0
  267. package/dist/guards/no-env-credentials.d.ts +36 -0
  268. package/dist/guards/no-env-credentials.d.ts.map +1 -0
  269. package/dist/guards/no-env-credentials.js +204 -0
  270. package/dist/guards/no-env-credentials.js.map +1 -0
  271. package/dist/guards/no-env-mutation.d.ts +23 -0
  272. package/dist/guards/no-env-mutation.d.ts.map +1 -0
  273. package/dist/guards/no-env-mutation.js +90 -0
  274. package/dist/guards/no-env-mutation.js.map +1 -0
  275. package/dist/guards/no-localhost-fallback.d.ts +30 -0
  276. package/dist/guards/no-localhost-fallback.d.ts.map +1 -0
  277. package/dist/guards/no-localhost-fallback.js +105 -0
  278. package/dist/guards/no-localhost-fallback.js.map +1 -0
  279. package/dist/guards/no-unscoped-credentials.d.ts +28 -0
  280. package/dist/guards/no-unscoped-credentials.d.ts.map +1 -0
  281. package/dist/guards/no-unscoped-credentials.js +199 -0
  282. package/dist/guards/no-unscoped-credentials.js.map +1 -0
  283. package/dist/guards/no-unscoped-queries.d.ts +32 -0
  284. package/dist/guards/no-unscoped-queries.d.ts.map +1 -0
  285. package/dist/guards/no-unscoped-queries.js +720 -0
  286. package/dist/guards/no-unscoped-queries.js.map +1 -0
  287. package/dist/guards/scan-utils.d.ts +28 -0
  288. package/dist/guards/scan-utils.d.ts.map +1 -0
  289. package/dist/guards/scan-utils.js +92 -0
  290. package/dist/guards/scan-utils.js.map +1 -0
  291. package/dist/guards/types.d.ts +28 -0
  292. package/dist/guards/types.d.ts.map +1 -0
  293. package/dist/guards/types.js +11 -0
  294. package/dist/guards/types.js.map +1 -0
  295. package/dist/org/accept-pending.d.ts.map +1 -1
  296. package/dist/org/accept-pending.js +9 -1
  297. package/dist/org/accept-pending.js.map +1 -1
  298. package/dist/org/migrations.d.ts +7 -2
  299. package/dist/org/migrations.d.ts.map +1 -1
  300. package/dist/org/migrations.js +41 -0
  301. package/dist/org/migrations.js.map +1 -1
  302. package/dist/package-lifecycle/index.d.ts +2 -0
  303. package/dist/package-lifecycle/index.d.ts.map +1 -0
  304. package/dist/package-lifecycle/index.js +2 -0
  305. package/dist/package-lifecycle/index.js.map +1 -0
  306. package/dist/package-lifecycle/manifest.d.ts +24 -0
  307. package/dist/package-lifecycle/manifest.d.ts.map +1 -0
  308. package/dist/package-lifecycle/manifest.js +81 -0
  309. package/dist/package-lifecycle/manifest.js.map +1 -0
  310. package/dist/progress/routes.d.ts +1 -1
  311. package/dist/provider-api/custom-registry.d.ts +32 -1
  312. package/dist/provider-api/custom-registry.d.ts.map +1 -1
  313. package/dist/provider-api/custom-registry.js +41 -1
  314. package/dist/provider-api/custom-registry.js.map +1 -1
  315. package/dist/provider-api/index.d.ts +1 -1
  316. package/dist/provider-api/index.d.ts.map +1 -1
  317. package/dist/provider-api/index.js +1 -1
  318. package/dist/provider-api/index.js.map +1 -1
  319. package/dist/secrets/storage.d.ts.map +1 -1
  320. package/dist/secrets/storage.js +45 -27
  321. package/dist/secrets/storage.js.map +1 -1
  322. package/dist/server/action-discovery.d.ts.map +1 -1
  323. package/dist/server/action-discovery.js +4 -0
  324. package/dist/server/action-discovery.js.map +1 -1
  325. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  326. package/dist/server/agent-chat-plugin.js +47 -13
  327. package/dist/server/agent-chat-plugin.js.map +1 -1
  328. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  329. package/dist/server/core-routes-plugin.js +23 -12
  330. package/dist/server/core-routes-plugin.js.map +1 -1
  331. package/dist/server/csrf.d.ts.map +1 -1
  332. package/dist/server/csrf.js +18 -5
  333. package/dist/server/csrf.js.map +1 -1
  334. package/dist/server/framework-request-handler.d.ts.map +1 -1
  335. package/dist/server/framework-request-handler.js +34 -0
  336. package/dist/server/framework-request-handler.js.map +1 -1
  337. package/dist/server/google-realtime-session.d.ts.map +1 -1
  338. package/dist/server/google-realtime-session.js +2 -34
  339. package/dist/server/google-realtime-session.js.map +1 -1
  340. package/dist/server/poll.d.ts.map +1 -1
  341. package/dist/server/poll.js +24 -2
  342. package/dist/server/poll.js.map +1 -1
  343. package/dist/server/realtime-voice.d.ts.map +1 -1
  344. package/dist/server/realtime-voice.js +9 -0
  345. package/dist/server/realtime-voice.js.map +1 -1
  346. package/dist/server/request-origin.d.ts +10 -0
  347. package/dist/server/request-origin.d.ts.map +1 -0
  348. package/dist/server/request-origin.js +60 -0
  349. package/dist/server/request-origin.js.map +1 -0
  350. package/dist/server/transcribe-voice.d.ts.map +1 -1
  351. package/dist/server/transcribe-voice.js +2 -48
  352. package/dist/server/transcribe-voice.js.map +1 -1
  353. package/dist/templates/default/package.json +2 -2
  354. package/dist/templates/headless/package.json +0 -1
  355. package/dist/templates/workspace-core/.agents/skills/audit-log/SKILL.md +3 -0
  356. package/dist/templates/workspace-core/.agents/skills/automations/SKILL.md +1 -1
  357. package/dist/templates/workspace-core/package.json +0 -1
  358. package/dist/templates/workspace-root/package.json +0 -1
  359. package/dist/triggers/actions.d.ts.map +1 -1
  360. package/dist/triggers/actions.js +8 -3
  361. package/dist/triggers/actions.js.map +1 -1
  362. package/dist/triggers/types.d.ts +7 -1
  363. package/dist/triggers/types.d.ts.map +1 -1
  364. package/dist/triggers/types.js.map +1 -1
  365. package/docs/content/audit-log.mdx +2 -1
  366. package/docs/content/automations.mdx +7 -7
  367. package/docs/content/creating-templates.mdx +1 -1
  368. package/docs/content/internationalization.mdx +2 -1
  369. package/docs/content/locales/ar-SA/audit-log.mdx +2 -1
  370. package/docs/content/locales/ar-SA/automations.mdx +7 -7
  371. package/docs/content/locales/ar-SA/getting-started.mdx +7 -1
  372. package/docs/content/locales/ar-SA/internationalization.mdx +1 -1
  373. package/docs/content/locales/ar-SA/package-lifecycle.mdx +19 -0
  374. package/docs/content/locales/ar-SA/sandbox-adapters.mdx +18 -7
  375. package/docs/content/locales/ar-SA/security.mdx +8 -0
  376. package/docs/content/locales/de-DE/audit-log.mdx +2 -1
  377. package/docs/content/locales/de-DE/automations.mdx +7 -7
  378. package/docs/content/locales/de-DE/getting-started.mdx +7 -1
  379. package/docs/content/locales/de-DE/internationalization.mdx +1 -1
  380. package/docs/content/locales/de-DE/package-lifecycle.mdx +22 -0
  381. package/docs/content/locales/de-DE/sandbox-adapters.mdx +18 -7
  382. package/docs/content/locales/de-DE/security.mdx +8 -0
  383. package/docs/content/locales/es-ES/audit-log.mdx +2 -1
  384. package/docs/content/locales/es-ES/automations.mdx +7 -7
  385. package/docs/content/locales/es-ES/getting-started.mdx +7 -1
  386. package/docs/content/locales/es-ES/internationalization.mdx +1 -1
  387. package/docs/content/locales/es-ES/package-lifecycle.mdx +22 -0
  388. package/docs/content/locales/es-ES/sandbox-adapters.mdx +18 -7
  389. package/docs/content/locales/es-ES/security.mdx +8 -0
  390. package/docs/content/locales/fr-FR/audit-log.mdx +2 -1
  391. package/docs/content/locales/fr-FR/automations.mdx +7 -7
  392. package/docs/content/locales/fr-FR/getting-started.mdx +7 -1
  393. package/docs/content/locales/fr-FR/internationalization.mdx +1 -1
  394. package/docs/content/locales/fr-FR/package-lifecycle.mdx +21 -0
  395. package/docs/content/locales/fr-FR/sandbox-adapters.mdx +19 -8
  396. package/docs/content/locales/fr-FR/security.mdx +8 -0
  397. package/docs/content/locales/hi-IN/audit-log.mdx +2 -1
  398. package/docs/content/locales/hi-IN/automations.mdx +7 -7
  399. package/docs/content/locales/hi-IN/getting-started.mdx +7 -1
  400. package/docs/content/locales/hi-IN/internationalization.mdx +1 -1
  401. package/docs/content/locales/hi-IN/package-lifecycle.mdx +20 -0
  402. package/docs/content/locales/hi-IN/sandbox-adapters.mdx +18 -7
  403. package/docs/content/locales/hi-IN/security.mdx +8 -0
  404. package/docs/content/locales/ja-JP/audit-log.mdx +2 -1
  405. package/docs/content/locales/ja-JP/automations.mdx +7 -7
  406. package/docs/content/locales/ja-JP/getting-started.mdx +7 -1
  407. package/docs/content/locales/ja-JP/internationalization.mdx +1 -1
  408. package/docs/content/locales/ja-JP/package-lifecycle.mdx +21 -0
  409. package/docs/content/locales/ja-JP/sandbox-adapters.mdx +17 -6
  410. package/docs/content/locales/ja-JP/security.mdx +8 -0
  411. package/docs/content/locales/ko-KR/audit-log.mdx +2 -1
  412. package/docs/content/locales/ko-KR/automations.mdx +7 -7
  413. package/docs/content/locales/ko-KR/getting-started.mdx +7 -1
  414. package/docs/content/locales/ko-KR/internationalization.mdx +1 -1
  415. package/docs/content/locales/ko-KR/package-lifecycle.mdx +20 -0
  416. package/docs/content/locales/ko-KR/sandbox-adapters.mdx +17 -6
  417. package/docs/content/locales/ko-KR/security.mdx +8 -0
  418. package/docs/content/locales/pt-BR/audit-log.mdx +2 -1
  419. package/docs/content/locales/pt-BR/automations.mdx +7 -7
  420. package/docs/content/locales/pt-BR/getting-started.mdx +7 -1
  421. package/docs/content/locales/pt-BR/internationalization.mdx +1 -1
  422. package/docs/content/locales/pt-BR/package-lifecycle.mdx +21 -0
  423. package/docs/content/locales/pt-BR/sandbox-adapters.mdx +18 -7
  424. package/docs/content/locales/pt-BR/security.mdx +8 -0
  425. package/docs/content/locales/zh-CN/audit-log.mdx +2 -1
  426. package/docs/content/locales/zh-CN/automations.mdx +7 -7
  427. package/docs/content/locales/zh-CN/getting-started.mdx +6 -4
  428. package/docs/content/locales/zh-CN/internationalization.mdx +1 -1
  429. package/docs/content/locales/zh-CN/package-lifecycle.mdx +19 -0
  430. package/docs/content/locales/zh-CN/sandbox-adapters.mdx +17 -6
  431. package/docs/content/locales/zh-CN/security.mdx +8 -0
  432. package/docs/content/locales/zh-TW/audit-log.mdx +2 -1
  433. package/docs/content/locales/zh-TW/automations.mdx +7 -7
  434. package/docs/content/locales/zh-TW/getting-started.mdx +6 -4
  435. package/docs/content/locales/zh-TW/internationalization.mdx +1 -1
  436. package/docs/content/locales/zh-TW/package-lifecycle.mdx +19 -0
  437. package/docs/content/locales/zh-TW/sandbox-adapters.mdx +18 -7
  438. package/docs/content/locales/zh-TW/security.mdx +8 -0
  439. package/docs/content/package-lifecycle.mdx +51 -0
  440. package/docs/content/sandbox-adapters.mdx +16 -5
  441. package/package.json +10 -3
  442. package/src/templates/default/package.json +2 -2
  443. package/src/templates/headless/package.json +0 -1
  444. package/src/templates/workspace-core/.agents/skills/audit-log/SKILL.md +3 -0
  445. package/src/templates/workspace-core/.agents/skills/automations/SKILL.md +1 -1
  446. package/src/templates/workspace-core/package.json +0 -1
  447. package/src/templates/workspace-root/package.json +0 -1
  448. package/corpus/templates/slides/app/components/ui/toast.tsx +0 -1
  449. package/corpus/templates/slides/app/components/ui/toaster.tsx +0 -1
  450. package/corpus/templates/slides/app/hooks/use-toast.ts +0 -1
@@ -415,3 +415,11 @@ AGENT_NATIVE_KEYS_WORKSPACE_FALLBACK=1
415
415
  ```
416
416
 
417
417
  無論此標誌如何,工作空間範圍的秘密寫入仍然需要組織所有者/管理員角色。
418
+
419
+ ## 下一步
420
+
421
+ - [**Authentication**](/docs/authentication) — 本頁所依賴的驗證模式、cookie realm 和工作階段細節
422
+ - [**Multi-Tenancy**](/docs/multi-tenancy) — `org_id` 範圍界定背後的組織成員模型
423
+ - [**Sharing**](/docs/sharing) — 應用於可共用資源的 `ownableColumns()` 和存取守衛模式
424
+ - [**Messaging**](/docs/messaging#env-vars) — 上方清單中提到的每個整合的 webhook 簽名金鑰
425
+ - [**Deployment**](/docs/deployment) — 此清單假定已設定的正式環境變數
@@ -0,0 +1,51 @@
1
+ ---
2
+ title: Package Lifecycle
3
+ description: Inspect, add, and eject manifest-driven Agent Native packages safely.
4
+ ---
5
+
6
+ # Package lifecycle
7
+
8
+ Reusable Agent Native packages can publish a versioned static
9
+ `agent-native.package.json`. The CLI reads that JSON without executing package
10
+ code and reports the package's actions, schema entry point, skills, secret key
11
+ names, and peer providers.
12
+
13
+ ```bash
14
+ agent-native package inspect @agent-native/scheduling
15
+ agent-native package inspect @agent-native/scheduling --json
16
+ agent-native package add @agent-native/scheduling
17
+ agent-native package add @agent-native/scheduling --apply
18
+ agent-native package eject @agent-native/scheduling --apply
19
+ ```
20
+
21
+ `add` and `eject` are dry-run by default. `--apply` is required before the CLI
22
+ writes files or runs the detected package manager. Use `--root` for a different
23
+ project root; at a workspace root, pass `--app <name>` to select the target app.
24
+
25
+ ## Safety and idempotency
26
+
27
+ Before writing, the CLI resolves every contribution and refuses missing or
28
+ ambiguous layouts, existing files with different content, escaping manifest
29
+ paths, and eject targets that already exist. It stages the complete write set,
30
+ uses atomic renames, snapshots package and lock files, and rolls back if the
31
+ package-manager install fails. A provenance record under
32
+ `.agent-native/packages/` makes a repeated add a no-op when generated files are
33
+ unchanged.
34
+
35
+ Inspection and registry staging use static package metadata only. The CLI never
36
+ imports a package's JavaScript manifest and passes `--ignore-scripts` while
37
+ downloading an uninstalled package archive. Reports show credential key names,
38
+ never credential values.
39
+
40
+ ## Scheduling pilot
41
+
42
+ `@agent-native/scheduling` is the first package with the generic manifest. Add
43
+ creates action re-export stubs, adds the schema export, copies its agent skills,
44
+ records the dependency, and reports required secret names and providers.
45
+ Eject copies the published Scheduling source to `packages/scheduling`, switches
46
+ the dependency to `workspace:*`, and preserves canonical
47
+ `@agent-native/scheduling` imports so workspace resolution selects the local
48
+ copy.
49
+
50
+ Ejecting other packages, including Pinpoint, is intentionally refused until the
51
+ Scheduling pilot has proven the contract.
@@ -106,6 +106,10 @@ The seam lives in core at `packages/core/src/coding-tools/sandbox/` — `adapter
106
106
  path: "index.ts",
107
107
  note: "selection: getSandboxAdapter() / registerSandboxAdapter()",
108
108
  },
109
+ {
110
+ path: "background.ts",
111
+ note: "durable queue marker and background execution lifecycle",
112
+ },
109
113
  {
110
114
  path: "local-child-process-adapter.ts",
111
115
  note: "the default backend — locked-down Node child process",
@@ -189,12 +193,17 @@ registerSandboxAdapter(adapter) → AGENT_NATIVE_SANDBOX → local default
189
193
 
190
194
  #### `AGENT_NATIVE_SANDBOX` env var {#env}
191
195
 
192
- Selects a built-in adapter by id. Currently only `local` (the default) is wired; unknown values fall back to local rather than failing the run.
196
+ Selects a built-in adapter by id. Both `local` (the default) and `background` are wired; unknown values fall back to local rather than failing the run.
193
197
 
194
198
  ```bash
195
- AGENT_NATIVE_SANDBOX=local # the default — explicit
199
+ AGENT_NATIVE_SANDBOX=local # the default — explicit
200
+ AGENT_NATIVE_SANDBOX=background # enqueue every run-code call durably
196
201
  ```
197
202
 
203
+ `background` stores the raw code in `sandbox_executions` and returns an `executionId` with `status: "queued"` immediately. A signed self-dispatch starts a fresh serverless invocation; long-lived Node starts detached in-process work; status polling and the periodic sweep redrive lost dispatches or expired leases. Poll the execution later for its persisted result.
204
+
205
+ `BackgroundQueueAdapter` is a durable queue marker, not the executor. Queued work uses a registered non-queued execution adapter when one is available; otherwise it falls back to the local child process. Selecting `background` alone does not provide remote or container isolation, and it does not make an edge runtime compatible with `node:child_process`.
206
+
198
207
  #### `registerSandboxAdapter()` {#register}
199
208
 
200
209
  A host process overrides the backend for all subsequent `run-code` invocations through the seam's `index.ts` — for example, to run every call in a remote container:
@@ -219,13 +228,15 @@ registerSandboxAdapter(new RemoteSandboxAdapter());
219
228
 
220
229
  ### The seam for a durable runner {#durable}
221
230
 
222
- This interface is deliberately the seam for a future remote/durable sandbox. A remote or durable adapter (Docker, a Vercel-Sandbox-style runner, or a queued background worker) would:
231
+ The built-in `background` adapter already provides durable queuing and a fresh execution budget, while actual execution still uses a non-queued adapter or the local child-process fallback. A separately registered remote or isolated adapter (Docker or a Vercel-Sandbox-style runner) can provide a different execution boundary and can also execute per-call background work.
232
+
233
+ Such an adapter would:
223
234
 
224
235
  1. Implement `SandboxAdapter.run` against an out-of-process runtime.
225
236
  2. Tunnel the loopback bridge (or proxy bridge calls back to the parent).
226
- 3. Let large data jobs run to completion independently of the request lifecycle exceeding the hosted ~40s code-exec ceiling that bounds the local child-process adapter.
237
+ 3. Supply remote or container isolation independently of the shipped durable queue lifecycle.
227
238
 
228
- Register it under a new `AGENT_NATIVE_SANDBOX` value (e.g. `remote`) and/or via `registerSandboxAdapter()`. The agent loop and `run-code.ts` never change.
239
+ Register it programmatically via `registerSandboxAdapter()`. The agent loop and `run-code.ts` do not need to change.
229
240
 
230
241
  <Callout id="doc-block-adap1tip" tone="info">
231
242
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.96.0",
3
+ "version": "0.97.0",
4
4
  "description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -101,6 +101,10 @@
101
101
  "./shared": "./dist/shared/index.js",
102
102
  "./voice": "./dist/voice/index.js",
103
103
  "./scripts": "./dist/scripts/index.js",
104
+ "./guards": {
105
+ "types": "./dist/guards/index.d.ts",
106
+ "default": "./dist/guards/index.js"
107
+ },
104
108
  "./application-state": "./dist/application-state/index.js",
105
109
  "./settings": "./dist/settings/index.js",
106
110
  "./localization": "./dist/localization/index.js",
@@ -207,6 +211,10 @@
207
211
  "default": "./dist/local-artifacts/index.js"
208
212
  },
209
213
  "./workspace-files": "./dist/workspace-files/index.js",
214
+ "./package-lifecycle": {
215
+ "types": "./dist/package-lifecycle/index.d.ts",
216
+ "default": "./dist/package-lifecycle/index.js"
217
+ },
210
218
  "./code-agents": "./dist/code-agents/index.js",
211
219
  "./code-agents/transcript-normalizer": "./dist/code-agents/transcript-normalizer.js",
212
220
  "./workspace-connections": "./dist/workspace-connections/index.js",
@@ -373,7 +381,6 @@
373
381
  "react-dom": "^19.2.7",
374
382
  "react-router": "^8.1.0",
375
383
  "tailwindcss": "catalog:",
376
- "typescript": "catalog:",
377
384
  "typescript-7": "catalog:",
378
385
  "vite": "catalog:",
379
386
  "vitest": "^4.1.5",
@@ -31,3 +31,36 @@ export function hasConfiguredA2ASecret(): boolean {
31
31
  export function shouldAdvertiseJwtA2AAuth(): boolean {
32
32
  return hasConfiguredA2ASecret() || isA2AProductionRuntime();
33
33
  }
34
+
35
+ /**
36
+ * True only when unsigned internal self-dispatch is acceptable: no A2A_SECRET
37
+ * is configured AND we can positively identify a local/dev runtime. Everything
38
+ * else — production, or any UNRECOGNIZED deployed/networked host — must fail
39
+ * closed and require A2A_SECRET. `loopback` should be whether the inbound
40
+ * request arrived over the loopback interface (127.0.0.1/::1); callers that
41
+ * cannot determine the peer address pass `false`.
42
+ *
43
+ * NODE_ENV alone is deliberately NOT a trust grant: a self-hosted deployment
44
+ * that doesn't set NODE_ENV=production and isn't recognized by
45
+ * `isA2AProductionRuntime()` (a bare Docker/VPS/K8s pod) must still fail
46
+ * closed unless the request actually came from loopback or the explicit
47
+ * opt-in flag is set.
48
+ */
49
+ export function isTrustedLocalRuntime(opts: { loopback: boolean }): boolean {
50
+ if (isA2AProductionRuntime()) return false;
51
+ if (process.env.A2A_ALLOW_UNSIGNED_INTERNAL === "1") return true;
52
+ return opts.loopback === true;
53
+ }
54
+
55
+ /** True if a socket peer address is a loopback/local address. */
56
+ export function isLoopbackAddress(addr: string | undefined | null): boolean {
57
+ if (!addr) return false;
58
+ const a = addr.trim();
59
+ return (
60
+ a === "127.0.0.1" ||
61
+ a === "::1" ||
62
+ a === "::ffff:127.0.0.1" ||
63
+ a.startsWith("127.") ||
64
+ a === "localhost"
65
+ );
66
+ }
@@ -39,7 +39,7 @@
39
39
  */
40
40
  import {
41
41
  hasConfiguredA2ASecret,
42
- isA2AProductionRuntime,
42
+ isTrustedLocalRuntime,
43
43
  } from "../a2a/auth-policy.js";
44
44
  import {
45
45
  extractBearerToken,
@@ -469,10 +469,13 @@ export function extractProcessRunId(body: unknown): string | null {
469
469
  *
470
470
  * Auth policy mirrors the agent-teams processor exactly:
471
471
  * - `A2A_SECRET` set → require a valid `verifyInternalToken(runId, token)`.
472
- * - no secret but a production runtime refuse (503) never run unsigned in
473
- * prod.
474
- * - no secret + non-prod (local dev) allow unsigned; the SQL atomic claim
475
- * in the worker still prevents double-processing.
472
+ * - no secret → require `isTrustedLocalRuntime({ loopback })` (see
473
+ * auth-policy.ts): refuse (503) unless `A2A_ALLOW_UNSIGNED_INTERNAL=1` is
474
+ * set. This function has no h3 `event` of its own, so callers that CAN
475
+ * see the inbound socket peer (the route handler, which has the event)
476
+ * should compute `loopback` from it and pass it through; callers that
477
+ * can't determine the peer address should omit it (defaults to `false`
478
+ * — never trust unsigned dispatch without an explicit opt-in).
476
479
  *
477
480
  * Extracted from the route handler so the auth + marker-prep decision is unit
478
481
  * testable without booting the whole Nitro plugin. The route only adds body
@@ -481,6 +484,7 @@ export function extractProcessRunId(body: unknown): string | null {
481
484
  export function prepareProcessRunRequest(
482
485
  body: unknown,
483
486
  authHeader: string | undefined,
487
+ loopback: boolean = false,
484
488
  ): ProcessRunPreparation {
485
489
  if (!body || typeof body !== "object") {
486
490
  return {
@@ -514,12 +518,16 @@ export function prepareProcessRunRequest(
514
518
  runId,
515
519
  };
516
520
  }
517
- } else if (isA2AProductionRuntime()) {
521
+ } else if (!isTrustedLocalRuntime({ loopback })) {
522
+ // Callers that can see the h3 `event` (the route handler) pass the real
523
+ // loopback signal; callers without one default to non-loopback. Unsigned
524
+ // dispatch is still allowed via A2A_ALLOW_UNSIGNED_INTERNAL=1 for trusted
525
+ // local/dev setups; see auth-policy.ts `isTrustedLocalRuntime`.
518
526
  return {
519
527
  ok: false,
520
528
  status: 503,
521
529
  error:
522
- "Agent chat background processor not configured — set A2A_SECRET on this deployment.",
530
+ "Agent chat background processor not configured — set A2A_SECRET on this deployment (or A2A_ALLOW_UNSIGNED_INTERNAL=1 for trusted local dev).",
523
531
  runId,
524
532
  };
525
533
  }
@@ -1759,7 +1759,7 @@ export async function listRunsForThread(
1759
1759
  LIMIT ?`,
1760
1760
  args: [threadId, limit],
1761
1761
  });
1762
- let repairedTerminalRow = false;
1762
+ const reconcileCandidateIds: string[] = [];
1763
1763
  for (const r of rows) {
1764
1764
  const row = r as {
1765
1765
  id?: string;
@@ -1773,10 +1773,19 @@ export async function listRunsForThread(
1773
1773
  (row.status === "errored" &&
1774
1774
  row.error_code === STALE_RUN_ERROR_EVENT.errorCode);
1775
1775
  if (!canReconcileFromEvents) continue;
1776
- repairedTerminalRow =
1777
- (await reconcileTerminalRunFromEvents(runId).catch(() => false)) ||
1778
- repairedTerminalRow;
1776
+ reconcileCandidateIds.push(runId);
1779
1777
  }
1778
+ // Each candidate's reconciliation is independently fenced by the UPDATE's
1779
+ // WHERE clause (status = 'running' OR errored-with-stale-code) inside
1780
+ // reconcileTerminalRunFromEvents, keyed on that run's own id — reconciling
1781
+ // several stale runs in parallel is safe and avoids N sequential
1782
+ // SELECT+UPDATE round-trip pairs on a shared-thread page load.
1783
+ const reconcileResults = await Promise.all(
1784
+ reconcileCandidateIds.map((runId) =>
1785
+ reconcileTerminalRunFromEvents(runId).catch(() => false),
1786
+ ),
1787
+ );
1788
+ const repairedTerminalRow = reconcileResults.some(Boolean);
1780
1789
  if (repairedTerminalRow) {
1781
1790
  const refreshed = await client.execute({
1782
1791
  sql: `SELECT id, thread_id, turn_id, status, started_at, heartbeat_at, completed_at, last_progress_at, error_code, abort_reason, dispatch_mode, terminal_reason, diag_stage
@@ -0,0 +1,162 @@
1
+ import { z } from "zod";
2
+
3
+ import { defineAction } from "../../action.js";
4
+ import { MAX_LIMIT, queryAuditEvents } from "../store.js";
5
+ import type { AuditEvent } from "../types.js";
6
+
7
+ const DEFAULT_MAX_ROWS = 5000;
8
+ const HARD_CAP_ROWS = 10000;
9
+
10
+ // Deterministic column order for CSV — mirrors the store's list projection
11
+ // (`LIST_COLUMNS`), which deliberately excludes `input` so a bulk export
12
+ // never streams every event's (redacted) request body at once. Future
13
+ // columns added to the audit store must be reflected here too.
14
+ const CSV_COLUMNS: Array<[key: keyof AuditEvent, header: string]> = [
15
+ ["id", "id"],
16
+ ["createdAt", "created_at"],
17
+ ["action", "action"],
18
+ ["caller", "caller"],
19
+ ["actorKind", "actor_kind"],
20
+ ["actorEmail", "actor_email"],
21
+ ["orgId", "org_id"],
22
+ ["threadId", "thread_id"],
23
+ ["turnId", "turn_id"],
24
+ ["targetType", "target_type"],
25
+ ["targetId", "target_id"],
26
+ ["status", "status"],
27
+ ["summary", "summary"],
28
+ ["errorCode", "error_code"],
29
+ ["ownerEmail", "owner_email"],
30
+ ["visibility", "visibility"],
31
+ ];
32
+
33
+ /** Hand-rolled CSV field escaper — quotes a field when it contains a comma,
34
+ * quote, or newline, doubling any embedded quotes. No dependency needed for
35
+ * ~10 lines of RFC 4180 escaping. */
36
+ function csvField(value: unknown): string {
37
+ if (value === null || value === undefined) return "";
38
+ const raw = String(value);
39
+ if (/[",\n\r]/.test(raw)) {
40
+ return `"${raw.replace(/"/g, '""')}"`;
41
+ }
42
+ return raw;
43
+ }
44
+
45
+ function toCsv(events: AuditEvent[]): string {
46
+ const header = CSV_COLUMNS.map(([, label]) => label).join(",");
47
+ const rows = events.map((event) =>
48
+ CSV_COLUMNS.map(([key]) => csvField(event[key])).join(","),
49
+ );
50
+ return [header, ...rows].join("\n");
51
+ }
52
+
53
+ function toNdjson(events: AuditEvent[]): string {
54
+ return events.map((event) => JSON.stringify(event)).join("\n");
55
+ }
56
+
57
+ /**
58
+ * Bulk-export audit-log events as CSV or NDJSON — the "bulk export" sensitive
59
+ * read the audit doc itself names. Pages past the per-call row clamp
60
+ * (`queryAuditEvents`'s `MAX_LIMIT`) up to `maxRows`, scoped in SQL to the
61
+ * caller's identity exactly like `list-audit-events`. Read-only; never
62
+ * exposes other tenants' rows.
63
+ */
64
+ export default defineAction({
65
+ description:
66
+ "Export audit-log events as a CSV or NDJSON document for offline/compliance pulls (up to maxRows, default 5000, hard cap 10000). Use this instead of hand-paging list-audit-events when you need a bulk download of the trail; use list-audit-events instead for browsing recent activity or answering 'what changed'.",
67
+ schema: z.object({
68
+ targetType: z
69
+ .string()
70
+ .optional()
71
+ .describe("Filter to one resource type, e.g. 'recording'."),
72
+ targetId: z
73
+ .string()
74
+ .optional()
75
+ .describe("Filter to one resource id (pair with targetType)."),
76
+ actorKind: z
77
+ .enum(["agent", "human", "system"])
78
+ .optional()
79
+ .describe("Filter to changes made by the agent, a human, or the system."),
80
+ actorEmail: z.string().optional().describe("Filter to one actor's email."),
81
+ status: z
82
+ .enum(["success", "error", "denied"])
83
+ .optional()
84
+ .describe("Filter by outcome."),
85
+ threadId: z.string().optional().describe("Filter to one agent thread."),
86
+ turnId: z
87
+ .string()
88
+ .optional()
89
+ .describe("Filter to one agent turn (a single agent response)."),
90
+ action: z.string().optional().describe("Filter to one action name."),
91
+ sinceMs: z
92
+ .number()
93
+ .optional()
94
+ .describe("Only events at or after this Unix epoch (ms)."),
95
+ format: z
96
+ .enum(["csv", "ndjson"])
97
+ .default("csv")
98
+ .describe(
99
+ "Export format — CSV with a header row, or one JSON event per line.",
100
+ ),
101
+ maxRows: z
102
+ .number()
103
+ .optional()
104
+ .describe("Max rows to export (default 5000, hard cap 10000)."),
105
+ }),
106
+ http: { method: "GET" },
107
+ audit: {
108
+ // Read-only actions are skipped by default — this is exactly the
109
+ // "bulk export" sensitive read the framework's own audit doc calls out.
110
+ onRead: true,
111
+ summary: (args) =>
112
+ `Bulk export of audit events (${(args as { format?: string }).format ?? "csv"})`,
113
+ },
114
+ run: async (args, ctx) => {
115
+ const scope = { userEmail: ctx?.userEmail, orgId: ctx?.orgId ?? null };
116
+ const cap = Math.min(
117
+ Math.max(1, Math.floor(args.maxRows ?? DEFAULT_MAX_ROWS)),
118
+ HARD_CAP_ROWS,
119
+ );
120
+
121
+ const filters = {
122
+ ...(args.targetType ? { targetType: args.targetType } : {}),
123
+ ...(args.targetId ? { targetId: args.targetId } : {}),
124
+ ...(args.actorKind ? { actorKind: args.actorKind } : {}),
125
+ ...(args.actorEmail ? { actorEmail: args.actorEmail } : {}),
126
+ ...(args.status ? { status: args.status } : {}),
127
+ ...(args.threadId ? { threadId: args.threadId } : {}),
128
+ ...(args.turnId ? { turnId: args.turnId } : {}),
129
+ ...(args.action ? { action: args.action } : {}),
130
+ ...(typeof args.sinceMs === "number" ? { sinceMs: args.sinceMs } : {}),
131
+ };
132
+
133
+ const events: AuditEvent[] = [];
134
+ let offset = 0;
135
+ while (events.length < cap) {
136
+ const pageLimit = Math.min(MAX_LIMIT, cap - events.length);
137
+ const page = await queryAuditEvents(scope, {
138
+ ...filters,
139
+ limit: pageLimit,
140
+ offset,
141
+ });
142
+ events.push(...page);
143
+ offset += page.length;
144
+ if (page.length < pageLimit) break; // exhausted — no more matching rows
145
+ }
146
+
147
+ // We stopped because we hit the cap, not because we ran out of rows —
148
+ // probe one more row to know whether the export was actually truncated.
149
+ let truncated = false;
150
+ if (events.length >= cap) {
151
+ const probe = await queryAuditEvents(scope, {
152
+ ...filters,
153
+ limit: 1,
154
+ offset,
155
+ });
156
+ truncated = probe.length > 0;
157
+ }
158
+
159
+ const content = args.format === "ndjson" ? toNdjson(events) : toCsv(events);
160
+ return { content, rowCount: events.length, truncated, format: args.format };
161
+ },
162
+ });
@@ -250,7 +250,9 @@ function scopeClause(scope: AuditReadScope): { sql: string; args: any[] } {
250
250
  return { sql: `(${clauses.join(" OR ")})`, args };
251
251
  }
252
252
 
253
- const MAX_LIMIT = 500;
253
+ // Exported so callers that must page past a single call (e.g.
254
+ // `export-audit-events`) can mirror the clamp instead of guessing it.
255
+ export const MAX_LIMIT = 500;
254
256
  const DEFAULT_LIMIT = 100;
255
257
 
256
258
  // Columns returned by the list surface — deliberately EXCLUDES `input` so a
@@ -297,13 +299,16 @@ export async function queryAuditEvents(
297
299
  Math.max(1, Math.floor(filters.limit ?? DEFAULT_LIMIT)),
298
300
  MAX_LIMIT,
299
301
  );
302
+ // 0-based, default-compatible: existing callers that never pass `offset`
303
+ // keep selecting from the top of the ordered result set.
304
+ const offset = Math.max(0, Math.floor(filters.offset ?? 0));
300
305
 
301
306
  const result = await client.execute({
302
307
  sql: `SELECT ${LIST_COLUMNS} FROM agent_audit_log
303
308
  WHERE ${where.join(" AND ")}
304
309
  ORDER BY created_at DESC
305
- LIMIT ?`,
306
- args: [...args, limit],
310
+ LIMIT ? OFFSET ?`,
311
+ args: [...args, limit, offset],
307
312
  });
308
313
  return (result.rows ?? []).map(mapRow);
309
314
  }
@@ -135,4 +135,7 @@ export interface AuditQueryFilters {
135
135
  sourcePlatform?: string;
136
136
  sinceMs?: number;
137
137
  limit?: number;
138
+ /** Skip this many matching rows before applying `limit` (0-based). Used by
139
+ * `export-audit-events` to page past the per-call `MAX_LIMIT` clamp. */
140
+ offset?: number;
138
141
  }