@codespar/cli 0.14.1 → 0.17.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 (534) hide show
  1. package/README.md +44 -17
  2. package/dist/commands/audit-replay.js +267 -0
  3. package/dist/commands/audit-replay.js.map +1 -0
  4. package/dist/commands/init.js +28 -0
  5. package/dist/commands/init.js.map +1 -1
  6. package/dist/commands/mandate-verify.js +98 -19
  7. package/dist/commands/mandate-verify.js.map +1 -1
  8. package/dist/index.js +17 -3
  9. package/dist/index.js.map +1 -1
  10. package/dist/mandate-codec.js +31 -20
  11. package/dist/mandate-codec.js.map +1 -1
  12. package/dist/surface.js +4 -1
  13. package/dist/surface.js.map +1 -1
  14. package/package.json +1 -1
  15. package/templates/bills-agent/README.md +8 -5
  16. package/templates/bills-agent/agents/bills-agent/.env.example +3 -3
  17. package/templates/bills-agent/agents/bills-agent/AGENTS.md +1 -1
  18. package/templates/bills-agent/agents/bills-agent/CLAUDE.md +1 -1
  19. package/templates/bills-agent/agents/bills-agent/README.md +62 -22
  20. package/templates/bills-agent/agents/bills-agent/SYSTEM_PROMPT.md +1 -1
  21. package/templates/bills-agent/agents/bills-agent/agent.yaml +2 -2
  22. package/templates/bills-agent/agents/bills-agent/package.json +14 -11
  23. package/templates/bills-agent/agents/bills-agent/src/kit.ts +193 -0
  24. package/templates/bills-agent/agents/bills-agent/test/adversarial.test.ts +8 -7
  25. package/templates/bills-agent/agents/bills-agent/test/check.test.ts +19 -2
  26. package/templates/bills-agent/agents/bills-agent/test/cli.test.ts +72 -24
  27. package/templates/bills-agent/agents/bills-agent/test/fixtures/excursao-300.transcript.jsonl +2 -0
  28. package/templates/bills-agent/agents/bills-agent/test/fixtures/material-400.transcript.jsonl +2 -0
  29. package/templates/bills-agent/agents/bills-agent/test/inspect.test.ts +124 -0
  30. package/templates/bills-agent/agents/bills-agent/test/provider.test.ts +25 -0
  31. package/templates/bills-agent/agents/bills-agent/test/scenarios.test.ts +10 -9
  32. package/templates/bills-agent/agents/bills-agent/tsconfig.json +0 -1
  33. package/templates/bills-agent/package.json +5 -2
  34. package/templates/bills-agent/packages/agent-core/README.md +2 -0
  35. package/templates/bills-agent/packages/agent-core/package.json +1 -1
  36. package/templates/bills-agent/packages/agent-core/src/api/charge-rail.ts +27 -6
  37. package/templates/bills-agent/packages/agent-core/src/api/rail.ts +16 -0
  38. package/templates/bills-agent/packages/agent-core/src/api/sandbox-payer.ts +20 -7
  39. package/templates/bills-agent/packages/agent-core/src/approval.ts +16 -2
  40. package/templates/bills-agent/packages/agent-core/src/bundle.ts +50 -4
  41. package/templates/bills-agent/packages/agent-core/src/channels.ts +140 -0
  42. package/templates/bills-agent/packages/agent-core/src/check.ts +90 -8
  43. package/templates/bills-agent/packages/agent-core/src/clock.ts +42 -0
  44. package/templates/bills-agent/packages/agent-core/src/engine.ts +119 -18
  45. package/templates/bills-agent/packages/agent-core/src/hash.ts +13 -0
  46. package/templates/bills-agent/packages/agent-core/src/index.ts +3 -0
  47. package/templates/bills-agent/packages/agent-core/src/manifest.ts +1 -1
  48. package/templates/bills-agent/packages/agent-core/src/rail.ts +16 -2
  49. package/templates/bills-agent/packages/agent-core/src/receipt-verification.ts +401 -0
  50. package/templates/bills-agent/packages/agent-core/src/state-machine.ts +3 -1
  51. package/templates/bills-agent/packages/agent-core/src/stubs/charge-rail.ts +2 -0
  52. package/templates/bills-agent/packages/agent-core/src/stubs/rail.ts +19 -2
  53. package/templates/bills-agent/packages/agent-core/src/types.ts +28 -0
  54. package/templates/bills-agent/packages/agent-core/test/approval.test.ts +36 -2
  55. package/templates/bills-agent/packages/agent-core/test/bundle.test.ts +85 -0
  56. package/templates/bills-agent/packages/agent-core/test/clock.test.ts +25 -0
  57. package/templates/bills-agent/packages/agent-core/test/engine.test.ts +73 -1
  58. package/templates/bills-agent/packages/agent-core/test/fixtures/staging-receipt-keys.json +18 -0
  59. package/templates/bills-agent/packages/agent-core/test/fixtures/staging-receipt.json +24 -0
  60. package/templates/bills-agent/packages/agent-core/test/helpers.ts +1 -1
  61. package/templates/bills-agent/packages/agent-core/test/manifest.test.ts +2 -2
  62. package/templates/bills-agent/packages/agent-core/test/receipt-verification.test.ts +316 -0
  63. package/templates/bills-agent/packages/agent-core/test/receivables.test.ts +51 -0
  64. package/templates/bills-agent/packages/agent-runtime/README.md +68 -0
  65. package/templates/bills-agent/packages/agent-runtime/bin.mjs +32 -0
  66. package/templates/bills-agent/packages/agent-runtime/package.json +23 -0
  67. package/templates/bills-agent/{agents/bills-agent → packages/agent-runtime}/src/adversarial.ts +36 -44
  68. package/templates/bills-agent/packages/agent-runtime/src/agent.ts +68 -0
  69. package/templates/bills-agent/packages/agent-runtime/src/channels/contact.ts +13 -0
  70. package/templates/bills-agent/packages/agent-runtime/src/channels/index.ts +72 -0
  71. package/templates/bills-agent/packages/agent-runtime/src/channels/rules.ts +120 -0
  72. package/templates/bills-agent/packages/agent-runtime/src/channels/types.ts +124 -0
  73. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +358 -0
  74. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +206 -0
  75. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/evidence.ts +109 -0
  76. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +225 -0
  77. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +143 -0
  78. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +47 -0
  79. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +113 -0
  80. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +113 -0
  81. package/templates/bills-agent/packages/agent-runtime/src/cli.ts +98 -0
  82. package/templates/bills-agent/packages/agent-runtime/src/commands/check.ts +15 -0
  83. package/templates/bills-agent/packages/agent-runtime/src/commands/decide.ts +63 -0
  84. package/templates/bills-agent/packages/agent-runtime/src/commands/eval.ts +58 -0
  85. package/templates/bills-agent/packages/agent-runtime/src/commands/inspect.ts +100 -0
  86. package/templates/bills-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +317 -0
  87. package/templates/bills-agent/packages/agent-runtime/src/commands/poll.ts +144 -0
  88. package/templates/bills-agent/packages/agent-runtime/src/commands/reconcile.ts +42 -0
  89. package/templates/bills-agent/packages/agent-runtime/src/commands/rerun.ts +86 -0
  90. package/templates/bills-agent/packages/agent-runtime/src/commands/resume.ts +43 -0
  91. package/templates/bills-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +131 -0
  92. package/templates/bills-agent/packages/agent-runtime/src/commands/start.ts +245 -0
  93. package/templates/bills-agent/packages/agent-runtime/src/commands/verify.ts +129 -0
  94. package/templates/bills-agent/packages/agent-runtime/src/commands/webhook.ts +39 -0
  95. package/templates/bills-agent/packages/agent-runtime/src/default-kit.ts +83 -0
  96. package/templates/bills-agent/packages/agent-runtime/src/index.ts +12 -0
  97. package/templates/bills-agent/packages/agent-runtime/src/inspect.ts +797 -0
  98. package/templates/bills-agent/packages/agent-runtime/src/kit.ts +206 -0
  99. package/templates/{collections-agent/agents/collections-agent → bills-agent/packages/agent-runtime}/src/poll.ts +22 -11
  100. package/templates/{collections-agent/agents/collections-agent → bills-agent/packages/agent-runtime}/src/scenarios.ts +50 -34
  101. package/templates/bills-agent/{agents/bills-agent → packages/agent-runtime}/src/setup.ts +88 -66
  102. package/templates/bills-agent/packages/agent-runtime/src/terminal.ts +154 -0
  103. package/templates/{collections-agent/agents/collections-agent/channels/webhook/index.ts → bills-agent/packages/agent-runtime/src/webhook.ts} +1 -1
  104. package/templates/bills-agent/packages/agent-runtime/test/inspect.test.ts +336 -0
  105. package/templates/bills-agent/packages/agent-runtime/test/verify-cli.test.ts +127 -0
  106. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +232 -0
  107. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +204 -0
  108. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-evidence.test.ts +94 -0
  109. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +174 -0
  110. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-session.test.ts +135 -0
  111. package/templates/bills-agent/packages/agent-runtime/tsconfig.json +9 -0
  112. package/templates/bills-agent/vitest.config.ts +1 -1
  113. package/templates/collections-agent/README.md +8 -5
  114. package/templates/collections-agent/agents/collections-agent/.env.example +14 -0
  115. package/templates/collections-agent/agents/collections-agent/AGENTS.md +6 -4
  116. package/templates/collections-agent/agents/collections-agent/CLAUDE.md +6 -4
  117. package/templates/collections-agent/agents/collections-agent/README.md +184 -16
  118. package/templates/collections-agent/agents/collections-agent/agent.yaml +3 -3
  119. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/README.md +111 -0
  120. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/acordo-1042.json +11 -0
  121. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/acordo-1103.json +11 -0
  122. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/templates.json +23 -0
  123. package/templates/collections-agent/agents/collections-agent/package.json +12 -10
  124. package/templates/collections-agent/agents/collections-agent/runbook.md +52 -1
  125. package/templates/collections-agent/agents/collections-agent/src/kit.ts +265 -0
  126. package/templates/collections-agent/agents/collections-agent/test/adversarial.test.ts +9 -8
  127. package/templates/collections-agent/agents/collections-agent/test/check.test.ts +43 -1
  128. package/templates/collections-agent/agents/collections-agent/test/cli.test.ts +56 -18
  129. package/templates/collections-agent/agents/collections-agent/test/fixtures/agreed-1042-awaiting-payer.transcript.jsonl +4 -0
  130. package/templates/collections-agent/agents/collections-agent/test/scenarios.test.ts +11 -10
  131. package/templates/collections-agent/agents/collections-agent/test/webhook.test.ts +4 -7
  132. package/templates/collections-agent/agents/collections-agent/test/whatsapp-poll.test.ts +271 -0
  133. package/templates/collections-agent/agents/collections-agent/test/whatsapp.test.ts +213 -0
  134. package/templates/collections-agent/agents/collections-agent/tsconfig.json +0 -1
  135. package/templates/collections-agent/package.json +3 -1
  136. package/templates/collections-agent/packages/agent-core/README.md +2 -0
  137. package/templates/collections-agent/packages/agent-core/package.json +1 -1
  138. package/templates/collections-agent/packages/agent-core/src/api/charge-rail.ts +27 -6
  139. package/templates/collections-agent/packages/agent-core/src/api/rail.ts +16 -0
  140. package/templates/collections-agent/packages/agent-core/src/api/sandbox-payer.ts +20 -7
  141. package/templates/collections-agent/packages/agent-core/src/approval.ts +16 -2
  142. package/templates/collections-agent/packages/agent-core/src/bundle.ts +50 -4
  143. package/templates/collections-agent/packages/agent-core/src/channels.ts +140 -0
  144. package/templates/collections-agent/packages/agent-core/src/check.ts +90 -8
  145. package/templates/collections-agent/packages/agent-core/src/clock.ts +42 -0
  146. package/templates/collections-agent/packages/agent-core/src/engine.ts +119 -18
  147. package/templates/collections-agent/packages/agent-core/src/hash.ts +13 -0
  148. package/templates/collections-agent/packages/agent-core/src/index.ts +3 -0
  149. package/templates/collections-agent/packages/agent-core/src/manifest.ts +1 -1
  150. package/templates/collections-agent/packages/agent-core/src/rail.ts +16 -2
  151. package/templates/collections-agent/packages/agent-core/src/receipt-verification.ts +401 -0
  152. package/templates/collections-agent/packages/agent-core/src/state-machine.ts +3 -1
  153. package/templates/collections-agent/packages/agent-core/src/stubs/charge-rail.ts +2 -0
  154. package/templates/collections-agent/packages/agent-core/src/stubs/rail.ts +19 -2
  155. package/templates/collections-agent/packages/agent-core/src/types.ts +28 -0
  156. package/templates/collections-agent/packages/agent-core/test/approval.test.ts +36 -2
  157. package/templates/collections-agent/packages/agent-core/test/bundle.test.ts +85 -0
  158. package/templates/collections-agent/packages/agent-core/test/clock.test.ts +25 -0
  159. package/templates/collections-agent/packages/agent-core/test/engine.test.ts +73 -1
  160. package/templates/collections-agent/packages/agent-core/test/fixtures/staging-receipt-keys.json +18 -0
  161. package/templates/collections-agent/packages/agent-core/test/fixtures/staging-receipt.json +24 -0
  162. package/templates/collections-agent/packages/agent-core/test/helpers.ts +1 -1
  163. package/templates/collections-agent/packages/agent-core/test/manifest.test.ts +2 -2
  164. package/templates/collections-agent/packages/agent-core/test/receipt-verification.test.ts +316 -0
  165. package/templates/collections-agent/packages/agent-core/test/receivables.test.ts +51 -0
  166. package/templates/collections-agent/packages/agent-runtime/README.md +68 -0
  167. package/templates/collections-agent/packages/agent-runtime/bin.mjs +32 -0
  168. package/templates/collections-agent/packages/agent-runtime/package.json +23 -0
  169. package/templates/collections-agent/{agents/collections-agent → packages/agent-runtime}/src/adversarial.ts +29 -50
  170. package/templates/collections-agent/packages/agent-runtime/src/agent.ts +68 -0
  171. package/templates/collections-agent/packages/agent-runtime/src/channels/contact.ts +13 -0
  172. package/templates/collections-agent/packages/agent-runtime/src/channels/index.ts +72 -0
  173. package/templates/collections-agent/packages/agent-runtime/src/channels/rules.ts +120 -0
  174. package/templates/collections-agent/packages/agent-runtime/src/channels/types.ts +124 -0
  175. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +358 -0
  176. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +206 -0
  177. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/evidence.ts +109 -0
  178. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +225 -0
  179. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +143 -0
  180. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +47 -0
  181. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +113 -0
  182. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +113 -0
  183. package/templates/collections-agent/packages/agent-runtime/src/cli.ts +98 -0
  184. package/templates/collections-agent/packages/agent-runtime/src/commands/check.ts +15 -0
  185. package/templates/collections-agent/packages/agent-runtime/src/commands/decide.ts +63 -0
  186. package/templates/collections-agent/packages/agent-runtime/src/commands/eval.ts +58 -0
  187. package/templates/collections-agent/packages/agent-runtime/src/commands/inspect.ts +100 -0
  188. package/templates/collections-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +317 -0
  189. package/templates/collections-agent/packages/agent-runtime/src/commands/poll.ts +144 -0
  190. package/templates/collections-agent/packages/agent-runtime/src/commands/reconcile.ts +42 -0
  191. package/templates/collections-agent/packages/agent-runtime/src/commands/rerun.ts +86 -0
  192. package/templates/collections-agent/packages/agent-runtime/src/commands/resume.ts +43 -0
  193. package/templates/collections-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +131 -0
  194. package/templates/collections-agent/packages/agent-runtime/src/commands/start.ts +245 -0
  195. package/templates/collections-agent/packages/agent-runtime/src/commands/verify.ts +129 -0
  196. package/templates/collections-agent/packages/agent-runtime/src/commands/webhook.ts +39 -0
  197. package/templates/collections-agent/packages/agent-runtime/src/default-kit.ts +83 -0
  198. package/templates/collections-agent/packages/agent-runtime/src/index.ts +12 -0
  199. package/templates/collections-agent/packages/agent-runtime/src/inspect.ts +797 -0
  200. package/templates/collections-agent/packages/agent-runtime/src/kit.ts +206 -0
  201. package/templates/collections-agent/packages/agent-runtime/src/poll.ts +105 -0
  202. package/templates/{bills-agent/agents/bills-agent → collections-agent/packages/agent-runtime}/src/scenarios.ts +98 -26
  203. package/templates/collections-agent/packages/agent-runtime/src/setup.ts +229 -0
  204. package/templates/collections-agent/packages/agent-runtime/src/terminal.ts +154 -0
  205. package/templates/collections-agent/packages/agent-runtime/src/webhook.ts +131 -0
  206. package/templates/collections-agent/packages/agent-runtime/test/inspect.test.ts +336 -0
  207. package/templates/collections-agent/packages/agent-runtime/test/verify-cli.test.ts +127 -0
  208. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +232 -0
  209. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +204 -0
  210. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-evidence.test.ts +94 -0
  211. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +174 -0
  212. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-session.test.ts +135 -0
  213. package/templates/collections-agent/packages/agent-runtime/tsconfig.json +9 -0
  214. package/templates/collections-agent/vitest.config.ts +1 -1
  215. package/templates/hello-agent/LICENSE +21 -0
  216. package/templates/hello-agent/README.md +23 -0
  217. package/templates/hello-agent/_gitignore +10 -0
  218. package/templates/hello-agent/agents/hello-agent/.env.example +5 -0
  219. package/templates/hello-agent/agents/hello-agent/AGENTS.md +15 -0
  220. package/templates/hello-agent/agents/hello-agent/CLAUDE.md +15 -0
  221. package/templates/hello-agent/agents/hello-agent/README.md +33 -0
  222. package/templates/hello-agent/agents/hello-agent/SYSTEM_PROMPT.md +19 -0
  223. package/templates/hello-agent/agents/hello-agent/agent.yaml +19 -0
  224. package/templates/hello-agent/agents/hello-agent/evals/adversarial/beneficiary-swap.json +6 -0
  225. package/templates/hello-agent/agents/hello-agent/evals/adversarial/beneficiary-swap.transcript.jsonl +2 -0
  226. package/templates/hello-agent/agents/hello-agent/evals/adversarial/exfiltration.json +6 -0
  227. package/templates/hello-agent/agents/hello-agent/evals/adversarial/exfiltration.transcript.jsonl +2 -0
  228. package/templates/hello-agent/agents/hello-agent/evals/adversarial/false-authority.json +6 -0
  229. package/templates/hello-agent/agents/hello-agent/evals/adversarial/false-authority.transcript.jsonl +2 -0
  230. package/templates/hello-agent/agents/hello-agent/evals/adversarial/fractioning.json +6 -0
  231. package/templates/hello-agent/agents/hello-agent/evals/adversarial/fractioning.transcript.jsonl +2 -0
  232. package/templates/hello-agent/agents/hello-agent/evals/adversarial/model-total.json +6 -0
  233. package/templates/hello-agent/agents/hello-agent/evals/adversarial/model-total.transcript.jsonl +2 -0
  234. package/templates/hello-agent/agents/hello-agent/evals/adversarial/prompt-injection.json +6 -0
  235. package/templates/hello-agent/agents/hello-agent/evals/adversarial/prompt-injection.transcript.jsonl +2 -0
  236. package/templates/hello-agent/agents/hello-agent/evals/adversarial/webhook-replay.json +6 -0
  237. package/templates/hello-agent/agents/hello-agent/evals/eval.yaml +7 -0
  238. package/templates/hello-agent/agents/hello-agent/guardrails.json +8 -0
  239. package/templates/hello-agent/agents/hello-agent/mandate.example.json +17 -0
  240. package/templates/hello-agent/agents/hello-agent/package.json +19 -0
  241. package/templates/hello-agent/agents/hello-agent/runbook.md +10 -0
  242. package/templates/hello-agent/agents/hello-agent/scenarios/happy-path.json +6 -0
  243. package/templates/hello-agent/agents/hello-agent/scenarios/happy-path.transcript.jsonl +2 -0
  244. package/templates/hello-agent/agents/hello-agent/scenarios/prompt-injection.json +6 -0
  245. package/templates/hello-agent/agents/hello-agent/scenarios/prompt-injection.transcript.jsonl +2 -0
  246. package/templates/hello-agent/agents/hello-agent/src/bills.ts +23 -0
  247. package/templates/hello-agent/agents/hello-agent/src/kit.ts +33 -0
  248. package/templates/hello-agent/agents/hello-agent/tools.json +11 -0
  249. package/templates/hello-agent/agents/hello-agent/tsconfig.json +9 -0
  250. package/templates/hello-agent/package.json +30 -0
  251. package/templates/hello-agent/packages/agent-core/README.md +21 -0
  252. package/templates/hello-agent/packages/agent-core/package.json +24 -0
  253. package/templates/hello-agent/packages/agent-core/src/agent.ts +125 -0
  254. package/templates/hello-agent/packages/agent-core/src/api/charge-rail.ts +175 -0
  255. package/templates/hello-agent/packages/agent-core/src/api/client.ts +53 -0
  256. package/templates/hello-agent/packages/agent-core/src/api/mandate-status.ts +58 -0
  257. package/templates/hello-agent/packages/agent-core/src/api/rail.ts +117 -0
  258. package/templates/hello-agent/packages/agent-core/src/api/sandbox-payer.ts +58 -0
  259. package/templates/hello-agent/packages/agent-core/src/approval.ts +123 -0
  260. package/templates/hello-agent/packages/agent-core/src/bundle.ts +159 -0
  261. package/templates/hello-agent/packages/agent-core/src/channels.ts +140 -0
  262. package/templates/hello-agent/packages/agent-core/src/check.ts +253 -0
  263. package/templates/hello-agent/packages/agent-core/src/clock.ts +42 -0
  264. package/templates/hello-agent/packages/agent-core/src/engine.ts +885 -0
  265. package/templates/hello-agent/packages/agent-core/src/escalate.ts +85 -0
  266. package/templates/hello-agent/packages/agent-core/src/events.ts +40 -0
  267. package/templates/hello-agent/packages/agent-core/src/guardrails.ts +45 -0
  268. package/templates/hello-agent/packages/agent-core/src/hash.ts +62 -0
  269. package/templates/hello-agent/packages/agent-core/src/ids.ts +10 -0
  270. package/templates/hello-agent/packages/agent-core/src/index.ts +32 -0
  271. package/templates/hello-agent/packages/agent-core/src/mandate.ts +100 -0
  272. package/templates/hello-agent/packages/agent-core/src/manifest.ts +76 -0
  273. package/templates/hello-agent/packages/agent-core/src/providers/anthropic.ts +76 -0
  274. package/templates/hello-agent/packages/agent-core/src/providers/replay.ts +63 -0
  275. package/templates/hello-agent/packages/agent-core/src/providers/types.ts +39 -0
  276. package/templates/hello-agent/packages/agent-core/src/rail.ts +101 -0
  277. package/templates/hello-agent/packages/agent-core/src/receipt-verification.ts +401 -0
  278. package/templates/hello-agent/packages/agent-core/src/revocation.ts +30 -0
  279. package/templates/hello-agent/packages/agent-core/src/secrets.ts +30 -0
  280. package/templates/hello-agent/packages/agent-core/src/state/store.ts +307 -0
  281. package/templates/hello-agent/packages/agent-core/src/state-machine.ts +148 -0
  282. package/templates/hello-agent/packages/agent-core/src/stubs/charge-rail.ts +195 -0
  283. package/templates/hello-agent/packages/agent-core/src/stubs/mandate-status.ts +57 -0
  284. package/templates/hello-agent/packages/agent-core/src/stubs/rail.ts +141 -0
  285. package/templates/hello-agent/packages/agent-core/src/tools.ts +55 -0
  286. package/templates/hello-agent/packages/agent-core/src/types.ts +134 -0
  287. package/templates/hello-agent/packages/agent-core/test/approval.test.ts +117 -0
  288. package/templates/hello-agent/packages/agent-core/test/bundle.test.ts +85 -0
  289. package/templates/hello-agent/packages/agent-core/test/clock.test.ts +25 -0
  290. package/templates/hello-agent/packages/agent-core/test/engine.test.ts +596 -0
  291. package/templates/hello-agent/packages/agent-core/test/escalate.test.ts +42 -0
  292. package/templates/hello-agent/packages/agent-core/test/fixtures/staging-receipt-keys.json +18 -0
  293. package/templates/hello-agent/packages/agent-core/test/fixtures/staging-receipt.json +24 -0
  294. package/templates/hello-agent/packages/agent-core/test/helpers.ts +139 -0
  295. package/templates/hello-agent/packages/agent-core/test/mandate-status.test.ts +153 -0
  296. package/templates/hello-agent/packages/agent-core/test/manifest.test.ts +45 -0
  297. package/templates/hello-agent/packages/agent-core/test/receipt-verification.test.ts +316 -0
  298. package/templates/hello-agent/packages/agent-core/test/receivables.test.ts +316 -0
  299. package/templates/hello-agent/packages/agent-core/test/secrets.test.ts +28 -0
  300. package/templates/hello-agent/packages/agent-core/test/state-machine.test.ts +67 -0
  301. package/templates/hello-agent/packages/agent-core/test/transitions.type-test.ts +59 -0
  302. package/templates/hello-agent/packages/agent-core/tsconfig.json +10 -0
  303. package/templates/hello-agent/packages/agent-runtime/README.md +68 -0
  304. package/templates/hello-agent/packages/agent-runtime/bin.mjs +32 -0
  305. package/templates/hello-agent/packages/agent-runtime/package.json +23 -0
  306. package/templates/hello-agent/packages/agent-runtime/src/adversarial.ts +169 -0
  307. package/templates/hello-agent/packages/agent-runtime/src/agent.ts +68 -0
  308. package/templates/hello-agent/packages/agent-runtime/src/channels/contact.ts +13 -0
  309. package/templates/hello-agent/packages/agent-runtime/src/channels/index.ts +72 -0
  310. package/templates/hello-agent/packages/agent-runtime/src/channels/rules.ts +120 -0
  311. package/templates/hello-agent/packages/agent-runtime/src/channels/types.ts +124 -0
  312. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +358 -0
  313. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +206 -0
  314. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/evidence.ts +109 -0
  315. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +225 -0
  316. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +143 -0
  317. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +47 -0
  318. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +113 -0
  319. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +113 -0
  320. package/templates/hello-agent/packages/agent-runtime/src/cli.ts +98 -0
  321. package/templates/hello-agent/packages/agent-runtime/src/commands/check.ts +15 -0
  322. package/templates/hello-agent/packages/agent-runtime/src/commands/decide.ts +63 -0
  323. package/templates/hello-agent/packages/agent-runtime/src/commands/eval.ts +58 -0
  324. package/templates/hello-agent/packages/agent-runtime/src/commands/inspect.ts +100 -0
  325. package/templates/hello-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +317 -0
  326. package/templates/hello-agent/packages/agent-runtime/src/commands/poll.ts +144 -0
  327. package/templates/hello-agent/packages/agent-runtime/src/commands/reconcile.ts +42 -0
  328. package/templates/hello-agent/packages/agent-runtime/src/commands/rerun.ts +86 -0
  329. package/templates/hello-agent/packages/agent-runtime/src/commands/resume.ts +43 -0
  330. package/templates/hello-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +131 -0
  331. package/templates/hello-agent/packages/agent-runtime/src/commands/start.ts +245 -0
  332. package/templates/hello-agent/packages/agent-runtime/src/commands/verify.ts +129 -0
  333. package/templates/hello-agent/packages/agent-runtime/src/commands/webhook.ts +39 -0
  334. package/templates/hello-agent/packages/agent-runtime/src/default-kit.ts +83 -0
  335. package/templates/hello-agent/packages/agent-runtime/src/index.ts +12 -0
  336. package/templates/hello-agent/packages/agent-runtime/src/inspect.ts +797 -0
  337. package/templates/hello-agent/packages/agent-runtime/src/kit.ts +206 -0
  338. package/templates/hello-agent/packages/agent-runtime/src/poll.ts +105 -0
  339. package/templates/hello-agent/packages/agent-runtime/src/scenarios.ts +268 -0
  340. package/templates/hello-agent/packages/agent-runtime/src/setup.ts +229 -0
  341. package/templates/hello-agent/packages/agent-runtime/src/terminal.ts +154 -0
  342. package/templates/hello-agent/packages/agent-runtime/src/webhook.ts +131 -0
  343. package/templates/hello-agent/packages/agent-runtime/test/inspect.test.ts +336 -0
  344. package/templates/hello-agent/packages/agent-runtime/test/verify-cli.test.ts +127 -0
  345. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +232 -0
  346. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +204 -0
  347. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-evidence.test.ts +94 -0
  348. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +174 -0
  349. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-session.test.ts +135 -0
  350. package/templates/hello-agent/packages/agent-runtime/tsconfig.json +9 -0
  351. package/templates/hello-agent/tsconfig.base.json +16 -0
  352. package/templates/hello-agent/vitest.config.ts +12 -0
  353. package/templates/kits.lock.json +60 -12
  354. package/templates/supplier-payments-agent/LICENSE +21 -0
  355. package/templates/supplier-payments-agent/README.md +23 -0
  356. package/templates/supplier-payments-agent/_gitignore +10 -0
  357. package/templates/supplier-payments-agent/agents/supplier-payments-agent/.env.example +7 -0
  358. package/templates/supplier-payments-agent/agents/supplier-payments-agent/AGENTS.md +21 -0
  359. package/templates/supplier-payments-agent/agents/supplier-payments-agent/CLAUDE.md +21 -0
  360. package/templates/supplier-payments-agent/agents/supplier-payments-agent/README.md +118 -0
  361. package/templates/supplier-payments-agent/agents/supplier-payments-agent/SYSTEM_PROMPT.md +29 -0
  362. package/templates/supplier-payments-agent/agents/supplier-payments-agent/agent.yaml +26 -0
  363. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/batch-tampering.json +12 -0
  364. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/batch-tampering.transcript.jsonl +3 -0
  365. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/beneficiary-swap-mandate.json +9 -0
  366. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/beneficiary-swap.json +10 -0
  367. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/beneficiary-swap.transcript.jsonl +2 -0
  368. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/exfiltration.json +13 -0
  369. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/exfiltration.transcript.jsonl +3 -0
  370. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/false-authority.json +9 -0
  371. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/false-authority.transcript.jsonl +3 -0
  372. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/fractioning.json +15 -0
  373. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/fractioning.transcript.jsonl +6 -0
  374. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/model-total.json +10 -0
  375. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/model-total.transcript.jsonl +2 -0
  376. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/prompt-injection.json +9 -0
  377. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/prompt-injection.transcript.jsonl +2 -0
  378. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/webhook-replay.json +9 -0
  379. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/eval.yaml +9 -0
  380. package/templates/supplier-payments-agent/agents/supplier-payments-agent/guardrails.json +15 -0
  381. package/templates/supplier-payments-agent/agents/supplier-payments-agent/mandate.example.json +70 -0
  382. package/templates/supplier-payments-agent/agents/supplier-payments-agent/package.json +26 -0
  383. package/templates/supplier-payments-agent/agents/supplier-payments-agent/runbook.md +19 -0
  384. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/beneficiary-not-allowed.json +14 -0
  385. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/beneficiary-not-allowed.transcript.jsonl +2 -0
  386. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/cap-exceeded.json +12 -0
  387. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/cap-exceeded.transcript.jsonl +2 -0
  388. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/escalated-above-threshold.json +20 -0
  389. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/escalated-above-threshold.transcript.jsonl +7 -0
  390. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/happy-path.json +19 -0
  391. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/happy-path.transcript.jsonl +3 -0
  392. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/mandate-revoked.json +21 -0
  393. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/mandate-revoked.transcript.jsonl +9 -0
  394. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/partial-batch-failure.json +21 -0
  395. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/partial-batch-failure.transcript.jsonl +3 -0
  396. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/prompt-injection.json +12 -0
  397. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/prompt-injection.transcript.jsonl +2 -0
  398. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/kit.ts +176 -0
  399. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/modules/batch-payout.ts +345 -0
  400. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/modules/pix-out.ts +118 -0
  401. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/payables.ts +76 -0
  402. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/adversarial.test.ts +53 -0
  403. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/batch.test.ts +384 -0
  404. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/check.test.ts +109 -0
  405. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/scenarios.test.ts +81 -0
  406. package/templates/supplier-payments-agent/agents/supplier-payments-agent/tools.json +53 -0
  407. package/templates/supplier-payments-agent/agents/supplier-payments-agent/tsconfig.json +9 -0
  408. package/templates/supplier-payments-agent/package.json +36 -0
  409. package/templates/supplier-payments-agent/packages/agent-core/README.md +21 -0
  410. package/templates/supplier-payments-agent/packages/agent-core/package.json +24 -0
  411. package/templates/supplier-payments-agent/packages/agent-core/src/agent.ts +125 -0
  412. package/templates/supplier-payments-agent/packages/agent-core/src/api/charge-rail.ts +175 -0
  413. package/templates/supplier-payments-agent/packages/agent-core/src/api/client.ts +53 -0
  414. package/templates/supplier-payments-agent/packages/agent-core/src/api/mandate-status.ts +58 -0
  415. package/templates/supplier-payments-agent/packages/agent-core/src/api/rail.ts +117 -0
  416. package/templates/supplier-payments-agent/packages/agent-core/src/api/sandbox-payer.ts +58 -0
  417. package/templates/supplier-payments-agent/packages/agent-core/src/approval.ts +123 -0
  418. package/templates/supplier-payments-agent/packages/agent-core/src/bundle.ts +159 -0
  419. package/templates/supplier-payments-agent/packages/agent-core/src/channels.ts +140 -0
  420. package/templates/supplier-payments-agent/packages/agent-core/src/check.ts +253 -0
  421. package/templates/supplier-payments-agent/packages/agent-core/src/clock.ts +42 -0
  422. package/templates/supplier-payments-agent/packages/agent-core/src/engine.ts +885 -0
  423. package/templates/supplier-payments-agent/packages/agent-core/src/escalate.ts +85 -0
  424. package/templates/supplier-payments-agent/packages/agent-core/src/events.ts +40 -0
  425. package/templates/supplier-payments-agent/packages/agent-core/src/guardrails.ts +45 -0
  426. package/templates/supplier-payments-agent/packages/agent-core/src/hash.ts +62 -0
  427. package/templates/supplier-payments-agent/packages/agent-core/src/ids.ts +10 -0
  428. package/templates/supplier-payments-agent/packages/agent-core/src/index.ts +32 -0
  429. package/templates/supplier-payments-agent/packages/agent-core/src/mandate.ts +100 -0
  430. package/templates/supplier-payments-agent/packages/agent-core/src/manifest.ts +76 -0
  431. package/templates/supplier-payments-agent/packages/agent-core/src/providers/anthropic.ts +76 -0
  432. package/templates/supplier-payments-agent/packages/agent-core/src/providers/replay.ts +63 -0
  433. package/templates/supplier-payments-agent/packages/agent-core/src/providers/types.ts +39 -0
  434. package/templates/supplier-payments-agent/packages/agent-core/src/rail.ts +101 -0
  435. package/templates/supplier-payments-agent/packages/agent-core/src/receipt-verification.ts +401 -0
  436. package/templates/supplier-payments-agent/packages/agent-core/src/revocation.ts +30 -0
  437. package/templates/supplier-payments-agent/packages/agent-core/src/secrets.ts +30 -0
  438. package/templates/supplier-payments-agent/packages/agent-core/src/state/store.ts +307 -0
  439. package/templates/supplier-payments-agent/packages/agent-core/src/state-machine.ts +148 -0
  440. package/templates/supplier-payments-agent/packages/agent-core/src/stubs/charge-rail.ts +195 -0
  441. package/templates/supplier-payments-agent/packages/agent-core/src/stubs/mandate-status.ts +57 -0
  442. package/templates/supplier-payments-agent/packages/agent-core/src/stubs/rail.ts +141 -0
  443. package/templates/supplier-payments-agent/packages/agent-core/src/tools.ts +55 -0
  444. package/templates/supplier-payments-agent/packages/agent-core/src/types.ts +134 -0
  445. package/templates/supplier-payments-agent/packages/agent-core/test/approval.test.ts +117 -0
  446. package/templates/supplier-payments-agent/packages/agent-core/test/bundle.test.ts +85 -0
  447. package/templates/supplier-payments-agent/packages/agent-core/test/clock.test.ts +25 -0
  448. package/templates/supplier-payments-agent/packages/agent-core/test/engine.test.ts +596 -0
  449. package/templates/supplier-payments-agent/packages/agent-core/test/escalate.test.ts +42 -0
  450. package/templates/supplier-payments-agent/packages/agent-core/test/fixtures/staging-receipt-keys.json +18 -0
  451. package/templates/supplier-payments-agent/packages/agent-core/test/fixtures/staging-receipt.json +24 -0
  452. package/templates/supplier-payments-agent/packages/agent-core/test/helpers.ts +139 -0
  453. package/templates/supplier-payments-agent/packages/agent-core/test/mandate-status.test.ts +153 -0
  454. package/templates/supplier-payments-agent/packages/agent-core/test/manifest.test.ts +45 -0
  455. package/templates/supplier-payments-agent/packages/agent-core/test/receipt-verification.test.ts +316 -0
  456. package/templates/supplier-payments-agent/packages/agent-core/test/receivables.test.ts +316 -0
  457. package/templates/supplier-payments-agent/packages/agent-core/test/secrets.test.ts +28 -0
  458. package/templates/supplier-payments-agent/packages/agent-core/test/state-machine.test.ts +67 -0
  459. package/templates/supplier-payments-agent/packages/agent-core/test/transitions.type-test.ts +59 -0
  460. package/templates/supplier-payments-agent/packages/agent-core/tsconfig.json +10 -0
  461. package/templates/supplier-payments-agent/packages/agent-runtime/README.md +68 -0
  462. package/templates/supplier-payments-agent/packages/agent-runtime/bin.mjs +32 -0
  463. package/templates/supplier-payments-agent/packages/agent-runtime/package.json +23 -0
  464. package/templates/supplier-payments-agent/packages/agent-runtime/src/adversarial.ts +169 -0
  465. package/templates/supplier-payments-agent/packages/agent-runtime/src/agent.ts +68 -0
  466. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/contact.ts +13 -0
  467. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/index.ts +72 -0
  468. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/rules.ts +120 -0
  469. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/types.ts +124 -0
  470. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +358 -0
  471. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +206 -0
  472. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/evidence.ts +109 -0
  473. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +225 -0
  474. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +143 -0
  475. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +47 -0
  476. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +113 -0
  477. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +113 -0
  478. package/templates/supplier-payments-agent/packages/agent-runtime/src/cli.ts +98 -0
  479. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/check.ts +15 -0
  480. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/decide.ts +63 -0
  481. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/eval.ts +58 -0
  482. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/inspect.ts +100 -0
  483. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +317 -0
  484. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/poll.ts +144 -0
  485. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/reconcile.ts +42 -0
  486. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/rerun.ts +86 -0
  487. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/resume.ts +43 -0
  488. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +131 -0
  489. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/start.ts +245 -0
  490. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/verify.ts +129 -0
  491. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/webhook.ts +39 -0
  492. package/templates/supplier-payments-agent/packages/agent-runtime/src/default-kit.ts +83 -0
  493. package/templates/supplier-payments-agent/packages/agent-runtime/src/index.ts +12 -0
  494. package/templates/supplier-payments-agent/packages/agent-runtime/src/inspect.ts +797 -0
  495. package/templates/supplier-payments-agent/packages/agent-runtime/src/kit.ts +206 -0
  496. package/templates/supplier-payments-agent/packages/agent-runtime/src/poll.ts +105 -0
  497. package/templates/supplier-payments-agent/packages/agent-runtime/src/scenarios.ts +268 -0
  498. package/templates/supplier-payments-agent/packages/agent-runtime/src/setup.ts +229 -0
  499. package/templates/supplier-payments-agent/packages/agent-runtime/src/terminal.ts +154 -0
  500. package/templates/supplier-payments-agent/packages/agent-runtime/src/webhook.ts +131 -0
  501. package/templates/supplier-payments-agent/packages/agent-runtime/test/inspect.test.ts +336 -0
  502. package/templates/supplier-payments-agent/packages/agent-runtime/test/verify-cli.test.ts +127 -0
  503. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +232 -0
  504. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +204 -0
  505. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-evidence.test.ts +94 -0
  506. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +174 -0
  507. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-session.test.ts +135 -0
  508. package/templates/supplier-payments-agent/packages/agent-runtime/tsconfig.json +9 -0
  509. package/templates/supplier-payments-agent/tsconfig.base.json +16 -0
  510. package/templates/supplier-payments-agent/vitest.config.ts +12 -0
  511. package/templates/bills-agent/agents/bills-agent/channels/terminal/index.ts +0 -108
  512. package/templates/bills-agent/agents/bills-agent/src/commands/approve.ts +0 -9
  513. package/templates/bills-agent/agents/bills-agent/src/commands/check.ts +0 -13
  514. package/templates/bills-agent/agents/bills-agent/src/commands/consent.ts +0 -26
  515. package/templates/bills-agent/agents/bills-agent/src/commands/decide.ts +0 -45
  516. package/templates/bills-agent/agents/bills-agent/src/commands/deny.ts +0 -7
  517. package/templates/bills-agent/agents/bills-agent/src/commands/eval.ts +0 -37
  518. package/templates/bills-agent/agents/bills-agent/src/commands/reconcile.ts +0 -38
  519. package/templates/bills-agent/agents/bills-agent/src/commands/rerun.ts +0 -65
  520. package/templates/bills-agent/agents/bills-agent/src/commands/resume.ts +0 -30
  521. package/templates/bills-agent/agents/bills-agent/src/main.ts +0 -185
  522. package/templates/collections-agent/agents/collections-agent/channels/terminal/index.ts +0 -178
  523. package/templates/collections-agent/agents/collections-agent/src/commands/approve.ts +0 -10
  524. package/templates/collections-agent/agents/collections-agent/src/commands/check.ts +0 -13
  525. package/templates/collections-agent/agents/collections-agent/src/commands/decide.ts +0 -48
  526. package/templates/collections-agent/agents/collections-agent/src/commands/deny.ts +0 -7
  527. package/templates/collections-agent/agents/collections-agent/src/commands/eval.ts +0 -39
  528. package/templates/collections-agent/agents/collections-agent/src/commands/poll.ts +0 -35
  529. package/templates/collections-agent/agents/collections-agent/src/commands/reconcile.ts +0 -38
  530. package/templates/collections-agent/agents/collections-agent/src/commands/rerun.ts +0 -55
  531. package/templates/collections-agent/agents/collections-agent/src/commands/resume.ts +0 -30
  532. package/templates/collections-agent/agents/collections-agent/src/commands/webhook.ts +0 -36
  533. package/templates/collections-agent/agents/collections-agent/src/main.ts +0 -193
  534. package/templates/collections-agent/agents/collections-agent/src/setup.ts +0 -250
