@stackmemoryai/stackmemory 0.2.8 → 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/compaction-handler.d.ts.map +1 -1
- package/dist/src/core/context/compaction-handler.js +1 -1
- package/dist/src/core/context/compaction-handler.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 +76 -0
- package/dist/src/core/digest/hybrid-digest-generator.d.ts.map +1 -0
- package/dist/src/core/digest/hybrid-digest-generator.js +629 -0
- package/dist/src/core/digest/hybrid-digest-generator.js.map +1 -0
- package/dist/src/core/digest/index.d.ts +9 -0
- package/dist/src/core/digest/index.d.ts.map +1 -0
- package/dist/src/core/digest/index.js +9 -0
- package/dist/src/core/digest/index.js.map +1 -0
- package/dist/src/core/digest/types.d.ts +154 -0
- package/dist/src/core/digest/types.d.ts.map +1 -0
- package/dist/src/core/digest/types.js +18 -0
- package/dist/src/core/digest/types.js.map +1 -0
- 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/monitoring/logger.d.ts +2 -2
- package/dist/src/core/monitoring/logger.d.ts.map +1 -1
- package/dist/src/core/monitoring/logger.js +10 -5
- package/dist/src/core/monitoring/logger.js.map +1 -1
- package/dist/src/core/monitoring/metrics.d.ts +3 -0
- package/dist/src/core/monitoring/metrics.d.ts.map +1 -1
- package/dist/src/core/monitoring/metrics.js +142 -3
- package/dist/src/core/monitoring/metrics.js.map +1 -1
- 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 +31 -0
- package/dist/src/core/persistence/postgres-adapter.d.ts.map +1 -0
- package/dist/src/core/persistence/postgres-adapter.js +330 -0
- package/dist/src/core/persistence/postgres-adapter.js.map +1 -0
- 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 +6 -6
- 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/core/types.d.ts +35 -0
- package/dist/src/core/types.d.ts.map +1 -0
- package/dist/src/core/types.js +2 -0
- package/dist/src/core/types.js.map +1 -0
- 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/server.js +2 -2
- package/dist/src/integrations/mcp/server.js.map +1 -1
- 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/embedding-provider.d.ts +48 -0
- package/dist/src/integrations/pg-aiguide/embedding-provider.d.ts.map +1 -0
- package/dist/src/integrations/pg-aiguide/embedding-provider.js +190 -0
- package/dist/src/integrations/pg-aiguide/embedding-provider.js.map +1 -0
- package/dist/src/integrations/pg-aiguide/semantic-search.d.ts +34 -0
- package/dist/src/integrations/pg-aiguide/semantic-search.d.ts.map +1 -0
- package/dist/src/integrations/pg-aiguide/semantic-search.js +176 -0
- package/dist/src/integrations/pg-aiguide/semantic-search.js.map +1 -0
- package/dist/src/integrations/pg-aiguide/timescale-analytics.d.ts +44 -0
- package/dist/src/integrations/pg-aiguide/timescale-analytics.d.ts.map +1 -0
- package/dist/src/integrations/pg-aiguide/timescale-analytics.js +215 -0
- package/dist/src/integrations/pg-aiguide/timescale-analytics.js.map +1 -0
- 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 +62 -0
- package/dist/src/models/user.model.d.ts.map +1 -0
- package/dist/src/models/user.model.js +311 -0
- package/dist/src/models/user.model.js.map +1 -0
- package/dist/src/servers/production/auth-middleware.d.ts +12 -2
- package/dist/src/servers/production/auth-middleware.d.ts.map +1 -1
- package/dist/src/servers/production/auth-middleware.js +240 -28
- package/dist/src/servers/production/auth-middleware.js.map +1 -1
- package/dist/src/servers/railway/index.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 +12 -3
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import express from "express";
|
|
3
|
+
import crypto from "crypto";
|
|
4
|
+
import { LinearSyncService } from "./sync-service.js";
|
|
5
|
+
import { Logger } from "../../utils/logger.js";
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
class LinearWebhookServer {
|
|
8
|
+
app;
|
|
9
|
+
server = null;
|
|
10
|
+
logger;
|
|
11
|
+
syncService;
|
|
12
|
+
config;
|
|
13
|
+
eventQueue = [];
|
|
14
|
+
isProcessing = false;
|
|
15
|
+
constructor(config) {
|
|
16
|
+
this.app = express();
|
|
17
|
+
this.logger = new Logger("LinearWebhook");
|
|
18
|
+
this.syncService = new LinearSyncService();
|
|
19
|
+
this.config = {
|
|
20
|
+
port: config?.port || parseInt(process.env.WEBHOOK_PORT || "3456"),
|
|
21
|
+
host: config?.host || process.env.WEBHOOK_HOST || "localhost",
|
|
22
|
+
webhookSecret: config?.webhookSecret || process.env.LINEAR_WEBHOOK_SECRET,
|
|
23
|
+
maxPayloadSize: config?.maxPayloadSize || "10mb",
|
|
24
|
+
rateLimit: {
|
|
25
|
+
windowMs: config?.rateLimit?.windowMs || 6e4,
|
|
26
|
+
max: config?.rateLimit?.max || 100
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
this.setupMiddleware();
|
|
30
|
+
this.setupRoutes();
|
|
31
|
+
}
|
|
32
|
+
setupMiddleware() {
|
|
33
|
+
this.app.use(
|
|
34
|
+
express.raw({
|
|
35
|
+
type: "application/json",
|
|
36
|
+
limit: this.config.maxPayloadSize
|
|
37
|
+
})
|
|
38
|
+
);
|
|
39
|
+
this.app.use((req, res, next) => {
|
|
40
|
+
res.setHeader("X-Powered-By", "StackMemory");
|
|
41
|
+
next();
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
setupRoutes() {
|
|
45
|
+
this.app.get("/health", (req, res) => {
|
|
46
|
+
res.json({
|
|
47
|
+
status: "healthy",
|
|
48
|
+
service: "linear-webhook",
|
|
49
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
50
|
+
queue: this.eventQueue.length,
|
|
51
|
+
processing: this.isProcessing
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
this.app.post("/webhook/linear", async (req, res) => {
|
|
55
|
+
try {
|
|
56
|
+
if (!this.verifyWebhookSignature(req)) {
|
|
57
|
+
this.logger.warn("Invalid webhook signature");
|
|
58
|
+
return res.status(401).json({ error: "Unauthorized" });
|
|
59
|
+
}
|
|
60
|
+
const payload = JSON.parse(req.body.toString());
|
|
61
|
+
this.logger.info(
|
|
62
|
+
`Received webhook: ${payload.type} - ${payload.action}`
|
|
63
|
+
);
|
|
64
|
+
this.eventQueue.push(payload);
|
|
65
|
+
this.processQueue();
|
|
66
|
+
return res.status(200).json({
|
|
67
|
+
status: "accepted",
|
|
68
|
+
queued: true
|
|
69
|
+
});
|
|
70
|
+
} catch (error) {
|
|
71
|
+
this.logger.error("Webhook processing error:", error);
|
|
72
|
+
return res.status(500).json({ error: "Internal server error" });
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
this.app.use((req, res) => {
|
|
76
|
+
res.status(404).json({ error: "Not found" });
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
verifyWebhookSignature(req) {
|
|
80
|
+
if (!this.config.webhookSecret) {
|
|
81
|
+
this.logger.warn("No webhook secret configured, accepting all webhooks");
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
const signature = req.headers["linear-signature"];
|
|
85
|
+
if (!signature) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
const hash = crypto.createHmac("sha256", this.config.webhookSecret).update(req.body).digest("hex");
|
|
89
|
+
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(hash));
|
|
90
|
+
}
|
|
91
|
+
async processQueue() {
|
|
92
|
+
if (this.isProcessing || this.eventQueue.length === 0) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
this.isProcessing = true;
|
|
96
|
+
while (this.eventQueue.length > 0) {
|
|
97
|
+
const event = this.eventQueue.shift();
|
|
98
|
+
try {
|
|
99
|
+
await this.handleWebhookEvent(event);
|
|
100
|
+
} catch (error) {
|
|
101
|
+
this.logger.error(`Failed to process event: ${event.type}`, error);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
this.isProcessing = false;
|
|
105
|
+
}
|
|
106
|
+
async handleWebhookEvent(payload) {
|
|
107
|
+
const { type, action, data } = payload;
|
|
108
|
+
switch (type) {
|
|
109
|
+
case "Issue":
|
|
110
|
+
await this.handleIssueEvent(action, data);
|
|
111
|
+
break;
|
|
112
|
+
case "Comment":
|
|
113
|
+
await this.handleCommentEvent(action, data);
|
|
114
|
+
break;
|
|
115
|
+
case "Project":
|
|
116
|
+
await this.handleProjectEvent(action, data);
|
|
117
|
+
break;
|
|
118
|
+
default:
|
|
119
|
+
this.logger.debug(`Unhandled event type: ${type}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
async handleIssueEvent(action, data) {
|
|
123
|
+
const issue = data;
|
|
124
|
+
switch (action) {
|
|
125
|
+
case "create":
|
|
126
|
+
this.logger.info(
|
|
127
|
+
`New issue created: ${issue.identifier} - ${issue.title}`
|
|
128
|
+
);
|
|
129
|
+
await this.syncService.syncIssueToLocal(issue);
|
|
130
|
+
break;
|
|
131
|
+
case "update":
|
|
132
|
+
this.logger.info(`Issue updated: ${issue.identifier} - ${issue.title}`);
|
|
133
|
+
await this.syncService.syncIssueToLocal(issue);
|
|
134
|
+
break;
|
|
135
|
+
case "remove":
|
|
136
|
+
this.logger.info(`Issue removed: ${issue.identifier}`);
|
|
137
|
+
await this.syncService.removeLocalIssue(issue.identifier);
|
|
138
|
+
break;
|
|
139
|
+
default:
|
|
140
|
+
this.logger.debug(`Unhandled issue action: ${action}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async handleCommentEvent(action, data) {
|
|
144
|
+
this.logger.debug(`Comment event: ${action}`, { issueId: data.issue?.id });
|
|
145
|
+
}
|
|
146
|
+
async handleProjectEvent(action, data) {
|
|
147
|
+
this.logger.debug(`Project event: ${action}`, { projectId: data.id });
|
|
148
|
+
}
|
|
149
|
+
async start() {
|
|
150
|
+
return new Promise((resolve) => {
|
|
151
|
+
this.server = this.app.listen(
|
|
152
|
+
this.config.port,
|
|
153
|
+
this.config.host,
|
|
154
|
+
() => {
|
|
155
|
+
console.log(
|
|
156
|
+
chalk.green("\u2713") + chalk.bold(" Linear Webhook Server Started")
|
|
157
|
+
);
|
|
158
|
+
console.log(
|
|
159
|
+
chalk.cyan(" URL: ") + `http://${this.config.host}:${this.config.port}/webhook/linear`
|
|
160
|
+
);
|
|
161
|
+
console.log(
|
|
162
|
+
chalk.cyan(" Health: ") + `http://${this.config.host}:${this.config.port}/health`
|
|
163
|
+
);
|
|
164
|
+
if (!this.config.webhookSecret) {
|
|
165
|
+
console.log(
|
|
166
|
+
chalk.yellow(
|
|
167
|
+
" \u26A0 Warning: No webhook secret configured (insecure)"
|
|
168
|
+
)
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
resolve();
|
|
172
|
+
}
|
|
173
|
+
);
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
async stop() {
|
|
177
|
+
return new Promise((resolve) => {
|
|
178
|
+
if (this.server) {
|
|
179
|
+
this.server.close(() => {
|
|
180
|
+
this.logger.info("Webhook server stopped");
|
|
181
|
+
resolve();
|
|
182
|
+
});
|
|
183
|
+
} else {
|
|
184
|
+
resolve();
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
if (process.argv[1] === new URL(import.meta.url).pathname) {
|
|
190
|
+
const server = new LinearWebhookServer();
|
|
191
|
+
server.start().catch((error) => {
|
|
192
|
+
console.error(chalk.red("Failed to start webhook server:"), error);
|
|
193
|
+
process.exit(1);
|
|
194
|
+
});
|
|
195
|
+
process.on("SIGINT", async () => {
|
|
196
|
+
console.log(chalk.yellow("\n\nShutting down webhook server..."));
|
|
197
|
+
await server.stop();
|
|
198
|
+
process.exit(0);
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
export {
|
|
202
|
+
LinearWebhookServer
|
|
203
|
+
};
|
|
204
|
+
//# sourceMappingURL=webhook-server.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/integrations/linear/webhook-server.ts"],
|
|
4
|
+
"sourcesContent": ["#!/usr/bin/env node\n\nimport express from 'express';\nimport crypto from 'crypto';\nimport http from 'http';\nimport {\n LinearWebhookPayload,\n LinearIssue,\n LinearComment,\n LinearProject,\n} from './types.js';\nimport { LinearSyncService } from './sync-service.js';\nimport { LinearIssue as ClientLinearIssue } from './client.js';\nimport { Logger } from '../../utils/logger.js';\nimport chalk from 'chalk';\n\nexport interface WebhookServerConfig {\n port?: number;\n host?: string;\n webhookSecret?: string;\n maxPayloadSize?: string;\n rateLimit?: {\n windowMs?: number;\n max?: number;\n };\n}\n\nexport class LinearWebhookServer {\n private app: express.Application;\n private server: http.Server | null = null;\n private logger: Logger;\n private syncService: LinearSyncService;\n private config: WebhookServerConfig;\n private eventQueue: LinearWebhookPayload[] = [];\n private isProcessing = false;\n\n constructor(config?: WebhookServerConfig) {\n this.app = express();\n this.logger = new Logger('LinearWebhook');\n this.syncService = new LinearSyncService();\n\n this.config = {\n port: config?.port || parseInt(process.env.WEBHOOK_PORT || '3456'),\n host: config?.host || process.env.WEBHOOK_HOST || 'localhost',\n webhookSecret: config?.webhookSecret || process.env.LINEAR_WEBHOOK_SECRET,\n maxPayloadSize: config?.maxPayloadSize || '10mb',\n rateLimit: {\n windowMs: config?.rateLimit?.windowMs || 60000,\n max: config?.rateLimit?.max || 100,\n },\n };\n\n this.setupMiddleware();\n this.setupRoutes();\n }\n\n private setupMiddleware(): void {\n this.app.use(\n express.raw({\n type: 'application/json',\n limit: this.config.maxPayloadSize,\n })\n );\n\n this.app.use((req, res, next) => {\n res.setHeader('X-Powered-By', 'StackMemory');\n next();\n });\n }\n\n private setupRoutes(): void {\n this.app.get('/health', (req, res) => {\n res.json({\n status: 'healthy',\n service: 'linear-webhook',\n timestamp: new Date().toISOString(),\n queue: this.eventQueue.length,\n processing: this.isProcessing,\n });\n });\n\n this.app.post('/webhook/linear', async (req, res) => {\n try {\n if (!this.verifyWebhookSignature(req)) {\n this.logger.warn('Invalid webhook signature');\n return res.status(401).json({ error: 'Unauthorized' });\n }\n\n const payload = JSON.parse(req.body.toString()) as LinearWebhookPayload;\n\n this.logger.info(\n `Received webhook: ${payload.type} - ${payload.action}`\n );\n\n this.eventQueue.push(payload);\n this.processQueue();\n\n return res.status(200).json({\n status: 'accepted',\n queued: true,\n });\n } catch (error) {\n this.logger.error('Webhook processing error:', error);\n return res.status(500).json({ error: 'Internal server error' });\n }\n });\n\n this.app.use((req, res) => {\n res.status(404).json({ error: 'Not found' });\n });\n }\n\n private verifyWebhookSignature(req: express.Request): boolean {\n if (!this.config.webhookSecret) {\n this.logger.warn('No webhook secret configured, accepting all webhooks');\n return true;\n }\n\n const signature = req.headers['linear-signature'] as string;\n if (!signature) {\n return false;\n }\n\n const hash = crypto\n .createHmac('sha256', this.config.webhookSecret)\n .update(req.body)\n .digest('hex');\n\n return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(hash));\n }\n\n private async processQueue(): Promise<void> {\n if (this.isProcessing || this.eventQueue.length === 0) {\n return;\n }\n\n this.isProcessing = true;\n\n while (this.eventQueue.length > 0) {\n const event = this.eventQueue.shift()!;\n\n try {\n await this.handleWebhookEvent(event);\n } catch (error) {\n this.logger.error(`Failed to process event: ${event.type}`, error);\n }\n }\n\n this.isProcessing = false;\n }\n\n private async handleWebhookEvent(\n payload: LinearWebhookPayload\n ): Promise<void> {\n const { type, action, data } = payload;\n\n switch (type) {\n case 'Issue':\n await this.handleIssueEvent(action, data as LinearIssue);\n break;\n case 'Comment':\n await this.handleCommentEvent(action, data as LinearComment);\n break;\n case 'Project':\n await this.handleProjectEvent(action, data as LinearProject);\n break;\n default:\n this.logger.debug(`Unhandled event type: ${type}`);\n }\n }\n\n private async handleIssueEvent(\n action: string,\n data: LinearIssue\n ): Promise<void> {\n const issue = data as ClientLinearIssue;\n\n switch (action) {\n case 'create':\n this.logger.info(\n `New issue created: ${issue.identifier} - ${issue.title}`\n );\n await this.syncService.syncIssueToLocal(issue);\n break;\n case 'update':\n this.logger.info(`Issue updated: ${issue.identifier} - ${issue.title}`);\n await this.syncService.syncIssueToLocal(issue);\n break;\n case 'remove':\n this.logger.info(`Issue removed: ${issue.identifier}`);\n await this.syncService.removeLocalIssue(issue.identifier);\n break;\n default:\n this.logger.debug(`Unhandled issue action: ${action}`);\n }\n }\n\n private async handleCommentEvent(\n action: string,\n data: LinearComment\n ): Promise<void> {\n this.logger.debug(`Comment event: ${action}`, { issueId: data.issue?.id });\n }\n\n private async handleProjectEvent(\n action: string,\n data: LinearProject\n ): Promise<void> {\n this.logger.debug(`Project event: ${action}`, { projectId: data.id });\n }\n\n public async start(): Promise<void> {\n return new Promise((resolve) => {\n this.server = this.app.listen(\n this.config.port!,\n this.config.host!,\n () => {\n console.log(\n chalk.green('\u2713') + chalk.bold(' Linear Webhook Server Started')\n );\n console.log(\n chalk.cyan(' URL: ') +\n `http://${this.config.host}:${this.config.port}/webhook/linear`\n );\n console.log(\n chalk.cyan(' Health: ') +\n `http://${this.config.host}:${this.config.port}/health`\n );\n\n if (!this.config.webhookSecret) {\n console.log(\n chalk.yellow(\n ' \u26A0 Warning: No webhook secret configured (insecure)'\n )\n );\n }\n\n resolve();\n }\n );\n });\n }\n\n public async stop(): Promise<void> {\n return new Promise((resolve) => {\n if (this.server) {\n this.server.close(() => {\n this.logger.info('Webhook server stopped');\n resolve();\n });\n } else {\n resolve();\n }\n });\n }\n}\n\n// Standalone execution support\nif (process.argv[1] === new URL(import.meta.url).pathname) {\n const server = new LinearWebhookServer();\n\n server.start().catch((error) => {\n console.error(chalk.red('Failed to start webhook server:'), error);\n process.exit(1);\n });\n\n process.on('SIGINT', async () => {\n console.log(chalk.yellow('\\n\\nShutting down webhook server...'));\n await server.stop();\n process.exit(0);\n });\n}\n"],
|
|
5
|
+
"mappings": ";AAEA,OAAO,aAAa;AACpB,OAAO,YAAY;AAQnB,SAAS,yBAAyB;AAElC,SAAS,cAAc;AACvB,OAAO,WAAW;AAaX,MAAM,oBAAoB;AAAA,EACvB;AAAA,EACA,SAA6B;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAqC,CAAC;AAAA,EACtC,eAAe;AAAA,EAEvB,YAAY,QAA8B;AACxC,SAAK,MAAM,QAAQ;AACnB,SAAK,SAAS,IAAI,OAAO,eAAe;AACxC,SAAK,cAAc,IAAI,kBAAkB;AAEzC,SAAK,SAAS;AAAA,MACZ,MAAM,QAAQ,QAAQ,SAAS,QAAQ,IAAI,gBAAgB,MAAM;AAAA,MACjE,MAAM,QAAQ,QAAQ,QAAQ,IAAI,gBAAgB;AAAA,MAClD,eAAe,QAAQ,iBAAiB,QAAQ,IAAI;AAAA,MACpD,gBAAgB,QAAQ,kBAAkB;AAAA,MAC1C,WAAW;AAAA,QACT,UAAU,QAAQ,WAAW,YAAY;AAAA,QACzC,KAAK,QAAQ,WAAW,OAAO;AAAA,MACjC;AAAA,IACF;AAEA,SAAK,gBAAgB;AACrB,SAAK,YAAY;AAAA,EACnB;AAAA,EAEQ,kBAAwB;AAC9B,SAAK,IAAI;AAAA,MACP,QAAQ,IAAI;AAAA,QACV,MAAM;AAAA,QACN,OAAO,KAAK,OAAO;AAAA,MACrB,CAAC;AAAA,IACH;AAEA,SAAK,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;AAC/B,UAAI,UAAU,gBAAgB,aAAa;AAC3C,WAAK;AAAA,IACP,CAAC;AAAA,EACH;AAAA,EAEQ,cAAoB;AAC1B,SAAK,IAAI,IAAI,WAAW,CAAC,KAAK,QAAQ;AACpC,UAAI,KAAK;AAAA,QACP,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,QAClC,OAAO,KAAK,WAAW;AAAA,QACvB,YAAY,KAAK;AAAA,MACnB,CAAC;AAAA,IACH,CAAC;AAED,SAAK,IAAI,KAAK,mBAAmB,OAAO,KAAK,QAAQ;AACnD,UAAI;AACF,YAAI,CAAC,KAAK,uBAAuB,GAAG,GAAG;AACrC,eAAK,OAAO,KAAK,2BAA2B;AAC5C,iBAAO,IAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,eAAe,CAAC;AAAA,QACvD;AAEA,cAAM,UAAU,KAAK,MAAM,IAAI,KAAK,SAAS,CAAC;AAE9C,aAAK,OAAO;AAAA,UACV,qBAAqB,QAAQ,IAAI,MAAM,QAAQ,MAAM;AAAA,QACvD;AAEA,aAAK,WAAW,KAAK,OAAO;AAC5B,aAAK,aAAa;AAElB,eAAO,IAAI,OAAO,GAAG,EAAE,KAAK;AAAA,UAC1B,QAAQ;AAAA,UACR,QAAQ;AAAA,QACV,CAAC;AAAA,MACH,SAAS,OAAO;AACd,aAAK,OAAO,MAAM,6BAA6B,KAAK;AACpD,eAAO,IAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,wBAAwB,CAAC;AAAA,MAChE;AAAA,IACF,CAAC;AAED,SAAK,IAAI,IAAI,CAAC,KAAK,QAAQ;AACzB,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,YAAY,CAAC;AAAA,IAC7C,CAAC;AAAA,EACH;AAAA,EAEQ,uBAAuB,KAA+B;AAC5D,QAAI,CAAC,KAAK,OAAO,eAAe;AAC9B,WAAK,OAAO,KAAK,sDAAsD;AACvE,aAAO;AAAA,IACT;AAEA,UAAM,YAAY,IAAI,QAAQ,kBAAkB;AAChD,QAAI,CAAC,WAAW;AACd,aAAO;AAAA,IACT;AAEA,UAAM,OAAO,OACV,WAAW,UAAU,KAAK,OAAO,aAAa,EAC9C,OAAO,IAAI,IAAI,EACf,OAAO,KAAK;AAEf,WAAO,OAAO,gBAAgB,OAAO,KAAK,SAAS,GAAG,OAAO,KAAK,IAAI,CAAC;AAAA,EACzE;AAAA,EAEA,MAAc,eAA8B;AAC1C,QAAI,KAAK,gBAAgB,KAAK,WAAW,WAAW,GAAG;AACrD;AAAA,IACF;AAEA,SAAK,eAAe;AAEpB,WAAO,KAAK,WAAW,SAAS,GAAG;AACjC,YAAM,QAAQ,KAAK,WAAW,MAAM;AAEpC,UAAI;AACF,cAAM,KAAK,mBAAmB,KAAK;AAAA,MACrC,SAAS,OAAO;AACd,aAAK,OAAO,MAAM,4BAA4B,MAAM,IAAI,IAAI,KAAK;AAAA,MACnE;AAAA,IACF;AAEA,SAAK,eAAe;AAAA,EACtB;AAAA,EAEA,MAAc,mBACZ,SACe;AACf,UAAM,EAAE,MAAM,QAAQ,KAAK,IAAI;AAE/B,YAAQ,MAAM;AAAA,MACZ,KAAK;AACH,cAAM,KAAK,iBAAiB,QAAQ,IAAmB;AACvD;AAAA,MACF,KAAK;AACH,cAAM,KAAK,mBAAmB,QAAQ,IAAqB;AAC3D;AAAA,MACF,KAAK;AACH,cAAM,KAAK,mBAAmB,QAAQ,IAAqB;AAC3D;AAAA,MACF;AACE,aAAK,OAAO,MAAM,yBAAyB,IAAI,EAAE;AAAA,IACrD;AAAA,EACF;AAAA,EAEA,MAAc,iBACZ,QACA,MACe;AACf,UAAM,QAAQ;AAEd,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,aAAK,OAAO;AAAA,UACV,sBAAsB,MAAM,UAAU,MAAM,MAAM,KAAK;AAAA,QACzD;AACA,cAAM,KAAK,YAAY,iBAAiB,KAAK;AAC7C;AAAA,MACF,KAAK;AACH,aAAK,OAAO,KAAK,kBAAkB,MAAM,UAAU,MAAM,MAAM,KAAK,EAAE;AACtE,cAAM,KAAK,YAAY,iBAAiB,KAAK;AAC7C;AAAA,MACF,KAAK;AACH,aAAK,OAAO,KAAK,kBAAkB,MAAM,UAAU,EAAE;AACrD,cAAM,KAAK,YAAY,iBAAiB,MAAM,UAAU;AACxD;AAAA,MACF;AACE,aAAK,OAAO,MAAM,2BAA2B,MAAM,EAAE;AAAA,IACzD;AAAA,EACF;AAAA,EAEA,MAAc,mBACZ,QACA,MACe;AACf,SAAK,OAAO,MAAM,kBAAkB,MAAM,IAAI,EAAE,SAAS,KAAK,OAAO,GAAG,CAAC;AAAA,EAC3E;AAAA,EAEA,MAAc,mBACZ,QACA,MACe;AACf,SAAK,OAAO,MAAM,kBAAkB,MAAM,IAAI,EAAE,WAAW,KAAK,GAAG,CAAC;AAAA,EACtE;AAAA,EAEA,MAAa,QAAuB;AAClC,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,WAAK,SAAS,KAAK,IAAI;AAAA,QACrB,KAAK,OAAO;AAAA,QACZ,KAAK,OAAO;AAAA,QACZ,MAAM;AACJ,kBAAQ;AAAA,YACN,MAAM,MAAM,QAAG,IAAI,MAAM,KAAK,gCAAgC;AAAA,UAChE;AACA,kBAAQ;AAAA,YACN,MAAM,KAAK,SAAS,IAClB,UAAU,KAAK,OAAO,IAAI,IAAI,KAAK,OAAO,IAAI;AAAA,UAClD;AACA,kBAAQ;AAAA,YACN,MAAM,KAAK,YAAY,IACrB,UAAU,KAAK,OAAO,IAAI,IAAI,KAAK,OAAO,IAAI;AAAA,UAClD;AAEA,cAAI,CAAC,KAAK,OAAO,eAAe;AAC9B,oBAAQ;AAAA,cACN,MAAM;AAAA,gBACJ;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAEA,kBAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAa,OAAsB;AACjC,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAI,KAAK,QAAQ;AACf,aAAK,OAAO,MAAM,MAAM;AACtB,eAAK,OAAO,KAAK,wBAAwB;AACzC,kBAAQ;AAAA,QACV,CAAC;AAAA,MACH,OAAO;AACL,gBAAQ;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAGA,IAAI,QAAQ,KAAK,CAAC,MAAM,IAAI,IAAI,YAAY,GAAG,EAAE,UAAU;AACzD,QAAM,SAAS,IAAI,oBAAoB;AAEvC,SAAO,MAAM,EAAE,MAAM,CAAC,UAAU;AAC9B,YAAQ,MAAM,MAAM,IAAI,iCAAiC,GAAG,KAAK;AACjE,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAED,UAAQ,GAAG,UAAU,YAAY;AAC/B,YAAQ,IAAI,MAAM,OAAO,qCAAqC,CAAC;AAC/D,UAAM,OAAO,KAAK;AAClB,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACH;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { logger } from "../../core/monitoring/logger.js";
|
|
2
|
+
import crypto from "crypto";
|
|
3
|
+
class LinearWebhookHandler {
|
|
4
|
+
syncEngine;
|
|
5
|
+
taskStore;
|
|
6
|
+
webhookSecret;
|
|
7
|
+
constructor(webhookSecret) {
|
|
8
|
+
this.webhookSecret = webhookSecret || process.env.LINEAR_WEBHOOK_SECRET;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Set the sync engine for processing webhooks
|
|
12
|
+
*/
|
|
13
|
+
setSyncEngine(syncEngine) {
|
|
14
|
+
this.syncEngine = syncEngine;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Set the task store for direct updates
|
|
18
|
+
*/
|
|
19
|
+
setTaskStore(taskStore) {
|
|
20
|
+
this.taskStore = taskStore;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Verify webhook signature
|
|
24
|
+
*/
|
|
25
|
+
verifySignature(body, signature) {
|
|
26
|
+
if (!this.webhookSecret) {
|
|
27
|
+
logger.warn("No webhook secret configured, skipping verification");
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
const hmac = crypto.createHmac("sha256", this.webhookSecret);
|
|
31
|
+
hmac.update(body);
|
|
32
|
+
const expectedSignature = hmac.digest("hex");
|
|
33
|
+
return signature === expectedSignature;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Validate webhook payload structure
|
|
37
|
+
*/
|
|
38
|
+
validateWebhookPayload(payload) {
|
|
39
|
+
if (!payload || typeof payload !== "object") return null;
|
|
40
|
+
const p = payload;
|
|
41
|
+
if (!p.action || typeof p.action !== "string") return null;
|
|
42
|
+
if (!p.type || typeof p.type !== "string") return null;
|
|
43
|
+
if (!p.data || typeof p.data !== "object") return null;
|
|
44
|
+
if (!p.data.id || typeof p.data.id !== "string") return null;
|
|
45
|
+
if (p.data.title && typeof p.data.title === "string") {
|
|
46
|
+
p.data.title = p.data.title.substring(0, 500);
|
|
47
|
+
}
|
|
48
|
+
if (p.data.description && typeof p.data.description === "string") {
|
|
49
|
+
p.data.description = p.data.description.substring(0, 5e3);
|
|
50
|
+
}
|
|
51
|
+
return p;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Process incoming webhook
|
|
55
|
+
*/
|
|
56
|
+
async processWebhook(payload) {
|
|
57
|
+
const validatedPayload = this.validateWebhookPayload(payload);
|
|
58
|
+
if (!validatedPayload) {
|
|
59
|
+
logger.error("Invalid webhook payload received");
|
|
60
|
+
throw new Error("Invalid webhook payload");
|
|
61
|
+
}
|
|
62
|
+
logger.info("Processing Linear webhook", {
|
|
63
|
+
action: validatedPayload.action,
|
|
64
|
+
type: validatedPayload.type,
|
|
65
|
+
id: validatedPayload.data.id
|
|
66
|
+
});
|
|
67
|
+
payload = validatedPayload;
|
|
68
|
+
if (payload.type !== "Issue") {
|
|
69
|
+
logger.info(`Ignoring webhook for type: ${payload.type}`);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
switch (payload.action) {
|
|
73
|
+
case "create":
|
|
74
|
+
await this.handleIssueCreated(payload);
|
|
75
|
+
break;
|
|
76
|
+
case "update":
|
|
77
|
+
await this.handleIssueUpdated(payload);
|
|
78
|
+
break;
|
|
79
|
+
case "remove":
|
|
80
|
+
await this.handleIssueRemoved(payload);
|
|
81
|
+
break;
|
|
82
|
+
default:
|
|
83
|
+
logger.warn(`Unknown webhook action: ${payload.action}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Handle issue created in Linear
|
|
88
|
+
*/
|
|
89
|
+
async handleIssueCreated(payload) {
|
|
90
|
+
logger.info("Linear issue created", {
|
|
91
|
+
identifier: payload.data.identifier
|
|
92
|
+
});
|
|
93
|
+
if (!this.shouldSyncIssue(payload.data)) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
logger.info("Would create StackMemory task for Linear issue", {
|
|
97
|
+
identifier: payload.data.identifier,
|
|
98
|
+
title: payload.data.title
|
|
99
|
+
});
|
|
100
|
+
if (this.taskStore) {
|
|
101
|
+
try {
|
|
102
|
+
const taskId = this.taskStore.createTask({
|
|
103
|
+
frameId: "linear-import",
|
|
104
|
+
// Special frame for Linear imports
|
|
105
|
+
title: payload.data.title || "Untitled Linear Issue",
|
|
106
|
+
description: payload.data.description || "",
|
|
107
|
+
priority: this.mapLinearPriorityToStackMemory(payload.data.priority),
|
|
108
|
+
assignee: payload.data.assignee?.email,
|
|
109
|
+
tags: payload.data.labels?.map((l) => l.name) || []
|
|
110
|
+
});
|
|
111
|
+
this.storeMapping(taskId, payload.data.id);
|
|
112
|
+
logger.info("Created StackMemory task from Linear issue", {
|
|
113
|
+
stackmemoryId: taskId,
|
|
114
|
+
linearId: payload.data.id
|
|
115
|
+
});
|
|
116
|
+
} catch (error) {
|
|
117
|
+
logger.error("Failed to create task from Linear issue", {
|
|
118
|
+
error: error instanceof Error ? error.message : String(error)
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Handle issue updated in Linear
|
|
125
|
+
*/
|
|
126
|
+
async handleIssueUpdated(payload) {
|
|
127
|
+
logger.info("Linear issue updated", {
|
|
128
|
+
identifier: payload.data.identifier
|
|
129
|
+
});
|
|
130
|
+
if (!this.syncEngine) {
|
|
131
|
+
logger.warn("No sync engine configured, cannot process update");
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const mapping = this.findMappingByLinearId(payload.data.id);
|
|
135
|
+
if (!mapping) {
|
|
136
|
+
logger.info("No mapping found for Linear issue", { id: payload.data.id });
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const task = this.taskStore?.getTask(mapping.stackmemoryId);
|
|
140
|
+
if (!task) {
|
|
141
|
+
logger.warn("StackMemory task not found", { id: mapping.stackmemoryId });
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
let newStatus;
|
|
145
|
+
if (payload.data.state) {
|
|
146
|
+
const mappedStatus = this.mapLinearStateToStatus(payload.data.state);
|
|
147
|
+
if (mappedStatus !== task.status) {
|
|
148
|
+
newStatus = mappedStatus;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (payload.data.completedAt) {
|
|
152
|
+
newStatus = "completed";
|
|
153
|
+
}
|
|
154
|
+
if (newStatus) {
|
|
155
|
+
this.taskStore?.updateTaskStatus(
|
|
156
|
+
mapping.stackmemoryId,
|
|
157
|
+
newStatus,
|
|
158
|
+
"Linear webhook update"
|
|
159
|
+
);
|
|
160
|
+
logger.info("Updated StackMemory task status from webhook", {
|
|
161
|
+
taskId: mapping.stackmemoryId,
|
|
162
|
+
newStatus
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
if (payload.data.title && payload.data.title !== task.title) {
|
|
166
|
+
logger.info(
|
|
167
|
+
"Task title changed in Linear but not updated in StackMemory",
|
|
168
|
+
{
|
|
169
|
+
taskId: mapping.stackmemoryId,
|
|
170
|
+
oldTitle: task.title,
|
|
171
|
+
newTitle: payload.data.title
|
|
172
|
+
}
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Handle issue removed in Linear
|
|
178
|
+
*/
|
|
179
|
+
async handleIssueRemoved(payload) {
|
|
180
|
+
logger.info("Linear issue removed", {
|
|
181
|
+
identifier: payload.data.identifier
|
|
182
|
+
});
|
|
183
|
+
const mapping = this.findMappingByLinearId(payload.data.id);
|
|
184
|
+
if (!mapping) {
|
|
185
|
+
logger.info("No mapping found for removed Linear issue");
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
this.taskStore?.updateTaskStatus(
|
|
189
|
+
mapping.stackmemoryId,
|
|
190
|
+
"cancelled",
|
|
191
|
+
"Linear issue deleted"
|
|
192
|
+
);
|
|
193
|
+
logger.info("Marked StackMemory task as cancelled due to Linear deletion", {
|
|
194
|
+
taskId: mapping.stackmemoryId
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Check if we should sync this issue
|
|
199
|
+
*/
|
|
200
|
+
shouldSyncIssue(issue) {
|
|
201
|
+
if (!issue.title) {
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
if (issue.state?.type === "canceled" || issue.state?.type === "archived") {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
return true;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Find mapping by Linear ID
|
|
211
|
+
*/
|
|
212
|
+
findMappingByLinearId(linearId) {
|
|
213
|
+
const mapping = this.taskMappings.get(linearId);
|
|
214
|
+
if (mapping) {
|
|
215
|
+
return { stackmemoryId: mapping, linearId };
|
|
216
|
+
}
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
// In-memory task mappings (Linear ID -> StackMemory ID)
|
|
220
|
+
taskMappings = /* @__PURE__ */ new Map();
|
|
221
|
+
/**
|
|
222
|
+
* Store mapping between Linear and StackMemory IDs
|
|
223
|
+
*/
|
|
224
|
+
storeMapping(stackmemoryId, linearId) {
|
|
225
|
+
this.taskMappings.set(linearId, stackmemoryId);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Map Linear priority to StackMemory priority
|
|
229
|
+
*/
|
|
230
|
+
mapLinearPriorityToStackMemory(priority) {
|
|
231
|
+
if (!priority) return "medium";
|
|
232
|
+
if (priority <= 1) return "urgent";
|
|
233
|
+
if (priority === 2) return "high";
|
|
234
|
+
if (priority === 3) return "medium";
|
|
235
|
+
return "low";
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Map Linear state to StackMemory status
|
|
239
|
+
*/
|
|
240
|
+
mapLinearStateToStatus(state) {
|
|
241
|
+
const stateType = state.type?.toLowerCase() || state.name?.toLowerCase();
|
|
242
|
+
switch (stateType) {
|
|
243
|
+
case "backlog":
|
|
244
|
+
case "unstarted":
|
|
245
|
+
return "pending";
|
|
246
|
+
case "started":
|
|
247
|
+
case "in progress":
|
|
248
|
+
return "in_progress";
|
|
249
|
+
case "completed":
|
|
250
|
+
case "done":
|
|
251
|
+
return "completed";
|
|
252
|
+
case "canceled":
|
|
253
|
+
case "cancelled":
|
|
254
|
+
return "cancelled";
|
|
255
|
+
default:
|
|
256
|
+
return "pending";
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Map Linear priority to StackMemory priority
|
|
261
|
+
*/
|
|
262
|
+
mapLinearPriorityToPriority(priority) {
|
|
263
|
+
return 5 - priority;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
export {
|
|
267
|
+
LinearWebhookHandler
|
|
268
|
+
};
|
|
269
|
+
//# sourceMappingURL=webhook.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/integrations/linear/webhook.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Linear Webhook Handler\n * Processes incoming webhooks from Linear for real-time sync\n */\n\nimport { logger } from '../../core/monitoring/logger.js';\nimport { LinearSyncEngine } from './sync.js';\nimport { PebblesTaskStore } from '../../features/tasks/pebbles-task-store.js';\nimport crypto from 'crypto';\n\nexport interface LinearWebhookPayload {\n action: 'create' | 'update' | 'remove';\n createdAt: string;\n data: {\n id: string;\n identifier: string;\n title?: string;\n description?: string;\n state?: {\n id: string;\n name: string;\n type: string;\n };\n priority?: number;\n assignee?: {\n id: string;\n name: string;\n email: string;\n };\n team?: {\n id: string;\n key: string;\n name: string;\n };\n labels?: Array<{\n id: string;\n name: string;\n color: string;\n }>;\n dueDate?: string;\n completedAt?: string;\n updatedAt: string;\n };\n type: 'Issue' | 'Comment' | 'Project' | 'Cycle';\n url: string;\n webhookId: string;\n webhookTimestamp: number;\n}\n\nexport class LinearWebhookHandler {\n private syncEngine?: LinearSyncEngine;\n private taskStore?: PebblesTaskStore;\n private webhookSecret?: string;\n\n constructor(webhookSecret?: string) {\n this.webhookSecret = webhookSecret || process.env.LINEAR_WEBHOOK_SECRET;\n }\n\n /**\n * Set the sync engine for processing webhooks\n */\n setSyncEngine(syncEngine: LinearSyncEngine): void {\n this.syncEngine = syncEngine;\n }\n\n /**\n * Set the task store for direct updates\n */\n setTaskStore(taskStore: PebblesTaskStore): void {\n this.taskStore = taskStore;\n }\n\n /**\n * Verify webhook signature\n */\n verifySignature(body: string, signature: string): boolean {\n if (!this.webhookSecret) {\n logger.warn('No webhook secret configured, skipping verification');\n return true; // Allow in development\n }\n\n const hmac = crypto.createHmac('sha256', this.webhookSecret);\n hmac.update(body);\n const expectedSignature = hmac.digest('hex');\n\n return signature === expectedSignature;\n }\n\n /**\n * Validate webhook payload structure\n */\n private validateWebhookPayload(\n payload: unknown\n ): LinearWebhookPayload | null {\n if (!payload || typeof payload !== 'object') return null;\n\n const p = payload as any;\n\n // Validate required fields\n if (!p.action || typeof p.action !== 'string') return null;\n if (!p.type || typeof p.type !== 'string') return null;\n if (!p.data || typeof p.data !== 'object') return null;\n if (!p.data.id || typeof p.data.id !== 'string') return null;\n\n // Sanitize string fields to prevent injection\n if (p.data.title && typeof p.data.title === 'string') {\n p.data.title = p.data.title.substring(0, 500); // Limit length\n }\n if (p.data.description && typeof p.data.description === 'string') {\n p.data.description = p.data.description.substring(0, 5000); // Limit length\n }\n\n return p as LinearWebhookPayload;\n }\n\n /**\n * Process incoming webhook\n */\n async processWebhook(payload: LinearWebhookPayload): Promise<void> {\n // Validate payload first\n const validatedPayload = this.validateWebhookPayload(payload);\n if (!validatedPayload) {\n logger.error('Invalid webhook payload received');\n throw new Error('Invalid webhook payload');\n }\n\n logger.info('Processing Linear webhook', {\n action: validatedPayload.action,\n type: validatedPayload.type,\n id: validatedPayload.data.id,\n });\n\n payload = validatedPayload;\n\n // Only process Issue webhooks for now\n if (payload.type !== 'Issue') {\n logger.info(`Ignoring webhook for type: ${payload.type}`);\n return;\n }\n\n switch (payload.action) {\n case 'create':\n await this.handleIssueCreated(payload);\n break;\n case 'update':\n await this.handleIssueUpdated(payload);\n break;\n case 'remove':\n await this.handleIssueRemoved(payload);\n break;\n default:\n logger.warn(`Unknown webhook action: ${payload.action}`);\n }\n }\n\n /**\n * Handle issue created in Linear\n */\n private async handleIssueCreated(\n payload: LinearWebhookPayload\n ): Promise<void> {\n logger.info('Linear issue created', {\n identifier: payload.data.identifier,\n });\n\n // Check if we should sync this issue\n if (!this.shouldSyncIssue(payload.data)) {\n return;\n }\n\n // For now, just log it - full implementation would create a StackMemory task\n logger.info('Would create StackMemory task for Linear issue', {\n identifier: payload.data.identifier,\n title: payload.data.title,\n });\n\n // Create a StackMemory task from Linear issue\n if (this.taskStore) {\n try {\n const taskId = this.taskStore.createTask({\n frameId: 'linear-import', // Special frame for Linear imports\n title: payload.data.title || 'Untitled Linear Issue',\n description: payload.data.description || '',\n priority: this.mapLinearPriorityToStackMemory(payload.data.priority),\n assignee: payload.data.assignee?.email,\n tags: payload.data.labels?.map((l: any) => l.name) || [],\n });\n\n // Store mapping for future syncing\n this.storeMapping(taskId, payload.data.id);\n\n logger.info('Created StackMemory task from Linear issue', {\n stackmemoryId: taskId,\n linearId: payload.data.id,\n });\n } catch (error) {\n logger.error('Failed to create task from Linear issue', {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n }\n\n /**\n * Handle issue updated in Linear\n */\n private async handleIssueUpdated(\n payload: LinearWebhookPayload\n ): Promise<void> {\n logger.info('Linear issue updated', {\n identifier: payload.data.identifier,\n });\n\n if (!this.syncEngine) {\n logger.warn('No sync engine configured, cannot process update');\n return;\n }\n\n // Find mapped StackMemory task\n const mapping = this.findMappingByLinearId(payload.data.id);\n if (!mapping) {\n logger.info('No mapping found for Linear issue', { id: payload.data.id });\n return;\n }\n\n // Check for conflicts\n const task = this.taskStore?.getTask(mapping.stackmemoryId);\n if (!task) {\n logger.warn('StackMemory task not found', { id: mapping.stackmemoryId });\n return;\n }\n\n // Update the task based on Linear changes\n let newStatus:\n | 'pending'\n | 'in_progress'\n | 'completed'\n | 'cancelled'\n | undefined;\n\n if (payload.data.state) {\n const mappedStatus = this.mapLinearStateToStatus(payload.data.state) as\n | 'pending'\n | 'in_progress'\n | 'completed'\n | 'cancelled';\n if (mappedStatus !== task.status) {\n newStatus = mappedStatus;\n }\n }\n\n if (payload.data.completedAt) {\n newStatus = 'completed';\n }\n\n // Update status if changed\n if (newStatus) {\n this.taskStore?.updateTaskStatus(\n mapping.stackmemoryId,\n newStatus,\n 'Linear webhook update'\n );\n logger.info('Updated StackMemory task status from webhook', {\n taskId: mapping.stackmemoryId,\n newStatus,\n });\n }\n\n // For other properties, we'd need to implement a more complete update method\n // For now, log what changed\n if (payload.data.title && payload.data.title !== task.title) {\n logger.info(\n 'Task title changed in Linear but not updated in StackMemory',\n {\n taskId: mapping.stackmemoryId,\n oldTitle: task.title,\n newTitle: payload.data.title,\n }\n );\n }\n }\n\n /**\n * Handle issue removed in Linear\n */\n private async handleIssueRemoved(\n payload: LinearWebhookPayload\n ): Promise<void> {\n logger.info('Linear issue removed', {\n identifier: payload.data.identifier,\n });\n\n const mapping = this.findMappingByLinearId(payload.data.id);\n if (!mapping) {\n logger.info('No mapping found for removed Linear issue');\n return;\n }\n\n // Mark the StackMemory task as cancelled\n this.taskStore?.updateTaskStatus(\n mapping.stackmemoryId,\n 'cancelled',\n 'Linear issue deleted'\n );\n\n logger.info('Marked StackMemory task as cancelled due to Linear deletion', {\n taskId: mapping.stackmemoryId,\n });\n }\n\n /**\n * Check if we should sync this issue\n */\n private shouldSyncIssue(issue: LinearWebhookPayload['data']): boolean {\n // Add your filtering logic here\n // For example, only sync issues from specific teams or with certain labels\n\n // Skip issues without a title\n if (!issue.title) {\n return false;\n }\n\n // Skip archived/cancelled issues\n if (issue.state?.type === 'canceled' || issue.state?.type === 'archived') {\n return false;\n }\n\n return true;\n }\n\n /**\n * Find mapping by Linear ID\n */\n private findMappingByLinearId(\n linearId: string\n ): { stackmemoryId: string; linearId: string } | null {\n // Use in-memory mapping for now\n // In production, this would query a database\n const mapping = this.taskMappings.get(linearId);\n if (mapping) {\n return { stackmemoryId: mapping, linearId };\n }\n return null;\n }\n\n // In-memory task mappings (Linear ID -> StackMemory ID)\n private taskMappings = new Map<string, string>();\n\n /**\n * Store mapping between Linear and StackMemory IDs\n */\n private storeMapping(stackmemoryId: string, linearId: string): void {\n this.taskMappings.set(linearId, stackmemoryId);\n // In production, persist to database\n }\n\n /**\n * Map Linear priority to StackMemory priority\n */\n private mapLinearPriorityToStackMemory(\n priority: number | undefined\n ): 'low' | 'medium' | 'high' | 'urgent' {\n if (!priority) return 'medium';\n if (priority <= 1) return 'urgent';\n if (priority === 2) return 'high';\n if (priority === 3) return 'medium';\n return 'low';\n }\n\n /**\n * Map Linear state to StackMemory status\n */\n private mapLinearStateToStatus(state: {\n type?: string;\n name?: string;\n }): string {\n const stateType = state.type?.toLowerCase() || state.name?.toLowerCase();\n\n switch (stateType) {\n case 'backlog':\n case 'unstarted':\n return 'pending';\n case 'started':\n case 'in progress':\n return 'in_progress';\n case 'completed':\n case 'done':\n return 'completed';\n case 'canceled':\n case 'cancelled':\n return 'cancelled';\n default:\n return 'pending';\n }\n }\n\n /**\n * Map Linear priority to StackMemory priority\n */\n private mapLinearPriorityToPriority(priority: number): number {\n // Linear uses 0-4, StackMemory uses 1-5\n return 5 - priority;\n }\n}\n"],
|
|
5
|
+
"mappings": "AAKA,SAAS,cAAc;AAGvB,OAAO,YAAY;AAyCZ,MAAM,qBAAqB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,eAAwB;AAClC,SAAK,gBAAgB,iBAAiB,QAAQ,IAAI;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,YAAoC;AAChD,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,WAAmC;AAC9C,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,MAAc,WAA4B;AACxD,QAAI,CAAC,KAAK,eAAe;AACvB,aAAO,KAAK,qDAAqD;AACjE,aAAO;AAAA,IACT;AAEA,UAAM,OAAO,OAAO,WAAW,UAAU,KAAK,aAAa;AAC3D,SAAK,OAAO,IAAI;AAChB,UAAM,oBAAoB,KAAK,OAAO,KAAK;AAE3C,WAAO,cAAc;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKQ,uBACN,SAC6B;AAC7B,QAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AAEpD,UAAM,IAAI;AAGV,QAAI,CAAC,EAAE,UAAU,OAAO,EAAE,WAAW,SAAU,QAAO;AACtD,QAAI,CAAC,EAAE,QAAQ,OAAO,EAAE,SAAS,SAAU,QAAO;AAClD,QAAI,CAAC,EAAE,QAAQ,OAAO,EAAE,SAAS,SAAU,QAAO;AAClD,QAAI,CAAC,EAAE,KAAK,MAAM,OAAO,EAAE,KAAK,OAAO,SAAU,QAAO;AAGxD,QAAI,EAAE,KAAK,SAAS,OAAO,EAAE,KAAK,UAAU,UAAU;AACpD,QAAE,KAAK,QAAQ,EAAE,KAAK,MAAM,UAAU,GAAG,GAAG;AAAA,IAC9C;AACA,QAAI,EAAE,KAAK,eAAe,OAAO,EAAE,KAAK,gBAAgB,UAAU;AAChE,QAAE,KAAK,cAAc,EAAE,KAAK,YAAY,UAAU,GAAG,GAAI;AAAA,IAC3D;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,SAA8C;AAEjE,UAAM,mBAAmB,KAAK,uBAAuB,OAAO;AAC5D,QAAI,CAAC,kBAAkB;AACrB,aAAO,MAAM,kCAAkC;AAC/C,YAAM,IAAI,MAAM,yBAAyB;AAAA,IAC3C;AAEA,WAAO,KAAK,6BAA6B;AAAA,MACvC,QAAQ,iBAAiB;AAAA,MACzB,MAAM,iBAAiB;AAAA,MACvB,IAAI,iBAAiB,KAAK;AAAA,IAC5B,CAAC;AAED,cAAU;AAGV,QAAI,QAAQ,SAAS,SAAS;AAC5B,aAAO,KAAK,8BAA8B,QAAQ,IAAI,EAAE;AACxD;AAAA,IACF;AAEA,YAAQ,QAAQ,QAAQ;AAAA,MACtB,KAAK;AACH,cAAM,KAAK,mBAAmB,OAAO;AACrC;AAAA,MACF,KAAK;AACH,cAAM,KAAK,mBAAmB,OAAO;AACrC;AAAA,MACF,KAAK;AACH,cAAM,KAAK,mBAAmB,OAAO;AACrC;AAAA,MACF;AACE,eAAO,KAAK,2BAA2B,QAAQ,MAAM,EAAE;AAAA,IAC3D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,mBACZ,SACe;AACf,WAAO,KAAK,wBAAwB;AAAA,MAClC,YAAY,QAAQ,KAAK;AAAA,IAC3B,CAAC;AAGD,QAAI,CAAC,KAAK,gBAAgB,QAAQ,IAAI,GAAG;AACvC;AAAA,IACF;AAGA,WAAO,KAAK,kDAAkD;AAAA,MAC5D,YAAY,QAAQ,KAAK;AAAA,MACzB,OAAO,QAAQ,KAAK;AAAA,IACtB,CAAC;AAGD,QAAI,KAAK,WAAW;AAClB,UAAI;AACF,cAAM,SAAS,KAAK,UAAU,WAAW;AAAA,UACvC,SAAS;AAAA;AAAA,UACT,OAAO,QAAQ,KAAK,SAAS;AAAA,UAC7B,aAAa,QAAQ,KAAK,eAAe;AAAA,UACzC,UAAU,KAAK,+BAA+B,QAAQ,KAAK,QAAQ;AAAA,UACnE,UAAU,QAAQ,KAAK,UAAU;AAAA,UACjC,MAAM,QAAQ,KAAK,QAAQ,IAAI,CAAC,MAAW,EAAE,IAAI,KAAK,CAAC;AAAA,QACzD,CAAC;AAGD,aAAK,aAAa,QAAQ,QAAQ,KAAK,EAAE;AAEzC,eAAO,KAAK,8CAA8C;AAAA,UACxD,eAAe;AAAA,UACf,UAAU,QAAQ,KAAK;AAAA,QACzB,CAAC;AAAA,MACH,SAAS,OAAO;AACd,eAAO,MAAM,2CAA2C;AAAA,UACtD,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAC9D,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,mBACZ,SACe;AACf,WAAO,KAAK,wBAAwB;AAAA,MAClC,YAAY,QAAQ,KAAK;AAAA,IAC3B,CAAC;AAED,QAAI,CAAC,KAAK,YAAY;AACpB,aAAO,KAAK,kDAAkD;AAC9D;AAAA,IACF;AAGA,UAAM,UAAU,KAAK,sBAAsB,QAAQ,KAAK,EAAE;AAC1D,QAAI,CAAC,SAAS;AACZ,aAAO,KAAK,qCAAqC,EAAE,IAAI,QAAQ,KAAK,GAAG,CAAC;AACxE;AAAA,IACF;AAGA,UAAM,OAAO,KAAK,WAAW,QAAQ,QAAQ,aAAa;AAC1D,QAAI,CAAC,MAAM;AACT,aAAO,KAAK,8BAA8B,EAAE,IAAI,QAAQ,cAAc,CAAC;AACvE;AAAA,IACF;AAGA,QAAI;AAOJ,QAAI,QAAQ,KAAK,OAAO;AACtB,YAAM,eAAe,KAAK,uBAAuB,QAAQ,KAAK,KAAK;AAKnE,UAAI,iBAAiB,KAAK,QAAQ;AAChC,oBAAY;AAAA,MACd;AAAA,IACF;AAEA,QAAI,QAAQ,KAAK,aAAa;AAC5B,kBAAY;AAAA,IACd;AAGA,QAAI,WAAW;AACb,WAAK,WAAW;AAAA,QACd,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,MACF;AACA,aAAO,KAAK,gDAAgD;AAAA,QAC1D,QAAQ,QAAQ;AAAA,QAChB;AAAA,MACF,CAAC;AAAA,IACH;AAIA,QAAI,QAAQ,KAAK,SAAS,QAAQ,KAAK,UAAU,KAAK,OAAO;AAC3D,aAAO;AAAA,QACL;AAAA,QACA;AAAA,UACE,QAAQ,QAAQ;AAAA,UAChB,UAAU,KAAK;AAAA,UACf,UAAU,QAAQ,KAAK;AAAA,QACzB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,mBACZ,SACe;AACf,WAAO,KAAK,wBAAwB;AAAA,MAClC,YAAY,QAAQ,KAAK;AAAA,IAC3B,CAAC;AAED,UAAM,UAAU,KAAK,sBAAsB,QAAQ,KAAK,EAAE;AAC1D,QAAI,CAAC,SAAS;AACZ,aAAO,KAAK,2CAA2C;AACvD;AAAA,IACF;AAGA,SAAK,WAAW;AAAA,MACd,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAEA,WAAO,KAAK,+DAA+D;AAAA,MACzE,QAAQ,QAAQ;AAAA,IAClB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgB,OAA8C;AAKpE,QAAI,CAAC,MAAM,OAAO;AAChB,aAAO;AAAA,IACT;AAGA,QAAI,MAAM,OAAO,SAAS,cAAc,MAAM,OAAO,SAAS,YAAY;AACxE,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,sBACN,UACoD;AAGpD,UAAM,UAAU,KAAK,aAAa,IAAI,QAAQ;AAC9C,QAAI,SAAS;AACX,aAAO,EAAE,eAAe,SAAS,SAAS;AAAA,IAC5C;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,eAAe,oBAAI,IAAoB;AAAA;AAAA;AAAA;AAAA,EAKvC,aAAa,eAAuB,UAAwB;AAClE,SAAK,aAAa,IAAI,UAAU,aAAa;AAAA,EAE/C;AAAA;AAAA;AAAA;AAAA,EAKQ,+BACN,UACsC;AACtC,QAAI,CAAC,SAAU,QAAO;AACtB,QAAI,YAAY,EAAG,QAAO;AAC1B,QAAI,aAAa,EAAG,QAAO;AAC3B,QAAI,aAAa,EAAG,QAAO;AAC3B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,uBAAuB,OAGpB;AACT,UAAM,YAAY,MAAM,MAAM,YAAY,KAAK,MAAM,MAAM,YAAY;AAEvE,YAAQ,WAAW;AAAA,MACjB,KAAK;AAAA,MACL,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,4BAA4B,UAA0B;AAE5D,WAAO,IAAI;AAAA,EACb;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|