@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
@@ -15,6 +15,8 @@ import type {
15
15
  LoadedManifest,
16
16
  LocalMandateStatusStub,
17
17
  Guardrails,
18
+ Locale,
19
+ LocaleTable,
18
20
  Mandate,
19
21
  MandateStatusSource,
20
22
  PaymentRail,
@@ -95,12 +97,30 @@ export interface RailBuild {
95
97
  pollIntervalMs?: number;
96
98
  }
97
99
 
100
+ /**
101
+ * What an agent calls the people and the records of a run. None of it is
102
+ * localized, on purpose: who approved is an id in a signed artifact, and an
103
+ * approver that changed with the language would be a different approver.
104
+ */
98
105
  export interface RuntimeLabels {
99
106
  /** Who decides when no `--user` is given: `usr_terminal`, `usr_operator`. */
100
107
  defaultUser: string;
101
108
  /** Who decides inside a scenario or an adversarial case. */
102
109
  evalUser: string;
103
- /** The word for the signed instrument in the banner: `mandato`, `politica`. */
110
+ /** `reconcile`'s finding kind and detail for a sealed outcome the bundle does not hold. */
111
+ missingReceiptKind: string;
112
+ missingReceiptDetail(receiptId: string, runId: string): string;
113
+ /** `resume`'s line for an execution it could not close. */
114
+ stillExecuting(execution: Execution): string;
115
+ }
116
+
117
+ /**
118
+ * The words the runner prints on an agent's behalf, one entry per locale
119
+ * (`kit.strings`). A kit adds keys of its own to the same entries; every key
120
+ * must exist in every locale, which `npm run check` verifies.
121
+ */
122
+ export interface KitStrings {
123
+ /** The word for the signed instrument in the banner: `mandato`, `política`. */
104
124
  mandateWord: string;
105
125
  /** The word for a sealed outcome in the console: `recibo`, `registro`. */
106
126
  receiptWord: string;
@@ -108,15 +128,12 @@ export interface RuntimeLabels {
108
128
  intro: string;
109
129
  /** The interactive prompt. */
110
130
  prompt: string;
111
- /** The question an `awaiting_approval` execution asks at the keyboard. */
131
+ /** The question an `awaiting_approval` execution asks at the keyboard. Its answers are read the same in every locale. */
112
132
  approveQuestion: string;
113
133
  /** What the console says when a dispatch ended with an unknown outcome. */
114
134
  uncertainDispatch: string;
115
- /** `reconcile`'s finding kind and detail for a sealed outcome the bundle does not hold. */
116
- missingReceiptKind: string;
117
- missingReceiptDetail(receiptId: string, runId: string): string;
118
- /** `resume`'s line for an execution it could not close. */
119
- stillExecuting(execution: Execution): string;
135
+ /** Who refuses a blocked execution: "o mandato não autoriza", "the policy does not authorize". */
136
+ notAuthorized: string;
120
137
  /** `await-payer` only: the line printed every few looks while the payer has not acted. */
121
138
  waitingForPayer?(round: number): string;
122
139
  }
@@ -132,6 +149,8 @@ export interface OneShotContext {
132
149
 
133
150
  export interface ConsentContext {
134
151
  agentDir: string;
152
+ /** The run's locale: the consent summary and its question are printed in it. */
153
+ locale: Locale;
135
154
  argv: string[];
136
155
  say(line: string): void;
137
156
  }
@@ -153,6 +172,8 @@ export interface AgentKit {
153
172
  */
154
173
  scenarioRail?: "stub" | "requested";
155
174
  labels: RuntimeLabels;
175
+ /** The words the runner prints for this agent, per locale. */
176
+ strings: LocaleTable<KitStrings>;
156
177
  /** The usage text `--help`, a bad flag and a bad `--now` print. */
157
178
  usage(manifest: LoadedManifest): string;
158
179
  buildRail(ctx: RailContext): RailBuild;
@@ -169,13 +190,13 @@ export interface AgentKit {
169
190
  */
170
191
  executeOnApproval?: boolean;
171
192
  /** The deterministic policy the core runs as its `policyExtension`. `store` is the run's state.db, for a policy that judges durable state of the agent's own (a cart). */
172
- policyExtension?(ctx: { agentDir: string; manifest: LoadedManifest; guardrails: Guardrails; store: StateStore }): PolicyExtension | undefined;
193
+ policyExtension?(ctx: { agentDir: string; manifest: LoadedManifest; guardrails: Guardrails; store: StateStore; locale: () => Locale }): PolicyExtension | undefined;
173
194
  /** The console lines that describe one execution. */
174
195
  describeExecution(execution: Execution, setup: Setup): string[];
175
196
  /** The `--json` body of a one-shot. */
176
197
  oneShotPayload(ctx: OneShotContext): Record<string, unknown>;
177
198
  /** `await-payer` only: what the payer reads when a receivable becomes payable. */
178
- presentInstrument?(execution: Execution, instalment: number, chargeId: string, instrument: ChargeInstrument, tell: (line: string) => void): void;
199
+ presentInstrument?(execution: Execution, instalment: number, chargeId: string, instrument: ChargeInstrument, tell: (line: string) => void, locale: Locale): void;
179
200
  /** `await-payer` only: the one message per outcome the counterparty receives. */
180
201
  announceOutcome?(execution: Execution, setup: Setup, tell: (line: string) => void): boolean;
181
202
  /**
@@ -189,12 +210,13 @@ export interface AgentKit {
189
210
  * close on, or it cannot tell the person at all.
190
211
  *
191
212
  * The name must be one the agent declares in
192
- * `channels/whatsapp/templates.json`; the language is the registry's and is
193
- * not repeated here. `undefined` means this agent has no approved copy for
213
+ * `channels/whatsapp/templates.json`; the language is the conversation's
214
+ * locale's, and the registry declares every template in each. `locale` is
215
+ * there for the variables, which are display text too (a formatted total). `undefined` means this agent has no approved copy for
194
216
  * that outcome, which the caller REPORTS rather than papers over: a person
195
217
  * who was not told was not told.
196
218
  */
197
- outcomeTemplate?(execution: Execution): { template: string; variables: string[] } | undefined;
219
+ outcomeTemplate?(execution: Execution, locale: Locale): { template: string; variables: string[] } | undefined;
198
220
  /**
199
221
  * Work that FOLLOWS an outcome and is not part of it: a sale's service
200
222
  * invoice once the order is `settled`. Runs after `announceOutcome`,
@@ -0,0 +1,118 @@
1
+ /**
2
+ * What a run did, counted from what the engine holds and not from what the
3
+ * model said. A reply is the model's (or a recording's) and may claim a
4
+ * payroll ran when every line was already paid or every line failed; this is
5
+ * the line the terminal prints after it, and the one-shot's exit code.
6
+ *
7
+ * The unit is the payment, not the execution: an execution that paid three
8
+ * bills and failed the fourth closes `failed`, and counts three settled and
9
+ * one failed.
10
+ */
11
+ import { isDeclinedReason, isTerminal, type CoreStrings, type Execution, type ExecutionEngine, type NotRunLine, type StateStore } from "@codespar/agent-core";
12
+
13
+ export interface RunOutcome {
14
+ /** Payments this run settled. */
15
+ settled: number;
16
+ /** Payments the rail failed, executions that failed before any, and lines refused before a draft existed. */
17
+ failed: number;
18
+ /** Denied or expired, or closed by a declined reason (`isDeclinedReason`): somebody said no, or nobody answered or paid in time. */
19
+ declined: number;
20
+ /** Payments an earlier run already made: skipped here, or answered by the API with the earlier payment. */
21
+ already_paid: number;
22
+ /** Executions not yet terminal, plus lines an earlier execution still holds. */
23
+ open: number;
24
+ }
25
+
26
+ /** A request the engine refused before a draft existed (`execution.refused_before_draft`): the gate's own reason and detail. */
27
+ export interface DraftRefusal {
28
+ reason: string;
29
+ detail: string;
30
+ }
31
+
32
+ /**
33
+ * Every refusal before a draft the engine recorded for this run, in order,
34
+ * for the sentence on the terminal and for `--json`. It is NOT what the count
35
+ * is taken from: each tool reports its refused request through `onNotRun`,
36
+ * and that is the one source of the count.
37
+ */
38
+ export function draftRefusals(store: StateStore, runId: string): DraftRefusal[] {
39
+ return store
40
+ .listEvents({ run_id: runId })
41
+ .filter((e) => e.type === "execution.refused_before_draft")
42
+ .map((e) => {
43
+ const payload = e.payload as { reason?: unknown; detail?: unknown };
44
+ return { reason: String(payload.reason ?? "unknown"), detail: String(payload.detail ?? "") };
45
+ });
46
+ }
47
+
48
+ export function refusalLine(refusal: DraftRefusal): string {
49
+ return ` -> refused_before_draft (${refusal.reason}): ${refusal.detail}`;
50
+ }
51
+
52
+ export function runOutcome(executions: readonly Execution[], notRun: readonly NotRunLine[]): RunOutcome {
53
+ const out: RunOutcome = { settled: 0, failed: 0, declined: 0, already_paid: 0, open: 0 };
54
+ for (const e of executions) {
55
+ if (!isTerminal(e.state)) out.open += 1;
56
+ else if (e.state === "denied" || e.state === "expired") out.declined += 1;
57
+ // Closed with no attempt on record: the execution is the one thing to count.
58
+ else if (e.outcomes.length === 0) out[e.state === "settled" ? "settled" : isDeclinedReason(e.reason) ? "declined" : "failed"] += 1;
59
+ else {
60
+ for (const o of e.outcomes) {
61
+ if (o.status === "settled") out[o.replayed === true ? "already_paid" : "settled"] += 1;
62
+ else if (o.status === "failed") out[isDeclinedReason(o.code) ? "declined" : "failed"] += 1;
63
+ else out.open += 1;
64
+ }
65
+ }
66
+ }
67
+ for (const line of notRun) {
68
+ if (line.why === "already_settled") out.already_paid += 1;
69
+ else if (line.why === "refused") out.failed += 1;
70
+ else out.open += 1;
71
+ }
72
+ return out;
73
+ }
74
+
75
+ export function outcomeLine(text: CoreStrings, outcome: RunOutcome): string {
76
+ return text.runOutcome(outcome.settled, outcome.failed, outcome.declined, outcome.already_paid, outcome.open);
77
+ }
78
+
79
+ /** The executions of one run as the engine holds them now, each once. */
80
+ export function runExecutions(engine: ExecutionEngine, runId: string): Execution[] {
81
+ const byId = new Map<string, Execution>();
82
+ for (const e of engine.list()) if (e.run_id === runId) byId.set(e.id, e);
83
+ return [...byId.values()];
84
+ }
85
+
86
+ /**
87
+ * The one place the terminal and the one-shot count a run: the engine's
88
+ * executions of this run plus the lines that created none. The refusals
89
+ * before a draft come back with it, to be said and listed. `say`, when given,
90
+ * receives the count line.
91
+ */
92
+ export function sayOutcome(
93
+ source: { engine: ExecutionEngine; store: StateStore; runId: string; coreStrings: CoreStrings },
94
+ notRun: readonly NotRunLine[],
95
+ say?: (line: string) => void,
96
+ ): { executions: Execution[]; refusals: DraftRefusal[]; outcome: RunOutcome; line: string } {
97
+ const executions = runExecutions(source.engine, source.runId);
98
+ const refusals = draftRefusals(source.store, source.runId);
99
+ const outcome = runOutcome(executions, notRun);
100
+ const line = outcomeLine(source.coreStrings, outcome);
101
+ say?.(line);
102
+ return { executions, refusals, outcome, line };
103
+ }
104
+
105
+ /**
106
+ * The one-shot's exit code. 1 when a payment failed or a line was refused
107
+ * before a draft, and it wins over 3: a run that failed something and left
108
+ * something else `executing` is a failed run, and the line still counts what
109
+ * is open. 3 when nothing failed and an execution OF THIS RUN was left
110
+ * `executing`, whose outcome the rail did not say. 0 otherwise: settled,
111
+ * already paid, still open, and also denied or expired, which are the agent
112
+ * doing its job and are named on the line. A line an earlier run still holds
113
+ * (`in_progress`) is open and exits 0: this run left nothing behind.
114
+ */
115
+ export function outcomeExitCode(outcome: RunOutcome, executions: readonly Execution[] = []): 0 | 1 | 3 {
116
+ if (outcome.failed > 0) return 1;
117
+ return executions.some((e) => e.state === "executing") ? 3 : 0;
118
+ }
@@ -30,9 +30,8 @@ export interface PollOptions extends PollHooks {
30
30
  timeoutMs: number;
31
31
  /** Cap on looks, for a zero-interval (stub) loop: the fixture payer acts within two looks; a third proves nothing changes. */
32
32
  maxRounds?: number;
33
- /** When set, the payer plays once every instalment is payable, or after `payerAfterRounds` looks (a scenario, `--simulate-payer`). */
33
+ /** When set, the payer plays once every instalment is payable (a scenario, `--simulate-payer`), and never before. */
34
34
  payer?: SandboxPayer | undefined;
35
- payerAfterRounds?: number;
36
35
  clock?: () => Date;
37
36
  sleep?: (ms: number) => Promise<void>;
38
37
  }
@@ -85,13 +84,14 @@ export async function pollUntilClosed(engine: ExecutionEngine, executionId: stri
85
84
  rounds += 1;
86
85
  execution = await engine.reconcile(execution.id);
87
86
  await present(execution);
88
- // The sandbox payer plays once every receivable is payable (the QR was shown first, as in the scene), or after a few looks if the
89
- // clearing house is still registering: the API's test route settles a PROCESSING charge too, and on the shared sandbox the
90
- // registration can take minutes. A real payer is not this hook.
87
+ // The sandbox payer plays once every receivable is payable, the QR shown first, as in the scene, and never before. It used to
88
+ // play after a few looks whatever it found, because the API's test route settles a charge still registering; on staging on
89
+ // 2026-09-27 that route settled a charge the issuer had ended in ERROR, with no QR at all, and the scenario called the order
90
+ // settled (OPEN_QUESTIONS §63, ent#1816). A payer can only pay what it can see, so a registration that never ends payable
91
+ // leaves the order open until the wait runs out, or closes it with the issuer's own failure.
91
92
  const issued = execution.outcomes.filter((o) => o.status === "accepted" && o.transaction_id);
92
93
  const allPayable = issued.length > 0 && issued.every((o) => o.instrument?.payable);
93
- const patienceOver = rounds >= (options.payerAfterRounds ?? 5);
94
- if (options.payer && !paidRequested && execution.state === "executing" && issued.length > 0 && issued.length === execution.outcomes.filter((o) => o.status === "accepted").length && (allPayable || patienceOver)) {
94
+ if (options.payer && !paidRequested && execution.state === "executing" && issued.length > 0 && issued.length === execution.outcomes.filter((o) => o.status === "accepted").length && allPayable) {
95
95
  paidRequested = true;
96
96
  for (const outcome of issued) {
97
97
  const result = await options.payer.pay(outcome.transaction_id!, outcome.attempt_id);
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Where a run's proof bundle lives. A run a person made (`npm start`, a
3
+ * scenario pack run by name) is `runs/<run-id>`. `npm run eval` writes dozens
4
+ * per pass, and they used to land beside the person's own, so the folder a
5
+ * person looks in was mostly the suite's. They go to `runs/eval/<run-id>`.
6
+ *
7
+ * A run id is still all `inspect` and `rerun` take: an eval run is found by
8
+ * its id alone, and `eval/<run-id>` is accepted too.
9
+ */
10
+ import { existsSync, readdirSync } from "node:fs";
11
+ import { join } from "node:path";
12
+ import { ProofBundle } from "@codespar/agent-core";
13
+ import type { Agent } from "./agent.js";
14
+ import { runsDir } from "./setup.js";
15
+
16
+ /** The folder name under `runs/` that holds what the eval suite wrote. Never a run id: every run id starts with `run_`. */
17
+ export const EVAL_RUNS = "eval";
18
+
19
+ export function evalRunsDir(agent: Agent, env: NodeJS.ProcessEnv = process.env): string {
20
+ return join(runsDir(agent, env), EVAL_RUNS);
21
+ }
22
+
23
+ /** The bundle of a run by its id, a person's or the eval suite's, and the folder it was found in. */
24
+ export function openRun(agent: Agent, runId: string, env: NodeJS.ProcessEnv = process.env): { bundle: ProofBundle; runsDir: string } | undefined {
25
+ const own = runsDir(agent, env);
26
+ const id = runId.startsWith(`${EVAL_RUNS}/`) ? runId.slice(EVAL_RUNS.length + 1) : runId;
27
+ // The folder itself is not a run, and neither is a path that climbs out of the runs folder.
28
+ if (id === "" || id === EVAL_RUNS || id.includes("/") || id.includes("\\") || id === "." || id === "..") return undefined;
29
+ for (const dir of runId === id ? [own, evalRunsDir(agent, env)] : [evalRunsDir(agent, env)]) {
30
+ const bundle = ProofBundle.open(dir, id);
31
+ if (bundle) return { bundle, runsDir: dir };
32
+ }
33
+ return undefined;
34
+ }
35
+
36
+ /** Run ids in a folder, newest first. Run ids start with a timestamp or a case name, so the order is by name. */
37
+ function idsIn(dir: string): string[] {
38
+ if (!existsSync(dir)) return [];
39
+ return readdirSync(dir, { withFileTypes: true })
40
+ .filter((e) => e.isDirectory() && e.name !== EVAL_RUNS)
41
+ .map((e) => e.name)
42
+ .sort()
43
+ .reverse();
44
+ }
45
+
46
+ /** The runs a person made, and how many the eval suite left beside them. */
47
+ export function listRuns(agent: Agent, env: NodeJS.ProcessEnv = process.env): { dir: string; ids: string[]; evalDir: string; evalCount: number } {
48
+ const dir = runsDir(agent, env);
49
+ const evalDir = evalRunsDir(agent, env);
50
+ return { dir, ids: idsIn(dir), evalDir, evalCount: idsIn(evalDir).length };
51
+ }
@@ -10,9 +10,10 @@ import { existsSync, mkdtempSync, readdirSync, readFileSync } from "node:fs";
10
10
  import { tmpdir } from "node:os";
11
11
  import { basename, join, resolve } from "node:path";
12
12
  import { z } from "zod";
13
- import type { ApprovalMode, Execution } from "@codespar/agent-core";
13
+ import type { ApprovalMode, Execution, Locale, StubChargeRailOptions, StubRailOptions } from "@codespar/agent-core";
14
14
  import type { Agent } from "./agent.js";
15
15
  import type { RailKind } from "./kit.js";
16
+ import { draftRefusals } from "./outcome.js";
16
17
  import { setup, type Setup } from "./setup.js";
17
18
  import { announceOutcome, followUp, handleExecution } from "./terminal.js";
18
19
 
@@ -84,14 +85,33 @@ export interface ScenarioRun {
84
85
  run_id: string;
85
86
  bundle_dir: string;
86
87
  replies: string[];
87
- executions: Array<{ id: string; state: string; reason: string | null; trigger: string | null; total: number; trail: string[]; charge_ids: string[]; receipt_ids: string[] }>;
88
+ executions: Array<{
89
+ id: string;
90
+ state: string;
91
+ reason: string | null;
92
+ trigger: string | null;
93
+ total: number;
94
+ trail: string[];
95
+ charge_ids: string[];
96
+ receipt_ids: string[];
97
+ /**
98
+ * A receivable that settled: whether a payable instrument (a Pix or a boleto line) was SEEN before anything paid it.
99
+ * `null` for anything that is not a settled receivable. `false` means the order settled on something nobody could
100
+ * have paid, which is how a failed issuance read as a closed cycle on staging (OPEN_QUESTIONS §63).
101
+ */
102
+ payable_seen: boolean | null;
103
+ }>;
88
104
  refused_before_draft: number;
89
105
  receipts: number;
90
106
  settled_total: number;
91
107
  charges_issued: number;
92
108
  debtor_messages: number;
93
- /** Seconds from the first issuance to the last terminal state (wall clock on the API; the fake clock's ticks on the stub). */
94
- cycle_seconds: number;
109
+ /**
110
+ * Seconds from the first issuance to the last terminal state (wall clock on the API; the fake clock's ticks on the stub).
111
+ * `null` when there was no real cycle to time: nothing was issued, nothing closed, or a receivable settled with no
112
+ * payable instrument seen first.
113
+ */
114
+ cycle_seconds: number | null;
95
115
  payer_calls: string[];
96
116
  }
97
117
 
@@ -127,6 +147,10 @@ export interface RunScenarioOptions {
127
147
  say?: (line: string) => void;
128
148
  tell?: (line: string) => void;
129
149
  waitSeconds?: number | undefined;
150
+ /** Test only: stub rail options merged over the scenario's, to script an issuer the packs do not (an error, an unpayable settlement). */
151
+ stubRail?: StubRailOptions | StubChargeRailOptions;
152
+ /** The locale of the lines the run prints. The pack's assertions are on states, never on wording, so it passes in either. */
153
+ locale?: Locale | undefined;
130
154
  }
131
155
 
132
156
  export async function runScenario(agent: Agent, scenario: Scenario, options: RunScenarioOptions): Promise<ScenarioRun> {
@@ -149,7 +173,8 @@ export async function runScenario(agent: Agent, scenario: Scenario, options: Run
149
173
  runsDir: options.runsDir ?? join(agent.dir, "runs"),
150
174
  stateDir,
151
175
  ...(rail === "stub" ? { now: tick } : {}),
152
- ...(scenario.stub_refuse_payees.length > 0 ? { stubRail: { refusePayees: scenario.stub_refuse_payees } } : {}),
176
+ ...(options.locale ? { locale: options.locale } : {}),
177
+ ...(scenario.stub_refuse_payees.length > 0 || options.stubRail ? { stubRail: { ...(scenario.stub_refuse_payees.length > 0 ? { refusePayees: scenario.stub_refuse_payees } : {}), ...(options.stubRail ?? {}) } } : {}),
153
178
  say,
154
179
  });
155
180
  const stub = s.rail as { armUncertainOnce?: () => void };
@@ -186,7 +211,7 @@ export async function runScenario(agent: Agent, scenario: Scenario, options: Run
186
211
  });
187
212
  const result = await loop.turn(turn.input);
188
213
  replies.push(result.reply);
189
- refusedBeforeDraft += s.store.listEvents({ run_id: s.runId }).filter((e) => e.type === "execution.refused_before_draft").length - refusedBeforeDraft;
214
+ refusedBeforeDraft = draftRefusals(s.store, s.runId).length;
190
215
  if (turn.payer === "late") for (const e of s.engine.list({ state: "executing" })) if (!before.has(e.id)) late.push(e.id);
191
216
  }
192
217
  // A late payer pays after the conversation ended (the receivable was in flight while the world changed).
@@ -219,6 +244,8 @@ export async function runScenario(agent: Agent, scenario: Scenario, options: Run
219
244
  if (e.type === "sandbox_payer") payerCalls.push(String((e.payload as { detail: string }).detail));
220
245
  }
221
246
  const executions = s.engine.list().filter((e) => e.run_id === s.runId);
247
+ const payableSeen = new Map(executions.map((e) => [e.id, awaitsPayer ? payableSeenBeforePayment(e, events) : null]));
248
+ const cycleIsReal = firstIssued !== undefined && lastClosed !== undefined && [...payableSeen.values()].every((seen) => seen !== false);
222
249
  return {
223
250
  scenario: scenario.name,
224
251
  mode: options.mode,
@@ -235,13 +262,14 @@ export async function runScenario(agent: Agent, scenario: Scenario, options: Run
235
262
  trail: e.history.map((h) => h.to),
236
263
  charge_ids: e.outcomes.map((o) => o.transaction_id).filter((x): x is string => typeof x === "string"),
237
264
  receipt_ids: e.outcomes.filter((o) => o.receipt_id).map((o) => o.receipt_id as string),
265
+ payable_seen: payableSeen.get(e.id) ?? null,
238
266
  })),
239
267
  refused_before_draft: refusedBeforeDraft,
240
268
  receipts: s.bundle.listReceipts().length,
241
269
  settled_total: executions.filter((e) => e.state === "settled").reduce((sum, e) => sum + e.total, 0),
242
270
  charges_issued: events.filter((e) => e.type === "rail.outcome" && (e.payload as { status: string }).status === "accepted").length,
243
271
  debtor_messages: events.filter((e) => e.type === "message.debtor").length,
244
- cycle_seconds: firstIssued !== undefined && lastClosed !== undefined ? Math.round(((lastClosed - firstIssued) / 1000) * 10) / 10 : 0,
272
+ cycle_seconds: cycleIsReal ? Math.round(((lastClosed! - firstIssued!) / 1000) * 10) / 10 : null,
245
273
  payer_calls: payerCalls,
246
274
  };
247
275
  } finally {
@@ -249,6 +277,20 @@ export async function runScenario(agent: Agent, scenario: Scenario, options: Run
249
277
  }
250
278
  }
251
279
 
280
+ /**
281
+ * For a receivable that settled: was a payable instrument (`charge.instrument` with `payable: true`) recorded for it BEFORE the
282
+ * first thing that paid it (the sandbox payer's call, `commerce.charge.paid`, or the transition to `settled`)? `null` for an
283
+ * execution that is not a settled receivable.
284
+ */
285
+ export function payableSeenBeforePayment(execution: Execution, events: ReadonlyArray<{ seq: number; execution_id: string | null; type: string; payload: unknown }>): boolean | null {
286
+ if (execution.state !== "settled") return null;
287
+ const own = events.filter((e) => e.execution_id === execution.id).sort((a, b) => a.seq - b.seq);
288
+ if (!own.some((e) => e.type === "rail.outcome" && (e.payload as { status?: string }).status === "accepted")) return null;
289
+ const paid = own.find((e) => e.type === "sandbox_payer" || e.type === "commerce.charge.paid" || (e.type === "execution.transition" && (e.payload as { to?: string }).to === "settled"));
290
+ if (!paid) return null;
291
+ return own.some((e) => e.seq < paid.seq && e.type === "charge.instrument" && (e.payload as { payable?: boolean }).payable === true);
292
+ }
293
+
252
294
  function applyHook(s: Setup, hook: "revoke_mandate" | "pause_all" | undefined): void {
253
295
  if (hook === "revoke_mandate") s.gate.revoke(s.mandate.id, "revoked mid-run by the scenario");
254
296
  if (hook === "pause_all") s.gate.pauseAll();
@@ -267,7 +309,12 @@ export function checkScenario(scenario: Scenario, run: ScenarioRun): ScenarioChe
267
309
  if (expect.settled_total !== undefined && run.settled_total !== expect.settled_total) failures.push(`settled_total ${run.settled_total} != ${expect.settled_total}`);
268
310
  if (expect.charges_issued !== undefined && run.charges_issued !== expect.charges_issued) failures.push(`charges_issued ${run.charges_issued} != ${expect.charges_issued}`);
269
311
  if (expect.debtor_messages !== undefined && run.debtor_messages !== expect.debtor_messages) failures.push(`debtor_messages ${run.debtor_messages} != ${expect.debtor_messages}`);
270
- if (expect.max_cycle_seconds !== undefined && run.rail === "api" && run.cycle_seconds > expect.max_cycle_seconds) failures.push(`cycle_seconds ${run.cycle_seconds} > ${expect.max_cycle_seconds}`);
312
+ if (expect.max_cycle_seconds !== undefined && run.rail === "api" && run.cycle_seconds !== null && run.cycle_seconds > expect.max_cycle_seconds) failures.push(`cycle_seconds ${run.cycle_seconds} > ${expect.max_cycle_seconds}`);
313
+ if (expect.max_cycle_seconds !== undefined && run.rail === "api" && run.cycle_seconds === null && !run.executions.some((e) => e.payable_seen === false)) failures.push("cycle_seconds: no cycle was measured");
314
+ }
315
+ // Every run, every rail: a receivable that settled on an instrument nobody saw is not a closed cycle, whatever state it reached.
316
+ for (const e of run.executions) {
317
+ if (e.payable_seen === false) failures.push(`no_payable_instrument: ${e.id} settled on ${e.charge_ids.join(", ") || "a receivable"} with no payable instrument seen before the payment`);
271
318
  }
272
319
  // Every run, every mode: nothing reaches executing without an approval artifact carrying its hash.
273
320
  return { ok: failures.length === 0, mode: run.mode, failures, run };
@@ -5,7 +5,7 @@
5
5
  * rail, the tool handlers and the policy extension, through its kit.
6
6
  */
7
7
  import { existsSync, readFileSync } from "node:fs";
8
- import { join } from "node:path";
8
+ import { isAbsolute, join, relative } from "node:path";
9
9
  import {
10
10
  AgentLoop,
11
11
  ExecutionEngine,
@@ -19,7 +19,13 @@ import {
19
19
  loadToolsFile,
20
20
  newRunId,
21
21
  resolveFixedClock,
22
+ resolveLocale,
23
+ isLocale,
24
+ parseLocale,
25
+ CORE_STRINGS,
22
26
  type AgentRuntime,
27
+ type CoreStrings,
28
+ type Locale,
23
29
  type ApprovalMode,
24
30
  type ConversationScript,
25
31
  type Execution,
@@ -32,15 +38,30 @@ import {
32
38
  type StubRailOptions,
33
39
  type ToolContext,
34
40
  type ToolHandler,
41
+ CODESPAR_KEY_PLACEHOLDER,
35
42
  } from "@codespar/agent-core";
36
43
  import { AnthropicRuntime } from "@codespar/agent-core/providers/anthropic";
37
44
  import type { ApiClient } from "@codespar/sdk";
38
45
  import { envName, type Agent } from "./agent.js";
39
- import type { AgentKit, RailKind, SandboxPayer, Settlement } from "./kit.js";
46
+ import type { AgentKit, KitStrings, RailKind, SandboxPayer, Settlement } from "./kit.js";
40
47
 
41
48
  /** The `.env.example` placeholder counts as no key: a copied example must replay, not call Anthropic with a fake key. */
42
49
  export const ANTHROPIC_KEY_PLACEHOLDER = "sk-ant-your_key_here";
43
- export const CODESPAR_KEY_PLACEHOLDER = "csk_test_your_key_here";
50
+ export { CODESPAR_KEY_PLACEHOLDER };
51
+
52
+ /**
53
+ * The `.env` an agent reads (`readDotEnv(agent.dir)`), as a person would type
54
+ * it from where they ran the command: relative when it is below, absolute when
55
+ * it is not. `npm run` moves a workspace script into the agent's directory, so
56
+ * where the PERSON ran it is `INIT_CWD`, which npm sets; `npm run consent` at
57
+ * the root names `agents/bills-agent/.env`, not `.env`. The key refusals name
58
+ * this path, never a guess (#50).
59
+ */
60
+ export function envFileOf(agentDir: string, cwd: string = process.env["INIT_CWD"] || process.cwd()): string {
61
+ const path = join(agentDir, ".env");
62
+ const rel = relative(cwd, path);
63
+ return rel === "" || rel.startsWith("..") || isAbsolute(rel) ? path : rel;
64
+ }
44
65
 
45
66
  export type ProviderKind = "anthropic" | "replay";
46
67
 
@@ -71,6 +92,8 @@ export interface SetupOptions {
71
92
  mandate?: Mandate | undefined;
72
93
  env?: NodeJS.ProcessEnv;
73
94
  say?: ((line: string) => void) | undefined;
95
+ /** `--locale`. Absent: the manifest's `locale`, else pt-BR. */
96
+ locale?: Locale | undefined;
74
97
  }
75
98
 
76
99
  export interface Setup {
@@ -97,6 +120,18 @@ export interface Setup {
97
120
  system: string;
98
121
  handlers: Record<string, ToolHandler>;
99
122
  tools: ReturnType<typeof loadToolsFile>;
123
+ /**
124
+ * The language of what the code prints in this run. Fixed at setup, and
125
+ * recorded in the bundle's `run.json`. The one command that changes it is
126
+ * `poll --channel whatsapp`, which sets it to the locale the conversation
127
+ * was recorded in before it says anything, so a conversation that started
128
+ * in one language is not told its outcome in the other.
129
+ */
130
+ locale: Locale;
131
+ /** The kit's words in `locale`. */
132
+ readonly strings: KitStrings;
133
+ /** The words every agent shares, in `locale`. */
134
+ readonly coreStrings: CoreStrings;
100
135
  /**
101
136
  * The conversation this run is bound to, when a channel binds one (WhatsApp):
102
137
  * its contact and its subject. Set by the channel's start, read by a kit
@@ -144,6 +179,7 @@ export function setup(agent: Agent, options: SetupOptions = {}): Setup {
144
179
  const tools = loadToolsFile(manifest.resolvePath(manifest.manifest.tools));
145
180
  const system = readFileSync(join(agent.dir, "SYSTEM_PROMPT.md"), "utf8");
146
181
  const mode: ApprovalMode = options.mode ?? manifest.manifest.default_approval;
182
+ const locale = resolveLocale(options.locale, manifest.manifest);
147
183
  if (!manifest.manifest.approval.includes(mode)) throw new Error(`agent.yaml does not support approval: ${mode}`);
148
184
 
149
185
  // <PREFIX>_STATE_DIR / <PREFIX>_RUNS_DIR exist for the restart test, which drives a child process over a scratch state.
@@ -174,9 +210,10 @@ export function setup(agent: Agent, options: SetupOptions = {}): Setup {
174
210
  const bundle = new ProofBundle(runs, runId);
175
211
  bundle.mandateSnapshot(mandate);
176
212
  // Section 11: mode, rail and mandate id. The VERSION rides with the id, so a reader knows which signing of the mandate authorised the run without opening the snapshot.
177
- bundle.meta({ run_id: runId, agent: `${manifest.manifest.name}@${manifest.manifest.version}`, mode, rail: railKind, mandate_id: mandate.id, mandate_version: mandate.version, started_at: (now ?? (() => new Date()))().toISOString() });
213
+ bundle.meta({ run_id: runId, agent: `${manifest.manifest.name}@${manifest.manifest.version}`, mode, rail: railKind, mandate_id: mandate.id, mandate_version: mandate.version, locale, started_at: (now ?? (() => new Date()))().toISOString() });
178
214
 
179
- const policyExtension = agent.kit.policyExtension?.({ agentDir: agent.dir, manifest, guardrails, store });
215
+ // Read at call time, because `poll --channel whatsapp` may move the run to the conversation's recorded locale after setup.
216
+ const policyExtension = agent.kit.policyExtension?.({ agentDir: agent.dir, manifest, guardrails, store, locale: () => s.locale });
180
217
  const engine = new ExecutionEngine({
181
218
  store,
182
219
  rail,
@@ -223,6 +260,13 @@ export function setup(agent: Agent, options: SetupOptions = {}): Setup {
223
260
  system,
224
261
  handlers: {},
225
262
  tools,
263
+ locale,
264
+ get strings() {
265
+ return agent.kit.strings[this.locale];
266
+ },
267
+ get coreStrings() {
268
+ return CORE_STRINGS[this.locale];
269
+ },
226
270
  makeRuntime,
227
271
  makeLoop: (runtime, onExecution, onBatch) => new AgentLoop({ runtime, tools, handlers: s.handlers, system, bundle, engine, onExecution, ...(onBatch ? { onBatch } : {}), ...(now ? { clock: now } : {}) }),
228
272
  close: () => store.close(),
@@ -231,6 +275,32 @@ export function setup(agent: Agent, options: SetupOptions = {}): Setup {
231
275
  return s;
232
276
  }
233
277
 
278
+ /** `--locale <pt-BR|en>` out of a command's argv, validated. `undefined` when absent. */
279
+ export function localeFlag(argv: readonly string[]): Locale | undefined {
280
+ const at = argv.indexOf("--locale");
281
+ if (at < 0) return undefined;
282
+ const value = argv[at + 1];
283
+ if (value === undefined) throw new Error("--locale needs a value");
284
+ return parseLocale(value);
285
+ }
286
+
287
+ /** The locale the run `runId` recorded in its bundle, if the bundle is here and records one. */
288
+ export function recordedLocale(agent: Agent, runId: string, env: NodeJS.ProcessEnv = process.env): Locale | undefined {
289
+ const locale = ProofBundle.open(runsDir(agent, env), runId)?.readMeta()?.["locale"];
290
+ return isLocale(locale) ? locale : undefined;
291
+ }
292
+
293
+ /**
294
+ * The same setup, speaking the locale the run that created `execution`
295
+ * recorded. For a command that tells an outcome days after the run that
296
+ * proposed it (`poll`, `webhook`): the counterparty is told in the language
297
+ * they were spoken to in, whatever this command's own locale is.
298
+ */
299
+ export function inLocaleOf(s: Setup, execution: Execution): Setup {
300
+ const locale = recordedLocale(s.agent, execution.run_id);
301
+ return locale === undefined || locale === s.locale ? s : (Object.create(s, { locale: { value: locale } }) as Setup);
302
+ }
303
+
234
304
  export class NoMandateError extends Error {
235
305
  constructor() {
236
306
  super("no signed mandate yet: run `npm run consent -- --yes` first (or `npm start` without --input, which starts the consent when a test key is present)");