@agent-native/core 0.221.0-same-host-mcp-20261027-20261027081850 → 0.221.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. package/dist/a2a/server.js +4 -4
  2. package/dist/a2a/task-lifecycle.d.ts +12 -12
  3. package/dist/a2a/task-lifecycle.js +10 -12
  4. package/dist/a2a/task-store.js +81 -228
  5. package/dist/action-caller.d.ts +3 -0
  6. package/dist/action-caller.js +8 -0
  7. package/dist/action.d.ts +1 -0
  8. package/dist/agent/engine/ai-sdk-engine.js +3 -3
  9. package/dist/agent/engine/anthropic-engine.js +3 -3
  10. package/dist/agent/engine/credential-owner.d.ts +3 -0
  11. package/dist/agent/engine/credential-owner.js +9 -0
  12. package/dist/agent/engine/registry.js +28 -2
  13. package/dist/agent/harness/acp-adapter.d.ts +1 -0
  14. package/dist/agent/harness/acp-adapter.js +36 -5
  15. package/dist/agent/harness/background.d.ts +5 -1
  16. package/dist/agent/harness/background.js +4 -3
  17. package/dist/agent/harness/lifecycle.d.ts +2 -0
  18. package/dist/agent/harness/lifecycle.js +452 -84
  19. package/dist/agent/harness/run-policy.d.ts +5 -0
  20. package/dist/agent/harness/run-policy.js +70 -0
  21. package/dist/agent/harness/runner.js +89 -73
  22. package/dist/agent/harness/store.d.ts +10 -1
  23. package/dist/agent/harness/store.js +91 -12
  24. package/dist/agent/harness/turn-driver.d.ts +12 -0
  25. package/dist/agent/harness/turn-driver.js +42 -0
  26. package/dist/agent/harness/types.d.ts +11 -0
  27. package/dist/agent/production-agent.d.ts +9 -0
  28. package/dist/agent/production-agent.js +153 -41
  29. package/dist/agent/run-manager.d.ts +4 -0
  30. package/dist/agent/run-manager.js +23 -7
  31. package/dist/agent/run-store.d.ts +3 -1
  32. package/dist/agent/run-store.fencing.native-harness.fixture.test.support.js +34 -0
  33. package/dist/agent/run-store.fencing.worker.test.support.d.ts +1 -0
  34. package/dist/agent/{run-store.fencing.worker.js → run-store.fencing.worker.test.support.js} +337 -4
  35. package/dist/agent/run-store.js +89 -17
  36. package/dist/app-config/clips.d.ts +10 -0
  37. package/dist/app-config/clips.js +24 -0
  38. package/dist/app-config/index.d.ts +1 -1
  39. package/dist/app-config/index.js +1 -1
  40. package/dist/app-config/schema.d.ts +1 -0
  41. package/dist/appearance/actions/set-theme-family.js +16 -2
  42. package/dist/appearance/theme-family.d.ts +11 -1
  43. package/dist/appearance/theme-family.js +21 -2
  44. package/dist/automations/outside-origin.d.ts +13 -0
  45. package/dist/automations/outside-origin.js +23 -0
  46. package/dist/automations/service.d.ts +4 -2
  47. package/dist/automations/service.js +11 -8
  48. package/dist/cli/code-agent-executor.js +5 -16
  49. package/dist/cli/create.d.ts +11 -2
  50. package/dist/cli/create.js +121 -32
  51. package/dist/cli/skills-content/turn-into-app-skill.d.ts +4 -3
  52. package/dist/cli/skills-content/turn-into-app-skill.js +143 -36
  53. package/dist/cli/skills.d.ts +3 -0
  54. package/dist/cli/skills.js +4 -1
  55. package/dist/cli/template-sync.js +4 -4
  56. package/dist/cli/upgrade.d.ts +1 -0
  57. package/dist/cli/upgrade.js +207 -2
  58. package/dist/client/chat/agentkit-agent-native.js +23 -3
  59. package/dist/client/mcp-approval.d.ts +53 -0
  60. package/dist/client/mcp-approval.js +81 -0
  61. package/dist/client/onboarding/use-onboarding.js +6 -4
  62. package/dist/client/resources/mcp-integration-catalog.js +19 -0
  63. package/dist/client/theme-family.d.ts +2 -1
  64. package/dist/client/theme-family.js +271 -32
  65. package/dist/client/theme.js +3 -2
  66. package/dist/code-agents/background-controller.js +1 -13
  67. package/dist/code-agents/prompt-attachments.d.ts +11 -0
  68. package/dist/code-agents/prompt-attachments.js +103 -6
  69. package/dist/collab/awareness-store.d.ts +8 -0
  70. package/dist/collab/awareness-store.js +9 -1
  71. package/dist/collab/index.d.ts +1 -1
  72. package/dist/collab/index.js +1 -1
  73. package/dist/collab/routes.d.ts +1 -1
  74. package/dist/collab/struct-routes.d.ts +1 -1
  75. package/dist/config.d.ts +13 -3
  76. package/dist/config.js +64 -1
  77. package/dist/db/client.d.ts +8 -6
  78. package/dist/db/client.js +56 -17
  79. package/dist/db/create-get-db.js +6 -1
  80. package/dist/db/index.d.ts +2 -1
  81. package/dist/db/index.js +1 -0
  82. package/dist/db/schema-snapshot.generated.js +9 -2
  83. package/dist/db/sql.d.ts +28 -0
  84. package/dist/db/sql.js +186 -0
  85. package/dist/decisions/actions/decide.d.ts +4 -0
  86. package/dist/decisions/actions/decide.js +7 -0
  87. package/dist/decisions/decide.d.ts +1 -0
  88. package/dist/decisions/decide.js +21 -9
  89. package/dist/decisions/index.d.ts +4 -1
  90. package/dist/decisions/index.js +3 -0
  91. package/dist/decisions/response.d.ts +1 -0
  92. package/dist/decisions/response.js +36 -11
  93. package/dist/decisions/types.d.ts +5 -0
  94. package/dist/decisions/validation.js +6 -3
  95. package/dist/deploy/build.js +11 -5
  96. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  97. package/dist/file-upload/attachment-text.d.ts +71 -0
  98. package/dist/file-upload/attachment-text.js +209 -0
  99. package/dist/file-upload/downscale-inline-image.d.ts +4 -0
  100. package/dist/file-upload/downscale-inline-image.js +27 -0
  101. package/dist/file-upload/inline-attachment-limits.d.ts +4 -0
  102. package/dist/file-upload/inline-attachment-limits.js +20 -1
  103. package/dist/file-upload/owned-attachment.d.ts +13 -1
  104. package/dist/file-upload/owned-attachment.js +52 -15
  105. package/dist/file-upload/pre-upload-attachments.js +74 -12
  106. package/dist/file-upload/registry.d.ts +1 -0
  107. package/dist/file-upload/registry.js +15 -7
  108. package/dist/file-upload/status.d.ts +19 -0
  109. package/dist/file-upload/status.js +49 -0
  110. package/dist/file-upload/thread-image-history.js +10 -2
  111. package/dist/index.browser.d.ts +1 -0
  112. package/dist/index.browser.js +1 -0
  113. package/dist/index.d.ts +1 -0
  114. package/dist/index.js +1 -0
  115. package/dist/ingestion/media.js +11 -5
  116. package/dist/jobs/actions/run-automation-now.js +2 -2
  117. package/dist/jobs/background-automation-runner.js +4 -4
  118. package/dist/jobs/frontmatter.d.ts +1 -1
  119. package/dist/jobs/frontmatter.js +5 -2
  120. package/dist/jobs/run-now.d.ts +2 -0
  121. package/dist/jobs/run-now.js +1 -1
  122. package/dist/jobs/scheduler.d.ts +2 -0
  123. package/dist/jobs/scheduler.js +1 -1
  124. package/dist/localization/automation-outcome-messages.js +22 -22
  125. package/dist/localization/core-messages/supplemental/ar-SA.js +1 -0
  126. package/dist/localization/core-messages/supplemental/de-DE.js +1 -0
  127. package/dist/localization/core-messages/supplemental/en-US.js +1 -0
  128. package/dist/localization/core-messages/supplemental/es-ES.js +1 -0
  129. package/dist/localization/core-messages/supplemental/fr-FR.js +1 -0
  130. package/dist/localization/core-messages/supplemental/hi-IN.js +1 -0
  131. package/dist/localization/core-messages/supplemental/ja-JP.js +1 -0
  132. package/dist/localization/core-messages/supplemental/ko-KR.js +1 -0
  133. package/dist/localization/core-messages/supplemental/pt-BR.js +1 -0
  134. package/dist/localization/core-messages/supplemental/zh-CN.js +1 -0
  135. package/dist/localization/core-messages/supplemental/zh-TW.js +1 -0
  136. package/dist/localization/mcp-approval-messages.d.ts +7 -1
  137. package/dist/localization/mcp-approval-messages.js +66 -0
  138. package/dist/localization/mcp-settings-messages.d.ts +1 -0
  139. package/dist/mcp/action-eligibility.d.ts +1 -0
  140. package/dist/mcp/action-eligibility.js +10 -5
  141. package/dist/mcp/analytics.d.ts +2 -0
  142. package/dist/mcp/analytics.js +10 -2
  143. package/dist/mcp/approval-route.d.ts +7 -0
  144. package/dist/mcp/approval-route.js +41 -16
  145. package/dist/mcp/approval-summary.d.ts +12 -2
  146. package/dist/mcp/approval-summary.js +128 -23
  147. package/dist/mcp/approval-time.d.ts +13 -3
  148. package/dist/mcp/approval-time.js +49 -5
  149. package/dist/mcp/build-server.d.ts +12 -1
  150. package/dist/mcp/build-server.js +157 -155
  151. package/dist/mcp/builtin-tools.d.ts +1 -0
  152. package/dist/mcp/builtin-tools.js +30 -14
  153. package/dist/mcp/direct-action-call.js +72 -27
  154. package/dist/mcp/embed-app.js +11 -6
  155. package/dist/mcp/embed-redaction.d.ts +10 -13
  156. package/dist/mcp/embed-redaction.js +227 -40
  157. package/dist/mcp/execute-action-call.d.ts +3 -2
  158. package/dist/mcp/execute-action-call.js +1 -4
  159. package/dist/mcp/framework-tools.d.ts +2 -2
  160. package/dist/mcp/oauth-route.js +102 -6
  161. package/dist/mcp/screen-memory-stdio.d.ts +3 -3
  162. package/dist/mcp/server.js +6 -0
  163. package/dist/mcp-client/oauth-routes.js +12 -2
  164. package/dist/notifications/routes.d.ts +3 -3
  165. package/dist/observability/failure-context.js +1 -0
  166. package/dist/observability/traces.js +11 -1
  167. package/dist/onboarding/first-run-builder-credits-experiment.d.ts +12 -0
  168. package/dist/onboarding/first-run-builder-credits-experiment.js +91 -0
  169. package/dist/org/index.d.ts +1 -1
  170. package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
  171. package/dist/provider-api/actions/provider-api.d.ts +12 -12
  172. package/dist/server/action-approval.d.ts +2 -2
  173. package/dist/server/action-approval.js +17 -10
  174. package/dist/server/action-discovery.js +2 -122
  175. package/dist/server/action-routes.d.ts +0 -1
  176. package/dist/server/action-routes.js +138 -58
  177. package/dist/server/agent-chat/action-filters-a2a.d.ts +1 -0
  178. package/dist/server/agent-chat/action-filters-a2a.js +11 -1
  179. package/dist/server/agent-chat/framework-prompts.d.ts +1 -0
  180. package/dist/server/agent-chat/framework-prompts.js +22 -1
  181. package/dist/server/agent-chat/mcp-options.d.ts +7 -0
  182. package/dist/server/agent-chat/mcp-options.js +1 -0
  183. package/dist/server/agent-chat/plugin-options.d.ts +23 -0
  184. package/dist/server/agent-chat/prompt-resources.d.ts +4 -2
  185. package/dist/server/agent-chat/prompt-resources.js +78 -32
  186. package/dist/server/agent-chat-plugin.js +214 -125
  187. package/dist/server/agent-engine-api-key-route.d.ts +2 -2
  188. package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
  189. package/dist/server/agent-run-context.js +4 -0
  190. package/dist/server/attachment-actions.d.ts +14 -7
  191. package/dist/server/attachment-actions.js +310 -65
  192. package/dist/server/attribution.d.ts +2 -0
  193. package/dist/server/auth.d.ts +2 -1
  194. package/dist/server/auth.js +84 -17
  195. package/dist/server/better-auth-instance.js +46 -12
  196. package/dist/server/builder-api-auth.d.ts +1 -0
  197. package/dist/server/builder-api-auth.js +8 -0
  198. package/dist/server/builder-browser.d.ts +5 -1
  199. package/dist/server/builder-browser.js +80 -4
  200. package/dist/server/cli-wrapper-flags.d.ts +27 -0
  201. package/dist/server/cli-wrapper-flags.js +500 -0
  202. package/dist/server/consent-route.d.ts +3 -0
  203. package/dist/server/consent-route.js +29 -10
  204. package/dist/server/core-routes-plugin.js +72 -60
  205. package/dist/server/credential-provider.js +26 -11
  206. package/dist/server/edge.d.ts +3 -2
  207. package/dist/server/edge.js +3 -2
  208. package/dist/server/embed-request-origin.d.ts +4 -0
  209. package/dist/server/embed-request-origin.js +28 -0
  210. package/dist/server/embed-route.js +4 -2
  211. package/dist/server/embed-session.d.ts +16 -4
  212. package/dist/server/embed-session.js +253 -145
  213. package/dist/server/embedded.d.ts +2 -1
  214. package/dist/server/embedded.js +9 -5
  215. package/dist/server/filesystem-action-entry.d.ts +15 -1
  216. package/dist/server/filesystem-action-entry.js +153 -23
  217. package/dist/server/first-touch-route.d.ts +1 -1
  218. package/dist/server/google-oauth.d.ts +7 -0
  219. package/dist/server/google-oauth.js +33 -6
  220. package/dist/server/index.d.ts +11 -6
  221. package/dist/server/index.js +8 -3
  222. package/dist/server/magic-link-attribution.d.ts +2 -0
  223. package/dist/server/magic-link-attribution.js +8 -2
  224. package/dist/server/mcp-signup-attribution.d.ts +23 -0
  225. package/dist/server/mcp-signup-attribution.js +135 -0
  226. package/dist/server/prompts/framework-core.js +2 -1
  227. package/dist/server/prompts/shared-rules.d.ts +2 -0
  228. package/dist/server/prompts/shared-rules.js +2 -0
  229. package/dist/server/realtime-voice.d.ts +65 -2
  230. package/dist/server/realtime-voice.js +235 -36
  231. package/dist/server/release-migrations.js +37 -10
  232. package/dist/server/request-context.d.ts +17 -0
  233. package/dist/server/request-context.js +4 -0
  234. package/dist/server/request-origin.d.ts +4 -6
  235. package/dist/server/request-origin.js +26 -28
  236. package/dist/server/session-resolution-unavailable.d.ts +22 -0
  237. package/dist/server/session-resolution-unavailable.js +65 -0
  238. package/dist/server/short-lived-token.d.ts +10 -2
  239. package/dist/server/short-lived-token.js +12 -4
  240. package/dist/server/ui-action-capability.js +18 -4
  241. package/dist/shared/first-run-builder-credits-experiment.d.ts +13 -0
  242. package/dist/shared/first-run-builder-credits-experiment.js +22 -0
  243. package/dist/shared/index.d.ts +1 -0
  244. package/dist/shared/index.js +1 -0
  245. package/dist/shared/mcp-approval-review.d.ts +19 -0
  246. package/dist/shared/mcp-approval-review.js +29 -0
  247. package/dist/shared/reasoning-effort.d.ts +4 -0
  248. package/dist/shared/reasoning-effort.js +20 -0
  249. package/dist/sharing/access.d.ts +11 -2
  250. package/dist/sharing/access.js +12 -7
  251. package/dist/state-machine/index.d.ts +5 -8
  252. package/dist/state-machine/index.js +6 -2
  253. package/dist/templates/builder-code-starter/app/components/layout/Layout.tsx.patch +48 -18
  254. package/dist/templates/builder-code-starter/server/plugins/agent-chat.ts.patch +7 -6
  255. package/dist/templates/builder-code-starter/template-layer.json +1 -0
  256. package/dist/templates/chat/.agents/skills/storing-data/SKILL.md +18 -0
  257. package/dist/templates/chat/app/components/chat/ChatRouteContent.tsx +18 -4
  258. package/dist/templates/chat/app/components/home/HomePage.tsx +28 -69
  259. package/dist/templates/chat/app/components/layout/Layout.tsx +46 -14
  260. package/dist/templates/chat/app/i18n/ar-SA.ts +0 -4
  261. package/dist/templates/chat/app/i18n/de-DE.ts +0 -5
  262. package/dist/templates/chat/app/i18n/en-US.ts +0 -4
  263. package/dist/templates/chat/app/i18n/es-ES.ts +0 -5
  264. package/dist/templates/chat/app/i18n/fr-FR.ts +0 -5
  265. package/dist/templates/chat/app/i18n/hi-IN.ts +0 -5
  266. package/dist/templates/chat/app/i18n/ja-JP.ts +0 -5
  267. package/dist/templates/chat/app/i18n/ko-KR.ts +0 -5
  268. package/dist/templates/chat/app/i18n/pt-BR.ts +0 -5
  269. package/dist/templates/chat/app/i18n/zh-CN.ts +0 -4
  270. package/dist/templates/chat/app/i18n/zh-TW.ts +0 -4
  271. package/dist/templates/chat/app/lib/chat-paths.ts +36 -13
  272. package/dist/templates/chat/package.json +1 -0
  273. package/dist/templates/chat/server/plugins/agent-chat.ts +2 -1
  274. package/dist/templates/default/.agents/skills/storing-data/SKILL.md +18 -0
  275. package/dist/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +123 -33
  276. package/dist/templates/headless/.agents/skills/storing-data/SKILL.md +18 -0
  277. package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +18 -0
  278. package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +34 -29
  279. package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/fresh-project.md +12 -5
  280. package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/review-loop.md +3 -2
  281. package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/where-it-runs.md +93 -0
  282. package/dist/tracking/registry.js +25 -0
  283. package/dist/triggers/actions/manage-automation.js +6 -2
  284. package/dist/triggers/actions.js +14 -2
  285. package/dist/triggers/index.d.ts +1 -0
  286. package/dist/triggers/index.js +1 -0
  287. package/dist/vite/client.js +5 -4
  288. package/docs/content/authentication.mdx +2 -0
  289. package/docs/content/components.mdx +1 -1
  290. package/docs/content/decisions.mdx +1 -1
  291. package/docs/content/recurring-jobs.mdx +15 -0
  292. package/docs/content/template-chat-developers.mdx +1 -1
  293. package/docs/content/template-chat-features.mdx +4 -4
  294. package/docs/content/turn-into-app.mdx +18 -10
  295. package/package.json +6 -4
  296. package/src/templates/builder-code-starter/app/components/layout/Layout.tsx.patch +48 -18
  297. package/src/templates/builder-code-starter/server/plugins/agent-chat.ts.patch +7 -6
  298. package/src/templates/builder-code-starter/template-layer.json +1 -0
  299. package/src/templates/chat/.agents/skills/storing-data/SKILL.md +18 -0
  300. package/src/templates/chat/app/components/chat/ChatRouteContent.tsx +18 -4
  301. package/src/templates/chat/app/components/home/HomePage.tsx +28 -69
  302. package/src/templates/chat/app/components/layout/Layout.tsx +46 -14
  303. package/src/templates/chat/app/i18n/ar-SA.ts +0 -4
  304. package/src/templates/chat/app/i18n/de-DE.ts +0 -5
  305. package/src/templates/chat/app/i18n/en-US.ts +0 -4
  306. package/src/templates/chat/app/i18n/es-ES.ts +0 -5
  307. package/src/templates/chat/app/i18n/fr-FR.ts +0 -5
  308. package/src/templates/chat/app/i18n/hi-IN.ts +0 -5
  309. package/src/templates/chat/app/i18n/ja-JP.ts +0 -5
  310. package/src/templates/chat/app/i18n/ko-KR.ts +0 -5
  311. package/src/templates/chat/app/i18n/pt-BR.ts +0 -5
  312. package/src/templates/chat/app/i18n/zh-CN.ts +0 -4
  313. package/src/templates/chat/app/i18n/zh-TW.ts +0 -4
  314. package/src/templates/chat/app/lib/chat-paths.ts +36 -13
  315. package/src/templates/chat/package.json +1 -0
  316. package/src/templates/chat/server/plugins/agent-chat.ts +2 -1
  317. package/src/templates/default/.agents/skills/storing-data/SKILL.md +18 -0
  318. package/src/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +123 -33
  319. package/src/templates/headless/.agents/skills/storing-data/SKILL.md +18 -0
  320. package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +18 -0
  321. package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +34 -29
  322. package/src/templates/workspace-core/.agents/skills/turn-into-app/references/fresh-project.md +12 -5
  323. package/src/templates/workspace-core/.agents/skills/turn-into-app/references/review-loop.md +3 -2
  324. package/src/templates/workspace-core/.agents/skills/turn-into-app/references/where-it-runs.md +93 -0
  325. package/dist/automations/mcp-origin.d.ts +0 -2
  326. package/dist/automations/mcp-origin.js +0 -10
  327. /package/dist/agent/{run-store.fencing.worker.d.ts → run-store.fencing.native-harness.fixture.test.support.d.ts} +0 -0
