@stackmemoryai/stackmemory 0.3.7 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/core/agent-task-manager.js +5 -5
- package/dist/agents/core/agent-task-manager.js.map +2 -2
- package/dist/agents/verifiers/base-verifier.js +2 -2
- package/dist/agents/verifiers/base-verifier.js.map +2 -2
- package/dist/cli/claude-sm.js +0 -11
- package/dist/cli/claude-sm.js.map +2 -2
- package/dist/cli/codex-sm.js +0 -11
- package/dist/cli/codex-sm.js.map +2 -2
- package/dist/cli/commands/chromadb.js +64 -34
- package/dist/cli/commands/chromadb.js.map +2 -2
- package/dist/cli/commands/clear.js +9 -13
- package/dist/cli/commands/clear.js.map +2 -2
- package/dist/cli/commands/config.js +43 -33
- package/dist/cli/commands/config.js.map +2 -2
- package/dist/cli/commands/context.js.map +2 -2
- package/dist/cli/commands/dashboard.js +41 -13
- package/dist/cli/commands/dashboard.js.map +2 -2
- package/dist/cli/commands/gc.js +69 -20
- package/dist/cli/commands/gc.js.map +2 -2
- package/dist/cli/commands/handoff.js.map +2 -2
- package/dist/cli/commands/infinite-storage.js +60 -19
- package/dist/cli/commands/infinite-storage.js.map +2 -2
- package/dist/cli/commands/linear-create.js +36 -8
- package/dist/cli/commands/linear-create.js.map +2 -2
- package/dist/cli/commands/linear-list.js +33 -10
- package/dist/cli/commands/linear-list.js.map +2 -2
- package/dist/cli/commands/linear-migrate.js +17 -4
- package/dist/cli/commands/linear-migrate.js.map +2 -2
- package/dist/cli/commands/linear-test.js +14 -6
- package/dist/cli/commands/linear-test.js.map +2 -2
- package/dist/cli/commands/linear-unified.js +123 -35
- package/dist/cli/commands/linear-unified.js.map +2 -2
- package/dist/cli/commands/linear.js.map +2 -2
- package/dist/cli/commands/monitor.js.map +2 -2
- package/dist/cli/commands/onboard.js +35 -8
- package/dist/cli/commands/onboard.js.map +2 -2
- package/dist/cli/commands/quality.js +2 -7
- package/dist/cli/commands/quality.js.map +2 -2
- package/dist/cli/commands/session.js +23 -6
- package/dist/cli/commands/session.js.map +2 -2
- package/dist/cli/commands/skills.js +72 -27
- package/dist/cli/commands/skills.js.map +2 -2
- package/dist/cli/commands/storage.js +108 -38
- package/dist/cli/commands/storage.js.map +2 -2
- package/dist/cli/commands/tui.js.map +2 -2
- package/dist/cli/commands/webhook.js +57 -18
- package/dist/cli/commands/webhook.js.map +2 -2
- package/dist/cli/commands/workflow.js +8 -15
- package/dist/cli/commands/workflow.js.map +2 -2
- package/dist/cli/commands/worktree.js +34 -13
- package/dist/cli/commands/worktree.js.map +2 -2
- package/dist/cli/index.js +0 -11
- package/dist/cli/index.js.map +2 -2
- package/dist/core/config/types.js.map +1 -1
- package/dist/core/context/auto-context.js +10 -6
- package/dist/core/context/auto-context.js.map +2 -2
- package/dist/core/context/context-bridge.js.map +2 -2
- package/dist/core/context/frame-database.js +13 -3
- package/dist/core/context/frame-database.js.map +2 -2
- package/dist/core/context/frame-digest.js +7 -5
- package/dist/core/context/frame-digest.js.map +2 -2
- package/dist/core/context/frame-manager.js.map +2 -2
- package/dist/core/context/frame-stack.js +16 -5
- package/dist/core/context/frame-stack.js.map +2 -2
- package/dist/core/context/incremental-gc.js +10 -3
- package/dist/core/context/incremental-gc.js.map +2 -2
- package/dist/core/context/index.js.map +1 -1
- package/dist/core/context/permission-manager.js.map +2 -2
- package/dist/core/context/refactored-frame-manager.js +12 -3
- package/dist/core/context/refactored-frame-manager.js.map +2 -2
- package/dist/core/context/shared-context-layer.js +4 -2
- package/dist/core/context/shared-context-layer.js.map +2 -2
- package/dist/core/database/batch-operations.js +112 -86
- package/dist/core/database/batch-operations.js.map +2 -2
- package/dist/core/database/query-cache.js +19 -9
- package/dist/core/database/query-cache.js.map +2 -2
- package/dist/core/database/sqlite-adapter.js +1 -1
- package/dist/core/database/sqlite-adapter.js.map +2 -2
- package/dist/core/digest/enhanced-hybrid-digest.js +8 -2
- package/dist/core/digest/enhanced-hybrid-digest.js.map +2 -2
- package/dist/core/errors/recovery.js +9 -2
- package/dist/core/errors/recovery.js.map +2 -2
- package/dist/core/frame/workflow-templates-stub.js.map +1 -1
- package/dist/core/frame/workflow-templates.js +40 -1
- package/dist/core/frame/workflow-templates.js.map +2 -2
- package/dist/core/monitoring/logger.js +6 -1
- package/dist/core/monitoring/logger.js.map +2 -2
- package/dist/core/monitoring/metrics.js.map +2 -2
- package/dist/core/monitoring/progress-tracker.js.map +2 -2
- package/dist/core/performance/context-cache.js.map +2 -2
- package/dist/core/performance/lazy-context-loader.js +24 -20
- package/dist/core/performance/lazy-context-loader.js.map +2 -2
- package/dist/core/performance/optimized-frame-context.js +27 -12
- package/dist/core/performance/optimized-frame-context.js.map +2 -2
- package/dist/core/performance/performance-benchmark.js +10 -6
- package/dist/core/performance/performance-benchmark.js.map +2 -2
- package/dist/core/performance/performance-profiler.js +51 -14
- package/dist/core/performance/performance-profiler.js.map +2 -2
- package/dist/core/performance/streaming-jsonl-parser.js +5 -1
- package/dist/core/performance/streaming-jsonl-parser.js.map +2 -2
- package/dist/core/projects/project-manager.js +14 -20
- package/dist/core/projects/project-manager.js.map +2 -2
- package/dist/core/retrieval/context-retriever.js.map +1 -1
- package/dist/core/retrieval/llm-context-retrieval.js.map +2 -2
- package/dist/core/session/clear-survival-stub.js +5 -1
- package/dist/core/session/clear-survival-stub.js.map +2 -2
- package/dist/core/session/clear-survival.js +35 -0
- package/dist/core/session/clear-survival.js.map +2 -2
- package/dist/core/session/index.js.map +1 -1
- package/dist/core/session/session-manager.js.map +2 -2
- package/dist/core/storage/chromadb-adapter.js +6 -2
- package/dist/core/storage/chromadb-adapter.js.map +2 -2
- package/dist/core/storage/chromadb-simple.js +17 -5
- package/dist/core/storage/chromadb-simple.js.map +2 -2
- package/dist/core/storage/infinite-storage.js +109 -46
- package/dist/core/storage/infinite-storage.js.map +2 -2
- package/dist/core/storage/railway-optimized-storage.js +48 -22
- package/dist/core/storage/railway-optimized-storage.js.map +2 -2
- package/dist/core/storage/remote-storage.js +41 -23
- package/dist/core/storage/remote-storage.js.map +2 -2
- package/dist/core/trace/cli-trace-wrapper.js +9 -2
- package/dist/core/trace/cli-trace-wrapper.js.map +2 -2
- package/dist/core/trace/db-trace-wrapper.js +96 -68
- package/dist/core/trace/db-trace-wrapper.js.map +2 -2
- package/dist/core/trace/debug-trace.js +25 -8
- package/dist/core/trace/debug-trace.js.map +2 -2
- package/dist/core/trace/index.js +6 -2
- package/dist/core/trace/index.js.map +2 -2
- package/dist/core/trace/linear-api-wrapper.js +10 -5
- package/dist/core/trace/linear-api-wrapper.js.map +2 -2
- package/dist/core/trace/trace-demo.js +14 -10
- package/dist/core/trace/trace-demo.js.map +2 -2
- package/dist/core/trace/trace-detector.js +9 -2
- package/dist/core/trace/trace-detector.js.map +2 -2
- package/dist/core/trace/types.js.map +1 -1
- package/dist/core/utils/compression.js.map +1 -1
- package/dist/core/utils/update-checker.js.map +1 -1
- package/dist/core/worktree/worktree-manager.js +18 -7
- package/dist/core/worktree/worktree-manager.js.map +2 -2
- package/dist/features/analytics/core/analytics-service.js.map +2 -2
- package/dist/features/analytics/queries/metrics-queries.js +1 -1
- package/dist/features/analytics/queries/metrics-queries.js.map +2 -2
- package/dist/features/tasks/pebbles-task-store.js.map +1 -1
- package/dist/features/tui/components/analytics-panel.js +36 -15
- package/dist/features/tui/components/analytics-panel.js.map +2 -2
- package/dist/features/tui/components/pr-tracker.js +19 -7
- package/dist/features/tui/components/pr-tracker.js.map +2 -2
- package/dist/features/tui/components/session-monitor.js +22 -9
- package/dist/features/tui/components/session-monitor.js.map +2 -2
- package/dist/features/tui/components/subagent-fleet.js +20 -13
- package/dist/features/tui/components/subagent-fleet.js.map +2 -2
- package/dist/features/tui/components/task-board.js +26 -10
- package/dist/features/tui/components/task-board.js.map +2 -2
- package/dist/features/tui/index.js.map +2 -2
- package/dist/features/tui/services/data-service.js +6 -2
- package/dist/features/tui/services/data-service.js.map +2 -2
- package/dist/features/tui/services/linear-task-reader.js +3 -1
- package/dist/features/tui/services/linear-task-reader.js.map +2 -2
- package/dist/features/tui/services/websocket-client.js +3 -1
- package/dist/features/tui/services/websocket-client.js.map +2 -2
- package/dist/features/tui/terminal-compat.js +6 -2
- package/dist/features/tui/terminal-compat.js.map +2 -2
- package/dist/features/web/client/stores/task-store.js.map +2 -2
- package/dist/features/web/server/index.js +18 -10
- package/dist/features/web/server/index.js.map +2 -2
- package/dist/integrations/linear/sync-service.js +12 -13
- package/dist/integrations/linear/sync-service.js.map +2 -2
- package/dist/integrations/linear/sync.js +174 -12
- package/dist/integrations/linear/sync.js.map +2 -2
- package/dist/integrations/linear/unified-sync.js +1 -1
- package/dist/integrations/linear/unified-sync.js.map +1 -1
- package/dist/integrations/linear/webhook-server.js +15 -16
- package/dist/integrations/linear/webhook-server.js.map +2 -2
- package/dist/mcp/stackmemory-mcp-server.js +0 -11
- package/dist/mcp/stackmemory-mcp-server.js.map +2 -2
- package/dist/servers/production/auth-middleware.js.map +2 -2
- package/dist/servers/railway/index.js.map +2 -2
- package/dist/services/config-service.js +6 -7
- package/dist/services/config-service.js.map +2 -2
- package/dist/services/context-service.js +11 -12
- package/dist/services/context-service.js.map +2 -2
- package/dist/skills/claude-skills.js +4 -2
- package/dist/skills/claude-skills.js.map +2 -2
- package/dist/skills/dashboard-launcher.js.map +2 -2
- package/dist/skills/repo-ingestion-skill.js.map +2 -2
- package/dist/utils/env.js +46 -0
- package/dist/utils/env.js.map +7 -0
- package/dist/utils/logger.js +0 -11
- package/dist/utils/logger.js.map +2 -2
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/cli/commands/infinite-storage.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * CLI commands for Infinite Storage System management\n */\n\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport Table from 'cli-table3';\nimport { InfiniteStorageSystem, StorageConfig } from '../../core/storage/infinite-storage.js';\nimport { FrameManager } from '../../core/context/frame-manager.js';\nimport { Logger } from '../../core/monitoring/logger.js';\nimport dotenv from 'dotenv';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\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 __dirname = path.dirname(fileURLToPath(import.meta.url));\n\n// Load environment variables\ndotenv.config({ \n path: path.join(__dirname, '../../../.env'),\n override: true,\n silent: true\n});\n\nconst logger = new Logger('InfiniteStorage-CLI');\n\nexport function createInfiniteStorageCommand(): Command {\n const storage = new Command('infinite-storage')\n .description('Manage infinite storage system with tiered storage')\n .alias('storage');\n\n // Initialize storage system\n storage\n .command('init')\n .description('Initialize infinite storage system')\n .option('--redis-url <url>', 'Redis connection URL')\n .option('--timeseries-url <url>', 'TimeSeries DB connection URL')\n .option('--s3-bucket <bucket>', 'S3 bucket name')\n .option('--s3-region <region>', 'S3 region', 'us-east-1')\n .action(async (options) => {\n const spinner = ora('Initializing infinite storage...').start();\n\n try {\n const config: StorageConfig = {\n redis: {\n url: options.redisUrl || process.env['REDIS_URL'] || 'redis://localhost:6379',\n ttlSeconds: 3600,\n maxMemoryMB: parseInt(process.env['REDIS_MAX_MEMORY_MB'] || '512'),\n },\n timeseries: {\n connectionString: options.timeseriesUrl || process.env['TIMESERIES_URL'] || '',\n retentionDays: 30,\n },\n s3: {\n bucket: options.s3Bucket || process.env['S3_BUCKET'] || '',\n region: options.s3Region || process.env['AWS_REGION'] || 'us-east-1',\n accessKeyId: process.env['AWS_ACCESS_KEY_ID'],\n secretAccessKey: process.env['AWS_SECRET_ACCESS_KEY'],\n },\n tiers: [],\n };\n\n const storage = new InfiniteStorageSystem(config);\n await storage.initialize();\n\n spinner.succeed('Infinite storage initialized');\n \n console.log(chalk.green('\\n\u2705 Storage Tiers Configured:'));\n console.log(' Hot (Redis): < 1 hour, 5ms latency');\n console.log(' Warm (TimeSeries): 1h - 7 days, 50ms latency');\n console.log(' Cold (S3): 7 - 30 days, 100ms latency');\n console.log(' Archive (Glacier): > 30 days, 1h latency');\n \n // Save config to env\n const envPath = path.join(__dirname, '../../../.env');\n const updates: string[] = [];\n \n if (!process.env['REDIS_URL'] && options.redisUrl) {\n updates.push(`REDIS_URL=${options.redisUrl}`);\n }\n if (!process.env['TIMESERIES_URL'] && options.timeseriesUrl) {\n updates.push(`TIMESERIES_URL=${options.timeseriesUrl}`);\n }\n if (!process.env['S3_BUCKET'] && options.s3Bucket) {\n updates.push(`S3_BUCKET=${options.s3Bucket}`);\n }\n \n if (updates.length > 0) {\n const fs = await import('fs');\n fs.appendFileSync(envPath, '\\n# Infinite Storage Configuration\\n' + updates.join('\\n') + '\\n');\n }\n } catch (error: unknown) {\n spinner.fail('Failed to initialize storage');\n logger.error('Initialization error', error);\n console.error(chalk.red(error instanceof Error ? error.message : 'Unknown error'));\n }\n });\n\n // Store frames\n storage\n .command('store')\n .description('Store current frames in infinite storage')\n .option('--project <name>', 'Project name')\n .option('--user <id>', 'User ID')\n .action(async (options) => {\n const spinner = ora('Storing frames...').start();\n\n try {\n const config = getStorageConfig();\n const storage = new InfiniteStorageSystem(config);\n await storage.initialize();\n\n const frameManager = new FrameManager();\n const frames = frameManager.getAllFrames();\n const userId = options.user || process.env['USER'] || 'default';\n\n for (const frame of frames) {\n await storage.storeFrame(frame, userId);\n }\n\n spinner.succeed(`Stored ${frames.length} frames`);\n } catch (error: unknown) {\n spinner.fail('Failed to store frames');\n logger.error('Store error', error);\n console.error(chalk.red(error instanceof Error ? error.message : 'Unknown error'));\n }\n });\n\n // Retrieve frame\n storage\n .command('retrieve <frameId>')\n .description('Retrieve a frame from storage')\n .option('--user <id>', 'User ID')\n .action(async (frameId, options) => {\n const spinner = ora('Retrieving frame...').start();\n\n try {\n const config = getStorageConfig();\n const storage = new InfiniteStorageSystem(config);\n await storage.initialize();\n\n const userId = options.user || process.env['USER'] || 'default';\n const frame = await storage.retrieveFrame(frameId, userId);\n\n spinner.stop();\n\n if (frame) {\n console.log(chalk.green('\\n\u2705 Frame Retrieved:'));\n console.log(JSON.stringify(frame, null, 2));\n } else {\n console.log(chalk.yellow('Frame not found'));\n }\n } catch (error: unknown) {\n spinner.fail('Failed to retrieve frame');\n logger.error('Retrieve error', error);\n console.error(chalk.red(error instanceof Error ? error.message : 'Unknown error'));\n }\n });\n\n // Show metrics\n storage\n .command('metrics')\n .description('Show storage system metrics')\n .action(async () => {\n const spinner = ora('Fetching metrics...').start();\n\n try {\n const config = getStorageConfig();\n const storage = new InfiniteStorageSystem(config);\n await storage.initialize();\n\n const metrics = await storage.getMetrics();\n\n spinner.stop();\n\n console.log(chalk.cyan('\\n\uD83D\uDCCA Infinite Storage Metrics\\n'));\n \n const table = new Table({\n head: ['Metric', 'Value'],\n colWidths: [30, 40],\n });\n\n table.push(\n ['Total Objects', metrics.totalObjects.toString()],\n ['Storage Size', formatBytes(metrics.storageBytes)],\n ['Avg Latency', `${metrics.avgLatencyMs.toFixed(2)}ms`],\n ['P50 Latency', `${metrics.p50LatencyMs}ms`],\n ['P99 Latency', `${metrics.p99LatencyMs}ms`],\n );\n\n console.log(table.toString());\n\n if (Object.keys(metrics.tierDistribution).length > 0) {\n console.log('\\nTier Distribution:');\n for (const [tier, count] of Object.entries(metrics.tierDistribution)) {\n const percentage = ((count / metrics.totalObjects) * 100).toFixed(1);\n console.log(` ${tier}: ${count} objects (${percentage}%)`);\n }\n }\n\n // Check if meeting STA-287 targets\n console.log(chalk.cyan('\\n\uD83C\uDFAF STA-287 Performance Targets:'));\n const p50Target = metrics.p50LatencyMs <= 50;\n const p99Target = metrics.p99LatencyMs <= 500;\n \n console.log(` P50 \u2264 50ms: ${p50Target ? chalk.green('\u2705 PASS') : chalk.red('\u274C FAIL')} (${metrics.p50LatencyMs}ms)`);\n console.log(` P99 \u2264 500ms: ${p99Target ? chalk.green('\u2705 PASS') : chalk.red('\u274C FAIL')} (${metrics.p99LatencyMs}ms)`);\n } catch (error: unknown) {\n spinner.fail('Failed to get metrics');\n logger.error('Metrics error', error);\n console.error(chalk.red(error instanceof Error ? error.message : 'Unknown error'));\n }\n });\n\n // Migrate data\n storage\n .command('migrate')\n .description('Manually trigger tier migration')\n .action(async () => {\n const spinner = ora('Running migration...').start();\n\n try {\n const config = getStorageConfig();\n const storage = new InfiniteStorageSystem(config);\n await storage.initialize();\n\n // Trigger migration (this would normally run automatically)\n // @ts-ignore - accessing private method for manual trigger\n await storage.migrateAgedData();\n\n spinner.succeed('Migration completed');\n } catch (error: unknown) {\n spinner.fail('Migration failed');\n logger.error('Migration error', error);\n console.error(chalk.red(error instanceof Error ? error.message : 'Unknown error'));\n }\n });\n\n // Status command\n storage\n .command('status')\n .description('Check storage system status')\n .action(async () => {\n const spinner = ora('Checking status...').start();\n\n try {\n const config = getStorageConfig();\n \n spinner.stop();\n \n console.log(chalk.cyan('\\n\uD83D\uDCE6 Storage System Status\\n'));\n \n // Check Redis\n if (config.redis?.url) {\n try {\n const { createClient } = await import('redis');\n const client = createClient({ url: config.redis.url });\n await client.connect();\n await client.ping();\n await client.quit();\n console.log('Redis (Hot Tier): ' + chalk.green('\u2705 Connected'));\n } catch {\n console.log('Redis (Hot Tier): ' + chalk.red('\u274C Not connected'));\n }\n } else {\n console.log('Redis (Hot Tier): ' + chalk.yellow('\u26A0\uFE0F Not configured'));\n }\n\n // Check TimeSeries DB\n if (config.timeseries?.connectionString) {\n try {\n const { Pool } = await import('pg');\n const pool = new Pool({ connectionString: config.timeseries.connectionString });\n await pool.query('SELECT 1');\n await pool.end();\n console.log('TimeSeries DB (Warm Tier): ' + chalk.green('\u2705 Connected'));\n } catch {\n console.log('TimeSeries DB (Warm Tier): ' + chalk.red('\u274C Not connected'));\n }\n } else {\n console.log('TimeSeries DB (Warm Tier): ' + chalk.yellow('\u26A0\uFE0F Not configured'));\n }\n\n // Check S3\n if (config.s3?.bucket) {\n console.log(`S3 (Cold/Archive Tier): ${chalk.green('\u2705')} Bucket: ${config.s3.bucket}`);\n } else {\n console.log('S3 (Cold/Archive Tier): ' + chalk.yellow('\u26A0\uFE0F Not configured'));\n }\n\n console.log('\\n' + chalk.gray('Configure missing tiers with: stackmemory infinite-storage init'));\n } catch (error: unknown) {\n spinner.fail('Failed to check status');\n logger.error('Status error', error);\n console.error(chalk.red(error instanceof Error ? error.message : 'Unknown error'));\n }\n });\n\n return storage;\n}\n\nfunction getStorageConfig(): StorageConfig {\n return {\n redis: {\n url: process.env['REDIS_URL'] || 'redis://localhost:6379',\n ttlSeconds: parseInt(process.env['REDIS_TTL'] || '3600'),\n maxMemoryMB: parseInt(process.env['REDIS_MAX_MEMORY_MB'] || '512'),\n },\n timeseries: {\n connectionString: process.env['TIMESERIES_URL'] || '',\n retentionDays: parseInt(process.env['TIMESERIES_RETENTION_DAYS'] || '30'),\n },\n s3: {\n bucket: process.env['S3_BUCKET'] || '',\n region: process.env['AWS_REGION'] || 'us-east-1',\n accessKeyId: process.env['AWS_ACCESS_KEY_ID'],\n secretAccessKey: process.env['AWS_SECRET_ACCESS_KEY'],\n },\n tiers: [],\n };\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) return '0 Bytes';\n const k = 1024;\n const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\n}"],
|
|
5
|
-
"mappings": "AAIA,SAAS,eAAe;AACxB,OAAO,WAAW;AAClB,OAAO,SAAS;AAChB,OAAO,WAAW;AAClB,
|
|
4
|
+
"sourcesContent": ["/**\n * CLI commands for Infinite Storage System management\n */\n\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport Table from 'cli-table3';\nimport {\n InfiniteStorageSystem,\n StorageConfig,\n} from '../../core/storage/infinite-storage.js';\nimport { FrameManager } from '../../core/context/frame-manager.js';\nimport { Logger } from '../../core/monitoring/logger.js';\nimport dotenv from 'dotenv';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\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 __dirname = path.dirname(fileURLToPath(import.meta.url));\n\n// Load environment variables\ndotenv.config({\n path: path.join(__dirname, '../../../.env'),\n override: true,\n silent: true,\n});\n\nconst logger = new Logger('InfiniteStorage-CLI');\n\nexport function createInfiniteStorageCommand(): Command {\n const storage = new Command('infinite-storage')\n .description('Manage infinite storage system with tiered storage')\n .alias('storage');\n\n // Initialize storage system\n storage\n .command('init')\n .description('Initialize infinite storage system')\n .option('--redis-url <url>', 'Redis connection URL')\n .option('--timeseries-url <url>', 'TimeSeries DB connection URL')\n .option('--s3-bucket <bucket>', 'S3 bucket name')\n .option('--s3-region <region>', 'S3 region', 'us-east-1')\n .action(async (options) => {\n const spinner = ora('Initializing infinite storage...').start();\n\n try {\n const config: StorageConfig = {\n redis: {\n url:\n options.redisUrl ||\n process.env['REDIS_URL'] ||\n 'redis://localhost:6379',\n ttlSeconds: 3600,\n maxMemoryMB: parseInt(process.env['REDIS_MAX_MEMORY_MB'] || '512'),\n },\n timeseries: {\n connectionString:\n options.timeseriesUrl || process.env['TIMESERIES_URL'] || '',\n retentionDays: 30,\n },\n s3: {\n bucket: options.s3Bucket || process.env['S3_BUCKET'] || '',\n region:\n options.s3Region || process.env['AWS_REGION'] || 'us-east-1',\n accessKeyId: process.env['AWS_ACCESS_KEY_ID'],\n secretAccessKey: process.env['AWS_SECRET_ACCESS_KEY'],\n },\n tiers: [],\n };\n\n const storage = new InfiniteStorageSystem(config);\n await storage.initialize();\n\n spinner.succeed('Infinite storage initialized');\n\n console.log(chalk.green('\\n\u2705 Storage Tiers Configured:'));\n console.log(' Hot (Redis): < 1 hour, 5ms latency');\n console.log(' Warm (TimeSeries): 1h - 7 days, 50ms latency');\n console.log(' Cold (S3): 7 - 30 days, 100ms latency');\n console.log(' Archive (Glacier): > 30 days, 1h latency');\n\n // Save config to env\n const envPath = path.join(__dirname, '../../../.env');\n const updates: string[] = [];\n\n if (!process.env['REDIS_URL'] && options.redisUrl) {\n updates.push(`REDIS_URL=${options.redisUrl}`);\n }\n if (!process.env['TIMESERIES_URL'] && options.timeseriesUrl) {\n updates.push(`TIMESERIES_URL=${options.timeseriesUrl}`);\n }\n if (!process.env['S3_BUCKET'] && options.s3Bucket) {\n updates.push(`S3_BUCKET=${options.s3Bucket}`);\n }\n\n if (updates.length > 0) {\n const fs = await import('fs');\n fs.appendFileSync(\n envPath,\n '\\n# Infinite Storage Configuration\\n' + updates.join('\\n') + '\\n'\n );\n }\n } catch (error: unknown) {\n spinner.fail('Failed to initialize storage');\n logger.error('Initialization error', error);\n console.error(\n chalk.red(error instanceof Error ? error.message : 'Unknown error')\n );\n }\n });\n\n // Store frames\n storage\n .command('store')\n .description('Store current frames in infinite storage')\n .option('--project <name>', 'Project name')\n .option('--user <id>', 'User ID')\n .action(async (options) => {\n const spinner = ora('Storing frames...').start();\n\n try {\n const config = getStorageConfig();\n const storage = new InfiniteStorageSystem(config);\n await storage.initialize();\n\n const frameManager = new FrameManager();\n const frames = frameManager.getAllFrames();\n const userId = options.user || process.env['USER'] || 'default';\n\n for (const frame of frames) {\n await storage.storeFrame(frame, userId);\n }\n\n spinner.succeed(`Stored ${frames.length} frames`);\n } catch (error: unknown) {\n spinner.fail('Failed to store frames');\n logger.error('Store error', error);\n console.error(\n chalk.red(error instanceof Error ? error.message : 'Unknown error')\n );\n }\n });\n\n // Retrieve frame\n storage\n .command('retrieve <frameId>')\n .description('Retrieve a frame from storage')\n .option('--user <id>', 'User ID')\n .action(async (frameId, options) => {\n const spinner = ora('Retrieving frame...').start();\n\n try {\n const config = getStorageConfig();\n const storage = new InfiniteStorageSystem(config);\n await storage.initialize();\n\n const userId = options.user || process.env['USER'] || 'default';\n const frame = await storage.retrieveFrame(frameId, userId);\n\n spinner.stop();\n\n if (frame) {\n console.log(chalk.green('\\n\u2705 Frame Retrieved:'));\n console.log(JSON.stringify(frame, null, 2));\n } else {\n console.log(chalk.yellow('Frame not found'));\n }\n } catch (error: unknown) {\n spinner.fail('Failed to retrieve frame');\n logger.error('Retrieve error', error);\n console.error(\n chalk.red(error instanceof Error ? error.message : 'Unknown error')\n );\n }\n });\n\n // Show metrics\n storage\n .command('metrics')\n .description('Show storage system metrics')\n .action(async () => {\n const spinner = ora('Fetching metrics...').start();\n\n try {\n const config = getStorageConfig();\n const storage = new InfiniteStorageSystem(config);\n await storage.initialize();\n\n const metrics = await storage.getMetrics();\n\n spinner.stop();\n\n console.log(chalk.cyan('\\n\uD83D\uDCCA Infinite Storage Metrics\\n'));\n\n const table = new Table({\n head: ['Metric', 'Value'],\n colWidths: [30, 40],\n });\n\n table.push(\n ['Total Objects', metrics.totalObjects.toString()],\n ['Storage Size', formatBytes(metrics.storageBytes)],\n ['Avg Latency', `${metrics.avgLatencyMs.toFixed(2)}ms`],\n ['P50 Latency', `${metrics.p50LatencyMs}ms`],\n ['P99 Latency', `${metrics.p99LatencyMs}ms`]\n );\n\n console.log(table.toString());\n\n if (Object.keys(metrics.tierDistribution).length > 0) {\n console.log('\\nTier Distribution:');\n for (const [tier, count] of Object.entries(\n metrics.tierDistribution\n )) {\n const percentage = ((count / metrics.totalObjects) * 100).toFixed(\n 1\n );\n console.log(` ${tier}: ${count} objects (${percentage}%)`);\n }\n }\n\n // Check if meeting STA-287 targets\n console.log(chalk.cyan('\\n\uD83C\uDFAF STA-287 Performance Targets:'));\n const p50Target = metrics.p50LatencyMs <= 50;\n const p99Target = metrics.p99LatencyMs <= 500;\n\n console.log(\n ` P50 \u2264 50ms: ${p50Target ? chalk.green('\u2705 PASS') : chalk.red('\u274C FAIL')} (${metrics.p50LatencyMs}ms)`\n );\n console.log(\n ` P99 \u2264 500ms: ${p99Target ? chalk.green('\u2705 PASS') : chalk.red('\u274C FAIL')} (${metrics.p99LatencyMs}ms)`\n );\n } catch (error: unknown) {\n spinner.fail('Failed to get metrics');\n logger.error('Metrics error', error);\n console.error(\n chalk.red(error instanceof Error ? error.message : 'Unknown error')\n );\n }\n });\n\n // Migrate data\n storage\n .command('migrate')\n .description('Manually trigger tier migration')\n .action(async () => {\n const spinner = ora('Running migration...').start();\n\n try {\n const config = getStorageConfig();\n const storage = new InfiniteStorageSystem(config);\n await storage.initialize();\n\n // Trigger migration (this would normally run automatically)\n // @ts-ignore - accessing private method for manual trigger\n await storage.migrateAgedData();\n\n spinner.succeed('Migration completed');\n } catch (error: unknown) {\n spinner.fail('Migration failed');\n logger.error('Migration error', error);\n console.error(\n chalk.red(error instanceof Error ? error.message : 'Unknown error')\n );\n }\n });\n\n // Status command\n storage\n .command('status')\n .description('Check storage system status')\n .action(async () => {\n const spinner = ora('Checking status...').start();\n\n try {\n const config = getStorageConfig();\n\n spinner.stop();\n\n console.log(chalk.cyan('\\n\uD83D\uDCE6 Storage System Status\\n'));\n\n // Check Redis\n if (config.redis?.url) {\n try {\n const { createClient } = await import('redis');\n const client = createClient({ url: config.redis.url });\n await client.connect();\n await client.ping();\n await client.quit();\n console.log('Redis (Hot Tier): ' + chalk.green('\u2705 Connected'));\n } catch {\n console.log('Redis (Hot Tier): ' + chalk.red('\u274C Not connected'));\n }\n } else {\n console.log('Redis (Hot Tier): ' + chalk.yellow('\u26A0\uFE0F Not configured'));\n }\n\n // Check TimeSeries DB\n if (config.timeseries?.connectionString) {\n try {\n const { Pool } = await import('pg');\n const pool = new Pool({\n connectionString: config.timeseries.connectionString,\n });\n await pool.query('SELECT 1');\n await pool.end();\n console.log(\n 'TimeSeries DB (Warm Tier): ' + chalk.green('\u2705 Connected')\n );\n } catch {\n console.log(\n 'TimeSeries DB (Warm Tier): ' + chalk.red('\u274C Not connected')\n );\n }\n } else {\n console.log(\n 'TimeSeries DB (Warm Tier): ' + chalk.yellow('\u26A0\uFE0F Not configured')\n );\n }\n\n // Check S3\n if (config.s3?.bucket) {\n console.log(\n `S3 (Cold/Archive Tier): ${chalk.green('\u2705')} Bucket: ${config.s3.bucket}`\n );\n } else {\n console.log(\n 'S3 (Cold/Archive Tier): ' + chalk.yellow('\u26A0\uFE0F Not configured')\n );\n }\n\n console.log(\n '\\n' +\n chalk.gray(\n 'Configure missing tiers with: stackmemory infinite-storage init'\n )\n );\n } catch (error: unknown) {\n spinner.fail('Failed to check status');\n logger.error('Status error', error);\n console.error(\n chalk.red(error instanceof Error ? error.message : 'Unknown error')\n );\n }\n });\n\n return storage;\n}\n\nfunction getStorageConfig(): StorageConfig {\n return {\n redis: {\n url: process.env['REDIS_URL'] || 'redis://localhost:6379',\n ttlSeconds: parseInt(process.env['REDIS_TTL'] || '3600'),\n maxMemoryMB: parseInt(process.env['REDIS_MAX_MEMORY_MB'] || '512'),\n },\n timeseries: {\n connectionString: process.env['TIMESERIES_URL'] || '',\n retentionDays: parseInt(process.env['TIMESERIES_RETENTION_DAYS'] || '30'),\n },\n s3: {\n bucket: process.env['S3_BUCKET'] || '',\n region: process.env['AWS_REGION'] || 'us-east-1',\n accessKeyId: process.env['AWS_ACCESS_KEY_ID'],\n secretAccessKey: process.env['AWS_SECRET_ACCESS_KEY'],\n },\n tiers: [],\n };\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) return '0 Bytes';\n const k = 1024;\n const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["storage"]
|
|
7
7
|
}
|
|
@@ -12,15 +12,29 @@ function getOptionalEnv(key) {
|
|
|
12
12
|
return process.env[key];
|
|
13
13
|
}
|
|
14
14
|
function registerLinearCreateCommand(parent) {
|
|
15
|
-
parent.command("linear:create").description("Create a new Linear task in the correct project").option("--api-key <key>", "Linear API key for target workspace").option("--title <title>", "Task title (required)").option("--description <desc>", "Task description").option(
|
|
15
|
+
parent.command("linear:create").description("Create a new Linear task in the correct project").option("--api-key <key>", "Linear API key for target workspace").option("--title <title>", "Task title (required)").option("--description <desc>", "Task description").option(
|
|
16
|
+
"--priority <level>",
|
|
17
|
+
"Priority: urgent(1), high(2), medium(3), low(4)",
|
|
18
|
+
"3"
|
|
19
|
+
).option(
|
|
20
|
+
"--state <state>",
|
|
21
|
+
"Initial state: backlog, todo, started",
|
|
22
|
+
"backlog"
|
|
23
|
+
).action(async (options) => {
|
|
16
24
|
try {
|
|
17
25
|
const apiKey = options.apiKey || process.env["LINEAR_NEW_API_KEY"];
|
|
18
26
|
if (!apiKey) {
|
|
19
|
-
console.error(
|
|
27
|
+
console.error(
|
|
28
|
+
chalk.red(
|
|
29
|
+
"\u274C API key required. Use --api-key or set LINEAR_NEW_API_KEY"
|
|
30
|
+
)
|
|
31
|
+
);
|
|
20
32
|
return;
|
|
21
33
|
}
|
|
22
34
|
if (!options.title) {
|
|
23
|
-
console.error(
|
|
35
|
+
console.error(
|
|
36
|
+
chalk.red('\u274C Task title required. Use --title "Your task title"')
|
|
37
|
+
);
|
|
24
38
|
return;
|
|
25
39
|
}
|
|
26
40
|
const client = new LinearRestClient(apiKey);
|
|
@@ -68,14 +82,21 @@ function registerLinearCreateCommand(parent) {
|
|
|
68
82
|
console.log(chalk.gray(` Description: ${options.description}`));
|
|
69
83
|
}
|
|
70
84
|
} catch (error) {
|
|
71
|
-
console.error(
|
|
85
|
+
console.error(
|
|
86
|
+
chalk.red("\u274C Task creation failed:"),
|
|
87
|
+
error.message
|
|
88
|
+
);
|
|
72
89
|
}
|
|
73
90
|
});
|
|
74
91
|
parent.command("linear:quick").description("Quick task creation with prompts").option("--api-key <key>", "Linear API key for target workspace").action(async (options) => {
|
|
75
92
|
try {
|
|
76
93
|
const apiKey = options.apiKey || process.env["LINEAR_NEW_API_KEY"];
|
|
77
94
|
if (!apiKey) {
|
|
78
|
-
console.error(
|
|
95
|
+
console.error(
|
|
96
|
+
chalk.red(
|
|
97
|
+
"\u274C API key required. Use --api-key or set LINEAR_NEW_API_KEY"
|
|
98
|
+
)
|
|
99
|
+
);
|
|
79
100
|
return;
|
|
80
101
|
}
|
|
81
102
|
const readline = await import("readline");
|
|
@@ -96,8 +117,12 @@ function registerLinearCreateCommand(parent) {
|
|
|
96
117
|
rl.close();
|
|
97
118
|
return;
|
|
98
119
|
}
|
|
99
|
-
const description = await question(
|
|
100
|
-
|
|
120
|
+
const description = await question(
|
|
121
|
+
chalk.yellow("Description (optional): ")
|
|
122
|
+
);
|
|
123
|
+
const priorityInput = await question(
|
|
124
|
+
chalk.yellow("Priority (1=urgent, 2=high, 3=medium, 4=low) [3]: ")
|
|
125
|
+
);
|
|
101
126
|
const priority = priorityInput.trim() || "3";
|
|
102
127
|
rl.close();
|
|
103
128
|
console.log(chalk.yellow("\n\u{1F504} Creating task..."));
|
|
@@ -133,7 +158,10 @@ function registerLinearCreateCommand(parent) {
|
|
|
133
158
|
console.log(chalk.blue(`\u{1F4CB} ${task.identifier}: ${task.title}`));
|
|
134
159
|
console.log(chalk.gray(` URL: ${task.url}`));
|
|
135
160
|
} catch (error) {
|
|
136
|
-
console.error(
|
|
161
|
+
console.error(
|
|
162
|
+
chalk.red("\u274C Task creation failed:"),
|
|
163
|
+
error.message
|
|
164
|
+
);
|
|
137
165
|
}
|
|
138
166
|
});
|
|
139
167
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/cli/commands/linear-create.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Linear Task Creation Command\n */\n\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport { LinearRestClient } from '../../integrations/linear/rest-client.js';\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\
|
|
5
|
-
"mappings": "AAKA,OAAO,WAAW;AAClB,SAAS,wBAAwB;AAEjC,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;
|
|
4
|
+
"sourcesContent": ["/**\n * Linear Task Creation Command\n */\n\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport { LinearRestClient } from '../../integrations/linear/rest-client.js';\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 function registerLinearCreateCommand(parent: Command) {\n parent\n .command('linear:create')\n .description('Create a new Linear task in the correct project')\n .option('--api-key <key>', 'Linear API key for target workspace')\n .option('--title <title>', 'Task title (required)')\n .option('--description <desc>', 'Task description')\n .option(\n '--priority <level>',\n 'Priority: urgent(1), high(2), medium(3), low(4)',\n '3'\n )\n .option(\n '--state <state>',\n 'Initial state: backlog, todo, started',\n 'backlog'\n )\n .action(async (options) => {\n try {\n const apiKey = options.apiKey || process.env['LINEAR_NEW_API_KEY'];\n\n if (!apiKey) {\n console.error(\n chalk.red(\n '\u274C API key required. Use --api-key or set LINEAR_NEW_API_KEY'\n )\n );\n return;\n }\n\n if (!options.title) {\n console.error(\n chalk.red('\u274C Task title required. Use --title \"Your task title\"')\n );\n return;\n }\n\n const client = new LinearRestClient(apiKey);\n\n console.log(chalk.yellow('\uD83D\uDD04 Creating new Linear task...'));\n\n // Get team info\n const team = await client.getTeam();\n console.log(chalk.cyan(`\uD83C\uDFAF Target team: ${team.name} (${team.key})`));\n\n // Create the task\n const createQuery = `\n mutation CreateIssue($input: IssueCreateInput!) {\n issueCreate(input: $input) {\n success\n issue {\n id\n identifier\n title\n description\n state {\n id\n name\n type\n }\n priority\n url\n createdAt\n }\n }\n }\n `;\n\n const taskInput = {\n title: options.title,\n description: options.description || '',\n teamId: team.id,\n priority: parseInt(options.priority),\n };\n\n const response = await client.makeRequest<{\n data: {\n issueCreate: {\n success: boolean;\n issue: any;\n };\n };\n }>(createQuery, { input: taskInput });\n\n if (!response.data?.issueCreate?.success) {\n throw new Error('Failed to create task in Linear');\n }\n\n const task = response.data.issueCreate.issue;\n\n console.log(chalk.green('\\n\u2705 Task created successfully!'));\n console.log(chalk.blue(`\uD83D\uDCCB ${task.identifier}: ${task.title}`));\n console.log(chalk.gray(` State: ${task.state.name}`));\n console.log(chalk.gray(` Priority: ${task.priority}`));\n console.log(chalk.gray(` URL: ${task.url}`));\n\n if (options.description) {\n console.log(chalk.gray(` Description: ${options.description}`));\n }\n } catch (error: unknown) {\n console.error(\n chalk.red('\u274C Task creation failed:'),\n (error as Error).message\n );\n }\n });\n\n parent\n .command('linear:quick')\n .description('Quick task creation with prompts')\n .option('--api-key <key>', 'Linear API key for target workspace')\n .action(async (options) => {\n try {\n const apiKey = options.apiKey || process.env['LINEAR_NEW_API_KEY'];\n\n if (!apiKey) {\n console.error(\n chalk.red(\n '\u274C API key required. Use --api-key or set LINEAR_NEW_API_KEY'\n )\n );\n return;\n }\n\n const readline = await import('readline');\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n const question = (prompt: string): Promise<string> => {\n return new Promise((resolve) => {\n rl.question(prompt, resolve);\n });\n };\n\n console.log(chalk.blue('\uD83D\uDCDD Quick Linear Task Creation'));\n console.log(chalk.gray('Press Ctrl+C to cancel at any time\\n'));\n\n const title = await question(chalk.yellow('Task title: '));\n if (!title.trim()) {\n console.log(chalk.red('\u274C Title is required'));\n rl.close();\n return;\n }\n\n const description = await question(\n chalk.yellow('Description (optional): ')\n );\n const priorityInput = await question(\n chalk.yellow('Priority (1=urgent, 2=high, 3=medium, 4=low) [3]: ')\n );\n const priority = priorityInput.trim() || '3';\n\n rl.close();\n\n console.log(chalk.yellow('\\n\uD83D\uDD04 Creating task...'));\n\n const client = new LinearRestClient(apiKey);\n const team = await client.getTeam();\n\n const createQuery = `\n mutation CreateIssue($input: IssueCreateInput!) {\n issueCreate(input: $input) {\n success\n issue {\n id\n identifier\n title\n state { name }\n priority\n url\n }\n }\n }\n `;\n\n const taskInput = {\n title: title.trim(),\n description: description.trim() || undefined,\n teamId: team.id,\n priority: parseInt(priority),\n };\n\n const response = await client.makeRequest<{\n data: {\n issueCreate: {\n success: boolean;\n issue: any;\n };\n };\n }>(createQuery, { input: taskInput });\n\n if (!response.data?.issueCreate?.success) {\n throw new Error('Failed to create task in Linear');\n }\n\n const task = response.data.issueCreate.issue;\n\n console.log(chalk.green('\\n\u2705 Task created successfully!'));\n console.log(chalk.blue(`\uD83D\uDCCB ${task.identifier}: ${task.title}`));\n console.log(chalk.gray(` URL: ${task.url}`));\n } catch (error: unknown) {\n console.error(\n chalk.red('\u274C Task creation failed:'),\n (error as Error).message\n );\n }\n });\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -12,11 +12,16 @@ function getOptionalEnv(key) {
|
|
|
12
12
|
return process.env[key];
|
|
13
13
|
}
|
|
14
14
|
function registerLinearListCommand(parent) {
|
|
15
|
-
parent.command("linear:list").alias("linear:ls").description("List Linear tasks (fast, memory-cached)").option("--limit <n>", "Number of tasks to show", "20").option(
|
|
15
|
+
parent.command("linear:list").alias("linear:ls").description("List Linear tasks (fast, memory-cached)").option("--limit <n>", "Number of tasks to show", "20").option(
|
|
16
|
+
"--status <status>",
|
|
17
|
+
"Filter by status (backlog, started, completed, etc.)"
|
|
18
|
+
).option("--my", "Show only tasks assigned to me").option("--cache", "Show cache stats only").option("--refresh", "Force refresh cache").option("--count", "Show count by status only").action(async (options) => {
|
|
16
19
|
try {
|
|
17
20
|
const apiKey = process.env["LINEAR_API_KEY"];
|
|
18
21
|
if (!apiKey) {
|
|
19
|
-
console.log(
|
|
22
|
+
console.log(
|
|
23
|
+
chalk.yellow("\u26A0 Set LINEAR_API_KEY environment variable")
|
|
24
|
+
);
|
|
20
25
|
return;
|
|
21
26
|
}
|
|
22
27
|
const restClient = new LinearRestClient(apiKey);
|
|
@@ -26,7 +31,9 @@ function registerLinearListCommand(parent) {
|
|
|
26
31
|
console.log(` Size: ${stats.size} tasks`);
|
|
27
32
|
console.log(` Age: ${Math.round(stats.age / 1e3)}s`);
|
|
28
33
|
console.log(` Fresh: ${stats.fresh ? "yes" : "no"}`);
|
|
29
|
-
console.log(
|
|
34
|
+
console.log(
|
|
35
|
+
` Last sync: ${new Date(stats.lastSync).toLocaleString()}`
|
|
36
|
+
);
|
|
30
37
|
return;
|
|
31
38
|
}
|
|
32
39
|
if (options.count) {
|
|
@@ -36,8 +43,12 @@ function registerLinearListCommand(parent) {
|
|
|
36
43
|
console.log(` ${status}: ${count}`);
|
|
37
44
|
});
|
|
38
45
|
const cacheStats2 = restClient.getCacheStats();
|
|
39
|
-
console.log(
|
|
40
|
-
|
|
46
|
+
console.log(
|
|
47
|
+
chalk.gray(
|
|
48
|
+
`
|
|
49
|
+
Cache: ${cacheStats2.size} tasks, age: ${Math.round(cacheStats2.age / 1e3)}s`
|
|
50
|
+
)
|
|
51
|
+
);
|
|
41
52
|
return;
|
|
42
53
|
}
|
|
43
54
|
let tasks;
|
|
@@ -54,18 +65,30 @@ Cache: ${cacheStats2.size} tasks, age: ${Math.round(cacheStats2.age / 1e3)}s`));
|
|
|
54
65
|
}
|
|
55
66
|
const limit = parseInt(options.limit);
|
|
56
67
|
const displayTasks = tasks.slice(0, limit);
|
|
57
|
-
console.log(
|
|
58
|
-
|
|
68
|
+
console.log(
|
|
69
|
+
chalk.cyan(
|
|
70
|
+
`
|
|
71
|
+
\u{1F4CB} Linear Tasks (${displayTasks.length}/${tasks.length}):`
|
|
72
|
+
)
|
|
73
|
+
);
|
|
59
74
|
displayTasks.forEach((task) => {
|
|
60
75
|
const priority = task.priority ? `P${task.priority}` : "";
|
|
61
76
|
const assignee = task.assignee ? ` @${task.assignee.name}` : "";
|
|
62
77
|
const statusColor = task.state.type === "completed" ? chalk.green : task.state.type === "started" ? chalk.yellow : chalk.gray;
|
|
63
78
|
console.log(`${chalk.blue(task.identifier)} ${task.title}`);
|
|
64
|
-
console.log(
|
|
79
|
+
console.log(
|
|
80
|
+
chalk.gray(
|
|
81
|
+
` ${statusColor(task.state.name)} ${priority}${assignee}`
|
|
82
|
+
)
|
|
83
|
+
);
|
|
65
84
|
});
|
|
66
85
|
const cacheStats = restClient.getCacheStats();
|
|
67
|
-
console.log(
|
|
68
|
-
|
|
86
|
+
console.log(
|
|
87
|
+
chalk.gray(
|
|
88
|
+
`
|
|
89
|
+
${displayTasks.length} shown, ${tasks.length} total \u2022 Cache: ${Math.round(cacheStats.age / 1e3)}s old`
|
|
90
|
+
)
|
|
91
|
+
);
|
|
69
92
|
} catch (error) {
|
|
70
93
|
console.error(
|
|
71
94
|
chalk.red("Failed to list tasks:"),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/cli/commands/linear-list.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Simple Linear task list command using memory cache\n */\n\nimport chalk from 'chalk';\nimport { Command } from 'commander';\nimport { LinearRestClient } from '../../integrations/linear/rest-client.js';\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\
|
|
5
|
-
"mappings": "AAIA,OAAO,WAAW;AAElB,SAAS,wBAAwB;AAEjC,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;
|
|
4
|
+
"sourcesContent": ["/**\n * Simple Linear task list command using memory cache\n */\n\nimport chalk from 'chalk';\nimport { Command } from 'commander';\nimport { LinearRestClient } from '../../integrations/linear/rest-client.js';\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 function registerLinearListCommand(parent: Command) {\n parent\n .command('linear:list')\n .alias('linear:ls')\n .description('List Linear tasks (fast, memory-cached)')\n .option('--limit <n>', 'Number of tasks to show', '20')\n .option(\n '--status <status>',\n 'Filter by status (backlog, started, completed, etc.)'\n )\n .option('--my', 'Show only tasks assigned to me')\n .option('--cache', 'Show cache stats only')\n .option('--refresh', 'Force refresh cache')\n .option('--count', 'Show count by status only')\n .action(async (options) => {\n try {\n const apiKey = process.env['LINEAR_API_KEY'];\n if (!apiKey) {\n console.log(\n chalk.yellow('\u26A0 Set LINEAR_API_KEY environment variable')\n );\n return;\n }\n\n const restClient = new LinearRestClient(apiKey);\n\n // Show cache stats if requested\n if (options.cache) {\n const stats = restClient.getCacheStats();\n console.log(chalk.cyan('\uD83D\uDCCA Cache Stats:'));\n console.log(` Size: ${stats.size} tasks`);\n console.log(` Age: ${Math.round(stats.age / 1000)}s`);\n console.log(` Fresh: ${stats.fresh ? 'yes' : 'no'}`);\n console.log(\n ` Last sync: ${new Date(stats.lastSync).toLocaleString()}`\n );\n return;\n }\n\n // Show counts only\n if (options.count) {\n const counts = await restClient.getTaskCounts();\n console.log(chalk.cyan('\uD83D\uDCCA Task Counts:'));\n Object.entries(counts)\n .sort(([, a], [, b]) => b - a)\n .forEach(([status, count]) => {\n console.log(` ${status}: ${count}`);\n });\n\n const cacheStats = restClient.getCacheStats();\n console.log(\n chalk.gray(\n `\\nCache: ${cacheStats.size} tasks, age: ${Math.round(cacheStats.age / 1000)}s`\n )\n );\n return;\n }\n\n let tasks;\n if (options.my) {\n tasks = await restClient.getMyTasks();\n } else if (options.status) {\n tasks = await restClient.getTasksByStatus(options.status);\n } else {\n tasks = await restClient.getAllTasks(options.refresh);\n }\n\n if (!tasks || tasks.length === 0) {\n console.log(chalk.gray('No tasks found'));\n return;\n }\n\n // Limit results\n const limit = parseInt(options.limit);\n const displayTasks = tasks.slice(0, limit);\n\n console.log(\n chalk.cyan(\n `\\n\uD83D\uDCCB Linear Tasks (${displayTasks.length}/${tasks.length}):`\n )\n );\n\n displayTasks.forEach((task) => {\n const priority = task.priority ? `P${task.priority}` : '';\n const assignee = task.assignee ? ` @${task.assignee.name}` : '';\n const statusColor =\n task.state.type === 'completed'\n ? chalk.green\n : task.state.type === 'started'\n ? chalk.yellow\n : chalk.gray;\n\n console.log(`${chalk.blue(task.identifier)} ${task.title}`);\n console.log(\n chalk.gray(\n ` ${statusColor(task.state.name)} ${priority}${assignee}`\n )\n );\n });\n\n const cacheStats = restClient.getCacheStats();\n console.log(\n chalk.gray(\n `\\n${displayTasks.length} shown, ${tasks.length} total \u2022 Cache: ${Math.round(cacheStats.age / 1000)}s old`\n )\n );\n } catch (error: unknown) {\n console.error(\n chalk.red('Failed to list tasks:'),\n (error as Error).message\n );\n }\n });\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["cacheStats"]
|
|
7
7
|
}
|
|
@@ -12,22 +12,35 @@ function getOptionalEnv(key) {
|
|
|
12
12
|
return process.env[key];
|
|
13
13
|
}
|
|
14
14
|
function registerLinearMigrateCommand(parent) {
|
|
15
|
-
parent.command("linear:migrate").description("Migrate STA- tasks from LiftCL to new Linear workspace").option("--source-key <key>", "Source workspace Linear API key").option("--target-key <key>", "Target workspace Linear API key").option("--dry-run", "Preview migration without making changes").option(
|
|
15
|
+
parent.command("linear:migrate").description("Migrate STA- tasks from LiftCL to new Linear workspace").option("--source-key <key>", "Source workspace Linear API key").option("--target-key <key>", "Target workspace Linear API key").option("--dry-run", "Preview migration without making changes").option(
|
|
16
|
+
"--delete-source",
|
|
17
|
+
"Delete tasks from source after successful migration"
|
|
18
|
+
).option("--batch-size <n>", "Number of tasks per batch", "3").option("--delay <ms>", "Delay between batches in milliseconds", "3000").action(async (options) => {
|
|
16
19
|
try {
|
|
17
20
|
const sourceKey = options.sourceKey || process.env["LINEAR_API_KEY"];
|
|
18
21
|
const targetKey = options.targetKey;
|
|
19
22
|
if (!sourceKey) {
|
|
20
|
-
console.error(
|
|
23
|
+
console.error(
|
|
24
|
+
chalk.red(
|
|
25
|
+
"\u274C Source API key required. Use --source-key or set LINEAR_API_KEY"
|
|
26
|
+
)
|
|
27
|
+
);
|
|
21
28
|
return;
|
|
22
29
|
}
|
|
23
30
|
if (!targetKey) {
|
|
24
|
-
console.error(
|
|
31
|
+
console.error(
|
|
32
|
+
chalk.red("\u274C Target API key required. Use --target-key")
|
|
33
|
+
);
|
|
25
34
|
return;
|
|
26
35
|
}
|
|
27
36
|
console.log(chalk.blue("\u{1F680} Starting Linear Migration"));
|
|
28
37
|
console.log(chalk.gray(" This will migrate all STA- prefixed tasks"));
|
|
29
38
|
if (options.deleteSource) {
|
|
30
|
-
console.log(
|
|
39
|
+
console.log(
|
|
40
|
+
chalk.yellow(
|
|
41
|
+
" \u26A0\uFE0F Tasks will be DELETED from source after migration"
|
|
42
|
+
)
|
|
43
|
+
);
|
|
31
44
|
}
|
|
32
45
|
console.log();
|
|
33
46
|
await runMigration({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/cli/commands/linear-migrate.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Linear Migration Command\n */\n\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport { runMigration } from '../../integrations/linear/migration.js';\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\
|
|
5
|
-
"mappings": "AAKA,OAAO,WAAW;AAClB,SAAS,oBAAoB;AAE7B,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;
|
|
4
|
+
"sourcesContent": ["/**\n * Linear Migration Command\n */\n\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport { runMigration } from '../../integrations/linear/migration.js';\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 function registerLinearMigrateCommand(parent: Command) {\n parent\n .command('linear:migrate')\n .description('Migrate STA- tasks from LiftCL to new Linear workspace')\n .option('--source-key <key>', 'Source workspace Linear API key')\n .option('--target-key <key>', 'Target workspace Linear API key')\n .option('--dry-run', 'Preview migration without making changes')\n .option(\n '--delete-source',\n 'Delete tasks from source after successful migration'\n )\n .option('--batch-size <n>', 'Number of tasks per batch', '3')\n .option('--delay <ms>', 'Delay between batches in milliseconds', '3000')\n .action(async (options) => {\n try {\n const sourceKey = options.sourceKey || process.env['LINEAR_API_KEY'];\n const targetKey = options.targetKey;\n\n if (!sourceKey) {\n console.error(\n chalk.red(\n '\u274C Source API key required. Use --source-key or set LINEAR_API_KEY'\n )\n );\n return;\n }\n\n if (!targetKey) {\n console.error(\n chalk.red('\u274C Target API key required. Use --target-key')\n );\n return;\n }\n\n console.log(chalk.blue('\uD83D\uDE80 Starting Linear Migration'));\n console.log(chalk.gray(' This will migrate all STA- prefixed tasks'));\n if (options.deleteSource) {\n console.log(\n chalk.yellow(\n ' \u26A0\uFE0F Tasks will be DELETED from source after migration'\n )\n );\n }\n console.log();\n\n await runMigration({\n sourceApiKey: sourceKey,\n targetApiKey: targetKey,\n taskPrefix: 'STA-',\n deleteFromSource: options.deleteSource,\n dryRun: options.dryRun,\n batchSize: parseInt(options.batchSize),\n delayMs: parseInt(options.delay),\n });\n } catch (error: unknown) {\n console.error(chalk.red('Migration failed:'), (error as Error).message);\n process.exit(1);\n }\n });\n}\n"],
|
|
5
|
+
"mappings": "AAKA,OAAO,WAAW;AAClB,SAAS,oBAAoB;AAE7B,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;AAEO,SAAS,6BAA6B,QAAiB;AAC5D,SACG,QAAQ,gBAAgB,EACxB,YAAY,wDAAwD,EACpE,OAAO,sBAAsB,iCAAiC,EAC9D,OAAO,sBAAsB,iCAAiC,EAC9D,OAAO,aAAa,0CAA0C,EAC9D;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC,OAAO,oBAAoB,6BAA6B,GAAG,EAC3D,OAAO,gBAAgB,yCAAyC,MAAM,EACtE,OAAO,OAAO,YAAY;AACzB,QAAI;AACF,YAAM,YAAY,QAAQ,aAAa,QAAQ,IAAI,gBAAgB;AACnE,YAAM,YAAY,QAAQ;AAE1B,UAAI,CAAC,WAAW;AACd,gBAAQ;AAAA,UACN,MAAM;AAAA,YACJ;AAAA,UACF;AAAA,QACF;AACA;AAAA,MACF;AAEA,UAAI,CAAC,WAAW;AACd,gBAAQ;AAAA,UACN,MAAM,IAAI,kDAA6C;AAAA,QACzD;AACA;AAAA,MACF;AAEA,cAAQ,IAAI,MAAM,KAAK,qCAA8B,CAAC;AACtD,cAAQ,IAAI,MAAM,KAAK,8CAA8C,CAAC;AACtE,UAAI,QAAQ,cAAc;AACxB,gBAAQ;AAAA,UACN,MAAM;AAAA,YACJ;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,cAAQ,IAAI;AAEZ,YAAM,aAAa;AAAA,QACjB,cAAc;AAAA,QACd,cAAc;AAAA,QACd,YAAY;AAAA,QACZ,kBAAkB,QAAQ;AAAA,QAC1B,QAAQ,QAAQ;AAAA,QAChB,WAAW,SAAS,QAAQ,SAAS;AAAA,QACrC,SAAS,SAAS,QAAQ,KAAK;AAAA,MACjC,CAAC;AAAA,IACH,SAAS,OAAgB;AACvB,cAAQ,MAAM,MAAM,IAAI,mBAAmB,GAAI,MAAgB,OAAO;AACtE,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AACL;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -16,14 +16,16 @@ function registerLinearTestCommand(parent) {
|
|
|
16
16
|
const apiKey = options.apiKey || process.env["LINEAR_API_KEY"];
|
|
17
17
|
if (!apiKey) {
|
|
18
18
|
console.log(chalk.red("\u274C No API key provided"));
|
|
19
|
-
console.log(
|
|
19
|
+
console.log(
|
|
20
|
+
"Use --api-key or set LINEAR_API_KEY environment variable"
|
|
21
|
+
);
|
|
20
22
|
return;
|
|
21
23
|
}
|
|
22
24
|
console.log(chalk.yellow("\u{1F504} Testing Linear connection..."));
|
|
23
25
|
const response = await fetch("https://api.linear.app/graphql", {
|
|
24
26
|
method: "POST",
|
|
25
27
|
headers: {
|
|
26
|
-
|
|
28
|
+
Authorization: apiKey,
|
|
27
29
|
"Content-Type": "application/json"
|
|
28
30
|
},
|
|
29
31
|
body: JSON.stringify({
|
|
@@ -46,13 +48,17 @@ function registerLinearTestCommand(parent) {
|
|
|
46
48
|
})
|
|
47
49
|
});
|
|
48
50
|
if (!response.ok) {
|
|
49
|
-
console.log(
|
|
51
|
+
console.log(
|
|
52
|
+
chalk.red(`\u274C API Error: ${response.status} ${response.statusText}`)
|
|
53
|
+
);
|
|
50
54
|
return;
|
|
51
55
|
}
|
|
52
56
|
const result = await response.json();
|
|
53
57
|
if (result.errors) {
|
|
54
58
|
console.log(chalk.red("\u274C GraphQL Errors:"));
|
|
55
|
-
result.errors.forEach(
|
|
59
|
+
result.errors.forEach(
|
|
60
|
+
(err) => console.log(` - ${err.message}`)
|
|
61
|
+
);
|
|
56
62
|
return;
|
|
57
63
|
}
|
|
58
64
|
if (result.data?.viewer) {
|
|
@@ -73,7 +79,7 @@ function registerLinearTestCommand(parent) {
|
|
|
73
79
|
const createResponse = await fetch("https://api.linear.app/graphql", {
|
|
74
80
|
method: "POST",
|
|
75
81
|
headers: {
|
|
76
|
-
|
|
82
|
+
Authorization: apiKey,
|
|
77
83
|
"Content-Type": "application/json"
|
|
78
84
|
},
|
|
79
85
|
body: JSON.stringify({
|
|
@@ -108,7 +114,9 @@ function registerLinearTestCommand(parent) {
|
|
|
108
114
|
console.log(` ID: ${issue.identifier}`);
|
|
109
115
|
console.log(` Title: ${issue.title}`);
|
|
110
116
|
console.log(` URL: ${issue.url}`);
|
|
111
|
-
console.log(
|
|
117
|
+
console.log(
|
|
118
|
+
chalk.gray("\n(You can delete this test issue from Linear)")
|
|
119
|
+
);
|
|
112
120
|
} else {
|
|
113
121
|
console.log(chalk.yellow("\u26A0 Could not create test issue"));
|
|
114
122
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/cli/commands/linear-test.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Simple Linear sync test command\n */\n\nimport chalk from 'chalk';\nimport { Command } from 'commander';\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\
|
|
5
|
-
"mappings": "AAIA,OAAO,WAAW;AAGlB,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;
|
|
4
|
+
"sourcesContent": ["/**\n * Simple Linear sync test command\n */\n\nimport chalk from 'chalk';\nimport { Command } from 'commander';\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 function registerLinearTestCommand(parent: Command) {\n parent\n .command('linear:test')\n .description('Test Linear API connection')\n .option('--api-key <key>', 'Linear API key')\n .action(async (options) => {\n try {\n const apiKey = options.apiKey || process.env['LINEAR_API_KEY'];\n\n if (!apiKey) {\n console.log(chalk.red('\u274C No API key provided'));\n console.log(\n 'Use --api-key or set LINEAR_API_KEY environment variable'\n );\n return;\n }\n\n console.log(chalk.yellow('\uD83D\uDD04 Testing Linear connection...'));\n\n // Simple GraphQL query to test connection\n const response = await fetch('https://api.linear.app/graphql', {\n method: 'POST',\n headers: {\n Authorization: apiKey,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n query: `\n query Me {\n viewer {\n id\n name\n email\n }\n teams {\n nodes {\n id\n key\n name\n }\n }\n }\n `,\n }),\n });\n\n if (!response.ok) {\n console.log(\n chalk.red(`\u274C API Error: ${response.status} ${response.statusText}`)\n );\n return;\n }\n\n const result: any = await response.json();\n\n if (result.errors) {\n console.log(chalk.red('\u274C GraphQL Errors:'));\n result.errors.forEach((err: any) =>\n console.log(` - ${err.message}`)\n );\n return;\n }\n\n if (result.data?.viewer) {\n console.log(chalk.green('\u2705 Connected to Linear!'));\n console.log(chalk.cyan('\\n\uD83D\uDC64 User:'));\n console.log(` Name: ${result.data.viewer.name}`);\n console.log(` Email: ${result.data.viewer.email}`);\n }\n\n if (result.data?.teams?.nodes?.length > 0) {\n console.log(chalk.cyan('\\n\uD83C\uDFE2 Teams:'));\n result.data.teams.nodes.forEach((team: any) => {\n console.log(` - ${team.name} (${team.key})`);\n });\n }\n\n // Test creating a sample issue (optional)\n console.log(chalk.yellow('\\n\uD83D\uDD04 Testing issue creation...'));\n\n if (result.data?.teams?.nodes?.length > 0) {\n const teamId = result.data.teams.nodes[0].id;\n\n const createResponse = await fetch('https://api.linear.app/graphql', {\n method: 'POST',\n headers: {\n Authorization: apiKey,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n query: `\n mutation CreateIssue($input: IssueCreateInput!) {\n issueCreate(input: $input) {\n success\n issue {\n id\n identifier\n title\n url\n }\n }\n }\n `,\n variables: {\n input: {\n teamId: teamId,\n title: '[TEST] StackMemory Integration Test',\n description:\n 'This is a test issue created by StackMemory to verify Linear integration.',\n priority: 4, // Low priority\n },\n },\n }),\n });\n\n const createResult: any = await createResponse.json();\n\n if (createResult.data?.issueCreate?.success) {\n const issue = createResult.data.issueCreate.issue;\n console.log(chalk.green('\u2705 Test issue created successfully!'));\n console.log(` ID: ${issue.identifier}`);\n console.log(` Title: ${issue.title}`);\n console.log(` URL: ${issue.url}`);\n\n // Optional: Delete the test issue\n console.log(\n chalk.gray('\\n(You can delete this test issue from Linear)')\n );\n } else {\n console.log(chalk.yellow('\u26A0 Could not create test issue'));\n }\n }\n\n console.log(chalk.green('\\n\u2705 Linear integration test completed!'));\n } catch (error: unknown) {\n console.error(chalk.red('\u274C Test failed:'), (error as Error).message);\n process.exit(1);\n }\n });\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|