@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
@@ -29,7 +29,7 @@
29
29
  */
30
30
  import { stdout } from "node:process";
31
31
  import { relative } from "node:path";
32
- import { ProofBundle, type ChargeInstrument, type Execution } from "@codespar/agent-core";
32
+ import { ProofBundle, isLocale, type ChargeInstrument, type Execution, type Locale } from "@codespar/agent-core";
33
33
  import type { Agent } from "../agent.js";
34
34
  import { runsDir, type Setup } from "../setup.js";
35
35
  import { followUp, waitForPayer } from "../terminal.js";
@@ -53,6 +53,8 @@ export interface PollWhatsAppOptions {
53
53
  payer?: "pays" | "expires" | "never" | undefined;
54
54
  now: () => Date;
55
55
  say: (line: string) => void;
56
+ /** `--locale`, when given. The conversation's recorded locale wins, and a flag that disagrees with it is refused. */
57
+ locale?: Locale | undefined;
56
58
  }
57
59
 
58
60
  /** How the outcome reached the person, or why it did not. */
@@ -97,14 +99,14 @@ export async function pollWhatsApp(options: PollWhatsAppOptions): Promise<number
97
99
  const mine = subject ? open.filter((e) => e.items.length > 0 && e.items.every((i) => i.alias === subject || i.payee === subject)) : [];
98
100
 
99
101
  if (!subject && open.length) {
100
- say(`a conversa ${script.name} nao declara subject: nao da para dizer quais execucoes sao dela, e mandar o desfecho de outra pessoa nesta conversa e exatamente o que a regra de sigilo proibe`);
102
+ say(s.coreStrings.pollNoSubject(script.name));
101
103
  return 2;
102
104
  }
103
105
  if (!mine.length) {
104
106
  // A clean no-op: nothing is waiting, so nothing is opened. The emulator is
105
107
  // not even contacted, which is the point — a poll with no work does no work.
106
108
  if (options.json) stdout.write(JSON.stringify({ polled: [], conversation: script.name, channel: null }) + "\n");
107
- else say(`nada aguardando pagador em ${script.name}`);
109
+ else say(s.coreStrings.pollNothingWaiting(script.name));
108
110
  return 0;
109
111
  }
110
112
 
@@ -114,10 +116,22 @@ export async function pollWhatsApp(options: PollWhatsAppOptions): Promise<number
114
116
  // one conversation stays one record instead of ending in a second folder.
115
117
  const { bundle, session, lines: priorLines } = conversationRecord(agent, mine);
116
118
  if (!bundle) {
117
- say(`nenhum bundle encontrado para ${mine.map((e) => e.run_id).join(", ")}: a conversa nao pode ser retomada sem o registro dela`);
119
+ say(s.coreStrings.pollNoBundle(mine.map((e) => e.run_id).join(", ")));
118
120
  return 1;
119
121
  }
120
122
 
