@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
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { checkApprovalArtifact, createApprovalArtifact, type ApprovalSigner } from "./approval.js";
|
|
15
15
|
import { maskPayee, type ProofBundle } from "./bundle.js";
|
|
16
|
-
import { evaluateEscalation, type Escalation } from "./escalate.js";
|
|
16
|
+
import { evaluateEscalation, localDate, type Escalation } from "./escalate.js";
|
|
17
17
|
import { CHARGE_CANCELLED, CHARGE_EXPIRED, CHARGE_PAID, PAYMENT_FAILED, PAYMENT_SUCCEEDED, type PublishedEvent } from "./events.js";
|
|
18
18
|
import type { Guardrails } from "./guardrails.js";
|
|
19
19
|
import { batchAttemptId, itemsHash, sha256Hex } from "./hash.js";
|
|
@@ -21,10 +21,10 @@ import { newId } from "./ids.js";
|
|
|
21
21
|
import { mandateExpired, payeeAllowed, resolveBeneficiary, windowCap, windowStart, type Mandate } from "./mandate.js";
|
|
22
22
|
import type { Manifest } from "./manifest.js";
|
|
23
23
|
import { checkQuote, quoteFromApproval } from "./quote.js";
|
|
24
|
-
import { spendApprovalOf, type PaymentRail, type RailOutcome, type RailPayment, type SealedSpendApproval, type SpendApproval } from "./rail.js";
|
|
24
|
+
import { sameWireActor, spendApprovalOf, wireActorOf, type PaymentRail, type RailOutcome, type RailPayment, type SealedSpendApproval, type SpendApproval } from "./rail.js";
|
|
25
25
|
import { sameApprovalHash } from "./receipt-chain.js";
|
|
26
26
|
import type { MandateStatusReport, MandateStatusSource } from "./revocation.js";
|
|
27
|
-
import { isTerminal, transition, type Execution, type ExecutionState } from "./state-machine.js";
|
|
27
|
+
import { isTerminal, transition, type Execution, type ExecutionState, type RailAnswer } from "./state-machine.js";
|
|
28
28
|
import type { StateStore } from "./state/store.js";
|
|
29
29
|
import type { Actor, ApprovalArtifact, ApprovalMode, ExecutionBatch, ExecutionComposition, ExecutionItem, ExecutionReason, ItemOutcome } from "./types.js";
|
|
30
30
|
|
|
@@ -131,6 +131,16 @@ export class ExecutionEngine {
|
|
|
131
131
|
return this.deps.mandate;
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
/**
|
|
135
|
+
* The day it is for the person, in the guardrails' timezone, at this
|
|
136
|
+
* engine's clock (so `--now` pins it too). A tool that shows a due date
|
|
137
|
+
* shows this next to it: the model has no calendar of its own, and without
|
|
138
|
+
* it a bill due next week reads as one that already fell due.
|
|
139
|
+
*/
|
|
140
|
+
today(): string {
|
|
141
|
+
return localDate(this.clock(), this.deps.guardrails.timezone);
|
|
142
|
+
}
|
|
143
|
+
|
|
134
144
|
// ---- the model's only entry point -------------------------------------
|
|
135
145
|
|
|
136
146
|
async draft(proposal: Proposal): Promise<DraftResult> {
|
|
@@ -420,6 +430,7 @@ export class ExecutionEngine {
|
|
|
420
430
|
private async dispatch(execution: Execution<"executing">, payments: RailPayment[]): Promise<Execution> {
|
|
421
431
|
const outcomes: ItemOutcome[] = [...execution.outcomes];
|
|
422
432
|
const unknown: string[] = [];
|
|
433
|
+
const unknownAnswers: RailAnswer[] = [];
|
|
423
434
|
const sealMismatches: string[] = [];
|
|
424
435
|
this.deps.store.updateOutbox(execution.idempotency_key, "sent", undefined, this.clock().toISOString());
|
|
425
436
|
|
|
@@ -453,10 +464,11 @@ export class ExecutionEngine {
|
|
|
453
464
|
// sent: an unknown answer about THIS payee says nothing about the next
|
|
454
465
|
// one, and the execution stays open until reconciliation settles it.
|
|
455
466
|
unknown.push(`attempt ${payment.attempt_id}: ${outcome.code} — outcome unknown, kept for reconciliation`);
|
|
467
|
+
unknownAnswers.push({ attempt_id: payment.attempt_id, code: outcome.code, message: outcome.message });
|
|
456
468
|
continue;
|
|
457
469
|
}
|
|
458
470
|
if (outcome.status === "failed") {
|
|
459
|
-
outcomes.push({ index, attempt_id: payment.attempt_id, status: "failed", code: outcome.code, error: `${outcome.code}: ${outcome.message}`, ...(outcome.held ? { held: outcome.held } : {}) });
|
|
471
|
+
outcomes.push({ index, attempt_id: payment.attempt_id, status: "failed", code: outcome.code, message: outcome.message, error: `${outcome.code}: ${outcome.message}`, ...(outcome.held ? { held: outcome.held } : {}) });
|
|
460
472
|
continue;
|
|
461
473
|
}
|
|
462
474
|
if (outcome.status === "accepted") {
|
|
@@ -469,7 +481,12 @@ export class ExecutionEngine {
|
|
|
469
481
|
const mismatch = await this.ingestSettlement(execution, index, payment, outcome.receipt_id, PAYMENT_SUCCEEDED);
|
|
470
482
|
if (mismatch) sealMismatches.push(mismatch);
|
|
471
483
|
}
|
|
472
|
-
const
|
|
484
|
+
const answers = [...(execution.uncertain_answers ?? []).filter((a) => !unknownAnswers.some((u) => u.attempt_id === a.attempt_id)), ...unknownAnswers];
|
|
485
|
+
const closed = this.close(
|
|
486
|
+
{ ...execution, outcomes, ...(Object.keys(generations).length > 0 ? { attempt_generations: generations } : {}), ...(answers.length > 0 ? { uncertain_answers: answers } : {}) },
|
|
487
|
+
payments.length,
|
|
488
|
+
unknown.join("; ") || undefined,
|
|
489
|
+
);
|
|
473
490
|
if (sealMismatches.length > 0) throw new ReceiptSealMismatchError(execution.id, sealMismatches);
|
|
474
491
|
return closed;
|
|
475
492
|
}
|
|
@@ -494,13 +511,12 @@ export class ExecutionEngine {
|
|
|
494
511
|
if (execution.outcomes.length < attempts) {
|
|
495
512
|
return this.leaveUnresolved(updated, unknownDetail ?? `${execution.outcomes.length} of ${attempts} attempt(s) have an outcome`);
|
|
496
513
|
}
|
|
497
|
-
|
|
498
|
-
const failed = execution.outcomes.find((o) => o.status === "failed" && o.code === "charge_reference_ambiguous") ?? execution.outcomes.find((o) => o.status === "failed");
|
|
514
|
+
const failed = decisiveFailure(execution.outcomes);
|
|
499
515
|
if (failed) {
|
|
500
516
|
this.deps.store.updateOutbox(execution.idempotency_key, "failed", execution.outcomes, at);
|
|
501
517
|
// `org_paused` is the API refusing the spend itself: the kill switch was pressed after the gate read the status. Nothing moved.
|
|
502
518
|
const reason: ExecutionReason =
|
|
503
|
-
failed.code === "charge_expired" || failed.code === "charge_cancelled" || failed.code === "org_paused" || failed.code === "charge_reference_ambiguous" ? failed.code : "rail_failed";
|
|
519
|
+
failed.code === "charge_expired" || failed.code === "charge_cancelled" || failed.code === "charge_issuer_error" || failed.code === "org_paused" || failed.code === "charge_reference_ambiguous" ? failed.code : "rail_failed";
|
|
504
520
|
return this.persist(transition(updated, "failed", { at, actor: this.agentActor, reason, detail: failed.error ?? "rail refused" }));
|
|
505
521
|
}
|
|
506
522
|
if (execution.outcomes.filter((o) => o.status === "settled").length === attempts) {
|
|
@@ -584,6 +600,11 @@ export class ExecutionEngine {
|
|
|
584
600
|
this.record("receipt.seal_mismatch", executionId, { receipt_id: receiptId, attempt_id: payment.attempt_id, sealed_approval: receipt.approval, sent_approval: payment.approval });
|
|
585
601
|
mismatches.push(`receipt ${receiptId} seals approval ${receipt.approval ? receipt.approval.items_hash : "none"}; attempt ${payment.attempt_id} sent ${payment.approval.items_hash}`);
|
|
586
602
|
}
|
|
603
|
+
// §2: the actor the spend declared, as the API recorded it. A different one, or none, is an event and not a seal mismatch:
|
|
604
|
+
// the money and its link to the approval are what the receipt proves, and who triggered it is what it RECORDS.
|
|
605
|
+
if (receipt.sealed_actor !== undefined && !sameWireActor(receipt.sealed_actor, wireActorOf(payment.actor))) {
|
|
606
|
+
this.record("receipt.actor_mismatch", executionId, { receipt_id: receiptId, attempt_id: payment.attempt_id, sealed_actor: receipt.sealed_actor, sent_actor: wireActorOf(payment.actor) });
|
|
607
|
+
}
|
|
587
608
|
return mismatches.length > 0 ? mismatches.join("; ") : undefined;
|
|
588
609
|
}
|
|
589
610
|
|
|
@@ -671,7 +692,12 @@ export class ExecutionEngine {
|
|
|
671
692
|
replace({ index, attempt_id: payment.attempt_id, status: "failed", code: seen.code, error: `${seen.code}: ${seen.message}`, ...(seen.held ? { held: seen.held } : {}) });
|
|
672
693
|
continue;
|
|
673
694
|
}
|
|
674
|
-
|
|
695
|
+
// No `replayed` here, whatever the rail said. A lookup IS a second
|
|
696
|
+
// presentation of an attempt this execution already sent, so on the API
|
|
697
|
+
// every settled lookup answers `idempotent_replay`, including the one
|
|
698
|
+
// whose payment was this execution's own. The mark would say "someone
|
|
699
|
+
// else paid" about a payment nobody can attribute from here.
|
|
700
|
+
replace({ index, attempt_id: payment.attempt_id, status: "settled", transaction_id: seen.transaction_id, ...(seen.receipt_id ? { receipt_id: seen.receipt_id } : {}) });
|
|
675
701
|
const mismatch = await this.ingestSettlement(execution, index, payment, seen.receipt_id, prior ? CHARGE_PAID : PAYMENT_SUCCEEDED);
|
|
676
702
|
if (mismatch) sealMismatches.push(mismatch);
|
|
677
703
|
}
|
|
@@ -1050,6 +1076,61 @@ function railAnswer(outcome: RailOutcome): Record<string, unknown> {
|
|
|
1050
1076
|
}
|
|
1051
1077
|
}
|
|
1052
1078
|
|
|
1079
|
+
/** The failed outcome an execution closes on. An ambiguous receivable outranks any other failure: it is the one outcome that must be reconciled rather than issued again. */
|
|
1080
|
+
function decisiveFailure(outcomes: readonly ItemOutcome[]): ItemOutcome | undefined {
|
|
1081
|
+
return outcomes.find((o) => o.status === "failed" && o.code === "charge_reference_ambiguous") ?? outcomes.find((o) => o.status === "failed");
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
/** What the rail answered, verbatim: the code and message the API sent, not only `rail_failed` or `rail_uncertain` (#50). */
|
|
1085
|
+
export interface RailError {
|
|
1086
|
+
/** `failed`: the answer the execution closed on. `uncertain`: an answer that left an attempt's outcome unknown. */
|
|
1087
|
+
outcome: "failed" | "uncertain";
|
|
1088
|
+
attempt_id: string;
|
|
1089
|
+
code: string;
|
|
1090
|
+
message: string | null;
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
/**
|
|
1094
|
+
* The rail's own answer behind a failure, for `--json` and the terminal. The
|
|
1095
|
+
* reason (`rail_failed`) says WHICH gate closed the execution; this says what
|
|
1096
|
+
* the API said, so a first failure explains itself — `insufficient_funds` on
|
|
1097
|
+
* an unfunded test wallet reads as that, not as a generic refusal. `null` when
|
|
1098
|
+
* nothing failed and nothing was left unknown. A 5xx is not a failure — the
|
|
1099
|
+
* money may have moved — so `provider_error` comes back as `uncertain`, with
|
|
1100
|
+
* the API's words, while the execution stays open for reconciliation. An
|
|
1101
|
+
* outcome stored before the message was kept carries only `code: message` in
|
|
1102
|
+
* `error`, and that is what is returned.
|
|
1103
|
+
*/
|
|
1104
|
+
export function railErrorOf(execution: Pick<Execution, "outcomes" | "uncertain_answers">): RailError | null {
|
|
1105
|
+
const failed = decisiveFailure(execution.outcomes);
|
|
1106
|
+
if (failed?.code !== undefined) return { outcome: "failed", attempt_id: failed.attempt_id, code: failed.code, message: failed.message ?? failed.error ?? null };
|
|
1107
|
+
const pending = (execution.uncertain_answers ?? []).find((a) => !execution.outcomes.some((o) => o.attempt_id === a.attempt_id));
|
|
1108
|
+
return pending ? { outcome: "uncertain", attempt_id: pending.attempt_id, code: pending.code, message: pending.message } : null;
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
/**
|
|
1112
|
+
* Settled, and every settled attempt was answered from the rail's record of
|
|
1113
|
+
* an earlier presentation this execution never made: the money moved, and
|
|
1114
|
+
* this execution did not move it. `dispatch` is the only writer of the mark,
|
|
1115
|
+
* so a report can say "paid by this run" of everything else it calls settled.
|
|
1116
|
+
*/
|
|
1117
|
+
export function isReplayedSettlement(execution: Pick<Execution, "state" | "outcomes">): boolean {
|
|
1118
|
+
const settled = execution.outcomes.filter((o) => o.status === "settled");
|
|
1119
|
+
return execution.state === "settled" && settled.length > 0 && settled.every((o) => o.replayed === true);
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
/**
|
|
1123
|
+
* A reason, or a rail code, that closes a payment without anything having
|
|
1124
|
+
* failed: nobody paid the charge in time, the charge was withdrawn, or the
|
|
1125
|
+
* organization pressed the kill switch. It reads with `denied` and `expired`,
|
|
1126
|
+
* not with a rail failure, in every count and report.
|
|
1127
|
+
*/
|
|
1128
|
+
const DECLINED_REASONS: readonly string[] = ["charge_expired", "charge_cancelled", "org_paused"];
|
|
1129
|
+
|
|
1130
|
+
export function isDeclinedReason(reason: string | null | undefined): boolean {
|
|
1131
|
+
return typeof reason === "string" && DECLINED_REASONS.includes(reason);
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1053
1134
|
/** The approval link a receipt sealed is the one a spend sent: the same hashes, in either spelling of the `sha256:` prefix. */
|
|
1054
1135
|
function sealsApproval(sealed: SealedSpendApproval | null, sent: SpendApproval): boolean {
|
|
1055
1136
|
return sealed !== null && sameApprovalHash(sealed.items_hash, sent.items_hash) && sameApprovalHash(sealed.batch_hash, sent.batch_hash ?? null);
|
|
@@ -71,6 +71,16 @@ export function localClock(now: Date, timezone: string): string {
|
|
|
71
71
|
return `${hour}:${minute}`;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
/** The calendar day `now` falls on in `timezone`, as `YYYY-MM-DD`. */
|
|
75
|
+
export function localDate(now: Date, timezone: string): string {
|
|
76
|
+
return new Intl.DateTimeFormat("en-CA", { timeZone: timezone, year: "numeric", month: "2-digit", day: "2-digit" }).format(now);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Whole days from `today` to `date` (both `YYYY-MM-DD`): 0 is today, negative is already past. */
|
|
80
|
+
export function daysUntil(today: string, date: string): number {
|
|
81
|
+
return Math.round((Date.parse(`${date}T00:00:00Z`) - Date.parse(`${today}T00:00:00Z`)) / 86_400_000);
|
|
82
|
+
}
|
|
83
|
+
|
|
74
84
|
/** `"22:00-07:00"` is the CLOSED window: inside it, the trigger fires. Crosses midnight when start > end. */
|
|
75
85
|
export function isOutsideHours(window: string, now: Date, timezone: string): boolean {
|
|
76
86
|
const [start, end] = window.split("-") as [string, string];
|
|
@@ -19,6 +19,9 @@ export * from "./tools.js";
|
|
|
19
19
|
export * from "./bundle.js";
|
|
20
20
|
export * from "./engine.js";
|
|
21
21
|
export * from "./agent.js";
|
|
22
|
+
export * from "./language.js";
|
|
23
|
+
export * from "./locale.js";
|
|
24
|
+
export * from "./strings.js";
|
|
22
25
|
export * from "./check.js";
|
|
23
26
|
export * from "./events.js";
|
|
24
27
|
export * from "./state/store.js";
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The language a person wrote in, of the two the kits speak, and the sentence
|
|
3
|
+
* that tells the model to answer in it.
|
|
4
|
+
*
|
|
5
|
+
* A rule in the system prompt ("answer in the language of the person's latest
|
|
6
|
+
* message") was not enough (docs/OPEN_QUESTIONS.md §64): on the Messages API a
|
|
7
|
+
* tool result is a user-role message, so on any turn that used a tool the
|
|
8
|
+
* latest message the model read was Portuguese data, and five English requests
|
|
9
|
+
* out of five were answered in Portuguese. The loop therefore reads the
|
|
10
|
+
* language from what the person TYPED, deterministically, and states it for
|
|
11
|
+
* the whole turn.
|
|
12
|
+
*
|
|
13
|
+
* Function words, not a classifier: payee names, bill descriptions and
|
|
14
|
+
* amounts are the same in both languages and count for neither.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export type ReplyLanguage = "pt-BR" | "en";
|
|
18
|
+
|
|
19
|
+
const PT = new Set(
|
|
20
|
+
"de da das do dos para pra pro que com um uma os é está esta estou já foi o e em na nas nos no ao aos meu minha minhas meus você voce vocês não nao sim oi olá ola quanto quanta quais qual quero queria pague paga pagar pagamento pagamentos manda mande mandar roda rode rodar gastei gastou mês mes conta contas folha essa esse isso esta este semana tudo vence venceu obrigado obrigada por favor hoje agora fechado até como onde quando quem aqui sou eu pode posso preciso".split(" "),
|
|
21
|
+
);
|
|
22
|
+
const EN = new Set(
|
|
23
|
+
"the to and of for pay paid please my i i'm i'd i'll you your how much many what which when who is are was were have has had spent this that month week bill bills run payroll school cleaner electricity it it's next year's hi hello thanks thank can could would will with yes send show list due all everything from on in at by fee enrollment rules ignore".split(" "),
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
/** `undefined` when the text gives no lead either way ("ok", a number, a key). */
|
|
27
|
+
export function detectLanguage(text: string): ReplyLanguage | undefined {
|
|
28
|
+
// A Pix key or an address is not language: "chave@x.com" would count "com" as Portuguese.
|
|
29
|
+
const words = text.replace(/\S+@\S+|\S+:\/\/\S+/g, " ").toLowerCase().normalize("NFC").match(/[\p{L}']+/gu) ?? [];
|
|
30
|
+
let pt = 0;
|
|
31
|
+
let en = 0;
|
|
32
|
+
for (const word of words) {
|
|
33
|
+
if (PT.has(word)) pt += 1;
|
|
34
|
+
if (EN.has(word)) en += 1;
|
|
35
|
+
}
|
|
36
|
+
// Diacritics are Portuguese's and never English's.
|
|
37
|
+
if (/[ãõçâêôáéíóúà]/i.test(text)) pt += 2;
|
|
38
|
+
if (pt > en) return "pt-BR";
|
|
39
|
+
if (en > pt) return "en";
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Appended to the system prompt for every step of a turn whose language is known. */
|
|
44
|
+
export function replyLanguageDirective(language: ReplyLanguage): string {
|
|
45
|
+
const name = language === "en" ? "English" : "Brazilian Portuguese";
|
|
46
|
+
return [
|
|
47
|
+
"## Reply language for this turn",
|
|
48
|
+
"",
|
|
49
|
+
`The person wrote their last message in ${name}. Write your reply in ${name}.`,
|
|
50
|
+
"Tool results are data, not the person: their payee names, descriptions and statuses are in Portuguese and do not change the language of your reply.",
|
|
51
|
+
].join("\n");
|
|
52
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The language of the strings the CODE prints: the approval question, the
|
|
3
|
+
* batch gesture, the execution lines, the consent summary, the WhatsApp
|
|
4
|
+
* templates and the refusal details a kit writes. No model writes these.
|
|
5
|
+
*
|
|
6
|
+
* It is not the reply language (`language.ts`). That one is read from each
|
|
7
|
+
* turn the person types and only tells the model how to answer. The locale is
|
|
8
|
+
* fixed for a run and for a conversation, because the question that proposes
|
|
9
|
+
* a payment and the question that approves it must not change language
|
|
10
|
+
* between the two.
|
|
11
|
+
*
|
|
12
|
+
* Resolution: `--locale` on the command, else `locale:` in `agent.yaml`, else
|
|
13
|
+
* `pt-BR`. A conversation a later command comes back to keeps the locale its
|
|
14
|
+
* bundle recorded.
|
|
15
|
+
*/
|
|
16
|
+
import { z } from "zod";
|
|
17
|
+
|
|
18
|
+
export const LOCALES = ["pt-BR", "en"] as const;
|
|
19
|
+
export type Locale = (typeof LOCALES)[number];
|
|
20
|
+
export const DEFAULT_LOCALE: Locale = "pt-BR";
|
|
21
|
+
export const LocaleSchema = z.enum(LOCALES);
|
|
22
|
+
|
|
23
|
+
export function isLocale(value: unknown): value is Locale {
|
|
24
|
+
return typeof value === "string" && (LOCALES as readonly string[]).includes(value);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** A `--locale` value, or the error the command prints next to its usage. */
|
|
28
|
+
export function parseLocale(value: string): Locale {
|
|
29
|
+
if (!isLocale(value)) throw new Error(`--locale must be ${LOCALES.join(" or ")}`);
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function resolveLocale(flag: Locale | undefined, manifest: { locale?: Locale | undefined }): Locale {
|
|
34
|
+
return flag ?? manifest.locale ?? DEFAULT_LOCALE;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The language code Meta approves a template in. Meta approves a template per
|
|
39
|
+
* (name, language) pair, so an English conversation sends the `en_US` copy of
|
|
40
|
+
* a template and never the `pt_BR` one.
|
|
41
|
+
*/
|
|
42
|
+
export const WHATSAPP_LANGUAGE: { readonly [L in Locale]: string } = { "pt-BR": "pt_BR", en: "en_US" };
|
|
43
|
+
|
|
44
|
+
/** One entry per locale. A table missing a locale does not type-check; a key missing from one entry fails `npm run check`. */
|
|
45
|
+
export type LocaleTable<T> = { readonly [L in Locale]: T };
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* What differs between the entries of a string table: a key one locale has and
|
|
49
|
+
* another lacks, a string where the other has a function, or a function that
|
|
50
|
+
* takes a different number of arguments. Empty means every key exists in every
|
|
51
|
+
* locale with the same shape. The check reads this at runtime because a kit is
|
|
52
|
+
* TypeScript that `npm run check` does not compile.
|
|
53
|
+
*/
|
|
54
|
+
export function tableGaps(name: string, table: Partial<Record<Locale, object>>): string[] {
|
|
55
|
+
const gaps: string[] = [];
|
|
56
|
+
const entry = (l: Locale) => table[l] as Record<string, unknown> | undefined;
|
|
57
|
+
for (const locale of LOCALES) if (!entry(locale)) gaps.push(`${name} has no ${locale} entry`);
|
|
58
|
+
const keys = new Set(LOCALES.flatMap((l) => Object.keys(entry(l) ?? {})));
|
|
59
|
+
for (const key of [...keys].sort()) {
|
|
60
|
+
const shapes = LOCALES.map((l) => {
|
|
61
|
+
const value = entry(l)?.[key];
|
|
62
|
+
if (value === undefined) return "missing";
|
|
63
|
+
if (typeof value === "function") return `function/${value.length}`;
|
|
64
|
+
return typeof value === "string" && value.length > 0 ? "string" : `empty ${typeof value}`;
|
|
65
|
+
});
|
|
66
|
+
for (const [i, shape] of shapes.entries()) {
|
|
67
|
+
if (shape === "missing" || shape.startsWith("empty")) gaps.push(`${name}.${key} is ${shape} in ${LOCALES[i]}`);
|
|
68
|
+
}
|
|
69
|
+
if (new Set(shapes.filter((s) => s !== "missing")).size > 1) gaps.push(`${name}.${key} differs in shape across locales: ${LOCALES.map((l, i) => `${l} ${shapes[i]}`).join(", ")}`);
|
|
70
|
+
}
|
|
71
|
+
return gaps;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** `185000` -> `R$ 1.850,00` in pt-BR, `R$1,850.00` in English: the two forms the prompts give the model since #62. */
|
|
75
|
+
export function formatBRL(minor: number, locale: Locale): string {
|
|
76
|
+
const sign = minor < 0 ? "-" : "";
|
|
77
|
+
const abs = Math.abs(minor);
|
|
78
|
+
const cents = String(abs % 100).padStart(2, "0");
|
|
79
|
+
if (locale === "en") return `${sign}R$${Math.floor(abs / 100).toLocaleString("en-US")}.${cents}`;
|
|
80
|
+
return `${sign}R$ ${Math.floor(abs / 100).toLocaleString("pt-BR")},${cents}`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** `2026-09-30` -> `30/09/2026` in pt-BR; English keeps the ISO date, which reads the same on either side of the Atlantic. */
|
|
84
|
+
export function formatDay(iso: string, locale: Locale): string {
|
|
85
|
+
if (locale === "en") return iso;
|
|
86
|
+
const [y, m, d] = iso.split("-");
|
|
87
|
+
return `${d}/${m}/${y}`;
|
|
88
|
+
}
|
|
@@ -8,6 +8,7 @@ import { readFileSync } from "node:fs";
|
|
|
8
8
|
import { dirname, resolve } from "node:path";
|
|
9
9
|
import { parse as parseYaml } from "yaml";
|
|
10
10
|
import { z } from "zod";
|
|
11
|
+
import { LocaleSchema } from "./locale.js";
|
|
11
12
|
|
|
12
13
|
const PINNED_PACKAGE = /^@codespar\/(mcp|cli)@\d+\.\d+\.\d+$/;
|
|
13
14
|
const HOURS_WINDOW = /^([01]\d|2[0-3]):[0-5]\d-([01]\d|2[0-3]):[0-5]\d$/;
|
|
@@ -34,12 +35,14 @@ export const ManifestSchema = z
|
|
|
34
35
|
default_approval: z.enum(["human", "mandate"]),
|
|
35
36
|
escalate_above: EscalateAboveSchema.optional(),
|
|
36
37
|
mcp: z.string().regex(PINNED_PACKAGE, "mcp must pin an exact version, e.g. @codespar/mcp@0.5.8"),
|
|
37
|
-
cli: z.string().regex(PINNED_PACKAGE, "cli must pin an exact version, e.g. @codespar/cli@0.
|
|
38
|
+
cli: z.string().regex(PINNED_PACKAGE, "cli must pin an exact version, e.g. @codespar/cli@0.18.1"),
|
|
38
39
|
tools: z.string(),
|
|
39
40
|
guardrails: z.string(),
|
|
40
41
|
mandate_schema: z.string(),
|
|
41
42
|
events: z.array(z.string().regex(/^commerce\.[a-z_.]+$/)),
|
|
42
43
|
channels: z.array(z.enum(["terminal", "whatsapp"])).nonempty(),
|
|
44
|
+
/** The language of the strings the code prints (not of the model's replies). Optional: absent is `pt-BR`, which is what every agent printed before the field existed. */
|
|
45
|
+
locale: LocaleSchema.optional(),
|
|
43
46
|
maturity: z.record(z.string(), MaturitySchema),
|
|
44
47
|
scenarios: z.string(),
|
|
45
48
|
evals: z.string(),
|
|
@@ -75,7 +75,7 @@ export interface RailPayment {
|
|
|
75
75
|
* its shape and never its content. A charge rail ignores it.
|
|
76
76
|
*/
|
|
77
77
|
approval?: SpendApproval;
|
|
78
|
-
/** Section 4.5: carried on every call
|
|
78
|
+
/** Section 4.5: carried on every call, on the wire as `PaymentActor` (`wireActorOf`) since @codespar/sdk 0.16.10; see OPEN_QUESTIONS §2. */
|
|
79
79
|
actor: Actor;
|
|
80
80
|
}
|
|
81
81
|
|
|
@@ -167,9 +167,37 @@ export interface RailReceipt {
|
|
|
167
167
|
receipt_sig_kid: string | null;
|
|
168
168
|
/** Section 4.5: the kit stamps the actor onto the local copy of every receipt. */
|
|
169
169
|
actor: Actor;
|
|
170
|
+
/**
|
|
171
|
+
* The actor the API RECORDED for the spend and read back (`PaymentActor`,
|
|
172
|
+
* @codespar/sdk 0.16.10): `null` when it recorded none — an API that did not
|
|
173
|
+
* take the field, or a spend that sent none. Absent when the rail cannot
|
|
174
|
+
* say: a charge, which records no actor.
|
|
175
|
+
*/
|
|
176
|
+
sealed_actor?: WireActor | null;
|
|
170
177
|
raw: unknown;
|
|
171
178
|
}
|
|
172
179
|
|
|
180
|
+
/**
|
|
181
|
+
* Who triggered a spend, in the API's own shape (`PaymentActor`,
|
|
182
|
+
* @codespar/sdk 0.16.10): the agent by its identifier and the consumer it acts
|
|
183
|
+
* for, or the person by id and the channel they acted from. The kit's `Actor`
|
|
184
|
+
* names the agent under `agent`; the wire names it under `id`, and that is the
|
|
185
|
+
* only difference.
|
|
186
|
+
*/
|
|
187
|
+
export type WireActor = { type: "agent"; id: string; on_behalf_of: string } | { type: "human"; id: string; channel?: string };
|
|
188
|
+
|
|
189
|
+
export function wireActorOf(actor: Actor): WireActor {
|
|
190
|
+
return actor.type === "agent" ? { type: "agent", id: actor.agent, on_behalf_of: actor.on_behalf_of } : { type: "human", id: actor.id, channel: actor.channel };
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** The same actor, field for field. A human's channel counts: the same person on WhatsApp and on a dashboard are two events. */
|
|
194
|
+
export function sameWireActor(a: WireActor | null, b: WireActor | null): boolean {
|
|
195
|
+
if (a === null || b === null) return a === b;
|
|
196
|
+
if (a.type === "agent" && b.type === "agent") return a.id === b.id && a.on_behalf_of === b.on_behalf_of;
|
|
197
|
+
if (a.type === "human" && b.type === "human") return a.id === b.id && (a.channel ?? null) === (b.channel ?? null);
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
|
|
173
201
|
/** What a reconcile learns: a recorded outcome, "still running", or nothing. Never a new payment. */
|
|
174
202
|
export type RailLookup = RailOutcome | { status: "in_flight" } | undefined;
|
|
175
203
|
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
*/
|
|
54
54
|
import { createPublicKey, verify as verifyDetached } from "node:crypto";
|
|
55
55
|
import { itemsHash } from "./hash.js";
|
|
56
|
-
import { readChainRecipe, readSealedApproval, recomputeChain, sameApprovalHash, type SealedApproval } from "./receipt-chain.js";
|
|
56
|
+
import { readChainRecipe, readSealedApproval, recomputeChain, sameApprovalHash, type ChainRecipe, type SealedApproval } from "./receipt-chain.js";
|
|
57
57
|
import type { ExecutionItem } from "./types.js";
|
|
58
58
|
|
|
59
59
|
/** The domain tag. A receipt names the version it was sealed under through
|
|
@@ -123,6 +123,16 @@ export interface ChainCheck {
|
|
|
123
123
|
reason: string;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
+
/**
|
|
127
|
+
* Whether the sealed payment was a sandbox one and whether money moved, read off a body that recomputed to the signed chain. A field
|
|
128
|
+
* is `null` when the recipe's payment link for that version does not seal it: a value the chain does not cover is not reported as one
|
|
129
|
+
* it does. Only these two, so a verdict never carries the rest of the read (the tenant's read also carries `mandate.sig`).
|
|
130
|
+
*/
|
|
131
|
+
export interface SealedPayment {
|
|
132
|
+
sandbox: boolean | null;
|
|
133
|
+
money_moved: boolean | null;
|
|
134
|
+
}
|
|
135
|
+
|
|
126
136
|
/** What the sealed approval link was held against. Present on a v4 chain that recomputed. */
|
|
127
137
|
export interface ApprovalLinkCheck {
|
|
128
138
|
/** `matched`: the artifact's hashes are the sealed ones. `mismatch`: they are not. `not_compared`: no artifact was given. */
|
|
@@ -161,6 +171,8 @@ export interface ReceiptVerification {
|
|
|
161
171
|
/** The body check, when one was attempted: only `verifyReceiptRead` attempts it, and only on a signature that verified. */
|
|
162
172
|
chain_check?: ChainCheck;
|
|
163
173
|
approval_check?: ApprovalLinkCheck;
|
|
174
|
+
/** Present exactly when the body recomputed to the signed chain. */
|
|
175
|
+
sealed_payment?: SealedPayment;
|
|
164
176
|
}
|
|
165
177
|
|
|
166
178
|
/** One published key, RFC 8037 shape, as the JWKS serves it. */
|
|
@@ -531,12 +543,13 @@ export function verifyReceiptRead(read: unknown, keyDocument: unknown, options:
|
|
|
531
543
|
};
|
|
532
544
|
}
|
|
533
545
|
const chainCheck: ChainCheck = { status: "recomputed", version: recomputed.version, recomputed: recomputed.chain, reason: "body_recomputes" };
|
|
546
|
+
const sealedPayment = sealedPaymentOf(read, recipe.recipe, recomputed.version);
|
|
534
547
|
const bound = `the body recomputes to the signed chain under the published recipe (v${recomputed.version})`;
|
|
535
548
|
|
|
536
549
|
const sealed = readSealedApproval(read);
|
|
537
550
|
if (!sealed) {
|
|
538
551
|
// Unreachable through the published recipe (v4 seals the link, and a read without it fails the recomputation above), kept so a future version is not misread.
|
|
539
|
-
return { ...signature, reason: "body_recomputes", message: `receipt ${signature.receipt_id} was sealed by CodeSpar and ${bound}; it seals no approval link`, chain_check: chainCheck };
|
|
552
|
+
return { ...signature, reason: "body_recomputes", message: `receipt ${signature.receipt_id} was sealed by CodeSpar and ${bound}; it seals no approval link`, chain_check: chainCheck, sealed_payment: sealedPayment };
|
|
540
553
|
}
|
|
541
554
|
const approval = options.approval;
|
|
542
555
|
if (!approval) {
|
|
@@ -546,6 +559,7 @@ export function verifyReceiptRead(read: unknown, keyDocument: unknown, options:
|
|
|
546
559
|
message: `receipt ${signature.receipt_id} was sealed by CodeSpar and ${bound}. It seals the approval ${sealed.items_hash}${sealed.batch_hash ? ` (batch ${sealed.batch_hash})` : ""}; no approval artifact was given to hold it against`,
|
|
547
560
|
chain_check: chainCheck,
|
|
548
561
|
approval_check: { status: "not_compared", sealed, artifact: null, reason: "no_artifact" },
|
|
562
|
+
sealed_payment: sealedPayment,
|
|
549
563
|
};
|
|
550
564
|
}
|
|
551
565
|
|
|
@@ -557,6 +571,7 @@ export function verifyReceiptRead(read: unknown, keyDocument: unknown, options:
|
|
|
557
571
|
message: `receipt ${signature.receipt_id} was sealed by CodeSpar and ${bound}, and ${why}: this payment was not sealed against the list artifact ${approval.approval_id} approved`,
|
|
558
572
|
chain_check: chainCheck,
|
|
559
573
|
approval_check: { status: "mismatch", sealed, artifact, reason },
|
|
574
|
+
sealed_payment: sealedPayment,
|
|
560
575
|
});
|
|
561
576
|
if (approval.items && itemsHash(approval.items) !== approval.items_hash) {
|
|
562
577
|
return mismatch("artifact_items_hash_inconsistent", `the artifact's items_hash ${approval.items_hash} is not the hash of the items it lists (${itemsHash(approval.items)})`);
|
|
@@ -573,5 +588,18 @@ export function verifyReceiptRead(read: unknown, keyDocument: unknown, options:
|
|
|
573
588
|
message: `receipt ${signature.receipt_id} was sealed by CodeSpar, ${bound}, and it was paid against the list artifact ${approval.approval_id} approved (${sealed.items_hash}${sealed.batch_hash ? `, batch ${sealed.batch_hash}` : ""}). WHO approved it is in the artifact, under a local key, and nowhere in the seal`,
|
|
574
589
|
chain_check: chainCheck,
|
|
575
590
|
approval_check: { status: "matched", sealed, artifact, reason: "approval_matches" },
|
|
591
|
+
sealed_payment: sealedPayment,
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
function sealedPaymentOf(read: Record<string, unknown>, recipe: ChainRecipe, version: number): SealedPayment {
|
|
596
|
+
const spec = recipe.links.find((l) => l.from === "payment");
|
|
597
|
+
const fields = spec?.fields ?? spec?.fields_by_version?.[String(version)] ?? [];
|
|
598
|
+
const payment = read["payment"];
|
|
599
|
+
const pick = (name: string): boolean | null => {
|
|
600
|
+
if (!fields.includes(name) && !fields.includes(`${name}${recipe.optional_marker}`)) return null;
|
|
601
|
+
const value = isRecord(payment) ? payment[name] : undefined;
|
|
602
|
+
return typeof value === "boolean" ? value : null;
|
|
576
603
|
};
|
|
604
|
+
return { sandbox: pick("sandbox"), money_moved: pick("money_moved") };
|
|
577
605
|
}
|
|
@@ -1,26 +1,71 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Sandbox by construction: a key outside the `csk_test_` pattern fails
|
|
3
3
|
* before any network call. Nothing in this repository ever holds a live key.
|
|
4
|
+
*
|
|
5
|
+
* Three different mistakes land here and each has its own fix, so each has
|
|
6
|
+
* its own message (#50): no key at all (the `.env` was never copied, or sits
|
|
7
|
+
* where the agent does not read it), the `.env.example` placeholder left in
|
|
8
|
+
* place, and a key that is not a test key. Telling a newcomer who has no key
|
|
9
|
+
* that their key is LIVE sends them looking for the wrong thing.
|
|
4
10
|
*/
|
|
5
11
|
export const TEST_KEY_PREFIX = "csk_test_";
|
|
6
12
|
|
|
13
|
+
/** The value `.env.example` ships with. It has the test prefix and is nobody's key. */
|
|
14
|
+
export const CODESPAR_KEY_PLACEHOLDER = "csk_test_your_key_here";
|
|
15
|
+
|
|
16
|
+
/** Why a `CODESPAR_API_KEY` cannot be used: absent or empty, the placeholder, or not a test key. */
|
|
17
|
+
export type TestKeyProblem = "missing" | "placeholder" | "not_test";
|
|
18
|
+
|
|
19
|
+
export function testKeyProblem(key: string | undefined): TestKeyProblem | undefined {
|
|
20
|
+
const value = key?.trim() ?? "";
|
|
21
|
+
if (value === "") return "missing";
|
|
22
|
+
if (value === CODESPAR_KEY_PLACEHOLDER) return "placeholder";
|
|
23
|
+
if (!value.startsWith(TEST_KEY_PREFIX) || value.length <= TEST_KEY_PREFIX.length) return "not_test";
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* `envFile` is the `.env` the agent actually reads, as the runner resolves it
|
|
29
|
+
* (`agents/<agent>/.env`, relative to where the command ran). The core does
|
|
30
|
+
* not know which agent it runs for, so without it the message names the
|
|
31
|
+
* pattern instead of the path.
|
|
32
|
+
*/
|
|
33
|
+
export function testKeyMessage(problem: TestKeyProblem, envFile?: string): string {
|
|
34
|
+
const file = envFile ?? "agents/<agent>/.env";
|
|
35
|
+
switch (problem) {
|
|
36
|
+
case "missing":
|
|
37
|
+
return (
|
|
38
|
+
`CODESPAR_API_KEY is not set: copy ${file}.example to ${file} and paste a ${TEST_KEY_PREFIX} key from https://codespar.dev/auth/signup. ` +
|
|
39
|
+
`${file} is the file this agent reads; a .env anywhere else, the repository root included, is not read.`
|
|
40
|
+
);
|
|
41
|
+
case "placeholder":
|
|
42
|
+
return `CODESPAR_API_KEY is still the placeholder from .env.example (${CODESPAR_KEY_PLACEHOLDER}): replace it in ${file} with your own ${TEST_KEY_PREFIX} key from https://codespar.dev/auth/signup.`;
|
|
43
|
+
case "not_test":
|
|
44
|
+
return (
|
|
45
|
+
`CODESPAR_API_KEY must be a test key (prefix "${TEST_KEY_PREFIX}"). ` +
|
|
46
|
+
`This kit runs in the sandbox only; a live key is refused before any call is made. It is read from the environment, or from ${file}.`
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
7
51
|
export class NotATestKeyError extends Error {
|
|
8
|
-
constructor(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
);
|
|
52
|
+
constructor(
|
|
53
|
+
readonly problem: TestKeyProblem = "not_test",
|
|
54
|
+
readonly envFile?: string,
|
|
55
|
+
) {
|
|
56
|
+
super(testKeyMessage(problem, envFile));
|
|
13
57
|
this.name = "NotATestKeyError";
|
|
14
58
|
}
|
|
15
59
|
}
|
|
16
60
|
|
|
17
61
|
export function isTestKey(key: string | undefined): key is string {
|
|
18
|
-
return
|
|
62
|
+
return testKeyProblem(key) === undefined;
|
|
19
63
|
}
|
|
20
64
|
|
|
21
65
|
export function assertTestKey(key: string | undefined): string {
|
|
22
|
-
|
|
23
|
-
|
|
66
|
+
const problem = testKeyProblem(key);
|
|
67
|
+
if (problem) throw new NotATestKeyError(problem);
|
|
68
|
+
return key!.trim();
|
|
24
69
|
}
|
|
25
70
|
|
|
26
71
|
/** For logs and bundles: the prefix and the last four characters, nothing else. */
|
|
@@ -62,6 +62,13 @@ export interface TransitionRecord {
|
|
|
62
62
|
actor: Actor;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
/** The code and message a rail answered for one attempt, as the rail gave them. */
|
|
66
|
+
export interface RailAnswer {
|
|
67
|
+
attempt_id: string;
|
|
68
|
+
code: string;
|
|
69
|
+
message: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
65
72
|
export interface Execution<S extends ExecutionState = ExecutionState> {
|
|
66
73
|
id: string;
|
|
67
74
|
run_id: string;
|
|
@@ -97,6 +104,13 @@ export interface Execution<S extends ExecutionState = ExecutionState> {
|
|
|
97
104
|
reason?: ExecutionReason;
|
|
98
105
|
detail?: string;
|
|
99
106
|
outcomes: ItemOutcome[];
|
|
107
|
+
/**
|
|
108
|
+
* What the rail answered, verbatim, for attempts whose outcome it left
|
|
109
|
+
* UNKNOWN (a timeout, a 5xx such as `provider_error`): no outcome exists for
|
|
110
|
+
* them, so their code and message would otherwise live only in the event
|
|
111
|
+
* log. An entry whose attempt later gains an outcome is superseded by it.
|
|
112
|
+
*/
|
|
113
|
+
uncertain_answers?: RailAnswer[];
|
|
100
114
|
history: TransitionRecord[];
|
|
101
115
|
created_at: string;
|
|
102
116
|
updated_at: string;
|