@@ -0,0 +1,206 @@
1
+ /**
2
+ * The seam between the shared runner and one agent. Everything the runner
3
+ * cannot know — which rail the agent drives, what the person at the keyboard
4
+ * is called, which tools the model may reach, what a one-shot prints as JSON —
5
+ * comes from the `kit` the agent exports; everything else is here and is the
6
+ * same for every agent.
7
+ *
8
+ * An agent that needs none of it ships no kit at all: `defaultKit` drives the
9
+ * stub payment rail with the example mandate, which is what a read-only agent
10
+ * wants.
11
+ */
12
+ import type {
13
+ ChargeInstrument,
14
+ Execution,
15
+ LoadedManifest,
16
+ LocalMandateStatusStub,
17
+ Guardrails,
18
+ Mandate,
19
+ MandateStatusSource,
20
+ PaymentRail,
21
+ PolicyExtension,
22
+ StateStore,
23
+ StubPayerBehaviour,
24
+ StubRailOptions,
25
+ StubChargeRailOptions,
26
+ ToolHandler,
27
+ } from "@codespar/agent-core";
28
+ import type { ApiClient } from "@codespar/sdk";
29
+ import type { Setup } from "./setup.js";
30
+ import type { ScenarioCheck } from "./scenarios.js";
31
+ import type { AdversarialResult } from "./adversarial.js";
32
+
33
+ export type RailKind = "stub" | "api";
34
+
35
+ /**
36
+ * How an execution reaches a terminal state. `immediate`: the rail answers
37
+ * and the execution is settled or failed (money out). `await-payer`: the rail
38
+ * accepts and somebody else has to act, so the run looks at the receivable
39
+ * until it closes (money in).
40
+ */
41
+ export type Settlement = "immediate" | "await-payer";
42
+
43
+ /**
44
+ * Who plays the counterparty in the sandbox. With the stub rail it is the
45
+ * fixture inside the rail; with a test key it is the API's own test route.
46
+ */
47
+ export interface SandboxPayer {
48
+ kind: RailKind;
49
+ /** Pays a receivable this run issued. Returns what the payer reported, or the refusal. */
50
+ pay(chargeId: string, attemptId: string): Promise<{ ok: true; detail: string } | { ok: false; detail: string }>;
51
+ /** Stub only: what the fixture does with receivables issued from now on. */
52
+ behave(behaviour: StubPayerBehaviour): void;
53
+ /**
54
+ * Stub only: what the fixture does with ONE receivable that was already
55
+ * issued and looked at.
56
+ *
57
+ * It is separate from `behave` because they answer different questions, and
58
+ * a poll needs the second one. `behave` sets the default for receivables
59
+ * the rail has not seen yet; by the time a poll resumes a conversation the
60
+ * rail HAS seen this one, and its fate is a row in state.db that only this
61
+ * rewrites. It is separate from `pay` because `pay` means pay — the
62
+ * scenario runner's late payer calls it after telling the fixture to sit on
63
+ * everything, and it has to pay anyway.
64
+ *
65
+ * The API's payer is a route and has no equivalent, so this is optional.
66
+ */
67
+ decideFor?(attemptId: string, behaviour: StubPayerBehaviour): void;
68
+ }
69
+
70
+ export interface RailContext {
71
+ kind: RailKind;
72
+ env: NodeJS.ProcessEnv;
73
+ agentDir: string;
74
+ stateDir: string;
75
+ manifest: LoadedManifest;
76
+ store: StateStore;
77
+ gate: LocalMandateStatusStub;
78
+ now: (() => Date) | undefined;
79
+ /** The mandate a caller pinned (a scenario, a test), if any. */
80
+ mandate: Mandate | undefined;
81
+ /** Stub-rail overrides a caller pinned (rerun, a scenario). */
82
+ stubRail: StubRailOptions | StubChargeRailOptions | undefined;
83
+ /** Reads `<PREFIX>_<NAME>` from the environment, the prefix being the agent's own. */
84
+ envVar(name: string): string | undefined;
85
+ }
86
+
87
+ export interface RailBuild {
88
+ rail: PaymentRail;
89
+ mandate: Mandate;
90
+ /** The section 4.7 source. Defaults to the local stub gate. */
91
+ status?: MandateStatusSource;
92
+ api?: ApiClient | undefined;
93
+ payer?: SandboxPayer;
94
+ /** Milliseconds between two looks at an issued receivable. */
95
+ pollIntervalMs?: number;
96
+ }
97
+
98
+ export interface RuntimeLabels {
99
+ /** Who decides when no `--user` is given: `usr_terminal`, `usr_operator`. */
100
+ defaultUser: string;
101
+ /** Who decides inside a scenario or an adversarial case. */
102
+ evalUser: string;
103
+ /** The word for the signed instrument in the banner: `mandato`, `politica`. */
104
+ mandateWord: string;
105
+ /** The word for a sealed outcome in the console: `recibo`, `registro`. */
106
+ receiptWord: string;
107
+ /** What the interactive loop prints under the banner. */
108
+ intro: string;
109
+ /** The interactive prompt. */
110
+ prompt: string;
111
+ /** The question an `awaiting_approval` execution asks at the keyboard. */
112
+ approveQuestion: string;
113
+ /** What the console says when a dispatch ended with an unknown outcome. */
114
+ uncertainDispatch: string;
115
+ /** `reconcile`'s finding kind and detail for a sealed outcome the bundle does not hold. */
116
+ missingReceiptKind: string;
117
+ missingReceiptDetail(receiptId: string, runId: string): string;
118
+ /** `resume`'s line for an execution it could not close. */
119
+ stillExecuting(execution: Execution): string;
120
+ /** `await-payer` only: the line printed every few looks while the payer has not acted. */
121
+ waitingForPayer?(round: number): string;
122
+ }
123
+
124
+ export interface OneShotContext {
125
+ setup: Setup;
126
+ reply: string;
127
+ toolCalls: Array<{ name: string; refused: boolean }>;
128
+ executions: Execution[];
129
+ /** `Date.now()` when the turn started, for an agent that reports its cycle. */
130
+ startedAt: number;
131
+ }
132
+
133
+ export interface ConsentContext {
134
+ agentDir: string;
135
+ argv: string[];
136
+ say(line: string): void;
137
+ }
138
+
139
+ export interface EnsureMandateContext extends ConsentContext {
140
+ railKind: RailKind;
141
+ /** True when the run has no conversation to fall back on (a one-shot). */
142
+ oneShot: boolean;
143
+ ask(question: string): Promise<string>;
144
+ }
145
+
146
+ export interface AgentKit {
147
+ /** `immediate` (money out) or `await-payer` (money in). Default `immediate`. */
148
+ settlement?: Settlement;
149
+ /**
150
+ * Which rail a `--scenario` run uses: the stub always, or the one the
151
+ * environment resolved. An agent whose packs declare `rails` wants
152
+ * `requested`; one whose packs are offline fixtures wants `stub`.
153
+ */
154
+ scenarioRail?: "stub" | "requested";
155
+ labels: RuntimeLabels;
156
+ /** The usage text `--help`, a bad flag and a bad `--now` print. */
157
+ usage(manifest: LoadedManifest): string;
158
+ buildRail(ctx: RailContext): RailBuild;
159
+ handlers(setup: Setup): Record<string, ToolHandler>;
160
+ /** The deterministic policy the core runs as its `policyExtension`. */
161
+ policyExtension?(ctx: { agentDir: string; manifest: LoadedManifest; guardrails: Guardrails }): PolicyExtension | undefined;
162
+ /** The console lines that describe one execution. */
163
+ describeExecution(execution: Execution, setup: Setup): string[];
164
+ /** The `--json` body of a one-shot. */
165
+ oneShotPayload(ctx: OneShotContext): Record<string, unknown>;
166
+ /** `await-payer` only: what the payer reads when a receivable becomes payable. */
167
+ presentInstrument?(execution: Execution, instalment: number, chargeId: string, instrument: ChargeInstrument, tell: (line: string) => void): void;
168
+ /** `await-payer` only: the one message per outcome the counterparty receives. */
169
+ announceOutcome?(execution: Execution, setup: Setup, tell: (line: string) => void): boolean;
170
+ /**
171
+ * The SAME outcome as `announceOutcome`, carried as an approved template.
172
+ *
173
+ * It exists because a channel can have a rule about WHEN free text may be
174
+ * sent, and WhatsApp does: outside the 24 hours after the person's last
175
+ * message only a template Meta approved goes out. A collection reaches that
176
+ * state as its normal case — agreed Tuesday, paid Friday — so an agent that
177
+ * closes its cycle on a channel owns a template for each outcome it can
178
+ * close on, or it cannot tell the person at all.
179
+ *
180
+ * The name must be one the agent declares in
181
+ * `channels/whatsapp/templates.json`; the language is the registry's and is
182
+ * not repeated here. `undefined` means this agent has no approved copy for
183
+ * that outcome, which the caller REPORTS rather than papers over: a person
184
+ * who was not told was not told.
185
+ */
186
+ outcomeTemplate?(execution: Execution): { template: string; variables: string[] } | undefined;
187
+ /** Runs before a one-shot or an interactive session, when the mandate may have to be born first. Returns false to stop the run. */
188
+ ensureMandate?(ctx: EnsureMandateContext): Promise<boolean>;
189
+ /** `codespar-agent consent`. Absent means the agent has no consent step. */
190
+ consent?(ctx: ConsentContext): Promise<number>;
191
+ /** The prior settled executions an adversarial case asks for, so a velocity window has history. */
192
+ warmUp?(setup: Setup, aliases: string[], approver: { id: string; channel: string }): Promise<Set<string>>;
193
+ /** The `kind: events` adversarial case: duplicated and out-of-order deliveries. */
194
+ runEventsCase?(setup: Setup, tell: (line: string) => void): Promise<void>;
195
+ /**
196
+ * What a `rerun` has to reproduce from the recorded events, beyond the
197
+ * model's own outputs: a payee the rail refused, a receivable the payer let
198
+ * expire. The rail's and the counterparty's answers are part of the recording.
199
+ */
200
+ rerunPlan?(events: Array<Record<string, unknown>>): { stubRail?: StubRailOptions | StubChargeRailOptions; simulatePayer?: boolean };
201
+ /** Whether `rerun` compares the rail's outcomes as well as the state trail. */
202
+ rerunComparesOutcomes?: boolean;
203
+ /** The one line `eval` prints per scenario run and per adversarial case. */
204
+ evalScenarioLine?(check: ScenarioCheck): string;
205
+ evalAdversarialLine?(result: AdversarialResult): string;
206
+ }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * How the cycle closes without a webhook: the kit LOOKS at the receivable
3
+ * (`GET /v1/charges/{id}` through the rail's `lookup`, the stub's fixture
4
+ * offline) until the payer acted or the wait ran out. Each look is a
5
+ * `reconcile`, which is read-only on the rail and never re-issues. The
6
+ * instrument (QR, copy-and-paste, bank line) is presented the first time a
7
+ * look finds it payable; the debtor is told the outcome once, whatever the
8
+ * number of looks or events that carried it.
9
+ */
10
+ import type { ChargeInstrument, Execution, ExecutionEngine } from "@codespar/agent-core";
11
+ import type { SandboxPayer } from "./kit.js";
12
+
13
+ export interface PollHooks {
14
+ /**
15
+ * A receivable became payable: show the payer how to pay. Called once per
16
+ * instalment, and AWAITED — on a console the lines are on the screen by the
17
+ * time the call returns, but on a channel the message still has to go out,
18
+ * and a payer told how to pay after the poll already closed was not told.
19
+ */
20
+ onInstrument?: (execution: Execution, instalment: number, chargeId: string, instrument: ChargeInstrument) => void | Promise<void>;
21
+ /** The execution reached a terminal state. Called once. */
22
+ onClosed?: (execution: Execution) => void;
23
+ /** Called before each look after the first. */
24
+ onWait?: (execution: Execution, round: number) => void;
25
+ }
26
+
27
+ export interface PollOptions extends PollHooks {
28
+ intervalMs: number;
29
+ /** Wall-clock budget for the wait. */
30
+ timeoutMs: number;
31
+ /** Cap on looks, for a zero-interval (stub) loop: the fixture payer acts within two looks; a third proves nothing changes. */
32
+ maxRounds?: number;
33
+ /** When set, the payer plays once every instalment is payable, or after `payerAfterRounds` looks (a scenario, `--simulate-payer`). */
34
+ payer?: SandboxPayer | undefined;
35
+ payerAfterRounds?: number;
36
+ clock?: () => Date;
37
+ sleep?: (ms: number) => Promise<void>;
38
+ }
39
+
40
+ export interface PollResult {
41
+ execution: Execution;
42
+ rounds: number;
43
+ /** Seconds from the first look to the terminal state, or to the end of the wait. */
44
+ seconds: number;
45
+ timed_out: boolean;
46
+ payer_calls: string[];
47
+ }
48
+
49
+ const defaultSleep = (ms: number) => new Promise<void>((r) => setTimeout(r, ms));
50
+
51
+ /**
52
+ * Presents each instalment once, records `message.debtor` once per outcome,
53
+ * and returns when the execution is terminal or the wait is over. Safe to
54
+ * call again on the same execution (a restart): what was already shown is
55
+ * remembered in the state.db cursor table, not in memory.
56
+ */
57
+ export async function pollUntilClosed(engine: ExecutionEngine, executionId: string, options: PollOptions): Promise<PollResult> {
58
+ const clock = options.clock ?? (() => new Date());
59
+ const sleep = options.sleep ?? defaultSleep;
60
+ const startedWall = Date.now();
61
+ const started = clock().getTime();
62
+ const maxRounds = options.maxRounds ?? (options.intervalMs === 0 ? 3 : Number.POSITIVE_INFINITY);
63
+ const payerCalls: string[] = [];
64
+ let execution = engine.get(executionId);
65
+ if (!execution) throw new Error(`unknown execution ${executionId}`);
66
+ let rounds = 0;
67
+ let paidRequested = false;
68
+
69
+ const present = async (e: Execution) => {
70
+ for (const outcome of e.outcomes) {
71
+ if (outcome.status !== "accepted" || !outcome.instrument?.payable || !outcome.transaction_id) continue;
72
+ if (!engine.markShown(e.id, outcome.attempt_id)) continue;
73
+ await options.onInstrument?.(e, outcome.index + 1, outcome.transaction_id, outcome.instrument);
74
+ }
75
+ };
76
+
77
+ await present(execution);
78
+ while (execution.state === "executing") {
79
+ if (rounds > 0) {
80
+ // A zero-interval loop (the stub) is bounded by looks; a real one by the wall clock.
81
+ if (rounds >= maxRounds || (options.intervalMs > 0 && Date.now() - startedWall >= options.timeoutMs)) break;
82
+ options.onWait?.(execution, rounds);
83
+ if (options.intervalMs > 0) await sleep(options.intervalMs);
84
+ }
85
+ rounds += 1;
86
+ execution = await engine.reconcile(execution.id);
87
+ await present(execution);
88
+ // The sandbox payer plays once every receivable is payable (the QR was shown first, as in the scene), or after a few looks if the
89
+ // clearing house is still registering: the API's test route settles a PROCESSING charge too, and on the shared sandbox the
90
+ // registration can take minutes. A real payer is not this hook.
91
+ const issued = execution.outcomes.filter((o) => o.status === "accepted" && o.transaction_id);
92
+ const allPayable = issued.length > 0 && issued.every((o) => o.instrument?.payable);
93
+ const patienceOver = rounds >= (options.payerAfterRounds ?? 5);
94
+ if (options.payer && !paidRequested && execution.state === "executing" && issued.length > 0 && issued.length === execution.outcomes.filter((o) => o.status === "accepted").length && (allPayable || patienceOver)) {
95
+ paidRequested = true;
96
+ for (const outcome of issued) {
97
+ const result = await options.payer.pay(outcome.transaction_id!, outcome.attempt_id);
98
+ payerCalls.push(result.detail);
99
+ engine.note("sandbox_payer", execution.id, { charge_id: outcome.transaction_id, ok: result.ok, detail: result.detail });
100
+ }
101
+ }
102
+ }
103
+ if (execution.state !== "executing") options.onClosed?.(execution);
104
+ return { execution, rounds, seconds: Math.round(((clock().getTime() - started) / 1000) * 10) / 10, timed_out: execution.state === "executing", payer_calls: payerCalls };
105
+ }
@@ -1,22 +1,27 @@
1
1
  /**
2
2
  * Section 12: scenario packs. A scenario is a JSON file with the person's
3
- * turns, the decision the approver gives, the hooks that make the world
4
- * change mid-run (revocation, an uncertain rail answer) and what the trail
5
- * must look like at the end. The model's outputs come from a recorded
6
- * transcript, so the same file feeds the CI, the live demo and the docs.
3
+ * turns, the decision the approver gives, what the counterparty does with what
4
+ * the run produced, the hooks that make the world change mid-run (revocation,
5
+ * an uncertain rail answer) and what the trail must look like at the end. The
6
+ * model's outputs come from a recorded transcript, so the same file feeds the
7
+ * CI, the live demo and the docs.
7
8
  */
