@codespar/cli 0.14.1 → 0.16.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 +44 -17
- package/dist/commands/audit-replay.js +267 -0
- package/dist/commands/audit-replay.js.map +1 -0
- package/dist/commands/init.js +28 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/index.js +16 -2
- package/dist/index.js.map +1 -1
- package/dist/surface.js +4 -1
- package/dist/surface.js.map +1 -1
- package/package.json +1 -1
- package/templates/bills-agent/README.md +8 -5
- package/templates/bills-agent/agents/bills-agent/.env.example +3 -3
- package/templates/bills-agent/agents/bills-agent/AGENTS.md +1 -1
- package/templates/bills-agent/agents/bills-agent/CLAUDE.md +1 -1
- package/templates/bills-agent/agents/bills-agent/README.md +62 -22
- package/templates/bills-agent/agents/bills-agent/SYSTEM_PROMPT.md +1 -1
- package/templates/bills-agent/agents/bills-agent/agent.yaml +2 -2
- package/templates/bills-agent/agents/bills-agent/package.json +14 -11
- package/templates/bills-agent/agents/bills-agent/src/kit.ts +193 -0
- package/templates/bills-agent/agents/bills-agent/test/adversarial.test.ts +8 -7
- package/templates/bills-agent/agents/bills-agent/test/check.test.ts +19 -2
- package/templates/bills-agent/agents/bills-agent/test/cli.test.ts +72 -24
- package/templates/bills-agent/agents/bills-agent/test/fixtures/excursao-300.transcript.jsonl +2 -0
- package/templates/bills-agent/agents/bills-agent/test/fixtures/material-400.transcript.jsonl +2 -0
- package/templates/bills-agent/agents/bills-agent/test/inspect.test.ts +124 -0
- package/templates/bills-agent/agents/bills-agent/test/provider.test.ts +25 -0
- package/templates/bills-agent/agents/bills-agent/test/scenarios.test.ts +10 -9
- package/templates/bills-agent/agents/bills-agent/tsconfig.json +0 -1
- package/templates/bills-agent/package.json +5 -2
- package/templates/bills-agent/packages/agent-core/README.md +2 -0
- package/templates/bills-agent/packages/agent-core/package.json +1 -1
- package/templates/bills-agent/packages/agent-core/src/api/charge-rail.ts +27 -6
- package/templates/bills-agent/packages/agent-core/src/api/rail.ts +16 -0
- package/templates/bills-agent/packages/agent-core/src/api/sandbox-payer.ts +20 -7
- package/templates/bills-agent/packages/agent-core/src/approval.ts +16 -2
- package/templates/bills-agent/packages/agent-core/src/bundle.ts +50 -4
- package/templates/bills-agent/packages/agent-core/src/channels.ts +140 -0
- package/templates/bills-agent/packages/agent-core/src/check.ts +90 -8
- package/templates/bills-agent/packages/agent-core/src/clock.ts +42 -0
- package/templates/bills-agent/packages/agent-core/src/engine.ts +119 -18
- package/templates/bills-agent/packages/agent-core/src/hash.ts +13 -0
- package/templates/bills-agent/packages/agent-core/src/index.ts +3 -0
- package/templates/bills-agent/packages/agent-core/src/manifest.ts +1 -1
- package/templates/bills-agent/packages/agent-core/src/rail.ts +16 -2
- package/templates/bills-agent/packages/agent-core/src/receipt-verification.ts +401 -0
- package/templates/bills-agent/packages/agent-core/src/state-machine.ts +3 -1
- package/templates/bills-agent/packages/agent-core/src/stubs/charge-rail.ts +2 -0
- package/templates/bills-agent/packages/agent-core/src/stubs/rail.ts +19 -2
- package/templates/bills-agent/packages/agent-core/src/types.ts +28 -0
- package/templates/bills-agent/packages/agent-core/test/approval.test.ts +36 -2
- package/templates/bills-agent/packages/agent-core/test/bundle.test.ts +85 -0
- package/templates/bills-agent/packages/agent-core/test/clock.test.ts +25 -0
- package/templates/bills-agent/packages/agent-core/test/engine.test.ts +73 -1
- package/templates/bills-agent/packages/agent-core/test/fixtures/staging-receipt-keys.json +18 -0
- package/templates/bills-agent/packages/agent-core/test/fixtures/staging-receipt.json +24 -0
- package/templates/bills-agent/packages/agent-core/test/helpers.ts +1 -1
- package/templates/bills-agent/packages/agent-core/test/manifest.test.ts +2 -2
- package/templates/bills-agent/packages/agent-core/test/receipt-verification.test.ts +316 -0
- package/templates/bills-agent/packages/agent-core/test/receivables.test.ts +51 -0
- package/templates/bills-agent/packages/agent-runtime/README.md +68 -0
- package/templates/bills-agent/packages/agent-runtime/bin.mjs +32 -0
- package/templates/bills-agent/packages/agent-runtime/package.json +23 -0
- package/templates/bills-agent/{agents/bills-agent → packages/agent-runtime}/src/adversarial.ts +36 -44
- package/templates/bills-agent/packages/agent-runtime/src/agent.ts +68 -0
- package/templates/bills-agent/packages/agent-runtime/src/channels/contact.ts +13 -0
- package/templates/bills-agent/packages/agent-runtime/src/channels/index.ts +72 -0
- package/templates/bills-agent/packages/agent-runtime/src/channels/rules.ts +120 -0
- package/templates/bills-agent/packages/agent-runtime/src/channels/types.ts +124 -0
- package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +358 -0
- package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +206 -0
- package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/evidence.ts +109 -0
- package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +225 -0
- package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +143 -0
- package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +47 -0
- package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +113 -0
- package/templates/bills-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +113 -0
- package/templates/bills-agent/packages/agent-runtime/src/cli.ts +98 -0
- package/templates/bills-agent/packages/agent-runtime/src/commands/check.ts +15 -0
- package/templates/bills-agent/packages/agent-runtime/src/commands/decide.ts +63 -0
- package/templates/bills-agent/packages/agent-runtime/src/commands/eval.ts +58 -0
- package/templates/bills-agent/packages/agent-runtime/src/commands/inspect.ts +100 -0
- package/templates/bills-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +317 -0
- package/templates/bills-agent/packages/agent-runtime/src/commands/poll.ts +144 -0
- package/templates/bills-agent/packages/agent-runtime/src/commands/reconcile.ts +42 -0
- package/templates/bills-agent/packages/agent-runtime/src/commands/rerun.ts +86 -0
- package/templates/bills-agent/packages/agent-runtime/src/commands/resume.ts +43 -0
- package/templates/bills-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +131 -0
- package/templates/bills-agent/packages/agent-runtime/src/commands/start.ts +245 -0
- package/templates/bills-agent/packages/agent-runtime/src/commands/verify.ts +129 -0
- package/templates/bills-agent/packages/agent-runtime/src/commands/webhook.ts +39 -0
- package/templates/bills-agent/packages/agent-runtime/src/default-kit.ts +83 -0
- package/templates/bills-agent/packages/agent-runtime/src/index.ts +12 -0
- package/templates/bills-agent/packages/agent-runtime/src/inspect.ts +797 -0
- package/templates/bills-agent/packages/agent-runtime/src/kit.ts +206 -0
- package/templates/{collections-agent/agents/collections-agent → bills-agent/packages/agent-runtime}/src/poll.ts +22 -11
- package/templates/{collections-agent/agents/collections-agent → bills-agent/packages/agent-runtime}/src/scenarios.ts +50 -34
- package/templates/bills-agent/{agents/bills-agent → packages/agent-runtime}/src/setup.ts +88 -66
- package/templates/bills-agent/packages/agent-runtime/src/terminal.ts +154 -0
- package/templates/{collections-agent/agents/collections-agent/channels/webhook/index.ts → bills-agent/packages/agent-runtime/src/webhook.ts} +1 -1
- package/templates/bills-agent/packages/agent-runtime/test/inspect.test.ts +336 -0
- package/templates/bills-agent/packages/agent-runtime/test/verify-cli.test.ts +127 -0
- package/templates/bills-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +232 -0
- package/templates/bills-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +204 -0
- package/templates/bills-agent/packages/agent-runtime/test/whatsapp-evidence.test.ts +94 -0
- package/templates/bills-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +174 -0
- package/templates/bills-agent/packages/agent-runtime/test/whatsapp-session.test.ts +135 -0
- package/templates/bills-agent/packages/agent-runtime/tsconfig.json +9 -0
- package/templates/bills-agent/vitest.config.ts +1 -1
- package/templates/collections-agent/README.md +8 -5
- package/templates/collections-agent/agents/collections-agent/.env.example +14 -0
- package/templates/collections-agent/agents/collections-agent/AGENTS.md +6 -4
- package/templates/collections-agent/agents/collections-agent/CLAUDE.md +6 -4
- package/templates/collections-agent/agents/collections-agent/README.md +184 -16
- package/templates/collections-agent/agents/collections-agent/agent.yaml +3 -3
- package/templates/collections-agent/agents/collections-agent/channels/whatsapp/README.md +111 -0
- package/templates/collections-agent/agents/collections-agent/channels/whatsapp/acordo-1042.json +11 -0
- package/templates/collections-agent/agents/collections-agent/channels/whatsapp/acordo-1103.json +11 -0
- package/templates/collections-agent/agents/collections-agent/channels/whatsapp/templates.json +23 -0
- package/templates/collections-agent/agents/collections-agent/package.json +12 -10
- package/templates/collections-agent/agents/collections-agent/runbook.md +52 -1
- package/templates/collections-agent/agents/collections-agent/src/kit.ts +265 -0
- package/templates/collections-agent/agents/collections-agent/test/adversarial.test.ts +9 -8
- package/templates/collections-agent/agents/collections-agent/test/check.test.ts +43 -1
- package/templates/collections-agent/agents/collections-agent/test/cli.test.ts +56 -18
- package/templates/collections-agent/agents/collections-agent/test/fixtures/agreed-1042-awaiting-payer.transcript.jsonl +4 -0
- package/templates/collections-agent/agents/collections-agent/test/scenarios.test.ts +11 -10
- package/templates/collections-agent/agents/collections-agent/test/webhook.test.ts +4 -7
- package/templates/collections-agent/agents/collections-agent/test/whatsapp-poll.test.ts +271 -0
- package/templates/collections-agent/agents/collections-agent/test/whatsapp.test.ts +213 -0
- package/templates/collections-agent/agents/collections-agent/tsconfig.json +0 -1
- package/templates/collections-agent/package.json +3 -1
- package/templates/collections-agent/packages/agent-core/README.md +2 -0
- package/templates/collections-agent/packages/agent-core/package.json +1 -1
- package/templates/collections-agent/packages/agent-core/src/api/charge-rail.ts +27 -6
- package/templates/collections-agent/packages/agent-core/src/api/rail.ts +16 -0
- package/templates/collections-agent/packages/agent-core/src/api/sandbox-payer.ts +20 -7
- package/templates/collections-agent/packages/agent-core/src/approval.ts +16 -2
- package/templates/collections-agent/packages/agent-core/src/bundle.ts +50 -4
- package/templates/collections-agent/packages/agent-core/src/channels.ts +140 -0
- package/templates/collections-agent/packages/agent-core/src/check.ts +90 -8
- package/templates/collections-agent/packages/agent-core/src/clock.ts +42 -0
- package/templates/collections-agent/packages/agent-core/src/engine.ts +119 -18
- package/templates/collections-agent/packages/agent-core/src/hash.ts +13 -0
- package/templates/collections-agent/packages/agent-core/src/index.ts +3 -0
- package/templates/collections-agent/packages/agent-core/src/manifest.ts +1 -1
- package/templates/collections-agent/packages/agent-core/src/rail.ts +16 -2
- package/templates/collections-agent/packages/agent-core/src/receipt-verification.ts +401 -0
- package/templates/collections-agent/packages/agent-core/src/state-machine.ts +3 -1
- package/templates/collections-agent/packages/agent-core/src/stubs/charge-rail.ts +2 -0
- package/templates/collections-agent/packages/agent-core/src/stubs/rail.ts +19 -2
- package/templates/collections-agent/packages/agent-core/src/types.ts +28 -0
- package/templates/collections-agent/packages/agent-core/test/approval.test.ts +36 -2
- package/templates/collections-agent/packages/agent-core/test/bundle.test.ts +85 -0
- package/templates/collections-agent/packages/agent-core/test/clock.test.ts +25 -0
- package/templates/collections-agent/packages/agent-core/test/engine.test.ts +73 -1
- package/templates/collections-agent/packages/agent-core/test/fixtures/staging-receipt-keys.json +18 -0
- package/templates/collections-agent/packages/agent-core/test/fixtures/staging-receipt.json +24 -0
- package/templates/collections-agent/packages/agent-core/test/helpers.ts +1 -1
- package/templates/collections-agent/packages/agent-core/test/manifest.test.ts +2 -2
- package/templates/collections-agent/packages/agent-core/test/receipt-verification.test.ts +316 -0
- package/templates/collections-agent/packages/agent-core/test/receivables.test.ts +51 -0
- package/templates/collections-agent/packages/agent-runtime/README.md +68 -0
- package/templates/collections-agent/packages/agent-runtime/bin.mjs +32 -0
- package/templates/collections-agent/packages/agent-runtime/package.json +23 -0
- package/templates/collections-agent/{agents/collections-agent → packages/agent-runtime}/src/adversarial.ts +29 -50
- package/templates/collections-agent/packages/agent-runtime/src/agent.ts +68 -0
- package/templates/collections-agent/packages/agent-runtime/src/channels/contact.ts +13 -0
- package/templates/collections-agent/packages/agent-runtime/src/channels/index.ts +72 -0
- package/templates/collections-agent/packages/agent-runtime/src/channels/rules.ts +120 -0
- package/templates/collections-agent/packages/agent-runtime/src/channels/types.ts +124 -0
- package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +358 -0
- package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +206 -0
- package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/evidence.ts +109 -0
- package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +225 -0
- package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +143 -0
- package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +47 -0
- package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +113 -0
- package/templates/collections-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +113 -0
- package/templates/collections-agent/packages/agent-runtime/src/cli.ts +98 -0
- package/templates/collections-agent/packages/agent-runtime/src/commands/check.ts +15 -0
- package/templates/collections-agent/packages/agent-runtime/src/commands/decide.ts +63 -0
- package/templates/collections-agent/packages/agent-runtime/src/commands/eval.ts +58 -0
- package/templates/collections-agent/packages/agent-runtime/src/commands/inspect.ts +100 -0
- package/templates/collections-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +317 -0
- package/templates/collections-agent/packages/agent-runtime/src/commands/poll.ts +144 -0
- package/templates/collections-agent/packages/agent-runtime/src/commands/reconcile.ts +42 -0
- package/templates/collections-agent/packages/agent-runtime/src/commands/rerun.ts +86 -0
- package/templates/collections-agent/packages/agent-runtime/src/commands/resume.ts +43 -0
- package/templates/collections-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +131 -0
- package/templates/collections-agent/packages/agent-runtime/src/commands/start.ts +245 -0
- package/templates/collections-agent/packages/agent-runtime/src/commands/verify.ts +129 -0
- package/templates/collections-agent/packages/agent-runtime/src/commands/webhook.ts +39 -0
- package/templates/collections-agent/packages/agent-runtime/src/default-kit.ts +83 -0
- package/templates/collections-agent/packages/agent-runtime/src/index.ts +12 -0
- package/templates/collections-agent/packages/agent-runtime/src/inspect.ts +797 -0
- package/templates/collections-agent/packages/agent-runtime/src/kit.ts +206 -0
- package/templates/collections-agent/packages/agent-runtime/src/poll.ts +105 -0
- package/templates/{bills-agent/agents/bills-agent → collections-agent/packages/agent-runtime}/src/scenarios.ts +98 -26
- package/templates/collections-agent/packages/agent-runtime/src/setup.ts +229 -0
- package/templates/collections-agent/packages/agent-runtime/src/terminal.ts +154 -0
- package/templates/collections-agent/packages/agent-runtime/src/webhook.ts +131 -0
- package/templates/collections-agent/packages/agent-runtime/test/inspect.test.ts +336 -0
- package/templates/collections-agent/packages/agent-runtime/test/verify-cli.test.ts +127 -0
- package/templates/collections-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +232 -0
- package/templates/collections-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +204 -0
- package/templates/collections-agent/packages/agent-runtime/test/whatsapp-evidence.test.ts +94 -0
- package/templates/collections-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +174 -0
- package/templates/collections-agent/packages/agent-runtime/test/whatsapp-session.test.ts +135 -0
- package/templates/collections-agent/packages/agent-runtime/tsconfig.json +9 -0
- package/templates/collections-agent/vitest.config.ts +1 -1
- package/templates/hello-agent/LICENSE +21 -0
- package/templates/hello-agent/README.md +23 -0
- package/templates/hello-agent/_gitignore +10 -0
- package/templates/hello-agent/agents/hello-agent/.env.example +5 -0
- package/templates/hello-agent/agents/hello-agent/AGENTS.md +15 -0
- package/templates/hello-agent/agents/hello-agent/CLAUDE.md +15 -0
- package/templates/hello-agent/agents/hello-agent/README.md +33 -0
- package/templates/hello-agent/agents/hello-agent/SYSTEM_PROMPT.md +19 -0
- package/templates/hello-agent/agents/hello-agent/agent.yaml +19 -0
- package/templates/hello-agent/agents/hello-agent/evals/adversarial/beneficiary-swap.json +6 -0
- package/templates/hello-agent/agents/hello-agent/evals/adversarial/beneficiary-swap.transcript.jsonl +2 -0
- package/templates/hello-agent/agents/hello-agent/evals/adversarial/exfiltration.json +6 -0
- package/templates/hello-agent/agents/hello-agent/evals/adversarial/exfiltration.transcript.jsonl +2 -0
- package/templates/hello-agent/agents/hello-agent/evals/adversarial/false-authority.json +6 -0
- package/templates/hello-agent/agents/hello-agent/evals/adversarial/false-authority.transcript.jsonl +2 -0
- package/templates/hello-agent/agents/hello-agent/evals/adversarial/fractioning.json +6 -0
- package/templates/hello-agent/agents/hello-agent/evals/adversarial/fractioning.transcript.jsonl +2 -0
- package/templates/hello-agent/agents/hello-agent/evals/adversarial/model-total.json +6 -0
- package/templates/hello-agent/agents/hello-agent/evals/adversarial/model-total.transcript.jsonl +2 -0
- package/templates/hello-agent/agents/hello-agent/evals/adversarial/prompt-injection.json +6 -0
- package/templates/hello-agent/agents/hello-agent/evals/adversarial/prompt-injection.transcript.jsonl +2 -0
- package/templates/hello-agent/agents/hello-agent/evals/adversarial/webhook-replay.json +6 -0
- package/templates/hello-agent/agents/hello-agent/evals/eval.yaml +7 -0
- package/templates/hello-agent/agents/hello-agent/guardrails.json +8 -0
- package/templates/hello-agent/agents/hello-agent/mandate.example.json +17 -0
- package/templates/hello-agent/agents/hello-agent/package.json +19 -0
- package/templates/hello-agent/agents/hello-agent/runbook.md +10 -0
- package/templates/hello-agent/agents/hello-agent/scenarios/happy-path.json +6 -0
- package/templates/hello-agent/agents/hello-agent/scenarios/happy-path.transcript.jsonl +2 -0
- package/templates/hello-agent/agents/hello-agent/scenarios/prompt-injection.json +6 -0
- package/templates/hello-agent/agents/hello-agent/scenarios/prompt-injection.transcript.jsonl +2 -0
- package/templates/hello-agent/agents/hello-agent/src/bills.ts +23 -0
- package/templates/hello-agent/agents/hello-agent/src/kit.ts +33 -0
- package/templates/hello-agent/agents/hello-agent/tools.json +11 -0
- package/templates/hello-agent/agents/hello-agent/tsconfig.json +9 -0
- package/templates/hello-agent/package.json +30 -0
- package/templates/hello-agent/packages/agent-core/README.md +21 -0
- package/templates/hello-agent/packages/agent-core/package.json +24 -0
- package/templates/hello-agent/packages/agent-core/src/agent.ts +125 -0
- package/templates/hello-agent/packages/agent-core/src/api/charge-rail.ts +175 -0
- package/templates/hello-agent/packages/agent-core/src/api/client.ts +53 -0
- package/templates/hello-agent/packages/agent-core/src/api/mandate-status.ts +58 -0
- package/templates/hello-agent/packages/agent-core/src/api/rail.ts +117 -0
- package/templates/hello-agent/packages/agent-core/src/api/sandbox-payer.ts +58 -0
- package/templates/hello-agent/packages/agent-core/src/approval.ts +123 -0
- package/templates/hello-agent/packages/agent-core/src/bundle.ts +159 -0
- package/templates/hello-agent/packages/agent-core/src/channels.ts +140 -0
- package/templates/hello-agent/packages/agent-core/src/check.ts +253 -0
- package/templates/hello-agent/packages/agent-core/src/clock.ts +42 -0
- package/templates/hello-agent/packages/agent-core/src/engine.ts +885 -0
- package/templates/hello-agent/packages/agent-core/src/escalate.ts +85 -0
- package/templates/hello-agent/packages/agent-core/src/events.ts +40 -0
- package/templates/hello-agent/packages/agent-core/src/guardrails.ts +45 -0
- package/templates/hello-agent/packages/agent-core/src/hash.ts +62 -0
- package/templates/hello-agent/packages/agent-core/src/ids.ts +10 -0
- package/templates/hello-agent/packages/agent-core/src/index.ts +32 -0
- package/templates/hello-agent/packages/agent-core/src/mandate.ts +100 -0
- package/templates/hello-agent/packages/agent-core/src/manifest.ts +76 -0
- package/templates/hello-agent/packages/agent-core/src/providers/anthropic.ts +76 -0
- package/templates/hello-agent/packages/agent-core/src/providers/replay.ts +63 -0
- package/templates/hello-agent/packages/agent-core/src/providers/types.ts +39 -0
- package/templates/hello-agent/packages/agent-core/src/rail.ts +101 -0
- package/templates/hello-agent/packages/agent-core/src/receipt-verification.ts +401 -0
- package/templates/hello-agent/packages/agent-core/src/revocation.ts +30 -0
- package/templates/hello-agent/packages/agent-core/src/secrets.ts +30 -0
- package/templates/hello-agent/packages/agent-core/src/state/store.ts +307 -0
- package/templates/hello-agent/packages/agent-core/src/state-machine.ts +148 -0
- package/templates/hello-agent/packages/agent-core/src/stubs/charge-rail.ts +195 -0
- package/templates/hello-agent/packages/agent-core/src/stubs/mandate-status.ts +57 -0
- package/templates/hello-agent/packages/agent-core/src/stubs/rail.ts +141 -0
- package/templates/hello-agent/packages/agent-core/src/tools.ts +55 -0
- package/templates/hello-agent/packages/agent-core/src/types.ts +134 -0
- package/templates/hello-agent/packages/agent-core/test/approval.test.ts +117 -0
- package/templates/hello-agent/packages/agent-core/test/bundle.test.ts +85 -0
- package/templates/hello-agent/packages/agent-core/test/clock.test.ts +25 -0
- package/templates/hello-agent/packages/agent-core/test/engine.test.ts +596 -0
- package/templates/hello-agent/packages/agent-core/test/escalate.test.ts +42 -0
- package/templates/hello-agent/packages/agent-core/test/fixtures/staging-receipt-keys.json +18 -0
- package/templates/hello-agent/packages/agent-core/test/fixtures/staging-receipt.json +24 -0
- package/templates/hello-agent/packages/agent-core/test/helpers.ts +139 -0
- package/templates/hello-agent/packages/agent-core/test/mandate-status.test.ts +153 -0
- package/templates/hello-agent/packages/agent-core/test/manifest.test.ts +45 -0
- package/templates/hello-agent/packages/agent-core/test/receipt-verification.test.ts +316 -0
- package/templates/hello-agent/packages/agent-core/test/receivables.test.ts +316 -0
- package/templates/hello-agent/packages/agent-core/test/secrets.test.ts +28 -0
- package/templates/hello-agent/packages/agent-core/test/state-machine.test.ts +67 -0
- package/templates/hello-agent/packages/agent-core/test/transitions.type-test.ts +59 -0
- package/templates/hello-agent/packages/agent-core/tsconfig.json +10 -0
- package/templates/hello-agent/packages/agent-runtime/README.md +68 -0
- package/templates/hello-agent/packages/agent-runtime/bin.mjs +32 -0
- package/templates/hello-agent/packages/agent-runtime/package.json +23 -0
- package/templates/hello-agent/packages/agent-runtime/src/adversarial.ts +169 -0
- package/templates/hello-agent/packages/agent-runtime/src/agent.ts +68 -0
- package/templates/hello-agent/packages/agent-runtime/src/channels/contact.ts +13 -0
- package/templates/hello-agent/packages/agent-runtime/src/channels/index.ts +72 -0
- package/templates/hello-agent/packages/agent-runtime/src/channels/rules.ts +120 -0
- package/templates/hello-agent/packages/agent-runtime/src/channels/types.ts +124 -0
- package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +358 -0
- package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +206 -0
- package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/evidence.ts +109 -0
- package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +225 -0
- package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +143 -0
- package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +47 -0
- package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +113 -0
- package/templates/hello-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +113 -0
- package/templates/hello-agent/packages/agent-runtime/src/cli.ts +98 -0
- package/templates/hello-agent/packages/agent-runtime/src/commands/check.ts +15 -0
- package/templates/hello-agent/packages/agent-runtime/src/commands/decide.ts +63 -0
- package/templates/hello-agent/packages/agent-runtime/src/commands/eval.ts +58 -0
- package/templates/hello-agent/packages/agent-runtime/src/commands/inspect.ts +100 -0
- package/templates/hello-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +317 -0
- package/templates/hello-agent/packages/agent-runtime/src/commands/poll.ts +144 -0
- package/templates/hello-agent/packages/agent-runtime/src/commands/reconcile.ts +42 -0
- package/templates/hello-agent/packages/agent-runtime/src/commands/rerun.ts +86 -0
- package/templates/hello-agent/packages/agent-runtime/src/commands/resume.ts +43 -0
- package/templates/hello-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +131 -0
- package/templates/hello-agent/packages/agent-runtime/src/commands/start.ts +245 -0
- package/templates/hello-agent/packages/agent-runtime/src/commands/verify.ts +129 -0
- package/templates/hello-agent/packages/agent-runtime/src/commands/webhook.ts +39 -0
- package/templates/hello-agent/packages/agent-runtime/src/default-kit.ts +83 -0
- package/templates/hello-agent/packages/agent-runtime/src/index.ts +12 -0
- package/templates/hello-agent/packages/agent-runtime/src/inspect.ts +797 -0
- package/templates/hello-agent/packages/agent-runtime/src/kit.ts +206 -0
- package/templates/hello-agent/packages/agent-runtime/src/poll.ts +105 -0
- package/templates/hello-agent/packages/agent-runtime/src/scenarios.ts +268 -0
- package/templates/hello-agent/packages/agent-runtime/src/setup.ts +229 -0
- package/templates/hello-agent/packages/agent-runtime/src/terminal.ts +154 -0
- package/templates/hello-agent/packages/agent-runtime/src/webhook.ts +131 -0
- package/templates/hello-agent/packages/agent-runtime/test/inspect.test.ts +336 -0
- package/templates/hello-agent/packages/agent-runtime/test/verify-cli.test.ts +127 -0
- package/templates/hello-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +232 -0
- package/templates/hello-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +204 -0
- package/templates/hello-agent/packages/agent-runtime/test/whatsapp-evidence.test.ts +94 -0
- package/templates/hello-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +174 -0
- package/templates/hello-agent/packages/agent-runtime/test/whatsapp-session.test.ts +135 -0
- package/templates/hello-agent/packages/agent-runtime/tsconfig.json +9 -0
- package/templates/hello-agent/tsconfig.base.json +16 -0
- package/templates/hello-agent/vitest.config.ts +12 -0
- package/templates/kits.lock.json +60 -12
- package/templates/supplier-payments-agent/LICENSE +21 -0
- package/templates/supplier-payments-agent/README.md +23 -0
- package/templates/supplier-payments-agent/_gitignore +10 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/.env.example +7 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/AGENTS.md +21 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/CLAUDE.md +21 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/README.md +118 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/SYSTEM_PROMPT.md +29 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/agent.yaml +26 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/batch-tampering.json +12 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/batch-tampering.transcript.jsonl +3 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/beneficiary-swap-mandate.json +9 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/beneficiary-swap.json +10 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/beneficiary-swap.transcript.jsonl +2 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/exfiltration.json +13 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/exfiltration.transcript.jsonl +3 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/false-authority.json +9 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/false-authority.transcript.jsonl +3 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/fractioning.json +15 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/fractioning.transcript.jsonl +6 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/model-total.json +10 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/model-total.transcript.jsonl +2 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/prompt-injection.json +9 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/prompt-injection.transcript.jsonl +2 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/adversarial/webhook-replay.json +9 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/evals/eval.yaml +9 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/guardrails.json +15 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/mandate.example.json +70 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/package.json +26 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/runbook.md +19 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/beneficiary-not-allowed.json +14 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/beneficiary-not-allowed.transcript.jsonl +2 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/cap-exceeded.json +12 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/cap-exceeded.transcript.jsonl +2 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/escalated-above-threshold.json +20 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/escalated-above-threshold.transcript.jsonl +7 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/happy-path.json +19 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/happy-path.transcript.jsonl +3 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/mandate-revoked.json +21 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/mandate-revoked.transcript.jsonl +9 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/partial-batch-failure.json +21 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/partial-batch-failure.transcript.jsonl +3 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/prompt-injection.json +12 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/scenarios/prompt-injection.transcript.jsonl +2 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/kit.ts +176 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/modules/batch-payout.ts +345 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/modules/pix-out.ts +118 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/src/payables.ts +76 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/adversarial.test.ts +53 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/batch.test.ts +384 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/check.test.ts +109 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/test/scenarios.test.ts +81 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/tools.json +53 -0
- package/templates/supplier-payments-agent/agents/supplier-payments-agent/tsconfig.json +9 -0
- package/templates/supplier-payments-agent/package.json +36 -0
- package/templates/supplier-payments-agent/packages/agent-core/README.md +21 -0
- package/templates/supplier-payments-agent/packages/agent-core/package.json +24 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/agent.ts +125 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/api/charge-rail.ts +175 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/api/client.ts +53 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/api/mandate-status.ts +58 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/api/rail.ts +117 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/api/sandbox-payer.ts +58 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/approval.ts +123 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/bundle.ts +159 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/channels.ts +140 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/check.ts +253 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/clock.ts +42 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/engine.ts +885 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/escalate.ts +85 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/events.ts +40 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/guardrails.ts +45 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/hash.ts +62 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/ids.ts +10 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/index.ts +32 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/mandate.ts +100 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/manifest.ts +76 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/providers/anthropic.ts +76 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/providers/replay.ts +63 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/providers/types.ts +39 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/rail.ts +101 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/receipt-verification.ts +401 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/revocation.ts +30 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/secrets.ts +30 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/state/store.ts +307 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/state-machine.ts +148 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/stubs/charge-rail.ts +195 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/stubs/mandate-status.ts +57 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/stubs/rail.ts +141 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/tools.ts +55 -0
- package/templates/supplier-payments-agent/packages/agent-core/src/types.ts +134 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/approval.test.ts +117 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/bundle.test.ts +85 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/clock.test.ts +25 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/engine.test.ts +596 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/escalate.test.ts +42 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/fixtures/staging-receipt-keys.json +18 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/fixtures/staging-receipt.json +24 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/helpers.ts +139 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/mandate-status.test.ts +153 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/manifest.test.ts +45 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/receipt-verification.test.ts +316 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/receivables.test.ts +316 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/secrets.test.ts +28 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/state-machine.test.ts +67 -0
- package/templates/supplier-payments-agent/packages/agent-core/test/transitions.type-test.ts +59 -0
- package/templates/supplier-payments-agent/packages/agent-core/tsconfig.json +10 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/README.md +68 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/bin.mjs +32 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/package.json +23 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/adversarial.ts +169 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/agent.ts +68 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/contact.ts +13 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/index.ts +72 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/rules.ts +120 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/types.ts +124 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/cloud-api.ts +358 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/emulator.ts +206 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/evidence.ts +109 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/index.ts +225 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/open.ts +143 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/present.ts +47 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/run.ts +113 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/channels/whatsapp/session.ts +113 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/cli.ts +98 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/check.ts +15 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/decide.ts +63 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/eval.ts +58 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/inspect.ts +100 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts +317 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/poll.ts +144 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/reconcile.ts +42 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/rerun.ts +86 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/resume.ts +43 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/start-whatsapp.ts +131 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/start.ts +245 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/verify.ts +129 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/webhook.ts +39 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/default-kit.ts +83 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/index.ts +12 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/inspect.ts +797 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/kit.ts +206 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/poll.ts +105 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/scenarios.ts +268 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/setup.ts +229 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/terminal.ts +154 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/src/webhook.ts +131 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/test/inspect.test.ts +336 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/test/verify-cli.test.ts +127 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-cloud-api.test.ts +232 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-emulator.integration.test.ts +204 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-evidence.test.ts +94 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-rules.test.ts +174 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/test/whatsapp-session.test.ts +135 -0
- package/templates/supplier-payments-agent/packages/agent-runtime/tsconfig.json +9 -0
- package/templates/supplier-payments-agent/tsconfig.base.json +16 -0
- package/templates/supplier-payments-agent/vitest.config.ts +12 -0
- package/templates/bills-agent/agents/bills-agent/channels/terminal/index.ts +0 -108
- package/templates/bills-agent/agents/bills-agent/src/commands/approve.ts +0 -9
- package/templates/bills-agent/agents/bills-agent/src/commands/check.ts +0 -13
- package/templates/bills-agent/agents/bills-agent/src/commands/consent.ts +0 -26
- package/templates/bills-agent/agents/bills-agent/src/commands/decide.ts +0 -45
- package/templates/bills-agent/agents/bills-agent/src/commands/deny.ts +0 -7
- package/templates/bills-agent/agents/bills-agent/src/commands/eval.ts +0 -37
- package/templates/bills-agent/agents/bills-agent/src/commands/reconcile.ts +0 -38
- package/templates/bills-agent/agents/bills-agent/src/commands/rerun.ts +0 -65
- package/templates/bills-agent/agents/bills-agent/src/commands/resume.ts +0 -30
- package/templates/bills-agent/agents/bills-agent/src/main.ts +0 -185
- package/templates/collections-agent/agents/collections-agent/channels/terminal/index.ts +0 -178
- package/templates/collections-agent/agents/collections-agent/src/commands/approve.ts +0 -10
- package/templates/collections-agent/agents/collections-agent/src/commands/check.ts +0 -13
- package/templates/collections-agent/agents/collections-agent/src/commands/decide.ts +0 -48
- package/templates/collections-agent/agents/collections-agent/src/commands/deny.ts +0 -7
- package/templates/collections-agent/agents/collections-agent/src/commands/eval.ts +0 -39
- package/templates/collections-agent/agents/collections-agent/src/commands/poll.ts +0 -35
- package/templates/collections-agent/agents/collections-agent/src/commands/reconcile.ts +0 -38
- package/templates/collections-agent/agents/collections-agent/src/commands/rerun.ts +0 -55
- package/templates/collections-agent/agents/collections-agent/src/commands/resume.ts +0 -30
- package/templates/collections-agent/agents/collections-agent/src/commands/webhook.ts +0 -36
- package/templates/collections-agent/agents/collections-agent/src/main.ts +0 -193
- package/templates/collections-agent/agents/collections-agent/src/setup.ts +0 -250
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* STUB, for runs without a key: the CI, the scenarios and `rerun`, where
|
|
3
|
+
* there is no network. Answers the section 4.7 status check from the local
|
|
4
|
+
* state.db, so a scenario can revoke or pause a mandate mid-run
|
|
5
|
+
* (`before_decision`, `before_execute` in the scenario packs) and the core
|
|
6
|
+
* reacts exactly as it does against the API. Behind the same
|
|
7
|
+
* `MandateStatusSource` interface as `api/mandate-status.ts`, which is what
|
|
8
|
+
* a run with a test key gets instead; this file is never consulted on that
|
|
9
|
+
* path.
|
|
10
|
+
*
|
|
11
|
+
* It also holds the organization kill switch (`pauseAll`), which the API
|
|
12
|
+
* does not expose yet, so `org_paused` can be exercised locally.
|
|
13
|
+
*/
|
|
14
|
+
import type { MandateStatusSource, MandateStatus, MandateStatusReport } from "../revocation.js";
|
|
15
|
+
import type { StateStore } from "../state/store.js";
|
|
16
|
+
|
|
17
|
+
export const STUB_ORG_ID = "org_local_stub";
|
|
18
|
+
|
|
19
|
+
export class LocalMandateStatusStub implements MandateStatusSource {
|
|
20
|
+
constructor(
|
|
21
|
+
private readonly store: StateStore,
|
|
22
|
+
private readonly clock: () => Date = () => new Date(),
|
|
23
|
+
) {}
|
|
24
|
+
|
|
25
|
+
async check(mandateId: string): Promise<MandateStatusReport> {
|
|
26
|
+
const row = this.store.stubMandateStatus(mandateId);
|
|
27
|
+
return {
|
|
28
|
+
mandate_id: mandateId,
|
|
29
|
+
status: (row?.status as MandateStatus | undefined) ?? "active",
|
|
30
|
+
org_paused: this.store.stubOrgPaused(STUB_ORG_ID),
|
|
31
|
+
checked_at: this.clock().toISOString(),
|
|
32
|
+
source: "stub",
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** `codespar mandate revoke <id>`, locally. */
|
|
37
|
+
revoke(mandateId: string, reason = "revoked by operator"): void {
|
|
38
|
+
this.store.stubSetMandateStatus(mandateId, "revoked", reason, this.clock().toISOString());
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
pause(mandateId: string, reason = "paused by operator"): void {
|
|
42
|
+
this.store.stubSetMandateStatus(mandateId, "paused", reason, this.clock().toISOString());
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
resume(mandateId: string): void {
|
|
46
|
+
this.store.stubSetMandateStatus(mandateId, "active", null, this.clock().toISOString());
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** The organization kill switch, locally: the API has no `org pauseAll` yet. */
|
|
50
|
+
pauseAll(): void {
|
|
51
|
+
this.store.stubSetOrgPaused(STUB_ORG_ID, true, this.clock().toISOString());
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
resumeAll(): void {
|
|
55
|
+
this.store.stubSetOrgPaused(STUB_ORG_ID, false, this.clock().toISOString());
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* STUB rail. A deterministic stand-in for the CodeSpar sandbox so the
|
|
3
|
+
* scenarios, the adversarial suite and the restart test run offline. Every
|
|
4
|
+
* attempt is persisted in state.db before the outcome is returned, which is
|
|
5
|
+
* what lets a process killed right after "the money left" be reconciled on
|
|
6
|
+
* `resume` instead of paying again. Receipts here are HMAC-shaped only in
|
|
7
|
+
* form; nothing about them is verifiable by anyone.
|
|
8
|
+
*/
|
|
9
|
+
import { sha256Hex } from "../hash.js";
|
|
10
|
+
import type { PaymentRail, RailLookup, RailOutcome, RailPayment, RailReceipt } from "../rail.js";
|
|
11
|
+
import type { StateStore } from "../state/store.js";
|
|
12
|
+
import type { Actor } from "../types.js";
|
|
13
|
+
|
|
14
|
+
export interface StubRailOptions {
|
|
15
|
+
clock?: () => Date;
|
|
16
|
+
/** Payees the stub refuses, to script a `failed` outcome. */
|
|
17
|
+
refusePayees?: string[];
|
|
18
|
+
/** Attempt ids the stub answers `uncertain` for, once. */
|
|
19
|
+
uncertainOnce?: string[];
|
|
20
|
+
/**
|
|
21
|
+
* Payees whose first presentation answers `uncertain`, the way a timeout
|
|
22
|
+
* does: the provider still took the attempt, so a later lookup finds it.
|
|
23
|
+
* The payee twin of `refusePayees`, for scripting an unknown outcome in the
|
|
24
|
+
* MIDDLE of a multi-item execution, where the attempt ids are not known
|
|
25
|
+
* until the execution exists.
|
|
26
|
+
*/
|
|
27
|
+
uncertainPayees?: string[];
|
|
28
|
+
/** Test hook: called after the attempt is persisted and before the outcome is returned. */
|
|
29
|
+
afterDispatch?: (attemptId: string) => void;
|
|
30
|
+
/** Attempt ids whose first lookup answers `in_flight` and whose second lookup finds the provider finished (settled), with no pay() in between. */
|
|
31
|
+
inFlightThenSettled?: string[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export class StubRail implements PaymentRail {
|
|
35
|
+
readonly name = "stub" as const;
|
|
36
|
+
private readonly clock: () => Date;
|
|
37
|
+
private readonly uncertainPending: Set<string>;
|
|
38
|
+
|
|
39
|
+
constructor(
|
|
40
|
+
private readonly store: StateStore,
|
|
41
|
+
private readonly options: StubRailOptions = {},
|
|
42
|
+
) {
|
|
43
|
+
this.clock = options.clock ?? (() => new Date());
|
|
44
|
+
this.uncertainPending = new Set(options.uncertainOnce ?? []);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private uncertainArmed = false;
|
|
48
|
+
private readonly inFlightSeen = new Set<string>();
|
|
49
|
+
/** Attempts that answered `uncertain` because the stub was armed: the "provider" did take them, and a later lookup finds them finished. */
|
|
50
|
+
private readonly lateAttempts = new Set<string>();
|
|
51
|
+
/** Attempts that already gave their one `uncertain`, so a re-presentation behaves normally. */
|
|
52
|
+
private readonly uncertainAnswered = new Set<string>();
|
|
53
|
+
/** How many times pay() reached the point of persisting a NEW attempt. */
|
|
54
|
+
payCount = 0;
|
|
55
|
+
|
|
56
|
+
/** The NEXT new attempt answers `uncertain` once, whatever its id; the provider still took it, so a later lookup sees it in flight and then settled. For scenarios that reconcile. */
|
|
57
|
+
armUncertainOnce(): void {
|
|
58
|
+
this.uncertainArmed = true;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async pay(payment: RailPayment): Promise<RailOutcome> {
|
|
62
|
+
const existing = this.store.stubRailGet(payment.attempt_id);
|
|
63
|
+
if (existing) return existing.outcome as RailOutcome;
|
|
64
|
+
|
|
65
|
+
const uncertainPayee = this.options.uncertainPayees?.includes(payment.payee) === true && !this.uncertainAnswered.has(payment.attempt_id);
|
|
66
|
+
if (this.uncertainArmed || this.uncertainPending.has(payment.attempt_id) || uncertainPayee) {
|
|
67
|
+
if (this.uncertainArmed || uncertainPayee) this.lateAttempts.add(payment.attempt_id);
|
|
68
|
+
this.uncertainAnswered.add(payment.attempt_id);
|
|
69
|
+
this.uncertainArmed = false;
|
|
70
|
+
this.uncertainPending.delete(payment.attempt_id);
|
|
71
|
+
return { status: "uncertain", code: "psp_dispatch_uncertain", message: "stub: outcome unknown on first presentation" };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const at = this.clock().toISOString();
|
|
75
|
+
const outcome: RailOutcome = this.options.refusePayees?.includes(payment.payee)
|
|
76
|
+
? { status: "failed", code: "psp_dispatch_failed", message: `stub: provider refused payee ${payment.payee}` }
|
|
77
|
+
: {
|
|
78
|
+
status: "settled",
|
|
79
|
+
transaction_id: `stubtx_${sha256Hex(payment.attempt_id).slice(0, 16)}`,
|
|
80
|
+
receipt_id: `rcpt_stub_${sha256Hex(`receipt:${payment.attempt_id}`).slice(0, 16)}`,
|
|
81
|
+
money_moved: false,
|
|
82
|
+
sandbox: true,
|
|
83
|
+
raw: { stub: true, attempt_id: payment.attempt_id, at },
|
|
84
|
+
};
|
|
85
|
+
const { actor: _actor, ...request } = payment;
|
|
86
|
+
this.payCount += 1;
|
|
87
|
+
this.store.stubRailPut(payment.attempt_id, request, outcome, at);
|
|
88
|
+
this.options.afterDispatch?.(payment.attempt_id);
|
|
89
|
+
return outcome;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async lookup(attemptId: string, payment: RailPayment): Promise<RailLookup> {
|
|
93
|
+
const recorded = this.store.stubRailGet(attemptId)?.outcome as RailOutcome | undefined;
|
|
94
|
+
if (recorded) return recorded;
|
|
95
|
+
if (this.options.inFlightThenSettled?.includes(attemptId) || this.lateAttempts.has(attemptId)) {
|
|
96
|
+
if (!this.inFlightSeen.has(attemptId)) {
|
|
97
|
+
this.inFlightSeen.add(attemptId);
|
|
98
|
+
return { status: "in_flight" };
|
|
99
|
+
}
|
|
100
|
+
// The provider finished on its own; the stub records the outcome as the rail would, without a new dispatch.
|
|
101
|
+
const { actor: _actor, ...request } = payment;
|
|
102
|
+
const outcome: RailOutcome = {
|
|
103
|
+
status: "settled",
|
|
104
|
+
transaction_id: `stubtx_${sha256Hex(attemptId).slice(0, 16)}`,
|
|
105
|
+
receipt_id: `rcpt_stub_${sha256Hex(`receipt:${attemptId}`).slice(0, 16)}`,
|
|
106
|
+
money_moved: false,
|
|
107
|
+
sandbox: true,
|
|
108
|
+
raw: { stub: true, attempt_id: attemptId, finished_in_background: true },
|
|
109
|
+
};
|
|
110
|
+
this.store.stubRailPut(attemptId, request, outcome, this.clock().toISOString());
|
|
111
|
+
return outcome;
|
|
112
|
+
}
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async receipt(receiptId: string, actor: Actor): Promise<RailReceipt | undefined> {
|
|
117
|
+
const sealed = this.store.stubRailFindByReceipt(receiptId);
|
|
118
|
+
if (!sealed) return undefined;
|
|
119
|
+
const req = sealed.request as Omit<RailPayment, "actor">;
|
|
120
|
+
const out = sealed.outcome as Extract<RailOutcome, { status: "settled" }>;
|
|
121
|
+
const body = {
|
|
122
|
+
receipt_id: receiptId,
|
|
123
|
+
state: "paid",
|
|
124
|
+
mandate: { id: req.mandate_id },
|
|
125
|
+
payment: { amount_minor: req.amount_minor, payee: req.payee, attempt_id: req.attempt_id, money_moved: false, sandbox: true, at: sealed.at },
|
|
126
|
+
};
|
|
127
|
+
const chain = `sha256:${sha256Hex(JSON.stringify(body))}`;
|
|
128
|
+
return {
|
|
129
|
+
...body,
|
|
130
|
+
chain,
|
|
131
|
+
receipt_sig: `stub:${sha256Hex(`sig:${chain}`).slice(0, 32)}`,
|
|
132
|
+
// The stub holds no CodeSpar key and must not look as though it did:
|
|
133
|
+
// `npm run verify` answers `unsigned` on a stub receipt, which is the
|
|
134
|
+
// truth about it.
|
|
135
|
+
receipt_sig_ed25519: null,
|
|
136
|
+
receipt_sig_kid: null,
|
|
137
|
+
actor,
|
|
138
|
+
raw: { stub: true, transaction_id: out.transaction_id },
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `tools.json`: the closed list of tools the model may call. Tool-level
|
|
3
|
+
* authority comes before mandate-level authority: a tool that is not in
|
|
4
|
+
* this file is refused before anything else looks at the call.
|
|
5
|
+
*
|
|
6
|
+
* Two kinds. `meta_tools` are CodeSpar meta-tool names, with the input the
|
|
7
|
+
* kit accepts for them (a snapshot of the MCP shape, pinned by `mcp` in the
|
|
8
|
+
* manifest; see OPEN_QUESTIONS on why the list is not fetched live).
|
|
9
|
+
* `local_tools` are the agent's own read-only helpers.
|
|
10
|
+
*/
|
|
11
|
+
import { readFileSync } from "node:fs";
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
import type { ToolSpec } from "./providers/types.js";
|
|
14
|
+
|
|
15
|
+
const ToolDefinitionSchema = z
|
|
16
|
+
.object({
|
|
17
|
+
name: z.string().regex(/^[a-z][a-z0-9_]*$/),
|
|
18
|
+
description: z.string().min(1),
|
|
19
|
+
input_schema: z.record(z.string(), z.unknown()),
|
|
20
|
+
/** `payment` and `charge` tools create a `drafted` execution and nothing else; `read` tools never touch money. `charge` is the receivable side: the counterparty pays us. */
|
|
21
|
+
effect: z.enum(["payment", "charge", "read"]),
|
|
22
|
+
})
|
|
23
|
+
.strict();
|
|
24
|
+
|
|
25
|
+
export const ToolsFileSchema = z
|
|
26
|
+
.object({
|
|
27
|
+
meta_tools: z.array(ToolDefinitionSchema),
|
|
28
|
+
local_tools: z.array(ToolDefinitionSchema),
|
|
29
|
+
})
|
|
30
|
+
.strict()
|
|
31
|
+
.superRefine((t, ctx) => {
|
|
32
|
+
const names = new Set<string>();
|
|
33
|
+
for (const tool of [...t.meta_tools, ...t.local_tools]) {
|
|
34
|
+
if (names.has(tool.name)) ctx.addIssue({ code: z.ZodIssueCode.custom, message: `duplicate tool ${tool.name}` });
|
|
35
|
+
names.add(tool.name);
|
|
36
|
+
}
|
|
37
|
+
for (const [i, tool] of t.meta_tools.entries()) {
|
|
38
|
+
if (!tool.name.startsWith("codespar_")) ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["meta_tools", i, "name"], message: "meta-tools are named codespar_*" });
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
export type ToolsFile = z.infer<typeof ToolsFileSchema>;
|
|
43
|
+
export type ToolDefinition = z.infer<typeof ToolDefinitionSchema>;
|
|
44
|
+
|
|
45
|
+
export function loadToolsFile(path: string): ToolsFile {
|
|
46
|
+
return ToolsFileSchema.parse(JSON.parse(readFileSync(path, "utf8")));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function toolSpecs(tools: ToolsFile): ToolSpec[] {
|
|
50
|
+
return [...tools.meta_tools, ...tools.local_tools].map((t) => ({ name: t.name, description: t.description, input_schema: t.input_schema }));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function allowedToolNames(tools: ToolsFile): Set<string> {
|
|
54
|
+
return new Set([...tools.meta_tools, ...tools.local_tools].map((t) => t.name));
|
|
55
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared shapes of the core. Amounts are always integer minor units (BRL
|
|
3
|
+
* cents). Timestamps are ISO 8601 strings so they survive SQLite and JSON
|
|
4
|
+
* unchanged.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export type ApprovalMode = "human" | "mandate";
|
|
8
|
+
|
|
9
|
+
/** Section 4.5: who acted. Every API call and every receipt carries one. */
|
|
10
|
+
export type Actor =
|
|
11
|
+
| { type: "agent"; agent: string; on_behalf_of: string }
|
|
12
|
+
| { type: "human"; id: string; channel: string };
|
|
13
|
+
|
|
14
|
+
/** One line of an execution: a payee and an amount, resolved by the core. */
|
|
15
|
+
export interface ExecutionItem {
|
|
16
|
+
/** The alias the model used (`escola`), when it used one. */
|
|
17
|
+
alias?: string;
|
|
18
|
+
/** Display name from the mandate's named payees, when known. */
|
|
19
|
+
beneficiary: string;
|
|
20
|
+
/** The pinned payee key (a Pix key for `pix-key` mandates). */
|
|
21
|
+
payee: string;
|
|
22
|
+
amount: number;
|
|
23
|
+
currency: string;
|
|
24
|
+
description?: string;
|
|
25
|
+
/** A receivable's due date (`YYYY-MM-DD`). Part of the `items_hash` when present: moving it after approval is a different charge. */
|
|
26
|
+
due_date?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The SET a line belongs to, when the line is one execution of a batch.
|
|
31
|
+
*
|
|
32
|
+
* A batch of N lines is N executions, each attested by its own `items_hash`.
|
|
33
|
+
* That leaves the list itself unattested: a person who approved four lines
|
|
34
|
+
* while the agent ran three leaves a bundle that does not say a fourth
|
|
35
|
+
* existed. `batch_hash` binds the set — computed once over the ordered lines
|
|
36
|
+
* at the moment the list is presented for approval, and carried by every
|
|
37
|
+
* artifact of that batch together with the line's own position in it.
|
|
38
|
+
*
|
|
39
|
+
* Absent on an execution that is not part of a batch, and an artifact
|
|
40
|
+
* without it is the artifact of section 4.2 unchanged, byte for byte: the
|
|
41
|
+
* field is omitted rather than null, so the canonical payload it signs is
|
|
42
|
+
* the same payload it signed before this existed.
|
|
43
|
+
*/
|
|
44
|
+
export interface ExecutionBatch {
|
|
45
|
+
/** The batch's reference, as the kit names it (`folha-2026-10`). */
|
|
46
|
+
ref: string;
|
|
47
|
+
/** `batchHash` over the batch's ordered lines, as they were presented. */
|
|
48
|
+
batch_hash: string;
|
|
49
|
+
/** This line's position in that ordered list, counting from 0. */
|
|
50
|
+
index: number;
|
|
51
|
+
/** How many lines the presented list held. */
|
|
52
|
+
count: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** The trigger of section 4.4 that sent a `mandate` execution to a human. */
|
|
56
|
+
export type EscalationTrigger = "amount" | "new_beneficiary" | "outside_hours";
|
|
57
|
+
|
|
58
|
+
/** Stable reasons a transition can carry. They are the readable-failure contract. */
|
|
59
|
+
export type ExecutionReason =
|
|
60
|
+
| "mandate_revoked"
|
|
61
|
+
| "mandate_paused"
|
|
62
|
+
| "mandate_expired"
|
|
63
|
+
| "mandate_status_unavailable"
|
|
64
|
+
| "org_paused"
|
|
65
|
+
| "beneficiary_not_allowed"
|
|
66
|
+
| "per_tx_cap_exceeded"
|
|
67
|
+
| "window_cap_exceeded"
|
|
68
|
+
| "approval_expired"
|
|
69
|
+
| "items_hash_mismatch"
|
|
70
|
+
| "mandate_changed"
|
|
71
|
+
| "denied_by_approver"
|
|
72
|
+
| "rail_failed"
|
|
73
|
+
| "rail_uncertain"
|
|
74
|
+
| "tool_not_allowed"
|
|
75
|
+
| "model_total_mismatch"
|
|
76
|
+
| "outside_hours"
|
|
77
|
+
| "escalated"
|
|
78
|
+
/** The agent's own envelope (guardrails) refused what the model proposed: a discount, an instalment count or a due date outside it. */
|
|
79
|
+
| "outside_envelope"
|
|
80
|
+
/** A receivable was issued and the rail is waiting for the payer; the execution stays `executing` until `commerce.charge.*` closes it. */
|
|
81
|
+
| "awaiting_settlement"
|
|
82
|
+
| "charge_expired"
|
|
83
|
+
| "charge_cancelled";
|
|
84
|
+
|
|
85
|
+
export interface MandateRef {
|
|
86
|
+
id: string;
|
|
87
|
+
version: number;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Section 4.2. */
|
|
91
|
+
export interface ApprovalArtifact {
|
|
92
|
+
approval_id: string;
|
|
93
|
+
execution_id: string;
|
|
94
|
+
mode: ApprovalMode;
|
|
95
|
+
approver:
|
|
96
|
+
| { type: "person"; id: string; channel: string }
|
|
97
|
+
| { type: "mandate"; id: string };
|
|
98
|
+
approved_at: string;
|
|
99
|
+
expires_at: string;
|
|
100
|
+
mandate: MandateRef;
|
|
101
|
+
items: ExecutionItem[];
|
|
102
|
+
items_hash: string;
|
|
103
|
+
/** Present when this execution is one line of a batch: what binds the SET this line was approved inside. */
|
|
104
|
+
batch?: ExecutionBatch;
|
|
105
|
+
/** Present when a section 4.4 trigger sent the execution to a human first. */
|
|
106
|
+
escalation?: { trigger: EscalationTrigger; detail: string };
|
|
107
|
+
actor: Actor;
|
|
108
|
+
signature: { alg: "HMAC-SHA256"; key_id: string; value: string };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface ItemOutcome {
|
|
112
|
+
index: number;
|
|
113
|
+
attempt_id: string;
|
|
114
|
+
/** `accepted`: the rail took the attempt and the outcome comes later (a receivable waiting for its payer). Not terminal. */
|
|
115
|
+
status: "settled" | "failed" | "accepted";
|
|
116
|
+
receipt_id?: string;
|
|
117
|
+
transaction_id?: string;
|
|
118
|
+
/** The rail's code on a failed outcome (`charge_expired`, `charge_cancelled`, a provider code). */
|
|
119
|
+
code?: string;
|
|
120
|
+
error?: string;
|
|
121
|
+
/** What the payer is shown for an accepted receivable, as the rail handed it back. Presentation only; nothing here decides money. */
|
|
122
|
+
instrument?: ChargeInstrument;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** The payable legs of a receivable. Null until the issuer registers the instrument (a cobranca com vencimento answers PROCESSING first). */
|
|
126
|
+
export interface ChargeInstrument {
|
|
127
|
+
payable: boolean;
|
|
128
|
+
pix_copy_paste: string | null;
|
|
129
|
+
boleto_bank_line: string | null;
|
|
130
|
+
boleto_bar_code: string | null;
|
|
131
|
+
due_date: string | null;
|
|
132
|
+
/** The issuer's normalized state as last read: PROCESSING, PENDING, CONFIRMED, EXPIRED, CANCELLED. */
|
|
133
|
+
status: string;
|
|
134
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { checkApprovalArtifact, createApprovalArtifact, hmacSigner } from "../src/approval.js";
|
|
3
|
+
import { batchHash, itemsHash } from "../src/hash.js";
|
|
4
|
+
import type { Execution } from "../src/state-machine.js";
|
|
5
|
+
import type { Actor, ExecutionBatch, ExecutionItem } from "../src/types.js";
|
|
6
|
+
|
|
7
|
+
const actor: Actor = { type: "human", id: "usr_1", channel: "terminal" };
|
|
8
|
+
const signer = hmacSigner("test", Buffer.alloc(32, 7));
|
|
9
|
+
const now = new Date("2026-09-23T14:03:11Z");
|
|
10
|
+
|
|
11
|
+
function execution(items: ExecutionItem[]): Execution<"awaiting_approval"> {
|
|
12
|
+
return {
|
|
13
|
+
id: "exe_1",
|
|
14
|
+
run_id: "run_1",
|
|
15
|
+
state: "awaiting_approval",
|
|
16
|
+
mode: "human",
|
|
17
|
+
actor: { type: "agent", agent: "bills-agent@0.1.0", on_behalf_of: "usr_1" },
|
|
18
|
+
items,
|
|
19
|
+
total: items.reduce((s, i) => s + i.amount, 0),
|
|
20
|
+
currency: "BRL",
|
|
21
|
+
items_hash: itemsHash(items),
|
|
22
|
+
mandate: { id: "mdt_1", version: 3 },
|
|
23
|
+
idempotency_key: "idk_1",
|
|
24
|
+
blocking_reasons: [],
|
|
25
|
+
outcomes: [],
|
|
26
|
+
history: [],
|
|
27
|
+
created_at: now.toISOString(),
|
|
28
|
+
updated_at: now.toISOString(),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const escola: ExecutionItem = { alias: "escola", beneficiary: "Escola", payee: "escola@exemplo.com.br", amount: 185000, currency: "BRL" };
|
|
33
|
+
const mercado: ExecutionItem = { alias: "mercado", beneficiary: "Mercado", payee: "+5511999990001", amount: 42000, currency: "BRL" };
|
|
34
|
+
|
|
35
|
+
describe("section 4.2: approval artifact", () => {
|
|
36
|
+
it("has the schema of the spec and an HMAC signature that verifies", () => {
|
|
37
|
+
const exe = execution([escola]);
|
|
38
|
+
const artifact = createApprovalArtifact(signer, { execution: exe, approver: { type: "person", id: "usr_1", channel: "terminal" }, actor, now });
|
|
39
|
+
expect(artifact.approval_id).toMatch(/^apr_/);
|
|
40
|
+
expect(artifact.execution_id).toBe("exe_1");
|
|
41
|
+
expect(artifact.mode).toBe("human");
|
|
42
|
+
expect(artifact.mandate).toEqual({ id: "mdt_1", version: 3 });
|
|
43
|
+
expect(artifact.items_hash).toMatch(/^sha256:[0-9a-f]{64}$/);
|
|
44
|
+
expect(artifact.signature.alg).toBe("HMAC-SHA256");
|
|
45
|
+
expect(artifact.actor).toEqual(actor);
|
|
46
|
+
expect(new Date(artifact.expires_at).getTime() - new Date(artifact.approved_at).getTime()).toBe(15 * 60 * 1000);
|
|
47
|
+
expect(checkApprovalArtifact(signer, artifact, exe, now)).toEqual({ ok: true });
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("items_hash ignores presentation fields and changes when the money fields change", () => {
|
|
51
|
+
const base = itemsHash([escola]);
|
|
52
|
+
expect(itemsHash([{ ...escola, description: "outubro", beneficiary: "Escola X" }])).toBe(base);
|
|
53
|
+
expect(itemsHash([{ ...escola, amount: 185001 }])).not.toBe(base);
|
|
54
|
+
expect(itemsHash([{ ...escola, payee: "outra@chave" }])).not.toBe(base);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("refuses when the list changed after approval (items_hash mismatch)", () => {
|
|
58
|
+
const exe = execution([escola]);
|
|
59
|
+
const artifact = createApprovalArtifact(signer, { execution: exe, approver: { type: "person", id: "usr_1", channel: "terminal" }, actor, now });
|
|
60
|
+
const tampered = { ...exe, items: [{ ...escola, amount: 500000 }] };
|
|
61
|
+
expect(checkApprovalArtifact(signer, artifact, tampered, now)).toEqual({ ok: false, problem: "items_hash_mismatch" });
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("refuses a tampered artifact, an expired one and a foreign key", () => {
|
|
65
|
+
const exe = execution([escola]);
|
|
66
|
+
const artifact = createApprovalArtifact(signer, { execution: exe, approver: { type: "person", id: "usr_1", channel: "terminal" }, actor, now });
|
|
67
|
+
expect(checkApprovalArtifact(signer, { ...artifact, items_hash: itemsHash([{ ...escola, amount: 1 }]) }, exe, now)).toEqual({ ok: false, problem: "signature_invalid" });
|
|
68
|
+
expect(checkApprovalArtifact(signer, artifact, exe, new Date(now.getTime() + 16 * 60 * 1000))).toEqual({ ok: false, problem: "expired" });
|
|
69
|
+
expect(checkApprovalArtifact(hmacSigner("other", Buffer.alloc(32, 9)), artifact, exe, now)).toEqual({ ok: false, problem: "signature_invalid" });
|
|
70
|
+
expect(checkApprovalArtifact(signer, artifact, { ...exe, mandate: { id: "mdt_1", version: 4 } }, now)).toEqual({ ok: false, problem: "wrong_mandate" });
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("carries the batch this line belongs to, and the whole of it is signed", () => {
|
|
74
|
+
const batch: ExecutionBatch = { ref: "folha-2026-10", batch_hash: batchHash([escola, mercado]), index: 0, count: 2 };
|
|
75
|
+
const exe = { ...execution([escola]), batch };
|
|
76
|
+
const artifact = createApprovalArtifact(signer, { execution: exe, approver: { type: "person", id: "usr_1", channel: "terminal" }, actor, now });
|
|
77
|
+
expect(artifact.batch).toEqual(batch);
|
|
78
|
+
expect(checkApprovalArtifact(signer, artifact, exe, now)).toEqual({ ok: true });
|
|
79
|
+
// Moving the line inside the list, re-pricing the list, or renaming it:
|
|
80
|
+
// each is a different set, and the signature covers all of it.
|
|
81
|
+
for (const changed of [{ ...batch, index: 1 }, { ...batch, count: 3 }, { ...batch, ref: "folha-2026-11" }, { ...batch, batch_hash: batchHash([escola]) }]) {
|
|
82
|
+
expect(checkApprovalArtifact(signer, { ...artifact, batch: changed }, exe, now)).toEqual({ ok: false, problem: "signature_invalid" });
|
|
83
|
+
expect(checkApprovalArtifact(signer, artifact, { ...exe, batch: changed }, now)).toEqual({ ok: false, problem: "batch_mismatch" });
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("an artifact with no batch signs the payload it signed before batches existed", () => {
|
|
88
|
+
const exe = execution([escola]);
|
|
89
|
+
const artifact = createApprovalArtifact(signer, { execution: exe, approver: { type: "person", id: "usr_1", channel: "terminal" }, actor, now });
|
|
90
|
+
// Omitted, never null: a bills-agent run has no batch and must not grow a key.
|
|
91
|
+
expect("batch" in artifact).toBe(false);
|
|
92
|
+
expect(checkApprovalArtifact(signer, artifact, exe, now)).toEqual({ ok: true });
|
|
93
|
+
// An execution that gained a batch after the artifact was signed is not the one that was approved.
|
|
94
|
+
const joined = { ...exe, batch: { ref: "folha-2026-10", batch_hash: batchHash([escola]), index: 0, count: 1 } };
|
|
95
|
+
expect(checkApprovalArtifact(signer, artifact, joined, now)).toEqual({ ok: false, problem: "batch_mismatch" });
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("the batch hash IS the items hash of the whole ordered list, so a reader can recompute it", () => {
|
|
99
|
+
expect(batchHash([escola, mercado])).toBe(itemsHash([escola, mercado]));
|
|
100
|
+
// Order is part of it: `index` names a position, and a position only means something in a fixed order.
|
|
101
|
+
expect(batchHash([mercado, escola])).not.toBe(batchHash([escola, mercado]));
|
|
102
|
+
// A line dropped is a different set, which is the whole point.
|
|
103
|
+
expect(batchHash([escola])).not.toBe(batchHash([escola, mercado]));
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("records the escalation trigger when there was one", () => {
|
|
107
|
+
const exe = execution([escola]);
|
|
108
|
+
const artifact = createApprovalArtifact(signer, {
|
|
109
|
+
execution: exe,
|
|
110
|
+
approver: { type: "person", id: "usr_1", channel: "terminal" },
|
|
111
|
+
actor,
|
|
112
|
+
now,
|
|
113
|
+
escalation: { trigger: "amount", detail: "above 150000" },
|
|
114
|
+
});
|
|
115
|
+
expect(artifact.escalation).toEqual({ trigger: "amount", detail: "above 150000" });
|
|
116
|
+
});
|
|
117
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Section 11: what the proof bundle has to carry for `npm run inspect` to
|
|
3
|
+
* answer "why could the agent pay this" from the folder alone — the rail's
|
|
4
|
+
* request and its answer per attempt, and a receipt path that travels with
|
|
5
|
+
* the bundle instead of naming the machine that wrote it.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { describe, expect, it } from "vitest";
|
|
10
|
+
import { maskPayee } from "../src/bundle.js";
|
|
11
|
+
import { harness } from "./helpers.js";
|
|
12
|
+
|
|
13
|
+
const approver = { id: "usr_demo", channel: "terminal" };
|
|
14
|
+
|
|
15
|
+
async function settledRun() {
|
|
16
|
+
const h = harness({ mode: "human" });
|
|
17
|
+
const draft = await h.engine.draft({ items: [{ payee: "escola", amount: 185000, description: "outubro" }] });
|
|
18
|
+
if (!draft.ok) throw new Error("refused");
|
|
19
|
+
const approved = h.engine.approve(draft.execution.id, approver);
|
|
20
|
+
const settled = await h.engine.execute(approved.id);
|
|
21
|
+
return { h, settled };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
describe("the proof bundle records the rail call and its answer", () => {
|
|
25
|
+
it("rail.dispatch names the idempotency key that makes a retry the same payment", async () => {
|
|
26
|
+
const { h, settled } = await settledRun();
|
|
27
|
+
const dispatch = h.bundle.readEvents().find((e) => e["type"] === "rail.dispatch");
|
|
28
|
+
expect(dispatch).toBeDefined();
|
|
29
|
+
const payload = dispatch!["payload"] as Record<string, unknown>;
|
|
30
|
+
expect(payload["idempotency_key"]).toBe(settled.idempotency_key);
|
|
31
|
+
expect(payload["attempt_id"]).toBe(settled.outcomes[0]?.attempt_id);
|
|
32
|
+
expect(payload["rail"]).toBe("stub");
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("rail.outcome carries what the rail answered: transaction, receipt and whether money moved", async () => {
|
|
36
|
+
const { h, settled } = await settledRun();
|
|
37
|
+
const outcome = h.bundle.readEvents().find((e) => e["type"] === "rail.outcome");
|
|
38
|
+
const payload = outcome!["payload"] as Record<string, unknown>;
|
|
39
|
+
expect(payload["status"]).toBe("settled");
|
|
40
|
+
expect(payload["receipt_id"]).toBe(settled.outcomes[0]?.receipt_id);
|
|
41
|
+
expect(payload["transaction_id"]).toBe(settled.outcomes[0]?.transaction_id);
|
|
42
|
+
expect(payload["money_moved"]).toBe(false);
|
|
43
|
+
expect(payload["sandbox"]).toBe(true);
|
|
44
|
+
// Never the provider's echo: `raw` may carry payer data the bundle does not promise to mask.
|
|
45
|
+
expect(payload["raw"]).toBeUndefined();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("a refused attempt records the rail's own code and message", async () => {
|
|
49
|
+
const h = harness({ mode: "human", rail: { refusePayees: ["escola@exemplo.com.br"] } });
|
|
50
|
+
const draft = await h.engine.draft({ items: [{ payee: "escola", amount: 185000 }] });
|
|
51
|
+
if (!draft.ok) throw new Error("refused");
|
|
52
|
+
const approved = h.engine.approve(draft.execution.id, approver);
|
|
53
|
+
await h.engine.execute(approved.id);
|
|
54
|
+
const outcome = h.bundle.readEvents().find((e) => e["type"] === "rail.outcome");
|
|
55
|
+
const payload = outcome!["payload"] as Record<string, unknown>;
|
|
56
|
+
expect(payload["status"]).toBe("failed");
|
|
57
|
+
expect(payload["code"]).toBeTypeOf("string");
|
|
58
|
+
expect(payload["message"]).toBeTypeOf("string");
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("receipt.saved names the file inside the bundle, not the machine that wrote it", async () => {
|
|
62
|
+
const { h } = await settledRun();
|
|
63
|
+
const saved = h.bundle.readEvents().find((e) => e["type"] === "receipt.saved");
|
|
64
|
+
const path = (saved!["payload"] as { path: string }).path;
|
|
65
|
+
expect(path).toMatch(/^receipts\//);
|
|
66
|
+
expect(path).not.toContain(h.bundle.dir);
|
|
67
|
+
const receipt = JSON.parse(readFileSync(join(h.bundle.dir, path), "utf8")) as { payment: { payee: string } };
|
|
68
|
+
expect(receipt.payment.payee).toBe(maskPayee("escola@exemplo.com.br"));
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("the mandate snapshot carries the version the approval artifact names", async () => {
|
|
72
|
+
const { h, settled } = await settledRun();
|
|
73
|
+
h.bundle.mandateSnapshot(h.engine.mandate);
|
|
74
|
+
const snapshot = JSON.parse(readFileSync(join(h.bundle.dir, "mandate.snapshot.json"), "utf8")) as { version: number; signature?: string };
|
|
75
|
+
expect(snapshot.version).toBe(settled.mandate.version);
|
|
76
|
+
expect(snapshot.signature).toBeUndefined();
|
|
77
|
+
expect(h.bundle.readApprovals()[0]?.mandate.version).toBe(snapshot.version);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("maskPayee is idempotent, so a reader may apply it to a value the bundle already masked", () => {
|
|
81
|
+
for (const raw of ["escola@exemplo.com.br", "+5511999990001", "12345678909", "*"]) {
|
|
82
|
+
expect(maskPayee(maskPayee(raw))).toBe(maskPayee(raw));
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { FIXED_CLOCK_ENV, InvalidFixedClockError, fixedClock, resolveFixedClock } from "../src/clock.js";
|
|
3
|
+
|
|
4
|
+
describe("fixedClock", () => {
|
|
5
|
+
it("starts at the instant and ticks one second per read, so no two events share a timestamp", () => {
|
|
6
|
+
const clock = fixedClock("2026-09-23T14:00:00-03:00");
|
|
7
|
+
expect(clock().toISOString()).toBe("2026-09-23T17:00:00.000Z");
|
|
8
|
+
expect(clock().toISOString()).toBe("2026-09-23T17:00:01.000Z");
|
|
9
|
+
expect(clock().toISOString()).toBe("2026-09-23T17:00:02.000Z");
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it("refuses what Date cannot parse, and a bare date, naming the source", () => {
|
|
13
|
+
expect(() => fixedClock("yesterday")).toThrow(InvalidFixedClockError);
|
|
14
|
+
expect(() => fixedClock("2026-09-23", FIXED_CLOCK_ENV)).toThrow(/CODESPAR_AGENT_NOW must be an ISO 8601 instant/);
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe("resolveFixedClock", () => {
|
|
19
|
+
it("prefers the flag, falls back to the environment, and is undefined (the wall clock) without either", () => {
|
|
20
|
+
expect(resolveFixedClock(undefined, {})).toBeUndefined();
|
|
21
|
+
expect(resolveFixedClock(undefined, { [FIXED_CLOCK_ENV]: " " })).toBeUndefined();
|
|
22
|
+
expect(resolveFixedClock(undefined, { [FIXED_CLOCK_ENV]: "2026-09-23T20:08:00-03:00" })!().toISOString()).toBe("2026-09-23T23:08:00.000Z");
|
|
23
|
+
expect(resolveFixedClock("2026-09-23T14:00:00-03:00", { [FIXED_CLOCK_ENV]: "2026-09-23T20:08:00-03:00" })!().toISOString()).toBe("2026-09-23T17:00:00.000Z");
|
|
24
|
+
});
|
|
25
|
+
});
|