@codespar/cli 0.18.1 → 0.20.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 (558) hide show
  1. package/README.md +1 -1
  2. package/dist/commands/login.js +52 -12
  3. package/dist/commands/login.js.map +1 -1
  4. package/dist/index.js +1 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/surface.js +31 -13
  7. package/dist/surface.js.map +1 -1
  8. package/package.json +1 -1
  9. package/templates/bills-agent/README.md +2 -2
  10. package/templates/bills-agent/agents/bills-agent/.env.example +2 -2
  11. package/templates/bills-agent/agents/bills-agent/README.md +25 -18
  12. package/templates/bills-agent/agents/bills-agent/SYSTEM_PROMPT.md +13 -3
  13. package/templates/bills-agent/agents/bills-agent/agent.yaml +2 -1
  14. package/templates/bills-agent/agents/bills-agent/evals/adversarial/exfiltration.transcript.jsonl +1 -1
  15. package/templates/bills-agent/agents/bills-agent/evals/adversarial/false-authority.transcript.jsonl +1 -1
  16. package/templates/bills-agent/agents/bills-agent/evals/adversarial/prompt-injection.transcript.jsonl +1 -1
  17. package/templates/bills-agent/agents/bills-agent/mandate.example.json +1 -1
  18. package/templates/bills-agent/agents/bills-agent/runbook.md +1 -1
  19. package/templates/bills-agent/agents/bills-agent/scenarios/beneficiary-not-allowed.transcript.jsonl +1 -1
  20. package/templates/bills-agent/agents/bills-agent/scenarios/cap-exceeded.transcript.jsonl +1 -1
  21. package/templates/bills-agent/agents/bills-agent/scenarios/escalated-above-threshold.transcript.jsonl +4 -4
  22. package/templates/bills-agent/agents/bills-agent/scenarios/happy-path.transcript.jsonl +1 -1
  23. package/templates/bills-agent/agents/bills-agent/scenarios/mandate-revoked.json +1 -1
  24. package/templates/bills-agent/agents/bills-agent/scenarios/mandate-revoked.transcript.jsonl +4 -4
  25. package/templates/bills-agent/agents/bills-agent/scenarios/prompt-injection.transcript.jsonl +1 -1
  26. package/templates/bills-agent/agents/bills-agent/src/bills.ts +1 -1
  27. package/templates/bills-agent/agents/bills-agent/src/kit.ts +15 -28
  28. package/templates/bills-agent/agents/bills-agent/src/modules/embedded-consent.ts +42 -15
  29. package/templates/bills-agent/agents/bills-agent/src/modules/pix-out.ts +21 -3
  30. package/templates/bills-agent/agents/bills-agent/src/strings.ts +68 -0
  31. package/templates/bills-agent/agents/bills-agent/test/cli.test.ts +130 -2
  32. package/templates/bills-agent/agents/bills-agent/test/consent-money.test.ts +25 -0
  33. package/templates/bills-agent/agents/bills-agent/test/dates-and-approval.test.ts +98 -0
  34. package/templates/bills-agent/agents/bills-agent/test/eval-runs.test.ts +81 -0
  35. package/templates/bills-agent/agents/bills-agent/test/fixtures/excursao-300.transcript.jsonl +2 -2
  36. package/templates/bills-agent/agents/bills-agent/test/fixtures/material-400.transcript.jsonl +1 -1
  37. package/templates/bills-agent/agents/bills-agent/test/locale.test.ts +161 -0
  38. package/templates/bills-agent/agents/bills-agent/test/mandate-state.test.ts +108 -0
  39. package/templates/bills-agent/agents/bills-agent/test/refused-before-draft.test.ts +81 -0
  40. package/templates/bills-agent/agents/bills-agent/test/replay.test.ts +76 -0
  41. package/templates/bills-agent/agents/bills-agent/test/reply-and-outcome.test.ts +84 -0
  42. package/templates/bills-agent/agents/bills-agent/test/reply-language.test.ts +95 -0
  43. package/templates/bills-agent/agents/bills-agent/test/rerun-and-missing-transcript.test.ts +120 -0
  44. package/templates/bills-agent/agents/bills-agent/test/rerun-world-events.test.ts +55 -0
  45. package/templates/bills-agent/agents/bills-agent/tools.json +1 -1
  46. package/templates/bills-agent/packages/agent-core/README.md +21 -2
  47. package/templates/bills-agent/packages/agent-core/package.json +1 -1
  48. package/templates/bills-agent/packages/agent-core/src/agent.ts +33 -6
  49. package/templates/bills-agent/packages/agent-core/src/api/charge-rail.ts +15 -1
  50. package/templates/bills-agent/packages/agent-core/src/api/rail.ts +11 -5
  51. package/templates/bills-agent/packages/agent-core/src/api/sandbox-payer.ts +36 -0
  52. package/templates/bills-agent/packages/agent-core/src/bundle.ts +2 -0
  53. package/templates/bills-agent/packages/agent-core/src/channels.ts +18 -8
  54. package/templates/bills-agent/packages/agent-core/src/check.ts +25 -3
  55. package/templates/bills-agent/packages/agent-core/src/engine.ts +90 -9
  56. package/templates/bills-agent/packages/agent-core/src/escalate.ts +10 -0
  57. package/templates/bills-agent/packages/agent-core/src/index.ts +3 -0
  58. package/templates/bills-agent/packages/agent-core/src/language.ts +52 -0
  59. package/templates/bills-agent/packages/agent-core/src/locale.ts +88 -0
  60. package/templates/bills-agent/packages/agent-core/src/manifest.ts +4 -1
  61. package/templates/bills-agent/packages/agent-core/src/rail.ts +29 -1
  62. package/templates/bills-agent/packages/agent-core/src/receipt-verification.ts +30 -2
  63. package/templates/bills-agent/packages/agent-core/src/secrets.ts +53 -8
  64. package/templates/bills-agent/packages/agent-core/src/state-machine.ts +14 -0
  65. package/templates/bills-agent/packages/agent-core/src/strings.ts +175 -0
  66. package/templates/bills-agent/packages/agent-core/src/stubs/charge-rail.ts +15 -2
  67. package/templates/bills-agent/packages/agent-core/src/stubs/rail.ts +7 -4
  68. package/templates/bills-agent/packages/agent-core/src/types.ts +15 -2
  69. package/templates/bills-agent/packages/agent-core/test/actor-on-the-wire.test.ts +144 -0
  70. package/templates/bills-agent/packages/agent-core/test/attempt-replay.test.ts +2 -2
  71. package/templates/bills-agent/packages/agent-core/test/engine.test.ts +23 -0
  72. package/templates/bills-agent/packages/agent-core/test/helpers.ts +1 -1
  73. package/templates/bills-agent/packages/agent-core/test/language.test.ts +40 -0
  74. package/templates/bills-agent/packages/agent-core/test/locale.test.ts +137 -0
  75. package/templates/bills-agent/packages/agent-core/test/mandate-status.test.ts +2 -2
  76. package/templates/bills-agent/packages/agent-core/test/manifest.test.ts +2 -2
  77. package/templates/bills-agent/packages/agent-core/test/rail-errors.test.ts +74 -0
  78. package/templates/bills-agent/packages/agent-core/test/receipt-read-verification.test.ts +32 -0
  79. package/templates/bills-agent/packages/agent-core/test/receivables.test.ts +49 -0
  80. package/templates/bills-agent/packages/agent-core/test/recorded-turns.ts +29 -0
  81. package/templates/bills-agent/packages/agent-core/test/secrets.test.ts +40 -1
  82. package/templates/bills-agent/packages/agent-runtime/README.md +31 -4
  83. package/templates/bills-agent/packages/agent-runtime/src/channels/rules.ts +4 -2
  84. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +11 -5
  85. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +43 -21
  86. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +3 -0
  87. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +8 -12
  88. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -4
  89. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +12 -9
  90. package/templates/bills-agent/packages/agent-runtime/src/cli.ts +30 -4
  91. package/templates/bills-agent/packages/agent-runtime/src/commands/check.ts +18 -2
  92. package/templates/bills-agent/packages/agent-runtime/src/commands/decide.ts +13 -4
  93. package/templates/bills-agent/packages/agent-runtime/src/commands/eval.ts +7 -2
  94. package/templates/bills-agent/packages/agent-runtime/src/commands/inspect.ts +11 -13
  95. package/templates/bills-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +32 -24
  96. package/templates/bills-agent/packages/agent-runtime/src/commands/poll.ts +12 -5
  97. package/templates/bills-agent/packages/agent-runtime/src/commands/rerun.ts +83 -10
  98. package/templates/bills-agent/packages/agent-runtime/src/commands/resume.ts +2 -1
  99. package/templates/bills-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +10 -5
  100. package/templates/bills-agent/packages/agent-runtime/src/commands/start.ts +48 -17
  101. package/templates/bills-agent/packages/agent-runtime/src/commands/verify.ts +37 -12
  102. package/templates/bills-agent/packages/agent-runtime/src/commands/webhook.ts +11 -3
  103. package/templates/bills-agent/packages/agent-runtime/src/default-kit.ts +52 -22
  104. package/templates/bills-agent/packages/agent-runtime/src/env.ts +64 -0
  105. package/templates/bills-agent/packages/agent-runtime/src/index.ts +2 -0
  106. package/templates/bills-agent/packages/agent-runtime/src/inspect.ts +81 -10
  107. package/templates/bills-agent/packages/agent-runtime/src/kit.ts +34 -12
  108. package/templates/bills-agent/packages/agent-runtime/src/outcome.ts +118 -0
  109. package/templates/bills-agent/packages/agent-runtime/src/poll.ts +7 -7
  110. package/templates/bills-agent/packages/agent-runtime/src/runs.ts +51 -0
  111. package/templates/bills-agent/packages/agent-runtime/src/scenarios.ts +55 -8
  112. package/templates/bills-agent/packages/agent-runtime/src/setup.ts +75 -5
  113. package/templates/bills-agent/packages/agent-runtime/src/terminal.ts +71 -33
  114. package/templates/bills-agent/packages/agent-runtime/test/env-names.test.ts +56 -0
  115. package/templates/bills-agent/packages/agent-runtime/test/inspect-mandate-status.test.ts +80 -0
  116. package/templates/bills-agent/packages/agent-runtime/test/inspect.test.ts +63 -2
  117. package/templates/bills-agent/packages/agent-runtime/test/outcome.test.ts +72 -0
  118. package/templates/bills-agent/packages/agent-runtime/test/poll-payer.test.ts +64 -0
  119. package/templates/bills-agent/packages/agent-runtime/test/rerun-not-replayed.test.ts +46 -0
  120. package/templates/bills-agent/packages/agent-runtime/test/transition-line.test.ts +29 -0
  121. package/templates/bills-agent/packages/agent-runtime/test/verify-cli.test.ts +99 -6
  122. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +8 -0
  123. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-session.test.ts +77 -0
  124. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +27 -1
  125. package/templates/checkout-agent/README.md +2 -2
  126. package/templates/checkout-agent/agents/checkout-agent/.env.example +6 -4
  127. package/templates/checkout-agent/agents/checkout-agent/README.md +16 -8
  128. package/templates/checkout-agent/agents/checkout-agent/SYSTEM_PROMPT.md +17 -7
  129. package/templates/checkout-agent/agents/checkout-agent/agent.yaml +4 -3
  130. package/templates/checkout-agent/agents/checkout-agent/channels/whatsapp/README.md +2 -2
  131. package/templates/checkout-agent/agents/checkout-agent/channels/whatsapp/templates.json +48 -4
  132. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/beneficiary-swap-human.json +1 -1
  133. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/beneficiary-swap.json +1 -1
  134. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/beneficiary-swap.transcript.jsonl +1 -1
  135. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/coupon-unknown.json +1 -1
  136. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/exfiltration.transcript.jsonl +1 -1
  137. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/fractioning.transcript.jsonl +1 -1
  138. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/payment-claimed.json +1 -1
  139. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/payment-claimed.transcript.jsonl +1 -1
  140. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/price-injected.json +1 -1
  141. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/prompt-injection.transcript.jsonl +1 -1
  142. package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/quantity-swapped.transcript.jsonl +1 -1
  143. package/templates/checkout-agent/agents/checkout-agent/package.json +1 -1
  144. package/templates/checkout-agent/agents/checkout-agent/runbook.md +4 -4
  145. package/templates/checkout-agent/agents/checkout-agent/scenarios/beneficiary-not-allowed.transcript.jsonl +1 -1
  146. package/templates/checkout-agent/agents/checkout-agent/scenarios/cart-recomposed.transcript.jsonl +2 -2
  147. package/templates/checkout-agent/agents/checkout-agent/scenarios/cart-replaced.json +2 -2
  148. package/templates/checkout-agent/agents/checkout-agent/scenarios/cart-replaced.transcript.jsonl +2 -2
  149. package/templates/checkout-agent/agents/checkout-agent/scenarios/charge-expired.json +1 -1
  150. package/templates/checkout-agent/agents/checkout-agent/scenarios/charge-expired.transcript.jsonl +2 -2
  151. package/templates/checkout-agent/agents/checkout-agent/scenarios/coupon-unknown.transcript.jsonl +1 -1
  152. package/templates/checkout-agent/agents/checkout-agent/scenarios/escalated-above-threshold.transcript.jsonl +1 -1
  153. package/templates/checkout-agent/agents/checkout-agent/scenarios/happy-path.transcript.jsonl +2 -2
  154. package/templates/checkout-agent/agents/checkout-agent/scenarios/item-unavailable.transcript.jsonl +1 -1
  155. package/templates/checkout-agent/agents/checkout-agent/scenarios/mandate-revoked.transcript.jsonl +3 -3
  156. package/templates/checkout-agent/agents/checkout-agent/scenarios/payment-claimed.json +1 -1
  157. package/templates/checkout-agent/agents/checkout-agent/scenarios/payment-claimed.transcript.jsonl +2 -2
  158. package/templates/checkout-agent/agents/checkout-agent/scenarios/price-injected.transcript.jsonl +1 -1
  159. package/templates/checkout-agent/agents/checkout-agent/scenarios/prompt-injection.transcript.jsonl +1 -1
  160. package/templates/checkout-agent/agents/checkout-agent/src/catalog.ts +7 -7
  161. package/templates/checkout-agent/agents/checkout-agent/src/kit.ts +47 -43
  162. package/templates/checkout-agent/agents/checkout-agent/src/modules/bolepix-receivables.ts +20 -12
  163. package/templates/checkout-agent/agents/checkout-agent/src/modules/nfse-invoice.ts +4 -4
  164. package/templates/checkout-agent/agents/checkout-agent/src/modules/storefront-cart.ts +9 -6
  165. package/templates/checkout-agent/agents/checkout-agent/src/pricing.ts +44 -41
  166. package/templates/checkout-agent/agents/checkout-agent/src/strings.ts +179 -0
  167. package/templates/checkout-agent/agents/checkout-agent/test/check.test.ts +4 -1
  168. package/templates/checkout-agent/agents/checkout-agent/test/fixtures/order-marina.transcript.jsonl +1 -1
  169. package/templates/checkout-agent/agents/checkout-agent/test/fixtures/ordered-marina-awaiting-payer.transcript.jsonl +2 -2
  170. package/templates/checkout-agent/agents/checkout-agent/test/fixtures/tap-falar-agora-marina.transcript.jsonl +1 -1
  171. package/templates/checkout-agent/agents/checkout-agent/test/payable-instrument.test.ts +58 -0
  172. package/templates/checkout-agent/agents/checkout-agent/test/pricing.test.ts +2 -2
  173. package/templates/checkout-agent/agents/checkout-agent/test/rerun-unpaid.test.ts +47 -0
  174. package/templates/checkout-agent/agents/checkout-agent/test/scenario-reach-and-seconds.test.ts +55 -0
  175. package/templates/checkout-agent/agents/checkout-agent/test/whatsapp.test.ts +26 -10
  176. package/templates/checkout-agent/agents/checkout-agent/tools.json +1 -1
  177. package/templates/checkout-agent/packages/agent-core/README.md +21 -2
  178. package/templates/checkout-agent/packages/agent-core/package.json +1 -1
  179. package/templates/checkout-agent/packages/agent-core/src/agent.ts +33 -6
  180. package/templates/checkout-agent/packages/agent-core/src/api/charge-rail.ts +15 -1
  181. package/templates/checkout-agent/packages/agent-core/src/api/rail.ts +11 -5
  182. package/templates/checkout-agent/packages/agent-core/src/api/sandbox-payer.ts +36 -0
  183. package/templates/checkout-agent/packages/agent-core/src/bundle.ts +2 -0
  184. package/templates/checkout-agent/packages/agent-core/src/channels.ts +18 -8
  185. package/templates/checkout-agent/packages/agent-core/src/check.ts +25 -3
  186. package/templates/checkout-agent/packages/agent-core/src/engine.ts +90 -9
  187. package/templates/checkout-agent/packages/agent-core/src/escalate.ts +10 -0
  188. package/templates/checkout-agent/packages/agent-core/src/index.ts +3 -0
  189. package/templates/checkout-agent/packages/agent-core/src/language.ts +52 -0
  190. package/templates/checkout-agent/packages/agent-core/src/locale.ts +88 -0
  191. package/templates/checkout-agent/packages/agent-core/src/manifest.ts +4 -1
  192. package/templates/checkout-agent/packages/agent-core/src/rail.ts +29 -1
  193. package/templates/checkout-agent/packages/agent-core/src/receipt-verification.ts +30 -2
  194. package/templates/checkout-agent/packages/agent-core/src/secrets.ts +53 -8
  195. package/templates/checkout-agent/packages/agent-core/src/state-machine.ts +14 -0
  196. package/templates/checkout-agent/packages/agent-core/src/strings.ts +175 -0
  197. package/templates/checkout-agent/packages/agent-core/src/stubs/charge-rail.ts +15 -2
  198. package/templates/checkout-agent/packages/agent-core/src/stubs/rail.ts +7 -4
  199. package/templates/checkout-agent/packages/agent-core/src/types.ts +15 -2
  200. package/templates/checkout-agent/packages/agent-core/test/actor-on-the-wire.test.ts +144 -0
  201. package/templates/checkout-agent/packages/agent-core/test/attempt-replay.test.ts +2 -2
  202. package/templates/checkout-agent/packages/agent-core/test/engine.test.ts +23 -0
  203. package/templates/checkout-agent/packages/agent-core/test/helpers.ts +1 -1
  204. package/templates/checkout-agent/packages/agent-core/test/language.test.ts +40 -0
  205. package/templates/checkout-agent/packages/agent-core/test/locale.test.ts +137 -0
  206. package/templates/checkout-agent/packages/agent-core/test/mandate-status.test.ts +2 -2
  207. package/templates/checkout-agent/packages/agent-core/test/manifest.test.ts +2 -2
  208. package/templates/checkout-agent/packages/agent-core/test/rail-errors.test.ts +74 -0
  209. package/templates/checkout-agent/packages/agent-core/test/receipt-read-verification.test.ts +32 -0
  210. package/templates/checkout-agent/packages/agent-core/test/receivables.test.ts +49 -0
  211. package/templates/checkout-agent/packages/agent-core/test/recorded-turns.ts +29 -0
  212. package/templates/checkout-agent/packages/agent-core/test/secrets.test.ts +40 -1
  213. package/templates/checkout-agent/packages/agent-runtime/README.md +31 -4
  214. package/templates/checkout-agent/packages/agent-runtime/src/channels/rules.ts +4 -2
  215. package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +11 -5
  216. package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +43 -21
  217. package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +3 -0
  218. package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +8 -12
  219. package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -4
  220. package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +12 -9
  221. package/templates/checkout-agent/packages/agent-runtime/src/cli.ts +30 -4
  222. package/templates/checkout-agent/packages/agent-runtime/src/commands/check.ts +18 -2
  223. package/templates/checkout-agent/packages/agent-runtime/src/commands/decide.ts +13 -4
  224. package/templates/checkout-agent/packages/agent-runtime/src/commands/eval.ts +7 -2
  225. package/templates/checkout-agent/packages/agent-runtime/src/commands/inspect.ts +11 -13
  226. package/templates/checkout-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +32 -24
  227. package/templates/checkout-agent/packages/agent-runtime/src/commands/poll.ts +12 -5
  228. package/templates/checkout-agent/packages/agent-runtime/src/commands/rerun.ts +83 -10
  229. package/templates/checkout-agent/packages/agent-runtime/src/commands/resume.ts +2 -1
  230. package/templates/checkout-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +10 -5
  231. package/templates/checkout-agent/packages/agent-runtime/src/commands/start.ts +48 -17
  232. package/templates/checkout-agent/packages/agent-runtime/src/commands/verify.ts +37 -12
  233. package/templates/checkout-agent/packages/agent-runtime/src/commands/webhook.ts +11 -3
  234. package/templates/checkout-agent/packages/agent-runtime/src/default-kit.ts +52 -22
  235. package/templates/checkout-agent/packages/agent-runtime/src/env.ts +64 -0
  236. package/templates/checkout-agent/packages/agent-runtime/src/index.ts +2 -0
  237. package/templates/checkout-agent/packages/agent-runtime/src/inspect.ts +81 -10
  238. package/templates/checkout-agent/packages/agent-runtime/src/kit.ts +34 -12
  239. package/templates/checkout-agent/packages/agent-runtime/src/outcome.ts +118 -0
  240. package/templates/checkout-agent/packages/agent-runtime/src/poll.ts +7 -7
  241. package/templates/checkout-agent/packages/agent-runtime/src/runs.ts +51 -0
  242. package/templates/checkout-agent/packages/agent-runtime/src/scenarios.ts +55 -8
  243. package/templates/checkout-agent/packages/agent-runtime/src/setup.ts +75 -5
  244. package/templates/checkout-agent/packages/agent-runtime/src/terminal.ts +71 -33
  245. package/templates/checkout-agent/packages/agent-runtime/test/env-names.test.ts +56 -0
  246. package/templates/checkout-agent/packages/agent-runtime/test/inspect-mandate-status.test.ts +80 -0
  247. package/templates/checkout-agent/packages/agent-runtime/test/inspect.test.ts +63 -2
  248. package/templates/checkout-agent/packages/agent-runtime/test/outcome.test.ts +72 -0
  249. package/templates/checkout-agent/packages/agent-runtime/test/poll-payer.test.ts +64 -0
  250. package/templates/checkout-agent/packages/agent-runtime/test/rerun-not-replayed.test.ts +46 -0
  251. package/templates/checkout-agent/packages/agent-runtime/test/transition-line.test.ts +29 -0
  252. package/templates/checkout-agent/packages/agent-runtime/test/verify-cli.test.ts +99 -6
  253. package/templates/checkout-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +8 -0
  254. package/templates/checkout-agent/packages/agent-runtime/test/whatsapp-session.test.ts +77 -0
  255. package/templates/checkout-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +27 -1
  256. package/templates/collections-agent/README.md +2 -2
  257. package/templates/collections-agent/agents/collections-agent/.env.example +6 -3
  258. package/templates/collections-agent/agents/collections-agent/README.md +14 -9
  259. package/templates/collections-agent/agents/collections-agent/SYSTEM_PROMPT.md +16 -5
  260. package/templates/collections-agent/agents/collections-agent/agent.yaml +4 -3
  261. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/README.md +21 -4
  262. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/templates.json +49 -5
  263. package/templates/collections-agent/agents/collections-agent/mandate.example.json +1 -1
  264. package/templates/collections-agent/agents/collections-agent/runbook.md +3 -3
  265. package/templates/collections-agent/agents/collections-agent/src/agreements.ts +1 -1
  266. package/templates/collections-agent/agents/collections-agent/src/envelope.ts +15 -13
  267. package/templates/collections-agent/agents/collections-agent/src/kit.ts +38 -35
  268. package/templates/collections-agent/agents/collections-agent/src/modules/bolepix-receivables.ts +16 -8
  269. package/templates/collections-agent/agents/collections-agent/src/strings.ts +91 -0
  270. package/templates/collections-agent/agents/collections-agent/test/ambiguous-charge.test.ts +2 -2
  271. package/templates/collections-agent/agents/collections-agent/test/check.test.ts +4 -1
  272. package/templates/collections-agent/agents/collections-agent/test/cli.test.ts +1 -1
  273. package/templates/collections-agent/agents/collections-agent/test/envelope.test.ts +2 -2
  274. package/templates/collections-agent/agents/collections-agent/test/fixtures/accept-1103.transcript.jsonl +1 -1
  275. package/templates/collections-agent/agents/collections-agent/test/fixtures/tap-emitir-nova-1042.transcript.jsonl +1 -1
  276. package/templates/collections-agent/agents/collections-agent/test/payable-instrument.test.ts +56 -0
  277. package/templates/collections-agent/agents/collections-agent/test/rerun-clock.test.ts +54 -0
  278. package/templates/collections-agent/agents/collections-agent/test/whatsapp-poll.test.ts +69 -2
  279. package/templates/collections-agent/agents/collections-agent/test/whatsapp-status-replies.test.ts +16 -3
  280. package/templates/collections-agent/agents/collections-agent/test/whatsapp.test.ts +16 -4
  281. package/templates/collections-agent/agents/collections-agent/tools.json +2 -2
  282. package/templates/collections-agent/packages/agent-core/README.md +21 -2
  283. package/templates/collections-agent/packages/agent-core/package.json +1 -1
  284. package/templates/collections-agent/packages/agent-core/src/agent.ts +33 -6
  285. package/templates/collections-agent/packages/agent-core/src/api/charge-rail.ts +15 -1
  286. package/templates/collections-agent/packages/agent-core/src/api/rail.ts +11 -5
  287. package/templates/collections-agent/packages/agent-core/src/api/sandbox-payer.ts +36 -0
  288. package/templates/collections-agent/packages/agent-core/src/bundle.ts +2 -0
  289. package/templates/collections-agent/packages/agent-core/src/channels.ts +18 -8
  290. package/templates/collections-agent/packages/agent-core/src/check.ts +25 -3
  291. package/templates/collections-agent/packages/agent-core/src/engine.ts +90 -9
  292. package/templates/collections-agent/packages/agent-core/src/escalate.ts +10 -0
  293. package/templates/collections-agent/packages/agent-core/src/index.ts +3 -0
  294. package/templates/collections-agent/packages/agent-core/src/language.ts +52 -0
  295. package/templates/collections-agent/packages/agent-core/src/locale.ts +88 -0
  296. package/templates/collections-agent/packages/agent-core/src/manifest.ts +4 -1
  297. package/templates/collections-agent/packages/agent-core/src/rail.ts +29 -1
  298. package/templates/collections-agent/packages/agent-core/src/receipt-verification.ts +30 -2
  299. package/templates/collections-agent/packages/agent-core/src/secrets.ts +53 -8
  300. package/templates/collections-agent/packages/agent-core/src/state-machine.ts +14 -0
  301. package/templates/collections-agent/packages/agent-core/src/strings.ts +175 -0
  302. package/templates/collections-agent/packages/agent-core/src/stubs/charge-rail.ts +15 -2
  303. package/templates/collections-agent/packages/agent-core/src/stubs/rail.ts +7 -4
  304. package/templates/collections-agent/packages/agent-core/src/types.ts +15 -2
  305. package/templates/collections-agent/packages/agent-core/test/actor-on-the-wire.test.ts +144 -0
  306. package/templates/collections-agent/packages/agent-core/test/attempt-replay.test.ts +2 -2
  307. package/templates/collections-agent/packages/agent-core/test/engine.test.ts +23 -0
  308. package/templates/collections-agent/packages/agent-core/test/helpers.ts +1 -1
  309. package/templates/collections-agent/packages/agent-core/test/language.test.ts +40 -0
  310. package/templates/collections-agent/packages/agent-core/test/locale.test.ts +137 -0
  311. package/templates/collections-agent/packages/agent-core/test/mandate-status.test.ts +2 -2
  312. package/templates/collections-agent/packages/agent-core/test/manifest.test.ts +2 -2
  313. package/templates/collections-agent/packages/agent-core/test/rail-errors.test.ts +74 -0
  314. package/templates/collections-agent/packages/agent-core/test/receipt-read-verification.test.ts +32 -0
  315. package/templates/collections-agent/packages/agent-core/test/receivables.test.ts +49 -0
  316. package/templates/collections-agent/packages/agent-core/test/recorded-turns.ts +29 -0
  317. package/templates/collections-agent/packages/agent-core/test/secrets.test.ts +40 -1
  318. package/templates/collections-agent/packages/agent-runtime/README.md +31 -4
  319. package/templates/collections-agent/packages/agent-runtime/src/channels/rules.ts +4 -2
  320. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +11 -5
  321. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +43 -21
  322. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +3 -0
  323. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +8 -12
  324. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -4
  325. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +12 -9
  326. package/templates/collections-agent/packages/agent-runtime/src/cli.ts +30 -4
  327. package/templates/collections-agent/packages/agent-runtime/src/commands/check.ts +18 -2
  328. package/templates/collections-agent/packages/agent-runtime/src/commands/decide.ts +13 -4
  329. package/templates/collections-agent/packages/agent-runtime/src/commands/eval.ts +7 -2
  330. package/templates/collections-agent/packages/agent-runtime/src/commands/inspect.ts +11 -13
  331. package/templates/collections-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +32 -24
  332. package/templates/collections-agent/packages/agent-runtime/src/commands/poll.ts +12 -5
  333. package/templates/collections-agent/packages/agent-runtime/src/commands/rerun.ts +83 -10
  334. package/templates/collections-agent/packages/agent-runtime/src/commands/resume.ts +2 -1
  335. package/templates/collections-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +10 -5
  336. package/templates/collections-agent/packages/agent-runtime/src/commands/start.ts +48 -17
  337. package/templates/collections-agent/packages/agent-runtime/src/commands/verify.ts +37 -12
  338. package/templates/collections-agent/packages/agent-runtime/src/commands/webhook.ts +11 -3
  339. package/templates/collections-agent/packages/agent-runtime/src/default-kit.ts +52 -22
  340. package/templates/collections-agent/packages/agent-runtime/src/env.ts +64 -0
  341. package/templates/collections-agent/packages/agent-runtime/src/index.ts +2 -0
  342. package/templates/collections-agent/packages/agent-runtime/src/inspect.ts +81 -10
  343. package/templates/collections-agent/packages/agent-runtime/src/kit.ts +34 -12
  344. package/templates/collections-agent/packages/agent-runtime/src/outcome.ts +118 -0
  345. package/templates/collections-agent/packages/agent-runtime/src/poll.ts +7 -7
  346. package/templates/collections-agent/packages/agent-runtime/src/runs.ts +51 -0
  347. package/templates/collections-agent/packages/agent-runtime/src/scenarios.ts +55 -8
  348. package/templates/collections-agent/packages/agent-runtime/src/setup.ts +75 -5
  349. package/templates/collections-agent/packages/agent-runtime/src/terminal.ts +71 -33
  350. package/templates/collections-agent/packages/agent-runtime/test/env-names.test.ts +56 -0
  351. package/templates/collections-agent/packages/agent-runtime/test/inspect-mandate-status.test.ts +80 -0
  352. package/templates/collections-agent/packages/agent-runtime/test/inspect.test.ts +63 -2
  353. package/templates/collections-agent/packages/agent-runtime/test/outcome.test.ts +72 -0
  354. package/templates/collections-agent/packages/agent-runtime/test/poll-payer.test.ts +64 -0
  355. package/templates/collections-agent/packages/agent-runtime/test/rerun-not-replayed.test.ts +46 -0
  356. package/templates/collections-agent/packages/agent-runtime/test/transition-line.test.ts +29 -0
  357. package/templates/collections-agent/packages/agent-runtime/test/verify-cli.test.ts +99 -6
  358. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +8 -0
  359. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-session.test.ts +77 -0
  360. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +27 -1
  361. package/templates/hello-agent/README.md +2 -2
  362. package/templates/hello-agent/agents/hello-agent/README.md +6 -0
  363. package/templates/hello-agent/agents/hello-agent/SYSTEM_PROMPT.md +27 -13
  364. package/templates/hello-agent/agents/hello-agent/agent.yaml +2 -1
  365. package/templates/hello-agent/agents/hello-agent/evals/adversarial/exfiltration.transcript.jsonl +1 -1
  366. package/templates/hello-agent/agents/hello-agent/evals/adversarial/prompt-injection.transcript.jsonl +1 -1
  367. package/templates/hello-agent/agents/hello-agent/mandate.example.json +1 -1
  368. package/templates/hello-agent/agents/hello-agent/scenarios/happy-path.json +1 -1
  369. package/templates/hello-agent/agents/hello-agent/scenarios/happy-path.transcript.jsonl +1 -1
  370. package/templates/hello-agent/agents/hello-agent/scenarios/prompt-injection.json +1 -1
  371. package/templates/hello-agent/agents/hello-agent/scenarios/prompt-injection.transcript.jsonl +1 -1
  372. package/templates/hello-agent/agents/hello-agent/src/bills.ts +9 -5
  373. package/templates/hello-agent/agents/hello-agent/src/kit.ts +4 -1
  374. package/templates/hello-agent/agents/hello-agent/tools.json +1 -1
  375. package/templates/hello-agent/packages/agent-core/README.md +21 -2
  376. package/templates/hello-agent/packages/agent-core/package.json +1 -1
  377. package/templates/hello-agent/packages/agent-core/src/agent.ts +33 -6
  378. package/templates/hello-agent/packages/agent-core/src/api/charge-rail.ts +15 -1
  379. package/templates/hello-agent/packages/agent-core/src/api/rail.ts +11 -5
  380. package/templates/hello-agent/packages/agent-core/src/api/sandbox-payer.ts +36 -0
  381. package/templates/hello-agent/packages/agent-core/src/bundle.ts +2 -0
  382. package/templates/hello-agent/packages/agent-core/src/channels.ts +18 -8
  383. package/templates/hello-agent/packages/agent-core/src/check.ts +25 -3
  384. package/templates/hello-agent/packages/agent-core/src/engine.ts +90 -9
  385. package/templates/hello-agent/packages/agent-core/src/escalate.ts +10 -0
  386. package/templates/hello-agent/packages/agent-core/src/index.ts +3 -0
  387. package/templates/hello-agent/packages/agent-core/src/language.ts +52 -0
  388. package/templates/hello-agent/packages/agent-core/src/locale.ts +88 -0
  389. package/templates/hello-agent/packages/agent-core/src/manifest.ts +4 -1
  390. package/templates/hello-agent/packages/agent-core/src/rail.ts +29 -1
  391. package/templates/hello-agent/packages/agent-core/src/receipt-verification.ts +30 -2
  392. package/templates/hello-agent/packages/agent-core/src/secrets.ts +53 -8
  393. package/templates/hello-agent/packages/agent-core/src/state-machine.ts +14 -0
  394. package/templates/hello-agent/packages/agent-core/src/strings.ts +175 -0
  395. package/templates/hello-agent/packages/agent-core/src/stubs/charge-rail.ts +15 -2
  396. package/templates/hello-agent/packages/agent-core/src/stubs/rail.ts +7 -4
  397. package/templates/hello-agent/packages/agent-core/src/types.ts +15 -2
  398. package/templates/hello-agent/packages/agent-core/test/actor-on-the-wire.test.ts +144 -0
  399. package/templates/hello-agent/packages/agent-core/test/attempt-replay.test.ts +2 -2
  400. package/templates/hello-agent/packages/agent-core/test/engine.test.ts +23 -0
  401. package/templates/hello-agent/packages/agent-core/test/helpers.ts +1 -1
  402. package/templates/hello-agent/packages/agent-core/test/language.test.ts +40 -0
  403. package/templates/hello-agent/packages/agent-core/test/locale.test.ts +137 -0
  404. package/templates/hello-agent/packages/agent-core/test/mandate-status.test.ts +2 -2
  405. package/templates/hello-agent/packages/agent-core/test/manifest.test.ts +2 -2
  406. package/templates/hello-agent/packages/agent-core/test/rail-errors.test.ts +74 -0
  407. package/templates/hello-agent/packages/agent-core/test/receipt-read-verification.test.ts +32 -0
  408. package/templates/hello-agent/packages/agent-core/test/receivables.test.ts +49 -0
  409. package/templates/hello-agent/packages/agent-core/test/recorded-turns.ts +29 -0
  410. package/templates/hello-agent/packages/agent-core/test/secrets.test.ts +40 -1
  411. package/templates/hello-agent/packages/agent-runtime/README.md +31 -4
  412. package/templates/hello-agent/packages/agent-runtime/src/channels/rules.ts +4 -2
  413. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +11 -5
  414. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +43 -21
  415. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +3 -0
  416. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +8 -12
  417. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -4
  418. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +12 -9
  419. package/templates/hello-agent/packages/agent-runtime/src/cli.ts +30 -4
  420. package/templates/hello-agent/packages/agent-runtime/src/commands/check.ts +18 -2
  421. package/templates/hello-agent/packages/agent-runtime/src/commands/decide.ts +13 -4
  422. package/templates/hello-agent/packages/agent-runtime/src/commands/eval.ts +7 -2
  423. package/templates/hello-agent/packages/agent-runtime/src/commands/inspect.ts +11 -13
  424. package/templates/hello-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +32 -24
  425. package/templates/hello-agent/packages/agent-runtime/src/commands/poll.ts +12 -5
  426. package/templates/hello-agent/packages/agent-runtime/src/commands/rerun.ts +83 -10
  427. package/templates/hello-agent/packages/agent-runtime/src/commands/resume.ts +2 -1
  428. package/templates/hello-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +10 -5
  429. package/templates/hello-agent/packages/agent-runtime/src/commands/start.ts +48 -17
  430. package/templates/hello-agent/packages/agent-runtime/src/commands/verify.ts +37 -12
  431. package/templates/hello-agent/packages/agent-runtime/src/commands/webhook.ts +11 -3
  432. package/templates/hello-agent/packages/agent-runtime/src/default-kit.ts +52 -22
  433. package/templates/hello-agent/packages/agent-runtime/src/env.ts +64 -0
  434. package/templates/hello-agent/packages/agent-runtime/src/index.ts +2 -0
  435. package/templates/hello-agent/packages/agent-runtime/src/inspect.ts +81 -10
  436. package/templates/hello-agent/packages/agent-runtime/src/kit.ts +34 -12
  437. package/templates/hello-agent/packages/agent-runtime/src/outcome.ts +118 -0
  438. package/templates/hello-agent/packages/agent-runtime/src/poll.ts +7 -7
  439. package/templates/hello-agent/packages/agent-runtime/src/runs.ts +51 -0
  440. package/templates/hello-agent/packages/agent-runtime/src/scenarios.ts +55 -8
  441. package/templates/hello-agent/packages/agent-runtime/src/setup.ts +75 -5
  442. package/templates/hello-agent/packages/agent-runtime/src/terminal.ts +71 -33
  443. package/templates/hello-agent/packages/agent-runtime/test/env-names.test.ts +56 -0
  444. package/templates/hello-agent/packages/agent-runtime/test/inspect-mandate-status.test.ts +80 -0
  445. package/templates/hello-agent/packages/agent-runtime/test/inspect.test.ts +63 -2
  446. package/templates/hello-agent/packages/agent-runtime/test/outcome.test.ts +72 -0
  447. package/templates/hello-agent/packages/agent-runtime/test/poll-payer.test.ts +64 -0
  448. package/templates/hello-agent/packages/agent-runtime/test/rerun-not-replayed.test.ts +46 -0
  449. package/templates/hello-agent/packages/agent-runtime/test/transition-line.test.ts +29 -0
  450. package/templates/hello-agent/packages/agent-runtime/test/verify-cli.test.ts +99 -6
  451. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +8 -0
  452. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-session.test.ts +77 -0
  453. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +27 -1
  454. package/templates/kits.lock.json +12 -12
  455. package/templates/supplier-payments-agent/README.md +2 -2
  456. package/templates/supplier-payments-agent/agents/supplier-payments-agent/.env.example +2 -2
  457. package/templates/supplier-payments-agent/agents/supplier-payments-agent/README.md +12 -7
  458. package/templates/supplier-payments-agent/agents/supplier-payments-agent/SYSTEM_PROMPT.md +14 -3
  459. package/templates/supplier-payments-agent/agents/supplier-payments-agent/agent.yaml +2 -1
  460. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/exfiltration.transcript.jsonl +1 -1
  461. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/false-authority.transcript.jsonl +1 -1
  462. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/prompt-injection.transcript.jsonl +1 -1
  463. package/templates/supplier-payments-agent/agents/supplier-payments-agent/mandate.example.json +3 -3
  464. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/beneficiary-not-allowed.transcript.jsonl +1 -1
  465. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/cap-exceeded.transcript.jsonl +1 -1
  466. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/escalated-above-threshold.transcript.jsonl +5 -5
  467. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/happy-path.transcript.jsonl +1 -1
  468. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/mandate-revoked.transcript.jsonl +5 -5
  469. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/partial-batch-failure.json +1 -1
  470. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/partial-batch-failure.transcript.jsonl +1 -1
  471. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/prompt-injection.transcript.jsonl +1 -1
  472. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/kit.ts +37 -26
  473. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/modules/batch-payout.ts +41 -14
  474. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/modules/pix-out.ts +12 -3
  475. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/payables.ts +8 -8
  476. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/batch.test.ts +75 -10
  477. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/locale.test.ts +101 -0
  478. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/run-outcome.test.ts +127 -0
  479. package/templates/supplier-payments-agent/agents/supplier-payments-agent/tools.json +1 -1
  480. package/templates/supplier-payments-agent/packages/agent-core/README.md +21 -2
  481. package/templates/supplier-payments-agent/packages/agent-core/package.json +1 -1
  482. package/templates/supplier-payments-agent/packages/agent-core/src/agent.ts +33 -6
  483. package/templates/supplier-payments-agent/packages/agent-core/src/api/charge-rail.ts +15 -1
  484. package/templates/supplier-payments-agent/packages/agent-core/src/api/rail.ts +11 -5
  485. package/templates/supplier-payments-agent/packages/agent-core/src/api/sandbox-payer.ts +36 -0
  486. package/templates/supplier-payments-agent/packages/agent-core/src/bundle.ts +2 -0
  487. package/templates/supplier-payments-agent/packages/agent-core/src/channels.ts +18 -8
  488. package/templates/supplier-payments-agent/packages/agent-core/src/check.ts +25 -3
  489. package/templates/supplier-payments-agent/packages/agent-core/src/engine.ts +90 -9
  490. package/templates/supplier-payments-agent/packages/agent-core/src/escalate.ts +10 -0
  491. package/templates/supplier-payments-agent/packages/agent-core/src/index.ts +3 -0
  492. package/templates/supplier-payments-agent/packages/agent-core/src/language.ts +52 -0
  493. package/templates/supplier-payments-agent/packages/agent-core/src/locale.ts +88 -0
  494. package/templates/supplier-payments-agent/packages/agent-core/src/manifest.ts +4 -1
  495. package/templates/supplier-payments-agent/packages/agent-core/src/rail.ts +29 -1
  496. package/templates/supplier-payments-agent/packages/agent-core/src/receipt-verification.ts +30 -2
  497. package/templates/supplier-payments-agent/packages/agent-core/src/secrets.ts +53 -8
  498. package/templates/supplier-payments-agent/packages/agent-core/src/state-machine.ts +14 -0
  499. package/templates/supplier-payments-agent/packages/agent-core/src/strings.ts +175 -0
  500. package/templates/supplier-payments-agent/packages/agent-core/src/stubs/charge-rail.ts +15 -2
  501. package/templates/supplier-payments-agent/packages/agent-core/src/stubs/rail.ts +7 -4
  502. package/templates/supplier-payments-agent/packages/agent-core/src/types.ts +15 -2
  503. package/templates/supplier-payments-agent/packages/agent-core/test/actor-on-the-wire.test.ts +144 -0
  504. package/templates/supplier-payments-agent/packages/agent-core/test/attempt-replay.test.ts +2 -2
  505. package/templates/supplier-payments-agent/packages/agent-core/test/engine.test.ts +23 -0
  506. package/templates/supplier-payments-agent/packages/agent-core/test/helpers.ts +1 -1
  507. package/templates/supplier-payments-agent/packages/agent-core/test/language.test.ts +40 -0
  508. package/templates/supplier-payments-agent/packages/agent-core/test/locale.test.ts +137 -0
  509. package/templates/supplier-payments-agent/packages/agent-core/test/mandate-status.test.ts +2 -2
  510. package/templates/supplier-payments-agent/packages/agent-core/test/manifest.test.ts +2 -2
  511. package/templates/supplier-payments-agent/packages/agent-core/test/rail-errors.test.ts +74 -0
  512. package/templates/supplier-payments-agent/packages/agent-core/test/receipt-read-verification.test.ts +32 -0
  513. package/templates/supplier-payments-agent/packages/agent-core/test/receivables.test.ts +49 -0
  514. package/templates/supplier-payments-agent/packages/agent-core/test/recorded-turns.ts +29 -0
  515. package/templates/supplier-payments-agent/packages/agent-core/test/secrets.test.ts +40 -1
  516. package/templates/supplier-payments-agent/packages/agent-runtime/README.md +31 -4
  517. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/rules.ts +4 -2
  518. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +11 -5
  519. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +43 -21
  520. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +3 -0
  521. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +8 -12
  522. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -4
  523. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +12 -9
  524. package/templates/supplier-payments-agent/packages/agent-runtime/src/cli.ts +30 -4
  525. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/check.ts +18 -2
  526. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/decide.ts +13 -4
  527. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/eval.ts +7 -2
  528. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/inspect.ts +11 -13
  529. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +32 -24
  530. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/poll.ts +12 -5
  531. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/rerun.ts +83 -10
  532. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/resume.ts +2 -1
  533. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +10 -5
  534. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/start.ts +48 -17
  535. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/verify.ts +37 -12
  536. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/webhook.ts +11 -3
  537. package/templates/supplier-payments-agent/packages/agent-runtime/src/default-kit.ts +52 -22
  538. package/templates/supplier-payments-agent/packages/agent-runtime/src/env.ts +64 -0
  539. package/templates/supplier-payments-agent/packages/agent-runtime/src/index.ts +2 -0
  540. package/templates/supplier-payments-agent/packages/agent-runtime/src/inspect.ts +81 -10
  541. package/templates/supplier-payments-agent/packages/agent-runtime/src/kit.ts +34 -12
  542. package/templates/supplier-payments-agent/packages/agent-runtime/src/outcome.ts +118 -0
  543. package/templates/supplier-payments-agent/packages/agent-runtime/src/poll.ts +7 -7
  544. package/templates/supplier-payments-agent/packages/agent-runtime/src/runs.ts +51 -0
  545. package/templates/supplier-payments-agent/packages/agent-runtime/src/scenarios.ts +55 -8
  546. package/templates/supplier-payments-agent/packages/agent-runtime/src/setup.ts +75 -5
  547. package/templates/supplier-payments-agent/packages/agent-runtime/src/terminal.ts +71 -33
  548. package/templates/supplier-payments-agent/packages/agent-runtime/test/env-names.test.ts +56 -0
  549. package/templates/supplier-payments-agent/packages/agent-runtime/test/inspect-mandate-status.test.ts +80 -0
  550. package/templates/supplier-payments-agent/packages/agent-runtime/test/inspect.test.ts +63 -2
  551. package/templates/supplier-payments-agent/packages/agent-runtime/test/outcome.test.ts +72 -0
  552. package/templates/supplier-payments-agent/packages/agent-runtime/test/poll-payer.test.ts +64 -0
  553. package/templates/supplier-payments-agent/packages/agent-runtime/test/rerun-not-replayed.test.ts +46 -0
  554. package/templates/supplier-payments-agent/packages/agent-runtime/test/transition-line.test.ts +29 -0
  555. package/templates/supplier-payments-agent/packages/agent-runtime/test/verify-cli.test.ts +99 -6
  556. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +8 -0
  557. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-session.test.ts +77 -0
  558. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +27 -1
