@codespar/cli 0.18.0 → 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 +79 -9
  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
@@ -3,11 +3,13 @@
3
3
  * else, the restart in `executing` followed by `resume`, and `rerun`.
4
4
  */
5
5
  import { spawnSync } from "node:child_process";
6
- import { existsSync, mkdtempSync, readdirSync, readFileSync } from "node:fs";
6
+ import { existsSync, mkdtempSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
7
7
  import { tmpdir } from "node:os";
8
8
  import { join, resolve } from "node:path";
9
9
  import { DatabaseSync } from "node:sqlite";
10
10
  import { describe, expect, it } from "vitest";
11
+ import { loadAdversarialCase, runAdversarialCase } from "@codespar/agent-runtime";
12
+ import { agent } from "../src/kit.js";
11
13
 
12
14
  const AGENT_DIR = resolve(import.meta.dirname, "..");
13
15
  const NODE = process.execPath;
@@ -53,6 +55,37 @@ describe("npm start -- --input ... --json", () => {
53
55
  expect(out.code).toBe(1);
54
56
  expect(out.stdout).toBe("");
55
57
  expect(out.stderr).toContain("csk_test_");
58
+ expect(out.stderr).toContain("a live key is refused");
59
+ });
60
+ });
61
+
62
+ // #50: no key, the placeholder and a live key are three mistakes with three fixes, and each refusal names the .env this agent reads,
63
+ // as the person would type it from where they ran npm (INIT_CWD): the repository root, here.
64
+ describe("a key the kit cannot use says which mistake it is", () => {
65
+ const REPO = resolve(AGENT_DIR, "../..");
66
+ const cases = [
67
+ ["no key at all", "", /CODESPAR_API_KEY is not set: copy agents\/bills-agent\/\.env\.example to agents\/bills-agent\/\.env/],
68
+ ["the .env.example placeholder", "csk_test_your_key_here", /still the placeholder from \.env\.example \(csk_test_your_key_here\): replace it in agents\/bills-agent\/\.env/],
69
+ ["a live key", ["csk", "live", "0000000000"].join("_"), /a live key is refused/],
70
+ ] as const;
71
+ for (const [name, key, message] of cases) {
72
+ it(`consent with ${name}: its own sentence, exit 1, no stack trace`, () => {
73
+ const stateDir = mkdtempSync(join(tmpdir(), "bills-key-"));
74
+ const out = run("consent", ["--yes"], { BILLS_STATE_DIR: stateDir, CODESPAR_API_KEY: key, INIT_CWD: REPO });
75
+ expect(out.code).toBe(1);
76
+ expect(out.stderr).toMatch(message);
77
+ expect(out.stderr).not.toMatch(/\n\s+at /);
78
+ if (key !== cases[2][1]) expect(out.stderr).not.toContain("live");
79
+ });
80
+ }
81
+
82
+ it("start --rail api names the same file, and without INIT_CWD the path is relative to where the command ran", () => {
83
+ const stateDir = mkdtempSync(join(tmpdir(), "bills-key-"));
84
+ const fromRoot = run("start", ["--input", "pague a escola de outubro", "--rail", "api", "--json"], { BILLS_STATE_DIR: stateDir, CODESPAR_API_KEY: "", INIT_CWD: REPO });
85
+ expect(fromRoot.code).toBe(1);
86
+ expect(fromRoot.stderr).toContain("copy agents/bills-agent/.env.example to agents/bills-agent/.env");
87
+ const here = run("start", ["--input", "pague a escola de outubro", "--rail", "api", "--json"], { BILLS_STATE_DIR: stateDir, CODESPAR_API_KEY: "", INIT_CWD: "" });
88
+ expect(here.stderr).toContain("copy .env.example to .env");
56
89
  });
57
90
  });
58
91
 
@@ -145,6 +178,94 @@ describe("npm run rerun <run-id>", () => {
145
178
  });
146
179
  });
147
180
 
