@stackmemoryai/stackmemory 0.5.57 → 0.5.59
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/bin/codex-smd +6 -0
- package/dist/cli/codex-sm-danger.js +21 -0
- package/dist/cli/codex-sm-danger.js.map +7 -0
- package/dist/cli/commands/handoff.js +33 -3
- package/dist/cli/commands/handoff.js.map +2 -2
- package/dist/cli/commands/search.js +20 -3
- package/dist/cli/commands/search.js.map +2 -2
- package/dist/core/database/sqlite-adapter.js +13 -3
- package/dist/core/database/sqlite-adapter.js.map +2 -2
- package/dist/core/errors/error-utils.js +208 -0
- package/dist/core/errors/error-utils.js.map +7 -0
- package/dist/core/errors/index.js +13 -4
- package/dist/core/errors/index.js.map +2 -2
- package/dist/core/merge/unified-merge-resolver.js +303 -0
- package/dist/core/merge/unified-merge-resolver.js.map +7 -0
- package/dist/core/monitoring/logger.js +61 -9
- package/dist/core/monitoring/logger.js.map +2 -2
- package/dist/core/security/index.js +35 -0
- package/dist/core/security/index.js.map +7 -0
- package/dist/core/security/input-sanitizer.js +321 -0
- package/dist/core/security/input-sanitizer.js.map +7 -0
- package/dist/core/session/enhanced-handoff.js +136 -2
- package/dist/core/session/enhanced-handoff.js.map +3 -3
- package/dist/integrations/linear/client.js +5 -1
- package/dist/integrations/linear/client.js.map +2 -2
- package/dist/integrations/mcp/remote-server.js +27 -36
- package/dist/integrations/mcp/remote-server.js.map +2 -2
- package/dist/integrations/mcp/server.js +44 -29
- package/dist/integrations/mcp/server.js.map +3 -3
- package/dist/scripts/benchmark-performance.js +48 -0
- package/dist/scripts/benchmark-performance.js.map +7 -0
- package/dist/scripts/check-redis.js +42 -0
- package/dist/scripts/check-redis.js.map +7 -0
- package/dist/scripts/initialize.js +116 -0
- package/dist/scripts/initialize.js.map +7 -0
- package/dist/scripts/list-linear-tasks.js +124 -0
- package/dist/scripts/list-linear-tasks.js.map +7 -0
- package/dist/scripts/measure-handoff-impact.js +340 -0
- package/dist/scripts/measure-handoff-impact.js.map +7 -0
- package/dist/scripts/query-chromadb.js +160 -0
- package/dist/scripts/query-chromadb.js.map +7 -0
- package/dist/scripts/show-linear-summary.js +119 -0
- package/dist/scripts/show-linear-summary.js.map +7 -0
- package/dist/scripts/simple-swarm-demo.js +90 -0
- package/dist/scripts/simple-swarm-demo.js.map +7 -0
- package/dist/scripts/status.js +155 -0
- package/dist/scripts/status.js.map +7 -0
- package/dist/scripts/test-chromadb-sync.js +192 -0
- package/dist/scripts/test-chromadb-sync.js.map +7 -0
- package/dist/scripts/test-ralph-iteration-fix.js +86 -0
- package/dist/scripts/test-ralph-iteration-fix.js.map +7 -0
- package/dist/scripts/test-ralph-iterations.js +121 -0
- package/dist/scripts/test-ralph-iterations.js.map +7 -0
- package/dist/scripts/test-redis-storage.js +389 -0
- package/dist/scripts/test-redis-storage.js.map +7 -0
- package/dist/scripts/test-simple-ralph-state-sync.js +115 -0
- package/dist/scripts/test-simple-ralph-state-sync.js.map +7 -0
- package/dist/scripts/test-swarm-fixes.js +125 -0
- package/dist/scripts/test-swarm-fixes.js.map +7 -0
- package/dist/scripts/test-swarm-tui.js +23 -0
- package/dist/scripts/test-swarm-tui.js.map +7 -0
- package/dist/scripts/test-tui-shortcuts.js +52 -0
- package/dist/scripts/test-tui-shortcuts.js.map +7 -0
- package/dist/scripts/validate-tui-shortcuts.js +60 -0
- package/dist/scripts/validate-tui-shortcuts.js.map +7 -0
- package/dist/src/agents/core/agent-task-manager.js +527 -0
- package/dist/src/agents/core/agent-task-manager.js.map +7 -0
- package/dist/src/agents/verifiers/base-verifier.js +133 -0
- package/dist/src/agents/verifiers/base-verifier.js.map +7 -0
- package/dist/src/agents/verifiers/formatter-verifier.js +130 -0
- package/dist/src/agents/verifiers/formatter-verifier.js.map +7 -0
- package/dist/src/agents/verifiers/llm-judge.js +252 -0
- package/dist/src/agents/verifiers/llm-judge.js.map +7 -0
- package/dist/src/cli/auto-detect.js +321 -0
- package/dist/src/cli/auto-detect.js.map +7 -0
- package/dist/src/cli/claude-sm-danger.js +21 -0
- package/dist/src/cli/claude-sm-danger.js.map +7 -0
- package/dist/src/cli/claude-sm.js +1156 -0
- package/dist/src/cli/claude-sm.js.map +7 -0
- package/dist/src/cli/codex-sm-danger.js +21 -0
- package/dist/src/cli/codex-sm-danger.js.map +7 -0
- package/dist/src/cli/codex-sm.js +349 -0
- package/dist/src/cli/codex-sm.js.map +7 -0
- package/dist/src/cli/commands/api.js +232 -0
- package/dist/src/cli/commands/api.js.map +7 -0
- package/dist/src/cli/commands/auto-background.js +180 -0
- package/dist/src/cli/commands/auto-background.js.map +7 -0
- package/dist/src/cli/commands/cleanup-processes.js +68 -0
- package/dist/src/cli/commands/cleanup-processes.js.map +7 -0
- package/dist/src/cli/commands/clear.js +202 -0
- package/dist/src/cli/commands/clear.js.map +7 -0
- package/dist/src/cli/commands/config.js +445 -0
- package/dist/src/cli/commands/config.js.map +7 -0
- package/dist/src/cli/commands/context-rehydrate.js +751 -0
- package/dist/src/cli/commands/context-rehydrate.js.map +7 -0
- package/dist/src/cli/commands/context.js +343 -0
- package/dist/src/cli/commands/context.js.map +7 -0
- package/dist/src/cli/commands/daemon.js +392 -0
- package/dist/src/cli/commands/daemon.js.map +7 -0
- package/dist/src/cli/commands/dashboard.js +210 -0
- package/dist/src/cli/commands/dashboard.js.map +7 -0
- package/dist/src/cli/commands/db.js +147 -0
- package/dist/src/cli/commands/db.js.map +7 -0
- package/dist/src/cli/commands/decision.js +266 -0
- package/dist/src/cli/commands/decision.js.map +7 -0
- package/dist/src/cli/commands/discovery.js +279 -0
- package/dist/src/cli/commands/discovery.js.map +7 -0
- package/dist/src/cli/commands/handoff.js +624 -0
- package/dist/src/cli/commands/handoff.js.map +7 -0
- package/dist/src/cli/commands/hooks.js +298 -0
- package/dist/src/cli/commands/hooks.js.map +7 -0
- package/dist/src/cli/commands/linear.js +529 -0
- package/dist/src/cli/commands/linear.js.map +7 -0
- package/dist/src/cli/commands/log.js +169 -0
- package/dist/src/cli/commands/log.js.map +7 -0
- package/dist/src/cli/commands/login.js +172 -0
- package/dist/src/cli/commands/login.js.map +7 -0
- package/dist/src/cli/commands/migrate.js +240 -0
- package/dist/src/cli/commands/migrate.js.map +7 -0
- package/dist/src/cli/commands/model.js +533 -0
- package/dist/src/cli/commands/model.js.map +7 -0
- package/dist/src/cli/commands/onboard.js +536 -0
- package/dist/src/cli/commands/onboard.js.map +7 -0
- package/dist/src/cli/commands/projects.js +199 -0
- package/dist/src/cli/commands/projects.js.map +7 -0
- package/dist/src/cli/commands/ralph.js +909 -0
- package/dist/src/cli/commands/ralph.js.map +7 -0
- package/dist/src/cli/commands/retrieval.js +248 -0
- package/dist/src/cli/commands/retrieval.js.map +7 -0
- package/dist/src/cli/commands/search.js +173 -0
- package/dist/src/cli/commands/search.js.map +7 -0
- package/dist/src/cli/commands/service.js +749 -0
- package/dist/src/cli/commands/service.js.map +7 -0
- package/dist/src/cli/commands/session.js +200 -0
- package/dist/src/cli/commands/session.js.map +7 -0
- package/dist/src/cli/commands/settings.js +306 -0
- package/dist/src/cli/commands/settings.js.map +7 -0
- package/dist/src/cli/commands/setup.js +701 -0
- package/dist/src/cli/commands/setup.js.map +7 -0
- package/dist/src/cli/commands/shell.js +249 -0
- package/dist/src/cli/commands/shell.js.map +7 -0
- package/dist/src/cli/commands/signup.js +50 -0
- package/dist/src/cli/commands/signup.js.map +7 -0
- package/dist/src/cli/commands/skills.js +470 -0
- package/dist/src/cli/commands/skills.js.map +7 -0
- package/dist/src/cli/commands/sms-notify.js +795 -0
- package/dist/src/cli/commands/sms-notify.js.map +7 -0
- package/dist/src/cli/commands/storage-tier.js +183 -0
- package/dist/src/cli/commands/storage-tier.js.map +7 -0
- package/dist/src/cli/commands/sweep.js +249 -0
- package/dist/src/cli/commands/sweep.js.map +7 -0
- package/dist/src/cli/commands/tasks.js +213 -0
- package/dist/src/cli/commands/tasks.js.map +7 -0
- package/dist/src/cli/commands/worktree.js +319 -0
- package/dist/src/cli/commands/worktree.js.map +7 -0
- package/dist/src/cli/index.js +594 -0
- package/dist/src/cli/index.js.map +7 -0
- package/dist/src/cli/opencode-sm.js +448 -0
- package/dist/src/cli/opencode-sm.js.map +7 -0
- package/dist/src/cli/utils/viewer.js +96 -0
- package/dist/src/cli/utils/viewer.js.map +7 -0
- package/dist/src/core/config/config-manager.js +398 -0
- package/dist/src/core/config/config-manager.js.map +7 -0
- package/dist/src/core/config/feature-flags.js +76 -0
- package/dist/src/core/config/feature-flags.js.map +7 -0
- package/dist/src/core/config/storage-config.js +115 -0
- package/dist/src/core/config/storage-config.js.map +7 -0
- package/dist/src/core/config/types.js +144 -0
- package/dist/src/core/config/types.js.map +7 -0
- package/dist/src/core/context/auto-context.js +80 -0
- package/dist/src/core/context/auto-context.js.map +7 -0
- package/dist/src/core/context/dual-stack-manager.js +870 -0
- package/dist/src/core/context/dual-stack-manager.js.map +7 -0
- package/dist/src/core/context/enhanced-rehydration.js +994 -0
- package/dist/src/core/context/enhanced-rehydration.js.map +7 -0
- package/dist/src/core/context/frame-database.js +479 -0
- package/dist/src/core/context/frame-database.js.map +7 -0
- package/dist/src/core/context/frame-digest.js +250 -0
- package/dist/src/core/context/frame-digest.js.map +7 -0
- package/dist/src/core/context/frame-handoff-manager.js +778 -0
- package/dist/src/core/context/frame-handoff-manager.js.map +7 -0
- package/dist/src/core/context/frame-lifecycle-hooks.js +119 -0
- package/dist/src/core/context/frame-lifecycle-hooks.js.map +7 -0
- package/dist/src/core/context/frame-recovery.js +302 -0
- package/dist/src/core/context/frame-recovery.js.map +7 -0
- package/dist/src/core/context/frame-stack.js +314 -0
- package/dist/src/core/context/frame-stack.js.map +7 -0
- package/dist/src/core/context/frame-types.js +5 -0
- package/dist/src/core/context/frame-types.js.map +7 -0
- package/dist/src/core/context/index.js +25 -0
- package/dist/src/core/context/index.js.map +7 -0
- package/dist/src/core/context/permission-manager.js +185 -0
- package/dist/src/core/context/permission-manager.js.map +7 -0
- package/dist/src/core/context/recursive-context-manager.js +592 -0
- package/dist/src/core/context/recursive-context-manager.js.map +7 -0
- package/dist/src/core/context/refactored-frame-manager.js +754 -0
- package/dist/src/core/context/refactored-frame-manager.js.map +7 -0
- package/dist/src/core/context/shared-context-layer.js +621 -0
- package/dist/src/core/context/shared-context-layer.js.map +7 -0
- package/dist/src/core/context/stack-merge-resolver.js +749 -0
- package/dist/src/core/context/stack-merge-resolver.js.map +7 -0
- package/dist/src/core/context/validation.js +130 -0
- package/dist/src/core/context/validation.js.map +7 -0
- package/dist/src/core/database/batch-operations.js +384 -0
- package/dist/src/core/database/batch-operations.js.map +7 -0
- package/dist/src/core/database/connection-pool.js +330 -0
- package/dist/src/core/database/connection-pool.js.map +7 -0
- package/dist/src/core/database/database-adapter.js +60 -0
- package/dist/src/core/database/database-adapter.js.map +7 -0
- package/dist/src/core/database/migration-manager.js +614 -0
- package/dist/src/core/database/migration-manager.js.map +7 -0
- package/dist/src/core/database/query-cache.js +298 -0
- package/dist/src/core/database/query-cache.js.map +7 -0
- package/dist/src/core/database/query-router.js +430 -0
- package/dist/src/core/database/query-router.js.map +7 -0
- package/dist/src/core/database/sqlite-adapter.js +738 -0
- package/dist/src/core/database/sqlite-adapter.js.map +7 -0
- package/dist/src/core/digest/enhanced-hybrid-digest.js +277 -0
- package/dist/src/core/digest/enhanced-hybrid-digest.js.map +7 -0
- package/dist/src/core/digest/frame-digest-integration.js +176 -0
- package/dist/src/core/digest/frame-digest-integration.js.map +7 -0
- package/dist/src/core/digest/hybrid-digest-generator.js +553 -0
- package/dist/src/core/digest/hybrid-digest-generator.js.map +7 -0
- package/dist/src/core/digest/index.js +9 -0
- package/dist/src/core/digest/index.js.map +7 -0
- package/dist/src/core/digest/types.js +25 -0
- package/dist/src/core/digest/types.js.map +7 -0
- package/dist/src/core/errors/error-utils.js +208 -0
- package/dist/src/core/errors/error-utils.js.map +7 -0
- package/dist/src/core/errors/index.js +521 -0
- package/dist/src/core/errors/index.js.map +7 -0
- package/dist/src/core/errors/recovery.js +269 -0
- package/dist/src/core/errors/recovery.js.map +7 -0
- package/dist/src/core/execution/parallel-executor.js +258 -0
- package/dist/src/core/execution/parallel-executor.js.map +7 -0
- package/dist/src/core/frame/workflow-templates.js +319 -0
- package/dist/src/core/frame/workflow-templates.js.map +7 -0
- package/dist/src/core/merge/conflict-detector.js +431 -0
- package/dist/src/core/merge/conflict-detector.js.map +7 -0
- package/dist/src/core/merge/index.js +9 -0
- package/dist/src/core/merge/index.js.map +7 -0
- package/dist/src/core/merge/resolution-engine.js +558 -0
- package/dist/src/core/merge/resolution-engine.js.map +7 -0
- package/dist/src/core/merge/stack-diff.js +532 -0
- package/dist/src/core/merge/stack-diff.js.map +7 -0
- package/dist/src/core/merge/types.js +5 -0
- package/dist/src/core/merge/types.js.map +7 -0
- package/dist/src/core/merge/unified-merge-resolver.js +303 -0
- package/dist/src/core/merge/unified-merge-resolver.js.map +7 -0
- package/dist/src/core/models/fallback-monitor.js +232 -0
- package/dist/src/core/models/fallback-monitor.js.map +7 -0
- package/dist/src/core/models/model-router.js +340 -0
- package/dist/src/core/models/model-router.js.map +7 -0
- package/dist/src/core/monitoring/error-handler.js +49 -0
- package/dist/src/core/monitoring/error-handler.js.map +7 -0
- package/dist/src/core/monitoring/logger.js +202 -0
- package/dist/src/core/monitoring/logger.js.map +7 -0
- package/dist/src/core/monitoring/metrics.js +172 -0
- package/dist/src/core/monitoring/metrics.js.map +7 -0
- package/dist/src/core/monitoring/progress-tracker.js +189 -0
- package/dist/src/core/monitoring/progress-tracker.js.map +7 -0
- package/dist/src/core/monitoring/session-monitor.js +300 -0
- package/dist/src/core/monitoring/session-monitor.js.map +7 -0
- package/dist/src/core/performance/context-cache.js +273 -0
- package/dist/src/core/performance/context-cache.js.map +7 -0
- package/dist/src/core/performance/index.js +11 -0
- package/dist/src/core/performance/index.js.map +7 -0
- package/dist/src/core/performance/lazy-context-loader.js +327 -0
- package/dist/src/core/performance/lazy-context-loader.js.map +7 -0
- package/dist/src/core/performance/monitor.js +221 -0
- package/dist/src/core/performance/monitor.js.map +7 -0
- package/dist/src/core/performance/optimized-frame-context.js +345 -0
- package/dist/src/core/performance/optimized-frame-context.js.map +7 -0
- package/dist/src/core/performance/performance-benchmark.js +277 -0
- package/dist/src/core/performance/performance-benchmark.js.map +7 -0
- package/dist/src/core/performance/performance-profiler.js +370 -0
- package/dist/src/core/performance/performance-profiler.js.map +7 -0
- package/dist/src/core/performance/streaming-jsonl-parser.js +195 -0
- package/dist/src/core/performance/streaming-jsonl-parser.js.map +7 -0
- package/dist/src/core/persistence/postgres-adapter.js +349 -0
- package/dist/src/core/persistence/postgres-adapter.js.map +7 -0
- package/dist/src/core/projects/project-isolation.js +201 -0
- package/dist/src/core/projects/project-isolation.js.map +7 -0
- package/dist/src/core/projects/project-manager.js +697 -0
- package/dist/src/core/projects/project-manager.js.map +7 -0
- package/dist/src/core/query/query-parser.js +370 -0
- package/dist/src/core/query/query-parser.js.map +7 -0
- package/dist/src/core/query/query-templates.js +321 -0
- package/dist/src/core/query/query-templates.js.map +7 -0
- package/dist/src/core/retrieval/context-retriever.js +479 -0
- package/dist/src/core/retrieval/context-retriever.js.map +7 -0
- package/dist/src/core/retrieval/index.js +8 -0
- package/dist/src/core/retrieval/index.js.map +7 -0
- package/dist/src/core/retrieval/llm-context-retrieval.js +613 -0
- package/dist/src/core/retrieval/llm-context-retrieval.js.map +7 -0
- package/dist/src/core/retrieval/llm-provider.js +151 -0
- package/dist/src/core/retrieval/llm-provider.js.map +7 -0
- package/dist/src/core/retrieval/retrieval-audit.js +236 -0
- package/dist/src/core/retrieval/retrieval-audit.js.map +7 -0
- package/dist/src/core/retrieval/summary-generator.js +589 -0
- package/dist/src/core/retrieval/summary-generator.js.map +7 -0
- package/dist/src/core/retrieval/types.js +21 -0
- package/dist/src/core/retrieval/types.js.map +7 -0
- package/dist/src/core/security/index.js +35 -0
- package/dist/src/core/security/index.js.map +7 -0
- package/dist/src/core/security/input-sanitizer.js +321 -0
- package/dist/src/core/security/input-sanitizer.js.map +7 -0
- package/dist/src/core/session/clear-survival.js +465 -0
- package/dist/src/core/session/clear-survival.js.map +7 -0
- package/dist/src/core/session/enhanced-handoff.js +792 -0
- package/dist/src/core/session/enhanced-handoff.js.map +7 -0
- package/dist/src/core/session/handoff-generator.js +343 -0
- package/dist/src/core/session/handoff-generator.js.map +7 -0
- package/dist/src/core/session/index.js +15 -0
- package/dist/src/core/session/index.js.map +7 -0
- package/dist/src/core/session/session-manager.js +347 -0
- package/dist/src/core/session/session-manager.js.map +7 -0
- package/dist/src/core/skills/index.js +7 -0
- package/dist/src/core/skills/index.js.map +7 -0
- package/dist/src/core/skills/skill-storage.js +764 -0
- package/dist/src/core/skills/skill-storage.js.map +7 -0
- package/dist/src/core/skills/types.js +193 -0
- package/dist/src/core/skills/types.js.map +7 -0
- package/dist/src/core/storage/chromadb-adapter.js +354 -0
- package/dist/src/core/storage/chromadb-adapter.js.map +7 -0
- package/dist/src/core/storage/infinite-storage.js +510 -0
- package/dist/src/core/storage/infinite-storage.js.map +7 -0
- package/dist/src/core/storage/remote-storage.js +489 -0
- package/dist/src/core/storage/remote-storage.js.map +7 -0
- package/dist/src/core/storage/two-tier-storage.js +766 -0
- package/dist/src/core/storage/two-tier-storage.js.map +7 -0
- package/dist/src/core/trace/cli-trace-wrapper.js +132 -0
- package/dist/src/core/trace/cli-trace-wrapper.js.map +7 -0
- package/dist/src/core/trace/db-trace-wrapper.js +247 -0
- package/dist/src/core/trace/db-trace-wrapper.js.map +7 -0
- package/dist/src/core/trace/debug-trace.js +417 -0
- package/dist/src/core/trace/debug-trace.js.map +7 -0
- package/dist/src/core/trace/index.js +109 -0
- package/dist/src/core/trace/index.js.map +7 -0
- package/dist/src/core/trace/linear-api-wrapper.js +178 -0
- package/dist/src/core/trace/linear-api-wrapper.js.map +7 -0
- package/dist/src/core/trace/trace-detector.js +528 -0
- package/dist/src/core/trace/trace-detector.js.map +7 -0
- package/dist/src/core/trace/trace-store.js +345 -0
- package/dist/src/core/trace/trace-store.js.map +7 -0
- package/dist/src/core/trace/types.js +77 -0
- package/dist/src/core/trace/types.js.map +7 -0
- package/dist/src/core/types.js +5 -0
- package/dist/src/core/types.js.map +7 -0
- package/dist/src/core/utils/async-mutex.js +114 -0
- package/dist/src/core/utils/async-mutex.js.map +7 -0
- package/dist/src/core/utils/compression.js +83 -0
- package/dist/src/core/utils/compression.js.map +7 -0
- package/dist/src/core/utils/update-checker.js +218 -0
- package/dist/src/core/utils/update-checker.js.map +7 -0
- package/dist/src/core/worktree/worktree-manager.js +465 -0
- package/dist/src/core/worktree/worktree-manager.js.map +7 -0
- package/dist/src/daemon/daemon-config.js +149 -0
- package/dist/src/daemon/daemon-config.js.map +7 -0
- package/dist/src/daemon/services/context-service.js +122 -0
- package/dist/src/daemon/services/context-service.js.map +7 -0
- package/dist/src/daemon/services/linear-service.js +136 -0
- package/dist/src/daemon/services/linear-service.js.map +7 -0
- package/dist/src/daemon/session-daemon.js +312 -0
- package/dist/src/daemon/session-daemon.js.map +7 -0
- package/dist/src/daemon/unified-daemon.js +276 -0
- package/dist/src/daemon/unified-daemon.js.map +7 -0
- package/dist/src/features/analytics/api/analytics-api.js +287 -0
- package/dist/src/features/analytics/api/analytics-api.js.map +7 -0
- package/dist/src/features/analytics/core/analytics-service.js +282 -0
- package/dist/src/features/analytics/core/analytics-service.js.map +7 -0
- package/dist/src/features/analytics/index.js +18 -0
- package/dist/src/features/analytics/index.js.map +7 -0
- package/dist/src/features/analytics/queries/metrics-queries.js +277 -0
- package/dist/src/features/analytics/queries/metrics-queries.js.map +7 -0
- package/dist/src/features/analytics/types/metrics.js +5 -0
- package/dist/src/features/analytics/types/metrics.js.map +7 -0
- package/dist/src/features/browser/browser-mcp.js +492 -0
- package/dist/src/features/browser/browser-mcp.js.map +7 -0
- package/dist/src/features/sweep/index.js +20 -0
- package/dist/src/features/sweep/index.js.map +7 -0
- package/dist/src/features/sweep/prediction-client.js +155 -0
- package/dist/src/features/sweep/prediction-client.js.map +7 -0
- package/dist/src/features/sweep/prompt-builder.js +85 -0
- package/dist/src/features/sweep/prompt-builder.js.map +7 -0
- package/dist/src/features/sweep/pty-wrapper.js +171 -0
- package/dist/src/features/sweep/pty-wrapper.js.map +7 -0
- package/dist/src/features/sweep/state-watcher.js +87 -0
- package/dist/src/features/sweep/state-watcher.js.map +7 -0
- package/dist/src/features/sweep/status-bar.js +88 -0
- package/dist/src/features/sweep/status-bar.js.map +7 -0
- package/dist/src/features/sweep/sweep-server-manager.js +226 -0
- package/dist/src/features/sweep/sweep-server-manager.js.map +7 -0
- package/dist/src/features/sweep/tab-interceptor.js +38 -0
- package/dist/src/features/sweep/tab-interceptor.js.map +7 -0
- package/dist/src/features/sweep/types.js +18 -0
- package/dist/src/features/sweep/types.js.map +7 -0
- package/dist/src/features/tasks/linear-task-manager.js +487 -0
- package/dist/src/features/tasks/linear-task-manager.js.map +7 -0
- package/dist/src/features/tasks/task-aware-context.js +410 -0
- package/dist/src/features/tasks/task-aware-context.js.map +7 -0
- package/dist/src/features/tui/simple-monitor.js +116 -0
- package/dist/src/features/tui/simple-monitor.js.map +7 -0
- package/dist/src/features/tui/swarm-monitor.js +648 -0
- package/dist/src/features/tui/swarm-monitor.js.map +7 -0
- package/dist/src/features/web/client/stores/task-store.js +26 -0
- package/dist/src/features/web/client/stores/task-store.js.map +7 -0
- package/dist/src/features/web/server/index.js +194 -0
- package/dist/src/features/web/server/index.js.map +7 -0
- package/dist/src/hooks/auto-background.js +151 -0
- package/dist/src/hooks/auto-background.js.map +7 -0
- package/dist/src/hooks/claude-code-whatsapp-hook.js +197 -0
- package/dist/src/hooks/claude-code-whatsapp-hook.js.map +7 -0
- package/dist/src/hooks/config.js +150 -0
- package/dist/src/hooks/config.js.map +7 -0
- package/dist/src/hooks/daemon.js +364 -0
- package/dist/src/hooks/daemon.js.map +7 -0
- package/dist/src/hooks/events.js +58 -0
- package/dist/src/hooks/events.js.map +7 -0
- package/dist/src/hooks/index.js +12 -0
- package/dist/src/hooks/index.js.map +7 -0
- package/dist/src/hooks/linear-task-picker.js +186 -0
- package/dist/src/hooks/linear-task-picker.js.map +7 -0
- package/dist/src/hooks/schemas.js +197 -0
- package/dist/src/hooks/schemas.js.map +7 -0
- package/dist/src/hooks/secure-fs.js +49 -0
- package/dist/src/hooks/secure-fs.js.map +7 -0
- package/dist/src/hooks/security-logger.js +155 -0
- package/dist/src/hooks/security-logger.js.map +7 -0
- package/dist/src/hooks/session-summary.js +222 -0
- package/dist/src/hooks/session-summary.js.map +7 -0
- package/dist/src/hooks/sms-action-runner.js +371 -0
- package/dist/src/hooks/sms-action-runner.js.map +7 -0
- package/dist/src/hooks/sms-notify.js +506 -0
- package/dist/src/hooks/sms-notify.js.map +7 -0
- package/dist/src/hooks/sms-watcher.js +93 -0
- package/dist/src/hooks/sms-watcher.js.map +7 -0
- package/dist/src/hooks/sms-webhook.js +555 -0
- package/dist/src/hooks/sms-webhook.js.map +7 -0
- package/dist/src/hooks/whatsapp-commands.js +479 -0
- package/dist/src/hooks/whatsapp-commands.js.map +7 -0
- package/dist/src/hooks/whatsapp-scheduler.js +317 -0
- package/dist/src/hooks/whatsapp-scheduler.js.map +7 -0
- package/dist/src/hooks/whatsapp-sync.js +409 -0
- package/dist/src/hooks/whatsapp-sync.js.map +7 -0
- package/dist/src/index.js +25 -0
- package/dist/src/index.js.map +7 -0
- package/dist/src/integrations/anthropic/client.js +263 -0
- package/dist/src/integrations/anthropic/client.js.map +7 -0
- package/dist/src/integrations/claude-code/agent-bridge.js +768 -0
- package/dist/src/integrations/claude-code/agent-bridge.js.map +7 -0
- package/dist/src/integrations/claude-code/enhanced-pre-clear-hooks.js +459 -0
- package/dist/src/integrations/claude-code/enhanced-pre-clear-hooks.js.map +7 -0
- package/dist/src/integrations/claude-code/lifecycle-hooks.js +254 -0
- package/dist/src/integrations/claude-code/lifecycle-hooks.js.map +7 -0
- package/dist/src/integrations/claude-code/post-task-hooks.js +545 -0
- package/dist/src/integrations/claude-code/post-task-hooks.js.map +7 -0
- package/dist/src/integrations/claude-code/subagent-client-stub.js +20 -0
- package/dist/src/integrations/claude-code/subagent-client-stub.js.map +7 -0
- package/dist/src/integrations/claude-code/subagent-client.js +511 -0
- package/dist/src/integrations/claude-code/subagent-client.js.map +7 -0
- package/dist/src/integrations/claude-code/task-coordinator.js +360 -0
- package/dist/src/integrations/claude-code/task-coordinator.js.map +7 -0
- package/dist/src/integrations/linear/auth.js +337 -0
- package/dist/src/integrations/linear/auth.js.map +7 -0
- package/dist/src/integrations/linear/auto-sync.js +258 -0
- package/dist/src/integrations/linear/auto-sync.js.map +7 -0
- package/dist/src/integrations/linear/client.js +634 -0
- package/dist/src/integrations/linear/client.js.map +7 -0
- package/dist/src/integrations/linear/config.js +130 -0
- package/dist/src/integrations/linear/config.js.map +7 -0
- package/dist/src/integrations/linear/migration.js +361 -0
- package/dist/src/integrations/linear/migration.js.map +7 -0
- package/dist/src/integrations/linear/oauth-server.js +454 -0
- package/dist/src/integrations/linear/oauth-server.js.map +7 -0
- package/dist/src/integrations/linear/rest-client.js +213 -0
- package/dist/src/integrations/linear/rest-client.js.map +7 -0
- package/dist/src/integrations/linear/sync-manager.js +236 -0
- package/dist/src/integrations/linear/sync-manager.js.map +7 -0
- package/dist/src/integrations/linear/sync-service.js +231 -0
- package/dist/src/integrations/linear/sync-service.js.map +7 -0
- package/dist/src/integrations/linear/sync.js +782 -0
- package/dist/src/integrations/linear/sync.js.map +7 -0
- package/dist/src/integrations/linear/types.js +5 -0
- package/dist/src/integrations/linear/types.js.map +7 -0
- package/dist/src/integrations/linear/unified-sync.js +589 -0
- package/dist/src/integrations/linear/unified-sync.js.map +7 -0
- package/dist/src/integrations/linear/webhook-handler.js +219 -0
- package/dist/src/integrations/linear/webhook-handler.js.map +7 -0
- package/dist/src/integrations/linear/webhook-server.js +218 -0
- package/dist/src/integrations/linear/webhook-server.js.map +7 -0
- package/dist/src/integrations/linear/webhook.js +291 -0
- package/dist/src/integrations/linear/webhook.js.map +7 -0
- package/dist/src/integrations/mcp/handlers/code-execution-handlers.js +266 -0
- package/dist/src/integrations/mcp/handlers/code-execution-handlers.js.map +7 -0
- package/dist/src/integrations/mcp/handlers/context-handlers.js +257 -0
- package/dist/src/integrations/mcp/handlers/context-handlers.js.map +7 -0
- package/dist/src/integrations/mcp/handlers/discovery-handlers.js +497 -0
- package/dist/src/integrations/mcp/handlers/discovery-handlers.js.map +7 -0
- package/dist/src/integrations/mcp/handlers/index.js +166 -0
- package/dist/src/integrations/mcp/handlers/index.js.map +7 -0
- package/dist/src/integrations/mcp/handlers/linear-handlers.js +247 -0
- package/dist/src/integrations/mcp/handlers/linear-handlers.js.map +7 -0
- package/dist/src/integrations/mcp/handlers/skill-handlers.js +529 -0
- package/dist/src/integrations/mcp/handlers/skill-handlers.js.map +7 -0
- package/dist/src/integrations/mcp/handlers/task-handlers.js +239 -0
- package/dist/src/integrations/mcp/handlers/task-handlers.js.map +7 -0
- package/dist/src/integrations/mcp/handlers/trace-handlers.js +308 -0
- package/dist/src/integrations/mcp/handlers/trace-handlers.js.map +7 -0
- package/dist/src/integrations/mcp/index.js +23 -0
- package/dist/src/integrations/mcp/index.js.map +7 -0
- package/dist/src/integrations/mcp/middleware/tool-scoring.js +356 -0
- package/dist/src/integrations/mcp/middleware/tool-scoring.js.map +7 -0
- package/dist/src/integrations/mcp/refactored-server.js +374 -0
- package/dist/src/integrations/mcp/refactored-server.js.map +7 -0
- package/dist/src/integrations/mcp/remote-server.js +682 -0
- package/dist/src/integrations/mcp/remote-server.js.map +7 -0
- package/dist/src/integrations/mcp/schemas.js +147 -0
- package/dist/src/integrations/mcp/schemas.js.map +7 -0
- package/dist/src/integrations/mcp/server.js +1975 -0
- package/dist/src/integrations/mcp/server.js.map +7 -0
- package/dist/src/integrations/mcp/tool-definitions-code.js +125 -0
- package/dist/src/integrations/mcp/tool-definitions-code.js.map +7 -0
- package/dist/src/integrations/mcp/tool-definitions.js +702 -0
- package/dist/src/integrations/mcp/tool-definitions.js.map +7 -0
- package/dist/src/integrations/ralph/bridge/ralph-stackmemory-bridge.js +860 -0
- package/dist/src/integrations/ralph/bridge/ralph-stackmemory-bridge.js.map +7 -0
- package/dist/src/integrations/ralph/context/context-budget-manager.js +301 -0
- package/dist/src/integrations/ralph/context/context-budget-manager.js.map +7 -0
- package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +360 -0
- package/dist/src/integrations/ralph/context/stackmemory-context-loader.js.map +7 -0
- package/dist/src/integrations/ralph/coordination/enhanced-coordination.js +410 -0
- package/dist/src/integrations/ralph/coordination/enhanced-coordination.js.map +7 -0
- package/dist/src/integrations/ralph/index.js +18 -0
- package/dist/src/integrations/ralph/index.js.map +7 -0
- package/dist/src/integrations/ralph/learning/pattern-learner.js +401 -0
- package/dist/src/integrations/ralph/learning/pattern-learner.js.map +7 -0
- package/dist/src/integrations/ralph/lifecycle/iteration-lifecycle.js +448 -0
- package/dist/src/integrations/ralph/lifecycle/iteration-lifecycle.js.map +7 -0
- package/dist/src/integrations/ralph/monitoring/swarm-dashboard.js +294 -0
- package/dist/src/integrations/ralph/monitoring/swarm-dashboard.js.map +7 -0
- package/dist/src/integrations/ralph/monitoring/swarm-registry.js +108 -0
- package/dist/src/integrations/ralph/monitoring/swarm-registry.js.map +7 -0
- package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js +463 -0
- package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js.map +7 -0
- package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js +400 -0
- package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js.map +7 -0
- package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js +473 -0
- package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js.map +7 -0
- package/dist/src/integrations/ralph/patterns/oracle-worker-pattern.js +388 -0
- package/dist/src/integrations/ralph/patterns/oracle-worker-pattern.js.map +7 -0
- package/dist/src/integrations/ralph/performance/performance-optimizer.js +358 -0
- package/dist/src/integrations/ralph/performance/performance-optimizer.js.map +7 -0
- package/dist/src/integrations/ralph/recovery/crash-recovery.js +462 -0
- package/dist/src/integrations/ralph/recovery/crash-recovery.js.map +7 -0
- package/dist/src/integrations/ralph/state/state-reconciler.js +404 -0
- package/dist/src/integrations/ralph/state/state-reconciler.js.map +7 -0
- package/dist/src/integrations/ralph/swarm/git-workflow-manager.js +428 -0
- package/dist/src/integrations/ralph/swarm/git-workflow-manager.js.map +7 -0
- package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +996 -0
- package/dist/src/integrations/ralph/swarm/swarm-coordinator.js.map +7 -0
- package/dist/src/integrations/ralph/types.js +5 -0
- package/dist/src/integrations/ralph/types.js.map +7 -0
- package/dist/src/integrations/ralph/visualization/ralph-debugger.js +585 -0
- package/dist/src/integrations/ralph/visualization/ralph-debugger.js.map +7 -0
- package/dist/src/mcp/stackmemory-mcp-server.js +554 -0
- package/dist/src/mcp/stackmemory-mcp-server.js.map +7 -0
- package/dist/src/middleware/exponential-rate-limiter.js +289 -0
- package/dist/src/middleware/exponential-rate-limiter.js.map +7 -0
- package/dist/src/models/user.model.js +358 -0
- package/dist/src/models/user.model.js.map +7 -0
- package/dist/src/servers/production/auth-middleware.js +528 -0
- package/dist/src/servers/production/auth-middleware.js.map +7 -0
- package/dist/src/services/config-service.js +65 -0
- package/dist/src/services/config-service.js.map +7 -0
- package/dist/src/services/context-service.js +194 -0
- package/dist/src/services/context-service.js.map +7 -0
- package/dist/src/skills/api-discovery.js +354 -0
- package/dist/src/skills/api-discovery.js.map +7 -0
- package/dist/src/skills/api-skill.js +475 -0
- package/dist/src/skills/api-skill.js.map +7 -0
- package/dist/src/skills/claude-skills.js +1061 -0
- package/dist/src/skills/claude-skills.js.map +7 -0
- package/dist/src/skills/dashboard-launcher.js +216 -0
- package/dist/src/skills/dashboard-launcher.js.map +7 -0
- package/dist/src/skills/recursive-agent-orchestrator.js +575 -0
- package/dist/src/skills/recursive-agent-orchestrator.js.map +7 -0
- package/dist/src/skills/repo-ingestion-skill.js +609 -0
- package/dist/src/skills/repo-ingestion-skill.js.map +7 -0
- package/dist/src/skills/unified-rlm-orchestrator.js +404 -0
- package/dist/src/skills/unified-rlm-orchestrator.js.map +7 -0
- package/dist/src/types/task.js +5 -0
- package/dist/src/types/task.js.map +7 -0
- package/dist/src/utils/env.js +50 -0
- package/dist/src/utils/env.js.map +7 -0
- package/dist/src/utils/formatting.js +62 -0
- package/dist/src/utils/formatting.js.map +7 -0
- package/dist/src/utils/process-cleanup.js +136 -0
- package/dist/src/utils/process-cleanup.js.map +7 -0
- package/package.json +4 -3
- package/scripts/create-cleanup-issues.js +302 -0
- package/scripts/demos/browser-test.ts +39 -0
- package/scripts/demos/ralph-integration-demo.ts +244 -0
- package/scripts/demos/trace-demo.ts +214 -0
- package/scripts/demos/trace-detector.demo.ts +171 -0
- package/scripts/demos/trace-test.ts +67 -0
- package/scripts/initialize.ts +16 -7
- package/scripts/install.sh +14 -62
- package/scripts/status.ts +111 -46
- package/scripts/test-claude-config.sh +123 -0
- package/scripts/validate-claude-config.sh +155 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/hooks/security-logger.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Security Event Logger for hooks\n * Logs security-relevant events for audit trail\n */\n\nimport { appendFileSync, existsSync, readFileSync, writeFileSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport { ensureSecureDir } from './secure-fs.js';\n\nconst LOG_DIR = join(homedir(), '.stackmemory', 'logs');\nconst SECURITY_LOG = join(LOG_DIR, 'security.log');\nconst MAX_LOG_ENTRIES = 10000;\n\nexport type SecurityEventType =\n | 'auth_success'\n | 'auth_failure'\n | 'rate_limit'\n | 'action_allowed'\n | 'action_blocked'\n | 'config_invalid'\n | 'config_loaded'\n | 'webhook_request'\n | 'signature_invalid'\n | 'body_too_large'\n | 'content_type_invalid'\n | 'cleanup';\n\nexport interface SecurityEvent {\n timestamp: string;\n type: SecurityEventType;\n source: string;\n message: string;\n details?: Record<string, unknown>;\n ip?: string;\n}\n\nlet logCount = 0;\n\n/**\n * Log a security event\n */\nexport function logSecurityEvent(\n type: SecurityEventType,\n source: string,\n message: string,\n details?: Record<string, unknown>,\n ip?: string\n): void {\n try {\n ensureSecureDir(LOG_DIR);\n\n const event: SecurityEvent = {\n timestamp: new Date().toISOString(),\n type,\n source,\n message,\n ...(details && { details }),\n ...(ip && { ip: maskIp(ip) }),\n };\n\n const logLine = JSON.stringify(event) + '\\n';\n appendFileSync(SECURITY_LOG, logLine, { mode: 0o600 });\n\n logCount++;\n\n // Rotate log if too large (simple rotation - truncate)\n if (logCount > MAX_LOG_ENTRIES) {\n rotateLog();\n }\n } catch {\n // Don't let logging failures break the application\n }\n}\n\n/**\n * Mask IP address for privacy (keep first two octets)\n */\nfunction maskIp(ip: string): string {\n if (!ip) return 'unknown';\n\n // Handle IPv6 localhost\n if (ip === '::1' || ip === '::ffff:127.0.0.1') return '127.0.0.x';\n\n // Handle IPv4\n const parts = ip.replace('::ffff:', '').split('.');\n if (parts.length === 4) {\n return `${parts[0]}.${parts[1]}.x.x`;\n }\n\n // Handle IPv6 - mask last 64 bits\n if (ip.includes(':')) {\n const segments = ip.split(':');\n if (segments.length >= 4) {\n return segments.slice(0, 4).join(':') + ':x:x:x:x';\n }\n }\n\n return 'masked';\n}\n\n/**\n * Simple log rotation - keep last half of entries\n */\nfunction rotateLog(): void {\n try {\n if (existsSync(SECURITY_LOG)) {\n const content = readFileSync(SECURITY_LOG, 'utf8');\n const lines = content.trim().split('\\n');\n const keepLines = lines.slice(-MAX_LOG_ENTRIES / 2);\n writeFileSync(SECURITY_LOG, keepLines.join('\\n') + '\\n', { mode: 0o600 });\n logCount = keepLines.length;\n }\n } catch {\n // Ignore rotation errors\n }\n}\n\n// Convenience functions for common events\n\nexport function logAuthSuccess(\n source: string,\n details?: Record<string, unknown>\n): void {\n logSecurityEvent(\n 'auth_success',\n source,\n 'Authentication successful',\n details\n );\n}\n\nexport function logAuthFailure(\n source: string,\n reason: string,\n ip?: string,\n details?: Record<string, unknown>\n): void {\n logSecurityEvent(\n 'auth_failure',\n source,\n `Authentication failed: ${reason}`,\n details,\n ip\n );\n}\n\nexport function logRateLimit(source: string, ip: string): void {\n logSecurityEvent('rate_limit', source, 'Rate limit exceeded', undefined, ip);\n}\n\nexport function logActionAllowed(source: string, action: string): void {\n logSecurityEvent(\n 'action_allowed',\n source,\n `Action executed: ${action.substring(0, 100)}`\n );\n}\n\nexport function logActionBlocked(\n source: string,\n action: string,\n reason: string\n): void {\n logSecurityEvent('action_blocked', source, `Action blocked: ${reason}`, {\n action: action.substring(0, 100),\n });\n}\n\nexport function logConfigInvalid(source: string, errors: string[]): void {\n logSecurityEvent('config_invalid', source, 'Invalid config rejected', {\n errors: errors.slice(0, 5),\n });\n}\n\nexport function logWebhookRequest(\n source: string,\n method: string,\n path: string,\n ip?: string\n): void {\n logSecurityEvent(\n 'webhook_request',\n source,\n `${method} ${path}`,\n undefined,\n ip\n );\n}\n\nexport function logSignatureInvalid(source: string, ip?: string): void {\n logSecurityEvent(\n 'signature_invalid',\n source,\n 'Invalid request signature',\n undefined,\n ip\n );\n}\n\nexport function logBodyTooLarge(\n source: string,\n size: number,\n ip?: string\n): void {\n logSecurityEvent(\n 'body_too_large',\n source,\n `Request body too large: ${size} bytes`,\n undefined,\n ip\n );\n}\n\nexport function logContentTypeInvalid(\n source: string,\n contentType: string,\n ip?: string\n): void {\n logSecurityEvent(\n 'content_type_invalid',\n source,\n `Invalid content type: ${contentType}`,\n undefined,\n ip\n );\n}\n\nexport function logCleanup(\n source: string,\n expiredPrompts: number,\n oldActions: number\n): void {\n if (expiredPrompts > 0 || oldActions > 0) {\n logSecurityEvent('cleanup', source, 'Cleanup completed', {\n expiredPrompts,\n oldActions,\n });\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { fileURLToPath as __fileURLToPath } from 'url';
|
|
2
|
+
import { dirname as __pathDirname } from 'path';
|
|
3
|
+
const __filename = __fileURLToPath(import.meta.url);
|
|
4
|
+
const __dirname = __pathDirname(__filename);
|
|
5
|
+
import { execSync } from "child_process";
|
|
6
|
+
import { pickNextLinearTask } from "./linear-task-picker.js";
|
|
7
|
+
function formatDuration(ms) {
|
|
8
|
+
const seconds = Math.floor(ms / 1e3);
|
|
9
|
+
const minutes = Math.floor(seconds / 60);
|
|
10
|
+
const hours = Math.floor(minutes / 60);
|
|
11
|
+
if (hours > 0) {
|
|
12
|
+
return `${hours}h ${minutes % 60}min`;
|
|
13
|
+
}
|
|
14
|
+
if (minutes > 0) {
|
|
15
|
+
return `${minutes}min`;
|
|
16
|
+
}
|
|
17
|
+
return `${seconds}s`;
|
|
18
|
+
}
|
|
19
|
+
function getCurrentBranch() {
|
|
20
|
+
try {
|
|
21
|
+
return execSync("git rev-parse --abbrev-ref HEAD", {
|
|
22
|
+
encoding: "utf8",
|
|
23
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
24
|
+
}).trim();
|
|
25
|
+
} catch {
|
|
26
|
+
return "unknown";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function hasUncommittedChanges() {
|
|
30
|
+
try {
|
|
31
|
+
const status = execSync("git status --porcelain", {
|
|
32
|
+
encoding: "utf8",
|
|
33
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
34
|
+
});
|
|
35
|
+
const lines = status.trim().split("\n").filter(Boolean);
|
|
36
|
+
return { changed: lines.length > 0, count: lines.length };
|
|
37
|
+
} catch {
|
|
38
|
+
return { changed: false, count: 0 };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function isInWorktree() {
|
|
42
|
+
try {
|
|
43
|
+
execSync("git rev-parse --is-inside-work-tree", {
|
|
44
|
+
encoding: "utf8",
|
|
45
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
46
|
+
});
|
|
47
|
+
const gitDir = execSync("git rev-parse --git-dir", {
|
|
48
|
+
encoding: "utf8",
|
|
49
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
50
|
+
}).trim();
|
|
51
|
+
return gitDir.includes(".git/worktrees/");
|
|
52
|
+
} catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function hasTestScript() {
|
|
57
|
+
try {
|
|
58
|
+
const packageJson = execSync("cat package.json", {
|
|
59
|
+
encoding: "utf8",
|
|
60
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
61
|
+
});
|
|
62
|
+
const pkg = JSON.parse(packageJson);
|
|
63
|
+
return !!(pkg.scripts?.test || pkg.scripts?.["test:run"]);
|
|
64
|
+
} catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async function generateSuggestions(context) {
|
|
69
|
+
const suggestions = [];
|
|
70
|
+
let keyIndex = 1;
|
|
71
|
+
const changes = hasUncommittedChanges();
|
|
72
|
+
const inWorktree = isInWorktree();
|
|
73
|
+
const hasTests = hasTestScript();
|
|
74
|
+
if (context.exitCode !== 0 && context.exitCode !== null) {
|
|
75
|
+
suggestions.push({
|
|
76
|
+
key: String(keyIndex++),
|
|
77
|
+
label: "Review error logs",
|
|
78
|
+
action: "cat ~/.claude/logs/claude-*.log | tail -50",
|
|
79
|
+
priority: 100
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
if (changes.changed) {
|
|
83
|
+
suggestions.push({
|
|
84
|
+
key: String(keyIndex++),
|
|
85
|
+
label: `Commit changes (${changes.count} files)`,
|
|
86
|
+
action: "git add -A && git commit",
|
|
87
|
+
priority: 90
|
|
88
|
+
});
|
|
89
|
+
const branch = getCurrentBranch();
|
|
90
|
+
if (branch !== "main" && branch !== "master" && branch !== "unknown") {
|
|
91
|
+
suggestions.push({
|
|
92
|
+
key: String(keyIndex++),
|
|
93
|
+
label: "Create PR",
|
|
94
|
+
action: "gh pr create --fill",
|
|
95
|
+
priority: 80
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (hasTests && changes.changed) {
|
|
100
|
+
suggestions.push({
|
|
101
|
+
key: String(keyIndex++),
|
|
102
|
+
label: "Run tests",
|
|
103
|
+
action: "npm run test:run",
|
|
104
|
+
priority: 85
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
if (inWorktree) {
|
|
108
|
+
suggestions.push({
|
|
109
|
+
key: String(keyIndex++),
|
|
110
|
+
label: "Merge to main",
|
|
111
|
+
action: "cwm",
|
|
112
|
+
// custom alias
|
|
113
|
+
priority: 70
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
const linearTask = await pickNextLinearTask({ preferTestTasks: true });
|
|
118
|
+
if (linearTask) {
|
|
119
|
+
suggestions.push({
|
|
120
|
+
key: String(keyIndex++),
|
|
121
|
+
label: `Start: ${linearTask.identifier} - ${linearTask.title.substring(0, 40)}${linearTask.title.length > 40 ? "..." : ""}${linearTask.hasTestRequirements ? " (has tests)" : ""}`,
|
|
122
|
+
action: `stackmemory task start ${linearTask.id} --assign-me`,
|
|
123
|
+
priority: 60
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
} catch {
|
|
127
|
+
}
|
|
128
|
+
const durationMs = Date.now() - context.sessionStartTime;
|
|
129
|
+
if (durationMs > 30 * 60 * 1e3) {
|
|
130
|
+
suggestions.push({
|
|
131
|
+
key: String(keyIndex++),
|
|
132
|
+
label: "Take a break",
|
|
133
|
+
action: 'echo "Great work! Time for a coffee break."',
|
|
134
|
+
priority: 10
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
suggestions.sort((a, b) => b.priority - a.priority);
|
|
138
|
+
if (suggestions.length < 2) {
|
|
139
|
+
if (suggestions.length === 0) {
|
|
140
|
+
suggestions.push({
|
|
141
|
+
key: "1",
|
|
142
|
+
label: "Start new Claude session",
|
|
143
|
+
action: "claude-sm",
|
|
144
|
+
priority: 50
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
if (suggestions.length < 2) {
|
|
148
|
+
suggestions.push({
|
|
149
|
+
key: "2",
|
|
150
|
+
label: "View session logs",
|
|
151
|
+
action: "cat ~/.claude/logs/claude-*.log | tail -30",
|
|
152
|
+
priority: 40
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
suggestions.forEach((s, i) => {
|
|
157
|
+
s.key = String(i + 1);
|
|
158
|
+
});
|
|
159
|
+
return suggestions;
|
|
160
|
+
}
|
|
161
|
+
async function generateSessionSummary(context) {
|
|
162
|
+
const durationMs = Date.now() - context.sessionStartTime;
|
|
163
|
+
const duration = formatDuration(durationMs);
|
|
164
|
+
const branch = context.branch || getCurrentBranch();
|
|
165
|
+
let status = "success";
|
|
166
|
+
if (context.exitCode !== 0 && context.exitCode !== null) {
|
|
167
|
+
status = "error";
|
|
168
|
+
}
|
|
169
|
+
const suggestions = await generateSuggestions(context);
|
|
170
|
+
let linearTask;
|
|
171
|
+
try {
|
|
172
|
+
linearTask = await pickNextLinearTask({ preferTestTasks: true });
|
|
173
|
+
} catch {
|
|
174
|
+
}
|
|
175
|
+
return {
|
|
176
|
+
duration,
|
|
177
|
+
exitCode: context.exitCode,
|
|
178
|
+
branch,
|
|
179
|
+
status,
|
|
180
|
+
suggestions,
|
|
181
|
+
linearTask
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
function formatSummaryMessage(summary, sessionId) {
|
|
185
|
+
const statusEmoji = summary.status === "success" ? "" : "";
|
|
186
|
+
const exitInfo = summary.exitCode !== null ? ` | Exit: ${summary.exitCode}` : "";
|
|
187
|
+
const sessionInfo = sessionId ? ` | Session: ${sessionId}` : "";
|
|
188
|
+
let message = `Claude session complete ${statusEmoji}
|
|
189
|
+
`;
|
|
190
|
+
message += `Duration: ${summary.duration}${exitInfo}${sessionInfo}
|
|
191
|
+
`;
|
|
192
|
+
message += `Branch: ${summary.branch}
|
|
193
|
+
`;
|
|
194
|
+
if (sessionId) {
|
|
195
|
+
message += `View: https://claude.ai/chat/${sessionId}
|
|
196
|
+
`;
|
|
197
|
+
}
|
|
198
|
+
message += "\n";
|
|
199
|
+
if (summary.suggestions.length > 0) {
|
|
200
|
+
message += `What to do next:
|
|
201
|
+
`;
|
|
202
|
+
for (const s of summary.suggestions.slice(0, 4)) {
|
|
203
|
+
message += `${s.key}. ${s.label}
|
|
204
|
+
`;
|
|
205
|
+
}
|
|
206
|
+
message += `
|
|
207
|
+
Reply with number or custom action`;
|
|
208
|
+
} else {
|
|
209
|
+
message += `No pending actions. Nice work!`;
|
|
210
|
+
}
|
|
211
|
+
return message;
|
|
212
|
+
}
|
|
213
|
+
function getActionForKey(suggestions, key) {
|
|
214
|
+
const suggestion = suggestions.find((s) => s.key === key);
|
|
215
|
+
return suggestion?.action || null;
|
|
216
|
+
}
|
|
217
|
+
export {
|
|
218
|
+
formatSummaryMessage,
|
|
219
|
+
generateSessionSummary,
|
|
220
|
+
getActionForKey
|
|
221
|
+
};
|
|
222
|
+
//# sourceMappingURL=session-summary.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/hooks/session-summary.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Session Summary Generator\n * Generates intelligent suggestions for what to do next after a Claude session\n */\n\nimport { execSync } from 'child_process';\nimport { pickNextLinearTask, TaskSuggestion } from './linear-task-picker.js';\n\nexport interface SessionContext {\n instanceId: string;\n exitCode: number | null;\n sessionStartTime: number;\n worktreePath?: string;\n branch?: string;\n task?: string;\n}\n\nexport interface Suggestion {\n key: string;\n label: string;\n action: string;\n priority: number;\n}\n\nexport interface SessionSummary {\n duration: string;\n exitCode: number | null;\n branch: string;\n status: 'success' | 'error' | 'interrupted';\n suggestions: Suggestion[];\n linearTask?: TaskSuggestion;\n}\n\n/**\n * Format duration in human-readable form\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 if (hours > 0) {\n return `${hours}h ${minutes % 60}min`;\n }\n if (minutes > 0) {\n return `${minutes}min`;\n }\n return `${seconds}s`;\n}\n\n/**\n * Get current git branch\n */\nfunction getCurrentBranch(): string {\n try {\n return execSync('git rev-parse --abbrev-ref HEAD', {\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim();\n } catch {\n return 'unknown';\n }\n}\n\n/**\n * Check for uncommitted changes\n */\nfunction hasUncommittedChanges(): { changed: boolean; count: number } {\n try {\n const status = execSync('git status --porcelain', {\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n const lines = status.trim().split('\\n').filter(Boolean);\n return { changed: lines.length > 0, count: lines.length };\n } catch {\n return { changed: false, count: 0 };\n }\n}\n\n/**\n * Check if we're in a worktree\n */\nfunction isInWorktree(): boolean {\n try {\n execSync('git rev-parse --is-inside-work-tree', {\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n // Check if it's a worktree (not the main repo)\n const gitDir = execSync('git rev-parse --git-dir', {\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim();\n return gitDir.includes('.git/worktrees/');\n } catch {\n return false;\n }\n}\n\n/**\n * Check if tests exist and might need running\n */\nfunction hasTestScript(): boolean {\n try {\n const packageJson = execSync('cat package.json', {\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n const pkg = JSON.parse(packageJson);\n return !!(pkg.scripts?.test || pkg.scripts?.['test:run']);\n } catch {\n return false;\n }\n}\n\n/**\n * Generate suggestions based on session context\n */\nasync function generateSuggestions(\n context: SessionContext\n): Promise<Suggestion[]> {\n const suggestions: Suggestion[] = [];\n let keyIndex = 1;\n\n const changes = hasUncommittedChanges();\n const inWorktree = isInWorktree();\n const hasTests = hasTestScript();\n\n // Error case - suggest reviewing logs\n if (context.exitCode !== 0 && context.exitCode !== null) {\n suggestions.push({\n key: String(keyIndex++),\n label: 'Review error logs',\n action: 'cat ~/.claude/logs/claude-*.log | tail -50',\n priority: 100,\n });\n }\n\n // Uncommitted changes - suggest commit or PR\n if (changes.changed) {\n suggestions.push({\n key: String(keyIndex++),\n label: `Commit changes (${changes.count} files)`,\n action: 'git add -A && git commit',\n priority: 90,\n });\n\n // If on feature branch, suggest PR\n const branch = getCurrentBranch();\n if (branch !== 'main' && branch !== 'master' && branch !== 'unknown') {\n suggestions.push({\n key: String(keyIndex++),\n label: 'Create PR',\n action: 'gh pr create --fill',\n priority: 80,\n });\n }\n }\n\n // If tests exist and changes were made, suggest running tests\n if (hasTests && changes.changed) {\n suggestions.push({\n key: String(keyIndex++),\n label: 'Run tests',\n action: 'npm run test:run',\n priority: 85,\n });\n }\n\n // Worktree-specific suggestions\n if (inWorktree) {\n suggestions.push({\n key: String(keyIndex++),\n label: 'Merge to main',\n action: 'cwm', // custom alias\n priority: 70,\n });\n }\n\n // Try to get next Linear task\n try {\n const linearTask = await pickNextLinearTask({ preferTestTasks: true });\n if (linearTask) {\n suggestions.push({\n key: String(keyIndex++),\n label: `Start: ${linearTask.identifier} - ${linearTask.title.substring(0, 40)}${linearTask.title.length > 40 ? '...' : ''}${linearTask.hasTestRequirements ? ' (has tests)' : ''}`,\n action: `stackmemory task start ${linearTask.id} --assign-me`,\n priority: 60,\n });\n }\n } catch {\n // Linear not available, skip\n }\n\n // Long session suggestion\n const durationMs = Date.now() - context.sessionStartTime;\n if (durationMs > 30 * 60 * 1000) {\n // > 30 minutes\n suggestions.push({\n key: String(keyIndex++),\n label: 'Take a break',\n action: 'echo \"Great work! Time for a coffee break.\"',\n priority: 10,\n });\n }\n\n // Sort by priority (highest first) and re-key\n suggestions.sort((a, b) => b.priority - a.priority);\n\n // Ensure minimum 2 options always\n if (suggestions.length < 2) {\n // Add default options if not enough suggestions\n if (suggestions.length === 0) {\n suggestions.push({\n key: '1',\n label: 'Start new Claude session',\n action: 'claude-sm',\n priority: 50,\n });\n }\n if (suggestions.length < 2) {\n suggestions.push({\n key: '2',\n label: 'View session logs',\n action: 'cat ~/.claude/logs/claude-*.log | tail -30',\n priority: 40,\n });\n }\n }\n\n suggestions.forEach((s, i) => {\n s.key = String(i + 1);\n });\n\n return suggestions;\n}\n\n/**\n * Generate full session summary\n */\nexport async function generateSessionSummary(\n context: SessionContext\n): Promise<SessionSummary> {\n const durationMs = Date.now() - context.sessionStartTime;\n const duration = formatDuration(durationMs);\n const branch = context.branch || getCurrentBranch();\n\n let status: 'success' | 'error' | 'interrupted' = 'success';\n if (context.exitCode !== 0 && context.exitCode !== null) {\n status = 'error';\n }\n\n const suggestions = await generateSuggestions(context);\n\n // Extract linear task if present\n let linearTask: TaskSuggestion | undefined;\n try {\n linearTask = await pickNextLinearTask({ preferTestTasks: true });\n } catch {\n // Linear not available\n }\n\n return {\n duration,\n exitCode: context.exitCode,\n branch,\n status,\n suggestions,\n linearTask,\n };\n}\n\n/**\n * Format session summary as WhatsApp message\n */\nexport function formatSummaryMessage(\n summary: SessionSummary,\n sessionId?: string\n): string {\n const statusEmoji = summary.status === 'success' ? '' : '';\n const exitInfo =\n summary.exitCode !== null ? ` | Exit: ${summary.exitCode}` : '';\n const sessionInfo = sessionId ? ` | Session: ${sessionId}` : '';\n\n let message = `Claude session complete ${statusEmoji}\\n`;\n message += `Duration: ${summary.duration}${exitInfo}${sessionInfo}\\n`;\n message += `Branch: ${summary.branch}\\n`;\n\n // Add Claude Code session URL if session ID is available\n if (sessionId) {\n message += `View: https://claude.ai/chat/${sessionId}\\n`;\n }\n\n message += '\\n';\n\n if (summary.suggestions.length > 0) {\n message += `What to do next:\\n`;\n for (const s of summary.suggestions.slice(0, 4)) {\n message += `${s.key}. ${s.label}\\n`;\n }\n message += `\\nReply with number or custom action`;\n } else {\n message += `No pending actions. Nice work!`;\n }\n\n return message;\n}\n\n/**\n * Get action for a suggestion key\n */\nexport function getActionForKey(\n suggestions: Suggestion[],\n key: string\n): string | null {\n const suggestion = suggestions.find((s) => s.key === key);\n return suggestion?.action || null;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
import { fileURLToPath as __fileURLToPath } from 'url';
|
|
2
|
+
import { dirname as __pathDirname } from 'path';
|
|
3
|
+
const __filename = __fileURLToPath(import.meta.url);
|
|
4
|
+
const __dirname = __pathDirname(__filename);
|
|
5
|
+
import { existsSync, readFileSync } from "fs";
|
|
6
|
+
import { join } from "path";
|
|
7
|
+
import { homedir } from "os";
|
|
8
|
+
import { execFileSync } from "child_process";
|
|
9
|
+
import { randomBytes } from "crypto";
|
|
10
|
+
import { writeFileSecure, ensureSecureDir } from "./secure-fs.js";
|
|
11
|
+
import { ActionQueueSchema, parseConfigSafe } from "./schemas.js";
|
|
12
|
+
import { LinearClient } from "../integrations/linear/client.js";
|
|
13
|
+
import { LinearAuthManager } from "../integrations/linear/auth.js";
|
|
14
|
+
function parseCommandArgs(command) {
|
|
15
|
+
const args = [];
|
|
16
|
+
let current = "";
|
|
17
|
+
let inSingleQuote = false;
|
|
18
|
+
let inDoubleQuote = false;
|
|
19
|
+
let escaped = false;
|
|
20
|
+
for (let i = 0; i < command.length; i++) {
|
|
21
|
+
const char = command[i];
|
|
22
|
+
if (escaped) {
|
|
23
|
+
current += char;
|
|
24
|
+
escaped = false;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (char === "\\" && !inSingleQuote) {
|
|
28
|
+
escaped = true;
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (char === "'" && !inDoubleQuote) {
|
|
32
|
+
inSingleQuote = !inSingleQuote;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (char === '"' && !inSingleQuote) {
|
|
36
|
+
inDoubleQuote = !inDoubleQuote;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (char === " " && !inSingleQuote && !inDoubleQuote) {
|
|
40
|
+
if (current.length > 0) {
|
|
41
|
+
args.push(current);
|
|
42
|
+
current = "";
|
|
43
|
+
}
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
current += char;
|
|
47
|
+
}
|
|
48
|
+
if (current.length > 0) {
|
|
49
|
+
args.push(current);
|
|
50
|
+
}
|
|
51
|
+
return args;
|
|
52
|
+
}
|
|
53
|
+
const SAFE_ACTION_PATTERNS = [
|
|
54
|
+
// Git/GitHub CLI commands (limited to safe operations)
|
|
55
|
+
{ pattern: /^gh pr (view|list|status|checks) (\d+)$/ },
|
|
56
|
+
{ pattern: /^gh pr review (\d+) --approve$/ },
|
|
57
|
+
{ pattern: /^gh pr merge (\d+) --squash$/ },
|
|
58
|
+
{ pattern: /^gh issue (view|list) (\d+)?$/ },
|
|
59
|
+
// NPM commands (limited to safe operations)
|
|
60
|
+
{ pattern: /^npm run (build|test|lint|lint:fix|test:run)$/ },
|
|
61
|
+
{ pattern: /^npm (test|run build)$/ },
|
|
62
|
+
// StackMemory commands
|
|
63
|
+
{ pattern: /^stackmemory (status|notify check|context list)$/ },
|
|
64
|
+
// Task start with optional --assign-me flag (Linear task ID is UUID format)
|
|
65
|
+
{
|
|
66
|
+
pattern: /^stackmemory task start ([a-f0-9-]{36})( --assign-me)?$/
|
|
67
|
+
},
|
|
68
|
+
// Additional StackMemory commands for mobile/WhatsApp
|
|
69
|
+
{ pattern: /^stackmemory context show$/ },
|
|
70
|
+
{ pattern: /^stackmemory task list$/ },
|
|
71
|
+
// Git commands
|
|
72
|
+
{ pattern: /^git (status|diff|log|branch)( --[a-z-]+)*$/ },
|
|
73
|
+
{ pattern: /^git add -A && git commit$/ },
|
|
74
|
+
{ pattern: /^gh pr create --fill$/ },
|
|
75
|
+
// Git log with line limit for mobile-friendly output
|
|
76
|
+
{ pattern: /^git log --oneline -\d{1,2}$/ },
|
|
77
|
+
// WhatsApp/Mobile quick commands
|
|
78
|
+
{ pattern: /^status$/i },
|
|
79
|
+
{ pattern: /^tasks$/i },
|
|
80
|
+
{ pattern: /^context$/i },
|
|
81
|
+
{ pattern: /^help$/i },
|
|
82
|
+
{ pattern: /^sync$/i },
|
|
83
|
+
// Claude Code launcher
|
|
84
|
+
{ pattern: /^claude-sm$/ },
|
|
85
|
+
// Log viewing (safe read-only)
|
|
86
|
+
{ pattern: /^tail -\d+ ~\/\.claude\/logs\/\*\.log$/ },
|
|
87
|
+
// Custom aliases (cwm = claude worktree merge)
|
|
88
|
+
{ pattern: /^cwm$/ },
|
|
89
|
+
// Simple echo/confirmation (no variables)
|
|
90
|
+
{
|
|
91
|
+
pattern: /^echo "?(Done|OK|Confirmed|Acknowledged|Great work! Time for a coffee break\.)"?$/
|
|
92
|
+
}
|
|
93
|
+
];
|
|
94
|
+
function isActionAllowed(action) {
|
|
95
|
+
const trimmed = action.trim();
|
|
96
|
+
return SAFE_ACTION_PATTERNS.some(({ pattern, validate }) => {
|
|
97
|
+
const match = trimmed.match(pattern);
|
|
98
|
+
if (!match) return false;
|
|
99
|
+
if (validate && !validate(match)) return false;
|
|
100
|
+
return true;
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
const QUEUE_PATH = join(homedir(), ".stackmemory", "sms-action-queue.json");
|
|
104
|
+
const DEFAULT_QUEUE = {
|
|
105
|
+
actions: [],
|
|
106
|
+
lastChecked: (/* @__PURE__ */ new Date()).toISOString()
|
|
107
|
+
};
|
|
108
|
+
function loadActionQueue() {
|
|
109
|
+
try {
|
|
110
|
+
if (existsSync(QUEUE_PATH)) {
|
|
111
|
+
const data = JSON.parse(readFileSync(QUEUE_PATH, "utf8"));
|
|
112
|
+
return parseConfigSafe(
|
|
113
|
+
ActionQueueSchema,
|
|
114
|
+
data,
|
|
115
|
+
DEFAULT_QUEUE,
|
|
116
|
+
"action-queue"
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
} catch {
|
|
120
|
+
}
|
|
121
|
+
return { ...DEFAULT_QUEUE, lastChecked: (/* @__PURE__ */ new Date()).toISOString() };
|
|
122
|
+
}
|
|
123
|
+
function saveActionQueue(queue) {
|
|
124
|
+
try {
|
|
125
|
+
ensureSecureDir(join(homedir(), ".stackmemory"));
|
|
126
|
+
writeFileSecure(QUEUE_PATH, JSON.stringify(queue, null, 2));
|
|
127
|
+
} catch {
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function queueAction(promptId, response, action) {
|
|
131
|
+
const queue = loadActionQueue();
|
|
132
|
+
const id = randomBytes(8).toString("hex");
|
|
133
|
+
queue.actions.push({
|
|
134
|
+
id,
|
|
135
|
+
promptId,
|
|
136
|
+
response,
|
|
137
|
+
action,
|
|
138
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
139
|
+
status: "pending"
|
|
140
|
+
});
|
|
141
|
+
saveActionQueue(queue);
|
|
142
|
+
return id;
|
|
143
|
+
}
|
|
144
|
+
function getLinearClient() {
|
|
145
|
+
const apiKey = process.env["LINEAR_API_KEY"];
|
|
146
|
+
if (apiKey && apiKey.startsWith("lin_api_")) {
|
|
147
|
+
return new LinearClient({ apiKey });
|
|
148
|
+
}
|
|
149
|
+
try {
|
|
150
|
+
const authManager = new LinearAuthManager();
|
|
151
|
+
const tokens = authManager.loadTokens();
|
|
152
|
+
if (tokens?.accessToken) {
|
|
153
|
+
return new LinearClient({ accessToken: tokens.accessToken });
|
|
154
|
+
}
|
|
155
|
+
} catch {
|
|
156
|
+
}
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
async function handleSpecialAction(action) {
|
|
160
|
+
const taskStartMatch = action.match(
|
|
161
|
+
/^stackmemory task start ([a-f0-9-]{36})( --assign-me)?$/
|
|
162
|
+
);
|
|
163
|
+
if (taskStartMatch) {
|
|
164
|
+
const issueId = taskStartMatch[1];
|
|
165
|
+
const client = getLinearClient();
|
|
166
|
+
if (!client) {
|
|
167
|
+
return {
|
|
168
|
+
handled: true,
|
|
169
|
+
success: false,
|
|
170
|
+
error: "Linear not configured. Set LINEAR_API_KEY or run stackmemory linear setup."
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
const result = await client.startIssue(issueId);
|
|
175
|
+
if (result.success && result.issue) {
|
|
176
|
+
return {
|
|
177
|
+
handled: true,
|
|
178
|
+
success: true,
|
|
179
|
+
output: `Started: ${result.issue.identifier} - ${result.issue.title}`
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
handled: true,
|
|
184
|
+
success: false,
|
|
185
|
+
error: result.error || "Failed to start issue"
|
|
186
|
+
};
|
|
187
|
+
} catch (err) {
|
|
188
|
+
return {
|
|
189
|
+
handled: true,
|
|
190
|
+
success: false,
|
|
191
|
+
error: err instanceof Error ? err.message : "Unknown error"
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return { handled: false };
|
|
196
|
+
}
|
|
197
|
+
async function executeActionSafe(action, _response) {
|
|
198
|
+
if (!isActionAllowed(action)) {
|
|
199
|
+
console.error(`[sms-action] Action not in allowlist: ${action}`);
|
|
200
|
+
return {
|
|
201
|
+
success: false,
|
|
202
|
+
error: `Action not allowed. Only pre-approved commands can be executed via SMS.`
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
const specialResult = await handleSpecialAction(action);
|
|
206
|
+
if (specialResult.handled) {
|
|
207
|
+
return {
|
|
208
|
+
success: specialResult.success || false,
|
|
209
|
+
output: specialResult.output,
|
|
210
|
+
error: specialResult.error
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
try {
|
|
214
|
+
console.log(`[sms-action] Executing safe action: ${action}`);
|
|
215
|
+
const parts = parseCommandArgs(action);
|
|
216
|
+
if (parts.length === 0) {
|
|
217
|
+
return { success: false, error: "Empty command" };
|
|
218
|
+
}
|
|
219
|
+
const cmd = parts[0];
|
|
220
|
+
const args = parts.slice(1);
|
|
221
|
+
const output = execFileSync(cmd, args, {
|
|
222
|
+
encoding: "utf8",
|
|
223
|
+
timeout: 6e4,
|
|
224
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
225
|
+
shell: false
|
|
226
|
+
// Explicitly disable shell
|
|
227
|
+
});
|
|
228
|
+
return { success: true, output };
|
|
229
|
+
} catch (err) {
|
|
230
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
231
|
+
return { success: false, error };
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function getPendingActions() {
|
|
235
|
+
const queue = loadActionQueue();
|
|
236
|
+
return queue.actions.filter((a) => a.status === "pending");
|
|
237
|
+
}
|
|
238
|
+
function markActionRunning(id) {
|
|
239
|
+
const queue = loadActionQueue();
|
|
240
|
+
const action = queue.actions.find((a) => a.id === id);
|
|
241
|
+
if (action) {
|
|
242
|
+
action.status = "running";
|
|
243
|
+
saveActionQueue(queue);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
function markActionCompleted(id, result, error) {
|
|
247
|
+
const queue = loadActionQueue();
|
|
248
|
+
const action = queue.actions.find((a) => a.id === id);
|
|
249
|
+
if (action) {
|
|
250
|
+
action.status = error ? "failed" : "completed";
|
|
251
|
+
action.result = result;
|
|
252
|
+
action.error = error;
|
|
253
|
+
saveActionQueue(queue);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
async function executeAction(action) {
|
|
257
|
+
markActionRunning(action.id);
|
|
258
|
+
const result = await executeActionSafe(action.action, action.response);
|
|
259
|
+
if (result.success) {
|
|
260
|
+
markActionCompleted(action.id, result.output);
|
|
261
|
+
} else {
|
|
262
|
+
markActionCompleted(action.id, void 0, result.error);
|
|
263
|
+
}
|
|
264
|
+
return result;
|
|
265
|
+
}
|
|
266
|
+
async function processAllPendingActions() {
|
|
267
|
+
const pending = getPendingActions();
|
|
268
|
+
let succeeded = 0;
|
|
269
|
+
let failed = 0;
|
|
270
|
+
for (const action of pending) {
|
|
271
|
+
const result = await executeAction(action);
|
|
272
|
+
if (result.success) {
|
|
273
|
+
succeeded++;
|
|
274
|
+
} else {
|
|
275
|
+
failed++;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return { processed: pending.length, succeeded, failed };
|
|
279
|
+
}
|
|
280
|
+
function cleanupOldActions() {
|
|
281
|
+
const queue = loadActionQueue();
|
|
282
|
+
const completed = queue.actions.filter(
|
|
283
|
+
(a) => a.status === "completed" || a.status === "failed"
|
|
284
|
+
);
|
|
285
|
+
if (completed.length > 50) {
|
|
286
|
+
const toRemove = completed.slice(0, completed.length - 50);
|
|
287
|
+
queue.actions = queue.actions.filter(
|
|
288
|
+
(a) => !toRemove.find((r) => r.id === a.id)
|
|
289
|
+
);
|
|
290
|
+
saveActionQueue(queue);
|
|
291
|
+
return toRemove.length;
|
|
292
|
+
}
|
|
293
|
+
return 0;
|
|
294
|
+
}
|
|
295
|
+
const ACTION_TEMPLATES = {
|
|
296
|
+
// Git/PR actions (PR numbers must be validated as integers)
|
|
297
|
+
approvePR: (prNumber) => {
|
|
298
|
+
if (!/^\d+$/.test(prNumber)) {
|
|
299
|
+
throw new Error("Invalid PR number");
|
|
300
|
+
}
|
|
301
|
+
return `gh pr review ${prNumber} --approve`;
|
|
302
|
+
},
|
|
303
|
+
mergePR: (prNumber) => {
|
|
304
|
+
if (!/^\d+$/.test(prNumber)) {
|
|
305
|
+
throw new Error("Invalid PR number");
|
|
306
|
+
}
|
|
307
|
+
return `gh pr merge ${prNumber} --squash`;
|
|
308
|
+
},
|
|
309
|
+
viewPR: (prNumber) => {
|
|
310
|
+
if (!/^\d+$/.test(prNumber)) {
|
|
311
|
+
throw new Error("Invalid PR number");
|
|
312
|
+
}
|
|
313
|
+
return `gh pr view ${prNumber}`;
|
|
314
|
+
},
|
|
315
|
+
// Build actions (no user input)
|
|
316
|
+
rebuild: () => `npm run build`,
|
|
317
|
+
retest: () => `npm run test:run`,
|
|
318
|
+
lint: () => `npm run lint:fix`,
|
|
319
|
+
// Status actions (no user input)
|
|
320
|
+
status: () => `stackmemory status`,
|
|
321
|
+
checkNotifications: () => `stackmemory notify check`
|
|
322
|
+
// REMOVED for security - these templates allowed arbitrary user input:
|
|
323
|
+
// - requestChanges (allowed arbitrary message)
|
|
324
|
+
// - closePR (could be used maliciously)
|
|
325
|
+
// - deploy/rollback (too dangerous for SMS)
|
|
326
|
+
// - verifyDeployment (allowed arbitrary URL)
|
|
327
|
+
// - notifySlack (allowed arbitrary message - command injection)
|
|
328
|
+
// - notifyTeam (allowed arbitrary message - command injection)
|
|
329
|
+
};
|
|
330
|
+
function createAction(template, ...args) {
|
|
331
|
+
const fn = ACTION_TEMPLATES[template];
|
|
332
|
+
if (typeof fn === "function") {
|
|
333
|
+
return fn(...args);
|
|
334
|
+
}
|
|
335
|
+
return fn;
|
|
336
|
+
}
|
|
337
|
+
function startActionWatcher(intervalMs = 5e3) {
|
|
338
|
+
console.log(
|
|
339
|
+
`[sms-action] Starting action watcher (interval: ${intervalMs}ms)`
|
|
340
|
+
);
|
|
341
|
+
return setInterval(() => {
|
|
342
|
+
const pending = getPendingActions();
|
|
343
|
+
if (pending.length > 0) {
|
|
344
|
+
console.log(`[sms-action] Found ${pending.length} pending action(s)`);
|
|
345
|
+
processAllPendingActions();
|
|
346
|
+
}
|
|
347
|
+
}, intervalMs);
|
|
348
|
+
}
|
|
349
|
+
function handleSMSResponse(promptId, response, action) {
|
|
350
|
+
if (action) {
|
|
351
|
+
const actionId = queueAction(promptId, response, action);
|
|
352
|
+
console.log(`[sms-action] Queued action ${actionId}: ${action}`);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
export {
|
|
356
|
+
ACTION_TEMPLATES,
|
|
357
|
+
cleanupOldActions,
|
|
358
|
+
createAction,
|
|
359
|
+
executeAction,
|
|
360
|
+
executeActionSafe,
|
|
361
|
+
getPendingActions,
|
|
362
|
+
handleSMSResponse,
|
|
363
|
+
loadActionQueue,
|
|
364
|
+
markActionCompleted,
|
|
365
|
+
markActionRunning,
|
|
366
|
+
processAllPendingActions,
|
|
367
|
+
queueAction,
|
|
368
|
+
saveActionQueue,
|
|
369
|
+
startActionWatcher
|
|
370
|
+
};
|
|
371
|
+
//# sourceMappingURL=sms-action-runner.js.map
|