@northflare/runner 0.0.32 → 0.0.34

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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/logger.ts","../src/utils/debug.ts","../src/services/SSEClient.ts","../src/services/RunnerAPIClient.ts","../src/utils/status-line.ts","../src/utils/message-log.ts","../src/components/message-handler-sse.ts","../src/components/claude-sdk-manager.ts","../src/utils/console.ts","../src/utils/expand-env.ts","../src/utils/model.ts","../src/components/codex-sdk-manager.ts","../../northflare-agent-sdk/src/session-persistence.ts","../../northflare-agent-sdk/src/image-storage/memory.ts","../../northflare-agent-sdk/src/image-storage/filesystem.ts","../src/components/northflare-agent-sdk-manager.ts","../src/components/repository-manager.ts","../src/components/enhanced-repository-manager.ts","../src/utils/StateManager.ts","../src/runner-sse.ts","../src/utils/tool-response-sanitizer.ts","../src/utils/update-coordinator.ts","../src/utils/version.ts","../src/utils/config.ts","../src/utils/inactivity-timeout.ts","../src/index.ts"],"sourcesContent":["/**\n * Logger configuration using Winston\n */\n\nimport winston from \"winston\";\nimport path from \"path\";\nimport {\n DebugSubsystem,\n getDebugConfig,\n isDebugEnabledFor,\n} from './debug.js';\n\n// Custom log levels\nconst levels = {\n error: 0,\n warn: 1,\n info: 2,\n http: 3,\n verbose: 4,\n debug: 5,\n silly: 6,\n};\n\n// Log colors\nconst colors = {\n error: \"red\",\n warn: \"yellow\",\n info: \"green\",\n http: \"magenta\",\n verbose: \"cyan\",\n debug: \"blue\",\n silly: \"gray\",\n};\n\nwinston.addColors(colors);\n\n// Use a getter function so debug state is checked at call time, not module load time\nfunction isDebugEnabled(): boolean {\n return getDebugConfig().enabled;\n}\n\nconst componentSubsystemMap: Record<string, DebugSubsystem> = {\n MessageHandler: \"rpc\",\n RunnerApp: \"runner\",\n SSEClient: \"sse\",\n RunnerAPIClient: \"rpc\",\n ConfigManager: \"runner\",\n StateManager: \"state\",\n MessageFlow: \"messages\",\n};\n\nfunction resolveSubsystem(value?: string): string {\n if (value && typeof value === \"string\") {\n return value.toLowerCase();\n }\n return \"runner\";\n}\n\nconst subsystemFilter = winston.format((info) => {\n if (info.level !== \"debug\") return info;\n const subsystem = resolveSubsystem(\n (info as any).subsystem || (info as any).component\n );\n\n return isDebugEnabledFor(subsystem) ? info : false;\n});\n\n// Format for console output\nconst consoleFormat = winston.format.combine(\n subsystemFilter(),\n winston.format.colorize({ all: true }),\n winston.format.timestamp({ format: \"YYYY-MM-DD HH:mm:ss\" }),\n winston.format.printf(\n ({ timestamp, level, message, stack, component, subsystem, ...metadata }) => {\n const scopeParts = [subsystem, component].filter(Boolean);\n const scope = scopeParts.length ? ` ${scopeParts.join('/')}` : \"\";\n\n let msg = `${timestamp} [${level}]${scope}: ${message}`;\n // Only show stack traces and metadata in debug mode\n if (isDebugEnabled()) {\n if (stack) {\n msg += `\\n${stack}`;\n }\n const filteredMetadata = { ...metadata } as Record<string, unknown>;\n delete filteredMetadata[\"component\"];\n delete filteredMetadata[\"subsystem\"];\n\n if (Object.keys(filteredMetadata).length > 0) {\n msg += ` ${JSON.stringify(filteredMetadata)}`;\n }\n }\n return msg;\n }\n )\n);\n\n// Format for file output\nconst fileFormat = winston.format.combine(\n subsystemFilter(),\n winston.format.timestamp({ format: \"YYYY-MM-DD HH:mm:ss\" }),\n winston.format.errors({ stack: true }),\n winston.format.json()\n);\n\n// Create logger instance\n// Set level to debug unconditionally - the subsystemFilter will decide what to actually output\n// This avoids issues with env vars not being set at module load time\nexport const logger = winston.createLogger({\n level: \"debug\",\n levels,\n transports: [\n // Console transport set to debug - subsystemFilter handles the actual filtering\n new winston.transports.Console({\n format: consoleFormat,\n level: \"debug\",\n }),\n ],\n});\n\n// Add file transports if log directory is configured\nexport function configureFileLogging(logDir: string): void {\n // Error log file\n logger.add(\n new winston.transports.File({\n filename: path.join(logDir, \"error.log\"),\n level: \"error\",\n format: fileFormat,\n maxsize: 10 * 1024 * 1024, // 10MB\n maxFiles: 5,\n })\n );\n\n // Combined log file\n logger.add(\n new winston.transports.File({\n filename: path.join(logDir, \"combined.log\"),\n format: fileFormat,\n maxsize: 50 * 1024 * 1024, // 50MB\n maxFiles: 10,\n })\n );\n\n // Debug log file (only in debug mode)\n if (isDebugEnabled()) {\n logger.add(\n new winston.transports.File({\n filename: path.join(logDir, \"debug.log\"),\n level: \"debug\",\n format: fileFormat,\n maxsize: 100 * 1024 * 1024, // 100MB\n maxFiles: 3,\n })\n );\n }\n}\n\n// Create child logger for specific components\nexport function createLogger(\n component: string,\n subsystem?: DebugSubsystem\n): winston.Logger {\n const resolvedSubsystem =\n subsystem || componentSubsystemMap[component] || \"runner\";\n return logger.child({ component, subsystem: resolvedSubsystem });\n}\n\n// Log unhandled errors\n// Route unhandled exceptions/rejections to the console so we don't litter local\n// directories with log files when the runner boots.\nconst exceptionTransportOptions = { format: consoleFormat } as const;\n\nlogger.exceptions.handle(\n new winston.transports.Console(exceptionTransportOptions)\n);\nlogger.rejections.handle(\n new winston.transports.Console(exceptionTransportOptions)\n);\n\n// Export default logger\nexport default logger;\n","export type DebugSubsystem =\n | \"runner\"\n | \"manager\"\n | \"rpc\"\n | \"sse\"\n | \"sdk\"\n | \"repo\"\n | \"state\"\n | \"messages\";\n\ntype DebugConfig = {\n enabled: boolean;\n allowAll: boolean;\n subsystems: Set<string>;\n raw: string;\n};\n\nconst KNOWN_SUBSYSTEMS: Set<string> = new Set([\n \"runner\",\n \"manager\",\n \"rpc\",\n \"sse\",\n \"sdk\",\n \"repo\",\n \"state\",\n \"messages\",\n]);\n\nlet cachedConfig: DebugConfig | null = null;\n\nexport function getDebugConfig(): DebugConfig {\n // Only use cache if we have already parsed a non-empty debug value.\n // This allows modules that load before CLI sets env vars to re-check\n // the config later once the env vars are actually set.\n if (cachedConfig && cachedConfig.enabled) {\n return cachedConfig;\n }\n\n const explicitFlag = process.env[\"NORTHFLARE_RUNNER_DEBUG\"];\n const legacyFlag = process.env[\"DEBUG\"];\n\n const config = parseDebugValue(\n typeof explicitFlag === \"string\" ? explicitFlag : legacyFlag\n );\n\n // Only cache if debug is enabled (meaning env vars were set)\n if (config.enabled) {\n cachedConfig = config;\n }\n\n return config;\n}\n\nexport function isRunnerDebugEnabled(): boolean {\n return getDebugConfig().enabled;\n}\n\nexport function isDebugEnabledFor(\n subsystem?: DebugSubsystem | string\n): boolean {\n const config = getDebugConfig();\n if (!config.enabled) return false;\n if (config.allowAll) return true;\n if (!subsystem) return false;\n\n const normalized = normalizeSubsystem(subsystem);\n return config.subsystems.has(normalized);\n}\n\nfunction parseDebugValue(value?: string): DebugConfig {\n if (!value) {\n return {\n enabled: false,\n allowAll: false,\n subsystems: new Set(),\n raw: \"\",\n };\n }\n\n const trimmed = value.trim();\n const normalized = trimmed.toLowerCase();\n\n // Support boolean-style flags\n if (isTruthy(normalized) || normalized === \"*\" || normalized === \"all\") {\n return {\n enabled: true,\n allowAll: true,\n subsystems: new Set(),\n raw: trimmed,\n };\n }\n\n const parts = normalized\n .split(\",\")\n .map((part) => part.trim())\n .filter(Boolean)\n .map((part) => normalizeSubsystem(part));\n\n return {\n enabled: parts.length > 0,\n allowAll: false,\n subsystems: new Set(parts),\n raw: trimmed,\n };\n}\n\nfunction normalizeSubsystem(value: string): string {\n const normalized = value.trim().toLowerCase();\n\n // Common aliases\n if (normalized === \"managers\") return \"manager\";\n if (normalized === \"repos\" || normalized === \"git\") return \"repo\";\n if (normalized === \"state-manager\") return \"state\";\n if (normalized === \"message\" || normalized === \"msg\") return \"messages\";\n\n return KNOWN_SUBSYSTEMS.has(normalized) ? normalized : normalized;\n}\n\nfunction isTruthy(value: string): boolean {\n const normalized = value.trim().toLowerCase();\n return (\n normalized === \"true\" ||\n normalized === \"1\" ||\n normalized === \"yes\" ||\n normalized === \"on\"\n );\n}\n","/**\n * SSE (Server-Sent Events) Client for real-time message streaming\n * \n * Connects to the server's SSE endpoint to receive real-time runner messages\n * and handles automatic reconnection with exponential backoff.\n */\n\nimport { createLogger } from '../utils/logger.js';\nimport { RunnerConfig } from '../types/index.js';\nimport { EventSource as NodeEventSource } from 'eventsource';\n\nconst logger = createLogger('SSEClient');\n\nexport interface SSEEvent {\n id?: string;\n type: string;\n data: any;\n}\n\nexport interface SSEClientOptions {\n url: string;\n runnerId: string;\n token: string;\n onMessage: (event: SSEEvent) => void;\n onError?: (error: Error) => void;\n onConnect?: () => void;\n onDisconnect?: () => void;\n reconnectInterval?: number;\n maxReconnectInterval?: number;\n reconnectMultiplier?: number;\n maxReconnectAttempts?: number;\n /** Callback to get the current lastProcessedAt timestamp for reconnection */\n getLastProcessedAt?: () => string | undefined;\n}\n\nexport class SSEClient {\n private eventSource: EventSource | null = null;\n private reconnectTimer: NodeJS.Timeout | null = null;\n private reconnectAttempts = 0;\n private currentReconnectInterval: number;\n private isConnected = false;\n private isStopped = false;\n private lastEventId: string | undefined;\n\n constructor(private options: SSEClientOptions) {\n this.currentReconnectInterval = options.reconnectInterval || 1000;\n }\n\n /**\n * Connect to the SSE endpoint\n */\n async connect(since?: string): Promise<void> {\n if (this.eventSource) {\n logger.warn('SSE client already connected');\n return;\n }\n\n this.isStopped = false;\n\n try {\n // Build URL with query parameters\n const url = new URL(this.options.url);\n // Include token as query param as a fallback in case proxies strip headers\n url.searchParams.set('token', this.options.token);\n if (since) {\n url.searchParams.set('since', since);\n }\n\n // Sanitize token from logs\n const sanitized = new URL(url.toString());\n if (sanitized.searchParams.has('token')) {\n sanitized.searchParams.set('token', '[redacted]');\n }\n logger.info(`Connecting to SSE endpoint: ${sanitized.toString()}`);\n logger.debug(`SSE auth header set: ${this.options.token ? 'yes' : 'no'}`);\n\n // Create EventSource with authorization header (Node polyfill supports headers)\n this.eventSource = new (NodeEventSource as any)(url.toString(), {\n headers: {\n 'Authorization': `Bearer ${this.options.token}`,\n },\n withCredentials: false,\n });\n\n // Set up event listeners\n this.eventSource!.onopen = () => {\n logger.info('SSE connection established');\n this.isConnected = true;\n this.reconnectAttempts = 0;\n this.currentReconnectInterval = this.options.reconnectInterval || 1000;\n \n if (this.options.onConnect) {\n this.options.onConnect();\n }\n };\n\n this.eventSource!.onmessage = (event: MessageEvent) => {\n try {\n const parsed = JSON.parse(event.data);\n const envelope = parsed && typeof parsed === 'object' ? parsed : { data: parsed };\n const inner = (envelope && 'data' in envelope) ? (envelope as any).data : parsed;\n const sseEvent: SSEEvent = {\n id: (envelope as any).id || (event as any).lastEventId,\n type: (envelope as any).type || (event as any).type || 'message',\n data: inner,\n };\n\n // Update last event ID for reconnection\n if (sseEvent.id) {\n this.lastEventId = sseEvent.id;\n }\n\n this.options.onMessage(sseEvent);\n } catch (error) {\n logger.error('Failed to parse SSE message:', error);\n }\n };\n\n this.eventSource!.onerror = (error: Event) => {\n logger.error('SSE connection error:', error);\n this.isConnected = false;\n\n if (this.options.onError) {\n this.options.onError(new Error('SSE connection error'));\n }\n\n // Close the connection and attempt reconnection\n this.disconnect();\n \n if (!this.isStopped) {\n this.scheduleReconnect();\n }\n };\n\n // Listen for specific event types\n this.eventSource!.addEventListener('runner.message', ((event: MessageEvent) => {\n try {\n const parsed = JSON.parse(event.data);\n const envelope = parsed && typeof parsed === 'object' ? parsed : { data: parsed };\n const inner = (envelope && 'data' in envelope) ? (envelope as any).data : parsed;\n const sseEvent: SSEEvent = {\n id: (envelope as any).id || (event as any).lastEventId,\n type: 'runner.message',\n data: inner,\n };\n\n // Update last event ID\n if (sseEvent.id) {\n this.lastEventId = sseEvent.id;\n }\n\n this.options.onMessage(sseEvent);\n } catch (error) {\n logger.error('Failed to parse runner.message event:', error);\n }\n }) as any);\n\n const typedRunnerRepoHandler = (eventType: string) => ((event: MessageEvent) => {\n try {\n const parsed = JSON.parse(event.data);\n const envelope = parsed && typeof parsed === 'object' ? parsed : { data: parsed };\n const inner = (envelope && 'data' in envelope) ? (envelope as any).data : parsed;\n const sseEvent: SSEEvent = {\n id: (envelope as any).id || (event as any).lastEventId,\n type: eventType,\n data: inner,\n };\n if (sseEvent.id) {\n this.lastEventId = sseEvent.id;\n }\n this.options.onMessage(sseEvent);\n } catch (error) {\n logger.error(`Failed to parse ${eventType} event:`, error);\n }\n }) as any;\n\n this.eventSource!.addEventListener('runnerRepo.created', typedRunnerRepoHandler('runnerRepo.created'));\n this.eventSource!.addEventListener('runnerRepo.updated', typedRunnerRepoHandler('runnerRepo.updated'));\n this.eventSource!.addEventListener('runnerRepo.deleted', typedRunnerRepoHandler('runnerRepo.deleted'));\n\n // Listen for connection established event\n this.eventSource!.addEventListener('connection.established', ((event: MessageEvent) => {\n logger.debug('Received connection.established event:', event.data);\n }) as any);\n\n // Listen for error events\n this.eventSource!.addEventListener('error', ((event: MessageEvent) => {\n logger.error('Received error event from server:', event.data);\n }) as any);\n\n // Listen for shutdown events\n this.eventSource!.addEventListener('shutdown', ((event: MessageEvent) => {\n logger.warn('Server is shutting down:', event.data);\n this.stop();\n }) as any);\n\n } catch (error) {\n logger.error('Failed to connect to SSE endpoint:', error);\n \n if (this.options.onError) {\n this.options.onError(error instanceof Error ? error : new Error(String(error)));\n }\n\n // Schedule reconnection\n if (!this.isStopped) {\n this.scheduleReconnect();\n }\n }\n }\n\n /**\n * Disconnect from the SSE endpoint\n */\n disconnect(): void {\n if (this.eventSource) {\n this.eventSource.close();\n this.eventSource = null;\n this.isConnected = false;\n\n if (this.options.onDisconnect) {\n this.options.onDisconnect();\n }\n }\n\n // Clear reconnection timer\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n }\n\n /**\n * Stop the client and prevent reconnection\n */\n stop(): void {\n logger.info('Stopping SSE client');\n this.isStopped = true;\n this.disconnect();\n }\n\n /**\n * Schedule a reconnection attempt\n */\n private scheduleReconnect(): void {\n const maxAttempts = this.options.maxReconnectAttempts || Infinity;\n\n if (this.reconnectAttempts >= maxAttempts) {\n logger.error(`Max reconnection attempts (${maxAttempts}) reached. Giving up.`);\n return;\n }\n\n this.reconnectAttempts++;\n\n logger.info(`Scheduling reconnection attempt ${this.reconnectAttempts} in ${this.currentReconnectInterval}ms`);\n\n this.reconnectTimer = setTimeout(() => {\n // Use the callback to get the current lastProcessedAt timestamp if available,\n // otherwise fall back to undefined (server will use runner's DB lastProcessedAt)\n const since = this.options.getLastProcessedAt?.();\n this.connect(since);\n }, this.currentReconnectInterval);\n\n // Exponential backoff\n const multiplier = this.options.reconnectMultiplier || 2;\n const maxInterval = this.options.maxReconnectInterval || 60000;\n\n this.currentReconnectInterval = Math.min(\n this.currentReconnectInterval * multiplier,\n maxInterval\n );\n }\n\n /**\n * Check if the client is currently connected\n */\n isConnectedToServer(): boolean {\n return this.isConnected;\n }\n\n /**\n * Get the last received event ID\n */\n getLastEventId(): string | undefined {\n return this.lastEventId;\n }\n}\n","/**\n * HTTP API client for runner-specific endpoints\n *\n * Provides methods to interact with the server's runner API endpoints\n * including fetching missed messages and other runner operations.\n */\n\nimport { createLogger } from '../utils/logger.js';\nimport { RunnerConfig, RunnerMessage } from '../types/index.js';\n\nconst logger = createLogger(\"RunnerAPIClient\");\n\nexport interface FetchMissedMessagesOptions {\n since: Date | string;\n limit?: number;\n}\n\nexport class RunnerAPIClient {\n private baseUrl: string;\n private token: string;\n private runnerId: string;\n private workspacePath?: string;\n\n constructor(config: RunnerConfig) {\n this.baseUrl = config.orchestratorUrl;\n this.token = process.env[\"NORTHFLARE_RUNNER_TOKEN\"] || \"\";\n this.runnerId = config.runnerId || \"\";\n this.workspacePath = config.workspacePath;\n }\n\n /**\n * Update the runner ID after registration\n */\n setRunnerId(runnerId: string): void {\n this.runnerId = runnerId;\n }\n\n /**\n * Fetch missed messages since a given timestamp\n */\n async fetchMissedMessages(\n options: FetchMissedMessagesOptions\n ): Promise<RunnerMessage[]> {\n const since =\n options.since instanceof Date\n ? options.since.toISOString()\n : options.since;\n const limit = options.limit || 1000;\n\n logger.debug(`Fetching missed messages since ${since} (limit: ${limit})`);\n\n try {\n const url = `${this.baseUrl}/api/runner/messages/since`;\n const params = new URLSearchParams({\n since,\n limit: limit.toString(),\n });\n\n const response = await fetch(`${url}?${params}`, {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${this.token}`,\n \"X-Runner-Id\": this.runnerId,\n \"Content-Type\": \"application/json\",\n },\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(\n `Failed to fetch missed messages: ${response.status} - ${error}`\n );\n }\n\n const data = (await response.json()) as any;\n\n // Transform the raw database records to our internal RunnerMessage format\n const messages: RunnerMessage[] = data.messages.map((msg: any) => ({\n id: msg.id,\n direction: msg.direction,\n runnerId: msg.runner || msg.runnerId,\n taskId: msg.task || msg.taskId || null,\n workspaceId: msg.workspace || msg.workspaceId || null,\n conversationId: msg.conversation || msg.conversationId || null,\n conversationObjectType: msg.conversationObjectType,\n conversationObjectId: msg.conversationObjectId,\n payload: msg.payload,\n expiresAt: msg.expiresAt,\n createdAt: msg.createdAt,\n }));\n\n logger.info(`Fetched ${messages.length} missed messages`);\n return messages;\n } catch (error) {\n logger.error(\"Failed to fetch missed messages:\", error);\n throw error;\n }\n }\n\n /**\n * Send a message acknowledgment to update the high-water mark\n */\n async acknowledgeMessage(messageTimestamp: string): Promise<void> {\n logger.debug(`Acknowledging message with timestamp: ${messageTimestamp}`);\n\n try {\n const response = await fetch(`${this.baseUrl}/api/runner/messages`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.token}`,\n \"X-Runner-Id\": this.runnerId,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n method: \"message.acknowledge\",\n params: {\n runnerId: this.runnerId,\n messageTimestamp,\n },\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(\n `Failed to acknowledge message: ${response.status} - ${error}`\n );\n }\n\n logger.debug(\"Message acknowledged successfully\");\n } catch (error) {\n logger.error(\"Failed to acknowledge message:\", error);\n throw error;\n }\n }\n\n /**\n * Sync runner repositories with the orchestrator\n */\n async syncRunnerRepos(\n repos: Array<{ uuid: string; name: string; path: string; external?: boolean }>\n ): Promise<{ success: boolean; syncedCount: number }> {\n logger.debug(`Syncing ${repos.length} runner repos with orchestrator`);\n\n try {\n const response = await fetch(`${this.baseUrl}/api/runner/repos/sync`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n repos,\n workspacePath: this.workspacePath,\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(\n `Failed to sync runner repos: ${response.status} - ${error}`\n );\n }\n\n const data = (await response.json()) as any;\n logger.info(\n `Successfully synced ${data.syncedCount} runner repos with orchestrator`\n );\n\n return {\n success: data.success,\n syncedCount: data.syncedCount,\n };\n } catch (error) {\n logger.error(\"Failed to sync runner repos:\", error);\n throw error;\n }\n }\n\n /**\n * Fetch the canonical runner repos snapshot from the server\n */\n async listRunnerRepos(): Promise<{ repos: any[]; workspacePath?: string }> {\n logger.debug(\"Fetching runner repo snapshot from orchestrator\");\n const response = await fetch(`${this.baseUrl}/api/runner/repos`, {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${this.token}`,\n \"X-Runner-Id\": this.runnerId,\n \"Content-Type\": \"application/json\",\n },\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to list runner repos: ${response.status} - ${error}`);\n }\n\n const data = (await response.json()) as any;\n return {\n repos: data.repos || [],\n workspacePath: data.workspacePath,\n };\n }\n\n /**\n * Upsert a single runner repo (CLI add-repo)\n */\n async upsertRunnerRepo(repo: {\n uuid?: string;\n name: string;\n path: string;\n external?: boolean;\n }): Promise<{ repo: any }> {\n logger.debug(`Upserting runner repo ${repo.name}`);\n const response = await fetch(`${this.baseUrl}/api/runner/repos`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.token}`,\n \"X-Runner-Id\": this.runnerId,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(repo),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to upsert runner repo: ${response.status} - ${error}`);\n }\n\n const data = (await response.json()) as any;\n return { repo: data.repo };\n }\n}\n","/**\n * StatusLineManager - Manages persistent status line output for active agent processes\n *\n * This component maintains a single-line status output that updates every minute to show\n * the count of active agent processes. It prevents the machine from entering idle\n * state while processes are running and provides clear visual feedback without cluttering\n * the terminal with multiple log lines.\n */\nimport { isRunnerDebugEnabled } from './debug.js';\n\nexport class StatusLineManager {\n private intervalId?: NodeJS.Timeout;\n private alignTimeoutId?: NodeJS.Timeout;\n private activeCount: number = 0;\n private lastLine: string = \"\";\n private isEnabledCached: boolean | null = null;\n\n constructor() {\n // Don't cache debug state here - defer until first use\n // This allows env vars to be set after module load\n }\n\n /**\n * Check if status line is enabled (only enabled when not in debug mode)\n */\n private get isEnabled(): boolean {\n // Cache on first call, after env vars have been set\n if (this.isEnabledCached === null) {\n this.isEnabledCached = !isRunnerDebugEnabled();\n }\n return this.isEnabledCached;\n }\n\n /**\n * Updates the count of active conversations\n */\n updateActiveCount(count: number): void {\n const previousCount = this.activeCount;\n const wasZero = previousCount === 0;\n const isZero = count === 0;\n const countChanged = count !== previousCount;\n this.activeCount = count;\n\n // Start interval when transitioning from 0 to active\n if (wasZero && !isZero) {\n this.startInterval();\n }\n // Stop interval when transitioning to 0\n else if (!wasZero && isZero) {\n this.stopInterval();\n }\n\n if (countChanged) {\n this.showStatus();\n }\n }\n\n /**\n * Starts the status line interval\n */\n private startInterval(): void {\n if (!this.isEnabled || this.intervalId || this.alignTimeoutId) return;\n\n // Update every minute on the minute\n const now = new Date();\n const msUntilNextMinute = (60 - now.getSeconds()) * 1000 - now.getMilliseconds();\n\n // First timeout to align with the minute\n this.alignTimeoutId = setTimeout(() => {\n this.alignTimeoutId = undefined;\n this.showStatus();\n \n // Then set up regular interval\n this.intervalId = setInterval(() => {\n this.showStatus();\n }, 60000); // Every 60 seconds\n }, msUntilNextMinute);\n }\n\n /**\n * Stops the status line interval\n */\n private stopInterval(): void {\n if (this.alignTimeoutId) {\n clearTimeout(this.alignTimeoutId);\n this.alignTimeoutId = undefined;\n }\n if (this.intervalId) {\n clearInterval(this.intervalId);\n this.intervalId = undefined;\n }\n }\n\n /**\n * Shows the current status\n */\n private showStatus(): void {\n if (!this.isEnabled) return;\n\n const now = new Date();\n const timeStr = now.toTimeString().slice(0, 5); // HH:MM format\n\n if (this.activeCount === 0) {\n if (this.lastLine) {\n process.stdout.write('\\r' + ' '.repeat(this.lastLine.length) + '\\r');\n this.lastLine = \"\";\n }\n return;\n }\n\n let newLine: string;\n if (this.activeCount === 1) {\n newLine = `${timeStr} 1 active agent process`;\n } else {\n newLine = `${timeStr} ${this.activeCount} active agent processes`;\n }\n\n // If this is the first status line, position it\n if (!this.lastLine) {\n // Move to start of line and save cursor position\n process.stdout.write('\\r');\n } else {\n // Clear the current line\n process.stdout.write('\\r' + ' '.repeat(this.lastLine.length) + '\\r');\n }\n \n // Write the new status without newline\n process.stdout.write(newLine);\n this.lastLine = newLine;\n }\n\n /**\n * Cleans up the status line manager\n */\n dispose(): void {\n this.stopInterval();\n // Add a newline to ensure next output starts on a new line\n if (this.lastLine) {\n process.stdout.write('\\n');\n }\n }\n}\n\n// Singleton instance\nexport const statusLineManager = new StatusLineManager();\n","import { createLogger } from './logger.js';\nimport { isDebugEnabledFor } from './debug.js';\nimport type { JsonRpcMessage, RunnerMessage } from '../types/index.js';\n\n// Limit used when trimming long content fields\nexport const MESSAGE_LOG_SEGMENT = 500;\n\n// Shared logger + flag for message flow tracing\nexport const messageFlowLogger = createLogger(\"MessageFlow\", \"messages\");\nexport const messagesDebugEnabled = (): boolean => isDebugEnabledFor(\"messages\");\n\n/**\n * Trim a long string by keeping the first and last segments.\n */\nexport function trimStringForLog(value: string, segment: number = MESSAGE_LOG_SEGMENT): string {\n if (value.length <= segment * 2) return value;\n const omitted = value.length - segment * 2;\n return `${value.slice(0, segment)}...[${omitted} chars trimmed]...${value.slice(-segment)}`;\n}\n\n/**\n * Recursively clone a payload for logging, trimming long string values when requested.\n */\nexport function clonePayloadForLog<T>(payload: T, options: { trimLongStrings: boolean }): T {\n if (!options.trimLongStrings) {\n return payload;\n }\n\n const clone = (value: any): any => {\n if (typeof value === \"string\") {\n return trimStringForLog(value);\n }\n\n if (Array.isArray(value)) {\n return value.map(clone);\n }\n\n if (value && typeof value === \"object\") {\n const result: Record<string, any> = {};\n for (const [key, val] of Object.entries(value)) {\n result[key] = clone(val);\n }\n return result;\n }\n\n return value;\n };\n\n return clone(payload) as T;\n}\n\n/**\n * Prepare a concise log entry for an incoming RunnerMessage.\n */\nexport function buildIncomingMessageLog(message: RunnerMessage): Record<string, unknown> {\n return {\n direction: message.direction,\n messageId: message.id,\n method: message.payload?.method,\n taskId: message.taskId,\n conversationId:\n message.conversationId || message.payload?.params?.conversationId || null,\n workspaceId: message.workspaceId,\n payload: clonePayloadForLog(message.payload, { trimLongStrings: true }),\n };\n}\n\n/**\n * Prepare a verbose log entry for an outgoing JsonRpcMessage.\n */\nexport function buildOutgoingMessageLog(message: JsonRpcMessage): Record<string, unknown> {\n return {\n direction: \"to_orchestrator\",\n method: message.method,\n id: message.id,\n params: message.params,\n result: message.result,\n error: message.error,\n };\n}\n","/**\n * MessageHandler - Processes incoming JSONRPC messages from SSE events\n */\n\nimport { IRunnerApp } from '../types/runner-interface.js';\nimport {\n RunnerMessage,\n MethodHandler,\n ConversationContext,\n ConversationConfig,\n} from '../types/index.js';\nimport { SSEClient, SSEEvent } from '../services/SSEClient.js';\nimport { RunnerAPIClient } from '../services/RunnerAPIClient.js';\nimport { statusLineManager } from '../utils/status-line.js';\nimport { createLogger } from '../utils/logger.js';\nimport { isDebugEnabledFor } from '../utils/debug.js';\nimport {\n buildIncomingMessageLog,\n messageFlowLogger,\n messagesDebugEnabled,\n} from '../utils/message-log.js';\nimport fs from \"fs/promises\";\nimport path from \"path\";\n\nconst logger = createLogger(\"MessageHandler\", \"rpc\");\nconst sseLogger = createLogger(\"MessageHandler:SSE\", \"sse\");\n// Use getters so debug state is checked at call time, not module load time\nconst rpcDebugEnabled = () => isDebugEnabledFor(\"rpc\");\nconst sseDebugEnabled = () => isDebugEnabledFor(\"sse\");\nconst isSubPath = (base?: string, candidate?: string) => {\n if (!base || !candidate) return false;\n const normBase = path.resolve(base);\n const normCandidate = path.resolve(candidate);\n return (\n normCandidate === normBase ||\n normCandidate.startsWith(normBase.endsWith(path.sep) ? normBase : normBase + path.sep)\n );\n};\n\nexport class MessageHandler {\n private methodHandlers: Map<string, MethodHandler>;\n private runner: IRunnerApp;\n /** Map of message ID to message timestamp for deduplication */\n private processedMessages: Map<string, Date> = new Map();\n /**\n * Queue SSE events to provide backpressure.\n * Without this, async handler promises can accumulate unbounded under load.\n */\n private sseEventQueue: SSEEvent[] = [];\n private isDrainingSseQueue: boolean = false;\n private isRecoveringSse: boolean = false;\n private readonly maxSseQueueLength: number;\n private sseClient: SSEClient | null = null;\n private apiClient: RunnerAPIClient;\n private isProcessing: boolean = false;\n\n constructor(runner: IRunnerApp) {\n this.runner = runner;\n this.methodHandlers = new Map();\n this.apiClient = new RunnerAPIClient(runner.config_);\n this.maxSseQueueLength = this.readMaxSseQueueLength();\n this.registerHandlers();\n }\n\n async startProcessing(): Promise<void> {\n logger.info(\"Starting message processing with SSE\", {\n runnerId: this.runner.getRunnerId(),\n });\n\n if (this.isProcessing) {\n logger.warn(\"Message processing already started\");\n return;\n }\n\n this.isProcessing = true;\n\n // Update API client with runner ID if available\n const runnerId = this.runner.getRunnerId();\n if (runnerId) {\n this.apiClient.setRunnerId(runnerId);\n }\n\n // Catch up on missed messages first\n await this.catchUpMissedMessages();\n\n // Start SSE connection\n await this.connectSSE();\n }\n\n async stopProcessing(): Promise<void> {\n logger.info(\"Stopping message processing\");\n\n this.isProcessing = false;\n\n // Stop SSE client\n if (this.sseClient) {\n this.sseClient.stop();\n this.sseClient = null;\n }\n\n // Clear queued events and stop drain loop\n this.sseEventQueue.length = 0;\n this.isDrainingSseQueue = false;\n this.isRecoveringSse = false;\n\n // NOTE: Do NOT clear processedMessages here. Keeping the map across\n // reconnections provides dedup protection in case the high watermark\n // wasn't persisted before disconnect. The pruneProcessedMessages()\n // method handles cleanup based on the acknowledged watermark.\n }\n\n /**\n * Prune processed messages older than the given watermark.\n * Messages at or before the watermark are filtered server-side,\n * so we don't need to track them for deduplication anymore.\n */\n private pruneProcessedMessages(watermark: Date): void {\n const beforeSize = this.processedMessages.size;\n for (const [messageId, timestamp] of this.processedMessages) {\n if (timestamp <= watermark) {\n this.processedMessages.delete(messageId);\n }\n }\n const pruned = beforeSize - this.processedMessages.size;\n if (pruned > 0 && rpcDebugEnabled()) {\n logger.debug(\"Pruned processed messages\", {\n pruned,\n remaining: this.processedMessages.size,\n watermark: watermark.toISOString(),\n });\n }\n }\n\n /**\n * Catch up on missed messages since lastProcessedAt\n */\n private async catchUpMissedMessages(): Promise<void> {\n const lastProcessedAt = this.runner.getLastProcessedAt();\n\n if (!lastProcessedAt) {\n logger.debug(\"No lastProcessedAt timestamp, skipping catch-up\");\n return;\n }\n\n logger.info(\"Catching up on messages\", {\n since: lastProcessedAt.toISOString(),\n });\n\n try {\n const messages = await this.apiClient.fetchMissedMessages({\n since: lastProcessedAt,\n limit: 1000,\n });\n\n if (messages.length > 0) {\n logger.info(\"Processing missed messages\", { count: messages.length });\n\n // Process messages in order\n for (const message of messages) {\n await this.processMessage(message);\n }\n }\n } catch (error) {\n logger.error(\"Failed to catch up on missed messages:\", error);\n // Continue anyway - SSE connection might still work\n }\n }\n\n /**\n * Connect to SSE endpoint\n */\n private async connectSSE(): Promise<void> {\n const runnerId = this.runner.getRunnerId();\n if (!runnerId) {\n throw new Error(\"Cannot connect to SSE without runner ID\");\n }\n\n const token = process.env[\"NORTHFLARE_RUNNER_TOKEN\"];\n if (!token) {\n throw new Error(\"Missing NORTHFLARE_RUNNER_TOKEN\");\n }\n\n logger.info(\"Connecting to SSE endpoint\", { runnerId });\n\n this.sseClient = new SSEClient({\n url: `${this.runner.config_.orchestratorUrl}/api/runner-events`,\n runnerId,\n token,\n // Important: onMessage must be sync to avoid accumulating unawaited promises.\n // Queue events and process them sequentially to provide backpressure.\n onMessage: this.enqueueSseEvent.bind(this),\n onError: (error) => {\n logger.error(\"SSE connection error:\", error);\n },\n onConnect: () => {\n sseLogger.info(\"SSE connection established\", { runnerId });\n },\n onDisconnect: () => {\n sseLogger.info(\"SSE connection closed\", { runnerId });\n },\n reconnectInterval: 1000,\n maxReconnectInterval: 30000,\n reconnectMultiplier: 2,\n // Provide callback to get current lastProcessedAt for reconnection\n getLastProcessedAt: () => this.runner.getLastProcessedAt()?.toISOString(),\n });\n\n // Connect with lastProcessedAt for server-side filtering\n const lastProcessedAt = this.runner.getLastProcessedAt();\n await this.sseClient.connect(lastProcessedAt?.toISOString());\n }\n\n private readMaxSseQueueLength(): number {\n const raw = process.env[\"NORTHFLARE_RUNNER_SSE_QUEUE_MAX\"];\n if (!raw) return 5000;\n const parsed = Number(raw);\n if (!Number.isFinite(parsed) || parsed <= 0) return 5000;\n return Math.floor(parsed);\n }\n\n private enqueueSseEvent(event: SSEEvent): void {\n if (!this.isProcessing) return;\n\n this.sseEventQueue.push(event);\n\n if (this.sseEventQueue.length > this.maxSseQueueLength) {\n // Apply backpressure by reconnecting and catching up from lastProcessedAt.\n // We intentionally clear the queue: unacknowledged messages will be\n // returned by catchUpMissedMessages() because lastProcessedAt hasn't advanced.\n sseLogger.warn(\"SSE event queue overflow; reconnecting to catch up\", {\n queued: this.sseEventQueue.length,\n max: this.maxSseQueueLength,\n lastProcessedAt: this.runner.getLastProcessedAt()?.toISOString() || \"null\",\n });\n void this.recoverSseFromBackpressure();\n return;\n }\n\n if (!this.isDrainingSseQueue) {\n void this.drainSseQueue();\n }\n }\n\n private async recoverSseFromBackpressure(): Promise<void> {\n if (this.isRecoveringSse) return;\n this.isRecoveringSse = true;\n\n try {\n // Stop current SSE connection if any\n if (this.sseClient) {\n this.sseClient.stop();\n this.sseClient = null;\n }\n\n // Clear queue to free memory immediately\n this.sseEventQueue.length = 0;\n\n // Catch up via REST, then reconnect SSE\n await this.catchUpMissedMessages();\n if (this.isProcessing) {\n await this.connectSSE();\n }\n } catch (error) {\n sseLogger.error(\"Failed to recover SSE after backpressure\", error);\n } finally {\n this.isRecoveringSse = false;\n }\n }\n\n private async drainSseQueue(): Promise<void> {\n if (this.isDrainingSseQueue) return;\n this.isDrainingSseQueue = true;\n\n try {\n while (this.isProcessing && this.sseEventQueue.length > 0) {\n const next = this.sseEventQueue.shift();\n if (!next) break;\n await this.handleSSEEvent(next);\n }\n } catch (error) {\n sseLogger.error(\"SSE queue drain failed\", error);\n } finally {\n this.isDrainingSseQueue = false;\n }\n }\n\n /**\n * Handle SSE event\n */\n private async handleSSEEvent(event: SSEEvent): Promise<void> {\n if (event.type === \"runner.message\") {\n const message = event.data as RunnerMessage;\n\n if (sseDebugEnabled()) {\n sseLogger.debug(\"Received SSE event\", {\n eventId: event.id,\n type: event.type,\n messageId: message?.id,\n method: message?.payload?.method,\n createdAt: message?.createdAt,\n });\n }\n\n try {\n // Process the message\n await this.processMessage(message);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(\"Failed to process runner.message:\", msg);\n // Do not crash the runner on a single bad message\n return;\n }\n } else if (event.type === \"connection.established\") {\n sseLogger.debug(\"SSE connection established\", event.data);\n } else if (event.type === \"runnerRepo.created\" || event.type === \"runnerRepo.updated\") {\n await this.handleRunnerRepoUpsert(event.data);\n } else if (event.type === \"runnerRepo.deleted\") {\n await this.handleRunnerRepoDeleted(event.data);\n } else {\n sseLogger.debug(`Received event type: ${event.type}`, event.data);\n }\n }\n\n private async processMessage(message: RunnerMessage): Promise<void> {\n if (rpcDebugEnabled()) {\n logger.debug(\"processMessage called\", {\n messageId: message.id,\n method: message.payload?.method,\n direction: message.direction,\n createdAt: message.createdAt,\n });\n }\n\n // Check for version update signal (do this early, before any filtering)\n if (message.expectedRunnerVersion) {\n await this.runner.checkForUpdate(message.expectedRunnerVersion);\n }\n\n // Skip if already processed\n if (this.processedMessages.has(message.id)) {\n return;\n }\n\n if (messagesDebugEnabled()) {\n messageFlowLogger.debug(\n \"[incoming] orchestrator -> runner\",\n buildIncomingMessageLog(message)\n );\n }\n\n // Check if we should process this message based on ownership\n if (!this.shouldProcessMessage(message)) {\n return;\n }\n\n const { method, params } = message.payload;\n\n if (!method) {\n await this.sendError(message, \"Missing method in message payload\");\n return;\n }\n\n const handler = this.methodHandlers.get(method);\n\n if (!handler) {\n await this.sendError(message, `Unknown method: ${method}`);\n return;\n }\n\n if (rpcDebugEnabled()) {\n logger.debug(\"Processing message\", {\n messageId: message.id,\n method: method,\n taskId: message.taskId,\n isActionMessage: this.isActionMessage(message),\n });\n }\n\n try {\n await handler(params, message);\n await this.markProcessed(message);\n\n // Acknowledge ALL messages to update lastProcessedAt\n await this.acknowledgeMessage(message);\n\n if (rpcDebugEnabled()) {\n logger.debug(\"Message acknowledged\", {\n messageId: message.id,\n method: method,\n timestamp: message.createdAt,\n wasActionMessage: this.isActionMessage(message),\n });\n }\n } catch (error) {\n if (rpcDebugEnabled()) {\n logger.debug(\"Message processing error\", {\n messageId: message.id,\n method: method,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n await this.handleError(message, error);\n }\n }\n\n private async handleRunnerRepoUpsert(eventData: any): Promise<void> {\n const runnerExternalId = this.runner.getRunnerId();\n if (!runnerExternalId) return;\n\n const targetRunnerExternalId = eventData?.runner?.id;\n if (targetRunnerExternalId && targetRunnerExternalId !== runnerExternalId) {\n return;\n }\n\n const runnerType = eventData?.runner?.type || \"local\";\n if (runnerType !== \"local\") return;\n\n const runnerPath = eventData?.runnerPath;\n const repoName = eventData?.name;\n const repoUuid = eventData?.uuid;\n const external = eventData?.external === true;\n if (!runnerPath || !repoName || !repoUuid) return;\n\n const workspacePath = (this.runner as any).getWorkspacePath?.();\n const pathAllowed =\n external || (workspacePath ? isSubPath(workspacePath, runnerPath) : true);\n\n if (!pathAllowed) {\n logger.warn(\n `Ignoring runnerRepo upsert outside workspace from SSE: ${runnerPath}`\n );\n return;\n }\n\n try {\n await fs.mkdir(runnerPath, { recursive: true });\n logger.info(`Ensured local workspace directory exists at ${runnerPath}`);\n } catch (error) {\n logger.error(\"Failed to create workspace directory\", error);\n }\n\n const repos = Array.isArray(this.runner.config_.runnerRepos)\n ? [...(this.runner.config_.runnerRepos as any[])]\n : [];\n\n const existingIndex = repos.findIndex(\n (r: any) =>\n r.uuid === repoUuid || r.path === runnerPath || r.name === repoName\n );\n\n const updatedEntry = {\n uuid: repoUuid,\n name: repoName,\n path: runnerPath,\n external,\n };\n\n if (existingIndex >= 0) {\n repos[existingIndex] = updatedEntry;\n } else {\n repos.push(updatedEntry);\n }\n\n // Persist to runner cache if available\n if (typeof (this.runner as any).replaceRunnerRepos === \"function\") {\n await (this.runner as any).replaceRunnerRepos(repos);\n } else {\n this.runner.config_.runnerRepos = repos as any;\n }\n\n logger.info(`Updated in-memory runnerRepo ${repoName} from SSE event`);\n }\n\n private async handleRunnerRepoDeleted(eventData: any): Promise<void> {\n const runnerExternalId = this.runner.getRunnerId();\n if (!runnerExternalId) return;\n\n const targetRunnerExternalId = eventData?.runner?.id;\n if (targetRunnerExternalId && targetRunnerExternalId !== runnerExternalId) {\n return;\n }\n\n const runnerType = eventData?.runner?.type || \"local\";\n if (runnerType !== \"local\") return;\n\n const repoUuid = eventData?.uuid;\n const repoName = eventData?.name;\n if (!repoUuid && !repoName) return;\n\n const repos = Array.isArray(this.runner.config_.runnerRepos)\n ? [...(this.runner.config_.runnerRepos as any[])]\n : [];\n\n const filtered = repos.filter(\n (repo: any) =>\n (repoUuid ? repo.uuid !== repoUuid : true) &&\n (repoName ? repo.name !== repoName : true)\n );\n\n if (filtered.length === repos.length) {\n return;\n }\n\n if (typeof (this.runner as any).replaceRunnerRepos === \"function\") {\n await (this.runner as any).replaceRunnerRepos(filtered);\n } else {\n this.runner.config_.runnerRepos = filtered as any;\n }\n logger.info(\n `Removed runnerRepo ${repoName || repoUuid} from in-memory state after deletion event`\n );\n }\n\n private shouldProcessMessage(message: RunnerMessage): boolean {\n const decision = (() => {\n // Always process our own responses going to orchestrator\n if (message.direction === \"to_orchestrator\") {\n return { shouldProcess: true, reason: \"own response to orchestrator\" };\n }\n\n // Always process UID change messages BEFORE checking timestamp\n // This is critical because UID changes can update lastProcessedAt itself\n if (message.payload?.method === \"runner.uid.changed\") {\n return { shouldProcess: true, reason: \"UID change message\" };\n }\n\n // Filter by lastProcessedAt (after checking for UID change messages)\n const lastProcessedAt = this.runner.getLastProcessedAt();\n if (lastProcessedAt && message.createdAt) {\n const messageTime = new Date(message.createdAt);\n if (messageTime <= lastProcessedAt) {\n return {\n shouldProcess: false,\n reason: \"message before lastProcessedAt\",\n };\n }\n }\n\n // If we're not the active runner\n if (!this.runner.getIsActiveRunner()) {\n // Only process if it's for a pre-handoff conversation by conversationId\n const cid =\n message.conversationId || message.payload?.params?.conversationId;\n if (cid && this.runner.getPreHandoffConversations().has(cid)) {\n return {\n shouldProcess: true,\n reason: \"pre-handoff conversation (by conversationId)\",\n };\n }\n return { shouldProcess: false, reason: \"not active runner\" };\n }\n\n // We're active and message is after lastProcessedAt\n return {\n shouldProcess: true,\n reason: \"active runner, message after watermark\",\n };\n })();\n\n if (rpcDebugEnabled()) {\n logger.debug(\"Message processing decision\", {\n messageId: message.id,\n method: message.payload?.method,\n shouldProcess: decision.shouldProcess,\n reason: decision.reason,\n runnerUid: this.runner.getRunnerUid(),\n isActiveRunner: this.runner.getIsActiveRunner(),\n lastProcessedAt:\n this.runner.getLastProcessedAt()?.toISOString() || \"null\",\n messageCreatedAt: message.createdAt,\n });\n }\n\n return decision.shouldProcess;\n }\n\n private isActionMessage(message: RunnerMessage): boolean {\n const actionMethods = [\n \"conversation.start\",\n \"conversation.stop\",\n \"conversation.resume\",\n \"conversation.config\",\n \"conversation.summary\",\n \"message.user\",\n ];\n return actionMethods.includes(message.payload?.method || \"\");\n }\n\n private async acknowledgeMessage(message: RunnerMessage): Promise<void> {\n const runnerId = this.runner.getRunnerId();\n if (rpcDebugEnabled()) {\n logger.debug(\"Sending message.acknowledge\", {\n runnerId,\n messageTimestamp: message.createdAt,\n messageId: message.id,\n method: message.payload?.method,\n });\n }\n\n try {\n await this.apiClient.acknowledgeMessage(message.createdAt);\n\n // Update local lastProcessedAt\n const newWatermark = new Date(message.createdAt);\n await this.runner.updateLastProcessedAt!(newWatermark);\n\n // Prune old entries from processedMessages map to prevent unbounded growth.\n // Messages at or before the watermark are filtered server-side, so we\n // don't need to track them for deduplication anymore.\n this.pruneProcessedMessages(newWatermark);\n\n if (rpcDebugEnabled()) {\n logger.debug(\"message.acknowledge sent\", {\n runnerId,\n messageId: message.id,\n });\n }\n } catch (error) {\n logger.error(\"Failed to acknowledge message:\", error);\n // Continue processing even if acknowledgment fails\n }\n }\n\n private async markProcessed(message: RunnerMessage): Promise<void> {\n // Track processed messages with their timestamp for later pruning\n const timestamp = message.createdAt ? new Date(message.createdAt) : new Date();\n this.processedMessages.set(message.id, timestamp);\n this.pruneProcessedMessagesFailsafe();\n }\n\n /**\n * Failsafe pruning to prevent unbounded growth if acknowledgements fail\n * and lastProcessedAt can't advance (so watermark-based pruning can't run).\n */\n private pruneProcessedMessagesFailsafe(): void {\n const MAX_ENTRIES = 20_000;\n const MAX_AGE_MS = 2 * 60 * 60 * 1000; // 2 hours\n\n const now = Date.now();\n const cutoff = now - MAX_AGE_MS;\n\n // Fast path: nothing to do\n if (this.processedMessages.size <= MAX_ENTRIES) {\n // Still prune by age if we can do it cheaply from the head\n const first = this.processedMessages.entries().next().value as\n | [string, Date]\n | undefined;\n if (!first) return;\n if (first[1].getTime() >= cutoff) return;\n }\n\n // Prune oldest entries by age first (Map preserves insertion order)\n while (this.processedMessages.size > 0) {\n const first = this.processedMessages.entries().next().value as\n | [string, Date]\n | undefined;\n if (!first) break;\n const [, ts] = first;\n if (ts.getTime() >= cutoff) break;\n this.processedMessages.delete(first[0]);\n }\n\n // Enforce max size (delete oldest until within bound)\n while (this.processedMessages.size > MAX_ENTRIES) {\n const firstKey = this.processedMessages.keys().next().value as\n | string\n | undefined;\n if (!firstKey) break;\n this.processedMessages.delete(firstKey);\n }\n }\n\n private async sendError(\n message: RunnerMessage,\n errorMessage: string\n ): Promise<void> {\n // Send error report with conversation object info if available\n const conversationObjectType =\n message.conversationObjectType || (message.taskId ? \"Task\" : undefined);\n const conversationObjectId = message.conversationObjectId || message.taskId;\n\n if (!conversationObjectId) {\n logger.warn(\"Cannot send error report - missing conversationObjectId\", {\n messageId: message.id,\n method: message.payload?.method,\n error: errorMessage,\n runnerId: message.runnerId,\n });\n return;\n }\n\n await this.runner.notify(\"error.report\", {\n conversationObjectType,\n conversationObjectId,\n messageId: message.id,\n errorType: \"method_error\",\n message: errorMessage,\n details: {\n originalMessage: message,\n timestamp: new Date(),\n },\n });\n }\n\n private async handleError(message: RunnerMessage, error: any): Promise<void> {\n const errorMessage = error instanceof Error ? error.message : String(error);\n const errorStack = error instanceof Error ? error.stack : undefined;\n\n // Send error report with conversation object info if available\n const conversationObjectType =\n message.conversationObjectType || (message.taskId ? \"Task\" : undefined);\n const conversationObjectId = message.conversationObjectId || message.taskId;\n\n if (!conversationObjectId) {\n logger.warn(\n \"Cannot send processing error report - missing conversationObjectId\",\n {\n messageId: message.id,\n method: message.payload?.method,\n error: errorMessage,\n stack: errorStack,\n runnerId: message.runnerId,\n }\n );\n return;\n }\n\n await this.runner.notify(\"error.report\", {\n conversationObjectType,\n conversationObjectId,\n messageId: message.id,\n errorType: \"processing_error\",\n message: errorMessage,\n details: {\n stack: errorStack,\n originalMessage: message,\n timestamp: new Date(),\n },\n });\n }\n\n private registerHandlers(): void {\n logger.info(\"Registering message handlers\");\n\n this.methodHandlers = new Map([\n [\"conversation.start\", this.handleConversationStart.bind(this)],\n [\"conversation.stop\", this.handleConversationStop.bind(this)],\n [\"conversation.resume\", this.handleConversationResume.bind(this)],\n [\"conversation.config\", this.handleConversationConfig.bind(this)],\n [\"conversation.summary\", this.handleConversationSummary.bind(this)],\n [\"message.user\", this.handleUserMessage.bind(this)],\n [\"runner.uid.changed\", this.handleUidChanged.bind(this)],\n [\"git.operation\", this.handleGitOperation.bind(this)],\n [\"git.cleanup\", this.handleGitCleanup.bind(this)],\n ]);\n }\n\n // All the handler methods remain the same as in the original file\n // Just copy them from the original message-handler.ts starting from line 386\n\n private async handleConversationStart(\n params: any,\n message: RunnerMessage\n ): Promise<void> {\n const {\n conversationObjectType = message.conversationObjectType || \"Task\",\n conversationObjectId = message.conversationObjectId ||\n params.conversation?.objectId,\n config,\n initialMessages,\n conversation,\n } = params;\n\n // Validate required parameters\n if (!config) {\n throw new Error(\"Missing required parameter: config\");\n }\n\n // Require a conversation object\n const conversationData = conversation;\n if (!conversationData) {\n throw new Error(\n \"Missing required parameter: conversation object must be provided\"\n );\n }\n\n const finalObjectType =\n conversationObjectType || conversationData.objectType;\n const finalObjectId = conversationObjectId || conversationData.objectId;\n if (!finalObjectId) {\n throw new Error(\"Missing conversationObjectId\");\n }\n\n if (rpcDebugEnabled()) {\n // Debug log the config\n logger.debug(\"conversation.start config\", {\n conversationObjectId,\n hasConfig: !!config,\n hasRepository: !!config?.repository,\n repositoryType: config?.repository?.type,\n repositoryUrl: config?.repository?.url,\n workspaceId: config?.workspaceId,\n fullConfig: JSON.stringify(config, null, 2),\n });\n\n logger.debug(\"Received conversation instructions\", {\n conversationId: conversationData.id,\n hasWorkspaceInstructions: !!conversationData.workspaceInstructions,\n workspaceInstructionsLength:\n conversationData.workspaceInstructions?.length ?? 0,\n workspaceInstructionsPreview:\n conversationData.workspaceInstructions?.slice(0, 100),\n hasGlobalInstructions: !!conversationData.globalInstructions,\n globalInstructionsLength: conversationData.globalInstructions?.length ?? 0,\n });\n }\n\n // Check if conversation is already active (prevent duplicate starts on catch-up)\n const conversationId = conversationData.id;\n if (this.runner.activeConversations_.has(conversationId)) {\n logger.info(\"Conversation already active, skipping duplicate start\", {\n conversationId,\n });\n return;\n }\n\n // Check if this conversation was recently completed (prevent restart on catch-up)\n if (this.runner.wasConversationCompleted(conversationId)) {\n logger.info(\n \"Conversation already completed recently, skipping restart\",\n { conversationId }\n );\n return;\n }\n\n const provider = this.resolveAgentProvider(conversationData, config);\n const manager = this.getManagerForProvider(provider);\n\n // Start the conversation with the provided/loaded conversation details\n // For CodexManager (openai) we pass the provider to distinguish\n if (provider === \"openai\") {\n await (manager as any).startConversation(\n finalObjectType,\n finalObjectId,\n config,\n initialMessages || [],\n conversationData,\n provider\n );\n } else {\n await manager.startConversation(\n finalObjectType,\n finalObjectId,\n config,\n initialMessages || [],\n conversationData,\n provider as any\n );\n }\n\n // Update status line\n statusLineManager.updateActiveCount(this.runner.activeConversations_.size);\n }\n\n private async handleConversationStop(\n params: any,\n message: RunnerMessage\n ): Promise<void> {\n // Require conversationId (present at message level); do not fall back to agentSessionId/taskId\n const { conversationId = message.conversationId, reason } = params;\n\n if (rpcDebugEnabled()) {\n logger.debug(\"handleConversationStop invoked\", {\n conversationId,\n messageConversationId: message.conversationId,\n agentSessionId: params?.agentSessionId,\n taskId: params?.taskId,\n params: JSON.stringify(params),\n activeConversations: this.runner.activeConversations_.size,\n conversationIds: Array.from(this.runner.activeConversations_.keys()),\n });\n }\n\n // Lookup strictly by conversationId\n let context: ConversationContext | undefined;\n let targetConversationId: string | undefined;\n if (conversationId) {\n context = this.runner.getConversationContext(conversationId);\n targetConversationId = conversationId;\n }\n\n if (rpcDebugEnabled()) {\n logger.debug(\"handleConversationStop lookup\", {\n contextFound: !!context,\n targetConversationId,\n contextTaskId: context?.taskId,\n contextAgentSessionId: context?.agentSessionId,\n });\n }\n\n // Check if we have any identifier to work with\n if (!conversationId) {\n throw new Error(\"Missing required parameter: conversationId\");\n }\n\n if (context && targetConversationId) {\n context.status = \"stopping\";\n const manager = this.getManagerForConversationContext(context);\n await manager.stopConversation(\n context.agentSessionId,\n context,\n false, // Not a runner shutdown\n reason // Pass the reason through\n );\n context.status = \"stopped\";\n this.runner.activeConversations_.delete(targetConversationId);\n\n // Update status line\n statusLineManager.updateActiveCount(\n this.runner.activeConversations_.size\n );\n } else {\n // No conversation found - this is expected as conversations may have already ended\n // or been cleaned up. Just log it and update status line.\n logger.info(\"Conversation stop requested but not found\", {\n conversationId,\n });\n\n // If we have a targetConversationId, ensure it's removed from tracking\n if (targetConversationId) {\n this.runner.activeConversations_.delete(targetConversationId);\n }\n\n statusLineManager.updateActiveCount(\n this.runner.activeConversations_.size\n );\n }\n }\n\n private async handleConversationResume(\n params: any,\n message: RunnerMessage\n ): Promise<void> {\n const {\n conversationId = message.conversationId,\n conversation: resumeConversation,\n config,\n message: resumeMessage,\n } = params;\n\n const cid = params.conversationId || conversationId;\n if (!cid) {\n throw new Error(\"Missing required parameter: conversationId\");\n }\n\n // Require conversation details\n const conversationData = resumeConversation;\n if (!conversationData) {\n throw new Error(\n \"Missing required parameter: conversation object must be provided\"\n );\n }\n\n const agentSessionId = conversationData.agentSessionId;\n if (!agentSessionId) {\n throw new Error(\"Cannot resume conversation without agentSessionId\");\n }\n\n const provider = this.resolveAgentProvider(conversationData, config);\n const manager = this.getManagerForProvider(provider);\n\n // For CodexManager (openai) we pass the provider to distinguish\n if (provider === \"openai\") {\n await (manager as any).resumeConversation(\n conversationData.objectType,\n conversationData.objectId,\n agentSessionId,\n config,\n conversationData,\n resumeMessage,\n provider\n );\n } else {\n await manager.resumeConversation(\n conversationData.objectType,\n conversationData.objectId,\n agentSessionId,\n config,\n conversationData,\n resumeMessage,\n provider as any\n );\n }\n }\n\n private async handleConversationConfig(\n params: any,\n message: RunnerMessage\n ): Promise<void> {\n const { conversationId, model, permissionsMode, config } = params;\n\n if (rpcDebugEnabled()) {\n logger.debug(\"handleConversationConfig invoked\", {\n conversationId,\n model,\n permissionsMode,\n hasConfig: !!config,\n });\n }\n\n // Find the active conversation by conversationId only\n let context: ConversationContext | undefined;\n if (conversationId) {\n context = this.runner.getConversationContext(conversationId);\n }\n\n if (!context) {\n throw new Error(\n `No active conversation found for conversationId: ${conversationId}`\n );\n }\n\n // Validate required parameters\n if (!model && !permissionsMode) {\n throw new Error(\n \"At least one of model or permissionsMode must be provided\"\n );\n }\n\n // Update the config with new values\n const newConfig = {\n ...context.config,\n ...(model && { model }),\n ...(permissionsMode && { permissionsMode }),\n ...config, // Allow full config overrides if provided\n };\n\n logger.info(\"Stopping conversation to apply new config\", {\n conversationId: context.conversationId,\n });\n\n // Stop the current conversation\n const manager = this.getManagerForConversationContext(context);\n\n await manager.stopConversation(\n context.agentSessionId,\n context,\n false // Not a runner shutdown, just updating config\n );\n\n // Remove from active conversations\n this.runner.activeConversations_.delete(context.conversationId);\n\n logger.info(\"Resuming conversation with updated config\", {\n conversationId: context.conversationId,\n });\n\n // Resume with new config\n // For CodexManager (openai) we pass the provider to distinguish\n const contextProvider = context.provider?.toLowerCase();\n if (contextProvider === \"openai\") {\n await (manager as any).resumeConversation(\n context.conversationObjectType,\n context.conversationObjectId,\n context.agentSessionId,\n newConfig,\n {\n id: context.conversationId,\n objectType: context.conversationObjectType,\n objectId: context.conversationObjectId,\n model: newConfig.model,\n globalInstructions: context.globalInstructions,\n workspaceInstructions: context.workspaceInstructions,\n permissionsMode: newConfig.permissionsMode,\n agentSessionId: context.agentSessionId,\n },\n \"<system-instructions>Configuration updated. Please continue with the new settings.</system-instructions>\",\n contextProvider as \"openai\"\n );\n } else {\n await manager.resumeConversation(\n context.conversationObjectType,\n context.conversationObjectId,\n context.agentSessionId,\n newConfig,\n {\n id: context.conversationId,\n objectType: context.conversationObjectType,\n objectId: context.conversationObjectId,\n model: newConfig.model,\n globalInstructions: context.globalInstructions,\n workspaceInstructions: context.workspaceInstructions,\n permissionsMode: newConfig.permissionsMode,\n agentSessionId: context.agentSessionId,\n },\n \"<system-instructions>Configuration updated. Please continue with the new settings.</system-instructions>\"\n );\n }\n\n // Update status line\n statusLineManager.updateActiveCount(this.runner.activeConversations_.size);\n\n logger.info(\"Conversation config updated\", {\n conversationId: context.conversationId,\n });\n }\n\n private async handleConversationSummary(\n params: any,\n _message: RunnerMessage\n ): Promise<void> {\n const { conversationId, summary } = params;\n\n if (!conversationId) {\n throw new Error(\"Missing required parameter: conversationId\");\n }\n\n // Allow null to mean \"no summary available yet\"\n if (summary != null && typeof summary !== \"string\") {\n throw new Error(\"Invalid parameter: summary must be a string or null\");\n }\n\n const normalized =\n typeof summary === \"string\" ? summary.replace(/\\s+/g, \" \").trim() : \"\";\n\n if (rpcDebugEnabled()) {\n logger.debug(\"handleConversationSummary invoked\", {\n conversationId,\n hasSummary: Boolean(normalized),\n summaryLength: normalized.length,\n });\n }\n\n this.runner.applyConversationSummary(conversationId, normalized || null);\n }\n\n private async handleUserMessage(\n params: any,\n message: RunnerMessage\n ): Promise<void> {\n const {\n conversationId,\n content,\n config,\n conversationObjectType = message.conversationObjectType || \"Task\",\n conversationObjectId = message.conversationObjectId,\n conversation,\n agentSessionId,\n } = params;\n\n // Validate required parameters\n if (!conversationId) {\n throw new Error(\"Missing required parameter: conversationId\");\n }\n\n if (!content) {\n throw new Error(\"Missing required parameter: content\");\n }\n\n let context = this.runner.getConversationContext(conversationId);\n let provider: \"openai\" | \"openrouter\" | \"claude\" | \"groq\";\n let manager;\n\n if (context) {\n provider = context.provider as typeof provider;\n if (!provider) {\n throw new Error(\n `Conversation context missing provider for conversationId ${conversationId}. Orchestrator must set providerType/agentProviderType or prefix the model when starting the conversation.`\n );\n }\n manager = this.getManagerForProvider(provider);\n } else {\n // Conversation is not active anymore (likely completed/cleaned up). We can\n // only restart it if the orchestrator provided full conversation details\n // and a resolvable provider.\n if (!conversation) {\n throw new Error(\n `No active conversation found for ${conversationId}, and no conversation details provided to restart it.`\n );\n }\n\n provider = this.resolveAgentProvider(conversation, config);\n manager = this.getManagerForProvider(provider);\n\n const targetObjectId =\n conversationObjectId ||\n conversation.conversationObjectId ||\n conversation.objectId;\n\n if (!targetObjectId) {\n throw new Error(\n `Missing conversationObjectId for ${conversationId}; cannot start conversation.`\n );\n }\n\n // Start a fresh conversation so the SDK process exists before streaming\n await (manager as any).startConversation(\n conversationObjectType,\n targetObjectId,\n config,\n [], // no initial messages here; this is a follow-up turn\n conversation,\n provider\n );\n\n context = this.runner.getConversationContext(conversationId);\n if (!context) {\n throw new Error(\n `Failed to start conversation for ${conversationId}; no context created.`\n );\n }\n }\n\n // For CodexManager (openai), pass the provider\n if (provider === \"openai\") {\n await (manager as any).sendUserMessage(\n conversationId,\n content,\n config,\n conversationObjectType,\n conversationObjectId,\n conversation,\n agentSessionId,\n provider\n );\n } else {\n await manager.sendUserMessage(\n conversationId,\n content,\n config,\n conversationObjectType,\n conversationObjectId,\n conversation,\n agentSessionId\n );\n }\n }\n\n private async handleUidChanged(\n params: any,\n _message: RunnerMessage\n ): Promise<void> {\n const { runnerUid, lastProcessedAt } = params;\n\n logger.info(\"Handling UID change notification\", {\n runnerUid,\n lastProcessedAt,\n });\n\n if (rpcDebugEnabled()) {\n logger.debug(\"UID change notification received\", {\n newUid: runnerUid,\n currentUid: this.runner.getRunnerUid(),\n newLastProcessedAt: lastProcessedAt,\n currentLastProcessedAt:\n this.runner.getLastProcessedAt()?.toISOString() || \"null\",\n wasActiveRunner: this.runner.getIsActiveRunner(),\n activeConversations: this.runner.activeConversations_.size,\n });\n }\n\n // Check if the UID matches ours FIRST, before checking timestamps\n // This ensures we activate even if we received the message during catch-up\n if (runnerUid === this.runner.getRunnerUid()) {\n // This is our UID - we're the active runner\n logger.info(\"Runner activated as primary\", {\n runnerUid,\n });\n this.runner.setIsActiveRunner(true);\n await this.runner.updateLastProcessedAt!(\n lastProcessedAt ? new Date(lastProcessedAt) : null\n );\n\n if (rpcDebugEnabled()) {\n logger.debug(\"Runner activated as primary\", {\n runnerUid: runnerUid,\n lastProcessedAt: lastProcessedAt,\n orchestratorUrl: this.runner.config_.orchestratorUrl,\n });\n }\n\n // Emit activation notification - wrap in try/catch to handle failures gracefully\n try {\n await this.runner.notify(\"runner.activate\", {\n runnerId: this.runner.getRunnerId(),\n runnerUid: runnerUid,\n });\n } catch (error) {\n logger.error(\"Failed to send activation notification\", error);\n if (rpcDebugEnabled()) {\n logger.debug(\"Activation notification failed\", {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n // Start processing messages from the lastProcessedAt point\n logger.info(\"Activation complete; setting message watermark\", {\n after: lastProcessedAt || \"beginning\",\n });\n } else {\n // Different UID - check if this is an old UID change that we should ignore\n const currentLastProcessedAt = this.runner.getLastProcessedAt();\n if (currentLastProcessedAt && lastProcessedAt) {\n const newTime = new Date(lastProcessedAt);\n if (newTime < currentLastProcessedAt) {\n logger.info(\"Ignoring old UID change\", {\n lastProcessedAt,\n currentLastProcessedAt: currentLastProcessedAt.toISOString(),\n });\n if (rpcDebugEnabled()) {\n logger.debug(\"Ignoring old UID change\", {\n newUid: runnerUid,\n newLastProcessedAt: lastProcessedAt,\n currentLastProcessedAt: currentLastProcessedAt.toISOString(),\n });\n }\n return;\n }\n }\n\n // Different UID - we're being replaced\n logger.info(\"Runner deactivated; replacement detected\", { runnerUid });\n this.runner.setIsActiveRunner(false);\n\n // Remember which conversations were active before handoff (by conversationId)\n for (const [conversationId, context] of this.runner\n .activeConversations_) {\n if (context.status === \"active\") {\n this.runner.getPreHandoffConversations().add(conversationId);\n }\n }\n\n if (rpcDebugEnabled()) {\n logger.debug(\"Runner deactivated - being replaced\", {\n newRunnerUid: runnerUid,\n ourUid: this.runner.getRunnerUid(),\n preHandoffConversations: Array.from(\n this.runner.getPreHandoffConversations()\n ),\n activeConversationsCount:\n this.runner.getPreHandoffConversations().size,\n });\n }\n\n logger.info(\"Runner replacement: completing active conversations\", {\n activeConversationCount: this.runner.getPreHandoffConversations().size,\n });\n\n // Emit deactivation notification - wrap in try/catch to handle failures gracefully\n try {\n await this.runner.notify(\"runner.deactivate\", {\n runnerId: this.runner.getRunnerId(),\n runnerUid: this.runner.getRunnerUid(),\n activeConversations: this.runner.getPreHandoffConversations().size,\n });\n } catch (error) {\n logger.error(\"Failed to send deactivation notification\", error);\n if (rpcDebugEnabled()) {\n logger.debug(\"Deactivation notification failed\", {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n }\n }\n\n private async handleGitOperation(\n params: any,\n message: RunnerMessage\n ): Promise<void> {\n const { taskId, operation, params: opParams } = params;\n\n if (!taskId || !operation) {\n throw new Error(\"Missing required parameters: taskId and operation\");\n }\n\n logger.info(\"Handling Git operation\", { operation, taskId });\n\n const repoManager = this.runner.repositoryManager_;\n\n try {\n switch (operation) {\n case \"stage\":\n await repoManager.stageAll(taskId);\n await this.sendGitStateUpdate(taskId);\n break;\n\n case \"commit\":\n if (!opParams?.message) {\n throw new Error(\"Commit message is required\");\n }\n const commitHash = await repoManager.commit(\n taskId,\n opParams.message,\n opParams.author\n );\n await this.recordGitOperation(taskId, \"commit\", \"succeeded\", {\n commitHash,\n });\n await this.sendGitStateUpdate(taskId);\n break;\n\n case \"push\":\n // TODO: Implement push operation\n logger.warn(\"Git push operation not yet implemented\", { taskId });\n break;\n\n case \"rebase\":\n if (!opParams?.targetBranch) {\n throw new Error(\"Target branch is required for rebase\");\n }\n const rebaseResult = await repoManager.rebaseTask(\n taskId,\n opParams.targetBranch\n );\n await this.recordGitOperation(\n taskId,\n \"rebase\",\n rebaseResult.success ? \"succeeded\" : \"failed\",\n rebaseResult\n );\n await this.sendGitStateUpdate(taskId);\n break;\n\n case \"merge\":\n if (!opParams?.targetBranch) {\n throw new Error(\"Target branch is required for merge\");\n }\n const mergeResult = await repoManager.mergeTask(\n taskId,\n opParams.targetBranch,\n opParams.mode\n );\n await this.recordGitOperation(\n taskId,\n \"merge\",\n mergeResult.success ? \"succeeded\" : \"failed\",\n mergeResult\n );\n await this.sendGitStateUpdate(taskId);\n break;\n\n default:\n throw new Error(`Unknown Git operation: ${operation}`);\n }\n } catch (error) {\n logger.error(`Git operation ${operation} failed`, {\n taskId,\n error,\n });\n await this.recordGitOperation(taskId, operation, \"failed\", {\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n private async handleGitCleanup(\n params: any,\n message: RunnerMessage\n ): Promise<void> {\n const { taskId, preserveBranch = false } = params;\n\n if (!taskId) {\n throw new Error(\"Missing required parameter: taskId\");\n }\n\n logger.info(\"Cleaning up Git worktree\", { taskId });\n\n const repoManager = this.runner.repositoryManager_;\n\n try {\n await repoManager.removeTaskWorktree(taskId, { preserveBranch });\n logger.info(\"Git worktree cleaned up\", { taskId, preserveBranch });\n } catch (error) {\n logger.error(`Failed to clean up worktree for task ${taskId}`, error);\n throw error;\n }\n }\n\n private async sendGitStateUpdate(taskId: string): Promise<void> {\n const repoManager = this.runner.repositoryManager_;\n const gitState = await repoManager.getTaskState(taskId);\n\n if (!gitState) {\n logger.warn(`No Git state found for task ${taskId}`);\n return;\n }\n\n // Send state update to orchestrator\n await this.runner.notify(\"git.state.update\", {\n taskId,\n state: {\n branch: gitState.branch,\n commit: gitState.lastCommit || \"\",\n isDirty: false, // TODO: Check actual dirty state\n ahead: 0, // TODO: Calculate ahead/behind\n behind: 0,\n },\n });\n }\n\n private async recordGitOperation(\n taskId: string,\n operation: string,\n status: string,\n details: any\n ): Promise<void> {\n // Send operation record to orchestrator\n await this.runner.notify(\"git.operation.record\", {\n taskId,\n operation,\n status,\n details,\n timestamp: new Date(),\n });\n }\n\n private resolveAgentProvider(\n conversation?: {\n providerType?: string;\n agentProviderType?: string;\n model?: string;\n },\n config?: ConversationConfig\n ): \"openai\" | \"openrouter\" | \"claude\" | \"groq\" {\n const model =\n conversation?.model ||\n (config as any)?.model ||\n (config as any)?.defaultModel ||\n \"\";\n const normalizedModel = model.toLowerCase();\n\n // 1) Trust explicit provider from orchestrator/config first\n const explicitProvider =\n conversation?.providerType ||\n conversation?.agentProviderType ||\n (config as any)?.providerType ||\n (config as any)?.agentProviderType;\n\n const normalizeProvider = (provider?: string | null) => {\n if (!provider || typeof provider !== \"string\") return null;\n const normalized = provider.toLowerCase();\n if (normalized === \"codex\") return \"openai\"; // codex alias for OpenAI\n if (normalized === \"openai\") return \"openai\";\n if (normalized === \"openrouter\") return \"openrouter\";\n if (normalized === \"groq\") return \"groq\";\n if (normalized === \"claude\") return \"claude\";\n return null;\n };\n\n const explicit = normalizeProvider(explicitProvider);\n if (explicit) {\n return explicit;\n }\n\n // 2) Fallback to model prefix hints (non-fragile)\n if (normalizedModel.startsWith(\"openrouter:\") || normalizedModel.startsWith(\"openrouter/\")) {\n return \"openrouter\";\n }\n if (normalizedModel.startsWith(\"groq:\") || normalizedModel.startsWith(\"groq/\")) {\n return \"groq\";\n }\n if (normalizedModel.startsWith(\"openai:\") || normalizedModel.startsWith(\"openai/\")) {\n return \"openai\";\n }\n if (normalizedModel.startsWith(\"claude:\") || normalizedModel.startsWith(\"claude/\")) {\n return \"claude\";\n }\n\n // 3) No explicit provider and no prefix – treat as configuration error\n throw new Error(\n \"Agent provider is required. Orchestrator must set providerType/agentProviderType or prefix the model (openai:/openrouter:/groq:/claude:).\"\n );\n }\n\n private getManagerForProvider(provider?: string) {\n const manager = this.resolveProviderManager(provider?.toLowerCase());\n if (manager) {\n return manager;\n }\n throw new Error(`Unknown agent provider: ${provider || \"<unset>\"}`);\n }\n\n private getManagerForConversationContext(context: ConversationContext) {\n const manager = this.resolveProviderManager(context.provider?.toLowerCase());\n if (manager) {\n return manager;\n }\n\n throw new Error(\n `Unknown or missing agent provider on conversation context: ${\n context.provider || \"<unset>\"\n }`\n );\n }\n\n private resolveProviderManager(provider?: string) {\n if (provider === \"openrouter\" || provider === \"groq\") {\n // OpenRouter now handled by Northflare Agent manager\n return this.runner.northflareAgentManager_;\n }\n if (provider === \"openai\" || provider === \"codex\") {\n return this.runner.codexManager_;\n }\n if (provider === \"claude\") {\n return this.runner.claudeManager_;\n }\n return null;\n }\n}\n","/**\n * ClaudeManager - Manages Claude conversations using SDK-native patterns\n *\n * This component handles stateful conversation lifecycle management, maintaining\n * persistent conversation instances indexed by taskId. Uses the SDK's native\n * capabilities including the builder pattern, native session management, and\n * built-in streaming instead of custom wrappers.\n *\n * Key improvements:\n * - Uses claude() builder pattern for simplified configuration\n * - Native session management with withSessionId()\n * - Direct AsyncGenerator streaming without custom wrappers\n * - SDK's onProcessComplete() for proper cleanup\n * - Simplified error handling while maintaining compatibility\n */\n\nimport { query as sdkQuery } from \"@anthropic-ai/claude-agent-sdk\";\nimport type { Conversation as ClaudeConversation } from \"@botanicastudios/claude-code-sdk-ts\";\n// Keep SDKMessage loosely typed to avoid tight coupling to SDK typings\ntype SDKMessage = any;\nimport { IRunnerApp } from '../types/runner-interface.js';\nimport { EnhancedRepositoryManager } from './enhanced-repository-manager.js';\nimport { ConversationContext, ConversationConfig, Message } from '../types/index.js';\nimport { statusLineManager } from '../utils/status-line.js';\nimport { createScopedConsole } from '../utils/console.js';\nimport { expandEnv } from '../utils/expand-env.js';\nimport { isDebugEnabledFor } from '../utils/debug.js';\nimport fs from \"fs/promises\";\nimport path from \"path\";\nimport { simpleGit } from \"simple-git\";\n\nconst console = createScopedConsole(\n isDebugEnabledFor(\"manager\") ? \"manager\" : \"sdk\"\n);\nimport jwt from \"jsonwebtoken\";\n\nexport class ClaudeManager {\n private runner: IRunnerApp;\n private repositoryManager: EnhancedRepositoryManager;\n\n constructor(\n runner: IRunnerApp,\n repositoryManager: EnhancedRepositoryManager\n ) {\n this.runner = runner;\n this.repositoryManager = repositoryManager;\n\n // Log debug mode status\n if (isDebugEnabledFor(\"sdk\")) {\n console.log(\n \"[ClaudeManager] DEBUG MODE ENABLED - Claude SDK will log verbose output\"\n );\n }\n\n // Note: MCP host configuration is passed from orchestrator\n // Runner does not define its own MCP tools\n this.setupInternalMcpServer();\n }\n\n private setupInternalMcpServer(): void {\n // Runner does not define its own MCP tools\n // All MCP tool configuration is passed from orchestrator in conversation config\n }\n\n async startConversation(\n conversationObjectType: \"Task\" | \"TaskPlan\" | \"ProjectStep\",\n conversationObjectId: string,\n config: ConversationConfig,\n initialMessages: Message[],\n conversationData?: {\n id: string;\n objectType: string;\n objectId: string;\n model: string;\n summary?: string | null;\n globalInstructions: string;\n workspaceInstructions: string;\n permissionsMode: string;\n agentSessionId: string;\n systemPrompt?: string;\n northflareSystemPrompt?: string;\n systemPromptMode?: \"append\" | \"replace\";\n }\n ): Promise<ConversationContext> {\n // Returns conversation context\n // Greenfield: conversationData.id is required as the authoritative DB conversation ID\n if (!conversationData?.id) {\n throw new Error(\n \"startConversation requires conversationData with a valid conversation.id\"\n );\n }\n // Use sessionId from config if resuming, or agentSessionId from conversationData if available\n const agentSessionId =\n config.sessionId || conversationData.agentSessionId || \"\";\n const conversationId = conversationData.id;\n const useWorktrees = config.useWorktrees !== false;\n const pendingSummary =\n this.runner.consumePendingConversationSummary(conversationId);\n const rawSummary =\n typeof conversationData.summary === \"string\"\n ? conversationData.summary\n : pendingSummary;\n const normalizedSummary =\n typeof rawSummary === \"string\"\n ? rawSummary.replace(/\\s+/g, \" \").trim()\n : null;\n\n const context: ConversationContext = {\n conversationId,\n agentSessionId, // Will be updated by onSessionId callback for new conversations\n conversationObjectType,\n conversationObjectId,\n taskId:\n conversationObjectType === \"Task\" ? conversationObjectId : undefined,\n workspaceId: config.workspaceId,\n status: \"starting\",\n config,\n startedAt: new Date(),\n lastActivityAt: new Date(),\n // Add conversation details if provided\n model: conversationData?.model || \"opus\",\n summary: normalizedSummary,\n globalInstructions: conversationData?.globalInstructions || \"\",\n workspaceInstructions: conversationData?.workspaceInstructions || \"\",\n permissionsMode: conversationData?.permissionsMode || \"all\",\n provider: \"claude\",\n metadata: {\n instructionsInjected: false,\n },\n };\n\n // Store with conversation.id as the key\n this.runner.activeConversations_.set(conversationId, context);\n console.log(`[ClaudeManager] Stored conversation context:`, {\n conversationId,\n agentSessionId: context.agentSessionId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n mapSize: this.runner.activeConversations_.size,\n allKeys: Array.from(this.runner.activeConversations_.keys()),\n });\n\n const workspaceId = config.workspaceId;\n\n // Checkout repository if specified\n let workspacePath: string;\n\n // Check if this is a local workspace by looking for runnerRepoPath in config\n if (config.runnerRepoPath) {\n // Local workspace - use the provided path directly\n workspacePath = config.runnerRepoPath;\n console.log(`Using local workspace path: ${workspacePath}`);\n\n // For task conversations, isolate the worktree/branch when the repo has a .git directory\n if (conversationObjectType === \"Task\" && workspaceId) {\n const hasGitDir = await fs\n .access(path.join(workspacePath, \".git\"))\n .then(() => true)\n .catch(() => false);\n\n if (hasGitDir && useWorktrees) {\n const repoUrl = (config.repository?.url as string) || `file://${workspacePath}`;\n const baseBranch = (config.repository?.branch as string) || \"main\";\n\n const taskHandle = await this.repositoryManager.createTaskWorktree(\n conversationObjectId,\n workspaceId,\n repoUrl,\n baseBranch,\n config.githubToken\n );\n workspacePath = taskHandle.worktreePath;\n (context as any).taskHandle = taskHandle;\n }\n }\n } else if (\n conversationObjectType === \"Task\" &&\n config.repository &&\n workspaceId &&\n useWorktrees\n ) {\n // Use task-specific worktree for all task conversations (keeps shared workspace checkout clean)\n console.log(\n `[ClaudeManager] Creating task worktree with repository config:`,\n {\n conversationObjectId,\n workspaceId,\n repository: config.repository,\n hasUrl: !!config.repository.url,\n url: config.repository.url,\n branch: config.repository.branch,\n type: config.repository.type,\n }\n );\n\n // Check if repository.url is missing\n if (!config.repository.url) {\n throw new Error(\n `Repository URL is missing in config for task ${conversationObjectId}. Repository config: ${JSON.stringify(\n config.repository\n )}`\n );\n }\n\n const taskHandle = await this.repositoryManager.createTaskWorktree(\n conversationObjectId,\n workspaceId,\n config.repository.url,\n config.repository.branch,\n config.githubToken\n );\n workspacePath = taskHandle.worktreePath;\n\n // Store task handle information in context for later use\n (context as any).taskHandle = taskHandle;\n } else if (config.repository && workspaceId) {\n // Check if it's a local repository\n if (config.repository.type === \"local\" && config.repository.localPath) {\n // Use the local path directly\n workspacePath = config.repository.localPath;\n console.log(`Using local repository path: ${workspacePath}`);\n } else {\n // Fall back to workspace-based checkout for non-task conversations\n workspacePath = await this.repositoryManager.checkoutRepository(\n workspaceId,\n config.repository.url,\n config.repository.branch,\n config.githubToken\n );\n }\n } else if (workspaceId) {\n workspacePath =\n await this.repositoryManager.getWorkspacePath(workspaceId);\n } else {\n // Default workspace path when no workspaceId is provided\n workspacePath = process.cwd();\n }\n\n // Fetch GitHub tokens from orchestrator API if we have a workspaceId\n const githubToken = workspaceId\n ? await this.fetchGithubTokens(workspaceId)\n : undefined;\n\n // Generate TOOL_TOKEN for MCP tools authentication\n let toolToken: string | undefined;\n if (config.mcpServers && Object.keys(config.mcpServers).length > 0) {\n const runnerToken = process.env[\"NORTHFLARE_RUNNER_TOKEN\"];\n const runnerUid = this.runner.getRunnerUid();\n\n if (runnerToken && runnerUid && context.conversationId) {\n // Sign JWT with runner's token\n toolToken = jwt.sign(\n {\n conversationId: context.conversationId,\n runnerUid: runnerUid,\n },\n runnerToken,\n {\n expiresIn: \"60m\", // 60 minutes expiry\n }\n );\n console.log(\n \"[ClaudeManager] Generated TOOL_TOKEN for MCP authentication\"\n );\n } else {\n console.warn(\n \"[ClaudeManager] Unable to generate TOOL_TOKEN - missing required data\"\n );\n }\n }\n\n // Simplified SDK configuration - using native query API with streamlined options\n // const cliPath = require.resolve(\"@anthropic-ai/claude-code/cli.js\");\n\n // Debug logging for executable paths\n //console.log(\"[ClaudeManager] SDK executable paths:\", {\n // cliPath,\n // cwd: workspacePath,\n //});\n\n // Simplified environment configuration\n const envVars: Record<string, string> = {\n ...(Object.fromEntries(\n Object.entries(process.env).filter(([_, value]) => value !== undefined)\n ) as Record<string, string>), // Preserve parent environment, filter out undefined values\n };\n\n if (config.anthropicApiKey) {\n envVars[\"ANTHROPIC_API_KEY\"] = config.anthropicApiKey;\n }\n\n if (config.accessToken) {\n envVars[\"CLAUDE_CODE_OAUTH_TOKEN\"] = config.accessToken;\n }\n\n if (githubToken) {\n envVars[\"GITHUB_TOKEN\"] = githubToken;\n }\n\n if (isDebugEnabledFor(\"sdk\")) {\n envVars[\"DEBUG\"] = \"1\";\n }\n\n const instructionPrefix = this.getInstructionPrefix(context);\n\n // System prompt handling (append uses preset+append; replace uses raw string)\n // Include global/workspace instructions in the system prompt so Claude sees them.\n const baseSystemPrompt =\n config.systemPrompt || (conversationData as any)?.systemPrompt;\n const northflareSystemPrompt =\n (config as any)?.northflareSystemPrompt ||\n (conversationData as any)?.northflareSystemPrompt;\n const providedSystemPrompt = [northflareSystemPrompt, instructionPrefix, baseSystemPrompt]\n .filter((p): p is string => typeof p === \"string\" && p.trim().length > 0)\n .map((p) => p.trim())\n .join(\"\\n\\n\");\n\n const systemPromptMode =\n config.systemPromptMode ||\n (conversationData as any)?.systemPromptMode ||\n // Default ProjectStep conversations to append so preset stays intact\n \"append\";\n\n let systemPromptOption: any;\n if (providedSystemPrompt) {\n if (systemPromptMode === \"replace\") {\n systemPromptOption = providedSystemPrompt;\n } else {\n systemPromptOption = {\n type: \"preset\" as const,\n preset: \"claude_code\" as const,\n append: providedSystemPrompt,\n };\n }\n }\n\n console.log(\n `[ClaudeManager] System prompt configuration for conversation ${context.conversationId}:`,\n {\n mode: systemPromptMode,\n hasProvidedSystemPrompt: Boolean(providedSystemPrompt),\n hasInstructionPrefix: Boolean(instructionPrefix),\n finalPromptType: typeof systemPromptOption,\n finalPromptLength:\n typeof systemPromptOption === \"string\"\n ? systemPromptOption.length\n : (systemPromptOption as any)?.append?.length ?? 0,\n }\n );\n\n // Tool restrictions based on permissions mode\n // \"read\" = read-only mode (no file writes, no shell)\n // \"project\" = no file writes but allows bash, no subagents (for Project conversation)\n const readOnlyTools = [\n \"Write\",\n \"Edit\",\n \"MultiEdit\",\n \"Bash\",\n \"KillBash\",\n \"NotebookEdit\",\n \"ExitPlanMode\",\n ];\n const projectModeTools = [\n \"Write\",\n \"Edit\",\n \"MultiEdit\",\n \"NotebookEdit\",\n \"ExitPlanMode\",\n \"Task\",\n ];\n const disallowedTools: string[] =\n context.permissionsMode === \"read\"\n ? readOnlyTools\n : context.permissionsMode === \"project\"\n ? projectModeTools\n : [];\n\n if (disallowedTools.length) {\n console.log(\"[ClaudeManager] Applied read-only mode tool restrictions\");\n }\n\n // Simplified MCP server configuration\n let mcpServers: Record<string, any> | undefined;\n if (config.mcpServers) {\n mcpServers = expandEnv(config.mcpServers, { TOOL_TOKEN: toolToken });\n console.log(\n \"[ClaudeManager] MCP servers configuration:\",\n JSON.stringify(mcpServers, null, 2)\n );\n }\n\n // Create input stream for user messages (simplified message queueing)\n const input = createUserMessageStream();\n\n // Launch SDK with simplified configuration\n const sdk = sdkQuery({\n prompt: input.iterable,\n options: {\n //pathToClaudeCodeExecutable: cliPath,\n cwd: workspacePath,\n env: envVars,\n model: context.model,\n permissionMode: \"bypassPermissions\", // Runner handles permissions\n resume:\n config.sessionId || conversationData?.agentSessionId || undefined,\n ...(systemPromptOption ? { systemPrompt: systemPromptOption } : {}),\n ...(disallowedTools.length ? { disallowedTools } : {}),\n ...(mcpServers ? { mcpServers } : {}),\n ...(isDebugEnabledFor(\"sdk\")\n ? {\n stderr: (data: string) => {\n try {\n console.log(`[Claude SDK] ${data}`);\n } catch {}\n },\n }\n : {}),\n },\n });\n\n // Simplified conversation wrapper - reduced complexity while maintaining interface\n const conversation = createConversationWrapper(\n sdk,\n input,\n async (hadError: boolean, error?: any) => {\n await this._handleRunCompletion(context, hadError, error);\n }\n );\n\n // Store conversation instance in context for reuse\n context.conversation = conversation as any;\n\n // Observe session id from first messages that include it\n conversation.onSessionId(async (agentSessionId: string) => {\n if (!agentSessionId) return;\n const oldSessionId = context.agentSessionId;\n if (oldSessionId !== agentSessionId) {\n context.agentSessionId = agentSessionId;\n context.status = \"active\";\n await this.runner.notify(\"agentSessionId.changed\", {\n conversationId: context.conversationId,\n conversationObjectType,\n conversationObjectId,\n oldAgentSessionId: oldSessionId,\n newAgentSessionId: agentSessionId,\n });\n }\n });\n\n // Set up streaming message handler\n const messageHandler = async (\n message: SDKMessage,\n sessionId: string | null\n ) => {\n await this.handleStreamedMessage(context, message, sessionId);\n\n // Heuristic: detect terminal system events and finalize\n try {\n if (message?.type === \"system\") {\n const m: any = message;\n const subtype = m.subtype || m?.message?.subtype || m?.event;\n const exitSignals = [\n \"exit\",\n \"exiting\",\n \"session_end\",\n \"conversation_end\",\n \"process_exit\",\n \"done\",\n \"completed\",\n ];\n if (subtype && exitSignals.includes(String(subtype))) {\n await this._handleRunCompletion(context, false);\n }\n } else if (message?.type === \"result\") {\n // Treat 'result' as an end-of-conversation signal for the SDK\n try {\n await this._handleRunCompletion(context, false);\n console.log(\n \"[ClaudeManager] Finalized conversation due to SDK 'result' message\",\n {\n conversationId: context.conversationId,\n agentSessionId: context.agentSessionId,\n }\n );\n } catch (e) {\n console.warn(\n \"[ClaudeManager] Error finalizing on 'result' message:\",\n e\n );\n }\n }\n } catch (e) {\n console.warn(\"[ClaudeManager] finalize-on-system heuristic error:\", e);\n }\n };\n\n conversation.stream(messageHandler);\n\n // Note: Error handling is done via process completion handler\n // The Claude SDK doesn't have an onError method on conversations\n\n // Send initial messages\n try {\n for (const message of initialMessages) {\n // Check if the message content contains multimodal content blocks (e.g., images, documents)\n const contentBlocks = this.normalizeToContentBlocks(message.content);\n\n if (contentBlocks && Array.isArray(contentBlocks) && contentBlocks.some(b => b.type === 'image' || b.type === 'document')) {\n // Send multimodal message with content blocks array\n // SDK supports URL images directly: { type: \"image\", source: { type: \"url\", url: \"...\" } }\n // SDK supports URL documents directly: { type: \"document\", source: { type: \"url\", url: \"...\" } }\n console.log('[ClaudeManager] Sending multimodal message with', contentBlocks.length, 'content blocks');\n if (isDebugEnabledFor(\"manager\")) {\n console.log('[ClaudeManager] Content blocks:', JSON.stringify(contentBlocks, null, 2));\n }\n (conversation as any).send(contentBlocks);\n } else {\n // Fallback to text-only message\n const initialText = this.normalizeToText(message.content);\n conversation.send({\n type: \"text\",\n text: initialText,\n });\n }\n }\n\n console.log(\n `Started conversation for ${conversationObjectType} ${conversationObjectId} in workspace ${workspacePath}`\n );\n\n // Return the conversation context directly\n return context;\n } catch (error) {\n // Handle startup errors\n await this._handleConversationError(context, error as Error);\n throw error;\n }\n }\n\n private getInstructionPrefix(context: ConversationContext): string {\n const parts: string[] = [];\n\n if (context.globalInstructions) {\n parts.push(\n `<global-instructions>\\n${context.globalInstructions}\\n</global-instructions>`\n );\n }\n\n if (context.workspaceInstructions) {\n parts.push(\n `<workspace-instructions>\\n${context.workspaceInstructions}\\n</workspace-instructions>`\n );\n }\n\n return parts.join(\"\\n\\n\");\n }\n\n private async _handleRunCompletion(\n context: ConversationContext,\n hadError: boolean,\n error?: any\n ): Promise<void> {\n if ((context as any)._finalized) return;\n\n const inFlight = (context as any)._runCompletionInFlight as\n | Promise<void>\n | undefined;\n if (inFlight) return inFlight;\n\n const promise = (async () => {\n\n const isTaskConversation = context.conversationObjectType === \"Task\";\n const stopRequested = (context as any)._stopRequested === true;\n const taskHandle = (context as any).taskHandle as any;\n const shouldRunGitFlow =\n context.config.useWorktrees !== false &&\n isTaskConversation &&\n !!taskHandle &&\n taskHandle.branch !== \"local\";\n\n if (!shouldRunGitFlow || hadError || stopRequested) {\n await this._finalizeConversation(context, hadError, error);\n return;\n }\n\n const taskId = context.conversationObjectId;\n const baseBranch =\n (context.config.repository?.branch as string | undefined) || \"main\";\n\n try {\n const taskState = await this.repositoryManager.getTaskState(taskId);\n const taskRepoInfo = await this.repositoryManager.getTaskRepoInfo(taskId);\n if (\n !taskState ||\n !taskRepoInfo ||\n !taskRepoInfo.worktreePath ||\n taskState.branch === \"local\"\n ) {\n await this._finalizeConversation(context, false);\n return;\n }\n\n const isLocalRepo = taskRepoInfo.repoKey.startsWith(\"local__\");\n const mergeWorkdir = isLocalRepo\n ? taskRepoInfo.controlPath\n : taskRepoInfo.worktreePath;\n\n // If we already have unresolved conflicts, immediately ask the agent to resolve them.\n const taskGit = simpleGit(taskRepoInfo.worktreePath);\n const initialTaskStatus = await taskGit.status();\n if (initialTaskStatus.conflicted.length > 0) {\n await this._resumeForGitConflictResolution(context, {\n kind: \"conflicts\",\n baseBranch,\n conflicts: initialTaskStatus.conflicted,\n workdir: taskRepoInfo.worktreePath,\n });\n return;\n }\n\n if (isLocalRepo && mergeWorkdir !== taskRepoInfo.worktreePath) {\n const mergeGit = simpleGit(mergeWorkdir);\n const mergeStatus = await mergeGit.status();\n if (mergeStatus.conflicted.length > 0) {\n await this._resumeForGitConflictResolution(context, {\n kind: \"conflicts\",\n baseBranch,\n conflicts: mergeStatus.conflicted,\n workdir: mergeWorkdir,\n });\n return;\n }\n }\n\n // Ensure we're on the task branch for commit/rebase operations.\n const currentBranch = (await taskGit.revparse([\"--abbrev-ref\", \"HEAD\"])).trim();\n if (currentBranch !== taskState.branch) {\n await taskGit.checkout(taskState.branch);\n }\n\n const status = await taskGit.status();\n if (!status.isClean()) {\n await this.repositoryManager.stageAll(taskId);\n try {\n const previousCommitCount = (taskState as any)?.commitCount ?? 0;\n const baseSubject =\n (context.summary ?? \"\").replace(/\\s+/g, \" \").trim() ||\n `Task ${taskId}`;\n const message =\n previousCommitCount > 0\n ? `${baseSubject} (followup #${previousCommitCount})`\n : baseSubject;\n await this.repositoryManager.commit(taskId, message);\n } catch (commitError) {\n const msg = commitError instanceof Error ? commitError.message : String(commitError);\n if (!msg.toLowerCase().includes(\"nothing to commit\")) {\n throw commitError;\n }\n }\n }\n\n const integrateResult = await this.repositoryManager.integrateTask(\n taskId,\n baseBranch,\n \"no-ff\"\n );\n if (!integrateResult.success) {\n await this._resumeForGitConflictResolution(context, {\n kind: integrateResult.phase,\n baseBranch,\n conflicts: integrateResult.conflicts ?? [],\n workdir: integrateResult.conflictWorkdir,\n error: integrateResult.error,\n });\n return;\n }\n\n // Worktree is no longer needed after a successful merge; preserve the branch\n await this.repositoryManager.removeTaskWorktree(taskId, { preserveBranch: true });\n\n const wsId = context.config.workspaceId || context.workspaceId;\n const repoUrl = context.config.repository?.url;\n if (wsId && repoUrl) {\n await this.repositoryManager.syncWorkspaceWorktree(wsId, repoUrl, baseBranch);\n }\n\n await this._finalizeConversation(context, false);\n } catch (mergeError) {\n console.error(\"[ClaudeManager] Post-task git flow failed\", mergeError);\n await this._finalizeConversation(context, true, mergeError);\n }\n })();\n\n (context as any)._runCompletionInFlight = promise.finally(() => {\n delete (context as any)._runCompletionInFlight;\n });\n return (context as any)._runCompletionInFlight;\n }\n\n private async _resumeForGitConflictResolution(\n context: ConversationContext,\n payload: {\n kind: \"conflicts\" | \"rebase\" | \"merge\";\n baseBranch: string;\n conflicts: string[];\n workdir: string;\n error?: string;\n }\n ): Promise<void> {\n const { kind, baseBranch, conflicts, workdir, error } = payload;\n\n const conflictsList = conflicts?.length\n ? `\\n\\nConflicted files:\\n${conflicts.map((f) => `- ${f}`).join(\"\\n\")}`\n : \"\";\n const workdirHint = workdir ? `\\n\\nWork directory:\\n- ${workdir}` : \"\";\n const errorHint = error ? `\\n\\nError:\\n${error}` : \"\";\n const hasConflicts = !!conflicts?.length;\n\n let instruction: string;\n if (kind === \"rebase\") {\n instruction = hasConflicts\n ? `<system-instructions>\\nA git rebase onto \\`${baseBranch}\\` produced merge conflicts.${conflictsList}${workdirHint}${errorHint}\\n\\nPlease resolve the conflicts in that directory, then run:\\n- git add -A\\n- git rebase --continue\\n\\nWhen the rebase finishes cleanly, reply briefly so I can retry the integration.\\n</system-instructions>`\n : `<system-instructions>\\nA git rebase onto \\`${baseBranch}\\` failed.${workdirHint}${errorHint}\\n\\nNo conflicted files were reported. Please run:\\n- git status\\n\\nFix the error (or complete/abort any in-progress git operation) and reply briefly so I can retry the integration.\\n</system-instructions>`;\n } else if (kind === \"merge\") {\n instruction = hasConflicts\n ? `<system-instructions>\\nA git merge into \\`${baseBranch}\\` produced merge conflicts.${conflictsList}${workdirHint}${errorHint}\\n\\nPlease resolve the conflicts in that directory, then run:\\n- git add -A\\n- git commit -m \\\"Resolve merge conflicts for ${context.conversationObjectId}\\\"\\n\\nWhen the working tree is clean, reply briefly so I can retry the integration.\\n</system-instructions>`\n : `<system-instructions>\\nA git merge into \\`${baseBranch}\\` failed.${workdirHint}${errorHint}\\n\\nNo conflicted files were reported. Please run:\\n- git status\\n\\nFix the error (or complete/abort any in-progress git operation) and reply briefly so I can retry the integration.\\n</system-instructions>`;\n } else {\n instruction = `<system-instructions>\\nGit has unresolved conflicts.${conflictsList}${workdirHint}${errorHint}\\n\\nPlease resolve the conflicts in that directory and complete the in-progress git operation (rebase or merge). When the working tree is clean, reply briefly so I can retry the integration.\\n</system-instructions>`;\n }\n\n const conversationData = {\n id: context.conversationId,\n objectType: context.conversationObjectType,\n objectId: context.conversationObjectId,\n model: context.model,\n summary: context.summary ?? null,\n globalInstructions: context.globalInstructions,\n workspaceInstructions: context.workspaceInstructions,\n permissionsMode: context.permissionsMode,\n agentSessionId: context.agentSessionId,\n };\n\n await this.resumeConversation(\n context.conversationObjectType,\n context.conversationObjectId,\n context.agentSessionId,\n context.config,\n conversationData,\n instruction\n );\n }\n\n async stopConversation(\n agentSessionId: string,\n context: ConversationContext,\n isRunnerShutdown: boolean = false,\n reason?: string\n ): Promise<void> {\n (context as any)._stopRequested = true;\n if (context && context.conversation) {\n context.status = \"stopping\";\n\n try {\n // Proactively send end notification to avoid missing it on abnormal exits\n // Use provided reason, or fall back to 'runner_shutdown' if isRunnerShutdown is true\n const finalReason =\n reason || (isRunnerShutdown ? \"runner_shutdown\" : undefined);\n (context as any)._stopReason = finalReason;\n await this._finalizeConversation(\n context,\n false,\n undefined,\n finalReason\n ).catch(() => {});\n // Mark conversation as stopped BEFORE ending to prevent race conditions\n context.status = \"stopped\";\n\n // Properly end the conversation using the SDK\n if (isClaudeConversation(context.conversation)) {\n await context.conversation.end();\n }\n } catch (error) {\n console.error(`Error ending conversation ${agentSessionId}:`, error);\n }\n\n // Clean up conversation reference\n delete context.conversation;\n }\n\n console.log(\n `Stopped conversation ${agentSessionId} for ${context.conversationObjectType} ${context.conversationObjectId}`\n );\n }\n\n async resumeConversation(\n conversationObjectType: \"Task\" | \"TaskPlan\" | \"ProjectStep\",\n conversationObjectId: string,\n agentSessionId: string,\n config: ConversationConfig,\n conversationData?: any,\n resumeMessage?: string\n ): Promise<string> {\n console.log(`[ClaudeManager] Resuming conversation ${agentSessionId}`);\n\n // Resume is handled by starting a new conversation with the existing session ID\n const context = await this.startConversation(\n conversationObjectType,\n conversationObjectId,\n { ...config, sessionId: agentSessionId },\n [], // Don't send initial messages\n conversationData\n );\n\n // After starting the conversation with the sessionId, we need to send a message\n // to actually trigger the Claude process to continue\n if (context.conversation && isClaudeConversation(context.conversation)) {\n try {\n // Use the provided resume message or default to system instruction\n const messageToSend =\n resumeMessage ||\n \"<system-instructions>Please continue</system-instructions>\";\n console.log(\n `[ClaudeManager] Sending resume message to conversation ${agentSessionId}`\n );\n context.conversation.send({\n type: \"text\",\n text: messageToSend,\n });\n } catch (error) {\n console.error(`[ClaudeManager] Error sending resume message:`, error);\n }\n } else {\n console.warn(\n \"[ClaudeManager] Resume requested but conversation instance missing or incompatible\"\n );\n }\n\n return context.agentSessionId;\n }\n\n private async _finalizeConversation(\n context: ConversationContext,\n hadError: boolean,\n error?: any,\n reason?: string\n ): Promise<void> {\n // Synchronous idempotency check - must happen before any async operations\n if ((context as any)._finalized) return;\n (context as any)._finalized = true;\n\n // Mark as completed immediately to prevent restart on catch-up\n // This is synchronous and happens before any async operations\n this.runner.markConversationCompleted(context.conversationId);\n\n // Clean up conversation from active conversations (synchronous)\n try {\n console.log(`[ClaudeManager] Removing conversation from active map:`, {\n conversationId: context.conversationId,\n agentSessionId: context.agentSessionId,\n mapSizeBefore: this.runner.activeConversations_.size,\n });\n this.runner.activeConversations_.delete(context.conversationId);\n statusLineManager.updateActiveCount(\n this.runner.activeConversations_.size\n );\n } catch {}\n\n // Now do async notification (after all sync cleanup)\n try {\n await this.runner.notify(\"conversation.end\", {\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n agentSessionId: context.agentSessionId,\n isError: hadError,\n errorMessage: error?.message,\n reason: reason,\n });\n } catch (e) {\n console.error(\"[ClaudeManager] Failed to notify conversation.end:\", e);\n }\n\n // Notify update coordinator that a conversation has ended\n // This may trigger an auto-update if one is pending and runner is now idle\n try {\n await this.runner.onConversationEnd();\n } catch (e) {\n console.error(\"[ClaudeManager] Failed to notify onConversationEnd:\", e);\n }\n }\n\n async sendUserMessage(\n conversationId: string,\n content: any,\n config?: ConversationConfig,\n conversationObjectType?: \"Task\" | \"TaskPlan\" | \"ProjectStep\",\n conversationObjectId?: string,\n conversation?: any,\n _agentSessionIdOverride?: string\n ): Promise<void> {\n console.log(`[ClaudeManager] sendUserMessage called with:`, {\n conversationId,\n conversationObjectType,\n conversationObjectId,\n hasConfig: !!config,\n hasConversation: !!conversation,\n activeConversations: this.runner.activeConversations_.size,\n });\n\n // Find by conversationId only\n let context = this.runner.getConversationContext(conversationId);\n console.log(`[ClaudeManager] Lookup by conversationId result:`, {\n found: !!context,\n conversationId: context?.conversationId,\n agentSessionId: context?.agentSessionId,\n });\n\n if (!context) {\n throw new Error(\n `No active or fetchable conversation found for ${conversationId}`\n );\n }\n\n try {\n // Send immediately when a conversation instance exists; no need to wait for \"active\"\n if (\n !context.conversation ||\n !isClaudeConversation(context.conversation)\n ) {\n throw new Error(\n `No conversation instance found for conversation ${context.conversationId}`\n );\n }\n\n // Guard: Don't send messages if conversation is stopped or stopping\n const conversationStatus = context.status as string;\n if (\n conversationStatus === \"stopped\" ||\n conversationStatus === \"stopping\"\n ) {\n console.warn(\n `Attempted to send message to stopped/stopping conversation ${context.conversationId}`,\n {\n status: context.status,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n }\n );\n return;\n }\n\n // Native message injection - SDK handles queueing and delivery\n // Check if the message content contains multimodal content blocks (e.g., images, documents)\n const contentBlocks = this.normalizeToContentBlocks(content);\n\n if (contentBlocks && Array.isArray(contentBlocks) && contentBlocks.some(b => b.type === 'image' || b.type === 'document')) {\n // Send multimodal message with content blocks array\n // SDK supports URL images directly: { type: \"image\", source: { type: \"url\", url: \"...\" } }\n // SDK supports URL documents directly: { type: \"document\", source: { type: \"url\", url: \"...\" } }\n console.log('[ClaudeManager] Sending multimodal follow-up message with', contentBlocks.length, 'content blocks');\n if (isDebugEnabledFor(\"manager\")) {\n console.log('[ClaudeManager] Content blocks:', JSON.stringify(contentBlocks, null, 2));\n }\n (context.conversation as any).send(contentBlocks);\n } else {\n // Fallback to text-only message\n const normalizedText = this.normalizeToText(content);\n\n if (isDebugEnabledFor(\"manager\")) {\n console.log(\"[ClaudeManager] Normalized follow-up content\", {\n originalType: typeof content,\n isArray: Array.isArray(content) || undefined,\n normalizedPreview:\n typeof normalizedText === \"string\"\n ? normalizedText.slice(0, 160)\n : String(normalizedText).slice(0, 160),\n });\n }\n\n context.conversation.send({\n type: \"text\",\n text: normalizedText,\n });\n }\n\n // Update last activity timestamp\n context.lastActivityAt = new Date();\n\n console.log(\n `Sent user message to conversation ${context.conversationId} (agentSessionId: ${context.agentSessionId}, status: ${context.status})`\n );\n } catch (error) {\n // Handle errors properly\n await this._handleConversationError(context, error as Error);\n throw error; // Re-throw to maintain the same behavior\n }\n }\n\n private async fetchGithubTokens(\n workspaceId: string\n ): Promise<string | undefined> {\n try {\n const response = await fetch(\n `${this.runner.config_.orchestratorUrl}/api/runner/tokens?workspaceId=${workspaceId}`,\n {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${process.env[\"NORTHFLARE_RUNNER_TOKEN\"]}`,\n },\n }\n );\n\n if (!response.ok) {\n console.error(`Failed to fetch GitHub tokens: ${response.status}`);\n return undefined;\n }\n\n const data = (await response.json()) as { githubToken?: string };\n return data.githubToken;\n } catch (error) {\n console.error(\"Error fetching GitHub tokens:\", error);\n return undefined;\n }\n }\n\n private async _handleConversationError(\n context: ConversationContext,\n error: Error\n ): Promise<void> {\n const errorType = this.classifyError(error);\n\n // Notify orchestrator\n await this.runner.notify(\"error.report\", {\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n agentSessionId: context.agentSessionId,\n errorType,\n message: error.message,\n details: {\n stack: error.stack,\n timestamp: new Date(),\n },\n });\n\n // Conversation continues on error - no automatic cleanup\n console.error(\n `Conversation error for ${context.conversationObjectType} ${context.conversationObjectId}:`,\n error\n );\n }\n\n private classifyError(error: Error): string {\n if (error.message.includes(\"process exited\")) {\n return \"process_exit\";\n } else if (error.message.includes(\"model\")) {\n return \"model_error\";\n } else if (error.message.includes(\"tool\")) {\n return \"tool_error\";\n } else if (error.message.includes(\"permission\")) {\n return \"permission_error\";\n } else if (error.message.includes(\"timeout\")) {\n return \"timeout_error\";\n }\n return \"unknown_error\";\n }\n\n /**\n * Normalize arbitrary content shapes into a plain string for the CLI\n */\n private normalizeToText(value: any): string {\n if (typeof value === \"string\") return value;\n if (value == null) return \"\";\n\n if (typeof value === \"object\") {\n // Common simple shapes\n if (typeof (value as any).text === \"string\") return (value as any).text;\n if (\n typeof (value as any).text === \"object\" &&\n (value as any).text &&\n typeof (value as any).text.text === \"string\"\n )\n return (value as any).text.text;\n if (typeof (value as any).content === \"string\")\n return (value as any).content;\n\n // Array of blocks: [{ type: 'text', text: '...' }, ...]\n if (Array.isArray(value)) {\n const texts = value\n .map((b) =>\n b && b.type === \"text\" && typeof b.text === \"string\" ? b.text : null\n )\n .filter((t): t is string => !!t);\n if (texts.length) return texts.join(\" \");\n }\n\n // Nested message shapes\n if (\n typeof (value as any).message === \"object\" &&\n (value as any).message &&\n typeof (value as any).message.text === \"string\"\n ) {\n return (value as any).message.text;\n }\n }\n\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n }\n\n /**\n * Normalize arbitrary content shapes into content blocks array for multimodal support.\n * Returns the array of content blocks if the content contains image or document blocks,\n * otherwise returns null to indicate text-only content.\n */\n private normalizeToContentBlocks(value: any): Array<{ type: string; [key: string]: any }> | null {\n // If already an array, check if it contains image or document blocks\n if (Array.isArray(value)) {\n const hasMultimodal = value.some(b => b && (b.type === 'image' || b.type === 'document'));\n if (hasMultimodal) {\n // Return the content blocks (will be converted to SDK format later)\n return value;\n }\n return null;\n }\n\n // Check if it's a wrapped content object\n if (typeof value === 'object' && value !== null) {\n // Check for nested content array\n if (Array.isArray(value.content)) {\n const hasMultimodal = value.content.some((b: any) => b && (b.type === 'image' || b.type === 'document'));\n if (hasMultimodal) {\n return value.content;\n }\n }\n }\n\n return null;\n }\n\n private async handleStreamedMessage(\n context: ConversationContext,\n message: SDKMessage,\n sessionId: string | null\n ): Promise<void> {\n /*\n * SDK tool call payload reference (observed shapes)\n *\n * 1) Assistant tool call (tool_use)\n * {\n * \"type\": \"assistant\",\n * \"message\": {\n * \"role\": \"assistant\",\n * \"content\": [\n * { \"type\": \"text\", \"text\": \"…optional text…\" },\n * { \"type\": \"tool_use\", \"id\": \"toolu_01Nbv…\", \"name\": \"TodoWrite\", \"input\": { ... } }\n * ]\n * },\n * \"session_id\": \"…\"\n * }\n *\n * 2) Tool result (often emitted as type 'user')\n * {\n * \"type\": \"user\",\n * \"message\": {\n * \"role\": \"user\",\n * \"content\": [\n * {\n * \"tool_use_id\": \"toolu_01E9R475…\",\n * \"type\": \"tool_result\",\n * \"content\": \"Todos have been modified successfully. …\"\n * }\n * ]\n * },\n * \"parent_tool_use_id\": null,\n * \"session_id\": \"…\",\n * \"uuid\": \"…\"\n * }\n *\n * Normalization (runner → server message.agent):\n * - assistant tool_use → type: 'assistant', content: [{ toolCalls: [{ id, name, arguments }] }, …]\n * - tool_result (any shape) → type: 'tool_result', subtype: 'tool_result', content:\n * [ { type: 'tool_result', subtype: 'tool_result', tool_use_id, content } ]\n */\n // Guard: Don't process messages if conversation is stopped or stopping\n const status = context.status as string;\n if (status === \"stopped\" || status === \"stopping\") {\n console.log(\n `Ignoring message for stopped/stopping conversation ${context.conversationId}`,\n {\n status: context.status,\n messageType: message.type,\n }\n );\n return;\n }\n\n try {\n // High-level receipt log\n console.log(\n `Received streamed message for ${context.conversationObjectType} ${context.conversationObjectId}`,\n {\n type: message?.type,\n }\n );\n\n // Raw SDK message diagnostics\n try {\n // Log the full raw SDK message safely (handles circular refs)\n const safeStringify = (obj: any) => {\n const seen = new WeakSet();\n return JSON.stringify(\n obj,\n (key, value) => {\n if (typeof value === \"function\") return undefined;\n if (typeof value === \"bigint\") return String(value);\n if (typeof value === \"object\" && value !== null) {\n if (seen.has(value)) return \"[Circular]\";\n seen.add(value);\n }\n return value;\n },\n 2\n );\n };\n\n console.log(\n \"[ClaudeManager] RAW SDK message FULL:\",\n safeStringify(message)\n );\n\n const summary = {\n keys: Object.keys(message || {}),\n hasMessage: !!(message as any)?.message,\n contentType: typeof (message as any)?.content,\n messageContentType: typeof (message as any)?.message?.content,\n sessionId:\n (message as any)?.session_id || (message as any)?.sessionId || null,\n };\n console.log(\"[ClaudeManager] RAW SDK message summary:\", summary);\n if ((message as any)?.content !== undefined) {\n console.log(\n \"[ClaudeManager] RAW SDK content:\",\n (message as any).content\n );\n }\n if ((message as any)?.message?.content !== undefined) {\n console.log(\n \"[ClaudeManager] RAW SDK nested content:\",\n (message as any).message.content\n );\n }\n } catch (e) {\n console.warn(\"[ClaudeManager] Failed to log raw SDK message:\", e);\n }\n\n // Build structured content based on message type\n let messageType: string = message.type;\n let subtype: string | undefined;\n let structuredContent: any = {};\n let isError = false;\n let skipSend = false;\n let metadata: any = null;\n\n // Extract parent_tool_use_id if present (for all message types)\n const msgAsAny = message as any;\n if (msgAsAny.parent_tool_use_id) {\n metadata = {\n parent_tool_use_id: msgAsAny.parent_tool_use_id,\n };\n }\n\n // Extract content based on message type\n switch (message.type) {\n case \"assistant\": {\n const assistantMsg = message as any;\n const blocks =\n assistantMsg?.message?.content || assistantMsg?.content || [];\n const textContent = Array.isArray(blocks)\n ? blocks\n .filter(\n (b: any) =>\n b && b.type === \"text\" && typeof b.text === \"string\"\n )\n .map((b: any) => b.text)\n .join(\"\")\n : \"\";\n const toolCalls = Array.isArray(blocks)\n ? blocks\n .filter((b: any) => b && b.type === \"tool_use\")\n .map((b: any) => ({\n id: b.id,\n name: b.name,\n arguments: b.input,\n }))\n : undefined;\n\n structuredContent = {\n ...(textContent ? { text: textContent } : {}),\n ...(toolCalls && toolCalls.length ? { toolCalls } : {}),\n timestamp: new Date().toISOString(),\n };\n break;\n }\n\n case \"thinking\" as any: {\n messageType = \"thinking\";\n subtype = undefined;\n const thinkingMsg = message as any;\n structuredContent = [\n {\n type: \"thinking\",\n thinking: thinkingMsg.content || \"\",\n text: thinkingMsg.content || \"\",\n timestamp: new Date().toISOString(),\n },\n ];\n break;\n }\n\n case \"tool_use\" as any: {\n // Tool call request - map to assistant\n messageType = \"assistant\";\n subtype = \"tool_use\";\n const toolUseMsg = message as any;\n structuredContent = {\n toolCalls: [\n {\n id: toolUseMsg.id,\n name: toolUseMsg.name,\n arguments: toolUseMsg.input,\n },\n ],\n timestamp: new Date().toISOString(),\n };\n break;\n }\n\n case \"tool_result\" as any: {\n // Tool execution result - normalize to v1-style tool_result blocks\n // so the server persists as messageType: tool_call_result with correct content\n messageType = \"tool_result\";\n subtype = \"tool_result\";\n const toolResultMsg = message as any;\n structuredContent = [\n {\n type: \"tool_result\",\n subtype: \"tool_result\",\n tool_use_id: toolResultMsg.tool_use_id,\n content: toolResultMsg.content, // Keep content as native (array or string)\n timestamp: new Date().toISOString(),\n },\n ];\n break;\n }\n\n case \"result\": {\n const resultMsg = message as any;\n structuredContent = {\n text: resultMsg.content || resultMsg.result || \"\",\n timestamp: new Date().toISOString(),\n };\n break;\n }\n\n case \"user\": {\n const userMsg = message as any;\n\n // Prefer nested message.content if present (SDK shape), fallback to top-level content\n const blocks =\n (userMsg && userMsg.message && userMsg.message.content) ||\n userMsg?.content ||\n [];\n\n if (Array.isArray(blocks)) {\n const hasToolResult = blocks.some(\n (b: any) => b && typeof b === \"object\" && b.type === \"tool_result\"\n );\n\n if (hasToolResult) {\n // Normalize tool_result blocks to v1-style\n messageType = \"tool_result\";\n subtype = \"tool_result\";\n structuredContent = blocks\n .filter((b: any) => b && b.type === \"tool_result\")\n .map((b: any) => ({\n type: \"tool_result\",\n subtype: \"tool_result\",\n tool_use_id: b.tool_use_id || b.toolUseId || b.id,\n content: b.content, // Keep content as native (array or string)\n }));\n } else {\n // Treat as plain text content by joining text blocks\n const textContent = blocks\n .filter(\n (b: any) =>\n b && b.type === \"text\" && typeof b.text === \"string\"\n )\n .map((b: any) => b.text)\n .join(\"\");\n structuredContent = {\n text: textContent,\n timestamp: new Date().toISOString(),\n };\n\n // Check if this is a subagent prompt (Task tool input being sent to subagent)\n // These have parent_tool_use_id but are NOT tool_result messages\n if (userMsg.parent_tool_use_id) {\n console.log(\n \"[ClaudeManager] Detected subagent prompt message (parent_tool_use_id present, no tool_result)\",\n {\n parent_tool_use_id: userMsg.parent_tool_use_id,\n }\n );\n messageType = \"assistant\"; // Change from \"user\" to \"assistant\"\n subtype = \"subagent_prompt\";\n // metadata already set above with parent_tool_use_id\n }\n }\n\n // If content array only contains empty objects, skip sending\n if (\n Array.isArray(structuredContent) &&\n structuredContent.length > 0 &&\n structuredContent.every(\n (it: any) =>\n !it || typeof it !== \"object\" || Object.keys(it).length === 0\n )\n ) {\n console.log(\n \"[ClaudeManager] Skipping empty 'user' message with only empty objects from SDK\"\n );\n skipSend = true;\n }\n } else if (typeof userMsg?.content === \"string\") {\n // Attempt to parse JSON arrays (common for tool_result payloads)\n const text = userMsg.content;\n try {\n const parsed = JSON.parse(text);\n if (Array.isArray(parsed)) {\n const hasToolResult = parsed.some(\n (item: any) =>\n item &&\n typeof item === \"object\" &&\n item.type === \"tool_result\"\n );\n if (hasToolResult) {\n messageType = \"tool_result\";\n subtype = \"tool_result\";\n structuredContent = parsed;\n } else {\n structuredContent = {\n text,\n timestamp: new Date().toISOString(),\n };\n }\n } else {\n structuredContent = {\n text,\n timestamp: new Date().toISOString(),\n };\n }\n } catch {\n // Not JSON - treat as plain text\n structuredContent = { text, timestamp: new Date().toISOString() };\n }\n } else {\n // Other object content - preserve as is\n structuredContent = userMsg?.content || {};\n }\n break;\n }\n\n case \"system\": {\n const systemMsg = message as any;\n const subtype = systemMsg.subtype || \"system\";\n const model = systemMsg.model || systemMsg?.message?.model;\n const permissionMode =\n systemMsg.permissionMode || systemMsg?.message?.permissionMode;\n const summary = [\n subtype && `[${subtype}]`,\n model && `model=${model}`,\n permissionMode && `perm=${permissionMode}`,\n ]\n .filter(Boolean)\n .join(\" \");\n structuredContent = {\n text: summary || \"\",\n timestamp: new Date().toISOString(),\n };\n break;\n }\n\n case \"error\" as any: {\n const errorMsg = message as any;\n messageType = \"system\";\n subtype = \"error\";\n isError = true;\n structuredContent = {\n text: errorMsg.message || errorMsg.error || \"Unknown error\",\n errorType: errorMsg.error_type || \"unknown\",\n errorDetails: {\n stack: errorMsg.stack,\n code: errorMsg.code,\n context: errorMsg,\n },\n timestamp: new Date().toISOString(),\n };\n break;\n }\n\n default: {\n // Unknown message type - log and send as assistant\n const unknownMsg = message as any;\n console.warn(`Unknown message type: ${unknownMsg.type}`, message);\n messageType = \"assistant\";\n structuredContent = {\n text: JSON.stringify(message),\n timestamp: new Date().toISOString(),\n };\n }\n }\n\n // Generate a unique message ID\n const messageId = `${context.agentSessionId}-${Date.now()}-${Math.random()\n .toString(36)\n .substr(2, 9)}`;\n\n // Send agent message to orchestrator with structured content\n // Skip if conversation is stopping/stopped to avoid race conditions\n const currentStatus = context.status as string;\n if (currentStatus !== \"stopped\" && currentStatus !== \"stopping\") {\n if (skipSend) {\n console.log(\n \"[ClaudeManager] Not sending message.agent due to skipSend=true\"\n );\n return;\n }\n\n const payload: any = {\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n agentSessionId: context.agentSessionId,\n type: messageType,\n subtype,\n content: Array.isArray(structuredContent)\n ? structuredContent\n : [structuredContent],\n messageId,\n isError,\n };\n\n // Add metadata if present\n if (metadata) {\n payload.metadata = metadata;\n }\n\n try {\n console.log(\"[ClaudeManager] Sending message.agent payload:\", {\n type: payload.type,\n subtype: payload.subtype,\n contentPreview: Array.isArray(payload.content)\n ? payload.content.slice(0, 1)\n : payload.content,\n });\n } catch {}\n\n await this.runner.notify(\"message.agent\", payload as any);\n }\n\n // Tool calls are now handled directly by Claude through the MCP server\n // We just log that we saw them but don't intercept or process them\n if (\n structuredContent.toolCalls &&\n structuredContent.toolCalls.length > 0\n ) {\n console.log(\n `Claude is making ${structuredContent.toolCalls.length} tool call(s) via MCP`,\n {\n conversationObjectId: context.conversationObjectId,\n toolNames: structuredContent.toolCalls.map((tc: any) => tc.name),\n }\n );\n }\n } catch (error) {\n // Check if this is a transport error due to stopped conversation\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n const isTransportError =\n errorMessage.includes(\"Cannot read properties of undefined\") ||\n errorMessage.includes(\"stdout\") ||\n errorMessage.includes(\"transport\");\n\n const statusCheck = context.status as string;\n if (\n isTransportError &&\n (statusCheck === \"stopped\" || statusCheck === \"stopping\")\n ) {\n // This is expected when conversation is stopped - just log it\n console.log(\n `Transport error for stopped/stopping conversation ${context.conversationId} (expected):`,\n errorMessage\n );\n return;\n }\n\n console.error(\n `Error handling streamed message for ${context.conversationObjectType} ${context.conversationObjectId}:`,\n error\n );\n await this._handleConversationError(context, error as Error);\n }\n }\n}\n\n// Simplified helper functions for SDK integration\n\ntype UserMessageStream = {\n iterable: AsyncIterable<any>;\n enqueue: (msg: any) => void;\n close: () => void;\n};\n\nfunction createUserMessageStream(): UserMessageStream {\n const queue: any[] = [];\n let resolver: (() => void) | null = null;\n let done = false;\n\n async function* iterator() {\n while (true) {\n if (queue.length > 0) {\n const value = queue.shift();\n yield value;\n continue;\n }\n if (done) return;\n await new Promise<void>((resolve) => (resolver = resolve));\n resolver = null;\n }\n }\n\n return {\n iterable: iterator(),\n enqueue: (msg: any) => {\n if (done) return;\n queue.push(msg);\n if (resolver) {\n const r = resolver;\n resolver = null;\n r();\n }\n },\n close: () => {\n done = true;\n if (resolver) {\n const r = resolver;\n resolver = null;\n r();\n }\n },\n };\n}\n\nfunction createConversationWrapper(\n sdk: any,\n input: UserMessageStream,\n onComplete?: (hadError: boolean, error?: any) => Promise<void> | void\n) {\n let onSessionIdCb: ((id: string) => void) | null = null;\n let observedSessionId: string | null = null;\n let startedReader = false;\n\n /**\n * Create an SDK user message from content.\n * Content can be a string (for text-only messages) or an array of content blocks\n * (for multimodal messages with images).\n */\n function toSdkUserMessage(content: string | Array<{ type: string; [key: string]: any }>) {\n const message = {\n type: \"user\" as const,\n session_id: observedSessionId || \"\",\n parent_tool_use_id: null,\n message: {\n role: \"user\" as const,\n // Content should be an array of content blocks for multimodal\n // For text-only, SDK accepts string directly\n content: typeof content === 'string'\n ? content\n : content,\n },\n };\n console.log('[ClaudeManager] toSdkUserMessage creating message:', JSON.stringify(message, null, 2));\n return message;\n }\n\n return {\n /**\n * Send a message to the conversation.\n * Accepts either:\n * - { type: \"text\", text: string } for text-only messages\n * - Array of content blocks for multimodal messages (e.g., [{ type: \"text\", text: \"...\" }, { type: \"image\", source: {...} }])\n */\n send(payload: { type: string; text?: string } | Array<{ type: string; [key: string]: any }>) {\n // Handle multimodal content (array of content blocks)\n if (Array.isArray(payload)) {\n input.enqueue(toSdkUserMessage(payload));\n return;\n }\n // Handle text-only messages\n const text = payload?.text ?? \"\";\n input.enqueue(toSdkUserMessage(text));\n },\n async end() {\n try {\n input.close();\n } finally {\n // Simplified process cleanup\n try {\n if (sdk?.abortController) {\n sdk.abortController.abort();\n }\n } catch {}\n }\n },\n onSessionId(cb: (id: string) => void) {\n onSessionIdCb = cb;\n },\n stream(\n handler: (message: SDKMessage, sessionId: string | null) => Promise<void>\n ) {\n if (startedReader) return;\n startedReader = true;\n (async () => {\n try {\n for await (const msg of sdk) {\n // Simplified session ID extraction\n const sid = (msg && (msg.session_id || msg.sessionId)) || null;\n if (sid && sid !== observedSessionId) {\n observedSessionId = sid;\n if (onSessionIdCb) onSessionIdCb(sid);\n }\n await handler(msg, sid);\n }\n // Normal completion\n if (onComplete) await onComplete(false);\n } catch (e) {\n // Error completion\n if (onComplete) await onComplete(true, e);\n }\n })();\n },\n };\n}\nfunction isClaudeConversation(\n conversation: ConversationContext[\"conversation\"]\n): conversation is ClaudeConversation {\n return (\n !!conversation &&\n typeof (conversation as ClaudeConversation).send === \"function\" &&\n typeof (conversation as ClaudeConversation).end === \"function\"\n );\n}\n","/**\n * Console wrapper that suppresses output unless the requested subsystem\n * is enabled in the debug filter.\n */\n\nimport { DebugSubsystem, isDebugEnabledFor } from './debug.js';\n\nexport function createScopedConsole(\n subsystem: DebugSubsystem = \"runner\"\n): Console {\n // Check debug flag on each call, not at creation time, so that\n // environment variables set after module import are respected\n return {\n log: (...args: unknown[]) => {\n if (isDebugEnabledFor(subsystem)) global.console.log(...args);\n },\n warn: (...args: unknown[]) => {\n if (isDebugEnabledFor(subsystem)) global.console.warn(...args);\n },\n error: global.console.error.bind(global.console), // Always show errors\n info: (...args: unknown[]) => {\n if (isDebugEnabledFor(subsystem)) global.console.info(...args);\n },\n debug: (...args: unknown[]) => {\n if (isDebugEnabledFor(subsystem)) global.console.debug(...args);\n },\n } as Console;\n}\n\n// Default console scoped to core runner events\nexport const console = createScopedConsole(\"runner\");\n","export function expandEnv(\n obj: any,\n env: Record<string, string | undefined> = process.env\n): any {\n if (typeof obj === \"string\") {\n return obj.replace(/\\$\\{([^}]+)\\}/g, (match, key) => env[key] || match);\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => expandEnv(item, env));\n }\n\n if (obj && typeof obj === \"object\") {\n const result: Record<string, any> = {};\n for (const [key, value] of Object.entries(obj)) {\n result[key] = expandEnv(value, env);\n }\n return result;\n }\n\n return obj;\n}\n","import type { ModelReasoningEffort as CodexModelReasoningEffort } from \"@northflare/codex-sdk\";\n\nexport type ModelReasoningEffort = \"low\" | \"medium\" | \"high\" | \"xhigh\";\n\nconst REASONING_VALUES: readonly ModelReasoningEffort[] = [\n \"low\",\n \"medium\",\n \"high\",\n \"xhigh\",\n];\n\nexport function parseModelValue(value?: string | null): {\n baseModel?: string;\n reasoningEffort?: ModelReasoningEffort;\n} {\n if (!value) {\n return {};\n }\n\n const [model, possibleEffort] = value.split(\":\");\n if (\n possibleEffort &&\n REASONING_VALUES.includes(possibleEffort as ModelReasoningEffort)\n ) {\n return {\n baseModel: model,\n reasoningEffort: possibleEffort as ModelReasoningEffort,\n };\n }\n\n return { baseModel: value };\n}\n\nexport function mapReasoningEffortForCodex(\n effort?: ModelReasoningEffort\n): CodexModelReasoningEffort | undefined {\n if (!effort) {\n return undefined;\n }\n\n switch (effort) {\n case \"xhigh\":\n // Pass xhigh through directly - Codex SDK now supports it\n return \"xhigh\";\n case \"low\":\n case \"medium\":\n case \"high\":\n return effort;\n default:\n return undefined;\n }\n}\n","import type {\n Thread,\n ThreadEvent,\n ThreadItem,\n ThreadOptions,\n Input,\n UserInput,\n} from \"@northflare/codex-sdk\";\nimport { IRunnerApp } from '../types/runner-interface.js';\nimport { EnhancedRepositoryManager } from './enhanced-repository-manager.js';\nimport { ConversationContext, ConversationConfig, Message } from '../types/index.js';\nimport { statusLineManager } from '../utils/status-line.js';\nimport { createScopedConsole } from '../utils/console.js';\nimport { expandEnv } from '../utils/expand-env.js';\nimport { mapReasoningEffortForCodex, parseModelValue } from '../utils/model.js';\nimport jwt from \"jsonwebtoken\";\nimport fs from \"fs/promises\";\nimport path from \"path\";\nimport { isDebugEnabledFor } from '../utils/debug.js';\nimport { tmpdir } from \"os\";\nimport crypto from \"crypto\";\nimport { simpleGit } from \"simple-git\";\n\nconst console = createScopedConsole(\n isDebugEnabledFor(\"manager\") ? \"manager\" : \"sdk\"\n);\n\nfunction buildSystemPromptWithNorthflare(\n basePrompt?: string,\n northflarePrompt?: string\n): string | undefined {\n const parts = [northflarePrompt, basePrompt]\n .filter((p): p is string => typeof p === \"string\" && p.trim().length > 0)\n .map((p) => p.trim());\n\n if (parts.length === 0) return undefined;\n return parts.join(\"\\n\\n\");\n}\n\nlet codexSdkPromise: Promise<typeof import(\"@northflare/codex-sdk\")> | null =\n null;\n\nasync function loadCodexSdk() {\n if (!codexSdkPromise) {\n codexSdkPromise = import(\"@northflare/codex-sdk\");\n }\n return codexSdkPromise;\n}\n\ntype CodexThreadState = {\n thread: Thread;\n abortController: AbortController | null;\n runPromise: Promise<void> | null;\n};\n\ntype ConversationDetails = {\n id: string;\n objectType: string;\n objectId: string;\n model: string;\n summary?: string | null;\n globalInstructions: string;\n workspaceInstructions: string;\n permissionsMode: string;\n agentSessionId?: string;\n workspaceId?: string;\n threadId?: string;\n systemPrompt?: string;\n northflareSystemPrompt?: string;\n systemPromptMode?: \"append\" | \"replace\";\n};\n\ntype NormalizedItemEvent = {\n type: string;\n content: any;\n subtype?: string;\n toolCalls?: any;\n isError?: boolean;\n};\n\nexport class CodexManager {\n private runner: IRunnerApp;\n private repositoryManager: EnhancedRepositoryManager;\n private threadStates: Map<string, CodexThreadState> = new Map();\n\n constructor(\n runner: IRunnerApp,\n repositoryManager: EnhancedRepositoryManager\n ) {\n this.runner = runner;\n this.repositoryManager = repositoryManager;\n }\n\n async startConversation(\n conversationObjectType: \"Task\" | \"TaskPlan\" | \"ProjectStep\",\n conversationObjectId: string,\n config: ConversationConfig,\n initialMessages: Message[],\n conversationData?: ConversationDetails,\n provider?: \"openai\" | \"openrouter\" | \"groq\"\n ): Promise<ConversationContext> {\n if (!conversationData?.id) {\n throw new Error(\n \"startConversation requires conversationData with a valid conversation.id\"\n );\n }\n\n const conversationId = conversationData.id;\n const agentSessionId = this.resolveSessionId(config, conversationData);\n const pendingSummary =\n this.runner.consumePendingConversationSummary(conversationId);\n const rawSummary =\n typeof conversationData.summary === \"string\"\n ? conversationData.summary\n : pendingSummary;\n const normalizedSummary =\n typeof rawSummary === \"string\"\n ? rawSummary.replace(/\\s+/g, \" \").trim()\n : null;\n\n const rawModel =\n conversationData?.model ||\n (config as any)?.model ||\n (config as any)?.defaultModel ||\n \"openai\";\n const { baseModel, reasoningEffort } = parseModelValue(rawModel);\n const codexReasoningEffort = mapReasoningEffortForCodex(reasoningEffort);\n const normalizedModel = baseModel || rawModel;\n\n // Debug logging for model parsing\n console.log(\"[CodexManager] Model parsing debug:\", {\n rawModel,\n baseModel,\n reasoningEffort,\n codexReasoningEffort,\n normalizedModel,\n });\n\n // Determine the actual provider - can be passed explicitly or detected from config\n const resolvedProvider =\n provider ||\n (config as any)?.providerType ||\n (conversationData as any)?.providerType ||\n \"openai\";\n\n // Optional system prompt handling (matches Northflare/Claude managers)\n const providedSystemPrompt = buildSystemPromptWithNorthflare(\n config.systemPrompt || (conversationData as any)?.systemPrompt,\n (config as any)?.northflareSystemPrompt ||\n (conversationData as any)?.northflareSystemPrompt\n );\n const systemPromptMode =\n config.systemPromptMode ||\n (conversationData as any)?.systemPromptMode ||\n \"append\";\n\n const metadata: Record<string, any> = {\n instructionsInjected: false,\n originalModelValue: rawModel,\n };\n\n metadata[\"hasSystemPrompt\"] = Boolean(providedSystemPrompt);\n metadata[\"systemPromptMode\"] = systemPromptMode;\n\n if (reasoningEffort) {\n metadata[\"modelReasoningEffort\"] = reasoningEffort;\n }\n\n const context: ConversationContext = {\n conversationId,\n agentSessionId,\n conversationObjectType,\n conversationObjectId,\n taskId:\n conversationObjectType === \"Task\" ? conversationObjectId : undefined,\n workspaceId: config.workspaceId,\n status: \"starting\",\n config,\n startedAt: new Date(),\n lastActivityAt: new Date(),\n model: normalizedModel,\n summary: normalizedSummary,\n globalInstructions: conversationData.globalInstructions || \"\",\n workspaceInstructions: conversationData.workspaceInstructions || \"\",\n permissionsMode:\n conversationData.permissionsMode ||\n (config as any)?.permissionsMode ||\n \"all\",\n provider: resolvedProvider,\n metadata,\n };\n\n this.runner.activeConversations_.set(conversationId, context);\n\n console.log(`[CodexManager] Stored conversation context`, {\n conversationId,\n agentSessionId,\n model: context.model,\n permissionsMode: context.permissionsMode,\n });\n\n const workspacePath = await this.resolveWorkspacePath(context, config);\n\n (context.metadata as Record<string, any>)[\"workspacePath\"] = workspacePath;\n\n const githubToken = context.workspaceId\n ? await this.fetchGithubTokens(context.workspaceId)\n : undefined;\n\n const toolToken = this.generateToolToken(context);\n\n let mcpServers: Record<string, any> | undefined;\n if (config.mcpServers && Object.keys(config.mcpServers).length > 0) {\n const expandedServers = expandEnv(config.mcpServers, {\n TOOL_TOKEN: toolToken,\n });\n mcpServers = this.normalizeMcpServersForCodex(expandedServers);\n console.log(\n \"[CodexManager] MCP servers configuration:\",\n JSON.stringify(mcpServers, null, 2)\n );\n (context.metadata as Record<string, any>)[\"mcpServers\"] = mcpServers;\n }\n\n let configOverrides = this.buildConfigOverridesFromMcp(mcpServers);\n\n // Add OpenRouter config overrides if using OpenRouter provider\n if (resolvedProvider === \"openrouter\") {\n const openRouterOverrides = this.buildOpenRouterConfigOverrides();\n configOverrides = {\n ...configOverrides,\n ...openRouterOverrides,\n };\n console.log(\n \"[CodexManager] OpenRouter config overrides:\",\n JSON.stringify(openRouterOverrides, null, 2)\n );\n }\n\n // Inject system prompt via developer_instructions (developer role message)\n if (providedSystemPrompt) {\n const trimmedPrompt = providedSystemPrompt.trim();\n if (trimmedPrompt.length) {\n const systemPromptOverrides: Record<string, unknown> = {\n developer_instructions: trimmedPrompt,\n };\n configOverrides = {\n ...configOverrides,\n ...systemPromptOverrides,\n };\n\n console.log(\"[CodexManager] Applied system prompt overrides\", {\n mode: systemPromptMode,\n hasSystemPrompt: true,\n replacesBase: systemPromptMode === \"replace\",\n });\n }\n }\n\n const envVars = await this.buildEnvVars(\n config,\n githubToken,\n toolToken,\n resolvedProvider\n );\n\n const { Codex } = await loadCodexSdk();\n const codex = new Codex({\n baseUrl:\n (config as any)?.openaiBaseUrl ||\n (config as any)?.codexBaseUrl ||\n process.env[\"OPENAI_BASE_URL\"],\n apiKey:\n (config as any)?.openaiApiKey ||\n (config as any)?.codexApiKey ||\n process.env[\"CODEX_API_KEY\"] ||\n process.env[\"OPENAI_API_KEY\"],\n env: envVars,\n });\n\n // Strip provider prefix (e.g., \"openrouter:\") from model name if present\n const modelName = context.model.includes(\":\")\n ? context.model.split(\":\").slice(1).join(\":\")\n : context.model;\n\n // Debug: log what model name we're using\n console.log(\"[CodexManager] Model name processing:\", {\n contextModel: context.model,\n hasColon: context.model.includes(\":\"),\n modelNameAfterStrip: modelName,\n });\n\n const threadOptions: ThreadOptions = {\n model: modelName,\n workingDirectory: workspacePath,\n sandboxMode: this.mapSandboxMode(context.permissionsMode),\n networkAccessEnabled: this.shouldEnableNetwork(context.permissionsMode),\n webSearchEnabled: true,\n // additionalDirectories: this.getAdditionalDirectories(config),\n configOverrides,\n skipGitRepoCheck: true,\n modelReasoningEffort: codexReasoningEffort,\n };\n\n console.log(\n \"[CodexManager] Thread options:\",\n JSON.stringify(threadOptions, null, 2)\n );\n\n const thread = agentSessionId\n ? codex.resumeThread(agentSessionId, threadOptions)\n : codex.startThread(threadOptions);\n\n this.threadStates.set(conversationId, {\n thread,\n abortController: null,\n runPromise: null,\n });\n\n context.conversation = thread;\n\n // Launch the first turn using the provided initial messages.\n // Supports multimodal (images/documents) by converting to Codex Input.\n if (initialMessages?.length) {\n const initialInput = await this.buildInitialInput(initialMessages, context);\n this.launchTurn(context, initialInput);\n }\n\n return context;\n }\n\n async stopConversation(\n _agentSessionId: string,\n context: ConversationContext,\n isRunnerShutdown: boolean = false,\n reason?: string\n ): Promise<void> {\n (context as any)._stopRequested = true;\n (context as any)._stopReason =\n reason || (isRunnerShutdown ? \"runner_shutdown\" : undefined);\n context.status = \"stopping\";\n\n await this.abortActiveRun(context.conversationId);\n\n try {\n await this._finalizeConversation(\n context,\n false,\n undefined,\n (context as any)._stopReason\n );\n } catch (error) {\n console.error(\n `[CodexManager] Error finalizing conversation ${context.conversationId}:`,\n error\n );\n } finally {\n this.threadStates.delete(context.conversationId);\n }\n\n context.status = \"stopped\";\n }\n\n async resumeConversation(\n conversationObjectType: \"Task\" | \"TaskPlan\" | \"ProjectStep\",\n conversationObjectId: string,\n agentSessionId: string,\n config: ConversationConfig,\n conversationData?: ConversationDetails,\n resumeMessage?: string,\n provider?: \"openai\" | \"openrouter\" | \"groq\"\n ): Promise<string> {\n console.log(`[CodexManager] Resuming conversation ${agentSessionId}`);\n\n const context = await this.startConversation(\n conversationObjectType,\n conversationObjectId,\n { ...config, sessionId: agentSessionId },\n [],\n conversationData,\n provider\n );\n\n if (resumeMessage) {\n const prompt = this.buildPromptForMessage(context, resumeMessage, false);\n this.launchTurn(context, prompt);\n }\n\n return context.agentSessionId;\n }\n\n async sendUserMessage(\n conversationId: string,\n content: any,\n config?: ConversationConfig,\n conversationObjectType?: \"Task\" | \"TaskPlan\" | \"ProjectStep\",\n conversationObjectId?: string,\n conversation?: any,\n agentSessionIdOverride?: string,\n provider?: \"openai\" | \"openrouter\" | \"groq\"\n ): Promise<void> {\n console.log(`[CodexManager] sendUserMessage called`, {\n conversationId,\n hasConfig: !!config,\n });\n\n let context = this.runner.getConversationContext(conversationId);\n\n if (!context && conversation) {\n const conversationDetails = conversation as ConversationDetails;\n const resumeSessionId = this.resolveSessionId(\n config,\n conversationDetails,\n agentSessionIdOverride\n );\n const startConfig: ConversationConfig = {\n ...(config || {}),\n workspaceId:\n conversationDetails.workspaceId || config?.workspaceId || undefined,\n ...(resumeSessionId ? { sessionId: resumeSessionId } : {}),\n };\n\n context = await this.startConversation(\n (conversationObjectType as \"Task\" | \"TaskPlan\") ||\n (conversationDetails.objectType as \"Task\" | \"TaskPlan\"),\n conversationObjectId || conversationDetails.objectId,\n startConfig,\n [],\n conversationDetails,\n provider\n );\n }\n\n if (!context) {\n throw new Error(\n `No active or fetchable conversation found for ${conversationId}`\n );\n }\n\n await this.abortActiveRun(conversationId);\n\n const input = await this.normalizeToInput(content, context, false);\n this.launchTurn(context, input);\n\n context.lastActivityAt = new Date();\n }\n\n private async _handleRunCompletion(\n context: ConversationContext,\n hadError: boolean,\n error?: any\n ): Promise<void> {\n if ((context as any)._finalized) return;\n\n const inFlight = (context as any)._runCompletionInFlight as\n | Promise<void>\n | undefined;\n if (inFlight) return inFlight;\n\n const promise = (async () => {\n\n const isTaskConversation = context.conversationObjectType === \"Task\";\n const stopRequested = (context as any)._stopRequested === true;\n const taskHandle = (context as any).taskHandle as any;\n const shouldRunGitFlow =\n context.config.useWorktrees !== false &&\n isTaskConversation &&\n !!taskHandle &&\n taskHandle.branch !== \"local\";\n\n if (!shouldRunGitFlow || hadError || stopRequested) {\n await this._finalizeConversation(context, hadError, error);\n return;\n }\n\n const taskId = context.conversationObjectId;\n const baseBranch =\n (context.config.repository?.branch as string | undefined) || \"main\";\n\n try {\n const taskState = await this.repositoryManager.getTaskState(taskId);\n const taskRepoInfo = await this.repositoryManager.getTaskRepoInfo(taskId);\n\n if (\n !taskState ||\n !taskRepoInfo ||\n !taskRepoInfo.worktreePath ||\n taskState.branch === \"local\"\n ) {\n await this._finalizeConversation(context, false);\n return;\n }\n\n const isLocalRepo = taskRepoInfo.repoKey.startsWith(\"local__\");\n const mergeWorkdir = isLocalRepo\n ? taskRepoInfo.controlPath\n : taskRepoInfo.worktreePath;\n\n // If we already have unresolved conflicts, immediately ask the agent to resolve them.\n const taskGit = simpleGit(taskRepoInfo.worktreePath);\n const initialTaskStatus = await taskGit.status();\n if (initialTaskStatus.conflicted.length > 0) {\n await this._resumeForGitConflictResolution(context, {\n kind: \"conflicts\",\n baseBranch,\n conflicts: initialTaskStatus.conflicted,\n workdir: taskRepoInfo.worktreePath,\n });\n return;\n }\n\n if (isLocalRepo && mergeWorkdir !== taskRepoInfo.worktreePath) {\n const mergeGit = simpleGit(mergeWorkdir);\n const mergeStatus = await mergeGit.status();\n if (mergeStatus.conflicted.length > 0) {\n await this._resumeForGitConflictResolution(context, {\n kind: \"conflicts\",\n baseBranch,\n conflicts: mergeStatus.conflicted,\n workdir: mergeWorkdir,\n });\n return;\n }\n }\n\n // Ensure we're on the task branch for commit/rebase operations.\n const currentBranch = (\n await taskGit.revparse([\"--abbrev-ref\", \"HEAD\"])\n ).trim();\n if (currentBranch !== taskState.branch) {\n await taskGit.checkout(taskState.branch);\n }\n\n const status = await taskGit.status();\n if (!status.isClean()) {\n await this.repositoryManager.stageAll(taskId);\n try {\n const previousCommitCount = (taskState as any)?.commitCount ?? 0;\n const baseSubject =\n (context.summary ?? \"\").replace(/\\s+/g, \" \").trim() ||\n `Task ${taskId}`;\n const message =\n previousCommitCount > 0\n ? `${baseSubject} (followup #${previousCommitCount})`\n : baseSubject;\n await this.repositoryManager.commit(taskId, message);\n } catch (commitError) {\n const msg =\n commitError instanceof Error\n ? commitError.message\n : String(commitError);\n if (!msg.toLowerCase().includes(\"nothing to commit\")) {\n throw commitError;\n }\n }\n }\n\n const integrateResult = await this.repositoryManager.integrateTask(\n taskId,\n baseBranch,\n \"no-ff\"\n );\n if (!integrateResult.success) {\n await this._resumeForGitConflictResolution(context, {\n kind: integrateResult.phase,\n baseBranch,\n conflicts: integrateResult.conflicts ?? [],\n workdir: integrateResult.conflictWorkdir,\n error: integrateResult.error,\n });\n return;\n }\n\n // Worktree is no longer needed after a successful merge; preserve the branch\n await this.repositoryManager.removeTaskWorktree(taskId, {\n preserveBranch: true,\n });\n\n const wsId = context.config.workspaceId || context.workspaceId;\n const repoUrl = context.config.repository?.url;\n if (wsId && repoUrl) {\n await this.repositoryManager.syncWorkspaceWorktree(wsId, repoUrl, baseBranch);\n }\n\n await this._finalizeConversation(context, false);\n } catch (mergeError) {\n console.error(\"[CodexManager] Post-task git flow failed\", mergeError);\n await this._finalizeConversation(context, true, mergeError);\n }\n })();\n\n (context as any)._runCompletionInFlight = promise.finally(() => {\n delete (context as any)._runCompletionInFlight;\n });\n return (context as any)._runCompletionInFlight;\n }\n\n private async _resumeForGitConflictResolution(\n context: ConversationContext,\n payload: {\n kind: \"conflicts\" | \"rebase\" | \"merge\";\n baseBranch: string;\n conflicts: string[];\n workdir: string;\n error?: string;\n }\n ): Promise<void> {\n const { kind, baseBranch, conflicts, workdir, error } = payload;\n\n const conflictsList = conflicts?.length\n ? `\\n\\nConflicted files:\\n${conflicts.map((f) => `- ${f}`).join(\"\\n\")}`\n : \"\";\n const workdirHint = workdir ? `\\n\\nWork directory:\\n- ${workdir}` : \"\";\n const errorHint = error ? `\\n\\nError:\\n${error}` : \"\";\n const hasConflicts = !!conflicts?.length;\n\n let instruction: string;\n if (kind === \"rebase\") {\n instruction = hasConflicts\n ? `<system-instructions>\\nA git rebase onto \\`${baseBranch}\\` produced merge conflicts.${conflictsList}${workdirHint}${errorHint}\\n\\nPlease resolve the conflicts in that directory, then run:\\n- git add -A\\n- git rebase --continue\\n\\nWhen the rebase finishes cleanly, reply briefly so I can retry the integration.\\n</system-instructions>`\n : `<system-instructions>\\nA git rebase onto \\`${baseBranch}\\` failed.${workdirHint}${errorHint}\\n\\nNo conflicted files were reported. Please run:\\n- git status\\n\\nFix the error (or complete/abort any in-progress git operation) and reply briefly so I can retry the integration.\\n</system-instructions>`;\n } else if (kind === \"merge\") {\n instruction = hasConflicts\n ? `<system-instructions>\\nA git merge into \\`${baseBranch}\\` produced merge conflicts.${conflictsList}${workdirHint}${errorHint}\\n\\nPlease resolve the conflicts in that directory, then run:\\n- git add -A\\n- git commit -m \\\"Resolve merge conflicts for ${context.conversationObjectId}\\\"\\n\\nWhen the working tree is clean, reply briefly so I can retry the integration.\\n</system-instructions>`\n : `<system-instructions>\\nA git merge into \\`${baseBranch}\\` failed.${workdirHint}${errorHint}\\n\\nNo conflicted files were reported. Please run:\\n- git status\\n\\nFix the error (or complete/abort any in-progress git operation) and reply briefly so I can retry the integration.\\n</system-instructions>`;\n } else {\n instruction = `<system-instructions>\\nGit has unresolved conflicts.${conflictsList}${workdirHint}${errorHint}\\n\\nPlease resolve the conflicts in that directory and complete the in-progress git operation (rebase or merge). When the working tree is clean, reply briefly so I can retry the integration.\\n</system-instructions>`;\n }\n\n const conversationData: ConversationDetails = {\n id: context.conversationId,\n objectType: context.conversationObjectType,\n objectId: context.conversationObjectId,\n model: context.model,\n summary: context.summary ?? null,\n globalInstructions: context.globalInstructions,\n workspaceInstructions: context.workspaceInstructions,\n permissionsMode: context.permissionsMode,\n agentSessionId: context.agentSessionId,\n workspaceId: context.workspaceId,\n };\n\n await this.resumeConversation(\n context.conversationObjectType,\n context.conversationObjectId,\n context.agentSessionId,\n context.config,\n conversationData,\n instruction,\n context.provider as \"openai\" | \"openrouter\" | \"groq\"\n );\n }\n\n private async buildEnvVars(\n config: ConversationConfig,\n githubToken?: string,\n toolToken?: string,\n provider?: string\n ): Promise<Record<string, string>> {\n const envVars: Record<string, string> = {\n ...(Object.fromEntries(\n Object.entries(process.env).filter(([, value]) => value !== undefined)\n ) as Record<string, string>),\n };\n\n if (config.codexAuth?.accessToken) {\n envVars[\"OPENAI_ACCESS_TOKEN\"] = config.codexAuth.accessToken;\n } else if (config.accessToken) {\n envVars[\"OPENAI_ACCESS_TOKEN\"] = config.accessToken;\n }\n\n if (githubToken) {\n envVars[\"GITHUB_TOKEN\"] = githubToken;\n }\n\n if (toolToken) {\n envVars[\"TOOL_TOKEN\"] = toolToken;\n }\n\n if (isDebugEnabledFor(\"sdk\")) {\n envVars[\"DEBUG\"] = \"1\";\n }\n\n // Add OpenRouter/Groq API keys when using Northflare-routed providers\n if (provider === \"openrouter\" || provider === \"groq\") {\n const openRouterApiKey =\n (config as any).openRouterApiKey ||\n process.env[\"OPENROUTER_API_KEY\"];\n if (openRouterApiKey) {\n envVars[\"OPENROUTER_API_KEY\"] = openRouterApiKey;\n }\n\n const groqApiKey =\n (config as any).groqApiKey ||\n process.env[\"GROQ_API_KEY\"];\n if (groqApiKey) {\n envVars[\"GROQ_API_KEY\"] = groqApiKey;\n }\n\n if (!openRouterApiKey && !groqApiKey) {\n console.warn(\n \"[CodexManager] OpenRouter/Groq provider selected but no API key found\"\n );\n }\n }\n\n const codexHome = await this.ensureCodexAuthHome(config);\n if (codexHome) {\n envVars[\"CODEX_HOME\"] = codexHome;\n }\n\n return envVars;\n }\n\n private async ensureCodexAuthHome(\n config: ConversationConfig\n ): Promise<string | null> {\n if (!config.codexAuth) {\n return null;\n }\n\n const runnerId = this.runner.getRunnerId();\n const dataDir = this.runner.config_.dataDir;\n\n if (!runnerId || !dataDir) {\n console.warn(\n \"[CodexManager] Missing runnerId or dataDir; cannot prepare Codex auth directory\"\n );\n return null;\n }\n\n const codexDir = path.join(dataDir, \"codex\", runnerId);\n const authPayload = {\n OPENAI_API_KEY: null,\n tokens: {\n id_token: config.codexAuth.idToken,\n access_token: config.codexAuth.accessToken,\n refresh_token: \"\",\n account_id: config.codexAuth.accountId,\n },\n last_refresh: config.codexAuth.lastRefresh || new Date().toISOString(),\n };\n\n try {\n await fs.mkdir(codexDir, { recursive: true });\n await fs.writeFile(\n path.join(codexDir, \"auth.json\"),\n JSON.stringify(authPayload, null, 2),\n \"utf-8\"\n );\n return codexDir;\n } catch (error) {\n console.error(\n \"[CodexManager] Failed to persist Codex auth configuration:\",\n error\n );\n throw new Error(\n \"Runner failed to persist Codex credentials. Check runner logs for details.\"\n );\n }\n }\n\n private buildPromptForMessage(\n context: ConversationContext,\n text: string,\n forceInstructions: boolean\n ): string {\n const trimmed = text ?? \"\";\n const instructions = this.getInstructionPrefix(context);\n\n const metadata =\n (context.metadata as Record<string, any>) || ({} as Record<string, any>);\n const shouldInjectInstructions =\n forceInstructions || !metadata[\"instructionsInjected\"];\n\n if (instructions && shouldInjectInstructions) {\n metadata[\"instructionsInjected\"] = true;\n context.metadata = metadata;\n return `${instructions}\\n\\n${trimmed}`.trim();\n }\n\n return trimmed;\n }\n\n private getInstructionPrefix(context: ConversationContext): string {\n const parts: string[] = [];\n\n if (context.globalInstructions) {\n parts.push(\n `<global-instructions>\\n${context.globalInstructions}\\n</global-instructions>`\n );\n }\n\n if (context.workspaceInstructions) {\n parts.push(\n `<workspace-instructions>\\n${context.workspaceInstructions}\\n</workspace-instructions>`\n );\n }\n\n return parts.join(\"\\n\\n\");\n }\n\n private formatInitialMessages(initialMessages: Message[]): string {\n return initialMessages\n .map((msg) => {\n const role = (msg.role as string) || \"user\";\n const content = this.normalizeToText(msg.content);\n return `<${role}-message>\\n${content}\\n</${role}-message>`;\n })\n .join(\"\\n\\n\");\n }\n\n private async buildInitialInput(\n initialMessages: Message[],\n context: ConversationContext\n ): Promise<Input> {\n const hasMultimodal = initialMessages.some((msg) =>\n this.hasMultimodalContent((msg as any).content)\n );\n\n if (!hasMultimodal) {\n const promptText = this.formatInitialMessages(initialMessages);\n return this.buildPromptForMessage(context, promptText, true);\n }\n\n // Preserve role markers while keeping image blocks attached\n const combinedBlocks: Array<any> = [];\n\n for (const msg of initialMessages) {\n const role = (msg.role as string) || \"user\";\n const content = (msg as any).content;\n\n // Start role section\n combinedBlocks.push({\n type: \"text\",\n text: `<${role}-message>`,\n });\n\n if (Array.isArray(content)) {\n for (const item of content) {\n if (!item || typeof item !== \"object\") continue;\n if (item.type === \"text\" && typeof item.text === \"string\") {\n combinedBlocks.push({ type: \"text\", text: item.text });\n } else if (item.type === \"image\" || item.type === \"document\") {\n combinedBlocks.push(item);\n }\n }\n } else {\n combinedBlocks.push({\n type: \"text\",\n text: this.normalizeToText(content),\n });\n }\n\n // Close role section\n combinedBlocks.push({\n type: \"text\",\n text: `</${role}-message>`,\n });\n }\n\n const input = await this.normalizeToInput(combinedBlocks, context, true);\n if (isDebugEnabledFor(\"manager\") || isDebugEnabledFor(\"sdk\")) {\n console.log(\"[CodexManager] buildInitialInput multimodal payload\", {\n conversationId: context.conversationId,\n blocks: combinedBlocks.map((b) => b.type),\n inputType: Array.isArray(input) ? \"array\" : \"string\",\n textItems: Array.isArray(input)\n ? input.filter((i: any) => i.type === \"text\").length\n : 1,\n imageItems: Array.isArray(input)\n ? input.filter((i: any) => i.type === \"local_image\").length\n : 0,\n });\n }\n return input;\n }\n\n private launchTurn(context: ConversationContext, prompt: Input): void {\n const state = this.threadStates.get(context.conversationId);\n\n if (!state || !state.thread) {\n throw new Error(\n `Thread state missing for conversation ${context.conversationId}`\n );\n }\n\n const abortController = new AbortController();\n state.abortController = abortController;\n\n context.lastActivityAt = new Date();\n\n const runPromise = this.streamThreadEvents(\n context,\n state.thread,\n prompt,\n abortController\n );\n\n state.runPromise = runPromise;\n\n runPromise\n .catch((error) => {\n if (!this.isAbortError(error)) {\n console.error(\n `[CodexManager] Run failed for ${context.conversationId}:`,\n error\n );\n this._handleConversationError(context, error as Error);\n }\n })\n .finally(() => {\n if (state.runPromise === runPromise) {\n state.runPromise = null;\n }\n if (state.abortController === abortController) {\n state.abortController = null;\n }\n });\n }\n\n private async streamThreadEvents(\n context: ConversationContext,\n thread: Thread,\n prompt: Input,\n abortController: AbortController\n ): Promise<void> {\n try {\n const { events } = await thread.runStreamed(prompt, {\n signal: abortController.signal,\n });\n\n for await (const event of events) {\n await this.handleThreadEvent(context, event);\n }\n } catch (error) {\n if (this.isAbortError(error)) {\n console.log(\n `[CodexManager] Turn aborted for ${context.conversationId}`\n );\n return;\n }\n\n throw error;\n }\n }\n\n private async abortActiveRun(conversationId: string): Promise<void> {\n const state = this.threadStates.get(conversationId);\n if (!state || !state.runPromise) return;\n\n if (state.abortController) {\n state.abortController.abort();\n }\n\n try {\n await state.runPromise;\n } catch (error) {\n if (!this.isAbortError(error)) {\n console.warn(\n `[CodexManager] Run aborted with error for ${conversationId}:`,\n error\n );\n }\n }\n }\n\n private async handleThreadEvent(\n context: ConversationContext,\n event: ThreadEvent\n ): Promise<void> {\n try {\n this.logRawThreadEvent(event);\n\n switch (event.type) {\n case \"thread.started\": {\n await this.handleThreadStarted(context, event.thread_id);\n break;\n }\n case \"turn.started\": {\n context.status = \"active\";\n await this.sendAgentMessage(context, \"system\", {\n subtype: \"turn.started\",\n content: [\n {\n type: \"text\",\n text: `Turn started at ${new Date().toISOString()}`,\n },\n ],\n });\n break;\n }\n case \"turn.completed\": {\n await this.sendAgentMessage(context, \"result\", {\n subtype: \"turn.completed\",\n content: [\n {\n type: \"usage\",\n usage: event.usage,\n },\n ],\n });\n context.status = \"stopped\";\n await this._handleRunCompletion(context, false);\n break;\n }\n case \"turn.failed\": {\n const error = new Error(event.error?.message || \"Turn failed\");\n await this.sendAgentMessage(context, \"error\", {\n subtype: \"turn.failed\",\n content: [\n {\n type: \"text\",\n text: error.message,\n },\n ],\n isError: true,\n });\n await this._handleConversationError(context, error);\n context.status = \"stopped\";\n await this._finalizeConversation(context, true, error, \"turn_failed\");\n break;\n }\n case \"item.started\":\n case \"item.updated\":\n case \"item.completed\": {\n await this.forwardItemEvent(\n context,\n event.item,\n event.type.split(\".\")[1] as \"started\" | \"updated\" | \"completed\"\n );\n break;\n }\n case \"error\": {\n const fatalError = new Error(event.message || \"Unknown error\");\n await this.sendAgentMessage(context, \"error\", {\n subtype: \"thread.error\",\n content: [{ type: \"text\", text: fatalError.message }],\n isError: true,\n });\n await this._handleConversationError(context, fatalError);\n context.status = \"stopped\";\n await this._finalizeConversation(\n context,\n true,\n fatalError,\n \"thread_error\"\n );\n break;\n }\n }\n } catch (error) {\n console.error(\"[CodexManager] Failed to handle thread event\", {\n event,\n error,\n });\n }\n }\n\n private async forwardItemEvent(\n context: ConversationContext,\n item: ThreadItem,\n phase: \"started\" | \"updated\" | \"completed\"\n ): Promise<void> {\n const normalized = this.normalizeItemEvent(context, item, phase);\n if (!normalized) return;\n\n const { subtype, content, isError, toolCalls, type } = normalized;\n const payload: {\n subtype?: string;\n content: any;\n toolCalls?: any;\n isError?: boolean;\n } = {\n subtype,\n content,\n isError,\n };\n\n if (toolCalls) {\n payload.toolCalls = toolCalls;\n }\n\n await this.sendAgentMessage(context, type, payload);\n }\n\n private normalizeItemEvent(\n context: ConversationContext,\n item: ThreadItem,\n phase: \"started\" | \"updated\" | \"completed\"\n ): NormalizedItemEvent | null {\n switch (item.type) {\n case \"agent_message\": {\n if (phase !== \"completed\") return null;\n return {\n type: \"assistant\",\n content: [\n {\n type: \"text\",\n text: item.text || \"\",\n },\n ],\n };\n }\n case \"reasoning\": {\n return {\n type: \"thinking\",\n content: [\n {\n type: \"thinking\",\n thinking: item.text,\n text: item.text,\n phase,\n },\n ],\n };\n }\n case \"command_execution\": {\n // Namespace command_execution tool use IDs so they don't collide\n // with MCP tool call IDs that may reuse the same raw item.id.\n const internalNamespace = \"codex_command\";\n const toolUseId = this.buildToolUseId(\n context,\n `${internalNamespace}:${item.id}`\n );\n const timestamp = new Date().toISOString();\n const isTerminal =\n phase === \"completed\" ||\n item.status === \"completed\" ||\n item.status === \"failed\";\n\n if (!isTerminal) {\n if (phase !== \"started\") {\n return null;\n }\n\n return {\n type: \"assistant\",\n subtype: \"tool_use\",\n content: [\n {\n toolCalls: [\n {\n id: toolUseId,\n name: \"codex_command\",\n arguments: {\n command: item.command,\n status: item.status,\n },\n status: item.status,\n },\n ],\n timestamp,\n },\n ],\n };\n }\n\n const exitCode =\n typeof item.exit_code === \"number\" ? item.exit_code : null;\n const isError = item.status === \"failed\" || (exitCode ?? 0) !== 0;\n\n return {\n type: \"tool_result\",\n subtype: \"tool_result\",\n content: [\n {\n type: \"tool_result\",\n tool_use_id: toolUseId,\n content: {\n kind: \"codex_command_result\",\n command: item.command,\n output: item.aggregated_output || \"\",\n exitCode,\n status: item.status,\n },\n timestamp,\n },\n ],\n isError,\n };\n }\n case \"file_change\": {\n if (phase === \"updated\") return null;\n return {\n type: \"file_change\",\n subtype: \"file_change\",\n content: [\n {\n type: \"file_change\",\n changes: item.changes,\n status: item.status,\n },\n ],\n };\n }\n case \"mcp_tool_call\": {\n const toolName = this.buildMcpToolName(item.server, item.tool);\n // Namespace MCP tool call IDs with the MCP tool name so they don't\n // collide with internal tool IDs or MCP calls from other servers.\n const namespacedRawId = `mcp:${toolName}:${item.id}`;\n const toolUseId = this.buildToolUseId(context, namespacedRawId);\n\n if (item.status === \"in_progress\" || phase !== \"completed\") {\n return {\n type: \"assistant\",\n subtype: \"tool_use\",\n content: [\n {\n toolCalls: [\n {\n id: toolUseId,\n name: toolName,\n arguments: item.arguments,\n server: item.server,\n tool: item.tool,\n status: item.status,\n },\n ],\n timestamp: new Date().toISOString(),\n },\n ],\n };\n }\n\n if (item.status === \"failed\") {\n return {\n type: \"error\",\n subtype: \"tool_result\",\n content: [\n {\n type: \"text\",\n text: item.error?.message || \"Tool call failed\",\n tool_use_id: toolUseId,\n tool_name: toolName,\n timestamp: new Date().toISOString(),\n },\n ],\n isError: true,\n };\n }\n\n return {\n type: \"tool_result\",\n subtype: \"tool_result\",\n content: [\n {\n type: \"tool_result\",\n subtype: \"tool_result\",\n tool_use_id: toolUseId,\n content: item.result?.content || [],\n structured_content: item.result?.structured_content,\n metadata: {\n server: item.server,\n tool: item.tool,\n name: toolName,\n original_tool_use_id: item.id,\n },\n timestamp: new Date().toISOString(),\n },\n ],\n };\n }\n case \"web_search\": {\n return {\n type: \"system\",\n subtype: `web_search.${phase}`,\n content: [\n {\n type: \"web_search\",\n query: item.query,\n status: phase,\n },\n ],\n };\n }\n case \"todo_list\": {\n return {\n type: \"system\",\n subtype: \"todo_list\",\n content: [\n {\n type: \"todo_list\",\n items: item.items,\n phase,\n },\n ],\n };\n }\n case \"error\": {\n return {\n type: \"error\",\n subtype: `item.${phase}`,\n content: [\n {\n type: \"text\",\n text: item.message,\n },\n ],\n isError: true,\n };\n }\n default:\n return null;\n }\n }\n\n private async sendAgentMessage(\n context: ConversationContext,\n type: string,\n {\n subtype,\n content,\n toolCalls,\n isError,\n }: {\n subtype?: string;\n content: any;\n toolCalls?: any;\n isError?: boolean;\n }\n ): Promise<void> {\n const normalizedContent = Array.isArray(content)\n ? content\n : content\n ? [content]\n : [];\n\n const payload = {\n taskId: context.taskId,\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n agentSessionId: context.agentSessionId,\n type,\n subtype,\n content: normalizedContent,\n toolCalls,\n isError: Boolean(isError),\n messageId: this.generateMessageId(context),\n timestamp: new Date().toISOString(),\n };\n\n if (isDebugEnabledFor(\"manager\")) {\n console.log(\"[CodexManager] Sending message.agent\", payload);\n }\n\n await this.runner.notify(\"message.agent\", payload);\n }\n\n private async handleThreadStarted(\n context: ConversationContext,\n threadId: string\n ): Promise<void> {\n if (!threadId || threadId === context.agentSessionId) {\n return;\n }\n\n const oldSessionId = context.agentSessionId;\n context.agentSessionId = threadId;\n\n await this.runner.notify(\"agentSessionId.changed\", {\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n oldAgentSessionId: oldSessionId,\n newAgentSessionId: threadId,\n });\n }\n\n private mapSandboxMode(\n permissionsMode?: string\n ): \"read-only\" | \"workspace-write\" | \"danger-full-access\" {\n const mode = (permissionsMode || \"\").toLowerCase();\n if (mode === \"read\" || mode === \"read_only\") {\n return \"read-only\";\n }\n // \"project\" mode allows bash but no file writes - Codex doesn't have fine-grained control,\n // so we use workspace-write which allows both bash and file writes\n if (mode === \"project\" || mode === \"workspace\" || mode === \"workspace-write\") {\n return \"workspace-write\";\n }\n return \"danger-full-access\";\n }\n\n private shouldEnableNetwork(permissionsMode?: string): boolean {\n const mode = (permissionsMode || \"\").toLowerCase();\n // project mode allows network (for fetching dependencies, running tests, etc.)\n if (mode === \"project\") return true;\n return mode !== \"read\" && mode !== \"read_only\";\n }\n\n private getAdditionalDirectories(\n config: ConversationConfig\n ): string[] | undefined {\n const additionalDirs: string[] = [];\n if (config.runnerRepoPath) {\n additionalDirs.push(config.runnerRepoPath);\n }\n return additionalDirs.length ? additionalDirs : undefined;\n }\n\n private buildConfigOverridesFromMcp(\n mcpServers?: Record<string, any>\n ): Record<string, unknown> | undefined {\n if (!mcpServers) return undefined;\n const overrides: Record<string, unknown> = {};\n\n for (const [serverName, config] of Object.entries(mcpServers)) {\n this.flattenOverrideObject(\n `mcp_servers.${serverName}`,\n config,\n overrides\n );\n }\n\n return Object.keys(overrides).length ? overrides : undefined;\n }\n\n /**\n * Build Codex config overrides for OpenRouter provider.\n * These correspond to the Codex CLI flags:\n * -c model_provider=openrouter\n * -c model_providers.openrouter.name=openrouter\n * -c model_providers.openrouter.base_url=https://openrouter.ai/api/v1\n * -c model_providers.openrouter.env_key=OPENROUTER_API_KEY\n */\n private buildOpenRouterConfigOverrides(): Record<string, unknown> {\n return {\n model_provider: \"openrouter\",\n \"model_providers.openrouter.name\": \"openrouter\",\n \"model_providers.openrouter.base_url\": \"https://openrouter.ai/api/v1\",\n \"model_providers.openrouter.env_key\": \"OPENROUTER_API_KEY\",\n };\n }\n\n private normalizeMcpServersForCodex(\n mcpServers: Record<string, any>\n ): Record<string, any> {\n const normalized: Record<string, any> = {};\n for (const [serverName, config] of Object.entries(mcpServers)) {\n normalized[serverName] = this.stripAuthorizationHeader(config);\n }\n return normalized;\n }\n\n private buildMcpToolName(server?: string, tool?: string): string {\n const safeServer = (server || \"unknown\").trim() || \"unknown\";\n const safeTool = (tool || \"unknown\").trim() || \"unknown\";\n return `mcp__${safeServer}__${safeTool}`;\n }\n\n private logRawThreadEvent(event: ThreadEvent): void {\n if (!isDebugEnabledFor(\"sdk\")) {\n return;\n }\n\n try {\n console.log(\n \"[CodexManager] RAW Codex event FULL:\",\n this.safeStringify(event)\n );\n\n const summary: Record<string, unknown> = {\n type: event?.type,\n keys: Object.keys((event as Record<string, unknown>) || {}),\n hasItem: Boolean((event as any)?.item),\n itemType: (event as any)?.item?.type,\n hasUsage: Boolean((event as any)?.usage),\n threadId: (event as any)?.thread_id,\n turnId: (event as any)?.turn_id,\n };\n\n console.log(\"[CodexManager] RAW Codex event summary:\", summary);\n\n if ((event as any)?.item) {\n console.log(\n \"[CodexManager] RAW Codex event item:\",\n this.safeStringify((event as any).item)\n );\n }\n\n if ((event as any)?.usage) {\n console.log(\"[CodexManager] RAW Codex usage:\", (event as any).usage);\n }\n } catch (error) {\n console.warn(\"[CodexManager] Failed to log raw Codex event:\", error);\n }\n }\n\n private safeStringify(value: any): string {\n const seen = new WeakSet();\n return JSON.stringify(\n value,\n (key, nested) => {\n if (typeof nested === \"function\") return undefined;\n if (typeof nested === \"bigint\") return nested.toString();\n if (typeof nested === \"object\" && nested !== null) {\n if (seen.has(nested)) return \"[Circular]\";\n seen.add(nested);\n }\n return nested;\n },\n 2\n );\n }\n\n private buildToolUseId(context: ConversationContext, rawId: string): string {\n const scope =\n context.agentSessionId ||\n context.conversationId ||\n context.conversationObjectId ||\n \"codex\";\n return `${scope}:${rawId}`;\n }\n\n private stripAuthorizationHeader(config: any): any {\n if (!config || typeof config !== \"object\" || Array.isArray(config)) {\n return config;\n }\n\n const normalized = { ...config };\n if (\n normalized.bearer_token_env_var &&\n normalized.headers &&\n typeof normalized.headers === \"object\" &&\n !Array.isArray(normalized.headers)\n ) {\n const headers = { ...normalized.headers };\n delete headers[\"Authorization\"];\n if (Object.keys(headers).length === 0) {\n delete normalized.headers;\n } else {\n normalized.headers = headers;\n }\n }\n\n return normalized;\n }\n\n private flattenOverrideObject(\n prefix: string,\n value: any,\n target: Record<string, unknown>\n ): void {\n if (value === undefined) {\n return;\n }\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n target[prefix] = value;\n return;\n }\n\n const entries = Object.entries(value);\n if (!entries.length) {\n target[prefix] = {};\n return;\n }\n\n for (const [key, nested] of entries) {\n this.flattenOverrideObject(`${prefix}.${key}`, nested, target);\n }\n }\n\n private async resolveWorkspacePath(\n context: ConversationContext,\n config: ConversationConfig\n ): Promise<string> {\n let workspacePath: string;\n const workspaceId = config.workspaceId;\n const useWorktrees = config.useWorktrees !== false;\n\n if (config.runnerRepoPath) {\n workspacePath = config.runnerRepoPath;\n console.log(`[CodexManager] Using local workspace path ${workspacePath}`);\n\n if (context.conversationObjectType === \"Task\" && workspaceId) {\n const hasGitDir = await fs\n .access(path.join(workspacePath, \".git\"))\n .then(() => true)\n .catch(() => false);\n\n if (hasGitDir && useWorktrees) {\n const repoUrl = (config.repository?.url as string) || `file://${workspacePath}`;\n const baseBranch = (config.repository?.branch as string) || \"main\";\n\n const taskHandle = await this.repositoryManager.createTaskWorktree(\n context.conversationObjectId,\n workspaceId,\n repoUrl,\n baseBranch,\n config.githubToken\n );\n (context as any).taskHandle = taskHandle;\n workspacePath = taskHandle.worktreePath;\n }\n }\n return workspacePath;\n }\n\n if (\n context.conversationObjectType === \"Task\" &&\n config.repository &&\n workspaceId &&\n useWorktrees\n ) {\n if (!config.repository.url) {\n throw new Error(\"Repository URL is required for task conversations\");\n }\n\n const taskHandle = await this.repositoryManager.createTaskWorktree(\n context.conversationObjectId,\n workspaceId,\n config.repository.url,\n config.repository.branch,\n config.githubToken\n );\n (context as any).taskHandle = taskHandle;\n workspacePath = taskHandle.worktreePath;\n return workspacePath;\n }\n\n if (config.repository && workspaceId) {\n if (config.repository.type === \"local\" && config.repository.localPath) {\n workspacePath = config.repository.localPath;\n return workspacePath;\n }\n\n workspacePath = await this.repositoryManager.checkoutRepository(\n workspaceId,\n config.repository.url,\n config.repository.branch,\n config.githubToken\n );\n return workspacePath;\n }\n\n if (workspaceId) {\n workspacePath =\n await this.repositoryManager.getWorkspacePath(workspaceId);\n return workspacePath;\n }\n\n return process.cwd();\n }\n\n private async fetchGithubTokens(\n workspaceId: string\n ): Promise<string | undefined> {\n try {\n const response = await fetch(\n `${this.runner.config_.orchestratorUrl}/api/runner/tokens?workspaceId=${workspaceId}`,\n {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${process.env[\"NORTHFLARE_RUNNER_TOKEN\"]}`,\n },\n }\n );\n\n if (!response.ok) {\n console.error(\n `[CodexManager] Failed to fetch GitHub tokens: ${response.status}`\n );\n return undefined;\n }\n\n const data = (await response.json()) as { githubToken?: string };\n return data.githubToken;\n } catch (error) {\n console.error(\"[CodexManager] Error fetching GitHub tokens\", error);\n return undefined;\n }\n }\n\n private generateToolToken(context: ConversationContext): string | undefined {\n if (!context.config.mcpServers) return undefined;\n\n const runnerToken = process.env[\"NORTHFLARE_RUNNER_TOKEN\"];\n const runnerUid = this.runner.getRunnerUid();\n\n if (!runnerToken || !runnerUid) return undefined;\n\n return jwt.sign(\n {\n conversationId: context.conversationId,\n runnerUid,\n },\n runnerToken,\n {\n expiresIn: \"60m\",\n }\n );\n }\n\n /**\n * Detect whether incoming content contains multimodal blocks (image/document).\n */\n private hasMultimodalContent(value: any): boolean {\n if (!Array.isArray(value)) return false;\n return value.some(\n (item) =>\n item &&\n typeof item === \"object\" &&\n (item.type === \"image\" || item.type === \"document\")\n );\n }\n\n /**\n * Normalize incoming content into the Codex SDK Input shape.\n * - Text-only -> single string (lets SDK do fast path)\n * - Multimodal -> [{ text }, ...{ local_image }]\n */\n private async normalizeToInput(\n value: any,\n context: ConversationContext,\n forceInstructions: boolean\n ): Promise<Input> {\n if (Array.isArray(value) && this.hasMultimodalContent(value)) {\n const inputs: UserInput[] = [];\n\n // Collect any text blocks (or document placeholders) to keep context\n const textChunks: string[] = [];\n for (const item of value) {\n if (!item || typeof item !== \"object\") continue;\n if (item.type === \"text\" && typeof item.text === \"string\") {\n textChunks.push(item.text);\n } else if (item.type === \"document\" && item.source) {\n const docUrl =\n item.source.type === \"url\" ? item.source.url : item.source.data;\n if (docUrl) {\n textChunks.push(`[Document: ${docUrl}]`);\n }\n }\n }\n\n const textPart = this.buildPromptForMessage(\n context,\n textChunks.join(\" \").trim(),\n forceInstructions\n );\n if (textPart) {\n inputs.push({ type: \"text\", text: textPart });\n }\n\n // Download image blocks to temp files and attach as local_image\n const imagePaths: string[] = [];\n for (const item of value) {\n if (!item || typeof item !== \"object\" || item.type !== \"image\" || !item.source) {\n continue;\n }\n const imageUrl =\n item.source.type === \"url\" ? item.source.url : item.source.data;\n if (!imageUrl) continue;\n\n const localPath = await this.downloadImageToTemp(imageUrl);\n inputs.push({ type: \"local_image\", path: localPath });\n imagePaths.push(localPath);\n }\n\n // If no text and instructions were never injected, inject an empty prompt to carry instructions\n if (!inputs.some((i) => i.type === \"text\")) {\n const instructionOnly = this.buildPromptForMessage(context, \"\", forceInstructions);\n if (instructionOnly) {\n inputs.unshift({ type: \"text\", text: instructionOnly });\n }\n }\n\n if (isDebugEnabledFor(\"manager\") || isDebugEnabledFor(\"sdk\")) {\n console.log(\"[CodexManager] normalizeToInput multimodal\", {\n conversationId: context.conversationId,\n imageCount: imagePaths.length,\n imagePaths,\n textIncluded: inputs.some((i) => i.type === \"text\"),\n });\n }\n\n return inputs;\n }\n\n // Fallback to text-only path\n const messageText = this.normalizeToText(value);\n return this.buildPromptForMessage(context, messageText, forceInstructions);\n }\n\n /**\n * Download an image (http(s) or data URL) to a temp file and return the path.\n */\n private async downloadImageToTemp(url: string): Promise<string> {\n // Allow local filesystem paths to be passed through unchanged\n if (url.startsWith(\"/\") || url.startsWith(\"./\") || url.startsWith(\"../\")) {\n return path.isAbsolute(url) ? url : path.resolve(url);\n }\n\n // Handle data URLs (e.g., data:image/png;base64,...)\n if (url.startsWith(\"data:\")) {\n const commaIdx = url.indexOf(\",\");\n if (commaIdx === -1) {\n throw new Error(\"Invalid data URL for image\");\n }\n const header = url.slice(5, commaIdx); // remove \"data:\"\n const dataPart = url.slice(commaIdx + 1);\n const isBase64 = header.endsWith(\";base64\");\n const mime = header.replace(\";base64\", \"\");\n const ext = this.mimeToExtension(mime) || \"png\";\n const buffer = isBase64\n ? Buffer.from(dataPart, \"base64\")\n : Buffer.from(decodeURIComponent(dataPart), \"utf-8\");\n return await this.writeBufferToTemp(buffer, ext);\n }\n\n // Standard remote URL\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to download image (${response.status}) from ${url}`);\n }\n const arrayBuffer = await response.arrayBuffer();\n const buffer = Buffer.from(arrayBuffer);\n const ext = this.inferExtensionFromUrl(url) || \"png\";\n return await this.writeBufferToTemp(buffer, ext);\n }\n\n private async writeBufferToTemp(buffer: Buffer, ext: string): Promise<string> {\n const dir = path.join(tmpdir(), \"codex-images\");\n await fs.mkdir(dir, { recursive: true });\n const filename = `${crypto.randomUUID()}.${ext}`;\n const fullPath = path.join(dir, filename);\n await fs.writeFile(fullPath, buffer);\n return fullPath;\n }\n\n private inferExtensionFromUrl(url: string): string | null {\n try {\n const parsed = new URL(url);\n const pathname = parsed.pathname;\n const ext = path.extname(pathname);\n if (ext) {\n return ext.replace(\".\", \"\").split(/[?#]/)[0] || null;\n }\n } catch {\n // Not a valid URL; fall through\n }\n return null;\n }\n\n private mimeToExtension(mime: string): string | null {\n if (!mime) return null;\n const map: Record<string, string> = {\n \"image/png\": \"png\",\n \"image/jpeg\": \"jpg\",\n \"image/jpg\": \"jpg\",\n \"image/webp\": \"webp\",\n \"image/gif\": \"gif\",\n };\n return map[mime] || null;\n }\n\n private normalizeToText(value: any): string {\n if (typeof value === \"string\") return value;\n if (value == null) return \"\";\n\n if (typeof value === \"object\") {\n if (typeof (value as any).text === \"string\") {\n return (value as any).text;\n }\n if (Array.isArray(value)) {\n const texts = value\n .map((entry) => {\n if (\n entry &&\n typeof entry === \"object\" &&\n typeof entry.text === \"string\"\n ) {\n return entry.text;\n }\n return null;\n })\n .filter((entry): entry is string => Boolean(entry));\n if (texts.length) {\n return texts.join(\" \");\n }\n }\n if (typeof (value as any).content === \"string\") {\n return (value as any).content;\n }\n }\n\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n }\n\n private normalizeSessionId(value?: string | null): string | undefined {\n if (!value) return undefined;\n const trimmed = value.trim();\n return trimmed.length ? trimmed : undefined;\n }\n\n private resolveSessionId(\n config?: ConversationConfig,\n conversationData?: ConversationDetails,\n override?: string | null\n ): string {\n return (\n this.normalizeSessionId(override) ||\n this.normalizeSessionId(config?.sessionId) ||\n this.normalizeSessionId(conversationData?.agentSessionId) ||\n this.normalizeSessionId((conversationData as any)?.threadId) ||\n this.normalizeSessionId((conversationData as any)?.sessionId) ||\n \"\"\n );\n }\n\n private isAbortError(error: unknown): boolean {\n if (!error) return false;\n return (\n (error as any).name === \"AbortError\" ||\n /aborted|abort/i.test((error as any).message || \"\")\n );\n }\n\n private async _finalizeConversation(\n context: ConversationContext,\n hadError: boolean,\n error?: any,\n reason?: string\n ): Promise<void> {\n // Synchronous idempotency check - must happen before any async operations\n if ((context as any)._finalized) return;\n (context as any)._finalized = true;\n\n // Mark as completed immediately to prevent restart on catch-up\n // This is synchronous and happens before any async operations\n this.runner.markConversationCompleted(context.conversationId);\n\n // Clean up local state synchronously\n this.threadStates.delete(context.conversationId);\n this.runner.activeConversations_.delete(context.conversationId);\n statusLineManager.updateActiveCount(this.runner.activeConversations_.size);\n\n // Now do async notification (after all sync cleanup)\n try {\n await this.runner.notify(\"conversation.end\", {\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n agentSessionId: context.agentSessionId,\n isError: hadError,\n errorMessage: error?.message,\n reason,\n });\n } catch (notifyError) {\n console.error(\n \"[CodexManager] Failed to send conversation.end notification\",\n notifyError\n );\n }\n\n // Notify update coordinator that a conversation has ended\n // This may trigger an auto-update if one is pending and runner is now idle\n try {\n await this.runner.onConversationEnd();\n } catch (e) {\n console.error(\"[CodexManager] Failed to notify onConversationEnd:\", e);\n }\n }\n\n private async _handleConversationError(\n context: ConversationContext,\n error: Error\n ): Promise<void> {\n console.error(\n `[CodexManager] Conversation error for ${context.conversationId}:`,\n error\n );\n\n await this.runner.notify(\"error.report\", {\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n agentSessionId: context.agentSessionId,\n errorType: \"codex_error\",\n message: error.message,\n details: {\n stack: error.stack,\n timestamp: new Date(),\n },\n });\n }\n\n private generateMessageId(context: ConversationContext): string {\n return `${context.agentSessionId}-${Date.now()}-${Math.random()\n .toString(36)\n .slice(2)}`;\n }\n}\n","import type { CoreMessage } from 'ai';\nimport type { SDKMessage } from './sdk-types';\nimport { promises as fs } from 'fs';\nimport path from 'path';\n\n/**\n * Session data that includes messages in AI SDK CoreMessage format\n * This is used when integrating with the AI SDK Agent directly\n */\nexport interface CoreMessageSessionData {\n /** The conversation messages in AI SDK CoreMessage format */\n messages: CoreMessage[];\n /** Optional metadata that can be stored with the session */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Session data that includes messages in SDK format\n * This is used with the query() SDK interface\n */\nexport interface SDKSessionData {\n /** The conversation messages in SDK format */\n messages: SDKMessage[];\n /** Optional metadata that can be stored with the session */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Function type for loading a session from storage (CoreMessage format)\n * @param sessionId - The unique identifier of the session to load\n * @returns A promise that resolves to the session data, or null if not found\n */\nexport type LoadCoreSessionFunction = (sessionId: string) => Promise<CoreMessageSessionData | null>;\n\n/**\n * Function type for saving a session to storage (CoreMessage format)\n * @param sessionId - The unique identifier of the session to save\n * @param messages - The conversation messages to save\n * @returns A promise that resolves when the session is saved\n */\nexport type SaveCoreSessionFunction = (sessionId: string, messages: CoreMessage[]) => Promise<void>;\n\n/**\n * Function type for loading a session from storage (SDK format)\n * @param sessionId - The unique identifier of the session to load\n * @returns A promise that resolves to the session data, or null if not found\n */\nexport type LoadSDKSessionFunction = (sessionId: string) => Promise<SDKSessionData | null>;\n\n/**\n * Function type for saving a session to storage (SDK format)\n * @param sessionId - The unique identifier of the session to save\n * @param messages - The conversation messages to save\n * @returns A promise that resolves when the session is saved\n */\nexport type SaveSDKSessionFunction = (sessionId: string, messages: SDKMessage[]) => Promise<void>;\n\n/**\n * Simple file-based session storage implementation for SDK messages.\n *\n * This class provides a basic implementation of session persistence using the filesystem.\n * In production environments, consider using a database like PostgreSQL, MongoDB, or Redis instead.\n *\n * @example\n * ```typescript\n * import { FileSessionStorage, query } from '@northflare/agent';\n *\n * const storage = new FileSessionStorage('./sessions');\n *\n * const q = query({\n * prompt: 'Create a hello world script',\n * options: {\n * resume: 'my-session-id',\n * loadSession: (id) => storage.loadSession(id),\n * saveSession: (id, messages) => storage.saveSession(id, messages),\n * }\n * });\n * ```\n */\nexport class FileSessionStorage {\n /**\n * Creates a new FileSessionStorage instance\n * @param storageDir - The directory where session files will be stored\n */\n constructor(private storageDir: string) {\n fs.mkdir(storageDir, { recursive: true });\n }\n\n /**\n * Gets the file path for a session ID\n * @param sessionId - The session identifier\n * @returns The sanitized file path\n */\n private getPath(sessionId: string): string {\n // Sanitize session ID to prevent directory traversal\n const safeId = sessionId.replace(/[^a-zA-Z0-9-_]/g, '_');\n return path.join(this.storageDir, `${safeId}.json`);\n }\n\n /**\n * Loads a session from the filesystem\n * @param sessionId - The unique identifier of the session to load\n * @returns The session data, or null if not found\n */\n async loadSession(sessionId: string): Promise<SDKSessionData | null> {\n try {\n const content = await fs.readFile(this.getPath(sessionId), 'utf-8');\n return JSON.parse(content);\n } catch {\n return null;\n }\n }\n\n /**\n * Saves a session to the filesystem\n * @param sessionId - The unique identifier of the session to save\n * @param messages - The conversation messages to save\n */\n async saveSession(sessionId: string, messages: SDKMessage[]): Promise<void> {\n const filePath = this.getPath(sessionId);\n const directory = path.dirname(filePath);\n\n // Ensure the directory exists\n await fs.mkdir(directory, { recursive: true });\n\n await fs.writeFile(\n filePath,\n JSON.stringify({ messages }, null, 2)\n );\n }\n}","import type { ImageStorageAdapter } from './types';\n\n/**\n * Provides an in-memory ImageStorageAdapter for ephemeral and test scenarios.\n */\nexport class MemoryImageStorage implements ImageStorageAdapter {\n private images: Map<string, string | URL>;\n\n constructor() {\n this.images = new Map();\n }\n\n /**\n * Stores an image payload in memory.\n * @param id - Unique image identifier.\n * @param data - Image data (URL object or base64 string).\n * @returns Promise that resolves when storage is complete.\n */\n async saveImage(id: string, data: string | URL): Promise<void> {\n this.images.set(id, data);\n }\n\n /**\n * Loads an image payload by identifier.\n * @param id - Unique image identifier.\n * @returns Stored image data.\n * @throws Error when the image cannot be found.\n */\n async loadImage(id: string): Promise<string | URL> {\n const image = this.images.get(id);\n if (!image) {\n throw new Error(`Image not found: ${id}`);\n }\n return image;\n }\n\n /**\n * Removes an image from memory.\n * @param id - Unique image identifier.\n * @returns Promise that resolves after deletion.\n */\n async deleteImage(id: string): Promise<void> {\n this.images.delete(id);\n }\n\n /**\n * Lists all stored image identifiers.\n * @returns Array of stored image IDs.\n */\n async listImages(): Promise<string[]> {\n return Array.from(this.images.keys());\n }\n\n /**\n * Clears all stored images.\n */\n clear(): void {\n this.images.clear();\n }\n\n /**\n * Reports the number of stored images.\n * @returns Count of stored images.\n */\n get size(): number {\n return this.images.size;\n }\n}\n","import { promises as fs } from 'node:fs';\nimport { join } from 'node:path';\nimport type { ImageStorageAdapter } from './types';\nimport { sanitizeImageId } from '../util/image-utils';\n\n/**\n * Default storage directory for images\n */\nconst DEFAULT_STORAGE_DIR = '.agent/images';\n\n/**\n * Persists images to the local filesystem for tool-based vision workflows.\n */\nexport class FilesystemImageStorage implements ImageStorageAdapter {\n private storageDir: string;\n\n constructor(storageDir: string = DEFAULT_STORAGE_DIR) {\n this.storageDir = storageDir;\n }\n\n /**\n * Ensures the storage directory exists.\n * @returns Promise that resolves once the directory is ready.\n */\n private async ensureStorageDir(): Promise<void> {\n try {\n await fs.mkdir(this.storageDir, { recursive: true });\n } catch (error) {\n throw new Error(`Failed to create storage directory: ${error}`);\n }\n }\n\n /**\n * Gets the on-disk path for an image identifier.\n * @param id - Image identifier to resolve.\n * @returns Absolute file path for the image metadata.\n */\n private getImagePath(id: string): string {\n const sanitizedId = sanitizeImageId(id);\n return join(this.storageDir, `${sanitizedId}.json`);\n }\n\n /**\n * Writes image data to disk.\n * @param id - Image identifier.\n * @param data - Image payload (URL or base64 string).\n * @returns Promise that resolves when the image is saved.\n */\n async saveImage(id: string, data: string | URL): Promise<void> {\n await this.ensureStorageDir();\n const imagePath = this.getImagePath(id);\n\n // Store both URLs and base64 data as JSON for consistency\n const imageData = {\n id,\n data: data instanceof URL ? data.href : data,\n type: data instanceof URL ? 'url' : 'base64',\n savedAt: new Date().toISOString()\n };\n\n try {\n await fs.writeFile(imagePath, JSON.stringify(imageData, null, 2), 'utf-8');\n } catch (error) {\n throw new Error(`Failed to save image ${id}: ${error}`);\n }\n }\n\n /**\n * Reads image data from disk.\n * @param id - Image identifier.\n * @returns Image payload as URL instance or base64 string.\n */\n async loadImage(id: string): Promise<string | URL> {\n const imagePath = this.getImagePath(id);\n\n try {\n const fileContent = await fs.readFile(imagePath, 'utf-8');\n const imageData = JSON.parse(fileContent);\n\n if (imageData.type === 'url') {\n return new URL(imageData.data);\n }\n return imageData.data;\n } catch (error) {\n if ((error as any).code === 'ENOENT') {\n throw new Error(`Image not found: ${id}`);\n }\n throw new Error(`Failed to load image ${id}: ${error}`);\n }\n }\n\n /**\n * Removes a stored image file.\n * @param id - Image identifier.\n * @returns Promise that resolves after deletion.\n */\n async deleteImage(id: string): Promise<void> {\n const imagePath = this.getImagePath(id);\n\n try {\n await fs.unlink(imagePath);\n } catch (error) {\n if ((error as any).code !== 'ENOENT') {\n throw new Error(`Failed to delete image ${id}: ${error}`);\n }\n // Ignore if file doesn't exist\n }\n }\n\n /**\n * Lists all stored image identifiers.\n * @returns Array of stored image IDs.\n */\n async listImages(): Promise<string[]> {\n try {\n await this.ensureStorageDir();\n const files = await fs.readdir(this.storageDir);\n\n // Filter for JSON files and extract IDs\n return files\n .filter(file => file.endsWith('.json'))\n .map(file => file.replace('.json', ''));\n } catch (error) {\n if ((error as any).code === 'ENOENT') {\n return [];\n }\n throw new Error(`Failed to list images: ${error}`);\n }\n }\n\n /**\n * Cleans up all stored images.\n * @returns Promise that resolves when cleanup finishes.\n */\n async clearAll(): Promise<void> {\n const images = await this.listImages();\n await Promise.all(images.map(id => this.deleteImage(id)));\n }\n}\n\n// Create default instance with default storage directory\nconst defaultStorage = new FilesystemImageStorage();\n\n// Export default adapter functions that can be used directly with Options\nexport const saveImage: ImageStorageAdapter['saveImage'] = (id, data) => defaultStorage.saveImage(id, data);\nexport const loadImage: ImageStorageAdapter['loadImage'] = (id) => defaultStorage.loadImage(id);\nexport const deleteImage: ImageStorageAdapter['deleteImage'] = (id) => defaultStorage.deleteImage!(id);\nexport const listImages: ImageStorageAdapter['listImages'] = () => defaultStorage.listImages!();\n\n// Also export the class for custom configurations\nexport default FilesystemImageStorage;\n","/**\n * NorthflareAgentManager - Manages conversations using the @northflare/agent SDK\n *\n * Mirrors the existing Claude integration but targets OpenRouter-style models\n * via the Northflare Agent SDK. Lifecycle, repository handling, and message\n * normalization stay aligned with the existing managers so downstream\n * interfaces remain compatible.\n */\n\nimport { query as sdkQuery } from \"@northflare/agent\";\nimport { createGroq, groq as groqProvider } from \"@ai-sdk/groq\";\nimport { createOpenRouter } from \"@openrouter/ai-sdk-provider\";\n// Keep SDKMessage loosely typed to avoid tight coupling to SDK typings\ntype SDKMessage = any;\nimport { IRunnerApp } from \"../types/runner-interface.js\";\nimport { EnhancedRepositoryManager } from \"./enhanced-repository-manager.js\";\nimport {\n ConversationContext,\n ConversationConfig,\n Message,\n} from \"../types/index.js\";\nimport { statusLineManager } from \"../utils/status-line.js\";\nimport { createScopedConsole } from \"../utils/console.js\";\nimport { expandEnv } from \"../utils/expand-env.js\";\nimport { isDebugEnabledFor } from \"../utils/debug.js\";\nimport jwt from \"jsonwebtoken\";\nimport fs from \"fs/promises\";\nimport path from \"path\";\nimport { simpleGit } from \"simple-git\";\n\nconst console = createScopedConsole(\n isDebugEnabledFor(\"manager\") ? \"manager\" : \"sdk\"\n);\n\nfunction buildSystemPromptWithNorthflare(\n basePrompt?: string,\n northflarePrompt?: string\n): string | undefined {\n const parts = [northflarePrompt, basePrompt]\n .filter((p): p is string => typeof p === \"string\" && p.trim().length > 0)\n .map((p) => p.trim());\n\n if (parts.length === 0) return undefined;\n return parts.join(\"\\n\\n\");\n}\n\nexport class NorthflareAgentManager {\n private runner: IRunnerApp;\n private repositoryManager: EnhancedRepositoryManager;\n private submitToolUseIds: Map<string, Set<string>> = new Map(); // conversationId -> Set of submit tool_use_ids\n\n constructor(\n runner: IRunnerApp,\n repositoryManager: EnhancedRepositoryManager\n ) {\n this.runner = runner;\n this.repositoryManager = repositoryManager;\n\n // Log debug mode status\n if (isDebugEnabledFor(\"sdk\")) {\n console.log(\n \"[NorthflareAgentManager] DEBUG MODE ENABLED - Northflare Agent SDK will log verbose output\"\n );\n }\n\n // Note: MCP host configuration is passed from orchestrator\n // Runner does not define its own MCP tools\n this.setupInternalMcpServer();\n }\n\n private setupInternalMcpServer(): void {\n // Runner does not define its own MCP tools\n // All MCP tool configuration is passed from orchestrator in conversation config\n }\n\n private buildSubAgentConfig(subAgentTypes?: Record<string, any>): {\n enabled: boolean;\n agents: Record<\n string,\n { description: string; prompt: string; model?: string }\n >;\n } {\n const enabled = subAgentTypes?.[\"enabled\"] !== false;\n const allowInherit = subAgentTypes?.[\"inherit\"] !== false;\n\n if (!enabled) {\n return { enabled: false, agents: {} };\n }\n\n const agents: Record<\n string,\n { description: string; prompt: string; model?: string }\n > = {};\n\n if (allowInherit) {\n agents[\"inherit\"] = {\n description: \"Use the main task model and toolset.\",\n prompt: \"\",\n model: \"inherit\",\n };\n }\n\n const RESERVED = new Set([\"inherit\", \"enabled\"]);\n\n Object.entries(subAgentTypes || {}).forEach(([name, value]) => {\n if (RESERVED.has(name)) return;\n if (!value || typeof value !== \"object\") return;\n\n const description =\n typeof (value as any).description === \"string\" &&\n (value as any).description.trim().length\n ? (value as any).description.trim()\n : `Use agentType \\\"${name}\\\" when its specialization fits the task.`;\n\n const prompt =\n typeof (value as any).instructions === \"string\"\n ? (value as any).instructions.trim()\n : \"\";\n\n const model =\n typeof (value as any).model === \"string\" &&\n (value as any).model.trim().length\n ? (value as any).model.trim()\n : \"inherit\";\n\n agents[name] = {\n description,\n prompt,\n model,\n };\n });\n\n if (Object.keys(agents).length === 0) {\n return { enabled: false, agents: {} };\n }\n\n return { enabled: true, agents };\n }\n\n async startConversation(\n conversationObjectType: \"Task\" | \"TaskPlan\" | \"ProjectStep\",\n conversationObjectId: string,\n config: ConversationConfig,\n initialMessages: Message[],\n conversationData?: {\n id: string;\n objectType: string;\n objectId: string;\n model: string;\n summary?: string | null;\n globalInstructions: string;\n workspaceInstructions: string;\n permissionsMode: string;\n agentSessionId: string;\n systemPrompt?: string;\n northflareSystemPrompt?: string;\n systemPromptMode?: \"append\" | \"replace\";\n },\n provider: \"openrouter\" | \"groq\" = \"openrouter\"\n ): Promise<ConversationContext> {\n // Returns conversation context\n // Greenfield: conversationData.id is required as the authoritative DB conversation ID\n if (!conversationData?.id) {\n throw new Error(\n \"startConversation requires conversationData with a valid conversation.id\"\n );\n }\n // Use sessionId from config if resuming, or agentSessionId from conversationData if available\n const agentSessionId =\n config.sessionId || conversationData.agentSessionId || \"\";\n const conversationId = conversationData.id;\n const rawModel =\n conversationData?.model ||\n (config as any)?.model ||\n (config as any)?.defaultModel;\n\n if (!rawModel) {\n throw new Error(\n \"Model is required for Northflare conversations (provide conversationData.model, config.model, or config.defaultModel).\"\n );\n }\n const model = this.normalizeModel(rawModel);\n const useWorktrees = config.useWorktrees !== false;\n const pendingSummary =\n this.runner.consumePendingConversationSummary(conversationId);\n const rawSummary =\n typeof conversationData.summary === \"string\"\n ? conversationData.summary\n : pendingSummary;\n const normalizedSummary =\n typeof rawSummary === \"string\"\n ? rawSummary.replace(/\\s+/g, \" \").trim()\n : null;\n\n const context: ConversationContext = {\n conversationId,\n agentSessionId, // Will be updated by onSessionId callback for new conversations\n conversationObjectType,\n conversationObjectId,\n taskId:\n conversationObjectType === \"Task\" ? conversationObjectId : undefined,\n workspaceId: config.workspaceId,\n status: \"starting\",\n config,\n startedAt: new Date(),\n lastActivityAt: new Date(),\n // Add conversation details if provided\n model,\n summary: normalizedSummary,\n globalInstructions: conversationData?.globalInstructions || \"\",\n workspaceInstructions: conversationData?.workspaceInstructions || \"\",\n permissionsMode: conversationData?.permissionsMode || \"all\",\n provider,\n };\n\n // Store with conversation.id as the key\n this.runner.activeConversations_.set(conversationId, context);\n console.log(`[NorthflareAgentManager] Stored conversation context:`, {\n conversationId,\n agentSessionId: context.agentSessionId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n mapSize: this.runner.activeConversations_.size,\n allKeys: Array.from(this.runner.activeConversations_.keys()),\n });\n\n const workspaceId = config.workspaceId;\n\n // Checkout repository if specified\n let workspacePath: string;\n\n // Check if this is a local workspace by looking for runnerRepoPath in config\n if (config.runnerRepoPath) {\n // Local workspace - use the provided path directly\n workspacePath = config.runnerRepoPath;\n console.log(`Using local workspace path: ${workspacePath}`);\n\n // For task conversations, isolate the worktree/branch when the repo has a .git directory\n if (conversationObjectType === \"Task\" && workspaceId) {\n const hasGitDir = await fs\n .access(path.join(workspacePath, \".git\"))\n .then(() => true)\n .catch(() => false);\n\n if (hasGitDir && useWorktrees) {\n const repoUrl = (config.repository?.url as string) || `file://${workspacePath}`;\n const baseBranch = (config.repository?.branch as string) || \"main\";\n\n const taskHandle = await this.repositoryManager.createTaskWorktree(\n conversationObjectId,\n workspaceId,\n repoUrl,\n baseBranch,\n config.githubToken\n );\n workspacePath = taskHandle.worktreePath;\n (context as any).taskHandle = taskHandle;\n }\n }\n } else if (\n conversationObjectType === \"Task\" &&\n config.repository &&\n workspaceId &&\n useWorktrees\n ) {\n // Use task-specific worktree for all task conversations (keeps shared workspace checkout clean)\n console.log(\n `[NorthflareAgentManager] Creating task worktree with repository config:`,\n {\n conversationObjectId,\n workspaceId,\n repository: config.repository,\n hasUrl: !!config.repository.url,\n url: config.repository.url,\n branch: config.repository.branch,\n type: config.repository.type,\n }\n );\n\n // Check if repository.url is missing\n if (!config.repository.url) {\n throw new Error(\n `Repository URL is missing in config for task ${conversationObjectId}. Repository config: ${JSON.stringify(\n config.repository\n )}`\n );\n }\n\n const taskHandle = await this.repositoryManager.createTaskWorktree(\n conversationObjectId,\n workspaceId,\n config.repository.url,\n config.repository.branch,\n config.githubToken\n );\n workspacePath = taskHandle.worktreePath;\n\n // Store task handle information in context for later use\n (context as any).taskHandle = taskHandle;\n } else if (config.repository && workspaceId) {\n // Check if it's a local repository\n if (config.repository.type === \"local\" && config.repository.localPath) {\n // Use the local path directly\n workspacePath = config.repository.localPath;\n console.log(`Using local repository path: ${workspacePath}`);\n } else {\n // Fall back to workspace-based checkout for non-task conversations\n workspacePath = await this.repositoryManager.checkoutRepository(\n workspaceId,\n config.repository.url,\n config.repository.branch,\n config.githubToken\n );\n }\n } else if (workspaceId) {\n workspacePath =\n await this.repositoryManager.getWorkspacePath(workspaceId);\n } else {\n // Default workspace path when no workspaceId is provided\n workspacePath = process.cwd();\n }\n\n // Fetch GitHub tokens from orchestrator API if we have a workspaceId\n const githubToken = workspaceId\n ? await this.fetchGithubTokens(workspaceId)\n : undefined;\n\n // Generate TOOL_TOKEN for MCP tools authentication\n let toolToken: string | undefined;\n if (config.mcpServers && Object.keys(config.mcpServers).length > 0) {\n const runnerToken = process.env[\"NORTHFLARE_RUNNER_TOKEN\"];\n const runnerUid = this.runner.getRunnerUid();\n\n if (runnerToken && runnerUid && context.conversationId) {\n // Sign JWT with runner's token\n toolToken = jwt.sign(\n {\n conversationId: context.conversationId,\n runnerUid: runnerUid,\n },\n runnerToken,\n {\n expiresIn: \"60m\", // 60 minutes expiry\n }\n );\n console.log(\n \"[NorthflareAgentManager] Generated TOOL_TOKEN for MCP authentication\"\n );\n } else {\n console.warn(\n \"[NorthflareAgentManager] Unable to generate TOOL_TOKEN - missing required data\"\n );\n }\n }\n\n const managerDebug = isDebugEnabledFor(\"manager\");\n const sdkDebug = isDebugEnabledFor(\"sdk\");\n const debugEnabled = managerDebug || sdkDebug;\n\n // Simplified SDK configuration - using native query API with streamlined options\n\n // Simplified environment configuration\n const envVars: Record<string, string> = {\n ...(Object.fromEntries(\n Object.entries(process.env).filter(([_, value]) => value !== undefined)\n ) as Record<string, string>), // Preserve parent environment, filter out undefined values\n };\n\n if (config.anthropicApiKey) {\n envVars[\"ANTHROPIC_API_KEY\"] = config.anthropicApiKey;\n }\n\n // OpenRouter / Groq API key support (prefer provider-specific fields)\n const openRouterApiKey =\n (config as any).openRouterApiKey || process.env[\"OPENROUTER_API_KEY\"];\n const groqApiKey =\n (config as any).groqApiKey || process.env[\"GROQ_API_KEY\"];\n\n if (openRouterApiKey) {\n envVars[\"OPENROUTER_API_KEY\"] = openRouterApiKey;\n }\n\n if (groqApiKey) {\n envVars[\"GROQ_API_KEY\"] = groqApiKey;\n }\n\n // Pass through OpenAI API key if supplied for provider-prefixed models\n if ((config as any).openaiApiKey) {\n envVars[\"OPENAI_API_KEY\"] = (config as any).openaiApiKey as string;\n }\n\n if (githubToken) {\n envVars[\"GITHUB_TOKEN\"] = githubToken;\n }\n\n if (toolToken) {\n envVars[\"TOOL_TOKEN\"] = toolToken;\n }\n\n if (sdkDebug) {\n envVars[\"DEBUG\"] = \"1\";\n }\n\n const subAgentConfig = this.buildSubAgentConfig(\n config.subAgentTypes as any\n );\n\n const agentsOption =\n subAgentConfig.enabled && Object.keys(subAgentConfig.agents).length > 0\n ? subAgentConfig.agents\n : undefined;\n\n // Simplified system prompt handling\n const providedSystemPrompt = buildSystemPromptWithNorthflare(\n config.systemPrompt || (conversationData as any)?.systemPrompt,\n (config as any)?.northflareSystemPrompt ||\n (conversationData as any)?.northflareSystemPrompt\n );\n\n const systemPromptMode =\n config.systemPromptMode ||\n (conversationData as any)?.systemPromptMode ||\n // Default ProjectStep conversations to append so preset stays intact\n \"append\";\n\n let systemPromptOption: any;\n if (providedSystemPrompt) {\n if (systemPromptMode === \"replace\") {\n systemPromptOption = providedSystemPrompt;\n } else {\n systemPromptOption = {\n type: \"preset\" as const,\n preset: \"claude_code\" as const,\n append: providedSystemPrompt,\n };\n }\n }\n\n // Debug log the systemPrompt being sent to Northflare Agent SDK\n console.log(\n `[NorthflareAgentManager] System prompt configuration for conversation ${context.conversationId}:`,\n {\n mode: systemPromptMode,\n hasProvidedSystemPrompt: Boolean(providedSystemPrompt),\n finalPromptType: typeof systemPromptOption,\n finalPromptLength:\n typeof systemPromptOption === \"string\"\n ? systemPromptOption.length\n : (systemPromptOption as any)?.append?.length ?? 0,\n }\n );\n\n // Tool restrictions based on permissions mode\n // \"read\" = read-only mode (no file writes, no shell)\n // \"project\" = no file writes but allows bash, no subagents (for Project conversation)\n const readOnlyTools = [\n \"write_file\",\n \"edit_file\",\n \"multi_edit_file\",\n \"delete_file\",\n \"move_file\",\n \"copy_file\",\n \"run_command\",\n \"todo_write\",\n ];\n const projectModeTools = [\n \"write_file\",\n \"edit_file\",\n \"multi_edit_file\",\n \"delete_file\",\n \"move_file\",\n \"copy_file\",\n \"todo_write\",\n \"task\",\n ];\n const disallowedTools: string[] =\n context.permissionsMode === \"read\"\n ? readOnlyTools\n : context.permissionsMode === \"project\"\n ? projectModeTools\n : [];\n\n if (!subAgentConfig.enabled) {\n disallowedTools.push(\"task\");\n }\n\n if (disallowedTools.length) {\n console.log(\"[NorthflareAgentManager] Tool restrictions applied\", {\n disallowedTools,\n });\n }\n\n // Simplified MCP server configuration\n let mcpServers: Record<string, any> | undefined;\n if (config.mcpServers) {\n mcpServers = expandEnv(config.mcpServers, { TOOL_TOKEN: toolToken });\n console.log(\n \"[NorthflareAgentManager] MCP servers configuration:\",\n JSON.stringify(mcpServers, null, 2)\n );\n }\n\n if (debugEnabled) {\n console.log(\"[NorthflareAgentManager] SDK launch summary\", {\n conversationId: context.conversationId,\n model,\n provider,\n cwd: workspacePath,\n hasMcpServers: !!mcpServers && Object.keys(mcpServers).length > 0,\n disallowedTools,\n systemPromptMode,\n hasSystemPrompt: Boolean(systemPromptOption),\n systemPromptType: typeof systemPromptOption,\n subAgentsEnabled: subAgentConfig.enabled,\n agentTypes: agentsOption ? Object.keys(agentsOption) : [],\n env: {\n OPENROUTER_API_KEY: Boolean(envVars[\"OPENROUTER_API_KEY\"]),\n GROQ_API_KEY: Boolean(envVars[\"GROQ_API_KEY\"]),\n ANTHROPIC_API_KEY: Boolean(envVars[\"ANTHROPIC_API_KEY\"]),\n OPENAI_API_KEY: Boolean(envVars[\"OPENAI_API_KEY\"]),\n GITHUB_TOKEN: Boolean(envVars[\"GITHUB_TOKEN\"]),\n TOOL_TOKEN: Boolean(envVars[\"TOOL_TOKEN\"]),\n },\n });\n }\n\n // Create input stream for user messages (simplified message queueing)\n const input = createUserMessageStream();\n\n // NOTE: different @ai-sdk/provider versions (v2 via @northflare/agent and\n // v3 via @ai-sdk/groq/ai) can lead to nominally incompatible LanguageModel\n // types. We only need runtime compatibility here, so coerce to `any` to\n // avoid TS conflicts between the duplicated provider packages.\n // Build provider-specific model instance. OpenRouter requires an explicit\n // client factory instead of the generic model string.\n const sdkModel: any = (() => {\n if (provider === \"groq\") {\n const groqClient =\n groqApiKey && groqApiKey.length > 0\n ? createGroq({ apiKey: groqApiKey })\n : groqProvider;\n return groqClient(context.model) as any;\n }\n\n if (provider === \"openrouter\") {\n const client = createOpenRouter({\n apiKey: openRouterApiKey || process.env[\"OPENROUTER_API_KEY\"] || \"\",\n });\n return client(context.model);\n }\n\n return context.model;\n })();\n\n // Respect a maxTurns override if provided (falls back to SDK default when unset)\n const maxTurns = Number.isFinite((config as any).maxTurns)\n ? (config as any).maxTurns\n : undefined;\n\n // Log how the model was resolved to help compare with the standalone script\n console.log(\"[NorthflareAgentManager] Model resolution\", {\n provider,\n rawModel: rawModel,\n normalizedModel: context.model,\n openRouterApiKeyPresent: Boolean(\n openRouterApiKey || process.env[\"OPENROUTER_API_KEY\"]\n ),\n sdkModelType: (sdkModel as any)?.constructor?.name,\n });\n\n // Build a modelResolver for sub-agents that can resolve model strings to LanguageModel instances\n const modelResolver = (modelId: string) => {\n // Normalize the model ID (strip provider prefixes)\n const normalizedModelId = this.normalizeModel(modelId);\n\n // Determine the provider from the model ID prefix or fall back to the parent provider\n let modelProvider = provider;\n if (modelId.startsWith(\"groq:\") || modelId.startsWith(\"groq/\")) {\n modelProvider = \"groq\";\n } else if (\n modelId.startsWith(\"openrouter:\") ||\n modelId.startsWith(\"openrouter/\")\n ) {\n modelProvider = \"openrouter\";\n }\n\n // Create the appropriate model instance\n if (modelProvider === \"groq\") {\n const groqClient =\n groqApiKey && groqApiKey.length > 0\n ? createGroq({ apiKey: groqApiKey })\n : groqProvider;\n return groqClient(normalizedModelId) as any;\n }\n\n if (modelProvider === \"openrouter\") {\n const client = createOpenRouter({\n apiKey: openRouterApiKey || process.env[\"OPENROUTER_API_KEY\"] || \"\",\n });\n return client(normalizedModelId);\n }\n\n // Unknown provider - return undefined to let SDK throw a helpful error\n return undefined;\n };\n\n // Launch SDK with simplified configuration\n let silenceTimer: NodeJS.Timeout | null = null;\n let lastSdkActivity = Date.now();\n\n const handleTaskProgress = async (update: {\n progressPercent?: number;\n toolCallId?: string;\n raw?: unknown;\n }) => {\n const pct = Number(update?.progressPercent);\n if (!Number.isFinite(pct)) return;\n\n const clamped = Math.max(0, Math.min(100, pct));\n const messageId = `${context.agentSessionId}-progress-${Date.now()}-${Math.random()\n .toString(36)\n .slice(2, 8)}`;\n\n const progressPayload: any = {\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n agentSessionId: context.agentSessionId,\n type: \"assistant\",\n subtype: \"task_progress\",\n messageMetaType: \"task_progress\",\n metadata: {\n progressPercent: clamped,\n toolCallId: update?.toolCallId,\n raw: update?.raw,\n },\n content: [\n {\n type: \"text\",\n text: `Task progress ${Math.round(clamped)}%`,\n },\n ],\n messageId,\n };\n\n try {\n await this.runner.notify(\"message.agent\", progressPayload);\n } catch (err) {\n console.warn(\"[NorthflareAgentManager] Failed to send task progress\", {\n conversationId: context.conversationId,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n };\n\n const sdk = sdkQuery({\n prompt: input.iterable,\n options: {\n cwd: workspacePath,\n env: envVars,\n model: sdkModel,\n modelResolver,\n resume:\n config.sessionId || conversationData?.agentSessionId || undefined,\n // Enable vision support - allows passing images directly to the model\n visionModel: true,\n ...(agentsOption ? { agents: agentsOption } : {}),\n ...(maxTurns !== undefined ? { maxTurns } : {}),\n ...(systemPromptOption ? { systemPrompt: systemPromptOption } : {}),\n ...(disallowedTools.length ? { disallowedTools } : {}),\n ...(mcpServers ? { mcpServers } : {}),\n conversationId: context.conversationId,\n conversationObjectId: context.conversationObjectId,\n taskId: context.taskId,\n onTaskProgress: handleTaskProgress,\n ...(sdkDebug\n ? {\n debug: true,\n stderr: (data: string) => {\n try {\n console.log(`[Northflare Agent SDK] ${data}`);\n } catch {}\n },\n onStepFinish: (step: any) => {\n try {\n console.log(\n \"[NorthflareAgentManager] Agent step finished (full step object): \" +\n JSON.stringify(step, null, 2)\n );\n } catch {}\n },\n }\n : {}),\n },\n });\n\n console.log(\"[NorthflareAgentManager] sdkQuery options summary\", {\n provider,\n model: context.model,\n cwd: workspacePath,\n maxTurns: maxTurns ?? \"default (SDK)\",\n hasSystemPrompt: Boolean(systemPromptOption),\n hasMcpServers: Boolean(mcpServers && Object.keys(mcpServers).length),\n disallowedToolsCount: disallowedTools.length,\n envKeys: Object.keys(envVars),\n });\n\n // Track number of streamed messages to aid debugging when sessions appear silent\n let streamedMessageCount = 0;\n const clearSilenceTimer = () => {\n if (silenceTimer) {\n clearInterval(silenceTimer);\n silenceTimer = null;\n }\n };\n\n // Simplified conversation wrapper - reduced complexity while maintaining interface\n const conversation = createConversationWrapper(\n sdk,\n input,\n async (hadError: boolean, error?: any) => {\n // Check if SDK reported an error via result message (stored in metadata)\n const sdkError = context.metadata?.[\"_sdkError\"];\n const effectiveHadError = hadError || sdkError?.isError === true;\n const effectiveError =\n error ||\n (sdkError?.isError\n ? new Error(sdkError.errorMessage || \"SDK execution error\")\n : undefined);\n\n console.log(\"[NorthflareAgentManager] SDK stream completed\", {\n conversationId: context.conversationId,\n agentSessionId: context.agentSessionId,\n hadError,\n sdkErrorDetected: sdkError?.isError,\n effectiveHadError,\n errorMessage: effectiveError?.message,\n streamedMessageCount,\n });\n clearSilenceTimer();\n\n // Surface SDK-level failures to the orchestrator so the task\n // transitions to needs_attention and an error bubble appears in chat.\n if (effectiveHadError && effectiveError) {\n try {\n const normalizedError =\n effectiveError instanceof Error\n ? effectiveError\n : new Error(String(effectiveError));\n await this._handleConversationError(context, normalizedError);\n } catch (err) {\n console.error(\n \"[NorthflareAgentManager] Failed to report SDK error:\",\n err\n );\n }\n }\n\n await this._handleRunCompletion(context, effectiveHadError, effectiveError);\n }\n );\n\n // Store conversation instance in context for reuse\n context.conversation = conversation as any;\n (context as any)._clearSilenceTimer = clearSilenceTimer;\n\n // Observe session id from first messages that include it\n conversation.onSessionId(async (agentSessionId: string) => {\n if (!agentSessionId) return;\n const oldSessionId = context.agentSessionId;\n if (oldSessionId !== agentSessionId) {\n context.agentSessionId = agentSessionId;\n context.status = \"active\";\n await this.runner.notify(\"agentSessionId.changed\", {\n conversationId: context.conversationId,\n conversationObjectType,\n conversationObjectId,\n oldAgentSessionId: oldSessionId,\n newAgentSessionId: agentSessionId,\n });\n }\n });\n\n // Set up streaming message handler\n const messageHandler = async (\n message: SDKMessage,\n sessionId: string | null\n ) => {\n streamedMessageCount += 1;\n lastSdkActivity = Date.now();\n\n // Lightweight visibility into every SDK message before normalization\n try {\n const preview = (() => {\n if (!message) return null;\n if (typeof message === \"string\") return message.slice(0, 300);\n\n const m: any = message;\n const content =\n m?.message?.content || m?.content || m?.message?.text || m?.text;\n\n if (typeof content === \"string\") return content.slice(0, 300);\n\n if (Array.isArray(content)) {\n const textBlock = content.find(\n (b: any) => b && b.type === \"text\" && typeof b.text === \"string\"\n );\n if (textBlock) return textBlock.text.slice(0, 300);\n }\n\n try {\n return JSON.stringify(message).slice(0, 300);\n } catch {\n return \"[unstringifiable message]\";\n }\n })();\n\n console.log(\"[NorthflareAgentManager] Agent stream message\", {\n conversationId: context.conversationId,\n agentSessionId: sessionId || context.agentSessionId,\n count: streamedMessageCount,\n type: (message as any)?.type,\n preview,\n });\n } catch (e) {\n console.warn(\n \"[NorthflareAgentManager] Failed to log early agent stream message:\",\n e\n );\n }\n\n await this.handleStreamedMessage(context, message, sessionId);\n\n // Heuristic: detect terminal system events and finalize\n try {\n if (message?.type === \"system\") {\n const m: any = message;\n const subtype = m.subtype || m?.message?.subtype || m?.event;\n const exitSignals = [\n \"exit\",\n \"exiting\",\n \"session_end\",\n \"conversation_end\",\n \"process_exit\",\n \"done\",\n \"completed\",\n ];\n if (subtype && exitSignals.includes(String(subtype))) {\n await this._handleRunCompletion(context, false);\n }\n }\n } catch (e) {\n console.warn(\n \"[NorthflareAgentManager] finalize-on-system heuristic error:\",\n e\n );\n }\n };\n\n if (managerDebug) {\n silenceTimer = setInterval(() => {\n const now = Date.now();\n const idleMs = now - lastSdkActivity;\n if (idleMs >= 5000) {\n console.log(\"[NorthflareAgentManager] Waiting for agent output\", {\n conversationId: context.conversationId,\n agentSessionId: context.agentSessionId || null,\n streamedMessageCount,\n idleMs,\n });\n }\n }, 5000);\n }\n\n // Send initial messages BEFORE starting the stream.\n // This ensures all initial messages are queued and available when the SDK\n // starts iterating, so it can collect them all without timing issues.\n try {\n for (const message of initialMessages) {\n // Use normalizeContentForSDK to preserve multimodal content (images)\n const normalizedContent = this.normalizeContentForSDK(message.content);\n const isMultimodal = Array.isArray(normalizedContent);\n\n console.log(\"[NorthflareAgentManager] Sending initial message to SDK\", {\n conversationId: context.conversationId,\n agentSessionId: context.agentSessionId,\n isMultimodal,\n contentPreview: isMultimodal\n ? `[${normalizedContent.length} blocks: ${normalizedContent.map((b: any) => b.type).join(\", \")}]`\n : (normalizedContent as string).slice(0, 200),\n length: isMultimodal ? normalizedContent.length : (normalizedContent as string).length,\n });\n\n if (isMultimodal) {\n // Send multimodal content blocks directly to the SDK\n conversation.send({\n type: \"multimodal\",\n content: normalizedContent as Array<{ type: string; text?: string; image?: string }>,\n });\n } else {\n conversation.send({\n type: \"text\",\n text: normalizedContent as string,\n });\n }\n }\n\n // Kick off streaming; completion/error is handled by the wrapper's\n // onComplete callback above. (The stream method returns void, so awaiting\n // it would resolve immediately and incorrectly mark the conversation\n // finished.)\n conversation.stream(messageHandler);\n\n // Note: Error handling is done via process completion handler\n // The Northflare Agent SDK doesn't have an onError method on conversations\n\n console.log(\n `Started conversation for ${conversationObjectType} ${conversationObjectId} in workspace ${workspacePath}`\n );\n\n // Return the conversation context directly\n return context;\n } catch (error) {\n // Handle startup errors\n await this._handleConversationError(context, error as Error);\n throw error;\n }\n }\n\n async stopConversation(\n agentSessionId: string,\n context: ConversationContext,\n isRunnerShutdown: boolean = false,\n reason?: string\n ): Promise<void> {\n (context as any)._stopRequested = true;\n if (context && context.conversation) {\n context.status = \"stopping\";\n\n try {\n // Proactively send end notification to avoid missing it on abnormal exits\n // Use provided reason, or fall back to 'runner_shutdown' if isRunnerShutdown is true\n const finalReason =\n reason || (isRunnerShutdown ? \"runner_shutdown\" : undefined);\n (context as any)._stopReason = finalReason;\n await this._finalizeConversation(\n context,\n false,\n undefined,\n finalReason\n ).catch(() => {});\n // Mark conversation as stopped BEFORE ending to prevent race conditions\n context.status = \"stopped\";\n\n // Properly end the conversation using the SDK\n if (isAgentConversation(context.conversation)) {\n await context.conversation.end();\n }\n } catch (error) {\n console.error(`Error ending conversation ${agentSessionId}:`, error);\n }\n\n // Clean up conversation reference\n delete context.conversation;\n }\n\n console.log(\n `Stopped conversation ${agentSessionId} for ${context.conversationObjectType} ${context.conversationObjectId}`\n );\n }\n\n async resumeConversation(\n conversationObjectType: \"Task\" | \"TaskPlan\" | \"ProjectStep\",\n conversationObjectId: string,\n agentSessionId: string,\n config: ConversationConfig,\n conversationData?: any,\n resumeMessage?: string,\n provider: \"openrouter\" | \"groq\" = \"openrouter\"\n ): Promise<string> {\n console.log(\n `[NorthflareAgentManager] Resuming conversation ${agentSessionId}`\n );\n\n // Resume is handled by starting a new conversation with the existing session ID\n const context = await this.startConversation(\n conversationObjectType,\n conversationObjectId,\n { ...config, sessionId: agentSessionId },\n [], // Don't send initial messages\n conversationData,\n provider\n );\n\n // After starting the conversation with the sessionId, we need to send a message\n // to actually trigger the agent process to continue\n if (context.conversation && isAgentConversation(context.conversation)) {\n try {\n // Use the provided resume message or default to system instruction\n const messageToSend =\n resumeMessage ||\n \"<system-instructions>Please continue</system-instructions>\";\n console.log(\n `[NorthflareAgentManager] Sending resume message to conversation ${agentSessionId}`\n );\n context.conversation.send({\n type: \"text\",\n text: messageToSend,\n });\n } catch (error) {\n console.error(\n `[NorthflareAgentManager] Error sending resume message:`,\n error\n );\n }\n } else {\n console.warn(\n \"[NorthflareAgentManager] Resume requested but conversation instance missing or incompatible\"\n );\n }\n\n return context.agentSessionId;\n }\n\n private async _handleRunCompletion(\n context: ConversationContext,\n hadError: boolean,\n error?: any\n ): Promise<void> {\n if ((context as any)._finalized) return;\n\n const inFlight = (context as any)._runCompletionInFlight as\n | Promise<void>\n | undefined;\n if (inFlight) return inFlight;\n\n const promise = (async () => {\n\n const isTaskConversation = context.conversationObjectType === \"Task\";\n const stopRequested = (context as any)._stopRequested === true;\n const taskHandle = (context as any).taskHandle as any;\n const shouldRunGitFlow =\n context.config.useWorktrees !== false &&\n isTaskConversation &&\n !!taskHandle &&\n taskHandle.branch !== \"local\";\n\n if (!shouldRunGitFlow || hadError || stopRequested) {\n await this._finalizeConversation(context, hadError, error);\n return;\n }\n\n const taskId = context.conversationObjectId;\n const baseBranch =\n (context.config.repository?.branch as string | undefined) || \"main\";\n\n try {\n const taskState = await this.repositoryManager.getTaskState(taskId);\n const taskRepoInfo = await this.repositoryManager.getTaskRepoInfo(taskId);\n\n if (\n !taskState ||\n !taskRepoInfo ||\n !taskRepoInfo.worktreePath ||\n taskState.branch === \"local\"\n ) {\n await this._finalizeConversation(context, false);\n return;\n }\n\n const isLocalRepo = taskRepoInfo.repoKey.startsWith(\"local__\");\n const mergeWorkdir = isLocalRepo\n ? taskRepoInfo.controlPath\n : taskRepoInfo.worktreePath;\n\n // If we already have unresolved conflicts, immediately ask the agent to resolve them.\n const taskGit = simpleGit(taskRepoInfo.worktreePath);\n const initialTaskStatus = await taskGit.status();\n if (initialTaskStatus.conflicted.length > 0) {\n await this._resumeForGitConflictResolution(context, {\n kind: \"conflicts\",\n baseBranch,\n conflicts: initialTaskStatus.conflicted,\n workdir: taskRepoInfo.worktreePath,\n });\n return;\n }\n\n if (isLocalRepo && mergeWorkdir !== taskRepoInfo.worktreePath) {\n const mergeGit = simpleGit(mergeWorkdir);\n const mergeStatus = await mergeGit.status();\n if (mergeStatus.conflicted.length > 0) {\n await this._resumeForGitConflictResolution(context, {\n kind: \"conflicts\",\n baseBranch,\n conflicts: mergeStatus.conflicted,\n workdir: mergeWorkdir,\n });\n return;\n }\n }\n\n // Ensure we're on the task branch for commit/rebase operations.\n const currentBranch = (\n await taskGit.revparse([\"--abbrev-ref\", \"HEAD\"])\n ).trim();\n if (currentBranch !== taskState.branch) {\n await taskGit.checkout(taskState.branch);\n }\n\n const status = await taskGit.status();\n if (!status.isClean()) {\n await this.repositoryManager.stageAll(taskId);\n try {\n const previousCommitCount = (taskState as any)?.commitCount ?? 0;\n const baseSubject =\n (context.summary ?? \"\").replace(/\\s+/g, \" \").trim() ||\n `Task ${taskId}`;\n const message =\n previousCommitCount > 0\n ? `${baseSubject} (followup #${previousCommitCount})`\n : baseSubject;\n await this.repositoryManager.commit(taskId, message);\n } catch (commitError) {\n const msg =\n commitError instanceof Error\n ? commitError.message\n : String(commitError);\n if (!msg.toLowerCase().includes(\"nothing to commit\")) {\n throw commitError;\n }\n }\n }\n\n const integrateResult = await this.repositoryManager.integrateTask(\n taskId,\n baseBranch,\n \"no-ff\"\n );\n if (!integrateResult.success) {\n await this._resumeForGitConflictResolution(context, {\n kind: integrateResult.phase,\n baseBranch,\n conflicts: integrateResult.conflicts ?? [],\n workdir: integrateResult.conflictWorkdir,\n error: integrateResult.error,\n });\n return;\n }\n\n // Worktree is no longer needed after a successful merge; preserve the branch\n await this.repositoryManager.removeTaskWorktree(taskId, {\n preserveBranch: true,\n });\n\n const wsId = context.config.workspaceId || context.workspaceId;\n const repoUrl = context.config.repository?.url;\n if (wsId && repoUrl) {\n await this.repositoryManager.syncWorkspaceWorktree(wsId, repoUrl, baseBranch);\n }\n\n await this._finalizeConversation(context, false);\n } catch (mergeError) {\n console.error(\n \"[NorthflareAgentManager] Post-task git flow failed\",\n mergeError\n );\n await this._finalizeConversation(context, true, mergeError);\n }\n })();\n\n (context as any)._runCompletionInFlight = promise.finally(() => {\n delete (context as any)._runCompletionInFlight;\n });\n return (context as any)._runCompletionInFlight;\n }\n\n private async _resumeForGitConflictResolution(\n context: ConversationContext,\n payload: {\n kind: \"conflicts\" | \"rebase\" | \"merge\";\n baseBranch: string;\n conflicts: string[];\n workdir: string;\n error?: string;\n }\n ): Promise<void> {\n const { kind, baseBranch, conflicts, workdir, error } = payload;\n\n const conflictsList = conflicts?.length\n ? `\\n\\nConflicted files:\\n${conflicts.map((f) => `- ${f}`).join(\"\\n\")}`\n : \"\";\n const workdirHint = workdir ? `\\n\\nWork directory:\\n- ${workdir}` : \"\";\n const errorHint = error ? `\\n\\nError:\\n${error}` : \"\";\n const hasConflicts = !!conflicts?.length;\n\n let instruction: string;\n if (kind === \"rebase\") {\n instruction = hasConflicts\n ? `<system-instructions>\\nA git rebase onto \\`${baseBranch}\\` produced merge conflicts.${conflictsList}${workdirHint}${errorHint}\\n\\nPlease resolve the conflicts in that directory, then run:\\n- git add -A\\n- git rebase --continue\\n\\nWhen the rebase finishes cleanly, reply briefly so I can retry the integration.\\n</system-instructions>`\n : `<system-instructions>\\nA git rebase onto \\`${baseBranch}\\` failed.${workdirHint}${errorHint}\\n\\nNo conflicted files were reported. Please run:\\n- git status\\n\\nFix the error (or complete/abort any in-progress git operation) and reply briefly so I can retry the integration.\\n</system-instructions>`;\n } else if (kind === \"merge\") {\n instruction = hasConflicts\n ? `<system-instructions>\\nA git merge into \\`${baseBranch}\\` produced merge conflicts.${conflictsList}${workdirHint}${errorHint}\\n\\nPlease resolve the conflicts in that directory, then run:\\n- git add -A\\n- git commit -m \\\"Resolve merge conflicts for ${context.conversationObjectId}\\\"\\n\\nWhen the working tree is clean, reply briefly so I can retry the integration.\\n</system-instructions>`\n : `<system-instructions>\\nA git merge into \\`${baseBranch}\\` failed.${workdirHint}${errorHint}\\n\\nNo conflicted files were reported. Please run:\\n- git status\\n\\nFix the error (or complete/abort any in-progress git operation) and reply briefly so I can retry the integration.\\n</system-instructions>`;\n } else {\n instruction = `<system-instructions>\\nGit has unresolved conflicts.${conflictsList}${workdirHint}${errorHint}\\n\\nPlease resolve the conflicts in that directory and complete the in-progress git operation (rebase or merge). When the working tree is clean, reply briefly so I can retry the integration.\\n</system-instructions>`;\n }\n\n const conversationData = {\n id: context.conversationId,\n objectType: context.conversationObjectType,\n objectId: context.conversationObjectId,\n model: context.model,\n summary: context.summary ?? null,\n globalInstructions: context.globalInstructions,\n workspaceInstructions: context.workspaceInstructions,\n permissionsMode: context.permissionsMode,\n agentSessionId: context.agentSessionId,\n };\n\n await this.resumeConversation(\n context.conversationObjectType,\n context.conversationObjectId,\n context.agentSessionId,\n context.config,\n conversationData,\n instruction,\n context.provider === \"groq\" ? \"groq\" : \"openrouter\"\n );\n }\n\n private async _finalizeConversation(\n context: ConversationContext,\n hadError: boolean,\n error?: any,\n reason?: string\n ): Promise<void> {\n // Synchronous idempotency check - must happen before any async operations\n if ((context as any)._finalized) return;\n (context as any)._finalized = true;\n\n try {\n const clearSilenceTimer = (context as any)._clearSilenceTimer;\n if (typeof clearSilenceTimer === \"function\") {\n clearSilenceTimer();\n }\n } catch {}\n\n // Mark as completed immediately to prevent restart on catch-up\n // This is synchronous and happens before any async operations\n this.runner.markConversationCompleted(context.conversationId);\n\n // Clean up conversation from active conversations (synchronous)\n try {\n console.log(\n `[NorthflareAgentManager] Removing conversation from active map:`,\n {\n conversationId: context.conversationId,\n agentSessionId: context.agentSessionId,\n mapSizeBefore: this.runner.activeConversations_.size,\n }\n );\n this.runner.activeConversations_.delete(context.conversationId);\n // Clean up submit tool tracking\n this.submitToolUseIds.delete(context.conversationId);\n statusLineManager.updateActiveCount(\n this.runner.activeConversations_.size\n );\n } catch {}\n\n // Now do async notification (after all sync cleanup)\n try {\n await this.runner.notify(\"conversation.end\", {\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n agentSessionId: context.agentSessionId,\n isError: hadError,\n errorMessage: error?.message,\n reason: reason,\n });\n } catch (e) {\n console.error(\n \"[NorthflareAgentManager] Failed to notify conversation.end:\",\n e\n );\n }\n\n // Notify update coordinator that a conversation has ended\n // This may trigger an auto-update if one is pending and runner is now idle\n try {\n await this.runner.onConversationEnd();\n } catch (e) {\n console.error(\n \"[NorthflareAgentManager] Failed to notify onConversationEnd:\",\n e\n );\n }\n }\n\n async sendUserMessage(\n conversationId: string,\n content: any,\n config?: ConversationConfig,\n conversationObjectType?: \"Task\" | \"TaskPlan\" | \"ProjectStep\",\n conversationObjectId?: string,\n conversation?: any,\n _agentSessionIdOverride?: string\n ): Promise<void> {\n console.log(`[NorthflareAgentManager] sendUserMessage called with:`, {\n conversationId,\n conversationObjectType,\n conversationObjectId,\n hasConfig: !!config,\n hasConversation: !!conversation,\n activeConversations: this.runner.activeConversations_.size,\n });\n\n // Find by conversationId only\n let context = this.runner.getConversationContext(conversationId);\n console.log(`[NorthflareAgentManager] Lookup by conversationId result:`, {\n found: !!context,\n conversationId: context?.conversationId,\n agentSessionId: context?.agentSessionId,\n });\n\n if (!context && conversation) {\n // Use provided conversation details\n try {\n const conversationDetails = conversation;\n console.log(\n `[NorthflareAgentManager] Using provided config from RunnerMessage:`,\n {\n hasConfig: !!config,\n hasRepository: !!config?.repository,\n repositoryType: config?.repository?.type,\n repositoryPath: config?.repository?.localPath,\n hasTokens: !!(config?.accessToken || config?.githubToken),\n hasMcpServers: !!config?.mcpServers,\n }\n );\n\n // Use the config that was already prepared by TaskOrchestrator and sent in the RunnerMessage\n const startConfig: ConversationConfig = {\n anthropicApiKey:\n config?.anthropicApiKey || process.env[\"ANTHROPIC_API_KEY\"] || \"\",\n systemPrompt:\n config?.systemPrompt || (conversationDetails as any)?.systemPrompt,\n systemPromptMode:\n config?.systemPromptMode ||\n (conversationDetails as any)?.systemPromptMode,\n workspaceId: conversationDetails.workspaceId,\n ...config, // Use the full config provided in the RunnerMessage\n ...(conversationDetails.agentSessionId\n ? { sessionId: conversationDetails.agentSessionId }\n : {}),\n };\n\n // Start the SDK conversation (no initial messages); this attaches to existing session when provided\n const derivedProvider =\n (conversationDetails as any)?.provider ||\n (startConfig as any)?.providerType ||\n \"openrouter\";\n\n await this.startConversation(\n conversationDetails.objectType,\n conversationDetails.objectId,\n startConfig,\n [],\n conversationDetails,\n derivedProvider as any\n );\n\n // Refresh context after start/resume\n context = this.runner.getConversationContext(conversationId);\n } catch (error) {\n console.error(`Failed to fetch conversation ${conversationId}:`, error);\n }\n }\n\n if (!context) {\n throw new Error(\n `No active or fetchable conversation found for ${conversationId}`\n );\n }\n\n try {\n // Send immediately when a conversation instance exists; no need to wait for \"active\"\n if (!context.conversation || !isAgentConversation(context.conversation)) {\n throw new Error(\n `No conversation instance found for conversation ${context.conversationId}`\n );\n }\n\n // Guard: Don't send messages if conversation is stopped or stopping\n const conversationStatus = context.status as string;\n if (\n conversationStatus === \"stopped\" ||\n conversationStatus === \"stopping\"\n ) {\n console.warn(\n `Attempted to send message to stopped/stopping conversation ${context.conversationId}`,\n {\n status: context.status,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n }\n );\n return;\n }\n\n // Native message injection - SDK handles queueing and delivery\n // Use normalizeContentForSDK to preserve multimodal content (images)\n const normalizedContent = this.normalizeContentForSDK(content);\n const isMultimodal = Array.isArray(normalizedContent);\n\n if (isDebugEnabledFor(\"manager\")) {\n console.log(\"[NorthflareAgentManager] Normalized follow-up content\", {\n originalType: typeof content,\n isArray: Array.isArray(content) || undefined,\n isMultimodal,\n normalizedPreview: isMultimodal\n ? `[${normalizedContent.length} blocks: ${normalizedContent.map((b: any) => b.type).join(\", \")}]`\n : (normalizedContent as string).slice(0, 160),\n });\n }\n\n if (isMultimodal) {\n // Send multimodal content blocks directly to the SDK\n // Use any cast to bypass type restrictions - our wrapper supports this\n (context.conversation as any).send({\n type: \"multimodal\",\n content: normalizedContent as Array<{ type: string; text?: string; image?: string }>,\n });\n } else {\n context.conversation.send({\n type: \"text\",\n text: normalizedContent as string,\n });\n }\n\n // Update last activity timestamp\n context.lastActivityAt = new Date();\n\n console.log(\n `Sent user message to conversation ${context.conversationId} (agentSessionId: ${context.agentSessionId}, status: ${context.status})`\n );\n } catch (error) {\n // Handle errors properly\n await this._handleConversationError(context, error as Error);\n throw error; // Re-throw to maintain the same behavior\n }\n }\n\n private async fetchGithubTokens(\n workspaceId: string\n ): Promise<string | undefined> {\n try {\n const response = await fetch(\n `${this.runner.config_.orchestratorUrl}/api/runner/tokens?workspaceId=${workspaceId}`,\n {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${process.env[\"NORTHFLARE_RUNNER_TOKEN\"]}`,\n },\n }\n );\n\n if (!response.ok) {\n console.error(`Failed to fetch GitHub tokens: ${response.status}`);\n return undefined;\n }\n\n const data = (await response.json()) as { githubToken?: string };\n return data.githubToken;\n } catch (error) {\n console.error(\"Error fetching GitHub tokens:\", error);\n return undefined;\n }\n }\n\n private async _handleConversationError(\n context: ConversationContext,\n error: Error\n ): Promise<void> {\n const errorType = this.classifyError(error);\n\n // Notify orchestrator\n await this.runner.notify(\"error.report\", {\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n agentSessionId: context.agentSessionId,\n errorType,\n message: error.message,\n details: {\n stack: error.stack,\n timestamp: new Date(),\n },\n });\n\n // Conversation continues on error - no automatic cleanup\n console.error(\n `Conversation error for ${context.conversationObjectType} ${context.conversationObjectId}:`,\n error\n );\n }\n\n private classifyError(error: Error): string {\n const msg = error.message.toLowerCase();\n if (msg.includes(\"process exited\")) {\n return \"process_exit\";\n } else if (msg.includes(\"model\")) {\n return \"model_error\";\n } else if (msg.includes(\"tool\")) {\n return \"tool_error\";\n } else if (\n msg.includes(\"permission\") ||\n msg.includes(\"forbidden\") ||\n msg.includes(\"403\")\n ) {\n return \"permission_error\";\n } else if (msg.includes(\"timeout\")) {\n return \"timeout_error\";\n } else if (\n msg.includes(\"unauthorized\") ||\n msg.includes(\"401\") ||\n msg.includes(\"authentication\")\n ) {\n return \"auth_error\";\n } else if (\n msg.includes(\"rate limit\") ||\n msg.includes(\"429\") ||\n msg.includes(\"too many requests\")\n ) {\n return \"rate_limit_error\";\n } else if (\n msg.includes(\"api\") ||\n msg.includes(\"network\") ||\n msg.includes(\"fetch\") ||\n msg.includes(\"connection\")\n ) {\n return \"api_error\";\n }\n return \"unknown_error\";\n }\n\n private normalizeModel(rawModel: string | undefined): string {\n if (!rawModel) {\n throw new Error(\"normalizeModel called without a model; caller must supply one.\");\n }\n\n const trimmed = rawModel.trim();\n\n if (trimmed.startsWith(\"openrouter:\")) {\n return trimmed.slice(\"openrouter:\".length);\n }\n\n if (trimmed.startsWith(\"openrouter/\")) {\n return trimmed.slice(\"openrouter/\".length);\n }\n\n if (trimmed.startsWith(\"groq:\")) {\n return trimmed.slice(\"groq:\".length);\n }\n\n if (trimmed.startsWith(\"groq/\")) {\n return trimmed.slice(\"groq/\".length);\n }\n\n if (!trimmed) {\n throw new Error(\"Model string cannot be empty.\");\n }\n\n return trimmed;\n }\n\n /**\n * Check if content contains multimodal blocks (images or documents)\n */\n private hasMultimodalContent(value: any): boolean {\n if (!Array.isArray(value)) return false;\n return value.some(\n (item) =>\n item &&\n typeof item === \"object\" &&\n (item.type === \"image\" || item.type === \"document\")\n );\n }\n\n /**\n * Normalize content for the SDK, preserving multimodal blocks when present.\n * Returns either a string (text-only) or an array of content blocks (multimodal).\n */\n private normalizeContentForSDK(\n value: any\n ): string | Array<{ type: string; text?: string; image?: string }> {\n // If it's an array with multimodal content, convert to SDK format\n if (Array.isArray(value) && this.hasMultimodalContent(value)) {\n const blocks: Array<{ type: string; text?: string; image?: string }> = [];\n\n for (const item of value) {\n if (!item || typeof item !== \"object\") continue;\n\n if (item.type === \"text\" && typeof item.text === \"string\") {\n blocks.push({ type: \"text\", text: item.text });\n } else if (item.type === \"image\" && item.source) {\n // Convert image blocks: { type: \"image\", source: { type: \"url\", url: \"...\" } }\n // to SDK format: { type: \"image\", image: \"...\" }\n const imageUrl =\n item.source.type === \"url\" ? item.source.url : item.source.data;\n if (imageUrl) {\n blocks.push({ type: \"image\", image: imageUrl });\n }\n } else if (item.type === \"document\" && item.source) {\n // Documents (PDFs) - the SDK doesn't have native document support,\n // so we include them as text with the URL for now\n // TODO: When SDK adds document support, update this\n const docUrl =\n item.source.type === \"url\" ? item.source.url : item.source.data;\n if (docUrl) {\n // For now, add PDF URL as text since SDK doesn't support documents directly\n // The model can still access PDFs via URL if supported\n blocks.push({\n type: \"text\",\n text: `[PDF Document: ${docUrl}]`,\n });\n }\n }\n }\n\n // If we have any image blocks, return the multimodal array\n if (blocks.some((b) => b.type === \"image\")) {\n return blocks;\n }\n // Otherwise, fall back to text extraction\n }\n\n // Fall back to text-only normalization\n return this.normalizeToText(value);\n }\n\n /**\n * Normalize arbitrary content shapes into a plain string for the CLI\n */\n private normalizeToText(value: any): string {\n if (typeof value === \"string\") return value;\n if (value == null) return \"\";\n\n if (typeof value === \"object\") {\n // Common simple shapes\n if (typeof (value as any).text === \"string\") return (value as any).text;\n if (\n typeof (value as any).text === \"object\" &&\n (value as any).text &&\n typeof (value as any).text.text === \"string\"\n )\n return (value as any).text.text;\n if (typeof (value as any).content === \"string\")\n return (value as any).content;\n\n // Array of blocks: [{ type: 'text', text: '...' }, ...]\n if (Array.isArray(value)) {\n const texts = value\n .map((b) =>\n b && b.type === \"text\" && typeof b.text === \"string\" ? b.text : null\n )\n .filter((t): t is string => !!t);\n if (texts.length) return texts.join(\" \");\n }\n\n // Nested message shapes\n if (\n typeof (value as any).message === \"object\" &&\n (value as any).message &&\n typeof (value as any).message.text === \"string\"\n ) {\n return (value as any).message.text;\n }\n }\n\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n }\n\n private async handleStreamedMessage(\n context: ConversationContext,\n message: SDKMessage,\n sessionId: string | null\n ): Promise<void> {\n /*\n * SDK tool call payload reference (observed shapes)\n *\n * 1) Assistant tool call (tool_use)\n * {\n * \"type\": \"assistant\",\n * \"message\": {\n * \"role\": \"assistant\",\n * \"content\": [\n * { \"type\": \"text\", \"text\": \"…optional text…\" },\n * { \"type\": \"tool_use\", \"id\": \"toolu_01Nbv…\", \"name\": \"TodoWrite\", \"input\": { ... } }\n * ]\n * },\n * \"session_id\": \"…\"\n * }\n *\n * 2) Tool result (often emitted as type 'user')\n * {\n * \"type\": \"user\",\n * \"message\": {\n * \"role\": \"user\",\n * \"content\": [\n * {\n * \"tool_use_id\": \"toolu_01E9R475…\",\n * \"type\": \"tool_result\",\n * \"content\": \"Todos have been modified successfully. …\"\n * }\n * ]\n * },\n * \"parent_tool_use_id\": null,\n * \"session_id\": \"…\",\n * \"uuid\": \"…\"\n * }\n *\n * Normalization (runner → server message.agent):\n * - assistant tool_use → type: 'assistant', content: [{ toolCalls: [{ id, name, arguments }] }, …]\n * - tool_result (any shape) → type: 'tool_result', subtype: 'tool_result', content:\n * [ { type: 'tool_result', subtype: 'tool_result', tool_use_id, content } ]\n */\n // Guard: Don't process messages if conversation is stopped or stopping\n const status = context.status as string;\n if (status === \"stopped\" || status === \"stopping\") {\n console.log(\n `Ignoring message for stopped/stopping conversation ${context.conversationId}`,\n {\n status: context.status,\n messageType: message.type,\n }\n );\n return;\n }\n\n try {\n // High-level receipt log\n console.log(\n `Received streamed message for ${context.conversationObjectType} ${context.conversationObjectId}`,\n {\n type: message?.type,\n }\n );\n\n // Raw SDK message diagnostics\n try {\n // Log the full raw SDK message safely (handles circular refs)\n const safeStringify = (obj: any) => {\n const seen = new WeakSet();\n return JSON.stringify(\n obj,\n (key, value) => {\n if (typeof value === \"function\") return undefined;\n if (typeof value === \"bigint\") return String(value);\n if (typeof value === \"object\" && value !== null) {\n if (seen.has(value)) return \"[Circular]\";\n seen.add(value);\n }\n return value;\n },\n 2\n );\n };\n\n console.log(\n \"[NorthflareAgentManager] RAW SDK message FULL:\",\n safeStringify(message)\n );\n\n const summary = {\n keys: Object.keys(message || {}),\n hasMessage: !!(message as any)?.message,\n contentType: typeof (message as any)?.content,\n messageContentType: typeof (message as any)?.message?.content,\n sessionId:\n (message as any)?.session_id || (message as any)?.sessionId || null,\n };\n console.log(\n \"[NorthflareAgentManager] RAW SDK message summary:\",\n summary\n );\n if ((message as any)?.content !== undefined) {\n console.log(\n \"[NorthflareAgentManager] RAW SDK content:\",\n (message as any).content\n );\n }\n if ((message as any)?.message?.content !== undefined) {\n console.log(\n \"[NorthflareAgentManager] RAW SDK nested content:\",\n (message as any).message.content\n );\n }\n\n // Highlight tool calls as soon as they appear so downstream observers\n // can correlate real-time activity without waiting for the final result.\n if (message?.type === \"assistant\") {\n const assistantMsg: any = message;\n const toolBlocks = Array.isArray(assistantMsg?.message?.content)\n ? assistantMsg.message.content.filter(\n (part: any) => part?.type === \"tool_use\"\n )\n : [];\n\n if (toolBlocks.length > 0) {\n console.log(\n \"[NorthflareAgentManager] Agent announced tool calls\",\n toolBlocks.map((part: any) => ({\n id: part?.id,\n name: part?.name,\n }))\n );\n }\n }\n } catch (e) {\n console.warn(\n \"[NorthflareAgentManager] Failed to log raw SDK message:\",\n e\n );\n }\n\n // Build structured content based on message type\n let messageType: string = message.type;\n let subtype: string | undefined;\n let structuredContent: any = {};\n let isError = false;\n let skipSend = false;\n let metadata: any = null;\n const mergeMetadata = (extra?: Record<string, any> | null) => {\n if (!extra) return;\n metadata = metadata ? { ...metadata, ...extra } : extra;\n };\n\n // Extract parent_tool_use_id if present (for all message types)\n const msgAsAny = message as any;\n if (msgAsAny.parent_tool_use_id) {\n mergeMetadata({\n parent_tool_use_id: msgAsAny.parent_tool_use_id,\n });\n }\n\n // Extract content based on message type\n switch (message.type) {\n case \"assistant\": {\n const assistantMsg = message as any;\n const blocks =\n assistantMsg?.message?.content || assistantMsg?.content || [];\n const textContent = Array.isArray(blocks)\n ? blocks\n .filter(\n (b: any) =>\n b && b.type === \"text\" && typeof b.text === \"string\"\n )\n .map((b: any) => b.text)\n .join(\"\")\n : \"\";\n const toolCalls = Array.isArray(blocks)\n ? blocks\n .filter((b: any) => b && b.type === \"tool_use\")\n .map((b: any) => ({\n id: b.id,\n name: b.name,\n arguments: b.input,\n }))\n : undefined;\n\n // Track submit tool calls for special handling of their results\n if (toolCalls && toolCalls.length > 0) {\n const submitTools = toolCalls.filter(\n (tc: any) => tc.name === \"submit\"\n );\n if (submitTools.length > 0) {\n if (!this.submitToolUseIds.has(context.conversationId)) {\n this.submitToolUseIds.set(context.conversationId, new Set());\n }\n const submitIds = this.submitToolUseIds.get(\n context.conversationId\n )!;\n submitTools.forEach((st: any) => submitIds.add(st.id));\n console.log(\n `[NorthflareAgentManager] Tracking submit tool calls:`,\n {\n conversationId: context.conversationId,\n submitToolIds: submitTools.map((st: any) => st.id),\n }\n );\n }\n }\n\n structuredContent = {\n ...(textContent ? { text: textContent } : {}),\n ...(toolCalls && toolCalls.length ? { toolCalls } : {}),\n timestamp: new Date().toISOString(),\n };\n break;\n }\n\n case \"thinking\" as any: {\n messageType = \"thinking\";\n subtype = undefined;\n const thinkingMsg = message as any;\n structuredContent = [\n {\n type: \"thinking\",\n thinking: thinkingMsg.content || \"\",\n text: thinkingMsg.content || \"\",\n timestamp: new Date().toISOString(),\n },\n ];\n break;\n }\n\n case \"tool_use\" as any: {\n // Tool call request - map to assistant\n messageType = \"assistant\";\n subtype = \"tool_use\";\n const toolUseMsg = message as any;\n structuredContent = {\n toolCalls: [\n {\n id: toolUseMsg.id,\n name: toolUseMsg.name,\n arguments: toolUseMsg.input,\n },\n ],\n timestamp: new Date().toISOString(),\n };\n break;\n }\n\n case \"tool_result\" as any: {\n const toolResultMsg = message as any;\n const toolName =\n toolResultMsg.tool_name ||\n toolResultMsg.name ||\n toolResultMsg?.toolCall?.name ||\n null;\n const toolUseId =\n toolResultMsg.tool_use_id ||\n toolResultMsg.tool_call_id ||\n toolResultMsg.id ||\n toolResultMsg?.message?.id;\n\n const resolvedContent = (() => {\n if (\n \"content\" in toolResultMsg &&\n toolResultMsg.content !== undefined\n ) {\n return toolResultMsg.content;\n }\n if (toolResultMsg.result !== undefined) {\n return toolResultMsg.result;\n }\n if (toolResultMsg.output !== undefined) {\n return toolResultMsg.output;\n }\n if (toolResultMsg?.message?.content !== undefined) {\n return toolResultMsg.message.content;\n }\n return null;\n })();\n\n // Check if this is a submit tool result\n const submitIds = this.submitToolUseIds.get(context.conversationId);\n const isSubmitTool = submitIds && submitIds.has(toolUseId);\n\n if (isSubmitTool) {\n // Convert submit tool result to assistant message\n const previewSource =\n resolvedContent ?? toolResultMsg.content ?? null;\n let previewText = \"[no content]\";\n if (typeof previewSource === \"string\") {\n previewText = previewSource.slice(0, 100);\n } else if (previewSource !== null) {\n try {\n previewText = JSON.stringify(previewSource).slice(0, 100);\n } catch {\n previewText = String(previewSource);\n }\n }\n\n console.log(\n `[NorthflareAgentManager] Converting submit tool result to assistant message:`,\n {\n conversationId: context.conversationId,\n toolUseId,\n contentPreview: previewText,\n }\n );\n\n messageType = \"assistant\";\n subtype = \"submit_result\";\n\n // Extract the text content from the tool result\n let textContent = \"\";\n if (typeof resolvedContent === \"string\") {\n textContent = resolvedContent;\n } else if (Array.isArray(resolvedContent)) {\n // Handle array of content blocks\n textContent = resolvedContent\n .filter(\n (b: any) =>\n b && b.type === \"text\" && typeof b.text === \"string\"\n )\n .map((b: any) => b.text)\n .join(\"\");\n } else if (resolvedContent && typeof resolvedContent === \"object\") {\n // Handle object with text property\n if (typeof (resolvedContent as any).text === \"string\") {\n textContent = (resolvedContent as any).text;\n } else if (typeof (resolvedContent as any).result === \"string\") {\n textContent = (resolvedContent as any).result;\n }\n }\n\n structuredContent = {\n text: textContent,\n timestamp: new Date().toISOString(),\n metadata: {\n source: \"submit_tool\",\n tool_use_id: toolUseId,\n },\n };\n\n // Remove this tool_use_id from tracking\n submitIds.delete(toolUseId);\n if (submitIds.size === 0) {\n this.submitToolUseIds.delete(context.conversationId);\n }\n } else {\n // Regular tool result - normalize to v1-style tool_result blocks\n messageType = \"tool_result\";\n subtype = \"tool_result\";\n structuredContent = [\n {\n type: \"tool_result\",\n subtype: \"tool_result\",\n tool_use_id: toolUseId,\n content: resolvedContent, // Keep content as native (array or string)\n timestamp: new Date().toISOString(),\n },\n ];\n\n const toolCallMetadata: Record<string, any> = {};\n if (toolUseId) {\n toolCallMetadata[\"id\"] = toolUseId;\n }\n if (toolName) {\n toolCallMetadata[\"name\"] = toolName;\n }\n\n mergeMetadata({\n ...(toolName ? { tool_name: toolName } : {}),\n ...(Object.keys(toolCallMetadata).length > 0\n ? { toolCall: toolCallMetadata }\n : {}),\n });\n }\n break;\n }\n\n case \"result\": {\n const resultMsg = message as any;\n structuredContent = {\n text: resultMsg.content || resultMsg.result || \"\",\n timestamp: new Date().toISOString(),\n };\n break;\n }\n\n case \"user\": {\n const userMsg = message as any;\n\n // Skip user messages that were sent by the runner itself (already in database via orchestrator)\n // Only process user messages that contain tool results (which need special handling)\n const rawContent =\n (userMsg && userMsg.message && userMsg.message.content) ||\n userMsg?.content ||\n [];\n\n // Check if this is a tool result message (needs processing)\n const blocks =\n typeof rawContent === \"string\"\n ? [{ type: \"text\", text: rawContent }]\n : rawContent;\n\n if (Array.isArray(blocks)) {\n const hasToolResult = blocks.some(\n (b: any) => b && typeof b === \"object\" && b.type === \"tool_result\"\n );\n\n if (hasToolResult) {\n // Normalize tool_result blocks to v1-style\n messageType = \"tool_result\";\n subtype = \"tool_result\";\n structuredContent = blocks\n .filter((b: any) => b && b.type === \"tool_result\")\n .map((b: any) => ({\n type: \"tool_result\",\n subtype: \"tool_result\",\n tool_use_id: b.tool_use_id || b.toolUseId || b.id,\n content: b.content, // Keep content as native (array or string)\n }));\n } else {\n // Regular user messages (non-tool-result) are already created by the orchestrator\n // Skip them to avoid duplicates\n console.log(\n \"[NorthflareAgentManager] Skipping regular user message (already in database via orchestrator)\"\n );\n skipSend = true;\n\n // Special case: Check if this is a subagent prompt (has parent_tool_use_id)\n if (userMsg.parent_tool_use_id) {\n // These should still be processed as assistant messages\n console.log(\n \"[NorthflareAgentManager] Detected subagent prompt message (parent_tool_use_id present, no tool_result)\",\n {\n parent_tool_use_id: userMsg.parent_tool_use_id,\n }\n );\n skipSend = false; // Don't skip subagent prompts\n messageType = \"assistant\"; // Change from \"user\" to \"assistant\"\n subtype = \"subagent_prompt\";\n const textContent = blocks\n .filter(\n (b: any) =>\n b && b.type === \"text\" && typeof b.text === \"string\"\n )\n .map((b: any) => b.text)\n .join(\"\");\n structuredContent = {\n text: textContent,\n timestamp: new Date().toISOString(),\n };\n // metadata already set above with parent_tool_use_id\n }\n }\n\n // If content array only contains empty objects, skip sending\n if (\n Array.isArray(structuredContent) &&\n structuredContent.length > 0 &&\n structuredContent.every(\n (it: any) =>\n !it || typeof it !== \"object\" || Object.keys(it).length === 0\n )\n ) {\n console.log(\n \"[NorthflareAgentManager] Skipping empty 'user' message with only empty objects from SDK\"\n );\n skipSend = true;\n }\n } else if (typeof userMsg?.content === \"string\") {\n // Attempt to parse JSON arrays (common for tool_result payloads)\n const text = userMsg.content;\n try {\n const parsed = JSON.parse(text);\n if (Array.isArray(parsed)) {\n const hasToolResult = parsed.some(\n (item: any) =>\n item &&\n typeof item === \"object\" &&\n item.type === \"tool_result\"\n );\n if (hasToolResult) {\n messageType = \"tool_result\";\n subtype = \"tool_result\";\n structuredContent = parsed;\n } else {\n // Regular user message in JSON array format - skip\n console.log(\n \"[NorthflareAgentManager] Skipping regular user message from JSON array (already in database)\"\n );\n skipSend = true;\n }\n } else {\n // Regular user message as parsed JSON - skip\n console.log(\n \"[NorthflareAgentManager] Skipping regular user message from parsed JSON (already in database)\"\n );\n skipSend = true;\n }\n } catch {\n // Not JSON - regular text user message - skip\n console.log(\n \"[NorthflareAgentManager] Skipping regular text user message (already in database)\"\n );\n skipSend = true;\n }\n } else {\n // Other object content - skip regular user messages\n console.log(\n \"[NorthflareAgentManager] Skipping regular user message with object content (already in database)\"\n );\n skipSend = true;\n }\n break;\n }\n\n case \"system\": {\n const systemMsg = message as any;\n const subtype = systemMsg.subtype || \"system\";\n const model = systemMsg.model || systemMsg?.message?.model;\n const permissionMode =\n systemMsg.permissionMode || systemMsg?.message?.permissionMode;\n const summary = [\n subtype && `[${subtype}]`,\n model && `model=${model}`,\n permissionMode && `perm=${permissionMode}`,\n ]\n .filter(Boolean)\n .join(\" \");\n structuredContent = {\n text: summary || \"\",\n timestamp: new Date().toISOString(),\n };\n break;\n }\n\n case \"error\" as any: {\n const errorMsg = message as any;\n messageType = \"system\";\n subtype = \"error\";\n isError = true;\n structuredContent = {\n text: errorMsg.message || errorMsg.error || \"Unknown error\",\n errorType: errorMsg.error_type || \"unknown\",\n errorDetails: {\n stack: errorMsg.stack,\n code: errorMsg.code,\n context: errorMsg,\n },\n timestamp: new Date().toISOString(),\n };\n break;\n }\n\n case \"result\" as any: {\n // SDK result message - check if it's an error result\n const resultMsg = message as any;\n const resultIsError = resultMsg.is_error === true;\n const resultSubtype = resultMsg.subtype || \"success\";\n const errorMessage = resultMsg.error_message || resultMsg.result || \"\";\n\n if (resultIsError) {\n // Store the SDK error in context metadata so onComplete knows about it\n context.metadata = context.metadata || {};\n context.metadata[\"_sdkError\"] = {\n isError: true,\n errorMessage: errorMessage,\n subtype: resultSubtype,\n };\n\n console.log(\n \"[NorthflareAgentManager] SDK result message indicates error\",\n {\n conversationId: context.conversationId,\n subtype: resultSubtype,\n errorMessage: errorMessage?.slice?.(0, 200),\n }\n );\n\n messageType = \"system\";\n subtype = \"error\";\n isError = true;\n structuredContent = {\n text: errorMessage || \"SDK execution error\",\n errorType: resultSubtype,\n errorDetails: {\n sdk_subtype: resultSubtype,\n duration_ms: resultMsg.duration_ms,\n num_turns: resultMsg.num_turns,\n },\n timestamp: new Date().toISOString(),\n };\n } else {\n // Success result - just log it, don't send as a separate message\n console.log(\n \"[NorthflareAgentManager] SDK result message (success)\",\n {\n conversationId: context.conversationId,\n subtype: resultSubtype,\n resultPreview: (resultMsg.result || \"\").slice?.(0, 100),\n }\n );\n skipSend = true;\n }\n break;\n }\n\n default: {\n // Unknown message type - log and send as assistant\n const unknownMsg = message as any;\n console.warn(`Unknown message type: ${unknownMsg.type}`, message);\n messageType = \"assistant\";\n structuredContent = {\n text: JSON.stringify(message),\n timestamp: new Date().toISOString(),\n };\n }\n }\n\n // Generate a unique message ID\n const messageId = `${context.agentSessionId}-${Date.now()}-${Math.random()\n .toString(36)\n .substr(2, 9)}`;\n\n // Send agent message to orchestrator with structured content\n // Skip if conversation is stopping/stopped to avoid race conditions\n const currentStatus = context.status as string;\n if (currentStatus !== \"stopped\" && currentStatus !== \"stopping\") {\n if (skipSend) {\n console.log(\n \"[NorthflareAgentManager] Not sending message.agent due to skipSend=true\"\n );\n return;\n }\n\n const payload: any = {\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n agentSessionId: context.agentSessionId,\n type: messageType,\n subtype,\n content: Array.isArray(structuredContent)\n ? structuredContent\n : [structuredContent],\n messageId,\n isError,\n };\n\n // Add metadata if present\n if (metadata) {\n payload.metadata = metadata;\n }\n\n try {\n console.log(\n \"[NorthflareAgentManager] Sending message.agent payload:\",\n {\n type: payload.type,\n subtype: payload.subtype,\n contentPreview: Array.isArray(payload.content)\n ? payload.content.slice(0, 1)\n : payload.content,\n }\n );\n } catch {}\n\n await this.runner.notify(\"message.agent\", payload as any);\n try {\n console.log(\"[NorthflareAgentManager] message.agent dispatched\", {\n conversationId: context.conversationId,\n agentSessionId: context.agentSessionId,\n messageId,\n type: payload.type,\n subtype: payload.subtype,\n });\n\n // If the main agent sent a submit tool result, treat it as terminal and finalize\n if (payload.subtype === \"submit_result\") {\n console.log(\n \"[NorthflareAgentManager] Submit tool detected - finalizing conversation\",\n {\n conversationId: context.conversationId,\n agentSessionId: context.agentSessionId,\n }\n );\n // End SDK conversation to stop further streaming\n try {\n if (\n context.conversation &&\n isAgentConversation(context.conversation)\n ) {\n await context.conversation.end();\n }\n } catch (e) {\n console.warn(\n \"[NorthflareAgentManager] Error ending conversation on submit:\",\n e\n );\n }\n await this._finalizeConversation(\n context,\n false,\n undefined,\n \"submit_tool\"\n );\n }\n } catch {}\n }\n\n // Tool calls are handled directly by the agent through the MCP server\n // We just log that we saw them but don't intercept or process them\n if (\n structuredContent.toolCalls &&\n structuredContent.toolCalls.length > 0\n ) {\n console.log(\n `Northflare Agent is making ${structuredContent.toolCalls.length} tool call(s) via MCP`,\n {\n conversationObjectId: context.conversationObjectId,\n toolNames: structuredContent.toolCalls.map((tc: any) => tc.name),\n }\n );\n }\n } catch (error) {\n // Check if this is a transport error due to stopped conversation\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n const isTransportError =\n errorMessage.includes(\"Cannot read properties of undefined\") ||\n errorMessage.includes(\"stdout\") ||\n errorMessage.includes(\"transport\");\n\n const statusCheck = context.status as string;\n if (\n isTransportError &&\n (statusCheck === \"stopped\" || statusCheck === \"stopping\")\n ) {\n // This is expected when conversation is stopped - just log it\n console.log(\n `Transport error for stopped/stopping conversation ${context.conversationId} (expected):`,\n errorMessage\n );\n return;\n }\n\n console.error(\n `Error handling streamed message for ${context.conversationObjectType} ${context.conversationObjectId}:`,\n error\n );\n await this._handleConversationError(context, error as Error);\n }\n }\n}\n\n// Simplified helper functions for SDK integration\n\ntype UserMessageStream = {\n iterable: AsyncIterable<any>;\n enqueue: (msg: any) => void;\n close: () => void;\n};\n\nfunction createUserMessageStream(): UserMessageStream {\n const queue: any[] = [];\n let resolver: (() => void) | null = null;\n let done = false;\n\n async function* iterator() {\n while (true) {\n if (queue.length > 0) {\n const value = queue.shift();\n // Attach metadata about remaining queue length so consumers can check\n // if more messages are immediately available without Promise.race tricks\n if (value && typeof value === \"object\") {\n (value as any).__queueHasMore = queue.length > 0;\n }\n yield value;\n continue;\n }\n if (done) return;\n await new Promise<void>((resolve) => (resolver = resolve));\n resolver = null;\n }\n }\n\n return {\n iterable: iterator(),\n enqueue: (msg: any) => {\n if (done) return;\n queue.push(msg);\n if (resolver) {\n const r = resolver;\n resolver = null;\n r();\n }\n },\n close: () => {\n done = true;\n if (resolver) {\n const r = resolver;\n resolver = null;\n r();\n }\n },\n };\n}\n\nfunction createConversationWrapper(\n sdk: any,\n input: UserMessageStream,\n onComplete?: (hadError: boolean, error?: any) => Promise<void> | void\n) {\n let onSessionIdCb: ((id: string) => void) | null = null;\n let observedSessionId: string | null = null;\n let startedReader = false;\n\n // Create SDK user message from text or multimodal content\n function toSdkUserMessage(\n content: string | Array<{ type: string; text?: string; image?: string }>\n ) {\n // If content is an array with image blocks, convert to SDK multimodal format\n if (Array.isArray(content)) {\n const sdkContent = content.map((block) => {\n if (block.type === \"text\" && block.text) {\n return { type: \"text\" as const, text: block.text };\n } else if (block.type === \"image\" && block.image) {\n return { type: \"image\" as const, image: block.image };\n }\n return null;\n }).filter(Boolean);\n\n return {\n type: \"user\",\n session_id: observedSessionId || \"\",\n parent_tool_use_id: null,\n message: {\n role: \"user\",\n content: sdkContent,\n },\n };\n }\n\n // Plain text message\n return {\n type: \"user\",\n session_id: observedSessionId || \"\",\n parent_tool_use_id: null,\n message: {\n role: \"user\",\n content: content,\n },\n };\n }\n\n return {\n // Send a message - accepts either text-only or multimodal content\n send(payload: {\n type: string;\n text?: string;\n content?: Array<{ type: string; text?: string; image?: string }>;\n }) {\n // Check if multimodal content is provided\n if (payload.content && Array.isArray(payload.content)) {\n const hasImages = payload.content.some((b) => b.type === \"image\");\n try {\n console.log(\"[NorthflareAgentManager] -> SDK send (multimodal)\", {\n sessionId: observedSessionId,\n type: payload?.type,\n blockCount: payload.content.length,\n hasImages,\n blockTypes: payload.content.map((b) => b.type).join(\", \"),\n });\n } catch {}\n input.enqueue(toSdkUserMessage(payload.content));\n return;\n }\n\n // Text-only message\n const text = payload?.text ?? \"\";\n try {\n console.log(\"[NorthflareAgentManager] -> SDK send\", {\n sessionId: observedSessionId,\n type: payload?.type,\n textPreview: text.slice(0, 200),\n length: text.length,\n });\n } catch {}\n input.enqueue(toSdkUserMessage(text));\n },\n async end() {\n try {\n input.close();\n } finally {\n // Simplified process cleanup\n try {\n if (sdk?.abortController) {\n sdk.abortController.abort();\n }\n } catch {}\n }\n },\n onSessionId(cb: (id: string) => void) {\n onSessionIdCb = cb;\n },\n stream(\n handler: (message: SDKMessage, sessionId: string | null) => Promise<void>\n ) {\n if (startedReader) return;\n startedReader = true;\n (async () => {\n try {\n for await (const msg of sdk) {\n // Simplified session ID extraction\n const sid = (msg && (msg.session_id || msg.sessionId)) || null;\n if (sid && sid !== observedSessionId) {\n observedSessionId = sid;\n if (onSessionIdCb) onSessionIdCb(sid);\n }\n await handler(msg, sid);\n }\n // Normal completion\n if (onComplete) await onComplete(false);\n } catch (e) {\n // Error completion\n if (onComplete) await onComplete(true, e);\n }\n })();\n },\n };\n}\ntype AgentConversation = {\n send: (payload: { type: string; text: string }) => void;\n end: () => Promise<void> | void;\n};\n\nfunction isAgentConversation(\n conversation: ConversationContext[\"conversation\"]\n): conversation is AgentConversation & ConversationContext[\"conversation\"] {\n return (\n !!conversation &&\n typeof (conversation as any).send === \"function\" &&\n typeof (conversation as any).end === \"function\"\n );\n}\n","/**\n * RepositoryManager - Manages Git repository checkouts and workspace isolation\n *\n * This component handles all Git operations for the runner, including:\n * - Cloning repositories with authentication\n * - Updating repositories to latest state\n * - Workspace isolation via separate directories\n * - Cleanup of old repositories\n * - Error handling for Git operations\n */\n\nimport { IRunnerApp } from '../types/runner-interface.js';\nimport { WorkspaceRepository } from '../types/index.js';\nimport path from \"path\";\nimport fs from \"fs/promises\";\nimport { mkdirSync } from \"fs\";\nimport { simpleGit, SimpleGit, GitError } from \"simple-git\";\nimport { createScopedConsole } from '../utils/console.js';\n\nconst console = createScopedConsole(\"repo\");\n\nexport class RepositoryManager {\n private repositories: Map<string, WorkspaceRepository>;\n protected repoBasePath: string;\n private runner: IRunnerApp;\n private git: SimpleGit;\n\n constructor(runner: IRunnerApp) {\n this.runner = runner;\n this.repositories = new Map();\n\n // Use workspacePath from config if available, otherwise use environment variable\n this.repoBasePath =\n runner.config_.workspacePath ||\n process.env[\"NORTHFLARE_WORKSPACE_PATH\"] ||\n \"/tmp/northflare-workspace\";\n if (!this.repoBasePath) {\n throw new Error(\n \"NORTHFLARE_WORKSPACE_PATH environment variable must be set\"\n );\n }\n\n // Ensure workspace directory exists before initializing simple-git\n try {\n mkdirSync(this.repoBasePath, { recursive: true });\n } catch (error) {\n console.error(\n `Failed to create workspace directory ${this.repoBasePath}:`,\n error\n );\n throw error;\n }\n\n // Initialize simple-git\n this.git = simpleGit({\n baseDir: this.repoBasePath,\n binary: \"git\",\n maxConcurrentProcesses: 3,\n config: [\"user.name=Northflare\", \"user.email=runner@northflare.ai\"],\n });\n }\n\n async checkoutRepository(\n workspaceId: string,\n repoUrl: string,\n branch: string,\n githubToken?: string\n ): Promise<string> {\n const existing = this.repositories.get(workspaceId);\n if (\n existing &&\n existing.repoUrl === repoUrl &&\n existing.branch === branch\n ) {\n await this.updateRepository(existing, githubToken);\n return existing.localPath;\n }\n\n const localPath = path.join(this.repoBasePath, workspaceId);\n\n // Clean up existing directory if it exists\n await this.cleanupDirectory(localPath);\n\n // Clone with authentication\n const authUrl = this.getAuthenticatedUrl(repoUrl, githubToken);\n\n try {\n console.log(`Cloning repository for workspace ${workspaceId}...`);\n await this.executeGit([\"clone\", \"--branch\", branch, authUrl, localPath]);\n\n // Configure the repository\n const repoGit = simpleGit(localPath);\n await repoGit.addConfig(\"credential.helper\", \"store\");\n\n const repo: WorkspaceRepository = {\n workspaceId,\n repoUrl,\n branch,\n localPath,\n lastAccessed: new Date(),\n };\n\n this.repositories.set(workspaceId, repo);\n console.log(\n `Successfully cloned repository for workspace ${workspaceId}`\n );\n return localPath;\n } catch (error) {\n console.error(\n `Failed to clone repository for workspace ${workspaceId}:`,\n error\n );\n await this.cleanupDirectory(localPath);\n throw error;\n }\n }\n\n /**\n * Checkout a local repository (bypasses Git operations)\n * Used for local workspaces that point to existing directories on the filesystem\n */\n async checkoutLocalRepository(\n workspaceId: string,\n localRepoPath: string\n ): Promise<string> {\n console.log(\n `Using local repository for workspace ${workspaceId}: ${localRepoPath}`\n );\n\n // Verify the path exists\n try {\n const stats = await fs.stat(localRepoPath);\n if (!stats.isDirectory()) {\n throw new Error(`Path is not a directory: ${localRepoPath}`);\n }\n } catch (error) {\n console.error(`Local repository path not found: ${localRepoPath}`);\n throw new Error(`Local repository path not found: ${localRepoPath}`);\n }\n\n // Store in repositories map for consistency\n const repo: WorkspaceRepository = {\n workspaceId,\n repoUrl: `file://${localRepoPath}`, // Use file:// protocol to indicate local\n branch: \"local\", // Local repos don't have branches in the same sense\n localPath: localRepoPath,\n lastAccessed: new Date(),\n };\n\n this.repositories.set(workspaceId, repo);\n console.log(\n `Successfully set up local repository for workspace ${workspaceId}`\n );\n return localRepoPath;\n }\n\n async getWorkspacePath(workspaceId: string): Promise<string> {\n const localPath = path.join(this.repoBasePath, workspaceId);\n await this.ensureDirectory(localPath);\n return localPath;\n }\n\n private async updateRepository(\n repo: WorkspaceRepository,\n githubToken?: string\n ): Promise<void> {\n repo.lastAccessed = new Date();\n\n // Skip Git operations for local repositories\n if (repo.repoUrl.startsWith(\"file://\")) {\n console.log(\n `Local repository for workspace ${repo.workspaceId} - no update needed`\n );\n return;\n }\n\n const repoGit = simpleGit(repo.localPath);\n\n try {\n console.log(`Updating repository for workspace ${repo.workspaceId}...`);\n\n // Update remote URL if token has changed\n if (githubToken) {\n const authUrl = this.getAuthenticatedUrl(repo.repoUrl, githubToken);\n await repoGit.remote([\"set-url\", \"origin\", authUrl]);\n }\n\n // Fetch latest changes\n await repoGit.fetch(\"origin\");\n\n // Reset to latest branch state\n await repoGit.reset([\"--hard\", `origin/${repo.branch}`]);\n\n // Clean untracked files\n await repoGit.clean(\"f\", [\"-d\"]);\n\n console.log(\n `Successfully updated repository for workspace ${repo.workspaceId}`\n );\n } catch (error) {\n console.error(\n `Failed to update repository for workspace ${repo.workspaceId}:`,\n error\n );\n throw error;\n }\n }\n\n async cleanupRepository(workspaceId: string): Promise<void> {\n const repo = this.repositories.get(workspaceId);\n if (!repo) return;\n\n console.log(`Cleaning up repository for workspace ${workspaceId}...`);\n\n // For local repositories, only remove from tracking, don't delete the directory\n if (repo.repoUrl.startsWith(\"file://\")) {\n console.log(`Local repository - removing from tracking only`);\n this.repositories.delete(workspaceId);\n return;\n }\n\n // Remove local directory for cloned repositories\n await this.cleanupDirectory(repo.localPath);\n\n this.repositories.delete(workspaceId);\n }\n\n async cleanupOldRepositories(\n maxAge: number = 7 * 24 * 60 * 60 * 1000\n ): Promise<void> {\n const now = new Date();\n const toCleanup: string[] = [];\n\n for (const [workspaceId, repo] of this.repositories.entries()) {\n const age = now.getTime() - repo.lastAccessed.getTime();\n if (age > maxAge) {\n toCleanup.push(workspaceId);\n }\n }\n\n for (const workspaceId of toCleanup) {\n await this.cleanupRepository(workspaceId);\n }\n\n console.log(`Cleaned up ${toCleanup.length} old repositories`);\n }\n\n protected async executeGit(args: string[], cwd?: string): Promise<void> {\n const git = cwd ? simpleGit(cwd) : this.git;\n try {\n await git.raw(args);\n } catch (error) {\n if (error instanceof GitError) {\n throw new Error(`Git operation failed: ${error.message}`);\n }\n throw error;\n }\n }\n\n protected getAuthenticatedUrl(repoUrl: string, githubToken?: string): string {\n if (!githubToken) {\n return repoUrl;\n }\n\n // Handle different URL formats\n if (repoUrl.startsWith(\"https://\")) {\n // HTTPS URL\n return repoUrl.replace(\"https://\", `https://${githubToken}@`);\n } else if (repoUrl.startsWith(\"git@\")) {\n // SSH URL - convert to HTTPS with token\n const httpsUrl = repoUrl\n .replace(\"git@github.com:\", \"https://github.com/\")\n .replace(\".git\", \"\");\n return `https://${githubToken}@${httpsUrl.replace(\"https://\", \"\")}.git`;\n }\n\n return repoUrl;\n }\n\n protected async ensureDirectory(dirPath: string): Promise<void> {\n try {\n await fs.mkdir(dirPath, { recursive: true });\n } catch (error) {\n console.error(`Failed to create directory ${dirPath}:`, error);\n throw error;\n }\n }\n\n protected async cleanupDirectory(dirPath: string): Promise<void> {\n try {\n const stats = await fs.stat(dirPath).catch(() => null);\n if (stats) {\n await fs.rm(dirPath, { recursive: true, force: true });\n }\n } catch (error) {\n console.error(`Failed to cleanup directory ${dirPath}:`, error);\n // Don't throw - cleanup errors are not critical\n }\n }\n\n /**\n * Get statistics about managed repositories\n */\n getRepositoryStats(): {\n total: number;\n workspaceIds: string[];\n oldestAccess: Date | null;\n newestAccess: Date | null;\n } {\n const repos = Array.from(this.repositories.values());\n\n return {\n total: repos.length,\n workspaceIds: Array.from(this.repositories.keys()),\n oldestAccess:\n repos.length > 0\n ? new Date(Math.min(...repos.map((r) => r.lastAccessed.getTime())))\n : null,\n newestAccess:\n repos.length > 0\n ? new Date(Math.max(...repos.map((r) => r.lastAccessed.getTime())))\n : null,\n };\n }\n\n /**\n * Check if a workspace has an existing repository\n */\n hasRepository(workspaceId: string): boolean {\n return this.repositories.has(workspaceId);\n }\n\n /**\n * Get repository info for a workspace\n */\n getRepository(workspaceId: string): WorkspaceRepository | undefined {\n return this.repositories.get(workspaceId);\n }\n}\n","/**\n * EnhancedRepositoryManager - Advanced Git repository management with worktree support\n *\n * This enhanced version builds upon the original RepositoryManager to add:\n * - Task-level Git isolation through worktrees\n * - Git operations (stage, commit, push, merge, rebase)\n * - State persistence and recovery\n * - Backward compatibility with workspace-based operations\n *\n * Directory structure:\n * /workspace/repos/<owner>__<repo>/\n * control/ # Primary clone (.git directory owner)\n * .git/\n * worktrees/\n * workspace_<workspaceId>/ # Backward compatibility - workspace default branch\n * task_<taskId>/ # New - isolated task worktrees\n * state.json # Persistent state mapping\n */\n\nimport { RepositoryManager } from './repository-manager.js';\nimport { IRunnerApp } from '../types/runner-interface.js';\nimport path from \"path\";\nimport fs from \"fs/promises\";\nimport crypto from \"crypto\";\nimport { simpleGit } from \"simple-git\";\nimport { createScopedConsole } from '../utils/console.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst console = createScopedConsole(\"repo\");\nconst logger = createLogger(\"EnhancedRepositoryManager\", \"repo\");\n\n// Types for enhanced functionality\nexport interface TaskHandle {\n taskId: string;\n worktreePath: string;\n branch: string;\n baseBranch: string;\n}\n\nexport interface RemoveOptions {\n preserveBranch?: boolean;\n force?: boolean;\n}\n\nexport interface GitAuthor {\n name: string;\n email: string;\n}\n\nexport interface RebaseResult {\n success: boolean;\n conflicts?: string[];\n error?: string;\n}\n\nexport interface MergeResult {\n success: boolean;\n conflicts?: string[];\n mergedCommit?: string;\n error?: string;\n}\n\nexport type MergeMode = \"ff-only\" | \"no-ff\" | \"squash\";\n\nexport type TaskIntegrationResult =\n | {\n success: true;\n mergedCommit?: string;\n }\n | {\n success: false;\n phase: \"rebase\" | \"merge\";\n conflicts?: string[];\n error?: string;\n conflictWorkdir: string;\n };\n\nexport interface TaskGitState {\n taskId: string;\n workspaceId?: string;\n branch: string;\n baseBranch: string;\n lastCommit?: string;\n commitCount?: number;\n worktreePath: string;\n status: \"active\" | \"conflicted\" | \"merged\" | \"abandoned\";\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface RepositoryState {\n repositories: Record<\n string,\n {\n owner: string;\n repo: string;\n controlPath: string;\n worktrees: Record<string, TaskGitState>;\n }\n >;\n}\n\nexport class EnhancedRepositoryManager extends RepositoryManager {\n private repoStates: Map<string, RepositoryState>;\n private stateFilePath: string;\n private legacyStateFilePath: string;\n private repoLocks: Map<string, Promise<void>>;\n private taskWorktreesBasePath: string;\n\n constructor(runner: IRunnerApp) {\n super(runner);\n this.repoStates = new Map();\n this.repoLocks = new Map();\n const dataDir = runner.config_.dataDir;\n const runnerId = runner.getRunnerId();\n const stateFileName = runnerId\n ? `repository-state-${runnerId}.json`\n : \"repository-state.json\";\n this.stateFilePath = path.join(dataDir, \"git\", stateFileName);\n this.legacyStateFilePath = path.join(this.repoBasePath, \"repository-state.json\");\n this.taskWorktreesBasePath = path.join(dataDir, \"git\", \"worktrees\");\n\n // Load persisted state on initialization\n this.restoreState().catch((err) => {\n console.error(\"Failed to restore repository state:\", err);\n });\n }\n\n /**\n * Get repository key from owner and repo name\n */\n private getRepoKey(repoUrl: string): {\n key: string;\n owner: string;\n repo: string;\n } {\n // Handle local repository URLs\n if (repoUrl.startsWith(\"file://\")) {\n const localPath = repoUrl.replace(\"file://\", \"\");\n const repoName = path.basename(localPath) || \"local\";\n const digest = crypto\n .createHash(\"sha1\")\n .update(localPath)\n .digest(\"hex\")\n .slice(0, 12);\n return { key: `local__${repoName}__${digest}`, owner: \"local\", repo: repoName };\n }\n\n // Extract owner and repo from URL\n const match = repoUrl.match(/github\\.com[:/]([^/]+)\\/([^/.]+)(\\.git)?$/);\n if (!match) {\n throw new Error(`Invalid GitHub repository URL: ${repoUrl}`);\n }\n\n const owner = match[1] || \"\";\n const repo = match[2] || \"\";\n const key = `${owner}__${repo}`;\n\n return { key, owner, repo };\n }\n\n private parseRepoKey(repoKey: string): { owner: string; repo: string } {\n const parts = repoKey.split(\"__\");\n const owner = parts[0] || repoKey;\n const repo = parts[1] || repoKey;\n return { owner, repo };\n }\n\n private findTaskStateEntry(taskId: string): {\n repoKey: string;\n repo: RepositoryState[\"repositories\"][string];\n taskState: TaskGitState;\n } | null {\n for (const [repoKey, state] of this.repoStates) {\n const repo = state.repositories[repoKey];\n const taskState = repo?.worktrees?.[taskId];\n if (repo && taskState) {\n return { repoKey, repo, taskState };\n }\n }\n return null;\n }\n\n private async withRepoLock<T>(repoKey: string, fn: () => Promise<T>): Promise<T> {\n const previous = this.repoLocks.get(repoKey) ?? Promise.resolve();\n let release!: () => void;\n const current = new Promise<void>((resolve) => {\n release = resolve;\n });\n\n const chained = previous.then(() => current);\n this.repoLocks.set(repoKey, chained);\n\n await previous;\n try {\n return await fn();\n } finally {\n release();\n if (this.repoLocks.get(repoKey) === chained) {\n this.repoLocks.delete(repoKey);\n }\n }\n }\n\n /**\n * Ensure control repository exists\n */\n private async ensureControlRepository(\n repoUrl: string,\n githubToken?: string\n ): Promise<string> {\n const { key, owner, repo } = this.getRepoKey(repoUrl);\n const controlPath = path.join(this.repoBasePath, \"repos\", key, \"control\");\n\n // Check if control repository already exists\n try {\n // Support both bare repos (config/objects at root) and legacy non-bare repos (.git/)\n const hasGitDir = await fs\n .access(path.join(controlPath, \".git\"))\n .then(() => true)\n .catch(() => false);\n\n const hasBareLayout = await fs\n .access(path.join(controlPath, \"config\"))\n .then(() => fs.access(path.join(controlPath, \"objects\")).then(() => true))\n .catch(() => false);\n\n if (!hasGitDir && !hasBareLayout) {\n throw new Error(\"missing\");\n }\n\n console.log(`Control repository already exists for ${key}`);\n\n // Update remote URL if token changed\n if (githubToken) {\n const git = simpleGit(controlPath);\n const authUrl = this.getAuthenticatedUrl(repoUrl, githubToken);\n await git.remote([\"set-url\", \"origin\", authUrl]);\n }\n\n // Fetch latest changes\n const git = simpleGit(controlPath);\n await git.fetch(\"origin\");\n\n return controlPath;\n } catch {\n // Control repository doesn't exist, create it\n console.log(`Creating control repository for ${key}...`);\n\n await this.ensureDirectory(path.dirname(controlPath));\n\n const authUrl = this.getAuthenticatedUrl(repoUrl, githubToken);\n await this.executeGit([\"clone\", \"--bare\", authUrl, controlPath]);\n\n console.log(`Successfully created control repository for ${key}`);\n return controlPath;\n }\n }\n\n /**\n * Create a task-specific worktree for local workspaces\n */\n async createLocalTaskHandle(\n taskId: string,\n localPath: string\n ): Promise<TaskHandle> {\n // For local workspaces, we don't create worktrees or branches\n // Just return a handle pointing to the local path\n const handle: TaskHandle = {\n taskId,\n worktreePath: localPath,\n branch: \"local\", // Placeholder branch name for local workspaces\n baseBranch: \"local\",\n };\n\n // Create and persist state for tracking\n const state: TaskGitState = {\n taskId,\n branch: \"local\",\n baseBranch: \"local\",\n worktreePath: localPath,\n status: \"active\",\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n\n // Store state using a special key for local workspaces\n await this.updateTaskState(\"__local__\", state);\n\n console.log(`Created local task handle for task ${taskId} at ${localPath}`);\n return handle;\n }\n\n /**\n * Create a task-specific worktree\n */\n async createTaskWorktree(\n taskId: string,\n workspaceId: string,\n repoUrl: string,\n baseBranch: string = \"main\",\n githubToken?: string\n ): Promise<TaskHandle> {\n const { key, owner, repo } = this.getRepoKey(repoUrl);\n\n // Reuse an existing worktree/branch for this task when possible\n const existing = this.findTaskStateEntry(taskId);\n if (existing && existing.repoKey !== \"__local__\" && existing.taskState.branch !== \"local\") {\n const expectedWorktreePath = path.join(\n this.taskWorktreesBasePath,\n existing.repoKey,\n `task_${taskId}`\n );\n const worktreePath = existing.taskState.worktreePath || expectedWorktreePath;\n const shouldPersistMetadata =\n existing.taskState.workspaceId !== workspaceId ||\n existing.taskState.baseBranch !== baseBranch;\n\n if (shouldPersistMetadata) {\n existing.taskState.workspaceId = workspaceId;\n existing.taskState.baseBranch = baseBranch;\n existing.taskState.updatedAt = new Date();\n await this.updateTaskStateByTaskId(taskId, existing.taskState);\n }\n\n try {\n await fs.access(worktreePath);\n return {\n taskId,\n worktreePath,\n branch: existing.taskState.branch,\n baseBranch: existing.taskState.baseBranch,\n };\n } catch {\n // Recreate missing worktree from the existing branch\n const git = simpleGit(existing.repo.controlPath);\n await this.ensureDirectory(path.dirname(worktreePath));\n\n try {\n await git.raw([\"worktree\", \"add\", worktreePath, existing.taskState.branch]);\n } catch (error) {\n console.error(`Failed to recreate worktree for task ${taskId}:`, error);\n await this.cleanupDirectory(worktreePath);\n throw error;\n }\n\n const worktreeGit = simpleGit(worktreePath);\n await worktreeGit.addConfig(\"user.name\", \"Northflare\");\n await worktreeGit.addConfig(\"user.email\", \"runner@northflare.ai\");\n\n existing.taskState.worktreePath = worktreePath;\n existing.taskState.workspaceId = workspaceId;\n existing.taskState.baseBranch = baseBranch;\n existing.taskState.status = \"active\";\n existing.taskState.updatedAt = new Date();\n await this.updateTaskState(existing.repoKey, existing.taskState);\n\n return {\n taskId,\n worktreePath,\n branch: existing.taskState.branch,\n baseBranch: existing.taskState.baseBranch,\n };\n }\n }\n\n const isLocalRepo = repoUrl.startsWith(\"file://\");\n\n // Ensure control repository exists\n let controlPath: string;\n if (isLocalRepo) {\n controlPath = repoUrl.replace(\"file://\", \"\");\n\n // Verify local path exists and has a Git directory\n const stats = await fs.stat(controlPath);\n if (!stats.isDirectory()) {\n throw new Error(`Local repository path is not a directory: ${controlPath}`);\n }\n await fs.access(path.join(controlPath, \".git\"));\n } else {\n controlPath = await this.ensureControlRepository(repoUrl, githubToken);\n }\n\n const worktreesPath = path.join(this.taskWorktreesBasePath, key);\n const taskWorktreePath = path.join(worktreesPath, `task_${taskId}`);\n\n // Create unique branch name for the task\n const branchName = `task/${taskId}`;\n\n try {\n console.log(`Creating worktree for task ${taskId} on branch ${branchName}...`);\n\n // Create worktree directory\n await this.ensureDirectory(worktreesPath);\n\n // Add worktree with new branch based on baseBranch\n const git = simpleGit(controlPath);\n const baseRef = isLocalRepo ? baseBranch : `origin/${baseBranch}`;\n let baseRefIsValid = await git\n .raw([\"rev-parse\", \"--verify\", `${baseRef}^{commit}`])\n .then(() => true)\n .catch(() => false);\n\n if (!baseRefIsValid) {\n const hasAnyCommit = await git\n .raw([\"rev-parse\", \"--verify\", \"HEAD^{commit}\"])\n .then(() => true)\n .catch(() => false);\n\n if (!hasAnyCommit) {\n await this.ensureInitialCommitOnBranch(controlPath, baseBranch);\n baseRefIsValid = await git\n .raw([\"rev-parse\", \"--verify\", `${baseRef}^{commit}`])\n .then(() => true)\n .catch(() => false);\n }\n\n if (!baseRefIsValid) {\n throw new Error(\n `Cannot create a task worktree for ${taskId}: base branch '${baseBranch}' is not a valid Git reference in ${controlPath}. Set Workspace → Settings → Git branch to an existing branch name and retry.`\n );\n }\n }\n\n const branchExists = await git\n .raw([\"show-ref\", \"--verify\", `refs/heads/${branchName}`])\n .then(() => true)\n .catch(() => false);\n\n if (branchExists) {\n await git.raw([\"worktree\", \"add\", taskWorktreePath, branchName]);\n } else {\n await git.raw([\n \"worktree\",\n \"add\",\n \"-b\",\n branchName,\n taskWorktreePath,\n baseRef,\n ]);\n }\n\n // Configure the worktree\n const worktreeGit = simpleGit(taskWorktreePath);\n await worktreeGit.addConfig(\"user.name\", \"Northflare\");\n await worktreeGit.addConfig(\"user.email\", \"runner@northflare.ai\");\n\n // Create and persist state\n const state: TaskGitState = {\n taskId,\n workspaceId,\n branch: branchName,\n baseBranch,\n worktreePath: taskWorktreePath,\n status: \"active\",\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n\n await this.updateTaskState(key, state, { owner, repo, controlPath });\n\n console.log(`Successfully created worktree for task ${taskId}`);\n\n return {\n taskId,\n worktreePath: taskWorktreePath,\n branch: branchName,\n baseBranch,\n };\n } catch (error) {\n console.error(`Failed to create worktree for task ${taskId}:`, error);\n // Cleanup on failure\n await this.cleanupDirectory(taskWorktreePath);\n throw error;\n }\n }\n\n private async ensureInitialCommitOnBranch(\n repoPath: string,\n branchName: string\n ): Promise<void> {\n const git = simpleGit(repoPath);\n\n await git.addConfig(\"user.name\", \"Northflare\");\n await git.addConfig(\"user.email\", \"runner@northflare.ai\");\n\n const hasAnyCommit = await git\n .raw([\"rev-parse\", \"--verify\", \"HEAD^{commit}\"])\n .then(() => true)\n .catch(() => false);\n\n if (hasAnyCommit) return;\n\n console.log(\n `Repository at ${repoPath} has no commits; creating an empty initial commit on '${branchName}'...`\n );\n\n const isBareRepo = await git\n .raw([\"rev-parse\", \"--is-bare-repository\"])\n .then((output) => output.trim() === \"true\")\n .catch(() => false);\n\n if (isBareRepo) {\n const emptyTreeHash = \"4b825dc642cb6eb9a060e54bf8d69288fbee4904\";\n const commitHash = (await git.raw([\n \"commit-tree\",\n emptyTreeHash,\n \"-m\",\n \"Initial commit\",\n ])).trim();\n\n await git.raw([\"update-ref\", `refs/heads/${branchName}`, commitHash]);\n await git.raw([\"symbolic-ref\", \"HEAD\", `refs/heads/${branchName}`]);\n\n const remotes = await git.getRemotes(true);\n const hasOrigin = remotes.some((remote) => remote.name === \"origin\");\n void hasOrigin;\n } else {\n await git.raw([\"checkout\", \"--orphan\", branchName]);\n await git.raw([\"commit\", \"--allow-empty\", \"-m\", \"Initial commit\"]);\n }\n }\n\n /**\n * Remove a task worktree\n */\n async removeTaskWorktree(\n taskId: string,\n options: RemoveOptions = {}\n ): Promise<void> {\n const entry = this.findTaskStateEntry(taskId);\n if (!entry) {\n console.log(`No worktree found for task ${taskId}`);\n return;\n }\n\n const { repoKey, repo, taskState } = entry;\n\n // Handle local workspaces differently\n if (repoKey === \"__local__\") {\n // Just remove from state, don't touch the filesystem\n const repoState = this.repoStates.get(repoKey);\n const repo = repoState?.repositories?.[repoKey];\n if (repo?.worktrees?.[taskId]) {\n delete repo.worktrees[taskId];\n }\n await this.persistState();\n console.log(`Removed local task handle for task ${taskId}`);\n return;\n }\n\n const controlPath = repo.controlPath;\n\n try {\n console.log(`Removing worktree for task ${taskId}...`);\n\n const git = simpleGit(controlPath);\n\n // Remove the worktree (when present)\n if (taskState.worktreePath) {\n const worktreePath = taskState.worktreePath;\n try {\n await fs.access(worktreePath);\n await git.raw([\"worktree\", \"remove\", worktreePath, \"--force\"]);\n } catch {\n // Worktree path already gone; continue so we can still delete the branch if needed\n } finally {\n await this.cleanupDirectory(worktreePath);\n }\n }\n\n // Delete the branch if not preserving\n if (!options.preserveBranch) {\n try {\n await git.raw([\"branch\", \"-D\", taskState.branch]);\n } catch (error) {\n console.warn(`Failed to delete branch ${taskState.branch}:`, error);\n }\n }\n\n // Update state\n const repoState = this.repoStates.get(repoKey);\n if (repoState?.repositories[repoKey]?.worktrees) {\n if (options.preserveBranch) {\n repoState.repositories[repoKey].worktrees[taskId] = {\n ...taskState,\n worktreePath: \"\",\n updatedAt: new Date(),\n };\n } else {\n delete repoState.repositories[repoKey].worktrees[taskId];\n }\n }\n await this.persistState();\n\n console.log(`Successfully removed worktree for task ${taskId}`);\n } catch (error) {\n console.error(`Failed to remove worktree for task ${taskId}:`, error);\n if (options.force) {\n // Force cleanup\n await this.cleanupDirectory(taskState.worktreePath);\n } else {\n throw error;\n }\n }\n }\n\n /**\n * Stage all changes in a task worktree\n */\n async stageAll(taskId: string): Promise<void> {\n const taskState = await this.getTaskState(taskId);\n if (!taskState) {\n throw new Error(`No worktree found for task ${taskId}`);\n }\n\n // Skip Git operations for local workspaces\n if (taskState.branch === \"local\") {\n console.log(\n `Skipping stage operation for local workspace task ${taskId}`\n );\n return;\n }\n\n const git = simpleGit(taskState.worktreePath);\n await git.add(\".\");\n\n console.log(`Staged all changes for task ${taskId}`);\n }\n\n /**\n * Commit changes in a task worktree\n */\n async commit(\n taskId: string,\n message: string,\n author?: GitAuthor\n ): Promise<string> {\n const taskState = await this.getTaskState(taskId);\n if (!taskState) {\n throw new Error(`No worktree found for task ${taskId}`);\n }\n\n // Skip Git operations for local workspaces\n if (taskState.branch === \"local\") {\n console.log(\n `Skipping commit operation for local workspace task ${taskId}`\n );\n return \"local-commit\"; // Return a placeholder commit hash\n }\n\n const git = simpleGit(taskState.worktreePath);\n\n // Set author if provided\n if (author) {\n await git.addConfig(\"user.name\", author.name);\n await git.addConfig(\"user.email\", author.email);\n }\n\n // Commit changes\n const result = await git.commit(message);\n const commitHash = result.commit;\n\n // Update task state\n taskState.lastCommit = commitHash;\n taskState.commitCount = (taskState.commitCount ?? 0) + 1;\n taskState.updatedAt = new Date();\n await this.updateTaskStateByTaskId(taskId, taskState);\n\n console.log(`Created commit ${commitHash} for task ${taskId}`);\n logger.info(`Committed task ${taskId} (${taskState.branch}) -> ${commitHash}`, {\n taskId,\n branch: taskState.branch,\n baseBranch: taskState.baseBranch,\n commit: commitHash,\n worktreePath: taskState.worktreePath,\n });\n return commitHash;\n }\n\n /**\n * Create a new branch for a task\n */\n async createBranch(taskId: string, branchName: string): Promise<void> {\n const taskState = await this.getTaskState(taskId);\n if (!taskState) {\n throw new Error(`No worktree found for task ${taskId}`);\n }\n\n // Skip Git operations for local workspaces\n if (taskState.branch === \"local\") {\n console.log(\n `Skipping branch creation for local workspace task ${taskId}`\n );\n return;\n }\n\n const git = simpleGit(taskState.worktreePath);\n await git.checkoutBranch(branchName, taskState.branch);\n\n // Update task state\n taskState.branch = branchName;\n taskState.updatedAt = new Date();\n await this.updateTaskStateByTaskId(taskId, taskState);\n\n console.log(`Created branch ${branchName} for task ${taskId}`);\n }\n\n /**\n * Rebase a task branch onto target branch\n */\n async rebaseTask(\n taskId: string,\n targetBranch: string\n ): Promise<RebaseResult> {\n const taskState = await this.getTaskState(taskId);\n if (!taskState) {\n throw new Error(`No worktree found for task ${taskId}`);\n }\n\n // Skip Git operations for local workspaces\n if (taskState.branch === \"local\") {\n console.log(\n `Skipping rebase operation for local workspace task ${taskId}`\n );\n return { success: true }; // Return success for local workspaces\n }\n\n const git = simpleGit(taskState.worktreePath);\n\n try {\n const remotes = await git.getRemotes(true);\n const hasOrigin = remotes.some((r) => r.name === \"origin\");\n\n logger.info(\n `Rebasing task ${taskId} (${taskState.branch}) onto ${targetBranch}`,\n {\n taskId,\n branch: taskState.branch,\n targetBranch,\n hasOrigin,\n worktreePath: taskState.worktreePath,\n }\n );\n\n if (hasOrigin) {\n // Fetch latest changes\n await git.fetch(\"origin\", targetBranch);\n // Perform rebase\n await git.rebase([`origin/${targetBranch}`]);\n } else {\n await git.rebase([targetBranch]);\n }\n\n // Update base branch in state\n taskState.baseBranch = targetBranch;\n taskState.updatedAt = new Date();\n await this.updateTaskStateByTaskId(taskId, taskState);\n\n console.log(`Successfully rebased task ${taskId} onto ${targetBranch}`);\n logger.info(\n `Rebased task ${taskId} (${taskState.branch}) onto ${targetBranch}`,\n {\n taskId,\n branch: taskState.branch,\n targetBranch,\n }\n );\n return { success: true };\n } catch (error) {\n console.error(`Rebase failed for task ${taskId}:`, error);\n logger.error(`Rebase failed for task ${taskId} (${taskState.branch})`, {\n taskId,\n branch: taskState.branch,\n targetBranch,\n error: error instanceof Error ? error.message : String(error),\n });\n\n // Check for conflicts\n const status = await git.status();\n if (status.conflicted.length > 0) {\n taskState.status = \"conflicted\";\n await this.updateTaskStateByTaskId(taskId, taskState);\n\n return {\n success: false,\n conflicts: status.conflicted,\n error: \"Rebase resulted in conflicts\",\n };\n }\n\n // Abort rebase on error\n try {\n await git.rebase([\"--abort\"]);\n } catch {\n // Ignore abort errors\n }\n\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n /**\n * Merge a task branch into target branch\n */\n async mergeTask(\n taskId: string,\n targetBranch: string,\n mode: MergeMode = \"no-ff\"\n ): Promise<MergeResult> {\n const entry = this.findTaskStateEntry(taskId);\n if (!entry) {\n throw new Error(`No worktree found for task ${taskId}`);\n }\n\n const { repoKey, taskState } = entry;\n\n // Skip Git operations for local workspaces\n if (taskState.branch === \"local\") {\n console.log(\n `Skipping merge operation for local workspace task ${taskId}`\n );\n return { success: true, mergedCommit: \"local-merge\" }; // Return success for local workspaces\n }\n\n return await this.withRepoLock(repoKey, async () => {\n return this.mergeTaskUnlocked(entry, targetBranch, mode);\n });\n }\n\n private async mergeTaskUnlocked(\n entry: {\n repoKey: string;\n repo: RepositoryState[\"repositories\"][string];\n taskState: TaskGitState;\n },\n targetBranch: string,\n mode: MergeMode\n ): Promise<MergeResult> {\n const { repoKey, repo, taskState } = entry;\n const isLocalRepo = repoKey.startsWith(\"local__\");\n const mergePath = await (async () => {\n if (isLocalRepo) return repo.controlPath;\n\n if (!taskState.workspaceId) {\n throw new Error(\n `Cannot merge task ${taskState.taskId}: missing workspaceId in task Git state`\n );\n }\n\n const worktreesPath = path.join(\n this.repoBasePath,\n \"repos\",\n repoKey,\n \"worktrees\"\n );\n const workspaceWorktreePath = path.join(\n worktreesPath,\n `workspace_${taskState.workspaceId}`\n );\n\n const exists = await fs\n .access(workspaceWorktreePath)\n .then(() => true)\n .catch(() => false);\n\n if (exists) return workspaceWorktreePath;\n\n await this.ensureDirectory(worktreesPath);\n\n const controlGit = simpleGit(repo.controlPath);\n await controlGit.fetch(\"origin\", targetBranch);\n\n await controlGit.raw([\n \"worktree\",\n \"add\",\n workspaceWorktreePath,\n `origin/${targetBranch}`,\n ]);\n\n console.log(\n `Created merge worktree for workspace ${taskState.workspaceId} at ${workspaceWorktreePath}`\n );\n\n return workspaceWorktreePath;\n })();\n const git = simpleGit(mergePath);\n\n try {\n const remotes = await git.getRemotes(true);\n const hasOrigin = remotes.some((r) => r.name === \"origin\");\n\n logger.info(\n `Merging task ${taskState.taskId} (${taskState.branch}) into ${targetBranch}`,\n {\n taskId: taskState.taskId,\n taskBranch: taskState.branch,\n targetBranch,\n mergePath,\n hasOrigin,\n isLocalRepo,\n mode,\n }\n );\n\n if (hasOrigin) {\n // Fetch latest changes and ensure a local targetBranch exists + is up-to-date\n await git.fetch(\"origin\", targetBranch);\n\n const localBranches = await git.branchLocal();\n const hasLocalTarget = localBranches.all.includes(targetBranch);\n\n if (!hasLocalTarget) {\n await git.raw([\"checkout\", \"-B\", targetBranch, `origin/${targetBranch}`]);\n } else {\n await git.checkout(targetBranch);\n try {\n await git.merge([\"--ff-only\", `origin/${targetBranch}`]);\n } catch (error) {\n throw new Error(\n `Base branch ${targetBranch} has diverged from origin/${targetBranch}; cannot fast-forward`\n );\n }\n }\n } else {\n await git.checkout(targetBranch);\n }\n\n // Perform merge based on mode\n let mergeArgs: string[] = [];\n switch (mode) {\n case \"ff-only\":\n mergeArgs = [\"--ff-only\"];\n break;\n case \"no-ff\":\n mergeArgs = [\"--no-ff\"];\n break;\n case \"squash\":\n mergeArgs = [\"--squash\"];\n break;\n }\n\n const result = await git.merge([...mergeArgs, taskState.branch]);\n\n // For squash merge, we need to commit\n if (mode === \"squash\") {\n const commitResult = await git.commit(\n `Merge task ${taskState.taskId} (${taskState.branch})`\n );\n result.result = commitResult.commit;\n }\n\n // Update task state\n taskState.status = \"merged\";\n taskState.updatedAt = new Date();\n await this.updateTaskStateByTaskId(taskState.taskId, taskState);\n\n console.log(\n `Successfully merged task ${taskState.taskId} into ${targetBranch}`\n );\n logger.info(\n `Merged task ${taskState.taskId} (${taskState.branch}) into ${targetBranch}`,\n {\n taskId: taskState.taskId,\n taskBranch: taskState.branch,\n targetBranch,\n mergedCommit: result.result,\n }\n );\n return {\n success: true,\n mergedCommit: result.result,\n };\n } catch (error) {\n console.error(`Merge failed for task ${taskState.taskId}:`, error);\n logger.error(`Merge failed for task ${taskState.taskId} (${taskState.branch})`, {\n taskId: taskState.taskId,\n taskBranch: taskState.branch,\n targetBranch,\n mergePath,\n error: error instanceof Error ? error.message : String(error),\n });\n\n // Check for conflicts\n try {\n const status = await git.status();\n if (status.conflicted.length > 0) {\n taskState.status = \"conflicted\";\n await this.updateTaskStateByTaskId(taskState.taskId, taskState);\n\n return {\n success: false,\n conflicts: status.conflicted,\n error: \"Merge resulted in conflicts\",\n };\n }\n } catch {\n // Ignore status errors (e.g. bare repositories)\n }\n\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n async getTaskRepoInfo(taskId: string): Promise<{\n repoKey: string;\n controlPath: string;\n worktreePath: string;\n branch: string;\n baseBranch: string;\n } | null> {\n const entry = this.findTaskStateEntry(taskId);\n if (!entry) return null;\n\n return {\n repoKey: entry.repoKey,\n controlPath: entry.repo.controlPath,\n worktreePath: entry.taskState.worktreePath,\n branch: entry.taskState.branch,\n baseBranch: entry.taskState.baseBranch,\n };\n }\n\n /**\n * Fast-forward (or hard reset) the shared workspace worktree to a branch tip after a task merge.\n * This keeps the \"workspace\" checkout in sync with concurrent task integrations.\n *\n * We only update existing workspace worktrees and only when they're clean to avoid\n * clobbering any active non-concurrent task that might be using the workspace checkout.\n */\n async syncWorkspaceWorktree(\n workspaceId: string,\n repoUrl: string,\n branch: string\n ): Promise<void> {\n if (!workspaceId || !repoUrl) return;\n\n // Local repos merge directly into the primary working tree (controlPath), nothing to sync.\n if (repoUrl.startsWith(\"file://\")) return;\n\n const { key } = this.getRepoKey(repoUrl);\n const workspaceWorktreePath = path.join(\n this.repoBasePath,\n \"repos\",\n key,\n \"worktrees\",\n `workspace_${workspaceId}`\n );\n\n const exists = await fs\n .access(workspaceWorktreePath)\n .then(() => true)\n .catch(() => false);\n\n await this.withRepoLock(key, async () => {\n if (!exists) {\n const controlPath = path.join(this.repoBasePath, \"repos\", key, \"control\");\n const controlExists = await fs\n .access(controlPath)\n .then(() => true)\n .catch(() => false);\n if (!controlExists) {\n console.warn(\n `Skipping workspace worktree sync for ${workspaceId}: control repo missing`,\n { controlPath, repoUrl }\n );\n return;\n }\n\n await this.ensureDirectory(path.dirname(workspaceWorktreePath));\n\n const controlGit = simpleGit(controlPath);\n const remotes = await controlGit.getRemotes(true);\n const hasOrigin = remotes.some((remote) => remote.name === \"origin\");\n const checkoutRef = hasOrigin ? `origin/${branch}` : branch;\n\n await controlGit.raw([\"worktree\", \"add\", workspaceWorktreePath, checkoutRef]);\n\n console.log(\n `Created workspace worktree for ${workspaceId} at ${workspaceWorktreePath}`\n );\n }\n\n const git = simpleGit(workspaceWorktreePath);\n const status = await git.status();\n\n if (status.conflicted.length > 0 || !status.isClean()) {\n console.warn(\n `Skipping workspace worktree sync for ${workspaceId}: worktree is not clean`,\n {\n path: workspaceWorktreePath,\n branch,\n conflicted: status.conflicted,\n fileCount: status.files.length,\n }\n );\n return;\n }\n\n const remotes = await git.getRemotes(true);\n const hasOrigin = remotes.some((remote) => remote.name === \"origin\");\n\n if (hasOrigin) {\n await git.fetch(\"origin\", branch);\n await git.reset([\"--hard\", `origin/${branch}`]);\n } else {\n await git.reset([\"--hard\", branch]);\n }\n\n await git.clean(\"f\", [\"-d\"]);\n\n console.log(\n `Synced workspace worktree for ${workspaceId} to ${branch} at ${workspaceWorktreePath}`\n );\n });\n }\n\n async isTaskBranchMerged(taskId: string, targetBranch: string): Promise<boolean> {\n const entry = this.findTaskStateEntry(taskId);\n if (!entry) return false;\n\n const { repo, taskState } = entry;\n const git = simpleGit(repo.controlPath);\n\n try {\n // Ensure targetBranch exists locally (avoid erroring for repos that only have origin/<branch>)\n const showRef = await git.raw([\n \"show-ref\",\n \"--verify\",\n `refs/heads/${targetBranch}`,\n ]);\n if (!showRef?.trim()) return false;\n } catch {\n return false;\n }\n\n try {\n await git.raw([\n \"merge-base\",\n \"--is-ancestor\",\n taskState.branch,\n targetBranch,\n ]);\n return true;\n } catch {\n return false;\n }\n }\n\n async pushBranch(taskId: string, branch: string): Promise<void> {\n const entry = this.findTaskStateEntry(taskId);\n if (!entry) return;\n\n const git = simpleGit(entry.repo.controlPath);\n const remotes = await git.getRemotes(true);\n const hasOrigin = remotes.some((r) => r.name === \"origin\");\n if (!hasOrigin) return;\n\n await git.push(\"origin\", branch);\n }\n\n async integrateTask(\n taskId: string,\n targetBranch: string,\n mode: MergeMode = \"no-ff\"\n ): Promise<TaskIntegrationResult> {\n const entry = this.findTaskStateEntry(taskId);\n if (!entry) {\n return {\n success: false,\n phase: \"merge\",\n error: `No worktree found for task ${taskId}`,\n conflictWorkdir: \"\",\n };\n }\n\n const { repoKey, repo, taskState } = entry;\n const isLocalRepo = repoKey.startsWith(\"local__\");\n const mergeWorkdir = isLocalRepo\n ? repo.controlPath\n : taskState.workspaceId\n ? path.join(\n this.repoBasePath,\n \"repos\",\n repoKey,\n \"worktrees\",\n `workspace_${taskState.workspaceId}`\n )\n : taskState.worktreePath;\n\n logger.info(`Integrating task ${taskId} (${taskState.branch}) into ${targetBranch}`, {\n taskId,\n taskBranch: taskState.branch,\n targetBranch,\n mode,\n isLocalRepo,\n controlPath: repo.controlPath,\n worktreePath: taskState.worktreePath,\n });\n\n return await this.withRepoLock(repoKey, async () => {\n const rebaseResult = await this.rebaseTask(taskId, targetBranch);\n if (!rebaseResult.success) {\n logger.warn(`Task ${taskId} rebase failed`, {\n taskId,\n phase: \"rebase\",\n targetBranch,\n conflicts: rebaseResult.conflicts ?? [],\n error: rebaseResult.error,\n });\n return {\n success: false,\n phase: \"rebase\",\n conflicts: rebaseResult.conflicts ?? [],\n error: rebaseResult.error,\n conflictWorkdir: taskState.worktreePath,\n };\n }\n\n const mergeResult = await this.mergeTaskUnlocked(entry, targetBranch, mode);\n if (!mergeResult.success) {\n logger.warn(`Task ${taskId} merge failed`, {\n taskId,\n phase: \"merge\",\n targetBranch,\n conflicts: mergeResult.conflicts ?? [],\n error: mergeResult.error,\n });\n return {\n success: false,\n phase: \"merge\",\n conflicts: mergeResult.conflicts ?? [],\n error: mergeResult.error,\n conflictWorkdir: mergeWorkdir,\n };\n }\n\n logger.info(`Integrated task ${taskId} into ${targetBranch}`, {\n taskId,\n targetBranch,\n mergedCommit: mergeResult.mergedCommit,\n });\n return {\n success: true,\n mergedCommit: mergeResult.mergedCommit,\n };\n });\n }\n\n /**\n * Get task Git state\n */\n async getTaskState(taskId: string): Promise<TaskGitState | null> {\n return this.findTaskStateEntry(taskId)?.taskState ?? null;\n }\n\n /**\n * Update task state\n */\n private async updateTaskState(\n repoKey: string,\n state: TaskGitState,\n repoInfo?: { owner: string; repo: string; controlPath: string }\n ): Promise<void> {\n if (!this.repoStates.has(repoKey)) {\n this.repoStates.set(repoKey, {\n repositories: {},\n });\n }\n\n const repoState = this.repoStates.get(repoKey)!;\n if (!repoState.repositories[repoKey]) {\n // Handle special case for local workspaces\n if (repoKey === \"__local__\") {\n repoState.repositories[repoKey] = {\n owner: \"local\",\n repo: \"local\",\n controlPath: \"local\",\n worktrees: {},\n };\n } else if (repoInfo) {\n repoState.repositories[repoKey] = {\n owner: repoInfo.owner,\n repo: repoInfo.repo,\n controlPath: repoInfo.controlPath,\n worktrees: {},\n };\n } else {\n const { owner, repo } = this.parseRepoKey(repoKey);\n repoState.repositories[repoKey] = {\n owner,\n repo,\n controlPath: path.join(\n this.repoBasePath,\n \"repos\",\n repoKey,\n \"control\"\n ),\n worktrees: {},\n };\n }\n } else if (repoInfo?.controlPath) {\n // Ensure we persist the latest controlPath (important for local repos)\n repoState.repositories[repoKey].controlPath = repoInfo.controlPath;\n }\n\n repoState.repositories[repoKey].worktrees[state.taskId] = state;\n await this.persistState();\n }\n\n /**\n * Update task state by task ID\n */\n private async updateTaskStateByTaskId(\n taskId: string,\n state: TaskGitState\n ): Promise<void> {\n for (const [repoKey, repoState] of this.repoStates) {\n for (const repo of Object.values(repoState.repositories)) {\n if (repo.worktrees[taskId]) {\n repo.worktrees[taskId] = state;\n await this.persistState();\n return;\n }\n }\n }\n }\n\n /**\n * Persist state to disk\n */\n async persistState(): Promise<void> {\n try {\n const stateData: Record<string, RepositoryState> = {};\n for (const [key, value] of this.repoStates) {\n stateData[key] = value;\n }\n\n await this.ensureDirectory(path.dirname(this.stateFilePath));\n await fs.writeFile(\n this.stateFilePath,\n JSON.stringify(stateData, null, 2)\n );\n\n console.log(\"Persisted repository state\");\n } catch (error) {\n console.error(\"Failed to persist repository state:\", error);\n }\n }\n\n /**\n * Restore state from disk\n */\n async restoreState(): Promise<void> {\n await this.migrateLegacyStateFileIfNeeded();\n\n try {\n const data = await fs.readFile(this.stateFilePath, \"utf-8\");\n const stateData = JSON.parse(data) as Record<string, RepositoryState>;\n\n this.repoStates.clear();\n for (const [key, value] of Object.entries(stateData)) {\n // Convert date strings back to Date objects\n for (const repo of Object.values(value.repositories)) {\n for (const worktree of Object.values(repo.worktrees)) {\n worktree.createdAt = new Date(worktree.createdAt);\n worktree.updatedAt = new Date(worktree.updatedAt);\n }\n }\n this.repoStates.set(key, value);\n }\n\n console.log(\"Restored repository state\");\n } catch (error) {\n if ((error as any).code !== \"ENOENT\") {\n console.error(\"Failed to restore repository state:\", error);\n }\n // If file doesn't exist, that's okay - we'll start fresh\n }\n }\n\n private async migrateLegacyStateFileIfNeeded(): Promise<void> {\n const hasNewStateFile = await fs\n .access(this.stateFilePath)\n .then(() => true)\n .catch(() => false);\n\n if (hasNewStateFile) return;\n\n const hasLegacyStateFile = await fs\n .access(this.legacyStateFilePath)\n .then(() => true)\n .catch(() => false);\n\n if (!hasLegacyStateFile) return;\n\n await this.ensureDirectory(path.dirname(this.stateFilePath));\n await fs.rename(this.legacyStateFilePath, this.stateFilePath);\n console.log(\n `Moved legacy repository state file to runner data directory: ${this.stateFilePath}`\n );\n }\n\n /**\n * Override parent's checkoutRepository to use worktrees for backward compatibility\n */\n override async checkoutRepository(\n workspaceId: string,\n repoUrl: string,\n branch: string,\n githubToken?: string\n ): Promise<string> {\n // If it's a local repository URL, delegate to parent's checkoutLocalRepository\n if (repoUrl.startsWith(\"file://\")) {\n const localPath = repoUrl.replace(\"file://\", \"\");\n return super.checkoutLocalRepository(workspaceId, localPath);\n }\n\n const { key } = this.getRepoKey(repoUrl);\n\n // Ensure control repository exists\n await this.ensureControlRepository(repoUrl, githubToken);\n\n // Create or update workspace worktree\n const worktreesPath = path.join(\n this.repoBasePath,\n \"repos\",\n key,\n \"worktrees\"\n );\n const workspaceWorktreePath = path.join(\n worktreesPath,\n `workspace_${workspaceId}`\n );\n\n try {\n // Check if workspace worktree already exists\n await fs.access(workspaceWorktreePath);\n\n // Update existing worktree\n const git = simpleGit(workspaceWorktreePath);\n await git.fetch(\"origin\");\n await git.reset([\"--hard\", `origin/${branch}`]);\n await git.clean(\"f\", [\"-d\"]);\n\n console.log(`Updated workspace worktree for ${workspaceId}`);\n } catch {\n // Create new workspace worktree\n const controlPath = path.join(this.repoBasePath, \"repos\", key, \"control\");\n const git = simpleGit(controlPath);\n\n await this.ensureDirectory(worktreesPath);\n await git.raw([\n \"worktree\",\n \"add\",\n workspaceWorktreePath,\n `origin/${branch}`,\n ]);\n\n console.log(`Created workspace worktree for ${workspaceId}`);\n }\n\n return workspaceWorktreePath;\n }\n}\n","/**\n * State Manager for persisting runner state\n * \n * Manages persistent state including lastProcessedAt timestamp\n * to enable proper catch-up on restart.\n */\n\nimport fs from 'fs/promises';\nimport path from 'path';\nimport { createLogger } from './logger.js';\n\nconst logger = createLogger('StateManager');\n\nexport interface RunnerState {\n runnerId: string;\n runnerUid: string | null;\n lastProcessedAt: string | null; // ISO string\n isActiveRunner: boolean;\n updatedAt: string; // ISO string\n}\n\nexport class StateManager {\n private statePath: string;\n private state: RunnerState | null = null;\n private saveTimer: NodeJS.Timeout | null = null;\n\n constructor(dataDir: string, runnerId: string) {\n // Namespace state file by runnerId (stable external ID) to separate different users\n const stateFile = `runner-state-${runnerId}.json`;\n this.statePath = path.join(dataDir, stateFile);\n }\n\n /**\n * Load state from disk\n */\n async loadState(): Promise<RunnerState | null> {\n try {\n const content = await fs.readFile(this.statePath, 'utf-8');\n this.state = JSON.parse(content);\n logger.info('Loaded runner state', {\n runnerId: this.state?.runnerId,\n runnerUid: this.state?.runnerUid,\n lastProcessedAt: this.state?.lastProcessedAt,\n isActiveRunner: this.state?.isActiveRunner,\n });\n return this.state;\n } catch (error) {\n if ((error as any).code === 'ENOENT') {\n logger.debug('No state file found, starting fresh');\n return null;\n }\n logger.error('Failed to load state file:', error);\n return null;\n }\n }\n\n /**\n * Save state to disk (debounced for non-critical updates)\n */\n async saveState(state: RunnerState): Promise<void> {\n this.state = state;\n\n // Cancel any pending save\n if (this.saveTimer) {\n clearTimeout(this.saveTimer);\n }\n\n // Debounce saves to avoid excessive disk writes\n // NOTE: lastProcessedAt updates use saveStateImmediate() instead\n this.saveTimer = setTimeout(async () => {\n await this.writeStateToDisk(state);\n }, 1000); // 1 second debounce for non-critical state\n }\n\n /**\n * Write state to disk immediately (no debounce)\n * Used for critical state like lastProcessedAt watermark\n */\n private async writeStateToDisk(state: RunnerState): Promise<void> {\n try {\n // Ensure directory exists\n const dir = path.dirname(this.statePath);\n await fs.mkdir(dir, { recursive: true });\n\n // Update timestamp\n state.updatedAt = new Date().toISOString();\n\n // Write atomically by writing to temp file first\n const tempPath = `${this.statePath}.tmp`;\n await fs.writeFile(tempPath, JSON.stringify(state, null, 2), 'utf-8');\n await fs.rename(tempPath, this.statePath);\n\n logger.debug('Saved runner state', {\n runnerId: state.runnerId,\n lastProcessedAt: state.lastProcessedAt,\n isActiveRunner: state.isActiveRunner,\n });\n } catch (error) {\n logger.error('Failed to save state file:', error);\n throw error;\n }\n }\n\n /**\n * Update lastProcessedAt timestamp\n *\n * CRITICAL: This writes to disk immediately (no debounce) to prevent\n * message replay on runner reconnection. If the watermark isn't persisted\n * before a disconnect, already-processed messages will be replayed.\n */\n async updateLastProcessedAt(timestamp: Date | string): Promise<void> {\n if (!this.state) {\n throw new Error('State not loaded');\n }\n\n const isoString = timestamp instanceof Date ? timestamp.toISOString() : timestamp;\n\n const updatedState: RunnerState = {\n ...this.state,\n lastProcessedAt: isoString,\n };\n\n // Update in-memory state immediately\n this.state = updatedState;\n\n // Write to disk immediately - critical for correctness on reconnection\n await this.writeStateToDisk(updatedState);\n }\n\n /**\n * Update runner registration details\n */\n async updateRunnerRegistration(\n runnerId: string,\n runnerUid: string | null,\n lastProcessedAt: Date | null\n ): Promise<void> {\n const state: RunnerState = this.state || {\n runnerId: '',\n runnerUid: null,\n lastProcessedAt: null,\n isActiveRunner: false,\n updatedAt: new Date().toISOString(),\n };\n\n const updatedState: RunnerState = {\n ...state,\n runnerId,\n runnerUid,\n lastProcessedAt: lastProcessedAt ? lastProcessedAt.toISOString() : null,\n };\n\n await this.saveState(updatedState);\n }\n\n /**\n * Update active runner status\n */\n async updateActiveStatus(isActive: boolean): Promise<void> {\n if (!this.state) {\n throw new Error('State not loaded');\n }\n\n const updatedState: RunnerState = {\n ...this.state,\n isActiveRunner: isActive,\n };\n\n await this.saveState(updatedState);\n }\n\n /**\n * Get current state\n */\n getState(): RunnerState | null {\n return this.state;\n }\n\n /**\n * Get lastProcessedAt as Date\n */\n getLastProcessedAt(): Date | null {\n if (!this.state || !this.state.lastProcessedAt) {\n return null;\n }\n return new Date(this.state.lastProcessedAt);\n }\n\n /**\n * Clear state (for testing or reset)\n */\n async clearState(): Promise<void> {\n this.state = null;\n try {\n await fs.unlink(this.statePath);\n logger.info('Cleared runner state');\n } catch (error) {\n if ((error as any).code !== 'ENOENT') {\n logger.error('Failed to clear state file:', error);\n throw error;\n }\n }\n }\n}","/**\n * Main RunnerApp class - entry point and lifecycle manager for the runner app\n * Updated to use SSE for real-time messaging instead of ElectricSQL\n */\n\nimport {\n RunnerConfig,\n ConversationContext,\n JsonRpcMessage,\n RetryStrategy,\n RunnerRepo,\n} from './types/index.js';\nimport { IRunnerApp } from './types/runner-interface.js';\nimport { MessageHandler } from './components/message-handler-sse.js';\nimport { ClaudeManager } from './components/claude-sdk-manager.js';\nimport { CodexManager } from './components/codex-sdk-manager.js';\nimport { NorthflareAgentManager } from './components/northflare-agent-sdk-manager.js';\nimport { EnhancedRepositoryManager } from './components/enhanced-repository-manager.js';\nimport { StateManager } from './utils/StateManager.js';\nimport { createLogger } from './utils/logger.js';\nimport { statusLineManager } from './utils/status-line.js';\nimport { isRunnerDebugEnabled } from './utils/debug.js';\nimport fs from \"fs/promises\";\nimport path from \"path\";\nimport computerName from \"computer-name\";\nimport {\n sanitizeToolResponsePayload,\n TOOL_RESPONSE_BYTE_LIMIT,\n} from './utils/tool-response-sanitizer.js';\nimport {\n buildOutgoingMessageLog,\n messageFlowLogger,\n messagesDebugEnabled,\n} from './utils/message-log.js';\nimport { RunnerAPIClient } from './services/RunnerAPIClient.js';\nimport { UpdateCoordinator } from './utils/update-coordinator.js';\nimport { RUNNER_VERSION } from './utils/version.js';\n\nfunction isSubPath(base: string | undefined, candidate: string): boolean {\n if (!base) return false;\n const normalizedBase = path.resolve(base);\n const normalizedCandidate = path.resolve(candidate);\n const baseWithSep =\n normalizedBase.endsWith(path.sep) ? normalizedBase : normalizedBase + path.sep;\n return (\n normalizedCandidate === normalizedBase ||\n normalizedCandidate.startsWith(baseWithSep)\n );\n}\n\nconst logger = createLogger(\"RunnerApp\");\n\nfunction logToolResponseTruncation(toolUseId?: string) {\n const message = `Tool response exceeded ${TOOL_RESPONSE_BYTE_LIMIT} bytes and was truncated`;\n if (toolUseId) {\n logger.warn(message, { toolUseId });\n } else {\n logger.warn(message);\n }\n}\n\nexport class RunnerApp implements IRunnerApp {\n private messageHandler!: MessageHandler;\n private claudeManager!: ClaudeManager;\n private codexManager!: CodexManager;\n private northflareAgentManager!: NorthflareAgentManager;\n private repositoryManager!: EnhancedRepositoryManager;\n private stateManager!: StateManager;\n private updateCoordinator!: UpdateCoordinator;\n private agentConversations: Map<string, ConversationContext>; // Keyed by conversation.id\n private config: RunnerConfig;\n private configPath?: string;\n private runnerReposCachePath?: string;\n private heartbeatInterval?: NodeJS.Timeout;\n private heartbeatInFlight: boolean = false;\n private isRunning: boolean = false;\n private isRegistered: boolean = false;\n private delayFn: (ms: number) => Promise<void> = (ms) =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\n // UID ownership fields\n private runnerUid: string | null = null;\n private lastProcessedAt: Date | null = null;\n private isActiveRunner: boolean = false;\n\n // Track conversations started before takeover\n private preHandoffConversations = new Set<string>();\n\n // Track recently completed conversation IDs to prevent restart on catch-up\n // Uses a Map with completion timestamp to allow cleanup of old entries\n private completedConversations = new Map<string, number>();\n private static readonly COMPLETED_CONVERSATION_TTL_MS = 60 * 60 * 1000; // 1 hour\n\n // Track summaries that arrive before a conversation starts.\n private pendingConversationSummaries = new Map<string, string>();\n\n constructor(config: RunnerConfig, configPath?: string) {\n this.config = config;\n this.configPath = configPath;\n this.agentConversations = new Map();\n this.runnerReposCachePath = path.join(this.config.dataDir, \"runner-repos-cache.json\");\n // Note: State manager will be initialized in start() after fetching runnerId\n }\n\n private async fetchRunnerId(): Promise<string> {\n const token = process.env[\"NORTHFLARE_RUNNER_TOKEN\"];\n if (!token) {\n throw new Error(\"NORTHFLARE_RUNNER_TOKEN environment variable is required\");\n }\n\n try {\n const response = await fetch(`${this.config.orchestratorUrl}/api/runner/id`, {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${token}`,\n },\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ error: response.statusText })) as any;\n throw new Error(`Failed to fetch runner ID: ${error.error || response.statusText}`);\n }\n\n const data = await response.json() as { runnerId?: string };\n if (!data.runnerId) {\n throw new Error(\"Server did not return runnerId\");\n }\n\n logger.info(`Fetched runnerId: ${data.runnerId}`);\n return data.runnerId;\n } catch (error) {\n logger.error(\"Failed to fetch runner ID from orchestrator\", error);\n throw error;\n }\n }\n\n private initializeComponents(): void {\n // Initialize repository manager first as it's used by Claude manager\n this.repositoryManager = new EnhancedRepositoryManager(this);\n\n // Initialize Claude manager with repository manager (using SDK-native manager)\n this.claudeManager = new ClaudeManager(this, this.repositoryManager);\n\n // Initialize Codex manager for OpenAI-based conversations\n this.codexManager = new CodexManager(this, this.repositoryManager);\n\n // Initialize Northflare Agent manager for OpenRouter-based conversations\n this.northflareAgentManager = new NorthflareAgentManager(\n this,\n this.repositoryManager\n );\n\n // Initialize message handler with SSE support\n this.messageHandler = new MessageHandler(this);\n\n // Initialize update coordinator for auto-updates\n this.updateCoordinator = new UpdateCoordinator({\n autoUpdateDisabled: process.env[\"NORTHFLARE_DISABLE_AUTO_UPDATE\"] === 'true',\n getActiveConversationCount: () => this.agentConversations.size,\n saveState: async () => {\n await this.stateManager.saveState({\n runnerId: this.config.runnerId!,\n runnerUid: this.runnerUid,\n lastProcessedAt: this.lastProcessedAt?.toISOString() || null,\n isActiveRunner: this.isActiveRunner,\n updatedAt: new Date().toISOString(),\n });\n },\n getConfigPath: () => this.configPath,\n });\n }\n\n async start(): Promise<void> {\n if (this.isRunning) {\n throw new Error(\"Runner is already running\");\n }\n\n try {\n // Fetch runnerId from orchestrator using token\n const runnerId = await this.fetchRunnerId();\n this.config.runnerId = runnerId;\n\n // Initialize state manager with runnerId\n this.stateManager = new StateManager(this.config.dataDir, runnerId);\n\n // Initialize other components\n this.initializeComponents();\n\n // Load persisted state\n const savedState = await this.stateManager.loadState();\n if (savedState) {\n // Restore state from previous run\n this.config.runnerId = savedState.runnerId;\n this.runnerUid = savedState.runnerUid;\n this.lastProcessedAt = savedState.lastProcessedAt\n ? new Date(savedState.lastProcessedAt)\n : null;\n this.isActiveRunner = savedState.isActiveRunner;\n\n logger.info(\"Restored runner state from disk\", {\n runnerId: savedState.runnerId,\n runnerUid: savedState.runnerUid,\n lastProcessedAt: savedState.lastProcessedAt,\n isActiveRunner: savedState.isActiveRunner,\n });\n }\n\n // Bootstrap runner repos from server (with cache fallback)\n await this.refreshRunnerReposFromServer(true);\n\n // Register with retry strategy\n await this.registerWithRetry();\n\n // Log debug info after registration\n if (isRunnerDebugEnabled()) {\n logger.debug(\"Runner initialized with ownership details\", {\n runnerId: this.config.runnerId,\n runnerUid: this.runnerUid,\n lastProcessedAt: this.lastProcessedAt?.toISOString() || \"null\",\n isActiveRunner: this.isActiveRunner,\n orchestratorUrl: this.config.orchestratorUrl,\n });\n }\n\n // Start message processing with SSE\n await this.messageHandler.startProcessing();\n\n // Start heartbeat after successful registration\n this.startHeartbeat();\n\n this.isRunning = true;\n\n logger.info(`Runner ${this.config.runnerId} started successfully`);\n } catch (error) {\n logger.error(\"Failed to start runner:\", error);\n throw error;\n }\n }\n\n async stop(): Promise<void> {\n if (!this.isRunning) {\n return;\n }\n\n logger.info(`Stopping runner ${this.config.runnerId}...`);\n\n // Stop heartbeat\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = undefined;\n }\n\n // Stop all conversations\n await this.stopAllConversations();\n\n // Stop message processing\n await this.messageHandler.stopProcessing();\n\n // Clean up status line\n statusLineManager.dispose();\n\n this.isRunning = false;\n\n logger.info(`Runner ${this.config.runnerId} stopped`);\n }\n\n async notify(method: string, params: any): Promise<void> {\n try {\n const sanitization = sanitizeToolResponsePayload(method, params);\n if (sanitization.truncated) {\n logToolResponseTruncation(sanitization.toolUseId);\n }\n const safeParams = sanitization.truncated\n ? sanitization.params\n : params;\n // Log RPC notification in debug mode\n logger.debug(`[RPC] Sending notification: ${method}`, {\n method,\n params: JSON.stringify(safeParams, null, 2),\n });\n\n // Send notification with retry logic\n await this.sendToOrchestratorWithRetry({\n jsonrpc: \"2.0\",\n method,\n params: safeParams,\n });\n } catch (error) {\n // Special handling for heartbeat errors - just log a simple line\n if (method === \"runner.heartbeat\") {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n logger.error(`Heartbeat failed: ${errorMessage}`);\n } else {\n // For other RPC errors, log the method and error without stack\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n logger.error(\n `RPC Error: Failed to notify with method '${method}': ${errorMessage}`\n );\n }\n throw error;\n }\n }\n\n async sendToOrchestrator(message: JsonRpcMessage): Promise<any> {\n const sanitization = sanitizeToolResponsePayload(\n message.method,\n message.params\n );\n if (sanitization.truncated) {\n logToolResponseTruncation(sanitization.toolUseId);\n }\n\n const messageToSend = sanitization.truncated\n ? {\n ...message,\n params: sanitization.params,\n }\n : message;\n\n try {\n if (messagesDebugEnabled()) {\n messageFlowLogger.debug(\n \"[outgoing] runner -> orchestrator\",\n {\n runnerId: this.config.runnerId,\n ...buildOutgoingMessageLog(messageToSend),\n }\n );\n }\n\n // Log RPC request in debug mode\n logger.debug(`[RPC] Sending request:`, {\n method: messageToSend.method,\n id: messageToSend.id,\n params: messageToSend.params\n ? JSON.stringify(messageToSend.params, null, 2)\n : undefined,\n });\n\n // Build headers - only include X-Runner-Id if we have one (not during registration)\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${process.env[\"NORTHFLARE_RUNNER_TOKEN\"]}`,\n };\n\n // Only add X-Runner-Id if we're registered (not during registration)\n if (this.config.runnerId && message.method !== \"runner.register\") {\n headers[\"X-Runner-Id\"] = this.config.runnerId;\n }\n\n const response = await fetch(\n `${this.config.orchestratorUrl}/api/runner/messages`,\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(messageToSend),\n signal: AbortSignal.timeout(30000), // 30 second timeout\n }\n );\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`HTTP ${response.status}: ${errorText}`);\n }\n\n const result = (await response.json()) as any;\n\n // Log RPC response in debug mode\n logger.debug(`[RPC] Received response:`, {\n method: messageToSend.method,\n id: messageToSend.id,\n result: result?.result\n ? JSON.stringify(result.result, null, 2)\n : undefined,\n error: result?.error\n ? JSON.stringify(result.error, null, 2)\n : undefined,\n });\n\n return result;\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n\n // Don't log verbose errors for heartbeat failures\n if (message.method === \"runner.heartbeat\") {\n // Heartbeat errors are already logged in notify()\n } else if (message.method === \"runner.register\") {\n // Special case for registration failures\n logger.error(`Registration failed: ${errorMessage}`);\n } else {\n // For other RPC messages, log the attempted message and error\n logger.error(`RPC failed:`, {\n method: messageToSend.method,\n params: messageToSend.params,\n error: errorMessage,\n });\n }\n throw error;\n }\n }\n\n getConversationContext(\n conversationId: string\n ): ConversationContext | undefined {\n // Using conversation.id as primary key for conversation tracking\n const context = this.agentConversations.get(conversationId);\n logger.debug(`[Runner] getConversationContext lookup:`, {\n conversationId,\n found: !!context,\n totalConversations: this.agentConversations.size,\n allConversationIds: Array.from(this.agentConversations.keys()),\n });\n return context;\n }\n\n applyConversationSummary(conversationId: string, summary: string | null): void {\n const normalizedSummary =\n typeof summary === \"string\" ? summary.replace(/\\s+/g, \" \").trim() : \"\";\n\n if (!normalizedSummary) return;\n\n const context = this.agentConversations.get(conversationId);\n if (context) {\n context.summary = normalizedSummary;\n return;\n }\n\n this.pendingConversationSummaries.set(conversationId, normalizedSummary);\n }\n\n consumePendingConversationSummary(conversationId: string): string | undefined {\n const summary = this.pendingConversationSummaries.get(conversationId);\n if (summary) {\n this.pendingConversationSummaries.delete(conversationId);\n }\n return summary;\n }\n\n /**\n * Check if a conversation was recently completed (to prevent restart on catch-up)\n */\n wasConversationCompleted(conversationId: string): boolean {\n const completedAt = this.completedConversations.get(conversationId);\n if (!completedAt) return false;\n\n // Check if the completion is still within TTL\n const now = Date.now();\n if (now - completedAt > RunnerApp.COMPLETED_CONVERSATION_TTL_MS) {\n // Expired, clean it up\n this.completedConversations.delete(conversationId);\n return false;\n }\n return true;\n }\n\n /**\n * Mark a conversation as completed to prevent restart on catch-up\n */\n markConversationCompleted(conversationId: string): void {\n this.completedConversations.set(conversationId, Date.now());\n\n // Opportunistically clean up old entries\n this.cleanupCompletedConversations();\n }\n\n /**\n * Clean up expired completed conversation entries\n */\n private cleanupCompletedConversations(): void {\n const now = Date.now();\n for (const [id, completedAt] of this.completedConversations) {\n if (now - completedAt > RunnerApp.COMPLETED_CONVERSATION_TTL_MS) {\n this.completedConversations.delete(id);\n }\n }\n }\n\n private async registerRunner(): Promise<void> {\n try {\n if (!this.config.workspacePath || !path.isAbsolute(this.config.workspacePath)) {\n throw new Error(\"workspacePath must be an absolute path\");\n }\n\n const filteredRunnerRepos: RunnerRepo[] = Array.isArray(this.config.runnerRepos)\n ? this.config.runnerRepos\n : [];\n\n // Get computer name for registration\n let hostComputerName: string | undefined;\n try {\n hostComputerName = await computerName();\n } catch (error) {\n logger.warn(\"Failed to get computer name, will use default\", error);\n }\n\n const response = await this.sendToOrchestratorWithRetry({\n jsonrpc: \"2.0\",\n id: \"register-\" + Date.now(),\n method: \"runner.register\",\n params: {\n version: RUNNER_VERSION,\n runnerRepos: filteredRunnerRepos,\n computerName: hostComputerName,\n workspacePath: this.config.workspacePath,\n },\n });\n\n // Debug log the full response\n logger.info(`Registration response:`, JSON.stringify(response, null, 2));\n\n // Log the runnerRepos being sent and received\n if (isRunnerDebugEnabled()) {\n logger.debug(\n \"Registration runnerRepos sent:\",\n JSON.stringify(filteredRunnerRepos)\n );\n logger.debug(\n \"Registration runnerRepos received:\",\n JSON.stringify(response?.result?.runnerRepos)\n );\n }\n\n // Check for JSONRPC error response\n if (response?.error) {\n logger.error(`Registration error from server:`, response.error);\n throw new Error(\n `Server error: ${response.error.message || \"Unknown error\"}`\n );\n }\n\n // Extract result from JSONRPC response structure\n const result = response?.result;\n\n if (result?.runnerId) {\n this.config.runnerId = result.runnerId;\n this.runnerUid = result.runnerUid;\n this.lastProcessedAt = result.lastProcessedAt\n ? new Date(result.lastProcessedAt)\n : null;\n this.isRegistered = true;\n\n // If this is a fresh start (no previous lastProcessedAt), set as active runner immediately\n // The server will also send a runner.uid.changed message, but we set it here to avoid\n // any window where isActiveRunner is incorrectly false\n if (!result.lastProcessedAt) {\n this.isActiveRunner = true;\n logger.info(\n `First-time registration - setting as active runner immediately`\n );\n }\n\n // Save registration state\n await this.stateManager.updateRunnerRegistration(\n result.runnerId,\n result.runnerUid,\n this.lastProcessedAt\n );\n\n // Persist the active status if we set it\n if (this.isActiveRunner) {\n await this.stateManager.updateActiveStatus(true);\n }\n\n logger.info(\n `Runner registered successfully with ID: ${this.config.runnerId} and UID: ${this.runnerUid}`\n );\n\n // Process runnerRepos from response\n if (result.runnerRepos && Array.isArray(result.runnerRepos)) {\n const prepared = await this.prepareRunnerRepos(result.runnerRepos);\n await this.replaceRunnerRepos(prepared);\n }\n\n // Debug logging for registration details\n if (isRunnerDebugEnabled()) {\n logger.debug(\"Registration complete with details\", {\n runnerId: this.config.runnerId,\n runnerUid: this.runnerUid,\n lastProcessedAt: this.lastProcessedAt?.toISOString() || \"null\",\n orchestratorUrl: this.config.orchestratorUrl,\n dataDir: this.config.dataDir,\n runnerReposCount: result.runnerRepos?.length || 0,\n });\n }\n } else {\n logger.error(`Registration failed. Expected result.runnerId but got:`, {\n hasResult: !!result,\n resultKeys: result ? Object.keys(result) : [],\n fullResponse: JSON.stringify(response, null, 2),\n });\n throw new Error(\"Registration response did not include runnerId\");\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n logger.error(`Failed to register runner: ${errorMessage}`);\n throw error;\n }\n }\n\n private async registerWithRetry(): Promise<void> {\n const strategy = this.config.retryStrategy;\n\n if (strategy === \"none\") {\n // Single attempt, no retries\n await this.registerRunner();\n return;\n }\n\n if (strategy === \"interval\") {\n // Retry at fixed intervals\n const intervalMs = this.config.retryIntervalSecs * 1000;\n let attempt = 0;\n\n while (!this.isRegistered) {\n attempt++;\n try {\n logger.info(`Registration attempt ${attempt}...`);\n await this.registerRunner();\n return;\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n logger.error(\n `Registration attempt ${attempt} failed: ${errorMessage}`\n );\n logger.info(\n `Retrying in ${this.config.retryIntervalSecs} seconds...`\n );\n await this.delayFn(intervalMs);\n }\n }\n }\n\n if (strategy === \"exponential\") {\n // Exponential backoff with max duration\n const maxDurationMs = this.config.retryDurationSecs * 1000;\n const startTime = Date.now();\n let delayMs = 8000; // Start with 8 seconds\n let attempt = 0;\n\n while (!this.isRegistered) {\n attempt++;\n try {\n logger.info(`Registration attempt ${attempt}...`);\n await this.registerRunner();\n return;\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n logger.error(\n `Registration attempt ${attempt} failed: ${errorMessage}`\n );\n\n const elapsedMs = Date.now() - startTime;\n if (elapsedMs >= maxDurationMs) {\n // Final retry at max duration\n const remainingMs = maxDurationMs - elapsedMs;\n if (remainingMs > 0) {\n logger.info(\n `Final retry in ${Math.ceil(remainingMs / 1000)} seconds...`\n );\n await this.delayFn(remainingMs);\n\n try {\n logger.info(\"Final registration attempt...\");\n await this.registerRunner();\n return;\n } catch (finalError) {\n const errorMessage =\n finalError instanceof Error\n ? finalError.message\n : String(finalError);\n logger.error(\n `Final registration attempt failed: ${errorMessage}`\n );\n throw new Error(\n `Failed to register after ${this.config.retryDurationSecs} seconds`\n );\n }\n } else {\n throw new Error(\n `Failed to register after ${this.config.retryDurationSecs} seconds`\n );\n }\n }\n\n // Calculate next delay with exponential backoff\n const nextDelayMs = Math.min(delayMs, maxDurationMs - elapsedMs);\n logger.info(\n `Retrying in ${Math.ceil(nextDelayMs / 1000)} seconds...`\n );\n await this.delayFn(nextDelayMs);\n\n // Double the delay for next attempt\n delayMs = Math.min(delayMs * 2, maxDurationMs);\n }\n }\n }\n }\n\n private async sendToOrchestratorWithRetry(\n message: JsonRpcMessage\n ): Promise<any> {\n const maxRetries = 5;\n const initialDelayMs = 1000; // Start with 1 second\n const maxDelayMs = 60000; // Max 60 seconds\n const jitterMs = 500; // Add up to 500ms of random jitter\n\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await this.sendToOrchestrator(message);\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n // Don't retry on certain errors\n if (\n lastError.message.includes(\"HTTP 401\") ||\n lastError.message.includes(\"HTTP 403\") ||\n lastError.message.includes(\"HTTP 404\")\n ) {\n throw lastError;\n }\n\n if (attempt < maxRetries) {\n // Calculate exponential backoff with jitter\n const baseDelay = Math.min(\n initialDelayMs * Math.pow(2, attempt),\n maxDelayMs\n );\n const jitter = Math.random() * jitterMs;\n const delayMs = baseDelay + jitter;\n\n // Log retry attempt\n const errorMessage = lastError.message || String(lastError);\n if (message.method === \"runner.heartbeat\") {\n // Less verbose for heartbeat retries\n logger.debug(\n `Heartbeat retry ${attempt + 1}/${maxRetries + 1} in ${Math.round(\n delayMs\n )}ms`\n );\n } else {\n logger.warn(\n `RPC retry ${attempt + 1}/${maxRetries + 1} for '${\n message.method\n }' after error: ${errorMessage}. Retrying in ${Math.round(\n delayMs\n )}ms`\n );\n }\n\n await this.delayFn(delayMs);\n }\n }\n }\n\n // All retries exhausted\n const finalError = lastError || new Error(\"Unknown error\");\n if (message.method !== \"runner.heartbeat\") {\n logger.error(`RPC failed after ${maxRetries + 1} attempts:`, {\n method: message.method,\n error: finalError.message,\n });\n }\n throw finalError;\n }\n\n private startHeartbeat(): void {\n if (!this.isRegistered || !this.config.runnerId) {\n logger.warn(\"Cannot start heartbeat: runner not registered\");\n return;\n }\n\n this.heartbeatInterval = setInterval(async () => {\n if (this.heartbeatInFlight) {\n return;\n }\n this.heartbeatInFlight = true;\n try {\n const response = await this.sendToOrchestrator({\n jsonrpc: \"2.0\",\n id: `heartbeat-${Date.now()}`,\n method: \"runner.heartbeat\",\n params: {\n runnerId: this.config.runnerId,\n activeConversations: this.agentConversations.size,\n uptime: process.uptime(),\n memoryUsage: process.memoryUsage(),\n },\n });\n\n // Check for expectedRunnerVersion in heartbeat response\n if (response?.result?.expectedRunnerVersion) {\n await this.checkForUpdate(response.result.expectedRunnerVersion);\n }\n } catch (error) {\n // Heartbeat errors are already logged in sendToOrchestrator\n } finally {\n this.heartbeatInFlight = false;\n }\n }, this.config.heartbeatInterval);\n }\n\n private async stopAllConversations(\n isRunnerShutdown: boolean = true\n ): Promise<void> {\n const stopPromises: Promise<void>[] = [];\n\n for (const [conversationId, context] of this.agentConversations) {\n if (context.status === \"active\" || context.status === \"starting\") {\n // Active/starting conversations: properly stop them via manager\n const manager = this.getManagerForContext(context);\n stopPromises.push(\n manager\n .stopConversation(context.agentSessionId, context, isRunnerShutdown)\n .catch((error) => {\n logger.error(\n `Failed to stop conversation ${context.agentSessionId}:`,\n error\n );\n })\n );\n } else {\n // Already stopped/errored conversations: ensure orchestrator is notified\n // This prevents tasks from restarting on runner restart\n stopPromises.push(\n this.notify(\"conversation.end\", {\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n agentSessionId: context.agentSessionId,\n isError: context.status === \"error\",\n reason: \"runner_shutdown_cleanup\",\n }).catch((error) => {\n logger.error(\n `Failed to notify conversation.end for ${conversationId}:`,\n error\n );\n })\n );\n }\n }\n\n await Promise.all(stopPromises);\n this.agentConversations.clear();\n }\n\n // Update lastProcessedAt and persist state\n async updateLastProcessedAt(timestamp: Date | null): Promise<void> {\n this.lastProcessedAt = timestamp;\n if (timestamp) {\n await this.stateManager.updateLastProcessedAt(timestamp);\n }\n }\n\n // Getters for components\n get config_(): RunnerConfig {\n return this.config;\n }\n\n get activeConversations_(): Map<string, ConversationContext> {\n return this.agentConversations;\n }\n\n get claudeManager_(): ClaudeManager {\n return this.claudeManager;\n }\n get codexManager_(): CodexManager {\n return this.codexManager;\n }\n get northflareAgentManager_(): NorthflareAgentManager {\n return this.northflareAgentManager;\n }\n get repositoryManager_(): EnhancedRepositoryManager {\n return this.repositoryManager;\n }\n\n getConfigPath(): string | undefined {\n return this.configPath;\n }\n\n getRunnerId(): string | undefined {\n return this.config.runnerId;\n }\n\n // UID ownership getters/setters\n getRunnerUid(): string | null {\n return this.runnerUid;\n }\n\n getLastProcessedAt(): Date | null {\n return this.lastProcessedAt;\n }\n\n getIsActiveRunner(): boolean {\n return this.isActiveRunner;\n }\n\n setIsActiveRunner(active: boolean): void {\n const previousState = this.isActiveRunner;\n this.isActiveRunner = active;\n\n // Persist state change\n this.stateManager.updateActiveStatus(active).catch((error) => {\n logger.error(\"Failed to persist active status:\", error);\n });\n\n if (isRunnerDebugEnabled()) {\n logger.debug(\"Active runner status changed\", {\n previous: previousState,\n new: active,\n runnerUid: this.runnerUid,\n lastProcessedAt: this.lastProcessedAt?.toISOString() || \"null\",\n });\n }\n }\n\n setLastProcessedAt(timestamp: Date | null): void {\n const previousTimestamp = this.lastProcessedAt;\n this.lastProcessedAt = timestamp;\n\n if (isRunnerDebugEnabled()) {\n logger.debug(\"LastProcessedAt updated\", {\n previous: previousTimestamp?.toISOString() || \"null\",\n new: timestamp?.toISOString() || \"null\",\n runnerUid: this.runnerUid,\n isActiveRunner: this.isActiveRunner,\n });\n }\n }\n\n getPreHandoffConversations(): Set<string> {\n return this.preHandoffConversations;\n }\n\n // For testing purposes - allows mocking delays\n setDelayFunction(fn: (ms: number) => Promise<void>): void {\n this.delayFn = fn;\n }\n\n getWorkspacePath(): string | undefined {\n return this.config.workspacePath;\n }\n\n /**\n * Check if an update is available and trigger update process if needed.\n * Called by message handler when a message includes expectedRunnerVersion.\n */\n async checkForUpdate(serverVersion: string): Promise<void> {\n await this.updateCoordinator.checkVersion(serverVersion);\n }\n\n /**\n * Notify the update coordinator that a conversation has ended.\n * If there's a pending update and this was the last active conversation,\n * the update will be triggered.\n */\n async onConversationEnd(): Promise<void> {\n await this.updateCoordinator.onConversationEnd();\n }\n\n /**\n * Check if there's a pending update waiting for conversations to complete.\n */\n hasPendingUpdate(): boolean {\n return this.updateCoordinator.hasPendingUpdate;\n }\n\n async replaceRunnerRepos(repos: RunnerRepo[]): Promise<void> {\n this.config.runnerRepos = repos;\n await this.saveRunnerRepoCache(repos);\n }\n\n private async saveRunnerRepoCache(repos: RunnerRepo[]): Promise<void> {\n if (!this.runnerReposCachePath) return;\n try {\n await fs.mkdir(path.dirname(this.runnerReposCachePath), { recursive: true });\n await fs.writeFile(\n this.runnerReposCachePath,\n JSON.stringify({ updatedAt: new Date().toISOString(), repos }, null, 2),\n \"utf-8\"\n );\n } catch (err) {\n logger.warn(\"Failed to persist runner repo cache\", err);\n }\n }\n\n private async loadRunnerRepoCache(): Promise<RunnerRepo[] | null> {\n if (!this.runnerReposCachePath) return null;\n try {\n const content = await fs.readFile(this.runnerReposCachePath, \"utf-8\");\n const parsed = JSON.parse(content);\n if (Array.isArray(parsed?.repos)) {\n logger.info(\n `Loaded ${parsed.repos.length} runner repos from cache at ${this.runnerReposCachePath}`\n );\n return parsed.repos as RunnerRepo[];\n }\n } catch (err: any) {\n if (err?.code !== \"ENOENT\") {\n logger.warn(\"Failed to load runner repo cache\", err);\n }\n }\n return null;\n }\n\n private isRepoAllowed(repo: RunnerRepo, workspacePath?: string): boolean {\n const base = workspacePath || this.config.workspacePath;\n const resolvedPath = path.resolve(repo.path);\n const external = repo.external === true || !isSubPath(base, resolvedPath);\n if (!external && base && !isSubPath(base, resolvedPath)) {\n return false;\n }\n return true;\n }\n\n private async prepareRunnerRepos(\n repos: RunnerRepo[],\n workspacePath?: string\n ): Promise<RunnerRepo[]> {\n const prepared: RunnerRepo[] = [];\n for (const repo of repos || []) {\n if (!repo?.path || !repo?.name) continue;\n const resolvedPath = path.resolve(repo.path);\n const external = repo.external === true || !isSubPath(workspacePath || this.config.workspacePath, resolvedPath);\n\n if (!external && workspacePath && !isSubPath(workspacePath, resolvedPath)) {\n logger.warn(\n `Ignoring runnerRepo ${repo.name} because path is outside workspace: ${resolvedPath}`\n );\n continue;\n }\n\n if (!external && this.config.workspacePath && !isSubPath(this.config.workspacePath, resolvedPath)) {\n logger.warn(\n `Ignoring runnerRepo ${repo.name} because path is outside configured workspace: ${resolvedPath}`\n );\n continue;\n }\n\n try {\n await fs.mkdir(resolvedPath, { recursive: true });\n const stats = await fs.stat(resolvedPath);\n if (!stats.isDirectory()) {\n logger.warn(\n `RunnerRepo path is not a directory: ${repo.name} at ${resolvedPath}`\n );\n continue;\n }\n } catch (err) {\n logger.warn(\n `RunnerRepo path could not be prepared: ${repo.name} at ${resolvedPath}`,\n err\n );\n continue;\n }\n\n prepared.push({\n ...repo,\n path: resolvedPath,\n external,\n });\n }\n\n return prepared;\n }\n\n private async refreshRunnerReposFromServer(\n useCacheOnFailure: boolean = true\n ): Promise<void> {\n const apiClient = new RunnerAPIClient(this.config);\n if (this.config.runnerId) {\n apiClient.setRunnerId(this.config.runnerId);\n }\n\n try {\n const snapshot = await apiClient.listRunnerRepos();\n const prepared = await this.prepareRunnerRepos(\n snapshot.repos || [],\n snapshot.workspacePath\n );\n await this.replaceRunnerRepos(prepared);\n logger.info(`Hydrated runner repos from server snapshot (${prepared.length})`);\n } catch (err) {\n logger.error(\"Failed to fetch runner repo snapshot from server\", err);\n if (useCacheOnFailure) {\n const cached = await this.loadRunnerRepoCache();\n if (cached) {\n const prepared = await this.prepareRunnerRepos(cached);\n await this.replaceRunnerRepos(prepared);\n logger.info(\n `Hydrated runner repos from local cache (${prepared.length}) after snapshot failure`\n );\n return;\n }\n }\n throw err;\n }\n }\n\n private getManagerForContext(\n context?: ConversationContext | null\n ): ClaudeManager | CodexManager {\n const provider = context?.provider?.toLowerCase();\n if (provider === \"openai\") {\n return this.codexManager;\n }\n return this.claudeManager;\n }\n}\n","export const TOOL_RESPONSE_BYTE_LIMIT = 500 * 1024; // 500 KiB cap per tool response payload\nexport const TOOL_RESPONSE_SUFFIX = \"... [truncated]\";\n\nexport interface ToolResponseSanitizationResult {\n params: any;\n truncated: boolean;\n toolUseId?: string;\n}\n\ninterface TruncationContext {\n bytesRemaining: number;\n truncated: boolean;\n}\n\nexport function sanitizeToolResponsePayload(\n method: string | undefined,\n params: any\n): ToolResponseSanitizationResult {\n if (method !== \"message.agent\" || !params) {\n return { params, truncated: false };\n }\n\n if (!isToolResultPayload(params)) {\n return { params, truncated: false };\n }\n\n const context: TruncationContext = {\n bytesRemaining: TOOL_RESPONSE_BYTE_LIMIT,\n truncated: false,\n };\n\n const [sanitized, changed] = truncateStringsRecursively(params, context);\n\n if (!changed && !context.truncated) {\n return { params, truncated: false };\n }\n\n return {\n params: sanitized,\n truncated: true,\n toolUseId: extractToolUseId(params),\n };\n}\n\nfunction isToolResultPayload(payload: any): boolean {\n if (!payload) {\n return false;\n }\n if (payload.type === \"tool_result\" || payload.subtype === \"tool_result\") {\n return true;\n }\n if (Array.isArray(payload.content)) {\n return payload.content.some((entry: any) => isToolResultBlock(entry));\n }\n return isToolResultBlock(payload.content);\n}\n\nfunction isToolResultBlock(block: any): boolean {\n if (!block) {\n return false;\n }\n return (\n block.type === \"tool_result\" ||\n block.subtype === \"tool_result\" ||\n typeof block.tool_use_id === \"string\"\n );\n}\n\nfunction extractToolUseId(payload: any): string | undefined {\n if (!payload) {\n return undefined;\n }\n if (typeof payload.tool_use_id === \"string\") {\n return payload.tool_use_id;\n }\n if (Array.isArray(payload.content)) {\n const match = payload.content.find(\n (entry: any) => entry && typeof entry.tool_use_id === \"string\"\n );\n if (match) {\n return match.tool_use_id;\n }\n }\n if (payload.content && typeof payload.content === \"object\") {\n return extractToolUseId(payload.content);\n }\n return undefined;\n}\n\nfunction truncateStringsRecursively(\n value: any,\n context: TruncationContext\n): [any, boolean] {\n if (typeof value === \"string\") {\n return truncateStringValue(value, context);\n }\n\n if (Array.isArray(value)) {\n let mutated = false;\n let result: any[] = value;\n for (let i = 0; i < value.length; i++) {\n const [newItem, changed] = truncateStringsRecursively(value[i], context);\n if (changed) {\n if (!mutated) {\n result = value.slice();\n mutated = true;\n }\n result[i] = newItem;\n }\n }\n return [result, mutated];\n }\n\n if (value && typeof value === \"object\") {\n let mutated = false;\n let result: Record<string, any> = value;\n for (const key of Object.keys(value)) {\n const [newVal, changed] = truncateStringsRecursively(\n value[key],\n context\n );\n if (changed) {\n if (!mutated) {\n result = { ...value };\n mutated = true;\n }\n result[key] = newVal;\n }\n }\n return [result, mutated];\n }\n\n return [value, false];\n}\n\nfunction truncateStringValue(\n value: string,\n context: TruncationContext\n): [string, boolean] {\n if (context.bytesRemaining <= 0) {\n if (value.length === 0) {\n return [value, false];\n }\n context.truncated = true;\n return [\"\", true];\n }\n\n const byteLength = Buffer.byteLength(value, \"utf8\");\n if (byteLength <= context.bytesRemaining) {\n context.bytesRemaining -= byteLength;\n return [value, false];\n }\n\n const suffixBytes = Buffer.byteLength(TOOL_RESPONSE_SUFFIX, \"utf8\");\n const maxBytes = Math.max(0, context.bytesRemaining - suffixBytes);\n const truncatedBuffer = Buffer.from(value, \"utf8\").subarray(0, maxBytes);\n context.bytesRemaining = 0;\n context.truncated = true;\n return [truncatedBuffer.toString(\"utf8\") + TOOL_RESPONSE_SUFFIX, true];\n}\n","/**\n * Coordinates runner auto-updates.\n *\n * When the server sends an expectedRunnerVersion that is newer than the current\n * version, the coordinator notes the pending update and waits for the runner to\n * become idle (no active conversations) before executing the update.\n *\n * The update is performed by spawning a new process with npx, which ensures\n * the latest version is fetched and executed with the same arguments/env.\n */\n\nimport { spawn } from \"child_process\";\nimport { logger } from \"./logger.js\";\nimport { RUNNER_VERSION, isNewerVersion } from \"./version.js\";\n\nexport type UpdateState =\n | \"idle\" // No update pending\n | \"pending\" // Update available, waiting for runner to become idle\n | \"updating\" // Executing update command\n | \"restarting\"; // About to exit and restart\n\nexport interface UpdateCoordinatorOptions {\n /** If true, auto-updates are disabled */\n autoUpdateDisabled: boolean;\n /** Returns the current number of active conversations */\n getActiveConversationCount: () => number;\n /** Saves runner state before restart */\n saveState: () => Promise<void>;\n /** Gets the config path for restart args */\n getConfigPath: () => string | undefined;\n}\n\nexport class UpdateCoordinator {\n private state: UpdateState = \"idle\";\n private pendingVersion: string | null = null;\n private readonly options: UpdateCoordinatorOptions;\n\n constructor(options: UpdateCoordinatorOptions) {\n this.options = options;\n }\n\n get currentState(): UpdateState {\n return this.state;\n }\n\n get hasPendingUpdate(): boolean {\n return this.state === \"pending\";\n }\n\n get pendingVersionNumber(): string | null {\n return this.pendingVersion;\n }\n\n /**\n * Called when a message is received with an expectedRunnerVersion.\n * If the version is newer, marks an update as pending.\n * If the runner is already idle, triggers the update immediately.\n *\n * @returns true if an update was triggered or marked as pending\n */\n async checkVersion(serverVersion: string): Promise<boolean> {\n if (this.options.autoUpdateDisabled) {\n logger.debug(\"Auto-update disabled via NORTHFLARE_DISABLE_AUTO_UPDATE\");\n return false;\n }\n\n // Already handling an update\n if (this.state !== \"idle\" && this.state !== \"pending\") {\n logger.debug(\"Update already in progress\", { state: this.state });\n return false;\n }\n\n // Check if server version is newer\n if (!isNewerVersion(serverVersion, RUNNER_VERSION)) {\n return false;\n }\n\n // Already have this version pending\n if (this.pendingVersion === serverVersion) {\n return false;\n }\n\n // Mark update as pending\n this.pendingVersion = serverVersion;\n this.state = \"pending\";\n logger.info(\n `Update available: ${serverVersion} (current: ${RUNNER_VERSION}). ` +\n `Will update when idle.`\n );\n\n // If already idle, update now\n if (this.options.getActiveConversationCount() === 0) {\n await this.executeUpdate();\n return true;\n }\n\n logger.info(\n `${this.options.getActiveConversationCount()} active conversation(s). ` +\n `Update will proceed when all complete.`\n );\n return true;\n }\n\n /**\n * Called when a conversation ends. If there's a pending update and the\n * runner is now idle, triggers the update.\n */\n async onConversationEnd(): Promise<void> {\n if (this.state !== \"pending\" || !this.pendingVersion) {\n return;\n }\n\n const activeCount = this.options.getActiveConversationCount();\n if (activeCount > 0) {\n logger.debug(\n `Conversation ended, but ${activeCount} still active. ` +\n `Waiting for idle before update.`\n );\n return;\n }\n\n logger.info(\"Runner now idle, proceeding with pending update\");\n await this.executeUpdate();\n }\n\n /**\n * Executes the update by spawning a new runner process and exiting.\n */\n private async executeUpdate(): Promise<void> {\n if (!this.pendingVersion) {\n logger.error(\"executeUpdate called but no pending version\");\n return;\n }\n\n this.state = \"updating\";\n logger.info(`Installing @northflare/runner@${this.pendingVersion}...`);\n\n try {\n // Save state before restart so we don't lose lastProcessedAt, etc.\n await this.options.saveState();\n logger.debug(\"State saved before update\");\n } catch (error) {\n logger.error(\"Failed to save state before update:\", error);\n // Continue anyway - better to update than to stay on old version\n }\n\n // Build the npx command\n // Using -y to auto-confirm and specifying the exact version\n const npxCommand = \"npx\";\n const npxArgs = [\n \"-y\",\n `@northflare/runner@${this.pendingVersion}`,\n ...this.buildRestartArgs(),\n ];\n\n logger.info(`Restarting with: ${npxCommand} ${npxArgs.join(\" \")}`);\n this.state = \"restarting\";\n\n // Spawn new process detached so it survives our exit\n const child = spawn(npxCommand, npxArgs, {\n detached: true,\n stdio: \"inherit\",\n env: process.env,\n shell: true,\n });\n\n // Prevent parent from waiting for child\n child.unref();\n\n // Handle spawn errors\n child.on(\"error\", (error) => {\n logger.error(\"Failed to spawn update process:\", error);\n // Reset state so we can try again\n this.state = \"pending\";\n });\n\n // Give the new process a moment to start before we exit\n await new Promise((resolve) => setTimeout(resolve, 1000));\n\n // Exit current process\n logger.info(\"Exiting for update...\");\n process.exit(0);\n }\n\n /**\n * Builds the command-line arguments for the restarted runner.\n * Most config is passed via environment variables which are inherited.\n */\n private buildRestartArgs(): string[] {\n const args: string[] = [];\n\n // Add start command explicitly\n args.push(\"start\");\n\n // Config path if provided\n const configPath = this.options.getConfigPath();\n if (configPath) {\n args.push(\"--config\", configPath);\n }\n\n // Other options are passed via inherited env vars:\n // - NORTHFLARE_RUNNER_TOKEN\n // - NORTHFLARE_WORKSPACE_PATH\n // - NORTHFLARE_DATA_DIR\n // - NORTHFLARE_RUNNER_DEBUG\n // - NORTHFLARE_RUNNER_INACTIVITY_TIMEOUT\n // - NORTHFLARE_ORCHESTRATOR_URL\n\n return args;\n }\n}\n","/**\n * Version utilities for runner auto-update\n */\n\nimport { createRequire } from \"module\";\n\nconst require = createRequire(import.meta.url);\nconst pkg = require(\"../../package.json\");\n\nexport const RUNNER_VERSION: string = pkg.version;\n\n/**\n * Compare two semver versions.\n * Returns true if serverVersion is newer than currentVersion.\n */\nexport function isNewerVersion(serverVersion: string, currentVersion: string): boolean {\n const parse = (v: string): [number, number, number] => {\n // Handle versions like \"0.0.26\" or \"1.2.3-beta.1\"\n const match = v.match(/^(\\d+)\\.(\\d+)\\.(\\d+)/);\n if (!match) {\n return [0, 0, 0];\n }\n return [\n parseInt(match[1]!, 10),\n parseInt(match[2]!, 10),\n parseInt(match[3]!, 10),\n ];\n };\n\n const [sMajor, sMinor, sPatch] = parse(serverVersion);\n const [cMajor, cMinor, cPatch] = parse(currentVersion);\n\n if (sMajor !== cMajor) return sMajor > cMajor;\n if (sMinor !== cMinor) return sMinor > cMinor;\n return sPatch > cPatch;\n}\n","/**\n * Configuration management utilities\n */\n\nimport { RunnerConfig, EnvironmentConfig, RetryStrategy } from '../types/index.js';\nimport fs from \"fs/promises\";\nimport { existsSync } from \"fs\";\nimport path from \"path\";\nimport envPaths from \"env-paths\";\nimport os from \"os\";\nimport { createLogger } from './logger.js';\nimport { Command } from \"commander\";\nimport readline from \"readline/promises\";\nimport { stdin as input, stdout as output } from \"node:process\";\n\nconst logger = createLogger(\"ConfigManager\");\nconst ENV_PATHS_APP_NAME = resolveEnvPathsAppName();\nconst ENV_PATHS_OPTIONS = { suffix: \"\" as const };\nconst IS_DEV_APP = ENV_PATHS_APP_NAME.endsWith(\"-dev\");\n\nfunction resolveEnvPathsAppName() {\n if (process.env[\"NODE_ENV\"] === \"development\") return \"northflare-runner-dev\";\n\n try {\n // When running from workspace (e.g., pnpm exec or direct node dist/...)\n // use the dev app name so config lives under the \"-dev\" path.\n const __dirname = path.dirname(new URL(import.meta.url).pathname);\n const repoRoot = path.resolve(__dirname, \"../..\");\n if (existsSync(path.join(repoRoot, \"pnpm-workspace.yaml\"))) {\n return \"northflare-runner-dev\";\n }\n } catch {\n // ignore and fall back to prod name\n }\n\n return \"northflare-runner\";\n}\n\n// ENV_PATHS_APP_NAME/OPTIONS defined above for reuse across helpers\n\nexport class ConfigManager {\n private static DEFAULT_CONFIG: Partial<RunnerConfig> = {\n dataDir: ConfigManager.resolveDefaultDataDir(),\n heartbeatInterval: 120000, // 2 minutes\n retryStrategy: \"exponential\" as RetryStrategy,\n retryIntervalSecs: 60,\n retryDurationSecs: 900,\n orchestratorUrl: \"https://api.northflare.app\",\n };\n\n private static resolveDefaultDataDir(): string {\n try {\n const paths = envPaths(ENV_PATHS_APP_NAME, ENV_PATHS_OPTIONS);\n return paths.data;\n } catch (error) {\n logger.debug(\"Falling back to cwd-relative data directory\", error);\n // Keep dev and prod state isolated when env-paths cannot resolve\n return path.resolve(IS_DEV_APP ? \"./data/dev\" : \"./data\");\n }\n }\n\n private static getDefaultConfigPath(): string {\n try {\n const paths = envPaths(ENV_PATHS_APP_NAME, ENV_PATHS_OPTIONS);\n return path.join(paths.config, \"config.json\");\n } catch (error) {\n logger.debug(\"Falling back to repo-relative config path\", error);\n // Separate dev/prod config files even when env-paths fails\n const localDir = IS_DEV_APP ? \"./config/dev\" : \"./config\";\n return path.resolve(localDir, \"config.json\");\n }\n }\n\n /**\n * Load configuration without parsing command line arguments\n * Used when arguments have already been parsed by the CLI\n */\n static async loadConfig(\n configPath?: string,\n options?: { promptForWorkspacePath?: boolean }\n ): Promise<RunnerConfig> {\n this.validateEnvironment();\n\n let config: Partial<RunnerConfig> = { ...this.DEFAULT_CONFIG };\n const effectiveConfigPath = configPath || this.getDefaultConfigPath();\n\n const fileConfig = await this.loadConfigFile(effectiveConfigPath);\n // Runner repos are now server-owned; ignore any persisted runnerRepos in config files\n if (fileConfig && (fileConfig as any).runnerRepos) {\n delete (fileConfig as any).runnerRepos;\n }\n const migratedWorkspacePath =\n !fileConfig.workspacePath && (fileConfig as any).workspaceDir\n ? (fileConfig as any).workspaceDir\n : undefined;\n\n config = { ...config, ...fileConfig };\n\n const envConfig = this.loadFromEnvironment();\n config = { ...config, ...envConfig };\n\n // Determine the workspacePath to use after env/CLI overrides\n let workspacePath = config.workspacePath;\n const appliedMigration = !workspacePath && !!migratedWorkspacePath;\n let shouldPersistWorkspacePath = false;\n\n if (appliedMigration) {\n workspacePath = migratedWorkspacePath;\n shouldPersistWorkspacePath = true;\n }\n\n if (!workspacePath) {\n if (options?.promptForWorkspacePath) {\n workspacePath = await this.promptForWorkspacePath();\n shouldPersistWorkspacePath = true;\n } else {\n throw new Error(\n \"workspacePath is required. Provide NORTHFLARE_WORKSPACE_PATH, --workspace-path, or set it in the runner config file.\"\n );\n }\n }\n\n const normalizedWorkspacePath = this.normalizeWorkspacePath(workspacePath!);\n config.workspacePath = normalizedWorkspacePath;\n\n if (shouldPersistWorkspacePath) {\n await this.persistConfigFile(effectiveConfigPath, {\n ...fileConfig,\n ...config,\n workspacePath: normalizedWorkspacePath,\n });\n }\n\n this.validateConfig(config);\n\n return config as RunnerConfig;\n }\n\n /**\n * Parse command line arguments and load configuration\n */\n static async parseArgsAndLoadConfig(argv: string[]): Promise<RunnerConfig> {\n const program = new Command();\n\n program\n .name(\"northflare-runner\")\n .description(\n \"Northflare Runner - Executes Claude agents for task processing\"\n )\n .version(\"1.0.0\")\n .option(\"-c, --config <path>\", \"Path to configuration file\")\n .option(\n \"--retry-strategy <strategy>\",\n \"Registration retry strategy (none, interval, exponential)\",\n \"exponential\"\n )\n .option(\n \"--retry-interval-secs <seconds>\",\n \"Retry interval in seconds for interval strategy\",\n \"60\"\n )\n .option(\n \"--retry-duration-secs <seconds>\",\n \"Max retry duration in seconds for exponential strategy\",\n \"900\"\n )\n .option(\"--data-dir <path>\", \"Data directory path\")\n .option(\n \"--heartbeat-interval <ms>\",\n \"Heartbeat interval in milliseconds\",\n \"120000\"\n )\n .option(\"--workspace-path <path>\", \"Workspace directory path\");\n\n program.parse(argv);\n const options = program.opts();\n\n // Validate required environment variables\n this.validateEnvironment();\n\n // Start with defaults\n let config: Partial<RunnerConfig> = { ...this.DEFAULT_CONFIG };\n\n // Load from config file (explicit path or default) and capture legacy workspaceDir for migration\n const effectiveConfigPath = options[\"config\"] || this.getDefaultConfigPath();\n const fileConfig = await this.loadConfigFile(effectiveConfigPath);\n if (fileConfig && (fileConfig as any).runnerRepos) {\n delete (fileConfig as any).runnerRepos;\n }\n const migratedWorkspacePath =\n !fileConfig.workspacePath && (fileConfig as any).workspaceDir\n ? (fileConfig as any).workspaceDir\n : undefined;\n\n config = { ...config, ...fileConfig };\n\n // Override with environment variables\n const envConfig = this.loadFromEnvironment();\n config = { ...config, ...envConfig };\n\n // Override with CLI arguments (highest priority)\n if (options[\"retryStrategy\"]) {\n config.retryStrategy = options[\"retryStrategy\"] as RetryStrategy;\n }\n if (options[\"retryIntervalSecs\"]) {\n config.retryIntervalSecs = parseInt(options[\"retryIntervalSecs\"]);\n }\n if (options[\"retryDurationSecs\"]) {\n config.retryDurationSecs = parseInt(options[\"retryDurationSecs\"]);\n }\n if (options[\"dataDir\"]) {\n config.dataDir = options[\"dataDir\"];\n }\n if (options[\"heartbeatInterval\"]) {\n config.heartbeatInterval = parseInt(options[\"heartbeatInterval\"]);\n }\n if (options[\"workspacePath\"]) {\n config.workspacePath = options[\"workspacePath\"];\n }\n\n const appliedMigration = !config.workspacePath && !!migratedWorkspacePath;\n let shouldPersistWorkspacePath = false;\n\n if (appliedMigration) {\n config.workspacePath = migratedWorkspacePath;\n shouldPersistWorkspacePath = true;\n }\n\n if (!config.workspacePath) {\n // Mirror loadConfig behavior: prompt when missing\n const workspacePath = await this.promptForWorkspacePath();\n config.workspacePath = workspacePath;\n shouldPersistWorkspacePath = true;\n }\n\n const normalizedWorkspacePath = this.normalizeWorkspacePath(\n config.workspacePath!\n );\n config.workspacePath = normalizedWorkspacePath;\n\n if (shouldPersistWorkspacePath) {\n await this.persistConfigFile(effectiveConfigPath, {\n ...fileConfig,\n ...config,\n workspacePath: normalizedWorkspacePath,\n });\n }\n\n // Validate final configuration\n this.validateConfig(config);\n\n return config as RunnerConfig;\n }\n\n /**\n * Validate required environment variables\n */\n private static validateEnvironment(): void {\n const required = [\"NORTHFLARE_RUNNER_TOKEN\"];\n\n const missing = required.filter((key) => !process.env[key]);\n\n if (missing.length > 0) {\n throw new Error(\n `Missing required environment variables: ${missing.join(\", \")}\\n` +\n \"Please set these environment variables before starting the runner.\"\n );\n }\n }\n\n /**\n * Load configuration from environment variables\n */\n private static loadFromEnvironment(): Partial<RunnerConfig> {\n const config: Partial<RunnerConfig> = {};\n\n if (process.env[\"NORTHFLARE_ORCHESTRATOR_URL\"]) {\n config.orchestratorUrl = process.env[\"NORTHFLARE_ORCHESTRATOR_URL\"]!;\n }\n\n // Optional environment overrides\n if (process.env[\"NORTHFLARE_DATA_DIR\"]) {\n config.dataDir = process.env[\"NORTHFLARE_DATA_DIR\"];\n }\n\n if (process.env[\"NORTHFLARE_WORKSPACE_PATH\"]) {\n config.workspacePath = process.env[\"NORTHFLARE_WORKSPACE_PATH\"];\n }\n\n return config;\n }\n\n /**\n * Load configuration from file\n */\n private static async loadConfigFile(\n configPath: string\n ): Promise<Partial<RunnerConfig>> {\n try {\n const absolutePath = path.resolve(configPath);\n const content = await fs.readFile(absolutePath, \"utf-8\");\n\n // Support both JSON and YAML formats\n if (configPath.endsWith(\".json\")) {\n const config = JSON.parse(content);\n // Runner repos are now server-sourced; ignore any persisted copy\n delete (config as any).runnerRepos;\n return config;\n } else if (configPath.endsWith(\".yaml\") || configPath.endsWith(\".yml\")) {\n // For YAML support, we'd need to add a yaml parser dependency\n throw new Error(\"YAML configuration files are not yet supported\");\n } else {\n throw new Error(\"Configuration file must be .json format\");\n }\n } catch (error) {\n if ((error as any).code === \"ENOENT\") {\n logger.warn(`Configuration file not found: ${configPath}`);\n return {};\n }\n throw error;\n }\n }\n\n private static async promptForWorkspacePath(): Promise<string> {\n const suggestedBase = this.resolveDefaultDataDir();\n const defaultPath = path.join(suggestedBase, \"workspaces\");\n const rl = readline.createInterface({ input, output });\n\n try {\n // Keep prompting until an absolute path is provided (tilde is allowed)\n // to avoid silently resolving relative paths.\n while (true) {\n const answer = await rl.question(\n `Enter a local workspace directory for runner workspaces (default: ${defaultPath}): `\n );\n\n const chosen = answer.trim() === \"\" ? defaultPath : answer.trim();\n\n try {\n const normalized = this.normalizeWorkspacePath(chosen);\n await fs.mkdir(normalized, { recursive: true });\n logger.info(`Using workspace path: ${normalized}`);\n return normalized;\n } catch (error) {\n logger.error(\n (error as Error).message ||\n \"workspacePath must be an absolute path. Please try again.\"\n );\n }\n }\n } finally {\n rl.close();\n }\n }\n\n private static normalizeWorkspacePath(workspacePath: string): string {\n const trimmed = workspacePath?.trim();\n\n if (!trimmed) {\n throw new Error(\"workspacePath is required\");\n }\n\n // Expand tilde to the user's home directory without accidentally\n // discarding the home path when the remainder begins with a path separator.\n let expanded = trimmed;\n\n if (trimmed === \"~\") {\n expanded = os.homedir();\n } else if (trimmed.startsWith(\"~/\")) {\n expanded = path.join(os.homedir(), trimmed.slice(2));\n } else if (trimmed.startsWith(\"~\\\\\")) {\n expanded = path.join(os.homedir(), trimmed.slice(2));\n }\n\n if (!path.isAbsolute(expanded)) {\n throw new Error(\"workspacePath must be an absolute path\");\n }\n\n return expanded;\n }\n\n private static async persistConfigFile(\n configPath: string,\n config: any\n ): Promise<void> {\n try {\n const absolutePath = path.resolve(configPath);\n await fs.mkdir(path.dirname(absolutePath), { recursive: true });\n await this.saveConfigFile(absolutePath, config);\n } catch (error) {\n logger.error(\"Failed to persist config file\", error);\n }\n }\n\n /**\n * Validate final configuration\n */\n private static validateConfig(config: Partial<RunnerConfig>): void {\n // Note: Runner ID will be generated by server during registration\n\n if (!config.workspacePath || config.workspacePath.trim() === \"\") {\n throw new Error(\"workspacePath is required\");\n }\n\n if (!path.isAbsolute(config.workspacePath)) {\n throw new Error(\"workspacePath must be an absolute path\");\n }\n\n if (!config.orchestratorUrl) {\n throw new Error(\"orchestratorUrl is required\");\n }\n\n if (!config.dataDir) {\n throw new Error(\"dataDir is required\");\n }\n\n if (!config.heartbeatInterval || config.heartbeatInterval < 1000) {\n throw new Error(\"heartbeatInterval must be at least 1000ms\");\n }\n\n // Validate retry strategy\n const validStrategies: RetryStrategy[] = [\n \"none\",\n \"interval\",\n \"exponential\",\n ];\n if (\n !config.retryStrategy ||\n !validStrategies.includes(config.retryStrategy)\n ) {\n throw new Error(\n `retryStrategy must be one of: ${validStrategies.join(\", \")}`\n );\n }\n\n if (\n config.retryStrategy === \"interval\" &&\n (!config.retryIntervalSecs || config.retryIntervalSecs < 1)\n ) {\n throw new Error(\n \"retryIntervalSecs must be at least 1 when using interval strategy\"\n );\n }\n\n if (\n config.retryStrategy === \"exponential\" &&\n (!config.retryDurationSecs || config.retryDurationSecs < 1)\n ) {\n throw new Error(\n \"retryDurationSecs must be at least 1 when using exponential strategy\"\n );\n }\n }\n\n /**\n * Get all environment configuration\n */\n static getEnvironmentConfig(): EnvironmentConfig {\n return {\n NORTHFLARE_RUNNER_TOKEN: process.env[\"NORTHFLARE_RUNNER_TOKEN\"]!,\n NORTHFLARE_WORKSPACE_PATH: process.env[\"NORTHFLARE_WORKSPACE_PATH\"],\n NORTHFLARE_ORCHESTRATOR_URL: process.env[\"NORTHFLARE_ORCHESTRATOR_URL\"]!,\n NORTHFLARE_RUNNER_DEBUG: process.env[\"NORTHFLARE_RUNNER_DEBUG\"],\n DEBUG: process.env[\"DEBUG\"],\n };\n }\n\n /**\n * Save configuration file with updated data\n */\n static async saveConfigFile(configPath: string, config: any): Promise<void> {\n try {\n const absolutePath = path.resolve(configPath);\n await fs.mkdir(path.dirname(absolutePath), { recursive: true });\n const content = JSON.stringify(config, null, 2);\n await fs.writeFile(absolutePath, content, \"utf-8\");\n logger.info(`Updated configuration file: ${absolutePath}`);\n } catch (error) {\n logger.error(\"Failed to save configuration file\", error);\n throw error;\n }\n }\n}\n","/**\n * Utilities for parsing and formatting inactivity timeout values\n */\n\nexport type InactivityTimeoutUnit = \"seconds\" | \"minutes\" | \"hours\";\n\nexport interface ParsedInactivityTimeout {\n milliseconds: number;\n value: number;\n unit: InactivityTimeoutUnit;\n display: string;\n}\n\ntype UnitKey = \"s\" | \"m\" | \"h\";\n\ninterface UnitMetadata {\n multiplier: number;\n unit: InactivityTimeoutUnit;\n singular: string;\n plural: string;\n}\nconst UNIT_METADATA = {\n s: {\n multiplier: 1000,\n unit: \"seconds\",\n singular: \"second\",\n plural: \"seconds\",\n },\n m: {\n multiplier: 60_000,\n unit: \"minutes\",\n singular: \"minute\",\n plural: \"minutes\",\n },\n h: {\n multiplier: 3_600_000,\n unit: \"hours\",\n singular: \"hour\",\n plural: \"hours\",\n },\n} satisfies Record<UnitKey, UnitMetadata>;\n\n/**\n * Parse CLI-provided inactivity timeout values (e.g. 30s, 5m, 1h, 45)\n */\nexport function parseInactivityTimeout(\n rawValue: string\n): ParsedInactivityTimeout {\n if (!rawValue) {\n throw new Error(\"Inactivity timeout value cannot be empty\");\n }\n\n const trimmed = rawValue.trim().toLowerCase();\n const match = trimmed.match(/^(\\d+)([smh])?$/);\n\n if (!match) {\n throw new Error(\n \"Invalid inactivity timeout format. Use a number optionally suffixed with s, m, or h (e.g. 30s, 5m, 1h).\"\n );\n }\n\n const value = Number(match[1]);\n if (!Number.isFinite(value) || value <= 0) {\n throw new Error(\"Inactivity timeout must be a number greater than zero\");\n }\n\n const unitKey = (match[2] || \"s\") as UnitKey;\n const metadata = UNIT_METADATA[unitKey];\n if (!metadata) {\n throw new Error(`Unsupported inactivity timeout unit: ${unitKey}`);\n }\n const milliseconds = value * metadata.multiplier;\n const unitLabel = value === 1 ? metadata.singular : metadata.plural;\n\n return {\n milliseconds,\n value,\n unit: metadata.unit,\n display: `${value} ${unitLabel}`,\n };\n}\n\n/**\n * Best-effort formatter for a timeout expressed in milliseconds.\n */\nexport function formatInactivityTimeoutFromMs(ms: number): string {\n if (!Number.isFinite(ms) || ms <= 0) {\n return \"unknown duration\";\n }\n\n if (ms % UNIT_METADATA.h.multiplier === 0) {\n const hours = ms / UNIT_METADATA.h.multiplier;\n return `${hours} ${hours === 1 ? \"hour\" : \"hours\"}`;\n }\n\n if (ms % UNIT_METADATA.m.multiplier === 0) {\n const minutes = ms / UNIT_METADATA.m.multiplier;\n return `${minutes} ${minutes === 1 ? \"minute\" : \"minutes\"}`;\n }\n\n const seconds = Math.round(ms / 1000);\n return `${seconds} ${seconds === 1 ? \"second\" : \"seconds\"}`;\n}\n","/**\n * Main entry point for the Northflare Runner App\n */\n\nimport { RunnerApp } from './runner-sse.js';\nimport { ConfigManager } from './utils/config.js';\nimport { logger, configureFileLogging } from './utils/logger.js';\nimport { isRunnerDebugEnabled } from './utils/debug.js';\nimport {\n parseInactivityTimeout,\n formatInactivityTimeoutFromMs,\n} from './utils/inactivity-timeout.js';\nimport type { ParsedInactivityTimeout } from './utils/inactivity-timeout.js';\nimport path from \"path\";\nimport fs from \"fs/promises\";\nimport { existsSync } from \"fs\";\nimport envPaths from \"env-paths\";\n\nconst INACTIVITY_TIMEOUT_ENV_KEY = \"NORTHFLARE_RUNNER_INACTIVITY_TIMEOUT\";\nconst INACTIVITY_CHECK_INTERVAL_MS = 1000;\n\nfunction resolveEnvPathsAppName() {\n if (process.env[\"NODE_ENV\"] === \"development\") return \"northflare-runner-dev\";\n\n try {\n const __dirname = path.dirname(new URL(import.meta.url).pathname);\n const repoRoot = path.resolve(__dirname, \"../..\");\n if (existsSync(path.join(repoRoot, \"pnpm-workspace.yaml\"))) {\n return \"northflare-runner-dev\";\n }\n } catch {\n // ignore and fall back\n }\n\n return \"northflare-runner\";\n}\n\nconst ENV_PATHS_APP_NAME = resolveEnvPathsAppName();\nconst ENV_PATHS_OPTIONS = { suffix: \"\" as const };\nconst IS_DEV_APP = ENV_PATHS_APP_NAME.endsWith(\"-dev\");\nconst SHUTDOWN_TIMEOUT_MS = 10_000;\n\nlet runner: RunnerApp | null = null;\nlet isShuttingDown = false;\nlet inactivityMonitorHandle: NodeJS.Timeout | null = null;\nlet inactivityCountdownStart: number | null = null;\nlet shutdownTimeoutHandle: NodeJS.Timeout | null = null;\n\nasync function main() {\n try {\n logger.info(\"Starting Northflare Runner...\");\n const debugEnabled = isRunnerDebugEnabled();\n const inactivityEnvValue = process.env[INACTIVITY_TIMEOUT_ENV_KEY];\n let inactivitySetting: ParsedInactivityTimeout | null = null;\n\n if (inactivityEnvValue) {\n try {\n inactivitySetting = parseInactivityTimeout(inactivityEnvValue);\n logger.info(\n `Runner will terminate after ${inactivitySetting.display} with no active agent processes`\n );\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n logger.error(\n `Invalid inactivity timeout '${inactivityEnvValue}': ${errorMessage}`\n );\n process.exit(1);\n }\n }\n\n // Load configuration (args already parsed by CLI)\n let configPath = process.argv[2]; // This is set by the CLI if --config was provided\n\n // If no config path provided, check for default location\n if (!configPath) {\n try {\n const paths = envPaths(ENV_PATHS_APP_NAME, ENV_PATHS_OPTIONS);\n configPath = path.join(paths.config, \"config.json\");\n } catch (error) {\n // env-paths not available or error accessing default location\n const localDir = IS_DEV_APP ? \"./config/dev\" : \"./config\";\n configPath = path.resolve(localDir, \"config.json\");\n }\n }\n // Normalize for downstream consumers and logging\n configPath = path.resolve(configPath);\n\n if (debugEnabled) {\n logger.debug(\"Using configuration file\", {\n configPath,\n exists: existsSync(configPath),\n });\n }\n\n const config = await ConfigManager.loadConfig(configPath, {\n promptForWorkspacePath: true,\n });\n\n if (inactivitySetting) {\n config.inactivityTimeoutMs = inactivitySetting.milliseconds;\n config.inactivityTimeoutDisplay = inactivitySetting.display;\n }\n\n // Set up file logging\n const logDir = path.join(config.dataDir, \"logs\");\n await fs.mkdir(logDir, { recursive: true });\n configureFileLogging(logDir);\n\n logger.info(\"Configuration loaded\", {\n orchestratorUrl: config.orchestratorUrl,\n retryStrategy: config.retryStrategy,\n retryIntervalSecs: config.retryIntervalSecs,\n retryDurationSecs: config.retryDurationSecs,\n });\n\n // Additional debug logging\n if (debugEnabled) {\n logger.debug(\"Debug mode enabled - verbose logging active\", {\n dataDir: config.dataDir,\n heartbeatInterval: config.heartbeatInterval,\n nodeVersion: process.version,\n platform: process.platform,\n pid: process.pid,\n });\n }\n\n // Create and start runner - pass the resolved config path\n runner = new RunnerApp(config, configPath);\n await runner.start();\n\n // Set up graceful shutdown handlers\n setupShutdownHandlers();\n\n if (config.inactivityTimeoutMs) {\n const timeoutLabel =\n config.inactivityTimeoutDisplay ||\n formatInactivityTimeoutFromMs(config.inactivityTimeoutMs);\n startInactivityMonitor(config.inactivityTimeoutMs, timeoutLabel);\n }\n\n logger.info(\"Northflare Runner is running\", {\n runnerId: runner.getRunnerId() || \"pending registration\",\n });\n\n // Log additional details in debug mode\n if (debugEnabled && runner) {\n logger.debug(\"Runner started with full details\", {\n runnerId: runner.getRunnerId(),\n runnerUid: runner.getRunnerUid(),\n lastProcessedAt: runner.getLastProcessedAt()?.toISOString() || \"null\",\n isActiveRunner: runner.getIsActiveRunner(),\n uptime: process.uptime(),\n memoryUsage: process.memoryUsage(),\n });\n }\n } catch (error) {\n logger.error(\"Failed to start runner:\", error);\n process.exit(1);\n }\n}\n\nfunction setupShutdownHandlers() {\n // Handle various shutdown signals\n const signals: NodeJS.Signals[] = [\"SIGTERM\", \"SIGINT\", \"SIGHUP\"];\n\n for (const signal of signals) {\n process.on(signal, () => {\n beginShutdown(0, `Received ${signal}, shutting down gracefully...`);\n });\n }\n\n // Handle uncaught exceptions\n process.on(\"uncaughtException\", (error) => {\n logger.error(\"Uncaught exception:\", error);\n beginShutdown(1);\n });\n\n // Handle unhandled promise rejections\n process.on(\"unhandledRejection\", (reason, promise) => {\n logger.error(\"Unhandled rejection\", { promise, reason });\n beginShutdown(1);\n });\n\n // Handle process warnings\n process.on(\"warning\", (warning) => {\n logger.warn(\"Process warning\", {\n name: warning.name,\n message: warning.message,\n stack: warning.stack,\n });\n });\n}\n\nfunction startInactivityMonitor(\n timeoutMs: number,\n displayLabel: string\n): void {\n clearInactivityMonitor();\n inactivityCountdownStart = null;\n\n inactivityMonitorHandle = setInterval(() => {\n if (!runner || isShuttingDown) {\n return;\n }\n\n const activeCount = runner.activeConversations_.size;\n\n if (activeCount > 0) {\n inactivityCountdownStart = null;\n return;\n }\n\n if (inactivityCountdownStart === null) {\n inactivityCountdownStart = Date.now();\n return;\n }\n\n const elapsed = Date.now() - inactivityCountdownStart;\n if (elapsed >= timeoutMs) {\n clearInactivityMonitor();\n beginShutdown(\n 0,\n `Inactivity timeout reached: no active agent processes for ${displayLabel}. Exiting.`\n );\n }\n }, INACTIVITY_CHECK_INTERVAL_MS);\n}\n\nfunction clearInactivityMonitor(): void {\n if (inactivityMonitorHandle) {\n clearInterval(inactivityMonitorHandle);\n inactivityMonitorHandle = null;\n }\n inactivityCountdownStart = null;\n}\n\nfunction beginShutdown(exitCode: number = 0, message?: string): void {\n if (isShuttingDown) {\n if (message) {\n logger.warn(`Shutdown already in progress. Forcing exit now (${message})`);\n } else {\n logger.warn(\"Shutdown already in progress. Forcing exit now\");\n }\n\n // If a second signal arrives while we're still stopping, exit immediately\n process.exit(exitCode || 1);\n }\n\n if (message) {\n logger.info(message);\n }\n isShuttingDown = true;\n\n // Ensure we don't hang forever waiting for async cleanup\n shutdownTimeoutHandle = setTimeout(() => {\n logger.error(\n `Shutdown did not complete within ${SHUTDOWN_TIMEOUT_MS}ms. Forcing exit.`\n );\n process.exit(1);\n }, SHUTDOWN_TIMEOUT_MS);\n shutdownTimeoutHandle.unref?.();\n void shutdown(exitCode);\n}\n\nasync function shutdown(exitCode: number = 0) {\n clearInactivityMonitor();\n\n if (runner) {\n try {\n await runner.stop();\n logger.info(\"Runner stopped successfully\");\n } catch (error) {\n logger.error(\"Error during shutdown:\", error);\n exitCode = 1;\n }\n }\n\n if (shutdownTimeoutHandle) {\n clearTimeout(shutdownTimeoutHandle);\n shutdownTimeoutHandle = null;\n }\n\n process.exit(exitCode);\n}\n\n// Note: In ESM, the bin/northflare-runner script handles calling main() directly\n\n// Export for programmatic usage\nexport { RunnerApp } from './runner-sse.js';\nexport { ConfigManager } from './utils/config.js';\nexport * from './types/index.js';\nexport { main, isShuttingDown };\n"],"mappings":"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","names":["logger","logger","path","logger","runner","fs","path","console","runner","input","agentSessionId","subtype","jwt","fs","path","simpleGit","console","runner","input","path","fs","jwt","ext","buffer","fs","fs","jwt","fs","path","simpleGit","console","buildSystemPromptWithNorthflare","runner","input","createUserMessageStream","createConversationWrapper","agentSessionId","subtype","hasImages","path","fs","simpleGit","console","runner","simpleGit","path","fs","path","fs","crypto","simpleGit","console","logger","runner","path","crypto","fs","git","simpleGit","output","repo","remotes","hasOrigin","fs","path","logger","path","fs","fs","path","require","isSubPath","path","logger","errorMessage","fs","fs","path","logger","path","fs","path","fs","existsSync","envPaths","resolveEnvPathsAppName","path","existsSync","ENV_PATHS_APP_NAME","ENV_PATHS_OPTIONS","IS_DEV_APP","envPaths","fs"]}
1
+ {"version":3,"sources":["../src/utils/logger.ts","../src/utils/debug.ts","../src/services/SSEClient.ts","../src/services/RunnerAPIClient.ts","../src/utils/status-line.ts","../src/utils/message-log.ts","../src/components/message-handler-sse.ts","../src/components/claude-sdk-manager.ts","../src/utils/console.ts","../src/utils/expand-env.ts","../src/utils/model.ts","../src/components/codex-sdk-manager.ts","../../northflare-agent-sdk/src/session-persistence.ts","../../northflare-agent-sdk/src/image-storage/memory.ts","../../northflare-agent-sdk/src/image-storage/filesystem.ts","../src/components/northflare-agent-sdk-manager.ts","../src/components/repository-manager.ts","../src/components/enhanced-repository-manager.ts","../src/utils/StateManager.ts","../src/runner-sse.ts","../src/utils/tool-response-sanitizer.ts","../src/utils/update-coordinator.ts","../src/utils/version.ts","../src/utils/config.ts","../src/utils/inactivity-timeout.ts","../src/index.ts"],"sourcesContent":["/**\n * Logger configuration using Winston\n */\n\nimport winston from \"winston\";\nimport path from \"path\";\nimport {\n DebugSubsystem,\n getDebugConfig,\n isDebugEnabledFor,\n} from './debug.js';\n\n// Custom log levels\nconst levels = {\n error: 0,\n warn: 1,\n info: 2,\n http: 3,\n verbose: 4,\n debug: 5,\n silly: 6,\n};\n\n// Log colors\nconst colors = {\n error: \"red\",\n warn: \"yellow\",\n info: \"green\",\n http: \"magenta\",\n verbose: \"cyan\",\n debug: \"blue\",\n silly: \"gray\",\n};\n\nwinston.addColors(colors);\n\n// Use a getter function so debug state is checked at call time, not module load time\nfunction isDebugEnabled(): boolean {\n return getDebugConfig().enabled;\n}\n\nconst componentSubsystemMap: Record<string, DebugSubsystem> = {\n MessageHandler: \"rpc\",\n RunnerApp: \"runner\",\n SSEClient: \"sse\",\n RunnerAPIClient: \"rpc\",\n ConfigManager: \"runner\",\n StateManager: \"state\",\n MessageFlow: \"messages\",\n};\n\nfunction resolveSubsystem(value?: string): string {\n if (value && typeof value === \"string\") {\n return value.toLowerCase();\n }\n return \"runner\";\n}\n\nconst subsystemFilter = winston.format((info) => {\n if (info.level !== \"debug\") return info;\n const subsystem = resolveSubsystem(\n (info as any).subsystem || (info as any).component\n );\n\n return isDebugEnabledFor(subsystem) ? info : false;\n});\n\n// Format for console output\nconst consoleFormat = winston.format.combine(\n subsystemFilter(),\n winston.format.colorize({ all: true }),\n winston.format.timestamp({ format: \"YYYY-MM-DD HH:mm:ss\" }),\n winston.format.printf(\n ({ timestamp, level, message, stack, component, subsystem, ...metadata }) => {\n const scopeParts = [subsystem, component].filter(Boolean);\n const scope = scopeParts.length ? ` ${scopeParts.join('/')}` : \"\";\n\n let msg = `${timestamp} [${level}]${scope}: ${message}`;\n // Only show stack traces and metadata in debug mode\n if (isDebugEnabled()) {\n if (stack) {\n msg += `\\n${stack}`;\n }\n const filteredMetadata = { ...metadata } as Record<string, unknown>;\n delete filteredMetadata[\"component\"];\n delete filteredMetadata[\"subsystem\"];\n\n if (Object.keys(filteredMetadata).length > 0) {\n msg += ` ${JSON.stringify(filteredMetadata)}`;\n }\n }\n return msg;\n }\n )\n);\n\n// Format for file output\nconst fileFormat = winston.format.combine(\n subsystemFilter(),\n winston.format.timestamp({ format: \"YYYY-MM-DD HH:mm:ss\" }),\n winston.format.errors({ stack: true }),\n winston.format.json()\n);\n\n// Create logger instance\n// Set level to debug unconditionally - the subsystemFilter will decide what to actually output\n// This avoids issues with env vars not being set at module load time\nexport const logger = winston.createLogger({\n level: \"debug\",\n levels,\n transports: [\n // Console transport set to debug - subsystemFilter handles the actual filtering\n new winston.transports.Console({\n format: consoleFormat,\n level: \"debug\",\n }),\n ],\n});\n\n// Add file transports if log directory is configured\nexport function configureFileLogging(logDir: string): void {\n // Error log file\n logger.add(\n new winston.transports.File({\n filename: path.join(logDir, \"error.log\"),\n level: \"error\",\n format: fileFormat,\n maxsize: 10 * 1024 * 1024, // 10MB\n maxFiles: 5,\n })\n );\n\n // Combined log file\n logger.add(\n new winston.transports.File({\n filename: path.join(logDir, \"combined.log\"),\n format: fileFormat,\n maxsize: 50 * 1024 * 1024, // 50MB\n maxFiles: 10,\n })\n );\n\n // Debug log file (only in debug mode)\n if (isDebugEnabled()) {\n logger.add(\n new winston.transports.File({\n filename: path.join(logDir, \"debug.log\"),\n level: \"debug\",\n format: fileFormat,\n maxsize: 100 * 1024 * 1024, // 100MB\n maxFiles: 3,\n })\n );\n }\n}\n\n// Create child logger for specific components\nexport function createLogger(\n component: string,\n subsystem?: DebugSubsystem\n): winston.Logger {\n const resolvedSubsystem =\n subsystem || componentSubsystemMap[component] || \"runner\";\n return logger.child({ component, subsystem: resolvedSubsystem });\n}\n\n// Log unhandled errors\n// Route unhandled exceptions/rejections to the console so we don't litter local\n// directories with log files when the runner boots.\nconst exceptionTransportOptions = { format: consoleFormat } as const;\n\nlogger.exceptions.handle(\n new winston.transports.Console(exceptionTransportOptions)\n);\nlogger.rejections.handle(\n new winston.transports.Console(exceptionTransportOptions)\n);\n\n// Export default logger\nexport default logger;\n","export type DebugSubsystem =\n | \"runner\"\n | \"manager\"\n | \"rpc\"\n | \"sse\"\n | \"sdk\"\n | \"repo\"\n | \"state\"\n | \"messages\";\n\ntype DebugConfig = {\n enabled: boolean;\n allowAll: boolean;\n subsystems: Set<string>;\n raw: string;\n};\n\nconst KNOWN_SUBSYSTEMS: Set<string> = new Set([\n \"runner\",\n \"manager\",\n \"rpc\",\n \"sse\",\n \"sdk\",\n \"repo\",\n \"state\",\n \"messages\",\n]);\n\nlet cachedConfig: DebugConfig | null = null;\n\nexport function getDebugConfig(): DebugConfig {\n // Only use cache if we have already parsed a non-empty debug value.\n // This allows modules that load before CLI sets env vars to re-check\n // the config later once the env vars are actually set.\n if (cachedConfig && cachedConfig.enabled) {\n return cachedConfig;\n }\n\n const explicitFlag = process.env[\"NORTHFLARE_RUNNER_DEBUG\"];\n const legacyFlag = process.env[\"DEBUG\"];\n\n const config = parseDebugValue(\n typeof explicitFlag === \"string\" ? explicitFlag : legacyFlag\n );\n\n // Only cache if debug is enabled (meaning env vars were set)\n if (config.enabled) {\n cachedConfig = config;\n }\n\n return config;\n}\n\nexport function isRunnerDebugEnabled(): boolean {\n return getDebugConfig().enabled;\n}\n\nexport function isDebugEnabledFor(\n subsystem?: DebugSubsystem | string\n): boolean {\n const config = getDebugConfig();\n if (!config.enabled) return false;\n if (config.allowAll) return true;\n if (!subsystem) return false;\n\n const normalized = normalizeSubsystem(subsystem);\n return config.subsystems.has(normalized);\n}\n\nfunction parseDebugValue(value?: string): DebugConfig {\n if (!value) {\n return {\n enabled: false,\n allowAll: false,\n subsystems: new Set(),\n raw: \"\",\n };\n }\n\n const trimmed = value.trim();\n const normalized = trimmed.toLowerCase();\n\n // Support boolean-style flags\n if (isTruthy(normalized) || normalized === \"*\" || normalized === \"all\") {\n return {\n enabled: true,\n allowAll: true,\n subsystems: new Set(),\n raw: trimmed,\n };\n }\n\n const parts = normalized\n .split(\",\")\n .map((part) => part.trim())\n .filter(Boolean)\n .map((part) => normalizeSubsystem(part));\n\n return {\n enabled: parts.length > 0,\n allowAll: false,\n subsystems: new Set(parts),\n raw: trimmed,\n };\n}\n\nfunction normalizeSubsystem(value: string): string {\n const normalized = value.trim().toLowerCase();\n\n // Common aliases\n if (normalized === \"managers\") return \"manager\";\n if (normalized === \"repos\" || normalized === \"git\") return \"repo\";\n if (normalized === \"state-manager\") return \"state\";\n if (normalized === \"message\" || normalized === \"msg\") return \"messages\";\n\n return KNOWN_SUBSYSTEMS.has(normalized) ? normalized : normalized;\n}\n\nfunction isTruthy(value: string): boolean {\n const normalized = value.trim().toLowerCase();\n return (\n normalized === \"true\" ||\n normalized === \"1\" ||\n normalized === \"yes\" ||\n normalized === \"on\"\n );\n}\n","/**\n * SSE (Server-Sent Events) Client for real-time message streaming\n * \n * Connects to the server's SSE endpoint to receive real-time runner messages\n * and handles automatic reconnection with exponential backoff.\n */\n\nimport { createLogger } from '../utils/logger.js';\nimport { RunnerConfig } from '../types/index.js';\nimport { EventSource as NodeEventSource } from 'eventsource';\n\nconst logger = createLogger('SSEClient');\n\nexport interface SSEEvent {\n id?: string;\n type: string;\n data: any;\n}\n\nexport interface SSEClientOptions {\n url: string;\n runnerId: string;\n token: string;\n onMessage: (event: SSEEvent) => void;\n onError?: (error: Error) => void;\n onConnect?: () => void;\n onDisconnect?: () => void;\n reconnectInterval?: number;\n maxReconnectInterval?: number;\n reconnectMultiplier?: number;\n maxReconnectAttempts?: number;\n /** Callback to get the current lastProcessedAt timestamp for reconnection */\n getLastProcessedAt?: () => string | undefined;\n}\n\nexport class SSEClient {\n private eventSource: EventSource | null = null;\n private reconnectTimer: NodeJS.Timeout | null = null;\n private reconnectAttempts = 0;\n private currentReconnectInterval: number;\n private isConnected = false;\n private isStopped = false;\n private lastEventId: string | undefined;\n\n constructor(private options: SSEClientOptions) {\n this.currentReconnectInterval = options.reconnectInterval || 1000;\n }\n\n /**\n * Connect to the SSE endpoint\n */\n async connect(since?: string): Promise<void> {\n if (this.eventSource) {\n logger.warn('SSE client already connected');\n return;\n }\n\n this.isStopped = false;\n\n try {\n // Build URL with query parameters\n const url = new URL(this.options.url);\n // Include token as query param as a fallback in case proxies strip headers\n url.searchParams.set('token', this.options.token);\n if (since) {\n url.searchParams.set('since', since);\n }\n\n // Sanitize token from logs\n const sanitized = new URL(url.toString());\n if (sanitized.searchParams.has('token')) {\n sanitized.searchParams.set('token', '[redacted]');\n }\n logger.info(`Connecting to SSE endpoint: ${sanitized.toString()}`);\n logger.debug(`SSE auth header set: ${this.options.token ? 'yes' : 'no'}`);\n\n // Create EventSource with authorization header (Node polyfill supports headers)\n this.eventSource = new (NodeEventSource as any)(url.toString(), {\n headers: {\n 'Authorization': `Bearer ${this.options.token}`,\n },\n withCredentials: false,\n });\n\n // Set up event listeners\n this.eventSource!.onopen = () => {\n logger.info('SSE connection established');\n this.isConnected = true;\n this.reconnectAttempts = 0;\n this.currentReconnectInterval = this.options.reconnectInterval || 1000;\n \n if (this.options.onConnect) {\n this.options.onConnect();\n }\n };\n\n this.eventSource!.onmessage = (event: MessageEvent) => {\n try {\n const parsed = JSON.parse(event.data);\n const envelope = parsed && typeof parsed === 'object' ? parsed : { data: parsed };\n const inner = (envelope && 'data' in envelope) ? (envelope as any).data : parsed;\n const sseEvent: SSEEvent = {\n id: (envelope as any).id || (event as any).lastEventId,\n type: (envelope as any).type || (event as any).type || 'message',\n data: inner,\n };\n\n // Update last event ID for reconnection\n if (sseEvent.id) {\n this.lastEventId = sseEvent.id;\n }\n\n this.options.onMessage(sseEvent);\n } catch (error) {\n logger.error('Failed to parse SSE message:', error);\n }\n };\n\n this.eventSource!.onerror = (error: Event) => {\n logger.error('SSE connection error:', error);\n this.isConnected = false;\n\n if (this.options.onError) {\n this.options.onError(new Error('SSE connection error'));\n }\n\n // Close the connection and attempt reconnection\n this.disconnect();\n \n if (!this.isStopped) {\n this.scheduleReconnect();\n }\n };\n\n // Listen for specific event types\n this.eventSource!.addEventListener('runner.message', ((event: MessageEvent) => {\n try {\n const parsed = JSON.parse(event.data);\n const envelope = parsed && typeof parsed === 'object' ? parsed : { data: parsed };\n const inner = (envelope && 'data' in envelope) ? (envelope as any).data : parsed;\n const sseEvent: SSEEvent = {\n id: (envelope as any).id || (event as any).lastEventId,\n type: 'runner.message',\n data: inner,\n };\n\n // Update last event ID\n if (sseEvent.id) {\n this.lastEventId = sseEvent.id;\n }\n\n this.options.onMessage(sseEvent);\n } catch (error) {\n logger.error('Failed to parse runner.message event:', error);\n }\n }) as any);\n\n const typedRunnerRepoHandler = (eventType: string) => ((event: MessageEvent) => {\n try {\n const parsed = JSON.parse(event.data);\n const envelope = parsed && typeof parsed === 'object' ? parsed : { data: parsed };\n const inner = (envelope && 'data' in envelope) ? (envelope as any).data : parsed;\n const sseEvent: SSEEvent = {\n id: (envelope as any).id || (event as any).lastEventId,\n type: eventType,\n data: inner,\n };\n if (sseEvent.id) {\n this.lastEventId = sseEvent.id;\n }\n this.options.onMessage(sseEvent);\n } catch (error) {\n logger.error(`Failed to parse ${eventType} event:`, error);\n }\n }) as any;\n\n this.eventSource!.addEventListener('runnerRepo.created', typedRunnerRepoHandler('runnerRepo.created'));\n this.eventSource!.addEventListener('runnerRepo.updated', typedRunnerRepoHandler('runnerRepo.updated'));\n this.eventSource!.addEventListener('runnerRepo.deleted', typedRunnerRepoHandler('runnerRepo.deleted'));\n\n // Listen for connection established event\n this.eventSource!.addEventListener('connection.established', ((event: MessageEvent) => {\n logger.debug('Received connection.established event:', event.data);\n }) as any);\n\n // Listen for error events\n this.eventSource!.addEventListener('error', ((event: MessageEvent) => {\n logger.error('Received error event from server:', event.data);\n }) as any);\n\n // Listen for shutdown events\n this.eventSource!.addEventListener('shutdown', ((event: MessageEvent) => {\n logger.warn('Server is shutting down:', event.data);\n this.stop();\n }) as any);\n\n } catch (error) {\n logger.error('Failed to connect to SSE endpoint:', error);\n \n if (this.options.onError) {\n this.options.onError(error instanceof Error ? error : new Error(String(error)));\n }\n\n // Schedule reconnection\n if (!this.isStopped) {\n this.scheduleReconnect();\n }\n }\n }\n\n /**\n * Disconnect from the SSE endpoint\n */\n disconnect(): void {\n if (this.eventSource) {\n this.eventSource.close();\n this.eventSource = null;\n this.isConnected = false;\n\n if (this.options.onDisconnect) {\n this.options.onDisconnect();\n }\n }\n\n // Clear reconnection timer\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n }\n\n /**\n * Stop the client and prevent reconnection\n */\n stop(): void {\n logger.info('Stopping SSE client');\n this.isStopped = true;\n this.disconnect();\n }\n\n /**\n * Schedule a reconnection attempt\n */\n private scheduleReconnect(): void {\n const maxAttempts = this.options.maxReconnectAttempts || Infinity;\n\n if (this.reconnectAttempts >= maxAttempts) {\n logger.error(`Max reconnection attempts (${maxAttempts}) reached. Giving up.`);\n return;\n }\n\n this.reconnectAttempts++;\n\n logger.info(`Scheduling reconnection attempt ${this.reconnectAttempts} in ${this.currentReconnectInterval}ms`);\n\n this.reconnectTimer = setTimeout(() => {\n // Use the callback to get the current lastProcessedAt timestamp if available,\n // otherwise fall back to undefined (server will use runner's DB lastProcessedAt)\n const since = this.options.getLastProcessedAt?.();\n this.connect(since);\n }, this.currentReconnectInterval);\n\n // Exponential backoff\n const multiplier = this.options.reconnectMultiplier || 2;\n const maxInterval = this.options.maxReconnectInterval || 60000;\n\n this.currentReconnectInterval = Math.min(\n this.currentReconnectInterval * multiplier,\n maxInterval\n );\n }\n\n /**\n * Check if the client is currently connected\n */\n isConnectedToServer(): boolean {\n return this.isConnected;\n }\n\n /**\n * Get the last received event ID\n */\n getLastEventId(): string | undefined {\n return this.lastEventId;\n }\n}\n","/**\n * HTTP API client for runner-specific endpoints\n *\n * Provides methods to interact with the server's runner API endpoints\n * including fetching missed messages and other runner operations.\n */\n\nimport { createLogger } from '../utils/logger.js';\nimport { RunnerConfig, RunnerMessage } from '../types/index.js';\n\nconst logger = createLogger(\"RunnerAPIClient\");\n\nexport interface FetchMissedMessagesOptions {\n since: Date | string;\n limit?: number;\n}\n\nexport class RunnerAPIClient {\n private baseUrl: string;\n private token: string;\n private runnerId: string;\n private workspacePath?: string;\n\n constructor(config: RunnerConfig) {\n this.baseUrl = config.orchestratorUrl;\n this.token = process.env[\"NORTHFLARE_RUNNER_TOKEN\"] || \"\";\n this.runnerId = config.runnerId || \"\";\n this.workspacePath = config.workspacePath;\n }\n\n /**\n * Update the runner ID after registration\n */\n setRunnerId(runnerId: string): void {\n this.runnerId = runnerId;\n }\n\n /**\n * Fetch missed messages since a given timestamp\n */\n async fetchMissedMessages(\n options: FetchMissedMessagesOptions\n ): Promise<RunnerMessage[]> {\n const since =\n options.since instanceof Date\n ? options.since.toISOString()\n : options.since;\n const limit = options.limit || 1000;\n\n logger.debug(`Fetching missed messages since ${since} (limit: ${limit})`);\n\n try {\n const url = `${this.baseUrl}/api/runner/messages/since`;\n const params = new URLSearchParams({\n since,\n limit: limit.toString(),\n });\n\n const response = await fetch(`${url}?${params}`, {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${this.token}`,\n \"X-Runner-Id\": this.runnerId,\n \"Content-Type\": \"application/json\",\n },\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(\n `Failed to fetch missed messages: ${response.status} - ${error}`\n );\n }\n\n const data = (await response.json()) as any;\n\n // Transform the raw database records to our internal RunnerMessage format\n const messages: RunnerMessage[] = data.messages.map((msg: any) => ({\n id: msg.id,\n direction: msg.direction,\n runnerId: msg.runner || msg.runnerId,\n taskId: msg.task || msg.taskId || null,\n workspaceId: msg.workspace || msg.workspaceId || null,\n conversationId: msg.conversation || msg.conversationId || null,\n conversationObjectType: msg.conversationObjectType,\n conversationObjectId: msg.conversationObjectId,\n payload: msg.payload,\n expiresAt: msg.expiresAt,\n createdAt: msg.createdAt,\n }));\n\n logger.info(`Fetched ${messages.length} missed messages`);\n return messages;\n } catch (error) {\n logger.error(\"Failed to fetch missed messages:\", error);\n throw error;\n }\n }\n\n /**\n * Send a message acknowledgment to update the high-water mark\n */\n async acknowledgeMessage(messageTimestamp: string): Promise<void> {\n logger.debug(`Acknowledging message with timestamp: ${messageTimestamp}`);\n\n try {\n const response = await fetch(`${this.baseUrl}/api/runner/messages`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.token}`,\n \"X-Runner-Id\": this.runnerId,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n method: \"message.acknowledge\",\n params: {\n runnerId: this.runnerId,\n messageTimestamp,\n },\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(\n `Failed to acknowledge message: ${response.status} - ${error}`\n );\n }\n\n logger.debug(\"Message acknowledged successfully\");\n } catch (error) {\n logger.error(\"Failed to acknowledge message:\", error);\n throw error;\n }\n }\n\n /**\n * Sync runner repositories with the orchestrator\n */\n async syncRunnerRepos(\n repos: Array<{ uuid: string; name: string; path: string; external?: boolean }>\n ): Promise<{ success: boolean; syncedCount: number }> {\n logger.debug(`Syncing ${repos.length} runner repos with orchestrator`);\n\n try {\n const response = await fetch(`${this.baseUrl}/api/runner/repos/sync`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n repos,\n workspacePath: this.workspacePath,\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(\n `Failed to sync runner repos: ${response.status} - ${error}`\n );\n }\n\n const data = (await response.json()) as any;\n logger.info(\n `Successfully synced ${data.syncedCount} runner repos with orchestrator`\n );\n\n return {\n success: data.success,\n syncedCount: data.syncedCount,\n };\n } catch (error) {\n logger.error(\"Failed to sync runner repos:\", error);\n throw error;\n }\n }\n\n /**\n * Fetch the canonical runner repos snapshot from the server\n */\n async listRunnerRepos(): Promise<{ repos: any[]; workspacePath?: string }> {\n logger.debug(\"Fetching runner repo snapshot from orchestrator\");\n const response = await fetch(`${this.baseUrl}/api/runner/repos`, {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${this.token}`,\n \"X-Runner-Id\": this.runnerId,\n \"Content-Type\": \"application/json\",\n },\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to list runner repos: ${response.status} - ${error}`);\n }\n\n const data = (await response.json()) as any;\n return {\n repos: data.repos || [],\n workspacePath: data.workspacePath,\n };\n }\n\n /**\n * Upsert a single runner repo (CLI add-repo)\n */\n async upsertRunnerRepo(repo: {\n uuid?: string;\n name: string;\n path: string;\n external?: boolean;\n }): Promise<{ repo: any }> {\n logger.debug(`Upserting runner repo ${repo.name}`);\n const response = await fetch(`${this.baseUrl}/api/runner/repos`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${this.token}`,\n \"X-Runner-Id\": this.runnerId,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(repo),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to upsert runner repo: ${response.status} - ${error}`);\n }\n\n const data = (await response.json()) as any;\n return { repo: data.repo };\n }\n}\n","/**\n * StatusLineManager - Manages persistent status line output for active agent processes\n *\n * This component maintains a single-line status output that updates every minute to show\n * the count of active agent processes. It prevents the machine from entering idle\n * state while processes are running and provides clear visual feedback without cluttering\n * the terminal with multiple log lines.\n */\nimport { isRunnerDebugEnabled } from './debug.js';\n\nexport class StatusLineManager {\n private intervalId?: NodeJS.Timeout;\n private alignTimeoutId?: NodeJS.Timeout;\n private activeCount: number = 0;\n private lastLine: string = \"\";\n private isEnabledCached: boolean | null = null;\n\n constructor() {\n // Don't cache debug state here - defer until first use\n // This allows env vars to be set after module load\n }\n\n /**\n * Check if status line is enabled (only enabled when not in debug mode)\n */\n private get isEnabled(): boolean {\n // Cache on first call, after env vars have been set\n if (this.isEnabledCached === null) {\n this.isEnabledCached = !isRunnerDebugEnabled();\n }\n return this.isEnabledCached;\n }\n\n /**\n * Updates the count of active conversations\n */\n updateActiveCount(count: number): void {\n const previousCount = this.activeCount;\n const wasZero = previousCount === 0;\n const isZero = count === 0;\n const countChanged = count !== previousCount;\n this.activeCount = count;\n\n // Start interval when transitioning from 0 to active\n if (wasZero && !isZero) {\n this.startInterval();\n }\n // Stop interval when transitioning to 0\n else if (!wasZero && isZero) {\n this.stopInterval();\n }\n\n if (countChanged) {\n this.showStatus();\n }\n }\n\n /**\n * Starts the status line interval\n */\n private startInterval(): void {\n if (!this.isEnabled || this.intervalId || this.alignTimeoutId) return;\n\n // Update every minute on the minute\n const now = new Date();\n const msUntilNextMinute = (60 - now.getSeconds()) * 1000 - now.getMilliseconds();\n\n // First timeout to align with the minute\n this.alignTimeoutId = setTimeout(() => {\n this.alignTimeoutId = undefined;\n this.showStatus();\n \n // Then set up regular interval\n this.intervalId = setInterval(() => {\n this.showStatus();\n }, 60000); // Every 60 seconds\n }, msUntilNextMinute);\n }\n\n /**\n * Stops the status line interval\n */\n private stopInterval(): void {\n if (this.alignTimeoutId) {\n clearTimeout(this.alignTimeoutId);\n this.alignTimeoutId = undefined;\n }\n if (this.intervalId) {\n clearInterval(this.intervalId);\n this.intervalId = undefined;\n }\n }\n\n /**\n * Shows the current status\n */\n private showStatus(): void {\n if (!this.isEnabled) return;\n\n const now = new Date();\n const timeStr = now.toTimeString().slice(0, 5); // HH:MM format\n\n if (this.activeCount === 0) {\n if (this.lastLine) {\n process.stdout.write('\\r' + ' '.repeat(this.lastLine.length) + '\\r');\n this.lastLine = \"\";\n }\n return;\n }\n\n let newLine: string;\n if (this.activeCount === 1) {\n newLine = `${timeStr} 1 active agent process`;\n } else {\n newLine = `${timeStr} ${this.activeCount} active agent processes`;\n }\n\n // If this is the first status line, position it\n if (!this.lastLine) {\n // Move to start of line and save cursor position\n process.stdout.write('\\r');\n } else {\n // Clear the current line\n process.stdout.write('\\r' + ' '.repeat(this.lastLine.length) + '\\r');\n }\n \n // Write the new status without newline\n process.stdout.write(newLine);\n this.lastLine = newLine;\n }\n\n /**\n * Cleans up the status line manager\n */\n dispose(): void {\n this.stopInterval();\n // Add a newline to ensure next output starts on a new line\n if (this.lastLine) {\n process.stdout.write('\\n');\n }\n }\n}\n\n// Singleton instance\nexport const statusLineManager = new StatusLineManager();\n","import { createLogger } from './logger.js';\nimport { isDebugEnabledFor } from './debug.js';\nimport type { JsonRpcMessage, RunnerMessage } from '../types/index.js';\n\n// Limit used when trimming long content fields\nexport const MESSAGE_LOG_SEGMENT = 500;\n\n// Shared logger + flag for message flow tracing\nexport const messageFlowLogger = createLogger(\"MessageFlow\", \"messages\");\nexport const messagesDebugEnabled = (): boolean => isDebugEnabledFor(\"messages\");\n\n/**\n * Trim a long string by keeping the first and last segments.\n */\nexport function trimStringForLog(value: string, segment: number = MESSAGE_LOG_SEGMENT): string {\n if (value.length <= segment * 2) return value;\n const omitted = value.length - segment * 2;\n return `${value.slice(0, segment)}...[${omitted} chars trimmed]...${value.slice(-segment)}`;\n}\n\n/**\n * Recursively clone a payload for logging, trimming long string values when requested.\n */\nexport function clonePayloadForLog<T>(payload: T, options: { trimLongStrings: boolean }): T {\n if (!options.trimLongStrings) {\n return payload;\n }\n\n const clone = (value: any): any => {\n if (typeof value === \"string\") {\n return trimStringForLog(value);\n }\n\n if (Array.isArray(value)) {\n return value.map(clone);\n }\n\n if (value && typeof value === \"object\") {\n const result: Record<string, any> = {};\n for (const [key, val] of Object.entries(value)) {\n result[key] = clone(val);\n }\n return result;\n }\n\n return value;\n };\n\n return clone(payload) as T;\n}\n\n/**\n * Prepare a concise log entry for an incoming RunnerMessage.\n */\nexport function buildIncomingMessageLog(message: RunnerMessage): Record<string, unknown> {\n return {\n direction: message.direction,\n messageId: message.id,\n method: message.payload?.method,\n taskId: message.taskId,\n conversationId:\n message.conversationId || message.payload?.params?.conversationId || null,\n workspaceId: message.workspaceId,\n payload: clonePayloadForLog(message.payload, { trimLongStrings: true }),\n };\n}\n\n/**\n * Prepare a verbose log entry for an outgoing JsonRpcMessage.\n */\nexport function buildOutgoingMessageLog(message: JsonRpcMessage): Record<string, unknown> {\n return {\n direction: \"to_orchestrator\",\n method: message.method,\n id: message.id,\n params: message.params,\n result: message.result,\n error: message.error,\n };\n}\n","/**\n * MessageHandler - Processes incoming JSONRPC messages from SSE events\n */\n\nimport { IRunnerApp } from '../types/runner-interface.js';\nimport {\n RunnerMessage,\n MethodHandler,\n ConversationContext,\n ConversationConfig,\n} from '../types/index.js';\nimport { SSEClient, SSEEvent } from '../services/SSEClient.js';\nimport { RunnerAPIClient } from '../services/RunnerAPIClient.js';\nimport { statusLineManager } from '../utils/status-line.js';\nimport { createLogger } from '../utils/logger.js';\nimport { isDebugEnabledFor } from '../utils/debug.js';\nimport {\n buildIncomingMessageLog,\n messageFlowLogger,\n messagesDebugEnabled,\n} from '../utils/message-log.js';\nimport fs from \"fs/promises\";\nimport path from \"path\";\n\nconst logger = createLogger(\"MessageHandler\", \"rpc\");\nconst sseLogger = createLogger(\"MessageHandler:SSE\", \"sse\");\n// Use getters so debug state is checked at call time, not module load time\nconst rpcDebugEnabled = () => isDebugEnabledFor(\"rpc\");\nconst sseDebugEnabled = () => isDebugEnabledFor(\"sse\");\nconst isSubPath = (base?: string, candidate?: string) => {\n if (!base || !candidate) return false;\n const normBase = path.resolve(base);\n const normCandidate = path.resolve(candidate);\n return (\n normCandidate === normBase ||\n normCandidate.startsWith(normBase.endsWith(path.sep) ? normBase : normBase + path.sep)\n );\n};\n\nexport class MessageHandler {\n private methodHandlers: Map<string, MethodHandler>;\n private runner: IRunnerApp;\n /** Map of message ID to message timestamp for deduplication */\n private processedMessages: Map<string, Date> = new Map();\n /**\n * Queue SSE events to provide backpressure.\n * Without this, async handler promises can accumulate unbounded under load.\n */\n private sseEventQueue: SSEEvent[] = [];\n private isDrainingSseQueue: boolean = false;\n private isRecoveringSse: boolean = false;\n private readonly maxSseQueueLength: number;\n private sseClient: SSEClient | null = null;\n private apiClient: RunnerAPIClient;\n private isProcessing: boolean = false;\n\n constructor(runner: IRunnerApp) {\n this.runner = runner;\n this.methodHandlers = new Map();\n this.apiClient = new RunnerAPIClient(runner.config_);\n this.maxSseQueueLength = this.readMaxSseQueueLength();\n this.registerHandlers();\n }\n\n async startProcessing(): Promise<void> {\n logger.info(\"Starting message processing with SSE\", {\n runnerId: this.runner.getRunnerId(),\n });\n\n if (this.isProcessing) {\n logger.warn(\"Message processing already started\");\n return;\n }\n\n this.isProcessing = true;\n\n // Update API client with runner ID if available\n const runnerId = this.runner.getRunnerId();\n if (runnerId) {\n this.apiClient.setRunnerId(runnerId);\n }\n\n // Catch up on missed messages first\n await this.catchUpMissedMessages();\n\n // Start SSE connection\n await this.connectSSE();\n }\n\n async stopProcessing(): Promise<void> {\n logger.info(\"Stopping message processing\");\n\n this.isProcessing = false;\n\n // Stop SSE client\n if (this.sseClient) {\n this.sseClient.stop();\n this.sseClient = null;\n }\n\n // Clear queued events and stop drain loop\n this.sseEventQueue.length = 0;\n this.isDrainingSseQueue = false;\n this.isRecoveringSse = false;\n\n // NOTE: Do NOT clear processedMessages here. Keeping the map across\n // reconnections provides dedup protection in case the high watermark\n // wasn't persisted before disconnect. The pruneProcessedMessages()\n // method handles cleanup based on the acknowledged watermark.\n }\n\n /**\n * Prune processed messages older than the given watermark.\n * Messages at or before the watermark are filtered server-side,\n * so we don't need to track them for deduplication anymore.\n */\n private pruneProcessedMessages(watermark: Date): void {\n const beforeSize = this.processedMessages.size;\n for (const [messageId, timestamp] of this.processedMessages) {\n if (timestamp <= watermark) {\n this.processedMessages.delete(messageId);\n }\n }\n const pruned = beforeSize - this.processedMessages.size;\n if (pruned > 0 && rpcDebugEnabled()) {\n logger.debug(\"Pruned processed messages\", {\n pruned,\n remaining: this.processedMessages.size,\n watermark: watermark.toISOString(),\n });\n }\n }\n\n /**\n * Catch up on missed messages since lastProcessedAt\n */\n private async catchUpMissedMessages(): Promise<void> {\n const lastProcessedAt = this.runner.getLastProcessedAt();\n\n if (!lastProcessedAt) {\n logger.debug(\"No lastProcessedAt timestamp, skipping catch-up\");\n return;\n }\n\n logger.info(\"Catching up on messages\", {\n since: lastProcessedAt.toISOString(),\n });\n\n try {\n const messages = await this.apiClient.fetchMissedMessages({\n since: lastProcessedAt,\n limit: 1000,\n });\n\n if (messages.length > 0) {\n logger.info(\"Processing missed messages\", { count: messages.length });\n\n // Process messages in order\n for (const message of messages) {\n await this.processMessage(message);\n }\n }\n } catch (error) {\n logger.error(\"Failed to catch up on missed messages:\", error);\n // Continue anyway - SSE connection might still work\n }\n }\n\n /**\n * Connect to SSE endpoint\n */\n private async connectSSE(): Promise<void> {\n const runnerId = this.runner.getRunnerId();\n if (!runnerId) {\n throw new Error(\"Cannot connect to SSE without runner ID\");\n }\n\n const token = process.env[\"NORTHFLARE_RUNNER_TOKEN\"];\n if (!token) {\n throw new Error(\"Missing NORTHFLARE_RUNNER_TOKEN\");\n }\n\n logger.info(\"Connecting to SSE endpoint\", { runnerId });\n\n this.sseClient = new SSEClient({\n url: `${this.runner.config_.orchestratorUrl}/api/runner-events`,\n runnerId,\n token,\n // Important: onMessage must be sync to avoid accumulating unawaited promises.\n // Queue events and process them sequentially to provide backpressure.\n onMessage: this.enqueueSseEvent.bind(this),\n onError: (error) => {\n logger.error(\"SSE connection error:\", error);\n },\n onConnect: () => {\n sseLogger.info(\"SSE connection established\", { runnerId });\n },\n onDisconnect: () => {\n sseLogger.info(\"SSE connection closed\", { runnerId });\n },\n reconnectInterval: 1000,\n maxReconnectInterval: 30000,\n reconnectMultiplier: 2,\n // Provide callback to get current lastProcessedAt for reconnection\n getLastProcessedAt: () => this.runner.getLastProcessedAt()?.toISOString(),\n });\n\n // Connect with lastProcessedAt for server-side filtering\n const lastProcessedAt = this.runner.getLastProcessedAt();\n await this.sseClient.connect(lastProcessedAt?.toISOString());\n }\n\n private readMaxSseQueueLength(): number {\n const raw = process.env[\"NORTHFLARE_RUNNER_SSE_QUEUE_MAX\"];\n if (!raw) return 5000;\n const parsed = Number(raw);\n if (!Number.isFinite(parsed) || parsed <= 0) return 5000;\n return Math.floor(parsed);\n }\n\n private enqueueSseEvent(event: SSEEvent): void {\n if (!this.isProcessing) return;\n\n this.sseEventQueue.push(event);\n\n if (this.sseEventQueue.length > this.maxSseQueueLength) {\n // Apply backpressure by reconnecting and catching up from lastProcessedAt.\n // We intentionally clear the queue: unacknowledged messages will be\n // returned by catchUpMissedMessages() because lastProcessedAt hasn't advanced.\n sseLogger.warn(\"SSE event queue overflow; reconnecting to catch up\", {\n queued: this.sseEventQueue.length,\n max: this.maxSseQueueLength,\n lastProcessedAt: this.runner.getLastProcessedAt()?.toISOString() || \"null\",\n });\n void this.recoverSseFromBackpressure();\n return;\n }\n\n if (!this.isDrainingSseQueue) {\n void this.drainSseQueue();\n }\n }\n\n private async recoverSseFromBackpressure(): Promise<void> {\n if (this.isRecoveringSse) return;\n this.isRecoveringSse = true;\n\n try {\n // Stop current SSE connection if any\n if (this.sseClient) {\n this.sseClient.stop();\n this.sseClient = null;\n }\n\n // Clear queue to free memory immediately\n this.sseEventQueue.length = 0;\n\n // Catch up via REST, then reconnect SSE\n await this.catchUpMissedMessages();\n if (this.isProcessing) {\n await this.connectSSE();\n }\n } catch (error) {\n sseLogger.error(\"Failed to recover SSE after backpressure\", error);\n } finally {\n this.isRecoveringSse = false;\n }\n }\n\n private async drainSseQueue(): Promise<void> {\n if (this.isDrainingSseQueue) return;\n this.isDrainingSseQueue = true;\n\n try {\n while (this.isProcessing && this.sseEventQueue.length > 0) {\n const next = this.sseEventQueue.shift();\n if (!next) break;\n await this.handleSSEEvent(next);\n }\n } catch (error) {\n sseLogger.error(\"SSE queue drain failed\", error);\n } finally {\n this.isDrainingSseQueue = false;\n }\n }\n\n /**\n * Handle SSE event\n */\n private async handleSSEEvent(event: SSEEvent): Promise<void> {\n if (event.type === \"runner.message\") {\n const message = event.data as RunnerMessage;\n\n if (sseDebugEnabled()) {\n sseLogger.debug(\"Received SSE event\", {\n eventId: event.id,\n type: event.type,\n messageId: message?.id,\n method: message?.payload?.method,\n createdAt: message?.createdAt,\n });\n }\n\n try {\n // Process the message\n await this.processMessage(message);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logger.error(\"Failed to process runner.message:\", msg);\n // Do not crash the runner on a single bad message\n return;\n }\n } else if (event.type === \"connection.established\") {\n sseLogger.debug(\"SSE connection established\", event.data);\n } else if (event.type === \"runnerRepo.created\" || event.type === \"runnerRepo.updated\") {\n await this.handleRunnerRepoUpsert(event.data);\n } else if (event.type === \"runnerRepo.deleted\") {\n await this.handleRunnerRepoDeleted(event.data);\n } else {\n sseLogger.debug(`Received event type: ${event.type}`, event.data);\n }\n }\n\n private async processMessage(message: RunnerMessage): Promise<void> {\n if (rpcDebugEnabled()) {\n logger.debug(\"processMessage called\", {\n messageId: message.id,\n method: message.payload?.method,\n direction: message.direction,\n createdAt: message.createdAt,\n });\n }\n\n // Check for version update signal (do this early, before any filtering)\n if (message.expectedRunnerVersion) {\n await this.runner.checkForUpdate(message.expectedRunnerVersion);\n }\n\n // Skip if already processed\n if (this.processedMessages.has(message.id)) {\n return;\n }\n\n if (messagesDebugEnabled()) {\n messageFlowLogger.debug(\n \"[incoming] orchestrator -> runner\",\n buildIncomingMessageLog(message)\n );\n }\n\n // Check if we should process this message based on ownership\n if (!this.shouldProcessMessage(message)) {\n return;\n }\n\n const { method, params } = message.payload;\n\n if (!method) {\n await this.sendError(message, \"Missing method in message payload\");\n return;\n }\n\n const handler = this.methodHandlers.get(method);\n\n if (!handler) {\n await this.sendError(message, `Unknown method: ${method}`);\n return;\n }\n\n if (rpcDebugEnabled()) {\n logger.debug(\"Processing message\", {\n messageId: message.id,\n method: method,\n taskId: message.taskId,\n isActionMessage: this.isActionMessage(message),\n });\n }\n\n try {\n await handler(params, message);\n await this.markProcessed(message);\n\n // Acknowledge ALL messages to update lastProcessedAt\n await this.acknowledgeMessage(message);\n\n if (rpcDebugEnabled()) {\n logger.debug(\"Message acknowledged\", {\n messageId: message.id,\n method: method,\n timestamp: message.createdAt,\n wasActionMessage: this.isActionMessage(message),\n });\n }\n } catch (error) {\n if (rpcDebugEnabled()) {\n logger.debug(\"Message processing error\", {\n messageId: message.id,\n method: method,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n await this.handleError(message, error);\n }\n }\n\n private async handleRunnerRepoUpsert(eventData: any): Promise<void> {\n const runnerExternalId = this.runner.getRunnerId();\n if (!runnerExternalId) return;\n\n const targetRunnerExternalId = eventData?.runner?.id;\n if (targetRunnerExternalId && targetRunnerExternalId !== runnerExternalId) {\n return;\n }\n\n const runnerType = eventData?.runner?.type || \"local\";\n if (runnerType !== \"local\") return;\n\n const runnerPath = eventData?.runnerPath;\n const repoName = eventData?.name;\n const repoUuid = eventData?.uuid;\n const external = eventData?.external === true;\n if (!runnerPath || !repoName || !repoUuid) return;\n\n const workspacePath = (this.runner as any).getWorkspacePath?.();\n const pathAllowed =\n external || (workspacePath ? isSubPath(workspacePath, runnerPath) : true);\n\n if (!pathAllowed) {\n logger.warn(\n `Ignoring runnerRepo upsert outside workspace from SSE: ${runnerPath}`\n );\n return;\n }\n\n try {\n await fs.mkdir(runnerPath, { recursive: true });\n logger.info(`Ensured local workspace directory exists at ${runnerPath}`);\n } catch (error) {\n logger.error(\"Failed to create workspace directory\", error);\n }\n\n const repos = Array.isArray(this.runner.config_.runnerRepos)\n ? [...(this.runner.config_.runnerRepos as any[])]\n : [];\n\n const existingIndex = repos.findIndex(\n (r: any) =>\n r.uuid === repoUuid || r.path === runnerPath || r.name === repoName\n );\n\n const updatedEntry = {\n uuid: repoUuid,\n name: repoName,\n path: runnerPath,\n external,\n };\n\n if (existingIndex >= 0) {\n repos[existingIndex] = updatedEntry;\n } else {\n repos.push(updatedEntry);\n }\n\n // Persist to runner cache if available\n if (typeof (this.runner as any).replaceRunnerRepos === \"function\") {\n await (this.runner as any).replaceRunnerRepos(repos);\n } else {\n this.runner.config_.runnerRepos = repos as any;\n }\n\n logger.info(`Updated in-memory runnerRepo ${repoName} from SSE event`);\n }\n\n private async handleRunnerRepoDeleted(eventData: any): Promise<void> {\n const runnerExternalId = this.runner.getRunnerId();\n if (!runnerExternalId) return;\n\n const targetRunnerExternalId = eventData?.runner?.id;\n if (targetRunnerExternalId && targetRunnerExternalId !== runnerExternalId) {\n return;\n }\n\n const runnerType = eventData?.runner?.type || \"local\";\n if (runnerType !== \"local\") return;\n\n const repoUuid = eventData?.uuid;\n const repoName = eventData?.name;\n if (!repoUuid && !repoName) return;\n\n const repos = Array.isArray(this.runner.config_.runnerRepos)\n ? [...(this.runner.config_.runnerRepos as any[])]\n : [];\n\n const filtered = repos.filter(\n (repo: any) =>\n (repoUuid ? repo.uuid !== repoUuid : true) &&\n (repoName ? repo.name !== repoName : true)\n );\n\n if (filtered.length === repos.length) {\n return;\n }\n\n if (typeof (this.runner as any).replaceRunnerRepos === \"function\") {\n await (this.runner as any).replaceRunnerRepos(filtered);\n } else {\n this.runner.config_.runnerRepos = filtered as any;\n }\n logger.info(\n `Removed runnerRepo ${repoName || repoUuid} from in-memory state after deletion event`\n );\n }\n\n private shouldProcessMessage(message: RunnerMessage): boolean {\n const decision = (() => {\n // Always process our own responses going to orchestrator\n if (message.direction === \"to_orchestrator\") {\n return { shouldProcess: true, reason: \"own response to orchestrator\" };\n }\n\n // Always process UID change messages BEFORE checking timestamp\n // This is critical because UID changes can update lastProcessedAt itself\n if (message.payload?.method === \"runner.uid.changed\") {\n return { shouldProcess: true, reason: \"UID change message\" };\n }\n\n // Filter by lastProcessedAt (after checking for UID change messages)\n const lastProcessedAt = this.runner.getLastProcessedAt();\n if (lastProcessedAt && message.createdAt) {\n const messageTime = new Date(message.createdAt);\n if (messageTime <= lastProcessedAt) {\n return {\n shouldProcess: false,\n reason: \"message before lastProcessedAt\",\n };\n }\n }\n\n // If we're not the active runner\n if (!this.runner.getIsActiveRunner()) {\n // Only process if it's for a pre-handoff conversation by conversationId\n const cid =\n message.conversationId || message.payload?.params?.conversationId;\n if (cid && this.runner.getPreHandoffConversations().has(cid)) {\n return {\n shouldProcess: true,\n reason: \"pre-handoff conversation (by conversationId)\",\n };\n }\n return { shouldProcess: false, reason: \"not active runner\" };\n }\n\n // We're active and message is after lastProcessedAt\n return {\n shouldProcess: true,\n reason: \"active runner, message after watermark\",\n };\n })();\n\n if (rpcDebugEnabled()) {\n logger.debug(\"Message processing decision\", {\n messageId: message.id,\n method: message.payload?.method,\n shouldProcess: decision.shouldProcess,\n reason: decision.reason,\n runnerUid: this.runner.getRunnerUid(),\n isActiveRunner: this.runner.getIsActiveRunner(),\n lastProcessedAt:\n this.runner.getLastProcessedAt()?.toISOString() || \"null\",\n messageCreatedAt: message.createdAt,\n });\n }\n\n return decision.shouldProcess;\n }\n\n private isActionMessage(message: RunnerMessage): boolean {\n const actionMethods = [\n \"conversation.start\",\n \"conversation.stop\",\n \"conversation.resume\",\n \"conversation.config\",\n \"conversation.summary\",\n \"message.user\",\n ];\n return actionMethods.includes(message.payload?.method || \"\");\n }\n\n private async acknowledgeMessage(message: RunnerMessage): Promise<void> {\n const runnerId = this.runner.getRunnerId();\n if (rpcDebugEnabled()) {\n logger.debug(\"Sending message.acknowledge\", {\n runnerId,\n messageTimestamp: message.createdAt,\n messageId: message.id,\n method: message.payload?.method,\n });\n }\n\n try {\n await this.apiClient.acknowledgeMessage(message.createdAt);\n\n // Update local lastProcessedAt\n const newWatermark = new Date(message.createdAt);\n await this.runner.updateLastProcessedAt!(newWatermark);\n\n // Prune old entries from processedMessages map to prevent unbounded growth.\n // Messages at or before the watermark are filtered server-side, so we\n // don't need to track them for deduplication anymore.\n this.pruneProcessedMessages(newWatermark);\n\n if (rpcDebugEnabled()) {\n logger.debug(\"message.acknowledge sent\", {\n runnerId,\n messageId: message.id,\n });\n }\n } catch (error) {\n logger.error(\"Failed to acknowledge message:\", error);\n // Continue processing even if acknowledgment fails\n }\n }\n\n private async markProcessed(message: RunnerMessage): Promise<void> {\n // Track processed messages with their timestamp for later pruning\n const timestamp = message.createdAt ? new Date(message.createdAt) : new Date();\n this.processedMessages.set(message.id, timestamp);\n this.pruneProcessedMessagesFailsafe();\n }\n\n /**\n * Failsafe pruning to prevent unbounded growth if acknowledgements fail\n * and lastProcessedAt can't advance (so watermark-based pruning can't run).\n */\n private pruneProcessedMessagesFailsafe(): void {\n const MAX_ENTRIES = 20_000;\n const MAX_AGE_MS = 2 * 60 * 60 * 1000; // 2 hours\n\n const now = Date.now();\n const cutoff = now - MAX_AGE_MS;\n\n // Fast path: nothing to do\n if (this.processedMessages.size <= MAX_ENTRIES) {\n // Still prune by age if we can do it cheaply from the head\n const first = this.processedMessages.entries().next().value as\n | [string, Date]\n | undefined;\n if (!first) return;\n if (first[1].getTime() >= cutoff) return;\n }\n\n // Prune oldest entries by age first (Map preserves insertion order)\n while (this.processedMessages.size > 0) {\n const first = this.processedMessages.entries().next().value as\n | [string, Date]\n | undefined;\n if (!first) break;\n const [, ts] = first;\n if (ts.getTime() >= cutoff) break;\n this.processedMessages.delete(first[0]);\n }\n\n // Enforce max size (delete oldest until within bound)\n while (this.processedMessages.size > MAX_ENTRIES) {\n const firstKey = this.processedMessages.keys().next().value as\n | string\n | undefined;\n if (!firstKey) break;\n this.processedMessages.delete(firstKey);\n }\n }\n\n private async sendError(\n message: RunnerMessage,\n errorMessage: string\n ): Promise<void> {\n // Send error report with conversation object info if available\n const conversationObjectType =\n message.conversationObjectType || (message.taskId ? \"Task\" : undefined);\n const conversationObjectId = message.conversationObjectId || message.taskId;\n\n if (!conversationObjectId) {\n logger.warn(\"Cannot send error report - missing conversationObjectId\", {\n messageId: message.id,\n method: message.payload?.method,\n error: errorMessage,\n runnerId: message.runnerId,\n });\n return;\n }\n\n await this.runner.notify(\"error.report\", {\n conversationObjectType,\n conversationObjectId,\n messageId: message.id,\n errorType: \"method_error\",\n message: errorMessage,\n details: {\n originalMessage: message,\n timestamp: new Date(),\n },\n });\n }\n\n private async handleError(message: RunnerMessage, error: any): Promise<void> {\n const errorMessage = error instanceof Error ? error.message : String(error);\n const errorStack = error instanceof Error ? error.stack : undefined;\n\n // Send error report with conversation object info if available\n const conversationObjectType =\n message.conversationObjectType || (message.taskId ? \"Task\" : undefined);\n const conversationObjectId = message.conversationObjectId || message.taskId;\n\n if (!conversationObjectId) {\n logger.warn(\n \"Cannot send processing error report - missing conversationObjectId\",\n {\n messageId: message.id,\n method: message.payload?.method,\n error: errorMessage,\n stack: errorStack,\n runnerId: message.runnerId,\n }\n );\n return;\n }\n\n await this.runner.notify(\"error.report\", {\n conversationObjectType,\n conversationObjectId,\n messageId: message.id,\n errorType: \"processing_error\",\n message: errorMessage,\n details: {\n stack: errorStack,\n originalMessage: message,\n timestamp: new Date(),\n },\n });\n }\n\n private registerHandlers(): void {\n logger.info(\"Registering message handlers\");\n\n this.methodHandlers = new Map([\n [\"conversation.start\", this.handleConversationStart.bind(this)],\n [\"conversation.stop\", this.handleConversationStop.bind(this)],\n [\"conversation.resume\", this.handleConversationResume.bind(this)],\n [\"conversation.config\", this.handleConversationConfig.bind(this)],\n [\"conversation.summary\", this.handleConversationSummary.bind(this)],\n [\"message.user\", this.handleUserMessage.bind(this)],\n [\"runner.uid.changed\", this.handleUidChanged.bind(this)],\n [\"git.operation\", this.handleGitOperation.bind(this)],\n [\"git.cleanup\", this.handleGitCleanup.bind(this)],\n ]);\n }\n\n // All the handler methods remain the same as in the original file\n // Just copy them from the original message-handler.ts starting from line 386\n\n private async handleConversationStart(\n params: any,\n message: RunnerMessage\n ): Promise<void> {\n const {\n conversationObjectType = message.conversationObjectType || \"Task\",\n conversationObjectId = message.conversationObjectId ||\n params.conversation?.objectId,\n config,\n initialMessages,\n conversation,\n } = params;\n\n // Validate required parameters\n if (!config) {\n throw new Error(\"Missing required parameter: config\");\n }\n\n // Require a conversation object\n const conversationData = conversation;\n if (!conversationData) {\n throw new Error(\n \"Missing required parameter: conversation object must be provided\"\n );\n }\n\n const finalObjectType =\n conversationObjectType || conversationData.objectType;\n const finalObjectId = conversationObjectId || conversationData.objectId;\n if (!finalObjectId) {\n throw new Error(\"Missing conversationObjectId\");\n }\n\n if (rpcDebugEnabled()) {\n // Debug log the config\n logger.debug(\"conversation.start config\", {\n conversationObjectId,\n hasConfig: !!config,\n hasRepository: !!config?.repository,\n repositoryType: config?.repository?.type,\n repositoryUrl: config?.repository?.url,\n workspaceId: config?.workspaceId,\n fullConfig: JSON.stringify(config, null, 2),\n });\n\n logger.debug(\"Received conversation instructions\", {\n conversationId: conversationData.id,\n hasWorkspaceInstructions: !!conversationData.workspaceInstructions,\n workspaceInstructionsLength:\n conversationData.workspaceInstructions?.length ?? 0,\n workspaceInstructionsPreview:\n conversationData.workspaceInstructions?.slice(0, 100),\n hasGlobalInstructions: !!conversationData.globalInstructions,\n globalInstructionsLength: conversationData.globalInstructions?.length ?? 0,\n });\n }\n\n // Check if conversation is already active (prevent duplicate starts on catch-up)\n const conversationId = conversationData.id;\n if (this.runner.activeConversations_.has(conversationId)) {\n logger.info(\"Conversation already active, skipping duplicate start\", {\n conversationId,\n });\n return;\n }\n\n // Check if this conversation was recently completed (prevent restart on catch-up)\n if (this.runner.wasConversationCompleted(conversationId)) {\n logger.info(\n \"Conversation already completed recently, skipping restart\",\n { conversationId }\n );\n return;\n }\n\n const provider = this.resolveAgentProvider(conversationData, config);\n const manager = this.getManagerForProvider(provider);\n\n // Start the conversation with the provided/loaded conversation details\n // For CodexManager (openai) we pass the provider to distinguish\n if (provider === \"openai\") {\n await (manager as any).startConversation(\n finalObjectType,\n finalObjectId,\n config,\n initialMessages || [],\n conversationData,\n provider\n );\n } else {\n await manager.startConversation(\n finalObjectType,\n finalObjectId,\n config,\n initialMessages || [],\n conversationData,\n provider as any\n );\n }\n\n // Update status line\n statusLineManager.updateActiveCount(this.runner.activeConversations_.size);\n }\n\n private async handleConversationStop(\n params: any,\n message: RunnerMessage\n ): Promise<void> {\n // Require conversationId (present at message level); do not fall back to agentSessionId/taskId\n const { conversationId = message.conversationId, reason } = params;\n\n if (rpcDebugEnabled()) {\n logger.debug(\"handleConversationStop invoked\", {\n conversationId,\n messageConversationId: message.conversationId,\n agentSessionId: params?.agentSessionId,\n taskId: params?.taskId,\n params: JSON.stringify(params),\n activeConversations: this.runner.activeConversations_.size,\n conversationIds: Array.from(this.runner.activeConversations_.keys()),\n });\n }\n\n // Lookup strictly by conversationId\n let context: ConversationContext | undefined;\n let targetConversationId: string | undefined;\n if (conversationId) {\n context = this.runner.getConversationContext(conversationId);\n targetConversationId = conversationId;\n }\n\n if (rpcDebugEnabled()) {\n logger.debug(\"handleConversationStop lookup\", {\n contextFound: !!context,\n targetConversationId,\n contextTaskId: context?.taskId,\n contextAgentSessionId: context?.agentSessionId,\n });\n }\n\n // Check if we have any identifier to work with\n if (!conversationId) {\n throw new Error(\"Missing required parameter: conversationId\");\n }\n\n if (context && targetConversationId) {\n context.status = \"stopping\";\n const manager = this.getManagerForConversationContext(context);\n await manager.stopConversation(\n context.agentSessionId,\n context,\n false, // Not a runner shutdown\n reason // Pass the reason through\n );\n context.status = \"stopped\";\n this.runner.activeConversations_.delete(targetConversationId);\n\n // Update status line\n statusLineManager.updateActiveCount(\n this.runner.activeConversations_.size\n );\n } else {\n // No conversation found - this is expected as conversations may have already ended\n // or been cleaned up. Just log it and update status line.\n logger.info(\"Conversation stop requested but not found\", {\n conversationId,\n });\n\n // If we have a targetConversationId, ensure it's removed from tracking\n if (targetConversationId) {\n this.runner.activeConversations_.delete(targetConversationId);\n }\n\n statusLineManager.updateActiveCount(\n this.runner.activeConversations_.size\n );\n }\n }\n\n private async handleConversationResume(\n params: any,\n message: RunnerMessage\n ): Promise<void> {\n const {\n conversationId = message.conversationId,\n conversation: resumeConversation,\n config,\n message: resumeMessage,\n } = params;\n\n const cid = params.conversationId || conversationId;\n if (!cid) {\n throw new Error(\"Missing required parameter: conversationId\");\n }\n\n // Require conversation details\n const conversationData = resumeConversation;\n if (!conversationData) {\n throw new Error(\n \"Missing required parameter: conversation object must be provided\"\n );\n }\n\n const agentSessionId = conversationData.agentSessionId;\n if (!agentSessionId) {\n throw new Error(\"Cannot resume conversation without agentSessionId\");\n }\n\n const provider = this.resolveAgentProvider(conversationData, config);\n const manager = this.getManagerForProvider(provider);\n\n // For CodexManager (openai) we pass the provider to distinguish\n if (provider === \"openai\") {\n await (manager as any).resumeConversation(\n conversationData.objectType,\n conversationData.objectId,\n agentSessionId,\n config,\n conversationData,\n resumeMessage,\n provider\n );\n } else {\n await manager.resumeConversation(\n conversationData.objectType,\n conversationData.objectId,\n agentSessionId,\n config,\n conversationData,\n resumeMessage,\n provider as any\n );\n }\n }\n\n private async handleConversationConfig(\n params: any,\n message: RunnerMessage\n ): Promise<void> {\n const { conversationId, model, permissionsMode, config } = params;\n\n if (rpcDebugEnabled()) {\n logger.debug(\"handleConversationConfig invoked\", {\n conversationId,\n model,\n permissionsMode,\n hasConfig: !!config,\n });\n }\n\n // Find the active conversation by conversationId only\n let context: ConversationContext | undefined;\n if (conversationId) {\n context = this.runner.getConversationContext(conversationId);\n }\n\n if (!context) {\n throw new Error(\n `No active conversation found for conversationId: ${conversationId}`\n );\n }\n\n // Validate required parameters\n if (!model && !permissionsMode) {\n throw new Error(\n \"At least one of model or permissionsMode must be provided\"\n );\n }\n\n // Update the config with new values\n const newConfig = {\n ...context.config,\n ...(model && { model }),\n ...(permissionsMode && { permissionsMode }),\n ...config, // Allow full config overrides if provided\n };\n\n logger.info(\"Stopping conversation to apply new config\", {\n conversationId: context.conversationId,\n });\n\n // Stop the current conversation\n const manager = this.getManagerForConversationContext(context);\n\n await manager.stopConversation(\n context.agentSessionId,\n context,\n false // Not a runner shutdown, just updating config\n );\n\n // Remove from active conversations\n this.runner.activeConversations_.delete(context.conversationId);\n\n logger.info(\"Resuming conversation with updated config\", {\n conversationId: context.conversationId,\n });\n\n // Resume with new config\n // For CodexManager (openai) we pass the provider to distinguish\n const contextProvider = context.provider?.toLowerCase();\n if (contextProvider === \"openai\") {\n await (manager as any).resumeConversation(\n context.conversationObjectType,\n context.conversationObjectId,\n context.agentSessionId,\n newConfig,\n {\n id: context.conversationId,\n objectType: context.conversationObjectType,\n objectId: context.conversationObjectId,\n model: newConfig.model,\n globalInstructions: context.globalInstructions,\n workspaceInstructions: context.workspaceInstructions,\n permissionsMode: newConfig.permissionsMode,\n agentSessionId: context.agentSessionId,\n },\n \"<system-instructions>Configuration updated. Please continue with the new settings.</system-instructions>\",\n contextProvider as \"openai\"\n );\n } else {\n await manager.resumeConversation(\n context.conversationObjectType,\n context.conversationObjectId,\n context.agentSessionId,\n newConfig,\n {\n id: context.conversationId,\n objectType: context.conversationObjectType,\n objectId: context.conversationObjectId,\n model: newConfig.model,\n globalInstructions: context.globalInstructions,\n workspaceInstructions: context.workspaceInstructions,\n permissionsMode: newConfig.permissionsMode,\n agentSessionId: context.agentSessionId,\n },\n \"<system-instructions>Configuration updated. Please continue with the new settings.</system-instructions>\"\n );\n }\n\n // Update status line\n statusLineManager.updateActiveCount(this.runner.activeConversations_.size);\n\n logger.info(\"Conversation config updated\", {\n conversationId: context.conversationId,\n });\n }\n\n private async handleConversationSummary(\n params: any,\n _message: RunnerMessage\n ): Promise<void> {\n const { conversationId, summary } = params;\n\n if (!conversationId) {\n throw new Error(\"Missing required parameter: conversationId\");\n }\n\n // Allow null to mean \"no summary available yet\"\n if (summary != null && typeof summary !== \"string\") {\n throw new Error(\"Invalid parameter: summary must be a string or null\");\n }\n\n const normalized =\n typeof summary === \"string\" ? summary.replace(/\\s+/g, \" \").trim() : \"\";\n\n if (rpcDebugEnabled()) {\n logger.debug(\"handleConversationSummary invoked\", {\n conversationId,\n hasSummary: Boolean(normalized),\n summaryLength: normalized.length,\n });\n }\n\n this.runner.applyConversationSummary(conversationId, normalized || null);\n }\n\n private async handleUserMessage(\n params: any,\n message: RunnerMessage\n ): Promise<void> {\n const {\n conversationId,\n content,\n config,\n conversationObjectType = message.conversationObjectType || \"Task\",\n conversationObjectId = message.conversationObjectId,\n conversation,\n agentSessionId,\n } = params;\n\n // Validate required parameters\n if (!conversationId) {\n throw new Error(\"Missing required parameter: conversationId\");\n }\n\n if (!content) {\n throw new Error(\"Missing required parameter: content\");\n }\n\n let context = this.runner.getConversationContext(conversationId);\n let provider: \"openai\" | \"openrouter\" | \"claude\" | \"groq\";\n let manager;\n\n if (context) {\n provider = context.provider as typeof provider;\n if (!provider) {\n throw new Error(\n `Conversation context missing provider for conversationId ${conversationId}. Orchestrator must set providerType/agentProviderType or prefix the model when starting the conversation.`\n );\n }\n manager = this.getManagerForProvider(provider);\n } else {\n // Conversation is not active anymore (likely completed/cleaned up). We can\n // only restart it if the orchestrator provided full conversation details\n // and a resolvable provider.\n if (!conversation) {\n throw new Error(\n `No active conversation found for ${conversationId}, and no conversation details provided to restart it.`\n );\n }\n\n provider = this.resolveAgentProvider(conversation, config);\n manager = this.getManagerForProvider(provider);\n\n const targetObjectId =\n conversationObjectId ||\n conversation.conversationObjectId ||\n conversation.objectId;\n\n if (!targetObjectId) {\n throw new Error(\n `Missing conversationObjectId for ${conversationId}; cannot start conversation.`\n );\n }\n\n // Start a fresh conversation so the SDK process exists before streaming\n await (manager as any).startConversation(\n conversationObjectType,\n targetObjectId,\n config,\n [], // no initial messages here; this is a follow-up turn\n conversation,\n provider\n );\n\n context = this.runner.getConversationContext(conversationId);\n if (!context) {\n throw new Error(\n `Failed to start conversation for ${conversationId}; no context created.`\n );\n }\n }\n\n // For CodexManager (openai), pass the provider\n if (provider === \"openai\") {\n await (manager as any).sendUserMessage(\n conversationId,\n content,\n config,\n conversationObjectType,\n conversationObjectId,\n conversation,\n agentSessionId,\n provider\n );\n } else {\n await manager.sendUserMessage(\n conversationId,\n content,\n config,\n conversationObjectType,\n conversationObjectId,\n conversation,\n agentSessionId\n );\n }\n }\n\n private async handleUidChanged(\n params: any,\n _message: RunnerMessage\n ): Promise<void> {\n const { runnerUid, lastProcessedAt } = params;\n\n logger.info(\"Handling UID change notification\", {\n runnerUid,\n lastProcessedAt,\n });\n\n if (rpcDebugEnabled()) {\n logger.debug(\"UID change notification received\", {\n newUid: runnerUid,\n currentUid: this.runner.getRunnerUid(),\n newLastProcessedAt: lastProcessedAt,\n currentLastProcessedAt:\n this.runner.getLastProcessedAt()?.toISOString() || \"null\",\n wasActiveRunner: this.runner.getIsActiveRunner(),\n activeConversations: this.runner.activeConversations_.size,\n });\n }\n\n // Check if the UID matches ours FIRST, before checking timestamps\n // This ensures we activate even if we received the message during catch-up\n if (runnerUid === this.runner.getRunnerUid()) {\n // This is our UID - we're the active runner\n logger.info(\"Runner activated as primary\", {\n runnerUid,\n });\n this.runner.setIsActiveRunner(true);\n await this.runner.updateLastProcessedAt!(\n lastProcessedAt ? new Date(lastProcessedAt) : null\n );\n\n if (rpcDebugEnabled()) {\n logger.debug(\"Runner activated as primary\", {\n runnerUid: runnerUid,\n lastProcessedAt: lastProcessedAt,\n orchestratorUrl: this.runner.config_.orchestratorUrl,\n });\n }\n\n // Emit activation notification - wrap in try/catch to handle failures gracefully\n try {\n await this.runner.notify(\"runner.activate\", {\n runnerId: this.runner.getRunnerId(),\n runnerUid: runnerUid,\n });\n } catch (error) {\n logger.error(\"Failed to send activation notification\", error);\n if (rpcDebugEnabled()) {\n logger.debug(\"Activation notification failed\", {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n // Start processing messages from the lastProcessedAt point\n logger.info(\"Activation complete; setting message watermark\", {\n after: lastProcessedAt || \"beginning\",\n });\n } else {\n // Different UID - check if this is an old UID change that we should ignore\n const currentLastProcessedAt = this.runner.getLastProcessedAt();\n if (currentLastProcessedAt && lastProcessedAt) {\n const newTime = new Date(lastProcessedAt);\n if (newTime < currentLastProcessedAt) {\n logger.info(\"Ignoring old UID change\", {\n lastProcessedAt,\n currentLastProcessedAt: currentLastProcessedAt.toISOString(),\n });\n if (rpcDebugEnabled()) {\n logger.debug(\"Ignoring old UID change\", {\n newUid: runnerUid,\n newLastProcessedAt: lastProcessedAt,\n currentLastProcessedAt: currentLastProcessedAt.toISOString(),\n });\n }\n return;\n }\n }\n\n // Different UID - we're being replaced\n logger.info(\"Runner deactivated; replacement detected\", { runnerUid });\n this.runner.setIsActiveRunner(false);\n\n // Remember which conversations were active before handoff (by conversationId)\n for (const [conversationId, context] of this.runner\n .activeConversations_) {\n if (context.status === \"active\") {\n this.runner.getPreHandoffConversations().add(conversationId);\n }\n }\n\n if (rpcDebugEnabled()) {\n logger.debug(\"Runner deactivated - being replaced\", {\n newRunnerUid: runnerUid,\n ourUid: this.runner.getRunnerUid(),\n preHandoffConversations: Array.from(\n this.runner.getPreHandoffConversations()\n ),\n activeConversationsCount:\n this.runner.getPreHandoffConversations().size,\n });\n }\n\n logger.info(\"Runner replacement: completing active conversations\", {\n activeConversationCount: this.runner.getPreHandoffConversations().size,\n });\n\n // Emit deactivation notification - wrap in try/catch to handle failures gracefully\n try {\n await this.runner.notify(\"runner.deactivate\", {\n runnerId: this.runner.getRunnerId(),\n runnerUid: this.runner.getRunnerUid(),\n activeConversations: this.runner.getPreHandoffConversations().size,\n });\n } catch (error) {\n logger.error(\"Failed to send deactivation notification\", error);\n if (rpcDebugEnabled()) {\n logger.debug(\"Deactivation notification failed\", {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n }\n }\n\n private async handleGitOperation(\n params: any,\n message: RunnerMessage\n ): Promise<void> {\n const { taskId, operation, params: opParams } = params;\n\n if (!taskId || !operation) {\n throw new Error(\"Missing required parameters: taskId and operation\");\n }\n\n logger.info(\"Handling Git operation\", { operation, taskId });\n\n const repoManager = this.runner.repositoryManager_;\n\n try {\n switch (operation) {\n case \"stage\":\n await repoManager.stageAll(taskId);\n await this.sendGitStateUpdate(taskId);\n break;\n\n case \"commit\":\n if (!opParams?.message) {\n throw new Error(\"Commit message is required\");\n }\n const commitHash = await repoManager.commit(\n taskId,\n opParams.message,\n opParams.author\n );\n await this.recordGitOperation(taskId, \"commit\", \"succeeded\", {\n commitHash,\n });\n await this.sendGitStateUpdate(taskId);\n break;\n\n case \"push\":\n // TODO: Implement push operation\n logger.warn(\"Git push operation not yet implemented\", { taskId });\n break;\n\n case \"rebase\":\n if (!opParams?.targetBranch) {\n throw new Error(\"Target branch is required for rebase\");\n }\n const rebaseResult = await repoManager.rebaseTask(\n taskId,\n opParams.targetBranch\n );\n await this.recordGitOperation(\n taskId,\n \"rebase\",\n rebaseResult.success ? \"succeeded\" : \"failed\",\n rebaseResult\n );\n await this.sendGitStateUpdate(taskId);\n break;\n\n case \"merge\":\n if (!opParams?.targetBranch) {\n throw new Error(\"Target branch is required for merge\");\n }\n const mergeResult = await repoManager.mergeTask(\n taskId,\n opParams.targetBranch,\n opParams.mode\n );\n await this.recordGitOperation(\n taskId,\n \"merge\",\n mergeResult.success ? \"succeeded\" : \"failed\",\n mergeResult\n );\n await this.sendGitStateUpdate(taskId);\n break;\n\n default:\n throw new Error(`Unknown Git operation: ${operation}`);\n }\n } catch (error) {\n logger.error(`Git operation ${operation} failed`, {\n taskId,\n error,\n });\n await this.recordGitOperation(taskId, operation, \"failed\", {\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n private async handleGitCleanup(\n params: any,\n message: RunnerMessage\n ): Promise<void> {\n const { taskId, preserveBranch = false } = params;\n\n if (!taskId) {\n throw new Error(\"Missing required parameter: taskId\");\n }\n\n logger.info(\"Cleaning up Git worktree\", { taskId });\n\n const repoManager = this.runner.repositoryManager_;\n\n try {\n await repoManager.removeTaskWorktree(taskId, { preserveBranch });\n logger.info(\"Git worktree cleaned up\", { taskId, preserveBranch });\n } catch (error) {\n logger.error(`Failed to clean up worktree for task ${taskId}`, error);\n throw error;\n }\n }\n\n private async sendGitStateUpdate(taskId: string): Promise<void> {\n const repoManager = this.runner.repositoryManager_;\n const gitState = await repoManager.getTaskState(taskId);\n\n if (!gitState) {\n logger.warn(`No Git state found for task ${taskId}`);\n return;\n }\n\n // Send state update to orchestrator\n await this.runner.notify(\"git.state.update\", {\n taskId,\n state: {\n branch: gitState.branch,\n commit: gitState.lastCommit || \"\",\n isDirty: false, // TODO: Check actual dirty state\n ahead: 0, // TODO: Calculate ahead/behind\n behind: 0,\n },\n });\n }\n\n private async recordGitOperation(\n taskId: string,\n operation: string,\n status: string,\n details: any\n ): Promise<void> {\n // Send operation record to orchestrator\n await this.runner.notify(\"git.operation.record\", {\n taskId,\n operation,\n status,\n details,\n timestamp: new Date(),\n });\n }\n\n private resolveAgentProvider(\n conversation?: {\n providerType?: string;\n agentProviderType?: string;\n model?: string;\n },\n config?: ConversationConfig\n ): \"openai\" | \"openrouter\" | \"claude\" | \"groq\" {\n const model =\n conversation?.model ||\n (config as any)?.model ||\n (config as any)?.defaultModel ||\n \"\";\n const normalizedModel = model.toLowerCase();\n\n // 1) Trust explicit provider from orchestrator/config first\n const explicitProvider =\n conversation?.providerType ||\n conversation?.agentProviderType ||\n (config as any)?.providerType ||\n (config as any)?.agentProviderType;\n\n const normalizeProvider = (provider?: string | null) => {\n if (!provider || typeof provider !== \"string\") return null;\n const normalized = provider.toLowerCase();\n if (normalized === \"codex\") return \"openai\"; // codex alias for OpenAI\n if (normalized === \"openai\") return \"openai\";\n if (normalized === \"openrouter\") return \"openrouter\";\n if (normalized === \"groq\") return \"groq\";\n if (normalized === \"claude\") return \"claude\";\n return null;\n };\n\n const explicit = normalizeProvider(explicitProvider);\n if (explicit) {\n return explicit;\n }\n\n // 2) Fallback to model prefix hints (non-fragile)\n if (normalizedModel.startsWith(\"openrouter:\") || normalizedModel.startsWith(\"openrouter/\")) {\n return \"openrouter\";\n }\n if (normalizedModel.startsWith(\"groq:\") || normalizedModel.startsWith(\"groq/\")) {\n return \"groq\";\n }\n if (normalizedModel.startsWith(\"openai:\") || normalizedModel.startsWith(\"openai/\")) {\n return \"openai\";\n }\n if (normalizedModel.startsWith(\"claude:\") || normalizedModel.startsWith(\"claude/\")) {\n return \"claude\";\n }\n\n // 3) No explicit provider and no prefix – treat as configuration error\n throw new Error(\n \"Agent provider is required. Orchestrator must set providerType/agentProviderType or prefix the model (openai:/openrouter:/groq:/claude:).\"\n );\n }\n\n private getManagerForProvider(provider?: string) {\n const manager = this.resolveProviderManager(provider?.toLowerCase());\n if (manager) {\n return manager;\n }\n throw new Error(`Unknown agent provider: ${provider || \"<unset>\"}`);\n }\n\n private getManagerForConversationContext(context: ConversationContext) {\n const manager = this.resolveProviderManager(context.provider?.toLowerCase());\n if (manager) {\n return manager;\n }\n\n throw new Error(\n `Unknown or missing agent provider on conversation context: ${\n context.provider || \"<unset>\"\n }`\n );\n }\n\n private resolveProviderManager(provider?: string) {\n if (provider === \"openrouter\" || provider === \"groq\") {\n // OpenRouter now handled by Northflare Agent manager\n return this.runner.northflareAgentManager_;\n }\n if (provider === \"openai\" || provider === \"codex\") {\n return this.runner.codexManager_;\n }\n if (provider === \"claude\") {\n return this.runner.claudeManager_;\n }\n return null;\n }\n}\n","/**\n * ClaudeManager - Manages Claude conversations using SDK-native patterns\n *\n * This component handles stateful conversation lifecycle management, maintaining\n * persistent conversation instances indexed by taskId. Uses the SDK's native\n * capabilities including the builder pattern, native session management, and\n * built-in streaming instead of custom wrappers.\n *\n * Key improvements:\n * - Uses claude() builder pattern for simplified configuration\n * - Native session management with withSessionId()\n * - Direct AsyncGenerator streaming without custom wrappers\n * - SDK's onProcessComplete() for proper cleanup\n * - Simplified error handling while maintaining compatibility\n */\n\nimport { query as sdkQuery } from \"@anthropic-ai/claude-agent-sdk\";\nimport type { Conversation as ClaudeConversation } from \"@botanicastudios/claude-code-sdk-ts\";\n// Keep SDKMessage loosely typed to avoid tight coupling to SDK typings\ntype SDKMessage = any;\nimport { IRunnerApp } from '../types/runner-interface.js';\nimport { EnhancedRepositoryManager } from './enhanced-repository-manager.js';\nimport { ConversationContext, ConversationConfig, Message } from '../types/index.js';\nimport { statusLineManager } from '../utils/status-line.js';\nimport { createScopedConsole } from '../utils/console.js';\nimport { expandEnv } from '../utils/expand-env.js';\nimport { isDebugEnabledFor } from '../utils/debug.js';\nimport fs from \"fs/promises\";\nimport path from \"path\";\nimport { simpleGit } from \"simple-git\";\n\nconst console = createScopedConsole(\n isDebugEnabledFor(\"manager\") ? \"manager\" : \"sdk\"\n);\nimport jwt from \"jsonwebtoken\";\n\nexport class ClaudeManager {\n private runner: IRunnerApp;\n private repositoryManager: EnhancedRepositoryManager;\n\n constructor(\n runner: IRunnerApp,\n repositoryManager: EnhancedRepositoryManager\n ) {\n this.runner = runner;\n this.repositoryManager = repositoryManager;\n\n // Log debug mode status\n if (isDebugEnabledFor(\"sdk\")) {\n console.log(\n \"[ClaudeManager] DEBUG MODE ENABLED - Claude SDK will log verbose output\"\n );\n }\n\n // Note: MCP host configuration is passed from orchestrator\n // Runner does not define its own MCP tools\n this.setupInternalMcpServer();\n }\n\n private setupInternalMcpServer(): void {\n // Runner does not define its own MCP tools\n // All MCP tool configuration is passed from orchestrator in conversation config\n }\n\n async startConversation(\n conversationObjectType: \"Task\" | \"TaskPlan\" | \"ProjectStep\",\n conversationObjectId: string,\n config: ConversationConfig,\n initialMessages: Message[],\n conversationData?: {\n id: string;\n objectType: string;\n objectId: string;\n model: string;\n summary?: string | null;\n globalInstructions: string;\n workspaceInstructions: string;\n permissionsMode: string;\n agentSessionId: string;\n systemPrompt?: string;\n northflareSystemPrompt?: string;\n systemPromptMode?: \"append\" | \"replace\";\n }\n ): Promise<ConversationContext> {\n // Returns conversation context\n // Greenfield: conversationData.id is required as the authoritative DB conversation ID\n if (!conversationData?.id) {\n throw new Error(\n \"startConversation requires conversationData with a valid conversation.id\"\n );\n }\n // Use sessionId from config if resuming, or agentSessionId from conversationData if available\n const agentSessionId =\n config.sessionId || conversationData.agentSessionId || \"\";\n const conversationId = conversationData.id;\n const useWorktrees = config.useWorktrees !== false;\n const pendingSummary =\n this.runner.consumePendingConversationSummary(conversationId);\n const rawSummary =\n typeof conversationData.summary === \"string\"\n ? conversationData.summary\n : pendingSummary;\n const normalizedSummary =\n typeof rawSummary === \"string\"\n ? rawSummary.replace(/\\s+/g, \" \").trim()\n : null;\n\n const context: ConversationContext = {\n conversationId,\n agentSessionId, // Will be updated by onSessionId callback for new conversations\n conversationObjectType,\n conversationObjectId,\n taskId:\n conversationObjectType === \"Task\" ? conversationObjectId : undefined,\n workspaceId: config.workspaceId,\n status: \"starting\",\n config,\n startedAt: new Date(),\n lastActivityAt: new Date(),\n // Add conversation details if provided\n model: conversationData?.model || \"opus\",\n summary: normalizedSummary,\n globalInstructions: conversationData?.globalInstructions || \"\",\n workspaceInstructions: conversationData?.workspaceInstructions || \"\",\n permissionsMode: conversationData?.permissionsMode || \"all\",\n provider: \"claude\",\n metadata: {\n instructionsInjected: false,\n },\n };\n\n // Store with conversation.id as the key\n this.runner.activeConversations_.set(conversationId, context);\n console.log(`[ClaudeManager] Stored conversation context:`, {\n conversationId,\n agentSessionId: context.agentSessionId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n mapSize: this.runner.activeConversations_.size,\n allKeys: Array.from(this.runner.activeConversations_.keys()),\n });\n\n const workspaceId = config.workspaceId;\n\n // Checkout repository if specified\n let workspacePath: string;\n\n // Check if this is a local workspace by looking for runnerRepoPath in config\n if (config.runnerRepoPath) {\n // Local workspace - use the provided path directly\n workspacePath = config.runnerRepoPath;\n console.log(`Using local workspace path: ${workspacePath}`);\n\n // For task conversations, isolate the worktree/branch when the repo has a .git directory\n if (conversationObjectType === \"Task\" && workspaceId) {\n const hasGitDir = await fs\n .access(path.join(workspacePath, \".git\"))\n .then(() => true)\n .catch(() => false);\n\n if (hasGitDir && useWorktrees) {\n const repoUrl = (config.repository?.url as string) || `file://${workspacePath}`;\n const baseBranch = (config.repository?.branch as string) || \"main\";\n\n const taskHandle = await this.repositoryManager.createTaskWorktree(\n conversationObjectId,\n workspaceId,\n repoUrl,\n baseBranch,\n config.githubToken\n );\n workspacePath = taskHandle.worktreePath;\n (context as any).taskHandle = taskHandle;\n }\n }\n } else if (\n conversationObjectType === \"Task\" &&\n config.repository &&\n workspaceId &&\n useWorktrees\n ) {\n // Use task-specific worktree for all task conversations (keeps shared workspace checkout clean)\n console.log(\n `[ClaudeManager] Creating task worktree with repository config:`,\n {\n conversationObjectId,\n workspaceId,\n repository: config.repository,\n hasUrl: !!config.repository.url,\n url: config.repository.url,\n branch: config.repository.branch,\n type: config.repository.type,\n }\n );\n\n // Check if repository.url is missing\n if (!config.repository.url) {\n throw new Error(\n `Repository URL is missing in config for task ${conversationObjectId}. Repository config: ${JSON.stringify(\n config.repository\n )}`\n );\n }\n\n const taskHandle = await this.repositoryManager.createTaskWorktree(\n conversationObjectId,\n workspaceId,\n config.repository.url,\n config.repository.branch,\n config.githubToken\n );\n workspacePath = taskHandle.worktreePath;\n\n // Store task handle information in context for later use\n (context as any).taskHandle = taskHandle;\n } else if (config.repository && workspaceId) {\n // Check if it's a local repository\n if (config.repository.type === \"local\" && config.repository.localPath) {\n // Use the local path directly\n workspacePath = config.repository.localPath;\n console.log(`Using local repository path: ${workspacePath}`);\n } else {\n // Fall back to workspace-based checkout for non-task conversations\n workspacePath = await this.repositoryManager.checkoutRepository(\n workspaceId,\n config.repository.url,\n config.repository.branch,\n config.githubToken\n );\n }\n } else if (workspaceId) {\n workspacePath =\n await this.repositoryManager.getWorkspacePath(workspaceId);\n } else {\n // Default workspace path when no workspaceId is provided\n workspacePath = process.cwd();\n }\n\n // Fetch GitHub tokens from orchestrator API if we have a workspaceId\n const githubToken = workspaceId\n ? await this.fetchGithubTokens(workspaceId)\n : undefined;\n\n // Generate TOOL_TOKEN for MCP tools authentication\n let toolToken: string | undefined;\n if (config.mcpServers && Object.keys(config.mcpServers).length > 0) {\n const runnerToken = process.env[\"NORTHFLARE_RUNNER_TOKEN\"];\n const runnerUid = this.runner.getRunnerUid();\n\n if (runnerToken && runnerUid && context.conversationId) {\n // Sign JWT with runner's token\n toolToken = jwt.sign(\n {\n conversationId: context.conversationId,\n runnerUid: runnerUid,\n },\n runnerToken,\n {\n expiresIn: \"60m\", // 60 minutes expiry\n }\n );\n console.log(\n \"[ClaudeManager] Generated TOOL_TOKEN for MCP authentication\"\n );\n } else {\n console.warn(\n \"[ClaudeManager] Unable to generate TOOL_TOKEN - missing required data\"\n );\n }\n }\n\n // Simplified SDK configuration - using native query API with streamlined options\n // const cliPath = require.resolve(\"@anthropic-ai/claude-code/cli.js\");\n\n // Debug logging for executable paths\n //console.log(\"[ClaudeManager] SDK executable paths:\", {\n // cliPath,\n // cwd: workspacePath,\n //});\n\n // Simplified environment configuration\n const envVars: Record<string, string> = {\n ...(Object.fromEntries(\n Object.entries(process.env).filter(([_, value]) => value !== undefined)\n ) as Record<string, string>), // Preserve parent environment, filter out undefined values\n };\n\n if (config.anthropicApiKey) {\n envVars[\"ANTHROPIC_API_KEY\"] = config.anthropicApiKey;\n }\n\n if (config.accessToken) {\n envVars[\"CLAUDE_CODE_OAUTH_TOKEN\"] = config.accessToken;\n }\n\n if (githubToken) {\n envVars[\"GITHUB_TOKEN\"] = githubToken;\n }\n\n if (isDebugEnabledFor(\"sdk\")) {\n envVars[\"DEBUG\"] = \"1\";\n }\n\n const instructionPrefix = this.getInstructionPrefix(context);\n\n // System prompt handling (append uses preset+append; replace uses raw string)\n // Include global/workspace instructions in the system prompt so Claude sees them.\n const baseSystemPrompt =\n config.systemPrompt || (conversationData as any)?.systemPrompt;\n const northflareSystemPrompt =\n (config as any)?.northflareSystemPrompt ||\n (conversationData as any)?.northflareSystemPrompt;\n const providedSystemPrompt = [northflareSystemPrompt, instructionPrefix, baseSystemPrompt]\n .filter((p): p is string => typeof p === \"string\" && p.trim().length > 0)\n .map((p) => p.trim())\n .join(\"\\n\\n\");\n\n const systemPromptMode =\n config.systemPromptMode ||\n (conversationData as any)?.systemPromptMode ||\n // Default ProjectStep conversations to append so preset stays intact\n \"append\";\n\n let systemPromptOption: any;\n if (providedSystemPrompt) {\n if (systemPromptMode === \"replace\") {\n systemPromptOption = providedSystemPrompt;\n } else {\n systemPromptOption = {\n type: \"preset\" as const,\n preset: \"claude_code\" as const,\n append: providedSystemPrompt,\n };\n }\n }\n\n console.log(\n `[ClaudeManager] System prompt configuration for conversation ${context.conversationId}:`,\n {\n mode: systemPromptMode,\n hasProvidedSystemPrompt: Boolean(providedSystemPrompt),\n hasInstructionPrefix: Boolean(instructionPrefix),\n finalPromptType: typeof systemPromptOption,\n finalPromptLength:\n typeof systemPromptOption === \"string\"\n ? systemPromptOption.length\n : (systemPromptOption as any)?.append?.length ?? 0,\n }\n );\n\n // Tool restrictions based on permissions mode\n // \"read\" = read-only mode (no file writes, no shell)\n // \"project\" = no file writes but allows bash, no subagents (for Project conversation)\n const readOnlyTools = [\n \"Write\",\n \"Edit\",\n \"MultiEdit\",\n \"Bash\",\n \"KillBash\",\n \"NotebookEdit\",\n \"ExitPlanMode\",\n ];\n const projectModeTools = [\n \"Write\",\n \"Edit\",\n \"MultiEdit\",\n \"NotebookEdit\",\n \"ExitPlanMode\",\n \"Task\",\n ];\n const disallowedTools: string[] =\n context.permissionsMode === \"read\"\n ? readOnlyTools\n : context.permissionsMode === \"project\"\n ? projectModeTools\n : [];\n\n if (disallowedTools.length) {\n console.log(\"[ClaudeManager] Applied read-only mode tool restrictions\");\n }\n\n // Simplified MCP server configuration\n let mcpServers: Record<string, any> | undefined;\n if (config.mcpServers) {\n mcpServers = expandEnv(config.mcpServers, { TOOL_TOKEN: toolToken });\n console.log(\n \"[ClaudeManager] MCP servers configuration:\",\n JSON.stringify(mcpServers, null, 2)\n );\n }\n\n // Create input stream for user messages (simplified message queueing)\n const input = createUserMessageStream();\n\n // Launch SDK with simplified configuration\n const sdk = sdkQuery({\n prompt: input.iterable,\n options: {\n //pathToClaudeCodeExecutable: cliPath,\n cwd: workspacePath,\n env: envVars,\n model: context.model,\n permissionMode: \"bypassPermissions\", // Runner handles permissions\n resume:\n config.sessionId || conversationData?.agentSessionId || undefined,\n ...(systemPromptOption ? { systemPrompt: systemPromptOption } : {}),\n ...(disallowedTools.length ? { disallowedTools } : {}),\n ...(mcpServers ? { mcpServers } : {}),\n ...(isDebugEnabledFor(\"sdk\")\n ? {\n stderr: (data: string) => {\n try {\n console.log(`[Claude SDK] ${data}`);\n } catch {}\n },\n }\n : {}),\n },\n });\n\n // Simplified conversation wrapper - reduced complexity while maintaining interface\n const conversation = createConversationWrapper(\n sdk,\n input,\n async (hadError: boolean, error?: any) => {\n await this._handleRunCompletion(context, hadError, error);\n }\n );\n\n // Store conversation instance in context for reuse\n context.conversation = conversation as any;\n\n // Observe session id from first messages that include it\n conversation.onSessionId(async (agentSessionId: string) => {\n if (!agentSessionId) return;\n const oldSessionId = context.agentSessionId;\n if (oldSessionId !== agentSessionId) {\n context.agentSessionId = agentSessionId;\n context.status = \"active\";\n await this.runner.notify(\"agentSessionId.changed\", {\n conversationId: context.conversationId,\n conversationObjectType,\n conversationObjectId,\n oldAgentSessionId: oldSessionId,\n newAgentSessionId: agentSessionId,\n });\n }\n });\n\n // Set up streaming message handler\n const messageHandler = async (\n message: SDKMessage,\n sessionId: string | null\n ) => {\n await this.handleStreamedMessage(context, message, sessionId);\n\n // Heuristic: detect terminal system events and finalize\n try {\n if (message?.type === \"system\") {\n const m: any = message;\n const subtype = m.subtype || m?.message?.subtype || m?.event;\n const exitSignals = [\n \"exit\",\n \"exiting\",\n \"session_end\",\n \"conversation_end\",\n \"process_exit\",\n \"done\",\n \"completed\",\n ];\n if (subtype && exitSignals.includes(String(subtype))) {\n await this._handleRunCompletion(context, false);\n }\n } else if (message?.type === \"result\") {\n // Treat 'result' as an end-of-conversation signal for the SDK\n try {\n await this._handleRunCompletion(context, false);\n console.log(\n \"[ClaudeManager] Finalized conversation due to SDK 'result' message\",\n {\n conversationId: context.conversationId,\n agentSessionId: context.agentSessionId,\n }\n );\n } catch (e) {\n console.warn(\n \"[ClaudeManager] Error finalizing on 'result' message:\",\n e\n );\n }\n }\n } catch (e) {\n console.warn(\"[ClaudeManager] finalize-on-system heuristic error:\", e);\n }\n };\n\n conversation.stream(messageHandler);\n\n // Note: Error handling is done via process completion handler\n // The Claude SDK doesn't have an onError method on conversations\n\n // Send initial messages\n try {\n for (const message of initialMessages) {\n // Check if the message content contains multimodal content blocks (e.g., images, documents)\n const contentBlocks = this.normalizeToContentBlocks(message.content);\n\n if (contentBlocks && Array.isArray(contentBlocks) && contentBlocks.some(b => b.type === 'image' || b.type === 'document')) {\n // Send multimodal message with content blocks array\n // SDK supports URL images directly: { type: \"image\", source: { type: \"url\", url: \"...\" } }\n // SDK supports URL documents directly: { type: \"document\", source: { type: \"url\", url: \"...\" } }\n console.log('[ClaudeManager] Sending multimodal message with', contentBlocks.length, 'content blocks');\n if (isDebugEnabledFor(\"manager\")) {\n console.log('[ClaudeManager] Content blocks:', JSON.stringify(contentBlocks, null, 2));\n }\n (conversation as any).send(contentBlocks);\n } else {\n // Fallback to text-only message\n const initialText = this.normalizeToText(message.content);\n conversation.send({\n type: \"text\",\n text: initialText,\n });\n }\n }\n\n console.log(\n `Started conversation for ${conversationObjectType} ${conversationObjectId} in workspace ${workspacePath}`\n );\n\n // Return the conversation context directly\n return context;\n } catch (error) {\n // Handle startup errors\n await this._handleConversationError(context, error as Error);\n throw error;\n }\n }\n\n private getInstructionPrefix(context: ConversationContext): string {\n const parts: string[] = [];\n\n if (context.globalInstructions) {\n parts.push(\n `<global-instructions>\\n${context.globalInstructions}\\n</global-instructions>`\n );\n }\n\n if (context.workspaceInstructions) {\n parts.push(\n `<workspace-instructions>\\n${context.workspaceInstructions}\\n</workspace-instructions>`\n );\n }\n\n return parts.join(\"\\n\\n\");\n }\n\n private async _handleRunCompletion(\n context: ConversationContext,\n hadError: boolean,\n error?: any\n ): Promise<void> {\n if ((context as any)._finalized) return;\n\n const inFlight = (context as any)._runCompletionInFlight as\n | Promise<void>\n | undefined;\n if (inFlight) return inFlight;\n\n const promise = (async () => {\n\n const isTaskConversation = context.conversationObjectType === \"Task\";\n const stopRequested = (context as any)._stopRequested === true;\n const taskHandle = (context as any).taskHandle as any;\n const shouldRunGitFlow =\n context.config.useWorktrees !== false &&\n isTaskConversation &&\n !!taskHandle &&\n taskHandle.branch !== \"local\";\n\n if (!shouldRunGitFlow || hadError || stopRequested) {\n await this._finalizeConversation(context, hadError, error);\n return;\n }\n\n const taskId = context.conversationObjectId;\n const baseBranch =\n (context.config.repository?.branch as string | undefined) || \"main\";\n\n try {\n const taskState = await this.repositoryManager.getTaskState(taskId);\n const taskRepoInfo = await this.repositoryManager.getTaskRepoInfo(taskId);\n if (\n !taskState ||\n !taskRepoInfo ||\n !taskRepoInfo.worktreePath ||\n taskState.branch === \"local\"\n ) {\n await this._finalizeConversation(context, false);\n return;\n }\n\n const isLocalRepo = taskRepoInfo.repoKey.startsWith(\"local__\");\n const mergeWorkdir = isLocalRepo\n ? taskRepoInfo.controlPath\n : taskRepoInfo.worktreePath;\n\n // If we already have unresolved conflicts, immediately ask the agent to resolve them.\n const taskGit = simpleGit(taskRepoInfo.worktreePath);\n const initialTaskStatus = await taskGit.status();\n if (initialTaskStatus.conflicted.length > 0) {\n await this._resumeForGitConflictResolution(context, {\n kind: \"conflicts\",\n baseBranch,\n conflicts: initialTaskStatus.conflicted,\n workdir: taskRepoInfo.worktreePath,\n });\n return;\n }\n\n if (isLocalRepo && mergeWorkdir !== taskRepoInfo.worktreePath) {\n const mergeGit = simpleGit(mergeWorkdir);\n const mergeStatus = await mergeGit.status();\n if (mergeStatus.conflicted.length > 0) {\n await this._resumeForGitConflictResolution(context, {\n kind: \"conflicts\",\n baseBranch,\n conflicts: mergeStatus.conflicted,\n workdir: mergeWorkdir,\n });\n return;\n }\n }\n\n // Ensure we're on the task branch for commit/rebase operations.\n const currentBranch = (await taskGit.revparse([\"--abbrev-ref\", \"HEAD\"])).trim();\n if (currentBranch !== taskState.branch) {\n await taskGit.checkout(taskState.branch);\n }\n\n const status = await taskGit.status();\n if (!status.isClean()) {\n await this.repositoryManager.stageAll(taskId);\n try {\n const previousCommitCount = (taskState as any)?.commitCount ?? 0;\n const baseSubject =\n (context.summary ?? \"\").replace(/\\s+/g, \" \").trim() ||\n `Task ${taskId}`;\n const message =\n previousCommitCount > 0\n ? `${baseSubject} (followup #${previousCommitCount})`\n : baseSubject;\n await this.repositoryManager.commit(taskId, message);\n } catch (commitError) {\n const msg = commitError instanceof Error ? commitError.message : String(commitError);\n if (!msg.toLowerCase().includes(\"nothing to commit\")) {\n throw commitError;\n }\n }\n }\n\n const integrateResult = await this.repositoryManager.integrateTask(\n taskId,\n baseBranch,\n \"no-ff\"\n );\n if (!integrateResult.success) {\n await this._resumeForGitConflictResolution(context, {\n kind: integrateResult.phase,\n baseBranch,\n conflicts: integrateResult.conflicts ?? [],\n workdir: integrateResult.conflictWorkdir,\n error: integrateResult.error,\n });\n return;\n }\n\n // Worktree is no longer needed after a successful merge; preserve the branch\n await this.repositoryManager.removeTaskWorktree(taskId, { preserveBranch: true });\n\n const wsId = context.config.workspaceId || context.workspaceId;\n const repoUrl = context.config.repository?.url;\n if (wsId && repoUrl) {\n await this.repositoryManager.syncWorkspaceWorktree(wsId, repoUrl, baseBranch);\n }\n\n await this._finalizeConversation(context, false);\n } catch (mergeError) {\n console.error(\"[ClaudeManager] Post-task git flow failed\", mergeError);\n await this._finalizeConversation(context, true, mergeError);\n }\n })();\n\n (context as any)._runCompletionInFlight = promise.finally(() => {\n delete (context as any)._runCompletionInFlight;\n });\n return (context as any)._runCompletionInFlight;\n }\n\n private async _resumeForGitConflictResolution(\n context: ConversationContext,\n payload: {\n kind: \"conflicts\" | \"rebase\" | \"merge\";\n baseBranch: string;\n conflicts: string[];\n workdir: string;\n error?: string;\n }\n ): Promise<void> {\n const { kind, baseBranch, conflicts, workdir, error } = payload;\n\n const conflictsList = conflicts?.length\n ? `\\n\\nConflicted files:\\n${conflicts.map((f) => `- ${f}`).join(\"\\n\")}`\n : \"\";\n const workdirHint = workdir ? `\\n\\nWork directory:\\n- ${workdir}` : \"\";\n const errorHint = error ? `\\n\\nError:\\n${error}` : \"\";\n const hasConflicts = !!conflicts?.length;\n\n let instruction: string;\n if (kind === \"rebase\") {\n instruction = hasConflicts\n ? `<system-instructions>\\nA git rebase onto \\`${baseBranch}\\` produced merge conflicts.${conflictsList}${workdirHint}${errorHint}\\n\\nPlease resolve the conflicts in that directory, then run:\\n- git add -A\\n- git rebase --continue\\n\\nWhen the rebase finishes cleanly, reply briefly so I can retry the integration.\\n</system-instructions>`\n : `<system-instructions>\\nA git rebase onto \\`${baseBranch}\\` failed.${workdirHint}${errorHint}\\n\\nNo conflicted files were reported. Please run:\\n- git status\\n\\nFix the error (or complete/abort any in-progress git operation) and reply briefly so I can retry the integration.\\n</system-instructions>`;\n } else if (kind === \"merge\") {\n instruction = hasConflicts\n ? `<system-instructions>\\nA git merge into \\`${baseBranch}\\` produced merge conflicts.${conflictsList}${workdirHint}${errorHint}\\n\\nPlease resolve the conflicts in that directory, then run:\\n- git add -A\\n- git commit -m \\\"Resolve merge conflicts for ${context.conversationObjectId}\\\"\\n\\nWhen the working tree is clean, reply briefly so I can retry the integration.\\n</system-instructions>`\n : `<system-instructions>\\nA git merge into \\`${baseBranch}\\` failed.${workdirHint}${errorHint}\\n\\nNo conflicted files were reported. Please run:\\n- git status\\n\\nFix the error (or complete/abort any in-progress git operation) and reply briefly so I can retry the integration.\\n</system-instructions>`;\n } else {\n instruction = `<system-instructions>\\nGit has unresolved conflicts.${conflictsList}${workdirHint}${errorHint}\\n\\nPlease resolve the conflicts in that directory and complete the in-progress git operation (rebase or merge). When the working tree is clean, reply briefly so I can retry the integration.\\n</system-instructions>`;\n }\n\n const conversationData = {\n id: context.conversationId,\n objectType: context.conversationObjectType,\n objectId: context.conversationObjectId,\n model: context.model,\n summary: context.summary ?? null,\n globalInstructions: context.globalInstructions,\n workspaceInstructions: context.workspaceInstructions,\n permissionsMode: context.permissionsMode,\n agentSessionId: context.agentSessionId,\n };\n\n await this.resumeConversation(\n context.conversationObjectType,\n context.conversationObjectId,\n context.agentSessionId,\n context.config,\n conversationData,\n instruction\n );\n }\n\n async stopConversation(\n agentSessionId: string,\n context: ConversationContext,\n isRunnerShutdown: boolean = false,\n reason?: string\n ): Promise<void> {\n (context as any)._stopRequested = true;\n if (context && context.conversation) {\n context.status = \"stopping\";\n\n try {\n // Proactively send end notification to avoid missing it on abnormal exits\n // Use provided reason, or fall back to 'runner_shutdown' if isRunnerShutdown is true\n const finalReason =\n reason || (isRunnerShutdown ? \"runner_shutdown\" : undefined);\n (context as any)._stopReason = finalReason;\n await this._finalizeConversation(\n context,\n false,\n undefined,\n finalReason\n ).catch(() => {});\n // Mark conversation as stopped BEFORE ending to prevent race conditions\n context.status = \"stopped\";\n\n // Properly end the conversation using the SDK\n if (isClaudeConversation(context.conversation)) {\n await context.conversation.end();\n }\n } catch (error) {\n console.error(`Error ending conversation ${agentSessionId}:`, error);\n }\n\n // Clean up conversation reference\n delete context.conversation;\n }\n\n console.log(\n `Stopped conversation ${agentSessionId} for ${context.conversationObjectType} ${context.conversationObjectId}`\n );\n }\n\n async resumeConversation(\n conversationObjectType: \"Task\" | \"TaskPlan\" | \"ProjectStep\",\n conversationObjectId: string,\n agentSessionId: string,\n config: ConversationConfig,\n conversationData?: any,\n resumeMessage?: string\n ): Promise<string> {\n console.log(`[ClaudeManager] Resuming conversation ${agentSessionId}`);\n\n // Resume is handled by starting a new conversation with the existing session ID\n const context = await this.startConversation(\n conversationObjectType,\n conversationObjectId,\n { ...config, sessionId: agentSessionId },\n [], // Don't send initial messages\n conversationData\n );\n\n // After starting the conversation with the sessionId, we need to send a message\n // to actually trigger the Claude process to continue\n if (context.conversation && isClaudeConversation(context.conversation)) {\n try {\n // Use the provided resume message or default to system instruction\n const messageToSend =\n resumeMessage ||\n \"<system-instructions>Please continue</system-instructions>\";\n console.log(\n `[ClaudeManager] Sending resume message to conversation ${agentSessionId}`\n );\n context.conversation.send({\n type: \"text\",\n text: messageToSend,\n });\n } catch (error) {\n console.error(`[ClaudeManager] Error sending resume message:`, error);\n }\n } else {\n console.warn(\n \"[ClaudeManager] Resume requested but conversation instance missing or incompatible\"\n );\n }\n\n return context.agentSessionId;\n }\n\n private async _finalizeConversation(\n context: ConversationContext,\n hadError: boolean,\n error?: any,\n reason?: string\n ): Promise<void> {\n // Synchronous idempotency check - must happen before any async operations\n if ((context as any)._finalized) return;\n (context as any)._finalized = true;\n\n // Mark as completed immediately to prevent restart on catch-up\n // This is synchronous and happens before any async operations\n this.runner.markConversationCompleted(context.conversationId);\n\n // Clean up conversation from active conversations (synchronous)\n try {\n console.log(`[ClaudeManager] Removing conversation from active map:`, {\n conversationId: context.conversationId,\n agentSessionId: context.agentSessionId,\n mapSizeBefore: this.runner.activeConversations_.size,\n });\n this.runner.activeConversations_.delete(context.conversationId);\n statusLineManager.updateActiveCount(\n this.runner.activeConversations_.size\n );\n } catch {}\n\n // Now do async notification (after all sync cleanup)\n try {\n await this.runner.notify(\"conversation.end\", {\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n agentSessionId: context.agentSessionId,\n isError: hadError,\n errorMessage: error?.message,\n reason: reason,\n });\n } catch (e) {\n console.error(\"[ClaudeManager] Failed to notify conversation.end:\", e);\n }\n\n // Notify update coordinator that a conversation has ended\n // This may trigger an auto-update if one is pending and runner is now idle\n try {\n await this.runner.onConversationEnd();\n } catch (e) {\n console.error(\"[ClaudeManager] Failed to notify onConversationEnd:\", e);\n }\n }\n\n async sendUserMessage(\n conversationId: string,\n content: any,\n config?: ConversationConfig,\n conversationObjectType?: \"Task\" | \"TaskPlan\" | \"ProjectStep\",\n conversationObjectId?: string,\n conversation?: any,\n _agentSessionIdOverride?: string\n ): Promise<void> {\n console.log(`[ClaudeManager] sendUserMessage called with:`, {\n conversationId,\n conversationObjectType,\n conversationObjectId,\n hasConfig: !!config,\n hasConversation: !!conversation,\n activeConversations: this.runner.activeConversations_.size,\n });\n\n // Find by conversationId only\n let context = this.runner.getConversationContext(conversationId);\n console.log(`[ClaudeManager] Lookup by conversationId result:`, {\n found: !!context,\n conversationId: context?.conversationId,\n agentSessionId: context?.agentSessionId,\n });\n\n if (!context) {\n throw new Error(\n `No active or fetchable conversation found for ${conversationId}`\n );\n }\n\n try {\n // Send immediately when a conversation instance exists; no need to wait for \"active\"\n if (\n !context.conversation ||\n !isClaudeConversation(context.conversation)\n ) {\n throw new Error(\n `No conversation instance found for conversation ${context.conversationId}`\n );\n }\n\n // Guard: Don't send messages if conversation is stopped or stopping\n const conversationStatus = context.status as string;\n if (\n conversationStatus === \"stopped\" ||\n conversationStatus === \"stopping\"\n ) {\n console.warn(\n `Attempted to send message to stopped/stopping conversation ${context.conversationId}`,\n {\n status: context.status,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n }\n );\n return;\n }\n\n // Native message injection - SDK handles queueing and delivery\n // Check if the message content contains multimodal content blocks (e.g., images, documents)\n const contentBlocks = this.normalizeToContentBlocks(content);\n\n if (contentBlocks && Array.isArray(contentBlocks) && contentBlocks.some(b => b.type === 'image' || b.type === 'document')) {\n // Send multimodal message with content blocks array\n // SDK supports URL images directly: { type: \"image\", source: { type: \"url\", url: \"...\" } }\n // SDK supports URL documents directly: { type: \"document\", source: { type: \"url\", url: \"...\" } }\n console.log('[ClaudeManager] Sending multimodal follow-up message with', contentBlocks.length, 'content blocks');\n if (isDebugEnabledFor(\"manager\")) {\n console.log('[ClaudeManager] Content blocks:', JSON.stringify(contentBlocks, null, 2));\n }\n (context.conversation as any).send(contentBlocks);\n } else {\n // Fallback to text-only message\n const normalizedText = this.normalizeToText(content);\n\n if (isDebugEnabledFor(\"manager\")) {\n console.log(\"[ClaudeManager] Normalized follow-up content\", {\n originalType: typeof content,\n isArray: Array.isArray(content) || undefined,\n normalizedPreview:\n typeof normalizedText === \"string\"\n ? normalizedText.slice(0, 160)\n : String(normalizedText).slice(0, 160),\n });\n }\n\n context.conversation.send({\n type: \"text\",\n text: normalizedText,\n });\n }\n\n // Update last activity timestamp\n context.lastActivityAt = new Date();\n\n console.log(\n `Sent user message to conversation ${context.conversationId} (agentSessionId: ${context.agentSessionId}, status: ${context.status})`\n );\n } catch (error) {\n // Handle errors properly\n await this._handleConversationError(context, error as Error);\n throw error; // Re-throw to maintain the same behavior\n }\n }\n\n private async fetchGithubTokens(\n workspaceId: string\n ): Promise<string | undefined> {\n try {\n const response = await fetch(\n `${this.runner.config_.orchestratorUrl}/api/runner/tokens?workspaceId=${workspaceId}`,\n {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${process.env[\"NORTHFLARE_RUNNER_TOKEN\"]}`,\n },\n }\n );\n\n if (!response.ok) {\n console.error(`Failed to fetch GitHub tokens: ${response.status}`);\n return undefined;\n }\n\n const data = (await response.json()) as { githubToken?: string };\n return data.githubToken;\n } catch (error) {\n console.error(\"Error fetching GitHub tokens:\", error);\n return undefined;\n }\n }\n\n private async _handleConversationError(\n context: ConversationContext,\n error: Error\n ): Promise<void> {\n const errorType = this.classifyError(error);\n\n // Notify orchestrator\n await this.runner.notify(\"error.report\", {\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n agentSessionId: context.agentSessionId,\n errorType,\n message: error.message,\n details: {\n stack: error.stack,\n timestamp: new Date(),\n },\n });\n\n // Conversation continues on error - no automatic cleanup\n console.error(\n `Conversation error for ${context.conversationObjectType} ${context.conversationObjectId}:`,\n error\n );\n }\n\n private classifyError(error: Error): string {\n if (error.message.includes(\"process exited\")) {\n return \"process_exit\";\n } else if (error.message.includes(\"model\")) {\n return \"model_error\";\n } else if (error.message.includes(\"tool\")) {\n return \"tool_error\";\n } else if (error.message.includes(\"permission\")) {\n return \"permission_error\";\n } else if (error.message.includes(\"timeout\")) {\n return \"timeout_error\";\n }\n return \"unknown_error\";\n }\n\n /**\n * Normalize arbitrary content shapes into a plain string for the CLI\n */\n private normalizeToText(value: any): string {\n if (typeof value === \"string\") return value;\n if (value == null) return \"\";\n\n if (typeof value === \"object\") {\n // Common simple shapes\n if (typeof (value as any).text === \"string\") return (value as any).text;\n if (\n typeof (value as any).text === \"object\" &&\n (value as any).text &&\n typeof (value as any).text.text === \"string\"\n )\n return (value as any).text.text;\n if (typeof (value as any).content === \"string\")\n return (value as any).content;\n\n // Array of blocks: [{ type: 'text', text: '...' }, ...]\n if (Array.isArray(value)) {\n const texts = value\n .map((b) =>\n b && b.type === \"text\" && typeof b.text === \"string\" ? b.text : null\n )\n .filter((t): t is string => !!t);\n if (texts.length) return texts.join(\" \");\n }\n\n // Nested message shapes\n if (\n typeof (value as any).message === \"object\" &&\n (value as any).message &&\n typeof (value as any).message.text === \"string\"\n ) {\n return (value as any).message.text;\n }\n }\n\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n }\n\n /**\n * Normalize arbitrary content shapes into content blocks array for multimodal support.\n * Returns the array of content blocks if the content contains image or document blocks,\n * otherwise returns null to indicate text-only content.\n */\n private normalizeToContentBlocks(value: any): Array<{ type: string; [key: string]: any }> | null {\n // If already an array, check if it contains image or document blocks\n if (Array.isArray(value)) {\n const hasMultimodal = value.some(b => b && (b.type === 'image' || b.type === 'document'));\n if (hasMultimodal) {\n // Return the content blocks (will be converted to SDK format later)\n return value;\n }\n return null;\n }\n\n // Check if it's a wrapped content object\n if (typeof value === 'object' && value !== null) {\n // Check for nested content array\n if (Array.isArray(value.content)) {\n const hasMultimodal = value.content.some((b: any) => b && (b.type === 'image' || b.type === 'document'));\n if (hasMultimodal) {\n return value.content;\n }\n }\n }\n\n return null;\n }\n\n private async handleStreamedMessage(\n context: ConversationContext,\n message: SDKMessage,\n sessionId: string | null\n ): Promise<void> {\n /*\n * SDK tool call payload reference (observed shapes)\n *\n * 1) Assistant tool call (tool_use)\n * {\n * \"type\": \"assistant\",\n * \"message\": {\n * \"role\": \"assistant\",\n * \"content\": [\n * { \"type\": \"text\", \"text\": \"…optional text…\" },\n * { \"type\": \"tool_use\", \"id\": \"toolu_01Nbv…\", \"name\": \"TodoWrite\", \"input\": { ... } }\n * ]\n * },\n * \"session_id\": \"…\"\n * }\n *\n * 2) Tool result (often emitted as type 'user')\n * {\n * \"type\": \"user\",\n * \"message\": {\n * \"role\": \"user\",\n * \"content\": [\n * {\n * \"tool_use_id\": \"toolu_01E9R475…\",\n * \"type\": \"tool_result\",\n * \"content\": \"Todos have been modified successfully. …\"\n * }\n * ]\n * },\n * \"parent_tool_use_id\": null,\n * \"session_id\": \"…\",\n * \"uuid\": \"…\"\n * }\n *\n * Normalization (runner → server message.agent):\n * - assistant tool_use → type: 'assistant', content: [{ toolCalls: [{ id, name, arguments }] }, …]\n * - tool_result (any shape) → type: 'tool_result', subtype: 'tool_result', content:\n * [ { type: 'tool_result', subtype: 'tool_result', tool_use_id, content } ]\n */\n // Guard: Don't process messages if conversation is stopped or stopping\n const status = context.status as string;\n if (status === \"stopped\" || status === \"stopping\") {\n console.log(\n `Ignoring message for stopped/stopping conversation ${context.conversationId}`,\n {\n status: context.status,\n messageType: message.type,\n }\n );\n return;\n }\n\n try {\n // High-level receipt log\n console.log(\n `Received streamed message for ${context.conversationObjectType} ${context.conversationObjectId}`,\n {\n type: message?.type,\n }\n );\n\n // Raw SDK message diagnostics\n try {\n // Log the full raw SDK message safely (handles circular refs)\n const safeStringify = (obj: any) => {\n const seen = new WeakSet();\n return JSON.stringify(\n obj,\n (key, value) => {\n if (typeof value === \"function\") return undefined;\n if (typeof value === \"bigint\") return String(value);\n if (typeof value === \"object\" && value !== null) {\n if (seen.has(value)) return \"[Circular]\";\n seen.add(value);\n }\n return value;\n },\n 2\n );\n };\n\n console.log(\n \"[ClaudeManager] RAW SDK message FULL:\",\n safeStringify(message)\n );\n\n const summary = {\n keys: Object.keys(message || {}),\n hasMessage: !!(message as any)?.message,\n contentType: typeof (message as any)?.content,\n messageContentType: typeof (message as any)?.message?.content,\n sessionId:\n (message as any)?.session_id || (message as any)?.sessionId || null,\n };\n console.log(\"[ClaudeManager] RAW SDK message summary:\", summary);\n if ((message as any)?.content !== undefined) {\n console.log(\n \"[ClaudeManager] RAW SDK content:\",\n (message as any).content\n );\n }\n if ((message as any)?.message?.content !== undefined) {\n console.log(\n \"[ClaudeManager] RAW SDK nested content:\",\n (message as any).message.content\n );\n }\n } catch (e) {\n console.warn(\"[ClaudeManager] Failed to log raw SDK message:\", e);\n }\n\n // Build structured content based on message type\n let messageType: string = message.type;\n let subtype: string | undefined;\n let structuredContent: any = {};\n let isError = false;\n let skipSend = false;\n let metadata: any = null;\n\n // Extract parent_tool_use_id if present (for all message types)\n const msgAsAny = message as any;\n if (msgAsAny.parent_tool_use_id) {\n metadata = {\n parent_tool_use_id: msgAsAny.parent_tool_use_id,\n };\n }\n\n // Extract content based on message type\n switch (message.type) {\n case \"assistant\": {\n const assistantMsg = message as any;\n const blocks =\n assistantMsg?.message?.content || assistantMsg?.content || [];\n const textContent = Array.isArray(blocks)\n ? blocks\n .filter(\n (b: any) =>\n b && b.type === \"text\" && typeof b.text === \"string\"\n )\n .map((b: any) => b.text)\n .join(\"\")\n : \"\";\n const toolCalls = Array.isArray(blocks)\n ? blocks\n .filter((b: any) => b && b.type === \"tool_use\")\n .map((b: any) => ({\n id: b.id,\n name: b.name,\n arguments: b.input,\n }))\n : undefined;\n\n structuredContent = {\n ...(textContent ? { text: textContent } : {}),\n ...(toolCalls && toolCalls.length ? { toolCalls } : {}),\n timestamp: new Date().toISOString(),\n };\n break;\n }\n\n case \"thinking\" as any: {\n messageType = \"thinking\";\n subtype = undefined;\n const thinkingMsg = message as any;\n structuredContent = [\n {\n type: \"thinking\",\n thinking: thinkingMsg.content || \"\",\n text: thinkingMsg.content || \"\",\n timestamp: new Date().toISOString(),\n },\n ];\n break;\n }\n\n case \"tool_use\" as any: {\n // Tool call request - map to assistant\n messageType = \"assistant\";\n subtype = \"tool_use\";\n const toolUseMsg = message as any;\n structuredContent = {\n toolCalls: [\n {\n id: toolUseMsg.id,\n name: toolUseMsg.name,\n arguments: toolUseMsg.input,\n },\n ],\n timestamp: new Date().toISOString(),\n };\n break;\n }\n\n case \"tool_result\" as any: {\n // Tool execution result - normalize to v1-style tool_result blocks\n // so the server persists as messageType: tool_call_result with correct content\n messageType = \"tool_result\";\n subtype = \"tool_result\";\n const toolResultMsg = message as any;\n structuredContent = [\n {\n type: \"tool_result\",\n subtype: \"tool_result\",\n tool_use_id: toolResultMsg.tool_use_id,\n content: toolResultMsg.content, // Keep content as native (array or string)\n timestamp: new Date().toISOString(),\n },\n ];\n break;\n }\n\n case \"result\": {\n const resultMsg = message as any;\n structuredContent = {\n text: resultMsg.content || resultMsg.result || \"\",\n timestamp: new Date().toISOString(),\n };\n break;\n }\n\n case \"user\": {\n const userMsg = message as any;\n\n // Prefer nested message.content if present (SDK shape), fallback to top-level content\n const blocks =\n (userMsg && userMsg.message && userMsg.message.content) ||\n userMsg?.content ||\n [];\n\n if (Array.isArray(blocks)) {\n const hasToolResult = blocks.some(\n (b: any) => b && typeof b === \"object\" && b.type === \"tool_result\"\n );\n\n if (hasToolResult) {\n // Normalize tool_result blocks to v1-style\n messageType = \"tool_result\";\n subtype = \"tool_result\";\n structuredContent = blocks\n .filter((b: any) => b && b.type === \"tool_result\")\n .map((b: any) => ({\n type: \"tool_result\",\n subtype: \"tool_result\",\n tool_use_id: b.tool_use_id || b.toolUseId || b.id,\n content: b.content, // Keep content as native (array or string)\n }));\n } else {\n // Treat as plain text content by joining text blocks\n const textContent = blocks\n .filter(\n (b: any) =>\n b && b.type === \"text\" && typeof b.text === \"string\"\n )\n .map((b: any) => b.text)\n .join(\"\");\n structuredContent = {\n text: textContent,\n timestamp: new Date().toISOString(),\n };\n\n // Check if this is a subagent prompt (Task tool input being sent to subagent)\n // These have parent_tool_use_id but are NOT tool_result messages\n if (userMsg.parent_tool_use_id) {\n console.log(\n \"[ClaudeManager] Detected subagent prompt message (parent_tool_use_id present, no tool_result)\",\n {\n parent_tool_use_id: userMsg.parent_tool_use_id,\n }\n );\n messageType = \"assistant\"; // Change from \"user\" to \"assistant\"\n subtype = \"subagent_prompt\";\n // metadata already set above with parent_tool_use_id\n }\n }\n\n // If content array only contains empty objects, skip sending\n if (\n Array.isArray(structuredContent) &&\n structuredContent.length > 0 &&\n structuredContent.every(\n (it: any) =>\n !it || typeof it !== \"object\" || Object.keys(it).length === 0\n )\n ) {\n console.log(\n \"[ClaudeManager] Skipping empty 'user' message with only empty objects from SDK\"\n );\n skipSend = true;\n }\n } else if (typeof userMsg?.content === \"string\") {\n // Attempt to parse JSON arrays (common for tool_result payloads)\n const text = userMsg.content;\n try {\n const parsed = JSON.parse(text);\n if (Array.isArray(parsed)) {\n const hasToolResult = parsed.some(\n (item: any) =>\n item &&\n typeof item === \"object\" &&\n item.type === \"tool_result\"\n );\n if (hasToolResult) {\n messageType = \"tool_result\";\n subtype = \"tool_result\";\n structuredContent = parsed;\n } else {\n structuredContent = {\n text,\n timestamp: new Date().toISOString(),\n };\n }\n } else {\n structuredContent = {\n text,\n timestamp: new Date().toISOString(),\n };\n }\n } catch {\n // Not JSON - treat as plain text\n structuredContent = { text, timestamp: new Date().toISOString() };\n }\n } else {\n // Other object content - preserve as is\n structuredContent = userMsg?.content || {};\n }\n break;\n }\n\n case \"system\": {\n const systemMsg = message as any;\n const subtype = systemMsg.subtype || \"system\";\n const model = systemMsg.model || systemMsg?.message?.model;\n const permissionMode =\n systemMsg.permissionMode || systemMsg?.message?.permissionMode;\n const summary = [\n subtype && `[${subtype}]`,\n model && `model=${model}`,\n permissionMode && `perm=${permissionMode}`,\n ]\n .filter(Boolean)\n .join(\" \");\n structuredContent = {\n text: summary || \"\",\n timestamp: new Date().toISOString(),\n };\n break;\n }\n\n case \"error\" as any: {\n const errorMsg = message as any;\n messageType = \"system\";\n subtype = \"error\";\n isError = true;\n structuredContent = {\n text: errorMsg.message || errorMsg.error || \"Unknown error\",\n errorType: errorMsg.error_type || \"unknown\",\n errorDetails: {\n stack: errorMsg.stack,\n code: errorMsg.code,\n context: errorMsg,\n },\n timestamp: new Date().toISOString(),\n };\n break;\n }\n\n default: {\n // Unknown message type - log and send as assistant\n const unknownMsg = message as any;\n console.warn(`Unknown message type: ${unknownMsg.type}`, message);\n messageType = \"assistant\";\n structuredContent = {\n text: JSON.stringify(message),\n timestamp: new Date().toISOString(),\n };\n }\n }\n\n // Generate a unique message ID\n const messageId = `${context.agentSessionId}-${Date.now()}-${Math.random()\n .toString(36)\n .substr(2, 9)}`;\n\n // Send agent message to orchestrator with structured content\n // Skip if conversation is stopping/stopped to avoid race conditions\n const currentStatus = context.status as string;\n if (currentStatus !== \"stopped\" && currentStatus !== \"stopping\") {\n if (skipSend) {\n console.log(\n \"[ClaudeManager] Not sending message.agent due to skipSend=true\"\n );\n return;\n }\n\n const payload: any = {\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n agentSessionId: context.agentSessionId,\n type: messageType,\n subtype,\n content: Array.isArray(structuredContent)\n ? structuredContent\n : [structuredContent],\n messageId,\n isError,\n };\n\n // Add metadata if present\n if (metadata) {\n payload.metadata = metadata;\n }\n\n try {\n console.log(\"[ClaudeManager] Sending message.agent payload:\", {\n type: payload.type,\n subtype: payload.subtype,\n contentPreview: Array.isArray(payload.content)\n ? payload.content.slice(0, 1)\n : payload.content,\n });\n } catch {}\n\n await this.runner.notify(\"message.agent\", payload as any);\n }\n\n // Tool calls are now handled directly by Claude through the MCP server\n // We just log that we saw them but don't intercept or process them\n if (\n structuredContent.toolCalls &&\n structuredContent.toolCalls.length > 0\n ) {\n console.log(\n `Claude is making ${structuredContent.toolCalls.length} tool call(s) via MCP`,\n {\n conversationObjectId: context.conversationObjectId,\n toolNames: structuredContent.toolCalls.map((tc: any) => tc.name),\n }\n );\n }\n } catch (error) {\n // Check if this is a transport error due to stopped conversation\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n const isTransportError =\n errorMessage.includes(\"Cannot read properties of undefined\") ||\n errorMessage.includes(\"stdout\") ||\n errorMessage.includes(\"transport\");\n\n const statusCheck = context.status as string;\n if (\n isTransportError &&\n (statusCheck === \"stopped\" || statusCheck === \"stopping\")\n ) {\n // This is expected when conversation is stopped - just log it\n console.log(\n `Transport error for stopped/stopping conversation ${context.conversationId} (expected):`,\n errorMessage\n );\n return;\n }\n\n console.error(\n `Error handling streamed message for ${context.conversationObjectType} ${context.conversationObjectId}:`,\n error\n );\n await this._handleConversationError(context, error as Error);\n }\n }\n}\n\n// Simplified helper functions for SDK integration\n\ntype UserMessageStream = {\n iterable: AsyncIterable<any>;\n enqueue: (msg: any) => void;\n close: () => void;\n};\n\nfunction createUserMessageStream(): UserMessageStream {\n const queue: any[] = [];\n let resolver: (() => void) | null = null;\n let done = false;\n\n async function* iterator() {\n while (true) {\n if (queue.length > 0) {\n const value = queue.shift();\n yield value;\n continue;\n }\n if (done) return;\n await new Promise<void>((resolve) => (resolver = resolve));\n resolver = null;\n }\n }\n\n return {\n iterable: iterator(),\n enqueue: (msg: any) => {\n if (done) return;\n queue.push(msg);\n if (resolver) {\n const r = resolver;\n resolver = null;\n r();\n }\n },\n close: () => {\n done = true;\n if (resolver) {\n const r = resolver;\n resolver = null;\n r();\n }\n },\n };\n}\n\nfunction createConversationWrapper(\n sdk: any,\n input: UserMessageStream,\n onComplete?: (hadError: boolean, error?: any) => Promise<void> | void\n) {\n let onSessionIdCb: ((id: string) => void) | null = null;\n let observedSessionId: string | null = null;\n let startedReader = false;\n\n /**\n * Create an SDK user message from content.\n * Content can be a string (for text-only messages) or an array of content blocks\n * (for multimodal messages with images).\n */\n function toSdkUserMessage(content: string | Array<{ type: string; [key: string]: any }>) {\n const message = {\n type: \"user\" as const,\n session_id: observedSessionId || \"\",\n parent_tool_use_id: null,\n message: {\n role: \"user\" as const,\n // Content should be an array of content blocks for multimodal\n // For text-only, SDK accepts string directly\n content: typeof content === 'string'\n ? content\n : content,\n },\n };\n console.log('[ClaudeManager] toSdkUserMessage creating message:', JSON.stringify(message, null, 2));\n return message;\n }\n\n return {\n /**\n * Send a message to the conversation.\n * Accepts either:\n * - { type: \"text\", text: string } for text-only messages\n * - Array of content blocks for multimodal messages (e.g., [{ type: \"text\", text: \"...\" }, { type: \"image\", source: {...} }])\n */\n send(payload: { type: string; text?: string } | Array<{ type: string; [key: string]: any }>) {\n // Handle multimodal content (array of content blocks)\n if (Array.isArray(payload)) {\n input.enqueue(toSdkUserMessage(payload));\n return;\n }\n // Handle text-only messages\n const text = payload?.text ?? \"\";\n input.enqueue(toSdkUserMessage(text));\n },\n async end() {\n try {\n input.close();\n } finally {\n // Simplified process cleanup\n try {\n if (sdk?.abortController) {\n sdk.abortController.abort();\n }\n } catch {}\n }\n },\n onSessionId(cb: (id: string) => void) {\n onSessionIdCb = cb;\n },\n stream(\n handler: (message: SDKMessage, sessionId: string | null) => Promise<void>\n ) {\n if (startedReader) return;\n startedReader = true;\n (async () => {\n try {\n for await (const msg of sdk) {\n // Simplified session ID extraction\n const sid = (msg && (msg.session_id || msg.sessionId)) || null;\n if (sid && sid !== observedSessionId) {\n observedSessionId = sid;\n if (onSessionIdCb) onSessionIdCb(sid);\n }\n await handler(msg, sid);\n }\n // Normal completion\n if (onComplete) await onComplete(false);\n } catch (e) {\n // Error completion\n if (onComplete) await onComplete(true, e);\n }\n })();\n },\n };\n}\nfunction isClaudeConversation(\n conversation: ConversationContext[\"conversation\"]\n): conversation is ClaudeConversation {\n return (\n !!conversation &&\n typeof (conversation as ClaudeConversation).send === \"function\" &&\n typeof (conversation as ClaudeConversation).end === \"function\"\n );\n}\n","/**\n * Console wrapper that suppresses output unless the requested subsystem\n * is enabled in the debug filter.\n */\n\nimport { DebugSubsystem, isDebugEnabledFor } from './debug.js';\n\nexport function createScopedConsole(\n subsystem: DebugSubsystem = \"runner\"\n): Console {\n // Check debug flag on each call, not at creation time, so that\n // environment variables set after module import are respected\n return {\n log: (...args: unknown[]) => {\n if (isDebugEnabledFor(subsystem)) global.console.log(...args);\n },\n warn: (...args: unknown[]) => {\n if (isDebugEnabledFor(subsystem)) global.console.warn(...args);\n },\n error: global.console.error.bind(global.console), // Always show errors\n info: (...args: unknown[]) => {\n if (isDebugEnabledFor(subsystem)) global.console.info(...args);\n },\n debug: (...args: unknown[]) => {\n if (isDebugEnabledFor(subsystem)) global.console.debug(...args);\n },\n } as Console;\n}\n\n// Default console scoped to core runner events\nexport const console = createScopedConsole(\"runner\");\n","export function expandEnv(\n obj: any,\n env: Record<string, string | undefined> = process.env\n): any {\n if (typeof obj === \"string\") {\n return obj.replace(/\\$\\{([^}]+)\\}/g, (match, key) => env[key] || match);\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => expandEnv(item, env));\n }\n\n if (obj && typeof obj === \"object\") {\n const result: Record<string, any> = {};\n for (const [key, value] of Object.entries(obj)) {\n result[key] = expandEnv(value, env);\n }\n return result;\n }\n\n return obj;\n}\n","import type { ModelReasoningEffort as CodexModelReasoningEffort } from \"@northflare/codex-sdk\";\n\nexport type ModelReasoningEffort = \"low\" | \"medium\" | \"high\" | \"xhigh\";\n\nconst REASONING_VALUES: readonly ModelReasoningEffort[] = [\n \"low\",\n \"medium\",\n \"high\",\n \"xhigh\",\n];\n\nexport function parseModelValue(value?: string | null): {\n baseModel?: string;\n reasoningEffort?: ModelReasoningEffort;\n} {\n if (!value) {\n return {};\n }\n\n const [model, possibleEffort] = value.split(\":\");\n if (\n possibleEffort &&\n REASONING_VALUES.includes(possibleEffort as ModelReasoningEffort)\n ) {\n return {\n baseModel: model,\n reasoningEffort: possibleEffort as ModelReasoningEffort,\n };\n }\n\n return { baseModel: value };\n}\n\nexport function mapReasoningEffortForCodex(\n effort?: ModelReasoningEffort\n): CodexModelReasoningEffort | undefined {\n if (!effort) {\n return undefined;\n }\n\n switch (effort) {\n case \"xhigh\":\n // Pass xhigh through directly - Codex SDK now supports it\n return \"xhigh\";\n case \"low\":\n case \"medium\":\n case \"high\":\n return effort;\n default:\n return undefined;\n }\n}\n","import type {\n Thread,\n ThreadEvent,\n ThreadItem,\n ThreadOptions,\n Input,\n UserInput,\n} from \"@northflare/codex-sdk\";\nimport { IRunnerApp } from '../types/runner-interface.js';\nimport { EnhancedRepositoryManager } from './enhanced-repository-manager.js';\nimport { ConversationContext, ConversationConfig, Message } from '../types/index.js';\nimport { statusLineManager } from '../utils/status-line.js';\nimport { createScopedConsole } from '../utils/console.js';\nimport { expandEnv } from '../utils/expand-env.js';\nimport { mapReasoningEffortForCodex, parseModelValue } from '../utils/model.js';\nimport jwt from \"jsonwebtoken\";\nimport fs from \"fs/promises\";\nimport path from \"path\";\nimport { isDebugEnabledFor } from '../utils/debug.js';\nimport { tmpdir } from \"os\";\nimport crypto from \"crypto\";\nimport { simpleGit } from \"simple-git\";\n\nconst console = createScopedConsole(\n isDebugEnabledFor(\"manager\") ? \"manager\" : \"sdk\"\n);\n\nfunction buildSystemPromptWithNorthflare(\n basePrompt?: string,\n northflarePrompt?: string\n): string | undefined {\n const parts = [northflarePrompt, basePrompt]\n .filter((p): p is string => typeof p === \"string\" && p.trim().length > 0)\n .map((p) => p.trim());\n\n if (parts.length === 0) return undefined;\n return parts.join(\"\\n\\n\");\n}\n\nlet codexSdkPromise: Promise<typeof import(\"@northflare/codex-sdk\")> | null =\n null;\n\nasync function loadCodexSdk() {\n if (!codexSdkPromise) {\n codexSdkPromise = import(\"@northflare/codex-sdk\");\n }\n return codexSdkPromise;\n}\n\ntype CodexThreadState = {\n thread: Thread;\n abortController: AbortController | null;\n runPromise: Promise<void> | null;\n};\n\ntype ConversationDetails = {\n id: string;\n objectType: string;\n objectId: string;\n model: string;\n summary?: string | null;\n globalInstructions: string;\n workspaceInstructions: string;\n permissionsMode: string;\n agentSessionId?: string;\n workspaceId?: string;\n threadId?: string;\n systemPrompt?: string;\n northflareSystemPrompt?: string;\n systemPromptMode?: \"append\" | \"replace\";\n};\n\ntype NormalizedItemEvent = {\n type: string;\n content: any;\n subtype?: string;\n toolCalls?: any;\n isError?: boolean;\n};\n\nexport class CodexManager {\n private runner: IRunnerApp;\n private repositoryManager: EnhancedRepositoryManager;\n private threadStates: Map<string, CodexThreadState> = new Map();\n\n constructor(\n runner: IRunnerApp,\n repositoryManager: EnhancedRepositoryManager\n ) {\n this.runner = runner;\n this.repositoryManager = repositoryManager;\n }\n\n async startConversation(\n conversationObjectType: \"Task\" | \"TaskPlan\" | \"ProjectStep\",\n conversationObjectId: string,\n config: ConversationConfig,\n initialMessages: Message[],\n conversationData?: ConversationDetails,\n provider?: \"openai\" | \"openrouter\" | \"groq\"\n ): Promise<ConversationContext> {\n if (!conversationData?.id) {\n throw new Error(\n \"startConversation requires conversationData with a valid conversation.id\"\n );\n }\n\n const conversationId = conversationData.id;\n const agentSessionId = this.resolveSessionId(config, conversationData);\n const pendingSummary =\n this.runner.consumePendingConversationSummary(conversationId);\n const rawSummary =\n typeof conversationData.summary === \"string\"\n ? conversationData.summary\n : pendingSummary;\n const normalizedSummary =\n typeof rawSummary === \"string\"\n ? rawSummary.replace(/\\s+/g, \" \").trim()\n : null;\n\n const rawModel =\n conversationData?.model ||\n (config as any)?.model ||\n (config as any)?.defaultModel ||\n \"openai\";\n const { baseModel, reasoningEffort } = parseModelValue(rawModel);\n const codexReasoningEffort = mapReasoningEffortForCodex(reasoningEffort);\n const normalizedModel = baseModel || rawModel;\n\n // Debug logging for model parsing\n console.log(\"[CodexManager] Model parsing debug:\", {\n rawModel,\n baseModel,\n reasoningEffort,\n codexReasoningEffort,\n normalizedModel,\n });\n\n // Determine the actual provider - can be passed explicitly or detected from config\n const resolvedProvider =\n provider ||\n (config as any)?.providerType ||\n (conversationData as any)?.providerType ||\n \"openai\";\n\n // Optional system prompt handling (matches Northflare/Claude managers)\n const providedSystemPrompt = buildSystemPromptWithNorthflare(\n config.systemPrompt || (conversationData as any)?.systemPrompt,\n (config as any)?.northflareSystemPrompt ||\n (conversationData as any)?.northflareSystemPrompt\n );\n const systemPromptMode =\n config.systemPromptMode ||\n (conversationData as any)?.systemPromptMode ||\n \"append\";\n\n const metadata: Record<string, any> = {\n instructionsInjected: false,\n originalModelValue: rawModel,\n };\n\n metadata[\"hasSystemPrompt\"] = Boolean(providedSystemPrompt);\n metadata[\"systemPromptMode\"] = systemPromptMode;\n\n if (reasoningEffort) {\n metadata[\"modelReasoningEffort\"] = reasoningEffort;\n }\n\n const context: ConversationContext = {\n conversationId,\n agentSessionId,\n conversationObjectType,\n conversationObjectId,\n taskId:\n conversationObjectType === \"Task\" ? conversationObjectId : undefined,\n workspaceId: config.workspaceId,\n status: \"starting\",\n config,\n startedAt: new Date(),\n lastActivityAt: new Date(),\n model: normalizedModel,\n summary: normalizedSummary,\n globalInstructions: conversationData.globalInstructions || \"\",\n workspaceInstructions: conversationData.workspaceInstructions || \"\",\n permissionsMode:\n conversationData.permissionsMode ||\n (config as any)?.permissionsMode ||\n \"all\",\n provider: resolvedProvider,\n metadata,\n };\n\n this.runner.activeConversations_.set(conversationId, context);\n\n console.log(`[CodexManager] Stored conversation context`, {\n conversationId,\n agentSessionId,\n model: context.model,\n permissionsMode: context.permissionsMode,\n });\n\n const workspacePath = await this.resolveWorkspacePath(context, config);\n\n (context.metadata as Record<string, any>)[\"workspacePath\"] = workspacePath;\n\n const githubToken = context.workspaceId\n ? await this.fetchGithubTokens(context.workspaceId)\n : undefined;\n\n const toolToken = this.generateToolToken(context);\n\n let mcpServers: Record<string, any> | undefined;\n if (config.mcpServers && Object.keys(config.mcpServers).length > 0) {\n const expandedServers = expandEnv(config.mcpServers, {\n TOOL_TOKEN: toolToken,\n });\n mcpServers = this.normalizeMcpServersForCodex(expandedServers);\n console.log(\n \"[CodexManager] MCP servers configuration:\",\n JSON.stringify(mcpServers, null, 2)\n );\n (context.metadata as Record<string, any>)[\"mcpServers\"] = mcpServers;\n }\n\n let configOverrides = this.buildConfigOverridesFromMcp(mcpServers);\n\n // Add OpenRouter config overrides if using OpenRouter provider\n if (resolvedProvider === \"openrouter\") {\n const openRouterOverrides = this.buildOpenRouterConfigOverrides();\n configOverrides = {\n ...configOverrides,\n ...openRouterOverrides,\n };\n console.log(\n \"[CodexManager] OpenRouter config overrides:\",\n JSON.stringify(openRouterOverrides, null, 2)\n );\n }\n\n // Inject system prompt via developer_instructions (developer role message)\n if (providedSystemPrompt) {\n const trimmedPrompt = providedSystemPrompt.trim();\n if (trimmedPrompt.length) {\n const systemPromptOverrides: Record<string, unknown> = {\n developer_instructions: trimmedPrompt,\n };\n configOverrides = {\n ...configOverrides,\n ...systemPromptOverrides,\n };\n\n console.log(\"[CodexManager] Applied system prompt overrides\", {\n mode: systemPromptMode,\n hasSystemPrompt: true,\n replacesBase: systemPromptMode === \"replace\",\n });\n }\n }\n\n const envVars = await this.buildEnvVars(\n config,\n githubToken,\n toolToken,\n resolvedProvider\n );\n\n const { Codex } = await loadCodexSdk();\n const codex = new Codex({\n baseUrl:\n (config as any)?.openaiBaseUrl ||\n (config as any)?.codexBaseUrl ||\n process.env[\"OPENAI_BASE_URL\"],\n apiKey:\n (config as any)?.openaiApiKey ||\n (config as any)?.codexApiKey ||\n process.env[\"CODEX_API_KEY\"] ||\n process.env[\"OPENAI_API_KEY\"],\n env: envVars,\n });\n\n // Strip provider prefix (e.g., \"openrouter:\") from model name if present\n const modelName = context.model.includes(\":\")\n ? context.model.split(\":\").slice(1).join(\":\")\n : context.model;\n\n // Debug: log what model name we're using\n console.log(\"[CodexManager] Model name processing:\", {\n contextModel: context.model,\n hasColon: context.model.includes(\":\"),\n modelNameAfterStrip: modelName,\n });\n\n const threadOptions: ThreadOptions = {\n model: modelName,\n workingDirectory: workspacePath,\n sandboxMode: this.mapSandboxMode(context.permissionsMode),\n networkAccessEnabled: this.shouldEnableNetwork(context.permissionsMode),\n webSearchEnabled: true,\n // additionalDirectories: this.getAdditionalDirectories(config),\n configOverrides,\n skipGitRepoCheck: true,\n modelReasoningEffort: codexReasoningEffort,\n };\n\n console.log(\n \"[CodexManager] Thread options:\",\n JSON.stringify(threadOptions, null, 2)\n );\n\n const thread = agentSessionId\n ? codex.resumeThread(agentSessionId, threadOptions)\n : codex.startThread(threadOptions);\n\n this.threadStates.set(conversationId, {\n thread,\n abortController: null,\n runPromise: null,\n });\n\n context.conversation = thread;\n\n // Launch the first turn using the provided initial messages.\n // Supports multimodal (images/documents) by converting to Codex Input.\n if (initialMessages?.length) {\n const initialInput = await this.buildInitialInput(initialMessages, context);\n this.launchTurn(context, initialInput);\n }\n\n return context;\n }\n\n async stopConversation(\n _agentSessionId: string,\n context: ConversationContext,\n isRunnerShutdown: boolean = false,\n reason?: string\n ): Promise<void> {\n (context as any)._stopRequested = true;\n (context as any)._stopReason =\n reason || (isRunnerShutdown ? \"runner_shutdown\" : undefined);\n context.status = \"stopping\";\n\n await this.abortActiveRun(context.conversationId);\n\n try {\n await this._finalizeConversation(\n context,\n false,\n undefined,\n (context as any)._stopReason\n );\n } catch (error) {\n console.error(\n `[CodexManager] Error finalizing conversation ${context.conversationId}:`,\n error\n );\n } finally {\n this.threadStates.delete(context.conversationId);\n }\n\n context.status = \"stopped\";\n }\n\n async resumeConversation(\n conversationObjectType: \"Task\" | \"TaskPlan\" | \"ProjectStep\",\n conversationObjectId: string,\n agentSessionId: string,\n config: ConversationConfig,\n conversationData?: ConversationDetails,\n resumeMessage?: string,\n provider?: \"openai\" | \"openrouter\" | \"groq\"\n ): Promise<string> {\n console.log(`[CodexManager] Resuming conversation ${agentSessionId}`);\n\n const context = await this.startConversation(\n conversationObjectType,\n conversationObjectId,\n { ...config, sessionId: agentSessionId },\n [],\n conversationData,\n provider\n );\n\n if (resumeMessage) {\n const prompt = this.buildPromptForMessage(context, resumeMessage, false);\n this.launchTurn(context, prompt);\n }\n\n return context.agentSessionId;\n }\n\n async sendUserMessage(\n conversationId: string,\n content: any,\n config?: ConversationConfig,\n conversationObjectType?: \"Task\" | \"TaskPlan\" | \"ProjectStep\",\n conversationObjectId?: string,\n conversation?: any,\n agentSessionIdOverride?: string,\n provider?: \"openai\" | \"openrouter\" | \"groq\"\n ): Promise<void> {\n console.log(`[CodexManager] sendUserMessage called`, {\n conversationId,\n hasConfig: !!config,\n });\n\n let context = this.runner.getConversationContext(conversationId);\n\n if (!context && conversation) {\n const conversationDetails = conversation as ConversationDetails;\n const resumeSessionId = this.resolveSessionId(\n config,\n conversationDetails,\n agentSessionIdOverride\n );\n const startConfig: ConversationConfig = {\n ...(config || {}),\n workspaceId:\n conversationDetails.workspaceId || config?.workspaceId || undefined,\n ...(resumeSessionId ? { sessionId: resumeSessionId } : {}),\n };\n\n context = await this.startConversation(\n (conversationObjectType as \"Task\" | \"TaskPlan\") ||\n (conversationDetails.objectType as \"Task\" | \"TaskPlan\"),\n conversationObjectId || conversationDetails.objectId,\n startConfig,\n [],\n conversationDetails,\n provider\n );\n }\n\n if (!context) {\n throw new Error(\n `No active or fetchable conversation found for ${conversationId}`\n );\n }\n\n await this.abortActiveRun(conversationId);\n\n const input = await this.normalizeToInput(content, context, false);\n this.launchTurn(context, input);\n\n context.lastActivityAt = new Date();\n }\n\n private async _handleRunCompletion(\n context: ConversationContext,\n hadError: boolean,\n error?: any\n ): Promise<void> {\n if ((context as any)._finalized) return;\n\n const inFlight = (context as any)._runCompletionInFlight as\n | Promise<void>\n | undefined;\n if (inFlight) return inFlight;\n\n const promise = (async () => {\n\n const isTaskConversation = context.conversationObjectType === \"Task\";\n const stopRequested = (context as any)._stopRequested === true;\n const taskHandle = (context as any).taskHandle as any;\n const shouldRunGitFlow =\n context.config.useWorktrees !== false &&\n isTaskConversation &&\n !!taskHandle &&\n taskHandle.branch !== \"local\";\n\n if (!shouldRunGitFlow || hadError || stopRequested) {\n await this._finalizeConversation(context, hadError, error);\n return;\n }\n\n const taskId = context.conversationObjectId;\n const baseBranch =\n (context.config.repository?.branch as string | undefined) || \"main\";\n\n try {\n const taskState = await this.repositoryManager.getTaskState(taskId);\n const taskRepoInfo = await this.repositoryManager.getTaskRepoInfo(taskId);\n\n if (\n !taskState ||\n !taskRepoInfo ||\n !taskRepoInfo.worktreePath ||\n taskState.branch === \"local\"\n ) {\n await this._finalizeConversation(context, false);\n return;\n }\n\n const isLocalRepo = taskRepoInfo.repoKey.startsWith(\"local__\");\n const mergeWorkdir = isLocalRepo\n ? taskRepoInfo.controlPath\n : taskRepoInfo.worktreePath;\n\n // If we already have unresolved conflicts, immediately ask the agent to resolve them.\n const taskGit = simpleGit(taskRepoInfo.worktreePath);\n const initialTaskStatus = await taskGit.status();\n if (initialTaskStatus.conflicted.length > 0) {\n await this._resumeForGitConflictResolution(context, {\n kind: \"conflicts\",\n baseBranch,\n conflicts: initialTaskStatus.conflicted,\n workdir: taskRepoInfo.worktreePath,\n });\n return;\n }\n\n if (isLocalRepo && mergeWorkdir !== taskRepoInfo.worktreePath) {\n const mergeGit = simpleGit(mergeWorkdir);\n const mergeStatus = await mergeGit.status();\n if (mergeStatus.conflicted.length > 0) {\n await this._resumeForGitConflictResolution(context, {\n kind: \"conflicts\",\n baseBranch,\n conflicts: mergeStatus.conflicted,\n workdir: mergeWorkdir,\n });\n return;\n }\n }\n\n // Ensure we're on the task branch for commit/rebase operations.\n const currentBranch = (\n await taskGit.revparse([\"--abbrev-ref\", \"HEAD\"])\n ).trim();\n if (currentBranch !== taskState.branch) {\n await taskGit.checkout(taskState.branch);\n }\n\n const status = await taskGit.status();\n if (!status.isClean()) {\n await this.repositoryManager.stageAll(taskId);\n try {\n const previousCommitCount = (taskState as any)?.commitCount ?? 0;\n const baseSubject =\n (context.summary ?? \"\").replace(/\\s+/g, \" \").trim() ||\n `Task ${taskId}`;\n const message =\n previousCommitCount > 0\n ? `${baseSubject} (followup #${previousCommitCount})`\n : baseSubject;\n await this.repositoryManager.commit(taskId, message);\n } catch (commitError) {\n const msg =\n commitError instanceof Error\n ? commitError.message\n : String(commitError);\n if (!msg.toLowerCase().includes(\"nothing to commit\")) {\n throw commitError;\n }\n }\n }\n\n const integrateResult = await this.repositoryManager.integrateTask(\n taskId,\n baseBranch,\n \"no-ff\"\n );\n if (!integrateResult.success) {\n await this._resumeForGitConflictResolution(context, {\n kind: integrateResult.phase,\n baseBranch,\n conflicts: integrateResult.conflicts ?? [],\n workdir: integrateResult.conflictWorkdir,\n error: integrateResult.error,\n });\n return;\n }\n\n // Worktree is no longer needed after a successful merge; preserve the branch\n await this.repositoryManager.removeTaskWorktree(taskId, {\n preserveBranch: true,\n });\n\n const wsId = context.config.workspaceId || context.workspaceId;\n const repoUrl = context.config.repository?.url;\n if (wsId && repoUrl) {\n await this.repositoryManager.syncWorkspaceWorktree(wsId, repoUrl, baseBranch);\n }\n\n await this._finalizeConversation(context, false);\n } catch (mergeError) {\n console.error(\"[CodexManager] Post-task git flow failed\", mergeError);\n await this._finalizeConversation(context, true, mergeError);\n }\n })();\n\n (context as any)._runCompletionInFlight = promise.finally(() => {\n delete (context as any)._runCompletionInFlight;\n });\n return (context as any)._runCompletionInFlight;\n }\n\n private async _resumeForGitConflictResolution(\n context: ConversationContext,\n payload: {\n kind: \"conflicts\" | \"rebase\" | \"merge\";\n baseBranch: string;\n conflicts: string[];\n workdir: string;\n error?: string;\n }\n ): Promise<void> {\n const { kind, baseBranch, conflicts, workdir, error } = payload;\n\n const conflictsList = conflicts?.length\n ? `\\n\\nConflicted files:\\n${conflicts.map((f) => `- ${f}`).join(\"\\n\")}`\n : \"\";\n const workdirHint = workdir ? `\\n\\nWork directory:\\n- ${workdir}` : \"\";\n const errorHint = error ? `\\n\\nError:\\n${error}` : \"\";\n const hasConflicts = !!conflicts?.length;\n\n let instruction: string;\n if (kind === \"rebase\") {\n instruction = hasConflicts\n ? `<system-instructions>\\nA git rebase onto \\`${baseBranch}\\` produced merge conflicts.${conflictsList}${workdirHint}${errorHint}\\n\\nPlease resolve the conflicts in that directory, then run:\\n- git add -A\\n- git rebase --continue\\n\\nWhen the rebase finishes cleanly, reply briefly so I can retry the integration.\\n</system-instructions>`\n : `<system-instructions>\\nA git rebase onto \\`${baseBranch}\\` failed.${workdirHint}${errorHint}\\n\\nNo conflicted files were reported. Please run:\\n- git status\\n\\nFix the error (or complete/abort any in-progress git operation) and reply briefly so I can retry the integration.\\n</system-instructions>`;\n } else if (kind === \"merge\") {\n instruction = hasConflicts\n ? `<system-instructions>\\nA git merge into \\`${baseBranch}\\` produced merge conflicts.${conflictsList}${workdirHint}${errorHint}\\n\\nPlease resolve the conflicts in that directory, then run:\\n- git add -A\\n- git commit -m \\\"Resolve merge conflicts for ${context.conversationObjectId}\\\"\\n\\nWhen the working tree is clean, reply briefly so I can retry the integration.\\n</system-instructions>`\n : `<system-instructions>\\nA git merge into \\`${baseBranch}\\` failed.${workdirHint}${errorHint}\\n\\nNo conflicted files were reported. Please run:\\n- git status\\n\\nFix the error (or complete/abort any in-progress git operation) and reply briefly so I can retry the integration.\\n</system-instructions>`;\n } else {\n instruction = `<system-instructions>\\nGit has unresolved conflicts.${conflictsList}${workdirHint}${errorHint}\\n\\nPlease resolve the conflicts in that directory and complete the in-progress git operation (rebase or merge). When the working tree is clean, reply briefly so I can retry the integration.\\n</system-instructions>`;\n }\n\n const conversationData: ConversationDetails = {\n id: context.conversationId,\n objectType: context.conversationObjectType,\n objectId: context.conversationObjectId,\n model: context.model,\n summary: context.summary ?? null,\n globalInstructions: context.globalInstructions,\n workspaceInstructions: context.workspaceInstructions,\n permissionsMode: context.permissionsMode,\n agentSessionId: context.agentSessionId,\n workspaceId: context.workspaceId,\n };\n\n await this.resumeConversation(\n context.conversationObjectType,\n context.conversationObjectId,\n context.agentSessionId,\n context.config,\n conversationData,\n instruction,\n context.provider as \"openai\" | \"openrouter\" | \"groq\"\n );\n }\n\n private async buildEnvVars(\n config: ConversationConfig,\n githubToken?: string,\n toolToken?: string,\n provider?: string\n ): Promise<Record<string, string>> {\n const envVars: Record<string, string> = {\n ...(Object.fromEntries(\n Object.entries(process.env).filter(([, value]) => value !== undefined)\n ) as Record<string, string>),\n };\n\n if (config.codexAuth?.accessToken) {\n envVars[\"OPENAI_ACCESS_TOKEN\"] = config.codexAuth.accessToken;\n } else if (config.accessToken) {\n envVars[\"OPENAI_ACCESS_TOKEN\"] = config.accessToken;\n }\n\n if (githubToken) {\n envVars[\"GITHUB_TOKEN\"] = githubToken;\n }\n\n if (toolToken) {\n envVars[\"TOOL_TOKEN\"] = toolToken;\n }\n\n if (isDebugEnabledFor(\"sdk\")) {\n envVars[\"DEBUG\"] = \"1\";\n }\n\n // Add OpenRouter/Groq API keys when using Northflare-routed providers\n if (provider === \"openrouter\" || provider === \"groq\") {\n const openRouterApiKey =\n (config as any).openRouterApiKey ||\n process.env[\"OPENROUTER_API_KEY\"];\n if (openRouterApiKey) {\n envVars[\"OPENROUTER_API_KEY\"] = openRouterApiKey;\n }\n\n const groqApiKey =\n (config as any).groqApiKey ||\n process.env[\"GROQ_API_KEY\"];\n if (groqApiKey) {\n envVars[\"GROQ_API_KEY\"] = groqApiKey;\n }\n\n if (!openRouterApiKey && !groqApiKey) {\n console.warn(\n \"[CodexManager] OpenRouter/Groq provider selected but no API key found\"\n );\n }\n }\n\n const codexHome = await this.ensureCodexAuthHome(config);\n if (codexHome) {\n envVars[\"CODEX_HOME\"] = codexHome;\n }\n\n return envVars;\n }\n\n private async ensureCodexAuthHome(\n config: ConversationConfig\n ): Promise<string | null> {\n if (!config.codexAuth) {\n return null;\n }\n\n const runnerId = this.runner.getRunnerId();\n const dataDir = this.runner.config_.dataDir;\n\n if (!runnerId || !dataDir) {\n console.warn(\n \"[CodexManager] Missing runnerId or dataDir; cannot prepare Codex auth directory\"\n );\n return null;\n }\n\n const codexDir = path.join(dataDir, \"codex\", runnerId);\n const authPayload = {\n OPENAI_API_KEY: null,\n tokens: {\n id_token: config.codexAuth.idToken,\n access_token: config.codexAuth.accessToken,\n refresh_token: \"\",\n account_id: config.codexAuth.accountId,\n },\n last_refresh: config.codexAuth.lastRefresh || new Date().toISOString(),\n };\n\n try {\n await fs.mkdir(codexDir, { recursive: true });\n await fs.writeFile(\n path.join(codexDir, \"auth.json\"),\n JSON.stringify(authPayload, null, 2),\n \"utf-8\"\n );\n return codexDir;\n } catch (error) {\n console.error(\n \"[CodexManager] Failed to persist Codex auth configuration:\",\n error\n );\n throw new Error(\n \"Runner failed to persist Codex credentials. Check runner logs for details.\"\n );\n }\n }\n\n private buildPromptForMessage(\n context: ConversationContext,\n text: string,\n forceInstructions: boolean\n ): string {\n const trimmed = text ?? \"\";\n const instructions = this.getInstructionPrefix(context);\n\n const metadata =\n (context.metadata as Record<string, any>) || ({} as Record<string, any>);\n const shouldInjectInstructions =\n forceInstructions || !metadata[\"instructionsInjected\"];\n\n if (instructions && shouldInjectInstructions) {\n metadata[\"instructionsInjected\"] = true;\n context.metadata = metadata;\n return `${instructions}\\n\\n${trimmed}`.trim();\n }\n\n return trimmed;\n }\n\n private getInstructionPrefix(context: ConversationContext): string {\n const parts: string[] = [];\n\n if (context.globalInstructions) {\n parts.push(\n `<global-instructions>\\n${context.globalInstructions}\\n</global-instructions>`\n );\n }\n\n if (context.workspaceInstructions) {\n parts.push(\n `<workspace-instructions>\\n${context.workspaceInstructions}\\n</workspace-instructions>`\n );\n }\n\n return parts.join(\"\\n\\n\");\n }\n\n private formatInitialMessages(initialMessages: Message[]): string {\n return initialMessages\n .map((msg) => {\n const role = (msg.role as string) || \"user\";\n const content = this.normalizeToText(msg.content);\n return `<${role}-message>\\n${content}\\n</${role}-message>`;\n })\n .join(\"\\n\\n\");\n }\n\n private async buildInitialInput(\n initialMessages: Message[],\n context: ConversationContext\n ): Promise<Input> {\n const hasMultimodal = initialMessages.some((msg) =>\n this.hasMultimodalContent((msg as any).content)\n );\n\n if (!hasMultimodal) {\n const promptText = this.formatInitialMessages(initialMessages);\n return this.buildPromptForMessage(context, promptText, true);\n }\n\n // Preserve role markers while keeping image blocks attached\n const combinedBlocks: Array<any> = [];\n\n for (const msg of initialMessages) {\n const role = (msg.role as string) || \"user\";\n const content = (msg as any).content;\n\n // Start role section\n combinedBlocks.push({\n type: \"text\",\n text: `<${role}-message>`,\n });\n\n if (Array.isArray(content)) {\n for (const item of content) {\n if (!item || typeof item !== \"object\") continue;\n if (item.type === \"text\" && typeof item.text === \"string\") {\n combinedBlocks.push({ type: \"text\", text: item.text });\n } else if (item.type === \"image\" || item.type === \"document\") {\n combinedBlocks.push(item);\n }\n }\n } else {\n combinedBlocks.push({\n type: \"text\",\n text: this.normalizeToText(content),\n });\n }\n\n // Close role section\n combinedBlocks.push({\n type: \"text\",\n text: `</${role}-message>`,\n });\n }\n\n const input = await this.normalizeToInput(combinedBlocks, context, true);\n if (isDebugEnabledFor(\"manager\") || isDebugEnabledFor(\"sdk\")) {\n console.log(\"[CodexManager] buildInitialInput multimodal payload\", {\n conversationId: context.conversationId,\n blocks: combinedBlocks.map((b) => b.type),\n inputType: Array.isArray(input) ? \"array\" : \"string\",\n textItems: Array.isArray(input)\n ? input.filter((i: any) => i.type === \"text\").length\n : 1,\n imageItems: Array.isArray(input)\n ? input.filter((i: any) => i.type === \"local_image\").length\n : 0,\n });\n }\n return input;\n }\n\n private launchTurn(context: ConversationContext, prompt: Input): void {\n const state = this.threadStates.get(context.conversationId);\n\n if (!state || !state.thread) {\n throw new Error(\n `Thread state missing for conversation ${context.conversationId}`\n );\n }\n\n const abortController = new AbortController();\n state.abortController = abortController;\n\n context.lastActivityAt = new Date();\n\n const runPromise = this.streamThreadEvents(\n context,\n state.thread,\n prompt,\n abortController\n );\n\n state.runPromise = runPromise;\n\n runPromise\n .catch((error) => {\n if (!this.isAbortError(error)) {\n console.error(\n `[CodexManager] Run failed for ${context.conversationId}:`,\n error\n );\n this._handleConversationError(context, error as Error);\n }\n })\n .finally(() => {\n if (state.runPromise === runPromise) {\n state.runPromise = null;\n }\n if (state.abortController === abortController) {\n state.abortController = null;\n }\n });\n }\n\n private async streamThreadEvents(\n context: ConversationContext,\n thread: Thread,\n prompt: Input,\n abortController: AbortController\n ): Promise<void> {\n try {\n const { events } = await thread.runStreamed(prompt, {\n signal: abortController.signal,\n });\n\n for await (const event of events) {\n await this.handleThreadEvent(context, event);\n }\n } catch (error) {\n if (this.isAbortError(error)) {\n console.log(\n `[CodexManager] Turn aborted for ${context.conversationId}`\n );\n return;\n }\n\n throw error;\n }\n }\n\n private async abortActiveRun(conversationId: string): Promise<void> {\n const state = this.threadStates.get(conversationId);\n if (!state || !state.runPromise) return;\n\n if (state.abortController) {\n state.abortController.abort();\n }\n\n try {\n await state.runPromise;\n } catch (error) {\n if (!this.isAbortError(error)) {\n console.warn(\n `[CodexManager] Run aborted with error for ${conversationId}:`,\n error\n );\n }\n }\n }\n\n private async handleThreadEvent(\n context: ConversationContext,\n event: ThreadEvent\n ): Promise<void> {\n try {\n this.logRawThreadEvent(event);\n\n switch (event.type) {\n case \"thread.started\": {\n await this.handleThreadStarted(context, event.thread_id);\n break;\n }\n case \"turn.started\": {\n context.status = \"active\";\n await this.sendAgentMessage(context, \"system\", {\n subtype: \"turn.started\",\n content: [\n {\n type: \"text\",\n text: `Turn started at ${new Date().toISOString()}`,\n },\n ],\n });\n break;\n }\n case \"turn.completed\": {\n await this.sendAgentMessage(context, \"result\", {\n subtype: \"turn.completed\",\n content: [\n {\n type: \"usage\",\n usage: event.usage,\n },\n ],\n });\n context.status = \"stopped\";\n await this._handleRunCompletion(context, false);\n break;\n }\n case \"turn.failed\": {\n const error = new Error(event.error?.message || \"Turn failed\");\n await this.sendAgentMessage(context, \"error\", {\n subtype: \"turn.failed\",\n content: [\n {\n type: \"text\",\n text: error.message,\n },\n ],\n isError: true,\n });\n await this._handleConversationError(context, error);\n context.status = \"stopped\";\n await this._finalizeConversation(context, true, error, \"turn_failed\");\n break;\n }\n case \"item.started\":\n case \"item.updated\":\n case \"item.completed\": {\n await this.forwardItemEvent(\n context,\n event.item,\n event.type.split(\".\")[1] as \"started\" | \"updated\" | \"completed\"\n );\n break;\n }\n case \"error\": {\n const fatalError = new Error(event.message || \"Unknown error\");\n await this.sendAgentMessage(context, \"error\", {\n subtype: \"thread.error\",\n content: [{ type: \"text\", text: fatalError.message }],\n isError: true,\n });\n await this._handleConversationError(context, fatalError);\n context.status = \"stopped\";\n await this._finalizeConversation(\n context,\n true,\n fatalError,\n \"thread_error\"\n );\n break;\n }\n }\n } catch (error) {\n console.error(\"[CodexManager] Failed to handle thread event\", {\n event,\n error,\n });\n }\n }\n\n private async forwardItemEvent(\n context: ConversationContext,\n item: ThreadItem,\n phase: \"started\" | \"updated\" | \"completed\"\n ): Promise<void> {\n const normalized = this.normalizeItemEvent(context, item, phase);\n if (!normalized) return;\n\n const { subtype, content, isError, toolCalls, type } = normalized;\n const payload: {\n subtype?: string;\n content: any;\n toolCalls?: any;\n isError?: boolean;\n } = {\n subtype,\n content,\n isError,\n };\n\n if (toolCalls) {\n payload.toolCalls = toolCalls;\n }\n\n await this.sendAgentMessage(context, type, payload);\n }\n\n private normalizeItemEvent(\n context: ConversationContext,\n item: ThreadItem,\n phase: \"started\" | \"updated\" | \"completed\"\n ): NormalizedItemEvent | null {\n switch (item.type) {\n case \"agent_message\": {\n if (phase !== \"completed\") return null;\n return {\n type: \"assistant\",\n content: [\n {\n type: \"text\",\n text: item.text || \"\",\n },\n ],\n };\n }\n case \"reasoning\": {\n return {\n type: \"thinking\",\n content: [\n {\n type: \"thinking\",\n thinking: item.text,\n text: item.text,\n phase,\n },\n ],\n };\n }\n case \"command_execution\": {\n // Namespace command_execution tool use IDs so they don't collide\n // with MCP tool call IDs that may reuse the same raw item.id.\n const internalNamespace = \"codex_command\";\n const toolUseId = this.buildToolUseId(\n context,\n `${internalNamespace}:${item.id}`\n );\n const timestamp = new Date().toISOString();\n const isTerminal =\n phase === \"completed\" ||\n item.status === \"completed\" ||\n item.status === \"failed\";\n\n if (!isTerminal) {\n if (phase !== \"started\") {\n return null;\n }\n\n return {\n type: \"assistant\",\n subtype: \"tool_use\",\n content: [\n {\n toolCalls: [\n {\n id: toolUseId,\n name: \"codex_command\",\n arguments: {\n command: item.command,\n status: item.status,\n },\n status: item.status,\n },\n ],\n timestamp,\n },\n ],\n };\n }\n\n const exitCode =\n typeof item.exit_code === \"number\" ? item.exit_code : null;\n const isError = item.status === \"failed\" || (exitCode ?? 0) !== 0;\n\n return {\n type: \"tool_result\",\n subtype: \"tool_result\",\n content: [\n {\n type: \"tool_result\",\n tool_use_id: toolUseId,\n content: {\n kind: \"codex_command_result\",\n command: item.command,\n output: item.aggregated_output || \"\",\n exitCode,\n status: item.status,\n },\n timestamp,\n },\n ],\n isError,\n };\n }\n case \"file_change\": {\n if (phase === \"updated\") return null;\n return {\n type: \"file_change\",\n subtype: \"file_change\",\n content: [\n {\n type: \"file_change\",\n changes: item.changes,\n status: item.status,\n },\n ],\n };\n }\n case \"mcp_tool_call\": {\n const toolName = this.buildMcpToolName(item.server, item.tool);\n // Namespace MCP tool call IDs with the MCP tool name so they don't\n // collide with internal tool IDs or MCP calls from other servers.\n const namespacedRawId = `mcp:${toolName}:${item.id}`;\n const toolUseId = this.buildToolUseId(context, namespacedRawId);\n\n if (item.status === \"in_progress\" || phase !== \"completed\") {\n return {\n type: \"assistant\",\n subtype: \"tool_use\",\n content: [\n {\n toolCalls: [\n {\n id: toolUseId,\n name: toolName,\n arguments: item.arguments,\n server: item.server,\n tool: item.tool,\n status: item.status,\n },\n ],\n timestamp: new Date().toISOString(),\n },\n ],\n };\n }\n\n if (item.status === \"failed\") {\n return {\n type: \"error\",\n subtype: \"tool_result\",\n content: [\n {\n type: \"text\",\n text: item.error?.message || \"Tool call failed\",\n tool_use_id: toolUseId,\n tool_name: toolName,\n timestamp: new Date().toISOString(),\n },\n ],\n isError: true,\n };\n }\n\n return {\n type: \"tool_result\",\n subtype: \"tool_result\",\n content: [\n {\n type: \"tool_result\",\n subtype: \"tool_result\",\n tool_use_id: toolUseId,\n content: item.result?.content || [],\n structured_content: item.result?.structured_content,\n metadata: {\n server: item.server,\n tool: item.tool,\n name: toolName,\n original_tool_use_id: item.id,\n },\n timestamp: new Date().toISOString(),\n },\n ],\n };\n }\n case \"web_search\": {\n return {\n type: \"system\",\n subtype: `web_search.${phase}`,\n content: [\n {\n type: \"web_search\",\n query: item.query,\n status: phase,\n },\n ],\n };\n }\n case \"todo_list\": {\n return {\n type: \"system\",\n subtype: \"todo_list\",\n content: [\n {\n type: \"todo_list\",\n items: item.items,\n phase,\n },\n ],\n };\n }\n case \"error\": {\n return {\n type: \"error\",\n subtype: `item.${phase}`,\n content: [\n {\n type: \"text\",\n text: item.message,\n },\n ],\n isError: true,\n };\n }\n default:\n return null;\n }\n }\n\n private async sendAgentMessage(\n context: ConversationContext,\n type: string,\n {\n subtype,\n content,\n toolCalls,\n isError,\n }: {\n subtype?: string;\n content: any;\n toolCalls?: any;\n isError?: boolean;\n }\n ): Promise<void> {\n const normalizedContent = Array.isArray(content)\n ? content\n : content\n ? [content]\n : [];\n\n const payload = {\n taskId: context.taskId,\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n agentSessionId: context.agentSessionId,\n type,\n subtype,\n content: normalizedContent,\n toolCalls,\n isError: Boolean(isError),\n messageId: this.generateMessageId(context),\n timestamp: new Date().toISOString(),\n };\n\n if (isDebugEnabledFor(\"manager\")) {\n console.log(\"[CodexManager] Sending message.agent\", payload);\n }\n\n await this.runner.notify(\"message.agent\", payload);\n }\n\n private async handleThreadStarted(\n context: ConversationContext,\n threadId: string\n ): Promise<void> {\n if (!threadId || threadId === context.agentSessionId) {\n return;\n }\n\n const oldSessionId = context.agentSessionId;\n context.agentSessionId = threadId;\n\n await this.runner.notify(\"agentSessionId.changed\", {\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n oldAgentSessionId: oldSessionId,\n newAgentSessionId: threadId,\n });\n }\n\n private mapSandboxMode(\n permissionsMode?: string\n ): \"read-only\" | \"workspace-write\" | \"danger-full-access\" {\n const mode = (permissionsMode || \"\").toLowerCase();\n if (mode === \"read\" || mode === \"read_only\") {\n return \"read-only\";\n }\n // \"project\" mode allows bash but no file writes - Codex doesn't have fine-grained control,\n // so we use workspace-write which allows both bash and file writes\n if (mode === \"project\" || mode === \"workspace\" || mode === \"workspace-write\") {\n return \"workspace-write\";\n }\n return \"danger-full-access\";\n }\n\n private shouldEnableNetwork(permissionsMode?: string): boolean {\n const mode = (permissionsMode || \"\").toLowerCase();\n // project mode allows network (for fetching dependencies, running tests, etc.)\n if (mode === \"project\") return true;\n return mode !== \"read\" && mode !== \"read_only\";\n }\n\n private getAdditionalDirectories(\n config: ConversationConfig\n ): string[] | undefined {\n const additionalDirs: string[] = [];\n if (config.runnerRepoPath) {\n additionalDirs.push(config.runnerRepoPath);\n }\n return additionalDirs.length ? additionalDirs : undefined;\n }\n\n private buildConfigOverridesFromMcp(\n mcpServers?: Record<string, any>\n ): Record<string, unknown> | undefined {\n if (!mcpServers) return undefined;\n const overrides: Record<string, unknown> = {};\n\n for (const [serverName, config] of Object.entries(mcpServers)) {\n this.flattenOverrideObject(\n `mcp_servers.${serverName}`,\n config,\n overrides\n );\n }\n\n return Object.keys(overrides).length ? overrides : undefined;\n }\n\n /**\n * Build Codex config overrides for OpenRouter provider.\n * These correspond to the Codex CLI flags:\n * -c model_provider=openrouter\n * -c model_providers.openrouter.name=openrouter\n * -c model_providers.openrouter.base_url=https://openrouter.ai/api/v1\n * -c model_providers.openrouter.env_key=OPENROUTER_API_KEY\n */\n private buildOpenRouterConfigOverrides(): Record<string, unknown> {\n return {\n model_provider: \"openrouter\",\n \"model_providers.openrouter.name\": \"openrouter\",\n \"model_providers.openrouter.base_url\": \"https://openrouter.ai/api/v1\",\n \"model_providers.openrouter.env_key\": \"OPENROUTER_API_KEY\",\n };\n }\n\n private normalizeMcpServersForCodex(\n mcpServers: Record<string, any>\n ): Record<string, any> {\n const normalized: Record<string, any> = {};\n for (const [serverName, config] of Object.entries(mcpServers)) {\n normalized[serverName] = this.stripAuthorizationHeader(config);\n }\n return normalized;\n }\n\n private buildMcpToolName(server?: string, tool?: string): string {\n const safeServer = (server || \"unknown\").trim() || \"unknown\";\n const safeTool = (tool || \"unknown\").trim() || \"unknown\";\n return `mcp__${safeServer}__${safeTool}`;\n }\n\n private logRawThreadEvent(event: ThreadEvent): void {\n if (!isDebugEnabledFor(\"sdk\")) {\n return;\n }\n\n try {\n console.log(\n \"[CodexManager] RAW Codex event FULL:\",\n this.safeStringify(event)\n );\n\n const summary: Record<string, unknown> = {\n type: event?.type,\n keys: Object.keys((event as Record<string, unknown>) || {}),\n hasItem: Boolean((event as any)?.item),\n itemType: (event as any)?.item?.type,\n hasUsage: Boolean((event as any)?.usage),\n threadId: (event as any)?.thread_id,\n turnId: (event as any)?.turn_id,\n };\n\n console.log(\"[CodexManager] RAW Codex event summary:\", summary);\n\n if ((event as any)?.item) {\n console.log(\n \"[CodexManager] RAW Codex event item:\",\n this.safeStringify((event as any).item)\n );\n }\n\n if ((event as any)?.usage) {\n console.log(\"[CodexManager] RAW Codex usage:\", (event as any).usage);\n }\n } catch (error) {\n console.warn(\"[CodexManager] Failed to log raw Codex event:\", error);\n }\n }\n\n private safeStringify(value: any): string {\n const seen = new WeakSet();\n return JSON.stringify(\n value,\n (key, nested) => {\n if (typeof nested === \"function\") return undefined;\n if (typeof nested === \"bigint\") return nested.toString();\n if (typeof nested === \"object\" && nested !== null) {\n if (seen.has(nested)) return \"[Circular]\";\n seen.add(nested);\n }\n return nested;\n },\n 2\n );\n }\n\n private buildToolUseId(context: ConversationContext, rawId: string): string {\n const scope =\n context.agentSessionId ||\n context.conversationId ||\n context.conversationObjectId ||\n \"codex\";\n return `${scope}:${rawId}`;\n }\n\n private stripAuthorizationHeader(config: any): any {\n if (!config || typeof config !== \"object\" || Array.isArray(config)) {\n return config;\n }\n\n const normalized = { ...config };\n if (\n normalized.bearer_token_env_var &&\n normalized.headers &&\n typeof normalized.headers === \"object\" &&\n !Array.isArray(normalized.headers)\n ) {\n const headers = { ...normalized.headers };\n delete headers[\"Authorization\"];\n if (Object.keys(headers).length === 0) {\n delete normalized.headers;\n } else {\n normalized.headers = headers;\n }\n }\n\n return normalized;\n }\n\n private flattenOverrideObject(\n prefix: string,\n value: any,\n target: Record<string, unknown>\n ): void {\n if (value === undefined) {\n return;\n }\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n target[prefix] = value;\n return;\n }\n\n const entries = Object.entries(value);\n if (!entries.length) {\n target[prefix] = {};\n return;\n }\n\n for (const [key, nested] of entries) {\n this.flattenOverrideObject(`${prefix}.${key}`, nested, target);\n }\n }\n\n private async resolveWorkspacePath(\n context: ConversationContext,\n config: ConversationConfig\n ): Promise<string> {\n let workspacePath: string;\n const workspaceId = config.workspaceId;\n const useWorktrees = config.useWorktrees !== false;\n\n if (config.runnerRepoPath) {\n workspacePath = config.runnerRepoPath;\n console.log(`[CodexManager] Using local workspace path ${workspacePath}`);\n\n if (context.conversationObjectType === \"Task\" && workspaceId) {\n const hasGitDir = await fs\n .access(path.join(workspacePath, \".git\"))\n .then(() => true)\n .catch(() => false);\n\n if (hasGitDir && useWorktrees) {\n const repoUrl = (config.repository?.url as string) || `file://${workspacePath}`;\n const baseBranch = (config.repository?.branch as string) || \"main\";\n\n const taskHandle = await this.repositoryManager.createTaskWorktree(\n context.conversationObjectId,\n workspaceId,\n repoUrl,\n baseBranch,\n config.githubToken\n );\n (context as any).taskHandle = taskHandle;\n workspacePath = taskHandle.worktreePath;\n }\n }\n return workspacePath;\n }\n\n if (\n context.conversationObjectType === \"Task\" &&\n config.repository &&\n workspaceId &&\n useWorktrees\n ) {\n if (!config.repository.url) {\n throw new Error(\"Repository URL is required for task conversations\");\n }\n\n const taskHandle = await this.repositoryManager.createTaskWorktree(\n context.conversationObjectId,\n workspaceId,\n config.repository.url,\n config.repository.branch,\n config.githubToken\n );\n (context as any).taskHandle = taskHandle;\n workspacePath = taskHandle.worktreePath;\n return workspacePath;\n }\n\n if (config.repository && workspaceId) {\n if (config.repository.type === \"local\" && config.repository.localPath) {\n workspacePath = config.repository.localPath;\n return workspacePath;\n }\n\n workspacePath = await this.repositoryManager.checkoutRepository(\n workspaceId,\n config.repository.url,\n config.repository.branch,\n config.githubToken\n );\n return workspacePath;\n }\n\n if (workspaceId) {\n workspacePath =\n await this.repositoryManager.getWorkspacePath(workspaceId);\n return workspacePath;\n }\n\n return process.cwd();\n }\n\n private async fetchGithubTokens(\n workspaceId: string\n ): Promise<string | undefined> {\n try {\n const response = await fetch(\n `${this.runner.config_.orchestratorUrl}/api/runner/tokens?workspaceId=${workspaceId}`,\n {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${process.env[\"NORTHFLARE_RUNNER_TOKEN\"]}`,\n },\n }\n );\n\n if (!response.ok) {\n console.error(\n `[CodexManager] Failed to fetch GitHub tokens: ${response.status}`\n );\n return undefined;\n }\n\n const data = (await response.json()) as { githubToken?: string };\n return data.githubToken;\n } catch (error) {\n console.error(\"[CodexManager] Error fetching GitHub tokens\", error);\n return undefined;\n }\n }\n\n private generateToolToken(context: ConversationContext): string | undefined {\n if (!context.config.mcpServers) return undefined;\n\n const runnerToken = process.env[\"NORTHFLARE_RUNNER_TOKEN\"];\n const runnerUid = this.runner.getRunnerUid();\n\n if (!runnerToken || !runnerUid) return undefined;\n\n return jwt.sign(\n {\n conversationId: context.conversationId,\n runnerUid,\n },\n runnerToken,\n {\n expiresIn: \"60m\",\n }\n );\n }\n\n /**\n * Detect whether incoming content contains multimodal blocks (image/document).\n */\n private hasMultimodalContent(value: any): boolean {\n if (!Array.isArray(value)) return false;\n return value.some(\n (item) =>\n item &&\n typeof item === \"object\" &&\n (item.type === \"image\" || item.type === \"document\")\n );\n }\n\n /**\n * Normalize incoming content into the Codex SDK Input shape.\n * - Text-only -> single string (lets SDK do fast path)\n * - Multimodal -> [{ text }, ...{ local_image }]\n */\n private async normalizeToInput(\n value: any,\n context: ConversationContext,\n forceInstructions: boolean\n ): Promise<Input> {\n if (Array.isArray(value) && this.hasMultimodalContent(value)) {\n const inputs: UserInput[] = [];\n\n // Collect any text blocks (or document placeholders) to keep context\n const textChunks: string[] = [];\n for (const item of value) {\n if (!item || typeof item !== \"object\") continue;\n if (item.type === \"text\" && typeof item.text === \"string\") {\n textChunks.push(item.text);\n } else if (item.type === \"document\" && item.source) {\n const docUrl =\n item.source.type === \"url\" ? item.source.url : item.source.data;\n if (docUrl) {\n textChunks.push(`[Document: ${docUrl}]`);\n }\n }\n }\n\n const textPart = this.buildPromptForMessage(\n context,\n textChunks.join(\" \").trim(),\n forceInstructions\n );\n if (textPart) {\n inputs.push({ type: \"text\", text: textPart });\n }\n\n // Download image blocks to temp files and attach as local_image\n const imagePaths: string[] = [];\n for (const item of value) {\n if (!item || typeof item !== \"object\" || item.type !== \"image\" || !item.source) {\n continue;\n }\n const imageUrl =\n item.source.type === \"url\" ? item.source.url : item.source.data;\n if (!imageUrl) continue;\n\n const localPath = await this.downloadImageToTemp(imageUrl);\n inputs.push({ type: \"local_image\", path: localPath });\n imagePaths.push(localPath);\n }\n\n // If no text and instructions were never injected, inject an empty prompt to carry instructions\n if (!inputs.some((i) => i.type === \"text\")) {\n const instructionOnly = this.buildPromptForMessage(context, \"\", forceInstructions);\n if (instructionOnly) {\n inputs.unshift({ type: \"text\", text: instructionOnly });\n }\n }\n\n if (isDebugEnabledFor(\"manager\") || isDebugEnabledFor(\"sdk\")) {\n console.log(\"[CodexManager] normalizeToInput multimodal\", {\n conversationId: context.conversationId,\n imageCount: imagePaths.length,\n imagePaths,\n textIncluded: inputs.some((i) => i.type === \"text\"),\n });\n }\n\n return inputs;\n }\n\n // Fallback to text-only path\n const messageText = this.normalizeToText(value);\n return this.buildPromptForMessage(context, messageText, forceInstructions);\n }\n\n /**\n * Download an image (http(s) or data URL) to a temp file and return the path.\n */\n private async downloadImageToTemp(url: string): Promise<string> {\n // Allow local filesystem paths to be passed through unchanged\n if (url.startsWith(\"/\") || url.startsWith(\"./\") || url.startsWith(\"../\")) {\n return path.isAbsolute(url) ? url : path.resolve(url);\n }\n\n // Handle data URLs (e.g., data:image/png;base64,...)\n if (url.startsWith(\"data:\")) {\n const commaIdx = url.indexOf(\",\");\n if (commaIdx === -1) {\n throw new Error(\"Invalid data URL for image\");\n }\n const header = url.slice(5, commaIdx); // remove \"data:\"\n const dataPart = url.slice(commaIdx + 1);\n const isBase64 = header.endsWith(\";base64\");\n const mime = header.replace(\";base64\", \"\");\n const ext = this.mimeToExtension(mime) || \"png\";\n const buffer = isBase64\n ? Buffer.from(dataPart, \"base64\")\n : Buffer.from(decodeURIComponent(dataPart), \"utf-8\");\n return await this.writeBufferToTemp(buffer, ext);\n }\n\n // Standard remote URL\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to download image (${response.status}) from ${url}`);\n }\n const arrayBuffer = await response.arrayBuffer();\n const buffer = Buffer.from(arrayBuffer);\n const ext = this.inferExtensionFromUrl(url) || \"png\";\n return await this.writeBufferToTemp(buffer, ext);\n }\n\n private async writeBufferToTemp(buffer: Buffer, ext: string): Promise<string> {\n const dir = path.join(tmpdir(), \"codex-images\");\n await fs.mkdir(dir, { recursive: true });\n const filename = `${crypto.randomUUID()}.${ext}`;\n const fullPath = path.join(dir, filename);\n await fs.writeFile(fullPath, buffer);\n return fullPath;\n }\n\n private inferExtensionFromUrl(url: string): string | null {\n try {\n const parsed = new URL(url);\n const pathname = parsed.pathname;\n const ext = path.extname(pathname);\n if (ext) {\n return ext.replace(\".\", \"\").split(/[?#]/)[0] || null;\n }\n } catch {\n // Not a valid URL; fall through\n }\n return null;\n }\n\n private mimeToExtension(mime: string): string | null {\n if (!mime) return null;\n const map: Record<string, string> = {\n \"image/png\": \"png\",\n \"image/jpeg\": \"jpg\",\n \"image/jpg\": \"jpg\",\n \"image/webp\": \"webp\",\n \"image/gif\": \"gif\",\n };\n return map[mime] || null;\n }\n\n private normalizeToText(value: any): string {\n if (typeof value === \"string\") return value;\n if (value == null) return \"\";\n\n if (typeof value === \"object\") {\n if (typeof (value as any).text === \"string\") {\n return (value as any).text;\n }\n if (Array.isArray(value)) {\n const texts = value\n .map((entry) => {\n if (\n entry &&\n typeof entry === \"object\" &&\n typeof entry.text === \"string\"\n ) {\n return entry.text;\n }\n return null;\n })\n .filter((entry): entry is string => Boolean(entry));\n if (texts.length) {\n return texts.join(\" \");\n }\n }\n if (typeof (value as any).content === \"string\") {\n return (value as any).content;\n }\n }\n\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n }\n\n private normalizeSessionId(value?: string | null): string | undefined {\n if (!value) return undefined;\n const trimmed = value.trim();\n return trimmed.length ? trimmed : undefined;\n }\n\n private resolveSessionId(\n config?: ConversationConfig,\n conversationData?: ConversationDetails,\n override?: string | null\n ): string {\n return (\n this.normalizeSessionId(override) ||\n this.normalizeSessionId(config?.sessionId) ||\n this.normalizeSessionId(conversationData?.agentSessionId) ||\n this.normalizeSessionId((conversationData as any)?.threadId) ||\n this.normalizeSessionId((conversationData as any)?.sessionId) ||\n \"\"\n );\n }\n\n private isAbortError(error: unknown): boolean {\n if (!error) return false;\n return (\n (error as any).name === \"AbortError\" ||\n /aborted|abort/i.test((error as any).message || \"\")\n );\n }\n\n private async _finalizeConversation(\n context: ConversationContext,\n hadError: boolean,\n error?: any,\n reason?: string\n ): Promise<void> {\n // Synchronous idempotency check - must happen before any async operations\n if ((context as any)._finalized) return;\n (context as any)._finalized = true;\n\n // Mark as completed immediately to prevent restart on catch-up\n // This is synchronous and happens before any async operations\n this.runner.markConversationCompleted(context.conversationId);\n\n // Clean up local state synchronously\n this.threadStates.delete(context.conversationId);\n this.runner.activeConversations_.delete(context.conversationId);\n statusLineManager.updateActiveCount(this.runner.activeConversations_.size);\n\n // Now do async notification (after all sync cleanup)\n try {\n await this.runner.notify(\"conversation.end\", {\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n agentSessionId: context.agentSessionId,\n isError: hadError,\n errorMessage: error?.message,\n reason,\n });\n } catch (notifyError) {\n console.error(\n \"[CodexManager] Failed to send conversation.end notification\",\n notifyError\n );\n }\n\n // Notify update coordinator that a conversation has ended\n // This may trigger an auto-update if one is pending and runner is now idle\n try {\n await this.runner.onConversationEnd();\n } catch (e) {\n console.error(\"[CodexManager] Failed to notify onConversationEnd:\", e);\n }\n }\n\n private async _handleConversationError(\n context: ConversationContext,\n error: Error\n ): Promise<void> {\n console.error(\n `[CodexManager] Conversation error for ${context.conversationId}:`,\n error\n );\n\n await this.runner.notify(\"error.report\", {\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n agentSessionId: context.agentSessionId,\n errorType: \"codex_error\",\n message: error.message,\n details: {\n stack: error.stack,\n timestamp: new Date(),\n },\n });\n }\n\n private generateMessageId(context: ConversationContext): string {\n return `${context.agentSessionId}-${Date.now()}-${Math.random()\n .toString(36)\n .slice(2)}`;\n }\n}\n","import type { CoreMessage } from 'ai';\nimport type { SDKMessage } from './sdk-types';\nimport { promises as fs } from 'fs';\nimport path from 'path';\n\n/**\n * Session data that includes messages in AI SDK CoreMessage format\n * This is used when integrating with the AI SDK Agent directly\n */\nexport interface CoreMessageSessionData {\n /** The conversation messages in AI SDK CoreMessage format */\n messages: CoreMessage[];\n /** Optional metadata that can be stored with the session */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Session data that includes messages in SDK format\n * This is used with the query() SDK interface\n */\nexport interface SDKSessionData {\n /** The conversation messages in SDK format */\n messages: SDKMessage[];\n /** Optional metadata that can be stored with the session */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Function type for loading a session from storage (CoreMessage format)\n * @param sessionId - The unique identifier of the session to load\n * @returns A promise that resolves to the session data, or null if not found\n */\nexport type LoadCoreSessionFunction = (sessionId: string) => Promise<CoreMessageSessionData | null>;\n\n/**\n * Function type for saving a session to storage (CoreMessage format)\n * @param sessionId - The unique identifier of the session to save\n * @param messages - The conversation messages to save\n * @returns A promise that resolves when the session is saved\n */\nexport type SaveCoreSessionFunction = (sessionId: string, messages: CoreMessage[]) => Promise<void>;\n\n/**\n * Function type for loading a session from storage (SDK format)\n * @param sessionId - The unique identifier of the session to load\n * @returns A promise that resolves to the session data, or null if not found\n */\nexport type LoadSDKSessionFunction = (sessionId: string) => Promise<SDKSessionData | null>;\n\n/**\n * Function type for saving a session to storage (SDK format)\n * @param sessionId - The unique identifier of the session to save\n * @param messages - The conversation messages to save\n * @returns A promise that resolves when the session is saved\n */\nexport type SaveSDKSessionFunction = (sessionId: string, messages: SDKMessage[]) => Promise<void>;\n\n/**\n * Simple file-based session storage implementation for SDK messages.\n *\n * This class provides a basic implementation of session persistence using the filesystem.\n * In production environments, consider using a database like PostgreSQL, MongoDB, or Redis instead.\n *\n * @example\n * ```typescript\n * import { FileSessionStorage, query } from '@northflare/agent';\n *\n * const storage = new FileSessionStorage('./sessions');\n *\n * const q = query({\n * prompt: 'Create a hello world script',\n * options: {\n * resume: 'my-session-id',\n * loadSession: (id) => storage.loadSession(id),\n * saveSession: (id, messages) => storage.saveSession(id, messages),\n * }\n * });\n * ```\n */\nexport class FileSessionStorage {\n /**\n * Creates a new FileSessionStorage instance\n * @param storageDir - The directory where session files will be stored\n */\n constructor(private storageDir: string) {\n fs.mkdir(storageDir, { recursive: true });\n }\n\n /**\n * Gets the file path for a session ID\n * @param sessionId - The session identifier\n * @returns The sanitized file path\n */\n private getPath(sessionId: string): string {\n // Sanitize session ID to prevent directory traversal\n const safeId = sessionId.replace(/[^a-zA-Z0-9-_]/g, '_');\n return path.join(this.storageDir, `${safeId}.json`);\n }\n\n /**\n * Loads a session from the filesystem\n * @param sessionId - The unique identifier of the session to load\n * @returns The session data, or null if not found\n */\n async loadSession(sessionId: string): Promise<SDKSessionData | null> {\n try {\n const content = await fs.readFile(this.getPath(sessionId), 'utf-8');\n return JSON.parse(content);\n } catch {\n return null;\n }\n }\n\n /**\n * Saves a session to the filesystem\n * @param sessionId - The unique identifier of the session to save\n * @param messages - The conversation messages to save\n */\n async saveSession(sessionId: string, messages: SDKMessage[]): Promise<void> {\n const filePath = this.getPath(sessionId);\n const directory = path.dirname(filePath);\n\n // Ensure the directory exists\n await fs.mkdir(directory, { recursive: true });\n\n await fs.writeFile(\n filePath,\n JSON.stringify({ messages }, null, 2)\n );\n }\n}","import type { ImageStorageAdapter } from './types';\n\n/**\n * Provides an in-memory ImageStorageAdapter for ephemeral and test scenarios.\n */\nexport class MemoryImageStorage implements ImageStorageAdapter {\n private images: Map<string, string | URL>;\n\n constructor() {\n this.images = new Map();\n }\n\n /**\n * Stores an image payload in memory.\n * @param id - Unique image identifier.\n * @param data - Image data (URL object or base64 string).\n * @returns Promise that resolves when storage is complete.\n */\n async saveImage(id: string, data: string | URL): Promise<void> {\n this.images.set(id, data);\n }\n\n /**\n * Loads an image payload by identifier.\n * @param id - Unique image identifier.\n * @returns Stored image data.\n * @throws Error when the image cannot be found.\n */\n async loadImage(id: string): Promise<string | URL> {\n const image = this.images.get(id);\n if (!image) {\n throw new Error(`Image not found: ${id}`);\n }\n return image;\n }\n\n /**\n * Removes an image from memory.\n * @param id - Unique image identifier.\n * @returns Promise that resolves after deletion.\n */\n async deleteImage(id: string): Promise<void> {\n this.images.delete(id);\n }\n\n /**\n * Lists all stored image identifiers.\n * @returns Array of stored image IDs.\n */\n async listImages(): Promise<string[]> {\n return Array.from(this.images.keys());\n }\n\n /**\n * Clears all stored images.\n */\n clear(): void {\n this.images.clear();\n }\n\n /**\n * Reports the number of stored images.\n * @returns Count of stored images.\n */\n get size(): number {\n return this.images.size;\n }\n}\n","import { promises as fs } from 'node:fs';\nimport { join } from 'node:path';\nimport type { ImageStorageAdapter } from './types';\nimport { sanitizeImageId } from '../util/image-utils';\n\n/**\n * Default storage directory for images\n */\nconst DEFAULT_STORAGE_DIR = '.agent/images';\n\n/**\n * Persists images to the local filesystem for tool-based vision workflows.\n */\nexport class FilesystemImageStorage implements ImageStorageAdapter {\n private storageDir: string;\n\n constructor(storageDir: string = DEFAULT_STORAGE_DIR) {\n this.storageDir = storageDir;\n }\n\n /**\n * Ensures the storage directory exists.\n * @returns Promise that resolves once the directory is ready.\n */\n private async ensureStorageDir(): Promise<void> {\n try {\n await fs.mkdir(this.storageDir, { recursive: true });\n } catch (error) {\n throw new Error(`Failed to create storage directory: ${error}`);\n }\n }\n\n /**\n * Gets the on-disk path for an image identifier.\n * @param id - Image identifier to resolve.\n * @returns Absolute file path for the image metadata.\n */\n private getImagePath(id: string): string {\n const sanitizedId = sanitizeImageId(id);\n return join(this.storageDir, `${sanitizedId}.json`);\n }\n\n /**\n * Writes image data to disk.\n * @param id - Image identifier.\n * @param data - Image payload (URL or base64 string).\n * @returns Promise that resolves when the image is saved.\n */\n async saveImage(id: string, data: string | URL): Promise<void> {\n await this.ensureStorageDir();\n const imagePath = this.getImagePath(id);\n\n // Store both URLs and base64 data as JSON for consistency\n const imageData = {\n id,\n data: data instanceof URL ? data.href : data,\n type: data instanceof URL ? 'url' : 'base64',\n savedAt: new Date().toISOString()\n };\n\n try {\n await fs.writeFile(imagePath, JSON.stringify(imageData, null, 2), 'utf-8');\n } catch (error) {\n throw new Error(`Failed to save image ${id}: ${error}`);\n }\n }\n\n /**\n * Reads image data from disk.\n * @param id - Image identifier.\n * @returns Image payload as URL instance or base64 string.\n */\n async loadImage(id: string): Promise<string | URL> {\n const imagePath = this.getImagePath(id);\n\n try {\n const fileContent = await fs.readFile(imagePath, 'utf-8');\n const imageData = JSON.parse(fileContent);\n\n if (imageData.type === 'url') {\n return new URL(imageData.data);\n }\n return imageData.data;\n } catch (error) {\n if ((error as any).code === 'ENOENT') {\n throw new Error(`Image not found: ${id}`);\n }\n throw new Error(`Failed to load image ${id}: ${error}`);\n }\n }\n\n /**\n * Removes a stored image file.\n * @param id - Image identifier.\n * @returns Promise that resolves after deletion.\n */\n async deleteImage(id: string): Promise<void> {\n const imagePath = this.getImagePath(id);\n\n try {\n await fs.unlink(imagePath);\n } catch (error) {\n if ((error as any).code !== 'ENOENT') {\n throw new Error(`Failed to delete image ${id}: ${error}`);\n }\n // Ignore if file doesn't exist\n }\n }\n\n /**\n * Lists all stored image identifiers.\n * @returns Array of stored image IDs.\n */\n async listImages(): Promise<string[]> {\n try {\n await this.ensureStorageDir();\n const files = await fs.readdir(this.storageDir);\n\n // Filter for JSON files and extract IDs\n return files\n .filter(file => file.endsWith('.json'))\n .map(file => file.replace('.json', ''));\n } catch (error) {\n if ((error as any).code === 'ENOENT') {\n return [];\n }\n throw new Error(`Failed to list images: ${error}`);\n }\n }\n\n /**\n * Cleans up all stored images.\n * @returns Promise that resolves when cleanup finishes.\n */\n async clearAll(): Promise<void> {\n const images = await this.listImages();\n await Promise.all(images.map(id => this.deleteImage(id)));\n }\n}\n\n// Create default instance with default storage directory\nconst defaultStorage = new FilesystemImageStorage();\n\n// Export default adapter functions that can be used directly with Options\nexport const saveImage: ImageStorageAdapter['saveImage'] = (id, data) => defaultStorage.saveImage(id, data);\nexport const loadImage: ImageStorageAdapter['loadImage'] = (id) => defaultStorage.loadImage(id);\nexport const deleteImage: ImageStorageAdapter['deleteImage'] = (id) => defaultStorage.deleteImage!(id);\nexport const listImages: ImageStorageAdapter['listImages'] = () => defaultStorage.listImages!();\n\n// Also export the class for custom configurations\nexport default FilesystemImageStorage;\n","/**\n * NorthflareAgentManager - Manages conversations using the @northflare/agent SDK\n *\n * Mirrors the existing Claude integration but targets OpenRouter-style models\n * via the Northflare Agent SDK. Lifecycle, repository handling, and message\n * normalization stay aligned with the existing managers so downstream\n * interfaces remain compatible.\n */\n\nimport { query as sdkQuery } from \"@northflare/agent\";\nimport { createGroq, groq as groqProvider } from \"@ai-sdk/groq\";\nimport { createOpenRouter } from \"@openrouter/ai-sdk-provider\";\n// Keep SDKMessage loosely typed to avoid tight coupling to SDK typings\ntype SDKMessage = any;\nimport { IRunnerApp } from \"../types/runner-interface.js\";\nimport { EnhancedRepositoryManager } from \"./enhanced-repository-manager.js\";\nimport {\n ConversationContext,\n ConversationConfig,\n Message,\n} from \"../types/index.js\";\nimport { statusLineManager } from \"../utils/status-line.js\";\nimport { createScopedConsole } from \"../utils/console.js\";\nimport { expandEnv } from \"../utils/expand-env.js\";\nimport { isDebugEnabledFor } from \"../utils/debug.js\";\nimport jwt from \"jsonwebtoken\";\nimport fs from \"fs/promises\";\nimport path from \"path\";\nimport { simpleGit } from \"simple-git\";\n\nconst console = createScopedConsole(\n isDebugEnabledFor(\"manager\") ? \"manager\" : \"sdk\"\n);\n\nfunction buildSystemPromptWithNorthflare(\n basePrompt?: string,\n northflarePrompt?: string\n): string | undefined {\n const parts = [northflarePrompt, basePrompt]\n .filter((p): p is string => typeof p === \"string\" && p.trim().length > 0)\n .map((p) => p.trim());\n\n if (parts.length === 0) return undefined;\n return parts.join(\"\\n\\n\");\n}\n\nexport class NorthflareAgentManager {\n private runner: IRunnerApp;\n private repositoryManager: EnhancedRepositoryManager;\n private submitToolUseIds: Map<string, Set<string>> = new Map(); // conversationId -> Set of submit tool_use_ids\n\n constructor(\n runner: IRunnerApp,\n repositoryManager: EnhancedRepositoryManager\n ) {\n this.runner = runner;\n this.repositoryManager = repositoryManager;\n\n // Log debug mode status\n if (isDebugEnabledFor(\"sdk\")) {\n console.log(\n \"[NorthflareAgentManager] DEBUG MODE ENABLED - Northflare Agent SDK will log verbose output\"\n );\n }\n\n // Note: MCP host configuration is passed from orchestrator\n // Runner does not define its own MCP tools\n this.setupInternalMcpServer();\n }\n\n private setupInternalMcpServer(): void {\n // Runner does not define its own MCP tools\n // All MCP tool configuration is passed from orchestrator in conversation config\n }\n\n private buildSubAgentConfig(subAgentTypes?: Record<string, any>): {\n enabled: boolean;\n agents: Record<\n string,\n { description: string; prompt: string; model?: string }\n >;\n } {\n const enabled = subAgentTypes?.[\"enabled\"] !== false;\n const allowInherit = subAgentTypes?.[\"inherit\"] !== false;\n\n if (!enabled) {\n return { enabled: false, agents: {} };\n }\n\n const agents: Record<\n string,\n { description: string; prompt: string; model?: string }\n > = {};\n\n if (allowInherit) {\n agents[\"inherit\"] = {\n description: \"Use the main task model and toolset.\",\n prompt: \"\",\n model: \"inherit\",\n };\n }\n\n const RESERVED = new Set([\"inherit\", \"enabled\"]);\n\n Object.entries(subAgentTypes || {}).forEach(([name, value]) => {\n if (RESERVED.has(name)) return;\n if (!value || typeof value !== \"object\") return;\n\n const description =\n typeof (value as any).description === \"string\" &&\n (value as any).description.trim().length\n ? (value as any).description.trim()\n : `Use agentType \\\"${name}\\\" when its specialization fits the task.`;\n\n const prompt =\n typeof (value as any).instructions === \"string\"\n ? (value as any).instructions.trim()\n : \"\";\n\n const model =\n typeof (value as any).model === \"string\" &&\n (value as any).model.trim().length\n ? (value as any).model.trim()\n : \"inherit\";\n\n agents[name] = {\n description,\n prompt,\n model,\n };\n });\n\n if (Object.keys(agents).length === 0) {\n return { enabled: false, agents: {} };\n }\n\n return { enabled: true, agents };\n }\n\n async startConversation(\n conversationObjectType: \"Task\" | \"TaskPlan\" | \"ProjectStep\",\n conversationObjectId: string,\n config: ConversationConfig,\n initialMessages: Message[],\n conversationData?: {\n id: string;\n objectType: string;\n objectId: string;\n model: string;\n summary?: string | null;\n globalInstructions: string;\n workspaceInstructions: string;\n permissionsMode: string;\n agentSessionId: string;\n systemPrompt?: string;\n northflareSystemPrompt?: string;\n systemPromptMode?: \"append\" | \"replace\";\n },\n provider: \"openrouter\" | \"groq\" = \"openrouter\"\n ): Promise<ConversationContext> {\n // Returns conversation context\n // Greenfield: conversationData.id is required as the authoritative DB conversation ID\n if (!conversationData?.id) {\n throw new Error(\n \"startConversation requires conversationData with a valid conversation.id\"\n );\n }\n // Use sessionId from config if resuming, or agentSessionId from conversationData if available\n const agentSessionId =\n config.sessionId || conversationData.agentSessionId || \"\";\n const conversationId = conversationData.id;\n const rawModel =\n conversationData?.model ||\n (config as any)?.model ||\n (config as any)?.defaultModel;\n\n if (!rawModel) {\n throw new Error(\n \"Model is required for Northflare conversations (provide conversationData.model, config.model, or config.defaultModel).\"\n );\n }\n const model = this.normalizeModel(rawModel);\n const useWorktrees = config.useWorktrees !== false;\n const pendingSummary =\n this.runner.consumePendingConversationSummary(conversationId);\n const rawSummary =\n typeof conversationData.summary === \"string\"\n ? conversationData.summary\n : pendingSummary;\n const normalizedSummary =\n typeof rawSummary === \"string\"\n ? rawSummary.replace(/\\s+/g, \" \").trim()\n : null;\n\n const context: ConversationContext = {\n conversationId,\n agentSessionId, // Will be updated by onSessionId callback for new conversations\n conversationObjectType,\n conversationObjectId,\n taskId:\n conversationObjectType === \"Task\" ? conversationObjectId : undefined,\n workspaceId: config.workspaceId,\n status: \"starting\",\n config,\n startedAt: new Date(),\n lastActivityAt: new Date(),\n // Add conversation details if provided\n model,\n summary: normalizedSummary,\n globalInstructions: conversationData?.globalInstructions || \"\",\n workspaceInstructions: conversationData?.workspaceInstructions || \"\",\n permissionsMode: conversationData?.permissionsMode || \"all\",\n provider,\n };\n\n // Store with conversation.id as the key\n this.runner.activeConversations_.set(conversationId, context);\n console.log(`[NorthflareAgentManager] Stored conversation context:`, {\n conversationId,\n agentSessionId: context.agentSessionId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n mapSize: this.runner.activeConversations_.size,\n allKeys: Array.from(this.runner.activeConversations_.keys()),\n });\n\n const workspaceId = config.workspaceId;\n\n // Checkout repository if specified\n let workspacePath: string;\n\n // Check if this is a local workspace by looking for runnerRepoPath in config\n if (config.runnerRepoPath) {\n // Local workspace - use the provided path directly\n workspacePath = config.runnerRepoPath;\n console.log(`Using local workspace path: ${workspacePath}`);\n\n // For task conversations, isolate the worktree/branch when the repo has a .git directory\n if (conversationObjectType === \"Task\" && workspaceId) {\n const hasGitDir = await fs\n .access(path.join(workspacePath, \".git\"))\n .then(() => true)\n .catch(() => false);\n\n if (hasGitDir && useWorktrees) {\n const repoUrl = (config.repository?.url as string) || `file://${workspacePath}`;\n const baseBranch = (config.repository?.branch as string) || \"main\";\n\n const taskHandle = await this.repositoryManager.createTaskWorktree(\n conversationObjectId,\n workspaceId,\n repoUrl,\n baseBranch,\n config.githubToken\n );\n workspacePath = taskHandle.worktreePath;\n (context as any).taskHandle = taskHandle;\n }\n }\n } else if (\n conversationObjectType === \"Task\" &&\n config.repository &&\n workspaceId &&\n useWorktrees\n ) {\n // Use task-specific worktree for all task conversations (keeps shared workspace checkout clean)\n console.log(\n `[NorthflareAgentManager] Creating task worktree with repository config:`,\n {\n conversationObjectId,\n workspaceId,\n repository: config.repository,\n hasUrl: !!config.repository.url,\n url: config.repository.url,\n branch: config.repository.branch,\n type: config.repository.type,\n }\n );\n\n // Check if repository.url is missing\n if (!config.repository.url) {\n throw new Error(\n `Repository URL is missing in config for task ${conversationObjectId}. Repository config: ${JSON.stringify(\n config.repository\n )}`\n );\n }\n\n const taskHandle = await this.repositoryManager.createTaskWorktree(\n conversationObjectId,\n workspaceId,\n config.repository.url,\n config.repository.branch,\n config.githubToken\n );\n workspacePath = taskHandle.worktreePath;\n\n // Store task handle information in context for later use\n (context as any).taskHandle = taskHandle;\n } else if (config.repository && workspaceId) {\n // Check if it's a local repository\n if (config.repository.type === \"local\" && config.repository.localPath) {\n // Use the local path directly\n workspacePath = config.repository.localPath;\n console.log(`Using local repository path: ${workspacePath}`);\n } else {\n // Fall back to workspace-based checkout for non-task conversations\n workspacePath = await this.repositoryManager.checkoutRepository(\n workspaceId,\n config.repository.url,\n config.repository.branch,\n config.githubToken\n );\n }\n } else if (workspaceId) {\n workspacePath =\n await this.repositoryManager.getWorkspacePath(workspaceId);\n } else {\n // Default workspace path when no workspaceId is provided\n workspacePath = process.cwd();\n }\n\n // Fetch GitHub tokens from orchestrator API if we have a workspaceId\n const githubToken = workspaceId\n ? await this.fetchGithubTokens(workspaceId)\n : undefined;\n\n // Generate TOOL_TOKEN for MCP tools authentication\n let toolToken: string | undefined;\n if (config.mcpServers && Object.keys(config.mcpServers).length > 0) {\n const runnerToken = process.env[\"NORTHFLARE_RUNNER_TOKEN\"];\n const runnerUid = this.runner.getRunnerUid();\n\n if (runnerToken && runnerUid && context.conversationId) {\n // Sign JWT with runner's token\n toolToken = jwt.sign(\n {\n conversationId: context.conversationId,\n runnerUid: runnerUid,\n },\n runnerToken,\n {\n expiresIn: \"60m\", // 60 minutes expiry\n }\n );\n console.log(\n \"[NorthflareAgentManager] Generated TOOL_TOKEN for MCP authentication\"\n );\n } else {\n console.warn(\n \"[NorthflareAgentManager] Unable to generate TOOL_TOKEN - missing required data\"\n );\n }\n }\n\n const managerDebug = isDebugEnabledFor(\"manager\");\n const sdkDebug = isDebugEnabledFor(\"sdk\");\n const debugEnabled = managerDebug || sdkDebug;\n\n // Simplified SDK configuration - using native query API with streamlined options\n\n // Simplified environment configuration\n const envVars: Record<string, string> = {\n ...(Object.fromEntries(\n Object.entries(process.env).filter(([_, value]) => value !== undefined)\n ) as Record<string, string>), // Preserve parent environment, filter out undefined values\n };\n\n if (config.anthropicApiKey) {\n envVars[\"ANTHROPIC_API_KEY\"] = config.anthropicApiKey;\n }\n\n // OpenRouter / Groq API key support (prefer provider-specific fields)\n const openRouterApiKey =\n (config as any).openRouterApiKey || process.env[\"OPENROUTER_API_KEY\"];\n const groqApiKey =\n (config as any).groqApiKey || process.env[\"GROQ_API_KEY\"];\n\n if (openRouterApiKey) {\n envVars[\"OPENROUTER_API_KEY\"] = openRouterApiKey;\n }\n\n if (groqApiKey) {\n envVars[\"GROQ_API_KEY\"] = groqApiKey;\n }\n\n // Pass through OpenAI API key if supplied for provider-prefixed models\n if ((config as any).openaiApiKey) {\n envVars[\"OPENAI_API_KEY\"] = (config as any).openaiApiKey as string;\n }\n\n if (githubToken) {\n envVars[\"GITHUB_TOKEN\"] = githubToken;\n }\n\n if (toolToken) {\n envVars[\"TOOL_TOKEN\"] = toolToken;\n }\n\n if (sdkDebug) {\n envVars[\"DEBUG\"] = \"1\";\n }\n\n const subAgentConfig = this.buildSubAgentConfig(\n config.subAgentTypes as any\n );\n\n const agentsOption =\n subAgentConfig.enabled && Object.keys(subAgentConfig.agents).length > 0\n ? subAgentConfig.agents\n : undefined;\n\n // Simplified system prompt handling\n const providedSystemPrompt = buildSystemPromptWithNorthflare(\n config.systemPrompt || (conversationData as any)?.systemPrompt,\n (config as any)?.northflareSystemPrompt ||\n (conversationData as any)?.northflareSystemPrompt\n );\n\n const systemPromptMode =\n config.systemPromptMode ||\n (conversationData as any)?.systemPromptMode ||\n // Default ProjectStep conversations to append so preset stays intact\n \"append\";\n\n let systemPromptOption: any;\n if (providedSystemPrompt) {\n if (systemPromptMode === \"replace\") {\n systemPromptOption = providedSystemPrompt;\n } else {\n systemPromptOption = {\n type: \"preset\" as const,\n preset: \"claude_code\" as const,\n append: providedSystemPrompt,\n };\n }\n }\n\n // Debug log the systemPrompt being sent to Northflare Agent SDK\n console.log(\n `[NorthflareAgentManager] System prompt configuration for conversation ${context.conversationId}:`,\n {\n mode: systemPromptMode,\n hasProvidedSystemPrompt: Boolean(providedSystemPrompt),\n finalPromptType: typeof systemPromptOption,\n finalPromptLength:\n typeof systemPromptOption === \"string\"\n ? systemPromptOption.length\n : (systemPromptOption as any)?.append?.length ?? 0,\n }\n );\n\n // Tool restrictions based on permissions mode\n // \"read\" = read-only mode (no file writes, no shell)\n // \"project\" = no file writes but allows bash, no subagents (for Project conversation)\n const readOnlyTools = [\n \"write_file\",\n \"edit_file\",\n \"multi_edit_file\",\n \"delete_file\",\n \"move_file\",\n \"copy_file\",\n \"run_command\",\n \"todo_write\",\n ];\n const projectModeTools = [\n \"write_file\",\n \"edit_file\",\n \"multi_edit_file\",\n \"delete_file\",\n \"move_file\",\n \"copy_file\",\n \"todo_write\",\n \"task\",\n ];\n const disallowedTools: string[] =\n context.permissionsMode === \"read\"\n ? readOnlyTools\n : context.permissionsMode === \"project\"\n ? projectModeTools\n : [];\n\n if (!subAgentConfig.enabled) {\n disallowedTools.push(\"task\");\n }\n\n if (disallowedTools.length) {\n console.log(\"[NorthflareAgentManager] Tool restrictions applied\", {\n disallowedTools,\n });\n }\n\n // Simplified MCP server configuration\n let mcpServers: Record<string, any> | undefined;\n if (config.mcpServers) {\n mcpServers = expandEnv(config.mcpServers, { TOOL_TOKEN: toolToken });\n console.log(\n \"[NorthflareAgentManager] MCP servers configuration:\",\n JSON.stringify(mcpServers, null, 2)\n );\n }\n\n if (debugEnabled) {\n console.log(\"[NorthflareAgentManager] SDK launch summary\", {\n conversationId: context.conversationId,\n model,\n provider,\n cwd: workspacePath,\n hasMcpServers: !!mcpServers && Object.keys(mcpServers).length > 0,\n disallowedTools,\n systemPromptMode,\n hasSystemPrompt: Boolean(systemPromptOption),\n systemPromptType: typeof systemPromptOption,\n subAgentsEnabled: subAgentConfig.enabled,\n agentTypes: agentsOption ? Object.keys(agentsOption) : [],\n env: {\n OPENROUTER_API_KEY: Boolean(envVars[\"OPENROUTER_API_KEY\"]),\n GROQ_API_KEY: Boolean(envVars[\"GROQ_API_KEY\"]),\n ANTHROPIC_API_KEY: Boolean(envVars[\"ANTHROPIC_API_KEY\"]),\n OPENAI_API_KEY: Boolean(envVars[\"OPENAI_API_KEY\"]),\n GITHUB_TOKEN: Boolean(envVars[\"GITHUB_TOKEN\"]),\n TOOL_TOKEN: Boolean(envVars[\"TOOL_TOKEN\"]),\n },\n });\n }\n\n // Create input stream for user messages (simplified message queueing)\n const input = createUserMessageStream();\n\n // NOTE: different @ai-sdk/provider versions (v2 via @northflare/agent and\n // v3 via @ai-sdk/groq/ai) can lead to nominally incompatible LanguageModel\n // types. We only need runtime compatibility here, so coerce to `any` to\n // avoid TS conflicts between the duplicated provider packages.\n // Build provider-specific model instance. OpenRouter requires an explicit\n // client factory instead of the generic model string.\n const sdkModel: any = (() => {\n if (provider === \"groq\") {\n const groqClient =\n groqApiKey && groqApiKey.length > 0\n ? createGroq({ apiKey: groqApiKey })\n : groqProvider;\n return groqClient(context.model) as any;\n }\n\n if (provider === \"openrouter\") {\n const client = createOpenRouter({\n apiKey: openRouterApiKey || process.env[\"OPENROUTER_API_KEY\"] || \"\",\n });\n return client(context.model);\n }\n\n return context.model;\n })();\n\n // Respect a maxTurns override if provided (falls back to SDK default when unset)\n const maxTurns = Number.isFinite((config as any).maxTurns)\n ? (config as any).maxTurns\n : undefined;\n\n // Log how the model was resolved to help compare with the standalone script\n console.log(\"[NorthflareAgentManager] Model resolution\", {\n provider,\n rawModel: rawModel,\n normalizedModel: context.model,\n openRouterApiKeyPresent: Boolean(\n openRouterApiKey || process.env[\"OPENROUTER_API_KEY\"]\n ),\n sdkModelType: (sdkModel as any)?.constructor?.name,\n });\n\n // Build a modelResolver for sub-agents that can resolve model strings to LanguageModel instances\n const modelResolver = (modelId: string) => {\n // Normalize the model ID (strip provider prefixes)\n const normalizedModelId = this.normalizeModel(modelId);\n\n // Determine the provider from the model ID prefix or fall back to the parent provider\n let modelProvider = provider;\n if (modelId.startsWith(\"groq:\") || modelId.startsWith(\"groq/\")) {\n modelProvider = \"groq\";\n } else if (\n modelId.startsWith(\"openrouter:\") ||\n modelId.startsWith(\"openrouter/\")\n ) {\n modelProvider = \"openrouter\";\n }\n\n // Create the appropriate model instance\n if (modelProvider === \"groq\") {\n const groqClient =\n groqApiKey && groqApiKey.length > 0\n ? createGroq({ apiKey: groqApiKey })\n : groqProvider;\n return groqClient(normalizedModelId) as any;\n }\n\n if (modelProvider === \"openrouter\") {\n const client = createOpenRouter({\n apiKey: openRouterApiKey || process.env[\"OPENROUTER_API_KEY\"] || \"\",\n });\n return client(normalizedModelId);\n }\n\n // Unknown provider - return undefined to let SDK throw a helpful error\n return undefined;\n };\n\n // Launch SDK with simplified configuration\n let silenceTimer: NodeJS.Timeout | null = null;\n let lastSdkActivity = Date.now();\n\n const handleTaskProgress = async (update: {\n progressPercent?: number;\n toolCallId?: string;\n raw?: unknown;\n }) => {\n const pct = Number(update?.progressPercent);\n if (!Number.isFinite(pct)) return;\n\n const clamped = Math.max(0, Math.min(100, pct));\n const messageId = `${context.agentSessionId}-progress-${Date.now()}-${Math.random()\n .toString(36)\n .slice(2, 8)}`;\n\n const progressPayload: any = {\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n agentSessionId: context.agentSessionId,\n type: \"assistant\",\n subtype: \"task_progress\",\n messageMetaType: \"task_progress\",\n metadata: {\n progressPercent: clamped,\n toolCallId: update?.toolCallId,\n raw: update?.raw,\n },\n content: [\n {\n type: \"text\",\n text: `Task progress ${Math.round(clamped)}%`,\n },\n ],\n messageId,\n };\n\n try {\n await this.runner.notify(\"message.agent\", progressPayload);\n } catch (err) {\n console.warn(\"[NorthflareAgentManager] Failed to send task progress\", {\n conversationId: context.conversationId,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n };\n\n const sdk = sdkQuery({\n prompt: input.iterable,\n options: {\n cwd: workspacePath,\n env: envVars,\n model: sdkModel,\n modelResolver,\n resume:\n config.sessionId || conversationData?.agentSessionId || undefined,\n // Enable vision support - allows passing images directly to the model\n visionModel: true,\n ...(agentsOption ? { agents: agentsOption } : {}),\n ...(maxTurns !== undefined ? { maxTurns } : {}),\n ...(systemPromptOption ? { systemPrompt: systemPromptOption } : {}),\n ...(disallowedTools.length ? { disallowedTools } : {}),\n ...(mcpServers ? { mcpServers } : {}),\n conversationId: context.conversationId,\n conversationObjectId: context.conversationObjectId,\n taskId: context.taskId,\n onTaskProgress: handleTaskProgress,\n ...(sdkDebug\n ? {\n debug: true,\n stderr: (data: string) => {\n try {\n console.log(`[Northflare Agent SDK] ${data}`);\n } catch {}\n },\n onStepFinish: (step: any) => {\n try {\n console.log(\n \"[NorthflareAgentManager] Agent step finished (full step object): \" +\n JSON.stringify(step, null, 2)\n );\n } catch {}\n },\n }\n : {}),\n },\n });\n\n console.log(\"[NorthflareAgentManager] sdkQuery options summary\", {\n provider,\n model: context.model,\n cwd: workspacePath,\n maxTurns: maxTurns ?? \"default (SDK)\",\n hasSystemPrompt: Boolean(systemPromptOption),\n hasMcpServers: Boolean(mcpServers && Object.keys(mcpServers).length),\n disallowedToolsCount: disallowedTools.length,\n envKeys: Object.keys(envVars),\n });\n\n // Track number of streamed messages to aid debugging when sessions appear silent\n let streamedMessageCount = 0;\n const clearSilenceTimer = () => {\n if (silenceTimer) {\n clearInterval(silenceTimer);\n silenceTimer = null;\n }\n };\n\n // Simplified conversation wrapper - reduced complexity while maintaining interface\n const conversation = createConversationWrapper(\n sdk,\n input,\n async (hadError: boolean, error?: any) => {\n // Check if SDK reported an error via result message (stored in metadata)\n const sdkError = context.metadata?.[\"_sdkError\"];\n const effectiveHadError = hadError || sdkError?.isError === true;\n const effectiveError =\n error ||\n (sdkError?.isError\n ? new Error(sdkError.errorMessage || \"SDK execution error\")\n : undefined);\n\n console.log(\"[NorthflareAgentManager] SDK stream completed\", {\n conversationId: context.conversationId,\n agentSessionId: context.agentSessionId,\n hadError,\n sdkErrorDetected: sdkError?.isError,\n effectiveHadError,\n errorMessage: effectiveError?.message,\n streamedMessageCount,\n });\n clearSilenceTimer();\n\n // Surface SDK-level failures to the orchestrator so the task\n // transitions to needs_attention and an error bubble appears in chat.\n if (effectiveHadError && effectiveError) {\n try {\n const normalizedError =\n effectiveError instanceof Error\n ? effectiveError\n : new Error(String(effectiveError));\n await this._handleConversationError(context, normalizedError);\n } catch (err) {\n console.error(\n \"[NorthflareAgentManager] Failed to report SDK error:\",\n err\n );\n }\n }\n\n await this._handleRunCompletion(context, effectiveHadError, effectiveError);\n }\n );\n\n // Store conversation instance in context for reuse\n context.conversation = conversation as any;\n (context as any)._clearSilenceTimer = clearSilenceTimer;\n\n // Observe session id from first messages that include it\n conversation.onSessionId(async (agentSessionId: string) => {\n if (!agentSessionId) return;\n const oldSessionId = context.agentSessionId;\n if (oldSessionId !== agentSessionId) {\n context.agentSessionId = agentSessionId;\n context.status = \"active\";\n await this.runner.notify(\"agentSessionId.changed\", {\n conversationId: context.conversationId,\n conversationObjectType,\n conversationObjectId,\n oldAgentSessionId: oldSessionId,\n newAgentSessionId: agentSessionId,\n });\n }\n });\n\n // Set up streaming message handler\n const messageHandler = async (\n message: SDKMessage,\n sessionId: string | null\n ) => {\n streamedMessageCount += 1;\n lastSdkActivity = Date.now();\n\n // Lightweight visibility into every SDK message before normalization\n try {\n const preview = (() => {\n if (!message) return null;\n if (typeof message === \"string\") return message.slice(0, 300);\n\n const m: any = message;\n const content =\n m?.message?.content || m?.content || m?.message?.text || m?.text;\n\n if (typeof content === \"string\") return content.slice(0, 300);\n\n if (Array.isArray(content)) {\n const textBlock = content.find(\n (b: any) => b && b.type === \"text\" && typeof b.text === \"string\"\n );\n if (textBlock) return textBlock.text.slice(0, 300);\n }\n\n try {\n return JSON.stringify(message).slice(0, 300);\n } catch {\n return \"[unstringifiable message]\";\n }\n })();\n\n console.log(\"[NorthflareAgentManager] Agent stream message\", {\n conversationId: context.conversationId,\n agentSessionId: sessionId || context.agentSessionId,\n count: streamedMessageCount,\n type: (message as any)?.type,\n preview,\n });\n } catch (e) {\n console.warn(\n \"[NorthflareAgentManager] Failed to log early agent stream message:\",\n e\n );\n }\n\n await this.handleStreamedMessage(context, message, sessionId);\n\n // Heuristic: detect terminal system events and finalize\n try {\n if (message?.type === \"system\") {\n const m: any = message;\n const subtype = m.subtype || m?.message?.subtype || m?.event;\n const exitSignals = [\n \"exit\",\n \"exiting\",\n \"session_end\",\n \"conversation_end\",\n \"process_exit\",\n \"done\",\n \"completed\",\n ];\n if (subtype && exitSignals.includes(String(subtype))) {\n await this._handleRunCompletion(context, false);\n }\n }\n } catch (e) {\n console.warn(\n \"[NorthflareAgentManager] finalize-on-system heuristic error:\",\n e\n );\n }\n };\n\n if (managerDebug) {\n silenceTimer = setInterval(() => {\n const now = Date.now();\n const idleMs = now - lastSdkActivity;\n if (idleMs >= 5000) {\n console.log(\"[NorthflareAgentManager] Waiting for agent output\", {\n conversationId: context.conversationId,\n agentSessionId: context.agentSessionId || null,\n streamedMessageCount,\n idleMs,\n });\n }\n }, 5000);\n }\n\n // Send initial messages BEFORE starting the stream.\n // This ensures all initial messages are queued and available when the SDK\n // starts iterating, so it can collect them all without timing issues.\n try {\n for (const message of initialMessages) {\n // Use normalizeContentForSDK to preserve multimodal content (images)\n const normalizedContent = this.normalizeContentForSDK(message.content);\n const isMultimodal = Array.isArray(normalizedContent);\n\n console.log(\"[NorthflareAgentManager] Sending initial message to SDK\", {\n conversationId: context.conversationId,\n agentSessionId: context.agentSessionId,\n isMultimodal,\n contentPreview: isMultimodal\n ? `[${normalizedContent.length} blocks: ${normalizedContent.map((b: any) => b.type).join(\", \")}]`\n : (normalizedContent as string).slice(0, 200),\n length: isMultimodal ? normalizedContent.length : (normalizedContent as string).length,\n });\n\n if (isMultimodal) {\n // Send multimodal content blocks directly to the SDK\n conversation.send({\n type: \"multimodal\",\n content: normalizedContent as Array<{ type: string; text?: string; image?: string }>,\n });\n } else {\n conversation.send({\n type: \"text\",\n text: normalizedContent as string,\n });\n }\n }\n\n // Kick off streaming; completion/error is handled by the wrapper's\n // onComplete callback above. (The stream method returns void, so awaiting\n // it would resolve immediately and incorrectly mark the conversation\n // finished.)\n conversation.stream(messageHandler);\n\n // Note: Error handling is done via process completion handler\n // The Northflare Agent SDK doesn't have an onError method on conversations\n\n console.log(\n `Started conversation for ${conversationObjectType} ${conversationObjectId} in workspace ${workspacePath}`\n );\n\n // Return the conversation context directly\n return context;\n } catch (error) {\n // Handle startup errors\n await this._handleConversationError(context, error as Error);\n throw error;\n }\n }\n\n async stopConversation(\n agentSessionId: string,\n context: ConversationContext,\n isRunnerShutdown: boolean = false,\n reason?: string\n ): Promise<void> {\n (context as any)._stopRequested = true;\n if (context && context.conversation) {\n context.status = \"stopping\";\n\n try {\n // Proactively send end notification to avoid missing it on abnormal exits\n // Use provided reason, or fall back to 'runner_shutdown' if isRunnerShutdown is true\n const finalReason =\n reason || (isRunnerShutdown ? \"runner_shutdown\" : undefined);\n (context as any)._stopReason = finalReason;\n await this._finalizeConversation(\n context,\n false,\n undefined,\n finalReason\n ).catch(() => {});\n // Mark conversation as stopped BEFORE ending to prevent race conditions\n context.status = \"stopped\";\n\n // Properly end the conversation using the SDK\n if (isAgentConversation(context.conversation)) {\n await context.conversation.end();\n }\n } catch (error) {\n console.error(`Error ending conversation ${agentSessionId}:`, error);\n }\n\n // Clean up conversation reference\n delete context.conversation;\n }\n\n console.log(\n `Stopped conversation ${agentSessionId} for ${context.conversationObjectType} ${context.conversationObjectId}`\n );\n }\n\n async resumeConversation(\n conversationObjectType: \"Task\" | \"TaskPlan\" | \"ProjectStep\",\n conversationObjectId: string,\n agentSessionId: string,\n config: ConversationConfig,\n conversationData?: any,\n resumeMessage?: string,\n provider: \"openrouter\" | \"groq\" = \"openrouter\"\n ): Promise<string> {\n console.log(\n `[NorthflareAgentManager] Resuming conversation ${agentSessionId}`\n );\n\n // Resume is handled by starting a new conversation with the existing session ID\n const context = await this.startConversation(\n conversationObjectType,\n conversationObjectId,\n { ...config, sessionId: agentSessionId },\n [], // Don't send initial messages\n conversationData,\n provider\n );\n\n // After starting the conversation with the sessionId, we need to send a message\n // to actually trigger the agent process to continue\n if (context.conversation && isAgentConversation(context.conversation)) {\n try {\n // Use the provided resume message or default to system instruction\n const messageToSend =\n resumeMessage ||\n \"<system-instructions>Please continue</system-instructions>\";\n console.log(\n `[NorthflareAgentManager] Sending resume message to conversation ${agentSessionId}`\n );\n context.conversation.send({\n type: \"text\",\n text: messageToSend,\n });\n } catch (error) {\n console.error(\n `[NorthflareAgentManager] Error sending resume message:`,\n error\n );\n }\n } else {\n console.warn(\n \"[NorthflareAgentManager] Resume requested but conversation instance missing or incompatible\"\n );\n }\n\n return context.agentSessionId;\n }\n\n private async _handleRunCompletion(\n context: ConversationContext,\n hadError: boolean,\n error?: any\n ): Promise<void> {\n if ((context as any)._finalized) return;\n\n const inFlight = (context as any)._runCompletionInFlight as\n | Promise<void>\n | undefined;\n if (inFlight) return inFlight;\n\n const promise = (async () => {\n\n const isTaskConversation = context.conversationObjectType === \"Task\";\n const stopRequested = (context as any)._stopRequested === true;\n const taskHandle = (context as any).taskHandle as any;\n const shouldRunGitFlow =\n context.config.useWorktrees !== false &&\n isTaskConversation &&\n !!taskHandle &&\n taskHandle.branch !== \"local\";\n\n if (!shouldRunGitFlow || hadError || stopRequested) {\n await this._finalizeConversation(context, hadError, error);\n return;\n }\n\n const taskId = context.conversationObjectId;\n const baseBranch =\n (context.config.repository?.branch as string | undefined) || \"main\";\n\n try {\n const taskState = await this.repositoryManager.getTaskState(taskId);\n const taskRepoInfo = await this.repositoryManager.getTaskRepoInfo(taskId);\n\n if (\n !taskState ||\n !taskRepoInfo ||\n !taskRepoInfo.worktreePath ||\n taskState.branch === \"local\"\n ) {\n await this._finalizeConversation(context, false);\n return;\n }\n\n const isLocalRepo = taskRepoInfo.repoKey.startsWith(\"local__\");\n const mergeWorkdir = isLocalRepo\n ? taskRepoInfo.controlPath\n : taskRepoInfo.worktreePath;\n\n // If we already have unresolved conflicts, immediately ask the agent to resolve them.\n const taskGit = simpleGit(taskRepoInfo.worktreePath);\n const initialTaskStatus = await taskGit.status();\n if (initialTaskStatus.conflicted.length > 0) {\n await this._resumeForGitConflictResolution(context, {\n kind: \"conflicts\",\n baseBranch,\n conflicts: initialTaskStatus.conflicted,\n workdir: taskRepoInfo.worktreePath,\n });\n return;\n }\n\n if (isLocalRepo && mergeWorkdir !== taskRepoInfo.worktreePath) {\n const mergeGit = simpleGit(mergeWorkdir);\n const mergeStatus = await mergeGit.status();\n if (mergeStatus.conflicted.length > 0) {\n await this._resumeForGitConflictResolution(context, {\n kind: \"conflicts\",\n baseBranch,\n conflicts: mergeStatus.conflicted,\n workdir: mergeWorkdir,\n });\n return;\n }\n }\n\n // Ensure we're on the task branch for commit/rebase operations.\n const currentBranch = (\n await taskGit.revparse([\"--abbrev-ref\", \"HEAD\"])\n ).trim();\n if (currentBranch !== taskState.branch) {\n await taskGit.checkout(taskState.branch);\n }\n\n const status = await taskGit.status();\n if (!status.isClean()) {\n await this.repositoryManager.stageAll(taskId);\n try {\n const previousCommitCount = (taskState as any)?.commitCount ?? 0;\n const baseSubject =\n (context.summary ?? \"\").replace(/\\s+/g, \" \").trim() ||\n `Task ${taskId}`;\n const message =\n previousCommitCount > 0\n ? `${baseSubject} (followup #${previousCommitCount})`\n : baseSubject;\n await this.repositoryManager.commit(taskId, message);\n } catch (commitError) {\n const msg =\n commitError instanceof Error\n ? commitError.message\n : String(commitError);\n if (!msg.toLowerCase().includes(\"nothing to commit\")) {\n throw commitError;\n }\n }\n }\n\n const integrateResult = await this.repositoryManager.integrateTask(\n taskId,\n baseBranch,\n \"no-ff\"\n );\n if (!integrateResult.success) {\n await this._resumeForGitConflictResolution(context, {\n kind: integrateResult.phase,\n baseBranch,\n conflicts: integrateResult.conflicts ?? [],\n workdir: integrateResult.conflictWorkdir,\n error: integrateResult.error,\n });\n return;\n }\n\n // Worktree is no longer needed after a successful merge; preserve the branch\n await this.repositoryManager.removeTaskWorktree(taskId, {\n preserveBranch: true,\n });\n\n const wsId = context.config.workspaceId || context.workspaceId;\n const repoUrl = context.config.repository?.url;\n if (wsId && repoUrl) {\n await this.repositoryManager.syncWorkspaceWorktree(wsId, repoUrl, baseBranch);\n }\n\n await this._finalizeConversation(context, false);\n } catch (mergeError) {\n console.error(\n \"[NorthflareAgentManager] Post-task git flow failed\",\n mergeError\n );\n await this._finalizeConversation(context, true, mergeError);\n }\n })();\n\n (context as any)._runCompletionInFlight = promise.finally(() => {\n delete (context as any)._runCompletionInFlight;\n });\n return (context as any)._runCompletionInFlight;\n }\n\n private async _resumeForGitConflictResolution(\n context: ConversationContext,\n payload: {\n kind: \"conflicts\" | \"rebase\" | \"merge\";\n baseBranch: string;\n conflicts: string[];\n workdir: string;\n error?: string;\n }\n ): Promise<void> {\n const { kind, baseBranch, conflicts, workdir, error } = payload;\n\n const conflictsList = conflicts?.length\n ? `\\n\\nConflicted files:\\n${conflicts.map((f) => `- ${f}`).join(\"\\n\")}`\n : \"\";\n const workdirHint = workdir ? `\\n\\nWork directory:\\n- ${workdir}` : \"\";\n const errorHint = error ? `\\n\\nError:\\n${error}` : \"\";\n const hasConflicts = !!conflicts?.length;\n\n let instruction: string;\n if (kind === \"rebase\") {\n instruction = hasConflicts\n ? `<system-instructions>\\nA git rebase onto \\`${baseBranch}\\` produced merge conflicts.${conflictsList}${workdirHint}${errorHint}\\n\\nPlease resolve the conflicts in that directory, then run:\\n- git add -A\\n- git rebase --continue\\n\\nWhen the rebase finishes cleanly, reply briefly so I can retry the integration.\\n</system-instructions>`\n : `<system-instructions>\\nA git rebase onto \\`${baseBranch}\\` failed.${workdirHint}${errorHint}\\n\\nNo conflicted files were reported. Please run:\\n- git status\\n\\nFix the error (or complete/abort any in-progress git operation) and reply briefly so I can retry the integration.\\n</system-instructions>`;\n } else if (kind === \"merge\") {\n instruction = hasConflicts\n ? `<system-instructions>\\nA git merge into \\`${baseBranch}\\` produced merge conflicts.${conflictsList}${workdirHint}${errorHint}\\n\\nPlease resolve the conflicts in that directory, then run:\\n- git add -A\\n- git commit -m \\\"Resolve merge conflicts for ${context.conversationObjectId}\\\"\\n\\nWhen the working tree is clean, reply briefly so I can retry the integration.\\n</system-instructions>`\n : `<system-instructions>\\nA git merge into \\`${baseBranch}\\` failed.${workdirHint}${errorHint}\\n\\nNo conflicted files were reported. Please run:\\n- git status\\n\\nFix the error (or complete/abort any in-progress git operation) and reply briefly so I can retry the integration.\\n</system-instructions>`;\n } else {\n instruction = `<system-instructions>\\nGit has unresolved conflicts.${conflictsList}${workdirHint}${errorHint}\\n\\nPlease resolve the conflicts in that directory and complete the in-progress git operation (rebase or merge). When the working tree is clean, reply briefly so I can retry the integration.\\n</system-instructions>`;\n }\n\n const conversationData = {\n id: context.conversationId,\n objectType: context.conversationObjectType,\n objectId: context.conversationObjectId,\n model: context.model,\n summary: context.summary ?? null,\n globalInstructions: context.globalInstructions,\n workspaceInstructions: context.workspaceInstructions,\n permissionsMode: context.permissionsMode,\n agentSessionId: context.agentSessionId,\n };\n\n await this.resumeConversation(\n context.conversationObjectType,\n context.conversationObjectId,\n context.agentSessionId,\n context.config,\n conversationData,\n instruction,\n context.provider === \"groq\" ? \"groq\" : \"openrouter\"\n );\n }\n\n private async _finalizeConversation(\n context: ConversationContext,\n hadError: boolean,\n error?: any,\n reason?: string\n ): Promise<void> {\n // Synchronous idempotency check - must happen before any async operations\n if ((context as any)._finalized) return;\n (context as any)._finalized = true;\n\n try {\n const clearSilenceTimer = (context as any)._clearSilenceTimer;\n if (typeof clearSilenceTimer === \"function\") {\n clearSilenceTimer();\n }\n } catch {}\n\n // Mark as completed immediately to prevent restart on catch-up\n // This is synchronous and happens before any async operations\n this.runner.markConversationCompleted(context.conversationId);\n\n // Clean up conversation from active conversations (synchronous)\n try {\n console.log(\n `[NorthflareAgentManager] Removing conversation from active map:`,\n {\n conversationId: context.conversationId,\n agentSessionId: context.agentSessionId,\n mapSizeBefore: this.runner.activeConversations_.size,\n }\n );\n this.runner.activeConversations_.delete(context.conversationId);\n // Clean up submit tool tracking\n this.submitToolUseIds.delete(context.conversationId);\n statusLineManager.updateActiveCount(\n this.runner.activeConversations_.size\n );\n } catch {}\n\n // Now do async notification (after all sync cleanup)\n try {\n await this.runner.notify(\"conversation.end\", {\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n agentSessionId: context.agentSessionId,\n isError: hadError,\n errorMessage: error?.message,\n reason: reason,\n });\n } catch (e) {\n console.error(\n \"[NorthflareAgentManager] Failed to notify conversation.end:\",\n e\n );\n }\n\n // Notify update coordinator that a conversation has ended\n // This may trigger an auto-update if one is pending and runner is now idle\n try {\n await this.runner.onConversationEnd();\n } catch (e) {\n console.error(\n \"[NorthflareAgentManager] Failed to notify onConversationEnd:\",\n e\n );\n }\n }\n\n async sendUserMessage(\n conversationId: string,\n content: any,\n config?: ConversationConfig,\n conversationObjectType?: \"Task\" | \"TaskPlan\" | \"ProjectStep\",\n conversationObjectId?: string,\n conversation?: any,\n _agentSessionIdOverride?: string\n ): Promise<void> {\n console.log(`[NorthflareAgentManager] sendUserMessage called with:`, {\n conversationId,\n conversationObjectType,\n conversationObjectId,\n hasConfig: !!config,\n hasConversation: !!conversation,\n activeConversations: this.runner.activeConversations_.size,\n });\n\n // Find by conversationId only\n let context = this.runner.getConversationContext(conversationId);\n console.log(`[NorthflareAgentManager] Lookup by conversationId result:`, {\n found: !!context,\n conversationId: context?.conversationId,\n agentSessionId: context?.agentSessionId,\n });\n\n if (!context && conversation) {\n // Use provided conversation details\n try {\n const conversationDetails = conversation;\n console.log(\n `[NorthflareAgentManager] Using provided config from RunnerMessage:`,\n {\n hasConfig: !!config,\n hasRepository: !!config?.repository,\n repositoryType: config?.repository?.type,\n repositoryPath: config?.repository?.localPath,\n hasTokens: !!(config?.accessToken || config?.githubToken),\n hasMcpServers: !!config?.mcpServers,\n }\n );\n\n // Use the config that was already prepared by TaskOrchestrator and sent in the RunnerMessage\n const startConfig: ConversationConfig = {\n anthropicApiKey:\n config?.anthropicApiKey || process.env[\"ANTHROPIC_API_KEY\"] || \"\",\n systemPrompt:\n config?.systemPrompt || (conversationDetails as any)?.systemPrompt,\n systemPromptMode:\n config?.systemPromptMode ||\n (conversationDetails as any)?.systemPromptMode,\n workspaceId: conversationDetails.workspaceId,\n ...config, // Use the full config provided in the RunnerMessage\n ...(conversationDetails.agentSessionId\n ? { sessionId: conversationDetails.agentSessionId }\n : {}),\n };\n\n // Start the SDK conversation (no initial messages); this attaches to existing session when provided\n const derivedProvider =\n (conversationDetails as any)?.provider ||\n (startConfig as any)?.providerType ||\n \"openrouter\";\n\n await this.startConversation(\n conversationDetails.objectType,\n conversationDetails.objectId,\n startConfig,\n [],\n conversationDetails,\n derivedProvider as any\n );\n\n // Refresh context after start/resume\n context = this.runner.getConversationContext(conversationId);\n } catch (error) {\n console.error(`Failed to fetch conversation ${conversationId}:`, error);\n }\n }\n\n if (!context) {\n throw new Error(\n `No active or fetchable conversation found for ${conversationId}`\n );\n }\n\n try {\n // Send immediately when a conversation instance exists; no need to wait for \"active\"\n if (!context.conversation || !isAgentConversation(context.conversation)) {\n throw new Error(\n `No conversation instance found for conversation ${context.conversationId}`\n );\n }\n\n // Guard: Don't send messages if conversation is stopped or stopping\n const conversationStatus = context.status as string;\n if (\n conversationStatus === \"stopped\" ||\n conversationStatus === \"stopping\"\n ) {\n console.warn(\n `Attempted to send message to stopped/stopping conversation ${context.conversationId}`,\n {\n status: context.status,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n }\n );\n return;\n }\n\n // Native message injection - SDK handles queueing and delivery\n // Use normalizeContentForSDK to preserve multimodal content (images)\n const normalizedContent = this.normalizeContentForSDK(content);\n const isMultimodal = Array.isArray(normalizedContent);\n\n if (isDebugEnabledFor(\"manager\")) {\n console.log(\"[NorthflareAgentManager] Normalized follow-up content\", {\n originalType: typeof content,\n isArray: Array.isArray(content) || undefined,\n isMultimodal,\n normalizedPreview: isMultimodal\n ? `[${normalizedContent.length} blocks: ${normalizedContent.map((b: any) => b.type).join(\", \")}]`\n : (normalizedContent as string).slice(0, 160),\n });\n }\n\n if (isMultimodal) {\n // Send multimodal content blocks directly to the SDK\n // Use any cast to bypass type restrictions - our wrapper supports this\n (context.conversation as any).send({\n type: \"multimodal\",\n content: normalizedContent as Array<{ type: string; text?: string; image?: string }>,\n });\n } else {\n context.conversation.send({\n type: \"text\",\n text: normalizedContent as string,\n });\n }\n\n // Update last activity timestamp\n context.lastActivityAt = new Date();\n\n console.log(\n `Sent user message to conversation ${context.conversationId} (agentSessionId: ${context.agentSessionId}, status: ${context.status})`\n );\n } catch (error) {\n // Handle errors properly\n await this._handleConversationError(context, error as Error);\n throw error; // Re-throw to maintain the same behavior\n }\n }\n\n private async fetchGithubTokens(\n workspaceId: string\n ): Promise<string | undefined> {\n try {\n const response = await fetch(\n `${this.runner.config_.orchestratorUrl}/api/runner/tokens?workspaceId=${workspaceId}`,\n {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${process.env[\"NORTHFLARE_RUNNER_TOKEN\"]}`,\n },\n }\n );\n\n if (!response.ok) {\n console.error(`Failed to fetch GitHub tokens: ${response.status}`);\n return undefined;\n }\n\n const data = (await response.json()) as { githubToken?: string };\n return data.githubToken;\n } catch (error) {\n console.error(\"Error fetching GitHub tokens:\", error);\n return undefined;\n }\n }\n\n private async _handleConversationError(\n context: ConversationContext,\n error: Error\n ): Promise<void> {\n const errorType = this.classifyError(error);\n\n // Notify orchestrator\n await this.runner.notify(\"error.report\", {\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n agentSessionId: context.agentSessionId,\n errorType,\n message: error.message,\n details: {\n stack: error.stack,\n timestamp: new Date(),\n },\n });\n\n // Conversation continues on error - no automatic cleanup\n console.error(\n `Conversation error for ${context.conversationObjectType} ${context.conversationObjectId}:`,\n error\n );\n }\n\n private classifyError(error: Error): string {\n const msg = error.message.toLowerCase();\n if (msg.includes(\"process exited\")) {\n return \"process_exit\";\n } else if (msg.includes(\"model\")) {\n return \"model_error\";\n } else if (msg.includes(\"tool\")) {\n return \"tool_error\";\n } else if (\n msg.includes(\"permission\") ||\n msg.includes(\"forbidden\") ||\n msg.includes(\"403\")\n ) {\n return \"permission_error\";\n } else if (msg.includes(\"timeout\")) {\n return \"timeout_error\";\n } else if (\n msg.includes(\"unauthorized\") ||\n msg.includes(\"401\") ||\n msg.includes(\"authentication\")\n ) {\n return \"auth_error\";\n } else if (\n msg.includes(\"rate limit\") ||\n msg.includes(\"429\") ||\n msg.includes(\"too many requests\")\n ) {\n return \"rate_limit_error\";\n } else if (\n msg.includes(\"api\") ||\n msg.includes(\"network\") ||\n msg.includes(\"fetch\") ||\n msg.includes(\"connection\")\n ) {\n return \"api_error\";\n }\n return \"unknown_error\";\n }\n\n private normalizeModel(rawModel: string | undefined): string {\n if (!rawModel) {\n throw new Error(\"normalizeModel called without a model; caller must supply one.\");\n }\n\n const trimmed = rawModel.trim();\n\n if (trimmed.startsWith(\"openrouter:\")) {\n return trimmed.slice(\"openrouter:\".length);\n }\n\n if (trimmed.startsWith(\"openrouter/\")) {\n return trimmed.slice(\"openrouter/\".length);\n }\n\n if (trimmed.startsWith(\"groq:\")) {\n return trimmed.slice(\"groq:\".length);\n }\n\n if (trimmed.startsWith(\"groq/\")) {\n return trimmed.slice(\"groq/\".length);\n }\n\n if (!trimmed) {\n throw new Error(\"Model string cannot be empty.\");\n }\n\n return trimmed;\n }\n\n /**\n * Check if content contains multimodal blocks (images or documents)\n */\n private hasMultimodalContent(value: any): boolean {\n if (!Array.isArray(value)) return false;\n return value.some(\n (item) =>\n item &&\n typeof item === \"object\" &&\n (item.type === \"image\" || item.type === \"document\")\n );\n }\n\n /**\n * Normalize content for the SDK, preserving multimodal blocks when present.\n * Returns either a string (text-only) or an array of content blocks (multimodal).\n */\n private normalizeContentForSDK(\n value: any\n ): string | Array<{ type: string; text?: string; image?: string }> {\n // If it's an array with multimodal content, convert to SDK format\n if (Array.isArray(value) && this.hasMultimodalContent(value)) {\n const blocks: Array<{ type: string; text?: string; image?: string }> = [];\n\n for (const item of value) {\n if (!item || typeof item !== \"object\") continue;\n\n if (item.type === \"text\" && typeof item.text === \"string\") {\n blocks.push({ type: \"text\", text: item.text });\n } else if (item.type === \"image\" && item.source) {\n // Convert image blocks: { type: \"image\", source: { type: \"url\", url: \"...\" } }\n // to SDK format: { type: \"image\", image: \"...\" }\n const imageUrl =\n item.source.type === \"url\" ? item.source.url : item.source.data;\n if (imageUrl) {\n blocks.push({ type: \"image\", image: imageUrl });\n }\n } else if (item.type === \"document\" && item.source) {\n // Documents (PDFs) - the SDK doesn't have native document support,\n // so we include them as text with the URL for now\n // TODO: When SDK adds document support, update this\n const docUrl =\n item.source.type === \"url\" ? item.source.url : item.source.data;\n if (docUrl) {\n // For now, add PDF URL as text since SDK doesn't support documents directly\n // The model can still access PDFs via URL if supported\n blocks.push({\n type: \"text\",\n text: `[PDF Document: ${docUrl}]`,\n });\n }\n }\n }\n\n // If we have any image blocks, return the multimodal array\n if (blocks.some((b) => b.type === \"image\")) {\n return blocks;\n }\n // Otherwise, fall back to text extraction\n }\n\n // Fall back to text-only normalization\n return this.normalizeToText(value);\n }\n\n /**\n * Normalize arbitrary content shapes into a plain string for the CLI\n */\n private normalizeToText(value: any): string {\n if (typeof value === \"string\") return value;\n if (value == null) return \"\";\n\n if (typeof value === \"object\") {\n // Common simple shapes\n if (typeof (value as any).text === \"string\") return (value as any).text;\n if (\n typeof (value as any).text === \"object\" &&\n (value as any).text &&\n typeof (value as any).text.text === \"string\"\n )\n return (value as any).text.text;\n if (typeof (value as any).content === \"string\")\n return (value as any).content;\n\n // Array of blocks: [{ type: 'text', text: '...' }, ...]\n if (Array.isArray(value)) {\n const texts = value\n .map((b) =>\n b && b.type === \"text\" && typeof b.text === \"string\" ? b.text : null\n )\n .filter((t): t is string => !!t);\n if (texts.length) return texts.join(\" \");\n }\n\n // Nested message shapes\n if (\n typeof (value as any).message === \"object\" &&\n (value as any).message &&\n typeof (value as any).message.text === \"string\"\n ) {\n return (value as any).message.text;\n }\n }\n\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n }\n\n private async handleStreamedMessage(\n context: ConversationContext,\n message: SDKMessage,\n sessionId: string | null\n ): Promise<void> {\n /*\n * SDK tool call payload reference (observed shapes)\n *\n * 1) Assistant tool call (tool_use)\n * {\n * \"type\": \"assistant\",\n * \"message\": {\n * \"role\": \"assistant\",\n * \"content\": [\n * { \"type\": \"text\", \"text\": \"…optional text…\" },\n * { \"type\": \"tool_use\", \"id\": \"toolu_01Nbv…\", \"name\": \"TodoWrite\", \"input\": { ... } }\n * ]\n * },\n * \"session_id\": \"…\"\n * }\n *\n * 2) Tool result (often emitted as type 'user')\n * {\n * \"type\": \"user\",\n * \"message\": {\n * \"role\": \"user\",\n * \"content\": [\n * {\n * \"tool_use_id\": \"toolu_01E9R475…\",\n * \"type\": \"tool_result\",\n * \"content\": \"Todos have been modified successfully. …\"\n * }\n * ]\n * },\n * \"parent_tool_use_id\": null,\n * \"session_id\": \"…\",\n * \"uuid\": \"…\"\n * }\n *\n * Normalization (runner → server message.agent):\n * - assistant tool_use → type: 'assistant', content: [{ toolCalls: [{ id, name, arguments }] }, …]\n * - tool_result (any shape) → type: 'tool_result', subtype: 'tool_result', content:\n * [ { type: 'tool_result', subtype: 'tool_result', tool_use_id, content } ]\n */\n // Guard: Don't process messages if conversation is stopped or stopping\n const status = context.status as string;\n if (status === \"stopped\" || status === \"stopping\") {\n console.log(\n `Ignoring message for stopped/stopping conversation ${context.conversationId}`,\n {\n status: context.status,\n messageType: message.type,\n }\n );\n return;\n }\n\n try {\n // High-level receipt log\n console.log(\n `Received streamed message for ${context.conversationObjectType} ${context.conversationObjectId}`,\n {\n type: message?.type,\n }\n );\n\n // Raw SDK message diagnostics\n try {\n // Log the full raw SDK message safely (handles circular refs)\n const safeStringify = (obj: any) => {\n const seen = new WeakSet();\n return JSON.stringify(\n obj,\n (key, value) => {\n if (typeof value === \"function\") return undefined;\n if (typeof value === \"bigint\") return String(value);\n if (typeof value === \"object\" && value !== null) {\n if (seen.has(value)) return \"[Circular]\";\n seen.add(value);\n }\n return value;\n },\n 2\n );\n };\n\n console.log(\n \"[NorthflareAgentManager] RAW SDK message FULL:\",\n safeStringify(message)\n );\n\n const summary = {\n keys: Object.keys(message || {}),\n hasMessage: !!(message as any)?.message,\n contentType: typeof (message as any)?.content,\n messageContentType: typeof (message as any)?.message?.content,\n sessionId:\n (message as any)?.session_id || (message as any)?.sessionId || null,\n };\n console.log(\n \"[NorthflareAgentManager] RAW SDK message summary:\",\n summary\n );\n if ((message as any)?.content !== undefined) {\n console.log(\n \"[NorthflareAgentManager] RAW SDK content:\",\n (message as any).content\n );\n }\n if ((message as any)?.message?.content !== undefined) {\n console.log(\n \"[NorthflareAgentManager] RAW SDK nested content:\",\n (message as any).message.content\n );\n }\n\n // Highlight tool calls as soon as they appear so downstream observers\n // can correlate real-time activity without waiting for the final result.\n if (message?.type === \"assistant\") {\n const assistantMsg: any = message;\n const toolBlocks = Array.isArray(assistantMsg?.message?.content)\n ? assistantMsg.message.content.filter(\n (part: any) => part?.type === \"tool_use\"\n )\n : [];\n\n if (toolBlocks.length > 0) {\n console.log(\n \"[NorthflareAgentManager] Agent announced tool calls\",\n toolBlocks.map((part: any) => ({\n id: part?.id,\n name: part?.name,\n }))\n );\n }\n }\n } catch (e) {\n console.warn(\n \"[NorthflareAgentManager] Failed to log raw SDK message:\",\n e\n );\n }\n\n // Build structured content based on message type\n let messageType: string = message.type;\n let subtype: string | undefined;\n let structuredContent: any = {};\n let isError = false;\n let skipSend = false;\n let metadata: any = null;\n const mergeMetadata = (extra?: Record<string, any> | null) => {\n if (!extra) return;\n metadata = metadata ? { ...metadata, ...extra } : extra;\n };\n\n // Extract parent_tool_use_id if present (for all message types)\n const msgAsAny = message as any;\n if (msgAsAny.parent_tool_use_id) {\n mergeMetadata({\n parent_tool_use_id: msgAsAny.parent_tool_use_id,\n });\n }\n\n // Extract content based on message type\n switch (message.type) {\n case \"assistant\": {\n const assistantMsg = message as any;\n const blocks =\n assistantMsg?.message?.content || assistantMsg?.content || [];\n const textContent = Array.isArray(blocks)\n ? blocks\n .filter(\n (b: any) =>\n b && b.type === \"text\" && typeof b.text === \"string\"\n )\n .map((b: any) => b.text)\n .join(\"\")\n : \"\";\n const toolCalls = Array.isArray(blocks)\n ? blocks\n .filter((b: any) => b && b.type === \"tool_use\")\n .map((b: any) => ({\n id: b.id,\n name: b.name,\n arguments: b.input,\n }))\n : undefined;\n\n // Track submit tool calls for special handling of their results\n if (toolCalls && toolCalls.length > 0) {\n const submitTools = toolCalls.filter(\n (tc: any) => tc.name === \"submit\"\n );\n if (submitTools.length > 0) {\n if (!this.submitToolUseIds.has(context.conversationId)) {\n this.submitToolUseIds.set(context.conversationId, new Set());\n }\n const submitIds = this.submitToolUseIds.get(\n context.conversationId\n )!;\n submitTools.forEach((st: any) => submitIds.add(st.id));\n console.log(\n `[NorthflareAgentManager] Tracking submit tool calls:`,\n {\n conversationId: context.conversationId,\n submitToolIds: submitTools.map((st: any) => st.id),\n }\n );\n }\n }\n\n structuredContent = {\n ...(textContent ? { text: textContent } : {}),\n ...(toolCalls && toolCalls.length ? { toolCalls } : {}),\n timestamp: new Date().toISOString(),\n };\n break;\n }\n\n case \"thinking\" as any: {\n messageType = \"thinking\";\n subtype = undefined;\n const thinkingMsg = message as any;\n structuredContent = [\n {\n type: \"thinking\",\n thinking: thinkingMsg.content || \"\",\n text: thinkingMsg.content || \"\",\n timestamp: new Date().toISOString(),\n },\n ];\n break;\n }\n\n case \"tool_use\" as any: {\n // Tool call request - map to assistant\n messageType = \"assistant\";\n subtype = \"tool_use\";\n const toolUseMsg = message as any;\n structuredContent = {\n toolCalls: [\n {\n id: toolUseMsg.id,\n name: toolUseMsg.name,\n arguments: toolUseMsg.input,\n },\n ],\n timestamp: new Date().toISOString(),\n };\n break;\n }\n\n case \"tool_result\" as any: {\n const toolResultMsg = message as any;\n const toolName =\n toolResultMsg.tool_name ||\n toolResultMsg.name ||\n toolResultMsg?.toolCall?.name ||\n null;\n const toolUseId =\n toolResultMsg.tool_use_id ||\n toolResultMsg.tool_call_id ||\n toolResultMsg.id ||\n toolResultMsg?.message?.id;\n\n const resolvedContent = (() => {\n if (\n \"content\" in toolResultMsg &&\n toolResultMsg.content !== undefined\n ) {\n return toolResultMsg.content;\n }\n if (toolResultMsg.result !== undefined) {\n return toolResultMsg.result;\n }\n if (toolResultMsg.output !== undefined) {\n return toolResultMsg.output;\n }\n if (toolResultMsg?.message?.content !== undefined) {\n return toolResultMsg.message.content;\n }\n return null;\n })();\n\n // Check if this is a submit tool result\n const submitIds = this.submitToolUseIds.get(context.conversationId);\n const isSubmitTool = submitIds && submitIds.has(toolUseId);\n\n if (isSubmitTool) {\n // Convert submit tool result to assistant message\n const previewSource =\n resolvedContent ?? toolResultMsg.content ?? null;\n let previewText = \"[no content]\";\n if (typeof previewSource === \"string\") {\n previewText = previewSource.slice(0, 100);\n } else if (previewSource !== null) {\n try {\n previewText = JSON.stringify(previewSource).slice(0, 100);\n } catch {\n previewText = String(previewSource);\n }\n }\n\n console.log(\n `[NorthflareAgentManager] Converting submit tool result to assistant message:`,\n {\n conversationId: context.conversationId,\n toolUseId,\n contentPreview: previewText,\n }\n );\n\n messageType = \"assistant\";\n subtype = \"submit_result\";\n\n // Extract the text content from the tool result\n let textContent = \"\";\n if (typeof resolvedContent === \"string\") {\n textContent = resolvedContent;\n } else if (Array.isArray(resolvedContent)) {\n // Handle array of content blocks\n textContent = resolvedContent\n .filter(\n (b: any) =>\n b && b.type === \"text\" && typeof b.text === \"string\"\n )\n .map((b: any) => b.text)\n .join(\"\");\n } else if (resolvedContent && typeof resolvedContent === \"object\") {\n // Handle object with text property\n if (typeof (resolvedContent as any).text === \"string\") {\n textContent = (resolvedContent as any).text;\n } else if (typeof (resolvedContent as any).result === \"string\") {\n textContent = (resolvedContent as any).result;\n }\n }\n\n structuredContent = {\n text: textContent,\n timestamp: new Date().toISOString(),\n metadata: {\n source: \"submit_tool\",\n tool_use_id: toolUseId,\n },\n };\n\n // Remove this tool_use_id from tracking\n submitIds.delete(toolUseId);\n if (submitIds.size === 0) {\n this.submitToolUseIds.delete(context.conversationId);\n }\n } else {\n // Regular tool result - normalize to v1-style tool_result blocks\n messageType = \"tool_result\";\n subtype = \"tool_result\";\n structuredContent = [\n {\n type: \"tool_result\",\n subtype: \"tool_result\",\n tool_use_id: toolUseId,\n content: resolvedContent, // Keep content as native (array or string)\n timestamp: new Date().toISOString(),\n },\n ];\n\n const toolCallMetadata: Record<string, any> = {};\n if (toolUseId) {\n toolCallMetadata[\"id\"] = toolUseId;\n }\n if (toolName) {\n toolCallMetadata[\"name\"] = toolName;\n }\n\n mergeMetadata({\n ...(toolName ? { tool_name: toolName } : {}),\n ...(Object.keys(toolCallMetadata).length > 0\n ? { toolCall: toolCallMetadata }\n : {}),\n });\n }\n break;\n }\n\n case \"result\": {\n // SDK result message - check if it's an error result\n const resultMsg = message as any;\n const resultIsError = resultMsg.is_error === true;\n const resultSubtype = resultMsg.subtype || \"success\";\n const errorMessage = resultMsg.error_message || resultMsg.result || \"\";\n\n if (resultIsError) {\n // Store the SDK error in context metadata so onComplete knows about it\n context.metadata = context.metadata || {};\n context.metadata[\"_sdkError\"] = {\n isError: true,\n errorMessage: errorMessage,\n subtype: resultSubtype,\n };\n\n console.log(\n \"[NorthflareAgentManager] SDK result message indicates error\",\n {\n conversationId: context.conversationId,\n subtype: resultSubtype,\n errorMessage: errorMessage?.slice?.(0, 200),\n }\n );\n\n messageType = \"system\";\n subtype = \"error\";\n isError = true;\n structuredContent = {\n text: errorMessage || \"SDK execution error\",\n errorType: resultSubtype,\n errorDetails: {\n sdk_subtype: resultSubtype,\n duration_ms: resultMsg.duration_ms,\n num_turns: resultMsg.num_turns,\n },\n timestamp: new Date().toISOString(),\n };\n } else if (typeof resultMsg.content === \"string\" || typeof resultMsg.result === \"string\") {\n // Keep legacy non-error result behavior for plain text payloads.\n structuredContent = {\n text: resultMsg.content || resultMsg.result || \"\",\n timestamp: new Date().toISOString(),\n };\n } else {\n // Success result - just log it, don't send as a separate message\n console.log(\n \"[NorthflareAgentManager] SDK result message (success)\",\n {\n conversationId: context.conversationId,\n subtype: resultSubtype,\n resultPreview: (resultMsg.result || \"\").slice?.(0, 100),\n }\n );\n skipSend = true;\n }\n break;\n }\n\n case \"user\": {\n const userMsg = message as any;\n\n // Skip user messages that were sent by the runner itself (already in database via orchestrator)\n // Only process user messages that contain tool results (which need special handling)\n const rawContent =\n (userMsg && userMsg.message && userMsg.message.content) ||\n userMsg?.content ||\n [];\n\n // Check if this is a tool result message (needs processing)\n const blocks =\n typeof rawContent === \"string\"\n ? [{ type: \"text\", text: rawContent }]\n : rawContent;\n\n if (Array.isArray(blocks)) {\n const hasToolResult = blocks.some(\n (b: any) => b && typeof b === \"object\" && b.type === \"tool_result\"\n );\n\n if (hasToolResult) {\n // Normalize tool_result blocks to v1-style\n messageType = \"tool_result\";\n subtype = \"tool_result\";\n structuredContent = blocks\n .filter((b: any) => b && b.type === \"tool_result\")\n .map((b: any) => ({\n type: \"tool_result\",\n subtype: \"tool_result\",\n tool_use_id: b.tool_use_id || b.toolUseId || b.id,\n content: b.content, // Keep content as native (array or string)\n }));\n } else {\n // Regular user messages (non-tool-result) are already created by the orchestrator\n // Skip them to avoid duplicates\n console.log(\n \"[NorthflareAgentManager] Skipping regular user message (already in database via orchestrator)\"\n );\n skipSend = true;\n\n // Special case: Check if this is a subagent prompt (has parent_tool_use_id)\n if (userMsg.parent_tool_use_id) {\n // These should still be processed as assistant messages\n console.log(\n \"[NorthflareAgentManager] Detected subagent prompt message (parent_tool_use_id present, no tool_result)\",\n {\n parent_tool_use_id: userMsg.parent_tool_use_id,\n }\n );\n skipSend = false; // Don't skip subagent prompts\n messageType = \"assistant\"; // Change from \"user\" to \"assistant\"\n subtype = \"subagent_prompt\";\n const textContent = blocks\n .filter(\n (b: any) =>\n b && b.type === \"text\" && typeof b.text === \"string\"\n )\n .map((b: any) => b.text)\n .join(\"\");\n structuredContent = {\n text: textContent,\n timestamp: new Date().toISOString(),\n };\n // metadata already set above with parent_tool_use_id\n }\n }\n\n // If content array only contains empty objects, skip sending\n if (\n Array.isArray(structuredContent) &&\n structuredContent.length > 0 &&\n structuredContent.every(\n (it: any) =>\n !it || typeof it !== \"object\" || Object.keys(it).length === 0\n )\n ) {\n console.log(\n \"[NorthflareAgentManager] Skipping empty 'user' message with only empty objects from SDK\"\n );\n skipSend = true;\n }\n } else if (typeof userMsg?.content === \"string\") {\n // Attempt to parse JSON arrays (common for tool_result payloads)\n const text = userMsg.content;\n try {\n const parsed = JSON.parse(text);\n if (Array.isArray(parsed)) {\n const hasToolResult = parsed.some(\n (item: any) =>\n item &&\n typeof item === \"object\" &&\n item.type === \"tool_result\"\n );\n if (hasToolResult) {\n messageType = \"tool_result\";\n subtype = \"tool_result\";\n structuredContent = parsed;\n } else {\n // Regular user message in JSON array format - skip\n console.log(\n \"[NorthflareAgentManager] Skipping regular user message from JSON array (already in database)\"\n );\n skipSend = true;\n }\n } else {\n // Regular user message as parsed JSON - skip\n console.log(\n \"[NorthflareAgentManager] Skipping regular user message from parsed JSON (already in database)\"\n );\n skipSend = true;\n }\n } catch {\n // Not JSON - regular text user message - skip\n console.log(\n \"[NorthflareAgentManager] Skipping regular text user message (already in database)\"\n );\n skipSend = true;\n }\n } else {\n // Other object content - skip regular user messages\n console.log(\n \"[NorthflareAgentManager] Skipping regular user message with object content (already in database)\"\n );\n skipSend = true;\n }\n break;\n }\n\n case \"system\": {\n const systemMsg = message as any;\n const subtype = systemMsg.subtype || \"system\";\n const model = systemMsg.model || systemMsg?.message?.model;\n const permissionMode =\n systemMsg.permissionMode || systemMsg?.message?.permissionMode;\n const summary = [\n subtype && `[${subtype}]`,\n model && `model=${model}`,\n permissionMode && `perm=${permissionMode}`,\n ]\n .filter(Boolean)\n .join(\" \");\n structuredContent = {\n text: summary || \"\",\n timestamp: new Date().toISOString(),\n };\n break;\n }\n\n case \"error\" as any: {\n const errorMsg = message as any;\n messageType = \"system\";\n subtype = \"error\";\n isError = true;\n structuredContent = {\n text: errorMsg.message || errorMsg.error || \"Unknown error\",\n errorType: errorMsg.error_type || \"unknown\",\n errorDetails: {\n stack: errorMsg.stack,\n code: errorMsg.code,\n context: errorMsg,\n },\n timestamp: new Date().toISOString(),\n };\n break;\n }\n\n default: {\n // Unknown message type - log and send as assistant\n const unknownMsg = message as any;\n console.warn(`Unknown message type: ${unknownMsg.type}`, message);\n messageType = \"assistant\";\n structuredContent = {\n text: JSON.stringify(message),\n timestamp: new Date().toISOString(),\n };\n }\n }\n\n // Generate a unique message ID\n const messageId = `${context.agentSessionId}-${Date.now()}-${Math.random()\n .toString(36)\n .substr(2, 9)}`;\n\n // Send agent message to orchestrator with structured content\n // Skip if conversation is stopping/stopped to avoid race conditions\n const currentStatus = context.status as string;\n if (currentStatus !== \"stopped\" && currentStatus !== \"stopping\") {\n if (skipSend) {\n console.log(\n \"[NorthflareAgentManager] Not sending message.agent due to skipSend=true\"\n );\n return;\n }\n\n const payload: any = {\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n agentSessionId: context.agentSessionId,\n type: messageType,\n subtype,\n content: Array.isArray(structuredContent)\n ? structuredContent\n : [structuredContent],\n messageId,\n isError,\n };\n\n // Add metadata if present\n if (metadata) {\n payload.metadata = metadata;\n }\n\n try {\n console.log(\n \"[NorthflareAgentManager] Sending message.agent payload:\",\n {\n type: payload.type,\n subtype: payload.subtype,\n contentPreview: Array.isArray(payload.content)\n ? payload.content.slice(0, 1)\n : payload.content,\n }\n );\n } catch {}\n\n await this.runner.notify(\"message.agent\", payload as any);\n try {\n console.log(\"[NorthflareAgentManager] message.agent dispatched\", {\n conversationId: context.conversationId,\n agentSessionId: context.agentSessionId,\n messageId,\n type: payload.type,\n subtype: payload.subtype,\n });\n\n // If the main agent sent a submit tool result, treat it as terminal and finalize\n if (payload.subtype === \"submit_result\") {\n console.log(\n \"[NorthflareAgentManager] Submit tool detected - finalizing conversation\",\n {\n conversationId: context.conversationId,\n agentSessionId: context.agentSessionId,\n }\n );\n // End SDK conversation to stop further streaming\n try {\n if (\n context.conversation &&\n isAgentConversation(context.conversation)\n ) {\n await context.conversation.end();\n }\n } catch (e) {\n console.warn(\n \"[NorthflareAgentManager] Error ending conversation on submit:\",\n e\n );\n }\n await this._finalizeConversation(\n context,\n false,\n undefined,\n \"submit_tool\"\n );\n }\n } catch {}\n }\n\n // Tool calls are handled directly by the agent through the MCP server\n // We just log that we saw them but don't intercept or process them\n if (\n structuredContent.toolCalls &&\n structuredContent.toolCalls.length > 0\n ) {\n console.log(\n `Northflare Agent is making ${structuredContent.toolCalls.length} tool call(s) via MCP`,\n {\n conversationObjectId: context.conversationObjectId,\n toolNames: structuredContent.toolCalls.map((tc: any) => tc.name),\n }\n );\n }\n } catch (error) {\n // Check if this is a transport error due to stopped conversation\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n const isTransportError =\n errorMessage.includes(\"Cannot read properties of undefined\") ||\n errorMessage.includes(\"stdout\") ||\n errorMessage.includes(\"transport\");\n\n const statusCheck = context.status as string;\n if (\n isTransportError &&\n (statusCheck === \"stopped\" || statusCheck === \"stopping\")\n ) {\n // This is expected when conversation is stopped - just log it\n console.log(\n `Transport error for stopped/stopping conversation ${context.conversationId} (expected):`,\n errorMessage\n );\n return;\n }\n\n console.error(\n `Error handling streamed message for ${context.conversationObjectType} ${context.conversationObjectId}:`,\n error\n );\n await this._handleConversationError(context, error as Error);\n }\n }\n}\n\n// Simplified helper functions for SDK integration\n\ntype UserMessageStream = {\n iterable: AsyncIterable<any>;\n enqueue: (msg: any) => void;\n close: () => void;\n};\n\nfunction createUserMessageStream(): UserMessageStream {\n const queue: any[] = [];\n let resolver: (() => void) | null = null;\n let done = false;\n\n async function* iterator() {\n while (true) {\n if (queue.length > 0) {\n const value = queue.shift();\n // Attach metadata about remaining queue length so consumers can check\n // if more messages are immediately available without Promise.race tricks\n if (value && typeof value === \"object\") {\n (value as any).__queueHasMore = queue.length > 0;\n }\n yield value;\n continue;\n }\n if (done) return;\n await new Promise<void>((resolve) => (resolver = resolve));\n resolver = null;\n }\n }\n\n return {\n iterable: iterator(),\n enqueue: (msg: any) => {\n if (done) return;\n queue.push(msg);\n if (resolver) {\n const r = resolver;\n resolver = null;\n r();\n }\n },\n close: () => {\n done = true;\n if (resolver) {\n const r = resolver;\n resolver = null;\n r();\n }\n },\n };\n}\n\nfunction createConversationWrapper(\n sdk: any,\n input: UserMessageStream,\n onComplete?: (hadError: boolean, error?: any) => Promise<void> | void\n) {\n let onSessionIdCb: ((id: string) => void) | null = null;\n let observedSessionId: string | null = null;\n let startedReader = false;\n\n // Create SDK user message from text or multimodal content\n function toSdkUserMessage(\n content: string | Array<{ type: string; text?: string; image?: string }>\n ) {\n // If content is an array with image blocks, convert to SDK multimodal format\n if (Array.isArray(content)) {\n const sdkContent = content.map((block) => {\n if (block.type === \"text\" && block.text) {\n return { type: \"text\" as const, text: block.text };\n } else if (block.type === \"image\" && block.image) {\n return { type: \"image\" as const, image: block.image };\n }\n return null;\n }).filter(Boolean);\n\n return {\n type: \"user\",\n session_id: observedSessionId || \"\",\n parent_tool_use_id: null,\n message: {\n role: \"user\",\n content: sdkContent,\n },\n };\n }\n\n // Plain text message\n return {\n type: \"user\",\n session_id: observedSessionId || \"\",\n parent_tool_use_id: null,\n message: {\n role: \"user\",\n content: content,\n },\n };\n }\n\n return {\n // Send a message - accepts either text-only or multimodal content\n send(payload: {\n type: string;\n text?: string;\n content?: Array<{ type: string; text?: string; image?: string }>;\n }) {\n // Check if multimodal content is provided\n if (payload.content && Array.isArray(payload.content)) {\n const hasImages = payload.content.some((b) => b.type === \"image\");\n try {\n console.log(\"[NorthflareAgentManager] -> SDK send (multimodal)\", {\n sessionId: observedSessionId,\n type: payload?.type,\n blockCount: payload.content.length,\n hasImages,\n blockTypes: payload.content.map((b) => b.type).join(\", \"),\n });\n } catch {}\n input.enqueue(toSdkUserMessage(payload.content));\n return;\n }\n\n // Text-only message\n const text = payload?.text ?? \"\";\n try {\n console.log(\"[NorthflareAgentManager] -> SDK send\", {\n sessionId: observedSessionId,\n type: payload?.type,\n textPreview: text.slice(0, 200),\n length: text.length,\n });\n } catch {}\n input.enqueue(toSdkUserMessage(text));\n },\n async end() {\n try {\n input.close();\n } finally {\n // Simplified process cleanup\n try {\n if (sdk?.abortController) {\n sdk.abortController.abort();\n }\n } catch {}\n }\n },\n onSessionId(cb: (id: string) => void) {\n onSessionIdCb = cb;\n },\n stream(\n handler: (message: SDKMessage, sessionId: string | null) => Promise<void>\n ) {\n if (startedReader) return;\n startedReader = true;\n (async () => {\n try {\n for await (const msg of sdk) {\n // Simplified session ID extraction\n const sid = (msg && (msg.session_id || msg.sessionId)) || null;\n if (sid && sid !== observedSessionId) {\n observedSessionId = sid;\n if (onSessionIdCb) onSessionIdCb(sid);\n }\n await handler(msg, sid);\n }\n // Normal completion\n if (onComplete) await onComplete(false);\n } catch (e) {\n // Error completion\n if (onComplete) await onComplete(true, e);\n }\n })();\n },\n };\n}\ntype AgentConversation = {\n send: (payload: { type: string; text: string }) => void;\n end: () => Promise<void> | void;\n};\n\nfunction isAgentConversation(\n conversation: ConversationContext[\"conversation\"]\n): conversation is AgentConversation & ConversationContext[\"conversation\"] {\n return (\n !!conversation &&\n typeof (conversation as any).send === \"function\" &&\n typeof (conversation as any).end === \"function\"\n );\n}\n","/**\n * RepositoryManager - Manages Git repository checkouts and workspace isolation\n *\n * This component handles all Git operations for the runner, including:\n * - Cloning repositories with authentication\n * - Updating repositories to latest state\n * - Workspace isolation via separate directories\n * - Cleanup of old repositories\n * - Error handling for Git operations\n */\n\nimport { IRunnerApp } from '../types/runner-interface.js';\nimport { WorkspaceRepository } from '../types/index.js';\nimport path from \"path\";\nimport fs from \"fs/promises\";\nimport { mkdirSync } from \"fs\";\nimport { simpleGit, SimpleGit, GitError } from \"simple-git\";\nimport { createScopedConsole } from '../utils/console.js';\n\nconst console = createScopedConsole(\"repo\");\n\nexport class RepositoryManager {\n private repositories: Map<string, WorkspaceRepository>;\n protected repoBasePath: string;\n private runner: IRunnerApp;\n private git: SimpleGit;\n\n constructor(runner: IRunnerApp) {\n this.runner = runner;\n this.repositories = new Map();\n\n // Use workspacePath from config if available, otherwise use environment variable\n this.repoBasePath =\n runner.config_.workspacePath ||\n process.env[\"NORTHFLARE_WORKSPACE_PATH\"] ||\n \"/tmp/northflare-workspace\";\n if (!this.repoBasePath) {\n throw new Error(\n \"NORTHFLARE_WORKSPACE_PATH environment variable must be set\"\n );\n }\n\n // Ensure workspace directory exists before initializing simple-git\n try {\n mkdirSync(this.repoBasePath, { recursive: true });\n } catch (error) {\n console.error(\n `Failed to create workspace directory ${this.repoBasePath}:`,\n error\n );\n throw error;\n }\n\n // Initialize simple-git\n this.git = simpleGit({\n baseDir: this.repoBasePath,\n binary: \"git\",\n maxConcurrentProcesses: 3,\n config: [\"user.name=Northflare\", \"user.email=runner@northflare.ai\"],\n });\n }\n\n async checkoutRepository(\n workspaceId: string,\n repoUrl: string,\n branch: string,\n githubToken?: string\n ): Promise<string> {\n const existing = this.repositories.get(workspaceId);\n if (\n existing &&\n existing.repoUrl === repoUrl &&\n existing.branch === branch\n ) {\n await this.updateRepository(existing, githubToken);\n return existing.localPath;\n }\n\n const localPath = path.join(this.repoBasePath, workspaceId);\n\n // Clean up existing directory if it exists\n await this.cleanupDirectory(localPath);\n\n // Clone with authentication\n const authUrl = this.getAuthenticatedUrl(repoUrl, githubToken);\n\n try {\n console.log(`Cloning repository for workspace ${workspaceId}...`);\n await this.executeGit([\"clone\", \"--branch\", branch, authUrl, localPath]);\n\n // Configure the repository\n const repoGit = simpleGit(localPath);\n await repoGit.addConfig(\"credential.helper\", \"store\");\n\n const repo: WorkspaceRepository = {\n workspaceId,\n repoUrl,\n branch,\n localPath,\n lastAccessed: new Date(),\n };\n\n this.repositories.set(workspaceId, repo);\n console.log(\n `Successfully cloned repository for workspace ${workspaceId}`\n );\n return localPath;\n } catch (error) {\n console.error(\n `Failed to clone repository for workspace ${workspaceId}:`,\n error\n );\n await this.cleanupDirectory(localPath);\n throw error;\n }\n }\n\n /**\n * Checkout a local repository (bypasses Git operations)\n * Used for local workspaces that point to existing directories on the filesystem\n */\n async checkoutLocalRepository(\n workspaceId: string,\n localRepoPath: string\n ): Promise<string> {\n console.log(\n `Using local repository for workspace ${workspaceId}: ${localRepoPath}`\n );\n\n // Verify the path exists\n try {\n const stats = await fs.stat(localRepoPath);\n if (!stats.isDirectory()) {\n throw new Error(`Path is not a directory: ${localRepoPath}`);\n }\n } catch (error) {\n console.error(`Local repository path not found: ${localRepoPath}`);\n throw new Error(`Local repository path not found: ${localRepoPath}`);\n }\n\n // Store in repositories map for consistency\n const repo: WorkspaceRepository = {\n workspaceId,\n repoUrl: `file://${localRepoPath}`, // Use file:// protocol to indicate local\n branch: \"local\", // Local repos don't have branches in the same sense\n localPath: localRepoPath,\n lastAccessed: new Date(),\n };\n\n this.repositories.set(workspaceId, repo);\n console.log(\n `Successfully set up local repository for workspace ${workspaceId}`\n );\n return localRepoPath;\n }\n\n async getWorkspacePath(workspaceId: string): Promise<string> {\n const localPath = path.join(this.repoBasePath, workspaceId);\n await this.ensureDirectory(localPath);\n return localPath;\n }\n\n private async updateRepository(\n repo: WorkspaceRepository,\n githubToken?: string\n ): Promise<void> {\n repo.lastAccessed = new Date();\n\n // Skip Git operations for local repositories\n if (repo.repoUrl.startsWith(\"file://\")) {\n console.log(\n `Local repository for workspace ${repo.workspaceId} - no update needed`\n );\n return;\n }\n\n const repoGit = simpleGit(repo.localPath);\n\n try {\n console.log(`Updating repository for workspace ${repo.workspaceId}...`);\n\n // Update remote URL if token has changed\n if (githubToken) {\n const authUrl = this.getAuthenticatedUrl(repo.repoUrl, githubToken);\n await repoGit.remote([\"set-url\", \"origin\", authUrl]);\n }\n\n // Fetch latest changes\n await repoGit.fetch(\"origin\");\n\n // Reset to latest branch state\n await repoGit.reset([\"--hard\", `origin/${repo.branch}`]);\n\n // Clean untracked files\n await repoGit.clean(\"f\", [\"-d\"]);\n\n console.log(\n `Successfully updated repository for workspace ${repo.workspaceId}`\n );\n } catch (error) {\n console.error(\n `Failed to update repository for workspace ${repo.workspaceId}:`,\n error\n );\n throw error;\n }\n }\n\n async cleanupRepository(workspaceId: string): Promise<void> {\n const repo = this.repositories.get(workspaceId);\n if (!repo) return;\n\n console.log(`Cleaning up repository for workspace ${workspaceId}...`);\n\n // For local repositories, only remove from tracking, don't delete the directory\n if (repo.repoUrl.startsWith(\"file://\")) {\n console.log(`Local repository - removing from tracking only`);\n this.repositories.delete(workspaceId);\n return;\n }\n\n // Remove local directory for cloned repositories\n await this.cleanupDirectory(repo.localPath);\n\n this.repositories.delete(workspaceId);\n }\n\n async cleanupOldRepositories(\n maxAge: number = 7 * 24 * 60 * 60 * 1000\n ): Promise<void> {\n const now = new Date();\n const toCleanup: string[] = [];\n\n for (const [workspaceId, repo] of this.repositories.entries()) {\n const age = now.getTime() - repo.lastAccessed.getTime();\n if (age > maxAge) {\n toCleanup.push(workspaceId);\n }\n }\n\n for (const workspaceId of toCleanup) {\n await this.cleanupRepository(workspaceId);\n }\n\n console.log(`Cleaned up ${toCleanup.length} old repositories`);\n }\n\n protected async executeGit(args: string[], cwd?: string): Promise<void> {\n const git = cwd ? simpleGit(cwd) : this.git;\n try {\n await git.raw(args);\n } catch (error) {\n if (error instanceof GitError) {\n throw new Error(`Git operation failed: ${error.message}`);\n }\n throw error;\n }\n }\n\n protected getAuthenticatedUrl(repoUrl: string, githubToken?: string): string {\n if (!githubToken) {\n return repoUrl;\n }\n\n // Handle different URL formats\n if (repoUrl.startsWith(\"https://\")) {\n // HTTPS URL\n return repoUrl.replace(\"https://\", `https://${githubToken}@`);\n } else if (repoUrl.startsWith(\"git@\")) {\n // SSH URL - convert to HTTPS with token\n const httpsUrl = repoUrl\n .replace(\"git@github.com:\", \"https://github.com/\")\n .replace(\".git\", \"\");\n return `https://${githubToken}@${httpsUrl.replace(\"https://\", \"\")}.git`;\n }\n\n return repoUrl;\n }\n\n protected async ensureDirectory(dirPath: string): Promise<void> {\n try {\n await fs.mkdir(dirPath, { recursive: true });\n } catch (error) {\n console.error(`Failed to create directory ${dirPath}:`, error);\n throw error;\n }\n }\n\n protected async cleanupDirectory(dirPath: string): Promise<void> {\n try {\n const stats = await fs.stat(dirPath).catch(() => null);\n if (stats) {\n await fs.rm(dirPath, { recursive: true, force: true });\n }\n } catch (error) {\n console.error(`Failed to cleanup directory ${dirPath}:`, error);\n // Don't throw - cleanup errors are not critical\n }\n }\n\n /**\n * Get statistics about managed repositories\n */\n getRepositoryStats(): {\n total: number;\n workspaceIds: string[];\n oldestAccess: Date | null;\n newestAccess: Date | null;\n } {\n const repos = Array.from(this.repositories.values());\n\n return {\n total: repos.length,\n workspaceIds: Array.from(this.repositories.keys()),\n oldestAccess:\n repos.length > 0\n ? new Date(Math.min(...repos.map((r) => r.lastAccessed.getTime())))\n : null,\n newestAccess:\n repos.length > 0\n ? new Date(Math.max(...repos.map((r) => r.lastAccessed.getTime())))\n : null,\n };\n }\n\n /**\n * Check if a workspace has an existing repository\n */\n hasRepository(workspaceId: string): boolean {\n return this.repositories.has(workspaceId);\n }\n\n /**\n * Get repository info for a workspace\n */\n getRepository(workspaceId: string): WorkspaceRepository | undefined {\n return this.repositories.get(workspaceId);\n }\n}\n","/**\n * EnhancedRepositoryManager - Advanced Git repository management with worktree support\n *\n * This enhanced version builds upon the original RepositoryManager to add:\n * - Task-level Git isolation through worktrees\n * - Git operations (stage, commit, push, merge, rebase)\n * - State persistence and recovery\n * - Backward compatibility with workspace-based operations\n *\n * Directory structure:\n * /workspace/repos/<owner>__<repo>/\n * control/ # Primary clone (.git directory owner)\n * .git/\n * worktrees/\n * workspace_<workspaceId>/ # Backward compatibility - workspace default branch\n * task_<taskId>/ # New - isolated task worktrees\n * state.json # Persistent state mapping\n */\n\nimport { RepositoryManager } from './repository-manager.js';\nimport { IRunnerApp } from '../types/runner-interface.js';\nimport path from \"path\";\nimport fs from \"fs/promises\";\nimport crypto from \"crypto\";\nimport { simpleGit } from \"simple-git\";\nimport { createScopedConsole } from '../utils/console.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst console = createScopedConsole(\"repo\");\nconst logger = createLogger(\"EnhancedRepositoryManager\", \"repo\");\n\n// Types for enhanced functionality\nexport interface TaskHandle {\n taskId: string;\n worktreePath: string;\n branch: string;\n baseBranch: string;\n}\n\nexport interface RemoveOptions {\n preserveBranch?: boolean;\n force?: boolean;\n}\n\nexport interface GitAuthor {\n name: string;\n email: string;\n}\n\nexport interface RebaseResult {\n success: boolean;\n conflicts?: string[];\n error?: string;\n}\n\nexport interface MergeResult {\n success: boolean;\n conflicts?: string[];\n mergedCommit?: string;\n error?: string;\n}\n\nexport type MergeMode = \"ff-only\" | \"no-ff\" | \"squash\";\n\nexport type TaskIntegrationResult =\n | {\n success: true;\n mergedCommit?: string;\n }\n | {\n success: false;\n phase: \"rebase\" | \"merge\";\n conflicts?: string[];\n error?: string;\n conflictWorkdir: string;\n };\n\nexport interface TaskGitState {\n taskId: string;\n workspaceId?: string;\n branch: string;\n baseBranch: string;\n lastCommit?: string;\n commitCount?: number;\n worktreePath: string;\n status: \"active\" | \"conflicted\" | \"merged\" | \"abandoned\";\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface RepositoryState {\n repositories: Record<\n string,\n {\n owner: string;\n repo: string;\n controlPath: string;\n worktrees: Record<string, TaskGitState>;\n }\n >;\n}\n\nexport class EnhancedRepositoryManager extends RepositoryManager {\n private repoStates: Map<string, RepositoryState>;\n private stateFilePath: string;\n private legacyStateFilePath: string;\n private repoLocks: Map<string, Promise<void>>;\n private taskWorktreesBasePath: string;\n\n constructor(runner: IRunnerApp) {\n super(runner);\n this.repoStates = new Map();\n this.repoLocks = new Map();\n const dataDir = runner.config_.dataDir;\n const runnerId = runner.getRunnerId();\n const stateFileName = runnerId\n ? `repository-state-${runnerId}.json`\n : \"repository-state.json\";\n this.stateFilePath = path.join(dataDir, \"git\", stateFileName);\n this.legacyStateFilePath = path.join(this.repoBasePath, \"repository-state.json\");\n this.taskWorktreesBasePath = path.join(dataDir, \"git\", \"worktrees\");\n\n // Load persisted state on initialization\n this.restoreState().catch((err) => {\n console.error(\"Failed to restore repository state:\", err);\n });\n }\n\n /**\n * Get repository key from owner and repo name\n */\n private getRepoKey(repoUrl: string): {\n key: string;\n owner: string;\n repo: string;\n } {\n // Handle local repository URLs\n if (repoUrl.startsWith(\"file://\")) {\n const localPath = repoUrl.replace(\"file://\", \"\");\n const repoName = path.basename(localPath) || \"local\";\n const digest = crypto\n .createHash(\"sha1\")\n .update(localPath)\n .digest(\"hex\")\n .slice(0, 12);\n return { key: `local__${repoName}__${digest}`, owner: \"local\", repo: repoName };\n }\n\n // Extract owner and repo from URL\n const match = repoUrl.match(/github\\.com[:/]([^/]+)\\/([^/.]+)(\\.git)?$/);\n if (!match) {\n throw new Error(`Invalid GitHub repository URL: ${repoUrl}`);\n }\n\n const owner = match[1] || \"\";\n const repo = match[2] || \"\";\n const key = `${owner}__${repo}`;\n\n return { key, owner, repo };\n }\n\n private parseRepoKey(repoKey: string): { owner: string; repo: string } {\n const parts = repoKey.split(\"__\");\n const owner = parts[0] || repoKey;\n const repo = parts[1] || repoKey;\n return { owner, repo };\n }\n\n private findTaskStateEntry(taskId: string): {\n repoKey: string;\n repo: RepositoryState[\"repositories\"][string];\n taskState: TaskGitState;\n } | null {\n for (const [repoKey, state] of this.repoStates) {\n const repo = state.repositories[repoKey];\n const taskState = repo?.worktrees?.[taskId];\n if (repo && taskState) {\n return { repoKey, repo, taskState };\n }\n }\n return null;\n }\n\n private async withRepoLock<T>(repoKey: string, fn: () => Promise<T>): Promise<T> {\n const previous = this.repoLocks.get(repoKey) ?? Promise.resolve();\n let release!: () => void;\n const current = new Promise<void>((resolve) => {\n release = resolve;\n });\n\n const chained = previous.then(() => current);\n this.repoLocks.set(repoKey, chained);\n\n await previous;\n try {\n return await fn();\n } finally {\n release();\n if (this.repoLocks.get(repoKey) === chained) {\n this.repoLocks.delete(repoKey);\n }\n }\n }\n\n /**\n * Ensure control repository exists\n */\n private async ensureControlRepository(\n repoUrl: string,\n githubToken?: string\n ): Promise<string> {\n const { key, owner, repo } = this.getRepoKey(repoUrl);\n const controlPath = path.join(this.repoBasePath, \"repos\", key, \"control\");\n\n // Check if control repository already exists\n try {\n // Support both bare repos (config/objects at root) and legacy non-bare repos (.git/)\n const hasGitDir = await fs\n .access(path.join(controlPath, \".git\"))\n .then(() => true)\n .catch(() => false);\n\n const hasBareLayout = await fs\n .access(path.join(controlPath, \"config\"))\n .then(() => fs.access(path.join(controlPath, \"objects\")).then(() => true))\n .catch(() => false);\n\n if (!hasGitDir && !hasBareLayout) {\n throw new Error(\"missing\");\n }\n\n console.log(`Control repository already exists for ${key}`);\n\n // Update remote URL if token changed\n if (githubToken) {\n const git = simpleGit(controlPath);\n const authUrl = this.getAuthenticatedUrl(repoUrl, githubToken);\n await git.remote([\"set-url\", \"origin\", authUrl]);\n }\n\n // Fetch latest changes\n const git = simpleGit(controlPath);\n await git.fetch(\"origin\");\n\n return controlPath;\n } catch {\n // Control repository doesn't exist, create it\n console.log(`Creating control repository for ${key}...`);\n\n await this.ensureDirectory(path.dirname(controlPath));\n\n const authUrl = this.getAuthenticatedUrl(repoUrl, githubToken);\n await this.executeGit([\"clone\", \"--bare\", authUrl, controlPath]);\n\n console.log(`Successfully created control repository for ${key}`);\n return controlPath;\n }\n }\n\n /**\n * Create a task-specific worktree for local workspaces\n */\n async createLocalTaskHandle(\n taskId: string,\n localPath: string\n ): Promise<TaskHandle> {\n // For local workspaces, we don't create worktrees or branches\n // Just return a handle pointing to the local path\n const handle: TaskHandle = {\n taskId,\n worktreePath: localPath,\n branch: \"local\", // Placeholder branch name for local workspaces\n baseBranch: \"local\",\n };\n\n // Create and persist state for tracking\n const state: TaskGitState = {\n taskId,\n branch: \"local\",\n baseBranch: \"local\",\n worktreePath: localPath,\n status: \"active\",\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n\n // Store state using a special key for local workspaces\n await this.updateTaskState(\"__local__\", state);\n\n console.log(`Created local task handle for task ${taskId} at ${localPath}`);\n return handle;\n }\n\n /**\n * Create a task-specific worktree\n */\n async createTaskWorktree(\n taskId: string,\n workspaceId: string,\n repoUrl: string,\n baseBranch: string = \"main\",\n githubToken?: string\n ): Promise<TaskHandle> {\n const { key, owner, repo } = this.getRepoKey(repoUrl);\n\n // Reuse an existing worktree/branch for this task when possible\n const existing = this.findTaskStateEntry(taskId);\n if (existing && existing.repoKey !== \"__local__\" && existing.taskState.branch !== \"local\") {\n const expectedWorktreePath = path.join(\n this.taskWorktreesBasePath,\n existing.repoKey,\n `task_${taskId}`\n );\n const worktreePath = existing.taskState.worktreePath || expectedWorktreePath;\n const shouldPersistMetadata =\n existing.taskState.workspaceId !== workspaceId ||\n existing.taskState.baseBranch !== baseBranch;\n\n if (shouldPersistMetadata) {\n existing.taskState.workspaceId = workspaceId;\n existing.taskState.baseBranch = baseBranch;\n existing.taskState.updatedAt = new Date();\n await this.updateTaskStateByTaskId(taskId, existing.taskState);\n }\n\n try {\n await fs.access(worktreePath);\n return {\n taskId,\n worktreePath,\n branch: existing.taskState.branch,\n baseBranch: existing.taskState.baseBranch,\n };\n } catch {\n // Recreate missing worktree from the existing branch\n const git = simpleGit(existing.repo.controlPath);\n await this.ensureDirectory(path.dirname(worktreePath));\n\n try {\n await git.raw([\"worktree\", \"add\", worktreePath, existing.taskState.branch]);\n } catch (error) {\n console.error(`Failed to recreate worktree for task ${taskId}:`, error);\n await this.cleanupDirectory(worktreePath);\n throw error;\n }\n\n const worktreeGit = simpleGit(worktreePath);\n await worktreeGit.addConfig(\"user.name\", \"Northflare\");\n await worktreeGit.addConfig(\"user.email\", \"runner@northflare.ai\");\n\n existing.taskState.worktreePath = worktreePath;\n existing.taskState.workspaceId = workspaceId;\n existing.taskState.baseBranch = baseBranch;\n existing.taskState.status = \"active\";\n existing.taskState.updatedAt = new Date();\n await this.updateTaskState(existing.repoKey, existing.taskState);\n\n return {\n taskId,\n worktreePath,\n branch: existing.taskState.branch,\n baseBranch: existing.taskState.baseBranch,\n };\n }\n }\n\n const isLocalRepo = repoUrl.startsWith(\"file://\");\n\n // Ensure control repository exists\n let controlPath: string;\n if (isLocalRepo) {\n controlPath = repoUrl.replace(\"file://\", \"\");\n\n // Verify local path exists and has a Git directory\n const stats = await fs.stat(controlPath);\n if (!stats.isDirectory()) {\n throw new Error(`Local repository path is not a directory: ${controlPath}`);\n }\n await fs.access(path.join(controlPath, \".git\"));\n } else {\n controlPath = await this.ensureControlRepository(repoUrl, githubToken);\n }\n\n const worktreesPath = path.join(this.taskWorktreesBasePath, key);\n const taskWorktreePath = path.join(worktreesPath, `task_${taskId}`);\n\n // Create unique branch name for the task\n const branchName = `task/${taskId}`;\n\n try {\n console.log(`Creating worktree for task ${taskId} on branch ${branchName}...`);\n\n // Create worktree directory\n await this.ensureDirectory(worktreesPath);\n\n // Add worktree with new branch based on baseBranch\n const git = simpleGit(controlPath);\n const baseRef = isLocalRepo ? baseBranch : `origin/${baseBranch}`;\n let baseRefIsValid = await git\n .raw([\"rev-parse\", \"--verify\", `${baseRef}^{commit}`])\n .then(() => true)\n .catch(() => false);\n\n if (!baseRefIsValid) {\n const hasAnyCommit = await git\n .raw([\"rev-parse\", \"--verify\", \"HEAD^{commit}\"])\n .then(() => true)\n .catch(() => false);\n\n if (!hasAnyCommit) {\n await this.ensureInitialCommitOnBranch(controlPath, baseBranch);\n baseRefIsValid = await git\n .raw([\"rev-parse\", \"--verify\", `${baseRef}^{commit}`])\n .then(() => true)\n .catch(() => false);\n }\n\n if (!baseRefIsValid) {\n throw new Error(\n `Cannot create a task worktree for ${taskId}: base branch '${baseBranch}' is not a valid Git reference in ${controlPath}. Set Workspace → Settings → Git branch to an existing branch name and retry.`\n );\n }\n }\n\n const branchExists = await git\n .raw([\"show-ref\", \"--verify\", `refs/heads/${branchName}`])\n .then(() => true)\n .catch(() => false);\n\n if (branchExists) {\n await git.raw([\"worktree\", \"add\", taskWorktreePath, branchName]);\n } else {\n await git.raw([\n \"worktree\",\n \"add\",\n \"-b\",\n branchName,\n taskWorktreePath,\n baseRef,\n ]);\n }\n\n // Configure the worktree\n const worktreeGit = simpleGit(taskWorktreePath);\n await worktreeGit.addConfig(\"user.name\", \"Northflare\");\n await worktreeGit.addConfig(\"user.email\", \"runner@northflare.ai\");\n\n // Create and persist state\n const state: TaskGitState = {\n taskId,\n workspaceId,\n branch: branchName,\n baseBranch,\n worktreePath: taskWorktreePath,\n status: \"active\",\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n\n await this.updateTaskState(key, state, { owner, repo, controlPath });\n\n console.log(`Successfully created worktree for task ${taskId}`);\n\n return {\n taskId,\n worktreePath: taskWorktreePath,\n branch: branchName,\n baseBranch,\n };\n } catch (error) {\n console.error(`Failed to create worktree for task ${taskId}:`, error);\n // Cleanup on failure\n await this.cleanupDirectory(taskWorktreePath);\n throw error;\n }\n }\n\n private async ensureInitialCommitOnBranch(\n repoPath: string,\n branchName: string\n ): Promise<void> {\n const git = simpleGit(repoPath);\n\n await git.addConfig(\"user.name\", \"Northflare\");\n await git.addConfig(\"user.email\", \"runner@northflare.ai\");\n\n const hasAnyCommit = await git\n .raw([\"rev-parse\", \"--verify\", \"HEAD^{commit}\"])\n .then(() => true)\n .catch(() => false);\n\n if (hasAnyCommit) return;\n\n console.log(\n `Repository at ${repoPath} has no commits; creating an empty initial commit on '${branchName}'...`\n );\n\n const isBareRepo = await git\n .raw([\"rev-parse\", \"--is-bare-repository\"])\n .then((output) => output.trim() === \"true\")\n .catch(() => false);\n\n if (isBareRepo) {\n const emptyTreeHash = \"4b825dc642cb6eb9a060e54bf8d69288fbee4904\";\n const commitHash = (await git.raw([\n \"commit-tree\",\n emptyTreeHash,\n \"-m\",\n \"Initial commit\",\n ])).trim();\n\n await git.raw([\"update-ref\", `refs/heads/${branchName}`, commitHash]);\n await git.raw([\"symbolic-ref\", \"HEAD\", `refs/heads/${branchName}`]);\n\n const remotes = await git.getRemotes(true);\n const hasOrigin = remotes.some((remote) => remote.name === \"origin\");\n void hasOrigin;\n } else {\n await git.raw([\"checkout\", \"--orphan\", branchName]);\n await git.raw([\"commit\", \"--allow-empty\", \"-m\", \"Initial commit\"]);\n }\n }\n\n /**\n * Remove a task worktree\n */\n async removeTaskWorktree(\n taskId: string,\n options: RemoveOptions = {}\n ): Promise<void> {\n const entry = this.findTaskStateEntry(taskId);\n if (!entry) {\n console.log(`No worktree found for task ${taskId}`);\n return;\n }\n\n const { repoKey, repo, taskState } = entry;\n\n // Handle local workspaces differently\n if (repoKey === \"__local__\") {\n // Just remove from state, don't touch the filesystem\n const repoState = this.repoStates.get(repoKey);\n const repo = repoState?.repositories?.[repoKey];\n if (repo?.worktrees?.[taskId]) {\n delete repo.worktrees[taskId];\n }\n await this.persistState();\n console.log(`Removed local task handle for task ${taskId}`);\n return;\n }\n\n const controlPath = repo.controlPath;\n\n try {\n console.log(`Removing worktree for task ${taskId}...`);\n\n const git = simpleGit(controlPath);\n\n // Remove the worktree (when present)\n if (taskState.worktreePath) {\n const worktreePath = taskState.worktreePath;\n try {\n await fs.access(worktreePath);\n await git.raw([\"worktree\", \"remove\", worktreePath, \"--force\"]);\n } catch {\n // Worktree path already gone; continue so we can still delete the branch if needed\n } finally {\n await this.cleanupDirectory(worktreePath);\n }\n }\n\n // Delete the branch if not preserving\n if (!options.preserveBranch) {\n try {\n await git.raw([\"branch\", \"-D\", taskState.branch]);\n } catch (error) {\n console.warn(`Failed to delete branch ${taskState.branch}:`, error);\n }\n }\n\n // Update state\n const repoState = this.repoStates.get(repoKey);\n if (repoState?.repositories[repoKey]?.worktrees) {\n if (options.preserveBranch) {\n repoState.repositories[repoKey].worktrees[taskId] = {\n ...taskState,\n worktreePath: \"\",\n updatedAt: new Date(),\n };\n } else {\n delete repoState.repositories[repoKey].worktrees[taskId];\n }\n }\n await this.persistState();\n\n console.log(`Successfully removed worktree for task ${taskId}`);\n } catch (error) {\n console.error(`Failed to remove worktree for task ${taskId}:`, error);\n if (options.force) {\n // Force cleanup\n await this.cleanupDirectory(taskState.worktreePath);\n } else {\n throw error;\n }\n }\n }\n\n /**\n * Stage all changes in a task worktree\n */\n async stageAll(taskId: string): Promise<void> {\n const taskState = await this.getTaskState(taskId);\n if (!taskState) {\n throw new Error(`No worktree found for task ${taskId}`);\n }\n\n // Skip Git operations for local workspaces\n if (taskState.branch === \"local\") {\n console.log(\n `Skipping stage operation for local workspace task ${taskId}`\n );\n return;\n }\n\n const git = simpleGit(taskState.worktreePath);\n await git.add(\".\");\n\n console.log(`Staged all changes for task ${taskId}`);\n }\n\n /**\n * Commit changes in a task worktree\n */\n async commit(\n taskId: string,\n message: string,\n author?: GitAuthor\n ): Promise<string> {\n const taskState = await this.getTaskState(taskId);\n if (!taskState) {\n throw new Error(`No worktree found for task ${taskId}`);\n }\n\n // Skip Git operations for local workspaces\n if (taskState.branch === \"local\") {\n console.log(\n `Skipping commit operation for local workspace task ${taskId}`\n );\n return \"local-commit\"; // Return a placeholder commit hash\n }\n\n const git = simpleGit(taskState.worktreePath);\n\n // Set author if provided\n if (author) {\n await git.addConfig(\"user.name\", author.name);\n await git.addConfig(\"user.email\", author.email);\n }\n\n // Commit changes\n const result = await git.commit(message);\n const commitHash = result.commit;\n\n // Update task state\n taskState.lastCommit = commitHash;\n taskState.commitCount = (taskState.commitCount ?? 0) + 1;\n taskState.updatedAt = new Date();\n await this.updateTaskStateByTaskId(taskId, taskState);\n\n console.log(`Created commit ${commitHash} for task ${taskId}`);\n logger.info(`Committed task ${taskId} (${taskState.branch}) -> ${commitHash}`, {\n taskId,\n branch: taskState.branch,\n baseBranch: taskState.baseBranch,\n commit: commitHash,\n worktreePath: taskState.worktreePath,\n });\n return commitHash;\n }\n\n /**\n * Create a new branch for a task\n */\n async createBranch(taskId: string, branchName: string): Promise<void> {\n const taskState = await this.getTaskState(taskId);\n if (!taskState) {\n throw new Error(`No worktree found for task ${taskId}`);\n }\n\n // Skip Git operations for local workspaces\n if (taskState.branch === \"local\") {\n console.log(\n `Skipping branch creation for local workspace task ${taskId}`\n );\n return;\n }\n\n const git = simpleGit(taskState.worktreePath);\n await git.checkoutBranch(branchName, taskState.branch);\n\n // Update task state\n taskState.branch = branchName;\n taskState.updatedAt = new Date();\n await this.updateTaskStateByTaskId(taskId, taskState);\n\n console.log(`Created branch ${branchName} for task ${taskId}`);\n }\n\n /**\n * Rebase a task branch onto target branch\n */\n async rebaseTask(\n taskId: string,\n targetBranch: string\n ): Promise<RebaseResult> {\n const taskState = await this.getTaskState(taskId);\n if (!taskState) {\n throw new Error(`No worktree found for task ${taskId}`);\n }\n\n // Skip Git operations for local workspaces\n if (taskState.branch === \"local\") {\n console.log(\n `Skipping rebase operation for local workspace task ${taskId}`\n );\n return { success: true }; // Return success for local workspaces\n }\n\n const git = simpleGit(taskState.worktreePath);\n\n try {\n const remotes = await git.getRemotes(true);\n const hasOrigin = remotes.some((r) => r.name === \"origin\");\n\n logger.info(\n `Rebasing task ${taskId} (${taskState.branch}) onto ${targetBranch}`,\n {\n taskId,\n branch: taskState.branch,\n targetBranch,\n hasOrigin,\n worktreePath: taskState.worktreePath,\n }\n );\n\n if (hasOrigin) {\n // Fetch latest changes\n await git.fetch(\"origin\", targetBranch);\n // Perform rebase\n await git.rebase([`origin/${targetBranch}`]);\n } else {\n await git.rebase([targetBranch]);\n }\n\n // Update base branch in state\n taskState.baseBranch = targetBranch;\n taskState.updatedAt = new Date();\n await this.updateTaskStateByTaskId(taskId, taskState);\n\n console.log(`Successfully rebased task ${taskId} onto ${targetBranch}`);\n logger.info(\n `Rebased task ${taskId} (${taskState.branch}) onto ${targetBranch}`,\n {\n taskId,\n branch: taskState.branch,\n targetBranch,\n }\n );\n return { success: true };\n } catch (error) {\n console.error(`Rebase failed for task ${taskId}:`, error);\n logger.error(`Rebase failed for task ${taskId} (${taskState.branch})`, {\n taskId,\n branch: taskState.branch,\n targetBranch,\n error: error instanceof Error ? error.message : String(error),\n });\n\n // Check for conflicts\n const status = await git.status();\n if (status.conflicted.length > 0) {\n taskState.status = \"conflicted\";\n await this.updateTaskStateByTaskId(taskId, taskState);\n\n return {\n success: false,\n conflicts: status.conflicted,\n error: \"Rebase resulted in conflicts\",\n };\n }\n\n // Abort rebase on error\n try {\n await git.rebase([\"--abort\"]);\n } catch {\n // Ignore abort errors\n }\n\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n /**\n * Merge a task branch into target branch\n */\n async mergeTask(\n taskId: string,\n targetBranch: string,\n mode: MergeMode = \"no-ff\"\n ): Promise<MergeResult> {\n const entry = this.findTaskStateEntry(taskId);\n if (!entry) {\n throw new Error(`No worktree found for task ${taskId}`);\n }\n\n const { repoKey, taskState } = entry;\n\n // Skip Git operations for local workspaces\n if (taskState.branch === \"local\") {\n console.log(\n `Skipping merge operation for local workspace task ${taskId}`\n );\n return { success: true, mergedCommit: \"local-merge\" }; // Return success for local workspaces\n }\n\n return await this.withRepoLock(repoKey, async () => {\n return this.mergeTaskUnlocked(entry, targetBranch, mode);\n });\n }\n\n private async mergeTaskUnlocked(\n entry: {\n repoKey: string;\n repo: RepositoryState[\"repositories\"][string];\n taskState: TaskGitState;\n },\n targetBranch: string,\n mode: MergeMode\n ): Promise<MergeResult> {\n const { repoKey, repo, taskState } = entry;\n const isLocalRepo = repoKey.startsWith(\"local__\");\n const mergePath = await (async () => {\n if (isLocalRepo) return repo.controlPath;\n\n if (!taskState.workspaceId) {\n throw new Error(\n `Cannot merge task ${taskState.taskId}: missing workspaceId in task Git state`\n );\n }\n\n const worktreesPath = path.join(\n this.repoBasePath,\n \"repos\",\n repoKey,\n \"worktrees\"\n );\n const workspaceWorktreePath = path.join(\n worktreesPath,\n `workspace_${taskState.workspaceId}`\n );\n\n const exists = await fs\n .access(workspaceWorktreePath)\n .then(() => true)\n .catch(() => false);\n\n if (exists) return workspaceWorktreePath;\n\n await this.ensureDirectory(worktreesPath);\n\n const controlGit = simpleGit(repo.controlPath);\n await controlGit.fetch(\"origin\", targetBranch);\n\n await controlGit.raw([\n \"worktree\",\n \"add\",\n workspaceWorktreePath,\n `origin/${targetBranch}`,\n ]);\n\n console.log(\n `Created merge worktree for workspace ${taskState.workspaceId} at ${workspaceWorktreePath}`\n );\n\n return workspaceWorktreePath;\n })();\n const git = simpleGit(mergePath);\n\n try {\n const remotes = await git.getRemotes(true);\n const hasOrigin = remotes.some((r) => r.name === \"origin\");\n\n logger.info(\n `Merging task ${taskState.taskId} (${taskState.branch}) into ${targetBranch}`,\n {\n taskId: taskState.taskId,\n taskBranch: taskState.branch,\n targetBranch,\n mergePath,\n hasOrigin,\n isLocalRepo,\n mode,\n }\n );\n\n if (hasOrigin) {\n // Fetch latest changes and ensure a local targetBranch exists + is up-to-date\n await git.fetch(\"origin\", targetBranch);\n\n const localBranches = await git.branchLocal();\n const hasLocalTarget = localBranches.all.includes(targetBranch);\n\n if (!hasLocalTarget) {\n await git.raw([\"checkout\", \"-B\", targetBranch, `origin/${targetBranch}`]);\n } else {\n await git.checkout(targetBranch);\n try {\n await git.merge([\"--ff-only\", `origin/${targetBranch}`]);\n } catch (error) {\n throw new Error(\n `Base branch ${targetBranch} has diverged from origin/${targetBranch}; cannot fast-forward`\n );\n }\n }\n } else {\n await git.checkout(targetBranch);\n }\n\n // Perform merge based on mode\n let mergeArgs: string[] = [];\n switch (mode) {\n case \"ff-only\":\n mergeArgs = [\"--ff-only\"];\n break;\n case \"no-ff\":\n mergeArgs = [\"--no-ff\"];\n break;\n case \"squash\":\n mergeArgs = [\"--squash\"];\n break;\n }\n\n const result = await git.merge([...mergeArgs, taskState.branch]);\n\n // For squash merge, we need to commit\n if (mode === \"squash\") {\n const commitResult = await git.commit(\n `Merge task ${taskState.taskId} (${taskState.branch})`\n );\n result.result = commitResult.commit;\n }\n\n // Update task state\n taskState.status = \"merged\";\n taskState.updatedAt = new Date();\n await this.updateTaskStateByTaskId(taskState.taskId, taskState);\n\n console.log(\n `Successfully merged task ${taskState.taskId} into ${targetBranch}`\n );\n logger.info(\n `Merged task ${taskState.taskId} (${taskState.branch}) into ${targetBranch}`,\n {\n taskId: taskState.taskId,\n taskBranch: taskState.branch,\n targetBranch,\n mergedCommit: result.result,\n }\n );\n return {\n success: true,\n mergedCommit: result.result,\n };\n } catch (error) {\n console.error(`Merge failed for task ${taskState.taskId}:`, error);\n logger.error(`Merge failed for task ${taskState.taskId} (${taskState.branch})`, {\n taskId: taskState.taskId,\n taskBranch: taskState.branch,\n targetBranch,\n mergePath,\n error: error instanceof Error ? error.message : String(error),\n });\n\n // Check for conflicts\n try {\n const status = await git.status();\n if (status.conflicted.length > 0) {\n taskState.status = \"conflicted\";\n await this.updateTaskStateByTaskId(taskState.taskId, taskState);\n\n return {\n success: false,\n conflicts: status.conflicted,\n error: \"Merge resulted in conflicts\",\n };\n }\n } catch {\n // Ignore status errors (e.g. bare repositories)\n }\n\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n async getTaskRepoInfo(taskId: string): Promise<{\n repoKey: string;\n controlPath: string;\n worktreePath: string;\n branch: string;\n baseBranch: string;\n } | null> {\n const entry = this.findTaskStateEntry(taskId);\n if (!entry) return null;\n\n return {\n repoKey: entry.repoKey,\n controlPath: entry.repo.controlPath,\n worktreePath: entry.taskState.worktreePath,\n branch: entry.taskState.branch,\n baseBranch: entry.taskState.baseBranch,\n };\n }\n\n /**\n * Fast-forward (or hard reset) the shared workspace worktree to a branch tip after a task merge.\n * This keeps the \"workspace\" checkout in sync with concurrent task integrations.\n *\n * We only update existing workspace worktrees and only when they're clean to avoid\n * clobbering any active non-concurrent task that might be using the workspace checkout.\n */\n async syncWorkspaceWorktree(\n workspaceId: string,\n repoUrl: string,\n branch: string\n ): Promise<void> {\n if (!workspaceId || !repoUrl) return;\n\n // Local repos merge directly into the primary working tree (controlPath), nothing to sync.\n if (repoUrl.startsWith(\"file://\")) return;\n\n const { key } = this.getRepoKey(repoUrl);\n const workspaceWorktreePath = path.join(\n this.repoBasePath,\n \"repos\",\n key,\n \"worktrees\",\n `workspace_${workspaceId}`\n );\n\n const exists = await fs\n .access(workspaceWorktreePath)\n .then(() => true)\n .catch(() => false);\n\n await this.withRepoLock(key, async () => {\n if (!exists) {\n const controlPath = path.join(this.repoBasePath, \"repos\", key, \"control\");\n const controlExists = await fs\n .access(controlPath)\n .then(() => true)\n .catch(() => false);\n if (!controlExists) {\n console.warn(\n `Skipping workspace worktree sync for ${workspaceId}: control repo missing`,\n { controlPath, repoUrl }\n );\n return;\n }\n\n await this.ensureDirectory(path.dirname(workspaceWorktreePath));\n\n const controlGit = simpleGit(controlPath);\n const remotes = await controlGit.getRemotes(true);\n const hasOrigin = remotes.some((remote) => remote.name === \"origin\");\n const checkoutRef = hasOrigin ? `origin/${branch}` : branch;\n\n await controlGit.raw([\"worktree\", \"add\", workspaceWorktreePath, checkoutRef]);\n\n console.log(\n `Created workspace worktree for ${workspaceId} at ${workspaceWorktreePath}`\n );\n }\n\n const git = simpleGit(workspaceWorktreePath);\n const status = await git.status();\n\n if (status.conflicted.length > 0 || !status.isClean()) {\n console.warn(\n `Skipping workspace worktree sync for ${workspaceId}: worktree is not clean`,\n {\n path: workspaceWorktreePath,\n branch,\n conflicted: status.conflicted,\n fileCount: status.files.length,\n }\n );\n return;\n }\n\n const remotes = await git.getRemotes(true);\n const hasOrigin = remotes.some((remote) => remote.name === \"origin\");\n\n if (hasOrigin) {\n await git.fetch(\"origin\", branch);\n await git.reset([\"--hard\", `origin/${branch}`]);\n } else {\n await git.reset([\"--hard\", branch]);\n }\n\n await git.clean(\"f\", [\"-d\"]);\n\n console.log(\n `Synced workspace worktree for ${workspaceId} to ${branch} at ${workspaceWorktreePath}`\n );\n });\n }\n\n async isTaskBranchMerged(taskId: string, targetBranch: string): Promise<boolean> {\n const entry = this.findTaskStateEntry(taskId);\n if (!entry) return false;\n\n const { repo, taskState } = entry;\n const git = simpleGit(repo.controlPath);\n\n try {\n // Ensure targetBranch exists locally (avoid erroring for repos that only have origin/<branch>)\n const showRef = await git.raw([\n \"show-ref\",\n \"--verify\",\n `refs/heads/${targetBranch}`,\n ]);\n if (!showRef?.trim()) return false;\n } catch {\n return false;\n }\n\n try {\n await git.raw([\n \"merge-base\",\n \"--is-ancestor\",\n taskState.branch,\n targetBranch,\n ]);\n return true;\n } catch {\n return false;\n }\n }\n\n async pushBranch(taskId: string, branch: string): Promise<void> {\n const entry = this.findTaskStateEntry(taskId);\n if (!entry) return;\n\n const git = simpleGit(entry.repo.controlPath);\n const remotes = await git.getRemotes(true);\n const hasOrigin = remotes.some((r) => r.name === \"origin\");\n if (!hasOrigin) return;\n\n await git.push(\"origin\", branch);\n }\n\n async integrateTask(\n taskId: string,\n targetBranch: string,\n mode: MergeMode = \"no-ff\"\n ): Promise<TaskIntegrationResult> {\n const entry = this.findTaskStateEntry(taskId);\n if (!entry) {\n return {\n success: false,\n phase: \"merge\",\n error: `No worktree found for task ${taskId}`,\n conflictWorkdir: \"\",\n };\n }\n\n const { repoKey, repo, taskState } = entry;\n const isLocalRepo = repoKey.startsWith(\"local__\");\n const mergeWorkdir = isLocalRepo\n ? repo.controlPath\n : taskState.workspaceId\n ? path.join(\n this.repoBasePath,\n \"repos\",\n repoKey,\n \"worktrees\",\n `workspace_${taskState.workspaceId}`\n )\n : taskState.worktreePath;\n\n logger.info(`Integrating task ${taskId} (${taskState.branch}) into ${targetBranch}`, {\n taskId,\n taskBranch: taskState.branch,\n targetBranch,\n mode,\n isLocalRepo,\n controlPath: repo.controlPath,\n worktreePath: taskState.worktreePath,\n });\n\n return await this.withRepoLock(repoKey, async () => {\n const rebaseResult = await this.rebaseTask(taskId, targetBranch);\n if (!rebaseResult.success) {\n logger.warn(`Task ${taskId} rebase failed`, {\n taskId,\n phase: \"rebase\",\n targetBranch,\n conflicts: rebaseResult.conflicts ?? [],\n error: rebaseResult.error,\n });\n return {\n success: false,\n phase: \"rebase\",\n conflicts: rebaseResult.conflicts ?? [],\n error: rebaseResult.error,\n conflictWorkdir: taskState.worktreePath,\n };\n }\n\n const mergeResult = await this.mergeTaskUnlocked(entry, targetBranch, mode);\n if (!mergeResult.success) {\n logger.warn(`Task ${taskId} merge failed`, {\n taskId,\n phase: \"merge\",\n targetBranch,\n conflicts: mergeResult.conflicts ?? [],\n error: mergeResult.error,\n });\n return {\n success: false,\n phase: \"merge\",\n conflicts: mergeResult.conflicts ?? [],\n error: mergeResult.error,\n conflictWorkdir: mergeWorkdir,\n };\n }\n\n logger.info(`Integrated task ${taskId} into ${targetBranch}`, {\n taskId,\n targetBranch,\n mergedCommit: mergeResult.mergedCommit,\n });\n return {\n success: true,\n mergedCommit: mergeResult.mergedCommit,\n };\n });\n }\n\n /**\n * Get task Git state\n */\n async getTaskState(taskId: string): Promise<TaskGitState | null> {\n return this.findTaskStateEntry(taskId)?.taskState ?? null;\n }\n\n /**\n * Update task state\n */\n private async updateTaskState(\n repoKey: string,\n state: TaskGitState,\n repoInfo?: { owner: string; repo: string; controlPath: string }\n ): Promise<void> {\n if (!this.repoStates.has(repoKey)) {\n this.repoStates.set(repoKey, {\n repositories: {},\n });\n }\n\n const repoState = this.repoStates.get(repoKey)!;\n if (!repoState.repositories[repoKey]) {\n // Handle special case for local workspaces\n if (repoKey === \"__local__\") {\n repoState.repositories[repoKey] = {\n owner: \"local\",\n repo: \"local\",\n controlPath: \"local\",\n worktrees: {},\n };\n } else if (repoInfo) {\n repoState.repositories[repoKey] = {\n owner: repoInfo.owner,\n repo: repoInfo.repo,\n controlPath: repoInfo.controlPath,\n worktrees: {},\n };\n } else {\n const { owner, repo } = this.parseRepoKey(repoKey);\n repoState.repositories[repoKey] = {\n owner,\n repo,\n controlPath: path.join(\n this.repoBasePath,\n \"repos\",\n repoKey,\n \"control\"\n ),\n worktrees: {},\n };\n }\n } else if (repoInfo?.controlPath) {\n // Ensure we persist the latest controlPath (important for local repos)\n repoState.repositories[repoKey].controlPath = repoInfo.controlPath;\n }\n\n repoState.repositories[repoKey].worktrees[state.taskId] = state;\n await this.persistState();\n }\n\n /**\n * Update task state by task ID\n */\n private async updateTaskStateByTaskId(\n taskId: string,\n state: TaskGitState\n ): Promise<void> {\n for (const [repoKey, repoState] of this.repoStates) {\n for (const repo of Object.values(repoState.repositories)) {\n if (repo.worktrees[taskId]) {\n repo.worktrees[taskId] = state;\n await this.persistState();\n return;\n }\n }\n }\n }\n\n /**\n * Persist state to disk\n */\n async persistState(): Promise<void> {\n try {\n const stateData: Record<string, RepositoryState> = {};\n for (const [key, value] of this.repoStates) {\n stateData[key] = value;\n }\n\n await this.ensureDirectory(path.dirname(this.stateFilePath));\n await fs.writeFile(\n this.stateFilePath,\n JSON.stringify(stateData, null, 2)\n );\n\n console.log(\"Persisted repository state\");\n } catch (error) {\n console.error(\"Failed to persist repository state:\", error);\n }\n }\n\n /**\n * Restore state from disk\n */\n async restoreState(): Promise<void> {\n await this.migrateLegacyStateFileIfNeeded();\n\n try {\n const data = await fs.readFile(this.stateFilePath, \"utf-8\");\n const stateData = JSON.parse(data) as Record<string, RepositoryState>;\n\n this.repoStates.clear();\n for (const [key, value] of Object.entries(stateData)) {\n // Convert date strings back to Date objects\n for (const repo of Object.values(value.repositories)) {\n for (const worktree of Object.values(repo.worktrees)) {\n worktree.createdAt = new Date(worktree.createdAt);\n worktree.updatedAt = new Date(worktree.updatedAt);\n }\n }\n this.repoStates.set(key, value);\n }\n\n console.log(\"Restored repository state\");\n } catch (error) {\n if ((error as any).code !== \"ENOENT\") {\n console.error(\"Failed to restore repository state:\", error);\n }\n // If file doesn't exist, that's okay - we'll start fresh\n }\n }\n\n private async migrateLegacyStateFileIfNeeded(): Promise<void> {\n const hasNewStateFile = await fs\n .access(this.stateFilePath)\n .then(() => true)\n .catch(() => false);\n\n if (hasNewStateFile) return;\n\n const hasLegacyStateFile = await fs\n .access(this.legacyStateFilePath)\n .then(() => true)\n .catch(() => false);\n\n if (!hasLegacyStateFile) return;\n\n await this.ensureDirectory(path.dirname(this.stateFilePath));\n await fs.rename(this.legacyStateFilePath, this.stateFilePath);\n console.log(\n `Moved legacy repository state file to runner data directory: ${this.stateFilePath}`\n );\n }\n\n /**\n * Override parent's checkoutRepository to use worktrees for backward compatibility\n */\n override async checkoutRepository(\n workspaceId: string,\n repoUrl: string,\n branch: string,\n githubToken?: string\n ): Promise<string> {\n // If it's a local repository URL, delegate to parent's checkoutLocalRepository\n if (repoUrl.startsWith(\"file://\")) {\n const localPath = repoUrl.replace(\"file://\", \"\");\n return super.checkoutLocalRepository(workspaceId, localPath);\n }\n\n const { key } = this.getRepoKey(repoUrl);\n\n // Ensure control repository exists\n await this.ensureControlRepository(repoUrl, githubToken);\n\n // Create or update workspace worktree\n const worktreesPath = path.join(\n this.repoBasePath,\n \"repos\",\n key,\n \"worktrees\"\n );\n const workspaceWorktreePath = path.join(\n worktreesPath,\n `workspace_${workspaceId}`\n );\n\n try {\n // Check if workspace worktree already exists\n await fs.access(workspaceWorktreePath);\n\n // Update existing worktree\n const git = simpleGit(workspaceWorktreePath);\n await git.fetch(\"origin\");\n await git.reset([\"--hard\", `origin/${branch}`]);\n await git.clean(\"f\", [\"-d\"]);\n\n console.log(`Updated workspace worktree for ${workspaceId}`);\n } catch {\n // Create new workspace worktree\n const controlPath = path.join(this.repoBasePath, \"repos\", key, \"control\");\n const git = simpleGit(controlPath);\n\n await this.ensureDirectory(worktreesPath);\n await git.raw([\n \"worktree\",\n \"add\",\n workspaceWorktreePath,\n `origin/${branch}`,\n ]);\n\n console.log(`Created workspace worktree for ${workspaceId}`);\n }\n\n return workspaceWorktreePath;\n }\n}\n","/**\n * State Manager for persisting runner state\n * \n * Manages persistent state including lastProcessedAt timestamp\n * to enable proper catch-up on restart.\n */\n\nimport fs from 'fs/promises';\nimport path from 'path';\nimport { createLogger } from './logger.js';\n\nconst logger = createLogger('StateManager');\n\nexport interface RunnerState {\n runnerId: string;\n runnerUid: string | null;\n lastProcessedAt: string | null; // ISO string\n isActiveRunner: boolean;\n updatedAt: string; // ISO string\n}\n\nexport class StateManager {\n private statePath: string;\n private state: RunnerState | null = null;\n private saveTimer: NodeJS.Timeout | null = null;\n\n constructor(dataDir: string, runnerId: string) {\n // Namespace state file by runnerId (stable external ID) to separate different users\n const stateFile = `runner-state-${runnerId}.json`;\n this.statePath = path.join(dataDir, stateFile);\n }\n\n /**\n * Load state from disk\n */\n async loadState(): Promise<RunnerState | null> {\n try {\n const content = await fs.readFile(this.statePath, 'utf-8');\n this.state = JSON.parse(content);\n logger.info('Loaded runner state', {\n runnerId: this.state?.runnerId,\n runnerUid: this.state?.runnerUid,\n lastProcessedAt: this.state?.lastProcessedAt,\n isActiveRunner: this.state?.isActiveRunner,\n });\n return this.state;\n } catch (error) {\n if ((error as any).code === 'ENOENT') {\n logger.debug('No state file found, starting fresh');\n return null;\n }\n logger.error('Failed to load state file:', error);\n return null;\n }\n }\n\n /**\n * Save state to disk (debounced for non-critical updates)\n */\n async saveState(state: RunnerState): Promise<void> {\n this.state = state;\n\n // Cancel any pending save\n if (this.saveTimer) {\n clearTimeout(this.saveTimer);\n }\n\n // Debounce saves to avoid excessive disk writes\n // NOTE: lastProcessedAt updates use saveStateImmediate() instead\n this.saveTimer = setTimeout(async () => {\n await this.writeStateToDisk(state);\n }, 1000); // 1 second debounce for non-critical state\n }\n\n /**\n * Write state to disk immediately (no debounce)\n * Used for critical state like lastProcessedAt watermark\n */\n private async writeStateToDisk(state: RunnerState): Promise<void> {\n try {\n // Ensure directory exists\n const dir = path.dirname(this.statePath);\n await fs.mkdir(dir, { recursive: true });\n\n // Update timestamp\n state.updatedAt = new Date().toISOString();\n\n // Write atomically by writing to temp file first\n const tempPath = `${this.statePath}.tmp`;\n await fs.writeFile(tempPath, JSON.stringify(state, null, 2), 'utf-8');\n await fs.rename(tempPath, this.statePath);\n\n logger.debug('Saved runner state', {\n runnerId: state.runnerId,\n lastProcessedAt: state.lastProcessedAt,\n isActiveRunner: state.isActiveRunner,\n });\n } catch (error) {\n logger.error('Failed to save state file:', error);\n throw error;\n }\n }\n\n /**\n * Update lastProcessedAt timestamp\n *\n * CRITICAL: This writes to disk immediately (no debounce) to prevent\n * message replay on runner reconnection. If the watermark isn't persisted\n * before a disconnect, already-processed messages will be replayed.\n */\n async updateLastProcessedAt(timestamp: Date | string): Promise<void> {\n if (!this.state) {\n throw new Error('State not loaded');\n }\n\n const isoString = timestamp instanceof Date ? timestamp.toISOString() : timestamp;\n\n const updatedState: RunnerState = {\n ...this.state,\n lastProcessedAt: isoString,\n };\n\n // Update in-memory state immediately\n this.state = updatedState;\n\n // Write to disk immediately - critical for correctness on reconnection\n await this.writeStateToDisk(updatedState);\n }\n\n /**\n * Update runner registration details\n */\n async updateRunnerRegistration(\n runnerId: string,\n runnerUid: string | null,\n lastProcessedAt: Date | null\n ): Promise<void> {\n const state: RunnerState = this.state || {\n runnerId: '',\n runnerUid: null,\n lastProcessedAt: null,\n isActiveRunner: false,\n updatedAt: new Date().toISOString(),\n };\n\n const updatedState: RunnerState = {\n ...state,\n runnerId,\n runnerUid,\n lastProcessedAt: lastProcessedAt ? lastProcessedAt.toISOString() : null,\n };\n\n await this.saveState(updatedState);\n }\n\n /**\n * Update active runner status\n */\n async updateActiveStatus(isActive: boolean): Promise<void> {\n if (!this.state) {\n throw new Error('State not loaded');\n }\n\n const updatedState: RunnerState = {\n ...this.state,\n isActiveRunner: isActive,\n };\n\n await this.saveState(updatedState);\n }\n\n /**\n * Get current state\n */\n getState(): RunnerState | null {\n return this.state;\n }\n\n /**\n * Get lastProcessedAt as Date\n */\n getLastProcessedAt(): Date | null {\n if (!this.state || !this.state.lastProcessedAt) {\n return null;\n }\n return new Date(this.state.lastProcessedAt);\n }\n\n /**\n * Clear state (for testing or reset)\n */\n async clearState(): Promise<void> {\n this.state = null;\n try {\n await fs.unlink(this.statePath);\n logger.info('Cleared runner state');\n } catch (error) {\n if ((error as any).code !== 'ENOENT') {\n logger.error('Failed to clear state file:', error);\n throw error;\n }\n }\n }\n}","/**\n * Main RunnerApp class - entry point and lifecycle manager for the runner app\n * Updated to use SSE for real-time messaging instead of ElectricSQL\n */\n\nimport {\n RunnerConfig,\n ConversationContext,\n JsonRpcMessage,\n RetryStrategy,\n RunnerRepo,\n} from './types/index.js';\nimport { IRunnerApp } from './types/runner-interface.js';\nimport { MessageHandler } from './components/message-handler-sse.js';\nimport { ClaudeManager } from './components/claude-sdk-manager.js';\nimport { CodexManager } from './components/codex-sdk-manager.js';\nimport { NorthflareAgentManager } from './components/northflare-agent-sdk-manager.js';\nimport { EnhancedRepositoryManager } from './components/enhanced-repository-manager.js';\nimport { StateManager } from './utils/StateManager.js';\nimport { createLogger } from './utils/logger.js';\nimport { statusLineManager } from './utils/status-line.js';\nimport { isRunnerDebugEnabled } from './utils/debug.js';\nimport fs from \"fs/promises\";\nimport path from \"path\";\nimport computerName from \"computer-name\";\nimport {\n sanitizeToolResponsePayload,\n TOOL_RESPONSE_BYTE_LIMIT,\n} from './utils/tool-response-sanitizer.js';\nimport {\n buildOutgoingMessageLog,\n messageFlowLogger,\n messagesDebugEnabled,\n} from './utils/message-log.js';\nimport { RunnerAPIClient } from './services/RunnerAPIClient.js';\nimport { UpdateCoordinator } from './utils/update-coordinator.js';\nimport { RUNNER_VERSION } from './utils/version.js';\n\nfunction isSubPath(base: string | undefined, candidate: string): boolean {\n if (!base) return false;\n const normalizedBase = path.resolve(base);\n const normalizedCandidate = path.resolve(candidate);\n const baseWithSep =\n normalizedBase.endsWith(path.sep) ? normalizedBase : normalizedBase + path.sep;\n return (\n normalizedCandidate === normalizedBase ||\n normalizedCandidate.startsWith(baseWithSep)\n );\n}\n\nconst logger = createLogger(\"RunnerApp\");\n\nfunction logToolResponseTruncation(toolUseId?: string) {\n const message = `Tool response exceeded ${TOOL_RESPONSE_BYTE_LIMIT} bytes and was truncated`;\n if (toolUseId) {\n logger.warn(message, { toolUseId });\n } else {\n logger.warn(message);\n }\n}\n\nexport class RunnerApp implements IRunnerApp {\n private messageHandler!: MessageHandler;\n private claudeManager!: ClaudeManager;\n private codexManager!: CodexManager;\n private northflareAgentManager!: NorthflareAgentManager;\n private repositoryManager!: EnhancedRepositoryManager;\n private stateManager!: StateManager;\n private updateCoordinator!: UpdateCoordinator;\n private agentConversations: Map<string, ConversationContext>; // Keyed by conversation.id\n private config: RunnerConfig;\n private configPath?: string;\n private runnerReposCachePath?: string;\n private heartbeatInterval?: NodeJS.Timeout;\n private heartbeatInFlight: boolean = false;\n private isRunning: boolean = false;\n private isRegistered: boolean = false;\n private delayFn: (ms: number) => Promise<void> = (ms) =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\n // UID ownership fields\n private runnerUid: string | null = null;\n private lastProcessedAt: Date | null = null;\n private isActiveRunner: boolean = false;\n\n // Track conversations started before takeover\n private preHandoffConversations = new Set<string>();\n\n // Track recently completed conversation IDs to prevent restart on catch-up\n // Uses a Map with completion timestamp to allow cleanup of old entries\n private completedConversations = new Map<string, number>();\n private static readonly COMPLETED_CONVERSATION_TTL_MS = 60 * 60 * 1000; // 1 hour\n\n // Track summaries that arrive before a conversation starts.\n private pendingConversationSummaries = new Map<string, string>();\n\n constructor(config: RunnerConfig, configPath?: string) {\n this.config = config;\n this.configPath = configPath;\n this.agentConversations = new Map();\n this.runnerReposCachePath = path.join(this.config.dataDir, \"runner-repos-cache.json\");\n // Note: State manager will be initialized in start() after fetching runnerId\n }\n\n private async fetchRunnerId(): Promise<string> {\n const token = process.env[\"NORTHFLARE_RUNNER_TOKEN\"];\n if (!token) {\n throw new Error(\"NORTHFLARE_RUNNER_TOKEN environment variable is required\");\n }\n\n try {\n const response = await fetch(`${this.config.orchestratorUrl}/api/runner/id`, {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${token}`,\n },\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ error: response.statusText })) as any;\n throw new Error(`Failed to fetch runner ID: ${error.error || response.statusText}`);\n }\n\n const data = await response.json() as { runnerId?: string };\n if (!data.runnerId) {\n throw new Error(\"Server did not return runnerId\");\n }\n\n logger.info(`Fetched runnerId: ${data.runnerId}`);\n return data.runnerId;\n } catch (error) {\n logger.error(\"Failed to fetch runner ID from orchestrator\", error);\n throw error;\n }\n }\n\n private initializeComponents(): void {\n // Initialize repository manager first as it's used by Claude manager\n this.repositoryManager = new EnhancedRepositoryManager(this);\n\n // Initialize Claude manager with repository manager (using SDK-native manager)\n this.claudeManager = new ClaudeManager(this, this.repositoryManager);\n\n // Initialize Codex manager for OpenAI-based conversations\n this.codexManager = new CodexManager(this, this.repositoryManager);\n\n // Initialize Northflare Agent manager for OpenRouter-based conversations\n this.northflareAgentManager = new NorthflareAgentManager(\n this,\n this.repositoryManager\n );\n\n // Initialize message handler with SSE support\n this.messageHandler = new MessageHandler(this);\n\n // Initialize update coordinator for auto-updates\n this.updateCoordinator = new UpdateCoordinator({\n autoUpdateDisabled: process.env[\"NORTHFLARE_DISABLE_AUTO_UPDATE\"] === 'true',\n getActiveConversationCount: () => this.agentConversations.size,\n saveState: async () => {\n await this.stateManager.saveState({\n runnerId: this.config.runnerId!,\n runnerUid: this.runnerUid,\n lastProcessedAt: this.lastProcessedAt?.toISOString() || null,\n isActiveRunner: this.isActiveRunner,\n updatedAt: new Date().toISOString(),\n });\n },\n getConfigPath: () => this.configPath,\n });\n }\n\n async start(): Promise<void> {\n if (this.isRunning) {\n throw new Error(\"Runner is already running\");\n }\n\n try {\n // Fetch runnerId from orchestrator using token\n const runnerId = await this.fetchRunnerId();\n this.config.runnerId = runnerId;\n\n // Initialize state manager with runnerId\n this.stateManager = new StateManager(this.config.dataDir, runnerId);\n\n // Initialize other components\n this.initializeComponents();\n\n // Load persisted state\n const savedState = await this.stateManager.loadState();\n if (savedState) {\n // Restore state from previous run\n this.config.runnerId = savedState.runnerId;\n this.runnerUid = savedState.runnerUid;\n this.lastProcessedAt = savedState.lastProcessedAt\n ? new Date(savedState.lastProcessedAt)\n : null;\n this.isActiveRunner = savedState.isActiveRunner;\n\n logger.info(\"Restored runner state from disk\", {\n runnerId: savedState.runnerId,\n runnerUid: savedState.runnerUid,\n lastProcessedAt: savedState.lastProcessedAt,\n isActiveRunner: savedState.isActiveRunner,\n });\n }\n\n // Bootstrap runner repos from server (with cache fallback)\n await this.refreshRunnerReposFromServer(true);\n\n // Register with retry strategy\n await this.registerWithRetry();\n\n // Log debug info after registration\n if (isRunnerDebugEnabled()) {\n logger.debug(\"Runner initialized with ownership details\", {\n runnerId: this.config.runnerId,\n runnerUid: this.runnerUid,\n lastProcessedAt: this.lastProcessedAt?.toISOString() || \"null\",\n isActiveRunner: this.isActiveRunner,\n orchestratorUrl: this.config.orchestratorUrl,\n });\n }\n\n // Start message processing with SSE\n await this.messageHandler.startProcessing();\n\n // Start heartbeat after successful registration\n this.startHeartbeat();\n\n this.isRunning = true;\n\n logger.info(`Runner ${this.config.runnerId} started successfully`);\n } catch (error) {\n logger.error(\"Failed to start runner:\", error);\n throw error;\n }\n }\n\n async stop(): Promise<void> {\n if (!this.isRunning) {\n return;\n }\n\n logger.info(`Stopping runner ${this.config.runnerId}...`);\n\n // Stop heartbeat\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = undefined;\n }\n\n // Stop all conversations\n await this.stopAllConversations();\n\n // Stop message processing\n await this.messageHandler.stopProcessing();\n\n // Clean up status line\n statusLineManager.dispose();\n\n this.isRunning = false;\n\n logger.info(`Runner ${this.config.runnerId} stopped`);\n }\n\n async notify(method: string, params: any): Promise<void> {\n try {\n const sanitization = sanitizeToolResponsePayload(method, params);\n if (sanitization.truncated) {\n logToolResponseTruncation(sanitization.toolUseId);\n }\n const safeParams = sanitization.truncated\n ? sanitization.params\n : params;\n // Log RPC notification in debug mode\n logger.debug(`[RPC] Sending notification: ${method}`, {\n method,\n params: JSON.stringify(safeParams, null, 2),\n });\n\n // Send notification with retry logic\n await this.sendToOrchestratorWithRetry({\n jsonrpc: \"2.0\",\n method,\n params: safeParams,\n });\n } catch (error) {\n // Special handling for heartbeat errors - just log a simple line\n if (method === \"runner.heartbeat\") {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n logger.error(`Heartbeat failed: ${errorMessage}`);\n } else {\n // For other RPC errors, log the method and error without stack\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n logger.error(\n `RPC Error: Failed to notify with method '${method}': ${errorMessage}`\n );\n }\n throw error;\n }\n }\n\n async sendToOrchestrator(message: JsonRpcMessage): Promise<any> {\n const sanitization = sanitizeToolResponsePayload(\n message.method,\n message.params\n );\n if (sanitization.truncated) {\n logToolResponseTruncation(sanitization.toolUseId);\n }\n\n const messageToSend = sanitization.truncated\n ? {\n ...message,\n params: sanitization.params,\n }\n : message;\n\n try {\n if (messagesDebugEnabled()) {\n messageFlowLogger.debug(\n \"[outgoing] runner -> orchestrator\",\n {\n runnerId: this.config.runnerId,\n ...buildOutgoingMessageLog(messageToSend),\n }\n );\n }\n\n // Log RPC request in debug mode\n logger.debug(`[RPC] Sending request:`, {\n method: messageToSend.method,\n id: messageToSend.id,\n params: messageToSend.params\n ? JSON.stringify(messageToSend.params, null, 2)\n : undefined,\n });\n\n // Build headers - only include X-Runner-Id if we have one (not during registration)\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${process.env[\"NORTHFLARE_RUNNER_TOKEN\"]}`,\n };\n\n // Only add X-Runner-Id if we're registered (not during registration)\n if (this.config.runnerId && message.method !== \"runner.register\") {\n headers[\"X-Runner-Id\"] = this.config.runnerId;\n }\n\n const response = await fetch(\n `${this.config.orchestratorUrl}/api/runner/messages`,\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(messageToSend),\n signal: AbortSignal.timeout(30000), // 30 second timeout\n }\n );\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`HTTP ${response.status}: ${errorText}`);\n }\n\n const result = (await response.json()) as any;\n\n // Log RPC response in debug mode\n logger.debug(`[RPC] Received response:`, {\n method: messageToSend.method,\n id: messageToSend.id,\n result: result?.result\n ? JSON.stringify(result.result, null, 2)\n : undefined,\n error: result?.error\n ? JSON.stringify(result.error, null, 2)\n : undefined,\n });\n\n return result;\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n\n // Don't log verbose errors for heartbeat failures\n if (message.method === \"runner.heartbeat\") {\n // Heartbeat errors are already logged in notify()\n } else if (message.method === \"runner.register\") {\n // Special case for registration failures\n logger.error(`Registration failed: ${errorMessage}`);\n } else {\n // For other RPC messages, log the attempted message and error\n logger.error(`RPC failed:`, {\n method: messageToSend.method,\n params: messageToSend.params,\n error: errorMessage,\n });\n }\n throw error;\n }\n }\n\n getConversationContext(\n conversationId: string\n ): ConversationContext | undefined {\n // Using conversation.id as primary key for conversation tracking\n const context = this.agentConversations.get(conversationId);\n logger.debug(`[Runner] getConversationContext lookup:`, {\n conversationId,\n found: !!context,\n totalConversations: this.agentConversations.size,\n allConversationIds: Array.from(this.agentConversations.keys()),\n });\n return context;\n }\n\n applyConversationSummary(conversationId: string, summary: string | null): void {\n const normalizedSummary =\n typeof summary === \"string\" ? summary.replace(/\\s+/g, \" \").trim() : \"\";\n\n if (!normalizedSummary) return;\n\n const context = this.agentConversations.get(conversationId);\n if (context) {\n context.summary = normalizedSummary;\n return;\n }\n\n this.pendingConversationSummaries.set(conversationId, normalizedSummary);\n }\n\n consumePendingConversationSummary(conversationId: string): string | undefined {\n const summary = this.pendingConversationSummaries.get(conversationId);\n if (summary) {\n this.pendingConversationSummaries.delete(conversationId);\n }\n return summary;\n }\n\n /**\n * Check if a conversation was recently completed (to prevent restart on catch-up)\n */\n wasConversationCompleted(conversationId: string): boolean {\n const completedAt = this.completedConversations.get(conversationId);\n if (!completedAt) return false;\n\n // Check if the completion is still within TTL\n const now = Date.now();\n if (now - completedAt > RunnerApp.COMPLETED_CONVERSATION_TTL_MS) {\n // Expired, clean it up\n this.completedConversations.delete(conversationId);\n return false;\n }\n return true;\n }\n\n /**\n * Mark a conversation as completed to prevent restart on catch-up\n */\n markConversationCompleted(conversationId: string): void {\n this.completedConversations.set(conversationId, Date.now());\n\n // Opportunistically clean up old entries\n this.cleanupCompletedConversations();\n }\n\n /**\n * Clean up expired completed conversation entries\n */\n private cleanupCompletedConversations(): void {\n const now = Date.now();\n for (const [id, completedAt] of this.completedConversations) {\n if (now - completedAt > RunnerApp.COMPLETED_CONVERSATION_TTL_MS) {\n this.completedConversations.delete(id);\n }\n }\n }\n\n private async registerRunner(): Promise<void> {\n try {\n if (!this.config.workspacePath || !path.isAbsolute(this.config.workspacePath)) {\n throw new Error(\"workspacePath must be an absolute path\");\n }\n\n const filteredRunnerRepos: RunnerRepo[] = Array.isArray(this.config.runnerRepos)\n ? this.config.runnerRepos\n : [];\n\n // Get computer name for registration\n let hostComputerName: string | undefined;\n try {\n hostComputerName = await computerName();\n } catch (error) {\n logger.warn(\"Failed to get computer name, will use default\", error);\n }\n\n const response = await this.sendToOrchestratorWithRetry({\n jsonrpc: \"2.0\",\n id: \"register-\" + Date.now(),\n method: \"runner.register\",\n params: {\n version: RUNNER_VERSION,\n runnerRepos: filteredRunnerRepos,\n computerName: hostComputerName,\n workspacePath: this.config.workspacePath,\n },\n });\n\n // Debug log the full response\n logger.info(`Registration response:`, JSON.stringify(response, null, 2));\n\n // Log the runnerRepos being sent and received\n if (isRunnerDebugEnabled()) {\n logger.debug(\n \"Registration runnerRepos sent:\",\n JSON.stringify(filteredRunnerRepos)\n );\n logger.debug(\n \"Registration runnerRepos received:\",\n JSON.stringify(response?.result?.runnerRepos)\n );\n }\n\n // Check for JSONRPC error response\n if (response?.error) {\n logger.error(`Registration error from server:`, response.error);\n throw new Error(\n `Server error: ${response.error.message || \"Unknown error\"}`\n );\n }\n\n // Extract result from JSONRPC response structure\n const result = response?.result;\n\n if (result?.runnerId) {\n this.config.runnerId = result.runnerId;\n this.runnerUid = result.runnerUid;\n this.lastProcessedAt = result.lastProcessedAt\n ? new Date(result.lastProcessedAt)\n : null;\n this.isRegistered = true;\n\n // If this is a fresh start (no previous lastProcessedAt), set as active runner immediately\n // The server will also send a runner.uid.changed message, but we set it here to avoid\n // any window where isActiveRunner is incorrectly false\n if (!result.lastProcessedAt) {\n this.isActiveRunner = true;\n logger.info(\n `First-time registration - setting as active runner immediately`\n );\n }\n\n // Save registration state\n await this.stateManager.updateRunnerRegistration(\n result.runnerId,\n result.runnerUid,\n this.lastProcessedAt\n );\n\n // Persist the active status if we set it\n if (this.isActiveRunner) {\n await this.stateManager.updateActiveStatus(true);\n }\n\n logger.info(\n `Runner registered successfully with ID: ${this.config.runnerId} and UID: ${this.runnerUid}`\n );\n\n // Process runnerRepos from response\n if (result.runnerRepos && Array.isArray(result.runnerRepos)) {\n const prepared = await this.prepareRunnerRepos(result.runnerRepos);\n await this.replaceRunnerRepos(prepared);\n }\n\n // Debug logging for registration details\n if (isRunnerDebugEnabled()) {\n logger.debug(\"Registration complete with details\", {\n runnerId: this.config.runnerId,\n runnerUid: this.runnerUid,\n lastProcessedAt: this.lastProcessedAt?.toISOString() || \"null\",\n orchestratorUrl: this.config.orchestratorUrl,\n dataDir: this.config.dataDir,\n runnerReposCount: result.runnerRepos?.length || 0,\n });\n }\n } else {\n logger.error(`Registration failed. Expected result.runnerId but got:`, {\n hasResult: !!result,\n resultKeys: result ? Object.keys(result) : [],\n fullResponse: JSON.stringify(response, null, 2),\n });\n throw new Error(\"Registration response did not include runnerId\");\n }\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n logger.error(`Failed to register runner: ${errorMessage}`);\n throw error;\n }\n }\n\n private async registerWithRetry(): Promise<void> {\n const strategy = this.config.retryStrategy;\n\n if (strategy === \"none\") {\n // Single attempt, no retries\n await this.registerRunner();\n return;\n }\n\n if (strategy === \"interval\") {\n // Retry at fixed intervals\n const intervalMs = this.config.retryIntervalSecs * 1000;\n let attempt = 0;\n\n while (!this.isRegistered) {\n attempt++;\n try {\n logger.info(`Registration attempt ${attempt}...`);\n await this.registerRunner();\n return;\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n logger.error(\n `Registration attempt ${attempt} failed: ${errorMessage}`\n );\n logger.info(\n `Retrying in ${this.config.retryIntervalSecs} seconds...`\n );\n await this.delayFn(intervalMs);\n }\n }\n }\n\n if (strategy === \"exponential\") {\n // Exponential backoff with max duration\n const maxDurationMs = this.config.retryDurationSecs * 1000;\n const startTime = Date.now();\n let delayMs = 8000; // Start with 8 seconds\n let attempt = 0;\n\n while (!this.isRegistered) {\n attempt++;\n try {\n logger.info(`Registration attempt ${attempt}...`);\n await this.registerRunner();\n return;\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n logger.error(\n `Registration attempt ${attempt} failed: ${errorMessage}`\n );\n\n const elapsedMs = Date.now() - startTime;\n if (elapsedMs >= maxDurationMs) {\n // Final retry at max duration\n const remainingMs = maxDurationMs - elapsedMs;\n if (remainingMs > 0) {\n logger.info(\n `Final retry in ${Math.ceil(remainingMs / 1000)} seconds...`\n );\n await this.delayFn(remainingMs);\n\n try {\n logger.info(\"Final registration attempt...\");\n await this.registerRunner();\n return;\n } catch (finalError) {\n const errorMessage =\n finalError instanceof Error\n ? finalError.message\n : String(finalError);\n logger.error(\n `Final registration attempt failed: ${errorMessage}`\n );\n throw new Error(\n `Failed to register after ${this.config.retryDurationSecs} seconds`\n );\n }\n } else {\n throw new Error(\n `Failed to register after ${this.config.retryDurationSecs} seconds`\n );\n }\n }\n\n // Calculate next delay with exponential backoff\n const nextDelayMs = Math.min(delayMs, maxDurationMs - elapsedMs);\n logger.info(\n `Retrying in ${Math.ceil(nextDelayMs / 1000)} seconds...`\n );\n await this.delayFn(nextDelayMs);\n\n // Double the delay for next attempt\n delayMs = Math.min(delayMs * 2, maxDurationMs);\n }\n }\n }\n }\n\n private async sendToOrchestratorWithRetry(\n message: JsonRpcMessage\n ): Promise<any> {\n const maxRetries = 5;\n const initialDelayMs = 1000; // Start with 1 second\n const maxDelayMs = 60000; // Max 60 seconds\n const jitterMs = 500; // Add up to 500ms of random jitter\n\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await this.sendToOrchestrator(message);\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n // Don't retry on certain errors\n if (\n lastError.message.includes(\"HTTP 401\") ||\n lastError.message.includes(\"HTTP 403\") ||\n lastError.message.includes(\"HTTP 404\")\n ) {\n throw lastError;\n }\n\n if (attempt < maxRetries) {\n // Calculate exponential backoff with jitter\n const baseDelay = Math.min(\n initialDelayMs * Math.pow(2, attempt),\n maxDelayMs\n );\n const jitter = Math.random() * jitterMs;\n const delayMs = baseDelay + jitter;\n\n // Log retry attempt\n const errorMessage = lastError.message || String(lastError);\n if (message.method === \"runner.heartbeat\") {\n // Less verbose for heartbeat retries\n logger.debug(\n `Heartbeat retry ${attempt + 1}/${maxRetries + 1} in ${Math.round(\n delayMs\n )}ms`\n );\n } else {\n logger.warn(\n `RPC retry ${attempt + 1}/${maxRetries + 1} for '${\n message.method\n }' after error: ${errorMessage}. Retrying in ${Math.round(\n delayMs\n )}ms`\n );\n }\n\n await this.delayFn(delayMs);\n }\n }\n }\n\n // All retries exhausted\n const finalError = lastError || new Error(\"Unknown error\");\n if (message.method !== \"runner.heartbeat\") {\n logger.error(`RPC failed after ${maxRetries + 1} attempts:`, {\n method: message.method,\n error: finalError.message,\n });\n }\n throw finalError;\n }\n\n private startHeartbeat(): void {\n if (!this.isRegistered || !this.config.runnerId) {\n logger.warn(\"Cannot start heartbeat: runner not registered\");\n return;\n }\n\n this.heartbeatInterval = setInterval(async () => {\n if (this.heartbeatInFlight) {\n return;\n }\n this.heartbeatInFlight = true;\n try {\n const response = await this.sendToOrchestrator({\n jsonrpc: \"2.0\",\n id: `heartbeat-${Date.now()}`,\n method: \"runner.heartbeat\",\n params: {\n runnerId: this.config.runnerId,\n activeConversations: this.agentConversations.size,\n uptime: process.uptime(),\n memoryUsage: process.memoryUsage(),\n },\n });\n\n // Check for expectedRunnerVersion in heartbeat response\n if (response?.result?.expectedRunnerVersion) {\n await this.checkForUpdate(response.result.expectedRunnerVersion);\n }\n } catch (error) {\n // Heartbeat errors are already logged in sendToOrchestrator\n } finally {\n this.heartbeatInFlight = false;\n }\n }, this.config.heartbeatInterval);\n }\n\n private async stopAllConversations(\n isRunnerShutdown: boolean = true\n ): Promise<void> {\n const stopPromises: Promise<void>[] = [];\n\n for (const [conversationId, context] of this.agentConversations) {\n if (context.status === \"active\" || context.status === \"starting\") {\n // Active/starting conversations: properly stop them via manager\n const manager = this.getManagerForContext(context);\n stopPromises.push(\n manager\n .stopConversation(context.agentSessionId, context, isRunnerShutdown)\n .catch((error) => {\n logger.error(\n `Failed to stop conversation ${context.agentSessionId}:`,\n error\n );\n })\n );\n } else {\n // Already stopped/errored conversations: ensure orchestrator is notified\n // This prevents tasks from restarting on runner restart\n stopPromises.push(\n this.notify(\"conversation.end\", {\n conversationId: context.conversationId,\n conversationObjectType: context.conversationObjectType,\n conversationObjectId: context.conversationObjectId,\n agentSessionId: context.agentSessionId,\n isError: context.status === \"error\",\n reason: \"runner_shutdown_cleanup\",\n }).catch((error) => {\n logger.error(\n `Failed to notify conversation.end for ${conversationId}:`,\n error\n );\n })\n );\n }\n }\n\n await Promise.all(stopPromises);\n this.agentConversations.clear();\n }\n\n // Update lastProcessedAt and persist state\n async updateLastProcessedAt(timestamp: Date | null): Promise<void> {\n this.lastProcessedAt = timestamp;\n if (timestamp) {\n await this.stateManager.updateLastProcessedAt(timestamp);\n }\n }\n\n // Getters for components\n get config_(): RunnerConfig {\n return this.config;\n }\n\n get activeConversations_(): Map<string, ConversationContext> {\n return this.agentConversations;\n }\n\n get claudeManager_(): ClaudeManager {\n return this.claudeManager;\n }\n get codexManager_(): CodexManager {\n return this.codexManager;\n }\n get northflareAgentManager_(): NorthflareAgentManager {\n return this.northflareAgentManager;\n }\n get repositoryManager_(): EnhancedRepositoryManager {\n return this.repositoryManager;\n }\n\n getConfigPath(): string | undefined {\n return this.configPath;\n }\n\n getRunnerId(): string | undefined {\n return this.config.runnerId;\n }\n\n // UID ownership getters/setters\n getRunnerUid(): string | null {\n return this.runnerUid;\n }\n\n getLastProcessedAt(): Date | null {\n return this.lastProcessedAt;\n }\n\n getIsActiveRunner(): boolean {\n return this.isActiveRunner;\n }\n\n setIsActiveRunner(active: boolean): void {\n const previousState = this.isActiveRunner;\n this.isActiveRunner = active;\n\n // Persist state change\n this.stateManager.updateActiveStatus(active).catch((error) => {\n logger.error(\"Failed to persist active status:\", error);\n });\n\n if (isRunnerDebugEnabled()) {\n logger.debug(\"Active runner status changed\", {\n previous: previousState,\n new: active,\n runnerUid: this.runnerUid,\n lastProcessedAt: this.lastProcessedAt?.toISOString() || \"null\",\n });\n }\n }\n\n setLastProcessedAt(timestamp: Date | null): void {\n const previousTimestamp = this.lastProcessedAt;\n this.lastProcessedAt = timestamp;\n\n if (isRunnerDebugEnabled()) {\n logger.debug(\"LastProcessedAt updated\", {\n previous: previousTimestamp?.toISOString() || \"null\",\n new: timestamp?.toISOString() || \"null\",\n runnerUid: this.runnerUid,\n isActiveRunner: this.isActiveRunner,\n });\n }\n }\n\n getPreHandoffConversations(): Set<string> {\n return this.preHandoffConversations;\n }\n\n // For testing purposes - allows mocking delays\n setDelayFunction(fn: (ms: number) => Promise<void>): void {\n this.delayFn = fn;\n }\n\n getWorkspacePath(): string | undefined {\n return this.config.workspacePath;\n }\n\n /**\n * Check if an update is available and trigger update process if needed.\n * Called by message handler when a message includes expectedRunnerVersion.\n */\n async checkForUpdate(serverVersion: string): Promise<void> {\n await this.updateCoordinator.checkVersion(serverVersion);\n }\n\n /**\n * Notify the update coordinator that a conversation has ended.\n * If there's a pending update and this was the last active conversation,\n * the update will be triggered.\n */\n async onConversationEnd(): Promise<void> {\n await this.updateCoordinator.onConversationEnd();\n }\n\n /**\n * Check if there's a pending update waiting for conversations to complete.\n */\n hasPendingUpdate(): boolean {\n return this.updateCoordinator.hasPendingUpdate;\n }\n\n async replaceRunnerRepos(repos: RunnerRepo[]): Promise<void> {\n this.config.runnerRepos = repos;\n await this.saveRunnerRepoCache(repos);\n }\n\n private async saveRunnerRepoCache(repos: RunnerRepo[]): Promise<void> {\n if (!this.runnerReposCachePath) return;\n try {\n await fs.mkdir(path.dirname(this.runnerReposCachePath), { recursive: true });\n await fs.writeFile(\n this.runnerReposCachePath,\n JSON.stringify({ updatedAt: new Date().toISOString(), repos }, null, 2),\n \"utf-8\"\n );\n } catch (err) {\n logger.warn(\"Failed to persist runner repo cache\", err);\n }\n }\n\n private async loadRunnerRepoCache(): Promise<RunnerRepo[] | null> {\n if (!this.runnerReposCachePath) return null;\n try {\n const content = await fs.readFile(this.runnerReposCachePath, \"utf-8\");\n const parsed = JSON.parse(content);\n if (Array.isArray(parsed?.repos)) {\n logger.info(\n `Loaded ${parsed.repos.length} runner repos from cache at ${this.runnerReposCachePath}`\n );\n return parsed.repos as RunnerRepo[];\n }\n } catch (err: any) {\n if (err?.code !== \"ENOENT\") {\n logger.warn(\"Failed to load runner repo cache\", err);\n }\n }\n return null;\n }\n\n private isRepoAllowed(repo: RunnerRepo, workspacePath?: string): boolean {\n const base = workspacePath || this.config.workspacePath;\n const resolvedPath = path.resolve(repo.path);\n const external = repo.external === true || !isSubPath(base, resolvedPath);\n if (!external && base && !isSubPath(base, resolvedPath)) {\n return false;\n }\n return true;\n }\n\n private async prepareRunnerRepos(\n repos: RunnerRepo[],\n workspacePath?: string\n ): Promise<RunnerRepo[]> {\n const prepared: RunnerRepo[] = [];\n for (const repo of repos || []) {\n if (!repo?.path || !repo?.name) continue;\n const resolvedPath = path.resolve(repo.path);\n const external = repo.external === true || !isSubPath(workspacePath || this.config.workspacePath, resolvedPath);\n\n if (!external && workspacePath && !isSubPath(workspacePath, resolvedPath)) {\n logger.warn(\n `Ignoring runnerRepo ${repo.name} because path is outside workspace: ${resolvedPath}`\n );\n continue;\n }\n\n if (!external && this.config.workspacePath && !isSubPath(this.config.workspacePath, resolvedPath)) {\n logger.warn(\n `Ignoring runnerRepo ${repo.name} because path is outside configured workspace: ${resolvedPath}`\n );\n continue;\n }\n\n try {\n await fs.mkdir(resolvedPath, { recursive: true });\n const stats = await fs.stat(resolvedPath);\n if (!stats.isDirectory()) {\n logger.warn(\n `RunnerRepo path is not a directory: ${repo.name} at ${resolvedPath}`\n );\n continue;\n }\n } catch (err) {\n logger.warn(\n `RunnerRepo path could not be prepared: ${repo.name} at ${resolvedPath}`,\n err\n );\n continue;\n }\n\n prepared.push({\n ...repo,\n path: resolvedPath,\n external,\n });\n }\n\n return prepared;\n }\n\n private async refreshRunnerReposFromServer(\n useCacheOnFailure: boolean = true\n ): Promise<void> {\n const apiClient = new RunnerAPIClient(this.config);\n if (this.config.runnerId) {\n apiClient.setRunnerId(this.config.runnerId);\n }\n\n try {\n const snapshot = await apiClient.listRunnerRepos();\n const prepared = await this.prepareRunnerRepos(\n snapshot.repos || [],\n snapshot.workspacePath\n );\n await this.replaceRunnerRepos(prepared);\n logger.info(`Hydrated runner repos from server snapshot (${prepared.length})`);\n } catch (err) {\n logger.error(\"Failed to fetch runner repo snapshot from server\", err);\n if (useCacheOnFailure) {\n const cached = await this.loadRunnerRepoCache();\n if (cached) {\n const prepared = await this.prepareRunnerRepos(cached);\n await this.replaceRunnerRepos(prepared);\n logger.info(\n `Hydrated runner repos from local cache (${prepared.length}) after snapshot failure`\n );\n return;\n }\n }\n throw err;\n }\n }\n\n private getManagerForContext(\n context?: ConversationContext | null\n ): ClaudeManager | CodexManager {\n const provider = context?.provider?.toLowerCase();\n if (provider === \"openai\") {\n return this.codexManager;\n }\n return this.claudeManager;\n }\n}\n","export const TOOL_RESPONSE_BYTE_LIMIT = 500 * 1024; // 500 KiB cap per tool response payload\nexport const TOOL_RESPONSE_SUFFIX = \"... [truncated]\";\n\nexport interface ToolResponseSanitizationResult {\n params: any;\n truncated: boolean;\n toolUseId?: string;\n}\n\ninterface TruncationContext {\n bytesRemaining: number;\n truncated: boolean;\n}\n\nexport function sanitizeToolResponsePayload(\n method: string | undefined,\n params: any\n): ToolResponseSanitizationResult {\n if (method !== \"message.agent\" || !params) {\n return { params, truncated: false };\n }\n\n if (!isToolResultPayload(params)) {\n return { params, truncated: false };\n }\n\n const context: TruncationContext = {\n bytesRemaining: TOOL_RESPONSE_BYTE_LIMIT,\n truncated: false,\n };\n\n const [sanitized, changed] = truncateStringsRecursively(params, context);\n\n if (!changed && !context.truncated) {\n return { params, truncated: false };\n }\n\n return {\n params: sanitized,\n truncated: true,\n toolUseId: extractToolUseId(params),\n };\n}\n\nfunction isToolResultPayload(payload: any): boolean {\n if (!payload) {\n return false;\n }\n if (payload.type === \"tool_result\" || payload.subtype === \"tool_result\") {\n return true;\n }\n if (Array.isArray(payload.content)) {\n return payload.content.some((entry: any) => isToolResultBlock(entry));\n }\n return isToolResultBlock(payload.content);\n}\n\nfunction isToolResultBlock(block: any): boolean {\n if (!block) {\n return false;\n }\n return (\n block.type === \"tool_result\" ||\n block.subtype === \"tool_result\" ||\n typeof block.tool_use_id === \"string\"\n );\n}\n\nfunction extractToolUseId(payload: any): string | undefined {\n if (!payload) {\n return undefined;\n }\n if (typeof payload.tool_use_id === \"string\") {\n return payload.tool_use_id;\n }\n if (Array.isArray(payload.content)) {\n const match = payload.content.find(\n (entry: any) => entry && typeof entry.tool_use_id === \"string\"\n );\n if (match) {\n return match.tool_use_id;\n }\n }\n if (payload.content && typeof payload.content === \"object\") {\n return extractToolUseId(payload.content);\n }\n return undefined;\n}\n\nfunction truncateStringsRecursively(\n value: any,\n context: TruncationContext\n): [any, boolean] {\n if (typeof value === \"string\") {\n return truncateStringValue(value, context);\n }\n\n if (Array.isArray(value)) {\n let mutated = false;\n let result: any[] = value;\n for (let i = 0; i < value.length; i++) {\n const [newItem, changed] = truncateStringsRecursively(value[i], context);\n if (changed) {\n if (!mutated) {\n result = value.slice();\n mutated = true;\n }\n result[i] = newItem;\n }\n }\n return [result, mutated];\n }\n\n if (value && typeof value === \"object\") {\n let mutated = false;\n let result: Record<string, any> = value;\n for (const key of Object.keys(value)) {\n const [newVal, changed] = truncateStringsRecursively(\n value[key],\n context\n );\n if (changed) {\n if (!mutated) {\n result = { ...value };\n mutated = true;\n }\n result[key] = newVal;\n }\n }\n return [result, mutated];\n }\n\n return [value, false];\n}\n\nfunction truncateStringValue(\n value: string,\n context: TruncationContext\n): [string, boolean] {\n if (context.bytesRemaining <= 0) {\n if (value.length === 0) {\n return [value, false];\n }\n context.truncated = true;\n return [\"\", true];\n }\n\n const byteLength = Buffer.byteLength(value, \"utf8\");\n if (byteLength <= context.bytesRemaining) {\n context.bytesRemaining -= byteLength;\n return [value, false];\n }\n\n const suffixBytes = Buffer.byteLength(TOOL_RESPONSE_SUFFIX, \"utf8\");\n const maxBytes = Math.max(0, context.bytesRemaining - suffixBytes);\n const truncatedBuffer = Buffer.from(value, \"utf8\").subarray(0, maxBytes);\n context.bytesRemaining = 0;\n context.truncated = true;\n return [truncatedBuffer.toString(\"utf8\") + TOOL_RESPONSE_SUFFIX, true];\n}\n","/**\n * Coordinates runner auto-updates.\n *\n * When the server sends an expectedRunnerVersion that is newer than the current\n * version, the coordinator notes the pending update and waits for the runner to\n * become idle (no active conversations) before executing the update.\n *\n * The update is performed by spawning a new process with npx, which ensures\n * the latest version is fetched and executed with the same arguments/env.\n */\n\nimport { spawn } from \"child_process\";\nimport { logger } from \"./logger.js\";\nimport { RUNNER_VERSION, isNewerVersion } from \"./version.js\";\n\nexport type UpdateState =\n | \"idle\" // No update pending\n | \"pending\" // Update available, waiting for runner to become idle\n | \"updating\" // Executing update command\n | \"restarting\"; // About to exit and restart\n\nexport interface UpdateCoordinatorOptions {\n /** If true, auto-updates are disabled */\n autoUpdateDisabled: boolean;\n /** Returns the current number of active conversations */\n getActiveConversationCount: () => number;\n /** Saves runner state before restart */\n saveState: () => Promise<void>;\n /** Gets the config path for restart args */\n getConfigPath: () => string | undefined;\n}\n\nexport class UpdateCoordinator {\n private state: UpdateState = \"idle\";\n private pendingVersion: string | null = null;\n private readonly options: UpdateCoordinatorOptions;\n\n constructor(options: UpdateCoordinatorOptions) {\n this.options = options;\n }\n\n get currentState(): UpdateState {\n return this.state;\n }\n\n get hasPendingUpdate(): boolean {\n return this.state === \"pending\";\n }\n\n get pendingVersionNumber(): string | null {\n return this.pendingVersion;\n }\n\n /**\n * Called when a message is received with an expectedRunnerVersion.\n * If the version is newer, marks an update as pending.\n * If the runner is already idle, triggers the update immediately.\n *\n * @returns true if an update was triggered or marked as pending\n */\n async checkVersion(serverVersion: string): Promise<boolean> {\n if (this.options.autoUpdateDisabled) {\n logger.debug(\"Auto-update disabled via NORTHFLARE_DISABLE_AUTO_UPDATE\");\n return false;\n }\n\n // Already handling an update\n if (this.state !== \"idle\" && this.state !== \"pending\") {\n logger.debug(\"Update already in progress\", { state: this.state });\n return false;\n }\n\n // Check if server version is newer\n if (!isNewerVersion(serverVersion, RUNNER_VERSION)) {\n return false;\n }\n\n // Already have this version pending\n if (this.pendingVersion === serverVersion) {\n return false;\n }\n\n // Mark update as pending\n this.pendingVersion = serverVersion;\n this.state = \"pending\";\n logger.info(\n `Update available: ${serverVersion} (current: ${RUNNER_VERSION}). ` +\n `Will update when idle.`\n );\n\n // If already idle, update now\n if (this.options.getActiveConversationCount() === 0) {\n await this.executeUpdate();\n return true;\n }\n\n logger.info(\n `${this.options.getActiveConversationCount()} active conversation(s). ` +\n `Update will proceed when all complete.`\n );\n return true;\n }\n\n /**\n * Called when a conversation ends. If there's a pending update and the\n * runner is now idle, triggers the update.\n */\n async onConversationEnd(): Promise<void> {\n if (this.state !== \"pending\" || !this.pendingVersion) {\n return;\n }\n\n const activeCount = this.options.getActiveConversationCount();\n if (activeCount > 0) {\n logger.debug(\n `Conversation ended, but ${activeCount} still active. ` +\n `Waiting for idle before update.`\n );\n return;\n }\n\n logger.info(\"Runner now idle, proceeding with pending update\");\n await this.executeUpdate();\n }\n\n /**\n * Executes the update by spawning a new runner process and exiting.\n */\n private async executeUpdate(): Promise<void> {\n if (!this.pendingVersion) {\n logger.error(\"executeUpdate called but no pending version\");\n return;\n }\n\n this.state = \"updating\";\n logger.info(`Installing @northflare/runner@${this.pendingVersion}...`);\n\n try {\n // Save state before restart so we don't lose lastProcessedAt, etc.\n await this.options.saveState();\n logger.debug(\"State saved before update\");\n } catch (error) {\n logger.error(\"Failed to save state before update:\", error);\n // Continue anyway - better to update than to stay on old version\n }\n\n // Build the npx command\n // Using -y to auto-confirm and specifying the exact version\n const npxCommand = \"npx\";\n const npxArgs = [\n \"-y\",\n `@northflare/runner@${this.pendingVersion}`,\n ...this.buildRestartArgs(),\n ];\n\n logger.info(`Restarting with: ${npxCommand} ${npxArgs.join(\" \")}`);\n this.state = \"restarting\";\n\n // Spawn new process detached so it survives our exit\n const child = spawn(npxCommand, npxArgs, {\n detached: true,\n stdio: \"inherit\",\n env: process.env,\n shell: true,\n });\n\n // Prevent parent from waiting for child\n child.unref();\n\n // Handle spawn errors\n child.on(\"error\", (error) => {\n logger.error(\"Failed to spawn update process:\", error);\n // Reset state so we can try again\n this.state = \"pending\";\n });\n\n // Give the new process a moment to start before we exit\n await new Promise((resolve) => setTimeout(resolve, 1000));\n\n // Exit current process\n logger.info(\"Exiting for update...\");\n process.exit(0);\n }\n\n /**\n * Builds the command-line arguments for the restarted runner.\n * Most config is passed via environment variables which are inherited.\n */\n private buildRestartArgs(): string[] {\n const args: string[] = [];\n\n // Add start command explicitly\n args.push(\"start\");\n\n // Config path if provided\n const configPath = this.options.getConfigPath();\n if (configPath) {\n args.push(\"--config\", configPath);\n }\n\n // Other options are passed via inherited env vars:\n // - NORTHFLARE_RUNNER_TOKEN\n // - NORTHFLARE_WORKSPACE_PATH\n // - NORTHFLARE_DATA_DIR\n // - NORTHFLARE_RUNNER_DEBUG\n // - NORTHFLARE_RUNNER_INACTIVITY_TIMEOUT\n // - NORTHFLARE_ORCHESTRATOR_URL\n\n return args;\n }\n}\n","/**\n * Version utilities for runner auto-update\n */\n\nimport { createRequire } from \"module\";\n\nconst require = createRequire(import.meta.url);\nconst pkg = (() => {\n try {\n // Works when bundled to dist/index.js\n return require(\"../package.json\");\n } catch {\n // Works when running directly from src/*\n return require(\"../../package.json\");\n }\n})();\n\nexport const RUNNER_VERSION: string = pkg.version;\n\n/**\n * Compare two semver versions.\n * Returns true if serverVersion is newer than currentVersion.\n */\nexport function isNewerVersion(serverVersion: string, currentVersion: string): boolean {\n const parse = (v: string): [number, number, number] => {\n // Handle versions like \"0.0.26\" or \"1.2.3-beta.1\"\n const match = v.match(/^(\\d+)\\.(\\d+)\\.(\\d+)/);\n if (!match) {\n return [0, 0, 0];\n }\n return [\n parseInt(match[1]!, 10),\n parseInt(match[2]!, 10),\n parseInt(match[3]!, 10),\n ];\n };\n\n const [sMajor, sMinor, sPatch] = parse(serverVersion);\n const [cMajor, cMinor, cPatch] = parse(currentVersion);\n\n if (sMajor !== cMajor) return sMajor > cMajor;\n if (sMinor !== cMinor) return sMinor > cMinor;\n return sPatch > cPatch;\n}\n","/**\n * Configuration management utilities\n */\n\nimport { RunnerConfig, EnvironmentConfig, RetryStrategy } from '../types/index.js';\nimport fs from \"fs/promises\";\nimport { existsSync } from \"fs\";\nimport path from \"path\";\nimport envPaths from \"env-paths\";\nimport os from \"os\";\nimport { createLogger } from './logger.js';\nimport { Command } from \"commander\";\nimport readline from \"readline/promises\";\nimport { stdin as input, stdout as output } from \"node:process\";\n\nconst logger = createLogger(\"ConfigManager\");\nconst ENV_PATHS_APP_NAME = resolveEnvPathsAppName();\nconst ENV_PATHS_OPTIONS = { suffix: \"\" as const };\nconst IS_DEV_APP = ENV_PATHS_APP_NAME.endsWith(\"-dev\");\n\nfunction resolveEnvPathsAppName() {\n if (process.env[\"NODE_ENV\"] === \"development\") return \"northflare-runner-dev\";\n\n try {\n // When running from workspace (e.g., pnpm exec or direct node dist/...)\n // use the dev app name so config lives under the \"-dev\" path.\n const __dirname = path.dirname(new URL(import.meta.url).pathname);\n const repoRoot = path.resolve(__dirname, \"../..\");\n if (existsSync(path.join(repoRoot, \"pnpm-workspace.yaml\"))) {\n return \"northflare-runner-dev\";\n }\n } catch {\n // ignore and fall back to prod name\n }\n\n return \"northflare-runner\";\n}\n\n// ENV_PATHS_APP_NAME/OPTIONS defined above for reuse across helpers\n\nexport class ConfigManager {\n private static DEFAULT_CONFIG: Partial<RunnerConfig> = {\n dataDir: ConfigManager.resolveDefaultDataDir(),\n heartbeatInterval: 120000, // 2 minutes\n retryStrategy: \"exponential\" as RetryStrategy,\n retryIntervalSecs: 60,\n retryDurationSecs: 900,\n orchestratorUrl: \"https://api.northflare.app\",\n };\n\n private static resolveDefaultDataDir(): string {\n try {\n const paths = envPaths(ENV_PATHS_APP_NAME, ENV_PATHS_OPTIONS);\n return paths.data;\n } catch (error) {\n logger.debug(\"Falling back to cwd-relative data directory\", error);\n // Keep dev and prod state isolated when env-paths cannot resolve\n return path.resolve(IS_DEV_APP ? \"./data/dev\" : \"./data\");\n }\n }\n\n private static getDefaultConfigPath(): string {\n try {\n const paths = envPaths(ENV_PATHS_APP_NAME, ENV_PATHS_OPTIONS);\n return path.join(paths.config, \"config.json\");\n } catch (error) {\n logger.debug(\"Falling back to repo-relative config path\", error);\n // Separate dev/prod config files even when env-paths fails\n const localDir = IS_DEV_APP ? \"./config/dev\" : \"./config\";\n return path.resolve(localDir, \"config.json\");\n }\n }\n\n /**\n * Load configuration without parsing command line arguments\n * Used when arguments have already been parsed by the CLI\n */\n static async loadConfig(\n configPath?: string,\n options?: { promptForWorkspacePath?: boolean }\n ): Promise<RunnerConfig> {\n this.validateEnvironment();\n\n let config: Partial<RunnerConfig> = { ...this.DEFAULT_CONFIG };\n const effectiveConfigPath = configPath || this.getDefaultConfigPath();\n\n const fileConfig = await this.loadConfigFile(effectiveConfigPath);\n // Runner repos are now server-owned; ignore any persisted runnerRepos in config files\n if (fileConfig && (fileConfig as any).runnerRepos) {\n delete (fileConfig as any).runnerRepos;\n }\n const migratedWorkspacePath =\n !fileConfig.workspacePath && (fileConfig as any).workspaceDir\n ? (fileConfig as any).workspaceDir\n : undefined;\n\n config = { ...config, ...fileConfig };\n\n const envConfig = this.loadFromEnvironment();\n config = { ...config, ...envConfig };\n\n // Determine the workspacePath to use after env/CLI overrides\n let workspacePath = config.workspacePath;\n const appliedMigration = !workspacePath && !!migratedWorkspacePath;\n let shouldPersistWorkspacePath = false;\n\n if (appliedMigration) {\n workspacePath = migratedWorkspacePath;\n shouldPersistWorkspacePath = true;\n }\n\n if (!workspacePath) {\n if (options?.promptForWorkspacePath) {\n workspacePath = await this.promptForWorkspacePath();\n shouldPersistWorkspacePath = true;\n } else {\n throw new Error(\n \"workspacePath is required. Provide NORTHFLARE_WORKSPACE_PATH, --workspace-path, or set it in the runner config file.\"\n );\n }\n }\n\n const normalizedWorkspacePath = this.normalizeWorkspacePath(workspacePath!);\n config.workspacePath = normalizedWorkspacePath;\n\n if (shouldPersistWorkspacePath) {\n await this.persistConfigFile(effectiveConfigPath, {\n ...fileConfig,\n ...config,\n workspacePath: normalizedWorkspacePath,\n });\n }\n\n this.validateConfig(config);\n\n return config as RunnerConfig;\n }\n\n /**\n * Parse command line arguments and load configuration\n */\n static async parseArgsAndLoadConfig(argv: string[]): Promise<RunnerConfig> {\n const program = new Command();\n\n program\n .name(\"northflare-runner\")\n .description(\n \"Northflare Runner - Executes Claude agents for task processing\"\n )\n .version(\"1.0.0\")\n .option(\"-c, --config <path>\", \"Path to configuration file\")\n .option(\n \"--retry-strategy <strategy>\",\n \"Registration retry strategy (none, interval, exponential)\",\n \"exponential\"\n )\n .option(\n \"--retry-interval-secs <seconds>\",\n \"Retry interval in seconds for interval strategy\",\n \"60\"\n )\n .option(\n \"--retry-duration-secs <seconds>\",\n \"Max retry duration in seconds for exponential strategy\",\n \"900\"\n )\n .option(\"--data-dir <path>\", \"Data directory path\")\n .option(\n \"--heartbeat-interval <ms>\",\n \"Heartbeat interval in milliseconds\",\n \"120000\"\n )\n .option(\"--workspace-path <path>\", \"Workspace directory path\");\n\n program.parse(argv);\n const options = program.opts();\n\n // Validate required environment variables\n this.validateEnvironment();\n\n // Start with defaults\n let config: Partial<RunnerConfig> = { ...this.DEFAULT_CONFIG };\n\n // Load from config file (explicit path or default) and capture legacy workspaceDir for migration\n const effectiveConfigPath = options[\"config\"] || this.getDefaultConfigPath();\n const fileConfig = await this.loadConfigFile(effectiveConfigPath);\n if (fileConfig && (fileConfig as any).runnerRepos) {\n delete (fileConfig as any).runnerRepos;\n }\n const migratedWorkspacePath =\n !fileConfig.workspacePath && (fileConfig as any).workspaceDir\n ? (fileConfig as any).workspaceDir\n : undefined;\n\n config = { ...config, ...fileConfig };\n\n // Override with environment variables\n const envConfig = this.loadFromEnvironment();\n config = { ...config, ...envConfig };\n\n // Override with CLI arguments (highest priority)\n if (options[\"retryStrategy\"]) {\n config.retryStrategy = options[\"retryStrategy\"] as RetryStrategy;\n }\n if (options[\"retryIntervalSecs\"]) {\n config.retryIntervalSecs = parseInt(options[\"retryIntervalSecs\"]);\n }\n if (options[\"retryDurationSecs\"]) {\n config.retryDurationSecs = parseInt(options[\"retryDurationSecs\"]);\n }\n if (options[\"dataDir\"]) {\n config.dataDir = options[\"dataDir\"];\n }\n if (options[\"heartbeatInterval\"]) {\n config.heartbeatInterval = parseInt(options[\"heartbeatInterval\"]);\n }\n if (options[\"workspacePath\"]) {\n config.workspacePath = options[\"workspacePath\"];\n }\n\n const appliedMigration = !config.workspacePath && !!migratedWorkspacePath;\n let shouldPersistWorkspacePath = false;\n\n if (appliedMigration) {\n config.workspacePath = migratedWorkspacePath;\n shouldPersistWorkspacePath = true;\n }\n\n if (!config.workspacePath) {\n // Mirror loadConfig behavior: prompt when missing\n const workspacePath = await this.promptForWorkspacePath();\n config.workspacePath = workspacePath;\n shouldPersistWorkspacePath = true;\n }\n\n const normalizedWorkspacePath = this.normalizeWorkspacePath(\n config.workspacePath!\n );\n config.workspacePath = normalizedWorkspacePath;\n\n if (shouldPersistWorkspacePath) {\n await this.persistConfigFile(effectiveConfigPath, {\n ...fileConfig,\n ...config,\n workspacePath: normalizedWorkspacePath,\n });\n }\n\n // Validate final configuration\n this.validateConfig(config);\n\n return config as RunnerConfig;\n }\n\n /**\n * Validate required environment variables\n */\n private static validateEnvironment(): void {\n const required = [\"NORTHFLARE_RUNNER_TOKEN\"];\n\n const missing = required.filter((key) => !process.env[key]);\n\n if (missing.length > 0) {\n throw new Error(\n `Missing required environment variables: ${missing.join(\", \")}\\n` +\n \"Please set these environment variables before starting the runner.\"\n );\n }\n }\n\n /**\n * Load configuration from environment variables\n */\n private static loadFromEnvironment(): Partial<RunnerConfig> {\n const config: Partial<RunnerConfig> = {};\n\n if (process.env[\"NORTHFLARE_ORCHESTRATOR_URL\"]) {\n config.orchestratorUrl = process.env[\"NORTHFLARE_ORCHESTRATOR_URL\"]!;\n }\n\n // Optional environment overrides\n if (process.env[\"NORTHFLARE_DATA_DIR\"]) {\n config.dataDir = process.env[\"NORTHFLARE_DATA_DIR\"];\n }\n\n if (process.env[\"NORTHFLARE_WORKSPACE_PATH\"]) {\n config.workspacePath = process.env[\"NORTHFLARE_WORKSPACE_PATH\"];\n }\n\n return config;\n }\n\n /**\n * Load configuration from file\n */\n private static async loadConfigFile(\n configPath: string\n ): Promise<Partial<RunnerConfig>> {\n try {\n const absolutePath = path.resolve(configPath);\n const content = await fs.readFile(absolutePath, \"utf-8\");\n\n // Support both JSON and YAML formats\n if (configPath.endsWith(\".json\")) {\n const config = JSON.parse(content);\n // Runner repos are now server-sourced; ignore any persisted copy\n delete (config as any).runnerRepos;\n return config;\n } else if (configPath.endsWith(\".yaml\") || configPath.endsWith(\".yml\")) {\n // For YAML support, we'd need to add a yaml parser dependency\n throw new Error(\"YAML configuration files are not yet supported\");\n } else {\n throw new Error(\"Configuration file must be .json format\");\n }\n } catch (error) {\n if ((error as any).code === \"ENOENT\") {\n logger.warn(`Configuration file not found: ${configPath}`);\n return {};\n }\n throw error;\n }\n }\n\n private static async promptForWorkspacePath(): Promise<string> {\n const suggestedBase = this.resolveDefaultDataDir();\n const defaultPath = path.join(suggestedBase, \"workspaces\");\n const rl = readline.createInterface({ input, output });\n\n try {\n // Keep prompting until an absolute path is provided (tilde is allowed)\n // to avoid silently resolving relative paths.\n while (true) {\n const answer = await rl.question(\n `Enter a local workspace directory for runner workspaces (default: ${defaultPath}): `\n );\n\n const chosen = answer.trim() === \"\" ? defaultPath : answer.trim();\n\n try {\n const normalized = this.normalizeWorkspacePath(chosen);\n await fs.mkdir(normalized, { recursive: true });\n logger.info(`Using workspace path: ${normalized}`);\n return normalized;\n } catch (error) {\n logger.error(\n (error as Error).message ||\n \"workspacePath must be an absolute path. Please try again.\"\n );\n }\n }\n } finally {\n rl.close();\n }\n }\n\n private static normalizeWorkspacePath(workspacePath: string): string {\n const trimmed = workspacePath?.trim();\n\n if (!trimmed) {\n throw new Error(\"workspacePath is required\");\n }\n\n // Expand tilde to the user's home directory without accidentally\n // discarding the home path when the remainder begins with a path separator.\n let expanded = trimmed;\n\n if (trimmed === \"~\") {\n expanded = os.homedir();\n } else if (trimmed.startsWith(\"~/\")) {\n expanded = path.join(os.homedir(), trimmed.slice(2));\n } else if (trimmed.startsWith(\"~\\\\\")) {\n expanded = path.join(os.homedir(), trimmed.slice(2));\n }\n\n if (!path.isAbsolute(expanded)) {\n throw new Error(\"workspacePath must be an absolute path\");\n }\n\n return expanded;\n }\n\n private static async persistConfigFile(\n configPath: string,\n config: any\n ): Promise<void> {\n try {\n const absolutePath = path.resolve(configPath);\n await fs.mkdir(path.dirname(absolutePath), { recursive: true });\n await this.saveConfigFile(absolutePath, config);\n } catch (error) {\n logger.error(\"Failed to persist config file\", error);\n }\n }\n\n /**\n * Validate final configuration\n */\n private static validateConfig(config: Partial<RunnerConfig>): void {\n // Note: Runner ID will be generated by server during registration\n\n if (!config.workspacePath || config.workspacePath.trim() === \"\") {\n throw new Error(\"workspacePath is required\");\n }\n\n if (!path.isAbsolute(config.workspacePath)) {\n throw new Error(\"workspacePath must be an absolute path\");\n }\n\n if (!config.orchestratorUrl) {\n throw new Error(\"orchestratorUrl is required\");\n }\n\n if (!config.dataDir) {\n throw new Error(\"dataDir is required\");\n }\n\n if (!config.heartbeatInterval || config.heartbeatInterval < 1000) {\n throw new Error(\"heartbeatInterval must be at least 1000ms\");\n }\n\n // Validate retry strategy\n const validStrategies: RetryStrategy[] = [\n \"none\",\n \"interval\",\n \"exponential\",\n ];\n if (\n !config.retryStrategy ||\n !validStrategies.includes(config.retryStrategy)\n ) {\n throw new Error(\n `retryStrategy must be one of: ${validStrategies.join(\", \")}`\n );\n }\n\n if (\n config.retryStrategy === \"interval\" &&\n (!config.retryIntervalSecs || config.retryIntervalSecs < 1)\n ) {\n throw new Error(\n \"retryIntervalSecs must be at least 1 when using interval strategy\"\n );\n }\n\n if (\n config.retryStrategy === \"exponential\" &&\n (!config.retryDurationSecs || config.retryDurationSecs < 1)\n ) {\n throw new Error(\n \"retryDurationSecs must be at least 1 when using exponential strategy\"\n );\n }\n }\n\n /**\n * Get all environment configuration\n */\n static getEnvironmentConfig(): EnvironmentConfig {\n return {\n NORTHFLARE_RUNNER_TOKEN: process.env[\"NORTHFLARE_RUNNER_TOKEN\"]!,\n NORTHFLARE_WORKSPACE_PATH: process.env[\"NORTHFLARE_WORKSPACE_PATH\"],\n NORTHFLARE_ORCHESTRATOR_URL: process.env[\"NORTHFLARE_ORCHESTRATOR_URL\"]!,\n NORTHFLARE_RUNNER_DEBUG: process.env[\"NORTHFLARE_RUNNER_DEBUG\"],\n DEBUG: process.env[\"DEBUG\"],\n };\n }\n\n /**\n * Save configuration file with updated data\n */\n static async saveConfigFile(configPath: string, config: any): Promise<void> {\n try {\n const absolutePath = path.resolve(configPath);\n await fs.mkdir(path.dirname(absolutePath), { recursive: true });\n const content = JSON.stringify(config, null, 2);\n await fs.writeFile(absolutePath, content, \"utf-8\");\n logger.info(`Updated configuration file: ${absolutePath}`);\n } catch (error) {\n logger.error(\"Failed to save configuration file\", error);\n throw error;\n }\n }\n}\n","/**\n * Utilities for parsing and formatting inactivity timeout values\n */\n\nexport type InactivityTimeoutUnit = \"seconds\" | \"minutes\" | \"hours\";\n\nexport interface ParsedInactivityTimeout {\n milliseconds: number;\n value: number;\n unit: InactivityTimeoutUnit;\n display: string;\n}\n\ntype UnitKey = \"s\" | \"m\" | \"h\";\n\ninterface UnitMetadata {\n multiplier: number;\n unit: InactivityTimeoutUnit;\n singular: string;\n plural: string;\n}\nconst UNIT_METADATA = {\n s: {\n multiplier: 1000,\n unit: \"seconds\",\n singular: \"second\",\n plural: \"seconds\",\n },\n m: {\n multiplier: 60_000,\n unit: \"minutes\",\n singular: \"minute\",\n plural: \"minutes\",\n },\n h: {\n multiplier: 3_600_000,\n unit: \"hours\",\n singular: \"hour\",\n plural: \"hours\",\n },\n} satisfies Record<UnitKey, UnitMetadata>;\n\n/**\n * Parse CLI-provided inactivity timeout values (e.g. 30s, 5m, 1h, 45)\n */\nexport function parseInactivityTimeout(\n rawValue: string\n): ParsedInactivityTimeout {\n if (!rawValue) {\n throw new Error(\"Inactivity timeout value cannot be empty\");\n }\n\n const trimmed = rawValue.trim().toLowerCase();\n const match = trimmed.match(/^(\\d+)([smh])?$/);\n\n if (!match) {\n throw new Error(\n \"Invalid inactivity timeout format. Use a number optionally suffixed with s, m, or h (e.g. 30s, 5m, 1h).\"\n );\n }\n\n const value = Number(match[1]);\n if (!Number.isFinite(value) || value <= 0) {\n throw new Error(\"Inactivity timeout must be a number greater than zero\");\n }\n\n const unitKey = (match[2] || \"s\") as UnitKey;\n const metadata = UNIT_METADATA[unitKey];\n if (!metadata) {\n throw new Error(`Unsupported inactivity timeout unit: ${unitKey}`);\n }\n const milliseconds = value * metadata.multiplier;\n const unitLabel = value === 1 ? metadata.singular : metadata.plural;\n\n return {\n milliseconds,\n value,\n unit: metadata.unit,\n display: `${value} ${unitLabel}`,\n };\n}\n\n/**\n * Best-effort formatter for a timeout expressed in milliseconds.\n */\nexport function formatInactivityTimeoutFromMs(ms: number): string {\n if (!Number.isFinite(ms) || ms <= 0) {\n return \"unknown duration\";\n }\n\n if (ms % UNIT_METADATA.h.multiplier === 0) {\n const hours = ms / UNIT_METADATA.h.multiplier;\n return `${hours} ${hours === 1 ? \"hour\" : \"hours\"}`;\n }\n\n if (ms % UNIT_METADATA.m.multiplier === 0) {\n const minutes = ms / UNIT_METADATA.m.multiplier;\n return `${minutes} ${minutes === 1 ? \"minute\" : \"minutes\"}`;\n }\n\n const seconds = Math.round(ms / 1000);\n return `${seconds} ${seconds === 1 ? \"second\" : \"seconds\"}`;\n}\n","/**\n * Main entry point for the Northflare Runner App\n */\n\nimport { RunnerApp } from './runner-sse.js';\nimport { ConfigManager } from './utils/config.js';\nimport { logger, configureFileLogging } from './utils/logger.js';\nimport { isRunnerDebugEnabled } from './utils/debug.js';\nimport {\n parseInactivityTimeout,\n formatInactivityTimeoutFromMs,\n} from './utils/inactivity-timeout.js';\nimport type { ParsedInactivityTimeout } from './utils/inactivity-timeout.js';\nimport path from \"path\";\nimport fs from \"fs/promises\";\nimport { existsSync } from \"fs\";\nimport envPaths from \"env-paths\";\n\nconst INACTIVITY_TIMEOUT_ENV_KEY = \"NORTHFLARE_RUNNER_INACTIVITY_TIMEOUT\";\nconst INACTIVITY_CHECK_INTERVAL_MS = 1000;\n\nfunction resolveEnvPathsAppName() {\n if (process.env[\"NODE_ENV\"] === \"development\") return \"northflare-runner-dev\";\n\n try {\n const __dirname = path.dirname(new URL(import.meta.url).pathname);\n const repoRoot = path.resolve(__dirname, \"../..\");\n if (existsSync(path.join(repoRoot, \"pnpm-workspace.yaml\"))) {\n return \"northflare-runner-dev\";\n }\n } catch {\n // ignore and fall back\n }\n\n return \"northflare-runner\";\n}\n\nconst ENV_PATHS_APP_NAME = resolveEnvPathsAppName();\nconst ENV_PATHS_OPTIONS = { suffix: \"\" as const };\nconst IS_DEV_APP = ENV_PATHS_APP_NAME.endsWith(\"-dev\");\nconst SHUTDOWN_TIMEOUT_MS = 10_000;\n\nlet runner: RunnerApp | null = null;\nlet isShuttingDown = false;\nlet inactivityMonitorHandle: NodeJS.Timeout | null = null;\nlet inactivityCountdownStart: number | null = null;\nlet shutdownTimeoutHandle: NodeJS.Timeout | null = null;\n\nasync function main() {\n try {\n logger.info(\"Starting Northflare Runner...\");\n const debugEnabled = isRunnerDebugEnabled();\n const inactivityEnvValue = process.env[INACTIVITY_TIMEOUT_ENV_KEY];\n let inactivitySetting: ParsedInactivityTimeout | null = null;\n\n if (inactivityEnvValue) {\n try {\n inactivitySetting = parseInactivityTimeout(inactivityEnvValue);\n logger.info(\n `Runner will terminate after ${inactivitySetting.display} with no active agent processes`\n );\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n logger.error(\n `Invalid inactivity timeout '${inactivityEnvValue}': ${errorMessage}`\n );\n process.exit(1);\n }\n }\n\n // Load configuration (args already parsed by CLI)\n let configPath = process.argv[2]; // This is set by the CLI if --config was provided\n\n // If no config path provided, check for default location\n if (!configPath) {\n try {\n const paths = envPaths(ENV_PATHS_APP_NAME, ENV_PATHS_OPTIONS);\n configPath = path.join(paths.config, \"config.json\");\n } catch (error) {\n // env-paths not available or error accessing default location\n const localDir = IS_DEV_APP ? \"./config/dev\" : \"./config\";\n configPath = path.resolve(localDir, \"config.json\");\n }\n }\n // Normalize for downstream consumers and logging\n configPath = path.resolve(configPath);\n\n if (debugEnabled) {\n logger.debug(\"Using configuration file\", {\n configPath,\n exists: existsSync(configPath),\n });\n }\n\n const config = await ConfigManager.loadConfig(configPath, {\n promptForWorkspacePath: true,\n });\n\n if (inactivitySetting) {\n config.inactivityTimeoutMs = inactivitySetting.milliseconds;\n config.inactivityTimeoutDisplay = inactivitySetting.display;\n }\n\n // Set up file logging\n const logDir = path.join(config.dataDir, \"logs\");\n await fs.mkdir(logDir, { recursive: true });\n configureFileLogging(logDir);\n\n logger.info(\"Configuration loaded\", {\n orchestratorUrl: config.orchestratorUrl,\n retryStrategy: config.retryStrategy,\n retryIntervalSecs: config.retryIntervalSecs,\n retryDurationSecs: config.retryDurationSecs,\n });\n\n // Additional debug logging\n if (debugEnabled) {\n logger.debug(\"Debug mode enabled - verbose logging active\", {\n dataDir: config.dataDir,\n heartbeatInterval: config.heartbeatInterval,\n nodeVersion: process.version,\n platform: process.platform,\n pid: process.pid,\n });\n }\n\n // Create and start runner - pass the resolved config path\n runner = new RunnerApp(config, configPath);\n await runner.start();\n\n // Set up graceful shutdown handlers\n setupShutdownHandlers();\n\n if (config.inactivityTimeoutMs) {\n const timeoutLabel =\n config.inactivityTimeoutDisplay ||\n formatInactivityTimeoutFromMs(config.inactivityTimeoutMs);\n startInactivityMonitor(config.inactivityTimeoutMs, timeoutLabel);\n }\n\n logger.info(\"Northflare Runner is running\", {\n runnerId: runner.getRunnerId() || \"pending registration\",\n });\n\n // Log additional details in debug mode\n if (debugEnabled && runner) {\n logger.debug(\"Runner started with full details\", {\n runnerId: runner.getRunnerId(),\n runnerUid: runner.getRunnerUid(),\n lastProcessedAt: runner.getLastProcessedAt()?.toISOString() || \"null\",\n isActiveRunner: runner.getIsActiveRunner(),\n uptime: process.uptime(),\n memoryUsage: process.memoryUsage(),\n });\n }\n } catch (error) {\n logger.error(\"Failed to start runner:\", error);\n process.exit(1);\n }\n}\n\nfunction setupShutdownHandlers() {\n // Handle various shutdown signals\n const signals: NodeJS.Signals[] = [\"SIGTERM\", \"SIGINT\", \"SIGHUP\"];\n\n for (const signal of signals) {\n process.on(signal, () => {\n beginShutdown(0, `Received ${signal}, shutting down gracefully...`);\n });\n }\n\n // Handle uncaught exceptions\n process.on(\"uncaughtException\", (error) => {\n logger.error(\"Uncaught exception:\", error);\n beginShutdown(1);\n });\n\n // Handle unhandled promise rejections\n process.on(\"unhandledRejection\", (reason, promise) => {\n logger.error(\"Unhandled rejection\", { promise, reason });\n beginShutdown(1);\n });\n\n // Handle process warnings\n process.on(\"warning\", (warning) => {\n logger.warn(\"Process warning\", {\n name: warning.name,\n message: warning.message,\n stack: warning.stack,\n });\n });\n}\n\nfunction startInactivityMonitor(\n timeoutMs: number,\n displayLabel: string\n): void {\n clearInactivityMonitor();\n inactivityCountdownStart = null;\n\n inactivityMonitorHandle = setInterval(() => {\n if (!runner || isShuttingDown) {\n return;\n }\n\n const activeCount = runner.activeConversations_.size;\n\n if (activeCount > 0) {\n inactivityCountdownStart = null;\n return;\n }\n\n if (inactivityCountdownStart === null) {\n inactivityCountdownStart = Date.now();\n return;\n }\n\n const elapsed = Date.now() - inactivityCountdownStart;\n if (elapsed >= timeoutMs) {\n clearInactivityMonitor();\n beginShutdown(\n 0,\n `Inactivity timeout reached: no active agent processes for ${displayLabel}. Exiting.`\n );\n }\n }, INACTIVITY_CHECK_INTERVAL_MS);\n}\n\nfunction clearInactivityMonitor(): void {\n if (inactivityMonitorHandle) {\n clearInterval(inactivityMonitorHandle);\n inactivityMonitorHandle = null;\n }\n inactivityCountdownStart = null;\n}\n\nfunction beginShutdown(exitCode: number = 0, message?: string): void {\n if (isShuttingDown) {\n if (message) {\n logger.warn(`Shutdown already in progress. Forcing exit now (${message})`);\n } else {\n logger.warn(\"Shutdown already in progress. Forcing exit now\");\n }\n\n // If a second signal arrives while we're still stopping, exit immediately\n process.exit(exitCode || 1);\n }\n\n if (message) {\n logger.info(message);\n }\n isShuttingDown = true;\n\n // Ensure we don't hang forever waiting for async cleanup\n shutdownTimeoutHandle = setTimeout(() => {\n logger.error(\n `Shutdown did not complete within ${SHUTDOWN_TIMEOUT_MS}ms. Forcing exit.`\n );\n process.exit(1);\n }, SHUTDOWN_TIMEOUT_MS);\n shutdownTimeoutHandle.unref?.();\n void shutdown(exitCode);\n}\n\nasync function shutdown(exitCode: number = 0) {\n clearInactivityMonitor();\n\n if (runner) {\n try {\n await runner.stop();\n logger.info(\"Runner stopped successfully\");\n } catch (error) {\n logger.error(\"Error during shutdown:\", error);\n exitCode = 1;\n }\n }\n\n if (shutdownTimeoutHandle) {\n clearTimeout(shutdownTimeoutHandle);\n shutdownTimeoutHandle = null;\n }\n\n process.exit(exitCode);\n}\n\n// Note: In ESM, the bin/northflare-runner script handles calling main() directly\n\n// Export for programmatic usage\nexport { RunnerApp } from './runner-sse.js';\nexport { ConfigManager } from './utils/config.js';\nexport * from './types/index.js';\nexport { main, isShuttingDown };\n"],"mappings":"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","names":["logger","logger","path","logger","runner","fs","path","console","runner","input","agentSessionId","subtype","jwt","fs","path","simpleGit","console","runner","input","path","fs","jwt","ext","buffer","fs","fs","jwt","fs","path","simpleGit","console","buildSystemPromptWithNorthflare","runner","input","createUserMessageStream","createConversationWrapper","agentSessionId","subtype","hasImages","path","fs","simpleGit","console","runner","simpleGit","path","fs","path","fs","crypto","simpleGit","console","logger","runner","path","crypto","fs","git","simpleGit","output","repo","remotes","hasOrigin","fs","path","logger","path","fs","fs","path","require","isSubPath","path","logger","errorMessage","fs","fs","path","logger","path","fs","path","fs","existsSync","envPaths","resolveEnvPathsAppName","path","existsSync","ENV_PATHS_APP_NAME","ENV_PATHS_OPTIONS","IS_DEV_APP","envPaths","fs"]}