@agent-native/core 0.131.5 → 0.131.7

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 (350) hide show
  1. package/corpus/README.md +3 -3
  2. package/corpus/core/CHANGELOG.md +70 -0
  3. package/corpus/core/docs/content/agent-native-toolkit.mdx +13 -6
  4. package/corpus/core/docs/content/cloneable-saas.mdx +5 -5
  5. package/corpus/core/docs/content/creating-templates.mdx +9 -0
  6. package/corpus/core/docs/content/deployment.mdx +18 -12
  7. package/corpus/core/docs/content/doctor.mdx +8 -1
  8. package/corpus/core/docs/content/drop-in-agent.mdx +1 -1
  9. package/corpus/core/docs/content/extensions.mdx +18 -18
  10. package/corpus/core/docs/content/faq.mdx +4 -4
  11. package/corpus/core/docs/content/key-concepts.mdx +30 -21
  12. package/corpus/core/docs/content/security.mdx +2 -2
  13. package/corpus/core/docs/content/template-brain-developers.mdx +4 -1
  14. package/corpus/core/docs/content/template-mail-developers.mdx +4 -1
  15. package/corpus/core/docs/content/what-is-agent-native.mdx +6 -6
  16. package/corpus/core/package.json +1 -1
  17. package/corpus/core/src/a2a/client.ts +449 -66
  18. package/corpus/core/src/a2a/correlation.ts +31 -0
  19. package/corpus/core/src/a2a/invoke.ts +4 -2
  20. package/corpus/core/src/a2a/types.ts +4 -0
  21. package/corpus/core/src/action.ts +3 -0
  22. package/corpus/core/src/agent/action-continuation-guidance.ts +2 -1
  23. package/corpus/core/src/agent/engine/registry.ts +98 -6
  24. package/corpus/core/src/agent/production-agent.ts +151 -18
  25. package/corpus/core/src/agent/run-loop-with-resume.ts +190 -3
  26. package/corpus/core/src/agent/run-manager.ts +117 -41
  27. package/corpus/core/src/agent/thread-debug-history.ts +86 -0
  28. package/corpus/core/src/agent/types.ts +3 -1
  29. package/corpus/core/src/cli/create.ts +11 -1
  30. package/corpus/core/src/cli/templates-meta.ts +2 -2
  31. package/corpus/core/src/client/agent-chat-adapter.ts +91 -13
  32. package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +11 -9
  33. package/corpus/core/src/client/sse-event-processor.ts +17 -3
  34. package/corpus/core/src/db/client.ts +57 -17
  35. package/corpus/core/src/guards/no-env-credentials.ts +2 -0
  36. package/corpus/core/src/integrations/adapters/slack.ts +8 -3
  37. package/corpus/core/src/localization/default-messages.ts +44 -0
  38. package/corpus/core/src/observability/traces.ts +78 -5
  39. package/corpus/core/src/scripts/call-agent.ts +294 -11
  40. package/corpus/core/src/scripts/describe-workspace-apps.ts +2 -2
  41. package/corpus/core/src/secrets/crypto.ts +156 -35
  42. package/corpus/core/src/secrets/storage.ts +64 -26
  43. package/corpus/core/src/server/agent-capabilities.ts +1 -1
  44. package/corpus/core/src/server/agent-chat/action-filters-a2a.ts +113 -7
  45. package/corpus/core/src/server/agent-chat/context-tools.ts +2 -0
  46. package/corpus/core/src/server/agent-chat/plugin-options.ts +34 -1
  47. package/corpus/core/src/server/agent-chat/prompt-resources.ts +1 -1
  48. package/corpus/core/src/server/agent-chat-plugin.ts +91 -59
  49. package/corpus/core/src/templates/default/.agents/skills/secrets/SKILL.md +19 -7
  50. package/corpus/core/src/templates/headless/.agents/skills/secrets/SKILL.md +19 -7
  51. package/corpus/core/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +18 -7
  52. package/corpus/core/src/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +15 -14
  53. package/corpus/core/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +19 -7
  54. package/corpus/core/src/vite/client.ts +1 -0
  55. package/corpus/templates/analytics/.agents/skills/dashboard-ops/SKILL.md +5 -4
  56. package/corpus/templates/analytics/.agents/skills/gong/SKILL.md +6 -4
  57. package/corpus/templates/analytics/AGENTS.md +7 -4
  58. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +4 -3
  59. package/corpus/templates/analytics/changelog/2026-07-30-delegated-analytics-questions-now-return-a-useful-current-me.md +6 -0
  60. package/corpus/templates/analytics/changelog/2026-07-30-scheduled-dashboard-emails-complete-every-panel-without-pool.md +6 -0
  61. package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +28 -1
  62. package/corpus/templates/analytics/server/jobs/dashboard-report.ts +18 -11
  63. package/corpus/templates/analytics/server/lib/analytics-connector-catalog.ts +4 -4
  64. package/corpus/templates/analytics/server/lib/canonical-first-party-dashboard-repair.ts +9 -5
  65. package/corpus/templates/analytics/server/lib/dashboard-panel-query.ts +6 -2
  66. package/corpus/templates/analytics/server/lib/dashboard-panel-source-resolver.ts +11 -4
  67. package/corpus/templates/analytics/server/lib/dashboard-report-render.ts +49 -31
  68. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +16 -8
  69. package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +9 -3
  70. package/corpus/templates/analytics/server/lib/production-serverless-runtime.ts +11 -0
  71. package/corpus/templates/analytics/server/lib/real-data-actions.ts +10 -0
  72. package/corpus/templates/analytics/server/plugins/agent-chat.ts +3 -2
  73. package/corpus/templates/analytics/server/plugins/analytics-alert-jobs.ts +2 -1
  74. package/corpus/templates/analytics/server/plugins/dashboard-report-jobs.ts +2 -1
  75. package/corpus/templates/analytics/server/plugins/uptime-monitor-jobs.ts +1 -12
  76. package/corpus/templates/brain/.agents/skills/brain/RUNBOOK.md +54 -6
  77. package/corpus/templates/brain/.agents/skills/brain/SKILL.md +20 -9
  78. package/corpus/templates/brain/.agents/skills/ingestion-and-connectors/SKILL.md +33 -1
  79. package/corpus/templates/brain/AGENTS.md +3 -1
  80. package/corpus/templates/brain/README.md +4 -1
  81. package/corpus/templates/brain/actions/_schemas.ts +30 -8
  82. package/corpus/templates/brain/actions/ask-brain.ts +124 -14
  83. package/corpus/templates/brain/actions/create-source.ts +18 -2
  84. package/corpus/templates/brain/actions/enqueue-captures-distillation.ts +8 -123
  85. package/corpus/templates/brain/actions/enqueue-distillation.ts +6 -127
  86. package/corpus/templates/brain/actions/import-capture.ts +17 -5
  87. package/corpus/templates/brain/actions/import-transcript.ts +17 -5
  88. package/corpus/templates/brain/actions/update-source.ts +25 -5
  89. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +1 -1
  90. package/corpus/templates/brain/changelog/2026-07-30-blessed-resources-can-feed-cited-company-answers.md +6 -0
  91. package/corpus/templates/brain/changelog/2026-07-30-the-left-sidebar-no-longer-shows-a-blank-organization-placeh.md +6 -0
  92. package/corpus/templates/brain/server/lib/brain.ts +49 -19
  93. package/corpus/templates/brain/server/lib/distillation-queue.ts +147 -0
  94. package/corpus/templates/brain/server/lib/source-policy.ts +264 -0
  95. package/corpus/templates/brain/server/plugins/agent-chat.ts +3 -2
  96. package/corpus/templates/brain/server/routes/api/_agent-native/brain/ingest.post.ts +116 -19
  97. package/corpus/templates/clips/app/components/meetings/google-oauth-identity-notice.tsx +51 -0
  98. package/corpus/templates/clips/app/i18n/en-US.ts +4 -0
  99. package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +3 -1
  100. package/corpus/templates/clips/changelog/2026-07-30-google-calendar-warning.md +6 -0
  101. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +72 -8
  102. package/corpus/templates/content/changelog/2026-07-30-the-slash-command-hint-now-stays-on-only-the-active-empty-li.md +6 -0
  103. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +506 -11
  104. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +148 -17
  105. package/corpus/templates/design/app/components/design/canvas-interactions/design-canvas-interactions.ts +357 -0
  106. package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +7 -466
  107. package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +15 -311
  108. package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +19 -997
  109. package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +8 -1216
  110. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +31 -38
  111. package/corpus/templates/design/package.json +0 -1
  112. package/corpus/templates/dispatch/AGENTS.md +8 -0
  113. package/corpus/templates/dispatch/DEVELOPING.md +29 -0
  114. package/corpus/templates/dispatch/actions/view-screen.ts +34 -2
  115. package/corpus/templates/dispatch/app/i18n-data.ts +457 -0
  116. package/corpus/templates/dispatch/changelog/2026-07-30-delegated-dispatch-work-continues-reliably-in-the-background.md +6 -0
  117. package/corpus/templates/dispatch/changelog/2026-07-30-find-failed-runs-across-apps.md +6 -0
  118. package/corpus/templates/dispatch/netlify.toml +3 -0
  119. package/corpus/templates/plan/actions/get-visual-plan.ts +10 -6
  120. package/corpus/templates/plan/actions/patch-visual-plan-source.ts +117 -1
  121. package/corpus/templates/plan/actions/update-visual-plan.ts +56 -14
  122. package/corpus/templates/plan/app/pages/PlansPage.tsx +1 -1
  123. package/corpus/templates/plan/changelog/2026-07-30-plan-agents-recover-with-targeted-writes.md +6 -0
  124. package/corpus/templates/plan/shared/plan-content.ts +35 -0
  125. package/corpus/templates/slides/.agents/skills/analytics-data-for-decks/SKILL.md +8 -12
  126. package/corpus/templates/slides/AGENTS.md +4 -4
  127. package/corpus/templates/slides/actions/create-deck.ts +1 -1
  128. package/corpus/templates/slides/actions/duplicate-deck.ts +19 -4
  129. package/corpus/templates/slides/app/components/deck/DeckCard.tsx +2 -10
  130. package/corpus/templates/slides/app/components/deck/MermaidRenderer.tsx +12 -1
  131. package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +30 -13
  132. package/corpus/templates/slides/app/components/editor/DeckEditorSkeleton.tsx +35 -0
  133. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +63 -56
  134. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +21 -76
  135. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +1110 -292
  136. package/corpus/templates/slides/app/components/editor/SlideOverflowWarning.tsx +53 -0
  137. package/corpus/templates/slides/app/components/editor/SlideStyleInspector.tsx +235 -18
  138. package/corpus/templates/slides/app/components/editor/SpeakerNotesPanel.tsx +4 -1
  139. package/corpus/templates/slides/app/components/editor/canvas-interactions/index.ts +11 -0
  140. package/corpus/templates/slides/app/components/editor/canvas-interactions/slides-canvas-adapter.ts +129 -0
  141. package/corpus/templates/slides/app/components/editor/selection-overlay-measurement.ts +70 -0
  142. package/corpus/templates/slides/app/components/editor/slide-object-interactions.ts +519 -65
  143. package/corpus/templates/slides/app/components/visual-editor/CanvasCommentPins.tsx +36 -426
  144. package/corpus/templates/slides/app/components/visual-editor/DrawOverlay.tsx +19 -458
  145. package/corpus/templates/slides/app/context/DeckContext.tsx +179 -72
  146. package/corpus/templates/slides/app/global.css +105 -0
  147. package/corpus/templates/slides/app/i18n/en-US.ts +8 -0
  148. package/corpus/templates/slides/app/lib/deck-editor-loading.ts +26 -0
  149. package/corpus/templates/slides/app/lib/mermaid-blocks.ts +27 -0
  150. package/corpus/templates/slides/app/pages/DeckEditor.tsx +71 -38
  151. package/corpus/templates/slides/app/pages/Index.tsx +98 -41
  152. package/corpus/templates/slides/changelog/2026-07-30-deck-loading-no-longer-flashes-an-unavailable-message.md +6 -0
  153. package/corpus/templates/slides/changelog/2026-07-30-duplicating-a-deck-from-the-deck-list-now-opens-the-copy-imm.md +6 -0
  154. package/corpus/templates/slides/changelog/2026-07-30-layout-overflow-warning-is-readable-and-dismissible.md +6 -0
  155. package/corpus/templates/slides/changelog/2026-07-30-new-decks-now-start-with-an-empty-slide-list-when-no-slides-.md +6 -0
  156. package/corpus/templates/slides/changelog/2026-07-30-shared-canvas-annotations.md +6 -0
  157. package/corpus/templates/slides/changelog/2026-07-30-slide-objects-can-be-moved-as-a-group-copied-and-pasted-with.md +6 -0
  158. package/corpus/templates/slides/changelog/2026-07-30-slide-text-editing-and-object-controls-now-match-google-slides.md +6 -0
  159. package/corpus/templates/slides/changelog/2026-07-30-style-panel-now-scrolls-with-speaker-notes-open-shows-the-sl.md +6 -0
  160. package/corpus/templates/slides/changelog/2026-07-30-top-toolbar-controls-now-use-consistent-sizing-with-undo-and.md +6 -0
  161. package/corpus/templates/slides/netlify.toml +3 -1
  162. package/corpus/templates/slides/package.json +0 -1
  163. package/corpus/templates/slides/server/lib/chat-attachments.ts +18 -0
  164. package/corpus/templates/slides/server/plugins/agent-chat.ts +5 -0
  165. package/corpus/templates/slides/vite.config.ts +0 -1
  166. package/corpus/toolkit/CHANGELOG.md +13 -0
  167. package/corpus/toolkit/README.md +19 -0
  168. package/corpus/toolkit/agent-native.eject.json +38 -0
  169. package/corpus/toolkit/package.json +29 -1
  170. package/corpus/toolkit/src/canvas-annotations/CanvasCommentPins.tsx +861 -0
  171. package/corpus/toolkit/src/canvas-annotations/DrawOverlay.tsx +1233 -0
  172. package/corpus/toolkit/src/canvas-annotations/index.ts +15 -0
  173. package/corpus/toolkit/src/canvas-annotations/types.ts +14 -0
  174. package/corpus/toolkit/src/canvas-interactions/canvas-interactions.ts +933 -0
  175. package/corpus/toolkit/src/canvas-interactions/index.ts +67 -0
  176. package/corpus/toolkit/src/design-tweaks/scrub-input-utils.ts +311 -0
  177. package/corpus/toolkit/src/design-tweaks/scrub-input.tsx +491 -0
  178. package/corpus/toolkit/src/design-tweaks/visual-style-controls.tsx +26 -171
  179. package/corpus/toolkit/src/index.ts +1 -0
  180. package/dist/a2a/client.d.ts +23 -0
  181. package/dist/a2a/client.d.ts.map +1 -1
  182. package/dist/a2a/client.js +309 -44
  183. package/dist/a2a/client.js.map +1 -1
  184. package/dist/a2a/correlation.d.ts +1 -0
  185. package/dist/a2a/correlation.d.ts.map +1 -1
  186. package/dist/a2a/correlation.js +27 -0
  187. package/dist/a2a/correlation.js.map +1 -1
  188. package/dist/a2a/invoke.d.ts.map +1 -1
  189. package/dist/a2a/invoke.js +4 -2
  190. package/dist/a2a/invoke.js.map +1 -1
  191. package/dist/a2a/types.d.ts +4 -0
  192. package/dist/a2a/types.d.ts.map +1 -1
  193. package/dist/a2a/types.js.map +1 -1
  194. package/dist/action.d.ts +3 -0
  195. package/dist/action.d.ts.map +1 -1
  196. package/dist/action.js.map +1 -1
  197. package/dist/agent/action-continuation-guidance.d.ts.map +1 -1
  198. package/dist/agent/action-continuation-guidance.js +2 -1
  199. package/dist/agent/action-continuation-guidance.js.map +1 -1
  200. package/dist/agent/engine/registry.d.ts.map +1 -1
  201. package/dist/agent/engine/registry.js +82 -8
  202. package/dist/agent/engine/registry.js.map +1 -1
  203. package/dist/agent/production-agent.d.ts +40 -1
  204. package/dist/agent/production-agent.d.ts.map +1 -1
  205. package/dist/agent/production-agent.js +113 -15
  206. package/dist/agent/production-agent.js.map +1 -1
  207. package/dist/agent/run-loop-with-resume.d.ts +21 -0
  208. package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
  209. package/dist/agent/run-loop-with-resume.js +163 -4
  210. package/dist/agent/run-loop-with-resume.js.map +1 -1
  211. package/dist/agent/run-manager.d.ts +16 -9
  212. package/dist/agent/run-manager.d.ts.map +1 -1
  213. package/dist/agent/run-manager.js +93 -42
  214. package/dist/agent/run-manager.js.map +1 -1
  215. package/dist/agent/thread-debug-history.d.ts +10 -0
  216. package/dist/agent/thread-debug-history.d.ts.map +1 -0
  217. package/dist/agent/thread-debug-history.js +68 -0
  218. package/dist/agent/thread-debug-history.js.map +1 -0
  219. package/dist/agent/types.d.ts +3 -1
  220. package/dist/agent/types.d.ts.map +1 -1
  221. package/dist/agent/types.js.map +1 -1
  222. package/dist/cli/create.d.ts.map +1 -1
  223. package/dist/cli/create.js +6 -1
  224. package/dist/cli/create.js.map +1 -1
  225. package/dist/cli/templates-meta.js +2 -2
  226. package/dist/cli/templates-meta.js.map +1 -1
  227. package/dist/client/agent-chat-adapter.d.ts +1 -1
  228. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  229. package/dist/client/agent-chat-adapter.js +76 -13
  230. package/dist/client/agent-chat-adapter.js.map +1 -1
  231. package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
  232. package/dist/client/resources/McpIntegrationDialog.js +1 -1
  233. package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
  234. package/dist/client/sse-event-processor.d.ts.map +1 -1
  235. package/dist/client/sse-event-processor.js +12 -3
  236. package/dist/client/sse-event-processor.js.map +1 -1
  237. package/dist/collab/routes.d.ts +1 -1
  238. package/dist/db/client.d.ts.map +1 -1
  239. package/dist/db/client.js +48 -17
  240. package/dist/db/client.js.map +1 -1
  241. package/dist/guards/no-env-credentials.d.ts.map +1 -1
  242. package/dist/guards/no-env-credentials.js +2 -0
  243. package/dist/guards/no-env-credentials.js.map +1 -1
  244. package/dist/integrations/adapters/slack.js +7 -3
  245. package/dist/integrations/adapters/slack.js.map +1 -1
  246. package/dist/localization/default-messages.d.ts +43 -0
  247. package/dist/localization/default-messages.d.ts.map +1 -1
  248. package/dist/localization/default-messages.js +43 -0
  249. package/dist/localization/default-messages.js.map +1 -1
  250. package/dist/observability/traces.d.ts +3 -1
  251. package/dist/observability/traces.d.ts.map +1 -1
  252. package/dist/observability/traces.js +73 -4
  253. package/dist/observability/traces.js.map +1 -1
  254. package/dist/progress/routes.d.ts +1 -1
  255. package/dist/provider-api/actions/custom-provider-registration.d.ts +12 -12
  256. package/dist/provider-api/actions/provider-api.d.ts +13 -13
  257. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  258. package/dist/scripts/call-agent.d.ts.map +1 -1
  259. package/dist/scripts/call-agent.js +237 -12
  260. package/dist/scripts/call-agent.js.map +1 -1
  261. package/dist/scripts/describe-workspace-apps.js +2 -2
  262. package/dist/scripts/describe-workspace-apps.js.map +1 -1
  263. package/dist/secrets/crypto.d.ts +36 -21
  264. package/dist/secrets/crypto.d.ts.map +1 -1
  265. package/dist/secrets/crypto.js +134 -33
  266. package/dist/secrets/crypto.js.map +1 -1
  267. package/dist/secrets/storage.d.ts +6 -6
  268. package/dist/secrets/storage.d.ts.map +1 -1
  269. package/dist/secrets/storage.js +43 -26
  270. package/dist/secrets/storage.js.map +1 -1
  271. package/dist/server/agent-capabilities.js +1 -1
  272. package/dist/server/agent-capabilities.js.map +1 -1
  273. package/dist/server/agent-chat/action-filters-a2a.d.ts +17 -3
  274. package/dist/server/agent-chat/action-filters-a2a.d.ts.map +1 -1
  275. package/dist/server/agent-chat/action-filters-a2a.js +94 -3
  276. package/dist/server/agent-chat/action-filters-a2a.js.map +1 -1
  277. package/dist/server/agent-chat/context-tools.d.ts.map +1 -1
  278. package/dist/server/agent-chat/context-tools.js +2 -0
  279. package/dist/server/agent-chat/context-tools.js.map +1 -1
  280. package/dist/server/agent-chat/plugin-options.d.ts +23 -0
  281. package/dist/server/agent-chat/plugin-options.d.ts.map +1 -1
  282. package/dist/server/agent-chat/plugin-options.js +4 -1
  283. package/dist/server/agent-chat/plugin-options.js.map +1 -1
  284. package/dist/server/agent-chat/prompt-resources.js +1 -1
  285. package/dist/server/agent-chat/prompt-resources.js.map +1 -1
  286. package/dist/server/agent-chat-plugin.d.ts +2 -1
  287. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  288. package/dist/server/agent-chat-plugin.js +79 -56
  289. package/dist/server/agent-chat-plugin.js.map +1 -1
  290. package/dist/server/realtime-token.d.ts +1 -1
  291. package/dist/templates/default/.agents/skills/secrets/SKILL.md +19 -7
  292. package/dist/templates/headless/.agents/skills/secrets/SKILL.md +19 -7
  293. package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +18 -7
  294. package/dist/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +15 -14
  295. package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +19 -7
  296. package/dist/vite/client.d.ts.map +1 -1
  297. package/dist/vite/client.js +1 -0
  298. package/dist/vite/client.js.map +1 -1
  299. package/docs/content/agent-native-toolkit.mdx +13 -6
  300. package/docs/content/cloneable-saas.mdx +5 -5
  301. package/docs/content/creating-templates.mdx +9 -0
  302. package/docs/content/deployment.mdx +18 -12
  303. package/docs/content/doctor.mdx +8 -1
  304. package/docs/content/drop-in-agent.mdx +1 -1
  305. package/docs/content/extensions.mdx +18 -18
  306. package/docs/content/faq.mdx +4 -4
  307. package/docs/content/key-concepts.mdx +30 -21
  308. package/docs/content/security.mdx +2 -2
  309. package/docs/content/template-brain-developers.mdx +4 -1
  310. package/docs/content/template-mail-developers.mdx +4 -1
  311. package/docs/content/what-is-agent-native.mdx +6 -6
  312. package/package.json +3 -3
  313. package/src/a2a/client.ts +449 -66
  314. package/src/a2a/correlation.ts +31 -0
  315. package/src/a2a/invoke.ts +4 -2
  316. package/src/a2a/types.ts +4 -0
  317. package/src/action.ts +3 -0
  318. package/src/agent/action-continuation-guidance.ts +2 -1
  319. package/src/agent/engine/registry.ts +98 -6
  320. package/src/agent/production-agent.ts +151 -18
  321. package/src/agent/run-loop-with-resume.ts +190 -3
  322. package/src/agent/run-manager.ts +117 -41
  323. package/src/agent/thread-debug-history.ts +86 -0
  324. package/src/agent/types.ts +3 -1
  325. package/src/cli/create.ts +11 -1
  326. package/src/cli/templates-meta.ts +2 -2
  327. package/src/client/agent-chat-adapter.ts +91 -13
  328. package/src/client/resources/McpIntegrationDialog.tsx +11 -9
  329. package/src/client/sse-event-processor.ts +17 -3
  330. package/src/db/client.ts +57 -17
  331. package/src/guards/no-env-credentials.ts +2 -0
  332. package/src/integrations/adapters/slack.ts +8 -3
  333. package/src/localization/default-messages.ts +44 -0
  334. package/src/observability/traces.ts +78 -5
  335. package/src/scripts/call-agent.ts +294 -11
  336. package/src/scripts/describe-workspace-apps.ts +2 -2
  337. package/src/secrets/crypto.ts +156 -35
  338. package/src/secrets/storage.ts +64 -26
  339. package/src/server/agent-capabilities.ts +1 -1
  340. package/src/server/agent-chat/action-filters-a2a.ts +113 -7
  341. package/src/server/agent-chat/context-tools.ts +2 -0
  342. package/src/server/agent-chat/plugin-options.ts +34 -1
  343. package/src/server/agent-chat/prompt-resources.ts +1 -1
  344. package/src/server/agent-chat-plugin.ts +91 -59
  345. package/src/templates/default/.agents/skills/secrets/SKILL.md +19 -7
  346. package/src/templates/headless/.agents/skills/secrets/SKILL.md +19 -7
  347. package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +18 -7
  348. package/src/templates/workspace-core/.agents/skills/composable-mini-apps/SKILL.md +15 -14
  349. package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +19 -7
  350. package/src/vite/client.ts +1 -0
