@codespar/cli 0.14.0 → 0.16.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 (538) 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/login.js +2 -1
  7. package/dist/commands/login.js.map +1 -1
  8. package/dist/commands/mandate-verify.js +75 -27
  9. package/dist/commands/mandate-verify.js.map +1 -1
  10. package/dist/config.js +17 -1
  11. package/dist/config.js.map +1 -1
  12. package/dist/did.js +262 -41
  13. package/dist/did.js.map +1 -1
  14. package/dist/index.js +33 -7
  15. package/dist/index.js.map +1 -1
  16. package/dist/surface.js +4 -1
  17. package/dist/surface.js.map +1 -1
  18. package/package.json +1 -1
  19. package/templates/bills-agent/README.md +8 -5
  20. package/templates/bills-agent/agents/bills-agent/.env.example +3 -3
  21. package/templates/bills-agent/agents/bills-agent/AGENTS.md +1 -1
  22. package/templates/bills-agent/agents/bills-agent/CLAUDE.md +1 -1
  23. package/templates/bills-agent/agents/bills-agent/README.md +62 -22
  24. package/templates/bills-agent/agents/bills-agent/SYSTEM_PROMPT.md +1 -1
  25. package/templates/bills-agent/agents/bills-agent/agent.yaml +2 -2
  26. package/templates/bills-agent/agents/bills-agent/package.json +14 -11
  27. package/templates/bills-agent/agents/bills-agent/src/kit.ts +193 -0
  28. package/templates/bills-agent/agents/bills-agent/test/adversarial.test.ts +8 -7
  29. package/templates/bills-agent/agents/bills-agent/test/check.test.ts +19 -2
  30. package/templates/bills-agent/agents/bills-agent/test/cli.test.ts +72 -24
  31. package/templates/bills-agent/agents/bills-agent/test/fixtures/excursao-300.transcript.jsonl +2 -0
  32. package/templates/bills-agent/agents/bills-agent/test/fixtures/material-400.transcript.jsonl +2 -0
  33. package/templates/bills-agent/agents/bills-agent/test/inspect.test.ts +124 -0
  34. package/templates/bills-agent/agents/bills-agent/test/provider.test.ts +25 -0
  35. package/templates/bills-agent/agents/bills-agent/test/scenarios.test.ts +10 -9
  36. package/templates/bills-agent/agents/bills-agent/tsconfig.json +0 -1
  37. package/templates/bills-agent/package.json +5 -2
  38. package/templates/bills-agent/packages/agent-core/README.md +2 -0
  39. package/templates/bills-agent/packages/agent-core/package.json +1 -1
  40. package/templates/bills-agent/packages/agent-core/src/api/charge-rail.ts +27 -6
  41. package/templates/bills-agent/packages/agent-core/src/api/rail.ts +16 -0
  42. package/templates/bills-agent/packages/agent-core/src/api/sandbox-payer.ts +20 -7
  43. package/templates/bills-agent/packages/agent-core/src/approval.ts +16 -2
  44. package/templates/bills-agent/packages/agent-core/src/bundle.ts +50 -4
  45. package/templates/bills-agent/packages/agent-core/src/channels.ts +140 -0
  46. package/templates/bills-agent/packages/agent-core/src/check.ts +90 -8
  47. package/templates/bills-agent/packages/agent-core/src/clock.ts +42 -0
  48. package/templates/bills-agent/packages/agent-core/src/engine.ts +119 -18
  49. package/templates/bills-agent/packages/agent-core/src/hash.ts +13 -0
  50. package/templates/bills-agent/packages/agent-core/src/index.ts +3 -0
  51. package/templates/bills-agent/packages/agent-core/src/manifest.ts +1 -1
  52. package/templates/bills-agent/packages/agent-core/src/rail.ts +16 -2
  53. package/templates/bills-agent/packages/agent-core/src/receipt-verification.ts +401 -0
  54. package/templates/bills-agent/packages/agent-core/src/state-machine.ts +3 -1
  55. package/templates/bills-agent/packages/agent-core/src/stubs/charge-rail.ts +2 -0
  56. package/templates/bills-agent/packages/agent-core/src/stubs/rail.ts +19 -2
  57. package/templates/bills-agent/packages/agent-core/src/types.ts +28 -0
  58. package/templates/bills-agent/packages/agent-core/test/approval.test.ts +36 -2
  59. package/templates/bills-agent/packages/agent-core/test/bundle.test.ts +85 -0
  60. package/templates/bills-agent/packages/agent-core/test/clock.test.ts +25 -0
  61. package/templates/bills-agent/packages/agent-core/test/engine.test.ts +73 -1
  62. package/templates/bills-agent/packages/agent-core/test/fixtures/staging-receipt-keys.json +18 -0
  63. package/templates/bills-agent/packages/agent-core/test/fixtures/staging-receipt.json +24 -0
  64. package/templates/bills-agent/packages/agent-core/test/helpers.ts +1 -1
  65. package/templates/bills-agent/packages/agent-core/test/manifest.test.ts +2 -2
  66. package/templates/bills-agent/packages/agent-core/test/receipt-verification.test.ts +316 -0
  67. package/templates/bills-agent/packages/agent-core/test/receivables.test.ts +51 -0
  68. package/templates/bills-agent/packages/agent-runtime/README.md +68 -0
  69. package/templates/bills-agent/packages/agent-runtime/bin.mjs +32 -0
  70. package/templates/bills-agent/packages/agent-runtime/package.json +23 -0
  71. package/templates/bills-agent/{agents/bills-agent → packages/agent-runtime}/src/adversarial.ts +36 -44
  72. package/templates/bills-agent/packages/agent-runtime/src/agent.ts +68 -0
  73. package/templates/bills-agent/packages/agent-runtime/src/channels/contact.ts +13 -0
  74. package/templates/bills-agent/packages/agent-runtime/src/channels/index.ts +72 -0
  75. package/templates/bills-agent/packages/agent-runtime/src/channels/rules.ts +120 -0
  76. package/templates/bills-agent/packages/agent-runtime/src/channels/types.ts +124 -0
  77. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +358 -0
  78. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +206 -0
  79. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/evidence.ts +109 -0
  80. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +225 -0
  81. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +143 -0
  82. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +47 -0
  83. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +113 -0
  84. package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +113 -0
  85. package/templates/bills-agent/packages/agent-runtime/src/cli.ts +98 -0
  86. package/templates/bills-agent/packages/agent-runtime/src/commands/check.ts +15 -0
  87. package/templates/bills-agent/packages/agent-runtime/src/commands/decide.ts +63 -0
  88. package/templates/bills-agent/packages/agent-runtime/src/commands/eval.ts +58 -0
  89. package/templates/bills-agent/packages/agent-runtime/src/commands/inspect.ts +100 -0
  90. package/templates/bills-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +317 -0
  91. package/templates/bills-agent/packages/agent-runtime/src/commands/poll.ts +144 -0
  92. package/templates/bills-agent/packages/agent-runtime/src/commands/reconcile.ts +42 -0
  93. package/templates/bills-agent/packages/agent-runtime/src/commands/rerun.ts +86 -0
  94. package/templates/bills-agent/packages/agent-runtime/src/commands/resume.ts +43 -0
  95. package/templates/bills-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +131 -0
  96. package/templates/bills-agent/packages/agent-runtime/src/commands/start.ts +245 -0
  97. package/templates/bills-agent/packages/agent-runtime/src/commands/verify.ts +129 -0
  98. package/templates/bills-agent/packages/agent-runtime/src/commands/webhook.ts +39 -0
  99. package/templates/bills-agent/packages/agent-runtime/src/default-kit.ts +83 -0
  100. package/templates/bills-agent/packages/agent-runtime/src/index.ts +12 -0
  101. package/templates/bills-agent/packages/agent-runtime/src/inspect.ts +797 -0
  102. package/templates/bills-agent/packages/agent-runtime/src/kit.ts +206 -0
  103. package/templates/{collections-agent/agents/collections-agent → bills-agent/packages/agent-runtime}/src/poll.ts +22 -11
  104. package/templates/{collections-agent/agents/collections-agent → bills-agent/packages/agent-runtime}/src/scenarios.ts +50 -34
  105. package/templates/bills-agent/{agents/bills-agent → packages/agent-runtime}/src/setup.ts +88 -66
  106. package/templates/bills-agent/packages/agent-runtime/src/terminal.ts +154 -0
  107. package/templates/{collections-agent/agents/collections-agent/channels/webhook/index.ts → bills-agent/packages/agent-runtime/src/webhook.ts} +1 -1
  108. package/templates/bills-agent/packages/agent-runtime/test/inspect.test.ts +336 -0
  109. package/templates/bills-agent/packages/agent-runtime/test/verify-cli.test.ts +127 -0
  110. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +232 -0
  111. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +204 -0
  112. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-evidence.test.ts +94 -0
  113. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +174 -0
  114. package/templates/bills-agent/packages/agent-runtime/test/whatsapp-session.test.ts +135 -0
  115. package/templates/bills-agent/packages/agent-runtime/tsconfig.json +9 -0
  116. package/templates/bills-agent/vitest.config.ts +1 -1
  117. package/templates/collections-agent/README.md +8 -5
  118. package/templates/collections-agent/agents/collections-agent/.env.example +14 -0
  119. package/templates/collections-agent/agents/collections-agent/AGENTS.md +6 -4
  120. package/templates/collections-agent/agents/collections-agent/CLAUDE.md +6 -4
  121. package/templates/collections-agent/agents/collections-agent/README.md +184 -16
  122. package/templates/collections-agent/agents/collections-agent/agent.yaml +3 -3
  123. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/README.md +111 -0
  124. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/acordo-1042.json +11 -0
  125. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/acordo-1103.json +11 -0
  126. package/templates/collections-agent/agents/collections-agent/channels/whatsapp/templates.json +23 -0
  127. package/templates/collections-agent/agents/collections-agent/package.json +12 -10
  128. package/templates/collections-agent/agents/collections-agent/runbook.md +52 -1
  129. package/templates/collections-agent/agents/collections-agent/src/kit.ts +265 -0
  130. package/templates/collections-agent/agents/collections-agent/test/adversarial.test.ts +9 -8
  131. package/templates/collections-agent/agents/collections-agent/test/check.test.ts +43 -1
  132. package/templates/collections-agent/agents/collections-agent/test/cli.test.ts +56 -18
  133. package/templates/collections-agent/agents/collections-agent/test/fixtures/agreed-1042-awaiting-payer.transcript.jsonl +4 -0
  134. package/templates/collections-agent/agents/collections-agent/test/scenarios.test.ts +11 -10
  135. package/templates/collections-agent/agents/collections-agent/test/webhook.test.ts +4 -7
  136. package/templates/collections-agent/agents/collections-agent/test/whatsapp-poll.test.ts +271 -0
  137. package/templates/collections-agent/agents/collections-agent/test/whatsapp.test.ts +213 -0
  138. package/templates/collections-agent/agents/collections-agent/tsconfig.json +0 -1
  139. package/templates/collections-agent/package.json +3 -1
  140. package/templates/collections-agent/packages/agent-core/README.md +2 -0
  141. package/templates/collections-agent/packages/agent-core/package.json +1 -1
  142. package/templates/collections-agent/packages/agent-core/src/api/charge-rail.ts +27 -6
  143. package/templates/collections-agent/packages/agent-core/src/api/rail.ts +16 -0
  144. package/templates/collections-agent/packages/agent-core/src/api/sandbox-payer.ts +20 -7
  145. package/templates/collections-agent/packages/agent-core/src/approval.ts +16 -2
  146. package/templates/collections-agent/packages/agent-core/src/bundle.ts +50 -4
  147. package/templates/collections-agent/packages/agent-core/src/channels.ts +140 -0
  148. package/templates/collections-agent/packages/agent-core/src/check.ts +90 -8
  149. package/templates/collections-agent/packages/agent-core/src/clock.ts +42 -0
  150. package/templates/collections-agent/packages/agent-core/src/engine.ts +119 -18
  151. package/templates/collections-agent/packages/agent-core/src/hash.ts +13 -0
  152. package/templates/collections-agent/packages/agent-core/src/index.ts +3 -0
  153. package/templates/collections-agent/packages/agent-core/src/manifest.ts +1 -1
  154. package/templates/collections-agent/packages/agent-core/src/rail.ts +16 -2
  155. package/templates/collections-agent/packages/agent-core/src/receipt-verification.ts +401 -0
  156. package/templates/collections-agent/packages/agent-core/src/state-machine.ts +3 -1
  157. package/templates/collections-agent/packages/agent-core/src/stubs/charge-rail.ts +2 -0
  158. package/templates/collections-agent/packages/agent-core/src/stubs/rail.ts +19 -2
  159. package/templates/collections-agent/packages/agent-core/src/types.ts +28 -0
  160. package/templates/collections-agent/packages/agent-core/test/approval.test.ts +36 -2
  161. package/templates/collections-agent/packages/agent-core/test/bundle.test.ts +85 -0
  162. package/templates/collections-agent/packages/agent-core/test/clock.test.ts +25 -0
  163. package/templates/collections-agent/packages/agent-core/test/engine.test.ts +73 -1
  164. package/templates/collections-agent/packages/agent-core/test/fixtures/staging-receipt-keys.json +18 -0
  165. package/templates/collections-agent/packages/agent-core/test/fixtures/staging-receipt.json +24 -0
  166. package/templates/collections-agent/packages/agent-core/test/helpers.ts +1 -1
  167. package/templates/collections-agent/packages/agent-core/test/manifest.test.ts +2 -2
  168. package/templates/collections-agent/packages/agent-core/test/receipt-verification.test.ts +316 -0
  169. package/templates/collections-agent/packages/agent-core/test/receivables.test.ts +51 -0
  170. package/templates/collections-agent/packages/agent-runtime/README.md +68 -0
  171. package/templates/collections-agent/packages/agent-runtime/bin.mjs +32 -0
  172. package/templates/collections-agent/packages/agent-runtime/package.json +23 -0
  173. package/templates/collections-agent/{agents/collections-agent → packages/agent-runtime}/src/adversarial.ts +29 -50
  174. package/templates/collections-agent/packages/agent-runtime/src/agent.ts +68 -0
  175. package/templates/collections-agent/packages/agent-runtime/src/channels/contact.ts +13 -0
  176. package/templates/collections-agent/packages/agent-runtime/src/channels/index.ts +72 -0
  177. package/templates/collections-agent/packages/agent-runtime/src/channels/rules.ts +120 -0
  178. package/templates/collections-agent/packages/agent-runtime/src/channels/types.ts +124 -0
  179. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +358 -0
  180. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +206 -0
  181. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/evidence.ts +109 -0
  182. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +225 -0
  183. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +143 -0
  184. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +47 -0
  185. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +113 -0
  186. package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +113 -0
  187. package/templates/collections-agent/packages/agent-runtime/src/cli.ts +98 -0
  188. package/templates/collections-agent/packages/agent-runtime/src/commands/check.ts +15 -0
  189. package/templates/collections-agent/packages/agent-runtime/src/commands/decide.ts +63 -0
  190. package/templates/collections-agent/packages/agent-runtime/src/commands/eval.ts +58 -0
  191. package/templates/collections-agent/packages/agent-runtime/src/commands/inspect.ts +100 -0
  192. package/templates/collections-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +317 -0
  193. package/templates/collections-agent/packages/agent-runtime/src/commands/poll.ts +144 -0
  194. package/templates/collections-agent/packages/agent-runtime/src/commands/reconcile.ts +42 -0
  195. package/templates/collections-agent/packages/agent-runtime/src/commands/rerun.ts +86 -0
  196. package/templates/collections-agent/packages/agent-runtime/src/commands/resume.ts +43 -0
  197. package/templates/collections-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +131 -0
  198. package/templates/collections-agent/packages/agent-runtime/src/commands/start.ts +245 -0
  199. package/templates/collections-agent/packages/agent-runtime/src/commands/verify.ts +129 -0
  200. package/templates/collections-agent/packages/agent-runtime/src/commands/webhook.ts +39 -0
  201. package/templates/collections-agent/packages/agent-runtime/src/default-kit.ts +83 -0
  202. package/templates/collections-agent/packages/agent-runtime/src/index.ts +12 -0
  203. package/templates/collections-agent/packages/agent-runtime/src/inspect.ts +797 -0
  204. package/templates/collections-agent/packages/agent-runtime/src/kit.ts +206 -0
  205. package/templates/collections-agent/packages/agent-runtime/src/poll.ts +105 -0
  206. package/templates/{bills-agent/agents/bills-agent → collections-agent/packages/agent-runtime}/src/scenarios.ts +98 -26
  207. package/templates/collections-agent/packages/agent-runtime/src/setup.ts +229 -0
  208. package/templates/collections-agent/packages/agent-runtime/src/terminal.ts +154 -0
  209. package/templates/collections-agent/packages/agent-runtime/src/webhook.ts +131 -0
  210. package/templates/collections-agent/packages/agent-runtime/test/inspect.test.ts +336 -0
  211. package/templates/collections-agent/packages/agent-runtime/test/verify-cli.test.ts +127 -0
  212. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +232 -0
  213. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +204 -0
  214. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-evidence.test.ts +94 -0
  215. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +174 -0
  216. package/templates/collections-agent/packages/agent-runtime/test/whatsapp-session.test.ts +135 -0
  217. package/templates/collections-agent/packages/agent-runtime/tsconfig.json +9 -0
  218. package/templates/collections-agent/vitest.config.ts +1 -1
  219. package/templates/hello-agent/LICENSE +21 -0
  220. package/templates/hello-agent/README.md +23 -0
  221. package/templates/hello-agent/_gitignore +10 -0
  222. package/templates/hello-agent/agents/hello-agent/.env.example +5 -0
  223. package/templates/hello-agent/agents/hello-agent/AGENTS.md +15 -0
  224. package/templates/hello-agent/agents/hello-agent/CLAUDE.md +15 -0
  225. package/templates/hello-agent/agents/hello-agent/README.md +33 -0
  226. package/templates/hello-agent/agents/hello-agent/SYSTEM_PROMPT.md +19 -0
  227. package/templates/hello-agent/agents/hello-agent/agent.yaml +19 -0
  228. package/templates/hello-agent/agents/hello-agent/evals/adversarial/beneficiary-swap.json +6 -0
  229. package/templates/hello-agent/agents/hello-agent/evals/adversarial/beneficiary-swap.transcript.jsonl +2 -0
  230. package/templates/hello-agent/agents/hello-agent/evals/adversarial/exfiltration.json +6 -0
  231. package/templates/hello-agent/agents/hello-agent/evals/adversarial/exfiltration.transcript.jsonl +2 -0
  232. package/templates/hello-agent/agents/hello-agent/evals/adversarial/false-authority.json +6 -0
  233. package/templates/hello-agent/agents/hello-agent/evals/adversarial/false-authority.transcript.jsonl +2 -0
  234. package/templates/hello-agent/agents/hello-agent/evals/adversarial/fractioning.json +6 -0
  235. package/templates/hello-agent/agents/hello-agent/evals/adversarial/fractioning.transcript.jsonl +2 -0
  236. package/templates/hello-agent/agents/hello-agent/evals/adversarial/model-total.json +6 -0
  237. package/templates/hello-agent/agents/hello-agent/evals/adversarial/model-total.transcript.jsonl +2 -0
  238. package/templates/hello-agent/agents/hello-agent/evals/adversarial/prompt-injection.json +6 -0
  239. package/templates/hello-agent/agents/hello-agent/evals/adversarial/prompt-injection.transcript.jsonl +2 -0
  240. package/templates/hello-agent/agents/hello-agent/evals/adversarial/webhook-replay.json +6 -0
  241. package/templates/hello-agent/agents/hello-agent/evals/eval.yaml +7 -0
  242. package/templates/hello-agent/agents/hello-agent/guardrails.json +8 -0
  243. package/templates/hello-agent/agents/hello-agent/mandate.example.json +17 -0
  244. package/templates/hello-agent/agents/hello-agent/package.json +19 -0
  245. package/templates/hello-agent/agents/hello-agent/runbook.md +10 -0
  246. package/templates/hello-agent/agents/hello-agent/scenarios/happy-path.json +6 -0
  247. package/templates/hello-agent/agents/hello-agent/scenarios/happy-path.transcript.jsonl +2 -0
  248. package/templates/hello-agent/agents/hello-agent/scenarios/prompt-injection.json +6 -0
  249. package/templates/hello-agent/agents/hello-agent/scenarios/prompt-injection.transcript.jsonl +2 -0
  250. package/templates/hello-agent/agents/hello-agent/src/bills.ts +23 -0
  251. package/templates/hello-agent/agents/hello-agent/src/kit.ts +33 -0
  252. package/templates/hello-agent/agents/hello-agent/tools.json +11 -0
  253. package/templates/hello-agent/agents/hello-agent/tsconfig.json +9 -0
  254. package/templates/hello-agent/package.json +30 -0
  255. package/templates/hello-agent/packages/agent-core/README.md +21 -0
  256. package/templates/hello-agent/packages/agent-core/package.json +24 -0
  257. package/templates/hello-agent/packages/agent-core/src/agent.ts +125 -0
  258. package/templates/hello-agent/packages/agent-core/src/api/charge-rail.ts +175 -0
  259. package/templates/hello-agent/packages/agent-core/src/api/client.ts +53 -0
  260. package/templates/hello-agent/packages/agent-core/src/api/mandate-status.ts +58 -0
  261. package/templates/hello-agent/packages/agent-core/src/api/rail.ts +117 -0
  262. package/templates/hello-agent/packages/agent-core/src/api/sandbox-payer.ts +58 -0
  263. package/templates/hello-agent/packages/agent-core/src/approval.ts +123 -0
  264. package/templates/hello-agent/packages/agent-core/src/bundle.ts +159 -0
  265. package/templates/hello-agent/packages/agent-core/src/channels.ts +140 -0
  266. package/templates/hello-agent/packages/agent-core/src/check.ts +253 -0
  267. package/templates/hello-agent/packages/agent-core/src/clock.ts +42 -0
  268. package/templates/hello-agent/packages/agent-core/src/engine.ts +885 -0
  269. package/templates/hello-agent/packages/agent-core/src/escalate.ts +85 -0
  270. package/templates/hello-agent/packages/agent-core/src/events.ts +40 -0
  271. package/templates/hello-agent/packages/agent-core/src/guardrails.ts +45 -0
  272. package/templates/hello-agent/packages/agent-core/src/hash.ts +62 -0
  273. package/templates/hello-agent/packages/agent-core/src/ids.ts +10 -0
  274. package/templates/hello-agent/packages/agent-core/src/index.ts +32 -0
  275. package/templates/hello-agent/packages/agent-core/src/mandate.ts +100 -0
  276. package/templates/hello-agent/packages/agent-core/src/manifest.ts +76 -0
  277. package/templates/hello-agent/packages/agent-core/src/providers/anthropic.ts +76 -0
  278. package/templates/hello-agent/packages/agent-core/src/providers/replay.ts +63 -0
  279. package/templates/hello-agent/packages/agent-core/src/providers/types.ts +39 -0
  280. package/templates/hello-agent/packages/agent-core/src/rail.ts +101 -0
  281. package/templates/hello-agent/packages/agent-core/src/receipt-verification.ts +401 -0
  282. package/templates/hello-agent/packages/agent-core/src/revocation.ts +30 -0
  283. package/templates/hello-agent/packages/agent-core/src/secrets.ts +30 -0
  284. package/templates/hello-agent/packages/agent-core/src/state/store.ts +307 -0
  285. package/templates/hello-agent/packages/agent-core/src/state-machine.ts +148 -0
  286. package/templates/hello-agent/packages/agent-core/src/stubs/charge-rail.ts +195 -0
  287. package/templates/hello-agent/packages/agent-core/src/stubs/mandate-status.ts +57 -0
  288. package/templates/hello-agent/packages/agent-core/src/stubs/rail.ts +141 -0
  289. package/templates/hello-agent/packages/agent-core/src/tools.ts +55 -0
  290. package/templates/hello-agent/packages/agent-core/src/types.ts +134 -0
  291. package/templates/hello-agent/packages/agent-core/test/approval.test.ts +117 -0
  292. package/templates/hello-agent/packages/agent-core/test/bundle.test.ts +85 -0
  293. package/templates/hello-agent/packages/agent-core/test/clock.test.ts +25 -0
  294. package/templates/hello-agent/packages/agent-core/test/engine.test.ts +596 -0
  295. package/templates/hello-agent/packages/agent-core/test/escalate.test.ts +42 -0
  296. package/templates/hello-agent/packages/agent-core/test/fixtures/staging-receipt-keys.json +18 -0
  297. package/templates/hello-agent/packages/agent-core/test/fixtures/staging-receipt.json +24 -0
  298. package/templates/hello-agent/packages/agent-core/test/helpers.ts +139 -0
  299. package/templates/hello-agent/packages/agent-core/test/mandate-status.test.ts +153 -0
  300. package/templates/hello-agent/packages/agent-core/test/manifest.test.ts +45 -0
  301. package/templates/hello-agent/packages/agent-core/test/receipt-verification.test.ts +316 -0
  302. package/templates/hello-agent/packages/agent-core/test/receivables.test.ts +316 -0
  303. package/templates/hello-agent/packages/agent-core/test/secrets.test.ts +28 -0
  304. package/templates/hello-agent/packages/agent-core/test/state-machine.test.ts +67 -0
  305. package/templates/hello-agent/packages/agent-core/test/transitions.type-test.ts +59 -0
  306. package/templates/hello-agent/packages/agent-core/tsconfig.json +10 -0
  307. package/templates/hello-agent/packages/agent-runtime/README.md +68 -0
  308. package/templates/hello-agent/packages/agent-runtime/bin.mjs +32 -0
  309. package/templates/hello-agent/packages/agent-runtime/package.json +23 -0
  310. package/templates/hello-agent/packages/agent-runtime/src/adversarial.ts +169 -0
  311. package/templates/hello-agent/packages/agent-runtime/src/agent.ts +68 -0
  312. package/templates/hello-agent/packages/agent-runtime/src/channels/contact.ts +13 -0
  313. package/templates/hello-agent/packages/agent-runtime/src/channels/index.ts +72 -0
  314. package/templates/hello-agent/packages/agent-runtime/src/channels/rules.ts +120 -0
  315. package/templates/hello-agent/packages/agent-runtime/src/channels/types.ts +124 -0
  316. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +358 -0
  317. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +206 -0
  318. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/evidence.ts +109 -0
  319. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +225 -0
  320. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +143 -0
  321. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +47 -0
  322. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +113 -0
  323. package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +113 -0
  324. package/templates/hello-agent/packages/agent-runtime/src/cli.ts +98 -0
  325. package/templates/hello-agent/packages/agent-runtime/src/commands/check.ts +15 -0
  326. package/templates/hello-agent/packages/agent-runtime/src/commands/decide.ts +63 -0
  327. package/templates/hello-agent/packages/agent-runtime/src/commands/eval.ts +58 -0
  328. package/templates/hello-agent/packages/agent-runtime/src/commands/inspect.ts +100 -0
  329. package/templates/hello-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +317 -0
  330. package/templates/hello-agent/packages/agent-runtime/src/commands/poll.ts +144 -0
  331. package/templates/hello-agent/packages/agent-runtime/src/commands/reconcile.ts +42 -0
  332. package/templates/hello-agent/packages/agent-runtime/src/commands/rerun.ts +86 -0
  333. package/templates/hello-agent/packages/agent-runtime/src/commands/resume.ts +43 -0
  334. package/templates/hello-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +131 -0
  335. package/templates/hello-agent/packages/agent-runtime/src/commands/start.ts +245 -0
  336. package/templates/hello-agent/packages/agent-runtime/src/commands/verify.ts +129 -0
  337. package/templates/hello-agent/packages/agent-runtime/src/commands/webhook.ts +39 -0
  338. package/templates/hello-agent/packages/agent-runtime/src/default-kit.ts +83 -0
  339. package/templates/hello-agent/packages/agent-runtime/src/index.ts +12 -0
  340. package/templates/hello-agent/packages/agent-runtime/src/inspect.ts +797 -0
  341. package/templates/hello-agent/packages/agent-runtime/src/kit.ts +206 -0
  342. package/templates/hello-agent/packages/agent-runtime/src/poll.ts +105 -0
  343. package/templates/hello-agent/packages/agent-runtime/src/scenarios.ts +268 -0
  344. package/templates/hello-agent/packages/agent-runtime/src/setup.ts +229 -0
  345. package/templates/hello-agent/packages/agent-runtime/src/terminal.ts +154 -0
  346. package/templates/hello-agent/packages/agent-runtime/src/webhook.ts +131 -0
  347. package/templates/hello-agent/packages/agent-runtime/test/inspect.test.ts +336 -0
  348. package/templates/hello-agent/packages/agent-runtime/test/verify-cli.test.ts +127 -0
  349. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +232 -0
  350. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +204 -0
  351. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-evidence.test.ts +94 -0
  352. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +174 -0
  353. package/templates/hello-agent/packages/agent-runtime/test/whatsapp-session.test.ts +135 -0
  354. package/templates/hello-agent/packages/agent-runtime/tsconfig.json +9 -0
  355. package/templates/hello-agent/tsconfig.base.json +16 -0
  356. package/templates/hello-agent/vitest.config.ts +12 -0
  357. package/templates/kits.lock.json +60 -12
  358. package/templates/supplier-payments-agent/LICENSE +21 -0
  359. package/templates/supplier-payments-agent/README.md +23 -0
  360. package/templates/supplier-payments-agent/_gitignore +10 -0
  361. package/templates/supplier-payments-agent/agents/supplier-payments-agent/.env.example +7 -0
  362. package/templates/supplier-payments-agent/agents/supplier-payments-agent/AGENTS.md +21 -0
  363. package/templates/supplier-payments-agent/agents/supplier-payments-agent/CLAUDE.md +21 -0
  364. package/templates/supplier-payments-agent/agents/supplier-payments-agent/README.md +118 -0
  365. package/templates/supplier-payments-agent/agents/supplier-payments-agent/SYSTEM_PROMPT.md +29 -0
  366. package/templates/supplier-payments-agent/agents/supplier-payments-agent/agent.yaml +26 -0
  367. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/batch-tampering.json +12 -0
  368. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/batch-tampering.transcript.jsonl +3 -0
  369. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/beneficiary-swap-mandate.json +9 -0
  370. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/beneficiary-swap.json +10 -0
  371. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/beneficiary-swap.transcript.jsonl +2 -0
  372. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/exfiltration.json +13 -0
  373. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/exfiltration.transcript.jsonl +3 -0
  374. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/false-authority.json +9 -0
  375. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/false-authority.transcript.jsonl +3 -0
  376. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/fractioning.json +15 -0
  377. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/fractioning.transcript.jsonl +6 -0
  378. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/model-total.json +10 -0
  379. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/model-total.transcript.jsonl +2 -0
  380. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/prompt-injection.json +9 -0
  381. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/prompt-injection.transcript.jsonl +2 -0
  382. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/webhook-replay.json +9 -0
  383. package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/eval.yaml +9 -0
  384. package/templates/supplier-payments-agent/agents/supplier-payments-agent/guardrails.json +15 -0
  385. package/templates/supplier-payments-agent/agents/supplier-payments-agent/mandate.example.json +70 -0
  386. package/templates/supplier-payments-agent/agents/supplier-payments-agent/package.json +26 -0
  387. package/templates/supplier-payments-agent/agents/supplier-payments-agent/runbook.md +19 -0
  388. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/beneficiary-not-allowed.json +14 -0
  389. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/beneficiary-not-allowed.transcript.jsonl +2 -0
  390. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/cap-exceeded.json +12 -0
  391. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/cap-exceeded.transcript.jsonl +2 -0
  392. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/escalated-above-threshold.json +20 -0
  393. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/escalated-above-threshold.transcript.jsonl +7 -0
  394. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/happy-path.json +19 -0
  395. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/happy-path.transcript.jsonl +3 -0
  396. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/mandate-revoked.json +21 -0
  397. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/mandate-revoked.transcript.jsonl +9 -0
  398. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/partial-batch-failure.json +21 -0
  399. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/partial-batch-failure.transcript.jsonl +3 -0
  400. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/prompt-injection.json +12 -0
  401. package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/prompt-injection.transcript.jsonl +2 -0
  402. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/kit.ts +176 -0
  403. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/modules/batch-payout.ts +345 -0
  404. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/modules/pix-out.ts +118 -0
  405. package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/payables.ts +76 -0
  406. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/adversarial.test.ts +53 -0
  407. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/batch.test.ts +384 -0
  408. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/check.test.ts +109 -0
  409. package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/scenarios.test.ts +81 -0
  410. package/templates/supplier-payments-agent/agents/supplier-payments-agent/tools.json +53 -0
  411. package/templates/supplier-payments-agent/agents/supplier-payments-agent/tsconfig.json +9 -0
  412. package/templates/supplier-payments-agent/package.json +36 -0
  413. package/templates/supplier-payments-agent/packages/agent-core/README.md +21 -0
  414. package/templates/supplier-payments-agent/packages/agent-core/package.json +24 -0
  415. package/templates/supplier-payments-agent/packages/agent-core/src/agent.ts +125 -0
  416. package/templates/supplier-payments-agent/packages/agent-core/src/api/charge-rail.ts +175 -0
  417. package/templates/supplier-payments-agent/packages/agent-core/src/api/client.ts +53 -0
  418. package/templates/supplier-payments-agent/packages/agent-core/src/api/mandate-status.ts +58 -0
  419. package/templates/supplier-payments-agent/packages/agent-core/src/api/rail.ts +117 -0
  420. package/templates/supplier-payments-agent/packages/agent-core/src/api/sandbox-payer.ts +58 -0
  421. package/templates/supplier-payments-agent/packages/agent-core/src/approval.ts +123 -0
  422. package/templates/supplier-payments-agent/packages/agent-core/src/bundle.ts +159 -0
  423. package/templates/supplier-payments-agent/packages/agent-core/src/channels.ts +140 -0
  424. package/templates/supplier-payments-agent/packages/agent-core/src/check.ts +253 -0
  425. package/templates/supplier-payments-agent/packages/agent-core/src/clock.ts +42 -0
  426. package/templates/supplier-payments-agent/packages/agent-core/src/engine.ts +885 -0
  427. package/templates/supplier-payments-agent/packages/agent-core/src/escalate.ts +85 -0
  428. package/templates/supplier-payments-agent/packages/agent-core/src/events.ts +40 -0
  429. package/templates/supplier-payments-agent/packages/agent-core/src/guardrails.ts +45 -0
  430. package/templates/supplier-payments-agent/packages/agent-core/src/hash.ts +62 -0
  431. package/templates/supplier-payments-agent/packages/agent-core/src/ids.ts +10 -0
  432. package/templates/supplier-payments-agent/packages/agent-core/src/index.ts +32 -0
  433. package/templates/supplier-payments-agent/packages/agent-core/src/mandate.ts +100 -0
  434. package/templates/supplier-payments-agent/packages/agent-core/src/manifest.ts +76 -0
  435. package/templates/supplier-payments-agent/packages/agent-core/src/providers/anthropic.ts +76 -0
  436. package/templates/supplier-payments-agent/packages/agent-core/src/providers/replay.ts +63 -0
  437. package/templates/supplier-payments-agent/packages/agent-core/src/providers/types.ts +39 -0
  438. package/templates/supplier-payments-agent/packages/agent-core/src/rail.ts +101 -0
  439. package/templates/supplier-payments-agent/packages/agent-core/src/receipt-verification.ts +401 -0
  440. package/templates/supplier-payments-agent/packages/agent-core/src/revocation.ts +30 -0
  441. package/templates/supplier-payments-agent/packages/agent-core/src/secrets.ts +30 -0
  442. package/templates/supplier-payments-agent/packages/agent-core/src/state/store.ts +307 -0
  443. package/templates/supplier-payments-agent/packages/agent-core/src/state-machine.ts +148 -0
  444. package/templates/supplier-payments-agent/packages/agent-core/src/stubs/charge-rail.ts +195 -0
  445. package/templates/supplier-payments-agent/packages/agent-core/src/stubs/mandate-status.ts +57 -0
  446. package/templates/supplier-payments-agent/packages/agent-core/src/stubs/rail.ts +141 -0
  447. package/templates/supplier-payments-agent/packages/agent-core/src/tools.ts +55 -0
  448. package/templates/supplier-payments-agent/packages/agent-core/src/types.ts +134 -0
  449. package/templates/supplier-payments-agent/packages/agent-core/test/approval.test.ts +117 -0
  450. package/templates/supplier-payments-agent/packages/agent-core/test/bundle.test.ts +85 -0
  451. package/templates/supplier-payments-agent/packages/agent-core/test/clock.test.ts +25 -0
  452. package/templates/supplier-payments-agent/packages/agent-core/test/engine.test.ts +596 -0
  453. package/templates/supplier-payments-agent/packages/agent-core/test/escalate.test.ts +42 -0
  454. package/templates/supplier-payments-agent/packages/agent-core/test/fixtures/staging-receipt-keys.json +18 -0
  455. package/templates/supplier-payments-agent/packages/agent-core/test/fixtures/staging-receipt.json +24 -0
  456. package/templates/supplier-payments-agent/packages/agent-core/test/helpers.ts +139 -0
  457. package/templates/supplier-payments-agent/packages/agent-core/test/mandate-status.test.ts +153 -0
  458. package/templates/supplier-payments-agent/packages/agent-core/test/manifest.test.ts +45 -0
  459. package/templates/supplier-payments-agent/packages/agent-core/test/receipt-verification.test.ts +316 -0
  460. package/templates/supplier-payments-agent/packages/agent-core/test/receivables.test.ts +316 -0
  461. package/templates/supplier-payments-agent/packages/agent-core/test/secrets.test.ts +28 -0
  462. package/templates/supplier-payments-agent/packages/agent-core/test/state-machine.test.ts +67 -0
  463. package/templates/supplier-payments-agent/packages/agent-core/test/transitions.type-test.ts +59 -0
  464. package/templates/supplier-payments-agent/packages/agent-core/tsconfig.json +10 -0
  465. package/templates/supplier-payments-agent/packages/agent-runtime/README.md +68 -0
  466. package/templates/supplier-payments-agent/packages/agent-runtime/bin.mjs +32 -0
  467. package/templates/supplier-payments-agent/packages/agent-runtime/package.json +23 -0
  468. package/templates/supplier-payments-agent/packages/agent-runtime/src/adversarial.ts +169 -0
  469. package/templates/supplier-payments-agent/packages/agent-runtime/src/agent.ts +68 -0
  470. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/contact.ts +13 -0
  471. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/index.ts +72 -0
  472. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/rules.ts +120 -0
  473. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/types.ts +124 -0
  474. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +358 -0
  475. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +206 -0
  476. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/evidence.ts +109 -0
  477. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +225 -0
  478. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +143 -0
  479. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +47 -0
  480. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +113 -0
  481. package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +113 -0
  482. package/templates/supplier-payments-agent/packages/agent-runtime/src/cli.ts +98 -0
  483. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/check.ts +15 -0
  484. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/decide.ts +63 -0
  485. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/eval.ts +58 -0
  486. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/inspect.ts +100 -0
  487. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +317 -0
  488. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/poll.ts +144 -0
  489. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/reconcile.ts +42 -0
  490. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/rerun.ts +86 -0
  491. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/resume.ts +43 -0
  492. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +131 -0
  493. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/start.ts +245 -0
  494. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/verify.ts +129 -0
  495. package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/webhook.ts +39 -0
  496. package/templates/supplier-payments-agent/packages/agent-runtime/src/default-kit.ts +83 -0
  497. package/templates/supplier-payments-agent/packages/agent-runtime/src/index.ts +12 -0
  498. package/templates/supplier-payments-agent/packages/agent-runtime/src/inspect.ts +797 -0
  499. package/templates/supplier-payments-agent/packages/agent-runtime/src/kit.ts +206 -0
  500. package/templates/supplier-payments-agent/packages/agent-runtime/src/poll.ts +105 -0
  501. package/templates/supplier-payments-agent/packages/agent-runtime/src/scenarios.ts +268 -0
  502. package/templates/supplier-payments-agent/packages/agent-runtime/src/setup.ts +229 -0
  503. package/templates/supplier-payments-agent/packages/agent-runtime/src/terminal.ts +154 -0
  504. package/templates/supplier-payments-agent/packages/agent-runtime/src/webhook.ts +131 -0
  505. package/templates/supplier-payments-agent/packages/agent-runtime/test/inspect.test.ts +336 -0
  506. package/templates/supplier-payments-agent/packages/agent-runtime/test/verify-cli.test.ts +127 -0
  507. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +232 -0
  508. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +204 -0
  509. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-evidence.test.ts +94 -0
  510. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +174 -0
  511. package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-session.test.ts +135 -0
  512. package/templates/supplier-payments-agent/packages/agent-runtime/tsconfig.json +9 -0
  513. package/templates/supplier-payments-agent/tsconfig.base.json +16 -0
  514. package/templates/supplier-payments-agent/vitest.config.ts +12 -0
  515. package/templates/bills-agent/agents/bills-agent/channels/terminal/index.ts +0 -108
  516. package/templates/bills-agent/agents/bills-agent/src/commands/approve.ts +0 -9
  517. package/templates/bills-agent/agents/bills-agent/src/commands/check.ts +0 -13
  518. package/templates/bills-agent/agents/bills-agent/src/commands/consent.ts +0 -26
  519. package/templates/bills-agent/agents/bills-agent/src/commands/decide.ts +0 -45
  520. package/templates/bills-agent/agents/bills-agent/src/commands/deny.ts +0 -7
  521. package/templates/bills-agent/agents/bills-agent/src/commands/eval.ts +0 -37
  522. package/templates/bills-agent/agents/bills-agent/src/commands/reconcile.ts +0 -38
  523. package/templates/bills-agent/agents/bills-agent/src/commands/rerun.ts +0 -65
  524. package/templates/bills-agent/agents/bills-agent/src/commands/resume.ts +0 -30
  525. package/templates/bills-agent/agents/bills-agent/src/main.ts +0 -185
  526. package/templates/collections-agent/agents/collections-agent/channels/terminal/index.ts +0 -178
  527. package/templates/collections-agent/agents/collections-agent/src/commands/approve.ts +0 -10
  528. package/templates/collections-agent/agents/collections-agent/src/commands/check.ts +0 -13
  529. package/templates/collections-agent/agents/collections-agent/src/commands/decide.ts +0 -48
  530. package/templates/collections-agent/agents/collections-agent/src/commands/deny.ts +0 -7
  531. package/templates/collections-agent/agents/collections-agent/src/commands/eval.ts +0 -39
  532. package/templates/collections-agent/agents/collections-agent/src/commands/poll.ts +0 -35
  533. package/templates/collections-agent/agents/collections-agent/src/commands/reconcile.ts +0 -38
  534. package/templates/collections-agent/agents/collections-agent/src/commands/rerun.ts +0 -55
  535. package/templates/collections-agent/agents/collections-agent/src/commands/resume.ts +0 -30
  536. package/templates/collections-agent/agents/collections-agent/src/commands/webhook.ts +0 -36
  537. package/templates/collections-agent/agents/collections-agent/src/main.ts +0 -193
  538. package/templates/collections-agent/agents/collections-agent/src/setup.ts +0 -250
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * `codespar-agent <command> [args]`. The agent is the working directory (or
4
+ * the nearest ancestor holding an `agent.yaml`), so an agent's package.json
5
+ * script is the command and nothing else.
6
+ *
7
+ * The repository has no build step: the TypeScript runs through tsx, which
8
+ * needs the loader flag on the process that imports it. So this launcher is
9
+ * a real process boundary — the same one `node --import tsx src/main.ts`
10
+ * was before the runner moved here.
11
+ */
12
+ import { spawnSync } from "node:child_process";
13
+ import { fileURLToPath } from "node:url";
14
+
15
+ const cli = fileURLToPath(new URL("./src/cli.ts", import.meta.url));
16
+ // Resolved from THIS file and not from the working directory: `verify` runs
17
+ // wherever the receipt file is, which is usually not inside this repository,
18
+ // and a bare "tsx" would be looked up next to the caller's cwd and not found.
19
+ let loader = "tsx";
20
+ try {
21
+ loader = import.meta.resolve("tsx");
22
+ } catch {
23
+ // Left as the bare specifier: the error a missing tsx raises is the same
24
+ // one it raised before, and it names the package.
25
+ }
26
+ const result = spawnSync(process.execPath, ["--disable-warning=ExperimentalWarning", "--import", loader, cli, ...process.argv.slice(2)], { stdio: "inherit" });
27
+ if (result.error) {
28
+ process.stderr.write(`${result.error.message}\n`);
29
+ process.exit(1);
30
+ }
31
+ if (result.signal) process.kill(process.pid, result.signal);
32
+ process.exit(result.status ?? 1);
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@codespar/agent-runtime",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "description": "The runner every CodeSpar starter-kit agent shares: the terminal and WhatsApp channels and the commands (start, consent, approve, deny, resume, rerun, reconcile, poll, webhook, check, eval), parameterised by the agent directory.",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "main": "./src/index.ts",
9
+ "types": "./src/index.ts",
10
+ "exports": {
11
+ ".": "./src/index.ts"
12
+ },
13
+ "bin": {
14
+ "codespar-agent": "./bin.mjs"
15
+ },
16
+ "scripts": {
17
+ "typecheck": "tsc --noEmit -p tsconfig.json"
18
+ },
19
+ "dependencies": {
20
+ "@codespar/agent-core": "0.1.0",
21
+ "zod": "3.25.76"
22
+ }
23
+ }
@@ -11,15 +11,16 @@ import { tmpdir } from "node:os";
11
11
  import { basename, join, resolve } from "node:path";
