@neotx/core 0.1.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/index.d.ts +1359 -0
- package/dist/index.js +3190 -0
- package/dist/index.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/agents/loader.ts","../src/agents/schema.ts","../src/agents/registry.ts","../src/agents/resolver.ts","../src/concurrency/queue.ts","../src/concurrency/semaphore.ts","../src/config.ts","../src/paths.ts","../src/cost/journal.ts","../src/events/emitter.ts","../src/events/journal.ts","../src/events/webhook.ts","../src/isolation/git.ts","../src/isolation/git-mutex.ts","../src/isolation/sandbox.ts","../src/isolation/worktree.ts","../src/middleware/audit-log.ts","../src/middleware/budget-guard.ts","../src/middleware/chain.ts","../src/middleware/loop-detection.ts","../src/orchestrator.ts","../src/runner/output-parser.ts","../src/runner/session.ts","../src/runner/recovery.ts","../src/workflows/registry.ts","../src/workflows/loader.ts","../src/supervisor/schemas.ts","../src/supervisor/activity-log.ts","../src/supervisor/daemon.ts","../src/supervisor/event-queue.ts","../src/supervisor/heartbeat.ts","../src/supervisor/memory.ts","../src/supervisor/prompt-builder.ts","../src/supervisor/webhook-server.ts","../src/index.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\nimport type { AgentConfig } from \"@/agents/schema\";\nimport { agentConfigSchema } from \"@/agents/schema\";\n\n/**\n * Load a single agent definition from a YAML file.\n * If the `prompt` field points to a .md file, resolve it relative\n * to the YAML file's directory and read its content.\n */\nexport async function loadAgentFile(filePath: string): Promise<AgentConfig> {\n let raw: string;\n try {\n raw = await readFile(filePath, \"utf-8\");\n } catch {\n throw new Error(`Agent file not found: ${filePath}`);\n }\n\n let parsed: unknown;\n try {\n parsed = parseYaml(raw);\n } catch (err) {\n throw new Error(\n `Invalid YAML in agent file ${filePath}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n const result = agentConfigSchema.safeParse(parsed);\n if (!result.success) {\n const issues = result.error.issues\n .map((i) => ` - ${i.path.join(\".\")}: ${i.message}`)\n .join(\"\\n\");\n throw new Error(`Invalid agent config in ${filePath}:\\n${issues}`);\n }\n\n const config = result.data;\n\n // If prompt points to a .md file, read it\n if (config.prompt?.endsWith(\".md\")) {\n const promptPath = path.resolve(path.dirname(filePath), config.prompt);\n try {\n config.prompt = await readFile(promptPath, \"utf-8\");\n } catch {\n throw new Error(`Prompt file not found: ${promptPath} (referenced in ${filePath})`);\n }\n }\n\n return config;\n}\n","import { z } from \"zod\";\n\n// ─── Agent model enum ────────────────────────────────────\n\nexport const agentModelSchema = z.enum([\"opus\", \"sonnet\", \"haiku\"]);\n\n// ─── Agent tool enum ─────────────────────────────────────\n\nexport const agentToolSchema = z.enum([\n \"Read\",\n \"Write\",\n \"Edit\",\n \"Bash\",\n \"Glob\",\n \"Grep\",\n \"Agent\",\n \"WebSearch\",\n \"WebFetch\",\n \"NotebookEdit\",\n]);\n\n// ─── Agent tool entry (tool or $inherited token) ─────────\n\nexport const agentToolEntrySchema = z.union([agentToolSchema, z.literal(\"$inherited\")]);\n\n// ─── Agent sandbox enum ──────────────────────────────────\n\nexport const agentSandboxSchema = z.enum([\"writable\", \"readonly\"]);\n\n// ─── AgentConfig schema (from YAML) ─────────────────────\n\nexport const agentConfigSchema = z.object({\n name: z.string(),\n extends: z.string().optional(),\n description: z.string().optional(),\n model: agentModelSchema.optional(),\n tools: z.array(agentToolEntrySchema).optional(),\n prompt: z.string().optional(),\n promptAppend: z.string().optional(),\n sandbox: agentSandboxSchema.optional(),\n maxTurns: z.number().optional(),\n mcpServers: z.array(z.string()).optional(),\n});\n\n// ─── Derived types ───────────────────────────────────────\n\nexport type AgentConfig = z.infer<typeof agentConfigSchema>;\nexport type AgentModel = z.infer<typeof agentModelSchema>;\nexport type AgentTool = z.infer<typeof agentToolSchema>;\nexport type AgentToolEntry = z.infer<typeof agentToolEntrySchema>;\n","import { readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { loadAgentFile } from \"@/agents/loader\";\nimport { resolveAgent } from \"@/agents/resolver\";\nimport type { AgentConfig } from \"@/agents/schema\";\nimport type { ResolvedAgent } from \"@/types\";\n\nexport class AgentRegistry {\n private readonly builtInDir: string;\n private readonly customDir: string | undefined;\n private agents = new Map<string, ResolvedAgent>();\n\n constructor(builtInDir: string, customDir?: string) {\n this.builtInDir = builtInDir;\n this.customDir = customDir;\n }\n\n async load(): Promise<void> {\n this.agents.clear();\n\n // Load built-in agents\n const builtInConfigs = await loadAgentsFromDir(this.builtInDir);\n const builtInMap = new Map<string, AgentConfig>();\n for (const config of builtInConfigs) {\n builtInMap.set(config.name, config);\n }\n\n // Resolve built-in agents\n for (const config of builtInConfigs) {\n const resolved = resolveAgent(config, builtInMap);\n // Force built-in source for agents loaded from the built-in dir\n this.agents.set(config.name, { ...resolved, source: \"built-in\" });\n }\n\n // Load custom agents (if directory exists)\n if (this.customDir) {\n let customConfigs: AgentConfig[];\n try {\n customConfigs = await loadAgentsFromDir(this.customDir);\n } catch {\n // Custom dir doesn't exist — that's fine\n customConfigs = [];\n }\n\n for (const config of customConfigs) {\n const resolved = resolveAgent(config, builtInMap);\n this.agents.set(config.name, resolved);\n }\n }\n }\n\n get(name: string): ResolvedAgent | undefined {\n return this.agents.get(name);\n }\n\n list(): ResolvedAgent[] {\n return [...this.agents.values()];\n }\n\n has(name: string): boolean {\n return this.agents.has(name);\n }\n}\n\nasync function loadAgentsFromDir(dir: string): Promise<AgentConfig[]> {\n const entries = await readdir(dir);\n const ymlFiles = entries.filter((f) => f.endsWith(\".yml\") || f.endsWith(\".yaml\"));\n\n const configs: AgentConfig[] = [];\n for (const file of ymlFiles) {\n const config = await loadAgentFile(path.join(dir, file));\n configs.push(config);\n }\n return configs;\n}\n","import type { AgentConfig, AgentTool } from \"@/agents/schema\";\nimport type { AgentDefinition, ResolvedAgent } from \"@/types\";\n\n/**\n * Resolve an agent config into a fully-merged ResolvedAgent.\n *\n * Resolution rules:\n * 1. No `extends` → agent must define all required fields\n * 2. With `extends: \"developer\"` → start from built-in, apply overrides\n * 3. Same name as built-in without `extends:` → treated as `extends: <name>` implicitly\n */\nexport function resolveAgent(\n config: AgentConfig,\n builtIns: Map<string, AgentConfig>,\n): ResolvedAgent {\n const extendsName =\n config.extends ??\n (builtIns.has(config.name) && config.extends === undefined ? config.name : undefined);\n const isExtending = extendsName !== undefined;\n\n if (isExtending) {\n const base = builtIns.get(extendsName);\n if (!base) {\n throw new Error(\n `Agent \"${config.name}\" extends \"${extendsName}\", but no built-in agent with that name exists.`,\n );\n }\n\n // Merge tools\n let tools: string[];\n if (config.tools) {\n if (config.tools.includes(\"$inherited\")) {\n // Keep inherited tools + add new ones\n const baseTols = base.tools ?? [];\n const newTools = config.tools.filter((t) => t !== \"$inherited\");\n tools = [...baseTols, ...newTools] as string[];\n } else {\n // Full replacement\n tools = config.tools as string[];\n }\n } else {\n tools = (base.tools ?? []) as string[];\n }\n\n // Merge prompt\n let prompt: string;\n if (config.prompt) {\n prompt = config.prompt;\n } else {\n prompt = base.prompt ?? \"\";\n }\n if (config.promptAppend) {\n prompt = `${prompt}\\n\\n${config.promptAppend}`;\n }\n\n const definition: AgentDefinition = {\n description: config.description ?? base.description ?? \"\",\n prompt,\n tools,\n model: config.model ?? base.model ?? \"sonnet\",\n };\n\n return {\n name: config.name,\n definition,\n sandbox: config.sandbox ?? base.sandbox ?? \"readonly\",\n ...(config.maxTurns !== undefined\n ? { maxTurns: config.maxTurns }\n : base.maxTurns !== undefined\n ? { maxTurns: base.maxTurns }\n : {}),\n source: config.name === extendsName && !config.extends ? \"built-in\" : \"extended\",\n };\n }\n\n // No extends — fully custom agent\n if (!config.description) {\n throw new Error(\n `Agent \"${config.name}\" has no \"extends\" and no \"description\". Add a 'description' field to the agent YAML.`,\n );\n }\n if (!config.model) {\n throw new Error(\n `Agent \"${config.name}\" has no \"extends\" and no \"model\". Add a 'model' field (e.g., 'claude-sonnet-4-20250514').`,\n );\n }\n if (!config.tools) {\n throw new Error(\n `Agent \"${config.name}\" has no \"extends\" and no \"tools\". Add a 'tools' array to the agent YAML.`,\n );\n }\n if (!config.sandbox) {\n throw new Error(\n `Agent \"${config.name}\" has no \"extends\" and no \"sandbox\". Add a 'sandbox' field ('full' or 'permissive').`,\n );\n }\n if (!config.prompt) {\n throw new Error(\n `Agent \"${config.name}\" has no \"extends\" and no \"prompt\". Add a 'prompt' field or 'promptFile' reference.`,\n );\n }\n\n // Filter out $inherited from tools (shouldn't be there without extends, but be safe)\n const tools = config.tools.filter((t): t is AgentTool => t !== \"$inherited\");\n\n let prompt = config.prompt;\n if (config.promptAppend) {\n prompt = `${prompt}\\n\\n${config.promptAppend}`;\n }\n\n const definition: AgentDefinition = {\n description: config.description,\n prompt,\n tools,\n model: config.model,\n };\n\n return {\n name: config.name,\n definition,\n sandbox: config.sandbox,\n ...(config.maxTurns !== undefined ? { maxTurns: config.maxTurns } : {}),\n source: \"custom\",\n };\n}\n","import type { Priority } from \"@/types\";\n\nconst PRIORITY_ORDER: Record<Priority, number> = {\n critical: 0,\n high: 1,\n medium: 2,\n low: 3,\n};\n\ninterface QueueItem<T> {\n value: T;\n priority: Priority;\n insertionOrder: number;\n}\n\n/**\n * FIFO priority queue. Items with higher priority (critical > high > medium > low)\n * are dequeued first. Within the same priority level, FIFO order is maintained.\n */\nexport class PriorityQueue<T> {\n private readonly items: QueueItem<T>[] = [];\n private readonly maxSize: number;\n private insertionCounter = 0;\n\n constructor(maxSize: number) {\n this.maxSize = maxSize;\n }\n\n enqueue(value: T, priority: Priority): void {\n // Reset counter when queue is empty to prevent overflow after prolonged use\n if (this.items.length === 0) {\n this.insertionCounter = 0;\n }\n\n if (this.items.length >= this.maxSize) {\n throw new Error(`Queue full (${this.maxSize} items). Cannot enqueue.`);\n }\n\n const item: QueueItem<T> = {\n value,\n priority,\n insertionOrder: this.insertionCounter++,\n };\n\n // Insert in sorted position (binary search would be overkill for queue sizes ≤ 50)\n let inserted = false;\n for (let i = 0; i < this.items.length; i++) {\n const existing = this.items[i];\n if (existing && this.comparePriority(item, existing) < 0) {\n this.items.splice(i, 0, item);\n inserted = true;\n break;\n }\n }\n if (!inserted) {\n this.items.push(item);\n }\n }\n\n dequeue(): T | undefined {\n const item = this.items.shift();\n return item?.value;\n }\n\n peek(): T | undefined {\n return this.items[0]?.value;\n }\n\n get size(): number {\n return this.items.length;\n }\n\n get isEmpty(): boolean {\n return this.items.length === 0;\n }\n\n remove(predicate: (item: T) => boolean): boolean {\n const index = this.items.findIndex((entry) => predicate(entry.value));\n if (index === -1) return false;\n this.items.splice(index, 1);\n return true;\n }\n\n /** Dequeue the first item matching the predicate (respects priority order). */\n dequeueWhere(predicate: (item: T) => boolean): T | undefined {\n const index = this.items.findIndex((entry) => predicate(entry.value));\n if (index === -1) return undefined;\n const removed = this.items.splice(index, 1)[0];\n if (!removed) return undefined;\n return removed.value;\n }\n\n /** Compare by priority first, then by insertion order (FIFO within same priority). */\n private comparePriority(a: QueueItem<T>, b: QueueItem<T>): number {\n const priorityDiff = PRIORITY_ORDER[a.priority] - PRIORITY_ORDER[b.priority];\n if (priorityDiff !== 0) return priorityDiff;\n return a.insertionOrder - b.insertionOrder;\n }\n}\n","import { PriorityQueue } from \"@/concurrency/queue\";\nimport type { Priority } from \"@/types\";\n\nexport interface SemaphoreConfig {\n maxSessions: number;\n maxPerRepo: number;\n queueMax?: number;\n}\n\nexport interface SemaphoreCallbacks {\n onEnqueue?: (sessionId: string, repo: string, position: number) => void;\n onDequeue?: (sessionId: string, repo: string, waitedMs: number) => void;\n}\n\ninterface WaitingEntry {\n sessionId: string;\n repo: string;\n resolve: () => void;\n reject: (reason: unknown) => void;\n enqueuedAt: number;\n _cleanupAbort?: () => void;\n}\n\n/**\n * Concurrency semaphore with global + per-repo limits and a priority queue.\n * When at capacity, `acquire()` blocks until a slot is available.\n */\nexport class Semaphore {\n private readonly maxSessions: number;\n private readonly maxPerRepo: number;\n private readonly queue: PriorityQueue<WaitingEntry>;\n private readonly callbacks: SemaphoreCallbacks;\n\n // sessionId → repo\n private readonly activeSessions = new Map<string, string>();\n // repo → count\n private readonly repoCounts = new Map<string, number>();\n\n constructor(config: SemaphoreConfig, callbacks: SemaphoreCallbacks = {}) {\n this.maxSessions = config.maxSessions;\n this.maxPerRepo = config.maxPerRepo;\n this.queue = new PriorityQueue<WaitingEntry>(config.queueMax ?? 50);\n this.callbacks = callbacks;\n }\n\n /**\n * Acquire a slot. Blocks (via promise) if at capacity.\n * Throws if the queue is full.\n */\n async acquire(\n repo: string,\n sessionId: string,\n priority: Priority = \"medium\",\n signal?: AbortSignal,\n ): Promise<void> {\n if (signal?.aborted) {\n throw signal.reason ?? new DOMException(\"The operation was aborted.\", \"AbortError\");\n }\n\n if (this.canAcquire(repo)) {\n this.allocate(repo, sessionId);\n return;\n }\n\n return new Promise<void>((resolve, reject) => {\n const entry: WaitingEntry = {\n sessionId,\n repo,\n resolve,\n reject,\n enqueuedAt: Date.now(),\n };\n\n this.queue.enqueue(entry, priority);\n this.callbacks.onEnqueue?.(sessionId, repo, this.queue.size);\n\n if (signal) {\n const onAbort = () => {\n this.queue.remove((e) => e === entry);\n reject(signal.reason ?? new DOMException(\"The operation was aborted.\", \"AbortError\"));\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n\n // Store cleanup so we can remove the listener on normal dequeue\n entry._cleanupAbort = () => signal.removeEventListener(\"abort\", onAbort);\n }\n });\n }\n\n /** Release a slot and process the next waiting entry. */\n release(sessionId: string): void {\n const repo = this.activeSessions.get(sessionId);\n if (!repo) return;\n\n this.activeSessions.delete(sessionId);\n const count = this.repoCounts.get(repo) ?? 0;\n if (count <= 1) {\n this.repoCounts.delete(repo);\n } else {\n this.repoCounts.set(repo, count - 1);\n }\n\n this.processQueue();\n }\n\n /** Non-blocking attempt to acquire a slot. Returns true if successful. */\n tryAcquire(repo: string, sessionId: string): boolean {\n if (!this.canAcquire(repo)) return false;\n this.allocate(repo, sessionId);\n return true;\n }\n\n /** Total number of active slots. */\n activeCount(): number {\n return this.activeSessions.size;\n }\n\n /** Number of active slots for a specific repo. */\n activeCountForRepo(repo: string): number {\n return this.repoCounts.get(repo) ?? 0;\n }\n\n /** Can a slot be acquired for this repo without blocking? */\n isAvailable(repo: string): boolean {\n return this.canAcquire(repo);\n }\n\n /** Current queue depth. */\n queueDepth(): number {\n return this.queue.size;\n }\n\n private canAcquire(repo: string): boolean {\n if (this.activeSessions.size >= this.maxSessions) return false;\n const repoCount = this.repoCounts.get(repo) ?? 0;\n return repoCount < this.maxPerRepo;\n }\n\n private allocate(repo: string, sessionId: string): void {\n this.activeSessions.set(sessionId, repo);\n this.repoCounts.set(repo, (this.repoCounts.get(repo) ?? 0) + 1);\n }\n\n private processQueue(): void {\n // Find the highest-priority entry whose repo has capacity\n const entry = this.queue.dequeueWhere((e) => this.canAcquire(e.repo));\n if (!entry) return;\n\n this.allocate(entry.repo, entry.sessionId);\n entry._cleanupAbort?.();\n const waitedMs = Date.now() - entry.enqueuedAt;\n this.callbacks.onDequeue?.(entry.sessionId, entry.repo, waitedMs);\n entry.resolve();\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { z } from \"zod\";\nimport { getDataDir, toRepoSlug } from \"@/paths\";\n\n// ─── McpServerConfig schemas ─────────────────────────────\n\nconst httpMcpServerSchema = z.object({\n type: z.literal(\"http\"),\n url: z.string(),\n headers: z.record(z.string(), z.string()).optional(),\n});\n\nconst stdioMcpServerSchema = z.object({\n type: z.literal(\"stdio\"),\n command: z.string(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n});\n\nexport const mcpServerConfigSchema = z.discriminatedUnion(\"type\", [\n httpMcpServerSchema,\n stdioMcpServerSchema,\n]);\n\n// ─── RepoConfig schema (single repo entry) ──────────────\n\nexport const repoConfigSchema = z.object({\n path: z.string(),\n name: z.string().optional(),\n defaultBranch: z.string().default(\"main\"),\n branchPrefix: z.string().default(\"feat\"),\n pushRemote: z.string().default(\"origin\"),\n autoCreatePr: z.boolean().default(false),\n prBaseBranch: z.string().optional(),\n});\n\n// ─── Global config schema (~/.neo/config.yml) ───────────\n// This is now the single source of truth — repos are registered here.\n\nexport const globalConfigSchema = z.object({\n repos: z.array(repoConfigSchema).default([]),\n\n concurrency: z\n .object({\n maxSessions: z.number().default(5),\n maxPerRepo: z.number().default(2),\n queueMax: z.number().default(50),\n })\n .default({ maxSessions: 5, maxPerRepo: 2, queueMax: 50 }),\n\n budget: z\n .object({\n dailyCapUsd: z.number().default(500),\n alertThresholdPct: z.number().default(80),\n })\n .default({ dailyCapUsd: 500, alertThresholdPct: 80 }),\n\n recovery: z\n .object({\n maxRetries: z.number().default(3),\n backoffBaseMs: z.number().default(30_000),\n })\n .default({ maxRetries: 3, backoffBaseMs: 30_000 }),\n\n sessions: z\n .object({\n initTimeoutMs: z.number().default(120_000),\n maxDurationMs: z.number().default(3_600_000),\n })\n .default({ initTimeoutMs: 120_000, maxDurationMs: 3_600_000 }),\n\n webhooks: z\n .array(\n z.object({\n url: z.string().url(),\n events: z.array(z.string()).optional(),\n secret: z.string().optional(),\n timeoutMs: z.number().default(5000),\n }),\n )\n .default([]),\n\n supervisor: z\n .object({\n port: z.number().default(7777),\n secret: z.string().optional(),\n idleIntervalMs: z.number().default(60_000),\n heartbeatTimeoutMs: z.number().default(300_000),\n maxConsecutiveFailures: z.number().default(3),\n maxEventsPerSec: z.number().default(10),\n dailyCapUsd: z.number().default(50),\n instructions: z.string().optional(),\n })\n .default({\n port: 7777,\n idleIntervalMs: 60_000,\n heartbeatTimeoutMs: 300_000,\n maxConsecutiveFailures: 3,\n maxEventsPerSec: 10,\n dailyCapUsd: 50,\n }),\n\n mcpServers: z.record(z.string(), mcpServerConfigSchema).optional(),\n claudeCodePath: z.string().optional(),\n\n idempotency: z\n .object({\n enabled: z.boolean().default(true),\n key: z.enum([\"metadata\", \"prompt\"]).default(\"metadata\"),\n ttlMs: z.number().default(3_600_000),\n })\n .optional(),\n});\n\n// ─── NeoConfig = GlobalConfig (single schema now) ────────\n\nexport const neoConfigSchema = globalConfigSchema;\n\n// ─── Derived types ───────────────────────────────────────\n\nexport type NeoConfig = z.infer<typeof neoConfigSchema>;\nexport type GlobalConfig = NeoConfig;\nexport type RepoConfig = z.infer<typeof repoConfigSchema>;\nexport type RepoConfigInput = z.input<typeof repoConfigSchema>;\nexport type McpServerConfig = z.infer<typeof mcpServerConfigSchema>;\n\n// ─── Default global config ──────────────────────────────\n\nconst DEFAULT_GLOBAL_CONFIG = {\n repos: [],\n concurrency: {\n maxSessions: 5,\n maxPerRepo: 2,\n queueMax: 50,\n },\n budget: {\n dailyCapUsd: 500,\n alertThresholdPct: 80,\n },\n};\n\n// ─── YAML loader helper ─────────────────────────────────\n\nfunction parseYamlFile(raw: string, filePath: string): unknown {\n try {\n return parseYaml(raw);\n } catch (err) {\n throw new Error(\n `Invalid YAML in ${filePath}: ${err instanceof Error ? err.message : String(err)}. Check YAML syntax at the indicated line.`,\n );\n }\n}\n\nfunction formatZodErrors(issues: z.ZodIssue[], filePath: string): string {\n const formatted = issues.map((i) => ` - ${i.path.join(\".\")}: ${i.message}`).join(\"\\n\");\n return `Invalid config in ${filePath}:\\n${formatted}`;\n}\n\n// ─── Config loaders ─────────────────────────────────────\n\n/**\n * Load NeoConfig from a single file (legacy compatibility).\n */\nexport async function loadConfig(configPath: string): Promise<NeoConfig> {\n let raw: string;\n try {\n raw = await readFile(configPath, \"utf-8\");\n } catch {\n throw new Error(`Config file not found: ${configPath}. Run 'neo init' to get started.`);\n }\n\n const parsed = parseYamlFile(raw, configPath);\n\n const result = neoConfigSchema.safeParse(parsed);\n if (!result.success) {\n throw new Error(formatZodErrors(result.error.issues, configPath));\n }\n\n return result.data;\n}\n\n/**\n * Load the global config from ~/.neo/config.yml.\n * Creates the file with defaults if it does not exist.\n */\nexport async function loadGlobalConfig(): Promise<NeoConfig> {\n const configPath = path.join(getDataDir(), \"config.yml\");\n\n if (!existsSync(configPath)) {\n await mkdir(getDataDir(), { recursive: true });\n await writeFile(configPath, stringifyYaml(DEFAULT_GLOBAL_CONFIG), \"utf-8\");\n return globalConfigSchema.parse(DEFAULT_GLOBAL_CONFIG);\n }\n\n const raw = await readFile(configPath, \"utf-8\");\n const parsed = parseYamlFile(raw, configPath);\n\n const result = globalConfigSchema.safeParse(parsed);\n if (!result.success) {\n throw new Error(formatZodErrors(result.error.issues, configPath));\n }\n\n return result.data;\n}\n\n// ─── Repo CRUD operations ───────────────────────────────\n\n/**\n * Add a repo to ~/.neo/config.yml. Deduplicates by resolved path.\n */\nexport async function addRepoToGlobalConfig(repo: RepoConfigInput): Promise<void> {\n const config = await loadGlobalConfig();\n const resolvedPath = path.resolve(repo.path);\n const parsed = repoConfigSchema.parse({ ...repo, path: resolvedPath });\n\n const existing = config.repos.findIndex((r) => path.resolve(r.path) === resolvedPath);\n if (existing >= 0) {\n config.repos[existing] = parsed;\n } else {\n config.repos.push(parsed);\n }\n\n const configPath = path.join(getDataDir(), \"config.yml\");\n await writeFile(configPath, stringifyYaml(config), \"utf-8\");\n}\n\n/**\n * Remove a repo from ~/.neo/config.yml by path, name, or slug.\n */\nexport async function removeRepoFromGlobalConfig(pathOrName: string): Promise<boolean> {\n const config = await loadGlobalConfig();\n const resolvedPath = path.resolve(pathOrName);\n const initialLength = config.repos.length;\n\n config.repos = config.repos.filter(\n (r) =>\n path.resolve(r.path) !== resolvedPath &&\n r.name !== pathOrName &&\n toRepoSlug(r) !== pathOrName,\n );\n\n if (config.repos.length === initialLength) return false;\n\n const configPath = path.join(getDataDir(), \"config.yml\");\n await writeFile(configPath, stringifyYaml(config), \"utf-8\");\n return true;\n}\n\n/**\n * List all registered repos from ~/.neo/config.yml.\n */\nexport async function listReposFromGlobalConfig(): Promise<RepoConfig[]> {\n const config = await loadGlobalConfig();\n return config.repos;\n}\n","import { homedir } from \"node:os\";\nimport path from \"node:path\";\n\n/**\n * Global data directory for runtime artifacts (journals, runs).\n * Located at ~/.neo, similar to how Claude Code uses ~/.claude.\n */\nexport function getDataDir(): string {\n return path.join(homedir(), \".neo\");\n}\n\nexport function getJournalsDir(): string {\n return path.join(getDataDir(), \"journals\");\n}\n\nexport function getRunsDir(): string {\n return path.join(getDataDir(), \"runs\");\n}\n\n/**\n * Derive a filesystem-safe slug from a repo config.\n * Uses `name` if present, otherwise `basename(path)`.\n */\nexport function toRepoSlug(repo: { name?: string | undefined; path: string }): string {\n const raw = repo.name ?? path.basename(repo.path);\n return raw\n .toLowerCase()\n .replace(/[^a-z0-9._-]/g, \"-\")\n .replace(/-+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n}\n\n/**\n * Runs directory for a specific repo: ~/.neo/runs/<slug>/\n */\nexport function getRepoRunsDir(repoSlug: string): string {\n return path.join(getRunsDir(), repoSlug);\n}\n\n/**\n * Path to the dispatch request file for a detached run.\n */\nexport function getRunDispatchPath(repoSlug: string, runId: string): string {\n return path.join(getRepoRunsDir(repoSlug), `${runId}.dispatch.json`);\n}\n\n/**\n * Path to the log file for a detached run.\n */\nexport function getRunLogPath(repoSlug: string, runId: string): string {\n return path.join(getRepoRunsDir(repoSlug), `${runId}.log`);\n}\n\n/**\n * Directory for all supervisor instances: ~/.neo/supervisors/\n */\nexport function getSupervisorsDir(): string {\n return path.join(getDataDir(), \"supervisors\");\n}\n\n/**\n * Directory for a specific supervisor instance: ~/.neo/supervisors/<name>/\n */\nexport function getSupervisorDir(name: string): string {\n return path.join(getSupervisorsDir(), name);\n}\n\n/**\n * Path to a supervisor state file: ~/.neo/supervisors/<name>/state.json\n */\nexport function getSupervisorStatePath(name: string): string {\n return path.join(getSupervisorDir(name), \"state.json\");\n}\n\nexport function getSupervisorMemoryPath(name: string): string {\n return path.join(getSupervisorDir(name), \"memory.md\");\n}\n\nexport function getSupervisorActivityPath(name: string): string {\n return path.join(getSupervisorDir(name), \"activity.jsonl\");\n}\n\nexport function getSupervisorInboxPath(name: string): string {\n return path.join(getSupervisorDir(name), \"inbox.jsonl\");\n}\n\nexport function getSupervisorEventsPath(name: string): string {\n return path.join(getSupervisorDir(name), \"events.jsonl\");\n}\n\nexport function getSupervisorLockPath(name: string): string {\n return path.join(getSupervisorDir(name), \"daemon.lock\");\n}\n","import { appendFile, mkdir, readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { CostEntry } from \"@/types\";\n\n/**\n * Append-only JSONL journal for cost tracking.\n * Monthly file rotation: cost-YYYY-MM.jsonl\n */\nexport class CostJournal {\n private readonly dir: string;\n private dirCreated = false;\n private dayCache: { key: string; total: number } | null = null;\n\n constructor(options: { dir: string }) {\n this.dir = options.dir;\n }\n\n async append(entry: CostEntry): Promise<void> {\n await this.ensureDir();\n const file = this.fileForDate(new Date(entry.timestamp));\n await appendFile(file, `${JSON.stringify(entry)}\\n`, \"utf-8\");\n // Invalidate cache — the day total may have changed\n this.dayCache = null;\n }\n\n async getDayTotal(date?: Date): Promise<number> {\n const d = date ?? new Date();\n const dayKey = toDateKey(d);\n\n if (this.dayCache?.key === dayKey) {\n return this.dayCache.total;\n }\n\n const file = this.fileForDate(d);\n let total = 0;\n\n try {\n const content = await readFile(file, \"utf-8\");\n for (const line of content.split(\"\\n\")) {\n if (!line.trim()) continue;\n const entry = JSON.parse(line) as CostEntry;\n if (toDateKey(new Date(entry.timestamp)) === dayKey) {\n total += entry.costUsd;\n }\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n // File doesn't exist yet — total is 0\n }\n\n this.dayCache = { key: dayKey, total };\n return total;\n }\n\n private fileForDate(date: Date): string {\n const yyyy = date.getUTCFullYear();\n const mm = String(date.getUTCMonth() + 1).padStart(2, \"0\");\n return path.join(this.dir, `cost-${yyyy}-${mm}.jsonl`);\n }\n\n private async ensureDir(): Promise<void> {\n if (this.dirCreated) return;\n await mkdir(this.dir, { recursive: true });\n this.dirCreated = true;\n }\n}\n\nfunction toDateKey(date: Date): string {\n return date.toISOString().slice(0, 10);\n}\n","import { EventEmitter } from \"node:events\";\nimport type { NeoEvent } from \"@/types\";\n\n/**\n * Safe EventEmitter wrapper (ADR-022).\n *\n * - Catches listener errors to prevent cascading crashes\n * - Emits on both the specific event type and the wildcard \"*\" channel\n * - Swallows errors from the error handler itself to guarantee stability\n */\nexport class NeoEventEmitter {\n private readonly emitter = new EventEmitter();\n\n emit(event: NeoEvent): void {\n this.safeEmit(event.type, event);\n this.safeEmit(\"*\", event);\n }\n\n on(eventType: string, listener: (event: NeoEvent) => void): this {\n this.emitter.on(eventType, listener);\n return this;\n }\n\n off(eventType: string, listener: (event: NeoEvent) => void): this {\n this.emitter.off(eventType, listener);\n return this;\n }\n\n once(eventType: string, listener: (event: NeoEvent) => void): this {\n this.emitter.once(eventType, listener);\n return this;\n }\n\n removeAllListeners(eventType?: string): this {\n this.emitter.removeAllListeners(eventType);\n return this;\n }\n\n private safeEmit(eventType: string, event: NeoEvent): void {\n try {\n this.emitter.emit(eventType, event);\n } catch (error) {\n if (eventType !== \"error\") {\n try {\n this.emitter.emit(\"error\", error);\n } catch {\n // Swallow — prevent crash even if error handler throws\n }\n }\n }\n }\n}\n","import { appendFile, mkdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { NeoEvent } from \"@/types\";\n\n/**\n * Append-only JSONL journal for events.\n * Monthly file rotation: events-YYYY-MM.jsonl\n * Write-only for v0.1 — read API comes in v0.2.\n */\nexport class EventJournal {\n private readonly dir: string;\n private dirCreated = false;\n\n constructor(options: { dir: string }) {\n this.dir = options.dir;\n }\n\n async append(event: NeoEvent): Promise<void> {\n await this.ensureDir();\n const file = this.fileForDate(new Date(event.timestamp));\n await appendFile(file, `${JSON.stringify(event)}\\n`, \"utf-8\");\n }\n\n private fileForDate(date: Date): string {\n const yyyy = date.getUTCFullYear();\n const mm = String(date.getUTCMonth() + 1).padStart(2, \"0\");\n return path.join(this.dir, `events-${yyyy}-${mm}.jsonl`);\n }\n\n private async ensureDir(): Promise<void> {\n if (this.dirCreated) return;\n await mkdir(this.dir, { recursive: true });\n this.dirCreated = true;\n }\n}\n","import { createHmac } from \"node:crypto\";\nimport type { NeoConfig } from \"@/config\";\nimport type { NeoEvent } from \"@/types\";\n\ntype WebhookConfig = NeoConfig[\"webhooks\"][number];\n\ninterface WebhookPayload {\n version: 1;\n event: Record<string, unknown>;\n source: \"neo\";\n deliveredAt: string;\n}\n\n/**\n * Fire-and-forget webhook dispatcher for NeoEvents.\n *\n * - Matches events against per-webhook filters (exact or wildcard like \"session:*\")\n * - Excludes gate:waiting events (contain non-serializable callbacks)\n * - Signs payloads with HMAC-SHA256 when a secret is configured\n * - Never throws — errors are silently swallowed (consistent with EventJournal)\n */\nexport class WebhookDispatcher {\n private readonly webhooks: WebhookConfig[];\n\n constructor(webhooks: WebhookConfig[]) {\n this.webhooks = webhooks;\n }\n\n dispatch(event: NeoEvent): void {\n // gate:waiting contains non-serializable callbacks (approve/reject)\n if (event.type === \"gate:waiting\") return;\n\n for (const webhook of this.webhooks) {\n if (!matchesFilter(event.type, webhook.events)) continue;\n\n const payload: WebhookPayload = {\n version: 1,\n event: toSerializable(event),\n source: \"neo\",\n deliveredAt: new Date().toISOString(),\n };\n\n const body = JSON.stringify(payload);\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n\n if (webhook.secret) {\n headers[\"X-Neo-Signature\"] = sign(body, webhook.secret);\n }\n\n // Fire-and-forget — never awaited, errors swallowed\n fetch(webhook.url, {\n method: \"POST\",\n headers,\n body,\n signal: AbortSignal.timeout(webhook.timeoutMs),\n }).catch(() => {});\n }\n }\n}\n\n/**\n * Check if an event type matches a filter list.\n * Supports exact matches and wildcard prefixes (e.g. \"session:*\").\n * No filter (undefined) means all events match.\n */\nexport function matchesFilter(eventType: string, filters?: string[]): boolean {\n if (!filters || filters.length === 0) return true;\n return filters.some((f) => {\n if (f.endsWith(\":*\")) return eventType.startsWith(f.slice(0, -1));\n return f === eventType;\n });\n}\n\nfunction sign(body: string, secret: string): string {\n return createHmac(\"sha256\", secret).update(body).digest(\"hex\");\n}\n\nfunction toSerializable(event: NeoEvent): Record<string, unknown> {\n const obj: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(event)) {\n if (typeof value !== \"function\") {\n obj[key] = value;\n }\n }\n return obj;\n}\n","import { execFile } from \"node:child_process\";\nimport { resolve } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport type { RepoConfig } from \"@/config\";\nimport { withGitLock } from \"@/isolation/git-mutex\";\n\nconst execFileAsync = promisify(execFile);\nconst GIT_TIMEOUT = 60_000;\n\n/**\n * Run a git command with execFile (no shell — prevents injection).\n * All callers should go through the public API which acquires the mutex.\n */\nasync function git(repoPath: string, args: string[]): Promise<string> {\n const { stdout } = await execFileAsync(\"git\", args, {\n cwd: resolve(repoPath),\n timeout: GIT_TIMEOUT,\n });\n return stdout.trim();\n}\n\nexport async function createBranch(\n repoPath: string,\n branch: string,\n baseBranch: string,\n): Promise<void> {\n await withGitLock(repoPath, () => git(repoPath, [\"branch\", branch, baseBranch]));\n}\n\nexport async function pushBranch(repoPath: string, branch: string, remote: string): Promise<void> {\n await withGitLock(repoPath, () => git(repoPath, [\"push\", remote, branch]));\n}\n\nexport async function fetchRemote(repoPath: string, remote: string): Promise<void> {\n await withGitLock(repoPath, () => git(repoPath, [\"fetch\", remote]));\n}\n\nexport async function deleteBranch(repoPath: string, branch: string): Promise<void> {\n await withGitLock(repoPath, () => git(repoPath, [\"branch\", \"-D\", branch]));\n}\n\nexport async function getCurrentBranch(repoPath: string): Promise<string> {\n return withGitLock(repoPath, () => git(repoPath, [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]));\n}\n\n/**\n * Generate a deterministic branch name for a run.\n * Uses the repo's branchPrefix (default \"feat\") and the runId.\n */\nexport function getBranchName(config: RepoConfig, runId: string): string {\n const prefix = config.branchPrefix ?? \"feat\";\n const sanitized = runId.toLowerCase().replace(/[^a-z0-9-]/g, \"-\");\n return `${prefix}/run-${sanitized}`;\n}\n","/**\n * Per-repository in-memory mutex to serialise git operations.\n * Concurrent git commands on the same repo corrupt the index — this prevents that.\n */\n\nconst locks = new Map<string, Promise<void>>();\n\n/**\n * Execute `fn` while holding an exclusive lock for `repoPath`.\n * Concurrent calls for the same repo are queued and executed serially.\n * Operations on different repos run in parallel.\n */\nexport async function withGitLock<T>(repoPath: string, fn: () => Promise<T>): Promise<T> {\n const previous = locks.get(repoPath) ?? Promise.resolve();\n\n let releaseLock: (() => void) | undefined;\n const current = new Promise<void>((resolve) => {\n releaseLock = resolve;\n });\n locks.set(repoPath, current);\n\n await previous;\n\n try {\n return await fn();\n } finally {\n releaseLock?.();\n if (locks.get(repoPath) === current) {\n locks.delete(repoPath);\n }\n }\n}\n","import { resolve } from \"node:path\";\nimport type { ResolvedAgent } from \"@/types\";\n\n/**\n * SDK-compatible sandbox configuration.\n * Controls which tools an agent can use and which paths it can access.\n */\nexport interface SandboxConfig {\n /** Tools the agent is allowed to use */\n allowedTools: string[];\n /** Directories the agent can read from */\n readablePaths: string[];\n /** Directories the agent can write to (empty for readonly agents) */\n writablePaths: string[];\n /** Whether the agent has write access */\n writable: boolean;\n}\n\n/** Tools that modify the filesystem */\nconst WRITE_TOOLS = new Set([\"Write\", \"Edit\", \"NotebookEdit\"]);\n\n/**\n * Build an SDK-compatible sandbox configuration for an agent.\n *\n * - Writable agents: all their tools are allowed, write paths include the worktree\n * - Readonly agents: write tools are filtered out, no writable paths\n */\nexport function buildSandboxConfig(agent: ResolvedAgent, worktreePath?: string): SandboxConfig {\n const isWritable = agent.sandbox === \"writable\";\n const absWorktree = worktreePath ? resolve(worktreePath) : undefined;\n\n const allowedTools = isWritable\n ? agent.definition.tools\n : agent.definition.tools.filter((t) => !WRITE_TOOLS.has(t));\n\n const readablePaths = absWorktree ? [absWorktree] : [];\n const writablePaths = isWritable && absWorktree ? [absWorktree] : [];\n\n return {\n allowedTools,\n readablePaths,\n writablePaths,\n writable: isWritable,\n };\n}\n","import { execFile } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { readdir, rm } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { withGitLock } from \"@/isolation/git-mutex\";\n\nconst execFileAsync = promisify(execFile);\nconst GIT_TIMEOUT = 60_000;\n\nexport interface WorktreeInfo {\n path: string;\n branch: string;\n repoPath: string;\n}\n\n/**\n * Create a new git worktree with an associated branch.\n * Creates the branch from baseBranch, then adds the worktree at worktreeDir.\n */\nexport async function createWorktree(options: {\n repoPath: string;\n branch: string;\n baseBranch: string;\n worktreeDir: string;\n}): Promise<WorktreeInfo> {\n const repoPath = resolve(options.repoPath);\n const worktreeDir = resolve(options.worktreeDir);\n\n await withGitLock(repoPath, async () => {\n await execFileAsync(\n \"git\",\n [\"worktree\", \"add\", \"-b\", options.branch, worktreeDir, options.baseBranch],\n { cwd: repoPath, timeout: GIT_TIMEOUT },\n );\n });\n\n // Disable git hooks in the worktree — pre-commit hooks (husky, lint-staged)\n // fail because node_modules are not available in worktrees.\n await execFileAsync(\"git\", [\"config\", \"core.hooksPath\", \"/dev/null\"], {\n cwd: worktreeDir,\n timeout: GIT_TIMEOUT,\n });\n\n return { path: worktreeDir, branch: options.branch, repoPath };\n}\n\n/**\n * Remove a worktree. Does NOT delete the branch (branch stays for the PR).\n * Idempotent — does not throw if the worktree is already gone.\n */\nexport async function removeWorktree(worktreePath: string): Promise<void> {\n const absPath = resolve(worktreePath);\n\n if (!existsSync(absPath)) {\n return;\n }\n\n // We need the repo path to acquire the lock.\n // Read the .git file in the worktree to find the main repo.\n const repoPath = await findRepoForWorktree(absPath);\n\n if (repoPath) {\n await withGitLock(repoPath, async () => {\n try {\n await execFileAsync(\"git\", [\"worktree\", \"remove\", absPath, \"--force\"], {\n cwd: repoPath,\n timeout: GIT_TIMEOUT,\n });\n } catch {\n // Worktree reference may be broken — force cleanup\n await rm(absPath, { recursive: true, force: true });\n await execFileAsync(\"git\", [\"worktree\", \"prune\"], {\n cwd: repoPath,\n timeout: GIT_TIMEOUT,\n }).catch(() => {});\n }\n\n // Refresh the main repo's index stat cache to prevent phantom modifications.\n // Worktree operations can desync timestamps causing `git status` to show\n // files as modified when they are not.\n await execFileAsync(\"git\", [\"update-index\", \"--refresh\"], {\n cwd: repoPath,\n timeout: GIT_TIMEOUT,\n }).catch(() => {});\n });\n } else {\n // No repo found — just remove the directory\n await rm(absPath, { recursive: true, force: true });\n }\n}\n\n/**\n * List all worktrees for a repository.\n */\nexport async function listWorktrees(repoPath: string): Promise<WorktreeInfo[]> {\n const absRepoPath = resolve(repoPath);\n\n const { stdout } = await execFileAsync(\"git\", [\"worktree\", \"list\", \"--porcelain\"], {\n cwd: absRepoPath,\n timeout: GIT_TIMEOUT,\n });\n\n const worktrees: WorktreeInfo[] = [];\n let current: { path: string; branch: string } | undefined;\n\n for (const line of stdout.split(\"\\n\")) {\n if (line.startsWith(\"worktree \")) {\n if (current) {\n worktrees.push({ ...current, repoPath: absRepoPath });\n }\n current = { path: line.slice(9), branch: \"\" };\n } else if (line.startsWith(\"branch \") && current) {\n // \"branch refs/heads/feat/run-abc\" → \"feat/run-abc\"\n current.branch = line.slice(7).replace(\"refs/heads/\", \"\");\n }\n }\n if (current) {\n worktrees.push({ ...current, repoPath: absRepoPath });\n }\n\n return worktrees;\n}\n\n/**\n * Clean up worktrees under worktreeBaseDir that no longer have a matching run.\n * Removes any subdirectory that is a git worktree.\n */\nexport async function cleanupOrphanedWorktrees(worktreeBaseDir: string): Promise<void> {\n const absBase = resolve(worktreeBaseDir);\n\n if (!existsSync(absBase)) {\n return;\n }\n\n const entries = await readdir(absBase, { withFileTypes: true });\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const worktreePath = resolve(absBase, entry.name);\n await removeWorktree(worktreePath);\n }\n}\n\n/**\n * Find the main repository path for a worktree by reading its .git file.\n * Worktrees have a .git *file* (not directory) that points to the main repo.\n */\nasync function findRepoForWorktree(worktreePath: string): Promise<string | undefined> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"rev-parse\", \"--git-common-dir\"], {\n cwd: worktreePath,\n timeout: GIT_TIMEOUT,\n });\n // Returns something like \"/path/to/repo/.git\" — we want the parent\n const gitCommonDir = resolve(worktreePath, stdout.trim());\n return resolve(gitCommonDir, \"..\");\n } catch {\n return undefined;\n }\n}\n","import { appendFile, mkdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { Middleware } from \"@/types\";\n\nconst DEFAULT_FLUSH_INTERVAL_MS = 500;\nconst DEFAULT_FLUSH_SIZE = 20;\n\n/**\n * Audit log middleware.\n *\n * Buffers JSONL entries in memory and flushes to disk either when\n * the buffer reaches `flushSize` entries or every `flushIntervalMs`.\n * File per session. Uses `{ decision: \"async\" }` so it never blocks the chain.\n *\n * Call `flush()` to force-write remaining entries (e.g. on shutdown).\n */\nexport interface AuditLogMiddleware extends Middleware {\n flush: () => Promise<void>;\n}\n\nexport function auditLog(options: {\n dir: string;\n includeInput?: boolean;\n includeOutput?: boolean;\n flushIntervalMs?: number;\n flushSize?: number;\n}): AuditLogMiddleware {\n const {\n dir,\n includeInput = true,\n includeOutput = false,\n flushIntervalMs = DEFAULT_FLUSH_INTERVAL_MS,\n flushSize = DEFAULT_FLUSH_SIZE,\n } = options;\n\n let dirCreated = false;\n // sessionId → buffered lines\n const buffers = new Map<string, string[]>();\n let flushTimer: ReturnType<typeof setInterval> | undefined;\n\n async function ensureDir(): Promise<void> {\n if (!dirCreated) {\n await mkdir(dir, { recursive: true });\n dirCreated = true;\n }\n }\n\n async function flushAll(): Promise<void> {\n if (buffers.size === 0) return;\n await ensureDir();\n\n const writes: Promise<void>[] = [];\n for (const [sessionId, lines] of buffers) {\n const filePath = path.join(dir, `${sessionId}.jsonl`);\n writes.push(appendFile(filePath, lines.join(\"\"), \"utf-8\"));\n }\n buffers.clear();\n await Promise.all(writes);\n }\n\n async function flushSession(sessionId: string): Promise<void> {\n const lines = buffers.get(sessionId);\n if (!lines || lines.length === 0) return;\n await ensureDir();\n\n const filePath = path.join(dir, `${sessionId}.jsonl`);\n await appendFile(filePath, lines.join(\"\"), \"utf-8\");\n buffers.delete(sessionId);\n }\n\n return {\n name: \"audit-log\",\n on: \"PostToolUse\",\n async flush() {\n await flushAll();\n if (flushTimer !== undefined) {\n clearInterval(flushTimer);\n flushTimer = undefined;\n }\n },\n async handler(event, context) {\n const entry: Record<string, unknown> = {\n timestamp: new Date().toISOString(),\n sessionId: event.sessionId,\n agent: context.agent,\n toolName: event.toolName,\n };\n\n if (includeInput && event.input !== undefined) {\n entry.input = event.input;\n }\n\n if (includeOutput && event.output !== undefined) {\n entry.output = event.output;\n }\n\n const sessionId = event.sessionId;\n let lines = buffers.get(sessionId);\n if (!lines) {\n lines = [];\n buffers.set(sessionId, lines);\n }\n lines.push(`${JSON.stringify(entry)}\\n`);\n\n // Flush when buffer is full\n if (lines.length >= flushSize) {\n await flushSession(sessionId);\n }\n\n // Start periodic flush timer if not already running\n if (flushTimer === undefined && flushIntervalMs > 0) {\n flushTimer = setInterval(() => {\n void flushAll();\n }, flushIntervalMs);\n // Unref so it doesn't keep the process alive\n if (typeof flushTimer === \"object\" && \"unref\" in flushTimer) {\n flushTimer.unref();\n }\n }\n\n return { decision: \"async\", asyncTimeout: 5_000 };\n },\n };\n}\n","import type { Middleware } from \"@/types\";\n\n/**\n * Budget guard middleware.\n *\n * Checks daily cost against budget cap on every tool call.\n * If over budget, blocks with reason \"Daily budget exceeded\".\n * Uses the middleware context's `get(\"costToday\")` and `get(\"budgetCapUsd\")`.\n */\nexport function budgetGuard(): Middleware {\n return {\n name: \"budget-guard\",\n on: \"PreToolUse\",\n async handler(_event, context) {\n const costToday = context.get(\"costToday\");\n const budgetCapUsd = context.get(\"budgetCapUsd\");\n\n if (costToday !== undefined && budgetCapUsd !== undefined && costToday >= budgetCapUsd) {\n return {\n decision: \"block\",\n reason: \"Daily budget exceeded\",\n };\n }\n\n return { decision: \"pass\" };\n },\n };\n}\n","import type {\n HookCallback,\n HookCallbackMatcher,\n HookInput,\n HookJSONOutput,\n HookEvent as SDKHookEvent,\n} from \"@anthropic-ai/claude-agent-sdk\";\nimport type {\n HookEvent,\n Middleware,\n MiddlewareContext,\n MiddlewareEvent,\n MiddlewareResult,\n} from \"@/types\";\n\nexport interface MiddlewareChain {\n execute(event: MiddlewareEvent, context: MiddlewareContext): Promise<MiddlewareResult>;\n}\n\nfunction matchesTool(match: string | string[] | undefined, toolName: string | undefined): boolean {\n if (match === undefined) return true;\n if (toolName === undefined) return false;\n if (Array.isArray(match)) return match.includes(toolName);\n return match === toolName;\n}\n\nexport function buildMiddlewareChain(middleware: Middleware[]): MiddlewareChain {\n return {\n async execute(event: MiddlewareEvent, context: MiddlewareContext): Promise<MiddlewareResult> {\n let lastAsync: MiddlewareResult | undefined;\n\n for (const mw of middleware) {\n // Hook event matching\n if (mw.on !== event.hookEvent) continue;\n\n // Tool name matching\n if (!matchesTool(mw.match, event.toolName)) continue;\n\n const result = await mw.handler(event, context);\n\n switch (result.decision) {\n case \"block\":\n return result;\n case \"async\":\n lastAsync = result;\n break;\n case \"pass\":\n break;\n }\n }\n\n return lastAsync ?? { decision: \"pass\" };\n },\n };\n}\n\n/**\n * SDK hooks type — maps hook event names to callback matchers.\n */\nexport type SDKHooks = Partial<Record<SDKHookEvent, HookCallbackMatcher[]>>;\n\n/**\n * Convert a middleware chain to Agent SDK hooks format.\n *\n * Creates one HookCallbackMatcher per supported event (PreToolUse, PostToolUse, Notification).\n * The matcher delegates to the chain's execute method, translating SDK input to our\n * MiddlewareEvent format.\n */\nexport function buildSDKHooks(\n chain: MiddlewareChain,\n context: MiddlewareContext,\n middleware: Middleware[] = [],\n): SDKHooks {\n function makeCallback(hookEvent: HookEvent): HookCallback {\n return async (input: HookInput): Promise<HookJSONOutput> => {\n const event: MiddlewareEvent = {\n hookEvent,\n sessionId: input.session_id,\n toolName: \"tool_name\" in input ? (input.tool_name as string) : undefined,\n input: \"tool_input\" in input ? (input.tool_input as Record<string, unknown>) : undefined,\n output: \"tool_response\" in input ? String(input.tool_response) : undefined,\n message: \"message\" in input ? (input.message as string) : undefined,\n };\n\n const result = await chain.execute(event, context);\n\n switch (result.decision) {\n case \"block\":\n return { decision: \"block\", reason: result.reason };\n case \"async\":\n return { async: true, asyncTimeout: result.asyncTimeout };\n case \"pass\":\n return {};\n }\n };\n }\n\n // Only register hooks for events that have at least one middleware listener\n const usedEvents = new Set(middleware.map((mw) => mw.on));\n const allEvents: HookEvent[] = [\"PreToolUse\", \"PostToolUse\", \"Notification\"];\n\n const hooks: SDKHooks = {};\n for (const hookEvent of allEvents) {\n // When no middleware list is provided, register all events (backward-compatible)\n if (middleware.length === 0 || usedEvents.has(hookEvent)) {\n hooks[hookEvent] = [{ hooks: [makeCallback(hookEvent)] }];\n }\n }\n\n return hooks;\n}\n","import type { Middleware } from \"@/types\";\n\n/**\n * Loop detection middleware.\n *\n * Tracks Bash commands per session. If the same command appears\n * `threshold` times, blocks it and tells the agent to escalate.\n *\n * Call `cleanup(sessionId)` when a session ends to prevent memory leaks.\n */\nexport interface LoopDetectionMiddleware extends Middleware {\n cleanup: (sessionId: string) => void;\n}\n\nexport function loopDetection(options: {\n threshold: number;\n scope?: \"session\";\n}): LoopDetectionMiddleware {\n const { threshold } = options;\n const commandHistory = new Map<string, Map<string, number>>();\n\n return {\n name: \"loop-detection\",\n on: \"PreToolUse\",\n match: \"Bash\",\n cleanup(sessionId: string) {\n commandHistory.delete(sessionId);\n },\n async handler(event) {\n const sessionId = event.sessionId;\n const command =\n event.input && typeof event.input === \"object\" && \"command\" in event.input\n ? String(event.input.command)\n : \"\";\n\n if (!command) return { decision: \"pass\" };\n\n if (!commandHistory.has(sessionId)) {\n commandHistory.set(sessionId, new Map());\n }\n\n const sessionHistory = commandHistory.get(sessionId) ?? new Map<string, number>();\n const count = (sessionHistory.get(command) ?? 0) + 1;\n sessionHistory.set(command, count);\n\n if (count >= threshold) {\n return {\n decision: \"block\",\n reason: `Loop detected: you have run this exact command ${String(count)} times. STOP and escalate — do not retry the same approach.`,\n };\n }\n\n return { decision: \"pass\" };\n },\n };\n}\n","import { randomUUID } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readdir, readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { Semaphore } from \"@/concurrency/semaphore\";\nimport type { NeoConfig, RepoConfig } from \"@/config\";\nimport { CostJournal } from \"@/cost/journal\";\nimport { NeoEventEmitter } from \"@/events\";\nimport { EventJournal } from \"@/events/journal\";\nimport { WebhookDispatcher } from \"@/events/webhook\";\nimport { getBranchName } from \"@/isolation/git\";\nimport { buildSandboxConfig } from \"@/isolation/sandbox\";\nimport { cleanupOrphanedWorktrees, createWorktree } from \"@/isolation/worktree\";\nimport { auditLog } from \"@/middleware/audit-log\";\nimport { budgetGuard } from \"@/middleware/budget-guard\";\nimport { buildMiddlewareChain, buildSDKHooks } from \"@/middleware/chain\";\nimport { loopDetection } from \"@/middleware/loop-detection\";\nimport { getJournalsDir, getRepoRunsDir, getRunsDir, toRepoSlug } from \"@/paths\";\nimport { parseOutput } from \"@/runner/output-parser\";\nimport { runWithRecovery } from \"@/runner/recovery\";\nimport type {\n ActiveSession,\n CostEntry,\n DispatchInput,\n Middleware,\n MiddlewareContext,\n NeoEvent,\n OrchestratorStatus,\n PersistedRun,\n ResolvedAgent,\n StepResult,\n TaskResult,\n WorkflowDefinition,\n WorkflowStepDef,\n} from \"@/types\";\nimport { WorkflowRegistry } from \"@/workflows/registry\";\n\n// ─── Constants ─────────────────────────────────────────\n\nconst MAX_PROMPT_SIZE = 100 * 1024; // 100 KB\nconst MAX_METADATA_DEPTH = 5;\nconst SHUTDOWN_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes\nconst WORKTREES_DIR = \".neo/worktrees\";\nconst textEncoder = new TextEncoder();\n\n// ─── Options ───────────────────────────────────────────\n\nexport interface OrchestratorOptions {\n middleware?: Middleware[] | undefined;\n journalDir?: string | undefined;\n builtInWorkflowDir?: string | undefined;\n customWorkflowDir?: string | undefined;\n}\n\n// ─── Internal dispatch context ─────────────────────────\n\ninterface DispatchContext {\n input: DispatchInput;\n runId: string;\n sessionId: string;\n startedAt: number;\n stepName: string;\n stepDef: WorkflowStepDef;\n agent: ResolvedAgent;\n repoConfig: RepoConfig;\n activeSession: ActiveSession;\n}\n\n// ─── Idempotency ───────────────────────────────────────\n\ninterface IdempotencyEntry {\n result: TaskResult;\n expiresAt: number;\n}\n\n// ─── Orchestrator ──────────────────────────────────────\n\nexport class Orchestrator extends NeoEventEmitter {\n private readonly config: NeoConfig;\n private readonly semaphore: Semaphore;\n private readonly userMiddleware: Middleware[];\n private readonly workflows = new Map<string, WorkflowDefinition>();\n private readonly registeredAgents = new Map<string, ResolvedAgent>();\n private readonly _activeSessions = new Map<string, ActiveSession>();\n private readonly idempotencyCache = new Map<string, IdempotencyEntry>();\n private readonly abortControllers = new Map<string, AbortController>();\n private readonly repoIndex = new Map<string, RepoConfig>();\n private readonly createdRunDirs = new Set<string>();\n private readonly journalDir: string;\n private readonly builtInWorkflowDir: string | undefined;\n private readonly customWorkflowDir: string | undefined;\n private costJournal: CostJournal | null = null;\n private eventJournal: EventJournal | null = null;\n private webhookDispatcher: WebhookDispatcher | null = null;\n private _paused = false;\n private _costToday = 0;\n private _startedAt = 0;\n private _drainResolve: (() => void) | null = null;\n\n constructor(config: NeoConfig, options: OrchestratorOptions = {}) {\n super();\n this.config = config;\n this.userMiddleware = options.middleware ?? [];\n this.journalDir = options.journalDir ?? getJournalsDir();\n this.builtInWorkflowDir = options.builtInWorkflowDir;\n this.customWorkflowDir = options.customWorkflowDir;\n for (const repo of config.repos) {\n const resolvedPath = path.resolve(repo.path);\n const normalizedRepo = { ...repo, path: resolvedPath };\n this.repoIndex.set(resolvedPath, normalizedRepo);\n }\n this.semaphore = new Semaphore(\n {\n maxSessions: config.concurrency.maxSessions,\n maxPerRepo: config.concurrency.maxPerRepo,\n queueMax: config.concurrency.queueMax,\n },\n {\n onEnqueue: (sessionId, repo, position) => {\n this.emit({\n type: \"queue:enqueue\",\n sessionId,\n repo,\n position,\n timestamp: new Date().toISOString(),\n });\n },\n onDequeue: (sessionId, repo, waitedMs) => {\n this.emit({\n type: \"queue:dequeue\",\n sessionId,\n repo,\n waitedMs,\n timestamp: new Date().toISOString(),\n });\n },\n },\n );\n }\n\n // ─── Registration ──────────────────────────────────────\n\n registerWorkflow(definition: WorkflowDefinition): void {\n this.workflows.set(definition.name, definition);\n }\n\n registerAgent(agent: ResolvedAgent): void {\n this.registeredAgents.set(agent.name, agent);\n }\n\n // ─── Dispatch ──────────────────────────────────────────\n\n async dispatch(input: DispatchInput): Promise<TaskResult> {\n const idempotencyKey = this.preDispatchChecks(input);\n const ctx = this.buildDispatchContext(input);\n\n // Acquire semaphore (blocks if at capacity)\n const abortController = new AbortController();\n this.abortControllers.set(ctx.sessionId, abortController);\n await this.semaphore.acquire(\n input.repo,\n ctx.sessionId,\n input.priority ?? \"medium\",\n abortController.signal,\n );\n ctx.activeSession.status = \"running\";\n\n const stepResult = await this.executeStep(ctx);\n return this.finalizeDispatch(ctx, stepResult, idempotencyKey);\n }\n\n // ─── Control ───────────────────────────────────────────\n\n pause(): void {\n this._paused = true;\n }\n\n resume(): void {\n this._paused = false;\n }\n\n async kill(sessionId: string): Promise<void> {\n const controller = this.abortControllers.get(sessionId);\n if (controller) {\n controller.abort(new Error(\"Session killed\"));\n }\n\n this._activeSessions.delete(sessionId);\n this.abortControllers.delete(sessionId);\n this.semaphore.release(sessionId);\n }\n\n async drain(): Promise<void> {\n this._paused = true;\n if (this._activeSessions.size === 0) return;\n return new Promise<void>((resolve) => {\n this._drainResolve = resolve;\n });\n }\n\n // ─── Getters ───────────────────────────────────────────\n\n get status(): OrchestratorStatus {\n return {\n paused: this._paused,\n activeSessions: [...this._activeSessions.values()],\n queueDepth: this.semaphore.queueDepth(),\n costToday: this._costToday,\n budgetCapUsd: this.config.budget.dailyCapUsd,\n budgetRemainingPct: this.computeBudgetRemainingPct(),\n uptime: this._startedAt > 0 ? Date.now() - this._startedAt : 0,\n };\n }\n\n get activeSessions(): ActiveSession[] {\n return [...this._activeSessions.values()];\n }\n\n // ─── Lifecycle ─────────────────────────────────────────\n\n async start(): Promise<void> {\n this._startedAt = Date.now();\n\n // Initialize journals\n this.costJournal = new CostJournal({ dir: this.journalDir });\n this.eventJournal = new EventJournal({ dir: this.journalDir });\n\n // Initialize webhook dispatcher if webhooks are configured\n if (this.config.webhooks.length > 0) {\n this.webhookDispatcher = new WebhookDispatcher(this.config.webhooks);\n }\n\n // Restore today's cost from journal\n this._costToday = await this.costJournal.getDayTotal();\n\n // Load workflows from registry if dirs are configured\n if (this.builtInWorkflowDir) {\n const registry = new WorkflowRegistry(this.builtInWorkflowDir, this.customWorkflowDir);\n await registry.load();\n for (const workflow of registry.list()) {\n this.registerWorkflow(workflow);\n }\n }\n\n await this.recoverOrphanedRuns();\n\n for (const repo of this.config.repos) {\n const worktreeBase = path.join(repo.path, WORKTREES_DIR);\n await cleanupOrphanedWorktrees(worktreeBase).catch(() => {});\n }\n }\n\n async shutdown(): Promise<void> {\n this._paused = true;\n\n if (this._activeSessions.size > 0) {\n await Promise.race([\n this.drain(),\n new Promise<void>((resolve) => setTimeout(resolve, SHUTDOWN_TIMEOUT_MS)),\n ]);\n }\n\n for (const mw of this.userMiddleware) {\n if (\"flush\" in mw && typeof mw.flush === \"function\") {\n await (mw as { flush: () => Promise<void> }).flush();\n }\n if (\"cleanup\" in mw && typeof mw.cleanup === \"function\") {\n for (const session of this._activeSessions.values()) {\n (mw as { cleanup: (id: string) => void }).cleanup(session.sessionId);\n }\n }\n }\n\n this.emit({\n type: \"orchestrator:shutdown\",\n timestamp: new Date().toISOString(),\n });\n }\n\n // ─── Emit override (journal events) ───────────────────\n\n override emit(event: NeoEvent): void {\n super.emit(event);\n // Fire-and-forget event journal append\n if (this.eventJournal) {\n this.eventJournal.append(event).catch(() => {});\n }\n // Fire-and-forget webhook dispatch\n if (this.webhookDispatcher) {\n this.webhookDispatcher.dispatch(event);\n }\n }\n\n // ─── Static middleware factories ───────────────────────\n\n static middleware = {\n loopDetection: (options: { threshold: number; scope?: \"session\" }) => loopDetection(options),\n auditLog: (options: {\n dir: string;\n includeInput?: boolean;\n includeOutput?: boolean;\n flushIntervalMs?: number;\n flushSize?: number;\n }) => auditLog(options),\n budgetGuard: () => budgetGuard(),\n };\n\n // ─── Private: Dispatch phases ──────────────────────────\n\n private preDispatchChecks(input: DispatchInput): string | null {\n this.validateInput(input);\n\n const idempotencyKey = this.computeIdempotencyKey(input);\n if (idempotencyKey) {\n this.evictExpiredIdempotencyEntries();\n const cached = this.idempotencyCache.get(idempotencyKey);\n if (cached && cached.expiresAt > Date.now()) {\n throw new Error(\n `Duplicate dispatch rejected: runId '${input.runId ?? \"auto-generated\"}' already exists. Each dispatch must use a unique runId.`,\n );\n }\n }\n\n if (this._paused) {\n throw new Error(\n \"Dispatch rejected: orchestrator is paused. Call orchestrator.resume() before dispatching.\",\n );\n }\n\n return idempotencyKey;\n }\n\n private buildDispatchContext(input: DispatchInput): DispatchContext {\n const runId = input.runId ?? randomUUID();\n const sessionId = randomUUID();\n const workflow = this.workflows.get(input.workflow);\n if (!workflow) {\n const available = [...this.workflows.keys()].join(\", \") || \"none\";\n throw new Error(\n `Workflow \"${input.workflow}\" not found. Available workflows: ${available}. Check the workflow name or register it first.`,\n );\n }\n const [stepName, stepDef] = this.getFirstStep(workflow, input);\n const agent = this.resolveStepAgent(stepDef, workflow.name);\n const repoConfig = this.resolveRepo(input.repo);\n\n const activeSession: ActiveSession = {\n sessionId,\n runId,\n workflow: input.workflow,\n step: stepName,\n agent: agent.name,\n repo: input.repo,\n status: \"queued\",\n startedAt: new Date().toISOString(),\n };\n this._activeSessions.set(sessionId, activeSession);\n\n return {\n input,\n runId,\n sessionId,\n startedAt: Date.now(),\n stepName,\n stepDef,\n agent,\n repoConfig,\n activeSession,\n };\n }\n\n private async executeStep(ctx: DispatchContext): Promise<StepResult> {\n const { input, runId, sessionId, startedAt, agent, repoConfig, activeSession } = ctx;\n let worktreePath: string | undefined;\n\n try {\n // Create worktree if writable agent\n if (agent.sandbox === \"writable\") {\n const branchName = getBranchName(repoConfig, runId);\n const worktreeDir = path.join(input.repo, WORKTREES_DIR, runId);\n const info = await createWorktree({\n repoPath: input.repo,\n branch: branchName,\n baseBranch: repoConfig.defaultBranch,\n worktreeDir,\n });\n worktreePath = info.path;\n activeSession.worktreePath = worktreePath;\n }\n\n const stepResult = await this.runAgentSession(ctx, worktreePath);\n this.emitCostEvents(sessionId, stepResult.costUsd, ctx);\n this.emitSessionComplete(ctx, stepResult);\n return stepResult;\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n this.emitSessionFail(ctx, errorMsg);\n\n return {\n status: \"failure\",\n sessionId,\n costUsd: 0,\n durationMs: Date.now() - startedAt,\n agent: agent.name,\n startedAt: activeSession.startedAt,\n completedAt: new Date().toISOString(),\n error: errorMsg,\n attempt: 1,\n };\n } finally {\n this.semaphore.release(sessionId);\n this._activeSessions.delete(sessionId);\n this.abortControllers.delete(sessionId);\n\n if (this._activeSessions.size === 0 && this._drainResolve) {\n this._drainResolve();\n this._drainResolve = null;\n }\n }\n }\n\n private async runAgentSession(\n ctx: DispatchContext,\n worktreePath: string | undefined,\n ): Promise<StepResult> {\n const { input, runId, sessionId, stepName, stepDef, agent, activeSession } = ctx;\n\n const sandboxConfig = buildSandboxConfig(agent, worktreePath);\n const chain = buildMiddlewareChain(this.userMiddleware);\n const middlewareContext = this.buildMiddlewareContext(\n runId,\n input.workflow,\n stepName,\n agent.name,\n input.repo,\n );\n const hooks = buildSDKHooks(chain, middlewareContext, this.userMiddleware);\n\n this.emit({\n type: \"session:start\",\n sessionId,\n runId,\n workflow: input.workflow,\n step: stepName,\n agent: agent.name,\n repo: input.repo,\n metadata: input.metadata,\n timestamp: new Date().toISOString(),\n });\n\n const recoveryOpts = stepDef.recovery;\n const sessionResult = await runWithRecovery({\n agent,\n prompt: stepDef.prompt ?? input.prompt,\n repoPath: input.repo,\n sandboxConfig,\n hooks,\n initTimeoutMs: this.config.sessions.initTimeoutMs,\n maxDurationMs: this.config.sessions.maxDurationMs,\n maxRetries: recoveryOpts?.maxRetries ?? this.config.recovery.maxRetries,\n backoffBaseMs: this.config.recovery.backoffBaseMs,\n ...(worktreePath ? { worktreePath } : {}),\n ...(recoveryOpts?.nonRetryable ? { nonRetryable: recoveryOpts.nonRetryable } : {}),\n onAttempt: (attempt, strategy) => {\n if (attempt > 1) {\n this.emit({\n type: \"session:fail\",\n sessionId,\n runId,\n error: `Retrying with strategy: ${strategy}`,\n attempt: attempt - 1,\n maxRetries: recoveryOpts?.maxRetries ?? this.config.recovery.maxRetries,\n willRetry: true,\n metadata: input.metadata,\n timestamp: new Date().toISOString(),\n });\n }\n },\n });\n\n const parsed = parseOutput(sessionResult.output);\n\n return {\n status: \"success\",\n sessionId: sessionResult.sessionId,\n output: parsed.output ?? parsed.rawOutput,\n rawOutput: sessionResult.output,\n costUsd: sessionResult.costUsd,\n durationMs: sessionResult.durationMs,\n agent: agent.name,\n startedAt: activeSession.startedAt,\n completedAt: new Date().toISOString(),\n attempt: 1,\n };\n }\n\n private async finalizeDispatch(\n ctx: DispatchContext,\n stepResult: StepResult,\n idempotencyKey: string | null,\n ): Promise<TaskResult> {\n const { input, runId, stepName, repoConfig, activeSession } = ctx;\n\n const taskResult: TaskResult = {\n runId,\n workflow: input.workflow,\n repo: input.repo,\n status: stepResult.status === \"success\" ? \"success\" : \"failure\",\n steps: { [stepName]: stepResult },\n branch:\n stepResult.status === \"success\" && activeSession.worktreePath\n ? getBranchName(repoConfig, runId)\n : undefined,\n costUsd: stepResult.costUsd,\n durationMs: Date.now() - ctx.startedAt,\n timestamp: new Date().toISOString(),\n metadata: input.metadata,\n };\n\n await this.persistRun({\n version: 1,\n runId,\n workflow: input.workflow,\n repo: input.repo,\n prompt: input.prompt,\n branch: taskResult.branch,\n status: taskResult.status === \"success\" ? \"completed\" : \"failed\",\n steps: taskResult.steps,\n createdAt: activeSession.startedAt,\n updatedAt: new Date().toISOString(),\n metadata: input.metadata,\n });\n\n if (idempotencyKey) {\n const ttl = this.config.idempotency?.ttlMs ?? 3_600_000;\n this.idempotencyCache.set(idempotencyKey, {\n result: taskResult,\n expiresAt: Date.now() + ttl,\n });\n }\n\n return taskResult;\n }\n\n // ─── Private: Event helpers ────────────────────────────\n\n private emitCostEvents(sessionId: string, sessionCost: number, ctx: DispatchContext): void {\n this._costToday += sessionCost;\n\n // Persist cost entry to journal (fire-and-forget)\n if (this.costJournal) {\n const costEntry: CostEntry = {\n timestamp: new Date().toISOString(),\n runId: ctx.runId,\n workflow: ctx.input.workflow,\n step: ctx.stepName,\n sessionId,\n agent: ctx.agent.name,\n costUsd: sessionCost,\n models: {},\n durationMs: Date.now() - ctx.startedAt,\n repo: ctx.input.repo,\n };\n this.costJournal.append(costEntry).catch(() => {});\n }\n\n this.emit({\n type: \"cost:update\",\n sessionId,\n sessionCost,\n todayTotal: this._costToday,\n budgetRemainingPct: this.computeBudgetRemainingPct(),\n timestamp: new Date().toISOString(),\n });\n\n const utilizationPct = (this._costToday / this.config.budget.dailyCapUsd) * 100;\n if (utilizationPct >= this.config.budget.alertThresholdPct) {\n this.emit({\n type: \"budget:alert\",\n todayTotal: this._costToday,\n capUsd: this.config.budget.dailyCapUsd,\n utilizationPct,\n timestamp: new Date().toISOString(),\n });\n }\n }\n\n private emitSessionComplete(ctx: DispatchContext, stepResult: StepResult): void {\n this.emit({\n type: \"session:complete\",\n sessionId: ctx.sessionId,\n runId: ctx.runId,\n status: \"success\",\n costUsd: stepResult.costUsd,\n durationMs: stepResult.durationMs,\n output: stepResult.output,\n metadata: ctx.input.metadata,\n timestamp: new Date().toISOString(),\n });\n }\n\n private emitSessionFail(ctx: DispatchContext, errorMsg: string): void {\n this.emit({\n type: \"session:fail\",\n sessionId: ctx.sessionId,\n runId: ctx.runId,\n error: errorMsg,\n attempt: 1,\n maxRetries: this.config.recovery.maxRetries,\n willRetry: false,\n metadata: ctx.input.metadata,\n timestamp: new Date().toISOString(),\n });\n }\n\n // ─── Private: Input validation ─────────────────────────\n\n private validateInput(input: DispatchInput): void {\n if (!input.prompt || input.prompt.trim().length === 0) {\n throw new Error(\"Validation error: prompt must be a non-empty string\");\n }\n if (textEncoder.encode(input.prompt).length > MAX_PROMPT_SIZE) {\n throw new Error(\n `Validation error: prompt exceeds maximum size of ${String(MAX_PROMPT_SIZE)} bytes`,\n );\n }\n\n if (!existsSync(input.repo)) {\n throw new Error(`Validation error: repo path does not exist: ${input.repo}`);\n }\n\n if (!this.workflows.has(input.workflow)) {\n throw new Error(`Validation error: workflow \"${input.workflow}\" not found in registry`);\n }\n\n if (input.metadata !== undefined) {\n if (!isPlainObject(input.metadata)) {\n throw new Error(\"Validation error: metadata must be a plain object\");\n }\n if (objectDepth(input.metadata) > MAX_METADATA_DEPTH) {\n throw new Error(\n `Validation error: metadata exceeds maximum nesting depth of ${String(MAX_METADATA_DEPTH)}`,\n );\n }\n }\n\n const resumeOptions = [input.step, input.from, input.retry].filter(Boolean);\n if (resumeOptions.length > 1) {\n throw new Error(\"Validation error: step, from, and retry are mutually exclusive\");\n }\n }\n\n // ─── Private: Helpers ──────────────────────────────────\n\n private evictExpiredIdempotencyEntries(): void {\n const now = Date.now();\n for (const [key, entry] of this.idempotencyCache) {\n if (entry.expiresAt <= now) {\n this.idempotencyCache.delete(key);\n }\n }\n }\n\n private computeIdempotencyKey(input: DispatchInput): string | null {\n const idempotency = this.config.idempotency;\n if (!idempotency?.enabled) return null;\n\n const key = idempotency.key ?? \"metadata\";\n if (key === \"prompt\") {\n return `${input.workflow}:${input.repo}:${input.prompt}`;\n }\n return `${input.workflow}:${input.repo}:${JSON.stringify(input.metadata ?? {})}`;\n }\n\n private getFirstStep(\n workflow: WorkflowDefinition,\n input: DispatchInput,\n ): [string, WorkflowStepDef] {\n if (input.step) {\n const step = workflow.steps[input.step];\n if (!step || step.type === \"gate\") {\n throw new Error(\n `Step \"${input.step}\" not found in workflow \"${workflow.name}\" or is a gate step. Check the step name in the workflow definition.`,\n );\n }\n return [input.step, step as WorkflowStepDef];\n }\n\n for (const [name, step] of Object.entries(workflow.steps)) {\n if (step.type === \"gate\") continue;\n const stepDef = step as WorkflowStepDef;\n if (!stepDef.dependsOn || stepDef.dependsOn.length === 0) {\n return [name, stepDef];\n }\n }\n\n const entries = Object.entries(workflow.steps);\n const first = entries[0];\n if (!first) {\n throw new Error(`Workflow \"${workflow.name}\" has no steps`);\n }\n return [first[0], first[1] as WorkflowStepDef];\n }\n\n private resolveStepAgent(step: WorkflowStepDef, workflowName: string): ResolvedAgent {\n const agent = this.registeredAgents.get(step.agent);\n if (!agent) {\n throw new Error(\n `Agent \"${step.agent}\" required by workflow \"${workflowName}\" not found in registry. Register the agent or check the workflow definition.`,\n );\n }\n return agent;\n }\n\n private resolveRepo(repoPath: string): RepoConfig {\n const repo = this.repoIndex.get(path.resolve(repoPath));\n if (repo) return repo;\n return {\n path: repoPath,\n defaultBranch: \"main\",\n branchPrefix: \"feat\",\n pushRemote: \"origin\",\n autoCreatePr: false,\n };\n }\n\n private buildMiddlewareContext(\n runId: string,\n workflow: string,\n step: string,\n agent: string,\n repo: string,\n ): MiddlewareContext {\n const store = new Map<string, unknown>();\n return {\n runId,\n workflow,\n step,\n agent,\n repo,\n get: ((key: string) => {\n if (key === \"costToday\") return this._costToday;\n if (key === \"budgetCapUsd\") return this.config.budget.dailyCapUsd;\n return store.get(key);\n }) as MiddlewareContext[\"get\"],\n set: ((key: string, value: unknown) => {\n store.set(key, value);\n }) as MiddlewareContext[\"set\"],\n };\n }\n\n private computeBudgetRemainingPct(): number {\n const cap = this.config.budget.dailyCapUsd;\n if (cap <= 0) return 0;\n return Math.max(0, ((cap - this._costToday) / cap) * 100);\n }\n\n // ─── Private: Run persistence ──────────────────────────\n\n private async persistRun(run: PersistedRun): Promise<void> {\n try {\n const slug = toRepoSlug({ path: run.repo });\n const runsDir = getRepoRunsDir(slug);\n if (!this.createdRunDirs.has(runsDir)) {\n await mkdir(runsDir, { recursive: true });\n this.createdRunDirs.add(runsDir);\n }\n const filePath = path.join(runsDir, `${run.runId}.json`);\n await writeFile(filePath, JSON.stringify(run, null, 2), \"utf-8\");\n } catch {\n // Non-critical — don't fail the dispatch if persistence fails\n }\n }\n\n private async recoverOrphanedRuns(): Promise<void> {\n const runsDir = getRunsDir();\n if (!existsSync(runsDir)) return;\n\n try {\n const entries = await readdir(runsDir, { withFileTypes: true });\n // Scan slug subdirs and legacy flat .json files\n const jsonFiles: string[] = [];\n\n for (const entry of entries) {\n if (entry.isDirectory()) {\n const subDir = path.join(runsDir, entry.name);\n const subFiles = await readdir(subDir);\n for (const f of subFiles) {\n if (f.endsWith(\".json\")) jsonFiles.push(path.join(subDir, f));\n }\n } else if (entry.name.endsWith(\".json\")) {\n jsonFiles.push(path.join(runsDir, entry.name));\n }\n }\n\n for (const filePath of jsonFiles) {\n const content = await readFile(filePath, \"utf-8\");\n const run = JSON.parse(content) as PersistedRun;\n\n if (run.status === \"running\") {\n run.status = \"failed\";\n run.updatedAt = new Date().toISOString();\n await writeFile(filePath, JSON.stringify(run, null, 2), \"utf-8\");\n }\n }\n } catch {\n // Non-critical\n }\n }\n}\n\n// ─── Utility functions ─────────────────────────────────\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction objectDepth(obj: unknown, current = 0): number {\n if (!isPlainObject(obj)) return current;\n let max = current + 1;\n for (const value of Object.values(obj)) {\n const depth = objectDepth(value, current + 1);\n if (depth > max) max = depth;\n }\n return max;\n}\n","import type { ZodType } from \"zod\";\n\nexport interface ParsedOutput {\n rawOutput: string;\n output?: unknown;\n parseError?: string;\n}\n\n/**\n * Extract JSON from agent output that may be wrapped in markdown code blocks.\n * Tries multiple strategies: raw JSON parse, then markdown code block extraction.\n */\nfunction extractJson(raw: string): unknown | undefined {\n // Strategy 1: Try parsing the entire string as JSON\n try {\n return JSON.parse(raw);\n } catch {\n // Not raw JSON, continue\n }\n\n // Strategy 2: Extract from markdown code blocks (```json ... ``` or ``` ... ```)\n const codeBlockRegex = /```(?:json)?\\s*\\n?([\\s\\S]*?)```/;\n const match = raw.match(codeBlockRegex);\n if (match?.[1]) {\n try {\n return JSON.parse(match[1].trim());\n } catch {\n // Invalid JSON inside code block\n }\n }\n\n return undefined;\n}\n\n/**\n * Parse agent output, optionally validating against a Zod schema.\n *\n * - If no schema: returns rawOutput only\n * - If schema provided: extracts JSON from output, validates with schema\n * - On failure: returns rawOutput + parseError (caller decides whether to retry)\n */\nexport function parseOutput(raw: string, schema?: ZodType): ParsedOutput {\n if (!schema) {\n return { rawOutput: raw };\n }\n\n const extracted = extractJson(raw);\n if (extracted === undefined) {\n return {\n rawOutput: raw,\n parseError: \"Failed to extract JSON from output\",\n };\n }\n\n const result = schema.safeParse(extracted);\n if (!result.success) {\n return {\n rawOutput: raw,\n parseError: `Schema validation failed: ${result.error.message}`,\n };\n }\n\n return {\n rawOutput: raw,\n output: result.data,\n };\n}\n","import type { McpServerConfig } from \"@/config\";\nimport type { SandboxConfig } from \"@/isolation/sandbox\";\nimport type { ResolvedAgent } from \"@/types\";\n\n// ─── Types ──────────────────────────────────────────────\n\nexport interface SessionOptions {\n agent: ResolvedAgent;\n prompt: string;\n repoPath?: string;\n worktreePath?: string;\n sandboxConfig: SandboxConfig;\n hooks?: Record<string, unknown>;\n mcpServers?: McpServerConfig[];\n initTimeoutMs: number;\n maxDurationMs: number;\n resumeSessionId?: string | undefined;\n onEvent?: ((event: SessionEvent) => void) | undefined;\n}\n\nexport interface SessionResult {\n sessionId: string;\n output: string;\n costUsd: number;\n durationMs: number;\n turnCount: number;\n}\n\nexport type SessionEvent =\n | { type: \"session:start\"; sessionId: string }\n | { type: \"session:complete\"; sessionId: string; result: SessionResult }\n | { type: \"session:fail\"; sessionId: string; error: string };\n\n// ─── SDK stream message shapes ──────────────────────────\n\ninterface SDKInitMessage {\n type: \"system\";\n subtype: \"init\";\n session_id: string;\n}\n\ninterface SDKResultMessage {\n type: \"result\";\n subtype: \"success\" | string;\n session_id: string;\n result: string;\n total_cost_usd: number;\n num_turns: number;\n}\n\ninterface SDKStreamMessage {\n type: string;\n subtype?: string;\n}\n\nfunction isInitMessage(msg: SDKStreamMessage): msg is SDKInitMessage {\n return msg.type === \"system\" && msg.subtype === \"init\";\n}\n\nfunction isResultMessage(msg: SDKStreamMessage): msg is SDKResultMessage {\n return msg.type === \"result\";\n}\n\n// ─── Helpers ────────────────────────────────────────────\n\nfunction checkAborted(signal: AbortSignal): void {\n if (signal.aborted) {\n const reason = signal.reason;\n throw reason instanceof Error ? reason : new Error(String(reason));\n }\n}\n\nfunction toSessionError(error: unknown, isTimeout: boolean, sessionId: string): SessionError {\n if (error instanceof SessionError) return error;\n const message = error instanceof Error ? error.message : String(error);\n return new SessionError(message, isTimeout ? \"timeout\" : \"unknown\", sessionId);\n}\n\n// ─── Session Runner ─────────────────────────────────────\n\nexport async function runSession(options: SessionOptions): Promise<SessionResult> {\n const { agent, prompt, worktreePath, sandboxConfig, initTimeoutMs, maxDurationMs, onEvent } =\n options;\n\n const startTime = Date.now();\n let sessionId = \"\";\n\n const abortController = new AbortController();\n const initTimer = setTimeout(() => {\n abortController.abort(new Error(\"Session init timeout exceeded\"));\n }, initTimeoutMs);\n const maxDurationTimer = setTimeout(() => {\n abortController.abort(new Error(\"Session max duration exceeded\"));\n }, maxDurationMs);\n\n try {\n const sdk = await import(\"@anthropic-ai/claude-agent-sdk\");\n\n const queryOptions: Record<string, unknown> = {\n // Always pass cwd: worktree for writable agents, repo root for readonly.\n // Without this, readonly agents default to process.cwd() and may write to main tree.\n cwd: worktreePath ?? options.repoPath,\n maxTurns: agent.maxTurns,\n allowedTools: sandboxConfig.allowedTools,\n };\n\n if (options.resumeSessionId) {\n queryOptions.resume = options.resumeSessionId;\n }\n\n if (options.mcpServers?.length) {\n queryOptions.mcpServers = options.mcpServers;\n }\n\n let output = \"\";\n let costUsd = 0;\n let turnCount = 0;\n\n const stream = sdk.query({ prompt, options: queryOptions as never });\n\n for await (const message of stream) {\n checkAborted(abortController.signal);\n\n const msg = message as SDKStreamMessage;\n\n if (isInitMessage(msg)) {\n sessionId = msg.session_id;\n clearTimeout(initTimer);\n onEvent?.({ type: \"session:start\", sessionId });\n }\n\n if (isResultMessage(msg)) {\n output = msg.result ?? \"\";\n costUsd = msg.total_cost_usd ?? 0;\n turnCount = msg.num_turns ?? 0;\n sessionId = msg.session_id ?? sessionId;\n\n if (msg.subtype !== \"success\") {\n throw new SessionError(\n `Session ended with error: ${msg.subtype}`,\n msg.subtype,\n sessionId,\n );\n }\n }\n }\n\n const sessionResult: SessionResult = {\n sessionId,\n output,\n costUsd,\n durationMs: Date.now() - startTime,\n turnCount,\n };\n\n onEvent?.({ type: \"session:complete\", sessionId, result: sessionResult });\n return sessionResult;\n } catch (error) {\n const errorSessionId = sessionId || \"unknown\";\n const sessionError = toSessionError(error, abortController.signal.aborted, errorSessionId);\n\n onEvent?.({ type: \"session:fail\", sessionId: errorSessionId, error: sessionError.message });\n throw sessionError;\n } finally {\n clearTimeout(initTimer);\n clearTimeout(maxDurationTimer);\n }\n}\n\n// ─── Error class ────────────────────────────────────────\n\nexport class SessionError extends Error {\n constructor(\n message: string,\n public readonly errorType: string,\n public readonly sessionId: string,\n ) {\n super(message);\n this.name = \"SessionError\";\n }\n}\n","import {\n runSession,\n SessionError,\n type SessionOptions,\n type SessionResult,\n} from \"@/runner/session\";\n\n// ─── Types ──────────────────────────────────────────────\n\nexport interface RecoveryOptions extends SessionOptions {\n maxRetries: number;\n backoffBaseMs: number;\n nonRetryable?: string[];\n onAttempt?: (attempt: number, strategy: string) => void;\n}\n\n// ─── Default non-retryable errors ───────────────────────\n\nconst DEFAULT_NON_RETRYABLE = [\"error_max_turns\", \"budget_exceeded\"];\n\n// ─── Recovery strategy names ────────────────────────────\n\nfunction getStrategy(attempt: number): string {\n switch (attempt) {\n case 1:\n return \"normal\";\n case 2:\n return \"resume\";\n default:\n return \"fresh\";\n }\n}\n\n// ─── Sleep utility ──────────────────────────────────────\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n// ─── Error handling ─────────────────────────────────────\n\nfunction isNonRetryable(error: unknown, nonRetryable: string[]): boolean {\n return error instanceof SessionError && nonRetryable.includes(error.errorType);\n}\n\nfunction updateSessionId(error: unknown, current: string | undefined): string | undefined {\n if (error instanceof SessionError && error.sessionId !== \"unknown\") {\n return error.sessionId;\n }\n return current;\n}\n\nfunction buildFinalError(error: unknown, maxRetries: number): Error {\n if (error instanceof Error) {\n return new Error(`Recovery failed after ${maxRetries} attempts. Last error: ${error.message}`, {\n cause: error,\n });\n }\n return new Error(`Recovery failed after ${maxRetries} attempts`);\n}\n\n/**\n * Run a session with 3-level recovery escalation (ADR-020).\n *\n * Level 1 (attempt 1): Normal execution — new session\n * Level 2 (attempt 2): Resume session — pass resumeSessionId from level 1\n * Level 3 (attempt 3): Fresh session — abandon previous, start clean\n *\n * Non-retryable errors skip to immediate failure.\n * Backoff: backoffBaseMs * attempt between levels.\n */\nexport async function runWithRecovery(options: RecoveryOptions): Promise<SessionResult> {\n const {\n maxRetries,\n backoffBaseMs,\n nonRetryable = DEFAULT_NON_RETRYABLE,\n onAttempt,\n ...rest\n } = options;\n\n let lastSessionId: string | undefined;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n const strategy = getStrategy(attempt);\n onAttempt?.(attempt, strategy);\n\n try {\n const result = await runSession({\n ...rest,\n resumeSessionId: strategy === \"resume\" ? lastSessionId : undefined,\n });\n return result;\n } catch (error) {\n lastSessionId = updateSessionId(error, lastSessionId);\n\n if (isNonRetryable(error, nonRetryable)) throw error;\n if (attempt === maxRetries) throw buildFinalError(error, maxRetries);\n\n // Next attempt will be \"fresh\" — clear session to start clean\n if (getStrategy(attempt + 1) === \"fresh\") {\n lastSessionId = undefined;\n }\n\n await sleep(backoffBaseMs * attempt);\n }\n }\n\n throw new Error(\"Recovery failed: unreachable\");\n}\n","import { existsSync } from \"node:fs\";\nimport { readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { WorkflowDefinition } from \"@/types\";\nimport { loadWorkflow } from \"@/workflows/loader\";\n\n/**\n * Registry for workflow definitions.\n * Loads built-in workflows from a directory and optional custom workflows.\n * Custom workflows with the same name override built-in ones.\n */\nexport class WorkflowRegistry {\n private readonly builtInDir: string;\n private readonly customDir: string | undefined;\n private readonly workflows = new Map<string, WorkflowDefinition>();\n\n constructor(builtInDir: string, customDir?: string) {\n this.builtInDir = builtInDir;\n this.customDir = customDir;\n }\n\n async load(): Promise<void> {\n // Load built-in workflows first\n await this.loadFromDir(this.builtInDir);\n\n // Custom workflows override built-in ones\n if (this.customDir) {\n await this.loadFromDir(this.customDir);\n }\n }\n\n get(name: string): WorkflowDefinition | undefined {\n return this.workflows.get(name);\n }\n\n list(): WorkflowDefinition[] {\n return [...this.workflows.values()];\n }\n\n has(name: string): boolean {\n return this.workflows.has(name);\n }\n\n private async loadFromDir(dir: string): Promise<void> {\n if (!existsSync(dir)) return;\n\n const files = await readdir(dir);\n for (const file of files) {\n if (!file.endsWith(\".yml\") && !file.endsWith(\".yaml\")) continue;\n const filePath = path.join(dir, file);\n const workflow = await loadWorkflow(filePath);\n this.workflows.set(workflow.name, workflow);\n }\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { parse } from \"yaml\";\nimport { z } from \"zod\";\nimport type { WorkflowDefinition, WorkflowGateDef, WorkflowStepDef } from \"@/types\";\n\n// ─── Zod Schemas ────────────────────────────────────────\n\nconst workflowStepDefSchema = z.object({\n type: z.literal(\"step\").optional().default(\"step\"),\n agent: z.string(),\n dependsOn: z.array(z.string()).optional(),\n prompt: z.string().optional(),\n sandbox: z.enum([\"writable\", \"readonly\"]).optional(),\n maxTurns: z.number().int().positive().optional(),\n mcpServers: z.array(z.string()).optional(),\n recovery: z\n .object({\n maxRetries: z.number().int().nonnegative().optional(),\n nonRetryable: z.array(z.string()).optional(),\n })\n .optional(),\n condition: z.string().optional(),\n});\n\nconst workflowGateDefSchema = z.object({\n type: z.literal(\"gate\"),\n dependsOn: z.array(z.string()).optional(),\n description: z.string(),\n timeout: z.string().optional(),\n autoApprove: z.boolean().optional(),\n});\n\nconst workflowHeaderSchema = z.object({\n name: z.string().min(1),\n description: z.string().optional(),\n steps: z.record(z.string(), z.unknown()),\n});\n\n// ─── Helpers ────────────────────────────────────────────\n\nfunction parseStepEntry(\n stepName: string,\n stepValue: unknown,\n): { step: WorkflowStepDef | WorkflowGateDef; errors: string[] } {\n const obj = stepValue as Record<string, unknown>;\n const schema = obj.type === \"gate\" ? workflowGateDefSchema : workflowStepDefSchema;\n const result = schema.safeParse(stepValue);\n\n if (result.success) {\n return { step: result.data as WorkflowStepDef | WorkflowGateDef, errors: [] };\n }\n return {\n step: stepValue as WorkflowStepDef,\n errors: result.error.issues.map(\n (i) => ` - steps.${stepName}.${i.path.join(\".\")}: ${i.message}`,\n ),\n };\n}\n\nfunction parseSteps(\n rawSteps: Record<string, unknown>,\n filePath: string,\n): Record<string, WorkflowStepDef | WorkflowGateDef> {\n if (Object.keys(rawSteps).length === 0) {\n throw new Error(\n `Invalid workflow definition in ${filePath}:\\n - steps: Workflow must have at least one step`,\n );\n }\n\n const steps: Record<string, WorkflowStepDef | WorkflowGateDef> = {};\n const errors: string[] = [];\n\n for (const [name, value] of Object.entries(rawSteps)) {\n const { step, errors: stepErrors } = parseStepEntry(name, value);\n if (stepErrors.length > 0) {\n errors.push(...stepErrors);\n } else {\n steps[name] = step;\n }\n }\n\n if (errors.length > 0) {\n throw new Error(`Invalid workflow definition in ${filePath}:\\n${errors.join(\"\\n\")}`);\n }\n\n return steps;\n}\n\n// ─── Loader ─────────────────────────────────────────────\n\nexport async function loadWorkflow(filePath: string): Promise<WorkflowDefinition> {\n const content = await readFile(filePath, \"utf-8\");\n const raw = parse(content) as unknown;\n\n const headerResult = workflowHeaderSchema.safeParse(raw);\n if (!headerResult.success) {\n const issues = headerResult.error.issues\n .map((i) => ` - ${i.path.join(\".\")}: ${i.message}`)\n .join(\"\\n\");\n throw new Error(`Invalid workflow definition in ${filePath}:\\n${issues}`);\n }\n\n const { name, description, steps: rawSteps } = headerResult.data;\n const steps = parseSteps(rawSteps, filePath);\n\n return { name, description, steps };\n}\n\nexport { workflowGateDefSchema, workflowStepDefSchema };\n","import { z } from \"zod\";\n\n// ─── Daemon state (persisted in state.json) ──────────────\n\nexport const supervisorDaemonStateSchema = z.object({\n pid: z.number(),\n tmuxSession: z.string(),\n sessionId: z.string(),\n port: z.number(),\n cwd: z.string(),\n startedAt: z.string(),\n lastHeartbeat: z.string().optional(),\n heartbeatCount: z.number().default(0),\n totalCostUsd: z.number().default(0),\n todayCostUsd: z.number().default(0),\n costResetDate: z.string().optional(),\n status: z.enum([\"running\", \"draining\", \"stopped\"]).default(\"running\"),\n});\n\nexport type SupervisorDaemonState = z.infer<typeof supervisorDaemonStateSchema>;\n\n// ─── Incoming webhook event ──────────────────────────────\n\nexport const webhookIncomingEventSchema = z.object({\n id: z.string().optional(),\n source: z.string().optional(),\n event: z.string().optional(),\n payload: z.record(z.string(), z.unknown()).optional(),\n receivedAt: z.string(),\n processedAt: z.string().optional(),\n});\n\nexport type WebhookIncomingEvent = z.infer<typeof webhookIncomingEventSchema>;\n\n// ─── TUI / external inbox message ───────────────────────\n\nexport const inboxMessageSchema = z.object({\n id: z.string(),\n from: z.enum([\"tui\", \"api\", \"external\"]),\n text: z.string(),\n timestamp: z.string(),\n processedAt: z.string().optional(),\n});\n\nexport type InboxMessage = z.infer<typeof inboxMessageSchema>;\n\n// ─── Activity log entry ─────────────────────────────────\n\nexport const activityEntrySchema = z.object({\n id: z.string(),\n type: z.enum([\n \"heartbeat\",\n \"decision\",\n \"action\",\n \"error\",\n \"event\",\n \"message\",\n \"thinking\",\n \"plan\",\n \"dispatch\",\n \"tool_use\",\n ]),\n summary: z.string(),\n detail: z.unknown().optional(),\n timestamp: z.string(),\n});\n\nexport type ActivityEntry = z.infer<typeof activityEntrySchema>;\n\n// ─── Queued event (union of all event sources) ──────────\n\nexport type QueuedEvent =\n | { kind: \"webhook\"; data: WebhookIncomingEvent }\n | { kind: \"message\"; data: InboxMessage }\n | { kind: \"run_complete\"; runId: string; timestamp: string };\n","import { randomUUID } from \"node:crypto\";\nimport { appendFile, readFile, rename, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { ActivityEntry } from \"./schemas.js\";\n\nconst ACTIVITY_FILE = \"activity.jsonl\";\nconst MAX_SIZE_BYTES = 10 * 1024 * 1024; // 10MB rotation threshold\n\nexport class ActivityLog {\n private readonly filePath: string;\n private readonly dir: string;\n\n constructor(dir: string) {\n this.dir = dir;\n this.filePath = path.join(dir, ACTIVITY_FILE);\n }\n\n /**\n * Append a structured entry to the activity log.\n * Rotates the file if it exceeds MAX_SIZE_BYTES.\n */\n async append(entry: ActivityEntry): Promise<void> {\n await this.checkRotation();\n const line = `${JSON.stringify(entry)}\\n`;\n await appendFile(this.filePath, line, \"utf-8\");\n }\n\n /**\n * Create and append a new entry with auto-generated id and timestamp.\n */\n async log(type: ActivityEntry[\"type\"], summary: string, detail?: unknown): Promise<void> {\n await this.append({\n id: randomUUID(),\n type,\n summary,\n detail,\n timestamp: new Date().toISOString(),\n });\n }\n\n /**\n * Read the last N entries from the activity log.\n */\n async tail(n: number): Promise<ActivityEntry[]> {\n let content: string;\n try {\n content = await readFile(this.filePath, \"utf-8\");\n } catch {\n return [];\n }\n\n const lines = content.trim().split(\"\\n\").filter(Boolean);\n const lastLines = lines.slice(-n);\n\n const entries: ActivityEntry[] = [];\n for (const line of lastLines) {\n try {\n entries.push(JSON.parse(line) as ActivityEntry);\n } catch {\n // Skip malformed lines\n }\n }\n return entries;\n }\n\n private async checkRotation(): Promise<void> {\n try {\n const stats = await stat(this.filePath);\n if (stats.size > MAX_SIZE_BYTES) {\n const timestamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n const rotatedPath = path.join(this.dir, `activity-${timestamp}.jsonl`);\n await rename(this.filePath, rotatedPath);\n }\n } catch {\n // File doesn't exist yet — no rotation needed\n }\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport type { GlobalConfig } from \"@/config\";\nimport { getSupervisorDir } from \"@/paths\";\nimport { ActivityLog } from \"./activity-log.js\";\nimport { EventQueue } from \"./event-queue.js\";\nimport { HeartbeatLoop } from \"./heartbeat.js\";\nimport type { SupervisorDaemonState } from \"./schemas.js\";\nimport { WebhookServer } from \"./webhook-server.js\";\n\nexport interface SupervisorDaemonOptions {\n name: string;\n config: GlobalConfig;\n}\n\n/**\n * Orchestrates all supervisor components: webhook server, event queue,\n * heartbeat loop, memory, and activity logging.\n */\nexport class SupervisorDaemon {\n private readonly name: string;\n private readonly config: GlobalConfig;\n private readonly dir: string;\n private webhookServer: WebhookServer | null = null;\n private eventQueue: EventQueue | null = null;\n private heartbeatLoop: HeartbeatLoop | null = null;\n private activityLog: ActivityLog | null = null;\n private sessionId = \"\";\n\n constructor(options: SupervisorDaemonOptions) {\n this.name = options.name;\n this.config = options.config;\n this.dir = getSupervisorDir(options.name);\n }\n\n async start(): Promise<void> {\n // Create supervisor directory\n await mkdir(this.dir, { recursive: true });\n\n // Check lockfile for duplicate daemons\n const lockPath = path.join(this.dir, \"daemon.lock\");\n if (existsSync(lockPath)) {\n const lockPid = await this.readLockPid(lockPath);\n if (lockPid && this.isProcessAlive(lockPid)) {\n throw new Error(\n `Supervisor \"${this.name}\" already running (PID ${lockPid}). Use --kill first.`,\n );\n }\n // Stale lock — clean up\n await rm(lockPath, { force: true });\n }\n\n // Write lockfile atomically\n const tempLock = `${lockPath}.${process.pid}`;\n await writeFile(tempLock, String(process.pid), \"utf-8\");\n const { rename } = await import(\"node:fs/promises\");\n await rename(tempLock, lockPath);\n\n // Recover session ID from previous state or generate new one\n const existingState = await this.readState();\n if (existingState?.sessionId && existingState.status !== \"stopped\") {\n this.sessionId = existingState.sessionId;\n } else {\n this.sessionId = randomUUID();\n }\n\n // Initialize activity log\n this.activityLog = new ActivityLog(this.dir);\n\n // Initialize event queue\n this.eventQueue = new EventQueue({\n maxEventsPerSec: this.config.supervisor.maxEventsPerSec,\n });\n\n // Replay unprocessed events from disk\n const inboxPath = path.join(this.dir, \"inbox.jsonl\");\n const eventsPath = path.join(this.dir, \"events.jsonl\");\n await this.eventQueue.replayUnprocessed(inboxPath, eventsPath);\n\n // Start file watching\n this.eventQueue.startWatching(inboxPath, eventsPath);\n\n // Start webhook server\n this.webhookServer = new WebhookServer({\n port: this.config.supervisor.port,\n secret: this.config.supervisor.secret,\n eventsPath,\n onEvent: (event) => {\n this.eventQueue?.push({ kind: \"webhook\", data: event });\n },\n getHealth: () => this.getHealthInfo(),\n });\n await this.webhookServer.start();\n\n // Write initial state\n await this.writeState({\n pid: process.pid,\n tmuxSession: `neo-${this.name}`,\n sessionId: this.sessionId,\n port: this.config.supervisor.port,\n cwd: homedir(),\n startedAt: new Date().toISOString(),\n lastHeartbeat: existingState?.lastHeartbeat,\n heartbeatCount: existingState?.heartbeatCount ?? 0,\n totalCostUsd: existingState?.totalCostUsd ?? 0,\n todayCostUsd: existingState?.todayCostUsd ?? 0,\n costResetDate: existingState?.costResetDate,\n status: \"running\",\n });\n\n // Install signal handlers\n const shutdown = () => {\n this.stop().catch(console.error);\n };\n process.on(\"SIGTERM\", shutdown);\n process.on(\"SIGINT\", shutdown);\n\n await this.activityLog.log(\n \"event\",\n `Supervisor \"${this.name}\" started on port ${this.config.supervisor.port}`,\n );\n\n // Start heartbeat loop (blocks until stopped)\n const statePath = path.join(this.dir, \"state.json\");\n this.heartbeatLoop = new HeartbeatLoop({\n config: this.config,\n supervisorDir: this.dir,\n statePath,\n sessionId: this.sessionId,\n eventQueue: this.eventQueue,\n activityLog: this.activityLog,\n });\n\n await this.heartbeatLoop.start();\n }\n\n async stop(): Promise<void> {\n this.heartbeatLoop?.stop();\n this.eventQueue?.stopWatching();\n\n if (this.webhookServer) {\n await this.webhookServer.stop();\n }\n\n // Update state\n const state = await this.readState();\n if (state) {\n state.status = \"stopped\";\n await this.writeState(state);\n }\n\n // Remove lockfile\n const lockPath = path.join(this.dir, \"daemon.lock\");\n await rm(lockPath, { force: true });\n\n if (this.activityLog) {\n await this.activityLog.log(\"event\", `Supervisor \"${this.name}\" stopped`);\n }\n }\n\n private getHealthInfo(): Record<string, unknown> {\n return {\n status: \"ok\",\n name: this.name,\n pid: process.pid,\n uptime: process.uptime(),\n sessionId: this.sessionId,\n port: this.config.supervisor.port,\n };\n }\n\n private async readState(): Promise<SupervisorDaemonState | null> {\n const statePath = path.join(this.dir, \"state.json\");\n try {\n const raw = await readFile(statePath, \"utf-8\");\n return JSON.parse(raw) as SupervisorDaemonState;\n } catch {\n return null;\n }\n }\n\n private async writeState(state: SupervisorDaemonState): Promise<void> {\n const statePath = path.join(this.dir, \"state.json\");\n await writeFile(statePath, JSON.stringify(state, null, 2), \"utf-8\");\n }\n\n private async readLockPid(lockPath: string): Promise<number | null> {\n try {\n const raw = await readFile(lockPath, \"utf-8\");\n const pid = Number.parseInt(raw.trim(), 10);\n return Number.isNaN(pid) ? null : pid;\n } catch {\n return null;\n }\n }\n\n private isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n }\n}\n","import { type FSWatcher, watch } from \"node:fs\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport type { InboxMessage, QueuedEvent, WebhookIncomingEvent } from \"./schemas.js\";\n\ninterface EventQueueOptions {\n maxEventsPerSec: number;\n}\n\n/**\n * In-memory event queue with deduplication, rate limiting, and file watching.\n *\n * Accumulates events from 3 sources:\n * - Webhooks (pushed directly by WebhookServer)\n * - Inbox messages (watched from inbox.jsonl)\n * - Run completions (watched from runs directory)\n *\n * The daemon drains this queue at each heartbeat.\n */\nexport class EventQueue {\n private readonly queue: QueuedEvent[] = [];\n private readonly seenIds = new Set<string>();\n private readonly maxSeenIds = 1000;\n private readonly maxEventsPerSec: number;\n private eventCountThisSecond = 0;\n private currentSecond = 0;\n private watchers: FSWatcher[] = [];\n private fileOffsets = new Map<string, number>();\n\n /** Resolve function to wake up the heartbeat loop when an event arrives */\n private wakeUp: (() => void) | null = null;\n\n constructor(options: EventQueueOptions) {\n this.maxEventsPerSec = options.maxEventsPerSec;\n }\n\n /**\n * Push an event into the queue. Applies dedup and rate limiting.\n */\n push(event: QueuedEvent): boolean {\n // Deduplication by event ID\n const id = this.getEventId(event);\n if (id && this.seenIds.has(id)) return false;\n\n // Rate limiting\n const now = Math.floor(Date.now() / 1000);\n if (now !== this.currentSecond) {\n this.currentSecond = now;\n this.eventCountThisSecond = 0;\n }\n if (this.eventCountThisSecond >= this.maxEventsPerSec) return false;\n this.eventCountThisSecond++;\n\n // Track seen IDs (LRU-style: evict oldest when full)\n if (id) {\n this.seenIds.add(id);\n if (this.seenIds.size > this.maxSeenIds) {\n const first = this.seenIds.values().next().value;\n if (first) this.seenIds.delete(first);\n }\n }\n\n this.queue.push(event);\n this.wakeUp?.();\n return true;\n }\n\n /**\n * Drain all queued events and return them. Clears the queue.\n */\n drain(): QueuedEvent[] {\n const events = [...this.queue];\n this.queue.length = 0;\n return events;\n }\n\n size(): number {\n return this.queue.length;\n }\n\n /**\n * Start watching inbox.jsonl and events.jsonl for new entries.\n * New lines are parsed and pushed into the queue.\n */\n startWatching(inboxPath: string, eventsPath: string): void {\n this.watchJsonlFile(inboxPath, \"message\");\n this.watchJsonlFile(eventsPath, \"webhook\");\n }\n\n stopWatching(): void {\n for (const w of this.watchers) w.close();\n this.watchers = [];\n this.fileOffsets.clear();\n }\n\n /**\n * Replay unprocessed events from disk on startup.\n */\n async replayUnprocessed(inboxPath: string, eventsPath: string): Promise<void> {\n await this.replayFile(inboxPath, \"message\");\n await this.replayFile(eventsPath, \"webhook\");\n }\n\n /**\n * Returns a promise that resolves when a new event arrives or timeout is reached.\n */\n waitForEvent(timeoutMs: number): Promise<void> {\n if (this.queue.length > 0) return Promise.resolve();\n return new Promise<void>((resolve) => {\n const timer = setTimeout(() => {\n this.wakeUp = null;\n resolve();\n }, timeoutMs);\n\n this.wakeUp = () => {\n clearTimeout(timer);\n this.wakeUp = null;\n resolve();\n };\n });\n }\n\n /**\n * Interrupt any pending waitForEvent — used during shutdown.\n */\n interrupt(): void {\n this.wakeUp?.();\n }\n\n private getEventId(event: QueuedEvent): string | undefined {\n if (event.kind === \"webhook\") return event.data.id;\n if (event.kind === \"message\") return event.data.id;\n if (event.kind === \"run_complete\") return `run:${event.runId}`;\n return undefined;\n }\n\n private watchJsonlFile(filePath: string, kind: \"message\" | \"webhook\"): void {\n try {\n const watcher = watch(filePath, () => {\n this.readNewLines(filePath, kind).catch(() => {});\n });\n this.watchers.push(watcher);\n } catch {\n // File may not exist yet — that's fine\n }\n }\n\n private async readNewLines(filePath: string, kind: \"message\" | \"webhook\"): Promise<void> {\n let content: string;\n try {\n content = await readFile(filePath, \"utf-8\");\n } catch {\n return;\n }\n\n const offset = this.fileOffsets.get(filePath) ?? 0;\n if (content.length <= offset) return;\n\n const newContent = content.slice(offset);\n this.fileOffsets.set(filePath, content.length);\n\n const lines = newContent.trim().split(\"\\n\").filter(Boolean);\n for (const line of lines) {\n try {\n const parsed = JSON.parse(line) as Record<string, unknown>;\n if (parsed.processedAt) continue; // Already processed\n\n if (kind === \"webhook\") {\n this.push({ kind: \"webhook\", data: parsed as unknown as WebhookIncomingEvent });\n } else {\n this.push({ kind: \"message\", data: parsed as unknown as InboxMessage });\n }\n } catch {\n // Skip malformed lines\n }\n }\n }\n\n private async replayFile(filePath: string, kind: \"message\" | \"webhook\"): Promise<void> {\n let content: string;\n try {\n content = await readFile(filePath, \"utf-8\");\n } catch {\n return;\n }\n\n // Set offset so watcher doesn't re-read\n this.fileOffsets.set(filePath, content.length);\n\n const lines = content.trim().split(\"\\n\").filter(Boolean);\n const unprocessed: string[] = [];\n for (const line of lines) {\n try {\n const parsed = JSON.parse(line) as Record<string, unknown>;\n if (parsed.processedAt) continue;\n\n if (kind === \"webhook\") {\n this.push({ kind: \"webhook\", data: parsed as unknown as WebhookIncomingEvent });\n } else {\n this.push({ kind: \"message\", data: parsed as unknown as InboxMessage });\n }\n unprocessed.push(line);\n } catch {\n // Skip malformed\n }\n }\n }\n\n /**\n * Mark events as processed by rewriting the source files.\n */\n async markProcessed(inboxPath: string, eventsPath: string, events: QueuedEvent[]): Promise<void> {\n const now = new Date().toISOString();\n\n for (const event of events) {\n if (event.kind === \"webhook\") {\n await this.markInFile(eventsPath, event.data.receivedAt, now);\n } else if (event.kind === \"message\") {\n await this.markInFile(inboxPath, event.data.timestamp, now);\n }\n }\n }\n\n private async markInFile(\n filePath: string,\n matchTimestamp: string,\n processedAt: string,\n ): Promise<void> {\n try {\n const content = await readFile(filePath, \"utf-8\");\n const lines = content.split(\"\\n\");\n let changed = false;\n\n const updated = lines.map((line) => {\n if (!line.trim()) return line;\n try {\n const parsed = JSON.parse(line) as Record<string, unknown>;\n if (\n (parsed.receivedAt === matchTimestamp || parsed.timestamp === matchTimestamp) &&\n !parsed.processedAt\n ) {\n parsed.processedAt = processedAt;\n changed = true;\n return JSON.stringify(parsed);\n }\n } catch {\n // Keep as-is\n }\n return line;\n });\n\n if (changed) {\n await writeFile(filePath, updated.join(\"\\n\"), \"utf-8\");\n this.fileOffsets.set(filePath, updated.join(\"\\n\").length);\n }\n } catch {\n // Non-critical\n }\n }\n}\n","import type { GlobalConfig } from \"@/config\";\nimport { getDataDir } from \"@/paths\";\nimport { randomUUID } from \"node:crypto\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport type { ActivityLog } from \"./activity-log.js\";\nimport type { EventQueue } from \"./event-queue.js\";\nimport { checkMemorySize, extractMemoryFromResponse, loadMemory, saveMemory } from \"./memory.js\";\nimport { buildHeartbeatPrompt } from \"./prompt-builder.js\";\nimport type { SupervisorDaemonState } from \"./schemas.js\";\n\n// ─── SDK message shapes (same as runner/session.ts) ──────\n\ninterface SDKStreamMessage {\n type: string;\n subtype?: string;\n [key: string]: unknown;\n}\n\n// ─── HeartbeatLoop ───────────────────────────────────────\n\nexport interface HeartbeatLoopOptions {\n config: GlobalConfig;\n supervisorDir: string;\n statePath: string;\n sessionId: string;\n eventQueue: EventQueue;\n activityLog: ActivityLog;\n}\n\n/**\n * The core autonomous loop. At each iteration:\n * 1. Drain events from the queue\n * 2. Build a prompt with context + memory + events\n * 3. Call sdk.query() for Claude to reason and act\n * 4. Extract and save updated memory\n * 5. Log activity\n * 6. Wait for the next event or idle timeout\n */\nexport class HeartbeatLoop {\n private stopping = false;\n private consecutiveFailures = 0;\n private activeAbort: AbortController | null = null;\n private readonly config: GlobalConfig;\n private readonly supervisorDir: string;\n private readonly statePath: string;\n private sessionId: string;\n private readonly eventQueue: EventQueue;\n private readonly activityLog: ActivityLog;\n\n private customInstructions: string | undefined;\n\n constructor(options: HeartbeatLoopOptions) {\n this.config = options.config;\n this.supervisorDir = options.supervisorDir;\n this.statePath = options.statePath;\n this.sessionId = options.sessionId;\n this.eventQueue = options.eventQueue;\n this.activityLog = options.activityLog;\n }\n\n async start(): Promise<void> {\n this.customInstructions = await this.loadInstructions();\n await this.activityLog.log(\"heartbeat\", \"Supervisor heartbeat loop started\");\n\n while (!this.stopping) {\n try {\n await this.runHeartbeat();\n this.consecutiveFailures = 0;\n } catch (error) {\n this.consecutiveFailures++;\n const msg = error instanceof Error ? error.message : String(error);\n await this.activityLog.log(\"error\", `Heartbeat failed: ${msg}`, { error: msg });\n\n // Circuit breaker: exponential backoff after consecutive failures\n if (this.consecutiveFailures >= this.config.supervisor.maxConsecutiveFailures) {\n const backoffMs = Math.min(\n this.config.supervisor.idleIntervalMs *\n 2 ** (this.consecutiveFailures - this.config.supervisor.maxConsecutiveFailures),\n 15 * 60 * 1000, // max 15 minutes\n );\n await this.activityLog.log(\n \"error\",\n `Circuit breaker: backing off ${Math.round(backoffMs / 1000)}s after ${this.consecutiveFailures} failures`,\n );\n await this.sleep(backoffMs);\n continue;\n }\n }\n\n if (this.stopping) break;\n\n // Wait for next event or idle timeout\n await this.eventQueue.waitForEvent(this.config.supervisor.idleIntervalMs);\n }\n\n await this.activityLog.log(\"heartbeat\", \"Supervisor heartbeat loop stopped\");\n }\n\n stop(): void {\n this.stopping = true;\n this.activeAbort?.abort(new Error(\"Supervisor shutting down\"));\n this.eventQueue.interrupt();\n }\n\n private async runHeartbeat(): Promise<void> {\n const startTime = Date.now();\n const heartbeatId = randomUUID();\n\n // Check supervisor daily budget\n const state = await this.readState();\n const today = new Date().toISOString().slice(0, 10);\n const todayCost = state?.costResetDate === today ? (state.todayCostUsd ?? 0) : 0;\n\n if (todayCost >= this.config.supervisor.dailyCapUsd) {\n await this.activityLog.log(\n \"error\",\n `Supervisor daily budget exceeded ($${todayCost.toFixed(2)} / $${this.config.supervisor.dailyCapUsd}). Skipping heartbeat.`,\n );\n await this.sleep(this.config.supervisor.idleIntervalMs);\n return;\n }\n\n // Drain events\n const events = this.eventQueue.drain();\n\n // Load memory\n const memory = await loadMemory(this.supervisorDir);\n const memoryCheck = checkMemorySize(memory);\n\n // Build prompt\n const mcpServerNames = this.config.mcpServers ? Object.keys(this.config.mcpServers) : [];\n\n const prompt = buildHeartbeatPrompt({\n repos: this.config.repos,\n memory,\n memorySizeKB: memoryCheck.sizeKB,\n events,\n budgetStatus: {\n todayUsd: todayCost,\n capUsd: this.config.supervisor.dailyCapUsd,\n remainingPct:\n ((this.config.supervisor.dailyCapUsd - todayCost) / this.config.supervisor.dailyCapUsd) *\n 100,\n },\n activeRuns: [], // TODO: read from persisted runs\n heartbeatCount: state?.heartbeatCount ?? 0,\n mcpServerNames,\n customInstructions: this.customInstructions,\n });\n\n await this.activityLog.log(\"heartbeat\", `Heartbeat #${state?.heartbeatCount ?? 0} starting`, {\n heartbeatId,\n eventCount: events.length,\n triggeredBy: events.map((e) => e.kind),\n });\n\n // Call SDK with timeout + shutdown abort\n const abortController = new AbortController();\n this.activeAbort = abortController;\n const timeout = setTimeout(() => {\n abortController.abort(new Error(\"Heartbeat timeout exceeded\"));\n }, this.config.supervisor.heartbeatTimeoutMs);\n\n let output = \"\";\n let costUsd = 0;\n let turnCount = 0;\n\n try {\n const sdk = await import(\"@anthropic-ai/claude-agent-sdk\");\n\n const queryOptions: Record<string, unknown> = {\n cwd: homedir(),\n maxTurns: 50,\n allowedTools: [\"Bash\", \"Read\"],\n permissionMode: \"bypassPermissions\",\n allowDangerouslySkipPermissions: true,\n };\n\n // Each heartbeat starts a fresh session — resume is unreliable\n // because the previous query completed and the session may not\n // be resumable. The prompt already contains memory for continuity.\n\n // Pass MCP servers if configured\n if (this.config.mcpServers) {\n queryOptions.mcpServers = this.config.mcpServers;\n }\n\n const stream = sdk.query({ prompt, options: queryOptions as never });\n\n for await (const message of stream) {\n if (abortController.signal.aborted) break;\n\n const msg = message as SDKStreamMessage;\n\n if (msg.type === \"system\" && msg.subtype === \"init\") {\n this.sessionId = msg.session_id as string;\n }\n\n if (msg.type === \"result\") {\n output = (msg.result as string) ?? \"\";\n costUsd = (msg.total_cost_usd as number) ?? 0;\n turnCount = (msg.num_turns as number) ?? 0;\n }\n\n await this.logStreamMessage(msg, heartbeatId);\n }\n } finally {\n clearTimeout(timeout);\n this.activeAbort = null;\n }\n\n // Extract and save memory\n const newMemory = extractMemoryFromResponse(output);\n if (newMemory) {\n await saveMemory(this.supervisorDir, newMemory);\n }\n\n // Update state\n const durationMs = Date.now() - startTime;\n await this.updateState({\n sessionId: this.sessionId,\n lastHeartbeat: new Date().toISOString(),\n heartbeatCount: (state?.heartbeatCount ?? 0) + 1,\n totalCostUsd: (state?.totalCostUsd ?? 0) + costUsd,\n todayCostUsd: todayCost + costUsd,\n costResetDate: today,\n });\n\n await this.activityLog.log(\n \"heartbeat\",\n `Heartbeat #${(state?.heartbeatCount ?? 0) + 1} complete`,\n {\n heartbeatId,\n costUsd,\n durationMs,\n turnCount,\n memoryUpdated: !!newMemory,\n responseSummary: output.slice(0, 500),\n },\n );\n }\n\n private async readState(): Promise<SupervisorDaemonState | null> {\n try {\n const raw = await readFile(this.statePath, \"utf-8\");\n return JSON.parse(raw) as SupervisorDaemonState;\n } catch {\n return null;\n }\n }\n\n private async updateState(updates: Partial<SupervisorDaemonState>): Promise<void> {\n try {\n const raw = await readFile(this.statePath, \"utf-8\");\n const state = JSON.parse(raw) as SupervisorDaemonState;\n Object.assign(state, updates);\n await writeFile(this.statePath, JSON.stringify(state, null, 2), \"utf-8\");\n } catch {\n // Non-critical\n }\n }\n\n /**\n * Load custom instructions from SUPERVISOR.md.\n * Resolution order:\n * 1. Explicit path via `supervisor.instructions` in config\n * 2. Default: ~/.neo/SUPERVISOR.md\n */\n private async loadInstructions(): Promise<string | undefined> {\n const candidates: string[] = [];\n\n if (this.config.supervisor.instructions) {\n candidates.push(path.resolve(this.config.supervisor.instructions));\n }\n\n candidates.push(path.join(getDataDir(), \"SUPERVISOR.md\"));\n\n for (const filePath of candidates) {\n try {\n const content = await readFile(filePath, \"utf-8\");\n await this.activityLog.log(\"event\", `Loaded custom instructions from ${filePath}`);\n return content;\n } catch {\n // File not found — try next candidate\n }\n }\n\n return undefined;\n }\n\n /** Route a single SDK stream message to the appropriate log handler. */\n private async logStreamMessage(msg: SDKStreamMessage, heartbeatId: string): Promise<void> {\n if (msg.type !== \"assistant\") return;\n\n if (!msg.subtype) {\n await this.logContentBlocks(msg, heartbeatId);\n } else if (msg.subtype === \"tool_use\") {\n await this.logToolUse(msg, heartbeatId);\n } else if (msg.subtype === \"tool_result\") {\n await this.logToolResult(msg, heartbeatId);\n }\n }\n\n /** Log thinking and plan blocks from assistant content. */\n private async logContentBlocks(msg: SDKStreamMessage, heartbeatId: string): Promise<void> {\n const content = (\n msg.message as\n | { content?: Array<{ type: string; thinking?: string; text?: string }> }\n | undefined\n )?.content;\n if (!content) return;\n\n for (const block of content) {\n if (block.type === \"thinking\" && block.thinking) {\n await this.activityLog.log(\"thinking\", block.thinking.slice(0, 500), { heartbeatId });\n }\n if (block.type === \"text\" && block.text) {\n await this.activityLog.log(\"plan\", block.text.slice(0, 500), { heartbeatId });\n break; // Only log first text block per message\n }\n }\n }\n\n /** Log tool use events — distinguish MCP tools from built-in tools. */\n private async logToolUse(msg: SDKStreamMessage, heartbeatId: string): Promise<void> {\n const toolName = String(msg.tool ?? \"unknown\");\n const isMcp = toolName.startsWith(\"mcp__\");\n await this.activityLog.log(\n isMcp ? \"tool_use\" : \"action\",\n isMcp ? toolName : `Tool use: ${toolName}`,\n { heartbeatId, tool: toolName, input: msg.input },\n );\n }\n\n /** Detect agent dispatches from bash tool results. */\n private async logToolResult(msg: SDKStreamMessage, heartbeatId: string): Promise<void> {\n const result = String(msg.result ?? \"\");\n const runMatch = /Run\\s+(\\S+)\\s+dispatched/i.exec(result);\n if (runMatch) {\n await this.activityLog.log(\"dispatch\", `Agent dispatched: ${runMatch[1]}`, {\n heartbeatId,\n runId: runMatch[1],\n });\n }\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nconst MEMORY_FILE = \"memory.md\";\nconst MAX_SIZE_KB = 10;\n\n// ─── Structured memory type ─────────────────────────────\n\nexport interface SupervisorMemory {\n activeWork: string[];\n blockers: string[];\n repoNotes: Record<string, string>;\n recentDecisions: Array<{\n date: string;\n decision: string;\n outcome?: string;\n }>;\n trackerSync: Record<string, string>;\n notes: string;\n}\n\n/**\n * Parse raw memory content into structured format.\n * Tries JSON first, falls back to wrapping raw markdown in { notes }.\n */\nexport function parseStructuredMemory(raw: string): SupervisorMemory {\n if (!raw.trim()) {\n return emptyMemory();\n }\n try {\n const parsed = JSON.parse(raw) as Partial<SupervisorMemory>;\n return {\n activeWork: parsed.activeWork ?? [],\n blockers: parsed.blockers ?? [],\n repoNotes: parsed.repoNotes ?? {},\n recentDecisions: parsed.recentDecisions ?? [],\n trackerSync: parsed.trackerSync ?? {},\n notes: parsed.notes ?? \"\",\n };\n } catch {\n // Legacy markdown format — wrap in notes\n return { ...emptyMemory(), notes: raw };\n }\n}\n\nfunction emptyMemory(): SupervisorMemory {\n return {\n activeWork: [],\n blockers: [],\n repoNotes: {},\n recentDecisions: [],\n trackerSync: {},\n notes: \"\",\n };\n}\n\n/**\n * Load the supervisor memory from disk.\n * Returns empty string if no memory file exists yet.\n */\nexport async function loadMemory(dir: string): Promise<string> {\n try {\n return await readFile(path.join(dir, MEMORY_FILE), \"utf-8\");\n } catch {\n return \"\";\n }\n}\n\n/**\n * Save the supervisor memory to disk (full overwrite).\n */\nexport async function saveMemory(dir: string, content: string): Promise<void> {\n await writeFile(path.join(dir, MEMORY_FILE), content, \"utf-8\");\n}\n\n/**\n * Extract memory content from Claude's response using <memory>...</memory> tags.\n * Handles both JSON and markdown content inside the tags.\n * Returns null if no memory block is found.\n */\nexport function extractMemoryFromResponse(response: string): string | null {\n const match = /<memory>([\\s\\S]*?)<\\/memory>/i.exec(response);\n if (!match?.[1]) return null;\n const content = match[1].trim();\n\n // Validate JSON if it looks like JSON — ensure it round-trips\n if (content.startsWith(\"{\")) {\n try {\n JSON.parse(content);\n return content;\n } catch {\n // Malformed JSON — still save as raw text\n }\n }\n return content;\n}\n\n/**\n * Check if memory content exceeds the recommended size limit.\n */\nexport function checkMemorySize(content: string): { ok: boolean; sizeKB: number } {\n const sizeKB = Buffer.byteLength(content, \"utf-8\") / 1024;\n return { ok: sizeKB <= MAX_SIZE_KB, sizeKB: Math.round(sizeKB * 10) / 10 };\n}\n","import type { RepoConfig } from \"@/config\";\nimport type { QueuedEvent } from \"./schemas.js\";\n\nexport interface HeartbeatPromptOptions {\n repos: RepoConfig[];\n memory: string;\n memorySizeKB: number;\n events: QueuedEvent[];\n budgetStatus: {\n todayUsd: number;\n capUsd: number;\n remainingPct: number;\n };\n activeRuns: string[];\n heartbeatCount: number;\n mcpServerNames: string[];\n customInstructions?: string | undefined;\n}\n\n/**\n * Build the prompt sent to Claude at each heartbeat.\n *\n * Includes: role definition, current memory, pending events,\n * budget status, active runs, and available integrations.\n */\nexport function buildHeartbeatPrompt(opts: HeartbeatPromptOptions): string {\n const sections: string[] = [];\n\n // ─── Role ──────────────────────────────────────────────\n sections.push(`You are the neo autonomous supervisor (heartbeat #${opts.heartbeatCount}).\nYou orchestrate developer agents across repositories. You make decisions autonomously.\n\nYour job:\n1. Process any incoming events (webhooks, user messages, run completions)\n2. Decide what actions to take (dispatch agents, check status, respond to users)\n3. Update your memory with relevant context for future heartbeats\n4. If nothing to do, simply acknowledge and wait\n\nAvailable commands (via bash):\n neo run <agent> --prompt \"...\" [--repo <path>] dispatch an agent\n neo runs --short [--all] check recent runs\n neo cost --short [--all] check budget\n neo agents list available agents\n\nIMPORTANT: Always include a <memory>...</memory> block at the end of your response with your updated memory.`);\n\n // ─── Custom instructions (SUPERVISOR.md) ─────────────\n if (opts.customInstructions) {\n sections.push(`## Custom instructions\\n${opts.customInstructions}`);\n }\n\n // ─── Repos ─────────────────────────────────────────────\n if (opts.repos.length > 0) {\n const repoList = opts.repos.map((r) => `- ${r.path} (branch: ${r.defaultBranch})`).join(\"\\n\");\n sections.push(`## Registered repositories\\n${repoList}`);\n } else {\n sections.push(\"## Registered repositories\\n(none — run 'neo init' in a repo to register it)\");\n }\n\n // ─── MCP Integrations ─────────────────────────────────\n if (opts.mcpServerNames.length > 0) {\n const mcpList = opts.mcpServerNames.map((n) => `- ${n}`).join(\"\\n\");\n\n sections.push(\n `## Available integrations (MCP)\\n${mcpList}\\n\\nYou can use these tools directly to query external systems.`,\n );\n }\n\n // ─── Budget ────────────────────────────────────────────\n sections.push(\n `## Budget status\\n- Today: $${opts.budgetStatus.todayUsd.toFixed(2)} / $${opts.budgetStatus.capUsd.toFixed(2)} (${opts.budgetStatus.remainingPct.toFixed(0)}% remaining)`,\n );\n\n // ─── Active runs ───────────────────────────────────────\n if (opts.activeRuns.length > 0) {\n sections.push(`## Active runs\\n${opts.activeRuns.map((r) => `- ${r}`).join(\"\\n\")}`);\n }\n\n // ─── Events ────────────────────────────────────────────\n if (opts.events.length > 0) {\n const eventDescriptions = opts.events.map(formatEvent);\n sections.push(`## Pending events (${opts.events.length})\\n${eventDescriptions.join(\"\\n\\n\")}`);\n } else {\n sections.push(\n \"## Pending events\\nNo new events. This is an idle heartbeat — check on active runs if any, or wait.\",\n );\n }\n\n // ─── Memory ────────────────────────────────────────────\n sections.push(buildMemorySection(opts.memory, opts.memorySizeKB));\n\n return sections.join(\"\\n\\n---\\n\\n\");\n}\n\nfunction buildMemorySection(memory: string, memorySizeKB: number): string {\n const schema = `{\n \"activeWork\": [\"description of current task 1\", ...],\n \"blockers\": [\"what is stuck and why\", ...],\n \"repoNotes\": { \"/path/to/repo\": \"relevant context about this repo\" },\n \"recentDecisions\": [{ \"date\": \"YYYY-MM-DD\", \"decision\": \"what you decided\", \"outcome\": \"result\" }],\n \"trackerSync\": { \"ticket-id\": \"last known status\" },\n \"notes\": \"free-form context that doesn't fit elsewhere\"\n}`;\n\n if (!memory) {\n return `## Your current memory\n(empty — this is your first heartbeat, initialize your memory)\n\nYour memory MUST be a JSON object inside \\`<memory>...</memory>\\` tags:\n\\`\\`\\`\n${schema}\n\\`\\`\\`\nKeep under 8KB. Prune old decisions (keep last 10).`;\n }\n\n const sizeWarning =\n memorySizeKB > 8\n ? \"\\n\\n**Memory is over 8KB — condense it. Remove old decisions, summarize notes.**\"\n : \"\";\n\n return `## Your current memory (${memorySizeKB}KB)${sizeWarning}\n${memory}\n\nRemember: update your memory as a JSON object inside \\`<memory>...</memory>\\` tags.\nSchema: ${schema}`;\n}\n\nfunction formatEvent(event: QueuedEvent): string {\n switch (event.kind) {\n case \"webhook\":\n return `**Webhook** [${event.data.source ?? \"unknown\"}] ${event.data.event ?? \"\"}\n\\`\\`\\`json\n${JSON.stringify(event.data.payload ?? {}, null, 2).slice(0, 2000)}\n\\`\\`\\``;\n\n case \"message\":\n return `**Message from ${event.data.from}**: ${event.data.text}`;\n\n case \"run_complete\":\n return `**Run completed**: ${event.runId} (check with \\`neo runs\\`)`;\n }\n}\n","import { timingSafeEqual } from \"node:crypto\";\nimport { appendFile } from \"node:fs/promises\";\nimport { createServer, type IncomingMessage, type Server, type ServerResponse } from \"node:http\";\nimport type { WebhookIncomingEvent } from \"./schemas.js\";\n\nconst MAX_BODY_SIZE = 1024 * 1024; // 1MB\n\ninterface WebhookServerOptions {\n port: number;\n secret?: string | undefined;\n eventsPath: string;\n onEvent: (event: WebhookIncomingEvent) => void;\n getHealth: () => Record<string, unknown>;\n}\n\n/**\n * Minimal HTTP server for receiving incoming webhooks.\n *\n * Routes:\n * POST /webhook — receive any JSON payload, persist to disk, push to queue\n * GET /health — liveness check with daemon status\n *\n * Uses raw http.createServer — zero external dependencies.\n */\nexport class WebhookServer {\n private server: Server | null = null;\n private readonly port: number;\n private readonly secret: string | undefined;\n private readonly eventsPath: string;\n private readonly onEvent: (event: WebhookIncomingEvent) => void;\n private readonly getHealth: () => Record<string, unknown>;\n\n constructor(options: WebhookServerOptions) {\n this.port = options.port;\n this.secret = options.secret;\n this.eventsPath = options.eventsPath;\n this.onEvent = options.onEvent;\n this.getHealth = options.getHealth;\n }\n\n async start(): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n this.server = createServer((req, res) => {\n this.handleRequest(req, res).catch((err) => {\n this.sendJson(res, 500, { error: \"Internal server error\", detail: String(err) });\n });\n });\n\n this.server.on(\"error\", reject);\n\n this.server.listen(this.port, () => {\n resolve();\n });\n });\n }\n\n async stop(): Promise<void> {\n return new Promise<void>((resolve) => {\n if (!this.server) {\n resolve();\n return;\n }\n this.server.close(() => resolve());\n });\n }\n\n private async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const url = req.url ?? \"/\";\n\n if (req.method === \"GET\" && url === \"/health\") {\n this.sendJson(res, 200, this.getHealth());\n return;\n }\n\n if (req.method === \"POST\" && url === \"/webhook\") {\n await this.handleWebhook(req, res);\n return;\n }\n\n this.sendJson(res, 404, { error: \"Not found\" });\n }\n\n private async handleWebhook(req: IncomingMessage, res: ServerResponse): Promise<void> {\n // Validate secret if configured\n if (this.secret) {\n const provided = req.headers[\"x-neo-secret\"] as string | undefined;\n if (!provided) {\n this.sendJson(res, 401, { error: \"Missing X-Neo-Secret header\" });\n return;\n }\n\n const expected = Buffer.from(this.secret, \"utf-8\");\n const actual = Buffer.from(provided, \"utf-8\");\n if (expected.length !== actual.length || !timingSafeEqual(expected, actual)) {\n this.sendJson(res, 403, { error: \"Invalid secret\" });\n return;\n }\n }\n\n // Read body with size limit\n const body = await this.readBody(req);\n if (body === null) {\n this.sendJson(res, 413, { error: \"Payload too large (max 1MB)\" });\n return;\n }\n\n // Parse JSON\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(body) as Record<string, unknown>;\n } catch {\n this.sendJson(res, 400, { error: \"Invalid JSON\" });\n return;\n }\n\n const event: WebhookIncomingEvent = {\n id: typeof parsed.id === \"string\" ? parsed.id : undefined,\n source: typeof parsed.source === \"string\" ? parsed.source : undefined,\n event: typeof parsed.event === \"string\" ? parsed.event : undefined,\n payload: (parsed.payload as Record<string, unknown> | undefined) ?? parsed,\n receivedAt: new Date().toISOString(),\n };\n\n // Disk-first: persist before pushing to memory\n await appendFile(this.eventsPath, `${JSON.stringify(event)}\\n`, \"utf-8\");\n\n // Push to in-memory queue\n this.onEvent(event);\n\n this.sendJson(res, 200, { ok: true, id: event.id });\n }\n\n private readBody(req: IncomingMessage): Promise<string | null> {\n return new Promise((resolve) => {\n const chunks: Buffer[] = [];\n let size = 0;\n\n req.on(\"data\", (chunk: Buffer) => {\n size += chunk.length;\n if (size > MAX_BODY_SIZE) {\n resolve(null);\n req.destroy();\n return;\n }\n chunks.push(chunk);\n });\n\n req.on(\"end\", () => {\n resolve(Buffer.concat(chunks).toString(\"utf-8\"));\n });\n\n req.on(\"error\", () => resolve(null));\n });\n }\n\n private sendJson(res: ServerResponse, status: number, data: unknown): void {\n res.writeHead(status, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify(data));\n }\n}\n","export const VERSION = \"0.1.0\";\n\n// ─── Orchestrator (public API) ──────────────────────────\n\nexport { loadAgentFile } from \"@/agents/loader\";\nexport { AgentRegistry } from \"@/agents/registry\";\nexport { resolveAgent } from \"@/agents/resolver\";\nexport {\n agentConfigSchema,\n agentModelSchema,\n agentSandboxSchema,\n agentToolEntrySchema,\n agentToolSchema,\n} from \"@/agents/schema\";\nexport type {\n SemaphoreCallbacks,\n SemaphoreConfig,\n} from \"@/concurrency/semaphore\";\n// ─── Concurrency ────────────────────────────────────────\nexport { Semaphore } from \"@/concurrency/semaphore\";\nexport type {\n GlobalConfig,\n McpServerConfig,\n NeoConfig,\n RepoConfig,\n RepoConfigInput,\n} from \"@/config\";\nexport {\n addRepoToGlobalConfig,\n globalConfigSchema,\n listReposFromGlobalConfig,\n loadConfig,\n loadGlobalConfig,\n mcpServerConfigSchema,\n neoConfigSchema,\n removeRepoFromGlobalConfig,\n repoConfigSchema,\n} from \"@/config\";\n// ─── Cost ──────────────────────────────────────────────\nexport { CostJournal } from \"@/cost/journal\";\nexport { NeoEventEmitter } from \"@/events\";\n// ─── Events ────────────────────────────────────────────\nexport { EventJournal } from \"@/events/journal\";\nexport { matchesFilter, WebhookDispatcher } from \"@/events/webhook\";\nexport {\n createBranch,\n deleteBranch,\n fetchRemote,\n getBranchName,\n getCurrentBranch,\n pushBranch,\n} from \"@/isolation/git\";\n// ─── Isolation ──────────────────────────────────────────\nexport { withGitLock } from \"@/isolation/git-mutex\";\nexport type { SandboxConfig } from \"@/isolation/sandbox\";\nexport { buildSandboxConfig } from \"@/isolation/sandbox\";\nexport type { WorktreeInfo } from \"@/isolation/worktree\";\nexport {\n cleanupOrphanedWorktrees,\n createWorktree,\n listWorktrees,\n removeWorktree,\n} from \"@/isolation/worktree\";\nexport type { AuditLogMiddleware } from \"@/middleware/audit-log\";\n// ─── Middleware ─────────────────────────────────────────\nexport { auditLog } from \"@/middleware/audit-log\";\nexport { budgetGuard } from \"@/middleware/budget-guard\";\nexport type { MiddlewareChain, SDKHooks } from \"@/middleware/chain\";\nexport { buildMiddlewareChain, buildSDKHooks } from \"@/middleware/chain\";\nexport type { LoopDetectionMiddleware } from \"@/middleware/loop-detection\";\nexport { loopDetection } from \"@/middleware/loop-detection\";\nexport type { OrchestratorOptions } from \"@/orchestrator\";\nexport { Orchestrator } from \"@/orchestrator\";\n// ─── Paths ─────────────────────────────────────────────\nexport {\n getDataDir,\n getJournalsDir,\n getRepoRunsDir,\n getRunDispatchPath,\n getRunLogPath,\n getRunsDir,\n getSupervisorActivityPath,\n getSupervisorDir,\n getSupervisorEventsPath,\n getSupervisorInboxPath,\n getSupervisorLockPath,\n getSupervisorMemoryPath,\n getSupervisorStatePath,\n getSupervisorsDir,\n toRepoSlug,\n} from \"@/paths\";\nexport type { ParsedOutput } from \"@/runner/output-parser\";\n// ─── Runner ────────────────────────────────────────────\nexport { parseOutput } from \"@/runner/output-parser\";\nexport type { RecoveryOptions } from \"@/runner/recovery\";\nexport { runWithRecovery } from \"@/runner/recovery\";\nexport type {\n SessionEvent,\n SessionOptions,\n SessionResult,\n} from \"@/runner/session\";\nexport { runSession, SessionError } from \"@/runner/session\";\n// ─── Supervisor (legacy) ──────────────────────────────\nexport type { SupervisorState } from \"@/supervisor\";\nexport { supervisorStateSchema } from \"@/supervisor\";\n// ─── Supervisor (daemon) ──────────────────────────────\nexport type {\n ActivityEntry,\n HeartbeatLoopOptions,\n HeartbeatPromptOptions,\n InboxMessage,\n QueuedEvent,\n SupervisorDaemonOptions,\n SupervisorDaemonState,\n WebhookIncomingEvent,\n} from \"@/supervisor/index\";\nexport {\n ActivityLog,\n activityEntrySchema,\n buildHeartbeatPrompt,\n checkMemorySize,\n EventQueue,\n extractMemoryFromResponse,\n HeartbeatLoop,\n inboxMessageSchema,\n loadMemory,\n SupervisorDaemon,\n saveMemory,\n supervisorDaemonStateSchema,\n WebhookServer,\n webhookIncomingEventSchema,\n} from \"@/supervisor/index\";\nexport * from \"@/types\";\n// ─── Workflows ─────────────────────────────────────────\nexport { loadWorkflow, workflowGateDefSchema, workflowStepDefSchema } from \"@/workflows/loader\";\nexport { WorkflowRegistry } from \"@/workflows/registry\";\n"],"mappings":"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","names":["path","tools","prompt","definition","path","resolve","readFile","path","parseYaml","z","path","z","parseYaml","readFile","path","mkdir","readFile","path","appendFile","mkdir","path","resolve","resolve","execFile","existsSync","readdir","resolve","promisify","execFileAsync","promisify","execFile","GIT_TIMEOUT","resolve","existsSync","readdir","appendFile","mkdir","path","existsSync","mkdir","readdir","readFile","writeFile","path","resolve","existsSync","readdir","path","readFile","z","existsSync","readdir","path","path","resolve","existsSync","mkdir","writeFile","readdir","readFile","z","randomUUID","appendFile","readFile","path","randomUUID","existsSync","mkdir","readFile","rm","writeFile","homedir","path","readFile","writeFile","resolve","randomUUID","readFile","writeFile","homedir","path","readFile","writeFile","path","readFile","path","writeFile","randomUUID","homedir","readFile","writeFile","path","resolve","appendFile","resolve","mkdir","path","existsSync","rm","writeFile","rename","randomUUID","homedir","readFile"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@neotx/core",
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"description": "Orchestration framework for autonomous developer agents",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/voltaire-network/neo.git",
|
|
10
|
+
"directory": "packages/core"
|
|
11
|
+
},
|
|
12
|
+
"main": "dist/index.js",
|
|
13
|
+
"types": "dist/index.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"import": "./dist/index.js",
|
|
17
|
+
"types": "./dist/index.d.ts"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"ai-agents",
|
|
28
|
+
"claude",
|
|
29
|
+
"orchestration",
|
|
30
|
+
"autonomous-agents",
|
|
31
|
+
"developer-tools",
|
|
32
|
+
"git-worktree",
|
|
33
|
+
"agent-sdk"
|
|
34
|
+
],
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=22"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@anthropic-ai/claude-agent-sdk": "^0.1.0",
|
|
40
|
+
"yaml": "^2.8.2",
|
|
41
|
+
"zod": "^4.3.6"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/node": "^25.5.0",
|
|
45
|
+
"tsup": "^8.5.1"
|
|
46
|
+
},
|
|
47
|
+
"scripts": {
|
|
48
|
+
"build": "tsup",
|
|
49
|
+
"typecheck": "tsc --noEmit",
|
|
50
|
+
"lint": "biome check src/",
|
|
51
|
+
"lint:fix": "biome check --write src/",
|
|
52
|
+
"test": "vitest run"
|
|
53
|
+
}
|
|
54
|
+
}
|