@@ -1,3 +1,4 @@
1
+ import { randomUUID } from "node:crypto";
1
2
  import * as jose from "jose";
2
3
  import { ssrfSafeFetch } from "../extensions/url-safety.js";
3
4
  /**
@@ -46,6 +47,10 @@ function workspacePrivateOrigins() {
46
47
  }
47
48
  import { sanitizeA2ACorrelationMetadata } from "./correlation.js";
48
49
  const DEFAULT_A2A_POLL_REQUEST_TIMEOUT_MS = 15_000;
50
+ const DEFAULT_A2A_DISCOVERY_TIMEOUT_MS = 3_000;
51
+ const MAX_A2A_RPC_ATTEMPTS = 3;
52
+ const A2A_RPC_RETRY_BASE_MS = 100;
53
+ export const MAX_A2A_CALLER_RESPONSE_CHARS = 32_768;
49
54
  export class A2ATaskTimeoutError extends Error {
50
55
  taskId;
51
56
  lastTask;
@@ -61,6 +66,40 @@ export class A2ATaskTimeoutError extends Error {
61
66
  this.timeoutMs = timeoutMs;
62
67
  }
63
68
  }
69
+ /**
70
+ * Preserves a receiver's terminal protocol state across the text-oriented
71
+ * callAgent convenience boundary. Callers can distinguish a real answer from
72
+ * failure, cancellation, approval/input, and an invalid empty completion
73
+ * without parsing English prose.
74
+ */
75
+ export class A2ATaskTerminalError extends Error {
76
+ taskId;
77
+ state;
78
+ responseText;
79
+ errorCode;
80
+ task;
81
+ constructor(task, state, responseText, errorCode = `a2a_task_${state.replace(/-/g, "_")}`) {
82
+ const detail = responseText.trim()
83
+ ? `: ${boundA2ACallerResponseText(responseText).trim()}`
84
+ : "";
85
+ super(`A2A task ${task.id} ended ${state}${detail}`);
86
+ this.name = "A2ATaskTerminalError";
87
+ this.taskId = task.id;
88
+ this.state = state;
89
+ this.responseText = boundA2ACallerResponseText(responseText);
90
+ this.errorCode = errorCode;
91
+ this.task = task;
92
+ }
93
+ }
94
+ /** Keep both the answer lead and artifact/source tail within caller context. */
95
+ export function boundA2ACallerResponseText(value) {
96
+ if (value.length <= MAX_A2A_CALLER_RESPONSE_CHARS)
97
+ return value;
98
+ const marker = "\n\n...[A2A response compacted at the caller boundary; use the receiving app or returned artifact links for full details]...\n\n";
99
+ const tailChars = 8_192;
100
+ const headChars = MAX_A2A_CALLER_RESPONSE_CHARS - tailChars - marker.length;
101
+ return value.slice(0, headChars) + marker + value.slice(-tailChars);
102
+ }
64
103
  /**
65
104
  * Sign a JWT for A2A cross-app identity verification.
66
105
  *
@@ -167,35 +206,72 @@ export class A2AClient {
167
206
  method,
168
207
  params,
169
208
  };
170
- await this.ensureEndpointCandidates();
209
+ const discoveryTimeoutMs = resolveA2ADiscoveryTimeoutMs(options?.requestTimeoutMs ?? this.requestTimeoutMs, options?.deadlineMs);
210
+ await this.ensureEndpointCandidates(discoveryTimeoutMs);
171
211
  let lastError = null;
172
212
  for (const url of this.endpointCandidates) {
173
213
  for (let i = 0; i < this.apiKeyAttempts.length; i++) {
174
- console.log(`[A2A Client] POST ${url} method=${method}`);
175
- const startTime = Date.now();
176
- const res = await this.postJson(url, body, this.apiKeyAttempts[i], options?.requestTimeoutMs);
177
- console.log(`[A2A Client] Response: ${res.status} in ${Date.now() - startTime}ms`);
178
- if (res.ok) {
214
+ const maxAttempts = isRetrySafeA2ARpc(method, params, this.apiKeyAttempts[i])
215
+ ? MAX_A2A_RPC_ATTEMPTS
216
+ : 1;
217
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
218
+ const requestTimeoutMs = resolveA2ARequestTimeoutMs(options?.requestTimeoutMs ?? this.requestTimeoutMs, options?.deadlineMs);
219
+ if (requestTimeoutMs !== undefined && requestTimeoutMs <= 0) {
220
+ throw new Error("A2A request deadline exceeded");
221
+ }
222
+ console.log(`[A2A Client] POST ${url} method=${method} attempt=${attempt}/${maxAttempts}`);
223
+ const startTime = Date.now();
224
+ let res;
225
+ try {
226
+ res = await this.postJson(url, body, this.apiKeyAttempts[i], requestTimeoutMs);
227
+ }
228
+ catch (error) {
229
+ lastError =
230
+ error instanceof Error ? error : new Error(String(error));
231
+ if (attempt < maxAttempts) {
232
+ await waitForA2ARetry(attempt, null, remainingA2ADeadlineMs(options?.deadlineMs));
233
+ continue;
234
+ }
235
+ break;
236
+ }
237
+ console.log(`[A2A Client] Response: ${res.status} in ${Date.now() - startTime}ms`);
238
+ if (res.ok) {
239
+ const text = await res.text();
240
+ if (i < this.apiKeyAttempts.length - 1 &&
241
+ isA2AAuthRejectionResponse(res.status, text)) {
242
+ lastError = new Error(`A2A request failed (${res.status}): ${text}`);
243
+ break;
244
+ }
245
+ try {
246
+ const parsed = JSON.parse(text);
247
+ this.endpointCandidates = [url];
248
+ this.markApiKeySucceeded(this.apiKeyAttempts[i]);
249
+ return parsed;
250
+ }
251
+ catch (error) {
252
+ lastError = new Error(`A2A response was not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
253
+ if (attempt < maxAttempts) {
254
+ await waitForA2ARetry(attempt, null, remainingA2ADeadlineMs(options?.deadlineMs));
255
+ continue;
256
+ }
257
+ break;
258
+ }
259
+ }
179
260
  const text = await res.text();
261
+ lastError = new Error(`A2A request failed (${res.status}): ${text}`);
180
262
  if (i < this.apiKeyAttempts.length - 1 &&
181
263
  isA2AAuthRejectionResponse(res.status, text)) {
182
- lastError = new Error(`A2A request failed (${res.status}): ${text}`);
264
+ break;
265
+ }
266
+ if (isRetryableA2AStatus(res.status) && attempt < maxAttempts) {
267
+ await waitForA2ARetry(attempt, res.headers.get("retry-after"), remainingA2ADeadlineMs(options?.deadlineMs));
183
268
  continue;
184
269
  }
185
- this.endpointCandidates = [url];
186
- this.markApiKeySucceeded(this.apiKeyAttempts[i]);
187
- return JSON.parse(text);
188
- }
189
- const text = await res.text();
190
- lastError = new Error(`A2A request failed (${res.status}): ${text}`);
191
- if (i < this.apiKeyAttempts.length - 1 &&
192
- isA2AAuthRejectionResponse(res.status, text)) {
193
- continue;
194
- }
195
- if (!shouldTryNextEndpoint(res.status)) {
196
- throw lastError;
270
+ if (!shouldTryNextEndpoint(res.status)) {
271
+ throw lastError;
272
+ }
273
+ break;
197
274
  }
198
- break;
199
275
  }
200
276
  }
201
277
  throw lastError ?? new Error("No A2A endpoint candidates available");
@@ -219,11 +295,16 @@ export class A2AClient {
219
295
  message,
220
296
  contextId: opts?.contextId,
221
297
  metadata: opts?.metadata,
222
- ...(opts?.idempotencyKey ? { idempotencyKey: opts.idempotencyKey } : {}),
298
+ ...(opts?.idempotencyKey
299
+ ? { idempotencyKey: opts.idempotencyKey }
300
+ : {}),
223
301
  ...(opts?.approvedActions?.length
224
302
  ? { approvedActions: opts.approvedActions }
225
303
  : {}),
226
304
  ...(opts?.async ? { async: true } : {}),
305
+ }, {
306
+ requestTimeoutMs: opts?.requestTimeoutMs,
307
+ deadlineMs: opts?.deadlineMs,
227
308
  });
228
309
  if (response.error) {
229
310
  throw new Error(`A2A error (${response.error.code}): ${response.error.message}`);
@@ -234,7 +315,10 @@ export class A2AClient {
234
315
  * Poll for a task by id. Used in async mode after `send({ async: true })`.
235
316
  */