@@ -0,0 +1,25 @@
1
+ /**
2
+ * The consent is what a person reads before signing a mandate, so its caps
3
+ * are money as a person writes it, not the minor units the API takes.
4
+ */
5
+ import { describe, expect, it } from "vitest";
6
+ import { STRINGS } from "../src/strings.js";
7
+
8
+ describe("the consent summary says its amounts in reais", () => {
9
+ it("the three caps, in pt-BR and in English", () => {
10
+ expect(STRINGS["pt-BR"].consentCaps(250000, 600000, 7200000)).toBe(" teto por pagamento: R$ 2.500,00 teto do mês: R$ 6.000,00 vitalício: R$ 72.000,00");
11
+ expect(STRINGS.en.consentCaps(250000, 600000, 7200000)).toBe(" cap per payment: R$2,500.00 cap per month: R$6,000.00 lifetime: R$72,000.00");
12
+ });
13
+
14
+ it("the sandbox credit too", () => {
15
+ expect(STRINGS["pt-BR"].consentFunded(600000, "acc_1", "dep_1")).toBe("Sandbox creditado: R$ 6.000,00 em acc_1 (deposit dep_1).");
16
+ expect(STRINGS.en.consentFunded(600000, "acc_1", "dep_1")).toBe("Sandbox credited: R$6,000.00 to acc_1 (deposit dep_1).");
17
+ });
18
+
19
+ it("no line of the consent counts in cents", () => {
20
+ for (const locale of ["pt-BR", "en"] as const) {
21
+ const lines = [STRINGS[locale].consentCaps(250000, 600000, 7200000), STRINGS[locale].consentFunded(600000, "acc_1", "dep_1")];
22
+ for (const line of lines) expect(line).not.toMatch(/centavos|cents|250000|600000|7200000/);
23
+ }
24
+ });
25
+ });
@@ -0,0 +1,98 @@
1
+ /**
2
+ * What the first real-model runs showed (docs/OPEN_QUESTIONS.md §64): with no
3
+ * date of its own, the model called a bill due next week "venceu dia 05"; told
4
+ * both approval modes exist and not which one ran, it said a payment the
5
+ * titular approved needed "no extra approval". The tools now carry both facts.
6
+ */
7
+ import { mkdtempSync } from "node:fs";
8
+ import { tmpdir } from "node:os";
9
+ import { join } from "node:path";
10
+ import { describe, expect, it } from "vitest";
11
+ import { daysUntil, fixedClock, localDate, type Execution, type ToolContext } from "@codespar/agent-core";
12
+ import { setup, type Setup } from "@codespar/agent-runtime";
13
+ import { agent } from "../src/kit.js";
14
+ import { codesparPay, listBills } from "../src/modules/pix-out.js";
15
+
16
+ function open(mode: "human" | "mandate", now: string): Setup {
17
+ return setup(agent, {
18
+ mode,
19
+ rail: "stub",
20
+ provider: "replay",
21
+ runsDir: mkdtempSync(join(tmpdir(), "bills-dates-runs-")),
22
+ stateDir: mkdtempSync(join(tmpdir(), "bills-dates-state-")),
23
+ now: fixedClock(now),
24
+ say: () => undefined,
25
+ });
26
+ }
27
+
28
+ function context(s: Setup, decide: boolean): ToolContext {
29
+ return {
30
+ engine: s.engine,
31
+ onExecution: async (execution: Execution) => {
32
+ let current = execution;
33
+ if (decide && current.state === "awaiting_approval") current = s.engine.approve(current.id, { id: "usr_demo", channel: "terminal" });
34
+ if (current.state === "approved") current = await s.engine.execute(current.id);
35
+ return current;
36
+ },
37
+ };
38
+ }
39
+
40
+ describe("the calendar the model reads", () => {
41
+ it("localDate is the day in the timezone, not in UTC", () => {
42
+ // 23:30 in Sao Paulo on the 28th is already the 29th in UTC.
43
+ expect(localDate(new Date("2026-09-29T02:30:00Z"), "America/Sao_Paulo")).toBe("2026-09-28");
44
+ expect(localDate(new Date("2026-09-29T02:30:00Z"), "UTC")).toBe("2026-09-29");
45
+ });
46
+
47
+ it("daysUntil counts whole days, negative once past", () => {
48
+ expect(daysUntil("2026-09-28", "2026-10-05")).toBe(7);
49
+ expect(daysUntil("2026-10-05", "2026-10-05")).toBe(0);
50
+ expect(daysUntil("2026-10-06", "2026-10-05")).toBe(-1);
51
+ });
52
+
53
+ it("list_bills carries today, from the pinned clock, and days_until_due per bill", async () => {
54
+ const s = open("human", "2026-09-28T14:00:00-03:00");
55
+ try {
56
+ const out = (await listBills({}, context(s, false))) as { today: string; bills: Array<{ alias: string; due: string; days_until_due: number }> };
57
+ expect(out.today).toBe("2026-09-28");
58
+ const mercado = out.bills.find((b) => b.alias === "mercado")!;
59
+ expect(mercado.due).toBe("2026-10-05");
60
+ expect(mercado.days_until_due).toBe(7);
61
+ } finally {
62
+ s.close();
63
+ }
64
+ });
65
+ });
66
+
67
+ describe("codespar_pay says who approved, so the model does not guess", () => {
68
+ const PIX = { action: "pix", items: [{ payee: "mercado", amount_minor: 64000 }] };
69
+
70
+ it("a person's approval is `human`", async () => {
71
+ const s = open("human", "2026-09-28T14:00:00-03:00");
72
+ try {
73
+ expect(await codesparPay(PIX, context(s, true))).toMatchObject({ status: "settled", approved_by: "human" });
74
+ } finally {
75
+ s.close();
76
+ }
77
+ });
78
+
79
+ it("nobody has approved an execution still waiting: `null`", async () => {
80
+ const s = open("human", "2026-09-28T14:00:00-03:00");
81
+ try {
82
+ expect(await codesparPay(PIX, context(s, false))).toMatchObject({ status: "awaiting_approval", approved_by: null });
83
+ } finally {
84
+ s.close();
85
+ }
86
+ });
87
+
88
+ it("the signed allowance's approval is `mandate`", async () => {
89
+ const s = open("mandate", "2026-09-28T14:00:00-03:00");
90
+ try {
91
+ // Warm the payee so `new_beneficiary` does not send it to a person.
92
+ await s.kit.warmUp!(s, ["mercado"], { id: "usr_demo", channel: "terminal" });
93
+ expect(await codesparPay(PIX, context(s, false))).toMatchObject({ status: "settled", approved_by: "mandate" });
94
+ } finally {
95
+ s.close();
96
+ }
97
+ });
98
+ });
@@ -0,0 +1,81 @@
1
+ /**
2
+ * `npm run eval` writes a proof bundle per case and per scenario run, dozens a
3
+ * pass. They go to `runs/eval/`, so `runs/` holds what the person ran, and
4
+ * `inspect` and `rerun` still find an eval run by its id.
5
+ */
6
+ import { spawnSync } from "node:child_process";
7
+ import { mkdtempSync, readdirSync } from "node:fs";
8
+ import { tmpdir } from "node:os";
9
+ import { join, resolve } from "node:path";
10
+ import { beforeAll, describe, expect, it } from "vitest";
11
+
12
+ const AGENT_DIR = resolve(import.meta.dirname, "..");
13
+ const BIN = resolve(AGENT_DIR, "../../packages/agent-runtime/bin.mjs");
14
+
15
+ describe("npm run eval beside a person's own runs", () => {
16
+ const stateDir = mkdtempSync(join(tmpdir(), "bills-eval-runs-"));
17
+ const runsDir = join(stateDir, "runs");
18
+ const run = (command: string, args: string[]) => {
19
+ const result = spawnSync(process.execPath, [BIN, command, ...args], {
20
+ cwd: AGENT_DIR,
21
+ env: { ...process.env, ANTHROPIC_API_KEY: "", CODESPAR_API_KEY: "", BILLS_STATE_DIR: stateDir, BILLS_RUNS_DIR: runsDir },
22
+ encoding: "utf8",
23
+ timeout: 120_000,
24
+ });
25
+ return { code: result.status, stdout: result.stdout, stderr: result.stderr };
26
+ };
27
+ let mine = "";
28
+ let evalRuns: string[] = [];
29
+
30
+ beforeAll(() => {
31
+ const own = run("start", ["--input", "pague a escola de outubro", "--approve", "--json"]);
32
+ mine = (JSON.parse(own.stdout.trim()) as { run_id: string }).run_id;
33
+ expect(run("eval", []).code).toBe(0);
34
+ evalRuns = readdirSync(join(runsDir, "eval")).sort();
35
+ }, 120_000);
36
+
37
+ it("leaves runs/ with the person's run and one folder for the suite's", () => {
38
+ expect(readdirSync(runsDir).sort()).toEqual(["eval", mine].sort());
39
+ // 8 adversarial cases and 11 scenario runs.
40
+ expect(evalRuns).toHaveLength(19);
41
+ expect(evalRuns.some((id) => id.startsWith("run_adv_"))).toBe(true);
42
+ });
43
+
44
+ it("inspect finds an eval run by its id alone, and by eval/<id>", () => {
45
+ const id = evalRuns.find((r) => r.startsWith("run_adv_prompt-injection"))!;
46
+ for (const arg of [id, `eval/${id}`]) {
47
+ const out = run("inspect", [arg, "--json"]);
48
+ expect(out.code).toBe(0);
49
+ expect((JSON.parse(out.stdout.trim()) as { run: { run_id: string } }).run.run_id).toBe(id);
50
+ }
51
+ expect(run("inspect", [mine, "--json"]).code).toBe(0);
52
+ });
53
+
54
+ it("an unknown id lists the person's runs and counts the suite's, without listing them", () => {
55
+ const out = run("inspect", ["run_nope"]);
56
+ expect(out.code).toBe(1);
57
+ expect(out.stderr).toContain(` ${mine}`);
58
+ expect(out.stderr).toContain(`19 more from \`npm run eval\` in ${join(runsDir, "eval")}`);
59
+ expect(out.stderr).not.toContain("run_adv_");
60
+ expect(out.stderr).not.toMatch(/^ {2}eval$/m);
61
+ });
62
+
63
+ it("the folder itself is not a run, and a path out of runs/ is not one either", () => {
64
+ for (const arg of ["eval", "eval/", "eval/../..", "../runs"]) {
65
+ const out = run("inspect", [arg]);
66
+ expect([arg, out.code]).toEqual([arg, 1]);
67
+ expect(out.stderr).toContain(`no proof bundle for run ${arg}`);
68
+ expect(out.stderr).not.toMatch(/^\s+at /m);
69
+ }
70
+ });
71
+
72
+ it("rerun replays an eval run by its id and leaves the rerun beside it, not among the person's", () => {
73
+ const id = evalRuns.find((r) => r.startsWith("run_adv_prompt-injection"))!;
74
+ const out = run("rerun", [id, "--json"]);
75
+ expect(out.code).toBe(0);
76
+ const report = JSON.parse(out.stdout.trim()) as { same_states: boolean; rerun_id: string };
77
+ expect(report.same_states).toBe(true);
78
+ expect(readdirSync(join(runsDir, "eval"))).toContain(report.rerun_id);
79
+ expect(readdirSync(runsDir).sort()).toEqual(["eval", mine].sort());
80
+ });
81
+ });
@@ -1,2 +1,2 @@
1
- {"kind":"assistant_step","tool_calls":[{"id":"tc_4","name":"codespar_pay","input":{"action":"pix","items":[{"payee":"escola","amount_minor":30000,"description":"excursao"}]}}]}
2
- {"kind":"assistant_step","reply":"Paguei R$ 300,00 para a Escola Aurora (excursao) dentro da alcada; o recibo esta no terminal."}
1
+ {"kind":"assistant_step","tool_calls":[{"id":"tc_4","name":"codespar_pay","input":{"action":"pix","items":[{"payee":"escola","amount_minor":30000,"description":"excursão"}]}}]}
2
+ {"kind":"assistant_step","reply":"Propus R$ 300,00 para a Escola Aurora (excursão). O resultado está no terminal."}
@@ -1,2 +1,2 @@
1
1
  {"kind":"assistant_step","tool_calls":[{"id":"tc_1","name":"codespar_pay","input":{"action":"pix","items":[{"payee":"escola","amount_minor":40000,"description":"material"}]}}]}
