@codespar/cli 0.18.0 → 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 +79 -9
- 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
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* stock come from this file, not from any warehouse.
|
|
13
13
|
*
|
|
14
14
|
* The customers' documents are valid CPFs (check digits computed): the
|
|
15
|
-
* clearing house validates the payer of a
|
|
15
|
+
* clearing house validates the payer of a cobrança com vencimento. `alias`
|
|
16
16
|
* matches the named entries of the sales policy (`mandate.example.json`); the
|
|
17
17
|
* core resolves it to the document, which the model never sees.
|
|
18
18
|
*/
|
|
@@ -28,15 +28,15 @@ export interface CatalogItem {
|
|
|
28
28
|
service_code: string;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
export const MERCHANT = { name: "
|
|
31
|
+
export const MERCHANT = { name: "Estúdio Tom Maior", city: "São Paulo" } as const;
|
|
32
32
|
|
|
33
33
|
export const CATALOG: CatalogItem[] = [
|
|
34
|
-
{ sku: "aula-avulsa", title: "Aula avulsa de
|
|
35
|
-
{ sku: "pacote-10-aulas", title: "Pacote de 10 aulas de
|
|
36
|
-
{ sku: "avaliacao-inicial", title: "
|
|
34
|
+
{ sku: "aula-avulsa", title: "Aula avulsa de violão (60 min)", category: "aula", price_minor: 10000, cost_minor: 4500, available: true, service_code: "8.02" },
|
|
35
|
+
{ sku: "pacote-10-aulas", title: "Pacote de 10 aulas de violão", category: "aula", price_minor: 39000, cost_minor: 30000, available: true, service_code: "8.02" },
|
|
36
|
+
{ sku: "avaliacao-inicial", title: "Avaliação inicial de nível", category: "avaliacao", price_minor: 8990, cost_minor: 3000, available: true, service_code: "8.02" },
|
|
37
37
|
{ sku: "consultoria-1h", title: "Consultoria de carreira musical (1 h)", category: "consultoria", price_minor: 20000, cost_minor: 9000, available: true, service_code: "17.01" },
|
|
38
38
|
{ sku: "ingresso-recital", title: "Ingresso para o recital de dezembro", category: "ingresso", price_minor: 4500, cost_minor: 1500, available: true, stock: 4, service_code: "12.07" },
|
|
39
|
-
{ sku: "masterclass-producao", title: "Masterclass de
|
|
39
|
+
{ sku: "masterclass-producao", title: "Masterclass de produção musical", category: "masterclass", price_minor: 25000, cost_minor: 10000, available: false, service_code: "8.02" },
|
|
40
40
|
];
|
|
41
41
|
|
|
42
42
|
/** Where the service invoice (NFS-e) is delivered: the borrower's registration at the store. */
|
|
@@ -60,7 +60,7 @@ export interface Customer {
|
|
|
60
60
|
address?: FiscalAddress;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
const SAO_PAULO = { city: "
|
|
63
|
+
const SAO_PAULO = { city: "São Paulo", city_code: "3550308", state: "SP" } as const;
|
|
64
64
|
|
|
65
65
|
export const CUSTOMERS: Customer[] = [
|
|
66
66
|
{ alias: "marina", name: "Marina Costa", document: "27548613008", email: "marina.costa@example.com", address: { street: "Rua Harmonia", number: "120", district: "Vila Madalena", postal_code: "05435000", ...SAO_PAULO } },
|
|
@@ -18,18 +18,21 @@ import { relative } from "node:path";
|
|
|
18
18
|
import qrcode from "qrcode-terminal";
|
|
19
19
|
import {
|
|
20
20
|
CodeSparChargeRail,
|
|
21
|
-
NotATestKeyError,
|
|
22
21
|
StubChargeRail,
|
|
23
22
|
createCodeSparClient,
|
|
24
|
-
|
|
23
|
+
assertTestKey,
|
|
25
24
|
loadMandate,
|
|
26
|
-
|
|
25
|
+
payIfPayable,
|
|
26
|
+
formatBRL,
|
|
27
|
+
formatDay,
|
|
28
|
+
CORE_STRINGS,
|
|
27
29
|
type Execution,
|
|
28
30
|
type StubChargeRailOptions,
|
|
31
|
+
railErrorOf,
|
|
29
32
|
} from "@codespar/agent-core";
|
|
30
33
|
import { defineAgent, envName, type AgentKit, type Setup } from "@codespar/agent-runtime";
|
|
31
|
-
import { formatBRL, formatDate } from "./catalog.js";
|
|
32
34
|
import { checkOrder, loadEnvelope, priceCart, localDate } from "./pricing.js";
|
|
35
|
+
import { STRINGS } from "./strings.js";
|
|
33
36
|
import { claimOrder, CartBook, makeCartHandlers, type Cart } from "./modules/storefront-cart.js";
|
|
34
37
|
import { followCart, makeChargeHandlers, orderProposal } from "./modules/bolepix-receivables.js";
|
|
35
38
|
import { CodeSparInvoiceRail, followSale, InvoiceBook, resumeInvoices, StubInvoiceRail, type InvoiceDeps, type InvoiceRail, type StubIssuerBehaviour } from "./modules/nfse-invoice.js";
|
|
@@ -68,7 +71,7 @@ function invoiceDeps(s: Setup, say: (line: string) => void): InvoiceDeps {
|
|
|
68
71
|
async function placeOrder(s: Setup, customer: string, lines: Array<{ sku: string; quantity: number }>): Promise<Execution> {
|
|
69
72
|
const book = new CartBook(s.store);
|
|
70
73
|
const now = s.engine.clock();
|
|
71
|
-
const priced = priceCart({ lines }, loadEnvelope(s.guardrails), localDate(now, s.guardrails.timezone));
|
|
74
|
+
const priced = priceCart({ lines }, loadEnvelope(s.guardrails), localDate(now, s.guardrails.timezone), s.locale);
|
|
72
75
|
const runId = s.runId;
|
|
73
76
|
const cartId = book.nextId(runId);
|
|
74
77
|
const cart: Cart = { ...priced, cart_id: cartId, ref: `${runId}/${cartId}`, run_id: runId, version: 1, currency: "BRL", order_discount_pct: 0, updated_at: now.toISOString() };
|
|
@@ -87,17 +90,11 @@ const kit: AgentKit = {
|
|
|
87
90
|
labels: {
|
|
88
91
|
defaultUser: "usr_atendente",
|
|
89
92
|
evalUser: "usr_atendente",
|
|
90
|
-
mandateWord: "politica",
|
|
91
|
-
receiptWord: "pedido",
|
|
92
|
-
intro: 'Voce e o cliente. Diga o que quer ("oi, sou a Marina, quero o pacote de dez aulas e uma avaliacao inicial"). Ctrl+D ou "sair" encerra.',
|
|
93
|
-
prompt: "cliente> ",
|
|
94
|
-
approveQuestion: " [atendente] Confirmar este pedido? [s/N] ",
|
|
95
|
-
uncertainDispatch: " desfecho desconhecido no trilho; rode `npm run resume` para reconciliar (nunca repita a emissao)",
|
|
96
93
|
missingReceiptKind: "record_missing_locally",
|
|
97
94
|
missingReceiptDetail: (receiptId, runId) => `paid charge ${receiptId} is not in runs/${runId}/receipts`,
|
|
98
95
|
stillExecuting: (e) => `${e.id}: still executing (${e.reason}) — ${e.detail}; nothing was re-issued; \`npm run poll\` keeps looking`,
|
|
99
|
-
waitingForPayer: (round) => ` aguardando o pagamento... (${round} consultas)`,
|
|
100
96
|
},
|
|
97
|
+
strings: STRINGS,
|
|
101
98
|
|
|
102
99
|
usage: () => `checkout-agent
|
|
103
100
|
npm start interactive terminal (you are the customer; the attendant answers the approval question)
|
|
@@ -109,12 +106,13 @@ const kit: AgentKit = {
|
|
|
109
106
|
npm run poll -- --channel whatsapp --conversation <name> back to a conversation whose payment landed after the run ended
|
|
110
107
|
options: --mode human|mandate --provider anthropic|replay --transcript <file> --rail stub|api --user <id>
|
|
111
108
|
--wait <seconds> --simulate-payer --payer pays|expires|never (stub only) --json
|
|
112
|
-
--now <ISO 8601> pin the run to that instant (service hours, the due date, timestamps); env CODESPAR_AGENT_NOW is the same thing
|
|
109
|
+
--now <ISO 8601> pin the run to that instant (service hours, the due date, timestamps); env CODESPAR_AGENT_NOW is the same thing
|
|
110
|
+
--locale pt-BR|en the language of what the code prints, WhatsApp templates included (the model answers in the language the customer types either way)`,
|
|
113
111
|
|
|
114
112
|
buildRail: (ctx) => {
|
|
115
113
|
const mandate = ctx.mandate ?? loadMandate(ctx.manifest.resolvePath(ctx.manifest.manifest.mandate_schema));
|
|
116
114
|
if (ctx.kind === "api") {
|
|
117
|
-
|
|
115
|
+
assertTestKey(ctx.env["CODESPAR_API_KEY"]);
|
|
118
116
|
const client = createCodeSparClient({ apiKey: ctx.env["CODESPAR_API_KEY"], baseUrl: ctx.env["CODESPAR_API_URL"], projectId: ctx.env["CODESPAR_PROJECT_ID"] });
|
|
119
117
|
return {
|
|
120
118
|
rail: new CodeSparChargeRail(client),
|
|
@@ -124,8 +122,8 @@ options: --mode human|mandate --provider anthropic|replay --transcript <file>
|
|
|
124
122
|
payer: {
|
|
125
123
|
kind: "api" as const,
|
|
126
124
|
async pay(chargeId: string) {
|
|
127
|
-
const result = await
|
|
128
|
-
if (!result.ok) return { ok: false as const, detail: `${result.failure.code}: ${result.failure.message}` };
|
|
125
|
+
const result = await payIfPayable(client, chargeId);
|
|
126
|
+
if (!result.ok) return { ok: false as const, detail: "refused" in result ? `${result.refused.code}: ${result.refused.message}` : `${result.failure.code}: ${result.failure.message}` };
|
|
129
127
|
const s = result.state;
|
|
130
128
|
return { ok: true as const, detail: `sandbox payer: ${s.charge_id} ${s.status} (${s.payment}, ${s.paid_minor} of ${s.quoted_minor}), simulated=${s.simulated}, settled_against=${s.settled_against}, money_moved=${s.money_moved}${s.idempotent_replay ? ", replay" : ""}` };
|
|
131
129
|
},
|
|
@@ -161,37 +159,40 @@ options: --mode human|mandate --provider anthropic|replay --transcript <file>
|
|
|
161
159
|
const envelope = loadEnvelope(setup.guardrails);
|
|
162
160
|
const book = new CartBook(setup.store);
|
|
163
161
|
// On a channel that binds a conversation, the customer is the one it is bound to: read at call time, because the channel binds after setup.
|
|
164
|
-
const orderDeps = { book, runId: setup.runId, timezone: setup.guardrails.timezone, clock: setup.engine.clock, boundCustomer: () => setup.conversation?.subject };
|
|
162
|
+
const orderDeps = { book, runId: setup.runId, timezone: setup.guardrails.timezone, clock: setup.engine.clock, boundCustomer: () => setup.conversation?.subject, locale: () => setup.locale };
|
|
165
163
|
return {
|
|
166
164
|
...makeCartHandlers({ ...orderDeps, envelope, onReplaced: (cart, engine) => void followCart(cart, engine, orderDeps) }),
|
|
167
165
|
...makeChargeHandlers(orderDeps),
|
|
168
166
|
};
|
|
169
167
|
},
|
|
170
168
|
|
|
171
|
-
policyExtension: ({ guardrails, store }) => {
|
|
169
|
+
policyExtension: ({ guardrails, store, locale }) => {
|
|
172
170
|
const envelope = loadEnvelope(guardrails);
|
|
173
171
|
const book = new CartBook(store);
|
|
174
|
-
return (execution, ctx) => checkOrder(execution, execution.composition ? book.get(execution.composition.ref) : undefined, envelope, ctx.now, ctx.guardrails.timezone);
|
|
172
|
+
return (execution, ctx) => checkOrder(execution, execution.composition ? book.get(execution.composition.ref) : undefined, envelope, ctx.now, ctx.guardrails.timezone, locale());
|
|
175
173
|
},
|
|
176
174
|
|
|
177
175
|
describeExecution: (execution, setup) => {
|
|
176
|
+
const text = setup.coreStrings;
|
|
177
|
+
const words = STRINGS[setup.locale];
|
|
178
|
+
const money = (minor: number) => formatBRL(minor, setup.locale);
|
|
178
179
|
const lines: string[] = [];
|
|
179
180
|
const cart = cartOf(setup, execution);
|
|
180
|
-
lines.push(`
|
|
181
|
-
lines.push(`
|
|
182
|
-
for (const l of cart?.line_items ?? []) lines.push(` - ${l.quantity}x ${l.name}: ${
|
|
183
|
-
for (const d of cart?.order_discounts ?? []) lines.push(` - ${d.kind === "coupon" ?
|
|
184
|
-
lines.push(`
|
|
185
|
-
if (execution.composition) lines.push(` cart_hash ${execution.composition.composition_hash.slice(0, 19)}… (${execution.composition.line_count}
|
|
186
|
-
if (execution.escalation) lines.push(`
|
|
187
|
-
if (execution.blocking_reasons.length) lines.push(`
|
|
181
|
+
lines.push(` ${words.order} ${execution.id}: ${execution.state}${execution.reason ? ` (${execution.reason})` : ""}`);
|
|
182
|
+
lines.push(` ${words.customerLine(execution.items[0]?.beneficiary ?? "?", cart ? `${cart.cart_id} v${cart.version}` : undefined)}`);
|
|
183
|
+
for (const l of cart?.line_items ?? []) lines.push(` - ${l.quantity}x ${l.name}: ${money(l.totals.find((t) => t.type === "total")!.amount)}${l.discount_pct ? words.lineDiscount(l.discount_pct) : ""}`);
|
|
184
|
+
for (const d of cart?.order_discounts ?? []) lines.push(` - ${d.kind === "coupon" ? words.coupon(d.ref.replace("coupon:", "")) : words.orderDiscount}: ${money(-d.amount)}`);
|
|
185
|
+
lines.push(` ${text.totalByCore}: ${money(execution.total)}${execution.items[0]?.due_date ? text.dueOn(formatDay(execution.items[0].due_date, setup.locale)) : ""}`);
|
|
186
|
+
if (execution.composition) lines.push(` cart_hash ${execution.composition.composition_hash.slice(0, 19)}… (${words.cartLines(execution.composition.line_count)})`);
|
|
187
|
+
if (execution.escalation) lines.push(` ${text.escalatedBy}: ${execution.escalation.trigger} — ${execution.escalation.detail}`);
|
|
188
|
+
if (execution.blocking_reasons.length) lines.push(` ${text.blocked(execution.blocking_reasons.join(", "), words.notAuthorized)}`);
|
|
188
189
|
if (execution.detail && execution.state !== "awaiting_approval") lines.push(` ${execution.detail}`);
|
|
189
190
|
for (const outcome of execution.outcomes) {
|
|
190
|
-
if (outcome.transaction_id) lines.push(`
|
|
191
|
-
if (outcome.receipt_id) lines.push(`
|
|
191
|
+
if (outcome.transaction_id) lines.push(` ${words.charge}: ${outcome.transaction_id} — ${outcome.status}${outcome.code ? ` (${outcome.code})` : ""}`);
|
|
192
|
+
if (outcome.receipt_id) lines.push(` ${words.paidOrder}: ${relative(process.cwd(), `${setup.bundle.dir}/receipts/${outcome.receipt_id}.json`)}`);
|
|
192
193
|
}
|
|
193
194
|
const invoice = new InvoiceBook(setup.store).of(execution.id);
|
|
194
|
-
if (invoice) lines.push(` NFS-e ${invoice.id}: ${invoice.state}${invoice.reason ? ` (${invoice.reason}, ${invoice.code})` : ""}${invoice.document ?
|
|
195
|
+
if (invoice) lines.push(` NFS-e ${invoice.id}: ${invoice.state}${invoice.reason ? ` (${invoice.reason}, ${invoice.code})` : ""}${invoice.document ? words.invoiceDocument(invoice.document.id) : ""}`);
|
|
195
196
|
return lines;
|
|
196
197
|
},
|
|
197
198
|
|
|
@@ -214,6 +215,7 @@ options: --mode human|mandate --provider anthropic|replay --transcript <file>
|
|
|
214
215
|
id: e.id,
|
|
215
216
|
state: e.state,
|
|
216
217
|
reason: e.reason ?? null,
|
|
218
|
+
rail_error: railErrorOf(e),
|
|
217
219
|
escalation: e.escalation ?? null,
|
|
218
220
|
cart_id: cart?.cart_id ?? null,
|
|
219
221
|
cart_hash: e.composition?.composition_hash ?? null,
|
|
@@ -234,18 +236,19 @@ options: --mode human|mandate --provider anthropic|replay --transcript <file>
|
|
|
234
236
|
},
|
|
235
237
|
|
|
236
238
|
/** What the customer reads when the charge is payable: the QR as an image, the copy-and-paste under it, the bank line if any. */
|
|
237
|
-
presentInstrument: (execution, _instalment, chargeId, instrument, tell) => {
|
|
239
|
+
presentInstrument: (execution, _instalment, chargeId, instrument, tell, locale) => {
|
|
240
|
+
const text = CORE_STRINGS[locale];
|
|
238
241
|
tell("");
|
|
239
|
-
tell(
|
|
242
|
+
tell(`${STRINGS[locale].orderOf(formatBRL(execution.total, locale))}${instrument.due_date ? text.dueOn(formatDay(instrument.due_date, locale)) : ""}${text.chargeRef(chargeId)}`);
|
|
240
243
|
if (instrument.pix_copy_paste) {
|
|
241
244
|
qrcode.generate(instrument.pix_copy_paste, { small: true }, (qr: string) => {
|
|
242
245
|
for (const line of qr.split("\n")) tell(line);
|
|
243
246
|
});
|
|
244
|
-
tell(
|
|
247
|
+
tell(text.pixCopyPaste);
|
|
245
248
|
tell(instrument.pix_copy_paste);
|
|
246
249
|
}
|
|
247
250
|
if (instrument.boleto_bank_line) {
|
|
248
|
-
tell(
|
|
251
|
+
tell(text.boletoLine);
|
|
249
252
|
tell(instrument.boleto_bank_line);
|
|
250
253
|
}
|
|
251
254
|
tell("");
|
|
@@ -255,14 +258,15 @@ options: --mode human|mandate --provider anthropic|replay --transcript <file>
|
|
|
255
258
|
announceOutcome: (execution, setup, tell) => {
|
|
256
259
|
if (!["settled", "failed", "denied", "expired"].includes(execution.state)) return false;
|
|
257
260
|
if (!setup.engine.markTold(execution.id, execution.state)) return false;
|
|
261
|
+
const words = STRINGS[setup.locale];
|
|
258
262
|
let text: string;
|
|
259
|
-
if (execution.state === "settled") text =
|
|
260
|
-
else if (execution.reason === "charge_expired") text =
|
|
261
|
-
else if (execution.reason === "charge_cancelled") text =
|
|
262
|
-
else if (execution.reason === "charge_reference_ambiguous") text =
|
|
263
|
-
else if (execution.state === "failed") text =
|
|
264
|
-
else if (execution.state === "denied") text =
|
|
265
|
-
else text =
|
|
263
|
+
if (execution.state === "settled") text = words.toldSettled(execution.outcomes.map((o) => o.transaction_id).filter(Boolean).join(", "));
|
|
264
|
+
else if (execution.reason === "charge_expired") text = words.toldExpired;
|
|
265
|
+
else if (execution.reason === "charge_cancelled") text = words.toldCancelled;
|
|
266
|
+
else if (execution.reason === "charge_reference_ambiguous") text = words.toldAmbiguous;
|
|
267
|
+
else if (execution.state === "failed") text = words.toldFailed(execution.reason);
|
|
268
|
+
else if (execution.state === "denied") text = words.toldDenied(execution.reason);
|
|
269
|
+
else text = words.toldUndecided(execution.reason ?? execution.state);
|
|
266
270
|
tell(text);
|
|
267
271
|
setup.engine.note("message.debtor", execution.id, { state: execution.state, reason: execution.reason ?? null, text });
|
|
268
272
|
return true;
|
|
@@ -284,8 +288,8 @@ options: --mode human|mandate --provider anthropic|replay --transcript <file>
|
|
|
284
288
|
* is answered inside the turn that produced it, so it has no template, and
|
|
285
289
|
* the poll reports it rather than sending approximate copy.
|
|
286
290
|
*/
|
|
287
|
-
outcomeTemplate: (execution) => {
|
|
288
|
-
const total = formatBRL(execution.total);
|
|
291
|
+
outcomeTemplate: (execution, locale) => {
|
|
292
|
+
const total = formatBRL(execution.total, locale);
|
|
289
293
|
if (execution.state === "settled") return { template: "pedido_confirmado", variables: [total] };
|
|
290
294
|
if (execution.reason === "charge_expired") return { template: "pedido_cobranca_vencida", variables: [total] };
|
|
291
295
|
if (execution.reason === "charge_cancelled") return { template: "pedido_cobranca_cancelada", variables: [total] };
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Module `bolepix-receivables`, the sales version: the `codespar_charge`
|
|
3
3
|
* handler. A copy of the collections-agent's module in its bones (agents do
|
|
4
4
|
* not import each other's modules, OPEN_QUESTIONS §39f) and different in what
|
|
5
|
-
* it charges: an ORDER, one
|
|
5
|
+
* it charges: an ORDER, one cobrança com vencimento whose amount is the
|
|
6
6
|
* cart's total as the code priced it, due today (checkout decision 1).
|
|
7
7
|
*
|
|
8
8
|
* Three actions, because ordering and issuing are two moments of a sale:
|
|
@@ -22,10 +22,11 @@
|
|
|
22
22
|
* No input carries an amount. `total_minor` is recorded and, with
|
|
23
23
|
* `model_total_mismatch: refuse`, refuses a total the model got wrong.
|
|
24
24
|
*/
|
|
25
|
-
import type { Execution, ExecutionEngine, Proposal, ToolHandler } from "@codespar/agent-core";
|
|
25
|
+
import type { Execution, ExecutionEngine, Locale, Proposal, ToolHandler } from "@codespar/agent-core";
|
|
26
26
|
import { MERCHANT, formatBRL, formatDate } from "../catalog.js";
|
|
27
27
|
import { localDate } from "../pricing.js";
|
|
28
28
|
import { claimOrder, currentCart, orderOf, resolveCart, type Cart, type CartBook } from "./storefront-cart.js";
|
|
29
|
+
import { STRINGS } from "../strings.js";
|
|
29
30
|
|
|
30
31
|
interface ChargeInput {
|
|
31
32
|
action?: unknown;
|
|
@@ -43,6 +44,8 @@ export interface OrderDeps {
|
|
|
43
44
|
clock: () => Date;
|
|
44
45
|
/** The customer a channel's conversation is bound to, when one is: an order in this conversation is theirs. */
|
|
45
46
|
boundCustomer?: () => string | undefined;
|
|
47
|
+
/** The run's locale, read at call time: an order's status message is worded in it. Default pt-BR. */
|
|
48
|
+
locale?: () => Locale;
|
|
46
49
|
}
|
|
47
50
|
|
|
48
51
|
const OPEN = new Set(["awaiting_approval", "approved"]);
|
|
@@ -74,6 +77,7 @@ export function followCart(cart: Cart, engine: ExecutionEngine, deps: Pick<Order
|
|
|
74
77
|
}
|
|
75
78
|
|
|
76
79
|
export function makeChargeHandlers(deps: OrderDeps): Record<string, ToolHandler> {
|
|
80
|
+
const text = () => STRINGS[deps.locale?.() ?? "pt-BR"];
|
|
77
81
|
const findOrder = (engine: ExecutionEngine, input: ChargeInput): { order: Execution | undefined; cart: Cart | undefined } => {
|
|
78
82
|
if (typeof input.execution_id === "string" && input.execution_id) {
|
|
79
83
|
const order = engine.get(input.execution_id);
|
|
@@ -91,14 +95,14 @@ export function makeChargeHandlers(deps: OrderDeps): Record<string, ToolHandler>
|
|
|
91
95
|
|
|
92
96
|
if (action === "status") {
|
|
93
97
|
const { order, cart } = findOrder(ctx.engine, input);
|
|
94
|
-
if (!order) return { found: false, message: cart ?
|
|
98
|
+
if (!order) return { found: false, message: cart ? text().noOrderForCart(cart.cart_id) : text().noOrder };
|
|
95
99
|
return { found: true, ...describe(order, cart) };
|
|
96
100
|
}
|
|
97
101
|
|
|
98
102
|
if (action === "issue") {
|
|
99
103
|
const { order, cart } = findOrder(ctx.engine, input);
|
|
100
104
|
if (!order) throw new Error("codespar_charge: no order to issue; create the order from the cart first (action=create)");
|
|
101
|
-
if (order.state !== "approved") return { ...describe(order, cart), message: messageFor(order) };
|
|
105
|
+
if (order.state !== "approved") return { ...describe(order, cart), message: messageFor(order, text()) };
|
|
102
106
|
// The cart may have moved since the order was approved; the order follows it, and the last gate compares.
|
|
103
107
|
if (cart) followCart(cart, ctx.engine, deps);
|
|
104
108
|
const executed = await ctx.engine.execute(order.id);
|
|
@@ -123,30 +127,34 @@ export function makeChargeHandlers(deps: OrderDeps): Record<string, ToolHandler>
|
|
|
123
127
|
if (existing && (OPEN.has(existing.state) || existing.state === "executing" || existing.state === "settled")) {
|
|
124
128
|
if (OPEN.has(existing.state)) followCart(cart, ctx.engine, deps);
|
|
125
129
|
const current = ctx.engine.get(existing.id)!;
|
|
126
|
-
return { ...describe(current, cart), message:
|
|
130
|
+
return { ...describe(current, cart), message: text().alreadyOrdered(current.id) };
|
|
127
131
|
}
|
|
128
132
|
|
|
129
133
|
const claimed = typeof input.total_minor === "number" ? input.total_minor : undefined;
|
|
130
134
|
const draft = await ctx.engine.draft(orderProposal(cart, customer, deps, claimed));
|
|
131
|
-
if (!draft.ok)
|
|
135
|
+
if (!draft.ok) {
|
|
136
|
+
// Refused before a draft: no execution will ever say so, and the run's count is taken from this.
|
|
137
|
+
ctx.onNotRun?.({ ref: cart.cart_id, why: "refused", detail: draft.reason });
|
|
138
|
+
return { status: "refused", reason: draft.reason, message: draft.message, issued: false, paid: false };
|
|
139
|
+
}
|
|
132
140
|
claimOrder(ctx.engine, cart, draft.execution.id);
|
|
133
141
|
const decided = await ctx.onExecution(draft.execution);
|
|
134
|
-
return { ...describe(decided, cart), message: messageFor(decided) };
|
|
142
|
+
return { ...describe(decided, cart), message: messageFor(decided, text()) };
|
|
135
143
|
};
|
|
136
144
|
|
|
137
145
|
return { codespar_charge: codesparCharge };
|
|
138
146
|
}
|
|
139
147
|
|
|
140
|
-
function messageFor(order: Execution): string {
|
|
148
|
+
function messageFor(order: Execution, text: (typeof STRINGS)[Locale]): string {
|
|
141
149
|
switch (order.state) {
|
|
142
150
|
case "approved":
|
|
143
|
-
return
|
|
151
|
+
return text.orderApproved;
|
|
144
152
|
case "awaiting_approval":
|
|
145
|
-
return order.reason === "items_hash_mismatch" ?
|
|
153
|
+
return order.reason === "items_hash_mismatch" ? text.orderCartChanged : text.orderAwaitingAttendant;
|
|
146
154
|
case "executing":
|
|
147
|
-
return order.reason === "awaiting_settlement" ?
|
|
155
|
+
return order.reason === "awaiting_settlement" ? text.orderIssued : text.orderUncertain;
|
|
148
156
|
case "settled":
|
|
149
|
-
return
|
|
157
|
+
return text.orderPaid;
|
|
150
158
|
default:
|
|
151
159
|
return `${order.state}${order.reason ? ` (${order.reason})` : ""}`;
|
|
152
160
|
}
|
|
@@ -178,7 +178,7 @@ export class StubInvoiceRail implements InvoiceRail {
|
|
|
178
178
|
return { status: "unsent", code: "no_eligible_providers", message: "stub: routing found no issuer this time; nothing was sent" };
|
|
179
179
|
}
|
|
180
180
|
if (behaviour === "refuses" || (behaviour === undefined && !request.recipient.address)) {
|
|
181
|
-
return { status: "refused", code: "E0101", message: "stub issuer: tomador sem
|
|
181
|
+
return { status: "refused", code: "E0101", message: "stub issuer: tomador sem endereço; a NFS-e exige o endereço do tomador" };
|
|
182
182
|
}
|
|
183
183
|
// What the issuer did is recorded before the answer is lost, as a real one would have.
|
|
184
184
|
const documentId = `nfse_stub_${key.slice(-16)}`;
|
|
@@ -248,7 +248,7 @@ export function nfseRequest(sale: Execution, cart: Cart, customer: Customer): Nf
|
|
|
248
248
|
description: `${MERCHANT.name} - pedido ${cart.cart_id}: ${cart.line_items.map((l) => `${l.quantity}x ${l.name}`).join("; ")}`,
|
|
249
249
|
// What was PAID, discounts included; the transform would otherwise sum list prices.
|
|
250
250
|
servicesAmount: sale.total / 100,
|
|
251
|
-
additionalInformation: `
|
|
251
|
+
additionalInformation: `cobrança ${chargeId}, ${formatBRL(sale.total)}`,
|
|
252
252
|
},
|
|
253
253
|
};
|
|
254
254
|
}
|
|
@@ -342,8 +342,8 @@ export async function dispatchInvoice(record: InvoiceRecord, deps: InvoiceDeps):
|
|
|
342
342
|
function notify(record: InvoiceRecord, deps: InvoiceDeps): InvoiceRecord {
|
|
343
343
|
const text =
|
|
344
344
|
record.reason === "invoice_uncertain"
|
|
345
|
-
? `NFS-e do pedido ${record.sale_execution_id} (
|
|
346
|
-
: `NFS-e do pedido ${record.sale_execution_id} (
|
|
345
|
+
? `NFS-e do pedido ${record.sale_execution_id} (cobrança ${record.charge_id}) com resultado INCERTO (${record.code}): pode ter sido emitida. Não reemita; confira no emissor. A venda continua paga.`
|
|
346
|
+
: `NFS-e do pedido ${record.sale_execution_id} (cobrança ${record.charge_id}) falhou (${record.reason}, ${record.code}): ${record.detail}. A venda continua paga.`;
|
|
347
347
|
deps.say(` [atendente] ${text}`);
|
|
348
348
|
deps.engine.note("message.attendant", record.sale_execution_id, { invoice_id: record.id, state: record.state, reason: record.reason ?? null, code: record.code ?? null, text });
|
|
349
349
|
return record;
|
|
@@ -18,9 +18,10 @@
|
|
|
18
18
|
* execution carries (`<run_id>/cart-1`) is unique across runs, so an order
|
|
19
19
|
* approved from another process (`npm run approve`) finds its cart.
|
|
20
20
|
*/
|
|
21
|
-
import type { ExecutionEngine, StateStore, ToolHandler } from "@codespar/agent-core";
|
|
21
|
+
import type { ExecutionEngine, Locale, StateStore, ToolHandler } from "@codespar/agent-core";
|
|
22
22
|
import { CATALOG, MERCHANT, formatBRL } from "../catalog.js";
|
|
23
23
|
import { localDate, priceCart, type Envelope, type PricedCart, type ValidationIssue } from "../pricing.js";
|
|
24
|
+
import { STRINGS } from "../strings.js";
|
|
24
25
|
|
|
25
26
|
export interface Cart extends PricedCart {
|
|
26
27
|
cart_id: string;
|
|
@@ -137,6 +138,8 @@ export interface CartDeps {
|
|
|
137
138
|
runId: string;
|
|
138
139
|
timezone: string;
|
|
139
140
|
clock: () => Date;
|
|
141
|
+
/** The run's locale, read at call time: the cart's issues and totals are worded in it. Default pt-BR. */
|
|
142
|
+
locale?: () => Locale;
|
|
140
143
|
/** Called after a replacement, with the cart as it is now: an open order follows it (`bolepix-receivables`). */
|
|
141
144
|
onReplaced(cart: Cart, engine: ExecutionEngine): void;
|
|
142
145
|
}
|
|
@@ -169,16 +172,16 @@ export function makeCartHandlers(deps: CartDeps): Record<string, ToolHandler> {
|
|
|
169
172
|
})),
|
|
170
173
|
policy: {
|
|
171
174
|
service_hours: deps.envelope.service_hours,
|
|
172
|
-
payment: "bolepix (
|
|
173
|
-
discounts: "
|
|
174
|
-
prices: "sempre os do
|
|
175
|
+
payment: "bolepix (cobrança com vencimento): paga por Pix ou por boleto, vence hoje",
|
|
176
|
+
discounts: "só dentro da política da loja, aplicada pelo código; o que estiver fora é recusado. Cupom: só os da tabela da loja, informados pelo cliente.",
|
|
177
|
+
prices: "sempre os do catálogo; nenhuma ferramenta aceita preço",
|
|
175
178
|
},
|
|
176
179
|
});
|
|
177
180
|
|
|
178
181
|
const cartView: ToolHandler = async (raw, ctx) => {
|
|
179
182
|
const input = raw as { cart_id?: unknown };
|
|
180
183
|
const cart = resolveCart(ctx.engine, deps, input.cart_id);
|
|
181
|
-
if (!cart) return { cart: null, message:
|
|
184
|
+
if (!cart) return { cart: null, message: STRINGS[deps.locale?.() ?? "pt-BR"].noCart };
|
|
182
185
|
return viewOf(ctx.engine, cart);
|
|
183
186
|
};
|
|
184
187
|
|
|
@@ -191,7 +194,7 @@ export function makeCartHandlers(deps: CartDeps): Record<string, ToolHandler> {
|
|
|
191
194
|
} else target = currentCart(ctx.engine, deps);
|
|
192
195
|
|
|
193
196
|
const now = deps.clock();
|
|
194
|
-
const priced = priceCart({ lines: input.lines, coupon: input.coupon, order_discount_pct: input.order_discount_pct }, deps.envelope, localDate(now, deps.timezone));
|
|
197
|
+
const priced = priceCart({ lines: input.lines, coupon: input.coupon, order_discount_pct: input.order_discount_pct }, deps.envelope, localDate(now, deps.timezone), deps.locale?.());
|
|
195
198
|
const cartId = target?.cart_id ?? deps.book.nextId(deps.runId);
|
|
196
199
|
const cart: Cart = {
|
|
197
200
|
...priced,
|
|
@@ -13,8 +13,9 @@
|
|
|
13
13
|
* `guardrails.json` under `envelope`, and every rule of it can only refuse.
|
|
14
14
|
*/
|
|
15
15
|
import { z } from "zod";
|
|
16
|
-
import { compositionHash, isOutsideHours, localClock, type CompositionLine, type Execution, type ExecutionReason, type Guardrails } from "@codespar/agent-core";
|
|
17
|
-
import { catalogItem
|
|
16
|
+
import { compositionHash, formatBRL, isOutsideHours, localClock, type CompositionLine, type Execution, type ExecutionReason, type Guardrails, type Locale } from "@codespar/agent-core";
|
|
17
|
+
import { catalogItem } from "./catalog.js";
|
|
18
|
+
import { STRINGS } from "./strings.js";
|
|
18
19
|
|
|
19
20
|
const HOURS = /^([01]\d|2[0-3]):[0-5]\d-([01]\d|2[0-3]):[0-5]\d$/;
|
|
20
21
|
|
|
@@ -131,7 +132,8 @@ export interface CartInput {
|
|
|
131
132
|
* priced from the catalog. A coupon that does not exist, or does not apply,
|
|
132
133
|
* is named and not applied, and nothing "equivalent" is applied in its place.
|
|
133
134
|
*/
|
|
134
|
-
export function priceCart(input: CartInput, envelope: Envelope, today: string): PricedCart {
|
|
135
|
+
export function priceCart(input: CartInput, envelope: Envelope, today: string, locale: Locale = "pt-BR"): PricedCart {
|
|
136
|
+
const text = STRINGS[locale];
|
|
135
137
|
const issues: ValidationIssue[] = [];
|
|
136
138
|
const lines: PricedLine[] = [];
|
|
137
139
|
const raw = Array.isArray(input.lines) ? input.lines : [];
|
|
@@ -143,30 +145,30 @@ export function priceCart(input: CartInput, envelope: Envelope, today: string):
|
|
|
143
145
|
const line = (entry ?? {}) as Record<string, unknown>;
|
|
144
146
|
const priced = PRICE_FIELDS.find((f) => f in line);
|
|
145
147
|
if (priced) {
|
|
146
|
-
issues.push({ code: "price_not_caller_input", field: `${field}.${priced}`, message:
|
|
148
|
+
issues.push({ code: "price_not_caller_input", field: `${field}.${priced}`, message: text.issuePriceNotInput });
|
|
147
149
|
continue;
|
|
148
150
|
}
|
|
149
151
|
const sku = typeof line["sku"] === "string" ? line["sku"].trim().toLowerCase() : "";
|
|
150
152
|
const item = sku ? catalogItem(sku) : undefined;
|
|
151
153
|
if (!item) {
|
|
152
|
-
issues.push({ code: "sku_unknown", field: `${field}.sku`, message:
|
|
154
|
+
issues.push({ code: "sku_unknown", field: `${field}.sku`, message: text.issueSkuUnknown(sku) });
|
|
153
155
|
continue;
|
|
154
156
|
}
|
|
155
157
|
if (!item.available) {
|
|
156
|
-
issues.push({ code: "item_unavailable", field: `${field}.sku`, message:
|
|
158
|
+
issues.push({ code: "item_unavailable", field: `${field}.sku`, message: text.issueUnavailable(item.title) });
|
|
157
159
|
continue;
|
|
158
160
|
}
|
|
159
161
|
const quantity = line["quantity"];
|
|
160
162
|
if (typeof quantity !== "number" || !Number.isInteger(quantity) || quantity <= 0 || quantity > envelope.max_units_per_line) {
|
|
161
|
-
issues.push({ code: "quantity_invalid", field: `${field}.quantity`, message:
|
|
163
|
+
issues.push({ code: "quantity_invalid", field: `${field}.quantity`, message: text.issueQuantityInvalid(envelope.max_units_per_line) });
|
|
162
164
|
continue;
|
|
163
165
|
}
|
|
164
166
|
if (seen.has(item.sku)) {
|
|
165
|
-
issues.push({ code: "quantity_invalid", field: `${field}.sku`, message:
|
|
167
|
+
issues.push({ code: "quantity_invalid", field: `${field}.sku`, message: text.issueDuplicateSku(item.sku) });
|
|
166
168
|
continue;
|
|
167
169
|
}
|
|
168
170
|
if (item.stock !== undefined && quantity > item.stock) {
|
|
169
|
-
issues.push({ code: "quantity_above_stock", field: `${field}.quantity`, message:
|
|
171
|
+
issues.push({ code: "quantity_above_stock", field: `${field}.quantity`, message: text.issueAboveStock(item.stock, item.title) });
|
|
170
172
|
continue;
|
|
171
173
|
}
|
|
172
174
|
const discount = line["discount_pct"] ?? 0;
|
|
@@ -184,9 +186,9 @@ export function priceCart(input: CartInput, envelope: Envelope, today: string):
|
|
|
184
186
|
discount_pct: discount,
|
|
185
187
|
availability_status: item.stock !== undefined && item.stock - quantity <= 1 ? "low_stock" : "in_stock",
|
|
186
188
|
totals: [
|
|
187
|
-
{ type: "items_base_amount", display_text:
|
|
188
|
-
{ type: "items_discount", display_text:
|
|
189
|
-
{ type: "total", display_text:
|
|
189
|
+
{ type: "items_base_amount", display_text: text.lineValue, amount: base },
|
|
190
|
+
{ type: "items_discount", display_text: text.lineDiscountTotal, amount: -off },
|
|
191
|
+
{ type: "total", display_text: text.lineTotal, amount: base - off },
|
|
190
192
|
],
|
|
191
193
|
});
|
|
192
194
|
}
|
|
@@ -198,9 +200,9 @@ export function priceCart(input: CartInput, envelope: Envelope, today: string):
|
|
|
198
200
|
if (typeof input.coupon !== "string") throw new Error("coupon must be a string");
|
|
199
201
|
const code = input.coupon.trim().toUpperCase();
|
|
200
202
|
const found = envelope.coupons.find((c) => c.code === code);
|
|
201
|
-
if (!found) issues.push({ code: "coupon_unknown", field: "coupon", message:
|
|
202
|
-
else if (found.expires_at < today) issues.push({ code: "coupon_not_applicable", field: "coupon", message:
|
|
203
|
-
else if (subtotal < found.min_order_minor) issues.push({ code: "coupon_not_applicable", field: "coupon", message:
|
|
203
|
+
if (!found) issues.push({ code: "coupon_unknown", field: "coupon", message: text.issueCouponUnknown(code) });
|
|
204
|
+
else if (found.expires_at < today) issues.push({ code: "coupon_not_applicable", field: "coupon", message: text.issueCouponExpired(code) });
|
|
205
|
+
else if (subtotal < found.min_order_minor) issues.push({ code: "coupon_not_applicable", field: "coupon", message: text.issueCouponMinimum(code, formatBRL(found.min_order_minor, locale)) });
|
|
204
206
|
else {
|
|
205
207
|
coupon = code;
|
|
206
208
|
orderDiscounts.push({ kind: "coupon", ref: `coupon:${code}`, pct: found.discount_pct, amount: Math.round((subtotal * found.discount_pct) / 100) });
|
|
@@ -224,11 +226,11 @@ export function priceCart(input: CartInput, envelope: Envelope, today: string):
|
|
|
224
226
|
coupon,
|
|
225
227
|
order_discounts: orderDiscounts,
|
|
226
228
|
totals: [
|
|
227
|
-
{ type: "items_base_amount", display_text:
|
|
228
|
-
{ type: "items_discount", display_text:
|
|
229
|
-
{ type: "subtotal", display_text:
|
|
230
|
-
{ type: "discount", display_text:
|
|
231
|
-
{ type: "total", display_text:
|
|
229
|
+
{ type: "items_base_amount", display_text: text.totalItems, amount: itemsBase },
|
|
230
|
+
{ type: "items_discount", display_text: text.totalItemsDiscount, amount: subtotal - itemsBase },
|
|
231
|
+
{ type: "subtotal", display_text: text.totalSubtotal, amount: subtotal },
|
|
232
|
+
{ type: "discount", display_text: text.totalOrderDiscount, amount: -orderOff },
|
|
233
|
+
{ type: "total", display_text: text.totalTotal, amount: total },
|
|
232
234
|
],
|
|
233
235
|
total,
|
|
234
236
|
validation_issues: issues,
|
|
@@ -248,46 +250,47 @@ export interface OrderVerdict {
|
|
|
248
250
|
* envelope's numbers or a cost: the maximum discount and the margin floor are
|
|
249
251
|
* negotiation information (checkout §5.6, exfiltration).
|
|
250
252
|
*/
|
|
251
|
-
export function checkOrder(execution: Pick<Execution, "items" | "total" | "composition">, cart: PricedCart | undefined, envelope: Envelope, now: Date, timezone: string): OrderVerdict | undefined {
|
|
253
|
+
export function checkOrder(execution: Pick<Execution, "items" | "total" | "composition">, cart: PricedCart | undefined, envelope: Envelope, now: Date, timezone: string, locale: Locale = "pt-BR"): OrderVerdict | undefined {
|
|
254
|
+
const text = STRINGS[locale];
|
|
252
255
|
const [open, close] = envelope.service_hours.split("-") as [string, string];
|
|
253
256
|
if (isOutsideHours(`${close}-${open}`, now, timezone)) {
|
|
254
|
-
return { reason: "outside_hours", detail:
|
|
257
|
+
return { reason: "outside_hours", detail: text.outsideServiceHours(envelope.service_hours, timezone, localClock(now, timezone)) };
|
|
255
258
|
}
|
|
256
|
-
if (execution.items.length !== 1) return { reason: "outside_envelope", detail:
|
|
257
|
-
if (!execution.composition) return { reason: "outside_envelope", detail:
|
|
258
|
-
if (!cart) return { reason: "outside_envelope", detail:
|
|
259
|
-
if (cart.cart_hash !== execution.composition.composition_hash) return { reason: "outside_envelope", detail:
|
|
260
|
-
if (cart.line_items.length === 0) return { reason: "outside_envelope", detail:
|
|
261
|
-
if (cart.validation_issues.length > 0) return { reason: "outside_envelope", detail:
|
|
262
|
-
if (execution.total !== cart.total || execution.items[0]!.amount !== cart.total) return { reason: "outside_envelope", detail:
|
|
259
|
+
if (execution.items.length !== 1) return { reason: "outside_envelope", detail: text.gateOneItem };
|
|
260
|
+
if (!execution.composition) return { reason: "outside_envelope", detail: text.gateNoCart };
|
|
261
|
+
if (!cart) return { reason: "outside_envelope", detail: text.gateCartMissing(execution.composition.ref) };
|
|
262
|
+
if (cart.cart_hash !== execution.composition.composition_hash) return { reason: "outside_envelope", detail: text.gateCartChanged };
|
|
263
|
+
if (cart.line_items.length === 0) return { reason: "outside_envelope", detail: text.gateCartEmpty };
|
|
264
|
+
if (cart.validation_issues.length > 0) return { reason: "outside_envelope", detail: text.gateCartIssues(cart.validation_issues.map((i) => i.code).join(", ")) };
|
|
265
|
+
if (execution.total !== cart.total || execution.items[0]!.amount !== cart.total) return { reason: "outside_envelope", detail: text.gateTotalMismatch(execution.total, cart.total) };
|
|
263
266
|
|
|
264
267
|
for (const line of cart.line_items) {
|
|
265
268
|
const item = catalogItem(line.sku);
|
|
266
|
-
if (!item || !item.available) return { reason: "outside_envelope", detail:
|
|
267
|
-
if (line.unit_amount !== item.price_minor) return { reason: "outside_envelope", detail:
|
|
268
|
-
if (line.quantity > envelope.max_units_per_line || (item.stock !== undefined && line.quantity > item.stock)) return { reason: "outside_envelope", detail:
|
|
269
|
-
if (line.discount_pct > envelope.max_discount_pct) return { reason: "outside_envelope", detail:
|
|
269
|
+
if (!item || !item.available) return { reason: "outside_envelope", detail: text.gateNotForSale(line.sku) };
|
|
270
|
+
if (line.unit_amount !== item.price_minor) return { reason: "outside_envelope", detail: text.gateNotListPrice(line.sku) };
|
|
271
|
+
if (line.quantity > envelope.max_units_per_line || (item.stock !== undefined && line.quantity > item.stock)) return { reason: "outside_envelope", detail: text.gateQuantity(line.sku) };
|
|
272
|
+
if (line.discount_pct > envelope.max_discount_pct) return { reason: "outside_envelope", detail: text.gateLineDiscount(line.sku) };
|
|
270
273
|
const total = lineTotal(line);
|
|
271
|
-
if (marginBelow(total, item.cost_minor * line.quantity, envelope.min_margin_pct)) return { reason: "outside_envelope", detail:
|
|
274
|
+
if (marginBelow(total, item.cost_minor * line.quantity, envelope.min_margin_pct)) return { reason: "outside_envelope", detail: text.gateLineMargin(line.sku) };
|
|
272
275
|
}
|
|
273
276
|
const negotiated = cart.order_discounts.filter((d) => d.kind === "negotiated");
|
|
274
277
|
const coupons = cart.order_discounts.filter((d) => d.kind === "coupon");
|
|
275
|
-
if (negotiated.some((d) => d.pct > envelope.max_order_discount_pct)) return { reason: "outside_envelope", detail:
|
|
276
|
-
if (negotiated.length > 0 && coupons.length > 0) return { reason: "outside_envelope", detail:
|
|
278
|
+
if (negotiated.some((d) => d.pct > envelope.max_order_discount_pct)) return { reason: "outside_envelope", detail: text.gateOrderDiscount };
|
|
279
|
+
if (negotiated.length > 0 && coupons.length > 0) return { reason: "outside_envelope", detail: text.gateCouponAndDiscount };
|
|
277
280
|
const today = localDate(now, timezone);
|
|
278
281
|
for (const c of coupons) {
|
|
279
282
|
const code = c.ref.replace(/^coupon:/, "");
|
|
280
283
|
const found = envelope.coupons.find((x) => x.code === code);
|
|
281
|
-
if (!found || found.expires_at < today || c.pct !== found.discount_pct) return { reason: "outside_envelope", detail:
|
|
284
|
+
if (!found || found.expires_at < today || c.pct !== found.discount_pct) return { reason: "outside_envelope", detail: text.gateCouponInvalid(code) };
|
|
282
285
|
}
|
|
283
286
|
const cost = cart.line_items.reduce((sum, l) => sum + (catalogItem(l.sku)?.cost_minor ?? 0) * l.quantity, 0);
|
|
284
|
-
if (marginBelow(cart.total, cost, envelope.min_margin_pct)) return { reason: "outside_envelope", detail:
|
|
285
|
-
if (cart.total > envelope.max_order_minor) return { reason: "outside_envelope", detail:
|
|
287
|
+
if (marginBelow(cart.total, cost, envelope.min_margin_pct)) return { reason: "outside_envelope", detail: text.gateOrderMargin };
|
|
288
|
+
if (cart.total > envelope.max_order_minor) return { reason: "outside_envelope", detail: text.gateTicket(formatBRL(cart.total, locale)) };
|
|
286
289
|
|
|
287
290
|
const due = execution.items[0]!.due_date;
|
|
288
|
-
if (!due) return { reason: "outside_envelope", detail:
|
|
291
|
+
if (!due) return { reason: "outside_envelope", detail: text.gateNoDueDate };
|
|
289
292
|
const last = addDays(today, envelope.due_date_window_days);
|
|
290
|
-
if (due < today || due > last) return { reason: "outside_envelope", detail:
|
|
293
|
+
if (due < today || due > last) return { reason: "outside_envelope", detail: text.gateDueOutsideWindow(due, today, last) };
|
|
291
294
|
return undefined;
|
|
292
295
|
}
|
|
293
296
|
|