@stackmemoryai/stackmemory 0.3.7 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/recursive-context-manager.js +582 -0
- package/dist/core/context/recursive-context-manager.js.map +7 -0
- 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/execution/parallel-executor.js +254 -0
- package/dist/core/execution/parallel-executor.js.map +7 -0
- 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/anthropic/client.js +259 -0
- package/dist/integrations/anthropic/client.js.map +7 -0
- package/dist/integrations/claude-code/subagent-client.js +404 -0
- package/dist/integrations/claude-code/subagent-client.js.map +7 -0
- 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 +101 -2
- package/dist/skills/claude-skills.js.map +2 -2
- package/dist/skills/dashboard-launcher.js.map +2 -2
- package/dist/skills/recursive-agent-orchestrator.js +559 -0
- package/dist/skills/recursive-agent-orchestrator.js.map +7 -0
- package/dist/skills/repo-ingestion-skill.js.map +2 -2
- package/dist/skills/security-secrets-scanner.js +265 -0
- package/dist/skills/security-secrets-scanner.js.map +7 -0
- 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/session.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Session Management CLI Commands\n * Provides commands for managing StackMemory sessions\n */\n\nimport { Command } from 'commander';\nimport { sessionManager } from '../../core/session/index.js';\nimport { logger } from '../../core/monitoring/logger.js';\nimport chalk from 'chalk';\n\nexport function createSessionCommands(): Command {\n const sessionCommand = new Command('session')\n
|
|
5
|
-
"mappings": "AAKA,SAAS,eAAe;AACxB,SAAS,sBAAsB;AAC/B,SAAS,cAAc;AACvB,OAAO,WAAW;AAEX,SAAS,wBAAiC;AAC/C,QAAM,iBAAiB,IAAI,QAAQ,SAAS,
|
|
4
|
+
"sourcesContent": ["/**\n * Session Management CLI Commands\n * Provides commands for managing StackMemory sessions\n */\n\nimport { Command } from 'commander';\nimport { sessionManager } from '../../core/session/index.js';\nimport { logger } from '../../core/monitoring/logger.js';\nimport chalk from 'chalk';\n\nexport function createSessionCommands(): Command {\n const sessionCommand = new Command('session').description(\n 'Manage StackMemory sessions'\n );\n\n sessionCommand\n .command('list')\n .description('List all sessions')\n .option('--project', 'Show only sessions for current project')\n .option('--active', 'Show only active sessions')\n .option('--all', 'Show all sessions including closed')\n .action(async (options) => {\n try {\n await sessionManager.initialize();\n\n const filter: any = {};\n if (options.project) {\n const projectHash = await getProjectHash();\n filter.projectId = projectHash;\n }\n if (options.active && !options.all) {\n filter.state = 'active';\n }\n\n const sessions = await sessionManager.listSessions(filter);\n\n if (sessions.length === 0) {\n console.log('No sessions found');\n return;\n }\n\n console.log(chalk.bold('\\n\uD83D\uDCCB StackMemory Sessions:\\n'));\n\n sessions.forEach((session) => {\n const age = formatAge(Date.now() - session.lastActiveAt);\n const status =\n session.state === 'active'\n ? chalk.green('\u25CF')\n : session.state === 'suspended'\n ? chalk.yellow('\u25CF')\n : chalk.gray('\u25CF');\n\n console.log(`${status} ${chalk.bold(session.sessionId.slice(0, 8))}`);\n console.log(` Project: ${session.projectId}`);\n if (session.branch) {\n console.log(` Branch: ${session.branch}`);\n }\n console.log(` State: ${session.state}`);\n console.log(` Last active: ${age} ago`);\n console.log('');\n });\n\n console.log(chalk.gray(`Total: ${sessions.length} session(s)`));\n } catch (error: unknown) {\n logger.error('Failed to list sessions', error as Error);\n console.error('\u274C Failed to list sessions:', (error as Error).message);\n process.exit(1);\n }\n });\n\n sessionCommand\n .command('current')\n .description('Show current session information')\n .action(async () => {\n try {\n await sessionManager.initialize();\n const session = sessionManager.getCurrentSession();\n\n if (!session) {\n console.log('No active session');\n return;\n }\n\n const duration = formatDuration(Date.now() - session.startedAt);\n\n console.log(chalk.bold('\\n\uD83D\uDD0D Current Session:\\n'));\n console.log(`Session ID: ${chalk.cyan(session.sessionId)}`);\n console.log(`Run ID: ${session.runId}`);\n console.log(`Project: ${session.projectId}`);\n if (session.branch) {\n console.log(`Branch: ${session.branch}`);\n }\n console.log(`State: ${session.state}`);\n console.log(`Duration: ${duration}`);\n\n if (session.metadata.user) {\n console.log(`User: ${session.metadata.user}`);\n }\n if (session.metadata.tags && session.metadata.tags.length > 0) {\n console.log(`Tags: ${session.metadata.tags.join(', ')}`);\n }\n } catch (error: unknown) {\n logger.error('Failed to show current session', error as Error);\n console.error(\n '\u274C Failed to show current session:',\n (error as Error).message\n );\n process.exit(1);\n }\n });\n\n sessionCommand\n .command('switch <sessionId>')\n .description('Switch to a different session')\n .action(async (sessionId) => {\n try {\n await sessionManager.initialize();\n\n // Suspend current session\n const current = sessionManager.getCurrentSession();\n if (current) {\n await sessionManager.suspendSession();\n console.log(`Suspended session: ${current.sessionId.slice(0, 8)}`);\n }\n\n // Resume target session\n const session = await sessionManager.resumeSession(sessionId);\n console.log(\n chalk.green(\n `\u2705 Switched to session: ${session.sessionId.slice(0, 8)}`\n )\n );\n console.log(` Project: ${session.projectId}`);\n if (session.branch) {\n console.log(` Branch: ${session.branch}`);\n }\n } catch (error: unknown) {\n logger.error('Failed to switch session', error as Error);\n console.error('\u274C Failed to switch session:', (error as Error).message);\n process.exit(1);\n }\n });\n\n sessionCommand\n .command('suspend [sessionId]')\n .description('Suspend a session (current if not specified)')\n .action(async (sessionId) => {\n try {\n await sessionManager.initialize();\n await sessionManager.suspendSession(sessionId);\n\n const id = sessionId || sessionManager.getCurrentSession()?.sessionId;\n console.log(chalk.yellow(`\u23F8\uFE0F Suspended session: ${id?.slice(0, 8)}`));\n } catch (error: unknown) {\n logger.error('Failed to suspend session', error as Error);\n console.error(\n '\u274C Failed to suspend session:',\n (error as Error).message\n );\n process.exit(1);\n }\n });\n\n sessionCommand\n .command('resume <sessionId>')\n .description('Resume a suspended session')\n .action(async (sessionId) => {\n try {\n await sessionManager.initialize();\n const session = await sessionManager.resumeSession(sessionId);\n\n console.log(\n chalk.green(`\u25B6\uFE0F Resumed session: ${session.sessionId.slice(0, 8)}`)\n );\n console.log(` Project: ${session.projectId}`);\n if (session.branch) {\n console.log(` Branch: ${session.branch}`);\n }\n } catch (error: unknown) {\n logger.error('Failed to resume session', error as Error);\n console.error('\u274C Failed to resume session:', (error as Error).message);\n process.exit(1);\n }\n });\n\n sessionCommand\n .command('merge <sourceId> <targetId>')\n .description('Merge two sessions')\n .action(async (sourceId, targetId) => {\n try {\n await sessionManager.initialize();\n const merged = await sessionManager.mergeSessions(sourceId, targetId);\n\n console.log(chalk.green(`\u2705 Merged sessions successfully`));\n console.log(` Target: ${merged.sessionId.slice(0, 8)}`);\n console.log(` Source ${sourceId.slice(0, 8)} has been closed`);\n } catch (error: unknown) {\n logger.error('Failed to merge sessions', error as Error);\n console.error('\u274C Failed to merge sessions:', (error as Error).message);\n process.exit(1);\n }\n });\n\n sessionCommand\n .command('cleanup')\n .description('Clean up old closed sessions')\n .option('--days <days>', 'Remove sessions older than N days', '30')\n .action(async (options) => {\n try {\n await sessionManager.initialize();\n\n const days = parseInt(options.days);\n const maxAge = days * 24 * 60 * 60 * 1000;\n const cleaned = await sessionManager.cleanupStaleSessions(maxAge);\n\n console.log(chalk.green(`\u2705 Cleaned up ${cleaned} old session(s)`));\n } catch (error: unknown) {\n logger.error('Failed to cleanup sessions', error as Error);\n console.error(\n '\u274C Failed to cleanup sessions:',\n (error as Error).message\n );\n process.exit(1);\n }\n });\n\n return sessionCommand;\n}\n\n// Helper functions\nasync function getProjectHash(): Promise<string> {\n const crypto = await import('crypto');\n const cwd = process.cwd();\n const hash = crypto.createHash('sha256');\n hash.update(cwd);\n return hash.digest('hex').substring(0, 12);\n}\n\nfunction formatAge(ms: number): string {\n const seconds = Math.floor(ms / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (days > 0) return `${days}d`;\n if (hours > 0) return `${hours}h`;\n if (minutes > 0) return `${minutes}m`;\n return `${seconds}s`;\n}\n\nfunction formatDuration(ms: number): string {\n const seconds = Math.floor(ms / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n\n const h = hours;\n const m = minutes % 60;\n const s = seconds % 60;\n\n if (h > 0) return `${h}h ${m}m ${s}s`;\n if (m > 0) return `${m}m ${s}s`;\n return `${s}s`;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
import { Command } from "commander";
|
|
3
3
|
import chalk from "chalk";
|
|
4
4
|
import ora from "ora";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
ClaudeSkillsManager
|
|
7
|
+
} from "../../skills/claude-skills.js";
|
|
6
8
|
import { DualStackManager } from "../../core/context/dual-stack-manager.js";
|
|
7
9
|
import { FrameHandoffManager } from "../../core/context/frame-handoff-manager.js";
|
|
8
10
|
import { ContextRetriever } from "../../core/retrieval/context-retriever.js";
|
|
@@ -47,17 +49,27 @@ async function initializeSkillContext() {
|
|
|
47
49
|
};
|
|
48
50
|
}
|
|
49
51
|
function createSkillsCommand() {
|
|
50
|
-
const skillsCmd = new Command("skills").description(
|
|
51
|
-
|
|
52
|
+
const skillsCmd = new Command("skills").description(
|
|
53
|
+
"Execute Claude skills for enhanced workflow"
|
|
54
|
+
);
|
|
55
|
+
skillsCmd.command("handoff <targetUser> <message>").description("Streamline frame handoffs between team members").option(
|
|
56
|
+
"-p, --priority <level>",
|
|
57
|
+
"Set priority (low, medium, high, critical)",
|
|
58
|
+
"medium"
|
|
59
|
+
).option("-f, --frames <frames...>", "Specific frames to handoff").option("--no-auto-detect", "Disable auto-detection of frames").action(async (targetUser, message, options) => {
|
|
52
60
|
const spinner = ora("Initiating handoff...").start();
|
|
53
61
|
try {
|
|
54
62
|
const context = await initializeSkillContext();
|
|
55
63
|
const skillsManager = new ClaudeSkillsManager(context);
|
|
56
|
-
const result = await skillsManager.executeSkill(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
64
|
+
const result = await skillsManager.executeSkill(
|
|
65
|
+
"handoff",
|
|
66
|
+
[targetUser, message],
|
|
67
|
+
{
|
|
68
|
+
priority: options.priority,
|
|
69
|
+
frames: options.frames,
|
|
70
|
+
autoDetect: options.autoDetect !== false
|
|
71
|
+
}
|
|
72
|
+
);
|
|
61
73
|
spinner.stop();
|
|
62
74
|
if (result.success) {
|
|
63
75
|
console.log(chalk.green("\u2713"), result.message);
|
|
@@ -89,10 +101,14 @@ function createSkillsCommand() {
|
|
|
89
101
|
try {
|
|
90
102
|
const context = await initializeSkillContext();
|
|
91
103
|
const skillsManager = new ClaudeSkillsManager(context);
|
|
92
|
-
const result = await skillsManager.executeSkill(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
104
|
+
const result = await skillsManager.executeSkill(
|
|
105
|
+
"checkpoint",
|
|
106
|
+
["create", description],
|
|
107
|
+
{
|
|
108
|
+
includeFiles: options.files,
|
|
109
|
+
autoDetectRisky: options.autoDetectRisky
|
|
110
|
+
}
|
|
111
|
+
);
|
|
96
112
|
spinner.stop();
|
|
97
113
|
if (result.success) {
|
|
98
114
|
console.log(chalk.green("\u2713"), result.message);
|
|
@@ -117,7 +133,10 @@ function createSkillsCommand() {
|
|
|
117
133
|
try {
|
|
118
134
|
const context = await initializeSkillContext();
|
|
119
135
|
const skillsManager = new ClaudeSkillsManager(context);
|
|
120
|
-
const result = await skillsManager.executeSkill("checkpoint", [
|
|
136
|
+
const result = await skillsManager.executeSkill("checkpoint", [
|
|
137
|
+
"restore",
|
|
138
|
+
checkpointId
|
|
139
|
+
]);
|
|
121
140
|
spinner.stop();
|
|
122
141
|
if (result.success) {
|
|
123
142
|
console.log(chalk.green("\u2713"), result.message);
|
|
@@ -141,10 +160,14 @@ function createSkillsCommand() {
|
|
|
141
160
|
try {
|
|
142
161
|
const context = await initializeSkillContext();
|
|
143
162
|
const skillsManager = new ClaudeSkillsManager(context);
|
|
144
|
-
const result = await skillsManager.executeSkill(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
163
|
+
const result = await skillsManager.executeSkill(
|
|
164
|
+
"checkpoint",
|
|
165
|
+
["list"],
|
|
166
|
+
{
|
|
167
|
+
limit: parseInt(options.limit),
|
|
168
|
+
since: options.since ? new Date(options.since) : void 0
|
|
169
|
+
}
|
|
170
|
+
);
|
|
148
171
|
spinner.stop();
|
|
149
172
|
if (result.success) {
|
|
150
173
|
console.log(chalk.cyan("Available Checkpoints:\n"));
|
|
@@ -153,8 +176,10 @@ function createSkillsCommand() {
|
|
|
153
176
|
const riskIndicator = cp.risky ? chalk.yellow(" [RISKY]") : "";
|
|
154
177
|
console.log(`${chalk.bold(cp.id)}${riskIndicator}`);
|
|
155
178
|
console.log(` ${cp.description}`);
|
|
156
|
-
console.log(
|
|
157
|
-
`)
|
|
179
|
+
console.log(
|
|
180
|
+
chalk.gray(` ${cp.timestamp} (${cp.frameCount} frames)
|
|
181
|
+
`)
|
|
182
|
+
);
|
|
158
183
|
});
|
|
159
184
|
} else {
|
|
160
185
|
console.log(chalk.gray("No checkpoints found"));
|
|
@@ -174,7 +199,11 @@ function createSkillsCommand() {
|
|
|
174
199
|
try {
|
|
175
200
|
const context = await initializeSkillContext();
|
|
176
201
|
const skillsManager = new ClaudeSkillsManager(context);
|
|
177
|
-
const result = await skillsManager.executeSkill("checkpoint", [
|
|
202
|
+
const result = await skillsManager.executeSkill("checkpoint", [
|
|
203
|
+
"diff",
|
|
204
|
+
checkpoint1,
|
|
205
|
+
checkpoint2
|
|
206
|
+
]);
|
|
178
207
|
spinner.stop();
|
|
179
208
|
if (result.success) {
|
|
180
209
|
console.log(chalk.cyan("Checkpoint Diff:\n"));
|
|
@@ -195,7 +224,11 @@ function createSkillsCommand() {
|
|
|
195
224
|
process.exit(1);
|
|
196
225
|
}
|
|
197
226
|
});
|
|
198
|
-
skillsCmd.command("dig <query>").description("Deep historical context retrieval").option(
|
|
227
|
+
skillsCmd.command("dig <query>").description("Deep historical context retrieval").option(
|
|
228
|
+
"-d, --depth <depth>",
|
|
229
|
+
"Search depth (e.g., 30days, 6months, all)",
|
|
230
|
+
"30days"
|
|
231
|
+
).option("--patterns", "Extract patterns from results").option("--decisions", "Extract key decisions").option("--timeline", "Generate activity timeline").action(async (query, options) => {
|
|
199
232
|
const spinner = ora("Digging through context...").start();
|
|
200
233
|
try {
|
|
201
234
|
const context = await initializeSkillContext();
|
|
@@ -210,15 +243,21 @@ function createSkillsCommand() {
|
|
|
210
243
|
if (result.success) {
|
|
211
244
|
console.log(chalk.green("\u2713"), result.message);
|
|
212
245
|
if (result.data) {
|
|
213
|
-
console.log(
|
|
214
|
-
|
|
246
|
+
console.log(
|
|
247
|
+
chalk.cyan(
|
|
248
|
+
`
|
|
249
|
+
Searched ${result.data.timeRange.from} to ${result.data.timeRange.to}`
|
|
250
|
+
)
|
|
251
|
+
);
|
|
215
252
|
if (result.data.summary) {
|
|
216
253
|
console.log("\n" + result.data.summary);
|
|
217
254
|
} else {
|
|
218
255
|
if (result.data.topResults?.length > 0) {
|
|
219
256
|
console.log(chalk.cyan("\nTop Results:"));
|
|
220
257
|
result.data.topResults.forEach((r) => {
|
|
221
|
-
console.log(
|
|
258
|
+
console.log(
|
|
259
|
+
` ${chalk.yellow(`[${r.score.toFixed(2)}]`)} ${r.summary}`
|
|
260
|
+
);
|
|
222
261
|
});
|
|
223
262
|
}
|
|
224
263
|
if (result.data.patterns?.length > 0) {
|
|
@@ -230,7 +269,9 @@ Searched ${result.data.timeRange.from} to ${result.data.timeRange.to}`));
|
|
|
230
269
|
if (result.data.decisions?.length > 0) {
|
|
231
270
|
console.log(chalk.cyan("\nKey Decisions:"));
|
|
232
271
|
result.data.decisions.slice(0, 5).forEach((d) => {
|
|
233
|
-
console.log(
|
|
272
|
+
console.log(
|
|
273
|
+
` ${chalk.gray(new Date(d.timestamp).toLocaleDateString())}: ${d.decision}`
|
|
274
|
+
);
|
|
234
275
|
});
|
|
235
276
|
}
|
|
236
277
|
if (result.data.timeline?.length > 0) {
|
|
@@ -258,10 +299,14 @@ Searched ${result.data.timeRange.from} to ${result.data.timeRange.to}`));
|
|
|
258
299
|
console.log(skillsManager.getSkillHelp(skill));
|
|
259
300
|
} else {
|
|
260
301
|
console.log(chalk.cyan("Available Claude Skills:\n"));
|
|
261
|
-
console.log(
|
|
302
|
+
console.log(
|
|
303
|
+
" handoff - Streamline frame handoffs between team members"
|
|
304
|
+
);
|
|
262
305
|
console.log(" checkpoint - Create and manage recovery points");
|
|
263
306
|
console.log(" dig - Deep historical context retrieval\n");
|
|
264
|
-
console.log(
|
|
307
|
+
console.log(
|
|
308
|
+
'Use "stackmemory skills help <skill>" for detailed help on each skill'
|
|
309
|
+
);
|
|
265
310
|
}
|
|
266
311
|
await context.database.disconnect();
|
|
267
312
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/cli/commands/skills.ts"],
|
|
4
|
-
"sourcesContent": ["#!/usr/bin/env node\n/**\n * Claude Skills CLI Commands\n * Integrates Claude skills into the stackmemory CLI\n */\n\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { ClaudeSkillsManager, type SkillContext } from '../../skills/claude-skills.js';\nimport { DualStackManager } from '../../core/context/dual-stack-manager.js';\nimport { FrameHandoffManager } from '../../core/context/frame-handoff-manager.js';\nimport { ContextRetriever } from '../../core/retrieval/context-retriever.js';\nimport { SQLiteAdapter } from '../../core/database/sqlite-adapter.js';\nimport { ConfigManager } from '../../core/config/config-manager.js';\nimport * as path from 'path';\nimport * as os from 'os';\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\nasync function initializeSkillContext(): Promise<SkillContext> {\n const config = ConfigManager.getInstance();\n const projectId = config.get('project.id');\n const userId = config.get('user.id') || process.env['USER'] || 'default';\n \n const dbPath = path.join(\n os.homedir(),\n '.stackmemory',\n 'data',\n projectId,\n 'stackmemory.db'\n );\n\n const database = new SQLiteAdapter(projectId, { dbPath });\n await database.connect();\n\n const dualStackManager = new DualStackManager(database, projectId, userId);\n const handoffManager = new FrameHandoffManager(dualStackManager);\n const contextRetriever = new ContextRetriever(database);\n\n return {\n projectId,\n userId,\n dualStackManager,\n handoffManager,\n contextRetriever,\n database,\n };\n}\n\nexport function createSkillsCommand(): Command {\n const skillsCmd = new Command('skills')\n .description('Execute Claude skills for enhanced workflow');\n\n // Handoff skill command\n skillsCmd\n .command('handoff <targetUser> <message>')\n .description('Streamline frame handoffs between team members')\n .option('-p, --priority <level>', 'Set priority (low, medium, high, critical)', 'medium')\n .option('-f, --frames <frames...>', 'Specific frames to handoff')\n .option('--no-auto-detect', 'Disable auto-detection of frames')\n .action(async (targetUser, message, options) => {\n const spinner = ora('Initiating handoff...').start();\n \n try {\n const context = await initializeSkillContext();\n const skillsManager = new ClaudeSkillsManager(context);\n \n const result = await skillsManager.executeSkill('handoff', [targetUser, message], {\n priority: options.priority,\n frames: options.frames,\n autoDetect: options.autoDetect !== false,\n });\n\n spinner.stop();\n\n if (result.success) {\n console.log(chalk.green('\u2713'), result.message);\n if (result.data) {\n console.log(chalk.cyan('\\nHandoff Details:'));\n console.log(` ID: ${result.data.handoffId}`);\n console.log(` Frames: ${result.data.frameCount}`);\n console.log(` Priority: ${result.data.priority}`);\n if (result.data.actionItems?.length > 0) {\n console.log(chalk.yellow('\\n Action Items:'));\n result.data.actionItems.forEach(item => {\n console.log(` \u2022 ${item}`);\n });\n }\n }\n } else {\n console.log(chalk.red('\u2717'), result.message);\n }\n\n await context.database.disconnect();\n } catch (error: unknown) {\n spinner.stop();\n console.error(chalk.red('Error:'), error.message);\n process.exit(1);\n }\n });\n\n // Checkpoint skill commands\n const checkpointCmd = skillsCmd.command('checkpoint')\n .description('Create and manage recovery points');\n\n checkpointCmd\n .command('create <description>')\n .description('Create a new checkpoint')\n .option('--files <files...>', 'Include specific files in checkpoint')\n .option('--auto-detect-risky', 'Auto-detect risky operations')\n .action(async (description, options) => {\n const spinner = ora('Creating checkpoint...').start();\n \n try {\n const context = await initializeSkillContext();\n const skillsManager = new ClaudeSkillsManager(context);\n \n const result = await skillsManager.executeSkill('checkpoint', ['create', description], {\n includeFiles: options.files,\n autoDetectRisky: options.autoDetectRisky,\n });\n\n spinner.stop();\n\n if (result.success) {\n console.log(chalk.green('\u2713'), result.message);\n if (result.data) {\n console.log(chalk.cyan('\\nCheckpoint Info:'));\n console.log(` ID: ${result.data.checkpointId}`);\n console.log(` Time: ${result.data.timestamp}`);\n console.log(` Frames: ${result.data.frameCount}`);\n }\n } else {\n console.log(chalk.red('\u2717'), result.message);\n }\n\n await context.database.disconnect();\n } catch (error: unknown) {\n spinner.stop();\n console.error(chalk.red('Error:'), error.message);\n process.exit(1);\n }\n });\n\n checkpointCmd\n .command('restore <checkpointId>')\n .description('Restore from a checkpoint')\n .action(async (checkpointId) => {\n const spinner = ora('Restoring checkpoint...').start();\n \n try {\n const context = await initializeSkillContext();\n const skillsManager = new ClaudeSkillsManager(context);\n \n const result = await skillsManager.executeSkill('checkpoint', ['restore', checkpointId]);\n\n spinner.stop();\n\n if (result.success) {\n console.log(chalk.green('\u2713'), result.message);\n if (result.data) {\n console.log(chalk.cyan('\\nRestored:'));\n console.log(` Frames: ${result.data.frameCount}`);\n console.log(` Files: ${result.data.filesRestored}`);\n }\n } else {\n console.log(chalk.red('\u2717'), result.message);\n }\n\n await context.database.disconnect();\n } catch (error: unknown) {\n spinner.stop();\n console.error(chalk.red('Error:'), error.message);\n process.exit(1);\n }\n });\n\n checkpointCmd\n .command('list')\n .description('List available checkpoints')\n .option('-l, --limit <number>', 'Limit number of results', '10')\n .option('-s, --since <date>', 'Show checkpoints since date')\n .action(async (options) => {\n const spinner = ora('Loading checkpoints...').start();\n \n try {\n const context = await initializeSkillContext();\n const skillsManager = new ClaudeSkillsManager(context);\n \n const result = await skillsManager.executeSkill('checkpoint', ['list'], {\n limit: parseInt(options.limit),\n since: options.since ? new Date(options.since) : undefined,\n });\n\n spinner.stop();\n\n if (result.success) {\n console.log(chalk.cyan('Available Checkpoints:\\n'));\n if (result.data && result.data.length > 0) {\n result.data.forEach((cp: any) => {\n const riskIndicator = cp.risky ? chalk.yellow(' [RISKY]') : '';\n console.log(`${chalk.bold(cp.id)}${riskIndicator}`);\n console.log(` ${cp.description}`);\n console.log(chalk.gray(` ${cp.timestamp} (${cp.frameCount} frames)\\n`));\n });\n } else {\n console.log(chalk.gray('No checkpoints found'));\n }\n } else {\n console.log(chalk.red('\u2717'), result.message);\n }\n\n await context.database.disconnect();\n } catch (error: unknown) {\n spinner.stop();\n console.error(chalk.red('Error:'), error.message);\n process.exit(1);\n }\n });\n\n checkpointCmd\n .command('diff <checkpoint1> <checkpoint2>')\n .description('Show differences between two checkpoints')\n .action(async (checkpoint1, checkpoint2) => {\n const spinner = ora('Comparing checkpoints...').start();\n \n try {\n const context = await initializeSkillContext();\n const skillsManager = new ClaudeSkillsManager(context);\n \n const result = await skillsManager.executeSkill('checkpoint', ['diff', checkpoint1, checkpoint2]);\n\n spinner.stop();\n\n if (result.success) {\n console.log(chalk.cyan('Checkpoint Diff:\\n'));\n if (result.data) {\n console.log(` Time difference: ${result.data.timeDiff}`);\n console.log(` Frame difference: ${result.data.framesDiff}`);\n console.log(` New frames: ${result.data.newFrames}`);\n console.log(` Removed frames: ${result.data.removedFrames}`);\n console.log(` Modified frames: ${result.data.modifiedFrames}`);\n }\n } else {\n console.log(chalk.red('\u2717'), result.message);\n }\n\n await context.database.disconnect();\n } catch (error: unknown) {\n spinner.stop();\n console.error(chalk.red('Error:'), error.message);\n process.exit(1);\n }\n });\n\n // Context Archaeologist skill command\n skillsCmd\n .command('dig <query>')\n .description('Deep historical context retrieval')\n .option('-d, --depth <depth>', 'Search depth (e.g., 30days, 6months, all)', '30days')\n .option('--patterns', 'Extract patterns from results')\n .option('--decisions', 'Extract key decisions')\n .option('--timeline', 'Generate activity timeline')\n .action(async (query, options) => {\n const spinner = ora('Digging through context...').start();\n \n try {\n const context = await initializeSkillContext();\n const skillsManager = new ClaudeSkillsManager(context);\n \n const result = await skillsManager.executeSkill('dig', [query], {\n depth: options.depth,\n patterns: options.patterns,\n decisions: options.decisions,\n timeline: options.timeline,\n });\n\n spinner.stop();\n\n if (result.success) {\n console.log(chalk.green('\u2713'), result.message);\n \n if (result.data) {\n console.log(chalk.cyan(`\\nSearched ${result.data.timeRange.from} to ${result.data.timeRange.to}`));\n \n if (result.data.summary) {\n console.log('\\n' + result.data.summary);\n } else {\n // Display top results\n if (result.data.topResults?.length > 0) {\n console.log(chalk.cyan('\\nTop Results:'));\n result.data.topResults.forEach((r: any) => {\n console.log(` ${chalk.yellow(`[${r.score.toFixed(2)}]`)} ${r.summary}`);\n });\n }\n\n // Display patterns if found\n if (result.data.patterns?.length > 0) {\n console.log(chalk.cyan('\\nDetected Patterns:'));\n result.data.patterns.forEach((p: any) => {\n console.log(` ${p.name}: ${p.count} occurrences`);\n });\n }\n\n // Display decisions if found\n if (result.data.decisions?.length > 0) {\n console.log(chalk.cyan('\\nKey Decisions:'));\n result.data.decisions.slice(0, 5).forEach((d: any) => {\n console.log(` ${chalk.gray(new Date(d.timestamp).toLocaleDateString())}: ${d.decision}`);\n });\n }\n\n // Display timeline if generated\n if (result.data.timeline?.length > 0) {\n console.log(chalk.cyan('\\nActivity Timeline:'));\n result.data.timeline.slice(0, 5).forEach((t: any) => {\n console.log(` ${t.date}: ${t.itemCount} activities`);\n });\n }\n }\n }\n } else {\n console.log(chalk.red('\u2717'), result.message);\n }\n\n await context.database.disconnect();\n } catch (error: unknown) {\n spinner.stop();\n console.error(chalk.red('Error:'), error.message);\n process.exit(1);\n }\n });\n\n // Help command for skills\n skillsCmd\n .command('help [skill]')\n .description('Show help for a specific skill')\n .action(async (skill) => {\n const context = await initializeSkillContext();\n const skillsManager = new ClaudeSkillsManager(context);\n \n if (skill) {\n console.log(skillsManager.getSkillHelp(skill));\n } else {\n console.log(chalk.cyan('Available Claude Skills:\\n'));\n console.log(' handoff - Streamline frame handoffs between team members');\n console.log(' checkpoint - Create and manage recovery points');\n console.log(' dig - Deep historical context retrieval\\n');\n console.log('Use \"stackmemory skills help <skill>\" for detailed help on each skill');\n }\n \n await context.database.disconnect();\n });\n\n return skillsCmd;\n}"],
|
|
5
|
-
"mappings": ";AAMA,SAAS,eAAe;AACxB,OAAO,WAAW;AAClB,OAAO,SAAS;AAChB,
|
|
4
|
+
"sourcesContent": ["#!/usr/bin/env node\n/**\n * Claude Skills CLI Commands\n * Integrates Claude skills into the stackmemory CLI\n */\n\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport {\n ClaudeSkillsManager,\n type SkillContext,\n} from '../../skills/claude-skills.js';\nimport { DualStackManager } from '../../core/context/dual-stack-manager.js';\nimport { FrameHandoffManager } from '../../core/context/frame-handoff-manager.js';\nimport { ContextRetriever } from '../../core/retrieval/context-retriever.js';\nimport { SQLiteAdapter } from '../../core/database/sqlite-adapter.js';\nimport { ConfigManager } from '../../core/config/config-manager.js';\nimport * as path from 'path';\nimport * as os from 'os';\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\nasync function initializeSkillContext(): Promise<SkillContext> {\n const config = ConfigManager.getInstance();\n const projectId = config.get('project.id');\n const userId = config.get('user.id') || process.env['USER'] || 'default';\n\n const dbPath = path.join(\n os.homedir(),\n '.stackmemory',\n 'data',\n projectId,\n 'stackmemory.db'\n );\n\n const database = new SQLiteAdapter(projectId, { dbPath });\n await database.connect();\n\n const dualStackManager = new DualStackManager(database, projectId, userId);\n const handoffManager = new FrameHandoffManager(dualStackManager);\n const contextRetriever = new ContextRetriever(database);\n\n return {\n projectId,\n userId,\n dualStackManager,\n handoffManager,\n contextRetriever,\n database,\n };\n}\n\nexport function createSkillsCommand(): Command {\n const skillsCmd = new Command('skills').description(\n 'Execute Claude skills for enhanced workflow'\n );\n\n // Handoff skill command\n skillsCmd\n .command('handoff <targetUser> <message>')\n .description('Streamline frame handoffs between team members')\n .option(\n '-p, --priority <level>',\n 'Set priority (low, medium, high, critical)',\n 'medium'\n )\n .option('-f, --frames <frames...>', 'Specific frames to handoff')\n .option('--no-auto-detect', 'Disable auto-detection of frames')\n .action(async (targetUser, message, options) => {\n const spinner = ora('Initiating handoff...').start();\n\n try {\n const context = await initializeSkillContext();\n const skillsManager = new ClaudeSkillsManager(context);\n\n const result = await skillsManager.executeSkill(\n 'handoff',\n [targetUser, message],\n {\n priority: options.priority,\n frames: options.frames,\n autoDetect: options.autoDetect !== false,\n }\n );\n\n spinner.stop();\n\n if (result.success) {\n console.log(chalk.green('\u2713'), result.message);\n if (result.data) {\n console.log(chalk.cyan('\\nHandoff Details:'));\n console.log(` ID: ${result.data.handoffId}`);\n console.log(` Frames: ${result.data.frameCount}`);\n console.log(` Priority: ${result.data.priority}`);\n if (result.data.actionItems?.length > 0) {\n console.log(chalk.yellow('\\n Action Items:'));\n result.data.actionItems.forEach((item) => {\n console.log(` \u2022 ${item}`);\n });\n }\n }\n } else {\n console.log(chalk.red('\u2717'), result.message);\n }\n\n await context.database.disconnect();\n } catch (error: unknown) {\n spinner.stop();\n console.error(chalk.red('Error:'), error.message);\n process.exit(1);\n }\n });\n\n // Checkpoint skill commands\n const checkpointCmd = skillsCmd\n .command('checkpoint')\n .description('Create and manage recovery points');\n\n checkpointCmd\n .command('create <description>')\n .description('Create a new checkpoint')\n .option('--files <files...>', 'Include specific files in checkpoint')\n .option('--auto-detect-risky', 'Auto-detect risky operations')\n .action(async (description, options) => {\n const spinner = ora('Creating checkpoint...').start();\n\n try {\n const context = await initializeSkillContext();\n const skillsManager = new ClaudeSkillsManager(context);\n\n const result = await skillsManager.executeSkill(\n 'checkpoint',\n ['create', description],\n {\n includeFiles: options.files,\n autoDetectRisky: options.autoDetectRisky,\n }\n );\n\n spinner.stop();\n\n if (result.success) {\n console.log(chalk.green('\u2713'), result.message);\n if (result.data) {\n console.log(chalk.cyan('\\nCheckpoint Info:'));\n console.log(` ID: ${result.data.checkpointId}`);\n console.log(` Time: ${result.data.timestamp}`);\n console.log(` Frames: ${result.data.frameCount}`);\n }\n } else {\n console.log(chalk.red('\u2717'), result.message);\n }\n\n await context.database.disconnect();\n } catch (error: unknown) {\n spinner.stop();\n console.error(chalk.red('Error:'), error.message);\n process.exit(1);\n }\n });\n\n checkpointCmd\n .command('restore <checkpointId>')\n .description('Restore from a checkpoint')\n .action(async (checkpointId) => {\n const spinner = ora('Restoring checkpoint...').start();\n\n try {\n const context = await initializeSkillContext();\n const skillsManager = new ClaudeSkillsManager(context);\n\n const result = await skillsManager.executeSkill('checkpoint', [\n 'restore',\n checkpointId,\n ]);\n\n spinner.stop();\n\n if (result.success) {\n console.log(chalk.green('\u2713'), result.message);\n if (result.data) {\n console.log(chalk.cyan('\\nRestored:'));\n console.log(` Frames: ${result.data.frameCount}`);\n console.log(` Files: ${result.data.filesRestored}`);\n }\n } else {\n console.log(chalk.red('\u2717'), result.message);\n }\n\n await context.database.disconnect();\n } catch (error: unknown) {\n spinner.stop();\n console.error(chalk.red('Error:'), error.message);\n process.exit(1);\n }\n });\n\n checkpointCmd\n .command('list')\n .description('List available checkpoints')\n .option('-l, --limit <number>', 'Limit number of results', '10')\n .option('-s, --since <date>', 'Show checkpoints since date')\n .action(async (options) => {\n const spinner = ora('Loading checkpoints...').start();\n\n try {\n const context = await initializeSkillContext();\n const skillsManager = new ClaudeSkillsManager(context);\n\n const result = await skillsManager.executeSkill(\n 'checkpoint',\n ['list'],\n {\n limit: parseInt(options.limit),\n since: options.since ? new Date(options.since) : undefined,\n }\n );\n\n spinner.stop();\n\n if (result.success) {\n console.log(chalk.cyan('Available Checkpoints:\\n'));\n if (result.data && result.data.length > 0) {\n result.data.forEach((cp: any) => {\n const riskIndicator = cp.risky ? chalk.yellow(' [RISKY]') : '';\n console.log(`${chalk.bold(cp.id)}${riskIndicator}`);\n console.log(` ${cp.description}`);\n console.log(\n chalk.gray(` ${cp.timestamp} (${cp.frameCount} frames)\\n`)\n );\n });\n } else {\n console.log(chalk.gray('No checkpoints found'));\n }\n } else {\n console.log(chalk.red('\u2717'), result.message);\n }\n\n await context.database.disconnect();\n } catch (error: unknown) {\n spinner.stop();\n console.error(chalk.red('Error:'), error.message);\n process.exit(1);\n }\n });\n\n checkpointCmd\n .command('diff <checkpoint1> <checkpoint2>')\n .description('Show differences between two checkpoints')\n .action(async (checkpoint1, checkpoint2) => {\n const spinner = ora('Comparing checkpoints...').start();\n\n try {\n const context = await initializeSkillContext();\n const skillsManager = new ClaudeSkillsManager(context);\n\n const result = await skillsManager.executeSkill('checkpoint', [\n 'diff',\n checkpoint1,\n checkpoint2,\n ]);\n\n spinner.stop();\n\n if (result.success) {\n console.log(chalk.cyan('Checkpoint Diff:\\n'));\n if (result.data) {\n console.log(` Time difference: ${result.data.timeDiff}`);\n console.log(` Frame difference: ${result.data.framesDiff}`);\n console.log(` New frames: ${result.data.newFrames}`);\n console.log(` Removed frames: ${result.data.removedFrames}`);\n console.log(` Modified frames: ${result.data.modifiedFrames}`);\n }\n } else {\n console.log(chalk.red('\u2717'), result.message);\n }\n\n await context.database.disconnect();\n } catch (error: unknown) {\n spinner.stop();\n console.error(chalk.red('Error:'), error.message);\n process.exit(1);\n }\n });\n\n // Context Archaeologist skill command\n skillsCmd\n .command('dig <query>')\n .description('Deep historical context retrieval')\n .option(\n '-d, --depth <depth>',\n 'Search depth (e.g., 30days, 6months, all)',\n '30days'\n )\n .option('--patterns', 'Extract patterns from results')\n .option('--decisions', 'Extract key decisions')\n .option('--timeline', 'Generate activity timeline')\n .action(async (query, options) => {\n const spinner = ora('Digging through context...').start();\n\n try {\n const context = await initializeSkillContext();\n const skillsManager = new ClaudeSkillsManager(context);\n\n const result = await skillsManager.executeSkill('dig', [query], {\n depth: options.depth,\n patterns: options.patterns,\n decisions: options.decisions,\n timeline: options.timeline,\n });\n\n spinner.stop();\n\n if (result.success) {\n console.log(chalk.green('\u2713'), result.message);\n\n if (result.data) {\n console.log(\n chalk.cyan(\n `\\nSearched ${result.data.timeRange.from} to ${result.data.timeRange.to}`\n )\n );\n\n if (result.data.summary) {\n console.log('\\n' + result.data.summary);\n } else {\n // Display top results\n if (result.data.topResults?.length > 0) {\n console.log(chalk.cyan('\\nTop Results:'));\n result.data.topResults.forEach((r: any) => {\n console.log(\n ` ${chalk.yellow(`[${r.score.toFixed(2)}]`)} ${r.summary}`\n );\n });\n }\n\n // Display patterns if found\n if (result.data.patterns?.length > 0) {\n console.log(chalk.cyan('\\nDetected Patterns:'));\n result.data.patterns.forEach((p: any) => {\n console.log(` ${p.name}: ${p.count} occurrences`);\n });\n }\n\n // Display decisions if found\n if (result.data.decisions?.length > 0) {\n console.log(chalk.cyan('\\nKey Decisions:'));\n result.data.decisions.slice(0, 5).forEach((d: any) => {\n console.log(\n ` ${chalk.gray(new Date(d.timestamp).toLocaleDateString())}: ${d.decision}`\n );\n });\n }\n\n // Display timeline if generated\n if (result.data.timeline?.length > 0) {\n console.log(chalk.cyan('\\nActivity Timeline:'));\n result.data.timeline.slice(0, 5).forEach((t: any) => {\n console.log(` ${t.date}: ${t.itemCount} activities`);\n });\n }\n }\n }\n } else {\n console.log(chalk.red('\u2717'), result.message);\n }\n\n await context.database.disconnect();\n } catch (error: unknown) {\n spinner.stop();\n console.error(chalk.red('Error:'), error.message);\n process.exit(1);\n }\n });\n\n // Help command for skills\n skillsCmd\n .command('help [skill]')\n .description('Show help for a specific skill')\n .action(async (skill) => {\n const context = await initializeSkillContext();\n const skillsManager = new ClaudeSkillsManager(context);\n\n if (skill) {\n console.log(skillsManager.getSkillHelp(skill));\n } else {\n console.log(chalk.cyan('Available Claude Skills:\\n'));\n console.log(\n ' handoff - Streamline frame handoffs between team members'\n );\n console.log(' checkpoint - Create and manage recovery points');\n console.log(' dig - Deep historical context retrieval\\n');\n console.log(\n 'Use \"stackmemory skills help <skill>\" for detailed help on each skill'\n );\n }\n\n await context.database.disconnect();\n });\n\n return skillsCmd;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -43,46 +43,70 @@ function createStorageCommand() {
|
|
|
43
43
|
console.log(`
|
|
44
44
|
${icon} ${color(tier.tier.toUpperCase())} Tier:`);
|
|
45
45
|
console.log(` Traces: ${chalk.white(tier.count)}`);
|
|
46
|
-
console.log(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
console.log(
|
|
46
|
+
console.log(
|
|
47
|
+
` Original Size: ${chalk.white(formatBytes(tier.total_original || 0))}`
|
|
48
|
+
);
|
|
49
|
+
console.log(
|
|
50
|
+
` Compressed Size: ${chalk.white(formatBytes(tier.total_compressed || 0))}`
|
|
51
|
+
);
|
|
52
|
+
console.log(
|
|
53
|
+
` Compression Ratio: ${chalk.green((tier.avg_compression * 100).toFixed(1) + "%")}`
|
|
54
|
+
);
|
|
55
|
+
console.log(
|
|
56
|
+
` Avg Access Count: ${chalk.white(tier.avg_access?.toFixed(1) || "0")}`
|
|
57
|
+
);
|
|
50
58
|
}
|
|
51
59
|
console.log(chalk.blue("\n\u{1F4C5} Age Distribution:"));
|
|
52
60
|
console.log(chalk.gray("\u2501".repeat(50)));
|
|
53
61
|
for (const age of stats.byAge) {
|
|
54
62
|
const percent = (age.count / stats.totalTraces * 100).toFixed(1);
|
|
55
63
|
const bar = "\u2588".repeat(Math.floor(percent / 2));
|
|
56
|
-
console.log(
|
|
64
|
+
console.log(
|
|
65
|
+
` ${age.age_group.padEnd(10)} ${bar} ${percent}% (${age.count})`
|
|
66
|
+
);
|
|
57
67
|
}
|
|
58
68
|
console.log(chalk.blue("\n\u{1F4C8} Summary:"));
|
|
59
69
|
console.log(chalk.gray("\u2501".repeat(50)));
|
|
60
70
|
console.log(` Total Traces: ${chalk.white(stats.totalTraces)}`);
|
|
61
|
-
console.log(
|
|
62
|
-
|
|
71
|
+
console.log(
|
|
72
|
+
` Total Size: ${chalk.white(formatBytes(stats.totalSize))}`
|
|
73
|
+
);
|
|
74
|
+
console.log(
|
|
75
|
+
` Compressed Size: ${chalk.white(formatBytes(stats.compressedSize))}`
|
|
76
|
+
);
|
|
63
77
|
const compressionRatio = ((1 - stats.compressedSize / stats.totalSize) * 100).toFixed(1);
|
|
64
|
-
console.log(
|
|
78
|
+
console.log(
|
|
79
|
+
` Overall Compression: ${chalk.green(compressionRatio + "%")}`
|
|
80
|
+
);
|
|
65
81
|
const costEstimate = calculateStorageCost(stats);
|
|
66
82
|
console.log(chalk.blue("\n\u{1F4B0} Estimated Monthly Cost:"));
|
|
67
83
|
console.log(chalk.gray("\u2501".repeat(50)));
|
|
68
|
-
console.log(
|
|
69
|
-
|
|
84
|
+
console.log(
|
|
85
|
+
` Redis (Hot): ${chalk.green("$0.00")} (included with Railway)`
|
|
86
|
+
);
|
|
87
|
+
console.log(
|
|
88
|
+
` Railway Buckets (Warm): ${chalk.yellow(costEstimate.railway)}`
|
|
89
|
+
);
|
|
70
90
|
console.log(` GCS Coldline (Cold): ${chalk.cyan(costEstimate.gcs)}`);
|
|
71
91
|
console.log(` Total: ${chalk.white(costEstimate.total)}`);
|
|
72
92
|
if (options.verbose) {
|
|
73
|
-
const recentMigrations = db.prepare(
|
|
93
|
+
const recentMigrations = db.prepare(
|
|
94
|
+
`
|
|
74
95
|
SELECT trace_id, tier, migrated_at, score
|
|
75
96
|
FROM storage_tiers
|
|
76
97
|
WHERE migrated_at > ?
|
|
77
98
|
ORDER BY migrated_at DESC
|
|
78
99
|
LIMIT 10
|
|
79
|
-
`
|
|
100
|
+
`
|
|
101
|
+
).all(Date.now() - 24 * 60 * 60 * 1e3);
|
|
80
102
|
if (recentMigrations.length > 0) {
|
|
81
103
|
console.log(chalk.blue("\n\u{1F504} Recent Migrations (last 24h):"));
|
|
82
104
|
console.log(chalk.gray("\u2501".repeat(50)));
|
|
83
105
|
for (const m of recentMigrations) {
|
|
84
106
|
const time = new Date(m.migrated_at).toLocaleTimeString();
|
|
85
|
-
console.log(
|
|
107
|
+
console.log(
|
|
108
|
+
` ${time} - ${m.trace_id.substring(0, 8)}... \u2192 ${m.tier} (score: ${m.score.toFixed(2)})`
|
|
109
|
+
);
|
|
86
110
|
}
|
|
87
111
|
}
|
|
88
112
|
}
|
|
@@ -101,13 +125,15 @@ ${icon} ${color(tier.tier.toUpperCase())} Tier:`);
|
|
|
101
125
|
const configManager = new ConfigManager();
|
|
102
126
|
const storage2 = new RailwayOptimizedStorage(db, configManager);
|
|
103
127
|
if (options.dryRun) {
|
|
104
|
-
const candidates = db.prepare(
|
|
128
|
+
const candidates = db.prepare(
|
|
129
|
+
`
|
|
105
130
|
SELECT trace_id, tier, created_at, score,
|
|
106
131
|
(? - created_at) / 3600000 as age_hours
|
|
107
132
|
FROM storage_tiers
|
|
108
133
|
WHERE tier != 'cold'
|
|
109
134
|
ORDER BY created_at ASC
|
|
110
|
-
`
|
|
135
|
+
`
|
|
136
|
+
).all(Date.now());
|
|
111
137
|
const toMigrate = {
|
|
112
138
|
hotToWarm: candidates.filter(
|
|
113
139
|
(c) => c.tier === "hot" && c.age_hours > 24
|
|
@@ -120,21 +146,33 @@ ${icon} ${color(tier.tier.toUpperCase())} Tier:`);
|
|
|
120
146
|
console.log(chalk.blue("\n\u{1F504} Migration Plan:"));
|
|
121
147
|
console.log(chalk.gray("\u2501".repeat(50)));
|
|
122
148
|
if (toMigrate.hotToWarm.length > 0) {
|
|
123
|
-
console.log(
|
|
124
|
-
|
|
149
|
+
console.log(
|
|
150
|
+
chalk.red(
|
|
151
|
+
`
|
|
152
|
+
\u{1F525} \u2192 \u2601\uFE0F Hot to Warm: ${toMigrate.hotToWarm.length} traces`
|
|
153
|
+
)
|
|
154
|
+
);
|
|
125
155
|
for (const t of toMigrate.hotToWarm.slice(0, 5)) {
|
|
126
|
-
console.log(
|
|
156
|
+
console.log(
|
|
157
|
+
` \u2022 ${t.trace_id.substring(0, 8)}... (${t.age_hours.toFixed(0)}h old, score: ${t.score.toFixed(2)})`
|
|
158
|
+
);
|
|
127
159
|
}
|
|
128
160
|
if (toMigrate.hotToWarm.length > 5) {
|
|
129
161
|
console.log(` ... and ${toMigrate.hotToWarm.length - 5} more`);
|
|
130
162
|
}
|
|
131
163
|
}
|
|
132
164
|
if (toMigrate.warmToCold.length > 0) {
|
|
133
|
-
console.log(
|
|
134
|
-
|
|
165
|
+
console.log(
|
|
166
|
+
chalk.yellow(
|
|
167
|
+
`
|
|
168
|
+
\u2601\uFE0F \u2192 \u2744\uFE0F Warm to Cold: ${toMigrate.warmToCold.length} traces`
|
|
169
|
+
)
|
|
170
|
+
);
|
|
135
171
|
for (const t of toMigrate.warmToCold.slice(0, 5)) {
|
|
136
172
|
const ageDays = Math.floor(t.age_hours / 24);
|
|
137
|
-
console.log(
|
|
173
|
+
console.log(
|
|
174
|
+
` \u2022 ${t.trace_id.substring(0, 8)}... (${ageDays}d old, score: ${t.score.toFixed(2)})`
|
|
175
|
+
);
|
|
138
176
|
}
|
|
139
177
|
if (toMigrate.warmToCold.length > 5) {
|
|
140
178
|
console.log(` ... and ${toMigrate.warmToCold.length - 5} more`);
|
|
@@ -149,8 +187,12 @@ ${icon} ${color(tier.tier.toUpperCase())} Tier:`);
|
|
|
149
187
|
spinner.succeed("Migration completed");
|
|
150
188
|
console.log(chalk.blue("\n\u2705 Migration Results:"));
|
|
151
189
|
console.log(chalk.gray("\u2501".repeat(50)));
|
|
152
|
-
console.log(
|
|
153
|
-
|
|
190
|
+
console.log(
|
|
191
|
+
` Hot \u2192 Warm: ${chalk.yellow(results.hotToWarm)} traces`
|
|
192
|
+
);
|
|
193
|
+
console.log(
|
|
194
|
+
` Warm \u2192 Cold: ${chalk.cyan(results.warmToCold)} traces`
|
|
195
|
+
);
|
|
154
196
|
if (results.errors.length > 0) {
|
|
155
197
|
console.log(chalk.red(`
|
|
156
198
|
\u274C Errors (${results.errors.length}):`));
|
|
@@ -175,16 +217,20 @@ ${icon} ${color(tier.tier.toUpperCase())} Tier:`);
|
|
|
175
217
|
const storage2 = new RailwayOptimizedStorage(db, configManager);
|
|
176
218
|
const cutoff = Date.now() - options.days * 24 * 60 * 60 * 1e3;
|
|
177
219
|
if (options.dryRun) {
|
|
178
|
-
const toRemove = db.prepare(
|
|
220
|
+
const toRemove = db.prepare(
|
|
221
|
+
`
|
|
179
222
|
SELECT COUNT(*) as count, SUM(compressed_size) as size
|
|
180
223
|
FROM storage_tiers
|
|
181
224
|
WHERE tier = 'cold' AND created_at < ? AND access_count = 0
|
|
182
|
-
`
|
|
225
|
+
`
|
|
226
|
+
).get(cutoff);
|
|
183
227
|
spinner.info("Dry run - no traces will be removed");
|
|
184
228
|
console.log(chalk.blue("\n\u{1F9F9} Cleanup Analysis:"));
|
|
185
229
|
console.log(chalk.gray("\u2501".repeat(50)));
|
|
186
230
|
console.log(` Traces to remove: ${chalk.red(toRemove.count || 0)}`);
|
|
187
|
-
console.log(
|
|
231
|
+
console.log(
|
|
232
|
+
` Space to free: ${chalk.yellow(formatBytes(toRemove.size || 0))}`
|
|
233
|
+
);
|
|
188
234
|
console.log(` Criteria: > ${options.days} days old with 0 access`);
|
|
189
235
|
} else {
|
|
190
236
|
const removed = await storage2.cleanup();
|
|
@@ -216,14 +262,24 @@ ${icon} ${color(tier.tier.toUpperCase())} Tier:`);
|
|
|
216
262
|
console.log(` Type: ${chalk.yellow(trace.type)}`);
|
|
217
263
|
console.log(` Score: ${chalk.green(trace.score.toFixed(3))}`);
|
|
218
264
|
console.log(` Summary: ${trace.summary}`);
|
|
219
|
-
console.log(
|
|
265
|
+
console.log(
|
|
266
|
+
` Tools: ${trace.tools?.length || trace.toolSummary?.count || 0}`
|
|
267
|
+
);
|
|
220
268
|
const metadata = trace.metadata;
|
|
221
269
|
if (metadata) {
|
|
222
270
|
console.log(chalk.blue("\n\u{1F4CB} Metadata:"));
|
|
223
|
-
console.log(
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
console.log(
|
|
271
|
+
console.log(
|
|
272
|
+
` Start: ${new Date(metadata.startTime).toLocaleString()}`
|
|
273
|
+
);
|
|
274
|
+
console.log(
|
|
275
|
+
` Duration: ${formatDuration(metadata.endTime - metadata.startTime)}`
|
|
276
|
+
);
|
|
277
|
+
console.log(
|
|
278
|
+
` Files: ${metadata.filesModified?.length || metadata.filesModified || 0}`
|
|
279
|
+
);
|
|
280
|
+
console.log(
|
|
281
|
+
` Errors: ${metadata.errorsEncountered?.length || metadata.errorsCount || 0}`
|
|
282
|
+
);
|
|
227
283
|
}
|
|
228
284
|
const location = db.prepare(
|
|
229
285
|
"SELECT tier, location, access_count FROM storage_tiers WHERE trace_id = ?"
|
|
@@ -245,18 +301,32 @@ ${icon} ${color(tier.tier.toUpperCase())} Tier:`);
|
|
|
245
301
|
console.log(chalk.blue("\n\u2699\uFE0F Storage Configuration:"));
|
|
246
302
|
console.log(chalk.gray("\u2501".repeat(50)));
|
|
247
303
|
console.log(chalk.red("\n\u{1F525} Hot Tier (Redis):"));
|
|
248
|
-
console.log(
|
|
304
|
+
console.log(
|
|
305
|
+
` URL: ${process.env["REDIS_URL"] ? chalk.green("Configured") : chalk.yellow("Not configured")}`
|
|
306
|
+
);
|
|
249
307
|
console.log(` TTL: 24 hours`);
|
|
250
308
|
console.log(` Max Memory: 100MB`);
|
|
251
309
|
console.log(chalk.yellow("\n\u2601\uFE0F Warm Tier (Railway Buckets):"));
|
|
252
|
-
console.log(
|
|
253
|
-
|
|
254
|
-
|
|
310
|
+
console.log(
|
|
311
|
+
` Endpoint: ${process.env["RAILWAY_BUCKET_ENDPOINT"] || "Not configured"}`
|
|
312
|
+
);
|
|
313
|
+
console.log(
|
|
314
|
+
` Bucket: ${process.env["RAILWAY_BUCKET_NAME"] || "stackmemory-warm"}`
|
|
315
|
+
);
|
|
316
|
+
console.log(
|
|
317
|
+
` Access Key: ${process.env["RAILWAY_BUCKET_ACCESS_KEY"] ? chalk.green("Set") : chalk.yellow("Not set")}`
|
|
318
|
+
);
|
|
255
319
|
console.log(` Retention: 30 days`);
|
|
256
320
|
console.log(chalk.cyan("\n\u2744\uFE0F Cold Tier (GCS):"));
|
|
257
|
-
console.log(
|
|
258
|
-
|
|
259
|
-
|
|
321
|
+
console.log(
|
|
322
|
+
` Project: ${process.env["GCP_PROJECT_ID"] || "Not configured"}`
|
|
323
|
+
);
|
|
324
|
+
console.log(
|
|
325
|
+
` Bucket: ${process.env["GCS_BUCKET"] || "stackmemory-cold"}`
|
|
326
|
+
);
|
|
327
|
+
console.log(
|
|
328
|
+
` Key File: ${process.env["GCP_KEY_FILE"] ? chalk.green("Set") : chalk.yellow("Not set")}`
|
|
329
|
+
);
|
|
260
330
|
console.log(` Storage Class: Coldline`);
|
|
261
331
|
console.log(` Retention: Infinite`);
|
|
262
332
|
console.log(chalk.blue("\n\u{1F4CA} Migration Thresholds:"));
|