@stackmemoryai/stackmemory 0.3.3 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +19 -18
  2. package/dist/cli/commands/chromadb.js +267 -0
  3. package/dist/cli/commands/chromadb.js.map +7 -0
  4. package/dist/cli/commands/context.js +15 -5
  5. package/dist/cli/commands/context.js.map +2 -2
  6. package/dist/cli/commands/infinite-storage.js +240 -0
  7. package/dist/cli/commands/infinite-storage.js.map +7 -0
  8. package/dist/cli/commands/skills.js +262 -0
  9. package/dist/cli/commands/skills.js.map +7 -0
  10. package/dist/cli/index.js +7 -0
  11. package/dist/cli/index.js.map +2 -2
  12. package/dist/core/context/frame-handoff-manager.js +399 -9
  13. package/dist/core/context/frame-handoff-manager.js.map +2 -2
  14. package/dist/core/context/frame-manager.js +11 -2
  15. package/dist/core/context/frame-manager.js.map +2 -2
  16. package/dist/core/storage/chromadb-adapter.js +346 -0
  17. package/dist/core/storage/chromadb-adapter.js.map +7 -0
  18. package/dist/core/storage/chromadb-simple.js +160 -0
  19. package/dist/core/storage/chromadb-simple.js.map +7 -0
  20. package/dist/core/storage/infinite-storage.js +443 -0
  21. package/dist/core/storage/infinite-storage.js.map +7 -0
  22. package/dist/core/utils/compression.js +79 -0
  23. package/dist/core/utils/compression.js.map +7 -0
  24. package/dist/features/tui/services/data-service.js +12 -40
  25. package/dist/features/tui/services/data-service.js.map +2 -2
  26. package/dist/features/tui/services/linear-task-reader.js +100 -0
  27. package/dist/features/tui/services/linear-task-reader.js.map +7 -0
  28. package/dist/features/web/client/stores/task-store.js +22 -0
  29. package/dist/features/web/client/stores/task-store.js.map +7 -0
  30. package/dist/features/web/server/index.js +171 -0
  31. package/dist/features/web/server/index.js.map +7 -0
  32. package/dist/skills/claude-skills.js +712 -0
  33. package/dist/skills/claude-skills.js.map +7 -0
  34. package/dist/skills/dashboard-launcher.js +212 -0
  35. package/dist/skills/dashboard-launcher.js.map +7 -0
  36. package/package.json +23 -31
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/core/storage/infinite-storage.ts"],
4
+ "sourcesContent": ["/**\n * Infinite Storage System for StackMemory\n * Implements STA-287: Remote storage with TimeSeries DB + S3 + Redis\n * \n * Storage Tiers:\n * - Hot: Redis (< 1 hour, frequently accessed)\n * - Warm: TimeSeries DB (1 hour - 7 days)\n * - Cold: S3 Standard (7 days - 30 days)\n * - Archive: S3 Glacier (> 30 days)\n */\n\nimport { S3Client, PutObjectCommand, GetObjectCommand, ListObjectsV2Command } from '@aws-sdk/client-s3';\nimport { createClient as createRedisClient } from 'redis';\nimport { Pool } from 'pg';\nimport { Logger } from '../monitoring/logger.js';\nimport { Frame } from '../context/frame-manager.js';\nimport { v4 as uuidv4 } from 'uuid';\nimport { compress, decompress } from '../utils/compression.js';\n\nexport interface StorageTier {\n name: 'hot' | 'warm' | 'cold' | 'archive';\n ageThresholdHours: number;\n storageClass: string;\n accessLatencyMs: number;\n}\n\nexport interface StorageConfig {\n redis: {\n url: string;\n ttlSeconds: number;\n maxMemoryMB: number;\n };\n timeseries: {\n connectionString: string;\n retentionDays: number;\n };\n s3: {\n bucket: string;\n region: string;\n accessKeyId?: string;\n secretAccessKey?: string;\n };\n tiers: StorageTier[];\n}\n\nexport interface StorageMetrics {\n totalObjects: number;\n tierDistribution: Record<string, number>;\n storageBytes: number;\n avgLatencyMs: number;\n p50LatencyMs: number;\n p99LatencyMs: number;\n}\n\nexport class InfiniteStorageSystem {\n private redisClient: any;\n private timeseriesPool: Pool;\n private s3Client: S3Client;\n private logger: Logger;\n private config: StorageConfig;\n private latencies: number[] = [];\n private migrationWorker: NodeJS.Timeout | null = null;\n\n constructor(config: StorageConfig) {\n this.config = config;\n this.logger = new Logger('InfiniteStorage');\n \n // Default storage tiers\n if (!config.tiers || config.tiers.length === 0) {\n this.config.tiers = [\n { name: 'hot', ageThresholdHours: 1, storageClass: 'MEMORY', accessLatencyMs: 5 },\n { name: 'warm', ageThresholdHours: 168, storageClass: 'TIMESERIES', accessLatencyMs: 50 },\n { name: 'cold', ageThresholdHours: 720, storageClass: 'S3_STANDARD', accessLatencyMs: 100 },\n { name: 'archive', ageThresholdHours: Infinity, storageClass: 'S3_GLACIER', accessLatencyMs: 3600000 },\n ];\n }\n }\n\n async initialize(): Promise<void> {\n try {\n // Initialize Redis (hot tier)\n if (this.config.redis?.url) {\n this.redisClient = createRedisClient({\n url: this.config.redis.url,\n });\n \n await this.redisClient.connect();\n \n // Configure Redis memory policy\n await this.redisClient.configSet('maxmemory-policy', 'allkeys-lru');\n if (this.config.redis.maxMemoryMB) {\n await this.redisClient.configSet('maxmemory', `${this.config.redis.maxMemoryMB}mb`);\n }\n \n this.logger.info('Redis client initialized for hot tier');\n }\n\n // Initialize TimeSeries DB (warm tier)\n if (this.config.timeseries?.connectionString) {\n this.timeseriesPool = new Pool({\n connectionString: this.config.timeseries.connectionString,\n max: 10,\n idleTimeoutMillis: 30000,\n });\n\n // Create TimeSeries tables if not exists\n await this.createTimeSeriesTables();\n this.logger.info('TimeSeries DB initialized for warm tier');\n }\n\n // Initialize S3 (cold/archive tiers)\n if (this.config.s3?.bucket) {\n this.s3Client = new S3Client({\n region: this.config.s3.region || 'us-east-1',\n credentials: this.config.s3.accessKeyId ? {\n accessKeyId: this.config.s3.accessKeyId,\n secretAccessKey: this.config.s3.secretAccessKey!,\n } : undefined,\n });\n \n this.logger.info('S3 client initialized for cold/archive tiers');\n }\n\n // Start background migration worker\n this.startMigrationWorker();\n \n this.logger.info('Infinite Storage System initialized');\n } catch (error) {\n this.logger.error('Failed to initialize storage system', error);\n throw error;\n }\n }\n\n /**\n * Create TimeSeries tables for warm tier storage\n */\n private async createTimeSeriesTables(): Promise<void> {\n const client = await this.timeseriesPool.connect();\n \n try {\n // Create hypertable for time-series data\n await client.query(`\n CREATE TABLE IF NOT EXISTS frame_timeseries (\n time TIMESTAMPTZ NOT NULL,\n frame_id TEXT NOT NULL,\n user_id TEXT NOT NULL,\n project_name TEXT,\n type TEXT,\n data JSONB,\n compressed_data BYTEA,\n storage_tier TEXT DEFAULT 'warm',\n access_count INTEGER DEFAULT 0,\n last_accessed TIMESTAMPTZ DEFAULT NOW(),\n PRIMARY KEY (time, frame_id)\n )\n `);\n\n // Create hypertable if using TimescaleDB\n await client.query(`\n SELECT create_hypertable('frame_timeseries', 'time', \n chunk_time_interval => INTERVAL '1 day',\n if_not_exists => TRUE)\n `).catch(() => {\n // Fallback to regular partitioning if not TimescaleDB\n this.logger.info('Using standard PostgreSQL partitioning');\n });\n\n // Create indexes\n await client.query(`\n CREATE INDEX IF NOT EXISTS idx_frame_user ON frame_timeseries (user_id, time DESC);\n CREATE INDEX IF NOT EXISTS idx_frame_project ON frame_timeseries (project_name, time DESC);\n CREATE INDEX IF NOT EXISTS idx_frame_tier ON frame_timeseries (storage_tier);\n `);\n\n // Create compression policy (TimescaleDB specific)\n await client.query(`\n SELECT add_compression_policy('frame_timeseries', INTERVAL '7 days', if_not_exists => TRUE)\n `).catch(() => {\n this.logger.info('Compression policy not available');\n });\n\n } finally {\n client.release();\n }\n }\n\n /**\n * Store a frame with automatic tier selection\n */\n async storeFrame(frame: Frame, userId: string): Promise<void> {\n const startTime = Date.now();\n \n try {\n const frameData = JSON.stringify(frame);\n const compressedData = await compress(frameData);\n const frameKey = `frame:${userId}:${frame.frameId}`;\n\n // Always store in hot tier first (Redis)\n if (this.redisClient) {\n await this.redisClient.setEx(\n frameKey,\n this.config.redis.ttlSeconds || 3600,\n compressedData\n );\n \n // Store metadata for quick lookups\n await this.redisClient.hSet(`meta:${frameKey}`, {\n userId,\n projectName: frame.projectName || 'default',\n type: frame.type,\n timestamp: frame.timestamp,\n tier: 'hot',\n });\n }\n\n // Also store in warm tier for durability\n if (this.timeseriesPool) {\n const client = await this.timeseriesPool.connect();\n \n try {\n await client.query(`\n INSERT INTO frame_timeseries (time, frame_id, user_id, project_name, type, data, compressed_data, storage_tier)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8)\n ON CONFLICT (time, frame_id) DO UPDATE\n SET data = EXCLUDED.data,\n compressed_data = EXCLUDED.compressed_data,\n last_accessed = NOW(),\n access_count = frame_timeseries.access_count + 1\n `, [\n new Date(frame.timestamp),\n frame.frameId,\n userId,\n frame.projectName || 'default',\n frame.type,\n frame,\n compressedData,\n 'warm',\n ]);\n } finally {\n client.release();\n }\n }\n\n // Track latency\n const latency = Date.now() - startTime;\n this.trackLatency(latency);\n \n this.logger.debug(`Stored frame ${frame.frameId} in ${latency}ms`);\n } catch (error) {\n this.logger.error(`Failed to store frame ${frame.frameId}`, error);\n throw error;\n }\n }\n\n /**\n * Retrieve a frame with intelligent caching\n */\n async retrieveFrame(frameId: string, userId: string): Promise<Frame | null> {\n const startTime = Date.now();\n const frameKey = `frame:${userId}:${frameId}`;\n\n try {\n // Try hot tier first (Redis)\n if (this.redisClient) {\n const cached = await this.redisClient.get(frameKey);\n if (cached) {\n const decompressed = await decompress(cached);\n const frame = JSON.parse(decompressed);\n \n // Refresh TTL on access\n await this.redisClient.expire(frameKey, this.config.redis.ttlSeconds || 3600);\n \n const latency = Date.now() - startTime;\n this.trackLatency(latency);\n this.logger.debug(`Retrieved frame ${frameId} from hot tier in ${latency}ms`);\n \n return frame;\n }\n }\n\n // Try warm tier (TimeSeries DB)\n if (this.timeseriesPool) {\n const client = await this.timeseriesPool.connect();\n \n try {\n const result = await client.query(`\n SELECT data, compressed_data, storage_tier \n FROM frame_timeseries \n WHERE frame_id = $1 AND user_id = $2\n ORDER BY time DESC\n LIMIT 1\n `, [frameId, userId]);\n\n if (result.rows.length > 0) {\n const row = result.rows[0];\n let frame: Frame;\n \n if (row.compressed_data) {\n const decompressed = await decompress(row.compressed_data);\n frame = JSON.parse(decompressed);\n } else {\n frame = row.data;\n }\n\n // Update access stats\n await client.query(`\n UPDATE frame_timeseries \n SET last_accessed = NOW(), access_count = access_count + 1\n WHERE frame_id = $1 AND user_id = $2\n `, [frameId, userId]);\n\n // Promote to hot tier if frequently accessed\n if (this.redisClient) {\n await this.promoteToHotTier(frame, userId);\n }\n\n const latency = Date.now() - startTime;\n this.trackLatency(latency);\n this.logger.debug(`Retrieved frame ${frameId} from warm tier in ${latency}ms`);\n \n return frame;\n }\n } finally {\n client.release();\n }\n }\n\n // Try cold/archive tiers (S3)\n if (this.s3Client && this.config.s3.bucket) {\n const key = `frames/${userId}/${frameId}.json.gz`;\n \n try {\n const command = new GetObjectCommand({\n Bucket: this.config.s3.bucket,\n Key: key,\n });\n \n const response = await this.s3Client.send(command);\n const compressedData = await response.Body!.transformToByteArray();\n const decompressed = await decompress(Buffer.from(compressedData));\n const frame = JSON.parse(decompressed);\n\n // Promote to warmer tiers for future access\n await this.promoteFrame(frame, userId);\n\n const latency = Date.now() - startTime;\n this.trackLatency(latency);\n this.logger.debug(`Retrieved frame ${frameId} from cold tier in ${latency}ms`);\n \n return frame;\n } catch (error: any) {\n if (error.Code !== 'NoSuchKey') {\n throw error;\n }\n }\n }\n\n this.logger.debug(`Frame ${frameId} not found in any tier`);\n return null;\n } catch (error) {\n this.logger.error(`Failed to retrieve frame ${frameId}`, error);\n throw error;\n }\n }\n\n /**\n * Promote frame to hot tier for fast access\n */\n private async promoteToHotTier(frame: Frame, userId: string): Promise<void> {\n if (!this.redisClient) return;\n \n try {\n const frameKey = `frame:${userId}:${frame.frameId}`;\n const frameData = JSON.stringify(frame);\n const compressedData = await compress(frameData);\n \n await this.redisClient.setEx(\n frameKey,\n this.config.redis.ttlSeconds || 3600,\n compressedData\n );\n \n this.logger.debug(`Promoted frame ${frame.frameId} to hot tier`);\n } catch (error) {\n this.logger.error(`Failed to promote frame ${frame.frameId}`, error);\n }\n }\n\n /**\n * Promote frame through storage tiers\n */\n private async promoteFrame(frame: Frame, userId: string): Promise<void> {\n // Promote to warm tier\n if (this.timeseriesPool) {\n const client = await this.timeseriesPool.connect();\n \n try {\n const compressedData = await compress(JSON.stringify(frame));\n \n await client.query(`\n INSERT INTO frame_timeseries (time, frame_id, user_id, data, compressed_data, storage_tier)\n VALUES ($1, $2, $3, $4, $5, $6)\n ON CONFLICT (time, frame_id) DO UPDATE\n SET storage_tier = 'warm',\n last_accessed = NOW(),\n access_count = frame_timeseries.access_count + 1\n `, [\n new Date(frame.timestamp),\n frame.frameId,\n userId,\n frame,\n compressedData,\n 'warm',\n ]);\n } finally {\n client.release();\n }\n }\n\n // Also promote to hot tier\n await this.promoteToHotTier(frame, userId);\n }\n\n /**\n * Start background worker for tier migration\n */\n private startMigrationWorker(): void {\n // Run migration every hour\n this.migrationWorker = setInterval(async () => {\n await this.migrateAgedData();\n }, 60 * 60 * 1000);\n \n this.logger.info('Migration worker started');\n }\n\n /**\n * Migrate aged data to appropriate storage tiers\n */\n private async migrateAgedData(): Promise<void> {\n this.logger.info('Starting tier migration...');\n \n if (!this.timeseriesPool) return;\n \n const client = await this.timeseriesPool.connect();\n \n try {\n // Find data eligible for cold storage (> 7 days old)\n const coldEligible = await client.query(`\n SELECT frame_id, user_id, data, compressed_data\n FROM frame_timeseries\n WHERE storage_tier = 'warm'\n AND time < NOW() - INTERVAL '7 days'\n AND last_accessed < NOW() - INTERVAL '7 days'\n LIMIT 1000\n `);\n\n // Migrate to S3 cold storage\n for (const row of coldEligible.rows) {\n await this.migrateToS3(row, 'STANDARD');\n \n // Update tier in database\n await client.query(`\n UPDATE frame_timeseries\n SET storage_tier = 'cold'\n WHERE frame_id = $1 AND user_id = $2\n `, [row.frame_id, row.user_id]);\n }\n\n // Find data eligible for archive (> 30 days old)\n const archiveEligible = await client.query(`\n SELECT frame_id, user_id, data, compressed_data\n FROM frame_timeseries\n WHERE storage_tier = 'cold'\n AND time < NOW() - INTERVAL '30 days'\n AND last_accessed < NOW() - INTERVAL '30 days'\n LIMIT 1000\n `);\n\n // Migrate to S3 Glacier\n for (const row of archiveEligible.rows) {\n await this.migrateToS3(row, 'GLACIER');\n \n // Update tier in database\n await client.query(`\n UPDATE frame_timeseries\n SET storage_tier = 'archive'\n WHERE frame_id = $1 AND user_id = $2\n `, [row.frame_id, row.user_id]);\n }\n\n this.logger.info(`Migration completed: ${coldEligible.rows.length} to cold, ${archiveEligible.rows.length} to archive`);\n } finally {\n client.release();\n }\n }\n\n /**\n * Migrate data to S3 storage\n */\n private async migrateToS3(row: any, storageClass: string): Promise<void> {\n if (!this.s3Client || !this.config.s3.bucket) return;\n \n try {\n const key = `frames/${row.user_id}/${row.frame_id}.json.gz`;\n const data = row.compressed_data || await compress(JSON.stringify(row.data));\n \n const command = new PutObjectCommand({\n Bucket: this.config.s3.bucket,\n Key: key,\n Body: data,\n StorageClass: storageClass,\n Metadata: {\n userId: row.user_id,\n frameId: row.frame_id,\n migratedAt: new Date().toISOString(),\n },\n });\n \n await this.s3Client.send(command);\n \n this.logger.debug(`Migrated frame ${row.frame_id} to S3 ${storageClass}`);\n } catch (error) {\n this.logger.error(`Failed to migrate frame ${row.frame_id} to S3`, error);\n throw error;\n }\n }\n\n /**\n * Track latency for performance monitoring\n */\n private trackLatency(latencyMs: number): void {\n this.latencies.push(latencyMs);\n \n // Keep only last 1000 measurements\n if (this.latencies.length > 1000) {\n this.latencies.shift();\n }\n }\n\n /**\n * Get storage metrics\n */\n async getMetrics(): Promise<StorageMetrics> {\n const metrics: StorageMetrics = {\n totalObjects: 0,\n tierDistribution: {},\n storageBytes: 0,\n avgLatencyMs: 0,\n p50LatencyMs: 0,\n p99LatencyMs: 0,\n };\n\n // Calculate latency percentiles\n if (this.latencies.length > 0) {\n const sorted = [...this.latencies].sort((a, b) => a - b);\n metrics.avgLatencyMs = sorted.reduce((a, b) => a + b, 0) / sorted.length;\n metrics.p50LatencyMs = sorted[Math.floor(sorted.length * 0.5)];\n metrics.p99LatencyMs = sorted[Math.floor(sorted.length * 0.99)];\n }\n\n // Get tier distribution from TimeSeries DB\n if (this.timeseriesPool) {\n const client = await this.timeseriesPool.connect();\n \n try {\n const result = await client.query(`\n SELECT \n storage_tier,\n COUNT(*) as count,\n SUM(pg_column_size(compressed_data)) as bytes\n FROM frame_timeseries\n GROUP BY storage_tier\n `);\n\n for (const row of result.rows) {\n metrics.tierDistribution[row.storage_tier] = parseInt(row.count);\n metrics.storageBytes += parseInt(row.bytes || 0);\n metrics.totalObjects += parseInt(row.count);\n }\n } finally {\n client.release();\n }\n }\n\n return metrics;\n }\n\n /**\n * Cleanup and shutdown\n */\n async shutdown(): Promise<void> {\n if (this.migrationWorker) {\n clearInterval(this.migrationWorker);\n }\n\n if (this.redisClient) {\n await this.redisClient.quit();\n }\n\n if (this.timeseriesPool) {\n await this.timeseriesPool.end();\n }\n\n this.logger.info('Infinite Storage System shut down');\n }\n}"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,79 @@
1
+ import zlib from "zlib";
2
+ import { promisify } from "util";
3
+ const gzipAsync = promisify(zlib.gzip);
4
+ const gunzipAsync = promisify(zlib.gunzip);
5
+ const brotliCompressAsync = promisify(zlib.brotliCompress);
6
+ const brotliDecompressAsync = promisify(zlib.brotliDecompress);
7
+ var CompressionType = /* @__PURE__ */ ((CompressionType2) => {
8
+ CompressionType2["NONE"] = "none";
9
+ CompressionType2["GZIP"] = "gzip";
10
+ CompressionType2["BROTLI"] = "brotli";
11
+ return CompressionType2;
12
+ })(CompressionType || {});
13
+ async function compress(data, options = {}) {
14
+ const { type = "gzip" /* GZIP */, level = 6 } = options;
15
+ const input = typeof data === "string" ? Buffer.from(data, "utf8") : data;
16
+ switch (type) {
17
+ case "none" /* NONE */:
18
+ return input;
19
+ case "gzip" /* GZIP */:
20
+ return gzipAsync(input, { level });
21
+ case "brotli" /* BROTLI */:
22
+ return brotliCompressAsync(input, {
23
+ params: {
24
+ [zlib.constants.BROTLI_PARAM_QUALITY]: level
25
+ }
26
+ });
27
+ default:
28
+ throw new Error(`Unknown compression type: ${type}`);
29
+ }
30
+ }
31
+ async function decompress(data, type = "gzip" /* GZIP */) {
32
+ let decompressed;
33
+ switch (type) {
34
+ case "none" /* NONE */:
35
+ decompressed = data;
36
+ break;
37
+ case "gzip" /* GZIP */:
38
+ decompressed = await gunzipAsync(data);
39
+ break;
40
+ case "brotli" /* BROTLI */:
41
+ decompressed = await brotliDecompressAsync(data);
42
+ break;
43
+ default:
44
+ throw new Error(`Unknown compression type: ${type}`);
45
+ }
46
+ return decompressed.toString("utf8");
47
+ }
48
+ function compressionRatio(original, compressed) {
49
+ if (original === 0) return 0;
50
+ return (1 - compressed / original) * 100;
51
+ }
52
+ function detectCompressionType(data) {
53
+ if (data.length >= 2 && data[0] === 31 && data[1] === 139) {
54
+ return "gzip" /* GZIP */;
55
+ }
56
+ if (data.length >= 4 && data[0] === 206 && data[1] === 178) {
57
+ return "brotli" /* BROTLI */;
58
+ }
59
+ return "none" /* NONE */;
60
+ }
61
+ function chooseOptimalCompression(data, speedPriority = false) {
62
+ const size = typeof data === "string" ? Buffer.byteLength(data) : data.length;
63
+ if (size < 1024) {
64
+ return "none" /* NONE */;
65
+ }
66
+ if (speedPriority || size < 100 * 1024) {
67
+ return "gzip" /* GZIP */;
68
+ }
69
+ return "brotli" /* BROTLI */;
70
+ }
71
+ export {
72
+ CompressionType,
73
+ chooseOptimalCompression,
74
+ compress,
75
+ compressionRatio,
76
+ decompress,
77
+ detectCompressionType
78
+ };
79
+ //# sourceMappingURL=compression.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/core/utils/compression.ts"],
4
+ "sourcesContent": ["/**\n * Compression utilities for storage optimization\n */\n\nimport zlib from 'zlib';\nimport { promisify } from 'util';\n\nconst gzipAsync = promisify(zlib.gzip);\nconst gunzipAsync = promisify(zlib.gunzip);\nconst brotliCompressAsync = promisify(zlib.brotliCompress);\nconst brotliDecompressAsync = promisify(zlib.brotliDecompress);\n\nexport enum CompressionType {\n NONE = 'none',\n GZIP = 'gzip',\n BROTLI = 'brotli',\n}\n\nexport interface CompressionOptions {\n type?: CompressionType;\n level?: number;\n}\n\n/**\n * Compress data using specified algorithm\n */\nexport async function compress(\n data: string | Buffer,\n options: CompressionOptions = {}\n): Promise<Buffer> {\n const { type = CompressionType.GZIP, level = 6 } = options;\n \n const input = typeof data === 'string' ? Buffer.from(data, 'utf8') : data;\n \n switch (type) {\n case CompressionType.NONE:\n return input;\n \n case CompressionType.GZIP:\n return gzipAsync(input, { level });\n \n case CompressionType.BROTLI:\n return brotliCompressAsync(input, {\n params: {\n [zlib.constants.BROTLI_PARAM_QUALITY]: level,\n },\n });\n \n default:\n throw new Error(`Unknown compression type: ${type}`);\n }\n}\n\n/**\n * Decompress data\n */\nexport async function decompress(\n data: Buffer,\n type: CompressionType = CompressionType.GZIP\n): Promise<string> {\n let decompressed: Buffer;\n \n switch (type) {\n case CompressionType.NONE:\n decompressed = data;\n break;\n \n case CompressionType.GZIP:\n decompressed = await gunzipAsync(data);\n break;\n \n case CompressionType.BROTLI:\n decompressed = await brotliDecompressAsync(data);\n break;\n \n default:\n throw new Error(`Unknown compression type: ${type}`);\n }\n \n return decompressed.toString('utf8');\n}\n\n/**\n * Calculate compression ratio\n */\nexport function compressionRatio(original: number, compressed: number): number {\n if (original === 0) return 0;\n return (1 - compressed / original) * 100;\n}\n\n/**\n * Auto-detect compression type from buffer\n */\nexport function detectCompressionType(data: Buffer): CompressionType {\n // Check for gzip magic number\n if (data.length >= 2 && data[0] === 0x1f && data[1] === 0x8b) {\n return CompressionType.GZIP;\n }\n \n // Check for brotli\n // Brotli doesn't have a consistent magic number, but we can try to decompress\n // This is a heuristic approach\n if (data.length >= 4 && data[0] === 0xce && data[1] === 0xb2) {\n return CompressionType.BROTLI;\n }\n \n return CompressionType.NONE;\n}\n\n/**\n * Choose optimal compression based on data characteristics\n */\nexport function chooseOptimalCompression(\n data: string | Buffer,\n speedPriority: boolean = false\n): CompressionType {\n const size = typeof data === 'string' ? Buffer.byteLength(data) : data.length;\n \n // Don't compress small data\n if (size < 1024) {\n return CompressionType.NONE;\n }\n \n // Use gzip for speed priority or medium data\n if (speedPriority || size < 100 * 1024) {\n return CompressionType.GZIP;\n }\n \n // Use brotli for large data and better compression\n return CompressionType.BROTLI;\n}"],
5
+ "mappings": "AAIA,OAAO,UAAU;AACjB,SAAS,iBAAiB;AAE1B,MAAM,YAAY,UAAU,KAAK,IAAI;AACrC,MAAM,cAAc,UAAU,KAAK,MAAM;AACzC,MAAM,sBAAsB,UAAU,KAAK,cAAc;AACzD,MAAM,wBAAwB,UAAU,KAAK,gBAAgB;AAEtD,IAAK,kBAAL,kBAAKA,qBAAL;AACL,EAAAA,iBAAA,UAAO;AACP,EAAAA,iBAAA,UAAO;AACP,EAAAA,iBAAA,YAAS;AAHC,SAAAA;AAAA,GAAA;AAcZ,eAAsB,SACpB,MACA,UAA8B,CAAC,GACd;AACjB,QAAM,EAAE,OAAO,mBAAsB,QAAQ,EAAE,IAAI;AAEnD,QAAM,QAAQ,OAAO,SAAS,WAAW,OAAO,KAAK,MAAM,MAAM,IAAI;AAErE,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO,UAAU,OAAO,EAAE,MAAM,CAAC;AAAA,IAEnC,KAAK;AACH,aAAO,oBAAoB,OAAO;AAAA,QAChC,QAAQ;AAAA,UACN,CAAC,KAAK,UAAU,oBAAoB,GAAG;AAAA,QACzC;AAAA,MACF,CAAC;AAAA,IAEH;AACE,YAAM,IAAI,MAAM,6BAA6B,IAAI,EAAE;AAAA,EACvD;AACF;AAKA,eAAsB,WACpB,MACA,OAAwB,mBACP;AACjB,MAAI;AAEJ,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,qBAAe;AACf;AAAA,IAEF,KAAK;AACH,qBAAe,MAAM,YAAY,IAAI;AACrC;AAAA,IAEF,KAAK;AACH,qBAAe,MAAM,sBAAsB,IAAI;AAC/C;AAAA,IAEF;AACE,YAAM,IAAI,MAAM,6BAA6B,IAAI,EAAE;AAAA,EACvD;AAEA,SAAO,aAAa,SAAS,MAAM;AACrC;AAKO,SAAS,iBAAiB,UAAkB,YAA4B;AAC7E,MAAI,aAAa,EAAG,QAAO;AAC3B,UAAQ,IAAI,aAAa,YAAY;AACvC;AAKO,SAAS,sBAAsB,MAA+B;AAEnE,MAAI,KAAK,UAAU,KAAK,KAAK,CAAC,MAAM,MAAQ,KAAK,CAAC,MAAM,KAAM;AAC5D,WAAO;AAAA,EACT;AAKA,MAAI,KAAK,UAAU,KAAK,KAAK,CAAC,MAAM,OAAQ,KAAK,CAAC,MAAM,KAAM;AAC5D,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAKO,SAAS,yBACd,MACA,gBAAyB,OACR;AACjB,QAAM,OAAO,OAAO,SAAS,WAAW,OAAO,WAAW,IAAI,IAAI,KAAK;AAGvE,MAAI,OAAO,MAAM;AACf,WAAO;AAAA,EACT;AAGA,MAAI,iBAAiB,OAAO,MAAM,MAAM;AACtC,WAAO;AAAA,EACT;AAGA,SAAO;AACT;",
6
+ "names": ["CompressionType"]
7
+ }
@@ -2,14 +2,13 @@ import { EventEmitter } from "events";
2
2
  import Database from "better-sqlite3";