@@ -13,7 +13,7 @@ import { readDeployCredentialEnv } from "../server/credential-provider.js";
13
13
  import { getH3App } from "../server/framework-request-handler.js";
14
14
  import { publicFrameworkPath } from "../server/framework-route-prefix.js";
15
15
  import { readBody } from "../server/h3-helpers.js";
16
- import { isSameOriginRequest } from "../server/request-origin.js";
16
+ import { hasSameOriginBrowserEvidence } from "../server/request-origin.js";
17
17
  import { generateAgentCard } from "./agent-card.js";
18
18
  import { addAgentProfileExamples } from "./app-profile.js";
19
19
  import { canonicalA2AAudience } from "./audience.js";
@@ -577,8 +577,8 @@ export function mountA2A(nitroApp, config, routePrefix = "/_agent-native") {
577
577
  setResponseStatus(event, 404);
578
578
  return { error: "Approval not found" };
579
579
  }
580
- const { getSession } = await import("../server/auth.js");
581
- const session = await getSession(event);
580
+ const { getBrowserCookieSession } = await import("../server/auth.js");
581
+ const session = await getBrowserCookieSession(event);
582
582
  if (!session?.email) {
583
583
  setResponseStatus(event, 401);
584
584
  return { error: "Sign in to review this approval" };
@@ -613,7 +613,7 @@ export function mountA2A(nitroApp, config, routePrefix = "/_agent-native") {
613
613
  setResponseStatus(event, 405);
614
614
  return { error: "Method not allowed" };
615
615
  }
616
- if (!isSameOriginRequest(event)) {
616
+ if (!hasSameOriginBrowserEvidence(event)) {
617
617
  setResponseStatus(event, 403);
618
618
  return { error: "Cross-origin approval denied" };
619
619
  }
@@ -1,20 +1,20 @@
1
- import { type Machine } from "../state-machine/index.js";
1
+ import { type SqlFragment } from "../db/sql.js";
2
2
  import type { TaskState } from "./types.js";
3
- export declare const a2aTaskMachine: Machine<"canceled" | "completed" | "failed" | "input-required" | "processing" | "submitted" | "working", "cancel" | "claimForProcessing" | "completeApproval" | "completeProcessing" | "failApproval" | "failProcessing" | "failStale" | "failStuckProcessing" | "failStuckQueued" | "overwriteAsCanceled" | "overwriteAsCompleted" | "overwriteAsFailed" | "overwriteAsInputRequired" | "overwriteAsProcessing" | "overwriteAsSubmitted" | "overwriteAsWorking" | "requireInput" | "resumeAfterApproval" | "retryStuck">;
4
- export declare const a2aApprovalMachine: Machine<"completed" | "failed" | "pending" | "processing", "claim" | "complete" | "fail" | "reclaim">;
3
+ export declare const a2aTaskMachine: import("../state-machine/index.js").SqlMachine<"canceled" | "completed" | "failed" | "input-required" | "processing" | "submitted" | "working", "cancel" | "claimForProcessing" | "completeApproval" | "completeProcessing" | "failApproval" | "failProcessing" | "failStale" | "failStuckProcessing" | "failStuckQueued" | "overwriteAsCanceled" | "overwriteAsCompleted" | "overwriteAsFailed" | "overwriteAsInputRequired" | "overwriteAsProcessing" | "overwriteAsSubmitted" | "overwriteAsWorking" | "requireInput" | "resumeAfterApproval" | "retryStuck">;
4
+ export declare const a2aApprovalMachine: import("../state-machine/index.js").SqlMachine<"completed" | "failed" | "pending" | "processing", "claim" | "complete" | "fail" | "reclaim">;
5
5
  export type A2ATaskStatus = (typeof a2aTaskMachine.states)[number];
6
6
  export type A2ATaskEvent = (typeof a2aTaskMachine.events)[number];
7
7
  export type A2AApprovalStatus = (typeof a2aApprovalMachine.states)[number];
8
8
  export type A2AApprovalEvent = (typeof a2aApprovalMachine.events)[number];
9
9
  type Mutual<A, B> = [A] extends [B] ? ([B] extends [A] ? true : false) : false;
10
10
  export declare const taskStatesMatchTaskState: Mutual<A2ATaskStatus, TaskState>;
11
- /** `'a', 'b'` for an event's source states, in the order the SQL lists them. */
12
- export declare function taskIn(event: A2ATaskEvent): string;
13
- /** `'x'` for the state an event lands in. */
14
- export declare function taskTarget(event: A2ATaskEvent): string;
15
- /** `'x'` for one state, for single-state WHERE and SELECT predicates. */
16
- export declare function taskSql(state: A2ATaskStatus): string;
17
- export declare function approvalIn(event: A2AApprovalEvent): string;
18
- export declare function approvalTarget(event: A2AApprovalEvent): string;
19
- export declare function approvalSql(state: A2AApprovalStatus): string;
11
+ /** Bound source states for an event's `IN` predicate. */
12
+ export declare function taskIn(event: A2ATaskEvent): SqlFragment;
13
+ /** Bound state value for the state an event lands in. */
14
+ export declare function taskTarget(event: A2ATaskEvent): SqlFragment;
15
+ /** Bound state value for single-state WHERE and SELECT predicates. */
16
+ export declare function taskSql(state: A2ATaskStatus): SqlFragment;
17
+ export declare function approvalIn(event: A2AApprovalEvent): SqlFragment;
18
+ export declare function approvalTarget(event: A2AApprovalEvent): SqlFragment;
19
+ export declare function approvalSql(state: A2AApprovalStatus): SqlFragment;
20
20
  export {};
@@ -1,3 +1,4 @@
1
+ import { sql } from "../db/sql.js";
1
2
  import { defineMachine } from "../state-machine/index.js";
2
3
  /**
3
4
  * Lifecycles of `a2a_tasks.status_state` and `a2a_approvals.status`.
@@ -95,27 +96,24 @@ function targetOf(machine, event) {
95
96
  }
96
97
  return machine.transition(from, event);
97
98
  }
98
- /** `'a', 'b'` for an event's source states, in the order the SQL lists them. */
99
+ /** Bound source states for an event's `IN` predicate. */
99
100
  export function taskIn(event) {
100
- return a2aTaskMachine.sqlStateList(event);
101
+ return a2aTaskMachine.sqlIn(event);
101
102
  }
102
- /** `'x'` for the state an event lands in. */
103
+ /** Bound state value for the state an event lands in. */
103
104
  export function taskTarget(event) {
104
- return sqlLiteral(a2aTaskMachine, targetOf(a2aTaskMachine, event));
105
+ return sql `${sql.value(targetOf(a2aTaskMachine, event))}`;
105
106
  }
106
- /** `'x'` for one state, for single-state WHERE and SELECT predicates. */
107
+ /** Bound state value for single-state WHERE and SELECT predicates. */
107
108
  export function taskSql(state) {
108
- return sqlLiteral(a2aTaskMachine, state);
109
+ return sql `${sql.value(a2aTaskMachine.parseState(state))}`;
109
110
  }
110
111
  export function approvalIn(event) {
111
- return a2aApprovalMachine.sqlStateList(event);
112
+ return a2aApprovalMachine.sqlIn(event);
112
113
  }
113
114
  export function approvalTarget(event) {
114
- return sqlLiteral(a2aApprovalMachine, targetOf(a2aApprovalMachine, event));
115
+ return sql `${sql.value(targetOf(a2aApprovalMachine, event))}`;
115
116
  }
116
117
  export function approvalSql(state) {
117
- return sqlLiteral(a2aApprovalMachine, state);
118
- }
119
- function sqlLiteral(machine, state) {
120
- return `'${machine.parseState(state)}'`;
118
+ return sql `${sql.value(a2aApprovalMachine.parseState(state))}`;
121
119
  }
@@ -2,6 +2,7 @@ import crypto from "crypto";
2
2
  import { currentExecutionFence, withFencedExecutionWrite, } from "../agent/execution-fence.js";
3
3
  import { getDbExec } from "../db/client.js";
4
4
  import { ensureTableExists, ensureColumnExists, ensureIndexExists, } from "../db/ddl-guard.js";
5
+ import { sql } from "../db/sql.js";
5
6
  import { defineStore } from "../db/store-registry.js";
6
7
  import { assertA2APersistablePayload } from "./persistence-safety.js";
7
8
  import { a2aApprovalMachine, a2aTaskMachine, approvalSql, approvalTarget, taskIn, taskSql, taskTarget, } from "./task-lifecycle.js";
@@ -127,22 +128,7 @@ export async function createA2AApproval(input) {
127
128
  const id = crypto.randomUUID();
128
129
  const now = Date.now();
129
130
  const expiresAt = now + (input.ttlMs ?? 15 * 60_000);
130
- await withFencedExecutionWrite((tx) => tx.execute({
131
- sql: `INSERT INTO a2a_approvals (id, task_id, owner_email, org_id, tool_name, tool_input, approval_key, call_id, status, expires_at, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ${approvalSql(a2aApprovalMachine.initial)}, ?, ?, ?)`,
132
- args: [
133
- id,
134
- input.taskId,
135
- input.ownerEmail,
136
- input.orgId ?? null,
137
- input.tool,
138
- JSON.stringify(input.toolInput ?? {}),
139
- input.approvalKey,
140
- input.callId,
141
- expiresAt,
142
- now,
143
- now,
144
- ],
145
- }), { threadId: a2aTaskLeaseThreadId(input.taskId), turnId: input.taskId });
131
+ await withFencedExecutionWrite((tx) => tx.execute(sql `INSERT INTO a2a_approvals (id, task_id, owner_email, org_id, tool_name, tool_input, approval_key, call_id, status, expires_at, created_at, updated_at) VALUES (${sql.value(id)}, ${sql.value(input.taskId)}, ${sql.value(input.ownerEmail)}, ${sql.value(input.orgId ?? null)}, ${sql.value(input.tool)}, ${sql.value(JSON.stringify(input.toolInput ?? {}))}, ${sql.value(input.approvalKey)}, ${sql.value(input.callId)}, ${approvalSql(a2aApprovalMachine.initial)}, ${sql.value(expiresAt)}, ${sql.value(now)}, ${sql.value(now)})`), { threadId: a2aTaskLeaseThreadId(input.taskId), turnId: input.taskId });
146
132
  return {
147
133
  id,
148
134
  taskId: input.taskId,
@@ -180,16 +166,10 @@ export async function claimA2AApproval(id, ownerEmail, orgId) {
180
166
  }
181
167
  try {
182
168
  return await withFencedExecutionWrite(async (tx) => {
183
- const approvalUpdate = await tx.execute({
184
- sql: `UPDATE a2a_approvals SET status = ${approvalTarget("claim")}, updated_at = ? WHERE id = ? AND owner_email = ? AND ((status = ${approvalSql("pending")} AND expires_at > ?) OR status = ${approvalSql("processing")}) AND (org_id IS NULL OR org_id = ?)`,
185
- args: [now, id, ownerEmail, now, orgId ?? null],
186
- });
169
+ const approvalUpdate = await tx.execute(sql `UPDATE a2a_approvals SET status = ${approvalTarget("claim")}, updated_at = ${sql.value(now)} WHERE id = ${sql.value(id)} AND owner_email = ${sql.value(ownerEmail)} AND ((status = ${approvalSql("pending")} AND expires_at > ${sql.value(now)}) OR status = ${approvalSql("processing")}) AND (org_id IS NULL OR org_id = ${sql.value(orgId ?? null)})`);
187
170
  if (getAffectedRowCount(approvalUpdate) === 0)
188
171
  throw new ClaimRejected();
189
- const { rows } = await tx.execute({
190
- sql: `SELECT * FROM a2a_approvals WHERE id = ? AND owner_email = ? AND status = ${approvalSql("processing")}`,
191
- args: [id, ownerEmail],
192
- });
172
+ const { rows } = await tx.execute(sql `SELECT * FROM a2a_approvals WHERE id = ${sql.value(id)} AND owner_email = ${sql.value(ownerEmail)} AND status = ${approvalSql("processing")}`);
193
173
  if (!rows[0])
194
174
  throw new ClaimRejected();
195
175
  const approval = approvalFromRow(rows[0]);
@@ -198,16 +178,7 @@ export async function claimA2AApproval(id, ownerEmail, orgId) {
198
178
  role: "agent",
199
179
  parts: [{ type: "text", text: "Approved action is running." }],
200
180
  };
201
- const taskUpdate = await tx.execute({
202
- sql: `UPDATE a2a_tasks SET status_state = ${taskTarget("resumeAfterApproval")}, status_message = ?, status_timestamp = ?, updated_at = ? WHERE id = ? AND owner_email = ? AND status_state IN (${taskIn("resumeAfterApproval")})`,
203
- args: [
204
- JSON.stringify(runningMessage),
205
- timestamp,
206
- now,
207
- approval.taskId,
208
- ownerEmail,
209
- ],
210
- });
181
+ const taskUpdate = await tx.execute(sql `UPDATE a2a_tasks SET status_state = ${taskTarget("resumeAfterApproval")}, status_message = ${sql.value(JSON.stringify(runningMessage))}, status_timestamp = ${sql.value(timestamp)}, updated_at = ${sql.value(now)} WHERE id = ${sql.value(approval.taskId)} AND owner_email = ${sql.value(ownerEmail)} AND status_state IN ${taskIn("resumeAfterApproval")}`);
211
182
  if (getAffectedRowCount(taskUpdate) === 0)
212
183
  throw new ClaimRejected();
213
184
  return approval;
@@ -232,10 +203,7 @@ export async function settleA2AApproval(id, status, resultText) {
232
203
  }
233
204
  await ensureTable();
234
205
  const client = getDbExec();
235
- const { rows: approvalRows } = await client.execute({
236
- sql: `SELECT task_id FROM a2a_approvals WHERE id = ? AND status = ${approvalSql("processing")}`,
237
- args: [id],
238
- });
206
+ const { rows: approvalRows } = await client.execute(sql `SELECT task_id FROM a2a_approvals WHERE id = ${sql.value(id)} AND status = ${approvalSql("processing")}`);
239
207
  if (!approvalRows[0])
240
208
  throw new Error("Approval is not processing");
241
209
  const taskId = String(approvalRows[0].task_id);
@@ -246,17 +214,11 @@ export async function settleA2AApproval(id, status, resultText) {
246
214
  parts: [{ type: "text", text: settledText }],
247
215
  };
248
216
  await withFencedExecutionWrite(async (tx) => {
249
- const { rows } = await tx.execute({
250
- sql: `SELECT task_id FROM a2a_approvals WHERE id = ? AND status = ${approvalSql("processing")}`,
251
- args: [id],
252
- });
217
+ const { rows } = await tx.execute(sql `SELECT task_id FROM a2a_approvals WHERE id = ${sql.value(id)} AND status = ${approvalSql("processing")}`);
253
218
  if (!rows[0])
254
219
  throw new Error("Approval is not processing");
255
220
  const taskId = String(rows[0].task_id);
256
- const { rows: taskRows } = await tx.execute({
257
- sql: `SELECT history FROM a2a_tasks WHERE id = ? AND status_state = ${taskSql("working")}`,
258
- args: [taskId],
259
- });
221
+ const { rows: taskRows } = await tx.execute(sql `SELECT history FROM a2a_tasks WHERE id = ${sql.value(taskId)} AND status_state = ${taskSql("working")}`);
260
222
  if (!taskRows[0]) {
261
223
  throw new Error("Approval task is no longer awaiting settlement");
262
224
  }
@@ -264,24 +226,11 @@ export async function settleA2AApproval(id, status, resultText) {
264
226
  history.push(message);
265
227
  assertA2APersistablePayload(history, "A2A task history");
266
228
  const timestamp = new Date(now).toISOString();
267
- const taskUpdate = await tx.execute({
268
- sql: `UPDATE a2a_tasks SET status_state = ?, status_message = ?, status_timestamp = ?, history = ?, updated_at = ? WHERE id = ? AND status_state = ${taskSql("working")}`,
269
- args: [
270
- settledStatus,
271
- JSON.stringify(message),
272
- timestamp,
273
- JSON.stringify(history),
274
- now,
275
- taskId,
276
- ],
277
- });
229
+ const taskUpdate = await tx.execute(sql `UPDATE a2a_tasks SET status_state = ${sql.value(settledStatus)}, status_message = ${sql.value(JSON.stringify(message))}, status_timestamp = ${sql.value(timestamp)}, history = ${sql.value(JSON.stringify(history))}, updated_at = ${sql.value(now)} WHERE id = ${sql.value(taskId)} AND status_state = ${taskSql("working")}`);
278
230
  if (getAffectedRowCount(taskUpdate) === 0) {
279
231
  throw new Error("Approval task settlement lost its state claim");
280
232
  }
281
- const approvalUpdate = await tx.execute({
282
- sql: `UPDATE a2a_approvals SET status = ?, result = ?, updated_at = ? WHERE id = ? AND status = ${approvalSql("processing")}`,
283
- args: [settledStatus, settledText, now, id],
284
- });
233
+ const approvalUpdate = await tx.execute(sql `UPDATE a2a_approvals SET status = ${sql.value(settledStatus)}, result = ${sql.value(settledText)}, updated_at = ${sql.value(now)} WHERE id = ${sql.value(id)} AND status = ${approvalSql("processing")}`);
285
234
  if (getAffectedRowCount(approvalUpdate) === 0) {
286
235
  throw new Error("Approval settlement lost its state claim");
287
236
  }
@@ -299,10 +248,7 @@ export async function pauseProcessingA2ATask(id, message) {
299
248
  assertA2APersistablePayload(message, "A2A task status message");
300
249
  await ensureTable();
301
250
  return withFencedExecutionWrite(async (tx) => {
302
- const { rows } = await tx.execute({
303
- sql: `SELECT * FROM a2a_tasks WHERE id = ? AND status_state = ${taskSql("processing")}`,
304
- args: [id],
305
- });
251
+ const { rows } = await tx.execute(sql `SELECT * FROM a2a_tasks WHERE id = ${sql.value(id)} AND status_state = ${taskSql("processing")}`);
306
252
  if (!rows[0])
307
253
  return null;
308
254
  const task = taskFromRow(rows[0]);
@@ -310,16 +256,7 @@ export async function pauseProcessingA2ATask(id, message) {
310
256
  assertA2APersistablePayload(task.history, "A2A task history");
311
257
  const now = Date.now();
312
258
  const timestamp = new Date(now).toISOString();
313
- const result = await tx.execute({
314
- sql: `UPDATE a2a_tasks SET status_state = ${taskTarget("requireInput")}, status_message = ?, status_timestamp = ?, history = ?, updated_at = ? WHERE id = ? AND status_state = ${taskSql("processing")}`,
315
- args: [
316
- JSON.stringify(message),
317
- timestamp,
318
- JSON.stringify(task.history ?? []),
319
- now,
320
- id,
321
- ],
322
- });
259
+ const result = await tx.execute(sql `UPDATE a2a_tasks SET status_state = ${taskTarget("requireInput")}, status_message = ${sql.value(JSON.stringify(message))}, status_timestamp = ${sql.value(timestamp)}, history = ${sql.value(JSON.stringify(task.history ?? []))}, updated_at = ${sql.value(now)} WHERE id = ${sql.value(id)} AND status_state = ${taskSql("processing")}`);
323
260
  if (getAffectedRowCount(result) === 0)
324
261
  return null;
325
262
  task.status = { state: "input-required", message, timestamp };
@@ -432,10 +369,7 @@ export async function createOrReuseTask(message, contextId, metadata, ownerEmail
432
369
  const reused = task.id !== id;
433
370
  if (reused &&
434
371
  (task.status.state === "failed" || task.status.state === "canceled")) {
435
- await client.execute({
436
- sql: `UPDATE a2a_tasks SET idempotency_key = NULL, updated_at = ? WHERE id = ? AND idempotency_key = ? AND status_state IN (${taskSql("failed")}, ${taskSql("canceled")})`,
437
- args: [Date.now(), task.id, idempotencyKey],
438
- });
372
+ await client.execute(sql `UPDATE a2a_tasks SET idempotency_key = NULL, updated_at = ${sql.value(Date.now())} WHERE id = ${sql.value(task.id)} AND idempotency_key = ${sql.value(idempotencyKey)} AND status_state IN (${taskSql("failed")}, ${taskSql("canceled")})`);
439
373
  continue;
440
374
  }
441
375
  return { task, reused };
@@ -444,11 +378,8 @@ export async function createOrReuseTask(message, contextId, metadata, ownerEmail
444
378
  }
445
379
  function taskAccessPredicate(scope) {
446
380
  if (!scope)
447
- return { sql: "", args: [] };
448
- return {
449
- sql: " AND LOWER(COALESCE(owner_email, '')) = LOWER(?) AND LOWER(COALESCE(owner_scope, '')) = LOWER(?)",
450
- args: [scope.ownerEmail, scope.ownerScope ?? ""],
451
- };
381
+ return sql ``;
382
+ return sql ` AND LOWER(COALESCE(owner_email, '')) = LOWER(${sql.value(scope.ownerEmail)}) AND LOWER(COALESCE(owner_scope, '')) = LOWER(${sql.value(scope.ownerScope ?? "")})`;
452
383
  }
453
384
  export async function getTaskOwner(id) {
454
385
  return (await getTaskOwnership(id)).ownerEmail;
@@ -474,16 +405,13 @@ export async function claimA2ATaskForProcessing(id) {
474
405
  const now = Date.now();
475
406
  const timestamp = new Date().toISOString();
476
407
  return withFencedExecutionWrite(async (tx) => {
477
- const { rows } = await tx.execute({
478
- sql: `UPDATE a2a_tasks
408
+ const { rows } = await tx.execute(sql `UPDATE a2a_tasks
479
409
  SET status_state = ${taskTarget("claimForProcessing")},
480
- status_timestamp = ?,
481
- updated_at = ?
482
- WHERE id = ?
483
- AND status_state IN (${taskIn("claimForProcessing")})
484
- RETURNING *`,
485
- args: [timestamp, now, id],
486
- });
410
+ status_timestamp = ${sql.value(timestamp)},
411
+ updated_at = ${sql.value(now)}
412
+ WHERE id = ${sql.value(id)}
413
+ AND status_state IN ${taskIn("claimForProcessing")}
414
+ RETURNING *`);
487
415
  return rows.length > 0 ? taskFromRow(rows[0]) : null;
488
416
  }, { threadId: a2aTaskLeaseThreadId(id), turnId: id });
489
417
  }
@@ -509,26 +437,20 @@ export async function touchQueuedA2ATaskDispatch(id) {
509
437
  await ensureTable();
510
438
  const client = getDbExec();
511
439
  const now = Date.now();
512
- const result = await client.execute({
513
- sql: `UPDATE a2a_tasks
514
- SET updated_at = ?
515
- WHERE id = ?
516
- AND status_state IN (${taskIn("claimForProcessing")})`,
517
- args: [now, id],
518
- });
440
+ const result = await client.execute(sql `UPDATE a2a_tasks
441
+ SET updated_at = ${sql.value(now)}
442
+ WHERE id = ${sql.value(id)}
443
+ AND status_state IN ${taskIn("claimForProcessing")}`);
519
444
  const affected = getAffectedRowCount(result);
520
445
  return affected !== 0;
521
446
  }
522
447
  export async function touchProcessingA2ATask(id) {
523
448
  await ensureTable();
524
449
  const now = Date.now();
525
- const result = await withFencedExecutionWrite((tx) => tx.execute({
526
- sql: `UPDATE a2a_tasks
527
- SET updated_at = ?
528
- WHERE id = ?
529
- AND status_state = ${taskSql("processing")}`,
530
- args: [now, id],
531
- }), { threadId: a2aTaskLeaseThreadId(id), turnId: id });
450
+ const result = await withFencedExecutionWrite((tx) => tx.execute(sql `UPDATE a2a_tasks
451
+ SET updated_at = ${sql.value(now)}
452
+ WHERE id = ${sql.value(id)}
453
+ AND status_state = ${taskSql("processing")}`), { threadId: a2aTaskLeaseThreadId(id), turnId: id });
532
454
  const affected = getAffectedRowCount(result);
533
455
  return affected !== 0;
534
456
  }
@@ -536,16 +458,13 @@ export async function resetStuckA2ATaskForRetry(id, processingCutoff) {
536
458
  await ensureTable();
537
459
  const now = Date.now();
538
460
  const timestamp = new Date().toISOString();
539
- const result = await withFencedExecutionWrite((tx) => tx.execute({
540
- sql: `UPDATE a2a_tasks
461
+ const result = await withFencedExecutionWrite((tx) => tx.execute(sql `UPDATE a2a_tasks
541
462
  SET status_state = ${taskTarget("retryStuck")},
542
- status_timestamp = ?,
543
- updated_at = ?
544
- WHERE id = ?
463
+ status_timestamp = ${sql.value(timestamp)},
464
+ updated_at = ${sql.value(now)}
465
+ WHERE id = ${sql.value(id)}
545
466
  AND status_state = ${taskSql("processing")}
546
- AND updated_at <= ?`,
547
- args: [timestamp, now, id, processingCutoff],
548
- }), { threadId: a2aTaskLeaseThreadId(id), turnId: id });
467
+ AND updated_at <= ${sql.value(processingCutoff)}`), { threadId: a2aTaskLeaseThreadId(id), turnId: id });
549
468
  const affected = getAffectedRowCount(result);
550
469
  return affected !== 0;
551
470
  }
@@ -562,31 +481,19 @@ export async function failStuckA2ATask(id, processingCutoff, reason, createdAtCu
562
481
  parts: [{ type: "text", text: reason }],
563
482
  };
564
483
  const ageCondition = createdAtCutoff !== undefined
565
- ? `AND (updated_at <= ? OR created_at <= ?)`
566
- : `AND updated_at <= ?`;
484
+ ? sql `AND (updated_at <= ${sql.value(processingCutoff)} OR created_at <= ${sql.value(createdAtCutoff)})`
485
+ : sql `AND updated_at <= ${sql.value(processingCutoff)}`;
567
486
  return withDbTransaction(client, async (tx) => {
568
487
  const leaseThreadId = a2aTaskLeaseThreadId(id);
569
488
  await lockTaskExecutionLease(tx, leaseThreadId, id);
570
- const result = await tx.execute({
571
- sql: `UPDATE a2a_tasks
489
+ const result = await tx.execute(sql `UPDATE a2a_tasks
572
490
  SET status_state = ${taskTarget("failStuckProcessing")},
573
- status_message = ?,
574
- status_timestamp = ?,
575
- updated_at = ?
576
- WHERE id = ?
491
+ status_message = ${sql.value(JSON.stringify(message))},
492
+ status_timestamp = ${sql.value(timestamp)},
493
+ updated_at = ${sql.value(now)}
494
+ WHERE id = ${sql.value(id)}
577
495
  AND status_state = ${taskSql("processing")}
578
- ${ageCondition}`,
579
- args: createdAtCutoff !== undefined
580
- ? [
581
- JSON.stringify(message),
582
- timestamp,
583
- now,
584
- id,
585
- processingCutoff,
586
- createdAtCutoff,
587
- ]
588
- : [JSON.stringify(message), timestamp, now, id, processingCutoff],
589
- });
496
+ ${ageCondition}`);
590
497
  const affected = getAffectedRowCount(result);
591
498
  if (affected === 1) {
592
499
  await revokeTaskExecutionLease(tx, leaseThreadId, id);
@@ -609,17 +516,14 @@ export async function failStuckQueuedA2ATask(id, createdAtCutoff, reason) {
609
516
  return withDbTransaction(client, async (tx) => {
610
517
  const leaseThreadId = a2aTaskLeaseThreadId(id);
611
518
  await lockTaskExecutionLease(tx, leaseThreadId, id);
612
- const result = await tx.execute({
613
- sql: `UPDATE a2a_tasks
519
+ const result = await tx.execute(sql `UPDATE a2a_tasks
614
520
  SET status_state = ${taskTarget("failStuckQueued")},
615
- status_message = ?,
616
- status_timestamp = ?,
617
- updated_at = ?
618
- WHERE id = ?
619
- AND status_state IN (${taskIn("failStuckQueued")})
620
- AND created_at <= ?`,
621
- args: [JSON.stringify(message), timestamp, now, id, createdAtCutoff],
622
- });
521
+ status_message = ${sql.value(JSON.stringify(message))},
522
+ status_timestamp = ${sql.value(timestamp)},
523
+ updated_at = ${sql.value(now)}
524
+ WHERE id = ${sql.value(id)}
525
+ AND status_state IN ${taskIn("failStuckQueued")}
526
+ AND created_at <= ${sql.value(createdAtCutoff)}`);
623
527
  const affected = getAffectedRowCount(result);
624
528
  if (affected === 1) {
625
529
  await revokeTaskExecutionLease(tx, leaseThreadId, id);
@@ -644,25 +548,15 @@ export async function failStaleA2ATask(id, staleBefore, reason, errorCode) {
644
548
  return withDbTransaction(client, async (tx) => {
645
549
  const leaseThreadId = a2aTaskLeaseThreadId(id);
646
550
  await lockTaskExecutionLease(tx, leaseThreadId, id);
647
- const result = await tx.execute({
648
- sql: `UPDATE a2a_tasks
551
+ const result = await tx.execute(sql `UPDATE a2a_tasks
649
552
  SET status_state = ${taskTarget("failStale")},
650
- status_message = ?,
651
- status_timestamp = ?,
652
- updated_at = ?
653
- WHERE id = ?
654
- AND status_state IN (${taskIn("failStale")})
655
- AND created_at < ?
656
- AND updated_at < ?`,
657
- args: [
658
- JSON.stringify(message),
659
- timestamp,
660
- now,
661
- id,
662
- staleBefore,
663
- staleBefore,
664
- ],
665
- });
553
+ status_message = ${sql.value(JSON.stringify(message))},
554
+ status_timestamp = ${sql.value(timestamp)},
555
+ updated_at = ${sql.value(now)}
556
+ WHERE id = ${sql.value(id)}
557
+ AND status_state IN ${taskIn("failStale")}
558
+ AND created_at < ${sql.value(staleBefore)}
559
+ AND updated_at < ${sql.value(staleBefore)}`);
666
560
  const affected = getAffectedRowCount(result);
667
561
  if (affected === 1) {
668
562
  await revokeTaskExecutionLease(tx, leaseThreadId, id);
@@ -674,10 +568,7 @@ export async function getTask(id, accessScope) {
674
568
  await ensureTable();
675
569
  const client = getDbExec();
676
570
  const predicate = taskAccessPredicate(accessScope);
677
- const { rows } = await client.execute({
678
- sql: `SELECT * FROM a2a_tasks WHERE id = ?${predicate.sql}`,
679
- args: [id, ...predicate.args],
680
- });
571
+ const { rows } = await client.execute(sql `SELECT * FROM a2a_tasks WHERE id = ${sql.value(id)}${predicate}`);
681
572
  if (rows.length === 0)
682
573
  return null;
683
574
  return taskFromRow(rows[0]);
@@ -688,10 +579,7 @@ export async function updateTask(id, update, accessScope) {
688
579
  await ensureTable();
689
580
  const predicate = taskAccessPredicate(accessScope);
690
581
  return withFencedExecutionWrite(async (tx) => {
691
- const { rows } = await tx.execute({
692
- sql: `SELECT * FROM a2a_tasks WHERE id = ?${predicate.sql}`,
693
- args: [id, ...predicate.args],
694
- });
582
+ const { rows } = await tx.execute(sql `SELECT * FROM a2a_tasks WHERE id = ${sql.value(id)}${predicate}`);
695
583
  if (rows.length === 0)
696
584
  return null;
697
585
  const task = taskFromRow(rows[0]);
@@ -712,27 +600,12 @@ export async function updateTask(id, update, accessScope) {
712
600
  assertA2APersistablePayload(task.status.message, "A2A task status message");
713
601
  assertA2APersistablePayload(task.history, "A2A task history");
714
602
  assertA2APersistablePayload(task.artifacts, "A2A task artifacts");
715
- const result = await tx.execute({
716
- sql: `UPDATE a2a_tasks SET status_state = ?, status_message = ?, status_timestamp = ?, history = ?, artifacts = ?, updated_at = ? WHERE id = ?${predicate.sql} AND status_state <> ${taskSql("canceled")}`,
717
- args: [
718
- task.status.state,
719
- task.status.message ? JSON.stringify(task.status.message) : null,
720
- task.status.timestamp,
721
- JSON.stringify(task.history),
722
- JSON.stringify(task.artifacts),
723
- now,
724
- id,
725
- ...predicate.args,
726
- ],
727
- });
603
+ const result = await tx.execute(sql `UPDATE a2a_tasks SET status_state = ${sql.value(task.status.state)}, status_message = ${sql.value(task.status.message ? JSON.stringify(task.status.message) : null)}, status_timestamp = ${sql.value(task.status.timestamp)}, history = ${sql.value(JSON.stringify(task.history))}, artifacts = ${sql.value(JSON.stringify(task.artifacts))}, updated_at = ${sql.value(now)} WHERE id = ${sql.value(id)}${predicate} AND status_state <> ${taskSql("canceled")}`);
728
604
  if (getAffectedRowCount(result) === 1)
729
605
  return task;
730
606
  // Zero rows: the task is missing, outside the access scope, or canceled.
731
607
  // Only a canceled row is a cancel win; the others stay null.
732
- const { rows: current } = await tx.execute({
733
- sql: `SELECT * FROM a2a_tasks WHERE id = ?${predicate.sql}`,
734
- args: [id, ...predicate.args],
735
- });
608
+ const { rows: current } = await tx.execute(sql `SELECT * FROM a2a_tasks WHERE id = ${sql.value(id)}${predicate}`);
736
609
  if (current[0]) {
737
610
  const stored = taskFromRow(current[0]);
738
611
  if (stored.status.state === "canceled") {
@@ -752,23 +625,17 @@ export async function cancelA2ATask(id, accessScope) {
752
625
  return withDbTransaction(client, async (tx) => {
753
626
  const leaseThreadId = a2aTaskLeaseThreadId(id);
754
627
  await lockTaskExecutionLease(tx, leaseThreadId, id);
755
- const { rows } = await tx.execute({
756
- sql: `SELECT * FROM a2a_tasks WHERE id = ?${predicate.sql} FOR UPDATE`,
757
- args: [id, ...predicate.args],
758
- });
628
+ const { rows } = await tx.execute(sql `SELECT * FROM a2a_tasks WHERE id = ${sql.value(id)}${predicate} FOR UPDATE`);
759
629
  if (!rows[0])
760
630
  return { status: "not_found" };
761
631
  // The row lock from FOR UPDATE means the guarded UPDATE below sees this
762
632
  // same state, so a zero-row update always means "not cancelable".
763
633
  const current = taskFromRow(rows[0]);
764
634
  const timestamp = new Date().toISOString();
765
- const result = await tx.execute({
766
- sql: `UPDATE a2a_tasks
767
- SET status_state = ${taskTarget("cancel")}, status_timestamp = ?, updated_at = ?
768
- WHERE id = ?${predicate.sql}
769
- AND status_state IN (${taskIn("cancel")})`,
770
- args: [timestamp, Date.now(), id, ...predicate.args],
771
- });
635
+ const result = await tx.execute(sql `UPDATE a2a_tasks
636
+ SET status_state = ${taskTarget("cancel")}, status_timestamp = ${sql.value(timestamp)}, updated_at = ${sql.value(Date.now())}
637
+ WHERE id = ${sql.value(id)}${predicate}
638
+ AND status_state IN ${taskIn("cancel")}`);
772
639
  if (getAffectedRowCount(result) !== 1) {
773
640
  return { status: "not_cancelable", state: current.status.state };
774
641
  }
@@ -821,26 +688,15 @@ export async function settleProcessingA2ATask(id, update) {
821
688
  assertA2APersistablePayload(task.status.message, "A2A task status message");
822
689
  assertA2APersistablePayload(task.history, "A2A task history");
823
690
  assertA2APersistablePayload(task.artifacts, "A2A task artifacts");
824
- const result = await tx.execute({
825
- sql: `UPDATE a2a_tasks
826
- SET status_state = ?,
827
- status_message = ?,
828
- status_timestamp = ?,
829
- history = ?,
830
- artifacts = ?,
831
- updated_at = ?
832
- WHERE id = ?
833
- AND status_state = ${taskSql("processing")}`,
834
- args: [
835
- task.status.state,
836
- task.status.message ? JSON.stringify(task.status.message) : null,
837
- task.status.timestamp,
838
- JSON.stringify(task.history),
839
- JSON.stringify(task.artifacts),
840
- now,
841
- id,
842
- ],
843
- });
691
+ const result = await tx.execute(sql `UPDATE a2a_tasks
692
+ SET status_state = ${sql.value(task.status.state)},
693
+ status_message = ${sql.value(task.status.message ? JSON.stringify(task.status.message) : null)},
694
+ status_timestamp = ${sql.value(task.status.timestamp)},
695
+ history = ${sql.value(JSON.stringify(task.history))},
696
+ artifacts = ${sql.value(JSON.stringify(task.artifacts))},
697
+ updated_at = ${sql.value(now)}
698
+ WHERE id = ${sql.value(id)}
699
+ AND status_state = ${taskSql("processing")}`);
844
700
  const affected = getAffectedRowCount(result);
845
701
  if (affected === 0)
846
702
  return null;
@@ -852,15 +708,12 @@ export async function updateTaskStatusMessage(id, message) {
852
708
  await ensureTable();
853
709
  const now = Date.now();
854
710
  const timestamp = new Date().toISOString();
855
- await withFencedExecutionWrite((tx) => tx.execute({
856
- sql: `UPDATE a2a_tasks
857
- SET status_message = ?,
858
- status_timestamp = ?,
859
- updated_at = ?
860
- WHERE id = ?
861
- AND status_state IN (${taskIn("failStale")})`,
862
- args: [JSON.stringify(message), timestamp, now, id],
863
- }), { threadId: a2aTaskLeaseThreadId(id), turnId: id });
711
+ await withFencedExecutionWrite((tx) => tx.execute(sql `UPDATE a2a_tasks
712
+ SET status_message = ${sql.value(JSON.stringify(message))},
713
+ status_timestamp = ${sql.value(timestamp)},
714
+ updated_at = ${sql.value(now)}
715
+ WHERE id = ${sql.value(id)}
716
+ AND status_state IN ${taskIn("failStale")}`), { threadId: a2aTaskLeaseThreadId(id), turnId: id });
864
717
  }
865
718
  export async function listTasksPage(contextId, options = {}) {
866
719
  await ensureTable();
@@ -0,0 +1,3 @@
1
+ import type { ActionRunContext } from "./action.js";
2
+ /** Classify provenance for approval policy; this does not authenticate a caller. */
3
+ export declare function isOutsideAgentCall(ctx?: Pick<ActionRunContext, "caller" | "networkProtocol" | "automation">): boolean;
@@ -0,0 +1,8 @@
1
+ /** Classify provenance for approval policy; this does not authenticate a caller. */
2
+ export function isOutsideAgentCall(ctx) {
3
+ // CLI defaults to outside because coding agents drive it; Alice's decision is pending.
4
+ // Automation has no trusted origin in ctx yet; #8070's mcpManaged is job frontmatter.
5
+ return (ctx?.networkProtocol !== undefined ||
6
+ ctx?.automation !== undefined ||
7
+ (ctx?.caller !== "frontend" && ctx?.caller !== "tool"));
8
+ }
package/dist/action.d.ts CHANGED
@@ -369,6 +369,7 @@ export interface ActionMcpAppResourceConfig {
369
369
  title?: string;
370
370
  description?: string;
371
371
  html: string | ActionMcpAppHtmlBuilder;
372
+ requiresEmbedSession?: boolean;
372
373
  mimeType?: typeof MCP_APP_MIME_TYPE;
373
374
  _meta?: Record<string, unknown>;
374
375
  csp?: ActionMcpAppCsp | ActionMcpAppCspBuilder;