@agent-native/core 0.100.2 → 0.101.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (388) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +83 -0
  3. package/corpus/core/docs/content/locales/ar-SA/pr-visual-recap.mdx +48 -30
  4. package/corpus/core/docs/content/locales/ar-SA/template-plan.mdx +7 -0
  5. package/corpus/core/docs/content/locales/de-DE/pr-visual-recap.mdx +48 -30
  6. package/corpus/core/docs/content/locales/de-DE/template-plan.mdx +7 -0
  7. package/corpus/core/docs/content/locales/es-ES/pr-visual-recap.mdx +48 -30
  8. package/corpus/core/docs/content/locales/es-ES/template-plan.mdx +14 -0
  9. package/corpus/core/docs/content/locales/fr-FR/pr-visual-recap.mdx +48 -30
  10. package/corpus/core/docs/content/locales/fr-FR/template-plan.mdx +7 -0
  11. package/corpus/core/docs/content/locales/hi-IN/pr-visual-recap.mdx +48 -30
  12. package/corpus/core/docs/content/locales/hi-IN/template-plan.mdx +7 -0
  13. package/corpus/core/docs/content/locales/ja-JP/pr-visual-recap.mdx +48 -30
  14. package/corpus/core/docs/content/locales/ja-JP/template-plan.mdx +7 -0
  15. package/corpus/core/docs/content/locales/ko-KR/pr-visual-recap.mdx +48 -30
  16. package/corpus/core/docs/content/locales/ko-KR/template-plan.mdx +7 -0
  17. package/corpus/core/docs/content/locales/pt-BR/pr-visual-recap.mdx +48 -30
  18. package/corpus/core/docs/content/locales/pt-BR/template-plan.mdx +14 -0
  19. package/corpus/core/docs/content/locales/zh-CN/pr-visual-recap.mdx +48 -30
  20. package/corpus/core/docs/content/locales/zh-CN/template-plan.mdx +7 -0
  21. package/corpus/core/docs/content/locales/zh-TW/pr-visual-recap.mdx +48 -30
  22. package/corpus/core/docs/content/locales/zh-TW/template-plan.mdx +7 -0
  23. package/corpus/core/docs/content/pr-visual-recap.mdx +50 -32
  24. package/corpus/core/docs/content/template-plan.mdx +14 -0
  25. package/corpus/core/docs/content/toolkit-comments-review.mdx +16 -2
  26. package/corpus/core/package.json +4 -1
  27. package/corpus/core/src/a2a/index.ts +2 -1
  28. package/corpus/core/src/a2a/server.ts +34 -9
  29. package/corpus/core/src/agent/production-agent.ts +56 -10
  30. package/corpus/core/src/cli/create.ts +47 -19
  31. package/corpus/core/src/cli/pr-visual-recap-workflow.ts +2 -3
  32. package/corpus/core/src/cli/recap.ts +3 -4932
  33. package/corpus/core/src/cli/skills-content/visual-plan-skill.ts +6 -4
  34. package/corpus/core/src/cli/skills-content/visual-recap-skill.ts +7 -1
  35. package/corpus/core/src/client/AgentPanel.tsx +19 -17
  36. package/corpus/core/src/client/analytics.ts +8 -1
  37. package/corpus/core/src/client/chat/markdown-renderer.tsx +54 -8
  38. package/corpus/core/src/client/chat/message-components.tsx +8 -2
  39. package/corpus/core/src/client/clipboard.ts +28 -1
  40. package/corpus/core/src/client/guided-questions.tsx +4 -0
  41. package/corpus/core/src/client/i18n.tsx +2 -1
  42. package/corpus/core/src/client/index.ts +4 -0
  43. package/corpus/core/src/client/review/ReviewCommentComposer.tsx +108 -0
  44. package/corpus/core/src/client/review/ReviewThreadPanel.tsx +482 -150
  45. package/corpus/core/src/client/review/index.ts +8 -0
  46. package/corpus/core/src/client/review/use-review.ts +35 -1
  47. package/corpus/core/src/client/use-agent-chat-context.ts +3 -2
  48. package/corpus/core/src/credentials/index.ts +41 -8
  49. package/corpus/core/src/extensions/fetch-tool.ts +33 -3
  50. package/corpus/core/src/notifications/channels.ts +20 -6
  51. package/corpus/core/src/review/actions/create-review-comment.ts +2 -1
  52. package/corpus/core/src/review/actions/get-review-feedback.ts +6 -11
  53. package/corpus/core/src/review/actions/list-review-comments.ts +38 -4
  54. package/corpus/core/src/review/actions/reply-review-comment.ts +33 -22
  55. package/corpus/core/src/review/actions/resolve-review-thread.ts +29 -2
  56. package/corpus/core/src/review/actions/send-review-thread-to-agent.ts +62 -0
  57. package/corpus/core/src/review/identity.ts +101 -0
  58. package/corpus/core/src/review/index.ts +14 -0
  59. package/corpus/core/src/review/store.ts +315 -8
  60. package/corpus/core/src/review/types.ts +4 -0
  61. package/corpus/core/src/secrets/crypto.ts +26 -10
  62. package/corpus/core/src/secrets/storage.ts +16 -3
  63. package/corpus/core/src/server/action-discovery.ts +4 -0
  64. package/corpus/core/src/server/action-routes.ts +125 -4
  65. package/corpus/core/src/server/agent-chat/plugin-options.ts +16 -0
  66. package/corpus/core/src/server/agent-chat-plugin.ts +61 -7
  67. package/corpus/core/src/server/derived-secret.ts +5 -1
  68. package/corpus/core/src/server/index.ts +8 -0
  69. package/corpus/core/src/vite/action-types-plugin.ts +4 -0
  70. package/corpus/templates/analytics/changelog/2026-07-14-daily-dashboard-email-captures-authenticate-with-a-sessi.md +6 -0
  71. package/corpus/templates/analytics/changelog/2026-07-14-long-running-cross-app-analyses-now-continue-reliably-in-the.md +6 -0
  72. package/corpus/templates/analytics/server/lib/dashboard-report.ts +156 -3
  73. package/corpus/templates/analytics/server/plugins/agent-chat.ts +8 -4
  74. package/corpus/templates/assets/app/components/generation/GenerationResults.tsx +402 -142
  75. package/corpus/templates/assets/app/i18n/zh-TW.ts +1 -0
  76. package/corpus/templates/assets/app/i18n-data.ts +1 -0
  77. package/corpus/templates/assets/app/routes/library.tsx +187 -48
  78. package/corpus/templates/assets/changelog/2026-07-13-merged-the-candidates-panel-into-the-library-as-a-drafts-tab.md +6 -0
  79. package/corpus/templates/chat/app/lib/agent-page.tsx +40 -0
  80. package/corpus/templates/chat/app/routes/agent.tsx +5 -3
  81. package/corpus/templates/chat/changelog/2026-07-14-fixed-chat-template-startup-with-older-core-versions.md +6 -0
  82. package/corpus/templates/clips/.agents/skills/ai-video-tools/SKILL.md +5 -0
  83. package/corpus/templates/clips/AGENTS.md +4 -0
  84. package/corpus/templates/clips/actions/get-feature-flags.ts +30 -0
  85. package/corpus/templates/clips/actions/lib/transcript-preview.ts +48 -0
  86. package/corpus/templates/clips/actions/request-transcript.ts +41 -1
  87. package/corpus/templates/clips/actions/view-screen.ts +5 -9
  88. package/corpus/templates/clips/app/components/library/library-layout.tsx +1 -1
  89. package/corpus/templates/clips/app/components/player/share-dialog.tsx +44 -81
  90. package/corpus/templates/clips/app/components/player/video-player.tsx +39 -1
  91. package/corpus/templates/clips/app/hooks/use-desktop-promo.ts +6 -12
  92. package/corpus/templates/clips/app/hooks/use-mse-video-source.ts +146 -0
  93. package/corpus/templates/clips/app/i18n/ar-SA.ts +0 -8
  94. package/corpus/templates/clips/app/i18n/de-DE.ts +0 -9
  95. package/corpus/templates/clips/app/i18n/en-US.ts +0 -8
  96. package/corpus/templates/clips/app/i18n/es-ES.ts +0 -9
  97. package/corpus/templates/clips/app/i18n/fr-FR.ts +0 -9
  98. package/corpus/templates/clips/app/i18n/hi-IN.ts +0 -8
  99. package/corpus/templates/clips/app/i18n/ja-JP.ts +0 -9
  100. package/corpus/templates/clips/app/i18n/ko-KR.ts +0 -9
  101. package/corpus/templates/clips/app/i18n/pt-BR.ts +0 -9
  102. package/corpus/templates/clips/app/i18n/zh-CN.ts +0 -7
  103. package/corpus/templates/clips/app/i18n/zh-TW.ts +0 -7
  104. package/corpus/templates/clips/app/lib/capture-install-options.ts +21 -0
  105. package/corpus/templates/clips/app/lib/fmp4.ts +271 -0
  106. package/corpus/templates/clips/app/lib/mse-video-loader.ts +585 -0
  107. package/corpus/templates/clips/app/routes/_app.dictate.tsx +0 -4
  108. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +5 -13
  109. package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +2 -37
  110. package/corpus/templates/clips/app/routes/download.tsx +3 -2
  111. package/corpus/templates/clips/changelog/2026-07-10-shared-clips-now-start-playing-instantly-instead-of-showing-.md +6 -0
  112. package/corpus/templates/clips/changelog/2026-07-14-clips-now-distinguishes-transcript-previews-from-incomplete-.md +6 -0
  113. package/corpus/templates/clips/changelog/2026-07-14-desktop-app-prompts-stay-hidden-after-you-download-the-insta.md +6 -0
  114. package/corpus/templates/clips/changelog/2026-07-14-share-dialogs-show-separate-links-for-people-and-agents.md +6 -0
  115. package/corpus/templates/clips/desktop/src/lib/recorder.ts +5 -0
  116. package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +10 -0
  117. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +4 -0
  118. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +2518 -0
  119. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/live_upload.rs +353 -0
  120. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +558 -67
  121. package/corpus/templates/clips/desktop/src-tauri/src/recording_indicator.rs +11 -1
  122. package/corpus/templates/clips/desktop/src-tauri/src/remote_flags.rs +188 -0
  123. package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +1 -1
  124. package/corpus/templates/clips/server/lib/post-finalize-dispatch.ts +1 -0
  125. package/corpus/templates/clips/server/plugins/agent-chat.ts +5 -0
  126. package/corpus/templates/clips/server/routes/api/_agent-native-background/post-finalize-worker.post.ts +5 -1
  127. package/corpus/templates/clips/shared/feature-flags.ts +41 -0
  128. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +3 -0
  129. package/corpus/templates/design/.agents/skills/design-review-feedback/SKILL.md +42 -0
  130. package/corpus/templates/design/AGENTS.md +6 -0
  131. package/corpus/templates/design/README.md +1 -0
  132. package/corpus/templates/design/actions/navigate.ts +4 -4
  133. package/corpus/templates/design/actions/view-screen.ts +116 -2
  134. package/corpus/templates/design/agent-native.app-skill.json +5 -0
  135. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +52 -59
  136. package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +13 -9
  137. package/corpus/templates/design/app/components/design/EditPanel.tsx +79 -11
  138. package/corpus/templates/design/app/components/design/LayersPanel.tsx +78 -65
  139. package/corpus/templates/design/app/components/design/ReviewCommentsPanel.tsx +161 -0
  140. package/corpus/templates/design/app/components/design/ReviewStatusControl.tsx +96 -0
  141. package/corpus/templates/design/app/components/design/bridge/hit-test.bridge.ts +166 -0
  142. package/corpus/templates/design/app/components/layout/Layout.tsx +1 -0
  143. package/corpus/templates/design/app/components/visual-editor/ReviewCanvasPins.tsx +1077 -0
  144. package/corpus/templates/design/app/components/visual-editor/index.ts +1 -0
  145. package/corpus/templates/design/app/components/visual-editor/review-canvas-state.ts +42 -0
  146. package/corpus/templates/design/app/hooks/use-design-systems.ts +2 -2
  147. package/corpus/templates/design/app/hooks/use-navigation-state.ts +9 -6
  148. package/corpus/templates/design/app/hooks/use-question-flow.ts +7 -1
  149. package/corpus/templates/design/app/i18n/ar-SA.ts +56 -1
  150. package/corpus/templates/design/app/i18n/de-DE.ts +57 -1
  151. package/corpus/templates/design/app/i18n/en-US.ts +56 -1
  152. package/corpus/templates/design/app/i18n/es-ES.ts +56 -1
  153. package/corpus/templates/design/app/i18n/fr-FR.ts +57 -1
  154. package/corpus/templates/design/app/i18n/hi-IN.ts +56 -1
  155. package/corpus/templates/design/app/i18n/ja-JP.ts +56 -1
  156. package/corpus/templates/design/app/i18n/ko-KR.ts +56 -1
  157. package/corpus/templates/design/app/i18n/pt-BR.ts +57 -1
  158. package/corpus/templates/design/app/i18n/zh-CN.ts +56 -1
  159. package/corpus/templates/design/app/i18n/zh-TW.ts +51 -0
  160. package/corpus/templates/design/app/pages/Present.tsx +172 -14
  161. package/corpus/templates/design/app/pages/design-editor/overview-camera.ts +23 -0
  162. package/corpus/templates/design/app/pages/design-editor/tool-state.ts +10 -0
  163. package/corpus/templates/design/app/pages/present-review-state.ts +18 -0
  164. package/corpus/templates/design/app/public-routes.ts +8 -0
  165. package/corpus/templates/design/app/root.tsx +7 -6
  166. package/corpus/templates/design/changelog/2026-07-13-dragged-design-assets-now-appear-at-the-visible-drop-locatio.md +6 -0
  167. package/corpus/templates/design/changelog/2026-07-13-reviewers-can-pin-comments-on-shared-designs-and-apply-verif.md +6 -0
  168. package/corpus/templates/design/server/plugins/agent-chat.ts +10 -0
  169. package/corpus/templates/design/server/plugins/auth.ts +7 -5
  170. package/corpus/templates/design/server/plugins/review.ts +9 -0
  171. package/corpus/templates/design/shared/review-anchor.ts +83 -0
  172. package/corpus/templates/design/shared/review-summary.ts +25 -0
  173. package/corpus/templates/dispatch/changelog/2026-07-14-dispatch-now-distinguishes-connected-agents-from-locally-mou.md +6 -0
  174. package/corpus/templates/forms/.agents/skills/form-publishing/SKILL.md +2 -0
  175. package/corpus/templates/forms/AGENTS.md +4 -0
  176. package/corpus/templates/forms/actions/create-form.ts +2 -1
  177. package/corpus/templates/forms/actions/update-form.ts +5 -2
  178. package/corpus/templates/forms/app/i18n/ar-SA.ts +3 -0
  179. package/corpus/templates/forms/app/i18n/de-DE.ts +3 -0
  180. package/corpus/templates/forms/app/i18n/en-US.ts +3 -0
  181. package/corpus/templates/forms/app/i18n/es-ES.ts +3 -0
  182. package/corpus/templates/forms/app/i18n/fr-FR.ts +3 -0
  183. package/corpus/templates/forms/app/i18n/hi-IN.ts +3 -0
  184. package/corpus/templates/forms/app/i18n/ja-JP.ts +3 -0
  185. package/corpus/templates/forms/app/i18n/ko-KR.ts +3 -0
  186. package/corpus/templates/forms/app/i18n/pt-BR.ts +3 -0
  187. package/corpus/templates/forms/app/i18n/zh-CN.ts +3 -0
  188. package/corpus/templates/forms/app/i18n/zh-TW.ts +3 -0
  189. package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +19 -0
  190. package/corpus/templates/forms/changelog/2026-07-14-fixed-the-ask-forms-loading-input-appearing-above-the-welcom.md +6 -0
  191. package/corpus/templates/forms/changelog/2026-07-14-form-social-previews-now-show-the-form-title-description-and.md +6 -0
  192. package/corpus/templates/forms/changelog/2026-07-14-forms-can-email-the-form-owner-when-new-responses-arrive.md +6 -0
  193. package/corpus/templates/forms/server/handlers/submissions.ts +17 -0
  194. package/corpus/templates/forms/server/lib/form-og-image.ts +64 -6
  195. package/corpus/templates/forms/server/lib/public-form-ssr.ts +6 -2
  196. package/corpus/templates/forms/server/lib/response-email.ts +65 -0
  197. package/corpus/templates/forms/server/plugins/agent-chat.ts +1 -0
  198. package/corpus/templates/forms/server/routes/api/forms/og/[...slug]/og.png.get.ts +184 -0
  199. package/corpus/templates/forms/shared/types.ts +2 -0
  200. package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +6 -4
  201. package/corpus/templates/plan/.agents/skills/visual-recap/SKILL.md +7 -1
  202. package/dist/a2a/index.d.ts +2 -1
  203. package/dist/a2a/index.d.ts.map +1 -1
  204. package/dist/a2a/index.js +1 -1
  205. package/dist/a2a/index.js.map +1 -1
  206. package/dist/a2a/server.d.ts +25 -0
  207. package/dist/a2a/server.d.ts.map +1 -1
  208. package/dist/a2a/server.js +30 -6
  209. package/dist/a2a/server.js.map +1 -1
  210. package/dist/agent/production-agent.d.ts +2 -0
  211. package/dist/agent/production-agent.d.ts.map +1 -1
  212. package/dist/agent/production-agent.js +37 -12
  213. package/dist/agent/production-agent.js.map +1 -1
  214. package/dist/cli/create.d.ts +5 -3
  215. package/dist/cli/create.d.ts.map +1 -1
  216. package/dist/cli/create.js +44 -19
  217. package/dist/cli/create.js.map +1 -1
  218. package/dist/cli/pr-visual-recap-workflow.d.ts +2 -2
  219. package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
  220. package/dist/cli/pr-visual-recap-workflow.js +2 -2
  221. package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
  222. package/dist/cli/recap.d.ts +3 -562
  223. package/dist/cli/recap.d.ts.map +1 -1
  224. package/dist/cli/recap.js +3 -3875
  225. package/dist/cli/recap.js.map +1 -1
  226. package/dist/cli/skills-content/visual-plan-skill.d.ts +1 -1
  227. package/dist/cli/skills-content/visual-plan-skill.d.ts.map +1 -1
  228. package/dist/cli/skills-content/visual-plan-skill.js +6 -4
  229. package/dist/cli/skills-content/visual-plan-skill.js.map +1 -1
  230. package/dist/cli/skills-content/visual-recap-skill.d.ts +1 -1
  231. package/dist/cli/skills-content/visual-recap-skill.d.ts.map +1 -1
  232. package/dist/cli/skills-content/visual-recap-skill.js +7 -1
  233. package/dist/cli/skills-content/visual-recap-skill.js.map +1 -1
  234. package/dist/client/AgentPanel.d.ts.map +1 -1
  235. package/dist/client/AgentPanel.js +3 -3
  236. package/dist/client/AgentPanel.js.map +1 -1
  237. package/dist/client/analytics.d.ts +5 -0
  238. package/dist/client/analytics.d.ts.map +1 -1
  239. package/dist/client/analytics.js +3 -1
  240. package/dist/client/analytics.js.map +1 -1
  241. package/dist/client/chat/markdown-renderer.d.ts +1 -0
  242. package/dist/client/chat/markdown-renderer.d.ts.map +1 -1
  243. package/dist/client/chat/markdown-renderer.js +36 -1
  244. package/dist/client/chat/markdown-renderer.js.map +1 -1
  245. package/dist/client/chat/message-components.d.ts.map +1 -1
  246. package/dist/client/chat/message-components.js +5 -2
  247. package/dist/client/chat/message-components.js.map +1 -1
  248. package/dist/client/clipboard.d.ts +3 -1
  249. package/dist/client/clipboard.d.ts.map +1 -1
  250. package/dist/client/clipboard.js +24 -1
  251. package/dist/client/clipboard.js.map +1 -1
  252. package/dist/client/guided-questions.d.ts +3 -1
  253. package/dist/client/guided-questions.d.ts.map +1 -1
  254. package/dist/client/guided-questions.js +2 -1
  255. package/dist/client/guided-questions.js.map +1 -1
  256. package/dist/client/i18n.d.ts.map +1 -1
  257. package/dist/client/i18n.js +3 -1
  258. package/dist/client/i18n.js.map +1 -1
  259. package/dist/client/index.d.ts +1 -1
  260. package/dist/client/index.d.ts.map +1 -1
  261. package/dist/client/index.js +1 -1
  262. package/dist/client/index.js.map +1 -1
  263. package/dist/client/review/ReviewCommentComposer.d.ts +18 -0
  264. package/dist/client/review/ReviewCommentComposer.d.ts.map +1 -0
  265. package/dist/client/review/ReviewCommentComposer.js +30 -0
  266. package/dist/client/review/ReviewCommentComposer.js.map +1 -0
  267. package/dist/client/review/ReviewThreadPanel.d.ts +28 -1
  268. package/dist/client/review/ReviewThreadPanel.d.ts.map +1 -1
  269. package/dist/client/review/ReviewThreadPanel.js +151 -39
  270. package/dist/client/review/ReviewThreadPanel.js.map +1 -1
  271. package/dist/client/review/index.d.ts +3 -2
  272. package/dist/client/review/index.d.ts.map +1 -1
  273. package/dist/client/review/index.js +2 -1
  274. package/dist/client/review/index.js.map +1 -1
  275. package/dist/client/review/use-review.d.ts +23 -0
  276. package/dist/client/review/use-review.d.ts.map +1 -1
  277. package/dist/client/review/use-review.js +3 -0
  278. package/dist/client/review/use-review.js.map +1 -1
  279. package/dist/client/use-agent-chat-context.d.ts +1 -1
  280. package/dist/client/use-agent-chat-context.d.ts.map +1 -1
  281. package/dist/client/use-agent-chat-context.js +4 -2
  282. package/dist/client/use-agent-chat-context.js.map +1 -1
  283. package/dist/collab/awareness.d.ts +2 -2
  284. package/dist/collab/awareness.d.ts.map +1 -1
  285. package/dist/collab/struct-routes.d.ts +1 -1
  286. package/dist/credentials/index.d.ts +12 -7
  287. package/dist/credentials/index.d.ts.map +1 -1
  288. package/dist/credentials/index.js +33 -8
  289. package/dist/credentials/index.js.map +1 -1
  290. package/dist/extensions/fetch-tool.d.ts +13 -1
  291. package/dist/extensions/fetch-tool.d.ts.map +1 -1
  292. package/dist/extensions/fetch-tool.js +9 -2
  293. package/dist/extensions/fetch-tool.js.map +1 -1
  294. package/dist/notifications/channels.js +20 -4
  295. package/dist/notifications/channels.js.map +1 -1
  296. package/dist/observability/routes.d.ts +5 -5
  297. package/dist/progress/routes.d.ts +1 -1
  298. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  299. package/dist/resources/handlers.d.ts +3 -3
  300. package/dist/review/actions/create-review-comment.js +2 -1
  301. package/dist/review/actions/create-review-comment.js.map +1 -1
  302. package/dist/review/actions/get-review-feedback.js +6 -11
  303. package/dist/review/actions/get-review-feedback.js.map +1 -1
  304. package/dist/review/actions/list-review-comments.d.ts +1 -0
  305. package/dist/review/actions/list-review-comments.js +25 -4
  306. package/dist/review/actions/list-review-comments.js.map +1 -1
  307. package/dist/review/actions/reply-review-comment.js +12 -5
  308. package/dist/review/actions/reply-review-comment.js.map +1 -1
  309. package/dist/review/actions/resolve-review-thread.d.ts +3 -0
  310. package/dist/review/actions/resolve-review-thread.js +20 -3
  311. package/dist/review/actions/resolve-review-thread.js.map +1 -1
  312. package/dist/review/actions/send-review-thread-to-agent.d.ts +17 -0
  313. package/dist/review/actions/send-review-thread-to-agent.d.ts.map +1 -0
  314. package/dist/review/actions/send-review-thread-to-agent.js +49 -0
  315. package/dist/review/actions/send-review-thread-to-agent.js.map +1 -0
  316. package/dist/review/identity.d.ts +6 -0
  317. package/dist/review/identity.d.ts.map +1 -0
  318. package/dist/review/identity.js +68 -0
  319. package/dist/review/identity.js.map +1 -0
  320. package/dist/review/index.d.ts +3 -1
  321. package/dist/review/index.d.ts.map +1 -1
  322. package/dist/review/index.js +2 -1
  323. package/dist/review/index.js.map +1 -1
  324. package/dist/review/store.d.ts +36 -0
  325. package/dist/review/store.d.ts.map +1 -1
  326. package/dist/review/store.js +223 -8
  327. package/dist/review/store.js.map +1 -1
  328. package/dist/review/types.d.ts +4 -0
  329. package/dist/review/types.d.ts.map +1 -1
  330. package/dist/review/types.js.map +1 -1
  331. package/dist/secrets/crypto.d.ts +15 -7
  332. package/dist/secrets/crypto.d.ts.map +1 -1
  333. package/dist/secrets/crypto.js +23 -10
  334. package/dist/secrets/crypto.js.map +1 -1
  335. package/dist/secrets/routes.d.ts +9 -9
  336. package/dist/secrets/storage.d.ts.map +1 -1
  337. package/dist/secrets/storage.js +16 -3
  338. package/dist/secrets/storage.js.map +1 -1
  339. package/dist/server/action-discovery.d.ts.map +1 -1
  340. package/dist/server/action-discovery.js +4 -0
  341. package/dist/server/action-discovery.js.map +1 -1
  342. package/dist/server/action-routes.d.ts +45 -0
  343. package/dist/server/action-routes.d.ts.map +1 -1
  344. package/dist/server/action-routes.js +71 -5
  345. package/dist/server/action-routes.js.map +1 -1
  346. package/dist/server/agent-chat/plugin-options.d.ts +16 -0
  347. package/dist/server/agent-chat/plugin-options.d.ts.map +1 -1
  348. package/dist/server/agent-chat/plugin-options.js.map +1 -1
  349. package/dist/server/agent-chat-plugin.d.ts +20 -0
  350. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  351. package/dist/server/agent-chat-plugin.js +39 -4
  352. package/dist/server/agent-chat-plugin.js.map +1 -1
  353. package/dist/server/derived-secret.d.ts +1 -1
  354. package/dist/server/derived-secret.d.ts.map +1 -1
  355. package/dist/server/derived-secret.js.map +1 -1
  356. package/dist/server/index.d.ts +3 -1
  357. package/dist/server/index.d.ts.map +1 -1
  358. package/dist/server/index.js +2 -0
  359. package/dist/server/index.js.map +1 -1
  360. package/dist/vite/action-types-plugin.d.ts.map +1 -1
  361. package/dist/vite/action-types-plugin.js +4 -0
  362. package/dist/vite/action-types-plugin.js.map +1 -1
  363. package/docs/content/locales/ar-SA/pr-visual-recap.mdx +48 -30
  364. package/docs/content/locales/ar-SA/template-plan.mdx +7 -0
  365. package/docs/content/locales/de-DE/pr-visual-recap.mdx +48 -30
  366. package/docs/content/locales/de-DE/template-plan.mdx +7 -0
  367. package/docs/content/locales/es-ES/pr-visual-recap.mdx +48 -30
  368. package/docs/content/locales/es-ES/template-plan.mdx +14 -0
  369. package/docs/content/locales/fr-FR/pr-visual-recap.mdx +48 -30
  370. package/docs/content/locales/fr-FR/template-plan.mdx +7 -0
  371. package/docs/content/locales/hi-IN/pr-visual-recap.mdx +48 -30
  372. package/docs/content/locales/hi-IN/template-plan.mdx +7 -0
  373. package/docs/content/locales/ja-JP/pr-visual-recap.mdx +48 -30
  374. package/docs/content/locales/ja-JP/template-plan.mdx +7 -0
  375. package/docs/content/locales/ko-KR/pr-visual-recap.mdx +48 -30
  376. package/docs/content/locales/ko-KR/template-plan.mdx +7 -0
  377. package/docs/content/locales/pt-BR/pr-visual-recap.mdx +48 -30
  378. package/docs/content/locales/pt-BR/template-plan.mdx +14 -0
  379. package/docs/content/locales/zh-CN/pr-visual-recap.mdx +48 -30
  380. package/docs/content/locales/zh-CN/template-plan.mdx +7 -0
  381. package/docs/content/locales/zh-TW/pr-visual-recap.mdx +48 -30
  382. package/docs/content/locales/zh-TW/template-plan.mdx +7 -0
  383. package/docs/content/pr-visual-recap.mdx +50 -32
  384. package/docs/content/template-plan.mdx +14 -0
  385. package/docs/content/toolkit-comments-review.mdx +16 -2
  386. package/package.json +4 -1
  387. package/corpus/templates/clips/app/components/sharing/slack-share-hint.tsx +0 -68
  388. package/corpus/templates/forms/server/routes/api/forms/og/[slug]/og.png.get.ts +0 -45
