@codespar/cli 0.16.0 → 0.18.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.
- package/README.md +1 -0
- package/dist/commands/mandate-verify.js +98 -19
- package/dist/commands/mandate-verify.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mandate-codec.js +31 -20
- package/dist/mandate-codec.js.map +1 -1
- package/package.json +1 -1
- package/templates/bills-agent/README.md +1 -1
- package/templates/bills-agent/agents/bills-agent/AGENTS.md +1 -1
- package/templates/bills-agent/agents/bills-agent/CLAUDE.md +1 -1
- package/templates/bills-agent/agents/bills-agent/README.md +6 -5
- package/templates/bills-agent/agents/bills-agent/src/modules/embedded-consent.ts +5 -4
- package/templates/bills-agent/packages/agent-core/README.md +14 -1
- package/templates/bills-agent/packages/agent-core/package.json +1 -1
- package/templates/bills-agent/packages/agent-core/src/agent.ts +39 -1
- package/templates/bills-agent/packages/agent-core/src/api/charge-rail.ts +54 -34
- package/templates/bills-agent/packages/agent-core/src/api/client.ts +28 -5
- package/templates/bills-agent/packages/agent-core/src/api/mandate-status.ts +28 -12
- package/templates/bills-agent/packages/agent-core/src/api/rail.ts +62 -26
- package/templates/bills-agent/packages/agent-core/src/api/sandbox-payer.ts +3 -18
- package/templates/bills-agent/packages/agent-core/src/approval.ts +14 -2
- package/templates/bills-agent/packages/agent-core/src/bundle.ts +35 -3
- package/templates/bills-agent/packages/agent-core/src/channels.ts +49 -3
- package/templates/bills-agent/packages/agent-core/src/check.ts +25 -2
- package/templates/bills-agent/packages/agent-core/src/engine.ts +235 -46
- package/templates/bills-agent/packages/agent-core/src/hash.ts +57 -1
- package/templates/bills-agent/packages/agent-core/src/index.ts +2 -0
- package/templates/bills-agent/packages/agent-core/src/quote.ts +50 -0
- package/templates/bills-agent/packages/agent-core/src/rail.ts +89 -4
- package/templates/bills-agent/packages/agent-core/src/receipt-chain.ts +270 -0
- package/templates/bills-agent/packages/agent-core/src/receipt-verification.ts +194 -18
- package/templates/bills-agent/packages/agent-core/src/revocation.ts +1 -1
- package/templates/bills-agent/packages/agent-core/src/state-machine.ts +10 -1
- package/templates/bills-agent/packages/agent-core/src/stubs/mandate-status.ts +4 -3
- package/templates/bills-agent/packages/agent-core/src/stubs/rail.ts +100 -32
- package/templates/bills-agent/packages/agent-core/src/tools.ts +17 -6
- package/templates/bills-agent/packages/agent-core/src/types.ts +54 -1
- package/templates/bills-agent/packages/agent-core/test/approval-seal.test.ts +233 -0
- package/templates/bills-agent/packages/agent-core/test/attempt-replay.test.ts +265 -0
- package/templates/bills-agent/packages/agent-core/test/composition.test.ts +204 -0
- package/templates/bills-agent/packages/agent-core/test/fixtures/production-receipt-keys.json +1 -0
- package/templates/bills-agent/packages/agent-core/test/helpers.ts +4 -1
- package/templates/bills-agent/packages/agent-core/test/mandate-status.test.ts +85 -9
- package/templates/bills-agent/packages/agent-core/test/quote.test.ts +198 -0
- package/templates/bills-agent/packages/agent-core/test/receipt-chain.test.ts +220 -0
- package/templates/bills-agent/packages/agent-core/test/receipt-read-verification.test.ts +197 -0
- package/templates/bills-agent/packages/agent-core/test/receivables.test.ts +103 -3
- package/templates/bills-agent/packages/agent-runtime/README.md +12 -0
- package/templates/bills-agent/packages/agent-runtime/src/adversarial.ts +32 -2
- package/templates/bills-agent/packages/agent-runtime/src/channels/types.ts +53 -4
- package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +123 -22
- package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +30 -20
- package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +146 -21
- package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +40 -3
- package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -1
- package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +16 -2
- package/templates/bills-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +70 -20
- package/templates/bills-agent/packages/agent-runtime/src/commands/poll.ts +2 -1
- package/templates/bills-agent/packages/agent-runtime/src/commands/resume.ts +8 -2
- package/templates/bills-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +3 -0
- package/templates/bills-agent/packages/agent-runtime/src/commands/start.ts +6 -3
- package/templates/bills-agent/packages/agent-runtime/src/commands/verify.ts +239 -38
- package/templates/bills-agent/packages/agent-runtime/src/commands/webhook.ts +3 -2
- package/templates/bills-agent/packages/agent-runtime/src/index.ts +1 -0
- package/templates/bills-agent/packages/agent-runtime/src/inspect.ts +5 -1
- package/templates/bills-agent/packages/agent-runtime/src/kit.ts +25 -2
- package/templates/bills-agent/packages/agent-runtime/src/scenarios.ts +8 -2
- package/templates/bills-agent/packages/agent-runtime/src/setup.ts +13 -3
- package/templates/bills-agent/packages/agent-runtime/src/terminal.ts +127 -18
- package/templates/bills-agent/packages/agent-runtime/test/verify-cli.test.ts +211 -9
- package/templates/bills-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +45 -0
- package/templates/bills-agent/packages/agent-runtime/test/whatsapp-session.test.ts +32 -0
- package/templates/bills-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +182 -0
- package/templates/checkout-agent/LICENSE +21 -0
- package/templates/checkout-agent/README.md +28 -0
- package/templates/checkout-agent/_gitignore +10 -0
- package/templates/checkout-agent/agents/checkout-agent/.env.example +5 -0
- package/templates/checkout-agent/agents/checkout-agent/AGENTS.md +20 -0
- package/templates/checkout-agent/agents/checkout-agent/CLAUDE.md +20 -0
- package/templates/checkout-agent/agents/checkout-agent/README.md +94 -0
- package/templates/checkout-agent/agents/checkout-agent/SYSTEM_PROMPT.md +36 -0
- package/templates/checkout-agent/agents/checkout-agent/agent.yaml +30 -0
- package/templates/checkout-agent/agents/checkout-agent/channels/whatsapp/README.md +28 -0
- package/templates/checkout-agent/agents/checkout-agent/channels/whatsapp/pedido-beatriz.json +11 -0
- package/templates/checkout-agent/agents/checkout-agent/channels/whatsapp/pedido-marina-retomada.json +10 -0
- package/templates/checkout-agent/agents/checkout-agent/channels/whatsapp/pedido-marina.json +11 -0
- package/templates/checkout-agent/agents/checkout-agent/channels/whatsapp/templates.json +49 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/beneficiary-swap-human.json +12 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/beneficiary-swap.json +11 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/beneficiary-swap.transcript.jsonl +5 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/coupon-unknown.json +13 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/coupon-unknown.transcript.jsonl +4 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/exfiltration.json +26 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/exfiltration.transcript.jsonl +3 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/false-authority.json +11 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/false-authority.transcript.jsonl +5 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/fractioning.json +12 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/fractioning.transcript.jsonl +5 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/model-total.json +13 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/model-total.transcript.jsonl +5 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/payment-claimed.json +15 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/payment-claimed.transcript.jsonl +7 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/price-injected.json +12 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/price-injected.transcript.jsonl +5 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/prompt-injection.json +13 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/prompt-injection.transcript.jsonl +4 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/quantity-swapped-human.json +16 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/quantity-swapped-human.transcript.jsonl +9 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/quantity-swapped.json +15 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/quantity-swapped.transcript.jsonl +8 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/webhook-replay.json +11 -0
- package/templates/checkout-agent/agents/checkout-agent/evals/eval.yaml +11 -0
- package/templates/checkout-agent/agents/checkout-agent/guardrails.json +25 -0
- package/templates/checkout-agent/agents/checkout-agent/mandate.example.json +28 -0
- package/templates/checkout-agent/agents/checkout-agent/package.json +33 -0
- package/templates/checkout-agent/agents/checkout-agent/runbook.md +19 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/beneficiary-not-allowed.json +42 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/beneficiary-not-allowed.transcript.jsonl +4 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/cap-exceeded.json +32 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/cap-exceeded.transcript.jsonl +4 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/cart-recomposed.json +61 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/cart-recomposed.transcript.jsonl +9 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/cart-replaced.json +61 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/cart-replaced.transcript.jsonl +9 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/charge-expired.json +36 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/charge-expired.transcript.jsonl +6 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/coupon-unknown.json +23 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/coupon-unknown.transcript.jsonl +4 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/escalated-above-threshold.json +72 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/escalated-above-threshold.transcript.jsonl +9 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/happy-path.json +15 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/happy-path.transcript.jsonl +6 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/item-unavailable.json +23 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/item-unavailable.transcript.jsonl +3 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/mandate-revoked.json +42 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/mandate-revoked.transcript.jsonl +12 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/nfse-failed.json +14 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/nfse-failed.transcript.jsonl +9 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/payment-claimed.json +34 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/payment-claimed.transcript.jsonl +7 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/price-injected.json +33 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/price-injected.transcript.jsonl +4 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/prompt-injection.json +32 -0
- package/templates/checkout-agent/agents/checkout-agent/scenarios/prompt-injection.transcript.jsonl +4 -0
- package/templates/checkout-agent/agents/checkout-agent/src/catalog.ts +92 -0
- package/templates/checkout-agent/agents/checkout-agent/src/kit.ts +338 -0
- package/templates/checkout-agent/agents/checkout-agent/src/modules/bolepix-receivables.ts +179 -0
- package/templates/checkout-agent/agents/checkout-agent/src/modules/nfse-invoice.ts +374 -0
- package/templates/checkout-agent/agents/checkout-agent/src/modules/storefront-cart.ts +220 -0
- package/templates/checkout-agent/agents/checkout-agent/src/pricing.ts +297 -0
- package/templates/checkout-agent/agents/checkout-agent/test/adversarial.test.ts +117 -0
- package/templates/checkout-agent/agents/checkout-agent/test/check.test.ts +67 -0
- package/templates/checkout-agent/agents/checkout-agent/test/cli.test.ts +169 -0
- package/templates/checkout-agent/agents/checkout-agent/test/fixtures/order-marina.transcript.jsonl +5 -0
- package/templates/checkout-agent/agents/checkout-agent/test/fixtures/ordered-marina-awaiting-payer.transcript.jsonl +6 -0
- package/templates/checkout-agent/agents/checkout-agent/test/fixtures/tap-falar-agora-marina.transcript.jsonl +2 -0
- package/templates/checkout-agent/agents/checkout-agent/test/nfse.test.ts +170 -0
- package/templates/checkout-agent/agents/checkout-agent/test/pricing.test.ts +138 -0
- package/templates/checkout-agent/agents/checkout-agent/test/scenarios.test.ts +113 -0
- package/templates/checkout-agent/agents/checkout-agent/test/whatsapp.test.ts +171 -0
- package/templates/checkout-agent/agents/checkout-agent/tools.json +68 -0
- package/templates/checkout-agent/agents/checkout-agent/tsconfig.json +10 -0
- package/templates/checkout-agent/package.json +38 -0
- package/templates/checkout-agent/packages/agent-core/README.md +34 -0
- package/templates/checkout-agent/packages/agent-core/package.json +24 -0
- package/templates/checkout-agent/packages/agent-core/src/agent.ts +163 -0
- package/templates/checkout-agent/packages/agent-core/src/api/charge-rail.ts +195 -0
- package/templates/checkout-agent/packages/agent-core/src/api/client.ts +76 -0
- package/templates/checkout-agent/packages/agent-core/src/api/mandate-status.ts +74 -0
- package/templates/checkout-agent/packages/agent-core/src/api/rail.ts +153 -0
- package/templates/checkout-agent/packages/agent-core/src/api/sandbox-payer.ts +43 -0
- package/templates/checkout-agent/packages/agent-core/src/approval.ts +135 -0
- package/templates/checkout-agent/packages/agent-core/src/bundle.ts +191 -0
- package/templates/checkout-agent/packages/agent-core/src/channels.ts +186 -0
- package/templates/checkout-agent/packages/agent-core/src/check.ts +276 -0
- package/templates/checkout-agent/packages/agent-core/src/clock.ts +42 -0
- package/templates/checkout-agent/packages/agent-core/src/engine.ts +1074 -0
- package/templates/checkout-agent/packages/agent-core/src/escalate.ts +85 -0
- package/templates/checkout-agent/packages/agent-core/src/events.ts +40 -0
- package/templates/checkout-agent/packages/agent-core/src/guardrails.ts +45 -0
- package/templates/checkout-agent/packages/agent-core/src/hash.ts +118 -0
- package/templates/checkout-agent/packages/agent-core/src/ids.ts +10 -0
- package/templates/checkout-agent/packages/agent-core/src/index.ts +34 -0
- package/templates/checkout-agent/packages/agent-core/src/mandate.ts +100 -0
- package/templates/checkout-agent/packages/agent-core/src/manifest.ts +76 -0
- package/templates/checkout-agent/packages/agent-core/src/providers/anthropic.ts +76 -0
- package/templates/checkout-agent/packages/agent-core/src/providers/replay.ts +63 -0
- package/templates/checkout-agent/packages/agent-core/src/providers/types.ts +39 -0
- package/templates/checkout-agent/packages/agent-core/src/quote.ts +50 -0
- package/templates/checkout-agent/packages/agent-core/src/rail.ts +186 -0
- package/templates/checkout-agent/packages/agent-core/src/receipt-chain.ts +270 -0
- package/templates/checkout-agent/packages/agent-core/src/receipt-verification.ts +577 -0
- package/templates/checkout-agent/packages/agent-core/src/revocation.ts +30 -0
- package/templates/checkout-agent/packages/agent-core/src/secrets.ts +30 -0
- package/templates/checkout-agent/packages/agent-core/src/state/store.ts +307 -0
- package/templates/checkout-agent/packages/agent-core/src/state-machine.ts +157 -0
- package/templates/checkout-agent/packages/agent-core/src/stubs/charge-rail.ts +195 -0
- package/templates/checkout-agent/packages/agent-core/src/stubs/mandate-status.ts +58 -0
- package/templates/checkout-agent/packages/agent-core/src/stubs/rail.ts +209 -0
- package/templates/checkout-agent/packages/agent-core/src/tools.ts +66 -0
- package/templates/checkout-agent/packages/agent-core/src/types.ts +187 -0
- package/templates/checkout-agent/packages/agent-core/test/approval-seal.test.ts +233 -0
- package/templates/checkout-agent/packages/agent-core/test/approval.test.ts +117 -0
- package/templates/checkout-agent/packages/agent-core/test/attempt-replay.test.ts +265 -0
- package/templates/checkout-agent/packages/agent-core/test/bundle.test.ts +85 -0
- package/templates/checkout-agent/packages/agent-core/test/clock.test.ts +25 -0
- package/templates/checkout-agent/packages/agent-core/test/composition.test.ts +204 -0
- package/templates/checkout-agent/packages/agent-core/test/engine.test.ts +596 -0
- package/templates/checkout-agent/packages/agent-core/test/escalate.test.ts +42 -0
- package/templates/checkout-agent/packages/agent-core/test/fixtures/production-receipt-keys.json +1 -0
- package/templates/checkout-agent/packages/agent-core/test/fixtures/staging-receipt-keys.json +18 -0
- package/templates/checkout-agent/packages/agent-core/test/fixtures/staging-receipt.json +24 -0
- package/templates/checkout-agent/packages/agent-core/test/helpers.ts +142 -0
- package/templates/checkout-agent/packages/agent-core/test/mandate-status.test.ts +229 -0
- package/templates/checkout-agent/packages/agent-core/test/manifest.test.ts +45 -0
- package/templates/checkout-agent/packages/agent-core/test/quote.test.ts +198 -0
- package/templates/checkout-agent/packages/agent-core/test/receipt-chain.test.ts +220 -0
- package/templates/checkout-agent/packages/agent-core/test/receipt-read-verification.test.ts +197 -0
- package/templates/checkout-agent/packages/agent-core/test/receipt-verification.test.ts +316 -0
- package/templates/checkout-agent/packages/agent-core/test/receivables.test.ts +416 -0
- package/templates/checkout-agent/packages/agent-core/test/secrets.test.ts +28 -0
- package/templates/checkout-agent/packages/agent-core/test/state-machine.test.ts +67 -0
- package/templates/checkout-agent/packages/agent-core/test/transitions.type-test.ts +59 -0
- package/templates/checkout-agent/packages/agent-core/tsconfig.json +10 -0
- package/templates/checkout-agent/packages/agent-runtime/README.md +80 -0
- package/templates/checkout-agent/packages/agent-runtime/bin.mjs +32 -0
- package/templates/checkout-agent/packages/agent-runtime/package.json +23 -0
- package/templates/checkout-agent/packages/agent-runtime/src/adversarial.ts +199 -0
- package/templates/checkout-agent/packages/agent-runtime/src/agent.ts +68 -0
- package/templates/checkout-agent/packages/agent-runtime/src/channels/contact.ts +13 -0
- package/templates/checkout-agent/packages/agent-runtime/src/channels/index.ts +72 -0
- package/templates/checkout-agent/packages/agent-runtime/src/channels/rules.ts +120 -0
- package/templates/checkout-agent/packages/agent-runtime/src/channels/types.ts +173 -0
- package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +459 -0
- package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +216 -0
- package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/evidence.ts +109 -0
- package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +350 -0
- package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +180 -0
- package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +47 -0
- package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +120 -0
- package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +127 -0
- package/templates/checkout-agent/packages/agent-runtime/src/cli.ts +98 -0
- package/templates/checkout-agent/packages/agent-runtime/src/commands/check.ts +15 -0
- package/templates/checkout-agent/packages/agent-runtime/src/commands/decide.ts +63 -0
- package/templates/checkout-agent/packages/agent-runtime/src/commands/eval.ts +58 -0
- package/templates/checkout-agent/packages/agent-runtime/src/commands/inspect.ts +100 -0
- package/templates/checkout-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +367 -0
- package/templates/checkout-agent/packages/agent-runtime/src/commands/poll.ts +145 -0
- package/templates/checkout-agent/packages/agent-runtime/src/commands/reconcile.ts +42 -0
- package/templates/checkout-agent/packages/agent-runtime/src/commands/rerun.ts +86 -0
- package/templates/checkout-agent/packages/agent-runtime/src/commands/resume.ts +49 -0
- package/templates/checkout-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +134 -0
- package/templates/checkout-agent/packages/agent-runtime/src/commands/start.ts +248 -0
- package/templates/checkout-agent/packages/agent-runtime/src/commands/verify.ts +330 -0
- package/templates/checkout-agent/packages/agent-runtime/src/commands/webhook.ts +40 -0
- package/templates/checkout-agent/packages/agent-runtime/src/default-kit.ts +83 -0
- package/templates/checkout-agent/packages/agent-runtime/src/index.ts +13 -0
- package/templates/checkout-agent/packages/agent-runtime/src/inspect.ts +801 -0
- package/templates/checkout-agent/packages/agent-runtime/src/kit.ts +229 -0
- package/templates/checkout-agent/packages/agent-runtime/src/poll.ts +105 -0
- package/templates/checkout-agent/packages/agent-runtime/src/scenarios.ts +274 -0
- package/templates/checkout-agent/packages/agent-runtime/src/setup.ts +239 -0
- package/templates/checkout-agent/packages/agent-runtime/src/terminal.ts +263 -0
- package/templates/checkout-agent/packages/agent-runtime/src/webhook.ts +131 -0
- package/templates/checkout-agent/packages/agent-runtime/test/inspect.test.ts +336 -0
- package/templates/checkout-agent/packages/agent-runtime/test/verify-cli.test.ts +329 -0
- package/templates/checkout-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +277 -0
- package/templates/checkout-agent/packages/agent-runtime/test/whatsapp-evidence.test.ts +94 -0
- package/templates/checkout-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +174 -0
- package/templates/checkout-agent/packages/agent-runtime/test/whatsapp-session.test.ts +167 -0
- package/templates/checkout-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +182 -0
- package/templates/checkout-agent/packages/agent-runtime/tsconfig.json +9 -0
- package/templates/checkout-agent/scripts/whatsapp-emulator.mjs +84 -0
- package/templates/checkout-agent/tsconfig.base.json +16 -0
- package/templates/checkout-agent/vitest.config.ts +12 -0
- package/templates/collections-agent/README.md +6 -1
- package/templates/collections-agent/agents/collections-agent/README.md +12 -8
- package/templates/collections-agent/agents/collections-agent/channels/whatsapp/README.md +8 -0
- package/templates/collections-agent/agents/collections-agent/channels/whatsapp/acordo-1042-retomada.json +10 -0
- package/templates/collections-agent/agents/collections-agent/channels/whatsapp/templates.json +27 -1
- package/templates/collections-agent/agents/collections-agent/src/kit.ts +2 -0
- package/templates/collections-agent/agents/collections-agent/src/modules/bolepix-receivables.ts +12 -2
- package/templates/collections-agent/agents/collections-agent/test/ambiguous-charge.test.ts +55 -0
- package/templates/collections-agent/agents/collections-agent/test/fixtures/tap-emitir-nova-1042.transcript.jsonl +2 -0
- package/templates/collections-agent/agents/collections-agent/test/whatsapp-poll.test.ts +12 -6
- package/templates/collections-agent/agents/collections-agent/test/whatsapp-status-replies.test.ts +148 -0
- package/templates/collections-agent/agents/collections-agent/test/whatsapp.test.ts +5 -0
- package/templates/collections-agent/package.json +1 -0
- package/templates/collections-agent/packages/agent-core/README.md +14 -1
- package/templates/collections-agent/packages/agent-core/package.json +1 -1
- package/templates/collections-agent/packages/agent-core/src/agent.ts +39 -1
- package/templates/collections-agent/packages/agent-core/src/api/charge-rail.ts +54 -34
- package/templates/collections-agent/packages/agent-core/src/api/client.ts +28 -5
- package/templates/collections-agent/packages/agent-core/src/api/mandate-status.ts +28 -12
- package/templates/collections-agent/packages/agent-core/src/api/rail.ts +62 -26
- package/templates/collections-agent/packages/agent-core/src/api/sandbox-payer.ts +3 -18
- package/templates/collections-agent/packages/agent-core/src/approval.ts +14 -2
- package/templates/collections-agent/packages/agent-core/src/bundle.ts +35 -3
- package/templates/collections-agent/packages/agent-core/src/channels.ts +49 -3
- package/templates/collections-agent/packages/agent-core/src/check.ts +25 -2
- package/templates/collections-agent/packages/agent-core/src/engine.ts +235 -46
- package/templates/collections-agent/packages/agent-core/src/hash.ts +57 -1
- package/templates/collections-agent/packages/agent-core/src/index.ts +2 -0
- package/templates/collections-agent/packages/agent-core/src/quote.ts +50 -0
- package/templates/collections-agent/packages/agent-core/src/rail.ts +89 -4
- package/templates/collections-agent/packages/agent-core/src/receipt-chain.ts +270 -0
- package/templates/collections-agent/packages/agent-core/src/receipt-verification.ts +194 -18
- package/templates/collections-agent/packages/agent-core/src/revocation.ts +1 -1
- package/templates/collections-agent/packages/agent-core/src/state-machine.ts +10 -1
- package/templates/collections-agent/packages/agent-core/src/stubs/mandate-status.ts +4 -3
- package/templates/collections-agent/packages/agent-core/src/stubs/rail.ts +100 -32
- package/templates/collections-agent/packages/agent-core/src/tools.ts +17 -6
- package/templates/collections-agent/packages/agent-core/src/types.ts +54 -1
- package/templates/collections-agent/packages/agent-core/test/approval-seal.test.ts +233 -0
- package/templates/collections-agent/packages/agent-core/test/attempt-replay.test.ts +265 -0
- package/templates/collections-agent/packages/agent-core/test/composition.test.ts +204 -0
- package/templates/collections-agent/packages/agent-core/test/fixtures/production-receipt-keys.json +1 -0
- package/templates/collections-agent/packages/agent-core/test/helpers.ts +4 -1
- package/templates/collections-agent/packages/agent-core/test/mandate-status.test.ts +85 -9
- package/templates/collections-agent/packages/agent-core/test/quote.test.ts +198 -0
- package/templates/collections-agent/packages/agent-core/test/receipt-chain.test.ts +220 -0
- package/templates/collections-agent/packages/agent-core/test/receipt-read-verification.test.ts +197 -0
- package/templates/collections-agent/packages/agent-core/test/receivables.test.ts +103 -3
- package/templates/collections-agent/packages/agent-runtime/README.md +12 -0
- package/templates/collections-agent/packages/agent-runtime/src/adversarial.ts +32 -2
- package/templates/collections-agent/packages/agent-runtime/src/channels/types.ts +53 -4
- package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +123 -22
- package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +30 -20
- package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +146 -21
- package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +40 -3
- package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -1
- package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +16 -2
- package/templates/collections-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +70 -20
- package/templates/collections-agent/packages/agent-runtime/src/commands/poll.ts +2 -1
- package/templates/collections-agent/packages/agent-runtime/src/commands/resume.ts +8 -2
- package/templates/collections-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +3 -0
- package/templates/collections-agent/packages/agent-runtime/src/commands/start.ts +6 -3
- package/templates/collections-agent/packages/agent-runtime/src/commands/verify.ts +239 -38
- package/templates/collections-agent/packages/agent-runtime/src/commands/webhook.ts +3 -2
- package/templates/collections-agent/packages/agent-runtime/src/index.ts +1 -0
- package/templates/collections-agent/packages/agent-runtime/src/inspect.ts +5 -1
- package/templates/collections-agent/packages/agent-runtime/src/kit.ts +25 -2
- package/templates/collections-agent/packages/agent-runtime/src/scenarios.ts +8 -2
- package/templates/collections-agent/packages/agent-runtime/src/setup.ts +13 -3
- package/templates/collections-agent/packages/agent-runtime/src/terminal.ts +127 -18
- package/templates/collections-agent/packages/agent-runtime/test/verify-cli.test.ts +211 -9
- package/templates/collections-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +45 -0
- package/templates/collections-agent/packages/agent-runtime/test/whatsapp-session.test.ts +32 -0
- package/templates/collections-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +182 -0
- package/templates/collections-agent/scripts/whatsapp-emulator.mjs +84 -0
- package/templates/hello-agent/README.md +1 -1
- package/templates/hello-agent/packages/agent-core/README.md +14 -1
- package/templates/hello-agent/packages/agent-core/package.json +1 -1
- package/templates/hello-agent/packages/agent-core/src/agent.ts +39 -1
- package/templates/hello-agent/packages/agent-core/src/api/charge-rail.ts +54 -34
- package/templates/hello-agent/packages/agent-core/src/api/client.ts +28 -5
- package/templates/hello-agent/packages/agent-core/src/api/mandate-status.ts +28 -12
- package/templates/hello-agent/packages/agent-core/src/api/rail.ts +62 -26
- package/templates/hello-agent/packages/agent-core/src/api/sandbox-payer.ts +3 -18
- package/templates/hello-agent/packages/agent-core/src/approval.ts +14 -2
- package/templates/hello-agent/packages/agent-core/src/bundle.ts +35 -3
- package/templates/hello-agent/packages/agent-core/src/channels.ts +49 -3
- package/templates/hello-agent/packages/agent-core/src/check.ts +25 -2
- package/templates/hello-agent/packages/agent-core/src/engine.ts +235 -46
- package/templates/hello-agent/packages/agent-core/src/hash.ts +57 -1
- package/templates/hello-agent/packages/agent-core/src/index.ts +2 -0
- package/templates/hello-agent/packages/agent-core/src/quote.ts +50 -0
- package/templates/hello-agent/packages/agent-core/src/rail.ts +89 -4
- package/templates/hello-agent/packages/agent-core/src/receipt-chain.ts +270 -0
- package/templates/hello-agent/packages/agent-core/src/receipt-verification.ts +194 -18
- package/templates/hello-agent/packages/agent-core/src/revocation.ts +1 -1
- package/templates/hello-agent/packages/agent-core/src/state-machine.ts +10 -1
- package/templates/hello-agent/packages/agent-core/src/stubs/mandate-status.ts +4 -3
- package/templates/hello-agent/packages/agent-core/src/stubs/rail.ts +100 -32
- package/templates/hello-agent/packages/agent-core/src/tools.ts +17 -6
- package/templates/hello-agent/packages/agent-core/src/types.ts +54 -1
- package/templates/hello-agent/packages/agent-core/test/approval-seal.test.ts +233 -0
- package/templates/hello-agent/packages/agent-core/test/attempt-replay.test.ts +265 -0
- package/templates/hello-agent/packages/agent-core/test/composition.test.ts +204 -0
- package/templates/hello-agent/packages/agent-core/test/fixtures/production-receipt-keys.json +1 -0
- package/templates/hello-agent/packages/agent-core/test/helpers.ts +4 -1
- package/templates/hello-agent/packages/agent-core/test/mandate-status.test.ts +85 -9
- package/templates/hello-agent/packages/agent-core/test/quote.test.ts +198 -0
- package/templates/hello-agent/packages/agent-core/test/receipt-chain.test.ts +220 -0
- package/templates/hello-agent/packages/agent-core/test/receipt-read-verification.test.ts +197 -0
- package/templates/hello-agent/packages/agent-core/test/receivables.test.ts +103 -3
- package/templates/hello-agent/packages/agent-runtime/README.md +12 -0
- package/templates/hello-agent/packages/agent-runtime/src/adversarial.ts +32 -2
- package/templates/hello-agent/packages/agent-runtime/src/channels/types.ts +53 -4
- package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +123 -22
- package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +30 -20
- package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +146 -21
- package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +40 -3
- package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -1
- package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +16 -2
- package/templates/hello-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +70 -20
- package/templates/hello-agent/packages/agent-runtime/src/commands/poll.ts +2 -1
- package/templates/hello-agent/packages/agent-runtime/src/commands/resume.ts +8 -2
- package/templates/hello-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +3 -0
- package/templates/hello-agent/packages/agent-runtime/src/commands/start.ts +6 -3
- package/templates/hello-agent/packages/agent-runtime/src/commands/verify.ts +239 -38
- package/templates/hello-agent/packages/agent-runtime/src/commands/webhook.ts +3 -2
- package/templates/hello-agent/packages/agent-runtime/src/index.ts +1 -0
- package/templates/hello-agent/packages/agent-runtime/src/inspect.ts +5 -1
- package/templates/hello-agent/packages/agent-runtime/src/kit.ts +25 -2
- package/templates/hello-agent/packages/agent-runtime/src/scenarios.ts +8 -2
- package/templates/hello-agent/packages/agent-runtime/src/setup.ts +13 -3
- package/templates/hello-agent/packages/agent-runtime/src/terminal.ts +127 -18
- package/templates/hello-agent/packages/agent-runtime/test/verify-cli.test.ts +211 -9
- package/templates/hello-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +45 -0
- package/templates/hello-agent/packages/agent-runtime/test/whatsapp-session.test.ts +32 -0
- package/templates/hello-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +182 -0
- package/templates/kits.lock.json +29 -6
- package/templates/supplier-payments-agent/README.md +1 -1
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/AGENTS.md +1 -1
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/CLAUDE.md +1 -1
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/README.md +11 -9
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/kit.ts +1 -1
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/modules/batch-payout.ts +67 -20
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/batch.test.ts +504 -5
- package/templates/supplier-payments-agent/packages/agent-core/README.md +14 -1
- package/templates/supplier-payments-agent/packages/agent-core/package.json +1 -1
- package/templates/supplier-payments-agent/packages/agent-core/src/agent.ts +39 -1
- package/templates/supplier-payments-agent/packages/agent-core/src/api/charge-rail.ts +54 -34
- package/templates/supplier-payments-agent/packages/agent-core/src/api/client.ts +28 -5
- package/templates/supplier-payments-agent/packages/agent-core/src/api/mandate-status.ts +28 -12
- package/templates/supplier-payments-agent/packages/agent-core/src/api/rail.ts +62 -26
- package/templates/supplier-payments-agent/packages/agent-core/src/api/sandbox-payer.ts +3 -18
- package/templates/supplier-payments-agent/packages/agent-core/src/approval.ts +14 -2
- package/templates/supplier-payments-agent/packages/agent-core/src/bundle.ts +35 -3
- package/templates/supplier-payments-agent/packages/agent-core/src/channels.ts +49 -3
- package/templates/supplier-payments-agent/packages/agent-core/src/check.ts +25 -2
- package/templates/supplier-payments-agent/packages/agent-core/src/engine.ts +235 -46
- package/templates/supplier-payments-agent/packages/agent-core/src/hash.ts +57 -1
- package/templates/supplier-payments-agent/packages/agent-core/src/index.ts +2 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/quote.ts +50 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/rail.ts +89 -4
- package/templates/supplier-payments-agent/packages/agent-core/src/receipt-chain.ts +270 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/receipt-verification.ts +194 -18
- package/templates/supplier-payments-agent/packages/agent-core/src/revocation.ts +1 -1
- package/templates/supplier-payments-agent/packages/agent-core/src/state-machine.ts +10 -1
- package/templates/supplier-payments-agent/packages/agent-core/src/stubs/mandate-status.ts +4 -3
- package/templates/supplier-payments-agent/packages/agent-core/src/stubs/rail.ts +100 -32
- package/templates/supplier-payments-agent/packages/agent-core/src/tools.ts +17 -6
- package/templates/supplier-payments-agent/packages/agent-core/src/types.ts +54 -1
- package/templates/supplier-payments-agent/packages/agent-core/test/approval-seal.test.ts +233 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/attempt-replay.test.ts +265 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/composition.test.ts +204 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/fixtures/production-receipt-keys.json +1 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/helpers.ts +4 -1
- package/templates/supplier-payments-agent/packages/agent-core/test/mandate-status.test.ts +85 -9
- package/templates/supplier-payments-agent/packages/agent-core/test/quote.test.ts +198 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/receipt-chain.test.ts +220 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/receipt-read-verification.test.ts +197 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/receivables.test.ts +103 -3
- package/templates/supplier-payments-agent/packages/agent-runtime/README.md +12 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/adversarial.ts +32 -2
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/types.ts +53 -4
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +123 -22
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +30 -20
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +146 -21
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +40 -3
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -1
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +16 -2
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +70 -20
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/poll.ts +2 -1
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/resume.ts +8 -2
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +3 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/start.ts +6 -3
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/verify.ts +239 -38
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/webhook.ts +3 -2
- package/templates/supplier-payments-agent/packages/agent-runtime/src/index.ts +1 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/inspect.ts +5 -1
- package/templates/supplier-payments-agent/packages/agent-runtime/src/kit.ts +25 -2
- package/templates/supplier-payments-agent/packages/agent-runtime/src/scenarios.ts +8 -2
- package/templates/supplier-payments-agent/packages/agent-runtime/src/setup.ts +13 -3
- package/templates/supplier-payments-agent/packages/agent-runtime/src/terminal.ts +127 -18
- package/templates/supplier-payments-agent/packages/agent-runtime/test/verify-cli.test.ts +211 -9
- package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +45 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-session.test.ts +32 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +182 -0
- package/templates/bills-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +0 -204
- package/templates/collections-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +0 -204
- package/templates/hello-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +0 -204
- package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +0 -204
|
@@ -29,9 +29,46 @@ export interface InboundMessage {
|
|
|
29
29
|
id: string;
|
|
30
30
|
/** Who wrote it, E.164 on WhatsApp. */
|
|
31
31
|
from: string;
|
|
32
|
+
/**
|
|
33
|
+
* What the person wrote. For a TAP (`reply` set) the backend puts the
|
|
34
|
+
* button's title here, and the channel replaces it with the intent the
|
|
35
|
+
* template that offered the button declared — the model never reads a
|
|
36
|
+
* title as if the person had typed it.
|
|
37
|
+
*/
|
|
32
38
|
text: string;
|
|
33
39
|
/** Unix seconds on the PROVIDER's clock, which is not this process's clock. */
|
|
34
40
|
timestamp: number;
|
|
41
|
+
/** Set when the person tapped a quick reply instead of typing. */
|
|
42
|
+
reply?: InboundReply;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** A tapped quick reply, as the provider reports it: which button, and on which message when it says. */
|
|
46
|
+
export interface InboundReply {
|
|
47
|
+
/** `button_reply` / `list_reply` (an interactive message), `button` (a template's quick reply). */
|
|
48
|
+
type: "button_reply" | "list_reply" | "button";
|
|
49
|
+
id: string;
|
|
50
|
+
title: string;
|
|
51
|
+
/** The message the button was on (`context.id`), when the provider sends it. */
|
|
52
|
+
context_id?: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* What the provider reports about a message the agent sent, after it left.
|
|
57
|
+
* `failed` carries Meta's errors (131026: not a WhatsApp number, or it blocked
|
|
58
|
+
* the business). Delivered by webhook, at any time, to whoever is listening.
|
|
59
|
+
*/
|
|
60
|
+
export interface StatusUpdate {
|
|
61
|
+
message_id: string;
|
|
62
|
+
status: DeliveryState;
|
|
63
|
+
/** Unix seconds, the provider's clock. */
|
|
64
|
+
timestamp: number;
|
|
65
|
+
errors: Array<{ code?: number; title?: string; details?: string }>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** The execution an outbound message tells the outcome of: what a failed delivery of it means. */
|
|
69
|
+
export interface OutcomeTag {
|
|
70
|
+
execution_id: string;
|
|
71
|
+
state: string;
|
|
35
72
|
}
|
|
36
73
|
|
|
37
74
|
/**
|
|
@@ -50,10 +87,11 @@ export interface InboundMessage {
|
|
|
50
87
|
* and which the rail did, and only the first are checked for a document.
|
|
51
88
|
*/
|
|
52
89
|
export type OutboundBody =
|
|
53
|
-
| { kind: "text"; text: string }
|
|
90
|
+
| { kind: "text"; text: string; about?: OutcomeTag }
|
|
54
91
|
| { kind: "media"; media: "qr"; data: string; caption?: string }
|
|
55
92
|
| { kind: "instrument"; instrument: "pix_copy_paste" | "boleto_bank_line"; value: string }
|
|
56
|
-
|
|
93
|
+
/** `buttons` are the declaration's, attached by the channel; a caller never composes them. */
|
|
94
|
+
| { kind: "template"; template: string; language: string; variables: string[]; about?: OutcomeTag; buttons?: Array<{ id: string; title: string }> };
|
|
57
95
|
|
|
58
96
|
export interface SentMessage {
|
|
59
97
|
/** The provider's id when it accepted one, else the id the backend minted. */
|
|
@@ -85,6 +123,8 @@ export interface ChannelBackend {
|
|
|
85
123
|
next(): Promise<InboundMessage | undefined>;
|
|
86
124
|
/** Hands the message to the provider. Rules have already run: a backend never re-decides policy. */
|
|
87
125
|
deliver(to: string, body: OutboundBody): Promise<SentMessage>;
|
|
126
|
+
/** Where the status webhooks go. A backend that cannot observe statuses never calls it. */
|
|
127
|
+
onStatus?(listener: (status: StatusUpdate) => void): void;
|
|
88
128
|
close(): Promise<void>;
|
|
89
129
|
}
|
|
90
130
|
|
|
@@ -105,10 +145,12 @@ export interface Channel {
|
|
|
105
145
|
|
|
106
146
|
export interface ChannelLogLine {
|
|
107
147
|
at: string;
|
|
108
|
-
|
|
148
|
+
/** `status`: what the provider reported about an outbound message, after it left. */
|
|
149
|
+
direction: "in" | "out" | "status";
|
|
109
150
|
/** The contact, MASKED. The raw value never reaches a file. */
|
|
110
151
|
contact: string;
|
|
111
|
-
|
|
152
|
+
/** `reply`: an inbound tap. `status`: a delivery status. */
|
|
153
|
+
kind: OutboundBody["kind"] | "reply" | "status";
|
|
112
154
|
/** The provider's id, or ours when nothing was sent. */
|
|
113
155
|
message_id: string;
|
|
114
156
|
state: DeliveryState;
|
|
@@ -121,4 +163,11 @@ export interface ChannelLogLine {
|
|
|
121
163
|
*/
|
|
122
164
|
provider_timestamp?: number;
|
|
123
165
|
refused?: { rule: string; detail: string };
|
|
166
|
+
/** Outbound: the execution whose outcome this message tells. Status: the same, looked up by message id. */
|
|
167
|
+
about?: OutcomeTag;
|
|
168
|
+
/** Outbound template: the reply ids it offered. Inbound tap: the reply tapped. */
|
|
169
|
+
offered?: string[];
|
|
170
|
+
reply?: { type: InboundReply["type"]; id: string; title: string };
|
|
171
|
+
/** Status `failed`: Meta's errors, as reported. */
|
|
172
|
+
errors?: StatusUpdate["errors"];
|
|
124
173
|
}
|
package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
*/
|
|
25
25
|
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
26
26
|
import { createServer, type Server } from "node:http";
|
|
27
|
-
import type { ChannelBackend, InboundMessage, OutboundBody, SentMessage } from "../types.js";
|
|
27
|
+
import type { ChannelBackend, DeliveryState, InboundMessage, InboundReply, OutboundBody, SentMessage, StatusUpdate } from "../types.js";
|
|
28
28
|
|
|
29
29
|
export interface CloudApiConfig {
|
|
30
30
|
/**
|
|
@@ -140,23 +140,36 @@ interface CloudApiEnvelope {
|
|
|
140
140
|
value?: {
|
|
141
141
|
messaging_product?: string;
|
|
142
142
|
metadata?: { phone_number_id?: string };
|
|
143
|
-
messages?: Array<{
|
|
144
|
-
|
|
143
|
+
messages?: Array<{
|
|
144
|
+
id?: string;
|
|
145
|
+
from?: string;
|
|
146
|
+
timestamp?: string;
|
|
147
|
+
type?: string;
|
|
148
|
+
text?: { body?: string };
|
|
149
|
+
interactive?: { type?: string; button_reply?: { id?: string; title?: string }; list_reply?: { id?: string; title?: string } };
|
|
150
|
+
button?: { payload?: string; text?: string };
|
|
151
|
+
context?: { id?: string };
|
|
152
|
+
}>;
|
|
153
|
+
statuses?: Array<{ id?: string; status?: string; timestamp?: string; errors?: Array<{ code?: number; title?: string; message?: string; error_data?: { details?: string } }> }>;
|
|
145
154
|
};
|
|
146
155
|
}>;
|
|
147
156
|
}>;
|
|
148
157
|
}
|
|
149
158
|
|
|
150
159
|
/**
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
160
|
+
* What one delivery carries. A delivery holds several entries, each with
|
|
161
|
+
* several changes, each with messages and with STATUS updates about messages
|
|
162
|
+
* we sent. A message is read when it is text, or a tapped quick reply (an
|
|
163
|
+
* interactive `button_reply` / `list_reply`, or a template's `button`), which
|
|
164
|
+
* keeps its id — the channel decides whether that id means anything. Anything
|
|
165
|
+
* else (an image, a location) is dropped with its id named: this channel
|
|
166
|
+
* reads words and taps, and an unreadable message must not become an empty
|
|
167
|
+
* turn.
|
|
156
168
|
*/
|
|
157
|
-
export function parseInbound(payload: unknown): { messages: InboundMessage[]; ignored: Array<{ id: string; type: string }> } {
|
|
169
|
+
export function parseInbound(payload: unknown): { messages: InboundMessage[]; statuses: StatusUpdate[]; ignored: Array<{ id: string; type: string }> } {
|
|
158
170
|
const envelope = payload as CloudApiEnvelope;
|
|
159
171
|
const messages: InboundMessage[] = [];
|
|
172
|
+
const statuses: StatusUpdate[] = [];
|
|
160
173
|
const ignored: Array<{ id: string; type: string }> = [];
|
|
161
174
|
for (const entry of envelope.entry ?? []) {
|
|
162
175
|
for (const change of entry.changes ?? []) {
|
|
@@ -164,15 +177,51 @@ export function parseInbound(payload: unknown): { messages: InboundMessage[]; ig
|
|
|
164
177
|
const id = message.id;
|
|
165
178
|
const from = message.from;
|
|
166
179
|
if (!id || !from) continue;
|
|
180
|
+
const base = { id, from: from.startsWith("+") ? from : `+${from}`, timestamp: Number(message.timestamp ?? 0) };
|
|
181
|
+
const reply = replyOf(message);
|
|
182
|
+
if (reply) {
|
|
183
|
+
messages.push({ ...base, text: reply.title, reply: { ...reply, ...(message.context?.id ? { context_id: message.context.id } : {}) } });
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
167
186
|
if (message.type !== "text" || !message.text?.body) {
|
|
168
|
-
ignored.push({ id, type: message.type ?? "unknown" });
|
|
187
|
+
ignored.push({ id, type: message.type === "interactive" ? `interactive:${message.interactive?.type ?? "unknown"}` : message.type ?? "unknown" });
|
|
169
188
|
continue;
|
|
170
189
|
}
|
|
171
|
-
messages.push({
|
|
190
|
+
messages.push({ ...base, text: message.text.body });
|
|
191
|
+
}
|
|
192
|
+
for (const status of change.value?.statuses ?? []) {
|
|
193
|
+
if (!status.id || !isDeliveryState(status.status)) continue;
|
|
194
|
+
statuses.push({
|
|
195
|
+
message_id: status.id,
|
|
196
|
+
status: status.status,
|
|
197
|
+
timestamp: Number(status.timestamp ?? 0),
|
|
198
|
+
errors: (status.errors ?? []).map((e) => ({
|
|
199
|
+
...(typeof e.code === "number" ? { code: e.code } : {}),
|
|
200
|
+
...(e.title ?? e.message ? { title: e.title ?? e.message } : {}),
|
|
201
|
+
...(e.error_data?.details ? { details: e.error_data.details } : {}),
|
|
202
|
+
})),
|
|
203
|
+
});
|
|
172
204
|
}
|
|
173
205
|
}
|
|
174
206
|
}
|
|
175
|
-
return { messages, ignored };
|
|
207
|
+
return { messages, statuses, ignored };
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
type CloudMessage = NonNullable<NonNullable<NonNullable<NonNullable<CloudApiEnvelope["entry"]>[number]["changes"]>[number]["value"]>["messages"]>[number];
|
|
211
|
+
|
|
212
|
+
function replyOf(message: CloudMessage): Omit<InboundReply, "context_id"> | undefined {
|
|
213
|
+
if (message.type === "interactive") {
|
|
214
|
+
const kind = message.interactive?.type;
|
|
215
|
+
const picked = kind === "button_reply" ? message.interactive?.button_reply : kind === "list_reply" ? message.interactive?.list_reply : undefined;
|
|
216
|
+
if ((kind === "button_reply" || kind === "list_reply") && picked?.id) return { type: kind, id: picked.id, title: picked.title ?? picked.id };
|
|
217
|
+
return undefined;
|
|
218
|
+
}
|
|
219
|
+
if (message.type === "button" && message.button?.payload) return { type: "button", id: message.button.payload, title: message.button.text ?? message.button.payload };
|
|
220
|
+
return undefined;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function isDeliveryState(value: unknown): value is DeliveryState {
|
|
224
|
+
return value === "sent" || value === "delivered" || value === "read" || value === "failed";
|
|
176
225
|
}
|
|
177
226
|
|
|
178
227
|
export interface SendRequest {
|
|
@@ -200,10 +249,6 @@ export function buildSendRequest(config: CloudApiConfig, to: string, body: Outbo
|
|
|
200
249
|
method: "POST" as const,
|
|
201
250
|
headers: { authorization: `Bearer ${config.accessToken}`, "content-type": "application/json" },
|
|
202
251
|
};
|
|
203
|
-
// `to` loses its `+`: the Cloud API documents the number in international
|
|
204
|
-
// format without one, and the emulator keys its conversation on the literal
|
|
205
|
-
// string, so a `+` here and none on the inbound side splits one person into
|
|
206
|
-
// two conversations (measured; docs/OPEN_QUESTIONS.md §46c).
|
|
207
252
|
const recipient = { messaging_product: "whatsapp", recipient_type: "individual", to: toGraphNumber(to) };
|
|
208
253
|
switch (body.kind) {
|
|
209
254
|
case "text":
|
|
@@ -219,7 +264,7 @@ export function buildSendRequest(config: CloudApiConfig, to: string, body: Outbo
|
|
|
219
264
|
template: {
|
|
220
265
|
name: body.template,
|
|
221
266
|
language: { code: body.language },
|
|
222
|
-
...(body
|
|
267
|
+
...templateComponents(body),
|
|
223
268
|
},
|
|
224
269
|
}),
|
|
225
270
|
};
|
|
@@ -228,6 +273,49 @@ export function buildSendRequest(config: CloudApiConfig, to: string, body: Outbo
|
|
|
228
273
|
}
|
|
229
274
|
}
|
|
230
275
|
|
|
276
|
+
/**
|
|
277
|
+
* A template's parameters as Meta takes them: the body's variables, and one
|
|
278
|
+
* `quick_reply` button component per declared reply, whose `payload` is the
|
|
279
|
+
* reply id — what comes back as `button.payload` when the person taps it.
|
|
280
|
+
*/
|
|
281
|
+
function templateComponents(body: Extract<OutboundBody, { kind: "template" }>): { components?: unknown[] } {
|
|
282
|
+
const components: unknown[] = [];
|
|
283
|
+
if (body.variables.length) components.push({ type: "body", parameters: body.variables.map((text) => ({ type: "text", text })) });
|
|
284
|
+
for (const [index, button] of (body.buttons ?? []).entries()) components.push({ type: "button", sub_type: "quick_reply", index: String(index), parameters: [{ type: "payload", payload: button.id }] });
|
|
285
|
+
return components.length ? { components } : {};
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/** Meta's error for a free-form message outside the 24 hours after the person's last one. */
|
|
289
|
+
export const WINDOW_CLOSED_ERROR = 131047;
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* What a non-2xx from `/messages` means, read from Meta's error body.
|
|
293
|
+
*
|
|
294
|
+
* One code gets its own rule: 131047 is the provider saying the 24-hour
|
|
295
|
+
* window is shut, which is the SAME rule the channel enforces before a send
|
|
296
|
+
* and is answered the same way — with a template. It reaches here only when
|
|
297
|
+
* the two clocks disagree (ours read the window open, the provider's read it
|
|
298
|
+
* shut), which at the boundary is a race and not a bug, so a caller has to be
|
|
299
|
+
* able to tell it from a refusal it cannot do anything about.
|
|
300
|
+
*/
|
|
301
|
+
export function providerRefusal(status: number, body: string): { rule: string; detail: string } {
|
|
302
|
+
let error: { code?: unknown; message?: unknown; error_data?: { details?: unknown } } | undefined;
|
|
303
|
+
try {
|
|
304
|
+
error = (JSON.parse(body) as { error?: typeof error }).error;
|
|
305
|
+
} catch {
|
|
306
|
+
/* an error without Meta's envelope: the status is all there is */
|
|
307
|
+
}
|
|
308
|
+
const details = typeof error?.error_data?.details === "string" ? error.error_data.details : undefined;
|
|
309
|
+
if (error?.code === WINDOW_CLOSED_ERROR) {
|
|
310
|
+
return {
|
|
311
|
+
rule: "session_window_closed",
|
|
312
|
+
detail: `the provider refused the free-form message (${status}/${WINDOW_CLOSED_ERROR}): its 24h window is shut${details ? ` — ${details}` : ""}`,
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
const code = typeof error?.code === "number" ? `/${error.code}` : "";
|
|
316
|
+
return { rule: "provider_refused", detail: `${status}${code} from the Cloud API${details ? ` — ${details}` : ""}` };
|
|
317
|
+
}
|
|
318
|
+
|
|
231
319
|
/* ── the impure half: one fetch over a request the above built ── */
|
|
232
320
|
|
|
233
321
|
/** `+5511987654321` -> `5511987654321`, the only form the Graph API takes. */
|
|
@@ -249,7 +337,10 @@ export class WhatsAppCloudApi implements ChannelBackend {
|
|
|
249
337
|
readonly live: boolean;
|
|
250
338
|
private server: Server | undefined;
|
|
251
339
|
private readonly queue: InboundMessage[] = [];
|
|
340
|
+
/** Message ids already handed on. Meta delivers at-least-once, so the same message can arrive twice. */
|
|
341
|
+
private readonly seen = new Set<string>();
|
|
252
342
|
private waiting: ((m: InboundMessage | undefined) => void) | undefined;
|
|
343
|
+
private statusListener: ((status: StatusUpdate) => void) | undefined;
|
|
253
344
|
private closed = false;
|
|
254
345
|
|
|
255
346
|
constructor(private readonly options: CloudApiOptions) {
|
|
@@ -287,15 +378,16 @@ export class WhatsAppCloudApi implements ChannelBackend {
|
|
|
287
378
|
res.writeHead(401, { "content-type": "application/json" }).end(JSON.stringify({ error: "bad_signature" }));
|
|
288
379
|
return;
|
|
289
380
|
}
|
|
290
|
-
let parsed:
|
|
381
|
+
let parsed: ReturnType<typeof parseInbound>;
|
|
291
382
|
try {
|
|
292
383
|
parsed = parseInbound(JSON.parse(raw));
|
|
293
384
|
} catch {
|
|
294
385
|
res.writeHead(400, { "content-type": "application/json" }).end(JSON.stringify({ error: "invalid_json" }));
|
|
295
386
|
return;
|
|
296
387
|
}
|
|
297
|
-
for (const ignored of parsed.ignored) say(`[whatsapp] ignored ${ignored.type} message ${ignored.id}: this channel reads text`);
|
|
388
|
+
for (const ignored of parsed.ignored) say(`[whatsapp] ignored ${ignored.type} message ${ignored.id}: this channel reads text and taps`);
|
|
298
389
|
for (const message of parsed.messages) this.push(message);
|
|
390
|
+
for (const status of parsed.statuses) this.statusListener?.(status);
|
|
299
391
|
// Always 200 once read: Meta retries on anything else, and a duplicate is not an error.
|
|
300
392
|
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ received: parsed.messages.length }));
|
|
301
393
|
});
|
|
@@ -309,6 +401,13 @@ export class WhatsAppCloudApi implements ChannelBackend {
|
|
|
309
401
|
}
|
|
310
402
|
|
|
311
403
|
private push(message: InboundMessage): void {
|
|
404
|
+
// A redelivery is the same message, not a second turn: answering it twice
|
|
405
|
+
// would put two replies in front of the person for one thing they said.
|
|
406
|
+
if (this.seen.has(message.id)) {
|
|
407
|
+
this.options.say(`[whatsapp] duplicate delivery of ${message.id} dropped`);
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
this.seen.add(message.id);
|
|
312
411
|
if (this.waiting) {
|
|
313
412
|
const resolve = this.waiting;
|
|
314
413
|
this.waiting = undefined;
|
|
@@ -318,6 +417,10 @@ export class WhatsAppCloudApi implements ChannelBackend {
|
|
|
318
417
|
this.queue.push(message);
|
|
319
418
|
}
|
|
320
419
|
|
|
420
|
+
onStatus(listener: (status: StatusUpdate) => void): void {
|
|
421
|
+
this.statusListener = listener;
|
|
422
|
+
}
|
|
423
|
+
|
|
321
424
|
async next(): Promise<InboundMessage | undefined> {
|
|
322
425
|
if (this.closed) return undefined;
|
|
323
426
|
const queued = this.queue.shift();
|
|
@@ -335,9 +438,7 @@ export class WhatsAppCloudApi implements ChannelBackend {
|
|
|
335
438
|
const doFetch = this.options.fetchImpl ?? fetch;
|
|
336
439
|
const response = await doFetch(request.url, { method: request.method, headers: request.headers, body: request.body });
|
|
337
440
|
const text = await response.text();
|
|
338
|
-
if (!response.ok) {
|
|
339
|
-
return { id: "", state: "failed", refused: { rule: "provider_refused", detail: `${response.status} from the Cloud API` } };
|
|
340
|
-
}
|
|
441
|
+
if (!response.ok) return { id: "", state: "failed", refused: providerRefusal(response.status, text) };
|
|
341
442
|
let id = "";
|
|
342
443
|
try {
|
|
343
444
|
id = String((JSON.parse(text) as { messages?: Array<{ id?: string }> }).messages?.[0]?.id ?? "");
|
package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts
CHANGED
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
* `npm run whatsapp:emulator` is the command.
|
|
27
27
|
*/
|
|
28
28
|
import type { ConversationScript } from "@codespar/agent-core";
|
|
29
|
-
import type { ChannelBackend, InboundMessage, OutboundBody, SentMessage } from "../types.js";
|
|
30
|
-
import {
|
|
29
|
+
import type { ChannelBackend, InboundMessage, OutboundBody, SentMessage, StatusUpdate } from "../types.js";
|
|
30
|
+
import { WhatsAppCloudApi, type CloudApiOptions } from "./cloud-api.js";
|
|
31
31
|
|
|
32
32
|
export const EMULATOR_ENV = {
|
|
33
33
|
url: "WHATSAPP_SIM_URL",
|
|
@@ -93,18 +93,23 @@ export class EmulatorDriver {
|
|
|
93
93
|
return this.post("/_sim/clock", { advance_hours: hours });
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
/** The person writes. The emulator answers with a signed inbound webhook to our receiver. */
|
|
97
|
-
inbound(options: { phoneNumberId: string; from: string; text: string; sentAt?: Date }): Promise<unknown> {
|
|
96
|
+
/** The person writes, or taps a quick reply. The emulator answers with a signed inbound webhook to our receiver. */
|
|
97
|
+
inbound(options: { phoneNumberId: string; from: string; text: string; sentAt?: Date } | { phoneNumberId: string; from: string; reply: { id: string; title: string }; sentAt?: Date }): Promise<unknown> {
|
|
98
98
|
return this.post("/_sim/inbound", {
|
|
99
99
|
phone_number_id: options.phoneNumberId,
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
from: options.from,
|
|
101
|
+
...("reply" in options
|
|
102
|
+
? { type: "interactive", interactive: { type: "button_reply", button_reply: { id: options.reply.id, title: options.reply.title } } }
|
|
103
|
+
: { text: options.text }),
|
|
104
104
|
...(options.sentAt ? { sent_at: options.sentAt.toISOString() } : {}),
|
|
105
105
|
});
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
/** Reports a delivery status for a message the business sent, as the provider would: `read`, or `failed` with a reason. */
|
|
109
|
+
status(options: { status: "read" | "failed"; messageId: string; reason?: string }): Promise<unknown> {
|
|
110
|
+
return this.post("/_sim/status", { status: options.status, message_id: options.messageId, ...(options.reason ? { reason: options.reason } : {}) });
|
|
111
|
+
}
|
|
112
|
+
|
|
108
113
|
/** The priced timeline, which is the emulator's own reason for existing. Read for the console, never asserted on. */
|
|
109
114
|
state(key: string): Promise<{ priced?: { total?: number; currency?: string } } | undefined> {
|
|
110
115
|
return this.call(`/_sim/state?key=${encodeURIComponent(key)}`).then(
|
|
@@ -156,20 +161,21 @@ export class WhatsAppEmulator implements ChannelBackend {
|
|
|
156
161
|
|
|
157
162
|
async next(): Promise<InboundMessage | undefined> {
|
|
158
163
|
if (this.closed) return undefined;
|
|
159
|
-
const
|
|
160
|
-
if (
|
|
161
|
-
// The person writes THROUGH the emulator: it mints the message id
|
|
162
|
-
// the signed webhook our receiver verifies, so a scripted turn
|
|
163
|
-
// same path a real one would.
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
from: this.options.conversation.contact,
|
|
167
|
-
text,
|
|
168
|
-
});
|
|
164
|
+
const turn = await this.nextTurn();
|
|
165
|
+
if (turn === undefined) return undefined;
|
|
166
|
+
// The person writes (or taps) THROUGH the emulator: it mints the message id
|
|
167
|
+
// and posts the signed webhook our receiver verifies, so a scripted turn
|
|
168
|
+
// takes the same path a real one would.
|
|
169
|
+
const who = { phoneNumberId: this.options.config.phoneNumberId, from: this.options.conversation.contact };
|
|
170
|
+
await this.options.driver.inbound(typeof turn === "string" ? { ...who, text: turn } : { ...who, reply: turn });
|
|
169
171
|
return this.api.next();
|
|
170
172
|
}
|
|
171
173
|
|
|
172
|
-
|
|
174
|
+
onStatus(listener: (status: StatusUpdate) => void): void {
|
|
175
|
+
this.api.onStatus(listener);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
private async nextTurn(): Promise<string | { id: string; title: string } | undefined> {
|
|
173
179
|
const script = this.options.script;
|
|
174
180
|
if (script) {
|
|
175
181
|
const turn = script.turns[this.turn];
|
|
@@ -178,8 +184,12 @@ export class WhatsAppEmulator implements ChannelBackend {
|
|
|
178
184
|
// The person's own pause, on the emulator's clock. A conversation that
|
|
179
185
|
// happens over days is what closes the 24-hour window.
|
|
180
186
|
if (turn.after_seconds > 0) await this.options.driver.advanceHours(turn.after_seconds / 3600);
|
|
181
|
-
return turn.text;
|
|
187
|
+
return turn.reply ? { id: turn.reply.id, title: turn.reply.title ?? turn.reply.id } : turn.text;
|
|
182
188
|
}
|
|
189
|
+
return this.nextText();
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private async nextText(): Promise<string | undefined> {
|
|
183
193
|
if (!this.options.ask) return undefined;
|
|
184
194
|
let answer: string;
|
|
185
195
|
try {
|