236
317
  async getTask(taskId, opts) {
237
- const response = await this.rpc("tasks/get", { id: taskId }, { requestTimeoutMs: opts?.requestTimeoutMs });
318
+ const response = await this.rpc("tasks/get", { id: taskId }, {
319
+ requestTimeoutMs: opts?.requestTimeoutMs,
320
+ deadlineMs: opts?.deadlineMs,
321
+ });
238
322
  if (response.error) {
239
323
  throw new Error(`A2A error (${response.error.code}): ${response.error.message}`);
240
324
  }
@@ -267,6 +351,8 @@ export class A2AClient {
267
351
  * receiving side and is checked via `tasks/get`.
268
352
  */
269
353
  async sendAndWait(message, opts) {
354
+ const timeoutMs = opts?.timeoutMs ?? 5 * 60_000;
355
+ const deadlineMs = Date.now() + timeoutMs;
270
356
  const submitted = await this.send(message, {
271
357
  contextId: opts?.contextId,
272
358
  metadata: opts?.metadata,
@@ -275,8 +361,10 @@ export class A2AClient {
275
361
  ? { approvedActions: opts.approvedActions }
276
362
  : {}),
277
363
  async: true,
364
+ requestTimeoutMs: Math.min(this.requestTimeoutMs ?? DEFAULT_A2A_POLL_REQUEST_TIMEOUT_MS, Math.max(1, deadlineMs - Date.now())),
365
+ deadlineMs,
278
366
  });
279
- return this.pollTask(submitted, opts);
367
+ return this.pollTask(submitted, { ...opts, timeoutMs, deadlineMs });
280
368
  }
281
369
  /**
282
370
  * Continue waiting for an existing async task without submitting a second
@@ -284,9 +372,14 @@ export class A2AClient {
284
372
  * task is still working.
285
373
  */
286
374
  async waitForTask(taskId, opts) {
287
- const current = await this.getTask(taskId);
288
- opts?.onUpdate?.(current);
289
- return this.pollTask(current, opts);
375
+ const timeoutMs = opts?.timeoutMs ?? 5 * 60_000;
376
+ const deadlineMs = Date.now() + timeoutMs;
377
+ const current = await this.getTask(taskId, {
378
+ requestTimeoutMs: Math.min(this.requestTimeoutMs ?? DEFAULT_A2A_POLL_REQUEST_TIMEOUT_MS, Math.max(1, deadlineMs - Date.now())),
379
+ deadlineMs,
380
+ });
381
+ safelyNotifyA2AUpdate(opts?.onUpdate, current);
382
+ return this.pollTask(current, { ...opts, timeoutMs, deadlineMs });
290
383
  }
291
384
  async pollTask(submitted, opts) {
292
385
  const terminalStates = new Set([
@@ -299,7 +392,7 @@ export class A2AClient {
299
392
  return submitted;
300
393
  const timeoutMs = opts?.timeoutMs ?? 5 * 60_000;
301
394
  const pollMs = opts?.pollIntervalMs ?? 2_000;
302
- const deadline = Date.now() + timeoutMs;
395
+ const deadline = opts?.deadlineMs ?? Date.now() + timeoutMs;
303
396
  let current = submitted;
304
397
  while (Date.now() < deadline) {
305
398
  const sleepMs = Math.min(pollMs, Math.max(0, deadline - Date.now()));
@@ -310,12 +403,17 @@ export class A2AClient {
310
403
  try {
311
404
  current = await this.getTask(submitted.id, {
312
405
  requestTimeoutMs: Math.min(this.requestTimeoutMs ?? DEFAULT_A2A_POLL_REQUEST_TIMEOUT_MS, remainingMs),
406
+ deadlineMs: deadline,
313
407
  });
314
- opts?.onUpdate?.(current);
408
+ safelyNotifyA2AUpdate(opts?.onUpdate, current);
315
409
  }
316
- catch {
317
- // Transient fetch failure keep polling until the deadline.
318
- continue;
410
+ catch (error) {
411
+ // Retry only transport/gateway interruptions. Authentication,
412
+ // task-not-found, invalid params, and other protocol failures are
413
+ // permanent for this poll and must surface immediately.
414
+ if (isRetryableA2APollError(error))
415
+ continue;
416
+ throw error;
319
417
  }
320
418
  if (terminalStates.has(current.status.state))
321
419
  return current;
@@ -388,14 +486,14 @@ export class A2AClient {
388
486
  }
389
487
  }
390
488
  }
391
- async ensureEndpointCandidates() {
489
+ async ensureEndpointCandidates(timeoutMs) {
392
490
  if (this.endpointResolved)
393
491
  return;
394
492
  this.endpointResolved = true;
395
493
  const candidates = [];
396
494
  addDefaultEndpointCandidates(candidates, this.baseUrl);
397
495
  try {
398
- const card = await this.getAgentCard();
496
+ const card = await this.getAgentCard({ timeoutMs });
399
497
  const cardUrl = normalizeUrl(card.url, this.baseUrl);
400
498
  if (cardUrl) {
401
499
  const explicitEndpoint = splitExplicitA2AEndpoint(cardUrl);
@@ -478,6 +576,92 @@ function normalizeUrl(value, baseUrl) {
478
576
  function shouldTryNextEndpoint(status) {
479
577
  return status === 404 || status === 405;
480
578
  }
579
+ function isRetrySafeA2ARpc(method, params, apiKey) {
580
+ if (method === "message/send") {
581
+ return (params.async === true &&
582
+ typeof params.idempotencyKey === "string" &&
583
+ params.idempotencyKey.trim().length > 0 &&
584
+ hasJwtSubject(apiKey));
585
+ }
586
+ return method === "tasks/get" || method === "actions/invoke";
587
+ }
588
+ function isRetryableA2AStatus(status) {
589
+ return (status === 408 ||
590
+ status === 425 ||
591
+ status === 429 ||
592
+ status === 500 ||
593
+ status === 502 ||
594
+ status === 503 ||
595
+ status === 504);
596
+ }
597
+ async function waitForA2ARetry(attempt, retryAfter = null, maxWaitMs) {
598
+ const retryAfterSeconds = retryAfter ? Number(retryAfter) : NaN;
599
+ const retryAfterMs = Number.isFinite(retryAfterSeconds)
600
+ ? Math.max(0, Math.min(2_000, retryAfterSeconds * 1_000))
601
+ : 0;
602
+ const backoffMs = Math.max(retryAfterMs, Math.min(1_000, A2A_RPC_RETRY_BASE_MS * 2 ** (attempt - 1)));
603
+ const boundedWaitMs = maxWaitMs === undefined ? backoffMs : Math.min(backoffMs, maxWaitMs);
604
+ if (boundedWaitMs <= 0)
605
+ return;
606
+ await new Promise((resolve) => setTimeout(resolve, boundedWaitMs));
607
+ }
608
+ function remainingA2ADeadlineMs(deadlineMs) {
609
+ return deadlineMs === undefined
610
+ ? undefined
611
+ : Math.max(0, deadlineMs - Date.now());
612
+ }
613
+ function resolveA2ARequestTimeoutMs(configuredMs, deadlineMs) {
614
+ const remainingMs = remainingA2ADeadlineMs(deadlineMs);
615
+ if (remainingMs === undefined)
616
+ return configuredMs;
617
+ return configuredMs === undefined
618
+ ? remainingMs
619
+ : Math.min(configuredMs, remainingMs);
620
+ }
621
+ /**
622
+ * Agent-card discovery is only a hint because first-party endpoints have
623
+ * conventional paths. Preserve most of a bounded call's deadline for the
624
+ * actual message instead of letting a cold or unavailable card consume it.
625
+ */
626
+ function resolveA2ADiscoveryTimeoutMs(configuredMs, deadlineMs) {
627
+ const transportBudgetMs = resolveA2ARequestTimeoutMs(configuredMs, deadlineMs);
628
+ const remainingMs = remainingA2ADeadlineMs(deadlineMs);
629
+ const deadlineShareMs = remainingMs === undefined
630
+ ? DEFAULT_A2A_DISCOVERY_TIMEOUT_MS
631
+ : Math.max(1, Math.floor(remainingMs / 4));
632
+ return Math.min(DEFAULT_A2A_DISCOVERY_TIMEOUT_MS, transportBudgetMs ?? DEFAULT_A2A_DISCOVERY_TIMEOUT_MS, deadlineShareMs);
633
+ }
634
+ function hasJwtSubject(apiKey) {
635
+ if (!apiKey)
636
+ return false;
637
+ const segments = apiKey.split(".");
638
+ if (segments.length !== 3)
639
+ return false;
640
+ try {
641
+ const payload = JSON.parse(Buffer.from(segments[1], "base64url").toString("utf8"));
642
+ return typeof payload.sub === "string" && payload.sub.trim().length > 0;
643
+ }
644
+ catch {
645
+ return false;
646
+ }
647
+ }
648
+ function isRetryableA2APollError(error) {
649
+ const message = error instanceof Error ? error.message : String(error ?? "");
650
+ if (isA2AAuthRejection(error))
651
+ return false;
652
+ if (/A2A error \(-32\d+\)|A2A request failed \((?:400|403|404|405|409|422)\)/i.test(message)) {
653
+ return false;
654
+ }
655
+ return /(?:A2A request failed \((?:408|425|429|5\d\d)\)|fetch failed|network|socket|ECONN|ETIMEDOUT|timeout|deadline|aborted|invalid JSON)/i.test(message);
656
+ }
657
+ function safelyNotifyA2AUpdate(callback, task) {
658
+ try {
659
+ callback?.(task);
660
+ }
661
+ catch {
662
+ // Presentation/progress callbacks cannot alter task polling.
663
+ }
664
+ }
481
665
  function unique(values) {
482
666
  return Array.from(new Set(values));
483
667
  }
@@ -521,6 +705,10 @@ export async function callAgent(url, text, opts) {
521
705
  // detached promises that get killed on Netlify/Vercel. Callers that
522
706
  // explicitly want a single-shot blocking POST can pass `async: false`.
523
707
  const useAsync = opts?.async ?? true;
708
+ // A stable per-call key makes retrying a submission safe even when this
709
+ // invocation has no durable parent turn id. If the receiver committed the
710
+ // task but the response was lost, the retry reuses the task.
711
+ const effectiveIdempotencyKey = opts?.idempotencyKey ?? (opts?.taskId ? undefined : `auto:${randomUUID()}`);
524
712
  const message = {
525
713
  role: "user",
526
714
  parts: [{ type: "text", text }],
@@ -546,7 +734,7 @@ export async function callAgent(url, text, opts) {
546
734
  : await client.sendAndWait(message, {
547
735
  contextId: opts?.contextId,
548
736
  metadata,
549
- idempotencyKey: opts?.idempotencyKey,
737
+ idempotencyKey: effectiveIdempotencyKey,
550
738
  ...(opts?.approvedActions?.length
551
739
  ? { approvedActions: opts.approvedActions }
552
740
  : {}),
@@ -562,28 +750,47 @@ export async function callAgent(url, text, opts) {
562
750
  task = await client.send(message, {
563
751
  contextId: opts?.contextId,
564
752
  metadata,
565
- idempotencyKey: opts?.idempotencyKey,
753
+ idempotencyKey: effectiveIdempotencyKey,
566
754
  ...(opts?.approvedActions?.length
567
755
  ? { approvedActions: opts.approvedActions }
568
756
  : {}),
569
757
  });
570
758
  }
571
- // Extract text from the response
759
+ // Preserve the receiver's typed terminal state. Failed, canceled, and
760
+ // input-required tasks are not successful text answers, even when the
761
+ // receiver attached a friendly explanatory message.
572
762
  const responseMessage = task.status.message;
573
- if (responseMessage) {
574
- const textParts = responseMessage.parts
575
- .filter((p) => p.type === "text")
576
- .map((p) => p.text);
577
- return textParts.join("\n");
763
+ const responseText = responseMessage
764
+ ? extractMessageText(responseMessage)
765
+ : "";
766
+ const state = task.status.state;
767
+ if (state === "failed" ||
768
+ state === "canceled" ||
769
+ state === "input-required") {
770
+ throw new A2ATaskTerminalError(task, state, responseText);
771
+ }
772
+ if (state !== "completed") {
773
+ throw new A2ATaskTerminalError(task, "failed", responseText || `Unexpected terminal state: ${state}`, "a2a_invalid_terminal_state");
774
+ }
775
+ if (responseText.trim()) {
776
+ if (responseText.length > MAX_A2A_CALLER_RESPONSE_CHARS) {
777
+ throw new A2ATaskTerminalError(task, "completed", responseText, "a2a_response_too_large");
778
+ }
779
+ return responseText;
578
780
  }
579
- return "";
781
+ const artifactSummary = verifiedArtifactSummary(task);
782
+ if (artifactSummary)
783
+ return artifactSummary;
784
+ throw new A2ATaskTerminalError(task, "completed", "Agent completed without a response or verified artifact.", "empty_agent_response");
580
785
  }
581
786
  catch (err) {
582
787
  if (opts?.returnRecoverableArtifactsOnTimeout !== false &&
583
788
  err instanceof A2ATaskTimeoutError) {
584
789
  const recoverableText = extractRecoverableArtifactText(err.lastTask);
585
- if (recoverableText)
790
+ if (recoverableText &&
791
+ recoverableText.length <= MAX_A2A_CALLER_RESPONSE_CHARS) {
586
792
  return recoverableText;
793
+ }
587
794
  }
588
795
  if (i < apiKeyAttempts.length - 1 && isA2AAuthRejection(err)) {
589
796
  lastAuthError = err;
@@ -683,9 +890,67 @@ function extractRecoverableArtifactText(task) {
683
890
  return extractMessageText(task.status.message);
684
891
  }
685
892
  function extractMessageText(message) {
686
- return message.parts
893
+ return (Array.isArray(message.parts) ? message.parts : [])
687
894
  .filter((p) => p.type === "text")
688
895
  .map((p) => p.text)
689
896
  .join("\n");
690
897
  }
898
+ function verifiedArtifactSummary(task) {
899
+ const artifacts = Array.isArray(task.artifacts) ? task.artifacts : [];
900
+ if (artifacts.length === 0)
901
+ return "";
902
+ const summaries = artifacts
903
+ .map((artifact, artifactIndex) => {
904
+ const parts = Array.isArray(artifact?.parts) ? artifact.parts : [];
905
+ const usableParts = parts
906
+ .map((part) => summarizeVerifiedArtifactPart(part))
907
+ .filter((value) => !!value)
908
+ .slice(0, 5);
909
+ if (usableParts.length === 0)
910
+ return null;
911
+ const fallbackFileName = parts.find((part) => part.type === "file" && part.file.name?.trim());
912
+ const label = artifact?.name?.trim() ||
913
+ (fallbackFileName?.type === "file"
914
+ ? fallbackFileName.file.name?.trim()
915
+ : "") ||
916
+ `Artifact ${artifactIndex + 1}`;
917
+ return `- ${label}\n${usableParts.map((part) => ` - ${part}`).join("\n")}`;
918
+ })
919
+ .filter((value) => !!value)
920
+ .slice(0, 20);
921
+ if (summaries.length === 0)
922
+ return "";
923
+ return boundA2ACallerResponseText(`The agent completed with ${summaries.length} verified artifact(s):\n` +
924
+ summaries.join("\n"));
925
+ }
926
+ function summarizeVerifiedArtifactPart(part) {
927
+ if (!part || typeof part !== "object")
928
+ return null;
929
+ const candidate = part;
930
+ if (candidate.type === "text" && typeof candidate.text === "string") {
931
+ const text = candidate.text.trim();
932
+ return text ? boundA2ACallerResponseText(text).slice(0, 2_000) : null;
933
+ }
934
+ if (candidate.type === "file") {
935
+ const file = candidate.file;
936
+ if (!file)
937
+ return null;
938
+ const uri = typeof file.uri === "string" ? file.uri.trim() : "";
939
+ const name = typeof file.name === "string" ? file.name.trim() : "";
940
+ const bytes = typeof file.bytes === "string" ? file.bytes : "";
941
+ if (uri)
942
+ return name ? `${name}: ${uri}` : uri;
943
+ if (bytes)
944
+ return name ? `${name} (inline file)` : "Inline file artifact";
945
+ return null;
946
+ }
947
+ if (candidate.type === "data") {
948
+ const data = candidate.data;
949
+ if (!data || typeof data !== "object" || Array.isArray(data))
950
+ return null;
951
+ const serialized = JSON.stringify(data);
952
+ return serialized !== "{}" ? serialized.slice(0, 2_000) : null;
953
+ }
954
+ return null;
955
+ }
691
956
  //# sourceMappingURL=client.js.map