@wrongstack/core 0.3.3 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{config-D2qvAxVd.d.ts → config-DgE3JslD.d.ts} +1 -0
- package/dist/coordination/index.d.ts +4 -2
- package/dist/coordination/index.js +38 -8
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +4 -4
- package/dist/defaults/index.js +94 -11
- package/dist/defaults/index.js.map +1 -1
- package/dist/execution/index.d.ts +3 -3
- package/dist/execution/index.js +45 -1
- package/dist/execution/index.js.map +1 -1
- package/dist/extension/index.d.ts +2 -2
- package/dist/{index-hWNybrNZ.d.ts → index-DedY4Euf.d.ts} +7 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.js +95 -12
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +2 -2
- package/dist/kernel/index.d.ts +1 -1
- package/dist/{mcp-servers-C2OopXOn.d.ts → mcp-servers-zGiC1lQc.d.ts} +1 -1
- package/dist/models/index.js +1 -0
- package/dist/models/index.js.map +1 -1
- package/dist/security/index.js +5 -1
- package/dist/security/index.js.map +1 -1
- package/dist/storage/index.d.ts +1 -1
- package/dist/storage/index.js +41 -1
- package/dist/storage/index.js.map +1 -1
- package/dist/{tool-executor-HsBLGRaA.d.ts → tool-executor-DY0iSXYf.d.ts} +1 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/index.js +43 -2
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +22 -1
- package/dist/utils/index.js +41 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export { D as DefaultLogger, a as DefaultLoggerOptions } from '../logger-BH6AE0W9.js';
|
|
2
2
|
export { D as DefaultPathResolver, a as DefaultTokenCounter } from '../path-resolver--59rCou3.js';
|
|
3
|
-
export { C as ContextManagerAction, a as ContextManagerInput, b as ContextManagerResult, c as ContextManagerToolOptions, d as allServers, e as awsServer, f as blockServer, g as braveSearchServer, h as context7Server, i as contextManagerTool, j as createContextManagerTool, k as everArtServer, l as filesystemServer, m as githubServer, n as googleMapsServer, o as miniMaxVisionServer, s as sentinelServer, p as slackServer, z as zaiVisionServer } from '../mcp-servers-
|
|
3
|
+
export { C as ContextManagerAction, a as ContextManagerInput, b as ContextManagerResult, c as ContextManagerToolOptions, d as allServers, e as awsServer, f as blockServer, g as braveSearchServer, h as context7Server, i as contextManagerTool, j as createContextManagerTool, k as everArtServer, l as filesystemServer, m as githubServer, n as googleMapsServer, o as miniMaxVisionServer, s as sentinelServer, p as slackServer, z as zaiVisionServer } from '../mcp-servers-zGiC1lQc.js';
|
|
4
4
|
import '../logger-BMQgxvdy.js';
|
|
5
5
|
import '../events-BHIQs4o1.js';
|
|
6
6
|
import '../context-IovtuTf8.js';
|
|
7
7
|
import '../models-registry-Y2xbog0E.js';
|
|
8
8
|
import '../path-resolver-CPRj4bFY.js';
|
|
9
9
|
import '../compactor-DpJBI1YH.js';
|
|
10
|
-
import '../config-
|
|
10
|
+
import '../config-DgE3JslD.js';
|
package/dist/kernel/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { T as Token, R as Renderer, S as SystemPromptBuilder } from '../system-p
|
|
|
2
2
|
export { a as BindOptions, C as Container, D as Decorator, F as Factory, b as Middleware, c as MiddlewareHandler, N as NextFn, P as Pipeline, d as PipelineOptions } from '../system-prompt-Dk1qm8ey.js';
|
|
3
3
|
export { E as EventBus, b as EventLogger, c as EventMap, a as EventName, L as Listener } from '../events-BHIQs4o1.js';
|
|
4
4
|
import { a as Compactor } from '../compactor-DpJBI1YH.js';
|
|
5
|
-
import { b as ConfigLoader, c as ConfigStore } from '../config-
|
|
5
|
+
import { b as ConfigLoader, c as ConfigStore } from '../config-DgE3JslD.js';
|
|
6
6
|
import { E as ErrorHandler, R as RetryPolicy, a as SkillLoader } from '../skill-C_7znCIC.js';
|
|
7
7
|
import { I as InputReader } from '../input-reader-E-ffP2ee.js';
|
|
8
8
|
import { L as Logger } from '../logger-BMQgxvdy.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as Compactor } from './compactor-DpJBI1YH.js';
|
|
2
2
|
import { M as Message, u as Tool } from './context-IovtuTf8.js';
|
|
3
|
-
import { M as MCPServerConfig } from './config-
|
|
3
|
+
import { M as MCPServerConfig } from './config-DgE3JslD.js';
|
|
4
4
|
|
|
5
5
|
type ContextManagerAction = 'check' | 'summary' | 'prune' | 'add_note' | 'compact' | 'repair';
|
|
6
6
|
interface ContextManagerInput {
|
package/dist/models/index.js
CHANGED
|
@@ -77,6 +77,7 @@ var FAMILY_BY_NPM = {
|
|
|
77
77
|
"@ai-sdk/xai": "openai-compatible",
|
|
78
78
|
"@ai-sdk/cerebras": "openai-compatible",
|
|
79
79
|
"@ai-sdk/togetherai": "openai-compatible",
|
|
80
|
+
"@ai-sdk/mistral": "openai-compatible",
|
|
80
81
|
"@ai-sdk/perplexity": "openai-compatible",
|
|
81
82
|
"@ai-sdk/deepinfra": "openai-compatible",
|
|
82
83
|
"@openrouter/ai-sdk-provider": "openai-compatible",
|
package/dist/models/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/atomic-write.ts","../../src/models/models-registry.ts","../../src/types/mode.ts","../../src/models/mode-store.ts","../../src/types/blocks.ts","../../src/models/llm-selector.ts"],"names":["path","stat","resolve","fs2","path2","fs3"],"mappings":"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","file":"index.js","sourcesContent":["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","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type {\n ModelsDevPayload,\n ModelsDevProvider,\n ModelsRegistry,\n ResolvedModel,\n ResolvedProvider,\n WireFamily,\n} from '../types/models-registry.js';\nimport { atomicWrite } from '../utils/atomic-write.js';\n\nconst DEFAULT_URL = 'https://models.dev/api.json';\nconst DEFAULT_TTL_SECONDS = 24 * 3600;\n\ninterface CacheEnvelope {\n fetchedAt: string;\n url: string;\n payload: ModelsDevPayload;\n}\n\nexport interface DefaultModelsRegistryOptions {\n cacheFile: string;\n url?: string;\n ttlSeconds?: number;\n fetchImpl?: typeof fetch;\n /** Pre-seeded payload — useful for offline scenarios and tests. */\n seed?: ModelsDevPayload;\n /**\n * Maximum age in seconds for stale cache fallback when network fails.\n * Defaults to 7 days. Set to `Infinity` for full offline resilience\n * (risk: deprecated models, wrong pricing). Set to `0` to disable\n * stale fallback entirely.\n */\n maxStaleAgeSeconds?: number;\n}\n\n/**\n * The npm package each models.dev provider declares determines which wire\n * family WrongStack speaks. Anything not listed falls into `unsupported` and\n * can be enabled by registering a custom provider factory via a plugin.\n */\nconst FAMILY_BY_NPM: Record<string, WireFamily> = {\n '@ai-sdk/anthropic': 'anthropic',\n '@ai-sdk/google-vertex/anthropic': 'anthropic',\n '@ai-sdk/openai': 'openai',\n '@ai-sdk/openai-compatible': 'openai-compatible',\n '@ai-sdk/groq': 'openai-compatible',\n '@ai-sdk/xai': 'openai-compatible',\n '@ai-sdk/cerebras': 'openai-compatible',\n '@ai-sdk/togetherai': 'openai-compatible',\n '@ai-sdk/perplexity': 'openai-compatible',\n '@ai-sdk/deepinfra': 'openai-compatible',\n '@openrouter/ai-sdk-provider': 'openai-compatible',\n 'ai-gateway-provider': 'openai-compatible',\n '@ai-sdk/vercel': 'openai-compatible',\n '@ai-sdk/gateway': 'openai-compatible',\n '@aihubmix/ai-sdk-provider': 'openai-compatible',\n 'venice-ai-sdk-provider': 'openai-compatible',\n '@ai-sdk/google': 'google',\n};\n\nexport function classifyFamily(npm: string | undefined): WireFamily {\n if (!npm) return 'unsupported';\n return FAMILY_BY_NPM[npm] ?? 'unsupported';\n}\n\nexport class DefaultModelsRegistry implements ModelsRegistry {\n private payload?: ModelsDevPayload;\n private fetchedAt?: Date;\n private readonly cacheFile: string;\n private readonly url: string;\n private readonly ttlMs: number;\n private readonly fetchImpl: typeof fetch;\n private readonly seed?: ModelsDevPayload;\n private readonly maxStaleAgeMs: number;\n\n constructor(opts: DefaultModelsRegistryOptions) {\n this.cacheFile = opts.cacheFile;\n this.url = opts.url ?? DEFAULT_URL;\n this.ttlMs = (opts.ttlSeconds ?? DEFAULT_TTL_SECONDS) * 1000;\n this.fetchImpl = opts.fetchImpl ?? fetch;\n this.seed = opts.seed;\n // Default max stale age: 7 days\n const maxStaleSeconds = opts.maxStaleAgeSeconds ?? 7 * 24 * 3600;\n this.maxStaleAgeMs = maxStaleSeconds * 1000;\n }\n\n async load(opts: { force?: boolean } = {}): Promise<ModelsDevPayload> {\n if (this.payload && !opts.force) return this.payload;\n if (this.seed) {\n this.payload = this.seed;\n this.fetchedAt = new Date();\n return this.payload;\n }\n if (!opts.force) {\n const cached = await this.readCache();\n if (cached && this.isFresh(cached.fetchedAt)) {\n this.payload = cached.payload;\n this.fetchedAt = new Date(cached.fetchedAt);\n return cached.payload;\n }\n }\n try {\n return await this.refresh();\n } catch (err) {\n // Network failed — fall back to stale cache if within maxStaleAgeMs.\n const cached = await this.readCache();\n if (cached && this.isWithinMaxStaleAge(cached.fetchedAt)) {\n this.payload = cached.payload;\n this.fetchedAt = new Date(cached.fetchedAt);\n return cached.payload;\n }\n throw err;\n }\n }\n\n async refresh(): Promise<ModelsDevPayload> {\n const res = await this.fetchImpl(this.url, {\n method: 'GET',\n headers: { accept: 'application/json' },\n });\n if (!res.ok) {\n throw new Error(`ModelsRegistry: HTTP ${res.status} fetching ${this.url}`);\n }\n const json = (await res.json()) as ModelsDevPayload;\n this.payload = json;\n this.fetchedAt = new Date();\n const envelope: CacheEnvelope = {\n fetchedAt: this.fetchedAt.toISOString(),\n url: this.url,\n payload: json,\n };\n await atomicWrite(this.cacheFile, JSON.stringify(envelope));\n return json;\n }\n\n async listProviders(): Promise<ResolvedProvider[]> {\n const payload = await this.load();\n return Object.values(payload).map((p) => this.resolveProvider(p));\n }\n\n async getProvider(id: string): Promise<ResolvedProvider | undefined> {\n const payload = await this.load();\n const p = payload[id];\n return p ? this.resolveProvider(p) : undefined;\n }\n\n async getModel(providerId: string, modelId: string): Promise<ResolvedModel | undefined> {\n const provider = await this.getProvider(providerId);\n if (!provider) return undefined;\n const model = provider.models.find((m) => m.id === modelId);\n if (!model) return undefined;\n return {\n providerId,\n modelId,\n capabilities: {\n tools: model.tool_call ?? false,\n vision: Boolean(model.modalities?.input?.includes('image')),\n reasoning: model.reasoning ?? false,\n maxContext: model.limit?.context ?? 0,\n maxOutput: model.limit?.output,\n knowledge: model.knowledge,\n },\n cost: model.cost,\n };\n }\n\n async suggestModel(providerId: string): Promise<string | undefined> {\n const provider = await this.getProvider(providerId);\n if (!provider || provider.models.length === 0) return undefined;\n const ranked = [...provider.models].sort((a, b) => {\n const at = a.release_date ?? a.last_updated ?? '';\n const bt = b.release_date ?? b.last_updated ?? '';\n return bt.localeCompare(at);\n });\n return ranked[0]?.id;\n }\n\n async ageSeconds(): Promise<number> {\n if (!this.fetchedAt) {\n const cached = await this.readCache();\n if (!cached) return Number.POSITIVE_INFINITY;\n return (Date.now() - new Date(cached.fetchedAt).getTime()) / 1000;\n }\n return (Date.now() - this.fetchedAt.getTime()) / 1000;\n }\n\n private resolveProvider(p: ModelsDevProvider): ResolvedProvider {\n return {\n id: p.id,\n name: p.name,\n family: classifyFamily(p.npm),\n apiBase: p.api,\n envVars: p.env ?? [],\n doc: p.doc,\n models: Object.values(p.models ?? {}),\n npm: p.npm,\n };\n }\n\n private isFresh(fetchedAtIso: string): boolean {\n return Date.now() - new Date(fetchedAtIso).getTime() < this.ttlMs;\n }\n\n private isWithinMaxStaleAge(fetchedAtIso: string): boolean {\n return Date.now() - new Date(fetchedAtIso).getTime() < this.maxStaleAgeMs;\n }\n\n private async readCache(): Promise<CacheEnvelope | undefined> {\n try {\n const raw = await fs.readFile(this.cacheFile, 'utf8');\n return JSON.parse(raw) as CacheEnvelope;\n } catch {\n return undefined;\n }\n }\n\n /** Used by `wstack models refresh` to expose where the cache lives. */\n cacheLocation(): string {\n return path.resolve(this.cacheFile);\n }\n}\n","export interface Mode {\n id: string;\n name: string;\n description: string;\n /** Additional prompt text injected into system prompt when mode is active */\n prompt: string;\n /** Tags for tool_search filtering */\n tags?: string[];\n /** Tools that should be prioritized/highlighted when this mode is active */\n toolPreferences?: string[];\n}\n\nexport interface ModeManifest {\n modes: Mode[];\n defaultMode?: string;\n}\n\nexport interface ModeStore {\n getActiveMode(): Promise<Mode | null>;\n setActiveMode(modeId: string | null): Promise<void>;\n listModes(): Promise<Mode[]>;\n getMode(modeId: string): Promise<Mode | null>;\n}\n\nexport interface ModeConfig {\n directory: string;\n}\n\nexport const DEFAULT_MODES: Mode[] = [\n {\n id: 'default',\n name: 'Default',\n description: 'General-purpose coding assistant',\n prompt: '',\n tags: ['general'],\n },\n {\n id: 'code-reviewer',\n name: 'Code Reviewer',\n description: 'Focus on code quality, best practices, and potential bugs',\n prompt: `## Code Reviewer Mode\n\nWhen reviewing code:\n- Look for potential bugs, race conditions, and edge cases\n- Check for security vulnerabilities (SQL injection, XSS, CSRF, etc.)\n- Evaluate error handling completeness\n- Assess code readability and maintainability\n- Check for performance anti-patterns\n- Verify test coverage for critical paths\n- Ensure naming conventions are followed`,\n tags: ['review', 'quality', 'security'],\n toolPreferences: ['read', 'grep', 'git', 'diff', 'test'],\n },\n {\n id: 'code-auditor',\n name: 'Code Auditor',\n description: 'Security-focused code analysis',\n prompt: `## Code Auditor Mode\n\nWhen auditing code for security:\n- Identify injection vulnerabilities (SQL, Command, XSS, LDAP)\n- Check authentication and authorization patterns\n- Look for sensitive data exposure (secrets, PII in logs)\n- Verify cryptographic implementations\n- Check for insecure dependencies or configurations\n- Assess input validation and output encoding\n- Look for timing attacks and information leakage`,\n tags: ['security', 'audit', 'compliance'],\n toolPreferences: ['grep', 'read', 'audit', 'bash'],\n },\n {\n id: 'architect',\n name: 'Software Architect',\n description: 'Design patterns, scalability, and system design',\n prompt: `## Architect Mode\n\nWhen designing or reviewing architecture:\n- Evaluate scalability and future growth\n- Check for appropriate design patterns\n- Assess coupling and cohesion\n- Look forSOLID principle violations\n- Evaluate data modeling decisions\n- Check for eventual consistency issues\n- Assess API design and contract stability\n- Consider operational aspects (monitoring, logging, deployment)`,\n tags: ['architecture', 'design', 'scalability'],\n toolPreferences: ['read', 'glob', 'tree', 'diff'],\n },\n {\n id: 'debugger',\n name: 'Debugger',\n description: 'Root cause analysis and error investigation',\n prompt: `## Debugger Mode\n\nWhen investigating bugs:\n- Reproduce the issue with minimal steps\n- Check error messages and stack traces thoroughly\n- Look for related logs and historical context\n- Verify assumptions about data flow\n- Check for race conditions in async code\n- Validate environment and configuration\n- Use binary search to isolate the root cause\n- Verify fixes with tests before considering done`,\n tags: ['debug', 'investigation', 'error-resolution'],\n toolPreferences: ['read', 'grep', 'bash', 'logs', 'test'],\n },\n {\n id: 'tester',\n name: 'QA Engineer',\n description: 'Test coverage, edge cases, and quality assurance',\n prompt: `## Tester Mode\n\nWhen testing or writing tests:\n- Cover happy path and error paths equally\n- Think about edge cases and boundary conditions\n- Check for missing null/undefined handling tests\n- Verify error messages are tested\n- Look for race condition tests in async code\n- Assess mutation testing opportunities\n- Check for integration test gaps\n- Verify test isolation and cleanup`,\n tags: ['testing', 'qa', 'quality'],\n toolPreferences: ['read', 'grep', 'test', 'bash'],\n },\n {\n id: 'devops',\n name: 'DevOps Engineer',\n description: 'Infrastructure, deployment, and operations',\n prompt: `## DevOps Mode\n\nWhen working on infrastructure:\n- Check for containerization and deployment readiness\n- Verify CI/CD pipeline configurations\n- Assess monitoring and alerting setup\n- Look for health check endpoints\n- Check for graceful shutdown handling\n- Verify backup and disaster recovery plans\n- Assess secrets management\n- Check for resource limits and quotas`,\n tags: ['devops', 'infrastructure', 'operations'],\n toolPreferences: ['read', 'bash', 'grep', 'logs', 'git'],\n },\n {\n id: 'refactorer',\n name: 'Refactorer',\n description: 'Code improvement and modernization',\n prompt: `## Refactorer Mode\n\nWhen refactoring code:\n- Maintain existing behavior — tests must pass before and after\n- Make one change at a time, verify after each\n- Prefer small, focused commits\n- Preserve API contracts unless explicitly changing\n- Remove dead code and comments\n- Improve naming as you go\n- Don't mix formatting changes with logic changes\n- Keep performance in mind — don't regress`,\n tags: ['refactor', 'modernization', 'improvement'],\n toolPreferences: ['read', 'edit', 'test', 'git', 'grep'],\n },\n];\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { Mode, ModeConfig, ModeManifest, ModeStore } from '../types/mode.js';\nimport { DEFAULT_MODES } from '../types/mode.js';\n\nexport class DefaultModeStore implements ModeStore {\n private activeModeId: string | null = null;\n private modes: Mode[];\n private configDir: string;\n\n constructor(config: ModeConfig) {\n this.configDir = config.directory;\n this.modes = [...DEFAULT_MODES];\n }\n\n async getActiveMode(): Promise<Mode | null> {\n if (!this.activeModeId) {\n await this.loadActiveMode();\n }\n if (!this.activeModeId) return null;\n return this.modes.find((m) => m.id === this.activeModeId) ?? null;\n }\n\n async setActiveMode(modeId: string | null): Promise<void> {\n this.activeModeId = modeId;\n await this.saveActiveMode();\n }\n\n async listModes(): Promise<Mode[]> {\n return [...this.modes];\n }\n\n async getMode(modeId: string): Promise<Mode | null> {\n return this.modes.find((m) => m.id === modeId) ?? null;\n }\n\n async addMode(mode: Mode): Promise<void> {\n const idx = this.modes.findIndex((m) => m.id === mode.id);\n if (idx >= 0) {\n this.modes[idx] = mode;\n } else {\n this.modes.push(mode);\n }\n }\n\n async removeMode(modeId: string): Promise<void> {\n const builtIn = DEFAULT_MODES.find((m) => m.id === modeId);\n if (builtIn) {\n throw new Error(`Cannot remove built-in mode \"${modeId}\"`);\n }\n this.modes = this.modes.filter((m) => m.id !== modeId);\n if (this.activeModeId === modeId) {\n this.activeModeId = null;\n await this.saveActiveMode();\n }\n }\n\n private async loadActiveMode(): Promise<void> {\n try {\n const configPath = path.join(this.configDir, 'mode.json');\n const content = await fs.readFile(configPath, 'utf8');\n const data = JSON.parse(content);\n this.activeModeId = data.activeMode ?? null;\n } catch {\n this.activeModeId = 'default';\n }\n }\n\n private async saveActiveMode(): Promise<void> {\n try {\n await fs.mkdir(this.configDir, { recursive: true });\n const configPath = path.join(this.configDir, 'mode.json');\n await fs.writeFile(\n configPath,\n JSON.stringify({ activeMode: this.activeModeId }, null, 2),\n 'utf8',\n );\n } catch {\n // ignore save errors\n }\n }\n}\n\nexport interface ModeLoaderOptions {\n projectModesDir?: string;\n userModesDir?: string;\n}\n\nexport async function loadProjectModes(modesDir: string): Promise<Mode[]> {\n const modes: Mode[] = [];\n try {\n const entries = await fs.readdir(modesDir);\n for (const entry of entries) {\n if (!entry.endsWith('.md') && !entry.endsWith('.txt')) continue;\n const filePath = path.join(modesDir, entry);\n const stat = await fs.stat(filePath);\n if (!stat.isFile()) continue;\n const content = await fs.readFile(filePath, 'utf8');\n const id = path.basename(entry, path.extname(entry));\n modes.push({\n id,\n name: id.replace(/[-_]/g, ' ').replace(/\\b\\w/g, (c) => c.toUpperCase()),\n description: content.split('\\n')[0] ?? id,\n prompt: content,\n tags: ['project'],\n });\n }\n } catch {\n // no project modes\n }\n return modes;\n}\n\nexport async function loadUserModes(modesDir: string): Promise<Mode[]> {\n const modes: Mode[] = [];\n try {\n const manifestPath = path.join(modesDir, 'modes.json');\n const content = await fs.readFile(manifestPath, 'utf8');\n const manifest: ModeManifest = JSON.parse(content);\n for (const mode of manifest.modes) {\n modes.push(mode);\n }\n } catch {\n // no user modes\n }\n return modes;\n}\n","export interface TextBlock {\n type: 'text';\n text: string;\n cache_control?: { type: 'ephemeral' };\n}\n\nexport interface ToolUseBlock {\n type: 'tool_use';\n id: string;\n name: string;\n input: Record<string, unknown>;\n /**\n * Provider-specific opaque metadata captured from the wire response.\n * Echoed back verbatim in the next request so providers that bind\n * extra state to function calls keep working. Example: Gemini's\n * `thoughtSignature` — required for tool-use turns with thinking\n * models, otherwise the next request fails with 400 \"Function call\n * is missing a thought_signature in functionCall parts\".\n *\n * Keys are namespaced by intent so multiple wires can coexist:\n * - `google.thoughtSignature` — Gemini signed-thought blob\n * Other providers can add their own keys without colliding.\n */\n providerMeta?: Record<string, unknown>;\n}\n\nexport interface ToolResultBlock {\n type: 'tool_result';\n tool_use_id: string;\n /**\n * The original tool name. Useful for providers like Google Gemini that\n * need the tool name in `functionResponse.name` — the tool_use_id is\n * only a session-local identifier and is not stable across replays.\n * Always set by ToolExecutor; may be absent on manually-constructed blocks.\n */\n name?: string;\n content: string;\n is_error?: boolean;\n}\n\nexport interface ImageBlock {\n type: 'image';\n source: {\n type: 'base64' | 'url';\n media_type?: string;\n data?: string;\n url?: string;\n };\n}\n\n/**\n * Chain-of-thought / extended-thinking content emitted by the model.\n *\n * Both Anthropic extended thinking (`{type:'thinking', thinking, signature}`)\n * and DeepSeek reasoning mode (top-level `reasoning_content` on the assistant\n * message) require this content to be echoed back verbatim on the next\n * request, otherwise the provider returns 400:\n * - Anthropic: \"The `content[].thinking` in the thinking mode must be passed back\"\n * - DeepSeek: \"The `reasoning_content` in the thinking mode must be passed back\"\n *\n * `signature` is Anthropic-specific (an opaque integrity blob). DeepSeek\n * doesn't issue a signature — the field is absent for that provider.\n *\n * Per Anthropic, thinking blocks MUST appear before any text/tool_use blocks\n * in an assistant message. Stream builders preserve that order.\n */\nexport interface ThinkingBlock {\n type: 'thinking';\n thinking: string;\n signature?: string;\n providerMeta?: Record<string, unknown>;\n}\n\nexport type ContentBlock = TextBlock | ToolUseBlock | ToolResultBlock | ImageBlock | ThinkingBlock;\n\nexport function isTextBlock(b: ContentBlock): b is TextBlock {\n return b.type === 'text';\n}\nexport function isToolUseBlock(b: ContentBlock): b is ToolUseBlock {\n return b.type === 'tool_use';\n}\nexport function isToolResultBlock(b: ContentBlock): b is ToolResultBlock {\n return b.type === 'tool_result';\n}\nexport function isImageBlock(b: ContentBlock): b is ImageBlock {\n return b.type === 'image';\n}\nexport function isThinkingBlock(b: ContentBlock): b is ThinkingBlock {\n return b.type === 'thinking';\n}\n","import { isTextBlock } from '../types/blocks.js';\nimport type { Message } from '../types/messages.js';\nimport type { Provider, Request } from '../types/provider.js';\nimport type { MessageSelector, SelectorResult } from '../types/selector.js';\n\nexport interface LLMSelectorOptions {\n /** Provider used for the selector LLM call. Required. */\n provider: Provider;\n /** Model for the selector. Defaults to the provider's default model. */\n model?: string;\n /**\n * Maximum tokens to keep in context (target budget).\n * Selector will aim to keep total content below this.\n */\n maxContextTokens?: number;\n /**\n * Prompt instructing the selector how to behave.\n * Should guide the LLM on importance tiers and output format.\n */\n systemPrompt?: string;\n}\n\nconst DEFAULT_SYSTEM_PROMPT = `You are a context pruning assistant. Given a conversation history and a token budget, decide which message ranges are worth keeping verbatim and which should be collapsed into summaries.\n\nOutput a JSON object with this structure:\n{\n \"kept\": [{\"from\": 0, \"to\": 5, \"importance\": \"critical\"}],\n \"collapsed\": [{\"from\": 6, \"to\": 20, \"summary\": \"optional summary\"}],\n \"reasoning\": \"brief explanation of decisions\"\n}\n\nImportance tiers:\n- \"critical\": decisions, file edits, tool results that affect state, final answers\n- \"high\": substantive tool use, complex reasoning, non-obvious observations\n- \"medium\": routine exchanges, confirmations, straightforward Q&A\n\nRules:\n- Always keep the most recent K pairs (preserve recency)\n- Never collapse the final 2 user/assistant pairs (working memory)\n- Preserve tool results that modified files or had external effects\n- Collapse old, low-information exchanges (greetings, acknowledgements, etc.)\n- If unsure, keep rather than collapse (errors are more costly than waste)\n\nReturn ONLY the JSON object, no markdown, no explanation outside the JSON.`;\n\n/** Rough token estimation for a message array */\nfunction estimateTokens(messages: Message[]): number {\n let total = 0;\n for (const m of messages) {\n if (typeof m.content === 'string') {\n total += Math.ceil(m.content.length / 4);\n } else if (Array.isArray(m.content)) {\n for (const b of m.content) {\n if (b.type === 'text') total += Math.ceil(b.text.length / 4);\n else total += Math.ceil(JSON.stringify(b).length / 4);\n }\n }\n }\n return total;\n}\n\n/** Format messages as a compact text dump for the selector LLM */\nfunction formatMessages(messages: Message[], maxChars = 8000): string {\n const lines: string[] = [];\n let used = 0;\n for (let i = 0; i < messages.length; i++) {\n const m = messages[i]!;\n const role = m.role.padEnd(10, ' ');\n let text: string;\n if (typeof m.content === 'string') {\n text = m.content.slice(0, 500);\n } else {\n const content = m.content as import('../types/blocks.js').ContentBlock[];\n text = content\n .filter(isTextBlock)\n .map((b) => b.text)\n .join(' ');\n // Also capture tool names for context\n const toolUses = content.filter((b) => b.type === 'tool_use');\n if (toolUses.length > 0) {\n text += ` [tools: ${toolUses.map((b) => (b as { name: string }).name).join(', ')}]`;\n }\n }\n const line = `[${i}][${role}]: ${text}`;\n if (used + line.length > maxChars) break;\n lines.push(line);\n used += line.length;\n }\n return lines.join('\\n');\n}\n\n/**\n * LLM-powered message selector. Calls a sub-LLM to analyze the\n * message history and produce a keep/collapse plan — more surgical\n * than fixed-window rules.\n */\nexport class LLMSelector implements MessageSelector {\n private readonly provider: Provider;\n private readonly model: string;\n private readonly maxContextTokens: number;\n private readonly systemPrompt: string;\n\n constructor(opts: LLMSelectorOptions) {\n this.provider = opts.provider;\n this.model = opts.model ?? 'unknown';\n this.maxContextTokens = opts.maxContextTokens ?? 40_000;\n this.systemPrompt = opts.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;\n }\n\n async select(messages: Message[], maxToKeep: number): Promise<SelectorResult> {\n const effectiveBudget = Math.min(maxToKeep, this.maxContextTokens);\n\n // Build a concise representation of the conversation\n const historyText = formatMessages(messages);\n const totalTokens = estimateTokens(messages);\n const systemText = `${this.systemPrompt}\\n\\nConversation (${messages.length} messages, ~${totalTokens} tokens, budget: ${effectiveBudget}):\\n`;\n\n // Add instruction to stay within budget\n const budgetInstruction =\n totalTokens > effectiveBudget\n ? `\\n\\nIMPORTANT: Total conversation (${totalTokens} tokens) exceeds budget (${effectiveBudget}). You MUST collapse enough to fit. Prefer collapsing older/lower-importance ranges.`\n : '';\n\n const req: Request = {\n model: this.model,\n system: [{ type: 'text', text: systemText + budgetInstruction }],\n messages: [{ role: 'user', content: historyText }],\n maxTokens: 1024,\n };\n\n let raw: string;\n try {\n // Wire the AbortController to the provider call so cancellation actually\n // fires — the original code passed a fresh signal that is never connected\n // to anything, leaking the controller on every selector call.\n const ac = new AbortController();\n const res = await this.provider.complete(req, { signal: ac.signal });\n const textBlocks = res.content.filter(isTextBlock);\n raw = textBlocks\n .map((b) => b.text)\n .join('\\n')\n .trim();\n } catch (err) {\n // Fallback: use simple recency-based selection\n return this.fallbackSelect(messages, effectiveBudget);\n }\n\n return this.parseSelectorOutput(raw, messages.length);\n }\n\n private fallbackSelect(messages: Message[], budget: number): SelectorResult {\n // Simple fallback: keep from the end until we hit budget\n const toKeep: SelectorResult['kept'] = [];\n const toCollapse: SelectorResult['collapsed'] = [];\n\n let tokenCount = 0;\n let startIdx = 0;\n\n // Scan from the end backwards\n for (let i = messages.length - 1; i >= 0; i--) {\n const m = messages[i]!;\n const cost =\n typeof m.content === 'string'\n ? Math.ceil(m.content.length / 4)\n : m.content.reduce(\n (acc, b) =>\n acc +\n (b.type === 'text'\n ? Math.ceil(b.text.length / 4)\n : Math.ceil(JSON.stringify(b).length / 4)),\n 0,\n );\n\n if (tokenCount + cost <= budget) {\n tokenCount += cost;\n } else {\n startIdx = i + 1;\n break;\n }\n }\n\n if (startIdx > 0) {\n toCollapse.push({ from: 0, to: startIdx - 1 });\n }\n toKeep.push({ from: startIdx, to: messages.length - 1, importance: 'high' });\n\n return {\n kept: toKeep,\n collapsed: toCollapse,\n reasoning: `Fallback: kept last ${messages.length - startIdx} messages within ${budget} token budget`,\n };\n }\n\n private parseSelectorOutput(raw: string, messageCount: number): SelectorResult {\n // Try to extract JSON from the response\n const jsonStart = raw.indexOf('{');\n const jsonEnd = raw.lastIndexOf('}');\n if (jsonStart === -1 || jsonEnd === -1) {\n // Can't parse — use fallback\n return this.fallbackSelect(\n Array.from({ length: messageCount }, () => ({ role: 'user', content: '' }) as Message),\n this.maxContextTokens,\n );\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw.slice(jsonStart, jsonEnd + 1));\n } catch {\n return this.fallbackSelect(\n Array.from({ length: messageCount }, () => ({ role: 'user', content: '' }) as Message),\n this.maxContextTokens,\n );\n }\n\n const obj = parsed as Record<string, unknown>;\n const kept =\n (obj.kept as Array<{ from: number; to: number; importance: string }> | undefined) ?? [];\n const collapsed =\n (obj.collapsed as Array<{ from: number; to: number; summary?: string }> | undefined) ?? [];\n\n return {\n kept: kept.map((k) => ({\n from: k.from,\n to: k.to,\n importance: (k.importance ?? 'medium') as 'critical' | 'high' | 'medium',\n })),\n collapsed: collapsed.map((c) => ({ from: c.from, to: c.to, summary: c.summary })),\n reasoning: typeof obj.reasoning === 'string' ? obj.reasoning : '',\n };\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/utils/atomic-write.ts","../../src/models/models-registry.ts","../../src/types/mode.ts","../../src/models/mode-store.ts","../../src/types/blocks.ts","../../src/models/llm-selector.ts"],"names":["path","stat","resolve","fs2","path2","fs3"],"mappings":"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","file":"index.js","sourcesContent":["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","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type {\n ModelsDevPayload,\n ModelsDevProvider,\n ModelsRegistry,\n ResolvedModel,\n ResolvedProvider,\n WireFamily,\n} from '../types/models-registry.js';\nimport { atomicWrite } from '../utils/atomic-write.js';\n\nconst DEFAULT_URL = 'https://models.dev/api.json';\nconst DEFAULT_TTL_SECONDS = 24 * 3600;\n\ninterface CacheEnvelope {\n fetchedAt: string;\n url: string;\n payload: ModelsDevPayload;\n}\n\nexport interface DefaultModelsRegistryOptions {\n cacheFile: string;\n url?: string;\n ttlSeconds?: number;\n fetchImpl?: typeof fetch;\n /** Pre-seeded payload — useful for offline scenarios and tests. */\n seed?: ModelsDevPayload;\n /**\n * Maximum age in seconds for stale cache fallback when network fails.\n * Defaults to 7 days. Set to `Infinity` for full offline resilience\n * (risk: deprecated models, wrong pricing). Set to `0` to disable\n * stale fallback entirely.\n */\n maxStaleAgeSeconds?: number;\n}\n\n/**\n * The npm package each models.dev provider declares determines which wire\n * family WrongStack speaks. Anything not listed falls into `unsupported` and\n * can be enabled by registering a custom provider factory via a plugin.\n */\nconst FAMILY_BY_NPM: Record<string, WireFamily> = {\n '@ai-sdk/anthropic': 'anthropic',\n '@ai-sdk/google-vertex/anthropic': 'anthropic',\n '@ai-sdk/openai': 'openai',\n '@ai-sdk/openai-compatible': 'openai-compatible',\n '@ai-sdk/groq': 'openai-compatible',\n '@ai-sdk/xai': 'openai-compatible',\n '@ai-sdk/cerebras': 'openai-compatible',\n '@ai-sdk/togetherai': 'openai-compatible',\n '@ai-sdk/mistral': 'openai-compatible',\n '@ai-sdk/perplexity': 'openai-compatible',\n '@ai-sdk/deepinfra': 'openai-compatible',\n '@openrouter/ai-sdk-provider': 'openai-compatible',\n 'ai-gateway-provider': 'openai-compatible',\n '@ai-sdk/vercel': 'openai-compatible',\n '@ai-sdk/gateway': 'openai-compatible',\n '@aihubmix/ai-sdk-provider': 'openai-compatible',\n 'venice-ai-sdk-provider': 'openai-compatible',\n '@ai-sdk/google': 'google',\n};\n\nexport function classifyFamily(npm: string | undefined): WireFamily {\n if (!npm) return 'unsupported';\n return FAMILY_BY_NPM[npm] ?? 'unsupported';\n}\n\nexport class DefaultModelsRegistry implements ModelsRegistry {\n private payload?: ModelsDevPayload;\n private fetchedAt?: Date;\n private readonly cacheFile: string;\n private readonly url: string;\n private readonly ttlMs: number;\n private readonly fetchImpl: typeof fetch;\n private readonly seed?: ModelsDevPayload;\n private readonly maxStaleAgeMs: number;\n\n constructor(opts: DefaultModelsRegistryOptions) {\n this.cacheFile = opts.cacheFile;\n this.url = opts.url ?? DEFAULT_URL;\n this.ttlMs = (opts.ttlSeconds ?? DEFAULT_TTL_SECONDS) * 1000;\n this.fetchImpl = opts.fetchImpl ?? fetch;\n this.seed = opts.seed;\n // Default max stale age: 7 days\n const maxStaleSeconds = opts.maxStaleAgeSeconds ?? 7 * 24 * 3600;\n this.maxStaleAgeMs = maxStaleSeconds * 1000;\n }\n\n async load(opts: { force?: boolean } = {}): Promise<ModelsDevPayload> {\n if (this.payload && !opts.force) return this.payload;\n if (this.seed) {\n this.payload = this.seed;\n this.fetchedAt = new Date();\n return this.payload;\n }\n if (!opts.force) {\n const cached = await this.readCache();\n if (cached && this.isFresh(cached.fetchedAt)) {\n this.payload = cached.payload;\n this.fetchedAt = new Date(cached.fetchedAt);\n return cached.payload;\n }\n }\n try {\n return await this.refresh();\n } catch (err) {\n // Network failed — fall back to stale cache if within maxStaleAgeMs.\n const cached = await this.readCache();\n if (cached && this.isWithinMaxStaleAge(cached.fetchedAt)) {\n this.payload = cached.payload;\n this.fetchedAt = new Date(cached.fetchedAt);\n return cached.payload;\n }\n throw err;\n }\n }\n\n async refresh(): Promise<ModelsDevPayload> {\n const res = await this.fetchImpl(this.url, {\n method: 'GET',\n headers: { accept: 'application/json' },\n });\n if (!res.ok) {\n throw new Error(`ModelsRegistry: HTTP ${res.status} fetching ${this.url}`);\n }\n const json = (await res.json()) as ModelsDevPayload;\n this.payload = json;\n this.fetchedAt = new Date();\n const envelope: CacheEnvelope = {\n fetchedAt: this.fetchedAt.toISOString(),\n url: this.url,\n payload: json,\n };\n await atomicWrite(this.cacheFile, JSON.stringify(envelope));\n return json;\n }\n\n async listProviders(): Promise<ResolvedProvider[]> {\n const payload = await this.load();\n return Object.values(payload).map((p) => this.resolveProvider(p));\n }\n\n async getProvider(id: string): Promise<ResolvedProvider | undefined> {\n const payload = await this.load();\n const p = payload[id];\n return p ? this.resolveProvider(p) : undefined;\n }\n\n async getModel(providerId: string, modelId: string): Promise<ResolvedModel | undefined> {\n const provider = await this.getProvider(providerId);\n if (!provider) return undefined;\n const model = provider.models.find((m) => m.id === modelId);\n if (!model) return undefined;\n return {\n providerId,\n modelId,\n capabilities: {\n tools: model.tool_call ?? false,\n vision: Boolean(model.modalities?.input?.includes('image')),\n reasoning: model.reasoning ?? false,\n maxContext: model.limit?.context ?? 0,\n maxOutput: model.limit?.output,\n knowledge: model.knowledge,\n },\n cost: model.cost,\n };\n }\n\n async suggestModel(providerId: string): Promise<string | undefined> {\n const provider = await this.getProvider(providerId);\n if (!provider || provider.models.length === 0) return undefined;\n const ranked = [...provider.models].sort((a, b) => {\n const at = a.release_date ?? a.last_updated ?? '';\n const bt = b.release_date ?? b.last_updated ?? '';\n return bt.localeCompare(at);\n });\n return ranked[0]?.id;\n }\n\n async ageSeconds(): Promise<number> {\n if (!this.fetchedAt) {\n const cached = await this.readCache();\n if (!cached) return Number.POSITIVE_INFINITY;\n return (Date.now() - new Date(cached.fetchedAt).getTime()) / 1000;\n }\n return (Date.now() - this.fetchedAt.getTime()) / 1000;\n }\n\n private resolveProvider(p: ModelsDevProvider): ResolvedProvider {\n return {\n id: p.id,\n name: p.name,\n family: classifyFamily(p.npm),\n apiBase: p.api,\n envVars: p.env ?? [],\n doc: p.doc,\n models: Object.values(p.models ?? {}),\n npm: p.npm,\n };\n }\n\n private isFresh(fetchedAtIso: string): boolean {\n return Date.now() - new Date(fetchedAtIso).getTime() < this.ttlMs;\n }\n\n private isWithinMaxStaleAge(fetchedAtIso: string): boolean {\n return Date.now() - new Date(fetchedAtIso).getTime() < this.maxStaleAgeMs;\n }\n\n private async readCache(): Promise<CacheEnvelope | undefined> {\n try {\n const raw = await fs.readFile(this.cacheFile, 'utf8');\n return JSON.parse(raw) as CacheEnvelope;\n } catch {\n return undefined;\n }\n }\n\n /** Used by `wstack models refresh` to expose where the cache lives. */\n cacheLocation(): string {\n return path.resolve(this.cacheFile);\n }\n}\n","export interface Mode {\n id: string;\n name: string;\n description: string;\n /** Additional prompt text injected into system prompt when mode is active */\n prompt: string;\n /** Tags for tool_search filtering */\n tags?: string[];\n /** Tools that should be prioritized/highlighted when this mode is active */\n toolPreferences?: string[];\n}\n\nexport interface ModeManifest {\n modes: Mode[];\n defaultMode?: string;\n}\n\nexport interface ModeStore {\n getActiveMode(): Promise<Mode | null>;\n setActiveMode(modeId: string | null): Promise<void>;\n listModes(): Promise<Mode[]>;\n getMode(modeId: string): Promise<Mode | null>;\n}\n\nexport interface ModeConfig {\n directory: string;\n}\n\nexport const DEFAULT_MODES: Mode[] = [\n {\n id: 'default',\n name: 'Default',\n description: 'General-purpose coding assistant',\n prompt: '',\n tags: ['general'],\n },\n {\n id: 'code-reviewer',\n name: 'Code Reviewer',\n description: 'Focus on code quality, best practices, and potential bugs',\n prompt: `## Code Reviewer Mode\n\nWhen reviewing code:\n- Look for potential bugs, race conditions, and edge cases\n- Check for security vulnerabilities (SQL injection, XSS, CSRF, etc.)\n- Evaluate error handling completeness\n- Assess code readability and maintainability\n- Check for performance anti-patterns\n- Verify test coverage for critical paths\n- Ensure naming conventions are followed`,\n tags: ['review', 'quality', 'security'],\n toolPreferences: ['read', 'grep', 'git', 'diff', 'test'],\n },\n {\n id: 'code-auditor',\n name: 'Code Auditor',\n description: 'Security-focused code analysis',\n prompt: `## Code Auditor Mode\n\nWhen auditing code for security:\n- Identify injection vulnerabilities (SQL, Command, XSS, LDAP)\n- Check authentication and authorization patterns\n- Look for sensitive data exposure (secrets, PII in logs)\n- Verify cryptographic implementations\n- Check for insecure dependencies or configurations\n- Assess input validation and output encoding\n- Look for timing attacks and information leakage`,\n tags: ['security', 'audit', 'compliance'],\n toolPreferences: ['grep', 'read', 'audit', 'bash'],\n },\n {\n id: 'architect',\n name: 'Software Architect',\n description: 'Design patterns, scalability, and system design',\n prompt: `## Architect Mode\n\nWhen designing or reviewing architecture:\n- Evaluate scalability and future growth\n- Check for appropriate design patterns\n- Assess coupling and cohesion\n- Look forSOLID principle violations\n- Evaluate data modeling decisions\n- Check for eventual consistency issues\n- Assess API design and contract stability\n- Consider operational aspects (monitoring, logging, deployment)`,\n tags: ['architecture', 'design', 'scalability'],\n toolPreferences: ['read', 'glob', 'tree', 'diff'],\n },\n {\n id: 'debugger',\n name: 'Debugger',\n description: 'Root cause analysis and error investigation',\n prompt: `## Debugger Mode\n\nWhen investigating bugs:\n- Reproduce the issue with minimal steps\n- Check error messages and stack traces thoroughly\n- Look for related logs and historical context\n- Verify assumptions about data flow\n- Check for race conditions in async code\n- Validate environment and configuration\n- Use binary search to isolate the root cause\n- Verify fixes with tests before considering done`,\n tags: ['debug', 'investigation', 'error-resolution'],\n toolPreferences: ['read', 'grep', 'bash', 'logs', 'test'],\n },\n {\n id: 'tester',\n name: 'QA Engineer',\n description: 'Test coverage, edge cases, and quality assurance',\n prompt: `## Tester Mode\n\nWhen testing or writing tests:\n- Cover happy path and error paths equally\n- Think about edge cases and boundary conditions\n- Check for missing null/undefined handling tests\n- Verify error messages are tested\n- Look for race condition tests in async code\n- Assess mutation testing opportunities\n- Check for integration test gaps\n- Verify test isolation and cleanup`,\n tags: ['testing', 'qa', 'quality'],\n toolPreferences: ['read', 'grep', 'test', 'bash'],\n },\n {\n id: 'devops',\n name: 'DevOps Engineer',\n description: 'Infrastructure, deployment, and operations',\n prompt: `## DevOps Mode\n\nWhen working on infrastructure:\n- Check for containerization and deployment readiness\n- Verify CI/CD pipeline configurations\n- Assess monitoring and alerting setup\n- Look for health check endpoints\n- Check for graceful shutdown handling\n- Verify backup and disaster recovery plans\n- Assess secrets management\n- Check for resource limits and quotas`,\n tags: ['devops', 'infrastructure', 'operations'],\n toolPreferences: ['read', 'bash', 'grep', 'logs', 'git'],\n },\n {\n id: 'refactorer',\n name: 'Refactorer',\n description: 'Code improvement and modernization',\n prompt: `## Refactorer Mode\n\nWhen refactoring code:\n- Maintain existing behavior — tests must pass before and after\n- Make one change at a time, verify after each\n- Prefer small, focused commits\n- Preserve API contracts unless explicitly changing\n- Remove dead code and comments\n- Improve naming as you go\n- Don't mix formatting changes with logic changes\n- Keep performance in mind — don't regress`,\n tags: ['refactor', 'modernization', 'improvement'],\n toolPreferences: ['read', 'edit', 'test', 'git', 'grep'],\n },\n];\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { Mode, ModeConfig, ModeManifest, ModeStore } from '../types/mode.js';\nimport { DEFAULT_MODES } from '../types/mode.js';\n\nexport class DefaultModeStore implements ModeStore {\n private activeModeId: string | null = null;\n private modes: Mode[];\n private configDir: string;\n\n constructor(config: ModeConfig) {\n this.configDir = config.directory;\n this.modes = [...DEFAULT_MODES];\n }\n\n async getActiveMode(): Promise<Mode | null> {\n if (!this.activeModeId) {\n await this.loadActiveMode();\n }\n if (!this.activeModeId) return null;\n return this.modes.find((m) => m.id === this.activeModeId) ?? null;\n }\n\n async setActiveMode(modeId: string | null): Promise<void> {\n this.activeModeId = modeId;\n await this.saveActiveMode();\n }\n\n async listModes(): Promise<Mode[]> {\n return [...this.modes];\n }\n\n async getMode(modeId: string): Promise<Mode | null> {\n return this.modes.find((m) => m.id === modeId) ?? null;\n }\n\n async addMode(mode: Mode): Promise<void> {\n const idx = this.modes.findIndex((m) => m.id === mode.id);\n if (idx >= 0) {\n this.modes[idx] = mode;\n } else {\n this.modes.push(mode);\n }\n }\n\n async removeMode(modeId: string): Promise<void> {\n const builtIn = DEFAULT_MODES.find((m) => m.id === modeId);\n if (builtIn) {\n throw new Error(`Cannot remove built-in mode \"${modeId}\"`);\n }\n this.modes = this.modes.filter((m) => m.id !== modeId);\n if (this.activeModeId === modeId) {\n this.activeModeId = null;\n await this.saveActiveMode();\n }\n }\n\n private async loadActiveMode(): Promise<void> {\n try {\n const configPath = path.join(this.configDir, 'mode.json');\n const content = await fs.readFile(configPath, 'utf8');\n const data = JSON.parse(content);\n this.activeModeId = data.activeMode ?? null;\n } catch {\n this.activeModeId = 'default';\n }\n }\n\n private async saveActiveMode(): Promise<void> {\n try {\n await fs.mkdir(this.configDir, { recursive: true });\n const configPath = path.join(this.configDir, 'mode.json');\n await fs.writeFile(\n configPath,\n JSON.stringify({ activeMode: this.activeModeId }, null, 2),\n 'utf8',\n );\n } catch {\n // ignore save errors\n }\n }\n}\n\nexport interface ModeLoaderOptions {\n projectModesDir?: string;\n userModesDir?: string;\n}\n\nexport async function loadProjectModes(modesDir: string): Promise<Mode[]> {\n const modes: Mode[] = [];\n try {\n const entries = await fs.readdir(modesDir);\n for (const entry of entries) {\n if (!entry.endsWith('.md') && !entry.endsWith('.txt')) continue;\n const filePath = path.join(modesDir, entry);\n const stat = await fs.stat(filePath);\n if (!stat.isFile()) continue;\n const content = await fs.readFile(filePath, 'utf8');\n const id = path.basename(entry, path.extname(entry));\n modes.push({\n id,\n name: id.replace(/[-_]/g, ' ').replace(/\\b\\w/g, (c) => c.toUpperCase()),\n description: content.split('\\n')[0] ?? id,\n prompt: content,\n tags: ['project'],\n });\n }\n } catch {\n // no project modes\n }\n return modes;\n}\n\nexport async function loadUserModes(modesDir: string): Promise<Mode[]> {\n const modes: Mode[] = [];\n try {\n const manifestPath = path.join(modesDir, 'modes.json');\n const content = await fs.readFile(manifestPath, 'utf8');\n const manifest: ModeManifest = JSON.parse(content);\n for (const mode of manifest.modes) {\n modes.push(mode);\n }\n } catch {\n // no user modes\n }\n return modes;\n}\n","export interface TextBlock {\n type: 'text';\n text: string;\n cache_control?: { type: 'ephemeral' };\n}\n\nexport interface ToolUseBlock {\n type: 'tool_use';\n id: string;\n name: string;\n input: Record<string, unknown>;\n /**\n * Provider-specific opaque metadata captured from the wire response.\n * Echoed back verbatim in the next request so providers that bind\n * extra state to function calls keep working. Example: Gemini's\n * `thoughtSignature` — required for tool-use turns with thinking\n * models, otherwise the next request fails with 400 \"Function call\n * is missing a thought_signature in functionCall parts\".\n *\n * Keys are namespaced by intent so multiple wires can coexist:\n * - `google.thoughtSignature` — Gemini signed-thought blob\n * Other providers can add their own keys without colliding.\n */\n providerMeta?: Record<string, unknown>;\n}\n\nexport interface ToolResultBlock {\n type: 'tool_result';\n tool_use_id: string;\n /**\n * The original tool name. Useful for providers like Google Gemini that\n * need the tool name in `functionResponse.name` — the tool_use_id is\n * only a session-local identifier and is not stable across replays.\n * Always set by ToolExecutor; may be absent on manually-constructed blocks.\n */\n name?: string;\n content: string;\n is_error?: boolean;\n}\n\nexport interface ImageBlock {\n type: 'image';\n source: {\n type: 'base64' | 'url';\n media_type?: string;\n data?: string;\n url?: string;\n };\n}\n\n/**\n * Chain-of-thought / extended-thinking content emitted by the model.\n *\n * Both Anthropic extended thinking (`{type:'thinking', thinking, signature}`)\n * and DeepSeek reasoning mode (top-level `reasoning_content` on the assistant\n * message) require this content to be echoed back verbatim on the next\n * request, otherwise the provider returns 400:\n * - Anthropic: \"The `content[].thinking` in the thinking mode must be passed back\"\n * - DeepSeek: \"The `reasoning_content` in the thinking mode must be passed back\"\n *\n * `signature` is Anthropic-specific (an opaque integrity blob). DeepSeek\n * doesn't issue a signature — the field is absent for that provider.\n *\n * Per Anthropic, thinking blocks MUST appear before any text/tool_use blocks\n * in an assistant message. Stream builders preserve that order.\n */\nexport interface ThinkingBlock {\n type: 'thinking';\n thinking: string;\n signature?: string;\n providerMeta?: Record<string, unknown>;\n}\n\nexport type ContentBlock = TextBlock | ToolUseBlock | ToolResultBlock | ImageBlock | ThinkingBlock;\n\nexport function isTextBlock(b: ContentBlock): b is TextBlock {\n return b.type === 'text';\n}\nexport function isToolUseBlock(b: ContentBlock): b is ToolUseBlock {\n return b.type === 'tool_use';\n}\nexport function isToolResultBlock(b: ContentBlock): b is ToolResultBlock {\n return b.type === 'tool_result';\n}\nexport function isImageBlock(b: ContentBlock): b is ImageBlock {\n return b.type === 'image';\n}\nexport function isThinkingBlock(b: ContentBlock): b is ThinkingBlock {\n return b.type === 'thinking';\n}\n","import { isTextBlock } from '../types/blocks.js';\nimport type { Message } from '../types/messages.js';\nimport type { Provider, Request } from '../types/provider.js';\nimport type { MessageSelector, SelectorResult } from '../types/selector.js';\n\nexport interface LLMSelectorOptions {\n /** Provider used for the selector LLM call. Required. */\n provider: Provider;\n /** Model for the selector. Defaults to the provider's default model. */\n model?: string;\n /**\n * Maximum tokens to keep in context (target budget).\n * Selector will aim to keep total content below this.\n */\n maxContextTokens?: number;\n /**\n * Prompt instructing the selector how to behave.\n * Should guide the LLM on importance tiers and output format.\n */\n systemPrompt?: string;\n}\n\nconst DEFAULT_SYSTEM_PROMPT = `You are a context pruning assistant. Given a conversation history and a token budget, decide which message ranges are worth keeping verbatim and which should be collapsed into summaries.\n\nOutput a JSON object with this structure:\n{\n \"kept\": [{\"from\": 0, \"to\": 5, \"importance\": \"critical\"}],\n \"collapsed\": [{\"from\": 6, \"to\": 20, \"summary\": \"optional summary\"}],\n \"reasoning\": \"brief explanation of decisions\"\n}\n\nImportance tiers:\n- \"critical\": decisions, file edits, tool results that affect state, final answers\n- \"high\": substantive tool use, complex reasoning, non-obvious observations\n- \"medium\": routine exchanges, confirmations, straightforward Q&A\n\nRules:\n- Always keep the most recent K pairs (preserve recency)\n- Never collapse the final 2 user/assistant pairs (working memory)\n- Preserve tool results that modified files or had external effects\n- Collapse old, low-information exchanges (greetings, acknowledgements, etc.)\n- If unsure, keep rather than collapse (errors are more costly than waste)\n\nReturn ONLY the JSON object, no markdown, no explanation outside the JSON.`;\n\n/** Rough token estimation for a message array */\nfunction estimateTokens(messages: Message[]): number {\n let total = 0;\n for (const m of messages) {\n if (typeof m.content === 'string') {\n total += Math.ceil(m.content.length / 4);\n } else if (Array.isArray(m.content)) {\n for (const b of m.content) {\n if (b.type === 'text') total += Math.ceil(b.text.length / 4);\n else total += Math.ceil(JSON.stringify(b).length / 4);\n }\n }\n }\n return total;\n}\n\n/** Format messages as a compact text dump for the selector LLM */\nfunction formatMessages(messages: Message[], maxChars = 8000): string {\n const lines: string[] = [];\n let used = 0;\n for (let i = 0; i < messages.length; i++) {\n const m = messages[i]!;\n const role = m.role.padEnd(10, ' ');\n let text: string;\n if (typeof m.content === 'string') {\n text = m.content.slice(0, 500);\n } else {\n const content = m.content as import('../types/blocks.js').ContentBlock[];\n text = content\n .filter(isTextBlock)\n .map((b) => b.text)\n .join(' ');\n // Also capture tool names for context\n const toolUses = content.filter((b) => b.type === 'tool_use');\n if (toolUses.length > 0) {\n text += ` [tools: ${toolUses.map((b) => (b as { name: string }).name).join(', ')}]`;\n }\n }\n const line = `[${i}][${role}]: ${text}`;\n if (used + line.length > maxChars) break;\n lines.push(line);\n used += line.length;\n }\n return lines.join('\\n');\n}\n\n/**\n * LLM-powered message selector. Calls a sub-LLM to analyze the\n * message history and produce a keep/collapse plan — more surgical\n * than fixed-window rules.\n */\nexport class LLMSelector implements MessageSelector {\n private readonly provider: Provider;\n private readonly model: string;\n private readonly maxContextTokens: number;\n private readonly systemPrompt: string;\n\n constructor(opts: LLMSelectorOptions) {\n this.provider = opts.provider;\n this.model = opts.model ?? 'unknown';\n this.maxContextTokens = opts.maxContextTokens ?? 40_000;\n this.systemPrompt = opts.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;\n }\n\n async select(messages: Message[], maxToKeep: number): Promise<SelectorResult> {\n const effectiveBudget = Math.min(maxToKeep, this.maxContextTokens);\n\n // Build a concise representation of the conversation\n const historyText = formatMessages(messages);\n const totalTokens = estimateTokens(messages);\n const systemText = `${this.systemPrompt}\\n\\nConversation (${messages.length} messages, ~${totalTokens} tokens, budget: ${effectiveBudget}):\\n`;\n\n // Add instruction to stay within budget\n const budgetInstruction =\n totalTokens > effectiveBudget\n ? `\\n\\nIMPORTANT: Total conversation (${totalTokens} tokens) exceeds budget (${effectiveBudget}). You MUST collapse enough to fit. Prefer collapsing older/lower-importance ranges.`\n : '';\n\n const req: Request = {\n model: this.model,\n system: [{ type: 'text', text: systemText + budgetInstruction }],\n messages: [{ role: 'user', content: historyText }],\n maxTokens: 1024,\n };\n\n let raw: string;\n try {\n // Wire the AbortController to the provider call so cancellation actually\n // fires — the original code passed a fresh signal that is never connected\n // to anything, leaking the controller on every selector call.\n const ac = new AbortController();\n const res = await this.provider.complete(req, { signal: ac.signal });\n const textBlocks = res.content.filter(isTextBlock);\n raw = textBlocks\n .map((b) => b.text)\n .join('\\n')\n .trim();\n } catch (err) {\n // Fallback: use simple recency-based selection\n return this.fallbackSelect(messages, effectiveBudget);\n }\n\n return this.parseSelectorOutput(raw, messages.length);\n }\n\n private fallbackSelect(messages: Message[], budget: number): SelectorResult {\n // Simple fallback: keep from the end until we hit budget\n const toKeep: SelectorResult['kept'] = [];\n const toCollapse: SelectorResult['collapsed'] = [];\n\n let tokenCount = 0;\n let startIdx = 0;\n\n // Scan from the end backwards\n for (let i = messages.length - 1; i >= 0; i--) {\n const m = messages[i]!;\n const cost =\n typeof m.content === 'string'\n ? Math.ceil(m.content.length / 4)\n : m.content.reduce(\n (acc, b) =>\n acc +\n (b.type === 'text'\n ? Math.ceil(b.text.length / 4)\n : Math.ceil(JSON.stringify(b).length / 4)),\n 0,\n );\n\n if (tokenCount + cost <= budget) {\n tokenCount += cost;\n } else {\n startIdx = i + 1;\n break;\n }\n }\n\n if (startIdx > 0) {\n toCollapse.push({ from: 0, to: startIdx - 1 });\n }\n toKeep.push({ from: startIdx, to: messages.length - 1, importance: 'high' });\n\n return {\n kept: toKeep,\n collapsed: toCollapse,\n reasoning: `Fallback: kept last ${messages.length - startIdx} messages within ${budget} token budget`,\n };\n }\n\n private parseSelectorOutput(raw: string, messageCount: number): SelectorResult {\n // Try to extract JSON from the response\n const jsonStart = raw.indexOf('{');\n const jsonEnd = raw.lastIndexOf('}');\n if (jsonStart === -1 || jsonEnd === -1) {\n // Can't parse — use fallback\n return this.fallbackSelect(\n Array.from({ length: messageCount }, () => ({ role: 'user', content: '' }) as Message),\n this.maxContextTokens,\n );\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw.slice(jsonStart, jsonEnd + 1));\n } catch {\n return this.fallbackSelect(\n Array.from({ length: messageCount }, () => ({ role: 'user', content: '' }) as Message),\n this.maxContextTokens,\n );\n }\n\n const obj = parsed as Record<string, unknown>;\n const kept =\n (obj.kept as Array<{ from: number; to: number; importance: string }> | undefined) ?? [];\n const collapsed =\n (obj.collapsed as Array<{ from: number; to: number; summary?: string }> | undefined) ?? [];\n\n return {\n kept: kept.map((k) => ({\n from: k.from,\n to: k.to,\n importance: (k.importance ?? 'medium') as 'critical' | 'high' | 'medium',\n })),\n collapsed: collapsed.map((c) => ({ from: c.from, to: c.to, summary: c.summary })),\n reasoning: typeof obj.reasoning === 'string' ? obj.reasoning : '',\n };\n }\n}\n"]}
|
package/dist/security/index.js
CHANGED
|
@@ -192,7 +192,7 @@ function walk(node, vault, transform) {
|
|
|
192
192
|
if (Array.isArray(node)) {
|
|
193
193
|
return node.map((item) => walk(item, vault, transform));
|
|
194
194
|
}
|
|
195
|
-
const out =
|
|
195
|
+
const out = /* @__PURE__ */ Object.create(null);
|
|
196
196
|
for (const [k, v] of Object.entries(node)) {
|
|
197
197
|
if (typeof v === "string" && isSecretField(k)) {
|
|
198
198
|
out[k] = transform(v, k);
|
|
@@ -364,7 +364,11 @@ function getCachedGlob(pattern) {
|
|
|
364
364
|
COMPILED_GLOB_CACHE.set(pattern, re);
|
|
365
365
|
return re;
|
|
366
366
|
}
|
|
367
|
+
var MAX_GLOB_PATTERN_LEN = 1024;
|
|
367
368
|
function compileGlob(pattern) {
|
|
369
|
+
if (pattern.length > MAX_GLOB_PATTERN_LEN) {
|
|
370
|
+
throw new Error(`Glob pattern exceeds ${MAX_GLOB_PATTERN_LEN} characters`);
|
|
371
|
+
}
|
|
368
372
|
let i = 0;
|
|
369
373
|
let re = "^";
|
|
370
374
|
while (i < pattern.length) {
|
|
@@ -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 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
|
+
{"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';\r\nimport * as fs from 'node:fs';\r\nimport * as fsp from 'node:fs/promises';\r\nimport * as path from 'node:path';\r\nimport type { SecretVault } from '../types/secret-vault.js';\r\nimport { ENCRYPTED_PREFIX } from '../types/secret-vault.js';\r\n\r\nexport interface SecretVaultOptions {\r\n /** Absolute path to the key file. Created with mode 0o600 if missing. */\r\n keyFile: string;\r\n}\r\n\r\nconst KEY_BYTES = 32;\r\nconst IV_BYTES = 12;\r\nconst TAG_BYTES = 16;\r\nconst ALGO = 'aes-256-gcm';\r\n\r\n/**\r\n * Default vault: AES-256-GCM with a key stored at `keyFile` (mode 0o600).\r\n * The key is loaded lazily on first encrypt/decrypt; if it does not exist,\r\n * a fresh one is generated. Decryption of plaintext values is a no-op so\r\n * legacy configs continue to work.\r\n */\r\nexport class DefaultSecretVault implements SecretVault {\r\n private readonly keyFile: string;\r\n private key?: Buffer;\r\n\r\n constructor(opts: SecretVaultOptions) {\r\n this.keyFile = opts.keyFile;\r\n }\r\n\r\n isEncrypted(value: string): boolean {\r\n return typeof value === 'string' && value.startsWith(ENCRYPTED_PREFIX);\r\n }\r\n\r\n encrypt(plaintext: string): string {\r\n if (this.isEncrypted(plaintext)) return plaintext;\r\n const key = this.loadOrCreateKey();\r\n const iv = randomBytes(IV_BYTES);\r\n const cipher = createCipheriv(ALGO, key, iv);\r\n const ct = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);\r\n const tag = cipher.getAuthTag();\r\n return `${ENCRYPTED_PREFIX}${iv.toString('base64')}:${tag.toString('base64')}:${ct.toString('base64')}`;\r\n }\r\n\r\n decrypt(value: string): string {\r\n if (!this.isEncrypted(value)) return value;\r\n const rest = value.slice(ENCRYPTED_PREFIX.length);\r\n const parts = rest.split(':');\r\n if (parts.length !== 3) {\r\n throw new Error('SecretVault: malformed encrypted value');\r\n }\r\n const [ivB64, tagB64, ctB64] = parts as [string, string, string];\r\n const iv = Buffer.from(ivB64, 'base64');\r\n const tag = Buffer.from(tagB64, 'base64');\r\n const ct = Buffer.from(ctB64, 'base64');\r\n if (iv.length !== IV_BYTES) throw new Error('SecretVault: bad IV length');\r\n if (tag.length !== TAG_BYTES) throw new Error('SecretVault: bad tag length');\r\n const key = this.loadOrCreateKey();\r\n const decipher = createDecipheriv(ALGO, key, iv);\r\n decipher.setAuthTag(tag);\r\n const pt = Buffer.concat([decipher.update(ct), decipher.final()]);\r\n return pt.toString('utf8');\r\n }\r\n\r\n private loadOrCreateKey(): Buffer {\r\n if (this.key) return this.key;\r\n try {\r\n const buf = fs.readFileSync(this.keyFile);\r\n if (buf.length !== KEY_BYTES) {\r\n throw new Error(`SecretVault: key file ${this.keyFile} has wrong size`);\r\n }\r\n this.key = buf;\r\n return this.key;\r\n } catch (err) {\r\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;\r\n }\r\n // Create a fresh key. Use sync APIs so the constructor-free getter\r\n // remains synchronous from the caller's perspective.\r\n fs.mkdirSync(path.dirname(this.keyFile), { recursive: true });\r\n const key = randomBytes(KEY_BYTES);\r\n // Use exclusive-create flag 'wx' to prevent races: if two processes race\r\n // to create the key file, only one succeeds and the loser gets EEXIST.\r\n try {\r\n fs.writeFileSync(this.keyFile, key, { mode: 0o600, flag: 'wx' });\r\n } catch (err) {\r\n if ((err as NodeJS.ErrnoException).code !== 'EEXIST') throw err;\r\n // Another process won the race — re-read what they wrote.\r\n const buf = fs.readFileSync(this.keyFile);\r\n if (buf.length !== KEY_BYTES) {\r\n throw new Error(`SecretVault: key file ${this.keyFile} has wrong size`);\r\n }\r\n this.key = buf;\r\n return this.key;\r\n }\r\n this.key = key;\r\n return key;\r\n }\r\n}\r\n\r\n/**\r\n * Walk a Config-shaped object and decrypt any apiKey-like fields in place,\r\n * returning a new object. Used by the config loader so the rest of the\r\n * system never has to know about the wire format.\r\n */\r\nexport function decryptConfigSecrets<T>(cfg: T, vault: SecretVault): T {\r\n // A single corrupted/malformed encrypted field should not kill the entire\r\n // config load. Swallow per-field decrypt errors (zero the field so callers\r\n // see \"missing key\" instead of holding ciphertext) and surface a warning.\r\n return walk(cfg, vault, (v, key) => {\r\n try {\r\n return vault.decrypt(v);\r\n } catch (err) {\r\n console.warn(\r\n `[secret-vault] Failed to decrypt \"${key}\":`,\r\n err instanceof Error ? err.message : err,\r\n );\r\n return '';\r\n }\r\n });\r\n}\r\n\r\nexport function encryptConfigSecrets<T>(cfg: T, vault: SecretVault): T {\r\n return walk(cfg, vault, (v) => vault.encrypt(v));\r\n}\r\n\r\nfunction walk<T>(node: T, vault: SecretVault, transform: (s: string, key: string) => string): T {\r\n if (node === null || node === undefined) return node;\r\n if (typeof node !== 'object') return node;\r\n if (Array.isArray(node)) {\r\n return node.map((item) => walk(item, vault, transform)) as unknown as T;\r\n }\r\n const out: Record<string, unknown> = Object.create(null);\r\n for (const [k, v] of Object.entries(node as Record<string, unknown>)) {\r\n if (typeof v === 'string' && isSecretField(k)) {\r\n out[k] = transform(v, k);\r\n } else if (typeof v === 'object' && v !== null) {\r\n out[k] = walk(v, vault, transform);\r\n } else {\r\n out[k] = v;\r\n }\r\n }\r\n return out as T;\r\n}\r\n\r\n/**\r\n * A key is treated as secret-bearing if its name (case-insensitive) contains\r\n * one of these tokens. Captures common variants like `apiKey`, `authToken`,\r\n * `refreshToken`, `sessionKey`, `password`, `client_secret`, `bearer`, etc.\r\n * Use a named field with `isSecret: false` annotation if you must opt out —\r\n * see `NON_SECRET_OVERRIDES` below.\r\n */\r\nconst SECRET_KEY_PATTERN =\r\n /(?:apikey|api_key|authtoken|auth_token|bearer|secret|password|passwd|pwd|refreshtoken|refresh_token|sessionkey|session_key|access[_-]?token|private[_-]?key)/i;\r\n\r\n// Field names that contain the literal substring \"key\" but are not secrets.\r\n// Keep this list short; the substring rule itself is intentionally narrow.\r\nconst NON_SECRET_OVERRIDES = new Set(['publickey', 'public_key']);\r\n\r\nfunction isSecretField(name: string): boolean {\r\n const lc = name.toLowerCase();\r\n if (NON_SECRET_OVERRIDES.has(lc)) return false;\r\n return SECRET_KEY_PATTERN.test(lc);\r\n}\r\n\r\n/**\r\n * Re-write `~/.wrongstack/config.json` (or any path) with all secret-bearing\r\n * fields encrypted. Used by the `wstack auth` subcommand.\r\n */\r\nexport async function rewriteConfigEncrypted(\r\n configPath: string,\r\n vault: SecretVault,\r\n patch?: Record<string, unknown>,\r\n): Promise<void> {\r\n let current: Record<string, unknown> = {};\r\n try {\r\n const raw = await fsp.readFile(configPath, 'utf8');\r\n current = JSON.parse(raw) as Record<string, unknown>;\r\n } catch {\r\n // start from empty\r\n }\r\n const merged = deepMerge(current, patch ?? {});\r\n const encrypted = encryptConfigSecrets(merged, vault);\r\n await fsp.mkdir(path.dirname(configPath), { recursive: true });\r\n await fsp.writeFile(configPath, JSON.stringify(encrypted, null, 2), { mode: 0o600 });\r\n try {\r\n await fsp.chmod(configPath, 0o600);\r\n } catch {\r\n // best-effort on Windows\r\n }\r\n}\r\n\r\n/**\r\n * Scan a config file on disk for plaintext secret-bearing fields and\r\n * rewrite the file with them encrypted in place. Returns a count of how\r\n * many fields were migrated. Idempotent — calling on a fully-encrypted\r\n * file is a no-op and writes nothing. Used by the CLI on every boot so\r\n * users who had plaintext keys before the vault landed are upgraded\r\n * transparently.\r\n */\r\nexport async function migratePlaintextSecrets(\r\n configPath: string,\r\n vault: SecretVault,\r\n): Promise<{ migrated: number; file: string }> {\r\n let raw: string;\r\n try {\r\n raw = await fsp.readFile(configPath, 'utf8');\r\n } catch {\r\n return { migrated: 0, file: configPath };\r\n }\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(raw);\r\n } catch {\r\n return { migrated: 0, file: configPath };\r\n }\r\n const counter = { n: 0 };\r\n const migrated = walkCount(parsed, vault, counter);\r\n if (counter.n === 0) return { migrated: 0, file: configPath };\r\n await fsp.writeFile(configPath, JSON.stringify(migrated, null, 2), { mode: 0o600 });\r\n try {\r\n await fsp.chmod(configPath, 0o600);\r\n } catch {\r\n // best-effort on Windows\r\n }\r\n return { migrated: counter.n, file: configPath };\r\n}\r\n\r\nfunction walkCount<T>(node: T, vault: SecretVault, counter: { n: number }): T {\r\n if (node === null || node === undefined) return node;\r\n if (typeof node !== 'object') return node;\r\n if (Array.isArray(node)) {\r\n return node.map((item) => walkCount(item, vault, counter)) as unknown as T;\r\n }\r\n const out: Record<string, unknown> = {};\r\n for (const [k, v] of Object.entries(node as Record<string, unknown>)) {\r\n if (typeof v === 'string' && isSecretField(k) && !vault.isEncrypted(v) && v.length > 0) {\r\n out[k] = vault.encrypt(v);\r\n counter.n++;\r\n } else if (typeof v === 'object' && v !== null) {\r\n out[k] = walkCount(v, vault, counter);\r\n } else {\r\n out[k] = v;\r\n }\r\n }\r\n return out as T;\r\n}\r\n\r\n/** Keys that, when written into a plain object, can poison the prototype\r\n * chain. We never want user config to carry these. */\r\nconst FORBIDDEN_PROTO_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\r\n\r\nfunction deepMerge<T extends Record<string, unknown>>(a: T, b: Record<string, unknown>): T {\r\n const out: Record<string, unknown> = { ...a };\r\n for (const [k, v] of Object.entries(b)) {\r\n if (FORBIDDEN_PROTO_KEYS.has(k)) continue;\r\n const existing = out[k];\r\n if (\r\n v !== null &&\r\n typeof v === 'object' &&\r\n !Array.isArray(v) &&\r\n existing !== null &&\r\n typeof existing === 'object' &&\r\n !Array.isArray(existing)\r\n ) {\r\n out[k] = deepMerge(existing as Record<string, unknown>, v as Record<string, unknown>);\r\n } else {\r\n out[k] = v;\r\n }\r\n }\r\n return out as T;\r\n}\r\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","/**\r\n * Minimal glob matcher for trust patterns.\r\n * Supports: *, **, ?, character classes [abc], [a-z], negation [!...] or [^...].\r\n *\r\n * Compiled regexes are cached so repeated calls with the same pattern\r\n * avoid recompilation overhead.\r\n */\r\n\r\nfunction escapeRegex(s: string): string {\r\n return s.replace(/[.+^${}()|\\\\]/g, '\\\\$&');\r\n}\r\n\r\n// Module-level cache to avoid recompiling the same pattern on every call.\r\n// LRU-ish eviction keeps unbounded growth in check for long-running processes.\r\nconst COMPILED_GLOB_CACHE = new Map<string, RegExp>();\r\nconst CACHE_MAX_SIZE = 2000;\r\n\r\nfunction getCachedGlob(pattern: string): RegExp {\r\n const cached = COMPILED_GLOB_CACHE.get(pattern);\r\n if (cached) return cached;\r\n if (COMPILED_GLOB_CACHE.size >= CACHE_MAX_SIZE) {\r\n // Evict oldest 25% when at capacity\r\n const keys = [...COMPILED_GLOB_CACHE.keys()];\r\n for (let i = 0; i < Math.floor(CACHE_MAX_SIZE / 4); i++) {\r\n COMPILED_GLOB_CACHE.delete(keys[i]!);\r\n }\r\n }\r\n const re = compileGlob(pattern);\r\n COMPILED_GLOB_CACHE.set(pattern, re);\r\n return re;\r\n}\r\n\r\n// Cap glob pattern length to prevent excessively long compiled regexes.\r\nconst MAX_GLOB_PATTERN_LEN = 1024;\r\n\r\nexport function compileGlob(pattern: string): RegExp {\r\n if (pattern.length > MAX_GLOB_PATTERN_LEN) {\r\n throw new Error(`Glob pattern exceeds ${MAX_GLOB_PATTERN_LEN} characters`);\r\n }\r\n let i = 0;\r\n let re = '^';\r\n while (i < pattern.length) {\r\n const c = pattern[i];\r\n if (c === '*') {\r\n if (pattern[i + 1] === '*') {\r\n // ** matches any number of chars including /\r\n re += '.*';\r\n i += 2;\r\n // Skip trailing slash so '**/x' matches 'x'\r\n if (pattern[i] === '/') i++;\r\n } else {\r\n // single * matches any chars except /\r\n re += '[^/]*';\r\n i++;\r\n }\r\n } else if (c === '?') {\r\n re += '[^/]';\r\n i++;\r\n } else if (c === '[') {\r\n let cls = '[';\r\n i++;\r\n if (pattern[i] === '!' || pattern[i] === '^') {\r\n cls += '^';\r\n i++;\r\n }\r\n while (i < pattern.length && pattern[i] !== ']') {\r\n const ch = pattern[i] ?? '';\r\n // Inside a regex class, only `]`, `\\`, and `^`/`-` at boundaries need\r\n // escaping. We've already consumed the leading `^`; the rest are\r\n // literal. Escape `\\` defensively and pass the rest through verbatim\r\n // so ranges like `a-z` continue to work.\r\n if (ch === '\\\\') {\r\n cls += '\\\\\\\\';\r\n } else if (ch === ']' || ch === '^') {\r\n cls += `\\\\${ch}`;\r\n } else {\r\n cls += ch;\r\n }\r\n i++;\r\n }\r\n cls += ']';\r\n re += cls;\r\n i++; // skip closing ]\r\n } else {\r\n re += escapeRegex(c ?? '');\r\n i++;\r\n }\r\n }\r\n re += '$';\r\n return new RegExp(re);\r\n}\r\n\r\nexport function matchGlob(pattern: string, input: string): boolean {\r\n return getCachedGlob(pattern).test(input);\r\n}\r\n\r\nexport function matchAny(patterns: string[], input: string): boolean {\r\n return patterns.some((p) => matchGlob(p, input));\r\n}\r\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"]}
|