@agent-native/core 0.95.1 → 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 (655) hide show
  1. package/README.md +6 -0
  2. package/corpus/README.md +2 -2
  3. package/corpus/core/CHANGELOG.md +64 -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 +11 -2
  81. package/corpus/core/src/a2a/auth-policy.ts +33 -0
  82. package/corpus/core/src/a2a/client.ts +11 -1
  83. package/corpus/core/src/agent/durable-background.ts +15 -7
  84. package/corpus/core/src/agent/production-agent.ts +87 -27
  85. package/corpus/core/src/agent/run-store.ts +13 -4
  86. package/corpus/core/src/agent/thread-data-builder.ts +7 -5
  87. package/corpus/core/src/audit/actions/export-audit-events.ts +162 -0
  88. package/corpus/core/src/audit/store.ts +8 -3
  89. package/corpus/core/src/audit/types.ts +3 -0
  90. package/corpus/core/src/chat-threads/store.ts +20 -1
  91. package/corpus/core/src/cli/code-agent-executor.ts +1 -0
  92. package/corpus/core/src/cli/code-agent-runs.ts +14 -0
  93. package/corpus/core/src/cli/doctor.ts +396 -0
  94. package/corpus/core/src/cli/index.ts +56 -0
  95. package/corpus/core/src/cli/info.ts +3 -3
  96. package/corpus/core/src/cli/package-lifecycle.ts +821 -0
  97. package/corpus/core/src/client/AgentPanel.tsx +32 -25
  98. package/corpus/core/src/client/AssistantChat.tsx +36 -20
  99. package/corpus/core/src/client/MultiTabAssistantChat.tsx +141 -90
  100. package/corpus/core/src/client/agent-chat-adapter.ts +9 -9
  101. package/corpus/core/src/client/chat/ChatHistoryList.tsx +404 -0
  102. package/corpus/core/src/client/chat/index.ts +6 -0
  103. package/corpus/core/src/client/chat/tool-call-display.tsx +37 -3
  104. package/corpus/core/src/client/code-agent-chat-adapter.ts +72 -4
  105. package/corpus/core/src/client/composer/RealtimeVoiceMode.tsx +52 -11
  106. package/corpus/core/src/client/composer/TiptapComposer.tsx +157 -20
  107. package/corpus/core/src/client/composer/VoiceButton.tsx +28 -0
  108. package/corpus/core/src/client/composer/useRealtimeVoiceMode.tsx +5 -0
  109. package/corpus/core/src/client/conversation/code-agent-transcript.ts +4 -5
  110. package/corpus/core/src/client/guided-questions.tsx +2 -1
  111. package/corpus/core/src/client/index.ts +11 -0
  112. package/corpus/core/src/client/use-chat-threads.ts +10 -1
  113. package/corpus/core/src/client/voice-provider-status.ts +44 -0
  114. package/corpus/core/src/code-agents/transcript-normalizer.ts +76 -0
  115. package/corpus/core/src/deploy/build.ts +12 -11
  116. package/corpus/core/src/guards/db-tool-scoping.ts +129 -0
  117. package/corpus/core/src/guards/index.ts +23 -0
  118. package/corpus/core/src/guards/no-drizzle-push.ts +116 -0
  119. package/corpus/core/src/guards/no-env-credentials.ts +229 -0
  120. package/corpus/core/src/guards/no-env-mutation.ts +114 -0
  121. package/corpus/core/src/guards/no-localhost-fallback.ts +124 -0
  122. package/corpus/core/src/guards/no-unscoped-credentials.ts +227 -0
  123. package/corpus/core/src/guards/no-unscoped-queries.ts +834 -0
  124. package/corpus/core/src/guards/scan-utils.ts +105 -0
  125. package/corpus/core/src/guards/types.ts +30 -0
  126. package/corpus/core/src/integrations/a2a-continuation-processor.ts +35 -5
  127. package/corpus/core/src/integrations/adapters/slack.ts +74 -21
  128. package/corpus/core/src/integrations/webhook-handler.ts +14 -0
  129. package/corpus/core/src/localization/default-messages.ts +6 -0
  130. package/corpus/core/src/observability/hosted-model-experiment.ts +118 -0
  131. package/corpus/core/src/observability/routes.ts +17 -0
  132. package/corpus/core/src/observability/store.ts +4 -1
  133. package/corpus/core/src/observability/traces.ts +41 -2
  134. package/corpus/core/src/org/accept-pending.ts +9 -1
  135. package/corpus/core/src/org/migrations.ts +41 -0
  136. package/corpus/core/src/package-lifecycle/index.ts +1 -0
  137. package/corpus/core/src/package-lifecycle/manifest.ts +120 -0
  138. package/corpus/core/src/provider-api/custom-registry.ts +56 -0
  139. package/corpus/core/src/provider-api/index.ts +2 -0
  140. package/corpus/core/src/scripts/agent-engines/list-agent-engines.ts +19 -1
  141. package/corpus/core/src/scripts/call-agent.ts +53 -3
  142. package/corpus/core/src/scripts/chat/search-chats.ts +11 -8
  143. package/corpus/core/src/secrets/register-framework-secrets.ts +1 -1
  144. package/corpus/core/src/secrets/storage.ts +47 -27
  145. package/corpus/core/src/server/action-discovery.ts +4 -0
  146. package/corpus/core/src/server/agent-chat-plugin.ts +95 -18
  147. package/corpus/core/src/server/core-routes-plugin.ts +45 -14
  148. package/corpus/core/src/server/csrf.ts +24 -5
  149. package/corpus/core/src/server/framework-request-handler.ts +34 -0
  150. package/corpus/core/src/server/google-realtime-session.ts +1 -36
  151. package/corpus/core/src/server/poll.ts +24 -2
  152. package/corpus/core/src/server/realtime-voice.ts +80 -24
  153. package/corpus/core/src/server/request-origin.ts +63 -0
  154. package/corpus/core/src/server/transcribe-voice.ts +1 -50
  155. package/corpus/core/src/server/voice-providers-status.ts +4 -3
  156. package/corpus/core/src/shared/cache-control.ts +2 -8
  157. package/corpus/core/src/styles/agent-native.css +1 -0
  158. package/corpus/core/src/styles/chat-history-list.css +313 -0
  159. package/corpus/core/src/templates/default/package.json +2 -2
  160. package/corpus/core/src/templates/headless/package.json +0 -1
  161. package/corpus/core/src/templates/workspace-core/.agents/skills/audit-log/SKILL.md +3 -0
  162. package/corpus/core/src/templates/workspace-core/.agents/skills/automations/SKILL.md +1 -1
  163. package/corpus/core/src/templates/workspace-core/.agents/skills/observability/SKILL.md +20 -0
  164. package/corpus/core/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +8 -4
  165. package/corpus/core/src/templates/workspace-core/package.json +0 -1
  166. package/corpus/core/src/templates/workspace-root/package.json +0 -1
  167. package/corpus/core/src/triggers/actions.ts +11 -3
  168. package/corpus/core/src/triggers/types.ts +7 -1
  169. package/corpus/core/src/vite/client.ts +1 -0
  170. package/corpus/templates/analytics/AGENTS.md +7 -0
  171. package/corpus/templates/analytics/actions/bigquery.ts +26 -2
  172. package/corpus/templates/analytics/actions/compose-dashboard.ts +65 -37
  173. package/corpus/templates/analytics/actions/data-source-status.ts +18 -0
  174. package/corpus/templates/analytics/actions/mutate-dashboard.ts +73 -24
  175. package/corpus/templates/analytics/actions/reorder-dashboard-panels.ts +16 -13
  176. package/corpus/templates/analytics/actions/update-dashboard.ts +53 -42
  177. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +5 -4
  178. package/corpus/templates/analytics/app/global.css +10 -0
  179. package/corpus/templates/analytics/app/pages/Ask.tsx +25 -2
  180. package/corpus/templates/analytics/changelog/2026-07-10-analytics-answers-simple-time-bounded-metrics-without-unnece.md +6 -0
  181. package/corpus/templates/analytics/changelog/2026-07-10-analytics-chat-reliably-uses-connected-data-sources-across-s.md +6 -0
  182. package/corpus/templates/analytics/changelog/2026-07-10-chat-threads-now-stay-clear-of-top-actions-and-fade-smoothly.md +6 -0
  183. package/corpus/templates/analytics/changelog/2026-07-10-context-chips-can-now-be-selected-and-removed-one-at-a-time-.md +6 -0
  184. package/corpus/templates/analytics/changelog/2026-07-10-dashboard-edits-from-the-agent-and-the-ui-at-the-same-time-n.md +6 -0
  185. package/corpus/templates/analytics/changelog/2026-07-10-the-ask-composer-no-longer-carries-dashboard-or-panel-contex.md +6 -0
  186. package/corpus/templates/analytics/changelog/2026-07-10-the-ask-section-stays-highlighted-while-its-chat-history-is-.md +6 -0
  187. package/corpus/templates/analytics/changelog/2026-07-10-timed-out-bigquery-jobs-are-now-cancelled-so-they-stop-consu.md +6 -0
  188. package/corpus/templates/analytics/package.json +1 -2
  189. package/corpus/templates/analytics/server/lib/bigquery.ts +91 -14
  190. package/corpus/templates/analytics/server/lib/dashboards-store.ts +154 -11
  191. package/corpus/templates/analytics/server/plugins/agent-chat.ts +82 -7
  192. package/corpus/templates/assets/package.json +1 -2
  193. package/corpus/templates/brain/package.json +1 -2
  194. package/corpus/templates/calendar/package.json +1 -2
  195. package/corpus/templates/chat/package.json +1 -2
  196. package/corpus/templates/clips/changelog/2026-07-10-atomic-view-tracking.md +6 -0
  197. package/corpus/templates/clips/chrome-extension/package.json +3 -2
  198. package/corpus/templates/clips/desktop/package.json +6 -4
  199. package/corpus/templates/clips/desktop/src/lib/recorder.ts +26 -13
  200. package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +4 -1
  201. package/corpus/templates/clips/package.json +1 -2
  202. package/corpus/templates/clips/server/db/schema.ts +29 -17
  203. package/corpus/templates/clips/server/plugins/db.ts +8 -0
  204. package/corpus/templates/clips/server/routes/api/view-event.post.ts +260 -105
  205. package/corpus/templates/content/.agents/skills/notion-integration/SKILL.md +16 -0
  206. package/corpus/templates/content/AGENTS.md +72 -62
  207. package/corpus/templates/content/actions/_content-database-source-adapters.ts +84 -0
  208. package/corpus/templates/content/actions/_database-source-utils.ts +206 -96
  209. package/corpus/templates/content/actions/_notion-database-source-adapter.ts +216 -0
  210. package/corpus/templates/content/actions/_position-utils.ts +76 -0
  211. package/corpus/templates/content/actions/_property-utils.ts +31 -20
  212. package/corpus/templates/content/actions/add-database-item.ts +52 -39
  213. package/corpus/templates/content/actions/attach-content-database-source.ts +95 -11
  214. package/corpus/templates/content/actions/change-content-database-source-role.ts +24 -1
  215. package/corpus/templates/content/actions/configure-document-property.ts +36 -27
  216. package/corpus/templates/content/actions/create-content-database.ts +40 -30
  217. package/corpus/templates/content/actions/create-document.ts +39 -32
  218. package/corpus/templates/content/actions/duplicate-document-property.ts +37 -28
  219. package/corpus/templates/content/actions/list-notion-database-sources.ts +80 -0
  220. package/corpus/templates/content/actions/move-document.ts +64 -48
  221. package/corpus/templates/content/actions/refresh-content-database-source.ts +42 -3
  222. package/corpus/templates/content/actions/share-local-file-document.ts +36 -27
  223. package/corpus/templates/content/actions/suggest-source-join-key.ts +39 -16
  224. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +89 -23
  225. package/corpus/templates/content/app/components/editor/database/settings.tsx +1 -1
  226. package/corpus/templates/content/app/hooks/use-content-database.ts +18 -1
  227. package/corpus/templates/content/app/i18n/zh-TW.ts +4 -0
  228. package/corpus/templates/content/app/i18n-data.ts +40 -0
  229. package/corpus/templates/content/changelog/2026-07-10-failed-row-creation-and-source-attach-now-show-an-error-inst.md +6 -0
  230. package/corpus/templates/content/changelog/2026-07-10-items-added-at-the-same-time-no-longer-end-up-with-identical.md +6 -0
  231. package/corpus/templates/content/changelog/2026-07-10-notion-databases-can-add-read-only-details-to-content-tables.md +6 -0
  232. package/corpus/templates/content/package.json +1 -2
  233. package/corpus/templates/content/parity/matrix.md +25 -25
  234. package/corpus/templates/content/parity/matrix.ts +1 -0
  235. package/corpus/templates/content/server/routes/api/documents/[id]/move.patch.ts +43 -26
  236. package/corpus/templates/content/shared/api.ts +16 -1
  237. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +8 -4
  238. package/corpus/templates/design/AGENTS.md +12 -2
  239. package/corpus/templates/design/DEVELOPING.md +10 -6
  240. package/corpus/templates/design/actions/apply-visual-edit.ts +191 -6
  241. package/corpus/templates/design/actions/duplicate-design.ts +31 -25
  242. package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +5 -1
  243. package/corpus/templates/design/changelog/2026-07-10-duplicating-a-design-can-no-longer-produce-a-copy-with-missi.md +6 -0
  244. package/corpus/templates/design/changelog/2026-07-10-local-visual-edits-can-now-save-safe-leaf-text-class-and.md +6 -0
  245. package/corpus/templates/design/package.json +1 -1
  246. package/corpus/templates/design/shared/local-jsx-visual-edit.ts +388 -0
  247. package/corpus/templates/dispatch/package.json +1 -2
  248. package/corpus/templates/forms/actions/patch-form-fields.ts +82 -44
  249. package/corpus/templates/forms/changelog/2026-07-10-simultaneous-edits-to-different-form-fields-no-longer-overwr.md +6 -0
  250. package/corpus/templates/forms/package.json +1 -2
  251. package/corpus/templates/macros/package.json +1 -2
  252. package/corpus/templates/mail/app/components/email/EmailThread.tsx +3 -1
  253. package/corpus/templates/mail/changelog/2026-07-10-fixed-calendar-rsvp-buttons-in-emails-firing-duplicate-respo.md +6 -0
  254. package/corpus/templates/mail/package.json +1 -2
  255. package/corpus/templates/plan/actions/restore-plan-version.ts +126 -96
  256. package/corpus/templates/plan/changelog/2026-07-10-restoring-a-plan-version-can-no-longer-leave-a-plan-half-res.md +6 -0
  257. package/corpus/templates/plan/package.json +1 -2
  258. package/corpus/templates/plan/server/plans.ts +9 -2
  259. package/corpus/templates/slides/actions/list-decks.ts +28 -0
  260. package/corpus/templates/slides/app/components/deck/MermaidRenderer.tsx +41 -26
  261. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +4 -8
  262. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +2 -4
  263. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +4 -8
  264. package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +5 -12
  265. package/corpus/templates/slides/app/components/editor/HistoryPanel.tsx +3 -6
  266. package/corpus/templates/slides/app/components/editor/ImageDropPromptPopover.tsx +3 -6
  267. package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +2 -5
  268. package/corpus/templates/slides/app/context/DeckContext.tsx +47 -4
  269. package/corpus/templates/slides/app/pages/DeckEditor.tsx +11 -30
  270. package/corpus/templates/slides/app/pages/Index.tsx +2 -3
  271. package/corpus/templates/slides/app/root.tsx +0 -5
  272. package/corpus/templates/slides/changelog/2026-07-10-deck-lists-load-much-faster-and-no-longer-re-download-slide-.md +6 -0
  273. package/corpus/templates/slides/package.json +1 -2
  274. package/dist/a2a/auth-policy.d.ts +19 -0
  275. package/dist/a2a/auth-policy.d.ts.map +1 -1
  276. package/dist/a2a/auth-policy.js +32 -0
  277. package/dist/a2a/auth-policy.js.map +1 -1
  278. package/dist/a2a/client.d.ts +7 -0
  279. package/dist/a2a/client.d.ts.map +1 -1
  280. package/dist/a2a/client.js +2 -1
  281. package/dist/a2a/client.js.map +1 -1
  282. package/dist/agent/durable-background.d.ts +8 -5
  283. package/dist/agent/durable-background.d.ts.map +1 -1
  284. package/dist/agent/durable-background.js +15 -8
  285. package/dist/agent/durable-background.js.map +1 -1
  286. package/dist/agent/production-agent.d.ts +6 -0
  287. package/dist/agent/production-agent.d.ts.map +1 -1
  288. package/dist/agent/production-agent.js +63 -26
  289. package/dist/agent/production-agent.js.map +1 -1
  290. package/dist/agent/run-store.d.ts.map +1 -1
  291. package/dist/agent/run-store.js +9 -4
  292. package/dist/agent/run-store.js.map +1 -1
  293. package/dist/agent/thread-data-builder.d.ts +1 -0
  294. package/dist/agent/thread-data-builder.d.ts.map +1 -1
  295. package/dist/agent/thread-data-builder.js +6 -5
  296. package/dist/agent/thread-data-builder.js.map +1 -1
  297. package/dist/audit/actions/export-audit-events.d.ts +27 -0
  298. package/dist/audit/actions/export-audit-events.d.ts.map +1 -0
  299. package/dist/audit/actions/export-audit-events.js +144 -0
  300. package/dist/audit/actions/export-audit-events.js.map +1 -0
  301. package/dist/audit/store.d.ts +1 -0
  302. package/dist/audit/store.d.ts.map +1 -1
  303. package/dist/audit/store.js +8 -3
  304. package/dist/audit/store.js.map +1 -1
  305. package/dist/audit/types.d.ts +3 -0
  306. package/dist/audit/types.d.ts.map +1 -1
  307. package/dist/audit/types.js.map +1 -1
  308. package/dist/chat-threads/store.d.ts +10 -0
  309. package/dist/chat-threads/store.d.ts.map +1 -1
  310. package/dist/chat-threads/store.js +6 -0
  311. package/dist/chat-threads/store.js.map +1 -1
  312. package/dist/cli/code-agent-executor.d.ts.map +1 -1
  313. package/dist/cli/code-agent-executor.js +1 -0
  314. package/dist/cli/code-agent-executor.js.map +1 -1
  315. package/dist/cli/code-agent-runs.d.ts +12 -0
  316. package/dist/cli/code-agent-runs.d.ts.map +1 -1
  317. package/dist/cli/code-agent-runs.js +1 -0
  318. package/dist/cli/code-agent-runs.js.map +1 -1
  319. package/dist/cli/doctor.d.ts +83 -0
  320. package/dist/cli/doctor.d.ts.map +1 -0
  321. package/dist/cli/doctor.js +277 -0
  322. package/dist/cli/doctor.js.map +1 -0
  323. package/dist/cli/index.js +50 -0
  324. package/dist/cli/index.js.map +1 -1
  325. package/dist/cli/info.js +3 -3
  326. package/dist/cli/info.js.map +1 -1
  327. package/dist/cli/package-lifecycle.d.ts +50 -0
  328. package/dist/cli/package-lifecycle.d.ts.map +1 -0
  329. package/dist/cli/package-lifecycle.js +560 -0
  330. package/dist/cli/package-lifecycle.js.map +1 -0
  331. package/dist/client/AgentPanel.d.ts.map +1 -1
  332. package/dist/client/AgentPanel.js +3 -3
  333. package/dist/client/AgentPanel.js.map +1 -1
  334. package/dist/client/AssistantChat.d.ts +11 -0
  335. package/dist/client/AssistantChat.d.ts.map +1 -1
  336. package/dist/client/AssistantChat.js +7 -4
  337. package/dist/client/AssistantChat.js.map +1 -1
  338. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  339. package/dist/client/MultiTabAssistantChat.js +83 -10
  340. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  341. package/dist/client/agent-chat-adapter.js +7 -3
  342. package/dist/client/agent-chat-adapter.js.map +1 -1
  343. package/dist/client/chat/ChatHistoryList.d.ts +88 -0
  344. package/dist/client/chat/ChatHistoryList.d.ts.map +1 -0
  345. package/dist/client/chat/ChatHistoryList.js +83 -0
  346. package/dist/client/chat/ChatHistoryList.js.map +1 -0
  347. package/dist/client/chat/index.d.ts +1 -0
  348. package/dist/client/chat/index.d.ts.map +1 -1
  349. package/dist/client/chat/index.js +1 -0
  350. package/dist/client/chat/index.js.map +1 -1
  351. package/dist/client/chat/tool-call-display.d.ts +13 -1
  352. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  353. package/dist/client/chat/tool-call-display.js +10 -2
  354. package/dist/client/chat/tool-call-display.js.map +1 -1
  355. package/dist/client/code-agent-chat-adapter.d.ts +17 -1
  356. package/dist/client/code-agent-chat-adapter.d.ts.map +1 -1
  357. package/dist/client/code-agent-chat-adapter.js +47 -3
  358. package/dist/client/code-agent-chat-adapter.js.map +1 -1
  359. package/dist/client/composer/RealtimeVoiceMode.d.ts +11 -1
  360. package/dist/client/composer/RealtimeVoiceMode.d.ts.map +1 -1
  361. package/dist/client/composer/RealtimeVoiceMode.js +5 -3
  362. package/dist/client/composer/RealtimeVoiceMode.js.map +1 -1
  363. package/dist/client/composer/TiptapComposer.d.ts +25 -2
  364. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  365. package/dist/client/composer/TiptapComposer.js +96 -5
  366. package/dist/client/composer/TiptapComposer.js.map +1 -1
  367. package/dist/client/composer/VoiceButton.d.ts.map +1 -1
  368. package/dist/client/composer/VoiceButton.js +21 -1
  369. package/dist/client/composer/VoiceButton.js.map +1 -1
  370. package/dist/client/composer/useRealtimeVoiceMode.d.ts.map +1 -1
  371. package/dist/client/composer/useRealtimeVoiceMode.js +5 -0
  372. package/dist/client/composer/useRealtimeVoiceMode.js.map +1 -1
  373. package/dist/client/conversation/code-agent-transcript.d.ts +2 -0
  374. package/dist/client/conversation/code-agent-transcript.d.ts.map +1 -1
  375. package/dist/client/conversation/code-agent-transcript.js +3 -5
  376. package/dist/client/conversation/code-agent-transcript.js.map +1 -1
  377. package/dist/client/guided-questions.d.ts.map +1 -1
  378. package/dist/client/guided-questions.js +2 -1
  379. package/dist/client/guided-questions.js.map +1 -1
  380. package/dist/client/index.d.ts +3 -1
  381. package/dist/client/index.d.ts.map +1 -1
  382. package/dist/client/index.js +3 -1
  383. package/dist/client/index.js.map +1 -1
  384. package/dist/client/use-chat-threads.d.ts.map +1 -1
  385. package/dist/client/use-chat-threads.js +9 -1
  386. package/dist/client/use-chat-threads.js.map +1 -1
  387. package/dist/client/voice-provider-status.d.ts +10 -0
  388. package/dist/client/voice-provider-status.d.ts.map +1 -0
  389. package/dist/client/voice-provider-status.js +32 -0
  390. package/dist/client/voice-provider-status.js.map +1 -0
  391. package/dist/code-agents/transcript-normalizer.d.ts +29 -0
  392. package/dist/code-agents/transcript-normalizer.d.ts.map +1 -1
  393. package/dist/code-agents/transcript-normalizer.js +55 -0
  394. package/dist/code-agents/transcript-normalizer.js.map +1 -1
  395. package/dist/collab/routes.d.ts +1 -1
  396. package/dist/deploy/build.d.ts.map +1 -1
  397. package/dist/deploy/build.js +13 -11
  398. package/dist/deploy/build.js.map +1 -1
  399. package/dist/guards/db-tool-scoping.d.ts +38 -0
  400. package/dist/guards/db-tool-scoping.d.ts.map +1 -0
  401. package/dist/guards/db-tool-scoping.js +114 -0
  402. package/dist/guards/db-tool-scoping.js.map +1 -0
  403. package/dist/guards/index.d.ts +23 -0
  404. package/dist/guards/index.d.ts.map +1 -0
  405. package/dist/guards/index.js +19 -0
  406. package/dist/guards/index.js.map +1 -0
  407. package/dist/guards/no-drizzle-push.d.ts +14 -0
  408. package/dist/guards/no-drizzle-push.d.ts.map +1 -0
  409. package/dist/guards/no-drizzle-push.js +97 -0
  410. package/dist/guards/no-drizzle-push.js.map +1 -0
  411. package/dist/guards/no-env-credentials.d.ts +36 -0
  412. package/dist/guards/no-env-credentials.d.ts.map +1 -0
  413. package/dist/guards/no-env-credentials.js +204 -0
  414. package/dist/guards/no-env-credentials.js.map +1 -0
  415. package/dist/guards/no-env-mutation.d.ts +23 -0
  416. package/dist/guards/no-env-mutation.d.ts.map +1 -0
  417. package/dist/guards/no-env-mutation.js +90 -0
  418. package/dist/guards/no-env-mutation.js.map +1 -0
  419. package/dist/guards/no-localhost-fallback.d.ts +30 -0
  420. package/dist/guards/no-localhost-fallback.d.ts.map +1 -0
  421. package/dist/guards/no-localhost-fallback.js +105 -0
  422. package/dist/guards/no-localhost-fallback.js.map +1 -0
  423. package/dist/guards/no-unscoped-credentials.d.ts +28 -0
  424. package/dist/guards/no-unscoped-credentials.d.ts.map +1 -0
  425. package/dist/guards/no-unscoped-credentials.js +199 -0
  426. package/dist/guards/no-unscoped-credentials.js.map +1 -0
  427. package/dist/guards/no-unscoped-queries.d.ts +32 -0
  428. package/dist/guards/no-unscoped-queries.d.ts.map +1 -0
  429. package/dist/guards/no-unscoped-queries.js +720 -0
  430. package/dist/guards/no-unscoped-queries.js.map +1 -0
  431. package/dist/guards/scan-utils.d.ts +28 -0
  432. package/dist/guards/scan-utils.d.ts.map +1 -0
  433. package/dist/guards/scan-utils.js +92 -0
  434. package/dist/guards/scan-utils.js.map +1 -0
  435. package/dist/guards/types.d.ts +28 -0
  436. package/dist/guards/types.d.ts.map +1 -0
  437. package/dist/guards/types.js +11 -0
  438. package/dist/guards/types.js.map +1 -0
  439. package/dist/integrations/a2a-continuation-processor.d.ts.map +1 -1
  440. package/dist/integrations/a2a-continuation-processor.js +25 -5
  441. package/dist/integrations/a2a-continuation-processor.js.map +1 -1
  442. package/dist/integrations/adapters/slack.d.ts.map +1 -1
  443. package/dist/integrations/adapters/slack.js +55 -21
  444. package/dist/integrations/adapters/slack.js.map +1 -1
  445. package/dist/integrations/webhook-handler.d.ts.map +1 -1
  446. package/dist/integrations/webhook-handler.js +11 -0
  447. package/dist/integrations/webhook-handler.js.map +1 -1
  448. package/dist/localization/default-messages.d.ts +5 -0
  449. package/dist/localization/default-messages.d.ts.map +1 -1
  450. package/dist/localization/default-messages.js +5 -0
  451. package/dist/localization/default-messages.js.map +1 -1
  452. package/dist/notifications/routes.d.ts +2 -2
  453. package/dist/observability/hosted-model-experiment.d.ts +39 -0
  454. package/dist/observability/hosted-model-experiment.d.ts.map +1 -0
  455. package/dist/observability/hosted-model-experiment.js +90 -0
  456. package/dist/observability/hosted-model-experiment.js.map +1 -0
  457. package/dist/observability/routes.d.ts +1 -1
  458. package/dist/observability/routes.d.ts.map +1 -1
  459. package/dist/observability/routes.js +16 -0
  460. package/dist/observability/routes.js.map +1 -1
  461. package/dist/observability/store.d.ts.map +1 -1
  462. package/dist/observability/store.js +4 -1
  463. package/dist/observability/store.js.map +1 -1
  464. package/dist/observability/traces.d.ts +6 -0
  465. package/dist/observability/traces.d.ts.map +1 -1
  466. package/dist/observability/traces.js +28 -2
  467. package/dist/observability/traces.js.map +1 -1
  468. package/dist/org/accept-pending.d.ts.map +1 -1
  469. package/dist/org/accept-pending.js +9 -1
  470. package/dist/org/accept-pending.js.map +1 -1
  471. package/dist/org/migrations.d.ts +7 -2
  472. package/dist/org/migrations.d.ts.map +1 -1
  473. package/dist/org/migrations.js +41 -0
  474. package/dist/org/migrations.js.map +1 -1
  475. package/dist/package-lifecycle/index.d.ts +2 -0
  476. package/dist/package-lifecycle/index.d.ts.map +1 -0
  477. package/dist/package-lifecycle/index.js +2 -0
  478. package/dist/package-lifecycle/index.js.map +1 -0
  479. package/dist/package-lifecycle/manifest.d.ts +24 -0
  480. package/dist/package-lifecycle/manifest.d.ts.map +1 -0
  481. package/dist/package-lifecycle/manifest.js +81 -0
  482. package/dist/package-lifecycle/manifest.js.map +1 -0
  483. package/dist/progress/routes.d.ts +1 -1
  484. package/dist/provider-api/custom-registry.d.ts +32 -1
  485. package/dist/provider-api/custom-registry.d.ts.map +1 -1
  486. package/dist/provider-api/custom-registry.js +41 -1
  487. package/dist/provider-api/custom-registry.js.map +1 -1
  488. package/dist/provider-api/index.d.ts +1 -1
  489. package/dist/provider-api/index.d.ts.map +1 -1
  490. package/dist/provider-api/index.js +1 -1
  491. package/dist/provider-api/index.js.map +1 -1
  492. package/dist/resources/handlers.d.ts +1 -1
  493. package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
  494. package/dist/scripts/agent-engines/list-agent-engines.js +19 -1
  495. package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
  496. package/dist/scripts/call-agent.d.ts.map +1 -1
  497. package/dist/scripts/call-agent.js +43 -3
  498. package/dist/scripts/call-agent.js.map +1 -1
  499. package/dist/scripts/chat/search-chats.d.ts +1 -1
  500. package/dist/scripts/chat/search-chats.d.ts.map +1 -1
  501. package/dist/scripts/chat/search-chats.js +11 -8
  502. package/dist/scripts/chat/search-chats.js.map +1 -1
  503. package/dist/secrets/register-framework-secrets.js +1 -1
  504. package/dist/secrets/register-framework-secrets.js.map +1 -1
  505. package/dist/secrets/storage.d.ts.map +1 -1
  506. package/dist/secrets/storage.js +45 -27
  507. package/dist/secrets/storage.js.map +1 -1
  508. package/dist/server/action-discovery.d.ts.map +1 -1
  509. package/dist/server/action-discovery.js +4 -0
  510. package/dist/server/action-discovery.js.map +1 -1
  511. package/dist/server/agent-chat-plugin.d.ts +11 -0
  512. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  513. package/dist/server/agent-chat-plugin.js +74 -19
  514. package/dist/server/agent-chat-plugin.js.map +1 -1
  515. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  516. package/dist/server/core-routes-plugin.d.ts +3 -0
  517. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  518. package/dist/server/core-routes-plugin.js +36 -12
  519. package/dist/server/core-routes-plugin.js.map +1 -1
  520. package/dist/server/csrf.d.ts.map +1 -1
  521. package/dist/server/csrf.js +18 -5
  522. package/dist/server/csrf.js.map +1 -1
  523. package/dist/server/framework-request-handler.d.ts.map +1 -1
  524. package/dist/server/framework-request-handler.js +34 -0
  525. package/dist/server/framework-request-handler.js.map +1 -1
  526. package/dist/server/google-realtime-session.d.ts.map +1 -1
  527. package/dist/server/google-realtime-session.js +2 -34
  528. package/dist/server/google-realtime-session.js.map +1 -1
  529. package/dist/server/poll.d.ts.map +1 -1
  530. package/dist/server/poll.js +24 -2
  531. package/dist/server/poll.js.map +1 -1
  532. package/dist/server/realtime-voice.d.ts.map +1 -1
  533. package/dist/server/realtime-voice.js +64 -21
  534. package/dist/server/realtime-voice.js.map +1 -1
  535. package/dist/server/request-origin.d.ts +10 -0
  536. package/dist/server/request-origin.d.ts.map +1 -0
  537. package/dist/server/request-origin.js +60 -0
  538. package/dist/server/request-origin.js.map +1 -0
  539. package/dist/server/transcribe-voice.d.ts.map +1 -1
  540. package/dist/server/transcribe-voice.js +2 -48
  541. package/dist/server/transcribe-voice.js.map +1 -1
  542. package/dist/server/voice-providers-status.d.ts.map +1 -1
  543. package/dist/server/voice-providers-status.js +2 -3
  544. package/dist/server/voice-providers-status.js.map +1 -1
  545. package/dist/shared/cache-control.d.ts +4 -6
  546. package/dist/shared/cache-control.d.ts.map +1 -1
  547. package/dist/shared/cache-control.js +2 -7
  548. package/dist/shared/cache-control.js.map +1 -1
  549. package/dist/styles/agent-native.css +1 -0
  550. package/dist/styles/chat-history-list.css +313 -0
  551. package/dist/templates/default/package.json +2 -2
  552. package/dist/templates/headless/package.json +0 -1
  553. package/dist/templates/workspace-core/.agents/skills/audit-log/SKILL.md +3 -0
  554. package/dist/templates/workspace-core/.agents/skills/automations/SKILL.md +1 -1
  555. package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +20 -0
  556. package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +8 -4
  557. package/dist/templates/workspace-core/package.json +0 -1
  558. package/dist/templates/workspace-root/package.json +0 -1
  559. package/dist/triggers/actions.d.ts.map +1 -1
  560. package/dist/triggers/actions.js +8 -3
  561. package/dist/triggers/actions.js.map +1 -1
  562. package/dist/triggers/types.d.ts +7 -1
  563. package/dist/triggers/types.d.ts.map +1 -1
  564. package/dist/triggers/types.js.map +1 -1
  565. package/dist/vite/client.d.ts.map +1 -1
  566. package/dist/vite/client.js +1 -0
  567. package/dist/vite/client.js.map +1 -1
  568. package/docs/content/audit-log.mdx +2 -1
  569. package/docs/content/automations.mdx +7 -7
  570. package/docs/content/creating-templates.mdx +1 -1
  571. package/docs/content/internationalization.mdx +2 -1
  572. package/docs/content/locales/ar-SA/audit-log.mdx +2 -1
  573. package/docs/content/locales/ar-SA/automations.mdx +7 -7
  574. package/docs/content/locales/ar-SA/getting-started.mdx +7 -1
  575. package/docs/content/locales/ar-SA/internationalization.mdx +1 -1
  576. package/docs/content/locales/ar-SA/package-lifecycle.mdx +19 -0
  577. package/docs/content/locales/ar-SA/sandbox-adapters.mdx +18 -7
  578. package/docs/content/locales/ar-SA/security.mdx +8 -0
  579. package/docs/content/locales/de-DE/audit-log.mdx +2 -1
  580. package/docs/content/locales/de-DE/automations.mdx +7 -7
  581. package/docs/content/locales/de-DE/getting-started.mdx +7 -1
  582. package/docs/content/locales/de-DE/internationalization.mdx +1 -1
  583. package/docs/content/locales/de-DE/package-lifecycle.mdx +22 -0
  584. package/docs/content/locales/de-DE/sandbox-adapters.mdx +18 -7
  585. package/docs/content/locales/de-DE/security.mdx +8 -0
  586. package/docs/content/locales/es-ES/audit-log.mdx +2 -1
  587. package/docs/content/locales/es-ES/automations.mdx +7 -7
  588. package/docs/content/locales/es-ES/getting-started.mdx +7 -1
  589. package/docs/content/locales/es-ES/internationalization.mdx +1 -1
  590. package/docs/content/locales/es-ES/package-lifecycle.mdx +22 -0
  591. package/docs/content/locales/es-ES/sandbox-adapters.mdx +18 -7
  592. package/docs/content/locales/es-ES/security.mdx +8 -0
  593. package/docs/content/locales/fr-FR/audit-log.mdx +2 -1
  594. package/docs/content/locales/fr-FR/automations.mdx +7 -7
  595. package/docs/content/locales/fr-FR/getting-started.mdx +7 -1
  596. package/docs/content/locales/fr-FR/internationalization.mdx +1 -1
  597. package/docs/content/locales/fr-FR/package-lifecycle.mdx +21 -0
  598. package/docs/content/locales/fr-FR/sandbox-adapters.mdx +19 -8
  599. package/docs/content/locales/fr-FR/security.mdx +8 -0
  600. package/docs/content/locales/hi-IN/audit-log.mdx +2 -1
  601. package/docs/content/locales/hi-IN/automations.mdx +7 -7
  602. package/docs/content/locales/hi-IN/getting-started.mdx +7 -1
  603. package/docs/content/locales/hi-IN/internationalization.mdx +1 -1
  604. package/docs/content/locales/hi-IN/package-lifecycle.mdx +20 -0
  605. package/docs/content/locales/hi-IN/sandbox-adapters.mdx +18 -7
  606. package/docs/content/locales/hi-IN/security.mdx +8 -0
  607. package/docs/content/locales/ja-JP/audit-log.mdx +2 -1
  608. package/docs/content/locales/ja-JP/automations.mdx +7 -7
  609. package/docs/content/locales/ja-JP/getting-started.mdx +7 -1
  610. package/docs/content/locales/ja-JP/internationalization.mdx +1 -1
  611. package/docs/content/locales/ja-JP/package-lifecycle.mdx +21 -0
  612. package/docs/content/locales/ja-JP/sandbox-adapters.mdx +17 -6
  613. package/docs/content/locales/ja-JP/security.mdx +8 -0
  614. package/docs/content/locales/ko-KR/audit-log.mdx +2 -1
  615. package/docs/content/locales/ko-KR/automations.mdx +7 -7
  616. package/docs/content/locales/ko-KR/getting-started.mdx +7 -1
  617. package/docs/content/locales/ko-KR/internationalization.mdx +1 -1
  618. package/docs/content/locales/ko-KR/package-lifecycle.mdx +20 -0
  619. package/docs/content/locales/ko-KR/sandbox-adapters.mdx +17 -6
  620. package/docs/content/locales/ko-KR/security.mdx +8 -0
  621. package/docs/content/locales/pt-BR/audit-log.mdx +2 -1
  622. package/docs/content/locales/pt-BR/automations.mdx +7 -7
  623. package/docs/content/locales/pt-BR/getting-started.mdx +7 -1
  624. package/docs/content/locales/pt-BR/internationalization.mdx +1 -1
  625. package/docs/content/locales/pt-BR/package-lifecycle.mdx +21 -0
  626. package/docs/content/locales/pt-BR/sandbox-adapters.mdx +18 -7
  627. package/docs/content/locales/pt-BR/security.mdx +8 -0
  628. package/docs/content/locales/zh-CN/audit-log.mdx +2 -1
  629. package/docs/content/locales/zh-CN/automations.mdx +7 -7
  630. package/docs/content/locales/zh-CN/getting-started.mdx +6 -4
  631. package/docs/content/locales/zh-CN/internationalization.mdx +1 -1
  632. package/docs/content/locales/zh-CN/package-lifecycle.mdx +19 -0
  633. package/docs/content/locales/zh-CN/sandbox-adapters.mdx +17 -6
  634. package/docs/content/locales/zh-CN/security.mdx +8 -0
  635. package/docs/content/locales/zh-TW/audit-log.mdx +2 -1
  636. package/docs/content/locales/zh-TW/automations.mdx +7 -7
  637. package/docs/content/locales/zh-TW/getting-started.mdx +6 -4
  638. package/docs/content/locales/zh-TW/internationalization.mdx +1 -1
  639. package/docs/content/locales/zh-TW/package-lifecycle.mdx +19 -0
  640. package/docs/content/locales/zh-TW/sandbox-adapters.mdx +18 -7
  641. package/docs/content/locales/zh-TW/security.mdx +8 -0
  642. package/docs/content/package-lifecycle.mdx +51 -0
  643. package/docs/content/sandbox-adapters.mdx +16 -5
  644. package/package.json +12 -3
  645. package/src/templates/default/package.json +2 -2
  646. package/src/templates/headless/package.json +0 -1
  647. package/src/templates/workspace-core/.agents/skills/audit-log/SKILL.md +3 -0
  648. package/src/templates/workspace-core/.agents/skills/automations/SKILL.md +1 -1
  649. package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +20 -0
  650. package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +8 -4
  651. package/src/templates/workspace-core/package.json +0 -1
  652. package/src/templates/workspace-root/package.json +0 -1
  653. package/corpus/templates/slides/app/components/ui/toast.tsx +0 -1
  654. package/corpus/templates/slides/app/components/ui/toaster.tsx +0 -1
  655. package/corpus/templates/slides/app/hooks/use-toast.ts +0 -1
