@stackmemoryai/stackmemory 0.3.7 → 0.3.9

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.
Files changed (202) hide show
  1. package/dist/agents/core/agent-task-manager.js +5 -5
  2. package/dist/agents/core/agent-task-manager.js.map +2 -2
  3. package/dist/agents/verifiers/base-verifier.js +2 -2
  4. package/dist/agents/verifiers/base-verifier.js.map +2 -2
  5. package/dist/cli/claude-sm.js +0 -11
  6. package/dist/cli/claude-sm.js.map +2 -2
  7. package/dist/cli/codex-sm.js +0 -11
  8. package/dist/cli/codex-sm.js.map +2 -2
  9. package/dist/cli/commands/chromadb.js +64 -34
  10. package/dist/cli/commands/chromadb.js.map +2 -2
  11. package/dist/cli/commands/clear.js +9 -13
  12. package/dist/cli/commands/clear.js.map +2 -2
  13. package/dist/cli/commands/config.js +43 -33
  14. package/dist/cli/commands/config.js.map +2 -2
  15. package/dist/cli/commands/context.js.map +2 -2
  16. package/dist/cli/commands/dashboard.js +41 -13
  17. package/dist/cli/commands/dashboard.js.map +2 -2
  18. package/dist/cli/commands/gc.js +69 -20
  19. package/dist/cli/commands/gc.js.map +2 -2
  20. package/dist/cli/commands/handoff.js.map +2 -2
  21. package/dist/cli/commands/infinite-storage.js +60 -19
  22. package/dist/cli/commands/infinite-storage.js.map +2 -2
  23. package/dist/cli/commands/linear-create.js +36 -8
  24. package/dist/cli/commands/linear-create.js.map +2 -2
  25. package/dist/cli/commands/linear-list.js +33 -10
  26. package/dist/cli/commands/linear-list.js.map +2 -2
  27. package/dist/cli/commands/linear-migrate.js +17 -4
  28. package/dist/cli/commands/linear-migrate.js.map +2 -2
  29. package/dist/cli/commands/linear-test.js +14 -6
  30. package/dist/cli/commands/linear-test.js.map +2 -2
  31. package/dist/cli/commands/linear-unified.js +123 -35
  32. package/dist/cli/commands/linear-unified.js.map +2 -2
  33. package/dist/cli/commands/linear.js.map +2 -2
  34. package/dist/cli/commands/monitor.js.map +2 -2
  35. package/dist/cli/commands/onboard.js +35 -8
  36. package/dist/cli/commands/onboard.js.map +2 -2
  37. package/dist/cli/commands/quality.js +2 -7
  38. package/dist/cli/commands/quality.js.map +2 -2
  39. package/dist/cli/commands/session.js +23 -6
  40. package/dist/cli/commands/session.js.map +2 -2
  41. package/dist/cli/commands/skills.js +72 -27
  42. package/dist/cli/commands/skills.js.map +2 -2
  43. package/dist/cli/commands/storage.js +108 -38
  44. package/dist/cli/commands/storage.js.map +2 -2
  45. package/dist/cli/commands/tui.js.map +2 -2
  46. package/dist/cli/commands/webhook.js +57 -18
  47. package/dist/cli/commands/webhook.js.map +2 -2
  48. package/dist/cli/commands/workflow.js +8 -15
  49. package/dist/cli/commands/workflow.js.map +2 -2
  50. package/dist/cli/commands/worktree.js +34 -13
  51. package/dist/cli/commands/worktree.js.map +2 -2
  52. package/dist/cli/index.js +0 -11
  53. package/dist/cli/index.js.map +2 -2
  54. package/dist/core/config/types.js.map +1 -1
  55. package/dist/core/context/auto-context.js +10 -6
  56. package/dist/core/context/auto-context.js.map +2 -2
  57. package/dist/core/context/context-bridge.js.map +2 -2
  58. package/dist/core/context/frame-database.js +13 -3
  59. package/dist/core/context/frame-database.js.map +2 -2
  60. package/dist/core/context/frame-digest.js +7 -5
  61. package/dist/core/context/frame-digest.js.map +2 -2
  62. package/dist/core/context/frame-manager.js.map +2 -2
  63. package/dist/core/context/frame-stack.js +16 -5
  64. package/dist/core/context/frame-stack.js.map +2 -2
  65. package/dist/core/context/incremental-gc.js +10 -3
  66. package/dist/core/context/incremental-gc.js.map +2 -2
  67. package/dist/core/context/index.js.map +1 -1
  68. package/dist/core/context/permission-manager.js.map +2 -2
  69. package/dist/core/context/recursive-context-manager.js +582 -0
  70. package/dist/core/context/recursive-context-manager.js.map +7 -0
  71. package/dist/core/context/refactored-frame-manager.js +12 -3
  72. package/dist/core/context/refactored-frame-manager.js.map +2 -2
  73. package/dist/core/context/shared-context-layer.js +4 -2
  74. package/dist/core/context/shared-context-layer.js.map +2 -2
  75. package/dist/core/database/batch-operations.js +112 -86
  76. package/dist/core/database/batch-operations.js.map +2 -2
  77. package/dist/core/database/query-cache.js +19 -9
  78. package/dist/core/database/query-cache.js.map +2 -2
  79. package/dist/core/database/sqlite-adapter.js +1 -1
  80. package/dist/core/database/sqlite-adapter.js.map +2 -2
  81. package/dist/core/digest/enhanced-hybrid-digest.js +8 -2
  82. package/dist/core/digest/enhanced-hybrid-digest.js.map +2 -2
  83. package/dist/core/errors/recovery.js +9 -2
  84. package/dist/core/errors/recovery.js.map +2 -2
  85. package/dist/core/execution/parallel-executor.js +254 -0
  86. package/dist/core/execution/parallel-executor.js.map +7 -0
  87. package/dist/core/frame/workflow-templates-stub.js.map +1 -1
  88. package/dist/core/frame/workflow-templates.js +40 -1
  89. package/dist/core/frame/workflow-templates.js.map +2 -2
  90. package/dist/core/monitoring/logger.js +6 -1
  91. package/dist/core/monitoring/logger.js.map +2 -2
  92. package/dist/core/monitoring/metrics.js.map +2 -2
  93. package/dist/core/monitoring/progress-tracker.js.map +2 -2
  94. package/dist/core/performance/context-cache.js.map +2 -2
  95. package/dist/core/performance/lazy-context-loader.js +24 -20
  96. package/dist/core/performance/lazy-context-loader.js.map +2 -2
  97. package/dist/core/performance/optimized-frame-context.js +27 -12
  98. package/dist/core/performance/optimized-frame-context.js.map +2 -2
  99. package/dist/core/performance/performance-benchmark.js +10 -6
  100. package/dist/core/performance/performance-benchmark.js.map +2 -2
  101. package/dist/core/performance/performance-profiler.js +51 -14
  102. package/dist/core/performance/performance-profiler.js.map +2 -2
  103. package/dist/core/performance/streaming-jsonl-parser.js +5 -1
  104. package/dist/core/performance/streaming-jsonl-parser.js.map +2 -2
  105. package/dist/core/projects/project-manager.js +14 -20
  106. package/dist/core/projects/project-manager.js.map +2 -2
  107. package/dist/core/retrieval/context-retriever.js.map +1 -1
  108. package/dist/core/retrieval/llm-context-retrieval.js.map +2 -2
  109. package/dist/core/session/clear-survival-stub.js +5 -1
  110. package/dist/core/session/clear-survival-stub.js.map +2 -2
  111. package/dist/core/session/clear-survival.js +35 -0
  112. package/dist/core/session/clear-survival.js.map +2 -2
  113. package/dist/core/session/index.js.map +1 -1
  114. package/dist/core/session/session-manager.js.map +2 -2
  115. package/dist/core/storage/chromadb-adapter.js +6 -2
  116. package/dist/core/storage/chromadb-adapter.js.map +2 -2
  117. package/dist/core/storage/chromadb-simple.js +17 -5
  118. package/dist/core/storage/chromadb-simple.js.map +2 -2
  119. package/dist/core/storage/infinite-storage.js +109 -46
  120. package/dist/core/storage/infinite-storage.js.map +2 -2
  121. package/dist/core/storage/railway-optimized-storage.js +48 -22
  122. package/dist/core/storage/railway-optimized-storage.js.map +2 -2
  123. package/dist/core/storage/remote-storage.js +41 -23
  124. package/dist/core/storage/remote-storage.js.map +2 -2
  125. package/dist/core/trace/cli-trace-wrapper.js +9 -2
  126. package/dist/core/trace/cli-trace-wrapper.js.map +2 -2
  127. package/dist/core/trace/db-trace-wrapper.js +96 -68
  128. package/dist/core/trace/db-trace-wrapper.js.map +2 -2
  129. package/dist/core/trace/debug-trace.js +25 -8
  130. package/dist/core/trace/debug-trace.js.map +2 -2
  131. package/dist/core/trace/index.js +6 -2
  132. package/dist/core/trace/index.js.map +2 -2
  133. package/dist/core/trace/linear-api-wrapper.js +10 -5
  134. package/dist/core/trace/linear-api-wrapper.js.map +2 -2
  135. package/dist/core/trace/trace-demo.js +14 -10
  136. package/dist/core/trace/trace-demo.js.map +2 -2
  137. package/dist/core/trace/trace-detector.js +9 -2
  138. package/dist/core/trace/trace-detector.js.map +2 -2
  139. package/dist/core/trace/types.js.map +1 -1
  140. package/dist/core/utils/compression.js.map +1 -1
  141. package/dist/core/utils/update-checker.js.map +1 -1
  142. package/dist/core/worktree/worktree-manager.js +18 -7
  143. package/dist/core/worktree/worktree-manager.js.map +2 -2
  144. package/dist/features/analytics/core/analytics-service.js.map +2 -2
  145. package/dist/features/analytics/queries/metrics-queries.js +1 -1
  146. package/dist/features/analytics/queries/metrics-queries.js.map +2 -2
  147. package/dist/features/tasks/pebbles-task-store.js.map +1 -1
  148. package/dist/features/tui/components/analytics-panel.js +36 -15
  149. package/dist/features/tui/components/analytics-panel.js.map +2 -2
  150. package/dist/features/tui/components/pr-tracker.js +19 -7
  151. package/dist/features/tui/components/pr-tracker.js.map +2 -2
  152. package/dist/features/tui/components/session-monitor.js +22 -9
  153. package/dist/features/tui/components/session-monitor.js.map +2 -2
  154. package/dist/features/tui/components/subagent-fleet.js +20 -13
  155. package/dist/features/tui/components/subagent-fleet.js.map +2 -2
  156. package/dist/features/tui/components/task-board.js +26 -10
  157. package/dist/features/tui/components/task-board.js.map +2 -2
  158. package/dist/features/tui/index.js.map +2 -2
  159. package/dist/features/tui/services/data-service.js +6 -2
  160. package/dist/features/tui/services/data-service.js.map +2 -2
  161. package/dist/features/tui/services/linear-task-reader.js +3 -1
  162. package/dist/features/tui/services/linear-task-reader.js.map +2 -2
  163. package/dist/features/tui/services/websocket-client.js +3 -1
  164. package/dist/features/tui/services/websocket-client.js.map +2 -2
  165. package/dist/features/tui/terminal-compat.js +6 -2
  166. package/dist/features/tui/terminal-compat.js.map +2 -2
  167. package/dist/features/web/client/stores/task-store.js.map +2 -2
  168. package/dist/features/web/server/index.js +18 -10
  169. package/dist/features/web/server/index.js.map +2 -2
  170. package/dist/integrations/anthropic/client.js +259 -0
  171. package/dist/integrations/anthropic/client.js.map +7 -0
  172. package/dist/integrations/claude-code/subagent-client.js +404 -0
  173. package/dist/integrations/claude-code/subagent-client.js.map +7 -0
  174. package/dist/integrations/linear/sync-service.js +12 -13
  175. package/dist/integrations/linear/sync-service.js.map +2 -2
  176. package/dist/integrations/linear/sync.js +174 -12
  177. package/dist/integrations/linear/sync.js.map +2 -2
  178. package/dist/integrations/linear/unified-sync.js +1 -1
  179. package/dist/integrations/linear/unified-sync.js.map +1 -1
  180. package/dist/integrations/linear/webhook-server.js +15 -16
  181. package/dist/integrations/linear/webhook-server.js.map +2 -2
  182. package/dist/mcp/stackmemory-mcp-server.js +0 -11
  183. package/dist/mcp/stackmemory-mcp-server.js.map +2 -2
  184. package/dist/servers/production/auth-middleware.js.map +2 -2
  185. package/dist/servers/railway/index.js.map +2 -2
  186. package/dist/services/config-service.js +6 -7
  187. package/dist/services/config-service.js.map +2 -2
  188. package/dist/services/context-service.js +11 -12
  189. package/dist/services/context-service.js.map +2 -2
  190. package/dist/skills/claude-skills.js +101 -2
  191. package/dist/skills/claude-skills.js.map +2 -2
  192. package/dist/skills/dashboard-launcher.js.map +2 -2
  193. package/dist/skills/recursive-agent-orchestrator.js +559 -0
  194. package/dist/skills/recursive-agent-orchestrator.js.map +7 -0
  195. package/dist/skills/repo-ingestion-skill.js.map +2 -2
  196. package/dist/skills/security-secrets-scanner.js +265 -0
  197. package/dist/skills/security-secrets-scanner.js.map +7 -0
  198. package/dist/utils/env.js +46 -0
  199. package/dist/utils/env.js.map +7 -0
  200. package/dist/utils/logger.js +0 -11
  201. package/dist/utils/logger.js.map +2 -2
  202. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/features/tui/services/data-service.ts"],