8
9
  import { existsSync, mkdtempSync, readdirSync, readFileSync } from "node:fs";
9
10
  import { tmpdir } from "node:os";
10
11
  import { basename, join, resolve } from "node:path";
11
12
  import { z } from "zod";
12
- import { StubRail, type ApprovalMode, type Execution } from "@codespar/agent-core";
13
- import { AGENT_DIR, RUNS_DIR, setup, type Setup } from "./setup.js";
14
- import { handleExecution } from "../channels/terminal/index.js";
13
+ import type { ApprovalMode, Execution } from "@codespar/agent-core";
14
+ import type { Agent } from "./agent.js";
15
+ import type { RailKind } from "./kit.js";
16
+ import { setup, type Setup } from "./setup.js";
17
+ import { announceOutcome, handleExecution } from "./terminal.js";
15
18
 
16
19
  const TurnSchema = z
17
20
  .object({
18
21
  input: z.string().min(1),
19
22
  decision: z.enum(["approve", "deny", "none"]).default("approve"),
23
+ /** `await-payer` only: what the payer does with what this turn issued — pays during the turn, pays only after the last turn (`late`), lets it expire (stub-only), or nothing. */
24
+ payer: z.enum(["pays", "late", "expires", "never"]).default("pays"),
20
25
  /** Runs after the execution is drafted and before the decision is taken. */
21
26
  before_decision: z.enum(["revoke_mandate", "pause_all"]).optional(),
22
27
  /** Runs after approval, before the rail is called; the core must catch it. */
@@ -38,6 +43,12 @@ const ExpectSchema = z
38
43
  refused_before_draft: z.number().int().nonnegative().optional(),
39
44
  /** Sum of the totals that reached `settled`. */
40
45
  settled_total: z.number().int().nonnegative().optional(),
46
+ /** Receivables the rail issued (one per instalment; a retry never adds one). */
47
+ charges_issued: z.number().int().nonnegative().optional(),
48
+ /** Messages the counterparty received about outcomes: one per outcome, never two. */
49
+ debtor_messages: z.number().int().nonnegative().optional(),
50
+ /** With a real key: the happy path closes inside this many seconds from issuance. */
51
+ max_cycle_seconds: z.number().positive().optional(),
41
52
  })
