@wrongstack/webui 0.8.5 → 0.8.6
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/assets/{index-DjDDhHNu.js → index-B5qzSV8A.js} +25 -25
- package/dist/assets/index-BTevO8Vz.css +1 -0
- package/dist/index.css +117 -0
- package/dist/index.css.map +1 -1
- package/dist/index.html +2 -2
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -1
- package/dist/server/entry.js +183 -9
- package/dist/server/entry.js.map +1 -1
- package/dist/server/index.js +183 -9
- package/dist/server/index.js.map +1 -1
- package/package.json +5 -5
- package/dist/assets/index-aTQFIbqW.css +0 -1
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/server/index.ts","../../../runtime/src/container.ts","../../src/server/boot.ts","../../src/server/autophase-ws-handler.ts"],"sourcesContent":["import * as fs from 'node:fs/promises';\r\nimport * as http from 'node:http';\r\nimport * as os from 'node:os';\r\nimport * as path from 'node:path';\r\nimport {\r\n Agent,\r\n AutoCompactionMiddleware,\r\n type Config,\r\n Container,\r\n Context,\r\n DefaultConfigLoader,\r\n DefaultConfigStore,\r\n DefaultErrorHandler,\r\n DefaultLogger,\r\n DefaultMemoryStore,\r\n DefaultModeStore,\r\n DefaultModelsRegistry,\r\n DefaultPathResolver,\r\n DefaultPermissionPolicy,\r\n DefaultRetryPolicy,\r\n DefaultSecretScrubber,\r\n DefaultSecretVault,\r\n DefaultSessionStore,\r\n DefaultSkillLoader,\r\n DefaultSystemPromptBuilder,\r\n DefaultTokenCounter,\r\n estimateRequestTokens,\r\n EventBus,\r\n HybridCompactor,\r\n type ProviderApiKey,\r\n type ProviderConfig,\r\n type Provider,\r\n ProviderRegistry,\r\n TOKENS,\r\n ToolRegistry,\r\n type WstackPaths,\r\n atomicWrite,\r\n createDefaultPipelines,\r\n DEFAULT_CONTEXT_WINDOW_MODE_ID,\r\n DEFAULT_TOOLS_CONFIG,\r\n migratePlaintextSecrets,\r\n resolveWstackPaths,\r\n listContextWindowModes,\r\n repairToolUseAdjacency,\r\n resolveContextWindowPolicy,\r\n} from '@wrongstack/core';\r\nimport { ToolExecutor } from '@wrongstack/core/execution';\r\nimport { decryptConfigSecrets, encryptConfigSecrets } from '@wrongstack/core/security';\r\nimport { buildProviderFactoriesFromRegistry, makeProviderFromConfig } from '@wrongstack/providers';\r\nimport { builtinToolsPack, forgetTool, rememberTool } from '@wrongstack/tools';\r\nimport { WebSocket, WebSocketServer } from 'ws';\r\nimport { randomBytes, timingSafeEqual } from 'node:crypto';\r\nimport { createDefaultContainer } from '../../../runtime/src/container.js';\r\nimport { bootConfig, patchConfig, type BootResult } from './boot.js';\r\nimport { AutoPhaseWebSocketHandler } from './autophase-ws-handler.js';\r\n\r\n// Re-export types\r\nexport type { WebUIOptions, BackendServices } from './types.js';\r\n\r\n// CSP for served HTML. script-src is 'self' only — the production bundle has no\r\n// inline scripts, so 'unsafe-inline' is dropped (defeats injected-script XSS).\r\n// style-src keeps 'unsafe-inline' because Radix/React inject inline styles at\r\n// runtime. object-src/base-uri/frame-ancestors/form-action are tightened as\r\n// defense-in-depth (frame-ancestors complements X-Frame-Options: DENY).\r\nconst HTML_CSP =\r\n \"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' ws: wss:; img-src 'self' data:; font-src 'self' data:; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; form-action 'self'\";\r\n\r\n// Internal message types\r\ninterface WSServerMessage {\r\n type: string;\r\n payload: unknown;\r\n}\r\n\r\ninterface WSClientMessage {\r\n type: string;\r\n payload?: unknown;\r\n}\r\n\r\ninterface ConnectedClient {\r\n ws: WebSocket;\r\n sessionId: string | null;\r\n connectedAt: number;\r\n}\r\n\r\nexport async function startWebUI(opts: { wsPort?: number; wsHost?: string } = {}): Promise<void> {\r\n const wsPort = opts.wsPort ?? 3457;\r\n // Bind to loopback IP by default (not the string \"localhost\", which on some\r\n // hosts resolves to IPv6 ::1 and surprises older WS clients). Set WS_HOST or\r\n // pass opts.wsHost to override (e.g. \"0.0.0.0\" for LAN access).\r\n const wsHost = opts.wsHost ?? '127.0.0.1';\r\n\r\n console.log('[WebUI] Starting backend services...');\r\n\r\n // Boot configuration\r\n const boot = await bootConfig();\r\n const { config: baseConfig, vault, globalConfigPath, projectRoot, wpaths, logger } = boot;\r\n let config = baseConfig;\r\n\r\n // Serialize concurrent config writes to prevent races between model.switch\r\n // and key.add/key.update handlers that both read-modify-write globalConfigPath.\r\n let configWriteLock: Promise<void> = Promise.resolve();\r\n\r\n console.log('[WebUI] Config loaded:', config.provider ?? '(none)', '/', config.model ?? '(none)');\r\n\r\n // If no active provider is set but there are saved providers, pick the first one.\r\n // This handles configs written in older formats or by external tools.\r\n if (!config.provider && config.providers && Object.keys(config.providers).length > 0) {\r\n const firstKey = Object.keys(config.providers)[0]!;\r\n config = patchConfig(config, { provider: firstKey });\r\n console.log('[WebUI] No active provider — auto-selected:', firstKey);\r\n }\r\n\r\n // If still no provider, the frontend will show a no-provider welcome screen.\r\n // We still start the HTTP/WS servers so the user can configure via the UI.\r\n const needsProvider = !config.provider || !config.model;\r\n\r\n // ModelsRegistry\r\n const modelsRegistry = new DefaultModelsRegistry({\r\n cacheFile: wpaths.modelsCache,\r\n ttlSeconds: 24 * 3600,\r\n });\r\n\r\n // Container via shared factory\r\n const container = createDefaultContainer({ config, wpaths, logger, modelsRegistry });\r\n const configStore = container.resolve(TOKENS.ConfigStore);\r\n\r\n // Provider registry\r\n const providerRegistry = new ProviderRegistry();\r\n try {\r\n const factories = await buildProviderFactoriesFromRegistry({\r\n registry: modelsRegistry,\r\n log: logger,\r\n });\r\n for (const f of factories) providerRegistry.register(f);\r\n console.log('[WebUI] Provider registry loaded:', providerRegistry.list().length, 'providers');\r\n } catch (err) {\r\n console.warn('[WebUI] Failed to load provider registry:', err);\r\n }\r\n\r\n // Tool registry\r\n const toolRegistry = new ToolRegistry();\r\n toolRegistry.registerAllOrThrow([...(builtinToolsPack.tools ?? [])], builtinToolsPack.name);\r\n\r\n // Memory tools\r\n const memoryStore = new DefaultMemoryStore({ paths: wpaths });\r\n if (config.features.memory) {\r\n toolRegistry.register(rememberTool(memoryStore));\r\n toolRegistry.register(forgetTool(memoryStore));\r\n }\r\n console.log('[WebUI] Tool registry loaded:', toolRegistry.list().length, 'tools');\r\n\r\n // Event bus\r\n const events = new EventBus();\r\n events.setLogger(logger);\r\n\r\n // Session store\r\n const sessionStore = new DefaultSessionStore({ dir: wpaths.projectSessions });\r\n let session = await sessionStore.create({\r\n id: '',\r\n title: '',\r\n model: config.model,\r\n provider: config.provider,\r\n });\r\n // Wall-clock when the *current* session started. Updated on /new and on\r\n // /resume so /stats can report accurate elapsed time per the active\r\n // session, not the daemon process uptime.\r\n let sessionStartedAt = Date.now();\r\n console.log('[WebUI] Session created:', session.id);\r\n\r\n // Token counter\r\n const tokenCounter = new DefaultTokenCounter({\r\n registry: modelsRegistry,\r\n providerId: config.provider,\r\n });\r\n\r\n // Mode store\r\n const modeStore = new DefaultModeStore({ directory: wpaths.configDir });\r\n const activeMode = await modeStore.getActiveMode();\r\n let modeId = activeMode?.id ?? 'default';\r\n const modePrompt = activeMode?.prompt ?? '';\r\n\r\n // System prompt builder\r\n const resolvedModel = await modelsRegistry.getModel(config.provider, config.model);\r\n const modelCapabilities = resolvedModel?.capabilities\r\n ? {\r\n maxContextTokens: resolvedModel.capabilities.maxContext,\r\n supportsTools: resolvedModel.capabilities.tools,\r\n supportsVision: resolvedModel.capabilities.vision,\r\n supportsReasoning: resolvedModel.capabilities.reasoning,\r\n }\r\n : undefined;\r\n\r\n const skillLoader = config.features.skills\r\n ? new DefaultSkillLoader({ paths: wpaths })\r\n : undefined;\r\n const systemPromptBuilder = new DefaultSystemPromptBuilder({\r\n memoryStore,\r\n skillLoader,\r\n modeStore,\r\n modeId,\r\n modePrompt,\r\n modelCapabilities,\r\n });\r\n\r\n const systemPrompt = await systemPromptBuilder.build({\r\n cwd: projectRoot,\r\n projectRoot,\r\n tools: toolRegistry.list(),\r\n provider: config.provider,\r\n model: config.model,\r\n });\r\n\r\n // Build provider (only if provider is configured)\r\n let provider: ReturnType<ProviderRegistry['create']>;\r\n if (!needsProvider) {\r\n const providerConfig = config.providers?.[config.provider] ?? {\r\n type: config.provider,\r\n apiKey: config.apiKey,\r\n baseUrl: config.baseUrl,\r\n };\r\n try {\r\n const cfgWithType = { ...providerConfig, type: config.provider };\r\n if (config.features.modelsRegistry && providerRegistry.has(config.provider)) {\r\n provider = providerRegistry.create(cfgWithType);\r\n } else {\r\n provider = makeProviderFromConfig(config.provider, cfgWithType);\r\n }\r\n } catch (err) {\r\n console.error('[WebUI] Failed to create provider:', err);\r\n throw err;\r\n }\r\n } else {\r\n // No provider is actively selected, but saved providers exist.\r\n // Re-read the config to find one with a usable encrypted API key\r\n // and create a real provider from it (the vault is already initialized).\r\n const savedProviders = config.providers ?? {};\r\n const firstKey = Object.keys(savedProviders)[0];\r\n if (firstKey) {\r\n const firstProvider = savedProviders[firstKey]!;\r\n try {\r\n provider = makeProviderFromConfig(firstKey, {\r\n ...firstProvider,\r\n type: firstKey,\r\n family: firstProvider.family,\r\n apiKey: firstProvider.apiKey,\r\n });\r\n console.log('[WebUI] Using saved provider:', firstKey);\r\n } catch (err) {\r\n console.error('[WebUI] Could not create provider stub:', err);\r\n throw err;\r\n }\r\n } else {\r\n throw new Error(\r\n 'No provider configured. Run `wrongstack init` first, or configure via the WebUI.',\r\n );\r\n }\r\n }\r\n\r\n // Context\r\n const context = new Context({\r\n systemPrompt,\r\n provider,\r\n session,\r\n signal: new AbortController().signal,\r\n tokenCounter,\r\n cwd: projectRoot,\r\n projectRoot,\r\n model: config.model,\r\n });\r\n const initialContextPolicy = resolveContextWindowPolicy(config.context);\r\n context.meta['contextWindowMode'] = initialContextPolicy.id;\r\n context.meta['contextWindowPolicy'] = initialContextPolicy;\r\n\r\n // Pipelines\r\n const pipelines = createDefaultPipelines();\r\n\r\n // Compactor\r\n const compactor = new HybridCompactor({\r\n preserveK: config.context?.preserveK ?? 20,\r\n eliseThreshold: config.context?.eliseThreshold ?? 0.7,\r\n });\r\n\r\n // Auto-compaction\r\n let autoCompactor: AutoCompactionMiddleware | undefined;\r\n if (config.context?.autoCompact !== false) {\r\n const effectiveMaxContext = config.context?.effectiveMaxContext ?? provider.capabilities.maxContext;\r\n autoCompactor = new AutoCompactionMiddleware(\r\n compactor,\r\n effectiveMaxContext,\r\n (ctx) => estimateRequestTokens(ctx.messages, ctx.systemPrompt, ctx.tools ?? []).total,\r\n {\r\n warn: initialContextPolicy.thresholds.warn,\r\n soft: initialContextPolicy.thresholds.soft,\r\n hard: initialContextPolicy.thresholds.hard,\r\n },\r\n {\r\n events,\r\n aggressiveOn: initialContextPolicy.aggressiveOn,\r\n policyProvider: (ctx) => {\r\n const policy = ctx.meta['contextWindowPolicy'];\r\n return policy && typeof policy === 'object'\r\n ? (policy as ReturnType<typeof resolveContextWindowPolicy>)\r\n : initialContextPolicy;\r\n },\r\n },\r\n );\r\n pipelines.contextWindow.use({ name: 'AutoCompaction', handler: autoCompactor.handler() });\r\n }\r\n\r\n /** Refresh AutoCompactionMiddleware denominator when the active model changes. */\r\n async function updateAutoCompactionMaxContext(newProvider: Provider): Promise<void> {\r\n if (!autoCompactor) return;\r\n let newMaxContext = config.context?.effectiveMaxContext ?? newProvider.capabilities.maxContext;\r\n try {\r\n const m = await modelsRegistry.getModel(newProvider.id, context.model);\r\n newMaxContext = m?.capabilities?.maxContext ?? newMaxContext;\r\n } catch {\r\n // best-effort: use provider capability\r\n }\r\n autoCompactor.setMaxContext(newMaxContext);\r\n }\r\n\r\n // Agent\r\n const secretScrubber = container.resolve(TOKENS.SecretScrubber);\r\n const renderer = container.has(TOKENS.Renderer)\r\n ? container.resolve(TOKENS.Renderer)\r\n : undefined;\r\n const toolExecutor = new ToolExecutor(toolRegistry, {\r\n permissionPolicy: container.resolve(TOKENS.PermissionPolicy),\r\n secretScrubber,\r\n renderer,\r\n events,\r\n confirmAwaiter: undefined,\r\n iterationTimeoutMs: config.tools?.iterationTimeoutMs ?? DEFAULT_TOOLS_CONFIG.iterationTimeoutMs,\r\n perIterationOutputCapBytes: config.tools?.perIterationOutputCapBytes ?? DEFAULT_TOOLS_CONFIG.perIterationOutputCapBytes,\r\n tracer: undefined,\r\n });\r\n\r\n const agent = new Agent({\r\n container,\r\n tools: toolRegistry,\r\n providers: providerRegistry,\r\n events,\r\n pipelines,\r\n context,\r\n maxIterations: config.tools?.maxIterations ?? DEFAULT_TOOLS_CONFIG.maxIterations,\r\n iterationTimeoutMs: config.tools?.iterationTimeoutMs ?? DEFAULT_TOOLS_CONFIG.iterationTimeoutMs,\r\n executionStrategy: config.tools?.defaultExecutionStrategy ?? DEFAULT_TOOLS_CONFIG.defaultExecutionStrategy,\r\n perIterationOutputCapBytes: config.tools?.perIterationOutputCapBytes ?? DEFAULT_TOOLS_CONFIG.perIterationOutputCapBytes,\r\n confirmAwaiter: undefined,\r\n toolExecutor,\r\n });\r\n console.log('[WebUI] Agent initialized');\r\n\r\n // AutoPhase handler — manages AutoPhaseRunner lifecycle via WS messages.\r\n // Stored under the per-project autophase dir (not the shared SDD task-graphs).\r\n const autoPhaseHandler = new AutoPhaseWebSocketHandler(agent, context, logger, wpaths.projectAutophase);\r\n\r\n // Helper: build the rich session.start payload from current runtime state.\r\n // Centralised so initial connect, post-/new, and post-model.switch all\r\n // broadcast the same shape — frontend treats this as the single source of\r\n // truth for everything in the status bar (model, context window, project).\r\n async function sessionStartPayload(): Promise<{\r\n sessionId: string;\r\n model: string;\r\n provider: string;\r\n maxContext: number;\r\n /** USD per 1M input tokens (0 if unknown / free). */\r\n inputCost: number;\r\n /** USD per 1M output tokens. */\r\n outputCost: number;\r\n /** USD per 1M cache-read tokens. */\r\n cacheReadCost: number;\r\n projectName: string;\r\n cwd: string;\r\n mode: string;\r\n contextMode: string;\r\n wsToken: string;\r\n }> {\r\n let maxContext = 0;\r\n let inputCost = 0;\r\n let outputCost = 0;\r\n let cacheReadCost = 0;\r\n try {\r\n const m = await modelsRegistry.getModel(config.provider, config.model);\r\n maxContext = m?.capabilities?.maxContext ?? 0;\r\n // models.dev pricing is dollars per 1M tokens; some providers omit the\r\n // field for free/unmetered plans (e.g. minimax-coding-plan) — in that\r\n // case we report 0 and the cost chip just stays at $0.\r\n const cost = (\r\n m as { cost?: { input?: number; output?: number; cache_read?: number } } | undefined\r\n )?.cost;\r\n inputCost = cost?.input ?? 0;\r\n outputCost = cost?.output ?? 0;\r\n cacheReadCost = cost?.cache_read ?? 0;\r\n } catch {\r\n // best-effort\r\n }\r\n return {\r\n sessionId: session.id,\r\n model: config.model,\r\n provider: config.provider,\r\n maxContext,\r\n inputCost,\r\n outputCost,\r\n cacheReadCost,\r\n projectName: path.basename(projectRoot) || projectRoot,\r\n cwd: projectRoot,\r\n mode: modeId,\r\n contextMode: String(context.meta['contextWindowMode'] ?? DEFAULT_CONTEXT_WINDOW_MODE_ID),\r\n wsToken,\r\n };\r\n }\r\n\r\n // WebSocket server(s).\r\n //\r\n // When the user keeps the default loopback bind (127.0.0.1), we ALSO open a\r\n // second listener on ::1 (IPv6 loopback). Reason: Chrome/Edge on Windows\r\n // resolve `localhost` to `[::1]` before `127.0.0.1`, so a single v4-only\r\n // bind causes \"ws disconnect hep\" — clients hammer the v6 socket, get\r\n // ECONNREFUSED, fall back to v4 inconsistently. Listening on both v4 and v6\r\n // loopback keeps the connection scope \"this machine only\" while removing\r\n // the resolution-order coin flip.\r\n //\r\n // When the user explicitly sets WS_HOST (e.g. 0.0.0.0 or a LAN IP), we\r\n // respect that choice exactly and don't add a second listener.\r\n // Generate a random WS auth token so only callers that know the token\r\n // can connect. Printed to console on startup; the frontend reads it from\r\n // the URL query param `?token=...`. Without a token, any client on the\r\n // network can connect and send `user_message`/`key.add`/`model.switch`.\r\n const wsToken = randomBytes(16).toString('hex');\r\n // Token is sent to clients via session.start payload — log only a masked\r\n // prefix so operators can correlate without leaking the full secret.\r\n console.log(`[WebUI] WS auth token: ${wsToken.slice(0, 4)}…${wsToken.slice(-4)} (masked)`);\r\n\r\n // CSWSH guard + token auth: when the user exposes the socket beyond\r\n // loopback, require the shared token. Local loopback connections\r\n // without a token are still allowed for convenience.\r\n const isLoopback = (hostname: string) =>\r\n hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1' || hostname === '[::1]';\r\n\r\n // Constant-time token comparison: avoids leaking the token byte-by-byte via\r\n // response timing. Length mismatch short-circuits (lengths aren't secret).\r\n const tokenMatches = (provided: string | undefined): boolean => {\r\n if (!provided) return false;\r\n const a = Buffer.from(provided);\r\n const b = Buffer.from(wsToken);\r\n if (a.length !== b.length) return false;\r\n return timingSafeEqual(a, b);\r\n };\r\n\r\n // DNS-rebinding defense: the browser puts the *name it dialed* in the Host\r\n // header. A page on evil.com that rebinds DNS to 127.0.0.1 still sends\r\n // `Host: evil.com:<port>`, so requiring a loopback Host rejects rebinding\r\n // regardless of the bind address. The legitimate same-machine client dials\r\n // 127.0.0.1/localhost/[::1], so this never blocks real usage on a loopback\r\n // bind. When the operator deliberately exposes the socket (wsHost set to a\r\n // LAN/0.0.0.0 address) the Host will legitimately be non-loopback, so we\r\n // only enforce the loopback-Host requirement on a loopback bind.\r\n const hostHeaderOk = (req: import('node:http').IncomingMessage): boolean => {\r\n const boundToLoopback = wsHost === '127.0.0.1' || wsHost === '::1' || wsHost === 'localhost';\r\n if (!boundToLoopback) return true; // operator opted into wider exposure\r\n const hostHeader = (req.headers.host ?? '').trim();\r\n if (!hostHeader) return false;\r\n // Strip the port (handle bare host, host:port, and [::1]:port).\r\n let hostname: string;\r\n try {\r\n hostname = new URL(`http://${hostHeader}`).hostname;\r\n } catch {\r\n return false;\r\n }\r\n return isLoopback(hostname);\r\n };\r\n\r\n const verifyClient = (info: {\r\n origin: string;\r\n secure: boolean;\r\n req: import('node:http').IncomingMessage;\r\n }) => {\r\n const origin = info.origin;\r\n const url = info.req.url ?? '';\r\n const tokenMatch = url.match(/[?&]token=([^&]+)/);\r\n const providedToken = tokenMatch ? tokenMatch[1] : undefined;\r\n const tokenOk = tokenMatches(providedToken);\r\n\r\n // DNS-rebinding guard runs first on a loopback bind — independent of token\r\n // and Origin. Blocks a rebound attacker page (Host = attacker domain) even\r\n // though the TCP peer is 127.0.0.1.\r\n if (!hostHeaderOk(info.req)) return false;\r\n\r\n if (!origin) {\r\n // Non-browser clients (curl, scripts): require token unless on loopback.\r\n // When wsHost=0.0.0.0 the server accepts connections from any network\r\n // interface — token is mandatory in that case.\r\n const remoteIp = info.req.socket.remoteAddress ?? '';\r\n const isRemoteLoopback = remoteIp === '127.0.0.1' || remoteIp === '::1';\r\n if (!isRemoteLoopback && wsHost === '0.0.0.0') return false; // LAN exposure without token = deny\r\n return tokenOk || wsHost === '127.0.0.1' || wsHost === '::1' || wsHost === 'localhost';\r\n }\r\n try {\r\n const { hostname } = new URL(origin);\r\n // Loopback browser origins: allow without token (bootstrap — the token is\r\n // delivered in session.start and replayed on reconnect). The Host-header\r\n // guard above already rejects cross-site/rebinding pages here.\r\n if (isLoopback(hostname)) return true;\r\n // Non-loopback origins: token is mandatory.\r\n return tokenOk;\r\n } catch {\r\n return false;\r\n }\r\n };\r\n // Cap inbound frame size (8 MiB) so a single oversized message can't exhaust\r\n // memory. Agent messages are small; large pastes/attachments stay well under.\r\n const WS_MAX_PAYLOAD = 8 * 1024 * 1024;\r\n const wssPrimary = new WebSocketServer({\r\n port: wsPort,\r\n host: wsHost,\r\n verifyClient,\r\n maxPayload: WS_MAX_PAYLOAD,\r\n } as ConstructorParameters<typeof WebSocketServer>[0]);\r\n const wssSecondary =\r\n wsHost === '127.0.0.1'\r\n ? new WebSocketServer({\r\n port: wsPort,\r\n host: '::1',\r\n verifyClient,\r\n maxPayload: WS_MAX_PAYLOAD,\r\n } as ConstructorParameters<typeof WebSocketServer>[0])\r\n : null;\r\n const clients = new Map<WebSocket, ConnectedClient>();\r\n\r\n // Per-connection message rate limiting: 60 messages per 60-second window.\r\n // Exceeding clients are temporarily blocked to prevent flooding.\r\n const RATE_LIMIT_MESSAGES = 60;\r\n const RATE_LIMIT_WINDOW_MS = 60_000;\r\n const rateLimits = new Map<WebSocket, { count: number; resetAt: number }>();\r\n\r\n function checkRateLimit(ws: WebSocket): boolean {\r\n const now = Date.now();\r\n const limit = rateLimits.get(ws);\r\n if (!limit || now > limit.resetAt) {\r\n rateLimits.set(ws, { count: 1, resetAt: now + RATE_LIMIT_WINDOW_MS });\r\n return true;\r\n }\r\n if (limit.count >= RATE_LIMIT_MESSAGES) return false;\r\n limit.count++;\r\n return true;\r\n }\r\n\r\n /** Holds the AbortController for the currently in-flight agent.run().\r\n * Non-null while the agent is running; guarded at the user_message\r\n * handler to prevent concurrent runs that would corrupt shared state\r\n * (context, agent, tokenCounter). A second user_message while running\r\n * is answered with an inline error instead of being queued — the\r\n * caller should wait for run.result. */\r\n let runLock: AbortController | null = null;\r\n\r\n console.log(\r\n `[WebUI] WebSocket server running on ws://${wsHost}:${wsPort}` +\r\n (wssSecondary ? ` (and ws://[::1]:${wsPort})` : ''),\r\n );\r\n\r\n // Pending permission confirmations. When the agent emits\r\n // tool.confirm_needed, we store the resolve function here keyed by\r\n // toolUseId. When the client sends tool.confirm_result back, we look\r\n // it up and resolve — unblocking the agent loop.\r\n const pendingConfirms = new Map<string, (d: 'yes' | 'no' | 'always' | 'deny') => void>();\r\n\r\n // Event subscriptions\r\n function setupEvents() {\r\n events.on('iteration.started', (e) => {\r\n broadcast({\r\n type: 'iteration.started',\r\n payload: { index: e.index, maxIterations: config.tools?.maxIterations ?? 100 },\r\n });\r\n });\r\n\r\n events.on('provider.text_delta', (e) => {\r\n broadcast({ type: 'provider.text_delta', payload: { text: e.text, messageId: 'current' } });\r\n });\r\n\r\n events.on('provider.thinking_delta', (e) => {\r\n broadcast({ type: 'provider.thinking_delta', payload: { text: e.text } });\r\n });\r\n\r\n events.on('tool.started', (e) => {\r\n broadcast({\r\n type: 'tool.started',\r\n payload: { id: e.id, name: e.name, input: e.input, messageId: `tool_${e.id}` },\r\n });\r\n });\r\n\r\n events.on('tool.progress', (e) => {\r\n // Streaming progress (bash stdout chunks, fetch body deltas, scan\r\n // counts...). We forward the lightweight shape: id + type + text so\r\n // the UI can render an inline \"live\" preview while the tool is still\r\n // running. Heavy `data` blob is intentionally dropped here — the\r\n // frontend doesn't need it and broadcasting it would balloon the WS\r\n // traffic for tools that emit progress every few ms.\r\n broadcast({\r\n type: 'tool.progress',\r\n payload: {\r\n id: e.id,\r\n name: e.name,\r\n eventType: e.event.type,\r\n text: e.event.text,\r\n },\r\n });\r\n });\r\n\r\n events.on('tool.executed', (e) => {\r\n broadcast({\r\n type: 'tool.executed',\r\n payload: {\r\n // Forward the tool_use id so frontend can correlate with the\r\n // matching tool.started bubble — without this, parallel tool calls\r\n // all stay stuck on \"Running…\" because the frontend can't tell\r\n // which bubble this result belongs to.\r\n id: e.id,\r\n name: e.name,\r\n durationMs: e.durationMs,\r\n ok: e.ok,\r\n input: e.input,\r\n output: e.output,\r\n },\r\n });\r\n // Push the current todo snapshot too — the TodoWrite tool mutates\r\n // context.todos in place, and a side-panel that needs to react to\r\n // that change shouldn't have to poll. Cheap (todos are tiny).\r\n broadcast({\r\n type: 'todos.updated',\r\n payload: { todos: [...context.todos] },\r\n });\r\n });\r\n\r\n events.on('provider.response', (e) => {\r\n broadcast({\r\n type: 'provider.response',\r\n payload: {\r\n usage: e.usage,\r\n stopReason: e.stopReason,\r\n messageId: 'current',\r\n },\r\n });\r\n });\r\n\r\n events.on('context.repaired', (e) => {\r\n broadcast({\r\n type: 'context.repaired',\r\n payload: {\r\n removedToolUses: e.removedToolUses,\r\n removedToolResults: e.removedToolResults,\r\n removedMessages: e.removedMessages,\r\n },\r\n });\r\n });\r\n\r\n events.on('tool.confirm_needed', (e) => {\r\n const id = e.toolUseId ?? `confirm_${Date.now()}`;\r\n pendingConfirms.set(id, e.resolve);\r\n broadcast({\r\n type: 'tool.confirm_needed',\r\n payload: {\r\n id,\r\n toolName: e.tool?.name ?? 'unknown',\r\n input: e.input,\r\n suggestedPattern: e.suggestedPattern,\r\n },\r\n });\r\n });\r\n\r\n events.on('error', (e) => {\r\n broadcast({\r\n type: 'error',\r\n payload: {\r\n phase: e.phase,\r\n message: e.err instanceof Error ? e.err.message : String(e.err),\r\n },\r\n });\r\n });\r\n }\r\n\r\n function send(ws: WebSocket, msg: WSServerMessage): void {\r\n if (ws.readyState === WebSocket.OPEN) {\r\n ws.send(JSON.stringify(msg));\r\n }\r\n }\r\n\r\n function broadcast(msg: WSServerMessage): void {\r\n const data = JSON.stringify(msg);\r\n for (const [ws] of clients) {\r\n if (ws.readyState === WebSocket.OPEN) {\r\n ws.send(data);\r\n }\r\n }\r\n }\r\n\r\n const handleConnection = (ws: WebSocket): void => {\r\n const client: ConnectedClient = { ws, sessionId: session.id, connectedAt: Date.now() };\r\n clients.set(ws, client);\r\n console.log('[WebUI] Client connected, total:', clients.size);\r\n\r\n void sessionStartPayload().then((payload) => {\r\n send(ws, { type: 'session.start', payload });\r\n });\r\n\r\n // Register this client with the AutoPhase handler so it receives phase events\r\n autoPhaseHandler.addClient(ws);\r\n\r\n ws.on('message', async (data) => {\r\n if (!checkRateLimit(ws)) {\r\n send(ws, {\r\n type: 'error',\r\n payload: {\r\n phase: 'rate_limit',\r\n message: 'Too many messages. Please wait before sending more.',\r\n },\r\n });\r\n return;\r\n }\r\n try {\r\n const msg = JSON.parse(data.toString()) as WSClientMessage;\r\n await handleMessage(ws, client, msg);\r\n } catch (err) {\r\n console.error('[WebUI] Failed to parse message', err);\r\n }\r\n });\r\n\r\n ws.on('close', () => {\r\n clients.delete(ws);\r\n rateLimits.delete(ws);\r\n console.log('[WebUI] Client disconnected, total:', clients.size);\r\n // If the client disconnects while a permission prompt is pending,\r\n // resolve all pending confirms with 'no' so the agent loop doesn't\r\n // hang forever waiting for a response that will never come.\r\n if (pendingConfirms.size > 0) {\r\n for (const [id, resolve] of pendingConfirms) {\r\n resolve('no');\r\n pendingConfirms.delete(id);\r\n }\r\n }\r\n });\r\n\r\n ws.on('error', (err) => {\r\n // Without this handler an errored socket would crash the process.\r\n console.warn('[WebUI] Client socket error:', err.message);\r\n });\r\n };\r\n\r\n let eventsArmed = false;\r\n const armOnce = (label: string): void => {\r\n if (eventsArmed) return;\r\n eventsArmed = true;\r\n console.log(`[WebUI] Backend ready (${label})`);\r\n setupEvents();\r\n };\r\n\r\n wssPrimary.on('listening', () => armOnce(`${wsHost}:${wsPort}`));\r\n wssPrimary.on('connection', handleConnection);\r\n wssPrimary.on('error', (err) => {\r\n console.error(`[WebUI] Primary WS server error (${wsHost}):`, err);\r\n });\r\n\r\n if (wssSecondary) {\r\n wssSecondary.on('listening', () => armOnce(`::1:${wsPort}`));\r\n wssSecondary.on('connection', handleConnection);\r\n wssSecondary.on('error', (err: NodeJS.ErrnoException) => {\r\n // Best-effort secondary: if IPv6 loopback isn't available on this host\r\n // (e.g. disabled in OS), just log and continue. Primary v4 is enough.\r\n if (err.code === 'EAFNOSUPPORT' || err.code === 'EADDRNOTAVAIL') {\r\n console.warn('[WebUI] IPv6 loopback not available, v4-only:', err.code);\r\n } else {\r\n console.error('[WebUI] Secondary WS server error (::1):', err);\r\n }\r\n });\r\n }\r\n\r\n async function handleMessage(\r\n ws: WebSocket,\r\n client: ConnectedClient,\r\n msg: WSClientMessage,\r\n ): Promise<void> {\r\n switch (msg.type) {\r\n case 'user_message': {\r\n const content = (msg as { payload: { content: string } }).payload.content;\r\n\r\n // Guard against concurrent agent runs — a second user_message while\r\n // the agent is already processing would kick off two agent.run()\r\n // calls on the same shared context/agent, leading to corrupted\r\n // state (duplicate tool bubbles, mixed text_delta streams, token\r\n // counter undercount). Reject with an inline error; the frontend\r\n // should wait for run.result before sending the next message.\r\n if (runLock) {\r\n send(ws, {\r\n type: 'error',\r\n payload: {\r\n phase: 'user_message',\r\n message: 'Agent is already processing a request. Wait for the current run to finish.',\r\n },\r\n });\r\n break;\r\n }\r\n\r\n runLock = new AbortController();\r\n // Capture so the finally block only clears its own lock — a\r\n // second race could set a new runLock between await and finally.\r\n const thisRun = runLock;\r\n\r\n try {\r\n const result = await agent.run(content, { signal: thisRun.signal });\r\n send(ws, {\r\n type: 'run.result',\r\n payload: {\r\n status: result.status,\r\n iterations: result.iterations,\r\n finalText: result.finalText,\r\n error: result.error\r\n ? {\r\n code: result.error.code,\r\n message: result.error.message,\r\n recoverable: result.error.recoverable,\r\n }\r\n : undefined,\r\n },\r\n });\r\n } catch (err) {\r\n send(ws, {\r\n type: 'error',\r\n payload: {\r\n phase: 'agent.run',\r\n message: err instanceof Error ? err.message : String(err),\r\n },\r\n });\r\n } finally {\r\n // Only clear runLock if it's still ours — otherwise we'd wipe a\r\n // newer run's controller set after we returned.\r\n if (runLock === thisRun) {\r\n runLock = null;\r\n }\r\n }\r\n break;\r\n }\r\n\r\n case 'tool.confirm_result': {\r\n const { id, decision } = (msg as { payload: { id: string; decision: 'yes' | 'no' | 'always' | 'deny' } }).payload;\r\n const resolve = pendingConfirms.get(id);\r\n if (resolve) {\r\n pendingConfirms.delete(id);\r\n resolve(decision);\r\n }\r\n break;\r\n }\r\n\r\n case 'abort':\r\n runLock?.abort();\r\n broadcast({ type: 'error', payload: { phase: 'abort', message: 'User aborted' } });\r\n break;\r\n\r\n case 'ping':\r\n send(ws, { type: 'pong', payload: {} });\r\n break;\r\n\r\n case 'session.new': {\r\n // Truly fresh chat: new on-disk session AND reset every piece of\r\n // in-memory state that survived (messages history, todos, read-file\r\n // tracking, token totals). Otherwise the model still sees the prior\r\n // turns even though the UI looks empty — that's the \"ghost context\"\r\n // bug. After this, the next user message goes out as turn 1 with no\r\n // prior history.\r\n session = await sessionStore.create({\r\n id: '',\r\n title: '',\r\n model: config.model,\r\n provider: config.provider,\r\n });\r\n context.session = session;\r\n context.state.replaceMessages([]);\r\n context.state.replaceTodos([]);\r\n context.readFiles.clear();\r\n context.fileMtimes.clear();\r\n tokenCounter.reset();\r\n sessionStartedAt = Date.now();\r\n broadcast({ type: 'session.start', payload: await sessionStartPayload() });\r\n break;\r\n }\r\n\r\n case 'context.clear': {\r\n // Same in-memory wipe as session.new, but reuses the current session\r\n // file (so the JSONL still has the history for audit / replay). The\r\n // user wants a clean slate on the model side; the disk record stays.\r\n context.state.replaceMessages([]);\r\n context.state.replaceTodos([]);\r\n context.readFiles.clear();\r\n context.fileMtimes.clear();\r\n tokenCounter.reset();\r\n sendResult(ws, true, 'Context cleared');\r\n broadcast({\r\n type: 'session.start',\r\n payload: { ...(await sessionStartPayload()), reset: true },\r\n });\r\n break;\r\n }\r\n\r\n case 'context.debug': {\r\n // Per-section token estimate so users can see what's actually eating\r\n // the context window. Uses the simple 4-chars-per-token heuristic —\r\n // not exact, but close enough to spot which section is bloated.\r\n const estimate = (s: string): number => Math.ceil(s.length / 4);\r\n const stringifyContent = (c: unknown): string => {\r\n if (typeof c === 'string') return c;\r\n try {\r\n return JSON.stringify(c);\r\n } catch {\r\n return String(c);\r\n }\r\n };\r\n const sysTokens = context.systemPrompt.reduce((acc, b) => acc + estimate(b.text ?? ''), 0);\r\n // Tool schemas: each tool sends a JSON schema to the model on every\r\n // turn. With 20+ builtins these can be 10-20k by themselves.\r\n const tools = toolRegistry.list();\r\n const toolBreakdown = tools.map((t) => {\r\n const schema = (t as { inputSchema?: unknown }).inputSchema ?? {};\r\n const desc = (t as { description?: string }).description ?? '';\r\n return {\r\n name: t.name,\r\n tokens: estimate(t.name) + estimate(desc) + estimate(stringifyContent(schema)),\r\n };\r\n });\r\n const toolTokens = toolBreakdown.reduce((a, b) => a + b.tokens, 0);\r\n const messageBreakdown = context.messages.map((m, i) => {\r\n let tk = 0;\r\n if (typeof m.content === 'string') {\r\n tk = estimate(m.content);\r\n } else if (Array.isArray(m.content)) {\r\n for (const b of m.content) {\r\n if (b.type === 'text') tk += estimate(b.text ?? '');\r\n else if (b.type === 'tool_use') tk += estimate(stringifyContent(b.input));\r\n else if (b.type === 'tool_result') tk += estimate(stringifyContent(b.content));\r\n else tk += estimate(stringifyContent(b));\r\n }\r\n }\r\n return {\r\n index: i,\r\n role: m.role,\r\n tokens: tk,\r\n preview:\r\n typeof m.content === 'string'\r\n ? m.content.slice(0, 60)\r\n : Array.isArray(m.content)\r\n ? m.content\r\n .map((b) =>\r\n b.type === 'text'\r\n ? (b.text ?? '').slice(0, 40)\r\n : b.type === 'tool_use'\r\n ? `[tool_use: ${b.name}]`\r\n : b.type === 'tool_result'\r\n ? `[tool_result]`\r\n : `[${b.type}]`,\r\n )\r\n .join(' ')\r\n .slice(0, 60)\r\n : '',\r\n };\r\n });\r\n const msgTokens = messageBreakdown.reduce((a, b) => a + b.tokens, 0);\r\n const total = sysTokens + toolTokens + msgTokens;\r\n send(ws, {\r\n type: 'context.debug',\r\n payload: {\r\n total,\r\n mode: context.meta['contextWindowMode'] ?? DEFAULT_CONTEXT_WINDOW_MODE_ID,\r\n policy: context.meta['contextWindowPolicy'],\r\n systemPrompt: sysTokens,\r\n tools: { total: toolTokens, count: tools.length, breakdown: toolBreakdown },\r\n messages: {\r\n total: msgTokens,\r\n count: context.messages.length,\r\n breakdown: messageBreakdown,\r\n },\r\n },\r\n });\r\n break;\r\n }\r\n\r\n case 'context.compact': {\r\n const aggressive = !!(msg as { payload?: { aggressive?: boolean } }).payload?.aggressive;\r\n try {\r\n const report = await compactor.compact(context, { aggressive });\r\n send(ws, {\r\n type: 'context.compacted',\r\n payload: {\r\n before: report.before,\r\n after: report.after,\r\n saved: Math.max(0, report.before - report.after),\r\n reductions: report.reductions,\r\n repaired: report.repaired,\r\n },\r\n });\r\n sendResult(\r\n ws,\r\n true,\r\n `Compacted: ${report.before} → ${report.after} tokens (saved ~${Math.max(0, report.before - report.after)})`,\r\n );\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n break;\r\n }\r\n\r\n case 'context.repair': {\r\n const beforeMessages = context.messages.length;\r\n const repaired = repairToolUseAdjacency(context.messages);\r\n if (repaired.report.changed) {\r\n context.state.replaceMessages(repaired.messages);\r\n }\r\n const payload = {\r\n removedToolUses: repaired.report.removedToolUses,\r\n removedToolResults: repaired.report.removedToolResults,\r\n removedMessages: repaired.report.removedMessages,\r\n beforeMessages,\r\n afterMessages: context.messages.length,\r\n };\r\n broadcast({ type: 'context.repaired', payload });\r\n const removed =\r\n payload.removedToolUses.length +\r\n payload.removedToolResults.length +\r\n payload.removedMessages;\r\n sendResult(\r\n ws,\r\n true,\r\n removed > 0\r\n ? `Context repaired: removed ${removed} orphan protocol item(s)`\r\n : 'Context repair found no orphan protocol blocks',\r\n );\r\n break;\r\n }\r\n\r\n case 'context.modes.list': {\r\n const active = String(context.meta['contextWindowMode'] ?? DEFAULT_CONTEXT_WINDOW_MODE_ID);\r\n send(ws, {\r\n type: 'context.modes.list',\r\n payload: {\r\n activeId: active,\r\n modes: listContextWindowModes().map((m) => ({\r\n id: m.id,\r\n name: m.name,\r\n description: m.description,\r\n isActive: m.id === active,\r\n thresholds: m.thresholds,\r\n preserveK: m.preserveK,\r\n eliseThreshold: m.eliseThreshold,\r\n })),\r\n },\r\n });\r\n break;\r\n }\r\n\r\n case 'context.mode.switch': {\r\n const { id } = (msg as { payload: { id: string } }).payload;\r\n const policy = resolveContextWindowPolicy({}, id);\r\n if (policy.id !== id) {\r\n sendResult(ws, false, `Unknown context mode \"${id}\"`);\r\n break;\r\n }\r\n context.meta['contextWindowMode'] = policy.id;\r\n context.meta['contextWindowPolicy'] = policy;\r\n sendResult(ws, true, `Context mode switched to ${policy.id}`);\r\n broadcast({\r\n type: 'context.mode.changed',\r\n payload: { id: policy.id, name: policy.name, policy },\r\n });\r\n break;\r\n }\r\n\r\n case 'providers.list': {\r\n const providers = await modelsRegistry.listProviders();\r\n // \"Configured\" should mean *any* working credential, not just env vars.\r\n // Users register keys with `wstack auth`, which writes apiKey/apiKeys\r\n // into config.providers[<id>] — those are decrypted in memory here.\r\n const savedIds = new Set(Object.keys(config.providers ?? {}));\r\n send(ws, {\r\n type: 'provider.catalog',\r\n payload: {\r\n providers: providers.map((p) => ({\r\n id: p.id,\r\n name: p.name,\r\n family: p.family,\r\n apiBase: p.apiBase,\r\n envVars: p.envVars,\r\n modelCount: p.models.length,\r\n hasApiKey: savedIds.has(p.id) || p.envVars.some((v) => !!process.env[v]),\r\n })),\r\n },\r\n });\r\n break;\r\n }\r\n\r\n case 'provider.models': {\r\n const providerId = (msg as { payload: { providerId: string } }).payload.providerId;\r\n const provider = await modelsRegistry.getProvider(providerId);\r\n if (provider) {\r\n send(ws, {\r\n type: 'provider.models',\r\n payload: {\r\n provider: providerId,\r\n models: provider.models.map((m) => ({\r\n id: m.id,\r\n name: m.name,\r\n releaseDate: (m as { release_date?: string }).release_date,\r\n contextWindow: (m as { limit?: { context?: number } }).limit?.context,\r\n inputCost: (m as { cost?: { input?: number } }).cost?.input,\r\n outputCost: (m as { cost?: { output?: number } }).cost?.output,\r\n capabilities: [\r\n ...((m as { tool_call?: boolean }).tool_call ? ['tools'] : []),\r\n ...((m as { reasoning?: boolean }).reasoning ? ['reasoning'] : []),\r\n ],\r\n })),\r\n },\r\n });\r\n }\r\n break;\r\n }\r\n\r\n case 'model.switch': {\r\n const { provider: newProvider, model: newModel } = (\r\n msg as { payload: { provider: string; model: string } }\r\n ).payload;\r\n try {\r\n // Update config\r\n config = patchConfig(config, { provider: newProvider, model: newModel });\r\n configStore.update({ provider: newProvider, model: newModel });\r\n context.model = newModel;\r\n\r\n // Create new provider instance — fail loudly if the user picks a\r\n // provider with no creds rather than silently keeping the old one.\r\n const providerCfg = config.providers?.[newProvider] ?? { type: newProvider };\r\n const newProv = providerRegistry.has(newProvider)\r\n ? providerRegistry.create({ ...providerCfg, type: newProvider })\r\n : makeProviderFromConfig(newProvider, providerCfg);\r\n context.provider = newProv;\r\n\r\n // Update AutoCompactionMiddleware with the new model's maxContext so\r\n // backend threshold triggers (warn/soft/hard) use the correct denominator.\r\n // sessionStartPayload is called below (after this block) and uses\r\n // the new provider for its modelsRegistry lookup.\r\n updateAutoCompactionMaxContext?.(newProv);\r\n\r\n // Persist to global config file\r\n try {\r\n configWriteLock = configWriteLock.then(async () => {\r\n const raw = await fs.readFile(globalConfigPath, 'utf8');\r\n const parsed = JSON.parse(raw);\r\n parsed.provider = newProvider;\r\n parsed.model = newModel;\r\n await atomicWrite(globalConfigPath, JSON.stringify(parsed, null, 2));\r\n });\r\n await configWriteLock;\r\n } catch (err) {\r\n console.warn('[WebUI] Failed to save config:', err);\r\n }\r\n\r\n // Toast for the SettingsPanel\r\n send(ws, {\r\n type: 'key.operation_result',\r\n payload: { success: true, message: `Switched to ${newProvider} / ${newModel}` },\r\n });\r\n } catch (err) {\r\n send(ws, {\r\n type: 'key.operation_result',\r\n payload: {\r\n success: false,\r\n message: `Switch failed: ${err instanceof Error ? err.message : String(err)}`,\r\n },\r\n });\r\n break;\r\n }\r\n\r\n broadcast({ type: 'session.start', payload: await sessionStartPayload() });\r\n break;\r\n }\r\n\r\n case 'key.add':\r\n case 'key.update': {\r\n const { providerId, label, apiKey } = (\r\n msg as { payload: { providerId: string; label: string; apiKey: string } }\r\n ).payload;\r\n await handleKeyUpsert(ws, providerId, label, apiKey);\r\n break;\r\n }\r\n\r\n case 'key.delete': {\r\n const { providerId, label } = (msg as { payload: { providerId: string; label: string } })\r\n .payload;\r\n await handleKeyDelete(ws, providerId, label);\r\n break;\r\n }\r\n\r\n case 'key.set_active': {\r\n const { providerId, label } = (msg as { payload: { providerId: string; label: string } })\r\n .payload;\r\n await handleKeySetActive(ws, providerId, label);\r\n break;\r\n }\r\n\r\n case 'provider.add': {\r\n const p = (\r\n msg as { payload: { id: string; family: string; baseUrl?: string; apiKey?: string } }\r\n ).payload;\r\n await handleProviderAdd(ws, p);\r\n break;\r\n }\r\n\r\n case 'provider.remove': {\r\n const { providerId } = (msg as { payload: { providerId: string } }).payload;\r\n await handleProviderRemove(ws, providerId);\r\n break;\r\n }\r\n\r\n case 'sessions.list': {\r\n // Per-project history. Sessions live under .wrongstack/sessions/ for\r\n // this project; we never enumerate cross-project state.\r\n const limit = (msg as { payload?: { limit?: number } }).payload?.limit ?? 50;\r\n try {\r\n const list = await sessionStore.list(limit);\r\n send(ws, {\r\n type: 'sessions.list',\r\n payload: {\r\n sessions: list.map((s) => ({\r\n id: s.id,\r\n title: s.title,\r\n startedAt: s.startedAt,\r\n model: s.model,\r\n provider: s.provider,\r\n tokenTotal: s.tokenTotal,\r\n isCurrent: s.id === session.id,\r\n })),\r\n },\r\n });\r\n } catch (err) {\r\n send(ws, {\r\n type: 'sessions.list',\r\n payload: { sessions: [], error: err instanceof Error ? err.message : String(err) },\r\n });\r\n }\r\n break;\r\n }\r\n\r\n case 'session.delete': {\r\n const { id } = (msg as { payload: { id: string } }).payload;\r\n try {\r\n if (id === session.id) {\r\n sendResult(ws, false, 'Cannot delete the active session');\r\n break;\r\n }\r\n await sessionStore.delete(id);\r\n sendResult(ws, true, `Session ${id} deleted`);\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n break;\r\n }\r\n\r\n case 'session.resume': {\r\n // Load a past session's messages + usage, swap the active session\r\n // writer, hydrate the live Context, then broadcast a session.start\r\n // payload tagged with the replayed transcript so the UI can render\r\n // the chat history.\r\n const { id } = (msg as { payload: { id: string } }).payload;\r\n try {\r\n if (id === session.id) {\r\n sendResult(ws, false, 'Session is already active');\r\n break;\r\n }\r\n const resumed = await sessionStore.resume(id);\r\n // Close prior writer best-effort; swallow errors so we don't block\r\n // the resume on a crashed file handle.\r\n try {\r\n await session.close();\r\n } catch {\r\n /* noop */\r\n }\r\n session = resumed.writer;\r\n context.session = session;\r\n context.state.replaceMessages(resumed.data.messages);\r\n context.readFiles.clear();\r\n context.fileMtimes.clear();\r\n tokenCounter.reset();\r\n // Replay usage so the topbar shows accurate totals after resume.\r\n tokenCounter.account(resumed.data.usage, config.model);\r\n sessionStartedAt = Date.now();\r\n broadcast({\r\n type: 'session.start',\r\n payload: {\r\n ...(await sessionStartPayload()),\r\n reset: true,\r\n replayMessages: resumed.data.messages,\r\n replayUsage: resumed.data.usage,\r\n },\r\n });\r\n sendResult(ws, true, `Resumed session ${id}`);\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n break;\r\n }\r\n\r\n case 'session.save': {\r\n // SessionWriter already flushes after every event; this is mostly a\r\n // no-op marker so the user gets confirmation. Useful for habit\r\n // parity with the CLI /save command.\r\n sendResult(ws, true, `Session ${session.id} is auto-saved`);\r\n break;\r\n }\r\n\r\n case 'tools.list': {\r\n // Full tool registry dump for the /tools inspect view. We surface\r\n // name, description, and schema-derived param names so the user\r\n // can tell at a glance which tools the model can call right now.\r\n const list = toolRegistry.list().map((t) => {\r\n const schema =\r\n (t as { inputSchema?: { properties?: Record<string, unknown> } }).inputSchema ?? {};\r\n const params = schema.properties ? Object.keys(schema.properties) : [];\r\n return {\r\n name: t.name,\r\n description: (t as { description?: string }).description ?? '',\r\n params,\r\n };\r\n });\r\n send(ws, { type: 'tools.list', payload: { tools: list } });\r\n break;\r\n }\r\n\r\n case 'memory.list': {\r\n // All three scopes (project-agents, project-memory, user-memory)\r\n // rolled up as readAll already does. Returned as raw markdown so\r\n // the UI can render with the same style as everything else.\r\n try {\r\n const text = await memoryStore.readAll();\r\n send(ws, { type: 'memory.list', payload: { text } });\r\n } catch (err) {\r\n send(ws, {\r\n type: 'memory.list',\r\n payload: { text: '', error: err instanceof Error ? err.message : String(err) },\r\n });\r\n }\r\n break;\r\n }\r\n\r\n case 'memory.remember': {\r\n const { text, scope } = (\r\n msg as {\r\n payload: { text: string; scope?: 'project-agents' | 'project-memory' | 'user-memory' };\r\n }\r\n ).payload;\r\n try {\r\n await memoryStore.remember(text, scope ?? 'project-memory');\r\n sendResult(ws, true, 'Saved to memory');\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n break;\r\n }\r\n\r\n case 'memory.forget': {\r\n const { text, scope } = (\r\n msg as {\r\n payload: { text: string; scope?: 'project-agents' | 'project-memory' | 'user-memory' };\r\n }\r\n ).payload;\r\n try {\r\n const removed = await memoryStore.forget(text, scope ?? 'project-memory');\r\n sendResult(\r\n ws,\r\n removed > 0,\r\n removed > 0\r\n ? `Removed ${removed} entr${removed === 1 ? 'y' : 'ies'}`\r\n : 'No matching entries',\r\n );\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n break;\r\n }\r\n\r\n case 'skills.list': {\r\n if (!skillLoader) {\r\n send(ws, { type: 'skills.list', payload: { skills: [], enabled: false } });\r\n break;\r\n }\r\n try {\r\n const manifests = await skillLoader.list();\r\n const entries = await skillLoader.listEntries();\r\n const byName = new Map(entries.map((e) => [e.name, e]));\r\n send(ws, {\r\n type: 'skills.list',\r\n payload: {\r\n enabled: true,\r\n skills: manifests.map((m) => ({\r\n name: m.name,\r\n description: m.description,\r\n version: m.version ?? '',\r\n source: m.source,\r\n path: m.path,\r\n trigger: byName.get(m.name)?.trigger ?? '',\r\n scope: byName.get(m.name)?.scope ?? [],\r\n })),\r\n },\r\n });\r\n } catch (err) {\r\n send(ws, {\r\n type: 'skills.list',\r\n payload: {\r\n skills: [],\r\n enabled: true,\r\n error: err instanceof Error ? err.message : String(err),\r\n },\r\n });\r\n }\r\n break;\r\n }\r\n\r\n case 'diag.get': {\r\n // Snapshot of the moving parts so the user can debug \"why is X\r\n // not working?\" without diving into the server logs.\r\n const usage = tokenCounter.total();\r\n send(ws, {\r\n type: 'diag.get',\r\n payload: {\r\n provider: config.provider,\r\n model: config.model,\r\n cwd: projectRoot,\r\n sessionId: session.id,\r\n tools: {\r\n count: toolRegistry.list().length,\r\n names: toolRegistry.list().map((t) => t.name),\r\n },\r\n features: {\r\n memory: !!config.features?.memory,\r\n skills: !!config.features?.skills,\r\n modelsRegistry: !!config.features?.modelsRegistry,\r\n },\r\n mode: modeId ?? 'default',\r\n usage,\r\n messages: context.messages.length,\r\n todos: context.todos.length,\r\n },\r\n });\r\n break;\r\n }\r\n\r\n case 'todos.get': {\r\n // On-demand snapshot — used when a UI surface first mounts and\r\n // needs to render the live todo list without waiting for the next\r\n // tool.executed to broadcast.\r\n send(ws, {\r\n type: 'todos.updated',\r\n payload: { todos: [...context.todos] },\r\n });\r\n break;\r\n }\r\n\r\n case 'todos.clear': {\r\n // Manual override — the agent normally curates this list via\r\n // TodoWrite, but the user might want a clean slate without losing\r\n // the rest of the context. Use state.replaceTodos so observers\r\n // (checkpoint writer) stay in sync.\r\n context.state.replaceTodos([]);\r\n sendResult(ws, true, 'Todos cleared');\r\n broadcast({ type: 'todos.updated', payload: { todos: [] } });\r\n break;\r\n }\r\n\r\n case 'plan.get': {\r\n // On-demand plan snapshot — used when a UI surface first mounts\r\n // and needs to render the live plan without waiting for the next\r\n // tool.executed to broadcast.\r\n const planPath = (context.meta as Record<string, unknown>)['plan.path'];\r\n if (typeof planPath === 'string' && planPath) {\r\n try {\r\n const { loadPlan } = await import('@wrongstack/core');\r\n const plan = await loadPlan(planPath);\r\n send(ws, {\r\n type: 'plan.updated',\r\n payload: { plan: plan ?? { version: 1, sessionId: session.id, updatedAt: new Date().toISOString(), items: [] } },\r\n });\r\n } catch {\r\n send(ws, {\r\n type: 'plan.updated',\r\n payload: { plan: { version: 1, sessionId: session.id, updatedAt: new Date().toISOString(), items: [] } },\r\n });\r\n }\r\n } else {\r\n send(ws, {\r\n type: 'plan.updated',\r\n payload: { plan: null, error: 'Plan storage is not configured for this session.' },\r\n });\r\n }\r\n break;\r\n }\r\n\r\n case 'plan.template_use': {\r\n const { template } = (msg as { payload: { template: string } }).payload;\r\n const planPath = (context.meta as Record<string, unknown>)['plan.path'];\r\n if (typeof planPath !== 'string' || !planPath) {\r\n sendResult(ws, false, 'Plan storage is not configured for this session.');\r\n break;\r\n }\r\n try {\r\n const { getPlanTemplate, loadPlan, savePlan, emptyPlan, addPlanItem, formatPlan } = await import('@wrongstack/core');\r\n const tpl = getPlanTemplate(template);\r\n if (!tpl) {\r\n sendResult(ws, false, `Unknown template \"${template}\".`);\r\n break;\r\n }\r\n let plan = (await loadPlan(planPath)) ?? emptyPlan(session.id);\r\n for (const item of tpl.items) {\r\n ({ plan } = addPlanItem(plan, item.title, item.details));\r\n }\r\n await savePlan(planPath, plan);\r\n sendResult(ws, true, `Applied template \"${tpl.name}\" — ${tpl.items.length} items added.`);\r\n broadcast({\r\n type: 'plan.updated',\r\n payload: { plan },\r\n });\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n break;\r\n }\r\n\r\n case 'files.list': {\r\n // Lightweight project file picker for the chat `@` mention popup.\r\n // Walks projectRoot, skipping the heavyweight build/vcs/node_modules\r\n // dirs that would blow up the response on a real project. Applies\r\n // a fuzzy substring match against the (lowercased) query and caps\r\n // the result so the popup never has to paginate.\r\n const payload = (msg as { payload?: { query?: string; limit?: number } }).payload ?? {};\r\n const query = (payload.query ?? '').toLowerCase();\r\n const limit = payload.limit ?? 50;\r\n const SKIP_DIRS = new Set([\r\n '.git',\r\n 'node_modules',\r\n 'dist',\r\n 'build',\r\n '.next',\r\n '.turbo',\r\n '.cache',\r\n 'target',\r\n 'coverage',\r\n '.nyc_output',\r\n 'out',\r\n '.pnpm-store',\r\n '.parcel-cache',\r\n ]);\r\n const results: string[] = [];\r\n async function walk(dir: string, rel: string, depth: number): Promise<void> {\r\n if (depth > 8 || results.length >= 600) return;\r\n let entries: import('node:fs').Dirent[] = [];\r\n try {\r\n entries = await fs.readdir(dir, { withFileTypes: true });\r\n } catch {\r\n return;\r\n }\r\n for (const e of entries) {\r\n if (results.length >= 600) return;\r\n if (e.name.startsWith('.') && e.name !== '.wrongstack' && e.name !== '.env.example') {\r\n // hide dotfiles by default; pick a couple common ones the user\r\n // might want anyway\r\n if (e.name !== '.gitignore' && e.name !== '.eslintrc' && e.name !== '.prettierrc')\r\n continue;\r\n }\r\n const childRel = rel ? `${rel}/${e.name}` : e.name;\r\n if (e.isDirectory()) {\r\n if (SKIP_DIRS.has(e.name)) continue;\r\n await walk(path.join(dir, e.name), childRel, depth + 1);\r\n } else if (e.isFile()) {\r\n results.push(childRel);\r\n }\r\n }\r\n }\r\n await walk(projectRoot, '', 0);\r\n // Score: exact basename match > prefix > substring. Cheap heuristic\r\n // that's good enough for a picker.\r\n const scored: Array<{ path: string; score: number }> = [];\r\n for (const p of results) {\r\n if (!query) {\r\n scored.push({ path: p, score: 0 });\r\n continue;\r\n }\r\n const lower = p.toLowerCase();\r\n const base = lower.split('/').pop() ?? lower;\r\n let score = 0;\r\n if (base === query) score = 100;\r\n else if (base.startsWith(query)) score = 60;\r\n else if (lower.includes(query)) score = 20;\r\n else continue;\r\n // Penalise depth so root files come first.\r\n score -= p.split('/').length;\r\n scored.push({ path: p, score });\r\n }\r\n scored.sort((a, b) => b.score - a.score || a.path.localeCompare(b.path));\r\n send(ws, {\r\n type: 'files.list',\r\n payload: { files: scored.slice(0, limit).map((s) => s.path) },\r\n });\r\n break;\r\n }\r\n\r\n case 'modes.list': {\r\n try {\r\n const modes = await modeStore.listModes();\r\n const active = await modeStore.getActiveMode();\r\n send(ws, {\r\n type: 'modes.list',\r\n payload: {\r\n modes: modes.map((m) => ({\r\n id: m.id,\r\n name: m.name,\r\n description: m.description,\r\n isActive: m.id === (active?.id ?? 'default'),\r\n })),\r\n activeId: active?.id ?? 'default',\r\n },\r\n });\r\n } catch (err) {\r\n send(ws, {\r\n type: 'modes.list',\r\n payload: {\r\n modes: [],\r\n activeId: 'default',\r\n error: err instanceof Error ? err.message : String(err),\r\n },\r\n });\r\n }\r\n break;\r\n }\r\n\r\n case 'mode.switch': {\r\n const { id } = (msg as { payload: { id: string } }).payload;\r\n try {\r\n // 'default' is the implicit no-mode state — persisting null\r\n // clears the override. Anything else has to exist in the store.\r\n if (id === 'default') {\r\n await modeStore.setActiveMode(null);\r\n } else {\r\n const found = await modeStore.getMode(id);\r\n if (!found) throw new Error(`Unknown mode \"${id}\"`);\r\n await modeStore.setActiveMode(id);\r\n }\r\n modeId = id;\r\n // Rebuild the system prompt so the next turn picks up the new\r\n // mode's instructions. The builder caches the environment block\r\n // per projectRoot (including the modeId), so we clear the cache\r\n // and rebuild. The `buildMode()` method reads this.opts.modePrompt\r\n // which is set on the builder constructor — we construct a fresh\r\n // builder with the updated mode. This is cheap (no fs/net IO in\r\n // the constructor; the real work happens in build()).\r\n const modePrompt = id === 'default' ? '' : ((await modeStore.getMode(id))?.prompt ?? '');\r\n const freshBuilder = new DefaultSystemPromptBuilder({\r\n memoryStore,\r\n skillLoader,\r\n modeStore,\r\n modeId: id,\r\n modePrompt,\r\n modelCapabilities,\r\n });\r\n context.systemPrompt = await freshBuilder.build({\r\n cwd: projectRoot,\r\n projectRoot,\r\n tools: toolRegistry.list(),\r\n provider: config.provider,\r\n model: config.model,\r\n });\r\n sendResult(ws, true, `Switched to mode \"${id}\"`);\r\n broadcast({\r\n type: 'session.start',\r\n payload: { ...(await sessionStartPayload()) },\r\n });\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n break;\r\n }\r\n\r\n case 'stats.get': {\r\n // Mirror of the CLI's /stats: detailed session report.\r\n const usage = tokenCounter.total();\r\n const cacheStats = tokenCounter.cacheStats();\r\n const m = await modelsRegistry.getModel(config.provider, config.model).catch(() => null);\r\n const inputCost = (m as { cost?: { input?: number } } | null)?.cost?.input ?? 0;\r\n const outputCost = (m as { cost?: { output?: number } } | null)?.cost?.output ?? 0;\r\n const cacheReadCost =\r\n (m as { cost?: { cache_read?: number } } | null)?.cost?.cache_read ?? 0;\r\n const cost =\r\n (usage.input * inputCost +\r\n usage.output * outputCost +\r\n (usage.cacheRead ?? 0) * cacheReadCost) /\r\n 1_000_000;\r\n send(ws, {\r\n type: 'stats.get',\r\n payload: {\r\n sessionId: session.id,\r\n provider: config.provider,\r\n model: config.model,\r\n usage,\r\n cache: cacheStats,\r\n cost,\r\n messages: context.messages.length,\r\n readFiles: context.readFiles.size,\r\n tools: toolRegistry.list().length,\r\n elapsedMs: Date.now() - sessionStartedAt,\r\n },\r\n });\r\n break;\r\n }\r\n\r\n default:\r\n if (msg.type.startsWith('autophase.')) {\r\n // Delegate all AutoPhase lifecycle messages to the handler\r\n await autoPhaseHandler.handleMessage(msg as { type: string; payload?: Record<string, unknown> });\r\n } else {\r\n send(ws, { type: 'error', payload: { phase: 'handleMessage', message: `Unknown message type: ${msg.type}` } });\r\n }\r\n }\r\n }\r\n\r\n // ---- Provider/Key management helpers (mirror packages/cli/src/webui-server.ts) ----\r\n\r\n async function loadSavedProviders(): Promise<Record<string, ProviderConfig>> {\r\n try {\r\n const raw = await fs.readFile(globalConfigPath, 'utf8');\r\n const parsed = JSON.parse(raw) as { providers?: Record<string, ProviderConfig> };\r\n if (!parsed.providers) return {};\r\n return decryptConfigSecrets(parsed.providers, vault);\r\n } catch {\r\n return {};\r\n }\r\n }\r\n\r\n async function saveProviders(providers: Record<string, ProviderConfig>): Promise<void> {\r\n configWriteLock = configWriteLock.then(async () => {\r\n let parsed: Record<string, unknown>;\r\n try {\r\n const raw = await fs.readFile(globalConfigPath, 'utf8');\r\n parsed = JSON.parse(raw) as Record<string, unknown>;\r\n } catch {\r\n parsed = {};\r\n }\r\n parsed['providers'] = providers;\r\n const encrypted = encryptConfigSecrets(parsed, vault);\r\n await atomicWrite(globalConfigPath, JSON.stringify(encrypted, null, 2), { mode: 0o600 });\r\n });\r\n await configWriteLock;\r\n }\r\n\r\n function normalizeKeys(cfg: ProviderConfig): ProviderApiKey[] {\r\n if (Array.isArray(cfg.apiKeys) && cfg.apiKeys.length > 0) {\r\n return cfg.apiKeys.map((k) => ({ ...k }));\r\n }\r\n if (typeof cfg.apiKey === 'string' && cfg.apiKey.length > 0) {\r\n return [{ label: 'default', apiKey: cfg.apiKey, createdAt: '' }];\r\n }\r\n return [];\r\n }\r\n\r\n function writeKeysBack(cfg: ProviderConfig, keys: ProviderApiKey[]): void {\r\n if (keys.length === 0) {\r\n delete cfg.apiKeys;\r\n delete cfg.apiKey;\r\n delete cfg.activeKey;\r\n return;\r\n }\r\n cfg.apiKeys = keys;\r\n const active = keys.find((k) => k.label === cfg.activeKey) ?? keys[0]!;\r\n cfg.apiKey = active.apiKey;\r\n if (!cfg.activeKey || !keys.some((k) => k.label === cfg.activeKey)) {\r\n cfg.activeKey = active.label;\r\n }\r\n }\r\n\r\n function maskedKey(key: string | undefined): string {\r\n if (!key) return '—';\r\n if (key.length <= 8) return '•'.repeat(key.length);\r\n return `${key.slice(0, 4)}…${key.slice(-4)}`;\r\n }\r\n\r\n function sendResult(ws: WebSocket, success: boolean, message: string): void {\r\n send(ws, { type: 'key.operation_result', payload: { success, message } });\r\n }\r\n\r\n async function handleKeyUpsert(\r\n ws: WebSocket,\r\n providerId: string,\r\n label: string,\r\n apiKey: string,\r\n ): Promise<void> {\r\n try {\r\n const providers = await loadSavedProviders();\r\n const existing: ProviderConfig = providers[providerId] ?? { type: providerId };\r\n const keys = normalizeKeys(existing);\r\n const idx = keys.findIndex((k) => k.label === label);\r\n const nowIso = new Date().toISOString();\r\n if (idx >= 0) {\r\n keys[idx] = { ...keys[idx]!, apiKey, createdAt: nowIso };\r\n } else {\r\n keys.push({ label, apiKey, createdAt: nowIso });\r\n }\r\n writeKeysBack(existing, keys);\r\n if (!existing.activeKey) existing.activeKey = label;\r\n providers[providerId] = existing;\r\n await saveProviders(providers);\r\n sendResult(ws, true, `Key \"${label}\" saved for ${providerId}`);\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n }\r\n\r\n async function handleKeyDelete(ws: WebSocket, providerId: string, label: string): Promise<void> {\r\n try {\r\n const providers = await loadSavedProviders();\r\n const existing = providers[providerId];\r\n if (!existing) {\r\n sendResult(ws, false, `Provider \"${providerId}\" not found`);\r\n return;\r\n }\r\n const keys = normalizeKeys(existing).filter((k) => k.label !== label);\r\n if (keys.length === 0) {\r\n delete providers[providerId];\r\n } else {\r\n writeKeysBack(existing, keys);\r\n if (existing.activeKey === label) existing.activeKey = keys[0]!.label;\r\n providers[providerId] = existing;\r\n }\r\n await saveProviders(providers);\r\n sendResult(ws, true, `Key \"${label}\" deleted from ${providerId}`);\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n }\r\n\r\n async function handleKeySetActive(\r\n ws: WebSocket,\r\n providerId: string,\r\n label: string,\r\n ): Promise<void> {\r\n try {\r\n const providers = await loadSavedProviders();\r\n const existing = providers[providerId];\r\n if (!existing) {\r\n sendResult(ws, false, `Provider \"${providerId}\" not found`);\r\n return;\r\n }\r\n existing.activeKey = label;\r\n writeKeysBack(existing, normalizeKeys(existing));\r\n providers[providerId] = existing;\r\n await saveProviders(providers);\r\n sendResult(ws, true, `Active key for ${providerId} set to \"${label}\"`);\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n }\r\n\r\n async function handleProviderAdd(\r\n ws: WebSocket,\r\n payload: { id: string; family: string; baseUrl?: string; apiKey?: string },\r\n ): Promise<void> {\r\n try {\r\n const providers = await loadSavedProviders();\r\n if (providers[payload.id]) {\r\n sendResult(ws, false, `Provider \"${payload.id}\" already exists. Use key.add to add a key.`);\r\n return;\r\n }\r\n const newProv: ProviderConfig = {\r\n type: payload.id,\r\n family: payload.family as ProviderConfig['family'],\r\n baseUrl: payload.baseUrl,\r\n };\r\n if (payload.apiKey) {\r\n newProv.apiKeys = [\r\n { label: 'default', apiKey: payload.apiKey, createdAt: new Date().toISOString() },\r\n ];\r\n newProv.activeKey = 'default';\r\n }\r\n providers[payload.id] = newProv;\r\n await saveProviders(providers);\r\n sendResult(ws, true, `Provider \"${payload.id}\" added`);\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n }\r\n\r\n async function handleProviderRemove(ws: WebSocket, providerId: string): Promise<void> {\r\n try {\r\n const providers = await loadSavedProviders();\r\n if (!providers[providerId]) {\r\n sendResult(ws, false, `Provider \"${providerId}\" not found`);\r\n return;\r\n }\r\n delete providers[providerId];\r\n await saveProviders(providers);\r\n sendResult(ws, true, `Provider \"${providerId}\" removed`);\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n }\r\n\r\n // HTTP server for the React frontend (port 3456)\r\n const httpPort = Number.parseInt(process.env['PORT'] ?? '3456', 10);\r\n const DIST_DIR = path.resolve(import.meta.dirname, '../../dist');\r\n\r\n const mimeTypes: Record<string, string> = {\r\n '.html': 'text/html',\r\n '.js': 'application/javascript',\r\n '.css': 'text/css',\r\n '.json': 'application/json',\r\n '.svg': 'image/svg+xml',\r\n '.png': 'image/png',\r\n '.ico': 'image/x-icon',\r\n };\r\n\r\n const httpServer = http.createServer(async (req, res) => {\r\n try {\r\n const url = new URL(req.url ?? '/', `http://127.0.0.1:${httpPort}`);\r\n let filePath: string;\r\n\r\n if (url.pathname === '/' || url.pathname === '') {\r\n filePath = path.join(DIST_DIR, 'index.html');\r\n } else if (url.pathname.startsWith('/assets/')) {\r\n filePath = path.join(DIST_DIR, url.pathname);\r\n } else if (url.pathname.startsWith('/')) {\r\n filePath = path.join(DIST_DIR, url.pathname);\r\n } else {\r\n filePath = path.join(DIST_DIR, 'index.html');\r\n }\r\n\r\n // Path traversal guard: the resolved path must stay inside DIST_DIR.\r\n // new URL() decodes percent-encoding (%2e%2e → ..), so path.join alone\r\n // does not prevent ../../../etc/passwd escapes.\r\n const resolvedPath = path.resolve(filePath);\r\n const resolvedRoot = path.resolve(DIST_DIR);\r\n if (!resolvedPath.startsWith(resolvedRoot + path.sep) && resolvedPath !== resolvedRoot) {\r\n res.writeHead(403, { 'Content-Type': 'text/plain' });\r\n res.end('Forbidden');\r\n return;\r\n }\r\n\r\n const ext = path.extname(resolvedPath);\r\n const contentType = mimeTypes[ext] ?? 'application/octet-stream';\r\n res.setHeader('Content-Type', contentType);\r\n res.setHeader('X-Content-Type-Options', 'nosniff');\r\n res.setHeader('X-Frame-Options', 'DENY');\r\n res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');\r\n\r\n if (ext === '.html') {\r\n res.setHeader('Cache-Control', 'no-cache');\r\n res.setHeader('Content-Security-Policy', HTML_CSP);\r\n }\r\n\r\n const fileContent = await fs.readFile(resolvedPath);\r\n res.writeHead(200);\r\n res.end(fileContent);\r\n } catch (err) {\r\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\r\n // Try index.html for SPA routing\r\n try {\r\n const fileContent = await fs.readFile(path.join(DIST_DIR, 'index.html'));\r\n res.writeHead(200, {\r\n 'Content-Type': 'text/html',\r\n 'X-Content-Type-Options': 'nosniff',\r\n 'X-Frame-Options': 'DENY',\r\n 'Referrer-Policy': 'strict-origin-when-cross-origin',\r\n // SPA fallback previously shipped no CSP — apply the same policy as\r\n // the direct .html branch so deep-linked routes aren't unprotected.\r\n 'Content-Security-Policy': HTML_CSP,\r\n });\r\n res.end(fileContent);\r\n } catch {\r\n res.writeHead(404);\r\n res.end('Not found');\r\n }\r\n } else {\r\n res.writeHead(500);\r\n res.end('Server error');\r\n }\r\n }\r\n });\r\n\r\n httpServer.listen(httpPort, wsHost, () => {\r\n console.log(`[WebUI] HTTP server running on http://${wsHost}:${httpPort}`);\r\n });\r\n\r\n // Graceful shutdown\r\n const shutdown = async () => {\r\n console.log('[WebUI] Shutting down...');\r\n try {\r\n await session.append({\r\n type: 'session_end',\r\n ts: new Date().toISOString(),\r\n usage: tokenCounter.total(),\r\n });\r\n await session.close();\r\n } catch (e) {\r\n console.warn('[WebUI] Error closing session:', e);\r\n }\r\n for (const [ws] of clients) ws.close();\r\n httpServer.close();\r\n wssPrimary.close();\r\n wssSecondary?.close();\r\n process.exit(0);\r\n };\r\n\r\n process.on('SIGINT', shutdown);\r\n process.on('SIGTERM', shutdown);\r\n}\r\n","import {\r\n Container,\r\n DefaultConfigStore,\r\n DefaultErrorHandler,\r\n DefaultMemoryStore,\r\n DefaultModeStore,\r\n DefaultPermissionPolicy,\r\n DefaultRetryPolicy,\r\n DefaultSecretScrubber,\r\n DefaultSessionStore,\r\n DefaultSkillLoader,\r\n DefaultSystemPromptBuilder,\r\n DefaultTokenCounter,\r\n HybridCompactor,\r\n TOKENS,\r\n type Config,\r\n type Logger,\r\n type ModelsRegistry,\r\n type Tool,\r\n type WstackPaths,\r\n} from '@wrongstack/core';\r\nimport type { DefaultSystemPromptBuilderOptions } from '@wrongstack/core';\r\n\r\nexport interface CreateContainerOptions {\r\n config: Config;\r\n wpaths: WstackPaths;\r\n logger: Logger;\r\n modelsRegistry: ModelsRegistry;\r\n permission?: {\r\n yolo?: boolean;\r\n forceAllYolo?: boolean;\r\n promptDelegate?: (\r\n tool: Tool,\r\n input: unknown,\r\n suggestedPattern: string,\r\n ) => Promise<'yes' | 'no' | 'always' | 'deny'>;\r\n };\r\n compactor?: { preserveK?: number; eliseThreshold?: number };\r\n systemPrompt?: Partial<DefaultSystemPromptBuilderOptions>;\r\n /** Bundled skills directory path (resolved at boot time). */\r\n bundledSkillsDir?: string;\r\n}\r\n\r\n/**\r\n * Create a Container pre-bound with all default service implementations.\r\n * Both CLI and WebUI use this factory so container wiring stays in one place.\r\n */\r\nexport function createDefaultContainer(opts: CreateContainerOptions): Container {\r\n const { config, wpaths, logger, modelsRegistry } = opts;\r\n const container = new Container();\r\n\r\n const configStore = new DefaultConfigStore(config);\r\n container.bind(TOKENS.ConfigStore, () => configStore);\r\n container.bind(TOKENS.Logger, () => logger);\r\n container.bind(TOKENS.SecretScrubber, () => new DefaultSecretScrubber());\r\n container.bind(TOKENS.RetryPolicy, () => new DefaultRetryPolicy());\r\n container.bind(TOKENS.ErrorHandler, () => new DefaultErrorHandler());\r\n container.bind(TOKENS.ModelsRegistry, () => modelsRegistry);\r\n container.bind(TOKENS.TokenCounter, () => new DefaultTokenCounter({ registry: modelsRegistry, providerId: config.provider }));\r\n\r\n const modeStore = new DefaultModeStore({ directory: wpaths.configDir });\r\n container.bind(TOKENS.ModeStore, () => modeStore);\r\n container.bind(TOKENS.SessionStore, () => new DefaultSessionStore({ dir: wpaths.projectSessions }));\r\n\r\n const memoryStore = new DefaultMemoryStore({ paths: wpaths });\r\n container.bind(TOKENS.MemoryStore, () => memoryStore);\r\n\r\n const skillLoader = new DefaultSkillLoader({ paths: wpaths, bundledDir: opts.bundledSkillsDir });\r\n container.bind(TOKENS.SkillLoader, () => skillLoader);\r\n\r\n if (opts.systemPrompt) {\r\n container.bind(TOKENS.SystemPromptBuilder, () => new DefaultSystemPromptBuilder(opts.systemPrompt as DefaultSystemPromptBuilderOptions));\r\n }\r\n\r\n container.bind(TOKENS.PermissionPolicy, () =>\r\n new DefaultPermissionPolicy({\r\n trustFile: wpaths.projectTrust,\r\n yolo: opts.permission?.yolo ?? false,\r\n forceAllYolo: opts.permission?.forceAllYolo ?? false,\r\n promptDelegate: opts.permission?.promptDelegate,\r\n }),\r\n );\r\n\r\n container.bind(TOKENS.Compactor, () =>\r\n new HybridCompactor({\r\n preserveK: opts.compactor?.preserveK ?? 20,\r\n eliseThreshold: opts.compactor?.eliseThreshold ?? 0.7,\r\n }),\r\n );\r\n\r\n return container;\r\n}\r\n","import * as fs from 'node:fs/promises';\nimport * as os from 'node:os';\nimport {\n DefaultConfigLoader,\n DefaultLogger,\n DefaultPathResolver,\n DefaultSecretVault,\n type Config,\n type WstackPaths,\n migratePlaintextSecrets,\n resolveWstackPaths,\n} from '@wrongstack/core';\n\nexport interface BootResult {\n config: Config;\n vault: DefaultSecretVault;\n globalConfigPath: string;\n projectRoot: string;\n wpaths: WstackPaths;\n logger: InstanceType<typeof DefaultLogger>;\n}\n\n/**\n * Boot config the same way the CLI does (mirrors packages/cli/src/boot-config.ts):\n * - resolve wstack paths\n * - create the real DefaultSecretVault (AES-GCM, not XOR)\n * - migrate any plaintext secrets in config files to encrypted form\n * - load + merge global/project config with apiKeys auto-decrypted\n */\nexport async function bootConfig(): Promise<BootResult> {\n const cwd = process.cwd();\n const pathResolver = new DefaultPathResolver(cwd);\n const projectRoot = pathResolver.projectRoot;\n const userHome = os.homedir();\n const wpaths = resolveWstackPaths({ projectRoot, userHome });\n\n await fs.mkdir(wpaths.globalRoot, { recursive: true });\n await fs.mkdir(wpaths.projectDir, { recursive: true });\n await fs.mkdir(wpaths.projectSessions, { recursive: true });\n\n const vault = new DefaultSecretVault({ keyFile: wpaths.secretsKey });\n\n for (const file of [wpaths.globalConfig, wpaths.projectLocalConfig]) {\n try {\n const { migrated } = await migratePlaintextSecrets(file, vault);\n if (migrated > 0) {\n process.stderr.write(`[WebUI] Encrypted ${migrated} plaintext secret(s) in ${file}\\n`);\n }\n } catch {\n // best-effort\n }\n }\n\n const configLoader = new DefaultConfigLoader({ paths: wpaths, vault });\n const config = await configLoader.load({ cliFlags: {} });\n\n const logger = new DefaultLogger({\n level: config.log?.level ?? 'info',\n file: wpaths.logFile,\n });\n\n return { config, vault, globalConfigPath: wpaths.globalConfig, projectRoot, wpaths, logger };\n}\n\nexport function patchConfig(config: Config, updates: Partial<Config>): Config {\n return Object.freeze({ ...config, ...updates });\n}\n","import type { WebSocket } from 'ws';\nimport {\n AutoPhasePlanner,\n PhaseGraphBuilder,\n PhaseOrchestrator,\n PhaseStore,\n type PhaseGraph,\n type PhaseProgress,\n type PhaseTemplate,\n} from '@wrongstack/core';\nimport type { Agent, Context, Logger } from '@wrongstack/core';\n\ninterface WSClient {\n ws: WebSocket;\n id: string;\n}\n\ninterface AutoPhaseWSMessage {\n type: string;\n payload?: Record<string, unknown>;\n}\n\n/**\n * AutoPhaseWebSocketHandler — WebSocket üzerinden AutoPhase kontrolü.\n *\n * Mesaj tipleri:\n * autophase.start → { title, phases?, autonomous? }\n * autophase.pause → {}\n * autophase.resume → {}\n * autophase.stop → {}\n * autophase.status → {}\n * autophase.selectPhase → { phaseId }\n * autophase.taskStatus → { taskId, status }\n */\nexport class AutoPhaseWebSocketHandler {\n private orchestrator: PhaseOrchestrator | null = null;\n private graph: PhaseGraph | null = null;\n private store: PhaseStore;\n private clients = new Set<WSClient>();\n private broadcastInterval: ReturnType<typeof setInterval> | null = null;\n /** Aborts in-flight task agents when the run is stopped. */\n private abort: AbortController | null = null;\n\n constructor(\n private agent: Agent,\n private context: Context,\n private logger: Logger,\n storeDir: string,\n ) {\n this.store = new PhaseStore({ baseDir: storeDir });\n }\n\n addClient(ws: WebSocket): void {\n const client: WSClient = { ws, id: crypto.randomUUID() };\n this.clients.add(client);\n\n ws.on('close', () => this.clients.delete(client));\n ws.on('error', () => this.clients.delete(client));\n\n // Anlık durum gönder\n this.sendState(client);\n }\n\n async handleMessage(msg: AutoPhaseWSMessage): Promise<void> {\n switch (msg.type) {\n case 'autophase.start':\n await this.handleStart(msg.payload);\n break;\n case 'autophase.pause':\n this.orchestrator?.pause();\n this.broadcast({ type: 'autophase.paused', payload: {} });\n break;\n case 'autophase.resume':\n this.orchestrator?.resume();\n this.broadcast({ type: 'autophase.resumed', payload: {} });\n break;\n case 'autophase.stop':\n this.abort?.abort();\n this.orchestrator?.stop();\n this.stopBroadcast();\n if (this.graph) void this.store.save(this.graph);\n this.broadcast({ type: 'autophase.stopped', payload: {} });\n break;\n case 'autophase.status':\n this.broadcastState();\n break;\n case 'autophase.selectPhase': {\n const phaseId = msg.payload?.phaseId as string;\n if (phaseId && this.graph) {\n this.broadcastState(phaseId);\n }\n break;\n }\n case 'autophase.taskStatus': {\n const { taskId, status } = msg.payload as { taskId: string; status: string };\n await this.handleTaskStatusChange(taskId, status);\n break;\n }\n case 'autophase.toggleAutonomous': {\n const autonomous = (msg.payload?.autonomous as boolean) ?? !this.graph?.autonomous;\n if (this.graph) {\n this.graph.autonomous = autonomous;\n await this.store.save(this.graph);\n this.broadcast({ type: 'autophase.state', payload: this.buildState() });\n }\n break;\n }\n case 'autophase.save': {\n if (this.graph) {\n await this.store.save(this.graph);\n this.broadcast({ type: 'autophase.saved', payload: { graphId: this.graph.id } });\n }\n break;\n }\n case 'autophase.list': {\n const graphs = await this.store.list();\n this.broadcast({ type: 'autophase.list', payload: { graphs } });\n break;\n }\n case 'autophase.load': {\n const graphId = msg.payload?.graphId as string | undefined;\n if (graphId) {\n const graph = await this.store.load(graphId);\n if (graph) {\n this.graph = graph;\n this.broadcast({ type: 'autophase.state', payload: this.buildState() });\n } else {\n this.broadcast({ type: 'autophase.error', payload: { message: `Graph not found: ${graphId}` } });\n }\n }\n break;\n }\n }\n }\n\n private async handleStart(payload?: Record<string, unknown>): Promise<void> {\n const title = (payload?.goal as string) || (payload?.title as string) || 'Untitled Project';\n const autonomous = (payload?.autonomous as boolean) ?? true;\n\n // Phase plan resolution:\n // 1. explicit phases in the payload win (caller override);\n // 2. otherwise the LLM plans phases+todos for the goal;\n // 3. failing that, fall back to the generic default phases.\n const phases = Array.isArray(payload?.phases)\n ? (payload.phases as PhaseTemplate[])\n : await this.planPhases(title);\n\n this.logger.info(`[AutoPhase] Starting: ${title}`);\n\n // Build the graph up-front so we have a reference for live broadcasts and\n // persistence *before* the (long-running) build begins.\n const graph = await new PhaseGraphBuilder({ title, phases, autonomous }).build();\n this.graph = graph;\n this.abort = new AbortController();\n await this.store.save(graph);\n\n this.orchestrator = new PhaseOrchestrator({\n graph,\n ctx: {\n executeTask: async (task, phaseId) => {\n this.logger.info(`[AutoPhase] [${phaseId}] Executing: ${task.title}`);\n const result = await this.executeTaskWithAgent(task, phaseId);\n this.logger.info(`[AutoPhase] [${phaseId}] Completed: ${task.title}`);\n return result;\n },\n onPhaseComplete: (phase) => {\n this.logger.info(`[AutoPhase] Phase completed: ${phase.name}`);\n void this.store.save(graph);\n this.broadcastState();\n },\n onPhaseFail: (phase, error) => {\n this.logger.error(`[AutoPhase] Phase failed: ${phase.name} — ${error.message}`);\n void this.store.save(graph);\n this.broadcastState();\n },\n },\n autonomous,\n maxConcurrentPhases: 1,\n // Sequential within a phase: each todo is a full-tool agent editing the\n // shared working tree, so running two at once risks concurrent writes.\n maxConcurrentTasks: 1,\n });\n\n // Start the live broadcast immediately, then run the orchestrator in the\n // background. Awaiting start() would block until the *entire* build\n // finishes — the periodic broadcast (below) reads the mutating graph, so\n // clients see live progress while it runs.\n this.startBroadcast();\n this.broadcastState();\n\n void this.orchestrator\n .start()\n .then(() => {\n this.orchestrator?.stop(); // clear the autonomous tick interval\n void this.store.save(graph);\n this.stopBroadcast();\n const failed = graph.failedPhaseIds.length > 0;\n this.broadcast(\n failed\n ? { type: 'autophase.failed', payload: { title } }\n : { type: 'autophase.completed', payload: { title } },\n );\n this.broadcastState();\n })\n .catch((err: unknown) => {\n this.logger.error(`[AutoPhase] Aborted: ${err instanceof Error ? err.message : String(err)}`);\n this.stopBroadcast();\n this.broadcast({ type: 'autophase.failed', payload: { title, error: String(err) } });\n });\n }\n\n /** Generic fallback phases when the LLM planner produces nothing usable. */\n private defaultPhases(): PhaseTemplate[] {\n return [\n { name: 'Discovery', description: 'Requirements gathering', priority: 'high', estimateHours: 2, parallelizable: false },\n { name: 'Design', description: 'Architecture and design', priority: 'critical', estimateHours: 4, parallelizable: false },\n { name: 'Implementation', description: 'Core development', priority: 'critical', estimateHours: 12, parallelizable: false },\n { name: 'Testing', description: 'Unit and integration tests', priority: 'high', estimateHours: 6, parallelizable: true },\n { name: 'Deployment', description: 'Deploy to production', priority: 'medium', estimateHours: 2, parallelizable: false },\n ];\n }\n\n /** Plan phases+todos for the goal via the LLM; fall back to defaults on failure. */\n private async planPhases(goal: string): Promise<PhaseTemplate[]> {\n try {\n const planner = new AutoPhasePlanner({\n goal,\n runOnce: async (prompt) => {\n const result = (await this.agent.run(prompt, { signal: new AbortController().signal })) as {\n status: string;\n finalText?: string;\n };\n return result.status === 'done' ? (result.finalText ?? '') : '';\n },\n });\n const { phases, parseFailed } = await planner.plan();\n if (!parseFailed && phases.length > 0) {\n const todos = phases.reduce((n, p) => n + (p.taskTemplates?.length ?? 0), 0);\n this.logger.info(`[AutoPhase] Planned ${phases.length} phases / ${todos} todos for: ${goal}`);\n return phases;\n }\n this.logger.info(`[AutoPhase] Planner produced no phases; using defaults for: ${goal}`);\n } catch (err) {\n this.logger.error(`[AutoPhase] Planning failed, using defaults: ${err instanceof Error ? err.message : String(err)}`);\n }\n return this.defaultPhases();\n }\n\n private async executeTaskWithAgent(task: import('@wrongstack/core').TaskNode, phaseId: string): Promise<unknown> {\n // Task'ı agent'a çalıştır\n const prompt = `Execute task: ${task.title}\\n\\nDescription: ${task.description}\\nPhase: ${phaseId}\\nPriority: ${task.priority}\\nType: ${task.type}`;\n const signal = this.abort?.signal ?? new AbortController().signal;\n const result = await this.agent.run(prompt, { signal });\n return result;\n }\n\n private async handleTaskStatusChange(taskId: string, status: string): Promise<void> {\n if (!this.graph) return;\n\n for (const phase of this.graph.phases.values()) {\n const task = phase.taskGraph.nodes.get(taskId);\n if (task) {\n task.status = status as import('@wrongstack/core').TaskStatus;\n task.updatedAt = Date.now();\n this.broadcastState();\n return;\n }\n }\n }\n\n private startBroadcast(): void {\n if (this.broadcastInterval) return;\n this.broadcastInterval = setInterval(() => {\n const progress = this.orchestrator?.getProgress();\n if (progress) this.broadcast({ type: 'autophase.progress', payload: progress });\n this.broadcastState();\n }, 2000);\n }\n\n private stopBroadcast(): void {\n if (this.broadcastInterval) {\n clearInterval(this.broadcastInterval);\n this.broadcastInterval = null;\n }\n }\n\n private broadcastState(activePhaseId?: string): void {\n if (!this.graph) return;\n\n const state = this.buildState(activePhaseId);\n this.broadcast({ type: 'autophase.state', payload: state });\n }\n\n private buildState(activePhaseId?: string): Record<string, unknown> {\n if (!this.graph) {\n return { phases: [], tasks: [], overallPercent: 0, autonomous: true, title: '' };\n }\n\n const phases = Array.from(this.graph.phases.values());\n const currentActiveId = activePhaseId || phases.find((p) => p.status === 'running')?.id || phases[0]?.id || '';\n const activePhase = this.graph.phases.get(currentActiveId);\n\n const totalTasks = phases.reduce((sum, p) => sum + p.taskGraph.nodes.size, 0);\n const completedTasks = phases.reduce(\n (sum, p) => sum + Array.from(p.taskGraph.nodes.values()).filter((t) => t.status === 'completed').length,\n 0,\n );\n\n const phaseItems = phases.map((p) => ({\n id: p.id,\n name: p.name,\n description: p.description,\n status: p.status,\n priority: p.priority,\n estimateHours: p.estimateHours,\n actualDurationMs: p.actualDurationMs,\n startedAt: p.startedAt,\n completedAt: p.completedAt,\n progressPercent: p.taskGraph.nodes.size > 0\n ? Math.round((Array.from(p.taskGraph.nodes.values()).filter((t) => t.status === 'completed').length / p.taskGraph.nodes.size) * 100)\n : 0,\n taskCount: p.taskGraph.nodes.size,\n completedTasks: Array.from(p.taskGraph.nodes.values()).filter((t) => t.status === 'completed').length,\n assignedAgents: p.assignedAgents,\n isActive: p.id === currentActiveId,\n }));\n\n const taskItems = activePhase\n ? Array.from(activePhase.taskGraph.nodes.values()).map((t) => ({\n id: t.id,\n title: t.title,\n description: t.description,\n status: t.status,\n priority: t.priority,\n type: t.type,\n estimateHours: t.estimateHours,\n actualHours: t.actualHours,\n assignee: t.assignee,\n tags: t.tags || [],\n startedAt: t.startedAt,\n completedAt: t.completedAt,\n }))\n : [];\n\n const completedPhases = phases.filter((p) => p.status === 'completed').length;\n\n return {\n title: this.graph.title,\n phases: phaseItems,\n tasks: taskItems,\n activePhaseId: currentActiveId,\n overallPercent: phases.length > 0 ? Math.round((completedPhases / phases.length) * 100) : 0,\n autonomous: this.graph.autonomous,\n totalTasks,\n completedTasks,\n };\n }\n\n private sendState(client: WSClient): void {\n if (!this.graph) return;\n const state = this.buildState();\n this.send(client, { type: 'autophase.state', payload: state });\n }\n\n private broadcast(msg: { type: string; payload: unknown }): void {\n const data = JSON.stringify(msg);\n for (const client of this.clients) {\n if (client.ws.readyState === 1) { // OPEN\n client.ws.send(data);\n }\n }\n }\n\n private send(client: WSClient, msg: { type: string; payload: unknown }): void {\n if (client.ws.readyState === 1) {\n client.ws.send(JSON.stringify(msg));\n }\n }\n}\n"],"mappings":"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","names":["fs","DefaultMemoryStore","DefaultModeStore","DefaultSessionStore","DefaultSkillLoader","DefaultSystemPromptBuilder","DefaultTokenCounter","HybridCompactor","TOKENS","TOKENS","DefaultMemoryStore","DefaultSessionStore","DefaultTokenCounter","DefaultModeStore","DefaultSkillLoader","DefaultSystemPromptBuilder","HybridCompactor","resolve","provider","modePrompt"]}
|
|
1
|
+
{"version":3,"sources":["../../src/server/index.ts","../../../runtime/src/container.ts","../../src/server/boot.ts","../../src/server/autophase-ws-handler.ts","../../src/server/worktree-ws-handler.ts"],"sourcesContent":["import * as fs from 'node:fs/promises';\r\nimport * as http from 'node:http';\r\nimport * as os from 'node:os';\r\nimport * as path from 'node:path';\r\nimport {\r\n Agent,\r\n AutoCompactionMiddleware,\r\n type Config,\r\n Container,\r\n Context,\r\n DefaultConfigLoader,\r\n DefaultConfigStore,\r\n DefaultErrorHandler,\r\n DefaultLogger,\r\n DefaultMemoryStore,\r\n DefaultModeStore,\r\n DefaultModelsRegistry,\r\n DefaultPathResolver,\r\n DefaultPermissionPolicy,\r\n DefaultRetryPolicy,\r\n DefaultSecretScrubber,\r\n DefaultSecretVault,\r\n DefaultSessionStore,\r\n DefaultSkillLoader,\r\n DefaultSystemPromptBuilder,\r\n DefaultTokenCounter,\r\n estimateRequestTokens,\r\n EventBus,\r\n HybridCompactor,\r\n type ProviderApiKey,\r\n type ProviderConfig,\r\n type Provider,\r\n ProviderRegistry,\r\n TOKENS,\r\n ToolRegistry,\r\n type WstackPaths,\r\n atomicWrite,\r\n createDefaultPipelines,\r\n DEFAULT_CONTEXT_WINDOW_MODE_ID,\r\n DEFAULT_TOOLS_CONFIG,\r\n migratePlaintextSecrets,\r\n resolveWstackPaths,\r\n listContextWindowModes,\r\n repairToolUseAdjacency,\r\n resolveContextWindowPolicy,\r\n} from '@wrongstack/core';\r\nimport { ToolExecutor } from '@wrongstack/core/execution';\r\nimport { decryptConfigSecrets, encryptConfigSecrets } from '@wrongstack/core/security';\r\nimport { buildProviderFactoriesFromRegistry, makeProviderFromConfig } from '@wrongstack/providers';\r\nimport { builtinToolsPack, forgetTool, rememberTool } from '@wrongstack/tools';\r\nimport { WebSocket, WebSocketServer } from 'ws';\r\nimport { randomBytes, timingSafeEqual } from 'node:crypto';\r\nimport { createDefaultContainer } from '../../../runtime/src/container.js';\r\nimport { bootConfig, patchConfig, type BootResult } from './boot.js';\r\nimport { AutoPhaseWebSocketHandler } from './autophase-ws-handler.js';\r\nimport { WorktreeWebSocketHandler } from './worktree-ws-handler.js';\r\n\r\n// Re-export types\r\nexport type { WebUIOptions, BackendServices } from './types.js';\r\n\r\n// CSP for served HTML. script-src is 'self' only — the production bundle has no\r\n// inline scripts, so 'unsafe-inline' is dropped (defeats injected-script XSS).\r\n// style-src keeps 'unsafe-inline' because Radix/React inject inline styles at\r\n// runtime. object-src/base-uri/frame-ancestors/form-action are tightened as\r\n// defense-in-depth (frame-ancestors complements X-Frame-Options: DENY).\r\nconst HTML_CSP =\r\n \"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' ws: wss:; img-src 'self' data:; font-src 'self' data:; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; form-action 'self'\";\r\n\r\n// Internal message types\r\ninterface WSServerMessage {\r\n type: string;\r\n payload: unknown;\r\n}\r\n\r\ninterface WSClientMessage {\r\n type: string;\r\n payload?: unknown;\r\n}\r\n\r\ninterface ConnectedClient {\r\n ws: WebSocket;\r\n sessionId: string | null;\r\n connectedAt: number;\r\n}\r\n\r\nexport async function startWebUI(opts: { wsPort?: number; wsHost?: string } = {}): Promise<void> {\r\n const wsPort = opts.wsPort ?? 3457;\r\n // Bind to loopback IP by default (not the string \"localhost\", which on some\r\n // hosts resolves to IPv6 ::1 and surprises older WS clients). Set WS_HOST or\r\n // pass opts.wsHost to override (e.g. \"0.0.0.0\" for LAN access).\r\n const wsHost = opts.wsHost ?? '127.0.0.1';\r\n\r\n console.log('[WebUI] Starting backend services...');\r\n\r\n // Boot configuration\r\n const boot = await bootConfig();\r\n const { config: baseConfig, vault, globalConfigPath, projectRoot, wpaths, logger } = boot;\r\n let config = baseConfig;\r\n\r\n // Serialize concurrent config writes to prevent races between model.switch\r\n // and key.add/key.update handlers that both read-modify-write globalConfigPath.\r\n let configWriteLock: Promise<void> = Promise.resolve();\r\n\r\n console.log('[WebUI] Config loaded:', config.provider ?? '(none)', '/', config.model ?? '(none)');\r\n\r\n // If no active provider is set but there are saved providers, pick the first one.\r\n // This handles configs written in older formats or by external tools.\r\n if (!config.provider && config.providers && Object.keys(config.providers).length > 0) {\r\n const firstKey = Object.keys(config.providers)[0]!;\r\n config = patchConfig(config, { provider: firstKey });\r\n console.log('[WebUI] No active provider — auto-selected:', firstKey);\r\n }\r\n\r\n // If still no provider, the frontend will show a no-provider welcome screen.\r\n // We still start the HTTP/WS servers so the user can configure via the UI.\r\n const needsProvider = !config.provider || !config.model;\r\n\r\n // ModelsRegistry\r\n const modelsRegistry = new DefaultModelsRegistry({\r\n cacheFile: wpaths.modelsCache,\r\n ttlSeconds: 24 * 3600,\r\n });\r\n\r\n // Container via shared factory\r\n const container = createDefaultContainer({ config, wpaths, logger, modelsRegistry });\r\n const configStore = container.resolve(TOKENS.ConfigStore);\r\n\r\n // Provider registry\r\n const providerRegistry = new ProviderRegistry();\r\n try {\r\n const factories = await buildProviderFactoriesFromRegistry({\r\n registry: modelsRegistry,\r\n log: logger,\r\n });\r\n for (const f of factories) providerRegistry.register(f);\r\n console.log('[WebUI] Provider registry loaded:', providerRegistry.list().length, 'providers');\r\n } catch (err) {\r\n console.warn('[WebUI] Failed to load provider registry:', err);\r\n }\r\n\r\n // Tool registry\r\n const toolRegistry = new ToolRegistry();\r\n toolRegistry.registerAllOrThrow([...(builtinToolsPack.tools ?? [])], builtinToolsPack.name);\r\n\r\n // Memory tools\r\n const memoryStore = new DefaultMemoryStore({ paths: wpaths });\r\n if (config.features.memory) {\r\n toolRegistry.register(rememberTool(memoryStore));\r\n toolRegistry.register(forgetTool(memoryStore));\r\n }\r\n console.log('[WebUI] Tool registry loaded:', toolRegistry.list().length, 'tools');\r\n\r\n // Event bus\r\n const events = new EventBus();\r\n events.setLogger(logger);\r\n\r\n // Session store\r\n const sessionStore = new DefaultSessionStore({ dir: wpaths.projectSessions });\r\n let session = await sessionStore.create({\r\n id: '',\r\n title: '',\r\n model: config.model,\r\n provider: config.provider,\r\n });\r\n // Wall-clock when the *current* session started. Updated on /new and on\r\n // /resume so /stats can report accurate elapsed time per the active\r\n // session, not the daemon process uptime.\r\n let sessionStartedAt = Date.now();\r\n console.log('[WebUI] Session created:', session.id);\r\n\r\n // Token counter\r\n const tokenCounter = new DefaultTokenCounter({\r\n registry: modelsRegistry,\r\n providerId: config.provider,\r\n });\r\n\r\n // Mode store\r\n const modeStore = new DefaultModeStore({ directory: wpaths.configDir });\r\n const activeMode = await modeStore.getActiveMode();\r\n let modeId = activeMode?.id ?? 'default';\r\n const modePrompt = activeMode?.prompt ?? '';\r\n\r\n // System prompt builder\r\n const resolvedModel = await modelsRegistry.getModel(config.provider, config.model);\r\n const modelCapabilities = resolvedModel?.capabilities\r\n ? {\r\n maxContextTokens: resolvedModel.capabilities.maxContext,\r\n supportsTools: resolvedModel.capabilities.tools,\r\n supportsVision: resolvedModel.capabilities.vision,\r\n supportsReasoning: resolvedModel.capabilities.reasoning,\r\n }\r\n : undefined;\r\n\r\n const skillLoader = config.features.skills\r\n ? new DefaultSkillLoader({ paths: wpaths })\r\n : undefined;\r\n const systemPromptBuilder = new DefaultSystemPromptBuilder({\r\n memoryStore,\r\n skillLoader,\r\n modeStore,\r\n modeId,\r\n modePrompt,\r\n modelCapabilities,\r\n });\r\n\r\n const systemPrompt = await systemPromptBuilder.build({\r\n cwd: projectRoot,\r\n projectRoot,\r\n tools: toolRegistry.list(),\r\n provider: config.provider,\r\n model: config.model,\r\n });\r\n\r\n // Build provider (only if provider is configured)\r\n let provider: ReturnType<ProviderRegistry['create']>;\r\n if (!needsProvider) {\r\n const providerConfig = config.providers?.[config.provider] ?? {\r\n type: config.provider,\r\n apiKey: config.apiKey,\r\n baseUrl: config.baseUrl,\r\n };\r\n try {\r\n const cfgWithType = { ...providerConfig, type: config.provider };\r\n if (config.features.modelsRegistry && providerRegistry.has(config.provider)) {\r\n provider = providerRegistry.create(cfgWithType);\r\n } else {\r\n provider = makeProviderFromConfig(config.provider, cfgWithType);\r\n }\r\n } catch (err) {\r\n console.error('[WebUI] Failed to create provider:', err);\r\n throw err;\r\n }\r\n } else {\r\n // No provider is actively selected, but saved providers exist.\r\n // Re-read the config to find one with a usable encrypted API key\r\n // and create a real provider from it (the vault is already initialized).\r\n const savedProviders = config.providers ?? {};\r\n const firstKey = Object.keys(savedProviders)[0];\r\n if (firstKey) {\r\n const firstProvider = savedProviders[firstKey]!;\r\n try {\r\n provider = makeProviderFromConfig(firstKey, {\r\n ...firstProvider,\r\n type: firstKey,\r\n family: firstProvider.family,\r\n apiKey: firstProvider.apiKey,\r\n });\r\n console.log('[WebUI] Using saved provider:', firstKey);\r\n } catch (err) {\r\n console.error('[WebUI] Could not create provider stub:', err);\r\n throw err;\r\n }\r\n } else {\r\n throw new Error(\r\n 'No provider configured. Run `wrongstack init` first, or configure via the WebUI.',\r\n );\r\n }\r\n }\r\n\r\n // Context\r\n const context = new Context({\r\n systemPrompt,\r\n provider,\r\n session,\r\n signal: new AbortController().signal,\r\n tokenCounter,\r\n cwd: projectRoot,\r\n projectRoot,\r\n model: config.model,\r\n });\r\n const initialContextPolicy = resolveContextWindowPolicy(config.context);\r\n context.meta['contextWindowMode'] = initialContextPolicy.id;\r\n context.meta['contextWindowPolicy'] = initialContextPolicy;\r\n\r\n // Pipelines\r\n const pipelines = createDefaultPipelines();\r\n\r\n // Compactor\r\n const compactor = new HybridCompactor({\r\n preserveK: config.context?.preserveK ?? 20,\r\n eliseThreshold: config.context?.eliseThreshold ?? 0.7,\r\n });\r\n\r\n // Auto-compaction\r\n let autoCompactor: AutoCompactionMiddleware | undefined;\r\n if (config.context?.autoCompact !== false) {\r\n const effectiveMaxContext = config.context?.effectiveMaxContext ?? provider.capabilities.maxContext;\r\n autoCompactor = new AutoCompactionMiddleware(\r\n compactor,\r\n effectiveMaxContext,\r\n (ctx) => estimateRequestTokens(ctx.messages, ctx.systemPrompt, ctx.tools ?? []).total,\r\n {\r\n warn: initialContextPolicy.thresholds.warn,\r\n soft: initialContextPolicy.thresholds.soft,\r\n hard: initialContextPolicy.thresholds.hard,\r\n },\r\n {\r\n events,\r\n aggressiveOn: initialContextPolicy.aggressiveOn,\r\n policyProvider: (ctx) => {\r\n const policy = ctx.meta['contextWindowPolicy'];\r\n return policy && typeof policy === 'object'\r\n ? (policy as ReturnType<typeof resolveContextWindowPolicy>)\r\n : initialContextPolicy;\r\n },\r\n },\r\n );\r\n pipelines.contextWindow.use({ name: 'AutoCompaction', handler: autoCompactor.handler() });\r\n }\r\n\r\n /** Refresh AutoCompactionMiddleware denominator when the active model changes. */\r\n async function updateAutoCompactionMaxContext(newProvider: Provider): Promise<void> {\r\n if (!autoCompactor) return;\r\n let newMaxContext = config.context?.effectiveMaxContext ?? newProvider.capabilities.maxContext;\r\n try {\r\n const m = await modelsRegistry.getModel(newProvider.id, context.model);\r\n newMaxContext = m?.capabilities?.maxContext ?? newMaxContext;\r\n } catch {\r\n // best-effort: use provider capability\r\n }\r\n autoCompactor.setMaxContext(newMaxContext);\r\n }\r\n\r\n // Agent\r\n const secretScrubber = container.resolve(TOKENS.SecretScrubber);\r\n const renderer = container.has(TOKENS.Renderer)\r\n ? container.resolve(TOKENS.Renderer)\r\n : undefined;\r\n const toolExecutor = new ToolExecutor(toolRegistry, {\r\n permissionPolicy: container.resolve(TOKENS.PermissionPolicy),\r\n secretScrubber,\r\n renderer,\r\n events,\r\n confirmAwaiter: undefined,\r\n iterationTimeoutMs: config.tools?.iterationTimeoutMs ?? DEFAULT_TOOLS_CONFIG.iterationTimeoutMs,\r\n perIterationOutputCapBytes: config.tools?.perIterationOutputCapBytes ?? DEFAULT_TOOLS_CONFIG.perIterationOutputCapBytes,\r\n tracer: undefined,\r\n });\r\n\r\n const agent = new Agent({\r\n container,\r\n tools: toolRegistry,\r\n providers: providerRegistry,\r\n events,\r\n pipelines,\r\n context,\r\n maxIterations: config.tools?.maxIterations ?? DEFAULT_TOOLS_CONFIG.maxIterations,\r\n iterationTimeoutMs: config.tools?.iterationTimeoutMs ?? DEFAULT_TOOLS_CONFIG.iterationTimeoutMs,\r\n executionStrategy: config.tools?.defaultExecutionStrategy ?? DEFAULT_TOOLS_CONFIG.defaultExecutionStrategy,\r\n perIterationOutputCapBytes: config.tools?.perIterationOutputCapBytes ?? DEFAULT_TOOLS_CONFIG.perIterationOutputCapBytes,\r\n confirmAwaiter: undefined,\r\n toolExecutor,\r\n });\r\n console.log('[WebUI] Agent initialized');\r\n\r\n // AutoPhase handler — manages AutoPhaseRunner lifecycle via WS messages.\r\n // Stored under the per-project autophase dir (not the shared SDD task-graphs).\r\n const autoPhaseHandler = new AutoPhaseWebSocketHandler(\r\n agent,\r\n context,\r\n logger,\r\n wpaths.projectAutophase,\r\n events,\r\n projectRoot,\r\n );\r\n\r\n // Worktree handler — subscribes to the shared EventBus `worktree.*` events\r\n // and streams live swim-lane / DAG state to connected clients.\r\n const worktreeHandler = new WorktreeWebSocketHandler(events, logger);\r\n\r\n // Helper: build the rich session.start payload from current runtime state.\r\n // Centralised so initial connect, post-/new, and post-model.switch all\r\n // broadcast the same shape — frontend treats this as the single source of\r\n // truth for everything in the status bar (model, context window, project).\r\n async function sessionStartPayload(): Promise<{\r\n sessionId: string;\r\n model: string;\r\n provider: string;\r\n maxContext: number;\r\n /** USD per 1M input tokens (0 if unknown / free). */\r\n inputCost: number;\r\n /** USD per 1M output tokens. */\r\n outputCost: number;\r\n /** USD per 1M cache-read tokens. */\r\n cacheReadCost: number;\r\n projectName: string;\r\n cwd: string;\r\n mode: string;\r\n contextMode: string;\r\n wsToken: string;\r\n }> {\r\n let maxContext = 0;\r\n let inputCost = 0;\r\n let outputCost = 0;\r\n let cacheReadCost = 0;\r\n try {\r\n const m = await modelsRegistry.getModel(config.provider, config.model);\r\n maxContext = m?.capabilities?.maxContext ?? 0;\r\n // models.dev pricing is dollars per 1M tokens; some providers omit the\r\n // field for free/unmetered plans (e.g. minimax-coding-plan) — in that\r\n // case we report 0 and the cost chip just stays at $0.\r\n const cost = (\r\n m as { cost?: { input?: number; output?: number; cache_read?: number } } | undefined\r\n )?.cost;\r\n inputCost = cost?.input ?? 0;\r\n outputCost = cost?.output ?? 0;\r\n cacheReadCost = cost?.cache_read ?? 0;\r\n } catch {\r\n // best-effort\r\n }\r\n return {\r\n sessionId: session.id,\r\n model: config.model,\r\n provider: config.provider,\r\n maxContext,\r\n inputCost,\r\n outputCost,\r\n cacheReadCost,\r\n projectName: path.basename(projectRoot) || projectRoot,\r\n cwd: projectRoot,\r\n mode: modeId,\r\n contextMode: String(context.meta['contextWindowMode'] ?? DEFAULT_CONTEXT_WINDOW_MODE_ID),\r\n wsToken,\r\n };\r\n }\r\n\r\n // WebSocket server(s).\r\n //\r\n // When the user keeps the default loopback bind (127.0.0.1), we ALSO open a\r\n // second listener on ::1 (IPv6 loopback). Reason: Chrome/Edge on Windows\r\n // resolve `localhost` to `[::1]` before `127.0.0.1`, so a single v4-only\r\n // bind causes \"ws disconnect hep\" — clients hammer the v6 socket, get\r\n // ECONNREFUSED, fall back to v4 inconsistently. Listening on both v4 and v6\r\n // loopback keeps the connection scope \"this machine only\" while removing\r\n // the resolution-order coin flip.\r\n //\r\n // When the user explicitly sets WS_HOST (e.g. 0.0.0.0 or a LAN IP), we\r\n // respect that choice exactly and don't add a second listener.\r\n // Generate a random WS auth token so only callers that know the token\r\n // can connect. Printed to console on startup; the frontend reads it from\r\n // the URL query param `?token=...`. Without a token, any client on the\r\n // network can connect and send `user_message`/`key.add`/`model.switch`.\r\n const wsToken = randomBytes(16).toString('hex');\r\n // Token is sent to clients via session.start payload — log only a masked\r\n // prefix so operators can correlate without leaking the full secret.\r\n console.log(`[WebUI] WS auth token: ${wsToken.slice(0, 4)}…${wsToken.slice(-4)} (masked)`);\r\n\r\n // CSWSH guard + token auth: when the user exposes the socket beyond\r\n // loopback, require the shared token. Local loopback connections\r\n // without a token are still allowed for convenience.\r\n const isLoopback = (hostname: string) =>\r\n hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1' || hostname === '[::1]';\r\n\r\n // Constant-time token comparison: avoids leaking the token byte-by-byte via\r\n // response timing. Length mismatch short-circuits (lengths aren't secret).\r\n const tokenMatches = (provided: string | undefined): boolean => {\r\n if (!provided) return false;\r\n const a = Buffer.from(provided);\r\n const b = Buffer.from(wsToken);\r\n if (a.length !== b.length) return false;\r\n return timingSafeEqual(a, b);\r\n };\r\n\r\n // DNS-rebinding defense: the browser puts the *name it dialed* in the Host\r\n // header. A page on evil.com that rebinds DNS to 127.0.0.1 still sends\r\n // `Host: evil.com:<port>`, so requiring a loopback Host rejects rebinding\r\n // regardless of the bind address. The legitimate same-machine client dials\r\n // 127.0.0.1/localhost/[::1], so this never blocks real usage on a loopback\r\n // bind. When the operator deliberately exposes the socket (wsHost set to a\r\n // LAN/0.0.0.0 address) the Host will legitimately be non-loopback, so we\r\n // only enforce the loopback-Host requirement on a loopback bind.\r\n const hostHeaderOk = (req: import('node:http').IncomingMessage): boolean => {\r\n const boundToLoopback = wsHost === '127.0.0.1' || wsHost === '::1' || wsHost === 'localhost';\r\n if (!boundToLoopback) return true; // operator opted into wider exposure\r\n const hostHeader = (req.headers.host ?? '').trim();\r\n if (!hostHeader) return false;\r\n // Strip the port (handle bare host, host:port, and [::1]:port).\r\n let hostname: string;\r\n try {\r\n hostname = new URL(`http://${hostHeader}`).hostname;\r\n } catch {\r\n return false;\r\n }\r\n return isLoopback(hostname);\r\n };\r\n\r\n const verifyClient = (info: {\r\n origin: string;\r\n secure: boolean;\r\n req: import('node:http').IncomingMessage;\r\n }) => {\r\n const origin = info.origin;\r\n const url = info.req.url ?? '';\r\n const tokenMatch = url.match(/[?&]token=([^&]+)/);\r\n const providedToken = tokenMatch ? tokenMatch[1] : undefined;\r\n const tokenOk = tokenMatches(providedToken);\r\n\r\n // DNS-rebinding guard runs first on a loopback bind — independent of token\r\n // and Origin. Blocks a rebound attacker page (Host = attacker domain) even\r\n // though the TCP peer is 127.0.0.1.\r\n if (!hostHeaderOk(info.req)) return false;\r\n\r\n if (!origin) {\r\n // Non-browser clients (curl, scripts): require token unless on loopback.\r\n // When wsHost=0.0.0.0 the server accepts connections from any network\r\n // interface — token is mandatory in that case.\r\n const remoteIp = info.req.socket.remoteAddress ?? '';\r\n const isRemoteLoopback = remoteIp === '127.0.0.1' || remoteIp === '::1';\r\n if (!isRemoteLoopback && wsHost === '0.0.0.0') return false; // LAN exposure without token = deny\r\n return tokenOk || wsHost === '127.0.0.1' || wsHost === '::1' || wsHost === 'localhost';\r\n }\r\n try {\r\n const { hostname } = new URL(origin);\r\n // Loopback browser origins: allow without token (bootstrap — the token is\r\n // delivered in session.start and replayed on reconnect). The Host-header\r\n // guard above already rejects cross-site/rebinding pages here.\r\n if (isLoopback(hostname)) return true;\r\n // Non-loopback origins: token is mandatory.\r\n return tokenOk;\r\n } catch {\r\n return false;\r\n }\r\n };\r\n // Cap inbound frame size (8 MiB) so a single oversized message can't exhaust\r\n // memory. Agent messages are small; large pastes/attachments stay well under.\r\n const WS_MAX_PAYLOAD = 8 * 1024 * 1024;\r\n const wssPrimary = new WebSocketServer({\r\n port: wsPort,\r\n host: wsHost,\r\n verifyClient,\r\n maxPayload: WS_MAX_PAYLOAD,\r\n } as ConstructorParameters<typeof WebSocketServer>[0]);\r\n const wssSecondary =\r\n wsHost === '127.0.0.1'\r\n ? new WebSocketServer({\r\n port: wsPort,\r\n host: '::1',\r\n verifyClient,\r\n maxPayload: WS_MAX_PAYLOAD,\r\n } as ConstructorParameters<typeof WebSocketServer>[0])\r\n : null;\r\n const clients = new Map<WebSocket, ConnectedClient>();\r\n\r\n // Per-connection message rate limiting: 60 messages per 60-second window.\r\n // Exceeding clients are temporarily blocked to prevent flooding.\r\n const RATE_LIMIT_MESSAGES = 60;\r\n const RATE_LIMIT_WINDOW_MS = 60_000;\r\n const rateLimits = new Map<WebSocket, { count: number; resetAt: number }>();\r\n\r\n function checkRateLimit(ws: WebSocket): boolean {\r\n const now = Date.now();\r\n const limit = rateLimits.get(ws);\r\n if (!limit || now > limit.resetAt) {\r\n rateLimits.set(ws, { count: 1, resetAt: now + RATE_LIMIT_WINDOW_MS });\r\n return true;\r\n }\r\n if (limit.count >= RATE_LIMIT_MESSAGES) return false;\r\n limit.count++;\r\n return true;\r\n }\r\n\r\n /** Holds the AbortController for the currently in-flight agent.run().\r\n * Non-null while the agent is running; guarded at the user_message\r\n * handler to prevent concurrent runs that would corrupt shared state\r\n * (context, agent, tokenCounter). A second user_message while running\r\n * is answered with an inline error instead of being queued — the\r\n * caller should wait for run.result. */\r\n let runLock: AbortController | null = null;\r\n\r\n console.log(\r\n `[WebUI] WebSocket server running on ws://${wsHost}:${wsPort}` +\r\n (wssSecondary ? ` (and ws://[::1]:${wsPort})` : ''),\r\n );\r\n\r\n // Pending permission confirmations. When the agent emits\r\n // tool.confirm_needed, we store the resolve function here keyed by\r\n // toolUseId. When the client sends tool.confirm_result back, we look\r\n // it up and resolve — unblocking the agent loop.\r\n const pendingConfirms = new Map<string, (d: 'yes' | 'no' | 'always' | 'deny') => void>();\r\n\r\n // Event subscriptions\r\n function setupEvents() {\r\n events.on('iteration.started', (e) => {\r\n broadcast({\r\n type: 'iteration.started',\r\n payload: { index: e.index, maxIterations: config.tools?.maxIterations ?? 100 },\r\n });\r\n });\r\n\r\n events.on('provider.text_delta', (e) => {\r\n broadcast({ type: 'provider.text_delta', payload: { text: e.text, messageId: 'current' } });\r\n });\r\n\r\n events.on('provider.thinking_delta', (e) => {\r\n broadcast({ type: 'provider.thinking_delta', payload: { text: e.text } });\r\n });\r\n\r\n events.on('tool.started', (e) => {\r\n broadcast({\r\n type: 'tool.started',\r\n payload: { id: e.id, name: e.name, input: e.input, messageId: `tool_${e.id}` },\r\n });\r\n });\r\n\r\n events.on('tool.progress', (e) => {\r\n // Streaming progress (bash stdout chunks, fetch body deltas, scan\r\n // counts...). We forward the lightweight shape: id + type + text so\r\n // the UI can render an inline \"live\" preview while the tool is still\r\n // running. Heavy `data` blob is intentionally dropped here — the\r\n // frontend doesn't need it and broadcasting it would balloon the WS\r\n // traffic for tools that emit progress every few ms.\r\n broadcast({\r\n type: 'tool.progress',\r\n payload: {\r\n id: e.id,\r\n name: e.name,\r\n eventType: e.event.type,\r\n text: e.event.text,\r\n },\r\n });\r\n });\r\n\r\n events.on('tool.executed', (e) => {\r\n broadcast({\r\n type: 'tool.executed',\r\n payload: {\r\n // Forward the tool_use id so frontend can correlate with the\r\n // matching tool.started bubble — without this, parallel tool calls\r\n // all stay stuck on \"Running…\" because the frontend can't tell\r\n // which bubble this result belongs to.\r\n id: e.id,\r\n name: e.name,\r\n durationMs: e.durationMs,\r\n ok: e.ok,\r\n input: e.input,\r\n output: e.output,\r\n },\r\n });\r\n // Push the current todo snapshot too — the TodoWrite tool mutates\r\n // context.todos in place, and a side-panel that needs to react to\r\n // that change shouldn't have to poll. Cheap (todos are tiny).\r\n broadcast({\r\n type: 'todos.updated',\r\n payload: { todos: [...context.todos] },\r\n });\r\n });\r\n\r\n events.on('provider.response', (e) => {\r\n broadcast({\r\n type: 'provider.response',\r\n payload: {\r\n usage: e.usage,\r\n stopReason: e.stopReason,\r\n messageId: 'current',\r\n },\r\n });\r\n });\r\n\r\n events.on('context.repaired', (e) => {\r\n broadcast({\r\n type: 'context.repaired',\r\n payload: {\r\n removedToolUses: e.removedToolUses,\r\n removedToolResults: e.removedToolResults,\r\n removedMessages: e.removedMessages,\r\n },\r\n });\r\n });\r\n\r\n events.on('tool.confirm_needed', (e) => {\r\n const id = e.toolUseId ?? `confirm_${Date.now()}`;\r\n pendingConfirms.set(id, e.resolve);\r\n broadcast({\r\n type: 'tool.confirm_needed',\r\n payload: {\r\n id,\r\n toolName: e.tool?.name ?? 'unknown',\r\n input: e.input,\r\n suggestedPattern: e.suggestedPattern,\r\n },\r\n });\r\n });\r\n\r\n events.on('error', (e) => {\r\n broadcast({\r\n type: 'error',\r\n payload: {\r\n phase: e.phase,\r\n message: e.err instanceof Error ? e.err.message : String(e.err),\r\n },\r\n });\r\n });\r\n }\r\n\r\n function send(ws: WebSocket, msg: WSServerMessage): void {\r\n if (ws.readyState === WebSocket.OPEN) {\r\n ws.send(JSON.stringify(msg));\r\n }\r\n }\r\n\r\n function broadcast(msg: WSServerMessage): void {\r\n const data = JSON.stringify(msg);\r\n for (const [ws] of clients) {\r\n if (ws.readyState === WebSocket.OPEN) {\r\n ws.send(data);\r\n }\r\n }\r\n }\r\n\r\n const handleConnection = (ws: WebSocket): void => {\r\n const client: ConnectedClient = { ws, sessionId: session.id, connectedAt: Date.now() };\r\n clients.set(ws, client);\r\n console.log('[WebUI] Client connected, total:', clients.size);\r\n\r\n void sessionStartPayload().then((payload) => {\r\n send(ws, { type: 'session.start', payload });\r\n });\r\n\r\n // Register this client with the AutoPhase handler so it receives phase events\r\n autoPhaseHandler.addClient(ws);\r\n // …and the worktree handler for live isolation lanes.\r\n worktreeHandler.addClient(ws);\r\n\r\n ws.on('message', async (data) => {\r\n if (!checkRateLimit(ws)) {\r\n send(ws, {\r\n type: 'error',\r\n payload: {\r\n phase: 'rate_limit',\r\n message: 'Too many messages. Please wait before sending more.',\r\n },\r\n });\r\n return;\r\n }\r\n try {\r\n const msg = JSON.parse(data.toString()) as WSClientMessage;\r\n await handleMessage(ws, client, msg);\r\n } catch (err) {\r\n console.error('[WebUI] Failed to parse message', err);\r\n }\r\n });\r\n\r\n ws.on('close', () => {\r\n clients.delete(ws);\r\n rateLimits.delete(ws);\r\n console.log('[WebUI] Client disconnected, total:', clients.size);\r\n // If the client disconnects while a permission prompt is pending,\r\n // resolve all pending confirms with 'no' so the agent loop doesn't\r\n // hang forever waiting for a response that will never come.\r\n if (pendingConfirms.size > 0) {\r\n for (const [id, resolve] of pendingConfirms) {\r\n resolve('no');\r\n pendingConfirms.delete(id);\r\n }\r\n }\r\n });\r\n\r\n ws.on('error', (err) => {\r\n // Without this handler an errored socket would crash the process.\r\n console.warn('[WebUI] Client socket error:', err.message);\r\n });\r\n };\r\n\r\n let eventsArmed = false;\r\n const armOnce = (label: string): void => {\r\n if (eventsArmed) return;\r\n eventsArmed = true;\r\n console.log(`[WebUI] Backend ready (${label})`);\r\n setupEvents();\r\n };\r\n\r\n wssPrimary.on('listening', () => armOnce(`${wsHost}:${wsPort}`));\r\n wssPrimary.on('connection', handleConnection);\r\n wssPrimary.on('error', (err) => {\r\n console.error(`[WebUI] Primary WS server error (${wsHost}):`, err);\r\n });\r\n\r\n if (wssSecondary) {\r\n wssSecondary.on('listening', () => armOnce(`::1:${wsPort}`));\r\n wssSecondary.on('connection', handleConnection);\r\n wssSecondary.on('error', (err: NodeJS.ErrnoException) => {\r\n // Best-effort secondary: if IPv6 loopback isn't available on this host\r\n // (e.g. disabled in OS), just log and continue. Primary v4 is enough.\r\n if (err.code === 'EAFNOSUPPORT' || err.code === 'EADDRNOTAVAIL') {\r\n console.warn('[WebUI] IPv6 loopback not available, v4-only:', err.code);\r\n } else {\r\n console.error('[WebUI] Secondary WS server error (::1):', err);\r\n }\r\n });\r\n }\r\n\r\n async function handleMessage(\r\n ws: WebSocket,\r\n client: ConnectedClient,\r\n msg: WSClientMessage,\r\n ): Promise<void> {\r\n switch (msg.type) {\r\n case 'user_message': {\r\n const content = (msg as { payload: { content: string } }).payload.content;\r\n\r\n // Guard against concurrent agent runs — a second user_message while\r\n // the agent is already processing would kick off two agent.run()\r\n // calls on the same shared context/agent, leading to corrupted\r\n // state (duplicate tool bubbles, mixed text_delta streams, token\r\n // counter undercount). Reject with an inline error; the frontend\r\n // should wait for run.result before sending the next message.\r\n if (runLock) {\r\n send(ws, {\r\n type: 'error',\r\n payload: {\r\n phase: 'user_message',\r\n message: 'Agent is already processing a request. Wait for the current run to finish.',\r\n },\r\n });\r\n break;\r\n }\r\n\r\n runLock = new AbortController();\r\n // Capture so the finally block only clears its own lock — a\r\n // second race could set a new runLock between await and finally.\r\n const thisRun = runLock;\r\n\r\n try {\r\n const result = await agent.run(content, { signal: thisRun.signal });\r\n send(ws, {\r\n type: 'run.result',\r\n payload: {\r\n status: result.status,\r\n iterations: result.iterations,\r\n finalText: result.finalText,\r\n error: result.error\r\n ? {\r\n code: result.error.code,\r\n message: result.error.message,\r\n recoverable: result.error.recoverable,\r\n }\r\n : undefined,\r\n },\r\n });\r\n } catch (err) {\r\n send(ws, {\r\n type: 'error',\r\n payload: {\r\n phase: 'agent.run',\r\n message: err instanceof Error ? err.message : String(err),\r\n },\r\n });\r\n } finally {\r\n // Only clear runLock if it's still ours — otherwise we'd wipe a\r\n // newer run's controller set after we returned.\r\n if (runLock === thisRun) {\r\n runLock = null;\r\n }\r\n }\r\n break;\r\n }\r\n\r\n case 'tool.confirm_result': {\r\n const { id, decision } = (msg as { payload: { id: string; decision: 'yes' | 'no' | 'always' | 'deny' } }).payload;\r\n const resolve = pendingConfirms.get(id);\r\n if (resolve) {\r\n pendingConfirms.delete(id);\r\n resolve(decision);\r\n }\r\n break;\r\n }\r\n\r\n case 'abort':\r\n runLock?.abort();\r\n broadcast({ type: 'error', payload: { phase: 'abort', message: 'User aborted' } });\r\n break;\r\n\r\n case 'ping':\r\n send(ws, { type: 'pong', payload: {} });\r\n break;\r\n\r\n case 'session.new': {\r\n // Truly fresh chat: new on-disk session AND reset every piece of\r\n // in-memory state that survived (messages history, todos, read-file\r\n // tracking, token totals). Otherwise the model still sees the prior\r\n // turns even though the UI looks empty — that's the \"ghost context\"\r\n // bug. After this, the next user message goes out as turn 1 with no\r\n // prior history.\r\n session = await sessionStore.create({\r\n id: '',\r\n title: '',\r\n model: config.model,\r\n provider: config.provider,\r\n });\r\n context.session = session;\r\n context.state.replaceMessages([]);\r\n context.state.replaceTodos([]);\r\n context.readFiles.clear();\r\n context.fileMtimes.clear();\r\n tokenCounter.reset();\r\n sessionStartedAt = Date.now();\r\n broadcast({ type: 'session.start', payload: await sessionStartPayload() });\r\n break;\r\n }\r\n\r\n case 'context.clear': {\r\n // Same in-memory wipe as session.new, but reuses the current session\r\n // file (so the JSONL still has the history for audit / replay). The\r\n // user wants a clean slate on the model side; the disk record stays.\r\n context.state.replaceMessages([]);\r\n context.state.replaceTodos([]);\r\n context.readFiles.clear();\r\n context.fileMtimes.clear();\r\n tokenCounter.reset();\r\n sendResult(ws, true, 'Context cleared');\r\n broadcast({\r\n type: 'session.start',\r\n payload: { ...(await sessionStartPayload()), reset: true },\r\n });\r\n break;\r\n }\r\n\r\n case 'context.debug': {\r\n // Per-section token estimate so users can see what's actually eating\r\n // the context window. Uses the simple 4-chars-per-token heuristic —\r\n // not exact, but close enough to spot which section is bloated.\r\n const estimate = (s: string): number => Math.ceil(s.length / 4);\r\n const stringifyContent = (c: unknown): string => {\r\n if (typeof c === 'string') return c;\r\n try {\r\n return JSON.stringify(c);\r\n } catch {\r\n return String(c);\r\n }\r\n };\r\n const sysTokens = context.systemPrompt.reduce((acc, b) => acc + estimate(b.text ?? ''), 0);\r\n // Tool schemas: each tool sends a JSON schema to the model on every\r\n // turn. With 20+ builtins these can be 10-20k by themselves.\r\n const tools = toolRegistry.list();\r\n const toolBreakdown = tools.map((t) => {\r\n const schema = (t as { inputSchema?: unknown }).inputSchema ?? {};\r\n const desc = (t as { description?: string }).description ?? '';\r\n return {\r\n name: t.name,\r\n tokens: estimate(t.name) + estimate(desc) + estimate(stringifyContent(schema)),\r\n };\r\n });\r\n const toolTokens = toolBreakdown.reduce((a, b) => a + b.tokens, 0);\r\n const messageBreakdown = context.messages.map((m, i) => {\r\n let tk = 0;\r\n if (typeof m.content === 'string') {\r\n tk = estimate(m.content);\r\n } else if (Array.isArray(m.content)) {\r\n for (const b of m.content) {\r\n if (b.type === 'text') tk += estimate(b.text ?? '');\r\n else if (b.type === 'tool_use') tk += estimate(stringifyContent(b.input));\r\n else if (b.type === 'tool_result') tk += estimate(stringifyContent(b.content));\r\n else tk += estimate(stringifyContent(b));\r\n }\r\n }\r\n return {\r\n index: i,\r\n role: m.role,\r\n tokens: tk,\r\n preview:\r\n typeof m.content === 'string'\r\n ? m.content.slice(0, 60)\r\n : Array.isArray(m.content)\r\n ? m.content\r\n .map((b) =>\r\n b.type === 'text'\r\n ? (b.text ?? '').slice(0, 40)\r\n : b.type === 'tool_use'\r\n ? `[tool_use: ${b.name}]`\r\n : b.type === 'tool_result'\r\n ? `[tool_result]`\r\n : `[${b.type}]`,\r\n )\r\n .join(' ')\r\n .slice(0, 60)\r\n : '',\r\n };\r\n });\r\n const msgTokens = messageBreakdown.reduce((a, b) => a + b.tokens, 0);\r\n const total = sysTokens + toolTokens + msgTokens;\r\n send(ws, {\r\n type: 'context.debug',\r\n payload: {\r\n total,\r\n mode: context.meta['contextWindowMode'] ?? DEFAULT_CONTEXT_WINDOW_MODE_ID,\r\n policy: context.meta['contextWindowPolicy'],\r\n systemPrompt: sysTokens,\r\n tools: { total: toolTokens, count: tools.length, breakdown: toolBreakdown },\r\n messages: {\r\n total: msgTokens,\r\n count: context.messages.length,\r\n breakdown: messageBreakdown,\r\n },\r\n },\r\n });\r\n break;\r\n }\r\n\r\n case 'context.compact': {\r\n const aggressive = !!(msg as { payload?: { aggressive?: boolean } }).payload?.aggressive;\r\n try {\r\n const report = await compactor.compact(context, { aggressive });\r\n send(ws, {\r\n type: 'context.compacted',\r\n payload: {\r\n before: report.before,\r\n after: report.after,\r\n saved: Math.max(0, report.before - report.after),\r\n reductions: report.reductions,\r\n repaired: report.repaired,\r\n },\r\n });\r\n sendResult(\r\n ws,\r\n true,\r\n `Compacted: ${report.before} → ${report.after} tokens (saved ~${Math.max(0, report.before - report.after)})`,\r\n );\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n break;\r\n }\r\n\r\n case 'context.repair': {\r\n const beforeMessages = context.messages.length;\r\n const repaired = repairToolUseAdjacency(context.messages);\r\n if (repaired.report.changed) {\r\n context.state.replaceMessages(repaired.messages);\r\n }\r\n const payload = {\r\n removedToolUses: repaired.report.removedToolUses,\r\n removedToolResults: repaired.report.removedToolResults,\r\n removedMessages: repaired.report.removedMessages,\r\n beforeMessages,\r\n afterMessages: context.messages.length,\r\n };\r\n broadcast({ type: 'context.repaired', payload });\r\n const removed =\r\n payload.removedToolUses.length +\r\n payload.removedToolResults.length +\r\n payload.removedMessages;\r\n sendResult(\r\n ws,\r\n true,\r\n removed > 0\r\n ? `Context repaired: removed ${removed} orphan protocol item(s)`\r\n : 'Context repair found no orphan protocol blocks',\r\n );\r\n break;\r\n }\r\n\r\n case 'context.modes.list': {\r\n const active = String(context.meta['contextWindowMode'] ?? DEFAULT_CONTEXT_WINDOW_MODE_ID);\r\n send(ws, {\r\n type: 'context.modes.list',\r\n payload: {\r\n activeId: active,\r\n modes: listContextWindowModes().map((m) => ({\r\n id: m.id,\r\n name: m.name,\r\n description: m.description,\r\n isActive: m.id === active,\r\n thresholds: m.thresholds,\r\n preserveK: m.preserveK,\r\n eliseThreshold: m.eliseThreshold,\r\n })),\r\n },\r\n });\r\n break;\r\n }\r\n\r\n case 'context.mode.switch': {\r\n const { id } = (msg as { payload: { id: string } }).payload;\r\n const policy = resolveContextWindowPolicy({}, id);\r\n if (policy.id !== id) {\r\n sendResult(ws, false, `Unknown context mode \"${id}\"`);\r\n break;\r\n }\r\n context.meta['contextWindowMode'] = policy.id;\r\n context.meta['contextWindowPolicy'] = policy;\r\n sendResult(ws, true, `Context mode switched to ${policy.id}`);\r\n broadcast({\r\n type: 'context.mode.changed',\r\n payload: { id: policy.id, name: policy.name, policy },\r\n });\r\n break;\r\n }\r\n\r\n case 'providers.list': {\r\n const providers = await modelsRegistry.listProviders();\r\n // \"Configured\" should mean *any* working credential, not just env vars.\r\n // Users register keys with `wstack auth`, which writes apiKey/apiKeys\r\n // into config.providers[<id>] — those are decrypted in memory here.\r\n const savedIds = new Set(Object.keys(config.providers ?? {}));\r\n send(ws, {\r\n type: 'provider.catalog',\r\n payload: {\r\n providers: providers.map((p) => ({\r\n id: p.id,\r\n name: p.name,\r\n family: p.family,\r\n apiBase: p.apiBase,\r\n envVars: p.envVars,\r\n modelCount: p.models.length,\r\n hasApiKey: savedIds.has(p.id) || p.envVars.some((v) => !!process.env[v]),\r\n })),\r\n },\r\n });\r\n break;\r\n }\r\n\r\n case 'provider.models': {\r\n const providerId = (msg as { payload: { providerId: string } }).payload.providerId;\r\n const provider = await modelsRegistry.getProvider(providerId);\r\n if (provider) {\r\n send(ws, {\r\n type: 'provider.models',\r\n payload: {\r\n provider: providerId,\r\n models: provider.models.map((m) => ({\r\n id: m.id,\r\n name: m.name,\r\n releaseDate: (m as { release_date?: string }).release_date,\r\n contextWindow: (m as { limit?: { context?: number } }).limit?.context,\r\n inputCost: (m as { cost?: { input?: number } }).cost?.input,\r\n outputCost: (m as { cost?: { output?: number } }).cost?.output,\r\n capabilities: [\r\n ...((m as { tool_call?: boolean }).tool_call ? ['tools'] : []),\r\n ...((m as { reasoning?: boolean }).reasoning ? ['reasoning'] : []),\r\n ],\r\n })),\r\n },\r\n });\r\n }\r\n break;\r\n }\r\n\r\n case 'model.switch': {\r\n const { provider: newProvider, model: newModel } = (\r\n msg as { payload: { provider: string; model: string } }\r\n ).payload;\r\n try {\r\n // Update config\r\n config = patchConfig(config, { provider: newProvider, model: newModel });\r\n configStore.update({ provider: newProvider, model: newModel });\r\n context.model = newModel;\r\n\r\n // Create new provider instance — fail loudly if the user picks a\r\n // provider with no creds rather than silently keeping the old one.\r\n const providerCfg = config.providers?.[newProvider] ?? { type: newProvider };\r\n const newProv = providerRegistry.has(newProvider)\r\n ? providerRegistry.create({ ...providerCfg, type: newProvider })\r\n : makeProviderFromConfig(newProvider, providerCfg);\r\n context.provider = newProv;\r\n\r\n // Update AutoCompactionMiddleware with the new model's maxContext so\r\n // backend threshold triggers (warn/soft/hard) use the correct denominator.\r\n // sessionStartPayload is called below (after this block) and uses\r\n // the new provider for its modelsRegistry lookup.\r\n updateAutoCompactionMaxContext?.(newProv);\r\n\r\n // Persist to global config file\r\n try {\r\n configWriteLock = configWriteLock.then(async () => {\r\n const raw = await fs.readFile(globalConfigPath, 'utf8');\r\n const parsed = JSON.parse(raw);\r\n parsed.provider = newProvider;\r\n parsed.model = newModel;\r\n await atomicWrite(globalConfigPath, JSON.stringify(parsed, null, 2));\r\n });\r\n await configWriteLock;\r\n } catch (err) {\r\n console.warn('[WebUI] Failed to save config:', err);\r\n }\r\n\r\n // Toast for the SettingsPanel\r\n send(ws, {\r\n type: 'key.operation_result',\r\n payload: { success: true, message: `Switched to ${newProvider} / ${newModel}` },\r\n });\r\n } catch (err) {\r\n send(ws, {\r\n type: 'key.operation_result',\r\n payload: {\r\n success: false,\r\n message: `Switch failed: ${err instanceof Error ? err.message : String(err)}`,\r\n },\r\n });\r\n break;\r\n }\r\n\r\n broadcast({ type: 'session.start', payload: await sessionStartPayload() });\r\n break;\r\n }\r\n\r\n case 'key.add':\r\n case 'key.update': {\r\n const { providerId, label, apiKey } = (\r\n msg as { payload: { providerId: string; label: string; apiKey: string } }\r\n ).payload;\r\n await handleKeyUpsert(ws, providerId, label, apiKey);\r\n break;\r\n }\r\n\r\n case 'key.delete': {\r\n const { providerId, label } = (msg as { payload: { providerId: string; label: string } })\r\n .payload;\r\n await handleKeyDelete(ws, providerId, label);\r\n break;\r\n }\r\n\r\n case 'key.set_active': {\r\n const { providerId, label } = (msg as { payload: { providerId: string; label: string } })\r\n .payload;\r\n await handleKeySetActive(ws, providerId, label);\r\n break;\r\n }\r\n\r\n case 'provider.add': {\r\n const p = (\r\n msg as { payload: { id: string; family: string; baseUrl?: string; apiKey?: string } }\r\n ).payload;\r\n await handleProviderAdd(ws, p);\r\n break;\r\n }\r\n\r\n case 'provider.remove': {\r\n const { providerId } = (msg as { payload: { providerId: string } }).payload;\r\n await handleProviderRemove(ws, providerId);\r\n break;\r\n }\r\n\r\n case 'sessions.list': {\r\n // Per-project history. Sessions live under .wrongstack/sessions/ for\r\n // this project; we never enumerate cross-project state.\r\n const limit = (msg as { payload?: { limit?: number } }).payload?.limit ?? 50;\r\n try {\r\n const list = await sessionStore.list(limit);\r\n send(ws, {\r\n type: 'sessions.list',\r\n payload: {\r\n sessions: list.map((s) => ({\r\n id: s.id,\r\n title: s.title,\r\n startedAt: s.startedAt,\r\n model: s.model,\r\n provider: s.provider,\r\n tokenTotal: s.tokenTotal,\r\n isCurrent: s.id === session.id,\r\n })),\r\n },\r\n });\r\n } catch (err) {\r\n send(ws, {\r\n type: 'sessions.list',\r\n payload: { sessions: [], error: err instanceof Error ? err.message : String(err) },\r\n });\r\n }\r\n break;\r\n }\r\n\r\n case 'session.delete': {\r\n const { id } = (msg as { payload: { id: string } }).payload;\r\n try {\r\n if (id === session.id) {\r\n sendResult(ws, false, 'Cannot delete the active session');\r\n break;\r\n }\r\n await sessionStore.delete(id);\r\n sendResult(ws, true, `Session ${id} deleted`);\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n break;\r\n }\r\n\r\n case 'session.resume': {\r\n // Load a past session's messages + usage, swap the active session\r\n // writer, hydrate the live Context, then broadcast a session.start\r\n // payload tagged with the replayed transcript so the UI can render\r\n // the chat history.\r\n const { id } = (msg as { payload: { id: string } }).payload;\r\n try {\r\n if (id === session.id) {\r\n sendResult(ws, false, 'Session is already active');\r\n break;\r\n }\r\n const resumed = await sessionStore.resume(id);\r\n // Close prior writer best-effort; swallow errors so we don't block\r\n // the resume on a crashed file handle.\r\n try {\r\n await session.close();\r\n } catch {\r\n /* noop */\r\n }\r\n session = resumed.writer;\r\n context.session = session;\r\n context.state.replaceMessages(resumed.data.messages);\r\n context.readFiles.clear();\r\n context.fileMtimes.clear();\r\n tokenCounter.reset();\r\n // Replay usage so the topbar shows accurate totals after resume.\r\n tokenCounter.account(resumed.data.usage, config.model);\r\n sessionStartedAt = Date.now();\r\n broadcast({\r\n type: 'session.start',\r\n payload: {\r\n ...(await sessionStartPayload()),\r\n reset: true,\r\n replayMessages: resumed.data.messages,\r\n replayUsage: resumed.data.usage,\r\n },\r\n });\r\n sendResult(ws, true, `Resumed session ${id}`);\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n break;\r\n }\r\n\r\n case 'session.save': {\r\n // SessionWriter already flushes after every event; this is mostly a\r\n // no-op marker so the user gets confirmation. Useful for habit\r\n // parity with the CLI /save command.\r\n sendResult(ws, true, `Session ${session.id} is auto-saved`);\r\n break;\r\n }\r\n\r\n case 'tools.list': {\r\n // Full tool registry dump for the /tools inspect view. We surface\r\n // name, description, and schema-derived param names so the user\r\n // can tell at a glance which tools the model can call right now.\r\n const list = toolRegistry.list().map((t) => {\r\n const schema =\r\n (t as { inputSchema?: { properties?: Record<string, unknown> } }).inputSchema ?? {};\r\n const params = schema.properties ? Object.keys(schema.properties) : [];\r\n return {\r\n name: t.name,\r\n description: (t as { description?: string }).description ?? '',\r\n params,\r\n };\r\n });\r\n send(ws, { type: 'tools.list', payload: { tools: list } });\r\n break;\r\n }\r\n\r\n case 'memory.list': {\r\n // All three scopes (project-agents, project-memory, user-memory)\r\n // rolled up as readAll already does. Returned as raw markdown so\r\n // the UI can render with the same style as everything else.\r\n try {\r\n const text = await memoryStore.readAll();\r\n send(ws, { type: 'memory.list', payload: { text } });\r\n } catch (err) {\r\n send(ws, {\r\n type: 'memory.list',\r\n payload: { text: '', error: err instanceof Error ? err.message : String(err) },\r\n });\r\n }\r\n break;\r\n }\r\n\r\n case 'memory.remember': {\r\n const { text, scope } = (\r\n msg as {\r\n payload: { text: string; scope?: 'project-agents' | 'project-memory' | 'user-memory' };\r\n }\r\n ).payload;\r\n try {\r\n await memoryStore.remember(text, scope ?? 'project-memory');\r\n sendResult(ws, true, 'Saved to memory');\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n break;\r\n }\r\n\r\n case 'memory.forget': {\r\n const { text, scope } = (\r\n msg as {\r\n payload: { text: string; scope?: 'project-agents' | 'project-memory' | 'user-memory' };\r\n }\r\n ).payload;\r\n try {\r\n const removed = await memoryStore.forget(text, scope ?? 'project-memory');\r\n sendResult(\r\n ws,\r\n removed > 0,\r\n removed > 0\r\n ? `Removed ${removed} entr${removed === 1 ? 'y' : 'ies'}`\r\n : 'No matching entries',\r\n );\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n break;\r\n }\r\n\r\n case 'skills.list': {\r\n if (!skillLoader) {\r\n send(ws, { type: 'skills.list', payload: { skills: [], enabled: false } });\r\n break;\r\n }\r\n try {\r\n const manifests = await skillLoader.list();\r\n const entries = await skillLoader.listEntries();\r\n const byName = new Map(entries.map((e) => [e.name, e]));\r\n send(ws, {\r\n type: 'skills.list',\r\n payload: {\r\n enabled: true,\r\n skills: manifests.map((m) => ({\r\n name: m.name,\r\n description: m.description,\r\n version: m.version ?? '',\r\n source: m.source,\r\n path: m.path,\r\n trigger: byName.get(m.name)?.trigger ?? '',\r\n scope: byName.get(m.name)?.scope ?? [],\r\n })),\r\n },\r\n });\r\n } catch (err) {\r\n send(ws, {\r\n type: 'skills.list',\r\n payload: {\r\n skills: [],\r\n enabled: true,\r\n error: err instanceof Error ? err.message : String(err),\r\n },\r\n });\r\n }\r\n break;\r\n }\r\n\r\n case 'diag.get': {\r\n // Snapshot of the moving parts so the user can debug \"why is X\r\n // not working?\" without diving into the server logs.\r\n const usage = tokenCounter.total();\r\n send(ws, {\r\n type: 'diag.get',\r\n payload: {\r\n provider: config.provider,\r\n model: config.model,\r\n cwd: projectRoot,\r\n sessionId: session.id,\r\n tools: {\r\n count: toolRegistry.list().length,\r\n names: toolRegistry.list().map((t) => t.name),\r\n },\r\n features: {\r\n memory: !!config.features?.memory,\r\n skills: !!config.features?.skills,\r\n modelsRegistry: !!config.features?.modelsRegistry,\r\n },\r\n mode: modeId ?? 'default',\r\n usage,\r\n messages: context.messages.length,\r\n todos: context.todos.length,\r\n },\r\n });\r\n break;\r\n }\r\n\r\n case 'todos.get': {\r\n // On-demand snapshot — used when a UI surface first mounts and\r\n // needs to render the live todo list without waiting for the next\r\n // tool.executed to broadcast.\r\n send(ws, {\r\n type: 'todos.updated',\r\n payload: { todos: [...context.todos] },\r\n });\r\n break;\r\n }\r\n\r\n case 'todos.clear': {\r\n // Manual override — the agent normally curates this list via\r\n // TodoWrite, but the user might want a clean slate without losing\r\n // the rest of the context. Use state.replaceTodos so observers\r\n // (checkpoint writer) stay in sync.\r\n context.state.replaceTodos([]);\r\n sendResult(ws, true, 'Todos cleared');\r\n broadcast({ type: 'todos.updated', payload: { todos: [] } });\r\n break;\r\n }\r\n\r\n case 'plan.get': {\r\n // On-demand plan snapshot — used when a UI surface first mounts\r\n // and needs to render the live plan without waiting for the next\r\n // tool.executed to broadcast.\r\n const planPath = (context.meta as Record<string, unknown>)['plan.path'];\r\n if (typeof planPath === 'string' && planPath) {\r\n try {\r\n const { loadPlan } = await import('@wrongstack/core');\r\n const plan = await loadPlan(planPath);\r\n send(ws, {\r\n type: 'plan.updated',\r\n payload: { plan: plan ?? { version: 1, sessionId: session.id, updatedAt: new Date().toISOString(), items: [] } },\r\n });\r\n } catch {\r\n send(ws, {\r\n type: 'plan.updated',\r\n payload: { plan: { version: 1, sessionId: session.id, updatedAt: new Date().toISOString(), items: [] } },\r\n });\r\n }\r\n } else {\r\n send(ws, {\r\n type: 'plan.updated',\r\n payload: { plan: null, error: 'Plan storage is not configured for this session.' },\r\n });\r\n }\r\n break;\r\n }\r\n\r\n case 'plan.template_use': {\r\n const { template } = (msg as { payload: { template: string } }).payload;\r\n const planPath = (context.meta as Record<string, unknown>)['plan.path'];\r\n if (typeof planPath !== 'string' || !planPath) {\r\n sendResult(ws, false, 'Plan storage is not configured for this session.');\r\n break;\r\n }\r\n try {\r\n const { getPlanTemplate, loadPlan, savePlan, emptyPlan, addPlanItem, formatPlan } = await import('@wrongstack/core');\r\n const tpl = getPlanTemplate(template);\r\n if (!tpl) {\r\n sendResult(ws, false, `Unknown template \"${template}\".`);\r\n break;\r\n }\r\n let plan = (await loadPlan(planPath)) ?? emptyPlan(session.id);\r\n for (const item of tpl.items) {\r\n ({ plan } = addPlanItem(plan, item.title, item.details));\r\n }\r\n await savePlan(planPath, plan);\r\n sendResult(ws, true, `Applied template \"${tpl.name}\" — ${tpl.items.length} items added.`);\r\n broadcast({\r\n type: 'plan.updated',\r\n payload: { plan },\r\n });\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n break;\r\n }\r\n\r\n case 'files.list': {\r\n // Lightweight project file picker for the chat `@` mention popup.\r\n // Walks projectRoot, skipping the heavyweight build/vcs/node_modules\r\n // dirs that would blow up the response on a real project. Applies\r\n // a fuzzy substring match against the (lowercased) query and caps\r\n // the result so the popup never has to paginate.\r\n const payload = (msg as { payload?: { query?: string; limit?: number } }).payload ?? {};\r\n const query = (payload.query ?? '').toLowerCase();\r\n const limit = payload.limit ?? 50;\r\n const SKIP_DIRS = new Set([\r\n '.git',\r\n 'node_modules',\r\n 'dist',\r\n 'build',\r\n '.next',\r\n '.turbo',\r\n '.cache',\r\n 'target',\r\n 'coverage',\r\n '.nyc_output',\r\n 'out',\r\n '.pnpm-store',\r\n '.parcel-cache',\r\n ]);\r\n const results: string[] = [];\r\n async function walk(dir: string, rel: string, depth: number): Promise<void> {\r\n if (depth > 8 || results.length >= 600) return;\r\n let entries: import('node:fs').Dirent[] = [];\r\n try {\r\n entries = await fs.readdir(dir, { withFileTypes: true });\r\n } catch {\r\n return;\r\n }\r\n for (const e of entries) {\r\n if (results.length >= 600) return;\r\n if (e.name.startsWith('.') && e.name !== '.wrongstack' && e.name !== '.env.example') {\r\n // hide dotfiles by default; pick a couple common ones the user\r\n // might want anyway\r\n if (e.name !== '.gitignore' && e.name !== '.eslintrc' && e.name !== '.prettierrc')\r\n continue;\r\n }\r\n const childRel = rel ? `${rel}/${e.name}` : e.name;\r\n if (e.isDirectory()) {\r\n if (SKIP_DIRS.has(e.name)) continue;\r\n await walk(path.join(dir, e.name), childRel, depth + 1);\r\n } else if (e.isFile()) {\r\n results.push(childRel);\r\n }\r\n }\r\n }\r\n await walk(projectRoot, '', 0);\r\n // Score: exact basename match > prefix > substring. Cheap heuristic\r\n // that's good enough for a picker.\r\n const scored: Array<{ path: string; score: number }> = [];\r\n for (const p of results) {\r\n if (!query) {\r\n scored.push({ path: p, score: 0 });\r\n continue;\r\n }\r\n const lower = p.toLowerCase();\r\n const base = lower.split('/').pop() ?? lower;\r\n let score = 0;\r\n if (base === query) score = 100;\r\n else if (base.startsWith(query)) score = 60;\r\n else if (lower.includes(query)) score = 20;\r\n else continue;\r\n // Penalise depth so root files come first.\r\n score -= p.split('/').length;\r\n scored.push({ path: p, score });\r\n }\r\n scored.sort((a, b) => b.score - a.score || a.path.localeCompare(b.path));\r\n send(ws, {\r\n type: 'files.list',\r\n payload: { files: scored.slice(0, limit).map((s) => s.path) },\r\n });\r\n break;\r\n }\r\n\r\n case 'modes.list': {\r\n try {\r\n const modes = await modeStore.listModes();\r\n const active = await modeStore.getActiveMode();\r\n send(ws, {\r\n type: 'modes.list',\r\n payload: {\r\n modes: modes.map((m) => ({\r\n id: m.id,\r\n name: m.name,\r\n description: m.description,\r\n isActive: m.id === (active?.id ?? 'default'),\r\n })),\r\n activeId: active?.id ?? 'default',\r\n },\r\n });\r\n } catch (err) {\r\n send(ws, {\r\n type: 'modes.list',\r\n payload: {\r\n modes: [],\r\n activeId: 'default',\r\n error: err instanceof Error ? err.message : String(err),\r\n },\r\n });\r\n }\r\n break;\r\n }\r\n\r\n case 'mode.switch': {\r\n const { id } = (msg as { payload: { id: string } }).payload;\r\n try {\r\n // 'default' is the implicit no-mode state — persisting null\r\n // clears the override. Anything else has to exist in the store.\r\n if (id === 'default') {\r\n await modeStore.setActiveMode(null);\r\n } else {\r\n const found = await modeStore.getMode(id);\r\n if (!found) throw new Error(`Unknown mode \"${id}\"`);\r\n await modeStore.setActiveMode(id);\r\n }\r\n modeId = id;\r\n // Rebuild the system prompt so the next turn picks up the new\r\n // mode's instructions. The builder caches the environment block\r\n // per projectRoot (including the modeId), so we clear the cache\r\n // and rebuild. The `buildMode()` method reads this.opts.modePrompt\r\n // which is set on the builder constructor — we construct a fresh\r\n // builder with the updated mode. This is cheap (no fs/net IO in\r\n // the constructor; the real work happens in build()).\r\n const modePrompt = id === 'default' ? '' : ((await modeStore.getMode(id))?.prompt ?? '');\r\n const freshBuilder = new DefaultSystemPromptBuilder({\r\n memoryStore,\r\n skillLoader,\r\n modeStore,\r\n modeId: id,\r\n modePrompt,\r\n modelCapabilities,\r\n });\r\n context.systemPrompt = await freshBuilder.build({\r\n cwd: projectRoot,\r\n projectRoot,\r\n tools: toolRegistry.list(),\r\n provider: config.provider,\r\n model: config.model,\r\n });\r\n sendResult(ws, true, `Switched to mode \"${id}\"`);\r\n broadcast({\r\n type: 'session.start',\r\n payload: { ...(await sessionStartPayload()) },\r\n });\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n break;\r\n }\r\n\r\n case 'stats.get': {\r\n // Mirror of the CLI's /stats: detailed session report.\r\n const usage = tokenCounter.total();\r\n const cacheStats = tokenCounter.cacheStats();\r\n const m = await modelsRegistry.getModel(config.provider, config.model).catch(() => null);\r\n const inputCost = (m as { cost?: { input?: number } } | null)?.cost?.input ?? 0;\r\n const outputCost = (m as { cost?: { output?: number } } | null)?.cost?.output ?? 0;\r\n const cacheReadCost =\r\n (m as { cost?: { cache_read?: number } } | null)?.cost?.cache_read ?? 0;\r\n const cost =\r\n (usage.input * inputCost +\r\n usage.output * outputCost +\r\n (usage.cacheRead ?? 0) * cacheReadCost) /\r\n 1_000_000;\r\n send(ws, {\r\n type: 'stats.get',\r\n payload: {\r\n sessionId: session.id,\r\n provider: config.provider,\r\n model: config.model,\r\n usage,\r\n cache: cacheStats,\r\n cost,\r\n messages: context.messages.length,\r\n readFiles: context.readFiles.size,\r\n tools: toolRegistry.list().length,\r\n elapsedMs: Date.now() - sessionStartedAt,\r\n },\r\n });\r\n break;\r\n }\r\n\r\n default:\r\n if (msg.type.startsWith('autophase.')) {\r\n // Delegate all AutoPhase lifecycle messages to the handler\r\n await autoPhaseHandler.handleMessage(msg as { type: string; payload?: Record<string, unknown> });\r\n } else {\r\n send(ws, { type: 'error', payload: { phase: 'handleMessage', message: `Unknown message type: ${msg.type}` } });\r\n }\r\n }\r\n }\r\n\r\n // ---- Provider/Key management helpers (mirror packages/cli/src/webui-server.ts) ----\r\n\r\n async function loadSavedProviders(): Promise<Record<string, ProviderConfig>> {\r\n try {\r\n const raw = await fs.readFile(globalConfigPath, 'utf8');\r\n const parsed = JSON.parse(raw) as { providers?: Record<string, ProviderConfig> };\r\n if (!parsed.providers) return {};\r\n return decryptConfigSecrets(parsed.providers, vault);\r\n } catch {\r\n return {};\r\n }\r\n }\r\n\r\n async function saveProviders(providers: Record<string, ProviderConfig>): Promise<void> {\r\n configWriteLock = configWriteLock.then(async () => {\r\n let parsed: Record<string, unknown>;\r\n try {\r\n const raw = await fs.readFile(globalConfigPath, 'utf8');\r\n parsed = JSON.parse(raw) as Record<string, unknown>;\r\n } catch {\r\n parsed = {};\r\n }\r\n parsed['providers'] = providers;\r\n const encrypted = encryptConfigSecrets(parsed, vault);\r\n await atomicWrite(globalConfigPath, JSON.stringify(encrypted, null, 2), { mode: 0o600 });\r\n });\r\n await configWriteLock;\r\n }\r\n\r\n function normalizeKeys(cfg: ProviderConfig): ProviderApiKey[] {\r\n if (Array.isArray(cfg.apiKeys) && cfg.apiKeys.length > 0) {\r\n return cfg.apiKeys.map((k) => ({ ...k }));\r\n }\r\n if (typeof cfg.apiKey === 'string' && cfg.apiKey.length > 0) {\r\n return [{ label: 'default', apiKey: cfg.apiKey, createdAt: '' }];\r\n }\r\n return [];\r\n }\r\n\r\n function writeKeysBack(cfg: ProviderConfig, keys: ProviderApiKey[]): void {\r\n if (keys.length === 0) {\r\n delete cfg.apiKeys;\r\n delete cfg.apiKey;\r\n delete cfg.activeKey;\r\n return;\r\n }\r\n cfg.apiKeys = keys;\r\n const active = keys.find((k) => k.label === cfg.activeKey) ?? keys[0]!;\r\n cfg.apiKey = active.apiKey;\r\n if (!cfg.activeKey || !keys.some((k) => k.label === cfg.activeKey)) {\r\n cfg.activeKey = active.label;\r\n }\r\n }\r\n\r\n function maskedKey(key: string | undefined): string {\r\n if (!key) return '—';\r\n if (key.length <= 8) return '•'.repeat(key.length);\r\n return `${key.slice(0, 4)}…${key.slice(-4)}`;\r\n }\r\n\r\n function sendResult(ws: WebSocket, success: boolean, message: string): void {\r\n send(ws, { type: 'key.operation_result', payload: { success, message } });\r\n }\r\n\r\n async function handleKeyUpsert(\r\n ws: WebSocket,\r\n providerId: string,\r\n label: string,\r\n apiKey: string,\r\n ): Promise<void> {\r\n try {\r\n const providers = await loadSavedProviders();\r\n const existing: ProviderConfig = providers[providerId] ?? { type: providerId };\r\n const keys = normalizeKeys(existing);\r\n const idx = keys.findIndex((k) => k.label === label);\r\n const nowIso = new Date().toISOString();\r\n if (idx >= 0) {\r\n keys[idx] = { ...keys[idx]!, apiKey, createdAt: nowIso };\r\n } else {\r\n keys.push({ label, apiKey, createdAt: nowIso });\r\n }\r\n writeKeysBack(existing, keys);\r\n if (!existing.activeKey) existing.activeKey = label;\r\n providers[providerId] = existing;\r\n await saveProviders(providers);\r\n sendResult(ws, true, `Key \"${label}\" saved for ${providerId}`);\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n }\r\n\r\n async function handleKeyDelete(ws: WebSocket, providerId: string, label: string): Promise<void> {\r\n try {\r\n const providers = await loadSavedProviders();\r\n const existing = providers[providerId];\r\n if (!existing) {\r\n sendResult(ws, false, `Provider \"${providerId}\" not found`);\r\n return;\r\n }\r\n const keys = normalizeKeys(existing).filter((k) => k.label !== label);\r\n if (keys.length === 0) {\r\n delete providers[providerId];\r\n } else {\r\n writeKeysBack(existing, keys);\r\n if (existing.activeKey === label) existing.activeKey = keys[0]!.label;\r\n providers[providerId] = existing;\r\n }\r\n await saveProviders(providers);\r\n sendResult(ws, true, `Key \"${label}\" deleted from ${providerId}`);\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n }\r\n\r\n async function handleKeySetActive(\r\n ws: WebSocket,\r\n providerId: string,\r\n label: string,\r\n ): Promise<void> {\r\n try {\r\n const providers = await loadSavedProviders();\r\n const existing = providers[providerId];\r\n if (!existing) {\r\n sendResult(ws, false, `Provider \"${providerId}\" not found`);\r\n return;\r\n }\r\n existing.activeKey = label;\r\n writeKeysBack(existing, normalizeKeys(existing));\r\n providers[providerId] = existing;\r\n await saveProviders(providers);\r\n sendResult(ws, true, `Active key for ${providerId} set to \"${label}\"`);\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n }\r\n\r\n async function handleProviderAdd(\r\n ws: WebSocket,\r\n payload: { id: string; family: string; baseUrl?: string; apiKey?: string },\r\n ): Promise<void> {\r\n try {\r\n const providers = await loadSavedProviders();\r\n if (providers[payload.id]) {\r\n sendResult(ws, false, `Provider \"${payload.id}\" already exists. Use key.add to add a key.`);\r\n return;\r\n }\r\n const newProv: ProviderConfig = {\r\n type: payload.id,\r\n family: payload.family as ProviderConfig['family'],\r\n baseUrl: payload.baseUrl,\r\n };\r\n if (payload.apiKey) {\r\n newProv.apiKeys = [\r\n { label: 'default', apiKey: payload.apiKey, createdAt: new Date().toISOString() },\r\n ];\r\n newProv.activeKey = 'default';\r\n }\r\n providers[payload.id] = newProv;\r\n await saveProviders(providers);\r\n sendResult(ws, true, `Provider \"${payload.id}\" added`);\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n }\r\n\r\n async function handleProviderRemove(ws: WebSocket, providerId: string): Promise<void> {\r\n try {\r\n const providers = await loadSavedProviders();\r\n if (!providers[providerId]) {\r\n sendResult(ws, false, `Provider \"${providerId}\" not found`);\r\n return;\r\n }\r\n delete providers[providerId];\r\n await saveProviders(providers);\r\n sendResult(ws, true, `Provider \"${providerId}\" removed`);\r\n } catch (err) {\r\n sendResult(ws, false, err instanceof Error ? err.message : String(err));\r\n }\r\n }\r\n\r\n // HTTP server for the React frontend (port 3456)\r\n const httpPort = Number.parseInt(process.env['PORT'] ?? '3456', 10);\r\n const DIST_DIR = path.resolve(import.meta.dirname, '../../dist');\r\n\r\n const mimeTypes: Record<string, string> = {\r\n '.html': 'text/html',\r\n '.js': 'application/javascript',\r\n '.css': 'text/css',\r\n '.json': 'application/json',\r\n '.svg': 'image/svg+xml',\r\n '.png': 'image/png',\r\n '.ico': 'image/x-icon',\r\n };\r\n\r\n const httpServer = http.createServer(async (req, res) => {\r\n try {\r\n const url = new URL(req.url ?? '/', `http://127.0.0.1:${httpPort}`);\r\n let filePath: string;\r\n\r\n if (url.pathname === '/' || url.pathname === '') {\r\n filePath = path.join(DIST_DIR, 'index.html');\r\n } else if (url.pathname.startsWith('/assets/')) {\r\n filePath = path.join(DIST_DIR, url.pathname);\r\n } else if (url.pathname.startsWith('/')) {\r\n filePath = path.join(DIST_DIR, url.pathname);\r\n } else {\r\n filePath = path.join(DIST_DIR, 'index.html');\r\n }\r\n\r\n // Path traversal guard: the resolved path must stay inside DIST_DIR.\r\n // new URL() decodes percent-encoding (%2e%2e → ..), so path.join alone\r\n // does not prevent ../../../etc/passwd escapes.\r\n const resolvedPath = path.resolve(filePath);\r\n const resolvedRoot = path.resolve(DIST_DIR);\r\n if (!resolvedPath.startsWith(resolvedRoot + path.sep) && resolvedPath !== resolvedRoot) {\r\n res.writeHead(403, { 'Content-Type': 'text/plain' });\r\n res.end('Forbidden');\r\n return;\r\n }\r\n\r\n const ext = path.extname(resolvedPath);\r\n const contentType = mimeTypes[ext] ?? 'application/octet-stream';\r\n res.setHeader('Content-Type', contentType);\r\n res.setHeader('X-Content-Type-Options', 'nosniff');\r\n res.setHeader('X-Frame-Options', 'DENY');\r\n res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');\r\n\r\n if (ext === '.html') {\r\n res.setHeader('Cache-Control', 'no-cache');\r\n res.setHeader('Content-Security-Policy', HTML_CSP);\r\n }\r\n\r\n const fileContent = await fs.readFile(resolvedPath);\r\n res.writeHead(200);\r\n res.end(fileContent);\r\n } catch (err) {\r\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\r\n // Try index.html for SPA routing\r\n try {\r\n const fileContent = await fs.readFile(path.join(DIST_DIR, 'index.html'));\r\n res.writeHead(200, {\r\n 'Content-Type': 'text/html',\r\n 'X-Content-Type-Options': 'nosniff',\r\n 'X-Frame-Options': 'DENY',\r\n 'Referrer-Policy': 'strict-origin-when-cross-origin',\r\n // SPA fallback previously shipped no CSP — apply the same policy as\r\n // the direct .html branch so deep-linked routes aren't unprotected.\r\n 'Content-Security-Policy': HTML_CSP,\r\n });\r\n res.end(fileContent);\r\n } catch {\r\n res.writeHead(404);\r\n res.end('Not found');\r\n }\r\n } else {\r\n res.writeHead(500);\r\n res.end('Server error');\r\n }\r\n }\r\n });\r\n\r\n httpServer.listen(httpPort, wsHost, () => {\r\n console.log(`[WebUI] HTTP server running on http://${wsHost}:${httpPort}`);\r\n });\r\n\r\n // Graceful shutdown\r\n const shutdown = async () => {\r\n console.log('[WebUI] Shutting down...');\r\n try {\r\n await session.append({\r\n type: 'session_end',\r\n ts: new Date().toISOString(),\r\n usage: tokenCounter.total(),\r\n });\r\n await session.close();\r\n } catch (e) {\r\n console.warn('[WebUI] Error closing session:', e);\r\n }\r\n for (const [ws] of clients) ws.close();\r\n httpServer.close();\r\n wssPrimary.close();\r\n wssSecondary?.close();\r\n process.exit(0);\r\n };\r\n\r\n process.on('SIGINT', shutdown);\r\n process.on('SIGTERM', shutdown);\r\n}\r\n","import {\r\n Container,\r\n DefaultConfigStore,\r\n DefaultErrorHandler,\r\n DefaultMemoryStore,\r\n DefaultModeStore,\r\n DefaultPermissionPolicy,\r\n DefaultRetryPolicy,\r\n DefaultSecretScrubber,\r\n DefaultSessionStore,\r\n DefaultSkillLoader,\r\n DefaultSystemPromptBuilder,\r\n DefaultTokenCounter,\r\n HybridCompactor,\r\n TOKENS,\r\n type Config,\r\n type Logger,\r\n type ModelsRegistry,\r\n type Tool,\r\n type WstackPaths,\r\n} from '@wrongstack/core';\r\nimport type { DefaultSystemPromptBuilderOptions } from '@wrongstack/core';\r\n\r\nexport interface CreateContainerOptions {\r\n config: Config;\r\n wpaths: WstackPaths;\r\n logger: Logger;\r\n modelsRegistry: ModelsRegistry;\r\n permission?: {\r\n yolo?: boolean;\r\n forceAllYolo?: boolean;\r\n promptDelegate?: (\r\n tool: Tool,\r\n input: unknown,\r\n suggestedPattern: string,\r\n ) => Promise<'yes' | 'no' | 'always' | 'deny'>;\r\n };\r\n compactor?: { preserveK?: number; eliseThreshold?: number };\r\n systemPrompt?: Partial<DefaultSystemPromptBuilderOptions>;\r\n /** Bundled skills directory path (resolved at boot time). */\r\n bundledSkillsDir?: string;\r\n}\r\n\r\n/**\r\n * Create a Container pre-bound with all default service implementations.\r\n * Both CLI and WebUI use this factory so container wiring stays in one place.\r\n */\r\nexport function createDefaultContainer(opts: CreateContainerOptions): Container {\r\n const { config, wpaths, logger, modelsRegistry } = opts;\r\n const container = new Container();\r\n\r\n const configStore = new DefaultConfigStore(config);\r\n container.bind(TOKENS.ConfigStore, () => configStore);\r\n container.bind(TOKENS.Logger, () => logger);\r\n container.bind(TOKENS.SecretScrubber, () => new DefaultSecretScrubber());\r\n container.bind(TOKENS.RetryPolicy, () => new DefaultRetryPolicy());\r\n container.bind(TOKENS.ErrorHandler, () => new DefaultErrorHandler());\r\n container.bind(TOKENS.ModelsRegistry, () => modelsRegistry);\r\n container.bind(TOKENS.TokenCounter, () => new DefaultTokenCounter({ registry: modelsRegistry, providerId: config.provider }));\r\n\r\n const modeStore = new DefaultModeStore({ directory: wpaths.configDir });\r\n container.bind(TOKENS.ModeStore, () => modeStore);\r\n container.bind(TOKENS.SessionStore, () => new DefaultSessionStore({ dir: wpaths.projectSessions }));\r\n\r\n const memoryStore = new DefaultMemoryStore({ paths: wpaths });\r\n container.bind(TOKENS.MemoryStore, () => memoryStore);\r\n\r\n const skillLoader = new DefaultSkillLoader({ paths: wpaths, bundledDir: opts.bundledSkillsDir });\r\n container.bind(TOKENS.SkillLoader, () => skillLoader);\r\n\r\n if (opts.systemPrompt) {\r\n container.bind(TOKENS.SystemPromptBuilder, () => new DefaultSystemPromptBuilder(opts.systemPrompt as DefaultSystemPromptBuilderOptions));\r\n }\r\n\r\n container.bind(TOKENS.PermissionPolicy, () =>\r\n new DefaultPermissionPolicy({\r\n trustFile: wpaths.projectTrust,\r\n yolo: opts.permission?.yolo ?? false,\r\n forceAllYolo: opts.permission?.forceAllYolo ?? false,\r\n promptDelegate: opts.permission?.promptDelegate,\r\n }),\r\n );\r\n\r\n container.bind(TOKENS.Compactor, () =>\r\n new HybridCompactor({\r\n preserveK: opts.compactor?.preserveK ?? 20,\r\n eliseThreshold: opts.compactor?.eliseThreshold ?? 0.7,\r\n }),\r\n );\r\n\r\n return container;\r\n}\r\n","import * as fs from 'node:fs/promises';\nimport * as os from 'node:os';\nimport {\n DefaultConfigLoader,\n DefaultLogger,\n DefaultPathResolver,\n DefaultSecretVault,\n type Config,\n type WstackPaths,\n migratePlaintextSecrets,\n resolveWstackPaths,\n} from '@wrongstack/core';\n\nexport interface BootResult {\n config: Config;\n vault: DefaultSecretVault;\n globalConfigPath: string;\n projectRoot: string;\n wpaths: WstackPaths;\n logger: InstanceType<typeof DefaultLogger>;\n}\n\n/**\n * Boot config the same way the CLI does (mirrors packages/cli/src/boot-config.ts):\n * - resolve wstack paths\n * - create the real DefaultSecretVault (AES-GCM, not XOR)\n * - migrate any plaintext secrets in config files to encrypted form\n * - load + merge global/project config with apiKeys auto-decrypted\n */\nexport async function bootConfig(): Promise<BootResult> {\n const cwd = process.cwd();\n const pathResolver = new DefaultPathResolver(cwd);\n const projectRoot = pathResolver.projectRoot;\n const userHome = os.homedir();\n const wpaths = resolveWstackPaths({ projectRoot, userHome });\n\n await fs.mkdir(wpaths.globalRoot, { recursive: true });\n await fs.mkdir(wpaths.projectDir, { recursive: true });\n await fs.mkdir(wpaths.projectSessions, { recursive: true });\n\n const vault = new DefaultSecretVault({ keyFile: wpaths.secretsKey });\n\n for (const file of [wpaths.globalConfig, wpaths.projectLocalConfig]) {\n try {\n const { migrated } = await migratePlaintextSecrets(file, vault);\n if (migrated > 0) {\n process.stderr.write(`[WebUI] Encrypted ${migrated} plaintext secret(s) in ${file}\\n`);\n }\n } catch {\n // best-effort\n }\n }\n\n const configLoader = new DefaultConfigLoader({ paths: wpaths, vault });\n const config = await configLoader.load({ cliFlags: {} });\n\n const logger = new DefaultLogger({\n level: config.log?.level ?? 'info',\n file: wpaths.logFile,\n });\n\n return { config, vault, globalConfigPath: wpaths.globalConfig, projectRoot, wpaths, logger };\n}\n\nexport function patchConfig(config: Config, updates: Partial<Config>): Config {\n return Object.freeze({ ...config, ...updates });\n}\n","import { spawnSync } from 'node:child_process';\nimport type { WebSocket } from 'ws';\nimport {\n AutoPhasePlanner,\n PhaseGraphBuilder,\n PhaseOrchestrator,\n PhaseStore,\n WorktreeManager,\n type PhaseGraph,\n type PhaseProgress,\n type PhaseTemplate,\n} from '@wrongstack/core';\nimport type { Agent, Context, EventBus, Logger } from '@wrongstack/core';\n\nfunction isGitRepo(cwd: string): boolean {\n try {\n const r = spawnSync('git', ['rev-parse', '--is-inside-work-tree'], { cwd, encoding: 'utf8' });\n return r.status === 0 && r.stdout.trim() === 'true';\n } catch {\n return false;\n }\n}\n\ninterface WSClient {\n ws: WebSocket;\n id: string;\n}\n\ninterface AutoPhaseWSMessage {\n type: string;\n payload?: Record<string, unknown>;\n}\n\n/**\n * AutoPhaseWebSocketHandler — WebSocket üzerinden AutoPhase kontrolü.\n *\n * Mesaj tipleri:\n * autophase.start → { title, phases?, autonomous? }\n * autophase.pause → {}\n * autophase.resume → {}\n * autophase.stop → {}\n * autophase.status → {}\n * autophase.selectPhase → { phaseId }\n * autophase.taskStatus → { taskId, status }\n */\nexport class AutoPhaseWebSocketHandler {\n private orchestrator: PhaseOrchestrator | null = null;\n private graph: PhaseGraph | null = null;\n private store: PhaseStore;\n private clients = new Set<WSClient>();\n private broadcastInterval: ReturnType<typeof setInterval> | null = null;\n /** Aborts in-flight task agents when the run is stopped. */\n private abort: AbortController | null = null;\n /** Optional per-phase git-worktree isolation (lazily created at start). */\n private worktrees: WorktreeManager | null = null;\n\n constructor(\n private agent: Agent,\n private context: Context,\n private logger: Logger,\n storeDir: string,\n private events?: EventBus,\n private projectRoot?: string,\n ) {\n this.store = new PhaseStore({ baseDir: storeDir });\n }\n\n addClient(ws: WebSocket): void {\n const client: WSClient = { ws, id: crypto.randomUUID() };\n this.clients.add(client);\n\n ws.on('close', () => this.clients.delete(client));\n ws.on('error', () => this.clients.delete(client));\n\n // Anlık durum gönder\n this.sendState(client);\n }\n\n async handleMessage(msg: AutoPhaseWSMessage): Promise<void> {\n switch (msg.type) {\n case 'autophase.start':\n await this.handleStart(msg.payload);\n break;\n case 'autophase.pause':\n this.orchestrator?.pause();\n this.broadcast({ type: 'autophase.paused', payload: {} });\n break;\n case 'autophase.resume':\n this.orchestrator?.resume();\n this.broadcast({ type: 'autophase.resumed', payload: {} });\n break;\n case 'autophase.stop':\n this.abort?.abort();\n this.orchestrator?.stop();\n this.stopBroadcast();\n if (this.graph) void this.store.save(this.graph);\n this.broadcast({ type: 'autophase.stopped', payload: {} });\n break;\n case 'autophase.status':\n this.broadcastState();\n break;\n case 'autophase.selectPhase': {\n const phaseId = msg.payload?.phaseId as string;\n if (phaseId && this.graph) {\n this.broadcastState(phaseId);\n }\n break;\n }\n case 'autophase.taskStatus': {\n const { taskId, status } = msg.payload as { taskId: string; status: string };\n await this.handleTaskStatusChange(taskId, status);\n break;\n }\n case 'autophase.toggleAutonomous': {\n const autonomous = (msg.payload?.autonomous as boolean) ?? !this.graph?.autonomous;\n if (this.graph) {\n this.graph.autonomous = autonomous;\n await this.store.save(this.graph);\n this.broadcast({ type: 'autophase.state', payload: this.buildState() });\n }\n break;\n }\n case 'autophase.save': {\n if (this.graph) {\n await this.store.save(this.graph);\n this.broadcast({ type: 'autophase.saved', payload: { graphId: this.graph.id } });\n }\n break;\n }\n case 'autophase.list': {\n const graphs = await this.store.list();\n this.broadcast({ type: 'autophase.list', payload: { graphs } });\n break;\n }\n case 'autophase.load': {\n const graphId = msg.payload?.graphId as string | undefined;\n if (graphId) {\n const graph = await this.store.load(graphId);\n if (graph) {\n this.graph = graph;\n this.broadcast({ type: 'autophase.state', payload: this.buildState() });\n } else {\n this.broadcast({ type: 'autophase.error', payload: { message: `Graph not found: ${graphId}` } });\n }\n }\n break;\n }\n }\n }\n\n private async handleStart(payload?: Record<string, unknown>): Promise<void> {\n const title = (payload?.goal as string) || (payload?.title as string) || 'Untitled Project';\n const autonomous = (payload?.autonomous as boolean) ?? true;\n\n // Phase plan resolution:\n // 1. explicit phases in the payload win (caller override);\n // 2. otherwise the LLM plans phases+todos for the goal;\n // 3. failing that, fall back to the generic default phases.\n const phases = Array.isArray(payload?.phases)\n ? (payload.phases as PhaseTemplate[])\n : await this.planPhases(title);\n\n this.logger.info(`[AutoPhase] Starting: ${title}`);\n\n // Build the graph up-front so we have a reference for live broadcasts and\n // persistence *before* the (long-running) build begins.\n const graph = await new PhaseGraphBuilder({ title, phases, autonomous }).build();\n this.graph = graph;\n this.abort = new AbortController();\n await this.store.save(graph);\n\n // Per-phase git-worktree isolation, when enabled and inside a git repo.\n // The shared agent/context means we can't run phases in parallel here\n // (we swap a single context.cwd per task), so phases stay sequential —\n // but each phase still commits + squash-merges back through its own\n // worktree, and the lifecycle events drive the live swim-lane/DAG view.\n if (\n !this.worktrees &&\n this.events &&\n this.projectRoot &&\n process.env['WRONGSTACK_AUTOPHASE_WORKTREES'] !== '0' &&\n isGitRepo(this.projectRoot)\n ) {\n this.worktrees = new WorktreeManager({ projectRoot: this.projectRoot, events: this.events });\n }\n\n this.orchestrator = new PhaseOrchestrator({\n graph,\n ctx: {\n executeTask: async (task, phaseId, env) => {\n this.logger.info(`[AutoPhase] [${phaseId}] Executing: ${task.title}`);\n const result = await this.executeTaskWithAgent(task, phaseId, env);\n this.logger.info(`[AutoPhase] [${phaseId}] Completed: ${task.title}`);\n return result;\n },\n onPhaseComplete: (phase) => {\n this.logger.info(`[AutoPhase] Phase completed: ${phase.name}`);\n void this.store.save(graph);\n this.broadcastState();\n },\n onPhaseFail: (phase, error) => {\n this.logger.error(`[AutoPhase] Phase failed: ${phase.name} — ${error.message}`);\n void this.store.save(graph);\n this.broadcastState();\n },\n },\n worktrees: this.worktrees ?? undefined,\n autonomous,\n // Must stay 1: phase tasks run on the single shared context whose cwd we\n // swap per phase, so parallel phases would race on context.cwd.\n maxConcurrentPhases: 1,\n // Sequential within a phase: each todo is a full-tool agent editing the\n // phase worktree, so running two at once risks concurrent writes.\n maxConcurrentTasks: 1,\n });\n\n // Start the live broadcast immediately, then run the orchestrator in the\n // background. Awaiting start() would block until the *entire* build\n // finishes — the periodic broadcast (below) reads the mutating graph, so\n // clients see live progress while it runs.\n this.startBroadcast();\n this.broadcastState();\n\n void this.orchestrator\n .start()\n .then(() => {\n this.orchestrator?.stop(); // clear the autonomous tick interval\n void this.store.save(graph);\n this.stopBroadcast();\n const failed = graph.failedPhaseIds.length > 0;\n this.broadcast(\n failed\n ? { type: 'autophase.failed', payload: { title } }\n : { type: 'autophase.completed', payload: { title } },\n );\n this.broadcastState();\n })\n .catch((err: unknown) => {\n this.logger.error(`[AutoPhase] Aborted: ${err instanceof Error ? err.message : String(err)}`);\n this.stopBroadcast();\n this.broadcast({ type: 'autophase.failed', payload: { title, error: String(err) } });\n });\n }\n\n /** Generic fallback phases when the LLM planner produces nothing usable. */\n private defaultPhases(): PhaseTemplate[] {\n return [\n { name: 'Discovery', description: 'Requirements gathering', priority: 'high', estimateHours: 2, parallelizable: false },\n { name: 'Design', description: 'Architecture and design', priority: 'critical', estimateHours: 4, parallelizable: false },\n { name: 'Implementation', description: 'Core development', priority: 'critical', estimateHours: 12, parallelizable: false },\n { name: 'Testing', description: 'Unit and integration tests', priority: 'high', estimateHours: 6, parallelizable: true },\n { name: 'Deployment', description: 'Deploy to production', priority: 'medium', estimateHours: 2, parallelizable: false },\n ];\n }\n\n /** Plan phases+todos for the goal via the LLM; fall back to defaults on failure. */\n private async planPhases(goal: string): Promise<PhaseTemplate[]> {\n try {\n const planner = new AutoPhasePlanner({\n goal,\n runOnce: async (prompt) => {\n const result = (await this.agent.run(prompt, { signal: new AbortController().signal })) as {\n status: string;\n finalText?: string;\n };\n return result.status === 'done' ? (result.finalText ?? '') : '';\n },\n });\n const { phases, parseFailed } = await planner.plan();\n if (!parseFailed && phases.length > 0) {\n const todos = phases.reduce((n, p) => n + (p.taskTemplates?.length ?? 0), 0);\n this.logger.info(`[AutoPhase] Planned ${phases.length} phases / ${todos} todos for: ${goal}`);\n return phases;\n }\n this.logger.info(`[AutoPhase] Planner produced no phases; using defaults for: ${goal}`);\n } catch (err) {\n this.logger.error(`[AutoPhase] Planning failed, using defaults: ${err instanceof Error ? err.message : String(err)}`);\n }\n return this.defaultPhases();\n }\n\n private async executeTaskWithAgent(\n task: import('@wrongstack/core').TaskNode,\n phaseId: string,\n env?: { cwd?: string; branch?: string },\n ): Promise<unknown> {\n // Task'ı agent'a çalıştır\n const prompt = `Execute task: ${task.title}\\n\\nDescription: ${task.description}\\nPhase: ${phaseId}\\nPriority: ${task.priority}\\nType: ${task.type}`;\n const signal = this.abort?.signal ?? new AbortController().signal;\n // Redirect the shared context's cwd at the phase worktree for the duration\n // of this task. Safe because phases/tasks run strictly sequentially here;\n // tools read `ctx.cwd` live, so the agent operates inside the worktree.\n const prevCwd = this.context.cwd;\n if (env?.cwd) this.context.cwd = env.cwd;\n try {\n return await this.agent.run(prompt, { signal });\n } finally {\n this.context.cwd = prevCwd;\n }\n }\n\n private async handleTaskStatusChange(taskId: string, status: string): Promise<void> {\n if (!this.graph) return;\n\n for (const phase of this.graph.phases.values()) {\n const task = phase.taskGraph.nodes.get(taskId);\n if (task) {\n task.status = status as import('@wrongstack/core').TaskStatus;\n task.updatedAt = Date.now();\n this.broadcastState();\n return;\n }\n }\n }\n\n private startBroadcast(): void {\n if (this.broadcastInterval) return;\n this.broadcastInterval = setInterval(() => {\n const progress = this.orchestrator?.getProgress();\n if (progress) this.broadcast({ type: 'autophase.progress', payload: progress });\n this.broadcastState();\n }, 2000);\n }\n\n private stopBroadcast(): void {\n if (this.broadcastInterval) {\n clearInterval(this.broadcastInterval);\n this.broadcastInterval = null;\n }\n }\n\n private broadcastState(activePhaseId?: string): void {\n if (!this.graph) return;\n\n const state = this.buildState(activePhaseId);\n this.broadcast({ type: 'autophase.state', payload: state });\n }\n\n private buildState(activePhaseId?: string): Record<string, unknown> {\n if (!this.graph) {\n return { phases: [], tasks: [], overallPercent: 0, autonomous: true, title: '' };\n }\n\n const phases = Array.from(this.graph.phases.values());\n const currentActiveId = activePhaseId || phases.find((p) => p.status === 'running')?.id || phases[0]?.id || '';\n const activePhase = this.graph.phases.get(currentActiveId);\n\n const totalTasks = phases.reduce((sum, p) => sum + p.taskGraph.nodes.size, 0);\n const completedTasks = phases.reduce(\n (sum, p) => sum + Array.from(p.taskGraph.nodes.values()).filter((t) => t.status === 'completed').length,\n 0,\n );\n\n const phaseItems = phases.map((p) => ({\n id: p.id,\n name: p.name,\n description: p.description,\n status: p.status,\n priority: p.priority,\n estimateHours: p.estimateHours,\n actualDurationMs: p.actualDurationMs,\n startedAt: p.startedAt,\n completedAt: p.completedAt,\n progressPercent: p.taskGraph.nodes.size > 0\n ? Math.round((Array.from(p.taskGraph.nodes.values()).filter((t) => t.status === 'completed').length / p.taskGraph.nodes.size) * 100)\n : 0,\n taskCount: p.taskGraph.nodes.size,\n completedTasks: Array.from(p.taskGraph.nodes.values()).filter((t) => t.status === 'completed').length,\n assignedAgents: p.assignedAgents,\n isActive: p.id === currentActiveId,\n }));\n\n const taskItems = activePhase\n ? Array.from(activePhase.taskGraph.nodes.values()).map((t) => ({\n id: t.id,\n title: t.title,\n description: t.description,\n status: t.status,\n priority: t.priority,\n type: t.type,\n estimateHours: t.estimateHours,\n actualHours: t.actualHours,\n assignee: t.assignee,\n tags: t.tags || [],\n startedAt: t.startedAt,\n completedAt: t.completedAt,\n }))\n : [];\n\n const completedPhases = phases.filter((p) => p.status === 'completed').length;\n\n return {\n title: this.graph.title,\n phases: phaseItems,\n tasks: taskItems,\n activePhaseId: currentActiveId,\n overallPercent: phases.length > 0 ? Math.round((completedPhases / phases.length) * 100) : 0,\n autonomous: this.graph.autonomous,\n totalTasks,\n completedTasks,\n };\n }\n\n private sendState(client: WSClient): void {\n if (!this.graph) return;\n const state = this.buildState();\n this.send(client, { type: 'autophase.state', payload: state });\n }\n\n private broadcast(msg: { type: string; payload: unknown }): void {\n const data = JSON.stringify(msg);\n for (const client of this.clients) {\n if (client.ws.readyState === 1) { // OPEN\n client.ws.send(data);\n }\n }\n }\n\n private send(client: WSClient, msg: { type: string; payload: unknown }): void {\n if (client.ws.readyState === 1) {\n client.ws.send(JSON.stringify(msg));\n }\n }\n}\n","import type { WebSocket } from 'ws';\nimport type { EventBus, Logger } from '@wrongstack/core';\nimport type { WorktreeHandleView, WSServerMessage } from '../types.js';\n\nconst MAX_ACTIVITY = 6;\n\n/**\n * WorktreeWebSocketHandler — mirrors AutoPhaseWebSocketHandler. Subscribes to\n * the shared EventBus `worktree.*` lifecycle events, keeps a live snapshot of\n * every worktree, and broadcasts:\n * - `worktree.event` incrementally (drives the flowing activity strip)\n * - `worktree.state` on connect + on a 2s timer (drives swim-lanes/DAG)\n */\nexport class WorktreeWebSocketHandler {\n private readonly clients = new Set<WebSocket>();\n private readonly handles = new Map<string, WorktreeHandleView>();\n private baseBranch = '';\n private broadcastInterval: ReturnType<typeof setInterval> | null = null;\n private readonly offs: Array<() => void> = [];\n\n constructor(\n private readonly events: EventBus,\n private readonly logger: Logger,\n ) {\n this.subscribe();\n }\n\n addClient(ws: WebSocket): void {\n this.clients.add(ws);\n ws.on('close', () => this.clients.delete(ws));\n ws.on('error', () => this.clients.delete(ws));\n this.send(ws, this.stateMessage());\n }\n\n dispose(): void {\n for (const off of this.offs) off();\n this.offs.length = 0;\n this.stopBroadcast();\n }\n\n // ── internals ───────────────────────────────────────────────────────────\n\n private subscribe(): void {\n const on = this.events.on.bind(this.events) as unknown as (\n ev: string,\n fn: (p: unknown) => void,\n ) => () => void;\n\n this.offs.push(\n on('worktree.allocated', (p) => {\n const e = p as { handleId: string; ownerId: string; ownerLabel: string; branch: string; baseBranch: string };\n this.baseBranch = e.baseBranch || this.baseBranch;\n this.upsert(e.handleId, {\n handleId: e.handleId,\n ownerId: e.ownerId,\n ownerLabel: e.ownerLabel,\n branch: e.branch,\n baseBranch: e.baseBranch,\n status: 'active',\n insertions: 0,\n deletions: 0,\n files: 0,\n allocatedAt: Date.now(),\n lastEventAt: Date.now(),\n recentActivity: [],\n });\n this.activity(e.handleId, 'allocated', `branch ${e.branch}`);\n this.ensureBroadcast();\n }),\n on('worktree.committed', (p) => {\n const e = p as { handleId: string; insertions: number; deletions: number; files: number; committed: boolean };\n this.patch(e.handleId, { status: 'committing', insertions: e.insertions, deletions: e.deletions, files: e.files });\n if (e.committed) this.activity(e.handleId, 'committed', `+${e.insertions}/-${e.deletions} (${e.files}f)`);\n this.broadcastState();\n }),\n on('worktree.merged', (p) => {\n const e = p as { handleId: string; baseBranch: string };\n this.patch(e.handleId, { status: 'merged' });\n this.activity(e.handleId, 'merged', `→ ${e.baseBranch}`);\n this.broadcastState();\n }),\n on('worktree.conflict', (p) => {\n const e = p as { handleId: string; conflictFiles: string[] };\n this.patch(e.handleId, { status: 'needs-review', conflictFiles: e.conflictFiles });\n this.activity(e.handleId, 'conflict', e.conflictFiles.join(', '));\n this.broadcastState();\n }),\n on('worktree.failed', (p) => {\n const e = p as { handleId: string; error: string };\n this.patch(e.handleId, { status: 'failed' });\n this.activity(e.handleId, 'failed', e.error);\n this.broadcastState();\n }),\n on('worktree.released', (p) => {\n const e = p as { handleId: string; kept: boolean };\n if (!e.kept) this.handles.delete(e.handleId);\n this.activity(e.handleId, 'released', e.kept ? 'kept for review' : 'removed');\n if (this.handles.size === 0) this.stopBroadcast();\n else this.broadcastState();\n }),\n );\n }\n\n private upsert(id: string, view: WorktreeHandleView): void {\n this.handles.set(id, view);\n }\n\n private patch(id: string, patch: Partial<WorktreeHandleView>): void {\n const cur = this.handles.get(id);\n if (!cur) return;\n this.handles.set(id, { ...cur, ...patch, lastEventAt: Date.now() });\n }\n\n private activity(id: string, kind: string, text: string): void {\n const cur = this.handles.get(id);\n if (cur) {\n const recentActivity = [...cur.recentActivity, { kind, text, at: Date.now() }].slice(-MAX_ACTIVITY);\n this.handles.set(id, { ...cur, recentActivity });\n }\n this.broadcast({ type: 'worktree.event', payload: { kind, handleId: id, text, at: Date.now() } });\n }\n\n private stateMessage(): WSServerMessage {\n return {\n type: 'worktree.state',\n payload: { worktrees: [...this.handles.values()], baseBranch: this.baseBranch },\n };\n }\n\n private broadcastState(): void {\n this.broadcast(this.stateMessage());\n }\n\n private ensureBroadcast(): void {\n this.broadcast(this.stateMessage());\n if (this.broadcastInterval) return;\n this.broadcastInterval = setInterval(() => this.broadcast(this.stateMessage()), 2000);\n }\n\n private stopBroadcast(): void {\n this.broadcast(this.stateMessage());\n if (this.broadcastInterval) {\n clearInterval(this.broadcastInterval);\n this.broadcastInterval = null;\n }\n }\n\n private broadcast(msg: WSServerMessage): void {\n const data = JSON.stringify(msg);\n for (const ws of this.clients) {\n try {\n if (ws.readyState === 1) ws.send(data);\n } catch (err) {\n this.logger.debug?.(`worktree broadcast failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n }\n\n private send(ws: WebSocket, msg: WSServerMessage): void {\n try {\n if (ws.readyState === 1) ws.send(JSON.stringify(msg));\n } catch {\n /* client gone */\n }\n }\n}\n"],"mappings":"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","names":["fs","DefaultMemoryStore","DefaultModeStore","DefaultSessionStore","DefaultSkillLoader","DefaultSystemPromptBuilder","DefaultTokenCounter","HybridCompactor","TOKENS","TOKENS","DefaultMemoryStore","DefaultSessionStore","DefaultTokenCounter","DefaultModeStore","DefaultSkillLoader","DefaultSystemPromptBuilder","HybridCompactor","resolve","provider","modePrompt"]}
|