3
3
  import { SessionManager } from "../../../core/session/session-manager.js";
4
4
  import { FrameManager } from "../../../core/context/frame-manager.js";
5
- import { PebblesTaskStore } from "../../tasks/pebbles-task-store.js";
6
- import { existsSync, readFileSync } from "fs";
7
- import { join } from "path";
5
+ import { LinearTaskReader } from "./linear-task-reader.js";
6
+ import { existsSync } from "fs";
8
7
  class DataService extends EventEmitter {
9
8
  db = null;
10
9
  sessionManager = null;
11
10
  frameManager = null;
12
- taskStore = null;
11
+ taskReader = null;
13
12
  linearMappings = /* @__PURE__ */ new Map();
14
13
  cache = /* @__PURE__ */ new Map();
15
14
  cacheTimeout = 5e3;
@@ -27,21 +26,15 @@ class DataService extends EventEmitter {
27
26
  }
28
27
  }
29
28
  try {
30
- this.taskStore = new PebblesTaskStore();
31
- const mappingsPath = join(
32
- process.env.PROJECT_ROOT || process.cwd(),
33
- ".stackmemory",
34
- "linear-mappings.json"
35
- );
36
- if (existsSync(mappingsPath)) {
37
- const mappingsData = JSON.parse(readFileSync(mappingsPath, "utf8"));
38
- mappingsData.forEach((mapping) => {
39
- this.linearMappings.set(mapping.stackmemoryId, mapping);
40
- });
29
+ this.taskReader = new LinearTaskReader(process.env.PROJECT_ROOT || process.cwd());
30
+ this.linearMappings = this.taskReader.getMappings();
31
+ if (process.env.DEBUG) {
32
+ const tasks = this.taskReader.getTasks();
33
+ console.log(`LinearTaskReader initialized with ${tasks.length} tasks`);
41
34
  }
42
35
  } catch (tsError) {
43
36
  if (process.env.DEBUG) {
44
- console.log("Task store initialization failed:", tsError.message);
37
+ console.log("Task reader initialization failed:", tsError.message);
45
38
  }
46
39
  }
47
40
  try {
@@ -118,31 +111,10 @@ class DataService extends EventEmitter {
118
111
  const cached = this.getFromCache("tasks");
119
112
  if (cached) return cached;
120
113
  const tasks = [];
121
- if (this.taskStore) {
114
+ if (this.taskReader) {
122
115
  try {
123
- const localTasks = this.taskStore.getActiveTasks();
124
- localTasks.forEach((localTask) => {
125
- const mapping = this.linearMappings.get(localTask.id);
126
- const identifierMatch = localTask.title.match(/\[(\w+-\d+)\]/);
127
- const identifier = identifierMatch ? identifierMatch[1] : mapping?.linearIdentifier || "LOCAL-" + localTask.id.slice(-6);
128
- const linearTask = {
129
- id: mapping?.linearId || localTask.id,
130
- identifier,
131
- title: localTask.title.replace(/\[\w+-\d+\]\s*/, ""),
132
- // Remove identifier from title
133
- description: localTask.description,
134
- state: this.mapLocalStatusToLinearState(localTask.status),
135
- priority: this.mapLocalPriorityToLinear(localTask.priority),
136
- estimate: localTask.estimated_effort ? Math.ceil(localTask.estimated_effort / 60) : void 0,
137
- assignee: localTask.assignee,
138
- createdAt: new Date(localTask.created_at * 1e3).toISOString(),
139
- updatedAt: new Date(localTask.timestamp * 1e3).toISOString(),
140
- // Add sync metadata
141
- lastSyncedAt: mapping?.lastSyncTimestamp ? new Date(mapping.lastSyncTimestamp).toISOString() : void 0,
142
- syncStatus: mapping ? "synced" : "local"
143
- };
144
- tasks.push(linearTask);
145
- });
116
+ const localTasks = this.taskReader.getTasks();
117
+ tasks.push(...localTasks);
146
118
  if (process.env.DEBUG) {
147
119
  console.log(
148
120
  `Loaded ${tasks.length} tasks from local store (no Linear API calls)`
@@ -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 { PebblesTaskStore } from '../../tasks/pebbles-task-store.js';\nimport { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport type {\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 taskStore: PebblesTaskStore | 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) {\n if (process.env.DEBUG) {\n console.log('Database not accessible, continuing without it');\n }\n }\n\n // Initialize task store for local synced tasks\n try {\n this.taskStore = new PebblesTaskStore();\n\n // Load Linear mappings if they exist\n const mappingsPath = join(\n process.env.PROJECT_ROOT || process.cwd(),\n '.stackmemory',\n 'linear-mappings.json'\n );\n if (existsSync(mappingsPath)) {\n const mappingsData = JSON.parse(readFileSync(mappingsPath, 'utf8'));\n mappingsData.forEach((mapping: any) => {\n this.linearMappings.set(mapping.stackmemoryId, mapping);\n });\n }\n } catch (tsError) {\n if (process.env.DEBUG) {\n console.log('Task store 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) {\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) {\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) {\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) {\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) {\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.taskStore) {\n try {\n const localTasks = this.taskStore.getActiveTasks();\n\n // Convert local tasks to TUI display format\n localTasks.forEach((localTask) => {\n const mapping = this.linearMappings.get(localTask.id);\n\n // Extract identifier from title (e.g., \"[ENG-123] Task title\")\n const identifierMatch = localTask.title.match(/\\[(\\w+-\\d+)\\]/);\n const identifier = identifierMatch\n ? identifierMatch[1]\n : mapping?.linearIdentifier || 'LOCAL-' + localTask.id.slice(-6);\n\n // Format local task for TUI display\n const linearTask: LinearTask = {\n id: mapping?.linearId || localTask.id,\n identifier: identifier,\n title: localTask.title.replace(/\\[\\w+-\\d+\\]\\s*/, ''), // Remove identifier from title\n description: localTask.description,\n state: this.mapLocalStatusToLinearState(localTask.status),\n priority: this.mapLocalPriorityToLinear(localTask.priority),\n estimate: localTask.estimated_effort\n ? Math.ceil(localTask.estimated_effort / 60)\n : undefined,\n assignee: localTask.assignee,\n createdAt: new Date(localTask.created_at * 1000).toISOString(),\n updatedAt: new Date(localTask.timestamp * 1000).toISOString(),\n // Add sync metadata\n lastSyncedAt: mapping?.lastSyncTimestamp\n ? new Date(mapping.lastSyncTimestamp).toISOString()\n : undefined,\n syncStatus: mapping ? 'synced' : 'local',\n };\n\n tasks.push(linearTask);\n });\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) {\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) {\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) {\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) {\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) {\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) {\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 {\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) {\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) {\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) {\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) {\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) {\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) {\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) {\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) {\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) {\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) {\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) {\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) {\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) {\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
  }
@@ -0,0 +1,100 @@
1
+ import { readFileSync, existsSync } from "fs";
2
+ import { join } from "path";
3
+ class LinearTaskReader {
4
+ tasksFile;
5
+ mappingsFile;
6
+ constructor(projectRoot) {
7
+ const root = projectRoot || process.cwd();
8
+ this.tasksFile = join(root, ".stackmemory", "tasks.jsonl");
9
+ this.mappingsFile = join(root, ".stackmemory", "linear-mappings.json");
10
+ }
11
+ /**
12
+ * Read tasks from the Linear-synced JSONL file
13
+ */
14
+ getTasks() {
15
+ if (!existsSync(this.tasksFile)) {
16
+ console.log('No tasks file found. Run "npm run linear:sync" to sync tasks.');
17
+ return [];
18
+ }
19
+ try {
20
+ const content = readFileSync(this.tasksFile, "utf8");
21
+ const lines = content.split("\n").filter(Boolean);
22
+ const tasks = lines.map((line) => {
23
+ const task = JSON.parse(line);
24
+ return {
25
+ id: task.id || task.linearId,
26
+ identifier: task.taskId || task.linearId || task.id,
27
+ title: task.title,
28
+ description: task.description || "",
29
+ state: task.linearState || this.mapStatusToState(task.status),
30
+ priority: task.priority || 4,
31
+ estimate: task.estimate,
32
+ assignee: task.assignee,
33
+ createdAt: task.createdAt,
34
+ updatedAt: task.updatedAt,
35
+ lastSyncedAt: task.updatedAt,
36
+ syncStatus: "synced"
37
+ };
38
+ });
39
+ return tasks;
40
+ } catch (error) {
41
+ console.error("Error reading tasks:", error);
42
+ return [];
43
+ }
44
+ }
45
+ /**
46
+ * Get task mappings between Linear and local IDs
47
+ */
48
+ getMappings() {
49
+ if (!existsSync(this.mappingsFile)) {
50
+ return /* @__PURE__ */ new Map();
51
+ }
52
+ try {
53
+ const content = readFileSync(this.mappingsFile, "utf8");
54
+ const mappings = JSON.parse(content);
55
+ return new Map(Object.entries(mappings));
56
+ } catch (error) {
57
+ console.error("Error reading mappings:", error);
58
+ return /* @__PURE__ */ new Map();
59
+ }
60
+ }
61
+ /**
62
+ * Get active tasks (not completed or canceled)
63
+ */
64
+ getActiveTasks() {
65
+ const allTasks = this.getTasks();
66
+ return allTasks.filter(
67
+ (task) => task.state !== "Done" && task.state !== "Canceled" && task.state !== "Duplicate"
68
+ );
69
+ }
70
+ /**
71
+ * Get tasks by state
72
+ */
73
+ getTasksByState(state) {
74
+ const allTasks = this.getTasks();
75
+ return allTasks.filter((task) => task.state === state);
76
+ }
77
+ /**
78
+ * Map local status to Linear state name
79
+ */
80
+ mapStatusToState(status) {
81
+ switch (status) {
82
+ case "completed":
83
+ return "Done";
84
+ case "in_progress":
85
+ return "In Progress";
86
+ case "cancelled":
87
+ return "Canceled";
88
+ case "backlog":
89
+ return "Backlog";
90
+ case "todo":
91
+ return "Todo";
92
+ default:
93
+ return "Backlog";
94
+ }
95
+ }
96
+ }
97
+ export {
98
+ LinearTaskReader
99
+ };
100
+ //# sourceMappingURL=linear-task-reader.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 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 => {\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) {\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) {\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 => \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 => 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,UAAQ;AAC5C,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,OAAO;AACd,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,OAAO;AACd,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,UACrB,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,UAAQ,KAAK,UAAU,KAAK;AAAA,EACrD;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;",
6
+ "names": []
7
+ }
@@ -0,0 +1,22 @@
1
+ import { create } from "zustand";
2
+ const useTaskStore = create((set, get) => ({
3
+ tasks: [],
4
+ setTasks: (tasks) => set({ tasks }),
5
+ addTask: (task) => set((state) => ({
6
+ tasks: [...state.tasks, task]
7
+ })),
8
+ updateTask: (id, updates) => set((state) => ({
9
+ tasks: state.tasks.map(
10
+ (task) => task.id === id ? { ...task, ...updates } : task
11
+ )
12
+ })),
13
+ removeTask: (id) => set((state) => ({
14
+ tasks: state.tasks.filter((task) => task.id !== id)
15
+ })),
16
+ getTaskById: (id) => get().tasks.find((task) => task.id === id),
17
+ getTasksByState: (state) => get().tasks.filter((task) => task.state === state)
18
+ }));
19
+ export {
20
+ useTaskStore
21
+ };
22
+ //# sourceMappingURL=task-store.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 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 =>\n task.id === id ? { ...task, ...updates } : task\n ),\n })),\n \n removeTask: (id) => set((state) => ({\n tasks: state.tasks.filter(task => task.id !== id),\n })),\n \n getTaskById: (id) => get().tasks.find(task => task.id === id),\n \n getTasksByState: (state) => get().tasks.filter(task => 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,UACrB,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,UAAQ,KAAK,OAAO,EAAE;AAAA,EAClD,EAAE;AAAA,EAEF,aAAa,CAAC,OAAO,IAAI,EAAE,MAAM,KAAK,UAAQ,KAAK,OAAO,EAAE;AAAA,EAE5D,iBAAiB,CAAC,UAAU,IAAI,EAAE,MAAM,OAAO,UAAQ,KAAK,UAAU,KAAK;AAC7E,EAAE;",
6
+ "names": []
7
+ }