@@ -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
  }
@@ -639,6 +639,14 @@ export interface ListThreadsOptions {
639
639
  /** When true, returns only threads with no scope (general chats). */
640
640
  unscopedOnly?: boolean;
641
641
  orgId?: string | null;
642
+ /**
643
+ * Include archived threads in the results. Defaults to false: archived
644
+ * threads (`archived_at` set via `setThreadArchived`) are hidden from the
645
+ * ordinary chat list/search so archiving actually removes a thread from
646
+ * view. Pass true for surfaces that explicitly need to see archived chats
647
+ * (e.g. an "Archived" filter or restoring one via `setThreadArchived`).
648
+ */
649
+ includeArchived?: boolean;
642
650
  }
643
651
 
644
652
  function chatThreadAccessSql(
@@ -686,6 +694,9 @@ export async function listThreads(
686
694
  );
687
695
  const filters: string[] = [access.sql, `message_count > 0`];
688
696
  const args: (string | number)[] = [...access.args];
697
+ if (!opts.includeArchived) {
698
+ filters.push(`archived_at IS NULL`);
699
+ }
689
700
  if (opts.scope) {
690
701
  filters.push(`scope_type = ? AND scope_id = ?`);
691
702
  args.push(opts.scope.type, opts.scope.id);
@@ -710,7 +721,12 @@ export async function searchThreads(
710
721
  ownerEmail: string,
711
722
  query: string,
712
723
  limit = 50,
713
- options: { scope?: { type: string; id: string }; orgId?: string | null } = {},
724
+ options: {
725
+ scope?: { type: string; id: string };
726
+ orgId?: string | null;
727
+ /** See `ListThreadsOptions.includeArchived` — defaults to false. */
728
+ includeArchived?: boolean;
729
+ } = {},
714
730
  ): Promise<ChatThreadSummary[]> {
715
731
  await ensureTable();
716
732
  const client = getDbExec();
@@ -728,6 +744,9 @@ export async function searchThreads(
728
744
  `(title LIKE ? ESCAPE '!' OR preview LIKE ? ESCAPE '!' OR thread_data LIKE ? ESCAPE '!')`,
729
745
  ];
730
746
  const args: (string | number)[] = [...access.args, pattern, pattern, pattern];
747
+ if (!options.includeArchived) {
748
+ filters.push(`archived_at IS NULL`);
749
+ }
731
750
  if (options.scope) {
732
751
  filters.push(`scope_type = ? AND scope_id = ?`);
733
752
  args.push(options.scope.type, options.scope.id);
@@ -215,6 +215,7 @@ export async function executeCodeAgentRun(
215
215
  runId: existing.id,
216
216
  kind: "status",
217
217
  message,
218
+ signal: "credential-gap",
218
219
  metadata: { status: "paused", phase: "missing-credentials" },
219
220
  });
220
221
  return updateCodeAgentRunRecord(existing.id, {
@@ -77,6 +77,17 @@ export type CodeAgentTranscriptEventKind =
77
77
  | "artifact"
78
78
  | "status";
79
79
 
80
+ /**
81
+ * Structured, machine-checkable marker for transcript events that need
82
+ * special handling in the UI beyond free-text matching. `"credential-gap"`
83
+ * marks the status event the executor appends when no LLM provider key (or
84
+ * Codex CLI login) is available; consumers should prefer this field over
85
+ * regex-matching `message` (see `isCredentialGapCodeAgentEvent` in
86
+ * `../code-agents/transcript-normalizer.js`). Optional so older, already
87
+ * persisted JSONL transcripts without the field keep parsing unchanged.
88
+ */
89
+ export type CodeAgentTranscriptEventSignal = "credential-gap";
90
+
80
91
  export interface CodeAgentTranscriptEvent {
81
92
  schemaVersion: 1;
82
93
  id: string;
@@ -85,6 +96,7 @@ export interface CodeAgentTranscriptEvent {
85
96
  message: string;
86
97
  createdAt: string;
87
98
  metadata?: Record<string, unknown>;
99
+ signal?: CodeAgentTranscriptEventSignal;
88
100
  }
89
101
 
90
102
  export interface CreateCodeAgentRunInput {
@@ -109,6 +121,7 @@ export interface AppendCodeAgentTranscriptEventInput {
109
121
  message: string;
110
122
  createdAt?: string;
111
123
  metadata?: Record<string, unknown>;
124
+ signal?: CodeAgentTranscriptEventSignal;
112
125
  }
113
126
 
114
127
  export interface QueueCodeAgentFollowUpInput {
@@ -294,6 +307,7 @@ export function appendCodeAgentTranscriptEvent(
294
307
  message: input.message,
295
308
  createdAt,
296
309
  metadata: input.metadata,
310
+ ...(input.signal ? { signal: input.signal } : {}),
297
311
  };
298
312
 
299
313
  fs.mkdirSync(codeAgentTranscriptsDir(), { recursive: true });
@@ -0,0 +1,396 @@
1
+ /**
2
+ * `agent-native doctor` — scan an app's source tree for the security-
3
+ * critical code-safety invariants this monorepo already enforces on
4
+ * itself via `scripts/guard-*.mjs` (see
5
+ * `advisor-plans/reports/005-doctor-design.md` for the full design and
6
+ * `advisor-plans/015-doctor-v1-implementation.md` for the implementation
7
+ * plan). v1 ships 7 of those guards, ported to work against a single
8
+ * generated app root instead of this monorepo's multi-template layout —
9
+ * see `../guards/index.ts`.
10
+ *
11
+ * This is a NEW top-level command, deliberately kept separate from the two
12
+ * existing "doctor" precedents in this CLI:
13
+ * - `agent-native upgrade check` (`upgrade.ts`) — dependency-pin health.
14
+ * - `agent-native recap doctor` (`recap.ts`) — PR Visual Recap config health.
15
+ * Each diagnoses a different domain; none are folded into a shared
16
+ * mega-doctor (see report 005, "Relationship to upgrade doctor and recap
17
+ * doctor").
18
+ *
19
+ * `--fix` is reserved, not implemented in v1 — it prints a message and
20
+ * exits 2 rather than silently no-op, so a future implementation doesn't
21
+ * collide with a script already passing the flag.
22
+ */
23
+ import fs from "node:fs";
24
+ import path from "node:path";
25
+
26
+ import {
27
+ scanDbToolScoping,
28
+ scanDrizzlePush,
29
+ scanEnvCredentials,
30
+ scanEnvMutation,
31
+ scanLocalhostFallback,
32
+ scanUnscopedCredentials,
33
+ scanUnscopedQueries,
34
+ } from "../guards/index.js";
35
+ import type { GuardResult } from "../guards/index.js";
36
+
37
+ export type GuardName =
38
+ | "no-drizzle-push"
39
+ | "no-unscoped-credentials"
40
+ | "no-unscoped-queries"
41
+ | "no-env-credentials"
42
+ | "db-tool-scoping"
43
+ | "no-env-mutation"
44
+ | "no-localhost-fallback";
45
+
46
+ export const ALL_GUARD_NAMES: GuardName[] = [
47
+ "no-drizzle-push",
48
+ "no-unscoped-credentials",
49
+ "no-unscoped-queries",
50
+ "no-env-credentials",
51
+ "db-tool-scoping",
52
+ "no-env-mutation",
53
+ "no-localhost-fallback",
54
+ ];
55
+
56
+ export interface DoctorConfig {
57
+ disabledGuards: string[];
58
+ dbToolScopingDenylist: Record<string, string>;
59
+ failOnBuild: boolean;
60
+ }
61
+
62
+ const DEFAULT_DOCTOR_CONFIG: DoctorConfig = {
63
+ disabledGuards: [],
64
+ dbToolScopingDenylist: {},
65
+ failOnBuild: false,
66
+ };
67
+
68
+ export interface DoctorFinding {
69
+ guard: string;
70
+ file: string;
71
+ line: number;
72
+ message: string;
73
+ }
74
+
75
+ export interface DoctorReport {
76
+ ok: boolean;
77
+ findings: DoctorFinding[];
78
+ guardsRun: string[];
79
+ }
80
+
81
+ /**
82
+ * Reads the optional `"doctor"` key from `<root>/agent-native.json`. All
83
+ * fields are optional with sane empty defaults — an app needs zero config
84
+ * to run `agent-native doctor` with every v1 guard enabled.
85
+ */
86
+ export function readDoctorConfig(root: string): DoctorConfig {
87
+ const manifestPath = path.join(root, "agent-native.json");
88
+ if (!fs.existsSync(manifestPath)) {
89
+ return { ...DEFAULT_DOCTOR_CONFIG, dbToolScopingDenylist: {} };
90
+ }
91
+ try {
92
+ const raw = fs.readFileSync(manifestPath, "utf-8");
93
+ const parsed = JSON.parse(raw) as { doctor?: Record<string, unknown> };
94
+ const doctor = parsed.doctor ?? {};
95
+ const disabledGuards = Array.isArray(doctor.disabledGuards)
96
+ ? doctor.disabledGuards.filter((v): v is string => typeof v === "string")
97
+ : [];
98
+ const dbToolScopingDenylist =
99
+ doctor.dbToolScopingDenylist &&
100
+ typeof doctor.dbToolScopingDenylist === "object"
101
+ ? (Object.fromEntries(
102
+ Object.entries(
103
+ doctor.dbToolScopingDenylist as Record<string, unknown>,
104
+ ).filter(
105
+ (entry): entry is [string, string] =>
106
+ typeof entry[1] === "string",
107
+ ),
108
+ ) as Record<string, string>)
109
+ : {};
110
+ const failOnBuild = doctor.failOnBuild === true;
111
+ return { disabledGuards, dbToolScopingDenylist, failOnBuild };
112
+ } catch {
113
+ return { ...DEFAULT_DOCTOR_CONFIG, dbToolScopingDenylist: {} };
114
+ }
115
+ }
116
+
117
+ function runGuard(
118
+ name: GuardName,
119
+ root: string,
120
+ config: DoctorConfig,
121
+ ): GuardResult {
122
+ switch (name) {
123
+ case "no-drizzle-push":
124
+ return scanDrizzlePush({ root });
125
+ case "no-unscoped-credentials":
126
+ return scanUnscopedCredentials({ root });
127
+ case "no-unscoped-queries":
128
+ return scanUnscopedQueries({ root, extraExemptPaths: [] });
129
+ case "no-env-credentials":
130
+ return scanEnvCredentials({ root });
131
+ case "db-tool-scoping":
132
+ return scanDbToolScoping({
133
+ root,
134
+ denylist: config.dbToolScopingDenylist,
135
+ });
136
+ case "no-env-mutation":
137
+ return scanEnvMutation({ root });
138
+ case "no-localhost-fallback":
139
+ return scanLocalhostFallback({ root, extraExemptPaths: [] });
140
+ }
141
+ }
142
+
143
+ export interface RunDoctorScanOptions {
144
+ root: string;
145
+ /** Restrict to these guard names. When omitted, runs every guard not
146
+ * listed in `agent-native.json`'s `doctor.disabledGuards`. Unknown names
147
+ * are silently ignored here — the CLI layer (`runDoctor`) validates
148
+ * `--only` and reports a usage error before calling this. */
149
+ only?: string[];
150
+ }
151
+
152
+ /** Pure scan orchestrator: runs the selected guards against `root` and
153
+ * returns a flat report. No I/O beyond reading `agent-native.json` and the
154
+ * app source tree — no printing, no process.exit. */
155
+ export function runDoctorScan(options: RunDoctorScanOptions): DoctorReport {
156
+ const root = options.root;
157
+ const config = readDoctorConfig(root);
158
+
159
+ let names: GuardName[];
160
+ if (options.only && options.only.length > 0) {
161
+ const knownOnly = options.only.filter((n): n is GuardName =>
162
+ (ALL_GUARD_NAMES as string[]).includes(n),
163
+ );
164
+ names = knownOnly;
165
+ } else {
166
+ names = ALL_GUARD_NAMES.filter((n) => !config.disabledGuards.includes(n));
167
+ }
168
+
169
+ const findings: DoctorFinding[] = [];
170
+ for (const name of names) {
171
+ const result = runGuard(name, root, config);
172
+ for (const f of result.findings) {
173
+ findings.push({
174
+ guard: name,
175
+ file: f.file,
176
+ line: f.line,
177
+ message: f.message,
178
+ });
179
+ }
180
+ }
181
+
182
+ return { ok: findings.length === 0, findings, guardsRun: names };
183
+ }
184
+
185
+ /** Pure escalation rule shared by the CLI (`--strict`) and the `build`
186
+ * pre-step (`--strict` / `agent-native.json` `doctor.failOnBuild`). Doctor
187
+ * findings never fail anything on their own — only `strict` or
188
+ * `failOnBuild` turn findings into a hard failure. */
189
+ export function shouldFailBuild(
190
+ hasFindings: boolean,
191
+ opts: { strict?: boolean; failOnBuild?: boolean },
192
+ ): boolean {
193
+ return hasFindings && Boolean(opts.strict || opts.failOnBuild);
194
+ }
195
+
196
+ export interface DoctorIo {
197
+ log: (message: string) => void;
198
+ err: (message: string) => void;
199
+ }
200
+
201
+ const defaultIo: DoctorIo = {
202
+ log: (message) => console.log(message),
203
+ err: (message) => console.error(message),
204
+ };
205
+
206
+ function formatDoctorHuman(report: DoctorReport, root: string): string {
207
+ const lines: string[] = [];
208
+ lines.push(`agent-native doctor: ${root}`);
209
+ lines.push(`Guards run: ${report.guardsRun.join(", ") || "(none)"}`);
210
+ if (report.findings.length === 0) {
211
+ lines.push("Clean — no findings.");
212
+ } else {
213
+ lines.push(`${report.findings.length} finding(s):`);
214
+ for (const f of report.findings) {
215
+ lines.push(` [${f.guard}] ${f.file}:${f.line} — ${f.message}`);
216
+ }
217
+ }
218
+ return lines.join("\n");
219
+ }
220
+
221
+ export interface DoctorCliOptions {
222
+ json?: boolean;
223
+ cwd?: string;
224
+ only?: string[];
225
+ strict?: boolean;
226
+ help?: boolean;
227
+ fix?: boolean;
228
+ }
229
+
230
+ export function parseDoctorArgs(argv: string[]): DoctorCliOptions {
231
+ const opts: DoctorCliOptions = {};
232
+ for (let i = 0; i < argv.length; i++) {
233
+ const arg = argv[i];
234
+ if (arg === "--help" || arg === "-h") {
235
+ opts.help = true;
236
+ } else if (arg === "--json") {
237
+ opts.json = true;
238
+ } else if (arg === "--strict") {
239
+ opts.strict = true;
240
+ } else if (arg === "--fix") {
241
+ opts.fix = true;
242
+ } else if (arg === "--cwd" && argv[i + 1] !== undefined) {
243
+ opts.cwd = argv[++i];
244
+ } else if (arg.startsWith("--cwd=")) {
245
+ opts.cwd = arg.slice("--cwd=".length);
246
+ } else if (arg === "--only" && argv[i + 1] !== undefined) {
247
+ opts.only = splitGuardList(argv[++i]);
248
+ } else if (arg.startsWith("--only=")) {
249
+ opts.only = splitGuardList(arg.slice("--only=".length));
250
+ }
251
+ }
252
+ return opts;
253
+ }
254
+
255
+ function splitGuardList(value: string): string[] {
256
+ return value
257
+ .split(",")
258
+ .map((s) => s.trim())
259
+ .filter((s) => s.length > 0);
260
+ }
261
+
262
+ export function printDoctorHelp(io: Pick<DoctorIo, "log"> = defaultIo): void {
263
+ io.log(
264
+ [
265
+ "Usage:",
266
+ " agent-native doctor Scan app source for security-critical guard violations",
267
+ " agent-native doctor --json Machine-readable report: { ok, findings, guardsRun }",
268
+ " agent-native doctor --only <guard,guard> Run only the named guard(s)",
269
+ " agent-native doctor --strict Escalate findings to a hard failure when used by `agent-native build --strict`",
270
+ " agent-native doctor --cwd <dir> Run against a project root other than the current directory",
271
+ " agent-native doctor --fix Not implemented in this version",
272
+ " agent-native doctor --help Show this help",
273
+ "",
274
+ `Guards: ${ALL_GUARD_NAMES.join(", ")}`,
275
+ "",
276
+ "Exit codes: 0 clean, 1 findings present, 2 usage/execution error.",
277
+ "",
278
+ "`agent-native build` runs doctor as a warn-only pre-step by default — it",
279
+ "never fails the build unless `agent-native build --strict` is passed or",
280
+ 'agent-native.json sets { "doctor": { "failOnBuild": true } }.',
281
+ "",
282
+ "For dependency-pin health (framework overrides/patches, stale",
283
+ "@agent-native/* pins), run `agent-native upgrade check` instead.",
284
+ ].join("\n"),
285
+ );
286
+ }
287
+
288
+ /** `agent-native doctor` CLI entrypoint. Returns the process exit code —
289
+ * callers are responsible for calling `process.exit(code)`. */
290
+ export async function runDoctor(
291
+ argv: string[],
292
+ io: DoctorIo = defaultIo,
293
+ ): Promise<number> {
294
+ const opts = parseDoctorArgs(argv);
295
+
296
+ if (opts.help) {
297
+ printDoctorHelp(io);
298
+ return 0;
299
+ }
300
+
301
+ if (opts.fix) {
302
+ io.err(
303
+ "agent-native doctor --fix is not implemented in this version. Fix findings manually and re-run `agent-native doctor`.",
304
+ );
305
+ return 2;
306
+ }
307
+
308
+ const root = path.resolve(opts.cwd ?? process.cwd());
309
+ if (!fs.existsSync(root) || !fs.statSync(root).isDirectory()) {
310
+ const message = `--cwd path does not exist or is not a directory: ${root}`;
311
+ if (opts.json) io.err(JSON.stringify({ ok: false, message }, null, 2));
312
+ else io.err(message);
313
+ return 2;
314
+ }
315
+
316
+ if (opts.only) {
317
+ const unknown = opts.only.filter(
318
+ (n) => !(ALL_GUARD_NAMES as string[]).includes(n),
319
+ );
320
+ if (unknown.length > 0) {
321
+ const message = `Unknown guard name(s) in --only: ${unknown.join(", ")}. Known guards: ${ALL_GUARD_NAMES.join(", ")}`;
322
+ if (opts.json) io.err(JSON.stringify({ ok: false, message }, null, 2));
323
+ else io.err(message);
324
+ return 2;
325
+ }
326
+ }
327
+
328
+ const report = runDoctorScan({ root, only: opts.only });
329
+
330
+ if (opts.json) {
331
+ const sink = report.ok ? io.log : io.err;
332
+ sink(JSON.stringify({ ...report, strict: Boolean(opts.strict) }, null, 2));
333
+ } else {
334
+ io.log(formatDoctorHuman(report, root));
335
+ if (!report.ok) {
336
+ io.err("");
337
+ io.err(
338
+ "agent-native doctor found issues above. Fix them, or add a `// guard:allow-<check> — reason` opt-out with reviewer approval.",
339
+ );
340
+ }
341
+ }
342
+
343
+ return report.ok ? 0 : 1;
344
+ }
345
+
346
+ export interface DoctorBuildHookOptions {
347
+ cwd: string;
348
+ /** Set when the caller passed `agent-native build --strict`. */
349
+ strict?: boolean;
350
+ }
351
+
352
+ export interface DoctorBuildHookResult {
353
+ /** False only when findings are present AND (`strict` was requested OR
354
+ * `agent-native.json`'s `doctor.failOnBuild` is true). */
355
+ ok: boolean;
356
+ report: DoctorReport;
357
+ }
358
+
359
+ /**
360
+ * `agent-native build`'s doctor pre-step. Always runs every enabled guard
361
+ * and always prints findings (as warnings) to `io.err` — never silent.
362
+ * Never causes the build to fail unless `strict` was passed or
363
+ * `agent-native.json` sets `doctor.failOnBuild: true` (see report 005,
364
+ * "Where it runs" — the v1 doctor has zero field mileage against arbitrary
365
+ * app layouts, so shipping fail-by-default would risk breaking a first
366
+ * deploy on a false positive).
367
+ */
368
+ export async function runDoctorBuildHook(
369
+ options: DoctorBuildHookOptions,
370
+ io: DoctorIo = defaultIo,
371
+ ): Promise<DoctorBuildHookResult> {
372
+ const root = path.resolve(options.cwd);
373
+ const config = readDoctorConfig(root);
374
+ const report = runDoctorScan({ root });
375
+
376
+ if (report.findings.length > 0) {
377
+ io.err(
378
+ `\n[doctor] ${report.findings.length} finding(s) from \`agent-native doctor\` — run it directly for details. This does not fail the build unless --strict was passed or agent-native.json's doctor.failOnBuild is true.`,
379
+ );
380
+ for (const f of report.findings) {
381
+ io.err(` [${f.guard}] ${f.file}:${f.line} — ${f.message}`);
382
+ }
383
+ }
384
+
385
+ const fail = shouldFailBuild(report.findings.length > 0, {
386
+ strict: options.strict,
387
+ failOnBuild: config.failOnBuild,
388
+ });
389
+ if (fail) {
390
+ io.err(
391
+ `\n[doctor] Failing build: ${options.strict ? "--strict was passed" : "agent-native.json's doctor.failOnBuild is true"}.`,
392
+ );
393
+ }
394
+
395
+ return { ok: !fail, report };
396
+ }