@stackmemoryai/stackmemory 0.5.57 → 0.5.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (611) hide show
  1. package/bin/codex-smd +6 -0
  2. package/dist/cli/codex-sm-danger.js +21 -0
  3. package/dist/cli/codex-sm-danger.js.map +7 -0
  4. package/dist/cli/commands/handoff.js +33 -3
  5. package/dist/cli/commands/handoff.js.map +2 -2
  6. package/dist/cli/commands/search.js +20 -3
  7. package/dist/cli/commands/search.js.map +2 -2
  8. package/dist/core/database/sqlite-adapter.js +13 -3
  9. package/dist/core/database/sqlite-adapter.js.map +2 -2
  10. package/dist/core/errors/error-utils.js +208 -0
  11. package/dist/core/errors/error-utils.js.map +7 -0
  12. package/dist/core/errors/index.js +13 -4
  13. package/dist/core/errors/index.js.map +2 -2
  14. package/dist/core/merge/unified-merge-resolver.js +303 -0
  15. package/dist/core/merge/unified-merge-resolver.js.map +7 -0
  16. package/dist/core/monitoring/logger.js +61 -9
  17. package/dist/core/monitoring/logger.js.map +2 -2
  18. package/dist/core/security/index.js +35 -0
  19. package/dist/core/security/index.js.map +7 -0
  20. package/dist/core/security/input-sanitizer.js +321 -0
  21. package/dist/core/security/input-sanitizer.js.map +7 -0
  22. package/dist/core/session/enhanced-handoff.js +136 -2
  23. package/dist/core/session/enhanced-handoff.js.map +3 -3
  24. package/dist/integrations/linear/client.js +5 -1
  25. package/dist/integrations/linear/client.js.map +2 -2
  26. package/dist/integrations/mcp/remote-server.js +27 -36
  27. package/dist/integrations/mcp/remote-server.js.map +2 -2
  28. package/dist/integrations/mcp/server.js +44 -29
  29. package/dist/integrations/mcp/server.js.map +3 -3
  30. package/dist/scripts/benchmark-performance.js +48 -0
  31. package/dist/scripts/benchmark-performance.js.map +7 -0
  32. package/dist/scripts/check-redis.js +42 -0
  33. package/dist/scripts/check-redis.js.map +7 -0
  34. package/dist/scripts/initialize.js +116 -0
  35. package/dist/scripts/initialize.js.map +7 -0
  36. package/dist/scripts/list-linear-tasks.js +124 -0
  37. package/dist/scripts/list-linear-tasks.js.map +7 -0
  38. package/dist/scripts/measure-handoff-impact.js +340 -0
  39. package/dist/scripts/measure-handoff-impact.js.map +7 -0
  40. package/dist/scripts/query-chromadb.js +160 -0
  41. package/dist/scripts/query-chromadb.js.map +7 -0
  42. package/dist/scripts/show-linear-summary.js +119 -0
  43. package/dist/scripts/show-linear-summary.js.map +7 -0
  44. package/dist/scripts/simple-swarm-demo.js +90 -0
  45. package/dist/scripts/simple-swarm-demo.js.map +7 -0
  46. package/dist/scripts/status.js +155 -0
  47. package/dist/scripts/status.js.map +7 -0
  48. package/dist/scripts/test-chromadb-sync.js +192 -0
  49. package/dist/scripts/test-chromadb-sync.js.map +7 -0
  50. package/dist/scripts/test-ralph-iteration-fix.js +86 -0
  51. package/dist/scripts/test-ralph-iteration-fix.js.map +7 -0
  52. package/dist/scripts/test-ralph-iterations.js +121 -0
  53. package/dist/scripts/test-ralph-iterations.js.map +7 -0
  54. package/dist/scripts/test-redis-storage.js +389 -0
  55. package/dist/scripts/test-redis-storage.js.map +7 -0
  56. package/dist/scripts/test-simple-ralph-state-sync.js +115 -0
  57. package/dist/scripts/test-simple-ralph-state-sync.js.map +7 -0
  58. package/dist/scripts/test-swarm-fixes.js +125 -0
  59. package/dist/scripts/test-swarm-fixes.js.map +7 -0
  60. package/dist/scripts/test-swarm-tui.js +23 -0
  61. package/dist/scripts/test-swarm-tui.js.map +7 -0
  62. package/dist/scripts/test-tui-shortcuts.js +52 -0
  63. package/dist/scripts/test-tui-shortcuts.js.map +7 -0
  64. package/dist/scripts/validate-tui-shortcuts.js +60 -0
  65. package/dist/scripts/validate-tui-shortcuts.js.map +7 -0
  66. package/dist/src/agents/core/agent-task-manager.js +527 -0
  67. package/dist/src/agents/core/agent-task-manager.js.map +7 -0
  68. package/dist/src/agents/verifiers/base-verifier.js +133 -0
  69. package/dist/src/agents/verifiers/base-verifier.js.map +7 -0
  70. package/dist/src/agents/verifiers/formatter-verifier.js +130 -0
  71. package/dist/src/agents/verifiers/formatter-verifier.js.map +7 -0
  72. package/dist/src/agents/verifiers/llm-judge.js +252 -0
  73. package/dist/src/agents/verifiers/llm-judge.js.map +7 -0
  74. package/dist/src/cli/auto-detect.js +321 -0
  75. package/dist/src/cli/auto-detect.js.map +7 -0
  76. package/dist/src/cli/claude-sm-danger.js +21 -0
  77. package/dist/src/cli/claude-sm-danger.js.map +7 -0
  78. package/dist/src/cli/claude-sm.js +1156 -0
  79. package/dist/src/cli/claude-sm.js.map +7 -0
  80. package/dist/src/cli/codex-sm-danger.js +21 -0
  81. package/dist/src/cli/codex-sm-danger.js.map +7 -0
  82. package/dist/src/cli/codex-sm.js +349 -0
  83. package/dist/src/cli/codex-sm.js.map +7 -0
  84. package/dist/src/cli/commands/api.js +232 -0
  85. package/dist/src/cli/commands/api.js.map +7 -0
  86. package/dist/src/cli/commands/auto-background.js +180 -0
  87. package/dist/src/cli/commands/auto-background.js.map +7 -0
  88. package/dist/src/cli/commands/cleanup-processes.js +68 -0
  89. package/dist/src/cli/commands/cleanup-processes.js.map +7 -0
  90. package/dist/src/cli/commands/clear.js +202 -0
  91. package/dist/src/cli/commands/clear.js.map +7 -0
  92. package/dist/src/cli/commands/config.js +445 -0
  93. package/dist/src/cli/commands/config.js.map +7 -0
  94. package/dist/src/cli/commands/context-rehydrate.js +751 -0
  95. package/dist/src/cli/commands/context-rehydrate.js.map +7 -0
  96. package/dist/src/cli/commands/context.js +343 -0
  97. package/dist/src/cli/commands/context.js.map +7 -0
  98. package/dist/src/cli/commands/daemon.js +392 -0
  99. package/dist/src/cli/commands/daemon.js.map +7 -0
  100. package/dist/src/cli/commands/dashboard.js +210 -0
  101. package/dist/src/cli/commands/dashboard.js.map +7 -0
  102. package/dist/src/cli/commands/db.js +147 -0
  103. package/dist/src/cli/commands/db.js.map +7 -0
  104. package/dist/src/cli/commands/decision.js +266 -0
  105. package/dist/src/cli/commands/decision.js.map +7 -0
  106. package/dist/src/cli/commands/discovery.js +279 -0
  107. package/dist/src/cli/commands/discovery.js.map +7 -0
  108. package/dist/src/cli/commands/handoff.js +624 -0
  109. package/dist/src/cli/commands/handoff.js.map +7 -0
  110. package/dist/src/cli/commands/hooks.js +298 -0
  111. package/dist/src/cli/commands/hooks.js.map +7 -0
  112. package/dist/src/cli/commands/linear.js +529 -0
  113. package/dist/src/cli/commands/linear.js.map +7 -0
  114. package/dist/src/cli/commands/log.js +169 -0
  115. package/dist/src/cli/commands/log.js.map +7 -0
  116. package/dist/src/cli/commands/login.js +172 -0
  117. package/dist/src/cli/commands/login.js.map +7 -0
  118. package/dist/src/cli/commands/migrate.js +240 -0
  119. package/dist/src/cli/commands/migrate.js.map +7 -0
  120. package/dist/src/cli/commands/model.js +533 -0
  121. package/dist/src/cli/commands/model.js.map +7 -0
  122. package/dist/src/cli/commands/onboard.js +536 -0
  123. package/dist/src/cli/commands/onboard.js.map +7 -0
  124. package/dist/src/cli/commands/projects.js +199 -0
  125. package/dist/src/cli/commands/projects.js.map +7 -0
  126. package/dist/src/cli/commands/ralph.js +909 -0
  127. package/dist/src/cli/commands/ralph.js.map +7 -0
  128. package/dist/src/cli/commands/retrieval.js +248 -0
  129. package/dist/src/cli/commands/retrieval.js.map +7 -0
  130. package/dist/src/cli/commands/search.js +173 -0
  131. package/dist/src/cli/commands/search.js.map +7 -0
  132. package/dist/src/cli/commands/service.js +749 -0
  133. package/dist/src/cli/commands/service.js.map +7 -0
  134. package/dist/src/cli/commands/session.js +200 -0
  135. package/dist/src/cli/commands/session.js.map +7 -0
  136. package/dist/src/cli/commands/settings.js +306 -0
  137. package/dist/src/cli/commands/settings.js.map +7 -0
  138. package/dist/src/cli/commands/setup.js +701 -0
  139. package/dist/src/cli/commands/setup.js.map +7 -0
  140. package/dist/src/cli/commands/shell.js +249 -0
  141. package/dist/src/cli/commands/shell.js.map +7 -0
  142. package/dist/src/cli/commands/signup.js +50 -0
  143. package/dist/src/cli/commands/signup.js.map +7 -0
  144. package/dist/src/cli/commands/skills.js +470 -0
  145. package/dist/src/cli/commands/skills.js.map +7 -0
  146. package/dist/src/cli/commands/sms-notify.js +795 -0
  147. package/dist/src/cli/commands/sms-notify.js.map +7 -0
  148. package/dist/src/cli/commands/storage-tier.js +183 -0
  149. package/dist/src/cli/commands/storage-tier.js.map +7 -0
  150. package/dist/src/cli/commands/sweep.js +249 -0
  151. package/dist/src/cli/commands/sweep.js.map +7 -0
  152. package/dist/src/cli/commands/tasks.js +213 -0
  153. package/dist/src/cli/commands/tasks.js.map +7 -0
  154. package/dist/src/cli/commands/worktree.js +319 -0
  155. package/dist/src/cli/commands/worktree.js.map +7 -0
  156. package/dist/src/cli/index.js +594 -0
  157. package/dist/src/cli/index.js.map +7 -0
  158. package/dist/src/cli/opencode-sm.js +448 -0
  159. package/dist/src/cli/opencode-sm.js.map +7 -0
  160. package/dist/src/cli/utils/viewer.js +96 -0
  161. package/dist/src/cli/utils/viewer.js.map +7 -0
  162. package/dist/src/core/config/config-manager.js +398 -0
  163. package/dist/src/core/config/config-manager.js.map +7 -0
  164. package/dist/src/core/config/feature-flags.js +76 -0
  165. package/dist/src/core/config/feature-flags.js.map +7 -0
  166. package/dist/src/core/config/storage-config.js +115 -0
  167. package/dist/src/core/config/storage-config.js.map +7 -0
  168. package/dist/src/core/config/types.js +144 -0
  169. package/dist/src/core/config/types.js.map +7 -0
  170. package/dist/src/core/context/auto-context.js +80 -0
  171. package/dist/src/core/context/auto-context.js.map +7 -0
  172. package/dist/src/core/context/dual-stack-manager.js +870 -0
  173. package/dist/src/core/context/dual-stack-manager.js.map +7 -0
  174. package/dist/src/core/context/enhanced-rehydration.js +994 -0
  175. package/dist/src/core/context/enhanced-rehydration.js.map +7 -0
  176. package/dist/src/core/context/frame-database.js +479 -0
  177. package/dist/src/core/context/frame-database.js.map +7 -0
  178. package/dist/src/core/context/frame-digest.js +250 -0
  179. package/dist/src/core/context/frame-digest.js.map +7 -0
  180. package/dist/src/core/context/frame-handoff-manager.js +778 -0
  181. package/dist/src/core/context/frame-handoff-manager.js.map +7 -0
  182. package/dist/src/core/context/frame-lifecycle-hooks.js +119 -0
  183. package/dist/src/core/context/frame-lifecycle-hooks.js.map +7 -0
  184. package/dist/src/core/context/frame-recovery.js +302 -0
  185. package/dist/src/core/context/frame-recovery.js.map +7 -0
  186. package/dist/src/core/context/frame-stack.js +314 -0
  187. package/dist/src/core/context/frame-stack.js.map +7 -0
  188. package/dist/src/core/context/frame-types.js +5 -0
  189. package/dist/src/core/context/frame-types.js.map +7 -0
  190. package/dist/src/core/context/index.js +25 -0
  191. package/dist/src/core/context/index.js.map +7 -0
  192. package/dist/src/core/context/permission-manager.js +185 -0
  193. package/dist/src/core/context/permission-manager.js.map +7 -0
  194. package/dist/src/core/context/recursive-context-manager.js +592 -0
  195. package/dist/src/core/context/recursive-context-manager.js.map +7 -0
  196. package/dist/src/core/context/refactored-frame-manager.js +754 -0
  197. package/dist/src/core/context/refactored-frame-manager.js.map +7 -0
  198. package/dist/src/core/context/shared-context-layer.js +621 -0
  199. package/dist/src/core/context/shared-context-layer.js.map +7 -0
  200. package/dist/src/core/context/stack-merge-resolver.js +749 -0
  201. package/dist/src/core/context/stack-merge-resolver.js.map +7 -0
  202. package/dist/src/core/context/validation.js +130 -0
  203. package/dist/src/core/context/validation.js.map +7 -0
  204. package/dist/src/core/database/batch-operations.js +384 -0
  205. package/dist/src/core/database/batch-operations.js.map +7 -0
  206. package/dist/src/core/database/connection-pool.js +330 -0
  207. package/dist/src/core/database/connection-pool.js.map +7 -0
  208. package/dist/src/core/database/database-adapter.js +60 -0
  209. package/dist/src/core/database/database-adapter.js.map +7 -0
  210. package/dist/src/core/database/migration-manager.js +614 -0
  211. package/dist/src/core/database/migration-manager.js.map +7 -0
  212. package/dist/src/core/database/query-cache.js +298 -0
  213. package/dist/src/core/database/query-cache.js.map +7 -0
  214. package/dist/src/core/database/query-router.js +430 -0
  215. package/dist/src/core/database/query-router.js.map +7 -0
  216. package/dist/src/core/database/sqlite-adapter.js +738 -0
  217. package/dist/src/core/database/sqlite-adapter.js.map +7 -0
  218. package/dist/src/core/digest/enhanced-hybrid-digest.js +277 -0
  219. package/dist/src/core/digest/enhanced-hybrid-digest.js.map +7 -0
  220. package/dist/src/core/digest/frame-digest-integration.js +176 -0
  221. package/dist/src/core/digest/frame-digest-integration.js.map +7 -0
  222. package/dist/src/core/digest/hybrid-digest-generator.js +553 -0
  223. package/dist/src/core/digest/hybrid-digest-generator.js.map +7 -0
  224. package/dist/src/core/digest/index.js +9 -0
  225. package/dist/src/core/digest/index.js.map +7 -0
  226. package/dist/src/core/digest/types.js +25 -0
  227. package/dist/src/core/digest/types.js.map +7 -0
  228. package/dist/src/core/errors/error-utils.js +208 -0
  229. package/dist/src/core/errors/error-utils.js.map +7 -0
  230. package/dist/src/core/errors/index.js +521 -0
  231. package/dist/src/core/errors/index.js.map +7 -0
  232. package/dist/src/core/errors/recovery.js +269 -0
  233. package/dist/src/core/errors/recovery.js.map +7 -0
  234. package/dist/src/core/execution/parallel-executor.js +258 -0
  235. package/dist/src/core/execution/parallel-executor.js.map +7 -0
  236. package/dist/src/core/frame/workflow-templates.js +319 -0
  237. package/dist/src/core/frame/workflow-templates.js.map +7 -0
  238. package/dist/src/core/merge/conflict-detector.js +431 -0
  239. package/dist/src/core/merge/conflict-detector.js.map +7 -0
  240. package/dist/src/core/merge/index.js +9 -0
  241. package/dist/src/core/merge/index.js.map +7 -0
  242. package/dist/src/core/merge/resolution-engine.js +558 -0
  243. package/dist/src/core/merge/resolution-engine.js.map +7 -0
  244. package/dist/src/core/merge/stack-diff.js +532 -0
  245. package/dist/src/core/merge/stack-diff.js.map +7 -0
  246. package/dist/src/core/merge/types.js +5 -0
  247. package/dist/src/core/merge/types.js.map +7 -0
  248. package/dist/src/core/merge/unified-merge-resolver.js +303 -0
  249. package/dist/src/core/merge/unified-merge-resolver.js.map +7 -0
  250. package/dist/src/core/models/fallback-monitor.js +232 -0
  251. package/dist/src/core/models/fallback-monitor.js.map +7 -0
  252. package/dist/src/core/models/model-router.js +340 -0
  253. package/dist/src/core/models/model-router.js.map +7 -0
  254. package/dist/src/core/monitoring/error-handler.js +49 -0
  255. package/dist/src/core/monitoring/error-handler.js.map +7 -0
  256. package/dist/src/core/monitoring/logger.js +202 -0
  257. package/dist/src/core/monitoring/logger.js.map +7 -0
  258. package/dist/src/core/monitoring/metrics.js +172 -0
  259. package/dist/src/core/monitoring/metrics.js.map +7 -0
  260. package/dist/src/core/monitoring/progress-tracker.js +189 -0
  261. package/dist/src/core/monitoring/progress-tracker.js.map +7 -0
  262. package/dist/src/core/monitoring/session-monitor.js +300 -0
  263. package/dist/src/core/monitoring/session-monitor.js.map +7 -0
  264. package/dist/src/core/performance/context-cache.js +273 -0
  265. package/dist/src/core/performance/context-cache.js.map +7 -0
  266. package/dist/src/core/performance/index.js +11 -0
  267. package/dist/src/core/performance/index.js.map +7 -0
  268. package/dist/src/core/performance/lazy-context-loader.js +327 -0
  269. package/dist/src/core/performance/lazy-context-loader.js.map +7 -0
  270. package/dist/src/core/performance/monitor.js +221 -0
  271. package/dist/src/core/performance/monitor.js.map +7 -0
  272. package/dist/src/core/performance/optimized-frame-context.js +345 -0
  273. package/dist/src/core/performance/optimized-frame-context.js.map +7 -0
  274. package/dist/src/core/performance/performance-benchmark.js +277 -0
  275. package/dist/src/core/performance/performance-benchmark.js.map +7 -0
  276. package/dist/src/core/performance/performance-profiler.js +370 -0
  277. package/dist/src/core/performance/performance-profiler.js.map +7 -0
  278. package/dist/src/core/performance/streaming-jsonl-parser.js +195 -0
  279. package/dist/src/core/performance/streaming-jsonl-parser.js.map +7 -0
  280. package/dist/src/core/persistence/postgres-adapter.js +349 -0
  281. package/dist/src/core/persistence/postgres-adapter.js.map +7 -0
  282. package/dist/src/core/projects/project-isolation.js +201 -0
  283. package/dist/src/core/projects/project-isolation.js.map +7 -0
  284. package/dist/src/core/projects/project-manager.js +697 -0
  285. package/dist/src/core/projects/project-manager.js.map +7 -0
  286. package/dist/src/core/query/query-parser.js +370 -0
  287. package/dist/src/core/query/query-parser.js.map +7 -0
  288. package/dist/src/core/query/query-templates.js +321 -0
  289. package/dist/src/core/query/query-templates.js.map +7 -0
  290. package/dist/src/core/retrieval/context-retriever.js +479 -0
  291. package/dist/src/core/retrieval/context-retriever.js.map +7 -0
  292. package/dist/src/core/retrieval/index.js +8 -0
  293. package/dist/src/core/retrieval/index.js.map +7 -0
  294. package/dist/src/core/retrieval/llm-context-retrieval.js +613 -0
  295. package/dist/src/core/retrieval/llm-context-retrieval.js.map +7 -0
  296. package/dist/src/core/retrieval/llm-provider.js +151 -0
  297. package/dist/src/core/retrieval/llm-provider.js.map +7 -0
  298. package/dist/src/core/retrieval/retrieval-audit.js +236 -0
  299. package/dist/src/core/retrieval/retrieval-audit.js.map +7 -0
  300. package/dist/src/core/retrieval/summary-generator.js +589 -0
  301. package/dist/src/core/retrieval/summary-generator.js.map +7 -0
  302. package/dist/src/core/retrieval/types.js +21 -0
  303. package/dist/src/core/retrieval/types.js.map +7 -0
  304. package/dist/src/core/security/index.js +35 -0
  305. package/dist/src/core/security/index.js.map +7 -0
  306. package/dist/src/core/security/input-sanitizer.js +321 -0
  307. package/dist/src/core/security/input-sanitizer.js.map +7 -0
  308. package/dist/src/core/session/clear-survival.js +465 -0
  309. package/dist/src/core/session/clear-survival.js.map +7 -0
  310. package/dist/src/core/session/enhanced-handoff.js +792 -0
  311. package/dist/src/core/session/enhanced-handoff.js.map +7 -0
  312. package/dist/src/core/session/handoff-generator.js +343 -0
  313. package/dist/src/core/session/handoff-generator.js.map +7 -0
  314. package/dist/src/core/session/index.js +15 -0
  315. package/dist/src/core/session/index.js.map +7 -0
  316. package/dist/src/core/session/session-manager.js +347 -0
  317. package/dist/src/core/session/session-manager.js.map +7 -0
  318. package/dist/src/core/skills/index.js +7 -0
  319. package/dist/src/core/skills/index.js.map +7 -0
  320. package/dist/src/core/skills/skill-storage.js +764 -0
  321. package/dist/src/core/skills/skill-storage.js.map +7 -0
  322. package/dist/src/core/skills/types.js +193 -0
  323. package/dist/src/core/skills/types.js.map +7 -0
  324. package/dist/src/core/storage/chromadb-adapter.js +354 -0
  325. package/dist/src/core/storage/chromadb-adapter.js.map +7 -0
  326. package/dist/src/core/storage/infinite-storage.js +510 -0
  327. package/dist/src/core/storage/infinite-storage.js.map +7 -0
  328. package/dist/src/core/storage/remote-storage.js +489 -0
  329. package/dist/src/core/storage/remote-storage.js.map +7 -0
  330. package/dist/src/core/storage/two-tier-storage.js +766 -0
  331. package/dist/src/core/storage/two-tier-storage.js.map +7 -0
  332. package/dist/src/core/trace/cli-trace-wrapper.js +132 -0
  333. package/dist/src/core/trace/cli-trace-wrapper.js.map +7 -0
  334. package/dist/src/core/trace/db-trace-wrapper.js +247 -0
  335. package/dist/src/core/trace/db-trace-wrapper.js.map +7 -0
  336. package/dist/src/core/trace/debug-trace.js +417 -0
  337. package/dist/src/core/trace/debug-trace.js.map +7 -0
  338. package/dist/src/core/trace/index.js +109 -0
  339. package/dist/src/core/trace/index.js.map +7 -0
  340. package/dist/src/core/trace/linear-api-wrapper.js +178 -0
  341. package/dist/src/core/trace/linear-api-wrapper.js.map +7 -0
  342. package/dist/src/core/trace/trace-detector.js +528 -0
  343. package/dist/src/core/trace/trace-detector.js.map +7 -0
  344. package/dist/src/core/trace/trace-store.js +345 -0
  345. package/dist/src/core/trace/trace-store.js.map +7 -0
  346. package/dist/src/core/trace/types.js +77 -0
  347. package/dist/src/core/trace/types.js.map +7 -0
  348. package/dist/src/core/types.js +5 -0
  349. package/dist/src/core/types.js.map +7 -0
  350. package/dist/src/core/utils/async-mutex.js +114 -0
  351. package/dist/src/core/utils/async-mutex.js.map +7 -0
  352. package/dist/src/core/utils/compression.js +83 -0
  353. package/dist/src/core/utils/compression.js.map +7 -0
  354. package/dist/src/core/utils/update-checker.js +218 -0
  355. package/dist/src/core/utils/update-checker.js.map +7 -0
  356. package/dist/src/core/worktree/worktree-manager.js +465 -0
  357. package/dist/src/core/worktree/worktree-manager.js.map +7 -0
  358. package/dist/src/daemon/daemon-config.js +149 -0
  359. package/dist/src/daemon/daemon-config.js.map +7 -0
  360. package/dist/src/daemon/services/context-service.js +122 -0
  361. package/dist/src/daemon/services/context-service.js.map +7 -0
  362. package/dist/src/daemon/services/linear-service.js +136 -0
  363. package/dist/src/daemon/services/linear-service.js.map +7 -0
  364. package/dist/src/daemon/session-daemon.js +312 -0
  365. package/dist/src/daemon/session-daemon.js.map +7 -0
  366. package/dist/src/daemon/unified-daemon.js +276 -0
  367. package/dist/src/daemon/unified-daemon.js.map +7 -0
  368. package/dist/src/features/analytics/api/analytics-api.js +287 -0
  369. package/dist/src/features/analytics/api/analytics-api.js.map +7 -0
  370. package/dist/src/features/analytics/core/analytics-service.js +282 -0
  371. package/dist/src/features/analytics/core/analytics-service.js.map +7 -0
  372. package/dist/src/features/analytics/index.js +18 -0
  373. package/dist/src/features/analytics/index.js.map +7 -0
  374. package/dist/src/features/analytics/queries/metrics-queries.js +277 -0
  375. package/dist/src/features/analytics/queries/metrics-queries.js.map +7 -0
  376. package/dist/src/features/analytics/types/metrics.js +5 -0
  377. package/dist/src/features/analytics/types/metrics.js.map +7 -0
  378. package/dist/src/features/browser/browser-mcp.js +492 -0
  379. package/dist/src/features/browser/browser-mcp.js.map +7 -0
  380. package/dist/src/features/sweep/index.js +20 -0
  381. package/dist/src/features/sweep/index.js.map +7 -0
  382. package/dist/src/features/sweep/prediction-client.js +155 -0
  383. package/dist/src/features/sweep/prediction-client.js.map +7 -0
  384. package/dist/src/features/sweep/prompt-builder.js +85 -0
  385. package/dist/src/features/sweep/prompt-builder.js.map +7 -0
  386. package/dist/src/features/sweep/pty-wrapper.js +171 -0
  387. package/dist/src/features/sweep/pty-wrapper.js.map +7 -0
  388. package/dist/src/features/sweep/state-watcher.js +87 -0
  389. package/dist/src/features/sweep/state-watcher.js.map +7 -0
  390. package/dist/src/features/sweep/status-bar.js +88 -0
  391. package/dist/src/features/sweep/status-bar.js.map +7 -0
  392. package/dist/src/features/sweep/sweep-server-manager.js +226 -0
  393. package/dist/src/features/sweep/sweep-server-manager.js.map +7 -0
  394. package/dist/src/features/sweep/tab-interceptor.js +38 -0
  395. package/dist/src/features/sweep/tab-interceptor.js.map +7 -0
  396. package/dist/src/features/sweep/types.js +18 -0
  397. package/dist/src/features/sweep/types.js.map +7 -0
  398. package/dist/src/features/tasks/linear-task-manager.js +487 -0
  399. package/dist/src/features/tasks/linear-task-manager.js.map +7 -0
  400. package/dist/src/features/tasks/task-aware-context.js +410 -0
  401. package/dist/src/features/tasks/task-aware-context.js.map +7 -0
  402. package/dist/src/features/tui/simple-monitor.js +116 -0
  403. package/dist/src/features/tui/simple-monitor.js.map +7 -0
  404. package/dist/src/features/tui/swarm-monitor.js +648 -0
  405. package/dist/src/features/tui/swarm-monitor.js.map +7 -0
  406. package/dist/src/features/web/client/stores/task-store.js +26 -0
  407. package/dist/src/features/web/client/stores/task-store.js.map +7 -0
  408. package/dist/src/features/web/server/index.js +194 -0
  409. package/dist/src/features/web/server/index.js.map +7 -0
  410. package/dist/src/hooks/auto-background.js +151 -0
  411. package/dist/src/hooks/auto-background.js.map +7 -0
  412. package/dist/src/hooks/claude-code-whatsapp-hook.js +197 -0
  413. package/dist/src/hooks/claude-code-whatsapp-hook.js.map +7 -0
  414. package/dist/src/hooks/config.js +150 -0
  415. package/dist/src/hooks/config.js.map +7 -0
  416. package/dist/src/hooks/daemon.js +364 -0
  417. package/dist/src/hooks/daemon.js.map +7 -0
  418. package/dist/src/hooks/events.js +58 -0
  419. package/dist/src/hooks/events.js.map +7 -0
  420. package/dist/src/hooks/index.js +12 -0
  421. package/dist/src/hooks/index.js.map +7 -0
  422. package/dist/src/hooks/linear-task-picker.js +186 -0
  423. package/dist/src/hooks/linear-task-picker.js.map +7 -0
  424. package/dist/src/hooks/schemas.js +197 -0
  425. package/dist/src/hooks/schemas.js.map +7 -0
  426. package/dist/src/hooks/secure-fs.js +49 -0
  427. package/dist/src/hooks/secure-fs.js.map +7 -0
  428. package/dist/src/hooks/security-logger.js +155 -0
  429. package/dist/src/hooks/security-logger.js.map +7 -0
  430. package/dist/src/hooks/session-summary.js +222 -0
  431. package/dist/src/hooks/session-summary.js.map +7 -0
  432. package/dist/src/hooks/sms-action-runner.js +371 -0
  433. package/dist/src/hooks/sms-action-runner.js.map +7 -0
  434. package/dist/src/hooks/sms-notify.js +506 -0
  435. package/dist/src/hooks/sms-notify.js.map +7 -0
  436. package/dist/src/hooks/sms-watcher.js +93 -0
  437. package/dist/src/hooks/sms-watcher.js.map +7 -0
  438. package/dist/src/hooks/sms-webhook.js +555 -0
  439. package/dist/src/hooks/sms-webhook.js.map +7 -0
  440. package/dist/src/hooks/whatsapp-commands.js +479 -0
  441. package/dist/src/hooks/whatsapp-commands.js.map +7 -0
  442. package/dist/src/hooks/whatsapp-scheduler.js +317 -0
  443. package/dist/src/hooks/whatsapp-scheduler.js.map +7 -0
  444. package/dist/src/hooks/whatsapp-sync.js +409 -0
  445. package/dist/src/hooks/whatsapp-sync.js.map +7 -0
  446. package/dist/src/index.js +25 -0
  447. package/dist/src/index.js.map +7 -0
  448. package/dist/src/integrations/anthropic/client.js +263 -0
  449. package/dist/src/integrations/anthropic/client.js.map +7 -0
  450. package/dist/src/integrations/claude-code/agent-bridge.js +768 -0
  451. package/dist/src/integrations/claude-code/agent-bridge.js.map +7 -0
  452. package/dist/src/integrations/claude-code/enhanced-pre-clear-hooks.js +459 -0
  453. package/dist/src/integrations/claude-code/enhanced-pre-clear-hooks.js.map +7 -0
  454. package/dist/src/integrations/claude-code/lifecycle-hooks.js +254 -0
  455. package/dist/src/integrations/claude-code/lifecycle-hooks.js.map +7 -0
  456. package/dist/src/integrations/claude-code/post-task-hooks.js +545 -0
  457. package/dist/src/integrations/claude-code/post-task-hooks.js.map +7 -0
  458. package/dist/src/integrations/claude-code/subagent-client-stub.js +20 -0
  459. package/dist/src/integrations/claude-code/subagent-client-stub.js.map +7 -0
  460. package/dist/src/integrations/claude-code/subagent-client.js +511 -0
  461. package/dist/src/integrations/claude-code/subagent-client.js.map +7 -0
  462. package/dist/src/integrations/claude-code/task-coordinator.js +360 -0
  463. package/dist/src/integrations/claude-code/task-coordinator.js.map +7 -0
  464. package/dist/src/integrations/linear/auth.js +337 -0
  465. package/dist/src/integrations/linear/auth.js.map +7 -0
  466. package/dist/src/integrations/linear/auto-sync.js +258 -0
  467. package/dist/src/integrations/linear/auto-sync.js.map +7 -0
  468. package/dist/src/integrations/linear/client.js +634 -0
  469. package/dist/src/integrations/linear/client.js.map +7 -0
  470. package/dist/src/integrations/linear/config.js +130 -0
  471. package/dist/src/integrations/linear/config.js.map +7 -0
  472. package/dist/src/integrations/linear/migration.js +361 -0
  473. package/dist/src/integrations/linear/migration.js.map +7 -0
  474. package/dist/src/integrations/linear/oauth-server.js +454 -0
  475. package/dist/src/integrations/linear/oauth-server.js.map +7 -0
  476. package/dist/src/integrations/linear/rest-client.js +213 -0
  477. package/dist/src/integrations/linear/rest-client.js.map +7 -0
  478. package/dist/src/integrations/linear/sync-manager.js +236 -0
  479. package/dist/src/integrations/linear/sync-manager.js.map +7 -0
  480. package/dist/src/integrations/linear/sync-service.js +231 -0
  481. package/dist/src/integrations/linear/sync-service.js.map +7 -0
  482. package/dist/src/integrations/linear/sync.js +782 -0
  483. package/dist/src/integrations/linear/sync.js.map +7 -0
  484. package/dist/src/integrations/linear/types.js +5 -0
  485. package/dist/src/integrations/linear/types.js.map +7 -0
  486. package/dist/src/integrations/linear/unified-sync.js +589 -0
  487. package/dist/src/integrations/linear/unified-sync.js.map +7 -0
  488. package/dist/src/integrations/linear/webhook-handler.js +219 -0
  489. package/dist/src/integrations/linear/webhook-handler.js.map +7 -0
  490. package/dist/src/integrations/linear/webhook-server.js +218 -0
  491. package/dist/src/integrations/linear/webhook-server.js.map +7 -0
  492. package/dist/src/integrations/linear/webhook.js +291 -0
  493. package/dist/src/integrations/linear/webhook.js.map +7 -0
  494. package/dist/src/integrations/mcp/handlers/code-execution-handlers.js +266 -0
  495. package/dist/src/integrations/mcp/handlers/code-execution-handlers.js.map +7 -0
  496. package/dist/src/integrations/mcp/handlers/context-handlers.js +257 -0
  497. package/dist/src/integrations/mcp/handlers/context-handlers.js.map +7 -0
  498. package/dist/src/integrations/mcp/handlers/discovery-handlers.js +497 -0
  499. package/dist/src/integrations/mcp/handlers/discovery-handlers.js.map +7 -0
  500. package/dist/src/integrations/mcp/handlers/index.js +166 -0
  501. package/dist/src/integrations/mcp/handlers/index.js.map +7 -0
  502. package/dist/src/integrations/mcp/handlers/linear-handlers.js +247 -0
  503. package/dist/src/integrations/mcp/handlers/linear-handlers.js.map +7 -0
  504. package/dist/src/integrations/mcp/handlers/skill-handlers.js +529 -0
  505. package/dist/src/integrations/mcp/handlers/skill-handlers.js.map +7 -0
  506. package/dist/src/integrations/mcp/handlers/task-handlers.js +239 -0
  507. package/dist/src/integrations/mcp/handlers/task-handlers.js.map +7 -0
  508. package/dist/src/integrations/mcp/handlers/trace-handlers.js +308 -0
  509. package/dist/src/integrations/mcp/handlers/trace-handlers.js.map +7 -0
  510. package/dist/src/integrations/mcp/index.js +23 -0
  511. package/dist/src/integrations/mcp/index.js.map +7 -0
  512. package/dist/src/integrations/mcp/middleware/tool-scoring.js +356 -0
  513. package/dist/src/integrations/mcp/middleware/tool-scoring.js.map +7 -0
  514. package/dist/src/integrations/mcp/refactored-server.js +374 -0
  515. package/dist/src/integrations/mcp/refactored-server.js.map +7 -0
  516. package/dist/src/integrations/mcp/remote-server.js +682 -0
  517. package/dist/src/integrations/mcp/remote-server.js.map +7 -0
  518. package/dist/src/integrations/mcp/schemas.js +147 -0
  519. package/dist/src/integrations/mcp/schemas.js.map +7 -0
  520. package/dist/src/integrations/mcp/server.js +1975 -0
  521. package/dist/src/integrations/mcp/server.js.map +7 -0
  522. package/dist/src/integrations/mcp/tool-definitions-code.js +125 -0
  523. package/dist/src/integrations/mcp/tool-definitions-code.js.map +7 -0
  524. package/dist/src/integrations/mcp/tool-definitions.js +702 -0
  525. package/dist/src/integrations/mcp/tool-definitions.js.map +7 -0
  526. package/dist/src/integrations/ralph/bridge/ralph-stackmemory-bridge.js +860 -0
  527. package/dist/src/integrations/ralph/bridge/ralph-stackmemory-bridge.js.map +7 -0
  528. package/dist/src/integrations/ralph/context/context-budget-manager.js +301 -0
  529. package/dist/src/integrations/ralph/context/context-budget-manager.js.map +7 -0
  530. package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +360 -0
  531. package/dist/src/integrations/ralph/context/stackmemory-context-loader.js.map +7 -0
  532. package/dist/src/integrations/ralph/coordination/enhanced-coordination.js +410 -0
  533. package/dist/src/integrations/ralph/coordination/enhanced-coordination.js.map +7 -0
  534. package/dist/src/integrations/ralph/index.js +18 -0
  535. package/dist/src/integrations/ralph/index.js.map +7 -0
  536. package/dist/src/integrations/ralph/learning/pattern-learner.js +401 -0
  537. package/dist/src/integrations/ralph/learning/pattern-learner.js.map +7 -0
  538. package/dist/src/integrations/ralph/lifecycle/iteration-lifecycle.js +448 -0
  539. package/dist/src/integrations/ralph/lifecycle/iteration-lifecycle.js.map +7 -0
  540. package/dist/src/integrations/ralph/monitoring/swarm-dashboard.js +294 -0
  541. package/dist/src/integrations/ralph/monitoring/swarm-dashboard.js.map +7 -0
  542. package/dist/src/integrations/ralph/monitoring/swarm-registry.js +108 -0
  543. package/dist/src/integrations/ralph/monitoring/swarm-registry.js.map +7 -0
  544. package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js +463 -0
  545. package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js.map +7 -0
  546. package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js +400 -0
  547. package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js.map +7 -0
  548. package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js +473 -0
  549. package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js.map +7 -0
  550. package/dist/src/integrations/ralph/patterns/oracle-worker-pattern.js +388 -0
  551. package/dist/src/integrations/ralph/patterns/oracle-worker-pattern.js.map +7 -0
  552. package/dist/src/integrations/ralph/performance/performance-optimizer.js +358 -0
  553. package/dist/src/integrations/ralph/performance/performance-optimizer.js.map +7 -0
  554. package/dist/src/integrations/ralph/recovery/crash-recovery.js +462 -0
  555. package/dist/src/integrations/ralph/recovery/crash-recovery.js.map +7 -0
  556. package/dist/src/integrations/ralph/state/state-reconciler.js +404 -0
  557. package/dist/src/integrations/ralph/state/state-reconciler.js.map +7 -0
  558. package/dist/src/integrations/ralph/swarm/git-workflow-manager.js +428 -0
  559. package/dist/src/integrations/ralph/swarm/git-workflow-manager.js.map +7 -0
  560. package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +996 -0
  561. package/dist/src/integrations/ralph/swarm/swarm-coordinator.js.map +7 -0
  562. package/dist/src/integrations/ralph/types.js +5 -0
  563. package/dist/src/integrations/ralph/types.js.map +7 -0
  564. package/dist/src/integrations/ralph/visualization/ralph-debugger.js +585 -0
  565. package/dist/src/integrations/ralph/visualization/ralph-debugger.js.map +7 -0
  566. package/dist/src/mcp/stackmemory-mcp-server.js +554 -0
  567. package/dist/src/mcp/stackmemory-mcp-server.js.map +7 -0
  568. package/dist/src/middleware/exponential-rate-limiter.js +289 -0
  569. package/dist/src/middleware/exponential-rate-limiter.js.map +7 -0
  570. package/dist/src/models/user.model.js +358 -0
  571. package/dist/src/models/user.model.js.map +7 -0
  572. package/dist/src/servers/production/auth-middleware.js +528 -0
  573. package/dist/src/servers/production/auth-middleware.js.map +7 -0
  574. package/dist/src/services/config-service.js +65 -0
  575. package/dist/src/services/config-service.js.map +7 -0
  576. package/dist/src/services/context-service.js +194 -0
  577. package/dist/src/services/context-service.js.map +7 -0
  578. package/dist/src/skills/api-discovery.js +354 -0
  579. package/dist/src/skills/api-discovery.js.map +7 -0
  580. package/dist/src/skills/api-skill.js +475 -0
  581. package/dist/src/skills/api-skill.js.map +7 -0
  582. package/dist/src/skills/claude-skills.js +1061 -0
  583. package/dist/src/skills/claude-skills.js.map +7 -0
  584. package/dist/src/skills/dashboard-launcher.js +216 -0
  585. package/dist/src/skills/dashboard-launcher.js.map +7 -0
  586. package/dist/src/skills/recursive-agent-orchestrator.js +575 -0
  587. package/dist/src/skills/recursive-agent-orchestrator.js.map +7 -0
  588. package/dist/src/skills/repo-ingestion-skill.js +609 -0
  589. package/dist/src/skills/repo-ingestion-skill.js.map +7 -0
  590. package/dist/src/skills/unified-rlm-orchestrator.js +404 -0
  591. package/dist/src/skills/unified-rlm-orchestrator.js.map +7 -0
  592. package/dist/src/types/task.js +5 -0
  593. package/dist/src/types/task.js.map +7 -0
  594. package/dist/src/utils/env.js +50 -0
  595. package/dist/src/utils/env.js.map +7 -0
  596. package/dist/src/utils/formatting.js +62 -0
  597. package/dist/src/utils/formatting.js.map +7 -0
  598. package/dist/src/utils/process-cleanup.js +136 -0
  599. package/dist/src/utils/process-cleanup.js.map +7 -0
  600. package/package.json +4 -3
  601. package/scripts/create-cleanup-issues.js +302 -0
  602. package/scripts/demos/browser-test.ts +39 -0
  603. package/scripts/demos/ralph-integration-demo.ts +244 -0
  604. package/scripts/demos/trace-demo.ts +214 -0
  605. package/scripts/demos/trace-detector.demo.ts +171 -0
  606. package/scripts/demos/trace-test.ts +67 -0
  607. package/scripts/initialize.ts +16 -7
  608. package/scripts/install.sh +14 -62
  609. package/scripts/status.ts +111 -46
  610. package/scripts/test-claude-config.sh +123 -0
  611. package/scripts/validate-claude-config.sh +155 -0
