@useagentpay/sdk 0.1.2 → 0.1.3

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_tsx@4.21.0_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","../src/errors.ts","../src/utils/paths.ts","../src/auth/keypair.ts","../src/auth/mandate.ts","../src/transactions/poller.ts","../src/server/approval-html.ts","../src/utils/open-browser.ts","../src/server/approval-server.ts","../src/server/passphrase-html.ts","../src/server/passphrase-server.ts","../src/index.ts","../src/utils/ids.ts","../src/utils/display.ts","../src/vault/vault.ts","../src/budget/budget.ts","../src/transactions/manager.ts","../src/audit/logger.ts","../src/executor/executor.ts","../src/executor/placeholder.ts","../src/executor/providers/local-provider.ts","../src/server/setup-server.ts","../src/server/setup-html.ts","../src/server/index.ts","../src/server/html.ts","../src/server/routes.ts","../src/utils/prompt.ts","../src/agentpay.ts"],"sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","export class NotSetupError extends Error {\n readonly code = 'NOT_SETUP';\n constructor(message = 'AgentPay has not been set up yet. Run `agentpay setup` first.') {\n super(message);\n this.name = 'NotSetupError';\n }\n}\n\nexport class DecryptError extends Error {\n readonly code = 'DECRYPT_FAILED';\n constructor(message = 'Failed to decrypt credentials. Wrong passphrase or corrupted file.') {\n super(message);\n this.name = 'DecryptError';\n }\n}\n\nexport class InsufficientBalanceError extends Error {\n readonly code = 'INSUFFICIENT_BALANCE';\n constructor(amount?: number, balance?: number) {\n const msg = amount !== undefined && balance !== undefined\n ? `Insufficient balance: requested $${amount.toFixed(2)} but only $${balance.toFixed(2)} available.`\n : 'Insufficient balance for this transaction.';\n super(msg);\n this.name = 'InsufficientBalanceError';\n }\n}\n\nexport class ExceedsTxLimitError extends Error {\n readonly code = 'EXCEEDS_TX_LIMIT';\n constructor(amount?: number, limit?: number) {\n const msg = amount !== undefined && limit !== undefined\n ? `Amount $${amount.toFixed(2)} exceeds per-transaction limit of $${limit.toFixed(2)}.`\n : 'Amount exceeds per-transaction limit.';\n super(msg);\n this.name = 'ExceedsTxLimitError';\n }\n}\n\nexport class NotApprovedError extends Error {\n readonly code = 'NOT_APPROVED';\n constructor(txId?: string) {\n super(txId ? `Transaction ${txId} has not been approved.` : 'Transaction has not been approved.');\n this.name = 'NotApprovedError';\n }\n}\n\nexport class InvalidMandateError extends Error {\n readonly code = 'INVALID_MANDATE';\n constructor(message = 'Purchase mandate signature verification failed.') {\n super(message);\n this.name = 'InvalidMandateError';\n }\n}\n\nexport class AlreadyExecutedError extends Error {\n readonly code = 'ALREADY_EXECUTED';\n constructor(txId?: string) {\n super(txId ? `Transaction ${txId} has already been executed.` : 'Transaction has already been executed.');\n this.name = 'AlreadyExecutedError';\n }\n}\n\nexport class CheckoutFailedError extends Error {\n readonly code = 'CHECKOUT_FAILED';\n constructor(message = 'Failed to complete checkout.') {\n super(message);\n this.name = 'CheckoutFailedError';\n }\n}\n\nexport class TimeoutError extends Error {\n readonly code = 'TIMEOUT';\n constructor(message = 'Operation timed out.') {\n super(message);\n this.name = 'TimeoutError';\n }\n}\n","import { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { existsSync } from 'node:fs';\n\nexport function getHomePath(): string {\n if (process.env.AGENTPAY_HOME) return process.env.AGENTPAY_HOME;\n const local = join(process.cwd(), 'agentpay');\n if (existsSync(local)) return local;\n return join(homedir(), '.agentpay');\n}\n\nexport function getCredentialsPath(): string {\n return join(getHomePath(), 'credentials.enc');\n}\n\nexport function getKeysPath(): string {\n return join(getHomePath(), 'keys');\n}\n\nexport function getPublicKeyPath(): string {\n return join(getKeysPath(), 'public.pem');\n}\n\nexport function getPrivateKeyPath(): string {\n return join(getKeysPath(), 'private.pem');\n}\n\nexport function getWalletPath(): string {\n return join(getHomePath(), 'wallet.json');\n}\n\nexport function getTransactionsPath(): string {\n return join(getHomePath(), 'transactions.json');\n}\n\nexport function getAuditPath(): string {\n return join(getHomePath(), 'audit.log');\n}\n","import { generateKeyPairSync, createPublicKey } from 'node:crypto';\nimport { readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type { KeyPair } from './types.js';\nimport { getPublicKeyPath, getPrivateKeyPath } from '../utils/paths.js';\n\nexport function generateKeyPair(passphrase: string): KeyPair {\n const { publicKey, privateKey } = generateKeyPairSync('ed25519', {\n publicKeyEncoding: { type: 'spki', format: 'pem' },\n privateKeyEncoding: {\n type: 'pkcs8',\n format: 'pem',\n cipher: 'aes-256-cbc',\n passphrase,\n },\n });\n\n return { publicKey, privateKey };\n}\n\nexport function saveKeyPair(keys: KeyPair, publicPath?: string, privatePath?: string): void {\n const pubPath = publicPath ?? getPublicKeyPath();\n const privPath = privatePath ?? getPrivateKeyPath();\n\n mkdirSync(dirname(pubPath), { recursive: true });\n writeFileSync(pubPath, keys.publicKey, { mode: 0o644 });\n writeFileSync(privPath, keys.privateKey, { mode: 0o600 });\n}\n\nexport function loadPublicKey(path?: string): string {\n return readFileSync(path ?? getPublicKeyPath(), 'utf8');\n}\n\nexport function loadPrivateKey(path?: string): string {\n return readFileSync(path ?? getPrivateKeyPath(), 'utf8');\n}\n","import { createHash, createPrivateKey, createPublicKey, sign, verify } from 'node:crypto';\nimport type { PurchaseMandate, TransactionDetails } from './types.js';\nimport { InvalidMandateError } from '../errors.js';\n\nfunction hashTransactionDetails(details: TransactionDetails): string {\n const canonical = JSON.stringify({\n txId: details.txId,\n merchant: details.merchant,\n amount: details.amount,\n description: details.description,\n timestamp: details.timestamp,\n });\n return createHash('sha256').update(canonical).digest('hex');\n}\n\nexport function createMandate(\n txDetails: TransactionDetails,\n privateKeyPem: string,\n passphrase: string,\n): PurchaseMandate {\n const txHash = hashTransactionDetails(txDetails);\n const data = Buffer.from(txHash);\n\n const privateKey = createPrivateKey({\n key: privateKeyPem,\n format: 'pem',\n type: 'pkcs8',\n passphrase,\n });\n\n const signature = sign(null, data, privateKey);\n\n const publicKey = createPublicKey(privateKey);\n const publicKeyPem = publicKey.export({ type: 'spki', format: 'pem' }) as string;\n\n return {\n txId: txDetails.txId,\n txHash,\n signature: signature.toString('base64'),\n publicKey: publicKeyPem,\n timestamp: new Date().toISOString(),\n };\n}\n\nexport function verifyMandate(mandate: PurchaseMandate, txDetails: TransactionDetails): boolean {\n try {\n const txHash = hashTransactionDetails(txDetails);\n if (txHash !== mandate.txHash) return false;\n\n const data = Buffer.from(txHash);\n const signature = Buffer.from(mandate.signature, 'base64');\n const publicKey = createPublicKey({\n key: mandate.publicKey,\n format: 'pem',\n type: 'spki',\n });\n\n return verify(null, data, publicKey, signature);\n } catch {\n return false;\n }\n}\n","import type { Transaction } from './types.js';\nimport type { TransactionManager } from './manager.js';\nimport { TimeoutError } from '../errors.js';\n\nexport interface PollOptions {\n pollInterval?: number;\n timeout?: number;\n}\n\nexport async function waitForApproval(\n txId: string,\n manager: TransactionManager,\n options?: PollOptions,\n): Promise<{ status: 'approved' | 'rejected'; reason?: string }> {\n const interval = options?.pollInterval ?? 2000;\n const timeout = options?.timeout ?? 300_000;\n const deadline = Date.now() + timeout;\n\n while (Date.now() < deadline) {\n const tx = manager.get(txId);\n if (!tx) throw new Error(`Transaction ${txId} not found.`);\n\n if (tx.status === 'approved') return { status: 'approved' };\n if (tx.status === 'rejected') return { status: 'rejected', reason: tx.rejectionReason };\n\n await new Promise((resolve) => setTimeout(resolve, interval));\n }\n\n throw new TimeoutError(`Timed out waiting for approval of ${txId}`);\n}\n","import type { Transaction } from '../transactions/types.js';\n\nfunction esc(s: string): string {\n return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n}\n\nfunction formatCurrency(n: number): string {\n return '$' + n.toFixed(2);\n}\n\nexport function getApprovalHtml(token: string, tx: Transaction): string {\n const lines: string[] = [];\n lines.push(`<div class=\"detail\"><span class=\"detail-label\">Merchant</span><span class=\"detail-value\">${esc(tx.merchant)}</span></div>`);\n lines.push(`<div class=\"detail\"><span class=\"detail-label\">Amount</span><span class=\"detail-value\">${formatCurrency(tx.amount)}</span></div>`);\n lines.push(`<div class=\"detail\"><span class=\"detail-label\">Description</span><span class=\"detail-value\">${esc(tx.description)}</span></div>`);\n if (tx.url) {\n lines.push(`<div class=\"detail\"><span class=\"detail-label\">URL</span><span class=\"detail-value\"><a href=\"${esc(tx.url)}\" target=\"_blank\" rel=\"noopener\" style=\"color:#111;\">${esc(tx.url)}</a></span></div>`);\n }\n lines.push(`<div class=\"detail\"><span class=\"detail-label\">Transaction</span><span class=\"detail-value\" style=\"font-family:monospace;font-size:12px;\">${esc(tx.id)}</span></div>`);\n const contextHtml = `<div class=\"card context-card\">${lines.join('')}</div>`;\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>AgentPay — Approve Purchase</title>\n<style>\n *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n background: #f5f5f5;\n color: #111;\n min-height: 100vh;\n display: flex;\n justify-content: center;\n padding: 40px 16px;\n }\n .container { width: 100%; max-width: 420px; }\n h1 { font-size: 24px; font-weight: 700; margin-bottom: 4px; }\n .subtitle { color: #666; font-size: 14px; margin-bottom: 24px; }\n .card {\n background: #fff;\n border-radius: 8px;\n padding: 24px;\n margin-bottom: 16px;\n border: 1px solid #e0e0e0;\n }\n .context-card { padding: 16px 20px; }\n .detail {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 0;\n border-bottom: 1px solid #f0f0f0;\n }\n .detail:last-child { border-bottom: none; }\n .detail-label { font-size: 13px; color: #666; }\n .detail-value { font-size: 14px; font-weight: 600; }\n label { display: block; font-size: 13px; font-weight: 500; color: #333; margin-bottom: 6px; }\n input[type=\"password\"], textarea {\n width: 100%;\n padding: 12px 14px;\n border: 1px solid #d0d0d0;\n border-radius: 8px;\n font-size: 15px;\n font-family: inherit;\n outline: none;\n transition: border-color 0.15s;\n }\n input[type=\"password\"]:focus, textarea:focus { border-color: #111; }\n textarea { resize: vertical; min-height: 60px; margin-top: 8px; }\n .btn-row { display: flex; gap: 12px; margin-top: 16px; }\n .btn-approve, .btn-deny {\n flex: 1;\n padding: 12px;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: opacity 0.15s;\n }\n .btn-approve { background: #111; color: #fff; }\n .btn-approve:hover { opacity: 0.85; }\n .btn-approve:disabled { opacity: 0.5; cursor: not-allowed; }\n .btn-deny { background: #fff; color: #c62828; border: 2px solid #c62828; }\n .btn-deny:hover { opacity: 0.85; }\n .btn-deny:disabled { opacity: 0.5; cursor: not-allowed; }\n .error { color: #c62828; font-size: 13px; margin-top: 10px; }\n .success-screen {\n text-align: center;\n padding: 40px 0;\n }\n .checkmark { font-size: 48px; margin-bottom: 16px; }\n .success-msg { font-size: 16px; font-weight: 600; margin-bottom: 8px; }\n .success-hint { font-size: 13px; color: #666; }\n .hidden { display: none; }\n .reason-section { margin-top: 12px; }\n</style>\n</head>\n<body>\n<div class=\"container\">\n <div id=\"form-view\">\n <h1>AgentPay</h1>\n <p class=\"subtitle\">Approve Purchase</p>\n ${contextHtml}\n <div class=\"card\">\n <label for=\"passphrase\">Passphrase</label>\n <input type=\"password\" id=\"passphrase\" placeholder=\"Enter your passphrase\" autofocus>\n <div id=\"reason-section\" class=\"reason-section hidden\">\n <label for=\"reason\">Reason (optional)</label>\n <textarea id=\"reason\" placeholder=\"Why are you denying this purchase?\"></textarea>\n </div>\n <div id=\"error\" class=\"error hidden\"></div>\n <div class=\"btn-row\">\n <button class=\"btn-approve\" id=\"btn-approve\">Approve</button>\n <button class=\"btn-deny\" id=\"btn-deny\">Deny</button>\n </div>\n </div>\n </div>\n <div id=\"success-view\" class=\"hidden\">\n <h1>AgentPay</h1>\n <p class=\"subtitle\" id=\"success-subtitle\"></p>\n <div class=\"card\">\n <div class=\"success-screen\">\n <div class=\"checkmark\" id=\"success-icon\"></div>\n <div class=\"success-msg\" id=\"success-msg\"></div>\n <div class=\"success-hint\">This tab will close automatically.</div>\n </div>\n </div>\n </div>\n</div>\n<script>\n(function() {\n var token = ${JSON.stringify(token)};\n var form = document.getElementById('form-view');\n var successView = document.getElementById('success-view');\n var input = document.getElementById('passphrase');\n var btnApprove = document.getElementById('btn-approve');\n var btnDeny = document.getElementById('btn-deny');\n var errDiv = document.getElementById('error');\n var reasonSection = document.getElementById('reason-section');\n var reasonInput = document.getElementById('reason');\n var successSubtitle = document.getElementById('success-subtitle');\n var successIcon = document.getElementById('success-icon');\n var successMsg = document.getElementById('success-msg');\n var denyMode = false;\n\n function showError(msg) {\n errDiv.textContent = msg;\n errDiv.classList.remove('hidden');\n }\n\n function clearError() {\n errDiv.classList.add('hidden');\n }\n\n function disableButtons() {\n btnApprove.disabled = true;\n btnDeny.disabled = true;\n }\n\n function enableButtons() {\n btnApprove.disabled = false;\n btnDeny.disabled = false;\n }\n\n function showSuccess(approved) {\n form.classList.add('hidden');\n successView.classList.remove('hidden');\n if (approved) {\n successSubtitle.textContent = 'Purchase Approved';\n successIcon.innerHTML = '&#10003;';\n successIcon.style.color = '#2e7d32';\n successMsg.textContent = 'Transaction approved and signed.';\n } else {\n successSubtitle.textContent = 'Purchase Denied';\n successIcon.innerHTML = '&#10007;';\n successIcon.style.color = '#c62828';\n successMsg.textContent = 'Transaction has been denied.';\n }\n setTimeout(function() { window.close(); }, 3000);\n }\n\n function doApprove() {\n var passphrase = input.value;\n if (!passphrase) {\n showError('Passphrase is required to approve.');\n return;\n }\n clearError();\n disableButtons();\n btnApprove.textContent = 'Approving...';\n\n fetch('/api/approve', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token: token, passphrase: passphrase })\n })\n .then(function(res) { return res.json(); })\n .then(function(data) {\n if (data.error) {\n showError(data.error);\n enableButtons();\n btnApprove.textContent = 'Approve';\n } else {\n showSuccess(true);\n }\n })\n .catch(function() {\n showError('Failed to submit. Is the CLI still running?');\n enableButtons();\n btnApprove.textContent = 'Approve';\n });\n }\n\n function doReject() {\n if (!denyMode) {\n denyMode = true;\n reasonSection.classList.remove('hidden');\n btnDeny.textContent = 'Confirm Deny';\n reasonInput.focus();\n return;\n }\n clearError();\n disableButtons();\n btnDeny.textContent = 'Denying...';\n\n fetch('/api/reject', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token: token, reason: reasonInput.value || undefined })\n })\n .then(function(res) { return res.json(); })\n .then(function(data) {\n if (data.error) {\n showError(data.error);\n enableButtons();\n btnDeny.textContent = 'Confirm Deny';\n } else {\n showSuccess(false);\n }\n })\n .catch(function() {\n showError('Failed to submit. Is the CLI still running?');\n enableButtons();\n btnDeny.textContent = 'Confirm Deny';\n });\n }\n\n btnApprove.addEventListener('click', doApprove);\n btnDeny.addEventListener('click', doReject);\n input.addEventListener('keydown', function(e) {\n if (e.key === 'Enter') doApprove();\n });\n})();\n</script>\n</body>\n</html>`;\n}\n","import { exec } from 'node:child_process';\nimport { platform } from 'node:os';\n\nexport function openBrowser(url: string): void {\n const plat = platform();\n let cmd: string;\n if (plat === 'darwin') cmd = `open \"${url}\"`;\n else if (plat === 'win32') cmd = `start \"\" \"${url}\"`;\n else cmd = `xdg-open \"${url}\"`;\n\n exec(cmd, (err) => {\n if (err) {\n console.log(`Open ${url} in your browser.`);\n }\n });\n}\n","import { createServer, type IncomingMessage, type ServerResponse, type Server } from 'node:http';\nimport { randomBytes } from 'node:crypto';\nimport { join } from 'node:path';\nimport { getApprovalHtml } from './approval-html.js';\nimport { openBrowser } from '../utils/open-browser.js';\nimport { loadPrivateKey } from '../auth/keypair.js';\nimport { createMandate } from '../auth/mandate.js';\nimport { TimeoutError } from '../errors.js';\nimport type { Transaction } from '../transactions/types.js';\nimport type { TransactionDetails } from '../auth/types.js';\nimport type { TransactionManager } from '../transactions/manager.js';\nimport type { AuditLogger } from '../audit/logger.js';\n\nconst TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes\nconst MAX_BODY = 4096;\n\nexport interface ApprovalResult {\n action: 'approved' | 'rejected';\n passphrase?: string; // only present on approve, for vault decryption\n reason?: string; // only present on reject\n}\n\nfunction parseBody(req: IncomingMessage): Promise<Record<string, unknown>> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n req.on('data', (chunk: Buffer) => {\n size += chunk.length;\n if (size > MAX_BODY) {\n req.destroy();\n reject(new Error('Request body too large'));\n return;\n }\n chunks.push(chunk);\n });\n req.on('end', () => {\n try {\n const text = Buffer.concat(chunks).toString('utf8');\n resolve(text ? JSON.parse(text) : {});\n } catch {\n reject(new Error('Invalid JSON'));\n }\n });\n req.on('error', reject);\n });\n}\n\nfunction sendJson(res: ServerResponse, status: number, body: Record<string, unknown>): void {\n const json = JSON.stringify(body);\n res.writeHead(status, {\n 'Content-Type': 'application/json',\n 'Content-Length': Buffer.byteLength(json),\n });\n res.end(json);\n}\n\nfunction sendHtml(res: ServerResponse, html: string): void {\n res.writeHead(200, {\n 'Content-Type': 'text/html; charset=utf-8',\n 'Content-Length': Buffer.byteLength(html),\n });\n res.end(html);\n}\n\nexport interface ApprovalServerHandle {\n server: Server;\n token: string;\n port: number;\n promise: Promise<ApprovalResult>;\n}\n\n/**\n * Create the ephemeral approval server without opening a browser.\n * Useful for testing — call `requestBrowserApproval` for the full flow.\n */\nexport function createApprovalServer(\n tx: Transaction,\n tm: TransactionManager,\n audit: AuditLogger,\n options?: { openBrowser?: boolean; home?: string },\n): ApprovalServerHandle {\n const nonce = randomBytes(32).toString('hex');\n let settled = false;\n let tokenUsed = false;\n let resolvePromise: (result: ApprovalResult) => void;\n let rejectPromise: (err: Error) => void;\n let timer: ReturnType<typeof setTimeout>;\n let serverInstance: Server;\n\n const promise = new Promise<ApprovalResult>((resolve, reject) => {\n resolvePromise = resolve;\n rejectPromise = reject;\n });\n\n function cleanup(): void {\n clearTimeout(timer);\n serverInstance.close();\n }\n\n serverInstance = createServer(async (req, res) => {\n const url = new URL(req.url ?? '/', `http://${req.headers.host}`);\n const method = req.method ?? 'GET';\n\n try {\n // GET /approve/:txId?token=X — serve approval page\n if (method === 'GET' && url.pathname === `/approve/${tx.id}`) {\n const token = url.searchParams.get('token');\n if (token !== nonce || tokenUsed) {\n sendHtml(res, '<h1>Invalid or expired link.</h1>');\n return;\n }\n sendHtml(res, getApprovalHtml(nonce, tx));\n return;\n }\n\n // POST /api/approve — approve with passphrase (server-side signing)\n if (method === 'POST' && url.pathname === '/api/approve') {\n const body = await parseBody(req);\n if (body.token !== nonce || tokenUsed) {\n sendJson(res, 403, { error: 'Invalid or expired token.' });\n return;\n }\n\n const passphrase = body.passphrase;\n if (typeof passphrase !== 'string' || !passphrase) {\n sendJson(res, 400, { error: 'Passphrase is required.' });\n return;\n }\n\n // Verify the tx is still pending\n const currentTx = tm.get(tx.id);\n if (!currentTx || currentTx.status !== 'pending') {\n sendJson(res, 400, { error: 'Transaction is no longer pending.' });\n return;\n }\n\n // Server-side signing: load private key and create mandate\n try {\n const keyPath = options?.home ? join(options.home, 'keys', 'private.pem') : undefined;\n const privateKeyPem = loadPrivateKey(keyPath);\n const txDetails: TransactionDetails = {\n txId: tx.id,\n merchant: tx.merchant,\n amount: tx.amount,\n description: tx.description,\n timestamp: tx.createdAt,\n };\n const mandate = createMandate(txDetails, privateKeyPem, passphrase);\n tm.approve(tx.id, mandate);\n audit.log('APPROVE', { txId: tx.id, source: 'browser-approval', mandateSigned: true });\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Signing failed';\n sendJson(res, 400, { error: msg });\n return;\n }\n\n tokenUsed = true;\n sendJson(res, 200, { ok: true });\n\n if (!settled) {\n settled = true;\n cleanup();\n resolvePromise({ action: 'approved', passphrase: passphrase as string });\n }\n return;\n }\n\n // POST /api/reject — reject the transaction\n if (method === 'POST' && url.pathname === '/api/reject') {\n const body = await parseBody(req);\n if (body.token !== nonce || tokenUsed) {\n sendJson(res, 403, { error: 'Invalid or expired token.' });\n return;\n }\n\n // Verify the tx is still pending\n const currentTx = tm.get(tx.id);\n if (!currentTx || currentTx.status !== 'pending') {\n sendJson(res, 400, { error: 'Transaction is no longer pending.' });\n return;\n }\n\n const reason = typeof body.reason === 'string' ? body.reason : undefined;\n tm.reject(tx.id, reason);\n audit.log('REJECT', { txId: tx.id, source: 'browser-approval', reason });\n\n tokenUsed = true;\n sendJson(res, 200, { ok: true });\n\n if (!settled) {\n settled = true;\n cleanup();\n resolvePromise({ action: 'rejected', reason });\n }\n return;\n }\n\n sendJson(res, 404, { error: 'Not found' });\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Internal error';\n sendJson(res, 500, { error: message });\n }\n });\n\n timer = setTimeout(() => {\n if (!settled) {\n settled = true;\n cleanup();\n rejectPromise(new TimeoutError('Approval timed out after 5 minutes.'));\n }\n }, TIMEOUT_MS);\n\n serverInstance.on('error', (err) => {\n if (!settled) {\n settled = true;\n cleanup();\n rejectPromise(err);\n }\n });\n\n // We need to wait for listen to get the port, but return synchronously.\n // The promise will resolve/reject based on server events.\n let portValue = 0;\n const handle: ApprovalServerHandle = {\n server: serverInstance,\n token: nonce,\n get port() { return portValue; },\n promise,\n };\n\n serverInstance.listen(0, '127.0.0.1', () => {\n const addr = serverInstance.address();\n if (!addr || typeof addr === 'string') {\n if (!settled) {\n settled = true;\n cleanup();\n rejectPromise(new Error('Failed to bind server'));\n }\n return;\n }\n portValue = addr.port;\n const pageUrl = `http://127.0.0.1:${addr.port}/approve/${tx.id}?token=${nonce}`;\n\n if (options?.openBrowser !== false) {\n console.log('Opening approval page in browser...');\n openBrowser(pageUrl);\n }\n });\n\n return handle;\n}\n\n/**\n * Launch an ephemeral HTTP server on localhost, open a browser page\n * where the human can approve or deny the transaction.\n * On approve: server-side signing is performed, passphrase returned in result.\n * On deny: transaction is rejected.\n */\nexport function requestBrowserApproval(\n tx: Transaction,\n tm: TransactionManager,\n audit: AuditLogger,\n home?: string,\n): Promise<ApprovalResult> {\n const handle = createApprovalServer(tx, tm, audit, { openBrowser: true, home });\n return handle.promise;\n}\n","export interface PassphraseContext {\n action: 'buy' | 'approve';\n merchant?: string;\n amount?: number;\n description?: string;\n txId?: string;\n}\n\nfunction esc(s: string): string {\n return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n}\n\nfunction formatCurrency(n: number): string {\n return '$' + n.toFixed(2);\n}\n\nexport function getPassphraseHtml(token: string, context?: PassphraseContext): string {\n const actionLabel = context?.action === 'approve' ? 'Approve Transaction' : 'Approve Purchase';\n const buttonLabel = context?.action === 'approve' ? 'Unlock &amp; Approve' : 'Unlock &amp; Approve';\n\n let contextHtml = '';\n if (context) {\n const lines: string[] = [];\n if (context.merchant) lines.push(`<div class=\"detail\"><span class=\"detail-label\">Merchant</span><span class=\"detail-value\">${esc(context.merchant)}</span></div>`);\n if (context.amount !== undefined) lines.push(`<div class=\"detail\"><span class=\"detail-label\">Amount</span><span class=\"detail-value\">${formatCurrency(context.amount)}</span></div>`);\n if (context.description) lines.push(`<div class=\"detail\"><span class=\"detail-label\">Description</span><span class=\"detail-value\">${esc(context.description)}</span></div>`);\n if (context.txId) lines.push(`<div class=\"detail\"><span class=\"detail-label\">Transaction</span><span class=\"detail-value\" style=\"font-family:monospace;font-size:12px;\">${esc(context.txId)}</span></div>`);\n if (lines.length > 0) {\n contextHtml = `<div class=\"card context-card\">${lines.join('')}</div>`;\n }\n }\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>AgentPay — Passphrase Required</title>\n<style>\n *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n background: #f5f5f5;\n color: #111;\n min-height: 100vh;\n display: flex;\n justify-content: center;\n padding: 40px 16px;\n }\n .container { width: 100%; max-width: 420px; }\n h1 { font-size: 24px; font-weight: 700; margin-bottom: 4px; }\n .subtitle { color: #666; font-size: 14px; margin-bottom: 24px; }\n .card {\n background: #fff;\n border-radius: 8px;\n padding: 24px;\n margin-bottom: 16px;\n border: 1px solid #e0e0e0;\n }\n .context-card { padding: 16px 20px; }\n .detail {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 0;\n border-bottom: 1px solid #f0f0f0;\n }\n .detail:last-child { border-bottom: none; }\n .detail-label { font-size: 13px; color: #666; }\n .detail-value { font-size: 14px; font-weight: 600; }\n label { display: block; font-size: 13px; font-weight: 500; color: #333; margin-bottom: 6px; }\n input[type=\"password\"] {\n width: 100%;\n padding: 12px 14px;\n border: 1px solid #d0d0d0;\n border-radius: 8px;\n font-size: 15px;\n outline: none;\n transition: border-color 0.15s;\n }\n input[type=\"password\"]:focus { border-color: #111; }\n button {\n width: 100%;\n padding: 12px;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: opacity 0.15s;\n margin-top: 16px;\n background: #111;\n color: #fff;\n }\n button:hover { opacity: 0.85; }\n button:disabled { opacity: 0.5; cursor: not-allowed; }\n .error { color: #c62828; font-size: 13px; margin-top: 10px; }\n .success-screen {\n text-align: center;\n padding: 40px 0;\n }\n .checkmark {\n font-size: 48px;\n margin-bottom: 16px;\n }\n .success-msg {\n font-size: 16px;\n font-weight: 600;\n margin-bottom: 8px;\n }\n .success-hint {\n font-size: 13px;\n color: #666;\n }\n .hidden { display: none; }\n</style>\n</head>\n<body>\n<div class=\"container\">\n <div id=\"form-view\">\n <h1>AgentPay</h1>\n <p class=\"subtitle\">${esc(actionLabel)}</p>\n ${contextHtml}\n <div class=\"card\">\n <label for=\"passphrase\">Passphrase</label>\n <input type=\"password\" id=\"passphrase\" placeholder=\"Enter your passphrase\" autofocus>\n <div id=\"error\" class=\"error hidden\"></div>\n <button id=\"submit\">${buttonLabel}</button>\n </div>\n </div>\n <div id=\"success-view\" class=\"hidden\">\n <h1>AgentPay</h1>\n <p class=\"subtitle\">${esc(actionLabel)}</p>\n <div class=\"card\">\n <div class=\"success-screen\">\n <div class=\"checkmark\">&#10003;</div>\n <div class=\"success-msg\">Passphrase received</div>\n <div class=\"success-hint\">You can close this tab.</div>\n </div>\n </div>\n </div>\n</div>\n<script>\n(function() {\n var token = ${JSON.stringify(token)};\n var form = document.getElementById('form-view');\n var success = document.getElementById('success-view');\n var input = document.getElementById('passphrase');\n var btn = document.getElementById('submit');\n var errDiv = document.getElementById('error');\n\n function submit() {\n var passphrase = input.value;\n if (!passphrase) {\n errDiv.textContent = 'Passphrase is required.';\n errDiv.classList.remove('hidden');\n return;\n }\n btn.disabled = true;\n btn.textContent = 'Submitting...';\n errDiv.classList.add('hidden');\n\n fetch('/passphrase', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token: token, passphrase: passphrase })\n })\n .then(function(res) { return res.json(); })\n .then(function(data) {\n if (data.error) {\n errDiv.textContent = data.error;\n errDiv.classList.remove('hidden');\n btn.disabled = false;\n btn.textContent = '${buttonLabel}';\n } else {\n form.classList.add('hidden');\n success.classList.remove('hidden');\n }\n })\n .catch(function() {\n errDiv.textContent = 'Failed to submit. Is the CLI still running?';\n errDiv.classList.remove('hidden');\n btn.disabled = false;\n btn.textContent = '${buttonLabel}';\n });\n }\n\n btn.addEventListener('click', submit);\n input.addEventListener('keydown', function(e) {\n if (e.key === 'Enter') submit();\n });\n})();\n</script>\n</body>\n</html>`;\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from 'node:http';\nimport { randomBytes } from 'node:crypto';\nimport { getPassphraseHtml, type PassphraseContext } from './passphrase-html.js';\nimport { openBrowser } from '../utils/open-browser.js';\nimport { TimeoutError } from '../errors.js';\n\nconst TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes\nconst MAX_BODY = 4096;\n\nfunction parseBody(req: IncomingMessage): Promise<Record<string, unknown>> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n req.on('data', (chunk: Buffer) => {\n size += chunk.length;\n if (size > MAX_BODY) {\n req.destroy();\n reject(new Error('Request body too large'));\n return;\n }\n chunks.push(chunk);\n });\n req.on('end', () => {\n try {\n const text = Buffer.concat(chunks).toString('utf8');\n resolve(text ? JSON.parse(text) : {});\n } catch {\n reject(new Error('Invalid JSON'));\n }\n });\n req.on('error', reject);\n });\n}\n\nfunction sendJson(res: ServerResponse, status: number, body: Record<string, unknown>): void {\n const json = JSON.stringify(body);\n res.writeHead(status, {\n 'Content-Type': 'application/json',\n 'Content-Length': Buffer.byteLength(json),\n });\n res.end(json);\n}\n\nfunction sendHtml(res: ServerResponse, html: string): void {\n res.writeHead(200, {\n 'Content-Type': 'text/html; charset=utf-8',\n 'Content-Length': Buffer.byteLength(html),\n });\n res.end(html);\n}\n\nexport type { PassphraseContext } from './passphrase-html.js';\n\n/**\n * Launch an ephemeral HTTP server on localhost, open a browser page\n * where the human enters their passphrase, and return it.\n * The passphrase never appears in stdout/stderr.\n */\nexport function collectPassphrase(context?: PassphraseContext): Promise<string> {\n return new Promise((resolve, reject) => {\n const nonce = randomBytes(32).toString('hex');\n let settled = false;\n\n const server = createServer(async (req, res) => {\n const url = new URL(req.url ?? '/', `http://${req.headers.host}`);\n const method = req.method ?? 'GET';\n\n try {\n if (method === 'GET' && url.pathname === '/passphrase') {\n const token = url.searchParams.get('token');\n if (token !== nonce) {\n sendHtml(res, '<h1>Invalid or expired link.</h1>');\n return;\n }\n sendHtml(res, getPassphraseHtml(nonce, context));\n } else if (method === 'POST' && url.pathname === '/passphrase') {\n const body = await parseBody(req);\n if (body.token !== nonce) {\n sendJson(res, 403, { error: 'Invalid token.' });\n return;\n }\n const passphrase = body.passphrase;\n if (typeof passphrase !== 'string' || !passphrase) {\n sendJson(res, 400, { error: 'Passphrase is required.' });\n return;\n }\n sendJson(res, 200, { ok: true });\n\n if (!settled) {\n settled = true;\n cleanup();\n resolve(passphrase);\n }\n } else {\n sendJson(res, 404, { error: 'Not found' });\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Internal error';\n sendJson(res, 500, { error: message });\n }\n });\n\n const timer = setTimeout(() => {\n if (!settled) {\n settled = true;\n cleanup();\n reject(new TimeoutError('Passphrase entry timed out after 5 minutes.'));\n }\n }, TIMEOUT_MS);\n\n function cleanup(): void {\n clearTimeout(timer);\n server.close();\n }\n\n server.on('error', (err) => {\n if (!settled) {\n settled = true;\n cleanup();\n reject(err);\n }\n });\n\n // Bind to localhost on a random available port\n server.listen(0, '127.0.0.1', () => {\n const addr = server.address();\n if (!addr || typeof addr === 'string') {\n if (!settled) {\n settled = true;\n cleanup();\n reject(new Error('Failed to bind server'));\n }\n return;\n }\n const url = `http://127.0.0.1:${addr.port}/passphrase?token=${nonce}`;\n console.log('Waiting for passphrase entry in browser...');\n openBrowser(url);\n });\n });\n}\n","declare const __PKG_VERSION__: string;\nexport const VERSION = typeof __PKG_VERSION__ !== 'undefined' ? __PKG_VERSION__ : '0.0.0';\n\n// Types\nexport type { BillingCredentials, EncryptedVault } from './vault/types.js';\nexport type { KeyPair, PurchaseMandate, TransactionDetails } from './auth/types.js';\nexport type { Wallet } from './budget/types.js';\nexport type { Transaction, TransactionStatus, Receipt, ProposeOptions } from './transactions/types.js';\nexport type { CheckoutResult, ExecutorConfig } from './executor/types.js';\nexport type { BrowserProvider } from './executor/browser-provider.js';\n\n// Errors\nexport {\n NotSetupError,\n DecryptError,\n InsufficientBalanceError,\n ExceedsTxLimitError,\n NotApprovedError,\n InvalidMandateError,\n AlreadyExecutedError,\n CheckoutFailedError,\n TimeoutError,\n} from './errors.js';\n\n// Utilities\nexport { generateTxId } from './utils/ids.js';\nexport { formatCurrency, formatTimestamp, formatTable, formatStatus } from './utils/display.js';\nexport { getHomePath, getCredentialsPath, getKeysPath, getWalletPath, getTransactionsPath, getAuditPath } from './utils/paths.js';\n\n// Vault\nexport { encrypt, decrypt, saveVault, loadVault } from './vault/vault.js';\n\n// Auth\nexport { generateKeyPair, saveKeyPair, loadPublicKey, loadPrivateKey } from './auth/keypair.js';\nexport { createMandate, verifyMandate } from './auth/mandate.js';\n\n// Budget\nexport { BudgetManager } from './budget/budget.js';\n\n// Transactions\nexport { TransactionManager } from './transactions/manager.js';\nexport { waitForApproval } from './transactions/poller.js';\n\n// Audit\nexport { AuditLogger } from './audit/logger.js';\n\n// Executor\nexport { PurchaseExecutor } from './executor/executor.js';\nexport { PLACEHOLDER_MAP, getPlaceholderVariables, credentialsToSwapMap } from './executor/placeholder.js';\n\n// Approval Server\nexport type { ApprovalResult } from './server/approval-server.js';\nexport { requestBrowserApproval } from './server/approval-server.js';\n\n// Setup Server\nexport type { SetupResult } from './server/setup-server.js';\nexport { requestBrowserSetup } from './server/setup-server.js';\n\n// Dashboard Server\nexport { startServer as startDashboardServer } from './server/index.js';\n\n// Browser & Prompt Utilities\nexport { openBrowser } from './utils/open-browser.js';\nexport { promptInput, promptPassphrase, promptConfirm, promptPassphraseSafe } from './utils/prompt.js';\n\n// AgentPay\nexport { AgentPay } from './agentpay.js';\nexport type { AgentPayOptions } from './agentpay.js';\n","import { randomBytes } from 'node:crypto';\n\nexport function generateTxId(): string {\n return `tx_${randomBytes(4).toString('hex')}`;\n}\n","import type { Transaction } from '../transactions/types.js';\n\nexport function formatCurrency(amount: number): string {\n return `$${amount.toFixed(2)}`;\n}\n\nexport function formatTimestamp(iso: string): string {\n const d = new Date(iso);\n return d.toLocaleString('en-US', {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\nexport function formatTable(transactions: Transaction[]): string {\n if (transactions.length === 0) return 'No transactions.';\n\n const header = 'TX_ID MERCHANT AMOUNT DESCRIPTION';\n const separator = '─'.repeat(header.length);\n const rows = transactions.map((tx) => {\n const id = tx.id.padEnd(14);\n const merchant = tx.merchant.padEnd(16);\n const amount = formatCurrency(tx.amount).padStart(9);\n return `${id}${merchant}${amount} ${tx.description}`;\n });\n\n return [header, separator, ...rows].join('\\n');\n}\n\nexport function formatStatus(data: {\n balance: number;\n budget: number;\n limitPerTx: number;\n pending: Transaction[];\n recent: Transaction[];\n}): string {\n const lines = [\n 'AgentPay Status',\n '───────────────',\n `Balance: ${formatCurrency(data.balance)} / ${formatCurrency(data.budget)}`,\n `Per-tx limit: ${formatCurrency(data.limitPerTx)}`,\n `Pending purchases: ${data.pending.length}`,\n ];\n\n if (data.recent.length > 0) {\n lines.push('', 'Recent:');\n for (const tx of data.recent) {\n const status = `[${tx.status}]`.padEnd(12);\n lines.push(` ${status} ${tx.id} ${tx.merchant.padEnd(12)} ${formatCurrency(tx.amount).padStart(8)} ${tx.description}`);\n }\n }\n\n return lines.join('\\n');\n}\n","import { pbkdf2Sync, randomBytes, createCipheriv, createDecipheriv } from 'node:crypto';\nimport { readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type { BillingCredentials, EncryptedVault } from './types.js';\nimport { DecryptError, NotSetupError } from '../errors.js';\nimport { getCredentialsPath } from '../utils/paths.js';\n\nconst ALGORITHM = 'aes-256-gcm';\nconst PBKDF2_ITERATIONS = 100_000;\nconst PBKDF2_DIGEST = 'sha512';\nconst KEY_LENGTH = 32;\nconst SALT_LENGTH = 32;\nconst IV_LENGTH = 16;\n\nexport function deriveKey(passphrase: string, salt: Buffer): Buffer {\n return pbkdf2Sync(passphrase, salt, PBKDF2_ITERATIONS, KEY_LENGTH, PBKDF2_DIGEST);\n}\n\nexport function encrypt(credentials: BillingCredentials, passphrase: string): EncryptedVault {\n const salt = randomBytes(SALT_LENGTH);\n const iv = randomBytes(IV_LENGTH);\n const key = deriveKey(passphrase, salt);\n\n const cipher = createCipheriv(ALGORITHM, key, iv);\n const plaintext = JSON.stringify(credentials);\n const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);\n const authTag = cipher.getAuthTag();\n\n return {\n ciphertext: Buffer.concat([encrypted, authTag]).toString('base64'),\n salt: salt.toString('base64'),\n iv: iv.toString('base64'),\n };\n}\n\nexport function decrypt(vault: EncryptedVault, passphrase: string): BillingCredentials {\n try {\n const salt = Buffer.from(vault.salt, 'base64');\n const iv = Buffer.from(vault.iv, 'base64');\n const data = Buffer.from(vault.ciphertext, 'base64');\n const key = deriveKey(passphrase, salt);\n\n const authTag = data.subarray(data.length - 16);\n const ciphertext = data.subarray(0, data.length - 16);\n\n const decipher = createDecipheriv(ALGORITHM, key, iv);\n decipher.setAuthTag(authTag);\n const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);\n\n return JSON.parse(decrypted.toString('utf8')) as BillingCredentials;\n } catch {\n throw new DecryptError();\n }\n}\n\nexport function saveVault(vault: EncryptedVault, path?: string): void {\n const filePath = path ?? getCredentialsPath();\n mkdirSync(dirname(filePath), { recursive: true });\n writeFileSync(filePath, JSON.stringify(vault, null, 2), { mode: 0o600 });\n}\n\nexport function loadVault(path?: string): EncryptedVault {\n const filePath = path ?? getCredentialsPath();\n try {\n const data = readFileSync(filePath, 'utf8');\n return JSON.parse(data) as EncryptedVault;\n } catch {\n throw new NotSetupError();\n }\n}\n","import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type { Wallet } from './types.js';\nimport { NotSetupError, InsufficientBalanceError, ExceedsTxLimitError } from '../errors.js';\nimport { getWalletPath } from '../utils/paths.js';\n\nexport class BudgetManager {\n private walletPath: string;\n\n constructor(walletPath?: string) {\n this.walletPath = walletPath ?? getWalletPath();\n }\n\n getWallet(): Wallet {\n try {\n const data = readFileSync(this.walletPath, 'utf8');\n return JSON.parse(data) as Wallet;\n } catch {\n throw new NotSetupError();\n }\n }\n\n private saveWallet(wallet: Wallet): void {\n mkdirSync(dirname(this.walletPath), { recursive: true });\n writeFileSync(this.walletPath, JSON.stringify(wallet, null, 2), { mode: 0o600 });\n }\n\n setBudget(amount: number): void {\n let wallet: Wallet;\n try {\n wallet = this.getWallet();\n } catch {\n wallet = { budget: 0, balance: 0, limitPerTx: 0, spent: 0 };\n }\n wallet.budget = amount;\n wallet.balance = amount - wallet.spent;\n this.saveWallet(wallet);\n }\n\n setLimitPerTx(limit: number): void {\n const wallet = this.getWallet();\n wallet.limitPerTx = limit;\n this.saveWallet(wallet);\n }\n\n deductBalance(amount: number): void {\n const wallet = this.getWallet();\n if (amount > wallet.balance) {\n throw new InsufficientBalanceError(amount, wallet.balance);\n }\n wallet.balance -= amount;\n wallet.spent += amount;\n this.saveWallet(wallet);\n }\n\n checkProposal(amount: number): void {\n const wallet = this.getWallet();\n if (amount > wallet.balance) {\n throw new InsufficientBalanceError(amount, wallet.balance);\n }\n if (wallet.limitPerTx > 0 && amount > wallet.limitPerTx) {\n throw new ExceedsTxLimitError(amount, wallet.limitPerTx);\n }\n }\n\n addFunds(amount: number): Wallet {\n const wallet = this.getWallet();\n wallet.budget += amount;\n wallet.balance += amount;\n this.saveWallet(wallet);\n return wallet;\n }\n\n getBalance(): { budget: number; balance: number; limitPerTx: number; spent: number } {\n const wallet = this.getWallet();\n return {\n budget: wallet.budget,\n balance: wallet.balance,\n limitPerTx: wallet.limitPerTx,\n spent: wallet.spent,\n };\n }\n\n initWallet(budget: number, limitPerTx: number = 0): void {\n const wallet: Wallet = { budget, balance: budget, limitPerTx, spent: 0 };\n this.saveWallet(wallet);\n }\n}\n","import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type { Transaction, Receipt, ProposeOptions } from './types.js';\nimport type { PurchaseMandate } from '../auth/types.js';\nimport { generateTxId } from '../utils/ids.js';\nimport { getTransactionsPath } from '../utils/paths.js';\n\nexport class TransactionManager {\n private txPath: string;\n\n constructor(txPath?: string) {\n this.txPath = txPath ?? getTransactionsPath();\n }\n\n private loadAll(): Transaction[] {\n try {\n const data = readFileSync(this.txPath, 'utf8');\n return JSON.parse(data) as Transaction[];\n } catch {\n return [];\n }\n }\n\n private saveAll(transactions: Transaction[]): void {\n mkdirSync(dirname(this.txPath), { recursive: true });\n writeFileSync(this.txPath, JSON.stringify(transactions, null, 2), { mode: 0o600 });\n }\n\n propose(options: ProposeOptions): Transaction {\n const transactions = this.loadAll();\n const tx: Transaction = {\n id: generateTxId(),\n status: 'pending',\n merchant: options.merchant,\n amount: options.amount,\n description: options.description,\n url: options.url,\n createdAt: new Date().toISOString(),\n };\n transactions.push(tx);\n this.saveAll(transactions);\n return tx;\n }\n\n get(txId: string): Transaction | undefined {\n return this.loadAll().find((tx) => tx.id === txId);\n }\n\n approve(txId: string, mandate: PurchaseMandate): void {\n const transactions = this.loadAll();\n const tx = transactions.find((t) => t.id === txId);\n if (!tx) throw new Error(`Transaction ${txId} not found.`);\n if (tx.status !== 'pending') throw new Error(`Cannot approve transaction in '${tx.status}' state.`);\n tx.status = 'approved';\n tx.mandate = mandate;\n this.saveAll(transactions);\n }\n\n reject(txId: string, reason?: string): void {\n const transactions = this.loadAll();\n const tx = transactions.find((t) => t.id === txId);\n if (!tx) throw new Error(`Transaction ${txId} not found.`);\n if (tx.status !== 'pending') throw new Error(`Cannot reject transaction in '${tx.status}' state.`);\n tx.status = 'rejected';\n tx.rejectionReason = reason;\n this.saveAll(transactions);\n }\n\n markExecuting(txId: string): void {\n const transactions = this.loadAll();\n const tx = transactions.find((t) => t.id === txId);\n if (!tx) throw new Error(`Transaction ${txId} not found.`);\n if (tx.status !== 'approved') throw new Error(`Cannot execute transaction in '${tx.status}' state.`);\n tx.status = 'executing';\n this.saveAll(transactions);\n }\n\n markCompleted(txId: string, receipt: Receipt): void {\n const transactions = this.loadAll();\n const tx = transactions.find((t) => t.id === txId);\n if (!tx) throw new Error(`Transaction ${txId} not found.`);\n if (tx.status !== 'executing') throw new Error(`Cannot complete transaction in '${tx.status}' state.`);\n tx.status = 'completed';\n tx.receipt = receipt;\n this.saveAll(transactions);\n }\n\n markFailed(txId: string, error: string): void {\n const transactions = this.loadAll();\n const tx = transactions.find((t) => t.id === txId);\n if (!tx) throw new Error(`Transaction ${txId} not found.`);\n if (tx.status !== 'executing') throw new Error(`Cannot fail transaction in '${tx.status}' state.`);\n tx.status = 'failed';\n tx.error = error;\n this.saveAll(transactions);\n }\n\n list(): Transaction[] {\n return this.loadAll();\n }\n\n getPending(): Transaction[] {\n return this.loadAll().filter((tx) => tx.status === 'pending');\n }\n\n getHistory(): Transaction[] {\n return this.loadAll().filter((tx) => tx.status !== 'pending');\n }\n}\n","import { appendFileSync, readFileSync, mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { getAuditPath } from '../utils/paths.js';\n\nexport class AuditLogger {\n private logPath: string;\n\n constructor(logPath?: string) {\n this.logPath = logPath ?? getAuditPath();\n }\n\n log(action: string, details: Record<string, unknown>): void {\n const timestamp = new Date().toISOString();\n const detailsStr = JSON.stringify(details);\n const entry = `${timestamp}\\t${action}\\t${detailsStr}\\n`;\n mkdirSync(dirname(this.logPath), { recursive: true });\n appendFileSync(this.logPath, entry, { mode: 0o600 });\n }\n\n getLog(): string[] {\n try {\n const data = readFileSync(this.logPath, 'utf8');\n return data.trim().split('\\n').filter(Boolean);\n } catch {\n return [];\n }\n }\n}\n","import { Stagehand } from '@browserbasehq/stagehand';\nimport type { BillingCredentials } from '../vault/types.js';\nimport type { Transaction } from '../transactions/types.js';\nimport type { CheckoutResult, ExecutorConfig } from './types.js';\nimport type { BrowserProvider } from './browser-provider.js';\nimport { CheckoutFailedError } from '../errors.js';\nimport { credentialsToSwapMap, getPlaceholderVariables } from './placeholder.js';\nimport { LocalBrowserProvider } from './providers/local-provider.js';\n\nexport interface DiscoverResult {\n price: number;\n productName: string;\n}\n\nexport class PurchaseExecutor {\n private provider: BrowserProvider;\n private modelApiKey?: string;\n private stagehand: Stagehand | null = null;\n private proxyUrl: string | undefined;\n private originalBaseUrl: string | undefined;\n\n constructor(config?: ExecutorConfig) {\n this.provider = config?.provider ?? new LocalBrowserProvider();\n this.modelApiKey = config?.modelApiKey ?? process.env.ANTHROPIC_API_KEY;\n }\n\n private createStagehand(): Stagehand {\n return this.provider.createStagehand(this.modelApiKey);\n }\n\n /**\n * Phase 1: Open browser, navigate to URL, extract price and product info.\n * Keeps the session alive for fillAndComplete().\n */\n async openAndDiscover(url: string, instructions?: string): Promise<DiscoverResult> {\n this.stagehand = this.createStagehand();\n await this.stagehand.init();\n const page = this.stagehand.context.activePage()!;\n\n await page.goto(url);\n\n // Let Stagehand find the product and add to cart with optional extra instructions\n const addToCartInstructions = instructions\n ? `On this product page: ${instructions}. Then add the item to the cart.`\n : 'Add this product to the cart.';\n await this.stagehand.act(addToCartInstructions);\n\n // Extract price and product name\n const extracted = await this.stagehand.extract(\n 'Extract the product name and the price (as a number without $ sign) from the page or cart. Return JSON: { \"price\": <number>, \"productName\": \"<string>\" }',\n ) as any;\n\n const price = parseFloat(extracted?.price ?? extracted?.extraction?.price ?? '0');\n const productName = extracted?.productName ?? extracted?.extraction?.productName ?? 'Unknown Product';\n\n return { price, productName };\n }\n\n /**\n * Phase 2: Proceed to checkout, fill forms, swap credentials, and submit.\n * Must be called after openAndDiscover().\n */\n async fillAndComplete(credentials: BillingCredentials): Promise<CheckoutResult> {\n if (!this.stagehand) {\n throw new CheckoutFailedError('No active session. Call openAndDiscover() first.');\n }\n\n try {\n // Proceed to checkout\n await this.stagehand.act('Proceed to checkout from the cart.');\n\n // Fill checkout form with placeholders\n const variables = getPlaceholderVariables();\n await this.stagehand.act(\n `Fill in the checkout form with these values:\n Name: ${variables.cardholder_name}\n Card Number: ${variables.card_number}\n Expiry: ${variables.card_expiry}\n CVV: ${variables.card_cvv}\n Email: ${variables.email}\n Phone: ${variables.phone}\n Billing Street: ${variables.billing_street}\n Billing City: ${variables.billing_city}\n Billing State: ${variables.billing_state}\n Billing ZIP: ${variables.billing_zip}\n Billing Country: ${variables.billing_country}\n Shipping Street: ${variables.shipping_street}\n Shipping City: ${variables.shipping_city}\n Shipping State: ${variables.shipping_state}\n Shipping ZIP: ${variables.shipping_zip}\n Shipping Country: ${variables.shipping_country}`,\n { variables },\n );\n\n // Atomic swap: replace placeholders with real credentials and submit\n const swapMap = credentialsToSwapMap(credentials);\n const page = this.stagehand.context.activePage()!;\n\n await page.evaluate((map: Record<string, string>) => {\n const inputs = document.querySelectorAll('input, textarea, select');\n for (const input of inputs) {\n const el = input as HTMLInputElement;\n for (const [placeholder, value] of Object.entries(map)) {\n if (el.value === placeholder) {\n el.value = value;\n el.dispatchEvent(new Event('input', { bubbles: true }));\n el.dispatchEvent(new Event('change', { bubbles: true }));\n }\n }\n }\n const submitBtn = document.querySelector('button[type=\"submit\"], input[type=\"submit\"]') as HTMLElement | null;\n if (submitBtn) submitBtn.click();\n }, swapMap);\n\n // Wait for confirmation page\n await page.waitForTimeout(5000);\n\n // Try to extract confirmation\n const result = await this.stagehand.extract(\n 'Extract the order confirmation number or ID from the page',\n );\n\n const confirmationId = (result as any)?.extraction;\n if (!confirmationId || confirmationId === 'null' || confirmationId === 'UNKNOWN') {\n throw new CheckoutFailedError('No order confirmation found. Checkout may not have completed.');\n }\n\n return {\n success: true,\n confirmationId,\n };\n } catch (err) {\n if (err instanceof CheckoutFailedError) throw err;\n const message = err instanceof Error ? err.message : 'Unknown checkout error';\n throw new CheckoutFailedError(message);\n }\n }\n\n /**\n * Convenience: single-shot execute (navigate + checkout in one call).\n * Used by AgentPay facade when amount is already known.\n */\n async execute(tx: Transaction, credentials: BillingCredentials): Promise<CheckoutResult> {\n this.stagehand = this.createStagehand();\n\n try {\n await this.stagehand.init();\n const page = this.stagehand.context.activePage()!;\n\n await page.goto(tx.url);\n\n const variables = getPlaceholderVariables();\n await this.stagehand.act(\n `Find the product and proceed to checkout. Fill in the checkout form with these values:\n Name: ${variables.cardholder_name}\n Card Number: ${variables.card_number}\n Expiry: ${variables.card_expiry}\n CVV: ${variables.card_cvv}\n Email: ${variables.email}\n Phone: ${variables.phone}\n Billing Street: ${variables.billing_street}\n Billing City: ${variables.billing_city}\n Billing State: ${variables.billing_state}\n Billing ZIP: ${variables.billing_zip}\n Billing Country: ${variables.billing_country}\n Shipping Street: ${variables.shipping_street}\n Shipping City: ${variables.shipping_city}\n Shipping State: ${variables.shipping_state}\n Shipping ZIP: ${variables.shipping_zip}\n Shipping Country: ${variables.shipping_country}`,\n { variables },\n );\n\n const swapMap = credentialsToSwapMap(credentials);\n await page.evaluate((map: Record<string, string>) => {\n const inputs = document.querySelectorAll('input, textarea, select');\n for (const input of inputs) {\n const el = input as HTMLInputElement;\n for (const [placeholder, value] of Object.entries(map)) {\n if (el.value === placeholder) {\n el.value = value;\n el.dispatchEvent(new Event('input', { bubbles: true }));\n el.dispatchEvent(new Event('change', { bubbles: true }));\n }\n }\n }\n const submitBtn = document.querySelector('button[type=\"submit\"], input[type=\"submit\"]') as HTMLElement | null;\n if (submitBtn) submitBtn.click();\n }, swapMap);\n\n await page.waitForTimeout(5000);\n\n const result = await this.stagehand.extract(\n 'Extract the order confirmation number or ID from the page',\n );\n\n const confirmationId = (result as any)?.extraction;\n if (!confirmationId || confirmationId === 'null' || confirmationId === 'UNKNOWN') {\n throw new CheckoutFailedError('No order confirmation found. Checkout may not have completed.');\n }\n\n return {\n success: true,\n confirmationId,\n };\n } catch (err) {\n if (err instanceof CheckoutFailedError) throw err;\n const message = err instanceof Error ? err.message : 'Unknown checkout error';\n throw new CheckoutFailedError(message);\n } finally {\n await this.close();\n }\n }\n\n async close(): Promise<void> {\n try {\n if (this.stagehand) {\n await this.stagehand.close();\n this.stagehand = null;\n }\n } catch {\n // Ignore cleanup errors\n } finally {\n await this.provider.close();\n }\n }\n}\n","import type { BillingCredentials } from '../vault/types.js';\n\nexport const PLACEHOLDER_MAP = {\n card_number: '{{card_number}}',\n cardholder_name: '{{cardholder_name}}',\n card_expiry: '{{card_expiry}}',\n card_cvv: '{{card_cvv}}',\n billing_street: '{{billing_street}}',\n billing_city: '{{billing_city}}',\n billing_state: '{{billing_state}}',\n billing_zip: '{{billing_zip}}',\n billing_country: '{{billing_country}}',\n shipping_street: '{{shipping_street}}',\n shipping_city: '{{shipping_city}}',\n shipping_state: '{{shipping_state}}',\n shipping_zip: '{{shipping_zip}}',\n shipping_country: '{{shipping_country}}',\n email: '{{email}}',\n phone: '{{phone}}',\n} as const;\n\nexport function getPlaceholderVariables(): Record<string, string> {\n // These are the %var% placeholders used with Stagehand act() variables\n // The AI never sees the real values — only these placeholders\n return {\n card_number: '%card_number%',\n cardholder_name: '%cardholder_name%',\n card_expiry: '%card_expiry%',\n card_cvv: '%card_cvv%',\n billing_street: '%billing_street%',\n billing_city: '%billing_city%',\n billing_state: '%billing_state%',\n billing_zip: '%billing_zip%',\n billing_country: '%billing_country%',\n shipping_street: '%shipping_street%',\n shipping_city: '%shipping_city%',\n shipping_state: '%shipping_state%',\n shipping_zip: '%shipping_zip%',\n shipping_country: '%shipping_country%',\n email: '%email%',\n phone: '%phone%',\n };\n}\n\nexport function credentialsToSwapMap(creds: BillingCredentials): Record<string, string> {\n return {\n [PLACEHOLDER_MAP.card_number]: creds.card.number,\n [PLACEHOLDER_MAP.cardholder_name]: creds.name,\n [PLACEHOLDER_MAP.card_expiry]: creds.card.expiry,\n [PLACEHOLDER_MAP.card_cvv]: creds.card.cvv,\n [PLACEHOLDER_MAP.billing_street]: creds.billingAddress.street,\n [PLACEHOLDER_MAP.billing_city]: creds.billingAddress.city,\n [PLACEHOLDER_MAP.billing_state]: creds.billingAddress.state,\n [PLACEHOLDER_MAP.billing_zip]: creds.billingAddress.zip,\n [PLACEHOLDER_MAP.billing_country]: creds.billingAddress.country,\n [PLACEHOLDER_MAP.shipping_street]: creds.shippingAddress.street,\n [PLACEHOLDER_MAP.shipping_city]: creds.shippingAddress.city,\n [PLACEHOLDER_MAP.shipping_state]: creds.shippingAddress.state,\n [PLACEHOLDER_MAP.shipping_zip]: creds.shippingAddress.zip,\n [PLACEHOLDER_MAP.shipping_country]: creds.shippingAddress.country,\n [PLACEHOLDER_MAP.email]: creds.email,\n [PLACEHOLDER_MAP.phone]: creds.phone,\n };\n}\n\n/**\n * Atomically swap placeholders with real credentials in the DOM and submit.\n * This is called via page.evaluate() — credentials exist in the DOM only for milliseconds.\n */\nexport function getAtomicSwapScript(): string {\n return `\n (swapMap) => {\n const inputs = document.querySelectorAll('input, textarea, select');\n for (const input of inputs) {\n const el = input;\n for (const [placeholder, value] of Object.entries(swapMap)) {\n if (el.value === placeholder) {\n el.value = value;\n el.dispatchEvent(new Event('input', { bubbles: true }));\n el.dispatchEvent(new Event('change', { bubbles: true }));\n }\n }\n }\n // Submit the form\n const submitBtn = document.querySelector('button[type=\"submit\"], input[type=\"submit\"]');\n if (submitBtn) submitBtn.click();\n }\n `;\n}\n","import { Stagehand } from '@browserbasehq/stagehand';\nimport type { BrowserProvider } from '../browser-provider.js';\n\n/**\n * Default browser provider — runs Chromium locally via Playwright.\n * No cloud browser service needed.\n */\nexport class LocalBrowserProvider implements BrowserProvider {\n createStagehand(modelApiKey?: string): Stagehand {\n return new Stagehand({\n env: 'LOCAL',\n model: modelApiKey\n ? { modelName: 'claude-3-7-sonnet-latest', apiKey: modelApiKey }\n : undefined,\n });\n }\n\n async close(): Promise<void> {\n // No cleanup needed for local mode\n }\n}\n","import { createServer, type IncomingMessage, type ServerResponse, type Server } from 'node:http';\nimport { randomBytes } from 'node:crypto';\nimport { mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { getSetupHtml } from './setup-html.js';\nimport { openBrowser } from '../utils/open-browser.js';\nimport { encrypt, saveVault } from '../vault/vault.js';\nimport { generateKeyPair, saveKeyPair } from '../auth/keypair.js';\nimport { BudgetManager } from '../budget/budget.js';\nimport { AuditLogger } from '../audit/logger.js';\nimport { getHomePath, getCredentialsPath, getKeysPath, getWalletPath, getAuditPath } from '../utils/paths.js';\nimport { TimeoutError } from '../errors.js';\nimport type { BillingCredentials } from '../vault/types.js';\n\nconst TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes\nconst MAX_BODY = 8192; // setup form sends more data than approval\n\nexport interface SetupResult {\n completed: boolean;\n}\n\nfunction parseBody(req: IncomingMessage): Promise<Record<string, unknown>> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n req.on('data', (chunk: Buffer) => {\n size += chunk.length;\n if (size > MAX_BODY) {\n req.destroy();\n reject(new Error('Request body too large'));\n return;\n }\n chunks.push(chunk);\n });\n req.on('end', () => {\n try {\n const text = Buffer.concat(chunks).toString('utf8');\n resolve(text ? JSON.parse(text) : {});\n } catch {\n reject(new Error('Invalid JSON'));\n }\n });\n req.on('error', reject);\n });\n}\n\nfunction sendJson(res: ServerResponse, status: number, body: Record<string, unknown>): void {\n const json = JSON.stringify(body);\n res.writeHead(status, {\n 'Content-Type': 'application/json',\n 'Content-Length': Buffer.byteLength(json),\n });\n res.end(json);\n}\n\nfunction sendHtml(res: ServerResponse, html: string): void {\n res.writeHead(200, {\n 'Content-Type': 'text/html; charset=utf-8',\n 'Content-Length': Buffer.byteLength(html),\n });\n res.end(html);\n}\n\nfunction isNonEmptyString(val: unknown): val is string {\n return typeof val === 'string' && val.length > 0;\n}\n\nfunction isAddress(val: unknown): val is { street: string; city: string; state: string; zip: string; country: string } {\n if (!val || typeof val !== 'object') return false;\n const a = val as Record<string, unknown>;\n return isNonEmptyString(a.street)\n && isNonEmptyString(a.city)\n && isNonEmptyString(a.state)\n && isNonEmptyString(a.zip)\n && isNonEmptyString(a.country);\n}\n\nfunction isCard(val: unknown): val is { number: string; expiry: string; cvv: string } {\n if (!val || typeof val !== 'object') return false;\n const c = val as Record<string, unknown>;\n return isNonEmptyString(c.number) && isNonEmptyString(c.expiry) && isNonEmptyString(c.cvv);\n}\n\nexport interface SetupServerHandle {\n server: Server;\n token: string;\n port: number;\n promise: Promise<SetupResult>;\n}\n\n/**\n * Create the ephemeral setup server without opening a browser.\n * Useful for testing — call `requestBrowserSetup` for the full flow.\n */\nexport function createSetupServer(\n options?: { openBrowser?: boolean; home?: string },\n): SetupServerHandle {\n const nonce = randomBytes(32).toString('hex');\n let settled = false;\n let tokenUsed = false;\n let resolvePromise: (result: SetupResult) => void;\n let rejectPromise: (err: Error) => void;\n let timer: ReturnType<typeof setTimeout>;\n let serverInstance: Server;\n\n const promise = new Promise<SetupResult>((resolve, reject) => {\n resolvePromise = resolve;\n rejectPromise = reject;\n });\n\n function cleanup(): void {\n clearTimeout(timer);\n serverInstance.close();\n }\n\n const home = options?.home ?? getHomePath();\n\n serverInstance = createServer(async (req, res) => {\n const url = new URL(req.url ?? '/', `http://${req.headers.host}`);\n const method = req.method ?? 'GET';\n\n try {\n // GET /setup?token=X — serve setup page\n if (method === 'GET' && url.pathname === '/setup') {\n const token = url.searchParams.get('token');\n if (token !== nonce || tokenUsed) {\n sendHtml(res, '<h1>Invalid or expired link.</h1>');\n return;\n }\n sendHtml(res, getSetupHtml(nonce));\n return;\n }\n\n // POST /api/setup — process setup form\n if (method === 'POST' && url.pathname === '/api/setup') {\n const body = await parseBody(req);\n if (body.token !== nonce || tokenUsed) {\n sendJson(res, 403, { error: 'Invalid or expired token.' });\n return;\n }\n\n // Validate required fields\n const passphrase = body.passphrase;\n if (!isNonEmptyString(passphrase)) {\n sendJson(res, 400, { error: 'Passphrase is required.' });\n return;\n }\n\n if (!isCard(body.card)) {\n sendJson(res, 400, { error: 'Card number, expiry, and CVV are required.' });\n return;\n }\n\n if (!isNonEmptyString(body.name) || !isNonEmptyString(body.email) || !isNonEmptyString(body.phone)) {\n sendJson(res, 400, { error: 'Name, email, and phone are required.' });\n return;\n }\n\n if (!isAddress(body.billingAddress)) {\n sendJson(res, 400, { error: 'Complete billing address is required.' });\n return;\n }\n\n if (!isAddress(body.shippingAddress)) {\n sendJson(res, 400, { error: 'Complete shipping address is required.' });\n return;\n }\n\n try {\n // Ensure home directory exists\n mkdirSync(home, { recursive: true });\n\n // Encrypt and save vault\n const credentials: BillingCredentials = {\n card: { number: body.card.number, expiry: body.card.expiry, cvv: body.card.cvv },\n name: body.name as string,\n billingAddress: {\n street: (body.billingAddress as Record<string, string>).street,\n city: (body.billingAddress as Record<string, string>).city,\n state: (body.billingAddress as Record<string, string>).state,\n zip: (body.billingAddress as Record<string, string>).zip,\n country: (body.billingAddress as Record<string, string>).country,\n },\n shippingAddress: {\n street: (body.shippingAddress as Record<string, string>).street,\n city: (body.shippingAddress as Record<string, string>).city,\n state: (body.shippingAddress as Record<string, string>).state,\n zip: (body.shippingAddress as Record<string, string>).zip,\n country: (body.shippingAddress as Record<string, string>).country,\n },\n email: body.email as string,\n phone: body.phone as string,\n };\n\n const credPath = join(home, 'credentials.enc');\n const vault = encrypt(credentials, passphrase);\n saveVault(vault, credPath);\n\n // Generate and save keypair\n const keysDir = join(home, 'keys');\n mkdirSync(keysDir, { recursive: true });\n const keys = generateKeyPair(passphrase);\n saveKeyPair(keys, join(keysDir, 'public.pem'), join(keysDir, 'private.pem'));\n\n // Initialize wallet\n const budget = typeof body.budget === 'number' ? body.budget : 0;\n const limitPerTx = typeof body.limitPerTx === 'number' ? body.limitPerTx : 0;\n const bm = new BudgetManager(join(home, 'wallet.json'));\n bm.initWallet(budget, limitPerTx);\n\n // Audit\n const audit = new AuditLogger(join(home, 'audit.log'));\n audit.log('SETUP', { message: 'credentials encrypted, keypair generated, wallet initialized', source: 'browser-setup' });\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Setup failed';\n sendJson(res, 500, { error: msg });\n return;\n }\n\n tokenUsed = true;\n sendJson(res, 200, { ok: true });\n\n if (!settled) {\n settled = true;\n cleanup();\n resolvePromise({ completed: true });\n }\n return;\n }\n\n sendJson(res, 404, { error: 'Not found' });\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Internal error';\n sendJson(res, 500, { error: message });\n }\n });\n\n timer = setTimeout(() => {\n if (!settled) {\n settled = true;\n cleanup();\n rejectPromise(new TimeoutError('Setup timed out after 10 minutes.'));\n }\n }, TIMEOUT_MS);\n\n serverInstance.on('error', (err) => {\n if (!settled) {\n settled = true;\n cleanup();\n rejectPromise(err);\n }\n });\n\n let portValue = 0;\n const handle: SetupServerHandle = {\n server: serverInstance,\n token: nonce,\n get port() { return portValue; },\n promise,\n };\n\n serverInstance.listen(0, '127.0.0.1', () => {\n const addr = serverInstance.address();\n if (!addr || typeof addr === 'string') {\n if (!settled) {\n settled = true;\n cleanup();\n rejectPromise(new Error('Failed to bind server'));\n }\n return;\n }\n portValue = addr.port;\n const pageUrl = `http://127.0.0.1:${addr.port}/setup?token=${nonce}`;\n\n if (options?.openBrowser !== false) {\n console.log('Opening setup form in browser...');\n openBrowser(pageUrl);\n }\n });\n\n return handle;\n}\n\n/**\n * Launch an ephemeral HTTP server on localhost, open a browser page\n * where the human fills in credentials, passphrase, and budget.\n * All sensitive data stays in the browser->server HTTP request on localhost.\n * Never touches stdout/terminal.\n */\nexport function requestBrowserSetup(home?: string): Promise<SetupResult> {\n const handle = createSetupServer({ openBrowser: true, home });\n return handle.promise;\n}\n","export function getSetupHtml(token: string): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>AgentPay — Setup</title>\n<style>\n *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n background: #f5f5f5;\n color: #111;\n min-height: 100vh;\n display: flex;\n justify-content: center;\n padding: 40px 16px;\n }\n .container { width: 100%; max-width: 480px; }\n h1 { font-size: 24px; font-weight: 700; margin-bottom: 4px; }\n .subtitle { color: #666; font-size: 14px; margin-bottom: 24px; }\n .card {\n background: #fff;\n border-radius: 8px;\n padding: 24px;\n margin-bottom: 16px;\n border: 1px solid #e0e0e0;\n }\n .card-title {\n font-size: 15px;\n font-weight: 600;\n margin-bottom: 16px;\n padding-bottom: 8px;\n border-bottom: 1px solid #f0f0f0;\n }\n label { display: block; font-size: 13px; font-weight: 500; color: #333; margin-bottom: 6px; }\n input[type=\"text\"], input[type=\"password\"], input[type=\"email\"], input[type=\"tel\"], input[type=\"number\"] {\n width: 100%;\n padding: 12px 14px;\n border: 1px solid #d0d0d0;\n border-radius: 8px;\n font-size: 15px;\n font-family: inherit;\n outline: none;\n transition: border-color 0.15s;\n }\n input:focus { border-color: #111; }\n .field { margin-bottom: 14px; }\n .field:last-child { margin-bottom: 0; }\n .row { display: flex; gap: 12px; }\n .row > .field { flex: 1; }\n .checkbox-row {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 14px;\n }\n .checkbox-row input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n }\n .checkbox-row label {\n margin-bottom: 0;\n cursor: pointer;\n font-size: 14px;\n }\n .btn-submit {\n width: 100%;\n padding: 14px;\n border: none;\n border-radius: 8px;\n font-size: 15px;\n font-weight: 600;\n cursor: pointer;\n background: #111;\n color: #fff;\n transition: opacity 0.15s;\n }\n .btn-submit:hover { opacity: 0.85; }\n .btn-submit:disabled { opacity: 0.5; cursor: not-allowed; }\n .error { color: #c62828; font-size: 13px; margin-top: 10px; }\n .success-screen {\n text-align: center;\n padding: 40px 0;\n }\n .checkmark { font-size: 48px; margin-bottom: 16px; color: #2e7d32; }\n .success-msg { font-size: 16px; font-weight: 600; margin-bottom: 8px; }\n .success-hint { font-size: 13px; color: #666; }\n .hidden { display: none; }\n .hint { font-size: 12px; color: #999; margin-top: 4px; }\n</style>\n</head>\n<body>\n<div class=\"container\">\n <div id=\"form-view\">\n <h1>AgentPay</h1>\n <p class=\"subtitle\">Initial Setup</p>\n\n <div class=\"card\">\n <div class=\"card-title\">Passphrase</div>\n <div class=\"field\">\n <label for=\"passphrase\">Choose a passphrase</label>\n <input type=\"password\" id=\"passphrase\" placeholder=\"Enter passphrase\" autofocus>\n </div>\n <div class=\"field\">\n <label for=\"passphrase-confirm\">Confirm passphrase</label>\n <input type=\"password\" id=\"passphrase-confirm\" placeholder=\"Re-enter passphrase\">\n </div>\n </div>\n\n <div class=\"card\">\n <div class=\"card-title\">Budget</div>\n <div class=\"row\">\n <div class=\"field\">\n <label for=\"budget\">Total budget ($)</label>\n <input type=\"number\" id=\"budget\" placeholder=\"0\" min=\"0\" step=\"0.01\">\n </div>\n <div class=\"field\">\n <label for=\"limit-per-tx\">Per-transaction limit ($)</label>\n <input type=\"number\" id=\"limit-per-tx\" placeholder=\"0\" min=\"0\" step=\"0.01\">\n </div>\n </div>\n <div class=\"hint\">Leave at 0 to set later via <code>agentpay budget</code>.</div>\n </div>\n\n <div class=\"card\">\n <div class=\"card-title\">Card</div>\n <div class=\"field\">\n <label for=\"card-number\">Card number</label>\n <input type=\"text\" id=\"card-number\" placeholder=\"4111 1111 1111 1111\" autocomplete=\"cc-number\">\n </div>\n <div class=\"row\">\n <div class=\"field\">\n <label for=\"card-expiry\">Expiry (MM/YY)</label>\n <input type=\"text\" id=\"card-expiry\" placeholder=\"MM/YY\" autocomplete=\"cc-exp\" maxlength=\"5\">\n </div>\n <div class=\"field\">\n <label for=\"card-cvv\">CVV</label>\n <input type=\"text\" id=\"card-cvv\" placeholder=\"123\" autocomplete=\"cc-csc\" maxlength=\"4\">\n </div>\n </div>\n </div>\n\n <div class=\"card\">\n <div class=\"card-title\">Personal</div>\n <div class=\"field\">\n <label for=\"name\">Full name</label>\n <input type=\"text\" id=\"name\" placeholder=\"Jane Doe\" autocomplete=\"name\">\n </div>\n <div class=\"row\">\n <div class=\"field\">\n <label for=\"email\">Email</label>\n <input type=\"email\" id=\"email\" placeholder=\"jane@example.com\" autocomplete=\"email\">\n </div>\n <div class=\"field\">\n <label for=\"phone\">Phone</label>\n <input type=\"tel\" id=\"phone\" placeholder=\"+1 555-0100\" autocomplete=\"tel\">\n </div>\n </div>\n </div>\n\n <div class=\"card\">\n <div class=\"card-title\">Billing Address</div>\n <div class=\"field\">\n <label for=\"billing-street\">Street</label>\n <input type=\"text\" id=\"billing-street\" autocomplete=\"billing street-address\">\n </div>\n <div class=\"row\">\n <div class=\"field\">\n <label for=\"billing-city\">City</label>\n <input type=\"text\" id=\"billing-city\" autocomplete=\"billing address-level2\">\n </div>\n <div class=\"field\">\n <label for=\"billing-state\">State</label>\n <input type=\"text\" id=\"billing-state\" autocomplete=\"billing address-level1\">\n </div>\n </div>\n <div class=\"row\">\n <div class=\"field\">\n <label for=\"billing-zip\">ZIP</label>\n <input type=\"text\" id=\"billing-zip\" autocomplete=\"billing postal-code\">\n </div>\n <div class=\"field\">\n <label for=\"billing-country\">Country</label>\n <input type=\"text\" id=\"billing-country\" placeholder=\"US\" autocomplete=\"billing country\">\n </div>\n </div>\n </div>\n\n <div class=\"card\">\n <div class=\"card-title\">Shipping Address</div>\n <div class=\"checkbox-row\">\n <input type=\"checkbox\" id=\"same-as-billing\" checked>\n <label for=\"same-as-billing\">Same as billing</label>\n </div>\n <div id=\"shipping-fields\" class=\"hidden\">\n <div class=\"field\">\n <label for=\"shipping-street\">Street</label>\n <input type=\"text\" id=\"shipping-street\" autocomplete=\"shipping street-address\">\n </div>\n <div class=\"row\">\n <div class=\"field\">\n <label for=\"shipping-city\">City</label>\n <input type=\"text\" id=\"shipping-city\" autocomplete=\"shipping address-level2\">\n </div>\n <div class=\"field\">\n <label for=\"shipping-state\">State</label>\n <input type=\"text\" id=\"shipping-state\" autocomplete=\"shipping address-level1\">\n </div>\n </div>\n <div class=\"row\">\n <div class=\"field\">\n <label for=\"shipping-zip\">ZIP</label>\n <input type=\"text\" id=\"shipping-zip\" autocomplete=\"shipping postal-code\">\n </div>\n <div class=\"field\">\n <label for=\"shipping-country\">Country</label>\n <input type=\"text\" id=\"shipping-country\" placeholder=\"US\" autocomplete=\"shipping country\">\n </div>\n </div>\n </div>\n </div>\n\n <div id=\"error\" class=\"error hidden\"></div>\n <button class=\"btn-submit\" id=\"btn-submit\">Complete Setup</button>\n </div>\n\n <div id=\"success-view\" class=\"hidden\">\n <h1>AgentPay</h1>\n <p class=\"subtitle\">Setup Complete</p>\n <div class=\"card\">\n <div class=\"success-screen\">\n <div class=\"checkmark\">&#10003;</div>\n <div class=\"success-msg\">Your wallet is ready.</div>\n <div class=\"success-hint\">You can close this tab and return to the terminal.</div>\n </div>\n </div>\n </div>\n</div>\n<script>\n(function() {\n var token = ${JSON.stringify(token)};\n var formView = document.getElementById('form-view');\n var successView = document.getElementById('success-view');\n var btnSubmit = document.getElementById('btn-submit');\n var errDiv = document.getElementById('error');\n var sameAsBilling = document.getElementById('same-as-billing');\n var shippingFields = document.getElementById('shipping-fields');\n\n sameAsBilling.addEventListener('change', function() {\n shippingFields.classList.toggle('hidden', sameAsBilling.checked);\n });\n\n function val(id) { return document.getElementById(id).value.trim(); }\n\n function showError(msg) {\n errDiv.textContent = msg;\n errDiv.classList.remove('hidden');\n }\n\n function clearError() {\n errDiv.classList.add('hidden');\n }\n\n btnSubmit.addEventListener('click', function() {\n clearError();\n\n var passphrase = val('passphrase');\n var passphraseConfirm = val('passphrase-confirm');\n\n if (!passphrase) { showError('Passphrase is required.'); return; }\n if (passphrase !== passphraseConfirm) { showError('Passphrases do not match.'); return; }\n\n var cardNumber = val('card-number');\n var cardExpiry = val('card-expiry');\n var cardCvv = val('card-cvv');\n if (!cardNumber || !cardExpiry || !cardCvv) { showError('Card number, expiry, and CVV are required.'); return; }\n\n var name = val('name');\n var email = val('email');\n var phone = val('phone');\n if (!name || !email || !phone) { showError('Name, email, and phone are required.'); return; }\n\n var billingStreet = val('billing-street');\n var billingCity = val('billing-city');\n var billingState = val('billing-state');\n var billingZip = val('billing-zip');\n var billingCountry = val('billing-country');\n if (!billingStreet || !billingCity || !billingState || !billingZip || !billingCountry) {\n showError('All billing address fields are required.'); return;\n }\n\n var shippingStreet, shippingCity, shippingState, shippingZip, shippingCountry;\n if (sameAsBilling.checked) {\n shippingStreet = billingStreet;\n shippingCity = billingCity;\n shippingState = billingState;\n shippingZip = billingZip;\n shippingCountry = billingCountry;\n } else {\n shippingStreet = val('shipping-street');\n shippingCity = val('shipping-city');\n shippingState = val('shipping-state');\n shippingZip = val('shipping-zip');\n shippingCountry = val('shipping-country');\n if (!shippingStreet || !shippingCity || !shippingState || !shippingZip || !shippingCountry) {\n showError('All shipping address fields are required.'); return;\n }\n }\n\n var budget = parseFloat(document.getElementById('budget').value) || 0;\n var limitPerTx = parseFloat(document.getElementById('limit-per-tx').value) || 0;\n\n btnSubmit.disabled = true;\n btnSubmit.textContent = 'Setting up...';\n\n fetch('/api/setup', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n token: token,\n passphrase: passphrase,\n budget: budget,\n limitPerTx: limitPerTx,\n card: { number: cardNumber, expiry: cardExpiry, cvv: cardCvv },\n name: name,\n email: email,\n phone: phone,\n billingAddress: { street: billingStreet, city: billingCity, state: billingState, zip: billingZip, country: billingCountry },\n shippingAddress: { street: shippingStreet, city: shippingCity, state: shippingState, zip: shippingZip, country: shippingCountry }\n })\n })\n .then(function(res) { return res.json(); })\n .then(function(data) {\n if (data.error) {\n showError(data.error);\n btnSubmit.disabled = false;\n btnSubmit.textContent = 'Complete Setup';\n } else {\n formView.classList.add('hidden');\n successView.classList.remove('hidden');\n setTimeout(function() { window.close(); }, 3000);\n }\n })\n .catch(function() {\n showError('Failed to submit. Is the CLI still running?');\n btnSubmit.disabled = false;\n btnSubmit.textContent = 'Complete Setup';\n });\n });\n})();\n</script>\n</body>\n</html>`;\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from 'node:http';\nimport { getDashboardHtml } from './html.js';\nimport { handleGetStatus, handlePostSetup, handlePostFund } from './routes.js';\n\nconst MAX_BODY = 1_048_576; // 1 MB\n\nfunction parseBody(req: IncomingMessage): Promise<Record<string, unknown>> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n req.on('data', (chunk: Buffer) => {\n size += chunk.length;\n if (size > MAX_BODY) {\n req.destroy();\n reject(new Error('Request body too large'));\n return;\n }\n chunks.push(chunk);\n });\n req.on('end', () => {\n try {\n const text = Buffer.concat(chunks).toString('utf8');\n resolve(text ? JSON.parse(text) : {});\n } catch {\n reject(new Error('Invalid JSON'));\n }\n });\n req.on('error', reject);\n });\n}\n\nfunction sendJson(res: ServerResponse, status: number, body: Record<string, unknown>): void {\n const json = JSON.stringify(body);\n res.writeHead(status, {\n 'Content-Type': 'application/json',\n 'Content-Length': Buffer.byteLength(json),\n });\n res.end(json);\n}\n\nfunction sendHtml(res: ServerResponse, html: string): void {\n res.writeHead(200, {\n 'Content-Type': 'text/html; charset=utf-8',\n 'Content-Length': Buffer.byteLength(html),\n });\n res.end(html);\n}\n\nexport function startServer(port: number): Promise<ReturnType<typeof createServer>> {\n return new Promise((resolve, reject) => {\n const server = createServer(async (req, res) => {\n const url = req.url ?? '/';\n const method = req.method ?? 'GET';\n\n try {\n if (method === 'GET' && url === '/api/status') {\n const result = handleGetStatus();\n sendJson(res, result.status, result.body);\n } else if (method === 'POST' && url === '/api/setup') {\n const body = await parseBody(req);\n const result = handlePostSetup(body as unknown as Parameters<typeof handlePostSetup>[0]);\n sendJson(res, result.status, result.body);\n } else if (method === 'POST' && url === '/api/fund') {\n const body = await parseBody(req);\n const result = handlePostFund(body as unknown as Parameters<typeof handlePostFund>[0]);\n sendJson(res, result.status, result.body);\n } else if (method === 'GET' && (url === '/' || url === '/index.html')) {\n sendHtml(res, getDashboardHtml());\n } else {\n sendJson(res, 404, { error: 'Not found' });\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Internal error';\n sendJson(res, 500, { error: message });\n }\n });\n\n server.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n reject(new Error(`Port ${port} is already in use. Try a different port with --port <number>.`));\n } else {\n reject(err);\n }\n });\n\n server.listen(port, '127.0.0.1', () => {\n resolve(server);\n });\n });\n}\n","export function getDashboardHtml(): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>AgentPay Dashboard</title>\n<style>\n *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n background: #f5f5f5;\n color: #111;\n min-height: 100vh;\n display: flex;\n justify-content: center;\n padding: 40px 16px;\n }\n .container { width: 100%; max-width: 480px; }\n h1 { font-size: 24px; font-weight: 700; margin-bottom: 8px; }\n h2 { font-size: 18px; font-weight: 600; margin-bottom: 12px; }\n .subtitle { color: #666; font-size: 14px; margin-bottom: 32px; }\n .card {\n background: #fff;\n border-radius: 8px;\n padding: 24px;\n margin-bottom: 16px;\n border: 1px solid #e0e0e0;\n }\n label { display: block; font-size: 13px; font-weight: 500; color: #333; margin-bottom: 4px; }\n input, select {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid #d0d0d0;\n border-radius: 8px;\n font-size: 14px;\n margin-bottom: 16px;\n outline: none;\n transition: border-color 0.15s;\n }\n input:focus { border-color: #111; }\n .row { display: flex; gap: 12px; }\n .row > div { flex: 1; }\n button {\n width: 100%;\n padding: 12px;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: opacity 0.15s;\n }\n button:hover { opacity: 0.85; }\n button:disabled { opacity: 0.5; cursor: not-allowed; }\n .btn-primary { background: #111; color: #fff; }\n .btn-secondary { background: #e0e0e0; color: #111; }\n\n /* Progress bar for wizard */\n .progress { display: flex; gap: 6px; margin-bottom: 24px; }\n .progress .step {\n flex: 1; height: 4px; border-radius: 2px; background: #e0e0e0;\n transition: background 0.3s;\n }\n .progress .step.active { background: #111; }\n\n /* Balance display */\n .balance-display {\n text-align: center;\n padding: 32px 0;\n }\n .balance-amount {\n font-size: 48px;\n font-weight: 700;\n letter-spacing: -1px;\n }\n .balance-label { font-size: 13px; color: #666; margin-top: 4px; }\n\n /* Budget bar */\n .budget-bar-container { margin: 16px 0; }\n .budget-bar {\n height: 8px;\n background: #e0e0e0;\n border-radius: 4px;\n overflow: hidden;\n }\n .budget-bar-fill {\n height: 100%;\n background: #111;\n border-radius: 4px;\n transition: width 0.3s;\n }\n .budget-bar-labels {\n display: flex;\n justify-content: space-between;\n font-size: 12px;\n color: #666;\n margin-top: 4px;\n }\n\n /* Stats grid */\n .stats { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 16px; }\n .stat { text-align: center; padding: 12px; background: #f9f9f9; border-radius: 8px; }\n .stat-value { font-size: 18px; font-weight: 700; }\n .stat-label { font-size: 11px; color: #666; margin-top: 2px; }\n\n /* Add funds inline */\n .add-funds-row { display: flex; gap: 8px; }\n .add-funds-row input { margin-bottom: 0; flex: 1; }\n .add-funds-row button { width: auto; padding: 10px 20px; }\n\n /* Transactions */\n .tx-list { margin-top: 12px; }\n .tx-item {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 10px 0;\n border-bottom: 1px solid #f0f0f0;\n font-size: 13px;\n }\n .tx-item:last-child { border-bottom: none; }\n .tx-merchant { font-weight: 500; }\n .tx-amount { font-weight: 600; }\n .tx-status {\n font-size: 11px;\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 500;\n }\n .tx-status.completed { background: #e6f4ea; color: #1e7e34; }\n .tx-status.pending { background: #fff8e1; color: #f57f17; }\n .tx-status.failed { background: #fde8e8; color: #c62828; }\n .tx-status.rejected { background: #fde8e8; color: #c62828; }\n .tx-status.approved { background: #e3f2fd; color: #1565c0; }\n .tx-status.executing { background: #e3f2fd; color: #1565c0; }\n\n .error { color: #c62828; font-size: 13px; margin-top: 8px; }\n .success { color: #1e7e34; font-size: 13px; margin-top: 8px; }\n .hidden { display: none; }\n\n /* Checkbox row for same-as-billing */\n .checkbox-row {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 16px;\n }\n .checkbox-row input { width: auto; margin: 0; }\n .checkbox-row label { margin: 0; }\n</style>\n</head>\n<body>\n<div class=\"container\" id=\"app\">\n <div id=\"loading\">Loading...</div>\n</div>\n\n<script>\nconst App = {\n state: { isSetup: false, wallet: null, recentTransactions: [], wizardStep: 1 },\n\n async init() {\n try {\n const res = await fetch('/api/status');\n const data = await res.json();\n this.state.isSetup = data.isSetup;\n this.state.wallet = data.wallet;\n this.state.recentTransactions = data.recentTransactions || [];\n } catch (e) {\n console.error('Failed to load status', e);\n }\n this.render();\n },\n\n render() {\n const app = document.getElementById('app');\n if (this.state.isSetup && this.state.wallet) {\n app.innerHTML = this.renderDashboard();\n this.bindDashboard();\n } else if (this.state.isSetup) {\n app.innerHTML = '<div class=\"card\"><h2>Setup detected</h2><p>Wallet data could not be loaded. Try running <code>agentpay budget --set 100</code> from the CLI.</p></div>';\n } else {\n app.innerHTML = this.renderWizard();\n this.bindWizard();\n }\n },\n\n fmt(n) {\n return '$' + Number(n).toFixed(2);\n },\n\n renderDashboard() {\n const w = this.state.wallet;\n const pct = w.budget > 0 ? Math.min(100, (w.spent / w.budget) * 100) : 0;\n const txHtml = this.state.recentTransactions.length === 0\n ? '<p style=\"color:#666;font-size:13px;\">No transactions yet.</p>'\n : this.state.recentTransactions.map(tx => \\`\n <div class=\"tx-item\">\n <div>\n <div class=\"tx-merchant\">\\${this.esc(tx.merchant)}</div>\n <div style=\"color:#999;font-size:11px;\">\\${new Date(tx.createdAt).toLocaleDateString()}</div>\n </div>\n <div style=\"text-align:right\">\n <div class=\"tx-amount\">\\${this.fmt(tx.amount)}</div>\n <span class=\"tx-status \\${tx.status}\">\\${tx.status}</span>\n </div>\n </div>\\`).join('');\n\n return \\`\n <h1>AgentPay</h1>\n <p class=\"subtitle\">Wallet Dashboard</p>\n\n <div class=\"card\">\n <div class=\"balance-display\">\n <div class=\"balance-amount\">\\${this.fmt(w.balance)}</div>\n <div class=\"balance-label\">Available Balance</div>\n </div>\n <div class=\"budget-bar-container\">\n <div class=\"budget-bar\"><div class=\"budget-bar-fill\" style=\"width:\\${pct.toFixed(1)}%\"></div></div>\n <div class=\"budget-bar-labels\">\n <span>\\${this.fmt(w.spent)} spent</span>\n <span>\\${this.fmt(w.budget)} budget</span>\n </div>\n </div>\n </div>\n\n <div class=\"card\">\n <div class=\"stats\">\n <div class=\"stat\"><div class=\"stat-value\">\\${this.fmt(w.budget)}</div><div class=\"stat-label\">Total Budget</div></div>\n <div class=\"stat\"><div class=\"stat-value\">\\${this.fmt(w.spent)}</div><div class=\"stat-label\">Total Spent</div></div>\n <div class=\"stat\"><div class=\"stat-value\">\\${this.fmt(w.balance)}</div><div class=\"stat-label\">Remaining</div></div>\n <div class=\"stat\"><div class=\"stat-value\">\\${w.limitPerTx > 0 ? this.fmt(w.limitPerTx) : 'None'}</div><div class=\"stat-label\">Per-Tx Limit</div></div>\n </div>\n </div>\n\n <div class=\"card\">\n <h2>Add Funds</h2>\n <div class=\"add-funds-row\">\n <input type=\"number\" id=\"fundAmount\" placeholder=\"Amount\" min=\"0.01\" step=\"0.01\">\n <button class=\"btn-primary\" id=\"fundBtn\">Add</button>\n </div>\n <div id=\"fundMsg\"></div>\n </div>\n\n <div class=\"card\">\n <h2>Recent Transactions</h2>\n <div class=\"tx-list\">\\${txHtml}</div>\n </div>\n \\`;\n },\n\n bindDashboard() {\n const btn = document.getElementById('fundBtn');\n const input = document.getElementById('fundAmount');\n const msg = document.getElementById('fundMsg');\n\n btn.addEventListener('click', async () => {\n const amount = parseFloat(input.value);\n if (!amount || amount <= 0) {\n msg.innerHTML = '<p class=\"error\">Enter a valid amount.</p>';\n return;\n }\n btn.disabled = true;\n btn.textContent = '...';\n try {\n const res = await fetch('/api/fund', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ amount }),\n });\n const data = await res.json();\n if (data.error) {\n msg.innerHTML = '<p class=\"error\">' + this.esc(data.error) + '</p>';\n } else {\n this.state.wallet = data.wallet;\n input.value = '';\n this.render();\n }\n } catch (e) {\n msg.innerHTML = '<p class=\"error\">Request failed.</p>';\n }\n btn.disabled = false;\n btn.textContent = 'Add';\n });\n },\n\n renderWizard() {\n const step = this.state.wizardStep;\n const steps = [1, 2, 3, 4];\n const progressHtml = '<div class=\"progress\">' + steps.map(s =>\n '<div class=\"step' + (s <= step ? ' active' : '') + '\"></div>'\n ).join('') + '</div>';\n\n const titles = ['Create Passphrase', 'Card Information', 'Personal Details', 'Budget & Limits'];\n\n let fields = '';\n if (step === 1) {\n fields = \\`\n <label for=\"w_pass\">Passphrase</label>\n <input type=\"password\" id=\"w_pass\" placeholder=\"Choose a strong passphrase\">\n <label for=\"w_pass2\">Confirm Passphrase</label>\n <input type=\"password\" id=\"w_pass2\" placeholder=\"Confirm your passphrase\">\n \\`;\n } else if (step === 2) {\n fields = \\`\n <label for=\"w_cardNum\">Card Number</label>\n <input type=\"text\" id=\"w_cardNum\" placeholder=\"4242 4242 4242 4242\">\n <div class=\"row\">\n <div><label for=\"w_expiry\">Expiry</label><input type=\"text\" id=\"w_expiry\" placeholder=\"MM/YY\"></div>\n <div><label for=\"w_cvv\">CVV</label><input type=\"text\" id=\"w_cvv\" placeholder=\"123\"></div>\n </div>\n \\`;\n } else if (step === 3) {\n fields = \\`\n <label for=\"w_name\">Full Name</label>\n <input type=\"text\" id=\"w_name\" placeholder=\"Jane Doe\">\n <div class=\"row\">\n <div><label for=\"w_email\">Email</label><input type=\"email\" id=\"w_email\" placeholder=\"jane@example.com\"></div>\n <div><label for=\"w_phone\">Phone</label><input type=\"tel\" id=\"w_phone\" placeholder=\"+1 555 0123\"></div>\n </div>\n <label for=\"w_street\">Street Address</label>\n <input type=\"text\" id=\"w_street\" placeholder=\"123 Main St\">\n <div class=\"row\">\n <div><label for=\"w_city\">City</label><input type=\"text\" id=\"w_city\" placeholder=\"San Francisco\"></div>\n <div><label for=\"w_state\">State</label><input type=\"text\" id=\"w_state\" placeholder=\"CA\"></div>\n </div>\n <div class=\"row\">\n <div><label for=\"w_zip\">ZIP</label><input type=\"text\" id=\"w_zip\" placeholder=\"94102\"></div>\n <div><label for=\"w_country\">Country</label><input type=\"text\" id=\"w_country\" placeholder=\"US\" value=\"US\"></div>\n </div>\n \\`;\n } else if (step === 4) {\n fields = \\`\n <label for=\"w_budget\">Initial Budget ($)</label>\n <input type=\"number\" id=\"w_budget\" placeholder=\"200\" min=\"0\" step=\"0.01\">\n <label for=\"w_limit\">Per-Transaction Limit ($)</label>\n <input type=\"number\" id=\"w_limit\" placeholder=\"50 (0 = no limit)\" min=\"0\" step=\"0.01\">\n \\`;\n }\n\n return \\`\n <h1>AgentPay</h1>\n <p class=\"subtitle\">Step \\${step} of 4 — \\${titles[step - 1]}</p>\n \\${progressHtml}\n <div class=\"card\">\n \\${fields}\n <div id=\"wizardError\"></div>\n <div style=\"display:flex;gap:8px;margin-top:8px;\">\n \\${step > 1 ? '<button class=\"btn-secondary\" id=\"wizBack\">Back</button>' : ''}\n <button class=\"btn-primary\" id=\"wizNext\">\\${step === 4 ? 'Complete Setup' : 'Continue'}</button>\n </div>\n </div>\n \\`;\n },\n\n // Wizard form data persisted across steps\n wizardData: {},\n\n bindWizard() {\n const step = this.state.wizardStep;\n const errDiv = document.getElementById('wizardError');\n const nextBtn = document.getElementById('wizNext');\n const backBtn = document.getElementById('wizBack');\n\n // Restore saved data into fields\n this.restoreWizardFields(step);\n\n if (backBtn) {\n backBtn.addEventListener('click', () => {\n this.saveWizardFields(step);\n this.state.wizardStep--;\n this.render();\n });\n }\n\n nextBtn.addEventListener('click', async () => {\n errDiv.innerHTML = '';\n\n if (step === 1) {\n const pass = document.getElementById('w_pass').value;\n const pass2 = document.getElementById('w_pass2').value;\n if (!pass) { errDiv.innerHTML = '<p class=\"error\">Passphrase is required.</p>'; return; }\n if (pass !== pass2) { errDiv.innerHTML = '<p class=\"error\">Passphrases do not match.</p>'; return; }\n this.wizardData.passphrase = pass;\n this.state.wizardStep = 2;\n this.render();\n } else if (step === 2) {\n this.saveWizardFields(step);\n const d = this.wizardData;\n if (!d.cardNumber) { errDiv.innerHTML = '<p class=\"error\">Card number is required.</p>'; return; }\n if (!d.expiry) { errDiv.innerHTML = '<p class=\"error\">Expiry is required.</p>'; return; }\n if (!d.cvv) { errDiv.innerHTML = '<p class=\"error\">CVV is required.</p>'; return; }\n this.state.wizardStep = 3;\n this.render();\n } else if (step === 3) {\n this.saveWizardFields(step);\n const d = this.wizardData;\n if (!d.name) { errDiv.innerHTML = '<p class=\"error\">Full name is required.</p>'; return; }\n this.state.wizardStep = 4;\n this.render();\n } else if (step === 4) {\n this.saveWizardFields(step);\n const d = this.wizardData;\n\n nextBtn.disabled = true;\n nextBtn.textContent = 'Setting up...';\n\n try {\n const res = await fetch('/api/setup', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n passphrase: d.passphrase,\n credentials: {\n card: { number: d.cardNumber, expiry: d.expiry, cvv: d.cvv },\n name: d.name,\n billingAddress: { street: d.street || '', city: d.city || '', state: d.state || '', zip: d.zip || '', country: d.country || 'US' },\n shippingAddress: { street: d.street || '', city: d.city || '', state: d.state || '', zip: d.zip || '', country: d.country || 'US' },\n email: d.email || '',\n phone: d.phone || '',\n },\n budget: parseFloat(d.budget) || 0,\n limitPerTx: parseFloat(d.limit) || 0,\n }),\n });\n const result = await res.json();\n if (result.error) {\n errDiv.innerHTML = '<p class=\"error\">' + this.esc(result.error) + '</p>';\n nextBtn.disabled = false;\n nextBtn.textContent = 'Complete Setup';\n } else {\n this.state.isSetup = true;\n this.state.wallet = result.wallet;\n this.state.recentTransactions = [];\n this.wizardData = {};\n this.render();\n }\n } catch (e) {\n errDiv.innerHTML = '<p class=\"error\">Setup request failed.</p>';\n nextBtn.disabled = false;\n nextBtn.textContent = 'Complete Setup';\n }\n }\n });\n },\n\n saveWizardFields(step) {\n const val = (id) => { const el = document.getElementById(id); return el ? el.value : ''; };\n if (step === 2) {\n this.wizardData.cardNumber = val('w_cardNum');\n this.wizardData.expiry = val('w_expiry');\n this.wizardData.cvv = val('w_cvv');\n } else if (step === 3) {\n this.wizardData.name = val('w_name');\n this.wizardData.email = val('w_email');\n this.wizardData.phone = val('w_phone');\n this.wizardData.street = val('w_street');\n this.wizardData.city = val('w_city');\n this.wizardData.state = val('w_state');\n this.wizardData.zip = val('w_zip');\n this.wizardData.country = val('w_country');\n } else if (step === 4) {\n this.wizardData.budget = val('w_budget');\n this.wizardData.limit = val('w_limit');\n }\n },\n\n restoreWizardFields(step) {\n const set = (id, val) => { const el = document.getElementById(id); if (el && val) el.value = val; };\n if (step === 2) {\n set('w_cardNum', this.wizardData.cardNumber);\n set('w_expiry', this.wizardData.expiry);\n set('w_cvv', this.wizardData.cvv);\n } else if (step === 3) {\n set('w_name', this.wizardData.name);\n set('w_email', this.wizardData.email);\n set('w_phone', this.wizardData.phone);\n set('w_street', this.wizardData.street);\n set('w_city', this.wizardData.city);\n set('w_state', this.wizardData.state);\n set('w_zip', this.wizardData.zip);\n set('w_country', this.wizardData.country);\n } else if (step === 4) {\n set('w_budget', this.wizardData.budget);\n set('w_limit', this.wizardData.limit);\n }\n },\n\n esc(s) {\n const d = document.createElement('div');\n d.textContent = s;\n return d.innerHTML;\n },\n};\n\nApp.init();\n</script>\n</body>\n</html>`;\n}\n","import { existsSync, mkdirSync } from 'node:fs';\nimport { encrypt, saveVault } from '../vault/vault.js';\nimport { generateKeyPair, saveKeyPair } from '../auth/keypair.js';\nimport { BudgetManager } from '../budget/budget.js';\nimport { TransactionManager } from '../transactions/manager.js';\nimport { AuditLogger } from '../audit/logger.js';\nimport { getCredentialsPath, getHomePath, getKeysPath } from '../utils/paths.js';\nimport type { BillingCredentials } from '../vault/types.js';\n\ninterface RouteResult {\n status: number;\n body: Record<string, unknown>;\n}\n\nexport function handleGetStatus(): RouteResult {\n const isSetup = existsSync(getCredentialsPath());\n\n if (!isSetup) {\n return { status: 200, body: { isSetup: false } };\n }\n\n try {\n const bm = new BudgetManager();\n const wallet = bm.getBalance();\n const tm = new TransactionManager();\n const recent = tm.list().slice(-10).reverse();\n\n return {\n status: 200,\n body: { isSetup: true, wallet, recentTransactions: recent },\n };\n } catch {\n return { status: 200, body: { isSetup: true, wallet: null, recentTransactions: [] } };\n }\n}\n\ninterface SetupBody {\n passphrase: string;\n credentials: BillingCredentials;\n budget: number;\n limitPerTx: number;\n}\n\nexport function handlePostSetup(body: SetupBody): RouteResult {\n if (!body.passphrase || !body.credentials) {\n return { status: 400, body: { error: 'Missing passphrase or credentials' } };\n }\n\n try {\n const home = getHomePath();\n mkdirSync(home, { recursive: true });\n\n // Encrypt and save vault\n const vault = encrypt(body.credentials, body.passphrase);\n saveVault(vault, getCredentialsPath());\n\n // Generate and save keypair\n const keys = generateKeyPair(body.passphrase);\n mkdirSync(getKeysPath(), { recursive: true });\n saveKeyPair(keys);\n\n // Initialize wallet\n const bm = new BudgetManager();\n bm.initWallet(body.budget || 0, body.limitPerTx || 0);\n\n // Audit\n const audit = new AuditLogger();\n audit.log('SETUP', { source: 'dashboard', message: 'credentials encrypted, keypair generated, wallet initialized' });\n\n const wallet = bm.getBalance();\n return { status: 200, body: { success: true, wallet } };\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Setup failed';\n return { status: 500, body: { error: message } };\n }\n}\n\ninterface FundBody {\n amount: number;\n}\n\nexport function handlePostFund(body: FundBody): RouteResult {\n if (!body.amount || body.amount <= 0) {\n return { status: 400, body: { error: 'Amount must be positive' } };\n }\n\n try {\n const bm = new BudgetManager();\n const wallet = bm.addFunds(body.amount);\n\n const audit = new AuditLogger();\n audit.log('ADD_FUNDS', { source: 'dashboard', amount: body.amount });\n\n return { status: 200, body: { success: true, wallet } };\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Failed to add funds';\n return { status: 500, body: { error: message } };\n }\n}\n","import { createInterface } from 'node:readline';\nimport type { PassphraseContext } from '../server/passphrase-html.js';\n\nexport type { PassphraseContext } from '../server/passphrase-html.js';\n\nfunction createRl() {\n return createInterface({ input: process.stdin, output: process.stdout });\n}\n\nexport function promptInput(question: string): Promise<string> {\n return new Promise((resolve) => {\n const rl = createRl();\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\nexport async function promptPassphrase(prompt = 'Passphrase: '): Promise<string> {\n // In a real terminal we'd hide input; for simplicity use standard prompt\n return promptInput(prompt);\n}\n\nexport function promptConfirm(question: string): Promise<boolean> {\n return new Promise((resolve) => {\n const rl = createRl();\n rl.question(`${question} (y/N): `, (answer) => {\n rl.close();\n resolve(answer.trim().toLowerCase() === 'y' || answer.trim().toLowerCase() === 'yes');\n });\n });\n}\n\n/**\n * Collect passphrase safely: uses terminal prompt when stdin is a TTY,\n * otherwise opens a browser page so the human can enter it directly\n * (keeping the passphrase out of the agent's context).\n */\nexport async function promptPassphraseSafe(context?: PassphraseContext): Promise<string> {\n if (process.stdin.isTTY) {\n return promptPassphrase('Enter passphrase: ');\n }\n // Dynamic import to avoid loading server code when not needed\n const { collectPassphrase } = await import('../server/passphrase-server.js');\n return collectPassphrase(context);\n}\n","import { join } from 'node:path';\nimport { BudgetManager } from './budget/budget.js';\nimport { TransactionManager } from './transactions/manager.js';\nimport { AuditLogger } from './audit/logger.js';\nimport { PurchaseExecutor } from './executor/executor.js';\nimport { verifyMandate } from './auth/mandate.js';\nimport { decrypt, loadVault } from './vault/vault.js';\nimport { getHomePath } from './utils/paths.js';\nimport {\n NotApprovedError,\n InvalidMandateError,\n InsufficientBalanceError,\n AlreadyExecutedError,\n} from './errors.js';\nimport type { Transaction, Receipt, ProposeOptions } from './transactions/types.js';\nimport type { TransactionDetails } from './auth/types.js';\nimport type { ExecutorConfig } from './executor/types.js';\n\nexport interface AgentPayOptions {\n home?: string;\n passphrase?: string;\n executor?: ExecutorConfig;\n}\n\nexport class AgentPay {\n public readonly home: string;\n private passphrase?: string;\n private budgetManager: BudgetManager;\n private txManager: TransactionManager;\n private auditLogger: AuditLogger;\n private executor: PurchaseExecutor;\n\n constructor(options?: AgentPayOptions) {\n this.home = options?.home ?? getHomePath();\n this.passphrase = options?.passphrase;\n this.budgetManager = new BudgetManager(join(this.home, 'wallet.json'));\n this.txManager = new TransactionManager(join(this.home, 'transactions.json'));\n this.auditLogger = new AuditLogger(join(this.home, 'audit.log'));\n this.executor = new PurchaseExecutor(options?.executor);\n }\n\n get wallet() {\n const bm = this.budgetManager;\n return {\n getBalance: () => bm.getBalance(),\n getHistory: () => this.txManager.getHistory(),\n getLimits: () => {\n const w = bm.getBalance();\n return { budget: w.budget, limitPerTx: w.limitPerTx, remaining: w.balance };\n },\n };\n }\n\n get transactions() {\n return {\n propose: (options: ProposeOptions): Transaction => {\n this.budgetManager.checkProposal(options.amount);\n const tx = this.txManager.propose(options);\n this.auditLogger.log('PROPOSE', { txId: tx.id, merchant: tx.merchant, amount: tx.amount });\n return tx;\n },\n get: (txId: string) => this.txManager.get(txId),\n waitForApproval: async (txId: string, options?: { pollInterval?: number; timeout?: number }) => {\n const { waitForApproval } = await import('./transactions/poller.js');\n return waitForApproval(txId, this.txManager, options);\n },\n requestApproval: async (txId: string): Promise<{ action: 'approved' | 'rejected'; passphrase?: string; reason?: string }> => {\n const tx = this.txManager.get(txId);\n if (!tx) throw new Error(`Transaction ${txId} not found.`);\n if (tx.status !== 'pending') throw new Error(`Transaction ${txId} is not pending.`);\n\n // Check if private key exists before opening browser\n const { existsSync } = await import('node:fs');\n const keyPath = join(this.home, 'keys', 'private.pem');\n if (!existsSync(keyPath)) {\n throw new Error('Private key not found. Run \"agentpay setup\" first.');\n }\n\n const { requestBrowserApproval } = await import('./server/approval-server.js');\n return requestBrowserApproval(tx, this.txManager, this.auditLogger, this.home);\n },\n execute: async (txId: string): Promise<Receipt> => {\n const tx = this.txManager.get(txId);\n if (!tx) throw new Error(`Transaction ${txId} not found.`);\n\n // Validate state\n if (tx.status === 'completed' || tx.status === 'failed') {\n throw new AlreadyExecutedError(txId);\n }\n if (tx.status !== 'approved') {\n throw new NotApprovedError(txId);\n }\n if (!tx.mandate) {\n throw new InvalidMandateError('No mandate found on approved transaction.');\n }\n\n // Verify mandate\n const txDetails: TransactionDetails = {\n txId: tx.id,\n merchant: tx.merchant,\n amount: tx.amount,\n description: tx.description,\n timestamp: tx.createdAt,\n };\n if (!verifyMandate(tx.mandate, txDetails)) {\n throw new InvalidMandateError();\n }\n\n // Check balance\n this.budgetManager.checkProposal(tx.amount);\n\n // Mark executing\n this.txManager.markExecuting(txId);\n this.auditLogger.log('EXECUTE', { txId, browserbaseSessionStarted: true });\n\n try {\n // Decrypt credentials\n if (!this.passphrase) {\n throw new Error('Passphrase required for execution. Pass it to AgentPay constructor.');\n }\n const vaultPath = join(this.home, 'credentials.enc');\n const vault = loadVault(vaultPath);\n const credentials = decrypt(vault, this.passphrase);\n\n // Execute checkout\n const result = await this.executor.execute(tx, credentials);\n\n // Mark completed and deduct balance\n const receipt: Receipt = {\n id: `rcpt_${txId.replace('tx_', '')}`,\n merchant: tx.merchant,\n amount: tx.amount,\n confirmationId: result.confirmationId ?? 'UNKNOWN',\n completedAt: new Date().toISOString(),\n };\n\n this.txManager.markCompleted(txId, receipt);\n this.budgetManager.deductBalance(tx.amount);\n this.auditLogger.log('COMPLETE', { txId, confirmationId: receipt.confirmationId });\n\n return receipt;\n } catch (err) {\n this.txManager.markFailed(txId, err instanceof Error ? err.message : 'Unknown error');\n this.auditLogger.log('FAILED', { txId, error: err instanceof Error ? err.message : 'Unknown' });\n throw err;\n }\n },\n getReceipt: (txId: string): Receipt | undefined => {\n const tx = this.txManager.get(txId);\n return tx?.receipt;\n },\n };\n }\n\n get audit() {\n return { getLog: () => this.auditLogger.getLog() };\n }\n\n status(): {\n balance: number;\n budget: number;\n limitPerTx: number;\n pending: Transaction[];\n recent: Transaction[];\n isSetup: boolean;\n } {\n try {\n const wallet = this.budgetManager.getBalance();\n const pending = this.txManager.getPending();\n const recent = this.txManager.list().slice(-5);\n return {\n balance: wallet.balance,\n budget: wallet.budget,\n limitPerTx: wallet.limitPerTx,\n pending,\n recent,\n isSetup: true,\n };\n } catch {\n return {\n balance: 0,\n budget: 0,\n limitPerTx: 0,\n pending: [],\n recent: [],\n isSetup: false,\n };\n }\n }\n}\n"],"mappings":"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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAiPO,KAAK,UAAU,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiHrC;;;AD9VA;AAEA;AAGA;AACA;AAGA,IAAMC,cAAa,KAAK,KAAK;AAC7B,IAAMC,YAAW;AAMjB,SAASC,WAAU,KAAwD;AACzE,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,SAAmB,CAAC;AAC1B,QAAI,OAAO;AACX,QAAI,GAAG,QAAQ,CAAC,UAAkB;AAChC,cAAQ,MAAM;AACd,UAAI,OAAOD,WAAU;AACnB,YAAI,QAAQ;AACZ,eAAO,IAAI,MAAM,wBAAwB,CAAC;AAC1C;AAAA,MACF;AACA,aAAO,KAAK,KAAK;AAAA,IACnB,CAAC;AACD,QAAI,GAAG,OAAO,MAAM;AAClB,UAAI;AACF,cAAM,OAAO,OAAO,OAAO,MAAM,EAAE,SAAS,MAAM;AAClD,gBAAQ,OAAO,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC;AAAA,MACtC,QAAQ;AACN,eAAO,IAAI,MAAM,cAAc,CAAC;AAAA,MAClC;AAAA,IACF,CAAC;AACD,QAAI,GAAG,SAAS,MAAM;AAAA,EACxB,CAAC;AACH;AAEA,SAASE,UAAS,KAAqB,QAAgB,MAAqC;AAC1F,QAAM,OAAO,KAAK,UAAU,IAAI;AAChC,MAAI,UAAU,QAAQ;AAAA,IACpB,gBAAgB;AAAA,IAChB,kBAAkB,OAAO,WAAW,IAAI;AAAA,EAC1C,CAAC;AACD,MAAI,IAAI,IAAI;AACd;AAEA,SAASC,UAAS,KAAqB,MAAoB;AACzD,MAAI,UAAU,KAAK;AAAA,IACjB,gBAAgB;AAAA,IAChB,kBAAkB,OAAO,WAAW,IAAI;AAAA,EAC1C,CAAC;AACD,MAAI,IAAI,IAAI;AACd;AAEA,SAAS,iBAAiB,KAA6B;AACrD,SAAO,OAAO,QAAQ,YAAY,IAAI,SAAS;AACjD;AAEA,SAAS,UAAU,KAAoG;AACrH,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,IAAI;AACV,SAAO,iBAAiB,EAAE,MAAM,KAC3B,iBAAiB,EAAE,IAAI,KACvB,iBAAiB,EAAE,KAAK,KACxB,iBAAiB,EAAE,GAAG,KACtB,iBAAiB,EAAE,OAAO;AACjC;AAEA,SAAS,OAAO,KAAsE;AACpF,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,IAAI;AACV,SAAO,iBAAiB,EAAE,MAAM,KAAK,iBAAiB,EAAE,MAAM,KAAK,iBAAiB,EAAE,GAAG;AAC3F;AAaO,SAAS,kBACd,SACmB;AACnB,QAAM,YAAQ,iCAAY,EAAE,EAAE,SAAS,KAAK;AAC5C,MAAI,UAAU;AACd,MAAI,YAAY;AAChB,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,QAAM,UAAU,IAAI,QAAqB,CAAC,SAAS,WAAW;AAC5D,qBAAiB;AACjB,oBAAgB;AAAA,EAClB,CAAC;AAED,WAAS,UAAgB;AACvB,iBAAa,KAAK;AAClB,mBAAe,MAAM;AAAA,EACvB;AAEA,QAAM,OAAO,SAAS,QAAQ,YAAY;AAE1C,uBAAiB,gCAAa,OAAO,KAAK,QAAQ;AAChD,UAAM,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK,UAAU,IAAI,QAAQ,IAAI,EAAE;AAChE,UAAM,SAAS,IAAI,UAAU;AAE7B,QAAI;AAEF,UAAI,WAAW,SAAS,IAAI,aAAa,UAAU;AACjD,cAAM,QAAQ,IAAI,aAAa,IAAI,OAAO;AAC1C,YAAI,UAAU,SAAS,WAAW;AAChC,UAAAA,UAAS,KAAK,mCAAmC;AACjD;AAAA,QACF;AACA,QAAAA,UAAS,KAAK,aAAa,KAAK,CAAC;AACjC;AAAA,MACF;AAGA,UAAI,WAAW,UAAU,IAAI,aAAa,cAAc;AACtD,cAAM,OAAO,MAAMF,WAAU,GAAG;AAChC,YAAI,KAAK,UAAU,SAAS,WAAW;AACrC,UAAAC,UAAS,KAAK,KAAK,EAAE,OAAO,4BAA4B,CAAC;AACzD;AAAA,QACF;AAGA,cAAM,aAAa,KAAK;AACxB,YAAI,CAAC,iBAAiB,UAAU,GAAG;AACjC,UAAAA,UAAS,KAAK,KAAK,EAAE,OAAO,0BAA0B,CAAC;AACvD;AAAA,QACF;AAEA,YAAI,CAAC,OAAO,KAAK,IAAI,GAAG;AACtB,UAAAA,UAAS,KAAK,KAAK,EAAE,OAAO,6CAA6C,CAAC;AAC1E;AAAA,QACF;AAEA,YAAI,CAAC,iBAAiB,KAAK,IAAI,KAAK,CAAC,iBAAiB,KAAK,KAAK,KAAK,CAAC,iBAAiB,KAAK,KAAK,GAAG;AAClG,UAAAA,UAAS,KAAK,KAAK,EAAE,OAAO,uCAAuC,CAAC;AACpE;AAAA,QACF;AAEA,YAAI,CAAC,UAAU,KAAK,cAAc,GAAG;AACnC,UAAAA,UAAS,KAAK,KAAK,EAAE,OAAO,wCAAwC,CAAC;AACrE;AAAA,QACF;AAEA,YAAI,CAAC,UAAU,KAAK,eAAe,GAAG;AACpC,UAAAA,UAAS,KAAK,KAAK,EAAE,OAAO,yCAAyC,CAAC;AACtE;AAAA,QACF;AAEA,YAAI;AAEF,yCAAU,MAAM,EAAE,WAAW,KAAK,CAAC;AAGnC,gBAAM,cAAkC;AAAA,YACtC,MAAM,EAAE,QAAQ,KAAK,KAAK,QAAQ,QAAQ,KAAK,KAAK,QAAQ,KAAK,KAAK,KAAK,IAAI;AAAA,YAC/E,MAAM,KAAK;AAAA,YACX,gBAAgB;AAAA,cACd,QAAS,KAAK,eAA0C;AAAA,cACxD,MAAO,KAAK,eAA0C;AAAA,cACtD,OAAQ,KAAK,eAA0C;AAAA,cACvD,KAAM,KAAK,eAA0C;AAAA,cACrD,SAAU,KAAK,eAA0C;AAAA,YAC3D;AAAA,YACA,iBAAiB;AAAA,cACf,QAAS,KAAK,gBAA2C;AAAA,cACzD,MAAO,KAAK,gBAA2C;AAAA,cACvD,OAAQ,KAAK,gBAA2C;AAAA,cACxD,KAAM,KAAK,gBAA2C;AAAA,cACtD,SAAU,KAAK,gBAA2C;AAAA,YAC5D;AAAA,YACA,OAAO,KAAK;AAAA,YACZ,OAAO,KAAK;AAAA,UACd;AAEA,gBAAM,eAAW,wBAAK,MAAM,iBAAiB;AAC7C,gBAAM,QAAQ,QAAQ,aAAa,UAAU;AAC7C,oBAAU,OAAO,QAAQ;AAGzB,gBAAM,cAAU,wBAAK,MAAM,MAAM;AACjC,yCAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AACtC,gBAAM,OAAO,gBAAgB,UAAU;AACvC,sBAAY,UAAM,wBAAK,SAAS,YAAY,OAAG,wBAAK,SAAS,aAAa,CAAC;AAG3E,gBAAM,SAAS,OAAO,KAAK,WAAW,WAAW,KAAK,SAAS;AAC/D,gBAAM,aAAa,OAAO,KAAK,eAAe,WAAW,KAAK,aAAa;AAC3E,gBAAM,KAAK,IAAI,kBAAc,wBAAK,MAAM,aAAa,CAAC;AACtD,aAAG,WAAW,QAAQ,UAAU;AAGhC,gBAAM,QAAQ,IAAI,gBAAY,wBAAK,MAAM,WAAW,CAAC;AACrD,gBAAM,IAAI,SAAS,EAAE,SAAS,gEAAgE,QAAQ,gBAAgB,CAAC;AAAA,QACzH,SAAS,KAAK;AACZ,gBAAM,MAAM,eAAe,QAAQ,IAAI,UAAU;AACjD,UAAAA,UAAS,KAAK,KAAK,EAAE,OAAO,IAAI,CAAC;AACjC;AAAA,QACF;AAEA,oBAAY;AACZ,QAAAA,UAAS,KAAK,KAAK,EAAE,IAAI,KAAK,CAAC;AAE/B,YAAI,CAAC,SAAS;AACZ,oBAAU;AACV,kBAAQ;AACR,yBAAe,EAAE,WAAW,KAAK,CAAC;AAAA,QACpC;AACA;AAAA,MACF;AAEA,MAAAA,UAAS,KAAK,KAAK,EAAE,OAAO,YAAY,CAAC;AAAA,IAC3C,SAAS,KAAK;AACZ,YAAM,UAAU,eAAe,QAAQ,IAAI,UAAU;AACrD,MAAAA,UAAS,KAAK,KAAK,EAAE,OAAO,QAAQ,CAAC;AAAA,IACvC;AAAA,EACF,CAAC;AAED,UAAQ,WAAW,MAAM;AACvB,QAAI,CAAC,SAAS;AACZ,gBAAU;AACV,cAAQ;AACR,oBAAc,IAAI,aAAa,mCAAmC,CAAC;AAAA,IACrE;AAAA,EACF,GAAGH,WAAU;AAEb,iBAAe,GAAG,SAAS,CAAC,QAAQ;AAClC,QAAI,CAAC,SAAS;AACZ,gBAAU;AACV,cAAQ;AACR,oBAAc,GAAG;AAAA,IACnB;AAAA,EACF,CAAC;AAED,MAAI,YAAY;AAChB,QAAM,SAA4B;AAAA,IAChC,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,IAAI,OAAO;AAAE,aAAO;AAAA,IAAW;AAAA,IAC/B;AAAA,EACF;AAEA,iBAAe,OAAO,GAAG,aAAa,MAAM;AAC1C,UAAM,OAAO,eAAe,QAAQ;AACpC,QAAI,CAAC,QAAQ,OAAO,SAAS,UAAU;AACrC,UAAI,CAAC,SAAS;AACZ,kBAAU;AACV,gBAAQ;AACR,sBAAc,IAAI,MAAM,uBAAuB,CAAC;AAAA,MAClD;AACA;AAAA,IACF;AACA,gBAAY,KAAK;AACjB,UAAM,UAAU,oBAAoB,KAAK,IAAI,gBAAgB,KAAK;AAElE,QAAI,SAAS,gBAAgB,OAAO;AAClC,cAAQ,IAAI,kCAAkC;AAC9C,kBAAY,OAAO;AAAA,IACrB;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAQO,SAAS,oBAAoB,MAAqC;AACvE,QAAM,SAAS,kBAAkB,EAAE,aAAa,MAAM,KAAK,CAAC;AAC5D,SAAO,OAAO;AAChB;;;AEpSA;AAAA,IAAAK,oBAAwE;;;ACAxE;AAAO,SAAS,mBAA2B;AACzC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","names":["import_node_crypto","import_node_fs","import_node_path","import_node_crypto","formatCurrency","import_node_os","import_node_crypto","import_node_path","esc","formatCurrency","parseBody","MAX_BODY","sendJson","sendHtml","TIMEOUT_MS","import_node_http","import_node_crypto","import_node_crypto","import_node_fs","import_node_path","import_node_fs","import_node_path","import_node_fs","import_node_path","import_node_fs","import_node_path","import_node_http","import_node_crypto","import_node_fs","import_node_path","TIMEOUT_MS","MAX_BODY","parseBody","sendJson","sendHtml","import_node_http","import_node_fs","MAX_BODY","parseBody","sendJson","sendHtml","collectPassphrase","import_node_path","waitForApproval","existsSync","requestBrowserApproval"]}
1
+ {"version":3,"sources":["../../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_tsx@4.21.0_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","../src/errors.ts","../src/utils/paths.ts","../src/auth/keypair.ts","../src/auth/mandate.ts","../src/transactions/poller.ts","../src/server/approval-html.ts","../src/utils/open-browser.ts","../src/server/approval-server.ts","../src/tunnel/tunnel.ts","../src/notify/notify.ts","../src/server/mobile-approval-server.ts","../src/server/passphrase-html.ts","../src/server/passphrase-server.ts","../src/index.ts","../src/utils/ids.ts","../src/utils/display.ts","../src/vault/vault.ts","../src/budget/budget.ts","../src/config/config.ts","../src/config/types.ts","../src/transactions/manager.ts","../src/audit/logger.ts","../src/executor/executor.ts","../src/executor/placeholder.ts","../src/executor/providers/local-provider.ts","../src/server/setup-server.ts","../src/server/setup-html.ts","../src/server/index.ts","../src/server/html.ts","../src/server/routes.ts","../src/utils/prompt.ts","../src/agentpay.ts"],"sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","export class NotSetupError extends Error {\n readonly code = 'NOT_SETUP';\n constructor(message = 'AgentPay has not been set up yet. Run `agentpay setup` first.') {\n super(message);\n this.name = 'NotSetupError';\n }\n}\n\nexport class DecryptError extends Error {\n readonly code = 'DECRYPT_FAILED';\n constructor(message = 'Failed to decrypt credentials. Wrong passphrase or corrupted file.') {\n super(message);\n this.name = 'DecryptError';\n }\n}\n\nexport class InsufficientBalanceError extends Error {\n readonly code = 'INSUFFICIENT_BALANCE';\n constructor(amount?: number, balance?: number) {\n const msg = amount !== undefined && balance !== undefined\n ? `Insufficient balance: requested $${amount.toFixed(2)} but only $${balance.toFixed(2)} available.`\n : 'Insufficient balance for this transaction.';\n super(msg);\n this.name = 'InsufficientBalanceError';\n }\n}\n\nexport class ExceedsTxLimitError extends Error {\n readonly code = 'EXCEEDS_TX_LIMIT';\n constructor(amount?: number, limit?: number) {\n const msg = amount !== undefined && limit !== undefined\n ? `Amount $${amount.toFixed(2)} exceeds per-transaction limit of $${limit.toFixed(2)}.`\n : 'Amount exceeds per-transaction limit.';\n super(msg);\n this.name = 'ExceedsTxLimitError';\n }\n}\n\nexport class NotApprovedError extends Error {\n readonly code = 'NOT_APPROVED';\n constructor(txId?: string) {\n super(txId ? `Transaction ${txId} has not been approved.` : 'Transaction has not been approved.');\n this.name = 'NotApprovedError';\n }\n}\n\nexport class InvalidMandateError extends Error {\n readonly code = 'INVALID_MANDATE';\n constructor(message = 'Purchase mandate signature verification failed.') {\n super(message);\n this.name = 'InvalidMandateError';\n }\n}\n\nexport class AlreadyExecutedError extends Error {\n readonly code = 'ALREADY_EXECUTED';\n constructor(txId?: string) {\n super(txId ? `Transaction ${txId} has already been executed.` : 'Transaction has already been executed.');\n this.name = 'AlreadyExecutedError';\n }\n}\n\nexport class CheckoutFailedError extends Error {\n readonly code = 'CHECKOUT_FAILED';\n constructor(message = 'Failed to complete checkout.') {\n super(message);\n this.name = 'CheckoutFailedError';\n }\n}\n\nexport class TimeoutError extends Error {\n readonly code = 'TIMEOUT';\n constructor(message = 'Operation timed out.') {\n super(message);\n this.name = 'TimeoutError';\n }\n}\n","import { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { existsSync } from 'node:fs';\n\nexport function getHomePath(): string {\n if (process.env.AGENTPAY_HOME) return process.env.AGENTPAY_HOME;\n const local = join(process.cwd(), 'agentpay');\n if (existsSync(local)) return local;\n return join(homedir(), '.agentpay');\n}\n\nexport function getCredentialsPath(): string {\n return join(getHomePath(), 'credentials.enc');\n}\n\nexport function getKeysPath(): string {\n return join(getHomePath(), 'keys');\n}\n\nexport function getPublicKeyPath(): string {\n return join(getKeysPath(), 'public.pem');\n}\n\nexport function getPrivateKeyPath(): string {\n return join(getKeysPath(), 'private.pem');\n}\n\nexport function getWalletPath(): string {\n return join(getHomePath(), 'wallet.json');\n}\n\nexport function getTransactionsPath(): string {\n return join(getHomePath(), 'transactions.json');\n}\n\nexport function getAuditPath(): string {\n return join(getHomePath(), 'audit.log');\n}\n","import { generateKeyPairSync, createPublicKey } from 'node:crypto';\nimport { readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type { KeyPair } from './types.js';\nimport { getPublicKeyPath, getPrivateKeyPath } from '../utils/paths.js';\n\nexport function generateKeyPair(passphrase: string): KeyPair {\n const { publicKey, privateKey } = generateKeyPairSync('ed25519', {\n publicKeyEncoding: { type: 'spki', format: 'pem' },\n privateKeyEncoding: {\n type: 'pkcs8',\n format: 'pem',\n cipher: 'aes-256-cbc',\n passphrase,\n },\n });\n\n return { publicKey, privateKey };\n}\n\nexport function saveKeyPair(keys: KeyPair, publicPath?: string, privatePath?: string): void {\n const pubPath = publicPath ?? getPublicKeyPath();\n const privPath = privatePath ?? getPrivateKeyPath();\n\n mkdirSync(dirname(pubPath), { recursive: true });\n writeFileSync(pubPath, keys.publicKey, { mode: 0o644 });\n writeFileSync(privPath, keys.privateKey, { mode: 0o600 });\n}\n\nexport function loadPublicKey(path?: string): string {\n return readFileSync(path ?? getPublicKeyPath(), 'utf8');\n}\n\nexport function loadPrivateKey(path?: string): string {\n return readFileSync(path ?? getPrivateKeyPath(), 'utf8');\n}\n","import { createHash, createPrivateKey, createPublicKey, sign, verify } from 'node:crypto';\nimport type { PurchaseMandate, TransactionDetails } from './types.js';\nimport { InvalidMandateError } from '../errors.js';\n\nfunction hashTransactionDetails(details: TransactionDetails): string {\n const canonical = JSON.stringify({\n txId: details.txId,\n merchant: details.merchant,\n amount: details.amount,\n description: details.description,\n timestamp: details.timestamp,\n });\n return createHash('sha256').update(canonical).digest('hex');\n}\n\nexport function createMandate(\n txDetails: TransactionDetails,\n privateKeyPem: string,\n passphrase: string,\n): PurchaseMandate {\n const txHash = hashTransactionDetails(txDetails);\n const data = Buffer.from(txHash);\n\n const privateKey = createPrivateKey({\n key: privateKeyPem,\n format: 'pem',\n type: 'pkcs8',\n passphrase,\n });\n\n const signature = sign(null, data, privateKey);\n\n const publicKey = createPublicKey(privateKey);\n const publicKeyPem = publicKey.export({ type: 'spki', format: 'pem' }) as string;\n\n return {\n txId: txDetails.txId,\n txHash,\n signature: signature.toString('base64'),\n publicKey: publicKeyPem,\n timestamp: new Date().toISOString(),\n };\n}\n\nexport function verifyMandate(mandate: PurchaseMandate, txDetails: TransactionDetails): boolean {\n try {\n const txHash = hashTransactionDetails(txDetails);\n if (txHash !== mandate.txHash) return false;\n\n const data = Buffer.from(txHash);\n const signature = Buffer.from(mandate.signature, 'base64');\n const publicKey = createPublicKey({\n key: mandate.publicKey,\n format: 'pem',\n type: 'spki',\n });\n\n return verify(null, data, publicKey, signature);\n } catch {\n return false;\n }\n}\n","import type { Transaction } from './types.js';\nimport type { TransactionManager } from './manager.js';\nimport { TimeoutError } from '../errors.js';\n\nexport interface PollOptions {\n pollInterval?: number;\n timeout?: number;\n}\n\nexport async function waitForApproval(\n txId: string,\n manager: TransactionManager,\n options?: PollOptions,\n): Promise<{ status: 'approved' | 'rejected'; reason?: string }> {\n const interval = options?.pollInterval ?? 2000;\n const timeout = options?.timeout ?? 300_000;\n const deadline = Date.now() + timeout;\n\n while (Date.now() < deadline) {\n const tx = manager.get(txId);\n if (!tx) throw new Error(`Transaction ${txId} not found.`);\n\n if (tx.status === 'approved') return { status: 'approved' };\n if (tx.status === 'rejected') return { status: 'rejected', reason: tx.rejectionReason };\n\n await new Promise((resolve) => setTimeout(resolve, interval));\n }\n\n throw new TimeoutError(`Timed out waiting for approval of ${txId}`);\n}\n","import type { Transaction } from '../transactions/types.js';\n\nfunction esc(s: string): string {\n return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n}\n\nfunction formatCurrency(n: number): string {\n return '$' + n.toFixed(2);\n}\n\nexport function getApprovalHtml(token: string, tx: Transaction): string {\n const lines: string[] = [];\n lines.push(`<div class=\"detail\"><span class=\"detail-label\">Merchant</span><span class=\"detail-value\">${esc(tx.merchant)}</span></div>`);\n lines.push(`<div class=\"detail\"><span class=\"detail-label\">Amount</span><span class=\"detail-value\">${formatCurrency(tx.amount)}</span></div>`);\n lines.push(`<div class=\"detail\"><span class=\"detail-label\">Description</span><span class=\"detail-value\">${esc(tx.description)}</span></div>`);\n if (tx.url) {\n lines.push(`<div class=\"detail\"><span class=\"detail-label\">URL</span><span class=\"detail-value\"><a href=\"${esc(tx.url)}\" target=\"_blank\" rel=\"noopener\" style=\"color:#111;\">${esc(tx.url)}</a></span></div>`);\n }\n lines.push(`<div class=\"detail\"><span class=\"detail-label\">Transaction</span><span class=\"detail-value\" style=\"font-family:monospace;font-size:12px;\">${esc(tx.id)}</span></div>`);\n const contextHtml = `<div class=\"card context-card\">${lines.join('')}</div>`;\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>AgentPay — Approve Purchase</title>\n<style>\n *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n background: #f5f5f5;\n color: #111;\n min-height: 100vh;\n display: flex;\n justify-content: center;\n padding: 40px 16px;\n }\n .container { width: 100%; max-width: 420px; }\n h1 { font-size: 24px; font-weight: 700; margin-bottom: 4px; }\n .subtitle { color: #666; font-size: 14px; margin-bottom: 24px; }\n .card {\n background: #fff;\n border-radius: 8px;\n padding: 24px;\n margin-bottom: 16px;\n border: 1px solid #e0e0e0;\n }\n .context-card { padding: 16px 20px; }\n .detail {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 0;\n border-bottom: 1px solid #f0f0f0;\n }\n .detail:last-child { border-bottom: none; }\n .detail-label { font-size: 13px; color: #666; }\n .detail-value { font-size: 14px; font-weight: 600; }\n label { display: block; font-size: 13px; font-weight: 500; color: #333; margin-bottom: 6px; }\n input[type=\"password\"], textarea {\n width: 100%;\n padding: 12px 14px;\n border: 1px solid #d0d0d0;\n border-radius: 8px;\n font-size: 15px;\n font-family: inherit;\n outline: none;\n transition: border-color 0.15s;\n }\n input[type=\"password\"]:focus, textarea:focus { border-color: #111; }\n textarea { resize: vertical; min-height: 60px; margin-top: 8px; }\n .btn-row { display: flex; gap: 12px; margin-top: 16px; }\n .btn-approve, .btn-deny {\n flex: 1;\n padding: 12px;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: opacity 0.15s;\n }\n .btn-approve { background: #111; color: #fff; }\n .btn-approve:hover { opacity: 0.85; }\n .btn-approve:disabled { opacity: 0.5; cursor: not-allowed; }\n .btn-deny { background: #fff; color: #c62828; border: 2px solid #c62828; }\n .btn-deny:hover { opacity: 0.85; }\n .btn-deny:disabled { opacity: 0.5; cursor: not-allowed; }\n .error { color: #c62828; font-size: 13px; margin-top: 10px; }\n .success-screen {\n text-align: center;\n padding: 40px 0;\n }\n .checkmark { font-size: 48px; margin-bottom: 16px; }\n .success-msg { font-size: 16px; font-weight: 600; margin-bottom: 8px; }\n .success-hint { font-size: 13px; color: #666; }\n .hidden { display: none; }\n .reason-section { margin-top: 12px; }\n</style>\n</head>\n<body>\n<div class=\"container\">\n <div id=\"form-view\">\n <h1>AgentPay</h1>\n <p class=\"subtitle\">Approve Purchase</p>\n ${contextHtml}\n <div class=\"card\">\n <label for=\"passphrase\">Passphrase</label>\n <input type=\"password\" id=\"passphrase\" placeholder=\"Enter your passphrase\" autofocus>\n <div id=\"reason-section\" class=\"reason-section hidden\">\n <label for=\"reason\">Reason (optional)</label>\n <textarea id=\"reason\" placeholder=\"Why are you denying this purchase?\"></textarea>\n </div>\n <div id=\"error\" class=\"error hidden\"></div>\n <div class=\"btn-row\">\n <button class=\"btn-approve\" id=\"btn-approve\">Approve</button>\n <button class=\"btn-deny\" id=\"btn-deny\">Deny</button>\n </div>\n </div>\n </div>\n <div id=\"success-view\" class=\"hidden\">\n <h1>AgentPay</h1>\n <p class=\"subtitle\" id=\"success-subtitle\"></p>\n <div class=\"card\">\n <div class=\"success-screen\">\n <div class=\"checkmark\" id=\"success-icon\"></div>\n <div class=\"success-msg\" id=\"success-msg\"></div>\n <div class=\"success-hint\">This tab will close automatically.</div>\n </div>\n </div>\n </div>\n</div>\n<script>\n(function() {\n var token = ${JSON.stringify(token)};\n var form = document.getElementById('form-view');\n var successView = document.getElementById('success-view');\n var input = document.getElementById('passphrase');\n var btnApprove = document.getElementById('btn-approve');\n var btnDeny = document.getElementById('btn-deny');\n var errDiv = document.getElementById('error');\n var reasonSection = document.getElementById('reason-section');\n var reasonInput = document.getElementById('reason');\n var successSubtitle = document.getElementById('success-subtitle');\n var successIcon = document.getElementById('success-icon');\n var successMsg = document.getElementById('success-msg');\n var denyMode = false;\n\n function showError(msg) {\n errDiv.textContent = msg;\n errDiv.classList.remove('hidden');\n }\n\n function clearError() {\n errDiv.classList.add('hidden');\n }\n\n function disableButtons() {\n btnApprove.disabled = true;\n btnDeny.disabled = true;\n }\n\n function enableButtons() {\n btnApprove.disabled = false;\n btnDeny.disabled = false;\n }\n\n function showSuccess(approved) {\n form.classList.add('hidden');\n successView.classList.remove('hidden');\n if (approved) {\n successSubtitle.textContent = 'Purchase Approved';\n successIcon.innerHTML = '&#10003;';\n successIcon.style.color = '#2e7d32';\n successMsg.textContent = 'Transaction approved and signed.';\n } else {\n successSubtitle.textContent = 'Purchase Denied';\n successIcon.innerHTML = '&#10007;';\n successIcon.style.color = '#c62828';\n successMsg.textContent = 'Transaction has been denied.';\n }\n setTimeout(function() { window.close(); }, 3000);\n }\n\n function doApprove() {\n var passphrase = input.value;\n if (!passphrase) {\n showError('Passphrase is required to approve.');\n return;\n }\n clearError();\n disableButtons();\n btnApprove.textContent = 'Approving...';\n\n fetch('/api/approve', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token: token, passphrase: passphrase })\n })\n .then(function(res) { return res.json(); })\n .then(function(data) {\n if (data.error) {\n showError(data.error);\n enableButtons();\n btnApprove.textContent = 'Approve';\n } else {\n showSuccess(true);\n }\n })\n .catch(function() {\n showError('Failed to submit. Is the CLI still running?');\n enableButtons();\n btnApprove.textContent = 'Approve';\n });\n }\n\n function doReject() {\n if (!denyMode) {\n denyMode = true;\n reasonSection.classList.remove('hidden');\n btnDeny.textContent = 'Confirm Deny';\n reasonInput.focus();\n return;\n }\n clearError();\n disableButtons();\n btnDeny.textContent = 'Denying...';\n\n fetch('/api/reject', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token: token, reason: reasonInput.value || undefined })\n })\n .then(function(res) { return res.json(); })\n .then(function(data) {\n if (data.error) {\n showError(data.error);\n enableButtons();\n btnDeny.textContent = 'Confirm Deny';\n } else {\n showSuccess(false);\n }\n })\n .catch(function() {\n showError('Failed to submit. Is the CLI still running?');\n enableButtons();\n btnDeny.textContent = 'Confirm Deny';\n });\n }\n\n btnApprove.addEventListener('click', doApprove);\n btnDeny.addEventListener('click', doReject);\n input.addEventListener('keydown', function(e) {\n if (e.key === 'Enter') doApprove();\n });\n})();\n</script>\n</body>\n</html>`;\n}\n","import { exec } from 'node:child_process';\nimport { platform } from 'node:os';\n\nexport function openBrowser(url: string): void {\n const plat = platform();\n let cmd: string;\n if (plat === 'darwin') cmd = `open \"${url}\"`;\n else if (plat === 'win32') cmd = `start \"\" \"${url}\"`;\n else cmd = `xdg-open \"${url}\"`;\n\n exec(cmd, (err) => {\n if (err) {\n console.log(`Open ${url} in your browser.`);\n }\n });\n}\n","import { createServer, type IncomingMessage, type ServerResponse, type Server } from 'node:http';\nimport { randomBytes } from 'node:crypto';\nimport { join } from 'node:path';\nimport { getApprovalHtml } from './approval-html.js';\nimport { openBrowser } from '../utils/open-browser.js';\nimport { loadPrivateKey } from '../auth/keypair.js';\nimport { createMandate } from '../auth/mandate.js';\nimport { TimeoutError } from '../errors.js';\nimport type { Transaction } from '../transactions/types.js';\nimport type { TransactionDetails } from '../auth/types.js';\nimport type { TransactionManager } from '../transactions/manager.js';\nimport type { AuditLogger } from '../audit/logger.js';\n\nconst TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes\nconst MAX_BODY = 4096;\n\nexport interface ApprovalResult {\n action: 'approved' | 'rejected';\n passphrase?: string; // only present on approve, for vault decryption\n reason?: string; // only present on reject\n}\n\nfunction parseBody(req: IncomingMessage): Promise<Record<string, unknown>> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n req.on('data', (chunk: Buffer) => {\n size += chunk.length;\n if (size > MAX_BODY) {\n req.destroy();\n reject(new Error('Request body too large'));\n return;\n }\n chunks.push(chunk);\n });\n req.on('end', () => {\n try {\n const text = Buffer.concat(chunks).toString('utf8');\n resolve(text ? JSON.parse(text) : {});\n } catch {\n reject(new Error('Invalid JSON'));\n }\n });\n req.on('error', reject);\n });\n}\n\nfunction sendJson(res: ServerResponse, status: number, body: Record<string, unknown>): void {\n const json = JSON.stringify(body);\n res.writeHead(status, {\n 'Content-Type': 'application/json',\n 'Content-Length': Buffer.byteLength(json),\n });\n res.end(json);\n}\n\nfunction sendHtml(res: ServerResponse, html: string): void {\n res.writeHead(200, {\n 'Content-Type': 'text/html; charset=utf-8',\n 'Content-Length': Buffer.byteLength(html),\n });\n res.end(html);\n}\n\nexport interface ApprovalServerHandle {\n server: Server;\n token: string;\n port: number;\n promise: Promise<ApprovalResult>;\n}\n\n/**\n * Create the ephemeral approval server without opening a browser.\n * Useful for testing — call `requestBrowserApproval` for the full flow.\n */\nexport function createApprovalServer(\n tx: Transaction,\n tm: TransactionManager,\n audit: AuditLogger,\n options?: { openBrowser?: boolean; home?: string },\n): ApprovalServerHandle {\n const nonce = randomBytes(32).toString('hex');\n let settled = false;\n let tokenUsed = false;\n let resolvePromise: (result: ApprovalResult) => void;\n let rejectPromise: (err: Error) => void;\n let timer: ReturnType<typeof setTimeout>;\n let serverInstance: Server;\n\n const promise = new Promise<ApprovalResult>((resolve, reject) => {\n resolvePromise = resolve;\n rejectPromise = reject;\n });\n\n function cleanup(): void {\n clearTimeout(timer);\n serverInstance.close();\n }\n\n serverInstance = createServer(async (req, res) => {\n const url = new URL(req.url ?? '/', `http://${req.headers.host}`);\n const method = req.method ?? 'GET';\n\n try {\n // GET /approve/:txId?token=X — serve approval page\n if (method === 'GET' && url.pathname === `/approve/${tx.id}`) {\n const token = url.searchParams.get('token');\n if (token !== nonce || tokenUsed) {\n sendHtml(res, '<h1>Invalid or expired link.</h1>');\n return;\n }\n sendHtml(res, getApprovalHtml(nonce, tx));\n return;\n }\n\n // POST /api/approve — approve with passphrase (server-side signing)\n if (method === 'POST' && url.pathname === '/api/approve') {\n const body = await parseBody(req);\n if (body.token !== nonce || tokenUsed) {\n sendJson(res, 403, { error: 'Invalid or expired token.' });\n return;\n }\n\n const passphrase = body.passphrase;\n if (typeof passphrase !== 'string' || !passphrase) {\n sendJson(res, 400, { error: 'Passphrase is required.' });\n return;\n }\n\n // Verify the tx is still pending\n const currentTx = tm.get(tx.id);\n if (!currentTx || currentTx.status !== 'pending') {\n sendJson(res, 400, { error: 'Transaction is no longer pending.' });\n return;\n }\n\n // Server-side signing: load private key and create mandate\n try {\n const keyPath = options?.home ? join(options.home, 'keys', 'private.pem') : undefined;\n const privateKeyPem = loadPrivateKey(keyPath);\n const txDetails: TransactionDetails = {\n txId: tx.id,\n merchant: tx.merchant,\n amount: tx.amount,\n description: tx.description,\n timestamp: tx.createdAt,\n };\n const mandate = createMandate(txDetails, privateKeyPem, passphrase);\n tm.approve(tx.id, mandate);\n audit.log('APPROVE', { txId: tx.id, source: 'browser-approval', mandateSigned: true });\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Signing failed';\n sendJson(res, 400, { error: msg });\n return;\n }\n\n tokenUsed = true;\n sendJson(res, 200, { ok: true });\n\n if (!settled) {\n settled = true;\n cleanup();\n resolvePromise({ action: 'approved', passphrase: passphrase as string });\n }\n return;\n }\n\n // POST /api/reject — reject the transaction\n if (method === 'POST' && url.pathname === '/api/reject') {\n const body = await parseBody(req);\n if (body.token !== nonce || tokenUsed) {\n sendJson(res, 403, { error: 'Invalid or expired token.' });\n return;\n }\n\n // Verify the tx is still pending\n const currentTx = tm.get(tx.id);\n if (!currentTx || currentTx.status !== 'pending') {\n sendJson(res, 400, { error: 'Transaction is no longer pending.' });\n return;\n }\n\n const reason = typeof body.reason === 'string' ? body.reason : undefined;\n tm.reject(tx.id, reason);\n audit.log('REJECT', { txId: tx.id, source: 'browser-approval', reason });\n\n tokenUsed = true;\n sendJson(res, 200, { ok: true });\n\n if (!settled) {\n settled = true;\n cleanup();\n resolvePromise({ action: 'rejected', reason });\n }\n return;\n }\n\n sendJson(res, 404, { error: 'Not found' });\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Internal error';\n sendJson(res, 500, { error: message });\n }\n });\n\n timer = setTimeout(() => {\n if (!settled) {\n settled = true;\n cleanup();\n rejectPromise(new TimeoutError('Approval timed out after 5 minutes.'));\n }\n }, TIMEOUT_MS);\n\n serverInstance.on('error', (err) => {\n if (!settled) {\n settled = true;\n cleanup();\n rejectPromise(err);\n }\n });\n\n // We need to wait for listen to get the port, but return synchronously.\n // The promise will resolve/reject based on server events.\n let portValue = 0;\n const handle: ApprovalServerHandle = {\n server: serverInstance,\n token: nonce,\n get port() { return portValue; },\n promise,\n };\n\n serverInstance.listen(0, '127.0.0.1', () => {\n const addr = serverInstance.address();\n if (!addr || typeof addr === 'string') {\n if (!settled) {\n settled = true;\n cleanup();\n rejectPromise(new Error('Failed to bind server'));\n }\n return;\n }\n portValue = addr.port;\n const pageUrl = `http://127.0.0.1:${addr.port}/approve/${tx.id}?token=${nonce}`;\n\n if (options?.openBrowser !== false) {\n console.log('Opening approval page in browser...');\n openBrowser(pageUrl);\n }\n });\n\n return handle;\n}\n\n/**\n * Launch an ephemeral HTTP server on localhost, open a browser page\n * where the human can approve or deny the transaction.\n * On approve: server-side signing is performed, passphrase returned in result.\n * On deny: transaction is rejected.\n */\nexport function requestBrowserApproval(\n tx: Transaction,\n tm: TransactionManager,\n audit: AuditLogger,\n home?: string,\n): Promise<ApprovalResult> {\n const handle = createApprovalServer(tx, tm, audit, { openBrowser: true, home });\n return handle.promise;\n}\n","import { spawn, type ChildProcess } from 'node:child_process';\n\nexport interface TunnelHandle {\n url: string;\n close: () => void;\n}\n\n/**\n * Expose a local port via a public HTTPS tunnel using Cloudflare Quick Tunnels.\n *\n * Requires `cloudflared` to be installed on the system. No Cloudflare account\n * needed — quick tunnels generate a random `*.trycloudflare.com` URL.\n *\n * The tunnel process is spawned as a child process and killed when `close()` is called.\n */\nexport async function openTunnel(port: number): Promise<TunnelHandle> {\n return new Promise<TunnelHandle>((resolve, reject) => {\n let child: ChildProcess;\n try {\n child = spawn('cloudflared', ['tunnel', '--url', `http://127.0.0.1:${port}`], {\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n } catch {\n reject(new Error(\n 'cloudflared is required for mobile approval. Install it: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/',\n ));\n return;\n }\n\n let resolved = false;\n const timeout = setTimeout(() => {\n if (!resolved) {\n resolved = true;\n child.kill();\n reject(new Error('cloudflared tunnel timed out waiting for URL (15s). Is cloudflared installed?'));\n }\n }, 15_000);\n\n const close = () => {\n child.kill();\n };\n\n // cloudflared prints the tunnel URL to stderr\n const chunks: string[] = [];\n child.stderr?.on('data', (data: Buffer) => {\n const text = data.toString();\n chunks.push(text);\n\n // Look for the trycloudflare.com URL in output\n const match = text.match(/https:\\/\\/[a-z0-9-]+\\.trycloudflare\\.com/);\n if (match && !resolved) {\n resolved = true;\n clearTimeout(timeout);\n resolve({ url: match[0], close });\n }\n });\n\n child.on('error', (err) => {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n reject(new Error(\n `cloudflared failed to start: ${err.message}. Install it: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/`,\n ));\n }\n });\n\n child.on('exit', (code) => {\n if (!resolved) {\n resolved = true;\n clearTimeout(timeout);\n const output = chunks.join('');\n reject(new Error(\n `cloudflared exited with code ${code}. Output: ${output.slice(0, 500)}`,\n ));\n }\n });\n });\n}\n","import { execFile } from 'node:child_process';\n\nexport interface NotifyOptions {\n /** Shell command to run. `{{url}}` is replaced with the approval URL. */\n command?: string;\n /** Webhook URL to POST `{ url, txId, merchant, amount }` to. */\n webhookUrl?: string;\n}\n\nexport interface NotifyPayload {\n url: string;\n txId: string;\n merchant: string;\n amount: number;\n}\n\n/**\n * Send a notification about a pending mobile approval.\n *\n * Supports two delivery methods (both can be used simultaneously):\n * - `command`: Shell command with `{{url}}` placeholder (e.g. send via iMessage, Telegram, etc.)\n * - `webhookUrl`: HTTP POST endpoint that receives JSON payload\n *\n * Returns an array of results (one per delivery method attempted).\n */\nexport async function sendNotification(\n payload: NotifyPayload,\n options: NotifyOptions,\n): Promise<{ method: string; success: boolean; error?: string }[]> {\n const results: { method: string; success: boolean; error?: string }[] = [];\n\n if (options.command) {\n const cmd = options.command.replace(/\\{\\{url\\}\\}/g, payload.url);\n try {\n await runCommand(cmd);\n results.push({ method: 'command', success: true });\n } catch (err) {\n results.push({\n method: 'command',\n success: false,\n error: err instanceof Error ? err.message : 'Command failed',\n });\n }\n }\n\n if (options.webhookUrl) {\n try {\n const res = await fetch(options.webhookUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n });\n if (!res.ok) {\n results.push({\n method: 'webhook',\n success: false,\n error: `Webhook returned ${res.status}`,\n });\n } else {\n results.push({ method: 'webhook', success: true });\n }\n } catch (err) {\n results.push({\n method: 'webhook',\n success: false,\n error: err instanceof Error ? err.message : 'Webhook failed',\n });\n }\n }\n\n if (results.length === 0) {\n results.push({\n method: 'none',\n success: false,\n error: 'No notification method configured. Set AGENTPAY_NOTIFY_COMMAND or AGENTPAY_NOTIFY_WEBHOOK.',\n });\n }\n\n return results;\n}\n\nfunction runCommand(cmd: string): Promise<void> {\n return new Promise((resolve, reject) => {\n execFile('sh', ['-c', cmd], { timeout: 10_000 }, (err) => {\n if (err) reject(err);\n else resolve();\n });\n });\n}\n","import { createApprovalServer, type ApprovalResult, type ApprovalServerHandle } from './approval-server.js';\nimport { openTunnel, type TunnelHandle } from '../tunnel/tunnel.js';\nimport { sendNotification, type NotifyOptions, type NotifyPayload } from '../notify/notify.js';\nimport type { Transaction } from '../transactions/types.js';\nimport type { TransactionManager } from '../transactions/manager.js';\nimport type { AuditLogger } from '../audit/logger.js';\n\nexport interface MobileApprovalOptions {\n /** Notification delivery options */\n notify: NotifyOptions;\n /** AgentPay home directory */\n home?: string;\n}\n\nexport interface MobileApprovalResult extends ApprovalResult {\n /** Public URL that was sent to the user */\n approvalUrl: string;\n /** Notification delivery results */\n notifyResults: { method: string; success: boolean; error?: string }[];\n}\n\n/**\n * Request approval via a publicly accessible URL.\n *\n * Flow:\n * 1. Start the local approval server (no browser opened)\n * 2. Open a tunnel to expose it publicly\n * 3. Send the tunnel URL to the user via configured notification method\n * 4. Wait for the user to approve/reject (same as browser flow)\n * 5. Clean up tunnel when done\n */\nexport async function requestMobileApproval(\n tx: Transaction,\n tm: TransactionManager,\n audit: AuditLogger,\n options: MobileApprovalOptions,\n): Promise<MobileApprovalResult> {\n // 1. Start local approval server WITHOUT opening browser\n const handle: ApprovalServerHandle = createApprovalServer(tx, tm, audit, {\n openBrowser: false,\n home: options.home,\n });\n\n // Wait for server to be listening (port assigned)\n await waitForPort(handle);\n\n let tunnel: TunnelHandle | undefined;\n\n try {\n // 2. Open tunnel to expose local server publicly\n tunnel = await openTunnel(handle.port);\n\n // 3. Build the public approval URL\n const approvalUrl = `${tunnel.url}/approve/${tx.id}?token=${handle.token}`;\n\n // 4. Send notification to user\n const payload: NotifyPayload = {\n url: approvalUrl,\n txId: tx.id,\n merchant: tx.merchant,\n amount: tx.amount,\n };\n const notifyResults = await sendNotification(payload, options.notify);\n\n audit.log('MOBILE_APPROVAL_REQUESTED', {\n txId: tx.id,\n tunnelUrl: tunnel.url,\n notifyResults,\n });\n\n // 5. Wait for user to approve/reject (or timeout)\n const result = await handle.promise;\n\n return {\n ...result,\n approvalUrl,\n notifyResults,\n };\n } finally {\n // Always clean up tunnel\n tunnel?.close();\n }\n}\n\n/**\n * Wait for the approval server to bind to a port.\n * The server uses port 0 (OS-assigned), so we need to poll until it's ready.\n */\nfunction waitForPort(handle: ApprovalServerHandle, timeoutMs = 5000): Promise<void> {\n return new Promise((resolve, reject) => {\n const start = Date.now();\n const check = () => {\n if (handle.port > 0) {\n resolve();\n return;\n }\n if (Date.now() - start > timeoutMs) {\n reject(new Error('Approval server failed to bind to a port'));\n return;\n }\n setTimeout(check, 50);\n };\n check();\n });\n}\n","export interface PassphraseContext {\n action: 'buy' | 'approve';\n merchant?: string;\n amount?: number;\n description?: string;\n txId?: string;\n}\n\nfunction esc(s: string): string {\n return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n}\n\nfunction formatCurrency(n: number): string {\n return '$' + n.toFixed(2);\n}\n\nexport function getPassphraseHtml(token: string, context?: PassphraseContext): string {\n const actionLabel = context?.action === 'approve' ? 'Approve Transaction' : 'Approve Purchase';\n const buttonLabel = context?.action === 'approve' ? 'Unlock &amp; Approve' : 'Unlock &amp; Approve';\n\n let contextHtml = '';\n if (context) {\n const lines: string[] = [];\n if (context.merchant) lines.push(`<div class=\"detail\"><span class=\"detail-label\">Merchant</span><span class=\"detail-value\">${esc(context.merchant)}</span></div>`);\n if (context.amount !== undefined) lines.push(`<div class=\"detail\"><span class=\"detail-label\">Amount</span><span class=\"detail-value\">${formatCurrency(context.amount)}</span></div>`);\n if (context.description) lines.push(`<div class=\"detail\"><span class=\"detail-label\">Description</span><span class=\"detail-value\">${esc(context.description)}</span></div>`);\n if (context.txId) lines.push(`<div class=\"detail\"><span class=\"detail-label\">Transaction</span><span class=\"detail-value\" style=\"font-family:monospace;font-size:12px;\">${esc(context.txId)}</span></div>`);\n if (lines.length > 0) {\n contextHtml = `<div class=\"card context-card\">${lines.join('')}</div>`;\n }\n }\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>AgentPay — Passphrase Required</title>\n<style>\n *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n background: #f5f5f5;\n color: #111;\n min-height: 100vh;\n display: flex;\n justify-content: center;\n padding: 40px 16px;\n }\n .container { width: 100%; max-width: 420px; }\n h1 { font-size: 24px; font-weight: 700; margin-bottom: 4px; }\n .subtitle { color: #666; font-size: 14px; margin-bottom: 24px; }\n .card {\n background: #fff;\n border-radius: 8px;\n padding: 24px;\n margin-bottom: 16px;\n border: 1px solid #e0e0e0;\n }\n .context-card { padding: 16px 20px; }\n .detail {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 0;\n border-bottom: 1px solid #f0f0f0;\n }\n .detail:last-child { border-bottom: none; }\n .detail-label { font-size: 13px; color: #666; }\n .detail-value { font-size: 14px; font-weight: 600; }\n label { display: block; font-size: 13px; font-weight: 500; color: #333; margin-bottom: 6px; }\n input[type=\"password\"] {\n width: 100%;\n padding: 12px 14px;\n border: 1px solid #d0d0d0;\n border-radius: 8px;\n font-size: 15px;\n outline: none;\n transition: border-color 0.15s;\n }\n input[type=\"password\"]:focus { border-color: #111; }\n button {\n width: 100%;\n padding: 12px;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: opacity 0.15s;\n margin-top: 16px;\n background: #111;\n color: #fff;\n }\n button:hover { opacity: 0.85; }\n button:disabled { opacity: 0.5; cursor: not-allowed; }\n .error { color: #c62828; font-size: 13px; margin-top: 10px; }\n .success-screen {\n text-align: center;\n padding: 40px 0;\n }\n .checkmark {\n font-size: 48px;\n margin-bottom: 16px;\n }\n .success-msg {\n font-size: 16px;\n font-weight: 600;\n margin-bottom: 8px;\n }\n .success-hint {\n font-size: 13px;\n color: #666;\n }\n .hidden { display: none; }\n</style>\n</head>\n<body>\n<div class=\"container\">\n <div id=\"form-view\">\n <h1>AgentPay</h1>\n <p class=\"subtitle\">${esc(actionLabel)}</p>\n ${contextHtml}\n <div class=\"card\">\n <label for=\"passphrase\">Passphrase</label>\n <input type=\"password\" id=\"passphrase\" placeholder=\"Enter your passphrase\" autofocus>\n <div id=\"error\" class=\"error hidden\"></div>\n <button id=\"submit\">${buttonLabel}</button>\n </div>\n </div>\n <div id=\"success-view\" class=\"hidden\">\n <h1>AgentPay</h1>\n <p class=\"subtitle\">${esc(actionLabel)}</p>\n <div class=\"card\">\n <div class=\"success-screen\">\n <div class=\"checkmark\">&#10003;</div>\n <div class=\"success-msg\">Passphrase received</div>\n <div class=\"success-hint\">You can close this tab.</div>\n </div>\n </div>\n </div>\n</div>\n<script>\n(function() {\n var token = ${JSON.stringify(token)};\n var form = document.getElementById('form-view');\n var success = document.getElementById('success-view');\n var input = document.getElementById('passphrase');\n var btn = document.getElementById('submit');\n var errDiv = document.getElementById('error');\n\n function submit() {\n var passphrase = input.value;\n if (!passphrase) {\n errDiv.textContent = 'Passphrase is required.';\n errDiv.classList.remove('hidden');\n return;\n }\n btn.disabled = true;\n btn.textContent = 'Submitting...';\n errDiv.classList.add('hidden');\n\n fetch('/passphrase', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token: token, passphrase: passphrase })\n })\n .then(function(res) { return res.json(); })\n .then(function(data) {\n if (data.error) {\n errDiv.textContent = data.error;\n errDiv.classList.remove('hidden');\n btn.disabled = false;\n btn.textContent = '${buttonLabel}';\n } else {\n form.classList.add('hidden');\n success.classList.remove('hidden');\n }\n })\n .catch(function() {\n errDiv.textContent = 'Failed to submit. Is the CLI still running?';\n errDiv.classList.remove('hidden');\n btn.disabled = false;\n btn.textContent = '${buttonLabel}';\n });\n }\n\n btn.addEventListener('click', submit);\n input.addEventListener('keydown', function(e) {\n if (e.key === 'Enter') submit();\n });\n})();\n</script>\n</body>\n</html>`;\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from 'node:http';\nimport { randomBytes } from 'node:crypto';\nimport { getPassphraseHtml, type PassphraseContext } from './passphrase-html.js';\nimport { openBrowser } from '../utils/open-browser.js';\nimport { TimeoutError } from '../errors.js';\n\nconst TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes\nconst MAX_BODY = 4096;\n\nfunction parseBody(req: IncomingMessage): Promise<Record<string, unknown>> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n req.on('data', (chunk: Buffer) => {\n size += chunk.length;\n if (size > MAX_BODY) {\n req.destroy();\n reject(new Error('Request body too large'));\n return;\n }\n chunks.push(chunk);\n });\n req.on('end', () => {\n try {\n const text = Buffer.concat(chunks).toString('utf8');\n resolve(text ? JSON.parse(text) : {});\n } catch {\n reject(new Error('Invalid JSON'));\n }\n });\n req.on('error', reject);\n });\n}\n\nfunction sendJson(res: ServerResponse, status: number, body: Record<string, unknown>): void {\n const json = JSON.stringify(body);\n res.writeHead(status, {\n 'Content-Type': 'application/json',\n 'Content-Length': Buffer.byteLength(json),\n });\n res.end(json);\n}\n\nfunction sendHtml(res: ServerResponse, html: string): void {\n res.writeHead(200, {\n 'Content-Type': 'text/html; charset=utf-8',\n 'Content-Length': Buffer.byteLength(html),\n });\n res.end(html);\n}\n\nexport type { PassphraseContext } from './passphrase-html.js';\n\n/**\n * Launch an ephemeral HTTP server on localhost, open a browser page\n * where the human enters their passphrase, and return it.\n * The passphrase never appears in stdout/stderr.\n */\nexport function collectPassphrase(context?: PassphraseContext): Promise<string> {\n return new Promise((resolve, reject) => {\n const nonce = randomBytes(32).toString('hex');\n let settled = false;\n\n const server = createServer(async (req, res) => {\n const url = new URL(req.url ?? '/', `http://${req.headers.host}`);\n const method = req.method ?? 'GET';\n\n try {\n if (method === 'GET' && url.pathname === '/passphrase') {\n const token = url.searchParams.get('token');\n if (token !== nonce) {\n sendHtml(res, '<h1>Invalid or expired link.</h1>');\n return;\n }\n sendHtml(res, getPassphraseHtml(nonce, context));\n } else if (method === 'POST' && url.pathname === '/passphrase') {\n const body = await parseBody(req);\n if (body.token !== nonce) {\n sendJson(res, 403, { error: 'Invalid token.' });\n return;\n }\n const passphrase = body.passphrase;\n if (typeof passphrase !== 'string' || !passphrase) {\n sendJson(res, 400, { error: 'Passphrase is required.' });\n return;\n }\n sendJson(res, 200, { ok: true });\n\n if (!settled) {\n settled = true;\n cleanup();\n resolve(passphrase);\n }\n } else {\n sendJson(res, 404, { error: 'Not found' });\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Internal error';\n sendJson(res, 500, { error: message });\n }\n });\n\n const timer = setTimeout(() => {\n if (!settled) {\n settled = true;\n cleanup();\n reject(new TimeoutError('Passphrase entry timed out after 5 minutes.'));\n }\n }, TIMEOUT_MS);\n\n function cleanup(): void {\n clearTimeout(timer);\n server.close();\n }\n\n server.on('error', (err) => {\n if (!settled) {\n settled = true;\n cleanup();\n reject(err);\n }\n });\n\n // Bind to localhost on a random available port\n server.listen(0, '127.0.0.1', () => {\n const addr = server.address();\n if (!addr || typeof addr === 'string') {\n if (!settled) {\n settled = true;\n cleanup();\n reject(new Error('Failed to bind server'));\n }\n return;\n }\n const url = `http://127.0.0.1:${addr.port}/passphrase?token=${nonce}`;\n console.log('Waiting for passphrase entry in browser...');\n openBrowser(url);\n });\n });\n}\n","declare const __PKG_VERSION__: string;\nexport const VERSION = typeof __PKG_VERSION__ !== 'undefined' ? __PKG_VERSION__ : '0.0.0';\n\n// Types\nexport type { BillingCredentials, EncryptedVault } from './vault/types.js';\nexport type { KeyPair, PurchaseMandate, TransactionDetails } from './auth/types.js';\nexport type { Wallet } from './budget/types.js';\nexport type { Transaction, TransactionStatus, Receipt, ProposeOptions } from './transactions/types.js';\nexport type { CheckoutResult, ExecutorConfig } from './executor/types.js';\nexport type { BrowserProvider } from './executor/browser-provider.js';\n\n// Errors\nexport {\n NotSetupError,\n DecryptError,\n InsufficientBalanceError,\n ExceedsTxLimitError,\n NotApprovedError,\n InvalidMandateError,\n AlreadyExecutedError,\n CheckoutFailedError,\n TimeoutError,\n} from './errors.js';\n\n// Utilities\nexport { generateTxId } from './utils/ids.js';\nexport { formatCurrency, formatTimestamp, formatTable, formatStatus } from './utils/display.js';\nexport { getHomePath, getCredentialsPath, getKeysPath, getWalletPath, getTransactionsPath, getAuditPath } from './utils/paths.js';\n\n// Vault\nexport { encrypt, decrypt, saveVault, loadVault } from './vault/vault.js';\n\n// Auth\nexport { generateKeyPair, saveKeyPair, loadPublicKey, loadPrivateKey } from './auth/keypair.js';\nexport { createMandate, verifyMandate } from './auth/mandate.js';\n\n// Budget\nexport { BudgetManager } from './budget/budget.js';\n\n// Config\nexport type { AgentPayConfig } from './config/types.js';\nexport { loadConfig, saveConfig, setMobileMode } from './config/config.js';\n\n// Transactions\nexport { TransactionManager } from './transactions/manager.js';\nexport { waitForApproval } from './transactions/poller.js';\n\n// Audit\nexport { AuditLogger } from './audit/logger.js';\n\n// Executor\nexport { PurchaseExecutor } from './executor/executor.js';\nexport { PLACEHOLDER_MAP, getPlaceholderVariables, credentialsToSwapMap } from './executor/placeholder.js';\n\n// Approval Server\nexport type { ApprovalResult } from './server/approval-server.js';\nexport { requestBrowserApproval } from './server/approval-server.js';\n\n// Mobile Approval Server\nexport type { MobileApprovalOptions, MobileApprovalResult } from './server/mobile-approval-server.js';\nexport { requestMobileApproval } from './server/mobile-approval-server.js';\n\n// Tunnel\nexport type { TunnelHandle } from './tunnel/tunnel.js';\nexport { openTunnel } from './tunnel/tunnel.js';\n\n// Notifications\nexport type { NotifyOptions, NotifyPayload } from './notify/notify.js';\nexport { sendNotification } from './notify/notify.js';\n\n// Setup Server\nexport type { SetupResult } from './server/setup-server.js';\nexport { requestBrowserSetup } from './server/setup-server.js';\n\n// Dashboard Server\nexport { startServer as startDashboardServer } from './server/index.js';\n\n// Browser & Prompt Utilities\nexport { openBrowser } from './utils/open-browser.js';\nexport { promptInput, promptPassphrase, promptConfirm, promptPassphraseSafe } from './utils/prompt.js';\n\n// AgentPay\nexport { AgentPay } from './agentpay.js';\nexport type { AgentPayOptions } from './agentpay.js';\n","import { randomBytes } from 'node:crypto';\n\nexport function generateTxId(): string {\n return `tx_${randomBytes(4).toString('hex')}`;\n}\n","import type { Transaction } from '../transactions/types.js';\n\nexport function formatCurrency(amount: number): string {\n return `$${amount.toFixed(2)}`;\n}\n\nexport function formatTimestamp(iso: string): string {\n const d = new Date(iso);\n return d.toLocaleString('en-US', {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\nexport function formatTable(transactions: Transaction[]): string {\n if (transactions.length === 0) return 'No transactions.';\n\n const header = 'TX_ID MERCHANT AMOUNT DESCRIPTION';\n const separator = '─'.repeat(header.length);\n const rows = transactions.map((tx) => {\n const id = tx.id.padEnd(14);\n const merchant = tx.merchant.padEnd(16);\n const amount = formatCurrency(tx.amount).padStart(9);\n return `${id}${merchant}${amount} ${tx.description}`;\n });\n\n return [header, separator, ...rows].join('\\n');\n}\n\nexport function formatStatus(data: {\n balance: number;\n budget: number;\n limitPerTx: number;\n pending: Transaction[];\n recent: Transaction[];\n}): string {\n const lines = [\n 'AgentPay Status',\n '───────────────',\n `Balance: ${formatCurrency(data.balance)} / ${formatCurrency(data.budget)}`,\n `Per-tx limit: ${formatCurrency(data.limitPerTx)}`,\n `Pending purchases: ${data.pending.length}`,\n ];\n\n if (data.recent.length > 0) {\n lines.push('', 'Recent:');\n for (const tx of data.recent) {\n const status = `[${tx.status}]`.padEnd(12);\n lines.push(` ${status} ${tx.id} ${tx.merchant.padEnd(12)} ${formatCurrency(tx.amount).padStart(8)} ${tx.description}`);\n }\n }\n\n return lines.join('\\n');\n}\n","import { pbkdf2Sync, randomBytes, createCipheriv, createDecipheriv } from 'node:crypto';\nimport { readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type { BillingCredentials, EncryptedVault } from './types.js';\nimport { DecryptError, NotSetupError } from '../errors.js';\nimport { getCredentialsPath } from '../utils/paths.js';\n\nconst ALGORITHM = 'aes-256-gcm';\nconst PBKDF2_ITERATIONS = 100_000;\nconst PBKDF2_DIGEST = 'sha512';\nconst KEY_LENGTH = 32;\nconst SALT_LENGTH = 32;\nconst IV_LENGTH = 16;\n\nexport function deriveKey(passphrase: string, salt: Buffer): Buffer {\n return pbkdf2Sync(passphrase, salt, PBKDF2_ITERATIONS, KEY_LENGTH, PBKDF2_DIGEST);\n}\n\nexport function encrypt(credentials: BillingCredentials, passphrase: string): EncryptedVault {\n const salt = randomBytes(SALT_LENGTH);\n const iv = randomBytes(IV_LENGTH);\n const key = deriveKey(passphrase, salt);\n\n const cipher = createCipheriv(ALGORITHM, key, iv);\n const plaintext = JSON.stringify(credentials);\n const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);\n const authTag = cipher.getAuthTag();\n\n return {\n ciphertext: Buffer.concat([encrypted, authTag]).toString('base64'),\n salt: salt.toString('base64'),\n iv: iv.toString('base64'),\n };\n}\n\nexport function decrypt(vault: EncryptedVault, passphrase: string): BillingCredentials {\n try {\n const salt = Buffer.from(vault.salt, 'base64');\n const iv = Buffer.from(vault.iv, 'base64');\n const data = Buffer.from(vault.ciphertext, 'base64');\n const key = deriveKey(passphrase, salt);\n\n const authTag = data.subarray(data.length - 16);\n const ciphertext = data.subarray(0, data.length - 16);\n\n const decipher = createDecipheriv(ALGORITHM, key, iv);\n decipher.setAuthTag(authTag);\n const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);\n\n return JSON.parse(decrypted.toString('utf8')) as BillingCredentials;\n } catch {\n throw new DecryptError();\n }\n}\n\nexport function saveVault(vault: EncryptedVault, path?: string): void {\n const filePath = path ?? getCredentialsPath();\n mkdirSync(dirname(filePath), { recursive: true });\n writeFileSync(filePath, JSON.stringify(vault, null, 2), { mode: 0o600 });\n}\n\nexport function loadVault(path?: string): EncryptedVault {\n const filePath = path ?? getCredentialsPath();\n try {\n const data = readFileSync(filePath, 'utf8');\n return JSON.parse(data) as EncryptedVault;\n } catch {\n throw new NotSetupError();\n }\n}\n","import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type { Wallet } from './types.js';\nimport { NotSetupError, InsufficientBalanceError, ExceedsTxLimitError } from '../errors.js';\nimport { getWalletPath } from '../utils/paths.js';\n\nexport class BudgetManager {\n private walletPath: string;\n\n constructor(walletPath?: string) {\n this.walletPath = walletPath ?? getWalletPath();\n }\n\n getWallet(): Wallet {\n try {\n const data = readFileSync(this.walletPath, 'utf8');\n return JSON.parse(data) as Wallet;\n } catch {\n throw new NotSetupError();\n }\n }\n\n private saveWallet(wallet: Wallet): void {\n mkdirSync(dirname(this.walletPath), { recursive: true });\n writeFileSync(this.walletPath, JSON.stringify(wallet, null, 2), { mode: 0o600 });\n }\n\n setBudget(amount: number): void {\n let wallet: Wallet;\n try {\n wallet = this.getWallet();\n } catch {\n wallet = { budget: 0, balance: 0, limitPerTx: 0, spent: 0 };\n }\n wallet.budget = amount;\n wallet.balance = amount - wallet.spent;\n this.saveWallet(wallet);\n }\n\n setLimitPerTx(limit: number): void {\n const wallet = this.getWallet();\n wallet.limitPerTx = limit;\n this.saveWallet(wallet);\n }\n\n deductBalance(amount: number): void {\n const wallet = this.getWallet();\n if (amount > wallet.balance) {\n throw new InsufficientBalanceError(amount, wallet.balance);\n }\n wallet.balance -= amount;\n wallet.spent += amount;\n this.saveWallet(wallet);\n }\n\n checkProposal(amount: number): void {\n const wallet = this.getWallet();\n if (amount > wallet.balance) {\n throw new InsufficientBalanceError(amount, wallet.balance);\n }\n if (wallet.limitPerTx > 0 && amount > wallet.limitPerTx) {\n throw new ExceedsTxLimitError(amount, wallet.limitPerTx);\n }\n }\n\n addFunds(amount: number): Wallet {\n const wallet = this.getWallet();\n wallet.budget += amount;\n wallet.balance += amount;\n this.saveWallet(wallet);\n return wallet;\n }\n\n getBalance(): { budget: number; balance: number; limitPerTx: number; spent: number } {\n const wallet = this.getWallet();\n return {\n budget: wallet.budget,\n balance: wallet.balance,\n limitPerTx: wallet.limitPerTx,\n spent: wallet.spent,\n };\n }\n\n initWallet(budget: number, limitPerTx: number = 0): void {\n const wallet: Wallet = { budget, balance: budget, limitPerTx, spent: 0 };\n this.saveWallet(wallet);\n }\n}\n","import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { getHomePath } from '../utils/paths.js';\nimport { DEFAULT_CONFIG, type AgentPayConfig } from './types.js';\n\nfunction getConfigPath(home?: string): string {\n return join(home ?? getHomePath(), 'config.json');\n}\n\nexport function loadConfig(home?: string): AgentPayConfig {\n try {\n const data = readFileSync(getConfigPath(home), 'utf8');\n return { ...DEFAULT_CONFIG, ...JSON.parse(data) };\n } catch {\n return { ...DEFAULT_CONFIG };\n }\n}\n\nexport function saveConfig(config: AgentPayConfig, home?: string): void {\n const path = getConfigPath(home);\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, JSON.stringify(config, null, 2), { mode: 0o600 });\n}\n\nexport function setMobileMode(enabled: boolean, home?: string): AgentPayConfig {\n const config = loadConfig(home);\n config.mobileMode = enabled;\n saveConfig(config, home);\n return config;\n}\n","export interface AgentPayConfig {\n /** When true, approval links are tunneled via Cloudflare for mobile access */\n mobileMode: boolean;\n /** Shell command to send notification. {{url}} is replaced with the approval URL. */\n notifyCommand?: string;\n /** Webhook URL to POST approval payload to */\n notifyWebhook?: string;\n}\n\nexport const DEFAULT_CONFIG: AgentPayConfig = {\n mobileMode: false,\n};\n","import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type { Transaction, Receipt, ProposeOptions } from './types.js';\nimport type { PurchaseMandate } from '../auth/types.js';\nimport { generateTxId } from '../utils/ids.js';\nimport { getTransactionsPath } from '../utils/paths.js';\n\nexport class TransactionManager {\n private txPath: string;\n\n constructor(txPath?: string) {\n this.txPath = txPath ?? getTransactionsPath();\n }\n\n private loadAll(): Transaction[] {\n try {\n const data = readFileSync(this.txPath, 'utf8');\n return JSON.parse(data) as Transaction[];\n } catch {\n return [];\n }\n }\n\n private saveAll(transactions: Transaction[]): void {\n mkdirSync(dirname(this.txPath), { recursive: true });\n writeFileSync(this.txPath, JSON.stringify(transactions, null, 2), { mode: 0o600 });\n }\n\n propose(options: ProposeOptions): Transaction {\n const transactions = this.loadAll();\n const tx: Transaction = {\n id: generateTxId(),\n status: 'pending',\n merchant: options.merchant,\n amount: options.amount,\n description: options.description,\n url: options.url,\n createdAt: new Date().toISOString(),\n };\n transactions.push(tx);\n this.saveAll(transactions);\n return tx;\n }\n\n get(txId: string): Transaction | undefined {\n return this.loadAll().find((tx) => tx.id === txId);\n }\n\n approve(txId: string, mandate: PurchaseMandate): void {\n const transactions = this.loadAll();\n const tx = transactions.find((t) => t.id === txId);\n if (!tx) throw new Error(`Transaction ${txId} not found.`);\n if (tx.status !== 'pending') throw new Error(`Cannot approve transaction in '${tx.status}' state.`);\n tx.status = 'approved';\n tx.mandate = mandate;\n this.saveAll(transactions);\n }\n\n reject(txId: string, reason?: string): void {\n const transactions = this.loadAll();\n const tx = transactions.find((t) => t.id === txId);\n if (!tx) throw new Error(`Transaction ${txId} not found.`);\n if (tx.status !== 'pending') throw new Error(`Cannot reject transaction in '${tx.status}' state.`);\n tx.status = 'rejected';\n tx.rejectionReason = reason;\n this.saveAll(transactions);\n }\n\n markExecuting(txId: string): void {\n const transactions = this.loadAll();\n const tx = transactions.find((t) => t.id === txId);\n if (!tx) throw new Error(`Transaction ${txId} not found.`);\n if (tx.status !== 'approved') throw new Error(`Cannot execute transaction in '${tx.status}' state.`);\n tx.status = 'executing';\n this.saveAll(transactions);\n }\n\n markCompleted(txId: string, receipt: Receipt): void {\n const transactions = this.loadAll();\n const tx = transactions.find((t) => t.id === txId);\n if (!tx) throw new Error(`Transaction ${txId} not found.`);\n if (tx.status !== 'executing') throw new Error(`Cannot complete transaction in '${tx.status}' state.`);\n tx.status = 'completed';\n tx.receipt = receipt;\n this.saveAll(transactions);\n }\n\n markFailed(txId: string, error: string): void {\n const transactions = this.loadAll();\n const tx = transactions.find((t) => t.id === txId);\n if (!tx) throw new Error(`Transaction ${txId} not found.`);\n if (tx.status !== 'executing') throw new Error(`Cannot fail transaction in '${tx.status}' state.`);\n tx.status = 'failed';\n tx.error = error;\n this.saveAll(transactions);\n }\n\n list(): Transaction[] {\n return this.loadAll();\n }\n\n getPending(): Transaction[] {\n return this.loadAll().filter((tx) => tx.status === 'pending');\n }\n\n getHistory(): Transaction[] {\n return this.loadAll().filter((tx) => tx.status !== 'pending');\n }\n}\n","import { appendFileSync, readFileSync, mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { getAuditPath } from '../utils/paths.js';\n\nexport class AuditLogger {\n private logPath: string;\n\n constructor(logPath?: string) {\n this.logPath = logPath ?? getAuditPath();\n }\n\n log(action: string, details: Record<string, unknown>): void {\n const timestamp = new Date().toISOString();\n const detailsStr = JSON.stringify(details);\n const entry = `${timestamp}\\t${action}\\t${detailsStr}\\n`;\n mkdirSync(dirname(this.logPath), { recursive: true });\n appendFileSync(this.logPath, entry, { mode: 0o600 });\n }\n\n getLog(): string[] {\n try {\n const data = readFileSync(this.logPath, 'utf8');\n return data.trim().split('\\n').filter(Boolean);\n } catch {\n return [];\n }\n }\n}\n","import { Stagehand } from '@browserbasehq/stagehand';\nimport type { BillingCredentials } from '../vault/types.js';\nimport type { Transaction } from '../transactions/types.js';\nimport type { CheckoutResult, ExecutorConfig } from './types.js';\nimport type { BrowserProvider } from './browser-provider.js';\nimport { CheckoutFailedError } from '../errors.js';\nimport { credentialsToSwapMap, getPlaceholderVariables } from './placeholder.js';\nimport { LocalBrowserProvider } from './providers/local-provider.js';\n\nexport interface DiscoverResult {\n price: number;\n productName: string;\n}\n\nexport class PurchaseExecutor {\n private provider: BrowserProvider;\n private modelApiKey?: string;\n private stagehand: Stagehand | null = null;\n private proxyUrl: string | undefined;\n private originalBaseUrl: string | undefined;\n\n constructor(config?: ExecutorConfig) {\n this.provider = config?.provider ?? new LocalBrowserProvider();\n this.modelApiKey = config?.modelApiKey ?? process.env.ANTHROPIC_API_KEY;\n }\n\n private createStagehand(): Stagehand {\n return this.provider.createStagehand(this.modelApiKey);\n }\n\n /**\n * Phase 1: Open browser, navigate to URL, extract price and product info.\n * Keeps the session alive for fillAndComplete().\n */\n async openAndDiscover(url: string, instructions?: string): Promise<DiscoverResult> {\n this.stagehand = this.createStagehand();\n await this.stagehand.init();\n const page = this.stagehand.context.activePage()!;\n\n await page.goto(url);\n\n // Let Stagehand find the product and add to cart with optional extra instructions\n const addToCartInstructions = instructions\n ? `On this product page: ${instructions}. Then add the item to the cart.`\n : 'Add this product to the cart.';\n await this.stagehand.act(addToCartInstructions);\n\n // Extract price and product name\n const extracted = await this.stagehand.extract(\n 'Extract the product name and the price (as a number without $ sign) from the page or cart. Return JSON: { \"price\": <number>, \"productName\": \"<string>\" }',\n ) as any;\n\n const price = parseFloat(extracted?.price ?? extracted?.extraction?.price ?? '0');\n const productName = extracted?.productName ?? extracted?.extraction?.productName ?? 'Unknown Product';\n\n return { price, productName };\n }\n\n /**\n * Phase 2: Proceed to checkout, fill forms, swap credentials, and submit.\n * Must be called after openAndDiscover().\n */\n async fillAndComplete(credentials: BillingCredentials): Promise<CheckoutResult> {\n if (!this.stagehand) {\n throw new CheckoutFailedError('No active session. Call openAndDiscover() first.');\n }\n\n try {\n // Proceed to checkout\n await this.stagehand.act('Proceed to checkout from the cart.');\n\n // Fill checkout form with placeholders\n const variables = getPlaceholderVariables();\n await this.stagehand.act(\n `Fill in the checkout form with these values:\n Name: ${variables.cardholder_name}\n Card Number: ${variables.card_number}\n Expiry: ${variables.card_expiry}\n CVV: ${variables.card_cvv}\n Email: ${variables.email}\n Phone: ${variables.phone}\n Billing Street: ${variables.billing_street}\n Billing City: ${variables.billing_city}\n Billing State: ${variables.billing_state}\n Billing ZIP: ${variables.billing_zip}\n Billing Country: ${variables.billing_country}\n Shipping Street: ${variables.shipping_street}\n Shipping City: ${variables.shipping_city}\n Shipping State: ${variables.shipping_state}\n Shipping ZIP: ${variables.shipping_zip}\n Shipping Country: ${variables.shipping_country}`,\n { variables },\n );\n\n // Atomic swap: replace placeholders with real credentials and submit\n const swapMap = credentialsToSwapMap(credentials);\n const page = this.stagehand.context.activePage()!;\n\n await page.evaluate((map: Record<string, string>) => {\n const inputs = document.querySelectorAll('input, textarea, select');\n for (const input of inputs) {\n const el = input as HTMLInputElement;\n for (const [placeholder, value] of Object.entries(map)) {\n if (el.value === placeholder) {\n el.value = value;\n el.dispatchEvent(new Event('input', { bubbles: true }));\n el.dispatchEvent(new Event('change', { bubbles: true }));\n }\n }\n }\n const submitBtn = document.querySelector('button[type=\"submit\"], input[type=\"submit\"]') as HTMLElement | null;\n if (submitBtn) submitBtn.click();\n }, swapMap);\n\n // Wait for confirmation page\n await page.waitForTimeout(5000);\n\n // Try to extract confirmation\n const result = await this.stagehand.extract(\n 'Extract the order confirmation number or ID from the page',\n );\n\n const confirmationId = (result as any)?.extraction;\n if (!confirmationId || confirmationId === 'null' || confirmationId === 'UNKNOWN') {\n throw new CheckoutFailedError('No order confirmation found. Checkout may not have completed.');\n }\n\n return {\n success: true,\n confirmationId,\n };\n } catch (err) {\n if (err instanceof CheckoutFailedError) throw err;\n const message = err instanceof Error ? err.message : 'Unknown checkout error';\n throw new CheckoutFailedError(message);\n }\n }\n\n /**\n * Convenience: single-shot execute (navigate + checkout in one call).\n * Used by AgentPay facade when amount is already known.\n */\n async execute(tx: Transaction, credentials: BillingCredentials): Promise<CheckoutResult> {\n this.stagehand = this.createStagehand();\n\n try {\n await this.stagehand.init();\n const page = this.stagehand.context.activePage()!;\n\n await page.goto(tx.url);\n\n const variables = getPlaceholderVariables();\n await this.stagehand.act(\n `Find the product and proceed to checkout. Fill in the checkout form with these values:\n Name: ${variables.cardholder_name}\n Card Number: ${variables.card_number}\n Expiry: ${variables.card_expiry}\n CVV: ${variables.card_cvv}\n Email: ${variables.email}\n Phone: ${variables.phone}\n Billing Street: ${variables.billing_street}\n Billing City: ${variables.billing_city}\n Billing State: ${variables.billing_state}\n Billing ZIP: ${variables.billing_zip}\n Billing Country: ${variables.billing_country}\n Shipping Street: ${variables.shipping_street}\n Shipping City: ${variables.shipping_city}\n Shipping State: ${variables.shipping_state}\n Shipping ZIP: ${variables.shipping_zip}\n Shipping Country: ${variables.shipping_country}`,\n { variables },\n );\n\n const swapMap = credentialsToSwapMap(credentials);\n await page.evaluate((map: Record<string, string>) => {\n const inputs = document.querySelectorAll('input, textarea, select');\n for (const input of inputs) {\n const el = input as HTMLInputElement;\n for (const [placeholder, value] of Object.entries(map)) {\n if (el.value === placeholder) {\n el.value = value;\n el.dispatchEvent(new Event('input', { bubbles: true }));\n el.dispatchEvent(new Event('change', { bubbles: true }));\n }\n }\n }\n const submitBtn = document.querySelector('button[type=\"submit\"], input[type=\"submit\"]') as HTMLElement | null;\n if (submitBtn) submitBtn.click();\n }, swapMap);\n\n await page.waitForTimeout(5000);\n\n const result = await this.stagehand.extract(\n 'Extract the order confirmation number or ID from the page',\n );\n\n const confirmationId = (result as any)?.extraction;\n if (!confirmationId || confirmationId === 'null' || confirmationId === 'UNKNOWN') {\n throw new CheckoutFailedError('No order confirmation found. Checkout may not have completed.');\n }\n\n return {\n success: true,\n confirmationId,\n };\n } catch (err) {\n if (err instanceof CheckoutFailedError) throw err;\n const message = err instanceof Error ? err.message : 'Unknown checkout error';\n throw new CheckoutFailedError(message);\n } finally {\n await this.close();\n }\n }\n\n async close(): Promise<void> {\n try {\n if (this.stagehand) {\n await this.stagehand.close();\n this.stagehand = null;\n }\n } catch {\n // Ignore cleanup errors\n } finally {\n await this.provider.close();\n }\n }\n}\n","import type { BillingCredentials } from '../vault/types.js';\n\nexport const PLACEHOLDER_MAP = {\n card_number: '{{card_number}}',\n cardholder_name: '{{cardholder_name}}',\n card_expiry: '{{card_expiry}}',\n card_cvv: '{{card_cvv}}',\n billing_street: '{{billing_street}}',\n billing_city: '{{billing_city}}',\n billing_state: '{{billing_state}}',\n billing_zip: '{{billing_zip}}',\n billing_country: '{{billing_country}}',\n shipping_street: '{{shipping_street}}',\n shipping_city: '{{shipping_city}}',\n shipping_state: '{{shipping_state}}',\n shipping_zip: '{{shipping_zip}}',\n shipping_country: '{{shipping_country}}',\n email: '{{email}}',\n phone: '{{phone}}',\n} as const;\n\nexport function getPlaceholderVariables(): Record<string, string> {\n // These are the %var% placeholders used with Stagehand act() variables\n // The AI never sees the real values — only these placeholders\n return {\n card_number: '%card_number%',\n cardholder_name: '%cardholder_name%',\n card_expiry: '%card_expiry%',\n card_cvv: '%card_cvv%',\n billing_street: '%billing_street%',\n billing_city: '%billing_city%',\n billing_state: '%billing_state%',\n billing_zip: '%billing_zip%',\n billing_country: '%billing_country%',\n shipping_street: '%shipping_street%',\n shipping_city: '%shipping_city%',\n shipping_state: '%shipping_state%',\n shipping_zip: '%shipping_zip%',\n shipping_country: '%shipping_country%',\n email: '%email%',\n phone: '%phone%',\n };\n}\n\nexport function credentialsToSwapMap(creds: BillingCredentials): Record<string, string> {\n return {\n [PLACEHOLDER_MAP.card_number]: creds.card.number,\n [PLACEHOLDER_MAP.cardholder_name]: creds.name,\n [PLACEHOLDER_MAP.card_expiry]: creds.card.expiry,\n [PLACEHOLDER_MAP.card_cvv]: creds.card.cvv,\n [PLACEHOLDER_MAP.billing_street]: creds.billingAddress.street,\n [PLACEHOLDER_MAP.billing_city]: creds.billingAddress.city,\n [PLACEHOLDER_MAP.billing_state]: creds.billingAddress.state,\n [PLACEHOLDER_MAP.billing_zip]: creds.billingAddress.zip,\n [PLACEHOLDER_MAP.billing_country]: creds.billingAddress.country,\n [PLACEHOLDER_MAP.shipping_street]: creds.shippingAddress.street,\n [PLACEHOLDER_MAP.shipping_city]: creds.shippingAddress.city,\n [PLACEHOLDER_MAP.shipping_state]: creds.shippingAddress.state,\n [PLACEHOLDER_MAP.shipping_zip]: creds.shippingAddress.zip,\n [PLACEHOLDER_MAP.shipping_country]: creds.shippingAddress.country,\n [PLACEHOLDER_MAP.email]: creds.email,\n [PLACEHOLDER_MAP.phone]: creds.phone,\n };\n}\n\n/**\n * Atomically swap placeholders with real credentials in the DOM and submit.\n * This is called via page.evaluate() — credentials exist in the DOM only for milliseconds.\n */\nexport function getAtomicSwapScript(): string {\n return `\n (swapMap) => {\n const inputs = document.querySelectorAll('input, textarea, select');\n for (const input of inputs) {\n const el = input;\n for (const [placeholder, value] of Object.entries(swapMap)) {\n if (el.value === placeholder) {\n el.value = value;\n el.dispatchEvent(new Event('input', { bubbles: true }));\n el.dispatchEvent(new Event('change', { bubbles: true }));\n }\n }\n }\n // Submit the form\n const submitBtn = document.querySelector('button[type=\"submit\"], input[type=\"submit\"]');\n if (submitBtn) submitBtn.click();\n }\n `;\n}\n","import { Stagehand } from '@browserbasehq/stagehand';\nimport type { BrowserProvider } from '../browser-provider.js';\n\n/**\n * Default browser provider — runs Chromium locally via Playwright.\n * No cloud browser service needed.\n */\nexport class LocalBrowserProvider implements BrowserProvider {\n createStagehand(modelApiKey?: string): Stagehand {\n return new Stagehand({\n env: 'LOCAL',\n model: modelApiKey\n ? { modelName: 'claude-3-7-sonnet-latest', apiKey: modelApiKey }\n : undefined,\n });\n }\n\n async close(): Promise<void> {\n // No cleanup needed for local mode\n }\n}\n","import { createServer, type IncomingMessage, type ServerResponse, type Server } from 'node:http';\nimport { randomBytes } from 'node:crypto';\nimport { mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { getSetupHtml } from './setup-html.js';\nimport { openBrowser } from '../utils/open-browser.js';\nimport { encrypt, saveVault } from '../vault/vault.js';\nimport { generateKeyPair, saveKeyPair } from '../auth/keypair.js';\nimport { BudgetManager } from '../budget/budget.js';\nimport { AuditLogger } from '../audit/logger.js';\nimport { getHomePath, getCredentialsPath, getKeysPath, getWalletPath, getAuditPath } from '../utils/paths.js';\nimport { TimeoutError } from '../errors.js';\nimport type { BillingCredentials } from '../vault/types.js';\n\nconst TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes\nconst MAX_BODY = 8192; // setup form sends more data than approval\n\nexport interface SetupResult {\n completed: boolean;\n}\n\nfunction parseBody(req: IncomingMessage): Promise<Record<string, unknown>> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n req.on('data', (chunk: Buffer) => {\n size += chunk.length;\n if (size > MAX_BODY) {\n req.destroy();\n reject(new Error('Request body too large'));\n return;\n }\n chunks.push(chunk);\n });\n req.on('end', () => {\n try {\n const text = Buffer.concat(chunks).toString('utf8');\n resolve(text ? JSON.parse(text) : {});\n } catch {\n reject(new Error('Invalid JSON'));\n }\n });\n req.on('error', reject);\n });\n}\n\nfunction sendJson(res: ServerResponse, status: number, body: Record<string, unknown>): void {\n const json = JSON.stringify(body);\n res.writeHead(status, {\n 'Content-Type': 'application/json',\n 'Content-Length': Buffer.byteLength(json),\n });\n res.end(json);\n}\n\nfunction sendHtml(res: ServerResponse, html: string): void {\n res.writeHead(200, {\n 'Content-Type': 'text/html; charset=utf-8',\n 'Content-Length': Buffer.byteLength(html),\n });\n res.end(html);\n}\n\nfunction isNonEmptyString(val: unknown): val is string {\n return typeof val === 'string' && val.length > 0;\n}\n\nfunction isAddress(val: unknown): val is { street: string; city: string; state: string; zip: string; country: string } {\n if (!val || typeof val !== 'object') return false;\n const a = val as Record<string, unknown>;\n return isNonEmptyString(a.street)\n && isNonEmptyString(a.city)\n && isNonEmptyString(a.state)\n && isNonEmptyString(a.zip)\n && isNonEmptyString(a.country);\n}\n\nfunction isCard(val: unknown): val is { number: string; expiry: string; cvv: string } {\n if (!val || typeof val !== 'object') return false;\n const c = val as Record<string, unknown>;\n return isNonEmptyString(c.number) && isNonEmptyString(c.expiry) && isNonEmptyString(c.cvv);\n}\n\nexport interface SetupServerHandle {\n server: Server;\n token: string;\n port: number;\n promise: Promise<SetupResult>;\n}\n\n/**\n * Create the ephemeral setup server without opening a browser.\n * Useful for testing — call `requestBrowserSetup` for the full flow.\n */\nexport function createSetupServer(\n options?: { openBrowser?: boolean; home?: string },\n): SetupServerHandle {\n const nonce = randomBytes(32).toString('hex');\n let settled = false;\n let tokenUsed = false;\n let resolvePromise: (result: SetupResult) => void;\n let rejectPromise: (err: Error) => void;\n let timer: ReturnType<typeof setTimeout>;\n let serverInstance: Server;\n\n const promise = new Promise<SetupResult>((resolve, reject) => {\n resolvePromise = resolve;\n rejectPromise = reject;\n });\n\n function cleanup(): void {\n clearTimeout(timer);\n serverInstance.close();\n }\n\n const home = options?.home ?? getHomePath();\n\n serverInstance = createServer(async (req, res) => {\n const url = new URL(req.url ?? '/', `http://${req.headers.host}`);\n const method = req.method ?? 'GET';\n\n try {\n // GET /setup?token=X — serve setup page\n if (method === 'GET' && url.pathname === '/setup') {\n const token = url.searchParams.get('token');\n if (token !== nonce || tokenUsed) {\n sendHtml(res, '<h1>Invalid or expired link.</h1>');\n return;\n }\n sendHtml(res, getSetupHtml(nonce));\n return;\n }\n\n // POST /api/setup — process setup form\n if (method === 'POST' && url.pathname === '/api/setup') {\n const body = await parseBody(req);\n if (body.token !== nonce || tokenUsed) {\n sendJson(res, 403, { error: 'Invalid or expired token.' });\n return;\n }\n\n // Validate required fields\n const passphrase = body.passphrase;\n if (!isNonEmptyString(passphrase)) {\n sendJson(res, 400, { error: 'Passphrase is required.' });\n return;\n }\n\n if (!isCard(body.card)) {\n sendJson(res, 400, { error: 'Card number, expiry, and CVV are required.' });\n return;\n }\n\n if (!isNonEmptyString(body.name) || !isNonEmptyString(body.email) || !isNonEmptyString(body.phone)) {\n sendJson(res, 400, { error: 'Name, email, and phone are required.' });\n return;\n }\n\n if (!isAddress(body.billingAddress)) {\n sendJson(res, 400, { error: 'Complete billing address is required.' });\n return;\n }\n\n if (!isAddress(body.shippingAddress)) {\n sendJson(res, 400, { error: 'Complete shipping address is required.' });\n return;\n }\n\n try {\n // Ensure home directory exists\n mkdirSync(home, { recursive: true });\n\n // Encrypt and save vault\n const credentials: BillingCredentials = {\n card: { number: body.card.number, expiry: body.card.expiry, cvv: body.card.cvv },\n name: body.name as string,\n billingAddress: {\n street: (body.billingAddress as Record<string, string>).street,\n city: (body.billingAddress as Record<string, string>).city,\n state: (body.billingAddress as Record<string, string>).state,\n zip: (body.billingAddress as Record<string, string>).zip,\n country: (body.billingAddress as Record<string, string>).country,\n },\n shippingAddress: {\n street: (body.shippingAddress as Record<string, string>).street,\n city: (body.shippingAddress as Record<string, string>).city,\n state: (body.shippingAddress as Record<string, string>).state,\n zip: (body.shippingAddress as Record<string, string>).zip,\n country: (body.shippingAddress as Record<string, string>).country,\n },\n email: body.email as string,\n phone: body.phone as string,\n };\n\n const credPath = join(home, 'credentials.enc');\n const vault = encrypt(credentials, passphrase);\n saveVault(vault, credPath);\n\n // Generate and save keypair\n const keysDir = join(home, 'keys');\n mkdirSync(keysDir, { recursive: true });\n const keys = generateKeyPair(passphrase);\n saveKeyPair(keys, join(keysDir, 'public.pem'), join(keysDir, 'private.pem'));\n\n // Initialize wallet\n const budget = typeof body.budget === 'number' ? body.budget : 0;\n const limitPerTx = typeof body.limitPerTx === 'number' ? body.limitPerTx : 0;\n const bm = new BudgetManager(join(home, 'wallet.json'));\n bm.initWallet(budget, limitPerTx);\n\n // Audit\n const audit = new AuditLogger(join(home, 'audit.log'));\n audit.log('SETUP', { message: 'credentials encrypted, keypair generated, wallet initialized', source: 'browser-setup' });\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Setup failed';\n sendJson(res, 500, { error: msg });\n return;\n }\n\n tokenUsed = true;\n sendJson(res, 200, { ok: true });\n\n if (!settled) {\n settled = true;\n cleanup();\n resolvePromise({ completed: true });\n }\n return;\n }\n\n sendJson(res, 404, { error: 'Not found' });\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Internal error';\n sendJson(res, 500, { error: message });\n }\n });\n\n timer = setTimeout(() => {\n if (!settled) {\n settled = true;\n cleanup();\n rejectPromise(new TimeoutError('Setup timed out after 10 minutes.'));\n }\n }, TIMEOUT_MS);\n\n serverInstance.on('error', (err) => {\n if (!settled) {\n settled = true;\n cleanup();\n rejectPromise(err);\n }\n });\n\n let portValue = 0;\n const handle: SetupServerHandle = {\n server: serverInstance,\n token: nonce,\n get port() { return portValue; },\n promise,\n };\n\n serverInstance.listen(0, '127.0.0.1', () => {\n const addr = serverInstance.address();\n if (!addr || typeof addr === 'string') {\n if (!settled) {\n settled = true;\n cleanup();\n rejectPromise(new Error('Failed to bind server'));\n }\n return;\n }\n portValue = addr.port;\n const pageUrl = `http://127.0.0.1:${addr.port}/setup?token=${nonce}`;\n\n if (options?.openBrowser !== false) {\n console.log('Opening setup form in browser...');\n openBrowser(pageUrl);\n }\n });\n\n return handle;\n}\n\n/**\n * Launch an ephemeral HTTP server on localhost, open a browser page\n * where the human fills in credentials, passphrase, and budget.\n * All sensitive data stays in the browser->server HTTP request on localhost.\n * Never touches stdout/terminal.\n */\nexport function requestBrowserSetup(home?: string): Promise<SetupResult> {\n const handle = createSetupServer({ openBrowser: true, home });\n return handle.promise;\n}\n","export function getSetupHtml(token: string): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>AgentPay — Setup</title>\n<style>\n *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n background: #f5f5f5;\n color: #111;\n min-height: 100vh;\n display: flex;\n justify-content: center;\n padding: 40px 16px;\n }\n .container { width: 100%; max-width: 480px; }\n h1 { font-size: 24px; font-weight: 700; margin-bottom: 4px; }\n .subtitle { color: #666; font-size: 14px; margin-bottom: 24px; }\n .card {\n background: #fff;\n border-radius: 8px;\n padding: 24px;\n margin-bottom: 16px;\n border: 1px solid #e0e0e0;\n }\n .card-title {\n font-size: 15px;\n font-weight: 600;\n margin-bottom: 16px;\n padding-bottom: 8px;\n border-bottom: 1px solid #f0f0f0;\n }\n label { display: block; font-size: 13px; font-weight: 500; color: #333; margin-bottom: 6px; }\n input[type=\"text\"], input[type=\"password\"], input[type=\"email\"], input[type=\"tel\"], input[type=\"number\"] {\n width: 100%;\n padding: 12px 14px;\n border: 1px solid #d0d0d0;\n border-radius: 8px;\n font-size: 15px;\n font-family: inherit;\n outline: none;\n transition: border-color 0.15s;\n }\n input:focus { border-color: #111; }\n .field { margin-bottom: 14px; }\n .field:last-child { margin-bottom: 0; }\n .row { display: flex; gap: 12px; }\n .row > .field { flex: 1; }\n .checkbox-row {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 14px;\n }\n .checkbox-row input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n }\n .checkbox-row label {\n margin-bottom: 0;\n cursor: pointer;\n font-size: 14px;\n }\n .btn-submit {\n width: 100%;\n padding: 14px;\n border: none;\n border-radius: 8px;\n font-size: 15px;\n font-weight: 600;\n cursor: pointer;\n background: #111;\n color: #fff;\n transition: opacity 0.15s;\n }\n .btn-submit:hover { opacity: 0.85; }\n .btn-submit:disabled { opacity: 0.5; cursor: not-allowed; }\n .error { color: #c62828; font-size: 13px; margin-top: 10px; }\n .success-screen {\n text-align: center;\n padding: 40px 0;\n }\n .checkmark { font-size: 48px; margin-bottom: 16px; color: #2e7d32; }\n .success-msg { font-size: 16px; font-weight: 600; margin-bottom: 8px; }\n .success-hint { font-size: 13px; color: #666; }\n .hidden { display: none; }\n .hint { font-size: 12px; color: #999; margin-top: 4px; }\n</style>\n</head>\n<body>\n<div class=\"container\">\n <div id=\"form-view\">\n <h1>AgentPay</h1>\n <p class=\"subtitle\">Initial Setup</p>\n\n <div class=\"card\">\n <div class=\"card-title\">Passphrase</div>\n <div class=\"field\">\n <label for=\"passphrase\">Choose a passphrase</label>\n <input type=\"password\" id=\"passphrase\" placeholder=\"Enter passphrase\" autofocus>\n </div>\n <div class=\"field\">\n <label for=\"passphrase-confirm\">Confirm passphrase</label>\n <input type=\"password\" id=\"passphrase-confirm\" placeholder=\"Re-enter passphrase\">\n </div>\n </div>\n\n <div class=\"card\">\n <div class=\"card-title\">Budget</div>\n <div class=\"row\">\n <div class=\"field\">\n <label for=\"budget\">Total budget ($)</label>\n <input type=\"number\" id=\"budget\" placeholder=\"0\" min=\"0\" step=\"0.01\">\n </div>\n <div class=\"field\">\n <label for=\"limit-per-tx\">Per-transaction limit ($)</label>\n <input type=\"number\" id=\"limit-per-tx\" placeholder=\"0\" min=\"0\" step=\"0.01\">\n </div>\n </div>\n <div class=\"hint\">Leave at 0 to set later via <code>agentpay budget</code>.</div>\n </div>\n\n <div class=\"card\">\n <div class=\"card-title\">Card</div>\n <div class=\"field\">\n <label for=\"card-number\">Card number</label>\n <input type=\"text\" id=\"card-number\" placeholder=\"4111 1111 1111 1111\" autocomplete=\"cc-number\">\n </div>\n <div class=\"row\">\n <div class=\"field\">\n <label for=\"card-expiry\">Expiry (MM/YY)</label>\n <input type=\"text\" id=\"card-expiry\" placeholder=\"MM/YY\" autocomplete=\"cc-exp\" maxlength=\"5\">\n </div>\n <div class=\"field\">\n <label for=\"card-cvv\">CVV</label>\n <input type=\"text\" id=\"card-cvv\" placeholder=\"123\" autocomplete=\"cc-csc\" maxlength=\"4\">\n </div>\n </div>\n </div>\n\n <div class=\"card\">\n <div class=\"card-title\">Personal</div>\n <div class=\"field\">\n <label for=\"name\">Full name</label>\n <input type=\"text\" id=\"name\" placeholder=\"Jane Doe\" autocomplete=\"name\">\n </div>\n <div class=\"row\">\n <div class=\"field\">\n <label for=\"email\">Email</label>\n <input type=\"email\" id=\"email\" placeholder=\"jane@example.com\" autocomplete=\"email\">\n </div>\n <div class=\"field\">\n <label for=\"phone\">Phone</label>\n <input type=\"tel\" id=\"phone\" placeholder=\"+1 555-0100\" autocomplete=\"tel\">\n </div>\n </div>\n </div>\n\n <div class=\"card\">\n <div class=\"card-title\">Billing Address</div>\n <div class=\"field\">\n <label for=\"billing-street\">Street</label>\n <input type=\"text\" id=\"billing-street\" autocomplete=\"billing street-address\">\n </div>\n <div class=\"row\">\n <div class=\"field\">\n <label for=\"billing-city\">City</label>\n <input type=\"text\" id=\"billing-city\" autocomplete=\"billing address-level2\">\n </div>\n <div class=\"field\">\n <label for=\"billing-state\">State</label>\n <input type=\"text\" id=\"billing-state\" autocomplete=\"billing address-level1\">\n </div>\n </div>\n <div class=\"row\">\n <div class=\"field\">\n <label for=\"billing-zip\">ZIP</label>\n <input type=\"text\" id=\"billing-zip\" autocomplete=\"billing postal-code\">\n </div>\n <div class=\"field\">\n <label for=\"billing-country\">Country</label>\n <input type=\"text\" id=\"billing-country\" placeholder=\"US\" autocomplete=\"billing country\">\n </div>\n </div>\n </div>\n\n <div class=\"card\">\n <div class=\"card-title\">Shipping Address</div>\n <div class=\"checkbox-row\">\n <input type=\"checkbox\" id=\"same-as-billing\" checked>\n <label for=\"same-as-billing\">Same as billing</label>\n </div>\n <div id=\"shipping-fields\" class=\"hidden\">\n <div class=\"field\">\n <label for=\"shipping-street\">Street</label>\n <input type=\"text\" id=\"shipping-street\" autocomplete=\"shipping street-address\">\n </div>\n <div class=\"row\">\n <div class=\"field\">\n <label for=\"shipping-city\">City</label>\n <input type=\"text\" id=\"shipping-city\" autocomplete=\"shipping address-level2\">\n </div>\n <div class=\"field\">\n <label for=\"shipping-state\">State</label>\n <input type=\"text\" id=\"shipping-state\" autocomplete=\"shipping address-level1\">\n </div>\n </div>\n <div class=\"row\">\n <div class=\"field\">\n <label for=\"shipping-zip\">ZIP</label>\n <input type=\"text\" id=\"shipping-zip\" autocomplete=\"shipping postal-code\">\n </div>\n <div class=\"field\">\n <label for=\"shipping-country\">Country</label>\n <input type=\"text\" id=\"shipping-country\" placeholder=\"US\" autocomplete=\"shipping country\">\n </div>\n </div>\n </div>\n </div>\n\n <div id=\"error\" class=\"error hidden\"></div>\n <button class=\"btn-submit\" id=\"btn-submit\">Complete Setup</button>\n </div>\n\n <div id=\"success-view\" class=\"hidden\">\n <h1>AgentPay</h1>\n <p class=\"subtitle\">Setup Complete</p>\n <div class=\"card\">\n <div class=\"success-screen\">\n <div class=\"checkmark\">&#10003;</div>\n <div class=\"success-msg\">Your wallet is ready.</div>\n <div class=\"success-hint\">You can close this tab and return to the terminal.</div>\n </div>\n </div>\n </div>\n</div>\n<script>\n(function() {\n var token = ${JSON.stringify(token)};\n var formView = document.getElementById('form-view');\n var successView = document.getElementById('success-view');\n var btnSubmit = document.getElementById('btn-submit');\n var errDiv = document.getElementById('error');\n var sameAsBilling = document.getElementById('same-as-billing');\n var shippingFields = document.getElementById('shipping-fields');\n\n sameAsBilling.addEventListener('change', function() {\n shippingFields.classList.toggle('hidden', sameAsBilling.checked);\n });\n\n function val(id) { return document.getElementById(id).value.trim(); }\n\n function showError(msg) {\n errDiv.textContent = msg;\n errDiv.classList.remove('hidden');\n }\n\n function clearError() {\n errDiv.classList.add('hidden');\n }\n\n btnSubmit.addEventListener('click', function() {\n clearError();\n\n var passphrase = val('passphrase');\n var passphraseConfirm = val('passphrase-confirm');\n\n if (!passphrase) { showError('Passphrase is required.'); return; }\n if (passphrase !== passphraseConfirm) { showError('Passphrases do not match.'); return; }\n\n var cardNumber = val('card-number');\n var cardExpiry = val('card-expiry');\n var cardCvv = val('card-cvv');\n if (!cardNumber || !cardExpiry || !cardCvv) { showError('Card number, expiry, and CVV are required.'); return; }\n\n var name = val('name');\n var email = val('email');\n var phone = val('phone');\n if (!name || !email || !phone) { showError('Name, email, and phone are required.'); return; }\n\n var billingStreet = val('billing-street');\n var billingCity = val('billing-city');\n var billingState = val('billing-state');\n var billingZip = val('billing-zip');\n var billingCountry = val('billing-country');\n if (!billingStreet || !billingCity || !billingState || !billingZip || !billingCountry) {\n showError('All billing address fields are required.'); return;\n }\n\n var shippingStreet, shippingCity, shippingState, shippingZip, shippingCountry;\n if (sameAsBilling.checked) {\n shippingStreet = billingStreet;\n shippingCity = billingCity;\n shippingState = billingState;\n shippingZip = billingZip;\n shippingCountry = billingCountry;\n } else {\n shippingStreet = val('shipping-street');\n shippingCity = val('shipping-city');\n shippingState = val('shipping-state');\n shippingZip = val('shipping-zip');\n shippingCountry = val('shipping-country');\n if (!shippingStreet || !shippingCity || !shippingState || !shippingZip || !shippingCountry) {\n showError('All shipping address fields are required.'); return;\n }\n }\n\n var budget = parseFloat(document.getElementById('budget').value) || 0;\n var limitPerTx = parseFloat(document.getElementById('limit-per-tx').value) || 0;\n\n btnSubmit.disabled = true;\n btnSubmit.textContent = 'Setting up...';\n\n fetch('/api/setup', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n token: token,\n passphrase: passphrase,\n budget: budget,\n limitPerTx: limitPerTx,\n card: { number: cardNumber, expiry: cardExpiry, cvv: cardCvv },\n name: name,\n email: email,\n phone: phone,\n billingAddress: { street: billingStreet, city: billingCity, state: billingState, zip: billingZip, country: billingCountry },\n shippingAddress: { street: shippingStreet, city: shippingCity, state: shippingState, zip: shippingZip, country: shippingCountry }\n })\n })\n .then(function(res) { return res.json(); })\n .then(function(data) {\n if (data.error) {\n showError(data.error);\n btnSubmit.disabled = false;\n btnSubmit.textContent = 'Complete Setup';\n } else {\n formView.classList.add('hidden');\n successView.classList.remove('hidden');\n setTimeout(function() { window.close(); }, 3000);\n }\n })\n .catch(function() {\n showError('Failed to submit. Is the CLI still running?');\n btnSubmit.disabled = false;\n btnSubmit.textContent = 'Complete Setup';\n });\n });\n})();\n</script>\n</body>\n</html>`;\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from 'node:http';\nimport { getDashboardHtml } from './html.js';\nimport { handleGetStatus, handlePostSetup, handlePostFund } from './routes.js';\n\nconst MAX_BODY = 1_048_576; // 1 MB\n\nfunction parseBody(req: IncomingMessage): Promise<Record<string, unknown>> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n req.on('data', (chunk: Buffer) => {\n size += chunk.length;\n if (size > MAX_BODY) {\n req.destroy();\n reject(new Error('Request body too large'));\n return;\n }\n chunks.push(chunk);\n });\n req.on('end', () => {\n try {\n const text = Buffer.concat(chunks).toString('utf8');\n resolve(text ? JSON.parse(text) : {});\n } catch {\n reject(new Error('Invalid JSON'));\n }\n });\n req.on('error', reject);\n });\n}\n\nfunction sendJson(res: ServerResponse, status: number, body: Record<string, unknown>): void {\n const json = JSON.stringify(body);\n res.writeHead(status, {\n 'Content-Type': 'application/json',\n 'Content-Length': Buffer.byteLength(json),\n });\n res.end(json);\n}\n\nfunction sendHtml(res: ServerResponse, html: string): void {\n res.writeHead(200, {\n 'Content-Type': 'text/html; charset=utf-8',\n 'Content-Length': Buffer.byteLength(html),\n });\n res.end(html);\n}\n\nexport function startServer(port: number): Promise<ReturnType<typeof createServer>> {\n return new Promise((resolve, reject) => {\n const server = createServer(async (req, res) => {\n const url = req.url ?? '/';\n const method = req.method ?? 'GET';\n\n try {\n if (method === 'GET' && url === '/api/status') {\n const result = handleGetStatus();\n sendJson(res, result.status, result.body);\n } else if (method === 'POST' && url === '/api/setup') {\n const body = await parseBody(req);\n const result = handlePostSetup(body as unknown as Parameters<typeof handlePostSetup>[0]);\n sendJson(res, result.status, result.body);\n } else if (method === 'POST' && url === '/api/fund') {\n const body = await parseBody(req);\n const result = handlePostFund(body as unknown as Parameters<typeof handlePostFund>[0]);\n sendJson(res, result.status, result.body);\n } else if (method === 'GET' && (url === '/' || url === '/index.html')) {\n sendHtml(res, getDashboardHtml());\n } else {\n sendJson(res, 404, { error: 'Not found' });\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Internal error';\n sendJson(res, 500, { error: message });\n }\n });\n\n server.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n reject(new Error(`Port ${port} is already in use. Try a different port with --port <number>.`));\n } else {\n reject(err);\n }\n });\n\n server.listen(port, '127.0.0.1', () => {\n resolve(server);\n });\n });\n}\n","export function getDashboardHtml(): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>AgentPay Dashboard</title>\n<style>\n *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n background: #f5f5f5;\n color: #111;\n min-height: 100vh;\n display: flex;\n justify-content: center;\n padding: 40px 16px;\n }\n .container { width: 100%; max-width: 480px; }\n h1 { font-size: 24px; font-weight: 700; margin-bottom: 8px; }\n h2 { font-size: 18px; font-weight: 600; margin-bottom: 12px; }\n .subtitle { color: #666; font-size: 14px; margin-bottom: 32px; }\n .card {\n background: #fff;\n border-radius: 8px;\n padding: 24px;\n margin-bottom: 16px;\n border: 1px solid #e0e0e0;\n }\n label { display: block; font-size: 13px; font-weight: 500; color: #333; margin-bottom: 4px; }\n input, select {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid #d0d0d0;\n border-radius: 8px;\n font-size: 14px;\n margin-bottom: 16px;\n outline: none;\n transition: border-color 0.15s;\n }\n input:focus { border-color: #111; }\n .row { display: flex; gap: 12px; }\n .row > div { flex: 1; }\n button {\n width: 100%;\n padding: 12px;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: opacity 0.15s;\n }\n button:hover { opacity: 0.85; }\n button:disabled { opacity: 0.5; cursor: not-allowed; }\n .btn-primary { background: #111; color: #fff; }\n .btn-secondary { background: #e0e0e0; color: #111; }\n\n /* Progress bar for wizard */\n .progress { display: flex; gap: 6px; margin-bottom: 24px; }\n .progress .step {\n flex: 1; height: 4px; border-radius: 2px; background: #e0e0e0;\n transition: background 0.3s;\n }\n .progress .step.active { background: #111; }\n\n /* Balance display */\n .balance-display {\n text-align: center;\n padding: 32px 0;\n }\n .balance-amount {\n font-size: 48px;\n font-weight: 700;\n letter-spacing: -1px;\n }\n .balance-label { font-size: 13px; color: #666; margin-top: 4px; }\n\n /* Budget bar */\n .budget-bar-container { margin: 16px 0; }\n .budget-bar {\n height: 8px;\n background: #e0e0e0;\n border-radius: 4px;\n overflow: hidden;\n }\n .budget-bar-fill {\n height: 100%;\n background: #111;\n border-radius: 4px;\n transition: width 0.3s;\n }\n .budget-bar-labels {\n display: flex;\n justify-content: space-between;\n font-size: 12px;\n color: #666;\n margin-top: 4px;\n }\n\n /* Stats grid */\n .stats { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 16px; }\n .stat { text-align: center; padding: 12px; background: #f9f9f9; border-radius: 8px; }\n .stat-value { font-size: 18px; font-weight: 700; }\n .stat-label { font-size: 11px; color: #666; margin-top: 2px; }\n\n /* Add funds inline */\n .add-funds-row { display: flex; gap: 8px; }\n .add-funds-row input { margin-bottom: 0; flex: 1; }\n .add-funds-row button { width: auto; padding: 10px 20px; }\n\n /* Transactions */\n .tx-list { margin-top: 12px; }\n .tx-item {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 10px 0;\n border-bottom: 1px solid #f0f0f0;\n font-size: 13px;\n }\n .tx-item:last-child { border-bottom: none; }\n .tx-merchant { font-weight: 500; }\n .tx-amount { font-weight: 600; }\n .tx-status {\n font-size: 11px;\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 500;\n }\n .tx-status.completed { background: #e6f4ea; color: #1e7e34; }\n .tx-status.pending { background: #fff8e1; color: #f57f17; }\n .tx-status.failed { background: #fde8e8; color: #c62828; }\n .tx-status.rejected { background: #fde8e8; color: #c62828; }\n .tx-status.approved { background: #e3f2fd; color: #1565c0; }\n .tx-status.executing { background: #e3f2fd; color: #1565c0; }\n\n .error { color: #c62828; font-size: 13px; margin-top: 8px; }\n .success { color: #1e7e34; font-size: 13px; margin-top: 8px; }\n .hidden { display: none; }\n\n /* Checkbox row for same-as-billing */\n .checkbox-row {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 16px;\n }\n .checkbox-row input { width: auto; margin: 0; }\n .checkbox-row label { margin: 0; }\n</style>\n</head>\n<body>\n<div class=\"container\" id=\"app\">\n <div id=\"loading\">Loading...</div>\n</div>\n\n<script>\nconst App = {\n state: { isSetup: false, wallet: null, recentTransactions: [], wizardStep: 1 },\n\n async init() {\n try {\n const res = await fetch('/api/status');\n const data = await res.json();\n this.state.isSetup = data.isSetup;\n this.state.wallet = data.wallet;\n this.state.recentTransactions = data.recentTransactions || [];\n } catch (e) {\n console.error('Failed to load status', e);\n }\n this.render();\n },\n\n render() {\n const app = document.getElementById('app');\n if (this.state.isSetup && this.state.wallet) {\n app.innerHTML = this.renderDashboard();\n this.bindDashboard();\n } else if (this.state.isSetup) {\n app.innerHTML = '<div class=\"card\"><h2>Setup detected</h2><p>Wallet data could not be loaded. Try running <code>agentpay budget --set 100</code> from the CLI.</p></div>';\n } else {\n app.innerHTML = this.renderWizard();\n this.bindWizard();\n }\n },\n\n fmt(n) {\n return '$' + Number(n).toFixed(2);\n },\n\n renderDashboard() {\n const w = this.state.wallet;\n const pct = w.budget > 0 ? Math.min(100, (w.spent / w.budget) * 100) : 0;\n const txHtml = this.state.recentTransactions.length === 0\n ? '<p style=\"color:#666;font-size:13px;\">No transactions yet.</p>'\n : this.state.recentTransactions.map(tx => \\`\n <div class=\"tx-item\">\n <div>\n <div class=\"tx-merchant\">\\${this.esc(tx.merchant)}</div>\n <div style=\"color:#999;font-size:11px;\">\\${new Date(tx.createdAt).toLocaleDateString()}</div>\n </div>\n <div style=\"text-align:right\">\n <div class=\"tx-amount\">\\${this.fmt(tx.amount)}</div>\n <span class=\"tx-status \\${tx.status}\">\\${tx.status}</span>\n </div>\n </div>\\`).join('');\n\n return \\`\n <h1>AgentPay</h1>\n <p class=\"subtitle\">Wallet Dashboard</p>\n\n <div class=\"card\">\n <div class=\"balance-display\">\n <div class=\"balance-amount\">\\${this.fmt(w.balance)}</div>\n <div class=\"balance-label\">Available Balance</div>\n </div>\n <div class=\"budget-bar-container\">\n <div class=\"budget-bar\"><div class=\"budget-bar-fill\" style=\"width:\\${pct.toFixed(1)}%\"></div></div>\n <div class=\"budget-bar-labels\">\n <span>\\${this.fmt(w.spent)} spent</span>\n <span>\\${this.fmt(w.budget)} budget</span>\n </div>\n </div>\n </div>\n\n <div class=\"card\">\n <div class=\"stats\">\n <div class=\"stat\"><div class=\"stat-value\">\\${this.fmt(w.budget)}</div><div class=\"stat-label\">Total Budget</div></div>\n <div class=\"stat\"><div class=\"stat-value\">\\${this.fmt(w.spent)}</div><div class=\"stat-label\">Total Spent</div></div>\n <div class=\"stat\"><div class=\"stat-value\">\\${this.fmt(w.balance)}</div><div class=\"stat-label\">Remaining</div></div>\n <div class=\"stat\"><div class=\"stat-value\">\\${w.limitPerTx > 0 ? this.fmt(w.limitPerTx) : 'None'}</div><div class=\"stat-label\">Per-Tx Limit</div></div>\n </div>\n </div>\n\n <div class=\"card\">\n <h2>Add Funds</h2>\n <div class=\"add-funds-row\">\n <input type=\"number\" id=\"fundAmount\" placeholder=\"Amount\" min=\"0.01\" step=\"0.01\">\n <button class=\"btn-primary\" id=\"fundBtn\">Add</button>\n </div>\n <div id=\"fundMsg\"></div>\n </div>\n\n <div class=\"card\">\n <h2>Recent Transactions</h2>\n <div class=\"tx-list\">\\${txHtml}</div>\n </div>\n \\`;\n },\n\n bindDashboard() {\n const btn = document.getElementById('fundBtn');\n const input = document.getElementById('fundAmount');\n const msg = document.getElementById('fundMsg');\n\n btn.addEventListener('click', async () => {\n const amount = parseFloat(input.value);\n if (!amount || amount <= 0) {\n msg.innerHTML = '<p class=\"error\">Enter a valid amount.</p>';\n return;\n }\n btn.disabled = true;\n btn.textContent = '...';\n try {\n const res = await fetch('/api/fund', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ amount }),\n });\n const data = await res.json();\n if (data.error) {\n msg.innerHTML = '<p class=\"error\">' + this.esc(data.error) + '</p>';\n } else {\n this.state.wallet = data.wallet;\n input.value = '';\n this.render();\n }\n } catch (e) {\n msg.innerHTML = '<p class=\"error\">Request failed.</p>';\n }\n btn.disabled = false;\n btn.textContent = 'Add';\n });\n },\n\n renderWizard() {\n const step = this.state.wizardStep;\n const steps = [1, 2, 3, 4];\n const progressHtml = '<div class=\"progress\">' + steps.map(s =>\n '<div class=\"step' + (s <= step ? ' active' : '') + '\"></div>'\n ).join('') + '</div>';\n\n const titles = ['Create Passphrase', 'Card Information', 'Personal Details', 'Budget & Limits'];\n\n let fields = '';\n if (step === 1) {\n fields = \\`\n <label for=\"w_pass\">Passphrase</label>\n <input type=\"password\" id=\"w_pass\" placeholder=\"Choose a strong passphrase\">\n <label for=\"w_pass2\">Confirm Passphrase</label>\n <input type=\"password\" id=\"w_pass2\" placeholder=\"Confirm your passphrase\">\n \\`;\n } else if (step === 2) {\n fields = \\`\n <label for=\"w_cardNum\">Card Number</label>\n <input type=\"text\" id=\"w_cardNum\" placeholder=\"4242 4242 4242 4242\">\n <div class=\"row\">\n <div><label for=\"w_expiry\">Expiry</label><input type=\"text\" id=\"w_expiry\" placeholder=\"MM/YY\"></div>\n <div><label for=\"w_cvv\">CVV</label><input type=\"text\" id=\"w_cvv\" placeholder=\"123\"></div>\n </div>\n \\`;\n } else if (step === 3) {\n fields = \\`\n <label for=\"w_name\">Full Name</label>\n <input type=\"text\" id=\"w_name\" placeholder=\"Jane Doe\">\n <div class=\"row\">\n <div><label for=\"w_email\">Email</label><input type=\"email\" id=\"w_email\" placeholder=\"jane@example.com\"></div>\n <div><label for=\"w_phone\">Phone</label><input type=\"tel\" id=\"w_phone\" placeholder=\"+1 555 0123\"></div>\n </div>\n <label for=\"w_street\">Street Address</label>\n <input type=\"text\" id=\"w_street\" placeholder=\"123 Main St\">\n <div class=\"row\">\n <div><label for=\"w_city\">City</label><input type=\"text\" id=\"w_city\" placeholder=\"San Francisco\"></div>\n <div><label for=\"w_state\">State</label><input type=\"text\" id=\"w_state\" placeholder=\"CA\"></div>\n </div>\n <div class=\"row\">\n <div><label for=\"w_zip\">ZIP</label><input type=\"text\" id=\"w_zip\" placeholder=\"94102\"></div>\n <div><label for=\"w_country\">Country</label><input type=\"text\" id=\"w_country\" placeholder=\"US\" value=\"US\"></div>\n </div>\n \\`;\n } else if (step === 4) {\n fields = \\`\n <label for=\"w_budget\">Initial Budget ($)</label>\n <input type=\"number\" id=\"w_budget\" placeholder=\"200\" min=\"0\" step=\"0.01\">\n <label for=\"w_limit\">Per-Transaction Limit ($)</label>\n <input type=\"number\" id=\"w_limit\" placeholder=\"50 (0 = no limit)\" min=\"0\" step=\"0.01\">\n \\`;\n }\n\n return \\`\n <h1>AgentPay</h1>\n <p class=\"subtitle\">Step \\${step} of 4 — \\${titles[step - 1]}</p>\n \\${progressHtml}\n <div class=\"card\">\n \\${fields}\n <div id=\"wizardError\"></div>\n <div style=\"display:flex;gap:8px;margin-top:8px;\">\n \\${step > 1 ? '<button class=\"btn-secondary\" id=\"wizBack\">Back</button>' : ''}\n <button class=\"btn-primary\" id=\"wizNext\">\\${step === 4 ? 'Complete Setup' : 'Continue'}</button>\n </div>\n </div>\n \\`;\n },\n\n // Wizard form data persisted across steps\n wizardData: {},\n\n bindWizard() {\n const step = this.state.wizardStep;\n const errDiv = document.getElementById('wizardError');\n const nextBtn = document.getElementById('wizNext');\n const backBtn = document.getElementById('wizBack');\n\n // Restore saved data into fields\n this.restoreWizardFields(step);\n\n if (backBtn) {\n backBtn.addEventListener('click', () => {\n this.saveWizardFields(step);\n this.state.wizardStep--;\n this.render();\n });\n }\n\n nextBtn.addEventListener('click', async () => {\n errDiv.innerHTML = '';\n\n if (step === 1) {\n const pass = document.getElementById('w_pass').value;\n const pass2 = document.getElementById('w_pass2').value;\n if (!pass) { errDiv.innerHTML = '<p class=\"error\">Passphrase is required.</p>'; return; }\n if (pass !== pass2) { errDiv.innerHTML = '<p class=\"error\">Passphrases do not match.</p>'; return; }\n this.wizardData.passphrase = pass;\n this.state.wizardStep = 2;\n this.render();\n } else if (step === 2) {\n this.saveWizardFields(step);\n const d = this.wizardData;\n if (!d.cardNumber) { errDiv.innerHTML = '<p class=\"error\">Card number is required.</p>'; return; }\n if (!d.expiry) { errDiv.innerHTML = '<p class=\"error\">Expiry is required.</p>'; return; }\n if (!d.cvv) { errDiv.innerHTML = '<p class=\"error\">CVV is required.</p>'; return; }\n this.state.wizardStep = 3;\n this.render();\n } else if (step === 3) {\n this.saveWizardFields(step);\n const d = this.wizardData;\n if (!d.name) { errDiv.innerHTML = '<p class=\"error\">Full name is required.</p>'; return; }\n this.state.wizardStep = 4;\n this.render();\n } else if (step === 4) {\n this.saveWizardFields(step);\n const d = this.wizardData;\n\n nextBtn.disabled = true;\n nextBtn.textContent = 'Setting up...';\n\n try {\n const res = await fetch('/api/setup', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n passphrase: d.passphrase,\n credentials: {\n card: { number: d.cardNumber, expiry: d.expiry, cvv: d.cvv },\n name: d.name,\n billingAddress: { street: d.street || '', city: d.city || '', state: d.state || '', zip: d.zip || '', country: d.country || 'US' },\n shippingAddress: { street: d.street || '', city: d.city || '', state: d.state || '', zip: d.zip || '', country: d.country || 'US' },\n email: d.email || '',\n phone: d.phone || '',\n },\n budget: parseFloat(d.budget) || 0,\n limitPerTx: parseFloat(d.limit) || 0,\n }),\n });\n const result = await res.json();\n if (result.error) {\n errDiv.innerHTML = '<p class=\"error\">' + this.esc(result.error) + '</p>';\n nextBtn.disabled = false;\n nextBtn.textContent = 'Complete Setup';\n } else {\n this.state.isSetup = true;\n this.state.wallet = result.wallet;\n this.state.recentTransactions = [];\n this.wizardData = {};\n this.render();\n }\n } catch (e) {\n errDiv.innerHTML = '<p class=\"error\">Setup request failed.</p>';\n nextBtn.disabled = false;\n nextBtn.textContent = 'Complete Setup';\n }\n }\n });\n },\n\n saveWizardFields(step) {\n const val = (id) => { const el = document.getElementById(id); return el ? el.value : ''; };\n if (step === 2) {\n this.wizardData.cardNumber = val('w_cardNum');\n this.wizardData.expiry = val('w_expiry');\n this.wizardData.cvv = val('w_cvv');\n } else if (step === 3) {\n this.wizardData.name = val('w_name');\n this.wizardData.email = val('w_email');\n this.wizardData.phone = val('w_phone');\n this.wizardData.street = val('w_street');\n this.wizardData.city = val('w_city');\n this.wizardData.state = val('w_state');\n this.wizardData.zip = val('w_zip');\n this.wizardData.country = val('w_country');\n } else if (step === 4) {\n this.wizardData.budget = val('w_budget');\n this.wizardData.limit = val('w_limit');\n }\n },\n\n restoreWizardFields(step) {\n const set = (id, val) => { const el = document.getElementById(id); if (el && val) el.value = val; };\n if (step === 2) {\n set('w_cardNum', this.wizardData.cardNumber);\n set('w_expiry', this.wizardData.expiry);\n set('w_cvv', this.wizardData.cvv);\n } else if (step === 3) {\n set('w_name', this.wizardData.name);\n set('w_email', this.wizardData.email);\n set('w_phone', this.wizardData.phone);\n set('w_street', this.wizardData.street);\n set('w_city', this.wizardData.city);\n set('w_state', this.wizardData.state);\n set('w_zip', this.wizardData.zip);\n set('w_country', this.wizardData.country);\n } else if (step === 4) {\n set('w_budget', this.wizardData.budget);\n set('w_limit', this.wizardData.limit);\n }\n },\n\n esc(s) {\n const d = document.createElement('div');\n d.textContent = s;\n return d.innerHTML;\n },\n};\n\nApp.init();\n</script>\n</body>\n</html>`;\n}\n","import { existsSync, mkdirSync } from 'node:fs';\nimport { encrypt, saveVault } from '../vault/vault.js';\nimport { generateKeyPair, saveKeyPair } from '../auth/keypair.js';\nimport { BudgetManager } from '../budget/budget.js';\nimport { TransactionManager } from '../transactions/manager.js';\nimport { AuditLogger } from '../audit/logger.js';\nimport { getCredentialsPath, getHomePath, getKeysPath } from '../utils/paths.js';\nimport type { BillingCredentials } from '../vault/types.js';\n\ninterface RouteResult {\n status: number;\n body: Record<string, unknown>;\n}\n\nexport function handleGetStatus(): RouteResult {\n const isSetup = existsSync(getCredentialsPath());\n\n if (!isSetup) {\n return { status: 200, body: { isSetup: false } };\n }\n\n try {\n const bm = new BudgetManager();\n const wallet = bm.getBalance();\n const tm = new TransactionManager();\n const recent = tm.list().slice(-10).reverse();\n\n return {\n status: 200,\n body: { isSetup: true, wallet, recentTransactions: recent },\n };\n } catch {\n return { status: 200, body: { isSetup: true, wallet: null, recentTransactions: [] } };\n }\n}\n\ninterface SetupBody {\n passphrase: string;\n credentials: BillingCredentials;\n budget: number;\n limitPerTx: number;\n}\n\nexport function handlePostSetup(body: SetupBody): RouteResult {\n if (!body.passphrase || !body.credentials) {\n return { status: 400, body: { error: 'Missing passphrase or credentials' } };\n }\n\n try {\n const home = getHomePath();\n mkdirSync(home, { recursive: true });\n\n // Encrypt and save vault\n const vault = encrypt(body.credentials, body.passphrase);\n saveVault(vault, getCredentialsPath());\n\n // Generate and save keypair\n const keys = generateKeyPair(body.passphrase);\n mkdirSync(getKeysPath(), { recursive: true });\n saveKeyPair(keys);\n\n // Initialize wallet\n const bm = new BudgetManager();\n bm.initWallet(body.budget || 0, body.limitPerTx || 0);\n\n // Audit\n const audit = new AuditLogger();\n audit.log('SETUP', { source: 'dashboard', message: 'credentials encrypted, keypair generated, wallet initialized' });\n\n const wallet = bm.getBalance();\n return { status: 200, body: { success: true, wallet } };\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Setup failed';\n return { status: 500, body: { error: message } };\n }\n}\n\ninterface FundBody {\n amount: number;\n}\n\nexport function handlePostFund(body: FundBody): RouteResult {\n if (!body.amount || body.amount <= 0) {\n return { status: 400, body: { error: 'Amount must be positive' } };\n }\n\n try {\n const bm = new BudgetManager();\n const wallet = bm.addFunds(body.amount);\n\n const audit = new AuditLogger();\n audit.log('ADD_FUNDS', { source: 'dashboard', amount: body.amount });\n\n return { status: 200, body: { success: true, wallet } };\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Failed to add funds';\n return { status: 500, body: { error: message } };\n }\n}\n","import { createInterface } from 'node:readline';\nimport type { PassphraseContext } from '../server/passphrase-html.js';\n\nexport type { PassphraseContext } from '../server/passphrase-html.js';\n\nfunction createRl() {\n return createInterface({ input: process.stdin, output: process.stdout });\n}\n\nexport function promptInput(question: string): Promise<string> {\n return new Promise((resolve) => {\n const rl = createRl();\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\nexport async function promptPassphrase(prompt = 'Passphrase: '): Promise<string> {\n // In a real terminal we'd hide input; for simplicity use standard prompt\n return promptInput(prompt);\n}\n\nexport function promptConfirm(question: string): Promise<boolean> {\n return new Promise((resolve) => {\n const rl = createRl();\n rl.question(`${question} (y/N): `, (answer) => {\n rl.close();\n resolve(answer.trim().toLowerCase() === 'y' || answer.trim().toLowerCase() === 'yes');\n });\n });\n}\n\n/**\n * Collect passphrase safely: uses terminal prompt when stdin is a TTY,\n * otherwise opens a browser page so the human can enter it directly\n * (keeping the passphrase out of the agent's context).\n */\nexport async function promptPassphraseSafe(context?: PassphraseContext): Promise<string> {\n if (process.stdin.isTTY) {\n return promptPassphrase('Enter passphrase: ');\n }\n // Dynamic import to avoid loading server code when not needed\n const { collectPassphrase } = await import('../server/passphrase-server.js');\n return collectPassphrase(context);\n}\n","import { join } from 'node:path';\nimport { BudgetManager } from './budget/budget.js';\nimport { TransactionManager } from './transactions/manager.js';\nimport { AuditLogger } from './audit/logger.js';\nimport { PurchaseExecutor } from './executor/executor.js';\nimport { verifyMandate } from './auth/mandate.js';\nimport { decrypt, loadVault } from './vault/vault.js';\nimport { getHomePath } from './utils/paths.js';\nimport {\n NotApprovedError,\n InvalidMandateError,\n InsufficientBalanceError,\n AlreadyExecutedError,\n} from './errors.js';\nimport type { Transaction, Receipt, ProposeOptions } from './transactions/types.js';\nimport type { TransactionDetails } from './auth/types.js';\nimport type { ExecutorConfig } from './executor/types.js';\nimport type { NotifyOptions } from './notify/notify.js';\nimport type { MobileApprovalResult } from './server/mobile-approval-server.js';\nimport { loadConfig, saveConfig, setMobileMode } from './config/config.js';\nimport type { AgentPayConfig } from './config/types.js';\n\nexport interface AgentPayOptions {\n home?: string;\n passphrase?: string;\n executor?: ExecutorConfig;\n}\n\nexport class AgentPay {\n public readonly home: string;\n private passphrase?: string;\n private budgetManager: BudgetManager;\n private txManager: TransactionManager;\n private auditLogger: AuditLogger;\n private executor: PurchaseExecutor;\n\n constructor(options?: AgentPayOptions) {\n this.home = options?.home ?? getHomePath();\n this.passphrase = options?.passphrase;\n this.budgetManager = new BudgetManager(join(this.home, 'wallet.json'));\n this.txManager = new TransactionManager(join(this.home, 'transactions.json'));\n this.auditLogger = new AuditLogger(join(this.home, 'audit.log'));\n this.executor = new PurchaseExecutor(options?.executor);\n }\n\n get wallet() {\n const bm = this.budgetManager;\n return {\n getBalance: () => bm.getBalance(),\n getHistory: () => this.txManager.getHistory(),\n getLimits: () => {\n const w = bm.getBalance();\n return { budget: w.budget, limitPerTx: w.limitPerTx, remaining: w.balance };\n },\n };\n }\n\n get config() {\n return {\n get: (): AgentPayConfig => loadConfig(this.home),\n setMobileMode: (enabled: boolean): AgentPayConfig => setMobileMode(enabled, this.home),\n save: (config: AgentPayConfig): void => saveConfig(config, this.home),\n };\n }\n\n get transactions() {\n return {\n propose: (options: ProposeOptions): Transaction => {\n this.budgetManager.checkProposal(options.amount);\n const tx = this.txManager.propose(options);\n this.auditLogger.log('PROPOSE', { txId: tx.id, merchant: tx.merchant, amount: tx.amount });\n return tx;\n },\n get: (txId: string) => this.txManager.get(txId),\n waitForApproval: async (txId: string, options?: { pollInterval?: number; timeout?: number }) => {\n const { waitForApproval } = await import('./transactions/poller.js');\n return waitForApproval(txId, this.txManager, options);\n },\n requestApproval: async (txId: string): Promise<{ action: 'approved' | 'rejected'; passphrase?: string; reason?: string }> => {\n const tx = this.txManager.get(txId);\n if (!tx) throw new Error(`Transaction ${txId} not found.`);\n if (tx.status !== 'pending') throw new Error(`Transaction ${txId} is not pending.`);\n\n // Check if private key exists before opening browser\n const { existsSync } = await import('node:fs');\n const keyPath = join(this.home, 'keys', 'private.pem');\n if (!existsSync(keyPath)) {\n throw new Error('Private key not found. Run \"agentpay setup\" first.');\n }\n\n const { requestBrowserApproval } = await import('./server/approval-server.js');\n return requestBrowserApproval(tx, this.txManager, this.auditLogger, this.home);\n },\n requestMobileApproval: async (txId: string, notify: NotifyOptions): Promise<MobileApprovalResult> => {\n const tx = this.txManager.get(txId);\n if (!tx) throw new Error(`Transaction ${txId} not found.`);\n if (tx.status !== 'pending') throw new Error(`Transaction ${txId} is not pending.`);\n\n const { existsSync } = await import('node:fs');\n const keyPath = join(this.home, 'keys', 'private.pem');\n if (!existsSync(keyPath)) {\n throw new Error('Private key not found. Run \"agentpay setup\" first.');\n }\n\n const { requestMobileApproval } = await import('./server/mobile-approval-server.js');\n return requestMobileApproval(tx, this.txManager, this.auditLogger, {\n notify,\n home: this.home,\n });\n },\n execute: async (txId: string): Promise<Receipt> => {\n const tx = this.txManager.get(txId);\n if (!tx) throw new Error(`Transaction ${txId} not found.`);\n\n // Validate state\n if (tx.status === 'completed' || tx.status === 'failed') {\n throw new AlreadyExecutedError(txId);\n }\n if (tx.status !== 'approved') {\n throw new NotApprovedError(txId);\n }\n if (!tx.mandate) {\n throw new InvalidMandateError('No mandate found on approved transaction.');\n }\n\n // Verify mandate\n const txDetails: TransactionDetails = {\n txId: tx.id,\n merchant: tx.merchant,\n amount: tx.amount,\n description: tx.description,\n timestamp: tx.createdAt,\n };\n if (!verifyMandate(tx.mandate, txDetails)) {\n throw new InvalidMandateError();\n }\n\n // Check balance\n this.budgetManager.checkProposal(tx.amount);\n\n // Mark executing\n this.txManager.markExecuting(txId);\n this.auditLogger.log('EXECUTE', { txId, browserbaseSessionStarted: true });\n\n try {\n // Decrypt credentials\n if (!this.passphrase) {\n throw new Error('Passphrase required for execution. Pass it to AgentPay constructor.');\n }\n const vaultPath = join(this.home, 'credentials.enc');\n const vault = loadVault(vaultPath);\n const credentials = decrypt(vault, this.passphrase);\n\n // Execute checkout\n const result = await this.executor.execute(tx, credentials);\n\n // Mark completed and deduct balance\n const receipt: Receipt = {\n id: `rcpt_${txId.replace('tx_', '')}`,\n merchant: tx.merchant,\n amount: tx.amount,\n confirmationId: result.confirmationId ?? 'UNKNOWN',\n completedAt: new Date().toISOString(),\n };\n\n this.txManager.markCompleted(txId, receipt);\n this.budgetManager.deductBalance(tx.amount);\n this.auditLogger.log('COMPLETE', { txId, confirmationId: receipt.confirmationId });\n\n return receipt;\n } catch (err) {\n this.txManager.markFailed(txId, err instanceof Error ? err.message : 'Unknown error');\n this.auditLogger.log('FAILED', { txId, error: err instanceof Error ? err.message : 'Unknown' });\n throw err;\n }\n },\n getReceipt: (txId: string): Receipt | undefined => {\n const tx = this.txManager.get(txId);\n return tx?.receipt;\n },\n };\n }\n\n get audit() {\n return { getLog: () => this.auditLogger.getLog() };\n }\n\n status(): {\n balance: number;\n budget: number;\n limitPerTx: number;\n pending: Transaction[];\n recent: Transaction[];\n isSetup: boolean;\n mobileMode: boolean;\n } {\n const cfg = loadConfig(this.home);\n try {\n const wallet = this.budgetManager.getBalance();\n const pending = this.txManager.getPending();\n const recent = this.txManager.list().slice(-5);\n return {\n balance: wallet.balance,\n budget: wallet.budget,\n limitPerTx: wallet.limitPerTx,\n pending,\n recent,\n isSetup: true,\n mobileMode: cfg.mobileMode,\n };\n } catch {\n return {\n balance: 0,\n budget: 0,\n limitPerTx: 0,\n pending: [],\n recent: [],\n isSetup: false,\n mobileMode: cfg.mobileMode,\n };\n }\n }\n}\n"],"mappings":"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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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","names":["import_node_crypto","import_node_fs","import_node_path","import_node_crypto","formatCurrency","import_node_os","import_node_crypto","import_node_path","import_node_child_process","import_node_child_process","esc","formatCurrency","parseBody","MAX_BODY","sendJson","sendHtml","TIMEOUT_MS","import_node_http","import_node_crypto","import_node_crypto","import_node_fs","import_node_path","import_node_fs","import_node_path","import_node_fs","import_node_path","import_node_fs","import_node_path","import_node_fs","import_node_path","import_node_http","import_node_crypto","import_node_fs","import_node_path","TIMEOUT_MS","MAX_BODY","parseBody","sendJson","sendHtml","import_node_http","import_node_fs","MAX_BODY","parseBody","sendJson","sendHtml","collectPassphrase","import_node_path","waitForApproval","existsSync","requestBrowserApproval","requestMobileApproval"]}