123
+ // The conversation keeps the locale it was recorded in: the outcome is told
124
+ // in the language the person was spoken to in, template and all. A bundle
125
+ // written before the field existed records none, and the run's own stands.
126
+ const recorded = bundle.readMeta()?.["locale"];
127
+ if (isLocale(recorded)) {
128
+ if (options.locale !== undefined && options.locale !== recorded) {
129
+ say(s.coreStrings.pollLocaleConflict(script.name, recorded, options.locale));
130
+ return 2;
131
+ }
132
+ s.locale = recorded;
133
+ }
134
+
121
135
  const built = buildWhatsApp({
122
136
  agent,
123
137
  setup: s,
@@ -159,11 +173,7 @@ export async function pollWhatsApp(options: PollWhatsAppOptions): Promise<number
159
173
  const results: Polled[] = [];
160
174
  try {
161
175
  const remaining = channel.sessionRemainingSeconds;
162
- say(
163
- `${s.manifest.manifest.name} ${s.manifest.manifest.version} — poll no canal whatsapp (${channel.backend}) — conversa ${script.name} — janela de 24h ${
164
- channel.sessionOpen ? `ABERTA (${Math.round(remaining / 60)} min restantes): mensagem livre` : "FECHADA: so template aprovado"
165
- }`,
166
- );
176
+ say(s.coreStrings.pollBanner(s.manifest.manifest.name, s.manifest.manifest.version, channel.backend, script.name, channel.sessionOpen ? Math.round(remaining / 60) : undefined));
167
177
  for (const execution of mine) {
168
178
  const sessionOpen = channel.sessionOpen;
169
179
  const result = await waitForPayer(execution.id, {
@@ -188,11 +198,8 @@ export async function pollWhatsApp(options: PollWhatsAppOptions): Promise<number
188
198
  session_open: sessionOpen,
189
199
  delivery,
190
200
  });
191
- say(
192
- `${closed.id}: ${closed.state}${closed.reason ? ` (${closed.reason})` : ""} apos ${result.rounds} consulta(s), ${result.seconds}s — ${
193
- delivery.told ? `avisado por ${delivery.carrier === "template" ? `template ${delivery.template}${delivery.fallback ? " (reserva: o kit nao tem copia para este desfecho)" : ""}` : "mensagem livre"}` : `nao avisado (${delivery.reason}${delivery.detail ? `: ${delivery.detail}` : ""})`
194
- }`,
195
- );
201
+ const told = delivery.told ? (delivery.carrier === "template" ? s.coreStrings.pollToldByTemplate(delivery.template ?? "?", delivery.fallback === true) : s.coreStrings.pollToldByText) : s.coreStrings.pollNotTold(delivery.reason, delivery.detail);
202
+ say(`${closed.id}: ${closed.state}${closed.reason ? ` (${closed.reason})` : ""}${s.coreStrings.afterLooks(result.rounds, result.seconds, false)} — ${told}`);
196
203
  }
197
204
  } finally {
198
205
  await channel.close();
@@ -213,7 +220,7 @@ export async function pollWhatsApp(options: PollWhatsAppOptions): Promise<number
213
220
  };
214
221
 
215
222
  if (options.json) stdout.write(JSON.stringify({ polled: results, conversation: script.name, channel: channelSummary }) + "\n");
216
- else say(`conversa em ${channelSummary.log} — ${channelSummary.messages_out} enviada(s)${refused.length ? `, ${refused.length} recusada(s)` : ""}`);
223
+ else say(s.coreStrings.waConversationSummary(channelSummary.log, undefined, channelSummary.messages_out, refused.length));
217
224
 
218
225
  if (results.some((r) => r.timed_out)) return 3;
219
226
  // A cycle that closed and a person who was not told is a failure worth an
@@ -267,7 +274,7 @@ function conversationRecord(agent: Agent, executions: readonly Execution[]): { b
267
274
  * it either.
268
275
  */
269
276
  async function presentInstrument(channel: WhatsAppChannel, s: Setup, execution: Execution, instalment: number, chargeId: string, instrument: ChargeInstrument): Promise<void> {
270
- for (const body of instrumentBodies(execution, instalment, chargeId, instrument, s.mandate.currency)) await channel.send(body);
277
+ for (const body of instrumentBodies(execution, instalment, chargeId, instrument, s.mandate.currency, s.locale)) await channel.send(body);
271
278
  }
272
279
 
273
280
  /**
@@ -298,7 +305,7 @@ async function tellOutcome(channel: WhatsAppChannel, s: Setup, execution: Execut
298
305
  // The provider's is the one the window is counted on, so the message goes
299
306
  // the way it would have gone had we known: as the template. The cursor is
300
307
  // already this call's, taken by `announceOutcome` above.
301
- if (sent.refused?.rule !== "session_window_closed") return confirmed(channel, sent, deliveryOf(sent, "text"));
308
+ if (sent.refused?.rule !== "session_window_closed") return confirmed(channel, sent, deliveryOf(s, sent, "text"));
302
309
  return tellByTemplate(channel, s, execution, { cursorHeld: true });
303
310
  }
304
311
  return tellByTemplate(channel, s, execution, { cursorHeld: false });
@@ -337,22 +344,23 @@ async function confirmed(channel: WhatsAppChannel, sent: SentMessage, delivery:
337
344
  * defect, reported as one and not papered over by the fallback.
338
345
  */
339
346
  async function tellByTemplate(channel: WhatsAppChannel, s: Setup, execution: Execution, options: { cursorHeld: boolean }): Promise<Delivery> {
340
- const chosen: { template: string; variables: string[]; fallback?: true } | undefined = s.kit.outcomeTemplate?.(execution) ?? fallbackOf(channel);
347
+ const chosen: { template: string; variables: string[]; fallback?: true } | undefined = s.kit.outcomeTemplate?.(execution, s.locale) ?? fallbackOf(channel);
341
348
  if (!chosen) {
342
349
  return {
343
350
  told: false,
344
351
  reason: "no_template_for_outcome",
345
- detail: `a janela de 24h esta fechada e o agente nao declara template para ${execution.state}${execution.reason ? ` (${execution.reason})` : ""}, nem um template de reserva`,
352
+ detail: s.coreStrings.pollNoTemplateForOutcome(`${execution.state}${execution.reason ? ` (${execution.reason})` : ""}`),
346
353
  };
347
354
  }
355
+ // The copy in the conversation's language: an English conversation is never sent the pt_BR template.
348
356
  const declared = channel.declaredTemplate(chosen.template);
349
357
  if (!declared) {
350
- return { told: false, reason: "no_template_for_outcome", detail: `o kit pediu o template ${chosen.template}, que channels/whatsapp/templates.json nao declara` };
358
+ return { told: false, reason: "no_template_for_outcome", detail: s.coreStrings.pollTemplateNotDeclared(`${chosen.template} (${channel.language})`) };
351
359
  }
352
360
  if (!options.cursorHeld && !s.engine.markTold(execution.id, execution.state)) return toldBefore(s, execution);
353
361
  const sent = await channel.send({ kind: "template", template: declared.name, language: declared.language, variables: chosen.variables, about: aboutOf(execution) });
354
- s.engine.note("message.debtor", execution.id, { state: execution.state, reason: execution.reason ?? null, template: declared.name, variables: chosen.variables, ...(chosen.fallback ? { fallback: true } : {}) });
355
- return confirmed(channel, sent, deliveryOf(sent, "template", declared.name, chosen.fallback));
362
+ s.engine.note("message.debtor", execution.id, { state: execution.state, reason: execution.reason ?? null, template: declared.name, language: declared.language, variables: chosen.variables, ...(chosen.fallback ? { fallback: true } : {}) });
363
+ return confirmed(channel, sent, deliveryOf(s, sent, "template", declared.name, chosen.fallback));
356
364
  }
357
365
 
358
366
  function fallbackOf(channel: WhatsAppChannel): { template: string; variables: string[]; fallback: true } | undefined {
@@ -360,8 +368,8 @@ function fallbackOf(channel: WhatsAppChannel): { template: string; variables: st
360
368
  return name ? { template: name, variables: [], fallback: true } : undefined;
361
369
  }
362
370
 
363
- function deliveryOf(sent: SentMessage, carrier: "text" | "template", template?: string, fallback?: boolean): Delivery {
371
+ function deliveryOf(s: Setup, sent: SentMessage, carrier: "text" | "template", template?: string, fallback?: boolean): Delivery {
364
372
  if (sent.refused) return { told: false, reason: "refused", detail: `${sent.refused.rule}: ${sent.refused.detail}` };
365
- if (sent.state === "failed") return { told: false, reason: "refused", detail: "o provedor nao aceitou a mensagem" };
373
+ if (sent.state === "failed") return { told: false, reason: "refused", detail: s.coreStrings.pollProviderRefused };
366
374
  return { told: true, carrier, ...(template ? { template } : {}), ...(fallback ? { fallback: true as const } : {}) };
367
375
  }
@@ -15,9 +15,9 @@
15
15
  */
16
16
  import { stderr, stdout } from "node:process";
17
17
  import { join } from "node:path";
18
- import { loadManifest, resolveFixedClock, type ChannelName } from "@codespar/agent-core";
18
+ import { loadManifest, parseLocale, resolveFixedClock, type ChannelName, type Locale } from "@codespar/agent-core";
19
19
  import type { Agent } from "../agent.js";
20
- import { setup } from "../setup.js";
20
+ import { inLocaleOf, setup } from "../setup.js";
21
21
  import { announceOutcome, followUp, waitForPayer } from "../terminal.js";
22
22
  import { pollWhatsApp } from "./poll-whatsapp.js";
23
23
  import type { WhatsAppBackendName } from "../channels/whatsapp/open.js";
@@ -30,6 +30,8 @@ const USAGE = `codespar-agent poll [options]
30
30
  --simulate-payer let the sandbox payer act once the receivable is payable
31
31
  --payer pays|expires|never what the fixture payer does when it acts (stub rail only)
32
32
  --now <ISO 8601> pin the run's clock; env CODESPAR_AGENT_NOW is the same thing
33
+ --locale pt-BR|en the language of this command's lines. An outcome is told in the locale its run recorded,
34
+ and --channel whatsapp refuses a --locale that disagrees with the conversation's
33
35
  --json machine output on stdout, everything else on stderr`;
34
36
 
35
37
  interface Args {
@@ -40,6 +42,7 @@ interface Args {
40
42
  simulatePayer: boolean;
41
43
  payer?: "pays" | "expires" | "never";
42
44
  now?: string;
45
+ locale?: Locale;
43
46
  json: boolean;
44
47
  }
45
48
 
@@ -73,6 +76,7 @@ export function parsePollArgs(argv: string[]): Args {
73
76
  args.payer = v;
74
77
  } else if (a === "--conversation") args.conversation = next();
75
78
  else if (a === "--now") args.now = next();
79
+ else if (a === "--locale") args.locale = parseLocale(next());
76
80
  else throw new Error(`unknown argument ${a}`);
77
81
  }
78
82
  if (args.channel !== "whatsapp" && (args.backend !== undefined || args.conversation !== undefined)) {
@@ -97,7 +101,7 @@ export async function poll(agent: Agent, argv: string[]): Promise<number> {
97
101
  return 2;
98
102
  }
99
103
 
100
- const s = setup(agent, { say, runId: `run_poll_${Date.now().toString(36)}`, ...(now ? { now } : {}) });
104
+ const s = setup(agent, { say, runId: `run_poll_${Date.now().toString(36)}`, ...(now ? { now } : {}), ...(args.locale ? { locale: args.locale } : {}) });
101
105
  // The same flag `start` has, and it means more here: a receivable nobody
102
106
  // paid reaches its due date BETWEEN two runs, never inside one, so "what
103
107
  // happens when it expires" is a question only a poll can be asked.
@@ -115,6 +119,7 @@ export async function poll(agent: Agent, argv: string[]): Promise<number> {
115
119
  ...(args.payer ? { payer: args.payer } : {}),
116
120
  now: now ?? (() => new Date()),
117
121
  say,
122
+ ...(args.locale ? { locale: args.locale } : {}),
118
123
  });
119
124
  }
120
125
  // `behave` only changes the default for receivables the rail has not
@@ -129,8 +134,10 @@ export async function poll(agent: Agent, argv: string[]): Promise<number> {
129
134
  const results = [];
130
135
  for (const open of s.engine.list({ state: "executing" })) {
131
136
  if (open.reason !== "awaiting_settlement") continue;
132
- const r = await waitForPayer(open.id, { setup: s, approver: { id: s.kit.labels.defaultUser, channel: "terminal" }, say, tell, waitSeconds: args.wait, simulatePayer: args.simulatePayer });
133
- announceOutcome(r.execution, s, tell);
137
+ // The payer is told in the locale of the run that issued the charge, which is where they were spoken to.
138
+ const told = inLocaleOf(s, open);
139
+ const r = await waitForPayer(open.id, { setup: told, approver: { id: s.kit.labels.defaultUser, channel: "terminal" }, say, tell, waitSeconds: args.wait, simulatePayer: args.simulatePayer });
140
+ announceOutcome(r.execution, told, tell);
134
141
  if (r.execution.state !== "executing") await s.engine.collectReceipts(r.execution.id);
135
142
  await followUp(r.execution, s, say);
136
143
  results.push({ id: r.execution.id, state: r.execution.state, reason: r.execution.reason ?? null, rounds: r.rounds, seconds: r.seconds, timed_out: r.timed_out });
@@ -8,11 +8,54 @@ import { mkdtempSync } from "node:fs";
8
8
  import { tmpdir } from "node:os";
9
9
  import { join } from "node:path";
10
10
  import { stderr, stdout } from "node:process";
11
- import { ProofBundle, type ApprovalMode, type Execution } from "@codespar/agent-core";
11
+ import { isLocale, type ApprovalMode, type Execution } from "@codespar/agent-core";
12
12
  import type { Agent } from "../agent.js";
13
- import { runsDir, setup } from "../setup.js";
13
+ import { setup } from "../setup.js";
14
+ import { openRun } from "../runs.js";
14
15
  import { handleExecution } from "../terminal.js";
15
16
 
17
+ /**
18
+ * A clock that starts where the original run did and moves a second per
19
+ * read, which is how the scenario and the adversarial runners keep theirs. Its
20
+ * first read is the original's `started_at`.
21
+ */
22
+ function clockFrom(startedAt: Date): () => Date {
23
+ let at = startedAt.getTime() - 1000;
24
+ return () => new Date((at += 1000));
25
+ }
26
+
27
+ const MANDATE_STOPPED: Record<string, string> = {
28
+ mandate_revoked: "a mandate that was revoked",
29
+ mandate_paused: "a mandate that was paused",
30
+ org_paused: "an organization that paused every mandate",
31
+ };
32
+
33
+ /**
34
+ * What the original run met that only the world can do, read off its events.
35
+ * The rerun starts from an active mandate, a rail that answers and a payer
36
+ * that pays; a run that met anything else would be replayed as a different
37
+ * run and reported as one that DIFFERS, with nothing to say why.
38
+ */
39
+ export function notReplayed(events: ReadonlyArray<Record<string, unknown>>): string[] {
40
+ const found = new Set<string>();
41
+ const last = new Map<string, string>();
42
+ const accepted = new Set<string>();
43
+ for (const event of events) {
44
+ const payload = (event["payload"] ?? {}) as { reason?: unknown; status?: unknown; to?: unknown };
45
+ const execution = typeof event["execution_id"] === "string" ? event["execution_id"] : undefined;
46
+ // An own key only: the reason is a string from a recording, and `constructor` is a key of every object.
47
+ const stopped = typeof payload.reason === "string" && Object.hasOwn(MANDATE_STOPPED, payload.reason) ? MANDATE_STOPPED[payload.reason] : undefined;
48
+ if (stopped && (event["type"] === "execution.transition" || event["type"] === "execution.refused_before_draft")) found.add(stopped);
49
+ // The engine writes all three for one uncertain dispatch; any of them is the run saying the rail did not answer.
50
+ if ((event["type"] === "rail.outcome" && payload.status === "uncertain") || event["type"] === "rail.uncertain" || event["type"] === "execution.uncertain") found.add("an uncertain answer from the rail");
51
+ if (event["type"] === "rail.outcome" && payload.status === "accepted" && execution) accepted.add(execution);
52
+ if (event["type"] === "execution.transition" && execution && typeof payload.to === "string") last.set(execution, payload.to);
53
+ }
54
+ // Issued and never closed: the charge was out when the run ended, and nobody paid it.
55
+ if ([...accepted].some((execution) => last.get(execution) === "executing")) found.add("a payer who had not paid when it ended");
56
+ return [...found];
57
+ }
58
+
16
59
  export async function rerun(agent: Agent, argv: string[]): Promise<number> {
17
60
  const json = argv.includes("--json");
18
61
  const runId = argv.find((a) => !a.startsWith("--"));
@@ -21,17 +64,40 @@ export async function rerun(agent: Agent, argv: string[]): Promise<number> {
21
64
  say("usage: npm run rerun <run-id> [--json]");
22
65
  return 2;
23
66
  }
24
- const original = ProofBundle.open(runsDir(agent), runId);
25
- if (!original) {
67
+ const found = openRun(agent, runId);
68
+ const original = found?.bundle;
69
+ if (!found || !original) {
26
70
  say(`no bundle at runs/${runId}`);
27
71
  return 1;
28
72
  }
29
73
  const meta = original.readMeta() ?? {};
74
+ const startedAt = typeof meta["started_at"] === "string" && Number.isFinite(Date.parse(meta["started_at"])) ? new Date(meta["started_at"]) : undefined;
30
75
  const mode = (meta["mode"] as ApprovalMode | undefined) ?? "human";
31
76
  const events = original.readEvents();
32
- const originalTrail = events.filter((e) => e["type"] === "execution.transition").map((e) => (e["payload"] as { to: string }).to);
33
- const originalDecisions = events.filter((e) => e["type"] === "approval.created").map((e) => ((e["payload"] as { approver: { type: string } }).approver.type === "person" ? "approve" : "mandate"));
34
- const userTurns = original.readTranscript().filter((l) => l.kind === "user").map((l) => l["text"] as string);
77
+ const transitions = events.filter((e) => e["type"] === "execution.transition").map((e) => ({ execution: e["execution_id"] as string, ...(e["payload"] as { from: string; to: string }) }));
78
+ const originalTrail = transitions.map((t) => t.to);
79
+ // What the original did with each approval it asked for, in the order it asked: approved it, denied it, or left it open. A run that stopped at `awaiting_approval` (a one-shot with no --approve or --deny, an adversarial case that only has to escalate) is replayed to the same place, not decided on its behalf.
80
+ const asked = transitions.flatMap((t, i) => (t.to === "awaiting_approval" ? [transitions.slice(i + 1).find((n) => n.execution === t.execution)?.to] : []));
81
+ // Nobody decides an approval that expired either: the rerun's clock does, or the sequences differ and the last line says so.
82
+ const originalDecisions = asked.map((next) => (next === "approved" ? "approve" : next === "denied" ? "deny" : "none"));
83
+ const leftOpen = asked.filter((next) => next === undefined).length;
84
+ const transcript = original.readTranscript();
85
+ // The transcript is the model's side, and replaying it is all a rerun does. A run that never asked the model recorded no step to replay: an adversarial case of `kind: events` drives rail deliveries and writes no transcript at all.
86
+ if (!transcript.some((l) => l.kind === "assistant_step")) {
87
+ const error = `runs/${runId} has no model turn in transcript.jsonl, so there is nothing to replay`;
88
+ if (json) stdout.write(JSON.stringify({ run_id: runId, error }) + "\n");
89
+ say(error);
90
+ return 1;
91
+ }
92
+ // What the world did in the original is not in the transcript, and a rerun that ignores it pays what the original denied. It is said by name, before anything is replayed.
93
+ const unreplayed = notReplayed(events);
94
+ if (unreplayed.length > 0) {
95
+ const error = `runs/${runId} cannot be compared with a rerun: it met ${unreplayed.join(", and ")}, which a rerun does not replay`;
96
+ if (json) stdout.write(JSON.stringify({ run_id: runId, error, not_replayed: unreplayed }) + "\n");
97
+ say(error);
98
+ return 1;
99
+ }
100
+ const userTurns = transcript.filter((l) => l.kind === "user").map((l) => l["text"] as string);
35
101
  const transcriptPath = join(original.dir, "transcript.jsonl");
36
102
  const plan = agent.kit.rerunPlan?.(events) ?? {};
37
103
 
@@ -40,16 +106,22 @@ export async function rerun(agent: Agent, argv: string[]): Promise<number> {
40
106
  rail: "stub",
41
107
  provider: "replay",
42
108
  transcript: transcriptPath,
43
- runId: `${runId}_rerun_${Date.now().toString(36)}`,
109
+ runId: `${original.runId}_rerun_${Date.now().toString(36)}`,
110
+ // Beside the run it replays: the rerun of an eval run stays with the eval runs.
111
+ runsDir: found.runsDir,
44
112
  stateDir: mkdtempSync(join(tmpdir(), `${agent.slug}-rerun-`)),
45
113
  stubRail: plan.stubRail,
114
+ // The original's clock, from where it started: a rule on a due date or on the hours of service decides today what it decided then.
115
+ ...(startedAt ? { now: clockFrom(startedAt) } : {}),
46
116
  say,
117
+ // The recording's locale, so the rerun's refusal details read as the original's did.
118
+ ...(isLocale(meta["locale"]) ? { locale: meta["locale"] } : {}),
47
119
  });
48
120
  try {
49
121
  let decisionIndex = 0;
50
122
  const runtime = s.makeRuntime();
51
123
  const loop = s.makeLoop(runtime, (execution: Execution) => {
52
- const decision = execution.state === "awaiting_approval" ? (originalDecisions[decisionIndex++] === "approve" ? "approve" : "deny") : "none";
124
+ const decision = execution.state === "awaiting_approval" ? (originalDecisions[decisionIndex++] ?? "deny") : "none";
53
125
  return handleExecution(execution, {
54
126
  setup: s,
55
127
  approver: { id: "usr_rerun", channel: "terminal" },
@@ -78,7 +150,8 @@ export async function rerun(agent: Agent, argv: string[]): Promise<number> {
78
150
  }) + "\n",
79
151
  );
80
152
  }
81
- say(same ? `rerun ok: ${trail.length} transition(s), same sequence as ${runId}` : `rerun DIFFERS: original ${JSON.stringify(originalTrail)} vs rerun ${JSON.stringify(trail)}`);
153
+ const open = leftOpen > 0 ? `; ${leftOpen} execution(s) left in awaiting_approval, as the original left ${leftOpen === 1 ? "it" : "them"}` : "";
154
+ say(same ? `rerun ok: ${trail.length} transition(s), same sequence as ${runId}${open}` : `rerun DIFFERS: original ${JSON.stringify(originalTrail)} vs rerun ${JSON.stringify(trail)}`);
82
155
  return same ? 0 : 1;
83
156
  } finally {
84
157
  s.close();
@@ -6,7 +6,7 @@
6
6
  * ones expire.
7
7
  */
8
8
  import { stderr, stdout } from "node:process";
9
- import type { Execution } from "@codespar/agent-core";
9
+ import { railErrorOf, type Execution } from "@codespar/agent-core";
10
10
  import type { Agent } from "../agent.js";
11
11
  import { setup } from "../setup.js";
12
12
  import { followUp } from "../terminal.js";
@@ -37,6 +37,7 @@ export async function resume(agent: Agent, argv: string[]): Promise<number> {
37
37
  state: e.state,
38
38
  ...(awaitsPayer ? { reason: e.reason ?? null } : {}),
39
39
  detail: e.detail ?? null,
40
+ rail_error: railErrorOf(e),
40
41
  ...(awaitsPayer ? { charge_ids: e.outcomes.map((o) => o.transaction_id ?? null) } : {}),
41
42
  receipt_ids: e.outcomes.filter((o) => o.receipt_id).map((o) => o.receipt_id),
42
43
  }));
@@ -14,6 +14,7 @@ import { stdout } from "node:process";
14
14
  import { relative } from "node:path";
15
15
  import type { ConversationScript } from "@codespar/agent-core";
16
16
  import type { Agent } from "../agent.js";
17
+ import { outcomeExitCode, refusalLine, sayOutcome } from "../outcome.js";
17
18
  import type { Setup } from "../setup.js";
18
19
  import { defaultAsk } from "../terminal.js";
19
20
  import { converse } from "../channels/whatsapp/run.js";
@@ -116,19 +117,23 @@ export async function startWhatsApp(options: StartWhatsAppOptions): Promise<numb
116
117
  ...(cost ? { simulated_cost: cost } : {}),
117
118
  };
118
119
 
120
+ // The same count, refusals and exit code as the terminal's one-shot: the channel changes who is told, not what the run did.
121
+ const { executions, refusals, outcome, line } = sayOutcome(s, result.notRun);
122
+ for (const refusal of refusals) say(refusalLine(refusal));
119
123
  if (options.json) {
120
124
  const payload = s.kit.oneShotPayload({
121
125
  setup: s,
122
126
  reply: result.replies[result.replies.length - 1] ?? "",
123
127
  toolCalls: result.toolCalls,
124
- executions: result.executions,
128
+ executions,
125
129
  startedAt: options.startedAt,
126
130
  });
127
- stdout.write(JSON.stringify({ ...payload, channel: channelSummary }) + "\n");
131
+ stdout.write(JSON.stringify({ ...payload, run_outcome: outcome, refused_before_draft: refusals, channel: channelSummary }) + "\n");
128
132
  } else {
129
- say(`conversa em ${channelSummary.log} — ${channelSummary.messages_in} recebida(s), ${channelSummary.messages_out} enviada(s)${refused.length ? `, ${refused.length} recusada(s)` : ""}`);
130
- if (cost) say(`custo simulado desta conversa nas regras da Meta: ${cost.total.toFixed(4)} ${cost.currency} (conta do emulador, nao nossa)`);
133
+ say(line);
134
+ say(s.coreStrings.waConversationSummary(channelSummary.log, channelSummary.messages_in, channelSummary.messages_out, refused.length));
135
+ if (cost) say(s.coreStrings.waSimulatedCost(cost.total.toFixed(4), cost.currency));
131
136
  }
132
137
 
133
- return result.executions.some((e) => e.state === "executing") ? 3 : 0;
138
+ return outcomeExitCode(outcome, executions);
134
139
  }
@@ -6,18 +6,29 @@
6
6
  *
7
7
  * `--json` puts machine data on stdout (valid JSON, nothing else) and the
8
8
  * human messages on stderr.
9
+ *
10
+ * A one-shot prints, after the reply, what the run did as the engine counts
11
+ * it (`outcome.ts`), and exits by it: see `EXIT_CODES`.
9
12
  */
13
+ import { statSync } from "node:fs";
10
14
  import { stderr, stdout } from "node:process";
11
15
  import { relative, resolve } from "node:path";
12
- import { NotATestKeyError, declaredReplies, isTestKey, loadManifest, resolveFixedClock, type ApprovalMode, type ChannelName } from "@codespar/agent-core";
16
+ import { CORE_STRINGS, NotATestKeyError, WHATSAPP_LANGUAGE, declaredReplies, loadManifest, parseLocale, resolveLocale, testKeyProblem, resolveFixedClock, type ApprovalMode, type ChannelName, type Locale } from "@codespar/agent-core";
13
17
  import { join } from "node:path";
14
18
  import type { Agent } from "../agent.js";
15
19
  import type { RailKind } from "../kit.js";
16
- import { resolveProvider, resolveRailKind, setup, type ProviderKind } from "../setup.js";
20
+ import { envFileOf, resolveProvider, resolveRailKind, setup, type ProviderKind } from "../setup.js";
17
21
  import { checkScenario, listScenarios, loadScenario, runScenario, scenariosDir } from "../scenarios.js";
18
22
  import { closeTerminal, defaultAsk, handleExecution, interactive } from "../terminal.js";
19
23
  import { loadTemplates, resolveConversation } from "../channels/index.js";
20
24
  import { startWhatsApp, type WhatsAppBackendName } from "./start-whatsapp.js";
25
+ import { outcomeExitCode, refusalLine, sayOutcome } from "../outcome.js";
26
+
27
+ const EXIT_CODES = `exit (--input): 0 nothing failed (settled, already paid, denied, expired or still open: the last line counts each payment); 1 a payment failed or a line was refused before a draft, and 1 wins over 3; 3 nothing failed and an execution of this run was left executing (npm run reconcile). A line an earlier run still holds is open and exits 0.`;
28
+
29
+ function isFile(path: string): boolean {
30
+ return statSync(path, { throwIfNoEntry: false })?.isFile() ?? false;
31
+ }
21
32
 
22
33
  interface Args {
23
34
  input?: string;
@@ -40,6 +51,8 @@ interface Args {
40
51
  conversation?: string;
41
52
  /** Replay the conversation's turns instead of reading them from the keyboard. */
42
53
  scripted: boolean;
54
+ /** The language of what the code prints; absent means agent.yaml's `locale`, else pt-BR. */
55
+ locale?: Locale;
43
56
  help: boolean;
44
57
  }
45
58
 
@@ -92,6 +105,7 @@ export function parseArgs(argv: string[], awaitsPayer: boolean): Args {
92
105
  args.backend = v;
93
106
  } else if (a === "--conversation") args.conversation = next();
94
107
  else if (a === "--scripted") args.scripted = true;
108
+ else if (a === "--locale") args.locale = parseLocale(next());
95
109
  else if (a === "--help" || a === "-h") args.help = true;
96
110
  else throw new Error(`unknown argument ${a}`);
97
111
  }
@@ -109,10 +123,12 @@ export async function start(agent: Agent, argv: string[]): Promise<number> {
109
123
  return 2;
110
124
  }
111
125
  if (args.help) {
112
- stderr.write(usage + "\n");
126
+ stderr.write(`${usage}\n${EXIT_CODES}\n`);
113
127
  return 0;
114
128
  }
115
129
  const say = (line: string) => stderr.write(line + "\n");
130
+ // Fixed for the run, and for a conversation: the proposal and its approval are asked in the same language.
131
+ const locale = resolveLocale(args.locale, loadManifest(join(agent.dir, "agent.yaml")).manifest);
116
132
 
117
133
  // A pinned instant makes the guardrails deterministic: the CI runs the fixture inside the declared hours whatever the hour is.
118
134
  let now: (() => Date) | undefined;
@@ -125,12 +141,19 @@ export async function start(agent: Agent, argv: string[]): Promise<number> {
125
141
 
126
142
  // Sandbox by construction: a live key dies here, before anything else runs.
127
143
  const railKind = resolveRailKind(process.env, args.rail);
128
- if (railKind === "api" && !isTestKey(process.env["CODESPAR_API_KEY"])) {
129
- say(new NotATestKeyError().message);
144
+ const keyProblem = railKind === "api" ? testKeyProblem(process.env["CODESPAR_API_KEY"]) : undefined;
145
+ if (keyProblem) {
146
+ say(new NotATestKeyError(keyProblem, envFileOf(agent.dir)).message);
147
+ return 1;
148
+ }
149
+
150
+ // A recording that is not there is said by its path, before a mandate is asked for or a run is opened.
151
+ if (args.transcript !== undefined && !isFile(args.transcript)) {
152
+ say(`no transcript at ${args.transcript}`);
130
153
  return 1;
131
154
  }
132
155
 
133
- if (args.scenario) return runScenarioCommand(agent, args, railKind, say);
156
+ if (args.scenario) return runScenarioCommand(agent, args, railKind, locale, say);
134
157
 
135
158
  // A channel is a conversation, so the flags a one-shot and a scenario pack use have no meaning on one.
136
159
  if (args.channel === "whatsapp" && (args.input !== undefined || args.scenario !== undefined)) {
@@ -147,7 +170,7 @@ export async function start(agent: Agent, argv: string[]): Promise<number> {
147
170
  }
148
171
 
149
172
  if (agent.kit.ensureMandate) {
150
- const ok = await agent.kit.ensureMandate({ agentDir: agent.dir, argv, say, railKind, oneShot: args.input !== undefined, ask: defaultAsk });
173
+ const ok = await agent.kit.ensureMandate({ agentDir: agent.dir, argv, locale, say, railKind, oneShot: args.input !== undefined, ask: defaultAsk });
151
174
  if (!ok) return 1;
152
175
  }
153
176
 
@@ -159,9 +182,9 @@ export async function start(agent: Agent, argv: string[]): Promise<number> {
159
182
  say(err instanceof Error ? err.message : String(err));
160
183
  return 2;
161
184
  }
162
- // A first turn that is a TAP is looked up by the intent the tap stands for, which is what the model is handed.
185
+ // A first turn that is a TAP is looked up by the intent the tap stands for in the run's language, which is what the model is handed.
163
186
  const firstTurn = args.scripted ? conversationScript?.turns[0] : undefined;
164
- const firstInput = args.input ?? firstTurn?.text ?? (firstTurn?.reply ? declaredReplies(loadTemplates(agent)).get(firstTurn.reply.id)?.intent : undefined);
187
+ const firstInput = args.input ?? firstTurn?.text ?? (firstTurn?.reply ? declaredReplies(loadTemplates(agent), WHATSAPP_LANGUAGE[locale]).get(firstTurn.reply.id)?.intent : undefined);
165
188
 
166
189
  // No model: replay the recorded scenario whose first turn is what the person said first.
167
190
  let transcript = args.transcript;
@@ -175,7 +198,7 @@ export async function start(agent: Agent, argv: string[]): Promise<number> {
175
198
  }
176
199
  }
177
200
 
178
- const s = setup(agent, { mode: args.mode, rail: railKind, provider, transcript, now, say });
201
+ const s = setup(agent, { mode: args.mode, rail: railKind, provider, transcript, now, say, locale });
179
202
  if (args.payer) s.payer?.behave(args.payer);
180
203
  const approver = { id: args.user ?? s.kit.labels.defaultUser, channel: "terminal" };
181
204
  const startedAt = Date.now();
@@ -207,18 +230,23 @@ export async function start(agent: Agent, argv: string[]): Promise<number> {
207
230
  handleExecution(execution, { setup: s, approver, decision: args.decision ?? "none", say, waitSeconds: args.wait, simulatePayer: args.simulatePayer, ...(args.json ? { tell: say } : {}) }),
208
231
  );
209
232
  const result = await loop.turn(args.input);
210
- const executions = s.engine.list().filter((e) => e.run_id === s.runId);
233
+ // Counted from the engine, printed whatever the reply says: a recorded reply cannot know what this run found.
234
+ const { executions, refusals, outcome, line } = sayOutcome(s, result.not_run);
235
+ // A request refused before a draft left no execution to describe: said here with the engine's own reason, or the terminal would be silent about it.
236
+ for (const refusal of refusals) say(refusalLine(refusal));
211
237
  const payload = s.kit.oneShotPayload({ setup: s, reply: result.reply, toolCalls: result.tool_calls, executions, startedAt });
212
- if (args.json) stdout.write(JSON.stringify(payload) + "\n");
213
- else stdout.write(result.reply + "\n");
214
- return executions.some((e) => e.state === "executing") ? 3 : 0;
238
+ // `run_outcome`, not `outcome`: the payload is the kit's, and a kit may name a field of its own that.
239
+ if (args.json) stdout.write(JSON.stringify({ ...payload, run_outcome: outcome, refused_before_draft: refusals }) + "\n");
240
+ else stdout.write(`${result.reply}\n${line}\n`);
241
+ return outcomeExitCode(outcome, executions);
215
242
  } finally {
216
243
  closeTerminal();
217
244
  s.close();
218
245
  }
219
246
  }
220
247
 
221
- async function runScenarioCommand(agent: Agent, args: Args, railKind: RailKind, say: (l: string) => void): Promise<number> {
248
+ async function runScenarioCommand(agent: Agent, args: Args, railKind: RailKind, locale: Locale, say: (l: string) => void): Promise<number> {
249
+ const text = CORE_STRINGS[locale];
222
250
  const scenario = loadScenario(agent, args.scenario!);
223
251
  const picksRail = agent.kit.scenarioRail === "requested";
224
252
  const rail: RailKind = picksRail ? railKind : "stub";
@@ -237,10 +265,13 @@ async function runScenarioCommand(agent: Agent, args: Args, railKind: RailKind,
237
265
  say: args.json ? () => undefined : say,
238
266
  ...(picksRail ? { tell: args.json ? () => undefined : (l: string) => void stdout.write(l + "\n") } : {}),
239
267
  waitSeconds: args.wait,
268
+ locale,
240
269
  });
241
270
  const check = checkScenario(scenario, run);
242
- for (const reply of run.replies) say(`agente: ${reply}`);
243
- say(check.ok ? `== ok — ${agent.settlement === "await-payer" ? `${run.cycle_seconds}s — ` : ""}bundle em ${relative(process.cwd(), run.bundle_dir)}` : `== FAIL: ${check.failures.join("; ")}`);
271
+ for (const reply of run.replies) say(text.scenarioReply(reply));
272
+ // Seconds are said only where a clock measured them. On the stub the clock is the scenario's, ticking a second per read: its "16s" is a count of reads in a run that took under one.
273
+ const measured = agent.settlement === "await-payer" && run.rail === "api" ? run.cycle_seconds : undefined;
274
+ say(check.ok ? text.scenarioOk(measured, relative(process.cwd(), run.bundle_dir)) : `== FAIL: ${check.failures.join("; ")}`);
244
275
  results.push({ mode, ok: check.ok, failures: check.failures, run });
245
276
  }
246
277
  if (args.json) stdout.write(JSON.stringify({ scenario: scenario.name, ...(picksRail ? { rail } : {}), results }) + "\n");