@@ -0,0 +1,337 @@
1
+ import { fileURLToPath as __fileURLToPath } from 'url';
2
+ import { dirname as __pathDirname } from 'path';
3
+ const __filename = __fileURLToPath(import.meta.url);
4
+ const __dirname = __pathDirname(__filename);
5
+ import { createHash, randomBytes } from "crypto";
6
+ import { readFileSync, writeFileSync, existsSync } from "fs";
7
+ import { join } from "path";
8
+ import { logger } from "../../core/monitoring/logger.js";
9
+ import { IntegrationError, ErrorCode } from "../../core/errors/index.js";
10
+ class LinearAuthManager {
11
+ configPath;
12
+ tokensPath;
13
+ config;
14
+ constructor(projectRoot) {
15
+ const configDir = join(projectRoot, ".stackmemory");
16
+ this.configPath = join(configDir, "linear-config.json");
17
+ this.tokensPath = join(configDir, "linear-tokens.json");
18
+ }
19
+ /**
20
+ * Check if Linear integration is configured
21
+ */
22
+ isConfigured() {
23
+ return existsSync(this.configPath) && existsSync(this.tokensPath);
24
+ }
25
+ /**
26
+ * Save OAuth application configuration
27
+ */
28
+ saveConfig(config) {
29
+ writeFileSync(this.configPath, JSON.stringify(config, null, 2));
30
+ this.config = config;
31
+ logger.info("Linear OAuth configuration saved");
32
+ }
33
+ /**
34
+ * Load OAuth configuration
35
+ */
36
+ loadConfig() {
37
+ if (!existsSync(this.configPath)) {
38
+ return null;
39
+ }
40
+ try {
41
+ const configData = readFileSync(this.configPath, "utf8");
42
+ this.config = JSON.parse(configData);
43
+ return this.config;
44
+ } catch (error) {
45
+ logger.error("Failed to load Linear configuration:", error);
46
+ return null;
47
+ }
48
+ }
49
+ /**
50
+ * Generate OAuth authorization URL with PKCE
51
+ */
52
+ generateAuthUrl(state) {
53
+ if (!this.config) {
54
+ throw new IntegrationError(
55
+ "Linear OAuth configuration not loaded",
56
+ ErrorCode.LINEAR_AUTH_FAILED
57
+ );
58
+ }
59
+ const codeVerifier = randomBytes(32).toString("base64url");
60
+ const codeChallenge = createHash("sha256").update(codeVerifier).digest("base64url");
61
+ const params = new URLSearchParams({
62
+ client_id: this.config.clientId,
63
+ redirect_uri: this.config.redirectUri,
64
+ response_type: "code",
65
+ scope: this.config.scopes.join(" "),
66
+ code_challenge: codeChallenge,
67
+ code_challenge_method: "S256",
68
+ actor: "app"
69
+ // Enable actor authorization for service accounts
70
+ });
71
+ if (state) {
72
+ params.set("state", state);
73
+ }
74
+ const authUrl = `https://linear.app/oauth/authorize?${params.toString()}`;
75
+ return { url: authUrl, codeVerifier };
76
+ }
77
+ /**
78
+ * Exchange authorization code for access token
79
+ */
80
+ async exchangeCodeForToken(authCode, codeVerifier) {
81
+ if (!this.config) {
82
+ throw new IntegrationError(
83
+ "Linear OAuth configuration not loaded",
84
+ ErrorCode.LINEAR_AUTH_FAILED
85
+ );
86
+ }
87
+ const tokenUrl = "https://api.linear.app/oauth/token";
88
+ const body = new URLSearchParams({
89
+ grant_type: "authorization_code",
90
+ client_id: this.config.clientId,
91
+ client_secret: this.config.clientSecret,
92
+ redirect_uri: this.config.redirectUri,
93
+ code: authCode,
94
+ code_verifier: codeVerifier
95
+ });
96
+ const response = await fetch(tokenUrl, {
97
+ method: "POST",
98
+ headers: {
99
+ "Content-Type": "application/x-www-form-urlencoded",
100
+ Accept: "application/json"
101
+ },
102
+ body: body.toString()
103
+ });
104
+ if (!response.ok) {
105
+ const errorText = await response.text();
106
+ throw new IntegrationError(
107
+ `Token exchange failed: ${response.status}`,
108
+ ErrorCode.LINEAR_AUTH_FAILED,
109
+ { status: response.status, body: errorText }
110
+ );
111
+ }
112
+ const result = await response.json();
113
+ const expiresAt = Date.now() + result.expiresIn * 1e3;
114
+ const tokens = {
115
+ accessToken: result.accessToken,
116
+ refreshToken: result.refreshToken,
117
+ expiresAt,
118
+ scope: result.scope.split(" ")
119
+ };
120
+ this.saveTokens(tokens);
121
+ return tokens;
122
+ }
123
+ /**
124
+ * Refresh access token using refresh token
125
+ */
126
+ async refreshAccessToken() {
127
+ if (!this.config) {
128
+ throw new IntegrationError(
129
+ "Linear OAuth configuration not loaded",
130
+ ErrorCode.LINEAR_AUTH_FAILED
131
+ );
132
+ }
133
+ const currentTokens = this.loadTokens();
134
+ if (!currentTokens?.refreshToken) {
135
+ throw new IntegrationError(
136
+ "No refresh token available",
137
+ ErrorCode.LINEAR_AUTH_FAILED
138
+ );
139
+ }
140
+ const tokenUrl = "https://api.linear.app/oauth/token";
141
+ const body = new URLSearchParams({
142
+ grant_type: "refresh_token",
143
+ client_id: this.config.clientId,
144
+ client_secret: this.config.clientSecret,
145
+ refresh_token: currentTokens.refreshToken
146
+ });
147
+ const response = await fetch(tokenUrl, {
148
+ method: "POST",
149
+ headers: {
150
+ "Content-Type": "application/x-www-form-urlencoded",
151
+ Accept: "application/json"
152
+ },
153
+ body: body.toString()
154
+ });
155
+ if (!response.ok) {
156
+ const errorText = await response.text();
157
+ throw new IntegrationError(
158
+ `Token refresh failed: ${response.status}`,
159
+ ErrorCode.LINEAR_AUTH_FAILED,
160
+ { status: response.status, body: errorText }
161
+ );
162
+ }
163
+ const result = await response.json();
164
+ const tokens = {
165
+ accessToken: result.accessToken,
166
+ refreshToken: result.refreshToken || currentTokens.refreshToken,
167
+ expiresAt: Date.now() + result.expiresIn * 1e3,
168
+ scope: result.scope.split(" ")
169
+ };
170
+ this.saveTokens(tokens);
171
+ return tokens;
172
+ }
173
+ /**
174
+ * Get valid access token (refresh if needed)
175
+ */
176
+ async getValidToken() {
177
+ const tokens = this.loadTokens();
178
+ if (!tokens) {
179
+ throw new IntegrationError(
180
+ "No Linear tokens found. Please complete OAuth setup.",
181
+ ErrorCode.LINEAR_AUTH_FAILED
182
+ );
183
+ }
184
+ const fiveMinutes = 5 * 60 * 1e3;
185
+ if (tokens.expiresAt - Date.now() < fiveMinutes) {
186
+ logger.info("Linear token expiring soon, refreshing...");
187
+ const newTokens = await this.refreshAccessToken();
188
+ return newTokens.accessToken;
189
+ }
190
+ return tokens.accessToken;
191
+ }
192
+ /**
193
+ * Save tokens to file
194
+ */
195
+ saveTokens(tokens) {
196
+ writeFileSync(this.tokensPath, JSON.stringify(tokens, null, 2));
197
+ logger.info("Linear tokens saved");
198
+ }
199
+ /**
200
+ * Load tokens from file
201
+ */
202
+ loadTokens() {
203
+ if (!existsSync(this.tokensPath)) {
204
+ return null;
205
+ }
206
+ try {
207
+ const tokensData = readFileSync(this.tokensPath, "utf8");
208
+ return JSON.parse(tokensData);
209
+ } catch (error) {
210
+ logger.error("Failed to load Linear tokens:", error);
211
+ return null;
212
+ }
213
+ }
214
+ /**
215
+ * Clear stored tokens and config
216
+ */
217
+ clearAuth() {
218
+ if (existsSync(this.tokensPath)) {
219
+ writeFileSync(this.tokensPath, "");
220
+ }
221
+ if (existsSync(this.configPath)) {
222
+ writeFileSync(this.configPath, "");
223
+ }
224
+ logger.info("Linear authentication cleared");
225
+ }
226
+ }
227
+ const DEFAULT_LINEAR_SCOPES = [
228
+ "read",
229
+ // Read issues, projects, teams
230
+ "write",
231
+ // Create and update issues
232
+ "admin"
233
+ // Manage team settings and workflows
234
+ ];
235
+ class LinearOAuthSetup {
236
+ authManager;
237
+ constructor(projectRoot) {
238
+ this.authManager = new LinearAuthManager(projectRoot);
239
+ }
240
+ /**
241
+ * Interactive setup for Linear OAuth
242
+ */
243
+ async setupInteractive() {
244
+ const config = {
245
+ clientId: process.env["LINEAR_CLIENT_ID"] || "",
246
+ clientSecret: process.env["LINEAR_CLIENT_SECRET"] || "",
247
+ redirectUri: process.env["LINEAR_REDIRECT_URI"] || "http://localhost:3456/auth/linear/callback",
248
+ scopes: DEFAULT_LINEAR_SCOPES
249
+ };
250
+ if (!config.clientId || !config.clientSecret) {
251
+ return {
252
+ authUrl: "",
253
+ instructions: [
254
+ "1. Create a Linear OAuth application at https://linear.app/settings/api",
255
+ "2. Set redirect URI to: http://localhost:3456/auth/linear/callback",
256
+ "3. Copy your Client ID and Client Secret",
257
+ "4. Set environment variables:",
258
+ ' export LINEAR_CLIENT_ID="your_client_id"',
259
+ ' export LINEAR_CLIENT_SECRET="your_client_secret"',
260
+ "5. Re-run this setup command"
261
+ ]
262
+ };
263
+ }
264
+ this.authManager.saveConfig(config);
265
+ const { url, codeVerifier } = this.authManager.generateAuthUrl();
266
+ process.env["_LINEAR_CODE_VERIFIER"] = codeVerifier;
267
+ return {
268
+ authUrl: url,
269
+ instructions: [
270
+ "1. Open this URL in your browser:",
271
+ url,
272
+ "",
273
+ "2. Approve the StackMemory integration",
274
+ "3. Copy the authorization code from the redirect URL",
275
+ "4. Run: stackmemory linear authorize <code>"
276
+ ]
277
+ };
278
+ }
279
+ /**
280
+ * Complete OAuth flow with authorization code
281
+ */
282
+ async completeAuth(authCode) {
283
+ try {
284
+ const codeVerifier = process.env["_LINEAR_CODE_VERIFIER"];
285
+ if (!codeVerifier) {
286
+ throw new IntegrationError(
287
+ "Code verifier not found. Please restart the setup process.",
288
+ ErrorCode.LINEAR_AUTH_FAILED
289
+ );
290
+ }
291
+ await this.authManager.exchangeCodeForToken(authCode, codeVerifier);
292
+ delete process.env["_LINEAR_CODE_VERIFIER"];
293
+ logger.info("Linear OAuth setup completed successfully!");
294
+ return true;
295
+ } catch (error) {
296
+ logger.error("Failed to complete Linear OAuth setup:", error);
297
+ return false;
298
+ }
299
+ }
300
+ /**
301
+ * Test the Linear connection
302
+ */
303
+ async testConnection() {
304
+ try {
305
+ const token = await this.authManager.getValidToken();
306
+ const response = await fetch("https://api.linear.app/graphql", {
307
+ method: "POST",
308
+ headers: {
309
+ Authorization: `Bearer ${token}`,
310
+ "Content-Type": "application/json"
311
+ },
312
+ body: JSON.stringify({
313
+ query: "query { viewer { id name email } }"
314
+ })
315
+ });
316
+ if (response.ok) {
317
+ const result = await response.json();
318
+ if (result.data?.viewer) {
319
+ logger.info(
320
+ `Connected to Linear as: ${result.data.viewer.name} (${result.data.viewer.email})`
321
+ );
322
+ return true;
323
+ }
324
+ }
325
+ return false;
326
+ } catch (error) {
327
+ logger.error("Linear connection test failed:", error);
328
+ return false;
329
+ }
330
+ }
331
+ }
332
+ export {
333
+ DEFAULT_LINEAR_SCOPES,
334
+ LinearAuthManager,
335
+ LinearOAuthSetup
336
+ };
337
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/integrations/linear/auth.ts"],
4
+ "sourcesContent": ["/**\n * Linear OAuth Authentication Setup\n * Handles initial OAuth flow and token management for Linear integration\n */\n\nimport { createHash, randomBytes } from 'crypto';\nimport { readFileSync, writeFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { logger } from '../../core/monitoring/logger.js';\nimport { IntegrationError, ErrorCode } from '../../core/errors/index.js';\n\nexport interface LinearAuthConfig {\n clientId: string;\n clientSecret: string;\n redirectUri: string;\n scopes: string[];\n}\n\nexport interface LinearTokens {\n accessToken: string;\n refreshToken?: string;\n expiresAt: number; // Unix timestamp\n scope: string[];\n}\n\nexport interface LinearAuthResult {\n accessToken: string;\n refreshToken?: string;\n expiresIn: number;\n scope: string;\n tokenType: string;\n}\n\nexport class LinearAuthManager {\n private configPath: string;\n private tokensPath: string;\n private config?: LinearAuthConfig;\n\n constructor(projectRoot: string) {\n const configDir = join(projectRoot, '.stackmemory');\n this.configPath = join(configDir, 'linear-config.json');\n this.tokensPath = join(configDir, 'linear-tokens.json');\n }\n\n /**\n * Check if Linear integration is configured\n */\n isConfigured(): boolean {\n return existsSync(this.configPath) && existsSync(this.tokensPath);\n }\n\n /**\n * Save OAuth application configuration\n */\n saveConfig(config: LinearAuthConfig): void {\n writeFileSync(this.configPath, JSON.stringify(config, null, 2));\n this.config = config;\n logger.info('Linear OAuth configuration saved');\n }\n\n /**\n * Load OAuth configuration\n */\n loadConfig(): LinearAuthConfig | null {\n if (!existsSync(this.configPath)) {\n return null;\n }\n\n try {\n const configData = readFileSync(this.configPath, 'utf8');\n this.config = JSON.parse(configData);\n return this.config!;\n } catch (error: unknown) {\n logger.error('Failed to load Linear configuration:', error as Error);\n return null;\n }\n }\n\n /**\n * Generate OAuth authorization URL with PKCE\n */\n generateAuthUrl(state?: string): { url: string; codeVerifier: string } {\n if (!this.config) {\n throw new IntegrationError(\n 'Linear OAuth configuration not loaded',\n ErrorCode.LINEAR_AUTH_FAILED\n );\n }\n\n // Generate PKCE parameters\n const codeVerifier = randomBytes(32).toString('base64url');\n const codeChallenge = createHash('sha256')\n .update(codeVerifier)\n .digest('base64url');\n\n const params = new URLSearchParams({\n client_id: this.config.clientId,\n redirect_uri: this.config.redirectUri,\n response_type: 'code',\n scope: this.config.scopes.join(' '),\n code_challenge: codeChallenge,\n code_challenge_method: 'S256',\n actor: 'app', // Enable actor authorization for service accounts\n });\n\n if (state) {\n params.set('state', state);\n }\n\n const authUrl = `https://linear.app/oauth/authorize?${params.toString()}`;\n\n return { url: authUrl, codeVerifier };\n }\n\n /**\n * Exchange authorization code for access token\n */\n async exchangeCodeForToken(\n authCode: string,\n codeVerifier: string\n ): Promise<LinearTokens> {\n if (!this.config) {\n throw new IntegrationError(\n 'Linear OAuth configuration not loaded',\n ErrorCode.LINEAR_AUTH_FAILED\n );\n }\n\n const tokenUrl = 'https://api.linear.app/oauth/token';\n\n const body = new URLSearchParams({\n grant_type: 'authorization_code',\n client_id: this.config.clientId,\n client_secret: this.config.clientSecret,\n redirect_uri: this.config.redirectUri,\n code: authCode,\n code_verifier: codeVerifier,\n });\n\n const response = await fetch(tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Accept: 'application/json',\n },\n body: body.toString(),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new IntegrationError(\n `Token exchange failed: ${response.status}`,\n ErrorCode.LINEAR_AUTH_FAILED,\n { status: response.status, body: errorText }\n );\n }\n\n const result = (await response.json()) as LinearAuthResult;\n\n // Calculate expiration time (tokens expire in 24 hours)\n const expiresAt = Date.now() + result.expiresIn * 1000;\n\n const tokens: LinearTokens = {\n accessToken: result.accessToken,\n refreshToken: result.refreshToken,\n expiresAt,\n scope: result.scope.split(' '),\n };\n\n this.saveTokens(tokens);\n return tokens;\n }\n\n /**\n * Refresh access token using refresh token\n */\n async refreshAccessToken(): Promise<LinearTokens> {\n if (!this.config) {\n throw new IntegrationError(\n 'Linear OAuth configuration not loaded',\n ErrorCode.LINEAR_AUTH_FAILED\n );\n }\n\n const currentTokens = this.loadTokens();\n if (!currentTokens?.refreshToken) {\n throw new IntegrationError(\n 'No refresh token available',\n ErrorCode.LINEAR_AUTH_FAILED\n );\n }\n\n const tokenUrl = 'https://api.linear.app/oauth/token';\n\n const body = new URLSearchParams({\n grant_type: 'refresh_token',\n client_id: this.config.clientId,\n client_secret: this.config.clientSecret,\n refresh_token: currentTokens.refreshToken,\n });\n\n const response = await fetch(tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Accept: 'application/json',\n },\n body: body.toString(),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new IntegrationError(\n `Token refresh failed: ${response.status}`,\n ErrorCode.LINEAR_AUTH_FAILED,\n { status: response.status, body: errorText }\n );\n }\n\n const result = (await response.json()) as LinearAuthResult;\n\n const tokens: LinearTokens = {\n accessToken: result.accessToken,\n refreshToken: result.refreshToken || currentTokens.refreshToken,\n expiresAt: Date.now() + result.expiresIn * 1000,\n scope: result.scope.split(' '),\n };\n\n this.saveTokens(tokens);\n return tokens;\n }\n\n /**\n * Get valid access token (refresh if needed)\n */\n async getValidToken(): Promise<string> {\n const tokens = this.loadTokens();\n if (!tokens) {\n throw new IntegrationError(\n 'No Linear tokens found. Please complete OAuth setup.',\n ErrorCode.LINEAR_AUTH_FAILED\n );\n }\n\n // Check if token expires in next 5 minutes\n const fiveMinutes = 5 * 60 * 1000;\n if (tokens.expiresAt - Date.now() < fiveMinutes) {\n logger.info('Linear token expiring soon, refreshing...');\n const newTokens = await this.refreshAccessToken();\n return newTokens.accessToken;\n }\n\n return tokens.accessToken;\n }\n\n /**\n * Save tokens to file\n */\n private saveTokens(tokens: LinearTokens): void {\n writeFileSync(this.tokensPath, JSON.stringify(tokens, null, 2));\n logger.info('Linear tokens saved');\n }\n\n /**\n * Load tokens from file\n */\n loadTokens(): LinearTokens | null {\n if (!existsSync(this.tokensPath)) {\n return null;\n }\n\n try {\n const tokensData = readFileSync(this.tokensPath, 'utf8');\n return JSON.parse(tokensData);\n } catch (error: unknown) {\n logger.error('Failed to load Linear tokens:', error as Error);\n return null;\n }\n }\n\n /**\n * Clear stored tokens and config\n */\n clearAuth(): void {\n if (existsSync(this.tokensPath)) {\n writeFileSync(this.tokensPath, '');\n }\n if (existsSync(this.configPath)) {\n writeFileSync(this.configPath, '');\n }\n logger.info('Linear authentication cleared');\n }\n}\n\n/**\n * Default Linear OAuth scopes for task management\n */\nexport const DEFAULT_LINEAR_SCOPES = [\n 'read', // Read issues, projects, teams\n 'write', // Create and update issues\n 'admin', // Manage team settings and workflows\n];\n\n/**\n * Linear OAuth setup helper\n */\nexport class LinearOAuthSetup {\n private authManager: LinearAuthManager;\n\n constructor(projectRoot: string) {\n this.authManager = new LinearAuthManager(projectRoot);\n }\n\n /**\n * Interactive setup for Linear OAuth\n */\n async setupInteractive(): Promise<{\n authUrl: string;\n instructions: string[];\n }> {\n // For now, we'll provide manual setup instructions\n // In a full implementation, this could open a browser or use a local server\n\n const config: LinearAuthConfig = {\n clientId: process.env['LINEAR_CLIENT_ID'] || '',\n clientSecret: process.env['LINEAR_CLIENT_SECRET'] || '',\n redirectUri:\n process.env['LINEAR_REDIRECT_URI'] ||\n 'http://localhost:3456/auth/linear/callback',\n scopes: DEFAULT_LINEAR_SCOPES,\n };\n\n if (!config.clientId || !config.clientSecret) {\n return {\n authUrl: '',\n instructions: [\n '1. Create a Linear OAuth application at https://linear.app/settings/api',\n '2. Set redirect URI to: http://localhost:3456/auth/linear/callback',\n '3. Copy your Client ID and Client Secret',\n '4. Set environment variables:',\n ' export LINEAR_CLIENT_ID=\"your_client_id\"',\n ' export LINEAR_CLIENT_SECRET=\"your_client_secret\"',\n '5. Re-run this setup command',\n ],\n };\n }\n\n this.authManager.saveConfig(config);\n\n const { url, codeVerifier } = this.authManager.generateAuthUrl();\n\n // Store code verifier temporarily (in a real app, this would be in a secure session store)\n process.env['_LINEAR_CODE_VERIFIER'] = codeVerifier;\n\n return {\n authUrl: url,\n instructions: [\n '1. Open this URL in your browser:',\n url,\n '',\n '2. Approve the StackMemory integration',\n '3. Copy the authorization code from the redirect URL',\n '4. Run: stackmemory linear authorize <code>',\n ],\n };\n }\n\n /**\n * Complete OAuth flow with authorization code\n */\n async completeAuth(authCode: string): Promise<boolean> {\n try {\n const codeVerifier = process.env['_LINEAR_CODE_VERIFIER'];\n if (!codeVerifier) {\n throw new IntegrationError(\n 'Code verifier not found. Please restart the setup process.',\n ErrorCode.LINEAR_AUTH_FAILED\n );\n }\n\n await this.authManager.exchangeCodeForToken(authCode, codeVerifier);\n delete process.env['_LINEAR_CODE_VERIFIER'];\n\n logger.info('Linear OAuth setup completed successfully!');\n return true;\n } catch (error: unknown) {\n logger.error('Failed to complete Linear OAuth setup:', error as Error);\n return false;\n }\n }\n\n /**\n * Test the Linear connection\n */\n async testConnection(): Promise<boolean> {\n try {\n const token = await this.authManager.getValidToken();\n\n // Test with a simple GraphQL query\n const response = await fetch('https://api.linear.app/graphql', {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n query: 'query { viewer { id name email } }',\n }),\n });\n\n if (response.ok) {\n const result = (await response.json()) as {\n data?: { viewer?: { id: string; name: string; email: string } };\n };\n if (result.data?.viewer) {\n logger.info(\n `Connected to Linear as: ${result.data.viewer.name} (${result.data.viewer.email})`\n );\n return true;\n }\n }\n\n return false;\n } catch (error: unknown) {\n logger.error('Linear connection test failed:', error as Error);\n return false;\n }\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,258 @@
1
+ import { fileURLToPath as __fileURLToPath } from 'url';
2
+ import { dirname as __pathDirname } from 'path';
3
+ const __filename = __fileURLToPath(import.meta.url);
4
+ const __dirname = __pathDirname(__filename);
5
+ import { logger } from "../../core/monitoring/logger.js";
6
+ import { LinearTaskManager } from "../../features/tasks/linear-task-manager.js";
7
+ import { LinearAuthManager } from "./auth.js";
8
+ import { LinearSyncEngine, DEFAULT_SYNC_CONFIG } from "./sync.js";
9
+ import { LinearConfigManager } from "./config.js";
10
+ import { IntegrationError, ErrorCode } from "../../core/errors/index.js";
11
+ import Database from "better-sqlite3";
12
+ import { join } from "path";
13
+ import { existsSync } from "fs";
14
+ class LinearAutoSyncService {
15
+ config;
16
+ projectRoot;
17
+ configManager;
18
+ syncEngine;
19
+ intervalId;
20
+ isRunning = false;
21
+ lastSyncTime = 0;
22
+ retryCount = 0;
23
+ constructor(projectRoot, config) {
24
+ this.projectRoot = projectRoot;
25
+ this.configManager = new LinearConfigManager(projectRoot);
26
+ const persistedConfig = this.configManager.loadConfig();
27
+ const baseConfig = persistedConfig ? this.configManager.toAutoSyncConfig(persistedConfig) : {
28
+ ...DEFAULT_SYNC_CONFIG,
29
+ enabled: true,
30
+ interval: 5,
31
+ retryAttempts: 3,
32
+ retryDelay: 3e4,
33
+ autoSync: true,
34
+ direction: "bidirectional",
35
+ conflictResolution: "newest_wins",
36
+ quietHours: { start: 22, end: 7 }
37
+ };
38
+ this.config = { ...baseConfig, ...config };
39
+ if (config && Object.keys(config).length > 0) {
40
+ this.configManager.saveConfig(config);
41
+ }
42
+ }
43
+ /**
44
+ * Start the auto-sync service
45
+ */
46
+ async start() {
47
+ if (this.isRunning) {
48
+ logger.warn("Linear auto-sync service is already running");
49
+ return;
50
+ }
51
+ try {
52
+ const authManager = new LinearAuthManager(this.projectRoot);
53
+ if (!authManager.isConfigured()) {
54
+ throw new IntegrationError(
55
+ 'Linear integration not configured. Run "stackmemory linear setup" first.',
56
+ ErrorCode.LINEAR_AUTH_FAILED
57
+ );
58
+ }
59
+ const dbPath = join(this.projectRoot, ".stackmemory", "context.db");
60
+ if (!existsSync(dbPath)) {
61
+ throw new IntegrationError(
62
+ 'StackMemory not initialized. Run "stackmemory init" first.',
63
+ ErrorCode.LINEAR_SYNC_FAILED
64
+ );
65
+ }
66
+ const db = new Database(dbPath);
67
+ const taskStore = new LinearTaskManager(this.projectRoot, db);
68
+ this.syncEngine = new LinearSyncEngine(
69
+ taskStore,
70
+ authManager,
71
+ this.config
72
+ );
73
+ const token = await authManager.getValidToken();
74
+ if (!token) {
75
+ throw new IntegrationError(
76
+ "Unable to get valid Linear token. Check authentication.",
77
+ ErrorCode.LINEAR_AUTH_FAILED
78
+ );
79
+ }
80
+ this.isRunning = true;
81
+ this.scheduleNextSync();
82
+ logger.info("Linear auto-sync service started", {
83
+ interval: this.config.interval,
84
+ direction: this.config.direction,
85
+ conflictResolution: this.config.conflictResolution
86
+ });
87
+ this.performSync();
88
+ } catch (error) {
89
+ logger.error("Failed to start Linear auto-sync service:", error);
90
+ throw error;
91
+ }
92
+ }
93
+ /**
94
+ * Stop the auto-sync service
95
+ */
96
+ stop() {
97
+ if (this.intervalId) {
98
+ clearTimeout(this.intervalId);
99
+ this.intervalId = void 0;
100
+ }
101
+ this.isRunning = false;
102
+ logger.info("Linear auto-sync service stopped");
103
+ }
104
+ /**
105
+ * Get service status
106
+ */
107
+ getStatus() {
108
+ const nextSyncTime = this.intervalId ? this.lastSyncTime + this.config.interval * 60 * 1e3 : void 0;
109
+ return {
110
+ running: this.isRunning,
111
+ lastSyncTime: this.lastSyncTime,
112
+ nextSyncTime,
113
+ retryCount: this.retryCount,
114
+ config: this.config
115
+ };
116
+ }
117
+ /**
118
+ * Update configuration
119
+ */
120
+ updateConfig(newConfig) {
121
+ this.config = { ...this.config, ...newConfig };
122
+ if (this.isRunning) {
123
+ this.stop();
124
+ this.start();
125
+ }
126
+ logger.info("Linear auto-sync config updated", newConfig);
127
+ }
128
+ /**
129
+ * Force immediate sync
130
+ */
131
+ async forceSync() {
132
+ if (!this.syncEngine) {
133
+ throw new IntegrationError(
134
+ "Sync engine not initialized",
135
+ ErrorCode.LINEAR_SYNC_FAILED
136
+ );
137
+ }
138
+ logger.info("Forcing immediate Linear sync");
139
+ await this.performSync();
140
+ }
141
+ /**
142
+ * Schedule next sync based on configuration
143
+ */
144
+ scheduleNextSync() {
145
+ if (!this.isRunning) return;
146
+ const delay = this.config.interval * 60 * 1e3;
147
+ this.intervalId = setTimeout(() => {
148
+ if (this.isRunning) {
149
+ this.performSync();
150
+ }
151
+ }, delay);
152
+ }
153
+ /**
154
+ * Perform synchronization with error handling and retries
155
+ */
156
+ async performSync() {
157
+ if (!this.syncEngine) {
158
+ logger.error("Sync engine not available");
159
+ return;
160
+ }
161
+ if (this.isInQuietHours()) {
162
+ logger.debug("Skipping sync during quiet hours");
163
+ this.scheduleNextSync();
164
+ return;
165
+ }
166
+ try {
167
+ logger.debug("Starting Linear auto-sync");
168
+ const result = await this.syncEngine.sync();
169
+ if (result.success) {
170
+ this.lastSyncTime = Date.now();
171
+ this.retryCount = 0;
172
+ const hasChanges = result.synced.toLinear > 0 || result.synced.fromLinear > 0 || result.synced.updated > 0;
173
+ if (hasChanges) {
174
+ logger.info("Linear auto-sync completed with changes", {
175
+ toLinear: result.synced.toLinear,
176
+ fromLinear: result.synced.fromLinear,
177
+ updated: result.synced.updated,
178
+ conflicts: result.conflicts.length
179
+ });
180
+ } else {
181
+ logger.debug("Linear auto-sync completed - no changes");
182
+ }
183
+ if (result.conflicts.length > 0) {
184
+ logger.warn("Linear sync conflicts detected", {
185
+ count: result.conflicts.length,
186
+ conflicts: result.conflicts.map((c) => ({
187
+ taskId: c.taskId,
188
+ reason: c.reason
189
+ }))
190
+ });
191
+ }
192
+ } else {
193
+ throw new IntegrationError(
194
+ `Sync failed: ${result.errors.join(", ")}`,
195
+ ErrorCode.LINEAR_SYNC_FAILED
196
+ );
197
+ }
198
+ } catch (error) {
199
+ logger.error("Linear auto-sync failed:", error);
200
+ this.retryCount++;
201
+ if (this.retryCount <= this.config.retryAttempts) {
202
+ logger.info(
203
+ `Retrying Linear sync in ${this.config.retryDelay / 1e3}s (attempt ${this.retryCount}/${this.config.retryAttempts})`
204
+ );
205
+ setTimeout(() => {
206
+ if (this.isRunning) {
207
+ this.performSync();
208
+ }
209
+ }, this.config.retryDelay);
210
+ return;
211
+ } else {
212
+ logger.error(
213
+ `Linear auto-sync failed after ${this.config.retryAttempts} attempts, skipping until next interval`
214
+ );
215
+ this.retryCount = 0;
216
+ }
217
+ }
218
+ this.scheduleNextSync();
219
+ }
220
+ /**
221
+ * Check if current time is within quiet hours
222
+ */
223
+ isInQuietHours() {
224
+ if (!this.config.quietHours) return false;
225
+ const now = /* @__PURE__ */ new Date();
226
+ const currentHour = now.getHours();
227
+ const { start, end } = this.config.quietHours;
228
+ if (start < end) {
229
+ return currentHour >= start || currentHour < end;
230
+ } else {
231
+ return currentHour >= start && currentHour < end;
232
+ }
233
+ }
234
+ }
235
+ let autoSyncService = null;
236
+ function initializeAutoSync(projectRoot, config) {
237
+ if (autoSyncService) {
238
+ autoSyncService.stop();
239
+ }
240
+ autoSyncService = new LinearAutoSyncService(projectRoot, config);
241
+ return autoSyncService;
242
+ }
243
+ function getAutoSyncService() {
244
+ return autoSyncService;
245
+ }
246
+ function stopAutoSync() {
247
+ if (autoSyncService) {
248
+ autoSyncService.stop();
249
+ autoSyncService = null;
250
+ }
251
+ }
252
+ export {
253
+ LinearAutoSyncService,
254
+ getAutoSyncService,
255
+ initializeAutoSync,
256
+ stopAutoSync
257
+ };
258
+ //# sourceMappingURL=auto-sync.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/integrations/linear/auto-sync.ts"],
4
+ "sourcesContent": ["/**\n * Linear Auto-Sync Service\n * Background service for automatic bidirectional synchronization\n */\n\nimport { logger } from '../../core/monitoring/logger.js';\nimport { LinearTaskManager } from '../../features/tasks/linear-task-manager.js';\nimport { LinearAuthManager } from './auth.js';\nimport { LinearSyncEngine, DEFAULT_SYNC_CONFIG, SyncConfig } from './sync.js';\nimport { LinearConfigManager } from './config.js';\nimport { IntegrationError, ErrorCode } from '../../core/errors/index.js';\nimport Database from 'better-sqlite3';\nimport { join } from 'path';\nimport { existsSync } from 'fs';\n\nexport interface AutoSyncConfig extends SyncConfig {\n enabled: boolean;\n interval: number; // minutes\n retryAttempts: number;\n retryDelay: number; // milliseconds\n quietHours?: {\n start: number; // hour 0-23\n end: number; // hour 0-23\n };\n}\n\nexport class LinearAutoSyncService {\n private config: AutoSyncConfig;\n private projectRoot: string;\n private configManager: LinearConfigManager;\n private syncEngine?: LinearSyncEngine;\n private intervalId?: NodeJS.Timeout;\n private isRunning = false;\n private lastSyncTime = 0;\n private retryCount = 0;\n\n constructor(projectRoot: string, config?: Partial<AutoSyncConfig>) {\n this.projectRoot = projectRoot;\n this.configManager = new LinearConfigManager(projectRoot);\n\n // Load persisted config or use defaults\n const persistedConfig = this.configManager.loadConfig();\n const baseConfig = persistedConfig\n ? this.configManager.toAutoSyncConfig(persistedConfig)\n : {\n ...DEFAULT_SYNC_CONFIG,\n enabled: true,\n interval: 5,\n retryAttempts: 3,\n retryDelay: 30000,\n autoSync: true,\n direction: 'bidirectional' as const,\n conflictResolution: 'newest_wins' as const,\n quietHours: { start: 22, end: 7 },\n };\n\n this.config = { ...baseConfig, ...config };\n\n // Save any new config updates\n if (config && Object.keys(config).length > 0) {\n this.configManager.saveConfig(config);\n }\n }\n\n /**\n * Start the auto-sync service\n */\n async start(): Promise<void> {\n if (this.isRunning) {\n logger.warn('Linear auto-sync service is already running');\n return;\n }\n\n try {\n // Verify Linear integration is configured\n const authManager = new LinearAuthManager(this.projectRoot);\n if (!authManager.isConfigured()) {\n throw new IntegrationError(\n 'Linear integration not configured. Run \"stackmemory linear setup\" first.',\n ErrorCode.LINEAR_AUTH_FAILED\n );\n }\n\n // Initialize sync engine\n const dbPath = join(this.projectRoot, '.stackmemory', 'context.db');\n if (!existsSync(dbPath)) {\n throw new IntegrationError(\n 'StackMemory not initialized. Run \"stackmemory init\" first.',\n ErrorCode.LINEAR_SYNC_FAILED\n );\n }\n\n const db = new Database(dbPath);\n const taskStore = new LinearTaskManager(this.projectRoot, db);\n\n this.syncEngine = new LinearSyncEngine(\n taskStore,\n authManager,\n this.config\n );\n\n // Test connection before starting\n const token = await authManager.getValidToken();\n if (!token) {\n throw new IntegrationError(\n 'Unable to get valid Linear token. Check authentication.',\n ErrorCode.LINEAR_AUTH_FAILED\n );\n }\n\n this.isRunning = true;\n this.scheduleNextSync();\n\n logger.info('Linear auto-sync service started', {\n interval: this.config.interval,\n direction: this.config.direction,\n conflictResolution: this.config.conflictResolution,\n });\n\n // Perform initial sync\n this.performSync();\n } catch (error: unknown) {\n logger.error('Failed to start Linear auto-sync service:', error as Error);\n throw error;\n }\n }\n\n /**\n * Stop the auto-sync service\n */\n stop(): void {\n if (this.intervalId) {\n clearTimeout(this.intervalId);\n this.intervalId = undefined;\n }\n\n this.isRunning = false;\n logger.info('Linear auto-sync service stopped');\n }\n\n /**\n * Get service status\n */\n getStatus(): {\n running: boolean;\n lastSyncTime: number;\n nextSyncTime?: number;\n retryCount: number;\n config: AutoSyncConfig;\n } {\n const nextSyncTime = this.intervalId\n ? this.lastSyncTime + this.config.interval * 60 * 1000\n : undefined;\n\n return {\n running: this.isRunning,\n lastSyncTime: this.lastSyncTime,\n nextSyncTime,\n retryCount: this.retryCount,\n config: this.config,\n };\n }\n\n /**\n * Update configuration\n */\n updateConfig(newConfig: Partial<AutoSyncConfig>): void {\n this.config = { ...this.config, ...newConfig };\n\n if (this.isRunning) {\n // Restart with new config\n this.stop();\n this.start();\n }\n\n logger.info('Linear auto-sync config updated', newConfig);\n }\n\n /**\n * Force immediate sync\n */\n async forceSync(): Promise<void> {\n if (!this.syncEngine) {\n throw new IntegrationError(\n 'Sync engine not initialized',\n ErrorCode.LINEAR_SYNC_FAILED\n );\n }\n\n logger.info('Forcing immediate Linear sync');\n await this.performSync();\n }\n\n /**\n * Schedule next sync based on configuration\n */\n private scheduleNextSync(): void {\n if (!this.isRunning) return;\n\n const delay = this.config.interval * 60 * 1000; // Convert minutes to milliseconds\n\n this.intervalId = setTimeout(() => {\n if (this.isRunning) {\n this.performSync();\n }\n }, delay);\n }\n\n /**\n * Perform synchronization with error handling and retries\n */\n private async performSync(): Promise<void> {\n if (!this.syncEngine) {\n logger.error('Sync engine not available');\n return;\n }\n\n // Check quiet hours\n if (this.isInQuietHours()) {\n logger.debug('Skipping sync during quiet hours');\n this.scheduleNextSync();\n return;\n }\n\n try {\n logger.debug('Starting Linear auto-sync');\n\n const result = await this.syncEngine.sync();\n\n if (result.success) {\n this.lastSyncTime = Date.now();\n this.retryCount = 0;\n\n // Log sync results\n const hasChanges =\n result.synced.toLinear > 0 ||\n result.synced.fromLinear > 0 ||\n result.synced.updated > 0;\n\n if (hasChanges) {\n logger.info('Linear auto-sync completed with changes', {\n toLinear: result.synced.toLinear,\n fromLinear: result.synced.fromLinear,\n updated: result.synced.updated,\n conflicts: result.conflicts.length,\n });\n } else {\n logger.debug('Linear auto-sync completed - no changes');\n }\n\n // Handle conflicts\n if (result.conflicts.length > 0) {\n logger.warn('Linear sync conflicts detected', {\n count: result.conflicts.length,\n conflicts: result.conflicts.map((c) => ({\n taskId: c.taskId,\n reason: c.reason,\n })),\n });\n }\n } else {\n throw new IntegrationError(\n `Sync failed: ${result.errors.join(', ')}`,\n ErrorCode.LINEAR_SYNC_FAILED\n );\n }\n } catch (error: unknown) {\n logger.error('Linear auto-sync failed:', error as Error);\n\n this.retryCount++;\n\n if (this.retryCount <= this.config.retryAttempts) {\n logger.info(\n `Retrying Linear sync in ${this.config.retryDelay / 1000}s (attempt ${this.retryCount}/${this.config.retryAttempts})`\n );\n\n // Schedule retry\n setTimeout(() => {\n if (this.isRunning) {\n this.performSync();\n }\n }, this.config.retryDelay);\n\n return; // Don't schedule next sync yet\n } else {\n logger.error(\n `Linear auto-sync failed after ${this.config.retryAttempts} attempts, skipping until next interval`\n );\n this.retryCount = 0;\n }\n }\n\n // Schedule next sync\n this.scheduleNextSync();\n }\n\n /**\n * Check if current time is within quiet hours\n */\n private isInQuietHours(): boolean {\n if (!this.config.quietHours) return false;\n\n const now = new Date();\n const currentHour = now.getHours();\n const { start, end } = this.config.quietHours;\n\n if (start < end) {\n // Quiet hours within same day (e.g., 22:00 - 07:00 next day)\n return currentHour >= start || currentHour < end;\n } else {\n // Quiet hours span midnight (e.g., 10:00 - 18:00)\n return currentHour >= start && currentHour < end;\n }\n }\n}\n\n/**\n * Global auto-sync service instance\n */\nlet autoSyncService: LinearAutoSyncService | null = null;\n\n/**\n * Initialize global auto-sync service\n */\nexport function initializeAutoSync(\n projectRoot: string,\n config?: Partial<AutoSyncConfig>\n): LinearAutoSyncService {\n if (autoSyncService) {\n autoSyncService.stop();\n }\n\n autoSyncService = new LinearAutoSyncService(projectRoot, config);\n return autoSyncService;\n}\n\n/**\n * Get global auto-sync service\n */\nexport function getAutoSyncService(): LinearAutoSyncService | null {\n return autoSyncService;\n}\n\n/**\n * Stop global auto-sync service\n */\nexport function stopAutoSync(): void {\n if (autoSyncService) {\n autoSyncService.stop();\n autoSyncService = null;\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }