@stackmemoryai/stackmemory 0.2.9 → 0.3.0
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 +512 -0
- package/dist/agents/core/agent-task-manager.js.map +7 -0
- package/dist/agents/verifiers/base-verifier.js +129 -0
- package/dist/agents/verifiers/base-verifier.js.map +7 -0
- package/dist/agents/verifiers/formatter-verifier.js +126 -0
- package/dist/agents/verifiers/formatter-verifier.js.map +7 -0
- package/dist/agents/verifiers/llm-judge.js +248 -0
- package/dist/agents/verifiers/llm-judge.js.map +7 -0
- package/dist/cli/__tests__/index.test.js +290 -0
- package/dist/cli/__tests__/index.test.js.map +7 -0
- package/dist/cli/auto-detect.js +317 -0
- package/dist/cli/auto-detect.js.map +7 -0
- package/dist/cli/browser-test.js +29 -0
- package/dist/cli/browser-test.js.map +7 -0
- package/dist/cli/claude-sm.js +369 -0
- package/dist/cli/claude-sm.js.map +7 -0
- package/dist/cli/codex-sm.js +283 -0
- package/dist/cli/codex-sm.js.map +7 -0
- package/dist/cli/commands/agent.js +286 -0
- package/dist/cli/commands/agent.js.map +7 -0
- package/dist/cli/commands/config.js +199 -0
- package/dist/cli/commands/config.js.map +7 -0
- package/dist/cli/commands/context.js +327 -0
- package/dist/cli/commands/context.js.map +7 -0
- package/dist/cli/commands/handoff.js +191 -0
- package/dist/cli/commands/handoff.js.map +7 -0
- package/dist/cli/commands/linear-test.js +115 -0
- package/dist/cli/commands/linear-test.js.map +7 -0
- package/dist/cli/commands/linear.js +378 -0
- package/dist/cli/commands/linear.js.map +7 -0
- package/dist/cli/commands/log.js +165 -0
- package/dist/cli/commands/log.js.map +7 -0
- package/dist/cli/commands/onboard.js +349 -0
- package/dist/cli/commands/onboard.js.map +7 -0
- package/dist/cli/commands/projects.js +195 -0
- package/dist/cli/commands/projects.js.map +7 -0
- package/dist/cli/commands/search.js +152 -0
- package/dist/cli/commands/search.js.map +7 -0
- package/dist/cli/commands/session.js +179 -0
- package/dist/cli/commands/session.js.map +7 -0
- package/dist/cli/commands/tasks.js +205 -0
- package/dist/cli/commands/tasks.js.map +7 -0
- package/dist/cli/commands/webhook.js +131 -0
- package/dist/cli/commands/webhook.js.map +7 -0
- package/dist/cli/commands/worktree.js +276 -0
- package/dist/cli/commands/worktree.js.map +7 -0
- package/dist/cli/index.js +953 -0
- package/dist/cli/index.js.map +7 -0
- package/dist/cli/utils/viewer.js +92 -0
- package/dist/cli/utils/viewer.js.map +7 -0
- package/dist/core/config/__tests__/config-manager.test.js +248 -0
- package/dist/core/config/__tests__/config-manager.test.js.map +7 -0
- package/dist/core/config/config-manager.js +368 -0
- package/dist/core/config/config-manager.js.map +7 -0
- package/dist/core/config/types.js +140 -0
- package/dist/core/config/types.js.map +7 -0
- package/dist/core/context/__tests__/frame-manager.test.js +879 -0
- package/dist/core/context/__tests__/frame-manager.test.js.map +7 -0
- package/dist/core/context/auto-context.js +72 -0
- package/dist/core/context/auto-context.js.map +7 -0
- package/dist/core/context/compaction-handler.js +326 -0
- package/dist/core/context/compaction-handler.js.map +7 -0
- package/dist/core/context/frame-database.js +376 -0
- package/dist/core/context/frame-database.js.map +7 -0
- package/dist/core/context/frame-digest.js +239 -0
- package/dist/core/context/frame-digest.js.map +7 -0
- package/dist/core/context/frame-manager.js +682 -0
- package/dist/core/context/frame-manager.js.map +7 -0
- package/dist/core/context/frame-stack.js +270 -0
- package/dist/core/context/frame-stack.js.map +7 -0
- package/dist/core/context/frame-types.js +1 -0
- package/dist/core/context/frame-types.js.map +7 -0
- package/dist/core/context/index.js +33 -0
- package/dist/core/context/index.js.map +7 -0
- package/dist/core/context/model-aware-compaction.js +619 -0
- package/dist/core/context/model-aware-compaction.js.map +7 -0
- package/dist/core/context/refactored-frame-manager.js +393 -0
- package/dist/core/context/refactored-frame-manager.js.map +7 -0
- package/dist/core/database/batch-operations.js +329 -0
- package/dist/core/database/batch-operations.js.map +7 -0
- package/dist/core/database/connection-pool.js +224 -0
- package/dist/core/database/connection-pool.js.map +7 -0
- package/dist/core/database/query-cache.js +284 -0
- package/dist/core/database/query-cache.js.map +7 -0
- package/dist/core/digest/__tests__/enhanced-hybrid-digest.test.js +379 -0
- package/dist/core/digest/__tests__/enhanced-hybrid-digest.test.js.map +7 -0
- package/dist/core/digest/__tests__/frame-digest-integration.test.js +230 -0
- package/dist/core/digest/__tests__/frame-digest-integration.test.js.map +7 -0
- package/dist/core/digest/enhanced-hybrid-digest.js +267 -0
- package/dist/core/digest/enhanced-hybrid-digest.js.map +7 -0
- package/dist/core/digest/frame-digest-integration.js +172 -0
- package/dist/core/digest/frame-digest-integration.js.map +7 -0
- package/dist/core/digest/hybrid-digest-generator.js +549 -0
- package/dist/core/digest/hybrid-digest-generator.js.map +7 -0
- package/dist/core/digest/index.js +5 -0
- package/dist/core/digest/index.js.map +7 -0
- package/dist/core/digest/types.js +21 -0
- package/dist/core/digest/types.js.map +7 -0
- package/dist/core/errors/__tests__/error-handling.test.js +270 -0
- package/dist/core/errors/__tests__/error-handling.test.js.map +7 -0
- package/dist/core/errors/index.js +239 -0
- package/dist/core/errors/index.js.map +7 -0
- package/dist/core/errors/recovery.js +258 -0
- package/dist/core/errors/recovery.js.map +7 -0
- package/dist/core/merge/__tests__/conflict-scenarios.test.js +414 -0
- package/dist/core/merge/__tests__/conflict-scenarios.test.js.map +7 -0
- package/dist/core/merge/conflict-detector.js +424 -0
- package/dist/core/merge/conflict-detector.js.map +7 -0
- package/dist/core/merge/index.js +5 -0
- package/dist/core/merge/index.js.map +7 -0
- package/dist/core/merge/resolution-engine.js +565 -0
- package/dist/core/merge/resolution-engine.js.map +7 -0
- package/dist/core/merge/stack-diff.js +528 -0
- package/dist/core/merge/stack-diff.js.map +7 -0
- package/dist/core/merge/types.js +1 -0
- package/dist/core/merge/types.js.map +7 -0
- package/dist/core/monitoring/error-handler.js +278 -0
- package/dist/core/monitoring/error-handler.js.map +7 -0
- package/dist/core/monitoring/logger.js +115 -0
- package/dist/core/monitoring/logger.js.map +7 -0
- package/dist/core/monitoring/metrics.js +157 -0
- package/dist/core/monitoring/metrics.js.map +7 -0
- package/dist/core/monitoring/progress-tracker.js +174 -0
- package/dist/core/monitoring/progress-tracker.js.map +7 -0
- package/dist/core/performance/context-cache.js +269 -0
- package/dist/core/performance/context-cache.js.map +7 -0
- package/dist/core/performance/index.js +7 -0
- package/dist/core/performance/index.js.map +7 -0
- package/dist/core/performance/lazy-context-loader.js +319 -0
- package/dist/core/performance/lazy-context-loader.js.map +7 -0
- package/dist/core/performance/monitor.js +217 -0
- package/dist/core/performance/monitor.js.map +7 -0
- package/dist/core/performance/optimized-frame-context.js +326 -0
- package/dist/core/performance/optimized-frame-context.js.map +7 -0
- package/dist/core/performance/performance-benchmark.js +269 -0
- package/dist/core/performance/performance-benchmark.js.map +7 -0
- package/dist/core/performance/performance-profiler.js +318 -0
- package/dist/core/performance/performance-profiler.js.map +7 -0
- package/dist/core/performance/streaming-jsonl-parser.js +187 -0
- package/dist/core/performance/streaming-jsonl-parser.js.map +7 -0
- package/dist/core/persistence/postgres-adapter.js +345 -0
- package/dist/core/persistence/postgres-adapter.js.map +7 -0
- package/dist/core/projects/project-manager.js +699 -0
- package/dist/core/projects/project-manager.js.map +7 -0
- package/dist/core/query/__tests__/query-parser.test.js +301 -0
- package/dist/core/query/__tests__/query-parser.test.js.map +7 -0
- package/dist/core/query/__tests__/query-templates.test.js +210 -0
- package/dist/core/query/__tests__/query-templates.test.js.map +7 -0
- package/dist/core/query/query-parser.js +366 -0
- package/dist/core/query/query-parser.js.map +7 -0
- package/dist/core/query/query-templates.js +317 -0
- package/dist/core/query/query-templates.js.map +7 -0
- package/dist/core/retrieval/index.js +4 -0
- package/dist/core/retrieval/index.js.map +7 -0
- package/dist/core/retrieval/llm-context-retrieval.js +577 -0
- package/dist/core/retrieval/llm-context-retrieval.js.map +7 -0
- package/dist/core/retrieval/summary-generator.js +585 -0
- package/dist/core/retrieval/summary-generator.js.map +7 -0
- package/dist/core/retrieval/types.js +17 -0
- package/dist/core/retrieval/types.js.map +7 -0
- package/dist/core/session/index.js +11 -0
- package/dist/core/session/index.js.map +7 -0
- package/dist/core/session/session-manager.js +297 -0
- package/dist/core/session/session-manager.js.map +7 -0
- package/dist/core/trace/cli-trace-wrapper.js +110 -0
- package/dist/core/trace/cli-trace-wrapper.js.map +7 -0
- package/dist/core/trace/db-trace-wrapper.js +215 -0
- package/dist/core/trace/db-trace-wrapper.js.map +7 -0
- package/dist/core/trace/debug-trace.js +385 -0
- package/dist/core/trace/debug-trace.js.map +7 -0
- package/dist/core/trace/index.js +158 -0
- package/dist/core/trace/index.js.map +7 -0
- package/dist/core/trace/linear-api-wrapper.js +169 -0
- package/dist/core/trace/linear-api-wrapper.js.map +7 -0
- package/dist/core/trace/trace-demo.js +135 -0
- package/dist/core/trace/trace-demo.js.map +7 -0
- package/dist/core/trace/trace-detector.demo.js +138 -0
- package/dist/core/trace/trace-detector.demo.js.map +7 -0
- package/dist/core/trace/trace-detector.js +386 -0
- package/dist/core/trace/trace-detector.js.map +7 -0
- package/dist/core/trace/trace-detector.test.js +401 -0
- package/dist/core/trace/trace-detector.test.js.map +7 -0
- package/dist/core/trace/trace-store.js +341 -0
- package/dist/core/trace/trace-store.js.map +7 -0
- package/dist/core/trace/types.js +73 -0
- package/dist/core/trace/types.js.map +7 -0
- package/dist/core/types.js +1 -0
- package/dist/core/types.js.map +7 -0
- package/dist/core/utils/update-checker.js +214 -0
- package/dist/core/utils/update-checker.js.map +7 -0
- package/dist/core/worktree/worktree-manager.js +450 -0
- package/dist/core/worktree/worktree-manager.js.map +7 -0
- package/dist/features/analytics/api/analytics-api.js +283 -0
- package/dist/features/analytics/api/analytics-api.js.map +7 -0
- package/dist/features/analytics/core/analytics-service.js +267 -0
- package/dist/features/analytics/core/analytics-service.js.map +7 -0
- package/dist/features/analytics/index.js +14 -0
- package/dist/features/analytics/index.js.map +7 -0
- package/dist/features/analytics/queries/metrics-queries.js +273 -0
- package/dist/features/analytics/queries/metrics-queries.js.map +7 -0
- package/dist/features/analytics/types/metrics.js +1 -0
- package/dist/features/analytics/types/metrics.js.map +7 -0
- package/dist/features/browser/browser-mcp.js +488 -0
- package/dist/features/browser/browser-mcp.js.map +7 -0
- package/dist/features/tasks/__tests__/pebbles-task-store.test.js +747 -0
- package/dist/features/tasks/__tests__/pebbles-task-store.test.js.map +7 -0
- package/dist/features/tasks/pebbles-task-store.js +647 -0
- package/dist/features/tasks/pebbles-task-store.js.map +7 -0
- package/dist/features/tasks/task-aware-context.js +406 -0
- package/dist/features/tasks/task-aware-context.js.map +7 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +7 -0
- package/dist/integrations/linear/__tests__/auth.test.js +558 -0
- package/dist/integrations/linear/__tests__/auth.test.js.map +7 -0
- package/dist/integrations/linear/__tests__/sync-service.test.js +760 -0
- package/dist/integrations/linear/__tests__/sync-service.test.js.map +7 -0
- package/dist/integrations/linear/auth.js +308 -0
- package/dist/integrations/linear/auth.js.map +7 -0
- package/dist/integrations/linear/auto-sync.js +244 -0
- package/dist/integrations/linear/auto-sync.js.map +7 -0
- package/dist/integrations/linear/client.js +448 -0
- package/dist/integrations/linear/client.js.map +7 -0
- package/dist/integrations/linear/config.js +115 -0
- package/dist/integrations/linear/config.js.map +7 -0
- package/dist/integrations/linear/sync-manager.js +233 -0
- package/dist/integrations/linear/sync-manager.js.map +7 -0
- package/dist/integrations/linear/sync-service.js +214 -0
- package/dist/integrations/linear/sync-service.js.map +7 -0
- package/dist/integrations/linear/sync.js +565 -0
- package/dist/integrations/linear/sync.js.map +7 -0
- package/dist/integrations/linear/types.js +1 -0
- package/dist/integrations/linear/types.js.map +7 -0
- package/dist/integrations/linear/webhook-server.js +204 -0
- package/dist/integrations/linear/webhook-server.js.map +7 -0
- package/dist/integrations/linear/webhook.js +269 -0
- package/dist/integrations/linear/webhook.js.map +7 -0
- package/dist/integrations/mcp/__tests__/server.test.js +798 -0
- package/dist/integrations/mcp/__tests__/server.test.js.map +7 -0
- package/dist/integrations/mcp/handlers/context-handlers.js +253 -0
- package/dist/integrations/mcp/handlers/context-handlers.js.map +7 -0
- package/dist/integrations/mcp/handlers/index.js +134 -0
- package/dist/integrations/mcp/handlers/index.js.map +7 -0
- package/dist/integrations/mcp/handlers/linear-handlers.js +243 -0
- package/dist/integrations/mcp/handlers/linear-handlers.js.map +7 -0
- package/dist/integrations/mcp/handlers/task-handlers.js +235 -0
- package/dist/integrations/mcp/handlers/task-handlers.js.map +7 -0
- package/dist/integrations/mcp/handlers/trace-handlers.js +304 -0
- package/dist/integrations/mcp/handlers/trace-handlers.js.map +7 -0
- package/dist/integrations/mcp/index.js +19 -0
- package/dist/integrations/mcp/index.js.map +7 -0
- package/dist/integrations/mcp/refactored-server.js +331 -0
- package/dist/integrations/mcp/refactored-server.js.map +7 -0
- package/dist/integrations/mcp/server.js +1621 -0
- package/dist/integrations/mcp/server.js.map +7 -0
- package/dist/integrations/mcp/tool-definitions.js +562 -0
- package/dist/integrations/mcp/tool-definitions.js.map +7 -0
- package/dist/integrations/mcp/trace-test.js +44 -0
- package/dist/integrations/mcp/trace-test.js.map +7 -0
- package/dist/integrations/pg-aiguide/embedding-provider.js +174 -0
- package/dist/integrations/pg-aiguide/embedding-provider.js.map +7 -0
- package/dist/integrations/pg-aiguide/semantic-search.js +183 -0
- package/dist/integrations/pg-aiguide/semantic-search.js.map +7 -0
- package/dist/integrations/pg-aiguide/timescale-analytics.js +220 -0
- package/dist/integrations/pg-aiguide/timescale-analytics.js.map +7 -0
- package/dist/mcp/stackmemory-mcp-server.js +550 -0
- package/dist/mcp/stackmemory-mcp-server.js.map +7 -0
- package/dist/middleware/exponential-rate-limiter.js +285 -0
- package/dist/middleware/exponential-rate-limiter.js.map +7 -0
- package/dist/models/user.model.js +351 -0
- package/dist/models/user.model.js.map +7 -0
- package/dist/scripts/benchmark-performance.d.ts +7 -0
- package/dist/scripts/benchmark-performance.d.ts.map +1 -0
- package/dist/scripts/benchmark-performance.js +44 -0
- package/dist/scripts/benchmark-performance.js.map +1 -0
- package/dist/scripts/cleanup-duplicate-tasks.d.ts +12 -0
- package/dist/scripts/cleanup-duplicate-tasks.d.ts.map +1 -0
- package/dist/scripts/cleanup-duplicate-tasks.js +215 -0
- package/dist/scripts/cleanup-duplicate-tasks.js.map +1 -0
- package/dist/servers/production/auth-middleware.js +513 -0
- package/dist/servers/production/auth-middleware.js.map +7 -0
- package/dist/servers/railway/index.js +390 -0
- package/dist/servers/railway/index.js.map +7 -0
- package/dist/services/config-service.js +62 -0
- package/dist/services/config-service.js.map +7 -0
- package/dist/services/context-service.js +191 -0
- package/dist/services/context-service.js.map +7 -0
- package/dist/src/agents/core/agent-task-manager.d.ts +154 -0
- package/dist/src/agents/core/agent-task-manager.d.ts.map +1 -0
- package/dist/src/agents/core/agent-task-manager.js +504 -0
- package/dist/src/agents/core/agent-task-manager.js.map +1 -0
- package/dist/src/agents/verifiers/base-verifier.d.ts +112 -0
- package/dist/src/agents/verifiers/base-verifier.d.ts.map +1 -0
- package/dist/src/agents/verifiers/base-verifier.js +130 -0
- package/dist/src/agents/verifiers/base-verifier.js.map +1 -0
- package/dist/src/agents/verifiers/formatter-verifier.d.ts +14 -0
- package/dist/src/agents/verifiers/formatter-verifier.d.ts.map +1 -0
- package/dist/src/agents/verifiers/formatter-verifier.js +107 -0
- package/dist/src/agents/verifiers/formatter-verifier.js.map +1 -0
- package/dist/src/agents/verifiers/llm-judge.d.ts +46 -0
- package/dist/src/agents/verifiers/llm-judge.d.ts.map +1 -0
- package/dist/src/agents/verifiers/llm-judge.js +248 -0
- package/dist/src/agents/verifiers/llm-judge.js.map +1 -0
- package/dist/src/cli/claude-sm.js +55 -0
- package/dist/src/cli/claude-sm.js.map +1 -1
- package/dist/src/cli/commands/agent.d.ts +9 -0
- package/dist/src/cli/commands/agent.d.ts.map +1 -0
- package/dist/src/cli/commands/agent.js +303 -0
- package/dist/src/cli/commands/agent.js.map +1 -0
- package/dist/src/cli/commands/handoff.d.ts +6 -0
- package/dist/src/cli/commands/handoff.d.ts.map +1 -0
- package/dist/src/cli/commands/handoff.js +212 -0
- package/dist/src/cli/commands/handoff.js.map +1 -0
- package/dist/src/cli/index.d.ts.map +1 -1
- package/dist/src/cli/index.js +4 -0
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/core/context/frame-database.d.ts +59 -0
- package/dist/src/core/context/frame-database.d.ts.map +1 -0
- package/dist/src/core/context/frame-database.js +333 -0
- package/dist/src/core/context/frame-database.js.map +1 -0
- package/dist/src/core/context/frame-digest.d.ts +59 -0
- package/dist/src/core/context/frame-digest.d.ts.map +1 -0
- package/dist/src/core/context/frame-digest.js +264 -0
- package/dist/src/core/context/frame-digest.js.map +1 -0
- package/dist/src/core/context/frame-manager.d.ts +2 -0
- package/dist/src/core/context/frame-manager.d.ts.map +1 -1
- package/dist/src/core/context/frame-manager.js +7 -0
- package/dist/src/core/context/frame-manager.js.map +1 -1
- package/dist/src/core/context/frame-stack.d.ts +85 -0
- package/dist/src/core/context/frame-stack.d.ts.map +1 -0
- package/dist/src/core/context/frame-stack.js +287 -0
- package/dist/src/core/context/frame-stack.js.map +1 -0
- package/dist/src/core/context/frame-types.d.ts +67 -0
- package/dist/src/core/context/frame-types.d.ts.map +1 -0
- package/dist/src/core/context/frame-types.js +6 -0
- package/dist/src/core/context/frame-types.js.map +1 -0
- package/dist/src/core/context/index.d.ts +11 -0
- package/dist/src/core/context/index.d.ts.map +1 -0
- package/dist/src/core/context/index.js +14 -0
- package/dist/src/core/context/index.js.map +1 -0
- package/dist/src/core/context/refactored-frame-manager.d.ts +99 -0
- package/dist/src/core/context/refactored-frame-manager.d.ts.map +1 -0
- package/dist/src/core/context/refactored-frame-manager.js +340 -0
- package/dist/src/core/context/refactored-frame-manager.js.map +1 -0
- package/dist/src/core/database/batch-operations.d.ts +118 -0
- package/dist/src/core/database/batch-operations.d.ts.map +1 -0
- package/dist/src/core/database/batch-operations.js +339 -0
- package/dist/src/core/database/batch-operations.js.map +1 -0
- package/dist/src/core/database/connection-pool.d.ts +79 -0
- package/dist/src/core/database/connection-pool.d.ts.map +1 -0
- package/dist/src/core/database/connection-pool.js +236 -0
- package/dist/src/core/database/connection-pool.js.map +1 -0
- package/dist/src/core/database/query-cache.d.ts +135 -0
- package/dist/src/core/database/query-cache.d.ts.map +1 -0
- package/dist/src/core/database/query-cache.js +294 -0
- package/dist/src/core/database/query-cache.js.map +1 -0
- package/dist/src/core/digest/enhanced-hybrid-digest.d.ts +125 -0
- package/dist/src/core/digest/enhanced-hybrid-digest.d.ts.map +1 -0
- package/dist/src/core/digest/enhanced-hybrid-digest.js +282 -0
- package/dist/src/core/digest/enhanced-hybrid-digest.js.map +1 -0
- package/dist/src/core/digest/frame-digest-integration.d.ts +67 -0
- package/dist/src/core/digest/frame-digest-integration.d.ts.map +1 -0
- package/dist/src/core/digest/frame-digest-integration.js +198 -0
- package/dist/src/core/digest/frame-digest-integration.js.map +1 -0
- package/dist/src/core/digest/hybrid-digest-generator.d.ts +3 -3
- package/dist/src/core/digest/hybrid-digest-generator.d.ts.map +1 -1
- package/dist/src/core/digest/hybrid-digest-generator.js.map +1 -1
- package/dist/src/core/digest/index.d.ts +3 -1
- package/dist/src/core/digest/index.d.ts.map +1 -1
- package/dist/src/core/digest/index.js +3 -1
- package/dist/src/core/digest/index.js.map +1 -1
- package/dist/src/core/errors/index.d.ts +13 -5
- package/dist/src/core/errors/index.d.ts.map +1 -1
- package/dist/src/core/errors/index.js +13 -5
- package/dist/src/core/errors/index.js.map +1 -1
- package/dist/src/core/merge/conflict-detector.d.ts +122 -0
- package/dist/src/core/merge/conflict-detector.d.ts.map +1 -0
- package/dist/src/core/merge/conflict-detector.js +468 -0
- package/dist/src/core/merge/conflict-detector.js.map +1 -0
- package/dist/src/core/merge/index.d.ts +9 -0
- package/dist/src/core/merge/index.d.ts.map +1 -0
- package/dist/src/core/merge/index.js +9 -0
- package/dist/src/core/merge/index.js.map +1 -0
- package/dist/src/core/merge/resolution-engine.d.ts +120 -0
- package/dist/src/core/merge/resolution-engine.d.ts.map +1 -0
- package/dist/src/core/merge/resolution-engine.js +573 -0
- package/dist/src/core/merge/resolution-engine.js.map +1 -0
- package/dist/src/core/merge/stack-diff.d.ts +97 -0
- package/dist/src/core/merge/stack-diff.d.ts.map +1 -0
- package/dist/src/core/merge/stack-diff.js +516 -0
- package/dist/src/core/merge/stack-diff.js.map +1 -0
- package/dist/src/core/merge/types.d.ts +110 -0
- package/dist/src/core/merge/types.d.ts.map +1 -0
- package/dist/src/core/merge/types.js +6 -0
- package/dist/src/core/merge/types.js.map +1 -0
- package/dist/src/core/performance/context-cache.d.ts +109 -0
- package/dist/src/core/performance/context-cache.d.ts.map +1 -0
- package/dist/src/core/performance/context-cache.js +280 -0
- package/dist/src/core/performance/context-cache.js.map +1 -0
- package/dist/src/core/performance/index.d.ts +3 -0
- package/dist/src/core/performance/index.d.ts.map +1 -0
- package/dist/src/core/performance/index.js +3 -0
- package/dist/src/core/performance/index.js.map +1 -0
- package/dist/src/core/performance/lazy-context-loader.d.ts +93 -0
- package/dist/src/core/performance/lazy-context-loader.d.ts.map +1 -0
- package/dist/src/core/performance/lazy-context-loader.js +332 -0
- package/dist/src/core/performance/lazy-context-loader.js.map +1 -0
- package/dist/src/core/performance/monitor.d.ts +48 -0
- package/dist/src/core/performance/monitor.d.ts.map +1 -0
- package/dist/src/core/performance/monitor.js +226 -0
- package/dist/src/core/performance/monitor.js.map +1 -0
- package/dist/src/core/performance/optimized-frame-context.d.ts +74 -0
- package/dist/src/core/performance/optimized-frame-context.d.ts.map +1 -0
- package/dist/src/core/performance/optimized-frame-context.js +330 -0
- package/dist/src/core/performance/optimized-frame-context.js.map +1 -0
- package/dist/src/core/performance/performance-benchmark.d.ts +50 -0
- package/dist/src/core/performance/performance-benchmark.d.ts.map +1 -0
- package/dist/src/core/performance/performance-benchmark.js +290 -0
- package/dist/src/core/performance/performance-benchmark.js.map +1 -0
- package/dist/src/core/performance/performance-profiler.d.ts +151 -0
- package/dist/src/core/performance/performance-profiler.d.ts.map +1 -0
- package/dist/src/core/performance/performance-profiler.js +346 -0
- package/dist/src/core/performance/performance-profiler.js.map +1 -0
- package/dist/src/core/performance/streaming-jsonl-parser.d.ts +41 -0
- package/dist/src/core/performance/streaming-jsonl-parser.d.ts.map +1 -0
- package/dist/src/core/performance/streaming-jsonl-parser.js +193 -0
- package/dist/src/core/performance/streaming-jsonl-parser.js.map +1 -0
- package/dist/src/core/persistence/postgres-adapter.d.ts.map +1 -1
- package/dist/src/core/persistence/postgres-adapter.js +18 -4
- package/dist/src/core/persistence/postgres-adapter.js.map +1 -1
- package/dist/src/core/query/query-parser.d.ts +5 -0
- package/dist/src/core/query/query-parser.d.ts.map +1 -1
- package/dist/src/core/query/query-parser.js +86 -18
- package/dist/src/core/query/query-parser.js.map +1 -1
- package/dist/src/core/query/query-templates.d.ts +44 -0
- package/dist/src/core/query/query-templates.d.ts.map +1 -0
- package/dist/src/core/query/query-templates.js +326 -0
- package/dist/src/core/query/query-templates.js.map +1 -0
- package/dist/src/core/retrieval/llm-context-retrieval.d.ts +5 -3
- package/dist/src/core/retrieval/llm-context-retrieval.d.ts.map +1 -1
- package/dist/src/core/retrieval/llm-context-retrieval.js +73 -21
- package/dist/src/core/retrieval/llm-context-retrieval.js.map +1 -1
- package/dist/src/core/trace/cli-trace-wrapper.d.ts +23 -0
- package/dist/src/core/trace/cli-trace-wrapper.d.ts.map +1 -0
- package/dist/src/core/trace/cli-trace-wrapper.js +141 -0
- package/dist/src/core/trace/cli-trace-wrapper.js.map +1 -0
- package/dist/src/core/trace/db-trace-wrapper.d.ts +36 -0
- package/dist/src/core/trace/db-trace-wrapper.d.ts.map +1 -0
- package/dist/src/core/trace/db-trace-wrapper.js +252 -0
- package/dist/src/core/trace/db-trace-wrapper.js.map +1 -0
- package/dist/src/core/trace/debug-trace.d.ts +84 -0
- package/dist/src/core/trace/debug-trace.d.ts.map +1 -0
- package/dist/src/core/trace/debug-trace.js +402 -0
- package/dist/src/core/trace/debug-trace.js.map +1 -0
- package/dist/src/core/trace/error-test.d.ts +6 -0
- package/dist/src/core/trace/error-test.d.ts.map +1 -0
- package/dist/src/core/trace/error-test.js +128 -0
- package/dist/src/core/trace/error-test.js.map +1 -0
- package/dist/src/core/trace/index.d.ts +25 -0
- package/dist/src/core/trace/index.d.ts.map +1 -0
- package/dist/src/core/trace/index.js +121 -0
- package/dist/src/core/trace/index.js.map +1 -0
- package/dist/src/core/trace/linear-api-wrapper.d.ts +17 -0
- package/dist/src/core/trace/linear-api-wrapper.d.ts.map +1 -0
- package/dist/src/core/trace/linear-api-wrapper.js +205 -0
- package/dist/src/core/trace/linear-api-wrapper.js.map +1 -0
- package/dist/src/core/trace/performance-test.d.ts +6 -0
- package/dist/src/core/trace/performance-test.d.ts.map +1 -0
- package/dist/src/core/trace/performance-test.js +111 -0
- package/dist/src/core/trace/performance-test.js.map +1 -0
- package/dist/src/core/trace/trace-demo.d.ts +8 -0
- package/dist/src/core/trace/trace-demo.d.ts.map +1 -0
- package/dist/src/core/trace/trace-demo.js +154 -0
- package/dist/src/core/trace/trace-demo.js.map +1 -0
- package/dist/src/core/trace/trace-detector.d.ts +2 -2
- package/dist/src/core/trace/trace-detector.d.ts.map +1 -1
- package/dist/src/core/trace/trace-detector.demo.js +1 -1
- package/dist/src/core/trace/trace-detector.demo.js.map +1 -1
- package/dist/src/core/trace/trace-detector.js +3 -3
- package/dist/src/core/trace/trace-detector.js.map +1 -1
- package/dist/src/features/tasks/pebbles-task-store.d.ts +9 -2
- package/dist/src/features/tasks/pebbles-task-store.d.ts.map +1 -1
- package/dist/src/features/tasks/pebbles-task-store.js +97 -18
- package/dist/src/features/tasks/pebbles-task-store.js.map +1 -1
- package/dist/src/integrations/linear/auth.d.ts.map +1 -1
- package/dist/src/integrations/linear/auth.js.map +1 -1
- package/dist/src/integrations/linear/client.d.ts +15 -1
- package/dist/src/integrations/linear/client.d.ts.map +1 -1
- package/dist/src/integrations/linear/client.js +85 -3
- package/dist/src/integrations/linear/client.js.map +1 -1
- package/dist/src/integrations/linear/sync-manager.d.ts +2 -0
- package/dist/src/integrations/linear/sync-manager.d.ts.map +1 -1
- package/dist/src/integrations/linear/sync-manager.js +16 -4
- package/dist/src/integrations/linear/sync-manager.js.map +1 -1
- package/dist/src/integrations/linear/sync-service.d.ts +23 -2
- package/dist/src/integrations/linear/sync-service.d.ts.map +1 -1
- package/dist/src/integrations/linear/sync-service.js +44 -25
- package/dist/src/integrations/linear/sync-service.js.map +1 -1
- package/dist/src/integrations/linear/sync.d.ts +6 -0
- package/dist/src/integrations/linear/sync.d.ts.map +1 -1
- package/dist/src/integrations/linear/sync.js +27 -2
- package/dist/src/integrations/linear/sync.js.map +1 -1
- package/dist/src/integrations/linear/types.d.ts +16 -1
- package/dist/src/integrations/linear/types.d.ts.map +1 -1
- package/dist/src/integrations/linear/webhook-server.d.ts.map +1 -1
- package/dist/src/integrations/linear/webhook-server.js +10 -8
- package/dist/src/integrations/linear/webhook-server.js.map +1 -1
- package/dist/src/integrations/linear/webhook.d.ts +13 -0
- package/dist/src/integrations/linear/webhook.d.ts.map +1 -1
- package/dist/src/integrations/linear/webhook.js +101 -14
- package/dist/src/integrations/linear/webhook.js.map +1 -1
- package/dist/src/integrations/mcp/handlers/context-handlers.d.ts +39 -0
- package/dist/src/integrations/mcp/handlers/context-handlers.d.ts.map +1 -0
- package/dist/src/integrations/mcp/handlers/context-handlers.js +266 -0
- package/dist/src/integrations/mcp/handlers/context-handlers.js.map +1 -0
- package/dist/src/integrations/mcp/handlers/index.d.ts +37 -0
- package/dist/src/integrations/mcp/handlers/index.d.ts.map +1 -0
- package/dist/src/integrations/mcp/handlers/index.js +134 -0
- package/dist/src/integrations/mcp/handlers/index.js.map +1 -0
- package/dist/src/integrations/mcp/handlers/linear-handlers.d.ts +33 -0
- package/dist/src/integrations/mcp/handlers/linear-handlers.d.ts.map +1 -0
- package/dist/src/integrations/mcp/handlers/linear-handlers.js +251 -0
- package/dist/src/integrations/mcp/handlers/linear-handlers.js.map +1 -0
- package/dist/src/integrations/mcp/handlers/task-handlers.d.ts +42 -0
- package/dist/src/integrations/mcp/handlers/task-handlers.d.ts.map +1 -0
- package/dist/src/integrations/mcp/handlers/task-handlers.js +238 -0
- package/dist/src/integrations/mcp/handlers/task-handlers.js.map +1 -0
- package/dist/src/integrations/mcp/handlers/trace-handlers.d.ts +41 -0
- package/dist/src/integrations/mcp/handlers/trace-handlers.d.ts.map +1 -0
- package/dist/src/integrations/mcp/handlers/trace-handlers.js +298 -0
- package/dist/src/integrations/mcp/handlers/trace-handlers.js.map +1 -0
- package/dist/src/integrations/mcp/index.d.ts +13 -0
- package/dist/src/integrations/mcp/index.d.ts.map +1 -0
- package/dist/src/integrations/mcp/index.js +17 -0
- package/dist/src/integrations/mcp/index.js.map +1 -0
- package/dist/src/integrations/mcp/refactored-server.d.ts +76 -0
- package/dist/src/integrations/mcp/refactored-server.d.ts.map +1 -0
- package/dist/src/integrations/mcp/refactored-server.js +351 -0
- package/dist/src/integrations/mcp/refactored-server.js.map +1 -0
- package/dist/src/integrations/mcp/tool-definitions.d.ts +44 -0
- package/dist/src/integrations/mcp/tool-definitions.d.ts.map +1 -0
- package/dist/src/integrations/mcp/tool-definitions.js +563 -0
- package/dist/src/integrations/mcp/tool-definitions.js.map +1 -0
- package/dist/src/integrations/pg-aiguide/semantic-search.d.ts.map +1 -1
- package/dist/src/integrations/pg-aiguide/semantic-search.js +43 -21
- package/dist/src/integrations/pg-aiguide/semantic-search.js.map +1 -1
- package/dist/src/mcp/stackmemory-mcp-server.d.ts +9 -0
- package/dist/src/mcp/stackmemory-mcp-server.d.ts.map +1 -0
- package/dist/src/mcp/stackmemory-mcp-server.js +519 -0
- package/dist/src/mcp/stackmemory-mcp-server.js.map +1 -0
- package/dist/src/middleware/exponential-rate-limiter.d.ts +78 -0
- package/dist/src/middleware/exponential-rate-limiter.d.ts.map +1 -0
- package/dist/src/middleware/exponential-rate-limiter.js +293 -0
- package/dist/src/middleware/exponential-rate-limiter.js.map +1 -0
- package/dist/src/models/user.model.d.ts +8 -1
- package/dist/src/models/user.model.d.ts.map +1 -1
- package/dist/src/models/user.model.js +62 -14
- package/dist/src/models/user.model.js.map +1 -1
- package/dist/src/servers/production/auth-middleware.d.ts +5 -2
- package/dist/src/servers/production/auth-middleware.d.ts.map +1 -1
- package/dist/src/servers/production/auth-middleware.js +71 -34
- package/dist/src/servers/production/auth-middleware.js.map +1 -1
- package/dist/src/services/context-service.d.ts.map +1 -1
- package/dist/src/services/context-service.js +86 -1
- package/dist/src/services/context-service.js.map +1 -1
- package/dist/src/validation/schemas.d.ts +633 -0
- package/dist/src/validation/schemas.d.ts.map +1 -0
- package/dist/src/validation/schemas.js +347 -0
- package/dist/src/validation/schemas.js.map +1 -0
- package/dist/types/task.js +1 -0
- package/dist/types/task.js.map +7 -0
- package/dist/utils/logger.js +52 -0
- package/dist/utils/logger.js.map +7 -0
- package/dist/validation/schemas.js +218 -0
- package/dist/validation/schemas.js.map +7 -0
- package/package.json +7 -3
|
@@ -0,0 +1,565 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { logger } from "../../core/monitoring/logger.js";
|
|
4
|
+
import { LinearClient } from "./client.js";
|
|
5
|
+
class LinearSyncEngine {
|
|
6
|
+
taskStore;
|
|
7
|
+
linearClient;
|
|
8
|
+
authManager;
|
|
9
|
+
config;
|
|
10
|
+
mappings = /* @__PURE__ */ new Map();
|
|
11
|
+
projectRoot;
|
|
12
|
+
mappingsPath;
|
|
13
|
+
constructor(taskStore, authManager, config, projectRoot) {
|
|
14
|
+
this.taskStore = taskStore;
|
|
15
|
+
this.authManager = authManager;
|
|
16
|
+
this.config = config;
|
|
17
|
+
this.projectRoot = projectRoot || process.cwd();
|
|
18
|
+
this.mappingsPath = join(
|
|
19
|
+
this.projectRoot,
|
|
20
|
+
".stackmemory",
|
|
21
|
+
"linear-mappings.json"
|
|
22
|
+
);
|
|
23
|
+
const apiKey = process.env.LINEAR_API_KEY;
|
|
24
|
+
if (apiKey) {
|
|
25
|
+
this.linearClient = new LinearClient({
|
|
26
|
+
apiKey
|
|
27
|
+
});
|
|
28
|
+
} else {
|
|
29
|
+
const tokens = this.authManager.loadTokens();
|
|
30
|
+
if (!tokens) {
|
|
31
|
+
throw new Error(
|
|
32
|
+
'Linear API key or authentication tokens not found. Set LINEAR_API_KEY environment variable or run "stackmemory linear setup" first.'
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
this.linearClient = new LinearClient({
|
|
36
|
+
apiKey: tokens.accessToken
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
this.loadMappings();
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Update sync configuration
|
|
43
|
+
*/
|
|
44
|
+
updateConfig(newConfig) {
|
|
45
|
+
this.config = { ...this.config, ...newConfig };
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Perform bi-directional sync
|
|
49
|
+
*/
|
|
50
|
+
async sync() {
|
|
51
|
+
if (!this.config.enabled) {
|
|
52
|
+
return {
|
|
53
|
+
success: false,
|
|
54
|
+
synced: { toLinear: 0, fromLinear: 0, updated: 0 },
|
|
55
|
+
conflicts: [],
|
|
56
|
+
errors: ["Sync is disabled"]
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
const result = {
|
|
60
|
+
success: true,
|
|
61
|
+
synced: { toLinear: 0, fromLinear: 0, updated: 0 },
|
|
62
|
+
conflicts: [],
|
|
63
|
+
errors: []
|
|
64
|
+
};
|
|
65
|
+
try {
|
|
66
|
+
const apiKey = process.env.LINEAR_API_KEY;
|
|
67
|
+
if (!apiKey) {
|
|
68
|
+
const token = await this.authManager.getValidToken();
|
|
69
|
+
this.linearClient = new LinearClient({ apiKey: token });
|
|
70
|
+
}
|
|
71
|
+
if (!this.config.defaultTeamId) {
|
|
72
|
+
const team = await this.linearClient.getTeam();
|
|
73
|
+
this.config.defaultTeamId = team.id;
|
|
74
|
+
logger.info(`Using Linear team: ${team.name} (${team.key})`);
|
|
75
|
+
}
|
|
76
|
+
if (this.config.direction === "bidirectional" || this.config.direction === "to_linear") {
|
|
77
|
+
const toLinearResult = await this.syncToLinear();
|
|
78
|
+
result.synced.toLinear = toLinearResult.created;
|
|
79
|
+
result.synced.updated += toLinearResult.updated;
|
|
80
|
+
result.errors.push(...toLinearResult.errors);
|
|
81
|
+
}
|
|
82
|
+
if (this.config.direction === "bidirectional" || this.config.direction === "from_linear") {
|
|
83
|
+
const fromLinearResult = await this.syncFromLinear();
|
|
84
|
+
result.synced.fromLinear = fromLinearResult.created;
|
|
85
|
+
result.synced.updated += fromLinearResult.updated;
|
|
86
|
+
result.conflicts.push(...fromLinearResult.conflicts);
|
|
87
|
+
result.errors.push(...fromLinearResult.errors);
|
|
88
|
+
}
|
|
89
|
+
this.saveMappings();
|
|
90
|
+
} catch (error) {
|
|
91
|
+
result.success = false;
|
|
92
|
+
result.errors.push(`Sync failed: ${String(error)}`);
|
|
93
|
+
logger.error("Linear sync failed:", error);
|
|
94
|
+
}
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Delay helper for rate limiting
|
|
99
|
+
*/
|
|
100
|
+
async delay(ms) {
|
|
101
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Sync tasks from StackMemory to Linear
|
|
105
|
+
*/
|
|
106
|
+
async syncToLinear() {
|
|
107
|
+
const result = { created: 0, updated: 0, errors: [] };
|
|
108
|
+
const maxBatchSize = this.config.maxBatchSize || 10;
|
|
109
|
+
const rateLimitDelay = this.config.rateLimitDelay || 500;
|
|
110
|
+
const unsyncedTasks = this.getUnsyncedTasks();
|
|
111
|
+
const tasksToSync = unsyncedTasks.slice(0, maxBatchSize);
|
|
112
|
+
if (unsyncedTasks.length > maxBatchSize) {
|
|
113
|
+
logger.info(
|
|
114
|
+
`Syncing ${tasksToSync.length} of ${unsyncedTasks.length} unsynced tasks (batch limit)`
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
for (const task of tasksToSync) {
|
|
118
|
+
try {
|
|
119
|
+
const linearIssue = await this.createLinearIssueFromTask(task);
|
|
120
|
+
const mapping = {
|
|
121
|
+
stackmemoryId: task.id,
|
|
122
|
+
linearId: linearIssue.id,
|
|
123
|
+
linearIdentifier: linearIssue.identifier,
|
|
124
|
+
lastSyncTimestamp: Date.now(),
|
|
125
|
+
lastLinearUpdate: linearIssue.updatedAt,
|
|
126
|
+
lastStackMemoryUpdate: task.timestamp * 1e3
|
|
127
|
+
};
|
|
128
|
+
this.mappings.set(task.id, mapping);
|
|
129
|
+
this.updateTaskWithLinearRef(task.id, linearIssue);
|
|
130
|
+
result.created++;
|
|
131
|
+
logger.info(
|
|
132
|
+
`Synced task to Linear: ${task.title} \u2192 ${linearIssue.identifier}`
|
|
133
|
+
);
|
|
134
|
+
await this.delay(rateLimitDelay);
|
|
135
|
+
} catch (error) {
|
|
136
|
+
const errorMsg = String(error);
|
|
137
|
+
if (errorMsg.includes("rate limit") || errorMsg.includes("usage limit")) {
|
|
138
|
+
logger.warn("Rate limit hit, stopping sync batch");
|
|
139
|
+
result.errors.push("Rate limit reached - sync paused");
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
result.errors.push(`Failed to sync task ${task.id}: ${errorMsg}`);
|
|
143
|
+
logger.error(
|
|
144
|
+
`Failed to sync task ${task.id} to Linear:`,
|
|
145
|
+
error
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
const modifiedTasks = this.getModifiedTasks();
|
|
150
|
+
for (const task of modifiedTasks) {
|
|
151
|
+
try {
|
|
152
|
+
const mapping = this.mappings.get(task.id);
|
|
153
|
+
if (!mapping) continue;
|
|
154
|
+
await this.updateLinearIssueFromTask(task, mapping);
|
|
155
|
+
mapping.lastSyncTimestamp = Date.now();
|
|
156
|
+
mapping.lastStackMemoryUpdate = task.timestamp * 1e3;
|
|
157
|
+
result.updated++;
|
|
158
|
+
logger.info(`Updated Linear issue: ${mapping.linearIdentifier}`);
|
|
159
|
+
} catch (error) {
|
|
160
|
+
result.errors.push(
|
|
161
|
+
`Failed to update Linear issue for task ${task.id}: ${String(error)}`
|
|
162
|
+
);
|
|
163
|
+
logger.error(
|
|
164
|
+
`Failed to update Linear issue for task ${task.id}:`,
|
|
165
|
+
error
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Sync tasks from Linear to StackMemory
|
|
173
|
+
*/
|
|
174
|
+
async syncFromLinear() {
|
|
175
|
+
const result = {
|
|
176
|
+
created: 0,
|
|
177
|
+
updated: 0,
|
|
178
|
+
conflicts: [],
|
|
179
|
+
errors: []
|
|
180
|
+
};
|
|
181
|
+
const importResult = await this.importFromLinear();
|
|
182
|
+
result.created = importResult.imported;
|
|
183
|
+
result.errors.push(...importResult.errors);
|
|
184
|
+
for (const [taskId, mapping] of this.mappings) {
|
|
185
|
+
try {
|
|
186
|
+
const linearIssue = await this.linearClient.getIssue(mapping.linearId);
|
|
187
|
+
if (!linearIssue) {
|
|
188
|
+
result.errors.push(`Linear issue ${mapping.linearId} not found`);
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
const linearUpdateTime = new Date(linearIssue.updatedAt).getTime();
|
|
192
|
+
if (linearUpdateTime <= mapping.lastSyncTimestamp) {
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
const task = this.taskStore.getTask(taskId);
|
|
196
|
+
if (!task) {
|
|
197
|
+
result.errors.push(`StackMemory task ${taskId} not found`);
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
const stackMemoryUpdateTime = task.timestamp * 1e3;
|
|
201
|
+
if (stackMemoryUpdateTime > mapping.lastSyncTimestamp && linearUpdateTime > mapping.lastSyncTimestamp) {
|
|
202
|
+
result.conflicts.push({
|
|
203
|
+
taskId,
|
|
204
|
+
linearId: mapping.linearId,
|
|
205
|
+
reason: "Both StackMemory and Linear were updated since last sync"
|
|
206
|
+
});
|
|
207
|
+
if (this.config.conflictResolution === "manual") {
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
const shouldUpdateFromLinear = this.shouldUpdateFromLinear(
|
|
212
|
+
task,
|
|
213
|
+
linearIssue,
|
|
214
|
+
mapping,
|
|
215
|
+
stackMemoryUpdateTime,
|
|
216
|
+
linearUpdateTime
|
|
217
|
+
);
|
|
218
|
+
if (shouldUpdateFromLinear) {
|
|
219
|
+
this.updateTaskFromLinearIssue(task, linearIssue);
|
|
220
|
+
mapping.lastSyncTimestamp = Date.now();
|
|
221
|
+
mapping.lastLinearUpdate = linearIssue.updatedAt;
|
|
222
|
+
result.updated++;
|
|
223
|
+
logger.info(`Updated StackMemory task from Linear: ${task.title}`);
|
|
224
|
+
}
|
|
225
|
+
} catch (error) {
|
|
226
|
+
result.errors.push(
|
|
227
|
+
`Failed to sync from Linear for task ${taskId}: ${String(error)}`
|
|
228
|
+
);
|
|
229
|
+
logger.error(
|
|
230
|
+
`Failed to sync from Linear for task ${taskId}:`,
|
|
231
|
+
error
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return result;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Create Linear issue from StackMemory task
|
|
239
|
+
*/
|
|
240
|
+
async createLinearIssueFromTask(task) {
|
|
241
|
+
const input = {
|
|
242
|
+
title: task.title,
|
|
243
|
+
description: this.formatDescriptionForLinear(task),
|
|
244
|
+
teamId: this.config.defaultTeamId,
|
|
245
|
+
priority: this.mapPriorityToLinear(task.priority),
|
|
246
|
+
estimate: task.estimated_effort ? Math.ceil(task.estimated_effort / 60) : void 0,
|
|
247
|
+
// Convert minutes to hours
|
|
248
|
+
labelIds: this.mapTagsToLinear(task.tags)
|
|
249
|
+
};
|
|
250
|
+
return await this.linearClient.createIssue(input);
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Update Linear issue from StackMemory task
|
|
254
|
+
*/
|
|
255
|
+
async updateLinearIssueFromTask(task, mapping) {
|
|
256
|
+
const updates = {
|
|
257
|
+
title: task.title,
|
|
258
|
+
description: this.formatDescriptionForLinear(task),
|
|
259
|
+
priority: this.mapPriorityToLinear(task.priority),
|
|
260
|
+
estimate: task.estimated_effort ? Math.ceil(task.estimated_effort / 60) : void 0,
|
|
261
|
+
stateId: await this.mapStatusToLinearState(task.status)
|
|
262
|
+
};
|
|
263
|
+
await this.linearClient.updateIssue(mapping.linearId, updates);
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Update StackMemory task from Linear issue
|
|
267
|
+
*/
|
|
268
|
+
updateTaskFromLinearIssue(task, linearIssue) {
|
|
269
|
+
const newStatus = this.mapLinearStateToStatus(linearIssue.state.type);
|
|
270
|
+
if (newStatus !== task.status) {
|
|
271
|
+
this.taskStore.updateTaskStatus(
|
|
272
|
+
task.id,
|
|
273
|
+
newStatus,
|
|
274
|
+
"Updated from Linear"
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Check if task should be updated from Linear based on conflict resolution strategy
|
|
280
|
+
*/
|
|
281
|
+
shouldUpdateFromLinear(task, linearIssue, mapping, stackMemoryUpdateTime, linearUpdateTime) {
|
|
282
|
+
switch (this.config.conflictResolution) {
|
|
283
|
+
case "linear_wins":
|
|
284
|
+
return true;
|
|
285
|
+
case "stackmemory_wins":
|
|
286
|
+
return false;
|
|
287
|
+
case "newest_wins":
|
|
288
|
+
return linearUpdateTime > stackMemoryUpdateTime;
|
|
289
|
+
case "manual":
|
|
290
|
+
return false;
|
|
291
|
+
default:
|
|
292
|
+
return false;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Get tasks that haven't been synced to Linear yet
|
|
297
|
+
*/
|
|
298
|
+
getUnsyncedTasks() {
|
|
299
|
+
const activeTasks = this.taskStore.getActiveTasks();
|
|
300
|
+
return activeTasks.filter(
|
|
301
|
+
(task) => !this.mappings.has(task.id) && !task.external_refs?.linear
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Get tasks that have been modified since last sync
|
|
306
|
+
*/
|
|
307
|
+
getModifiedTasks() {
|
|
308
|
+
const tasks = [];
|
|
309
|
+
for (const [taskId, mapping] of this.mappings) {
|
|
310
|
+
const task = this.taskStore.getTask(taskId);
|
|
311
|
+
if (task && task.timestamp * 1e3 > mapping.lastSyncTimestamp) {
|
|
312
|
+
tasks.push(task);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
return tasks;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Update task with Linear reference
|
|
319
|
+
*/
|
|
320
|
+
updateTaskWithLinearRef(taskId, linearIssue) {
|
|
321
|
+
const task = this.taskStore.getTask(taskId);
|
|
322
|
+
if (!task) return;
|
|
323
|
+
logger.info(`Task ${taskId} mapped to Linear ${linearIssue.identifier}`);
|
|
324
|
+
}
|
|
325
|
+
// Mapping utilities
|
|
326
|
+
formatDescriptionForLinear(task) {
|
|
327
|
+
let description = task.description || "";
|
|
328
|
+
description += `
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
**StackMemory Context:**
|
|
332
|
+
`;
|
|
333
|
+
description += `- Task ID: ${task.id}
|
|
334
|
+
`;
|
|
335
|
+
description += `- Frame: ${task.frame_id}
|
|
336
|
+
`;
|
|
337
|
+
description += `- Created: ${new Date(task.created_at * 1e3).toISOString()}
|
|
338
|
+
`;
|
|
339
|
+
if (task.tags.length > 0) {
|
|
340
|
+
description += `- Tags: ${task.tags.join(", ")}
|
|
341
|
+
`;
|
|
342
|
+
}
|
|
343
|
+
if (task.depends_on.length > 0) {
|
|
344
|
+
description += `- Dependencies: ${task.depends_on.join(", ")}
|
|
345
|
+
`;
|
|
346
|
+
}
|
|
347
|
+
return description;
|
|
348
|
+
}
|
|
349
|
+
mapPriorityToLinear(priority) {
|
|
350
|
+
const map = {
|
|
351
|
+
low: 1,
|
|
352
|
+
// Low priority in Linear
|
|
353
|
+
medium: 2,
|
|
354
|
+
// Medium priority in Linear
|
|
355
|
+
high: 3,
|
|
356
|
+
// High priority in Linear
|
|
357
|
+
urgent: 4
|
|
358
|
+
// Urgent priority in Linear
|
|
359
|
+
};
|
|
360
|
+
return map[priority] || 2;
|
|
361
|
+
}
|
|
362
|
+
mapTagsToLinear(_tags) {
|
|
363
|
+
return void 0;
|
|
364
|
+
}
|
|
365
|
+
mapLinearStateToStatus(linearStateType) {
|
|
366
|
+
switch (linearStateType) {
|
|
367
|
+
case "backlog":
|
|
368
|
+
case "unstarted":
|
|
369
|
+
return "pending";
|
|
370
|
+
case "started":
|
|
371
|
+
return "in_progress";
|
|
372
|
+
case "completed":
|
|
373
|
+
return "completed";
|
|
374
|
+
case "cancelled":
|
|
375
|
+
return "cancelled";
|
|
376
|
+
default:
|
|
377
|
+
return "pending";
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
async mapStatusToLinearState(status) {
|
|
381
|
+
try {
|
|
382
|
+
const team = await this.linearClient.getTeam();
|
|
383
|
+
const states = await this.linearClient.getWorkflowStates(team.id);
|
|
384
|
+
const targetStateType = this.getLinearStateTypeFromStatus(status);
|
|
385
|
+
const matchingState = states.find(
|
|
386
|
+
(state) => state.type === targetStateType
|
|
387
|
+
);
|
|
388
|
+
return matchingState?.id;
|
|
389
|
+
} catch (error) {
|
|
390
|
+
logger.warn(
|
|
391
|
+
"Failed to map status to Linear state:",
|
|
392
|
+
error instanceof Error ? { error } : void 0
|
|
393
|
+
);
|
|
394
|
+
return void 0;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
getLinearStateTypeFromStatus(status) {
|
|
398
|
+
switch (status) {
|
|
399
|
+
case "pending":
|
|
400
|
+
return "unstarted";
|
|
401
|
+
case "in_progress":
|
|
402
|
+
return "started";
|
|
403
|
+
case "completed":
|
|
404
|
+
return "completed";
|
|
405
|
+
case "cancelled":
|
|
406
|
+
return "cancelled";
|
|
407
|
+
case "blocked":
|
|
408
|
+
return "unstarted";
|
|
409
|
+
// Map blocked to unstarted in Linear
|
|
410
|
+
default:
|
|
411
|
+
return "unstarted";
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
// Persistence for mappings
|
|
415
|
+
loadMappings() {
|
|
416
|
+
this.mappings.clear();
|
|
417
|
+
if (existsSync(this.mappingsPath)) {
|
|
418
|
+
try {
|
|
419
|
+
const data = readFileSync(this.mappingsPath, "utf8");
|
|
420
|
+
const mappingsArray = JSON.parse(data);
|
|
421
|
+
for (const mapping of mappingsArray) {
|
|
422
|
+
this.mappings.set(mapping.stackmemoryId, mapping);
|
|
423
|
+
}
|
|
424
|
+
logger.info(`Loaded ${this.mappings.size} task mappings from disk`);
|
|
425
|
+
} catch (error) {
|
|
426
|
+
logger.warn("Failed to load mappings, starting fresh");
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
saveMappings() {
|
|
431
|
+
try {
|
|
432
|
+
const mappingsArray = Array.from(this.mappings.values());
|
|
433
|
+
writeFileSync(this.mappingsPath, JSON.stringify(mappingsArray, null, 2));
|
|
434
|
+
logger.info(`Saved ${this.mappings.size} task mappings to disk`);
|
|
435
|
+
} catch (error) {
|
|
436
|
+
logger.error("Failed to save mappings:", error);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Import all issues from Linear to local task store
|
|
441
|
+
*/
|
|
442
|
+
async importFromLinear() {
|
|
443
|
+
const result = { imported: 0, skipped: 0, errors: [] };
|
|
444
|
+
try {
|
|
445
|
+
if (!this.config.defaultTeamId) {
|
|
446
|
+
const team = await this.linearClient.getTeam();
|
|
447
|
+
this.config.defaultTeamId = team.id;
|
|
448
|
+
logger.info(`Using Linear team: ${team.name} (${team.key})`);
|
|
449
|
+
}
|
|
450
|
+
const issues = await this.linearClient.getIssues({
|
|
451
|
+
teamId: this.config.defaultTeamId,
|
|
452
|
+
limit: 100
|
|
453
|
+
});
|
|
454
|
+
logger.info(`Found ${issues.length} issues in Linear`);
|
|
455
|
+
const linearIdToTaskId = /* @__PURE__ */ new Map();
|
|
456
|
+
for (const [taskId, mapping] of this.mappings) {
|
|
457
|
+
linearIdToTaskId.set(mapping.linearId, taskId);
|
|
458
|
+
}
|
|
459
|
+
for (const issue of issues) {
|
|
460
|
+
try {
|
|
461
|
+
if (linearIdToTaskId.has(issue.id)) {
|
|
462
|
+
result.skipped++;
|
|
463
|
+
continue;
|
|
464
|
+
}
|
|
465
|
+
const taskId = await this.createTaskFromLinearIssue(issue);
|
|
466
|
+
if (taskId) {
|
|
467
|
+
const mapping = {
|
|
468
|
+
stackmemoryId: taskId,
|
|
469
|
+
linearId: issue.id,
|
|
470
|
+
linearIdentifier: issue.identifier,
|
|
471
|
+
lastSyncTimestamp: Date.now(),
|
|
472
|
+
lastLinearUpdate: issue.updatedAt,
|
|
473
|
+
lastStackMemoryUpdate: Date.now()
|
|
474
|
+
};
|
|
475
|
+
this.mappings.set(taskId, mapping);
|
|
476
|
+
result.imported++;
|
|
477
|
+
logger.info(`Imported ${issue.identifier}: ${issue.title}`);
|
|
478
|
+
}
|
|
479
|
+
} catch (error) {
|
|
480
|
+
result.errors.push(
|
|
481
|
+
`Failed to import ${issue.identifier}: ${String(error)}`
|
|
482
|
+
);
|
|
483
|
+
logger.error(`Failed to import ${issue.identifier}:`, error);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
this.saveMappings();
|
|
487
|
+
} catch (error) {
|
|
488
|
+
result.errors.push(`Import failed: ${String(error)}`);
|
|
489
|
+
logger.error("Linear import failed:", error);
|
|
490
|
+
}
|
|
491
|
+
return result;
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Create a local task from a Linear issue
|
|
495
|
+
*/
|
|
496
|
+
async createTaskFromLinearIssue(issue) {
|
|
497
|
+
try {
|
|
498
|
+
const priority = this.mapLinearPriorityToLocal(issue.priority);
|
|
499
|
+
let description = issue.description || "";
|
|
500
|
+
description += `
|
|
501
|
+
|
|
502
|
+
---
|
|
503
|
+
**Linear:** ${issue.identifier} | ${issue.url}`;
|
|
504
|
+
const labels = Array.isArray(issue.labels) ? issue.labels : issue.labels?.nodes || [];
|
|
505
|
+
const tags = labels.map((l) => l.name);
|
|
506
|
+
if (tags.length === 0) tags.push("linear");
|
|
507
|
+
const taskId = this.taskStore.createTask({
|
|
508
|
+
title: `[${issue.identifier}] ${issue.title}`,
|
|
509
|
+
description,
|
|
510
|
+
priority,
|
|
511
|
+
frameId: "linear-import",
|
|
512
|
+
tags,
|
|
513
|
+
estimatedEffort: issue.estimate ? issue.estimate * 60 : void 0
|
|
514
|
+
});
|
|
515
|
+
const status = this.mapLinearStateToStatus(issue.state.type);
|
|
516
|
+
if (status !== "pending") {
|
|
517
|
+
this.taskStore.updateTaskStatus(
|
|
518
|
+
taskId,
|
|
519
|
+
status,
|
|
520
|
+
`Imported from Linear as ${status}`
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
return taskId;
|
|
524
|
+
} catch (error) {
|
|
525
|
+
logger.error(
|
|
526
|
+
`Failed to create task from Linear issue ${issue.identifier}: ${String(error)}`
|
|
527
|
+
);
|
|
528
|
+
return null;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* Map Linear priority (0-4) to local TaskPriority
|
|
533
|
+
*/
|
|
534
|
+
mapLinearPriorityToLocal(priority) {
|
|
535
|
+
switch (priority) {
|
|
536
|
+
case 1:
|
|
537
|
+
return "urgent";
|
|
538
|
+
case 2:
|
|
539
|
+
return "high";
|
|
540
|
+
case 3:
|
|
541
|
+
return "medium";
|
|
542
|
+
case 4:
|
|
543
|
+
return "low";
|
|
544
|
+
default:
|
|
545
|
+
return "medium";
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
const DEFAULT_SYNC_CONFIG = {
|
|
550
|
+
enabled: false,
|
|
551
|
+
direction: "bidirectional",
|
|
552
|
+
autoSync: true,
|
|
553
|
+
conflictResolution: "newest_wins",
|
|
554
|
+
syncInterval: 15,
|
|
555
|
+
// minutes
|
|
556
|
+
maxBatchSize: 10,
|
|
557
|
+
// max tasks per sync batch
|
|
558
|
+
rateLimitDelay: 500
|
|
559
|
+
// 500ms between API calls
|
|
560
|
+
};
|
|
561
|
+
export {
|
|
562
|
+
DEFAULT_SYNC_CONFIG,
|
|
563
|
+
LinearSyncEngine
|
|
564
|
+
};
|
|
565
|
+
//# sourceMappingURL=sync.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/integrations/linear/sync.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Linear Bi-directional Sync Engine\n * Handles syncing tasks between StackMemory and Linear\n */\n\nimport { readFileSync, writeFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { logger } from '../../core/monitoring/logger.js';\nimport {\n PebblesTask,\n PebblesTaskStore,\n TaskStatus,\n TaskPriority,\n} from '../../features/tasks/pebbles-task-store.js';\nimport { LinearClient, LinearIssue, LinearCreateIssueInput } from './client.js';\nimport { LinearAuthManager } from './auth.js';\n\nexport interface SyncConfig {\n enabled: boolean;\n direction: 'bidirectional' | 'to_linear' | 'from_linear';\n defaultTeamId?: string;\n autoSync: boolean;\n conflictResolution:\n | 'linear_wins'\n | 'stackmemory_wins'\n | 'manual'\n | 'newest_wins';\n syncInterval?: number; // minutes\n maxBatchSize?: number; // max tasks to sync per batch\n rateLimitDelay?: number; // ms delay between API calls\n}\n\nexport interface SyncResult {\n success: boolean;\n synced: {\n toLinear: number;\n fromLinear: number;\n updated: number;\n };\n conflicts: Array<{\n taskId: string;\n linearId: string;\n reason: string;\n }>;\n errors: string[];\n}\n\nexport interface TaskMapping {\n stackmemoryId: string;\n linearId: string;\n linearIdentifier: string;\n lastSyncTimestamp: number;\n lastLinearUpdate: string;\n lastStackMemoryUpdate: number;\n}\n\nexport class LinearSyncEngine {\n private taskStore: PebblesTaskStore;\n private linearClient: LinearClient;\n private authManager: LinearAuthManager;\n private config: SyncConfig;\n private mappings: Map<string, TaskMapping> = new Map();\n private projectRoot: string;\n private mappingsPath: string;\n\n constructor(\n taskStore: PebblesTaskStore,\n authManager: LinearAuthManager,\n config: SyncConfig,\n projectRoot?: string\n ) {\n this.taskStore = taskStore;\n this.authManager = authManager;\n this.config = config;\n this.projectRoot = projectRoot || process.cwd();\n this.mappingsPath = join(\n this.projectRoot,\n '.stackmemory',\n 'linear-mappings.json'\n );\n\n // Check for API key from environment variable first\n const apiKey = process.env.LINEAR_API_KEY;\n\n if (apiKey) {\n // Use API key from environment\n this.linearClient = new LinearClient({\n apiKey: apiKey,\n });\n } else {\n // Fall back to OAuth tokens\n const tokens = this.authManager.loadTokens();\n if (!tokens) {\n throw new Error(\n 'Linear API key or authentication tokens not found. Set LINEAR_API_KEY environment variable or run \"stackmemory linear setup\" first.'\n );\n }\n\n this.linearClient = new LinearClient({\n apiKey: tokens.accessToken,\n });\n }\n\n this.loadMappings();\n }\n\n /**\n * Update sync configuration\n */\n updateConfig(newConfig: Partial<SyncConfig>): void {\n this.config = { ...this.config, ...newConfig };\n }\n\n /**\n * Perform bi-directional sync\n */\n async sync(): Promise<SyncResult> {\n if (!this.config.enabled) {\n return {\n success: false,\n synced: { toLinear: 0, fromLinear: 0, updated: 0 },\n conflicts: [],\n errors: ['Sync is disabled'],\n };\n }\n\n const result: SyncResult = {\n success: true,\n synced: { toLinear: 0, fromLinear: 0, updated: 0 },\n conflicts: [],\n errors: [],\n };\n\n try {\n // Update client with valid token if not using environment API key\n const apiKey = process.env.LINEAR_API_KEY;\n if (!apiKey) {\n const token = await this.authManager.getValidToken();\n this.linearClient = new LinearClient({ apiKey: token });\n }\n\n // Get team info if not configured\n if (!this.config.defaultTeamId) {\n const team = await this.linearClient.getTeam();\n this.config.defaultTeamId = team.id;\n logger.info(`Using Linear team: ${team.name} (${team.key})`);\n }\n\n // Sync in both directions based on configuration\n if (\n this.config.direction === 'bidirectional' ||\n this.config.direction === 'to_linear'\n ) {\n const toLinearResult = await this.syncToLinear();\n result.synced.toLinear = toLinearResult.created;\n result.synced.updated += toLinearResult.updated;\n result.errors.push(...toLinearResult.errors);\n }\n\n if (\n this.config.direction === 'bidirectional' ||\n this.config.direction === 'from_linear'\n ) {\n const fromLinearResult = await this.syncFromLinear();\n result.synced.fromLinear = fromLinearResult.created;\n result.synced.updated += fromLinearResult.updated;\n result.conflicts.push(...fromLinearResult.conflicts);\n result.errors.push(...fromLinearResult.errors);\n }\n\n this.saveMappings();\n } catch (error) {\n result.success = false;\n result.errors.push(`Sync failed: ${String(error)}`);\n logger.error('Linear sync failed:', error as Error);\n }\n\n return result;\n }\n\n /**\n * Delay helper for rate limiting\n */\n private async delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n /**\n * Sync tasks from StackMemory to Linear\n */\n private async syncToLinear(): Promise<{\n created: number;\n updated: number;\n errors: string[];\n }> {\n const result = { created: 0, updated: 0, errors: [] as string[] };\n const maxBatchSize = this.config.maxBatchSize || 10;\n const rateLimitDelay = this.config.rateLimitDelay || 500;\n\n // Get unsynced tasks from StackMemory\n const unsyncedTasks = this.getUnsyncedTasks();\n\n // Limit batch size to avoid rate limits\n const tasksToSync = unsyncedTasks.slice(0, maxBatchSize);\n\n if (unsyncedTasks.length > maxBatchSize) {\n logger.info(\n `Syncing ${tasksToSync.length} of ${unsyncedTasks.length} unsynced tasks (batch limit)`\n );\n }\n\n for (const task of tasksToSync) {\n try {\n const linearIssue = await this.createLinearIssueFromTask(task);\n\n // Create mapping\n const mapping: TaskMapping = {\n stackmemoryId: task.id,\n linearId: linearIssue.id,\n linearIdentifier: linearIssue.identifier,\n lastSyncTimestamp: Date.now(),\n lastLinearUpdate: linearIssue.updatedAt,\n lastStackMemoryUpdate: task.timestamp * 1000,\n };\n\n this.mappings.set(task.id, mapping);\n\n // Update task with Linear reference\n this.updateTaskWithLinearRef(task.id, linearIssue);\n\n result.created++;\n logger.info(\n `Synced task to Linear: ${task.title} \u2192 ${linearIssue.identifier}`\n );\n\n // Rate limit delay between creates\n await this.delay(rateLimitDelay);\n } catch (error) {\n const errorMsg = String(error);\n // Stop syncing on rate limit errors\n if (\n errorMsg.includes('rate limit') ||\n errorMsg.includes('usage limit')\n ) {\n logger.warn('Rate limit hit, stopping sync batch');\n result.errors.push('Rate limit reached - sync paused');\n break;\n }\n result.errors.push(`Failed to sync task ${task.id}: ${errorMsg}`);\n logger.error(\n `Failed to sync task ${task.id} to Linear:`,\n error as Error\n );\n }\n }\n\n // Update existing Linear issues for modified StackMemory tasks\n const modifiedTasks = this.getModifiedTasks();\n\n for (const task of modifiedTasks) {\n try {\n const mapping = this.mappings.get(task.id);\n if (!mapping) continue;\n\n await this.updateLinearIssueFromTask(task, mapping);\n\n mapping.lastSyncTimestamp = Date.now();\n mapping.lastStackMemoryUpdate = task.timestamp * 1000;\n\n result.updated++;\n logger.info(`Updated Linear issue: ${mapping.linearIdentifier}`);\n } catch (error) {\n result.errors.push(\n `Failed to update Linear issue for task ${task.id}: ${String(error)}`\n );\n logger.error(\n `Failed to update Linear issue for task ${task.id}:`,\n error as Error\n );\n }\n }\n\n return result;\n }\n\n /**\n * Sync tasks from Linear to StackMemory\n */\n private async syncFromLinear(): Promise<{\n created: number;\n updated: number;\n conflicts: Array<{ taskId: string; linearId: string; reason: string }>;\n errors: string[];\n }> {\n const result = {\n created: 0,\n updated: 0,\n conflicts: [] as Array<{\n taskId: string;\n linearId: string;\n reason: string;\n }>,\n errors: [] as string[],\n };\n\n // First, import any new issues from Linear that aren't mapped yet\n const importResult = await this.importFromLinear();\n result.created = importResult.imported;\n result.errors.push(...importResult.errors);\n\n // Then update existing mapped tasks\n for (const [taskId, mapping] of this.mappings) {\n try {\n const linearIssue = await this.linearClient.getIssue(mapping.linearId);\n\n if (!linearIssue) {\n result.errors.push(`Linear issue ${mapping.linearId} not found`);\n continue;\n }\n\n // Check if Linear issue was updated since last sync\n const linearUpdateTime = new Date(linearIssue.updatedAt).getTime();\n if (linearUpdateTime <= mapping.lastSyncTimestamp) {\n continue; // No changes in Linear\n }\n\n // Check for conflicts\n const task = this.taskStore.getTask(taskId);\n if (!task) {\n result.errors.push(`StackMemory task ${taskId} not found`);\n continue;\n }\n\n const stackMemoryUpdateTime = task.timestamp * 1000;\n\n if (\n stackMemoryUpdateTime > mapping.lastSyncTimestamp &&\n linearUpdateTime > mapping.lastSyncTimestamp\n ) {\n // Conflict: both sides updated since last sync\n result.conflicts.push({\n taskId,\n linearId: mapping.linearId,\n reason: 'Both StackMemory and Linear were updated since last sync',\n });\n\n if (this.config.conflictResolution === 'manual') {\n continue; // Skip, let user resolve manually\n }\n }\n\n // Apply conflict resolution\n const shouldUpdateFromLinear = this.shouldUpdateFromLinear(\n task,\n linearIssue,\n mapping,\n stackMemoryUpdateTime,\n linearUpdateTime\n );\n\n if (shouldUpdateFromLinear) {\n this.updateTaskFromLinearIssue(task, linearIssue);\n\n mapping.lastSyncTimestamp = Date.now();\n mapping.lastLinearUpdate = linearIssue.updatedAt;\n\n result.updated++;\n logger.info(`Updated StackMemory task from Linear: ${task.title}`);\n }\n } catch (error) {\n result.errors.push(\n `Failed to sync from Linear for task ${taskId}: ${String(error)}`\n );\n logger.error(\n `Failed to sync from Linear for task ${taskId}:`,\n error as Error\n );\n }\n }\n\n return result;\n }\n\n /**\n * Create Linear issue from StackMemory task\n */\n private async createLinearIssueFromTask(\n task: PebblesTask\n ): Promise<LinearIssue> {\n const input: LinearCreateIssueInput = {\n title: task.title,\n description: this.formatDescriptionForLinear(task),\n teamId: this.config.defaultTeamId!,\n priority: this.mapPriorityToLinear(task.priority),\n estimate: task.estimated_effort\n ? Math.ceil(task.estimated_effort / 60)\n : undefined, // Convert minutes to hours\n labelIds: this.mapTagsToLinear(task.tags),\n };\n\n return await this.linearClient.createIssue(input);\n }\n\n /**\n * Update Linear issue from StackMemory task\n */\n private async updateLinearIssueFromTask(\n task: PebblesTask,\n mapping: TaskMapping\n ): Promise<void> {\n const updates: Partial<LinearCreateIssueInput> & { stateId?: string } = {\n title: task.title,\n description: this.formatDescriptionForLinear(task),\n priority: this.mapPriorityToLinear(task.priority),\n estimate: task.estimated_effort\n ? Math.ceil(task.estimated_effort / 60)\n : undefined,\n stateId: await this.mapStatusToLinearState(task.status),\n };\n\n await this.linearClient.updateIssue(mapping.linearId, updates);\n }\n\n /**\n * Update StackMemory task from Linear issue\n */\n private updateTaskFromLinearIssue(\n task: PebblesTask,\n linearIssue: LinearIssue\n ): void {\n // Map Linear state to StackMemory status\n const newStatus = this.mapLinearStateToStatus(linearIssue.state.type);\n\n if (newStatus !== task.status) {\n this.taskStore.updateTaskStatus(\n task.id,\n newStatus,\n 'Updated from Linear'\n );\n }\n\n // Note: Other fields like title, description could be updated here\n // but require careful consideration of conflict resolution\n }\n\n /**\n * Check if task should be updated from Linear based on conflict resolution strategy\n */\n private shouldUpdateFromLinear(\n task: PebblesTask,\n linearIssue: LinearIssue,\n mapping: TaskMapping,\n stackMemoryUpdateTime: number,\n linearUpdateTime: number\n ): boolean {\n switch (this.config.conflictResolution) {\n case 'linear_wins':\n return true;\n case 'stackmemory_wins':\n return false;\n case 'newest_wins':\n return linearUpdateTime > stackMemoryUpdateTime;\n case 'manual':\n return false;\n default:\n return false;\n }\n }\n\n /**\n * Get tasks that haven't been synced to Linear yet\n */\n private getUnsyncedTasks(): PebblesTask[] {\n const activeTasks = this.taskStore.getActiveTasks();\n return activeTasks.filter(\n (task) => !this.mappings.has(task.id) && !task.external_refs?.linear\n );\n }\n\n /**\n * Get tasks that have been modified since last sync\n */\n private getModifiedTasks(): PebblesTask[] {\n const tasks: PebblesTask[] = [];\n\n for (const [taskId, mapping] of this.mappings) {\n const task = this.taskStore.getTask(taskId);\n if (task && task.timestamp * 1000 > mapping.lastSyncTimestamp) {\n tasks.push(task);\n }\n }\n\n return tasks;\n }\n\n /**\n * Update task with Linear reference\n */\n private updateTaskWithLinearRef(\n taskId: string,\n linearIssue: LinearIssue\n ): void {\n const task = this.taskStore.getTask(taskId);\n if (!task) return;\n\n // This would need a method in PebblesTaskStore to update external_refs\n // For now, we'll track this in our mappings\n logger.info(`Task ${taskId} mapped to Linear ${linearIssue.identifier}`);\n }\n\n // Mapping utilities\n\n private formatDescriptionForLinear(task: PebblesTask): string {\n let description = task.description || '';\n\n description += `\\n\\n---\\n**StackMemory Context:**\\n`;\n description += `- Task ID: ${task.id}\\n`;\n description += `- Frame: ${task.frame_id}\\n`;\n description += `- Created: ${new Date(task.created_at * 1000).toISOString()}\\n`;\n\n if (task.tags.length > 0) {\n description += `- Tags: ${task.tags.join(', ')}\\n`;\n }\n\n if (task.depends_on.length > 0) {\n description += `- Dependencies: ${task.depends_on.join(', ')}\\n`;\n }\n\n return description;\n }\n\n private mapPriorityToLinear(priority: TaskPriority): number {\n const map: Record<TaskPriority, number> = {\n low: 1, // Low priority in Linear\n medium: 2, // Medium priority in Linear\n high: 3, // High priority in Linear\n urgent: 4, // Urgent priority in Linear\n };\n return map[priority] || 2;\n }\n\n private mapTagsToLinear(_tags: string[]): string[] | undefined {\n // In a full implementation, this would map StackMemory tags to Linear label IDs\n // For now, return undefined to skip label assignment\n return undefined;\n }\n\n private mapLinearStateToStatus(linearStateType: string): TaskStatus {\n switch (linearStateType) {\n case 'backlog':\n case 'unstarted':\n return 'pending';\n case 'started':\n return 'in_progress';\n case 'completed':\n return 'completed';\n case 'cancelled':\n return 'cancelled';\n default:\n return 'pending';\n }\n }\n\n private async mapStatusToLinearState(\n status: TaskStatus\n ): Promise<string | undefined> {\n // Get available states for the team\n try {\n const team = await this.linearClient.getTeam();\n const states = await this.linearClient.getWorkflowStates(team.id);\n\n // Map StackMemory status to Linear state types\n const targetStateType = this.getLinearStateTypeFromStatus(status);\n\n // Find the first state that matches the target type\n const matchingState = states.find(\n (state) => state.type === targetStateType\n );\n return matchingState?.id;\n } catch (error) {\n logger.warn(\n 'Failed to map status to Linear state:',\n error instanceof Error ? { error } : undefined\n );\n return undefined;\n }\n }\n\n private getLinearStateTypeFromStatus(status: TaskStatus): string {\n switch (status) {\n case 'pending':\n return 'unstarted';\n case 'in_progress':\n return 'started';\n case 'completed':\n return 'completed';\n case 'cancelled':\n return 'cancelled';\n case 'blocked':\n return 'unstarted'; // Map blocked to unstarted in Linear\n default:\n return 'unstarted';\n }\n }\n\n // Persistence for mappings\n\n private loadMappings(): void {\n this.mappings.clear();\n\n if (existsSync(this.mappingsPath)) {\n try {\n const data = readFileSync(this.mappingsPath, 'utf8');\n const mappingsArray: TaskMapping[] = JSON.parse(data);\n for (const mapping of mappingsArray) {\n this.mappings.set(mapping.stackmemoryId, mapping);\n }\n logger.info(`Loaded ${this.mappings.size} task mappings from disk`);\n } catch (error) {\n logger.warn('Failed to load mappings, starting fresh');\n }\n }\n }\n\n private saveMappings(): void {\n try {\n const mappingsArray = Array.from(this.mappings.values());\n writeFileSync(this.mappingsPath, JSON.stringify(mappingsArray, null, 2));\n logger.info(`Saved ${this.mappings.size} task mappings to disk`);\n } catch (error) {\n logger.error('Failed to save mappings:', error as Error);\n }\n }\n\n /**\n * Import all issues from Linear to local task store\n */\n async importFromLinear(): Promise<{\n imported: number;\n skipped: number;\n errors: string[];\n }> {\n const result = { imported: 0, skipped: 0, errors: [] as string[] };\n\n try {\n // Get team info\n if (!this.config.defaultTeamId) {\n const team = await this.linearClient.getTeam();\n this.config.defaultTeamId = team.id;\n logger.info(`Using Linear team: ${team.name} (${team.key})`);\n }\n\n // Fetch all issues from Linear (excluding completed/cancelled)\n const issues = await this.linearClient.getIssues({\n teamId: this.config.defaultTeamId,\n limit: 100,\n });\n\n logger.info(`Found ${issues.length} issues in Linear`);\n\n // Build reverse mapping (linearId -> stackmemoryId)\n const linearIdToTaskId = new Map<string, string>();\n for (const [taskId, mapping] of this.mappings) {\n linearIdToTaskId.set(mapping.linearId, taskId);\n }\n\n for (const issue of issues) {\n try {\n // Skip if already mapped\n if (linearIdToTaskId.has(issue.id)) {\n result.skipped++;\n continue;\n }\n\n // Create local task from Linear issue\n const taskId = await this.createTaskFromLinearIssue(issue);\n\n if (taskId) {\n // Create mapping\n const mapping: TaskMapping = {\n stackmemoryId: taskId,\n linearId: issue.id,\n linearIdentifier: issue.identifier,\n lastSyncTimestamp: Date.now(),\n lastLinearUpdate: issue.updatedAt,\n lastStackMemoryUpdate: Date.now(),\n };\n this.mappings.set(taskId, mapping);\n result.imported++;\n logger.info(`Imported ${issue.identifier}: ${issue.title}`);\n }\n } catch (error) {\n result.errors.push(\n `Failed to import ${issue.identifier}: ${String(error)}`\n );\n logger.error(`Failed to import ${issue.identifier}:`, error as Error);\n }\n }\n\n this.saveMappings();\n } catch (error) {\n result.errors.push(`Import failed: ${String(error)}`);\n logger.error('Linear import failed:', error as Error);\n }\n\n return result;\n }\n\n /**\n * Create a local task from a Linear issue\n */\n private async createTaskFromLinearIssue(\n issue: LinearIssue\n ): Promise<string | null> {\n try {\n const priority = this.mapLinearPriorityToLocal(issue.priority);\n\n // Build description with Linear context\n let description = issue.description || '';\n description += `\\n\\n---\\n**Linear:** ${issue.identifier} | ${issue.url}`;\n\n // Extract labels (handle both array and {nodes: [...]} formats)\n const labels = Array.isArray(issue.labels)\n ? issue.labels\n : (issue.labels as unknown as { nodes: Array<{ name: string }> })\n ?.nodes || [];\n const tags = labels.map((l) => l.name);\n if (tags.length === 0) tags.push('linear');\n\n // Create the task via the task store\n const taskId = this.taskStore.createTask({\n title: `[${issue.identifier}] ${issue.title}`,\n description,\n priority,\n frameId: 'linear-import',\n tags,\n estimatedEffort: issue.estimate ? issue.estimate * 60 : undefined,\n });\n\n // Update status if not pending\n const status = this.mapLinearStateToStatus(issue.state.type);\n if (status !== 'pending') {\n this.taskStore.updateTaskStatus(\n taskId,\n status,\n `Imported from Linear as ${status}`\n );\n }\n\n return taskId;\n } catch (error) {\n logger.error(\n `Failed to create task from Linear issue ${issue.identifier}: ${String(error)}`\n );\n return null;\n }\n }\n\n /**\n * Map Linear priority (0-4) to local TaskPriority\n */\n private mapLinearPriorityToLocal(priority: number): TaskPriority {\n switch (priority) {\n case 1:\n return 'urgent';\n case 2:\n return 'high';\n case 3:\n return 'medium';\n case 4:\n return 'low';\n default:\n return 'medium';\n }\n }\n}\n\n/**\n * Default sync configuration\n */\nexport const DEFAULT_SYNC_CONFIG: SyncConfig = {\n enabled: false,\n direction: 'bidirectional',\n autoSync: true,\n conflictResolution: 'newest_wins',\n syncInterval: 15, // minutes\n maxBatchSize: 10, // max tasks per sync batch\n rateLimitDelay: 500, // 500ms between API calls\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=types.js.map
|