|
| 1 | +// ───────────────────────────────────────────────────────────────────────────── |
| 2 | +// authority-layer simulate |
| 3 | +// |
| 4 | +// Runs a short simulated agent execution that intentionally exceeds the |
| 5 | +// budget cap so developers can see enforcement halt output without writing |
| 6 | +// any code. |
| 7 | +// |
| 8 | +// Usage: |
| 9 | +// npx authority-layer simulate |
| 10 | +// ───────────────────────────────────────────────────────────────────────────── |
| 11 | + |
| 12 | +import { AuthorityLayer } from "../AuthorityLayer"; |
| 13 | +import { EnforcementHalt } from "../EnforcementHalt"; |
| 14 | + |
| 15 | +const RESET = "\x1b[0m"; |
| 16 | +const GREEN = "\x1b[1;32m"; |
| 17 | +const RED = "\x1b[1;31m"; |
| 18 | +const YELLOW = "\x1b[1;33m"; |
| 19 | +const BOLD = "\x1b[1m"; |
| 20 | +const DIM = "\x1b[2m"; |
| 21 | + |
| 22 | +export async function runSimulate(): Promise<void> { |
| 23 | + console.log(`\n${BOLD}AuthorityLayer Simulation${RESET}`); |
| 24 | + console.log(`${DIM}Demonstrating runtime enforcement.${RESET}\n`); |
| 25 | + |
| 26 | + const authority = new AuthorityLayer({ |
| 27 | + budget: { dailyUSD: 0.05 }, |
| 28 | + loopGuard: { maxToolCallsPerRun: 10 }, |
| 29 | + toolThrottle: { maxCallsPerMinute: 100 }, |
| 30 | + }); |
| 31 | + |
| 32 | + console.log(`${DIM}Config: $0.05 budget cap · 10 calls/run max · 100 calls/min${RESET}\n`); |
| 33 | + console.log("Starting simulated agent run...\n"); |
| 34 | + |
| 35 | + let callCount = 0; |
| 36 | + |
| 37 | + try { |
| 38 | + await authority.wrap(async () => { |
| 39 | + // 7 calls × $0.01 = $0.07 — exceeds the $0.05 cap after call 6 |
| 40 | + for (let i = 1; i <= 7; i++) { |
| 41 | + callCount++; |
| 42 | + await authority.tool("llm.chat", async () => "LLM response"); |
| 43 | + console.log(` Tool call #${i} ${DIM}llm.chat${RESET}`); |
| 44 | + authority.recordSpend(0.01); |
| 45 | + } |
| 46 | + }); |
| 47 | + } catch (err) { |
| 48 | + if (err instanceof EnforcementHalt) { |
| 49 | + console.log(`\n${RED}${BOLD}⛔ Execution halted by AuthorityLayer${RESET}\n`); |
| 50 | + const h = err.enforcement; |
| 51 | + const display = { |
| 52 | + status: h.status, |
| 53 | + reason: h.reason, |
| 54 | + limit: Math.round(h.limit * 100) / 100, |
| 55 | + spent: Math.round(h.spent * 100) / 100, |
| 56 | + event_id: h.event_id, |
| 57 | + }; |
| 58 | + console.log(YELLOW + JSON.stringify(display, null, 2) + RESET); |
| 59 | + } else { |
| 60 | + throw err; |
| 61 | + } |
| 62 | + } |
| 63 | + |
| 64 | + // ── Integrity check ─────────────────────────────────────────────────────── |
| 65 | + |
| 66 | + const valid = authority.verifyChain(); |
| 67 | + const chain = authority.getChain(); |
| 68 | + |
| 69 | + console.log(`\n${DIM}─── Event chain ${"─".repeat(44)}${RESET}`); |
| 70 | + for (const event of chain) { |
| 71 | + const ts = new Date(event.timestamp).toISOString().slice(11, 23); |
| 72 | + console.log(` ${DIM}[${ts}]${RESET} ${event.type.padEnd(20)} ${DIM}${event.event_id}${RESET}`); |
| 73 | + } |
| 74 | + |
| 75 | + console.log(); |
| 76 | + if (valid) { |
| 77 | + console.log(`Event chain integrity: ${GREEN}${BOLD}VERIFIED${RESET}`); |
| 78 | + } else { |
| 79 | + console.log(`Event chain integrity: ${RED}${BOLD}TAMPERED${RESET}`); |
| 80 | + } |
| 81 | + console.log(`Total events: ${chain.length}\n`); |
| 82 | +} |
0 commit comments