12
12
  import { z } from "zod";
13
13
  import type { Execution } from "@codespar/agent-core";
14
- import { AGENT_DIR, RUNS_DIR, setup, type Setup } from "./setup.js";
15
- import { announceOutcome, handleExecution } from "../channels/terminal/index.js";
14
+ import type { Agent } from "./agent.js";
15
+ import { setup } from "./setup.js";
16
+ import { handleExecution } from "./terminal.js";
16
17
 
17
18
  const ExpectSchema = z
18
19
  .object({
19
20
  must_refuse: z.boolean().optional(),
20
21
  must_escalate: z.boolean().optional(),
21
22
  must_not_call: z.string().optional(),
22
- /** Fractioning: what the agent may issue alone in the window, at most. */
23
+ /** Fractioning: what the agent may run alone in the window, at most. */
23
24
  max_auto_settled_minor: z.number().int().optional(),
24
25
  /** The core's total, when the model claimed another. */
25
26
  core_total: z.number().int().optional(),
@@ -41,6 +42,8 @@ export const AdversarialCaseSchema = z
41
42
  kind: z.enum(["turn", "events"]).default("turn"),
42
43
  transcript: z.string().optional(),
43
44
  decision: z.enum(["approve", "deny", "none"]).default("none"),
45
+ /** Payees with a prior settled payment under this mandate, so `new_beneficiary` is not what fires. */
46
+ warm_payees: z.array(z.string()).default([]),
44
47
  /** Agreements with a prior settled receivable under this policy, so the velocity window has history. */
45
48
  warm_agreements: z.array(z.string()).default([]),
46
49
  now: z.string().datetime().default("2026-09-23T18:00:00.000Z"),
@@ -61,34 +64,35 @@ export interface AdversarialResult {
61
64
  run_id: string;
62
65
  }
63
66
 
64
- export function adversarialDir(): string {
65
- return join(AGENT_DIR, "evals", "adversarial");
67
+ export function adversarialDir(agent: Agent): string {
68
+ return join(agent.dir, "evals", "adversarial");
66
69
  }
67
70
 
68
- export function listAdversarialCases(): string[] {
69
- return readdirSync(adversarialDir())
71
+ export function listAdversarialCases(agent: Agent): string[] {
72
+ return readdirSync(adversarialDir(agent))
70
73
  .filter((f) => f.endsWith(".json"))
71
74
  .map((f) => basename(f, ".json"))
72
75
  .sort();
73
76
  }
74
77
 
75
- export function loadAdversarialCase(name: string): AdversarialCase {
76
- const path = join(adversarialDir(), `${name}.json`);
78
+ export function loadAdversarialCase(agent: Agent, name: string): AdversarialCase {
79
+ const path = join(adversarialDir(agent), `${name}.json`);
77
80
  if (!existsSync(path)) throw new Error(`unknown adversarial case ${name}`);
78
81
  return AdversarialCaseSchema.parse(JSON.parse(readFileSync(path, "utf8")));
79
82
  }
80
83
 
81
- export async function runAdversarialCase(kase: AdversarialCase, options: { runsDir?: string; say?: (l: string) => void } = {}): Promise<AdversarialResult> {
84
+ export async function runAdversarialCase(agent: Agent, kase: AdversarialCase, options: { runsDir?: string; say?: (l: string) => void } = {}): Promise<AdversarialResult> {
82
85
  const say = options.say ?? (() => undefined);
86
+ const awaitsPayer = agent.settlement === "await-payer";
83
87
  let clock = new Date(kase.now);
84
88
  const tick = () => (clock = new Date(clock.getTime() + 1000));
85
- const s = setup({
89
+ const s = setup(agent, {
86
90
  mode: kase.mode,
87
91
  rail: "stub",
88
92
  provider: "replay",
89
- transcript: kase.transcript ? resolve(adversarialDir(), kase.transcript) : undefined,
90
- runsDir: options.runsDir ?? RUNS_DIR,
91
- stateDir: mkdtempSync(join(tmpdir(), `collections-adv-${kase.name}-`)),
93
+ transcript: kase.transcript ? resolve(adversarialDir(agent), kase.transcript) : undefined,
94
+ runsDir: options.runsDir ?? join(agent.dir, "runs"),
95
+ stateDir: mkdtempSync(join(tmpdir(), `${agent.slug}-adv-${kase.name}-`)),
92
96
  runId: `run_adv_${kase.name}_${Date.now().toString(36)}`,
93
97
  now: tick,
94
98
  say,
@@ -96,26 +100,19 @@ export async function runAdversarialCase(kase: AdversarialCase, options: { runsD
96
100
  const replies: string[] = [];
97
101
  const called: string[] = [];
98
102
  const refused: string[] = [];
99
- const approver = { id: "usr_operator", channel: kase.channel };
103
+ const approver = { id: s.kit.labels.evalUser, channel: kase.channel };
100
104
  const tell = () => undefined;
101
105
 
102
106
  try {
103
- const warm = new Set<string>();
104
- for (const alias of kase.warm_agreements) {
105
- const d = await s.engine.draft({ items: [{ payee: alias, amount: 20000, due_date: "2026-09-30", description: "prior instalment" }] });
106
- if (!d.ok) throw new Error(`warm-up refused: ${d.reason}`);
107
- let e = d.execution;
108
- if (e.state === "awaiting_approval") e = s.engine.approve(e.id, approver);
109
- if (e.state === "approved") e = await s.engine.execute(e.id);
110
- for (let i = 0; i < 2 && e.state === "executing"; i += 1) e = await s.engine.reconcile(e.id);
111
- if (e.state !== "settled") throw new Error(`warm-up for ${alias} ended ${e.state} (${e.reason})`);
112
- warm.add(e.id);
113
- }
107
+ const warm = (await s.kit.warmUp?.(s, [...kase.warm_payees, ...kase.warm_agreements], approver)) ?? new Set<string>();
114
108
 
115
109
  if (kase.kind === "events") {
116
- await runEventsCase(s, tell);
110
+ if (!s.kit.runEventsCase) throw new Error(`${kase.name}: this agent's kit has no runEventsCase`);
111
+ await s.kit.runEventsCase(s, tell);
117
112
  } else {
118
- const loop = s.makeLoop(s.makeRuntime(), (execution: Execution) => handleExecution(execution, { setup: s, approver, decision: kase.decision, say, tell, simulatePayer: true }));
113
+ const loop = s.makeLoop(s.makeRuntime(), (execution: Execution) =>
114
+ handleExecution(execution, { setup: s, approver, decision: kase.decision, say, ...(awaitsPayer ? { tell, simulatePayer: true } : {}) }),
115
+ );
119
116
  const result = await loop.turn(kase.input);
120
117
  replies.push(result.reply);
121
118
  for (const c of result.tool_calls) (c.refused ? refused : called).push(c.name);
@@ -159,8 +156,10 @@ export async function runAdversarialCase(kase: AdversarialCase, options: { runsD
159
156
  const settledTransitions = s.store.listEvents({ run_id: s.runId }).filter((ev) => ev.type === "execution.transition" && (ev.payload as { to: string }).to === "settled");
160
157
  if (settledTransitions.length !== 1) failures.push(`settled_once: ${settledTransitions.length} settled transitions`);
161
158
  if (states.length !== 1 || states[0] !== "settled") failures.push(`settled_once: states ${JSON.stringify(states)}`);
162
- const messages = s.store.listEvents({ run_id: s.runId }).filter((ev) => ev.type === "message.debtor");
163
- if (messages.length !== 1) failures.push(`settled_once: the debtor was told ${messages.length} times`);
159
+ if (awaitsPayer) {
160
+ const messages = s.store.listEvents({ run_id: s.runId }).filter((ev) => ev.type === "message.debtor");
161
+ if (messages.length !== 1) failures.push(`settled_once: the debtor was told ${messages.length} times`);
162
+ }
164
163
  }
165
164
 
166
165
  return { name: kase.name, attack: kase.attack, ok: failures.length === 0, failures, states, tools_called: called, tools_refused: refused, run_id: s.runId };
@@ -168,23 +167,3 @@ export async function runAdversarialCase(kase: AdversarialCase, options: { runsD
168
167
  s.close();
169
168
  }
170
169
  }
171
-
172
- /** Webhook duplicated or out of order: the same `commerce.charge.paid` twice, `paid` before `created`, `expired` after `paid`. One settled, one message. */
173
- async function runEventsCase(s: Setup, tell: (l: string) => void): Promise<void> {
174
- s.payer.behave("never");
175
- const draft = await s.engine.draft({ items: [{ payee: "acordo-1042", amount: 108000, due_date: "2026-09-30" }] });
176
- if (!draft.ok) throw new Error("refused");
177
- let execution = draft.execution;
178
- if (execution.state === "awaiting_approval") execution = s.engine.approve(execution.id, { id: "usr_operator", channel: "terminal" });
179
- execution = await s.engine.execute(execution.id);
180
- const chargeId = execution.outcomes[0]!.transaction_id!;
181
- const apply = (event_id: string, type: string) => {
182
- s.engine.ingestExternalEvent({ event_id, type, transaction_id: chargeId });
183
- announceOutcome(s.engine.get(execution.id)!, s, tell);
184
- };
185
- apply("evt_paid_1", "commerce.charge.paid");
186
- apply("evt_paid_1", "commerce.charge.paid");
187
- apply("evt_created_late", "commerce.charge.created");
188
- apply("evt_paid_2", "commerce.charge.paid");
189
- apply("evt_expired_late", "commerce.charge.expired");
190
- }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Which agent a command is running. Every function of the runner takes one:
3
+ * the directory that holds `agent.yaml` and the kit that directory exports.
4
+ * Nothing else in the runner knows an agent's name.
5
+ */
6
+ import { existsSync, readFileSync } from "node:fs";
7
+ import { dirname, join, resolve } from "node:path";
8
+ import { fileURLToPath, pathToFileURL } from "node:url";
9
+ import type { AgentKit, Settlement } from "./kit.js";
10
+ import { defaultKit } from "./default-kit.js";
11
+
12
+ export interface Agent {
13
+ /** The directory holding `agent.yaml`. */
14
+ dir: string;
15
+ kit: AgentKit;
16
+ /** `bills-agent` -> `bills`: the temp-directory and env-variable prefix. */
17
+ slug: string;
18
+ settlement: Settlement;
19
+ }
20
+
21
+ /** The nearest ancestor of `from` that holds an `agent.yaml`, `from` included. */
22
+ export function findAgentDir(from: string): string | undefined {
23
+ let dir = resolve(from);
24
+ for (;;) {
25
+ if (existsSync(join(dir, "agent.yaml"))) return dir;
26
+ const up = dirname(dir);
27
+ if (up === dir) return undefined;
28
+ dir = up;
29
+ }
30
+ }
31
+
32
+ function slugOf(agentDir: string): string {
33
+ const m = /^\s*name:\s*"?([a-z0-9-]+)"?/m.exec(readFileSync(join(agentDir, "agent.yaml"), "utf8"));
34
+ return (m?.[1] ?? "agent").replace(/-agent$/, "");
35
+ }
36
+
37
+ /** The handle an agent's `src/kit.ts` exports: `export const agent = defineAgent(import.meta.url, kit)`. */
38
+ export function defineAgent(moduleUrl: string, kit: AgentKit): Agent {
39
+ const dir = findAgentDir(dirname(fileURLToPath(moduleUrl)));
40
+ if (!dir) throw new Error(`no agent.yaml above ${moduleUrl}`);
41
+ return { dir, kit, slug: slugOf(dir), settlement: kit.settlement ?? "immediate" };
42
+ }
43
+
44
+ /**
45
+ * The agent a `codespar-agent` invocation runs against: `CODESPAR_AGENT_DIR`,
46
+ * else the nearest `agent.yaml` at or above the working directory. Its kit is
47
+ * `src/kit.ts` (or `kit.ts`) if it ships one, and `defaultKit` if it does not.
48
+ */
49
+ export async function loadAgent(dir?: string): Promise<Agent> {
50
+ const start = dir ?? process.env["CODESPAR_AGENT_DIR"] ?? process.cwd();
51
+ const agentDir = findAgentDir(start);
52
+ if (!agentDir) throw new Error(`no agent.yaml at or above ${start}; run the command inside an agent directory`);
53
+ for (const rel of ["src/kit.ts", "kit.ts"]) {
54
+ const path = join(agentDir, rel);
55
+ if (!existsSync(path)) continue;
56
+ const module = (await import(pathToFileURL(path).href)) as { agent?: Agent; kit?: AgentKit; default?: AgentKit };
57
+ if (module.agent) return module.agent;
58
+ const kit = module.kit ?? module.default;
59
+ if (!kit) throw new Error(`${rel} must export \`agent\` (defineAgent) or \`kit\``);
60
+ return { dir: agentDir, kit, slug: slugOf(agentDir), settlement: kit.settlement ?? "immediate" };
61
+ }
62
+ return { dir: agentDir, kit: defaultKit, slug: slugOf(agentDir), settlement: "immediate" };
63
+ }
64
+
65
+ /** `BILLS_STATE_DIR` for `bills-agent`: the test-only overrides are namespaced by the agent. */
66
+ export function envName(agent: Agent, name: string): string {
67
+ return `${agent.slug.toUpperCase().replace(/-/g, "_")}_${name}`;
68
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * How a contact is written down.
3
+ *
4
+ * A conversation log travels: it goes in the proof bundle, and the bundle is
5
+ * the thing somebody sends to somebody else. The person's number is not part
6
+ * of what a bundle has to prove, so it never reaches one in the clear.
7
+ */
8
+
9
+ /** `+5511987654321` -> `+55 11 ****4321`. What the console and the bundle see. */
10
+ export function maskContact(contact: string): string {
11
+ if (!contact.startsWith("+") || contact.length < 8) return "***";
12
+ return `${contact.slice(0, 5)} ****${contact.slice(-4)}`;
13
+ }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Which channels the runner can open, and how one is opened for an agent.
3
+ *
4
+ * The runner owns channels; an agent owns the CONVERSATIONS it ships for one
5
+ * (`channels/whatsapp/*.json`). That is the split `npm run check` enforces in
6
+ * both directions: declare a channel and ship no conversation for it and the
7
+ * manifest gate fails; ship one and declare nothing and it fails too.
8
+ */
9
+ import { existsSync, readFileSync, readdirSync } from "node:fs";
10
+ import { basename, join } from "node:path";
11
+ import { parseConversationScript, parseTemplateRegistry, TEMPLATE_REGISTRY_FILE, type ChannelName, type ConversationScript, type WhatsAppTemplate } from "@codespar/agent-core";
12
+ import type { Agent } from "../agent.js";
13
+
14
+ export * from "./types.js";
15
+ export * from "./rules.js";
16
+ export * from "./whatsapp/index.js";
17
+ export * from "./whatsapp/run.js";
18
+
19
+ export function conversationsDir(agent: Agent): string {
20
+ return join(agent.dir, "channels", "whatsapp");
21
+ }
22
+
23
+ export function listConversations(agent: Agent): string[] {
24
+ const dir = conversationsDir(agent);
25
+ if (!existsSync(dir)) return [];
26
+ return readdirSync(dir)
27
+ .filter((f) => f.endsWith(".json") && f !== TEMPLATE_REGISTRY_FILE)
28
+ .map((f) => basename(f, ".json"))
29
+ .sort();
30
+ }
31
+
32
+ /**
33
+ * The templates this agent declares, or none. An agent that never speaks
34
+ * outside the session window ships no registry and the channel then refuses
35
+ * every template, which is the honest answer: a template nobody declared is
36
+ * one Meta was never asked to approve.
37
+ */
38
+ export function loadTemplates(agent: Agent): WhatsAppTemplate[] {
39
+ const path = join(conversationsDir(agent), TEMPLATE_REGISTRY_FILE);
40
+ if (!existsSync(path)) return [];
41
+ return parseTemplateRegistry(readFileSync(path, "utf8")).templates;
42
+ }
43
+
44
+ export function loadConversation(agent: Agent, name: string): ConversationScript {
45
+ const path = join(conversationsDir(agent), `${name}.json`);
46
+ if (!existsSync(path)) throw new Error(`unknown conversation ${name}; available: ${listConversations(agent).join(", ") || "none"}`);
47
+ return parseConversationScript(readFileSync(path, "utf8"));
48
+ }
49
+
50
+ /**
51
+ * The conversation a run binds to: the one named, or the only one the agent
52
+ * ships. An agent with several and no `--conversation` is asked rather than
53
+ * guessed for — which debtor a message goes to is not a default.
54
+ */
55
+ export function resolveConversation(agent: Agent, name: string | undefined): ConversationScript {
56
+ const available = listConversations(agent);
57
+ if (name) return loadConversation(agent, name);
58
+ if (available.length === 1) return loadConversation(agent, available[0]!);
59
+ if (available.length === 0) throw new Error(`${agent.slug} ships no conversation under channels/whatsapp/`);
60
+ throw new Error(`--conversation is required: ${agent.slug} ships ${available.join(", ")}`);
61
+ }
62
+
63
+ /** Every subject the agent has a conversation for, so "names another agreement" is decidable. */
64
+ export function knownSubjects(agent: Agent): string[] {
65
+ return listConversations(agent)
66
+ .map((name) => loadConversation(agent, name).subject)
67
+ .filter((s): s is string => typeof s === "string");
68
+ }
69
+
70
+ export function isChannelName(value: string): value is ChannelName {
71
+ return value === "terminal" || value === "whatsapp";
72
+ }
@@ -0,0 +1,120 @@
1
+ /**
2
+ * The rules of collecting over a conversation, as code.
3
+ *
4
+ * The spec names four (section 16): the hours, the secrecy of the debt, no
5
+ * embarrassment, LGPD. Two of those are decidable by a machine and are
6
+ * enforced here, on EVERY outbound message, above the backend — so choosing
7
+ * the simulator or the official API changes nothing about what may be said.
8
+ * The other two are the prompt's and the operator's: no code can read a
9
+ * sentence and tell whether it shames somebody.
10
+ *
11
+ * hours nothing is sent outside the collection window. The
12
+ * envelope already refuses to DRAFT a receivable outside
13
+ * it; this refuses to SPEAK outside it, which is the rule
14
+ * the law actually states.
15
+ * bound contact a message goes to the person the conversation is bound to
16
+ * and to no other number. This is the secrecy rule: the way
17
+ * a debt reaches a third party is by being sent to one.
18
+ * subject a message may not name an agreement other than this
19
+ * conversation's. Same rule, other direction: the debtor
20
+ * learning about somebody else's debt.
21
+ * no document a CPF or a CNPJ never appears in a message. The prompt
22
+ * says so; this makes it true even if the model ignores it.
23
+ *
24
+ * Every rule can only REFUSE. None of them rewrites a message: a message
25
+ * that is edited on the way out is not the message the transcript shows.
26
+ */
27
+ import { isOutsideHours, localClock } from "@codespar/agent-core";
28
+ import type { Conversation, OutboundBody } from "./types.js";
29
+
30
+ export interface ChannelRefusal {
31
+ rule: string;
32
+ detail: string;
33
+ }
34
+
35
+ export interface HoursRule {
36
+ /** The OPEN window, `HH:MM-HH:MM`, as `guardrails.envelope.collection_hours` spells it. */
37
+ window: string;
38
+ timezone: string;
39
+ }
40
+
41
+ export interface RuleContext {
42
+ conversation: Conversation;
43
+ hours?: HoursRule | undefined;
44
+ now: () => Date;
45
+ /** Agreement aliases this agent knows, so "names another agreement" is decidable. */
46
+ knownSubjects?: readonly string[] | undefined;
47
+ }
48
+
49
+ /** `123.456.789-00`, `12345678900`, `12.345.678/0001-95`, `12345678000195`. */
50
+ const FORMATTED_DOCUMENT = /\b\d{3}\.\d{3}\.\d{3}-\d{2}\b|\b\d{2}\.\d{3}\.\d{3}\/\d{4}-\d{2}\b/;
51
+
52
+ /**
53
+ * A bare document is a token of exactly 11 or 14 digits. Token-wise and not
54
+ * substring-wise on purpose: a Pix BR Code is one token of 100+ characters
55
+ * and a substring rule would find a "CPF" inside every payable message.
56
+ */
57
+ function hasBareDocument(text: string): boolean {
58
+ return text
59
+ .split(/\s+/)
60
+ .map((t) => t.replace(/^[^0-9]+|[^0-9]+$/g, ""))
61
+ .some((t) => /^\d{11}$/.test(t) || /^\d{14}$/.test(t));
62
+ }
63
+
64
+ /** The prose a rule reads. The rail's own strings are not prose and are not read. */
65
+ export function proseOf(body: OutboundBody): string[] {
66
+ switch (body.kind) {
67
+ case "text":
68
+ return [body.text];
69
+ case "media":
70
+ return body.caption === undefined ? [] : [body.caption];
71
+ case "template":
72
+ return body.variables;
73
+ case "instrument":
74
+ return [];
75
+ }
76
+ }
77
+
78
+ /** `undefined` when the message may go out. The first refusal wins, so the reason is stable. */
79
+ export function checkOutbound(to: string, body: OutboundBody, ctx: RuleContext): ChannelRefusal | undefined {
80
+ if (to !== ctx.conversation.contact) {
81
+ return {
82
+ rule: "bound_contact",
83
+ detail: "a collection message goes to the person who owes and to nobody else; this conversation is bound to another contact",
84
+ };
85
+ }
86
+
87
+ if (ctx.hours) {
88
+ const [open, close] = ctx.hours.window.split("-") as [string, string];
89
+ // The envelope states the OPEN window; `isOutsideHours` reads a CLOSED one, so it is inverted here the same way the envelope policy inverts it.
90
+ if (isOutsideHours(`${close}-${open}`, ctx.now(), ctx.hours.timezone)) {
91
+ return {
92
+ rule: "collection_hours",
93
+ detail: `fora do horario de cobranca (${ctx.hours.window} ${ctx.hours.timezone}); agora sao ${localClock(ctx.now(), ctx.hours.timezone)}`,
94
+ };
95
+ }
96
+ }
97
+
98
+ const prose = proseOf(body);
99
+
100
+ for (const text of prose) {
101
+ if (FORMATTED_DOCUMENT.test(text) || hasBareDocument(text)) {
102
+ return { rule: "no_document", detail: "a message must not carry a CPF or a CNPJ; the code takes the document from the agreement and never speaks it" };
103
+ }
104
+ }
105
+
106
+ const subject = ctx.conversation.subject;
107
+ if (subject && ctx.knownSubjects?.length) {
108
+ for (const text of prose) {
109
+ const lowered = text.toLowerCase();
110
+ const other = ctx.knownSubjects.find((s) => s !== subject && lowered.includes(s.toLowerCase()));
111
+ if (other) {
112
+ return { rule: "subject_scope", detail: `this conversation is about ${subject}; a message here may not name ${other}` };
113
+ }
114
+ }
115
+ }
116
+
117
+ if (body.kind === "text" && body.text.trim() === "") return { rule: "empty_message", detail: "an empty message is not a message" };
118
+
119
+ return undefined;
120
+ }
@@ -0,0 +1,124 @@
1
+ /**
2
+ * One interface, several backends. What a channel is, from the runner's side:
3
+ * a place a person writes from, a place the agent writes to, and a record of
4
+ * what happened to each message.
5
+ *
6
+ * The shape is deliberately the shape of a MESSAGING channel and not of a
7
+ * terminal, because the two are not the same thing and pretending they are is
8
+ * how an approval question ends up in a debtor's chat. A terminal has one
9
+ * stream and one reader; a channel has a counterparty on one side and an
10
+ * operator somewhere else entirely, and the runner keeps them apart by
11
+ * construction: `send` reaches the counterparty, and the operator's console
12
+ * and questions never touch it.
13
+ *
14
+ * Every backend answers the same five questions, and the ADAPTER above them
15
+ * (`whatsapp/index.ts`) is where the rules live, so a rule cannot be skipped
16
+ * by choosing a different backend.
17
+ */
18
+ import type { ChannelName } from "@codespar/agent-core";
19
+
20
+ /**
21
+ * What a provider tells us about a message after it left. `queued` is ours
22
+ * (accepted, not yet handed over); the rest are the provider's own, and a
23
+ * backend that cannot observe one never invents it.
24
+ */
25
+ export type DeliveryState = "queued" | "sent" | "delivered" | "read" | "failed";
26
+
27
+ export interface InboundMessage {
28
+ /** The PROVIDER's message id (`wamid....` on WhatsApp). Never ours. */
29
+ id: string;
30
+ /** Who wrote it, E.164 on WhatsApp. */
31
+ from: string;
32
+ text: string;
33
+ /** Unix seconds on the PROVIDER's clock, which is not this process's clock. */
34
+ timestamp: number;
35
+ }
36
+
37
+ /**
38
+ * What the agent can put on a channel.
39
+ *
40
+ * `text` is the ordinary message. `media` is a QR, which on WhatsApp is an
41
+ * image and never ASCII art. `template` is the only thing a provider accepts
42
+ * outside the 24-hour session window, which is why it is a separate kind
43
+ * rather than a flag.
44
+ *
45
+ * `instrument` is the Pix copy-and-paste or the boleto line, and it is its own
46
+ * kind for a reason that is not cosmetic: those strings are minted by the rail
47
+ * and are long runs of digits, and the rule that keeps a CPF out of a message
48
+ * would refuse a boleto line (whose last field is fourteen digits) if it read
49
+ * one as prose. Separating them says which strings the conversation composed
50
+ * and which the rail did, and only the first are checked for a document.
51
+ */
52
+ export type OutboundBody =
53
+ | { kind: "text"; text: string }
54
+ | { kind: "media"; media: "qr"; data: string; caption?: string }
55
+ | { kind: "instrument"; instrument: "pix_copy_paste" | "boleto_bank_line"; value: string }
56
+ | { kind: "template"; template: string; language: string; variables: string[] };
57
+
58
+ export interface SentMessage {
59
+ /** The provider's id when it accepted one, else the id the backend minted. */
60
+ id: string;
61
+ state: DeliveryState;
62
+ /**
63
+ * Set when something REFUSED the message. Nothing left the process: a
64
+ * refusal here is not a delivery failure, it is the message never having
65
+ * been sent. `rule` is the stable name a test and a log both key on.
66
+ */
67
+ refused?: { rule: string; detail: string };
68
+ }
69
+
70
+ /** What the person on the other side is called, and what the conversation may be about. */
71
+ export interface Conversation {
72
+ /** The contact the conversation is bound to. Every outbound goes here and nowhere else. */
73
+ contact: string;
74
+ /** What the conversation may name — an agreement alias. Absent means the channel enforces no subject rule. */
75
+ subject?: string | undefined;
76
+ }
77
+
78
+ export interface ChannelBackend {
79
+ /** `simulator`, `cloud-api`. Named in the console, in the bundle and in the gate's output. */
80
+ readonly name: string;
81
+ /** Whether this backend talks to a real provider. The gate and the tests refuse to run a live one. */
82
+ readonly live: boolean;
83
+ open(): Promise<void>;
84
+ /** The next inbound message, or `undefined` when the conversation is over. */
85
+ next(): Promise<InboundMessage | undefined>;
86
+ /** Hands the message to the provider. Rules have already run: a backend never re-decides policy. */
87
+ deliver(to: string, body: OutboundBody): Promise<SentMessage>;
88
+ close(): Promise<void>;
89
+ }
90
+
91
+ export interface Channel {
92
+ readonly name: ChannelName;
93
+ readonly backend: string;
94
+ readonly conversation: Conversation;
95
+ open(): Promise<void>;
96
+ next(): Promise<InboundMessage | undefined>;
97
+ /** Applies the channel's rules, then delivers. A refused message is recorded and never sent. */
98
+ send(body: OutboundBody): Promise<SentMessage>;
99
+ /** Convenience for the common case. */
100
+ say(text: string): Promise<SentMessage>;
101
+ close(): Promise<void>;
102
+ /** Every message of this conversation, in order, as the bundle records it. */
103
+ log(): ReadonlyArray<ChannelLogLine>;
104
+ }
105
+
106
+ export interface ChannelLogLine {
107
+ at: string;
108
+ direction: "in" | "out";
109
+ /** The contact, MASKED. The raw value never reaches a file. */
110
+ contact: string;
111
+ kind: OutboundBody["kind"];
112
+ /** The provider's id, or ours when nothing was sent. */
113
+ message_id: string;
114
+ state: DeliveryState;
115
+ text?: string;
116
+ /**
117
+ * Inbound only: the PROVIDER's own timestamp, unix seconds. Recorded
118
+ * because the 24-hour session window is counted on WhatsApp's clock and
119
+ * `at` is this process's, and a later run has to read the window back from
120
+ * this log rather than from a clock it does not share.
121
+ */
122
+ provider_timestamp?: number;
123
+ refused?: { rule: string; detail: string };
124
+ }