@@ -1,4 +1,5 @@
1
1
  import {
2
+ createError,
2
3
  defineEventHandler,
3
4
  setResponseStatus,
4
5
  setResponseHeader,
@@ -10,6 +11,7 @@ import {
10
11
 
11
12
  import { isAgentActionStopError } from "../action.js";
12
13
  import type { ActionEntry } from "../agent/production-agent.js";
14
+ import { resolveOrgIdForEmail } from "../org/context.js";
13
15
  import { readBody } from "../server/h3-helpers.js";
14
16
  import { EMBED_TARGET_HEADER } from "../shared/embed-auth.js";
15
17
  import {
@@ -18,6 +20,10 @@ import {
18
20
  shouldAllowMcpEmbedCredentials,
19
21
  } from "../shared/mcp-embed-headers.js";
20
22
  import { notifyActionChange } from "./action-change.js";
23
+ import {
24
+ seedAgentRunOwnerContext,
25
+ type AgentRunOwnerContext,
26
+ } from "./agent-run-context.js";
21
27
  import {
22
28
  getAllowedCorsOrigin as resolveAllowedCorsOrigin,
23
29
  readCorsAllowedOrigins,
@@ -164,6 +170,51 @@ function handleOptionsRequest(event: any): string {
164
170
  return "";
165
171
  }
166
172
 
173
+ /**
174
+ * Declarative auth adapter for the HTTP action route. Its `resolveCaller` runs
175
+ * BEFORE the framework's `getOwnerFromEvent` / `getSession` chain, letting an
176
+ * app accept caller identities `getSession` doesn't understand (e.g. an A2A
177
+ * JWT) without reaching into request context from a Nitro `request` hook.
178
+ *
179
+ * Scoped to `/_agent-native/actions/*` only — it does not affect other routes.
180
+ */
181
+ export type ActionRouteResolvedCaller = AgentRunOwnerContext & {
182
+ /**
183
+ * Org to scope the request to, verified from the same credential as the
184
+ * caller identity (e.g. the A2A token's org claim). When omitted, the org
185
+ * is derived from the verified owner email via the framework's owner→org
186
+ * membership lookup. The ambient session/org state on the request is never
187
+ * consulted for adapter-resolved callers: a request can carry both a valid
188
+ * A2A bearer and an unrelated browser cookie, and the cookie user's org
189
+ * must not leak into the token caller's request context.
190
+ */
191
+ orgId?: string;
192
+ };
193
+
194
+ export interface ActionRouteAuthAdapter {
195
+ /**
196
+ * Resolve a caller from the raw event before the cookie/bearer chain.
197
+ *
198
+ * - Return the resolved caller to run the action scoped to that identity.
199
+ * Org scoping comes exclusively from the caller: the returned `orgId` if
200
+ * set, otherwise the owner-email membership lookup — never from the
201
+ * request's session cookie or org context.
202
+ * - Return `null` when the credential isn't yours to judge — the request
203
+ * defers to `getOwnerFromEvent` / `getSession`.
204
+ * - THROW to hard-reject: the credential is present but invalid (e.g. an
205
+ * expired or forged A2A bearer). The action route responds 401 and does
206
+ * NOT fall through to the cookie/session chain, so a valid same-origin
207
+ * session cookie can't be used to execute the request as the logged-in
208
+ * user. Do not throw merely to signal "not mine" — return `null` for that.
209
+ */
210
+ resolveCaller?: (
211
+ event: any,
212
+ ) =>
213
+ | ActionRouteResolvedCaller
214
+ | null
215
+ | Promise<ActionRouteResolvedCaller | null>;
216
+ }
217
+
167
218
  export interface MountActionRoutesOptions {
168
219
  /** Resolve owner email from the H3 event (for data scoping). */
169
220
  getOwnerFromEvent?: (event: any) => string | Promise<string>;
@@ -173,6 +224,18 @@ export interface MountActionRoutesOptions {
173
224
  ) => string | undefined | Promise<string | undefined>;
174
225
  /** Resolve org ID from the H3 event (for org scoping). */
175
226
  resolveOrgId?: (event: any) => string | null | Promise<string | null>;
227
+ /**
228
+ * Optional caller resolver that runs before the `getOwnerFromEvent` /
229
+ * `getSession` chain. Lets apps accept A2A JWTs (or other bearer schemes) on
230
+ * the action route declaratively. See {@link ActionRouteAuthAdapter}.
231
+ */
232
+ actionRouteAuth?: ActionRouteAuthAdapter;
233
+ }
234
+
235
+ function normalizeOrgId(value: string | null | undefined): string | undefined {
236
+ return typeof value === "string" && value.trim().length > 0
237
+ ? value.trim()
238
+ : undefined;
176
239
  }
177
240
 
178
241
  function isAuthResolutionFailure(error: unknown): boolean {
@@ -259,7 +322,42 @@ export function mountActionRoutes(
259
322
  // Resolve auth context for per-request scoping
260
323
  let userEmail: string | undefined;
261
324
  let userName: string | undefined;
262
- if (options?.getOwnerFromEvent) {
325
+ // An app-supplied auth adapter runs first: it can accept caller
326
+ // identities the framework's getSession chain doesn't understand (e.g.
327
+ // an A2A JWT). A resolved caller is seeded onto the event context so any
328
+ // downstream resolveAgentRunOwnerContext (nested agent runs) sees the
329
+ // same identity. The adapter is only consulted for the action route, so
330
+ // it can't affect other surfaces.
331
+ //
332
+ // Contract: `resolveCaller` returning `null` means "this credential
333
+ // isn't mine — defer to the cookie/session chain below". THROWING means
334
+ // "the credential is mine but invalid" (e.g. an expired/forged A2A
335
+ // bearer) and is a hard rejection: we surface a 401 instead of falling
336
+ // through, so a live same-origin session cookie can't silently execute
337
+ // the request as the logged-in user.
338
+ let resolvedCaller: ActionRouteResolvedCaller | null = null;
339
+ if (options?.actionRouteAuth?.resolveCaller) {
340
+ let caller: ActionRouteResolvedCaller | null;
341
+ try {
342
+ caller = await options.actionRouteAuth.resolveCaller(event);
343
+ } catch {
344
+ throw createError({
345
+ statusCode: 401,
346
+ statusMessage: "Unauthorized",
347
+ });
348
+ }
349
+ if (caller) {
350
+ seedAgentRunOwnerContext(event, {
351
+ owner: caller.owner,
352
+ anonymous: caller.anonymous,
353
+ name: caller.name,
354
+ });
355
+ userEmail = caller.owner;
356
+ userName = caller.name;
357
+ resolvedCaller = caller;
358
+ }
359
+ }
360
+ if (!resolvedCaller && options?.getOwnerFromEvent) {
263
361
  try {
264
362
  userEmail = await options.getOwnerFromEvent(event);
265
363
  userName = options?.getUserNameFromEvent
@@ -277,9 +375,32 @@ export function mountActionRoutes(
277
375
  }
278
376
  }
279
377
  }
280
- const orgId = options?.resolveOrgId
281
- ? ((await options.resolveOrgId(event)) ?? undefined)
282
- : undefined;
378
+ // Org scoping. For adapter-resolved callers the org must come
379
+ // exclusively from the verified credential: the adapter-asserted
380
+ // orgId when present, otherwise the owner-email membership lookup.
381
+ // The request's ambient session/org state (`resolveOrgId`, usually
382
+ // getSession-backed) is deliberately NOT consulted — a request can
383
+ // carry both a valid A2A bearer and an unrelated same-origin browser
384
+ // cookie, and the cookie user's org must not become the org the
385
+ // token caller's actions execute under. Non-adapter callers keep the
386
+ // original resolveOrgId-only behavior.
387
+ let orgId: string | undefined;
388
+ if (resolvedCaller) {
389
+ orgId = normalizeOrgId(resolvedCaller.orgId);
390
+ if (!orgId && resolvedCaller.owner && !resolvedCaller.anonymous) {
391
+ try {
392
+ orgId = normalizeOrgId(
393
+ await resolveOrgIdForEmail(resolvedCaller.owner),
394
+ );
395
+ } catch {
396
+ // Org tables may not exist yet on first boot.
397
+ }
398
+ }
399
+ } else {
400
+ orgId = options?.resolveOrgId
401
+ ? ((await options.resolveOrgId(event)) ?? undefined)
402
+ : undefined;
403
+ }
283
404
  const timezone = readTimezoneHeader(event);
284
405
 
285
406
  return runWithRequestContext(
@@ -109,6 +109,22 @@ export interface AgentChatPluginOptions {
109
109
  * agent mutations.
110
110
  */
111
111
  anonymousReadOnly?: boolean;
112
+ /**
113
+ * Optional auth adapter for the HTTP action route
114
+ * (`/_agent-native/actions/*`). Its `resolveCaller` runs before the
115
+ * cookie/bearer `getSession` chain, letting an app accept caller identities
116
+ * `getSession` doesn't understand (e.g. an A2A JWT verified with
117
+ * `verifyA2AToken`) declaratively, instead of pre-seeding request context
118
+ * from a Nitro `request` hook.
119
+ *
120
+ * Returning `null` defers to the normal chain; THROWING hard-rejects with a
121
+ * 401 (an invalid/forged credential must not fall through to a same-origin
122
+ * session cookie). A resolved caller's org comes exclusively from the
123
+ * verified credential — the returned `orgId` or the owner-email membership
124
+ * lookup — never from the request's session cookie.
125
+ * See {@link import("../action-routes.js").ActionRouteAuthAdapter}.
126
+ */
127
+ actionRouteAuth?: import("../action-routes.js").ActionRouteAuthAdapter;
112
128
  /**
113
129
  * Optional callback to append template-specific context to the system
114
130
  * prompt on each request. Runs after AGENTS.md / skills / memory are
@@ -134,6 +134,7 @@ import {
134
134
  WORKSPACE_OWNER,
135
135
  } from "../resources/store.js";
136
136
  import { normalizeDatabaseToolsMode } from "../scripts/db/tool-mode.js";
137
+ import type { ResolvedKeyReference } from "../secrets/substitution.js";
137
138
  import { getSetting, putSetting } from "../settings/store.js";
138
139
  import {
139
140
  handleSharedThreadRequest,
@@ -323,6 +324,41 @@ const generateTitleRateLimit = new Map<string, number[]>();
323
324
  * so the common small-map case stays O(1). */
324
325
  const RATE_LIMIT_SWEEP_THRESHOLD = 1000;
325
326
 
327
+ /**
328
+ * Pick the URL allowlist to enforce for a `${keys.NAME}` reference used by
329
+ * the agent fetch tool.
330
+ *
331
+ * SECURITY (audit 05 H2 alignment): the allowlist check must stay
332
+ * consistent with the scope a key actually resolved at (see the
333
+ * `getKeyAllowlist` docstring in secrets/substitution.ts). Since the fetch
334
+ * tool now resolves keys via `resolveKeyReferencesWithRequestScopes` — which
335
+ * cascades user → org → workspace scope — a plain user-scope-only allowlist
336
+ * lookup would silently miss an allowlist configured on the org/workspace
337
+ * row that actually supplied the value. When `resolvedKeys` reports which
338
+ * scope a key resolved at, look up the allowlist there; only fall back to
339
+ * the legacy user-scope lookup for a key the resolver didn't report (should
340
+ * not normally happen — every key the cascade resolves reports a ref).
341
+ */
342
+ export async function resolveFetchToolKeyAllowlist(
343
+ keyName: string,
344
+ resolvedKeys: ResolvedKeyReference[] | undefined,
345
+ owner: string,
346
+ deps: {
347
+ getKeyAllowlist: (
348
+ name: string,
349
+ scope: "user",
350
+ scopeId: string,
351
+ ) => Promise<string[] | null>;
352
+ getResolvedKeyAllowlist: (
353
+ ref: ResolvedKeyReference,
354
+ ) => Promise<string[] | null>;
355
+ },
356
+ ): Promise<string[] | null> {
357
+ const ref = resolvedKeys?.find((candidate) => candidate.name === keyName);
358
+ if (ref) return deps.getResolvedKeyAllowlist(ref);
359
+ return deps.getKeyAllowlist(keyName, "user", owner);
360
+ }
361
+
326
362
  export function createAgentChatPlugin(
327
363
  options?: AgentChatPluginOptions,
328
364
  ): NitroPluginDef {
@@ -793,21 +829,38 @@ export function createAgentChatPlugin(
793
829
  try {
794
830
  const { createFetchToolEntry } =
795
831
  await import("../extensions/fetch-tool.js");
796
- const { resolveKeyReferences, validateUrlAllowlist, getKeyAllowlist } =
797
- await import("../secrets/substitution.js");
832
+ // Resolve `${keys.NAME}` through the same request-scope cascade
833
+ // already used by extension fetches (extensions/routes.ts) and
834
+ // automation connector headers (automation/index.ts): user scope
835
+ // first (personal overrides win), then the active org scope (the
836
+ // Dispatch vault syncs workspace secrets here), then workspace
837
+ // scope. Org/workspace vault rows are write-gated (org-admin +
838
+ // Dispatch vault UI), so this is safe to read by default — unlike
839
+ // the opt-in-only user→workspace fallback in resolveKeyReferences
840
+ // (see audit 05 H2 in secrets/substitution.ts), which stays off.
841
+ // Previously this tool only looked at scope "user", so a
842
+ // ${keys.NAME} reference to a key synced into the org/workspace
843
+ // vault could never resolve here even though the same key already
844
+ // worked for extension fetches and automations.
845
+ const {
846
+ resolveKeyReferencesWithRequestScopes,
847
+ validateUrlAllowlist,
848
+ getKeyAllowlist,
849
+ getResolvedKeyAllowlist,
850
+ } = await import("../secrets/substitution.js");
798
851
  fetchTool = createFetchToolEntry({
799
852
  resolveKeys: async (text) =>
800
- resolveKeyReferences(
853
+ resolveKeyReferencesWithRequestScopes(
801
854
  text,
802
- "user",
803
855
  requireCurrentRunOwner("resolve key references"),
804
856
  ),
805
- validateUrl: async (url, usedKeys) => {
857
+ validateUrl: async (url, usedKeys, resolvedKeys) => {
806
858
  for (const keyName of usedKeys) {
807
- const allowlist = await getKeyAllowlist(
859
+ const allowlist = await resolveFetchToolKeyAllowlist(
808
860
  keyName,
809
- "user",
861
+ resolvedKeys,
810
862
  requireCurrentRunOwner("validate URL allowlist"),
863
+ { getKeyAllowlist, getResolvedKeyAllowlist },
811
864
  );
812
865
  if (allowlist && !validateUrlAllowlist(url, allowlist)) {
813
866
  return false;
@@ -1804,6 +1857,7 @@ export function createAgentChatPlugin(
1804
1857
  getOwnerFromEvent,
1805
1858
  getUserNameFromEvent,
1806
1859
  resolveOrgId: options?.resolveOrgId,
1860
+ actionRouteAuth: options?.actionRouteAuth,
1807
1861
  });
1808
1862
  }
1809
1863
 
@@ -20,7 +20,11 @@ export function deriveServerSecret(
20
20
  }
21
21
 
22
22
  export function getWorkspaceA2ADerivedSecret(
23
- purpose: "better-auth" | "oauth-state" | "short-lived-token",
23
+ purpose:
24
+ | "better-auth"
25
+ | "oauth-state"
26
+ | "short-lived-token"
27
+ | "secrets-encryption",
24
28
  ): string | undefined {
25
29
  if (!isWorkspaceRuntime()) return undefined;
26
30
  const rootSecret = process.env.A2A_SECRET?.trim();
@@ -241,6 +241,7 @@ export {
241
241
  renderAgentNativeOgImageSvg,
242
242
  type AgentNativeOgImageInput,
243
243
  } from "./social-og-image.js";
244
+ export { resolveOgFontFiles } from "./og-fonts.js";
244
245
  export {
245
246
  createBrowserSessionActionEntries,
246
247
  type CreateBrowserSessionActionEntriesOptions,
@@ -320,7 +321,14 @@ export {
320
321
  export {
321
322
  mountActionRoutes,
322
323
  type MountActionRoutesOptions,
324
+ type ActionRouteAuthAdapter,
325
+ type ActionRouteResolvedCaller,
323
326
  } from "./action-routes.js";
327
+ export {
328
+ AGENT_RUN_OWNER_CONTEXT_KEY,
329
+ seedAgentRunOwnerContext,
330
+ type AgentRunOwnerContext,
331
+ } from "./agent-run-context.js";
324
332
  export {
325
333
  runWithRequestContext,
326
334
  hasRequestContext,
@@ -141,6 +141,10 @@ const CORE_SHARING_ACTIONS: Array<{ name: string; specifier: string }> = [
141
141
  name: "set-review-status",
142
142
  specifier: "@agent-native/core/review/actions/set-review-status",
143
143
  },
144
+ {
145
+ name: "send-review-thread-to-agent",
146
+ specifier: "@agent-native/core/review/actions/send-review-thread-to-agent",
147
+ },
144
148
  ];
145
149
 
146
150
  function isRuntimeSourceFile(filename: string): boolean {
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-14
4
+ ---
5
+
6
+ Daily dashboard email captures authenticate with a session cookie, fall back to a lighter panel set, and record page diagnostics when a capture fails.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-14
4
+ ---
5
+
6
+ Long-running cross-app analyses now continue reliably in the background and can use synced workspace provider credentials.
@@ -11,6 +11,7 @@ import {
11
11
  } from "@agent-native/core/server";
12
12
  import {
13
13
  EMBED_MODE_QUERY_PARAM,
14
+ EMBED_SESSION_COOKIE,
14
15
  EMBED_TOKEN_QUERY_PARAM,
15
16
  } from "@agent-native/core/shared";
16
17
 
@@ -60,6 +61,7 @@ type DashboardScreenshotAttempt = {
60
61
  readyTimeout?: number;
61
62
  secondReadyTimeout?: number;
62
63
  totalTimeout?: number;
64
+ reportPanelLimit?: number;
63
65
  };
64
66
 
65
67
  type LaunchedScreenshotBrowser = {
@@ -466,6 +468,96 @@ async function runBoundedBrowserCleanup(
466
468
  }
467
469
  }
468
470
 
471
+ const DIAGNOSTICS_PROBE_TIMEOUT_MS = 2_000;
472
+ const DIAGNOSTICS_MAX_LENGTH = 700;
473
+ const DIAGNOSTICS_COLLECTOR_LIMIT = 5;
474
+
475
+ // Best-effort page inspection used when the report surface never becomes
476
+ // visible, so failures carry enough state to tell wrong-page/wedged-renderer/
477
+ // auth-bounce apart. Must never throw and must stay bounded even if the page
478
+ // is hung.
479
+ async function collectPageDiagnostics(
480
+ page: any,
481
+ consoleErrors: string[],
482
+ failedRequests: string[],
483
+ ): Promise<string> {
484
+ try {
485
+ let responsive = true;
486
+ let probeTimeout: ReturnType<typeof setTimeout> | undefined;
487
+ try {
488
+ await Promise.race([
489
+ Promise.resolve(page.evaluate("1")),
490
+ new Promise((_, reject) => {
491
+ probeTimeout = setTimeout(
492
+ () => reject(new Error("diagnostics probe timed out")),
493
+ DIAGNOSTICS_PROBE_TIMEOUT_MS,
494
+ );
495
+ }),
496
+ ]);
497
+ } catch {
498
+ responsive = false;
499
+ } finally {
500
+ if (probeTimeout) clearTimeout(probeTimeout);
501
+ }
502
+
503
+ if (!responsive) {
504
+ return `page unresponsive (renderer hung or crashed); consoleErrors=${JSON.stringify(
505
+ consoleErrors,
506
+ )} failedRequests=${JSON.stringify(failedRequests)}`.slice(
507
+ 0,
508
+ DIAGNOSTICS_MAX_LENGTH,
509
+ );
510
+ }
511
+
512
+ let url = "";
513
+ try {
514
+ url = page.url();
515
+ } catch {
516
+ // page may already be closed; leave url empty
517
+ }
518
+
519
+ let title = "";
520
+ let bodyText = "";
521
+ let detailsTimeout: ReturnType<typeof setTimeout> | undefined;
522
+ try {
523
+ // page.evaluate ignores setDefaultTimeout, so race it like the probe —
524
+ // a renderer that wedges after the probe must not stall diagnostics.
525
+ const details = await Promise.race([
526
+ Promise.resolve(
527
+ page.evaluate(
528
+ `(() => ({
529
+ title: document.title,
530
+ bodyText: document.body?.innerText?.slice(0, 240) ?? "",
531
+ }))()`,
532
+ ),
533
+ ),
534
+ new Promise<never>((_, reject) => {
535
+ detailsTimeout = setTimeout(
536
+ () => reject(new Error("diagnostics details timed out")),
537
+ DIAGNOSTICS_PROBE_TIMEOUT_MS,
538
+ );
539
+ }),
540
+ ]);
541
+ title = (details as any)?.title ?? "";
542
+ bodyText = (details as any)?.bodyText ?? "";
543
+ } catch {
544
+ // best effort; leave title/bodyText empty
545
+ } finally {
546
+ if (detailsTimeout) clearTimeout(detailsTimeout);
547
+ }
548
+
549
+ return `page state: ${JSON.stringify({
550
+ url,
551
+ title,
552
+ bodyText,
553
+ consoleErrors,
554
+ failedRequests,
555
+ })}`.slice(0, DIAGNOSTICS_MAX_LENGTH);
556
+ } catch {
557
+ return "diagnostics unavailable";
558
+ }
559
+ }
560
+
469
561
  async function captureDashboardPng(
470
562
  sub: DashboardReportSubscription,
471
563
  snapshot: ReportSnapshot,
@@ -488,6 +580,12 @@ async function captureDashboardPng(
488
580
  const screenshotUrl = new URL(targetPath, `${dashboardBaseUrl()}/`);
489
581
  screenshotUrl.searchParams.set(EMBED_MODE_QUERY_PARAM, "1");
490
582
  screenshotUrl.searchParams.set(EMBED_TOKEN_QUERY_PARAM, token);
583
+ if (attempt.reportPanelLimit) {
584
+ screenshotUrl.searchParams.set(
585
+ "reportPanelLimit",
586
+ String(attempt.reportPanelLimit),
587
+ );
588
+ }
491
589
 
492
590
  let browser: any;
493
591
  let cleanup = async () => {};
@@ -498,6 +596,7 @@ async function captureDashboardPng(
498
596
  let launchTimeout: ReturnType<typeof setTimeout> | undefined;
499
597
  let captureStage = "launching the screenshot browser";
500
598
  let attemptTimedOut = false;
599
+ let lastDiagnostics: string | null = null;
501
600
  const attemptTimeout = attempt.totalTimeout
502
601
  ? setTimeout(() => {
503
602
  attemptTimedOut = true;
@@ -530,6 +629,51 @@ async function captureDashboardPng(
530
629
 
531
630
  const timeout = screenshotTimeoutMs();
532
631
  const page = await newPage();
632
+
633
+ // Belt-and-braces auth: the query token authenticates only after the
634
+ // client-side bootstrap harvests it from the URL, which gives the
635
+ // stripped-down serverless browser several ways to end up session-less.
636
+ // Seeding the same signed token as a cookie authenticates every request
637
+ // server-side with no client cooperation. Never abort the capture over
638
+ // this — the query token path still exists.
639
+ try {
640
+ await page.context().addCookies([
641
+ {
642
+ name: EMBED_SESSION_COOKIE,
643
+ value: token,
644
+ url: `${dashboardBaseUrl()}/`,
645
+ },
646
+ ]);
647
+ } catch (err) {
648
+ console.warn(
649
+ "[dashboard-report] Failed to pre-seed embed session cookie:",
650
+ errorMessage(err),
651
+ );
652
+ }
653
+
654
+ // Bounded diagnostics collectors so a failed wait carries evidence of
655
+ // wrong-page/wedged-renderer/auth-bounce instead of a bare timeout.
656
+ const consoleErrors: string[] = [];
657
+ page.on("console", (msg: any) => {
658
+ if (msg.type() !== "error") return;
659
+ if (consoleErrors.length >= DIAGNOSTICS_COLLECTOR_LIMIT) return;
660
+ consoleErrors.push(msg.text().slice(0, 160));
661
+ });
662
+ const failedRequests: string[] = [];
663
+ page.on("requestfailed", (req: any) => {
664
+ if (failedRequests.length >= DIAGNOSTICS_COLLECTOR_LIMIT) return;
665
+ failedRequests.push(
666
+ `${req.method()} ${req.url().slice(0, 120)}: ${req.failure()?.errorText ?? "failed"}`,
667
+ );
668
+ });
669
+ page.on("response", (res: any) => {
670
+ if (res.status() < 400) return;
671
+ if (failedRequests.length >= DIAGNOSTICS_COLLECTOR_LIMIT) return;
672
+ failedRequests.push(
673
+ `${res.request().method()} ${res.url().slice(0, 120)}: HTTP ${res.status()}`,
674
+ );
675
+ });
676
+
533
677
  page.setDefaultTimeout(timeout);
534
678
  await page.emulateMedia({ media: "screen", colorScheme: "light" });
535
679
  await page.addInitScript(() => {
@@ -542,7 +686,14 @@ async function captureDashboardPng(
542
686
 
543
687
  captureStage = "waiting for the report surface";
544
688
  const capture = page.locator("[data-dashboard-report-capture]");
545
- await capture.waitFor({ state: "visible", timeout });
689
+ try {
690
+ await capture.waitFor({ state: "visible", timeout });
691
+ } catch (err) {
692
+ lastDiagnostics = errorMessage(
693
+ await collectPageDiagnostics(page, consoleErrors, failedRequests),
694
+ );
695
+ throw new Error(`${errorMessage(err)}; ${lastDiagnostics}`);
696
+ }
546
697
  captureStage = "waiting for dashboard queries";
547
698
  await waitForDashboardReportReady(page, attempt.readyTimeout ?? timeout);
548
699
  captureStage = "rendering lazy dashboard panels";
@@ -569,7 +720,8 @@ async function captureDashboardPng(
569
720
  } catch (err) {
570
721
  if (attemptTimedOut) {
571
722
  throw new Error(
572
- `${attempt.label} capture exceeded ${attempt.totalTimeout}ms while ${captureStage}`,
723
+ `${attempt.label} capture exceeded ${attempt.totalTimeout}ms while ${captureStage}` +
724
+ (lastDiagnostics ? `; ${lastDiagnostics}` : ""),
573
725
  );
574
726
  }
575
727
  throw new Error(`${captureStage}: ${errorMessage(err)}`);
@@ -612,7 +764,7 @@ function errorMessage(err: unknown): string {
612
764
 
613
765
  function storedAttemptError(message: string): string {
614
766
  const normalized = message.replace(/\s+/g, " ").trim();
615
- return normalized.length > 220 ? `${normalized.slice(0, 219)}…` : normalized;
767
+ return normalized.length > 400 ? `${normalized.slice(0, 399)}…` : normalized;
616
768
  }
617
769
 
618
770
  async function captureDashboardPngWithFallback(
@@ -640,6 +792,7 @@ async function captureDashboardPngWithFallback(
640
792
  label: "full-lightweight",
641
793
  viewport: { width: 1200, height: 1400 },
642
794
  captureScale: 0.7,
795
+ reportPanelLimit: 8,
643
796
  ...(serverless
644
797
  ? {
645
798
  readyTimeout: 55_000,
@@ -27,6 +27,9 @@ import {
27
27
  needsCorpusWorkflowForCoverageSensitiveRequest,
28
28
  needsSourceRecordBodyWorkflowForCoverageSensitiveRequest,
29
29
  } from "../lib/real-data-actions";
30
+
31
+ const ANALYTICS_BACKGROUND_RUN_SOFT_TIMEOUT_MS = 13 * 60_000;
32
+
30
33
  export const SIMPLE_TIME_BOUNDED_METRIC_FAST_PATH_GUIDANCE =
31
34
  "SIMPLE TIME-BOUNDED METRIC FAST PATH — When the data dictionary or a known canonical source identifies the metric, run one bounded aggregate. Once it returns a valid result, answer the explicit question immediately with the source, time window, row count, and only necessary caveats. Do not schema-discover, retry, enrich, cross-check, or add breakdowns after that successful result unless the query failed or the result conflicts with the known metric definition. This does not waive the real-data requirement: never answer from a guess, stale value, or unverified result. ";
32
35
 
@@ -271,10 +274,11 @@ export default createAgentChatPlugin({
271
274
  // Operators deploying to trusted internal environments can set
272
275
  // AGENT_PROD_CODE_EXECUTION=trusted to also enable bash/read/edit/write.
273
276
  codeExecution: { production: "sandboxed" },
274
- // Analytics uses the portable A2A processor until its dedicated background
275
- // worker is verified live. This explicit opt-out also protects production
276
- // from a stale deploy-wide AGENT_CHAT_DURABLE_BACKGROUND flag.
277
- durableBackgroundRuns: false,
277
+ // Long-running A2A analysis belongs on the durable worker so provider
278
+ // pagination, cross-source joins, and corpus reduction can outlive the
279
+ // standard serverless request budget without orphaning the task.
280
+ durableBackgroundRuns: true,
281
+ runSoftTimeoutMs: ANALYTICS_BACKGROUND_RUN_SOFT_TIMEOUT_MS,
278
282
  connectorCatalog: [...ANALYTICS_CONNECTOR_CATALOG],
279
283
  externalAgents: {
280
284
  // Keep the direct MCP surface deliberately curated. External agents