2
- {"kind":"assistant_step","reply":"Propus R$ 400,00 para a Escola Aurora (material). Como e o primeiro pagamento a esse favorecido, o mandato pediu sua aprovacao."}
2
+ {"kind":"assistant_step","reply":"Propus R$ 400,00 para a Escola Aurora (material). Como é o primeiro pagamento a esse favorecido, o mandato pediu sua aprovação."}
@@ -0,0 +1,161 @@
1
+ /**
2
+ * #64 on the approval path: the locale changes what the titular READS and
3
+ * nothing about what their answer DECIDES. The same answer to the pt-BR
4
+ * question and to the English one ends in the same state, and the approval
5
+ * artifact names the same approver.
6
+ *
7
+ * And the resolution, end to end: `--locale` beats `agent.yaml`, which beats
8
+ * the default, and the run's bundle records the locale it ran in.
9
+ */
10
+ import { spawnSync } from "node:child_process";
11
+ import { cpSync, mkdtempSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
12
+ import { tmpdir } from "node:os";
13
+ import { join, resolve } from "node:path";
14
+ import { describe, expect, it } from "vitest";
15
+ import { fixedClock, type Locale } from "@codespar/agent-core";
16
+ import { handleExecution, parseApproval, setup, type Setup } from "@codespar/agent-runtime";
17
+ import { agent } from "../src/kit.js";
18
+
19
+ const AGENT_DIR = resolve(import.meta.dirname, "..");
20
+ const NODE = process.execPath;
21
+ const BIN = resolve(AGENT_DIR, "../../packages/agent-runtime/bin.mjs");
22
+ const APPROVER = { id: "usr_demo_titular", channel: "terminal" };
23
+ /** Every answer the `[s/N]` parser has a rule for, both languages, plus what falls through to no. */
24
+ const ANSWERS = ["s", "sim", "y", "yes", " SIM ", "Yes", "n", "nao", "não", "no", "", "talvez", "si"];
25
+
26
+ function open(locale: Locale | undefined, dir = AGENT_DIR): Setup {
27
+ return setup(dir === AGENT_DIR ? agent : { ...agent, dir }, {
28
+ mode: "human",
29
+ rail: "stub",
30
+ provider: "replay",
31
+ runsDir: mkdtempSync(join(tmpdir(), "bills-locale-runs-")),
32
+ stateDir: mkdtempSync(join(tmpdir(), "bills-locale-state-")),
33
+ now: fixedClock("2026-09-23T14:00:00-03:00"),
34
+ say: () => undefined,
35
+ ...(locale ? { locale } : {}),
36
+ });
37
+ }
38
+
39
+ /** Proposes one payment and answers the approval question with `answer`; returns the final state, the question asked and the console. */
40
+ async function decideOnce(locale: Locale, answer: string) {
41
+ const s = open(locale);
42
+ const asked: string[] = [];
43
+ const said: string[] = [];
44
+ try {
45
+ const draft = await s.engine.draft({ items: [{ payee: "escola", amount: 185000, description: "mensalidade de outubro" }] });
46
+ if (!draft.ok) throw new Error(draft.reason);
47
+ const final = await handleExecution(draft.execution, {
48
+ setup: s,
49
+ approver: APPROVER,
50
+ ask: async (q) => {
51
+ asked.push(q);
52
+ return answer;
53
+ },
54
+ say: (l) => void said.push(l),
55
+ });
56
+ const approvers = s.bundle.readApprovals().map((a) => a.approver);
57
+ return { state: final.state, asked, said, approvers };
58
+ } finally {
59
+ s.close();
60
+ }
61
+ }
62
+
63
+ describe("the approval question decides the same in both locales", () => {
64
+ it.each(ANSWERS)("answer %j", async (answer) => {
65
+ const pt = await decideOnce("pt-BR", answer);
66
+ const en = await decideOnce("en", answer);
67
+ // What was shown differs...
68
+ expect(pt.asked).toEqual([" Aprovar este pagamento? [s/N] "]);
69
+ expect(en.asked).toEqual([" Approve this payment? [y/N] "]);
70
+ // ...and what was decided does not.
71
+ expect(en.state).toBe(pt.state);
72
+ expect(en.approvers).toEqual(pt.approvers);
73
+ expect(pt.state).toBe(parseApproval(answer) === "approve" ? "settled" : "denied");
74
+ });
75
+
76
+ it("prints the execution in the run's locale, accents included", async () => {
77
+ const pt = await decideOnce("pt-BR", "s");
78
+ const en = await decideOnce("en", "y");
79
+ expect(pt.said.join("\n")).toContain("execução exe_");
80
+ expect(pt.said.join("\n")).toContain("total (calculado pelo core): R$ 1.850,00");
81
+ expect(pt.said.join("\n")).toMatch(/recibo: /);
82
+ expect(en.said.join("\n")).toContain("execution exe_");
83
+ expect(en.said.join("\n")).toContain("total (computed by the core): R$1,850.00");
84
+ expect(en.said.join("\n")).toMatch(/receipt: /);
85
+ });
86
+ });
87
+
88
+ describe("which locale a run speaks", () => {
89
+ function copyWithLocale(locale: string | undefined): string {
90
+ const dir = mkdtempSync(join(tmpdir(), "bills-locale-agent-"));
91
+ cpSync(AGENT_DIR, dir, { recursive: true, filter: (src) => !/node_modules|\/runs|\.codespar/.test(src) });
92
+ const yaml = readFileSync(join(dir, "agent.yaml"), "utf8").replace(/^locale:.*\n/m, locale ? `locale: ${locale}\n` : "");
93
+ writeFileSync(join(dir, "agent.yaml"), yaml);
94
+ return dir;
95
+ }
96
+
97
+ it("is --locale, else agent.yaml's locale, else pt-BR; and the bundle records it", () => {
98
+ const cases: Array<[string | undefined, Locale | undefined, Locale]> = [
99
+ [undefined, undefined, "pt-BR"],
100
+ ["en", undefined, "en"],
101
+ ["en", "pt-BR", "pt-BR"],
102
+ ["pt-BR", "en", "en"],
103
+ ];
104
+ for (const [manifest, flag, expected] of cases) {
105
+ const s = open(flag, copyWithLocale(manifest));
106
+ try {
107
+ expect(s.locale).toBe(expected);
108
+ expect(s.bundle.readMeta()?.["locale"]).toBe(expected);
109
+ expect(s.strings).toBe(agent.kit.strings[expected]);
110
+ } finally {
111
+ s.close();
112
+ }
113
+ }
114
+ });
115
+
116
+ function run(args: string[]) {
117
+ const stateDir = mkdtempSync(join(tmpdir(), "bills-locale-cli-"));
118
+ const result = spawnSync(NODE, [BIN, "start", ...args], {
119
+ cwd: AGENT_DIR,
120
+ env: { ...process.env, ANTHROPIC_API_KEY: "", CODESPAR_API_KEY: "", BILLS_STATE_DIR: stateDir, BILLS_RUNS_DIR: join(stateDir, "runs") },
121
+ encoding: "utf8",
122
+ timeout: 60_000,
123
+ });
124
+ const runs = join(stateDir, "runs");
125
+ let meta: Record<string, unknown> | undefined;
126
+ try {
127
+ const [dir] = readdirSync(runs);
128
+ meta = JSON.parse(readFileSync(join(runs, dir!, "run.json"), "utf8")) as Record<string, unknown>;
129
+ } catch {
130
+ meta = undefined;
131
+ }
132
+ return { code: result.status, stdout: result.stdout, stderr: result.stderr, meta };
133
+ }
134
+
135
+ it("`npm start -- --locale en` prints the code's lines in English and pays the same", () => {
136
+ const pt = run(["--input", "pague a escola de outubro", "--approve", "--json"]);
137
+ const en = run(["--input", "pague a escola de outubro", "--approve", "--json", "--locale", "en"]);
138
+ expect(pt.code).toBe(0);
139
+ expect(en.code).toBe(0);
140
+ expect(pt.stderr).toContain("execução");
141
+ expect(pt.stderr).toContain("calculado pelo core");
142
+ expect(en.stderr).toContain("execution");
143
+ expect(en.stderr).toContain("computed by the core");
144
+ expect(en.stderr).not.toContain("execução");
145
+ expect(pt.meta?.["locale"]).toBe("pt-BR");
146
+ expect(en.meta?.["locale"]).toBe("en");
147
+ // The machine output is the same contract in both: same states, same receipts, no locale-dependent field.
148
+ const shape = (o: string) => {
149
+ const p = JSON.parse(o) as { executions: Array<{ state: string; total_minor: number; receipt_ids: string[] }> };
150
+ return p.executions.map((e) => ({ state: e.state, total_minor: e.total_minor, receipts: e.receipt_ids.length }));
151
+ };
152
+ expect(shape(en.stdout)).toEqual(shape(pt.stdout));
153
+ });
154
+
155
+ it("an unknown --locale is a usage error, before anything runs", () => {
156
+ const out = run(["--input", "pague a escola de outubro", "--locale", "es"]);
157
+ expect(out.code).toBe(2);
158
+ expect(out.stderr).toContain("--locale must be pt-BR or en");
159
+ expect(out.meta).toBeUndefined();
160
+ });
161
+ });
@@ -0,0 +1,108 @@
1
+ /**
2
+ * What the kit says about a mandate after it was revoked: `inspect` on the
3
+ * run that met the revocation, and the consent that replaces the mandate.
4
+ */
5
+ import { mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs";
6
+ import { tmpdir } from "node:os";
7
+ import { join, relative, resolve } from "node:path";
8
+ import { describe, expect, it } from "vitest";
9
+ import type { ApiClient } from "@codespar/sdk";
10
+ import { ProofBundle, loadMandate, type Mandate } from "@codespar/agent-core";
11
+ import { assembleTimeline, loadScenario, renderText, runScenario } from "@codespar/agent-runtime";
12
+ import { agent } from "../src/kit.js";
13
+ import { runEmbeddedConsent } from "../src/modules/embedded-consent.js";
14
+
15
+ const AGENT_DIR = resolve(import.meta.dirname, "..");
16
+
17
+ describe("npm run inspect on the run that met a revocation", () => {
18
+ it("the header says revoked, from the source that answered, and no longer says active", async () => {
19
+ const runsDir = mkdtempSync(join(tmpdir(), "bills-inspect-revoked-"));
20
+ const run = await runScenario(agent, loadScenario(agent, "mandate-revoked"), { mode: "human", runsDir });
21
+ const text = renderText(assembleTimeline(ProofBundle.open(runsDir, run.run_id)!));
22
+ const header = text.split("\n")[2]!;
23
+
24
+ // The line two below it, which the header used to contradict.
25
+ expect(text).toMatch(/was revoked \(source: stub\)/);
26
+ expect(header).toMatch(/^ {2}mandate revoked \(source: stub, \d\d:\d\d:\d\d; active in the snapshot at the start of the run\), expires /);
27
+ expect(text).not.toMatch(/^ {2}mandate active,/m);
28
+ });
29
+
30
+ it("a run that met none still says active", async () => {
31
+ const runsDir = mkdtempSync(join(tmpdir(), "bills-inspect-active-"));
32
+ const run = await runScenario(agent, loadScenario(agent, "happy-path"), { mode: "human", runsDir });
33
+ expect(renderText(assembleTimeline(ProofBundle.open(runsDir, run.run_id)!)).split("\n")[2]).toMatch(/^ {2}mandate active, expires /);
34
+ });
35
+ });
36
+
37
+ /** The four calls a consent makes, answered as the sandbox answers them; `status` is what `GET /v1/mandates/{id}` says of the mandate the file already holds. */
38
+ function fakeApi(example: Mandate, status: string | Error): { api: ApiClient; reads: string[] } {
39
+ const reads: string[] = [];
40
+ const api = {
41
+ post: async (path: string) => {
42
+ if (path === "/v1/consents/init") return { token: "tok_test", expires_at: "2026-09-23T18:30:00.000Z" };
43
+ if (path === "/v1/consents/{token}/submit") {
44
+ return {
45
+ mandate_id: "cm_new",
46
+ signature: "0".repeat(64),
47
+ mandate: { consumer_id: example.consumer_id, agent_id: example.agent_id, purpose: example.purpose, currency: "BRL", cap_minor: example.cap_minor, per_tx_cap_minor: example.per_tx_cap_minor, merchant_pin_kind: "pix-key", merchant_allowlist: example.beneficiaries.map((b) => b.payee), expires_at: 1821312000 },
48
+ };
49
+ }
50
+ return { amount_minor: 600000, account: "acc_test", deposit_id: "dep_test" };
51
+ },
52
+ get: async (_path: string, options: { path: { id: string } }) => {
53
+ reads.push(options.path.id);
54
+ if (status instanceof Error) throw status;
55
+ return { status, expires_at: "2027-09-23T00:00:00.000Z", org_paused: false };
56
+ },
57
+ };
58
+ return { api: api as unknown as ApiClient, reads };
59
+ }
60
+
61
+ describe("npm run consent", () => {
62
+ const example = loadMandate(join(AGENT_DIR, "mandate.example.json"));
63
+ const NOT_YET = "O mandato ainda não existe.";
64
+
65
+ async function consent(options: { previous?: Mandate; status?: string | Error; locale?: "pt-BR" | "en" }) {
66
+ const dir = mkdtempSync(join(tmpdir(), "bills-consent-"));
67
+ const mandatePath = join(dir, ".codespar", "mandate.json");
68
+ if (options.previous) {
69
+ mkdirSync(join(dir, ".codespar"));
70
+ writeFileSync(mandatePath, JSON.stringify(options.previous));
71
+ }
72
+ const said: string[] = [];
73
+ const { api, reads } = fakeApi(example, options.status ?? "active");
74
+ const mandate = await runEmbeddedConsent({ api, example, mandatePath, say: (l) => said.push(l), confirm: async () => true, now: () => new Date("2026-09-23T18:00:00.000Z"), ...(options.locale ? { locale: options.locale } : {}) });
75
+ return { said, reads, mandate, mandatePath, file: relative(process.cwd(), mandatePath) };
76
+ }
77
+
78
+ it("with no mandate in the file, says it does not exist yet and reads no status", async () => {
79
+ const out = await consent({});
80
+ expect(out.said[1]).toContain(NOT_YET);
81
+ expect(out.reads).toEqual([]);
82
+ });
83
+
84
+ it("after a revocation, names the revoked mandate the file holds instead of saying none exists", async () => {
85
+ const previous = { ...example, id: "cm_old" };
86
+ const out = await consent({ previous, status: "revoked" });
87
+ expect(out.reads).toEqual(["cm_old"]);
88
+ expect(out.said[1]).toBe(`Já existe um mandato em ${out.file}: cm_old, revogado na API. Este é o consentimento de um mandato novo, que passa a ser o do arquivo (sandbox):`);
89
+ expect(out.said.join("\n")).not.toContain(NOT_YET);
90
+ // And the file is the new mandate's afterwards, as the line said.
91
+ expect((JSON.parse(readFileSync(out.mandatePath, "utf8")) as { id: string }).id).toBe("cm_new");
92
+ expect(out.mandate.id).toBe("cm_new");
93
+ });
94
+
95
+ it("says the state the API answers, whatever it is, and says so when it does not answer", async () => {
96
+ const previous = { ...example, id: "cm_old" };
97
+ expect((await consent({ previous, status: "active" })).said[1]).toContain("cm_old, ativo na API.");
98
+ expect((await consent({ previous, status: "paused" })).said[1]).toContain("cm_old, pausado na API.");
99
+ expect((await consent({ previous, status: new Error("ECONNRESET") })).said[1]).toContain("cm_old, com estado que a API não respondeu.");
100
+ expect((await consent({ previous, status: "revoked", locale: "en" })).said[1]).toContain("already holds a mandate: cm_old, revoked on the API.");
101
+ });
102
+
103
+ it("a file it cannot read does not stop a new consent", async () => {
104
+ const out = await consent({ previous: { id: "not a mandate" } as unknown as Mandate });
105
+ expect(out.said[1]).toContain(NOT_YET);
106
+ expect(out.mandate.id).toBe("cm_new");
107
+ });
108
+ });
@@ -0,0 +1,81 @@
1
+ /**
2
+ * A request made under a revoked mandate creates no execution: the engine
3
+ * refuses it before a draft. The terminal used to say nothing about it (the
4
+ * recorded reply even says "see the result on the terminal"), and only
5
+ * `inspect` showed the event. Driven as real processes, over a scratch state
6
+ * whose stub mandate is revoked between two runs.
7
+ */
8
+ import { spawn, spawnSync } from "node:child_process";
9
+ import { mkdtempSync } from "node:fs";
10
+ import { tmpdir } from "node:os";
11
+ import { join, resolve } from "node:path";
12
+ import { DatabaseSync } from "node:sqlite";
13
+ import { describe, expect, it } from "vitest";
14
+
15
+ const AGENT_DIR = resolve(import.meta.dirname, "..");
16
+ const BIN = resolve(AGENT_DIR, "../../packages/agent-runtime/bin.mjs");
17
+ const SCHOOL = "pague a escola de outubro";
18
+ const BASE_ENV = { ANTHROPIC_API_KEY: "", CODESPAR_API_KEY: "", CODESPAR_AGENT_NOW: "2026-10-07T14:00:00-03:00" };
19
+
20
+ function run(args: string[], env: Record<string, string>) {
21
+ const result = spawnSync(process.execPath, [BIN, "start", ...args], { cwd: AGENT_DIR, env: { ...process.env, ...BASE_ENV, ...env }, encoding: "utf8", timeout: 60_000 });
22
+ return { code: result.status, stdout: result.stdout, stderr: result.stderr };
23
+ }
24
+
25
+ /** A scratch state holding one settled payment, with the stub mandate then revoked: what `codespar mandate revoke` leaves behind. */
26
+ function revoked(label: string): Record<string, string> {
27
+ const stateDir = mkdtempSync(join(tmpdir(), `bills-refused-${label}-`));
28
+ const env = { BILLS_STATE_DIR: stateDir, BILLS_RUNS_DIR: join(stateDir, "runs") };
29
+ const first = run(["--input", SCHOOL, "--approve", "--json"], env);
30
+ expect(first.code).toBe(0);
31
+ const mandateId = (JSON.parse(first.stdout.trim()) as { mandate_id: string }).mandate_id;
32
+ const db = new DatabaseSync(join(stateDir, "state.db"));
33
+ db.prepare("INSERT OR REPLACE INTO stub_mandate_status (mandate_id, status, reason, updated_at) VALUES (?, 'revoked', 'revoked by the test', ?)").run(mandateId, new Date().toISOString());
34
+ db.close();
35
+ return env;
36
+ }
37
+
38
+ describe("a request under a revoked mandate, one-shot", () => {
39
+ it("names the refusal and its reason on the terminal, counts it, and exits 1", () => {
40
+ const out = run(["--input", SCHOOL, "--approve"], revoked("text"));
41
+ expect(out.stderr).toContain("-> refused_before_draft (mandate_revoked)");
42
+ expect(out.stdout).toContain("resultado deste run: 0 liquidada(s), 1 com falha ou recusada(s)");
43
+ expect(out.code).toBe(1);
44
+ });
45
+
46
+ it("carries the same refusal in --json, with no execution", () => {
47
+ const out = run(["--input", SCHOOL, "--approve", "--json"], revoked("json"));
48
+ const payload = JSON.parse(out.stdout.trim()) as { executions: unknown[]; run_outcome: { failed: number }; refused_before_draft: Array<{ reason: string; detail: string }> };
49
+ expect(payload.executions).toHaveLength(0);
50
+ expect(payload.refused_before_draft).toHaveLength(1);
51
+ expect(payload.refused_before_draft[0]).toMatchObject({ reason: "mandate_revoked" });
52
+ expect(payload.refused_before_draft[0]?.detail).not.toBe("");
53
+ expect(payload.run_outcome.failed).toBe(1);
54
+ expect(out.code).toBe(1);
55
+ });
56
+ });
57
+
58
+ describe("a request under a revoked mandate, interactive", () => {
59
+ it("names the refusal under the turn that made it", async () => {
60
+ const env = revoked("interactive");
61
+ const out = await new Promise<{ stdout: string; stderr: string }>((done, fail) => {
62
+ const child = spawn(process.execPath, [BIN, "start", "--transcript", "scenarios/mandate-revoked.transcript.jsonl"], { cwd: AGENT_DIR, env: { ...process.env, ...BASE_ENV, ...env } });
63
+ let stdout = "";
64
+ let stderr = "";
65
+ let typed = false;
66
+ // Typed when the prompt shows: readline drops a line that arrives before the question.
67
+ const feed = () => {
68
+ if (!typed && stderr.includes("> ")) {
69
+ typed = true;
70
+ child.stdin.end(SCHOOL + "\n");
71
+ }
72
+ };
73
+ child.stdout.on("data", (chunk: Buffer) => { stdout += chunk.toString(); });
74
+ child.stderr.on("data", (chunk: Buffer) => { stderr += chunk.toString(); feed(); });
75
+ child.on("error", fail);
76
+ child.on("close", () => done({ stdout, stderr }));
77
+ });
78
+ expect(out.stderr).toContain("-> refused_before_draft (mandate_revoked)");
79
+ expect(out.stdout).toContain("1 com falha ou recusada(s)");
80
+ });
81
+ });
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Issue #60 on the one-off payment: `codespar_pay` says `paid: true` only for
3
+ * a payment this call made. A bill's attempt id comes from its own execution,
4
+ * so the rail cannot replay one at dispatch today; the rail is scripted to
5
+ * answer the way the API answers a repeat, so the report is pinned before
6
+ * anything makes that reachable.
7
+ */
8
+ import { mkdtempSync } from "node:fs";
9
+ import { tmpdir } from "node:os";
10
+ import { join } from "node:path";
11
+ import { describe, expect, it } from "vitest";
12
+ import { fixedClock, type Execution, type StubRail, type ToolContext } from "@codespar/agent-core";
13
+ import { setup, type Setup } from "@codespar/agent-runtime";
14
+ import { agent } from "../src/kit.js";
15
+ import { codesparPay } from "../src/modules/pix-out.js";
16
+
17
+ const APPROVER = { id: "usr_demo", channel: "terminal" };
18
+
19
+ function open(): Setup {
20
+ return setup(agent, {
21
+ mode: "human",
22
+ rail: "stub",
23
+ provider: "replay",
24
+ runsDir: mkdtempSync(join(tmpdir(), "bills-replay-runs-")),
25
+ stateDir: mkdtempSync(join(tmpdir(), "bills-replay-state-")),
26
+ now: fixedClock("2026-09-23T14:00:00-03:00"),
27
+ say: () => undefined,
28
+ });
29
+ }
30
+
31
+ function context(s: Setup): ToolContext {
32
+ return {
33
+ engine: s.engine,
34
+ onExecution: async (execution: Execution) => {
35
+ let current = execution;
36
+ if (current.state === "awaiting_approval") current = s.engine.approve(current.id, APPROVER);
37
+ if (current.state === "approved") current = await s.engine.execute(current.id);
38
+ return current;
39
+ },
40
+ };
41
+ }
42
+
43
+ const PIX = { action: "pix", items: [{ payee: "mercado", amount_minor: 64000, description: "compras da semana" }] };
44
+
45
+ describe("codespar_pay: a settlement this call did not make is not reported as paid (#60)", () => {
46
+ it("a payment this call made is paid, and not replayed", async () => {
47
+ const s = open();
48
+ try {
49
+ const result = await codesparPay(PIX, context(s));
50
+ expect(result).toMatchObject({ status: "settled", paid: true, replayed: false });
51
+ } finally {
52
+ s.close();
53
+ }
54
+ });
55
+
56
+ it("a payment the rail answered from an earlier presentation is settled, replayed, and not paid by this call", async () => {
57
+ const s = open();
58
+ try {
59
+ const rail = s.rail as StubRail;
60
+ const pay = rail.pay.bind(rail);
61
+ rail.pay = async (payment) => {
62
+ const outcome = await pay(payment);
63
+ return outcome.status === "settled" ? { ...outcome, replayed: true } : outcome;
64
+ };
65
+ const result = (await codesparPay(PIX, context(s))) as { status: string; paid: boolean; replayed: boolean; receipt_ids: string[] };
66
+ expect(result).toMatchObject({ status: "settled", paid: false, replayed: true });
67
+ expect(result.receipt_ids).toHaveLength(1);
68
+
69
+ const oneShot = agent.kit.oneShotPayload({ setup: s, reply: "", toolCalls: [], executions: s.engine.list(), startedAt: 0 }) as { executions: Array<{ state: string; replayed: boolean }> };
70
+ expect(oneShot.executions).toEqual([expect.objectContaining({ state: "settled", replayed: true })]);
71
+ expect(agent.kit.describeExecution(s.engine.list()[0]!, s).join("\n")).toContain("esta execução não moveu dinheiro");
72
+ } finally {
73
+ s.close();
74
+ }
75
+ });
76
+ });