42
53
  .strict();
43
54
 
@@ -46,7 +57,18 @@ export const ScenarioSchema = z
46
57
  name: z.string().regex(/^[a-z0-9-]+$/),
47
58
  description: z.string(),
48
59
  modes: z.array(z.enum(["human", "mandate"])).nonempty(),
60
+ /** Which rails can run it. A fixture-only outcome (`expires`) needs the stub. */
61
+ rails: z.array(z.enum(["stub", "api"])).nonempty().default(["stub", "api"]),
49
62
  now: z.string().datetime().default("2026-09-23T18:00:00.000Z"),
63
+ /**
64
+ * Payees the stub rail refuses for the whole run, by their pinned key.
65
+ * The rail's answer is the only part of a partial failure a pack cannot
66
+ * script from the mandate: an allowlist refusal never reaches the rail,
67
+ * and a payout that the provider itself declines is what a batch has to
68
+ * survive. Empty by default, so a pack that does not name one runs
69
+ * exactly as before.
70
+ */
71
+ stub_refuse_payees: z.array(z.string()).default([]),
50
72
  transcript: z.string(),
51
73
  turns: z.array(TurnSchema).nonempty(),
52
74
  expect: z.record(z.enum(["human", "mandate", "both"]), ExpectSchema),
@@ -58,13 +80,19 @@ export type Scenario = z.infer<typeof ScenarioSchema>;
58
80
  export interface ScenarioRun {
59
81
  scenario: string;
60
82
  mode: ApprovalMode;
83
+ rail: RailKind;
61
84
  run_id: string;
62
85
  bundle_dir: string;
63
86
  replies: string[];
64
- executions: Array<{ id: string; state: string; reason: string | null; trigger: string | null; total: number; trail: string[]; receipt_ids: string[] }>;
87
+ executions: Array<{ id: string; state: string; reason: string | null; trigger: string | null; total: number; trail: string[]; charge_ids: string[]; receipt_ids: string[] }>;
65
88
  refused_before_draft: number;
66
89
  receipts: number;
67
90
  settled_total: number;
91
+ charges_issued: number;
92
+ debtor_messages: number;
93
+ /** Seconds from the first issuance to the last terminal state (wall clock on the API; the fake clock's ticks on the stub). */
94
+ cycle_seconds: number;
95
+ payer_calls: string[];
68
96
  }
