@codespar/cli 0.14.1 → 0.17.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/commands/mandate-verify.js +98 -19
- package/dist/commands/mandate-verify.js.map +1 -1
- package/dist/index.js +17 -3
- package/dist/index.js.map +1 -1
- package/dist/mandate-codec.js +31 -20
- package/dist/mandate-codec.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
package/templates/supplier-payments-agent/packages/agent-runtime/src/commands/poll-whatsapp.ts
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `codespar-agent poll --channel whatsapp`: the conversation's loop-closer.
|
|
3
|
+
*
|
|
4
|
+
* The terminal already had one, and the reason the channel needs its own is
|
|
5
|
+
* the whole of issue #25. Over a terminal the operator and the counterparty
|
|
6
|
+
* are the same pair of eyes and the run never really ends. Over WhatsApp the
|
|
7
|
+
* debtor agrees on Tuesday and pays on Friday: the run that issued the charge
|
|
8
|
+
* exited days ago, and by the time the money lands the 24-hour customer
|
|
9
|
+
* service window has shut, so "recebemos, acordo quitado" can only go out as
|
|
10
|
+
* a template Meta approved in advance. Without this command that case cannot
|
|
11
|
+
* be run at all, which is why the confirmation in every recorded run so far
|
|
12
|
+
* happened inside the turn that issued the charge.
|
|
13
|
+
*
|
|
14
|
+
* What it does: reopens a conversation from the RECORD — the bundle of the
|
|
15
|
+
* run that held it, plus `state.db` — looks at the receivable the way the
|
|
16
|
+
* terminal poll does, and puts the outcome back into that same conversation.
|
|
17
|
+
* Nothing about which message may be sent is decided here: the channel's
|
|
18
|
+
* rules and the session window decide, and this only ASKS the window which of
|
|
19
|
+
* the two carriers it may use, because composing a message in order to watch
|
|
20
|
+
* it be refused is not a decision.
|
|
21
|
+
*
|
|
22
|
+
* Three things it deliberately does not do. It does not invent a conversation
|
|
23
|
+
* when there is nothing waiting for a payer — that is a no-op and exits 0,
|
|
24
|
+
* because a cron that fails when there is no work is a cron somebody turns
|
|
25
|
+
* off. It does not send a second confirmation when it runs twice, because the
|
|
26
|
+
* once-only cursor is in `state.db` and outlives the process. And it does not
|
|
27
|
+
* pin the emulator's clock, unlike the run that started the conversation:
|
|
28
|
+
* rewinding the provider's clock would reopen a window that really is shut.
|
|
29
|
+
*/
|
|
30
|
+
import { stdout } from "node:process";
|
|
31
|
+
import { relative } from "node:path";
|
|
32
|
+
import { ProofBundle, type ChargeInstrument, type Execution } from "@codespar/agent-core";
|
|
33
|
+
import type { Agent } from "../agent.js";
|
|
34
|
+
import { runsDir, type Setup } from "../setup.js";
|
|
35
|
+
import { waitForPayer } from "../terminal.js";
|
|
36
|
+
import { resolveConversation } from "../channels/index.js";
|
|
37
|
+
import { buildWhatsApp, simulatedCost, type WhatsAppBackendName } from "../channels/whatsapp/open.js";
|
|
38
|
+
import { EmulatorUnreachableError } from "../channels/whatsapp/emulator.js";
|
|
39
|
+
import { sessionStateFromChannelLog, type SessionState } from "../channels/whatsapp/session.js";
|
|
40
|
+
import { instrumentBodies } from "../channels/whatsapp/present.js";
|
|
41
|
+
import type { WhatsAppChannel } from "../channels/whatsapp/index.js";
|
|
42
|
+
import type { SentMessage } from "../channels/types.js";
|
|
43
|
+
|
|
44
|
+
export interface PollWhatsAppOptions {
|
|
45
|
+
agent: Agent;
|
|
46
|
+
setup: Setup;
|
|
47
|
+
conversation: string | undefined;
|
|
48
|
+
backend: WhatsAppBackendName;
|
|
49
|
+
json: boolean;
|
|
50
|
+
waitSeconds?: number | undefined;
|
|
51
|
+
simulatePayer?: boolean | undefined;
|
|
52
|
+
/** Stub only: what the fixture payer does with the receivables THIS conversation is waiting on. */
|
|
53
|
+
payer?: "pays" | "expires" | "never" | undefined;
|
|
54
|
+
now: () => Date;
|
|
55
|
+
say: (line: string) => void;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** How the outcome reached the person, or why it did not. */
|
|
59
|
+
type Delivery =
|
|
60
|
+
| { told: true; carrier: "text" | "template"; template?: string }
|
|
61
|
+
| { told: false; reason: "already_told" | "still_open" | "no_template_for_outcome" | "refused"; detail?: string };
|
|
62
|
+
|
|
63
|
+
interface Polled {
|
|
64
|
+
id: string;
|
|
65
|
+
state: string;
|
|
66
|
+
reason: string | null;
|
|
67
|
+
rounds: number;
|
|
68
|
+
seconds: number;
|
|
69
|
+
timed_out: boolean;
|
|
70
|
+
session_open: boolean;
|
|
71
|
+
delivery: Delivery;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export async function pollWhatsApp(options: PollWhatsAppOptions): Promise<number> {
|
|
75
|
+
const { agent, setup: s, say, now } = options;
|
|
76
|
+
|
|
77
|
+
let script;
|
|
78
|
+
try {
|
|
79
|
+
script = resolveConversation(agent, options.conversation);
|
|
80
|
+
} catch (err) {
|
|
81
|
+
say(err instanceof Error ? err.message : String(err));
|
|
82
|
+
return 2;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Which open executions belong to THIS conversation. The binding is the
|
|
86
|
+
// conversation's subject — the agreement alias it is allowed to name — and
|
|
87
|
+
// that is not a convenience: sending one debtor's outcome into another
|
|
88
|
+
// debtor's chat is the secrecy rule broken, and the same `subject` is what
|
|
89
|
+
// the channel already refuses other agreements by. A conversation that
|
|
90
|
+
// declares no subject binds to nothing and says so, rather than taking
|
|
91
|
+
// every open execution and hoping.
|
|
92
|
+
const open = s.engine.list({ state: "executing" }).filter((e) => e.reason === "awaiting_settlement");
|
|
93
|
+
const subject = script.subject;
|
|
94
|
+
// EVERY item, not some: an execution that mixes this conversation's
|
|
95
|
+
// agreement with another's belongs to neither, and confirming it here would
|
|
96
|
+
// put somebody else's debt in front of this person.
|
|
97
|
+
const mine = subject ? open.filter((e) => e.items.length > 0 && e.items.every((i) => i.alias === subject || i.payee === subject)) : [];
|
|
98
|
+
|
|
99
|
+
if (!subject && open.length) {
|
|
100
|
+
say(`a conversa ${script.name} nao declara subject: nao da para dizer quais execucoes sao dela, e mandar o desfecho de outra pessoa nesta conversa e exatamente o que a regra de sigilo proibe`);
|
|
101
|
+
return 2;
|
|
102
|
+
}
|
|
103
|
+
if (!mine.length) {
|
|
104
|
+
// A clean no-op: nothing is waiting, so nothing is opened. The emulator is
|
|
105
|
+
// not even contacted, which is the point — a poll with no work does no work.
|
|
106
|
+
if (options.json) stdout.write(JSON.stringify({ polled: [], conversation: script.name, channel: null }) + "\n");
|
|
107
|
+
else say(`nada aguardando pagador em ${script.name}`);
|
|
108
|
+
return 0;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// The conversation as it was left: the bundle of the run that held it. The
|
|
112
|
+
// window is counted from the person's last message on the PROVIDER's clock,
|
|
113
|
+
// which only that record holds, and the confirmation is appended THERE, so
|
|
114
|
+
// one conversation stays one record instead of ending in a second folder.
|
|
115
|
+
const { bundle, session } = conversationRecord(agent, mine);
|
|
116
|
+
if (!bundle) {
|
|
117
|
+
say(`nenhum bundle encontrado para ${mine.map((e) => e.run_id).join(", ")}: a conversa nao pode ser retomada sem o registro dela`);
|
|
118
|
+
return 1;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const built = buildWhatsApp({
|
|
122
|
+
agent,
|
|
123
|
+
setup: s,
|
|
124
|
+
conversation: { contact: script.contact, subject: script.subject },
|
|
125
|
+
backend: options.backend,
|
|
126
|
+
now,
|
|
127
|
+
say,
|
|
128
|
+
bundle,
|
|
129
|
+
// Nobody writes in a poll: the person already said what they had to say,
|
|
130
|
+
// and this run is here because the PAYER acted, not because the person did.
|
|
131
|
+
session,
|
|
132
|
+
});
|
|
133
|
+
if ("refusal" in built) {
|
|
134
|
+
for (const line of built.refusal) say(line);
|
|
135
|
+
return 1;
|
|
136
|
+
}
|
|
137
|
+
const { channel, driver, sessionKey } = built;
|
|
138
|
+
|
|
139
|
+
// Scoped to the receivables of THIS conversation: `behave` set the default
|
|
140
|
+
// for new ones, and this rewrites the fate of the ones already issued —
|
|
141
|
+
// another conversation's charge is none of this command's business.
|
|
142
|
+
if (options.payer) {
|
|
143
|
+
for (const execution of mine) {
|
|
144
|
+
for (const outcome of execution.outcomes) if (outcome.status === "accepted") s.payer?.decideFor?.(outcome.attempt_id, options.payer);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
try {
|
|
149
|
+
await channel.open();
|
|
150
|
+
} catch (err) {
|
|
151
|
+
if (err instanceof EmulatorUnreachableError) {
|
|
152
|
+
say(err.message);
|
|
153
|
+
return 1;
|
|
154
|
+
}
|
|
155
|
+
throw err;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const results: Polled[] = [];
|
|
159
|
+
try {
|
|
160
|
+
const remaining = channel.sessionRemainingSeconds;
|
|
161
|
+
say(
|
|
162
|
+
`${s.manifest.manifest.name} ${s.manifest.manifest.version} — poll no canal whatsapp (${channel.backend}) — conversa ${script.name} — janela de 24h ${
|
|
163
|
+
channel.sessionOpen ? `ABERTA (${Math.round(remaining / 60)} min restantes): mensagem livre` : "FECHADA: so template aprovado"
|
|
164
|
+
}`,
|
|
165
|
+
);
|
|
166
|
+
for (const execution of mine) {
|
|
167
|
+
const sessionOpen = channel.sessionOpen;
|
|
168
|
+
const result = await waitForPayer(execution.id, {
|
|
169
|
+
setup: s,
|
|
170
|
+
approver: { id: s.kit.labels.defaultUser, channel: "whatsapp" },
|
|
171
|
+
say,
|
|
172
|
+
waitSeconds: options.waitSeconds,
|
|
173
|
+
simulatePayer: options.simulatePayer,
|
|
174
|
+
presentInstrument: (e, n, id, instrument) => presentInstrument(channel, s, e, n, id, instrument),
|
|
175
|
+
});
|
|
176
|
+
const closed = result.execution;
|
|
177
|
+
if (closed.state !== "executing") await s.engine.collectReceipts(closed.id);
|
|
178
|
+
const delivery = await tellOutcome(channel, s, closed);
|
|
179
|
+
results.push({
|
|
180
|
+
id: closed.id,
|
|
181
|
+
state: closed.state,
|
|
182
|
+
reason: closed.reason ?? null,
|
|
183
|
+
rounds: result.rounds,
|
|
184
|
+
seconds: result.seconds,
|
|
185
|
+
timed_out: result.timed_out,
|
|
186
|
+
session_open: sessionOpen,
|
|
187
|
+
delivery,
|
|
188
|
+
});
|
|
189
|
+
say(
|
|
190
|
+
`${closed.id}: ${closed.state}${closed.reason ? ` (${closed.reason})` : ""} apos ${result.rounds} consulta(s), ${result.seconds}s — ${
|
|
191
|
+
delivery.told ? `avisado por ${delivery.carrier === "template" ? `template ${delivery.template}` : "mensagem livre"}` : `nao avisado (${delivery.reason}${delivery.detail ? `: ${delivery.detail}` : ""})`
|
|
192
|
+
}`,
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
} finally {
|
|
196
|
+
await channel.close();
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const cost = await simulatedCost(driver, sessionKey);
|
|
200
|
+
const log = channel.log();
|
|
201
|
+
const refused = log.filter((l) => l.refused).map((l) => ({ rule: l.refused!.rule, detail: l.refused!.detail }));
|
|
202
|
+
const channelSummary = {
|
|
203
|
+
name: "whatsapp",
|
|
204
|
+
backend: channel.backend,
|
|
205
|
+
conversation: script.name,
|
|
206
|
+
session_open: channel.sessionOpen,
|
|
207
|
+
messages_out: log.filter((l) => l.direction === "out" && !l.refused).length,
|
|
208
|
+
refused,
|
|
209
|
+
log: relative(process.cwd(), `${bundle.dir}/channel.jsonl`),
|
|
210
|
+
...(cost ? { simulated_cost: cost } : {}),
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
if (options.json) stdout.write(JSON.stringify({ polled: results, conversation: script.name, channel: channelSummary }) + "\n");
|
|
214
|
+
else say(`conversa em ${channelSummary.log} — ${channelSummary.messages_out} enviada(s)${refused.length ? `, ${refused.length} recusada(s)` : ""}`);
|
|
215
|
+
|
|
216
|
+
if (results.some((r) => r.timed_out)) return 3;
|
|
217
|
+
// A cycle that closed and a person who was not told is a failure worth an
|
|
218
|
+
// exit code: the record says the agreement is settled and the debtor does
|
|
219
|
+
// not know it. The other two are not failures — `already_told` is this
|
|
220
|
+
// command running twice, which is the thing it is built to be safe under,
|
|
221
|
+
// and `still_open` is a wait that ran out, which the 3 above already said.
|
|
222
|
+
return results.some((r) => !r.delivery.told && r.delivery.reason !== "already_told" && r.delivery.reason !== "still_open") ? 1 : 0;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* The bundle the conversation lives in, and where its window stood. When
|
|
227
|
+
* several runs touched the same conversation the LATEST one holds the last
|
|
228
|
+
* inbound, so that is the record the confirmation is appended to; the window
|
|
229
|
+
* itself is read across all of them, because the person's last message is the
|
|
230
|
+
* person's last message whichever run recorded it.
|
|
231
|
+
*/
|
|
232
|
+
function conversationRecord(agent: Agent, executions: readonly Execution[]): { bundle: ProofBundle | undefined; session: SessionState } {
|
|
233
|
+
const runs = runsDir(agent);
|
|
234
|
+
const seen = new Set<string>();
|
|
235
|
+
let bundle: ProofBundle | undefined;
|
|
236
|
+
let lastInboundAt: number | undefined;
|
|
237
|
+
// `list()` orders by creation, so the last execution that carries a log is the most recent record of the conversation.
|
|
238
|
+
for (const execution of executions) {
|
|
239
|
+
if (seen.has(execution.run_id)) continue;
|
|
240
|
+
seen.add(execution.run_id);
|
|
241
|
+
const opened = ProofBundle.open(runs, execution.run_id);
|
|
242
|
+
if (!opened) continue;
|
|
243
|
+
const lines = opened.readChannel();
|
|
244
|
+
if (!lines.length) continue;
|
|
245
|
+
bundle = opened;
|
|
246
|
+
const state = sessionStateFromChannelLog(lines);
|
|
247
|
+
if (state.lastInboundAt !== undefined && (lastInboundAt === undefined || state.lastInboundAt > lastInboundAt)) lastInboundAt = state.lastInboundAt;
|
|
248
|
+
}
|
|
249
|
+
return { bundle, session: { lastInboundAt } };
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* The payable artifact, the way a person can use it: the QR as an image and
|
|
254
|
+
* the copy-and-paste as its OWN message. The same shape `converse` sends,
|
|
255
|
+
* because a payer told how to pay by a poll is told the same way a payer told
|
|
256
|
+
* by a run is.
|
|
257
|
+
*
|
|
258
|
+
* It is only reached for an instrument nobody has shown yet — `markShown` is a
|
|
259
|
+
* cursor in `state.db` — so in the ordinary resumed conversation nothing is
|
|
260
|
+
* sent here at all. When it IS reached with the window shut the channel
|
|
261
|
+
* refuses it, and that refusal is the record: WhatsApp would not have carried
|
|
262
|
+
* it either.
|
|
263
|
+
*/
|
|
264
|
+
async function presentInstrument(channel: WhatsAppChannel, s: Setup, execution: Execution, instalment: number, chargeId: string, instrument: ChargeInstrument): Promise<void> {
|
|
265
|
+
for (const body of instrumentBodies(execution, instalment, chargeId, instrument, s.mandate.currency)) await channel.send(body);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* The one message per outcome, carried by whichever of the two the window
|
|
270
|
+
* allows. Both halves share `markTold`, the cursor in `state.db`, so a second
|
|
271
|
+
* poll sends nothing whichever carrier the first one used.
|
|
272
|
+
*
|
|
273
|
+
* The order matters and is deliberate: the cursor is taken BEFORE the send.
|
|
274
|
+
* Taking it after would mean a process killed between the send and the write
|
|
275
|
+
* tells the person twice, and on a channel that is a second "recebemos" for
|
|
276
|
+
* one payment. A send that is then refused is reported instead, with the
|
|
277
|
+
* rule, and it is the exit code of the command — the record says settled and
|
|
278
|
+
* the debtor does not know.
|
|
279
|
+
*/
|
|
280
|
+
async function tellOutcome(channel: WhatsAppChannel, s: Setup, execution: Execution): Promise<Delivery> {
|
|
281
|
+
// Nothing closed, so there is no outcome to carry. Not a failure and not a
|
|
282
|
+
// silence to explain: the wait ran out and the receivable is still open.
|
|
283
|
+
if (execution.state === "executing") return { told: false, reason: "still_open" };
|
|
284
|
+
|
|
285
|
+
if (channel.sessionOpen) {
|
|
286
|
+
// The kit writes lines, the channel sends messages. Joined rather than
|
|
287
|
+
// last-one-wins, so a kit that says two sentences does not lose one.
|
|
288
|
+
const lines: string[] = [];
|
|
289
|
+
const told = s.kit.announceOutcome?.(execution, s, (line) => void lines.push(line)) ?? false;
|
|
290
|
+
if (!told) return { told: false, reason: "already_told" };
|
|
291
|
+
const sent = await channel.send({ kind: "text", text: lines.join("\n") });
|
|
292
|
+
return deliveryOf(sent, "text");
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const chosen = s.kit.outcomeTemplate?.(execution);
|
|
296
|
+
if (!chosen) {
|
|
297
|
+
return {
|
|
298
|
+
told: false,
|
|
299
|
+
reason: "no_template_for_outcome",
|
|
300
|
+
detail: `a janela de 24h esta fechada e o agente nao declara template para ${execution.state}${execution.reason ? ` (${execution.reason})` : ""}`,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
const declared = channel.declaredTemplate(chosen.template);
|
|
304
|
+
if (!declared) {
|
|
305
|
+
return { told: false, reason: "no_template_for_outcome", detail: `o kit pediu o template ${chosen.template}, que channels/whatsapp/templates.json nao declara` };
|
|
306
|
+
}
|
|
307
|
+
if (!s.engine.markTold(execution.id, execution.state)) return { told: false, reason: "already_told" };
|
|
308
|
+
const sent = await channel.send({ kind: "template", template: declared.name, language: declared.language, variables: chosen.variables });
|
|
309
|
+
s.engine.note("message.debtor", execution.id, { state: execution.state, reason: execution.reason ?? null, template: declared.name, variables: chosen.variables });
|
|
310
|
+
return deliveryOf(sent, "template", declared.name);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function deliveryOf(sent: SentMessage, carrier: "text" | "template", template?: string): Delivery {
|
|
314
|
+
if (sent.refused) return { told: false, reason: "refused", detail: `${sent.refused.rule}: ${sent.refused.detail}` };
|
|
315
|
+
if (sent.state === "failed") return { told: false, reason: "refused", detail: "o provedor nao aceitou a mensagem" };
|
|
316
|
+
return { told: true, carrier, ...(template ? { template } : {}) };
|
|
317
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `codespar-agent poll [--channel terminal|whatsapp] [--wait <seconds>] [--simulate-payer] [--json]`:
|
|
3
|
+
* keeps looking at every receivable still waiting for its payer until it
|
|
4
|
+
* closes or the wait runs out. This is the loop-closer for a run that has no
|
|
5
|
+
* webhook URL; `codespar-agent webhook` is the other. Presents an instrument
|
|
6
|
+
* not yet shown, tells the payer the outcome once, fetches the paid record.
|
|
7
|
+
*
|
|
8
|
+
* `--channel` is on THIS command rather than in a second one, and the reason
|
|
9
|
+
* is that only one thing differs between the two: where the outcome message
|
|
10
|
+
* goes, and which carriers that place allows. The looking, the once-only
|
|
11
|
+
* presentation, the sandbox payer, the receipts and the terminal states are
|
|
12
|
+
* one loop — `pollUntilClosed` — and a second command would have meant a
|
|
13
|
+
* second copy of it, which is exactly how a channel ends up closing a cycle
|
|
14
|
+
* differently from the terminal.
|
|
15
|
+
*/
|
|
16
|
+
import { stderr, stdout } from "node:process";
|
|
17
|
+
import { join } from "node:path";
|
|
18
|
+
import { loadManifest, resolveFixedClock, type ChannelName } from "@codespar/agent-core";
|
|
19
|
+
import type { Agent } from "../agent.js";
|
|
20
|
+
import { setup } from "../setup.js";
|
|
21
|
+
import { announceOutcome, waitForPayer } from "../terminal.js";
|
|
22
|
+
import { pollWhatsApp } from "./poll-whatsapp.js";
|
|
23
|
+
import type { WhatsAppBackendName } from "../channels/whatsapp/open.js";
|
|
24
|
+
|
|
25
|
+
const USAGE = `codespar-agent poll [options]
|
|
26
|
+
--channel terminal|whatsapp where the outcome is told. Default terminal.
|
|
27
|
+
--conversation <name> which channels/whatsapp/<name>.json to come back to (--channel whatsapp)
|
|
28
|
+
--backend simulator|cloud-api default simulator, the local emulator (--channel whatsapp)
|
|
29
|
+
--wait <seconds> how long to keep looking
|
|
30
|
+
--simulate-payer let the sandbox payer act once the receivable is payable
|
|
31
|
+
--payer pays|expires|never what the fixture payer does when it acts (stub rail only)
|
|
32
|
+
--now <ISO 8601> pin the run's clock; env CODESPAR_AGENT_NOW is the same thing
|
|
33
|
+
--json machine output on stdout, everything else on stderr`;
|
|
34
|
+
|
|
35
|
+
interface Args {
|
|
36
|
+
channel: ChannelName;
|
|
37
|
+
conversation?: string;
|
|
38
|
+
backend?: WhatsAppBackendName;
|
|
39
|
+
wait?: number;
|
|
40
|
+
simulatePayer: boolean;
|
|
41
|
+
payer?: "pays" | "expires" | "never";
|
|
42
|
+
now?: string;
|
|
43
|
+
json: boolean;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function parsePollArgs(argv: string[]): Args {
|
|
47
|
+
const args: Args = { channel: "terminal", simulatePayer: false, json: false };
|
|
48
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
49
|
+
const a = argv[i]!;
|
|
50
|
+
const next = () => {
|
|
51
|
+
const v = argv[i + 1];
|
|
52
|
+
if (v === undefined) throw new Error(`${a} needs a value`);
|
|
53
|
+
i += 1;
|
|
54
|
+
return v;
|
|
55
|
+
};
|
|
56
|
+
if (a === "--json") args.json = true;
|
|
57
|
+
else if (a === "--simulate-payer") args.simulatePayer = true;
|
|
58
|
+
else if (a === "--wait") {
|
|
59
|
+
const v = Number(next());
|
|
60
|
+
if (!Number.isFinite(v) || v < 0) throw new Error("--wait must be a number of seconds");
|
|
61
|
+
args.wait = v;
|
|
62
|
+
} else if (a === "--channel") {
|
|
63
|
+
const v = next();
|
|
64
|
+
if (v !== "terminal" && v !== "whatsapp") throw new Error("--channel must be terminal or whatsapp");
|
|
65
|
+
args.channel = v;
|
|
66
|
+
} else if (a === "--backend") {
|
|
67
|
+
const v = next();
|
|
68
|
+
if (v !== "simulator" && v !== "cloud-api") throw new Error("--backend must be simulator or cloud-api");
|
|
69
|
+
args.backend = v;
|
|
70
|
+
} else if (a === "--payer") {
|
|
71
|
+
const v = next();
|
|
72
|
+
if (v !== "pays" && v !== "expires" && v !== "never") throw new Error("--payer must be pays, expires or never");
|
|
73
|
+
args.payer = v;
|
|
74
|
+
} else if (a === "--conversation") args.conversation = next();
|
|
75
|
+
else if (a === "--now") args.now = next();
|
|
76
|
+
else throw new Error(`unknown argument ${a}`);
|
|
77
|
+
}
|
|
78
|
+
if (args.channel !== "whatsapp" && (args.backend !== undefined || args.conversation !== undefined)) {
|
|
79
|
+
throw new Error("--backend and --conversation belong to --channel whatsapp");
|
|
80
|
+
}
|
|
81
|
+
return args;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export async function poll(agent: Agent, argv: string[]): Promise<number> {
|
|
85
|
+
const say = (l: string) => stderr.write(l + "\n");
|
|
86
|
+
let args: Args;
|
|
87
|
+
let now: (() => Date) | undefined;
|
|
88
|
+
try {
|
|
89
|
+
args = parsePollArgs(argv);
|
|
90
|
+
now = resolveFixedClock(args.now, process.env);
|
|
91
|
+
} catch (err) {
|
|
92
|
+
say(`${err instanceof Error ? err.message : String(err)}\n${USAGE}`);
|
|
93
|
+
return 2;
|
|
94
|
+
}
|
|
95
|
+
if (args.channel === "whatsapp" && !loadManifest(join(agent.dir, "agent.yaml")).manifest.channels.includes("whatsapp")) {
|
|
96
|
+
say(`${agent.slug} does not declare the whatsapp channel in agent.yaml`);
|
|
97
|
+
return 2;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const s = setup(agent, { say, runId: `run_poll_${Date.now().toString(36)}`, ...(now ? { now } : {}) });
|
|
101
|
+
// The same flag `start` has, and it means more here: a receivable nobody
|
|
102
|
+
// paid reaches its due date BETWEEN two runs, never inside one, so "what
|
|
103
|
+
// happens when it expires" is a question only a poll can be asked.
|
|
104
|
+
if (args.payer) s.payer?.behave(args.payer);
|
|
105
|
+
try {
|
|
106
|
+
if (args.channel === "whatsapp") {
|
|
107
|
+
return await pollWhatsApp({
|
|
108
|
+
agent,
|
|
109
|
+
setup: s,
|
|
110
|
+
conversation: args.conversation,
|
|
111
|
+
backend: args.backend ?? "simulator",
|
|
112
|
+
json: args.json,
|
|
113
|
+
waitSeconds: args.wait,
|
|
114
|
+
simulatePayer: args.simulatePayer,
|
|
115
|
+
...(args.payer ? { payer: args.payer } : {}),
|
|
116
|
+
now: now ?? (() => new Date()),
|
|
117
|
+
say,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
// `behave` only changes the default for receivables the rail has not
|
|
121
|
+
// looked at, and by now it has looked at these; `decideFor` is what
|
|
122
|
+
// rewrites the fate of one that already exists.
|
|
123
|
+
if (args.payer) {
|
|
124
|
+
for (const open of s.engine.list({ state: "executing" })) {
|
|
125
|
+
for (const outcome of open.outcomes) if (outcome.status === "accepted") s.payer?.decideFor?.(outcome.attempt_id, args.payer);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const tell = (l: string) => void (args.json ? stderr : stdout).write(l + "\n");
|
|
129
|
+
const results = [];
|
|
130
|
+
for (const open of s.engine.list({ state: "executing" })) {
|
|
131
|
+
if (open.reason !== "awaiting_settlement") continue;
|
|
132
|
+
const r = await waitForPayer(open.id, { setup: s, approver: { id: s.kit.labels.defaultUser, channel: "terminal" }, say, tell, waitSeconds: args.wait, simulatePayer: args.simulatePayer });
|
|
133
|
+
announceOutcome(r.execution, s, tell);
|
|
134
|
+
if (r.execution.state !== "executing") await s.engine.collectReceipts(r.execution.id);
|
|
135
|
+
results.push({ id: r.execution.id, state: r.execution.state, reason: r.execution.reason ?? null, rounds: r.rounds, seconds: r.seconds, timed_out: r.timed_out });
|
|
136
|
+
say(`${r.execution.id}: ${r.execution.state}${r.execution.reason ? ` (${r.execution.reason})` : ""} after ${r.rounds} look(s), ${r.seconds}s`);
|
|
137
|
+
}
|
|
138
|
+
if (args.json) stdout.write(JSON.stringify({ polled: results }) + "\n");
|
|
139
|
+
else if (!results.length) say("nothing waiting for a payer");
|
|
140
|
+
return results.some((r) => r.timed_out) ? 3 : 0;
|
|
141
|
+
} finally {
|
|
142
|
+
s.close();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `codespar-agent reconcile [--json]`: compares local state with the rail.
|
|
3
|
+
* Names executions without an outcome, attempts the rail never saw, sealed
|
|
4
|
+
* outcomes the rail holds that the bundle does not. Read-only unless an
|
|
5
|
+
* execution is in `executing`, which it closes from what the rail says.
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { stderr, stdout } from "node:process";
|
|
10
|
+
import type { Agent } from "../agent.js";
|
|
11
|
+
import { runsDir, setup } from "../setup.js";
|
|
12
|
+
|
|
13
|
+
export async function reconcile(agent: Agent, argv: string[]): Promise<number> {
|
|
14
|
+
const json = argv.includes("--json");
|
|
15
|
+
const awaitsPayer = agent.settlement === "await-payer";
|
|
16
|
+
const say = (l: string) => stderr.write(l + "\n");
|
|
17
|
+
const s = setup(agent, { say, runId: `run_reconcile_${Date.now().toString(36)}` });
|
|
18
|
+
try {
|
|
19
|
+
const findings: Array<{ execution_id: string; kind: string; detail: string }> = [];
|
|
20
|
+
for (const e of s.engine.list()) {
|
|
21
|
+
if (e.state === "executing") {
|
|
22
|
+
const closed = await s.engine.reconcile(e.id);
|
|
23
|
+
const kind = closed.state === "executing" ? (awaitsPayer && closed.reason === "awaiting_settlement" ? "awaiting_payer" : "still_uncertain") : "closed_from_rail";
|
|
24
|
+
findings.push({ execution_id: e.id, kind, detail: `executing -> ${closed.state}${awaitsPayer && closed.detail ? ` (${closed.detail})` : ""}` });
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
for (const o of e.outcomes) {
|
|
28
|
+
if (o.receipt_id && !existsSync(join(runsDir(agent), e.run_id, "receipts", `${o.receipt_id}.json`))) {
|
|
29
|
+
findings.push({ execution_id: e.id, kind: s.kit.labels.missingReceiptKind, detail: s.kit.labels.missingReceiptDetail(o.receipt_id, e.run_id) });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const outbox = s.store.getOutbox(e.idempotency_key);
|
|
33
|
+
if (e.state === "settled" && outbox?.status !== "done") findings.push({ execution_id: e.id, kind: "outbox_mismatch", detail: `settled but outbox is ${outbox?.status ?? "absent"}` });
|
|
34
|
+
}
|
|
35
|
+
for (const f of findings) say(`${f.kind} ${f.execution_id}: ${f.detail}`);
|
|
36
|
+
if (json) stdout.write(JSON.stringify({ executions: s.engine.list().length, findings }) + "\n");
|
|
37
|
+
else say(findings.length ? `${findings.length} finding(s)` : "local state and rail agree");
|
|
38
|
+
return 0;
|
|
39
|
+
} finally {
|
|
40
|
+
s.close();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `codespar-agent rerun <run-id> [--json]`: replays a recorded run against
|
|
3
|
+
* the deterministic provider and the stub rail, with no network, in a fresh
|
|
4
|
+
* state, and compares the sequence of states with the original bundle. The
|
|
5
|
+
* model's outputs are the recording; every decision of the core is recomputed.
|
|
6
|
+
*/
|
|
7
|
+
import { mkdtempSync } from "node:fs";
|
|
8
|
+
import { tmpdir } from "node:os";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { stderr, stdout } from "node:process";
|
|
11
|
+
import { ProofBundle, type ApprovalMode, type Execution } from "@codespar/agent-core";
|
|
12
|
+
import type { Agent } from "../agent.js";
|
|
13
|
+
import { runsDir, setup } from "../setup.js";
|
|
14
|
+
import { handleExecution } from "../terminal.js";
|
|
15
|
+
|
|
16
|
+
export async function rerun(agent: Agent, argv: string[]): Promise<number> {
|
|
17
|
+
const json = argv.includes("--json");
|
|
18
|
+
const runId = argv.find((a) => !a.startsWith("--"));
|
|
19
|
+
const say = (l: string) => stderr.write(l + "\n");
|
|
20
|
+
if (!runId) {
|
|
21
|
+
say("usage: npm run rerun <run-id> [--json]");
|
|
22
|
+
return 2;
|
|
23
|
+
}
|
|
24
|
+
const original = ProofBundle.open(runsDir(agent), runId);
|
|
25
|
+
if (!original) {
|
|
26
|
+
say(`no bundle at runs/${runId}`);
|
|
27
|
+
return 1;
|
|
28
|
+
}
|
|
29
|
+
const meta = original.readMeta() ?? {};
|
|
30
|
+
const mode = (meta["mode"] as ApprovalMode | undefined) ?? "human";
|
|
31
|
+
const events = original.readEvents();
|
|
32
|
+
const originalTrail = events.filter((e) => e["type"] === "execution.transition").map((e) => (e["payload"] as { to: string }).to);
|
|
33
|
+
const originalDecisions = events.filter((e) => e["type"] === "approval.created").map((e) => ((e["payload"] as { approver: { type: string } }).approver.type === "person" ? "approve" : "mandate"));
|
|
34
|
+
const userTurns = original.readTranscript().filter((l) => l.kind === "user").map((l) => l["text"] as string);
|
|
35
|
+
const transcriptPath = join(original.dir, "transcript.jsonl");
|
|
36
|
+
const plan = agent.kit.rerunPlan?.(events) ?? {};
|
|
37
|
+
|
|
38
|
+
const s = setup(agent, {
|
|
39
|
+
mode,
|
|
40
|
+
rail: "stub",
|
|
41
|
+
provider: "replay",
|
|
42
|
+
transcript: transcriptPath,
|
|
43
|
+
runId: `${runId}_rerun_${Date.now().toString(36)}`,
|
|
44
|
+
stateDir: mkdtempSync(join(tmpdir(), `${agent.slug}-rerun-`)),
|
|
45
|
+
stubRail: plan.stubRail,
|
|
46
|
+
say,
|
|
47
|
+
});
|
|
48
|
+
try {
|
|
49
|
+
let decisionIndex = 0;
|
|
50
|
+
const runtime = s.makeRuntime();
|
|
51
|
+
const loop = s.makeLoop(runtime, (execution: Execution) => {
|
|
52
|
+
const decision = execution.state === "awaiting_approval" ? (originalDecisions[decisionIndex++] === "approve" ? "approve" : "deny") : "none";
|
|
53
|
+
return handleExecution(execution, {
|
|
54
|
+
setup: s,
|
|
55
|
+
approver: { id: "usr_rerun", channel: "terminal" },
|
|
56
|
+
decision,
|
|
57
|
+
say,
|
|
58
|
+
...(agent.settlement === "await-payer" ? { tell: () => undefined, simulatePayer: plan.simulatePayer ?? false } : {}),
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
for (const text of userTurns) await loop.turn(text);
|
|
62
|
+
const trail = s.store.listEvents({ run_id: s.runId }).filter((e) => e.type === "execution.transition").map((e) => (e.payload as { to: string }).to);
|
|
63
|
+
const outcomesOf = (list: Record<string, unknown>[]) => list.filter((e) => e["type"] === "rail.outcome").map((e) => (e["payload"] as { status: string }).status);
|
|
64
|
+
const originalOutcomes = outcomesOf(events);
|
|
65
|
+
const rerunOutcomes = outcomesOf(s.bundle.readEvents());
|
|
66
|
+
const sameTrail = JSON.stringify(trail) === JSON.stringify(originalTrail);
|
|
67
|
+
const same = agent.kit.rerunComparesOutcomes ? sameTrail && JSON.stringify(rerunOutcomes) === JSON.stringify(originalOutcomes) : sameTrail;
|
|
68
|
+
if (json) {
|
|
69
|
+
stdout.write(
|
|
70
|
+
JSON.stringify({
|
|
71
|
+
run_id: runId,
|
|
72
|
+
rerun_id: s.runId,
|
|
73
|
+
same_states: same,
|
|
74
|
+
original: originalTrail,
|
|
75
|
+
rerun: trail,
|
|
76
|
+
...(agent.kit.rerunComparesOutcomes ? { original_outcomes: originalOutcomes, rerun_outcomes: rerunOutcomes } : {}),
|
|
77
|
+
bundle_dir: s.bundle.dir,
|
|
78
|
+
}) + "\n",
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
say(same ? `rerun ok: ${trail.length} transition(s), same sequence as ${runId}` : `rerun DIFFERS: original ${JSON.stringify(originalTrail)} vs rerun ${JSON.stringify(trail)}`);
|
|
82
|
+
return same ? 0 : 1;
|
|
83
|
+
} finally {
|
|
84
|
+
s.close();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `codespar-agent resume [--json]`: after a crash or a restart. Executions
|
|
3
|
+
* left in `executing` are reconciled against the rail (idempotent on
|
|
4
|
+
* attempt_id), never repeated; stale open ones expire.
|
|
5
|
+
*/
|
|
6
|
+
import { stderr, stdout } from "node:process";
|
|
7
|
+
import type { Execution } from "@codespar/agent-core";
|
|
8
|
+
import type { Agent } from "../agent.js";
|
|
9
|
+
import { setup } from "../setup.js";
|
|
10
|
+
|
|
11
|
+
export async function resume(agent: Agent, argv: string[]): Promise<number> {
|
|
12
|
+
const json = argv.includes("--json");
|
|
13
|
+
const awaitsPayer = agent.settlement === "await-payer";
|
|
14
|
+
const say = (l: string) => stderr.write(l + "\n");
|
|
15
|
+
const s = setup(agent, { say, runId: `run_resume_${Date.now().toString(36)}` });
|
|
16
|
+
try {
|
|
17
|
+
const closed: Execution[] = [];
|
|
18
|
+
// Only resume dispatches, and only what the outbox proves was never sent; everything else is reconciled from the rail.
|
|
19
|
+
for (const stuck of s.engine.list({ state: "executing" })) {
|
|
20
|
+
const e = await s.engine.resumePending(stuck.id);
|
|
21
|
+
closed.push(e);
|
|
22
|
+
say(e.state === "executing" ? s.kit.labels.stillExecuting(e) : `${e.id}: executing -> ${e.state}`);
|
|
23
|
+
}
|
|
24
|
+
const expired = s.engine.expireStale().map((e) => ({ id: e.id, state: e.state }));
|
|
25
|
+
for (const e of expired) say(`${e.id}: -> expired`);
|
|
26
|
+
const open = s.engine.list({ state: ["awaiting_approval", "approved"] }).map((e) => ({ id: e.id, state: e.state }));
|
|
27
|
+
for (const e of open) say(`${e.id}: still ${e.state}; decide it with npm run approve ${e.id} / npm run deny ${e.id}`);
|
|
28
|
+
if (json) {
|
|
29
|
+
const resumed = closed.map((e) => ({
|
|
30
|
+
id: e.id,
|
|
31
|
+
state: e.state,
|
|
32
|
+
...(awaitsPayer ? { reason: e.reason ?? null } : {}),
|
|
33
|
+
detail: e.detail ?? null,
|
|
34
|
+
...(awaitsPayer ? { charge_ids: e.outcomes.map((o) => o.transaction_id ?? null) } : {}),
|
|
35
|
+
receipt_ids: e.outcomes.filter((o) => o.receipt_id).map((o) => o.receipt_id),
|
|
36
|
+
}));
|
|
37
|
+
stdout.write(JSON.stringify({ resumed, expired, open, bundle_dir: s.bundle.dir }) + "\n");
|
|
38
|
+
} else say(closed.length || expired.length ? "resume done" : "nothing to resume");
|
|
39
|
+
return closed.some((e) => e.state === "executing" && (!awaitsPayer || e.reason !== "awaiting_settlement")) ? 3 : 0;
|
|
40
|
+
} finally {
|
|
41
|
+
s.close();
|
|
42
|
+
}
|
|
43
|
+
}
|