@wrongstack/core 0.2.0 → 0.3.2

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.
Files changed (57) hide show
  1. package/dist/{agent-bridge-DmBiCipY.d.ts → agent-bridge-C3DUGjSb.d.ts} +1 -1
  2. package/dist/{compactor-DSl2FK7a.d.ts → compactor-DpJBI1YH.d.ts} +8 -2
  3. package/dist/{config-DXrqb41m.d.ts → config-D2qvAxVd.d.ts} +39 -2
  4. package/dist/{context-u0bryklF.d.ts → context-IovtuTf8.d.ts} +2 -0
  5. package/dist/coordination/index.d.ts +11 -11
  6. package/dist/coordination/index.js +307 -245
  7. package/dist/coordination/index.js.map +1 -1
  8. package/dist/defaults/index.d.ts +30 -15
  9. package/dist/defaults/index.js +1077 -479
  10. package/dist/defaults/index.js.map +1 -1
  11. package/dist/{events-B6Q03pTu.d.ts → events-BHIQs4o1.d.ts} +34 -1
  12. package/dist/execution/index.d.ts +17 -14
  13. package/dist/execution/index.js +166 -18
  14. package/dist/execution/index.js.map +1 -1
  15. package/dist/extension/index.d.ts +9 -0
  16. package/dist/extension/index.js +241 -0
  17. package/dist/extension/index.js.map +1 -0
  18. package/dist/{plugin-CoYYZKdn.d.ts → index-hWNybrNZ.d.ts} +368 -11
  19. package/dist/index.d.ts +76 -26
  20. package/dist/index.js +1595 -748
  21. package/dist/index.js.map +1 -1
  22. package/dist/infrastructure/index.d.ts +6 -6
  23. package/dist/infrastructure/index.js +191 -20
  24. package/dist/infrastructure/index.js.map +1 -1
  25. package/dist/kernel/index.d.ts +12 -9
  26. package/dist/kernel/index.js +73 -7
  27. package/dist/kernel/index.js.map +1 -1
  28. package/dist/{mcp-servers-BA1Ofmfj.d.ts → mcp-servers-C2OopXOn.d.ts} +21 -5
  29. package/dist/models/index.d.ts +2 -2
  30. package/dist/models/index.js +24 -1
  31. package/dist/models/index.js.map +1 -1
  32. package/dist/{multi-agent-BDfkxL5C.d.ts → multi-agent-B9a6sflH.d.ts} +2 -2
  33. package/dist/observability/index.d.ts +2 -2
  34. package/dist/{path-resolver-Crkt8wTQ.d.ts → path-resolver--59rCou3.d.ts} +2 -2
  35. package/dist/provider-runner-B39miKRw.d.ts +36 -0
  36. package/dist/sdd/index.d.ts +3 -3
  37. package/dist/{secret-scrubber-3TLUkiCV.d.ts → secret-scrubber-CgG2tV2B.d.ts} +1 -1
  38. package/dist/{secret-scrubber-CwYliRWd.d.ts → secret-scrubber-Cuy5afaQ.d.ts} +1 -1
  39. package/dist/security/index.d.ts +3 -3
  40. package/dist/security/index.js +24 -1
  41. package/dist/security/index.js.map +1 -1
  42. package/dist/{selector-BRqzvugb.d.ts → selector-wT2fv9Fg.d.ts} +1 -1
  43. package/dist/{session-reader-C3x96CDR.d.ts → session-reader-CcPi4BQ8.d.ts} +1 -1
  44. package/dist/{skill-Bx8jxznf.d.ts → skill-C_7znCIC.d.ts} +2 -2
  45. package/dist/storage/index.d.ts +7 -6
  46. package/dist/storage/index.js +204 -14
  47. package/dist/storage/index.js.map +1 -1
  48. package/dist/{renderer-0A2ZEtca.d.ts → system-prompt-Dk1qm8ey.d.ts} +30 -2
  49. package/dist/{tool-executor-CYdZdtno.d.ts → tool-executor-HsBLGRaA.d.ts} +5 -5
  50. package/dist/types/index.d.ts +16 -16
  51. package/dist/types/index.js +230 -10
  52. package/dist/types/index.js.map +1 -1
  53. package/dist/utils/index.d.ts +23 -2
  54. package/dist/utils/index.js +117 -2
  55. package/dist/utils/index.js.map +1 -1
  56. package/package.json +5 -1
  57. package/dist/system-prompt-CG9jU5-5.d.ts +0 -31
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/security/secret-scrubber.ts","../../src/types/secret-vault.ts","../../src/security/secret-vault.ts","../../src/utils/atomic-write.ts","../../src/utils/glob-match.ts","../../src/utils/safe-json.ts","../../src/security/permission-policy.ts"],"names":["path","fsp","randomBytes","stat","fs3"],"mappings":"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","file":"index.js","sourcesContent":["import type { SecretScrubber } from '../types/secret-scrubber.js';\n\ninterface Pattern {\n type: string;\n regex: RegExp;\n}\n\nconst PATTERNS: Pattern[] = [\n // Anchored at the start where possible so partial matches inside larger\n // strings don't trigger false positives.\n {\n type: 'anthropic_key',\n regex: /(?<![A-Za-z0-9])sk-ant-api\\d+-[A-Za-z0-9_-]{20,}(?![A-Za-z0-9])/g,\n },\n { type: 'openai_key', regex: /(?<![A-Za-z0-9])sk-(?:proj-)?[A-Za-z0-9_-]{20,}(?![A-Za-z0-9])/g },\n { type: 'github_pat', regex: /(?<![A-Za-z0-9])ghp_[A-Za-z0-9]{36,}(?![A-Za-z0-9])/g },\n { type: 'github_pat_v2', regex: /(?<![A-Za-z0-9])github_pat_[A-Za-z0-9_]{50,}(?![A-Za-z0-9])/g },\n { type: 'aws_access_key', regex: /(?<![A-Za-z0-9])AKIA[0-9A-Z]{16}(?![A-Za-z0-9])/g },\n { type: 'gcp_key', regex: /(?<![A-Za-z0-9])AIza[0-9A-Za-z_-]{35}(?![A-Za-z0-9])/g },\n { type: 'slack_token', regex: /(?<![A-Za-z0-9-])xox[abpos]-[A-Za-z0-9-]{10,}(?![A-Za-z0-9-])/g },\n {\n type: 'stripe_key',\n regex: /(?<![A-Za-z0-9])sk_(?:live|test)_[A-Za-z0-9]{24,}(?![A-Za-z0-9])/g,\n },\n { type: 'twilio_sid', regex: /(?<![A-Za-z0-9])AC[a-f0-9]{32}(?![A-Za-z0-9])/g },\n {\n type: 'jwt',\n // Anchored: look for literal \"eyJ\" which is unambiguous for JWT header\n regex:\n /(?<![A-Za-z0-9/+=])eyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}(?![A-Za-z0-9/+=])/g,\n },\n {\n type: 'private_key',\n // Anchored: start must be BEGIN, end must be END with no extra dashes after END\n regex:\n /(?:^|\\n)-----BEGIN (?:RSA|EC|OPENSSH|DSA|PGP)? ?PRIVATE KEY-----[\\s\\S]*?-----END[^-]*-----(?:\\n|$)/g,\n },\n { type: 'mongodb_uri', regex: /mongodb(?:\\+srv)?:\\/\\/[^\\s\"'`]+/g },\n { type: 'postgres_uri', regex: /postgres(?:ql)?:\\/\\/[^\\s\"'`]+/g },\n { type: 'mysql_uri', regex: /mysql:\\/\\/[^\\s\"'`]+/g },\n { type: 'redis_uri', regex: /redis:\\/\\/[^\\s\"'`]+/g },\n {\n type: 'bearer_token',\n regex: /(?<![A-Za-z0-9_.~+/-])Bearer\\s+[A-Za-z0-9._~+/-]{20,}=*(?![A-Za-z0-9_.~+/-])/g,\n },\n {\n type: 'high_entropy_env',\n // Value-side word boundary + length gate to avoid matching short random strings\n regex:\n /\\b([A-Z_]{4,}(?:KEY|TOKEN|SECRET|PASSWORD|PWD))\\s*[:=]\\s*['\"]?([A-Za-z0-9_/+=-]{20,})['\"]?(?!\\s*[A-Za-z_]{4,}(?:KEY|TOKEN|SECRET|PASSWORD|PWD))/g,\n },\n];\n\n/**\n * Per-chunk cap. The `high_entropy_env` and `bearer_token` patterns use\n * negative lookahead/lookbehind which are theoretically backtracking-prone\n * on adversarial input. Real scrub() inputs (LLM responses, tool outputs)\n * are typically much smaller, but defense-in-depth: split very long inputs\n * into smaller chunks and scrub each independently.\n */\nconst SCRUB_CHUNK_BYTES = 64 * 1024;\n\nexport class DefaultSecretScrubber implements SecretScrubber {\n scrub(text: string): string {\n if (!text) return text;\n // For oversize inputs, scrub in fixed chunks. We split on newlines\n // where possible so secrets that span a few hundred bytes still get\n // matched within a single chunk; only inputs above ~64 KB risk a\n // boundary cutting a secret in half, and those are uncommon.\n if (text.length <= SCRUB_CHUNK_BYTES) {\n return this.scrubOne(text);\n }\n const out: string[] = [];\n let i = 0;\n while (i < text.length) {\n let end = Math.min(i + SCRUB_CHUNK_BYTES, text.length);\n // Try to break on a newline near the boundary so we don't cut secrets.\n if (end < text.length) {\n const nl = text.lastIndexOf('\\n', end);\n if (nl > i + SCRUB_CHUNK_BYTES / 2) end = nl + 1;\n }\n out.push(this.scrubOne(text.slice(i, end)));\n i = end;\n }\n return out.join('');\n }\n\n private scrubOne(text: string): string {\n let out = text;\n for (const p of PATTERNS) {\n out = out.replace(p.regex, (_match, group1, group2) => {\n if (p.type === 'high_entropy_env' && group1 && group2) {\n return `${group1}=[REDACTED:${p.type}]`;\n }\n return `[REDACTED:${p.type}]`;\n });\n }\n return out;\n }\n\n scrubObject<T>(obj: T): T {\n const seen = new WeakSet();\n const visit = (v: unknown): unknown => {\n if (typeof v === 'string') return this.scrub(v);\n if (v === null || typeof v !== 'object') return v;\n if (seen.has(v as object)) return v;\n seen.add(v as object);\n if (Array.isArray(v)) return v.map(visit);\n const out: Record<string, unknown> = {};\n for (const [k, val] of Object.entries(v as Record<string, unknown>)) {\n out[k] = visit(val);\n }\n return out;\n };\n return visit(obj) as T;\n }\n}\n","/**\n * SecretVault encrypts secrets-at-rest in config files. The wire format is\n * `enc:v1:<base64-iv>:<base64-tag>:<base64-ciphertext>`. Plaintext strings\n * (those that do not match this prefix) are passed through unchanged so that\n * existing configs and env-var-derived values keep working.\n *\n * The vault is intentionally NOT designed to defeat a determined local\n * attacker who can read both the config file and the key file — that level\n * of secrecy needs the OS keychain. The goal is to keep keys from being\n * visible in screen shares, accidental log captures, and `cat config.json`\n * over someone's shoulder.\n */\nexport interface SecretVault {\n encrypt(plaintext: string): string;\n decrypt(value: string): string;\n isEncrypted(value: string): boolean;\n}\n\nexport const ENCRYPTED_PREFIX = 'enc:v1:';\n","import { createCipheriv, createDecipheriv, randomBytes } from 'node:crypto';\nimport * as fs from 'node:fs';\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { SecretVault } from '../types/secret-vault.js';\nimport { ENCRYPTED_PREFIX } from '../types/secret-vault.js';\n\nexport interface SecretVaultOptions {\n /** Absolute path to the key file. Created with mode 0o600 if missing. */\n keyFile: string;\n}\n\nconst KEY_BYTES = 32;\nconst IV_BYTES = 12;\nconst TAG_BYTES = 16;\nconst ALGO = 'aes-256-gcm';\n\n/**\n * Default vault: AES-256-GCM with a key stored at `keyFile` (mode 0o600).\n * The key is loaded lazily on first encrypt/decrypt; if it does not exist,\n * a fresh one is generated. Decryption of plaintext values is a no-op so\n * legacy configs continue to work.\n */\nexport class DefaultSecretVault implements SecretVault {\n private readonly keyFile: string;\n private key?: Buffer;\n\n constructor(opts: SecretVaultOptions) {\n this.keyFile = opts.keyFile;\n }\n\n isEncrypted(value: string): boolean {\n return typeof value === 'string' && value.startsWith(ENCRYPTED_PREFIX);\n }\n\n encrypt(plaintext: string): string {\n if (this.isEncrypted(plaintext)) return plaintext;\n const key = this.loadOrCreateKey();\n const iv = randomBytes(IV_BYTES);\n const cipher = createCipheriv(ALGO, key, iv);\n const ct = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);\n const tag = cipher.getAuthTag();\n return `${ENCRYPTED_PREFIX}${iv.toString('base64')}:${tag.toString('base64')}:${ct.toString('base64')}`;\n }\n\n decrypt(value: string): string {\n if (!this.isEncrypted(value)) return value;\n const rest = value.slice(ENCRYPTED_PREFIX.length);\n const parts = rest.split(':');\n if (parts.length !== 3) {\n throw new Error('SecretVault: malformed encrypted value');\n }\n const [ivB64, tagB64, ctB64] = parts as [string, string, string];\n const iv = Buffer.from(ivB64, 'base64');\n const tag = Buffer.from(tagB64, 'base64');\n const ct = Buffer.from(ctB64, 'base64');\n if (iv.length !== IV_BYTES) throw new Error('SecretVault: bad IV length');\n if (tag.length !== TAG_BYTES) throw new Error('SecretVault: bad tag length');\n const key = this.loadOrCreateKey();\n const decipher = createDecipheriv(ALGO, key, iv);\n decipher.setAuthTag(tag);\n const pt = Buffer.concat([decipher.update(ct), decipher.final()]);\n return pt.toString('utf8');\n }\n\n private loadOrCreateKey(): Buffer {\n if (this.key) return this.key;\n try {\n const buf = fs.readFileSync(this.keyFile);\n if (buf.length !== KEY_BYTES) {\n throw new Error(`SecretVault: key file ${this.keyFile} has wrong size`);\n }\n this.key = buf;\n return this.key;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;\n }\n // Create a fresh key. Use sync APIs so the constructor-free getter\n // remains synchronous from the caller's perspective.\n fs.mkdirSync(path.dirname(this.keyFile), { recursive: true });\n const key = randomBytes(KEY_BYTES);\n // Use exclusive-create flag 'wx' to prevent races: if two processes race\n // to create the key file, only one succeeds and the loser gets EEXIST.\n try {\n fs.writeFileSync(this.keyFile, key, { mode: 0o600, flag: 'wx' });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'EEXIST') throw err;\n // Another process won the race — re-read what they wrote.\n const buf = fs.readFileSync(this.keyFile);\n if (buf.length !== KEY_BYTES) {\n throw new Error(`SecretVault: key file ${this.keyFile} has wrong size`);\n }\n this.key = buf;\n return this.key;\n }\n this.key = key;\n return key;\n }\n}\n\n/**\n * Walk a Config-shaped object and decrypt any apiKey-like fields in place,\n * returning a new object. Used by the config loader so the rest of the\n * system never has to know about the wire format.\n */\nexport function decryptConfigSecrets<T>(cfg: T, vault: SecretVault): T {\n // A single corrupted/malformed encrypted field should not kill the entire\n // config load. Swallow per-field decrypt errors (zero the field so callers\n // see \"missing key\" instead of holding ciphertext) and surface a warning.\n return walk(cfg, vault, (v, key) => {\n try {\n return vault.decrypt(v);\n } catch (err) {\n console.warn(\n `[secret-vault] Failed to decrypt \"${key}\":`,\n err instanceof Error ? err.message : err,\n );\n return '';\n }\n });\n}\n\nexport function encryptConfigSecrets<T>(cfg: T, vault: SecretVault): T {\n return walk(cfg, vault, (v) => vault.encrypt(v));\n}\n\nfunction walk<T>(node: T, vault: SecretVault, transform: (s: string, key: string) => string): T {\n if (node === null || node === undefined) return node;\n if (typeof node !== 'object') return node;\n if (Array.isArray(node)) {\n return node.map((item) => walk(item, vault, transform)) as unknown as T;\n }\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(node as Record<string, unknown>)) {\n if (typeof v === 'string' && isSecretField(k)) {\n out[k] = transform(v, k);\n } else if (typeof v === 'object' && v !== null) {\n out[k] = walk(v, vault, transform);\n } else {\n out[k] = v;\n }\n }\n return out as T;\n}\n\n/**\n * A key is treated as secret-bearing if its name (case-insensitive) contains\n * one of these tokens. Captures common variants like `apiKey`, `authToken`,\n * `refreshToken`, `sessionKey`, `password`, `client_secret`, `bearer`, etc.\n * Use a named field with `isSecret: false` annotation if you must opt out —\n * see `NON_SECRET_OVERRIDES` below.\n */\nconst SECRET_KEY_PATTERN =\n /(?:apikey|api_key|authtoken|auth_token|bearer|secret|password|passwd|pwd|refreshtoken|refresh_token|sessionkey|session_key|access[_-]?token|private[_-]?key)/i;\n\n// Field names that contain the literal substring \"key\" but are not secrets.\n// Keep this list short; the substring rule itself is intentionally narrow.\nconst NON_SECRET_OVERRIDES = new Set(['publickey', 'public_key']);\n\nfunction isSecretField(name: string): boolean {\n const lc = name.toLowerCase();\n if (NON_SECRET_OVERRIDES.has(lc)) return false;\n return SECRET_KEY_PATTERN.test(lc);\n}\n\n/**\n * Re-write `~/.wrongstack/config.json` (or any path) with all secret-bearing\n * fields encrypted. Used by the `wstack auth` subcommand.\n */\nexport async function rewriteConfigEncrypted(\n configPath: string,\n vault: SecretVault,\n patch?: Record<string, unknown>,\n): Promise<void> {\n let current: Record<string, unknown> = {};\n try {\n const raw = await fsp.readFile(configPath, 'utf8');\n current = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n // start from empty\n }\n const merged = deepMerge(current, patch ?? {});\n const encrypted = encryptConfigSecrets(merged, vault);\n await fsp.mkdir(path.dirname(configPath), { recursive: true });\n await fsp.writeFile(configPath, JSON.stringify(encrypted, null, 2), { mode: 0o600 });\n try {\n await fsp.chmod(configPath, 0o600);\n } catch {\n // best-effort on Windows\n }\n}\n\n/**\n * Scan a config file on disk for plaintext secret-bearing fields and\n * rewrite the file with them encrypted in place. Returns a count of how\n * many fields were migrated. Idempotent — calling on a fully-encrypted\n * file is a no-op and writes nothing. Used by the CLI on every boot so\n * users who had plaintext keys before the vault landed are upgraded\n * transparently.\n */\nexport async function migratePlaintextSecrets(\n configPath: string,\n vault: SecretVault,\n): Promise<{ migrated: number; file: string }> {\n let raw: string;\n try {\n raw = await fsp.readFile(configPath, 'utf8');\n } catch {\n return { migrated: 0, file: configPath };\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return { migrated: 0, file: configPath };\n }\n const counter = { n: 0 };\n const migrated = walkCount(parsed, vault, counter);\n if (counter.n === 0) return { migrated: 0, file: configPath };\n await fsp.writeFile(configPath, JSON.stringify(migrated, null, 2), { mode: 0o600 });\n try {\n await fsp.chmod(configPath, 0o600);\n } catch {\n // best-effort on Windows\n }\n return { migrated: counter.n, file: configPath };\n}\n\nfunction walkCount<T>(node: T, vault: SecretVault, counter: { n: number }): T {\n if (node === null || node === undefined) return node;\n if (typeof node !== 'object') return node;\n if (Array.isArray(node)) {\n return node.map((item) => walkCount(item, vault, counter)) as unknown as T;\n }\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(node as Record<string, unknown>)) {\n if (typeof v === 'string' && isSecretField(k) && !vault.isEncrypted(v) && v.length > 0) {\n out[k] = vault.encrypt(v);\n counter.n++;\n } else if (typeof v === 'object' && v !== null) {\n out[k] = walkCount(v, vault, counter);\n } else {\n out[k] = v;\n }\n }\n return out as T;\n}\n\n/** Keys that, when written into a plain object, can poison the prototype\n * chain. We never want user config to carry these. */\nconst FORBIDDEN_PROTO_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\nfunction deepMerge<T extends Record<string, unknown>>(a: T, b: Record<string, unknown>): T {\n const out: Record<string, unknown> = { ...a };\n for (const [k, v] of Object.entries(b)) {\n if (FORBIDDEN_PROTO_KEYS.has(k)) continue;\n const existing = out[k];\n if (\n v !== null &&\n typeof v === 'object' &&\n !Array.isArray(v) &&\n existing !== null &&\n typeof existing === 'object' &&\n !Array.isArray(existing)\n ) {\n out[k] = deepMerge(existing as Record<string, unknown>, v as Record<string, unknown>);\n } else {\n out[k] = v;\n }\n }\n return out as T;\n}\n","import { randomBytes } from 'node:crypto';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\nexport interface AtomicWriteOptions {\n mode?: number;\n encoding?: BufferEncoding;\n}\n\nexport async function atomicWrite(\n targetPath: string,\n content: string | Uint8Array,\n opts: AtomicWriteOptions = {},\n): Promise<void> {\n const dir = path.dirname(targetPath);\n await fs.mkdir(dir, { recursive: true });\n const tmp = path.join(dir, `.${path.basename(targetPath)}.${randomBytes(6).toString('hex')}.tmp`);\n\n // Write content to tmp first; 'wx' ensures exclusive creation (fails if\n // tmp already exists — extremely unlikely with 6-byte random suffix).\n try {\n if (typeof content === 'string') {\n await fs.writeFile(tmp, content, { flag: 'wx', encoding: opts.encoding ?? 'utf8' });\n } else {\n await fs.writeFile(tmp, content, { flag: 'wx' });\n }\n try {\n const fh = await fs.open(tmp, 'r+');\n try {\n await fh.sync();\n } finally {\n await fh.close();\n }\n } catch {\n // fsync best-effort\n }\n // Now safely read mode from target (if it exists) and apply to tmp before rename.\n // Prefer opts.mode for new files; for existing files preserve their mode.\n let mode: number | undefined;\n try {\n const stat = await fs.stat(targetPath);\n mode = stat.mode & 0o777;\n } catch {\n mode = opts.mode;\n }\n if (mode !== undefined) {\n await fs.chmod(tmp, mode);\n }\n await fs.rename(tmp, targetPath);\n } catch (err) {\n try {\n await fs.unlink(tmp);\n } catch {\n // ignore cleanup error\n }\n throw err;\n }\n}\n\nexport async function ensureDir(dir: string): Promise<void> {\n await fs.mkdir(dir, { recursive: true });\n}\n","/**\n * Minimal glob matcher for trust patterns.\n * Supports: *, **, ?, character classes [abc], [a-z], negation [!...] or [^...].\n *\n * Compiled regexes are cached so repeated calls with the same pattern\n * avoid recompilation overhead.\n */\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.+^${}()|\\\\]/g, '\\\\$&');\n}\n\n// Module-level cache to avoid recompiling the same pattern on every call.\n// LRU-ish eviction keeps unbounded growth in check for long-running processes.\nconst COMPILED_GLOB_CACHE = new Map<string, RegExp>();\nconst CACHE_MAX_SIZE = 2000;\n\nfunction getCachedGlob(pattern: string): RegExp {\n const cached = COMPILED_GLOB_CACHE.get(pattern);\n if (cached) return cached;\n if (COMPILED_GLOB_CACHE.size >= CACHE_MAX_SIZE) {\n // Evict oldest 25% when at capacity\n const keys = [...COMPILED_GLOB_CACHE.keys()];\n for (let i = 0; i < Math.floor(CACHE_MAX_SIZE / 4); i++) {\n COMPILED_GLOB_CACHE.delete(keys[i]!);\n }\n }\n const re = compileGlob(pattern);\n COMPILED_GLOB_CACHE.set(pattern, re);\n return re;\n}\n\nexport function compileGlob(pattern: string): RegExp {\n let i = 0;\n let re = '^';\n while (i < pattern.length) {\n const c = pattern[i];\n if (c === '*') {\n if (pattern[i + 1] === '*') {\n // ** matches any number of chars including /\n re += '.*';\n i += 2;\n // Skip trailing slash so '**/x' matches 'x'\n if (pattern[i] === '/') i++;\n } else {\n // single * matches any chars except /\n re += '[^/]*';\n i++;\n }\n } else if (c === '?') {\n re += '[^/]';\n i++;\n } else if (c === '[') {\n let cls = '[';\n i++;\n if (pattern[i] === '!' || pattern[i] === '^') {\n cls += '^';\n i++;\n }\n while (i < pattern.length && pattern[i] !== ']') {\n const ch = pattern[i] ?? '';\n // Inside a regex class, only `]`, `\\`, and `^`/`-` at boundaries need\n // escaping. We've already consumed the leading `^`; the rest are\n // literal. Escape `\\` defensively and pass the rest through verbatim\n // so ranges like `a-z` continue to work.\n if (ch === '\\\\') {\n cls += '\\\\\\\\';\n } else if (ch === ']' || ch === '^') {\n cls += `\\\\${ch}`;\n } else {\n cls += ch;\n }\n i++;\n }\n cls += ']';\n re += cls;\n i++; // skip closing ]\n } else {\n re += escapeRegex(c ?? '');\n i++;\n }\n }\n re += '$';\n return new RegExp(re);\n}\n\nexport function matchGlob(pattern: string, input: string): boolean {\n return getCachedGlob(pattern).test(input);\n}\n\nexport function matchAny(patterns: string[], input: string): boolean {\n return patterns.some((p) => matchGlob(p, input));\n}\n","export interface SafeParseResult<T> {\n ok: boolean;\n value?: T;\n error?: string;\n}\n\nexport function safeParse<T = unknown>(input: string, maxBytes = 5_000_000): SafeParseResult<T> {\n if (input.length > maxBytes) {\n return { ok: false, error: `Input exceeds limit (${maxBytes} bytes)` };\n }\n try {\n return { ok: true, value: JSON.parse(input) as T };\n } catch (err) {\n return {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\nexport function safeStringify(value: unknown, pretty = false): string {\n const seen = new WeakSet();\n const replacer = (_k: string, v: unknown): unknown => {\n if (typeof v === 'bigint') return v.toString();\n if (v instanceof Error) {\n return { name: v.name, message: v.message, stack: v.stack };\n }\n if (typeof v === 'object' && v !== null) {\n if (seen.has(v as object)) return '[Circular]';\n seen.add(v as object);\n }\n return v;\n };\n try {\n return JSON.stringify(value, replacer, pretty ? 2 : undefined) ?? 'null';\n } catch (err) {\n return JSON.stringify({\n __serialization_error: err instanceof Error ? err.message : String(err),\n });\n }\n}\n\n/**\n * Attempt to parse JSON5-style input and return a valid JSON string.\n * Handles trailing commas, single-line comments, and unquoted keys\n * that are common in provider output.\n *\n * Returns the sanitized string if it parses successfully as JSON,\n * or `null` if the input cannot be made valid. Callers use this to\n * decide whether to proceed with the parsed result or fall back to\n * raw handling.\n */\nexport function sanitizeJsonString(s: string): string | null {\n let out = s.trim();\n\n // Stage 1: strip single-line comments (// to end of line) that appear\n // outside of string values. This is a heuristic: comments inside strings\n // are preserved because we only strip // when preceded by a char that\n // strongly suggests we're not in a string (quote count modulo 2 is even).\n out = stripSingleLineComments(out);\n\n // Stage 2: strip trailing commas before } or ]\n out = out.replace(/,(\\s*[}\\]])/g, '$1');\n\n // Stage 3: attempt full parse; return null if it fails so callers can\n // distinguish \"already valid JSON\" from \"unrecoverable\".\n try {\n JSON.parse(out);\n return out;\n } catch {\n return null; // stripped but still not valid JSON; caller handles it\n }\n}\n\nfunction stripSingleLineComments(s: string): string {\n let inString = false;\n const chars: string[] = [];\n let i = 0;\n while (i < s.length) {\n const c = s[i]!;\n if (c === '\"' && (i === 0 || s[i - 1] !== '\\\\')) {\n inString = !inString;\n chars.push(c);\n } else if (c === '/' && s[i + 1] === '/' && !inString) {\n // skip to end of line\n while (i < s.length && s[i] !== '\\n') i++;\n } else {\n chars.push(c);\n }\n i++;\n }\n return chars.join('');\n}\n","import * as fs from 'node:fs/promises';\nimport type { Context } from '../core/context.js';\nimport type { InputReader } from '../types/input-reader.js';\nimport type { PermissionDecision, PermissionPolicy, TrustPolicy } from '../types/permission.js';\nimport type { Tool } from '../types/tool.js';\nimport { atomicWrite } from '../utils/atomic-write.js';\nimport { matchAny, matchGlob } from '../utils/glob-match.js';\nimport { safeParse } from '../utils/safe-json.js';\n\nexport interface PermissionPolicyOptions {\n trustFile: string;\n yolo?: boolean;\n promptDelegate?: (\n tool: Tool,\n input: unknown,\n suggestedPattern: string,\n ) => Promise<'yes' | 'no' | 'always' | 'deny'>;\n inputReader?: InputReader;\n}\n\nexport class DefaultPermissionPolicy implements PermissionPolicy {\n private policy: TrustPolicy = {};\n private loaded = false;\n private readonly trustFile: string;\n private readonly yolo: boolean;\n private readonly promptDelegate?: PermissionPolicyOptions['promptDelegate'];\n\n constructor(opts: PermissionPolicyOptions) {\n this.trustFile = opts.trustFile;\n this.yolo = opts.yolo ?? false;\n this.promptDelegate = opts.promptDelegate;\n }\n\n async reload(): Promise<void> {\n try {\n const raw = await fs.readFile(this.trustFile, 'utf8');\n const parsed = safeParse<TrustPolicy>(raw);\n if (parsed.ok && parsed.value) this.policy = parsed.value;\n } catch {\n this.policy = {};\n }\n this.loaded = true;\n }\n\n async evaluate(tool: Tool, input: unknown, _ctx: Context): Promise<PermissionDecision> {\n if (!this.loaded) await this.reload();\n\n // 1. Tool-namespace matching (mcp__server__* etc.)\n const namespaceEntry = this.findNamespaceEntry(tool.name);\n\n // 2. Tool-name entry\n const entry = this.policy[tool.name] ?? namespaceEntry;\n\n // 3. Compute subject (the thing being matched)\n const subject = this.subjectFor(tool.name, input, tool.subjectKey);\n\n // 4. Deny — absolute\n if (entry?.deny && subject && matchAny(entry.deny, subject)) {\n return { permission: 'deny', source: 'deny', reason: 'matched deny pattern' };\n }\n if (tool.permission === 'deny') {\n return { permission: 'deny', source: 'default', reason: 'tool default deny' };\n }\n\n // 5. Allow\n if (entry?.allow && subject && matchAny(entry.allow, subject)) {\n return { permission: 'auto', source: 'trust', reason: 'matched allow pattern' };\n }\n if (entry?.auto) {\n return { permission: 'auto', source: 'trust' };\n }\n\n // 6. YOLO\n if (this.yolo) {\n return { permission: 'auto', source: 'yolo' };\n }\n\n // 7. Tool default\n if (tool.permission === 'auto') {\n return { permission: 'auto', source: 'default' };\n }\n\n // 8. Confirm — delegate to prompt\n if (this.promptDelegate) {\n const decision = await this.promptDelegate(tool, input, subject ?? tool.name);\n if (decision === 'always') {\n await this.trust({ tool: tool.name, pattern: subject ?? tool.name });\n return { permission: 'auto', source: 'user', reason: 'user always-allowed' };\n }\n if (decision === 'deny') {\n return { permission: 'deny', source: 'user', reason: 'user denied' };\n }\n return { permission: decision === 'yes' ? 'auto' : 'deny', source: 'user' };\n }\n return { permission: 'confirm', source: 'default' };\n }\n\n async trust(rule: { tool: string; pattern: string }): Promise<void> {\n if (!this.loaded) await this.reload();\n const entry = this.policy[rule.tool] ?? {};\n entry.allow = Array.from(new Set([...(entry.allow ?? []), rule.pattern]));\n this.policy[rule.tool] = entry;\n try {\n await atomicWrite(this.trustFile, JSON.stringify(this.policy, null, 2));\n } catch (err) {\n // Revert in-memory state since disk write failed\n const existing = this.policy[rule.tool];\n if (existing?.allow) {\n const idx = existing.allow.indexOf(rule.pattern);\n if (idx !== -1) existing.allow.splice(idx, 1);\n }\n throw err;\n }\n }\n\n private subjectFor(toolName: string, input: unknown, subjectKey?: string): string | undefined {\n if (!input || typeof input !== 'object') return undefined;\n const obj = input as Record<string, unknown>;\n\n // Glob metacharacters are dangerous: a crafted subject like \"**\" or \"foo/**/bar\"\n // can match too broadly in the allow/deny pattern match. Escape them so the\n // matching is done on the literal string.\n const globChars = /[*?\\[\\]]/g;\n const escapeGlob = (s: string) => s.replace(globChars, (c) => `\\\\${c}`);\n const normalizePath = (s: string) => escapeGlob(s.replace(/\\\\/g, '/'));\n\n // 1. Explicit subjectKey on the tool wins — eliminates the cross-tool\n // collision where e.g. an HTTP tool's `path` field meant \"request\n // path\" but was matched against filesystem-path trust rules.\n if (subjectKey) {\n const v = obj[subjectKey];\n if (typeof v === 'string') {\n // Heuristic: path-like keys get backslash normalization for glob\n // matching on Windows; everything else is treated as opaque.\n return subjectKey === 'path' || subjectKey === 'file' || subjectKey === 'files'\n ? normalizePath(v)\n : escapeGlob(v);\n }\n // subjectKey was declared but the runtime value isn't a string —\n // fall through to the legacy heuristic so the policy still has a\n // chance to match on something sensible.\n }\n\n // 2. Legacy heuristic — preserved for tools that haven't migrated.\n if (toolName === 'bash' && typeof obj.command === 'string') {\n return escapeGlob(obj.command);\n }\n if (typeof obj.path === 'string') {\n return normalizePath(obj.path);\n }\n if (typeof obj.url === 'string') {\n return escapeGlob(obj.url);\n }\n if (typeof obj.name === 'string') {\n return escapeGlob(obj.name);\n }\n return undefined;\n }\n\n private findNamespaceEntry(toolName: string): TrustPolicy[string] | undefined {\n for (const key of Object.keys(this.policy)) {\n if (key.includes('*') && matchGlob(key, toolName)) {\n return this.policy[key];\n }\n }\n return undefined;\n }\n}\n\n/**\n * Auto-approving PermissionPolicy used for subagents. Subagents run\n * non-interactively under a director — they cannot answer permission\n * prompts, so a non-YOLO policy on the leader would silently hang the\n * delegated run on the first sensitive tool call. The user already\n * authorized the delegation when they invoked the leader; subagents\n * inherit that authorization automatically.\n *\n * Tool defaults of `permission: 'deny'` are still honored (this is a\n * subagent capability override, not a deny-bypass).\n */\nexport class AutoApprovePermissionPolicy implements PermissionPolicy {\n async evaluate(tool: Tool): Promise<PermissionDecision> {\n if (tool.permission === 'deny') {\n return { permission: 'deny', source: 'default', reason: 'tool default deny' };\n }\n return { permission: 'auto', source: 'yolo' };\n }\n async trust(): Promise<void> {\n // No-op: subagent permission decisions are ephemeral and must not\n // pollute the leader's persisted trust file.\n }\n async reload(): Promise<void> {\n // No-op: nothing to load.\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/security/secret-scrubber.ts","../../src/types/secret-vault.ts","../../src/security/secret-vault.ts","../../src/utils/atomic-write.ts","../../src/utils/glob-match.ts","../../src/utils/safe-json.ts","../../src/security/permission-policy.ts"],"names":["path","fsp","randomBytes","stat","fs3"],"mappings":"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","file":"index.js","sourcesContent":["import type { SecretScrubber } from '../types/secret-scrubber.js';\n\ninterface Pattern {\n type: string;\n regex: RegExp;\n}\n\nconst PATTERNS: Pattern[] = [\n // Anchored at the start where possible so partial matches inside larger\n // strings don't trigger false positives.\n {\n type: 'anthropic_key',\n regex: /(?<![A-Za-z0-9])sk-ant-api\\d+-[A-Za-z0-9_-]{20,}(?![A-Za-z0-9])/g,\n },\n { type: 'openai_key', regex: /(?<![A-Za-z0-9])sk-(?:proj-)?[A-Za-z0-9_-]{20,}(?![A-Za-z0-9])/g },\n { type: 'github_pat', regex: /(?<![A-Za-z0-9])ghp_[A-Za-z0-9]{36,}(?![A-Za-z0-9])/g },\n { type: 'github_pat_v2', regex: /(?<![A-Za-z0-9])github_pat_[A-Za-z0-9_]{50,}(?![A-Za-z0-9])/g },\n { type: 'aws_access_key', regex: /(?<![A-Za-z0-9])AKIA[0-9A-Z]{16}(?![A-Za-z0-9])/g },\n { type: 'gcp_key', regex: /(?<![A-Za-z0-9])AIza[0-9A-Za-z_-]{35}(?![A-Za-z0-9])/g },\n { type: 'slack_token', regex: /(?<![A-Za-z0-9-])xox[abpos]-[A-Za-z0-9-]{10,}(?![A-Za-z0-9-])/g },\n {\n type: 'stripe_key',\n regex: /(?<![A-Za-z0-9])sk_(?:live|test)_[A-Za-z0-9]{24,}(?![A-Za-z0-9])/g,\n },\n { type: 'twilio_sid', regex: /(?<![A-Za-z0-9])AC[a-f0-9]{32}(?![A-Za-z0-9])/g },\n {\n type: 'jwt',\n // Anchored: look for literal \"eyJ\" which is unambiguous for JWT header\n regex:\n /(?<![A-Za-z0-9/+=])eyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}(?![A-Za-z0-9/+=])/g,\n },\n {\n type: 'private_key',\n // Anchored: start must be BEGIN, end must be END with no extra dashes after END\n regex:\n /(?:^|\\n)-----BEGIN (?:RSA|EC|OPENSSH|DSA|PGP)? ?PRIVATE KEY-----[\\s\\S]*?-----END[^-]*-----(?:\\n|$)/g,\n },\n { type: 'mongodb_uri', regex: /mongodb(?:\\+srv)?:\\/\\/[^\\s\"'`]+/g },\n { type: 'postgres_uri', regex: /postgres(?:ql)?:\\/\\/[^\\s\"'`]+/g },\n { type: 'mysql_uri', regex: /mysql:\\/\\/[^\\s\"'`]+/g },\n { type: 'redis_uri', regex: /redis:\\/\\/[^\\s\"'`]+/g },\n {\n type: 'bearer_token',\n regex: /(?<![A-Za-z0-9_.~+/-])Bearer\\s+[A-Za-z0-9._~+/-]{20,}=*(?![A-Za-z0-9_.~+/-])/g,\n },\n {\n type: 'high_entropy_env',\n // Value-side word boundary + length gate to avoid matching short random strings\n regex:\n /\\b([A-Z_]{4,}(?:KEY|TOKEN|SECRET|PASSWORD|PWD))\\s*[:=]\\s*['\"]?([A-Za-z0-9_/+=-]{20,})['\"]?(?!\\s*[A-Za-z_]{4,}(?:KEY|TOKEN|SECRET|PASSWORD|PWD))/g,\n },\n];\n\n/**\n * Per-chunk cap. The `high_entropy_env` and `bearer_token` patterns use\n * negative lookahead/lookbehind which are theoretically backtracking-prone\n * on adversarial input. Real scrub() inputs (LLM responses, tool outputs)\n * are typically much smaller, but defense-in-depth: split very long inputs\n * into smaller chunks and scrub each independently.\n */\nconst SCRUB_CHUNK_BYTES = 64 * 1024;\n\nexport class DefaultSecretScrubber implements SecretScrubber {\n scrub(text: string): string {\n if (!text) return text;\n // For oversize inputs, scrub in fixed chunks. We split on newlines\n // where possible so secrets that span a few hundred bytes still get\n // matched within a single chunk; only inputs above ~64 KB risk a\n // boundary cutting a secret in half, and those are uncommon.\n if (text.length <= SCRUB_CHUNK_BYTES) {\n return this.scrubOne(text);\n }\n const out: string[] = [];\n let i = 0;\n while (i < text.length) {\n let end = Math.min(i + SCRUB_CHUNK_BYTES, text.length);\n // Try to break on a newline near the boundary so we don't cut secrets.\n if (end < text.length) {\n const nl = text.lastIndexOf('\\n', end);\n if (nl > i + SCRUB_CHUNK_BYTES / 2) end = nl + 1;\n }\n out.push(this.scrubOne(text.slice(i, end)));\n i = end;\n }\n return out.join('');\n }\n\n private scrubOne(text: string): string {\n let out = text;\n for (const p of PATTERNS) {\n out = out.replace(p.regex, (_match, group1, group2) => {\n if (p.type === 'high_entropy_env' && group1 && group2) {\n return `${group1}=[REDACTED:${p.type}]`;\n }\n return `[REDACTED:${p.type}]`;\n });\n }\n return out;\n }\n\n scrubObject<T>(obj: T): T {\n const seen = new WeakSet();\n const visit = (v: unknown): unknown => {\n if (typeof v === 'string') return this.scrub(v);\n if (v === null || typeof v !== 'object') return v;\n if (seen.has(v as object)) return v;\n seen.add(v as object);\n if (Array.isArray(v)) return v.map(visit);\n const out: Record<string, unknown> = {};\n for (const [k, val] of Object.entries(v as Record<string, unknown>)) {\n out[k] = visit(val);\n }\n return out;\n };\n return visit(obj) as T;\n }\n}\n","/**\n * SecretVault encrypts secrets-at-rest in config files. The wire format is\n * `enc:v1:<base64-iv>:<base64-tag>:<base64-ciphertext>`. Plaintext strings\n * (those that do not match this prefix) are passed through unchanged so that\n * existing configs and env-var-derived values keep working.\n *\n * The vault is intentionally NOT designed to defeat a determined local\n * attacker who can read both the config file and the key file — that level\n * of secrecy needs the OS keychain. The goal is to keep keys from being\n * visible in screen shares, accidental log captures, and `cat config.json`\n * over someone's shoulder.\n */\nexport interface SecretVault {\n encrypt(plaintext: string): string;\n decrypt(value: string): string;\n isEncrypted(value: string): boolean;\n}\n\nexport const ENCRYPTED_PREFIX = 'enc:v1:';\n","import { createCipheriv, createDecipheriv, randomBytes } from 'node:crypto';\nimport * as fs from 'node:fs';\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { SecretVault } from '../types/secret-vault.js';\nimport { ENCRYPTED_PREFIX } from '../types/secret-vault.js';\n\nexport interface SecretVaultOptions {\n /** Absolute path to the key file. Created with mode 0o600 if missing. */\n keyFile: string;\n}\n\nconst KEY_BYTES = 32;\nconst IV_BYTES = 12;\nconst TAG_BYTES = 16;\nconst ALGO = 'aes-256-gcm';\n\n/**\n * Default vault: AES-256-GCM with a key stored at `keyFile` (mode 0o600).\n * The key is loaded lazily on first encrypt/decrypt; if it does not exist,\n * a fresh one is generated. Decryption of plaintext values is a no-op so\n * legacy configs continue to work.\n */\nexport class DefaultSecretVault implements SecretVault {\n private readonly keyFile: string;\n private key?: Buffer;\n\n constructor(opts: SecretVaultOptions) {\n this.keyFile = opts.keyFile;\n }\n\n isEncrypted(value: string): boolean {\n return typeof value === 'string' && value.startsWith(ENCRYPTED_PREFIX);\n }\n\n encrypt(plaintext: string): string {\n if (this.isEncrypted(plaintext)) return plaintext;\n const key = this.loadOrCreateKey();\n const iv = randomBytes(IV_BYTES);\n const cipher = createCipheriv(ALGO, key, iv);\n const ct = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);\n const tag = cipher.getAuthTag();\n return `${ENCRYPTED_PREFIX}${iv.toString('base64')}:${tag.toString('base64')}:${ct.toString('base64')}`;\n }\n\n decrypt(value: string): string {\n if (!this.isEncrypted(value)) return value;\n const rest = value.slice(ENCRYPTED_PREFIX.length);\n const parts = rest.split(':');\n if (parts.length !== 3) {\n throw new Error('SecretVault: malformed encrypted value');\n }\n const [ivB64, tagB64, ctB64] = parts as [string, string, string];\n const iv = Buffer.from(ivB64, 'base64');\n const tag = Buffer.from(tagB64, 'base64');\n const ct = Buffer.from(ctB64, 'base64');\n if (iv.length !== IV_BYTES) throw new Error('SecretVault: bad IV length');\n if (tag.length !== TAG_BYTES) throw new Error('SecretVault: bad tag length');\n const key = this.loadOrCreateKey();\n const decipher = createDecipheriv(ALGO, key, iv);\n decipher.setAuthTag(tag);\n const pt = Buffer.concat([decipher.update(ct), decipher.final()]);\n return pt.toString('utf8');\n }\n\n private loadOrCreateKey(): Buffer {\n if (this.key) return this.key;\n try {\n const buf = fs.readFileSync(this.keyFile);\n if (buf.length !== KEY_BYTES) {\n throw new Error(`SecretVault: key file ${this.keyFile} has wrong size`);\n }\n this.key = buf;\n return this.key;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;\n }\n // Create a fresh key. Use sync APIs so the constructor-free getter\n // remains synchronous from the caller's perspective.\n fs.mkdirSync(path.dirname(this.keyFile), { recursive: true });\n const key = randomBytes(KEY_BYTES);\n // Use exclusive-create flag 'wx' to prevent races: if two processes race\n // to create the key file, only one succeeds and the loser gets EEXIST.\n try {\n fs.writeFileSync(this.keyFile, key, { mode: 0o600, flag: 'wx' });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'EEXIST') throw err;\n // Another process won the race — re-read what they wrote.\n const buf = fs.readFileSync(this.keyFile);\n if (buf.length !== KEY_BYTES) {\n throw new Error(`SecretVault: key file ${this.keyFile} has wrong size`);\n }\n this.key = buf;\n return this.key;\n }\n this.key = key;\n return key;\n }\n}\n\n/**\n * Walk a Config-shaped object and decrypt any apiKey-like fields in place,\n * returning a new object. Used by the config loader so the rest of the\n * system never has to know about the wire format.\n */\nexport function decryptConfigSecrets<T>(cfg: T, vault: SecretVault): T {\n // A single corrupted/malformed encrypted field should not kill the entire\n // config load. Swallow per-field decrypt errors (zero the field so callers\n // see \"missing key\" instead of holding ciphertext) and surface a warning.\n return walk(cfg, vault, (v, key) => {\n try {\n return vault.decrypt(v);\n } catch (err) {\n console.warn(\n `[secret-vault] Failed to decrypt \"${key}\":`,\n err instanceof Error ? err.message : err,\n );\n return '';\n }\n });\n}\n\nexport function encryptConfigSecrets<T>(cfg: T, vault: SecretVault): T {\n return walk(cfg, vault, (v) => vault.encrypt(v));\n}\n\nfunction walk<T>(node: T, vault: SecretVault, transform: (s: string, key: string) => string): T {\n if (node === null || node === undefined) return node;\n if (typeof node !== 'object') return node;\n if (Array.isArray(node)) {\n return node.map((item) => walk(item, vault, transform)) as unknown as T;\n }\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(node as Record<string, unknown>)) {\n if (typeof v === 'string' && isSecretField(k)) {\n out[k] = transform(v, k);\n } else if (typeof v === 'object' && v !== null) {\n out[k] = walk(v, vault, transform);\n } else {\n out[k] = v;\n }\n }\n return out as T;\n}\n\n/**\n * A key is treated as secret-bearing if its name (case-insensitive) contains\n * one of these tokens. Captures common variants like `apiKey`, `authToken`,\n * `refreshToken`, `sessionKey`, `password`, `client_secret`, `bearer`, etc.\n * Use a named field with `isSecret: false` annotation if you must opt out —\n * see `NON_SECRET_OVERRIDES` below.\n */\nconst SECRET_KEY_PATTERN =\n /(?:apikey|api_key|authtoken|auth_token|bearer|secret|password|passwd|pwd|refreshtoken|refresh_token|sessionkey|session_key|access[_-]?token|private[_-]?key)/i;\n\n// Field names that contain the literal substring \"key\" but are not secrets.\n// Keep this list short; the substring rule itself is intentionally narrow.\nconst NON_SECRET_OVERRIDES = new Set(['publickey', 'public_key']);\n\nfunction isSecretField(name: string): boolean {\n const lc = name.toLowerCase();\n if (NON_SECRET_OVERRIDES.has(lc)) return false;\n return SECRET_KEY_PATTERN.test(lc);\n}\n\n/**\n * Re-write `~/.wrongstack/config.json` (or any path) with all secret-bearing\n * fields encrypted. Used by the `wstack auth` subcommand.\n */\nexport async function rewriteConfigEncrypted(\n configPath: string,\n vault: SecretVault,\n patch?: Record<string, unknown>,\n): Promise<void> {\n let current: Record<string, unknown> = {};\n try {\n const raw = await fsp.readFile(configPath, 'utf8');\n current = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n // start from empty\n }\n const merged = deepMerge(current, patch ?? {});\n const encrypted = encryptConfigSecrets(merged, vault);\n await fsp.mkdir(path.dirname(configPath), { recursive: true });\n await fsp.writeFile(configPath, JSON.stringify(encrypted, null, 2), { mode: 0o600 });\n try {\n await fsp.chmod(configPath, 0o600);\n } catch {\n // best-effort on Windows\n }\n}\n\n/**\n * Scan a config file on disk for plaintext secret-bearing fields and\n * rewrite the file with them encrypted in place. Returns a count of how\n * many fields were migrated. Idempotent — calling on a fully-encrypted\n * file is a no-op and writes nothing. Used by the CLI on every boot so\n * users who had plaintext keys before the vault landed are upgraded\n * transparently.\n */\nexport async function migratePlaintextSecrets(\n configPath: string,\n vault: SecretVault,\n): Promise<{ migrated: number; file: string }> {\n let raw: string;\n try {\n raw = await fsp.readFile(configPath, 'utf8');\n } catch {\n return { migrated: 0, file: configPath };\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return { migrated: 0, file: configPath };\n }\n const counter = { n: 0 };\n const migrated = walkCount(parsed, vault, counter);\n if (counter.n === 0) return { migrated: 0, file: configPath };\n await fsp.writeFile(configPath, JSON.stringify(migrated, null, 2), { mode: 0o600 });\n try {\n await fsp.chmod(configPath, 0o600);\n } catch {\n // best-effort on Windows\n }\n return { migrated: counter.n, file: configPath };\n}\n\nfunction walkCount<T>(node: T, vault: SecretVault, counter: { n: number }): T {\n if (node === null || node === undefined) return node;\n if (typeof node !== 'object') return node;\n if (Array.isArray(node)) {\n return node.map((item) => walkCount(item, vault, counter)) as unknown as T;\n }\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(node as Record<string, unknown>)) {\n if (typeof v === 'string' && isSecretField(k) && !vault.isEncrypted(v) && v.length > 0) {\n out[k] = vault.encrypt(v);\n counter.n++;\n } else if (typeof v === 'object' && v !== null) {\n out[k] = walkCount(v, vault, counter);\n } else {\n out[k] = v;\n }\n }\n return out as T;\n}\n\n/** Keys that, when written into a plain object, can poison the prototype\n * chain. We never want user config to carry these. */\nconst FORBIDDEN_PROTO_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\nfunction deepMerge<T extends Record<string, unknown>>(a: T, b: Record<string, unknown>): T {\n const out: Record<string, unknown> = { ...a };\n for (const [k, v] of Object.entries(b)) {\n if (FORBIDDEN_PROTO_KEYS.has(k)) continue;\n const existing = out[k];\n if (\n v !== null &&\n typeof v === 'object' &&\n !Array.isArray(v) &&\n existing !== null &&\n typeof existing === 'object' &&\n !Array.isArray(existing)\n ) {\n out[k] = deepMerge(existing as Record<string, unknown>, v as Record<string, unknown>);\n } else {\n out[k] = v;\n }\n }\n return out as T;\n}\n","import { randomBytes } from 'node:crypto';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\nexport interface AtomicWriteOptions {\n mode?: number;\n encoding?: BufferEncoding;\n}\n\nexport async function atomicWrite(\n targetPath: string,\n content: string | Uint8Array,\n opts: AtomicWriteOptions = {},\n): Promise<void> {\n const dir = path.dirname(targetPath);\n await fs.mkdir(dir, { recursive: true });\n const tmp = path.join(dir, `.${path.basename(targetPath)}.${randomBytes(6).toString('hex')}.tmp`);\n\n // Write content to tmp first; 'wx' ensures exclusive creation (fails if\n // tmp already exists — extremely unlikely with 6-byte random suffix).\n try {\n if (typeof content === 'string') {\n await fs.writeFile(tmp, content, { flag: 'wx', encoding: opts.encoding ?? 'utf8' });\n } else {\n await fs.writeFile(tmp, content, { flag: 'wx' });\n }\n try {\n const fh = await fs.open(tmp, 'r+');\n try {\n await fh.sync();\n } finally {\n await fh.close();\n }\n } catch {\n // fsync best-effort\n }\n // Now safely read mode from target (if it exists) and apply to tmp before rename.\n // Prefer opts.mode for new files; for existing files preserve their mode.\n let mode: number | undefined;\n try {\n const stat = await fs.stat(targetPath);\n mode = stat.mode & 0o777;\n } catch {\n mode = opts.mode;\n }\n if (mode !== undefined) {\n await fs.chmod(tmp, mode);\n }\n await renameWithRetry(tmp, targetPath);\n } catch (err) {\n try {\n await fs.unlink(tmp);\n } catch {\n // ignore cleanup error\n }\n throw err;\n }\n}\n\nexport async function ensureDir(dir: string): Promise<void> {\n await fs.mkdir(dir, { recursive: true });\n}\n\n// On Windows, fs.rename over an existing file can fail with EPERM/EBUSY/EACCES\n// when antivirus, file indexers, editor file watchers, or a concurrent writer\n// briefly hold a handle on the destination. These are transient — retry with a\n// short backoff before giving up. POSIX renames are atomic and won't hit this.\nconst TRANSIENT_RENAME_CODES = new Set(['EPERM', 'EBUSY', 'EACCES', 'ENOTEMPTY']);\n\nasync function renameWithRetry(from: string, to: string): Promise<void> {\n if (process.platform !== 'win32') {\n await fs.rename(from, to);\n return;\n }\n const delays = [10, 25, 60, 120, 250];\n let lastErr: unknown;\n for (let i = 0; i <= delays.length; i++) {\n try {\n await fs.rename(from, to);\n return;\n } catch (err) {\n lastErr = err;\n const code = (err as NodeJS.ErrnoException)?.code;\n if (!code || !TRANSIENT_RENAME_CODES.has(code) || i === delays.length) {\n throw err;\n }\n await new Promise((resolve) => setTimeout(resolve, delays[i]));\n }\n }\n throw lastErr;\n}\n","/**\n * Minimal glob matcher for trust patterns.\n * Supports: *, **, ?, character classes [abc], [a-z], negation [!...] or [^...].\n *\n * Compiled regexes are cached so repeated calls with the same pattern\n * avoid recompilation overhead.\n */\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.+^${}()|\\\\]/g, '\\\\$&');\n}\n\n// Module-level cache to avoid recompiling the same pattern on every call.\n// LRU-ish eviction keeps unbounded growth in check for long-running processes.\nconst COMPILED_GLOB_CACHE = new Map<string, RegExp>();\nconst CACHE_MAX_SIZE = 2000;\n\nfunction getCachedGlob(pattern: string): RegExp {\n const cached = COMPILED_GLOB_CACHE.get(pattern);\n if (cached) return cached;\n if (COMPILED_GLOB_CACHE.size >= CACHE_MAX_SIZE) {\n // Evict oldest 25% when at capacity\n const keys = [...COMPILED_GLOB_CACHE.keys()];\n for (let i = 0; i < Math.floor(CACHE_MAX_SIZE / 4); i++) {\n COMPILED_GLOB_CACHE.delete(keys[i]!);\n }\n }\n const re = compileGlob(pattern);\n COMPILED_GLOB_CACHE.set(pattern, re);\n return re;\n}\n\nexport function compileGlob(pattern: string): RegExp {\n let i = 0;\n let re = '^';\n while (i < pattern.length) {\n const c = pattern[i];\n if (c === '*') {\n if (pattern[i + 1] === '*') {\n // ** matches any number of chars including /\n re += '.*';\n i += 2;\n // Skip trailing slash so '**/x' matches 'x'\n if (pattern[i] === '/') i++;\n } else {\n // single * matches any chars except /\n re += '[^/]*';\n i++;\n }\n } else if (c === '?') {\n re += '[^/]';\n i++;\n } else if (c === '[') {\n let cls = '[';\n i++;\n if (pattern[i] === '!' || pattern[i] === '^') {\n cls += '^';\n i++;\n }\n while (i < pattern.length && pattern[i] !== ']') {\n const ch = pattern[i] ?? '';\n // Inside a regex class, only `]`, `\\`, and `^`/`-` at boundaries need\n // escaping. We've already consumed the leading `^`; the rest are\n // literal. Escape `\\` defensively and pass the rest through verbatim\n // so ranges like `a-z` continue to work.\n if (ch === '\\\\') {\n cls += '\\\\\\\\';\n } else if (ch === ']' || ch === '^') {\n cls += `\\\\${ch}`;\n } else {\n cls += ch;\n }\n i++;\n }\n cls += ']';\n re += cls;\n i++; // skip closing ]\n } else {\n re += escapeRegex(c ?? '');\n i++;\n }\n }\n re += '$';\n return new RegExp(re);\n}\n\nexport function matchGlob(pattern: string, input: string): boolean {\n return getCachedGlob(pattern).test(input);\n}\n\nexport function matchAny(patterns: string[], input: string): boolean {\n return patterns.some((p) => matchGlob(p, input));\n}\n","export interface SafeParseResult<T> {\n ok: boolean;\n value?: T;\n error?: string;\n}\n\nexport function safeParse<T = unknown>(input: string, maxBytes = 5_000_000): SafeParseResult<T> {\n if (input.length > maxBytes) {\n return { ok: false, error: `Input exceeds limit (${maxBytes} bytes)` };\n }\n try {\n return { ok: true, value: JSON.parse(input) as T };\n } catch (err) {\n return {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\nexport function safeStringify(value: unknown, pretty = false): string {\n const seen = new WeakSet();\n const replacer = (_k: string, v: unknown): unknown => {\n if (typeof v === 'bigint') return v.toString();\n if (v instanceof Error) {\n return { name: v.name, message: v.message, stack: v.stack };\n }\n if (typeof v === 'object' && v !== null) {\n if (seen.has(v as object)) return '[Circular]';\n seen.add(v as object);\n }\n return v;\n };\n try {\n return JSON.stringify(value, replacer, pretty ? 2 : undefined) ?? 'null';\n } catch (err) {\n return JSON.stringify({\n __serialization_error: err instanceof Error ? err.message : String(err),\n });\n }\n}\n\n/**\n * Attempt to parse JSON5-style input and return a valid JSON string.\n * Handles trailing commas, single-line comments, and unquoted keys\n * that are common in provider output.\n *\n * Returns the sanitized string if it parses successfully as JSON,\n * or `null` if the input cannot be made valid. Callers use this to\n * decide whether to proceed with the parsed result or fall back to\n * raw handling.\n */\nexport function sanitizeJsonString(s: string): string | null {\n let out = s.trim();\n\n // Stage 1: strip single-line comments (// to end of line) that appear\n // outside of string values. This is a heuristic: comments inside strings\n // are preserved because we only strip // when preceded by a char that\n // strongly suggests we're not in a string (quote count modulo 2 is even).\n out = stripSingleLineComments(out);\n\n // Stage 2: strip trailing commas before } or ]\n out = out.replace(/,(\\s*[}\\]])/g, '$1');\n\n // Stage 3: attempt full parse; return null if it fails so callers can\n // distinguish \"already valid JSON\" from \"unrecoverable\".\n try {\n JSON.parse(out);\n return out;\n } catch {\n return null; // stripped but still not valid JSON; caller handles it\n }\n}\n\nfunction stripSingleLineComments(s: string): string {\n let inString = false;\n const chars: string[] = [];\n let i = 0;\n while (i < s.length) {\n const c = s[i]!;\n if (c === '\"' && (i === 0 || s[i - 1] !== '\\\\')) {\n inString = !inString;\n chars.push(c);\n } else if (c === '/' && s[i + 1] === '/' && !inString) {\n // skip to end of line\n while (i < s.length && s[i] !== '\\n') i++;\n } else {\n chars.push(c);\n }\n i++;\n }\n return chars.join('');\n}\n","import * as fs from 'node:fs/promises';\nimport type { Context } from '../core/context.js';\nimport type { InputReader } from '../types/input-reader.js';\nimport type { PermissionDecision, PermissionPolicy, TrustPolicy } from '../types/permission.js';\nimport type { Tool } from '../types/tool.js';\nimport { atomicWrite } from '../utils/atomic-write.js';\nimport { matchAny, matchGlob } from '../utils/glob-match.js';\nimport { safeParse } from '../utils/safe-json.js';\n\nexport interface PermissionPolicyOptions {\n trustFile: string;\n yolo?: boolean;\n promptDelegate?: (\n tool: Tool,\n input: unknown,\n suggestedPattern: string,\n ) => Promise<'yes' | 'no' | 'always' | 'deny'>;\n inputReader?: InputReader;\n}\n\nexport class DefaultPermissionPolicy implements PermissionPolicy {\n private policy: TrustPolicy = {};\n private loaded = false;\n private readonly trustFile: string;\n private readonly yolo: boolean;\n private readonly promptDelegate?: PermissionPolicyOptions['promptDelegate'];\n\n constructor(opts: PermissionPolicyOptions) {\n this.trustFile = opts.trustFile;\n this.yolo = opts.yolo ?? false;\n this.promptDelegate = opts.promptDelegate;\n }\n\n async reload(): Promise<void> {\n try {\n const raw = await fs.readFile(this.trustFile, 'utf8');\n const parsed = safeParse<TrustPolicy>(raw);\n if (parsed.ok && parsed.value) this.policy = parsed.value;\n } catch {\n this.policy = {};\n }\n this.loaded = true;\n }\n\n async evaluate(tool: Tool, input: unknown, _ctx: Context): Promise<PermissionDecision> {\n if (!this.loaded) await this.reload();\n\n // 1. Tool-namespace matching (mcp__server__* etc.)\n const namespaceEntry = this.findNamespaceEntry(tool.name);\n\n // 2. Tool-name entry\n const entry = this.policy[tool.name] ?? namespaceEntry;\n\n // 3. Compute subject (the thing being matched)\n const subject = this.subjectFor(tool.name, input, tool.subjectKey);\n\n // 4. Deny — absolute\n if (entry?.deny && subject && matchAny(entry.deny, subject)) {\n return { permission: 'deny', source: 'deny', reason: 'matched deny pattern' };\n }\n if (tool.permission === 'deny') {\n return { permission: 'deny', source: 'default', reason: 'tool default deny' };\n }\n\n // 5. Allow\n if (entry?.allow && subject && matchAny(entry.allow, subject)) {\n return { permission: 'auto', source: 'trust', reason: 'matched allow pattern' };\n }\n if (entry?.auto) {\n return { permission: 'auto', source: 'trust' };\n }\n\n // 6. YOLO\n if (this.yolo) {\n return { permission: 'auto', source: 'yolo' };\n }\n\n // 7. Tool default\n if (tool.permission === 'auto') {\n return { permission: 'auto', source: 'default' };\n }\n\n // 8. Confirm — delegate to prompt\n if (this.promptDelegate) {\n const decision = await this.promptDelegate(tool, input, subject ?? tool.name);\n if (decision === 'always') {\n await this.trust({ tool: tool.name, pattern: subject ?? tool.name });\n return { permission: 'auto', source: 'user', reason: 'user always-allowed' };\n }\n if (decision === 'deny') {\n return { permission: 'deny', source: 'user', reason: 'user denied' };\n }\n return { permission: decision === 'yes' ? 'auto' : 'deny', source: 'user' };\n }\n return { permission: 'confirm', source: 'default' };\n }\n\n async trust(rule: { tool: string; pattern: string }): Promise<void> {\n if (!this.loaded) await this.reload();\n const entry = this.policy[rule.tool] ?? {};\n entry.allow = Array.from(new Set([...(entry.allow ?? []), rule.pattern]));\n this.policy[rule.tool] = entry;\n try {\n await atomicWrite(this.trustFile, JSON.stringify(this.policy, null, 2));\n } catch (err) {\n // Revert in-memory state since disk write failed\n const existing = this.policy[rule.tool];\n if (existing?.allow) {\n const idx = existing.allow.indexOf(rule.pattern);\n if (idx !== -1) existing.allow.splice(idx, 1);\n }\n throw err;\n }\n }\n\n private subjectFor(toolName: string, input: unknown, subjectKey?: string): string | undefined {\n if (!input || typeof input !== 'object') return undefined;\n const obj = input as Record<string, unknown>;\n\n // Glob metacharacters are dangerous: a crafted subject like \"**\" or \"foo/**/bar\"\n // can match too broadly in the allow/deny pattern match. Escape them so the\n // matching is done on the literal string.\n const globChars = /[*?\\[\\]]/g;\n const escapeGlob = (s: string) => s.replace(globChars, (c) => `\\\\${c}`);\n const normalizePath = (s: string) => escapeGlob(s.replace(/\\\\/g, '/'));\n\n // 1. Explicit subjectKey on the tool wins — eliminates the cross-tool\n // collision where e.g. an HTTP tool's `path` field meant \"request\n // path\" but was matched against filesystem-path trust rules.\n if (subjectKey) {\n const v = obj[subjectKey];\n if (typeof v === 'string') {\n // Heuristic: path-like keys get backslash normalization for glob\n // matching on Windows; everything else is treated as opaque.\n return subjectKey === 'path' || subjectKey === 'file' || subjectKey === 'files'\n ? normalizePath(v)\n : escapeGlob(v);\n }\n // subjectKey was declared but the runtime value isn't a string —\n // fall through to the legacy heuristic so the policy still has a\n // chance to match on something sensible.\n }\n\n // 2. Legacy heuristic — preserved for tools that haven't migrated.\n if (toolName === 'bash' && typeof obj.command === 'string') {\n return escapeGlob(obj.command);\n }\n if (typeof obj.path === 'string') {\n return normalizePath(obj.path);\n }\n if (typeof obj.url === 'string') {\n return escapeGlob(obj.url);\n }\n if (typeof obj.name === 'string') {\n return escapeGlob(obj.name);\n }\n return undefined;\n }\n\n private findNamespaceEntry(toolName: string): TrustPolicy[string] | undefined {\n for (const key of Object.keys(this.policy)) {\n if (key.includes('*') && matchGlob(key, toolName)) {\n return this.policy[key];\n }\n }\n return undefined;\n }\n}\n\n/**\n * Auto-approving PermissionPolicy used for subagents. Subagents run\n * non-interactively under a director — they cannot answer permission\n * prompts, so a non-YOLO policy on the leader would silently hang the\n * delegated run on the first sensitive tool call. The user already\n * authorized the delegation when they invoked the leader; subagents\n * inherit that authorization automatically.\n *\n * Tool defaults of `permission: 'deny'` are still honored (this is a\n * subagent capability override, not a deny-bypass).\n */\nexport class AutoApprovePermissionPolicy implements PermissionPolicy {\n async evaluate(tool: Tool): Promise<PermissionDecision> {\n if (tool.permission === 'deny') {\n return { permission: 'deny', source: 'default', reason: 'tool default deny' };\n }\n return { permission: 'auto', source: 'yolo' };\n }\n async trust(): Promise<void> {\n // No-op: subagent permission decisions are ephemeral and must not\n // pollute the leader's persisted trust file.\n }\n async reload(): Promise<void> {\n // No-op: nothing to load.\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { M as Message } from './context-u0bryklF.js';
1
+ import { M as Message } from './context-IovtuTf8.js';
2
2
 
3
3
  /**
4
4
  * Result of LLM-driven message importance analysis.
@@ -1,4 +1,4 @@
1
- import { b as ContentBlock, m as SessionEvent, n as SessionMetadata, o as SessionStore } from './context-u0bryklF.js';
1
+ import { b as ContentBlock, m as SessionEvent, n as SessionMetadata, o as SessionStore } from './context-IovtuTf8.js';
2
2
 
3
3
  type AttachmentKind = 'text' | 'image' | 'file';
4
4
  interface AttachmentMeta {
@@ -1,4 +1,4 @@
1
- import { j as Response, a0 as Context, h as ProviderError } from './context-u0bryklF.js';
1
+ import { j as Response, a0 as Context, h as ProviderError } from './context-IovtuTf8.js';
2
2
 
3
3
  type RecoveryDecision = {
4
4
  /**
@@ -69,4 +69,4 @@ interface SkillLoader {
69
69
  readBody(name: string): Promise<string>;
70
70
  }
71
71
 
72
- export type { ErrorHandler as E, RecoveryDecision as R, SkillEntry as S, SkillLoader as a, SkillManifest as b, RetryPolicy as c };
72
+ export type { ErrorHandler as E, RetryPolicy as R, SkillEntry as S, SkillLoader as a, SkillManifest as b, RecoveryDecision as c };
@@ -1,10 +1,10 @@
1
- import { E as EventBus } from '../events-B6Q03pTu.js';
2
- import { o as SessionStore, n as SessionMetadata, q as SessionWriter, k as ResumedSession, S as SessionData, p as SessionSummary, b as ContentBlock, m as SessionEvent, aa as TodoItem, a4 as ConversationState } from '../context-u0bryklF.js';
3
- import { e as AttachmentStore, A as AddAttachmentInput, d as AttachmentRef, a as Attachment } from '../session-reader-C3x96CDR.js';
4
- export { D as DefaultSessionReader } from '../session-reader-C3x96CDR.js';
1
+ import { E as EventBus } from '../events-BHIQs4o1.js';
2
+ import { o as SessionStore, n as SessionMetadata, q as SessionWriter, k as ResumedSession, S as SessionData, p as SessionSummary, b as ContentBlock, m as SessionEvent, aa as TodoItem, a4 as ConversationState } from '../context-IovtuTf8.js';
3
+ import { e as AttachmentStore, A as AddAttachmentInput, d as AttachmentRef, a as Attachment } from '../session-reader-CcPi4BQ8.js';
4
+ export { D as DefaultSessionReader } from '../session-reader-CcPi4BQ8.js';
5
5
  import { b as MemoryStore, a as MemoryScope } from '../memory-CEXuo7sz.js';
6
6
  import { a as WstackPaths } from '../wstack-paths-BGu2INTm.js';
7
- import { b as ConfigStore, C as Config, a as ConfigLoader } from '../config-DXrqb41m.js';
7
+ import { c as ConfigStore, a as Config, b as ConfigLoader } from '../config-D2qvAxVd.js';
8
8
  import { S as SecretVault } from '../secret-vault-DoISxaKO.js';
9
9
  import '../models-registry-Y2xbog0E.js';
10
10
 
@@ -395,6 +395,7 @@ interface TodosCheckpointFile {
395
395
  updatedAt: string;
396
396
  todos: TodoItem[];
397
397
  }
398
+ type TodosCheckpointDetach = () => Promise<void>;
398
399
  /** Read a checkpoint from disk. Returns null when the file doesn't
399
400
  * exist or is corrupt — callers treat both cases as "no prior state".
400
401
  */
@@ -412,7 +413,7 @@ declare function saveTodosCheckpoint(filePath: string, sessionId: string, todos:
412
413
  * marking three items done in the same tool call) coalesces into one
413
414
  * disk hit.
414
415
  */
415
- declare function attachTodosCheckpoint(state: ConversationState, filePath: string, sessionId: string): () => void;
416
+ declare function attachTodosCheckpoint(state: ConversationState, filePath: string, sessionId: string): TodosCheckpointDetach;
416
417
 
417
418
  /**
418
419
  * Plan items are the strategic counterpart to todos. Where `ctx.todos`
@@ -1,7 +1,6 @@
1
1
  import { randomBytes, randomUUID } from 'crypto';
2
2
  import * as fsp from 'fs/promises';
3
3
  import * as path2 from 'path';
4
- import 'fs';
5
4
  import * as os from 'os';
6
5
 
7
6
  // src/storage/session-store.ts
@@ -34,7 +33,7 @@ async function atomicWrite(targetPath, content, opts = {}) {
34
33
  if (mode !== void 0) {
35
34
  await fsp.chmod(tmp, mode);
36
35
  }
37
- await fsp.rename(tmp, targetPath);
36
+ await renameWithRetry(tmp, targetPath);
38
37
  } catch (err) {
39
38
  try {
40
39
  await fsp.unlink(tmp);
@@ -46,6 +45,121 @@ async function atomicWrite(targetPath, content, opts = {}) {
46
45
  async function ensureDir(dir) {
47
46
  await fsp.mkdir(dir, { recursive: true });
48
47
  }
48
+ var TRANSIENT_RENAME_CODES = /* @__PURE__ */ new Set(["EPERM", "EBUSY", "EACCES", "ENOTEMPTY"]);
49
+ async function renameWithRetry(from, to) {
50
+ if (process.platform !== "win32") {
51
+ await fsp.rename(from, to);
52
+ return;
53
+ }
54
+ const delays = [10, 25, 60, 120, 250];
55
+ let lastErr;
56
+ for (let i = 0; i <= delays.length; i++) {
57
+ try {
58
+ await fsp.rename(from, to);
59
+ return;
60
+ } catch (err) {
61
+ lastErr = err;
62
+ const code = err?.code;
63
+ if (!code || !TRANSIENT_RENAME_CODES.has(code) || i === delays.length) {
64
+ throw err;
65
+ }
66
+ await new Promise((resolve) => setTimeout(resolve, delays[i]));
67
+ }
68
+ }
69
+ throw lastErr;
70
+ }
71
+
72
+ // src/utils/message-invariants.ts
73
+ function repairToolUseAdjacency(messages) {
74
+ const removedToolUses = [];
75
+ const removedToolResults = [];
76
+ let removedMessages = 0;
77
+ let changed = false;
78
+ const out = [];
79
+ for (let i = 0; i < messages.length; i++) {
80
+ const original = messages[i];
81
+ let msg = original;
82
+ if (hasToolUse(msg)) {
83
+ const nextIds = toolResultIds(messages[i + 1]);
84
+ const filtered = mapContent(msg, (blocks) => {
85
+ const next = [];
86
+ for (const block of blocks) {
87
+ if (block.type === "tool_use" && !nextIds.has(block.id)) {
88
+ removedToolUses.push(block.id);
89
+ changed = true;
90
+ continue;
91
+ }
92
+ next.push(block);
93
+ }
94
+ return next;
95
+ });
96
+ msg = filtered ?? msg;
97
+ }
98
+ if (hasToolResult(msg)) {
99
+ const allowed = toolUseIds(out[out.length - 1]);
100
+ const filtered = mapContent(msg, (blocks) => {
101
+ const next = [];
102
+ for (const block of blocks) {
103
+ if (block.type === "tool_result" && !allowed.has(block.tool_use_id)) {
104
+ removedToolResults.push(block.tool_use_id);
105
+ changed = true;
106
+ continue;
107
+ }
108
+ next.push(block);
109
+ }
110
+ return next;
111
+ });
112
+ msg = filtered ?? msg;
113
+ }
114
+ if (isEmptyMessage(msg)) {
115
+ removedMessages++;
116
+ changed = true;
117
+ continue;
118
+ }
119
+ out.push(msg);
120
+ }
121
+ return {
122
+ messages: changed ? out : messages,
123
+ report: { changed, removedToolUses, removedToolResults, removedMessages }
124
+ };
125
+ }
126
+ function hasToolUse(msg) {
127
+ return contentBlocks(msg).some((b) => b.type === "tool_use");
128
+ }
129
+ function hasToolResult(msg) {
130
+ return contentBlocks(msg).some((b) => b.type === "tool_result");
131
+ }
132
+ function toolUseIds(msg) {
133
+ const ids = /* @__PURE__ */ new Set();
134
+ if (!msg || msg.role !== "assistant") return ids;
135
+ for (const block of contentBlocks(msg)) {
136
+ if (block.type === "tool_use") ids.add(block.id);
137
+ }
138
+ return ids;
139
+ }
140
+ function toolResultIds(msg) {
141
+ const ids = /* @__PURE__ */ new Set();
142
+ if (!msg || msg.role !== "user") return ids;
143
+ for (const block of contentBlocks(msg)) {
144
+ if (block.type === "tool_result") ids.add(block.tool_use_id);
145
+ }
146
+ return ids;
147
+ }
148
+ function contentBlocks(msg) {
149
+ return msg && Array.isArray(msg.content) ? msg.content : [];
150
+ }
151
+ function mapContent(msg, fn) {
152
+ if (!Array.isArray(msg.content)) return msg;
153
+ const next = fn(msg.content);
154
+ if (next.length === msg.content.length && next.every((b, idx) => b === msg.content[idx])) {
155
+ return msg;
156
+ }
157
+ return { ...msg, content: next };
158
+ }
159
+ function isEmptyMessage(msg) {
160
+ if (typeof msg.content === "string") return msg.content.trim().length === 0;
161
+ return msg.content.length === 0;
162
+ }
49
163
 
50
164
  // src/storage/session-store.ts
51
165
  var DefaultSessionStore = class {
@@ -249,11 +363,17 @@ var DefaultSessionStore = class {
249
363
  if (openToolUses.size > 0) {
250
364
  this.events?.emit("session.damaged", {
251
365
  sessionId,
252
- detail: `${openToolUses.size} tool_use blocks without matching results \u2014 replay truncated`
366
+ detail: `${openToolUses.size} tool_use blocks without matching results - replay repaired`
367
+ });
368
+ }
369
+ const repaired = repairToolUseAdjacency(messages);
370
+ if (repaired.report.changed) {
371
+ this.events?.emit("session.damaged", {
372
+ sessionId,
373
+ detail: `Repaired replay adjacency: removed ${repaired.report.removedToolUses.length} tool_use, ${repaired.report.removedToolResults.length} tool_result, ${repaired.report.removedMessages} empty messages`
253
374
  });
254
- return { messages, usage };
255
375
  }
256
- return { messages, usage };
376
+ return { messages: repaired.messages, usage };
257
377
  }
258
378
  };
259
379
  var FileSessionWriter = class {
@@ -279,6 +399,7 @@ var FileSessionWriter = class {
279
399
  startedAt;
280
400
  meta;
281
401
  closed = false;
402
+ closing = false;
282
403
  manifestFile;
283
404
  summary;
284
405
  tokenIn = 0;
@@ -294,9 +415,7 @@ var FileSessionWriter = class {
294
415
  resumed;
295
416
  appendFailCount = 0;
296
417
  lastAppendWarnAt = 0;
297
- async writeSessionStart() {
298
- if (this.initDone || this.closed) return;
299
- this.initDone = true;
418
+ async writeSessionStartLazy() {
300
419
  const record = `${JSON.stringify({
301
420
  type: this.resumed ? "session_resumed" : "session_start",
302
421
  ts: this.startedAt,
@@ -315,7 +434,8 @@ var FileSessionWriter = class {
315
434
  async append(event) {
316
435
  if (this.closed) return;
317
436
  if (!this.initDone) {
318
- await this.writeSessionStart();
437
+ this.initDone = true;
438
+ await this.writeSessionStartLazy();
319
439
  }
320
440
  this.observeForSummary(event);
321
441
  try {
@@ -356,7 +476,8 @@ var FileSessionWriter = class {
356
476
  }
357
477
  }
358
478
  async close() {
359
- if (this.closed) return;
479
+ if (this.closing) return;
480
+ this.closing = true;
360
481
  this.closed = true;
361
482
  if (this.manifestFile) {
362
483
  try {
@@ -758,6 +879,8 @@ function deepFreeze(obj) {
758
879
  }
759
880
  return Object.freeze(obj);
760
881
  }
882
+
883
+ // src/security/config-secrets.ts
761
884
  function decryptConfigSecrets(cfg, vault) {
762
885
  return walk(cfg, vault, (v, key) => {
763
886
  try {
@@ -797,6 +920,57 @@ function isSecretField(name) {
797
920
  return SECRET_KEY_PATTERN.test(lc);
798
921
  }
799
922
 
923
+ // src/types/context-window.ts
924
+ var DEFAULT_CONTEXT_WINDOW_MODE_ID = "balanced";
925
+ var CONTEXT_WINDOW_MODES = Object.freeze([
926
+ {
927
+ id: "balanced",
928
+ name: "Balanced",
929
+ description: "Default rolling compaction: recent work stays verbatim, old tool output is trimmed.",
930
+ thresholds: { warn: 0.6, soft: 0.75, hard: 0.9 },
931
+ aggressiveOn: "soft",
932
+ preserveK: 10,
933
+ eliseThreshold: 2e3,
934
+ targetLoad: 0.65
935
+ },
936
+ {
937
+ id: "frugal",
938
+ name: "Frugal",
939
+ description: "Token-saver mode: compacts early and keeps a tighter verbatim tail.",
940
+ thresholds: { warn: 0.45, soft: 0.6, hard: 0.75 },
941
+ aggressiveOn: "warn",
942
+ preserveK: 6,
943
+ eliseThreshold: 700,
944
+ targetLoad: 0.5
945
+ },
946
+ {
947
+ id: "deep",
948
+ name: "Deep",
949
+ description: "Long-reasoning mode: delays compaction and keeps more recent turns intact.",
950
+ thresholds: { warn: 0.72, soft: 0.86, hard: 0.96 },
951
+ aggressiveOn: "hard",
952
+ preserveK: 18,
953
+ eliseThreshold: 5e3,
954
+ targetLoad: 0.78
955
+ },
956
+ {
957
+ id: "archival",
958
+ name: "Archival",
959
+ description: "Decision-preserving mode: compacts steadily while keeping summaries prominent.",
960
+ thresholds: { warn: 0.55, soft: 0.7, hard: 0.84 },
961
+ aggressiveOn: "soft",
962
+ preserveK: 8,
963
+ eliseThreshold: 1200,
964
+ targetLoad: 0.58
965
+ }
966
+ ]);
967
+ function listContextWindowModes() {
968
+ return CONTEXT_WINDOW_MODES.map((m) => ({ ...m, thresholds: { ...m.thresholds } }));
969
+ }
970
+ function isContextWindowModeId(id) {
971
+ return CONTEXT_WINDOW_MODES.some((m) => m.id === id);
972
+ }
973
+
800
974
  // src/utils/safe-json.ts
801
975
  function safeParse(input, maxBytes = 5e6) {
802
976
  if (input.length > maxBytes) {
@@ -816,6 +990,7 @@ function safeParse(input, maxBytes = 5e6) {
816
990
  var BEHAVIOR_DEFAULTS = {
817
991
  version: 1,
818
992
  context: {
993
+ mode: DEFAULT_CONTEXT_WINDOW_MODE_ID,
819
994
  warnThreshold: 0.6,
820
995
  softThreshold: 0.75,
821
996
  hardThreshold: 0.9,
@@ -990,6 +1165,10 @@ var DefaultConfigLoader = class {
990
1165
  if (c.warnThreshold >= c.softThreshold || c.softThreshold >= c.hardThreshold) {
991
1166
  throw new Error("Config: context thresholds must satisfy warn < soft < hard");
992
1167
  }
1168
+ if (c.mode !== void 0 && !isContextWindowModeId(c.mode)) {
1169
+ const known = listContextWindowModes().map((m) => m.id).join(", ");
1170
+ throw new Error(`Config: context.mode must be one of: ${known}`);
1171
+ }
993
1172
  }
994
1173
  validateIdentity(cfg) {
995
1174
  if (!cfg.provider) {
@@ -1566,24 +1745,35 @@ async function saveTodosCheckpoint(filePath, sessionId, todos) {
1566
1745
  function attachTodosCheckpoint(state, filePath, sessionId) {
1567
1746
  let timer = null;
1568
1747
  let pending = null;
1748
+ let writeChain = Promise.resolve();
1749
+ const enqueueWrite = (todos) => {
1750
+ writeChain = writeChain.then(() => saveTodosCheckpoint(filePath, sessionId, todos));
1751
+ return writeChain;
1752
+ };
1569
1753
  const flush = () => {
1570
1754
  timer = null;
1571
1755
  if (pending) {
1572
- void saveTodosCheckpoint(filePath, sessionId, pending);
1756
+ const todos = pending;
1573
1757
  pending = null;
1758
+ return enqueueWrite(todos);
1574
1759
  }
1760
+ return writeChain;
1575
1761
  };
1576
1762
  const unsubscribe = state.onChange((change) => {
1577
1763
  if (change.kind !== "todos_replaced") return;
1578
1764
  pending = change.todos;
1579
1765
  if (timer) clearTimeout(timer);
1580
- timer = setTimeout(flush, 150);
1766
+ timer = setTimeout(() => {
1767
+ void flush();
1768
+ }, 150);
1581
1769
  });
1582
- return () => {
1770
+ return async () => {
1583
1771
  unsubscribe();
1584
1772
  if (timer) {
1585
1773
  clearTimeout(timer);
1586
- flush();
1774
+ await flush();
1775
+ } else {
1776
+ await writeChain;
1587
1777
  }
1588
1778
  };
1589
1779
  }