@stackmemoryai/stackmemory 0.3.6 → 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/agents/verifiers/formatter-verifier.js.map +2 -2
- package/dist/agents/verifiers/llm-judge.js.map +2 -2
- package/dist/cli/claude-sm.js +13 -13
- package/dist/cli/claude-sm.js.map +2 -2
- package/dist/cli/codex-sm.js +13 -13
- package/dist/cli/codex-sm.js.map +2 -2
- package/dist/cli/commands/agent.js.map +2 -2
- package/dist/cli/commands/chromadb.js +261 -46
- package/dist/cli/commands/chromadb.js.map +2 -2
- package/dist/cli/commands/clear.js +10 -3
- 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 +13 -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 +251 -0
- package/dist/cli/commands/gc.js.map +7 -0
- package/dist/cli/commands/handoff.js +12 -1
- package/dist/cli/commands/handoff.js.map +2 -2
- package/dist/cli/commands/infinite-storage.js +92 -40
- package/dist/cli/commands/infinite-storage.js.map +2 -2
- package/dist/cli/commands/linear-create.js +49 -10
- package/dist/cli/commands/linear-create.js.map +2 -2
- package/dist/cli/commands/linear-list.js +45 -11
- package/dist/cli/commands/linear-list.js.map +2 -2
- package/dist/cli/commands/linear-migrate.js +29 -5
- package/dist/cli/commands/linear-migrate.js.map +2 -2
- package/dist/cli/commands/linear-test.js +26 -7
- package/dist/cli/commands/linear-test.js.map +2 -2
- package/dist/cli/commands/linear-unified.js +350 -0
- package/dist/cli/commands/linear-unified.js.map +7 -0
- package/dist/cli/commands/linear.js +17 -6
- 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/search.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 +84 -28
- package/dist/cli/commands/skills.js.map +2 -2
- package/dist/cli/commands/storage.js +119 -38
- package/dist/cli/commands/storage.js.map +2 -2
- package/dist/cli/commands/tasks.js.map +2 -2
- package/dist/cli/commands/tui.js +13 -2
- package/dist/cli/commands/tui.js.map +2 -2
- package/dist/cli/commands/webhook.js +71 -21
- package/dist/cli/commands/webhook.js.map +2 -2
- package/dist/cli/commands/workflow.js +11 -7
- 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 +7 -5
- package/dist/cli/index.js.map +2 -2
- package/dist/core/config/config-manager.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/compaction-handler.js.map +2 -2
- package/dist/core/context/context-bridge.js.map +2 -2
- package/dist/core/context/dual-stack-manager.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-handoff-manager.js.map +2 -2
- package/dist/core/context/frame-manager.js +12 -1
- 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 +286 -0
- package/dist/core/context/incremental-gc.js.map +7 -0
- package/dist/core/context/index.js.map +1 -1
- package/dist/core/context/permission-manager.js +12 -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 +16 -3
- package/dist/core/context/shared-context-layer.js.map +2 -2
- package/dist/core/context/stack-merge-resolver.js.map +2 -2
- package/dist/core/context/validation.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/connection-pool.js.map +2 -2
- package/dist/core/database/migration-manager.js.map +2 -2
- package/dist/core/database/paradedb-adapter.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/query-router.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/merge/resolution-engine.js.map +2 -2
- package/dist/core/monitoring/error-handler.js.map +2 -2
- package/dist/core/monitoring/logger.js +19 -3
- package/dist/core/monitoring/logger.js.map +2 -2
- package/dist/core/monitoring/metrics.js +13 -2
- package/dist/core/monitoring/metrics.js.map +2 -2
- package/dist/core/monitoring/progress-tracker.js +12 -1
- package/dist/core/monitoring/progress-tracker.js.map +2 -2
- package/dist/core/monitoring/session-monitor.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/monitor.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 +63 -15
- 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/persistence/postgres-adapter.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 +2 -2
- package/dist/core/retrieval/graph-retrieval.js.map +2 -2
- package/dist/core/retrieval/llm-context-retrieval.js.map +2 -2
- package/dist/core/retrieval/retrieval-benchmarks.js.map +2 -2
- package/dist/core/retrieval/summary-generator.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/handoff-generator.js.map +2 -2
- package/dist/core/session/index.js.map +1 -1
- package/dist/core/session/session-manager.js +16 -5
- package/dist/core/session/session-manager.js.map +2 -2
- package/dist/core/skills/skill-storage.js +13 -2
- package/dist/core/skills/skill-storage.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 +67 -30
- package/dist/core/storage/railway-optimized-storage.js.map +2 -2
- package/dist/core/storage/remote-storage.js +53 -24
- package/dist/core/storage/remote-storage.js.map +2 -2
- package/dist/core/trace/cli-trace-wrapper.js +25 -7
- 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 +44 -16
- package/dist/core/trace/debug-trace.js.map +2 -2
- package/dist/core/trace/index.js +50 -35
- 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 +26 -11
- 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/trace-store.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 +2 -2
- package/dist/core/worktree/worktree-manager.js +18 -7
- package/dist/core/worktree/worktree-manager.js.map +2 -2
- package/dist/features/analytics/api/analytics-api.js.map +2 -2
- package/dist/features/analytics/core/analytics-service.js +12 -1
- 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 +2 -2
- 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 +666 -2
- package/dist/features/tui/components/task-board.js.map +2 -2
- package/dist/features/tui/index.js +16 -5
- package/dist/features/tui/index.js.map +2 -2
- package/dist/features/tui/services/data-service.js +30 -15
- 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 +16 -3
- package/dist/features/tui/services/websocket-client.js.map +2 -2
- package/dist/features/tui/terminal-compat.js +33 -18
- 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 +31 -12
- package/dist/features/web/server/index.js.map +2 -2
- package/dist/integrations/claude-code/enhanced-pre-clear-hooks.js.map +2 -2
- package/dist/integrations/claude-code/lifecycle-hooks.js.map +2 -2
- package/dist/integrations/claude-code/post-task-hooks.js.map +2 -2
- package/dist/integrations/linear/auth.js +17 -6
- package/dist/integrations/linear/auth.js.map +2 -2
- package/dist/integrations/linear/auto-sync.js.map +2 -2
- package/dist/integrations/linear/client.js.map +2 -2
- package/dist/integrations/linear/config.js.map +2 -2
- package/dist/integrations/linear/migration.js.map +2 -2
- package/dist/integrations/linear/oauth-server.js +13 -2
- package/dist/integrations/linear/oauth-server.js.map +2 -2
- package/dist/integrations/linear/rest-client.js.map +2 -2
- package/dist/integrations/linear/sync-enhanced.js +202 -0
- package/dist/integrations/linear/sync-enhanced.js.map +7 -0
- package/dist/integrations/linear/sync-manager.js.map +2 -2
- package/dist/integrations/linear/sync-service.js +24 -14
- package/dist/integrations/linear/sync-service.js.map +2 -2
- package/dist/integrations/linear/sync.js +196 -3
- package/dist/integrations/linear/sync.js.map +2 -2
- package/dist/integrations/linear/unified-sync.js +560 -0
- package/dist/integrations/linear/unified-sync.js.map +7 -0
- package/dist/integrations/linear/webhook-handler.js +12 -1
- package/dist/integrations/linear/webhook-handler.js.map +2 -2
- package/dist/integrations/linear/webhook-server.js +29 -19
- package/dist/integrations/linear/webhook-server.js.map +2 -2
- package/dist/integrations/linear/webhook.js +12 -1
- package/dist/integrations/linear/webhook.js.map +2 -2
- package/dist/integrations/mcp/handlers/context-handlers.js.map +2 -2
- package/dist/integrations/mcp/handlers/linear-handlers.js.map +2 -2
- package/dist/integrations/mcp/handlers/skill-handlers.js +13 -2
- package/dist/integrations/mcp/handlers/skill-handlers.js.map +2 -2
- package/dist/integrations/mcp/handlers/task-handlers.js.map +2 -2
- package/dist/integrations/mcp/handlers/trace-handlers.js.map +2 -2
- package/dist/integrations/mcp/middleware/tool-scoring.js.map +2 -2
- package/dist/integrations/mcp/refactored-server.js +15 -4
- package/dist/integrations/mcp/refactored-server.js.map +2 -2
- package/dist/integrations/mcp/server.js +12 -1
- package/dist/integrations/mcp/server.js.map +2 -2
- package/dist/integrations/mcp/tool-definitions.js.map +2 -2
- package/dist/integrations/pg-aiguide/embedding-provider.js +13 -2
- package/dist/integrations/pg-aiguide/embedding-provider.js.map +2 -2
- package/dist/integrations/pg-aiguide/semantic-search.js.map +2 -2
- package/dist/mcp/stackmemory-mcp-server.js +1 -1
- package/dist/mcp/stackmemory-mcp-server.js.map +2 -2
- package/dist/middleware/exponential-rate-limiter.js.map +2 -2
- package/dist/servers/production/auth-middleware.js +13 -2
- package/dist/servers/production/auth-middleware.js.map +2 -2
- package/dist/servers/railway/index.js +22 -11
- 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 +108 -3
- 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 +561 -0
- package/dist/skills/repo-ingestion-skill.js.map +7 -0
- package/dist/utils/env.js +46 -0
- package/dist/utils/env.js.map +7 -0
- package/dist/utils/logger.js +1 -1
- package/dist/utils/logger.js.map +2 -2
- package/package.json +5 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/cli/commands/dashboard.ts"],
|
|
4
|
-
"sourcesContent": ["#!/usr/bin/env node\n/**\n * Dashboard Command - Display monitoring dashboard in terminal\n */\n\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\nimport { SessionManager } from '../../core/session/session-manager.js';\nimport { FrameManager } from '../../core/context/frame-manager.js';\nimport Database from 'better-sqlite3';\nimport { join } from 'path';\nimport { existsSync } from 'fs';\n\nexport const dashboardCommand = {\n command: 'dashboard',\n describe: 'Display monitoring dashboard in terminal',\n builder: (yargs: any) => {\n return yargs\n .option('watch', {\n alias: 'w',\n type: 'boolean',\n description: 'Auto-refresh dashboard',\n default: false
|
|
5
|
-
"mappings": ";AAKA,OAAO,WAAW;AAClB,OAAO,WAAW;AAClB,SAAS,sBAAsB;AAE/B,OAAO,cAAc;AACrB,SAAS,YAAY;AACrB,SAAS,kBAAkB;AAEpB,MAAM,mBAAmB;AAAA,EAC9B,SAAS;AAAA,EACT,UAAU;AAAA,EACV,SAAS,CAAC,UAAe;AACvB,WAAO,MACJ,OAAO,SAAS;AAAA,MACf,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC,EACA,OAAO,YAAY;AAAA,MAClB,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,EACL;AAAA,EACA,SAAS,OAAO,SAAc;AAC5B,UAAM,cAAc,QAAQ,IAAI;AAChC,UAAM,SAAS,KAAK,aAAa,gBAAgB,YAAY;AAE7D,QAAI,CAAC,WAAW,MAAM,GAAG;AACvB,cAAQ,
|
|
4
|
+
"sourcesContent": ["#!/usr/bin/env node\n/**\n * Dashboard Command - Display monitoring dashboard in terminal\n */\n\nimport chalk from 'chalk';\nimport Table from 'cli-table3';\nimport { SessionManager } from '../../core/session/session-manager.js';\nimport { FrameManager } from '../../core/context/frame-manager.js';\nimport Database from 'better-sqlite3';\nimport { join } from 'path';\nimport { existsSync } from 'fs';\n\nexport const dashboardCommand = {\n command: 'dashboard',\n describe: 'Display monitoring dashboard in terminal',\n builder: (yargs: any) => {\n return yargs\n .option('watch', {\n alias: 'w',\n type: 'boolean',\n description: 'Auto-refresh dashboard',\n default: false,\n })\n .option('interval', {\n alias: 'i',\n type: 'number',\n description: 'Refresh interval in seconds',\n default: 5,\n });\n },\n handler: async (argv: any) => {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n if (!existsSync(dbPath)) {\n console.log(\n '\u274C StackMemory not initialized. Run \"stackmemory init\" first.'\n );\n return;\n }\n\n const displayDashboard = async () => {\n console.clear();\n\n // Header\n console.log(\n chalk.cyan.bold(\n '\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'\n )\n );\n console.log(\n chalk.cyan.bold(\n ' \uD83D\uDE80 StackMemory Monitoring Dashboard '\n )\n );\n console.log(\n chalk.cyan.bold(\n '\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550'\n )\n );\n console.log();\n\n const sessionManager = new SessionManager({ enableMonitoring: false });\n await sessionManager.initialize();\n\n const db = new Database(dbPath);\n\n // Get sessions\n const sessions = await sessionManager.listSessions({\n state: 'active',\n limit: 5,\n });\n\n // Sessions Table\n const sessionsTable = new Table({\n head: [\n chalk.white('Session ID'),\n chalk.white('Status'),\n chalk.white('Branch'),\n chalk.white('Duration'),\n chalk.white('Last Active'),\n ],\n style: { head: [], border: [] },\n });\n\n sessions.forEach((session) => {\n const duration = Math.round(\n (Date.now() - session.startedAt) / 1000 / 60\n );\n const lastActive = Math.round(\n (Date.now() - session.lastActiveAt) / 1000 / 60\n );\n const status =\n session.state === 'active'\n ? chalk.green('\u25CF Active')\n : session.state === 'completed'\n ? chalk.gray('\u25CF Completed')\n : chalk.yellow('\u25CF Idle');\n\n sessionsTable.push([\n session.sessionId.substring(0, 8),\n status,\n session.branch || 'main',\n `${duration}m`,\n `${lastActive}m ago`,\n ]);\n });\n\n console.log(chalk.yellow.bold('\uD83D\uDCCA Active Sessions'));\n console.log(sessionsTable.toString());\n console.log();\n\n // Frame Statistics\n const frameStats = db\n .prepare(\n `\n SELECT \n COUNT(*) as total,\n SUM(CASE WHEN state = 'active' THEN 1 ELSE 0 END) as active,\n COUNT(DISTINCT run_id) as sessions\n FROM frames\n `\n )\n .get() as any;\n\n const statsTable = new Table({\n head: [chalk.white('Metric'), chalk.white('Value')],\n style: { head: [], border: [] },\n });\n\n statsTable.push(\n ['Total Frames', frameStats.total || 0],\n ['Active Frames', chalk.green(frameStats.active || 0)],\n ['Total Sessions', frameStats.sessions || 0]\n );\n\n console.log(chalk.yellow.bold('\uD83D\uDCC8 Frame Statistics'));\n console.log(statsTable.toString());\n console.log();\n\n // Recent Activity\n const recentActivity = db\n .prepare(\n `\n SELECT \n name,\n type,\n state,\n datetime(created_at, 'unixepoch') as created\n FROM frames\n ORDER BY created_at DESC\n LIMIT 5\n `\n )\n .all() as any[];\n\n if (recentActivity.length > 0) {\n const activityTable = new Table({\n head: [\n chalk.white('Frame'),\n chalk.white('Type'),\n chalk.white('Status'),\n chalk.white('Created'),\n ],\n style: { head: [], border: [] },\n });\n\n recentActivity.forEach((frame) => {\n const status =\n frame.state === 'active'\n ? chalk.green('Active')\n : chalk.gray('Closed');\n\n activityTable.push([\n frame.name.substring(0, 30),\n frame.type,\n status,\n frame.created,\n ]);\n });\n\n console.log(chalk.yellow.bold('\uD83D\uDD50 Recent Activity'));\n console.log(activityTable.toString());\n console.log();\n }\n\n // Memory Usage\n const contextUsage = await estimateContextUsage(db);\n const usageBar = createProgressBar(contextUsage, 100);\n\n console.log(chalk.yellow.bold('\uD83D\uDCBE Context Usage'));\n console.log(`${usageBar} ${contextUsage}%`);\n console.log();\n\n db.close();\n\n // Footer\n if (argv.watch) {\n console.log(\n chalk.gray(\n `Auto-refreshing every ${argv.interval} seconds. Press Ctrl+C to exit.`\n )\n );\n } else {\n console.log(chalk.gray('Run with --watch to auto-refresh'));\n }\n };\n\n try {\n await displayDashboard();\n\n if (argv.watch) {\n const interval = setInterval(async () => {\n await displayDashboard();\n }, argv.interval * 1000);\n\n process.on('SIGINT', () => {\n clearInterval(interval);\n console.clear();\n console.log(chalk.green('\u2705 Dashboard closed'));\n process.exit(0);\n });\n }\n } catch (error: unknown) {\n console.error(chalk.red('\u274C Dashboard error:'), (error as Error).message);\n process.exit(1);\n }\n },\n};\n\nfunction createProgressBar(value: number, max: number): string {\n const percentage = Math.min(100, Math.round((value / max) * 100));\n const filled = Math.round(percentage / 5);\n const empty = 20 - filled;\n\n let color = chalk.green;\n if (percentage > 80) color = chalk.red;\n else if (percentage > 60) color = chalk.yellow;\n\n return color('\u2588'.repeat(filled)) + chalk.gray('\u2591'.repeat(empty));\n}\n\nasync function estimateContextUsage(db: Database): Promise<number> {\n const result = db\n .prepare(\n `\n SELECT \n COUNT(*) as frame_count,\n SUM(LENGTH(inputs)) as input_size,\n SUM(LENGTH(outputs)) as output_size\n FROM frames\n WHERE state = 'active'\n `\n )\n .get() as any;\n\n // Rough estimate: assume average token is 4 bytes\n const totalBytes = (result.input_size || 0) + (result.output_size || 0);\n const estimatedTokens = totalBytes / 4;\n const maxTokens = 128000; // Claude's context window\n\n return Math.round((estimatedTokens / maxTokens) * 100);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import ora from "ora";
|
|
4
|
+
import Table from "cli-table3";
|
|
5
|
+
import { IncrementalGarbageCollector } from "../../core/context/incremental-gc.js";
|
|
6
|
+
import { FrameManager } from "../../core/context/frame-manager.js";
|
|
7
|
+
import { Logger } from "../../core/monitoring/logger.js";
|
|
8
|
+
const logger = new Logger("GC-CLI");
|
|
9
|
+
function createGCCommand() {
|
|
10
|
+
const gc = new Command("gc").description("Manage incremental garbage collection system").alias("garbage-collect");
|
|
11
|
+
gc.command("status").description("Show garbage collection statistics").action(async () => {
|
|
12
|
+
const spinner = ora("Getting GC status...").start();
|
|
13
|
+
try {
|
|
14
|
+
const frameManager = new FrameManager();
|
|
15
|
+
const collector = new IncrementalGarbageCollector(frameManager);
|
|
16
|
+
const stats = collector.getStats();
|
|
17
|
+
spinner.stop();
|
|
18
|
+
console.log(
|
|
19
|
+
chalk.cyan("\n\u{1F5D1}\uFE0F Incremental Garbage Collection Status\n")
|
|
20
|
+
);
|
|
21
|
+
const table = new Table({
|
|
22
|
+
head: ["Metric", "Value"],
|
|
23
|
+
colWidths: [25, 20]
|
|
24
|
+
});
|
|
25
|
+
table.push(
|
|
26
|
+
["Total Frames", stats.totalFrames.toString()],
|
|
27
|
+
["Collected Frames", stats.collectedFrames.toString()],
|
|
28
|
+
["Collection Cycles", stats.cycleCount.toString()],
|
|
29
|
+
["Avg Cycle Time", `${stats.avgCycleTime.toFixed(2)}ms`],
|
|
30
|
+
["Protected Frames", stats.protectedFrames.toString()],
|
|
31
|
+
[
|
|
32
|
+
"Last Run",
|
|
33
|
+
stats.lastRunTime ? new Date(stats.lastRunTime).toLocaleString() : "Never"
|
|
34
|
+
]
|
|
35
|
+
);
|
|
36
|
+
console.log(table.toString());
|
|
37
|
+
if (stats.totalFrames > 0) {
|
|
38
|
+
const collectionRate = (stats.collectedFrames / stats.totalFrames * 100).toFixed(1);
|
|
39
|
+
const protectionRate = (stats.protectedFrames / stats.totalFrames * 100).toFixed(1);
|
|
40
|
+
console.log("\n\u{1F4CA} Collection Efficiency:");
|
|
41
|
+
console.log(` Collection Rate: ${collectionRate}%`);
|
|
42
|
+
console.log(` Protection Rate: ${protectionRate}%`);
|
|
43
|
+
}
|
|
44
|
+
} catch (error) {
|
|
45
|
+
spinner.fail("Failed to get GC status");
|
|
46
|
+
logger.error("GC status error", error);
|
|
47
|
+
console.error(
|
|
48
|
+
chalk.red(error instanceof Error ? error.message : "Unknown error")
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
gc.command("collect").description("Run manual garbage collection cycle").option(
|
|
53
|
+
"--dry-run",
|
|
54
|
+
"Show what would be collected without actually collecting"
|
|
55
|
+
).action(async (options) => {
|
|
56
|
+
const spinner = ora("Running garbage collection...").start();
|
|
57
|
+
try {
|
|
58
|
+
const frameManager = new FrameManager();
|
|
59
|
+
const collector = new IncrementalGarbageCollector(frameManager);
|
|
60
|
+
if (options.dryRun) {
|
|
61
|
+
spinner.text = "Analyzing collection candidates (dry run)...";
|
|
62
|
+
spinner.succeed("Dry run completed - check logs for details");
|
|
63
|
+
} else {
|
|
64
|
+
await collector.forceCollection();
|
|
65
|
+
const stats = collector.getStats();
|
|
66
|
+
spinner.succeed(
|
|
67
|
+
`Collection completed - collected ${stats.collectedFrames} frames`
|
|
68
|
+
);
|
|
69
|
+
console.log(chalk.green("\n\u2705 Manual collection completed"));
|
|
70
|
+
console.log(` Processed: ${stats.totalFrames} frames`);
|
|
71
|
+
console.log(` Collected: ${stats.collectedFrames} frames`);
|
|
72
|
+
console.log(` Protected: ${stats.protectedFrames} frames`);
|
|
73
|
+
}
|
|
74
|
+
} catch (error) {
|
|
75
|
+
spinner.fail("Collection failed");
|
|
76
|
+
logger.error("GC collection error", error);
|
|
77
|
+
console.error(
|
|
78
|
+
chalk.red(error instanceof Error ? error.message : "Unknown error")
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
gc.command("start").description("Start incremental GC daemon").option("--interval <seconds>", "Collection interval in seconds", "60").option("--frames-per-cycle <number>", "Frames to process per cycle", "100").action(async (options) => {
|
|
83
|
+
const spinner = ora("Starting GC daemon...").start();
|
|
84
|
+
try {
|
|
85
|
+
const frameManager = new FrameManager();
|
|
86
|
+
const collector = new IncrementalGarbageCollector(frameManager, {
|
|
87
|
+
cycleInterval: parseInt(options.interval) * 1e3,
|
|
88
|
+
framesPerCycle: parseInt(options.framesPerCycle)
|
|
89
|
+
});
|
|
90
|
+
collector.start();
|
|
91
|
+
spinner.succeed("GC daemon started");
|
|
92
|
+
console.log(chalk.green("\n\u{1F680} Incremental GC daemon is running"));
|
|
93
|
+
console.log(` Interval: ${options.interval}s`);
|
|
94
|
+
console.log(` Frames per cycle: ${options.framesPerCycle}`);
|
|
95
|
+
console.log("\nPress Ctrl+C to stop");
|
|
96
|
+
process.on("SIGINT", () => {
|
|
97
|
+
console.log("\n\u23F9\uFE0F Stopping GC daemon...");
|
|
98
|
+
collector.stop();
|
|
99
|
+
process.exit(0);
|
|
100
|
+
});
|
|
101
|
+
await new Promise(() => {
|
|
102
|
+
});
|
|
103
|
+
} catch (error) {
|
|
104
|
+
spinner.fail("Failed to start GC daemon");
|
|
105
|
+
logger.error("GC start error", error);
|
|
106
|
+
console.error(
|
|
107
|
+
chalk.red(error instanceof Error ? error.message : "Unknown error")
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
gc.command("config").description("View or update GC configuration").option("--set-interval <seconds>", "Set collection interval").option("--set-frames-per-cycle <number>", "Set frames per cycle").option("--set-max-age <days>", "Set max frame age before collection").action(async (options) => {
|
|
112
|
+
try {
|
|
113
|
+
const frameManager = new FrameManager();
|
|
114
|
+
const collector = new IncrementalGarbageCollector(frameManager);
|
|
115
|
+
if (options.setInterval || options.setFramesPerCycle || options.setMaxAge) {
|
|
116
|
+
const newConfig = {};
|
|
117
|
+
if (options.setInterval)
|
|
118
|
+
newConfig.cycleInterval = parseInt(options.setInterval) * 1e3;
|
|
119
|
+
if (options.setFramesPerCycle)
|
|
120
|
+
newConfig.framesPerCycle = parseInt(options.setFramesPerCycle);
|
|
121
|
+
if (options.setMaxAge)
|
|
122
|
+
newConfig.maxAge = parseInt(options.setMaxAge) * 24 * 60 * 60 * 1e3;
|
|
123
|
+
collector.updateConfig(newConfig);
|
|
124
|
+
console.log(chalk.green("\u2705 Configuration updated"));
|
|
125
|
+
}
|
|
126
|
+
console.log(chalk.cyan("\n\u2699\uFE0F Current GC Configuration\n"));
|
|
127
|
+
console.log("Cycle Interval: 60s");
|
|
128
|
+
console.log("Frames per Cycle: 100");
|
|
129
|
+
console.log("Max Age: 30 days");
|
|
130
|
+
console.log("\nGenerations:");
|
|
131
|
+
console.log(" Young: < 1 day");
|
|
132
|
+
console.log(" Mature: 1-7 days");
|
|
133
|
+
console.log(" Old: 7-30 days");
|
|
134
|
+
} catch (error) {
|
|
135
|
+
logger.error("GC config error", error);
|
|
136
|
+
console.error(
|
|
137
|
+
chalk.red(error instanceof Error ? error.message : "Unknown error")
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
gc.command("analyze").description("Analyze frame distribution and collection opportunities").action(async () => {
|
|
142
|
+
const spinner = ora("Analyzing frames...").start();
|
|
143
|
+
try {
|
|
144
|
+
const frameManager = new FrameManager();
|
|
145
|
+
const allFrames = await frameManager.getAllFrames();
|
|
146
|
+
if (allFrames.length === 0) {
|
|
147
|
+
spinner.succeed("No frames to analyze");
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const now = Date.now();
|
|
151
|
+
const analysis = {
|
|
152
|
+
total: allFrames.length,
|
|
153
|
+
active: 0,
|
|
154
|
+
closed: 0,
|
|
155
|
+
young: 0,
|
|
156
|
+
mature: 0,
|
|
157
|
+
old: 0,
|
|
158
|
+
withOutputs: 0,
|
|
159
|
+
withoutOutputs: 0,
|
|
160
|
+
rootFrames: 0,
|
|
161
|
+
leafFrames: 0
|
|
162
|
+
};
|
|
163
|
+
for (const frame of allFrames) {
|
|
164
|
+
const age = now - frame.created_at;
|
|
165
|
+
if (frame.state === "active") analysis.active++;
|
|
166
|
+
else analysis.closed++;
|
|
167
|
+
if (age < 24 * 60 * 60 * 1e3) analysis.young++;
|
|
168
|
+
else if (age < 7 * 24 * 60 * 60 * 1e3) analysis.mature++;
|
|
169
|
+
else analysis.old++;
|
|
170
|
+
if (frame.outputs && Object.keys(frame.outputs).length > 0) {
|
|
171
|
+
analysis.withOutputs++;
|
|
172
|
+
} else {
|
|
173
|
+
analysis.withoutOutputs++;
|
|
174
|
+
}
|
|
175
|
+
if (frame.depth === 0) analysis.rootFrames++;
|
|
176
|
+
if (!allFrames.some((f) => f.parent_frame_id === frame.frame_id)) {
|
|
177
|
+
analysis.leafFrames++;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
spinner.stop();
|
|
181
|
+
console.log(chalk.cyan("\n\u{1F4CA} Frame Distribution Analysis\n"));
|
|
182
|
+
const stateTable = new Table({
|
|
183
|
+
head: ["Category", "Count", "Percentage"],
|
|
184
|
+
colWidths: [20, 10, 15]
|
|
185
|
+
});
|
|
186
|
+
const pct = (count) => `${(count / analysis.total * 100).toFixed(1)}%`;
|
|
187
|
+
stateTable.push(
|
|
188
|
+
["Active Frames", analysis.active.toString(), pct(analysis.active)],
|
|
189
|
+
["Closed Frames", analysis.closed.toString(), pct(analysis.closed)],
|
|
190
|
+
["", "", ""],
|
|
191
|
+
["Young (< 1 day)", analysis.young.toString(), pct(analysis.young)],
|
|
192
|
+
[
|
|
193
|
+
"Mature (1-7 days)",
|
|
194
|
+
analysis.mature.toString(),
|
|
195
|
+
pct(analysis.mature)
|
|
196
|
+
],
|
|
197
|
+
["Old (> 7 days)", analysis.old.toString(), pct(analysis.old)],
|
|
198
|
+
["", "", ""],
|
|
199
|
+
[
|
|
200
|
+
"With Outputs",
|
|
201
|
+
analysis.withOutputs.toString(),
|
|
202
|
+
pct(analysis.withOutputs)
|
|
203
|
+
],
|
|
204
|
+
[
|
|
205
|
+
"Without Outputs",
|
|
206
|
+
analysis.withoutOutputs.toString(),
|
|
207
|
+
pct(analysis.withoutOutputs)
|
|
208
|
+
],
|
|
209
|
+
["", "", ""],
|
|
210
|
+
[
|
|
211
|
+
"Root Frames",
|
|
212
|
+
analysis.rootFrames.toString(),
|
|
213
|
+
pct(analysis.rootFrames)
|
|
214
|
+
],
|
|
215
|
+
[
|
|
216
|
+
"Leaf Frames",
|
|
217
|
+
analysis.leafFrames.toString(),
|
|
218
|
+
pct(analysis.leafFrames)
|
|
219
|
+
]
|
|
220
|
+
);
|
|
221
|
+
console.log(stateTable.toString());
|
|
222
|
+
console.log(chalk.yellow("\n\u{1F4A1} Collection Recommendations:\n"));
|
|
223
|
+
const candidatesForCollection = analysis.closed + analysis.withoutOutputs;
|
|
224
|
+
console.log(
|
|
225
|
+
`\u2022 Potential collection candidates: ${candidatesForCollection} frames`
|
|
226
|
+
);
|
|
227
|
+
console.log(
|
|
228
|
+
`\u2022 Estimated space savings: ${(candidatesForCollection / analysis.total * 100).toFixed(1)}%`
|
|
229
|
+
);
|
|
230
|
+
if (analysis.old > 0) {
|
|
231
|
+
console.log(`\u2022 ${analysis.old} old frames ready for collection`);
|
|
232
|
+
}
|
|
233
|
+
if (analysis.withoutOutputs > 0) {
|
|
234
|
+
console.log(
|
|
235
|
+
`\u2022 ${analysis.withoutOutputs} frames without outputs can be collected`
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
} catch (error) {
|
|
239
|
+
spinner.fail("Analysis failed");
|
|
240
|
+
logger.error("GC analysis error", error);
|
|
241
|
+
console.error(
|
|
242
|
+
chalk.red(error instanceof Error ? error.message : "Unknown error")
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
return gc;
|
|
247
|
+
}
|
|
248
|
+
export {
|
|
249
|
+
createGCCommand
|
|
250
|
+
};
|
|
251
|
+
//# sourceMappingURL=gc.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/cli/commands/gc.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * CLI commands for Incremental Garbage Collection management\n */\n\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport Table from 'cli-table3';\nimport { IncrementalGarbageCollector } from '../../core/context/incremental-gc.js';\nimport { FrameManager } from '../../core/context/frame-manager.js';\nimport { Logger } from '../../core/monitoring/logger.js';\n\nconst logger = new Logger('GC-CLI');\n\nexport function createGCCommand(): Command {\n const gc = new Command('gc')\n .description('Manage incremental garbage collection system')\n .alias('garbage-collect');\n\n // Status command\n gc.command('status')\n .description('Show garbage collection statistics')\n .action(async () => {\n const spinner = ora('Getting GC status...').start();\n\n try {\n const frameManager = new FrameManager();\n const collector = new IncrementalGarbageCollector(frameManager);\n\n const stats = collector.getStats();\n spinner.stop();\n\n console.log(\n chalk.cyan('\\n\uD83D\uDDD1\uFE0F Incremental Garbage Collection Status\\n')\n );\n\n const table = new Table({\n head: ['Metric', 'Value'],\n colWidths: [25, 20],\n });\n\n table.push(\n ['Total Frames', stats.totalFrames.toString()],\n ['Collected Frames', stats.collectedFrames.toString()],\n ['Collection Cycles', stats.cycleCount.toString()],\n ['Avg Cycle Time', `${stats.avgCycleTime.toFixed(2)}ms`],\n ['Protected Frames', stats.protectedFrames.toString()],\n [\n 'Last Run',\n stats.lastRunTime\n ? new Date(stats.lastRunTime).toLocaleString()\n : 'Never',\n ]\n );\n\n console.log(table.toString());\n\n // Show efficiency metrics\n if (stats.totalFrames > 0) {\n const collectionRate = (\n (stats.collectedFrames / stats.totalFrames) *\n 100\n ).toFixed(1);\n const protectionRate = (\n (stats.protectedFrames / stats.totalFrames) *\n 100\n ).toFixed(1);\n\n console.log('\\n\uD83D\uDCCA Collection Efficiency:');\n console.log(` Collection Rate: ${collectionRate}%`);\n console.log(` Protection Rate: ${protectionRate}%`);\n }\n } catch (error: unknown) {\n spinner.fail('Failed to get GC status');\n logger.error('GC status error', error);\n console.error(\n chalk.red(error instanceof Error ? error.message : 'Unknown error')\n );\n }\n });\n\n // Manual collection command\n gc.command('collect')\n .description('Run manual garbage collection cycle')\n .option(\n '--dry-run',\n 'Show what would be collected without actually collecting'\n )\n .action(async (options) => {\n const spinner = ora('Running garbage collection...').start();\n\n try {\n const frameManager = new FrameManager();\n const collector = new IncrementalGarbageCollector(frameManager);\n\n if (options.dryRun) {\n spinner.text = 'Analyzing collection candidates (dry run)...';\n // TODO: Implement dry run mode\n spinner.succeed('Dry run completed - check logs for details');\n } else {\n await collector.forceCollection();\n const stats = collector.getStats();\n\n spinner.succeed(\n `Collection completed - collected ${stats.collectedFrames} frames`\n );\n\n console.log(chalk.green('\\n\u2705 Manual collection completed'));\n console.log(` Processed: ${stats.totalFrames} frames`);\n console.log(` Collected: ${stats.collectedFrames} frames`);\n console.log(` Protected: ${stats.protectedFrames} frames`);\n }\n } catch (error: unknown) {\n spinner.fail('Collection failed');\n logger.error('GC collection error', error);\n console.error(\n chalk.red(error instanceof Error ? error.message : 'Unknown error')\n );\n }\n });\n\n // Start/stop daemon commands\n gc.command('start')\n .description('Start incremental GC daemon')\n .option('--interval <seconds>', 'Collection interval in seconds', '60')\n .option('--frames-per-cycle <number>', 'Frames to process per cycle', '100')\n .action(async (options) => {\n const spinner = ora('Starting GC daemon...').start();\n\n try {\n const frameManager = new FrameManager();\n const collector = new IncrementalGarbageCollector(frameManager, {\n cycleInterval: parseInt(options.interval) * 1000,\n framesPerCycle: parseInt(options.framesPerCycle),\n });\n\n collector.start();\n\n spinner.succeed('GC daemon started');\n console.log(chalk.green('\\n\uD83D\uDE80 Incremental GC daemon is running'));\n console.log(` Interval: ${options.interval}s`);\n console.log(` Frames per cycle: ${options.framesPerCycle}`);\n console.log('\\nPress Ctrl+C to stop');\n\n // Keep process alive\n process.on('SIGINT', () => {\n console.log('\\n\u23F9\uFE0F Stopping GC daemon...');\n collector.stop();\n process.exit(0);\n });\n\n // Keep the process running\n await new Promise(() => {}); // Run forever\n } catch (error: unknown) {\n spinner.fail('Failed to start GC daemon');\n logger.error('GC start error', error);\n console.error(\n chalk.red(error instanceof Error ? error.message : 'Unknown error')\n );\n }\n });\n\n // Configuration command\n gc.command('config')\n .description('View or update GC configuration')\n .option('--set-interval <seconds>', 'Set collection interval')\n .option('--set-frames-per-cycle <number>', 'Set frames per cycle')\n .option('--set-max-age <days>', 'Set max frame age before collection')\n .action(async (options) => {\n try {\n const frameManager = new FrameManager();\n const collector = new IncrementalGarbageCollector(frameManager);\n\n if (\n options.setInterval ||\n options.setFramesPerCycle ||\n options.setMaxAge\n ) {\n // Update configuration\n const newConfig: any = {};\n if (options.setInterval)\n newConfig.cycleInterval = parseInt(options.setInterval) * 1000;\n if (options.setFramesPerCycle)\n newConfig.framesPerCycle = parseInt(options.setFramesPerCycle);\n if (options.setMaxAge)\n newConfig.maxAge =\n parseInt(options.setMaxAge) * 24 * 60 * 60 * 1000;\n\n collector.updateConfig(newConfig);\n console.log(chalk.green('\u2705 Configuration updated'));\n }\n\n // Show current config\n console.log(chalk.cyan('\\n\u2699\uFE0F Current GC Configuration\\n'));\n console.log('Cycle Interval: 60s');\n console.log('Frames per Cycle: 100');\n console.log('Max Age: 30 days');\n console.log('\\nGenerations:');\n console.log(' Young: < 1 day');\n console.log(' Mature: 1-7 days');\n console.log(' Old: 7-30 days');\n } catch (error: unknown) {\n logger.error('GC config error', error);\n console.error(\n chalk.red(error instanceof Error ? error.message : 'Unknown error')\n );\n }\n });\n\n // Analysis command\n gc.command('analyze')\n .description('Analyze frame distribution and collection opportunities')\n .action(async () => {\n const spinner = ora('Analyzing frames...').start();\n\n try {\n const frameManager = new FrameManager();\n const allFrames = await frameManager.getAllFrames();\n\n if (allFrames.length === 0) {\n spinner.succeed('No frames to analyze');\n return;\n }\n\n // Analyze frame distribution\n const now = Date.now();\n const analysis = {\n total: allFrames.length,\n active: 0,\n closed: 0,\n young: 0,\n mature: 0,\n old: 0,\n withOutputs: 0,\n withoutOutputs: 0,\n rootFrames: 0,\n leafFrames: 0,\n };\n\n for (const frame of allFrames) {\n const age = now - frame.created_at;\n\n // State analysis\n if (frame.state === 'active') analysis.active++;\n else analysis.closed++;\n\n // Age analysis\n if (age < 24 * 60 * 60 * 1000) analysis.young++;\n else if (age < 7 * 24 * 60 * 60 * 1000) analysis.mature++;\n else analysis.old++;\n\n // Output analysis\n if (frame.outputs && Object.keys(frame.outputs).length > 0) {\n analysis.withOutputs++;\n } else {\n analysis.withoutOutputs++;\n }\n\n // Hierarchy analysis\n if (frame.depth === 0) analysis.rootFrames++;\n if (!allFrames.some((f) => f.parent_frame_id === frame.frame_id)) {\n analysis.leafFrames++;\n }\n }\n\n spinner.stop();\n\n console.log(chalk.cyan('\\n\uD83D\uDCCA Frame Distribution Analysis\\n'));\n\n const stateTable = new Table({\n head: ['Category', 'Count', 'Percentage'],\n colWidths: [20, 10, 15],\n });\n\n const pct = (count: number) =>\n `${((count / analysis.total) * 100).toFixed(1)}%`;\n\n stateTable.push(\n ['Active Frames', analysis.active.toString(), pct(analysis.active)],\n ['Closed Frames', analysis.closed.toString(), pct(analysis.closed)],\n ['', '', ''],\n ['Young (< 1 day)', analysis.young.toString(), pct(analysis.young)],\n [\n 'Mature (1-7 days)',\n analysis.mature.toString(),\n pct(analysis.mature),\n ],\n ['Old (> 7 days)', analysis.old.toString(), pct(analysis.old)],\n ['', '', ''],\n [\n 'With Outputs',\n analysis.withOutputs.toString(),\n pct(analysis.withOutputs),\n ],\n [\n 'Without Outputs',\n analysis.withoutOutputs.toString(),\n pct(analysis.withoutOutputs),\n ],\n ['', '', ''],\n [\n 'Root Frames',\n analysis.rootFrames.toString(),\n pct(analysis.rootFrames),\n ],\n [\n 'Leaf Frames',\n analysis.leafFrames.toString(),\n pct(analysis.leafFrames),\n ]\n );\n\n console.log(stateTable.toString());\n\n // Collection recommendations\n console.log(chalk.yellow('\\n\uD83D\uDCA1 Collection Recommendations:\\n'));\n const candidatesForCollection =\n analysis.closed + analysis.withoutOutputs;\n console.log(\n `\u2022 Potential collection candidates: ${candidatesForCollection} frames`\n );\n console.log(\n `\u2022 Estimated space savings: ${((candidatesForCollection / analysis.total) * 100).toFixed(1)}%`\n );\n\n if (analysis.old > 0) {\n console.log(`\u2022 ${analysis.old} old frames ready for collection`);\n }\n if (analysis.withoutOutputs > 0) {\n console.log(\n `\u2022 ${analysis.withoutOutputs} frames without outputs can be collected`\n );\n }\n } catch (error: unknown) {\n spinner.fail('Analysis failed');\n logger.error('GC analysis error', error);\n console.error(\n chalk.red(error instanceof Error ? error.message : 'Unknown error')\n );\n }\n });\n\n return gc;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -6,6 +6,17 @@ import Database from "better-sqlite3";
|
|
|
6
6
|
import { FrameManager } from "../../core/context/frame-manager.js";
|
|
7
7
|
import { PebblesTaskStore } from "../../features/tasks/pebbles-task-store.js";
|
|
8
8
|
import { logger } from "../../core/monitoring/logger.js";
|
|
9
|
+
function getEnv(key, defaultValue) {
|
|
10
|
+
const value = process.env[key];
|
|
11
|
+
if (value === void 0) {
|
|
12
|
+
if (defaultValue !== void 0) return defaultValue;
|
|
13
|
+
throw new Error(`Environment variable ${key} is required`);
|
|
14
|
+
}
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
function getOptionalEnv(key) {
|
|
18
|
+
return process.env[key];
|
|
19
|
+
}
|
|
9
20
|
function createHandoffCommand() {
|
|
10
21
|
const cmd = new Command("handoff");
|
|
11
22
|
cmd.description("Session handoff for continuity between Claude sessions");
|
|
@@ -209,7 +220,7 @@ Generated by stackmemory handoff at ${timestamp}
|
|
|
209
220
|
"last-handoff.md"
|
|
210
221
|
);
|
|
211
222
|
const metaPath = join(
|
|
212
|
-
process.env
|
|
223
|
+
process.env["HOME"] || "~",
|
|
213
224
|
".stackmemory",
|
|
214
225
|
"handoffs",
|
|
215
226
|
"last-handoff-meta.json"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/cli/commands/handoff.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Handoff command - Commits work and generates a prompt for the next session\n */\n\nimport { Command } from 'commander';\nimport { execSync } from 'child_process';\nimport { existsSync, readFileSync, writeFileSync } from 'fs';\nimport { join } from 'path';\nimport Database from 'better-sqlite3';\nimport { FrameManager } from '../../core/context/frame-manager.js';\nimport { PebblesTaskStore } from '../../features/tasks/pebbles-task-store.js';\nimport { logger } from '../../core/monitoring/logger.js';\n\nexport function createHandoffCommand(): Command {\n const cmd = new Command('handoff');\n\n cmd.description('Session handoff for continuity between Claude sessions');\n\n // Default action - capture handoff\n cmd\n .command('capture', { isDefault: true })\n .description('Commit current work and generate a handoff prompt')\n .option('-m, --message <message>', 'Custom commit message')\n .option('--no-commit', 'Skip git commit')\n .option('--copy', 'Copy the handoff prompt to clipboard')\n .action(async (options) => {\n try {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n // 1. Check git status\n let gitStatus = '';\n let hasChanges = false;\n\n try {\n gitStatus = execSync('git status --short', {\n encoding: 'utf-8',\n cwd: projectRoot,\n });\n hasChanges = gitStatus.trim().length > 0;\n } catch (err) {\n console.log('\u26A0\uFE0F Not in a git repository');\n }\n\n // 2. Commit if there are changes and not skipped\n if (hasChanges && options.commit !== false) {\n try {\n // Get current branch\n const currentBranch = execSync('git rev-parse --abbrev-ref HEAD', {\n encoding: 'utf-8',\n cwd: projectRoot,\n }).trim();\n\n // Stage all changes\n execSync('git add -A', { cwd: projectRoot });\n\n // Generate or use custom commit message\n const commitMessage =\n options.message ||\n `chore: handoff checkpoint on ${currentBranch}`;\n\n // Commit\n execSync(`git commit -m \"${commitMessage}\"`, { cwd: projectRoot });\n\n console.log(`\u2705 Committed changes: \"${commitMessage}\"`);\n console.log(` Branch: ${currentBranch}`);\n } catch (err) {\n console.error(\n '\u274C Failed to commit changes:',\n (err as Error).message\n );\n }\n } else if (!hasChanges) {\n console.log('\u2139\uFE0F No changes to commit');\n }\n\n // 3. Gather context for handoff prompt\n let contextSummary = '';\n let tasksSummary = '';\n let recentWork = '';\n\n if (existsSync(dbPath)) {\n const db = new Database(dbPath);\n\n // Get recent context\n const frameManager = new FrameManager(db, 'cli-project');\n const activeFrames = frameManager.getActiveFramePath();\n\n if (activeFrames.length > 0) {\n contextSummary = 'Active context frames:\\n';\n activeFrames.forEach((frame) => {\n contextSummary += ` - ${frame.name} [${frame.type}]\\n`;\n });\n }\n\n // Get task status\n const taskStore = new PebblesTaskStore(projectRoot, db);\n const activeTasks = taskStore.getActiveTasks();\n\n const inProgress = activeTasks.filter(\n (t: any) => t.status === 'in_progress'\n );\n const todo = activeTasks.filter((t: any) => t.status === 'pending');\n const recentlyCompleted = activeTasks\n .filter((t: any) => t.status === 'completed' && t.completed_at)\n .sort(\n (a: any, b: any) => (b.completed_at || 0) - (a.completed_at || 0)\n )\n .slice(0, 3);\n\n if (inProgress.length > 0 || todo.length > 0) {\n tasksSummary = '\\nTasks:\\n';\n\n if (inProgress.length > 0) {\n tasksSummary += 'In Progress:\\n';\n inProgress.forEach((t: any) => {\n const externalId = t.external_refs?.linear?.id;\n tasksSummary += ` - ${t.title}${externalId ? ` [${externalId}]` : ''}\\n`;\n });\n }\n\n if (todo.length > 0) {\n tasksSummary += 'TODO:\\n';\n todo.slice(0, 5).forEach((t: any) => {\n const externalId = t.external_refs?.linear?.id;\n tasksSummary += ` - ${t.title}${externalId ? ` [${externalId}]` : ''}\\n`;\n });\n if (todo.length > 5) {\n tasksSummary += ` ... and ${todo.length - 5} more\\n`;\n }\n }\n }\n\n if (recentlyCompleted.length > 0) {\n recentWork = '\\nRecently Completed:\\n';\n recentlyCompleted.forEach((t: any) => {\n recentWork += ` \u2713 ${t.title}\\n`;\n });\n }\n\n // Get recent events\n const recentEvents = db\n .prepare(\n `\n SELECT event_type as type, payload as data, datetime(ts, 'unixepoch') as time\n FROM events\n ORDER BY ts DESC\n LIMIT 5\n `\n )\n .all() as any[];\n\n if (recentEvents.length > 0) {\n recentWork += '\\nRecent Activity:\\n';\n recentEvents.forEach((event) => {\n const data = JSON.parse(event.data);\n recentWork += ` - ${event.type}: ${data.message || data.name || 'activity'}\\n`;\n });\n }\n\n db.close();\n }\n\n // 4. Get current git info\n let gitInfo = '';\n try {\n const branch = execSync('git rev-parse --abbrev-ref HEAD', {\n encoding: 'utf-8',\n cwd: projectRoot,\n }).trim();\n\n const lastCommit = execSync('git log -1 --oneline', {\n encoding: 'utf-8',\n cwd: projectRoot,\n }).trim();\n\n gitInfo = `\\nGit Status:\\n Branch: ${branch}\\n Last commit: ${lastCommit}\\n`;\n } catch (err) {\n // Ignore git errors\n }\n\n // 5. Check for any blockers or notes\n let notes = '';\n const notesPath = join(projectRoot, '.stackmemory', 'handoff.md');\n if (existsSync(notesPath)) {\n const handoffNotes = readFileSync(notesPath, 'utf-8');\n if (handoffNotes.trim()) {\n notes = `\\nNotes from previous handoff:\\n${handoffNotes}\\n`;\n }\n }\n\n // 6. Generate the handoff prompt\n const timestamp = new Date().toISOString();\n const handoffPrompt = `# Session Handoff - ${timestamp}\n\n## Project: ${projectRoot.split('/').pop()}\n\n${gitInfo}\n${contextSummary}\n${tasksSummary}\n${recentWork}\n${notes}\n\n## Continue from here:\n\n1. Run \\`stackmemory status\\` to check the current state\n2. Review any in-progress tasks above\n3. Check for any uncommitted changes with \\`git status\\`\n4. Resume work on the active context\n\n## Quick Commands:\n- \\`stackmemory context load --recent\\` - Load recent context\n- \\`stackmemory task list --state in_progress\\` - Show in-progress tasks\n- \\`stackmemory linear sync\\` - Sync with Linear if configured\n- \\`stackmemory log recent\\` - View recent activity\n\n---\nGenerated by stackmemory handoff at ${timestamp}\n`;\n\n // 7. Save handoff prompt\n const handoffPath = join(\n projectRoot,\n '.stackmemory',\n 'last-handoff.md'\n );\n writeFileSync(handoffPath, handoffPrompt);\n\n // 8. Display the prompt\n console.log('\\n' + '='.repeat(60));\n console.log(handoffPrompt);\n console.log('='.repeat(60));\n\n // 9. Copy to clipboard if requested\n if (options.copy) {\n try {\n const copyCommand =\n process.platform === 'darwin'\n ? 'pbcopy'\n : process.platform === 'win32'\n ? 'clip'\n : 'xclip -selection clipboard';\n\n execSync(copyCommand, {\n input: handoffPrompt,\n cwd: projectRoot,\n });\n\n console.log('\\n\u2705 Handoff prompt copied to clipboard!');\n } catch (err) {\n console.log('\\n\u26A0\uFE0F Could not copy to clipboard');\n }\n }\n\n console.log(`\\n\uD83D\uDCBE Handoff saved to: ${handoffPath}`);\n console.log('\uD83D\uDCCB Use this prompt when starting your next session');\n } catch (error) {\n logger.error('Handoff command failed', error as Error);\n console.error('\u274C Handoff failed:', (error as Error).message);\n process.exit(1);\n }\n });\n\n // Restore command\n cmd\n .command('restore')\n .description('Restore context from last handoff')\n .option('--no-copy', 'Do not copy prompt to clipboard')\n .action(async (options) => {\n try {\n const projectRoot = process.cwd();\n const handoffPath = join(\n projectRoot,\n '.stackmemory',\n 'last-handoff.md'\n );\n const metaPath = join(\n process.env.HOME || '~',\n '.stackmemory',\n 'handoffs',\n 'last-handoff-meta.json'\n );\n\n if (!existsSync(handoffPath)) {\n console.log('\u274C No handoff found in this project');\n console.log('\uD83D\uDCA1 Run \"stackmemory handoff\" to create one');\n return;\n }\n\n // Read handoff prompt\n const handoffPrompt = readFileSync(handoffPath, 'utf-8');\n\n // Display the prompt\n console.log('\\n' + '='.repeat(60));\n console.log('\uD83D\uDCCB RESTORED HANDOFF');\n console.log('='.repeat(60));\n console.log(handoffPrompt);\n console.log('='.repeat(60));\n\n // Check for metadata\n if (existsSync(metaPath)) {\n const metadata = JSON.parse(readFileSync(metaPath, 'utf-8'));\n console.log('\\n\uD83D\uDCCA Session Metadata:');\n console.log(` Timestamp: ${metadata.timestamp}`);\n console.log(` Reason: ${metadata.reason}`);\n console.log(` Duration: ${metadata.session_duration}s`);\n console.log(` Command: ${metadata.command}`);\n }\n\n // Check current git status\n try {\n const gitStatus = execSync('git status --short', {\n encoding: 'utf-8',\n }).trim();\n if (gitStatus) {\n console.log('\\n\u26A0\uFE0F Current uncommitted changes:');\n console.log(gitStatus);\n }\n } catch (err) {\n // Not a git repo\n }\n\n // Copy to clipboard unless disabled\n if (options.copy !== false) {\n try {\n const copyCommand =\n process.platform === 'darwin'\n ? 'pbcopy'\n : process.platform === 'win32'\n ? 'clip'\n : 'xclip -selection clipboard';\n\n execSync(copyCommand, {\n input: handoffPrompt,\n cwd: projectRoot,\n });\n\n console.log('\\n\u2705 Handoff prompt copied to clipboard!');\n } catch (err) {\n console.log('\\n\u26A0\uFE0F Could not copy to clipboard');\n }\n }\n\n console.log('\\n\uD83D\uDE80 Ready to continue where you left off!');\n } catch (error) {\n logger.error('Handoff restore failed', error as Error);\n console.error('\u274C Restore failed:', (error as Error).message);\n process.exit(1);\n }\n });\n\n // Auto command - enable auto-capture\n cmd\n .command('auto')\n .description('Enable auto-capture on session termination')\n .option('--command <command>', 'Command to wrap with auto-handoff')\n .action(async (options) => {\n const scriptPath = join(\n __dirname,\n '..',\n '..',\n '..',\n 'scripts',\n 'stackmemory-auto-handoff.sh'\n );\n\n if (!existsSync(scriptPath)) {\n console.error('\u274C Auto-handoff script not found');\n console.log('\uD83D\uDCE6 Please ensure StackMemory is properly installed');\n return;\n }\n\n console.log('\uD83D\uDEE1\uFE0F StackMemory Auto-Handoff');\n console.log('\u2500'.repeat(50));\n\n if (options.command) {\n // Wrap specific command\n console.log(`Wrapping command: ${options.command}`);\n execSync(`${scriptPath} ${options.command}`, {\n stdio: 'inherit',\n env: { ...process.env, AUTO_CAPTURE_ON_EXIT: 'true' },\n });\n } else {\n // Interactive mode\n console.log('To enable auto-handoff for your current session:');\n console.log('');\n console.log(' For bash/zsh:');\n console.log(` source <(${scriptPath} --shell)`);\n console.log('');\n console.log(' Or wrap a command:');\n console.log(` ${scriptPath} claude`);\n console.log(` ${scriptPath} npm run dev`);\n console.log('');\n console.log(' Add to your shell profile for permanent setup:');\n console.log(\n ` echo 'alias claude=\"${scriptPath} claude\"' >> ~/.bashrc`\n );\n }\n });\n\n return cmd;\n}\n"],
|
|
5
|
-
"mappings": "AAIA,SAAS,eAAe;AACxB,SAAS,gBAAgB;AACzB,SAAS,YAAY,cAAc,qBAAqB;AACxD,SAAS,YAAY;AACrB,OAAO,cAAc;AACrB,SAAS,oBAAoB;AAC7B,SAAS,wBAAwB;AACjC,SAAS,cAAc;
|
|
4
|
+
"sourcesContent": ["/**\n * Handoff command - Commits work and generates a prompt for the next session\n */\n\nimport { Command } from 'commander';\nimport { execSync } from 'child_process';\nimport { existsSync, readFileSync, writeFileSync } from 'fs';\nimport { join } from 'path';\nimport Database from 'better-sqlite3';\nimport { FrameManager } from '../../core/context/frame-manager.js';\nimport { PebblesTaskStore } from '../../features/tasks/pebbles-task-store.js';\nimport { logger } from '../../core/monitoring/logger.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 createHandoffCommand(): Command {\n const cmd = new Command('handoff');\n\n cmd.description('Session handoff for continuity between Claude sessions');\n\n // Default action - capture handoff\n cmd\n .command('capture', { isDefault: true })\n .description('Commit current work and generate a handoff prompt')\n .option('-m, --message <message>', 'Custom commit message')\n .option('--no-commit', 'Skip git commit')\n .option('--copy', 'Copy the handoff prompt to clipboard')\n .action(async (options) => {\n try {\n const projectRoot = process.cwd();\n const dbPath = join(projectRoot, '.stackmemory', 'context.db');\n\n // 1. Check git status\n let gitStatus = '';\n let hasChanges = false;\n\n try {\n gitStatus = execSync('git status --short', {\n encoding: 'utf-8',\n cwd: projectRoot,\n });\n hasChanges = gitStatus.trim().length > 0;\n } catch (err: unknown) {\n console.log('\u26A0\uFE0F Not in a git repository');\n }\n\n // 2. Commit if there are changes and not skipped\n if (hasChanges && options.commit !== false) {\n try {\n // Get current branch\n const currentBranch = execSync('git rev-parse --abbrev-ref HEAD', {\n encoding: 'utf-8',\n cwd: projectRoot,\n }).trim();\n\n // Stage all changes\n execSync('git add -A', { cwd: projectRoot });\n\n // Generate or use custom commit message\n const commitMessage =\n options.message ||\n `chore: handoff checkpoint on ${currentBranch}`;\n\n // Commit\n execSync(`git commit -m \"${commitMessage}\"`, { cwd: projectRoot });\n\n console.log(`\u2705 Committed changes: \"${commitMessage}\"`);\n console.log(` Branch: ${currentBranch}`);\n } catch (err: unknown) {\n console.error(\n '\u274C Failed to commit changes:',\n (err as Error).message\n );\n }\n } else if (!hasChanges) {\n console.log('\u2139\uFE0F No changes to commit');\n }\n\n // 3. Gather context for handoff prompt\n let contextSummary = '';\n let tasksSummary = '';\n let recentWork = '';\n\n if (existsSync(dbPath)) {\n const db = new Database(dbPath);\n\n // Get recent context\n const frameManager = new FrameManager(db, 'cli-project');\n const activeFrames = frameManager.getActiveFramePath();\n\n if (activeFrames.length > 0) {\n contextSummary = 'Active context frames:\\n';\n activeFrames.forEach((frame) => {\n contextSummary += ` - ${frame.name} [${frame.type}]\\n`;\n });\n }\n\n // Get task status\n const taskStore = new PebblesTaskStore(projectRoot, db);\n const activeTasks = taskStore.getActiveTasks();\n\n const inProgress = activeTasks.filter(\n (t: any) => t.status === 'in_progress'\n );\n const todo = activeTasks.filter((t: any) => t.status === 'pending');\n const recentlyCompleted = activeTasks\n .filter((t: any) => t.status === 'completed' && t.completed_at)\n .sort(\n (a: any, b: any) => (b.completed_at || 0) - (a.completed_at || 0)\n )\n .slice(0, 3);\n\n if (inProgress.length > 0 || todo.length > 0) {\n tasksSummary = '\\nTasks:\\n';\n\n if (inProgress.length > 0) {\n tasksSummary += 'In Progress:\\n';\n inProgress.forEach((t: any) => {\n const externalId = t.external_refs?.linear?.id;\n tasksSummary += ` - ${t.title}${externalId ? ` [${externalId}]` : ''}\\n`;\n });\n }\n\n if (todo.length > 0) {\n tasksSummary += 'TODO:\\n';\n todo.slice(0, 5).forEach((t: any) => {\n const externalId = t.external_refs?.linear?.id;\n tasksSummary += ` - ${t.title}${externalId ? ` [${externalId}]` : ''}\\n`;\n });\n if (todo.length > 5) {\n tasksSummary += ` ... and ${todo.length - 5} more\\n`;\n }\n }\n }\n\n if (recentlyCompleted.length > 0) {\n recentWork = '\\nRecently Completed:\\n';\n recentlyCompleted.forEach((t: any) => {\n recentWork += ` \u2713 ${t.title}\\n`;\n });\n }\n\n // Get recent events\n const recentEvents = db\n .prepare(\n `\n SELECT event_type as type, payload as data, datetime(ts, 'unixepoch') as time\n FROM events\n ORDER BY ts DESC\n LIMIT 5\n `\n )\n .all() as any[];\n\n if (recentEvents.length > 0) {\n recentWork += '\\nRecent Activity:\\n';\n recentEvents.forEach((event) => {\n const data = JSON.parse(event.data);\n recentWork += ` - ${event.type}: ${data.message || data.name || 'activity'}\\n`;\n });\n }\n\n db.close();\n }\n\n // 4. Get current git info\n let gitInfo = '';\n try {\n const branch = execSync('git rev-parse --abbrev-ref HEAD', {\n encoding: 'utf-8',\n cwd: projectRoot,\n }).trim();\n\n const lastCommit = execSync('git log -1 --oneline', {\n encoding: 'utf-8',\n cwd: projectRoot,\n }).trim();\n\n gitInfo = `\\nGit Status:\\n Branch: ${branch}\\n Last commit: ${lastCommit}\\n`;\n } catch (err: unknown) {\n // Ignore git errors\n }\n\n // 5. Check for any blockers or notes\n let notes = '';\n const notesPath = join(projectRoot, '.stackmemory', 'handoff.md');\n if (existsSync(notesPath)) {\n const handoffNotes = readFileSync(notesPath, 'utf-8');\n if (handoffNotes.trim()) {\n notes = `\\nNotes from previous handoff:\\n${handoffNotes}\\n`;\n }\n }\n\n // 6. Generate the handoff prompt\n const timestamp = new Date().toISOString();\n const handoffPrompt = `# Session Handoff - ${timestamp}\n\n## Project: ${projectRoot.split('/').pop()}\n\n${gitInfo}\n${contextSummary}\n${tasksSummary}\n${recentWork}\n${notes}\n\n## Continue from here:\n\n1. Run \\`stackmemory status\\` to check the current state\n2. Review any in-progress tasks above\n3. Check for any uncommitted changes with \\`git status\\`\n4. Resume work on the active context\n\n## Quick Commands:\n- \\`stackmemory context load --recent\\` - Load recent context\n- \\`stackmemory task list --state in_progress\\` - Show in-progress tasks\n- \\`stackmemory linear sync\\` - Sync with Linear if configured\n- \\`stackmemory log recent\\` - View recent activity\n\n---\nGenerated by stackmemory handoff at ${timestamp}\n`;\n\n // 7. Save handoff prompt\n const handoffPath = join(\n projectRoot,\n '.stackmemory',\n 'last-handoff.md'\n );\n writeFileSync(handoffPath, handoffPrompt);\n\n // 8. Display the prompt\n console.log('\\n' + '='.repeat(60));\n console.log(handoffPrompt);\n console.log('='.repeat(60));\n\n // 9. Copy to clipboard if requested\n if (options.copy) {\n try {\n const copyCommand =\n process.platform === 'darwin'\n ? 'pbcopy'\n : process.platform === 'win32'\n ? 'clip'\n : 'xclip -selection clipboard';\n\n execSync(copyCommand, {\n input: handoffPrompt,\n cwd: projectRoot,\n });\n\n console.log('\\n\u2705 Handoff prompt copied to clipboard!');\n } catch (err: unknown) {\n console.log('\\n\u26A0\uFE0F Could not copy to clipboard');\n }\n }\n\n console.log(`\\n\uD83D\uDCBE Handoff saved to: ${handoffPath}`);\n console.log('\uD83D\uDCCB Use this prompt when starting your next session');\n } catch (error: unknown) {\n logger.error('Handoff command failed', error as Error);\n console.error('\u274C Handoff failed:', (error as Error).message);\n process.exit(1);\n }\n });\n\n // Restore command\n cmd\n .command('restore')\n .description('Restore context from last handoff')\n .option('--no-copy', 'Do not copy prompt to clipboard')\n .action(async (options) => {\n try {\n const projectRoot = process.cwd();\n const handoffPath = join(\n projectRoot,\n '.stackmemory',\n 'last-handoff.md'\n );\n const metaPath = join(\n process.env['HOME'] || '~',\n '.stackmemory',\n 'handoffs',\n 'last-handoff-meta.json'\n );\n\n if (!existsSync(handoffPath)) {\n console.log('\u274C No handoff found in this project');\n console.log('\uD83D\uDCA1 Run \"stackmemory handoff\" to create one');\n return;\n }\n\n // Read handoff prompt\n const handoffPrompt = readFileSync(handoffPath, 'utf-8');\n\n // Display the prompt\n console.log('\\n' + '='.repeat(60));\n console.log('\uD83D\uDCCB RESTORED HANDOFF');\n console.log('='.repeat(60));\n console.log(handoffPrompt);\n console.log('='.repeat(60));\n\n // Check for metadata\n if (existsSync(metaPath)) {\n const metadata = JSON.parse(readFileSync(metaPath, 'utf-8'));\n console.log('\\n\uD83D\uDCCA Session Metadata:');\n console.log(` Timestamp: ${metadata.timestamp}`);\n console.log(` Reason: ${metadata.reason}`);\n console.log(` Duration: ${metadata.session_duration}s`);\n console.log(` Command: ${metadata.command}`);\n }\n\n // Check current git status\n try {\n const gitStatus = execSync('git status --short', {\n encoding: 'utf-8',\n }).trim();\n if (gitStatus) {\n console.log('\\n\u26A0\uFE0F Current uncommitted changes:');\n console.log(gitStatus);\n }\n } catch (err: unknown) {\n // Not a git repo\n }\n\n // Copy to clipboard unless disabled\n if (options.copy !== false) {\n try {\n const copyCommand =\n process.platform === 'darwin'\n ? 'pbcopy'\n : process.platform === 'win32'\n ? 'clip'\n : 'xclip -selection clipboard';\n\n execSync(copyCommand, {\n input: handoffPrompt,\n cwd: projectRoot,\n });\n\n console.log('\\n\u2705 Handoff prompt copied to clipboard!');\n } catch (err: unknown) {\n console.log('\\n\u26A0\uFE0F Could not copy to clipboard');\n }\n }\n\n console.log('\\n\uD83D\uDE80 Ready to continue where you left off!');\n } catch (error: unknown) {\n logger.error('Handoff restore failed', error as Error);\n console.error('\u274C Restore failed:', (error as Error).message);\n process.exit(1);\n }\n });\n\n // Auto command - enable auto-capture\n cmd\n .command('auto')\n .description('Enable auto-capture on session termination')\n .option('--command <command>', 'Command to wrap with auto-handoff')\n .action(async (options) => {\n const scriptPath = join(\n __dirname,\n '..',\n '..',\n '..',\n 'scripts',\n 'stackmemory-auto-handoff.sh'\n );\n\n if (!existsSync(scriptPath)) {\n console.error('\u274C Auto-handoff script not found');\n console.log('\uD83D\uDCE6 Please ensure StackMemory is properly installed');\n return;\n }\n\n console.log('\uD83D\uDEE1\uFE0F StackMemory Auto-Handoff');\n console.log('\u2500'.repeat(50));\n\n if (options.command) {\n // Wrap specific command\n console.log(`Wrapping command: ${options.command}`);\n execSync(`${scriptPath} ${options.command}`, {\n stdio: 'inherit',\n env: { ...process.env, AUTO_CAPTURE_ON_EXIT: 'true' },\n });\n } else {\n // Interactive mode\n console.log('To enable auto-handoff for your current session:');\n console.log('');\n console.log(' For bash/zsh:');\n console.log(` source <(${scriptPath} --shell)`);\n console.log('');\n console.log(' Or wrap a command:');\n console.log(` ${scriptPath} claude`);\n console.log(` ${scriptPath} npm run dev`);\n console.log('');\n console.log(' Add to your shell profile for permanent setup:');\n console.log(\n ` echo 'alias claude=\"${scriptPath} claude\"' >> ~/.bashrc`\n );\n }\n });\n\n return cmd;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|