@codespar/cli 0.18.1 → 0.21.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 -1
- package/dist/commands/login.js +52 -12
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/payables.js +220 -0
- package/dist/commands/payables.js.map +1 -0
- package/dist/index.js +77 -1
- package/dist/index.js.map +1 -1
- package/dist/surface.js +31 -13
- package/dist/surface.js.map +1 -1
- package/package.json +2 -2
- package/templates/bills-agent/README.md +2 -2
- package/templates/bills-agent/agents/bills-agent/.env.example +2 -2
- package/templates/bills-agent/agents/bills-agent/README.md +25 -18
- package/templates/bills-agent/agents/bills-agent/SYSTEM_PROMPT.md +13 -3
- package/templates/bills-agent/agents/bills-agent/agent.yaml +2 -1
- package/templates/bills-agent/agents/bills-agent/evals/adversarial/exfiltration.transcript.jsonl +1 -1
- package/templates/bills-agent/agents/bills-agent/evals/adversarial/false-authority.transcript.jsonl +1 -1
- package/templates/bills-agent/agents/bills-agent/evals/adversarial/prompt-injection.transcript.jsonl +1 -1
- package/templates/bills-agent/agents/bills-agent/mandate.example.json +1 -1
- package/templates/bills-agent/agents/bills-agent/runbook.md +1 -1
- package/templates/bills-agent/agents/bills-agent/scenarios/beneficiary-not-allowed.transcript.jsonl +1 -1
- package/templates/bills-agent/agents/bills-agent/scenarios/cap-exceeded.transcript.jsonl +1 -1
- package/templates/bills-agent/agents/bills-agent/scenarios/escalated-above-threshold.transcript.jsonl +4 -4
- package/templates/bills-agent/agents/bills-agent/scenarios/happy-path.transcript.jsonl +1 -1
- package/templates/bills-agent/agents/bills-agent/scenarios/mandate-revoked.json +1 -1
- package/templates/bills-agent/agents/bills-agent/scenarios/mandate-revoked.transcript.jsonl +4 -4
- package/templates/bills-agent/agents/bills-agent/scenarios/prompt-injection.transcript.jsonl +1 -1
- package/templates/bills-agent/agents/bills-agent/src/bills.ts +1 -1
- package/templates/bills-agent/agents/bills-agent/src/kit.ts +15 -28
- package/templates/bills-agent/agents/bills-agent/src/modules/embedded-consent.ts +42 -15
- package/templates/bills-agent/agents/bills-agent/src/modules/pix-out.ts +21 -3
- package/templates/bills-agent/agents/bills-agent/src/strings.ts +68 -0
- package/templates/bills-agent/agents/bills-agent/test/cli.test.ts +130 -2
- package/templates/bills-agent/agents/bills-agent/test/consent-money.test.ts +25 -0
- package/templates/bills-agent/agents/bills-agent/test/dates-and-approval.test.ts +98 -0
- package/templates/bills-agent/agents/bills-agent/test/eval-runs.test.ts +81 -0
- package/templates/bills-agent/agents/bills-agent/test/fixtures/excursao-300.transcript.jsonl +2 -2
- package/templates/bills-agent/agents/bills-agent/test/fixtures/material-400.transcript.jsonl +1 -1
- package/templates/bills-agent/agents/bills-agent/test/locale.test.ts +161 -0
- package/templates/bills-agent/agents/bills-agent/test/mandate-state.test.ts +108 -0
- package/templates/bills-agent/agents/bills-agent/test/refused-before-draft.test.ts +81 -0
- package/templates/bills-agent/agents/bills-agent/test/replay.test.ts +76 -0
- package/templates/bills-agent/agents/bills-agent/test/reply-and-outcome.test.ts +84 -0
- package/templates/bills-agent/agents/bills-agent/test/reply-language.test.ts +95 -0
- package/templates/bills-agent/agents/bills-agent/test/rerun-and-missing-transcript.test.ts +120 -0
- package/templates/bills-agent/agents/bills-agent/test/rerun-world-events.test.ts +55 -0
- package/templates/bills-agent/agents/bills-agent/tools.json +1 -1
- package/templates/bills-agent/packages/agent-core/README.md +21 -2
- package/templates/bills-agent/packages/agent-core/package.json +1 -1
- package/templates/bills-agent/packages/agent-core/src/agent.ts +33 -6
- package/templates/bills-agent/packages/agent-core/src/api/charge-rail.ts +15 -1
- package/templates/bills-agent/packages/agent-core/src/api/rail.ts +11 -5
- package/templates/bills-agent/packages/agent-core/src/api/sandbox-payer.ts +36 -0
- package/templates/bills-agent/packages/agent-core/src/bundle.ts +2 -0
- package/templates/bills-agent/packages/agent-core/src/channels.ts +18 -8
- package/templates/bills-agent/packages/agent-core/src/check.ts +25 -3
- package/templates/bills-agent/packages/agent-core/src/engine.ts +90 -9
- package/templates/bills-agent/packages/agent-core/src/escalate.ts +10 -0
- package/templates/bills-agent/packages/agent-core/src/index.ts +3 -0
- package/templates/bills-agent/packages/agent-core/src/language.ts +52 -0
- package/templates/bills-agent/packages/agent-core/src/locale.ts +88 -0
- package/templates/bills-agent/packages/agent-core/src/manifest.ts +4 -1
- package/templates/bills-agent/packages/agent-core/src/rail.ts +29 -1
- package/templates/bills-agent/packages/agent-core/src/receipt-verification.ts +30 -2
- package/templates/bills-agent/packages/agent-core/src/secrets.ts +53 -8
- package/templates/bills-agent/packages/agent-core/src/state-machine.ts +14 -0
- package/templates/bills-agent/packages/agent-core/src/strings.ts +175 -0
- package/templates/bills-agent/packages/agent-core/src/stubs/charge-rail.ts +15 -2
- package/templates/bills-agent/packages/agent-core/src/stubs/rail.ts +7 -4
- package/templates/bills-agent/packages/agent-core/src/types.ts +15 -2
- package/templates/bills-agent/packages/agent-core/test/actor-on-the-wire.test.ts +144 -0
- package/templates/bills-agent/packages/agent-core/test/attempt-replay.test.ts +2 -2
- package/templates/bills-agent/packages/agent-core/test/engine.test.ts +23 -0
- package/templates/bills-agent/packages/agent-core/test/helpers.ts +1 -1
- package/templates/bills-agent/packages/agent-core/test/language.test.ts +40 -0
- package/templates/bills-agent/packages/agent-core/test/locale.test.ts +137 -0
- package/templates/bills-agent/packages/agent-core/test/mandate-status.test.ts +2 -2
- package/templates/bills-agent/packages/agent-core/test/manifest.test.ts +2 -2
- package/templates/bills-agent/packages/agent-core/test/rail-errors.test.ts +74 -0
- package/templates/bills-agent/packages/agent-core/test/receipt-read-verification.test.ts +32 -0
- package/templates/bills-agent/packages/agent-core/test/receivables.test.ts +49 -0
- package/templates/bills-agent/packages/agent-core/test/recorded-turns.ts +29 -0
- package/templates/bills-agent/packages/agent-core/test/secrets.test.ts +40 -1
- package/templates/bills-agent/packages/agent-runtime/README.md +31 -4
- package/templates/bills-agent/packages/agent-runtime/src/channels/rules.ts +4 -2
- package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +11 -5
- package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +43 -21
- package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +3 -0
- package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +8 -12
- package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -4
- package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +12 -9
- package/templates/bills-agent/packages/agent-runtime/src/cli.ts +30 -4
- package/templates/bills-agent/packages/agent-runtime/src/commands/check.ts +18 -2
- package/templates/bills-agent/packages/agent-runtime/src/commands/decide.ts +13 -4
- package/templates/bills-agent/packages/agent-runtime/src/commands/eval.ts +7 -2
- package/templates/bills-agent/packages/agent-runtime/src/commands/inspect.ts +11 -13
- package/templates/bills-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +32 -24
- package/templates/bills-agent/packages/agent-runtime/src/commands/poll.ts +12 -5
- package/templates/bills-agent/packages/agent-runtime/src/commands/rerun.ts +83 -10
- package/templates/bills-agent/packages/agent-runtime/src/commands/resume.ts +2 -1
- package/templates/bills-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +10 -5
- package/templates/bills-agent/packages/agent-runtime/src/commands/start.ts +48 -17
- package/templates/bills-agent/packages/agent-runtime/src/commands/verify.ts +37 -12
- package/templates/bills-agent/packages/agent-runtime/src/commands/webhook.ts +11 -3
- package/templates/bills-agent/packages/agent-runtime/src/default-kit.ts +52 -22
- package/templates/bills-agent/packages/agent-runtime/src/env.ts +64 -0
- package/templates/bills-agent/packages/agent-runtime/src/index.ts +2 -0
- package/templates/bills-agent/packages/agent-runtime/src/inspect.ts +81 -10
- package/templates/bills-agent/packages/agent-runtime/src/kit.ts +34 -12
- package/templates/bills-agent/packages/agent-runtime/src/outcome.ts +118 -0
- package/templates/bills-agent/packages/agent-runtime/src/poll.ts +7 -7
- package/templates/bills-agent/packages/agent-runtime/src/runs.ts +51 -0
- package/templates/bills-agent/packages/agent-runtime/src/scenarios.ts +55 -8
- package/templates/bills-agent/packages/agent-runtime/src/setup.ts +75 -5
- package/templates/bills-agent/packages/agent-runtime/src/terminal.ts +71 -33
- package/templates/bills-agent/packages/agent-runtime/test/env-names.test.ts +56 -0
- package/templates/bills-agent/packages/agent-runtime/test/inspect-mandate-status.test.ts +80 -0
- package/templates/bills-agent/packages/agent-runtime/test/inspect.test.ts +63 -2
- package/templates/bills-agent/packages/agent-runtime/test/outcome.test.ts +72 -0
- package/templates/bills-agent/packages/agent-runtime/test/poll-payer.test.ts +64 -0
- package/templates/bills-agent/packages/agent-runtime/test/rerun-not-replayed.test.ts +46 -0
- package/templates/bills-agent/packages/agent-runtime/test/transition-line.test.ts +29 -0
- package/templates/bills-agent/packages/agent-runtime/test/verify-cli.test.ts +99 -6
- package/templates/bills-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +8 -0
- package/templates/bills-agent/packages/agent-runtime/test/whatsapp-session.test.ts +77 -0
- package/templates/bills-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +27 -1
- package/templates/checkout-agent/README.md +2 -2
- package/templates/checkout-agent/agents/checkout-agent/.env.example +6 -4
- package/templates/checkout-agent/agents/checkout-agent/README.md +16 -8
- package/templates/checkout-agent/agents/checkout-agent/SYSTEM_PROMPT.md +17 -7
- package/templates/checkout-agent/agents/checkout-agent/agent.yaml +4 -3
- package/templates/checkout-agent/agents/checkout-agent/channels/whatsapp/README.md +2 -2
- package/templates/checkout-agent/agents/checkout-agent/channels/whatsapp/templates.json +48 -4
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/beneficiary-swap-human.json +1 -1
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/beneficiary-swap.json +1 -1
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/beneficiary-swap.transcript.jsonl +1 -1
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/coupon-unknown.json +1 -1
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/exfiltration.transcript.jsonl +1 -1
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/fractioning.transcript.jsonl +1 -1
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/payment-claimed.json +1 -1
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/payment-claimed.transcript.jsonl +1 -1
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/price-injected.json +1 -1
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/prompt-injection.transcript.jsonl +1 -1
- package/templates/checkout-agent/agents/checkout-agent/evals/adversarial/quantity-swapped.transcript.jsonl +1 -1
- package/templates/checkout-agent/agents/checkout-agent/package.json +1 -1
- package/templates/checkout-agent/agents/checkout-agent/runbook.md +4 -4
- package/templates/checkout-agent/agents/checkout-agent/scenarios/beneficiary-not-allowed.transcript.jsonl +1 -1
- package/templates/checkout-agent/agents/checkout-agent/scenarios/cart-recomposed.transcript.jsonl +2 -2
- package/templates/checkout-agent/agents/checkout-agent/scenarios/cart-replaced.json +2 -2
- package/templates/checkout-agent/agents/checkout-agent/scenarios/cart-replaced.transcript.jsonl +2 -2
- package/templates/checkout-agent/agents/checkout-agent/scenarios/charge-expired.json +1 -1
- package/templates/checkout-agent/agents/checkout-agent/scenarios/charge-expired.transcript.jsonl +2 -2
- package/templates/checkout-agent/agents/checkout-agent/scenarios/coupon-unknown.transcript.jsonl +1 -1
- package/templates/checkout-agent/agents/checkout-agent/scenarios/escalated-above-threshold.transcript.jsonl +1 -1
- package/templates/checkout-agent/agents/checkout-agent/scenarios/happy-path.transcript.jsonl +2 -2
- package/templates/checkout-agent/agents/checkout-agent/scenarios/item-unavailable.transcript.jsonl +1 -1
- package/templates/checkout-agent/agents/checkout-agent/scenarios/mandate-revoked.transcript.jsonl +3 -3
- package/templates/checkout-agent/agents/checkout-agent/scenarios/payment-claimed.json +1 -1
- package/templates/checkout-agent/agents/checkout-agent/scenarios/payment-claimed.transcript.jsonl +2 -2
- package/templates/checkout-agent/agents/checkout-agent/scenarios/price-injected.transcript.jsonl +1 -1
- package/templates/checkout-agent/agents/checkout-agent/scenarios/prompt-injection.transcript.jsonl +1 -1
- package/templates/checkout-agent/agents/checkout-agent/src/catalog.ts +7 -7
- package/templates/checkout-agent/agents/checkout-agent/src/kit.ts +47 -43
- package/templates/checkout-agent/agents/checkout-agent/src/modules/bolepix-receivables.ts +20 -12
- package/templates/checkout-agent/agents/checkout-agent/src/modules/nfse-invoice.ts +4 -4
- package/templates/checkout-agent/agents/checkout-agent/src/modules/storefront-cart.ts +9 -6
- package/templates/checkout-agent/agents/checkout-agent/src/pricing.ts +44 -41
- package/templates/checkout-agent/agents/checkout-agent/src/strings.ts +179 -0
- package/templates/checkout-agent/agents/checkout-agent/test/check.test.ts +4 -1
- package/templates/checkout-agent/agents/checkout-agent/test/fixtures/order-marina.transcript.jsonl +1 -1
- package/templates/checkout-agent/agents/checkout-agent/test/fixtures/ordered-marina-awaiting-payer.transcript.jsonl +2 -2
- package/templates/checkout-agent/agents/checkout-agent/test/fixtures/tap-falar-agora-marina.transcript.jsonl +1 -1
- package/templates/checkout-agent/agents/checkout-agent/test/payable-instrument.test.ts +58 -0
- package/templates/checkout-agent/agents/checkout-agent/test/pricing.test.ts +2 -2
- package/templates/checkout-agent/agents/checkout-agent/test/rerun-unpaid.test.ts +47 -0
- package/templates/checkout-agent/agents/checkout-agent/test/scenario-reach-and-seconds.test.ts +55 -0
- package/templates/checkout-agent/agents/checkout-agent/test/whatsapp.test.ts +26 -10
- package/templates/checkout-agent/agents/checkout-agent/tools.json +1 -1
- package/templates/checkout-agent/packages/agent-core/README.md +21 -2
- package/templates/checkout-agent/packages/agent-core/package.json +1 -1
- package/templates/checkout-agent/packages/agent-core/src/agent.ts +33 -6
- package/templates/checkout-agent/packages/agent-core/src/api/charge-rail.ts +15 -1
- package/templates/checkout-agent/packages/agent-core/src/api/rail.ts +11 -5
- package/templates/checkout-agent/packages/agent-core/src/api/sandbox-payer.ts +36 -0
- package/templates/checkout-agent/packages/agent-core/src/bundle.ts +2 -0
- package/templates/checkout-agent/packages/agent-core/src/channels.ts +18 -8
- package/templates/checkout-agent/packages/agent-core/src/check.ts +25 -3
- package/templates/checkout-agent/packages/agent-core/src/engine.ts +90 -9
- package/templates/checkout-agent/packages/agent-core/src/escalate.ts +10 -0
- package/templates/checkout-agent/packages/agent-core/src/index.ts +3 -0
- package/templates/checkout-agent/packages/agent-core/src/language.ts +52 -0
- package/templates/checkout-agent/packages/agent-core/src/locale.ts +88 -0
- package/templates/checkout-agent/packages/agent-core/src/manifest.ts +4 -1
- package/templates/checkout-agent/packages/agent-core/src/rail.ts +29 -1
- package/templates/checkout-agent/packages/agent-core/src/receipt-verification.ts +30 -2
- package/templates/checkout-agent/packages/agent-core/src/secrets.ts +53 -8
- package/templates/checkout-agent/packages/agent-core/src/state-machine.ts +14 -0
- package/templates/checkout-agent/packages/agent-core/src/strings.ts +175 -0
- package/templates/checkout-agent/packages/agent-core/src/stubs/charge-rail.ts +15 -2
- package/templates/checkout-agent/packages/agent-core/src/stubs/rail.ts +7 -4
- package/templates/checkout-agent/packages/agent-core/src/types.ts +15 -2
- package/templates/checkout-agent/packages/agent-core/test/actor-on-the-wire.test.ts +144 -0
- package/templates/checkout-agent/packages/agent-core/test/attempt-replay.test.ts +2 -2
- package/templates/checkout-agent/packages/agent-core/test/engine.test.ts +23 -0
- package/templates/checkout-agent/packages/agent-core/test/helpers.ts +1 -1
- package/templates/checkout-agent/packages/agent-core/test/language.test.ts +40 -0
- package/templates/checkout-agent/packages/agent-core/test/locale.test.ts +137 -0
- package/templates/checkout-agent/packages/agent-core/test/mandate-status.test.ts +2 -2
- package/templates/checkout-agent/packages/agent-core/test/manifest.test.ts +2 -2
- package/templates/checkout-agent/packages/agent-core/test/rail-errors.test.ts +74 -0
- package/templates/checkout-agent/packages/agent-core/test/receipt-read-verification.test.ts +32 -0
- package/templates/checkout-agent/packages/agent-core/test/receivables.test.ts +49 -0
- package/templates/checkout-agent/packages/agent-core/test/recorded-turns.ts +29 -0
- package/templates/checkout-agent/packages/agent-core/test/secrets.test.ts +40 -1
- package/templates/checkout-agent/packages/agent-runtime/README.md +31 -4
- package/templates/checkout-agent/packages/agent-runtime/src/channels/rules.ts +4 -2
- package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +11 -5
- package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +43 -21
- package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +3 -0
- package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +8 -12
- package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -4
- package/templates/checkout-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +12 -9
- package/templates/checkout-agent/packages/agent-runtime/src/cli.ts +30 -4
- package/templates/checkout-agent/packages/agent-runtime/src/commands/check.ts +18 -2
- package/templates/checkout-agent/packages/agent-runtime/src/commands/decide.ts +13 -4
- package/templates/checkout-agent/packages/agent-runtime/src/commands/eval.ts +7 -2
- package/templates/checkout-agent/packages/agent-runtime/src/commands/inspect.ts +11 -13
- package/templates/checkout-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +32 -24
- package/templates/checkout-agent/packages/agent-runtime/src/commands/poll.ts +12 -5
- package/templates/checkout-agent/packages/agent-runtime/src/commands/rerun.ts +83 -10
- package/templates/checkout-agent/packages/agent-runtime/src/commands/resume.ts +2 -1
- package/templates/checkout-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +10 -5
- package/templates/checkout-agent/packages/agent-runtime/src/commands/start.ts +48 -17
- package/templates/checkout-agent/packages/agent-runtime/src/commands/verify.ts +37 -12
- package/templates/checkout-agent/packages/agent-runtime/src/commands/webhook.ts +11 -3
- package/templates/checkout-agent/packages/agent-runtime/src/default-kit.ts +52 -22
- package/templates/checkout-agent/packages/agent-runtime/src/env.ts +64 -0
- package/templates/checkout-agent/packages/agent-runtime/src/index.ts +2 -0
- package/templates/checkout-agent/packages/agent-runtime/src/inspect.ts +81 -10
- package/templates/checkout-agent/packages/agent-runtime/src/kit.ts +34 -12
- package/templates/checkout-agent/packages/agent-runtime/src/outcome.ts +118 -0
- package/templates/checkout-agent/packages/agent-runtime/src/poll.ts +7 -7
- package/templates/checkout-agent/packages/agent-runtime/src/runs.ts +51 -0
- package/templates/checkout-agent/packages/agent-runtime/src/scenarios.ts +55 -8
- package/templates/checkout-agent/packages/agent-runtime/src/setup.ts +75 -5
- package/templates/checkout-agent/packages/agent-runtime/src/terminal.ts +71 -33
- package/templates/checkout-agent/packages/agent-runtime/test/env-names.test.ts +56 -0
- package/templates/checkout-agent/packages/agent-runtime/test/inspect-mandate-status.test.ts +80 -0
- package/templates/checkout-agent/packages/agent-runtime/test/inspect.test.ts +63 -2
- package/templates/checkout-agent/packages/agent-runtime/test/outcome.test.ts +72 -0
- package/templates/checkout-agent/packages/agent-runtime/test/poll-payer.test.ts +64 -0
- package/templates/checkout-agent/packages/agent-runtime/test/rerun-not-replayed.test.ts +46 -0
- package/templates/checkout-agent/packages/agent-runtime/test/transition-line.test.ts +29 -0
- package/templates/checkout-agent/packages/agent-runtime/test/verify-cli.test.ts +99 -6
- package/templates/checkout-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +8 -0
- package/templates/checkout-agent/packages/agent-runtime/test/whatsapp-session.test.ts +77 -0
- package/templates/checkout-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +27 -1
- package/templates/collections-agent/README.md +2 -2
- package/templates/collections-agent/agents/collections-agent/.env.example +6 -3
- package/templates/collections-agent/agents/collections-agent/README.md +14 -9
- package/templates/collections-agent/agents/collections-agent/SYSTEM_PROMPT.md +16 -5
- package/templates/collections-agent/agents/collections-agent/agent.yaml +4 -3
- package/templates/collections-agent/agents/collections-agent/channels/whatsapp/README.md +21 -4
- package/templates/collections-agent/agents/collections-agent/channels/whatsapp/templates.json +49 -5
- package/templates/collections-agent/agents/collections-agent/mandate.example.json +1 -1
- package/templates/collections-agent/agents/collections-agent/runbook.md +3 -3
- package/templates/collections-agent/agents/collections-agent/src/agreements.ts +1 -1
- package/templates/collections-agent/agents/collections-agent/src/envelope.ts +15 -13
- package/templates/collections-agent/agents/collections-agent/src/kit.ts +38 -35
- package/templates/collections-agent/agents/collections-agent/src/modules/bolepix-receivables.ts +16 -8
- package/templates/collections-agent/agents/collections-agent/src/strings.ts +91 -0
- package/templates/collections-agent/agents/collections-agent/test/ambiguous-charge.test.ts +2 -2
- package/templates/collections-agent/agents/collections-agent/test/check.test.ts +4 -1
- package/templates/collections-agent/agents/collections-agent/test/cli.test.ts +1 -1
- package/templates/collections-agent/agents/collections-agent/test/envelope.test.ts +2 -2
- package/templates/collections-agent/agents/collections-agent/test/fixtures/accept-1103.transcript.jsonl +1 -1
- package/templates/collections-agent/agents/collections-agent/test/fixtures/tap-emitir-nova-1042.transcript.jsonl +1 -1
- package/templates/collections-agent/agents/collections-agent/test/payable-instrument.test.ts +56 -0
- package/templates/collections-agent/agents/collections-agent/test/rerun-clock.test.ts +54 -0
- package/templates/collections-agent/agents/collections-agent/test/whatsapp-poll.test.ts +69 -2
- package/templates/collections-agent/agents/collections-agent/test/whatsapp-status-replies.test.ts +16 -3
- package/templates/collections-agent/agents/collections-agent/test/whatsapp.test.ts +16 -4
- package/templates/collections-agent/agents/collections-agent/tools.json +2 -2
- package/templates/collections-agent/packages/agent-core/README.md +21 -2
- package/templates/collections-agent/packages/agent-core/package.json +1 -1
- package/templates/collections-agent/packages/agent-core/src/agent.ts +33 -6
- package/templates/collections-agent/packages/agent-core/src/api/charge-rail.ts +15 -1
- package/templates/collections-agent/packages/agent-core/src/api/rail.ts +11 -5
- package/templates/collections-agent/packages/agent-core/src/api/sandbox-payer.ts +36 -0
- package/templates/collections-agent/packages/agent-core/src/bundle.ts +2 -0
- package/templates/collections-agent/packages/agent-core/src/channels.ts +18 -8
- package/templates/collections-agent/packages/agent-core/src/check.ts +25 -3
- package/templates/collections-agent/packages/agent-core/src/engine.ts +90 -9
- package/templates/collections-agent/packages/agent-core/src/escalate.ts +10 -0
- package/templates/collections-agent/packages/agent-core/src/index.ts +3 -0
- package/templates/collections-agent/packages/agent-core/src/language.ts +52 -0
- package/templates/collections-agent/packages/agent-core/src/locale.ts +88 -0
- package/templates/collections-agent/packages/agent-core/src/manifest.ts +4 -1
- package/templates/collections-agent/packages/agent-core/src/rail.ts +29 -1
- package/templates/collections-agent/packages/agent-core/src/receipt-verification.ts +30 -2
- package/templates/collections-agent/packages/agent-core/src/secrets.ts +53 -8
- package/templates/collections-agent/packages/agent-core/src/state-machine.ts +14 -0
- package/templates/collections-agent/packages/agent-core/src/strings.ts +175 -0
- package/templates/collections-agent/packages/agent-core/src/stubs/charge-rail.ts +15 -2
- package/templates/collections-agent/packages/agent-core/src/stubs/rail.ts +7 -4
- package/templates/collections-agent/packages/agent-core/src/types.ts +15 -2
- package/templates/collections-agent/packages/agent-core/test/actor-on-the-wire.test.ts +144 -0
- package/templates/collections-agent/packages/agent-core/test/attempt-replay.test.ts +2 -2
- package/templates/collections-agent/packages/agent-core/test/engine.test.ts +23 -0
- package/templates/collections-agent/packages/agent-core/test/helpers.ts +1 -1
- package/templates/collections-agent/packages/agent-core/test/language.test.ts +40 -0
- package/templates/collections-agent/packages/agent-core/test/locale.test.ts +137 -0
- package/templates/collections-agent/packages/agent-core/test/mandate-status.test.ts +2 -2
- package/templates/collections-agent/packages/agent-core/test/manifest.test.ts +2 -2
- package/templates/collections-agent/packages/agent-core/test/rail-errors.test.ts +74 -0
- package/templates/collections-agent/packages/agent-core/test/receipt-read-verification.test.ts +32 -0
- package/templates/collections-agent/packages/agent-core/test/receivables.test.ts +49 -0
- package/templates/collections-agent/packages/agent-core/test/recorded-turns.ts +29 -0
- package/templates/collections-agent/packages/agent-core/test/secrets.test.ts +40 -1
- package/templates/collections-agent/packages/agent-runtime/README.md +31 -4
- package/templates/collections-agent/packages/agent-runtime/src/channels/rules.ts +4 -2
- package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +11 -5
- package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +43 -21
- package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +3 -0
- package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +8 -12
- package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -4
- package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +12 -9
- package/templates/collections-agent/packages/agent-runtime/src/cli.ts +30 -4
- package/templates/collections-agent/packages/agent-runtime/src/commands/check.ts +18 -2
- package/templates/collections-agent/packages/agent-runtime/src/commands/decide.ts +13 -4
- package/templates/collections-agent/packages/agent-runtime/src/commands/eval.ts +7 -2
- package/templates/collections-agent/packages/agent-runtime/src/commands/inspect.ts +11 -13
- package/templates/collections-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +32 -24
- package/templates/collections-agent/packages/agent-runtime/src/commands/poll.ts +12 -5
- package/templates/collections-agent/packages/agent-runtime/src/commands/rerun.ts +83 -10
- package/templates/collections-agent/packages/agent-runtime/src/commands/resume.ts +2 -1
- package/templates/collections-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +10 -5
- package/templates/collections-agent/packages/agent-runtime/src/commands/start.ts +48 -17
- package/templates/collections-agent/packages/agent-runtime/src/commands/verify.ts +37 -12
- package/templates/collections-agent/packages/agent-runtime/src/commands/webhook.ts +11 -3
- package/templates/collections-agent/packages/agent-runtime/src/default-kit.ts +52 -22
- package/templates/collections-agent/packages/agent-runtime/src/env.ts +64 -0
- package/templates/collections-agent/packages/agent-runtime/src/index.ts +2 -0
- package/templates/collections-agent/packages/agent-runtime/src/inspect.ts +81 -10
- package/templates/collections-agent/packages/agent-runtime/src/kit.ts +34 -12
- package/templates/collections-agent/packages/agent-runtime/src/outcome.ts +118 -0
- package/templates/collections-agent/packages/agent-runtime/src/poll.ts +7 -7
- package/templates/collections-agent/packages/agent-runtime/src/runs.ts +51 -0
- package/templates/collections-agent/packages/agent-runtime/src/scenarios.ts +55 -8
- package/templates/collections-agent/packages/agent-runtime/src/setup.ts +75 -5
- package/templates/collections-agent/packages/agent-runtime/src/terminal.ts +71 -33
- package/templates/collections-agent/packages/agent-runtime/test/env-names.test.ts +56 -0
- package/templates/collections-agent/packages/agent-runtime/test/inspect-mandate-status.test.ts +80 -0
- package/templates/collections-agent/packages/agent-runtime/test/inspect.test.ts +63 -2
- package/templates/collections-agent/packages/agent-runtime/test/outcome.test.ts +72 -0
- package/templates/collections-agent/packages/agent-runtime/test/poll-payer.test.ts +64 -0
- package/templates/collections-agent/packages/agent-runtime/test/rerun-not-replayed.test.ts +46 -0
- package/templates/collections-agent/packages/agent-runtime/test/transition-line.test.ts +29 -0
- package/templates/collections-agent/packages/agent-runtime/test/verify-cli.test.ts +99 -6
- package/templates/collections-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +8 -0
- package/templates/collections-agent/packages/agent-runtime/test/whatsapp-session.test.ts +77 -0
- package/templates/collections-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +27 -1
- package/templates/hello-agent/README.md +2 -2
- package/templates/hello-agent/agents/hello-agent/README.md +6 -0
- package/templates/hello-agent/agents/hello-agent/SYSTEM_PROMPT.md +27 -13
- package/templates/hello-agent/agents/hello-agent/agent.yaml +2 -1
- package/templates/hello-agent/agents/hello-agent/evals/adversarial/exfiltration.transcript.jsonl +1 -1
- package/templates/hello-agent/agents/hello-agent/evals/adversarial/prompt-injection.transcript.jsonl +1 -1
- package/templates/hello-agent/agents/hello-agent/mandate.example.json +1 -1
- package/templates/hello-agent/agents/hello-agent/scenarios/happy-path.json +1 -1
- package/templates/hello-agent/agents/hello-agent/scenarios/happy-path.transcript.jsonl +1 -1
- package/templates/hello-agent/agents/hello-agent/scenarios/prompt-injection.json +1 -1
- package/templates/hello-agent/agents/hello-agent/scenarios/prompt-injection.transcript.jsonl +1 -1
- package/templates/hello-agent/agents/hello-agent/src/bills.ts +9 -5
- package/templates/hello-agent/agents/hello-agent/src/kit.ts +4 -1
- package/templates/hello-agent/agents/hello-agent/tools.json +1 -1
- package/templates/hello-agent/packages/agent-core/README.md +21 -2
- package/templates/hello-agent/packages/agent-core/package.json +1 -1
- package/templates/hello-agent/packages/agent-core/src/agent.ts +33 -6
- package/templates/hello-agent/packages/agent-core/src/api/charge-rail.ts +15 -1
- package/templates/hello-agent/packages/agent-core/src/api/rail.ts +11 -5
- package/templates/hello-agent/packages/agent-core/src/api/sandbox-payer.ts +36 -0
- package/templates/hello-agent/packages/agent-core/src/bundle.ts +2 -0
- package/templates/hello-agent/packages/agent-core/src/channels.ts +18 -8
- package/templates/hello-agent/packages/agent-core/src/check.ts +25 -3
- package/templates/hello-agent/packages/agent-core/src/engine.ts +90 -9
- package/templates/hello-agent/packages/agent-core/src/escalate.ts +10 -0
- package/templates/hello-agent/packages/agent-core/src/index.ts +3 -0
- package/templates/hello-agent/packages/agent-core/src/language.ts +52 -0
- package/templates/hello-agent/packages/agent-core/src/locale.ts +88 -0
- package/templates/hello-agent/packages/agent-core/src/manifest.ts +4 -1
- package/templates/hello-agent/packages/agent-core/src/rail.ts +29 -1
- package/templates/hello-agent/packages/agent-core/src/receipt-verification.ts +30 -2
- package/templates/hello-agent/packages/agent-core/src/secrets.ts +53 -8
- package/templates/hello-agent/packages/agent-core/src/state-machine.ts +14 -0
- package/templates/hello-agent/packages/agent-core/src/strings.ts +175 -0
- package/templates/hello-agent/packages/agent-core/src/stubs/charge-rail.ts +15 -2
- package/templates/hello-agent/packages/agent-core/src/stubs/rail.ts +7 -4
- package/templates/hello-agent/packages/agent-core/src/types.ts +15 -2
- package/templates/hello-agent/packages/agent-core/test/actor-on-the-wire.test.ts +144 -0
- package/templates/hello-agent/packages/agent-core/test/attempt-replay.test.ts +2 -2
- package/templates/hello-agent/packages/agent-core/test/engine.test.ts +23 -0
- package/templates/hello-agent/packages/agent-core/test/helpers.ts +1 -1
- package/templates/hello-agent/packages/agent-core/test/language.test.ts +40 -0
- package/templates/hello-agent/packages/agent-core/test/locale.test.ts +137 -0
- package/templates/hello-agent/packages/agent-core/test/mandate-status.test.ts +2 -2
- package/templates/hello-agent/packages/agent-core/test/manifest.test.ts +2 -2
- package/templates/hello-agent/packages/agent-core/test/rail-errors.test.ts +74 -0
- package/templates/hello-agent/packages/agent-core/test/receipt-read-verification.test.ts +32 -0
- package/templates/hello-agent/packages/agent-core/test/receivables.test.ts +49 -0
- package/templates/hello-agent/packages/agent-core/test/recorded-turns.ts +29 -0
- package/templates/hello-agent/packages/agent-core/test/secrets.test.ts +40 -1
- package/templates/hello-agent/packages/agent-runtime/README.md +31 -4
- package/templates/hello-agent/packages/agent-runtime/src/channels/rules.ts +4 -2
- package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +11 -5
- package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +43 -21
- package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +3 -0
- package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +8 -12
- package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -4
- package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +12 -9
- package/templates/hello-agent/packages/agent-runtime/src/cli.ts +30 -4
- package/templates/hello-agent/packages/agent-runtime/src/commands/check.ts +18 -2
- package/templates/hello-agent/packages/agent-runtime/src/commands/decide.ts +13 -4
- package/templates/hello-agent/packages/agent-runtime/src/commands/eval.ts +7 -2
- package/templates/hello-agent/packages/agent-runtime/src/commands/inspect.ts +11 -13
- package/templates/hello-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +32 -24
- package/templates/hello-agent/packages/agent-runtime/src/commands/poll.ts +12 -5
- package/templates/hello-agent/packages/agent-runtime/src/commands/rerun.ts +83 -10
- package/templates/hello-agent/packages/agent-runtime/src/commands/resume.ts +2 -1
- package/templates/hello-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +10 -5
- package/templates/hello-agent/packages/agent-runtime/src/commands/start.ts +48 -17
- package/templates/hello-agent/packages/agent-runtime/src/commands/verify.ts +37 -12
- package/templates/hello-agent/packages/agent-runtime/src/commands/webhook.ts +11 -3
- package/templates/hello-agent/packages/agent-runtime/src/default-kit.ts +52 -22
- package/templates/hello-agent/packages/agent-runtime/src/env.ts +64 -0
- package/templates/hello-agent/packages/agent-runtime/src/index.ts +2 -0
- package/templates/hello-agent/packages/agent-runtime/src/inspect.ts +81 -10
- package/templates/hello-agent/packages/agent-runtime/src/kit.ts +34 -12
- package/templates/hello-agent/packages/agent-runtime/src/outcome.ts +118 -0
- package/templates/hello-agent/packages/agent-runtime/src/poll.ts +7 -7
- package/templates/hello-agent/packages/agent-runtime/src/runs.ts +51 -0
- package/templates/hello-agent/packages/agent-runtime/src/scenarios.ts +55 -8
- package/templates/hello-agent/packages/agent-runtime/src/setup.ts +75 -5
- package/templates/hello-agent/packages/agent-runtime/src/terminal.ts +71 -33
- package/templates/hello-agent/packages/agent-runtime/test/env-names.test.ts +56 -0
- package/templates/hello-agent/packages/agent-runtime/test/inspect-mandate-status.test.ts +80 -0
- package/templates/hello-agent/packages/agent-runtime/test/inspect.test.ts +63 -2
- package/templates/hello-agent/packages/agent-runtime/test/outcome.test.ts +72 -0
- package/templates/hello-agent/packages/agent-runtime/test/poll-payer.test.ts +64 -0
- package/templates/hello-agent/packages/agent-runtime/test/rerun-not-replayed.test.ts +46 -0
- package/templates/hello-agent/packages/agent-runtime/test/transition-line.test.ts +29 -0
- package/templates/hello-agent/packages/agent-runtime/test/verify-cli.test.ts +99 -6
- package/templates/hello-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +8 -0
- package/templates/hello-agent/packages/agent-runtime/test/whatsapp-session.test.ts +77 -0
- package/templates/hello-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +27 -1
- package/templates/kits.lock.json +12 -12
- package/templates/supplier-payments-agent/README.md +2 -2
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/.env.example +2 -2
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/README.md +12 -7
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/SYSTEM_PROMPT.md +14 -3
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/agent.yaml +2 -1
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/exfiltration.transcript.jsonl +1 -1
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/false-authority.transcript.jsonl +1 -1
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/prompt-injection.transcript.jsonl +1 -1
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/mandate.example.json +3 -3
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/beneficiary-not-allowed.transcript.jsonl +1 -1
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/cap-exceeded.transcript.jsonl +1 -1
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/escalated-above-threshold.transcript.jsonl +5 -5
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/happy-path.transcript.jsonl +1 -1
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/mandate-revoked.transcript.jsonl +5 -5
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/partial-batch-failure.json +1 -1
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/partial-batch-failure.transcript.jsonl +1 -1
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/prompt-injection.transcript.jsonl +1 -1
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/kit.ts +37 -26
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/modules/batch-payout.ts +41 -14
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/modules/pix-out.ts +12 -3
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/payables.ts +8 -8
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/batch.test.ts +75 -10
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/locale.test.ts +101 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/run-outcome.test.ts +127 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/tools.json +1 -1
- package/templates/supplier-payments-agent/packages/agent-core/README.md +21 -2
- package/templates/supplier-payments-agent/packages/agent-core/package.json +1 -1
- package/templates/supplier-payments-agent/packages/agent-core/src/agent.ts +33 -6
- package/templates/supplier-payments-agent/packages/agent-core/src/api/charge-rail.ts +15 -1
- package/templates/supplier-payments-agent/packages/agent-core/src/api/rail.ts +11 -5
- package/templates/supplier-payments-agent/packages/agent-core/src/api/sandbox-payer.ts +36 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/bundle.ts +2 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/channels.ts +18 -8
- package/templates/supplier-payments-agent/packages/agent-core/src/check.ts +25 -3
- package/templates/supplier-payments-agent/packages/agent-core/src/engine.ts +90 -9
- package/templates/supplier-payments-agent/packages/agent-core/src/escalate.ts +10 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/index.ts +3 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/language.ts +52 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/locale.ts +88 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/manifest.ts +4 -1
- package/templates/supplier-payments-agent/packages/agent-core/src/rail.ts +29 -1
- package/templates/supplier-payments-agent/packages/agent-core/src/receipt-verification.ts +30 -2
- package/templates/supplier-payments-agent/packages/agent-core/src/secrets.ts +53 -8
- package/templates/supplier-payments-agent/packages/agent-core/src/state-machine.ts +14 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/strings.ts +175 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/stubs/charge-rail.ts +15 -2
- package/templates/supplier-payments-agent/packages/agent-core/src/stubs/rail.ts +7 -4
- package/templates/supplier-payments-agent/packages/agent-core/src/types.ts +15 -2
- package/templates/supplier-payments-agent/packages/agent-core/test/actor-on-the-wire.test.ts +144 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/attempt-replay.test.ts +2 -2
- package/templates/supplier-payments-agent/packages/agent-core/test/engine.test.ts +23 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/helpers.ts +1 -1
- package/templates/supplier-payments-agent/packages/agent-core/test/language.test.ts +40 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/locale.test.ts +137 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/mandate-status.test.ts +2 -2
- package/templates/supplier-payments-agent/packages/agent-core/test/manifest.test.ts +2 -2
- package/templates/supplier-payments-agent/packages/agent-core/test/rail-errors.test.ts +74 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/receipt-read-verification.test.ts +32 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/receivables.test.ts +49 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/recorded-turns.ts +29 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/secrets.test.ts +40 -1
- package/templates/supplier-payments-agent/packages/agent-runtime/README.md +31 -4
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/rules.ts +4 -2
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +11 -5
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +43 -21
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +3 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +8 -12
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +8 -4
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +12 -9
- package/templates/supplier-payments-agent/packages/agent-runtime/src/cli.ts +30 -4
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/check.ts +18 -2
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/decide.ts +13 -4
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/eval.ts +7 -2
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/inspect.ts +11 -13
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +32 -24
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/poll.ts +12 -5
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/rerun.ts +83 -10
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/resume.ts +2 -1
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +10 -5
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/start.ts +48 -17
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/verify.ts +37 -12
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/webhook.ts +11 -3
- package/templates/supplier-payments-agent/packages/agent-runtime/src/default-kit.ts +52 -22
- package/templates/supplier-payments-agent/packages/agent-runtime/src/env.ts +64 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/index.ts +2 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/inspect.ts +81 -10
- package/templates/supplier-payments-agent/packages/agent-runtime/src/kit.ts +34 -12
- package/templates/supplier-payments-agent/packages/agent-runtime/src/outcome.ts +118 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/poll.ts +7 -7
- package/templates/supplier-payments-agent/packages/agent-runtime/src/runs.ts +51 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/scenarios.ts +55 -8
- package/templates/supplier-payments-agent/packages/agent-runtime/src/setup.ts +75 -5
- package/templates/supplier-payments-agent/packages/agent-runtime/src/terminal.ts +71 -33
- package/templates/supplier-payments-agent/packages/agent-runtime/test/env-names.test.ts +56 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/test/inspect-mandate-status.test.ts +80 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/test/inspect.test.ts +63 -2
- package/templates/supplier-payments-agent/packages/agent-runtime/test/outcome.test.ts +72 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/test/poll-payer.test.ts +64 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/test/rerun-not-replayed.test.ts +46 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/test/transition-line.test.ts +29 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/test/verify-cli.test.ts +99 -6
- package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +8 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-session.test.ts +77 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-status-replies.test.ts +27 -1
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #64 on the approval path: the locale changes what the titular READS and
|
|
3
|
+
* nothing about what their answer DECIDES. The same answer to the pt-BR
|
|
4
|
+
* question and to the English one ends in the same state, and the approval
|
|
5
|
+
* artifact names the same approver.
|
|
6
|
+
*
|
|
7
|
+
* And the resolution, end to end: `--locale` beats `agent.yaml`, which beats
|
|
8
|
+
* the default, and the run's bundle records the locale it ran in.
|
|
9
|
+
*/
|
|
10
|
+
import { spawnSync } from "node:child_process";
|
|
11
|
+
import { cpSync, mkdtempSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { tmpdir } from "node:os";
|
|
13
|
+
import { join, resolve } from "node:path";
|
|
14
|
+
import { describe, expect, it } from "vitest";
|
|
15
|
+
import { fixedClock, type Locale } from "@codespar/agent-core";
|
|
16
|
+
import { handleExecution, parseApproval, setup, type Setup } from "@codespar/agent-runtime";
|
|
17
|
+
import { agent } from "../src/kit.js";
|
|
18
|
+
|
|
19
|
+
const AGENT_DIR = resolve(import.meta.dirname, "..");
|
|
20
|
+
const NODE = process.execPath;
|
|
21
|
+
const BIN = resolve(AGENT_DIR, "../../packages/agent-runtime/bin.mjs");
|
|
22
|
+
const APPROVER = { id: "usr_demo_titular", channel: "terminal" };
|
|
23
|
+
/** Every answer the `[s/N]` parser has a rule for, both languages, plus what falls through to no. */
|
|
24
|
+
const ANSWERS = ["s", "sim", "y", "yes", " SIM ", "Yes", "n", "nao", "não", "no", "", "talvez", "si"];
|
|
25
|
+
|
|
26
|
+
function open(locale: Locale | undefined, dir = AGENT_DIR): Setup {
|
|
27
|
+
return setup(dir === AGENT_DIR ? agent : { ...agent, dir }, {
|
|
28
|
+
mode: "human",
|
|
29
|
+
rail: "stub",
|
|
30
|
+
provider: "replay",
|
|
31
|
+
runsDir: mkdtempSync(join(tmpdir(), "bills-locale-runs-")),
|
|
32
|
+
stateDir: mkdtempSync(join(tmpdir(), "bills-locale-state-")),
|
|
33
|
+
now: fixedClock("2026-09-23T14:00:00-03:00"),
|
|
34
|
+
say: () => undefined,
|
|
35
|
+
...(locale ? { locale } : {}),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Proposes one payment and answers the approval question with `answer`; returns the final state, the question asked and the console. */
|
|
40
|
+
async function decideOnce(locale: Locale, answer: string) {
|
|
41
|
+
const s = open(locale);
|
|
42
|
+
const asked: string[] = [];
|
|
43
|
+
const said: string[] = [];
|
|
44
|
+
try {
|
|
45
|
+
const draft = await s.engine.draft({ items: [{ payee: "escola", amount: 185000, description: "mensalidade de outubro" }] });
|
|
46
|
+
if (!draft.ok) throw new Error(draft.reason);
|
|
47
|
+
const final = await handleExecution(draft.execution, {
|
|
48
|
+
setup: s,
|
|
49
|
+
approver: APPROVER,
|
|
50
|
+
ask: async (q) => {
|
|
51
|
+
asked.push(q);
|
|
52
|
+
return answer;
|
|
53
|
+
},
|
|
54
|
+
say: (l) => void said.push(l),
|
|
55
|
+
});
|
|
56
|
+
const approvers = s.bundle.readApprovals().map((a) => a.approver);
|
|
57
|
+
return { state: final.state, asked, said, approvers };
|
|
58
|
+
} finally {
|
|
59
|
+
s.close();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
describe("the approval question decides the same in both locales", () => {
|
|
64
|
+
it.each(ANSWERS)("answer %j", async (answer) => {
|
|
65
|
+
const pt = await decideOnce("pt-BR", answer);
|
|
66
|
+
const en = await decideOnce("en", answer);
|
|
67
|
+
// What was shown differs...
|
|
68
|
+
expect(pt.asked).toEqual([" Aprovar este pagamento? [s/N] "]);
|
|
69
|
+
expect(en.asked).toEqual([" Approve this payment? [y/N] "]);
|
|
70
|
+
// ...and what was decided does not.
|
|
71
|
+
expect(en.state).toBe(pt.state);
|
|
72
|
+
expect(en.approvers).toEqual(pt.approvers);
|
|
73
|
+
expect(pt.state).toBe(parseApproval(answer) === "approve" ? "settled" : "denied");
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("prints the execution in the run's locale, accents included", async () => {
|
|
77
|
+
const pt = await decideOnce("pt-BR", "s");
|
|
78
|
+
const en = await decideOnce("en", "y");
|
|
79
|
+
expect(pt.said.join("\n")).toContain("execução exe_");
|
|
80
|
+
expect(pt.said.join("\n")).toContain("total (calculado pelo core): R$ 1.850,00");
|
|
81
|
+
expect(pt.said.join("\n")).toMatch(/recibo: /);
|
|
82
|
+
expect(en.said.join("\n")).toContain("execution exe_");
|
|
83
|
+
expect(en.said.join("\n")).toContain("total (computed by the core): R$1,850.00");
|
|
84
|
+
expect(en.said.join("\n")).toMatch(/receipt: /);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe("which locale a run speaks", () => {
|
|
89
|
+
function copyWithLocale(locale: string | undefined): string {
|
|
90
|
+
const dir = mkdtempSync(join(tmpdir(), "bills-locale-agent-"));
|
|
91
|
+
cpSync(AGENT_DIR, dir, { recursive: true, filter: (src) => !/node_modules|\/runs|\.codespar/.test(src) });
|
|
92
|
+
const yaml = readFileSync(join(dir, "agent.yaml"), "utf8").replace(/^locale:.*\n/m, locale ? `locale: ${locale}\n` : "");
|
|
93
|
+
writeFileSync(join(dir, "agent.yaml"), yaml);
|
|
94
|
+
return dir;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
it("is --locale, else agent.yaml's locale, else pt-BR; and the bundle records it", () => {
|
|
98
|
+
const cases: Array<[string | undefined, Locale | undefined, Locale]> = [
|
|
99
|
+
[undefined, undefined, "pt-BR"],
|
|
100
|
+
["en", undefined, "en"],
|
|
101
|
+
["en", "pt-BR", "pt-BR"],
|
|
102
|
+
["pt-BR", "en", "en"],
|
|
103
|
+
];
|
|
104
|
+
for (const [manifest, flag, expected] of cases) {
|
|
105
|
+
const s = open(flag, copyWithLocale(manifest));
|
|
106
|
+
try {
|
|
107
|
+
expect(s.locale).toBe(expected);
|
|
108
|
+
expect(s.bundle.readMeta()?.["locale"]).toBe(expected);
|
|
109
|
+
expect(s.strings).toBe(agent.kit.strings[expected]);
|
|
110
|
+
} finally {
|
|
111
|
+
s.close();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
function run(args: string[]) {
|
|
117
|
+
const stateDir = mkdtempSync(join(tmpdir(), "bills-locale-cli-"));
|
|
118
|
+
const result = spawnSync(NODE, [BIN, "start", ...args], {
|
|
119
|
+
cwd: AGENT_DIR,
|
|
120
|
+
env: { ...process.env, ANTHROPIC_API_KEY: "", CODESPAR_API_KEY: "", BILLS_STATE_DIR: stateDir, BILLS_RUNS_DIR: join(stateDir, "runs") },
|
|
121
|
+
encoding: "utf8",
|
|
122
|
+
timeout: 60_000,
|
|
123
|
+
});
|
|
124
|
+
const runs = join(stateDir, "runs");
|
|
125
|
+
let meta: Record<string, unknown> | undefined;
|
|
126
|
+
try {
|
|
127
|
+
const [dir] = readdirSync(runs);
|
|
128
|
+
meta = JSON.parse(readFileSync(join(runs, dir!, "run.json"), "utf8")) as Record<string, unknown>;
|
|
129
|
+
} catch {
|
|
130
|
+
meta = undefined;
|
|
131
|
+
}
|
|
132
|
+
return { code: result.status, stdout: result.stdout, stderr: result.stderr, meta };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
it("`npm start -- --locale en` prints the code's lines in English and pays the same", () => {
|
|
136
|
+
const pt = run(["--input", "pague a escola de outubro", "--approve", "--json"]);
|
|
137
|
+
const en = run(["--input", "pague a escola de outubro", "--approve", "--json", "--locale", "en"]);
|
|
138
|
+
expect(pt.code).toBe(0);
|
|
139
|
+
expect(en.code).toBe(0);
|
|
140
|
+
expect(pt.stderr).toContain("execução");
|
|
141
|
+
expect(pt.stderr).toContain("calculado pelo core");
|
|
142
|
+
expect(en.stderr).toContain("execution");
|
|
143
|
+
expect(en.stderr).toContain("computed by the core");
|
|
144
|
+
expect(en.stderr).not.toContain("execução");
|
|
145
|
+
expect(pt.meta?.["locale"]).toBe("pt-BR");
|
|
146
|
+
expect(en.meta?.["locale"]).toBe("en");
|
|
147
|
+
// The machine output is the same contract in both: same states, same receipts, no locale-dependent field.
|
|
148
|
+
const shape = (o: string) => {
|
|
149
|
+
const p = JSON.parse(o) as { executions: Array<{ state: string; total_minor: number; receipt_ids: string[] }> };
|
|
150
|
+
return p.executions.map((e) => ({ state: e.state, total_minor: e.total_minor, receipts: e.receipt_ids.length }));
|
|
151
|
+
};
|
|
152
|
+
expect(shape(en.stdout)).toEqual(shape(pt.stdout));
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("an unknown --locale is a usage error, before anything runs", () => {
|
|
156
|
+
const out = run(["--input", "pague a escola de outubro", "--locale", "es"]);
|
|
157
|
+
expect(out.code).toBe(2);
|
|
158
|
+
expect(out.stderr).toContain("--locale must be pt-BR or en");
|
|
159
|
+
expect(out.meta).toBeUndefined();
|
|
160
|
+
});
|
|
161
|
+
});
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the kit says about a mandate after it was revoked: `inspect` on the
|
|
3
|
+
* run that met the revocation, and the consent that replaces the mandate.
|
|
4
|
+
*/
|
|
5
|
+
import { mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
7
|
+
import { join, relative, resolve } from "node:path";
|
|
8
|
+
import { describe, expect, it } from "vitest";
|
|
9
|
+
import type { ApiClient } from "@codespar/sdk";
|
|
10
|
+
import { ProofBundle, loadMandate, type Mandate } from "@codespar/agent-core";
|
|
11
|
+
import { assembleTimeline, loadScenario, renderText, runScenario } from "@codespar/agent-runtime";
|
|
12
|
+
import { agent } from "../src/kit.js";
|
|
13
|
+
import { runEmbeddedConsent } from "../src/modules/embedded-consent.js";
|
|
14
|
+
|
|
15
|
+
const AGENT_DIR = resolve(import.meta.dirname, "..");
|
|
16
|
+
|
|
17
|
+
describe("npm run inspect on the run that met a revocation", () => {
|
|
18
|
+
it("the header says revoked, from the source that answered, and no longer says active", async () => {
|
|
19
|
+
const runsDir = mkdtempSync(join(tmpdir(), "bills-inspect-revoked-"));
|
|
20
|
+
const run = await runScenario(agent, loadScenario(agent, "mandate-revoked"), { mode: "human", runsDir });
|
|
21
|
+
const text = renderText(assembleTimeline(ProofBundle.open(runsDir, run.run_id)!));
|
|
22
|
+
const header = text.split("\n")[2]!;
|
|
23
|
+
|
|
24
|
+
// The line two below it, which the header used to contradict.
|
|
25
|
+
expect(text).toMatch(/was revoked \(source: stub\)/);
|
|
26
|
+
expect(header).toMatch(/^ {2}mandate revoked \(source: stub, \d\d:\d\d:\d\d; active in the snapshot at the start of the run\), expires /);
|
|
27
|
+
expect(text).not.toMatch(/^ {2}mandate active,/m);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("a run that met none still says active", async () => {
|
|
31
|
+
const runsDir = mkdtempSync(join(tmpdir(), "bills-inspect-active-"));
|
|
32
|
+
const run = await runScenario(agent, loadScenario(agent, "happy-path"), { mode: "human", runsDir });
|
|
33
|
+
expect(renderText(assembleTimeline(ProofBundle.open(runsDir, run.run_id)!)).split("\n")[2]).toMatch(/^ {2}mandate active, expires /);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
/** The four calls a consent makes, answered as the sandbox answers them; `status` is what `GET /v1/mandates/{id}` says of the mandate the file already holds. */
|
|
38
|
+
function fakeApi(example: Mandate, status: string | Error): { api: ApiClient; reads: string[] } {
|
|
39
|
+
const reads: string[] = [];
|
|
40
|
+
const api = {
|
|
41
|
+
post: async (path: string) => {
|
|
42
|
+
if (path === "/v1/consents/init") return { token: "tok_test", expires_at: "2026-09-23T18:30:00.000Z" };
|
|
43
|
+
if (path === "/v1/consents/{token}/submit") {
|
|
44
|
+
return {
|
|
45
|
+
mandate_id: "cm_new",
|
|
46
|
+
signature: "0".repeat(64),
|
|
47
|
+
mandate: { consumer_id: example.consumer_id, agent_id: example.agent_id, purpose: example.purpose, currency: "BRL", cap_minor: example.cap_minor, per_tx_cap_minor: example.per_tx_cap_minor, merchant_pin_kind: "pix-key", merchant_allowlist: example.beneficiaries.map((b) => b.payee), expires_at: 1821312000 },
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return { amount_minor: 600000, account: "acc_test", deposit_id: "dep_test" };
|
|
51
|
+
},
|
|
52
|
+
get: async (_path: string, options: { path: { id: string } }) => {
|
|
53
|
+
reads.push(options.path.id);
|
|
54
|
+
if (status instanceof Error) throw status;
|
|
55
|
+
return { status, expires_at: "2027-09-23T00:00:00.000Z", org_paused: false };
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
return { api: api as unknown as ApiClient, reads };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
describe("npm run consent", () => {
|
|
62
|
+
const example = loadMandate(join(AGENT_DIR, "mandate.example.json"));
|
|
63
|
+
const NOT_YET = "O mandato ainda não existe.";
|
|
64
|
+
|
|
65
|
+
async function consent(options: { previous?: Mandate; status?: string | Error; locale?: "pt-BR" | "en" }) {
|
|
66
|
+
const dir = mkdtempSync(join(tmpdir(), "bills-consent-"));
|
|
67
|
+
const mandatePath = join(dir, ".codespar", "mandate.json");
|
|
68
|
+
if (options.previous) {
|
|
69
|
+
mkdirSync(join(dir, ".codespar"));
|
|
70
|
+
writeFileSync(mandatePath, JSON.stringify(options.previous));
|
|
71
|
+
}
|
|
72
|
+
const said: string[] = [];
|
|
73
|
+
const { api, reads } = fakeApi(example, options.status ?? "active");
|
|
74
|
+
const mandate = await runEmbeddedConsent({ api, example, mandatePath, say: (l) => said.push(l), confirm: async () => true, now: () => new Date("2026-09-23T18:00:00.000Z"), ...(options.locale ? { locale: options.locale } : {}) });
|
|
75
|
+
return { said, reads, mandate, mandatePath, file: relative(process.cwd(), mandatePath) };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
it("with no mandate in the file, says it does not exist yet and reads no status", async () => {
|
|
79
|
+
const out = await consent({});
|
|
80
|
+
expect(out.said[1]).toContain(NOT_YET);
|
|
81
|
+
expect(out.reads).toEqual([]);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("after a revocation, names the revoked mandate the file holds instead of saying none exists", async () => {
|
|
85
|
+
const previous = { ...example, id: "cm_old" };
|
|
86
|
+
const out = await consent({ previous, status: "revoked" });
|
|
87
|
+
expect(out.reads).toEqual(["cm_old"]);
|
|
88
|
+
expect(out.said[1]).toBe(`Já existe um mandato em ${out.file}: cm_old, revogado na API. Este é o consentimento de um mandato novo, que passa a ser o do arquivo (sandbox):`);
|
|
89
|
+
expect(out.said.join("\n")).not.toContain(NOT_YET);
|
|
90
|
+
// And the file is the new mandate's afterwards, as the line said.
|
|
91
|
+
expect((JSON.parse(readFileSync(out.mandatePath, "utf8")) as { id: string }).id).toBe("cm_new");
|
|
92
|
+
expect(out.mandate.id).toBe("cm_new");
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("says the state the API answers, whatever it is, and says so when it does not answer", async () => {
|
|
96
|
+
const previous = { ...example, id: "cm_old" };
|
|
97
|
+
expect((await consent({ previous, status: "active" })).said[1]).toContain("cm_old, ativo na API.");
|
|
98
|
+
expect((await consent({ previous, status: "paused" })).said[1]).toContain("cm_old, pausado na API.");
|
|
99
|
+
expect((await consent({ previous, status: new Error("ECONNRESET") })).said[1]).toContain("cm_old, com estado que a API não respondeu.");
|
|
100
|
+
expect((await consent({ previous, status: "revoked", locale: "en" })).said[1]).toContain("already holds a mandate: cm_old, revoked on the API.");
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("a file it cannot read does not stop a new consent", async () => {
|
|
104
|
+
const out = await consent({ previous: { id: "not a mandate" } as unknown as Mandate });
|
|
105
|
+
expect(out.said[1]).toContain(NOT_YET);
|
|
106
|
+
expect(out.mandate.id).toBe("cm_new");
|
|
107
|
+
});
|
|
108
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A request made under a revoked mandate creates no execution: the engine
|
|
3
|
+
* refuses it before a draft. The terminal used to say nothing about it (the
|
|
4
|
+
* recorded reply even says "see the result on the terminal"), and only
|
|
5
|
+
* `inspect` showed the event. Driven as real processes, over a scratch state
|
|
6
|
+
* whose stub mandate is revoked between two runs.
|
|
7
|
+
*/
|
|
8
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
9
|
+
import { mkdtempSync } from "node:fs";
|
|
10
|
+
import { tmpdir } from "node:os";
|
|
11
|
+
import { join, resolve } from "node:path";
|
|
12
|
+
import { DatabaseSync } from "node:sqlite";
|
|
13
|
+
import { describe, expect, it } from "vitest";
|
|
14
|
+
|
|
15
|
+
const AGENT_DIR = resolve(import.meta.dirname, "..");
|
|
16
|
+
const BIN = resolve(AGENT_DIR, "../../packages/agent-runtime/bin.mjs");
|
|
17
|
+
const SCHOOL = "pague a escola de outubro";
|
|
18
|
+
const BASE_ENV = { ANTHROPIC_API_KEY: "", CODESPAR_API_KEY: "", CODESPAR_AGENT_NOW: "2026-10-07T14:00:00-03:00" };
|
|
19
|
+
|
|
20
|
+
function run(args: string[], env: Record<string, string>) {
|
|
21
|
+
const result = spawnSync(process.execPath, [BIN, "start", ...args], { cwd: AGENT_DIR, env: { ...process.env, ...BASE_ENV, ...env }, encoding: "utf8", timeout: 60_000 });
|
|
22
|
+
return { code: result.status, stdout: result.stdout, stderr: result.stderr };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** A scratch state holding one settled payment, with the stub mandate then revoked: what `codespar mandate revoke` leaves behind. */
|
|
26
|
+
function revoked(label: string): Record<string, string> {
|
|
27
|
+
const stateDir = mkdtempSync(join(tmpdir(), `bills-refused-${label}-`));
|
|
28
|
+
const env = { BILLS_STATE_DIR: stateDir, BILLS_RUNS_DIR: join(stateDir, "runs") };
|
|
29
|
+
const first = run(["--input", SCHOOL, "--approve", "--json"], env);
|
|
30
|
+
expect(first.code).toBe(0);
|
|
31
|
+
const mandateId = (JSON.parse(first.stdout.trim()) as { mandate_id: string }).mandate_id;
|
|
32
|
+
const db = new DatabaseSync(join(stateDir, "state.db"));
|
|
33
|
+
db.prepare("INSERT OR REPLACE INTO stub_mandate_status (mandate_id, status, reason, updated_at) VALUES (?, 'revoked', 'revoked by the test', ?)").run(mandateId, new Date().toISOString());
|
|
34
|
+
db.close();
|
|
35
|
+
return env;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
describe("a request under a revoked mandate, one-shot", () => {
|
|
39
|
+
it("names the refusal and its reason on the terminal, counts it, and exits 1", () => {
|
|
40
|
+
const out = run(["--input", SCHOOL, "--approve"], revoked("text"));
|
|
41
|
+
expect(out.stderr).toContain("-> refused_before_draft (mandate_revoked)");
|
|
42
|
+
expect(out.stdout).toContain("resultado deste run: 0 liquidada(s), 1 com falha ou recusada(s)");
|
|
43
|
+
expect(out.code).toBe(1);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("carries the same refusal in --json, with no execution", () => {
|
|
47
|
+
const out = run(["--input", SCHOOL, "--approve", "--json"], revoked("json"));
|
|
48
|
+
const payload = JSON.parse(out.stdout.trim()) as { executions: unknown[]; run_outcome: { failed: number }; refused_before_draft: Array<{ reason: string; detail: string }> };
|
|
49
|
+
expect(payload.executions).toHaveLength(0);
|
|
50
|
+
expect(payload.refused_before_draft).toHaveLength(1);
|
|
51
|
+
expect(payload.refused_before_draft[0]).toMatchObject({ reason: "mandate_revoked" });
|
|
52
|
+
expect(payload.refused_before_draft[0]?.detail).not.toBe("");
|
|
53
|
+
expect(payload.run_outcome.failed).toBe(1);
|
|
54
|
+
expect(out.code).toBe(1);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe("a request under a revoked mandate, interactive", () => {
|
|
59
|
+
it("names the refusal under the turn that made it", async () => {
|
|
60
|
+
const env = revoked("interactive");
|
|
61
|
+
const out = await new Promise<{ stdout: string; stderr: string }>((done, fail) => {
|
|
62
|
+
const child = spawn(process.execPath, [BIN, "start", "--transcript", "scenarios/mandate-revoked.transcript.jsonl"], { cwd: AGENT_DIR, env: { ...process.env, ...BASE_ENV, ...env } });
|
|
63
|
+
let stdout = "";
|
|
64
|
+
let stderr = "";
|
|
65
|
+
let typed = false;
|
|
66
|
+
// Typed when the prompt shows: readline drops a line that arrives before the question.
|
|
67
|
+
const feed = () => {
|
|
68
|
+
if (!typed && stderr.includes("> ")) {
|
|
69
|
+
typed = true;
|
|
70
|
+
child.stdin.end(SCHOOL + "\n");
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
child.stdout.on("data", (chunk: Buffer) => { stdout += chunk.toString(); });
|
|
74
|
+
child.stderr.on("data", (chunk: Buffer) => { stderr += chunk.toString(); feed(); });
|
|
75
|
+
child.on("error", fail);
|
|
76
|
+
child.on("close", () => done({ stdout, stderr }));
|
|
77
|
+
});
|
|
78
|
+
expect(out.stderr).toContain("-> refused_before_draft (mandate_revoked)");
|
|
79
|
+
expect(out.stdout).toContain("1 com falha ou recusada(s)");
|
|
80
|
+
});
|
|
81
|
+
});
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Issue #60 on the one-off payment: `codespar_pay` says `paid: true` only for
|
|
3
|
+
* a payment this call made. A bill's attempt id comes from its own execution,
|
|
4
|
+
* so the rail cannot replay one at dispatch today; the rail is scripted to
|
|
5
|
+
* answer the way the API answers a repeat, so the report is pinned before
|
|
6
|
+
* anything makes that reachable.
|
|
7
|
+
*/
|
|
8
|
+
import { mkdtempSync } from "node:fs";
|
|
9
|
+
import { tmpdir } from "node:os";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { describe, expect, it } from "vitest";
|
|
12
|
+
import { fixedClock, type Execution, type StubRail, type ToolContext } from "@codespar/agent-core";
|
|
13
|
+
import { setup, type Setup } from "@codespar/agent-runtime";
|
|
14
|
+
import { agent } from "../src/kit.js";
|
|
15
|
+
import { codesparPay } from "../src/modules/pix-out.js";
|
|
16
|
+
|
|
17
|
+
const APPROVER = { id: "usr_demo", channel: "terminal" };
|
|
18
|
+
|
|
19
|
+
function open(): Setup {
|
|
20
|
+
return setup(agent, {
|
|
21
|
+
mode: "human",
|
|
22
|
+
rail: "stub",
|
|
23
|
+
provider: "replay",
|
|
24
|
+
runsDir: mkdtempSync(join(tmpdir(), "bills-replay-runs-")),
|
|
25
|
+
stateDir: mkdtempSync(join(tmpdir(), "bills-replay-state-")),
|
|
26
|
+
now: fixedClock("2026-09-23T14:00:00-03:00"),
|
|
27
|
+
say: () => undefined,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function context(s: Setup): ToolContext {
|
|
32
|
+
return {
|
|
33
|
+
engine: s.engine,
|
|
34
|
+
onExecution: async (execution: Execution) => {
|
|
35
|
+
let current = execution;
|
|
36
|
+
if (current.state === "awaiting_approval") current = s.engine.approve(current.id, APPROVER);
|
|
37
|
+
if (current.state === "approved") current = await s.engine.execute(current.id);
|
|
38
|
+
return current;
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const PIX = { action: "pix", items: [{ payee: "mercado", amount_minor: 64000, description: "compras da semana" }] };
|
|
44
|
+
|
|
45
|
+
describe("codespar_pay: a settlement this call did not make is not reported as paid (#60)", () => {
|
|
46
|
+
it("a payment this call made is paid, and not replayed", async () => {
|
|
47
|
+
const s = open();
|
|
48
|
+
try {
|
|
49
|
+
const result = await codesparPay(PIX, context(s));
|
|
50
|
+
expect(result).toMatchObject({ status: "settled", paid: true, replayed: false });
|
|
51
|
+
} finally {
|
|
52
|
+
s.close();
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("a payment the rail answered from an earlier presentation is settled, replayed, and not paid by this call", async () => {
|
|
57
|
+
const s = open();
|
|
58
|
+
try {
|
|
59
|
+
const rail = s.rail as StubRail;
|
|
60
|
+
const pay = rail.pay.bind(rail);
|
|
61
|
+
rail.pay = async (payment) => {
|
|
62
|
+
const outcome = await pay(payment);
|
|
63
|
+
return outcome.status === "settled" ? { ...outcome, replayed: true } : outcome;
|
|
64
|
+
};
|
|
65
|
+
const result = (await codesparPay(PIX, context(s))) as { status: string; paid: boolean; replayed: boolean; receipt_ids: string[] };
|
|
66
|
+
expect(result).toMatchObject({ status: "settled", paid: false, replayed: true });
|
|
67
|
+
expect(result.receipt_ids).toHaveLength(1);
|
|
68
|
+
|
|
69
|
+
const oneShot = agent.kit.oneShotPayload({ setup: s, reply: "", toolCalls: [], executions: s.engine.list(), startedAt: 0 }) as { executions: Array<{ state: string; replayed: boolean }> };
|
|
70
|
+
expect(oneShot.executions).toEqual([expect.objectContaining({ state: "settled", replayed: true })]);
|
|
71
|
+
expect(agent.kit.describeExecution(s.engine.list()[0]!, s).join("\n")).toContain("esta execução não moveu dinheiro");
|
|
72
|
+
} finally {
|
|
73
|
+
s.close();
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
});
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The replayed reply of `happy-path` is the same sentence whatever the run
|
|
3
|
+
* does with the payment it proposed. It promises a result, which every run
|
|
4
|
+
* has, and no receipt, which only a settled one has.
|
|
5
|
+
*/
|
|
6
|
+
import { spawnSync } from "node:child_process";
|
|
7
|
+
import { mkdtempSync } from "node:fs";
|
|
8
|
+
import { tmpdir } from "node:os";
|
|
9
|
+
import { join, resolve } from "node:path";
|
|
10
|
+
import { describe, expect, it } from "vitest";
|
|
11
|
+
|
|
12
|
+
const AGENT_DIR = resolve(import.meta.dirname, "..");
|
|
13
|
+
const BIN = resolve(AGENT_DIR, "../../packages/agent-runtime/bin.mjs");
|
|
14
|
+
/** Inside the escalation hours and inside the example mandate's validity, whatever the day and the shell the suite runs in. */
|
|
15
|
+
const DAYTIME = "2026-09-23T14:00:00-03:00";
|
|
16
|
+
/** The line the terminal prints for a receipt that exists, in the locale these runs are pinned to. */
|
|
17
|
+
const RECEIPT_LINE = /^\s*recibo: .*rcpt_stub_/;
|
|
18
|
+
|
|
19
|
+
interface Payload {
|
|
20
|
+
reply: string;
|
|
21
|
+
executions: Array<{ state: string; escalation: { trigger: string } | null; receipt_ids: string[] }>;
|
|
22
|
+
receipts: string[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function scratch(): Record<string, string> {
|
|
26
|
+
const stateDir = mkdtempSync(join(tmpdir(), "bills-reply-"));
|
|
27
|
+
return { BILLS_STATE_DIR: stateDir, BILLS_RUNS_DIR: join(stateDir, "runs") };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** One `npm start`, in pt-BR and on a pinned clock; `--now` in `args` overrides the clock. */
|
|
31
|
+
function start(args: string[], env: Record<string, string> = scratch()) {
|
|
32
|
+
const result = spawnSync(process.execPath, [BIN, "start", "--locale", "pt-BR", ...args], {
|
|
33
|
+
cwd: AGENT_DIR,
|
|
34
|
+
env: { ...process.env, ANTHROPIC_API_KEY: "", CODESPAR_API_KEY: "", CODESPAR_AGENT_NOW: DAYTIME, ...env },
|
|
35
|
+
encoding: "utf8",
|
|
36
|
+
timeout: 60_000,
|
|
37
|
+
});
|
|
38
|
+
return { code: result.status, stdout: result.stdout, stderr: result.stderr, payload: () => JSON.parse(result.stdout.trim()) as Payload };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const receiptLines = (terminal: string) => terminal.split("\n").filter((line) => RECEIPT_LINE.test(line));
|
|
42
|
+
|
|
43
|
+
describe("npm start -- --input: the replayed reply against what the run did", () => {
|
|
44
|
+
const INPUT = ["--input", "pague a escola de outubro", "--json"];
|
|
45
|
+
|
|
46
|
+
it.each([
|
|
47
|
+
{ name: "a person denied", flags: ["--deny"], state: "denied" },
|
|
48
|
+
{ name: "nobody decided", flags: [], state: "awaiting_approval" },
|
|
49
|
+
])("cites no receipt when $name, and there is none", ({ flags, state }) => {
|
|
50
|
+
const out = start([...INPUT, ...flags]);
|
|
51
|
+
const payload = out.payload();
|
|
52
|
+
expect(payload.executions.map((e) => e.state)).toEqual([state]);
|
|
53
|
+
expect(payload.receipts).toEqual([]);
|
|
54
|
+
expect(payload.reply).toContain("O resultado está no terminal.");
|
|
55
|
+
expect(payload.reply).not.toMatch(/recibo/i);
|
|
56
|
+
expect(receiptLines(out.stderr)).toEqual([]);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("says the same when the payment settled, and the receipt is the terminal's own line", () => {
|
|
60
|
+
const out = start([...INPUT, "--approve"]);
|
|
61
|
+
expect(out.code).toBe(0);
|
|
62
|
+
const payload = out.payload();
|
|
63
|
+
expect(payload.executions.map((e) => e.state)).toEqual(["settled"]);
|
|
64
|
+
expect(payload.receipts).toHaveLength(1);
|
|
65
|
+
expect(payload.reply).toContain("O resultado está no terminal.");
|
|
66
|
+
expect(payload.reply).not.toMatch(/recibo/i);
|
|
67
|
+
// The receipt is named once, by the terminal, on the line that gives its path.
|
|
68
|
+
expect(receiptLines(out.stderr)).toHaveLength(1);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("a payment inside the mandate that the hour sends to a human is not said to be paid", () => {
|
|
72
|
+
// The payee has a settled payment under this mandate first, so what escalates the next one is the hour and not `new_beneficiary`, which is checked before it.
|
|
73
|
+
const env = scratch();
|
|
74
|
+
const seed = start(["--mode", "mandate", "--input", "paga 400 reais pra escola (material)", "--transcript", "test/fixtures/material-400.transcript.jsonl", "--approve", "--json"], env);
|
|
75
|
+
expect(seed.payload().executions[0]).toMatchObject({ state: "settled", escalation: { trigger: "new_beneficiary" } });
|
|
76
|
+
|
|
77
|
+
const night = start(["--mode", "mandate", "--input", "e mais 300 reais pra escola, a excursao", "--transcript", "test/fixtures/excursao-300.transcript.jsonl", "--now", "2026-09-23T23:00:00-03:00", "--json"], env);
|
|
78
|
+
const payload = night.payload();
|
|
79
|
+
expect(payload.executions).toHaveLength(1);
|
|
80
|
+
expect(payload.executions[0]).toMatchObject({ state: "awaiting_approval", escalation: { trigger: "outside_hours" }, receipt_ids: [] });
|
|
81
|
+
expect(payload.reply).not.toMatch(/paguei|recibo/i);
|
|
82
|
+
expect(receiptLines(night.stderr)).toEqual([]);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The request the Anthropic provider actually sends, captured at `fetch`, for
|
|
3
|
+
* one turn in each language (docs/OPEN_QUESTIONS.md §64). The real-model run
|
|
4
|
+
* of 9a5383e answered five English requests out of five in Portuguese, with a
|
|
5
|
+
* `## Language` rule in the system prompt. What these requests show: the
|
|
6
|
+
* system prompt is the file, the person's words arrive untouched, and the
|
|
7
|
+
* last user-role message the model reads before it replies is a tool result
|
|
8
|
+
* full of Portuguese data. So "the language of the person's latest message"
|
|
9
|
+
* was a rule the context argued against on every turn that used a tool. The
|
|
10
|
+
* loop now reads the language of what the person typed and states it in the
|
|
11
|
+
* system prompt of every step of that turn.
|
|
12
|
+
*/
|
|
13
|
+
import { mkdtempSync, readFileSync } from "node:fs";
|
|
14
|
+
import { tmpdir } from "node:os";
|
|
15
|
+
import { join } from "node:path";
|
|
16
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
17
|
+
import { fixedClock, type Execution } from "@codespar/agent-core";
|
|
18
|
+
import { setup, type Setup } from "@codespar/agent-runtime";
|
|
19
|
+
import { agent } from "../src/kit.js";
|
|
20
|
+
|
|
21
|
+
interface SentRequest {
|
|
22
|
+
system: string;
|
|
23
|
+
messages: Array<{ role: string; content: unknown }>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function message(content: unknown[], stop: string) {
|
|
27
|
+
return { id: "msg_test", type: "message", role: "assistant", model: "claude-sonnet-5", content, stop_reason: stop, stop_sequence: null, usage: { input_tokens: 1, output_tokens: 1 } };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** The model's side, scripted: read the bills, then answer. Every request body is kept. */
|
|
31
|
+
function scriptedAnthropic(): SentRequest[] {
|
|
32
|
+
const sent: SentRequest[] = [];
|
|
33
|
+
const answers = [message([{ type: "tool_use", id: "toolu_1", name: "list_bills", input: {} }], "tool_use"), message([{ type: "text", text: "ok" }], "end_turn")];
|
|
34
|
+
vi.stubGlobal("fetch", async (_url: unknown, init?: { body?: unknown }) => {
|
|
35
|
+
sent.push(JSON.parse(String(init?.body)) as SentRequest);
|
|
36
|
+
const body = answers[Math.min(sent.length - 1, answers.length - 1)];
|
|
37
|
+
return new Response(JSON.stringify(body), { status: 200, headers: { "content-type": "application/json" } });
|
|
38
|
+
});
|
|
39
|
+
return sent;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function open(): Setup {
|
|
43
|
+
return setup(agent, {
|
|
44
|
+
mode: "human",
|
|
45
|
+
rail: "stub",
|
|
46
|
+
provider: "anthropic",
|
|
47
|
+
env: { ANTHROPIC_API_KEY: "sk-ant-test-not-a-key" },
|
|
48
|
+
runsDir: mkdtempSync(join(tmpdir(), "bills-lang-runs-")),
|
|
49
|
+
stateDir: mkdtempSync(join(tmpdir(), "bills-lang-state-")),
|
|
50
|
+
now: fixedClock("2026-09-28T14:00:00-03:00"),
|
|
51
|
+
say: () => undefined,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function oneTurn(text: string): Promise<SentRequest[]> {
|
|
56
|
+
const sent = scriptedAnthropic();
|
|
57
|
+
const s = open();
|
|
58
|
+
try {
|
|
59
|
+
const loop = s.makeLoop(s.makeRuntime(), async (e: Execution) => e);
|
|
60
|
+
await loop.turn(text);
|
|
61
|
+
} finally {
|
|
62
|
+
s.close();
|
|
63
|
+
}
|
|
64
|
+
return sent;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const PROMPT = readFileSync(join(agent.dir, "SYSTEM_PROMPT.md"), "utf8");
|
|
68
|
+
|
|
69
|
+
afterEach(() => vi.unstubAllGlobals());
|
|
70
|
+
|
|
71
|
+
describe("the reply language travels in the request, not only in the prompt", () => {
|
|
72
|
+
it("an English turn: every request of the turn states English, and the person's words arrive as typed", async () => {
|
|
73
|
+
const sent = await oneTurn("pay the cleaner for September, please");
|
|
74
|
+
expect(sent).toHaveLength(2);
|
|
75
|
+
for (const request of sent) {
|
|
76
|
+
expect(request.system.startsWith(PROMPT)).toBe(true);
|
|
77
|
+
expect(request.system).toMatch(/wrote their last message in English\. Write your reply in English/);
|
|
78
|
+
expect(request.messages[0]).toEqual({ role: "user", content: "pay the cleaner for September, please" });
|
|
79
|
+
}
|
|
80
|
+
// What the model reads last before it answers: a user-role tool result, in Portuguese.
|
|
81
|
+
const last = sent[1]!.messages.at(-1)!;
|
|
82
|
+
expect(last.role).toBe("user");
|
|
83
|
+
expect(JSON.stringify(last.content)).toContain("mensalidade outubro");
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("a Portuguese turn states Brazilian Portuguese", async () => {
|
|
87
|
+
const sent = await oneTurn("pague a escola de outubro");
|
|
88
|
+
for (const request of sent) expect(request.system).toMatch(/wrote their last message in Brazilian Portuguese\. Write your reply in Brazilian Portuguese/);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("a turn whose language cannot be read adds nothing, and the prompt's own default stands", async () => {
|
|
92
|
+
const sent = await oneTurn("ok");
|
|
93
|
+
for (const request of sent) expect(request.system).toBe(PROMPT);
|
|
94
|
+
});
|
|
95
|
+
});
|