69
97
 
70
98
  export interface ScenarioCheck {
@@ -74,57 +102,71 @@ export interface ScenarioCheck {
74
102
  run: ScenarioRun;
75
103
  }
76
104
 
77
- export function scenariosDir(): string {
78
- return join(AGENT_DIR, "scenarios");
105
+ export function scenariosDir(agent: Agent): string {
106
+ return join(agent.dir, "scenarios");
79
107
  }
80
108
 
81
- export function listScenarios(): string[] {
82
- return readdirSync(scenariosDir())
109
+ export function listScenarios(agent: Agent): string[] {
110
+ return readdirSync(scenariosDir(agent))
83
111
  .filter((f) => f.endsWith(".json"))
84
112
  .map((f) => basename(f, ".json"))
85
113
  .sort();
86
114
  }
87
115
 
88
- export function loadScenario(name: string): Scenario {
89
- const path = join(scenariosDir(), `${name}.json`);
90
- if (!existsSync(path)) throw new Error(`unknown scenario ${name}; available: ${listScenarios().join(", ")}`);
116
+ export function loadScenario(agent: Agent, name: string): Scenario {
117
+ const path = join(scenariosDir(agent), `${name}.json`);
118
+ if (!existsSync(path)) throw new Error(`unknown scenario ${name}; available: ${listScenarios(agent).join(", ")}`);
91
119
  return ScenarioSchema.parse(JSON.parse(readFileSync(path, "utf8")));
92
120
  }
93
121
 
94
122
  export interface RunScenarioOptions {
95
123
  mode: ApprovalMode;
124
+ rail?: RailKind;
96
125
  runsDir?: string;
97
126
  stateDir?: string;
98
127
  say?: (line: string) => void;
128
+ tell?: (line: string) => void;
129
+ waitSeconds?: number | undefined;
99
130
  }
100
131
 
101
- export async function runScenario(scenario: Scenario, options: RunScenarioOptions): Promise<ScenarioRun> {
132
+ export async function runScenario(agent: Agent, scenario: Scenario, options: RunScenarioOptions): Promise<ScenarioRun> {
102
133
  const say = options.say ?? (() => undefined);
134
+ const tell = options.tell ?? (() => undefined);
135
+ const rail = options.rail ?? "stub";
136
+ const awaitsPayer = agent.settlement === "await-payer";
137
+ // On the stub the clock is the scenario's and ticks a second per read; on the API it is the wall clock, so the cycle is measured for real.
103
138
  let clock = new Date(scenario.now);
104
139
  const tick = () => {
105
140
  clock = new Date(clock.getTime() + 1000);
106
141
  return clock;
107
142
  };
108
- const stateDir = options.stateDir ?? mkdtempSync(join(tmpdir(), `bills-${scenario.name}-${options.mode}-`));
109
- const s: Setup = setup({
143
+ const stateDir = options.stateDir ?? mkdtempSync(join(tmpdir(), `${agent.slug}-${scenario.name}-${options.mode}-`));
144
+ const s: Setup = setup(agent, {
110
145
  mode: options.mode,
111
- rail: "stub",
146
+ rail,
112
147
  provider: "replay",
113
- transcript: resolve(scenariosDir(), scenario.transcript),
114
- runsDir: options.runsDir ?? RUNS_DIR,
148
+ transcript: resolve(scenariosDir(agent), scenario.transcript),
149
+ runsDir: options.runsDir ?? join(agent.dir, "runs"),
115
150
  stateDir,
116
- now: tick,
151
+ ...(rail === "stub" ? { now: tick } : {}),
152
+ ...(scenario.stub_refuse_payees.length > 0 ? { stubRail: { refusePayees: scenario.stub_refuse_payees } } : {}),
117
153
  say,
118
154
  });
119
- const stub = s.rail as StubRail;
155
+ const stub = s.rail as { armUncertainOnce?: () => void };
120
156
  const runtime = s.makeRuntime();
121
157
  const replies: string[] = [];
122
- const approver = { id: "usr_demo_titular", channel: "terminal" };
158
+ const approver = { id: s.kit.labels.evalUser, channel: "terminal" };
123
159
  let refusedBeforeDraft = 0;
160
+ const payerCalls: string[] = [];
161
+ const late: string[] = [];
162
+ let firstIssued: number | undefined;
163
+ let lastClosed: number | undefined;
124
164
 
125
165
  try {
126
166
  for (const turn of scenario.turns) {
127
- if (turn.rail_uncertain) stub.armUncertainOnce();
167
+ if (turn.rail_uncertain) stub.armUncertainOnce?.();
168
+ s.payer?.behave(turn.payer === "late" ? "never" : turn.payer);
169
+ const before = new Set(s.engine.list().map((e) => e.id));
128
170
  const loop = s.makeLoop(runtime, async (execution: Execution) => {
129
171
  applyHook(s, turn.before_decision);
130
172
  const decided = await handleExecution(execution, {
@@ -132,7 +174,9 @@ export async function runScenario(scenario: Scenario, options: RunScenarioOption
132
174
  approver,
133
175
  decision: turn.decision,
134
176
  say,
177
+ tell,
135
178
  ask: async () => (turn.decision === "approve" ? "s" : "n"),
179
+ ...(awaitsPayer ? { simulatePayer: turn.payer === "pays", waitSeconds: options.waitSeconds ?? (rail === "api" ? 60 : 0) } : {}),
136
180
  });
137
181
  if (turn.before_execute && decided.state === "approved") {
138
182
  applyHook(s, turn.before_execute);
@@ -143,16 +187,36 @@ export async function runScenario(scenario: Scenario, options: RunScenarioOption
143
187
  const result = await loop.turn(turn.input);
144
188
  replies.push(result.reply);
145
189
  refusedBeforeDraft += s.store.listEvents({ run_id: s.runId }).filter((e) => e.type === "execution.refused_before_draft").length - refusedBeforeDraft;
190
+ if (turn.payer === "late") for (const e of s.engine.list({ state: "executing" })) if (!before.has(e.id)) late.push(e.id);
191
+ }
192
+ // A late payer pays after the conversation ended (the receivable was in flight while the world changed).
193
+ for (const id of late) {
194
+ for (const o of s.engine.get(id)?.outcomes ?? []) {
195
+ if (o.status !== "accepted" || !o.transaction_id) continue;
196
+ if (rail === "stub") await s.engine.reconcile(id); // the fixture registers the instrument on the first look
197
+ const r = await s.payer!.pay(o.transaction_id, o.attempt_id);
198
+ s.engine.note("sandbox_payer", id, { charge_id: o.transaction_id, ok: r.ok, detail: r.detail });
199
+ }
146
200
  }
147
201
  // Section 10: what is still executing is reconciled, never repeated. A rail that answers late needs more than one look.
148
- for (let round = 0; round < 3 && s.engine.list({ state: "executing" }).length > 0; round += 1) {
202
+ for (let round = 0; round < (rail === "api" ? 20 : 3) && s.engine.list({ state: "executing" }).length > 0; round += 1) {
203
+ if (rail === "api" && round > 0) await new Promise((r) => setTimeout(r, s.pollIntervalMs));
149
204
  for (const stuck of s.engine.list({ state: "executing" })) await s.engine.reconcile(stuck.id);
150
205
  }
206
+ // Whatever closed after the conversation is told to the counterparty once, as the poll or the webhook would.
207
+ if (awaitsPayer) for (const e of s.engine.list()) if (e.run_id === s.runId) announceOutcome(e, s, tell);
151
208
 
209
+ const events = s.store.listEvents({ run_id: s.runId });
210
+ for (const e of events) {
211
+ if (e.type === "rail.outcome" && (e.payload as { status: string }).status === "accepted" && firstIssued === undefined) firstIssued = new Date(e.at).getTime();
212
+ if (e.type === "execution.transition" && ["settled", "failed"].includes((e.payload as { to: string }).to)) lastClosed = new Date(e.at).getTime();
213
+ if (e.type === "sandbox_payer") payerCalls.push(String((e.payload as { detail: string }).detail));
214
+ }
152
215
  const executions = s.engine.list().filter((e) => e.run_id === s.runId);
153
216
  return {
154
217
  scenario: scenario.name,
155
218
  mode: options.mode,
219
+ rail,
156
220
  run_id: s.runId,
157
221
  bundle_dir: s.bundle.dir,
158
222
  replies,
@@ -163,11 +227,16 @@ export async function runScenario(scenario: Scenario, options: RunScenarioOption
163
227
  trigger: e.escalation?.trigger ?? null,
164
228
  total: e.total,
165
229
  trail: e.history.map((h) => h.to),
230
+ charge_ids: e.outcomes.map((o) => o.transaction_id).filter((x): x is string => typeof x === "string"),
166
231
  receipt_ids: e.outcomes.filter((o) => o.receipt_id).map((o) => o.receipt_id as string),
167
232
  })),
168
233
  refused_before_draft: refusedBeforeDraft,
169
234
  receipts: s.bundle.listReceipts().length,
170
235
  settled_total: executions.filter((e) => e.state === "settled").reduce((sum, e) => sum + e.total, 0),
236
+ charges_issued: events.filter((e) => e.type === "rail.outcome" && (e.payload as { status: string }).status === "accepted").length,
237
+ debtor_messages: events.filter((e) => e.type === "message.debtor").length,
238
+ cycle_seconds: firstIssued !== undefined && lastClosed !== undefined ? Math.round(((lastClosed - firstIssued) / 1000) * 10) / 10 : 0,
239
+ payer_calls: payerCalls,
171
240
  };
172
241
  } finally {
173
242
  s.close();
@@ -190,6 +259,9 @@ export function checkScenario(scenario: Scenario, run: ScenarioRun): ScenarioChe
190
259
  if (expect.receipts !== undefined && run.receipts !== expect.receipts) failures.push(`receipts ${run.receipts} != ${expect.receipts}`);
191
260
  if (expect.refused_before_draft !== undefined && run.refused_before_draft !== expect.refused_before_draft) failures.push(`refused_before_draft ${run.refused_before_draft} != ${expect.refused_before_draft}`);
192
261
  if (expect.settled_total !== undefined && run.settled_total !== expect.settled_total) failures.push(`settled_total ${run.settled_total} != ${expect.settled_total}`);
262
+ if (expect.charges_issued !== undefined && run.charges_issued !== expect.charges_issued) failures.push(`charges_issued ${run.charges_issued} != ${expect.charges_issued}`);
263
+ if (expect.debtor_messages !== undefined && run.debtor_messages !== expect.debtor_messages) failures.push(`debtor_messages ${run.debtor_messages} != ${expect.debtor_messages}`);
264
+ if (expect.max_cycle_seconds !== undefined && run.rail === "api" && run.cycle_seconds > expect.max_cycle_seconds) failures.push(`cycle_seconds ${run.cycle_seconds} > ${expect.max_cycle_seconds}`);
193
265
  }
194
266
  // Every run, every mode: nothing reaches executing without an approval artifact carrying its hash.
195
267
  return { ok: failures.length === 0, mode: run.mode, failures, run };