4
- "sourcesContent": ["/**\n * Data Service\n * Manages data fetching and caching for TUI dashboard\n */\n\nimport { EventEmitter } from 'events';\nimport Database from 'better-sqlite3';\nimport { SessionManager } from '../../../core/session/session-manager.js';\nimport { FrameManager } from '../../../core/context/frame-manager.js';\nimport { LinearTaskReader } from './linear-task-reader.js';\nimport { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport type {} from './types.js';\n\n// Type-safe environment variable access\nfunction getEnv(key: string, defaultValue?: string): string {\n const value = process.env[key];\n if (value === undefined) {\n if (defaultValue !== undefined) return defaultValue;\n throw new Error(`Environment variable ${key} is required`);\n }\n return value;\n}\n\nfunction getOptionalEnv(key: string): string | undefined {\n return process.env[key];\n}\n\nimport {\n SessionData,\n LinearTask,\n FrameData,\n SubagentData,\n PRData,\n IssueData,\n AnalyticsData,\n} from '../types.js';\n\nexport class DataService extends EventEmitter {\n private db: Database.Database | null = null;\n private sessionManager: SessionManager | null = null;\n private frameManager: FrameManager | null = null;\n private taskReader: LinearTaskReader | null = null;\n private linearMappings: Map<string, any> = new Map();\n private cache: Map<string, { data: any; timestamp: number }> = new Map();\n private cacheTimeout = 5000; // 5 seconds\n\n async initialize(): Promise<void> {\n try {\n // Initialize database with error handling\n try {\n const dbPath = process.env['PROJECT_ROOT']\n ? `${process.env['PROJECT_ROOT']}/.stackmemory/context.db`\n : `${process.cwd()}/.stackmemory/context.db`;\n\n if (existsSync(dbPath)) {\n this.db = new Database(dbPath);\n }\n } catch (dbError: unknown) {\n if (process.env['DEBUG']) {\n console.log('Database not accessible, continuing without it');\n }\n }\n\n // Initialize task reader for Linear-synced tasks\n try {\n this.taskReader = new LinearTaskReader(process.env['PROJECT_ROOT'] || process.cwd());\n \n // Load Linear mappings\n this.linearMappings = this.taskReader.getMappings();\n \n if (process.env['DEBUG']) {\n const tasks = this.taskReader.getTasks();\n console.log(`LinearTaskReader initialized with ${tasks.length} tasks`);\n }\n } catch (tsError: unknown) {\n if (process.env['DEBUG']) {\n console.log('Task reader initialization failed:', tsError.message);\n }\n }\n\n // Initialize managers with error handling\n try {\n this.sessionManager = new SessionManager({\n enableMonitoring: true,\n });\n } catch (smError: unknown) {\n if (process.env['DEBUG']) {\n console.log('SessionManager initialization failed:', smError.message);\n }\n // Continue without session manager\n }\n\n if (this.db) {\n try {\n this.frameManager = new FrameManager(this.db, 'tui');\n } catch (fmError: unknown) {\n if (process.env['DEBUG']) {\n console.log('FrameManager initialization failed:', fmError.message);\n }\n // Continue without frame manager\n }\n }\n\n // Note: Linear clients removed - all syncing happens via webhook or scheduled scripts\n // The TUI only displays locally synced tasks from the task store\n if (process.env['DEBUG']) {\n console.log(\n 'TUI: Using local task store only (no direct Linear API calls)'\n );\n }\n\n this.emit('data:ready');\n } catch (error: unknown) {\n if (process.env['DEBUG']) {\n console.error('DataService initialization error:', error);\n }\n // Don't throw, just emit ready with mock data\n this.emit('data:ready');\n }\n }\n\n async getSessions(): Promise<SessionData[]> {\n const cached = this.getFromCache('sessions');\n if (cached) return cached;\n\n try {\n // Get active sessions from manager\n const activeSessions = this.sessionManager?.getActiveSessions() || [];\n\n // Try to get recent sessions from database\n let recentSessions = [];\n if (this.db) {\n try {\n const stmt = this.db.prepare(`\n SELECT * FROM sessions \n WHERE created_at > datetime('now', '-24 hours')\n ORDER BY created_at DESC\n LIMIT 20\n `);\n recentSessions = stmt.all() || [];\n } catch (dbError: unknown) {\n // Database table might not exist, continue with mock data\n if (process.env['DEBUG']) {\n console.log('Sessions table not found, using mock data');\n }\n }\n }\n\n // If no real data, provide mock sessions for demo\n if (activeSessions.length === 0 && recentSessions.length === 0) {\n const mockSessions = this.getMockSessions();\n this.setCache('sessions', mockSessions);\n return mockSessions;\n }\n\n // Combine and format\n const sessions: SessionData[] = [\n ...activeSessions.map(this.formatSession),\n ...recentSessions.map(this.formatDatabaseSession),\n ];\n\n this.setCache('sessions', sessions);\n return sessions;\n } catch (error: unknown) {\n if (process.env['DEBUG']) {\n console.error('Error getting sessions:', error);\n }\n return this.getMockSessions();\n }\n }\n\n async getTasks(): Promise<LinearTask[]> {\n const cached = this.getFromCache('tasks');\n if (cached) return cached;\n\n const tasks: LinearTask[] = [];\n\n // ONLY use locally synced tasks - no direct Linear API calls\n // Tasks should be synced via webhook or scheduled sync scripts\n if (this.taskReader) {\n try {\n // LinearTaskReader already returns tasks in the correct format\n const localTasks = this.taskReader.getTasks();\n tasks.push(...localTasks);\n\n if (process.env['DEBUG']) {\n console.log(\n `Loaded ${tasks.length} tasks from local store (no Linear API calls)`\n );\n }\n } catch (error: unknown) {\n if (process.env['DEBUG']) {\n console.log('Failed to get local tasks:', error.message);\n }\n }\n }\n\n // If no local tasks, show helpful message instead of mock data\n if (tasks.length === 0) {\n console.log(\n '\u2139\uFE0F No local tasks found. Run \"npm run linear:sync\" to sync tasks from Linear.'\n );\n const mockTasks = this.getMockTasks();\n this.setCache('tasks', mockTasks);\n return mockTasks;\n }\n\n this.setCache('tasks', tasks);\n return tasks;\n }\n\n async getFrames(): Promise<FrameData[]> {\n const cached = this.getFromCache('frames');\n if (cached) return cached;\n\n try {\n const frames = this.frameManager?.getAllFrames() || [];\n\n // If no frames, return mock data\n if (frames.length === 0) {\n const mockFrames = this.getMockFrames();\n this.setCache('frames', mockFrames);\n return mockFrames;\n }\n\n const formatted = frames.map(this.formatFrame);\n this.setCache('frames', formatted);\n return formatted;\n } catch (error: unknown) {\n if (process.env['DEBUG']) {\n console.error('Error getting frames:', error);\n }\n // Return mock frames on error\n const mockFrames = this.getMockFrames();\n this.setCache('frames', mockFrames);\n return mockFrames;\n }\n }\n\n async getAgents(): Promise<SubagentData[]> {\n const cached = this.getFromCache('agents');\n if (cached) return cached;\n\n try {\n // Mock data for now - would integrate with actual agent manager\n const agents: SubagentData[] = [\n {\n id: 'agent-1',\n type: 'analyzer',\n status: 'active',\n currentTask: {\n id: 'task-1',\n description: 'Analyzing codebase for performance issues',\n progress: 0.65,\n startTime: Date.now() - 120000,\n },\n tasksCompleted: 42,\n tasksFailed: 3,\n averageTime: 180000,\n successRate: 0.93,\n cpuUsage: 45,\n memoryUsage: 62,\n tokenUsage: 125000,\n },\n {\n id: 'agent-2',\n type: 'builder',\n status: 'idle',\n tasksCompleted: 28,\n tasksFailed: 1,\n averageTime: 240000,\n successRate: 0.96,\n cpuUsage: 12,\n memoryUsage: 38,\n tokenUsage: 85000,\n },\n {\n id: 'agent-3',\n type: 'tester',\n status: 'error',\n tasksCompleted: 15,\n tasksFailed: 5,\n averageTime: 90000,\n successRate: 0.75,\n lastError: {\n message: 'Test suite timeout',\n timestamp: Date.now() - 60000,\n recoverable: true,\n },\n cpuUsage: 0,\n memoryUsage: 25,\n tokenUsage: 45000,\n },\n ];\n\n this.setCache('agents', agents);\n return agents;\n } catch (error: unknown) {\n this.emit('error', error);\n return [];\n }\n }\n\n async getPRs(): Promise<PRData[]> {\n const cached = this.getFromCache('prs');\n if (cached) return cached;\n\n try {\n // Mock data - would integrate with GitHub API\n const prs: PRData[] = [\n {\n id: 'pr-1',\n number: 142,\n title: 'feat: Add TUI monitoring dashboard',\n state: 'open',\n draft: false,\n author: { login: 'stackmemory-bot' },\n reviews: [{ user: 'reviewer1', state: 'approved' }],\n checks: {\n total: 5,\n passed: 3,\n failed: 0,\n pending: 2,\n },\n createdAt: new Date(Date.now() - 3600000).toISOString(),\n updatedAt: new Date().toISOString(),\n additions: 1250,\n deletions: 85,\n changedFiles: 12,\n comments: 3,\n labels: ['enhancement', 'monitoring'],\n linearTask: 'STA-100',\n },\n ];\n\n this.setCache('prs', prs);\n return prs;\n } catch (error: unknown) {\n this.emit('error', error);\n return [];\n }\n }\n\n async getIssues(): Promise<IssueData[]> {\n const cached = this.getFromCache('issues');\n if (cached) return cached;\n\n try {\n // Mock data - would integrate with GitHub API\n const issues: IssueData[] = [\n {\n id: 'issue-1',\n number: 89,\n title: 'Session monitoring improvements needed',\n state: 'open',\n author: { login: 'user1' },\n assignees: ['stackmemory-bot'],\n labels: ['enhancement', 'monitoring'],\n createdAt: new Date(Date.now() - 86400000).toISOString(),\n updatedAt: new Date().toISOString(),\n comments: 5,\n },\n ];\n\n this.setCache('issues', issues);\n return issues;\n } catch (error: unknown) {\n this.emit('error', error);\n return [];\n }\n }\n\n async getAnalytics(): Promise<AnalyticsData> {\n const cached = this.getFromCache('analytics');\n if (cached) return cached;\n\n try {\n // Generate analytics data\n const analytics: AnalyticsData = {\n sessions: {\n labels: ['1h', '2h', '3h', '4h', '5h', '6h'],\n values: [5, 8, 12, 15, 18, 22],\n },\n tokens: {\n labels: ['1h', '2h', '3h', '4h', '5h', '6h'],\n values: [12000, 25000, 45000, 62000, 78000, 95000],\n },\n tasks: {\n completed: 45,\n inProgress: 12,\n todo: 28,\n velocity: [8, 12, 15, 18, 20],\n },\n quality: {\n testsPassed: 142,\n testsFailed: 3,\n coverage: 78,\n lintErrors: 0,\n },\n performance: {\n avgResponseTime: [120, 115, 108, 105, 110],\n errorRate: [0.02, 0.015, 0.01, 0.008, 0.005],\n throughput: [100, 120, 135, 140, 145],\n },\n };\n\n this.setCache('analytics', analytics);\n return analytics;\n } catch (error: unknown) {\n this.emit('error', error);\n return {\n sessions: { labels: [], values: [] },\n tokens: { labels: [], values: [] },\n tasks: { completed: 0, inProgress: 0, todo: 0, velocity: [] },\n quality: { testsPassed: 0, testsFailed: 0, coverage: 0, lintErrors: 0 },\n performance: { avgResponseTime: [], errorRate: [], throughput: [] },\n };\n }\n }\n\n private formatSession(session: any): SessionData {\n return {\n id: session.id,\n startTime: session.startTime,\n lastActivity: session.lastActivity,\n completed: session.completed,\n error: session.error,\n totalTokens: session.totalTokens,\n contextUsage: session.contextUsage || 0,\n filesEdited: session.filesEdited,\n commandsRun: session.commandsRun,\n errors: session.errors,\n primaryFile: session.primaryFile,\n gitBranch: session.gitBranch,\n lastCommit: session.lastCommit,\n linearTask: session.linearTask,\n agentType: session.agentType,\n recentActivities: session.recentActivities,\n };\n }\n\n private formatDatabaseSession(row: any): SessionData {\n return {\n id: row.id,\n startTime: new Date(row.created_at).getTime(),\n lastActivity: row.updated_at\n ? new Date(row.updated_at).getTime()\n : undefined,\n completed: row.status === 'completed',\n totalTokens: row.token_count,\n contextUsage: row.context_usage || 0,\n filesEdited: row.files_edited ? JSON.parse(row.files_edited) : [],\n commandsRun: row.commands_run || 0,\n };\n }\n\n private formatLinearTask(task: any): LinearTask {\n return {\n id: task.id,\n identifier: task.identifier,\n title: task.title,\n description: task.description,\n // Use Linear state.type for stable mapping ('unstarted'|'started'|...)\n state: task.state?.type || task.state?.name,\n priority: task.priority,\n estimate: task.estimate,\n dueDate: task.dueDate,\n assignee: task.assignee\n ? {\n id: task.assignee.id,\n name: task.assignee.name,\n email: task.assignee.email,\n }\n : undefined,\n labels: task.labels?.nodes.map((l: any) => l.name),\n project: task.project\n ? {\n id: task.project.id,\n name: task.project.name,\n key: task.project.key,\n }\n : undefined,\n };\n }\n\n private formatRestLinearTask(task: any): LinearTask {\n // Map Linear state.type to TUI display states\n const stateMap: Record<string, string> = {\n backlog: 'Backlog',\n unstarted: 'To Do',\n started: 'In Progress',\n completed: 'Done',\n canceled: 'Canceled',\n };\n\n return {\n id: task.id,\n identifier: task.identifier,\n title: task.title,\n description: task.description,\n state: stateMap[task.state.type] || task.state.name,\n priority: task.priority,\n estimate: task.estimate,\n assignee: task.assignee ? task.assignee.name : undefined,\n createdAt: task.createdAt,\n updatedAt: task.updatedAt,\n };\n }\n\n private formatFrame(frame: any): FrameData {\n return {\n id: frame.id,\n sessionId: frame.sessionId,\n parentId: frame.parentId,\n type: frame.type || 'leaf',\n inputs: frame.inputs,\n outputs: frame.outputs,\n tools: frame.tools,\n digest: frame.digest,\n timestamp: frame.timestamp,\n tokenCount: frame.tokenCount || 0,\n tier: frame.tier || 'hot',\n compressionRatio: frame.compressionRatio,\n score: frame.score,\n children: frame.children,\n references: frame.references,\n };\n }\n\n private getFromCache(key: string): any {\n const cached = this.cache.get(key);\n if (cached && Date.now() - cached.timestamp < this.cacheTimeout) {\n return cached.data;\n }\n return null;\n }\n\n private setCache(key: string, data: any): void {\n this.cache.set(key, { data, timestamp: Date.now() });\n }\n\n private mapLocalStatusToLinearState(status: string): string {\n const statusMap: Record<string, string> = {\n pending: 'To Do',\n in_progress: 'In Progress',\n completed: 'Done',\n cancelled: 'Canceled',\n blocked: 'To Do',\n };\n return statusMap[status] || 'To Do';\n }\n\n private mapLocalPriorityToLinear(priority: string): number {\n const priorityMap: Record<string, number> = {\n urgent: 0,\n high: 1,\n medium: 2,\n low: 3,\n };\n return priorityMap[priority] || 2;\n }\n\n cleanup(): void {\n if (this.db) {\n this.db.close();\n }\n this.cache.clear();\n }\n\n // Mock data methods for demo/offline mode\n private getMockSessions(): SessionData[] {\n const now = Date.now();\n return [\n {\n id: 'demo-session-1',\n startTime: now - 8100000, // 2h 15m ago\n lastActivity: now - 60000, // 1 minute ago\n completed: false,\n totalTokens: 45000,\n contextUsage: 0.45, // 45%\n filesEdited: ['src/components/Dashboard.tsx', 'src/hooks/useAuth.ts'],\n commandsRun: 23,\n primaryFile: 'src/components/Dashboard.tsx',\n gitBranch: 'feature/tui-dashboard',\n agentType: 'frontend',\n recentActivities: [\n {\n timestamp: now - 120000,\n type: 'file_edit' as const,\n description: 'Modified Dashboard.tsx',\n },\n {\n timestamp: now - 60000,\n type: 'command' as const,\n description: 'npm run test',\n },\n ],\n },\n {\n id: 'demo-session-2',\n startTime: now - 2700000, // 45m ago\n lastActivity: now - 300000, // 5 minutes ago\n completed: false,\n totalTokens: 22000,\n contextUsage: 0.22, // 22%\n filesEdited: ['src/api/endpoints.ts', 'src/middleware/auth.ts'],\n commandsRun: 15,\n primaryFile: 'src/api/endpoints.ts',\n gitBranch: 'main',\n agentType: 'backend',\n recentActivities: [\n {\n timestamp: now - 600000,\n type: 'file_edit' as const,\n description: 'Updated API endpoints',\n },\n ],\n },\n ];\n }\n\n private getMockFrames(): FrameData[] {\n return [\n {\n id: 'frame-1',\n sessionId: 'demo-session-1',\n type: 'root',\n tier: 'hot' as const,\n timestamp: new Date().toISOString(),\n tokenCount: 2500,\n score: 95,\n compressionRatio: 2.3,\n digest: 'Implementing React component with hooks',\n tools: ['Edit', 'Read', 'MultiEdit'],\n inputs: ['Create user dashboard'],\n outputs: ['Dashboard component created'],\n children: [],\n references: [],\n },\n {\n id: 'frame-2',\n sessionId: 'demo-session-1',\n type: 'branch',\n tier: 'warm' as const,\n timestamp: new Date(Date.now() - 3600000).toISOString(),\n tokenCount: 1800,\n score: 78,\n compressionRatio: 1.8,\n digest: 'Setting up API endpoints',\n tools: ['Write', 'Edit'],\n inputs: ['Setup REST API'],\n outputs: ['API routes configured'],\n children: [],\n references: [],\n },\n ];\n }\n\n private getMockTasks(): LinearTask[] {\n return [\n {\n id: 'task-1',\n identifier: 'STA-101',\n title: 'Implement TUI dashboard',\n state: 'In Progress',\n priority: 2,\n assignee: 'demo-user',\n createdAt: new Date(Date.now() - 86400000).toISOString(),\n updatedAt: new Date().toISOString(),\n },\n {\n id: 'task-2',\n identifier: 'STA-102',\n title: 'Add terminal compatibility',\n state: 'Done',\n priority: 1,\n assignee: 'demo-user',\n createdAt: new Date(Date.now() - 172800000).toISOString(),\n updatedAt: new Date().toISOString(),\n },\n ];\n }\n\n private getMockAgents(): SubagentData[] {\n return [\n {\n id: 'agent-1',\n name: 'code-reviewer',\n type: 'reviewer',\n status: 'idle',\n tasksCompleted: 45,\n averageTime: '2.3s',\n successRate: 98.5,\n lastActive: new Date().toISOString(),\n },\n {\n id: 'agent-2',\n name: 'test-runner',\n type: 'qa',\n status: 'active',\n tasksCompleted: 156,\n averageTime: '5.6s',\n successRate: 95.2,\n lastActive: new Date().toISOString(),\n },\n ];\n }\n\n private getMockPRs(): PRData[] {\n return [\n {\n id: 'pr-1',\n number: 123,\n title: 'feat: Add terminal compatibility layer',\n state: 'open',\n author: { login: 'demo-user' },\n assignees: [],\n labels: ['enhancement', 'tui'],\n createdAt: new Date(Date.now() - 86400000).toISOString(),\n updatedAt: new Date().toISOString(),\n comments: 3,\n reviews: 1,\n checks: {\n total: 5,\n passed: 5,\n failed: 0,\n pending: 0,\n },\n },\n ];\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Data Service\n * Manages data fetching and caching for TUI dashboard\n */\n\nimport { EventEmitter } from 'events';\nimport Database from 'better-sqlite3';\nimport { SessionManager } from '../../../core/session/session-manager.js';\nimport { FrameManager } from '../../../core/context/frame-manager.js';\nimport { LinearTaskReader } from './linear-task-reader.js';\nimport { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport type {} from './types.js';\n\n// Type-safe environment variable access\nfunction getEnv(key: string, defaultValue?: string): string {\n const value = process.env[key];\n if (value === undefined) {\n if (defaultValue !== undefined) return defaultValue;\n throw new Error(`Environment variable ${key} is required`);\n }\n return value;\n}\n\nfunction getOptionalEnv(key: string): string | undefined {\n return process.env[key];\n}\n\nimport {\n SessionData,\n LinearTask,\n FrameData,\n SubagentData,\n PRData,\n IssueData,\n AnalyticsData,\n} from '../types.js';\n\nexport class DataService extends EventEmitter {\n private db: Database.Database | null = null;\n private sessionManager: SessionManager | null = null;\n private frameManager: FrameManager | null = null;\n private taskReader: LinearTaskReader | null = null;\n private linearMappings: Map<string, any> = new Map();\n private cache: Map<string, { data: any; timestamp: number }> = new Map();\n private cacheTimeout = 5000; // 5 seconds\n\n async initialize(): Promise<void> {\n try {\n // Initialize database with error handling\n try {\n const dbPath = process.env['PROJECT_ROOT']\n ? `${process.env['PROJECT_ROOT']}/.stackmemory/context.db`\n : `${process.cwd()}/.stackmemory/context.db`;\n\n if (existsSync(dbPath)) {\n this.db = new Database(dbPath);\n }\n } catch (dbError: unknown) {\n if (process.env['DEBUG']) {\n console.log('Database not accessible, continuing without it');\n }\n }\n\n // Initialize task reader for Linear-synced tasks\n try {\n this.taskReader = new LinearTaskReader(\n process.env['PROJECT_ROOT'] || process.cwd()\n );\n\n // Load Linear mappings\n this.linearMappings = this.taskReader.getMappings();\n\n if (process.env['DEBUG']) {\n const tasks = this.taskReader.getTasks();\n console.log(\n `LinearTaskReader initialized with ${tasks.length} tasks`\n );\n }\n } catch (tsError: unknown) {\n if (process.env['DEBUG']) {\n console.log('Task reader initialization failed:', tsError.message);\n }\n }\n\n // Initialize managers with error handling\n try {\n this.sessionManager = new SessionManager({\n enableMonitoring: true,\n });\n } catch (smError: unknown) {\n if (process.env['DEBUG']) {\n console.log('SessionManager initialization failed:', smError.message);\n }\n // Continue without session manager\n }\n\n if (this.db) {\n try {\n this.frameManager = new FrameManager(this.db, 'tui');\n } catch (fmError: unknown) {\n if (process.env['DEBUG']) {\n console.log('FrameManager initialization failed:', fmError.message);\n }\n // Continue without frame manager\n }\n }\n\n // Note: Linear clients removed - all syncing happens via webhook or scheduled scripts\n // The TUI only displays locally synced tasks from the task store\n if (process.env['DEBUG']) {\n console.log(\n 'TUI: Using local task store only (no direct Linear API calls)'\n );\n }\n\n this.emit('data:ready');\n } catch (error: unknown) {\n if (process.env['DEBUG']) {\n console.error('DataService initialization error:', error);\n }\n // Don't throw, just emit ready with mock data\n this.emit('data:ready');\n }\n }\n\n async getSessions(): Promise<SessionData[]> {\n const cached = this.getFromCache('sessions');\n if (cached) return cached;\n\n try {\n // Get active sessions from manager\n const activeSessions = this.sessionManager?.getActiveSessions() || [];\n\n // Try to get recent sessions from database\n let recentSessions = [];\n if (this.db) {\n try {\n const stmt = this.db.prepare(`\n SELECT * FROM sessions \n WHERE created_at > datetime('now', '-24 hours')\n ORDER BY created_at DESC\n LIMIT 20\n `);\n recentSessions = stmt.all() || [];\n } catch (dbError: unknown) {\n // Database table might not exist, continue with mock data\n if (process.env['DEBUG']) {\n console.log('Sessions table not found, using mock data');\n }\n }\n }\n\n // If no real data, provide mock sessions for demo\n if (activeSessions.length === 0 && recentSessions.length === 0) {\n const mockSessions = this.getMockSessions();\n this.setCache('sessions', mockSessions);\n return mockSessions;\n }\n\n // Combine and format\n const sessions: SessionData[] = [\n ...activeSessions.map(this.formatSession),\n ...recentSessions.map(this.formatDatabaseSession),\n ];\n\n this.setCache('sessions', sessions);\n return sessions;\n } catch (error: unknown) {\n if (process.env['DEBUG']) {\n console.error('Error getting sessions:', error);\n }\n return this.getMockSessions();\n }\n }\n\n async getTasks(): Promise<LinearTask[]> {\n const cached = this.getFromCache('tasks');\n if (cached) return cached;\n\n const tasks: LinearTask[] = [];\n\n // ONLY use locally synced tasks - no direct Linear API calls\n // Tasks should be synced via webhook or scheduled sync scripts\n if (this.taskReader) {\n try {\n // LinearTaskReader already returns tasks in the correct format\n const localTasks = this.taskReader.getTasks();\n tasks.push(...localTasks);\n\n if (process.env['DEBUG']) {\n console.log(\n `Loaded ${tasks.length} tasks from local store (no Linear API calls)`\n );\n }\n } catch (error: unknown) {\n if (process.env['DEBUG']) {\n console.log('Failed to get local tasks:', error.message);\n }\n }\n }\n\n // If no local tasks, show helpful message instead of mock data\n if (tasks.length === 0) {\n console.log(\n '\u2139\uFE0F No local tasks found. Run \"npm run linear:sync\" to sync tasks from Linear.'\n );\n const mockTasks = this.getMockTasks();\n this.setCache('tasks', mockTasks);\n return mockTasks;\n }\n\n this.setCache('tasks', tasks);\n return tasks;\n }\n\n async getFrames(): Promise<FrameData[]> {\n const cached = this.getFromCache('frames');\n if (cached) return cached;\n\n try {\n const frames = this.frameManager?.getAllFrames() || [];\n\n // If no frames, return mock data\n if (frames.length === 0) {\n const mockFrames = this.getMockFrames();\n this.setCache('frames', mockFrames);\n return mockFrames;\n }\n\n const formatted = frames.map(this.formatFrame);\n this.setCache('frames', formatted);\n return formatted;\n } catch (error: unknown) {\n if (process.env['DEBUG']) {\n console.error('Error getting frames:', error);\n }\n // Return mock frames on error\n const mockFrames = this.getMockFrames();\n this.setCache('frames', mockFrames);\n return mockFrames;\n }\n }\n\n async getAgents(): Promise<SubagentData[]> {\n const cached = this.getFromCache('agents');\n if (cached) return cached;\n\n try {\n // Mock data for now - would integrate with actual agent manager\n const agents: SubagentData[] = [\n {\n id: 'agent-1',\n type: 'analyzer',\n status: 'active',\n currentTask: {\n id: 'task-1',\n description: 'Analyzing codebase for performance issues',\n progress: 0.65,\n startTime: Date.now() - 120000,\n },\n tasksCompleted: 42,\n tasksFailed: 3,\n averageTime: 180000,\n successRate: 0.93,\n cpuUsage: 45,\n memoryUsage: 62,\n tokenUsage: 125000,\n },\n {\n id: 'agent-2',\n type: 'builder',\n status: 'idle',\n tasksCompleted: 28,\n tasksFailed: 1,\n averageTime: 240000,\n successRate: 0.96,\n cpuUsage: 12,\n memoryUsage: 38,\n tokenUsage: 85000,\n },\n {\n id: 'agent-3',\n type: 'tester',\n status: 'error',\n tasksCompleted: 15,\n tasksFailed: 5,\n averageTime: 90000,\n successRate: 0.75,\n lastError: {\n message: 'Test suite timeout',\n timestamp: Date.now() - 60000,\n recoverable: true,\n },\n cpuUsage: 0,\n memoryUsage: 25,\n tokenUsage: 45000,\n },\n ];\n\n this.setCache('agents', agents);\n return agents;\n } catch (error: unknown) {\n this.emit('error', error);\n return [];\n }\n }\n\n async getPRs(): Promise<PRData[]> {\n const cached = this.getFromCache('prs');\n if (cached) return cached;\n\n try {\n // Mock data - would integrate with GitHub API\n const prs: PRData[] = [\n {\n id: 'pr-1',\n number: 142,\n title: 'feat: Add TUI monitoring dashboard',\n state: 'open',\n draft: false,\n author: { login: 'stackmemory-bot' },\n reviews: [{ user: 'reviewer1', state: 'approved' }],\n checks: {\n total: 5,\n passed: 3,\n failed: 0,\n pending: 2,\n },\n createdAt: new Date(Date.now() - 3600000).toISOString(),\n updatedAt: new Date().toISOString(),\n additions: 1250,\n deletions: 85,\n changedFiles: 12,\n comments: 3,\n labels: ['enhancement', 'monitoring'],\n linearTask: 'STA-100',\n },\n ];\n\n this.setCache('prs', prs);\n return prs;\n } catch (error: unknown) {\n this.emit('error', error);\n return [];\n }\n }\n\n async getIssues(): Promise<IssueData[]> {\n const cached = this.getFromCache('issues');\n if (cached) return cached;\n\n try {\n // Mock data - would integrate with GitHub API\n const issues: IssueData[] = [\n {\n id: 'issue-1',\n number: 89,\n title: 'Session monitoring improvements needed',\n state: 'open',\n author: { login: 'user1' },\n assignees: ['stackmemory-bot'],\n labels: ['enhancement', 'monitoring'],\n createdAt: new Date(Date.now() - 86400000).toISOString(),\n updatedAt: new Date().toISOString(),\n comments: 5,\n },\n ];\n\n this.setCache('issues', issues);\n return issues;\n } catch (error: unknown) {\n this.emit('error', error);\n return [];\n }\n }\n\n async getAnalytics(): Promise<AnalyticsData> {\n const cached = this.getFromCache('analytics');\n if (cached) return cached;\n\n try {\n // Generate analytics data\n const analytics: AnalyticsData = {\n sessions: {\n labels: ['1h', '2h', '3h', '4h', '5h', '6h'],\n values: [5, 8, 12, 15, 18, 22],\n },\n tokens: {\n labels: ['1h', '2h', '3h', '4h', '5h', '6h'],\n values: [12000, 25000, 45000, 62000, 78000, 95000],\n },\n tasks: {\n completed: 45,\n inProgress: 12,\n todo: 28,\n velocity: [8, 12, 15, 18, 20],\n },\n quality: {\n testsPassed: 142,\n testsFailed: 3,\n coverage: 78,\n lintErrors: 0,\n },\n performance: {\n avgResponseTime: [120, 115, 108, 105, 110],\n errorRate: [0.02, 0.015, 0.01, 0.008, 0.005],\n throughput: [100, 120, 135, 140, 145],\n },\n };\n\n this.setCache('analytics', analytics);\n return analytics;\n } catch (error: unknown) {\n this.emit('error', error);\n return {\n sessions: { labels: [], values: [] },\n tokens: { labels: [], values: [] },\n tasks: { completed: 0, inProgress: 0, todo: 0, velocity: [] },\n quality: { testsPassed: 0, testsFailed: 0, coverage: 0, lintErrors: 0 },\n performance: { avgResponseTime: [], errorRate: [], throughput: [] },\n };\n }\n }\n\n private formatSession(session: any): SessionData {\n return {\n id: session.id,\n startTime: session.startTime,\n lastActivity: session.lastActivity,\n completed: session.completed,\n error: session.error,\n totalTokens: session.totalTokens,\n contextUsage: session.contextUsage || 0,\n filesEdited: session.filesEdited,\n commandsRun: session.commandsRun,\n errors: session.errors,\n primaryFile: session.primaryFile,\n gitBranch: session.gitBranch,\n lastCommit: session.lastCommit,\n linearTask: session.linearTask,\n agentType: session.agentType,\n recentActivities: session.recentActivities,\n };\n }\n\n private formatDatabaseSession(row: any): SessionData {\n return {\n id: row.id,\n startTime: new Date(row.created_at).getTime(),\n lastActivity: row.updated_at\n ? new Date(row.updated_at).getTime()\n : undefined,\n completed: row.status === 'completed',\n totalTokens: row.token_count,\n contextUsage: row.context_usage || 0,\n filesEdited: row.files_edited ? JSON.parse(row.files_edited) : [],\n commandsRun: row.commands_run || 0,\n };\n }\n\n private formatLinearTask(task: any): LinearTask {\n return {\n id: task.id,\n identifier: task.identifier,\n title: task.title,\n description: task.description,\n // Use Linear state.type for stable mapping ('unstarted'|'started'|...)\n state: task.state?.type || task.state?.name,\n priority: task.priority,\n estimate: task.estimate,\n dueDate: task.dueDate,\n assignee: task.assignee\n ? {\n id: task.assignee.id,\n name: task.assignee.name,\n email: task.assignee.email,\n }\n : undefined,\n labels: task.labels?.nodes.map((l: any) => l.name),\n project: task.project\n ? {\n id: task.project.id,\n name: task.project.name,\n key: task.project.key,\n }\n : undefined,\n };\n }\n\n private formatRestLinearTask(task: any): LinearTask {\n // Map Linear state.type to TUI display states\n const stateMap: Record<string, string> = {\n backlog: 'Backlog',\n unstarted: 'To Do',\n started: 'In Progress',\n completed: 'Done',\n canceled: 'Canceled',\n };\n\n return {\n id: task.id,\n identifier: task.identifier,\n title: task.title,\n description: task.description,\n state: stateMap[task.state.type] || task.state.name,\n priority: task.priority,\n estimate: task.estimate,\n assignee: task.assignee ? task.assignee.name : undefined,\n createdAt: task.createdAt,\n updatedAt: task.updatedAt,\n };\n }\n\n private formatFrame(frame: any): FrameData {\n return {\n id: frame.id,\n sessionId: frame.sessionId,\n parentId: frame.parentId,\n type: frame.type || 'leaf',\n inputs: frame.inputs,\n outputs: frame.outputs,\n tools: frame.tools,\n digest: frame.digest,\n timestamp: frame.timestamp,\n tokenCount: frame.tokenCount || 0,\n tier: frame.tier || 'hot',\n compressionRatio: frame.compressionRatio,\n score: frame.score,\n children: frame.children,\n references: frame.references,\n };\n }\n\n private getFromCache(key: string): any {\n const cached = this.cache.get(key);\n if (cached && Date.now() - cached.timestamp < this.cacheTimeout) {\n return cached.data;\n }\n return null;\n }\n\n private setCache(key: string, data: any): void {\n this.cache.set(key, { data, timestamp: Date.now() });\n }\n\n private mapLocalStatusToLinearState(status: string): string {\n const statusMap: Record<string, string> = {\n pending: 'To Do',\n in_progress: 'In Progress',\n completed: 'Done',\n cancelled: 'Canceled',\n blocked: 'To Do',\n };\n return statusMap[status] || 'To Do';\n }\n\n private mapLocalPriorityToLinear(priority: string): number {\n const priorityMap: Record<string, number> = {\n urgent: 0,\n high: 1,\n medium: 2,\n low: 3,\n };\n return priorityMap[priority] || 2;\n }\n\n cleanup(): void {\n if (this.db) {\n this.db.close();\n }\n this.cache.clear();\n }\n\n // Mock data methods for demo/offline mode\n private getMockSessions(): SessionData[] {\n const now = Date.now();\n return [\n {\n id: 'demo-session-1',\n startTime: now - 8100000, // 2h 15m ago\n lastActivity: now - 60000, // 1 minute ago\n completed: false,\n totalTokens: 45000,\n contextUsage: 0.45, // 45%\n filesEdited: ['src/components/Dashboard.tsx', 'src/hooks/useAuth.ts'],\n commandsRun: 23,\n primaryFile: 'src/components/Dashboard.tsx',\n gitBranch: 'feature/tui-dashboard',\n agentType: 'frontend',\n recentActivities: [\n {\n timestamp: now - 120000,\n type: 'file_edit' as const,\n description: 'Modified Dashboard.tsx',\n },\n {\n timestamp: now - 60000,\n type: 'command' as const,\n description: 'npm run test',\n },\n ],\n },\n {\n id: 'demo-session-2',\n startTime: now - 2700000, // 45m ago\n lastActivity: now - 300000, // 5 minutes ago\n completed: false,\n totalTokens: 22000,\n contextUsage: 0.22, // 22%\n filesEdited: ['src/api/endpoints.ts', 'src/middleware/auth.ts'],\n commandsRun: 15,\n primaryFile: 'src/api/endpoints.ts',\n gitBranch: 'main',\n agentType: 'backend',\n recentActivities: [\n {\n timestamp: now - 600000,\n type: 'file_edit' as const,\n description: 'Updated API endpoints',\n },\n ],\n },\n ];\n }\n\n private getMockFrames(): FrameData[] {\n return [\n {\n id: 'frame-1',\n sessionId: 'demo-session-1',\n type: 'root',\n tier: 'hot' as const,\n timestamp: new Date().toISOString(),\n tokenCount: 2500,\n score: 95,\n compressionRatio: 2.3,\n digest: 'Implementing React component with hooks',\n tools: ['Edit', 'Read', 'MultiEdit'],\n inputs: ['Create user dashboard'],\n outputs: ['Dashboard component created'],\n children: [],\n references: [],\n },\n {\n id: 'frame-2',\n sessionId: 'demo-session-1',\n type: 'branch',\n tier: 'warm' as const,\n timestamp: new Date(Date.now() - 3600000).toISOString(),\n tokenCount: 1800,\n score: 78,\n compressionRatio: 1.8,\n digest: 'Setting up API endpoints',\n tools: ['Write', 'Edit'],\n inputs: ['Setup REST API'],\n outputs: ['API routes configured'],\n children: [],\n references: [],\n },\n ];\n }\n\n private getMockTasks(): LinearTask[] {\n return [\n {\n id: 'task-1',\n identifier: 'STA-101',\n title: 'Implement TUI dashboard',\n state: 'In Progress',\n priority: 2,\n assignee: 'demo-user',\n createdAt: new Date(Date.now() - 86400000).toISOString(),\n updatedAt: new Date().toISOString(),\n },\n {\n id: 'task-2',\n identifier: 'STA-102',\n title: 'Add terminal compatibility',\n state: 'Done',\n priority: 1,\n assignee: 'demo-user',\n createdAt: new Date(Date.now() - 172800000).toISOString(),\n updatedAt: new Date().toISOString(),\n },\n ];\n }\n\n private getMockAgents(): SubagentData[] {\n return [\n {\n id: 'agent-1',\n name: 'code-reviewer',\n type: 'reviewer',\n status: 'idle',\n tasksCompleted: 45,\n averageTime: '2.3s',\n successRate: 98.5,\n lastActive: new Date().toISOString(),\n },\n {\n id: 'agent-2',\n name: 'test-runner',\n type: 'qa',\n status: 'active',\n tasksCompleted: 156,\n averageTime: '5.6s',\n successRate: 95.2,\n lastActive: new Date().toISOString(),\n },\n ];\n }\n\n private getMockPRs(): PRData[] {\n return [\n {\n id: 'pr-1',\n number: 123,\n title: 'feat: Add terminal compatibility layer',\n state: 'open',\n author: { login: 'demo-user' },\n assignees: [],\n labels: ['enhancement', 'tui'],\n createdAt: new Date(Date.now() - 86400000).toISOString(),\n updatedAt: new Date().toISOString(),\n comments: 3,\n reviews: 1,\n checks: {\n total: 5,\n passed: 5,\n failed: 0,\n pending: 0,\n },\n },\n ];\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -13,7 +13,9 @@ class LinearTaskReader {
13
13
  */
14
14
  getTasks() {
15
15
  if (!existsSync(this.tasksFile)) {
16
- console.log('No tasks file found. Run "npm run linear:sync" to sync tasks.');
16
+ console.log(
17
+ 'No tasks file found. Run "npm run linear:sync" to sync tasks.'
18
+ );
17
19
  return [];
18
20
  }
19
21
  try {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/features/tui/services/linear-task-reader.ts"],
4
- "sourcesContent": ["/**\n * Linear Task Reader for TUI\n * Reads Linear-synced tasks from tasks.jsonl\n */\n\nimport { readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport type { LinearTask } from '../types.js';\n\nexport class LinearTaskReader {\n private tasksFile: string;\n private mappingsFile: string;\n\n constructor(projectRoot?: string) {\n const root = projectRoot || process.cwd();\n this.tasksFile = join(root, '.stackmemory', 'tasks.jsonl');\n this.mappingsFile = join(root, '.stackmemory', 'linear-mappings.json');\n }\n\n /**\n * Read tasks from the Linear-synced JSONL file\n */\n getTasks(): LinearTask[] {\n if (!existsSync(this.tasksFile)) {\n console.log('No tasks file found. Run \"npm run linear:sync\" to sync tasks.');\n return [];\n }\n\n try {\n const content = readFileSync(this.tasksFile, 'utf8');\n const lines = content.split('\\n').filter(Boolean);\n \n const tasks: LinearTask[] = lines.map((line: any) => {\n const task = JSON.parse(line);\n \n // Convert from synced format to TUI LinearTask format\n return {\n id: task.id || task.linearId,\n identifier: task.taskId || task.linearId || task.id,\n title: task.title,\n description: task.description || '',\n state: task.linearState || this.mapStatusToState(task.status),\n priority: task.priority || 4,\n estimate: task.estimate,\n assignee: task.assignee,\n createdAt: task.createdAt,\n updatedAt: task.updatedAt,\n lastSyncedAt: task.updatedAt,\n syncStatus: 'synced',\n };\n });\n\n return tasks;\n } catch (error: unknown) {\n console.error('Error reading tasks:', error);\n return [];\n }\n }\n\n /**\n * Get task mappings between Linear and local IDs\n */\n getMappings(): Map<string, any> {\n if (!existsSync(this.mappingsFile)) {\n return new Map();\n }\n\n try {\n const content = readFileSync(this.mappingsFile, 'utf8');\n const mappings = JSON.parse(content);\n return new Map(Object.entries(mappings));\n } catch (error: unknown) {\n console.error('Error reading mappings:', error);\n return new Map();\n }\n }\n\n /**\n * Get active tasks (not completed or canceled)\n */\n getActiveTasks(): LinearTask[] {\n const allTasks = this.getTasks();\n return allTasks.filter((task: any) => \n task.state !== 'Done' && \n task.state !== 'Canceled' &&\n task.state !== 'Duplicate'\n );\n }\n\n /**\n * Get tasks by state\n */\n getTasksByState(state: string): LinearTask[] {\n const allTasks = this.getTasks();\n return allTasks.filter((task: any) => task.state === state);\n }\n\n /**\n * Map local status to Linear state name\n */\n private mapStatusToState(status: string): string {\n switch (status) {\n case 'completed': return 'Done';\n case 'in_progress': return 'In Progress';\n case 'cancelled': return 'Canceled';\n case 'backlog': return 'Backlog';\n case 'todo': return 'Todo';\n default: return 'Backlog';\n }\n }\n}"],
5
- "mappings": "AAKA,SAAS,cAAc,kBAAkB;AACzC,SAAS,YAAY;AAGd,MAAM,iBAAiB;AAAA,EACpB;AAAA,EACA;AAAA,EAER,YAAY,aAAsB;AAChC,UAAM,OAAO,eAAe,QAAQ,IAAI;AACxC,SAAK,YAAY,KAAK,MAAM,gBAAgB,aAAa;AACzD,SAAK,eAAe,KAAK,MAAM,gBAAgB,sBAAsB;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA,EAKA,WAAyB;AACvB,QAAI,CAAC,WAAW,KAAK,SAAS,GAAG;AAC/B,cAAQ,IAAI,+DAA+D;AAC3E,aAAO,CAAC;AAAA,IACV;AAEA,QAAI;AACF,YAAM,UAAU,aAAa,KAAK,WAAW,MAAM;AACnD,YAAM,QAAQ,QAAQ,MAAM,IAAI,EAAE,OAAO,OAAO;AAEhD,YAAM,QAAsB,MAAM,IAAI,CAAC,SAAc;AACnD,cAAM,OAAO,KAAK,MAAM,IAAI;AAG5B,eAAO;AAAA,UACL,IAAI,KAAK,MAAM,KAAK;AAAA,UACpB,YAAY,KAAK,UAAU,KAAK,YAAY,KAAK;AAAA,UACjD,OAAO,KAAK;AAAA,UACZ,aAAa,KAAK,eAAe;AAAA,UACjC,OAAO,KAAK,eAAe,KAAK,iBAAiB,KAAK,MAAM;AAAA,UAC5D,UAAU,KAAK,YAAY;AAAA,UAC3B,UAAU,KAAK;AAAA,UACf,UAAU,KAAK;AAAA,UACf,WAAW,KAAK;AAAA,UAChB,WAAW,KAAK;AAAA,UAChB,cAAc,KAAK;AAAA,UACnB,YAAY;AAAA,QACd;AAAA,MACF,CAAC;AAED,aAAO;AAAA,IACT,SAAS,OAAgB;AACvB,cAAQ,MAAM,wBAAwB,KAAK;AAC3C,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,cAAgC;AAC9B,QAAI,CAAC,WAAW,KAAK,YAAY,GAAG;AAClC,aAAO,oBAAI,IAAI;AAAA,IACjB;AAEA,QAAI;AACF,YAAM,UAAU,aAAa,KAAK,cAAc,MAAM;AACtD,YAAM,WAAW,KAAK,MAAM,OAAO;AACnC,aAAO,IAAI,IAAI,OAAO,QAAQ,QAAQ,CAAC;AAAA,IACzC,SAAS,OAAgB;AACvB,cAAQ,MAAM,2BAA2B,KAAK;AAC9C,aAAO,oBAAI,IAAI;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,iBAA+B;AAC7B,UAAM,WAAW,KAAK,SAAS;AAC/B,WAAO,SAAS;AAAA,MAAO,CAAC,SACtB,KAAK,UAAU,UACf,KAAK,UAAU,cACf,KAAK,UAAU;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,OAA6B;AAC3C,UAAM,WAAW,KAAK,SAAS;AAC/B,WAAO,SAAS,OAAO,CAAC,SAAc,KAAK,UAAU,KAAK;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAiB,QAAwB;AAC/C,YAAQ,QAAQ;AAAA,MACd,KAAK;AAAa,eAAO;AAAA,MACzB,KAAK;AAAe,eAAO;AAAA,MAC3B,KAAK;AAAa,eAAO;AAAA,MACzB,KAAK;AAAW,eAAO;AAAA,MACvB,KAAK;AAAQ,eAAO;AAAA,MACpB;AAAS,eAAO;AAAA,IAClB;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["/**\n * Linear Task Reader for TUI\n * Reads Linear-synced tasks from tasks.jsonl\n */\n\nimport { readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport type { LinearTask } from '../types.js';\n\nexport class LinearTaskReader {\n private tasksFile: string;\n private mappingsFile: string;\n\n constructor(projectRoot?: string) {\n const root = projectRoot || process.cwd();\n this.tasksFile = join(root, '.stackmemory', 'tasks.jsonl');\n this.mappingsFile = join(root, '.stackmemory', 'linear-mappings.json');\n }\n\n /**\n * Read tasks from the Linear-synced JSONL file\n */\n getTasks(): LinearTask[] {\n if (!existsSync(this.tasksFile)) {\n console.log(\n 'No tasks file found. Run \"npm run linear:sync\" to sync tasks.'\n );\n return [];\n }\n\n try {\n const content = readFileSync(this.tasksFile, 'utf8');\n const lines = content.split('\\n').filter(Boolean);\n\n const tasks: LinearTask[] = lines.map((line: any) => {\n const task = JSON.parse(line);\n\n // Convert from synced format to TUI LinearTask format\n return {\n id: task.id || task.linearId,\n identifier: task.taskId || task.linearId || task.id,\n title: task.title,\n description: task.description || '',\n state: task.linearState || this.mapStatusToState(task.status),\n priority: task.priority || 4,\n estimate: task.estimate,\n assignee: task.assignee,\n createdAt: task.createdAt,\n updatedAt: task.updatedAt,\n lastSyncedAt: task.updatedAt,\n syncStatus: 'synced',\n };\n });\n\n return tasks;\n } catch (error: unknown) {\n console.error('Error reading tasks:', error);\n return [];\n }\n }\n\n /**\n * Get task mappings between Linear and local IDs\n */\n getMappings(): Map<string, any> {\n if (!existsSync(this.mappingsFile)) {\n return new Map();\n }\n\n try {\n const content = readFileSync(this.mappingsFile, 'utf8');\n const mappings = JSON.parse(content);\n return new Map(Object.entries(mappings));\n } catch (error: unknown) {\n console.error('Error reading mappings:', error);\n return new Map();\n }\n }\n\n /**\n * Get active tasks (not completed or canceled)\n */\n getActiveTasks(): LinearTask[] {\n const allTasks = this.getTasks();\n return allTasks.filter(\n (task: any) =>\n task.state !== 'Done' &&\n task.state !== 'Canceled' &&\n task.state !== 'Duplicate'\n );\n }\n\n /**\n * Get tasks by state\n */\n getTasksByState(state: string): LinearTask[] {\n const allTasks = this.getTasks();\n return allTasks.filter((task: any) => task.state === state);\n }\n\n /**\n * Map local status to Linear state name\n */\n private mapStatusToState(status: string): string {\n switch (status) {\n case 'completed':\n return 'Done';\n case 'in_progress':\n return 'In Progress';\n case 'cancelled':\n return 'Canceled';\n case 'backlog':\n return 'Backlog';\n case 'todo':\n return 'Todo';\n default:\n return 'Backlog';\n }\n }\n}\n"],
5
+ "mappings": "AAKA,SAAS,cAAc,kBAAkB;AACzC,SAAS,YAAY;AAGd,MAAM,iBAAiB;AAAA,EACpB;AAAA,EACA;AAAA,EAER,YAAY,aAAsB;AAChC,UAAM,OAAO,eAAe,QAAQ,IAAI;AACxC,SAAK,YAAY,KAAK,MAAM,gBAAgB,aAAa;AACzD,SAAK,eAAe,KAAK,MAAM,gBAAgB,sBAAsB;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA,EAKA,WAAyB;AACvB,QAAI,CAAC,WAAW,KAAK,SAAS,GAAG;AAC/B,cAAQ;AAAA,QACN;AAAA,MACF;AACA,aAAO,CAAC;AAAA,IACV;AAEA,QAAI;AACF,YAAM,UAAU,aAAa,KAAK,WAAW,MAAM;AACnD,YAAM,QAAQ,QAAQ,MAAM,IAAI,EAAE,OAAO,OAAO;AAEhD,YAAM,QAAsB,MAAM,IAAI,CAAC,SAAc;AACnD,cAAM,OAAO,KAAK,MAAM,IAAI;AAG5B,eAAO;AAAA,UACL,IAAI,KAAK,MAAM,KAAK;AAAA,UACpB,YAAY,KAAK,UAAU,KAAK,YAAY,KAAK;AAAA,UACjD,OAAO,KAAK;AAAA,UACZ,aAAa,KAAK,eAAe;AAAA,UACjC,OAAO,KAAK,eAAe,KAAK,iBAAiB,KAAK,MAAM;AAAA,UAC5D,UAAU,KAAK,YAAY;AAAA,UAC3B,UAAU,KAAK;AAAA,UACf,UAAU,KAAK;AAAA,UACf,WAAW,KAAK;AAAA,UAChB,WAAW,KAAK;AAAA,UAChB,cAAc,KAAK;AAAA,UACnB,YAAY;AAAA,QACd;AAAA,MACF,CAAC;AAED,aAAO;AAAA,IACT,SAAS,OAAgB;AACvB,cAAQ,MAAM,wBAAwB,KAAK;AAC3C,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,cAAgC;AAC9B,QAAI,CAAC,WAAW,KAAK,YAAY,GAAG;AAClC,aAAO,oBAAI,IAAI;AAAA,IACjB;AAEA,QAAI;AACF,YAAM,UAAU,aAAa,KAAK,cAAc,MAAM;AACtD,YAAM,WAAW,KAAK,MAAM,OAAO;AACnC,aAAO,IAAI,IAAI,OAAO,QAAQ,QAAQ,CAAC;AAAA,IACzC,SAAS,OAAgB;AACvB,cAAQ,MAAM,2BAA2B,KAAK;AAC9C,aAAO,oBAAI,IAAI;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,iBAA+B;AAC7B,UAAM,WAAW,KAAK,SAAS;AAC/B,WAAO,SAAS;AAAA,MACd,CAAC,SACC,KAAK,UAAU,UACf,KAAK,UAAU,cACf,KAAK,UAAU;AAAA,IACnB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,OAA6B;AAC3C,UAAM,WAAW,KAAK,SAAS;AAC/B,WAAO,SAAS,OAAO,CAAC,SAAc,KAAK,UAAU,KAAK;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAiB,QAAwB;AAC/C,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IACX;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -126,7 +126,9 @@ class WebSocketClient extends EventEmitter {
126
126
  }
127
127
  this.reconnectAttempts++;
128
128
  const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
129
- console.log(`Attempting to reconnect in ${delay}ms (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})`);
129
+ console.log(
130
+ `Attempting to reconnect in ${delay}ms (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})`
131
+ );
130
132
  this.reconnectTimer = setTimeout(() => {
131
133
  this.connect().catch((error) => {
132
134
  console.error("Reconnection failed:", error);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/features/tui/services/websocket-client.ts"],
4
- "sourcesContent": ["/**\n * WebSocket Client\n * Real-time data streaming for TUI dashboard\n */\n\nimport { EventEmitter } from 'events';\nimport WebSocket from 'ws';\n// Type-safe environment variable access\nfunction getEnv(key: string, defaultValue?: string): string {\n const value = process.env[key];\n if (value === undefined) {\n if (defaultValue !== undefined) return defaultValue;\n throw new Error(`Environment variable ${key} is required`);\n }\n return value;\n}\n\nfunction getOptionalEnv(key: string): string | undefined {\n return process.env[key];\n}\n\n\nexport class WebSocketClient extends EventEmitter {\n private ws: WebSocket | null = null;\n private url: string;\n private reconnectTimer: NodeJS.Timeout | null = null;\n private reconnectAttempts = 0;\n private maxReconnectAttempts = 10;\n private reconnectDelay = 1000;\n\n constructor(url: string) {\n super();\n this.url = url;\n }\n\n async connect(): Promise<void> {\n return new Promise((resolve) => {\n try {\n // Add error handler before creating WebSocket to catch connection errors\n const handleError = (error: Error) => {\n clearTimeout(connectionTimeout);\n // Silent error handling - continue in offline mode\n if (process.env['DEBUG']) {\n console.log('WebSocket connection failed:', error.message);\n }\n if (this.ws) {\n this.ws.removeAllListeners();\n this.ws.terminate();\n this.ws = null;\n }\n resolve(); // Always resolve to continue in offline mode\n };\n\n // Set a timeout for connection\n const connectionTimeout = setTimeout(() => {\n if (this.ws) {\n this.ws.removeAllListeners();\n this.ws.terminate();\n this.ws = null;\n }\n console.log('\u26A0\uFE0F Running in offline mode (no WebSocket server)');\n this.emit('offline');\n resolve();\n }, 1000); // Reduce timeout to 1 second\n\n try {\n this.ws = new WebSocket(this.url);\n } catch (wsError: unknown) {\n handleError(wsError as Error);\n return;\n }\n\n // Immediately add error handler to catch connection errors\n this.ws.once('error', handleError);\n\n this.ws.once('open', () => {\n clearTimeout(connectionTimeout);\n // Remove the error handler and add a new one for ongoing errors\n this.ws?.removeListener('error', handleError);\n this.ws?.on('error', (error: Error) => {\n if (process.env['DEBUG']) {\n console.error('WebSocket error during operation:', error);\n }\n this.emit('error', error);\n });\n \n console.log('\u2705 WebSocket connected');\n this.reconnectAttempts = 0;\n this.emit('connected');\n resolve();\n });\n\n this.ws.on('message', (data: WebSocket.Data) => {\n this.handleMessage(data);\n });\n\n this.ws.once('close', () => {\n clearTimeout(connectionTimeout);\n if (this.reconnectAttempts > 0) {\n console.log('WebSocket disconnected');\n this.emit('disconnected');\n this.attemptReconnect();\n }\n // If this is the first close, just resolve\n resolve();\n });\n\n } catch (error: unknown) {\n // If anything fails, continue in offline mode\n console.log('\u26A0\uFE0F Running in offline mode');\n this.emit('offline');\n resolve();\n }\n });\n }\n\n private handleMessage(data: WebSocket.Data): void {\n try {\n const message = JSON.parse(data.toString());\n \n switch (message.type) {\n case 'session:update':\n this.emit('session:update', message.data);\n break;\n \n case 'task:update':\n this.emit('task:update', message.data);\n break;\n \n case 'frame:update':\n this.emit('frame:update', message.data);\n break;\n \n case 'agent:status':\n this.emit('agent:status', message.data);\n break;\n \n case 'pr:update':\n this.emit('pr:update', message.data);\n break;\n \n case 'analytics:update':\n this.emit('analytics:update', message.data);\n break;\n \n case 'notification':\n this.emit('notification', message.data);\n break;\n \n default:\n this.emit('message', message);\n }\n } catch (error: unknown) {\n console.error('Failed to parse WebSocket message:', error);\n }\n }\n\n private attemptReconnect(): void {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n this.emit('error', new Error('Max reconnection attempts reached'));\n return;\n }\n\n this.reconnectAttempts++;\n const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);\n\n console.log(`Attempting to reconnect in ${delay}ms (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})`);\n\n this.reconnectTimer = setTimeout(() => {\n this.connect().catch(error => {\n console.error('Reconnection failed:', error);\n });\n }, delay);\n }\n\n send(type: string, data: any): void {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify({ type, data }));\n } else {\n console.warn('WebSocket is not connected');\n }\n }\n\n disconnect(): void {\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n }\n\n isConnected(): boolean {\n return this.ws !== null && this.ws.readyState === WebSocket.OPEN;\n }\n}"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * WebSocket Client\n * Real-time data streaming for TUI dashboard\n */\n\nimport { EventEmitter } from 'events';\nimport WebSocket from 'ws';\n// Type-safe environment variable access\nfunction getEnv(key: string, defaultValue?: string): string {\n const value = process.env[key];\n if (value === undefined) {\n if (defaultValue !== undefined) return defaultValue;\n throw new Error(`Environment variable ${key} is required`);\n }\n return value;\n}\n\nfunction getOptionalEnv(key: string): string | undefined {\n return process.env[key];\n}\n\nexport class WebSocketClient extends EventEmitter {\n private ws: WebSocket | null = null;\n private url: string;\n private reconnectTimer: NodeJS.Timeout | null = null;\n private reconnectAttempts = 0;\n private maxReconnectAttempts = 10;\n private reconnectDelay = 1000;\n\n constructor(url: string) {\n super();\n this.url = url;\n }\n\n async connect(): Promise<void> {\n return new Promise((resolve) => {\n try {\n // Add error handler before creating WebSocket to catch connection errors\n const handleError = (error: Error) => {\n clearTimeout(connectionTimeout);\n // Silent error handling - continue in offline mode\n if (process.env['DEBUG']) {\n console.log('WebSocket connection failed:', error.message);\n }\n if (this.ws) {\n this.ws.removeAllListeners();\n this.ws.terminate();\n this.ws = null;\n }\n resolve(); // Always resolve to continue in offline mode\n };\n\n // Set a timeout for connection\n const connectionTimeout = setTimeout(() => {\n if (this.ws) {\n this.ws.removeAllListeners();\n this.ws.terminate();\n this.ws = null;\n }\n console.log('\u26A0\uFE0F Running in offline mode (no WebSocket server)');\n this.emit('offline');\n resolve();\n }, 1000); // Reduce timeout to 1 second\n\n try {\n this.ws = new WebSocket(this.url);\n } catch (wsError: unknown) {\n handleError(wsError as Error);\n return;\n }\n\n // Immediately add error handler to catch connection errors\n this.ws.once('error', handleError);\n\n this.ws.once('open', () => {\n clearTimeout(connectionTimeout);\n // Remove the error handler and add a new one for ongoing errors\n this.ws?.removeListener('error', handleError);\n this.ws?.on('error', (error: Error) => {\n if (process.env['DEBUG']) {\n console.error('WebSocket error during operation:', error);\n }\n this.emit('error', error);\n });\n\n console.log('\u2705 WebSocket connected');\n this.reconnectAttempts = 0;\n this.emit('connected');\n resolve();\n });\n\n this.ws.on('message', (data: WebSocket.Data) => {\n this.handleMessage(data);\n });\n\n this.ws.once('close', () => {\n clearTimeout(connectionTimeout);\n if (this.reconnectAttempts > 0) {\n console.log('WebSocket disconnected');\n this.emit('disconnected');\n this.attemptReconnect();\n }\n // If this is the first close, just resolve\n resolve();\n });\n } catch (error: unknown) {\n // If anything fails, continue in offline mode\n console.log('\u26A0\uFE0F Running in offline mode');\n this.emit('offline');\n resolve();\n }\n });\n }\n\n private handleMessage(data: WebSocket.Data): void {\n try {\n const message = JSON.parse(data.toString());\n\n switch (message.type) {\n case 'session:update':\n this.emit('session:update', message.data);\n break;\n\n case 'task:update':\n this.emit('task:update', message.data);\n break;\n\n case 'frame:update':\n this.emit('frame:update', message.data);\n break;\n\n case 'agent:status':\n this.emit('agent:status', message.data);\n break;\n\n case 'pr:update':\n this.emit('pr:update', message.data);\n break;\n\n case 'analytics:update':\n this.emit('analytics:update', message.data);\n break;\n\n case 'notification':\n this.emit('notification', message.data);\n break;\n\n default:\n this.emit('message', message);\n }\n } catch (error: unknown) {\n console.error('Failed to parse WebSocket message:', error);\n }\n }\n\n private attemptReconnect(): void {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n this.emit('error', new Error('Max reconnection attempts reached'));\n return;\n }\n\n this.reconnectAttempts++;\n const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);\n\n console.log(\n `Attempting to reconnect in ${delay}ms (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})`\n );\n\n this.reconnectTimer = setTimeout(() => {\n this.connect().catch((error) => {\n console.error('Reconnection failed:', error);\n });\n }, delay);\n }\n\n send(type: string, data: any): void {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify({ type, data }));\n } else {\n console.warn('WebSocket is not connected');\n }\n }\n\n disconnect(): void {\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n }\n\n isConnected(): boolean {\n return this.ws !== null && this.ws.readyState === WebSocket.OPEN;\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -181,10 +181,14 @@ class TerminalCompatibility {
181
181
  const warnings = [];
182
182
  const { type, supportsUnicode, supportsTrueColor } = this.terminalInfo;
183
183
  if (type === "ghostty") {
184
- warnings.push("Ghostty terminal detected: Using compatibility mode with reduced features");
184
+ warnings.push(
185
+ "Ghostty terminal detected: Using compatibility mode with reduced features"
186
+ );
185
187
  }
186
188
  if (!supportsUnicode) {
187
- warnings.push("Unicode support not detected: Some icons may not display correctly");
189
+ warnings.push(
190
+ "Unicode support not detected: Some icons may not display correctly"
191
+ );
188
192
  }
189
193
  if (!supportsTrueColor) {
190
194
  warnings.push("True color support not detected: Using 256 color mode");
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/features/tui/terminal-compat.ts"],
4
- "sourcesContent": ["/**\n * Terminal Compatibility Layer\n * Handles different terminal environments (Ghostty, tmux, standard terminals)\n */\n\nimport os from 'os';\nimport { execSync } from 'child_process';\n// Type-safe environment variable access\nfunction getEnv(key: string, defaultValue?: string): string {\n const value = process.env[key];\n if (value === undefined) {\n if (defaultValue !== undefined) return defaultValue;\n throw new Error(`Environment variable ${key} is required`);\n }\n return value;\n}\n\nfunction getOptionalEnv(key: string): string | undefined {\n return process.env[key];\n}\n\n\nexport interface TerminalInfo {\n type: 'ghostty' | 'tmux' | 'iterm2' | 'terminal' | 'xterm' | 'unknown';\n isInsideTmux: boolean;\n supportsTrueColor: boolean;\n supportsUnicode: boolean;\n termEnv: string;\n recommendedConfig: BlessedConfig;\n}\n\nexport interface BlessedConfig {\n smartCSR: boolean;\n fullUnicode: boolean;\n forceUnicode: boolean | null;\n dockBorders: boolean;\n terminal: string;\n title: string;\n // Compatibility flags\n artificalCursor?: boolean;\n grabKeys?: boolean;\n sendFocus?: boolean;\n warnings?: boolean;\n}\n\nexport class TerminalCompatibility {\n private static instance: TerminalCompatibility;\n private terminalInfo: TerminalInfo;\n\n private constructor() {\n this.terminalInfo = this.detectTerminal();\n }\n\n static getInstance(): TerminalCompatibility {\n if (!this.instance) {\n this.instance = new TerminalCompatibility();\n }\n return this.instance;\n }\n\n private detectTerminal(): TerminalInfo {\n const termEnv = process.env['TERM'] || '';\n const termProgram = process.env['TERM_PROGRAM'] || '';\n const isInsideTmux = !!process.env['TMUX'];\n const isGhostty = termEnv.includes('ghostty') || termProgram === 'ghostty';\n const isIterm2 = termProgram === 'iTerm.app';\n const isTerminalApp = termProgram === 'Apple_Terminal';\n \n let type: TerminalInfo['type'] = 'unknown';\n \n if (isGhostty) {\n type = 'ghostty';\n } else if (isInsideTmux) {\n type = 'tmux';\n } else if (isIterm2) {\n type = 'iterm2';\n } else if (isTerminalApp) {\n type = 'terminal';\n } else if (termEnv.includes('xterm')) {\n type = 'xterm';\n }\n\n // Check for true color support\n const supportsTrueColor = this.checkTrueColorSupport();\n const supportsUnicode = this.checkUnicodeSupport();\n\n // Get recommended config based on terminal type\n const recommendedConfig = this.getRecommendedConfig(type, isInsideTmux);\n\n return {\n type,\n isInsideTmux,\n supportsTrueColor,\n supportsUnicode,\n termEnv,\n recommendedConfig\n };\n }\n\n private checkTrueColorSupport(): boolean {\n const colorterm = process.env['COLORTERM'];\n if (colorterm === 'truecolor' || colorterm === '24bit') {\n return true;\n }\n \n // Check terminal specific env vars\n const termProgram = process.env['TERM_PROGRAM'] || '';\n if (['iTerm.app', 'Hyper', 'vscode'].includes(termProgram)) {\n return true;\n }\n \n return false;\n }\n\n private checkUnicodeSupport(): boolean {\n // Most modern terminals support unicode\n const lang = process.env['LANG'] || '';\n const lcAll = process.env['LC_ALL'] || '';\n const lcCtype = process.env['LC_CTYPE'] || '';\n \n const hasUtf8 = [lang, lcAll, lcCtype].some(v => \n v.toLowerCase().includes('utf-8') || v.toLowerCase().includes('utf8')\n );\n \n return hasUtf8;\n }\n\n private getRecommendedConfig(\n type: TerminalInfo['type'],\n isInsideTmux: boolean\n ): BlessedConfig {\n const baseConfig: BlessedConfig = {\n smartCSR: true,\n fullUnicode: true,\n forceUnicode: null,\n dockBorders: true,\n terminal: 'xterm-256color',\n title: 'StackMemory TUI Dashboard',\n warnings: false\n };\n\n // Terminal-specific adjustments\n switch (type) {\n case 'ghostty':\n // Ghostty has issues with certain escape sequences\n return {\n ...baseConfig,\n smartCSR: false, // Disable smart cursor restore\n terminal: 'xterm', // Use basic xterm instead of xterm-256color\n dockBorders: false, // Can cause rendering issues\n artificalCursor: true, // Use artificial cursor\n grabKeys: false, // Don't grab all keys\n sendFocus: false // Don't send focus events\n };\n \n case 'tmux':\n // Inside tmux, we need to be more conservative\n return {\n ...baseConfig,\n terminal: isInsideTmux ? 'screen-256color' : 'xterm-256color',\n smartCSR: !isInsideTmux, // Disable inside tmux\n sendFocus: false\n };\n \n case 'iterm2':\n // iTerm2 has excellent terminal support\n return {\n ...baseConfig,\n terminal: 'xterm-256color',\n fullUnicode: true,\n forceUnicode: true\n };\n \n case 'terminal':\n // macOS Terminal.app\n return {\n ...baseConfig,\n terminal: 'xterm-256color',\n fullUnicode: true\n };\n \n case 'xterm':\n default:\n // Conservative defaults for unknown terminals\n return {\n ...baseConfig,\n smartCSR: false,\n fullUnicode: false,\n forceUnicode: false\n };\n }\n }\n\n getTerminalInfo(): TerminalInfo {\n return this.terminalInfo;\n }\n\n getBlessedConfig(): BlessedConfig {\n return this.terminalInfo.recommendedConfig;\n }\n\n /**\n * Set optimal TERM environment variable for the detected terminal\n */\n configureEnvironment(): void {\n const { type, isInsideTmux } = this.terminalInfo;\n \n if (type === 'ghostty') {\n // Ghostty works better with basic xterm\n process.env['TERM'] = 'xterm';\n } else if (isInsideTmux) {\n // Inside tmux, use screen-256color\n process.env['TERM'] = 'screen-256color';\n } else if (!process.env['TERM'] || process.env['TERM'] === 'dumb') {\n // Fallback to xterm-256color if not set\n process.env['TERM'] = 'xterm-256color';\n }\n\n // Disable Node warnings that can interfere with TUI\n process.env['NODE_NO_WARNINGS'] = '1';\n }\n\n /**\n * Check if terminal is suitable for TUI\n */\n isCompatible(): boolean {\n // Check if we're in a non-interactive environment\n if (process.env['CI'] || process.env['CONTINUOUS_INTEGRATION']) {\n return false;\n }\n\n // Check if terminal is too basic\n const term = process.env['TERM'] || '';\n if (term === 'dumb') {\n return false;\n }\n\n // Allow if FORCE_TUI is set\n if (process.env['FORCE_TUI']) {\n return true;\n }\n\n // Check if any TTY is available (stdout, stdin, or stderr)\n const hasAnyTTY = process.stdout.isTTY || process.stdin.isTTY || process.stderr.isTTY;\n \n // When running through npm/node, TTY detection might fail\n // but we still want to allow TUI if terminal is capable\n if (!hasAnyTTY) {\n const { type } = this.terminalInfo;\n // Allow known terminal types even without TTY detection\n if (type !== 'unknown' || term.includes('xterm') || term.includes('screen')) {\n return true;\n }\n return false;\n }\n\n return true;\n }\n\n /**\n * Get compatibility warnings for the current terminal\n */\n getWarnings(): string[] {\n const warnings: string[] = [];\n const { type, supportsUnicode, supportsTrueColor } = this.terminalInfo;\n\n if (type === 'ghostty') {\n warnings.push('Ghostty terminal detected: Using compatibility mode with reduced features');\n }\n\n if (!supportsUnicode) {\n warnings.push('Unicode support not detected: Some icons may not display correctly');\n }\n\n if (!supportsTrueColor) {\n warnings.push('True color support not detected: Using 256 color mode');\n }\n\n if (type === 'unknown') {\n warnings.push('Unknown terminal type: Using conservative settings');\n }\n\n return warnings;\n }\n\n /**\n * Get terminal capabilities as a string for debugging\n */\n getCapabilitiesString(): string {\n const { type, isInsideTmux, supportsTrueColor, supportsUnicode, termEnv } = this.terminalInfo;\n \n return [\n `Terminal Type: ${type}`,\n `TERM: ${termEnv}`,\n `Inside tmux: ${isInsideTmux}`,\n `True Color: ${supportsTrueColor}`,\n `Unicode: ${supportsUnicode}`\n ].join(' | ');\n }\n}\n\n// Export singleton instance\nexport const terminalCompat = TerminalCompatibility.getInstance();"],
5
- "mappings": "AAQA,SAAS,OAAO,KAAa,cAA+B;AAC1D,QAAM,QAAQ,QAAQ,IAAI,GAAG;AAC7B,MAAI,UAAU,QAAW;AACvB,QAAI,iBAAiB,OAAW,QAAO;AACvC,UAAM,IAAI,MAAM,wBAAwB,GAAG,cAAc;AAAA,EAC3D;AACA,SAAO;AACT;AAEA,SAAS,eAAe,KAAiC;AACvD,SAAO,QAAQ,IAAI,GAAG;AACxB;AA0BO,MAAM,sBAAsB;AAAA,EACjC,OAAe;AAAA,EACP;AAAA,EAEA,cAAc;AACpB,SAAK,eAAe,KAAK,eAAe;AAAA,EAC1C;AAAA,EAEA,OAAO,cAAqC;AAC1C,QAAI,CAAC,KAAK,UAAU;AAClB,WAAK,WAAW,IAAI,sBAAsB;AAAA,IAC5C;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,iBAA+B;AACrC,UAAM,UAAU,QAAQ,IAAI,MAAM,KAAK;AACvC,UAAM,cAAc,QAAQ,IAAI,cAAc,KAAK;AACnD,UAAM,eAAe,CAAC,CAAC,QAAQ,IAAI,MAAM;AACzC,UAAM,YAAY,QAAQ,SAAS,SAAS,KAAK,gBAAgB;AACjE,UAAM,WAAW,gBAAgB;AACjC,UAAM,gBAAgB,gBAAgB;AAEtC,QAAI,OAA6B;AAEjC,QAAI,WAAW;AACb,aAAO;AAAA,IACT,WAAW,cAAc;AACvB,aAAO;AAAA,IACT,WAAW,UAAU;AACnB,aAAO;AAAA,IACT,WAAW,eAAe;AACxB,aAAO;AAAA,IACT,WAAW,QAAQ,SAAS,OAAO,GAAG;AACpC,aAAO;AAAA,IACT;AAGA,UAAM,oBAAoB,KAAK,sBAAsB;AACrD,UAAM,kBAAkB,KAAK,oBAAoB;AAGjD,UAAM,oBAAoB,KAAK,qBAAqB,MAAM,YAAY;AAEtE,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,wBAAiC;AACvC,UAAM,YAAY,QAAQ,IAAI,WAAW;AACzC,QAAI,cAAc,eAAe,cAAc,SAAS;AACtD,aAAO;AAAA,IACT;AAGA,UAAM,cAAc,QAAQ,IAAI,cAAc,KAAK;AACnD,QAAI,CAAC,aAAa,SAAS,QAAQ,EAAE,SAAS,WAAW,GAAG;AAC1D,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,sBAA+B;AAErC,UAAM,OAAO,QAAQ,IAAI,MAAM,KAAK;AACpC,UAAM,QAAQ,QAAQ,IAAI,QAAQ,KAAK;AACvC,UAAM,UAAU,QAAQ,IAAI,UAAU,KAAK;AAE3C,UAAM,UAAU,CAAC,MAAM,OAAO,OAAO,EAAE;AAAA,MAAK,OAC1C,EAAE,YAAY,EAAE,SAAS,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,MAAM;AAAA,IACtE;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,qBACN,MACA,cACe;AACf,UAAM,aAA4B;AAAA,MAChC,UAAU;AAAA,MACV,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa;AAAA,MACb,UAAU;AAAA,MACV,OAAO;AAAA,MACP,UAAU;AAAA,IACZ;AAGA,YAAQ,MAAM;AAAA,MACZ,KAAK;AAEH,eAAO;AAAA,UACL,GAAG;AAAA,UACH,UAAU;AAAA;AAAA,UACV,UAAU;AAAA;AAAA,UACV,aAAa;AAAA;AAAA,UACb,iBAAiB;AAAA;AAAA,UACjB,UAAU;AAAA;AAAA,UACV,WAAW;AAAA;AAAA,QACb;AAAA,MAEF,KAAK;AAEH,eAAO;AAAA,UACL,GAAG;AAAA,UACH,UAAU,eAAe,oBAAoB;AAAA,UAC7C,UAAU,CAAC;AAAA;AAAA,UACX,WAAW;AAAA,QACb;AAAA,MAEF,KAAK;AAEH,eAAO;AAAA,UACL,GAAG;AAAA,UACH,UAAU;AAAA,UACV,aAAa;AAAA,UACb,cAAc;AAAA,QAChB;AAAA,MAEF,KAAK;AAEH,eAAO;AAAA,UACL,GAAG;AAAA,UACH,UAAU;AAAA,UACV,aAAa;AAAA,QACf;AAAA,MAEF,KAAK;AAAA,MACL;AAEE,eAAO;AAAA,UACL,GAAG;AAAA,UACH,UAAU;AAAA,UACV,aAAa;AAAA,UACb,cAAc;AAAA,QAChB;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,kBAAgC;AAC9B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,mBAAkC;AAChC,WAAO,KAAK,aAAa;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,uBAA6B;AAC3B,UAAM,EAAE,MAAM,aAAa,IAAI,KAAK;AAEpC,QAAI,SAAS,WAAW;AAEtB,cAAQ,IAAI,MAAM,IAAI;AAAA,IACxB,WAAW,cAAc;AAEvB,cAAQ,IAAI,MAAM,IAAI;AAAA,IACxB,WAAW,CAAC,QAAQ,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,MAAM,QAAQ;AAEjE,cAAQ,IAAI,MAAM,IAAI;AAAA,IACxB;AAGA,YAAQ,IAAI,kBAAkB,IAAI;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKA,eAAwB;AAEtB,QAAI,QAAQ,IAAI,IAAI,KAAK,QAAQ,IAAI,wBAAwB,GAAG;AAC9D,aAAO;AAAA,IACT;AAGA,UAAM,OAAO,QAAQ,IAAI,MAAM,KAAK;AACpC,QAAI,SAAS,QAAQ;AACnB,aAAO;AAAA,IACT;AAGA,QAAI,QAAQ,IAAI,WAAW,GAAG;AAC5B,aAAO;AAAA,IACT;AAGA,UAAM,YAAY,QAAQ,OAAO,SAAS,QAAQ,MAAM,SAAS,QAAQ,OAAO;AAIhF,QAAI,CAAC,WAAW;AACd,YAAM,EAAE,KAAK,IAAI,KAAK;AAEtB,UAAI,SAAS,aAAa,KAAK,SAAS,OAAO,KAAK,KAAK,SAAS,QAAQ,GAAG;AAC3E,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,cAAwB;AACtB,UAAM,WAAqB,CAAC;AAC5B,UAAM,EAAE,MAAM,iBAAiB,kBAAkB,IAAI,KAAK;AAE1D,QAAI,SAAS,WAAW;AACtB,eAAS,KAAK,2EAA2E;AAAA,IAC3F;AAEA,QAAI,CAAC,iBAAiB;AACpB,eAAS,KAAK,oEAAoE;AAAA,IACpF;AAEA,QAAI,CAAC,mBAAmB;AACtB,eAAS,KAAK,uDAAuD;AAAA,IACvE;AAEA,QAAI,SAAS,WAAW;AACtB,eAAS,KAAK,oDAAoD;AAAA,IACpE;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,wBAAgC;AAC9B,UAAM,EAAE,MAAM,cAAc,mBAAmB,iBAAiB,QAAQ,IAAI,KAAK;AAEjF,WAAO;AAAA,MACL,kBAAkB,IAAI;AAAA,MACtB,SAAS,OAAO;AAAA,MAChB,gBAAgB,YAAY;AAAA,MAC5B,eAAe,iBAAiB;AAAA,MAChC,YAAY,eAAe;AAAA,IAC7B,EAAE,KAAK,KAAK;AAAA,EACd;AACF;AAGO,MAAM,iBAAiB,sBAAsB,YAAY;",
4
+ "sourcesContent": ["/**\n * Terminal Compatibility Layer\n * Handles different terminal environments (Ghostty, tmux, standard terminals)\n */\n\nimport os from 'os';\nimport { execSync } from 'child_process';\n// Type-safe environment variable access\nfunction getEnv(key: string, defaultValue?: string): string {\n const value = process.env[key];\n if (value === undefined) {\n if (defaultValue !== undefined) return defaultValue;\n throw new Error(`Environment variable ${key} is required`);\n }\n return value;\n}\n\nfunction getOptionalEnv(key: string): string | undefined {\n return process.env[key];\n}\n\nexport interface TerminalInfo {\n type: 'ghostty' | 'tmux' | 'iterm2' | 'terminal' | 'xterm' | 'unknown';\n isInsideTmux: boolean;\n supportsTrueColor: boolean;\n supportsUnicode: boolean;\n termEnv: string;\n recommendedConfig: BlessedConfig;\n}\n\nexport interface BlessedConfig {\n smartCSR: boolean;\n fullUnicode: boolean;\n forceUnicode: boolean | null;\n dockBorders: boolean;\n terminal: string;\n title: string;\n // Compatibility flags\n artificalCursor?: boolean;\n grabKeys?: boolean;\n sendFocus?: boolean;\n warnings?: boolean;\n}\n\nexport class TerminalCompatibility {\n private static instance: TerminalCompatibility;\n private terminalInfo: TerminalInfo;\n\n private constructor() {\n this.terminalInfo = this.detectTerminal();\n }\n\n static getInstance(): TerminalCompatibility {\n if (!this.instance) {\n this.instance = new TerminalCompatibility();\n }\n return this.instance;\n }\n\n private detectTerminal(): TerminalInfo {\n const termEnv = process.env['TERM'] || '';\n const termProgram = process.env['TERM_PROGRAM'] || '';\n const isInsideTmux = !!process.env['TMUX'];\n const isGhostty = termEnv.includes('ghostty') || termProgram === 'ghostty';\n const isIterm2 = termProgram === 'iTerm.app';\n const isTerminalApp = termProgram === 'Apple_Terminal';\n\n let type: TerminalInfo['type'] = 'unknown';\n\n if (isGhostty) {\n type = 'ghostty';\n } else if (isInsideTmux) {\n type = 'tmux';\n } else if (isIterm2) {\n type = 'iterm2';\n } else if (isTerminalApp) {\n type = 'terminal';\n } else if (termEnv.includes('xterm')) {\n type = 'xterm';\n }\n\n // Check for true color support\n const supportsTrueColor = this.checkTrueColorSupport();\n const supportsUnicode = this.checkUnicodeSupport();\n\n // Get recommended config based on terminal type\n const recommendedConfig = this.getRecommendedConfig(type, isInsideTmux);\n\n return {\n type,\n isInsideTmux,\n supportsTrueColor,\n supportsUnicode,\n termEnv,\n recommendedConfig,\n };\n }\n\n private checkTrueColorSupport(): boolean {\n const colorterm = process.env['COLORTERM'];\n if (colorterm === 'truecolor' || colorterm === '24bit') {\n return true;\n }\n\n // Check terminal specific env vars\n const termProgram = process.env['TERM_PROGRAM'] || '';\n if (['iTerm.app', 'Hyper', 'vscode'].includes(termProgram)) {\n return true;\n }\n\n return false;\n }\n\n private checkUnicodeSupport(): boolean {\n // Most modern terminals support unicode\n const lang = process.env['LANG'] || '';\n const lcAll = process.env['LC_ALL'] || '';\n const lcCtype = process.env['LC_CTYPE'] || '';\n\n const hasUtf8 = [lang, lcAll, lcCtype].some(\n (v) =>\n v.toLowerCase().includes('utf-8') || v.toLowerCase().includes('utf8')\n );\n\n return hasUtf8;\n }\n\n private getRecommendedConfig(\n type: TerminalInfo['type'],\n isInsideTmux: boolean\n ): BlessedConfig {\n const baseConfig: BlessedConfig = {\n smartCSR: true,\n fullUnicode: true,\n forceUnicode: null,\n dockBorders: true,\n terminal: 'xterm-256color',\n title: 'StackMemory TUI Dashboard',\n warnings: false,\n };\n\n // Terminal-specific adjustments\n switch (type) {\n case 'ghostty':\n // Ghostty has issues with certain escape sequences\n return {\n ...baseConfig,\n smartCSR: false, // Disable smart cursor restore\n terminal: 'xterm', // Use basic xterm instead of xterm-256color\n dockBorders: false, // Can cause rendering issues\n artificalCursor: true, // Use artificial cursor\n grabKeys: false, // Don't grab all keys\n sendFocus: false, // Don't send focus events\n };\n\n case 'tmux':\n // Inside tmux, we need to be more conservative\n return {\n ...baseConfig,\n terminal: isInsideTmux ? 'screen-256color' : 'xterm-256color',\n smartCSR: !isInsideTmux, // Disable inside tmux\n sendFocus: false,\n };\n\n case 'iterm2':\n // iTerm2 has excellent terminal support\n return {\n ...baseConfig,\n terminal: 'xterm-256color',\n fullUnicode: true,\n forceUnicode: true,\n };\n\n case 'terminal':\n // macOS Terminal.app\n return {\n ...baseConfig,\n terminal: 'xterm-256color',\n fullUnicode: true,\n };\n\n case 'xterm':\n default:\n // Conservative defaults for unknown terminals\n return {\n ...baseConfig,\n smartCSR: false,\n fullUnicode: false,\n forceUnicode: false,\n };\n }\n }\n\n getTerminalInfo(): TerminalInfo {\n return this.terminalInfo;\n }\n\n getBlessedConfig(): BlessedConfig {\n return this.terminalInfo.recommendedConfig;\n }\n\n /**\n * Set optimal TERM environment variable for the detected terminal\n */\n configureEnvironment(): void {\n const { type, isInsideTmux } = this.terminalInfo;\n\n if (type === 'ghostty') {\n // Ghostty works better with basic xterm\n process.env['TERM'] = 'xterm';\n } else if (isInsideTmux) {\n // Inside tmux, use screen-256color\n process.env['TERM'] = 'screen-256color';\n } else if (!process.env['TERM'] || process.env['TERM'] === 'dumb') {\n // Fallback to xterm-256color if not set\n process.env['TERM'] = 'xterm-256color';\n }\n\n // Disable Node warnings that can interfere with TUI\n process.env['NODE_NO_WARNINGS'] = '1';\n }\n\n /**\n * Check if terminal is suitable for TUI\n */\n isCompatible(): boolean {\n // Check if we're in a non-interactive environment\n if (process.env['CI'] || process.env['CONTINUOUS_INTEGRATION']) {\n return false;\n }\n\n // Check if terminal is too basic\n const term = process.env['TERM'] || '';\n if (term === 'dumb') {\n return false;\n }\n\n // Allow if FORCE_TUI is set\n if (process.env['FORCE_TUI']) {\n return true;\n }\n\n // Check if any TTY is available (stdout, stdin, or stderr)\n const hasAnyTTY =\n process.stdout.isTTY || process.stdin.isTTY || process.stderr.isTTY;\n\n // When running through npm/node, TTY detection might fail\n // but we still want to allow TUI if terminal is capable\n if (!hasAnyTTY) {\n const { type } = this.terminalInfo;\n // Allow known terminal types even without TTY detection\n if (\n type !== 'unknown' ||\n term.includes('xterm') ||\n term.includes('screen')\n ) {\n return true;\n }\n return false;\n }\n\n return true;\n }\n\n /**\n * Get compatibility warnings for the current terminal\n */\n getWarnings(): string[] {\n const warnings: string[] = [];\n const { type, supportsUnicode, supportsTrueColor } = this.terminalInfo;\n\n if (type === 'ghostty') {\n warnings.push(\n 'Ghostty terminal detected: Using compatibility mode with reduced features'\n );\n }\n\n if (!supportsUnicode) {\n warnings.push(\n 'Unicode support not detected: Some icons may not display correctly'\n );\n }\n\n if (!supportsTrueColor) {\n warnings.push('True color support not detected: Using 256 color mode');\n }\n\n if (type === 'unknown') {\n warnings.push('Unknown terminal type: Using conservative settings');\n }\n\n return warnings;\n }\n\n /**\n * Get terminal capabilities as a string for debugging\n */\n getCapabilitiesString(): string {\n const { type, isInsideTmux, supportsTrueColor, supportsUnicode, termEnv } =\n this.terminalInfo;\n\n return [\n `Terminal Type: ${type}`,\n `TERM: ${termEnv}`,\n `Inside tmux: ${isInsideTmux}`,\n `True Color: ${supportsTrueColor}`,\n `Unicode: ${supportsUnicode}`,\n ].join(' | ');\n }\n}\n\n// Export singleton instance\nexport const terminalCompat = TerminalCompatibility.getInstance();\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/features/web/client/stores/task-store.ts"],
4
- "sourcesContent": ["import { create } from 'zustand'\n\nexport interface Task {\n id: string\n identifier: string\n title: string\n description?: string\n state: string\n priority?: number\n estimate?: number\n assignee?: string\n createdAt: string\n updatedAt: string\n lastSyncedAt?: string\n syncStatus?: string\n}\n\ninterface TaskStore {\n tasks: Task[]\n setTasks: (tasks: Task[]) => void\n addTask: (task: Task) => void\n updateTask: (id: string, updates: Partial<Task>) => void\n removeTask: (id: string) => void\n getTaskById: (id: string) => Task | undefined\n getTasksByState: (state: string) => Task[]\n}\n\nexport const useTaskStore = create<TaskStore>((set, get) => ({\n tasks: [],\n \n setTasks: (tasks) => set({ tasks }),\n \n addTask: (task) => set((state) => ({\n tasks: [...state.tasks, task],\n })),\n \n updateTask: (id, updates) => set((state) => ({\n tasks: state.tasks.map((task: any) =>\n task.id === id ? { ...task, ...updates } : task\n ),\n })),\n \n removeTask: (id) => set((state) => ({\n tasks: state.tasks.filter((task: any) => task.id !== id),\n })),\n \n getTaskById: (id) => get().tasks.find((task: any) => task.id === id),\n \n getTasksByState: (state) => get().tasks.filter((task: any) => task.state === state),\n}))"],
5
- "mappings": "AAAA,SAAS,cAAc;AA2BhB,MAAM,eAAe,OAAkB,CAAC,KAAK,SAAS;AAAA,EAC3D,OAAO,CAAC;AAAA,EAER,UAAU,CAAC,UAAU,IAAI,EAAE,MAAM,CAAC;AAAA,EAElC,SAAS,CAAC,SAAS,IAAI,CAAC,WAAW;AAAA,IACjC,OAAO,CAAC,GAAG,MAAM,OAAO,IAAI;AAAA,EAC9B,EAAE;AAAA,EAEF,YAAY,CAAC,IAAI,YAAY,IAAI,CAAC,WAAW;AAAA,IAC3C,OAAO,MAAM,MAAM;AAAA,MAAI,CAAC,SACtB,KAAK,OAAO,KAAK,EAAE,GAAG,MAAM,GAAG,QAAQ,IAAI;AAAA,IAC7C;AAAA,EACF,EAAE;AAAA,EAEF,YAAY,CAAC,OAAO,IAAI,CAAC,WAAW;AAAA,IAClC,OAAO,MAAM,MAAM,OAAO,CAAC,SAAc,KAAK,OAAO,EAAE;AAAA,EACzD,EAAE;AAAA,EAEF,aAAa,CAAC,OAAO,IAAI,EAAE,MAAM,KAAK,CAAC,SAAc,KAAK,OAAO,EAAE;AAAA,EAEnE,iBAAiB,CAAC,UAAU,IAAI,EAAE,MAAM,OAAO,CAAC,SAAc,KAAK,UAAU,KAAK;AACpF,EAAE;",
4
+ "sourcesContent": ["import { create } from 'zustand';\n\nexport interface Task {\n id: string;\n identifier: string;\n title: string;\n description?: string;\n state: string;\n priority?: number;\n estimate?: number;\n assignee?: string;\n createdAt: string;\n updatedAt: string;\n lastSyncedAt?: string;\n syncStatus?: string;\n}\n\ninterface TaskStore {\n tasks: Task[];\n setTasks: (tasks: Task[]) => void;\n addTask: (task: Task) => void;\n updateTask: (id: string, updates: Partial<Task>) => void;\n removeTask: (id: string) => void;\n getTaskById: (id: string) => Task | undefined;\n getTasksByState: (state: string) => Task[];\n}\n\nexport const useTaskStore = create<TaskStore>((set, get) => ({\n tasks: [],\n\n setTasks: (tasks) => set({ tasks }),\n\n addTask: (task) =>\n set((state) => ({\n tasks: [...state.tasks, task],\n })),\n\n updateTask: (id, updates) =>\n set((state) => ({\n tasks: state.tasks.map((task: any) =>\n task.id === id ? { ...task, ...updates } : task\n ),\n })),\n\n removeTask: (id) =>\n set((state) => ({\n tasks: state.tasks.filter((task: any) => task.id !== id),\n })),\n\n getTaskById: (id) => get().tasks.find((task: any) => task.id === id),\n\n getTasksByState: (state) =>\n get().tasks.filter((task: any) => task.state === state),\n}));\n"],
5
+ "mappings": "AAAA,SAAS,cAAc;AA2BhB,MAAM,eAAe,OAAkB,CAAC,KAAK,SAAS;AAAA,EAC3D,OAAO,CAAC;AAAA,EAER,UAAU,CAAC,UAAU,IAAI,EAAE,MAAM,CAAC;AAAA,EAElC,SAAS,CAAC,SACR,IAAI,CAAC,WAAW;AAAA,IACd,OAAO,CAAC,GAAG,MAAM,OAAO,IAAI;AAAA,EAC9B,EAAE;AAAA,EAEJ,YAAY,CAAC,IAAI,YACf,IAAI,CAAC,WAAW;AAAA,IACd,OAAO,MAAM,MAAM;AAAA,MAAI,CAAC,SACtB,KAAK,OAAO,KAAK,EAAE,GAAG,MAAM,GAAG,QAAQ,IAAI;AAAA,IAC7C;AAAA,EACF,EAAE;AAAA,EAEJ,YAAY,CAAC,OACX,IAAI,CAAC,WAAW;AAAA,IACd,OAAO,MAAM,MAAM,OAAO,CAAC,SAAc,KAAK,OAAO,EAAE;AAAA,EACzD,EAAE;AAAA,EAEJ,aAAa,CAAC,OAAO,IAAI,EAAE,MAAM,KAAK,CAAC,SAAc,KAAK,OAAO,EAAE;AAAA,EAEnE,iBAAiB,CAAC,UAChB,IAAI,EAAE,MAAM,OAAO,CAAC,SAAc,KAAK,UAAU,KAAK;AAC1D,EAAE;",
6
6
  "names": []
7
7
  }
@@ -36,7 +36,9 @@ let db = null;
36
36
  function initializeServices() {
37
37
  console.log("\u{1F680} Initializing StackMemory Web Server...");
38
38
  taskReader = new LinearTaskReader(process.cwd());
39
- console.log(`\u{1F4CB} TaskReader initialized with ${taskReader.getTasks().length} tasks`);
39
+ console.log(
40
+ `\u{1F4CB} TaskReader initialized with ${taskReader.getTasks().length} tasks`
41
+ );
40
42
  sessionManager = new SessionManager({ enableMonitoring: true });
41
43
  console.log("\u{1F4CA} SessionManager initialized");
42
44
  const dbPath = join(process.cwd(), ".stackmemory", "context.db");
@@ -110,15 +112,21 @@ app.get("/api/analytics", (req, res) => {
110
112
  totalSessions: sessions.length,
111
113
  totalFrames: frames.length
112
114
  },
113
- tasksByState: tasks.reduce((acc, task) => {
114
- acc[task.state] = (acc[task.state] || 0) + 1;
115
- return acc;
116
- }, {}),
117
- tasksByPriority: tasks.reduce((acc, task) => {
118
- const priority = task.priority || 4;
119
- acc[priority] = (acc[priority] || 0) + 1;
120
- return acc;
121
- }, {}),
115
+ tasksByState: tasks.reduce(
116
+ (acc, task) => {
117
+ acc[task.state] = (acc[task.state] || 0) + 1;
118
+ return acc;
119
+ },
120
+ {}
121
+ ),
122
+ tasksByPriority: tasks.reduce(
123
+ (acc, task) => {
124
+ const priority = task.priority || 4;
125
+ acc[priority] = (acc[priority] || 0) + 1;
126
+ return acc;
127
+ },
128
+ {}
129
+ ),
122
130
  recentActivity: {
123
131
  tasksUpdatedToday: tasks.filter((t) => {
124
132
  const updated = new Date(t.updatedAt);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/features/web/server/index.ts"],
4
- "sourcesContent": ["/**\n * StackMemory Web Dashboard Server\n * Express + Socket.io server for real-time dashboard\n */\n\nimport express from 'express';\nimport { createServer } from 'http';\nimport { Server as SocketServer } from 'socket.io';\nimport cors from 'cors';\nimport { LinearTaskReader } from '../../tui/services/linear-task-reader.js';\nimport { SessionManager } from '../../../core/session/session-manager.js';\nimport { FrameManager } from '../../../core/context/frame-manager.js';\nimport Database from 'better-sqlite3';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\n// Type-safe environment variable access\nfunction getEnv(key: string, defaultValue?: string): string {\n const value = process.env[key];\n if (value === undefined) {\n if (defaultValue !== undefined) return defaultValue;\n throw new Error(`Environment variable ${key} is required`);\n }\n return value;\n}\n\nfunction getOptionalEnv(key: string): string | undefined {\n return process.env[key];\n}\n\n\nconst app = express();\nconst httpServer = createServer(app);\nconst io = new SocketServer(httpServer, {\n cors: {\n origin: process.env['CLIENT_URL'] || 'http://localhost:3000',\n methods: ['GET', 'POST'],\n },\n});\n\n// Middleware\napp.use(cors());\napp.use(express.json());\n\n// Data services\nlet taskReader: LinearTaskReader;\nlet sessionManager: SessionManager;\nlet frameManager: FrameManager | null = null;\nlet db: Database.Database | null = null;\n\n// Initialize services\nfunction initializeServices() {\n console.log('\uD83D\uDE80 Initializing StackMemory Web Server...');\n \n // Initialize task reader\n taskReader = new LinearTaskReader(process.cwd());\n console.log(`\uD83D\uDCCB TaskReader initialized with ${taskReader.getTasks().length} tasks`);\n \n // Initialize session manager\n sessionManager = new SessionManager({ enableMonitoring: true });\n console.log('\uD83D\uDCCA SessionManager initialized');\n \n // Initialize database and frame manager\n const dbPath = join(process.cwd(), '.stackmemory', 'context.db');\n if (existsSync(dbPath)) {\n try {\n db = new Database(dbPath);\n frameManager = new FrameManager(db, 'web');\n console.log('\uD83D\uDCBE Database and FrameManager initialized');\n } catch (error: unknown) {\n console.error('\u274C Failed to initialize database:', error);\n }\n }\n}\n\n// REST API Routes\napp.get('/api/health', (req, res) => {\n res.json({ status: 'ok', timestamp: new Date().toISOString() });\n});\n\napp.get('/api/tasks', (req, res) => {\n try {\n const tasks = taskReader.getTasks();\n res.json({ tasks, total: tasks.length });\n } catch (error: unknown) {\n res.status(500).json({ error: 'Failed to fetch tasks' });\n }\n});\n\napp.get('/api/tasks/active', (req, res) => {\n try {\n const tasks = taskReader.getActiveTasks();\n res.json({ tasks, total: tasks.length });\n } catch (error: unknown) {\n res.status(500).json({ error: 'Failed to fetch active tasks' });\n }\n});\n\napp.get('/api/tasks/by-state/:state', (req, res) => {\n try {\n const tasks = taskReader.getTasksByState(req.params.state);\n res.json({ tasks, total: tasks.length });\n } catch (error: unknown) {\n res.status(500).json({ error: 'Failed to fetch tasks by state' });\n }\n});\n\napp.get('/api/sessions', (req, res) => {\n try {\n const sessions = sessionManager?.getActiveSessions ? sessionManager.getActiveSessions() : [];\n res.json({ sessions, total: sessions.length });\n } catch (error: unknown) {\n res.status(500).json({ error: 'Failed to fetch sessions' });\n }\n});\n\napp.get('/api/frames', (req, res) => {\n try {\n if (!frameManager) {\n res.json({ frames: [], total: 0 });\n return;\n }\n const frames = frameManager.getAllFrames();\n res.json({ frames, total: frames.length });\n } catch (error: unknown) {\n res.status(500).json({ error: 'Failed to fetch frames' });\n }\n});\n\napp.get('/api/analytics', (req, res) => {\n try {\n const tasks = taskReader.getTasks();\n const sessions = sessionManager?.getActiveSessions ? sessionManager.getActiveSessions() : [];\n const frames = frameManager?.getAllFrames() || [];\n \n // Calculate analytics\n const analytics = {\n summary: {\n totalTasks: tasks.length,\n activeTasks: tasks.filter((t: any) => t.state === 'In Progress').length,\n completedTasks: tasks.filter((t: any) => t.state === 'Done').length,\n totalSessions: sessions.length,\n totalFrames: frames.length,\n },\n tasksByState: tasks.reduce((acc, task) => {\n acc[task.state] = (acc[task.state] || 0) + 1;\n return acc;\n }, {} as Record<string, number>),\n tasksByPriority: tasks.reduce((acc, task) => {\n const priority = task.priority || 4;\n acc[priority] = (acc[priority] || 0) + 1;\n return acc;\n }, {} as Record<number, number>),\n recentActivity: {\n tasksUpdatedToday: tasks.filter((t: any) => {\n const updated = new Date(t.updatedAt);\n const today = new Date();\n return updated.toDateString() === today.toDateString();\n }).length,\n sessionsToday: sessions.filter((s: any) => {\n const started = new Date(s.startTime);\n const today = new Date();\n return started.toDateString() === today.toDateString();\n }).length,\n },\n };\n \n res.json(analytics);\n } catch (error: unknown) {\n res.status(500).json({ error: 'Failed to fetch analytics' });\n }\n});\n\n// WebSocket handling\nio.on('connection', (socket) => {\n console.log('\uD83D\uDC64 Client connected:', socket.id);\n \n // Send initial data\n socket.emit('initial-data', {\n tasks: taskReader.getTasks(),\n sessions: sessionManager?.getActiveSessions ? sessionManager.getActiveSessions() : [],\n frames: frameManager?.getAllFrames() || [],\n });\n \n // Handle client requests\n socket.on('refresh-tasks', () => {\n socket.emit('tasks:update', taskReader.getTasks());\n });\n \n socket.on('refresh-sessions', () => {\n const sessions = sessionManager?.getActiveSessions ? sessionManager.getActiveSessions() : [];\n socket.emit('sessions:update', sessions);\n });\n \n socket.on('refresh-frames', () => {\n socket.emit('frames:update', frameManager?.getAllFrames() || []);\n });\n \n socket.on('disconnect', () => {\n console.log('\uD83D\uDC4B Client disconnected:', socket.id);\n });\n});\n\n// Periodic updates (every 5 seconds)\nsetInterval(() => {\n try {\n io.emit('tasks:update', taskReader.getTasks());\n // SessionManager might not have getActiveSessions yet\n const sessions = sessionManager?.getActiveSessions ? sessionManager.getActiveSessions() : [];\n io.emit('sessions:update', sessions);\n io.emit('frames:update', frameManager?.getAllFrames() || []);\n } catch (error: unknown) {\n console.error('Error in periodic update:', error);\n }\n}, 5000);\n\n// Start server\nconst PORT = process.env['WS_PORT'] || 8080;\n\ninitializeServices();\n\nhttpServer.listen(PORT, () => {\n console.log(`\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n\u2551 StackMemory Web Dashboard Server \u2551\n\u2551 Running on http://localhost:${PORT} \u2551\n\u2551 WebSocket: ws://localhost:${PORT} \u2551\n\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n `);\n});"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * StackMemory Web Dashboard Server\n * Express + Socket.io server for real-time dashboard\n */\n\nimport express from 'express';\nimport { createServer } from 'http';\nimport { Server as SocketServer } from 'socket.io';\nimport cors from 'cors';\nimport { LinearTaskReader } from '../../tui/services/linear-task-reader.js';\nimport { SessionManager } from '../../../core/session/session-manager.js';\nimport { FrameManager } from '../../../core/context/frame-manager.js';\nimport Database from 'better-sqlite3';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\n// Type-safe environment variable access\nfunction getEnv(key: string, defaultValue?: string): string {\n const value = process.env[key];\n if (value === undefined) {\n if (defaultValue !== undefined) return defaultValue;\n throw new Error(`Environment variable ${key} is required`);\n }\n return value;\n}\n\nfunction getOptionalEnv(key: string): string | undefined {\n return process.env[key];\n}\n\nconst app = express();\nconst httpServer = createServer(app);\nconst io = new SocketServer(httpServer, {\n cors: {\n origin: process.env['CLIENT_URL'] || 'http://localhost:3000',\n methods: ['GET', 'POST'],\n },\n});\n\n// Middleware\napp.use(cors());\napp.use(express.json());\n\n// Data services\nlet taskReader: LinearTaskReader;\nlet sessionManager: SessionManager;\nlet frameManager: FrameManager | null = null;\nlet db: Database.Database | null = null;\n\n// Initialize services\nfunction initializeServices() {\n console.log('\uD83D\uDE80 Initializing StackMemory Web Server...');\n\n // Initialize task reader\n taskReader = new LinearTaskReader(process.cwd());\n console.log(\n `\uD83D\uDCCB TaskReader initialized with ${taskReader.getTasks().length} tasks`\n );\n\n // Initialize session manager\n sessionManager = new SessionManager({ enableMonitoring: true });\n console.log('\uD83D\uDCCA SessionManager initialized');\n\n // Initialize database and frame manager\n const dbPath = join(process.cwd(), '.stackmemory', 'context.db');\n if (existsSync(dbPath)) {\n try {\n db = new Database(dbPath);\n frameManager = new FrameManager(db, 'web');\n console.log('\uD83D\uDCBE Database and FrameManager initialized');\n } catch (error: unknown) {\n console.error('\u274C Failed to initialize database:', error);\n }\n }\n}\n\n// REST API Routes\napp.get('/api/health', (req, res) => {\n res.json({ status: 'ok', timestamp: new Date().toISOString() });\n});\n\napp.get('/api/tasks', (req, res) => {\n try {\n const tasks = taskReader.getTasks();\n res.json({ tasks, total: tasks.length });\n } catch (error: unknown) {\n res.status(500).json({ error: 'Failed to fetch tasks' });\n }\n});\n\napp.get('/api/tasks/active', (req, res) => {\n try {\n const tasks = taskReader.getActiveTasks();\n res.json({ tasks, total: tasks.length });\n } catch (error: unknown) {\n res.status(500).json({ error: 'Failed to fetch active tasks' });\n }\n});\n\napp.get('/api/tasks/by-state/:state', (req, res) => {\n try {\n const tasks = taskReader.getTasksByState(req.params.state);\n res.json({ tasks, total: tasks.length });\n } catch (error: unknown) {\n res.status(500).json({ error: 'Failed to fetch tasks by state' });\n }\n});\n\napp.get('/api/sessions', (req, res) => {\n try {\n const sessions = sessionManager?.getActiveSessions\n ? sessionManager.getActiveSessions()\n : [];\n res.json({ sessions, total: sessions.length });\n } catch (error: unknown) {\n res.status(500).json({ error: 'Failed to fetch sessions' });\n }\n});\n\napp.get('/api/frames', (req, res) => {\n try {\n if (!frameManager) {\n res.json({ frames: [], total: 0 });\n return;\n }\n const frames = frameManager.getAllFrames();\n res.json({ frames, total: frames.length });\n } catch (error: unknown) {\n res.status(500).json({ error: 'Failed to fetch frames' });\n }\n});\n\napp.get('/api/analytics', (req, res) => {\n try {\n const tasks = taskReader.getTasks();\n const sessions = sessionManager?.getActiveSessions\n ? sessionManager.getActiveSessions()\n : [];\n const frames = frameManager?.getAllFrames() || [];\n\n // Calculate analytics\n const analytics = {\n summary: {\n totalTasks: tasks.length,\n activeTasks: tasks.filter((t: any) => t.state === 'In Progress').length,\n completedTasks: tasks.filter((t: any) => t.state === 'Done').length,\n totalSessions: sessions.length,\n totalFrames: frames.length,\n },\n tasksByState: tasks.reduce(\n (acc, task) => {\n acc[task.state] = (acc[task.state] || 0) + 1;\n return acc;\n },\n {} as Record<string, number>\n ),\n tasksByPriority: tasks.reduce(\n (acc, task) => {\n const priority = task.priority || 4;\n acc[priority] = (acc[priority] || 0) + 1;\n return acc;\n },\n {} as Record<number, number>\n ),\n recentActivity: {\n tasksUpdatedToday: tasks.filter((t: any) => {\n const updated = new Date(t.updatedAt);\n const today = new Date();\n return updated.toDateString() === today.toDateString();\n }).length,\n sessionsToday: sessions.filter((s: any) => {\n const started = new Date(s.startTime);\n const today = new Date();\n return started.toDateString() === today.toDateString();\n }).length,\n },\n };\n\n res.json(analytics);\n } catch (error: unknown) {\n res.status(500).json({ error: 'Failed to fetch analytics' });\n }\n});\n\n// WebSocket handling\nio.on('connection', (socket) => {\n console.log('\uD83D\uDC64 Client connected:', socket.id);\n\n // Send initial data\n socket.emit('initial-data', {\n tasks: taskReader.getTasks(),\n sessions: sessionManager?.getActiveSessions\n ? sessionManager.getActiveSessions()\n : [],\n frames: frameManager?.getAllFrames() || [],\n });\n\n // Handle client requests\n socket.on('refresh-tasks', () => {\n socket.emit('tasks:update', taskReader.getTasks());\n });\n\n socket.on('refresh-sessions', () => {\n const sessions = sessionManager?.getActiveSessions\n ? sessionManager.getActiveSessions()\n : [];\n socket.emit('sessions:update', sessions);\n });\n\n socket.on('refresh-frames', () => {\n socket.emit('frames:update', frameManager?.getAllFrames() || []);\n });\n\n socket.on('disconnect', () => {\n console.log('\uD83D\uDC4B Client disconnected:', socket.id);\n });\n});\n\n// Periodic updates (every 5 seconds)\nsetInterval(() => {\n try {\n io.emit('tasks:update', taskReader.getTasks());\n // SessionManager might not have getActiveSessions yet\n const sessions = sessionManager?.getActiveSessions\n ? sessionManager.getActiveSessions()\n : [];\n io.emit('sessions:update', sessions);\n io.emit('frames:update', frameManager?.getAllFrames() || []);\n } catch (error: unknown) {\n console.error('Error in periodic update:', error);\n }\n}, 5000);\n\n// Start server\nconst PORT = process.env['WS_PORT'] || 8080;\n\ninitializeServices();\n\nhttpServer.listen(PORT, () => {\n console.log(`\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n\u2551 StackMemory Web Dashboard Server \u2551\n\u2551 Running on http://localhost:${PORT} \u2551\n\u2551 WebSocket: ws://localhost:${PORT} \u2551\n\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n `);\n});\n"],
5
+ "mappings": "AAKA,OAAO,aAAa;AACpB,SAAS,oBAAoB;AAC7B,SAAS,UAAU,oBAAoB;AACvC,OAAO,UAAU;AACjB,SAAS,wBAAwB;AACjC,SAAS,sBAAsB;AAC/B,SAAS,oBAAoB;AAC7B,OAAO,cAAc;AACrB,SAAS,kBAAkB;AAC3B,SAAS,YAAY;AAErB,SAAS,OAAO,KAAa,cAA+B;AAC1D,QAAM,QAAQ,QAAQ,IAAI,GAAG;AAC7B,MAAI,UAAU,QAAW;AACvB,QAAI,iBAAiB,OAAW,QAAO;AACvC,UAAM,IAAI,MAAM,wBAAwB,GAAG,cAAc;AAAA,EAC3D;AACA,SAAO;AACT;AAEA,SAAS,eAAe,KAAiC;AACvD,SAAO,QAAQ,IAAI,GAAG;AACxB;AAEA,MAAM,MAAM,QAAQ;AACpB,MAAM,aAAa,aAAa,GAAG;AACnC,MAAM,KAAK,IAAI,aAAa,YAAY;AAAA,EACtC,MAAM;AAAA,IACJ,QAAQ,QAAQ,IAAI,YAAY,KAAK;AAAA,IACrC,SAAS,CAAC,OAAO,MAAM;AAAA,EACzB;AACF,CAAC;AAGD,IAAI,IAAI,KAAK,CAAC;AACd,IAAI,IAAI,QAAQ,KAAK,CAAC;AAGtB,IAAI;AACJ,IAAI;AACJ,IAAI,eAAoC;AACxC,IAAI,KAA+B;AAGnC,SAAS,qBAAqB;AAC5B,UAAQ,IAAI,kDAA2C;AAGvD,eAAa,IAAI,iBAAiB,QAAQ,IAAI,CAAC;AAC/C,UAAQ;AAAA,IACN,yCAAkC,WAAW,SAAS,EAAE,MAAM;AAAA,EAChE;AAGA,mBAAiB,IAAI,eAAe,EAAE,kBAAkB,KAAK,CAAC;AAC9D,UAAQ,IAAI,sCAA+B;AAG3C,QAAM,SAAS,KAAK,QAAQ,IAAI,GAAG,gBAAgB,YAAY;AAC/D,MAAI,WAAW,MAAM,GAAG;AACtB,QAAI;AACF,WAAK,IAAI,SAAS,MAAM;AACxB,qBAAe,IAAI,aAAa,IAAI,KAAK;AACzC,cAAQ,IAAI,iDAA0C;AAAA,IACxD,SAAS,OAAgB;AACvB,cAAQ,MAAM,yCAAoC,KAAK;AAAA,IACzD;AAAA,EACF;AACF;AAGA,IAAI,IAAI,eAAe,CAAC,KAAK,QAAQ;AACnC,MAAI,KAAK,EAAE,QAAQ,MAAM,YAAW,oBAAI,KAAK,GAAE,YAAY,EAAE,CAAC;AAChE,CAAC;AAED,IAAI,IAAI,cAAc,CAAC,KAAK,QAAQ;AAClC,MAAI;AACF,UAAM,QAAQ,WAAW,SAAS;AAClC,QAAI,KAAK,EAAE,OAAO,OAAO,MAAM,OAAO,CAAC;AAAA,EACzC,SAAS,OAAgB;AACvB,QAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,wBAAwB,CAAC;AAAA,EACzD;AACF,CAAC;AAED,IAAI,IAAI,qBAAqB,CAAC,KAAK,QAAQ;AACzC,MAAI;AACF,UAAM,QAAQ,WAAW,eAAe;AACxC,QAAI,KAAK,EAAE,OAAO,OAAO,MAAM,OAAO,CAAC;AAAA,EACzC,SAAS,OAAgB;AACvB,QAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,+BAA+B,CAAC;AAAA,EAChE;AACF,CAAC;AAED,IAAI,IAAI,8BAA8B,CAAC,KAAK,QAAQ;AAClD,MAAI;AACF,UAAM,QAAQ,WAAW,gBAAgB,IAAI,OAAO,KAAK;AACzD,QAAI,KAAK,EAAE,OAAO,OAAO,MAAM,OAAO,CAAC;AAAA,EACzC,SAAS,OAAgB;AACvB,QAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,iCAAiC,CAAC;AAAA,EAClE;AACF,CAAC;AAED,IAAI,IAAI,iBAAiB,CAAC,KAAK,QAAQ;AACrC,MAAI;AACF,UAAM,WAAW,gBAAgB,oBAC7B,eAAe,kBAAkB,IACjC,CAAC;AACL,QAAI,KAAK,EAAE,UAAU,OAAO,SAAS,OAAO,CAAC;AAAA,EAC/C,SAAS,OAAgB;AACvB,QAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,2BAA2B,CAAC;AAAA,EAC5D;AACF,CAAC;AAED,IAAI,IAAI,eAAe,CAAC,KAAK,QAAQ;AACnC,MAAI;AACF,QAAI,CAAC,cAAc;AACjB,UAAI,KAAK,EAAE,QAAQ,CAAC,GAAG,OAAO,EAAE,CAAC;AACjC;AAAA,IACF;AACA,UAAM,SAAS,aAAa,aAAa;AACzC,QAAI,KAAK,EAAE,QAAQ,OAAO,OAAO,OAAO,CAAC;AAAA,EAC3C,SAAS,OAAgB;AACvB,QAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,yBAAyB,CAAC;AAAA,EAC1D;AACF,CAAC;AAED,IAAI,IAAI,kBAAkB,CAAC,KAAK,QAAQ;AACtC,MAAI;AACF,UAAM,QAAQ,WAAW,SAAS;AAClC,UAAM,WAAW,gBAAgB,oBAC7B,eAAe,kBAAkB,IACjC,CAAC;AACL,UAAM,SAAS,cAAc,aAAa,KAAK,CAAC;AAGhD,UAAM,YAAY;AAAA,MAChB,SAAS;AAAA,QACP,YAAY,MAAM;AAAA,QAClB,aAAa,MAAM,OAAO,CAAC,MAAW,EAAE,UAAU,aAAa,EAAE;AAAA,QACjE,gBAAgB,MAAM,OAAO,CAAC,MAAW,EAAE,UAAU,MAAM,EAAE;AAAA,QAC7D,eAAe,SAAS;AAAA,QACxB,aAAa,OAAO;AAAA,MACtB;AAAA,MACA,cAAc,MAAM;AAAA,QAClB,CAAC,KAAK,SAAS;AACb,cAAI,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,KAAK,KAAK;AAC3C,iBAAO;AAAA,QACT;AAAA,QACA,CAAC;AAAA,MACH;AAAA,MACA,iBAAiB,MAAM;AAAA,QACrB,CAAC,KAAK,SAAS;AACb,gBAAM,WAAW,KAAK,YAAY;AAClC,cAAI,QAAQ,KAAK,IAAI,QAAQ,KAAK,KAAK;AACvC,iBAAO;AAAA,QACT;AAAA,QACA,CAAC;AAAA,MACH;AAAA,MACA,gBAAgB;AAAA,QACd,mBAAmB,MAAM,OAAO,CAAC,MAAW;AAC1C,gBAAM,UAAU,IAAI,KAAK,EAAE,SAAS;AACpC,gBAAM,QAAQ,oBAAI,KAAK;AACvB,iBAAO,QAAQ,aAAa,MAAM,MAAM,aAAa;AAAA,QACvD,CAAC,EAAE;AAAA,QACH,eAAe,SAAS,OAAO,CAAC,MAAW;AACzC,gBAAM,UAAU,IAAI,KAAK,EAAE,SAAS;AACpC,gBAAM,QAAQ,oBAAI,KAAK;AACvB,iBAAO,QAAQ,aAAa,MAAM,MAAM,aAAa;AAAA,QACvD,CAAC,EAAE;AAAA,MACL;AAAA,IACF;AAEA,QAAI,KAAK,SAAS;AAAA,EACpB,SAAS,OAAgB;AACvB,QAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,4BAA4B,CAAC;AAAA,EAC7D;AACF,CAAC;AAGD,GAAG,GAAG,cAAc,CAAC,WAAW;AAC9B,UAAQ,IAAI,+BAAwB,OAAO,EAAE;AAG7C,SAAO,KAAK,gBAAgB;AAAA,IAC1B,OAAO,WAAW,SAAS;AAAA,IAC3B,UAAU,gBAAgB,oBACtB,eAAe,kBAAkB,IACjC,CAAC;AAAA,IACL,QAAQ,cAAc,aAAa,KAAK,CAAC;AAAA,EAC3C,CAAC;AAGD,SAAO,GAAG,iBAAiB,MAAM;AAC/B,WAAO,KAAK,gBAAgB,WAAW,SAAS,CAAC;AAAA,EACnD,CAAC;AAED,SAAO,GAAG,oBAAoB,MAAM;AAClC,UAAM,WAAW,gBAAgB,oBAC7B,eAAe,kBAAkB,IACjC,CAAC;AACL,WAAO,KAAK,mBAAmB,QAAQ;AAAA,EACzC,CAAC;AAED,SAAO,GAAG,kBAAkB,MAAM;AAChC,WAAO,KAAK,iBAAiB,cAAc,aAAa,KAAK,CAAC,CAAC;AAAA,EACjE,CAAC;AAED,SAAO,GAAG,cAAc,MAAM;AAC5B,YAAQ,IAAI,kCAA2B,OAAO,EAAE;AAAA,EAClD,CAAC;AACH,CAAC;AAGD,YAAY,MAAM;AAChB,MAAI;AACF,OAAG,KAAK,gBAAgB,WAAW,SAAS,CAAC;AAE7C,UAAM,WAAW,gBAAgB,oBAC7B,eAAe,kBAAkB,IACjC,CAAC;AACL,OAAG,KAAK,mBAAmB,QAAQ;AACnC,OAAG,KAAK,iBAAiB,cAAc,aAAa,KAAK,CAAC,CAAC;AAAA,EAC7D,SAAS,OAAgB;AACvB,YAAQ,MAAM,6BAA6B,KAAK;AAAA,EAClD;AACF,GAAG,GAAI;AAGP,MAAM,OAAO,QAAQ,IAAI,SAAS,KAAK;AAEvC,mBAAmB;AAEnB,WAAW,OAAO,MAAM,MAAM;AAC5B,UAAQ,IAAI;AAAA;AAAA;AAAA,uCAGoB,IAAI;AAAA,qCACN,IAAI;AAAA;AAAA,GAEjC;AACH,CAAC;",
6
6
  "names": []
7
7
  }