@codespar/cli 0.14.1 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (534) hide show
  1. package/README.md +44 -17
  2. package/dist/commands/audit-replay.js +267 -0
  3. package/dist/commands/audit-replay.js.map +1 -0
  4. package/dist/commands/init.js +28 -0
  5. package/dist/commands/init.js.map +1 -1
  6. package/dist/commands/mandate-verify.js +98 -19
  7. package/dist/commands/mandate-verify.js.map +1 -1
  8. package/dist/index.js +17 -3
  9. package/dist/index.js.map +1 -1
  10. package/dist/mandate-codec.js +31 -20
  11. package/dist/mandate-codec.js.map +1 -1
  12. package/dist/surface.js +4 -1
  13. package/dist/surface.js.map +1 -1
  14. package/package.json +1 -1
  15. package/templates/bills-agent/README.md +8 -5
  16. package/templates/bills-agent/agents/bills-agent/.env.example +3 -3
  17. package/templates/bills-agent/agents/bills-agent/AGENTS.md +1 -1
  18. package/templates/bills-agent/agents/bills-agent/CLAUDE.md +1 -1
  19. package/templates/bills-agent/agents/bills-agent/README.md +62 -22
  20. package/templates/bills-agent/agents/bills-agent/SYSTEM_PROMPT.md +1 -1
  21. package/templates/bills-agent/agents/bills-agent/agent.yaml +2 -2
  22. package/templates/bills-agent/agents/bills-agent/package.json +14 -11
  23. package/templates/bills-agent/agents/bills-agent/src/kit.ts +193 -0
  24. package/templates/bills-agent/agents/bills-agent/test/adversarial.test.ts +8 -7
  25. package/templates/bills-agent/agents/bills-agent/test/check.test.ts +19 -2
  26. package/templates/bills-agent/agents/bills-agent/test/cli.test.ts +72 -24
  27. package/templates/bills-agent/agents/bills-agent/test/fixtures/excursao-300.transcript.jsonl +2 -0
  28. package/templates/bills-agent/agents/bills-agent/test/fixtures/material-400.transcript.jsonl +2 -0
  29. package/templates/bills-agent/agents/bills-agent/test/inspect.test.ts +124 -0
  30. package/templates/bills-agent/agents/bills-agent/test/provider.test.ts +25 -0
  31. package/templates/bills-agent/agents/bills-agent/test/scenarios.test.ts +10 -9
  32. package/templates/bills-agent/agents/bills-agent/tsconfig.json +0 -1
  33. package/templates/bills-agent/package.json +5 -2
  34. package/templates/bills-agent/packages/agent-core/README.md +2 -0
  35. package/templates/bills-agent/packages/agent-core/package.json +1 -1
  36. package/templates/bills-agent/packages/agent-core/src/api/charge-rail.ts +27 -6
  37. package/templates/bills-agent/packages/agent-core/src/api/rail.ts +16 -0
  38. package/templates/bills-agent/packages/agent-core/src/api/sandbox-payer.ts +20 -7
  39. package/templates/bills-agent/packages/agent-core/src/approval.ts +16 -2
  40. package/templates/bills-agent/packages/agent-core/src/bundle.ts +50 -4
  41. package/templates/bills-agent/packages/agent-core/src/channels.ts +140 -0
  42. package/templates/bills-agent/packages/agent-core/src/check.ts +90 -8
  43. package/templates/bills-agent/packages/agent-core/src/clock.ts +42 -0
  44. package/templates/bills-agent/packages/agent-core/src/engine.ts +119 -18
  45. package/templates/bills-agent/packages/agent-core/src/hash.ts +13 -0
  46. package/templates/bills-agent/packages/agent-core/src/index.ts +3 -0
  47. package/templates/bills-agent/packages/agent-core/src/manifest.ts +1 -1
  48. package/templates/bills-agent/packages/agent-core/src/rail.ts +16 -2
  49. package/templates/bills-agent/packages/agent-core/src/receipt-verification.ts +401 -0
  50. package/templates/bills-agent/packages/agent-core/src/state-machine.ts +3 -1
  51. package/templates/bills-agent/packages/agent-core/src/stubs/charge-rail.ts +2 -0
  52. package/templates/bills-agent/packages/agent-core/src/stubs/rail.ts +19 -2
  53. package/templates/bills-agent/packages/agent-core/src/types.ts +28 -0
  54. package/templates/bills-agent/packages/agent-core/test/approval.test.ts +36 -2
  55. package/templates/bills-agent/packages/agent-core/test/bundle.test.ts +85 -0
  56. package/templates/bills-agent/packages/agent-core/test/clock.test.ts +25 -0
  57. package/templates/bills-agent/packages/agent-core/test/engine.test.ts +73 -1
  58. package/templates/bills-agent/packages/agent-core/test/fixtures/staging-receipt-keys.json +18 -0
  59. package/templates/bills-agent/packages/agent-core/test/fixtures/staging-receipt.json +24 -0
  60. package/templates/bills-agent/packages/agent-core/test/helpers.ts +1 -1
  61. package/templates/bills-agent/packages/agent-core/test/manifest.test.ts +2 -2
  62. package/templates/bills-agent/packages/agent-core/test/receipt-verification.test.ts +316 -0
  63. package/templates/bills-agent/packages/agent-core/test/receivables.test.ts +51 -0
  64. package/templates/bills-agent/packages/agent-runtime/README.md +68 -0
  65. package/templates/bills-agent/packages/agent-runtime/bin.mjs +32 -0
  66. package/templates/bills-agent/packages/agent-runtime/package.json +23 -0
  67. package/templates/bills-agent/{agents/bills-agent → packages/agent-runtime}/src/adversarial.ts +36 -44
  68. package/templates/bills-agent/packages/agent-runtime/src/agent.ts +68 -0
  69. package/templates/bills-agent/packages/agent-runtime/src/channels/contact.ts +13 -0
  70. package/templates/bills-agent/packages/agent-runtime/src/channels/index.ts +72 -0
  71. package/templates/bills-agent/packages/agent-runtime/src/channels/rules.ts +120 -0
  72. package/templates/bills-agent/packages/agent-runtime/src/channels/types.ts +124 -0
  73. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +358 -0
  74. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +206 -0
  75. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/evidence.ts +109 -0
  76. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +225 -0
  77. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +143 -0
  78. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +47 -0
  79. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +113 -0
  80. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +113 -0
  81. package/templates/bills-agent/packages/agent-runtime/src/cli.ts +98 -0
  82. package/templates/bills-agent/packages/agent-runtime/src/commands/check.ts +15 -0
  83. package/templates/bills-agent/packages/agent-runtime/src/commands/decide.ts +63 -0
  84. package/templates/bills-agent/packages/agent-runtime/src/commands/eval.ts +58 -0
  85. package/templates/bills-agent/packages/agent-runtime/src/commands/inspect.ts +100 -0
  86. package/templates/bills-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +317 -0
  87. package/templates/bills-agent/packages/agent-runtime/src/commands/poll.ts +144 -0
  88. package/templates/bills-agent/packages/agent-runtime/src/commands/reconcile.ts +42 -0
  89. package/templates/bills-agent/packages/agent-runtime/src/commands/rerun.ts +86 -0
  90. package/templates/bills-agent/packages/agent-runtime/src/commands/resume.ts +43 -0
  91. package/templates/bills-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +131 -0
  92. package/templates/bills-agent/packages/agent-runtime/src/commands/start.ts +245 -0
  93. package/templates/bills-agent/packages/agent-runtime/src/commands/verify.ts +129 -0
  94. package/templates/bills-agent/packages/agent-runtime/src/commands/webhook.ts +39 -0
  95. package/templates/bills-agent/packages/agent-runtime/src/default-kit.ts +83 -0
  96. package/templates/bills-agent/packages/agent-runtime/src/index.ts +12 -0
  97. package/templates/bills-agent/packages/agent-runtime/src/inspect.ts +797 -0
  98. package/templates/bills-agent/packages/agent-runtime/src/kit.ts +206 -0
  99. package/templates/{collections-agent/agents/collections-agent → bills-agent/packages/agent-runtime}/src/poll.ts +22 -11
  100. package/templates/{collections-agent/agents/collections-agent → bills-agent/packages/agent-runtime}/src/scenarios.ts +50 -34
  101. package/templates/bills-agent/{agents/bills-agent → packages/agent-runtime}/src/setup.ts +88 -66
  102. package/templates/bills-agent/packages/agent-runtime/src/terminal.ts +154 -0
  103. package/templates/{collections-agent/agents/collections-agent/channels/webhook/index.ts → bills-agent/packages/agent-runtime/src/webhook.ts} +1 -1
  104. package/templates/bills-agent/packages/agent-runtime/test/inspect.test.ts +336 -0
  105. package/templates/bills-agent/packages/agent-runtime/test/verify-cli.test.ts +127 -0
  106. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +232 -0
  107. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +204 -0
  108. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-evidence.test.ts +94 -0
  109. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +174 -0
  110. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-session.test.ts +135 -0
  111. package/templates/bills-agent/packages/agent-runtime/tsconfig.json +9 -0
  112. package/templates/bills-agent/vitest.config.ts +1 -1
  113. package/templates/collections-agent/README.md +8 -5
  114. package/templates/collections-agent/agents/collections-agent/.env.example +14 -0
  115. package/templates/collections-agent/agents/collections-agent/AGENTS.md +6 -4
  116. package/templates/collections-agent/agents/collections-agent/CLAUDE.md +6 -4
  117. package/templates/collections-agent/agents/collections-agent/README.md +184 -16
  118. package/templates/collections-agent/agents/collections-agent/agent.yaml +3 -3
  119. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/README.md +111 -0
  120. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/acordo-1042.json +11 -0
  121. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/acordo-1103.json +11 -0
  122. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/templates.json +23 -0
  123. package/templates/collections-agent/agents/collections-agent/package.json +12 -10
  124. package/templates/collections-agent/agents/collections-agent/runbook.md +52 -1
  125. package/templates/collections-agent/agents/collections-agent/src/kit.ts +265 -0
  126. package/templates/collections-agent/agents/collections-agent/test/adversarial.test.ts +9 -8
  127. package/templates/collections-agent/agents/collections-agent/test/check.test.ts +43 -1
  128. package/templates/collections-agent/agents/collections-agent/test/cli.test.ts +56 -18
  129. package/templates/collections-agent/agents/collections-agent/test/fixtures/agreed-1042-awaiting-payer.transcript.jsonl +4 -0
  130. package/templates/collections-agent/agents/collections-agent/test/scenarios.test.ts +11 -10
  131. package/templates/collections-agent/agents/collections-agent/test/webhook.test.ts +4 -7
  132. package/templates/collections-agent/agents/collections-agent/test/whatsapp-poll.test.ts +271 -0
  133. package/templates/collections-agent/agents/collections-agent/test/whatsapp.test.ts +213 -0
  134. package/templates/collections-agent/agents/collections-agent/tsconfig.json +0 -1
  135. package/templates/collections-agent/package.json +3 -1
  136. package/templates/collections-agent/packages/agent-core/README.md +2 -0
  137. package/templates/collections-agent/packages/agent-core/package.json +1 -1
  138. package/templates/collections-agent/packages/agent-core/src/api/charge-rail.ts +27 -6
  139. package/templates/collections-agent/packages/agent-core/src/api/rail.ts +16 -0
  140. package/templates/collections-agent/packages/agent-core/src/api/sandbox-payer.ts +20 -7
  141. package/templates/collections-agent/packages/agent-core/src/approval.ts +16 -2
  142. package/templates/collections-agent/packages/agent-core/src/bundle.ts +50 -4
  143. package/templates/collections-agent/packages/agent-core/src/channels.ts +140 -0
  144. package/templates/collections-agent/packages/agent-core/src/check.ts +90 -8
  145. package/templates/collections-agent/packages/agent-core/src/clock.ts +42 -0
  146. package/templates/collections-agent/packages/agent-core/src/engine.ts +119 -18
  147. package/templates/collections-agent/packages/agent-core/src/hash.ts +13 -0
  148. package/templates/collections-agent/packages/agent-core/src/index.ts +3 -0
  149. package/templates/collections-agent/packages/agent-core/src/manifest.ts +1 -1
  150. package/templates/collections-agent/packages/agent-core/src/rail.ts +16 -2
  151. package/templates/collections-agent/packages/agent-core/src/receipt-verification.ts +401 -0
  152. package/templates/collections-agent/packages/agent-core/src/state-machine.ts +3 -1
  153. package/templates/collections-agent/packages/agent-core/src/stubs/charge-rail.ts +2 -0
  154. package/templates/collections-agent/packages/agent-core/src/stubs/rail.ts +19 -2
  155. package/templates/collections-agent/packages/agent-core/src/types.ts +28 -0
  156. package/templates/collections-agent/packages/agent-core/test/approval.test.ts +36 -2
  157. package/templates/collections-agent/packages/agent-core/test/bundle.test.ts +85 -0
  158. package/templates/collections-agent/packages/agent-core/test/clock.test.ts +25 -0
  159. package/templates/collections-agent/packages/agent-core/test/engine.test.ts +73 -1
  160. package/templates/collections-agent/packages/agent-core/test/fixtures/staging-receipt-keys.json +18 -0
  161. package/templates/collections-agent/packages/agent-core/test/fixtures/staging-receipt.json +24 -0
  162. package/templates/collections-agent/packages/agent-core/test/helpers.ts +1 -1
  163. package/templates/collections-agent/packages/agent-core/test/manifest.test.ts +2 -2
  164. package/templates/collections-agent/packages/agent-core/test/receipt-verification.test.ts +316 -0
  165. package/templates/collections-agent/packages/agent-core/test/receivables.test.ts +51 -0
  166. package/templates/collections-agent/packages/agent-runtime/README.md +68 -0
  167. package/templates/collections-agent/packages/agent-runtime/bin.mjs +32 -0
  168. package/templates/collections-agent/packages/agent-runtime/package.json +23 -0
  169. package/templates/collections-agent/{agents/collections-agent → packages/agent-runtime}/src/adversarial.ts +29 -50
  170. package/templates/collections-agent/packages/agent-runtime/src/agent.ts +68 -0
  171. package/templates/collections-agent/packages/agent-runtime/src/channels/contact.ts +13 -0
  172. package/templates/collections-agent/packages/agent-runtime/src/channels/index.ts +72 -0
  173. package/templates/collections-agent/packages/agent-runtime/src/channels/rules.ts +120 -0
  174. package/templates/collections-agent/packages/agent-runtime/src/channels/types.ts +124 -0
  175. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +358 -0
  176. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +206 -0
  177. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/evidence.ts +109 -0
  178. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +225 -0
  179. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +143 -0
  180. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +47 -0
  181. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +113 -0
  182. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +113 -0
  183. package/templates/collections-agent/packages/agent-runtime/src/cli.ts +98 -0
  184. package/templates/collections-agent/packages/agent-runtime/src/commands/check.ts +15 -0
  185. package/templates/collections-agent/packages/agent-runtime/src/commands/decide.ts +63 -0
  186. package/templates/collections-agent/packages/agent-runtime/src/commands/eval.ts +58 -0
  187. package/templates/collections-agent/packages/agent-runtime/src/commands/inspect.ts +100 -0
  188. package/templates/collections-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +317 -0
  189. package/templates/collections-agent/packages/agent-runtime/src/commands/poll.ts +144 -0
  190. package/templates/collections-agent/packages/agent-runtime/src/commands/reconcile.ts +42 -0
  191. package/templates/collections-agent/packages/agent-runtime/src/commands/rerun.ts +86 -0
  192. package/templates/collections-agent/packages/agent-runtime/src/commands/resume.ts +43 -0
  193. package/templates/collections-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +131 -0
  194. package/templates/collections-agent/packages/agent-runtime/src/commands/start.ts +245 -0
  195. package/templates/collections-agent/packages/agent-runtime/src/commands/verify.ts +129 -0
  196. package/templates/collections-agent/packages/agent-runtime/src/commands/webhook.ts +39 -0
  197. package/templates/collections-agent/packages/agent-runtime/src/default-kit.ts +83 -0
  198. package/templates/collections-agent/packages/agent-runtime/src/index.ts +12 -0
  199. package/templates/collections-agent/packages/agent-runtime/src/inspect.ts +797 -0
  200. package/templates/collections-agent/packages/agent-runtime/src/kit.ts +206 -0
  201. package/templates/collections-agent/packages/agent-runtime/src/poll.ts +105 -0
  202. package/templates/{bills-agent/agents/bills-agent → collections-agent/packages/agent-runtime}/src/scenarios.ts +98 -26
  203. package/templates/collections-agent/packages/agent-runtime/src/setup.ts +229 -0
  204. package/templates/collections-agent/packages/agent-runtime/src/terminal.ts +154 -0
  205. package/templates/collections-agent/packages/agent-runtime/src/webhook.ts +131 -0
  206. package/templates/collections-agent/packages/agent-runtime/test/inspect.test.ts +336 -0
  207. package/templates/collections-agent/packages/agent-runtime/test/verify-cli.test.ts +127 -0
  208. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +232 -0
  209. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +204 -0
  210. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-evidence.test.ts +94 -0
  211. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +174 -0
  212. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-session.test.ts +135 -0
  213. package/templates/collections-agent/packages/agent-runtime/tsconfig.json +9 -0
  214. package/templates/collections-agent/vitest.config.ts +1 -1
  215. package/templates/hello-agent/LICENSE +21 -0
  216. package/templates/hello-agent/README.md +23 -0
  217. package/templates/hello-agent/_gitignore +10 -0
  218. package/templates/hello-agent/agents/hello-agent/.env.example +5 -0
  219. package/templates/hello-agent/agents/hello-agent/AGENTS.md +15 -0
  220. package/templates/hello-agent/agents/hello-agent/CLAUDE.md +15 -0
  221. package/templates/hello-agent/agents/hello-agent/README.md +33 -0
  222. package/templates/hello-agent/agents/hello-agent/SYSTEM_PROMPT.md +19 -0
  223. package/templates/hello-agent/agents/hello-agent/agent.yaml +19 -0
  224. package/templates/hello-agent/agents/hello-agent/evals/adversarial/beneficiary-swap.json +6 -0
  225. package/templates/hello-agent/agents/hello-agent/evals/adversarial/beneficiary-swap.transcript.jsonl +2 -0
  226. package/templates/hello-agent/agents/hello-agent/evals/adversarial/exfiltration.json +6 -0
  227. package/templates/hello-agent/agents/hello-agent/evals/adversarial/exfiltration.transcript.jsonl +2 -0
  228. package/templates/hello-agent/agents/hello-agent/evals/adversarial/false-authority.json +6 -0
  229. package/templates/hello-agent/agents/hello-agent/evals/adversarial/false-authority.transcript.jsonl +2 -0
  230. package/templates/hello-agent/agents/hello-agent/evals/adversarial/fractioning.json +6 -0
  231. package/templates/hello-agent/agents/hello-agent/evals/adversarial/fractioning.transcript.jsonl +2 -0
  232. package/templates/hello-agent/agents/hello-agent/evals/adversarial/model-total.json +6 -0
  233. package/templates/hello-agent/agents/hello-agent/evals/adversarial/model-total.transcript.jsonl +2 -0
  234. package/templates/hello-agent/agents/hello-agent/evals/adversarial/prompt-injection.json +6 -0
  235. package/templates/hello-agent/agents/hello-agent/evals/adversarial/prompt-injection.transcript.jsonl +2 -0
  236. package/templates/hello-agent/agents/hello-agent/evals/adversarial/webhook-replay.json +6 -0
  237. package/templates/hello-agent/agents/hello-agent/evals/eval.yaml +7 -0
  238. package/templates/hello-agent/agents/hello-agent/guardrails.json +8 -0
  239. package/templates/hello-agent/agents/hello-agent/mandate.example.json +17 -0
  240. package/templates/hello-agent/agents/hello-agent/package.json +19 -0
  241. package/templates/hello-agent/agents/hello-agent/runbook.md +10 -0
  242. package/templates/hello-agent/agents/hello-agent/scenarios/happy-path.json +6 -0
  243. package/templates/hello-agent/agents/hello-agent/scenarios/happy-path.transcript.jsonl +2 -0
  244. package/templates/hello-agent/agents/hello-agent/scenarios/prompt-injection.json +6 -0
  245. package/templates/hello-agent/agents/hello-agent/scenarios/prompt-injection.transcript.jsonl +2 -0
  246. package/templates/hello-agent/agents/hello-agent/src/bills.ts +23 -0
  247. package/templates/hello-agent/agents/hello-agent/src/kit.ts +33 -0
  248. package/templates/hello-agent/agents/hello-agent/tools.json +11 -0
  249. package/templates/hello-agent/agents/hello-agent/tsconfig.json +9 -0
  250. package/templates/hello-agent/package.json +30 -0
  251. package/templates/hello-agent/packages/agent-core/README.md +21 -0
  252. package/templates/hello-agent/packages/agent-core/package.json +24 -0
  253. package/templates/hello-agent/packages/agent-core/src/agent.ts +125 -0
  254. package/templates/hello-agent/packages/agent-core/src/api/charge-rail.ts +175 -0
  255. package/templates/hello-agent/packages/agent-core/src/api/client.ts +53 -0
  256. package/templates/hello-agent/packages/agent-core/src/api/mandate-status.ts +58 -0
  257. package/templates/hello-agent/packages/agent-core/src/api/rail.ts +117 -0
  258. package/templates/hello-agent/packages/agent-core/src/api/sandbox-payer.ts +58 -0
  259. package/templates/hello-agent/packages/agent-core/src/approval.ts +123 -0
  260. package/templates/hello-agent/packages/agent-core/src/bundle.ts +159 -0
  261. package/templates/hello-agent/packages/agent-core/src/channels.ts +140 -0
  262. package/templates/hello-agent/packages/agent-core/src/check.ts +253 -0
  263. package/templates/hello-agent/packages/agent-core/src/clock.ts +42 -0
  264. package/templates/hello-agent/packages/agent-core/src/engine.ts +885 -0
  265. package/templates/hello-agent/packages/agent-core/src/escalate.ts +85 -0
  266. package/templates/hello-agent/packages/agent-core/src/events.ts +40 -0
  267. package/templates/hello-agent/packages/agent-core/src/guardrails.ts +45 -0
  268. package/templates/hello-agent/packages/agent-core/src/hash.ts +62 -0
  269. package/templates/hello-agent/packages/agent-core/src/ids.ts +10 -0
  270. package/templates/hello-agent/packages/agent-core/src/index.ts +32 -0
  271. package/templates/hello-agent/packages/agent-core/src/mandate.ts +100 -0
  272. package/templates/hello-agent/packages/agent-core/src/manifest.ts +76 -0
  273. package/templates/hello-agent/packages/agent-core/src/providers/anthropic.ts +76 -0
  274. package/templates/hello-agent/packages/agent-core/src/providers/replay.ts +63 -0
  275. package/templates/hello-agent/packages/agent-core/src/providers/types.ts +39 -0
  276. package/templates/hello-agent/packages/agent-core/src/rail.ts +101 -0
  277. package/templates/hello-agent/packages/agent-core/src/receipt-verification.ts +401 -0
  278. package/templates/hello-agent/packages/agent-core/src/revocation.ts +30 -0
  279. package/templates/hello-agent/packages/agent-core/src/secrets.ts +30 -0
  280. package/templates/hello-agent/packages/agent-core/src/state/store.ts +307 -0
  281. package/templates/hello-agent/packages/agent-core/src/state-machine.ts +148 -0
  282. package/templates/hello-agent/packages/agent-core/src/stubs/charge-rail.ts +195 -0
  283. package/templates/hello-agent/packages/agent-core/src/stubs/mandate-status.ts +57 -0
  284. package/templates/hello-agent/packages/agent-core/src/stubs/rail.ts +141 -0
  285. package/templates/hello-agent/packages/agent-core/src/tools.ts +55 -0
  286. package/templates/hello-agent/packages/agent-core/src/types.ts +134 -0
  287. package/templates/hello-agent/packages/agent-core/test/approval.test.ts +117 -0
  288. package/templates/hello-agent/packages/agent-core/test/bundle.test.ts +85 -0
  289. package/templates/hello-agent/packages/agent-core/test/clock.test.ts +25 -0
  290. package/templates/hello-agent/packages/agent-core/test/engine.test.ts +596 -0
  291. package/templates/hello-agent/packages/agent-core/test/escalate.test.ts +42 -0
  292. package/templates/hello-agent/packages/agent-core/test/fixtures/staging-receipt-keys.json +18 -0
  293. package/templates/hello-agent/packages/agent-core/test/fixtures/staging-receipt.json +24 -0
  294. package/templates/hello-agent/packages/agent-core/test/helpers.ts +139 -0
  295. package/templates/hello-agent/packages/agent-core/test/mandate-status.test.ts +153 -0
  296. package/templates/hello-agent/packages/agent-core/test/manifest.test.ts +45 -0
  297. package/templates/hello-agent/packages/agent-core/test/receipt-verification.test.ts +316 -0
  298. package/templates/hello-agent/packages/agent-core/test/receivables.test.ts +316 -0
  299. package/templates/hello-agent/packages/agent-core/test/secrets.test.ts +28 -0
  300. package/templates/hello-agent/packages/agent-core/test/state-machine.test.ts +67 -0
  301. package/templates/hello-agent/packages/agent-core/test/transitions.type-test.ts +59 -0
  302. package/templates/hello-agent/packages/agent-core/tsconfig.json +10 -0
  303. package/templates/hello-agent/packages/agent-runtime/README.md +68 -0
  304. package/templates/hello-agent/packages/agent-runtime/bin.mjs +32 -0
  305. package/templates/hello-agent/packages/agent-runtime/package.json +23 -0
  306. package/templates/hello-agent/packages/agent-runtime/src/adversarial.ts +169 -0
  307. package/templates/hello-agent/packages/agent-runtime/src/agent.ts +68 -0
  308. package/templates/hello-agent/packages/agent-runtime/src/channels/contact.ts +13 -0
  309. package/templates/hello-agent/packages/agent-runtime/src/channels/index.ts +72 -0
  310. package/templates/hello-agent/packages/agent-runtime/src/channels/rules.ts +120 -0
  311. package/templates/hello-agent/packages/agent-runtime/src/channels/types.ts +124 -0
  312. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +358 -0
  313. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +206 -0
  314. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/evidence.ts +109 -0
  315. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +225 -0
  316. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +143 -0
  317. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +47 -0
  318. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +113 -0
  319. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +113 -0
  320. package/templates/hello-agent/packages/agent-runtime/src/cli.ts +98 -0
  321. package/templates/hello-agent/packages/agent-runtime/src/commands/check.ts +15 -0
  322. package/templates/hello-agent/packages/agent-runtime/src/commands/decide.ts +63 -0
  323. package/templates/hello-agent/packages/agent-runtime/src/commands/eval.ts +58 -0
  324. package/templates/hello-agent/packages/agent-runtime/src/commands/inspect.ts +100 -0
  325. package/templates/hello-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +317 -0
  326. package/templates/hello-agent/packages/agent-runtime/src/commands/poll.ts +144 -0
  327. package/templates/hello-agent/packages/agent-runtime/src/commands/reconcile.ts +42 -0
  328. package/templates/hello-agent/packages/agent-runtime/src/commands/rerun.ts +86 -0
  329. package/templates/hello-agent/packages/agent-runtime/src/commands/resume.ts +43 -0
  330. package/templates/hello-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +131 -0
  331. package/templates/hello-agent/packages/agent-runtime/src/commands/start.ts +245 -0
  332. package/templates/hello-agent/packages/agent-runtime/src/commands/verify.ts +129 -0
  333. package/templates/hello-agent/packages/agent-runtime/src/commands/webhook.ts +39 -0
  334. package/templates/hello-agent/packages/agent-runtime/src/default-kit.ts +83 -0
  335. package/templates/hello-agent/packages/agent-runtime/src/index.ts +12 -0
  336. package/templates/hello-agent/packages/agent-runtime/src/inspect.ts +797 -0
  337. package/templates/hello-agent/packages/agent-runtime/src/kit.ts +206 -0
  338. package/templates/hello-agent/packages/agent-runtime/src/poll.ts +105 -0
  339. package/templates/hello-agent/packages/agent-runtime/src/scenarios.ts +268 -0
  340. package/templates/hello-agent/packages/agent-runtime/src/setup.ts +229 -0
  341. package/templates/hello-agent/packages/agent-runtime/src/terminal.ts +154 -0
  342. package/templates/hello-agent/packages/agent-runtime/src/webhook.ts +131 -0
  343. package/templates/hello-agent/packages/agent-runtime/test/inspect.test.ts +336 -0
  344. package/templates/hello-agent/packages/agent-runtime/test/verify-cli.test.ts +127 -0
  345. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +232 -0
  346. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +204 -0
  347. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-evidence.test.ts +94 -0
  348. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +174 -0
  349. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-session.test.ts +135 -0
  350. package/templates/hello-agent/packages/agent-runtime/tsconfig.json +9 -0
  351. package/templates/hello-agent/tsconfig.base.json +16 -0
  352. package/templates/hello-agent/vitest.config.ts +12 -0
  353. package/templates/kits.lock.json +60 -12
  354. package/templates/supplier-payments-agent/LICENSE +21 -0
  355. package/templates/supplier-payments-agent/README.md +23 -0
  356. package/templates/supplier-payments-agent/_gitignore +10 -0
  357. package/templates/supplier-payments-agent/agents/supplier-payments-agent/.env.example +7 -0
  358. package/templates/supplier-payments-agent/agents/supplier-payments-agent/AGENTS.md +21 -0
  359. package/templates/supplier-payments-agent/agents/supplier-payments-agent/CLAUDE.md +21 -0
  360. package/templates/supplier-payments-agent/agents/supplier-payments-agent/README.md +118 -0
  361. package/templates/supplier-payments-agent/agents/supplier-payments-agent/SYSTEM_PROMPT.md +29 -0
  362. package/templates/supplier-payments-agent/agents/supplier-payments-agent/agent.yaml +26 -0
  363. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/batch-tampering.json +12 -0
  364. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/batch-tampering.transcript.jsonl +3 -0
  365. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/beneficiary-swap-mandate.json +9 -0
  366. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/beneficiary-swap.json +10 -0
  367. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/beneficiary-swap.transcript.jsonl +2 -0
  368. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/exfiltration.json +13 -0
  369. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/exfiltration.transcript.jsonl +3 -0
  370. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/false-authority.json +9 -0
  371. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/false-authority.transcript.jsonl +3 -0
  372. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/fractioning.json +15 -0
  373. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/fractioning.transcript.jsonl +6 -0
  374. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/model-total.json +10 -0
  375. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/model-total.transcript.jsonl +2 -0
  376. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/prompt-injection.json +9 -0
  377. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/prompt-injection.transcript.jsonl +2 -0
  378. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/webhook-replay.json +9 -0
  379. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/eval.yaml +9 -0
  380. package/templates/supplier-payments-agent/agents/supplier-payments-agent/guardrails.json +15 -0
  381. package/templates/supplier-payments-agent/agents/supplier-payments-agent/mandate.example.json +70 -0
  382. package/templates/supplier-payments-agent/agents/supplier-payments-agent/package.json +26 -0
  383. package/templates/supplier-payments-agent/agents/supplier-payments-agent/runbook.md +19 -0
  384. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/beneficiary-not-allowed.json +14 -0
  385. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/beneficiary-not-allowed.transcript.jsonl +2 -0
  386. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/cap-exceeded.json +12 -0
  387. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/cap-exceeded.transcript.jsonl +2 -0
  388. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/escalated-above-threshold.json +20 -0
  389. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/escalated-above-threshold.transcript.jsonl +7 -0
  390. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/happy-path.json +19 -0
  391. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/happy-path.transcript.jsonl +3 -0
  392. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/mandate-revoked.json +21 -0
  393. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/mandate-revoked.transcript.jsonl +9 -0
  394. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/partial-batch-failure.json +21 -0
  395. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/partial-batch-failure.transcript.jsonl +3 -0
  396. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/prompt-injection.json +12 -0
  397. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/prompt-injection.transcript.jsonl +2 -0
  398. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/kit.ts +176 -0
  399. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/modules/batch-payout.ts +345 -0
  400. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/modules/pix-out.ts +118 -0
  401. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/payables.ts +76 -0
  402. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/adversarial.test.ts +53 -0
  403. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/batch.test.ts +384 -0
  404. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/check.test.ts +109 -0
  405. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/scenarios.test.ts +81 -0
  406. package/templates/supplier-payments-agent/agents/supplier-payments-agent/tools.json +53 -0
  407. package/templates/supplier-payments-agent/agents/supplier-payments-agent/tsconfig.json +9 -0
  408. package/templates/supplier-payments-agent/package.json +36 -0
  409. package/templates/supplier-payments-agent/packages/agent-core/README.md +21 -0
  410. package/templates/supplier-payments-agent/packages/agent-core/package.json +24 -0
  411. package/templates/supplier-payments-agent/packages/agent-core/src/agent.ts +125 -0
  412. package/templates/supplier-payments-agent/packages/agent-core/src/api/charge-rail.ts +175 -0
  413. package/templates/supplier-payments-agent/packages/agent-core/src/api/client.ts +53 -0
  414. package/templates/supplier-payments-agent/packages/agent-core/src/api/mandate-status.ts +58 -0
  415. package/templates/supplier-payments-agent/packages/agent-core/src/api/rail.ts +117 -0
  416. package/templates/supplier-payments-agent/packages/agent-core/src/api/sandbox-payer.ts +58 -0
  417. package/templates/supplier-payments-agent/packages/agent-core/src/approval.ts +123 -0
  418. package/templates/supplier-payments-agent/packages/agent-core/src/bundle.ts +159 -0
  419. package/templates/supplier-payments-agent/packages/agent-core/src/channels.ts +140 -0
  420. package/templates/supplier-payments-agent/packages/agent-core/src/check.ts +253 -0
  421. package/templates/supplier-payments-agent/packages/agent-core/src/clock.ts +42 -0
  422. package/templates/supplier-payments-agent/packages/agent-core/src/engine.ts +885 -0
  423. package/templates/supplier-payments-agent/packages/agent-core/src/escalate.ts +85 -0
  424. package/templates/supplier-payments-agent/packages/agent-core/src/events.ts +40 -0
  425. package/templates/supplier-payments-agent/packages/agent-core/src/guardrails.ts +45 -0
  426. package/templates/supplier-payments-agent/packages/agent-core/src/hash.ts +62 -0
  427. package/templates/supplier-payments-agent/packages/agent-core/src/ids.ts +10 -0
  428. package/templates/supplier-payments-agent/packages/agent-core/src/index.ts +32 -0
  429. package/templates/supplier-payments-agent/packages/agent-core/src/mandate.ts +100 -0
  430. package/templates/supplier-payments-agent/packages/agent-core/src/manifest.ts +76 -0
  431. package/templates/supplier-payments-agent/packages/agent-core/src/providers/anthropic.ts +76 -0
  432. package/templates/supplier-payments-agent/packages/agent-core/src/providers/replay.ts +63 -0
  433. package/templates/supplier-payments-agent/packages/agent-core/src/providers/types.ts +39 -0
  434. package/templates/supplier-payments-agent/packages/agent-core/src/rail.ts +101 -0
  435. package/templates/supplier-payments-agent/packages/agent-core/src/receipt-verification.ts +401 -0
  436. package/templates/supplier-payments-agent/packages/agent-core/src/revocation.ts +30 -0
  437. package/templates/supplier-payments-agent/packages/agent-core/src/secrets.ts +30 -0
  438. package/templates/supplier-payments-agent/packages/agent-core/src/state/store.ts +307 -0
  439. package/templates/supplier-payments-agent/packages/agent-core/src/state-machine.ts +148 -0
  440. package/templates/supplier-payments-agent/packages/agent-core/src/stubs/charge-rail.ts +195 -0
  441. package/templates/supplier-payments-agent/packages/agent-core/src/stubs/mandate-status.ts +57 -0
  442. package/templates/supplier-payments-agent/packages/agent-core/src/stubs/rail.ts +141 -0
  443. package/templates/supplier-payments-agent/packages/agent-core/src/tools.ts +55 -0
  444. package/templates/supplier-payments-agent/packages/agent-core/src/types.ts +134 -0
  445. package/templates/supplier-payments-agent/packages/agent-core/test/approval.test.ts +117 -0
  446. package/templates/supplier-payments-agent/packages/agent-core/test/bundle.test.ts +85 -0
  447. package/templates/supplier-payments-agent/packages/agent-core/test/clock.test.ts +25 -0
  448. package/templates/supplier-payments-agent/packages/agent-core/test/engine.test.ts +596 -0
  449. package/templates/supplier-payments-agent/packages/agent-core/test/escalate.test.ts +42 -0
  450. package/templates/supplier-payments-agent/packages/agent-core/test/fixtures/staging-receipt-keys.json +18 -0
  451. package/templates/supplier-payments-agent/packages/agent-core/test/fixtures/staging-receipt.json +24 -0
  452. package/templates/supplier-payments-agent/packages/agent-core/test/helpers.ts +139 -0
  453. package/templates/supplier-payments-agent/packages/agent-core/test/mandate-status.test.ts +153 -0
  454. package/templates/supplier-payments-agent/packages/agent-core/test/manifest.test.ts +45 -0
  455. package/templates/supplier-payments-agent/packages/agent-core/test/receipt-verification.test.ts +316 -0
  456. package/templates/supplier-payments-agent/packages/agent-core/test/receivables.test.ts +316 -0
  457. package/templates/supplier-payments-agent/packages/agent-core/test/secrets.test.ts +28 -0
  458. package/templates/supplier-payments-agent/packages/agent-core/test/state-machine.test.ts +67 -0
  459. package/templates/supplier-payments-agent/packages/agent-core/test/transitions.type-test.ts +59 -0
  460. package/templates/supplier-payments-agent/packages/agent-core/tsconfig.json +10 -0
  461. package/templates/supplier-payments-agent/packages/agent-runtime/README.md +68 -0
  462. package/templates/supplier-payments-agent/packages/agent-runtime/bin.mjs +32 -0
  463. package/templates/supplier-payments-agent/packages/agent-runtime/package.json +23 -0
  464. package/templates/supplier-payments-agent/packages/agent-runtime/src/adversarial.ts +169 -0
  465. package/templates/supplier-payments-agent/packages/agent-runtime/src/agent.ts +68 -0
  466. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/contact.ts +13 -0
  467. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/index.ts +72 -0
  468. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/rules.ts +120 -0
  469. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/types.ts +124 -0
  470. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +358 -0
  471. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +206 -0
  472. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/evidence.ts +109 -0
  473. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +225 -0
  474. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +143 -0
  475. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +47 -0
  476. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +113 -0
  477. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +113 -0
  478. package/templates/supplier-payments-agent/packages/agent-runtime/src/cli.ts +98 -0
  479. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/check.ts +15 -0
  480. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/decide.ts +63 -0
  481. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/eval.ts +58 -0
  482. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/inspect.ts +100 -0
  483. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +317 -0
  484. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/poll.ts +144 -0
  485. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/reconcile.ts +42 -0
  486. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/rerun.ts +86 -0
  487. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/resume.ts +43 -0
  488. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +131 -0
  489. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/start.ts +245 -0
  490. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/verify.ts +129 -0
  491. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/webhook.ts +39 -0
  492. package/templates/supplier-payments-agent/packages/agent-runtime/src/default-kit.ts +83 -0
  493. package/templates/supplier-payments-agent/packages/agent-runtime/src/index.ts +12 -0
  494. package/templates/supplier-payments-agent/packages/agent-runtime/src/inspect.ts +797 -0
  495. package/templates/supplier-payments-agent/packages/agent-runtime/src/kit.ts +206 -0
  496. package/templates/supplier-payments-agent/packages/agent-runtime/src/poll.ts +105 -0
  497. package/templates/supplier-payments-agent/packages/agent-runtime/src/scenarios.ts +268 -0
  498. package/templates/supplier-payments-agent/packages/agent-runtime/src/setup.ts +229 -0
  499. package/templates/supplier-payments-agent/packages/agent-runtime/src/terminal.ts +154 -0
  500. package/templates/supplier-payments-agent/packages/agent-runtime/src/webhook.ts +131 -0
  501. package/templates/supplier-payments-agent/packages/agent-runtime/test/inspect.test.ts +336 -0
  502. package/templates/supplier-payments-agent/packages/agent-runtime/test/verify-cli.test.ts +127 -0
  503. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +232 -0
  504. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +204 -0
  505. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-evidence.test.ts +94 -0
  506. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +174 -0
  507. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-session.test.ts +135 -0
  508. package/templates/supplier-payments-agent/packages/agent-runtime/tsconfig.json +9 -0
  509. package/templates/supplier-payments-agent/tsconfig.base.json +16 -0
  510. package/templates/supplier-payments-agent/vitest.config.ts +12 -0
  511. package/templates/bills-agent/agents/bills-agent/channels/terminal/index.ts +0 -108
  512. package/templates/bills-agent/agents/bills-agent/src/commands/approve.ts +0 -9
  513. package/templates/bills-agent/agents/bills-agent/src/commands/check.ts +0 -13
  514. package/templates/bills-agent/agents/bills-agent/src/commands/consent.ts +0 -26
  515. package/templates/bills-agent/agents/bills-agent/src/commands/decide.ts +0 -45
  516. package/templates/bills-agent/agents/bills-agent/src/commands/deny.ts +0 -7
  517. package/templates/bills-agent/agents/bills-agent/src/commands/eval.ts +0 -37
  518. package/templates/bills-agent/agents/bills-agent/src/commands/reconcile.ts +0 -38
  519. package/templates/bills-agent/agents/bills-agent/src/commands/rerun.ts +0 -65
  520. package/templates/bills-agent/agents/bills-agent/src/commands/resume.ts +0 -30
  521. package/templates/bills-agent/agents/bills-agent/src/main.ts +0 -185
  522. package/templates/collections-agent/agents/collections-agent/channels/terminal/index.ts +0 -178
  523. package/templates/collections-agent/agents/collections-agent/src/commands/approve.ts +0 -10
  524. package/templates/collections-agent/agents/collections-agent/src/commands/check.ts +0 -13
  525. package/templates/collections-agent/agents/collections-agent/src/commands/decide.ts +0 -48
  526. package/templates/collections-agent/agents/collections-agent/src/commands/deny.ts +0 -7
  527. package/templates/collections-agent/agents/collections-agent/src/commands/eval.ts +0 -39
  528. package/templates/collections-agent/agents/collections-agent/src/commands/poll.ts +0 -35
  529. package/templates/collections-agent/agents/collections-agent/src/commands/reconcile.ts +0 -38
  530. package/templates/collections-agent/agents/collections-agent/src/commands/rerun.ts +0 -55
  531. package/templates/collections-agent/agents/collections-agent/src/commands/resume.ts +0 -30
  532. package/templates/collections-agent/agents/collections-agent/src/commands/webhook.ts +0 -36
  533. package/templates/collections-agent/agents/collections-agent/src/main.ts +0 -193
  534. package/templates/collections-agent/agents/collections-agent/src/setup.ts +0 -250
