@codespar/cli 0.18.1 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/commands/login.js +52 -12
- package/dist/commands/login.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/surface.js +31 -13
- package/dist/surface.js.map +1 -1
- package/package.json +1 -1
- 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,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The consent is what a person reads before signing a mandate, so its caps
|
|
3
|
+
* are money as a person writes it, not the minor units the API takes.
|
|
4
|
+
*/
|
|
5
|
+
import { describe, expect, it } from "vitest";
|
|
6
|
+
import { STRINGS } from "../src/strings.js";
|
|
7
|
+
|
|
8
|
+
describe("the consent summary says its amounts in reais", () => {
|
|
9
|
+
it("the three caps, in pt-BR and in English", () => {
|
|
10
|
+
expect(STRINGS["pt-BR"].consentCaps(250000, 600000, 7200000)).toBe(" teto por pagamento: R$ 2.500,00 teto do mês: R$ 6.000,00 vitalício: R$ 72.000,00");
|
|
11
|
+
expect(STRINGS.en.consentCaps(250000, 600000, 7200000)).toBe(" cap per payment: R$2,500.00 cap per month: R$6,000.00 lifetime: R$72,000.00");
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("the sandbox credit too", () => {
|
|
15
|
+
expect(STRINGS["pt-BR"].consentFunded(600000, "acc_1", "dep_1")).toBe("Sandbox creditado: R$ 6.000,00 em acc_1 (deposit dep_1).");
|
|
16
|
+
expect(STRINGS.en.consentFunded(600000, "acc_1", "dep_1")).toBe("Sandbox credited: R$6,000.00 to acc_1 (deposit dep_1).");
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("no line of the consent counts in cents", () => {
|
|
20
|
+
for (const locale of ["pt-BR", "en"] as const) {
|
|
21
|
+
const lines = [STRINGS[locale].consentCaps(250000, 600000, 7200000), STRINGS[locale].consentFunded(600000, "acc_1", "dep_1")];
|
|
22
|
+
for (const line of lines) expect(line).not.toMatch(/centavos|cents|250000|600000|7200000/);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
});
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the first real-model runs showed (docs/OPEN_QUESTIONS.md §64): with no
|
|
3
|
+
* date of its own, the model called a bill due next week "venceu dia 05"; told
|
|
4
|
+
* both approval modes exist and not which one ran, it said a payment the
|
|
5
|
+
* titular approved needed "no extra approval". The tools now carry both facts.
|
|
6
|
+
*/
|
|
7
|
+
import { mkdtempSync } from "node:fs";
|
|
8
|
+
import { tmpdir } from "node:os";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { describe, expect, it } from "vitest";
|
|
11
|
+
import { daysUntil, fixedClock, localDate, type Execution, type ToolContext } from "@codespar/agent-core";
|
|
12
|
+
import { setup, type Setup } from "@codespar/agent-runtime";
|
|
13
|
+
import { agent } from "../src/kit.js";
|
|
14
|
+
import { codesparPay, listBills } from "../src/modules/pix-out.js";
|
|
15
|
+
|
|
16
|
+
function open(mode: "human" | "mandate", now: string): Setup {
|
|
17
|
+
return setup(agent, {
|
|
18
|
+
mode,
|
|
19
|
+
rail: "stub",
|
|
20
|
+
provider: "replay",
|
|
21
|
+
runsDir: mkdtempSync(join(tmpdir(), "bills-dates-runs-")),
|
|
22
|
+
stateDir: mkdtempSync(join(tmpdir(), "bills-dates-state-")),
|
|
23
|
+
now: fixedClock(now),
|
|
24
|
+
say: () => undefined,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function context(s: Setup, decide: boolean): ToolContext {
|
|
29
|
+
return {
|
|
30
|
+
engine: s.engine,
|
|
31
|
+
onExecution: async (execution: Execution) => {
|
|
32
|
+
let current = execution;
|
|
33
|
+
if (decide && current.state === "awaiting_approval") current = s.engine.approve(current.id, { id: "usr_demo", channel: "terminal" });
|
|
34
|
+
if (current.state === "approved") current = await s.engine.execute(current.id);
|
|
35
|
+
return current;
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
describe("the calendar the model reads", () => {
|
|
41
|
+
it("localDate is the day in the timezone, not in UTC", () => {
|
|
42
|
+
// 23:30 in Sao Paulo on the 28th is already the 29th in UTC.
|
|
43
|
+
expect(localDate(new Date("2026-09-29T02:30:00Z"), "America/Sao_Paulo")).toBe("2026-09-28");
|
|
44
|
+
expect(localDate(new Date("2026-09-29T02:30:00Z"), "UTC")).toBe("2026-09-29");
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("daysUntil counts whole days, negative once past", () => {
|
|
48
|
+
expect(daysUntil("2026-09-28", "2026-10-05")).toBe(7);
|
|
49
|
+
expect(daysUntil("2026-10-05", "2026-10-05")).toBe(0);
|
|
50
|
+
expect(daysUntil("2026-10-06", "2026-10-05")).toBe(-1);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("list_bills carries today, from the pinned clock, and days_until_due per bill", async () => {
|
|
54
|
+
const s = open("human", "2026-09-28T14:00:00-03:00");
|
|
55
|
+
try {
|
|
56
|
+
const out = (await listBills({}, context(s, false))) as { today: string; bills: Array<{ alias: string; due: string; days_until_due: number }> };
|
|
57
|
+
expect(out.today).toBe("2026-09-28");
|
|
58
|
+
const mercado = out.bills.find((b) => b.alias === "mercado")!;
|
|
59
|
+
expect(mercado.due).toBe("2026-10-05");
|
|
60
|
+
expect(mercado.days_until_due).toBe(7);
|
|
61
|
+
} finally {
|
|
62
|
+
s.close();
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe("codespar_pay says who approved, so the model does not guess", () => {
|
|
68
|
+
const PIX = { action: "pix", items: [{ payee: "mercado", amount_minor: 64000 }] };
|
|
69
|
+
|
|
70
|
+
it("a person's approval is `human`", async () => {
|
|
71
|
+
const s = open("human", "2026-09-28T14:00:00-03:00");
|
|
72
|
+
try {
|
|
73
|
+
expect(await codesparPay(PIX, context(s, true))).toMatchObject({ status: "settled", approved_by: "human" });
|
|
74
|
+
} finally {
|
|
75
|
+
s.close();
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("nobody has approved an execution still waiting: `null`", async () => {
|
|
80
|
+
const s = open("human", "2026-09-28T14:00:00-03:00");
|
|
81
|
+
try {
|
|
82
|
+
expect(await codesparPay(PIX, context(s, false))).toMatchObject({ status: "awaiting_approval", approved_by: null });
|
|
83
|
+
} finally {
|
|
84
|
+
s.close();
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("the signed allowance's approval is `mandate`", async () => {
|
|
89
|
+
const s = open("mandate", "2026-09-28T14:00:00-03:00");
|
|
90
|
+
try {
|
|
91
|
+
// Warm the payee so `new_beneficiary` does not send it to a person.
|
|
92
|
+
await s.kit.warmUp!(s, ["mercado"], { id: "usr_demo", channel: "terminal" });
|
|
93
|
+
expect(await codesparPay(PIX, context(s, false))).toMatchObject({ status: "settled", approved_by: "mandate" });
|
|
94
|
+
} finally {
|
|
95
|
+
s.close();
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `npm run eval` writes a proof bundle per case and per scenario run, dozens a
|
|
3
|
+
* pass. They go to `runs/eval/`, so `runs/` holds what the person ran, and
|
|
4
|
+
* `inspect` and `rerun` still find an eval run by its id.
|
|
5
|
+
*/
|
|
6
|
+
import { spawnSync } from "node:child_process";
|
|
7
|
+
import { mkdtempSync, readdirSync } from "node:fs";
|
|
8
|
+
import { tmpdir } from "node:os";
|
|
9
|
+
import { join, resolve } from "node:path";
|
|
10
|
+
import { beforeAll, 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
|
+
|
|
15
|
+
describe("npm run eval beside a person's own runs", () => {
|
|
16
|
+
const stateDir = mkdtempSync(join(tmpdir(), "bills-eval-runs-"));
|
|
17
|
+
const runsDir = join(stateDir, "runs");
|
|
18
|
+
const run = (command: string, args: string[]) => {
|
|
19
|
+
const result = spawnSync(process.execPath, [BIN, command, ...args], {
|
|
20
|
+
cwd: AGENT_DIR,
|
|
21
|
+
env: { ...process.env, ANTHROPIC_API_KEY: "", CODESPAR_API_KEY: "", BILLS_STATE_DIR: stateDir, BILLS_RUNS_DIR: runsDir },
|
|
22
|
+
encoding: "utf8",
|
|
23
|
+
timeout: 120_000,
|
|
24
|
+
});
|
|
25
|
+
return { code: result.status, stdout: result.stdout, stderr: result.stderr };
|
|
26
|
+
};
|
|
27
|
+
let mine = "";
|
|
28
|
+
let evalRuns: string[] = [];
|
|
29
|
+
|
|
30
|
+
beforeAll(() => {
|
|
31
|
+
const own = run("start", ["--input", "pague a escola de outubro", "--approve", "--json"]);
|
|
32
|
+
mine = (JSON.parse(own.stdout.trim()) as { run_id: string }).run_id;
|
|
33
|
+
expect(run("eval", []).code).toBe(0);
|
|
34
|
+
evalRuns = readdirSync(join(runsDir, "eval")).sort();
|
|
35
|
+
}, 120_000);
|
|
36
|
+
|
|
37
|
+
it("leaves runs/ with the person's run and one folder for the suite's", () => {
|
|
38
|
+
expect(readdirSync(runsDir).sort()).toEqual(["eval", mine].sort());
|
|
39
|
+
// 8 adversarial cases and 11 scenario runs.
|
|
40
|
+
expect(evalRuns).toHaveLength(19);
|
|
41
|
+
expect(evalRuns.some((id) => id.startsWith("run_adv_"))).toBe(true);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("inspect finds an eval run by its id alone, and by eval/<id>", () => {
|
|
45
|
+
const id = evalRuns.find((r) => r.startsWith("run_adv_prompt-injection"))!;
|
|
46
|
+
for (const arg of [id, `eval/${id}`]) {
|
|
47
|
+
const out = run("inspect", [arg, "--json"]);
|
|
48
|
+
expect(out.code).toBe(0);
|
|
49
|
+
expect((JSON.parse(out.stdout.trim()) as { run: { run_id: string } }).run.run_id).toBe(id);
|
|
50
|
+
}
|
|
51
|
+
expect(run("inspect", [mine, "--json"]).code).toBe(0);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("an unknown id lists the person's runs and counts the suite's, without listing them", () => {
|
|
55
|
+
const out = run("inspect", ["run_nope"]);
|
|
56
|
+
expect(out.code).toBe(1);
|
|
57
|
+
expect(out.stderr).toContain(` ${mine}`);
|
|
58
|
+
expect(out.stderr).toContain(`19 more from \`npm run eval\` in ${join(runsDir, "eval")}`);
|
|
59
|
+
expect(out.stderr).not.toContain("run_adv_");
|
|
60
|
+
expect(out.stderr).not.toMatch(/^ {2}eval$/m);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("the folder itself is not a run, and a path out of runs/ is not one either", () => {
|
|
64
|
+
for (const arg of ["eval", "eval/", "eval/../..", "../runs"]) {
|
|
65
|
+
const out = run("inspect", [arg]);
|
|
66
|
+
expect([arg, out.code]).toEqual([arg, 1]);
|
|
67
|
+
expect(out.stderr).toContain(`no proof bundle for run ${arg}`);
|
|
68
|
+
expect(out.stderr).not.toMatch(/^\s+at /m);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("rerun replays an eval run by its id and leaves the rerun beside it, not among the person's", () => {
|
|
73
|
+
const id = evalRuns.find((r) => r.startsWith("run_adv_prompt-injection"))!;
|
|
74
|
+
const out = run("rerun", [id, "--json"]);
|
|
75
|
+
expect(out.code).toBe(0);
|
|
76
|
+
const report = JSON.parse(out.stdout.trim()) as { same_states: boolean; rerun_id: string };
|
|
77
|
+
expect(report.same_states).toBe(true);
|
|
78
|
+
expect(readdirSync(join(runsDir, "eval"))).toContain(report.rerun_id);
|
|
79
|
+
expect(readdirSync(runsDir).sort()).toEqual(["eval", mine].sort());
|
|
80
|
+
});
|
|
81
|
+
});
|
package/templates/bills-agent/agents/bills-agent/test/fixtures/excursao-300.transcript.jsonl
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
{"kind":"assistant_step","tool_calls":[{"id":"tc_4","name":"codespar_pay","input":{"action":"pix","items":[{"payee":"escola","amount_minor":30000,"description":"
|
|
2
|
-
{"kind":"assistant_step","reply":"
|
|
1
|
+
{"kind":"assistant_step","tool_calls":[{"id":"tc_4","name":"codespar_pay","input":{"action":"pix","items":[{"payee":"escola","amount_minor":30000,"description":"excursão"}]}}]}
|
|
2
|
+
{"kind":"assistant_step","reply":"Propus R$ 300,00 para a Escola Aurora (excursão). O resultado está no terminal."}
|
package/templates/bills-agent/agents/bills-agent/test/fixtures/material-400.transcript.jsonl
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
{"kind":"assistant_step","tool_calls":[{"id":"tc_1","name":"codespar_pay","input":{"action":"pix","items":[{"payee":"escola","amount_minor":40000,"description":"material"}]}}]}
|
|
2
|
-
{"kind":"assistant_step","reply":"Propus R$ 400,00 para a Escola Aurora (material). Como
|
|
2
|
+
{"kind":"assistant_step","reply":"Propus R$ 400,00 para a Escola Aurora (material). Como é o primeiro pagamento a esse favorecido, o mandato pediu sua aprovação."}
|
|
@@ -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
|
+
});
|