@qiaolei81/copilot-session-viewer 0.3.8 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/server/telemetry.js", "../src/server/config/index.js", "../src/server/middleware/common.js", "../src/server/utils/sourceMapping.js", "../src/server/utils/helpers.js", "../src/server/utils/fileUtils.js", "../src/server/adapters/AdapterRegistry.js", "../src/server/adapters/BaseSourceAdapter.js", "../src/server/models/Session.js", "../src/server/adapters/adapterUtils.js", "../src/server/adapters/CopilotAdapter.js", "../lib/parsers/base-parser.js", "../lib/parsers/copilot-parser.js", "../lib/parsers/claude-parser.js", "../lib/parsers/pi-mono-parser.js", "../lib/parsers/vscode-parser.js", "../lib/parsers/parser-factory.js", "../lib/parsers/index.js", "../src/server/adapters/ClaudeAdapter.js", "../src/server/adapters/PiMonoAdapter.js", "../src/server/adapters/VsCodeAdapter.js", "../src/server/adapters/ModernizeAdapter.js", "../src/server/adapters/index.js", "../src/server/services/sessionRepository.js", "../src/server/services/eventNormalizer.js", "../src/server/services/sessionService.js", "../src/server/services/tagService.js", "../src/server/services/dirRegistryService.js", "../src/server/controllers/sessionController.js", "../src/server/utils/processManager.js", "../src/server/services/insightService.js", "../src/server/controllers/insightController.js", "../src/server/controllers/uploadController.js", "../src/server/controllers/tagController.js", "../src/server/controllers/dirController.js", "../src/server/app.js", "../server.js"],
4
+ "sourcesContent": ["/**\n * Application Insights Telemetry Module\n *\n * This module initializes and configures Application Insights for telemetry tracking.\n * Must be required BEFORE any other modules (especially Express) in server.js.\n *\n * Features:\n * - Auto-collection of requests, dependencies, exceptions, and performance counters\n * - Custom event and metric tracking\n * - Automatic disabling in test environments\n * - Support for manual disabling via DISABLE_TELEMETRY env var\n */\n\nconst appInsights = require('applicationinsights');\nconst fs = require('fs');\nconst path = require('path');\nconst crypto = require('crypto');\nconst os = require('os');\n\n/**\n * Get or create a persistent anonymous user ID.\n * Stored in ~/.copilot-session-viewer/analytics-id\n */\nfunction getAnonymousId() {\n const dir = path.join(os.homedir(), '.copilot-session-viewer');\n const filePath = path.join(dir, 'analytics-id');\n try {\n return fs.readFileSync(filePath, 'utf8').trim();\n } catch {\n const id = crypto.randomUUID();\n try {\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(filePath, id);\n } catch { /* ignore write errors */ }\n return id;\n }\n}\n\n/**\n * Get app version from package.json\n */\nfunction getAppVersion() {\n try {\n // Try multiple paths (source vs bundled)\n const candidates = [\n path.join(__dirname, '../..', 'package.json'),\n path.join(__dirname, '..', 'package.json'),\n path.join(__dirname, 'package.json'),\n ];\n for (const p of candidates) {\n try {\n return JSON.parse(fs.readFileSync(p, 'utf8')).version;\n } catch { /* try next */ }\n }\n } catch { /* ignore */ }\n return 'unknown';\n}\n\n// Determine if telemetry should be disabled\nconst DEFAULT_CONNECTION_STRING = 'InstrumentationKey=39f4fbf1-d82f-42c3-b4ef-ea92a1fd82cb;IngestionEndpoint=https://eastus-8.in.applicationinsights.azure.com/;LiveEndpoint=https://eastus.livediagnostics.monitor.azure.com/;ApplicationId=7d4bb432-f2f5-4526-a5e6-31901e5a2db2';\nconst connectionString = process.env.APPLICATIONINSIGHTS_CONNECTION_STRING || DEFAULT_CONNECTION_STRING;\nconst isDisabled = process.env.DISABLE_TELEMETRY === 'true';\n\nlet client = null;\n\nif (!isDisabled) {\n try {\n // Setup and start Application Insights\n appInsights.setup(connectionString)\n .setAutoDependencyCorrelation(true)\n .setAutoCollectRequests(true)\n .setAutoCollectPerformance(true, true)\n .setAutoCollectExceptions(true)\n .setAutoCollectDependencies(true)\n .setAutoCollectConsole(false) // Disable console tracking to avoid noise\n .setUseDiskRetryCaching(true)\n .setSendLiveMetrics(false) // Disable live metrics for local dev tool\n .setDistributedTracingMode(appInsights.DistributedTracingModes.AI_AND_W3C)\n .start();\n\n client = appInsights.defaultClient;\n\n // Set context properties\n const appVersion = getAppVersion();\n const anonymousId = getAnonymousId();\n client.context.tags[client.context.keys.cloudRole] = 'copilot-session-viewer';\n client.context.tags[client.context.keys.cloudRoleInstance] = os.hostname();\n client.context.tags[client.context.keys.applicationVersion] = appVersion;\n client.context.tags[client.context.keys.userId] = anonymousId;\n\n // Add version to every event via telemetry initializer\n client.addTelemetryProcessor((envelope) => {\n envelope.data.baseData.properties = envelope.data.baseData.properties || {};\n envelope.data.baseData.properties.appVersion = appVersion;\n return true;\n });\n\n console.log('\u2705 Application Insights telemetry initialized');\n } catch (error) {\n console.error('\u274C Failed to initialize Application Insights:', error.message);\n // Continue without telemetry rather than crashing\n client = createNoOpClient();\n }\n} else {\n // Return no-op client when disabled\n client = createNoOpClient();\n\n console.log('\uD83D\uDCCA Telemetry disabled (DISABLE_TELEMETRY=true)');\n}\n\n/**\n * Creates a no-op client that safely ignores all telemetry calls\n * Used when telemetry is disabled or in test environments\n */\nfunction createNoOpClient() {\n return {\n trackEvent: () => {},\n trackMetric: () => {},\n trackException: () => {},\n trackTrace: () => {},\n trackDependency: () => {},\n trackRequest: () => {},\n flush: (callback) => {\n if (callback) callback();\n }\n };\n}\n\n/**\n * Track a custom event\n * @param {string} name - Event name\n * @param {Object} properties - Event properties\n */\nfunction trackEvent(name, properties = {}) {\n if (client && client.trackEvent) {\n client.trackEvent({\n name,\n properties\n });\n }\n}\n\n/**\n * Track a custom metric\n * @param {string} name - Metric name\n * @param {number} value - Metric value\n * @param {Object} properties - Additional properties\n */\nfunction trackMetric(name, value, properties = {}) {\n if (client && client.trackMetric) {\n client.trackMetric({\n name,\n value,\n properties\n });\n }\n}\n\n/**\n * Track an exception\n * @param {Error} error - Error object\n * @param {Object} properties - Additional properties\n */\nfunction trackException(error, properties = {}) {\n if (client && client.trackException) {\n client.trackException({\n exception: error,\n properties\n });\n }\n}\n\n/**\n * Flush telemetry data (useful for short-lived processes)\n * @returns {Promise<void>}\n */\nfunction flush() {\n return new Promise((resolve) => {\n if (client && client.flush) {\n client.flush({\n callback: () => resolve()\n });\n } else {\n resolve();\n }\n });\n}\n\n// Export the client and helper functions\nmodule.exports = {\n client,\n trackEvent,\n trackMetric,\n trackException,\n flush,\n isEnabled: !isDisabled\n};\n", "/**\n * Application Configuration Constants\n */\n\nmodule.exports = {\n // Server\n PORT: process.env.PORT || 3838,\n NODE_ENV: process.env.NODE_ENV || 'production', // Default to production for security\n\n // Logging\n LOG_LEVEL: process.env.LOG_LEVEL || (process.env.NODE_ENV === 'development' ? 'DEBUG' : 'INFO'),\n\n // Insight Generation\n INSIGHT_TIMEOUT_MS: 5 * 60 * 1000, // 5 minutes\n INSIGHT_CACHE_TTL_MS: 24 * 60 * 60 * 1000, // 24 hours\n\n // File Upload\n MAX_UPLOAD_SIZE: 10 * 1024 * 1024, // 10MB (reduced from 50MB for security)\n\n // Session Repository\n SESSION_CACHE_TTL_MS: 30 * 1000, // 30 seconds\n\n // Request Limits - More lenient for better UX\n RATE_LIMIT_WINDOW_MS: 15 * 60 * 1000, // 15 minutes\n RATE_LIMIT_MAX_REQUESTS: 15, // Increased from 5 to 15 for better UX\n REQUEST_TIMEOUT_MS: 30 * 1000 // 30 seconds\n};\n", "const config = require('../config');\nconst { trackException } = require('../telemetry');\n\n// Request timeout middleware\nconst requestTimeout = (req, res, next) => {\n req.setTimeout(config.REQUEST_TIMEOUT_MS);\n next();\n};\n\n// Telemetry middleware - no-op (connection strings must not be exposed to clients)\nconst telemetryLocals = (req, res, next) => {\n next();\n};\n\n// CORS middleware for development\nconst developmentCors = (req, res, next) => {\n if (config.NODE_ENV === 'development') {\n const allowedOrigins = ['http://localhost:3838', 'http://127.0.0.1:3838'];\n const origin = req.headers.origin;\n if (allowedOrigins.includes(origin)) {\n res.header('Access-Control-Allow-Origin', origin);\n res.header('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');\n res.header('Access-Control-Allow-Headers', 'Content-Type');\n }\n }\n next();\n};\n\n// Error handling middleware\nconst errorHandler = (err, req, res, _next) => {\n console.error('Unhandled error:', err.stack);\n\n // Track exception in Application Insights\n trackException(err, {\n url: req.url,\n method: req.method,\n statusCode: (err.status || 500).toString(),\n userAgent: (req.headers && req.headers['user-agent']) || 'unknown'\n });\n\n const statusCode = err.status || 500;\n // Default to production-safe behavior if NODE_ENV is not set\n const isDevelopment = config.NODE_ENV === 'development';\n const message = isDevelopment ? err.message : 'Internal server error';\n\n res.status(statusCode).json({\n error: message,\n ...(isDevelopment && { stack: err.stack })\n });\n};\n\n// 404 handler\nconst notFoundHandler = (req, res) => {\n res.status(404).json({ error: 'Not found' });\n};\n\nmodule.exports = {\n requestTimeout,\n developmentCors,\n errorHandler,\n notFoundHandler,\n telemetryLocals\n};", "/**\n * Source Mapping \u2014 maps URL :source param to internal adapter types\n *\n * URL param -> Adapter type\n * copilot-cli -> copilot\n * copilot-chat -> vscode\n * claude -> claude\n * modernize -> modernize\n * pi-mono -> pi-mono\n */\n\nconst SOURCE_MAP = {\n 'copilot-cli': { adapterType: 'copilot', label: 'Copilot CLI' },\n 'copilot-chat': { adapterType: 'vscode', label: 'Copilot Chat (VS Code)' },\n 'claude': { adapterType: 'claude', label: 'Claude Code' },\n 'modernize': { adapterType: 'modernize', label: 'Modernize' },\n 'pi-mono': { adapterType: 'pi-mono', label: 'Pi Mono' },\n};\n\nconst VALID_SOURCES = new Set(Object.keys(SOURCE_MAP));\n\n/**\n * Resolve a URL source param to the internal adapter type.\n * @param {string} urlParam - The :source URL parameter\n * @returns {string|null} The adapter type, or null if invalid\n */\nfunction resolveSource(urlParam) {\n const entry = SOURCE_MAP[urlParam];\n return entry ? entry.adapterType : null;\n}\n\n/**\n * Get all available sources with id and label.\n * @returns {Array<{id: string, label: string}>}\n */\nfunction getAllSources() {\n return Object.entries(SOURCE_MAP).map(([id, { label }]) => ({ id, label }));\n}\n\n/**\n * Check if a source param is valid.\n * @param {string} urlParam\n * @returns {boolean}\n */\nfunction isValidSource(urlParam) {\n return VALID_SOURCES.has(urlParam);\n}\n\nmodule.exports = { resolveSource, getAllSources, isValidSource, SOURCE_MAP };\n", "/**\n * Helper utilities for server routes\n */\n\n/**\n * Build metadata object from session\n * @param {Session} session - Session model instance\n * @returns {Object} Metadata object\n */\nfunction buildMetadata(session) {\n const json = session.toJSON ? session.toJSON() : {};\n return {\n type: session.type,\n source: session.source, // 'copilot' or 'claude'\n sourceName: json.sourceName || session.source,\n sourceBadgeClass: json.sourceBadgeClass || 'source-unknown',\n summary: session.summary,\n model: session.selectedModel || session.model,\n repo: session.workspace?.repository,\n branch: session.workspace?.branch,\n cwd: session.workspace?.cwd,\n created: session.createdAt,\n updated: session.updatedAt,\n copilotVersion: session.copilotVersion,\n modernizeVersion: session.modernizeVersion,\n agentName: session.agentName,\n sessionStatus: session.sessionStatus\n };\n}\n\n/**\n * Validate session ID to prevent path traversal\n * @param {string} sessionId - Session identifier\n * @returns {boolean} True if valid\n */\nfunction isValidSessionId(sessionId) {\n // Allow alphanumeric, underscore, and hyphen (common in UUIDs and session IDs)\n // Length limit prevents abuse\n return typeof sessionId === 'string' && \n /^[a-zA-Z0-9_-]+$/.test(sessionId) && \n sessionId.length < 256;\n}\n\n/**\n * Validate UUID v4 format\n * @param {string} id\n * @returns {boolean}\n */\nfunction isValidUuidV4(id) {\n return typeof id === 'string'\n && /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(id);\n}\n\nmodule.exports = {\n buildMetadata,\n isValidSessionId,\n isValidUuidV4\n};\n", "const fs = require('fs').promises;\nconst fsSync = require('fs');\nconst readline = require('readline');\nconst yaml = require('js-yaml');\n\n/**\n * File utility functions\n */\n\n/**\n * Check if a file exists\n * @param {string} filePath - File path\n * @returns {Promise<boolean>}\n */\nasync function fileExists(filePath) {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Count lines in a file (non-empty lines only)\n * @param {string} filePath - File path\n * @returns {Promise<number>}\n */\nasync function countLines(filePath) {\n try {\n const stream = fsSync.createReadStream(filePath, { encoding: 'utf-8' });\n const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });\n let count = 0;\n try {\n for await (const line of rl) {\n if (line.trim()) count++;\n }\n return count;\n } finally {\n rl.close();\n stream.destroy();\n }\n } catch (err) {\n console.error(`Error counting lines in ${filePath}:`, err.message);\n return 0;\n }\n}\n\n/**\n * Read and parse YAML file (simple key: value format)\n * @param {string} filePath - YAML file path\n * @returns {Promise<object>}\n */\nasync function parseYAML(filePath) {\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n const parsed = yaml.load(content);\n return (parsed && typeof parsed === 'object') ? parsed : {};\n } catch (err) {\n // js-yaml fails on some malformed files; fall back to line-by-line\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n const result = {};\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const colonIdx = trimmed.indexOf(':');\n if (colonIdx <= 0) continue;\n const key = trimmed.slice(0, colonIdx).trim();\n const value = trimmed.slice(colonIdx + 1).trim();\n if (key) result[key] = value;\n }\n return result;\n } catch (fallbackErr) {\n console.error(`Error parsing YAML ${filePath}:`, fallbackErr.message);\n return {};\n }\n }\n}\n\n/**\n * Efficiently read session metadata in a single pass\n * Combines getFirstUserMessage, getSessionDuration, getSessionMetadata\n * @param {string} filePath - Path to .jsonl file\n * @param {number} maxMessageLength - Max characters for first message (default 200)\n * @returns {Promise<Object>} Combined metadata object\n */\nasync function getSessionMetadataOptimized(filePath, maxMessageLength = 500) {\n try {\n const stream = fsSync.createReadStream(filePath, { encoding: 'utf-8' });\n const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });\n\n let firstUserMessage = '';\n let firstTimestamp = null;\n let lastTimestamp = null;\n let copilotVersion = null;\n let selectedModel = null;\n let hasSessionEnd = false;\n let eventCount = 0;\n\n try {\n for await (const line of rl) {\n if (!line.trim()) continue;\n\n try {\n const event = JSON.parse(line);\n eventCount++;\n\n // Extract timestamp for duration calculation\n if (event.timestamp) {\n const ts = new Date(event.timestamp).getTime();\n if (!isNaN(ts)) {\n if (!firstTimestamp) firstTimestamp = ts;\n lastTimestamp = ts;\n }\n }\n\n // Get first user message\n if (!firstUserMessage && (event.type === 'user.message' || event.type === 'request')) {\n let msg = event.data?.message || event.data?.content || event.data?.text || '';\n // Copilot-cli request format: payload.messages[].content\n if (!msg && event.type === 'request' && Array.isArray(event.payload?.messages)) {\n const userMsg = event.payload.messages.find(m => m.role === 'user');\n if (userMsg) msg = typeof userMsg.content === 'string' ? userMsg.content : '';\n }\n if (msg) {\n firstUserMessage = msg.length > maxMessageLength ? msg.substring(0, maxMessageLength) + '...' : msg;\n }\n }\n\n // Check for session.end event\n if (event.type === 'session.end') {\n hasSessionEnd = true;\n }\n\n // Get copilot version from session start\n if (event.type === 'session.start' && event.data?.copilotVersion && !copilotVersion) {\n copilotVersion = event.data.copilotVersion;\n }\n\n // Get selected model\n if ((event.type === 'session.start' || event.type === 'session.model_change') && !selectedModel) {\n if (event.data?.selectedModel) {\n selectedModel = event.data.selectedModel;\n } else if (event.data?.newModel) {\n selectedModel = event.data.newModel;\n } else if (event.data?.model) {\n selectedModel = event.data.model;\n }\n }\n } catch {\n // Skip malformed JSON lines\n }\n }\n } finally {\n rl.close();\n stream.destroy();\n }\n\n // Calculate duration\n const duration = firstTimestamp && lastTimestamp && lastTimestamp > firstTimestamp\n ? lastTimestamp - firstTimestamp\n : null;\n\n return {\n firstUserMessage: firstUserMessage || '',\n duration,\n eventCount,\n copilotVersion: copilotVersion || null,\n selectedModel: selectedModel || null,\n hasSessionEnd,\n lastEventTime: lastTimestamp,\n firstEventTime: firstTimestamp\n };\n } catch (err) {\n console.error(`Error reading session metadata from ${filePath}:`, err.message);\n return {\n firstUserMessage: '',\n duration: null,\n eventCount: 0,\n copilotVersion: null,\n selectedModel: null,\n hasSessionEnd: false,\n lastEventTime: null\n };\n }\n}\n\n/**\n * Get the first user message from a .jsonl events file\n * Reads line by line and stops at the first user.message event\n * @param {string} filePath - Path to .jsonl file\n * @param {number} maxLength - Max characters to return (default 200)\n * @returns {Promise<string>} First user message or empty string\n */\nasync function getFirstUserMessage(filePath, maxLength = 200) {\n try {\n const stream = fsSync.createReadStream(filePath, { encoding: 'utf-8' });\n const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });\n\n for await (const line of rl) {\n if (!line.trim()) continue;\n try {\n const event = JSON.parse(line);\n if (event.type === 'user.message') {\n const msg = event.data?.message || event.data?.content || event.data?.text || '';\n if (msg) {\n rl.close();\n stream.destroy();\n return msg.length > maxLength ? msg.substring(0, maxLength) + '...' : msg;\n }\n }\n } catch {\n // Skip malformed JSON lines\n }\n }\n return '';\n } catch (_err) {\n return '';\n }\n}\n\n/**\n * Get session duration by reading first and last event timestamps\n * @param {string} filePath - Path to .jsonl events file\n * @returns {Promise<number|null>} Duration in milliseconds, or null if unable to calculate\n */\nasync function getSessionDuration(filePath) {\n try {\n const stream = fsSync.createReadStream(filePath, { encoding: 'utf-8' });\n const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });\n\n let firstTimestamp = null;\n let lastTimestamp = null;\n\n try {\n for await (const line of rl) {\n if (!line.trim()) continue;\n try {\n const event = JSON.parse(line);\n if (event.timestamp) {\n const ts = new Date(event.timestamp).getTime();\n if (!firstTimestamp) {\n firstTimestamp = ts;\n }\n lastTimestamp = ts;\n }\n } catch {\n // Skip malformed JSON lines\n }\n }\n } finally {\n rl.close();\n stream.destroy();\n }\n\n if (firstTimestamp && lastTimestamp && lastTimestamp >= firstTimestamp) {\n return lastTimestamp - firstTimestamp;\n }\n return null;\n } catch (err) {\n console.error(`Error calculating session duration for ${filePath}:`, err.message);\n return null;\n }\n}\n\n/**\n * Get session metadata from session.start event\n * @param {string} filePath - Path to .jsonl events file\n * @returns {Promise<{copilotVersion: string|null, selectedModel: string|null}>}\n */\nasync function getSessionMetadata(filePath) {\n try {\n const stream = fsSync.createReadStream(filePath, { encoding: 'utf-8' });\n const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });\n\n let copilotVersion = null;\n let selectedModel = null;\n\n try {\n for await (const line of rl) {\n if (!line.trim()) continue;\n try {\n const event = JSON.parse(line);\n\n if (event.type === 'session.start' && event.data) {\n copilotVersion = event.data.copilotVersion || null;\n selectedModel = event.data.selectedModel || null;\n if (selectedModel) {\n return { copilotVersion, selectedModel };\n }\n }\n\n if (!selectedModel && event.type === 'session.model_change' && event.data) {\n selectedModel = event.data.newModel || null;\n return { copilotVersion, selectedModel };\n }\n } catch {\n // Skip malformed JSON lines\n }\n }\n return { copilotVersion, selectedModel };\n } finally {\n rl.close();\n stream.destroy();\n }\n } catch (err) {\n console.error(`Error reading session metadata from ${filePath}:`, err.message);\n return { copilotVersion: null, selectedModel: null };\n }\n}\n\n/**\n * Check if entry should be skipped\n * @param {string} entry - Directory/file name\n * @returns {boolean}\n */\nfunction shouldSkipEntry(entry) {\n return entry === '.DS_Store' || entry.startsWith('.');\n}\n\nmodule.exports = {\n fileExists,\n countLines,\n parseYAML,\n getFirstUserMessage,\n getSessionDuration,\n getSessionMetadata,\n getSessionMetadataOptimized, // New optimized function\n shouldSkipEntry\n};\n", "/**\n * Adapter Registry\n *\n * Central registry for Source Adapters. Provides lookup by type string\n * and iteration over all registered adapters.\n *\n * Usage:\n * const { registry } = require('../adapters');\n * const adapter = registry.get('copilot');\n * for (const adapter of registry.all()) { ... }\n */\nclass AdapterRegistry {\n constructor() {\n /** @type {Map<string, import('./BaseSourceAdapter')>} */\n this._adapters = new Map();\n }\n\n /**\n * Register a source adapter.\n * @param {import('./BaseSourceAdapter')} adapter\n * @throws {Error} If adapter.type is already registered\n */\n register(adapter) {\n if (this._adapters.has(adapter.type)) {\n throw new Error(`Adapter already registered for type: ${adapter.type}`);\n }\n this._adapters.set(adapter.type, adapter);\n }\n\n /**\n * Get adapter by source type.\n * @param {string} type - e.g. 'copilot', 'claude', 'pi-mono', 'vscode'\n * @returns {import('./BaseSourceAdapter')|null}\n */\n get(type) {\n return this._adapters.get(type) || null;\n }\n\n /**\n * Get all registered adapters.\n * @returns {import('./BaseSourceAdapter')[]}\n */\n all() {\n return Array.from(this._adapters.values());\n }\n\n /**\n * Get all registered type strings.\n * @returns {string[]}\n */\n types() {\n return Array.from(this._adapters.keys());\n }\n\n /**\n * Number of registered adapters.\n * @returns {number}\n */\n get size() {\n return this._adapters.size;\n }\n\n /**\n * Ask every adapter to inspect an extracted zip.\n * Returns sorted results (highest score first).\n * @param {string} extractDir\n * @returns {Promise<Object[]>}\n */\n async detectImportCandidates(extractDir) {\n const results = await Promise.all(\n this.all().map(async (adapter) => {\n try {\n const r = await adapter.detectImportCandidate(extractDir);\n return { source: adapter.type, matched: false, score: 0, ...r };\n } catch (err) {\n return { source: adapter.type, matched: false, score: 0, reason: `Detection error: ${err.message}` };\n }\n })\n );\n return results.sort((a, b) => (b.score || 0) - (a.score || 0));\n }\n}\n\nmodule.exports = AdapterRegistry;\n\n", "const fs = require('fs');\nconst fsPromises = fs.promises;\nconst path = require('path');\nconst readline = require('readline');\nconst { shouldSkipEntry } = require('../utils/fileUtils');\n\n/**\n * Base Source Adapter Interface\n *\n * All source adapters (Copilot, Claude, Pi-Mono, VSCode, etc.) must extend\n * this class and implement the abstract methods. This enables the Source\n * Adapter pattern: SessionRepository and SessionService delegate all\n * source-specific logic to the appropriate adapter, eliminating if/else\n * branching across the codebase.\n *\n * To add a new source:\n * 1. Create a new adapter extending BaseSourceAdapter\n * 2. Register it in src/adapters/index.js\n * That's it \u2014 no changes to SessionRepository, SessionService, or controllers.\n */\nclass BaseSourceAdapter {\n /**\n * Unique source type identifier.\n * @returns {string} e.g. 'copilot', 'claude', 'pi-mono', 'vscode'\n */\n get type() {\n throw new Error('BaseSourceAdapter: type getter must be implemented');\n }\n\n /**\n * Human-readable display name shown in the UI.\n * @returns {string} e.g. 'Copilot CLI', 'Claude'\n */\n get displayName() {\n throw new Error('BaseSourceAdapter: displayName getter must be implemented');\n }\n\n /**\n * CSS badge class for the source badge in views.\n * Default: 'source-<type>'. Override if a different class is needed.\n * @returns {string}\n */\n get badgeClass() {\n return `source-${this.type}`;\n }\n\n /**\n * Environment variable name that overrides the default directory.\n * Return undefined if no env var is supported.\n * @returns {string|undefined}\n */\n get envVar() {\n return undefined;\n }\n\n /**\n * Display metadata for Session.toJSON().\n * @returns {{ name: string, badgeClass: string }}\n */\n get displayMetadata() {\n return { name: this.displayName, badgeClass: this.badgeClass };\n }\n\n /**\n * Default filesystem path for this source's session data.\n * @returns {string}\n */\n getDefaultDir() {\n throw new Error('BaseSourceAdapter: getDefaultDir() must be implemented');\n }\n\n /**\n * Resolve the actual directory to scan. Checks env var override first,\n * then falls back to getDefaultDir(). Override for sources with multiple\n * candidates (e.g. VSCode stable vs Insiders).\n * @returns {Promise<string|null>}\n */\n async resolveDir() {\n if (this.envVar && process.env[this.envVar]) {\n return process.env[this.envVar];\n }\n return this.getDefaultDir();\n }\n\n /**\n * Scan the source directory and return Session objects.\n * @param {string} _dir - Resolved source directory\n * @returns {Promise<import('../models/Session')[]>}\n */\n async scanEntries(_dir) {\n throw new Error('BaseSourceAdapter: scanEntries() must be implemented');\n }\n\n /**\n * Recursively scan a directory tree for session entries.\n * Calls `matchEntry(fullPath, entry, stats)` on each entry.\n * - If it returns a Session or Session[], those are collected.\n * - If it returns null and the entry is a directory, recurse into it.\n * - If it returns false, skip (don't recurse).\n * @param {string} dir - Directory to scan\n * @param {function} matchEntry - async (fullPath, entry, stats) => Session|Session[]|null|false\n * @param {number} [maxDepth=5] - Maximum recursion depth\n * @param {number} [_depth=0] - Current depth (internal)\n * @returns {Promise<import('../models/Session')[]>}\n */\n async recursiveScan(dir, matchEntry, maxDepth = 5, _depth = 0) {\n if (_depth > maxDepth) return [];\n\n let entries;\n try {\n entries = await fsPromises.readdir(dir);\n } catch {\n return [];\n }\n\n const tasks = entries\n .filter(entry => !shouldSkipEntry(entry))\n .map(async (entry) => {\n const fullPath = path.join(dir, entry);\n let stats;\n try {\n stats = await fsPromises.stat(fullPath);\n } catch {\n return [];\n }\n\n const result = await matchEntry(fullPath, entry, stats);\n\n if (result === false) {\n // Explicitly skip\n return [];\n }\n if (result !== null && result !== undefined) {\n // Got session(s)\n return Array.isArray(result) ? result : [result];\n }\n // null => not a session entry, recurse if directory\n if (stats.isDirectory()) {\n return this.recursiveScan(path.join(dir, entry), matchEntry, maxDepth, _depth + 1);\n }\n return [];\n });\n\n const results = await Promise.allSettled(tasks);\n return results\n .filter(r => r.status === 'fulfilled')\n .flatMap(r => r.value)\n .filter(s => s !== null && s !== undefined);\n }\n\n /**\n * Find a specific session by ID within this source.\n * @param {string} _sessionId - Session ID\n * @param {string} _dir - Resolved source directory\n * @returns {Promise<import('../models/Session')|null>}\n */\n async findById(_sessionId, _dir) {\n throw new Error('BaseSourceAdapter: findById() must be implemented');\n }\n\n /**\n * Resolve the events file path for a given session.\n * @param {import('../models/Session')} _session - Session object\n * @param {string} _dir - Resolved source directory\n * @returns {Promise<string|null>}\n */\n async resolveEventsFile(_session, _dir) {\n throw new Error('BaseSourceAdapter: resolveEventsFile() must be implemented');\n }\n\n /**\n * Helper to read JSONL events stream\n * @param {string} eventsFile - Path to the events.jsonl file\n * @returns {Promise<Array>} Parsed events array\n */\n async readJsonlEvents(eventsFile) {\n if (!eventsFile) return [];\n \n try {\n await fs.promises.access(eventsFile);\n \n const fileStream = fs.createReadStream(eventsFile, { encoding: 'utf-8' });\n const rl = readline.createInterface({\n input: fileStream,\n crlfDelay: Infinity\n });\n \n let lineIndex = 0;\n const parsedEvents = [];\n \n for await (const line of rl) {\n const trimmedLine = line.trim();\n if (trimmedLine) {\n try {\n const event = JSON.parse(trimmedLine);\n event._fileIndex = lineIndex;\n parsedEvents.push(event);\n } catch (err) {\n console.error(`Error parsing line ${lineIndex + 1} in ${eventsFile}:`, err.message);\n }\n }\n lineIndex++;\n }\n \n return parsedEvents;\n } catch (err) {\n console.error('Error reading main events file:', err);\n return [];\n }\n }\n\n /**\n * Read and return raw events for a session.\n *\n * Adapters with a completely custom event pipeline (e.g. VSCode) should\n * override this method and return an array of raw events. Adapters that do\n * not implement a custom pipeline may leave the base implementation as-is,\n * in which case callers must not rely on any implicit fallback in\n * SessionService.\n *\n * Returning {@code null} from this method indicates that the adapter does\n * not produce events for the given session (i.e., \"no events\"), and should\n * not be interpreted as a request to invoke any shared JSONL pipeline.\n *\n * @param {import('../models/Session')} _session - Session object\n * @param {string} _dir - Resolved source directory\n * @returns {Promise<Array|null>} Events array, or {@code null} if the adapter\n * does not provide events for this session.\n */\n async readEvents(_session, _dir) {\n return null;\n }\n\n /**\n * Whether this adapter uses a fully custom readEvents() pipeline instead of\n * relying on the default/simple behavior expected by callers.\n *\n * When true, callers should treat this adapter as owning the complete event\n * ingestion pipeline for its sessions.\n *\n * @returns {boolean}\n */\n get hasCustomPipeline() {\n return false;\n }\n\n /**\n * Source-specific event normalization.\n * @param {Object} _event - Raw event object\n * @returns {Object} Normalized event\n */\n normalizeEvent(_event) {\n return _event;\n }\n\n /**\n * Match tool call/result pairs within the events array (mutates in-place).\n * @param {Array} _events - Events array\n */\n matchToolCalls(_events) {\n // Default: no-op\n }\n\n /**\n * Expand events into timeline-compatible format.\n * @param {Array} events - Events array\n * @returns {Array} Expanded events\n */\n expandToTimelineFormat(events) {\n return events;\n }\n\n /**\n * Resolve and merge sub-agent events into the main events array.\n * @param {Array} _events - Main events array (mutated in-place)\n * @param {string|null} _mainEventsFile - Path to main events file\n * @param {string} _sessionId - Session ID\n * @param {string} _dir - Resolved source directory\n * @returns {Promise<void>}\n */\n async mergeSubAgentEvents(_events, _mainEventsFile, _sessionId, _dir) {\n // Default: no-op\n }\n\n /**\n * Build unified timeline structure from events and session.\n * @param {Array} _events - Normalized events\n * @param {import('../models/Session')} _session - Session object\n * @returns {Object} Timeline data with turns, summary, etc.\n */\n buildTimeline(_events, _session) {\n return { turns: [], summary: {} };\n }\n\n /**\n * Locate session files on disk (for upload/import features).\n * @param {string} _sessionId - Session ID\n * @param {string} _baseDir - Base directory to search\n * @returns {Promise<Object|null>} Location info or null\n */\n async findSessionLocation(_sessionId, _baseDir) {\n return null;\n }\n\n /**\n * Resolve file/directory path for zip export.\n * @param {import('../models/Session')} _session - Session object\n * @param {string} _dir - Resolved source directory\n * @returns {Promise<{ path: string, isDirectory: boolean }|null>}\n */\n async resolveExportPath(_session, _dir) {\n return null;\n }\n\n /**\n * Inspect extracted zip and decide if this adapter can import it.\n * @param {string} _extractDir\n * @returns {Promise<{matched:boolean, score:number, reason:string, [key:string]:*}>}\n */\n async detectImportCandidate(_extractDir) {\n return { matched: false, score: 0, reason: `${this.type} import detection not implemented` };\n }\n\n /**\n * Import a previously matched extracted zip directory.\n * @param {Object} _detection - from detectImportCandidate\n * @param {Object} _ctx - { extractDir, req, targetDir? }\n * @returns {Promise<Object>}\n */\n async importDetectedSession(_detection, _ctx) {\n return { success: false, error: `Import not implemented for ${this.type}`, statusCode: 400 };\n }\n}\n\nmodule.exports = BaseSourceAdapter;\n\n", "const path = require('path');\n\n/**\n * Session domain model\n */\nclass Session {\n constructor(id, type, options = {}) {\n this.id = id;\n this.type = type; // 'directory' or 'file'\n this.source = options.source || 'copilot'; // 'copilot' or 'claude'\n this.directory = options.directory || null; // Full path to session directory\n this.filePath = options.filePath || null; // Full path to session file (for file-based sessions)\n this.workspace = options.workspace || {};\n this.createdAt = options.createdAt;\n this.updatedAt = options.updatedAt;\n this.summary = options.summary || (type === 'file' ? 'Legacy session' : 'No summary');\n this.hasEvents = options.hasEvents || false;\n this.eventCount = options.eventCount || 0;\n this.duration = options.duration || null; // Duration in milliseconds\n this.isImported = options.isImported || false; // Whether session was imported\n this.hasInsight = options.hasInsight || false; // Whether session has insight report\n this.copilotVersion = options.copilotVersion || null; // Copilot CLI version\n this.modernizeVersion = options.modernizeVersion || null; // Modernize CLI version (from dir path)\n this.selectedModel = options.selectedModel || null; // LLM model used\n this.agentName = options.agentName || null; // Custom agent name (from chatSessions)\n this.sessionStatus = options.sessionStatus || 'completed'; // 'completed' | 'wip'\n }\n\n /**\n * Create Session from directory\n * @param {string} dirPath - Directory path\n * @param {string} id - Session ID\n * @param {object} stats - fs.Stats object\n * @param {object} workspace - Parsed workspace.yaml\n * @param {number} eventCount - Number of events\n * @param {number|null} duration - Duration in milliseconds\n * @param {boolean} isImported - Whether session was imported\n * @param {boolean} hasInsight - Whether session has insight report\n * @param {string|null} copilotVersion - Copilot CLI version\n * @param {string|null} selectedModel - LLM model used\n * @param {string} sessionStatus - Session status: 'completed' or 'wip'\n * @returns {Session}\n */\n static fromDirectory(dirPath, id, stats, workspace, eventCount, duration, isImported, hasInsight, copilotVersion, selectedModel, sessionStatus) {\n const createdAt = workspace?.created_at\n ? new Date(workspace.created_at)\n : workspace?.startTime\n ? new Date(workspace.startTime)\n : (stats.birthtime || (stats.birthtimeMs ? new Date(stats.birthtimeMs) : undefined));\n const updatedAt = workspace?.updated_at\n ? new Date(workspace.updated_at)\n : workspace?.endTime\n ? new Date(workspace.endTime)\n : stats.mtime;\n return new Session(id, 'directory', {\n directory: dirPath, // Add directory path\n workspace: workspace,\n createdAt,\n updatedAt,\n summary: workspace?.summary || 'No summary',\n hasEvents: eventCount > 0,\n eventCount: eventCount,\n duration: duration,\n isImported: isImported,\n hasInsight: hasInsight,\n copilotVersion: copilotVersion,\n selectedModel: selectedModel,\n sessionStatus: sessionStatus\n });\n }\n\n /**\n * Create Session from .jsonl file\n * @param {string} filePath - File path\n * @param {string} id - Session ID\n * @param {object} stats - fs.Stats object\n * @param {number} eventCount - Number of events\n * @param {string} [summary] - Optional summary (e.g. first user message)\n * @param {number|null} duration - Duration in milliseconds\n * @param {string|null} copilotVersion - Copilot CLI version\n * @param {string|null} selectedModel - LLM model used\n * @param {string} sessionStatus - Session status: 'completed' or 'wip'\n * @returns {Session}\n */\n static fromFile(filePath, id, stats, eventCount, summary, duration, copilotVersion, selectedModel, sessionStatus) {\n return new Session(id, 'file', {\n filePath: filePath,\n directory: path.dirname(filePath), // Directory containing the file\n createdAt: stats.birthtime || (stats.birthtimeMs ? new Date(stats.birthtimeMs) : undefined),\n updatedAt: stats.mtime,\n summary: summary || 'Legacy session',\n hasEvents: true,\n eventCount: eventCount,\n duration: duration,\n isImported: false, // .jsonl files can't be imported\n hasInsight: false, // .jsonl files don't have insights\n copilotVersion: copilotVersion,\n selectedModel: selectedModel,\n sessionStatus: sessionStatus\n });\n }\n\n /**\n * Convert to plain object\n * @returns {object}\n */\n toJSON() {\n // Generate display-ready source metadata (Violation #3 & #5 fix)\n const sourceMetadata = this._getSourceDisplayMetadata(this.source);\n \n return {\n id: this.id,\n type: this.type,\n source: this.source,\n sourceName: sourceMetadata.name,\n sourceBadgeClass: sourceMetadata.badgeClass,\n directory: this.directory, // Include directory path\n workspace: this.workspace,\n createdAt: this.createdAt,\n updatedAt: this.updatedAt,\n summary: this.summary,\n hasEvents: this.hasEvents,\n eventCount: this.eventCount,\n duration: this.duration,\n isImported: this.isImported,\n hasInsight: this.hasInsight,\n copilotVersion: this.copilotVersion,\n modernizeVersion: this.modernizeVersion,\n selectedModel: this.selectedModel,\n agentName: this.agentName,\n sessionStatus: this.sessionStatus\n };\n }\n\n /**\n * Get display metadata for source.\n * Tries the adapter registry first, falls back to a hardcoded map for\n * backward compatibility (e.g. when registry hasn't loaded adapters yet).\n * @private\n */\n _getSourceDisplayMetadata(source) {\n // Try adapter registry first (dynamic \u2014 no code change needed for new sources)\n try {\n const { registry } = require('../adapters');\n const adapter = registry.get(source);\n if (adapter) {\n return adapter.displayMetadata;\n }\n } catch {\n // Registry not available (e.g. during early init or tests) \u2014 use fallback\n }\n\n // Hardcoded fallback (kept for backward compatibility)\n const metadata = {\n 'copilot': { name: 'Copilot CLI', badgeClass: 'source-copilot' },\n 'claude': { name: 'Claude', badgeClass: 'source-claude' },\n 'pi-mono': { name: 'Pi', badgeClass: 'source-pi-mono' },\n 'vscode': { name: 'Copilot Chat', badgeClass: 'source-vscode' }\n };\n return metadata[source] || { name: source, badgeClass: 'source-unknown' };\n }\n}\n\nmodule.exports = Session;\n", "/**\n * Shared utilities for Source Adapters.\n *\n * These functions are used by multiple adapters and extracted here\n * to avoid duplication. They were previously private methods on\n * SessionRepository.\n */\n\nconst fsSync = require('fs');\nconst readline = require('readline');\n\n/**\n * Read the first line of a file efficiently (streams, doesn't load entire file).\n * @param {string} filePath - Absolute path to the file\n * @returns {Promise<string|null>} First trimmed line, or null if file is empty\n */\nfunction readFirstLine(filePath) {\n return new Promise((resolve, reject) => {\n const stream = fsSync.createReadStream(filePath, { encoding: 'utf-8' });\n const rl = readline.createInterface({\n input: stream,\n crlfDelay: Infinity\n });\n\n let resolved = false;\n\n rl.on('line', (line) => {\n if (!resolved) {\n resolved = true;\n rl.close();\n resolve(line.trim());\n }\n });\n\n rl.on('close', () => {\n if (!resolved) {\n resolve(null);\n }\n });\n\n rl.on('error', (err) => {\n if (!resolved) {\n resolved = true;\n reject(err);\n }\n });\n\n stream.on('error', (err) => {\n if (!resolved) {\n resolved = true;\n rl.close();\n reject(err);\n }\n });\n });\n}\n\n/**\n * Compute session status from metadata.\n * A session is 'wip' if it has no session.end event AND the last event\n * was within the WIP threshold (5 minutes). Otherwise it's 'completed'.\n *\n * @param {Object} metadata - Session metadata from getSessionMetadataOptimized()\n * @param {boolean} metadata.hasSessionEnd - Whether a session.end event exists\n * @param {number|null|undefined} metadata.lastEventTime - Timestamp of last event (ms)\n * @returns {'completed'|'wip'}\n */\nfunction computeSessionStatus(metadata) {\n if (metadata.hasSessionEnd) {\n return 'completed';\n }\n if (metadata.lastEventTime !== null && metadata.lastEventTime !== undefined) {\n const WIP_THRESHOLD_MS = 5 * 60 * 1000;\n if ((Date.now() - metadata.lastEventTime) < WIP_THRESHOLD_MS) {\n return 'wip';\n }\n }\n return 'completed';\n}\n\nmodule.exports = {\n readFirstLine,\n computeSessionStatus\n};\n\n", "const path = require('path');\nconst os = require('os');\nconst fsSync = require('fs');\nconst fs = fsSync.promises;\nconst BaseSourceAdapter = require('./BaseSourceAdapter');\nconst Session = require('../models/Session');\nconst { fileExists, countLines, parseYAML, getSessionMetadataOptimized, shouldSkipEntry } = require('../utils/fileUtils');\nconst { computeSessionStatus } = require('./adapterUtils');\n\n/**\n * Copilot CLI Source Adapter\n *\n * Handles sessions stored in ~/.copilot/session-state/\n * Supports both directory-based (events.jsonl + workspace.yaml) and\n * standalone .jsonl file sessions.\n */\nclass CopilotAdapter extends BaseSourceAdapter {\n get type() { return 'copilot'; }\n get displayName() { return 'Copilot CLI'; }\n get envVar() { return 'COPILOT_SESSION_DIR'; }\n\n getDefaultDir() {\n return process.env.SESSION_DIR || // Legacy fallback\n path.join(os.homedir(), '.copilot', 'session-state');\n }\n\n async scanEntries(dir) {\n return this.recursiveScan(dir, async (fullPath, entry, stats) => {\n if (stats.isDirectory()) {\n const hasEvents = await fileExists(path.join(fullPath, 'events.jsonl'));\n const hasWorkspace = await fileExists(path.join(fullPath, 'workspace.yaml'));\n if (hasEvents || hasWorkspace) {\n return this._createDirectorySession(entry, fullPath, stats);\n }\n return null; // recurse\n } else if (entry.endsWith('.jsonl')) {\n return this._createFileSession(entry, fullPath, stats);\n }\n return false; // skip non-jsonl files\n });\n }\n\n async findById(sessionId, dir) {\n // Try direct path first (fast path)\n try {\n const dirPath = path.join(dir, sessionId);\n const dirStats = await fs.stat(dirPath);\n if (dirStats.isDirectory()) {\n return await this._createDirectorySession(sessionId, dirPath, dirStats);\n }\n } catch {\n // Not a directory\n }\n\n try {\n const filePath = path.join(dir, `${sessionId}.jsonl`);\n const fileStats = await fs.stat(filePath);\n if (fileStats.isFile()) {\n return await this._createFileSession(`${sessionId}.jsonl`, filePath, fileStats);\n }\n } catch {\n // File not found\n }\n\n // Recursive search for nested session dirs\n const result = await this._findByIdRecursive(sessionId, dir, 5, 0);\n return result;\n }\n\n async _findByIdRecursive(sessionId, dir, maxDepth, depth) {\n if (depth > maxDepth) return null;\n let entries;\n try {\n entries = await fs.readdir(dir);\n } catch {\n return null;\n }\n for (const entry of entries) {\n if (shouldSkipEntry(entry)) continue;\n const fullPath = path.join(dir, entry);\n let stats;\n try {\n stats = await fs.stat(fullPath);\n } catch {\n continue;\n }\n if (!stats.isDirectory()) continue;\n if (entry === sessionId) {\n const hasEvents = await fileExists(path.join(fullPath, 'events.jsonl'));\n const hasWorkspace = await fileExists(path.join(fullPath, 'workspace.yaml'));\n if (hasEvents || hasWorkspace) {\n return this._createDirectorySession(entry, fullPath, stats);\n }\n }\n const found = await this._findByIdRecursive(sessionId, fullPath, maxDepth, depth + 1);\n if (found) return found;\n }\n return null;\n }\n\n async resolveEventsFile(session, dir) {\n // Use session's stored directory path if available (handles nested/recursive dirs)\n if (session.directory) {\n const eventsPath = path.join(session.directory, 'events.jsonl');\n try {\n await fs.access(eventsPath);\n return eventsPath;\n } catch {\n // fall through to dir-based resolution\n }\n }\n\n const sessionId = session.id || session;\n const sessionPath = path.join(dir, sessionId);\n try {\n const stats = await fs.stat(sessionPath);\n if (stats.isDirectory()) {\n return path.join(sessionPath, 'events.jsonl');\n } else {\n return path.join(dir, `${sessionId}.jsonl`);\n }\n } catch (_err) {\n // For file-based sessions\n if (session.filePath) return session.filePath;\n return path.join(dir, `${sessionId}.jsonl`);\n }\n }\n\n async readEvents(session, dir) {\n const eventsFile = await this.resolveEventsFile(session, dir);\n return this.readJsonlEvents(eventsFile);\n }\n\n async _createDirectorySession(entry, fullPath, stats) {\n const workspaceFile = path.join(fullPath, 'workspace.yaml');\n const eventsFile = path.join(fullPath, 'events.jsonl');\n const importedMarkerFile = path.join(fullPath, '.imported');\n const insightReportFile = path.join(fullPath, `${entry}.agent-review.md`);\n\n const workspace = await fileExists(workspaceFile)\n ? await parseYAML(workspaceFile)\n : { summary: entry, repo: 'unknown' };\n\n const eventCount = await fileExists(eventsFile) ? await countLines(eventsFile) : 0;\n const isImported = await fileExists(importedMarkerFile);\n const hasInsight = await fileExists(insightReportFile);\n\n let duration = null;\n let copilotVersion = null;\n let selectedModel = null;\n let sessionStatus = 'completed';\n\n if (await fileExists(eventsFile)) {\n const optimizedMetadata = await getSessionMetadataOptimized(eventsFile);\n duration = optimizedMetadata.duration;\n copilotVersion = optimizedMetadata.copilotVersion;\n selectedModel = optimizedMetadata.selectedModel;\n sessionStatus = computeSessionStatus(optimizedMetadata);\n\n if (!workspace.summary && optimizedMetadata.firstUserMessage) {\n workspace.summary = optimizedMetadata.firstUserMessage;\n }\n\n if (optimizedMetadata.lastEventTime) {\n const lastEventMs = new Date(optimizedMetadata.lastEventTime).getTime();\n const mtimeMs = new Date(stats.mtime).getTime();\n if (lastEventMs > mtimeMs) {\n stats = { ...stats, mtime: new Date(lastEventMs) };\n }\n }\n }\n\n const session = Session.fromDirectory(fullPath, entry, stats, workspace, eventCount, duration, isImported, hasInsight, copilotVersion, selectedModel, sessionStatus);\n session.source = 'copilot';\n return session;\n }\n\n async _createFileSession(entry, fullPath, stats) {\n const sessionId = entry.replace('.jsonl', '');\n const eventCount = await countLines(fullPath);\n\n const optimizedMetadata = await getSessionMetadataOptimized(fullPath);\n const sessionStatus = computeSessionStatus(optimizedMetadata);\n\n const session = Session.fromFile(\n fullPath, sessionId, stats, eventCount,\n optimizedMetadata.firstUserMessage,\n optimizedMetadata.duration,\n optimizedMetadata.copilotVersion,\n optimizedMetadata.selectedModel,\n sessionStatus\n );\n session.source = 'copilot';\n return session;\n }\n\n async detectImportCandidate(extractDir) {\n const entries = await fs.readdir(extractDir);\n for (const entry of entries) {\n const entryPath = path.join(extractDir, entry);\n const stat = await fs.stat(entryPath);\n if (stat.isDirectory() && fsSync.existsSync(path.join(entryPath, 'events.jsonl'))) {\n return { matched: true, score: 100, reason: 'Directory with events.jsonl', sessionId: entry, directoryName: entry };\n }\n }\n return { matched: false, score: 0, reason: 'No directory containing events.jsonl found' };\n }\n\n async importDetectedSession(det, ctx) {\n const { isValidSessionId } = require('../utils/helpers');\n const { sessionId, directoryName } = det;\n if (!isValidSessionId(sessionId)) return { success: false, error: 'Invalid session ID', statusCode: 400 };\n const src = path.join(ctx.extractDir, directoryName);\n if (!fsSync.existsSync(path.join(src, 'events.jsonl'))) return { success: false, error: 'Invalid session structure (no events.jsonl)', statusCode: 400 };\n const targetBase = ctx.targetDir || await this.resolveDir();\n const target = path.join(targetBase, sessionId);\n if (fsSync.existsSync(target)) return { success: false, error: 'Session already exists', statusCode: 409 };\n await fs.mkdir(targetBase, { recursive: true });\n await fs.rename(src, target);\n await fs.writeFile(path.join(target, '.imported'), '');\n return { success: true, sessionId, format: this.type };\n }\n}\n\nmodule.exports = CopilotAdapter;\n", "/**\n * Base Session Parser Interface\n * \n * All session parsers must implement these methods\n */\nclass BaseSessionParser {\n /**\n * Detect if this parser can handle the given events\n * @param {Array<Object>} _events - Raw events from jsonl\n * @returns {boolean}\n */\n canParse(_events) {\n throw new Error('canParse() must be implemented');\n }\n\n /**\n * Parse raw events into normalized format\n * @param {Array<Object>} _events - Raw events from jsonl\n * @returns {Object} Parsed session data\n */\n parse(_events) {\n throw new Error('parse() must be implemented');\n }\n\n /**\n * Get session metadata (sessionId, startTime, model, etc.)\n * @param {Array<Object>} _events - Raw events\n * @returns {Object} Session metadata\n */\n getMetadata(_events) {\n throw new Error('getMetadata() must be implemented');\n }\n\n /**\n * Extract turns (user message + assistant response pairs)\n * @param {Array<Object>} _events - Raw events\n * @returns {Array<Object>} Array of turns\n */\n extractTurns(_events) {\n throw new Error('extractTurns() must be implemented');\n }\n\n /**\n * Extract tool calls/executions\n * @param {Array<Object>} _events - Raw events\n * @returns {Array<Object>} Array of tool calls\n */\n extractToolCalls(_events) {\n throw new Error('extractToolCalls() must be implemented');\n }\n}\n\nmodule.exports = BaseSessionParser;\n", "const BaseSessionParser = require('./base-parser');\n\n/**\n * Copilot CLI Session Parser\n * \n * Parses events from GitHub Copilot CLI (copilot-agent)\n * Format: {type: \"session.start\", data: {...}, id: \"...\", parentId: \"...\"}\n */\nclass CopilotSessionParser extends BaseSessionParser {\n canParse(events) {\n if (!events || events.length === 0) return false;\n \n // Check for Copilot CLI specific event types\n const copilotEventTypes = [\n 'session.start',\n 'user.message',\n 'assistant.turn_start',\n 'assistant.message',\n 'tool.execution_start'\n ];\n \n return events.some(e => \n e.type && copilotEventTypes.some(t => e.type.startsWith(t))\n );\n }\n\n parse(events) {\n return {\n metadata: this.getMetadata(events),\n turns: this.extractTurns(events),\n toolCalls: this.extractToolCalls(events),\n allEvents: events\n };\n }\n\n getMetadata(events) {\n const sessionStart = events.find(e => e.type === 'session.start');\n if (!sessionStart) return null;\n\n const data = sessionStart.data || {};\n return {\n sessionId: data.sessionId,\n startTime: data.startTime,\n model: data.selectedModel,\n version: data.copilotVersion,\n producer: data.producer,\n cwd: data.context?.cwd,\n gitRoot: data.context?.gitRoot,\n branch: data.context?.branch,\n repository: data.context?.repository\n };\n }\n\n extractTurns(events) {\n const turns = [];\n let currentTurn = null;\n\n for (const event of events) {\n if (event.type === 'user.message') {\n // Start new turn\n if (currentTurn) {\n turns.push(currentTurn);\n }\n currentTurn = {\n turnId: event.id,\n userMessage: {\n id: event.id,\n content: event.data?.content || '',\n transformedContent: event.data?.transformedContent,\n timestamp: event.timestamp\n },\n assistantMessages: [],\n toolCalls: []\n };\n } else if (event.type === 'assistant.message' && currentTurn) {\n currentTurn.assistantMessages.push({\n id: event.id,\n messageId: event.data?.messageId,\n content: event.data?.content || '',\n toolRequests: event.data?.toolRequests || [],\n reasoningText: event.data?.reasoningText,\n timestamp: event.timestamp\n });\n } else if (event.type.startsWith('tool.execution_') && currentTurn) {\n const toolCallId = event.data?.toolCallId;\n let toolCall = currentTurn.toolCalls.find(tc => tc.toolCallId === toolCallId);\n \n if (!toolCall) {\n toolCall = { toolCallId, events: [] };\n currentTurn.toolCalls.push(toolCall);\n }\n \n toolCall.events.push(event);\n \n if (event.type === 'tool.execution_start') {\n toolCall.name = event.data?.toolName;\n toolCall.arguments = event.data?.arguments;\n } else if (event.type === 'tool.execution_complete') {\n toolCall.result = event.data?.result;\n toolCall.exitCode = event.data?.exitCode;\n }\n }\n }\n\n // Push last turn\n if (currentTurn) {\n turns.push(currentTurn);\n }\n\n return turns;\n }\n\n extractToolCalls(events) {\n const toolCalls = [];\n const toolCallMap = new Map();\n\n for (const event of events) {\n if (event.type === 'tool.execution_start') {\n const toolCallId = event.data?.toolCallId;\n toolCallMap.set(toolCallId, {\n toolCallId,\n name: event.data?.toolName,\n arguments: event.data?.arguments,\n startEvent: event,\n completeEvent: null\n });\n } else if (event.type === 'tool.execution_complete') {\n const toolCallId = event.data?.toolCallId;\n const toolCall = toolCallMap.get(toolCallId);\n if (toolCall) {\n toolCall.completeEvent = event;\n toolCall.result = event.data?.result;\n toolCall.exitCode = event.data?.exitCode;\n toolCalls.push(toolCall);\n }\n }\n }\n\n return toolCalls;\n }\n}\n\nmodule.exports = CopilotSessionParser;\n", "const BaseSessionParser = require('./base-parser');\n\n/**\n * Claude Code Session Parser\n * \n * Parses events from Anthropic Claude Code CLI\n * Format: {type: \"user\"|\"assistant\", uuid: \"...\", parentUuid: \"...\", message: {...}}\n */\nclass ClaudeSessionParser extends BaseSessionParser {\n canParse(events) {\n if (!events || events.length === 0) return false;\n \n // Check for Claude Code specific structure\n return events.some(e => \n e.type && ['user', 'assistant'].includes(e.type) &&\n e.uuid && Object.prototype.hasOwnProperty.call(e, 'parentUuid') && e.sessionId\n );\n }\n\n parse(events) {\n return {\n metadata: this.getMetadata(events),\n turns: this.extractTurns(events),\n toolCalls: this.extractToolCalls(events),\n allEvents: events\n };\n }\n\n getMetadata(events) {\n const firstUserMessage = events.find(e => e.type === 'user');\n if (!firstUserMessage) return null;\n\n // Extract model from assistant messages\n const firstAssistant = events.find(e => e.type === 'assistant' && e.message?.model);\n const model = firstAssistant?.message?.model || 'unknown';\n\n return {\n sessionId: firstUserMessage.sessionId,\n startTime: firstUserMessage.timestamp,\n model: model,\n version: firstUserMessage.version,\n producer: 'claude-code',\n cwd: firstUserMessage.cwd,\n gitRoot: null, // Not available in Claude format\n branch: firstUserMessage.gitBranch,\n repository: null // Not available in Claude format\n };\n }\n\n extractTurns(events) {\n const turns = [];\n const messageEvents = events.filter(e => \n ['user', 'assistant'].includes(e.type) &&\n e.type !== 'file-history-snapshot' &&\n e.type !== 'queue-operation'\n );\n\n // Build parent-child tree\n const eventMap = new Map();\n for (const event of messageEvents) {\n eventMap.set(event.uuid, event);\n }\n\n // Find root user messages (no parentUuid or parent is not a message)\n const rootMessages = messageEvents.filter(e => \n e.type === 'user' && (!e.parentUuid || !eventMap.has(e.parentUuid))\n );\n\n for (const userMsg of rootMessages) {\n const turn = {\n turnId: userMsg.uuid,\n userMessage: {\n id: userMsg.uuid,\n content: this._extractMessageContent(userMsg.message),\n timestamp: userMsg.timestamp\n },\n assistantMessages: [],\n toolCalls: []\n };\n\n // Find all children of this user message\n this._collectAssistantResponses(userMsg.uuid, eventMap, turn);\n\n turns.push(turn);\n }\n\n return turns;\n }\n\n _collectAssistantResponses(parentUuid, eventMap, turn) {\n for (const [_uuid, event] of eventMap.entries()) {\n if (event.parentUuid === parentUuid) {\n if (event.type === 'assistant') {\n const assistantMsg = {\n id: event.uuid,\n messageId: event.message?.id,\n content: this._extractMessageContent(event.message),\n model: event.message?.model,\n timestamp: event.timestamp\n };\n\n // Extract tool calls from content\n const toolUseBlocks = this._extractToolUse(event.message);\n if (toolUseBlocks.length > 0) {\n assistantMsg.toolRequests = toolUseBlocks;\n turn.toolCalls.push(...toolUseBlocks.map(t => ({\n toolCallId: t.id,\n name: t.name,\n arguments: t.input,\n parentUuid: event.uuid\n })));\n }\n\n turn.assistantMessages.push(assistantMsg);\n\n // Recursively collect children (follow-up messages)\n this._collectAssistantResponses(event.uuid, eventMap, turn);\n }\n }\n }\n }\n\n _extractMessageContent(message) {\n if (!message || !message.content) return '';\n \n if (typeof message.content === 'string') {\n return message.content;\n }\n\n if (Array.isArray(message.content)) {\n return message.content\n .filter(block => block.type === 'text')\n .map(block => block.text)\n .join('\\n');\n }\n\n return '';\n }\n\n _extractToolUse(message) {\n if (!message || !message.content || !Array.isArray(message.content)) {\n return [];\n }\n\n return message.content\n .filter(block => block.type === 'tool_use')\n .map(block => ({\n id: block.id,\n name: block.name,\n input: block.input\n }));\n }\n\n extractToolCalls(events) {\n const toolCalls = [];\n\n for (const event of events) {\n if (event.type === 'assistant' && event.message?.content) {\n const toolUseBlocks = this._extractToolUse(event.message);\n \n for (const tool of toolUseBlocks) {\n toolCalls.push({\n toolCallId: tool.id,\n name: tool.name,\n arguments: tool.input,\n parentUuid: event.uuid,\n timestamp: event.timestamp,\n // Claude format doesn't have separate execution events\n // Tool result would be in a following user message with tool_result\n result: null,\n exitCode: null\n });\n }\n }\n }\n\n return toolCalls;\n }\n}\n\nmodule.exports = ClaudeSessionParser;\n", "/**\n * Pi-Mono session parser\n * Parses ~/.pi/agent/sessions/ format\n */\n\nconst BaseParser = require('./base-parser');\n\nclass PiMonoParser extends BaseParser {\n constructor() {\n super('pi-mono');\n }\n\n /**\n * Parse Pi-Mono session directory\n * @param {string} sessionDir - e.g., ~/.pi/agent/sessions/--project-path--/\n * @returns {Object|null} - Session metadata or null if invalid\n */\n async parseSessionDir(sessionDir) {\n const fs = require('fs').promises;\n const path = require('path');\n\n try {\n // List .jsonl files in directory\n const entries = await fs.readdir(sessionDir);\n const jsonlFiles = entries.filter(f => f.endsWith('.jsonl'));\n\n if (jsonlFiles.length === 0) {\n return null;\n }\n\n // Use the latest file for metadata\n jsonlFiles.sort().reverse();\n const latestFile = path.join(sessionDir, jsonlFiles[0]);\n const firstLine = await this._readFirstLine(latestFile);\n\n if (!firstLine) {\n return null;\n }\n\n const sessionEvent = JSON.parse(firstLine);\n \n if (sessionEvent.type !== 'session') {\n console.warn(`Pi-Mono file ${latestFile} doesn't start with session event`);\n return null;\n }\n\n // Extract project name from directory name\n const dirName = path.basename(sessionDir);\n const projectPath = dirName.replace(/^--/, '').replace(/--$/, '');\n\n return {\n id: sessionEvent.id,\n type: 'pi-mono',\n source: 'pi-mono',\n cwd: sessionEvent.cwd || projectPath,\n createdAt: new Date(sessionEvent.timestamp),\n updatedAt: new Date(sessionEvent.timestamp), // Will be updated when scanning all files\n summary: `Pi-Mono: ${projectPath}`,\n fileCount: jsonlFiles.length\n };\n } catch (err) {\n console.error(`Error parsing Pi-Mono session dir ${sessionDir}:`, err.message);\n return null;\n }\n }\n\n /**\n * Read first line of a file\n */\n async _readFirstLine(filePath) {\n const fs = require('fs');\n const readline = require('readline');\n\n return new Promise((resolve) => {\n const stream = fs.createReadStream(filePath, { encoding: 'utf-8' });\n const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });\n\n rl.on('line', (line) => {\n rl.close();\n stream.destroy();\n resolve(line.trim());\n });\n\n rl.on('close', () => resolve(null));\n });\n }\n\n /**\n * Parse Pi-Mono events from .jsonl file\n * @param {string} filePath\n * @returns {Array} - Array of parsed events\n */\n async parseEvents(filePath) {\n const fs = require('fs');\n const readline = require('readline');\n\n const events = [];\n const stream = fs.createReadStream(filePath, { encoding: 'utf-8' });\n const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });\n\n let lineIndex = 0;\n for await (const line of rl) {\n lineIndex++;\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n try {\n const event = JSON.parse(trimmed);\n events.push(event);\n } catch (err) {\n console.error(`Error parsing Pi-Mono line ${lineIndex}:`, err.message);\n }\n }\n\n return events;\n }\n}\n\nmodule.exports = PiMonoParser;\n", "const BaseSessionParser = require('./base-parser');\n\n/**\n * VSCode Copilot Chat Session Parser\n *\n * Parses chat sessions stored by VS Code's GitHub Copilot Chat extension.\n * Location: ~/Library/Application Support/Code/User/workspaceStorage/<hash>/chatSessions/<uuid>.json\n *\n * Format: A single JSON object with a `requests` array. Each request has\n * a `message` (user input) and a `response` array of typed content items.\n */\nclass VsCodeParser extends BaseSessionParser {\n /**\n * VSCode sessions can be either:\n * 1. Old format: Plain JSON object with `requests` array\n * 2. New format: JSONL with ObjectMutationLog entries (kind: 0|1|2|3)\n *\n * For JSONL format, the first line has kind=0 with v.sessionId\n */\n canParse(lines) {\n if (!Array.isArray(lines) || lines.length === 0) return false;\n\n // Check if this is JSONL format (array of parsed lines)\n const firstLine = lines[0];\n\n // New JSONL format: first line has kind=0 and v.sessionId\n if (firstLine && typeof firstLine === 'object' &&\n firstLine.kind === 0 &&\n firstLine.v &&\n firstLine.v.sessionId) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Parse a VSCode chat session JSON object into the normalised format.\n * @param {Object} sessionJson - Parsed JSON from chatSessions/<uuid>.json\n * @returns {Object} Normalised session data\n */\n parseVsCode(sessionJson) {\n const metadata = this._getMetadata(sessionJson);\n const events = this._toEvents(sessionJson);\n return {\n metadata,\n turns: this._extractTurns(events),\n toolCalls: this._extractToolCalls(events),\n allEvents: events,\n };\n }\n\n /**\n * Parse JSONL format (ObjectMutationLog) - new VS Code format\n * @param {Array} lines - Array of parsed JSON objects from JSONL file\n * @returns {Object} Normalised session data\n */\n parseJsonl(lines) {\n // Replay mutations to reconstruct the session state\n const sessionState = this.replayMutations(lines);\n\n // Use existing methods to convert to events\n const metadata = this._getMetadata(sessionState);\n const events = this._toEvents(sessionState);\n\n return {\n metadata,\n turns: this._extractTurns(events),\n toolCalls: this._extractToolCalls(events),\n allEvents: events,\n };\n }\n\n /**\n * Replay ObjectMutationLog entries to reconstruct session state\n * @param {Array} lines - Array of mutation entries { kind, k, v, i }\n * @returns {Object} Reconstructed session state\n */\n replayMutations(lines) {\n let state = null;\n\n for (const entry of lines) {\n if (!entry || typeof entry !== 'object') continue;\n\n const { kind, k, v, i } = entry;\n\n switch (kind) {\n case 0: // Initial - set entire state\n state = v;\n break;\n\n case 1: // Set - update property at path\n if (k && Array.isArray(k)) {\n this._applySet(state, k, v);\n }\n break;\n\n case 2: // Push - append to array (with optional truncate)\n if (k && Array.isArray(k)) {\n this._applyPush(state, k, v, i);\n }\n break;\n\n case 3: // Delete - remove property at path\n if (k && Array.isArray(k)) {\n this._applyDelete(state, k);\n }\n break;\n\n default:\n console.warn(`[VsCodeParser] Unknown mutation kind: ${kind}`);\n }\n }\n\n return state;\n }\n\n /**\n * Apply Set mutation: set value at path k in state\n * @private\n */\n _applySet(state, path, value) {\n if (!state || path.length === 0) return;\n\n let current = state;\n for (let i = 0; i < path.length - 1; i++) {\n const key = path[i];\n if (!current[key]) {\n // Create intermediate object or array based on next key type\n current[key] = typeof path[i + 1] === 'number' ? [] : {};\n }\n current = current[key];\n }\n\n const lastKey = path[path.length - 1];\n current[lastKey] = value;\n }\n\n /**\n * Apply Push mutation: append items to array at path k\n * If i is set, truncate array to index i first\n * @private\n */\n _applyPush(state, path, values, startIndex) {\n if (!state || path.length === 0) return;\n\n let current = state;\n for (let i = 0; i < path.length - 1; i++) {\n const key = path[i];\n if (!current[key]) {\n current[key] = typeof path[i + 1] === 'number' ? [] : {};\n }\n current = current[key];\n }\n\n const lastKey = path[path.length - 1];\n if (!current[lastKey]) {\n current[lastKey] = [];\n }\n\n const arr = current[lastKey];\n if (!Array.isArray(arr)) {\n console.warn(`[VsCodeParser] Push target is not an array: ${path.join('.')}`);\n return;\n }\n\n // Truncate if startIndex is specified\n if (startIndex !== undefined && startIndex !== null) {\n arr.length = startIndex;\n }\n\n // Append new values\n if (values && Array.isArray(values) && values.length > 0) {\n arr.push(...values);\n }\n }\n\n /**\n * Apply Delete mutation: remove property at path k\n * @private\n */\n _applyDelete(state, path) {\n if (!state || path.length === 0) return;\n\n let current = state;\n for (let i = 0; i < path.length - 1; i++) {\n const key = path[i];\n if (!current[key]) return; // Path doesn't exist\n current = current[key];\n }\n\n const lastKey = path[path.length - 1];\n delete current[lastKey];\n }\n\n // ---- required abstract methods (for ParserFactory interface) ----\n parse(events) {\n // For JSONL format, use parseJsonl\n if (Array.isArray(events) && events.length > 0 && this.canParse(events)) {\n return this.parseJsonl(events);\n }\n return null;\n }\n\n getMetadata(events) {\n const parsed = this.parse(events);\n return parsed ? parsed.metadata : null;\n }\n\n extractTurns(events) {\n const parsed = this.parse(events);\n return parsed ? parsed.turns : [];\n }\n\n extractToolCalls(events) {\n const parsed = this.parse(events);\n return parsed ? parsed.toolCalls : [];\n }\n\n // ---- private helpers ----\n\n _getMetadata(sessionJson) {\n const requests = sessionJson.requests || [];\n const firstReq = requests[0] || {};\n const lastReq = requests[requests.length - 1] || {};\n\n // Derive workspace label from agent name or fallback\n const agentName = firstReq.agent?.name || firstReq.agent?.id || 'vscode-copilot';\n\n return {\n sessionId: sessionJson.sessionId,\n startTime: sessionJson.creationDate\n ? new Date(sessionJson.creationDate).toISOString()\n : (firstReq.timestamp ? new Date(firstReq.timestamp).toISOString() : null),\n endTime: sessionJson.lastMessageDate\n ? new Date(sessionJson.lastMessageDate).toISOString()\n : (lastReq.timestamp ? new Date(lastReq.timestamp).toISOString() : null),\n model: firstReq.modelId || null,\n producer: 'vscode-copilot-chat',\n version: firstReq.agent?.extensionVersion || null,\n agentName,\n requestCount: requests.length,\n };\n }\n\n /**\n * Convert VSCode session JSON into a flat event array that matches the\n * normalised event schema used by the rest of the viewer.\n */\n _toEvents(sessionJson) {\n const events = [];\n const requests = sessionJson.requests || [];\n\n // session.start synthetic event\n events.push({\n type: 'session.start',\n id: `${sessionJson.sessionId}-start`,\n timestamp: sessionJson.creationDate\n ? new Date(sessionJson.creationDate).toISOString()\n : null,\n data: {\n sessionId: sessionJson.sessionId,\n producer: 'vscode-copilot-chat',\n selectedModel: requests[0]?.modelId || null,\n },\n });\n\n for (const req of requests) {\n const ts = req.timestamp ? new Date(req.timestamp).toISOString() : null;\n // Use completedAt for assistant events \u2014 more accurate than request start time\n const completedAt = req.modelState?.completedAt\n ? new Date(req.modelState.completedAt).toISOString()\n : ts;\n\n\n // Build subAgentInvocationId \u2192 agent name map from this request's response items\n const responseItems = Array.isArray(req.response) ? req.response : [];\n const subAgentNames = this._buildSubAgentNameMap(responseItems);\n\n // Note: VS Code JSONL does not record per-subagent timestamps.\n // All subagents in a request span the same wall-clock window (they run in parallel).\n // Use request start as START and request completedAt as COMPLETE for all subagents,\n // which is accurate for parallel dispatch and avoids interleaved/crossed timelines.\n\n // user.message\n const userText = this._extractUserText(req.message);\n events.push({\n type: 'user.message',\n id: req.requestId,\n timestamp: ts,\n data: {\n message: userText,\n content: userText,\n },\n });\n\n // assistant.turn_start\n events.push({\n type: 'assistant.turn_start',\n id: `${req.requestId}-turn`,\n timestamp: ts,\n parentId: req.requestId,\n data: {},\n });\n\n let assistantText = '';\n let itemIndex = 0;\n let currentSubAgentId = null;\n\n const flushText = () => {\n const trimmed = assistantText.trim().replace(/^`{3,}$/gm, '').trim();\n assistantText = '';\n if (!trimmed) return;\n const sid = currentSubAgentId;\n const agentName = sid ? (subAgentNames[sid] || sid.slice(0, 8)) : null;\n events.push({\n type: 'assistant.message',\n id: `${req.requestId}-text-${itemIndex}`,\n timestamp: completedAt,\n parentId: req.requestId,\n data: {\n message: trimmed,\n content: trimmed,\n tools: [],\n subAgentId: sid || null,\n subAgentName: agentName,\n parentToolCallId: null,\n },\n });\n };\n\n for (const item of responseItems) {\n itemIndex++;\n switch (item.kind) {\n case 'thinking': {\n const text = item.content?.value || item.content || '';\n if (text) assistantText += text + '\\n';\n break;\n }\n\n case 'markdownContent': {\n const text = item.content?.value || item.content || '';\n if (text) assistantText += text + '\\n';\n break;\n }\n\n case undefined:\n case null: {\n // Plain markdown text item (no kind field, has 'value')\n const text = item.value || '';\n if (text) assistantText += text;\n break;\n }\n\n case 'inlineReference': {\n // File/folder reference inline in markdown \u2014 append name as code reference\n const name = item.name || '';\n if (name) assistantText += '`' + name + '`';\n break;\n }\n\n case 'toolInvocationSerialized': {\n flushText();\n // runSubagent items: toolId='runSubagent', toolCallId=subagent-id, subAgentInvocationId=null\n // Regular tool items: toolId=e.g. 'copilot_readFile', subAgentInvocationId=owning-subagent-id\n const sid = item.toolId === 'runSubagent'\n ? item.toolCallId // the subagent being launched\n : item.subAgentInvocationId; // the subagent that launched this tool\n if (item.toolId === 'runSubagent') {\n // Mark current context as this subagent (for subsequent tool items)\n currentSubAgentId = sid;\n }\n if (sid) currentSubAgentId = sid;\n const tool = this._normalizeTool(item);\n if (tool) {\n const agentName = sid ? (subAgentNames[sid] || sid.slice(0, 8)) : null;\n events.push({\n type: 'tool.invocation',\n id: tool.id || `${req.requestId}-tool-${itemIndex}`,\n timestamp: completedAt,\n parentId: req.requestId,\n data: {\n tool,\n subAgentId: sid || null,\n subAgentName: agentName,\n parentToolCallId: sid || null,\n badgeLabel: tool.name,\n badgeClass: tool.status === 'error' ? 'badge-error' : 'badge-tool',\n },\n });\n }\n break;\n }\n\n case 'textEditGroup': {\n flushText();\n const edits = item.edits || item.uri ? [item] : [];\n events.push({\n type: 'tool.invocation',\n id: `${req.requestId}-edit-${itemIndex}`,\n timestamp: completedAt,\n parentId: req.requestId,\n data: {\n tool: {\n type: 'tool_use',\n id: `${req.requestId}-edit-${itemIndex}`,\n name: 'textEdit',\n startTime: ts,\n endTime: ts,\n status: 'completed',\n input: { uri: item.uri, edits },\n result: 'file edit',\n error: null,\n },\n badgeLabel: 'textEdit',\n badgeClass: 'badge-tool',\n },\n });\n break;\n }\n\n case 'prepareToolInvocation':\n case 'undoStop':\n case 'codeblockUri':\n case 'mcpServersStarting':\n // Skip non-visible items\n break;\n\n default:\n break;\n }\n }\n\n flushText(); // flush any trailing text\n }\n\n return events;\n }\n\n /**\n * Build a map of subagent id \u2192 agent name from runSubagent tool invocations.\n * runSubagent items: toolId='runSubagent', toolCallId=subagent-id\n * Agent name is extracted from invocationMessage or resultDetails.\n */\n _buildSubAgentNameMap(items) {\n const nameMap = {};\n for (const item of items) {\n if (!item || typeof item !== 'object') continue;\n if (item.kind !== 'toolInvocationSerialized') continue;\n if (item.toolId !== 'runSubagent') continue;\n\n const sid = item.toolCallId;\n if (!sid || nameMap[sid]) continue;\n\n // Prefer agentName from toolSpecificData (e.g. \"FoundationAgent\")\n const agentName = item.toolSpecificData?.agentName;\n if (agentName) { nameMap[sid] = agentName; continue; }\n\n // Fallback: Use invocationMessage as agent display name\n const msgObj = item.invocationMessage;\n const msg = typeof msgObj === 'string' ? msgObj\n : (msgObj && typeof msgObj === 'object') ? (msgObj.value || '') : '';\n if (msg) { nameMap[sid] = msg; continue; }\n\n // Fallback: try agent file path in message\n let m = msg.match(/agents\\/([^/\\]]+?)\\.agent\\.md/);\n if (m) { nameMap[sid] = m[1]; continue; }\n\n // Try resultDetails\n const resultDetails = item.resultDetails;\n const rdList = Array.isArray(resultDetails) ? resultDetails : (resultDetails ? [resultDetails] : []);\n for (const rd of rdList) {\n if (typeof rd !== 'object') continue;\n const fp = rd.fsPath || rd.path || '';\n m = fp.match(/agents\\/([^/]+?)\\.agent\\.md/);\n if (m) { nameMap[sid] = m[1]; break; }\n }\n }\n return nameMap;\n }\n\n _extractUserText(message) {\n if (!message) return '';\n if (typeof message.text === 'string') return message.text;\n // parts[] may contain text fragments\n if (Array.isArray(message.parts)) {\n return message.parts\n .filter(p => p.kind === 'text')\n .map(p => p.text || '')\n .join('');\n }\n return '';\n }\n\n _normalizeTool(item) {\n if (!item.toolCallId) return null;\n\n // toolSpecificData may hold input/output depending on tool type\n const tsd = item.toolSpecificData || {};\n let input = tsd.input || tsd.parameters || tsd.request || {};\n let result = tsd.output || tsd.result || null;\n const isError = item.isConfirmed === false;\n\n // vscode tools don't serialize input/result into toolSpecificData.\n // Use invocationMessage as a human-readable description of what the tool did,\n // and generatedTitle / resultDetails as the result summary.\n if (!result && (item.generatedTitle || item.resultDetails)) {\n // resultDetails is an array of URIs (e.g. files found/read)\n if (item.resultDetails) {\n const rdList = Array.isArray(item.resultDetails) ? item.resultDetails : [item.resultDetails];\n const paths = rdList.map(rd => rd.fsPath || rd.path || rd.external || JSON.stringify(rd)).filter(Boolean);\n result = paths.length > 0 ? paths.join('\\n') : item.generatedTitle || null;\n } else {\n result = item.generatedTitle || null;\n }\n }\n // Use invocationMessage (plain text) as input description if input is empty\n if (Object.keys(input).length === 0 && item.invocationMessage) {\n const msg = item.invocationMessage;\n const msgText = typeof msg === 'string' ? msg\n : (msg && typeof msg === 'object') ? (msg.value || '') : '';\n if (msgText) input = { description: msgText };\n }\n\n // Simplify URI objects: replace {$mid, fsPath, external, path, scheme} with just the filename\n const simplifyUri = (uri) => {\n if (!uri || typeof uri !== 'object') return uri;\n const p = uri.fsPath || uri.path || uri.external || '';\n return p ? p.replace(/.*\\//, '') : JSON.stringify(uri);\n };\n const simplifyInput = (obj) => {\n if (!obj || typeof obj !== 'object') return obj;\n const out = {};\n for (const [k, v] of Object.entries(obj)) {\n if (k === '$mid' || k === 'external' || k === 'scheme') continue; // skip internal URI fields\n if (k === 'fsPath' || k === 'path') { out['file'] = v.replace(/.*\\//, ''); continue; }\n if (v && typeof v === 'object' && ('fsPath' in v || '$mid' in v)) {\n out[k] = simplifyUri(v);\n } else if (Array.isArray(v) && k === 'edits') {\n out['edits'] = `${v.length} edit(s)`;\n } else {\n out[k] = v;\n }\n }\n return out;\n };\n if (input && typeof input === 'object' && !input.description) {\n input = simplifyInput(input);\n }\n\n return {\n type: 'tool_use',\n id: item.toolCallId,\n name: item.toolId || 'unknown',\n startTime: null,\n endTime: null,\n status: isError ? 'error' : (item.isComplete ? 'completed' : 'pending'),\n input,\n result: typeof result === 'string' ? result : JSON.stringify(result),\n error: isError ? (item.resultDetails || 'Tool invocation not confirmed') : null,\n };\n }\n\n _extractTurns(events) {\n const turns = [];\n let current = null;\n\n for (const event of events) {\n if (event.type === 'user.message') {\n if (current) turns.push(current);\n current = { userMessage: event, assistantMessages: [], toolCalls: [] };\n } else if (current) {\n if (event.type === 'assistant.message') {\n current.assistantMessages.push(event);\n } else if (event.type === 'tool.invocation') {\n current.toolCalls.push(event.data?.tool);\n }\n }\n }\n if (current) turns.push(current);\n return turns;\n }\n\n _extractToolCalls(events) {\n return events\n .filter(e => e.type === 'tool.invocation' && e.data?.tool)\n .map(e => e.data.tool);\n }\n}\n\nmodule.exports = VsCodeParser;\n", "const CopilotSessionParser = require('./copilot-parser');\nconst ClaudeSessionParser = require('./claude-parser');\nconst PiMonoParser = require('./pi-mono-parser');\n\n/**\n * Parser Factory\n * \n * Automatically detects the session format and returns the appropriate parser\n */\nclass ParserFactory {\n constructor() {\n this.parsers = [\n new CopilotSessionParser(),\n new ClaudeSessionParser(),\n new PiMonoParser()\n ];\n \n // Name-to-parser mapping\n this.parserMap = {\n 'copilot': new CopilotSessionParser(),\n 'claude': new ClaudeSessionParser(),\n 'pi-mono': new PiMonoParser()\n };\n }\n\n /**\n * Get parser by name or auto-detect from events\n * @param {string|Array<Object>} nameOrEvents - Parser name or events array\n * @returns {BaseSessionParser|null}\n */\n getParser(nameOrEvents) {\n // If it's a string, get parser by name\n if (typeof nameOrEvents === 'string') {\n return this.parserMap[nameOrEvents] || null;\n }\n \n // Otherwise, auto-detect from events\n const events = nameOrEvents;\n for (const parser of this.parsers) {\n if (parser.canParse(events)) {\n return parser;\n }\n }\n return null;\n }\n\n /**\n * Parse events using the appropriate parser\n * @param {Array<Object>} events - Raw events from jsonl\n * @returns {Object|null} Parsed session data or null if no parser found\n */\n parse(events) {\n const parser = this.getParser(events);\n if (!parser) {\n return null;\n }\n return parser.parse(events);\n }\n\n /**\n * Get parser type name\n * @param {Array<Object>} events - Raw events from jsonl\n * @returns {string|null} Parser name ('copilot', 'claude', 'pi-mono') or null\n */\n getParserType(events) {\n const parser = this.getParser(events);\n if (!parser) return null;\n \n if (parser instanceof CopilotSessionParser) return 'copilot';\n if (parser instanceof ClaudeSessionParser) return 'claude';\n if (parser instanceof PiMonoParser) return 'pi-mono';\n \n return 'unknown';\n }\n}\n\nmodule.exports = ParserFactory;\n", "const BaseSessionParser = require('./base-parser');\nconst CopilotSessionParser = require('./copilot-parser');\nconst ClaudeSessionParser = require('./claude-parser');\nconst PiMonoParser = require('./pi-mono-parser');\nconst VsCodeParser = require('./vscode-parser');\nconst ParserFactory = require('./parser-factory');\n\nmodule.exports = {\n BaseSessionParser,\n CopilotSessionParser,\n ClaudeSessionParser,\n PiMonoParser,\n VsCodeParser,\n ParserFactory\n};\n", "const path = require('path');\nconst os = require('os');\nconst fsSync = require('fs');\nconst fs = fsSync.promises;\nconst readline = require('readline');\nconst BaseSourceAdapter = require('./BaseSourceAdapter');\nconst Session = require('../models/Session');\nconst { countLines, shouldSkipEntry } = require('../utils/fileUtils');\nconst { ParserFactory } = require('../../../lib/parsers');\n\n/**\n * Claude Code Source Adapter\n *\n * Handles sessions stored in ~/.claude/projects/\n * Each project directory contains .jsonl session files and optional\n * subagents-only session directories.\n */\nclass ClaudeAdapter extends BaseSourceAdapter {\n constructor() {\n super();\n this.parserFactory = new ParserFactory();\n }\n\n get type() { return 'claude'; }\n get displayName() { return 'Claude'; }\n get envVar() { return 'CLAUDE_SESSION_DIR'; }\n\n getDefaultDir() {\n return path.join(os.homedir(), '.claude', 'projects');\n }\n\n async scanEntries(dir) {\n // Top-level entries are project directories\n const entries = await fs.readdir(dir);\n const tasks = entries\n .filter(entry => !shouldSkipEntry(entry))\n .map(async (entry) => {\n const fullPath = path.join(dir, entry);\n const stats = await fs.stat(fullPath);\n if (stats.isDirectory()) {\n return this._scanProjectDir(fullPath, entry);\n }\n return null;\n });\n\n const results = await Promise.allSettled(tasks);\n return results\n .filter(r => r.status === 'fulfilled' && r.value !== null && r.value !== undefined)\n .map(r => r.value)\n .flat();\n }\n\n async findById(sessionId, dir) {\n try {\n const projects = await fs.readdir(dir);\n\n for (const project of projects) {\n const projectPath = path.join(dir, project);\n\n // Try main session file first\n const sessionFile = path.join(projectPath, `${sessionId}.jsonl`);\n try {\n const stats = await fs.stat(sessionFile);\n if (stats.isFile()) {\n const session = await this._createClaudeSession(`${sessionId}.jsonl`, sessionFile, stats, project);\n if (session) return session;\n }\n } catch {\n // File not found\n }\n\n // Try session directory (subagents-only sessions)\n const sessionDir = path.join(projectPath, sessionId);\n try {\n const dirStats = await fs.stat(sessionDir);\n if (dirStats.isDirectory()) {\n const subagentsDir = path.join(sessionDir, 'subagents');\n try {\n const subStats = await fs.stat(subagentsDir);\n if (subStats.isDirectory()) {\n return await this._createSubagentsSession(sessionId, sessionDir, dirStats, project);\n }\n } catch {\n // No subagents directory\n }\n }\n } catch {\n // Directory not found\n }\n }\n } catch {\n // Projects dir not found\n }\n\n return null;\n }\n\n async resolveEventsFile(session, dir) {\n if (session.type === 'directory') return null; // Subagents only\n \n try {\n const projects = await fs.readdir(dir);\n for (const project of projects) {\n const candidateFile = path.join(dir, project, `${session.id}.jsonl`);\n try {\n await fs.access(candidateFile);\n return candidateFile;\n } catch {\n // Not here\n }\n }\n } catch (err) {\n console.error('Error searching Claude projects:', err);\n }\n return null;\n }\n\n async readEvents(session, dir) {\n const eventsFile = await this.resolveEventsFile(session, dir);\n return this.readJsonlEvents(eventsFile);\n }\n\n async _scanProjectDir(projectDir, projectName) {\n try {\n const entries = await fs.readdir(projectDir);\n const sessions = [];\n\n for (const entry of entries) {\n if (shouldSkipEntry(entry)) continue;\n\n const fullPath = path.join(projectDir, entry);\n const stats = await fs.stat(fullPath);\n\n if (stats.isFile() && entry.endsWith('.jsonl')) {\n const session = await this._createClaudeSession(entry, fullPath, stats, projectName);\n if (session) sessions.push(session);\n }\n\n if (stats.isDirectory()) {\n const subagentsDir = path.join(fullPath, 'subagents');\n try {\n const subStats = await fs.stat(subagentsDir);\n if (subStats.isDirectory()) {\n const session = await this._createSubagentsSession(entry, fullPath, stats, projectName);\n if (session) sessions.push(session);\n }\n } catch {\n // No subagents directory\n }\n }\n }\n\n return sessions;\n } catch (err) {\n console.error(`Error scanning Claude project dir ${projectDir}:`, err.message);\n return [];\n }\n }\n\n async _createClaudeSession(entry, fullPath, stats, projectName) {\n const sessionId = entry.replace('.jsonl', '');\n const eventCount = await countLines(fullPath);\n\n try {\n // Stream first ~50 lines instead of loading entire file\n const stream = fsSync.createReadStream(fullPath, { encoding: 'utf-8' });\n const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });\n const events = [];\n const MAX_LINES = 50;\n let scanned = 0;\n try {\n for await (const line of rl) {\n if (!line.trim()) continue;\n scanned++;\n try {\n events.push(JSON.parse(line));\n } catch {\n // skip\n }\n if (scanned >= MAX_LINES) break;\n }\n } finally {\n rl.close();\n stream.destroy();\n }\n\n // VALIDATION: Check for Claude core events\n const hasClaudeCoreEvents = events.some(e => e.type === 'assistant' || e.type === 'user');\n const hasCopilotCoreEvents = events.some(e => e.type === 'assistant.message' || e.type === 'user.message');\n\n if (!hasClaudeCoreEvents && hasCopilotCoreEvents) {\n return null;\n }\n if (!hasClaudeCoreEvents) {\n return null;\n }\n\n const parserType = this.parserFactory.getParserType(events);\n if (parserType !== 'claude') return null;\n\n const parsed = this.parserFactory.parse(events);\n const metadata = parsed.metadata || {};\n const projectPath = projectName.replace(/^-/, '/').replace(/-/g, '/');\n\n return new Session(sessionId, 'file', {\n source: 'claude',\n filePath: fullPath,\n directory: path.dirname(fullPath),\n workspace: {\n summary: metadata.model ? `Claude Code session (${metadata.model})` : 'Claude Code session',\n cwd: metadata.cwd || projectPath\n },\n createdAt: metadata.startTime || stats.birthtime,\n updatedAt: stats.mtime,\n summary: parsed.turns[0]?.userMessage?.content?.substring(0, 100) || 'No summary',\n hasEvents: eventCount > 0,\n eventCount: eventCount,\n duration: null,\n isImported: false,\n hasInsight: false,\n copilotVersion: metadata.version,\n selectedModel: metadata.model,\n sessionStatus: 'completed'\n });\n } catch (err) {\n console.error(`Error creating Claude session ${sessionId}:`, err.message);\n return null;\n }\n }\n\n async _createSubagentsSession(sessionId, sessionDir, stats, projectName) {\n try {\n const subagentsDir = path.join(sessionDir, 'subagents');\n const files = await fs.readdir(subagentsDir);\n const subagentFiles = files.filter(f => f.startsWith('agent-') && f.endsWith('.jsonl'));\n\n if (subagentFiles.length === 0) return null;\n\n let totalEvents = 0;\n for (const file of subagentFiles) {\n const filePath = path.join(subagentsDir, file);\n totalEvents += await countLines(filePath);\n }\n\n const firstFile = path.join(subagentsDir, subagentFiles[0]);\n const content = await fs.readFile(firstFile, 'utf-8');\n const lines = content.trim().split('\\n').filter(line => line.trim());\n const firstEvent = lines.length > 0 ? JSON.parse(lines[0]) : null;\n\n const metadata = {\n cwd: firstEvent?.cwd || projectName,\n version: firstEvent?.version,\n model: firstEvent?.message?.model,\n startTime: firstEvent?.timestamp\n };\n\n const projectPath = projectName.replace(/^-/, '/').replace(/-/g, '/');\n\n return new Session(sessionId, 'directory', {\n source: 'claude',\n directory: sessionDir,\n workspace: {\n summary: `Claude session (${subagentFiles.length} sub-agents)`,\n cwd: metadata.cwd || projectPath\n },\n createdAt: metadata.startTime || stats.birthtime,\n updatedAt: stats.mtime,\n summary: firstEvent?.message?.content?.substring(0, 100) || 'Sub-agent tasks',\n hasEvents: totalEvents > 0,\n eventCount: totalEvents,\n duration: null,\n isImported: false,\n hasInsight: false,\n copilotVersion: metadata.version,\n selectedModel: metadata.model,\n sessionStatus: 'completed'\n });\n } catch (err) {\n console.error(`Error creating Claude subagents session ${sessionId}:`, err.message);\n return null;\n }\n }\n\n async detectImportCandidate(extractDir) {\n const entries = await fs.readdir(extractDir);\n for (const entry of entries) {\n if (!entry.endsWith('.jsonl')) continue;\n const entryPath = path.join(extractDir, entry);\n const stat = await fs.stat(entryPath);\n if (!stat.isFile()) continue;\n const sessionId = entry.replace(/\\.jsonl$/, '');\n // Read first line to check for Claude signatures\n const firstLine = (await fs.readFile(entryPath, 'utf-8')).split('\\n').find(l => l.trim());\n let parsed; try { parsed = firstLine ? JSON.parse(firstLine) : null; } catch { parsed = null; }\n if (parsed && (parsed.type === 'user' || parsed.type === 'assistant' || parsed.parentUuid || parsed.uuid)) {\n const hasDir = fsSync.existsSync(path.join(extractDir, sessionId));\n return {\n matched: true, score: hasDir ? 95 : 90,\n reason: hasDir ? 'Claude JSONL + companion dir' : 'Claude JSONL file',\n sessionId, fileName: entry, hasDirectory: hasDir, directoryName: hasDir ? sessionId : undefined\n };\n }\n }\n return { matched: false, score: 0, reason: 'No Claude session JSONL signature found' };\n }\n\n async importDetectedSession(det, ctx) {\n const { isValidSessionId } = require('../utils/helpers');\n const { sessionId, fileName, hasDirectory, directoryName } = det;\n if (!isValidSessionId(sessionId)) return { success: false, error: 'Invalid session ID', statusCode: 400 };\n const project = ctx.req.query.project || 'imported-sessions';\n const baseDir = ctx.targetDir || await this.resolveDir();\n const projectPath = path.join(baseDir, project);\n await fs.mkdir(projectPath, { recursive: true });\n await fs.rename(path.join(ctx.extractDir, fileName), path.join(projectPath, fileName));\n if (hasDirectory && directoryName) {\n await fs.rename(path.join(ctx.extractDir, directoryName), path.join(projectPath, directoryName));\n }\n return { success: true, sessionId, format: this.type, project };\n }\n}\n\nmodule.exports = ClaudeAdapter;\n\n", "const path = require('path');\nconst os = require('os');\nconst fsSync = require('fs');\nconst fs = fsSync.promises;\nconst BaseSourceAdapter = require('./BaseSourceAdapter');\nconst Session = require('../models/Session');\nconst { countLines, shouldSkipEntry } = require('../utils/fileUtils');\nconst { readFirstLine } = require('./adapterUtils');\n\n/**\n * Pi-Mono Source Adapter\n *\n * Handles sessions stored in ~/.pi/agent/sessions/\n * Each project directory contains timestamped .jsonl files:\n * YYYY-MM-DDTHH-mm-ss-SSSZ_<uuid>.jsonl\n */\nclass PiMonoAdapter extends BaseSourceAdapter {\n get type() { return 'pi-mono'; }\n get displayName() { return 'Pi'; }\n get envVar() { return 'PI_MONO_SESSION_DIR'; }\n\n getDefaultDir() {\n return path.join(os.homedir(), '.pi', 'agent', 'sessions');\n }\n\n async scanEntries(dir) {\n const entries = await fs.readdir(dir);\n const tasks = entries\n .filter(entry => !shouldSkipEntry(entry))\n .map(async (entry) => {\n const fullPath = path.join(dir, entry);\n const stats = await fs.stat(fullPath);\n if (stats.isDirectory()) {\n return this._scanProjectDir(fullPath, entry);\n }\n return null;\n });\n\n const results = await Promise.allSettled(tasks);\n return results\n .filter(r => r.status === 'fulfilled' && r.value !== null && r.value !== undefined)\n .map(r => r.value)\n .flat();\n }\n\n async findById(sessionId, dir) {\n try {\n const projects = await fs.readdir(dir);\n\n for (const project of projects) {\n const projectPath = path.join(dir, project);\n try {\n const files = await fs.readdir(projectPath);\n const matchingFile = files.find(f => f.endsWith(`_${sessionId}.jsonl`));\n if (matchingFile) {\n const fullPath = path.join(projectPath, matchingFile);\n const stats = await fs.stat(fullPath);\n return await this._createSession(matchingFile, fullPath, stats, project);\n }\n } catch {\n // Not a directory or can't read\n }\n }\n } catch (err) {\n console.error('Error searching Pi-Mono sessions:', err);\n }\n\n return null;\n }\n\n async _createSession(file, fullPath, stats, projectName) {\n const match = file.match(/_([a-f0-9-]+)\\.jsonl$/);\n if (!match) return null;\n\n const sessionId = match[1];\n const firstLine = await readFirstLine(fullPath);\n if (!firstLine) return null;\n\n try {\n const sessionEvent = JSON.parse(firstLine);\n if (sessionEvent.type !== 'session') return null;\n\n const eventCount = await countLines(fullPath);\n const mappedProjectPath = projectName.replace(/^--/, '').replace(/--$/, '');\n\n return new Session(sessionId, 'directory', {\n source: 'pi-mono',\n directory: path.dirname(fullPath),\n workspace: { cwd: sessionEvent.cwd || mappedProjectPath },\n createdAt: new Date(sessionEvent.timestamp),\n updatedAt: new Date(stats.mtime),\n summary: `Pi-Mono: ${path.basename(sessionEvent.cwd || mappedProjectPath)}`,\n hasEvents: eventCount > 0,\n eventCount: eventCount,\n duration: null,\n sessionStatus: 'completed'\n });\n } catch (err) {\n console.error(`[PI-MONO] Error parsing session ${file}:`, err.message);\n return null;\n }\n }\n\n async resolveEventsFile(session, dir) {\n try {\n const projects = await fs.readdir(dir);\n for (const project of projects) {\n const projectPath = path.join(dir, project);\n try {\n const files = await fs.readdir(projectPath);\n const matchingFile = files.find(f => f.endsWith(`_${session.id}.jsonl`));\n if (matchingFile) {\n return path.join(projectPath, matchingFile);\n }\n } catch {\n // Not a directory or can't read\n }\n }\n } catch (err) {\n console.error('Error searching Pi-Mono sessions:', err);\n }\n return null;\n }\n\n async readEvents(session, dir) {\n const eventsFile = await this.resolveEventsFile(session, dir);\n return this.readJsonlEvents(eventsFile);\n }\n\n async _scanProjectDir(projectPath, projectName) {\n try {\n const entries = await fs.readdir(projectPath);\n const jsonlFiles = entries.filter(e => e.endsWith('.jsonl'));\n\n if (jsonlFiles.length === 0) return [];\n\n const sessions = [];\n jsonlFiles.sort().reverse();\n\n for (const file of jsonlFiles) {\n const fullPath = path.join(projectPath, file);\n const stats = await fs.stat(fullPath);\n\n const match = file.match(/_([a-f0-9-]+)\\.jsonl$/);\n if (!match) continue;\n\n const sessionId = match[1];\n\n const firstLine = await readFirstLine(fullPath);\n if (!firstLine) continue;\n\n try {\n const sessionEvent = JSON.parse(firstLine);\n if (sessionEvent.type !== 'session') continue;\n\n const eventCount = await countLines(fullPath);\n const mappedProjectPath = projectName.replace(/^--/, '').replace(/--$/, '');\n\n const session = new Session(sessionId, 'directory', {\n source: 'pi-mono',\n directory: projectPath,\n workspace: { cwd: sessionEvent.cwd || mappedProjectPath },\n createdAt: new Date(sessionEvent.timestamp),\n updatedAt: new Date(stats.mtime),\n summary: `Pi-Mono: ${path.basename(sessionEvent.cwd || mappedProjectPath)}`,\n hasEvents: eventCount > 0,\n eventCount: eventCount,\n duration: null,\n sessionStatus: 'completed'\n });\n\n sessions.push(session);\n } catch (err) {\n console.error(`[PI-MONO] Error parsing session ${file}:`, err.message);\n }\n }\n\n return sessions;\n } catch (err) {\n console.error(`[PI-MONO] Error scanning dir ${projectPath}:`, err.message);\n return [];\n }\n }\n\n async detectImportCandidate(extractDir) {\n const piPattern = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}-\\d{3}Z_([a-zA-Z0-9_-]+)\\.jsonl$/;\n const entries = await fs.readdir(extractDir);\n for (const entry of entries) {\n const m = entry.match(piPattern);\n if (!m) continue;\n const firstLine = await readFirstLine(path.join(extractDir, entry));\n let parsed; try { parsed = firstLine ? JSON.parse(firstLine) : null; } catch { parsed = null; }\n if (parsed?.type === 'session') {\n return { matched: true, score: 100, reason: 'Pi-Mono timestamped JSONL', sessionId: m[1], fileName: entry };\n }\n }\n return { matched: false, score: 0, reason: 'No Pi-Mono timestamped session JSONL found' };\n }\n\n async importDetectedSession(det, ctx) {\n const { isValidSessionId } = require('../utils/helpers');\n const { sessionId, fileName } = det;\n if (!isValidSessionId(sessionId)) return { success: false, error: 'Invalid session ID', statusCode: 400 };\n const project = ctx.req.query.project || 'imported-sessions';\n const baseDir = ctx.targetDir || await this.resolveDir();\n const projectPath = path.join(baseDir, project);\n await fs.mkdir(projectPath, { recursive: true });\n await fs.rename(path.join(ctx.extractDir, fileName), path.join(projectPath, fileName));\n return { success: true, sessionId, format: this.type, project };\n }\n}\n\nmodule.exports = PiMonoAdapter;\n\n", "const path = require('path');\nconst os = require('os');\nconst fs = require('fs').promises;\nconst { fileURLToPath } = require('url');\nconst BaseSourceAdapter = require('./BaseSourceAdapter');\nconst Session = require('../models/Session');\nconst { shouldSkipEntry, getSessionMetadataOptimized } = require('../utils/fileUtils');\nconst { computeSessionStatus } = require('./adapterUtils');\n\n/**\n * Return candidate VS Code workspace storage paths in preference order.\n * Returns [stable, insiders] \u2014 stable is always tried first.\n */\nfunction getVSCodeWorkspaceStorageCandidates() {\n let base;\n switch (os.platform()) {\n case 'win32':\n base = path.join(process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming'));\n break;\n case 'darwin':\n base = path.join(os.homedir(), 'Library', 'Application Support');\n break;\n case 'linux':\n base = path.join(os.homedir(), '.config');\n break;\n default:\n base = path.join(os.homedir(), '.config');\n }\n return [\n path.join(base, 'Code', 'User', 'workspaceStorage'),\n path.join(base, 'Code - Insiders', 'User', 'workspaceStorage'),\n ];\n}\n\n/**\n * VSCode Copilot Chat Source Adapter\n *\n * Reads copilot-agent transcript sessions from VS Code workspaceStorage.\n * Only reads GitHub.copilot-chat/transcripts/*.jsonl (same format as copilot-cli).\n */\nclass VsCodeAdapter extends BaseSourceAdapter {\n constructor() {\n super();\n this._candidates = null;\n }\n\n get type() { return 'vscode'; }\n get displayName() { return 'Copilot Chat'; }\n get envVar() { return 'VSCODE_WORKSPACE_STORAGE_DIR'; }\n get hasCustomPipeline() { return true; }\n\n getDefaultDir() {\n const candidates = this._getCandidates();\n return candidates[0];\n }\n\n _getCandidates() {\n if (!this._candidates) {\n this._candidates = getVSCodeWorkspaceStorageCandidates();\n }\n return this._candidates;\n }\n\n /**\n * Override resolveDir to try stable then Insiders.\n */\n async resolveDir() {\n if (this.envVar && process.env[this.envVar]) {\n return process.env[this.envVar];\n }\n const candidates = this._getCandidates();\n for (const candidate of candidates) {\n try {\n await fs.access(candidate);\n return candidate;\n } catch { /* try next */ }\n }\n return null;\n }\n\n async scanEntries(dir) {\n const entries = await fs.readdir(dir);\n const tasks = entries\n .filter(entry => !shouldSkipEntry(entry))\n .map(async (entry) => {\n const fullPath = path.join(dir, entry);\n const stats = await fs.stat(fullPath);\n if (stats.isDirectory()) {\n return this._scanWorkspaceDir(fullPath);\n }\n return null;\n });\n\n const results = await Promise.allSettled(tasks);\n return results\n .filter(r => r.status === 'fulfilled' && r.value !== null && r.value !== undefined)\n .map(r => r.value)\n .flat();\n }\n\n async findById(sessionId, dir) {\n try {\n const hashes = await fs.readdir(dir);\n const candidates = [];\n\n for (const hash of hashes) {\n const transcriptsDir = path.join(dir, hash, 'GitHub.copilot-chat', 'transcripts');\n try {\n const files = await fs.readdir(transcriptsDir);\n const matchingFile = files.find(f => f === `${sessionId}.jsonl` || f.replace(/\\.jsonl$/, '') === sessionId);\n if (matchingFile) {\n const fullPath = path.join(transcriptsDir, matchingFile);\n const stats = await fs.stat(fullPath);\n const realWorkspacePath = await this._resolveWorkspacePath(path.join(dir, hash));\n const session = await this._buildTranscriptSession(\n matchingFile, fullPath, stats, hash, realWorkspacePath\n );\n if (session) candidates.push(session);\n }\n } catch {\n // No transcripts dir\n }\n }\n if (candidates.length > 0) {\n candidates.sort((a, b) => (b.updatedAt?.getTime?.() ?? 0) - (a.updatedAt?.getTime?.() ?? 0));\n return candidates[0];\n }\n } catch (err) {\n console.error(`[VSCode findById] Error searching VSCode sessions: ${err.message}`);\n }\n return null;\n }\n\n async readEvents(session, _dir) {\n if (!session?.filePath) {\n return [];\n }\n\n try {\n const events = await this.readJsonlEvents(session.filePath);\n\n // Inject synthetic user.message at the start if chatSessions has user prompt\n // and the transcript doesn't start with one\n if (session._chatSessionInfo?.userMessage && events.length > 0) {\n const hasUserMsgAtStart = events.some((e, i) =>\n i < 3 && (e.type === 'user.message' || e.type === 'user' || e.type === 'request')\n );\n if (!hasUserMsgAtStart) {\n const sessionStart = events.find(e => e.type === 'session.start');\n const startTs = sessionStart?.timestamp || events[0]?.timestamp;\n events.splice(sessionStart ? 1 : 0, 0, {\n type: 'user.message',\n id: 'synthetic-user-msg-0',\n timestamp: startTs,\n data: {\n content: session._chatSessionInfo.userMessage,\n message: session._chatSessionInfo.userMessage,\n _synthetic: true\n },\n _synthetic: true\n });\n }\n }\n\n return events;\n } catch (err) {\n console.error(`[VSCode readEvents] Error reading session ${session.id}:`, err);\n return [];\n }\n }\n\n buildTimeline(_events, _session) {\n // All sessions are transcripts now \u2014 fall through to _buildCopilotTimeline via source dispatch\n return null;\n }\n\n // --- Private helpers ---\n\n async _scanWorkspaceDir(workspaceHashDir) {\n const workspaceHash = path.basename(workspaceHashDir);\n const realWorkspacePath = await this._resolveWorkspacePath(workspaceHashDir);\n const sessions = [];\n\n const transcriptsDir = path.join(workspaceHashDir, 'GitHub.copilot-chat', 'transcripts');\n try {\n await fs.access(transcriptsDir);\n const entries = await fs.readdir(transcriptsDir);\n const jsonlFiles = entries.filter(e => e.endsWith('.jsonl') && !shouldSkipEntry(e));\n for (const file of jsonlFiles) {\n const fullPath = path.join(transcriptsDir, file);\n try {\n const stats = await fs.stat(fullPath);\n const session = await this._buildTranscriptSession(\n file, fullPath, stats, workspaceHash, realWorkspacePath\n );\n if (session) sessions.push(session);\n } catch (err) {\n console.warn(`[VSCode scan] Skipping transcript ${fullPath}: ${err.message}`);\n }\n }\n } catch { /* no transcripts dir */ }\n\n return sessions;\n }\n\n async _resolveWorkspacePath(workspaceHashDir) {\n try {\n const workspaceJsonPath = path.join(workspaceHashDir, 'workspace.json');\n const raw = await fs.readFile(workspaceJsonPath, 'utf-8');\n const meta = JSON.parse(raw);\n\n if (meta.folder) {\n return fileURLToPath(meta.folder);\n }\n\n if (meta.workspace) {\n const wsFilePath = fileURLToPath(meta.workspace);\n try {\n const wsRaw = await fs.readFile(wsFilePath, 'utf-8');\n const ws = JSON.parse(wsRaw);\n if (Array.isArray(ws.folders) && ws.folders.length > 0) {\n const wsDir = path.dirname(wsFilePath);\n return path.resolve(wsDir, ws.folders[0].path);\n }\n } catch {\n // Can't read the workspace file (e.g. running on a different machine).\n // Return null rather than a misleading internal VSCode path.\n }\n }\n } catch {\n // No workspace.json or unreadable\n }\n return null;\n }\n\n /**\n * Build a Session from a copilot-agent transcript file.\n * Reuses the same metadata extraction as CopilotAdapter.\n */\n async _buildTranscriptSession(file, fullPath, stats, workspaceHash, workspaceCwd) {\n const sessionId = file.replace('.jsonl', '');\n const optimizedMetadata = await getSessionMetadataOptimized(fullPath);\n const sessionStatus = computeSessionStatus(optimizedMetadata);\n\n // Try to extract agent info from chatSessions file\n const chatSessionInfo = await this._extractChatSessionInfo(fullPath, sessionId);\n\n const createdAt = optimizedMetadata.startTime\n ? new Date(optimizedMetadata.startTime)\n : stats.birthtime;\n const updatedAt = optimizedMetadata.lastEventTime\n ? new Date(optimizedMetadata.lastEventTime)\n : stats.mtime;\n\n // Prefer chatSession user message over transcript firstUserMessage\n const firstUserMessage = chatSessionInfo.userMessage || optimizedMetadata.firstUserMessage;\n\n const session = new Session(sessionId, 'file', {\n source: 'vscode',\n filePath: fullPath,\n directory: path.dirname(fullPath),\n createdAt,\n updatedAt,\n summary: firstUserMessage\n ? firstUserMessage.slice(0, 120)\n : 'Copilot agent session',\n hasEvents: true,\n eventCount: optimizedMetadata.eventCount || 0,\n duration: optimizedMetadata.duration,\n sessionStatus,\n selectedModel: chatSessionInfo.modelId || optimizedMetadata.selectedModel || null,\n copilotVersion: optimizedMetadata.copilotVersion || null,\n workspace: workspaceCwd ? { cwd: workspaceCwd, workspaceHash } : { workspaceHash },\n agentName: chatSessionInfo.agentName || null,\n });\n session._isTranscript = true;\n session._chatSessionInfo = chatSessionInfo;\n return session;\n }\n\n /**\n * Extract agent name, model, and user message from the chatSessions JSONL.\n * Path: <hash>/chatSessions/<sessionId>.jsonl (sibling of transcripts dir).\n */\n async _extractChatSessionInfo(transcriptPath, sessionId) {\n const result = { agentName: null, modelId: null, userMessage: null };\n try {\n // Navigate from transcripts dir to chatSessions dir\n const hashDir = path.resolve(path.dirname(transcriptPath), '..', '..');\n const chatSessionPath = path.join(hashDir, 'chatSessions', `${sessionId}.jsonl`);\n await fs.access(chatSessionPath);\n\n const raw = await fs.readFile(chatSessionPath, 'utf-8');\n const lines = raw.trim().split('\\n');\n\n for (const line of lines) {\n const entry = JSON.parse(line);\n\n // kind=0: initial state with requests array\n if (entry.kind === 0 && entry.v?.requests?.[0]) {\n const req = entry.v.requests[0];\n // User message\n if (req.message?.text) {\n result.userMessage = req.message.text;\n }\n // Model\n if (req.modelId) {\n result.modelId = req.modelId;\n }\n // Agent (built-in agent mode)\n if (req.agent?.id && req.agent.id !== 'github.copilot.editsAgent') {\n result.agentName = req.agent.id;\n }\n }\n\n // kind=1: diff entries \u2014 look for agent mode with file-based agent\n if (entry.kind === 1) {\n const keys = entry.k || [];\n const val = entry.v;\n if (keys.includes('mode') && val?.kind === 'agent' && val?.id) {\n const agentId = val.id;\n // Extract agent name from file path: .../agents/name.agent.md \u2192 name\n const fileMatch = agentId.match(/agents\\/([^/]+)\\.agent\\.md$/);\n if (fileMatch) {\n result.agentName = fileMatch[1];\n }\n }\n }\n }\n } catch {\n // chatSessions file not found or unreadable \u2014 not critical\n }\n return result;\n }\n}\n\nmodule.exports = VsCodeAdapter;\n", "const path = require('path');\nconst os = require('os');\nconst fs = require('fs').promises;\nconst CopilotAdapter = require('./CopilotAdapter');\n\n/**\n * Modernize CLI Source Adapter\n *\n * Handles sessions stored in ~/.modernize/configuration/<version>+<hash>/session-state/\n * where each <version>+<hash> directory represents a different Modernize CLI version.\n * Sessions may exist across multiple version directories.\n *\n * Log format is identical to Copilot CLI, so this adapter extends CopilotAdapter\n * and only overrides identity, directory resolution, and scanning logic.\n */\nclass ModernizeAdapter extends CopilotAdapter {\n get type() { return 'modernize'; }\n get displayName() { return 'Modernize CLI'; }\n get envVar() { return 'MODERNIZE_SESSION_DIR'; }\n\n getDefaultDir() {\n return path.join(os.homedir(), '.modernize', 'configuration');\n }\n\n /**\n * Resolve the base configuration directory.\n * Returns the env var override (pointing directly to a session-state dir)\n * or the default configuration directory (parent of all version dirs).\n */\n async resolveDir() {\n if (this.envVar && process.env[this.envVar]) {\n return process.env[this.envVar];\n }\n return this.getDefaultDir();\n }\n\n /**\n * Find all session-state directories across all version+hash subdirectories.\n * @param {string} configDir - The configuration directory\n * @returns {Promise<string[]>} Array of session-state directory paths\n */\n async _findSessionStateDirs(configDir) {\n const dirs = [];\n try {\n const entries = await fs.readdir(configDir);\n for (const entry of entries) {\n if (!entry.includes('+')) continue;\n const sessionStateDir = path.join(configDir, entry, 'session-state');\n try {\n const stats = await fs.stat(sessionStateDir);\n if (stats.isDirectory()) {\n dirs.push(sessionStateDir);\n }\n } catch {\n // No session-state in this version dir\n }\n }\n } catch {\n // Config dir doesn't exist or isn't readable\n }\n return dirs;\n }\n\n /**\n * Determine whether dir is an env-var override (direct session-state path)\n * or the default config dir containing version+hash subdirectories.\n */\n _isEnvVarOverride() {\n return !!(this.envVar && process.env[this.envVar]);\n }\n\n /**\n * Scan all version+hash/session-state directories for sessions.\n */\n async scanEntries(dir) {\n // When env var points directly to a session-state dir, scan it directly\n if (this._isEnvVarOverride()) {\n return this._scanAndTag(dir);\n }\n\n // Otherwise, scan all version subdirectories\n const sessionStateDirs = await this._findSessionStateDirs(dir);\n const allSessions = [];\n for (const ssDir of sessionStateDirs) {\n const sessions = await this._scanAndTag(ssDir);\n allSessions.push(...sessions);\n }\n return allSessions;\n }\n\n /**\n * Extract the Modernize CLI version from a session-state directory path.\n * Path pattern: <configDir>/<version>+<hash>/session-state\n * @param {string} sessionStateDir\n * @returns {string|null} e.g. \"0.0.226\"\n */\n _extractModernizeVersion(sessionStateDir) {\n // Parent of session-state is the version+hash directory\n const versionHashDir = path.basename(path.dirname(sessionStateDir));\n const plusIndex = versionHashDir.indexOf('+');\n if (plusIndex > 0) {\n return versionHashDir.substring(0, plusIndex);\n }\n return null;\n }\n\n /**\n * Scan a single session-state directory and tag results as modernize.\n */\n async _scanAndTag(sessionStateDir) {\n try {\n const modernizeVersion = this._extractModernizeVersion(sessionStateDir);\n const sessions = await super.scanEntries(sessionStateDir);\n for (const session of sessions) {\n session.source = 'modernize';\n session.modernizeVersion = modernizeVersion;\n }\n return sessions;\n } catch {\n return [];\n }\n }\n\n /**\n * Search all version directories for a session by ID.\n */\n async findById(sessionId, dir) {\n if (this._isEnvVarOverride()) {\n return this._findByIdInDir(sessionId, dir);\n }\n\n const sessionStateDirs = await this._findSessionStateDirs(dir);\n for (const ssDir of sessionStateDirs) {\n const session = await this._findByIdInDir(sessionId, ssDir);\n if (session) return session;\n }\n return null;\n }\n\n async _findByIdInDir(sessionId, sessionStateDir) {\n const session = await super.findById(sessionId, sessionStateDir);\n if (session) {\n session.source = 'modernize';\n session.modernizeVersion = this._extractModernizeVersion(sessionStateDir);\n }\n return session;\n }\n\n /**\n * Resolve events file across all version directories.\n */\n async resolveEventsFile(session, dir) {\n if (this._isEnvVarOverride()) {\n return super.resolveEventsFile(session, dir);\n }\n\n const sessionStateDirs = await this._findSessionStateDirs(dir);\n for (const ssDir of sessionStateDirs) {\n try {\n const eventsFile = await super.resolveEventsFile(session, ssDir);\n await fs.access(eventsFile);\n return eventsFile;\n } catch {\n // Not in this version dir\n }\n }\n return null;\n }\n\n /**\n * Read events, searching across all version directories.\n */\n async readEvents(session, dir) {\n const eventsFile = await this.resolveEventsFile(session, dir);\n return this.readJsonlEvents(eventsFile);\n }\n\n // Source tagging overrides \u2014 these are called by super.scanEntries()\n // which we already wrap in _scanAndTag, but keep them for direct calls\n async _createDirectorySession(entry, fullPath, stats) {\n const session = await super._createDirectorySession(entry, fullPath, stats);\n if (session) {\n session.source = 'modernize';\n }\n return session;\n }\n\n async _createFileSession(entry, fullPath, stats) {\n const session = await super._createFileSession(entry, fullPath, stats);\n if (session) {\n session.source = 'modernize';\n }\n return session;\n }\n\n // Modernize uses the same format as Copilot but shouldn't claim zip imports;\n // Copilot adapter handles the generic events.jsonl-directory format.\n async detectImportCandidate(_extractDir) {\n return { matched: false, score: 0, reason: 'Modernize does not support zip import (use Copilot)' };\n }\n}\n\nmodule.exports = ModernizeAdapter;\n", "/**\n * Source Adapter Registry \u2014 Central Registration Point\n *\n * To add a new source adapter:\n * 1. Create src/adapters/MyNewAdapter.js extending BaseSourceAdapter\n * 2. Import and register it below\n * That's it \u2014 no other files need to change.\n */\n\nconst AdapterRegistry = require('./AdapterRegistry');\nconst BaseSourceAdapter = require('./BaseSourceAdapter');\n\n// Concrete adapters\nconst CopilotAdapter = require('./CopilotAdapter');\nconst ClaudeAdapter = require('./ClaudeAdapter');\nconst PiMonoAdapter = require('./PiMonoAdapter');\nconst VsCodeAdapter = require('./VsCodeAdapter');\nconst ModernizeAdapter = require('./ModernizeAdapter');\n\n// Create singleton registry\nconst registry = new AdapterRegistry();\n\n// --- Register adapters here ---\nregistry.register(new CopilotAdapter());\nregistry.register(new ClaudeAdapter());\nregistry.register(new PiMonoAdapter());\nregistry.register(new VsCodeAdapter());\nregistry.register(new ModernizeAdapter());\n\nmodule.exports = {\n registry,\n AdapterRegistry,\n BaseSourceAdapter\n};\n", "const fs = require('fs').promises;\nconst { shouldSkipEntry } = require('../utils/fileUtils');\nconst { registry } = require('../adapters');\n\n/**\n * Session Repository - Data access layer for sessions\n *\n * Delegates all source-specific logic to Source Adapters registered\n * in the adapter registry. This class handles only cross-cutting\n * concerns: caching, deduplication, sorting, and orchestration.\n */\nclass SessionRepository {\n constructor(sessionDirs) {\n this.registry = registry;\n\n // Build the sources list from the adapter registry\n // Support both old (single dir) and new (multi-source) initialization\n if (typeof sessionDirs === 'string') {\n // Backward compatibility: single directory treated as copilot\n this.sources = [{\n type: 'copilot',\n dir: sessionDirs\n }];\n } else if (Array.isArray(sessionDirs)) {\n this.sources = sessionDirs;\n } else {\n // Default: build sources from all registered adapters\n this.sources = this.registry.all().map(adapter => ({\n type: adapter.type,\n dir: adapter.getDefaultDir()\n }));\n // Apply env var overrides\n for (const source of this.sources) {\n const adapter = this.registry.get(source.type);\n if (adapter && adapter.envVar && process.env[adapter.envVar]) {\n source.dir = process.env[adapter.envVar];\n }\n // Legacy SESSION_DIR fallback for copilot\n if (source.type === 'copilot' && process.env.SESSION_DIR && !process.env.COPILOT_SESSION_DIR) {\n source.dir = process.env.SESSION_DIR;\n }\n }\n }\n\n // Cache: keyed by sourceType (null = all sources)\n this._cache = new Map();\n this._cacheTTL = 60 * 1000; // 60 seconds\n this._pendingScans = new Map(); // dedup concurrent requests\n }\n\n /**\n * Invalidate cache (call after tag/insight changes if needed)\n */\n invalidateCache(sourceType = null) {\n if (sourceType) {\n this._cache.delete(sourceType);\n this._cache.delete(null); // also invalidate \"all\" cache\n } else {\n this._cache.clear();\n }\n }\n\n /**\n * Get all sessions from all sources (or a specific source)\n * @param {string|null} sourceType - Optional source type filter\n * @returns {Promise<import('../models/Session')[]>}\n */\n async findAll(sourceType = null) {\n const cacheKey = sourceType || '__all__';\n\n // Check cache\n const cached = this._cache.get(cacheKey);\n if (cached && (Date.now() - cached.timestamp < this._cacheTTL)) {\n return cached.data;\n }\n\n // Dedup concurrent scans for same key\n if (this._pendingScans.has(cacheKey)) {\n return this._pendingScans.get(cacheKey);\n }\n\n const scanPromise = this._doFindAll(sourceType).then(result => {\n this._cache.set(cacheKey, { data: result, timestamp: Date.now() });\n this._pendingScans.delete(cacheKey);\n return result;\n }).catch(err => {\n this._pendingScans.delete(cacheKey);\n throw err;\n });\n\n this._pendingScans.set(cacheKey, scanPromise);\n return scanPromise;\n }\n\n /**\n * @private\n */\n async _doFindAll(sourceType = null) {\n const allSessions = [];\n\n const sources = sourceType\n ? this.sources.filter(s => s.type === sourceType)\n : this.sources;\n\n for (const source of sources) {\n try {\n const sessions = await this.scanSource(source);\n allSessions.push(...sessions);\n } catch (err) {\n console.error(`Error reading ${source.type} sessions from ${source.dir}:`, err.message);\n }\n }\n\n return this._sortByUpdatedAt(this._deduplicateSessions(allSessions));\n }\n\n /**\n * Scan a single source via its adapter.\n * @private\n */\n async scanSource(source) {\n const adapter = this.registry.get(source.type);\n if (!adapter) {\n console.warn(`No adapter registered for source type: ${source.type}`);\n return [];\n }\n\n // Resolve directory \u2014 adapter handles candidates (e.g. VSCode stable/Insiders)\n let dir;\n if (source.dir) {\n dir = source.dir;\n } else {\n dir = await adapter.resolveDir();\n }\n\n if (!dir) {\n console.warn(`No directory resolved for ${source.type}`);\n return [];\n }\n\n try {\n await fs.access(dir);\n } catch {\n console.warn(`Source directory not found: ${dir}`);\n return [];\n }\n\n return adapter.scanEntries(dir);\n }\n\n /**\n * Deduplicate sessions with the same ID.\n * Keeps the most recently updated session for each ID.\n * @private\n */\n _deduplicateSessions(sessions) {\n const seen = new Map();\n for (const session of sessions) {\n const existing = seen.get(session.id);\n if (!existing || (session.updatedAt && existing.updatedAt && new Date(session.updatedAt) > new Date(existing.updatedAt))) {\n seen.set(session.id, session);\n }\n }\n return Array.from(seen.values());\n }\n\n /**\n * Find session by ID (searches all sources via adapters).\n * @param {string} sessionId - Session ID\n * @returns {Promise<import('../models/Session')|null>}\n */\n async findById(sessionId, customDir = null) {\n if (shouldSkipEntry(sessionId)) return null;\n\n // If a custom dir is specified, use the source type from the first source\n // and search directly in that dir\n if (customDir) {\n for (const source of this.sources) {\n const adapter = this.registry.get(source.type);\n if (!adapter) continue;\n try {\n await fs.access(customDir);\n } catch {\n continue;\n }\n const session = await adapter.findById(sessionId, customDir);\n if (session) return session;\n }\n return null;\n }\n\n for (const source of this.sources) {\n const adapter = this.registry.get(source.type);\n if (!adapter) continue;\n\n // Resolve directory\n let dir;\n if (source.dir) {\n dir = source.dir;\n } else {\n dir = await adapter.resolveDir();\n }\n if (!dir) continue;\n\n try {\n await fs.access(dir);\n } catch {\n console.warn(`Source directory not found: ${dir}`);\n continue;\n }\n\n const session = await adapter.findById(sessionId, dir);\n if (session) return session;\n }\n\n return null;\n }\n\n\n /**\n * Sort sessions by updated time (newest first)\n * @private\n */\n _sortByUpdatedAt(sessions) {\n return sessions.sort((a, b) => new Date(b.updatedAt) - new Date(a.updatedAt));\n }\n}\n\nmodule.exports = SessionRepository;\n", "/**\n * EventNormalizer - Unified Event Format Transformer\n *\n * Converts tool events from different AI session formats (Copilot, Claude, Pi-Mono)\n * into a single, consistent schema for frontend consumption.\n *\n * Key transformations:\n * - Normalizes tool call structure to UnifiedToolCall schema\n * - Computes consistent status fields ('pending' | 'running' | 'completed' | 'error')\n * - Adds timing metadata (startTime, endTime, duration)\n * - Handles edge cases (orphaned events, missing fields)\n *\n * Usage:\n * const normalizer = new EventNormalizer();\n * const normalizedEvents = normalizer.normalizeEvents(rawEvents, 'copilot');\n */\n\nclass EventNormalizer {\n /**\n * Normalize all events to unified format\n * @param {Array} events - Raw events from parsers (after matching)\n * @param {string} _source - 'copilot' | 'claude' | 'pi-mono'\n * @returns {Array} - Normalized events\n */\n normalizeEvents(events, _source) {\n if (!Array.isArray(events)) {\n console.warn('[EventNormalizer] normalizeEvents: events is not an array', typeof events);\n return [];\n }\n\n return events\n .filter(event => {\n // Filter out Claude tool_result wrappers (marked by sessionService._matchClaudeToolResults)\n if (event._isToolResultWrapper) {\n return false;\n }\n return true;\n })\n .map(event => this.normalizeEvent(event, _source));\n }\n\n /**\n * Normalize a single event\n * @param {Object} event - Raw event\n * @param {string} source - Source format\n * @returns {Object} - Normalized event\n */\n normalizeEvent(event, source) {\n if (!event || typeof event !== 'object') {\n console.warn('[EventNormalizer] normalizeEvent: invalid event', event);\n return event;\n }\n\n // Handle assistant messages with tools\n if (this._isAssistantMessage(event)) {\n return this._normalizeAssistantMessage(event, source);\n }\n\n // Handle timeline events (tool.execution_start/complete, subagent events)\n if (this._isTimelineEvent(event)) {\n return this._normalizeTimelineEvent(event, source);\n }\n\n // Pass through other events unchanged\n return event;\n }\n\n /**\n * Check if event is an assistant message with tools (needs normalization)\n * @private\n */\n _isAssistantMessage(event) {\n // Check if event has tools array (works for all sources)\n if (event.data?.tools && Array.isArray(event.data.tools) && event.data.tools.length > 0) {\n return true;\n }\n // Fallback: check specific types (Copilot/Claude legacy)\n return event.type === 'assistant.message' || event.type === 'assistant' || event.type === 'user.message' || event.type === 'user';\n }\n\n /**\n * Check if event is a timeline event (tool/subagent events)\n * @private\n */\n _isTimelineEvent(event) {\n return event.type?.startsWith('tool.') || event.type?.startsWith('subagent.');\n }\n\n /**\n * Normalize assistant message with embedded tools\n * @private\n */\n _normalizeAssistantMessage(event, source) {\n const normalized = { ...event };\n\n // Normalize tools array if present\n if (event.data?.tools && Array.isArray(event.data.tools)) {\n normalized.data = {\n ...event.data,\n tools: event.data.tools\n .filter(tool => tool.type !== 'tool_result') // Filter out orphan tool_result\n .map(tool => this._normalizeToolCall(tool, source, event.timestamp))\n };\n }\n\n return normalized;\n }\n\n /**\n * Normalize a tool call to unified schema\n *\n * UnifiedToolCall schema:\n * {\n * id: string,\n * name: string,\n * startTime: string (ISO 8601),\n * endTime: string | null,\n * status: 'pending' | 'running' | 'completed' | 'error',\n * input: Record<string, any>,\n * result: string | null,\n * error: string | null,\n * metadata: {\n * source: string,\n * duration?: number,\n * ...\n * }\n * }\n *\n * @private\n */\n _normalizeToolCall(tool, source, messageTimestamp) {\n // Handle Copilot/Claude format with _matched flag\n if (tool.type === 'tool_use') {\n const status = this._computeStatus(tool);\n const startTime = tool._startTime || messageTimestamp;\n const endTime = tool._matched ? (tool._endTime || messageTimestamp) : null;\n\n return {\n type: 'tool_use', // Preserve type for frontend compatibility\n id: tool.id,\n name: tool.name,\n startTime,\n endTime,\n status,\n input: tool.input || {},\n result: tool.result || null,\n error: tool.error || null,\n metadata: {\n source,\n matched: tool._matched,\n duration: this._computeDuration(startTime, endTime)\n }\n };\n }\n\n // Handle Pi-Mono format (already has status)\n if (tool.name && tool.status) {\n const startTime = messageTimestamp;\n // Normalize 'success' to 'completed' for backward compatibility\n const normalizedStatus = tool.status === 'success' ? 'completed' : tool.status;\n const endTime = normalizedStatus === 'completed' || normalizedStatus === 'error'\n ? messageTimestamp\n : null;\n\n return {\n id: tool.id || this._generateToolId(),\n name: tool.name,\n startTime,\n endTime,\n status: normalizedStatus,\n input: tool.input || {},\n result: tool.isError ? null : (tool.result || null),\n error: tool.isError ? tool.result : null,\n metadata: {\n source,\n duration: this._computeDuration(startTime, endTime)\n }\n };\n }\n\n // Fallback: minimal normalization for unknown formats\n console.warn('[EventNormalizer] Unknown tool format, applying fallback normalization', tool);\n return {\n id: tool.id || this._generateToolId(),\n name: tool.name || 'unknown',\n startTime: messageTimestamp,\n endTime: null,\n status: 'running',\n input: tool.input || {},\n result: null,\n error: null,\n metadata: {\n source,\n fallback: true\n }\n };\n }\n\n /**\n * Compute tool status from tool object\n * @private\n */\n _computeStatus(tool) {\n // Explicit error indication\n if (tool.error) {\n return 'error';\n }\n\n // Has result = completed (regardless of _matched flag)\n if (tool.result !== undefined && tool.result !== null && tool.result !== '') {\n return 'completed';\n }\n\n // Explicitly unmatched with no result\n if (tool._matched === false) {\n return 'running';\n }\n\n // Matched = completed\n if (tool._matched) {\n return 'completed';\n }\n\n // No match info: assume running\n return 'running';\n }\n\n /**\n * Compute duration in milliseconds from start/end timestamps\n * @private\n */\n _computeDuration(startTime, endTime) {\n if (!startTime || !endTime) {\n return undefined;\n }\n\n try {\n const start = new Date(startTime);\n const end = new Date(endTime);\n\n if (isNaN(start.getTime()) || isNaN(end.getTime())) {\n return undefined;\n }\n\n const duration = end.getTime() - start.getTime();\n return duration >= 0 ? duration : undefined;\n } catch (err) {\n return undefined;\n }\n }\n\n /**\n * Generate a unique tool ID\n * @private\n */\n _generateToolId() {\n return `tool-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n\n /**\n * Normalize timeline events (tool.execution_start/complete, subagent events)\n * Ensures consistent schema for these events\n * @private\n */\n _normalizeTimelineEvent(event) {\n // For tool.execution_start/complete, ensure consistent schema\n if (event.type === 'tool.execution_start' || event.type === 'tool.execution_complete') {\n return {\n ...event,\n data: {\n ...event.data,\n // Normalize field names for consistency\n toolCallId: event.data?.toolCallId || event.data?.id,\n toolName: event.data?.toolName || event.data?.tool || event.data?.name,\n // Preserve original fields\n ...event.data\n }\n };\n }\n\n // Subagent events: pass through (already have consistent schema)\n if (event.type?.startsWith('subagent.')) {\n return event;\n }\n\n // Unknown timeline event: pass through\n return event;\n }\n}\n\nmodule.exports = EventNormalizer;\n", "const fs = require('fs');\nconst path = require('path');\nconst readline = require('readline');\nconst { isValidSessionId, buildMetadata } = require('../utils/helpers');\nconst SessionRepository = require('./sessionRepository');\nconst EventNormalizer = require('./eventNormalizer');\n\nclass SessionService {\n constructor(sessionDir) {\n // If sessionDir is provided, use it (for backward compatibility)\n // Otherwise, use SessionRepository's default multi-source configuration\n if (sessionDir) {\n this.SESSION_DIR = sessionDir;\n this.sessionRepository = new SessionRepository(sessionDir);\n } else {\n // Use default configuration (Copilot + Claude + Pi-Mono)\n this.sessionRepository = new SessionRepository();\n }\n\n // Initialize EventNormalizer for unified tool format\n this.eventNormalizer = new EventNormalizer();\n }\n\n async getAllSessions(sourceFilter = null) {\n const sessions = await this.sessionRepository.findAll(sourceFilter);\n return sessions.map(s => s.toJSON());\n }\n\n async getPaginatedSessions(page = 1, limit = 20, sourceFilter = null) {\n const allSessions = await this.sessionRepository.findAll(sourceFilter);\n const sessions = allSessions.map(s => s.toJSON());\n\n const startIndex = (page - 1) * limit;\n const endIndex = startIndex + limit;\n const paginatedSessions = sessions.slice(startIndex, endIndex);\n\n return {\n sessions: paginatedSessions,\n totalSessions: sessions.length,\n currentPage: page,\n totalPages: Math.ceil(sessions.length / limit),\n hasNextPage: endIndex < sessions.length,\n hasPrevPage: page > 1\n };\n }\n\n async getSessionById(sessionId, dir = null) {\n if (!isValidSessionId(sessionId)) {\n return null;\n }\n\n const session = await this.sessionRepository.findById(sessionId, dir);\n if (!session) {\n return undefined;\n }\n\n return typeof session.toJSON === 'function' ? session.toJSON() : session;\n }\n\n async getSessionEvents(sessionId, options = null, dir = null) {\n if (!isValidSessionId(sessionId)) {\n return options ? { events: [], total: 0 } : [];\n }\n\n // First, find the session to get its source and type\n const session = await this.sessionRepository.findById(sessionId, dir);\n if (!session) {\n return options ? { events: [], total: 0 } : [];\n }\n\n const adapter = this._getSourceAdapter(session.source);\n const sourceConfig = this.sessionRepository.sources.find(s => s.type === session.source);\n let resolvedSourceDir = dir || sourceConfig?.dir || null;\n\n if (!resolvedSourceDir && adapter) {\n resolvedSourceDir = await adapter.resolveDir();\n }\n \n // Support legacy single source dir mode\n if (this.SESSION_DIR && session.source === 'copilot') {\n resolvedSourceDir = this.SESSION_DIR;\n }\n\n const eventsFile = adapter && !adapter.hasCustomPipeline\n ? await adapter.resolveEventsFile(session, resolvedSourceDir)\n : null;\n\n let events = [];\n if (!adapter) {\n console.warn(\n `SessionService.getSessionEvents: No adapter found for source '${session.source}'. Returning no events.`\n );\n } else {\n events = (await adapter.readEvents(session, resolvedSourceDir)) || [];\n }\n\n // Sanitize the adapter-provided base stream before sub-agent merging.\n // Note: regular sessions intentionally still include merged sub-agent events\n // added later by _mergeSubAgentEvents() for timeline/detail analysis.\n if (events.length > 0) {\n const isSubAgentOnlySession = session.source === 'claude' && session.type === 'directory';\n\n if (isSubAgentOnlySession) {\n // Claude directory sessions represent sub-agent-only views.\n // If the adapter returns any mixed events, keep only sub-agent entries.\n events = events.filter(e => e._subagent);\n } else {\n // For regular sessions, remove sub-agent-tagged events from the adapter's\n // base stream so sub-agents are added in one place via _mergeSubAgentEvents().\n events = events.filter(e => !e._subagent);\n }\n }\n\n\n // Sort by timestamp with stable tiebreaker on original file order\n events.sort((a, b) => {\n const timeA = a.timestamp ? new Date(a.timestamp).getTime() : 0;\n const timeB = b.timestamp ? new Date(b.timestamp).getTime() : 0;\n if (timeA !== timeB) return timeA - timeB;\n return (a._fileIndex ?? 0) - (b._fileIndex ?? 0);\n });\n\n // Remove file-history-snapshot events early to avoid unnecessary normalization work\n events = events.filter(e => e.type !== 'file-history-snapshot');\n\n // Normalize events to unified format (convert Claude format to standard)\n const effectiveSource = session.source === 'vscode' ? 'copilot' : session.source;\n events = events.map(event => this._normalizeEvent(event, effectiveSource));\n \n // Load and merge sub-agent events (for both Copilot and Claude)\n // For Claude sessions without main events.jsonl, this will load subagents from correct path\n if (adapter && !adapter.hasCustomPipeline) {\n await this._mergeSubAgentEvents(events, eventsFile, sessionId, session.source);\n }\n \n // Re-run tool matching after merging subagents (subagent events need matching too)\n if ((adapter && !adapter.hasCustomPipeline && session.source === 'copilot') || session.source === 'vscode') {\n this._matchCopilotToolCalls(events);\n this._mergeHookEvents(events);\n events = this._expandCopilotToTimelineFormat(events);\n events = this._synthesizeSubagentBoundaryEvents(events);\n } else if (adapter && !adapter.hasCustomPipeline && session.source === 'claude') {\n this._matchClaudeToolResults(events);\n events = this._expandClaudeToTimelineFormat(events);\n } else if (adapter && !adapter.hasCustomPipeline && session.source === 'pi-mono') {\n // Pi-Mono: Keep original event structure, no transformation\n // Events are already normalized with type=\"message\" + role in data\n // But we need to merge toolResult events into their parent assistant messages\n this._mergePiMonoToolResults(events);\n }\n \n // Clean up events for timeline rendering\n events = events.filter(e => {\n // Keep events with valid timestamps\n const ts = e.timestamp || e.snapshot?.timestamp;\n if (!ts) {\n console.warn('[SessionService] Filtered event without timestamp:', e.type, e.id || e._fileIndex);\n return false;\n }\n return true;\n });\n \n // Fix fileIndex for subagent events (999999 is too large and breaks sorting)\n events.forEach(e => {\n if (e._fileIndex === 999999 && e.timestamp) {\n // Use timestamp for sorting instead\n delete e._fileIndex;\n }\n });\n\n // Apply unified tool schema normalization (adds startTime, endTime, status, etc.)\n events = this.eventNormalizer.normalizeEvents(events, session.source);\n\n // Apply pagination if requested\n if (options && typeof options.limit === 'number' && typeof options.offset === 'number') {\n const total = events.length;\n const paginatedEvents = events.slice(options.offset, options.offset + options.limit);\n return {\n events: paginatedEvents,\n total\n };\n }\n\n // Backward compatibility: return array when no pagination options\n return events;\n }\n\n /**\n * Load and merge sub-agent events into main event stream\n * @private\n * @param {Array} events - Main events array\n * @param {string|null} mainEventsFile - Path to main events file (null if doesn't exist)\n * @param {string} sessionId - Session ID\n * @param {string} source - Session source ('copilot' or 'claude')\n */\n async _mergeSubAgentEvents(events, mainEventsFile, sessionId, source) {\n let subagentsDir;\n const existingClaudeEventKeys = source === 'claude'\n ? new Set(events.map(event => this._getClaudeSubagentMergeKey(event)).filter(Boolean))\n : null;\n \n if (source === 'claude') {\n // For Claude sessions, look in .claude/projects/*/sessionId/subagents\n const claudeSource = this.sessionRepository.sources.find(s => s.type === 'claude');\n if (!claudeSource) return;\n \n try {\n const projects = await fs.promises.readdir(claudeSource.dir);\n for (const project of projects) {\n const candidateDir = path.join(claudeSource.dir, project, sessionId, 'subagents');\n try {\n const stats = await fs.promises.stat(candidateDir);\n if (stats.isDirectory()) {\n subagentsDir = candidateDir;\n break;\n }\n } catch {\n // Not in this project, continue\n }\n }\n } catch (err) {\n console.error('Error searching Claude subagents:', err);\n return;\n }\n } else if (source === 'copilot' && mainEventsFile) {\n // For Copilot sessions, detect from main events file path\n const eventsDir = path.dirname(mainEventsFile);\n const eventsBasename = path.basename(mainEventsFile);\n \n if (eventsBasename === 'events.jsonl') {\n // .copilot/session-state/<sessionId>/events.jsonl \u2192 check <sessionId>/subagents\n subagentsDir = path.join(eventsDir, 'subagents');\n } else {\n // <sessionId>.jsonl alongside session directory \u2192 check <parent>/<sessionId>/subagents\n subagentsDir = path.join(eventsDir, sessionId, 'subagents');\n }\n }\n \n if (!subagentsDir) {\n return;\n }\n \n try {\n const stats = await fs.promises.stat(subagentsDir);\n if (!stats.isDirectory()) {\n return;\n }\n } catch (err) {\n // No subagents directory\n return;\n }\n \n try {\n const files = await fs.promises.readdir(subagentsDir);\n const subagentFiles = files.filter(f => f.startsWith('agent-') && f.endsWith('.jsonl'));\n \n if (subagentFiles.length === 0) return;\n \n // Process each sub-agent\n for (const file of subagentFiles) {\n const subagentId = file.replace('.jsonl', '');\n const subagentPath = path.join(subagentsDir, file);\n \n try {\n // Stream-based reading for subagent files\n const fileStream = fs.createReadStream(subagentPath, { encoding: 'utf-8' });\n const rl = readline.createInterface({\n input: fileStream,\n crlfDelay: Infinity\n });\n \n const lines = [];\n try {\n for await (const line of rl) {\n const trimmedLine = line.trim();\n if (trimmedLine) {\n lines.push(trimmedLine);\n }\n }\n } finally {\n rl.close();\n fileStream.destroy();\n }\n \n if (lines.length === 0) continue;\n \n // Parse first event to get metadata (slug, agentId, first message)\n let agentName = subagentId.replace('agent-', '');\n let agentDisplayName = agentName.toUpperCase();\n let agentDescription = `Sub-agent ${subagentId}`;\n \n try {\n const firstEvent = JSON.parse(lines[0]);\n // Use agentId (unique per sub-agent) instead of slug (same for all)\n if (firstEvent.agentId) {\n agentName = firstEvent.agentId;\n agentDisplayName = `agent-${firstEvent.agentId}`;\n }\n if (firstEvent.message?.content) {\n // Use first message as description (truncate if too long)\n const content = typeof firstEvent.message.content === 'string' \n ? firstEvent.message.content \n : JSON.stringify(firstEvent.message.content);\n agentDescription = content.length > 100 ? content.slice(0, 100) + '...' : content;\n }\n } catch (err) {\n // Fall back to file-based name\n }\n \n const subagentEvents = lines.map((line, index) => {\n try {\n const event = JSON.parse(line);\n event._fileIndex = 1000000 + index; // Offset to avoid collision\n \n // Mark as sub-agent event\n event._subagent = {\n id: subagentId,\n name: agentName\n };\n \n return event;\n } catch (err) {\n console.error(`Error parsing sub-agent ${subagentId} line ${index + 1}:`, err.message);\n return null;\n }\n }).filter(e => e !== null);\n \n if (subagentEvents.length === 0) continue;\n \n // Normalize sub-agent events (use same source as parent session)\n let normalizedSubEvents = subagentEvents.map(event => this._normalizeEvent(event, source));\n\n if (existingClaudeEventKeys) {\n normalizedSubEvents = normalizedSubEvents.filter(event => {\n const eventKey = this._getClaudeSubagentMergeKey(event);\n if (!eventKey) {\n return true;\n }\n\n if (existingClaudeEventKeys.has(eventKey)) {\n return false;\n }\n\n existingClaudeEventKeys.add(eventKey);\n return true;\n });\n }\n\n if (normalizedSubEvents.length === 0) continue;\n \n // Get first and last event timestamps\n const firstEvent = normalizedSubEvents[0];\n const lastEvent = normalizedSubEvents[normalizedSubEvents.length - 1];\n \n const startTime = firstEvent.timestamp || new Date().toISOString();\n const endTime = lastEvent.timestamp || new Date().toISOString();\n \n // Generate subagent.started event\n const startEvent = {\n type: 'subagent.started',\n id: `${subagentId}-start`,\n timestamp: startTime,\n _fileIndex: firstEvent._fileIndex - 1,\n _subagent: { id: subagentId, name: agentName },\n data: {\n toolCallId: subagentId,\n agentName: agentName,\n agentDisplayName: agentDisplayName,\n agentDescription: agentDescription\n }\n };\n \n // Generate subagent.completed event\n const endEvent = {\n type: 'subagent.completed',\n id: `${subagentId}-end`,\n timestamp: endTime,\n _fileIndex: lastEvent._fileIndex + 1,\n _subagent: { id: subagentId, name: agentName },\n data: {\n toolCallId: subagentId,\n result: `Sub-agent ${agentDisplayName} completed`\n }\n };\n \n // Add to main events array\n events.push(startEvent, ...normalizedSubEvents, endEvent);\n \n } catch (err) {\n console.error(`Error reading sub-agent ${subagentId}:`, err);\n }\n }\n \n // Re-sort all events by timestamp\n events.sort((a, b) => {\n const timeA = a.timestamp ? new Date(a.timestamp).getTime() : 0;\n const timeB = b.timestamp ? new Date(b.timestamp).getTime() : 0;\n if (timeA !== timeB) return timeA - timeB;\n return a._fileIndex - b._fileIndex;\n });\n \n } catch (err) {\n console.error('Error processing sub-agents:', err);\n }\n }\n\n _getClaudeSubagentMergeKey(event) {\n if (!event || event.type?.startsWith('subagent.')) {\n return null;\n }\n\n const timestamp = event.timestamp || event.snapshot?.timestamp;\n if (!timestamp) {\n return null;\n }\n\n const identifier = event.uuid || event.id || '';\n const parentIdentifier = event.parentUuid || event.parentId || '';\n const message = event.data?.message || '';\n const toolSignature = Array.isArray(event.data?.tools)\n ? event.data.tools.map(tool => {\n if (!tool || typeof tool !== 'object') {\n return '';\n }\n\n if (tool.type === 'tool_use') {\n return `${tool.type}:${tool.id || ''}:${tool.name || ''}`;\n }\n\n if (tool.type === 'tool_result') {\n return `${tool.type}:${tool.tool_use_id || ''}`;\n }\n\n return `${tool.type || 'tool'}:${tool.id || ''}:${tool.name || ''}`;\n }).join('|')\n : '';\n\n if (!identifier && !parentIdentifier && !message && !toolSignature) {\n return null;\n }\n\n return JSON.stringify([\n event.type,\n timestamp,\n identifier,\n parentIdentifier,\n message,\n toolSignature\n ]);\n }\n\n /**\n * Match tool_result events with tool_use for Claude format\n * @private\n */\n _matchClaudeToolResults(events) {\n // Build map of tool_result by tool_use_id\n const toolResultMap = new Map();\n \n events.forEach(event => {\n if (event.data?.tools) {\n event.data.tools.forEach(tool => {\n if (tool.type === 'tool_result') {\n // Bug fix #1: Validate tool_use_id exists\n if (tool.tool_use_id) {\n toolResultMap.set(tool.tool_use_id, tool);\n } else {\n console.warn('[sessionService] tool_result missing tool_use_id:', tool);\n }\n }\n });\n }\n });\n \n // Mark user events that are entirely tool_result responses (will be filtered out in normalizer)\n events.forEach(event => {\n if (event.type === 'user' && Array.isArray(event.message?.content)) {\n const allToolResults = event.message.content.length > 0 &&\n event.message.content.every(block => block?.type === 'tool_result');\n if (allToolResults) {\n event._isToolResultWrapper = true;\n }\n }\n });\n\n // Match tool_use with tool_result\n events.forEach(event => {\n if (event.data?.tools) {\n event.data.tools = event.data.tools.map(tool => {\n if (tool.type === 'tool_use') {\n const result = toolResultMap.get(tool.id);\n if (result) {\n return {\n ...tool,\n result: result.content,\n _matched: true\n };\n }\n // Bug fix #4: Add _matched: false for unmatched Claude tools (consistency with Copilot)\n return {\n ...tool,\n _matched: false\n };\n }\n return tool;\n });\n \n // Bug fix: Only remove tool_result from assistant messages\n // Mark user messages that consist entirely of tool_results as wrappers (will be filtered out)\n if (event.type === 'assistant' || event.type === 'assistant.message') {\n event.data.tools = event.data.tools.filter(tool => tool.type !== 'tool_result');\n } else if (event.type === 'user' || event.type === 'user.message') {\n const allToolResults = event.data.tools.length > 0 &&\n event.data.tools.every(tool => tool.type === 'tool_result');\n if (allToolResults) {\n event._isToolResultWrapper = true;\n }\n }\n }\n });\n }\n\n /**\n * Match Pi-Mono tool results with tool calls by order (parentId chain)\n * Pi-Mono format: toolResult messages form a parentId chain starting from assistant message\n * After matching, removes tool.result events from the stream (they're attached to tools)\n * @private\n */\n /**\n * Merge Pi-Mono toolResult messages into their parent assistant messages\n * Pi-Mono has message events with role: user/assistant/toolResult\n * After normalization: user.message, assistant.message, and message (toolResult only)\n * toolResult events are chained via parentId (first points to assistant, rest chain to previous)\n * @private\n */\n _mergePiMonoToolResults(events) {\n const toolResultIdsToRemove = new Set();\n\n // Find all assistant messages with tool calls\n events.forEach(assistantEvent => {\n if (assistantEvent.type === 'assistant.message' && // After normalization\n assistantEvent.data.tools && \n assistantEvent.data.tools.length > 0) {\n \n const tools = assistantEvent.data.tools;\n \n // Collect toolResult events by following parentId chain\n const resultEvents = [];\n let currentId = assistantEvent.id;\n \n // Follow the chain: find events whose parentId points to current\n let foundMore = true;\n while (foundMore && resultEvents.length < tools.length) {\n foundMore = false;\n for (const event of events) {\n if (event.type === 'message' && \n event.data.role === 'toolResult' && \n event.parentId === currentId && \n !resultEvents.includes(event)) {\n resultEvents.push(event);\n currentId = event.id;\n foundMore = true;\n break;\n }\n }\n }\n\n // Match results to tools by order\n resultEvents.forEach((resultEvent, index) => {\n if (index < tools.length) {\n const tool = tools[index];\n tool.result = resultEvent.data.result;\n tool.resultId = resultEvent.id;\n tool.status = 'completed';\n toolResultIdsToRemove.add(resultEvent.id);\n }\n });\n }\n });\n\n // Remove toolResult events from the stream (they're now merged into assistant messages)\n const originalLength = events.length;\n for (let i = events.length - 1; i >= 0; i--) {\n if (events[i].type === 'message' && \n events[i].data.role === 'toolResult' && \n toolResultIdsToRemove.has(events[i].id)) {\n events.splice(i, 1);\n }\n }\n \n if (toolResultIdsToRemove.size > 0) {\n console.log(`[PI-MONO] Merged ${toolResultIdsToRemove.size} toolResult events into assistant messages (${originalLength} \u2192 ${events.length} events)`);\n }\n }\n\n\n /**\n * Merge hook.start/hook.end pairs: attach end result to start, mark end for removal.\n * @private\n */\n _mergeHookEvents(events) {\n const pending = new Map(); // hookInvocationId \u2192 index in events array\n\n for (let i = 0; i < events.length; i++) {\n const ev = events[i];\n const invId = ev.data?.hookInvocationId;\n if (!invId) continue;\n\n if (ev.type === 'hook.start') {\n pending.set(invId, i);\n } else if (ev.type === 'hook.end') {\n const startIdx = pending.get(invId);\n if (startIdx !== undefined) {\n // Merge end result into start event\n const start = events[startIdx];\n const success = ev.data?.success !== false;\n start.data.hookSuccess = success;\n start.data.hookError = ev.data?.error || null;\n // Calculate duration\n if (start.timestamp && ev.timestamp) {\n const ms = new Date(ev.timestamp) - new Date(start.timestamp);\n start.data.hookDurationMs = ms;\n // Append duration to message\n const durationStr = ms < 1000 ? `${ms}ms` : `${(ms / 1000).toFixed(2)}s`;\n if (start.data.message) {\n start.data.message += `\\n**Duration:** ${durationStr}`;\n }\n }\n // Update badge to show result\n start.data.badgeLabel = success ? '\u2713 HOOK' : '\u2717 HOOK';\n start.data.badgeClass = success ? 'badge-hook' : 'badge-error';\n pending.delete(invId);\n }\n // Mark hook.end for removal\n ev._remove = true;\n }\n }\n\n // Remove hook.end events in-place\n for (let i = events.length - 1; i >= 0; i--) {\n if (events[i]._remove) events.splice(i, 1);\n }\n }\n\n /**\n * Match Copilot tool.execution_start/complete events and attach to assistant.message\n * @private\n */\n _matchCopilotToolCalls(events) {\n // Step 1: Build tool execution map (start + complete paired by toolCallId)\n const toolExecutions = new Map();\n \n events.forEach(event => {\n if (event.type === 'tool.execution_start') {\n const toolId = event.data?.toolCallId;\n if (toolId) {\n toolExecutions.set(toolId, {\n name: event.data.toolName,\n input: event.data.arguments || {},\n start: event\n });\n }\n } else if (event.type === 'tool.execution_complete') {\n const toolId = event.data?.toolCallId;\n if (toolId) {\n if (toolExecutions.has(toolId)) {\n const exec = toolExecutions.get(toolId);\n exec.complete = event;\n exec.result = event.data?.result;\n exec.status = event.data?.error ? 'error' : 'completed';\n exec.error = event.data?.error;\n } else {\n // Bug fix #3: Handle orphaned execution_complete events (no matching start)\n console.warn(`[sessionService] Orphaned tool.execution_complete for toolCallId=${toolId}`);\n toolExecutions.set(toolId, {\n name: event.data.toolName || 'unknown',\n input: {},\n start: null, // No start event\n complete: event,\n result: event.data?.result,\n status: event.data?.error ? 'error' : 'completed',\n error: event.data?.error\n });\n }\n }\n }\n });\n \n // Step 2: Match toolRequests in assistant.message with tool executions\n events.forEach(event => {\n if (event.type === 'assistant.message' && event.data?.toolRequests) {\n const tools = [];\n \n event.data.toolRequests.forEach(req => {\n const toolId = req.toolCallId;\n if (toolExecutions.has(toolId)) {\n const exec = toolExecutions.get(toolId);\n tools.push({\n type: 'tool_use',\n id: toolId,\n name: req.name || exec.name,\n input: req.arguments || exec.input,\n result: exec.result,\n status: exec.status || 'running',\n error: exec.error,\n _matched: !!exec.complete,\n _startTime: exec.start?.timestamp,\n _endTime: exec.complete?.timestamp\n });\n } else {\n // Tool request but no execution found (shouldn't happen normally)\n tools.push({\n type: 'tool_use',\n id: toolId,\n name: req.name,\n input: req.arguments || {},\n status: 'running',\n _matched: false\n });\n }\n });\n \n if (tools.length > 0) {\n event.data.tools = tools;\n }\n }\n });\n }\n\n /**\n * Generate badge display information for an event\n * @private\n */\n _generateBadgeInfo(normalized) {\n const type = normalized.type;\n const data = normalized.data || {};\n \n // Special case: toolResult still uses type='message'\n if (type === 'message' && data.role === 'toolResult') {\n normalized.data.badgeLabel = 'TOOL RESULT';\n normalized.data.badgeClass = 'badge-tool';\n return;\n }\n \n // Special cases for specific event types\n if (type === 'session.model_change' || type === 'model.change') {\n normalized.data.badgeLabel = 'MODEL CHANGE';\n normalized.data.badgeClass = 'badge-session';\n return;\n }\n if (type === 'session.truncation') {\n normalized.data.badgeLabel = 'TRUNCATION';\n normalized.data.badgeClass = 'badge-truncation';\n return;\n }\n if (type === 'session.compaction_start' || type === 'session.compaction_complete' || type === 'compaction') {\n normalized.data.badgeLabel = 'COMPACTION';\n normalized.data.badgeClass = 'badge-compaction';\n return;\n }\n if (type === 'thinking.change') {\n normalized.data.badgeLabel = 'THINKING';\n normalized.data.badgeClass = 'badge-session';\n return;\n }\n if (type === 'system.notification') {\n normalized.data.badgeLabel = 'SYSTEM';\n normalized.data.badgeClass = 'badge-system';\n return;\n }\n \n // Extract category from type (e.g., 'user.message' \u2192 'user')\n const parts = (type || '').split('.');\n const category = parts[0] || 'unknown';\n \n const badgeMap = {\n user: { label: 'USER', class: 'badge-user' },\n assistant: { label: 'ASSISTANT', class: 'badge-assistant' },\n reasoning: { label: 'REASONING', class: 'badge-reasoning' },\n turn: { label: 'TURN', class: 'badge-turn' },\n tool: { label: 'TOOL', class: 'badge-tool' },\n subagent: { label: 'SUBAGENT', class: 'badge-subagent' },\n skill: { label: 'SKILL', class: 'badge-skill' },\n session: { label: 'SESSION', class: 'badge-session' },\n error: { label: 'ERROR', class: 'badge-error' },\n abort: { label: 'ABORT', class: 'badge-error' }\n };\n \n const badge = badgeMap[category] || { label: category.toUpperCase(), class: 'badge-info' };\n normalized.data.badgeLabel = badge.label;\n normalized.data.badgeClass = badge.class;\n }\n\n /**\n * Normalize event to unified format for frontend\n * @private\n */\n _normalizeEvent(event, source) {\n const normalized = { ...event };\n normalized.data = normalized.data || {};\n\n if (source === 'copilot') {\n // Copilot format normalization\n\n // system-sourced user.message \u2192 system.notification (separate type for display)\n if (event.type === 'user.message' && event.data?.source === 'system') {\n normalized.type = 'system.notification';\n // Extract text from <system_notification>...</system_notification> tag if present\n const raw = event.data.content || event.data.message || '';\n const match = raw.match(/<system_notification>([\\s\\S]*?)<\\/system_notification>/);\n normalized.data.message = match ? match[1].trim() : raw.trim();\n this._generateBadgeInfo(normalized);\n return normalized;\n }\n if (event.type === 'request') {\n normalized.type = 'user';\n // Extract message from payload.messages (Anthropic API format)\n if (event.payload?.messages && Array.isArray(event.payload.messages)) {\n const userMessage = event.payload.messages.find(m => m.role === 'user');\n if (userMessage) {\n normalized.message = {\n role: 'user',\n content: userMessage.content || ''\n };\n }\n }\n } else if (event.type === 'response') {\n normalized.type = 'assistant';\n // Extract message from payload.content (Anthropic API format)\n if (event.payload?.content && Array.isArray(event.payload.content)) {\n const textBlocks = event.payload.content.filter(block => block.type === 'text');\n if (textBlocks.length > 0) {\n normalized.message = {\n role: 'assistant',\n content: textBlocks.map(block => block.text).join('\\n')\n };\n }\n }\n }\n \n // New format: assistant.message data normalization\n if (event.type === 'assistant.message') {\n // Convert data.content \u2192 data.message for consistency\n if (event.data?.content && event.data.content.trim()) {\n normalized.data.message = event.data.content;\n }\n // If only toolcalls, leave message empty (don't create placeholder)\n }\n \n // subagent.selected: rename data.tools to data.allowedTools to avoid collision with tool rendering\n if (event.type === 'subagent.selected' && Array.isArray(event.data?.tools)) {\n normalized.data.allowedTools = event.data.tools;\n delete normalized.data.tools;\n if (event.data.agentDisplayName || event.data.agentName) {\n normalized.data.message = `Agent: ${event.data.agentDisplayName || event.data.agentName}`;\n if (normalized.data.allowedTools.length > 0 && normalized.data.allowedTools[0] !== '*') {\n normalized.data.message += `\\nTools: ${normalized.data.allowedTools.join(', ')}`;\n }\n }\n }\n\n // Hook events (hook.start / hook.end)\n if (event.type === 'hook.start') {\n const d = event.data || {};\n // Store structured hook data for rich rendering\n normalized.data.hookType = d.hookType || null;\n normalized.data.hookToolName = d.input?.toolName || null;\n normalized.data.hookArgs = d.input?.toolArgs || null;\n normalized.data.hookResult = d.input?.toolResult?.textResultForLlm || null;\n // Summary line for the collapsed view\n const summaryParts = [];\n if (d.hookType) summaryParts.push(d.hookType);\n if (d.input?.toolName) summaryParts.push(`\u2192 ${d.input.toolName}`);\n normalized.data.message = summaryParts.join(' ') || 'hook';\n normalized.data.badgeLabel = 'HOOK';\n normalized.data.badgeClass = 'badge-hook';\n this._generateBadgeInfo(normalized);\n return normalized;\n }\n if (event.type === 'hook.end') {\n const d = event.data || {};\n const parts = [];\n if (d.hookType) parts.push(`**Hook:** ${d.hookType}`);\n parts.push(d.success ? '**Status:** \u2713 success' : '**Status:** \u2717 failed');\n if (d.error) parts.push(`**Error:** ${d.error}`);\n normalized.data.message = parts.join('\\n');\n normalized.data.badgeLabel = 'HOOK END';\n normalized.data.badgeClass = d.success ? 'badge-hook' : 'badge-error';\n this._generateBadgeInfo(normalized);\n return normalized;\n }\n\n // Generate badge display info\n this._generateBadgeInfo(normalized);\n return normalized;\n }\n\n if (source === 'pi-mono') {\n // Pi-Mono format normalization - TRANSFORM TO UNIFIED TYPE\n if (event.type === 'message') {\n const { message } = event;\n \n // Transform type to unified format (like Copilot/Claude)\n if (message.role === 'user') {\n normalized.type = 'user.message';\n } else if (message.role === 'assistant') {\n normalized.type = 'assistant.message';\n } else if (message.role === 'toolResult') {\n // toolResult keeps 'message' type - will be merged by _mergePiMonoToolResults\n normalized.type = 'message';\n }\n normalized.data.role = message.role;\n \n // Extract text content\n if (Array.isArray(message.content)) {\n const textBlocks = message.content.filter(block => block.type === 'text');\n if (textBlocks.length > 0) {\n normalized.data.message = textBlocks.map(block => block.text).join('\\n');\n }\n \n // Extract tool calls (for assistant messages)\n if (message.role === 'assistant') {\n const toolCalls = message.content.filter(block => block.type === 'toolCall');\n if (toolCalls.length > 0) {\n normalized.data.tools = toolCalls.map(tool => ({\n type: 'tool_use',\n id: tool.id,\n name: tool.name,\n input: tool.arguments\n }));\n }\n }\n \n // Extract tool result (for toolResult messages)\n if (message.role === 'toolResult') {\n normalized.data.result = textBlocks.map(block => block.text).join('\\n');\n }\n }\n \n // Preserve usage metadata if available\n if (message.usage) {\n normalized.usage = message.usage;\n }\n } else if (event.type === 'model_change') {\n // Normalize to model.change format\n normalized.type = 'model.change';\n normalized.data = {\n provider: event.provider,\n model: event.modelId\n };\n // Generate readable message\n if (event.provider && event.modelId) {\n normalized.data.message = `Model changed to ${event.provider}/${event.modelId}`;\n } else if (event.modelId) {\n normalized.data.message = `Model changed to ${event.modelId}`;\n }\n } else if (event.type === 'thinking_level_change') {\n // Normalize to thinking.change format\n normalized.type = 'thinking.change';\n normalized.data = {\n level: event.thinkingLevel\n };\n // Generate readable message\n if (event.thinkingLevel) {\n normalized.data.message = `Thinking level: ${event.thinkingLevel}`;\n }\n } else if (event.type === 'session') {\n // Session metadata\n normalized.data = {\n cwd: event.cwd,\n version: event.version\n };\n // Generate readable message\n const parts = [];\n if (event.cwd) {\n parts.push(`Working directory: ${event.cwd}`);\n }\n if (event.version) {\n parts.push(`Session version: ${event.version}`);\n }\n if (parts.length > 0) {\n normalized.data.message = parts.join('\\n');\n }\n }\n \n // Generate badge display info\n this._generateBadgeInfo(normalized);\n return normalized;\n }\n\n // Claude format normalization\n // Handle different event types\n switch (event.type) {\n case 'user':\n case 'assistant':\n // Convert Claude user/assistant messages to standard format\n if (event.message) {\n if (event.message.model) {\n normalized.model = event.message.model;\n }\n\n if (event.message.usage) {\n normalized.usage = event.message.usage;\n }\n\n // Extract text content from message.content\n if (event.message.content) {\n const textContent = this._extractClaudeTextContent(event.message.content);\n if (textContent) {\n normalized.data.message = textContent;\n }\n }\n\n // Extract tool calls from message.content\n if (Array.isArray(event.message.content)) {\n // Gap #6 fix: Add null safety check for block objects\n const toolBlocks = event.message.content.filter(block => \n block && typeof block === 'object' && \n (block.type === 'tool_use' || block.type === 'tool_result')\n );\n \n if (toolBlocks.length > 0) {\n normalized.data.tools = toolBlocks.map(block => {\n if (block.type === 'tool_use') {\n return {\n type: 'tool_use',\n id: block.id,\n name: block.name,\n input: block.input\n };\n } else {\n return {\n type: 'tool_result',\n tool_use_id: block.tool_use_id,\n content: block.content\n };\n }\n });\n }\n }\n\n // Preserve original message for reference\n normalized._originalMessage = event.message;\n }\n break;\n\n case 'file-history-snapshot':\n // Extract file list from snapshot\n if (event.snapshot?.trackedFileBackups) {\n const files = Object.entries(event.snapshot.trackedFileBackups);\n if (files.length > 0) {\n const fileList = files.map(([filename, backup]) => \n `${filename} (v${backup.version})`\n ).join('\\n');\n normalized.data.message = `Tracked files:\\n${fileList}`;\n } else {\n normalized.data.message = 'No files tracked';\n }\n }\n break;\n\n case 'progress':\n // Extract progress information\n if (event.data) {\n const parts = [];\n if (event.data.hookName) parts.push(`Hook: ${event.data.hookName}`);\n if (event.data.hookEvent) parts.push(`Event: ${event.data.hookEvent}`);\n if (event.data.command) parts.push(`Command: ${event.data.command}`);\n if (parts.length > 0) {\n normalized.data.message = parts.join('\\n');\n }\n \n // Extract nested tool_use from progress events (subagent messages)\n // Progress events from subagents contain message.message.content with tool_use blocks\n if (event.data.message?.message?.content && Array.isArray(event.data.message.message.content)) {\n const toolBlocks = event.data.message.message.content.filter(block =>\n block && typeof block === 'object' && (block.type === 'tool_use' || block.type === 'tool_result')\n );\n \n if (toolBlocks.length > 0) {\n normalized.data.tools = toolBlocks.map(block => {\n if (block.type === 'tool_use') {\n return {\n type: 'tool_use',\n id: block.id,\n name: block.name,\n input: block.input\n };\n } else {\n return {\n type: 'tool_result',\n tool_use_id: block.tool_use_id,\n content: block.content\n };\n }\n });\n }\n }\n }\n break;\n\n case 'hook.start': {\n const d = event.data || {};\n normalized.data.hookType = d.hookType || null;\n normalized.data.hookToolName = d.input?.toolName || null;\n normalized.data.hookArgs = d.input?.toolArgs || null;\n normalized.data.hookResult = d.input?.toolResult?.textResultForLlm || null;\n const summaryParts = [];\n if (d.hookType) summaryParts.push(d.hookType);\n if (d.input?.toolName) summaryParts.push(`\u2192 ${d.input.toolName}`);\n normalized.data.message = summaryParts.join(' ') || 'hook';\n normalized.data.badgeLabel = 'HOOK';\n normalized.data.badgeClass = 'badge-hook';\n break;\n }\n\n case 'hook.end': {\n const d = event.data || {};\n const parts = [];\n if (d.hookType) parts.push(`**Hook:** ${d.hookType}`);\n parts.push(d.success ? '**Status:** \u2713 success' : '**Status:** \u2717 failed');\n if (d.error) parts.push(`**Error:** ${d.error}`);\n normalized.data.message = parts.join('\\n');\n normalized.data.badgeLabel = 'HOOK END';\n normalized.data.badgeClass = d.success ? 'badge-hook' : 'badge-error';\n break;\n }\n\n // Add more event types as needed\n default:\n // For unknown types, try to extract any reasonable text\n if (event.data?.message && !normalized.data.message) {\n normalized.data.message = event.data.message;\n }\n }\n\n // Generate badge display info\n this._generateBadgeInfo(normalized);\n return normalized;\n }\n\n /**\n * Extract text content from Claude message.content\n * @private\n */\n _extractClaudeTextContent(content) {\n if (typeof content === 'string') {\n return content;\n }\n \n if (Array.isArray(content)) {\n const textParts = [];\n \n for (const block of content) {\n if (block.type === 'text') {\n // Direct text block\n textParts.push(block.text);\n } else if (block.type === 'tool_result') {\n // Extract text from tool_result content\n if (typeof block.content === 'string') {\n // Format 2: direct string\n textParts.push(block.content);\n } else if (Array.isArray(block.content)) {\n // Format 1: nested array with text blocks\n const nestedText = block.content\n .filter(item => item.type === 'text')\n .map(item => item.text)\n .join('\\n');\n if (nestedText) {\n textParts.push(nestedText);\n }\n }\n }\n }\n \n return textParts.join('\\n');\n }\n \n return '';\n }\n\n /**\n * Normalize optional Claude token counters into finite numbers.\n * @private\n * @param {*} value - Raw token count\n * @returns {number} Normalized token count\n */\n _getClaudeUsageNumber(value) {\n return typeof value === 'number' && Number.isFinite(value) ? value : 0;\n }\n\n /**\n * Extract cache creation tokens from Claude usage data.\n * @private\n * @param {Object} usage - Claude usage payload\n * @returns {number} Cache write token count\n */\n _getClaudeCacheWriteTokens(usage) {\n const topLevel = this._getClaudeUsageNumber(usage?.cache_creation_input_tokens);\n if (topLevel > 0) {\n return topLevel;\n }\n\n if (!usage?.cache_creation || typeof usage.cache_creation !== 'object') {\n return 0;\n }\n\n return Object.values(usage.cache_creation)\n .reduce((total, value) => total + this._getClaudeUsageNumber(value), 0);\n }\n\n /**\n * Get Claude usage payload from a normalized event.\n * Supports both message.usage and newer top-level usage fields.\n * @private\n * @param {Object} event - Normalized event\n * @returns {Object|null} Usage payload\n */\n _getClaudeUsagePayload(event) {\n if (event?.usage && typeof event.usage === 'object') {\n return event.usage;\n }\n\n if (event?.toolUseResult?.usage && typeof event.toolUseResult.usage === 'object') {\n return event.toolUseResult.usage;\n }\n\n if (event?.message?.usage && typeof event.message.usage === 'object') {\n return event.message.usage;\n }\n\n // Copilot-cli: usage in payload.usage (Anthropic API response format)\n if (event?.payload?.usage && typeof event.payload.usage === 'object') {\n return event.payload.usage;\n }\n\n return null;\n }\n\n /**\n * Get total Claude token count from an event or nested toolUseResult payload.\n * @private\n * @param {Object} event - Normalized event\n * @returns {number} Total token count\n */\n _getClaudeEventTotalTokens(event) {\n return this._getClaudeUsageNumber(event?.totalTokens)\n || this._getClaudeUsageNumber(event?.toolUseResult?.totalTokens);\n }\n\n /**\n * Get total Claude API duration from an event or nested toolUseResult payload.\n * @private\n * @param {Object} event - Normalized event\n * @returns {number} Total duration in milliseconds\n */\n _getClaudeEventDurationMs(event) {\n return this._getClaudeUsageNumber(event?.totalDurationMs)\n || this._getClaudeUsageNumber(event?.toolUseResult?.totalDurationMs);\n }\n\n /**\n * Get the Claude model directly declared on an event.\n * @private\n * @param {Object} event - Normalized event\n * @returns {string|null} Model name\n */\n _getClaudeEventModel(event) {\n return event?.model || event?.message?.model || event?._originalMessage?.model || event?.payload?.model || null;\n }\n\n /**\n * Resolve the Claude model for a usage event using direct fields and lineage.\n * @private\n * @param {Object} event - Normalized event\n * @param {Map<string, string>} modelByUuid - UUID to model map\n * @returns {string} Model name\n */\n _resolveClaudeUsageModel(event, modelByUuid) {\n return this._getClaudeEventModel(event)\n || modelByUuid.get(event?.sourceToolAssistantUUID)\n || modelByUuid.get(event?.parentUuid)\n || modelByUuid.get(event?.uuid)\n || 'unknown';\n }\n\n /**\n * Index Claude tool-result wrapper usage events by related assistant UUID.\n * Preserves original event order and avoids duplicate insertion when both\n * sourceToolAssistantUUID and parentUuid point to the same assistant.\n * @private\n * @param {Array} events - Normalized Claude events\n * @returns {Map<string, Array>} Assistant UUID to related usage wrapper events\n */\n _indexClaudeRelatedUsageEvents(events) {\n const relatedUsageEventsByAssistantUuid = new Map();\n\n for (const event of events) {\n if (!event?._isToolResultWrapper) {\n continue;\n }\n\n if (!this._getClaudeUsagePayload(event) && this._getClaudeEventTotalTokens(event) === 0) {\n continue;\n }\n\n const assistantUuids = new Set([\n event.sourceToolAssistantUUID,\n event.parentUuid\n ].filter(uuid => typeof uuid === 'string' && uuid.length > 0));\n\n for (const assistantUuid of assistantUuids) {\n if (!relatedUsageEventsByAssistantUuid.has(assistantUuid)) {\n relatedUsageEventsByAssistantUuid.set(assistantUuid, []);\n }\n relatedUsageEventsByAssistantUuid.get(assistantUuid).push(event);\n }\n }\n\n return relatedUsageEventsByAssistantUuid;\n }\n\n /**\n * Aggregate Claude per-message usage into the shared usage metadata shape.\n * @private\n * @param {Array} events - Session events\n * @returns {Object|null} Usage data or null if not found\n */\n _extractClaudeUsageData(events) {\n const modelMetrics = {};\n const modelByUuid = new Map();\n\n for (const event of events) {\n const model = this._getClaudeEventModel(event);\n if (model && event?.uuid) {\n modelByUuid.set(event.uuid, model);\n }\n }\n\n let totalApiDurationMs = 0;\n\n for (const event of events) {\n const usageEvents = [event, ...(Array.isArray(event._relatedUsageEvents) ? event._relatedUsageEvents : [])];\n\n for (const usageEvent of usageEvents) {\n const usage = this._getClaudeUsagePayload(usageEvent) || {};\n\n const cacheReadTokens = this._getClaudeUsageNumber(usage.cache_read_input_tokens);\n const cacheWriteTokens = this._getClaudeCacheWriteTokens(usage);\n const uncachedInputTokens = this._getClaudeUsageNumber(usage.input_tokens);\n const outputTokens = this._getClaudeUsageNumber(usage.output_tokens);\n const fallbackTotalTokens = this._getClaudeEventTotalTokens(usageEvent);\n let inputTokens = uncachedInputTokens;\n\n if (inputTokens === 0 && outputTokens === 0 && cacheReadTokens === 0 && cacheWriteTokens === 0) {\n if (fallbackTotalTokens > 0) {\n inputTokens = Math.max(fallbackTotalTokens - outputTokens, 0);\n } else {\n continue;\n }\n }\n\n const model = this._resolveClaudeUsageModel(usageEvent, modelByUuid);\n if (!modelMetrics[model]) {\n modelMetrics[model] = {\n requests: { count: 0 },\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0\n }\n };\n }\n\n modelMetrics[model].requests.count += 1;\n modelMetrics[model].usage.inputTokens += inputTokens;\n modelMetrics[model].usage.outputTokens += outputTokens;\n modelMetrics[model].usage.cacheReadTokens += cacheReadTokens;\n modelMetrics[model].usage.cacheWriteTokens += cacheWriteTokens;\n totalApiDurationMs += this._getClaudeEventDurationMs(usageEvent);\n }\n }\n\n if (Object.keys(modelMetrics).length === 0) {\n return null;\n }\n\n return {\n modelMetrics,\n totalPremiumRequests: 0,\n totalApiDurationMs,\n codeChanges: { linesAdded: 0, linesRemoved: 0, filesModified: [] },\n currentTokens: 0,\n systemTokens: 0,\n conversationTokens: 0,\n toolDefinitionsTokens: 0\n };\n }\n\n /**\n * Extract usage data from session events.\n * Public API so controllers and other callers do not depend on service internals.\n * @param {Array} events - Session events\n * @returns {Object|null} Usage data or null if not found\n */\n extractUsageData(events) {\n if (!Array.isArray(events) || events.length === 0) {\n return null;\n }\n\n const shutdownEvent = events.find(e => e.type === 'session.shutdown');\n if (shutdownEvent && shutdownEvent.data) {\n const data = shutdownEvent.data;\n // Copilot CLI includes cacheRead/cacheWrite in inputTokens.\n // Normalize so inputTokens only reflects uncached input.\n const modelMetrics = data.modelMetrics || {};\n for (const model of Object.keys(modelMetrics)) {\n const usage = modelMetrics[model]?.usage;\n if (usage) {\n const cacheRead = usage.cacheReadTokens || 0;\n const cacheWrite = usage.cacheWriteTokens || 0;\n if (cacheRead > 0 || cacheWrite > 0) {\n usage.inputTokens = Math.max((usage.inputTokens || 0) - cacheRead - cacheWrite, 0);\n }\n }\n }\n return {\n modelMetrics,\n totalPremiumRequests: data.totalPremiumRequests || 0,\n totalApiDurationMs: data.totalApiDurationMs || 0,\n codeChanges: data.codeChanges || { linesAdded: 0, linesRemoved: 0, filesModified: [] },\n currentTokens: data.currentTokens || 0,\n systemTokens: data.systemTokens || 0,\n conversationTokens: data.conversationTokens || 0,\n toolDefinitionsTokens: data.toolDefinitionsTokens || 0\n };\n }\n\n return this._extractClaudeUsageData(events);\n }\n\n async getSessionWithEvents(sessionId) {\n const session = await this.getSessionById(sessionId);\n if (!session) {\n return null;\n }\n\n const events = await this.getSessionEvents(sessionId);\n const metadata = buildMetadata(session);\n\n // Extract model from events\n const sessionStartEvent = events.find(e => e.type === 'session.start');\n if (sessionStartEvent?.data?.selectedModel) {\n metadata.model = sessionStartEvent.data.selectedModel;\n }\n\n const modelChangeEvent = events.find(e => e.type === 'session.model_change');\n if (modelChangeEvent?.data) {\n metadata.model = modelChangeEvent.data.newModel || modelChangeEvent.data.model;\n }\n\n // Derive \"updated\" from last event timestamp (more accurate than filesystem mtime)\n if (events.length) {\n const lastEvent = events[events.length - 1];\n if (lastEvent?.timestamp) {\n metadata.updated = lastEvent.timestamp;\n }\n }\n\n // Derive \"created\" from first event timestamp if available\n if (events.length) {\n const firstEvent = events[0];\n if (firstEvent?.timestamp) {\n metadata.created = firstEvent.timestamp;\n }\n }\n\n // Extract usage data from session.shutdown event\n metadata.usage = this.extractUsageData(events);\n\n return { session, events, metadata };\n }\n\n /**\n * Get unified timeline structure (source-agnostic)\n * Converts raw events into standardized turns/tools/subagents structure\n * @param {string} sessionId\n * @returns {Promise<Object>} Unified timeline data\n */\n async getTimeline(sessionId) {\n const session = await this.getSessionById(sessionId);\n if (!session) {\n return null;\n }\n\n const events = await this.getSessionEvents(sessionId);\n const adapter = this._getSourceAdapter(session.source);\n\n if (adapter) {\n const timeline = adapter.buildTimeline(events, session);\n if (timeline && (timeline.turns?.length > 0 || Object.keys(timeline.summary || {}).length > 0)) {\n return timeline;\n }\n }\n\n // Dispatch to source-specific builder\n if (session.source === 'copilot' || session.source === 'vscode') {\n return this._buildCopilotTimeline(events, session);\n } else if (session.source === 'claude') {\n return this._buildClaudeTimeline(events, session);\n } else if (session.source === 'pi-mono') {\n return this._buildPiMonoTimeline(events, session);\n }\n\n return { turns: [], summary: {} };\n }\n\n /**\n * Build Pi-Mono timeline from normalized events\n * Pi-Mono uses user.message/assistant.message (unified with Copilot/Claude)\n * @private\n */\n _buildPiMonoTimeline(events, _session) {\n const turns = [];\n let turnId = 0;\n\n // Find consecutive user -> assistant pairs\n for (let i = 0; i < events.length; i++) {\n const event = events[i];\n \n // After normalization, Pi-Mono uses unified type 'user.message'\n if (event.type === 'user.message') {\n turnId++;\n const turn = {\n id: `turn-${turnId}`,\n type: 'user-request',\n message: event.data.message || '',\n startTime: event.timestamp,\n endTime: event.timestamp,\n assistantTurns: [], // Group assistant messages\n subagents: []\n };\n\n // Find all assistant responses until next user message\n let j = i + 1;\n let assistantId = 0;\n while (j < events.length && events[j].type !== 'user.message') {\n const nextEvent = events[j];\n \n if (nextEvent.type === 'assistant.message') {\n assistantId++;\n turn.endTime = nextEvent.timestamp;\n \n // Create assistant turn with its tools\n const assistantTurn = {\n id: `assistant-${assistantId}`,\n startTime: nextEvent.timestamp,\n endTime: nextEvent.timestamp,\n tools: []\n };\n\n // Extract tools from this assistant message\n if (nextEvent.data.tools && Array.isArray(nextEvent.data.tools)) {\n for (const tool of nextEvent.data.tools) {\n assistantTurn.tools.push({\n name: tool.name,\n startTime: nextEvent.timestamp,\n endTime: nextEvent.timestamp, // Pi-Mono doesn't have separate end time\n status: tool.status || 'completed',\n input: tool.input,\n result: tool.result\n });\n }\n }\n\n turn.assistantTurns.push(assistantTurn);\n }\n \n j++;\n }\n\n turns.push(turn);\n }\n }\n\n // Calculate summary statistics\n const totalTools = turns.reduce((sum, t) => \n sum + t.assistantTurns.reduce((aSum, at) => aSum + at.tools.length, 0), 0\n );\n\n const summary = {\n totalTurns: turns.length,\n totalAssistantTurns: turns.reduce((sum, t) => sum + t.assistantTurns.length, 0),\n totalTools,\n totalSubagents: 0,\n startTime: events[0]?.timestamp,\n endTime: events[events.length - 1]?.timestamp\n };\n\n return { turns, summary };\n }\n\n /**\n * Build Copilot timeline from normalized events\n * Copilot has explicit turn_start/complete and tool.execution_start/complete\n * @private\n */\n _buildCopilotTimeline(events, _session) {\n const turns = [];\n let currentTurn = null;\n let turnId = 0;\n\n for (const event of events) {\n if (event.type === 'assistant.turn_start') {\n turnId++;\n currentTurn = {\n id: `turn-${turnId}`,\n type: 'assistant-turn',\n message: event.data.message || '',\n startTime: event.timestamp,\n endTime: null,\n tools: [],\n subagents: []\n };\n } else if (event.type === 'assistant.turn_complete' && currentTurn) {\n currentTurn.endTime = event.timestamp;\n turns.push(currentTurn);\n currentTurn = null;\n } else if (event.type === 'tool.execution_start' && currentTurn) {\n const tool = {\n name: event.data.tool || event.data.name,\n startTime: event.timestamp,\n endTime: null,\n status: 'running',\n input: event.data.arguments || event.data.input\n };\n currentTurn.tools.push(tool);\n } else if (event.type === 'tool.execution_complete' && currentTurn) {\n // Find matching tool by name and update\n const tool = currentTurn.tools.find(t => \n t.name === (event.data.tool || event.data.name) && !t.endTime\n );\n if (tool) {\n tool.endTime = event.timestamp;\n tool.status = (event.data?.error || event.data?.isError) ? 'error' : 'completed';\n tool.result = event.data?.result;\n }\n }\n }\n\n // Close any open turn\n if (currentTurn) {\n currentTurn.endTime = events[events.length - 1]?.timestamp;\n turns.push(currentTurn);\n }\n\n const summary = {\n totalTurns: turns.length,\n totalTools: turns.reduce((sum, t) => sum + t.tools.length, 0),\n totalSubagents: 0,\n startTime: events[0]?.timestamp,\n endTime: events[events.length - 1]?.timestamp\n };\n\n return { turns, summary };\n }\n\n /**\n * Build Claude timeline from normalized events\n * Claude has tool_use/tool_result embedded in messages\n * @private\n */\n _buildClaudeTimeline(events, session) {\n // Similar to Pi-Mono but may have different patterns\n // For now, delegate to Pi-Mono logic (can refine later)\n return this._buildPiMonoTimeline(events, session);\n }\n\n /**\n * Expand Pi-Mono format (assistant.message with embedded tools) to Copilot-compatible event stream\n * This allows time-analyze.ejs to work with Pi-Mono sessions without modification\n * @private\n * @param {Array} events - Normalized Pi-Mono events\n * @returns {Array} Expanded events in Copilot format\n */\n _expandPiMonoToCopilotFormat(events) {\n const expanded = [];\n let turnCounter = 0;\n let toolCallCounter = 0;\n\n for (let i = 0; i < events.length; i++) {\n const event = events[i];\n\n // Keep non-message events as-is\n if (event.type !== 'user.message' && event.type !== 'assistant.message') {\n expanded.push(event);\n continue;\n }\n\n // Track user messages for turn grouping\n if (event.type === 'user.message') {\n turnCounter++;\n expanded.push({\n ...event,\n _turnNumber: turnCounter\n });\n continue;\n }\n\n // Expand assistant.message to turn_start + tool events + turn_complete\n if (event.type === 'assistant.message') {\n const tools = event.data.tools || [];\n const turnStartTime = event.timestamp;\n const turnId = `pi-turn-${i}`;\n\n // Insert assistant.turn_start\n expanded.push({\n type: 'assistant.turn_start',\n id: `${turnId}-start`,\n timestamp: turnStartTime,\n parentId: event.parentId,\n data: {\n message: event.data.message || '',\n model: event.data.model,\n tools: tools.length > 0 ? tools : undefined\n },\n _synthetic: true,\n _turnNumber: turnCounter,\n _fileIndex: event._fileIndex\n });\n\n // Keep the original assistant.message event\n expanded.push({\n ...event,\n _fileIndex: event._fileIndex + 0.05\n });\n\n // Insert tool.execution_start and tool.execution_complete for each tool\n tools.forEach((tool, idx) => {\n const toolCallId = `pi-tool-${toolCallCounter++}`;\n const toolStartTime = turnStartTime; // Pi-Mono doesn't have separate timestamps\n const toolEndTime = turnStartTime; // Same timestamp\n\n expanded.push({\n type: 'tool.execution_start',\n id: `${toolCallId}-start`,\n timestamp: toolStartTime,\n parentId: turnId,\n data: {\n toolCallId,\n toolName: tool.name,\n tool: tool.name, // Alias for compatibility\n arguments: tool.input || {}\n },\n _synthetic: true,\n _fileIndex: event._fileIndex + 0.1 + (idx * 0.01)\n });\n\n expanded.push({\n type: 'tool.execution_complete',\n id: `${toolCallId}-complete`,\n timestamp: toolEndTime,\n parentId: toolCallId,\n data: {\n toolCallId,\n toolName: tool.name,\n tool: tool.name, // Alias\n result: tool.result,\n error: tool.status === 'error' ? 'Tool execution failed' : null,\n isError: tool.status === 'error'\n },\n _synthetic: true,\n _fileIndex: event._fileIndex + 0.15 + (idx * 0.01)\n });\n });\n\n // Insert assistant.turn_complete\n expanded.push({\n type: 'assistant.turn_complete',\n id: `${turnId}-complete`,\n timestamp: event.timestamp,\n parentId: turnId,\n data: {\n message: event.data.message || ''\n },\n _synthetic: true,\n _turnNumber: turnCounter,\n _fileIndex: event._fileIndex + 0.9\n });\n }\n }\n\n return expanded;\n }\n\n /**\n * Expand Copilot format (user/assistant) to timeline format with turn_start/complete\n * @private\n /**\n * Convert VSCode tool.invocation events into assistant.message events with data.tools,\n * so they render using the same frontend tool-list component.\n * Groups consecutive tool.invocation events under a single assistant.message when possible.\n */\n _expandVsCodeEvents(events) {\n const result = [];\n let pendingTools = [];\n let pendingParentId = null;\n let pendingTs = null;\n let pendingIdx = 0;\n let pendingSubAgentId = null;\n let pendingSubAgentName = null;\n\n const flushTools = () => {\n if (pendingTools.length === 0) return;\n result.push({\n type: 'assistant.message',\n id: `vscode-tools-${pendingIdx}`,\n timestamp: pendingTs,\n parentId: pendingParentId,\n data: {\n message: '',\n content: '',\n tools: pendingTools,\n subAgentId: pendingSubAgentId,\n subAgentName: pendingSubAgentName,\n },\n _synthetic: true,\n });\n pendingTools = [];\n pendingSubAgentId = null;\n pendingSubAgentName = null;\n };\n\n for (let i = 0; i < events.length; i++) {\n const ev = events[i];\n if (ev.type === 'tool.invocation') {\n const evSubAgentId = ev.data?.subAgentId || null;\n // Flush if switching to a different subagent's tool group\n if (pendingTools.length > 0 && evSubAgentId !== pendingSubAgentId) {\n flushTools();\n }\n if (pendingTools.length === 0) {\n pendingParentId = ev.parentId;\n pendingTs = ev.timestamp;\n pendingIdx = i;\n pendingSubAgentId = evSubAgentId;\n pendingSubAgentName = ev.data?.subAgentName || null;\n }\n if (ev.data?.tool) pendingTools.push(ev.data.tool);\n } else {\n flushTools();\n result.push(ev);\n }\n }\n flushTools();\n return result;\n }\n\n /**\n * @param {Array} events - Normalized Copilot events\n * @returns {Array} Expanded events with turn_start/complete\n */\n _expandCopilotToTimelineFormat(events) {\n const expanded = [];\n let turnCounter = 0;\n\n for (let i = 0; i < events.length; i++) {\n const event = events[i];\n\n // Convert user \u2192 user.message\n if (event.type === 'user') {\n turnCounter++;\n expanded.push({\n ...event,\n type: 'user.message',\n _turnNumber: turnCounter,\n data: {\n ...event.data,\n message: event.message?.content || event.data?.message || ''\n }\n });\n continue;\n }\n\n // Convert assistant \u2192 turn_start + (optional tools) + turn_complete\n if (event.type === 'assistant') {\n const assistantId = event.uuid || `copilot-assistant-${i}`;\n const timestamp = event.timestamp;\n\n // Extract message content\n let messageText = '';\n if (event.message?.content) {\n if (Array.isArray(event.message.content)) {\n // Claude-style content array\n messageText = event.message.content\n .filter(block => block && block.type === 'text')\n .map(block => block.text)\n .join('\\n');\n } else if (typeof event.message.content === 'string') {\n // Simple string content\n messageText = event.message.content;\n }\n } else if (event.data?.message) {\n messageText = event.data.message;\n }\n\n // Insert assistant.turn_start\n expanded.push({\n type: 'assistant.turn_start',\n id: `${assistantId}-start`,\n uuid: event.uuid,\n timestamp,\n parentId: event.parentId,\n data: {\n message: messageText,\n turnId: assistantId\n },\n _synthetic: true,\n _turnNumber: turnCounter,\n _fileIndex: event._fileIndex\n });\n\n // Insert assistant.message (for Timeline rendering)\n expanded.push({\n type: 'assistant.message',\n id: assistantId,\n uuid: event.uuid,\n timestamp,\n parentId: event.parentId,\n data: {\n message: messageText,\n tools: event.data?.tools || []\n },\n _synthetic: true,\n _turnNumber: turnCounter,\n _fileIndex: event._fileIndex + 0.05\n });\n\n // Insert tool events if they exist (already matched by _matchCopilotToolCalls)\n // Tools are attached to assistant event as data.tools array\n if (event.data?.tools && event.data.tools.length > 0) {\n event.data.tools.forEach((tool, idx) => {\n // tool.execution_start\n if (tool.start) {\n expanded.push({\n ...tool.start,\n _fileIndex: event._fileIndex + 0.1 + (idx * 0.02)\n });\n }\n \n // tool.execution_complete\n if (tool.complete) {\n expanded.push({\n ...tool.complete,\n _fileIndex: event._fileIndex + 0.15 + (idx * 0.02)\n });\n }\n });\n }\n\n // Insert assistant.turn_complete\n expanded.push({\n type: 'assistant.turn_complete',\n id: `${assistantId}-complete`,\n uuid: event.uuid,\n timestamp,\n parentId: assistantId,\n data: {\n message: messageText\n },\n _synthetic: true,\n _turnNumber: turnCounter,\n _fileIndex: event._fileIndex + 0.9\n });\n\n continue;\n }\n\n // Handle already-expanded events (vscode transcripts come pre-expanded)\n if (event.type === 'user.message') {\n turnCounter++;\n expanded.push({\n ...event,\n _turnNumber: turnCounter,\n data: {\n ...event.data,\n message: event.data?.content || event.data?.message || ''\n }\n });\n continue;\n }\n\n // Keep other events as-is, with turn number\n expanded.push({\n ...event,\n _turnNumber: turnCounter\n });\n }\n\n return expanded;\n }\n\n /**\n * @private\n * @param {Array} events - Normalized Claude events\n * @returns {Array} Expanded events with turn_start/complete\n */\n /**\n * Synthesize subagent.started / subagent.completed events from runSubagent\n * tool execution pairs when native boundary events are absent.\n * Works on already-expanded event arrays (post-_expandCopilotToTimelineFormat).\n * @private\n */\n _synthesizeSubagentBoundaryEvents(events) {\n if (events.some(e => e.type === 'subagent.started')) {\n return events; // native events exist, skip\n }\n\n // Collect runSubagent toolCallIds from start events\n const runSubagentIds = new Map(); // toolCallId \u2192 start event\n for (const ev of events) {\n if (ev.type === 'tool.execution_start' && ev.data?.toolName === 'runSubagent') {\n runSubagentIds.set(ev.data.toolCallId, ev);\n }\n }\n\n if (runSubagentIds.size === 0) return events;\n\n const synthetic = [];\n for (const ev of events) {\n if (ev.type === 'tool.execution_start' && runSubagentIds.has(ev.data?.toolCallId)) {\n const tcid = ev.data.toolCallId;\n let args = ev.data.arguments;\n if (typeof args === 'string') {\n try { args = JSON.parse(args); } catch (_e) { args = {}; }\n }\n args = args || {};\n const agentName = args.description || args.agentName || args.name || 'SubAgent';\n synthetic.push({\n type: 'subagent.started',\n id: `${tcid}-synth-start`,\n timestamp: ev.timestamp,\n data: {\n toolCallId: tcid,\n agentName,\n agentDisplayName: agentName,\n agentDescription: args.description || ''\n },\n _synthetic: true,\n _fileIndex: (ev._fileIndex || 0) - 0.001\n });\n } else if (ev.type === 'tool.execution_complete' && runSubagentIds.has(ev.data?.toolCallId)) {\n const tcid = ev.data.toolCallId;\n synthetic.push({\n type: 'subagent.completed',\n id: `${tcid}-synth-end`,\n timestamp: ev.timestamp,\n data: {\n toolCallId: tcid,\n result: 'Sub-agent completed'\n },\n _synthetic: true,\n _fileIndex: (ev._fileIndex || 0) + 0.001\n });\n }\n }\n\n if (synthetic.length === 0) return events;\n\n const merged = events.concat(synthetic);\n merged.sort((a, b) => {\n const ta = new Date(a.timestamp || 0).getTime();\n const tb = new Date(b.timestamp || 0).getTime();\n if (ta !== tb) return ta - tb;\n return (a._fileIndex || 0) - (b._fileIndex || 0);\n });\n return merged;\n }\n\n _expandClaudeToTimelineFormat(events) {\n const expanded = [];\n let turnCounter = 0;\n const relatedUsageEventsByAssistantUuid = this._indexClaudeRelatedUsageEvents(events);\n\n for (let i = 0; i < events.length; i++) {\n const event = events[i];\n\n // Convert user \u2192 user.message\n if (event.type === 'user') {\n // Skip tool-result-wrapper events \u2014 their usage data is already captured\n // via _relatedUsageEvents on assistant.turn_complete. Including them here\n // would cause double-counting in _extractClaudeUsageData.\n if (event._isToolResultWrapper) {\n continue;\n }\n turnCounter++;\n expanded.push({\n ...event,\n type: 'user.message',\n _turnNumber: turnCounter,\n data: {\n ...event.data,\n message: event.data?.message || ''\n }\n });\n continue;\n }\n\n // Convert assistant \u2192 turn_start + (optional tools) + turn_complete\n if (event.type === 'assistant') {\n const assistantId = event.id || `claude-assistant-${i}`;\n const timestamp = event.timestamp;\n const relatedUsageEvents = event.uuid\n ? (relatedUsageEventsByAssistantUuid.get(event.uuid) || [])\n : [];\n\n // Extract message content (already normalized in _normalizeEvent)\n const messageText = event.data?.message || '';\n\n // Insert assistant.turn_start\n expanded.push({\n type: 'assistant.turn_start',\n id: `${assistantId}-start`,\n uuid: event.uuid,\n timestamp,\n parentId: event.parentId,\n data: {\n message: messageText,\n turnId: assistantId\n },\n _synthetic: true,\n _turnNumber: turnCounter,\n _fileIndex: event._fileIndex\n });\n\n // Insert assistant.message (for Timeline rendering)\n expanded.push({\n type: 'assistant.message',\n id: assistantId,\n uuid: event.uuid,\n timestamp,\n parentId: event.parentId,\n model: event.model,\n usage: event.usage,\n data: {\n message: messageText,\n tools: event.data?.tools || []\n },\n _synthetic: true,\n _turnNumber: turnCounter,\n _fileIndex: event._fileIndex + 0.05\n });\n\n // Insert tool events if they exist (already matched by _matchClaudeToolResults)\n if (event.data?.tools && event.data.tools.length > 0) {\n event.data.tools.forEach((tool, idx) => {\n if (tool.type === 'tool_use') {\n // Tool call\n expanded.push({\n type: 'tool.execution_start',\n id: `${tool.id}-start`,\n timestamp,\n data: {\n toolCallId: tool.id,\n toolName: tool.name,\n arguments: tool.input || {}\n },\n _synthetic: true,\n _fileIndex: event._fileIndex + 0.1 + (idx * 0.02)\n });\n\n // Tool result (if matched)\n if (tool.result) {\n expanded.push({\n type: 'tool.execution_complete',\n id: `${tool.id}-complete`,\n timestamp,\n data: {\n toolCallId: tool.id,\n toolName: tool.name,\n result: tool.result,\n isError: false\n },\n _synthetic: true,\n _fileIndex: event._fileIndex + 0.15 + (idx * 0.02)\n });\n }\n }\n });\n }\n\n // Insert assistant.turn_complete\n expanded.push({\n type: 'assistant.turn_complete',\n id: `${assistantId}-complete`,\n uuid: event.uuid,\n timestamp,\n parentId: assistantId,\n model: event.model,\n _relatedUsageEvents: relatedUsageEvents.map(usageEvent => ({\n uuid: usageEvent.uuid,\n parentUuid: usageEvent.parentUuid,\n sourceToolAssistantUUID: usageEvent.sourceToolAssistantUUID,\n usage: this._getClaudeUsagePayload(usageEvent),\n totalTokens: this._getClaudeEventTotalTokens(usageEvent),\n totalDurationMs: this._getClaudeEventDurationMs(usageEvent)\n })),\n data: {\n message: messageText\n },\n _synthetic: true,\n _turnNumber: turnCounter,\n _fileIndex: event._fileIndex + 0.9\n });\n\n continue;\n }\n\n // Keep other events as-is\n expanded.push(event);\n }\n\n return expanded;\n }\n\n /**\n * Expand VSCode format to timeline format with tool.execution_start/complete events\n * VSCode events already have assistant.message events with data.tools arrays (from _expandVsCodeEvents)\n * This method generates tool.execution_start/complete events for the time-analyze page\n * @private\n * @param {Array} events - VSCode events with assistant.message events containing data.tools\n * @returns {Array} Expanded events with tool execution events\n */\n _expandVsCodeToTimelineFormat(events) {\n const expanded = [];\n\n for (let i = 0; i < events.length; i++) {\n const event = events[i];\n\n // Keep the original event\n expanded.push(event);\n\n // Generate tool.execution_start and tool.execution_complete for assistant.message events with tools\n if (event.type === 'assistant.message' && event.data?.tools && event.data.tools.length > 0) {\n event.data.tools.forEach((tool, idx) => {\n // Skip if tool doesn't have required fields\n if (!tool.id || !tool.name) return;\n\n const toolStartTime = tool.startTime || event.timestamp;\n const toolEndTime = tool.endTime || event.timestamp;\n\n // Generate tool.execution_start event\n expanded.push({\n type: 'tool.execution_start',\n id: `${tool.id}-start`,\n timestamp: toolStartTime,\n parentId: event.id,\n data: {\n toolCallId: tool.id,\n toolName: tool.name,\n tool: tool.name, // Alias for compatibility\n arguments: tool.input || {}\n },\n _synthetic: true,\n _fileIndex: event._fileIndex ? event._fileIndex + 0.1 + (idx * 0.02) : undefined\n });\n\n // Generate tool.execution_complete event\n expanded.push({\n type: 'tool.execution_complete',\n id: `${tool.id}-complete`,\n timestamp: toolEndTime,\n parentId: tool.id,\n data: {\n toolCallId: tool.id,\n toolName: tool.name,\n tool: tool.name, // Alias\n result: tool.result || null,\n error: tool.error || (tool.status === 'error' ? 'Tool execution failed' : null),\n isError: tool.status === 'error'\n },\n _synthetic: true,\n _fileIndex: event._fileIndex ? event._fileIndex + 0.15 + (idx * 0.02) : undefined\n });\n });\n }\n }\n\n return expanded;\n }\n\n _getSourceAdapter(source) {\n const registry = this.sessionRepository.registry || require('../adapters').registry;\n return registry?.get ? registry.get(source) : null;\n }\n}\n\nmodule.exports = SessionService;\n\n", "const fs = require('fs').promises;\nconst path = require('path');\nconst os = require('os');\n\n// Single module-level promise tail to serialize tag writes across instances/calls.\nlet _writeTail = Promise.resolve();\nfunction _serializeWrite(fn) {\n const next = _writeTail.then(fn, fn);\n // Swallow rejection on the tail so one failed write doesn't poison subsequent ones.\n _writeTail = next.catch(() => {});\n return next;\n}\n\n/**\n * Service for managing session tags\n * - Per-session tags: stored in {session.directory}/tags.json as [\"tag1\", \"tag2\"]\n * - Global known tags: stored in ~/.session-viewer/known-tags.json as [\"tag1\", \"tag2\", ...]\n */\nclass TagService {\n constructor() {\n this.knownTagsDir = path.join(os.homedir(), '.session-viewer');\n this.knownTagsFilePath = path.join(this.knownTagsDir, 'known-tags.json');\n }\n\n /**\n * Ensure known-tags directory and file exist\n */\n async ensureKnownTagsFile() {\n try {\n await fs.access(this.knownTagsFilePath);\n } catch (err) {\n // File doesn't exist, create directory and empty array\n await fs.mkdir(this.knownTagsDir, { recursive: true });\n await fs.writeFile(this.knownTagsFilePath, JSON.stringify([]), 'utf8');\n }\n }\n\n /**\n * Read known tags from global file\n * @returns {Promise<string[]>} Array of known tags\n */\n async readKnownTagsFile() {\n await this.ensureKnownTagsFile();\n try {\n const content = await fs.readFile(this.knownTagsFilePath, 'utf8');\n const parsed = JSON.parse(content);\n return Array.isArray(parsed) ? parsed : [];\n } catch (err) {\n console.error('Error reading known tags file:', err);\n return [];\n }\n }\n\n /**\n * Write known tags to global file\n * @param {string[]} tags - Array of known tags\n */\n async writeKnownTagsFile(tags) {\n await this.ensureKnownTagsFile();\n await fs.writeFile(this.knownTagsFilePath, JSON.stringify(tags, null, 2), 'utf8');\n }\n\n /**\n * Get tags file path for a session\n * @param {Session} session - Session object with directory field\n * @returns {string} Path to tags.json\n */\n getSessionTagsFilePath(session) {\n // File-based sessions (e.g. Claude .jsonl): per-file tags to avoid sharing\n if (session.filePath) {\n const dir = path.dirname(session.filePath);\n const base = path.basename(session.filePath, path.extname(session.filePath));\n return path.join(dir, `${base}.tags.json`);\n }\n // Directory-based sessions (e.g. Copilot CLI): tags.json inside session dir\n if (session.directory) {\n return path.join(session.directory, 'tags.json');\n }\n // Fallback: store in central location by session id\n return path.join(this.knownTagsDir, 'session-tags', `${session.id}.tags.json`);\n }\n\n /**\n * Normalize tag name (lowercase, trim, max 30 chars)\n * @param {string} tag - Tag name\n * @returns {string} Normalized tag\n */\n normalizeTag(tag) {\n return tag.trim().toLowerCase().substring(0, 30);\n }\n\n /**\n * Get all known tags for autocomplete\n * @returns {Promise<string[]>} Array of unique tags\n */\n async getAllKnownTags() {\n const tags = await this.readKnownTagsFile();\n return tags.sort();\n }\n\n /**\n * Get tags for a specific session\n * @param {Session} session - Session object with directory field\n * @returns {Promise<string[]>} Array of tags\n */\n async getSessionTags(session) {\n const tagsFilePath = this.getSessionTagsFilePath(session);\n\n try {\n await fs.access(tagsFilePath);\n const content = await fs.readFile(tagsFilePath, 'utf8');\n return JSON.parse(content);\n } catch (err) {\n // File doesn't exist or can't be read, return empty array\n return [];\n }\n }\n\n /**\n * Set tags for a specific session\n * @param {Session} session - Session object with directory field\n * @param {string[]} tags - Array of tag names\n * @returns {Promise<string[]>} Normalized and saved tags\n */\n async setSessionTags(session, tags) {\n return _serializeWrite(() => this._setSessionTagsInternal(session, tags));\n }\n\n async _setSessionTagsInternal(session, tags) {\n if (!Array.isArray(tags)) {\n throw new Error('Tags must be an array');\n }\n\n // Normalize tags (lowercase, trim, max 30 chars)\n const normalizedTags = tags\n .map(tag => this.normalizeTag(tag))\n .filter(tag => tag.length > 0)\n .filter((tag, index, self) => self.indexOf(tag) === index); // Remove duplicates\n\n // Enforce max 10 tags per session\n if (normalizedTags.length > 10) {\n throw new Error('Maximum 10 tags per session');\n }\n\n const tagsFilePath = this.getSessionTagsFilePath(session);\n\n if (normalizedTags.length === 0) {\n // Remove tags file if no tags\n try {\n await fs.unlink(tagsFilePath);\n } catch (err) {\n // File doesn't exist, ignore\n }\n } else {\n // Ensure directory exists for tags file\n await fs.mkdir(path.dirname(tagsFilePath), { recursive: true });\n // Write tags to session directory\n await fs.writeFile(tagsFilePath, JSON.stringify(normalizedTags, null, 2), 'utf8');\n\n // Update known tags (append and deduplicate)\n await this.updateKnownTags(normalizedTags);\n }\n\n return normalizedTags;\n }\n\n /**\n * Update known tags by appending new tags and deduplicating\n * @param {string[]} newTags - New tags to add to known tags\n */\n async updateKnownTags(newTags) {\n const knownTags = await this.readKnownTagsFile();\n const allTags = [...knownTags, ...newTags];\n const uniqueTags = [...new Set(allTags)];\n await this.writeKnownTagsFile(uniqueTags);\n }\n\n /**\n * Add tags to a session (merge with existing)\n * @param {Session} session - Session object with directory field\n * @param {string[]} newTags - Tags to add\n * @returns {Promise<string[]>} Updated tags array\n */\n async addSessionTags(session, newTags) {\n const existingTags = await this.getSessionTags(session);\n const mergedTags = [...existingTags, ...newTags];\n return await this.setSessionTags(session, mergedTags);\n }\n\n /**\n * Remove tags from a session\n * @param {Session} session - Session object with directory field\n * @param {string[]} tagsToRemove - Tags to remove\n * @returns {Promise<string[]>} Updated tags array\n */\n async removeSessionTags(session, tagsToRemove) {\n const existingTags = await this.getSessionTags(session);\n const normalizedToRemove = tagsToRemove.map(tag => this.normalizeTag(tag));\n const updatedTags = existingTags.filter(tag => !normalizedToRemove.includes(tag));\n return await this.setSessionTags(session, updatedTags);\n }\n\n /**\n * Get tags for multiple sessions (batch)\n * @param {Session[]} sessions - Array of session objects\n * @returns {Promise<Object>} Map of sessionId -> tags array\n */\n async getMultipleSessionTags(sessions) {\n const result = {};\n\n for (const session of sessions) {\n result[session.id] = await this.getSessionTags(session);\n }\n\n return result;\n }\n}\n\nmodule.exports = TagService;\n", "const fs = require('fs').promises;\nconst path = require('path');\nconst os = require('os');\nconst crypto = require('crypto');\n\n// Single module-level promise tail to serialize writes across instances/calls.\nlet _writeTail = Promise.resolve();\nfunction _serializeWrite(fn) {\n const next = _writeTail.then(fn, fn);\n _writeTail = next.catch(() => {});\n return next;\n}\n\n/**\n * Service for managing user-registered custom session directories.\n * Storage: { \"<uuid-v4>\": { id, label, path, addedAt } }\n */\nclass DirRegistryService {\n constructor(registryPath) {\n this.registryPath = registryPath\n || process.env.CUSTOM_DIRS_REGISTRY\n || path.join(os.homedir(), '.config', 'copilot-session-viewer', 'registered-dirs.json');\n }\n\n async _load() {\n try {\n const content = await fs.readFile(this.registryPath, 'utf8');\n const parsed = JSON.parse(content);\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return {};\n }\n return parsed;\n } catch (err) {\n if (err.code === 'ENOENT') return {};\n // Corrupt JSON or unreadable \u2014 coerce to empty per spec\n return {};\n }\n }\n\n async _save(data) {\n const dir = path.dirname(this.registryPath);\n await fs.mkdir(dir, { recursive: true });\n const tmp = `${this.registryPath}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n const payload = JSON.stringify(data, null, 2);\n await fs.writeFile(tmp, payload, { encoding: 'utf8', mode: 0o600 });\n try {\n await fs.chmod(tmp, 0o600);\n } catch {\n // best effort\n }\n await fs.rename(tmp, this.registryPath);\n try {\n await fs.chmod(this.registryPath, 0o600);\n } catch {\n // best effort\n }\n }\n\n _expand(rawPath) {\n if (typeof rawPath !== 'string' || rawPath.length === 0) return rawPath;\n if (rawPath === '~') return os.homedir();\n if (rawPath.startsWith('~/')) return path.join(os.homedir(), rawPath.slice(2));\n return rawPath;\n }\n\n async register(rawPath, label) {\n if (!rawPath || typeof rawPath !== 'string') {\n throw new Error('Path is required');\n }\n\n const expanded = this._expand(rawPath);\n\n let stat;\n try {\n stat = await fs.stat(expanded);\n } catch (err) {\n throw new Error(`Path does not exist: ${rawPath}`, { cause: err });\n }\n if (!stat.isDirectory()) {\n throw new Error(`Path is not a directory: ${rawPath}`);\n }\n\n let resolved;\n try {\n resolved = await fs.realpath(expanded);\n } catch (err) {\n throw new Error(`Cannot resolve path: ${rawPath}`, { cause: err });\n }\n\n const finalLabel = (label && String(label).trim()) || path.basename(resolved);\n\n const entry = {\n id: crypto.randomUUID(),\n label: finalLabel,\n path: resolved,\n addedAt: new Date().toISOString()\n };\n\n return _serializeWrite(async () => {\n const data = await this._load();\n data[entry.id] = entry;\n await this._save(data);\n return entry;\n });\n }\n\n async getById(id) {\n if (!id || typeof id !== 'string') return null;\n const data = await this._load();\n return Object.prototype.hasOwnProperty.call(data, id) ? data[id] : null;\n }\n\n async getAll() {\n const data = await this._load();\n return Object.values(data).sort(\n (a, b) => new Date(b.addedAt) - new Date(a.addedAt)\n );\n }\n\n async remove(id) {\n return _serializeWrite(async () => {\n const data = await this._load();\n if (!Object.prototype.hasOwnProperty.call(data, id)) return false;\n delete data[id];\n await this._save(data);\n return true;\n });\n }\n}\n\nmodule.exports = DirRegistryService;\n", "const SessionService = require('../services/sessionService');\nconst { isValidSessionId } = require('../utils/helpers');\nconst { resolveSource } = require('../utils/sourceMapping');\nconst { trackEvent } = require('../telemetry');\nconst AdmZip = require('adm-zip');\nconst path = require('path');\nconst fs = require('fs');\nconst crypto = require('crypto');\nconst TagService = require('../services/tagService');\nconst DirRegistryService = require('../services/dirRegistryService');\n\n// Cache of realpath'd source dirs so symlink trickery cannot defeat containment check\nconst _resolvedSourceDirCache = new Map();\nasync function _getResolvedSourceDirs(sources) {\n const out = [];\n for (const s of sources) {\n if (!s || !s.dir) continue;\n if (!_resolvedSourceDirCache.has(s.dir)) {\n try {\n _resolvedSourceDirCache.set(s.dir, await fs.promises.realpath(s.dir));\n } catch {\n _resolvedSourceDirCache.set(s.dir, path.resolve(s.dir));\n }\n }\n out.push(_resolvedSourceDirCache.get(s.dir));\n }\n return out;\n}\n\nclass SessionController {\n constructor(sessionService = null, tagService = null, dirRegistryService = null) {\n this.sessionService = sessionService || new SessionService();\n this.tagService = tagService || new TagService();\n this.dirRegistryService = dirRegistryService || new DirRegistryService();\n }\n\n // \u2500\u2500 Helper to get sessionId from either new or legacy param \u2500\u2500\n _getSessionId(req) {\n return req.params.sessionId || req.params.id;\n }\n\n // Resolve registered dir from req.query.dirId. Returns { dir, error }.\n // If no dirId present, returns { dir: null }. If dirId present but unknown, error.\n async _resolveDirId(req) {\n const dirId = req.query.dirId || null;\n if (!dirId) return { dir: null };\n const entry = await this.dirRegistryService.getById(dirId);\n if (!entry) return { dir: null, error: 'Unknown dirId' };\n return { dir: entry.path };\n }\n\n // API: Get sessions with optional pagination\n async getSessions(req, res) {\n try {\n // New route: source from path param; legacy: source from query\n const sourceParam = req.params.source || null;\n const sourceFilter = sourceParam\n ? resolveSource(sourceParam)\n : (req.query.source || null);\n\n // Registered custom directory scanning via UUID lookup\n const { dir: customDir, error: dirErr } = await this._resolveDirId(req);\n if (dirErr) {\n return res.status(400).json({ error: dirErr });\n }\n if (customDir) {\n const repo = this.sessionService.sessionRepository;\n const sessions = await repo.scanSource({ type: sourceFilter, dir: customDir });\n const sorted = sessions.sort((a, b) => new Date(b.updatedAt) - new Date(a.updatedAt));\n return res.json({\n sessions: sorted,\n hasMore: false,\n totalSessions: sorted.length\n });\n }\n\n const offset = req.query.offset !== undefined ? parseInt(req.query.offset) : null;\n const limit = req.query.limit ? parseInt(req.query.limit) : null;\n const page = req.query.page ? parseInt(req.query.page) : null;\n\n // offset+limit pagination (new API)\n if (offset !== null && limit) {\n if (offset < 0 || limit < 1 || limit > 100) {\n return res.status(400).json({ error: 'Invalid pagination parameters' });\n }\n const pageNum = Math.floor(offset / limit) + 1;\n const paginationData = await this.sessionService.getPaginatedSessions(pageNum, limit, sourceFilter);\n\n trackEvent('SessionListLoaded', {\n offset: offset.toString(),\n limit: limit.toString(),\n totalSessions: paginationData.totalSessions.toString()\n });\n\n res.set({ 'Cache-Control': 'public, max-age=60' });\n res.json({\n sessions: paginationData.sessions,\n hasMore: paginationData.hasNextPage ?? (offset + limit < paginationData.totalSessions),\n totalSessions: paginationData.totalSessions\n });\n } else if (page && limit) {\n // Legacy page+limit pagination\n if (page < 1 || limit < 1 || limit > 100) {\n return res.status(400).json({ error: 'Invalid pagination parameters' });\n }\n const paginationData = await this.sessionService.getPaginatedSessions(page, limit, sourceFilter);\n\n trackEvent('SessionListLoaded', {\n page: page.toString(),\n limit: limit.toString(),\n totalSessions: paginationData.totalSessions.toString()\n });\n\n res.set({ 'Cache-Control': 'public, max-age=60' });\n res.json(paginationData);\n } else if (sourceFilter && limit) {\n // Source-filtered first page (for pill switching)\n const sessions = await this.sessionService.getAllSessions(sourceFilter);\n const sliced = sessions.slice(0, limit);\n res.set({ 'Cache-Control': 'public, max-age=60' });\n res.json({ sessions: sliced, hasMore: sessions.length > limit, totalSessions: sessions.length });\n } else {\n // Return all sessions for backward compatibility\n const sessions = await this.sessionService.getAllSessions(sourceFilter);\n res.set({ 'Cache-Control': 'public, max-age=300' });\n res.json(sessions);\n }\n } catch (err) {\n console.error('Error loading sessions:', err);\n res.status(500).json({ error: 'Error loading sessions' });\n }\n }\n\n // API: Get session metadata\n async getSessionById(req, res) {\n try {\n const sessionId = this._getSessionId(req);\n if (!isValidSessionId(sessionId)) {\n return res.status(400).json({ error: 'Invalid session ID' });\n }\n const { dir, error: dirErr } = await this._resolveDirId(req);\n if (dirErr) {\n return res.status(400).json({ error: dirErr });\n }\n const session = await this.sessionService.getSessionById(sessionId, dir);\n if (!session) {\n return res.status(404).json({ error: 'Session not found' });\n }\n // Aggregate usage data from events\n try {\n const events = await this.sessionService.getSessionEvents(sessionId, null, dir);\n if (events && events.length > 0) {\n const usage = this.sessionService.extractUsageData(events);\n if (usage) {\n session.usage = usage;\n }\n }\n } catch (usageErr) {\n console.warn('Failed to extract usage data:', usageErr.message);\n }\n trackEvent('SessionViewed', { sessionId, source: session.source || 'unknown' });\n res.json(session);\n } catch (err) {\n console.error('Error loading session:', err);\n res.status(500).json({ error: 'Failed to load session' });\n }\n }\n\n async getSessionEvents(req, res) {\n try {\n const sessionId = this._getSessionId(req);\n\n if (!isValidSessionId(sessionId)) {\n return res.status(400).json({ error: 'Invalid session ID' });\n }\n\n const { dir, error: dirErr } = await this._resolveDirId(req);\n if (dirErr) {\n return res.status(400).json({ error: dirErr });\n }\n const isPaginationRequested = req.query.limit !== undefined || req.query.offset !== undefined;\n\n let limit, offset, result;\n\n if (isPaginationRequested) {\n limit = parseInt(req.query.limit) || 100;\n offset = parseInt(req.query.offset) || 0;\n\n if (limit < 1 || limit > 1000) {\n return res.status(400).json({ error: 'Limit must be between 1 and 1000' });\n }\n if (offset < 0) {\n return res.status(400).json({ error: 'Offset must be non-negative' });\n }\n }\n\n const session = await this.sessionService.sessionRepository.findById(sessionId, dir);\n if (!session) {\n return res.status(404).json({ error: 'Session not found' });\n }\n\n if (isPaginationRequested) {\n result = await this.sessionService.getSessionEvents(sessionId, { limit, offset }, dir);\n } else {\n const events = await this.sessionService.getSessionEvents(sessionId, null, dir);\n result = events;\n }\n\n res.set({\n 'Cache-Control': 'no-store',\n 'Vary': 'Accept-Encoding'\n });\n\n if (isPaginationRequested) {\n res.json({\n events: result.events,\n pagination: {\n total: result.total,\n limit,\n offset,\n hasMore: offset + limit < result.total\n }\n });\n trackEvent('SessionEventsLoaded', { sessionId, source: session.source || 'unknown', eventCount: result.total, paginated: true });\n } else {\n res.json(result);\n trackEvent('SessionEventsLoaded', { sessionId, source: session.source || 'unknown', eventCount: Array.isArray(result) ? result.length : 0, paginated: false });\n }\n } catch (err) {\n console.error('Error loading events:', err);\n res.status(500).json({ error: 'Error loading events' });\n }\n }\n\n // API: Get timeline data (source-agnostic)\n async getTimeline(req, res) {\n try {\n const sessionId = this._getSessionId(req);\n\n if (!isValidSessionId(sessionId)) {\n return res.status(400).json({ error: 'Invalid session ID' });\n }\n\n const session = await this.sessionService.getSessionById(sessionId);\n if (!session) {\n return res.status(404).json({ error: 'Session not found' });\n }\n\n const timeline = await this.sessionService.getTimeline(sessionId);\n\n const etagBase = `${sessionId}-timeline-${session.updatedAt || session.createdAt}`;\n const etag = crypto.createHash('sha256').update(etagBase).digest('hex');\n\n res.set({\n 'ETag': etag,\n 'Cache-Control': 'private, max-age=300',\n 'Vary': 'Accept-Encoding'\n });\n\n trackEvent('TimelineViewed', { sessionId, source: session.source || 'unknown' });\n res.json(timeline);\n } catch (err) {\n console.error('Error loading timeline:', err);\n res.status(500).json({ error: 'Error loading timeline' });\n }\n }\n\n // Export session as zip\n async exportSession(req, res) {\n const sessionId = this._getSessionId(req);\n\n if (!isValidSessionId(sessionId)) {\n return res.status(400).json({ error: 'Invalid session ID' });\n }\n\n try {\n const session = await this.sessionService.sessionRepository.findById(sessionId);\n if (!session) {\n return res.status(404).json({ error: 'Session not found' });\n }\n\n let sessionPath;\n let isDirectory = false;\n\n if (session.directory) {\n try {\n const stats = await fs.promises.stat(session.directory);\n if (stats.isDirectory()) {\n sessionPath = session.directory;\n isDirectory = true;\n }\n } catch {\n // Fall through to filePath\n }\n }\n\n if (!sessionPath && session.filePath) {\n try {\n await fs.promises.access(session.filePath);\n sessionPath = session.filePath;\n } catch {\n // Not accessible\n }\n }\n\n // Legacy source-specific lookup as fallback\n if (!sessionPath) {\n if (session.source === 'copilot') {\n const copilotSource = this.sessionService.sessionRepository.sources.find(s => s.type === 'copilot');\n if (copilotSource) {\n const basePath = path.join(copilotSource.dir, sessionId);\n try {\n const stats = await fs.promises.stat(basePath);\n if (stats.isDirectory()) {\n sessionPath = basePath;\n isDirectory = true;\n } else {\n sessionPath = `${basePath}.jsonl`;\n }\n } catch {\n sessionPath = `${basePath}.jsonl`;\n }\n }\n } else if (session.source === 'claude') {\n const claudeSource = this.sessionService.sessionRepository.sources.find(s => s.type === 'claude');\n if (claudeSource) {\n const projectDirs = await fs.promises.readdir(claudeSource.dir);\n for (const projectDir of projectDirs) {\n const candidatePath = path.join(claudeSource.dir, projectDir, `${sessionId}.jsonl`);\n try {\n await fs.promises.access(candidatePath);\n sessionPath = candidatePath;\n break;\n } catch {\n // Try next project\n }\n }\n }\n } else if (session.source === 'pi-mono') {\n const piMonoSource = this.sessionService.sessionRepository.sources.find(s => s.type === 'pi-mono');\n if (piMonoSource) {\n const files = await fs.promises.readdir(piMonoSource.dir);\n const matchingFile = files.find(f => f.includes(sessionId) && f.endsWith('.jsonl'));\n if (matchingFile) {\n sessionPath = path.join(piMonoSource.dir, matchingFile);\n }\n }\n }\n }\n\n if (!sessionPath) {\n return res.status(404).json({ error: 'Session file not found' });\n }\n\n try {\n await fs.promises.access(sessionPath);\n } catch {\n return res.status(404).json({ error: 'Session file not accessible' });\n }\n\n // Resolve symlinks and verify path is within expected source directories\n const resolvedPath = await fs.promises.realpath(sessionPath);\n const sourceDirs = await _getResolvedSourceDirs(this.sessionService.sessionRepository.sources);\n const isWithinSource = sourceDirs.some(dir => {\n const rel = path.relative(dir, resolvedPath);\n return rel !== '' ? !rel.startsWith('..') && !path.isAbsolute(rel) : true;\n });\n if (!isWithinSource) {\n return res.status(403).json({ error: 'Access denied: path outside source directories' });\n }\n\n const zip = new AdmZip();\n\n if (isDirectory) {\n zip.addLocalFolder(sessionPath, sessionId);\n } else {\n const fileName = path.basename(sessionPath);\n zip.addLocalFile(sessionPath, '', fileName);\n\n const tagsFilePath = this.tagService.getSessionTagsFilePath(session);\n try {\n await fs.promises.access(tagsFilePath);\n zip.addLocalFile(tagsFilePath, '', path.basename(tagsFilePath));\n } catch {\n // No tags file, skip\n }\n }\n\n const zipBuffer = zip.toBuffer();\n res.setHeader('Content-Type', 'application/zip');\n res.setHeader('Content-Disposition', `attachment; filename=\"session-${sessionId}.zip\"`);\n\n trackEvent('SessionExported', { sessionId });\n\n res.send(zipBuffer);\n } catch (err) {\n console.error('Error exporting session:', err);\n res.status(500).json({ error: 'Error exporting session' });\n }\n }\n\n}\n\nmodule.exports = SessionController;\n", "/**\n * Process Manager - Track and cleanup spawned processes\n */\n\nclass ProcessManager {\n constructor() {\n this.activeProcesses = new Set();\n this.isShuttingDown = false;\n this._setupCleanupHandlers();\n }\n\n /**\n * Register a new process for tracking\n * @param {ChildProcess} process - The spawned process\n * @param {Object} metadata - Optional metadata for logging\n */\n register(process, metadata = {}) {\n const processInfo = { process, metadata, startTime: Date.now() };\n this.activeProcesses.add(processInfo);\n \n process.on('exit', () => {\n this.activeProcesses.delete(processInfo);\n const duration = Date.now() - processInfo.startTime;\n console.log(`\uD83D\uDD04 Process exited (${metadata.name || 'unknown'}): ${duration}ms`);\n });\n \n return processInfo;\n }\n\n /**\n * Kill all active processes\n */\n killAll() {\n console.log(`\uD83D\uDED1 Killing ${this.activeProcesses.size} active processes...`);\n \n for (const { process, metadata } of this.activeProcesses) {\n try {\n if (!process.killed) {\n process.kill('SIGTERM');\n console.log(` \u2713 Killed ${metadata.name || process.pid}`);\n }\n } catch (err) {\n console.error(` \u2717 Failed to kill ${metadata.name || process.pid}:`, err.message);\n }\n }\n \n this.activeProcesses.clear();\n }\n\n /**\n * Get count of active processes\n */\n getActiveCount() {\n return this.activeProcesses.size;\n }\n\n /**\n * Setup cleanup handlers for graceful shutdown\n */\n _setupCleanupHandlers() {\n const cleanup = (signal, exitCode = 0) => {\n if (this.isShuttingDown) return;\n this.isShuttingDown = true;\n \n console.log(`\\n\uD83D\uDCDB Received ${signal}, shutting down gracefully...`);\n this.killAll();\n \n // Give processes time to exit\n setTimeout(() => {\n process.exit(exitCode);\n }, 1000);\n };\n\n process.on('SIGTERM', () => cleanup('SIGTERM', 0));\n process.on('SIGINT', () => cleanup('SIGINT', 0));\n \n // Handle uncaught errors with error exit code\n process.on('uncaughtException', (err) => {\n console.error('\uD83D\uDCA5 Uncaught exception:', err);\n cleanup('uncaughtException', 1);\n });\n\n process.on('unhandledRejection', (reason) => {\n console.error('\uD83D\uDCA5 Unhandled rejection:', reason);\n cleanup('unhandledRejection', 1);\n });\n }\n}\n\nconst PROCESS_MANAGER_SINGLETON_KEY = '__copilotSessionViewerProcessManager';\n\nif (!globalThis[PROCESS_MANAGER_SINGLETON_KEY]) {\n globalThis[PROCESS_MANAGER_SINGLETON_KEY] = new ProcessManager();\n}\n\nmodule.exports = globalThis[PROCESS_MANAGER_SINGLETON_KEY];\n", "/**\n * Insight Generation Service\n * Handles session insight report generation with atomic operations\n */\n\nconst fs = require('fs').promises;\nconst fsSync = require('fs');\nconst path = require('path');\nconst os = require('os');\nconst { spawn } = require('child_process');\nconst config = require('../config');\nconst processManager = require('../utils/processManager');\n\nclass InsightService {\n constructor() {\n // No longer needs session directories - paths are passed directly\n }\n\n /**\n * Get CLI tool configuration based on session source\n * @private\n */\n _getToolConfig(source, sessionPath) {\n const configs = {\n copilot: {\n name: 'Copilot',\n cli: 'copilot',\n args: (tmpDir, prompt) => ['--config-dir', tmpDir, '--yolo', '-p', prompt],\n cwd: sessionPath\n },\n vscode: {\n name: 'Copilot',\n cli: 'copilot',\n args: (tmpDir, prompt) => ['--config-dir', tmpDir, '--yolo', '-p', prompt],\n cwd: sessionPath\n },\n claude: {\n name: 'Claude Code',\n cli: 'claude',\n args: (_tmpDir, prompt) => ['-p', prompt, '--allowedTools', 'Read', '--max-turns', '10'],\n cwd: sessionPath\n },\n 'pi-mono': {\n name: 'Pi',\n cli: 'pi',\n args: (_tmpDir, prompt) => ['-p', prompt],\n cwd: sessionPath\n }\n };\n\n return configs[source] || configs.copilot; // fallback to copilot\n }\n\n /**\n * Generate or retrieve insight report\n * @param {string} sessionId - Session ID\n * @param {string} sessionPath - Full path to session directory\n * @param {string} source - Session source: 'copilot', 'claude', or 'pi-mono'\n * @param {boolean} forceRegenerate - Force new generation\n * @returns {Promise<Object>} Insight status and report\n */\n async generateInsight(sessionId, sessionPath, source = 'copilot', forceRegenerate = false) {\n // Use per-session insight file to avoid collisions in shared directories\n const insightFile = path.join(sessionPath, `${sessionId}.agent-review.md`);\n const lockFile = path.join(sessionPath, `${sessionId}.agent-review.md.lock`);\n \n // Determine events file location based on directory structure\n // Try standard events.jsonl first, then <sessionId>.jsonl (for file-type sessions),\n // finally *_<sessionId>.jsonl (for Pi-Mono timestamped sessions)\n let eventsFile = path.join(sessionPath, 'events.jsonl');\n try {\n await fs.access(eventsFile);\n } catch {\n // Try <sessionId>.jsonl (common for Claude file-type sessions)\n try {\n eventsFile = path.join(sessionPath, `${sessionId}.jsonl`);\n await fs.access(eventsFile);\n } catch {\n // Try *_<sessionId>.jsonl (Pi-Mono format: YYYY-MM-DDTHH-mm-ss-SSSZ_<uuid>.jsonl)\n try {\n const entries = await fs.readdir(sessionPath);\n const piFile = entries.find(f => f.endsWith(`_${sessionId}.jsonl`));\n if (piFile) {\n eventsFile = path.join(sessionPath, piFile);\n }\n } catch (_readdirErr) {\n // Fall through \u2014 eventsFile remains; the access check below will produce\n // the standard \"Events file not found\" 400 response.\n }\n }\n }\n\n const toolConfig = this._getToolConfig(source, sessionPath);\n const toolName = toolConfig.name;\n\n // Check if complete insight exists\n if (!forceRegenerate) {\n try {\n const report = await fs.readFile(insightFile, 'utf-8');\n const stats = await fs.stat(insightFile);\n return {\n status: 'completed',\n report,\n generatedAt: stats.mtime\n };\n } catch (_err) {\n // File doesn't exist, continue to generation\n }\n }\n\n // Check if generation is already in progress (atomic check via rename)\n const _acquireLock = async () => {\n const tmp = `${lockFile}.${process.pid}.${Date.now()}.tmp`;\n await fs.writeFile(tmp, JSON.stringify({\n sessionId,\n startTime: new Date().toISOString(),\n pid: process.pid\n }));\n try {\n // rename to a non-existent destination is atomic on POSIX; if dest exists\n // on POSIX rename will overwrite, so guard with link()+unlink pattern.\n // Use link (which fails with EEXIST if target exists) for true atomicity.\n await fs.link(tmp, lockFile);\n await fs.unlink(tmp).catch(() => {});\n } catch (e) {\n await fs.unlink(tmp).catch(() => {});\n throw e;\n }\n };\n\n try {\n await _acquireLock();\n } catch (err) {\n if (err.code === 'EEXIST') {\n // Another process is generating, check if it's stale\n try {\n const _lockData = JSON.parse(await fs.readFile(lockFile, 'utf-8'));\n const lockStats = await fs.stat(lockFile);\n const ageMs = Date.now() - lockStats.mtime.getTime();\n \n if (ageMs < config.INSIGHT_TIMEOUT_MS) {\n // Still valid, return generating status\n return {\n status: 'generating',\n report: `# Generating ${toolName} Insight...\\n\\nAnother request is currently generating this insight. Please wait.`,\n startedAt: lockStats.birthtime,\n lastUpdate: lockStats.mtime,\n ageMs: Date.now() - lockStats.birthtime.getTime()\n };\n }\n \n // Stale lock, remove it\n console.log(`\u26A0\uFE0F Removing stale lock file (${Math.floor(ageMs/1000)}s old)`);\n await fs.unlink(lockFile);\n \n // Retry lock creation atomically\n await _acquireLock();\n } catch (_retryErr) {\n throw new Error('Failed to acquire lock for insight generation', { cause: _retryErr });\n }\n } else {\n throw err;\n }\n }\n\n // Check if events file exists\n try {\n await fs.access(eventsFile);\n } catch (_err) {\n await fs.unlink(lockFile);\n throw new Error('Events file not found', { cause: _err });\n }\n\n // Clean up old files if force regenerate\n if (forceRegenerate) {\n try {\n await fs.unlink(insightFile);\n } catch (_err) {\n // File might not exist\n }\n }\n\n // Start generation\n await this._spawnAnalysisProcess(sessionPath, eventsFile, insightFile, lockFile, toolConfig);\n\n return {\n status: 'generating',\n report: `# Generating ${toolName} Insight...\\n\\nAnalysis in progress. Please wait.`,\n startedAt: new Date()\n };\n }\n\n /**\n * Spawn analysis process safely (no shell)\n * @private\n */\n async _spawnAnalysisProcess(sessionPath, eventsFile, insightFile, lockFile, toolConfig) {\n const sessionId = path.basename(sessionPath); // Extract session ID from path\n const tmpDir = path.join(os.tmpdir(), `agent-review-${sessionId}-${Date.now()}`);\n await fs.mkdir(tmpDir, { recursive: true});\n\n const prompt = this._buildPrompt(insightFile, eventsFile);\n const outputFile = path.join(sessionPath, `${sessionId}.agent-review.md.tmp`);\n\n // Spawn analysis tool directly (no shell)\n const cliPath = toolConfig.cli;\n const args = toolConfig.args(tmpDir, prompt);\n \n console.log(`\uD83E\uDD16 Starting ${toolConfig.name} analysis: ${cliPath} ${args.slice(0, 2).join(' ')}...`);\n console.log(`\uD83D\uDCCB Args count: ${args.length}, prompt length: ${prompt.length} chars`);\n \n // Use system PATH - CLI should be in the user's PATH\n const analysisProcess = spawn(cliPath, args, {\n env: { ...process.env },\n cwd: sessionPath,\n stdio: ['pipe', 'pipe', 'pipe']\n });\n\n // Register for cleanup\n processManager.register(analysisProcess, { name: `insight-${sessionId}` });\n\n // Always attach an 'error' handler to stdin to avoid unhandled EPIPE crashes.\n analysisProcess.stdin.on('error', (err) => {\n if (err.code !== 'EPIPE') {\n console.error('\u274C stdin error:', err);\n }\n });\n\n // Pipe events file to stdin (for tools that read from stdin like copilot)\n // Claude Code and Pi read files directly, so they don't need stdin\n if (toolConfig.cli === 'copilot') {\n const eventsStream = fsSync.createReadStream(eventsFile);\n eventsStream.on('error', (err) => {\n console.error('\u274C events stream error:', err);\n });\n analysisProcess.stdin.on('error', (err) => {\n if (err.code === 'EPIPE') {\n eventsStream.destroy();\n }\n });\n eventsStream.pipe(analysisProcess.stdin);\n } else {\n // Close stdin for tools that don't need it\n analysisProcess.stdin.end();\n }\n\n // Capture output\n const outputStream = fsSync.createWriteStream(outputFile);\n analysisProcess.stdout.pipe(outputStream);\n\n // Capture stderr with size limit\n const stderrChunks = [];\n let stderrSize = 0;\n const MAX_STDERR = 64 * 1024; // 64KB cap\n\n analysisProcess.stderr.on('data', (data) => {\n if (stderrSize < MAX_STDERR) {\n stderrChunks.push(data);\n stderrSize += data.length;\n }\n });\n\n analysisProcess.on('close', async (code) => {\n try {\n outputStream.end();\n\n const stderr = Buffer.concat(stderrChunks).toString('utf-8').slice(0, MAX_STDERR);\n console.log(`\uD83D\uDCCB ${toolConfig.name} process exited with code ${code}`);\n if (stderr) {\n console.log(`\uD83D\uDCCB ${toolConfig.name} stderr:`, stderr.substring(0, 500));\n }\n\n if (code !== 0) {\n console.error(`\u274C ${toolConfig.name} CLI failed (code ${code}):`, stderr);\n await fs.writeFile(insightFile,\n `# \u274C Generation Failed\\n\\nExit code: ${code}\\n\\n\\`\\`\\`\\n${stderr || '(no error output)'}\\n\\`\\`\\`\\n`,\n 'utf-8'\n );\n } else {\n // The agent was told to write directly to insightFile.\n // Check if it did; if not, fall back to cleaning stdout from .tmp.\n let hasDirectOutput = false;\n try {\n const direct = await fs.readFile(insightFile, 'utf-8');\n if (direct && direct.trim().length > 50) {\n hasDirectOutput = true;\n console.log(`\u2705 Insight generated for session ${sessionId} (agent wrote directly)`);\n }\n } catch (_e) { /* file doesn't exist */ }\n\n if (!hasDirectOutput) {\n let report = await fs.readFile(outputFile, 'utf-8');\n report = this._cleanReport(report);\n await fs.writeFile(insightFile, report, 'utf-8');\n console.log(`\u2705 Insight generated for session ${sessionId} (cleaned from stdout)`);\n }\n }\n\n // Cleanup\n await fs.unlink(outputFile).catch(() => {});\n await fs.unlink(lockFile).catch(() => {});\n await fs.rm(tmpDir, { recursive: true, force: true }).catch(() => {});\n // Clean up sub-agent working directory (safety net)\n await fs.rm(path.join(sessionPath, '.output'), { recursive: true, force: true }).catch(() => {});\n } catch (err) {\n console.error('\u274C Error finalizing insight:', err);\n await fs.unlink(lockFile).catch(() => {});\n await fs.rm(tmpDir, { recursive: true, force: true }).catch(() => {});\n }\n });\n\n analysisProcess.on('error', async (err) => {\n console.error(`\u274C Failed to spawn ${toolConfig.name}:`, err);\n await fs.unlink(lockFile).catch(() => {});\n await fs.rm(tmpDir, { recursive: true, force: true }).catch(() => {});\n });\n }\n\n /**\n * Build insight generation prompt\n * @private\n */\n _buildPrompt(outputPath, eventsFile) {\n const sessionDir = path.dirname(outputPath);\n const eventsFilename = path.basename(eventsFile);\n const workDir = `${sessionDir}/.output`;\n \n // For Pi-Mono: emphasize analyzing ONLY the specified file\n const fileInstruction = eventsFilename.includes('_') \n ? `\\n**IMPORTANT**: This directory may contain multiple .jsonl files. You MUST analyze ONLY the file named \\`${eventsFilename}\\`. Do NOT read or analyze any other .jsonl files in this directory.\\n`\n : '';\n \n return `You are an expert AI agent prompt-compliance auditor. The current working directory is an AI coding agent session folder containing raw session data from an agent run.\n${fileInstruction}\n**Step 1 \u2014 Discover session files.** Run \\`ls -la\\` to see what's available:\n- \\`${eventsFilename}\\` \u2014 the main session event log (JSONL, one JSON event per line). **This is the ONLY events file you should analyze.**\n- \\`plan.md\\` \u2014 the agent's plan (if it exists).\n- \\`workspace.yaml\\` \u2014 workspace configuration (if it exists).\n\n**Step 2 \u2014 Extract prompts and execution trace.** Parse \\`${eventsFilename}\\` to extract:\n- The **system prompt** (the agent's instructions/rules/constraints)\n- The **user prompt** (what the user actually asked for)\n- The **execution trace** \u2014 what the agent actually did (tool calls, decisions, outputs)\n- All **build/test/compile** operations and their exit codes, stdout/stderr\n\n**Step 3 \u2014 Spawn 3 sub-agents for parallel analysis.** First create the working directory: \\`mkdir -p ${workDir}\\`. Then use the Task tool to launch ALL of the following sub-agents simultaneously. Each sub-agent should read \\`${eventsFilename}\\` from \\`${sessionDir}\\` (use Bash: \\`cat\\`, \\`jq\\`, or \\`python3\\` to parse) **\u2014 ONLY this file, ignore others**.\n\nSub-agents to spawn:\n\n1. **Prompt Compliance Analyst** \u2014 Extract the system prompt rules/constraints and check each against the execution trace. For each rule: was it followed, partially followed, or violated? Identify instructions the agent ignored and actions the agent took that weren't requested. Write findings to \\`${workDir}/compliance.md\\`.\n\n2. **Task Completion Analyst** \u2014 Compare the user's ask against the agent's final output/artifacts. Did the agent deliver what was asked? Did it go off-track, do extra unrequested work, or miss requirements? Evaluate the logical coherence of the agent's plan-to-execution flow. Write findings to \\`${workDir}/task.md\\`.\n\n3. **Build & Test Analyst** \u2014 Find ALL build, compile, test, lint operations in the trace. For each: extract the command, exit code, and key output lines. For failures: diagnose root cause (missing dependency? syntax error? test assertion? wrong config?). Track if the agent fixed failures or left them broken. Write findings to \\`${workDir}/buildtest.md\\`.\n\n**CRITICAL: You MUST wait for ALL 3 sub-agents to complete before proceeding to Step 4.** Do NOT move on until every sub-agent has returned its results.\n\n**Step 4 \u2014 Synthesize the final report.** Once all sub-agents are done:\n1. Read the intermediate files from \\`${workDir}/\\`\n2. Synthesize a unified report\n3. Write the final report to \\`${outputPath}\\`\n4. Clean up: \\`rm -rf ${workDir}\\`\n\nThe final report MUST follow this exact structure:\n\n---\n\n## \uD83D\uDCCA Scorecard\n\n| Dimension | Score | Notes |\n|-----------|-------|-------|\n| System Prompt Compliance | X/10 | one-line summary |\n| User Ask Alignment | X/10 | one-line summary |\n| Execution Consistency | X/10 | one-line summary |\n| Error Recovery | X/10 | one-line summary |\n\n**Overall: X/10**\n\n## \uD83D\uDD28 Build & Test Results\n\nFor each build/test operation found in the session, list:\n- Command, exit code, pass/fail\n- For failures: root cause in one sentence\n- Final state: all green, or what's still broken\n\nIf no build/test operations exist, state \"No build/test operations found in this session.\"\n\n## \uD83D\uDCCB System Prompt Compliance\n\nList the key rules/constraints from the system prompt. For each:\n- \u2705 Followed \u2014 with brief evidence\n- \u26A0\uFE0F Partially followed \u2014 what was missed\n- \u274C Violated \u2014 what happened instead\n\nFocus on rules that were violated or partially followed. Don't exhaustively list every rule that was trivially followed.\n\n## \uD83C\uDFAF User Ask Alignment\n\n- What the user asked for (summarize the ask)\n- What the agent actually delivered\n- Gap analysis: missing deliverables, extra unrequested work, misinterpretations\n\n## \uD83D\uDD04 Execution Consistency\n\n- Did the agent's execution match its own stated plan?\n- Any backtracking, contradictions, or abandoned approaches?\n- Were decisions internally consistent throughout the session?\n\n## \uD83D\uDCA1 Key Findings\n\nTop 3-5 specific, evidence-backed observations. Every finding must reference concrete events from the session trace (tool call IDs, timestamps, or quoted output). No generic advice.\n\n---\n\nIMPORTANT CONSTRAINTS:\n- Be precise and concise. Every sentence must carry data or actionable insight.\n- The scorecard dimensions are the backbone \u2014 all analysis must map back to them.\n- Always cite evidence from the session trace. \"The agent violated rule X\" is useless without showing where.\n- The entire report should be under 4000 characters.`;\n }\n\n /**\n * Clean report output \u2014 strip copilot CLI working logs, thinking blocks, meta-commentary.\n * The copilot CLI dumps tool call logs (\u25CF Tool name, $ command, \u2514 output) to stdout\n * alongside the actual report. We need to extract just the final markdown.\n * @private\n */\n _cleanReport(report) {\n // Remove <thinking>...</thinking> blocks\n report = report.replace(/<thinking>[\\s\\S]*?<\\/thinking>/g, '');\n\n // Remove meta-commentary lines\n report = report.replace(/^(Let me analyze|I'll analyze|Analyzing|Here's my analysis of|I need the session data).*$/gm, '');\n\n // Strategy: try to find the final markdown report section.\n // The copilot CLI log has patterns like:\n // \u25CF Tool name (tool call header)\n // $ command (bash command)\n // \u2514 N lines... (output summary)\n // (+N lines) (file write indicator)\n // The actual report starts with a markdown heading like \"## \uD83C\uDFAF\"\n\n // Look for the last occurrence of the report structure (## \uD83C\uDFAF Effectiveness Score)\n // which indicates the final output vs. intermediate attempts\n const reportStartPattern = /^## \uD83D\uDCCA\\s*Scorecard/m;\n const matches = [...report.matchAll(new RegExp(reportStartPattern.source, 'gm'))];\n\n if (matches.length > 0) {\n // Take from the last match onward (in case the agent generated it multiple times)\n const lastMatch = matches[matches.length - 1];\n report = report.slice(lastMatch.index);\n } else {\n // Try broader: find any markdown heading (## with emoji or #)\n const anyHeadingMatch = report.match(/^(## [\uD83C\uDFAF\uD83D\uDD27\uD83D\uDD04\u26A1\uD83D\uDCA1#])/mu);\n if (anyHeadingMatch) {\n report = report.slice(anyHeadingMatch.index);\n } else {\n // Last resort: strip known copilot CLI log patterns line by line\n const lines = report.split('\\n');\n const cleanedLines = [];\n let skipBlock = false;\n\n for (const line of lines) {\n // Skip copilot CLI working log patterns\n if (/^\u25CF /.test(line)) { skipBlock = true; continue; }\n if (/^ {2}\\$ /.test(line)) { skipBlock = true; continue; }\n if (/^ {2}\u2514 /.test(line)) { skipBlock = false; continue; }\n if (/^\\(\\+\\d+ lines?\\)/.test(line)) { continue; }\n if (/^ {2}\u2514 \\d+ lines/.test(line)) { continue; }\n // Skip \"Asked user\" and \"User responded\" log lines\n if (/^\u25CF Asked user:/.test(line)) { skipBlock = true; continue; }\n if (/^ {2}\u2514 User responded:/.test(line)) { skipBlock = false; continue; }\n\n // If we hit a non-log line, stop skipping\n if (skipBlock && /\\S/.test(line) && !/^ {2}/.test(line)) {\n skipBlock = false;\n }\n if (skipBlock) continue;\n\n cleanedLines.push(line);\n }\n report = cleanedLines.join('\\n');\n }\n }\n\n // Trim excessive whitespace\n report = report.replace(/\\n{3,}/g, '\\n\\n').trim();\n\n return report;\n }\n\n /**\n * Get insight status\n */\n /**\n * Get insight status\n * @param {string} sessionId - Session ID\n * @param {string} sessionPath - Full path to session directory\n * @param {string} source - Session source\n * @returns {Promise<Object>} Status object\n */\n async getInsightStatus(sessionId, sessionPath, _source = 'copilot') {\n return await this._getStatusForSource(sessionId, sessionPath);\n }\n\n /**\n * Get status for a specific session directory\n * @private\n */\n async _getStatusForSource(sessionId, sessionPath) {\n const insightFile = path.join(sessionPath, `${sessionId}.agent-review.md`);\n const lockFile = path.join(sessionPath, `${sessionId}.agent-review.md.lock`);\n const tmpFile = path.join(sessionPath, `${sessionId}.agent-review.md.tmp`);\n\n try {\n const report = await fs.readFile(insightFile, 'utf-8');\n const stats = await fs.stat(insightFile);\n return {\n status: 'completed',\n report,\n generatedAt: stats.mtime\n };\n } catch (_err) {\n // Check if generation is in progress\n try {\n await fs.access(lockFile);\n const stats = await fs.stat(lockFile);\n const ageMs = Date.now() - stats.birthtime.getTime();\n\n // Read live working log from tmp file\n let log = null;\n try {\n log = await fs.readFile(tmpFile, 'utf-8');\n } catch (_tmpErr) {\n // tmp file may not exist yet\n }\n\n if (ageMs >= config.INSIGHT_TIMEOUT_MS) {\n return {\n status: 'timeout',\n log,\n startedAt: stats.birthtime,\n lastUpdate: stats.mtime,\n ageMs\n };\n }\n\n return {\n status: 'generating',\n log,\n startedAt: stats.birthtime,\n lastUpdate: stats.mtime,\n ageMs\n };\n } catch (_lockErr) {\n return { status: 'not_started' };\n }\n }\n }\n\n /**\n * Delete insight report\n * @param {string} sessionId - Session ID\n * @param {string} sessionPath - Full path to session directory\n * @param {string} source - Session source\n * @returns {Promise<Object>} Result object\n */\n async deleteInsight(sessionId, sessionPath, _source = 'copilot') {\n const insightFile = path.join(sessionPath, `${sessionId}.agent-review.md`);\n\n try {\n await fs.unlink(insightFile);\n return { success: true };\n } catch (err) {\n if (err.code === 'ENOENT') {\n return { success: true, message: 'Insight file not found' };\n }\n throw err;\n }\n }\n}\n\nmodule.exports = InsightService;\n", "const InsightService = require('../services/insightService');\nconst { isValidSessionId } = require('../utils/helpers');\nconst { trackEvent, trackMetric, trackException } = require('../telemetry');\n\nclass InsightController {\n constructor(insightService = null, sessionService = null) {\n if (insightService) {\n this.insightService = insightService;\n } else {\n this.insightService = new InsightService();\n }\n\n if (sessionService) {\n this.sessionService = sessionService;\n } else {\n const SessionService = require('../services/sessionService');\n this.sessionService = new SessionService();\n }\n }\n\n // Helper to get sessionId from either new or legacy param\n _getSessionId(req) {\n return req.params.sessionId || req.params.id;\n }\n\n _getGenerateInsightErrorResponse(err) {\n if (err instanceof Error) {\n if (err.message === 'Events file not found') {\n return { status: 400, body: { error: err.message } };\n }\n\n if (err.message === 'Failed to acquire lock for insight generation') {\n return { status: 503, body: { error: err.message } };\n }\n\n }\n\n return { status: 500, body: { error: 'Error generating insight' } };\n }\n\n // Generate or get insight\n async generateInsight(req, res) {\n try {\n const sessionId = this._getSessionId(req);\n const forceRegenerate = req.body?.force === true;\n\n if (!isValidSessionId(sessionId)) {\n return res.status(400).json({ error: 'Invalid session ID' });\n }\n\n const session = await this.sessionService.getSessionById(sessionId);\n if (!session) {\n return res.status(404).json({ error: 'Session not found' });\n }\n\n if (!session.directory) {\n return res.status(400).json({ error: 'Session directory not available' });\n }\n\n const startTime = Date.now();\n const result = await this.insightService.generateInsight(session.id, session.directory, session.source, forceRegenerate);\n const durationMs = Date.now() - startTime;\n\n trackEvent('InsightGenerated', {\n sessionId,\n source: session.source || 'unknown',\n durationMs: durationMs.toString()\n });\n\n trackMetric('InsightGenerationTime', durationMs, { sessionId, source: session.source || 'unknown' });\n\n res.json(result);\n } catch (err) {\n console.error('Error generating insight:', err);\n\n trackException(err, {\n sessionId: this._getSessionId(req),\n operation: 'generateInsight'\n });\n\n const errorResponse = this._getGenerateInsightErrorResponse(err);\n res.status(errorResponse.status).json(errorResponse.body);\n }\n }\n\n // Get insight status\n async getInsightStatus(req, res) {\n try {\n const sessionId = this._getSessionId(req);\n\n if (!isValidSessionId(sessionId)) {\n return res.status(400).json({ error: 'Invalid session ID' });\n }\n\n const session = await this.sessionService.getSessionById(sessionId);\n if (!session) {\n return res.status(404).json({ error: 'Session not found' });\n }\n\n if (!session.directory) {\n return res.status(400).json({ error: 'Session directory not available' });\n }\n\n const result = await this.insightService.getInsightStatus(session.id, session.directory, session.source);\n\n if (result.status === 'ready' && result.report) {\n trackEvent('InsightViewed', { sessionId });\n }\n\n res.json(result);\n } catch (err) {\n console.error('Error getting insight status:', err);\n res.status(500).json({ error: 'Error getting insight status' });\n }\n }\n\n // Delete insight\n async deleteInsight(req, res) {\n try {\n const sessionId = this._getSessionId(req);\n\n if (!isValidSessionId(sessionId)) {\n return res.status(400).json({ error: 'Invalid session ID' });\n }\n\n const session = await this.sessionService.getSessionById(sessionId);\n if (!session) {\n return res.status(404).json({ error: 'Session not found' });\n }\n\n if (!session.directory) {\n return res.status(400).json({ error: 'Session directory not available' });\n }\n\n const result = await this.insightService.deleteInsight(session.id, session.directory, session.source);\n\n trackEvent('InsightDeleted', { sessionId });\n\n res.json(result);\n } catch (err) {\n console.error('Error deleting insight:', err);\n res.status(500).json({ error: 'Error deleting insight' });\n }\n }\n\n}\n\nmodule.exports = InsightController;\n", "const fs = require('fs');\nconst path = require('path');\nconst os = require('os');\nconst multer = require('multer');\nconst { spawn } = require('child_process');\nconst { isValidSessionId } = require('../utils/helpers');\nconst { trackEvent, trackException } = require('../telemetry');\nconst processManager = require('../utils/processManager');\nconst config = require('../config');\nconst { registry } = require('../adapters');\n\nclass UploadController {\n constructor() {\n this.SESSION_DIR = process.env.SESSION_DIR || path.join(os.homedir(), '.copilot', 'session-state');\n this.uploadDir = process.env.UPLOAD_DIR || path.join(os.tmpdir(), 'copilot-session-uploads');\n\n // Multi-format session directories\n this.SESSION_DIRS = {\n copilot: this.SESSION_DIR,\n claude: path.join(os.homedir(), '.claude', 'projects'),\n 'pi-mono': path.join(os.homedir(), '.pi', 'agent', 'sessions')\n };\n\n // Don't create uploadDir here - multer's DiskStorage will handle it\n // This avoids EEXIST errors when multiple tests run in parallel\n this.upload = this.createMulterInstance();\n }\n\n createMulterInstance() {\n return multer({\n dest: this.uploadDir,\n limits: { fileSize: config.MAX_UPLOAD_SIZE },\n fileFilter: (req, file, cb) => {\n // Check both file extension and MIME type\n const isZipExtension = file.originalname.toLowerCase().endsWith('.zip');\n const isZipMime = file.mimetype === 'application/zip' ||\n file.mimetype === 'application/x-zip-compressed';\n\n if (!isZipExtension || !isZipMime) {\n return cb(new Error('Only .zip files are allowed'));\n }\n cb(null, true);\n }\n });\n }\n\n // Import session from zip (with validation)\n async importSession(req, res) {\n let extractDir = null;\n try {\n if (!req.file) {\n return res.status(400).json({ error: 'No file uploaded' });\n }\n\n const zipPath = req.file.path;\n extractDir = path.join(this.uploadDir, `extract-${Date.now()}`);\n const uploadedFileSize = (await fs.promises.stat(zipPath)).size;\n\n await fs.promises.mkdir(extractDir, { recursive: true });\n await this._validateZipArchive(zipPath);\n\n const unzipProcess = spawn('unzip', ['-q', zipPath, '-d', extractDir]);\n processManager.register(unzipProcess, { name: 'unzip-import' });\n\n let responded = false;\n\n unzipProcess.on('close', async (code) => {\n if (responded) return;\n responded = true;\n try {\n await fs.promises.unlink(zipPath).catch(() => {});\n\n if (code !== 0) {\n await fs.promises.rm(extractDir, { recursive: true, force: true });\n return res.status(500).json({ error: 'Failed to extract zip file' });\n }\n\n const result = await this._importExtractedSession(extractDir, req);\n await fs.promises.rm(extractDir, { recursive: true, force: true }).catch(() => {});\n\n if (!result.success) {\n const body = { error: result.error };\n if (result.code) body.code = result.code;\n if (result.candidates) body.candidates = result.candidates;\n return res.status(result.statusCode || 500).json(body);\n }\n\n trackEvent('SessionImported', { format: result.format, fileSize: uploadedFileSize.toString() });\n const body = { success: true, sessionId: result.sessionId, format: result.format };\n if (result.project) body.project = result.project;\n return res.json(body);\n } catch (err) {\n console.error('Error importing session:', err);\n trackException(err, { operation: 'importSession' });\n await fs.promises.rm(extractDir, { recursive: true, force: true }).catch(() => {});\n return res.status(500).json({ error: 'Error importing session' });\n }\n });\n\n unzipProcess.on('error', async (err) => {\n if (responded) return;\n responded = true;\n console.error('Error extracting zip:', err);\n trackException(err, { operation: 'importSession_unzip' });\n await fs.promises.unlink(zipPath).catch(() => {});\n await fs.promises.rm(extractDir, { recursive: true, force: true }).catch(() => {});\n return res.status(500).json({ error: 'Failed to extract zip file' });\n });\n } catch (err) {\n console.error('Error processing upload:', err);\n trackException(err, { operation: 'importSession_upload' });\n if (req.file) await fs.promises.unlink(req.file.path).catch(() => {});\n if (extractDir) await fs.promises.rm(extractDir, { recursive: true, force: true }).catch(() => {});\n // Surface known validation errors as 400\n if (err.message?.match(/Compressed file too large|Uncompressed size too large|Too many files|Directory nesting too deep|Failed to list zip/)) {\n return res.status(400).json({ error: err.message });\n }\n return res.status(500).json({ error: 'Error processing upload' });\n }\n }\n\n // Multer middleware accessor\n getUploadMiddleware() {\n // Accept both 'zipFile' (canonical) and 'sessionZip' (legacy frontend)\n const fieldNames = ['zipFile', 'sessionZip'];\n const middleware = this.upload.fields(fieldNames.map(name => ({ name, maxCount: 1 })));\n return (req, res, next) => {\n middleware(req, res, (err) => {\n if (err) return next(err);\n req.file = fieldNames.map(n => req.files?.[n]?.[0]).find(Boolean) || null;\n return next();\n });\n };\n }\n\n /**\n * Detect format via adapter registry. Returns backward-compat shape for _detectFormat,\n * plus structured result via _detectImportCandidates.\n */\n async _detectFormat(extractDir) {\n const det = await this._detectImportCandidates(extractDir);\n if (det.status !== 'matched') return null;\n return { format: det.match.source, extractDir, ...det.match };\n }\n\n async _detectImportCandidates(extractDir) {\n try {\n const entries = await fs.promises.readdir(extractDir);\n if (entries.length === 0) {\n return { status: 'unsupported-format', matches: [], candidates: [], error: 'Empty zip file' };\n }\n // Path-traversal guard\n if (entries.some(e => e.includes('..') || path.isAbsolute(e))) {\n return { status: 'invalid-structure', matches: [], candidates: [], error: 'Invalid session directory name in zip file' };\n }\n const candidates = await registry.detectImportCandidates(extractDir);\n const matches = candidates.filter(c => c.matched);\n if (matches.length === 0) return { status: 'unsupported-format', matches: [], candidates, error: 'Unsupported session zip format' };\n if (matches.length > 1) return { status: 'ambiguous', matches, candidates, error: 'Ambiguous session zip format' };\n return { status: 'matched', match: matches[0], matches, candidates };\n } catch (err) {\n console.error('Error detecting format:', err);\n return { status: 'error', matches: [], candidates: [], error: 'Error detecting format' };\n }\n }\n\n async _importCopilotSession(formatInfo, extractDir) {\n return registry.get('copilot').importDetectedSession(formatInfo, { extractDir, req: { query: {} }, targetDir: this.SESSION_DIRS.copilot });\n }\n async _importClaudeSession(formatInfo, extractDir, req) {\n return registry.get('claude').importDetectedSession(formatInfo, { extractDir, req, targetDir: this.SESSION_DIRS.claude });\n }\n async _importPiMonoSession(formatInfo, extractDir, req) {\n return registry.get('pi-mono').importDetectedSession(formatInfo, { extractDir, req, targetDir: this.SESSION_DIRS['pi-mono'] });\n }\n\n async _importByFormat(formatInfo, extractDir, req) {\n if (!isValidSessionId(formatInfo.sessionId)) {\n return { success: false, error: 'Invalid session ID', statusCode: 400 };\n }\n const adapter = registry.get(formatInfo.format || formatInfo.source);\n if (!adapter) {\n return { success: false, error: `Unsupported format: ${formatInfo.format || formatInfo.source}`, statusCode: 400, code: 'unsupported-format' };\n }\n return adapter.importDetectedSession(formatInfo, { extractDir, req, targetDir: this.SESSION_DIRS[formatInfo.format || formatInfo.source] });\n }\n\n async _validateZipArchive(zipPath) {\n const MAX_COMPRESSED = 50 * 1024 * 1024, MAX_UNCOMPRESSED = 200 * 1024 * 1024, MAX_FILES = 1000, MAX_DEPTH = 5;\n const stats = await fs.promises.stat(zipPath);\n if (stats.size > MAX_COMPRESSED) throw new Error('Compressed file too large (max 50MB)');\n const listProc = spawn('unzip', ['-l', zipPath]);\n let out = '';\n listProc.stdout.on('data', d => { out += d.toString(); });\n await new Promise((ok, fail) => {\n listProc.on('close', c => c !== 0 ? fail(new Error('Failed to list zip contents')) : ok());\n listProc.on('error', fail);\n });\n let totalSize = 0, count = 0, maxD = 0;\n for (const line of out.split('\\n')) {\n const m = line.trim().match(/^\\s*(\\d+)\\s+\\d{4}-\\d{2}-\\d{2}\\s+\\d{2}:\\d{2}\\s+(.+)$/);\n if (!m) continue;\n totalSize += parseInt(m[1], 10); count++;\n maxD = Math.max(maxD, (m[2].match(/\\//g) || []).length);\n }\n if (totalSize > MAX_UNCOMPRESSED) throw new Error(`Uncompressed size too large (${Math.round(totalSize/1024/1024)}MB > ${MAX_UNCOMPRESSED/1024/1024}MB)`);\n if (count > MAX_FILES) throw new Error(`Too many files in archive (${count} > ${MAX_FILES})`);\n if (maxD > MAX_DEPTH) throw new Error(`Directory nesting too deep (${maxD} > ${MAX_DEPTH})`);\n }\n\n async _importExtractedSession(extractDir, req) {\n const det = await this._detectImportCandidates(extractDir);\n if (det.status === 'error') return { success: false, statusCode: 500, error: 'Error importing session' };\n if (det.status === 'invalid-structure') return { success: false, statusCode: 400, error: det.error };\n if (det.status === 'unsupported-format') {\n return { success: false, statusCode: det.error === 'Empty zip file' ? 400 : 415, error: det.error, code: 'unsupported-format', candidates: det.candidates };\n }\n if (det.status === 'ambiguous') {\n return { success: false, statusCode: 400, error: det.error, code: 'ambiguous-format', candidates: det.matches };\n }\n return this._importByFormat(det.match, extractDir, req);\n }\n\n}\n\nmodule.exports = UploadController;", "const TagService = require('../services/tagService');\nconst SessionRepository = require('../services/sessionRepository');\nconst { isValidSessionId } = require('../utils/helpers');\nconst { trackEvent } = require('../telemetry');\n\nclass TagController {\n constructor(tagService = null, sessionRepository = null) {\n this.tagService = tagService || new TagService();\n this.sessionRepository = sessionRepository || new SessionRepository();\n }\n\n // Helper to get sessionId from either new or legacy param\n _getSessionId(req) {\n return req.params.sessionId || req.params.id;\n }\n\n /**\n * GET /api/tags\n * Get all unique tags across all sessions (for autocomplete)\n */\n async getAllTags(req, res) {\n try {\n const tags = await this.tagService.getAllKnownTags();\n res.json({ tags });\n } catch (err) {\n console.error('Error getting all tags:', err);\n res.status(500).json({ error: 'Error loading tags' });\n }\n }\n\n /**\n * GET /api/:source/sessions/:sessionId/tags\n * Get tags for a specific session\n */\n async getSessionTags(req, res) {\n try {\n const sessionId = this._getSessionId(req);\n\n if (!isValidSessionId(sessionId)) {\n return res.status(400).json({ error: 'Invalid session ID' });\n }\n\n const session = await this.sessionRepository.findById(sessionId);\n if (!session) {\n return res.status(404).json({ error: 'Session not found' });\n }\n\n const tags = await this.tagService.getSessionTags(session);\n res.json({ tags });\n } catch (err) {\n console.error('Error getting session tags:', err);\n res.status(500).json({ error: 'Error loading session tags' });\n }\n }\n\n /**\n * PUT /api/:source/sessions/:sessionId/tags\n * Set tags for a specific session\n * Body: { tags: [\"tag1\", \"tag2\"] }\n */\n async setSessionTags(req, res) {\n try {\n const sessionId = this._getSessionId(req);\n const { tags } = req.body;\n\n if (!isValidSessionId(sessionId)) {\n return res.status(400).json({ error: 'Invalid session ID' });\n }\n\n if (!Array.isArray(tags)) {\n return res.status(400).json({ error: 'Tags must be an array' });\n }\n\n if (tags.length > 10) {\n return res.status(400).json({ error: 'Maximum 10 tags per session' });\n }\n\n for (const tag of tags) {\n if (typeof tag !== 'string' || tag.trim().length === 0) {\n return res.status(400).json({ error: 'Tags must be non-empty strings' });\n }\n if (tag.length > 30) {\n return res.status(400).json({ error: 'Tag length must not exceed 30 characters' });\n }\n }\n\n const session = await this.sessionRepository.findById(sessionId);\n if (!session) {\n return res.status(404).json({ error: 'Session not found' });\n }\n\n const savedTags = await this.tagService.setSessionTags(session, tags);\n\n trackEvent('TagUpdated', {\n sessionId,\n tagCount: savedTags.length.toString()\n });\n\n res.json({ tags: savedTags });\n } catch (err) {\n console.error('Error setting session tags:', err);\n if (err.message === 'Maximum 10 tags per session') {\n return res.status(400).json({ error: err.message });\n }\n if (err.message === 'Session must have a directory field') {\n return res.status(400).json({ error: 'Session does not support tagging' });\n }\n res.status(500).json({ error: 'Error saving session tags' });\n }\n }\n\n}\n\nmodule.exports = TagController;\n", "const DirRegistryService = require('../services/dirRegistryService');\n\nclass DirController {\n constructor(dirRegistryService = null) {\n this.dirRegistryService = dirRegistryService || new DirRegistryService();\n }\n\n async listDirs(req, res) {\n try {\n const dirs = await this.dirRegistryService.getAll();\n res.json(dirs);\n } catch (err) {\n console.error('Error listing registered dirs:', err);\n res.status(500).json({ error: 'Error listing registered directories' });\n }\n }\n\n async registerDir(req, res) {\n const body = req.body || {};\n const rawPath = body.path;\n const label = body.label;\n\n if (!rawPath || typeof rawPath !== 'string') {\n return res.status(400).json({ error: 'Path is required' });\n }\n\n try {\n const entry = await this.dirRegistryService.register(rawPath, label);\n return res.status(201).json(entry);\n } catch (err) {\n return res.status(400).json({ error: err.message });\n }\n }\n\n async removeDir(req, res) {\n const { id } = req.params;\n try {\n const removed = await this.dirRegistryService.remove(id);\n if (!removed) {\n return res.status(404).json({ error: 'Directory not found' });\n }\n return res.status(204).end();\n } catch (err) {\n console.error('Error removing registered dir:', err);\n return res.status(500).json({ error: 'Error removing directory' });\n }\n }\n}\n\nmodule.exports = DirController;\n", "const express = require('express');\nconst path = require('path');\nconst fs = require('fs');\nconst compression = require('compression');\nconst helmet = require('helmet');\n\n// Configuration\nconst config = require('./config');\n\n// Resolve dist/client location across both layouts:\n// - source: src/server/app.js \u2192 ../../dist/client\n// - bundled: dist/server.min.js (this file becomes part of the bundle, but the\n// bundle's runtime __dirname is /dist) \u2192 ./client\n// Pick whichever exists.\nconst DIST_CLIENT_DIR = (() => {\n const candidates = [\n path.join(__dirname, '../../dist/client'),\n path.join(__dirname, 'client'),\n path.join(__dirname, '../dist/client'),\n ];\n for (const p of candidates) {\n if (fs.existsSync(path.join(p, 'index.html'))) return p;\n }\n // Fall back to the source-layout path; will 404 with a clear error if missing.\n return candidates[0];\n})();\nconst PUBLIC_DIR = (() => {\n const candidates = [\n path.join(__dirname, '../../public'),\n path.join(__dirname, '../public'),\n ];\n for (const p of candidates) {\n if (fs.existsSync(p)) return p;\n }\n return candidates[0];\n})();\n\n// Middleware\n// Rate limiting disabled for local development\n\nconst { requestTimeout, developmentCors, errorHandler, notFoundHandler, telemetryLocals } = require('./middleware/common');\n\n// Source mapping\nconst { isValidSource, getAllSources } = require('./utils/sourceMapping');\n\n// Controllers\nconst SessionController = require('./controllers/sessionController');\nconst InsightController = require('./controllers/insightController');\nconst UploadController = require('./controllers/uploadController');\nconst TagController = require('./controllers/tagController');\nconst DirController = require('./controllers/dirController');\nconst DirRegistryService = require('./services/dirRegistryService');\nconst { isValidUuidV4 } = require('./utils/helpers');\n\n// Source validation middleware\nfunction validateSource(req, res, next) {\n const { source } = req.params;\n if (!isValidSource(source)) {\n const sanitizedSource = String(source).replace(/[^a-zA-Z0-9_-]/g, '');\n return res.status(404).json({ error: `Unknown source: ${sanitizedSource}` });\n }\n next();\n}\n\n// :id validation middleware for registered-dir routes\nfunction validateDirId(req, res, next) {\n if (!isValidUuidV4(req.params.id)) {\n return res.status(400).json({ error: 'Invalid dir id' });\n }\n next();\n}\n\nfunction createApp(options = {}) {\n const app = express();\n\n // Disable Express's automatic ETag generation (prevents 304 on live/active session files)\n app.set('etag', false);\n\n // Create controller instances (with optional dependency injection)\n const dirRegistryService = options.dirRegistryService || new DirRegistryService();\n const sessionController = new SessionController(options.sessionService, options.tagService, dirRegistryService);\n const insightController = new InsightController(options.insightService, options.sessionService);\n const uploadController = new UploadController();\n const tagController = new TagController(options.tagService);\n const dirController = new DirController(dirRegistryService);\n\n // Minimal security headers for local development tool\n // Custom CSP without upgrade-insecure-requests\n app.use((req, res, next) => {\n res.setHeader(\n 'Content-Security-Policy',\n \"default-src 'self'; \" +\n \"style-src 'self' 'unsafe-inline'; \" +\n \"font-src 'self'; \" +\n \"script-src 'self'; \" +\n \"img-src 'self' data:; \" +\n \"connect-src 'self'\"\n );\n next();\n });\n\n // Other helmet protections (without CSP and HSTS)\n app.use(helmet({\n contentSecurityPolicy: false,\n hsts: false,\n referrerPolicy: false,\n crossOriginEmbedderPolicy: false,\n crossOriginOpenerPolicy: false,\n crossOriginResourcePolicy: false\n }));\n\n app.use(compression({\n level: 1, // Fast compression (speed > ratio for local use)\n threshold: 1024, // Compress responses > 1KB\n filter: (req, res) => {\n // Skip compression for large JSON API responses (handled separately)\n if (req.path.includes('/events') && res.getHeader('Content-Type')?.includes('application/json')) {\n return false;\n }\n return compression.filter(req, res);\n }\n }));\n app.use(express.json({ limit: '1mb' }));\n app.use(express.urlencoded({ extended: true }));\n app.use(requestTimeout);\n app.use(telemetryLocals);\n\n // CORS in development\n if (config.NODE_ENV === 'development') {\n app.use(developmentCors);\n }\n\n // Rate limiting - DISABLED for local development\n\n\n // Static files (legacy public folder)\n app.use('/public', express.static(PUBLIC_DIR));\n\n // Serve Vue SPA static assets from dist/client\n app.use(express.static(DIST_CLIENT_DIR));\n\n // \u2500\u2500 API routes \u2500\u2500\n\n // Sources endpoint\n app.get('/api/sources', (req, res) => {\n res.json(getAllSources());\n });\n\n // Source hints (directory paths per source type)\n app.get('/api/source-hints', (req, res) => {\n const sources = sessionController.sessionService.sessionRepository.sources;\n const hints = {};\n if (sources) {\n for (const src of sources) {\n hints[src.type] = { configured: true, dir: src.dir };\n }\n }\n res.json(hints);\n });\n\n // Global tags (no source needed)\n app.get('/api/tags', tagController.getAllTags.bind(tagController));\n\n // Registered custom directories\n app.get('/api/dirs', dirController.listDirs.bind(dirController));\n app.post('/api/dirs', dirController.registerDir.bind(dirController));\n app.delete('/api/dirs/:id', validateDirId, dirController.removeDir.bind(dirController));\n\n // Import (no source needed \u2014 auto-detected)\n app.post('/api/import',\n (req, res, next) => uploadController.getUploadMiddleware()(req, res, next),\n uploadController.importSession.bind(uploadController)\n );\n\n // \u2500\u2500 Source-scoped routes \u2500\u2500 (all use :source param with validation)\n\n // Session list\n app.get('/api/:source/sessions', validateSource, sessionController.getSessions.bind(sessionController));\n\n // Session detail\n app.get('/api/:source/sessions/:sessionId', validateSource, sessionController.getSessionById.bind(sessionController));\n\n // Session events\n app.get('/api/:source/sessions/:sessionId/events', validateSource, sessionController.getSessionEvents.bind(sessionController));\n\n // Session timeline\n app.get('/api/:source/sessions/:sessionId/timeline', validateSource, sessionController.getTimeline.bind(sessionController));\n\n // Session export\n app.get('/api/:source/sessions/:sessionId/export', validateSource, sessionController.exportSession.bind(sessionController));\n\n // Session tags\n app.get('/api/:source/sessions/:sessionId/tags', validateSource, tagController.getSessionTags.bind(tagController));\n app.put('/api/:source/sessions/:sessionId/tags', validateSource, tagController.setSessionTags.bind(tagController));\n\n \n\n // Insight routes\n app.post('/api/:source/sessions/:sessionId/insight', validateSource, insightController.generateInsight.bind(insightController));\n app.get('/api/:source/sessions/:sessionId/insight', validateSource, insightController.getInsightStatus.bind(insightController));\n app.delete('/api/:source/sessions/:sessionId/insight', validateSource, insightController.deleteInsight.bind(insightController));\n\n // SPA fallback: serve index.html for all non-API routes\n app.get('*', (req, res, next) => {\n // Skip API routes and static files\n if (req.path.startsWith('/api/') || req.path.startsWith('/public/')) {\n return next();\n }\n res.sendFile(path.join(DIST_CLIENT_DIR, 'index.html'));\n });\n\n // Error handling\n app.use(notFoundHandler);\n app.use(errorHandler);\n\n return app;\n}\n\nmodule.exports = createApp;\n", "// IMPORTANT: Initialize telemetry FIRST, before any other requires (especially Express)\nrequire('./src/server/telemetry');\n\nconst createApp = require('./src/server/app');\nconst config = require('./src/server/config');\nconst processManager = require('./src/server/utils/processManager');\n\n// Create the Express app\nconst app = createApp();\n\n// Export app for testing\nmodule.exports = app;\n\n// Start server only if not being required by tests\nif (require.main === module) {\n const server = app.listen(config.PORT, () => {\n console.log(`\uD83D\uDE80 Copilot Session Viewer running at http://localhost:${config.PORT}`);\n console.log(`\uD83D\uDD27 Environment: ${config.NODE_ENV}`);\n console.log(`\u26A1 Active processes: ${processManager.getActiveCount()}`);\n });\n\n // Graceful shutdown\n process.on('SIGTERM', () => {\n console.log('\uD83D\uDCDB SIGTERM received, closing server...');\n server.close(() => {\n console.log('\u2705 Server closed');\n });\n });\n}"],
5
+ "mappings": "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",
6
+ "names": ["exports", "module", "exports", "module", "exports", "module", "config", "exports", "module", "exports", "module", "exports", "module", "exports", "module", "exports", "module", "exports", "module", "exports", "module", "exports", "module", "exports", "module", "exports", "module", "exports", "module", "exports", "module", "exports", "module", "exports", "module", "exports", "module", "exports", "module", "exports", "module", "exports", "module", "exports", "module", "exports", "module", "exports", "module", "exports", "module", "exports", "module", "firstEvent", "exports", "module", "exports", "module", "exports", "module", "exports", "module", "process", "exports", "module", "config", "processManager", "exports", "module", "exports", "module", "processManager", "config", "body", "exports", "module", "exports", "module", "exports", "module", "config", "createApp", "app"]
7
+ }