@@ -0,0 +1,98 @@
1
+ /**
2
+ * `codespar-agent <command> [args]`. The agent is the working directory; the
3
+ * command is this runner's, the same for every agent. What differs between
4
+ * agents is behind `kit`.
5
+ */
6
+ import { stderr } from "node:process";
7
+ import { loadAgent, type Agent } from "./agent.js";
8
+ import { readDotEnv } from "./setup.js";
9
+ import { check } from "./commands/check.js";
10
+ import { decide } from "./commands/decide.js";
11
+ import { runEval } from "./commands/eval.js";
12
+ import { inspect } from "./commands/inspect.js";
13
+ import { poll } from "./commands/poll.js";
14
+ import { reconcile } from "./commands/reconcile.js";
15
+ import { rerun } from "./commands/rerun.js";
16
+ import { resume } from "./commands/resume.js";
17
+ import { start } from "./commands/start.js";
18
+ import { verify } from "./commands/verify.js";
19
+ import { webhook } from "./commands/webhook.js";
20
+
21
+ const COMMANDS = ["start", "consent", "approve", "deny", "resume", "rerun", "reconcile", "inspect", "poll", "webhook", "check", "eval", "verify"] as const;
22
+
23
+ /** Commands that are not about an agent. `verify` reads a receipt file and a
24
+ * public key set, which is all a party outside CodeSpar has: requiring an
25
+ * `agent.yaml` above the working directory would mean the verifier needed the
26
+ * agent that produced the receipt, and the whole point is that it does not. */
27
+ const AGENTLESS: readonly string[] = ["verify"];
28
+
29
+ export async function main(argv: string[] = process.argv.slice(2)): Promise<number> {
30
+ const rest = [...argv];
31
+ let dir: string | undefined;
32
+ const at = rest.indexOf("--agent");
33
+ if (at >= 0) {
34
+ dir = rest[at + 1];
35
+ rest.splice(at, dir === undefined ? 1 : 2);
36
+ }
37
+ const first = rest[0];
38
+ const command = first !== undefined && !first.startsWith("-") ? rest.shift()! : "start";
39
+ if (!(COMMANDS as readonly string[]).includes(command)) {
40
+ stderr.write(`unknown command ${command}; one of: ${COMMANDS.join(", ")}\n`);
41
+ return 2;
42
+ }
43
+ if (AGENTLESS.includes(command)) return verify(rest);
44
+ const agent = await loadAgent(dir);
45
+ readDotEnv(agent.dir);
46
+ return run(agent, command, rest);
47
+ }
48
+
49
+ async function run(agent: Agent, command: string, argv: string[]): Promise<number> {
50
+ const awaitsPayer = agent.settlement === "await-payer";
51
+ switch (command) {
52
+ case "start":
53
+ return start(agent, argv);
54
+ case "consent": {
55
+ if (!agent.kit.consent) {
56
+ stderr.write(`${agent.slug}: this agent has no consent step (its policy is its own file, not a signed mandate)\n`);
57
+ return 2;
58
+ }
59
+ return agent.kit.consent({ agentDir: agent.dir, argv, say: (l) => void stderr.write(l + "\n") });
60
+ }
61
+ case "approve":
62
+ return decide(agent, "approve", argv);
63
+ case "deny":
64
+ return decide(agent, "deny", argv);
65
+ case "resume":
66
+ return resume(agent, argv);
67
+ case "rerun":
68
+ return rerun(agent, argv);
69
+ case "reconcile":
70
+ return reconcile(agent, argv);
71
+ case "inspect":
72
+ return inspect(agent, argv);
73
+ case "check":
74
+ return check(agent, argv);
75
+ case "eval":
76
+ return runEval(agent, argv);
77
+ case "poll":
78
+ case "webhook": {
79
+ if (!awaitsPayer) {
80
+ stderr.write(`${agent.slug}: ${command} is for an agent that waits for a payer; this one settles on the rail's answer\n`);
81
+ return 2;
82
+ }
83
+ return command === "poll" ? poll(agent, argv) : webhook(agent, argv);
84
+ }
85
+ default:
86
+ stderr.write(`unknown command ${command}\n`);
87
+ return 2;
88
+ }
89
+ }
90
+
91
+ if (process.argv[1] && import.meta.url === new URL(`file://${process.argv[1]}`).href) {
92
+ main()
93
+ .then((code) => process.exit(code))
94
+ .catch((err) => {
95
+ stderr.write(`${err instanceof Error ? err.stack ?? err.message : String(err)}\n`);
96
+ process.exit(1);
97
+ });
98
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * `codespar-agent check [--json]`: the manifest-coherence gate of section 4.3.
3
+ */
4
+ import { stderr, stdout } from "node:process";
5
+ import { checkAgent } from "@codespar/agent-core";
6
+ import type { Agent } from "../agent.js";
7
+
8
+ export function check(agent: Agent, argv: string[]): number {
9
+ const json = argv.includes("--json");
10
+ const report = checkAgent(agent.dir);
11
+ if (json) stdout.write(JSON.stringify(report) + "\n");
12
+ for (const f of report.findings) stderr.write(`${f.level === "error" ? "ERROR" : "warn "} ${f.code}: ${f.message}\n`);
13
+ stderr.write(report.ok ? `check ok: ${report.agent} agrees with its agent.yaml\n` : `check FAILED for ${report.agent ?? "agent"}\n`);
14
+ return report.ok ? 0 : 1;
15
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * `codespar-agent approve|deny <execution-id> [--user <id>] [--json]`:
3
+ * decides an execution left in `awaiting_approval` (a `--input` run without
4
+ * `--approve`, a restart). Produces the section 4.2 artifact and runs the
5
+ * execution through the same last gate `start` uses.
6
+ */
7
+ import { relative } from "node:path";
8
+ import { stderr, stdout } from "node:process";
9
+ import type { Agent } from "../agent.js";
10
+ import { setup } from "../setup.js";
11
+ import { handleExecution } from "../terminal.js";
12
+
13
+ export async function decide(agent: Agent, decision: "approve" | "deny", argv: string[]): Promise<number> {
14
+ const awaitsPayer = agent.settlement === "await-payer";
15
+ const json = argv.includes("--json");
16
+ const user = argv.includes("--user") ? argv[argv.indexOf("--user") + 1] : undefined;
17
+ const wait = awaitsPayer && argv.includes("--wait") ? Number(argv[argv.indexOf("--wait") + 1]) : undefined;
18
+ const simulatePayer = awaitsPayer && argv.includes("--simulate-payer");
19
+ const executionId = argv.find((a, i) => !a.startsWith("--") && argv[i - 1] !== "--user" && (!awaitsPayer || argv[i - 1] !== "--wait"));
20
+ const say = (l: string) => stderr.write(l + "\n");
21
+ if (!executionId) {
22
+ say(`usage: npm run ${decision} <execution-id> [--user <id>]${awaitsPayer ? " [--wait <seconds>] [--simulate-payer]" : ""} [--json]`);
23
+ return 2;
24
+ }
25
+ const s = setup(agent, { say, runId: `run_${decision}_${Date.now().toString(36)}` });
26
+ try {
27
+ const execution = s.engine.get(executionId);
28
+ if (!execution) {
29
+ say(`unknown execution ${executionId}`);
30
+ return 1;
31
+ }
32
+ if (execution.state !== "awaiting_approval") {
33
+ say(`${executionId} is ${execution.state}, not awaiting_approval; nothing to decide`);
34
+ return 1;
35
+ }
36
+ const final = await handleExecution(execution, {
37
+ setup: s,
38
+ approver: { id: user ?? s.kit.labels.defaultUser, channel: "terminal" },
39
+ decision,
40
+ say,
41
+ ...(json ? { tell: say } : {}),
42
+ waitSeconds: wait,
43
+ simulatePayer,
44
+ });
45
+ if (json) {
46
+ stdout.write(
47
+ JSON.stringify({
48
+ execution_id: final.id,
49
+ state: final.state,
50
+ reason: final.reason ?? null,
51
+ approval_id: final.approval_id ?? null,
52
+ ...(awaitsPayer ? { charge_ids: final.outcomes.map((o) => o.transaction_id ?? null) } : {}),
53
+ receipt_ids: final.outcomes.filter((o) => o.receipt_id).map((o) => o.receipt_id),
54
+ bundle_dir: relative(process.cwd(), s.bundle.dir),
55
+ }) + "\n",
56
+ );
57
+ }
58
+ if (awaitsPayer) return final.state === "executing" && final.reason !== "awaiting_settlement" ? 3 : 0;
59
+ return final.state === "executing" ? 3 : 0;
60
+ } finally {
61
+ s.close();
62
+ }
63
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * `codespar-agent eval [--json] [--case <name>]`: the adversarial suite of
3
+ * section 9 plus every scenario of section 12 in every mode it declares. Runs
4
+ * on the replay provider and the stub rail, with no model and no network. A
5
+ * regression blocks merge.
6
+ */
7
+ import { stderr, stdout } from "node:process";
8
+ import type { Agent } from "../agent.js";
9
+ import { listAdversarialCases, loadAdversarialCase, runAdversarialCase, type AdversarialResult } from "../adversarial.js";
10
+ import { checkScenario, listScenarios, loadScenario, runScenario, type ScenarioCheck } from "../scenarios.js";
11
+
12
+ export async function runEval(agent: Agent, argv: string[]): Promise<number> {
13
+ const json = argv.includes("--json");
14
+ const only = argv.includes("--case") ? argv[argv.indexOf("--case") + 1] : undefined;
15
+ const say = (l: string) => stderr.write(l + "\n");
16
+ const awaitsPayer = agent.settlement === "await-payer";
17
+
18
+ const adversarial = [];
19
+ for (const name of listAdversarialCases(agent)) {
20
+ if (only && only !== name) continue;
21
+ const result = await runAdversarialCase(agent, loadAdversarialCase(agent, name));
22
+ adversarial.push(result);
23
+ say(agent.kit.evalAdversarialLine?.(result) ?? adversarialLine(result));
24
+ }
25
+
26
+ const scenarios = [];
27
+ for (const name of listScenarios(agent)) {
28
+ if (only && only !== name) continue;
29
+ const scenario = loadScenario(agent, name);
30
+ if (!scenario.rails.includes("stub")) continue;
31
+ for (const mode of scenario.modes) {
32
+ const check = checkScenario(scenario, await runScenario(agent, scenario, { mode, rail: "stub" }));
33
+ scenarios.push({
34
+ name,
35
+ mode,
36
+ ok: check.ok,
37
+ failures: check.failures,
38
+ states: check.run.executions.map((e) => e.state),
39
+ receipts: check.run.receipts,
40
+ ...(awaitsPayer ? { charges_issued: check.run.charges_issued, debtor_messages: check.run.debtor_messages } : {}),
41
+ });
42
+ say(agent.kit.evalScenarioLine?.(check) ?? scenarioLine(check));
43
+ }
44
+ }
45
+
46
+ const ok = adversarial.every((r) => r.ok) && scenarios.every((r) => r.ok);
47
+ if (json) stdout.write(JSON.stringify({ ok, adversarial, scenarios }) + "\n");
48
+ say(ok ? `eval ok: ${adversarial.length} adversarial case(s), ${scenarios.length} scenario run(s)` : "eval FAILED");
49
+ return ok ? 0 : 1;
50
+ }
51
+
52
+ function adversarialLine(result: AdversarialResult): string {
53
+ return `${result.ok ? "ok " : "FAIL"} adversarial/${result.name} — ${result.attack} — states ${JSON.stringify(result.states)}${result.failures.length ? ` — ${result.failures.join("; ")}` : ""}`;
54
+ }
55
+
56
+ function scenarioLine(check: ScenarioCheck): string {
57
+ return `${check.ok ? "ok " : "FAIL"} scenario/${check.run.scenario} [${check.mode}] — states ${JSON.stringify(check.run.executions.map((e) => e.state))}, ${check.run.receipts} receipt(s)${check.failures.length ? ` — ${check.failures.join("; ")}` : ""}`;
58
+ }
@@ -0,0 +1,100 @@
1
+ /**
2
+ * `codespar-agent inspect <run-id> [--json] [--html <path>]`: the proof bundle
3
+ * of section 11 read back as a timeline. Defaults to the terminal rendering;
4
+ * `--json` follows the rule of section 14.5 — machine data on stdout, valid
5
+ * JSON and nothing else, human messages on stderr.
6
+ *
7
+ * It reads the bundle and nothing else, so it works on any agent's run, and
8
+ * on a folder copied off the machine that produced it.
9
+ */
10
+ import { existsSync, readdirSync, writeFileSync } from "node:fs";
11
+ import { resolve } from "node:path";
12
+ import { stderr, stdout } from "node:process";
13
+ import { ProofBundle } from "@codespar/agent-core";
14
+ import type { Agent } from "../agent.js";
15
+ import { runsDir } from "../setup.js";
16
+ import { assembleTimeline, renderHtml, renderText } from "../inspect.js";
17
+
18
+ const USAGE = "usage: npm run inspect <run-id> [--json] [--html <file>]";
19
+
20
+ export function inspect(agent: Agent, argv: string[]): number {
21
+ const say = (line: string) => stderr.write(line + "\n");
22
+ let json = false;
23
+ let html: string | undefined;
24
+ let runId: string | undefined;
25
+
26
+ for (let i = 0; i < argv.length; i += 1) {
27
+ const a = argv[i]!;
28
+ if (a === "--json") json = true;
29
+ else if (a === "--html") {
30
+ const value = argv[i + 1];
31
+ if (value === undefined || value.startsWith("--")) {
32
+ say(`--html needs a file path\n${USAGE}`);
33
+ return 2;
34
+ }
35
+ html = value;
36
+ i += 1;
37
+ } else if (a === "--help" || a === "-h") {
38
+ say(USAGE);
39
+ return 0;
40
+ } else if (a.startsWith("-")) {
41
+ say(`unknown argument ${a}\n${USAGE}`);
42
+ return 2;
43
+ } else if (runId === undefined) runId = a;
44
+ else {
45
+ say(`inspect takes one run id (got ${runId} and ${a})\n${USAGE}`);
46
+ return 2;
47
+ }
48
+ }
49
+
50
+ const runs = runsDir(agent);
51
+ if (!runId) {
52
+ say(USAGE);
53
+ say(available(runs));
54
+ return 2;
55
+ }
56
+
57
+ // An unknown run id is a refusal a person can act on, never a stack trace.
58
+ const bundle = ProofBundle.open(runs, runId);
59
+ if (!bundle) {
60
+ say(`no proof bundle for run ${runId}: nothing at ${resolve(runs, runId)}`);
61
+ say(available(runs));
62
+ return 1;
63
+ }
64
+
65
+ // A bundle half-written by a run that was killed is exactly when somebody looks at it: say which file is unreadable, do not throw a stack at them.
66
+ let report;
67
+ try {
68
+ report = assembleTimeline(bundle);
69
+ } catch (err) {
70
+ say(`the bundle at ${bundle.dir} could not be read: ${err instanceof Error ? err.message : String(err)}`);
71
+ say("a file in it is missing or not valid JSON; the folder is the run's own output and is safe to delete and re-run");
72
+ return 1;
73
+ }
74
+
75
+ if (html) {
76
+ try {
77
+ writeFileSync(html, renderHtml(report));
78
+ } catch (err) {
79
+ say(`could not write ${resolve(html)}: ${err instanceof Error ? err.message : String(err)}`);
80
+ return 1;
81
+ }
82
+ say(`wrote ${resolve(html)} — one file, no network, opens from disk`);
83
+ }
84
+ if (json) stdout.write(JSON.stringify(report) + "\n");
85
+ else stdout.write(renderText(report));
86
+ return 0;
87
+ }
88
+
89
+ /** What the person can inspect instead. Bounded: a long-lived agent has many runs and this is an error message, not a listing command. */
90
+ function available(runs: string): string {
91
+ if (!existsSync(runs)) return `no runs yet: ${runs} does not exist. Run the agent once, then inspect the run id it printed.`;
92
+ const ids = readdirSync(runs, { withFileTypes: true })
93
+ .filter((e) => e.isDirectory())
94
+ .map((e) => e.name)
95
+ .sort()
96
+ .reverse();
97
+ if (!ids.length) return `no runs yet in ${runs}. Run the agent once, then inspect the run id it printed.`;
98
+ const shown = ids.slice(0, 10);
99
+ return `runs in ${runs}${ids.length > shown.length ? ` (newest ${shown.length} of ${ids.length})` : ""}:\n${shown.map((id) => ` ${id}`).join("\n")}`;
100
+ }
@@ -0,0 +1,317 @@
1
+ /**
2
+ * `codespar-agent poll --channel whatsapp`: the conversation's loop-closer.
3
+ *
4
+ * The terminal already had one, and the reason the channel needs its own is
5
+ * the whole of issue #25. Over a terminal the operator and the counterparty
6
+ * are the same pair of eyes and the run never really ends. Over WhatsApp the
7
+ * debtor agrees on Tuesday and pays on Friday: the run that issued the charge
8
+ * exited days ago, and by the time the money lands the 24-hour customer
9
+ * service window has shut, so "recebemos, acordo quitado" can only go out as
10
+ * a template Meta approved in advance. Without this command that case cannot
11
+ * be run at all, which is why the confirmation in every recorded run so far
12
+ * happened inside the turn that issued the charge.
13
+ *
14
+ * What it does: reopens a conversation from the RECORD — the bundle of the
15
+ * run that held it, plus `state.db` — looks at the receivable the way the
16
+ * terminal poll does, and puts the outcome back into that same conversation.
17
+ * Nothing about which message may be sent is decided here: the channel's
18
+ * rules and the session window decide, and this only ASKS the window which of
19
+ * the two carriers it may use, because composing a message in order to watch
20
+ * it be refused is not a decision.
21
+ *
22
+ * Three things it deliberately does not do. It does not invent a conversation
23
+ * when there is nothing waiting for a payer — that is a no-op and exits 0,
24
+ * because a cron that fails when there is no work is a cron somebody turns
25
+ * off. It does not send a second confirmation when it runs twice, because the
26
+ * once-only cursor is in `state.db` and outlives the process. And it does not
27
+ * pin the emulator's clock, unlike the run that started the conversation:
28
+ * rewinding the provider's clock would reopen a window that really is shut.
29
+ */
30
+ import { stdout } from "node:process";
31
+ import { relative } from "node:path";
32
+ import { ProofBundle, type ChargeInstrument, type Execution } from "@codespar/agent-core";
33
+ import type { Agent } from "../agent.js";
34
+ import { runsDir, type Setup } from "../setup.js";
35
+ import { waitForPayer } from "../terminal.js";
36
+ import { resolveConversation } from "../channels/index.js";
37
+ import { buildWhatsApp, simulatedCost, type WhatsAppBackendName } from "../channels/whatsapp/open.js";
38
+ import { EmulatorUnreachableError } from "../channels/whatsapp/emulator.js";
39
+ import { sessionStateFromChannelLog, type SessionState } from "../channels/whatsapp/session.js";
40
+ import { instrumentBodies } from "../channels/whatsapp/present.js";
41
+ import type { WhatsAppChannel } from "../channels/whatsapp/index.js";
42
+ import type { SentMessage } from "../channels/types.js";
43
+
44
+ export interface PollWhatsAppOptions {
45
+ agent: Agent;
46
+ setup: Setup;
47
+ conversation: string | undefined;
48
+ backend: WhatsAppBackendName;
49
+ json: boolean;
50
+ waitSeconds?: number | undefined;
51
+ simulatePayer?: boolean | undefined;
52
+ /** Stub only: what the fixture payer does with the receivables THIS conversation is waiting on. */
53
+ payer?: "pays" | "expires" | "never" | undefined;
54
+ now: () => Date;
55
+ say: (line: string) => void;
56
+ }
57
+
58
+ /** How the outcome reached the person, or why it did not. */
59
+ type Delivery =
60
+ | { told: true; carrier: "text" | "template"; template?: string }
61
+ | { told: false; reason: "already_told" | "still_open" | "no_template_for_outcome" | "refused"; detail?: string };
62
+
63
+ interface Polled {
64
+ id: string;
65
+ state: string;
66
+ reason: string | null;
67
+ rounds: number;
68
+ seconds: number;
69
+ timed_out: boolean;
70
+ session_open: boolean;
71
+ delivery: Delivery;
72
+ }
73
+
74
+ export async function pollWhatsApp(options: PollWhatsAppOptions): Promise<number> {
75
+ const { agent, setup: s, say, now } = options;
76
+
77
+ let script;
78
+ try {
79
+ script = resolveConversation(agent, options.conversation);
80
+ } catch (err) {
81
+ say(err instanceof Error ? err.message : String(err));
82
+ return 2;
83
+ }
84
+
85
+ // Which open executions belong to THIS conversation. The binding is the
86
+ // conversation's subject — the agreement alias it is allowed to name — and
87
+ // that is not a convenience: sending one debtor's outcome into another
88
+ // debtor's chat is the secrecy rule broken, and the same `subject` is what
89
+ // the channel already refuses other agreements by. A conversation that
90
+ // declares no subject binds to nothing and says so, rather than taking
91
+ // every open execution and hoping.
92
+ const open = s.engine.list({ state: "executing" }).filter((e) => e.reason === "awaiting_settlement");
93
+ const subject = script.subject;
94
+ // EVERY item, not some: an execution that mixes this conversation's
95
+ // agreement with another's belongs to neither, and confirming it here would
96
+ // put somebody else's debt in front of this person.
97
+ const mine = subject ? open.filter((e) => e.items.length > 0 && e.items.every((i) => i.alias === subject || i.payee === subject)) : [];
98
+
99
+ 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`);
101
+ return 2;
102
+ }
103
+ if (!mine.length) {
104
+ // A clean no-op: nothing is waiting, so nothing is opened. The emulator is
105
+ // not even contacted, which is the point — a poll with no work does no work.
106
+ if (options.json) stdout.write(JSON.stringify({ polled: [], conversation: script.name, channel: null }) + "\n");
107
+ else say(`nada aguardando pagador em ${script.name}`);
108
+ return 0;
109
+ }
110
+
111
+ // The conversation as it was left: the bundle of the run that held it. The
112
+ // window is counted from the person's last message on the PROVIDER's clock,
113
+ // which only that record holds, and the confirmation is appended THERE, so
114
+ // one conversation stays one record instead of ending in a second folder.
115
+ const { bundle, session } = conversationRecord(agent, mine);
116
+ 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`);
118
+ return 1;
119
+ }
120
+
121
+ const built = buildWhatsApp({
122
+ agent,
123
+ setup: s,
124
+ conversation: { contact: script.contact, subject: script.subject },
125
+ backend: options.backend,
126
+ now,
127
+ say,
128
+ bundle,
129
+ // Nobody writes in a poll: the person already said what they had to say,
130
+ // and this run is here because the PAYER acted, not because the person did.
131
+ session,
132
+ });
133
+ if ("refusal" in built) {
134
+ for (const line of built.refusal) say(line);
135
+ return 1;
136
+ }
137
+ const { channel, driver, sessionKey } = built;
138
+
139
+ // Scoped to the receivables of THIS conversation: `behave` set the default
140
+ // for new ones, and this rewrites the fate of the ones already issued —
141
+ // another conversation's charge is none of this command's business.
142
+ if (options.payer) {
143
+ for (const execution of mine) {
144
+ for (const outcome of execution.outcomes) if (outcome.status === "accepted") s.payer?.decideFor?.(outcome.attempt_id, options.payer);
145
+ }
146
+ }
147
+
148
+ try {
149
+ await channel.open();
150
+ } catch (err) {
151
+ if (err instanceof EmulatorUnreachableError) {
152
+ say(err.message);
153
+ return 1;
154
+ }
155
+ throw err;
156
+ }
157
+
158
+ const results: Polled[] = [];
159
+ try {
160
+ const remaining = channel.sessionRemainingSeconds;
161
+ say(
162
+ `${s.manifest.manifest.name} ${s.manifest.manifest.version} — poll no canal whatsapp (${channel.backend}) — conversa ${script.name} — janela de 24h ${
163
+ channel.sessionOpen ? `ABERTA (${Math.round(remaining / 60)} min restantes): mensagem livre` : "FECHADA: so template aprovado"
164
+ }`,
165
+ );
166
+ for (const execution of mine) {
167
+ const sessionOpen = channel.sessionOpen;
168
+ const result = await waitForPayer(execution.id, {
169
+ setup: s,
170
+ approver: { id: s.kit.labels.defaultUser, channel: "whatsapp" },
171
+ say,
172
+ waitSeconds: options.waitSeconds,
173
+ simulatePayer: options.simulatePayer,
174
+ presentInstrument: (e, n, id, instrument) => presentInstrument(channel, s, e, n, id, instrument),
175
+ });
176
+ const closed = result.execution;
177
+ if (closed.state !== "executing") await s.engine.collectReceipts(closed.id);
178
+ const delivery = await tellOutcome(channel, s, closed);
179
+ results.push({
180
+ id: closed.id,
181
+ state: closed.state,
182
+ reason: closed.reason ?? null,
183
+ rounds: result.rounds,
184
+ seconds: result.seconds,
185
+ timed_out: result.timed_out,
186
+ session_open: sessionOpen,
187
+ delivery,
188
+ });
189
+ say(
190
+ `${closed.id}: ${closed.state}${closed.reason ? ` (${closed.reason})` : ""} apos ${result.rounds} consulta(s), ${result.seconds}s — ${
191
+ delivery.told ? `avisado por ${delivery.carrier === "template" ? `template ${delivery.template}` : "mensagem livre"}` : `nao avisado (${delivery.reason}${delivery.detail ? `: ${delivery.detail}` : ""})`
192
+ }`,
193
+ );
194
+ }
195
+ } finally {
196
+ await channel.close();
197
+ }
198
+
199
+ const cost = await simulatedCost(driver, sessionKey);
200
+ const log = channel.log();
201
+ const refused = log.filter((l) => l.refused).map((l) => ({ rule: l.refused!.rule, detail: l.refused!.detail }));
202
+ const channelSummary = {
203
+ name: "whatsapp",
204
+ backend: channel.backend,
205
+ conversation: script.name,
206
+ session_open: channel.sessionOpen,
207
+ messages_out: log.filter((l) => l.direction === "out" && !l.refused).length,
208
+ refused,
209
+ log: relative(process.cwd(), `${bundle.dir}/channel.jsonl`),
210
+ ...(cost ? { simulated_cost: cost } : {}),
211
+ };
212
+
213
+ if (options.json) stdout.write(JSON.stringify({ polled: results, conversation: script.name, channel: channelSummary }) + "\n");
214
+ else say(`conversa em ${channelSummary.log} — ${channelSummary.messages_out} enviada(s)${refused.length ? `, ${refused.length} recusada(s)` : ""}`);
215
+
216
+ if (results.some((r) => r.timed_out)) return 3;
217
+ // A cycle that closed and a person who was not told is a failure worth an
218
+ // exit code: the record says the agreement is settled and the debtor does
219
+ // not know it. The other two are not failures — `already_told` is this
220
+ // command running twice, which is the thing it is built to be safe under,
221
+ // and `still_open` is a wait that ran out, which the 3 above already said.
222
+ return results.some((r) => !r.delivery.told && r.delivery.reason !== "already_told" && r.delivery.reason !== "still_open") ? 1 : 0;
223
+ }
224
+
225
+ /**
226
+ * The bundle the conversation lives in, and where its window stood. When
227
+ * several runs touched the same conversation the LATEST one holds the last
228
+ * inbound, so that is the record the confirmation is appended to; the window
229
+ * itself is read across all of them, because the person's last message is the
230
+ * person's last message whichever run recorded it.
231
+ */
232
+ function conversationRecord(agent: Agent, executions: readonly Execution[]): { bundle: ProofBundle | undefined; session: SessionState } {
233
+ const runs = runsDir(agent);
234
+ const seen = new Set<string>();
235
+ let bundle: ProofBundle | undefined;
236
+ let lastInboundAt: number | undefined;
237
+ // `list()` orders by creation, so the last execution that carries a log is the most recent record of the conversation.
238
+ for (const execution of executions) {
239
+ if (seen.has(execution.run_id)) continue;
240
+ seen.add(execution.run_id);
241
+ const opened = ProofBundle.open(runs, execution.run_id);
242
+ if (!opened) continue;
243
+ const lines = opened.readChannel();
244
+ if (!lines.length) continue;
245
+ bundle = opened;
246
+ const state = sessionStateFromChannelLog(lines);
247
+ if (state.lastInboundAt !== undefined && (lastInboundAt === undefined || state.lastInboundAt > lastInboundAt)) lastInboundAt = state.lastInboundAt;
248
+ }
249
+ return { bundle, session: { lastInboundAt } };
250
+ }
251
+
252
+ /**
253
+ * The payable artifact, the way a person can use it: the QR as an image and
254
+ * the copy-and-paste as its OWN message. The same shape `converse` sends,
255
+ * because a payer told how to pay by a poll is told the same way a payer told
256
+ * by a run is.
257
+ *
258
+ * It is only reached for an instrument nobody has shown yet — `markShown` is a
259
+ * cursor in `state.db` — so in the ordinary resumed conversation nothing is
260
+ * sent here at all. When it IS reached with the window shut the channel
261
+ * refuses it, and that refusal is the record: WhatsApp would not have carried
262
+ * it either.
263
+ */
264
+ async function presentInstrument(channel: WhatsAppChannel, s: Setup, execution: Execution, instalment: number, chargeId: string, instrument: ChargeInstrument): Promise<void> {
265
+ for (const body of instrumentBodies(execution, instalment, chargeId, instrument, s.mandate.currency)) await channel.send(body);
266
+ }
267
+
268
+ /**
269
+ * The one message per outcome, carried by whichever of the two the window
270
+ * allows. Both halves share `markTold`, the cursor in `state.db`, so a second
271
+ * poll sends nothing whichever carrier the first one used.
272
+ *
273
+ * The order matters and is deliberate: the cursor is taken BEFORE the send.
274
+ * Taking it after would mean a process killed between the send and the write
275
+ * tells the person twice, and on a channel that is a second "recebemos" for
276
+ * one payment. A send that is then refused is reported instead, with the
277
+ * rule, and it is the exit code of the command — the record says settled and
278
+ * the debtor does not know.
279
+ */
280
+ async function tellOutcome(channel: WhatsAppChannel, s: Setup, execution: Execution): Promise<Delivery> {
281
+ // Nothing closed, so there is no outcome to carry. Not a failure and not a
282
+ // silence to explain: the wait ran out and the receivable is still open.
283
+ if (execution.state === "executing") return { told: false, reason: "still_open" };
284
+
285
+ if (channel.sessionOpen) {
286
+ // The kit writes lines, the channel sends messages. Joined rather than
287
+ // last-one-wins, so a kit that says two sentences does not lose one.
288
+ const lines: string[] = [];
289
+ const told = s.kit.announceOutcome?.(execution, s, (line) => void lines.push(line)) ?? false;
290
+ if (!told) return { told: false, reason: "already_told" };
291
+ const sent = await channel.send({ kind: "text", text: lines.join("\n") });
292
+ return deliveryOf(sent, "text");
293
+ }
294
+
295
+ const chosen = s.kit.outcomeTemplate?.(execution);
296
+ if (!chosen) {
297
+ return {
298
+ told: false,
299
+ reason: "no_template_for_outcome",
300
+ detail: `a janela de 24h esta fechada e o agente nao declara template para ${execution.state}${execution.reason ? ` (${execution.reason})` : ""}`,
301
+ };
302
+ }
303
+ const declared = channel.declaredTemplate(chosen.template);
304
+ if (!declared) {
305
+ return { told: false, reason: "no_template_for_outcome", detail: `o kit pediu o template ${chosen.template}, que channels/whatsapp/templates.json nao declara` };
306
+ }
307
+ if (!s.engine.markTold(execution.id, execution.state)) return { told: false, reason: "already_told" };
308
+ const sent = await channel.send({ kind: "template", template: declared.name, language: declared.language, variables: chosen.variables });
309
+ s.engine.note("message.debtor", execution.id, { state: execution.state, reason: execution.reason ?? null, template: declared.name, variables: chosen.variables });
310
+ return deliveryOf(sent, "template", declared.name);
311
+ }
312
+
313
+ function deliveryOf(sent: SentMessage, carrier: "text" | "template", template?: string): Delivery {
314
+ if (sent.refused) return { told: false, reason: "refused", detail: `${sent.refused.rule}: ${sent.refused.detail}` };
315
+ if (sent.state === "failed") return { told: false, reason: "refused", detail: "o provedor nao aceitou a mensagem" };
316
+ return { told: true, carrier, ...(template ? { template } : {}) };
317
+ }