openfox 0.1.0 → 0.2.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/dist/agent-defaults/builder.agent.md +38 -0
- package/dist/agent-defaults/code-reviewer.agent.md +21 -0
- package/dist/agent-defaults/debugger.agent.md +21 -0
- package/dist/agent-defaults/planner.agent.md +35 -0
- package/dist/agent-defaults/test-generator.agent.md +22 -0
- package/dist/agent-defaults/verifier.agent.md +41 -0
- package/dist/{chunk-FF6Z2MC3.js → chunk-5ZUU23XF.js} +18 -1
- package/dist/{chunk-IVHCPQO2.js → chunk-ARFK3RZW.js} +1 -1
- package/dist/{chunk-IKAWIOXM.js → chunk-FUUYYDVG.js} +387 -73
- package/dist/{chunk-YQ36AK5A.js → chunk-JFQEATRC.js} +623 -327
- package/dist/{chunk-43SWNGYW.js → chunk-L475ND2Z.js} +9 -9
- package/dist/{chunk-6MOGZMGX.js → chunk-L4XDA3V7.js} +2 -2
- package/dist/{chunk-EI46G5WO.js → chunk-MKAHOQBI.js} +10 -10
- package/dist/cli/dev.js +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/{config-6GJ4SVFH.js → config-BMXSDOZB.js} +3 -3
- package/dist/{init-UVZDOHMX.js → init-PLRTRSDC.js} +6 -6
- package/dist/{protocol-BJsm88OW.d.ts → protocol-BFFz3WM0.d.ts} +14 -3
- package/dist/{provider-LCE6WZA6.js → provider-ETVY64A2.js} +5 -5
- package/dist/{serve-27DZK34K.js → serve-EOKIXTWM.js} +8 -8
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +5 -5
- package/dist/shared/index.d.ts +2 -2
- package/dist/shared/index.js +1 -1
- package/dist/{tools-R4YQAYUF.js → tools-QMIIDJTV.js} +7 -5
- package/dist/web/assets/index-CAD7Iv_d.js +122 -0
- package/dist/web/assets/{index-BSlSWZrM.css → index-DHmZmhnR.css} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +34 -16
- package/dist/branch.api-WDHKZJS6.js.map +0 -1
- package/dist/chunk-26NRL3HX.js.map +0 -1
- package/dist/chunk-43SWNGYW.js.map +0 -1
- package/dist/chunk-4Z2OZ6NX.js.map +0 -1
- package/dist/chunk-6MOGZMGX.js.map +0 -1
- package/dist/chunk-AF7XS4OI.js.map +0 -1
- package/dist/chunk-EI46G5WO.js.map +0 -1
- package/dist/chunk-FF6Z2MC3.js.map +0 -1
- package/dist/chunk-IKAWIOXM.js.map +0 -1
- package/dist/chunk-IVHCPQO2.js.map +0 -1
- package/dist/chunk-MTX5Y3V3.js.map +0 -1
- package/dist/chunk-N2XYX4ZA.js.map +0 -1
- package/dist/chunk-QY7BMXWT.js.map +0 -1
- package/dist/chunk-U62ZECSQ.js.map +0 -1
- package/dist/chunk-YQ36AK5A.js.map +0 -1
- package/dist/cli/dev.js.map +0 -1
- package/dist/cli/index.js.map +0 -1
- package/dist/config-6GJ4SVFH.js.map +0 -1
- package/dist/init-UVZDOHMX.js.map +0 -1
- package/dist/paths-4BPXWB2W.js.map +0 -1
- package/dist/project-creator-CWPKRIKI.js.map +0 -1
- package/dist/provider-LCE6WZA6.js.map +0 -1
- package/dist/serve-27DZK34K.js.map +0 -1
- package/dist/server/index.js.map +0 -1
- package/dist/settings-D5O3TMLD.js.map +0 -1
- package/dist/shared/index.js.map +0 -1
- package/dist/tools-R4YQAYUF.js.map +0 -1
- package/dist/web/assets/index-BMNDCsbJ.js +0 -120
- /package/dist/command-defaults/{defaults/commit-push.command.md → commit-push.command.md} +0 -0
- /package/dist/command-defaults/{defaults/init.command.md → init.command.md} +0 -0
- /package/dist/command-defaults/{defaults/test-ui.command.md → test-ui.command.md} +0 -0
- /package/dist/skill-defaults/{defaults/playwright-cli.skill.md → playwright-cli.skill.md} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server/index.ts","../src/server/llm/mock.ts","../src/server/ws/server.ts","../src/server/sub-agents/verifier-helpers.ts","../src/server/chat/orchestrator.ts","../src/server/workflows/registry.ts","../src/server/runner/types.ts","../src/server/workflows/types.ts","../src/server/workflows/shell.ts","../src/server/workflows/executor.ts","../src/server/runner/orchestrator.ts","../src/server/db/sessions.ts","../src/server/session/name-generator.ts","../src/server/session/summary-generator.ts","../src/server/lsp/server.ts","../src/server/utils/which.ts","../src/server/lsp/languages.ts","../src/server/lsp/manager.ts","../src/server/context/tokenizer.ts","../src/server/session/manager.ts","../src/server/commands/registry.ts"],"sourcesContent":["import express from 'express'\nimport cors from 'cors'\nimport { createServer as createHttpServer } from 'node:http'\nimport { fileURLToPath } from 'node:url'\nimport { dirname, resolve, join } from 'node:path'\nimport { readFile } from 'node:fs/promises'\nimport { createServer as createViteServer, type ViteDevServer } from 'vite'\n\nimport type { Config, Provider } from '../shared/types.js'\nimport type { ServerHandle } from './context.js'\nimport { initDatabase, closeDatabase, getDatabase } from './db/index.js'\nimport { initEventStore } from './events/index.js'\nimport { createLLMClient, detectModel, getLlmStatus, detectBackend, getBackendDisplayName, type Backend } from './llm/index.js'\nimport { createMockLLMClient } from './llm/mock.js'\nimport { createProviderManager } from './provider-manager.js'\nimport { createToolRegistry } from './tools/index.js'\nimport { createWebSocketServer } from './ws/index.js'\nimport { SessionManager } from './session/manager.js'\nimport { setRuntimeConfig, getRuntimeConfig } from './runtime-config.js'\nimport { ensureDefaultSkills, loadAllSkills, isSkillEnabled, setSkillEnabled, findSkillById, saveSkill, deleteSkill, skillExists, getDefaultSkillIds, getModifiedDefaultSkillIds, restoreDefaultSkill, restoreAllDefaultSkills } from './skills/registry.js'\nimport type { SkillDefinition } from './skills/types.js'\nimport { ensureDefaultCommands, loadAllCommands, findCommandById, saveCommand, deleteCommand, commandExists, getDefaultCommandIds, getModifiedDefaultCommandIds, restoreDefaultCommand, restoreAllDefaultCommands } from './commands/registry.js'\nimport type { CommandDefinition } from './commands/types.js'\nimport { ensureDefaultAgents, loadAllAgents, findAgentById, getSubAgents, getTopLevelAgents, saveAgent, deleteAgent, agentExists, getDefaultAgentIds, getModifiedDefaultAgentIds, restoreDefaultAgent, restoreAllDefaultAgents } from './agents/registry.js'\nimport type { AgentDefinition } from './agents/types.js'\nimport { ensureDefaultWorkflows, loadAllWorkflows, findWorkflowById, saveWorkflow, deleteWorkflow, workflowExists, getDefaultWorkflowIds, getModifiedDefaultWorkflowIds, restoreDefaultWorkflow, restoreAllDefaultWorkflows } from './workflows/registry.js'\nimport type { WorkflowDefinition } from './workflows/types.js'\nimport { getGlobalConfigDir } from '../cli/paths.js'\nimport { logger, setLogLevel } from './utils/logger.js'\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\n/**\n * Create a server handle that can be started on any port.\n * Returns a ServerHandle with start() and close() methods.\n * \n * Use this for:\n * - In-process testing with isolated instances\n * - Programmatic server control\n */\nexport async function createServerHandle(config: Config): Promise<ServerHandle> {\n setRuntimeConfig(config)\n\n // Set log level\n setLogLevel(config.logging?.level ?? undefined, config.mode)\n\n // Initialize database\n const db = initDatabase(config)\n\n // Initialize event store\n initEventStore(db)\n\n // Initialize skills and commands (copy defaults to config dir)\n const configDir = getGlobalConfigDir(config.mode ?? 'production')\n await ensureDefaultSkills(configDir)\n await ensureDefaultCommands(configDir)\n await ensureDefaultAgents(configDir)\n await ensureDefaultWorkflows(configDir)\n\n // Create SessionManager instance (not singleton!)\n const sessionManager = new SessionManager()\n\n // Create Provider Manager (handles LLM client lifecycle)\n const providerManager = createProviderManager(config)\n \n // Create LLM client - use mock if OPENFOX_MOCK_LLM is set\n const useMock = process.env['OPENFOX_MOCK_LLM'] === 'true'\n // For mock mode, we bypass the provider manager\n const getMockClient = useMock ? createMockLLMClient : null\n const getLLMClient = () => getMockClient ? getMockClient() : providerManager.getLLMClient()\n \n if (useMock) {\n logger.info('Using MOCK LLM client - deterministic responses for testing')\n }\n\n // Auto-detect backend and model from LLM server\n async function initLLM(): Promise<void> {\n const llmClient = getLLMClient()\n let backend: Backend = 'unknown'\n const useMock = process.env['OPENFOX_MOCK_LLM'] === 'true'\n \n if (config.llm.backend === 'auto') {\n backend = await detectBackend(config.llm.baseUrl, undefined, useMock)\n llmClient.setBackend(backend)\n if (!useMock) {\n logger.info('Auto-detected LLM backend', { backend: getBackendDisplayName(backend) })\n }\n } else {\n backend = config.llm.backend\n llmClient.setBackend(backend)\n if (!useMock) {\n logger.info('Using configured LLM backend', { backend: getBackendDisplayName(backend) })\n }\n }\n \n const detected = await detectModel(config.llm.baseUrl)\n if (detected) {\n llmClient.setModel(detected)\n if (!useMock) {\n logger.info('Auto-detected LLM model', { model: detected, backend: getBackendDisplayName(backend) })\n }\n } else {\n if (!useMock) {\n logger.warn('Could not auto-detect model, using config', { model: config.llm.model })\n }\n }\n }\n\n initLLM().catch(err => logger.error('LLM initialization failed', { error: err instanceof Error ? err.message : String(err) }))\n\n const toolRegistry = createToolRegistry()\n \n const app = express()\n\n // Middleware\n app.use(cors())\n app.use(express.json())\n\n // Health check\n app.get('/api/health', (_req, res) => {\n res.json({ status: 'ok', timestamp: new Date().toISOString() })\n })\n\n // Session endpoints (REST)\n\n app.post('/api/sessions', async (req, res) => {\n const { workdir, title } = req.body\n\n const session = sessionManager.createSession(workdir, title)\n res.status(201).json({ session })\n })\n\n app.get('/api/sessions/:id', (req, res) => {\n const session = sessionManager.getSession(req.params.id)\n if (!session) {\n return res.status(404).json({ error: 'Session not found' })\n }\n res.json({ session })\n })\n\n app.delete('/api/sessions/:id', (req, res) => {\n sessionManager.deleteSession(req.params['id'] as string)\n res.json({ success: true })\n })\n\n app.delete('/api/projects/:projectId/sessions', (req, res) => {\n const projectId = req.params['projectId'] as string\n const project = sessionManager.getProject(projectId)\n if (!project) {\n return res.status(404).json({ error: 'Project not found' })\n }\n sessionManager.deleteAllSessions(projectId, project.workdir)\n res.json({ success: true })\n })\n\n // Config endpoint\n app.get('/api/config', (_req, res) => {\n const llmClient = getLLMClient()\n const activeProvider = providerManager.getActiveProvider()\n res.json({\n model: llmClient.getModel(),\n maxContext: config.context.maxTokens,\n llmUrl: activeProvider?.url ?? config.llm.baseUrl,\n llmStatus: getLlmStatus(),\n backend: llmClient.getBackend(),\n workdir: config.workdir,\n // Include provider info\n providers: providerManager.getProviders(),\n activeProviderId: providerManager.getActiveProviderId(),\n defaultModelSelection: config.defaultModelSelection,\n })\n })\n\n // Model refresh endpoint\n app.post('/api/model/refresh', async (_req, res) => {\n const llmClient = getLLMClient()\n const currentModel = providerManager.getCurrentModel()\n \n // Only auto-detect if the current model is 'auto'\n // Otherwise, preserve the explicitly selected model\n if (currentModel === 'auto') {\n const activeProvider = providerManager.getActiveProvider()\n const baseUrl = activeProvider?.url ?? config.llm.baseUrl\n const detected = await detectModel(baseUrl)\n if (detected) {\n llmClient.setModel(detected)\n return res.json({ model: detected, source: 'detected', llmStatus: getLlmStatus(), backend: llmClient.getBackend() })\n }\n }\n \n // Return current model without overwriting\n res.json({ model: llmClient.getModel(), source: 'cached', llmStatus: getLlmStatus(), backend: llmClient.getBackend() })\n })\n\n // Provider endpoints\n app.get('/api/providers', (_req, res) => {\n const providers = providerManager.getProviders().map(p => ({\n ...p,\n status: providerManager.getProviderStatus(p.id),\n }))\n res.json({\n providers,\n activeProviderId: providerManager.getActiveProviderId(),\n })\n })\n\n app.get('/api/providers/:id/models', async (req, res) => {\n const { id } = req.params\n const models = await providerManager.getProviderModels(id as string)\n res.json({ models })\n })\n\n app.post('/api/providers/:id/activate', async (req, res) => {\n const { id } = req.params\n const body = req.body as { model?: string }\n const result = await providerManager.activateProvider(id as string, body.model ? { model: body.model } : undefined)\n if (!result.success) {\n return res.status(400).json({ error: result.error })\n }\n \n // Persist the model selection to config\n const llmClient = getLLMClient()\n const { loadGlobalConfig, saveGlobalConfig, setDefaultModelSelection } = await import('../cli/config.js')\n const globalConfig = await loadGlobalConfig(config.mode ?? 'production')\n const updatedConfig = setDefaultModelSelection(globalConfig, id as string, llmClient.getModel())\n await saveGlobalConfig(config.mode ?? 'production', updatedConfig)\n \n res.json({\n success: true,\n activeProviderId: id,\n model: llmClient.getModel(),\n backend: llmClient.getBackend(),\n })\n })\n\n // Skills endpoints\n app.get('/api/skills', async (_req, res) => {\n const [skills, defaultIds, modifiedIds] = await Promise.all([\n loadAllSkills(configDir),\n getDefaultSkillIds(),\n getModifiedDefaultSkillIds(configDir),\n ])\n res.json({\n skills: skills.map(s => ({\n ...s.metadata,\n enabled: isSkillEnabled(s.metadata.id),\n })),\n defaultIds,\n modifiedIds,\n })\n })\n\n app.get('/api/skills/default-ids', async (_req, res) => {\n const ids = await getDefaultSkillIds()\n res.json({ ids })\n })\n\n app.post('/api/skills/restore-all-defaults', async (_req, res) => {\n const count = await restoreAllDefaultSkills(configDir)\n res.json({ success: true, count })\n })\n\n app.post('/api/skills/:id/restore-default', async (req, res) => {\n const { id } = req.params\n const restored = await restoreDefaultSkill(configDir, id as string)\n if (!restored) {\n return res.status(404).json({ error: 'No bundled default found for this skill' })\n }\n res.json({ success: true })\n })\n\n app.post('/api/skills/:id/toggle', (req, res) => {\n const { id } = req.params\n const currentlyEnabled = isSkillEnabled(id as string)\n setSkillEnabled(id as string, !currentlyEnabled)\n res.json({ id, enabled: !currentlyEnabled })\n })\n\n app.get('/api/skills/:id', async (req, res) => {\n const { id } = req.params\n const skills = await loadAllSkills(configDir)\n const skill = findSkillById(id as string, skills)\n if (!skill) {\n return res.status(404).json({ error: 'Skill not found' })\n }\n res.json(skill)\n })\n\n app.post('/api/skills', async (req, res) => {\n const body = req.body as SkillDefinition\n if (!body.metadata?.id || !body.metadata?.name || !body.prompt) {\n return res.status(400).json({ error: 'Missing required fields: metadata.id, metadata.name, prompt' })\n }\n if (!/^[a-z0-9-]+$/.test(body.metadata.id)) {\n return res.status(400).json({ error: 'Skill ID must be lowercase alphanumeric with hyphens only' })\n }\n if (await skillExists(configDir, body.metadata.id)) {\n return res.status(409).json({ error: 'A skill with this ID already exists' })\n }\n await saveSkill(configDir, body)\n res.status(201).json(body)\n })\n\n app.put('/api/skills/:id', async (req, res) => {\n const { id } = req.params\n if (!await skillExists(configDir, id as string)) {\n return res.status(404).json({ error: 'Skill not found' })\n }\n const body = req.body as Partial<SkillDefinition>\n const skills = await loadAllSkills(configDir)\n const existing = findSkillById(id as string, skills)\n if (!existing) {\n return res.status(404).json({ error: 'Skill not found' })\n }\n const updated: SkillDefinition = {\n metadata: { ...existing.metadata, ...body.metadata, id: id as string },\n prompt: body.prompt ?? existing.prompt,\n }\n await saveSkill(configDir, updated)\n res.json(updated)\n })\n\n app.delete('/api/skills/:id', async (req, res) => {\n const { id } = req.params\n const deleted = await deleteSkill(configDir, id as string)\n if (!deleted) {\n return res.status(404).json({ error: 'Skill not found' })\n }\n res.json({ success: true })\n })\n\n // Commands endpoints\n app.get('/api/commands', async (_req, res) => {\n const [commands, defaultIds, modifiedIds] = await Promise.all([\n loadAllCommands(configDir),\n getDefaultCommandIds(),\n getModifiedDefaultCommandIds(configDir),\n ])\n res.json({\n commands: commands.map(c => c.metadata),\n defaultIds,\n modifiedIds,\n })\n })\n\n app.get('/api/commands/default-ids', async (_req, res) => {\n const ids = await getDefaultCommandIds()\n res.json({ ids })\n })\n\n app.post('/api/commands/restore-all-defaults', async (_req, res) => {\n const count = await restoreAllDefaultCommands(configDir)\n res.json({ success: true, count })\n })\n\n app.post('/api/commands/:id/restore-default', async (req, res) => {\n const { id } = req.params\n const restored = await restoreDefaultCommand(configDir, id as string)\n if (!restored) {\n return res.status(404).json({ error: 'No bundled default found for this command' })\n }\n res.json({ success: true })\n })\n\n app.get('/api/commands/:id', async (req, res) => {\n const { id } = req.params\n const commands = await loadAllCommands(configDir)\n const command = findCommandById(id as string, commands)\n if (!command) {\n return res.status(404).json({ error: 'Command not found' })\n }\n res.json(command)\n })\n\n app.post('/api/commands', async (req, res) => {\n const body = req.body as CommandDefinition\n if (!body.metadata?.id || !body.metadata?.name || !body.prompt) {\n return res.status(400).json({ error: 'Missing required fields: metadata.id, metadata.name, prompt' })\n }\n if (!/^[a-z0-9-]+$/.test(body.metadata.id)) {\n return res.status(400).json({ error: 'Command ID must be lowercase alphanumeric with hyphens only' })\n }\n if (await commandExists(configDir, body.metadata.id)) {\n return res.status(409).json({ error: 'A command with this ID already exists' })\n }\n await saveCommand(configDir, body)\n res.status(201).json(body)\n })\n\n app.put('/api/commands/:id', async (req, res) => {\n const { id } = req.params\n if (!await commandExists(configDir, id as string)) {\n return res.status(404).json({ error: 'Command not found' })\n }\n const body = req.body as Partial<CommandDefinition>\n const commands = await loadAllCommands(configDir)\n const existing = findCommandById(id as string, commands)\n if (!existing) {\n return res.status(404).json({ error: 'Command not found' })\n }\n const updated: CommandDefinition = {\n metadata: { ...existing.metadata, ...body.metadata, id: id as string },\n prompt: body.prompt ?? existing.prompt,\n }\n await saveCommand(configDir, updated)\n res.json(updated)\n })\n\n app.delete('/api/commands/:id', async (req, res) => {\n const { id } = req.params\n const deleted = await deleteCommand(configDir, id as string)\n if (!deleted) {\n return res.status(404).json({ error: 'Command not found' })\n }\n res.json({ success: true })\n })\n\n // Agents endpoints\n app.get('/api/agents', async (_req, res) => {\n const [agents, defaultIds, modifiedIds] = await Promise.all([\n loadAllAgents(configDir),\n getDefaultAgentIds(),\n getModifiedDefaultAgentIds(configDir),\n ])\n res.json({\n agents: agents.map(a => a.metadata),\n defaultIds,\n modifiedIds,\n })\n })\n\n app.get('/api/agents/default-ids', async (_req, res) => {\n const ids = await getDefaultAgentIds()\n res.json({ ids })\n })\n\n app.post('/api/agents/restore-all-defaults', async (_req, res) => {\n const count = await restoreAllDefaultAgents(configDir)\n res.json({ success: true, count })\n })\n\n app.post('/api/agents/:id/restore-default', async (req, res) => {\n const { id } = req.params\n const restored = await restoreDefaultAgent(configDir, id as string)\n if (!restored) {\n return res.status(404).json({ error: 'No bundled default found for this agent' })\n }\n res.json({ success: true })\n })\n\n app.get('/api/agents/:id', async (req, res) => {\n const { id } = req.params\n const agents = await loadAllAgents(configDir)\n const agent = findAgentById(id as string, agents)\n if (!agent) {\n return res.status(404).json({ error: 'Agent not found' })\n }\n res.json(agent)\n })\n\n app.post('/api/agents', async (req, res) => {\n const body = req.body as AgentDefinition\n if (!body?.metadata?.id || !body?.prompt) {\n return res.status(400).json({ error: 'Missing required fields: metadata.id, prompt' })\n }\n if (await agentExists(configDir, body.metadata.id)) {\n return res.status(409).json({ error: 'An agent with this ID already exists' })\n }\n await saveAgent(configDir, body)\n res.status(201).json(body)\n })\n\n app.put('/api/agents/:id', async (req, res) => {\n const { id } = req.params\n if (!id) {\n return res.status(400).json({ error: 'Missing agent ID' })\n }\n const body = req.body as Partial<AgentDefinition>\n const agents = await loadAllAgents(configDir)\n const existing = findAgentById(id as string, agents)\n if (!existing) {\n return res.status(404).json({ error: 'Agent not found' })\n }\n const updated: AgentDefinition = {\n metadata: { ...existing.metadata, ...body.metadata, id: id as string },\n prompt: body.prompt ?? existing.prompt,\n }\n await saveAgent(configDir, updated)\n res.json(updated)\n })\n\n app.delete('/api/agents/:id', async (req, res) => {\n const { id } = req.params\n const deleted = await deleteAgent(configDir, id as string)\n if (!deleted) {\n return res.status(404).json({ error: 'Agent not found' })\n }\n res.json({ success: true })\n })\n\n // Workflows endpoints\n app.get('/api/workflows', async (_req, res) => {\n const [workflows, defaultIds, modifiedIds] = await Promise.all([\n loadAllWorkflows(configDir),\n getDefaultWorkflowIds(),\n getModifiedDefaultWorkflowIds(configDir),\n ])\n res.json({\n workflows: workflows.map(p => p.metadata),\n activeWorkflowId: config.activeWorkflowId ?? 'default',\n defaultIds,\n modifiedIds,\n })\n })\n\n app.get('/api/workflows/default-ids', async (_req, res) => {\n const ids = await getDefaultWorkflowIds()\n res.json({ ids })\n })\n\n app.post('/api/workflows/restore-all-defaults', async (_req, res) => {\n const count = await restoreAllDefaultWorkflows(configDir)\n res.json({ success: true, count })\n })\n\n app.post('/api/workflows/:id/restore-default', async (req, res) => {\n const { id } = req.params\n const restored = await restoreDefaultWorkflow(configDir, id as string)\n if (!restored) {\n return res.status(404).json({ error: 'No bundled default found for this workflow' })\n }\n res.json({ success: true })\n })\n\n app.get('/api/workflows/:id', async (req, res) => {\n const { id } = req.params\n const workflows = await loadAllWorkflows(configDir)\n const workflow = findWorkflowById(id as string, workflows)\n if (!workflow) {\n return res.status(404).json({ error: 'Workflow not found' })\n }\n res.json(workflow)\n })\n\n app.post('/api/workflows', async (req, res) => {\n const body = req.body as WorkflowDefinition\n if (!body?.metadata?.id || !body?.steps?.length) {\n return res.status(400).json({ error: 'Missing required fields: metadata.id, steps' })\n }\n if (await workflowExists(configDir, body.metadata.id)) {\n return res.status(409).json({ error: 'A workflow with this ID already exists' })\n }\n await saveWorkflow(configDir, body)\n res.status(201).json(body)\n })\n\n app.put('/api/workflows/:id', async (req, res) => {\n const { id } = req.params\n if (!await workflowExists(configDir, id as string)) {\n return res.status(404).json({ error: 'Workflow not found' })\n }\n const body = req.body as WorkflowDefinition\n // Ensure the ID matches the URL parameter\n const updated: WorkflowDefinition = {\n ...body,\n metadata: { ...body.metadata, id: id as string },\n }\n await saveWorkflow(configDir, updated)\n res.json(updated)\n })\n\n app.delete('/api/workflows/:id', async (req, res) => {\n const { id } = req.params\n if (id === 'default') {\n return res.status(400).json({ error: 'Cannot delete the default workflow' })\n }\n const deleted = await deleteWorkflow(configDir, id as string)\n if (!deleted) {\n return res.status(404).json({ error: 'Workflow not found' })\n }\n res.json({ success: true })\n })\n\n\n // Branch API endpoint\n const { getCurrentBranch } = await import('./branch.api.js')\n\n app.get('/api/branch', async (req, res) => {\n await getCurrentBranch(req, res)\n })\n\n // Directory browser endpoint\n const DEFAULT_BASE_PATH = process.cwd()\n\n app.get('/api/directories', async (req, res) => {\n const path = req.query['path'] as string || DEFAULT_BASE_PATH\n \n try {\n const resolvedPath = resolve(path)\n \n const entries = await import('node:fs/promises').then(m => m.readdir(resolvedPath, { withFileTypes: true }))\n const directories = entries\n .filter(entry => entry.isDirectory() && !entry.name.startsWith('.'))\n .map(entry => ({\n name: entry.name,\n path: join(resolvedPath, entry.name),\n }))\n .sort((a, b) => a.name.localeCompare(b.name))\n \n const parent = dirname(resolvedPath)\n const hasParent = parent !== resolvedPath\n \n res.json({\n current: resolvedPath,\n parent: hasParent ? parent : null,\n directories,\n basename: basename(resolvedPath),\n })\n } catch {\n res.status(400).json({ \n error: 'Cannot read directory',\n current: DEFAULT_BASE_PATH,\n parent: null,\n directories: [],\n basename: basename(DEFAULT_BASE_PATH),\n })\n }\n })\n\n // Serve static web UI\n const webDir = resolve(__dirname, '../../web')\n const isDev = config.mode === 'development'\n \n let viteServer: ViteDevServer | undefined\n \n // Dev mode: use Vite as middleware\n if (isDev) {\n logger.info('Dev mode: using Vite middleware')\n \n // Create Vite server in middleware mode\n viteServer = await createViteServer({\n root: webDir,\n configFile: resolve(__dirname, '../../web/vite.config.ts'),\n server: { middlewareMode: true },\n appType: 'spa',\n logLevel: 'warn',\n })\n \n // Mount Vite middleware - handles /@vite/*, /@react-refresh, /src/*, etc.\n app.use(viteServer.middlewares)\n \n // Handle CSS files explicitly - Vite middleware doesn't catch them\n app.get('/src/styles/*.css', async (req, res) => {\n try {\n const result = await viteServer!.transformRequest(req.path.substring(1))\n if (!result) {\n return res.status(404).send('Not found')\n }\n res.set('Content-Type', 'text/css')\n res.send(result.code)\n } catch (err) {\n logger.error('CSS transform error', { path: req.path, error: err })\n res.status(500).send('Transform error')\n }\n })\n \n // Static files that Vite doesn't handle (after Vite middleware)\n app.get('/fox.svg', (_req, res) => {\n readFile(join(webDir, 'fox.svg')).then(content => {\n res.set('Content-Type', 'image/svg+xml')\n res.send(content)\n }).catch(() => {\n res.status(404).send('Not found')\n })\n })\n \n app.get('/sounds/*', (req, res) => {\n const fullPath = join(webDir, req.path.substring(1))\n readFile(fullPath).then(content => {\n res.set('Content-Type', 'audio/mpeg')\n res.send(content)\n }).catch(() => {\n res.status(404).send('Not found')\n })\n })\n \n // SPA fallback for non-API routes (must be last)\n app.get('*', (req, res) => {\n if (req.path.startsWith('/api/')) {\n return\n }\n readFile(join(webDir, 'index.html'), 'utf-8')\n .then(indexHtml => viteServer!.transformIndexHtml(req.originalUrl, indexHtml))\n .then(transformed => res.send(transformed))\n .catch(err => {\n logger.error('Error serving index.html', { error: err })\n res.status(500).send('Server error')\n })\n })\n \n logger.info('Vite middleware ready', { port: config.server.port })\n }\n \n // Production mode: serve static files from dist/web\n if (!isDev) {\n const distWebDir = resolve(__dirname, 'web')\n \n // Serve static assets with proper caching\n app.use('/assets', express.static(join(distWebDir, 'assets'), {\n setHeaders: (res, filepath) => {\n if (filepath.endsWith('.css')) {\n res.set('Content-Type', 'text/css')\n }\n }\n }))\n \n // Static files\n app.get('/fox.svg', (_req, res) => {\n readFile(join(distWebDir, 'fox.svg')).then(content => {\n res.set('Content-Type', 'image/svg+xml')\n res.send(content)\n }).catch(() => {\n res.status(404).send('Not found')\n })\n })\n \n app.get('/sounds/*', (req, res) => {\n const fullPath = join(distWebDir, req.path.substring(1))\n readFile(fullPath).then(content => {\n res.set('Content-Type', 'audio/mpeg')\n res.send(content)\n }).catch(() => {\n res.status(404).send('Not found')\n })\n })\n \n // Root serves index.html\n app.get('/', (_req, res) => {\n readFile(join(distWebDir, 'index.html'), 'utf-8')\n .then(content => res.send(content))\n .catch(() => {\n res.status(404).send('Web UI not built. Run `npm run build:web`')\n })\n })\n \n // SPA fallback - serve index.html for any unmatched path\n app.get('*', (req, res) => {\n if (req.path.startsWith('/api/') || req.path.startsWith('/assets/') || req.path.startsWith('/sounds/') || req.path === '/fox.svg') {\n return\n }\n readFile(join(distWebDir, 'index.html'), 'utf-8')\n .then(content => res.send(content))\n .catch(() => {\n res.status(404).send('Web UI not built')\n })\n })\n }\n\n // Create HTTP server from Express app\n const httpServer = createHttpServer(app)\n\n // Create WebSocket server attached to HTTP server\n const wss = createWebSocketServer(httpServer, config, getLLMClient, () => providerManager.getActiveProvider(), toolRegistry, sessionManager, providerManager)\n\n // Return the handle with start/close methods\n return {\n httpServer,\n ctx: { config, sessionManager, llmClient: getLLMClient(), toolRegistry, providerManager },\n \n start: (port?: number) => new Promise((resolve, reject) => {\n const listenPort = port ?? config.server.port\n const host = config.server.host\n \n httpServer.listen(listenPort, host, () => {\n const addr = httpServer.address()\n const actualPort = typeof addr === 'object' && addr ? addr.port : listenPort\n const client = getLLMClient()\n logger.info(`OpenFox server running at http://${host}:${actualPort}`)\n logger.info(`WebSocket available at ws://${host}:${actualPort}/ws`)\n logger.info(`LLM backend: ${client.getBackend()}, model: ${client.getModel()}, url: ${config.llm.baseUrl}`)\n resolve({ port: actualPort })\n })\n \n httpServer.on('error', reject)\n }),\n \n close: () => new Promise<void>((resolve) => {\n logger.info('Shutting down...')\n void (async () => {\n viteServer?.close()\n\n // Note: Not closing database here - it's a singleton shared across servers.\n // Database should only be closed when the application exits.\n // Terminate all WebSocket connections to allow clean shutdown\n for (const client of wss.clients) {\n client.terminate()\n }\n wss.close()\n httpServer.close(() => resolve())\n })()\n }),\n }\n}\n\n/**\n * Create and start a server (convenience function for CLI).\n * Starts listening immediately on the configured port.\n * Sets up SIGINT/SIGTERM handlers.\n */\nexport async function createServer(config: Config): Promise<void> {\n const handle = await createServerHandle(config)\n await handle.start()\n \n // Graceful shutdown with force exit timeout\n const shutdown = () => {\n // Force exit after 3 seconds if graceful shutdown hangs\n const forceExitTimer = setTimeout(() => {\n logger.warn('Forcing exit after timeout')\n process.exit(1)\n }, 3000)\n forceExitTimer.unref() // Don't keep process alive just for this timer\n \n handle.close().then(() => process.exit(0))\n }\n \n process.on('SIGINT', shutdown)\n process.on('SIGTERM', shutdown)\n}\n\nfunction basename(path: string): string {\n return path.split('/').pop() || path.split('\\\\').pop() || path\n}\n","/**\n * Mock LLM Client for E2E Tests\n * \n * Provides deterministic LLM responses for testing without real inference.\n * Activated via OPENFOX_MOCK_LLM=true environment variable.\n * \n * Pattern-matches prompts to return specific tool calls, enabling fast\n * deterministic testing of the entire system through the WebSocket API.\n */\n\nimport { setTimeout as sleep } from 'node:timers/promises'\n\nimport type { LLMClientWithModel } from './client.js'\nimport type { LLMCompletionRequest, LLMCompletionResponse, LLMStreamEvent } from './types.js'\nimport type { ToolCall } from '../../shared/types.js'\nimport { getModelProfile } from './profiles.js'\nimport { type Backend } from './backend.js'\nimport { logger } from '../utils/logger.js'\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface MockToolCall {\n name: string\n arguments: Record<string, unknown>\n}\n\ninterface MockRule {\n match: RegExp\n tools: MockToolCall[]\n response: string\n}\n\ninterface MockMatchResult {\n tools: MockToolCall[]\n response: string\n}\n\n// ============================================================================\n// Rules - Pattern → Tool Calls\n// ============================================================================\n\nconst RULES: MockRule[] = [\n // -------------------------------------------------------------------------\n // Criterion Tools\n // -------------------------------------------------------------------------\n // Multi-criteria: ID \"crit-a\": \"First\" and ID \"crit-b\": \"Second\"\n {\n match: /ID\\s*[\"']([a-z0-9-]+)[\"']:\\s*[\"']([^\"']+)[\"'][\\s\\S]*ID\\s*[\"']([a-z0-9-]+)[\"']:\\s*[\"']([^\"']+)[\"']/i,\n tools: [\n { name: 'add_criterion', arguments: { id: '$1', description: '$2' } },\n { name: 'add_criterion', arguments: { id: '$3', description: '$4' } },\n ],\n response: 'Added both criteria.',\n },\n // Single criterion: ID \"test-1\" with/: description \"The tests pass\"\n {\n match: /ID\\s*[\"']([a-z0-9-]+)[\"'].*description\\s*[\"']([^\"']+)[\"']/i,\n tools: [{ name: 'add_criterion', arguments: { id: '$1', description: '$2' } }],\n response: 'Added the criterion.',\n },\n {\n match: /Add these two acceptance criteria:\\s*1\\.\\s*([^\\n]+)\\s*2\\.\\s*([^\\n]+)\\s*Use add_criterion for each\\./i,\n tools: [\n { name: 'add_criterion', arguments: { id: 'criterion-1', description: '$1' } },\n { name: 'add_criterion', arguments: { id: 'criterion-2', description: '$2' } },\n ],\n response: 'Added both criteria.',\n },\n {\n match: /Add these two acceptance criteria:[\\s\\S]*?1\\.\\s*([^\\n]+)[\\s\\S]*?2\\.\\s*([^\\n]+)[\\s\\S]*?Use add_criterion for each one\\./i,\n tools: [\n { name: 'add_criterion', arguments: { id: 'criterion-1', description: '$1' } },\n { name: 'add_criterion', arguments: { id: 'criterion-2', description: '$2' } },\n ],\n response: 'Added both criteria.',\n },\n {\n match: /Add criterion:\\s*([\\s\\S]+?)\\s*Use add_criterion\\.?/i,\n tools: [{ name: 'add_criterion', arguments: { id: '$auto', description: '$1' } }],\n response: 'Added the criterion.',\n },\n // Single criterion: ID \"test-1\": \"The tests pass\" (colon format)\n {\n match: /ID\\s*[\"']([a-z0-9-]+)[\"']\\s*:\\s*[\"']([^\"']+)[\"']/i,\n tools: [{ name: 'add_criterion', arguments: { id: '$1', description: '$2' } }],\n response: 'Added the criterion.',\n },\n // complete_criterion to mark \"id\" as done\n {\n match: /complete_criterion.*mark\\s*[\"']([a-z0-9-]+)[\"']/i,\n tools: [{ name: 'complete_criterion', arguments: { id: '$1', reason: 'Completed successfully' } }],\n response: 'Marked criterion as complete.',\n },\n // complete_criterion with ID\n {\n match: /complete_criterion.*[\"']([a-z0-9-]+)[\"']/i,\n tools: [{ name: 'complete_criterion', arguments: { id: '$1', reason: 'Completed successfully' } }],\n response: 'Marked criterion as complete.',\n },\n // remove_criterion to remove \"id\"\n {\n match: /remove_criterion.*remove\\s*[\"']([a-z0-9-]+)[\"']/i,\n tools: [{ name: 'remove_criterion', arguments: { id: '$1' } }],\n response: 'Removed the criterion.',\n },\n // remove_criterion with ID\n {\n match: /remove_criterion.*[\"']([a-z0-9-]+)[\"']/i,\n tools: [{ name: 'remove_criterion', arguments: { id: '$1' } }],\n response: 'Removed the criterion.',\n },\n // update_criterion to change \"id\" description to \"new\"\n {\n match: /update_criterion.*change\\s*[\"']([a-z0-9-]+)[\"'].*to\\s*[\"']([^\"']+)[\"']/i,\n tools: [{ name: 'update_criterion', arguments: { id: '$1', description: '$2' } }],\n response: 'Updated the criterion.',\n },\n // update_criterion with ID and description\n {\n match: /update_criterion.*[\"']([a-z0-9-]+)[\"'].*[\"']([^\"']+)[\"']/i,\n tools: [{ name: 'update_criterion', arguments: { id: '$1', description: '$2' } }],\n response: 'Updated the criterion.',\n },\n // get_criteria\n {\n match: /get_criteria/i,\n tools: [{ name: 'get_criteria', arguments: {} }],\n response: 'Here are the current criteria.',\n },\n // Generic add criterion (fallback)\n {\n match: /add.*criterion/i,\n tools: [{ name: 'add_criterion', arguments: { id: '$auto', description: 'Test criterion' } }],\n response: 'Added the criterion.',\n },\n\n // -------------------------------------------------------------------------\n // File Read Tools\n // -------------------------------------------------------------------------\n {\n match: /read.*src\\/math\\.ts.*offset|offset.*src\\/math\\.ts/i,\n tools: [{ name: 'read_file', arguments: { path: 'src/math.ts', offset: 5 } }],\n response: 'Read the file starting from line 5.',\n },\n {\n match: /read.*src\\/math\\.ts.*limit|limit.*src\\/math\\.ts|first.*lines.*src\\/math\\.ts/i,\n tools: [{ name: 'read_file', arguments: { path: 'src/math.ts', limit: 3 } }],\n response: 'Read the first 3 lines of the file.',\n },\n {\n match: /read.*src.*directory|read the src directory/i,\n tools: [{ name: 'read_file', arguments: { path: 'src' } }],\n response: 'Listed directory contents.',\n },\n {\n match: /read.*src\\/nonexistent|nonexistent.*does not exist/i,\n tools: [{ name: 'read_file', arguments: { path: 'src/nonexistent.ts' } }],\n response: 'Attempted to read the file.',\n },\n {\n match: /read.*src\\/index\\.ts/i,\n tools: [{ name: 'read_file', arguments: { path: 'src/index.ts' } }],\n response: 'Read the file contents.',\n },\n {\n match: /read.*src\\/math\\.ts/i,\n tools: [{ name: 'read_file', arguments: { path: 'src/math.ts' } }],\n response: 'Read the file contents.',\n },\n {\n match: /read.*src\\/multi\\.ts/i,\n tools: [{ name: 'read_file', arguments: { path: 'src/multi.ts' } }],\n response: 'Read the file contents.',\n },\n {\n match: /read.*package\\.json/i,\n tools: [{ name: 'read_file', arguments: { path: 'package.json' } }],\n response: 'Read package.json.',\n },\n {\n match: /read.*file/i,\n tools: [{ name: 'read_file', arguments: { path: 'src/index.ts' } }],\n response: 'Read the file.',\n },\n\n // -------------------------------------------------------------------------\n // Glob Tool\n // -------------------------------------------------------------------------\n {\n match: /glob.*\\*\\*\\/\\*\\.ts|recursive.*typescript/i,\n tools: [{ name: 'glob', arguments: { pattern: '**/*.ts' } }],\n response: 'Found TypeScript files recursively.',\n },\n {\n match: /glob.*\\*\\.xyz|no matches/i,\n tools: [{ name: 'glob', arguments: { pattern: '*.xyz' } }],\n response: 'No files matched the pattern.',\n },\n {\n match: /glob.*\\.ts|find.*typescript|find all.*\\.ts/i,\n tools: [{ name: 'glob', arguments: { pattern: '**/*.ts' } }],\n response: 'Found TypeScript files.',\n },\n {\n match: /glob|find.*file/i,\n tools: [{ name: 'glob', arguments: { pattern: '**/*' } }],\n response: 'Found files.',\n },\n\n // -------------------------------------------------------------------------\n // Grep Tool\n // -------------------------------------------------------------------------\n {\n match: /grep.*XYZNONEXISTENT|search.*XYZNONEXISTENT/i,\n tools: [{ name: 'grep', arguments: { pattern: 'XYZNONEXISTENT123', path: '.' } }],\n response: 'No matches found.',\n },\n {\n match: /grep.*regex.*function\\\\s/i,\n tools: [{ name: 'grep', arguments: { pattern: 'function\\\\s+\\\\w+', path: '.' } }],\n response: 'Found function declarations.',\n },\n {\n match: /grep.*export.*\\*\\.ts|search.*export.*typescript/i,\n tools: [{ name: 'grep', arguments: { pattern: 'export', path: '.', include: '*.ts' } }],\n response: 'Found exports in TypeScript files.',\n },\n {\n match: /grep.*function|search.*function/i,\n tools: [{ name: 'grep', arguments: { pattern: 'function', path: '.' } }],\n response: 'Found function occurrences.',\n },\n {\n match: /grep|search/i,\n tools: [{ name: 'grep', arguments: { pattern: 'export', path: '.' } }],\n response: 'Searched for pattern.',\n },\n\n // -------------------------------------------------------------------------\n // Write Tool\n // -------------------------------------------------------------------------\n // Path security test rules - writing outside /tmp (requires confirmation)\n {\n match: /write.*\\/home\\/test\\/approved/i,\n tools: [{ name: 'write_file', arguments: { path: '/home/test/approved.txt', content: 'approved' } }],\n response: 'Wrote to the approved path.',\n },\n {\n match: /write.*\\/home\\/test\\/denied/i,\n tools: [{ name: 'write_file', arguments: { path: '/home/test/denied.txt', content: 'denied' } }],\n response: 'Wrote to the denied path.',\n },\n {\n match: /write.*\\/home\\/test\\/first/i,\n tools: [{ name: 'write_file', arguments: { path: '/home/test/first.txt', content: 'first' } }],\n response: 'Wrote the first file.',\n },\n {\n match: /write.*\\/home\\/test\\/second/i,\n tools: [{ name: 'write_file', arguments: { path: '/home/test/second.txt', content: 'second' } }],\n response: 'Wrote the second file.',\n },\n {\n match: /write.*\\/home\\/test\\/secret/i,\n tools: [{ name: 'write_file', arguments: { path: '/home/test/secret.txt', content: 'secret' } }],\n response: 'Wrote to home.',\n },\n {\n match: /without reading.*write|write.*without reading/i,\n tools: [{ name: 'write_file', arguments: { path: 'src/index.ts', content: 'new content' } }],\n response: 'Attempted to write without reading first.',\n },\n {\n match: /create.*deep\\/nested|nested.*path.*file/i,\n tools: [{ name: 'write_file', arguments: { path: 'deep/nested/path/file.ts', content: 'export const x = 1' } }],\n response: 'Created file in nested directory.',\n },\n {\n match: /create.*src\\/newfile\\.ts.*greeting/i,\n tools: [{ name: 'write_file', arguments: { path: 'src/newfile.ts', content: 'export const greeting = \"hello\"' } }],\n response: 'Created the new file.',\n },\n {\n match: /create.*src\\/utils\\.ts.*greet/i,\n tools: [{ name: 'write_file', arguments: { path: 'src/utils.ts', content: 'export function greet() { return \"Hello!\" }' } }],\n response: 'Created utils.ts with greet function.',\n },\n {\n match: /create.*src\\/new\\.ts/i,\n tools: [{ name: 'write_file', arguments: { path: 'src/new.ts', content: 'export const x = 1' } }],\n response: 'Created the file.',\n },\n {\n match: /write.*src\\/newfile\\.ts/i,\n tools: [{ name: 'write_file', arguments: { path: 'src/newfile.ts', content: 'export const x = 1' } }],\n response: 'Wrote to file.',\n },\n {\n match: /create.*file|write.*file/i,\n tools: [{ name: 'write_file', arguments: { path: 'src/newfile.ts', content: 'export const x = 1' } }],\n response: 'Created file.',\n },\n\n // -------------------------------------------------------------------------\n // Edit Tool\n // -------------------------------------------------------------------------\n {\n match: /without reading.*edit_file|edit_file.*without reading/i,\n tools: [{ name: 'edit_file', arguments: { path: 'src/math.ts', old_string: 'function', new_string: 'const' } }],\n response: 'Attempted to edit without reading first.',\n },\n {\n match: /edit_file.*replaceAll.*const.*let/i,\n tools: [\n { name: 'read_file', arguments: { path: 'src/multi.ts' } },\n { name: 'edit_file', arguments: { path: 'src/multi.ts', old_string: 'const', new_string: 'let', replaceAll: true } },\n ],\n response: 'Replaced all occurrences.',\n },\n {\n match: /edit_file.*NONEXISTENT_STRING/i,\n tools: [\n { name: 'read_file', arguments: { path: 'src/math.ts' } },\n { name: 'edit_file', arguments: { path: 'src/math.ts', old_string: 'NONEXISTENT_STRING_XYZ', new_string: 'replacement' } },\n ],\n response: 'Attempted to edit with non-existent string.',\n },\n {\n match: /edit_file.*add.*sum/i,\n tools: [\n { name: 'read_file', arguments: { path: 'src/math.ts' } },\n { name: 'edit_file', arguments: { path: 'src/math.ts', old_string: 'add', new_string: 'sum' } },\n ],\n response: 'Renamed function from add to sum.',\n },\n {\n match: /edit_file|edit.*file/i,\n tools: [\n { name: 'read_file', arguments: { path: 'src/math.ts' } },\n { name: 'edit_file', arguments: { path: 'src/math.ts', old_string: 'function', new_string: 'const' } },\n ],\n response: 'Edited the file.',\n },\n\n // -------------------------------------------------------------------------\n // Shell/Command Tool\n // -------------------------------------------------------------------------\n {\n match: /run.*echo.*first.*sleep.*second/i,\n tools: [{ name: 'run_command', arguments: { command: 'echo \"first\" && sleep 0.2 && echo \"second\"' } }],\n response: 'Executed the command sequence.',\n },\n {\n match: /run.*echo.*stdout.*stderr/i,\n tools: [{ name: 'run_command', arguments: { command: 'echo \"stdout\" && echo \"stderr\" >&2' } }],\n response: 'Executed command with stdout and stderr.',\n },\n {\n match: /run.*echo.*streaming/i,\n tools: [{ name: 'run_command', arguments: { command: 'echo \"streaming test output\"' } }],\n response: 'Executed streaming command.',\n },\n {\n match: /run.*echo.*Hello World/i,\n tools: [{ name: 'run_command', arguments: { command: 'echo \"Hello World\"' } }],\n response: 'Executed echo command.',\n },\n {\n match: /run.*cat.*package\\.json/i,\n tools: [{ name: 'run_command', arguments: { command: 'cat package.json' } }],\n response: 'Displayed package.json contents.',\n },\n {\n match: /run.*cat.*nonexistent/i,\n tools: [{ name: 'run_command', arguments: { command: 'cat nonexistent-file-xyz.txt' } }],\n response: 'Attempted to read non-existent file.',\n },\n {\n match: /run.*find\\s*\\./i,\n tools: [{ name: 'run_command', arguments: { command: 'find .' } }],\n response: 'Listed all files.',\n },\n {\n match: /run.*ls.*workdir.*src|ls.*src.*workdir/i,\n tools: [{ name: 'run_command', arguments: { command: 'ls', cwd: 'src' } }],\n response: 'Listed src directory.',\n },\n {\n match: /run.*ls.*-la.*src/i,\n tools: [{ name: 'run_command', arguments: { command: 'ls -la src' } }],\n response: 'Listed src directory with details.',\n },\n {\n match: /run.*ls.*nonexistent/i,\n tools: [{ name: 'run_command', arguments: { command: 'ls /nonexistent/path/xyz' } }],\n response: 'Attempted to list non-existent path.',\n },\n {\n match: /run.*npm.*--version/i,\n tools: [{ name: 'run_command', arguments: { command: 'npm --version' } }],\n response: 'Checked npm version.',\n },\n {\n match: /run.*pwd.*ls/i,\n tools: [\n { name: 'run_command', arguments: { command: 'pwd' } },\n { name: 'run_command', arguments: { command: 'ls src' } },\n ],\n response: 'Executed pwd and ls.',\n },\n {\n match: /run.*ls.*src/i,\n tools: [{ name: 'run_command', arguments: { command: 'ls src' } }],\n response: 'Listed src directory.',\n },\n {\n match: /run.*ls|list.*files/i,\n tools: [{ name: 'run_command', arguments: { command: 'ls' } }],\n response: 'Listed directory contents.',\n },\n {\n match: /run.*command|execute/i,\n tools: [{ name: 'run_command', arguments: { command: 'echo \"test\"' } }],\n response: 'Executed the command.',\n },\n\n // -------------------------------------------------------------------------\n // Todo Tool\n // -------------------------------------------------------------------------\n {\n match: /todo_write.*Read files.*Make changes/i,\n tools: [{\n name: 'todo_write',\n arguments: {\n todos: [\n { content: 'Read files', status: 'in_progress', priority: 'high' },\n { content: 'Make changes', status: 'pending', priority: 'medium' },\n ],\n },\n }],\n response: 'Created todo list.',\n },\n {\n match: /todo_write|todo.*list/i,\n tools: [{\n name: 'todo_write',\n arguments: {\n todos: [{ content: 'Test task', status: 'pending', priority: 'medium' }],\n },\n }],\n response: 'Created todo list.',\n },\n\n // -------------------------------------------------------------------------\n // Mode/Context\n // -------------------------------------------------------------------------\n {\n match: /think.*step.*step/i,\n tools: [],\n response: 'Let me think step by step about this problem. First, I need to understand the requirements. Then I can propose a solution.',\n },\n {\n match: /long.*explanation|detailed.*explanation/i,\n tools: [],\n response: 'Here is a detailed explanation of the topic. TypeScript is a statically typed superset of JavaScript that adds optional type annotations. It provides better tooling, catches errors at compile time, and makes code more maintainable.',\n },\n\n // -------------------------------------------------------------------------\n // Default Responses (no tools)\n // -------------------------------------------------------------------------\n {\n match: /hello|hi there|introduce yourself/i,\n tools: [],\n response: 'Hello! I am your coding assistant. How can I help you today?',\n },\n {\n match: /magic word/i,\n tools: [],\n response: 'The magic word is \"please\".',\n },\n {\n match: /what.*files.*project/i,\n tools: [{ name: 'glob', arguments: { pattern: '**/*' } }],\n response: 'Let me list the project files.',\n },\n {\n match: /what.*guidelines/i,\n tools: [{ name: 'read_file', arguments: { path: 'AGENTS.md' } }],\n response: 'Let me check the guidelines.',\n },\n {\n match: /typescript|features/i,\n tools: [],\n response: 'TypeScript is a strongly typed programming language that builds on JavaScript.',\n },\n\n // -------------------------------------------------------------------------\n // Fallback\n // -------------------------------------------------------------------------\n {\n match: /.*/,\n tools: [],\n response: 'I understand. Let me help you with that.',\n },\n]\n\n// ============================================================================\n// Rule Matching\n// ============================================================================\n\nfunction matchRule(prompt: string): { rule: MockRule; captures: string[] } {\n for (const rule of RULES) {\n const match = prompt.match(rule.match)\n if (match) {\n return { rule, captures: match.slice(1) }\n }\n }\n // Should never reach here due to fallback rule\n return { rule: RULES[RULES.length - 1]!, captures: [] }\n}\n\nfunction applyCaptures(args: Record<string, unknown>, captures: string[]): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(args)) {\n if (typeof value === 'string' && value.startsWith('$')) {\n if (value === '$auto') {\n // Generate unique ID using timestamp\n result[key] = `auto-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`\n } else {\n const idx = parseInt(value.slice(1), 10) - 1\n result[key] = captures[idx] ?? value\n }\n } else {\n result[key] = value\n }\n }\n return result\n}\n\nfunction getLastUserPrompt(request: LLMCompletionRequest): string {\n const stripRuntimeReminders = (content: string): string => {\n return content.replace(/\\n*<system-reminder>[\\s\\S]*<\\/system-reminder>\\s*/gi, '').trim()\n }\n\n const userMessages = request.messages.filter(message => message.role === 'user')\n const latestUserMessage = userMessages.at(-1)\n if (!latestUserMessage) {\n return ''\n }\n\n const isRuntimeReminder = (content: string): boolean => {\n return /<system-reminder>[\\s\\S]*<\\/system-reminder>/i.test(content)\n }\n\n const isBuilderKickoff = (content: string): boolean => {\n return /Implement the task and make sure you fulfil the \\d+ criteria\\./i.test(content)\n }\n\n const isSummaryPrompt = (content: string): boolean => {\n return /Write a 2-3 sentence summary of what the user wants to accomplish\\./i.test(content)\n }\n\n const isCompactionPrompt = (content: string): boolean => {\n return /Summarize the conversation history concisely/i.test(content)\n }\n\n const isWaitingPrompt = (content: string): boolean => {\n return /Waiting for user input/i.test(content)\n }\n\n const isXmlCorrectionPrompt = (content: string): boolean => {\n return /IMPORTANT: You used XML tags/i.test(content)\n }\n\n const isVerifierKickoff = (content: string): boolean => {\n return /Verify each criterion marked \\[NEEDS VERIFICATION\\]\\./i.test(content)\n }\n\n const isAutoPrompt = (content: string): boolean => {\n const strippedContent = stripRuntimeReminders(content)\n\n return (\n (isRuntimeReminder(content) && strippedContent.length === 0) ||\n isBuilderKickoff(strippedContent) ||\n isSummaryPrompt(strippedContent) ||\n isCompactionPrompt(strippedContent) ||\n isWaitingPrompt(strippedContent) ||\n isXmlCorrectionPrompt(strippedContent) ||\n isVerifierKickoff(strippedContent)\n )\n }\n\n const latestPrompt = stripRuntimeReminders(latestUserMessage.content)\n\n if (isVerifierKickoff(latestPrompt)) {\n return latestPrompt\n }\n\n if (\n isBuilderKickoff(latestPrompt)\n || isSummaryPrompt(latestPrompt)\n || isCompactionPrompt(latestPrompt)\n || isWaitingPrompt(latestPrompt)\n || isXmlCorrectionPrompt(latestPrompt)\n ) {\n return latestPrompt\n }\n\n if (!isAutoPrompt(latestUserMessage.content)) {\n return latestPrompt\n }\n\n for (let i = userMessages.length - 2; i >= 0; i--) {\n const message = userMessages[i]!\n if (!isAutoPrompt(message.content)) {\n return stripRuntimeReminders(message.content)\n }\n }\n\n return latestPrompt\n}\n\nfunction getConversationText(request: LLMCompletionRequest): string {\n return request.messages.map(message => message.content).join('\\n\\n')\n}\n\nfunction getInstructionAwareResponse(request: LLMCompletionRequest): string | null {\n const prompt = getLastUserPrompt(request)\n const conversationText = getConversationText(request)\n const previousUserPrompts = request.messages\n .filter(message => message.role === 'user')\n .slice(0, -1)\n .map(message => message.content)\n\n const projectName = [...previousUserPrompts]\n .reverse()\n .map(content => content.match(/project name is [\"']([^\"']+)[\"']/i)?.[1])\n .find((value): value is string => Boolean(value))\n\n if (/Generate a concise, descriptive session name/i.test(prompt)) {\n const userMessage = prompt.match(/User message:\\s*([\\s\\S]+)$/i)?.[1]?.trim()\n if (!userMessage) {\n return 'New session'\n }\n\n if (/react/i.test(userMessage) && /typescript/i.test(userMessage)) {\n return 'React TypeScript setup'\n }\n if (/authentication bug/i.test(userMessage)) {\n return 'Fix authentication bug'\n }\n if (/unit tests/i.test(userMessage) && /api/i.test(userMessage)) {\n return 'Add API unit tests'\n }\n if (/oauth2/i.test(userMessage) && /jwt/i.test(userMessage)) {\n return 'OAuth2 JWT auth'\n }\n\n const words = userMessage\n .replace(/[^a-z0-9\\s]/gi, ' ')\n .trim()\n .split(/\\s+/)\n .slice(0, 6)\n return words.length > 0 ? words.join(' ') : 'New session'\n }\n\n if (/what did i say the project name was\\??/i.test(prompt) && projectName) {\n return `You said the project name was ${projectName}.`\n }\n\n if (/what guidelines should i follow\\??/i.test(prompt)) {\n return 'Follow the function, test, TDD, and style guidelines.'\n }\n\n if (/hello there!?/i.test(prompt) && conversationText.includes('CUSTOM_MARKER')) {\n return 'ACKNOWLEDGED. Hello there!'\n }\n\n if (/what is the magic word\\??/i.test(prompt) && conversationText.includes('ABRACADABRA')) {\n return 'The magic word is ABRACADABRA.'\n }\n\n if (/say hello briefly\\.?/i.test(prompt) && conversationText.includes('GLOBAL_MARKER')) {\n return 'Hello. [DONE]'\n }\n\n if (/what should you say now\\??/i.test(prompt) && conversationText.includes('Updated instruction: say UPDATED')) {\n return 'UPDATED'\n }\n\n if (/what should you say\\??/i.test(prompt) && conversationText.includes('Original instruction: say ORIGINAL')) {\n return 'ORIGINAL'\n }\n\n return null\n}\n\nfunction getPromptAwareToolResponse(prompt: string): MockMatchResult | null {\n const exactCommandMatch = prompt.match(/Run the exact command:\\s*(.+)$/i) ?? prompt.match(/^Run exactly:\\s*(.+)$/i)\n const quotedValues = [...prompt.matchAll(/\"([^\"]+)\"/g)].map(match => match[1]!)\n\n if (/Use the todo_write tool to create a todo list with 2 items/i.test(prompt)) {\n return {\n tools: [{\n name: 'todo_write',\n arguments: {\n todos: [\n { content: 'Read files', status: 'in_progress', priority: 'high' },\n { content: 'Make changes', status: 'pending', priority: 'medium' },\n ],\n },\n }],\n response: 'Created todo list.',\n }\n }\n\n if (/First call get_criteria to see what needs to be done, then create src\\/test\\.ts and call complete_criterion for [\"']test-file[\"']\\./i.test(prompt)) {\n return {\n tools: [\n { name: 'get_criteria', arguments: {} },\n { name: 'write_file', arguments: { path: 'src/test.ts', content: 'export const created = true' } },\n { name: 'complete_criterion', arguments: { id: 'test-file', reason: 'Created the requested file' } },\n ],\n response: 'Reviewed the criteria, created the file, and completed the criterion.',\n }\n }\n\n if (/Create the file src\\/utils\\.ts with any content, then call complete_criterion/i.test(prompt)) {\n return {\n tools: [\n { name: 'write_file', arguments: { path: 'src/utils.ts', content: 'export const created = true' } },\n { name: 'complete_criterion', arguments: { id: 'file-created', reason: 'Created the requested file' } },\n ],\n response: 'Created the file and completed the criterion.',\n }\n }\n\n if (/Create a new file called src\\/utils\\.ts/i.test(prompt)) {\n return {\n tools: [{ name: 'write_file', arguments: { path: 'src/utils.ts', content: 'export function greet() { return \"Hello!\" }' } }],\n response: 'Created src/utils.ts.',\n }\n }\n\n if (/Create a new file at src\\/newfile\\.ts/i.test(prompt)) {\n return {\n tools: [{ name: 'write_file', arguments: { path: 'src/newfile.ts', content: 'export const greeting = \"hello\"' } }],\n response: 'Created src/newfile.ts.',\n }\n }\n\n if (/Create a file at deep\\/nested\\/path\\/file\\.ts/i.test(prompt)) {\n return {\n tools: [{ name: 'write_file', arguments: { path: 'deep/nested/path/file.ts', content: 'export const x = 1' } }],\n response: 'Created nested file.',\n }\n }\n\n if (/Read src\\/math\\.ts, then use edit_file/i.test(prompt) && quotedValues.length >= 2) {\n return {\n tools: [\n { name: 'read_file', arguments: { path: 'src/math.ts' } },\n { name: 'edit_file', arguments: { path: 'src/math.ts', old_string: quotedValues[0], new_string: quotedValues[1] } },\n ],\n response: 'Updated src/math.ts.',\n }\n }\n\n if (prompt.includes('workdir parameter') && prompt.includes('src directory')) {\n return {\n tools: [{ name: 'run_command', arguments: { command: 'ls', cwd: 'src' } }],\n response: 'Listed src directory.',\n }\n }\n\n if (/Run the command \"ls src\" to list files in src directory/i.test(prompt)) {\n return {\n tools: [{ name: 'run_command', arguments: { command: 'ls src' } }],\n response: 'Listed src files.',\n }\n }\n\n if (/Run the command \"ls\" to list files in the current directory/i.test(prompt)) {\n return {\n tools: [{ name: 'run_command', arguments: { command: 'ls' } }],\n response: 'Listed current directory.',\n }\n }\n\n if (/Run the command \"ls \\/nonexistent\\/path\\/xyz\"/i.test(prompt)) {\n return {\n tools: [{ name: 'run_command', arguments: { command: 'ls nonexistent-path-xyz' } }],\n response: 'Ran the failing command.',\n }\n }\n\n if (exactCommandMatch) {\n return {\n tools: [{ name: 'run_command', arguments: { command: exactCommandMatch[1]!.trim() } }],\n response: 'Ran the exact command.',\n }\n }\n\n if (/^Run \"/i.test(prompt)) {\n const commands = quotedValues\n if (/and then run/i.test(prompt) && commands.length >= 2) {\n return {\n tools: commands.slice(0, 2).map(command => ({ name: 'run_command', arguments: { command } })),\n response: 'Ran both commands.',\n }\n }\n\n if (commands.length >= 1) {\n return {\n tools: [{ name: 'run_command', arguments: { command: commands[0] } }],\n response: 'Ran the command.',\n }\n }\n }\n\n return null\n}\n\nfunction getConversationAwareToolResponse(request: LLMCompletionRequest): MockMatchResult | null {\n const prompt = getLastUserPrompt(request)\n const conversationText = getConversationText(request)\n\n if (\n /Implement the task and make sure you fulfil the \\d+ criteria\\./i.test(prompt)\n || /Continue working on the acceptance criteria\\./i.test(prompt)\n ) {\n const tools: Array<{ name: string; arguments: Record<string, unknown> }> = []\n const completedCriteria: string[] = []\n\n if (conversationText.includes('inspect-src')) {\n tools.push(\n { name: 'read_file', arguments: { path: 'src' } },\n { name: 'complete_criterion', arguments: { id: 'inspect-src', reason: 'Inspected the src directory and reported what exists' } },\n )\n completedCriteria.push('inspect-src')\n }\n\n if (conversationText.includes('trivial-pass')) {\n tools.push({ name: 'complete_criterion', arguments: { id: 'trivial-pass', reason: 'Trivial criterion passes immediately' } })\n completedCriteria.push('trivial-pass')\n }\n\n if (conversationText.includes('verify-fail')) {\n tools.push({ name: 'complete_criterion', arguments: { id: 'verify-fail', reason: 'Prepared criterion for verification' } })\n completedCriteria.push('verify-fail')\n }\n\n if (conversationText.includes('file-created')) {\n tools.push(\n { name: 'write_file', arguments: { path: 'src/utils.ts', content: 'export const created = true' } },\n { name: 'complete_criterion', arguments: { id: 'file-created', reason: 'Created the requested file' } },\n )\n completedCriteria.push('file-created')\n }\n\n if (tools.length > 0) {\n return {\n tools,\n response: `Completed builder work for: ${completedCriteria.join(', ')}.`,\n }\n }\n }\n\n if (/Verify each criterion marked \\[NEEDS VERIFICATION\\]\\./i.test(prompt)) {\n // Only return verifier tools on the first call — if we already called pass/fail, stop\n const alreadyVerified = request.messages.some(m =>\n m.role === 'assistant' && m.toolCalls?.some(tc =>\n tc.name === 'pass_criterion' || tc.name === 'fail_criterion'\n )\n )\n if (alreadyVerified) {\n return null\n }\n\n const tools: Array<{ name: string; arguments: Record<string, unknown> }> = []\n const terminalizedCriteria: string[] = []\n\n if (conversationText.includes('trivial-pass')) {\n tools.push({ name: 'pass_criterion', arguments: { id: 'trivial-pass', reason: 'Verified successfully' } })\n terminalizedCriteria.push('trivial-pass')\n }\n\n if (conversationText.includes('inspect-src')) {\n tools.push({ name: 'pass_criterion', arguments: { id: 'inspect-src', reason: 'Verified the src directory was inspected successfully' } })\n terminalizedCriteria.push('inspect-src')\n }\n\n if (conversationText.includes('verify-fail')) {\n tools.push({ name: 'fail_criterion', arguments: { id: 'verify-fail', reason: 'Verification fails intentionally for this criterion' } })\n terminalizedCriteria.push('verify-fail')\n }\n\n if (conversationText.includes('file-created')) {\n tools.push({ name: 'pass_criterion', arguments: { id: 'file-created', reason: 'Verified the file was created successfully' } })\n terminalizedCriteria.push('file-created')\n }\n\n if (conversationText.includes('impossible/path')) {\n tools.push({ name: 'fail_criterion', arguments: { id: 'auto-impossible', reason: 'Impossible path does not exist' } })\n terminalizedCriteria.push('auto-impossible')\n }\n\n if (tools.length > 0) {\n tools.push({ name: 'return_value', arguments: { summary: `Terminalized verifier work for: ${terminalizedCriteria.join(', ')}.` } })\n return {\n tools,\n response: `Terminalized verifier work for: ${terminalizedCriteria.join(', ')}.`,\n }\n }\n }\n\n return null\n}\n\nfunction getToolFollowUpResponse(request: LLMCompletionRequest): string {\n const prompt = getLastUserPrompt(request)\n\n if (/what guidelines should i follow\\??/i.test(prompt)) {\n return 'Follow the function, test, TDD, and style guidelines.'\n }\n\n if (/read the package\\.json file and tell me the project name\\.?/i.test(prompt)) {\n return 'The project name is test-project.'\n }\n\n if (/read package\\.json and tell me the project version\\.?/i.test(prompt)) {\n return 'The project version is 1.0.0.'\n }\n\n if (/read package\\.json and summarize it\\.?/i.test(prompt)) {\n return 'The package defines test-project version 1.0.0 with TypeScript build and test scripts.'\n }\n\n return 'Done.'\n}\n\nfunction isSlowStreamingPrompt(prompt: string): boolean {\n return /long.*explanation|detailed.*explanation/i.test(prompt)\n}\n\nfunction buildMockResponse(request: LLMCompletionRequest): {\n content: string\n toolCalls: ToolCall[]\n finishReason: LLMCompletionResponse['finishReason']\n} {\n // Detect compaction requests: no tools, toolChoice 'none' (summary generation)\n if (request.toolChoice === 'none' && (!request.tools || request.tools.length === 0)) {\n return {\n content: 'Summary of conversation: The user has been working on the project. Files were modified and progress was made on all tasks. No errors were encountered during the session.',\n toolCalls: [],\n finishReason: 'stop',\n }\n }\n\n const lastMsg = request.messages[request.messages.length - 1]\n if (lastMsg?.role === 'tool') {\n return {\n content: getToolFollowUpResponse(request),\n toolCalls: [],\n finishReason: 'stop',\n }\n }\n\n const instructionAwareResponse = getInstructionAwareResponse(request)\n if (instructionAwareResponse) {\n return {\n content: instructionAwareResponse,\n toolCalls: [],\n finishReason: 'stop',\n }\n }\n\n const prompt = getLastUserPrompt(request)\n const conversationAwareToolResponse = getConversationAwareToolResponse(request)\n if (conversationAwareToolResponse) {\n const toolCalls: ToolCall[] = conversationAwareToolResponse.tools.map((tool, index) => ({\n id: `mock-${Date.now()}-${index}`,\n name: tool.name,\n arguments: tool.arguments,\n }))\n\n return {\n content: conversationAwareToolResponse.response,\n toolCalls,\n finishReason: toolCalls.length > 0 ? 'tool_calls' : 'stop',\n }\n }\n\n const promptAwareToolResponse = getPromptAwareToolResponse(prompt)\n if (promptAwareToolResponse) {\n const toolCalls: ToolCall[] = promptAwareToolResponse.tools.map((tool, index) => ({\n id: `mock-${Date.now()}-${index}`,\n name: tool.name,\n arguments: tool.arguments,\n }))\n\n return {\n content: promptAwareToolResponse.response,\n toolCalls,\n finishReason: toolCalls.length > 0 ? 'tool_calls' : 'stop',\n }\n }\n\n const { rule, captures } = matchRule(prompt)\n const toolCalls: ToolCall[] = rule.tools.map((tool, index) => ({\n id: `mock-${Date.now()}-${index}`,\n name: tool.name,\n arguments: applyCaptures(tool.arguments, captures),\n }))\n\n return {\n content: rule.response,\n toolCalls,\n finishReason: toolCalls.length > 0 ? 'tool_calls' : 'stop',\n }\n}\n\n// ============================================================================\n// Mock LLM Client\n// ============================================================================\n\nexport function createMockLLMClient(): LLMClientWithModel {\n const model = process.env['OPENFOX_MODEL_NAME'] ?? 'mock-model'\n const profile = getModelProfile(model)\n let backend: Backend = 'unknown'\n\n return {\n getModel: () => model,\n setModel: () => {},\n getProfile: () => profile,\n getBackend: () => backend,\n setBackend: (b: Backend) => { backend = b },\n\n async complete(request: LLMCompletionRequest): Promise<LLMCompletionResponse> {\n const prompt = getLastUserPrompt(request)\n\n if (request.signal?.aborted) throw new Error('Aborted')\n const response = buildMockResponse(request)\n\n if (process.env['OPENFOX_TEST_VERBOSE'] === 'true') {\n logger.debug('MockLLM completion', { prompt: prompt.slice(0, 50), hasTools: response.toolCalls.length > 0, tools: response.toolCalls.map(tc => tc.name) })\n }\n\n return {\n id: `mock-${Date.now()}`,\n content: response.content,\n thinkingContent: '',\n toolCalls: response.toolCalls,\n finishReason: response.finishReason,\n usage: { promptTokens: 100, completionTokens: 50, totalTokens: 150 },\n }\n },\n\n async *stream(request: LLMCompletionRequest): AsyncIterable<LLMStreamEvent> {\n const prompt = getLastUserPrompt(request)\n\n if (request.signal?.aborted) throw new Error('Aborted')\n const response = buildMockResponse(request)\n\n if (process.env['OPENFOX_TEST_VERBOSE'] === 'true') {\n logger.debug('MockLLM stream', { prompt: prompt.slice(0, 50), hasTools: response.toolCalls.length > 0, tools: response.toolCalls.map(tc => tc.name) })\n }\n\n // Stream tool calls\n for (let i = 0; i < response.toolCalls.length; i++) {\n const tc = response.toolCalls[i]!\n yield { type: 'tool_call_delta', index: i, id: tc.id, name: tc.name, arguments: JSON.stringify(tc.arguments) }\n }\n\n // Stream text response\n const words = response.content.split(' ')\n const slowStreaming = isSlowStreamingPrompt(prompt)\n for (const word of words) {\n yield { type: 'text_delta', content: word + ' ' }\n if (slowStreaming) {\n await sleep(20)\n }\n }\n\n // Done\n yield {\n type: 'done',\n response: {\n id: `mock-${Date.now()}`,\n content: response.content,\n thinkingContent: '',\n toolCalls: response.toolCalls,\n finishReason: response.finishReason,\n usage: { promptTokens: 100, completionTokens: 50, totalTokens: 150 },\n },\n }\n },\n }\n}\n","import { WebSocketServer, WebSocket } from 'ws'\nimport type { Server } from 'node:http'\nimport type { ServerMessage } from '../../shared/protocol.js'\nimport type { Config } from '../config.js'\nimport type { LLMClientWithModel } from '../llm/client.js'\nimport type { ToolRegistry } from '../tools/index.js'\nimport type { SessionManager } from '../session/index.js'\nimport { getEventStore, getCurrentContextWindowId, getRecentUserPromptsForSession } from '../events/index.js'\nimport { buildContextMessagesFromEventHistory, buildMessagesFromStoredEvents } from '../events/folding.js'\nimport type { Message, Provider, ProviderBackend, StatsIdentity, Attachment } from '../../shared/types.js'\nimport type { ProviderManager } from '../provider-manager.js'\nimport { createLLMClient } from '../llm/index.js'\nimport { runChatTurn, createMessageStartEvent, createChatDoneEvent } from '../chat/orchestrator.js'\nimport { loadAllAgentsDefault, findAgentById } from '../agents/registry.js'\nimport { runOrchestrator } from '../runner/index.js'\nimport { maybeAutoCompactContext, performManualContextCompaction } from '../context/auto-compaction.js'\nimport {\n providePathConfirmation,\n addAllowedPaths,\n cancelQuestionsForSession,\n cancelPathConfirmationsForSession,\n} from '../tools/index.js'\nimport { logger } from '../utils/logger.js'\nimport {\n createProject,\n getProject,\n listProjects,\n updateProject,\n deleteProject,\n} from '../db/projects.js'\nimport { getSetting, setSetting } from '../db/settings.js'\nimport { updateSessionMetadata } from '../db/sessions.js'\nimport { generateSessionName, needsNameGeneration } from '../session/name-generator.js'\nimport { generateSessionSummary, needsSummaryGeneration } from '../session/summary-generator.js'\n// Messages are now retrieved from EventStore, not DB\nimport {\n parseClientMessage,\n serializeServerMessage,\n createErrorMessage,\n createSessionStateMessage,\n createSessionListMessage,\n createSessionRunningMessage,\n createProjectStateMessage,\n createProjectListMessage,\n createChatDeltaMessage,\n createChatThinkingMessage,\n createChatToolCallMessage,\n createChatToolResultMessage,\n createChatMessageMessage,\n createChatMessageUpdatedMessage,\n createChatDoneMessage,\n createChatErrorMessage,\n createModeChangedMessage,\n createPhaseChangedMessage,\n createCriteriaUpdatedMessage,\n createContextStateMessage,\n isProjectCreatePayload,\n isProjectCreateWithDirPayload,\n isProjectLoadPayload,\n isProjectUpdatePayload,\n isProjectDeletePayload,\n isSessionCreatePayload,\n isSessionLoadPayload,\n isChatSendPayload,\n isModeSwitchPayload,\n isCriteriaEditPayload,\n isPathConfirmPayload,\n isSettingsGetPayload,\n isSettingsSetPayload,\n isSessionSetProviderPayload,\n createSettingsValueMessage,\n storedEventToServerMessage,\n createQueueStateMessage,\n isQueueAsapPayload,\n isQueueCompletionPayload,\n isQueueCancelPayload,\n} from './protocol.js'\n\nfunction getCurrentWindowMessageOptions(sessionId: string): { contextWindowId: string } | undefined {\n const contextWindowId = getCurrentContextWindowId(sessionId)\n return contextWindowId ? { contextWindowId } : undefined\n}\n\n/**\n * Get the count of user messages in a session.\n * Used to determine if this is the first user message.\n */\nfunction getSessionMessageCount(sessionId: string): number {\n const eventStore = getEventStore()\n const events = eventStore.getEvents(sessionId)\n \n let count = 0\n for (const event of events) {\n if (event.type === 'message.start') {\n const data = event.data as { role: string }\n if (data.role === 'user') {\n count++\n }\n }\n }\n \n return count\n}\n\nfunction resolveStatsIdentity(\n llmClient: LLMClientWithModel,\n getActiveProvider?: () => Provider | undefined,\n): StatsIdentity {\n const provider = getActiveProvider?.()\n const model = llmClient.getModel()\n const backend = provider?.backend ?? (llmClient.getBackend() === 'unknown' ? 'unknown' : llmClient.getBackend())\n\n return {\n providerId: provider?.id ?? `provider:${model}`,\n providerName: provider?.name ?? 'Unknown Provider',\n backend,\n model,\n }\n}\n\n// Track active agent AbortControllers by sessionId\nconst activeAgents = new Map<string, AbortController>()\n\ninterface ClientConnection {\n ws: WebSocket\n activeSessionId: string | null // Currently viewing session\n subscribedSessions: Map<string, () => void> // sessionId -> unsubscribe fn (old event system)\n eventStoreSubscriptions: Map<string, () => void> // sessionId -> unsubscribe fn (new EventStore)\n}\n\nexport function createWebSocketServer(\n httpServer: Server,\n config: Config,\n getLLMClient: () => LLMClientWithModel,\n getActiveProvider: (() => Provider | undefined) | undefined,\n toolRegistry: ToolRegistry,\n sessionManager: SessionManager,\n providerManager?: ProviderManager,\n): WebSocketServer {\n const wss = new WebSocketServer({ server: httpServer, path: '/ws' })\n const clients = new Map<WebSocket, ClientConnection>()\n\n // Per-session LLM client cache: sessionId -> { cacheKey, client }\n const sessionLLMClients = new Map<string, { key: string; client: LLMClientWithModel }>()\n\n function getSessionLLMClient(sessionId: string): LLMClientWithModel {\n const session = sessionManager.getSession(sessionId)\n if (!session?.providerId || !session?.providerModel || !providerManager) {\n return getLLMClient()\n }\n\n const cacheKey = `${session.providerId}:${session.providerModel}`\n const cached = sessionLLMClients.get(sessionId)\n if (cached && cached.key === cacheKey) {\n return cached.client\n }\n\n // Look up the provider to get URL, apiKey, backend\n const provider = providerManager.getProviders().find(p => p.id === session.providerId)\n if (!provider) {\n // Provider was deleted — clear preference and fall back to global\n logger.warn('Session references deleted provider, falling back to global', {\n sessionId, providerId: session.providerId,\n })\n sessionManager.setSessionProvider(sessionId, null, null)\n sessionLLMClients.delete(sessionId)\n return getLLMClient()\n }\n\n // Create a new LLM client for this session\n const baseUrl = provider.url.includes('/v1') ? provider.url : `${provider.url}/v1`\n const sessionConfig: Config = {\n ...config,\n llm: { ...config.llm, baseUrl, model: session.providerModel! },\n }\n const client = createLLMClient(sessionConfig)\n // Set backend from provider (skip auto-detect for cached clients)\n if (provider.backend !== 'auto') {\n client.setBackend(provider.backend as import('../llm/index.js').Backend)\n }\n client.setModel(session.providerModel!)\n\n sessionLLMClients.set(sessionId, { key: cacheKey, client })\n return client\n }\n\n function getSessionStatsIdentity(sessionId: string): StatsIdentity {\n const session = sessionManager.getSession(sessionId)\n if (!session?.providerId || !providerManager) {\n return resolveStatsIdentity(getLLMClient(), getActiveProvider)\n }\n\n const provider = providerManager.getProviders().find(p => p.id === session.providerId)\n const client = getSessionLLMClient(sessionId)\n return {\n providerId: provider?.id ?? session.providerId!,\n providerName: provider?.name ?? 'Unknown Provider',\n backend: (provider?.backend ?? client.getBackend()) as ProviderBackend,\n model: client.getModel(),\n }\n }\n\n function invalidateSessionLLMClient(sessionId: string): void {\n sessionLLMClients.delete(sessionId)\n }\n const isSubscribedToSession = (client: ClientConnection, sessionId: string) => {\n return client.activeSessionId === sessionId || client.eventStoreSubscriptions.has(sessionId)\n }\n \n const broadcastForSession = (sessionId: string, msg: ServerMessage) => {\n for (const [clientWs, client] of clients) {\n if (isSubscribedToSession(client, sessionId) && clientWs.readyState === WebSocket.OPEN) {\n clientWs.send(serializeServerMessage({ ...msg, sessionId }))\n }\n }\n }\n \n // Subscribe to session events and broadcast to relevant clients\n sessionManager.subscribe((event) => {\n const sessionId = 'sessionId' in event ? event.sessionId : \n 'session' in event ? event.session.id : null\n \n if (!sessionId) return\n \n for (const [ws, client] of clients) {\n // Send events to all clients subscribed to this session (tab model)\n if (isSubscribedToSession(client, sessionId) && ws.readyState === WebSocket.OPEN) {\n // Only broadcast session.state for session_updated (not mode_changed)\n // mode_changed is handled via the event queue to maintain ordering during streaming\n if (event.type === 'session_updated') {\n const session = sessionManager.getSession(sessionId)\n if (session) {\n // Get messages from EventStore\n const eventStore = getEventStore()\n const events = eventStore.getEvents(sessionId)\n const messages = events.length > 0\n ? buildMessagesFromStoredEvents(events)\n : []\n ws.send(serializeServerMessage({ ...createSessionStateMessage(session, messages), sessionId }))\n }\n }\n \n // Broadcast running state changes in real-time\n if (event.type === 'running_changed') {\n ws.send(serializeServerMessage({ ...createSessionRunningMessage(event.isRunning), sessionId }))\n }\n }\n }\n })\n \n wss.on('connection', (ws) => {\n logger.debug('WebSocket client connected')\n clients.set(ws, { ws, activeSessionId: null, subscribedSessions: new Map(), eventStoreSubscriptions: new Map() })\n \n ws.on('message', async (data) => {\n const message = parseClientMessage(data.toString())\n \n if (!message) {\n ws.send(serializeServerMessage(createErrorMessage('INVALID_MESSAGE', 'Invalid message format')))\n return\n }\n \n const client = clients.get(ws)!\n \n try {\n await handleClientMessage(ws, client, message, config, getLLMClient, getActiveProvider, toolRegistry, sessionManager, broadcastForSession, providerManager, getSessionLLMClient, getSessionStatsIdentity, invalidateSessionLLMClient)\n } catch (error) {\n logger.error('Error handling client message', { error, type: message.type })\n ws.send(serializeServerMessage(\n createErrorMessage(\n 'INTERNAL_ERROR',\n error instanceof Error ? error.message : 'Unknown error',\n message.id\n )\n ))\n }\n })\n \n ws.on('close', () => {\n logger.debug('WebSocket client disconnected')\n const client = clients.get(ws)\n // Unsubscribe from all session events (both old and new systems)\n if (client) {\n for (const unsubscribe of client.subscribedSessions.values()) {\n unsubscribe()\n }\n for (const unsubscribe of client.eventStoreSubscriptions.values()) {\n unsubscribe()\n }\n }\n clients.delete(ws)\n })\n \n ws.on('error', (error) => {\n logger.error('WebSocket error', { error })\n })\n })\n \n return wss\n}\n\nasync function handleClientMessage(\n ws: WebSocket,\n client: ClientConnection,\n message: { id: string; type: string; payload: unknown },\n config: Config,\n getLLMClient: () => LLMClientWithModel,\n getActiveProvider: (() => Provider | undefined) | undefined,\n toolRegistry: ToolRegistry,\n sessionManager: SessionManager,\n broadcastForSession: (sessionId: string, msg: ServerMessage) => void,\n providerManager?: ProviderManager,\n getSessionLLMClient?: (sessionId: string) => LLMClientWithModel,\n getSessionStatsIdentity?: (sessionId: string) => StatsIdentity,\n invalidateSessionLLMClient?: (sessionId: string) => void,\n): Promise<void> {\n const send = (msg: ServerMessage) => {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(serializeServerMessage(msg))\n }\n }\n\n const sendForSession = (sessionId: string, msg: ServerMessage) => {\n send({ ...msg, sessionId })\n }\n\n const abortSessionExecution = (sessionId: string, reason: string) => {\n const controller = activeAgents.get(sessionId)\n if (!controller) {\n return false\n }\n\n activeAgents.delete(sessionId)\n controller.abort()\n cancelQuestionsForSession(sessionId, reason)\n cancelPathConfirmationsForSession(sessionId, reason)\n sessionManager.setRunning(sessionId, false)\n sendForSession(sessionId, createSessionRunningMessage(false))\n const contextState = sessionManager.getContextState(sessionId)\n sendForSession(sessionId, createContextStateMessage(contextState))\n return true\n }\n\n // Per-session LLM resolution helpers\n const llmForSession = (sessionId: string): LLMClientWithModel =>\n getSessionLLMClient?.(sessionId) ?? getLLMClient()\n\n const statsForSession = (sessionId: string): StatsIdentity =>\n getSessionStatsIdentity?.(sessionId) ?? resolveStatsIdentity(getLLMClient(), getActiveProvider)\n\n /**\n * Start a chat turn with completion queue continuation.\n * When a turn finishes, checks for queued completion messages and auto-starts the next turn.\n */\n const startTurnWithCompletionChain = (sessionId: string, controller: AbortController) => {\n runChatTurn({\n sessionManager,\n sessionId,\n llmClient: llmForSession(sessionId),\n statsIdentity: statsForSession(sessionId),\n signal: controller.signal,\n onMessage: (msg) => sendForSession(sessionId, msg),\n }).catch((error) => {\n if (error instanceof Error && error.message === 'Aborted') {\n return\n }\n logger.error('Chat turn error', { error })\n }).finally(() => {\n if (activeAgents.get(sessionId) !== controller) {\n return\n }\n activeAgents.delete(sessionId)\n\n // Check completion queue before going idle\n const completionMsgs = sessionManager.drainCompletionMessages(sessionId)\n const next = completionMsgs[0]\n if (next) {\n // Re-queue remaining completion messages\n for (const remaining of completionMsgs.slice(1)) {\n sessionManager.queueMessage(sessionId, 'completion', remaining.content, remaining.attachments)\n }\n // Broadcast updated queue state\n sendForSession(sessionId, createQueueStateMessage(sessionManager.getQueueState(sessionId)))\n\n // Add user message and start new turn\n const userMessage = sessionManager.addMessage(sessionId, {\n role: 'user',\n content: next.content,\n ...(next.attachments ? { attachments: next.attachments } : {}),\n })\n sendForSession(sessionId, createChatMessageMessage(userMessage))\n\n const newController = new AbortController()\n activeAgents.set(sessionId, newController)\n startTurnWithCompletionChain(sessionId, newController)\n return // Keep isRunning=true\n }\n\n // No more queued messages — go idle\n sessionManager.clearMessageQueue(sessionId)\n sessionManager.setRunning(sessionId, false)\n const contextState = sessionManager.getContextState(sessionId)\n sendForSession(sessionId, createContextStateMessage(contextState))\n })\n }\n\n const ensureEventStoreSubscription = (sessionId: string) => {\n if (client.eventStoreSubscriptions.has(sessionId)) {\n return\n }\n\n const sid = sessionId\n const eventStore = getEventStore()\n const { iterator, unsubscribe } = eventStore.subscribe(sid)\n client.eventStoreSubscriptions.set(sessionId, unsubscribe)\n\n ;(async () => {\n try {\n for await (const storedEvent of iterator) {\n const serverMsg = storedEventToServerMessage(storedEvent)\n if (serverMsg && ws.readyState === WebSocket.OPEN) {\n ws.send(serializeServerMessage({ ...serverMsg, seq: storedEvent.seq, sessionId: sid }))\n }\n }\n } catch (error) {\n logger.debug('EventStore subscription ended', { sessionId: sid, error })\n }\n })()\n\n logger.debug('Subscribed to EventStore', { sessionId })\n }\n \n switch (message.type) {\n // =========================================================================\n // Project Management\n // =========================================================================\n \n case 'project.create': {\n if (!isProjectCreatePayload(message.payload)) {\n send(createErrorMessage('INVALID_PAYLOAD', 'Invalid project.create payload', message.id))\n return\n }\n \n const project = createProject(message.payload.name, message.payload.workdir)\n send(createProjectStateMessage(project, message.id))\n break\n }\n \n case 'project.create-with-dir': {\n logger.debug('WS project.create-with-dir received', { payload: message.payload })\n if (!isProjectCreateWithDirPayload(message.payload)) {\n logger.error('WS project.create-with-dir invalid payload')\n send(createErrorMessage('INVALID_PAYLOAD', 'Invalid project.create-with-dir payload', message.id))\n return\n }\n \n try {\n const workdir = config.workdir\n logger.debug('WS creating project directory', { name: message.payload.name, workdir })\n const { createDirectoryWithGit } = await import('../utils/project-creator.js')\n const project = await createDirectoryWithGit(message.payload.name, workdir)\n logger.debug('WS project created', { id: project.id, name: project.name })\n send(createProjectStateMessage(project, message.id))\n logger.debug('WS sent project.state', { messageId: message.id })\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error'\n logger.error('WS project creation failed', { error: errorMessage })\n send(createErrorMessage('PROJECT_CREATION_FAILED', errorMessage, message.id))\n }\n break\n }\n \n case 'project.list': {\n logger.debug('WS project.list received', { messageId: message.id })\n const projects = listProjects()\n logger.debug('WS projects found', { count: projects.length, projects: projects.map(p => ({ id: p.id, name: p.name })) })\n send(createProjectListMessage(projects, message.id))\n logger.debug('WS sent project.list', { messageId: message.id })\n break\n }\n \n case 'project.load': {\n if (!isProjectLoadPayload(message.payload)) {\n send(createErrorMessage('INVALID_PAYLOAD', 'Invalid project.load payload', message.id))\n return\n }\n \n const project = getProject(message.payload.projectId)\n if (!project) {\n send(createErrorMessage('NOT_FOUND', 'Project not found', message.id))\n return\n }\n \n send(createProjectStateMessage(project, message.id))\n break\n }\n \n case 'project.update': {\n if (!isProjectUpdatePayload(message.payload)) {\n send(createErrorMessage('INVALID_PAYLOAD', 'Invalid project.update payload', message.id))\n return\n }\n \n const updates: { name?: string; customInstructions?: string | null } = {}\n if (message.payload.name !== undefined) {\n updates.name = message.payload.name\n }\n if (message.payload.customInstructions !== undefined) {\n updates.customInstructions = message.payload.customInstructions\n }\n \n const updated = updateProject(message.payload.projectId, updates)\n if (!updated) {\n send(createErrorMessage('NOT_FOUND', 'Project not found', message.id))\n return\n }\n \n send(createProjectStateMessage(updated, message.id))\n break\n }\n \n case 'project.delete': {\n if (!isProjectDeletePayload(message.payload)) {\n send(createErrorMessage('INVALID_PAYLOAD', 'Invalid project.delete payload', message.id))\n return\n }\n \n deleteProject(message.payload.projectId)\n send({ type: 'project.deleted', payload: { projectId: message.payload.projectId }, id: message.id })\n break\n }\n \n // =========================================================================\n // Settings Management\n // =========================================================================\n \n case 'settings.get': {\n if (!isSettingsGetPayload(message.payload)) {\n send(createErrorMessage('INVALID_PAYLOAD', 'Invalid settings.get payload', message.id))\n return\n }\n \n const value = getSetting(message.payload.key)\n send(createSettingsValueMessage(message.payload.key, value, message.id))\n break\n }\n \n case 'settings.set': {\n if (!isSettingsSetPayload(message.payload)) {\n send(createErrorMessage('INVALID_PAYLOAD', 'Invalid settings.set payload', message.id))\n return\n }\n \n setSetting(message.payload.key, message.payload.value)\n send(createSettingsValueMessage(message.payload.key, message.payload.value, message.id))\n break\n }\n \n // =========================================================================\n // Session Management\n // =========================================================================\n \n case 'session.create': {\n if (!isSessionCreatePayload(message.payload)) {\n send(createErrorMessage('INVALID_PAYLOAD', 'Invalid session.create payload', message.id))\n return\n }\n \n // Snapshot current global provider/model into new session\n const currentProvider = providerManager?.getActiveProvider()\n const currentModel = currentProvider ? getLLMClient().getModel() : null\n const session = sessionManager.createSession(\n message.payload.projectId,\n message.payload.title,\n currentProvider?.id ?? null,\n currentModel,\n )\n client.activeSessionId = session.id\n // New session has no events yet\n sendForSession(session.id, createSessionStateMessage(session, [], message.id))\n \n // Send initial context state\n const contextState = sessionManager.getContextState(session.id)\n sendForSession(session.id, createContextStateMessage(contextState))\n break\n }\n \n case 'session.load': {\n if (!isSessionLoadPayload(message.payload)) {\n send(createErrorMessage('INVALID_PAYLOAD', 'Invalid session.load payload', message.id))\n return\n }\n \n const session = sessionManager.getSession(message.payload.sessionId)\n if (!session) {\n send(createErrorMessage('NOT_FOUND', 'Session not found', message.id))\n return\n }\n \n // Tab model: set active session and subscribe if not already subscribed\n client.activeSessionId = session.id\n ensureEventStoreSubscription(session.id)\n \n // Fetch messages - prefer EventStore if it has events, otherwise fall back to messages table\n const eventStore = getEventStore()\n const events = eventStore.getEvents(session.id)\n \n let messages: Message[]\n // Build messages from EventStore\n messages = buildMessagesFromStoredEvents(events)\n logger.debug('Loaded messages from EventStore', { sessionId: session.id, eventCount: events.length, messageCount: messages.length })\n\n sendForSession(session.id, createSessionStateMessage(session, messages, message.id))\n \n // Send context state\n const contextState = sessionManager.getContextState(session.id)\n sendForSession(session.id, createContextStateMessage(contextState))\n \n // No event replay needed - client stays subscribed to all sessions (tab model)\n break\n }\n \n case 'session.list': {\n const sessions = sessionManager.listSessions()\n \n // Add recent user prompts to each session\n const sessionsWithPrompts = sessions.map(session => ({\n ...session,\n recentUserPrompts: getRecentUserPromptsForSession(session.id, 10),\n }))\n \n send(createSessionListMessage(sessionsWithPrompts, message.id))\n break\n }\n \n case 'session.delete': {\n if (!isSessionLoadPayload(message.payload)) {\n send(createErrorMessage('INVALID_PAYLOAD', 'Invalid session.delete payload', message.id))\n return\n }\n \n sessionManager.deleteSession(message.payload.sessionId)\n send({ type: 'session.deleted', payload: { sessionId: message.payload.sessionId }, id: message.id })\n break\n }\n \n case 'session.deleteAll': {\n if (!message.payload || typeof message.payload !== 'object' || !('projectId' in message.payload)) {\n send(createErrorMessage('INVALID_PAYLOAD', 'Invalid session.deleteAll payload', message.id))\n return\n }\n const payload = message.payload as { projectId: string }\n const project = sessionManager.getProject(payload.projectId)\n if (!project) {\n send(createErrorMessage('PROJECT_NOT_FOUND', 'Project not found', message.id))\n return\n }\n sessionManager.deleteAllSessions(payload.projectId, project.workdir)\n send({ type: 'session.deletedAll', payload: { projectId: payload.projectId }, id: message.id })\n break\n }\n\n case 'session.setProvider': {\n if (!client.activeSessionId) {\n send(createErrorMessage('NO_SESSION', 'No active session', message.id))\n return\n }\n\n if (!isSessionSetProviderPayload(message.payload)) {\n send(createErrorMessage('INVALID_PAYLOAD', 'Invalid session.setProvider payload', message.id))\n return\n }\n\n if (!providerManager) {\n send(createErrorMessage('NO_PROVIDERS', 'Provider management not available', message.id))\n return\n }\n\n const { providerId, model: requestedModel } = message.payload\n const provider = providerManager.getProviders().find(p => p.id === providerId)\n if (!provider) {\n send(createErrorMessage('PROVIDER_NOT_FOUND', 'Provider not found', message.id))\n return\n }\n\n // Resolve model: use requested, or default to 'auto'\n const resolvedModel = requestedModel ?? 'auto'\n\n const sessionId = client.activeSessionId\n sessionManager.setSessionProvider(sessionId, providerId, resolvedModel)\n invalidateSessionLLMClient?.(sessionId)\n\n // Send updated session state\n const eventStore = getEventStore()\n const updatedSession = sessionManager.requireSession(sessionId)\n const events = eventStore.getEvents(sessionId)\n const messages = buildMessagesFromStoredEvents(events)\n sendForSession(sessionId, createSessionStateMessage(updatedSession, messages, message.id))\n break\n }\n\n // =========================================================================\n // Unified Chat (replaces plan.message, agent.start, etc.)\n // =========================================================================\n \n case 'chat.send': {\n if (!client.activeSessionId) {\n send(createErrorMessage('NO_SESSION', 'No active session', message.id))\n return\n }\n \n if (!isChatSendPayload(message.payload)) {\n send(createErrorMessage('INVALID_PAYLOAD', 'Invalid chat.send payload', message.id))\n return\n }\n \n // Check if session is already running - reject concurrent execution\n const currentSession = sessionManager.requireSession(client.activeSessionId)\n if (currentSession.isRunning) {\n send(createErrorMessage('ALREADY_RUNNING', 'Session is already running', message.id))\n return\n }\n \n // Check if session is blocked - user intervention resets it\n if (currentSession.phase === 'blocked') {\n logger.info('User intervention - resetting blocked state', { sessionId: client.activeSessionId })\n sessionManager.setPhase(client.activeSessionId, 'build')\n sessionManager.resetAllCriteriaAttempts(client.activeSessionId)\n sendForSession(client.activeSessionId, createPhaseChangedMessage('build'))\n }\n \n const sessionId = client.activeSessionId\n const eventStore = getEventStore()\n\n ensureEventStoreSubscription(sessionId)\n\n await maybeAutoCompactContext({\n sessionManager,\n sessionId,\n llmClient: llmForSession(sessionId),\n statsIdentity: statsForSession(sessionId),\n })\n \n // Add user message with attachments (emits events to EventStore)\n const userMessage = sessionManager.addMessage(sessionId, {\n role: 'user',\n content: message.payload.content,\n ...(message.payload.attachments && { attachments: message.payload.attachments }),\n ...(message.payload.messageKind && { messageKind: message.payload.messageKind }),\n ...(message.payload.isSystemGenerated && { isSystemGenerated: message.payload.isSystemGenerated }),\n })\n \n // Check if we need to generate a session name (first message with default/empty title)\n const messageCount = getSessionMessageCount(sessionId)\n if (needsNameGeneration(currentSession.metadata.title, messageCount)) {\n // Generate name in parallel - don't block the chat turn\n // Use the active LLM client (respects user's selected model)\n generateSessionName({\n userMessage: message.payload.content,\n llmClient: llmForSession(sessionId),\n })\n .then(async (result) => {\n if (result.success && result.name) {\n // Update DB with the generated name\n updateSessionMetadata(sessionId, { title: result.name })\n \n // Emit session.name_generated event to EventStore\n eventStore.append(sessionId, {\n type: 'session.name_generated',\n data: { name: result.name },\n })\n \n // Broadcast updated session state to all WebSocket clients\n const updatedSession = sessionManager.getSession(sessionId)\n if (updatedSession) {\n const events = eventStore.getEvents(sessionId)\n const messages = buildMessagesFromStoredEvents(events)\n broadcastForSession(sessionId, createSessionStateMessage(updatedSession, messages))\n }\n \n logger.info('Session name generated', { sessionId, name: result.name })\n }\n })\n .catch((error) => {\n logger.warn('Session name generation failed', { sessionId, error: error instanceof Error ? error.message : error })\n // Don't propagate error - name generation is optional\n })\n }\n \n // Mark session as running (emits running.changed event)\n sessionManager.setRunning(sessionId, true)\n \n // Send user message directly to client (don't rely on EventStore subscription for this)\n sendForSession(sessionId, createChatMessageMessage(userMessage))\n sendForSession(sessionId, createSessionRunningMessage(true))\n \n // Create AbortController for this chat (abort existing if any - defense in depth)\n const controller = new AbortController()\n const existingController = activeAgents.get(sessionId)\n if (existingController) {\n logger.warn('Aborting existing agent before starting new one', { sessionId })\n existingController.abort()\n }\n activeAgents.set(sessionId, controller)\n \n // Acknowledge immediately\n send({ type: 'ack', payload: {}, id: message.id })\n \n // Use NEW orchestrator (events go through EventStore → WS subscription)\n // Completion queue auto-sends next message when turn finishes\n startTurnWithCompletionChain(sessionId, controller)\n \n break\n }\n\n case 'chat.stop': {\n if (!client.activeSessionId) {\n send(createErrorMessage('NO_SESSION', 'No active session', message.id))\n return\n }\n\n abortSessionExecution(client.activeSessionId, 'Session aborted by user')\n\n send({ type: 'ack', payload: {}, id: message.id })\n break\n }\n\n // =========================================================================\n // Message Queue\n // =========================================================================\n\n case 'queue.asap': {\n if (!client.activeSessionId) {\n send(createErrorMessage('NO_SESSION', 'No active session', message.id))\n return\n }\n if (!isQueueAsapPayload(message.payload)) {\n send(createErrorMessage('INVALID_PAYLOAD', 'Invalid queue.asap payload', message.id))\n return\n }\n const { content, attachments } = message.payload\n sessionManager.queueMessage(client.activeSessionId, 'asap', content, attachments)\n sendForSession(client.activeSessionId, createQueueStateMessage(sessionManager.getQueueState(client.activeSessionId)))\n send({ type: 'ack', payload: {}, id: message.id })\n break\n }\n\n case 'queue.completion': {\n if (!client.activeSessionId) {\n send(createErrorMessage('NO_SESSION', 'No active session', message.id))\n return\n }\n if (!isQueueCompletionPayload(message.payload)) {\n send(createErrorMessage('INVALID_PAYLOAD', 'Invalid queue.completion payload', message.id))\n return\n }\n const { content, attachments } = message.payload\n sessionManager.queueMessage(client.activeSessionId, 'completion', content, attachments)\n sendForSession(client.activeSessionId, createQueueStateMessage(sessionManager.getQueueState(client.activeSessionId)))\n send({ type: 'ack', payload: {}, id: message.id })\n break\n }\n\n case 'queue.cancel': {\n if (!client.activeSessionId) {\n send(createErrorMessage('NO_SESSION', 'No active session', message.id))\n return\n }\n if (!isQueueCancelPayload(message.payload)) {\n send(createErrorMessage('INVALID_PAYLOAD', 'Invalid queue.cancel payload', message.id))\n return\n }\n sessionManager.cancelQueuedMessage(client.activeSessionId, message.payload.queueId)\n sendForSession(client.activeSessionId, createQueueStateMessage(sessionManager.getQueueState(client.activeSessionId)))\n send({ type: 'ack', payload: {}, id: message.id })\n break\n }\n\n case 'chat.continue': {\n if (!client.activeSessionId) {\n send(createErrorMessage('NO_SESSION', 'No active session', message.id))\n return\n }\n\n const session = sessionManager.requireSession(client.activeSessionId)\n if (session.isRunning) {\n send(createErrorMessage('ALREADY_RUNNING', 'Session is already running', message.id))\n return\n }\n\n const continueEventStore = getEventStore()\n const events = continueEventStore.getEvents(session.id)\n const messages = buildMessagesFromStoredEvents(events)\n const lastAssistantMessage = [...messages].reverse().find(msg => msg.role === 'assistant')\n const fallbackMessageId = lastAssistantMessage?.id ?? [...messages].reverse().find(msg => msg.role === 'user')?.id ?? crypto.randomUUID()\n\n send({ type: 'ack', payload: {}, id: message.id })\n sendForSession(session.id, createChatDoneMessage(fallbackMessageId, 'complete', lastAssistantMessage?.stats))\n break\n }\n \n // =========================================================================\n // Mode Switching\n // =========================================================================\n \n case 'mode.switch': {\n if (!client.activeSessionId) {\n send(createErrorMessage('NO_SESSION', 'No active session', message.id))\n return\n }\n \n if (!isModeSwitchPayload(message.payload)) {\n send(createErrorMessage('INVALID_PAYLOAD', 'Invalid mode.switch payload', message.id))\n return\n }\n\n // Validate that the target agent exists and is a top-level agent\n const allAgents = await loadAllAgentsDefault()\n const targetAgent = findAgentById(message.payload.mode, allAgents)\n if (!targetAgent || targetAgent.metadata.subagent) {\n send(createErrorMessage('INVALID_AGENT', `Agent '${message.payload.mode}' not found or is a sub-agent`, message.id))\n return\n }\n\n const sessionId = client.activeSessionId\n const session = sessionManager.requireSession(sessionId)\n const eventStore = getEventStore()\n \n // Trigger summary generation when switching to builder mode for the first time\n // Only if there are actual conversation messages to summarize\n if (message.payload.mode === 'builder' && needsSummaryGeneration(session.summary)) {\n const events = eventStore.getEvents(sessionId)\n \n // Filter out system-generated messages (like \"Waiting for user input...\")\n const nonSystemEvents = events.filter(event => {\n if (event.type !== 'message.start') return true\n return (event.data as any).isSystemGenerated !== true\n })\n \n const contextMessages = buildContextMessagesFromEventHistory(nonSystemEvents)\n const summaryMessages = contextMessages.filter(m => m.role === 'user' || m.role === 'assistant')\n .map(m => ({ role: m.role as 'user' | 'assistant', content: m.content }))\n \n // Only generate summary if there are conversation messages\n if (summaryMessages.length > 0) {\n generateSessionSummary({\n messages: summaryMessages,\n llmClient: llmForSession(sessionId),\n })\n .then(async (result) => {\n if (result.success && result.summary) {\n // Update DB with the generated summary\n sessionManager.setSummary(sessionId, result.summary)\n\n // Broadcast updated session state to all WebSocket clients\n const updatedSession = sessionManager.getSession(sessionId)\n if (updatedSession) {\n const events = eventStore.getEvents(sessionId)\n const messages = buildMessagesFromStoredEvents(events)\n broadcastForSession(sessionId, createSessionStateMessage(updatedSession, messages))\n }\n \n logger.info('Session summary generated', { sessionId, summaryLength: result.summary.length })\n }\n })\n .catch((error) => {\n logger.warn('Session summary generation failed', { sessionId, error: error instanceof Error ? error.message : error })\n // Don't propagate error - summary generation is optional\n })\n }\n }\n \n sessionManager.setMode(sessionId, message.payload.mode)\n sendForSession(sessionId, createModeChangedMessage(message.payload.mode, false))\n const modeEvents = eventStore.getEvents(sessionId)\n const modeMessages = buildMessagesFromStoredEvents(modeEvents)\n sendForSession(sessionId, createSessionStateMessage(sessionManager.getSession(sessionId)!, modeMessages, message.id))\n break\n }\n \n case 'mode.accept': {\n if (!client.activeSessionId) {\n send(createErrorMessage('NO_SESSION', 'No active session', message.id))\n return\n }\n \n const session = sessionManager.requireSession(client.activeSessionId)\n \n // Check if session is already running - reject concurrent execution\n if (session.isRunning) {\n send(createErrorMessage('ALREADY_RUNNING', 'Session is already running', message.id))\n return\n }\n \n if (session.criteria.length === 0) {\n send(createErrorMessage('NO_CRITERIA', 'Cannot accept: no criteria defined', message.id))\n return\n }\n \n const sessionId = client.activeSessionId\n const eventStore = getEventStore()\n \n // Acknowledge immediately\n send({ type: 'ack', payload: {}, id: message.id })\n \n // Ensure client is subscribed to EventStore (tab model - additive)\n if (!client.eventStoreSubscriptions.has(sessionId)) {\n const sid = sessionId\n const { iterator, unsubscribe } = eventStore.subscribe(sid)\n client.eventStoreSubscriptions.set(sessionId, unsubscribe)\n \n ;(async () => {\n try {\n for await (const storedEvent of iterator) {\n const serverMsg = storedEventToServerMessage(storedEvent)\n if (serverMsg && ws.readyState === WebSocket.OPEN) {\n ws.send(serializeServerMessage({ ...serverMsg, seq: storedEvent.seq, sessionId: sid }))\n }\n }\n } catch (error) {\n logger.debug('EventStore subscription ended', { sessionId: sid, error })\n }\n })()\n }\n \n // Mark session as running\n sessionManager.setRunning(sessionId, true)\n eventStore.append(sessionId, { type: 'running.changed', data: { isRunning: true } })\n sendForSession(sessionId, createSessionRunningMessage(true))\n \n // Generate summary if needed (summary generation on first entry to builder mode)\n // Only if there are actual conversation messages to summarize\n const currentSession = sessionManager.requireSession(sessionId)\n if (needsSummaryGeneration(currentSession.summary)) {\n const events = eventStore.getEvents(sessionId)\n \n // Filter out system-generated messages (like \"Waiting for user input...\")\n const nonSystemEvents = events.filter(event => {\n if (event.type !== 'message.start') return true\n return (event.data as any).isSystemGenerated !== true\n })\n \n const contextMessages = buildContextMessagesFromEventHistory(nonSystemEvents)\n const summaryMessages = contextMessages.filter(m => m.role === 'user' || m.role === 'assistant')\n .map(m => ({ role: m.role as 'user' | 'assistant', content: m.content }))\n \n // Only generate summary if there are conversation messages\n if (summaryMessages.length > 0) {\n generateSessionSummary({\n messages: summaryMessages,\n llmClient: llmForSession(sessionId),\n })\n .then(async (result) => {\n if (result.success && result.summary) {\n // Update DB with the generated summary\n sessionManager.setSummary(sessionId, result.summary)\n }\n })\n .catch((error) => {\n logger.warn('Session summary generation failed', { sessionId, error: error instanceof Error ? error.message : error })\n })\n }\n }\n\n // Start builder asynchronously (summary already generated on mode.switch if needed)\n ;(async () => {\n let controller: AbortController | null = null\n try {\n // Switch to builder mode and phase\n sessionManager.setMode(sessionId, 'builder')\n sessionManager.setPhase(sessionId, 'build')\n eventStore.append(sessionId, { type: 'mode.changed', data: { mode: 'builder', auto: false, reason: 'Criteria accepted' } })\n eventStore.append(sessionId, { type: 'phase.changed', data: { phase: 'build' } })\n\n // Create AbortController for builder (abort existing if any - defense in depth)\n controller = new AbortController()\n const existingController = activeAgents.get(sessionId)\n if (existingController) {\n logger.warn('Aborting existing agent before starting new one', { sessionId })\n existingController.abort()\n }\n activeAgents.set(sessionId, controller)\n\n // Auto-start orchestrator (full state machine with verification)\n const acceptPayload = message.payload as { workflowId?: string } | undefined\n await runOrchestrator({\n sessionManager,\n sessionId,\n llmClient: llmForSession(sessionId),\n statsIdentity: statsForSession(sessionId),\n injectBuilderKickoff: true,\n ...(acceptPayload?.workflowId ? { workflowId: acceptPayload.workflowId } : {}),\n signal: controller.signal,\n onMessage: (msg) => sendForSession(sessionId, msg), // For path confirmation dialogs\n })\n } catch (error) {\n if (error instanceof Error && error.message === 'Aborted') {\n return\n }\n logger.error('mode.accept error', { error })\n // Emit error event\n eventStore.append(sessionId, {\n type: 'chat.error',\n data: {\n error: error instanceof Error ? error.message : 'Unknown error',\n recoverable: false,\n },\n })\n const errorMsgId = crypto.randomUUID()\n eventStore.append(sessionId, createMessageStartEvent(errorMsgId, 'user', `Error: ${error instanceof Error ? error.message : 'Unknown error'}`, {\n ...(getCurrentWindowMessageOptions(sessionId) ?? {}),\n isSystemGenerated: true,\n messageKind: 'correction',\n }))\n eventStore.append(sessionId, { type: 'message.done', data: { messageId: errorMsgId } })\n eventStore.append(sessionId, createChatDoneEvent(errorMsgId, 'error'))\n } finally {\n if (!controller || activeAgents.get(sessionId) !== controller) {\n return\n }\n activeAgents.delete(sessionId)\n\n // Check completion queue before going idle\n const completionMsgs = sessionManager.drainCompletionMessages(sessionId)\n const nextCompletion = completionMsgs[0]\n if (nextCompletion) {\n for (const remaining of completionMsgs.slice(1)) {\n sessionManager.queueMessage(sessionId, 'completion', remaining.content, remaining.attachments)\n }\n sendForSession(sessionId, createQueueStateMessage(sessionManager.getQueueState(sessionId)))\n const userMessage = sessionManager.addMessage(sessionId, {\n role: 'user',\n content: nextCompletion.content,\n ...(nextCompletion.attachments ? { attachments: nextCompletion.attachments } : {}),\n })\n sendForSession(sessionId, createChatMessageMessage(userMessage))\n const newController = new AbortController()\n activeAgents.set(sessionId, newController)\n startTurnWithCompletionChain(sessionId, newController)\n return\n }\n\n sessionManager.clearMessageQueue(sessionId)\n sessionManager.setRunning(sessionId, false)\n eventStore.append(sessionId, { type: 'running.changed', data: { isRunning: false } })\n const contextState = sessionManager.getContextState(sessionId)\n sendForSession(sessionId, createContextStateMessage(contextState))\n }\n })()\n \n break\n }\n \n // =========================================================================\n // Criteria Editing\n // =========================================================================\n \n case 'criteria.edit': {\n if (!client.activeSessionId) {\n send(createErrorMessage('NO_SESSION', 'No active session', message.id))\n return\n }\n \n if (!isCriteriaEditPayload(message.payload)) {\n send(createErrorMessage('INVALID_PAYLOAD', 'Invalid criteria.edit payload', message.id))\n return\n }\n \n sessionManager.setCriteria(client.activeSessionId, message.payload.criteria)\n sendForSession(client.activeSessionId, createCriteriaUpdatedMessage(message.payload.criteria))\n send({ type: 'ack', payload: {}, id: message.id })\n break\n }\n \n // =========================================================================\n // Context Management\n // =========================================================================\n \n case 'context.compact': {\n if (!client.activeSessionId) {\n send(createErrorMessage('NO_SESSION', 'No active session', message.id))\n return\n }\n \n const session = sessionManager.requireSession(client.activeSessionId)\n const sessionId = client.activeSessionId\n \n // Check if session is running\n if (session.isRunning) {\n send(createErrorMessage('SESSION_RUNNING', 'Cannot compact while session is running', message.id))\n return\n }\n \n const contextState = sessionManager.getContextState(sessionId)\n const tokensBefore = contextState.currentTokens\n const eventStore = getEventStore()\n \n // Acknowledge immediately\n send({ type: 'ack', payload: {}, id: message.id })\n \n // Perform compaction asynchronously\n ;(async () => {\n try {\n await performManualContextCompaction({\n sessionManager,\n sessionId,\n llmClient: llmForSession(sessionId),\n statsIdentity: statsForSession(sessionId),\n tokenCountAtClose: tokensBefore,\n })\n \n // Send updated context state\n const newContextState = sessionManager.getContextState(sessionId)\n sendForSession(sessionId, createContextStateMessage(newContextState))\n \n // Send updated session state so client sees all messages\n const updatedSession = sessionManager.requireSession(sessionId)\n const compactEventStore = getEventStore()\n const compactEvents = compactEventStore.getEvents(sessionId)\n const compactMessages = buildMessagesFromStoredEvents(compactEvents)\n sendForSession(sessionId, createSessionStateMessage(updatedSession, compactMessages))\n } catch (error) {\n logger.error('Compaction failed', { error, sessionId })\n sendForSession(sessionId, createChatErrorMessage(\n `Compaction failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n true\n ))\n }\n })()\n \n break\n }\n \n // =========================================================================\n // Runner (Auto-Loop)\n // =========================================================================\n \n case 'runner.launch': {\n if (!client.activeSessionId) {\n send(createErrorMessage('NO_SESSION', 'No active session', message.id))\n return\n }\n \n const session = sessionManager.requireSession(client.activeSessionId)\n \n // Check if session is already running - reject concurrent execution\n if (session.isRunning) {\n send(createErrorMessage('ALREADY_RUNNING', 'Session is already running', message.id))\n return\n }\n \n // Only allow launching from builder mode\n if (session.mode !== 'builder') {\n send(createErrorMessage('INVALID_MODE', 'Runner can only be launched in builder mode', message.id))\n return\n }\n \n // Check if there are pending criteria\n const pendingCriteria = session.criteria.filter(c => c.status.type !== 'passed')\n if (pendingCriteria.length === 0) {\n send(createErrorMessage('NO_WORK', 'No pending criteria to work on', message.id))\n return\n }\n \n const sessionId = client.activeSessionId\n const eventStore = getEventStore()\n\n // Check if session is blocked - user intervention resets it\n if (session.phase === 'blocked') {\n logger.info('User launched runner - resetting blocked state', { sessionId })\n // setPhase emits phase.changed event\n sessionManager.setPhase(sessionId, 'build')\n sessionManager.resetAllCriteriaAttempts(sessionId)\n }\n\n // If the user included a message with the launch, add it as a user message\n const launchPayload = message.payload as { content?: string; attachments?: unknown[]; workflowId?: string } | undefined\n const hasUserMessage = launchPayload?.content && typeof launchPayload.content === 'string' && launchPayload.content.trim()\n if (hasUserMessage) {\n const attachments = launchPayload.attachments as Attachment[] | undefined\n sessionManager.addMessage(sessionId, {\n role: 'user',\n content: launchPayload.content!,\n ...(attachments ? { attachments } : {}),\n })\n }\n\n // Mark session as running (emits running.changed event)\n sessionManager.setRunning(sessionId, true)\n sendForSession(sessionId, createSessionRunningMessage(true))\n\n // Create AbortController for this run (abort existing if any - defense in depth)\n const controller = new AbortController()\n const existingController = activeAgents.get(sessionId)\n if (existingController) {\n logger.warn('Aborting existing agent before starting new one', { sessionId })\n existingController.abort()\n }\n activeAgents.set(sessionId, controller)\n\n // Acknowledge immediately\n send({ type: 'ack', payload: {}, id: message.id })\n\n // Ensure client is subscribed to EventStore (tab model - additive)\n ensureEventStoreSubscription(sessionId)\n\n // Run orchestrator asynchronously\n logger.info('Runner launching', { sessionId, pendingCriteria: pendingCriteria.length })\n\n runOrchestrator({\n sessionManager,\n sessionId,\n llmClient: llmForSession(sessionId),\n statsIdentity: statsForSession(sessionId),\n injectBuilderKickoff: !hasUserMessage,\n ...(launchPayload?.workflowId ? { workflowId: launchPayload.workflowId } : {}),\n signal: controller.signal,\n onMessage: (msg) => sendForSession(sessionId, msg), // For path confirmation dialogs\n }).catch((error) => {\n // Don't create error message for controlled abort\n if (error instanceof Error && error.message === 'Aborted') {\n return\n }\n logger.error('Runner error', { error, sessionId })\n // Error events are handled inside runOrchestrator and appended to EventStore\n }).finally(() => {\n if (activeAgents.get(sessionId) !== controller) {\n return\n }\n activeAgents.delete(sessionId)\n\n // Check completion queue before going idle\n const completionMsgs = sessionManager.drainCompletionMessages(sessionId)\n const nextCompletion = completionMsgs[0]\n if (nextCompletion) {\n for (const remaining of completionMsgs.slice(1)) {\n sessionManager.queueMessage(sessionId, 'completion', remaining.content, remaining.attachments)\n }\n sendForSession(sessionId, createQueueStateMessage(sessionManager.getQueueState(sessionId)))\n const userMessage = sessionManager.addMessage(sessionId, {\n role: 'user',\n content: nextCompletion.content,\n ...(nextCompletion.attachments ? { attachments: nextCompletion.attachments } : {}),\n })\n sendForSession(sessionId, createChatMessageMessage(userMessage))\n const newController = new AbortController()\n activeAgents.set(sessionId, newController)\n startTurnWithCompletionChain(sessionId, newController)\n return\n }\n\n sessionManager.clearMessageQueue(sessionId)\n sessionManager.setRunning(sessionId, false)\n })\n \n break\n }\n \n // =========================================================================\n // Path Confirmation\n // =========================================================================\n \n case 'path.confirm': {\n if (!client.activeSessionId) {\n send(createErrorMessage('NO_SESSION', 'No active session', message.id))\n return\n }\n \n if (!isPathConfirmPayload(message.payload)) {\n send(createErrorMessage('INVALID_PAYLOAD', 'Invalid path.confirm payload', message.id))\n return\n }\n \n const { callId, approved } = message.payload\n const result = providePathConfirmation(callId, approved)\n \n if (!result.found) {\n send(createErrorMessage('NOT_FOUND', 'No pending path confirmation with that ID', message.id))\n return\n }\n \n logger.debug('Path confirmation response', { \n sessionId: client.activeSessionId, \n callId, \n approved \n })\n \n // Just acknowledge - the Promise resolution will resume tool execution automatically.\n // If approved: paths were added to allowlist, tool continues.\n // If denied: requestPathAccess throws PathAccessDeniedError, handled by existing error catch.\n send({ type: 'ack', payload: {}, id: message.id })\n break\n }\n \n default: {\n send(createErrorMessage('UNKNOWN_MESSAGE', `Unknown message type: ${message.type}`, message.id))\n }\n }\n}\n","/**\n * Verifier Helpers\n *\n * Nudge/stall logic for the verifier sub-agent.\n */\n\nimport type { Criterion } from '../../shared/types.js'\nimport type { NudgeConfig } from './manager.js'\n\nexport const MAX_CONSECUTIVE_VERIFIER_NUDGES = 10\nexport const VERIFIER_STALL_REASON = 'Verifier stopped repeatedly before terminalizing verification after repeated nudges.'\n\nexport function getCriteriaAwaitingVerification(criteria: Criterion[]): Criterion[] {\n return criteria.filter((criterion) => criterion.status.type === 'completed')\n}\n\nexport function buildVerifierNudgeContent(criteria: Criterion[]): string {\n const ids = criteria.map((criterion) => criterion.id).join(', ')\n return `You stopped before finalizing verification. ${criteria.length} criteria still need a terminal verification result. Use pass_criterion or fail_criterion for each remaining criterion: ${ids}.`\n}\n\nexport function buildVerifierRestartContent(criteria: Criterion[]): string {\n const ids = criteria.map((criterion) => criterion.id).join(', ')\n return `${VERIFIER_STALL_REASON} Leaving remaining criteria unchanged so verification can restart in a fresh window: ${ids}.`\n}\n\nexport function createVerifierNudgeConfig(): NudgeConfig {\n return {\n maxConsecutiveNudges: MAX_CONSECUTIVE_VERIFIER_NUDGES,\n getCriteriaAwaiting: getCriteriaAwaitingVerification,\n buildNudgeContent: buildVerifierNudgeContent,\n buildRestartContent: buildVerifierRestartContent,\n }\n}\n","/**\n * Chat Orchestrator\n *\n * Orchestrates chat turns by:\n * 1. Consuming pure generators that yield TurnEvents\n * 2. Appending events to EventStore\n * 3. Executing tools and yielding tool events\n * 4. Creating snapshots at end of turn\n *\n * This is the ONE place where events get appended to the store.\n */\n\nimport type { MessageStats, StatsIdentity, ToolCall, ToolResult } from '../../shared/types.js'\nimport type { ServerMessage } from '../../shared/protocol.js'\nimport type { LLMClientWithModel } from '../llm/client.js'\nimport type { SessionSnapshot } from '../events/types.js'\nimport { getEventStore, getCurrentContextWindowId } from '../events/index.js'\nimport { buildSnapshotFromSessionState } from '../events/folding.js'\nimport type { SessionManager } from '../session/index.js'\nimport { getToolRegistryForAgent, AskUserInterrupt, PathAccessDeniedError } from '../tools/index.js'\nimport { BUILDER_KICKOFF_PROMPT, VERIFIER_KICKOFF_PROMPT } from './prompts.js'\nimport { TurnMetrics, createMessageStartEvent, createMessageDoneEvent, createToolCallEvent, createToolResultEvent, createChatDoneEvent } from './stream-pure.js'\nimport { assembleAgentRequest } from './request-context.js'\nimport { runTopLevelAgentLoop } from './agent-loop.js'\nimport { executeSubAgent } from '../sub-agents/manager.js'\nimport { createVerifierNudgeConfig } from '../sub-agents/verifier-helpers.js'\nimport { loadAllAgentsDefault, findAgentById, getSubAgents } from '../agents/registry.js'\nimport { logger } from '../utils/logger.js'\n\n// Re-export for runner orchestrator\nexport { TurnMetrics, createMessageStartEvent, createMessageDoneEvent, createToolCallEvent, createToolResultEvent, createChatDoneEvent }\n\nfunction getCurrentWindowMessageOptions(sessionId: string): { contextWindowId: string } | undefined {\n const contextWindowId = getCurrentContextWindowId(sessionId)\n return contextWindowId ? { contextWindowId } : undefined\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface OrchestratorOptions {\n sessionManager: SessionManager\n sessionId: string\n llmClient: LLMClientWithModel\n statsIdentity?: StatsIdentity\n signal?: AbortSignal\n injectBuilderKickoff?: boolean\n /** Optional callback for WebSocket forwarding (temporary, until WS layer is refactored) */\n onMessage?: (msg: ServerMessage) => void\n}\n\nfunction resolveStatsIdentity(options: OrchestratorOptions): StatsIdentity {\n const model = options.llmClient.getModel()\n\n if (options.statsIdentity) {\n return {\n ...options.statsIdentity,\n model,\n }\n }\n\n return {\n providerId: `provider:${model}`,\n providerName: 'Unknown Provider',\n backend: 'unknown',\n model,\n }\n}\n\n// ============================================================================\n// Core Orchestrator\n// ============================================================================\n\n/**\n * Run a chat turn in the current mode.\n * Appends all events to EventStore and creates a snapshot at end of turn.\n */\nexport async function runChatTurn(options: OrchestratorOptions): Promise<void> {\n const { sessionManager, sessionId } = options\n const eventStore = getEventStore()\n const statsIdentity = resolveStatsIdentity(options)\n\n const session = sessionManager.requireSession(sessionId)\n const mode = session.mode\n\n logger.debug('Starting chat turn', { sessionId, mode })\n\n // Track metrics across the turn\n const turnMetrics = new TurnMetrics()\n\n try {\n // Run the appropriate handler based on mode (agent ID)\n if (mode === 'builder') {\n await runBuilderTurn(options, turnMetrics)\n } else {\n await runGenericAgentTurn(options, turnMetrics, mode)\n }\n\n // Create end-of-turn snapshot\n const snapshot = buildSnapshot(sessionManager, sessionId, turnMetrics.buildStats(statsIdentity, mode))\n const snapshotEvent = eventStore.append(sessionId, { type: 'turn.snapshot', data: snapshot })\n\n const deletedCount = eventStore.cleanupOldEvents(sessionId)\n if (deletedCount > 0) {\n logger.debug('Cleaned up old events after snapshot', { sessionId, deletedCount, snapshotSeq: snapshotEvent.seq })\n }\n\n } catch (error) {\n if (error instanceof AskUserInterrupt) {\n const waitMsgId = crypto.randomUUID()\n eventStore.append(sessionId, createMessageStartEvent(waitMsgId, 'user', 'Waiting for user input...', {\n ...(getCurrentWindowMessageOptions(sessionId) ?? {}),\n isSystemGenerated: true,\n messageKind: 'auto-prompt',\n }))\n eventStore.append(sessionId, createChatDoneEvent(waitMsgId, 'waiting_for_user'))\n return\n }\n\n if (error instanceof PathAccessDeniedError) {\n const errorMsgId = crypto.randomUUID()\n const reasonText = error.reason === 'sensitive_file'\n ? 'sensitive files that may contain secrets'\n : error.reason === 'both'\n ? 'files outside the project and sensitive files'\n : 'files outside the project directory'\n eventStore.append(sessionId, {\n type: 'chat.error',\n data: {\n error: `User denied access to ${reasonText}.`,\n recoverable: false,\n },\n })\n eventStore.append(sessionId, createMessageStartEvent(errorMsgId, 'user', `Access denied: ${error.paths.join(', ')}. If you need this file, explain why and ask the user for permission.`, {\n ...(getCurrentWindowMessageOptions(sessionId) ?? {}),\n isSystemGenerated: true,\n messageKind: 'correction',\n }))\n eventStore.append(sessionId, createChatDoneEvent(errorMsgId, 'error'))\n return\n }\n\n if (error instanceof Error && error.message === 'Aborted') {\n return\n }\n\n logger.error('Chat turn error', { sessionId, mode, error })\n const errorMsgId = crypto.randomUUID()\n eventStore.append(sessionId, {\n type: 'chat.error',\n data: {\n error: error instanceof Error ? error.message : 'Unknown error',\n recoverable: false,\n },\n })\n eventStore.append(sessionId, createMessageStartEvent(errorMsgId, 'user', `Error: ${error instanceof Error ? error.message : 'Unknown error'}`, {\n ...(getCurrentWindowMessageOptions(sessionId) ?? {}),\n isSystemGenerated: true,\n messageKind: 'correction',\n }))\n eventStore.append(sessionId, createChatDoneEvent(errorMsgId, 'error'))\n } finally {\n eventStore.append(sessionId, { type: 'running.changed', data: { isRunning: false } })\n }\n}\n\n// ============================================================================\n// Generic Agent Turn (works for planner, custom agents, etc.)\n// ============================================================================\n\nasync function runGenericAgentTurn(\n options: OrchestratorOptions,\n turnMetrics: TurnMetrics,\n agentId: string,\n): Promise<void> {\n const statsIdentity = resolveStatsIdentity(options)\n const allAgents = await loadAllAgentsDefault()\n const agentDef = findAgentById(agentId, allAgents) ?? findAgentById('planner', allAgents)!\n const subAgentDefs = getSubAgents(allAgents)\n\n await runTopLevelAgentLoop({\n mode: agentId,\n sessionManager: options.sessionManager,\n sessionId: options.sessionId,\n llmClient: options.llmClient,\n statsIdentity,\n signal: options.signal,\n onMessage: options.onMessage,\n assembleRequest: (input) => assembleAgentRequest({ ...input, agentDef, subAgentDefs }),\n getToolRegistry: () => getToolRegistryForAgent(agentDef),\n }, turnMetrics)\n}\n\n// ============================================================================\n// Builder Turn\n// ============================================================================\n\nexport async function runBuilderTurn(\n options: OrchestratorOptions,\n turnMetrics: TurnMetrics,\n): Promise<void> {\n const { sessionManager, sessionId } = options\n const statsIdentity = resolveStatsIdentity(options)\n const eventStore = getEventStore()\n const allAgents = await loadAllAgentsDefault()\n const builderDef = findAgentById('builder', allAgents)!\n const subAgentDefs = getSubAgents(allAgents)\n\n await runTopLevelAgentLoop({\n mode: 'builder',\n sessionManager,\n sessionId,\n llmClient: options.llmClient,\n statsIdentity,\n signal: options.signal,\n onMessage: options.onMessage,\n assembleRequest: (input) => assembleAgentRequest({ ...input, agentDef: builderDef, subAgentDefs }),\n getToolRegistry: () => getToolRegistryForAgent(builderDef),\n onToolExecuted: (toolCall: ToolCall, toolResult: ToolResult) => {\n if (toolResult.success && ['write_file', 'edit_file'].includes(toolCall.name)) {\n const path = toolCall.arguments['path'] as string\n sessionManager.addModifiedFile(sessionId, path)\n }\n },\n injectKickoff: () => {\n if (options.injectBuilderKickoff !== true) return\n const session = sessionManager.requireSession(sessionId)\n const events = eventStore.getEvents(sessionId)\n const hasBuilderKickoff = events.some(e => {\n if (e.type !== 'message.start') return false\n const data = e.data as { messageKind?: string; content?: string }\n return data.messageKind === 'auto-prompt' && data.content?.includes('fulfil the')\n })\n\n if (!hasBuilderKickoff) {\n const kickoffMsgId = crypto.randomUUID()\n const kickoffContent = BUILDER_KICKOFF_PROMPT(session.criteria.length)\n eventStore.append(sessionId, createMessageStartEvent(kickoffMsgId, 'user', kickoffContent, {\n ...(getCurrentWindowMessageOptions(sessionId) ?? {}),\n isSystemGenerated: true,\n messageKind: 'auto-prompt',\n }))\n eventStore.append(sessionId, { type: 'message.done', data: { messageId: kickoffMsgId } })\n }\n },\n }, turnMetrics)\n}\n\n// ============================================================================\n// Verifier Turn (Fresh Context)\n// ============================================================================\n\nexport interface VerifierResult {\n allPassed: boolean\n failed: Array<{ id: string; reason: string }>\n content?: string\n}\n\n/**\n * Run a verifier turn with fresh context.\n * Delegates to SubAgentManager for execution.\n */\nexport async function runVerifierTurn(\n options: OrchestratorOptions,\n turnMetrics: TurnMetrics\n): Promise<VerifierResult> {\n const { sessionManager, sessionId, llmClient, signal, onMessage } = options\n const statsIdentity = resolveStatsIdentity(options)\n\n const session = sessionManager.requireSession(sessionId)\n const toVerify = session.criteria.filter(c => c.status.type === 'completed')\n if (toVerify.length === 0) {\n logger.debug('Nothing to verify', { sessionId })\n return { allPassed: true, failed: [] }\n }\n\n const allAgents = await loadAllAgentsDefault()\n const verifierDef = findAgentById('verifier', allAgents)!\n const toolRegistry = getToolRegistryForAgent(verifierDef)\n\n const result = await executeSubAgent({\n subAgentType: 'verifier',\n prompt: VERIFIER_KICKOFF_PROMPT,\n sessionManager,\n sessionId,\n llmClient,\n toolRegistry,\n turnMetrics,\n statsIdentity,\n signal,\n onMessage,\n nudgeConfig: createVerifierNudgeConfig(),\n })\n\n return {\n allPassed: result.allPassed ?? true,\n failed: result.failed ?? [],\n content: result.content,\n }\n}\n\n/**\n * Build a snapshot of current session state.\n */\nfunction buildSnapshot(sessionManager: SessionManager, sessionId: string, lastStats?: MessageStats): SessionSnapshot {\n const eventStore = getEventStore()\n const session = sessionManager.requireSession(sessionId)\n const events = eventStore.getEvents(sessionId)\n const latestSeq = eventStore.getLatestSeq(sessionId) ?? 0\n\n return buildSnapshotFromSessionState({\n session,\n events,\n latestSeq,\n })\n}\n","/**\n * Workflow Registry\n *\n * Discovers, loads, and manages workflows from the workflows directory.\n * Workflows are stored as .workflow.json files (plain JSON, not markdown).\n */\n\nimport { readdir, readFile, writeFile, copyFile, mkdir, access, unlink } from 'node:fs/promises'\nimport { join, dirname } from 'node:path'\nimport { constants } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport type { WorkflowDefinition } from './types.js'\nimport { logger } from '../utils/logger.js'\n\nconst __bundleDir = dirname(fileURLToPath(import.meta.url))\nconst DEFAULTS_DIR = join(__bundleDir, 'defaults')\nconst DEFAULTS_DIR_ALT = join(__bundleDir, 'workflow-defaults')\nconst WORKFLOW_EXTENSION = '.workflow.json'\n\n// ============================================================================\n// Directory Helpers\n// ============================================================================\n\nfunction getWorkflowsDir(configDir: string): string {\n return join(configDir, 'workflows')\n}\n\nasync function pathExists(path: string): Promise<boolean> {\n try {\n await access(path, constants.R_OK)\n return true\n } catch {\n return false\n }\n}\n\n// ============================================================================\n// Default Workflows Installation\n// ============================================================================\n\n/**\n * Copy bundled default workflows to the config workflows directory if they don't already exist.\n */\nexport async function ensureDefaultWorkflows(configDir: string): Promise<void> {\n const workflowsDir = getWorkflowsDir(configDir)\n\n if (!await pathExists(workflowsDir)) {\n await mkdir(workflowsDir, { recursive: true })\n }\n\n // Find bundled defaults (try dev path first, then production path)\n let defaultFiles: string[]\n let sourceDir: string\n try {\n defaultFiles = (await readdir(DEFAULTS_DIR)).filter(f => f.endsWith(WORKFLOW_EXTENSION))\n sourceDir = DEFAULTS_DIR\n } catch {\n try {\n defaultFiles = (await readdir(DEFAULTS_DIR_ALT)).filter(f => f.endsWith(WORKFLOW_EXTENSION))\n sourceDir = DEFAULTS_DIR_ALT\n } catch {\n logger.warn('No bundled workflow defaults found', { dir: DEFAULTS_DIR })\n return\n }\n }\n\n for (const file of defaultFiles) {\n const targetPath = join(workflowsDir, file)\n try {\n await copyFile(join(sourceDir, file), targetPath)\n } catch (err) {\n logger.error('Failed to copy default workflow', { file, error: err instanceof Error ? err.message : String(err) })\n }\n }\n}\n\n// ============================================================================\n// Workflow Loading\n// ============================================================================\n\n/**\n * Load all workflows from the workflows directory.\n */\nexport async function loadAllWorkflows(configDir: string): Promise<WorkflowDefinition[]> {\n const workflowsDir = getWorkflowsDir(configDir)\n\n if (!await pathExists(workflowsDir)) {\n return []\n }\n\n let files: string[]\n try {\n files = (await readdir(workflowsDir)).filter(f => f.endsWith(WORKFLOW_EXTENSION))\n } catch {\n return []\n }\n\n const workflows: WorkflowDefinition[] = []\n for (const file of files) {\n try {\n const raw = await readFile(join(workflowsDir, file), 'utf-8')\n const parsed = JSON.parse(raw) as WorkflowDefinition\n if (parsed.metadata?.id && parsed.steps?.length > 0) {\n workflows.push(parsed)\n } else {\n logger.warn('Skipping invalid workflow file', { file })\n }\n } catch (err) {\n logger.warn('Failed to parse workflow file', { file, error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n return workflows\n}\n\n// ============================================================================\n// Default Restoration\n// ============================================================================\n\n/**\n * Get the list of workflow IDs that have bundled defaults.\n */\nexport async function getDefaultWorkflowIds(): Promise<string[]> {\n for (const dir of [DEFAULTS_DIR, DEFAULTS_DIR_ALT]) {\n try {\n const files = (await readdir(dir)).filter(f => f.endsWith(WORKFLOW_EXTENSION))\n return files.map(f => f.replace(WORKFLOW_EXTENSION, ''))\n } catch { /* try next */ }\n }\n return []\n}\n\n/**\n * Restore a single workflow to its bundled default by re-copying from defaults.\n */\nexport async function restoreDefaultWorkflow(configDir: string, workflowId: string): Promise<boolean> {\n const filename = `${workflowId}${WORKFLOW_EXTENSION}`\n for (const dir of [DEFAULTS_DIR, DEFAULTS_DIR_ALT]) {\n const sourcePath = join(dir, filename)\n if (await pathExists(sourcePath)) {\n const targetPath = join(getWorkflowsDir(configDir), filename)\n await copyFile(sourcePath, targetPath)\n return true\n }\n }\n return false\n}\n\n/**\n * Return the IDs of default workflows whose user copy differs from the bundled version.\n */\nexport async function getModifiedDefaultWorkflowIds(configDir: string): Promise<string[]> {\n const defaultIds = await getDefaultWorkflowIds()\n const modified: string[] = []\n\n for (const id of defaultIds) {\n const filename = `${id}${WORKFLOW_EXTENSION}`\n const userPath = join(getWorkflowsDir(configDir), filename)\n\n let bundledContent: string | null = null\n for (const dir of [DEFAULTS_DIR, DEFAULTS_DIR_ALT]) {\n try {\n bundledContent = await readFile(join(dir, filename), 'utf-8')\n break\n } catch { /* try next */ }\n }\n if (!bundledContent) continue\n\n try {\n const userContent = await readFile(userPath, 'utf-8')\n if (userContent !== bundledContent) {\n modified.push(id)\n }\n } catch {\n // User file doesn't exist\n }\n }\n\n return modified\n}\n\n/**\n * Restore all workflows to their bundled defaults.\n */\nexport async function restoreAllDefaultWorkflows(configDir: string): Promise<number> {\n const ids = await getDefaultWorkflowIds()\n let count = 0\n for (const id of ids) {\n if (await restoreDefaultWorkflow(configDir, id)) count++\n }\n return count\n}\n\n// ============================================================================\n// Workflow Lookup\n// ============================================================================\n\n/**\n * Find a workflow by ID from a list of loaded workflows.\n */\nexport function findWorkflowById(workflowId: string, workflows: WorkflowDefinition[]): WorkflowDefinition | undefined {\n return workflows.find(p => p.metadata.id === workflowId)\n}\n\n// ============================================================================\n// Workflow CRUD\n// ============================================================================\n\n/**\n * Check if a workflow file exists.\n */\nexport async function workflowExists(configDir: string, workflowId: string): Promise<boolean> {\n const filePath = join(getWorkflowsDir(configDir), `${workflowId}${WORKFLOW_EXTENSION}`)\n return pathExists(filePath)\n}\n\n/**\n * Save a workflow definition to disk.\n */\nexport async function saveWorkflow(configDir: string, workflow: WorkflowDefinition): Promise<void> {\n const workflowsDir = getWorkflowsDir(configDir)\n if (!await pathExists(workflowsDir)) {\n await mkdir(workflowsDir, { recursive: true })\n }\n const filePath = join(workflowsDir, `${workflow.metadata.id}${WORKFLOW_EXTENSION}`)\n await writeFile(filePath, JSON.stringify(workflow, null, 2) + '\\n', 'utf-8')\n}\n\n/**\n * Delete a workflow from disk.\n */\nexport async function deleteWorkflow(configDir: string, workflowId: string): Promise<boolean> {\n const filePath = join(getWorkflowsDir(configDir), `${workflowId}${WORKFLOW_EXTENSION}`)\n try {\n await unlink(filePath)\n return true\n } catch {\n return false\n }\n}\n","/**\n * Runner State Machine Types\n * \n * The runner orchestrates the build → verify → done/blocked cycle.\n * State is derived from session criteria, not persisted separately.\n */\n\nimport type { Criterion, MessageStats, StatsIdentity } from '../../shared/types.js'\nimport type { ServerMessage } from '../../shared/protocol.js'\nimport type { LLMClientWithModel } from '../llm/client.js'\nimport type { StreamTiming } from '../llm/streaming.js'\nimport type { SessionManager } from '../session/index.js'\n\n// ============================================================================\n// Decision Types - What the state machine decides to do next\n// ============================================================================\n\nexport type NextAction =\n | { type: 'RUN_BUILDER'; reason: string }\n | { type: 'RUN_VERIFIER'; criteriaToVerify: string[] }\n | { type: 'DONE' }\n | { type: 'BLOCKED'; reason: string; blockedCriteria: string[] }\n\n// ============================================================================\n// Orchestrator Types\n// ============================================================================\n\nexport interface OrchestratorOptions {\n sessionManager: SessionManager\n sessionId: string\n llmClient: LLMClientWithModel\n statsIdentity?: StatsIdentity\n signal?: AbortSignal\n injectBuilderKickoff?: boolean\n /** Override the globally active workflow for this session */\n workflowId?: string\n /** For path confirmation dialogs (sent directly, not through EventStore) */\n onMessage?: (msg: ServerMessage) => void\n}\n\nexport interface OrchestratorResult {\n finalAction: NextAction\n iterations: number\n totalTime: number\n}\n\n// ============================================================================\n// Worker Types - Results from individual build/verify steps\n// ============================================================================\n\nexport interface StepResult {\n messageId: string\n hasToolCalls: boolean\n content: string\n timing: StreamTiming\n usage: { promptTokens: number; completionTokens: number }\n toolTime: number // Total tool execution time in milliseconds\n}\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\nexport const RUNNER_CONFIG = {\n maxVerifyRetries: 4, // Max times to retry a failing criterion\n} as const\n","/**\n * Workflow Configuration Types\n *\n * A workflow defines the orchestrator's step sequence as a state machine.\n * Steps have explicit transitions with conditions — the executor walks\n * the graph until it reaches a terminal state ($done or $blocked).\n */\n\n// ============================================================================\n// Workflow Definition\n// ============================================================================\n\nexport interface WorkflowMetadata {\n id: string\n name: string\n description: string\n version: string\n color?: string\n}\n\nexport interface WorkflowSettings {\n /** Safety limit on total state-machine iterations (default 50) */\n maxIterations: number\n}\n\nexport interface WorkflowDefinition {\n metadata: WorkflowMetadata\n /** ID of the first step to execute */\n entryStep: string\n settings: WorkflowSettings\n /** Ordered for display; execution follows transitions, not array order */\n steps: WorkflowStep[]\n /** Condition that must be met before the workflow starts (default: always) */\n startCondition?: TransitionCondition\n}\n\n// ============================================================================\n// Steps\n// ============================================================================\n\nexport type WorkflowStep = AgentStep | SubAgentStep | ShellStep\n\ninterface StepBase {\n /** Unique within this workflow */\n id: string\n /** Display name */\n name: string\n /** Maps to SessionPhase for UI display (\"build\", \"verification\", etc.) */\n phase: string\n /** Evaluated in order; first match wins */\n transitions: Transition[]\n}\n\n/** Full LLM call + tool execution loop (like the current builder turn) */\nexport interface AgentStep extends StepBase {\n type: 'agent'\n /** Which tool registry to use */\n toolMode: 'builder' | 'planner'\n /** Injected as user message on first entry. Supports template variables. */\n prompt?: string\n /** Injected when re-entering after a failed verify. Supports template variables. */\n nudgePrompt?: string\n}\n\n/** Isolated LLM sub-agent with fresh context */\nexport interface SubAgentStep extends StepBase {\n type: 'sub_agent'\n /** e.g. \"verifier\" or a custom sub-agent type */\n subAgentType: string\n /** Injected as user message on first entry. Supports template variables. */\n prompt?: string\n /** Injected when nudging the sub-agent. Supports template variables. */\n nudgePrompt?: string\n /** Tool set override */\n toolMode?: 'verifier' | 'builder'\n}\n\n/** Run a shell command, branch on exit code */\nexport interface ShellStep extends StepBase {\n type: 'shell'\n /** Shell command to run. Supports template variables: {{workdir}}, etc. */\n command: string\n /** Timeout in milliseconds (default 60000) */\n timeout?: number\n /** Which exit codes count as success (default [0]) */\n successExitCodes?: number[]\n}\n\n// ============================================================================\n// Transitions\n// ============================================================================\n\nexport interface Transition {\n when: TransitionCondition\n /** Step ID, or \"$done\" / \"$blocked\" for terminal states */\n goto: string\n}\n\nexport type TransitionCondition =\n | { type: 'all_criteria_passed' }\n | { type: 'all_criteria_completed_or_passed' }\n | { type: 'any_criteria_blocked' }\n | { type: 'has_pending_criteria' }\n | { type: 'step_result'; result: 'success' | 'failure' }\n | { type: 'always' }\n\n// ============================================================================\n// Terminal state constants\n// ============================================================================\n\nexport const TERMINAL_DONE = '$done'\nexport const TERMINAL_BLOCKED = '$blocked'\n","/**\n * Shell command execution for workflow shell steps.\n */\n\nimport { spawn } from 'node:child_process'\n\nexport interface ShellResult {\n exitCode: number\n stdout: string\n stderr: string\n success: boolean\n}\n\n/**\n * Execute a shell command with timeout and abort support.\n * Returns the exit code, stdout, and stderr.\n */\nexport function executeShellCommand(\n command: string,\n cwd: string,\n timeout: number,\n signal?: AbortSignal,\n): Promise<ShellResult> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new Error('Aborted'))\n return\n }\n\n const proc = spawn('sh', ['-c', command], {\n cwd,\n env: { ...process.env, FORCE_COLOR: '0' },\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n\n let stdout = ''\n let stderr = ''\n let killed = false\n\n const timer = setTimeout(() => {\n killed = true\n proc.kill('SIGTERM')\n resolve({ exitCode: 1, stdout, stderr: stderr + '\\nCommand timed out', success: false })\n }, timeout)\n\n const onAbort = () => {\n if (!killed) {\n killed = true\n proc.kill('SIGTERM')\n clearTimeout(timer)\n reject(new Error('Aborted'))\n }\n }\n signal?.addEventListener('abort', onAbort)\n\n proc.stdout.on('data', (data: Buffer) => { stdout += data.toString() })\n proc.stderr.on('data', (data: Buffer) => { stderr += data.toString() })\n\n proc.on('close', (code) => {\n clearTimeout(timer)\n signal?.removeEventListener('abort', onAbort)\n if (killed) return\n const exitCode = code ?? 1\n resolve({ exitCode, stdout, stderr, success: exitCode === 0 })\n })\n\n proc.on('error', (err) => {\n clearTimeout(timer)\n signal?.removeEventListener('abort', onAbort)\n if (killed) return\n resolve({ exitCode: 1, stdout, stderr: err.message, success: false })\n })\n })\n}\n","/**\n * Workflow Executor\n *\n * Walks a workflow state machine: evaluate current step, execute it,\n * evaluate transitions, move to next step. Repeats until a terminal\n * state ($done or $blocked) is reached.\n */\n\nimport type { Criterion, Session } from '../../shared/types.js'\nimport type { OrchestratorOptions, OrchestratorResult, NextAction } from '../runner/types.js'\nimport { RUNNER_CONFIG } from '../runner/types.js'\nimport type {\n WorkflowDefinition,\n WorkflowStep,\n Transition,\n TransitionCondition,\n AgentStep,\n SubAgentStep,\n ShellStep,\n} from './types.js'\nimport { TERMINAL_DONE, TERMINAL_BLOCKED } from './types.js'\nimport { getEventStore, getCurrentContextWindowId } from '../events/index.js'\nimport { runBuilderTurn, TurnMetrics, createMessageStartEvent } from '../chat/orchestrator.js'\nimport { executeSubAgent } from '../sub-agents/manager.js'\nimport { createVerifierNudgeConfig } from '../sub-agents/verifier-helpers.js'\nimport { loadAllAgentsDefault, findAgentById } from '../agents/registry.js'\nimport { getToolRegistryForAgent } from '../tools/index.js'\nimport { computeSessionStats } from '../../shared/stats.js'\nimport { executeShellCommand } from './shell.js'\nimport { logger } from '../utils/logger.js'\n\n// ============================================================================\n// Template Variables\n// ============================================================================\n\ninterface TemplateContext {\n workdir: string\n reason: string\n verifierFindings: string\n previousStepOutput: string\n criteriaCount: number\n pendingCount: number\n summary: string\n criteriaList: string\n modifiedFiles: string\n}\n\nfunction formatCriteriaList(criteria: Criterion[]): string {\n if (criteria.length === 0) return '(none)'\n return criteria\n .map(c => {\n const status = c.status.type === 'passed' ? '[PASSED]'\n : c.status.type === 'completed' ? '[NEEDS VERIFICATION]'\n : c.status.type === 'failed' ? '[FAILED]'\n : '[NOT COMPLETED]'\n return `- **${c.id}** ${status}: ${c.description}`\n })\n .join('\\n')\n}\n\nfunction formatModifiedFiles(session: Session): string {\n const files = session.executionState?.modifiedFiles ?? []\n return files.length > 0 ? files.map(f => `- ${f}`).join('\\n') : '(none)'\n}\n\nfunction resolveTemplate(template: string, ctx: TemplateContext): string {\n return template\n .replace(/\\{\\{workdir\\}\\}/g, ctx.workdir)\n .replace(/\\{\\{reason\\}\\}/g, ctx.reason)\n .replace(/\\{\\{verifierFindings\\}\\}/g, ctx.verifierFindings)\n .replace(/\\{\\{previousStepOutput\\}\\}/g, ctx.previousStepOutput)\n .replace(/\\{\\{criteriaCount\\}\\}/g, String(ctx.criteriaCount))\n .replace(/\\{\\{pendingCount\\}\\}/g, String(ctx.pendingCount))\n .replace(/\\{\\{summary\\}\\}/g, ctx.summary)\n .replace(/\\{\\{criteriaList\\}\\}/g, ctx.criteriaList)\n .replace(/\\{\\{modifiedFiles\\}\\}/g, ctx.modifiedFiles)\n}\n\n// ============================================================================\n// Transition Evaluation\n// ============================================================================\n\ninterface StepOutcome {\n success: boolean\n}\n\nfunction evaluateCondition(\n condition: TransitionCondition,\n criteria: Criterion[],\n stepOutcome: StepOutcome | null,\n): boolean {\n switch (condition.type) {\n case 'all_criteria_passed':\n return criteria.length === 0 || criteria.every(c => c.status.type === 'passed')\n\n case 'all_criteria_completed_or_passed':\n return criteria.every(c => c.status.type === 'completed' || c.status.type === 'passed')\n\n case 'any_criteria_blocked':\n return criteria.some(c =>\n c.status.type === 'failed' &&\n c.attempts.filter(a => a.status === 'failed').length >= RUNNER_CONFIG.maxVerifyRetries\n )\n\n case 'has_pending_criteria':\n return criteria.some(c => c.status.type !== 'passed')\n\n case 'step_result':\n if (!stepOutcome) return false\n return condition.result === 'success' ? stepOutcome.success : !stepOutcome.success\n\n case 'always':\n return true\n }\n}\n\nfunction evaluateTransitions(\n transitions: Transition[],\n criteria: Criterion[],\n stepOutcome: StepOutcome | null,\n): string {\n for (const transition of transitions) {\n if (evaluateCondition(transition.when, criteria, stepOutcome)) {\n return transition.goto\n }\n }\n // No transition matched — treat as blocked\n return TERMINAL_BLOCKED\n}\n\n// ============================================================================\n// Helper\n// ============================================================================\n\nfunction getCurrentWindowMessageOptions(sessionId: string): { contextWindowId: string } | undefined {\n const contextWindowId = getCurrentContextWindowId(sessionId)\n return contextWindowId ? { contextWindowId } : undefined\n}\n\nfunction buildReason(criteria: Criterion[]): string {\n const remaining = criteria.filter(c => c.status.type !== 'passed')\n return `${remaining.length} criteria remaining`\n}\n\n// ============================================================================\n// Executor\n// ============================================================================\n\nexport async function executeWorkflow(\n workflow: WorkflowDefinition,\n options: OrchestratorOptions,\n): Promise<OrchestratorResult> {\n const { sessionManager, sessionId, llmClient, signal, onMessage } = options\n const eventStore = getEventStore()\n const startTime = performance.now()\n let iterations = 0\n\n let currentStepId = workflow.entryStep\n let lastSubAgentContent = ''\n let lastShellOutput = ''\n let isFirstBuilderEntry = true\n\n // Snapshot message count so we can compute workflow-scoped stats (not session-wide)\n const messagesBeforeWorkflow = sessionManager.requireSession(sessionId).messages.length\n\n const stepsById = new Map<string, WorkflowStep>()\n for (const step of workflow.steps) {\n stepsById.set(step.id, step)\n }\n\n logger.debug('Workflow executor starting', { sessionId, workflow: workflow.metadata.id })\n\n // Evaluate start condition if present\n if (workflow.startCondition && workflow.startCondition.type !== 'always') {\n const session = sessionManager.requireSession(sessionId)\n const criteria = session.criteria\n const conditionMet = evaluateCondition(\n workflow.startCondition as TransitionCondition,\n criteria,\n null,\n )\n if (!conditionMet) {\n logger.debug('Workflow start condition not met', { sessionId, condition: workflow.startCondition.type })\n return {\n finalAction: { type: 'BLOCKED', reason: `Start condition not met: ${workflow.startCondition.type}`, blockedCriteria: [] },\n iterations: 0,\n totalTime: (performance.now() - startTime) / 1000,\n }\n }\n }\n\n // Emit workflow-started marker into the feed\n const startMsgId = crypto.randomUUID()\n const startWindowOpts = getCurrentWindowMessageOptions(sessionId)\n eventStore.append(sessionId, createMessageStartEvent(startMsgId, 'user',\n JSON.stringify({ workflowName: workflow.metadata.name, workflowId: workflow.metadata.id, workflowColor: workflow.metadata.color }),\n { ...(startWindowOpts ?? {}), isSystemGenerated: true, messageKind: 'workflow-started' },\n ))\n eventStore.append(sessionId, { type: 'message.done', data: { messageId: startMsgId } })\n\n while (iterations < workflow.settings.maxIterations) {\n // Check abort\n if (signal?.aborted) {\n logger.debug('Workflow executor aborted', { sessionId, iterations })\n return {\n finalAction: { type: 'RUN_BUILDER', reason: 'Aborted' },\n iterations,\n totalTime: (performance.now() - startTime) / 1000,\n }\n }\n\n iterations++\n\n const step = stepsById.get(currentStepId)\n if (!step) {\n logger.error('Workflow step not found', { sessionId, stepId: currentStepId })\n return {\n finalAction: { type: 'BLOCKED', reason: `Step \"${currentStepId}\" not found in workflow`, blockedCriteria: [] },\n iterations,\n totalTime: (performance.now() - startTime) / 1000,\n }\n }\n\n const session = sessionManager.requireSession(sessionId)\n const currentWindowMessageOptions = getCurrentWindowMessageOptions(sessionId)\n const criteria = session.criteria\n\n // Build template context\n const templateCtx: TemplateContext = {\n workdir: session.workdir,\n reason: buildReason(criteria),\n verifierFindings: lastSubAgentContent,\n previousStepOutput: lastShellOutput,\n criteriaCount: criteria.length,\n pendingCount: criteria.filter(c => c.status.type !== 'passed').length,\n summary: session.summary ?? 'No summary available',\n criteriaList: formatCriteriaList(criteria),\n modifiedFiles: formatModifiedFiles(session),\n }\n\n // Set session phase\n sessionManager.setPhase(sessionId, step.phase as 'build' | 'verification' | 'blocked' | 'done')\n\n logger.debug('Workflow step executing', { sessionId, iteration: iterations, stepId: step.id, stepType: step.type })\n\n let stepOutcome: StepOutcome | null = null\n\n // Execute step\n switch (step.type) {\n case 'agent': {\n const agentStep = step as AgentStep\n\n if (isFirstBuilderEntry && agentStep.prompt) {\n const promptContent = resolveTemplate(agentStep.prompt, templateCtx)\n const promptMsgId = crypto.randomUUID()\n eventStore.append(sessionId, createMessageStartEvent(promptMsgId, 'user', promptContent, {\n ...(currentWindowMessageOptions ?? {}),\n isSystemGenerated: true,\n messageKind: 'auto-prompt',\n }))\n eventStore.append(sessionId, { type: 'message.done', data: { messageId: promptMsgId } })\n } else if (!isFirstBuilderEntry && agentStep.nudgePrompt) {\n const nudgeContent = resolveTemplate(agentStep.nudgePrompt, templateCtx)\n const nudgeMsgId = crypto.randomUUID()\n eventStore.append(sessionId, createMessageStartEvent(nudgeMsgId, 'user', nudgeContent, {\n ...(currentWindowMessageOptions ?? {}),\n isSystemGenerated: true,\n messageKind: 'correction',\n }))\n eventStore.append(sessionId, { type: 'message.done', data: { messageId: nudgeMsgId } })\n }\n\n const turnMetrics = new TurnMetrics()\n await runBuilderTurn({\n sessionManager,\n sessionId,\n llmClient,\n ...(options.statsIdentity ? { statsIdentity: options.statsIdentity } : {}),\n ...(isFirstBuilderEntry && !agentStep.prompt && options.injectBuilderKickoff === true ? { injectBuilderKickoff: true } : {}),\n ...(signal ? { signal } : {}),\n ...(onMessage ? { onMessage } : {}),\n }, turnMetrics)\n\n isFirstBuilderEntry = false\n stepOutcome = { success: true }\n break\n }\n\n case 'sub_agent': {\n const subStep = step as SubAgentStep\n const turnMetrics = new TurnMetrics()\n\n const promptTemplate = subStep.prompt ?? 'Perform your task.'\n const resolvedPrompt = resolveTemplate(promptTemplate, templateCtx)\n\n const allAgents = await loadAllAgentsDefault()\n const agentDef = findAgentById(subStep.subAgentType, allAgents)\n if (!agentDef) {\n logger.error('Sub-agent definition not found', { subAgentType: subStep.subAgentType })\n stepOutcome = { success: false }\n break\n }\n\n const toolRegistry = getToolRegistryForAgent(agentDef)\n\n const nudgeConfig = subStep.subAgentType === 'verifier' && !subStep.nudgePrompt\n ? createVerifierNudgeConfig()\n : undefined\n\n const result = await executeSubAgent({\n subAgentType: subStep.subAgentType,\n prompt: resolvedPrompt,\n sessionManager,\n sessionId,\n llmClient,\n toolRegistry,\n turnMetrics,\n statsIdentity: options.statsIdentity ?? { providerId: '', providerName: '', backend: 'unknown', model: llmClient.getModel() },\n ...(signal ? { signal } : {}),\n ...(onMessage ? { onMessage } : {}),\n nudgeConfig,\n })\n\n lastSubAgentContent = result.content ?? ''\n stepOutcome = { success: result.allPassed ?? true }\n break\n }\n\n case 'shell': {\n const shellStep = step as ShellStep\n const command = resolveTemplate(shellStep.command, templateCtx)\n const timeout = shellStep.timeout ?? 60_000\n const successCodes = shellStep.successExitCodes ?? [0]\n\n // Emit a message showing the shell command being run\n const shellMsgId = crypto.randomUUID()\n eventStore.append(sessionId, createMessageStartEvent(shellMsgId, 'user', `Running: \\`${command}\\``, {\n ...(currentWindowMessageOptions ?? {}),\n isSystemGenerated: true,\n messageKind: 'auto-prompt',\n }))\n\n const result = await executeShellCommand(command, session.workdir, timeout, signal)\n\n const output = [result.stdout, result.stderr].filter(Boolean).join('\\n').trim()\n lastShellOutput = output\n\n // Append output as message content\n const outputContent = output\n ? `Exit code: ${result.exitCode}\\n\\`\\`\\`\\n${output.slice(0, 10000)}\\n\\`\\`\\``\n : `Exit code: ${result.exitCode}`\n eventStore.append(sessionId, { type: 'message.done', data: { messageId: shellMsgId } })\n\n const outputMsgId = crypto.randomUUID()\n eventStore.append(sessionId, createMessageStartEvent(outputMsgId, 'user', outputContent, {\n ...(currentWindowMessageOptions ?? {}),\n isSystemGenerated: true,\n messageKind: 'correction',\n }))\n eventStore.append(sessionId, { type: 'message.done', data: { messageId: outputMsgId } })\n\n stepOutcome = { success: successCodes.includes(result.exitCode) }\n break\n }\n }\n\n // Evaluate transitions\n const refreshedSession = sessionManager.requireSession(sessionId)\n const nextStepId = evaluateTransitions(\n step.transitions,\n refreshedSession.criteria,\n stepOutcome,\n )\n\n // Handle terminal states\n if (nextStepId === TERMINAL_DONE) {\n sessionManager.setPhase(sessionId, 'done')\n\n const totalTimeSeconds = Math.round((performance.now() - startTime) / 100) / 10\n const completedSession = sessionManager.requireSession(sessionId)\n // Only aggregate stats for messages created during this workflow run\n const workflowMessages = completedSession.messages.slice(messagesBeforeWorkflow)\n const workflowStats = computeSessionStats(workflowMessages)\n const totalToolCalls = workflowMessages.reduce(\n (sum, m) => sum + (m.toolCalls?.length ?? 0), 0\n )\n const taskCompletedData = {\n summary: null,\n iterations,\n totalTimeSeconds,\n totalToolCalls,\n totalTokensGenerated: workflowStats?.generationTokens ?? 0,\n avgGenerationSpeed: workflowStats?.avgGenerationSpeed ?? 0,\n responseCount: workflowStats?.responseCount ?? 0,\n llmCallCount: workflowStats?.llmCallCount ?? 0,\n criteria: [] as Array<{ id: string; description: string; status: string }>,\n workflowName: workflow.metadata.name,\n workflowId: workflow.metadata.id,\n ...(workflow.metadata.color ? { workflowColor: workflow.metadata.color } : {}),\n }\n eventStore.append(sessionId, { type: 'task.completed', data: taskCompletedData })\n\n const markerMsgId = crypto.randomUUID()\n eventStore.append(sessionId, createMessageStartEvent(markerMsgId, 'user', JSON.stringify(taskCompletedData), {\n ...(currentWindowMessageOptions ?? {}),\n isSystemGenerated: true,\n messageKind: 'task-completed',\n }))\n eventStore.append(sessionId, { type: 'message.done', data: { messageId: markerMsgId } })\n\n logger.debug('Workflow executor complete', { sessionId, iterations })\n const doneAction: NextAction = { type: 'DONE' }\n return {\n finalAction: doneAction,\n iterations,\n totalTime: totalTimeSeconds,\n }\n }\n\n if (nextStepId === TERMINAL_BLOCKED) {\n sessionManager.setPhase(sessionId, 'blocked')\n\n const blockedCriteria = refreshedSession.criteria\n .filter(c => c.status.type === 'failed' &&\n c.attempts.filter(a => a.status === 'failed').length >= RUNNER_CONFIG.maxVerifyRetries)\n .map(c => c.id)\n const reason = blockedCriteria.length > 0\n ? `Retry limit reached for: ${blockedCriteria.join(', ')}`\n : 'No matching transition'\n\n const blockedMsgId = crypto.randomUUID()\n eventStore.append(sessionId, createMessageStartEvent(blockedMsgId, 'user', `Runner blocked: ${reason}`, {\n ...(currentWindowMessageOptions ?? {}),\n isSystemGenerated: true,\n messageKind: 'correction',\n }))\n eventStore.append(sessionId, { type: 'message.done', data: { messageId: blockedMsgId } })\n\n logger.warn('Workflow executor blocked', { sessionId, iterations, reason })\n const blockedAction: NextAction = { type: 'BLOCKED', reason, blockedCriteria }\n return {\n finalAction: blockedAction,\n iterations,\n totalTime: (performance.now() - startTime) / 1000,\n }\n }\n\n // Move to next step\n currentStepId = nextStepId\n }\n\n // Max iterations reached\n logger.warn('Workflow executor max iterations reached', { sessionId, iterations })\n return {\n finalAction: { type: 'BLOCKED', reason: `Max iterations (${workflow.settings.maxIterations}) reached`, blockedCriteria: [] },\n iterations,\n totalTime: (performance.now() - startTime) / 1000,\n }\n}\n","/**\n * Runner Orchestrator\n *\n * Loads the active workflow and delegates to the workflow executor\n * (state machine driven). All events are appended to EventStore.\n */\n\nimport type { OrchestratorOptions, OrchestratorResult } from './types.js'\nimport { logger } from '../utils/logger.js'\nimport { getRuntimeConfig } from '../runtime-config.js'\nimport { getGlobalConfigDir } from '../../cli/paths.js'\nimport { loadAllWorkflows, findWorkflowById } from '../workflows/registry.js'\nimport { executeWorkflow } from '../workflows/executor.js'\n\n/**\n * Run the orchestrator loop until done, blocked, or aborted.\n *\n * Loads the workflow (per-session override or global active) and\n * delegates to the workflow executor state machine.\n */\nexport async function runOrchestrator(options: OrchestratorOptions): Promise<OrchestratorResult> {\n const runtimeConfig = getRuntimeConfig()\n const workflowId = options.workflowId ?? runtimeConfig.activeWorkflowId ?? 'default'\n const configDir = getGlobalConfigDir(runtimeConfig.mode ?? 'production')\n\n const workflows = await loadAllWorkflows(configDir)\n const workflow = findWorkflowById(workflowId, workflows)\n\n if (!workflow) {\n throw new Error(`Workflow \"${workflowId}\" not found`)\n }\n\n logger.debug('Using workflow executor', { sessionId: options.sessionId, workflow: workflow.metadata.id })\n return executeWorkflow(workflow, options)\n}\n","/**\n * Session Database Operations\n *\n * Manages session metadata in SQLite. Session content (messages, criteria, todos)\n * is stored in the events table and derived via EventStore folding.\n */\n\nimport type {\n Session,\n SessionSummary,\n SessionMode,\n SessionPhase,\n} from '../../shared/types.js'\nimport { getDatabase } from './index.js'\n\n// ============================================================================\n// Session Operations\n// ============================================================================\n\nexport function createSession(projectId: string, workdir: string, title?: string, providerId?: string | null, providerModel?: string | null): Session {\n const db = getDatabase()\n const now = new Date().toISOString()\n const id = crypto.randomUUID()\n\n db.prepare(`\n INSERT INTO sessions (id, project_id, workdir, phase, mode, workflow_phase, is_running, created_at, updated_at, title, provider_id, provider_model)\n VALUES (?, ?, ?, 'idle', 'planner', 'plan', 0, ?, ?, ?, ?, ?)\n `).run(id, projectId, workdir, now, now, title ?? null, providerId ?? null, providerModel ?? null)\n\n return {\n id,\n projectId,\n workdir,\n mode: 'planner',\n phase: 'plan',\n isRunning: false,\n summary: null,\n providerId: providerId ?? null,\n providerModel: providerModel ?? null,\n createdAt: now,\n updatedAt: now,\n messages: [],\n criteria: [],\n contextWindows: [],\n executionState: null,\n metadata: {\n ...(title ? { title } : {}),\n totalTokensUsed: 0,\n totalToolCalls: 0,\n iterationCount: 0,\n },\n }\n}\n\nexport function getSession(id: string): Session | null {\n const db = getDatabase()\n \n const row = db.prepare(`\n SELECT * FROM sessions WHERE id = ?\n `).get(id) as SessionRow | undefined\n \n if (!row) {\n return null\n }\n \n // Note: messages, criteria, contextWindows, executionState are derived from EventStore\n // This function returns the DB row data only - caller should enrich with event data\n return {\n id: row.id,\n projectId: row.project_id,\n workdir: row.workdir,\n mode: (row.mode ?? 'planner') as SessionMode,\n phase: (row.workflow_phase ?? 'plan') as SessionPhase,\n isRunning: Boolean(row.is_running),\n summary: row.summary ?? null,\n providerId: row.provider_id ?? null,\n providerModel: row.provider_model ?? null,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n messages: [],\n criteria: [],\n contextWindows: [],\n executionState: null,\n metadata: {\n ...(row.title ? { title: row.title } : {}),\n totalTokensUsed: row.total_tokens_used,\n totalToolCalls: row.total_tool_calls,\n iterationCount: row.iteration_count,\n },\n }\n}\n\nexport function updateSessionProvider(id: string, providerId: string | null, providerModel: string | null): void {\n const db = getDatabase()\n const now = new Date().toISOString()\n\n db.prepare(`\n UPDATE sessions SET provider_id = ?, provider_model = ?, updated_at = ? WHERE id = ?\n `).run(providerId, providerModel, now, id)\n}\n\nexport function updateSessionMode(id: string, mode: SessionMode): void {\n const db = getDatabase()\n const now = new Date().toISOString()\n \n db.prepare(`\n UPDATE sessions SET mode = ?, updated_at = ? WHERE id = ?\n `).run(mode, now, id)\n}\n\nexport function updateSessionPhase(id: string, phase: SessionPhase): void {\n const db = getDatabase()\n const now = new Date().toISOString()\n \n db.prepare(`\n UPDATE sessions SET workflow_phase = ?, updated_at = ? WHERE id = ?\n `).run(phase, now, id)\n}\n\nexport function updateSessionRunning(id: string, isRunning: boolean): void {\n const db = getDatabase()\n const now = new Date().toISOString()\n \n db.prepare(`\n UPDATE sessions SET is_running = ?, updated_at = ? WHERE id = ?\n `).run(isRunning ? 1 : 0, now, id)\n}\n\nexport function updateSessionSummary(id: string, summary: string): void {\n const db = getDatabase()\n const now = new Date().toISOString()\n \n db.prepare(`\n UPDATE sessions SET summary = ?, updated_at = ? WHERE id = ?\n `).run(summary, now, id)\n}\n\nexport function updateSessionMetadata(\n id: string,\n metadata: Partial<Session['metadata']>\n): void {\n const db = getDatabase()\n const now = new Date().toISOString()\n \n const updates: string[] = ['updated_at = ?']\n const values: (string | number)[] = [now]\n \n if (metadata.title !== undefined) {\n updates.push('title = ?')\n values.push(metadata.title ?? '')\n }\n if (metadata.totalTokensUsed !== undefined) {\n updates.push('total_tokens_used = ?')\n values.push(metadata.totalTokensUsed)\n }\n if (metadata.totalToolCalls !== undefined) {\n updates.push('total_tool_calls = ?')\n values.push(metadata.totalToolCalls)\n }\n if (metadata.iterationCount !== undefined) {\n updates.push('iteration_count = ?')\n values.push(metadata.iterationCount)\n }\n \n values.push(id)\n \n db.prepare(`\n UPDATE sessions SET ${updates.join(', ')} WHERE id = ?\n `).run(...values)\n}\n\nexport function listSessions(): SessionSummary[] {\n const db = getDatabase()\n \n // Note: criteriaCount and criteriaCompleted are now derived from events\n // For now, return 0 as placeholders - the frontend will get real data from session state\n const rows = db.prepare(`\n SELECT\n s.id,\n s.project_id,\n s.workdir,\n s.mode,\n s.workflow_phase,\n s.is_running,\n s.created_at,\n s.updated_at,\n s.title,\n s.provider_id,\n s.provider_model\n FROM sessions s\n ORDER BY s.updated_at DESC\n `).all() as SessionSummaryRow[]\n\n return rows.map(row => ({\n id: row.id,\n projectId: row.project_id,\n ...(row.title ? { title: row.title } : {}),\n workdir: row.workdir,\n mode: (row.mode ?? 'planner') as SessionMode,\n phase: (row.workflow_phase ?? 'plan') as SessionPhase,\n isRunning: Boolean(row.is_running),\n providerId: row.provider_id ?? null,\n providerModel: row.provider_model ?? null,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n criteriaCount: 0, // Derived from events\n criteriaCompleted: 0, // Derived from events\n }))\n}\n\nexport function listSessionsByProject(projectId: string): SessionSummary[] {\n const db = getDatabase()\n \n // Get sessions where project_id matches (workdir check removed to prevent session leakage)\n const rows = db.prepare(`\n SELECT\n s.id,\n s.project_id,\n s.workdir,\n s.mode,\n s.workflow_phase,\n s.is_running,\n s.created_at,\n s.updated_at,\n s.title,\n s.provider_id,\n s.provider_model\n FROM sessions s\n WHERE s.project_id = ?\n ORDER BY s.updated_at DESC\n `).all(projectId) as SessionSummaryRow[]\n\n return rows.map(row => ({\n id: row.id,\n projectId: row.project_id,\n ...(row.title ? { title: row.title } : {}),\n workdir: row.workdir,\n mode: (row.mode ?? 'planner') as SessionMode,\n phase: (row.workflow_phase ?? 'plan') as SessionPhase,\n isRunning: Boolean(row.is_running),\n providerId: row.provider_id ?? null,\n providerModel: row.provider_model ?? null,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n criteriaCount: 0, // Derived from events\n criteriaCompleted: 0, // Derived from events\n }))\n}\n\nexport function deleteSession(id: string): void {\n const db = getDatabase()\n db.prepare('DELETE FROM sessions WHERE id = ?').run(id)\n}\n\n// ============================================================================\n// Row Types\n// ============================================================================\n\ninterface SessionRow {\n id: string\n project_id: string\n workdir: string\n phase: string // Legacy, kept for compatibility\n mode: string\n workflow_phase: string // UI phase: plan/build/verification/done\n is_running: number\n summary: string | null\n provider_id: string | null\n provider_model: string | null\n created_at: string\n updated_at: string\n title: string | null\n total_tokens_used: number\n total_tool_calls: number\n iteration_count: number\n}\n\ninterface SessionSummaryRow {\n id: string\n project_id: string\n workdir: string\n mode: string\n workflow_phase: string\n is_running: number\n created_at: string\n updated_at: string\n title: string | null\n provider_id: string | null\n provider_model: string | null\n}\n","/**\n * Session Name Generator\n *\n * Generates concise, descriptive session names from the first user message.\n * Uses an ultra-lightweight prompt with NO project context or extra metadata.\n * Non-thinking variant to minimize cost and latency.\n */\n\nimport type { LLMClientWithModel } from '../llm/client.js'\nimport type { LLMMessage } from '../llm/types.js'\n\n// ============================================================================\n// Ultra-Lightweight Prompt\n// ============================================================================\n\n/**\n * The prompt is intentionally minimal:\n * - Only instructions for name generation\n * - Max 50 characters\n * - Descriptive and concise\n * - NO project context\n * - NO system instructions\n * - NO extra metadata\n */\nexport const SESSION_NAME_PROMPT = `Generate a concise, descriptive session name (max 50 characters) based on the user's message.\nReturn ONLY the name, nothing else.\n\nExample inputs and outputs:\n- \"How do I set up React?\" → \"React setup\"\n- \"Fix the authentication bug\" → \"Fix authentication bug\"\n- \"Add unit tests for the API\" → \"Add API unit tests\"\n\nUser message: {message}`\n\n// ============================================================================\n// Name Generation\n// ============================================================================\n\nexport interface GenerateSessionNameOptions {\n userMessage: string\n llmClient: LLMClientWithModel\n}\n\nexport interface GenerateSessionNameResult {\n success: boolean\n name?: string\n error?: string\n}\n\n/**\n * Generate a session name from the user's first message.\n * Uses the provided LLM client (respecting user's selected model).\n * Disables thinking output for minimal latency.\n */\nexport async function generateSessionName(\n options: GenerateSessionNameOptions\n): Promise<GenerateSessionNameResult> {\n const { userMessage, llmClient } = options\n \n try {\n // Use non-thinking variant by disabling thinking\n // This ensures only the name is returned, no reasoning\n const prompt = SESSION_NAME_PROMPT.replace('{message}', userMessage)\n \n const messages: LLMMessage[] = [\n {\n role: 'user',\n content: prompt,\n },\n ]\n\n const response = await llmClient.complete({\n messages,\n tools: [],\n signal: AbortSignal.timeout(60000),\n disableThinking: true\n })\n\n // Clean up the response: trim whitespace and ensure it's under 50 chars\n let name = response.content.trim()\n \n // Truncate to 50 characters if needed\n if (name.length > 50) {\n name = name.substring(0, 47) + '...'\n }\n\n // Basic validation: ensure it's not empty\n if (!name || name.length < 3) {\n return {\n success: false,\n error: 'Generated name is too short or empty',\n }\n }\n\n return {\n success: true,\n name,\n }\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error generating session name',\n }\n }\n}\n\n/**\n * Check if a session needs name generation.\n * A session needs a name if:\n * - It has no title in the DB, OR\n * - It has a default title like \"Session N\"\n * AND it's the first user message\n */\nexport function needsNameGeneration(sessionTitle: string | null | undefined, messageCount: number): boolean {\n // Only generate on the first user message\n if (messageCount > 1) {\n return false\n }\n\n // If session has no title yet\n if (!sessionTitle || sessionTitle.trim() === '') {\n return true\n }\n\n // If title matches default pattern \"Session N\"\n if (/^Session \\d+$/.test(sessionTitle)) {\n return true\n }\n\n return false\n}\n","/**\n * Session Summary Generator\n *\n * Generates concise summaries of user conversations when switching to builder mode.\n * Uses a non-thinking variant for minimal latency.\n */\n\nimport type { LLMClientWithModel } from '../llm/client.js'\nimport type { LLMMessage } from '../llm/types.js'\n\n// ============================================================================\n// Summary Prompt\n// ============================================================================\n\n/**\n * Prompt for generating session summaries.\n * Focuses on WHAT and WHY, not HOW.\n * Returns only the summary, no preamble.\n */\nexport const SESSION_SUMMARY_PROMPT = `Write a 2-3 sentence summary of what the user wants to accomplish. Focus on WHAT and WHY, not HOW. Output only the summary, no preamble.\n\n## Conversation History\n{messages}\n\n## Summary\n`\n\n// ============================================================================\n// Summary Generation\n// ============================================================================\n\nexport interface GenerateSessionSummaryOptions {\n messages: Array<{ role: 'user' | 'assistant'; content: string }>\n llmClient: LLMClientWithModel\n}\n\nexport interface GenerateSessionSummaryResult {\n success: boolean\n summary?: string\n error?: string\n}\n\n/**\n * Generate a session summary from conversation messages.\n * Uses the provided LLM client (respecting user's selected model).\n * Disables thinking output for minimal latency.\n */\nexport async function generateSessionSummary(\n options: GenerateSessionSummaryOptions\n): Promise<GenerateSessionSummaryResult> {\n const { messages, llmClient } = options\n \n try {\n // Format messages for the prompt\n const messagesText = messages\n .map(m => `${m.role}: ${m.content}`)\n .join('\\n')\n \n const prompt = SESSION_SUMMARY_PROMPT.replace('{messages}', messagesText)\n \n const llmMessages: LLMMessage[] = [\n {\n role: 'user',\n content: prompt,\n },\n ]\n\n const response = await llmClient.complete({\n messages: llmMessages,\n tools: [],\n signal: AbortSignal.timeout(60000),\n disableThinking: true,\n })\n\n // Clean up the response: trim whitespace\n let summary = response.content.trim()\n \n // Truncate to 500 characters if needed\n if (summary.length > 500) {\n summary = summary.substring(0, 497) + '...'\n }\n\n // Basic validation: ensure it's not too short\n if (!summary || summary.length < 10) {\n return {\n success: false,\n error: 'Generated summary is too short or empty',\n }\n }\n\n return {\n success: true,\n summary,\n }\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error generating summary',\n }\n }\n}\n\n/**\n * Check if a session needs summary generation.\n * A session needs a summary if:\n * - It has no summary in the DB (summary is null)\n */\nexport function needsSummaryGeneration(sessionSummary: string | null): boolean {\n return sessionSummary === null || sessionSummary.trim() === ''\n}\n","import { spawn, type ChildProcess } from 'node:child_process'\nimport { extname } from 'node:path'\nimport { createMessageConnection, StreamMessageReader, StreamMessageWriter } from 'vscode-jsonrpc/node.js'\nimport type { MessageConnection } from 'vscode-jsonrpc'\nimport type { Diagnostic } from '../../shared/types.js'\nimport type { LanguageConfig, LspServerState } from './types.js'\nimport { logger } from '../utils/logger.js'\n\n// ============================================================================\n// LSP Protocol Constants & Types (minimal definitions)\n// ============================================================================\n\n// LSP method names\nconst LSP = {\n initialize: 'initialize',\n initialized: 'initialized',\n shutdown: 'shutdown',\n exit: 'exit',\n didOpen: 'textDocument/didOpen',\n didChange: 'textDocument/didChange',\n didClose: 'textDocument/didClose',\n publishDiagnostics: 'textDocument/publishDiagnostics',\n} as const\n\n// LSP diagnostic severity\nconst DiagnosticSeverity = {\n Error: 1,\n Warning: 2,\n Information: 3,\n Hint: 4,\n} as const\n\ntype DiagnosticSeverityValue = (typeof DiagnosticSeverity)[keyof typeof DiagnosticSeverity]\n\n// LSP types\ninterface LspRange {\n start: { line: number; character: number }\n end: { line: number; character: number }\n}\n\ninterface LspDiagnostic {\n range: LspRange\n severity?: DiagnosticSeverityValue\n code?: number | string\n source?: string\n message: string\n}\n\ninterface PublishDiagnosticsParams {\n uri: string\n diagnostics: LspDiagnostic[]\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DIAGNOSTIC_WAIT_MS = 2000\n\n// Map LSP severity to our severity\nfunction mapSeverity(severity: DiagnosticSeverityValue | undefined): Diagnostic['severity'] {\n switch (severity) {\n case DiagnosticSeverity.Error: return 'error'\n case DiagnosticSeverity.Warning: return 'warning'\n case DiagnosticSeverity.Information: return 'info'\n case DiagnosticSeverity.Hint: return 'hint'\n default: return 'info'\n }\n}\n\n// ============================================================================\n// LSP Server\n// ============================================================================\n\nexport class LspServer {\n private config: LanguageConfig\n private workdir: string\n private process: ChildProcess | null = null\n private connection: MessageConnection | null = null\n private state: LspServerState = 'stopped'\n \n // Document tracking\n private openDocuments = new Map<string, { version: number; content: string }>()\n \n // Diagnostics storage\n private diagnostics = new Map<string, Diagnostic[]>()\n private diagnosticsCallbacks = new Set<(path: string, diagnostics: Diagnostic[]) => void>()\n \n // Pending diagnostic waiters\n private pendingDiagnostics = new Map<string, {\n resolve: (diagnostics: Diagnostic[]) => void\n timeout: NodeJS.Timeout\n }>()\n \n private commandPath: string\n \n constructor(config: LanguageConfig, workdir: string, commandPath?: string) {\n this.config = config\n this.workdir = workdir\n this.commandPath = commandPath ?? config.serverCommand\n }\n \n // ============================================================================\n // Lifecycle\n // ============================================================================\n \n async start(): Promise<void> {\n if (this.state === 'running' || this.state === 'starting') {\n return\n }\n \n this.state = 'starting'\n \n try {\n // Spawn the language server process using resolved command path\n this.process = spawn(this.commandPath, this.config.serverArgs, {\n cwd: this.workdir,\n stdio: ['pipe', 'pipe', 'pipe'],\n env: {\n ...process.env,\n HOME: process.env['HOME'],\n PATH: process.env['PATH'],\n },\n })\n \n if (!this.process.stdin || !this.process.stdout) {\n throw new Error('Failed to get stdio streams from language server process')\n }\n \n // Set up JSON-RPC connection\n this.connection = createMessageConnection(\n new StreamMessageReader(this.process.stdout),\n new StreamMessageWriter(this.process.stdin)\n )\n \n // Handle diagnostics\n this.connection.onNotification(\n LSP.publishDiagnostics,\n (params: PublishDiagnosticsParams) => {\n this.handleDiagnostics(params)\n }\n )\n \n // Handle process errors\n this.process.on('error', (err) => {\n logger.error('LSP server process error', { language: this.config.id, error: err.message })\n this.handleProcessExit()\n })\n \n this.process.on('exit', (code) => {\n if (this.state === 'running') {\n logger.warn('LSP server exited unexpectedly', { language: this.config.id, code })\n this.handleProcessExit()\n }\n })\n \n this.process.stderr?.on('data', (data: Buffer) => {\n const msg = data.toString().trim()\n if (msg) {\n logger.debug('LSP server stderr', { language: this.config.id, message: msg })\n }\n })\n \n // Start the connection\n this.connection.listen()\n \n // Send initialize request\n const initParams = {\n processId: process.pid,\n rootUri: `file://${this.workdir}`,\n rootPath: this.workdir,\n capabilities: {\n textDocument: {\n publishDiagnostics: {\n relatedInformation: true,\n },\n synchronization: {\n willSave: false,\n didSave: true,\n willSaveWaitUntil: false,\n },\n },\n workspace: {\n workspaceFolders: true,\n },\n },\n workspaceFolders: [\n { uri: `file://${this.workdir}`, name: 'workspace' }\n ],\n initializationOptions: this.config.initOptions,\n }\n \n const result = await this.connection.sendRequest(LSP.initialize, initParams)\n \n logger.debug('LSP server initialized', {\n language: this.config.id,\n capabilities: result,\n })\n \n // Send initialized notification\n await this.connection.sendNotification(LSP.initialized, {})\n \n this.state = 'running'\n \n logger.debug('LSP server started', {\n language: this.config.id,\n pid: this.process.pid,\n })\n \n } catch (error) {\n this.state = 'error'\n logger.error('Failed to start LSP server', {\n language: this.config.id,\n command: this.config.serverCommand,\n error: error instanceof Error ? error.message : String(error),\n })\n throw error\n }\n }\n \n async stop(): Promise<void> {\n if (this.state === 'stopped') {\n return\n }\n \n // Clear pending waiters\n for (const [, waiter] of this.pendingDiagnostics) {\n clearTimeout(waiter.timeout)\n waiter.resolve([])\n }\n this.pendingDiagnostics.clear()\n \n if (this.connection && this.state === 'running') {\n try {\n await this.connection.sendRequest(LSP.shutdown)\n await this.connection.sendNotification(LSP.exit)\n } catch {\n // Ignore errors during shutdown\n }\n }\n \n // Force kill if still running\n if (this.process) {\n this.process.kill('SIGTERM')\n this.process = null\n }\n \n this.connection?.dispose()\n this.connection = null\n this.state = 'stopped'\n this.openDocuments.clear()\n this.diagnostics.clear()\n \n logger.debug('LSP server stopped', { language: this.config.id })\n }\n \n private handleProcessExit(): void {\n this.state = 'error'\n this.connection?.dispose()\n this.connection = null\n this.process = null\n \n // Clear pending waiters\n for (const [, waiter] of this.pendingDiagnostics) {\n clearTimeout(waiter.timeout)\n waiter.resolve([])\n }\n this.pendingDiagnostics.clear()\n }\n \n // ============================================================================\n // Document Synchronization\n // ============================================================================\n \n async didOpen(path: string, content: string): Promise<void> {\n if (this.state !== 'running' || !this.connection) {\n return\n }\n \n // Already open? Send change instead\n const existing = this.openDocuments.get(path)\n if (existing) {\n await this.didChange(path, content)\n return\n }\n \n const uri = `file://${path}`\n const languageId = this.getLanguageIdForFile(path)\n \n this.openDocuments.set(path, { version: 1, content })\n \n await this.connection.sendNotification(LSP.didOpen, {\n textDocument: {\n uri,\n languageId,\n version: 1,\n text: content,\n },\n })\n }\n \n /**\n * Get the correct LSP languageId for a file path.\n * Uses extension-specific mapping if available, otherwise falls back to config id.\n */\n private getLanguageIdForFile(path: string): string {\n if (this.config.languageIds) {\n const ext = extname(path).toLowerCase()\n const languageId = this.config.languageIds[ext]\n if (languageId) {\n return languageId\n }\n }\n return this.config.id\n }\n \n async didChange(path: string, content: string): Promise<void> {\n if (this.state !== 'running' || !this.connection) {\n return\n }\n \n const uri = `file://${path}`\n const existing = this.openDocuments.get(path)\n \n if (!existing) {\n await this.didOpen(path, content)\n return\n }\n \n const newVersion = existing.version + 1\n this.openDocuments.set(path, { version: newVersion, content })\n \n // Clear cached diagnostics - we want fresh ones after this change\n this.diagnostics.delete(path)\n \n await this.connection.sendNotification(LSP.didChange, {\n textDocument: {\n uri,\n version: newVersion,\n },\n contentChanges: [{ text: content }],\n })\n }\n \n async didClose(path: string): Promise<void> {\n if (this.state !== 'running' || !this.connection) {\n return\n }\n \n if (!this.openDocuments.has(path)) {\n return\n }\n \n const uri = `file://${path}`\n this.openDocuments.delete(path)\n \n await this.connection.sendNotification(LSP.didClose, {\n textDocument: { uri },\n })\n }\n \n // ============================================================================\n // Diagnostics\n // ============================================================================\n \n private handleDiagnostics(params: PublishDiagnosticsParams): void {\n // Convert URI to path\n const path = params.uri.replace(/^file:\\/\\//, '')\n \n // Convert LSP diagnostics to our format\n const diagnostics: Diagnostic[] = params.diagnostics.map(d => ({\n path,\n range: {\n start: { line: d.range.start.line, character: d.range.start.character },\n end: { line: d.range.end.line, character: d.range.end.character },\n },\n severity: mapSeverity(d.severity),\n message: d.message,\n source: d.source ?? this.config.id,\n ...(d.code !== undefined && { code: String(d.code) }),\n }))\n \n // Store diagnostics\n this.diagnostics.set(path, diagnostics)\n \n // Notify callbacks\n for (const callback of this.diagnosticsCallbacks) {\n callback(path, diagnostics)\n }\n \n // Resolve any pending waiters for this path\n const waiter = this.pendingDiagnostics.get(path)\n if (waiter) {\n clearTimeout(waiter.timeout)\n this.pendingDiagnostics.delete(path)\n waiter.resolve(diagnostics)\n }\n }\n \n /**\n * Get diagnostics for a file, waiting for LSP to respond if needed\n */\n async getDiagnosticsWithWait(path: string, timeoutMs: number = DIAGNOSTIC_WAIT_MS): Promise<Diagnostic[]> {\n // Return cached if available and we already have this file open\n if (this.openDocuments.has(path)) {\n return new Promise<Diagnostic[]>((resolve) => {\n // Check if we already have diagnostics\n const existing = this.diagnostics.get(path)\n if (existing !== undefined) {\n // Give a brief moment for any pending updates\n setTimeout(() => {\n resolve(this.diagnostics.get(path) ?? [])\n }, 100)\n return\n }\n \n // Wait for diagnostics\n const timeout = setTimeout(() => {\n this.pendingDiagnostics.delete(path)\n resolve(this.diagnostics.get(path) ?? [])\n }, timeoutMs)\n \n this.pendingDiagnostics.set(path, { resolve, timeout })\n })\n }\n \n return this.diagnostics.get(path) ?? []\n }\n \n /**\n * Get current diagnostics for a file (no waiting)\n */\n getDiagnostics(path: string): Diagnostic[] {\n return this.diagnostics.get(path) ?? []\n }\n \n /**\n * Subscribe to diagnostic updates\n */\n onDiagnostics(callback: (path: string, diagnostics: Diagnostic[]) => void): () => void {\n this.diagnosticsCallbacks.add(callback)\n return () => this.diagnosticsCallbacks.delete(callback)\n }\n \n // ============================================================================\n // Status\n // ============================================================================\n \n isRunning(): boolean {\n return this.state === 'running'\n }\n \n getState(): LspServerState {\n return this.state\n }\n \n getLanguage(): string {\n return this.config.id\n }\n}\n","import { access, constants } from 'node:fs/promises'\nimport { join, dirname } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\n// Get the directory where this module is located\n// In dev: src/server/utils/\n// In prod: dist/server/utils/\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\n// Path to bundled node_modules/.bin\n// Uses process.cwd() as the primary source (where user runs the command)\n// Falls back to relative paths from this module location\nfunction getBundledBinPaths(): string[] {\n const paths: string[] = []\n \n // Primary: use current working directory (where user runs openfox)\n paths.push(join(process.cwd(), 'node_modules', '.bin'))\n \n // Fallback: relative to this module (for edge cases)\n paths.push(join(__dirname, '..', '..', '..', 'node_modules', '.bin'))\n paths.push(join(__dirname, '..', '..', '..', '..', 'node_modules', '.bin'))\n \n return paths\n}\n\n/**\n * Check if a command exists at a given path\n */\nasync function existsExecutable(path: string): Promise<boolean> {\n try {\n await access(path, constants.X_OK)\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Find the path to an executable command.\n * Search order:\n * 1. Bundled language servers in @openfox/server's node_modules/.bin\n * 2. Project-local node_modules/.bin (if workdir provided)\n * 3. System PATH\n * \n * Returns null if the command is not found.\n */\nexport async function which(command: string, workdir?: string): Promise<string | null> {\n // If it's an absolute path, check if it exists and is executable\n if (command.startsWith('/')) {\n if (await existsExecutable(command)) {\n return command\n }\n return null\n }\n \n // 1. Check bundled node_modules/.bin first (language servers bundled with @openfox/server)\n for (const binDir of getBundledBinPaths()) {\n const fullPath = join(binDir, command)\n if (await existsExecutable(fullPath)) {\n return fullPath\n }\n }\n \n // 2. Check project-local node_modules/.bin (if workdir provided)\n if (workdir) {\n const projectBin = join(workdir, 'node_modules', '.bin', command)\n if (await existsExecutable(projectBin)) {\n return projectBin\n }\n }\n \n // 3. Search system PATH\n const pathEnv = process.env['PATH'] ?? ''\n const paths = pathEnv.split(':')\n \n for (const dir of paths) {\n if (!dir) continue\n \n const fullPath = join(dir, command)\n if (await existsExecutable(fullPath)) {\n return fullPath\n }\n }\n \n return null\n}\n","import { extname, basename } from 'node:path'\nimport type { LanguageConfig } from './types.js'\n\n// ============================================================================\n// Supported Language Servers\n// ============================================================================\n\nexport const LANGUAGES: LanguageConfig[] = [\n // JavaScript/TypeScript ecosystem\n {\n id: 'typescript',\n name: 'TypeScript',\n extensions: ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'],\n serverCommand: 'typescript-language-server',\n serverArgs: ['--stdio'],\n rootPatterns: ['tsconfig.json', 'jsconfig.json', 'package.json'],\n languageIds: {\n '.ts': 'typescript',\n '.tsx': 'typescriptreact',\n '.js': 'javascript',\n '.jsx': 'javascriptreact',\n '.mjs': 'javascript',\n '.cjs': 'javascript',\n },\n },\n \n // Python\n {\n id: 'python',\n name: 'Python',\n extensions: ['.py', '.pyi', '.pyw'],\n serverCommand: 'pyright-langserver',\n serverArgs: ['--stdio'],\n rootPatterns: ['pyproject.toml', 'setup.py', 'requirements.txt', 'Pipfile'],\n },\n \n // Rust\n {\n id: 'rust',\n name: 'Rust',\n extensions: ['.rs'],\n serverCommand: 'rust-analyzer',\n serverArgs: [],\n rootPatterns: ['Cargo.toml'],\n },\n \n // Go\n {\n id: 'go',\n name: 'Go',\n extensions: ['.go'],\n serverCommand: 'gopls',\n serverArgs: ['serve'],\n rootPatterns: ['go.mod', 'go.sum'],\n },\n \n // C/C++\n {\n id: 'cpp',\n name: 'C/C++',\n extensions: ['.c', '.cpp', '.cc', '.cxx', '.h', '.hpp', '.hxx', '.hh'],\n serverCommand: 'clangd',\n serverArgs: ['--background-index'],\n rootPatterns: ['compile_commands.json', 'CMakeLists.txt', '.clangd', 'Makefile'],\n },\n \n // Zig\n {\n id: 'zig',\n name: 'Zig',\n extensions: ['.zig'],\n serverCommand: 'zls',\n serverArgs: [],\n rootPatterns: ['build.zig', 'build.zig.zon'],\n },\n \n // Lua\n {\n id: 'lua',\n name: 'Lua',\n extensions: ['.lua'],\n serverCommand: 'lua-language-server',\n serverArgs: [],\n rootPatterns: ['.luarc.json', '.luarc.jsonc', '.luacheckrc'],\n },\n \n // Ruby\n {\n id: 'ruby',\n name: 'Ruby',\n extensions: ['.rb', '.rake', '.gemspec'],\n serverCommand: 'solargraph',\n serverArgs: ['stdio'],\n rootPatterns: ['Gemfile', '.ruby-version'],\n },\n \n // Elixir\n {\n id: 'elixir',\n name: 'Elixir',\n extensions: ['.ex', '.exs'],\n serverCommand: 'elixir-ls',\n serverArgs: [],\n rootPatterns: ['mix.exs'],\n },\n \n // Haskell\n {\n id: 'haskell',\n name: 'Haskell',\n extensions: ['.hs', '.lhs'],\n serverCommand: 'haskell-language-server-wrapper',\n serverArgs: ['--lsp'],\n rootPatterns: ['stack.yaml', 'cabal.project', '*.cabal'],\n },\n \n // OCaml\n {\n id: 'ocaml',\n name: 'OCaml',\n extensions: ['.ml', '.mli'],\n serverCommand: 'ocamllsp',\n serverArgs: [],\n rootPatterns: ['dune-project', 'dune', '*.opam'],\n },\n \n // Scala\n {\n id: 'scala',\n name: 'Scala',\n extensions: ['.scala', '.sc'],\n serverCommand: 'metals',\n serverArgs: [],\n rootPatterns: ['build.sbt', 'build.sc', '.metals'],\n },\n \n // Kotlin\n {\n id: 'kotlin',\n name: 'Kotlin',\n extensions: ['.kt', '.kts'],\n serverCommand: 'kotlin-language-server',\n serverArgs: [],\n rootPatterns: ['build.gradle.kts', 'build.gradle', 'settings.gradle.kts'],\n },\n \n // Java\n {\n id: 'java',\n name: 'Java',\n extensions: ['.java'],\n serverCommand: 'jdtls',\n serverArgs: [],\n rootPatterns: ['pom.xml', 'build.gradle', '.project'],\n },\n \n // C#\n {\n id: 'csharp',\n name: 'C#',\n extensions: ['.cs', '.csx'],\n serverCommand: 'OmniSharp',\n serverArgs: ['-lsp'],\n rootPatterns: ['*.csproj', '*.sln'],\n },\n \n // Swift\n {\n id: 'swift',\n name: 'Swift',\n extensions: ['.swift'],\n serverCommand: 'sourcekit-lsp',\n serverArgs: [],\n rootPatterns: ['Package.swift', '*.xcodeproj', '*.xcworkspace'],\n },\n \n // PHP\n {\n id: 'php',\n name: 'PHP',\n extensions: ['.php', '.phtml'],\n serverCommand: 'phpactor',\n serverArgs: ['language-server'],\n rootPatterns: ['composer.json', 'phpunit.xml'],\n },\n \n // YAML\n {\n id: 'yaml',\n name: 'YAML',\n extensions: ['.yaml', '.yml'],\n serverCommand: 'yaml-language-server',\n serverArgs: ['--stdio'],\n rootPatterns: [],\n },\n \n // JSON\n {\n id: 'json',\n name: 'JSON',\n extensions: ['.json', '.jsonc'],\n serverCommand: 'vscode-json-language-server',\n serverArgs: ['--stdio'],\n rootPatterns: [],\n },\n \n // HTML\n {\n id: 'html',\n name: 'HTML',\n extensions: ['.html', '.htm', '.xhtml'],\n serverCommand: 'vscode-html-language-server',\n serverArgs: ['--stdio'],\n rootPatterns: [],\n },\n \n // CSS\n {\n id: 'css',\n name: 'CSS',\n extensions: ['.css', '.scss', '.sass', '.less'],\n serverCommand: 'vscode-css-language-server',\n serverArgs: ['--stdio'],\n rootPatterns: [],\n },\n \n // Vue\n {\n id: 'vue',\n name: 'Vue',\n extensions: ['.vue'],\n serverCommand: 'vue-language-server',\n serverArgs: ['--stdio'],\n rootPatterns: ['vite.config.ts', 'vite.config.js', 'vue.config.js'],\n },\n \n // Svelte\n {\n id: 'svelte',\n name: 'Svelte',\n extensions: ['.svelte'],\n serverCommand: 'svelteserver',\n serverArgs: ['--stdio'],\n rootPatterns: ['svelte.config.js', 'svelte.config.ts'],\n },\n \n // Terraform\n {\n id: 'terraform',\n name: 'Terraform',\n extensions: ['.tf', '.tfvars'],\n serverCommand: 'terraform-ls',\n serverArgs: ['serve'],\n rootPatterns: ['.terraform', 'main.tf'],\n },\n \n // Dockerfile\n {\n id: 'dockerfile',\n name: 'Docker',\n extensions: [], // Uses filename matching\n serverCommand: 'docker-langserver',\n serverArgs: ['--stdio'],\n rootPatterns: ['Dockerfile', 'docker-compose.yml'],\n },\n \n // Bash/Shell\n {\n id: 'bash',\n name: 'Bash',\n extensions: ['.sh', '.bash', '.zsh'],\n serverCommand: 'bash-language-server',\n serverArgs: ['start'],\n rootPatterns: [],\n },\n \n // SQL\n {\n id: 'sql',\n name: 'SQL',\n extensions: ['.sql'],\n serverCommand: 'sql-language-server',\n serverArgs: ['up', '--method', 'stdio'],\n rootPatterns: [],\n },\n \n // GraphQL\n {\n id: 'graphql',\n name: 'GraphQL',\n extensions: ['.graphql', '.gql'],\n serverCommand: 'graphql-lsp',\n serverArgs: ['server', '-m', 'stream'],\n rootPatterns: ['.graphqlrc', '.graphqlrc.yml', '.graphqlrc.json', 'graphql.config.js'],\n },\n \n // Nix\n {\n id: 'nix',\n name: 'Nix',\n extensions: ['.nix'],\n serverCommand: 'nil',\n serverArgs: [],\n rootPatterns: ['flake.nix', 'default.nix', 'shell.nix'],\n },\n \n // Gleam\n {\n id: 'gleam',\n name: 'Gleam',\n extensions: ['.gleam'],\n serverCommand: 'gleam',\n serverArgs: ['lsp'],\n rootPatterns: ['gleam.toml'],\n },\n \n // Elm\n {\n id: 'elm',\n name: 'Elm',\n extensions: ['.elm'],\n serverCommand: 'elm-language-server',\n serverArgs: [],\n rootPatterns: ['elm.json'],\n },\n \n // Dart\n {\n id: 'dart',\n name: 'Dart',\n extensions: ['.dart'],\n serverCommand: 'dart',\n serverArgs: ['language-server', '--protocol=lsp'],\n rootPatterns: ['pubspec.yaml'],\n },\n \n // Julia\n {\n id: 'julia',\n name: 'Julia',\n extensions: ['.jl'],\n serverCommand: 'julia',\n serverArgs: ['--startup-file=no', '--history-file=no', '-e', 'using LanguageServer; runserver()'],\n rootPatterns: ['Project.toml'],\n },\n \n // R\n {\n id: 'r',\n name: 'R',\n extensions: ['.r', '.R', '.rmd', '.Rmd'],\n serverCommand: 'R',\n serverArgs: ['--slave', '-e', 'languageserver::run()'],\n rootPatterns: ['DESCRIPTION', '.Rproj'],\n },\n \n // Clojure\n {\n id: 'clojure',\n name: 'Clojure',\n extensions: ['.clj', '.cljs', '.cljc', '.edn'],\n serverCommand: 'clojure-lsp',\n serverArgs: [],\n rootPatterns: ['deps.edn', 'project.clj', 'shadow-cljs.edn'],\n },\n \n // Nim\n {\n id: 'nim',\n name: 'Nim',\n extensions: ['.nim', '.nims'],\n serverCommand: 'nimlsp',\n serverArgs: [],\n rootPatterns: ['*.nimble'],\n },\n \n // V\n {\n id: 'vlang',\n name: 'V',\n extensions: ['.v', '.vv'],\n serverCommand: 'vls',\n serverArgs: [],\n rootPatterns: ['v.mod'],\n },\n \n // Crystal\n {\n id: 'crystal',\n name: 'Crystal',\n extensions: ['.cr'],\n serverCommand: 'crystalline',\n serverArgs: [],\n rootPatterns: ['shard.yml'],\n },\n \n // D\n {\n id: 'd',\n name: 'D',\n extensions: ['.d'],\n serverCommand: 'serve-d',\n serverArgs: [],\n rootPatterns: ['dub.json', 'dub.sdl'],\n },\n \n // Erlang\n {\n id: 'erlang',\n name: 'Erlang',\n extensions: ['.erl', '.hrl'],\n serverCommand: 'erlang_ls',\n serverArgs: [],\n rootPatterns: ['rebar.config', 'erlang.mk'],\n },\n \n // F#\n {\n id: 'fsharp',\n name: 'F#',\n extensions: ['.fs', '.fsx', '.fsi'],\n serverCommand: 'fsautocomplete',\n serverArgs: ['--adaptive-lsp-server-enabled'],\n rootPatterns: ['*.fsproj'],\n },\n \n // Fortran\n {\n id: 'fortran',\n name: 'Fortran',\n extensions: ['.f', '.f90', '.f95', '.f03', '.f08'],\n serverCommand: 'fortls',\n serverArgs: [],\n rootPatterns: [],\n },\n \n // LaTeX\n {\n id: 'latex',\n name: 'LaTeX',\n extensions: ['.tex', '.bib'],\n serverCommand: 'texlab',\n serverArgs: [],\n rootPatterns: ['*.tex'],\n },\n \n // Markdown\n {\n id: 'markdown',\n name: 'Markdown',\n extensions: ['.md', '.markdown'],\n serverCommand: 'marksman',\n serverArgs: [],\n rootPatterns: [],\n },\n \n // TOML\n {\n id: 'toml',\n name: 'TOML',\n extensions: ['.toml'],\n serverCommand: 'taplo',\n serverArgs: ['lsp', 'stdio'],\n rootPatterns: [],\n },\n \n // Protobuf\n {\n id: 'protobuf',\n name: 'Protocol Buffers',\n extensions: ['.proto'],\n serverCommand: 'bufls',\n serverArgs: ['serve'],\n rootPatterns: ['buf.yaml', 'buf.gen.yaml'],\n },\n \n // Assembly (various)\n {\n id: 'asm',\n name: 'Assembly',\n extensions: ['.asm', '.s', '.S'],\n serverCommand: 'asm-lsp',\n serverArgs: [],\n rootPatterns: [],\n },\n \n // CMake\n {\n id: 'cmake',\n name: 'CMake',\n extensions: ['.cmake'],\n serverCommand: 'cmake-language-server',\n serverArgs: [],\n rootPatterns: ['CMakeLists.txt'],\n },\n \n // Perl\n {\n id: 'perl',\n name: 'Perl',\n extensions: ['.pl', '.pm'],\n serverCommand: 'pls',\n serverArgs: [],\n rootPatterns: ['cpanfile', 'Makefile.PL'],\n },\n]\n\n// Build extension -> language map for fast lookup\nconst extensionToLanguage = new Map<string, LanguageConfig>()\nfor (const lang of LANGUAGES) {\n for (const ext of lang.extensions) {\n extensionToLanguage.set(ext, lang)\n }\n}\n\n// Special filename matching (case-insensitive)\nconst specialFilenames: Record<string, LanguageConfig> = {}\nconst dockerLang = LANGUAGES.find(l => l.id === 'dockerfile')\nif (dockerLang) {\n specialFilenames['dockerfile'] = dockerLang\n specialFilenames['containerfile'] = dockerLang\n}\n\n/**\n * Detect language configuration from a file path\n */\nexport function detectLanguage(filePath: string): LanguageConfig | null {\n // Check special filenames first\n const filename = basename(filePath).toLowerCase()\n const special = specialFilenames[filename]\n if (special) {\n return special\n }\n \n // Check extension\n const ext = extname(filePath).toLowerCase()\n if (!ext) {\n return null\n }\n \n return extensionToLanguage.get(ext) ?? null\n}\n\n/**\n * Get all supported languages\n */\nexport function getSupportedLanguages(): LanguageConfig[] {\n return [...LANGUAGES]\n}\n\n/**\n * Get language by ID\n */\nexport function getLanguageById(id: string): LanguageConfig | null {\n return LANGUAGES.find(l => l.id === id) ?? null\n}\n","import { which } from '../utils/which.js'\nimport type { Diagnostic } from '../../shared/types.js'\nimport type { LanguageConfig, LspManagerInterface } from './types.js'\nimport { LspServer } from './server.js'\nimport { detectLanguage } from './languages.js'\nimport { logger } from '../utils/logger.js'\n\n// ============================================================================\n// LSP Manager\n// ============================================================================\n\n/**\n * Manages multiple LSP servers for a session.\n * Lazy-starts servers on first file access for each language.\n */\nexport class LspManager implements LspManagerInterface {\n private workdir: string\n private sessionId: string\n private servers = new Map<string, LspServer>() // language id -> server\n private unavailableServers = new Set<string>() // language ids we've tried and failed\n private serverPromises = new Map<string, Promise<LspServer | null>>() // pending server starts\n \n constructor(workdir: string, sessionId: string) {\n this.workdir = workdir\n this.sessionId = sessionId\n }\n \n // ============================================================================\n // Server Management\n // ============================================================================\n \n private async getOrCreateServer(config: LanguageConfig): Promise<LspServer | null> {\n const langId = config.id\n \n // Already have a running server?\n const existing = this.servers.get(langId)\n if (existing?.isRunning()) {\n return existing\n }\n \n // Already known to be unavailable?\n if (this.unavailableServers.has(langId)) {\n return null\n }\n \n // Already starting?\n const pending = this.serverPromises.get(langId)\n if (pending) {\n return pending\n }\n \n // Start a new server\n const promise = this.startServer(config)\n this.serverPromises.set(langId, promise)\n \n try {\n const server = await promise\n return server\n } finally {\n this.serverPromises.delete(langId)\n }\n }\n \n private async startServer(config: LanguageConfig): Promise<LspServer | null> {\n const langId = config.id\n \n // Check if command exists (checks bundled, project-local, then system PATH)\n const commandPath = await which(config.serverCommand, this.workdir)\n if (!commandPath) {\n logger.warn('LSP server not installed, skipping', {\n language: langId,\n command: config.serverCommand,\n sessionId: this.sessionId,\n })\n this.unavailableServers.add(langId)\n return null\n }\n \n // Create and start server with resolved command path\n const server = new LspServer(config, this.workdir, commandPath)\n \n try {\n await server.start()\n this.servers.set(langId, server)\n \n logger.debug('LSP server started for session', {\n language: langId,\n sessionId: this.sessionId,\n })\n \n return server\n } catch (error) {\n logger.warn('Failed to start LSP server', {\n language: langId,\n error: error instanceof Error ? error.message : String(error),\n sessionId: this.sessionId,\n })\n this.unavailableServers.add(langId)\n return null\n }\n }\n \n private async getServerForFile(path: string): Promise<LspServer | null> {\n const config = detectLanguage(path)\n if (!config) {\n return null\n }\n \n return this.getOrCreateServer(config)\n }\n \n // ============================================================================\n // Public Interface\n // ============================================================================\n \n /**\n * Notify LSP that a file has changed and get diagnostics.\n * This is the main entry point for tools like write_file and edit_file.\n */\n async notifyFileChange(path: string, content: string): Promise<Diagnostic[]> {\n const server = await this.getServerForFile(path)\n if (!server) {\n return []\n }\n \n try {\n // Send the change to LSP\n await server.didChange(path, content)\n \n // Wait for and return diagnostics\n const diagnostics = await server.getDiagnosticsWithWait(path)\n \n return diagnostics\n } catch (error) {\n logger.error('Error notifying LSP of file change', {\n path,\n error: error instanceof Error ? error.message : String(error),\n sessionId: this.sessionId,\n })\n return []\n }\n }\n \n /**\n * Get current diagnostics for a file without triggering a change.\n */\n getDiagnostics(path: string): Diagnostic[] {\n const config = detectLanguage(path)\n if (!config) {\n return []\n }\n \n const server = this.servers.get(config.id)\n if (!server?.isRunning()) {\n return []\n }\n \n return server.getDiagnostics(path)\n }\n \n /**\n * Check if LSP is available for a given file type.\n * Returns true if we have or can start a server for this file type.\n */\n isAvailableFor(path: string): boolean {\n const config = detectLanguage(path)\n if (!config) {\n return false\n }\n \n // Check if we know it's unavailable\n if (this.unavailableServers.has(config.id)) {\n return false\n }\n \n // We have a server or can potentially start one\n return true\n }\n \n /**\n * Shutdown all LSP servers.\n */\n async shutdown(): Promise<void> {\n const shutdownPromises: Promise<void>[] = []\n \n for (const server of this.servers.values()) {\n shutdownPromises.push(server.stop())\n }\n \n await Promise.all(shutdownPromises)\n \n this.servers.clear()\n this.unavailableServers.clear()\n this.serverPromises.clear()\n \n logger.debug('LSP manager shutdown complete', { sessionId: this.sessionId })\n }\n \n /**\n * Get status of all servers.\n */\n getStatus(): { language: string; state: string }[] {\n return Array.from(this.servers.entries()).map(([lang, server]) => ({\n language: lang,\n state: server.getState(),\n }))\n }\n}\n\n// ============================================================================\n// Session LSP Manager Registry\n// ============================================================================\n\nconst sessionManagers = new Map<string, LspManager>()\n\n/**\n * Get or create an LSP manager for a session.\n */\nexport function getLspManager(sessionId: string, workdir: string): LspManager {\n let manager = sessionManagers.get(sessionId)\n if (!manager) {\n manager = new LspManager(workdir, sessionId)\n sessionManagers.set(sessionId, manager)\n }\n return manager\n}\n\n/**\n * Shutdown and remove LSP manager for a session.\n */\nexport async function shutdownLspManager(sessionId: string): Promise<void> {\n const manager = sessionManagers.get(sessionId)\n if (manager) {\n await manager.shutdown()\n sessionManagers.delete(sessionId)\n }\n}\n\n/**\n * Shutdown all LSP managers.\n */\nexport async function shutdownAllLspManagers(): Promise<void> {\n const promises: Promise<void>[] = []\n for (const manager of sessionManagers.values()) {\n promises.push(manager.shutdown())\n }\n await Promise.all(promises)\n sessionManagers.clear()\n}\n","// Approximate token counting for pre-flight estimation\n// For English text, approximately 4 characters = 1 token\nconst CHARS_PER_TOKEN = 4\n\n// Danger zone threshold: auto-compact when < 20K tokens remaining\nexport const DANGER_ZONE_THRESHOLD = 20000\n\n// Minimum context usage before allowing compaction (20% of max)\nexport const MIN_COMPACT_THRESHOLD_RATIO = 0.20\n\n// Target context after manual compaction (20K tokens)\nexport const MANUAL_COMPACT_TARGET = 20000\n\n/**\n * Estimate tokens for a string (used for pre-flight checks only).\n * For accurate context tracking, use real promptTokens from the LLM.\n */\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / CHARS_PER_TOKEN)\n}\n\n/**\n * Check if context is in danger zone (< 20K tokens remaining).\n */\nexport function isInDangerZone(currentTokens: number, maxTokens: number): boolean {\n return (maxTokens - currentTokens) < DANGER_ZONE_THRESHOLD\n}\n\n/**\n * Check if session has enough context to warrant compaction.\n */\nexport function canCompact(currentTokens: number, maxTokens: number): boolean {\n return currentTokens > (maxTokens * MIN_COMPACT_THRESHOLD_RATIO)\n}\n\n/**\n * Pre-flight estimation: estimate the context size before sending to LLM.\n * Used to warn user or trigger compaction before context overflows.\n */\nexport interface ContextEstimate {\n estimatedTokens: number\n maxTokens: number\n percentUsed: number\n isNearLimit: boolean // > 80%\n isOverLimit: boolean // > 100%\n}\n\nexport function estimateContextSize(\n systemPrompt: string,\n messages: Array<{ role: string; content: string }>,\n maxTokens: number\n): ContextEstimate {\n // Estimate system prompt\n let total = estimateTokens(systemPrompt)\n \n // Estimate each message with overhead\n for (const msg of messages) {\n total += 4 // Message structure overhead\n total += estimateTokens(msg.content)\n }\n \n const percentUsed = Math.round((total / maxTokens) * 100)\n \n return {\n estimatedTokens: total,\n maxTokens,\n percentUsed,\n isNearLimit: percentUsed > 80,\n isOverLimit: percentUsed > 100,\n }\n}\n","/**\n * Session Manager\n *\n * Manages session lifecycle (create, delete, list) and provides access to session state.\n * All session state is derived from EventStore - this is a thin wrapper.\n *\n * State changes should go through the events/session.ts API directly,\n * not through SessionManager.\n */\n\nimport type {\n Session,\n SessionSummary,\n SessionMode,\n SessionPhase,\n Criterion,\n ContextState,\n Attachment,\n} from '../../shared/types.js'\nimport type { QueuedMessage } from '../../shared/protocol.js'\nimport {\n createSession as dbCreateSession,\n getSession as dbGetSession,\n listSessions as dbListSessions,\n listSessionsByProject as dbListSessionsByProject,\n deleteSession as dbDeleteSession,\n updateSessionSummary,\n updateSessionMetadata,\n updateSessionProvider,\n} from '../db/sessions.js'\nimport { getProject } from '../db/projects.js'\nimport { SessionNotFoundError } from '../utils/errors.js'\nimport { logger } from '../utils/logger.js'\nimport { EventEmitter, type Unsubscribe } from '../utils/async.js'\nimport { getLspManager as getOrCreateLspManager, shutdownLspManager, type LspManager } from '../lsp/index.js'\nimport { getEventStore } from '../events/store.js'\nimport {\n getSessionState,\n emitSessionInitialized,\n emitModeChanged,\n emitPhaseChanged,\n emitRunningChanged,\n emitUserMessage,\n emitAssistantMessageStart,\n emitMessageDone,\n emitCriteriaSet,\n emitCriterionUpdated,\n emitContextCompacted,\n emitContextState,\n getCurrentWindowMessages as getWindowMessages,\n type FoldedSessionState,\n} from '../events/index.js'\nimport type { Message, CriterionStatus } from '../../shared/types.js'\nimport { isInDangerZone, canCompact } from '../context/tokenizer.js'\nimport { getRuntimeConfig } from '../runtime-config.js'\n\n// ============================================================================\n// Event Types (for backward compatibility with existing subscribers)\n// ============================================================================\n\nexport type SessionEvent =\n | { type: 'session_created'; session: Session }\n | { type: 'session_updated'; session: Session }\n | { type: 'session_deleted'; sessionId: string }\n | { type: 'mode_changed'; sessionId: string; from: SessionMode; to: SessionMode }\n | { type: 'phase_changed'; sessionId: string; phase: SessionPhase }\n | { type: 'running_changed'; sessionId: string; isRunning: boolean }\n | { type: 'criteria_updated'; sessionId: string; criteria: Criterion[] }\n | { type: 'message_added'; sessionId: string; message: Message }\n\ntype SessionEvents = {\n event: [SessionEvent]\n [key: `session:${string}`]: [SessionEvent]\n}\n\n// ============================================================================\n// Session Manager\n// ============================================================================\n\nexport class SessionManager {\n private events = new EventEmitter<SessionEvents>()\n private activeSessionId: string | null = null\n\n // ============================================================================\n // Session Lifecycle\n // ============================================================================\n\n /**\n * Create a new session. Emits session.initialized event.\n */\n createSession(projectId: string, title?: string, providerId?: string | null, providerModel?: string | null): Session {\n const project = getProject(projectId)\n if (!project) {\n throw new Error(`Project not found: ${projectId}`)\n }\n\n // Auto-generate title if not provided\n let sessionTitle = title\n if (!sessionTitle) {\n const existingSessions = dbListSessionsByProject(projectId)\n sessionTitle = `Session ${existingSessions.length + 1}`\n }\n\n logger.debug('Creating session', { projectId, workdir: project.workdir, title: sessionTitle })\n\n // Create session in DB (minimal: id, projectId, workdir, title, timestamps)\n const dbSession = dbCreateSession(projectId, project.workdir, sessionTitle, providerId, providerModel)\n\n // Emit session.initialized event to EventStore\n const contextWindowId = crypto.randomUUID()\n emitSessionInitialized(dbSession.id, projectId, project.workdir, contextWindowId, sessionTitle)\n\n // Build full session object\n const session = this.buildSessionFromDb(dbSession)\n\n this.emit({ type: 'session_created', session })\n\n return session\n }\n\n /**\n * Get a session by ID. Returns null if not found.\n * Session state is derived from EventStore.\n */\n getSession(id: string): Session | null {\n const dbSession = dbGetSession(id)\n if (!dbSession) {\n return null\n }\n return this.buildSessionFromDb(dbSession)\n }\n\n /**\n * Get a session by ID. Throws if not found.\n */\n requireSession(id: string): Session {\n const session = this.getSession(id)\n if (!session) {\n throw new SessionNotFoundError(id)\n }\n return session\n }\n\n /**\n * List all sessions (summary only).\n */\n listSessions(): SessionSummary[] {\n return dbListSessions()\n }\n\n /**\n * List sessions for a project.\n */\n listSessionsByProject(projectId: string): SessionSummary[] {\n const project = getProject(projectId)\n if (!project) {\n return []\n }\n return dbListSessionsByProject(projectId)\n }\n\n /**\n * Delete a session and all its events.\n */\n deleteSession(id: string): void {\n logger.debug('Deleting session', { id })\n\n // Shutdown LSP manager\n shutdownLspManager(id).catch((err) => {\n logger.error('Error shutting down LSP manager', { sessionId: id, error: err })\n })\n\n // Delete events first\n const eventStore = getEventStore()\n eventStore.deleteSession(id)\n\n // Delete session from DB\n dbDeleteSession(id)\n\n if (this.activeSessionId === id) {\n this.activeSessionId = null\n }\n\n this.emit({ type: 'session_deleted', sessionId: id })\n }\n\n /**\n * Get a project by ID.\n */\n getProject(projectId: string) {\n return getProject(projectId)\n }\n\n /**\n * Delete all sessions for a project.\n */\n deleteAllSessions(projectId: string, workdir: string): void {\n logger.debug('Deleting all sessions for project', { projectId, workdir })\n\n const sessions = dbListSessionsByProject(projectId)\n\n sessions.forEach((session) => {\n this.deleteSession(session.id)\n })\n }\n\n // ============================================================================\n // State Changes (emit events + notify subscribers)\n // ============================================================================\n\n /**\n * Change session mode. Emits mode.changed event.\n */\n setMode(sessionId: string, toMode: SessionMode): Session {\n const session = this.requireSession(sessionId)\n const fromMode = session.mode\n\n if (fromMode === toMode) {\n return session\n }\n\n logger.debug('Changing session mode', { sessionId, from: fromMode, to: toMode })\n\n emitModeChanged(sessionId, toMode, false)\n\n const updatedSession = this.requireSession(sessionId)\n\n this.emit({ type: 'mode_changed', sessionId, from: fromMode, to: toMode })\n this.emit({ type: 'session_updated', session: updatedSession })\n\n return updatedSession\n }\n\n /**\n * Change session phase. Emits phase.changed event.\n */\n setPhase(sessionId: string, phase: SessionPhase): Session {\n const session = this.requireSession(sessionId)\n\n if (session.phase === phase) {\n return session\n }\n\n logger.debug('Changing session phase', { sessionId, from: session.phase, to: phase })\n\n emitPhaseChanged(sessionId, phase)\n\n const updatedSession = this.requireSession(sessionId)\n\n this.emit({ type: 'phase_changed', sessionId, phase })\n\n return updatedSession\n }\n\n /**\n * Set session running state. Emits running.changed event.\n */\n setRunning(sessionId: string, isRunning: boolean): Session {\n const session = this.requireSession(sessionId)\n\n if (session.isRunning === isRunning) {\n return session\n }\n\n logger.debug('Setting session running state', { sessionId, isRunning })\n\n emitRunningChanged(sessionId, isRunning)\n\n const updatedSession = this.requireSession(sessionId)\n this.emit({ type: 'session_updated', session: updatedSession })\n this.emit({ type: 'running_changed', sessionId, isRunning })\n\n return updatedSession\n }\n\n /**\n * Set session summary. Updates DB directly (metadata, not event).\n */\n setSummary(sessionId: string, summary: string): Session {\n logger.debug('Setting session summary', { sessionId, summaryLength: summary.length })\n\n updateSessionSummary(sessionId, summary)\n\n const updatedSession = this.requireSession(sessionId)\n this.emit({ type: 'session_updated', session: updatedSession })\n\n return updatedSession\n }\n\n /**\n * Set session provider/model. Updates DB directly.\n */\n setSessionProvider(sessionId: string, providerId: string | null, providerModel: string | null): Session {\n logger.debug('Setting session provider', { sessionId, providerId, providerModel })\n\n updateSessionProvider(sessionId, providerId, providerModel)\n\n const updatedSession = this.requireSession(sessionId)\n this.emit({ type: 'session_updated', session: updatedSession })\n\n return updatedSession\n }\n\n // ============================================================================\n // Session Metadata (DB operations)\n // ============================================================================\n\n /**\n * Add to the cumulative token usage.\n */\n addTokensUsed(sessionId: string, tokens: number): void {\n const session = this.requireSession(sessionId)\n updateSessionMetadata(sessionId, {\n totalTokensUsed: session.metadata.totalTokensUsed + tokens,\n })\n }\n\n /**\n * Increment tool call counter.\n */\n incrementToolCalls(sessionId: string): void {\n const session = this.requireSession(sessionId)\n updateSessionMetadata(sessionId, {\n totalToolCalls: session.metadata.totalToolCalls + 1,\n })\n }\n\n // ============================================================================\n // Message Operations (delegates to EventStore)\n // ============================================================================\n\n /**\n * Add a message. Delegates to EventStore.\n */\n addMessage(\n sessionId: string,\n message: Omit<Message, 'id' | 'timestamp'>\n ): Message {\n this.requireSession(sessionId)\n\n const state = getSessionState(sessionId)\n const contextWindowId = message.contextWindowId ?? state?.currentContextWindowId\n\n // Build options object without undefined values\n const options: {\n contextWindowId?: string\n isSystemGenerated?: boolean\n messageKind?: 'correction' | 'auto-prompt' | 'context-reset' | 'task-completed' | 'workflow-started' | 'command'\n tokenCount?: number\n attachments?: Attachment[] // Optional image attachments\n subAgentId?: string\n subAgentType?: string\n } = {}\n if (contextWindowId !== undefined) options.contextWindowId = contextWindowId\n if (message.isSystemGenerated !== undefined) options.isSystemGenerated = message.isSystemGenerated\n if (message.messageKind !== undefined) options.messageKind = message.messageKind\n if (message.tokenCount !== undefined) options.tokenCount = message.tokenCount\n if (message.attachments !== undefined) options.attachments = message.attachments\n if (message.subAgentId !== undefined) options.subAgentId = message.subAgentId\n if (message.subAgentType !== undefined) options.subAgentType = message.subAgentType\n\n // Emit message events\n const messageId = emitUserMessage(sessionId, message.content, options)\n\n // Build result without undefined values\n const result: Message = {\n id: messageId,\n role: message.role,\n content: message.content,\n timestamp: new Date().toISOString(),\n }\n if (contextWindowId !== undefined) result.contextWindowId = contextWindowId\n if (message.isSystemGenerated !== undefined) result.isSystemGenerated = message.isSystemGenerated\n if (message.messageKind !== undefined) result.messageKind = message.messageKind\n if (message.attachments !== undefined) result.attachments = message.attachments\n if (message.subAgentId !== undefined) result.subAgentId = message.subAgentId\n if (message.subAgentType !== undefined) result.subAgentType = message.subAgentType\n\n // Emit internal event for subscribers\n this.emit({ type: 'message_added', sessionId, message: result })\n\n return result\n }\n\n /**\n * Add an assistant message. Delegates to EventStore.\n */\n addAssistantMessage(\n sessionId: string,\n message: Omit<Message, 'id' | 'timestamp' | 'role'>\n ): Message {\n this.requireSession(sessionId)\n\n const state = getSessionState(sessionId)\n const contextWindowId = message.contextWindowId ?? state?.currentContextWindowId\n\n // Build options object without undefined values\n const options: {\n contextWindowId?: string\n subAgentId?: string\n subAgentType?: string\n } = {}\n if (contextWindowId !== undefined) options.contextWindowId = contextWindowId\n if (message.subAgentId !== undefined) options.subAgentId = message.subAgentId\n if (message.subAgentType !== undefined) options.subAgentType = message.subAgentType\n\n // Emit message start event\n const messageId = emitAssistantMessageStart(sessionId, options)\n\n // Build result without undefined values\n const result: Message = {\n id: messageId,\n role: 'assistant',\n content: message.content ?? '',\n timestamp: new Date().toISOString(),\n }\n if (contextWindowId !== undefined) result.contextWindowId = contextWindowId\n if (message.subAgentId !== undefined) result.subAgentId = message.subAgentId\n if (message.subAgentType !== undefined) result.subAgentType = message.subAgentType\n if (message.isStreaming !== undefined) result.isStreaming = message.isStreaming\n if (message.thinkingContent !== undefined) result.thinkingContent = message.thinkingContent\n\n // Emit internal event for subscribers\n this.emit({ type: 'message_added', sessionId, message: result })\n\n return result\n }\n\n /**\n * Update message stats. Delegates to EventStore (emits message.done if needed).\n */\n updateMessageStats(sessionId: string, messageId: string, stats: Message['stats']): void {\n this.requireSession(sessionId)\n // Stats are included in message.done event, which should already have been emitted\n // This is a no-op in the new model - stats come from LLM streaming\n logger.debug('updateMessageStats called (no-op in event model)', { sessionId, messageId })\n }\n\n /**\n * Update a message. Delegates to EventStore.\n */\n updateMessage(\n sessionId: string,\n messageId: string,\n updates: Partial<Omit<Message, 'id' | 'timestamp' | 'role'>>\n ): void {\n this.requireSession(sessionId)\n // In the event model, messages are immutable after message.done\n // Some updates like isCompactionSummary should be set in message.start\n logger.debug('updateMessage called (limited support in event model)', { sessionId, messageId, updates })\n }\n\n /**\n * Get messages for the current context window.\n */\n getCurrentWindowMessages(sessionId: string): Message[] {\n const state = getSessionState(sessionId)\n if (!state) return []\n\n return state.messages\n .filter((m) => m.contextWindowId === state.currentContextWindowId)\n .map((m) => {\n const msg: Message = {\n id: m.id,\n role: m.role,\n content: m.content,\n timestamp: new Date(m.timestamp).toISOString(),\n }\n if (m.thinkingContent !== undefined) msg.thinkingContent = m.thinkingContent\n if (m.toolCalls !== undefined) msg.toolCalls = m.toolCalls\n if (m.segments !== undefined) msg.segments = m.segments\n if (m.stats !== undefined) msg.stats = m.stats\n if (m.partial !== undefined) msg.partial = m.partial\n if (m.isStreaming !== undefined) msg.isStreaming = m.isStreaming\n if (m.contextWindowId !== undefined) msg.contextWindowId = m.contextWindowId\n if (m.isSystemGenerated !== undefined) msg.isSystemGenerated = m.isSystemGenerated\n if (m.messageKind !== undefined) msg.messageKind = m.messageKind\n if (m.isCompactionSummary !== undefined) msg.isCompactionSummary = m.isCompactionSummary\n if (m.promptContext !== undefined) msg.promptContext = m.promptContext\n return msg\n })\n }\n\n /**\n * Compact context. Delegates to EventStore.\n */\n compactContext(sessionId: string, summary: string, tokenCountAtClose: number): void {\n const state = getSessionState(sessionId)\n if (!state) {\n throw new Error('Session not found')\n }\n\n const closedWindowId = state.currentContextWindowId\n const newWindowId = crypto.randomUUID()\n\n emitContextCompacted(sessionId, closedWindowId, newWindowId, tokenCountAtClose, 0, summary)\n emitUserMessage(sessionId, `Previous context summary:\\n${summary}`, {\n contextWindowId: newWindowId,\n isSystemGenerated: true,\n messageKind: 'auto-prompt',\n isCompactionSummary: true,\n })\n }\n\n /**\n * Set current context size (for token tracking).\n * Emits a context.state event with the real promptTokens from the LLM.\n */\n setCurrentContextSize(sessionId: string, promptTokens: number): void {\n const config = getRuntimeConfig()\n const maxTokens = config.context.maxTokens\n const state = getSessionState(sessionId)\n const compactionCount = state?.contextState.compactionCount ?? 0\n\n emitContextState(\n sessionId,\n promptTokens,\n maxTokens,\n compactionCount,\n isInDangerZone(promptTokens, maxTokens),\n canCompact(promptTokens, maxTokens)\n )\n\n logger.debug('Context state updated', { sessionId, promptTokens, maxTokens })\n }\n\n // ============================================================================\n // Criteria Operations (delegates to EventStore)\n // ============================================================================\n\n /**\n * Set criteria. Delegates to EventStore.\n */\n setCriteria(sessionId: string, criteria: Criterion[]): void {\n this.requireSession(sessionId)\n emitCriteriaSet(sessionId, criteria)\n this.emit({ type: 'criteria_updated', sessionId, criteria })\n }\n\n /**\n * Update criterion status. Delegates to EventStore.\n */\n updateCriterionStatus(sessionId: string, criterionId: string, status: CriterionStatus): void {\n this.requireSession(sessionId)\n emitCriterionUpdated(sessionId, criterionId, status)\n }\n\n /**\n * Reset all criteria verification attempts.\n */\n resetAllCriteriaAttempts(sessionId: string): void {\n const state = getSessionState(sessionId)\n if (!state) return\n\n // Reset attempts by re-emitting criteria with cleared attempts\n const resetCriteria = state.criteria.map((c) => ({\n ...c,\n attempts: [],\n }))\n emitCriteriaSet(sessionId, resetCriteria)\n }\n\n /**\n * Add a criterion attempt.\n */\n addCriterionAttempt(\n sessionId: string,\n criterionId: string,\n attempt: Criterion['attempts'][number]\n ): void {\n const state = getSessionState(sessionId)\n if (!state) return\n\n const criterion = state.criteria.find((c) => c.id === criterionId)\n if (!criterion) {\n throw new Error(`Criterion not found: ${criterionId}`)\n }\n\n // Re-emit criteria with new attempt added\n const updatedCriteria = state.criteria.map((c) =>\n c.id === criterionId\n ? { ...c, attempts: [...c.attempts, attempt] }\n : c\n )\n emitCriteriaSet(sessionId, updatedCriteria)\n }\n\n // ============================================================================\n // Execution State (runtime tracking, not persisted to events)\n // ============================================================================\n\n /**\n * Record that a file was modified.\n */\n addModifiedFile(sessionId: string, filePath: string): void {\n // In event model, this could be tracked via file.modified events\n // For now, this is a no-op - modifications are tracked per-tool\n logger.debug('addModifiedFile called', { sessionId, filePath })\n }\n\n /**\n * Add a criterion. Returns the updated criteria list.\n */\n addCriterion(sessionId: string, criterion: Criterion): { criteria: Criterion[]; actualId: string } | { error: string } {\n const state = getSessionState(sessionId)\n if (!state) {\n return { error: 'Session not found' }\n }\n\n // If ID already exists, generate a unique one\n let actualId = criterion.id\n if (state.criteria.some((c) => c.id === criterion.id)) {\n let suffix = 1\n while (state.criteria.some((c) => c.id === `${criterion.id}-${suffix}`)) {\n suffix++\n }\n actualId = `${criterion.id}-${suffix}`\n }\n\n const updatedCriteria = [...state.criteria, { ...criterion, id: actualId }]\n emitCriteriaSet(sessionId, updatedCriteria)\n\n return { criteria: updatedCriteria, actualId }\n }\n\n /**\n * Update criterion description.\n */\n updateCriterionFull(\n sessionId: string,\n criterionId: string,\n updates: Partial<Pick<Criterion, 'description'>>\n ): Criterion[] {\n const state = getSessionState(sessionId)\n if (!state) {\n throw new Error('Session not found')\n }\n\n if (!state.criteria.find((c) => c.id === criterionId)) {\n throw new Error(`Criterion not found: ${criterionId}`)\n }\n\n const updatedCriteria = state.criteria.map((c) =>\n c.id === criterionId ? { ...c, ...updates } : c\n )\n emitCriteriaSet(sessionId, updatedCriteria)\n\n return updatedCriteria\n }\n\n /**\n * Remove a criterion.\n */\n removeCriterion(sessionId: string, criterionId: string): Criterion[] {\n const state = getSessionState(sessionId)\n if (!state) {\n throw new Error('Session not found')\n }\n\n if (!state.criteria.find((c) => c.id === criterionId)) {\n throw new Error(`Criterion not found: ${criterionId}`)\n }\n\n const updatedCriteria = state.criteria.filter((c) => c.id !== criterionId)\n emitCriteriaSet(sessionId, updatedCriteria)\n\n return updatedCriteria\n }\n\n // ============================================================================\n // Message Queue (runtime state, transient while agent is running)\n // ============================================================================\n\n private messageQueues = new Map<string, QueuedMessage[]>()\n\n queueMessage(sessionId: string, mode: 'asap' | 'completion', content: string, attachments?: Attachment[]): QueuedMessage {\n const queue = this.messageQueues.get(sessionId) ?? []\n const msg: QueuedMessage = {\n queueId: crypto.randomUUID(),\n mode,\n content,\n ...(attachments ? { attachments } : {}),\n queuedAt: new Date().toISOString(),\n }\n queue.push(msg)\n this.messageQueues.set(sessionId, queue)\n return msg\n }\n\n cancelQueuedMessage(sessionId: string, queueId: string): boolean {\n const queue = this.messageQueues.get(sessionId)\n if (!queue) return false\n const idx = queue.findIndex(m => m.queueId === queueId)\n if (idx === -1) return false\n queue.splice(idx, 1)\n return true\n }\n\n drainAsapMessages(sessionId: string): QueuedMessage[] {\n const queue = this.messageQueues.get(sessionId)\n if (!queue) return []\n const asap = queue.filter(m => m.mode === 'asap')\n this.messageQueues.set(sessionId, queue.filter(m => m.mode !== 'asap'))\n return asap\n }\n\n drainCompletionMessages(sessionId: string): QueuedMessage[] {\n const queue = this.messageQueues.get(sessionId)\n if (!queue) return []\n const completion = queue.filter(m => m.mode === 'completion')\n this.messageQueues.set(sessionId, queue.filter(m => m.mode !== 'completion'))\n return completion\n }\n\n getQueueState(sessionId: string): QueuedMessage[] {\n return this.messageQueues.get(sessionId) ?? []\n }\n\n clearMessageQueue(sessionId: string): void {\n this.messageQueues.delete(sessionId)\n }\n\n // ============================================================================\n // File Tracking (runtime state, stored in memory per session)\n // ============================================================================\n\n private readFilesCache = new Map<string, Record<string, { hash: string; readAt: string }>>()\n\n /**\n * Record that a file was read.\n */\n recordFileRead(sessionId: string, filePath: string, contentHash: string): void {\n const cache = this.readFilesCache.get(sessionId) ?? {}\n cache[filePath] = { hash: contentHash, readAt: new Date().toISOString() }\n this.readFilesCache.set(sessionId, cache)\n }\n\n /**\n * Get read files cache.\n */\n getReadFiles(sessionId: string): Record<string, { hash: string; readAt: string }> {\n return this.readFilesCache.get(sessionId) ?? {}\n }\n\n /**\n * Update file hash after write.\n */\n updateFileHash(sessionId: string, filePath: string, contentHash: string): void {\n const cache = this.readFilesCache.get(sessionId) ?? {}\n const existingEntry = cache[filePath]\n cache[filePath] = {\n hash: contentHash,\n readAt: existingEntry?.readAt ?? new Date().toISOString(),\n }\n this.readFilesCache.set(sessionId, cache)\n }\n\n /**\n * Record a tool failure.\n */\n recordToolFailure(sessionId: string, tool: string, reason: string): void {\n // In event model, this could be tracked via events\n // For now, log it\n logger.debug('recordToolFailure called', { sessionId, tool, reason })\n }\n\n /**\n * Reset tool failures.\n */\n resetToolFailures(sessionId: string): void {\n logger.debug('resetToolFailures called', { sessionId })\n }\n\n /**\n * Update execution state.\n */\n updateExecutionState(sessionId: string, updates: Record<string, unknown>): void {\n // In event model, execution state is derived from events\n logger.debug('updateExecutionState called', { sessionId, updates })\n }\n\n /**\n * @deprecated Use addMessage + compactContext instead\n */\n compactMessages(sessionId: string, _messageIds: string[], summary: string): Message {\n // Emit a system message with the compacted summary\n const messageId = emitUserMessage(sessionId, `[COMPACTED HISTORY]\\n${summary}`, {\n isSystemGenerated: true,\n })\n\n return {\n id: messageId,\n role: 'system',\n content: `[COMPACTED HISTORY]\\n${summary}`,\n timestamp: new Date().toISOString(),\n isCompacted: true,\n }\n }\n\n /**\n * @deprecated Use addTokensUsed instead\n */\n incrementTokenCount(sessionId: string, tokens: number): void {\n this.addTokensUsed(sessionId, tokens)\n }\n\n // ============================================================================\n // Context State\n // ============================================================================\n\n /**\n * Get the current context state for a session.\n */\n getContextState(sessionId: string): ContextState {\n const state = getSessionState(sessionId)\n if (!state) {\n const config = getRuntimeConfig()\n return {\n currentTokens: 0,\n maxTokens: config.context.maxTokens,\n compactionCount: 0,\n dangerZone: false,\n canCompact: false,\n }\n }\n return state.contextState\n }\n\n // ============================================================================\n // LSP Manager\n // ============================================================================\n\n /**\n * Get the LSP manager for a session.\n */\n getLspManager(sessionId: string): LspManager {\n const session = this.requireSession(sessionId)\n return getOrCreateLspManager(sessionId, session.workdir)\n }\n\n // ============================================================================\n // Active Session\n // ============================================================================\n\n setActiveSession(id: string | null): void {\n this.activeSessionId = id\n }\n\n getActiveSessionId(): string | null {\n return this.activeSessionId\n }\n\n // ============================================================================\n // Event Subscription\n // ============================================================================\n\n subscribe(callback: (event: SessionEvent) => void): Unsubscribe {\n return this.events.on('event', callback)\n }\n\n subscribeToSession(sessionId: string, callback: (event: SessionEvent) => void): Unsubscribe {\n return this.events.on(`session:${sessionId}`, callback)\n }\n\n private emit(event: SessionEvent): void {\n this.events.emit('event', event)\n\n if ('sessionId' in event) {\n this.events.emit(`session:${event.sessionId}`, event)\n } else if ('session' in event) {\n this.events.emit(`session:${event.session.id}`, event)\n }\n }\n\n // ============================================================================\n // Private Helpers\n // ============================================================================\n\n /**\n * Build a full Session object from DB session + EventStore state\n */\n private buildSessionFromDb(dbSession: Session): Session {\n const eventState = getSessionState(dbSession.id)\n\n if (!eventState) {\n // No events yet - return defaults\n return {\n ...dbSession,\n mode: 'planner',\n phase: 'plan',\n isRunning: false,\n messages: [],\n criteria: [],\n contextWindows: [],\n executionState: null,\n }\n }\n\n // Map SnapshotMessage[] to Message[]\n const messages = eventState.messages.map((m) => {\n const msg: import('../../shared/types.js').Message = {\n id: m.id,\n role: m.role,\n content: m.content,\n timestamp: new Date(m.timestamp).toISOString(),\n }\n if (m.thinkingContent !== undefined) msg.thinkingContent = m.thinkingContent\n if (m.toolCalls !== undefined) msg.toolCalls = m.toolCalls\n if (m.segments !== undefined) msg.segments = m.segments\n if (m.stats !== undefined) msg.stats = m.stats\n if (m.partial !== undefined) msg.partial = m.partial\n if (m.isStreaming !== undefined) msg.isStreaming = m.isStreaming\n if (m.subAgentId !== undefined) msg.subAgentId = m.subAgentId\n if (m.subAgentType !== undefined) msg.subAgentType = m.subAgentType\n if (m.isSystemGenerated !== undefined) msg.isSystemGenerated = m.isSystemGenerated\n if (m.messageKind !== undefined) msg.messageKind = m.messageKind\n if (m.contextWindowId !== undefined) msg.contextWindowId = m.contextWindowId\n if (m.isCompactionSummary !== undefined) msg.isCompactionSummary = m.isCompactionSummary\n if (m.promptContext !== undefined) msg.promptContext = m.promptContext\n return msg\n })\n\n return {\n ...dbSession,\n mode: eventState.mode,\n phase: eventState.phase,\n isRunning: eventState.isRunning,\n messages,\n criteria: eventState.criteria,\n contextWindows: [], // Derived from events, not stored separately\n executionState: null, // No longer using execution state\n }\n }\n}\n\n// Singleton for gradual migration\nexport const sessionManager = new SessionManager()\n","/**\n * Command Registry\n *\n * Discovers, loads, and manages commands from the commands directory.\n */\n\nimport { readdir, readFile, writeFile, copyFile, mkdir, access, unlink } from 'node:fs/promises'\nimport { join, dirname } from 'node:path'\nimport { constants } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport matter from 'gray-matter'\nimport type { CommandDefinition, CommandMetadata } from './types.js'\nimport { logger } from '../utils/logger.js'\n\nconst __bundleDir = dirname(fileURLToPath(import.meta.url))\nconst DEFAULTS_DIR = join(__bundleDir, 'defaults')\nconst DEFAULTS_DIR_ALT = join(__bundleDir, 'command-defaults')\nconst COMMAND_EXTENSION = '.command.md'\n\n// ============================================================================\n// Directory Helpers\n// ============================================================================\n\nfunction getCommandsDir(configDir: string): string {\n return join(configDir, 'commands')\n}\n\nasync function dirExists(path: string): Promise<boolean> {\n try {\n await access(path, constants.R_OK)\n return true\n } catch {\n return false\n }\n}\n\n// ============================================================================\n// Default Commands Installation\n// ============================================================================\n\n/**\n * Copy bundled default commands to the config commands directory if they don't already exist.\n */\nexport async function ensureDefaultCommands(configDir: string): Promise<void> {\n const commandsDir = getCommandsDir(configDir)\n\n if (!await dirExists(commandsDir)) {\n await mkdir(commandsDir, { recursive: true })\n }\n\n // Find bundled defaults (try dev path first, then production path)\n let defaultFiles: string[]\n let sourceDir: string\n try {\n defaultFiles = (await readdir(DEFAULTS_DIR)).filter(f => f.endsWith(COMMAND_EXTENSION))\n sourceDir = DEFAULTS_DIR\n } catch {\n try {\n defaultFiles = (await readdir(DEFAULTS_DIR_ALT)).filter(f => f.endsWith(COMMAND_EXTENSION))\n sourceDir = DEFAULTS_DIR_ALT\n } catch {\n logger.warn('No bundled command defaults found', { dir: DEFAULTS_DIR })\n return\n }\n }\n\n for (const file of defaultFiles) {\n const targetPath = join(commandsDir, file)\n if (!await dirExists(targetPath)) {\n try {\n await copyFile(join(sourceDir, file), targetPath)\n logger.info('Installed default command', { file })\n } catch (err) {\n logger.error('Failed to copy default command', { file, error: err instanceof Error ? err.message : String(err) })\n }\n }\n }\n}\n\n// ============================================================================\n// Command Loading\n// ============================================================================\n\n/**\n * Load all commands from the commands directory.\n */\nexport async function loadAllCommands(configDir: string): Promise<CommandDefinition[]> {\n const commandsDir = getCommandsDir(configDir)\n\n if (!await dirExists(commandsDir)) {\n return []\n }\n\n let files: string[]\n try {\n files = (await readdir(commandsDir)).filter(f => f.endsWith(COMMAND_EXTENSION))\n } catch {\n return []\n }\n\n const commands: CommandDefinition[] = []\n for (const file of files) {\n try {\n const raw = await readFile(join(commandsDir, file), 'utf-8')\n const { data, content } = matter(raw)\n const metadata = data as CommandMetadata\n if (metadata.id && content.trim()) {\n commands.push({ metadata, prompt: content.trim() })\n } else {\n logger.warn('Skipping invalid command file', { file })\n }\n } catch (err) {\n logger.warn('Failed to parse command file', { file, error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n return commands\n}\n\n// ============================================================================\n// Default Restoration\n// ============================================================================\n\n/**\n * Get the list of command IDs that have bundled defaults.\n */\nexport async function getDefaultCommandIds(): Promise<string[]> {\n for (const dir of [DEFAULTS_DIR, DEFAULTS_DIR_ALT]) {\n try {\n const files = (await readdir(dir)).filter(f => f.endsWith(COMMAND_EXTENSION))\n return files.map(f => f.replace(COMMAND_EXTENSION, ''))\n } catch { /* try next */ }\n }\n return []\n}\n\n/**\n * Restore a single command to its bundled default by re-copying from defaults.\n */\nexport async function restoreDefaultCommand(configDir: string, commandId: string): Promise<boolean> {\n const filename = `${commandId}${COMMAND_EXTENSION}`\n for (const dir of [DEFAULTS_DIR, DEFAULTS_DIR_ALT]) {\n const sourcePath = join(dir, filename)\n if (await dirExists(sourcePath)) {\n const targetPath = join(getCommandsDir(configDir), filename)\n await copyFile(sourcePath, targetPath)\n return true\n }\n }\n return false\n}\n\n/**\n * Return the IDs of default commands whose user copy differs from the bundled version.\n */\nexport async function getModifiedDefaultCommandIds(configDir: string): Promise<string[]> {\n const defaultIds = await getDefaultCommandIds()\n const modified: string[] = []\n\n for (const id of defaultIds) {\n const filename = `${id}${COMMAND_EXTENSION}`\n const userPath = join(getCommandsDir(configDir), filename)\n\n let bundledContent: string | null = null\n for (const dir of [DEFAULTS_DIR, DEFAULTS_DIR_ALT]) {\n try {\n bundledContent = await readFile(join(dir, filename), 'utf-8')\n break\n } catch { /* try next */ }\n }\n if (!bundledContent) continue\n\n try {\n const userContent = await readFile(userPath, 'utf-8')\n if (userContent !== bundledContent) {\n modified.push(id)\n }\n } catch {\n // User file doesn't exist\n }\n }\n\n return modified\n}\n\n/**\n * Restore all commands to their bundled defaults.\n */\nexport async function restoreAllDefaultCommands(configDir: string): Promise<number> {\n const ids = await getDefaultCommandIds()\n let count = 0\n for (const id of ids) {\n if (await restoreDefaultCommand(configDir, id)) count++\n }\n return count\n}\n\n// ============================================================================\n// Command Lookup\n// ============================================================================\n\n/**\n * Find a command by ID from a list of loaded commands.\n */\nexport function findCommandById(commandId: string, commands: CommandDefinition[]): CommandDefinition | undefined {\n return commands.find(c => c.metadata.id === commandId)\n}\n\n// ============================================================================\n// Command CRUD\n// ============================================================================\n\n/**\n * Check if a command file exists.\n */\nexport async function commandExists(configDir: string, commandId: string): Promise<boolean> {\n const filePath = join(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`)\n return dirExists(filePath)\n}\n\n/**\n * Save a command definition to disk.\n */\nexport async function saveCommand(configDir: string, command: CommandDefinition): Promise<void> {\n const commandsDir = getCommandsDir(configDir)\n if (!await dirExists(commandsDir)) {\n await mkdir(commandsDir, { recursive: true })\n }\n const filePath = join(commandsDir, `${command.metadata.id}${COMMAND_EXTENSION}`)\n const content = matter.stringify(command.prompt, command.metadata)\n await writeFile(filePath, content, 'utf-8')\n}\n\n/**\n * Delete a command from disk.\n */\nexport async function deleteCommand(configDir: string, commandId: string): Promise<boolean> {\n const filePath = join(getCommandsDir(configDir), `${commandId}${COMMAND_EXTENSION}`)\n try {\n await unlink(filePath)\n return true\n } catch {\n return false\n }\n}\n"],"mappings":"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","names":["fileURLToPath","dirname","join","readFile","toolCalls","sessionManager","errorMsgId","sessionManager","resolve","getCurrentWindowMessageOptions","sessionManager","getCurrentWindowMessageOptions","resolveStatsIdentity","sessionManager","events","spawn","spawn","resolve","access","constants","join","dirname","fileURLToPath","extname","readdir","readFile","writeFile","copyFile","mkdir","access","unlink","join","dirname","constants","fileURLToPath","__bundleDir","dirname","fileURLToPath","DEFAULTS_DIR","join","DEFAULTS_DIR_ALT","access","constants","mkdir","readdir","copyFile","readFile","writeFile","unlink","__dirname","dirname","fileURLToPath","sessionManager","useMock","join","basename","readFile","resolve"]}
|