181
+ /**
182
+ * The kit reads `CODESPAR_API_URL` and `CODESPAR_PROJECT_ID`; the CodeSpar CLI
183
+ * reads `CODESPAR_BASE_URL` and `CODESPAR_PROJECT`. A command that talks to
184
+ * the API stops when the two disagree; the stub rail reads neither.
185
+ */
186
+ describe("the two names for the deployment and the project", () => {
187
+ const STAGING = "https://api.staging.codespar.dev";
188
+ const DISAGREE = { CODESPAR_API_URL: "https://api.codespar.dev", CODESPAR_BASE_URL: STAGING };
189
+ const scratch = () => {
190
+ const stateDir = mkdtempSync(join(tmpdir(), "bills-env-names-"));
191
+ return { BILLS_STATE_DIR: stateDir, BILLS_RUNS_DIR: join(stateDir, "runs"), CODESPAR_API_URL: "", CODESPAR_PROJECT_ID: "", CODESPAR_BASE_URL: "", CODESPAR_PROJECT: "" };
192
+ };
193
+ const ONE_SHOT = ["--input", "pague a escola de outubro", "--approve", "--json"];
194
+
195
+ it("with a key, two that disagree stop the command with both named, no stack, nothing run", () => {
196
+ // Not the placeholder; the underscore keeps it below the secret scan's key shape.
197
+ const out = run("start", ONE_SHOT, { ...scratch(), ...DISAGREE, CODESPAR_API_KEY: "csk_test_unit_0000" });
198
+ expect(out.code).toBe(1);
199
+ expect(out.stdout).toBe("");
200
+ expect(out.stderr).toContain("CODESPAR_API_URL=https://api.codespar.dev");
201
+ expect(out.stderr).toContain(`CODESPAR_BASE_URL=${STAGING}`);
202
+ expect(out.stderr).not.toMatch(/^\s+at /m);
203
+ });
204
+
205
+ it("on the stub rail the same disagreement is not read, and the run goes on", () => {
206
+ const out = run("start", ONE_SHOT, { ...scratch(), ...DISAGREE });
207
+ expect(out.code).toBe(0);
208
+ expect(out.stderr).not.toContain("disagree");
209
+ });
210
+
211
+ it("runs with only the CLI's names set", () => {
212
+ const out = run("start", ONE_SHOT, { ...scratch(), CODESPAR_BASE_URL: STAGING, CODESPAR_PROJECT: "prj_cli" });
213
+ expect(out.code).toBe(0);
214
+ });
215
+ });
216
+
217
+ /**
218
+ * `rerun` replays the model's side of a run. An adversarial case of
219
+ * `kind: events` has none: it drives rail deliveries and never asks the
220
+ * model, so its bundle holds no `transcript.jsonl`.
221
+ */
222
+ describe("npm run rerun <run-id> on a run with no model turn", () => {
223
+ const NOTHING = "has no model turn in transcript.jsonl, so there is nothing to replay";
224
+
225
+ it("refuses the adversarial events case by name of what is missing, with no stack", async () => {
226
+ const runsDir = mkdtempSync(join(tmpdir(), "bills-rerun-adv-"));
227
+ const env = { BILLS_STATE_DIR: join(runsDir, "state"), BILLS_RUNS_DIR: runsDir };
228
+ const original = await runAdversarialCase(agent, loadAdversarialCase(agent, "webhook-replay"), { runsDir });
229
+ expect(original.ok).toBe(true);
230
+ expect(existsSync(join(runsDir, original.run_id, "transcript.jsonl"))).toBe(false);
231
+
232
+ const out = run("rerun", [original.run_id], env);
233
+ expect(out.code).toBe(1);
234
+ expect(out.stdout).toBe("");
235
+ expect(out.stderr).toContain(`runs/${original.run_id} ${NOTHING}`);
236
+ expect(out.stderr).not.toContain("ENOENT");
237
+ expect(out.stderr).not.toMatch(/^\s+at /m);
238
+
239
+ // A script reading stdout gets the refusal as data, not an empty line.
240
+ const asJson = run("rerun", [original.run_id, "--json"], env);
241
+ expect(asJson.code).toBe(1);
242
+ expect(JSON.parse(asJson.stdout.trim())).toEqual({ run_id: original.run_id, error: `runs/${original.run_id} ${NOTHING}` });
243
+ });
244
+
245
+ it("refuses a transcript that is empty, or holds the person's turn and no step of the model", async () => {
246
+ const runsDir = mkdtempSync(join(tmpdir(), "bills-rerun-adv-"));
247
+ const env = { BILLS_STATE_DIR: join(runsDir, "state"), BILLS_RUNS_DIR: runsDir };
248
+ const original = await runAdversarialCase(agent, loadAdversarialCase(agent, "webhook-replay"), { runsDir });
249
+ const transcript = join(runsDir, original.run_id, "transcript.jsonl");
250
+ for (const content of ["", JSON.stringify({ kind: "user", text: "pague a escola de outubro" }) + "\n"]) {
251
+ writeFileSync(transcript, content);
252
+ const out = run("rerun", [original.run_id], env);
253
+ expect(out.code).toBe(1);
254
+ expect(out.stderr).toContain(NOTHING);
255
+ expect(out.stderr).not.toContain("rerun ok");
256
+ }
257
+ });
258
+
259
+ it("still replays an adversarial case that did ask the model", async () => {
260
+ const runsDir = mkdtempSync(join(tmpdir(), "bills-rerun-adv-"));
261
+ const original = await runAdversarialCase(agent, loadAdversarialCase(agent, "prompt-injection"), { runsDir });
262
+ expect(original.ok).toBe(true);
263
+ const out = run("rerun", [original.run_id], { BILLS_STATE_DIR: join(runsDir, "state"), BILLS_RUNS_DIR: runsDir });
264
+ expect(out.code).toBe(0);
265
+ expect(out.stderr).toContain("rerun ok");
266
+ });
267
+ });
268
+
148
269
  describe("npm run check", () => {
149
270
  it("is green for the shipped agent and prints JSON with --json", () => {
150
271
  const out = run("check", ["--json"], {});
@@ -203,13 +324,20 @@ describe("partial failure of a multi-item execution, and rerun reproducing it",
203
324
  const runsDir = join(stateDir, "runs");
204
325
  const env = { BILLS_STATE_DIR: stateDir, BILLS_RUNS_DIR: runsDir, BILLS_STUB_REFUSE: "+5511999990001" };
205
326
  const first = run("start", ["--input", "libera o lote do mes", "--transcript", "evals/adversarial/false-authority.transcript.jsonl", "--approve", "--json"], env);
206
- expect(first.code).toBe(0);
327
+ // One attempt failed, so the execution is `failed` and the process says so.
328
+ expect(first.code).toBe(1);
207
329
  const payload = JSON.parse(first.stdout.trim()) as { run_id: string; executions: Array<{ state: string; receipt_ids: string[] }>; receipts: string[] };
208
330
  // Four bills, the SECOND refused by the rail. The execution closes `failed`
209
331
  // because one attempt failed, and the two bills after the refused one are
210
332
  // paid all the same: an attempt's outcome is that attempt's business.
211
333
  expect(payload.executions[0]?.state).toBe("failed");
212
334
  expect(payload.executions[0]?.receipt_ids).toHaveLength(3);
335
+ // Counted by payment, not by execution: three bills were paid and one failed, and the line says both.
336
+ expect((payload as unknown as { run_outcome: unknown }).run_outcome).toEqual({ settled: 3, failed: 1, declined: 0, already_paid: 0, open: 0 });
337
+ // #50: the rail's own code and message, verbatim, next to the reason — on stdout for a script, on stderr for a person.
338
+ const railError = (payload.executions[0] as unknown as { rail_error: unknown }).rail_error;
339
+ expect(railError).toMatchObject({ outcome: "failed", code: "psp_dispatch_failed", message: "stub: provider refused payee +5511999990001" });
340
+ expect(first.stderr).toContain("-> failed (rail_failed): psp_dispatch_failed — stub: provider refused payee +5511999990001");
213
341
  expect(payload.receipts).toHaveLength(3);
214
342
  const events = readFileSync(join(runsDir, payload.run_id, "events.jsonl"), "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l) as { type: string; payload: { status?: string } });
215
343
  expect(events.filter((e) => e.type === "rail.outcome").map((e) => e.payload.status)).toEqual(["settled", "failed", "settled", "settled"]);
@@ -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
+ });