@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,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/features/analytics/api/analytics-api.ts"],
4
+ "sourcesContent": ["import express, { Request, Response, Router } from 'express';\nimport { AnalyticsService } from '../core/analytics-service.js';\nimport { AnalyticsQuery, TimeRange } from '../types/metrics.js';\nimport { WebSocketServer, WebSocket } from 'ws';\nimport { Server } from 'http';\n\nexport class AnalyticsAPI {\n private router: Router;\n private analyticsService: AnalyticsService;\n private wss?: WebSocketServer;\n\n constructor(projectPath?: string) {\n this.router = express.Router();\n this.analyticsService = new AnalyticsService(projectPath);\n this.setupRoutes();\n }\n\n private setupRoutes(): void {\n this.router.use(express.json());\n\n this.router.get('/metrics', this.getMetrics.bind(this));\n this.router.get('/tasks', this.getTasks.bind(this));\n this.router.get('/team/:userId', this.getTeamMetrics.bind(this));\n this.router.post('/tasks', this.addTask.bind(this));\n this.router.put('/tasks/:taskId', this.updateTask.bind(this));\n this.router.post('/sync', this.syncLinear.bind(this));\n this.router.get('/export', this.exportMetrics.bind(this));\n }\n\n private async getMetrics(req: Request, res: Response): Promise<void> {\n try {\n const query = this.parseQuery(req.query);\n const dashboardState =\n await this.analyticsService.getDashboardState(query);\n\n res.json({\n success: true,\n data: {\n metrics: dashboardState.metrics,\n lastUpdated: dashboardState.lastUpdated,\n },\n });\n } catch (error: unknown) {\n this.handleError(res, error);\n }\n }\n\n private async getTasks(req: Request, res: Response): Promise<void> {\n try {\n const query = this.parseQuery(req.query);\n const dashboardState =\n await this.analyticsService.getDashboardState(query);\n\n res.json({\n success: true,\n data: {\n tasks: dashboardState.recentTasks,\n total: dashboardState.metrics.totalTasks,\n },\n });\n } catch (error: unknown) {\n this.handleError(res, error);\n }\n }\n\n private async getTeamMetrics(req: Request, res: Response): Promise<void> {\n try {\n const { userId } = req.params;\n const query = this.parseQuery(req.query);\n\n if (userId === 'all') {\n const dashboardState =\n await this.analyticsService.getDashboardState(query);\n res.json({\n success: true,\n data: dashboardState.teamMetrics,\n });\n } else {\n const dashboardState = await this.analyticsService.getDashboardState({\n ...query,\n userIds: [userId],\n });\n\n const userMetrics = dashboardState.teamMetrics.find(\n (m) => m.userId === userId\n );\n\n if (!userMetrics) {\n res.status(404).json({\n success: false,\n error: 'User metrics not found',\n });\n return;\n }\n\n res.json({\n success: true,\n data: userMetrics,\n });\n }\n } catch (error: unknown) {\n this.handleError(res, error);\n }\n }\n\n private async addTask(req: Request, res: Response): Promise<void> {\n try {\n const task = {\n ...req.body,\n createdAt: new Date(req.body.createdAt || Date.now()),\n completedAt: req.body.completedAt\n ? new Date(req.body.completedAt)\n : undefined,\n };\n\n await this.analyticsService.addTask(task);\n\n res.status(201).json({\n success: true,\n message: 'Task added successfully',\n });\n } catch (error: unknown) {\n this.handleError(res, error);\n }\n }\n\n private async updateTask(req: Request, res: Response): Promise<void> {\n try {\n const { taskId } = req.params;\n const updates = req.body;\n\n if (updates.completedAt) {\n updates.completedAt = new Date(updates.completedAt);\n }\n\n await this.analyticsService.updateTask(taskId, updates);\n\n res.json({\n success: true,\n message: 'Task updated successfully',\n });\n } catch (error: unknown) {\n this.handleError(res, error);\n }\n }\n\n private async syncLinear(req: Request, res: Response): Promise<void> {\n try {\n await this.analyticsService.syncLinearTasks();\n\n res.json({\n success: true,\n message: 'Linear tasks synced successfully',\n });\n } catch (error: unknown) {\n this.handleError(res, error);\n }\n }\n\n private async exportMetrics(req: Request, res: Response): Promise<void> {\n try {\n const query = this.parseQuery(req.query);\n const format = (req.query.format as 'json' | 'csv') || 'json';\n const dashboardState =\n await this.analyticsService.getDashboardState(query);\n\n if (format === 'csv') {\n const csv = this.convertToCSV(dashboardState);\n res.setHeader('Content-Type', 'text/csv');\n res.setHeader(\n 'Content-Disposition',\n 'attachment; filename=\"analytics-export.csv\"'\n );\n res.send(csv);\n } else {\n res.json({\n success: true,\n data: dashboardState,\n });\n }\n } catch (error: unknown) {\n this.handleError(res, error);\n }\n }\n\n private parseQuery(query: any): AnalyticsQuery {\n const result: AnalyticsQuery = {};\n\n if (query.start && query.end) {\n result.timeRange = {\n start: new Date(query.start),\n end: new Date(query.end),\n preset: query.preset,\n };\n } else if (query.preset) {\n result.timeRange = this.getPresetTimeRange(query.preset);\n }\n\n if (query.users) {\n result.userIds = Array.isArray(query.users) ? query.users : [query.users];\n }\n\n if (query.states) {\n result.states = Array.isArray(query.states)\n ? query.states\n : [query.states];\n }\n\n if (query.priorities) {\n result.priorities = Array.isArray(query.priorities)\n ? query.priorities\n : [query.priorities];\n }\n\n if (query.labels) {\n result.labels = Array.isArray(query.labels)\n ? query.labels\n : [query.labels];\n }\n\n if (query.limit) {\n result.limit = parseInt(query.limit);\n }\n\n if (query.offset) {\n result.offset = parseInt(query.offset);\n }\n\n return result;\n }\n\n private getPresetTimeRange(preset: string): TimeRange {\n const end = new Date();\n const start = new Date();\n\n switch (preset) {\n case 'today':\n start.setHours(0, 0, 0, 0);\n break;\n case '7d':\n start.setDate(start.getDate() - 7);\n break;\n case '30d':\n start.setDate(start.getDate() - 30);\n break;\n case '90d':\n start.setDate(start.getDate() - 90);\n break;\n default:\n start.setDate(start.getDate() - 7);\n }\n\n return { start, end, preset: preset as TimeRange['preset'] };\n }\n\n private convertToCSV(dashboardState: any): string {\n const tasks = dashboardState.recentTasks;\n if (!tasks || tasks.length === 0) return 'No data';\n\n const headers = Object.keys(tasks[0]).join(',');\n const rows = tasks.map((task: any) =>\n Object.values(task)\n .map((v) => (typeof v === 'object' ? JSON.stringify(v) : v))\n .join(',')\n );\n\n return [headers, ...rows].join('\\n');\n }\n\n private handleError(res: Response, error: any): void {\n console.error('Analytics API error:', error);\n res.status(500).json({\n success: false,\n error: error.message || 'Internal server error',\n });\n }\n\n setupWebSocket(server: Server): void {\n this.wss = new WebSocketServer({\n server,\n path: '/ws/analytics',\n });\n\n this.wss.on('connection', (ws: WebSocket) => {\n console.log('WebSocket client connected to analytics');\n\n const unsubscribe = this.analyticsService.subscribeToUpdates((state) => {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(\n JSON.stringify({\n type: 'update',\n data: state,\n })\n );\n }\n });\n\n ws.on('message', async (message: string) => {\n try {\n const data = JSON.parse(message);\n\n if (data.type === 'subscribe') {\n const query = this.parseQuery(data.query || {});\n const state = await this.analyticsService.getDashboardState(query);\n\n ws.send(\n JSON.stringify({\n type: 'initial',\n data: state,\n })\n );\n }\n } catch (error: unknown) {\n ws.send(\n JSON.stringify({\n type: 'error',\n error: 'Invalid message format',\n })\n );\n }\n });\n\n ws.on('close', () => {\n unsubscribe();\n console.log('WebSocket client disconnected');\n });\n\n ws.on('error', (error) => {\n console.error('WebSocket error:', error);\n unsubscribe();\n });\n });\n }\n\n getRouter(): Router {\n return this.router;\n }\n\n close(): void {\n this.analyticsService.close();\n if (this.wss) {\n this.wss.close();\n }\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,282 @@
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 { MetricsQueries } from "../queries/metrics-queries.js";
6
+ import { LinearClient } from "../../../integrations/linear/client.js";
7
+ import { LinearTaskManager } from "../../tasks/linear-task-manager.js";
8
+ import Database from "better-sqlite3";
9
+ import path from "path";
10
+ import fs from "fs";
11
+ import os from "os";
12
+ function getEnv(key, defaultValue) {
13
+ const value = process.env[key];
14
+ if (value === void 0) {
15
+ if (defaultValue !== void 0) return defaultValue;
16
+ throw new Error(`Environment variable ${key} is required`);
17
+ }
18
+ return value;
19
+ }
20
+ function getOptionalEnv(key) {
21
+ return process.env[key];
22
+ }
23
+ class AnalyticsService {
24
+ metricsQueries;
25
+ linearClient;
26
+ taskStore;
27
+ dbPath;
28
+ projectPath;
29
+ updateCallbacks = /* @__PURE__ */ new Set();
30
+ constructor(projectPath) {
31
+ this.projectPath = projectPath || process.cwd();
32
+ this.dbPath = path.join(this.projectPath, ".stackmemory", "analytics.db");
33
+ this.ensureDirectoryExists();
34
+ this.metricsQueries = new MetricsQueries(this.dbPath);
35
+ this.initializeTaskStore();
36
+ if (process.env["LINEAR_API_KEY"]) {
37
+ this.initializeLinearIntegration();
38
+ }
39
+ }
40
+ initializeTaskStore() {
41
+ try {
42
+ const contextDbPath = path.join(
43
+ this.projectPath,
44
+ ".stackmemory",
45
+ "context.db"
46
+ );
47
+ if (fs.existsSync(contextDbPath)) {
48
+ const db = new Database(contextDbPath);
49
+ this.taskStore = new LinearTaskManager(this.projectPath, db);
50
+ }
51
+ } catch (error) {
52
+ console.error("Failed to initialize task store:", error);
53
+ }
54
+ }
55
+ ensureDirectoryExists() {
56
+ const dir = path.dirname(this.dbPath);
57
+ if (!fs.existsSync(dir)) {
58
+ fs.mkdirSync(dir, { recursive: true });
59
+ }
60
+ }
61
+ async initializeLinearIntegration() {
62
+ try {
63
+ const configPath = path.join(
64
+ os.homedir(),
65
+ ".stackmemory",
66
+ "linear-config.json"
67
+ );
68
+ if (fs.existsSync(configPath)) {
69
+ const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
70
+ this.linearClient = new LinearClient(config);
71
+ await this.syncLinearTasks();
72
+ }
73
+ } catch (error) {
74
+ console.error("Failed to initialize Linear integration:", error);
75
+ }
76
+ }
77
+ async syncLinearTasks() {
78
+ await this.syncFromTaskStore();
79
+ if (this.linearClient) {
80
+ try {
81
+ const issues = await this.linearClient.getIssues({ limit: 100 });
82
+ for (const issue of issues) {
83
+ const task = {
84
+ id: issue.id,
85
+ title: issue.title,
86
+ state: this.mapLinearState(issue.state.type),
87
+ createdAt: new Date(issue.createdAt),
88
+ completedAt: issue.state.type === "completed" ? new Date(issue.updatedAt) : void 0,
89
+ estimatedEffort: issue.estimate ? issue.estimate * 60 : void 0,
90
+ assigneeId: issue.assignee?.id,
91
+ priority: this.mapLinearPriority(issue.priority),
92
+ labels: Array.isArray(issue.labels) ? issue.labels.map((l) => l.name) : issue.labels?.nodes?.map((l) => l.name) || [],
93
+ blockingIssues: []
94
+ };
95
+ this.metricsQueries.upsertTask(task);
96
+ }
97
+ } catch (error) {
98
+ console.error("Failed to sync from Linear API:", error);
99
+ }
100
+ }
101
+ await this.notifyUpdate();
102
+ }
103
+ async syncFromTaskStore() {
104
+ if (!this.taskStore) return 0;
105
+ try {
106
+ const allTasks = this.getAllTasksFromStore();
107
+ let synced = 0;
108
+ for (const task of allTasks) {
109
+ const analyticsTask = {
110
+ id: task.id,
111
+ title: task.title,
112
+ state: this.mapTaskStatus(task.status),
113
+ createdAt: new Date(task.created_at * 1e3),
114
+ completedAt: task.completed_at ? new Date(task.completed_at * 1e3) : void 0,
115
+ estimatedEffort: task.estimated_effort,
116
+ actualEffort: task.actual_effort,
117
+ assigneeId: task.assignee,
118
+ priority: task.priority,
119
+ labels: task.tags || [],
120
+ blockingIssues: task.depends_on || []
121
+ };
122
+ this.metricsQueries.upsertTask(analyticsTask);
123
+ synced++;
124
+ }
125
+ return synced;
126
+ } catch (error) {
127
+ console.error("Failed to sync from task store:", error);
128
+ return 0;
129
+ }
130
+ }
131
+ getAllTasksFromStore() {
132
+ if (!this.taskStore) return [];
133
+ try {
134
+ const contextDbPath = path.join(
135
+ this.projectPath,
136
+ ".stackmemory",
137
+ "context.db"
138
+ );
139
+ const db = new Database(contextDbPath);
140
+ const rows = db.prepare(
141
+ `
142
+ SELECT * FROM task_cache
143
+ ORDER BY created_at DESC
144
+ `
145
+ ).all();
146
+ db.close();
147
+ return rows.map((row) => ({
148
+ id: row.id,
149
+ title: row.title,
150
+ description: row.description,
151
+ status: row.status,
152
+ priority: row.priority,
153
+ created_at: row.created_at,
154
+ completed_at: row.completed_at,
155
+ estimated_effort: row.estimated_effort,
156
+ actual_effort: row.actual_effort,
157
+ assignee: row.assignee,
158
+ tags: JSON.parse(row.tags || "[]"),
159
+ depends_on: JSON.parse(row.depends_on || "[]")
160
+ }));
161
+ } catch (error) {
162
+ console.error("Failed to get all tasks:", error);
163
+ return [];
164
+ }
165
+ }
166
+ mapTaskStatus(status) {
167
+ const statusMap = {
168
+ pending: "todo",
169
+ in_progress: "in_progress",
170
+ completed: "completed",
171
+ blocked: "blocked",
172
+ cancelled: "blocked"
173
+ };
174
+ return statusMap[status] || "todo";
175
+ }
176
+ mapLinearState(linearState) {
177
+ const stateMap = {
178
+ backlog: "todo",
179
+ unstarted: "todo",
180
+ started: "in_progress",
181
+ completed: "completed",
182
+ done: "completed",
183
+ canceled: "blocked"
184
+ };
185
+ return stateMap[linearState.toLowerCase()] || "todo";
186
+ }
187
+ mapLinearPriority(priority) {
188
+ if (priority === 1) return "urgent";
189
+ if (priority === 2) return "high";
190
+ if (priority === 3) return "medium";
191
+ return "low";
192
+ }
193
+ async getDashboardState(query = {}) {
194
+ const timeRange = query.timeRange || this.getDefaultTimeRange();
195
+ const metrics = this.metricsQueries.getTaskMetrics({
196
+ ...query,
197
+ timeRange
198
+ });
199
+ const recentTasks = this.metricsQueries.getRecentTasks({
200
+ ...query,
201
+ limit: 20
202
+ });
203
+ const teamMetrics = await this.getTeamMetrics(query);
204
+ return {
205
+ metrics,
206
+ teamMetrics,
207
+ recentTasks,
208
+ timeRange,
209
+ teamFilter: query.userIds || [],
210
+ isLive: this.updateCallbacks.size > 0,
211
+ lastUpdated: /* @__PURE__ */ new Date()
212
+ };
213
+ }
214
+ async getTeamMetrics(query) {
215
+ const uniqueUserIds = /* @__PURE__ */ new Set();
216
+ const tasks = this.metricsQueries.getRecentTasks({ limit: 1e3 });
217
+ tasks.forEach((task) => {
218
+ if (task.assigneeId) {
219
+ uniqueUserIds.add(task.assigneeId);
220
+ }
221
+ });
222
+ const teamMetrics = [];
223
+ const totalCompleted = tasks.filter((t) => t.state === "completed").length;
224
+ for (const userId of uniqueUserIds) {
225
+ const userQuery = { ...query, userIds: [userId] };
226
+ const individualMetrics = this.metricsQueries.getTaskMetrics(userQuery);
227
+ teamMetrics.push({
228
+ userId,
229
+ userName: await this.getUserName(userId),
230
+ individualMetrics,
231
+ contributionPercentage: totalCompleted > 0 ? individualMetrics.completedTasks / totalCompleted * 100 : 0,
232
+ lastActive: /* @__PURE__ */ new Date()
233
+ });
234
+ }
235
+ return teamMetrics.sort(
236
+ (a, b) => b.contributionPercentage - a.contributionPercentage
237
+ );
238
+ }
239
+ async getUserName(userId) {
240
+ return userId;
241
+ }
242
+ getDefaultTimeRange() {
243
+ const end = /* @__PURE__ */ new Date();
244
+ const start = /* @__PURE__ */ new Date();
245
+ start.setDate(start.getDate() - 7);
246
+ return {
247
+ start,
248
+ end,
249
+ preset: "7d"
250
+ };
251
+ }
252
+ subscribeToUpdates(callback) {
253
+ this.updateCallbacks.add(callback);
254
+ return () => {
255
+ this.updateCallbacks.delete(callback);
256
+ };
257
+ }
258
+ async notifyUpdate() {
259
+ const state = await this.getDashboardState();
260
+ this.updateCallbacks.forEach((callback) => callback(state));
261
+ }
262
+ async addTask(task) {
263
+ this.metricsQueries.upsertTask(task);
264
+ await this.notifyUpdate();
265
+ }
266
+ async updateTask(taskId, updates) {
267
+ const tasks = this.metricsQueries.getRecentTasks({ limit: 1 });
268
+ const existingTask = tasks.find((t) => t.id === taskId);
269
+ if (existingTask) {
270
+ const updatedTask = { ...existingTask, ...updates };
271
+ this.metricsQueries.upsertTask(updatedTask);
272
+ await this.notifyUpdate();
273
+ }
274
+ }
275
+ close() {
276
+ this.metricsQueries.close();
277
+ }
278
+ }
279
+ export {
280
+ AnalyticsService
281
+ };
282
+ //# sourceMappingURL=analytics-service.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/features/analytics/core/analytics-service.ts"],
4
+ "sourcesContent": ["import { MetricsQueries } from '../queries/metrics-queries.js';\nimport { LinearClient } from '../../../integrations/linear/client.js';\nimport { LinearTaskManager } from '../../tasks/linear-task-manager.js';\nimport Database from 'better-sqlite3';\nimport {\n TaskMetrics,\n TeamMetrics,\n TaskAnalytics,\n DashboardState,\n TimeRange,\n AnalyticsQuery,\n} from '../types/metrics.js';\nimport path from 'path';\nimport fs from 'fs';\nimport os from 'os';\n// Type-safe environment variable access\nfunction getEnv(key: string, defaultValue?: string): string {\n const value = process.env[key];\n if (value === undefined) {\n if (defaultValue !== undefined) return defaultValue;\n throw new Error(`Environment variable ${key} is required`);\n }\n return value;\n}\n\nfunction getOptionalEnv(key: string): string | undefined {\n return process.env[key];\n}\n\nexport class AnalyticsService {\n private metricsQueries: MetricsQueries;\n private linearClient?: LinearClient;\n private taskStore?: LinearTaskManager;\n private dbPath: string;\n private projectPath: string;\n private updateCallbacks: Set<(state: DashboardState) => void> = new Set();\n\n constructor(projectPath?: string) {\n this.projectPath = projectPath || process.cwd();\n this.dbPath = path.join(this.projectPath, '.stackmemory', 'analytics.db');\n\n this.ensureDirectoryExists();\n this.metricsQueries = new MetricsQueries(this.dbPath);\n\n // Initialize task store for syncing\n this.initializeTaskStore();\n\n if (process.env['LINEAR_API_KEY']) {\n this.initializeLinearIntegration();\n }\n }\n\n private initializeTaskStore(): void {\n try {\n const contextDbPath = path.join(\n this.projectPath,\n '.stackmemory',\n 'context.db'\n );\n if (fs.existsSync(contextDbPath)) {\n const db = new Database(contextDbPath);\n this.taskStore = new LinearTaskManager(this.projectPath, db);\n }\n } catch (error: unknown) {\n console.error('Failed to initialize task store:', error);\n }\n }\n\n private ensureDirectoryExists(): void {\n const dir = path.dirname(this.dbPath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n }\n\n private async initializeLinearIntegration(): Promise<void> {\n try {\n const configPath = path.join(\n os.homedir(),\n '.stackmemory',\n 'linear-config.json'\n );\n if (fs.existsSync(configPath)) {\n const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));\n this.linearClient = new LinearClient(config);\n await this.syncLinearTasks();\n }\n } catch (error: unknown) {\n console.error('Failed to initialize Linear integration:', error);\n }\n }\n\n async syncLinearTasks(): Promise<void> {\n // First sync from task store (which includes Linear-synced tasks)\n await this.syncFromTaskStore();\n\n // Then try direct Linear sync if client available\n if (this.linearClient) {\n try {\n const issues = await this.linearClient.getIssues({ limit: 100 });\n for (const issue of issues) {\n const task: TaskAnalytics = {\n id: issue.id,\n title: issue.title,\n state: this.mapLinearState(issue.state.type),\n createdAt: new Date(issue.createdAt),\n completedAt:\n issue.state.type === 'completed'\n ? new Date(issue.updatedAt)\n : undefined,\n estimatedEffort: issue.estimate ? issue.estimate * 60 : undefined,\n assigneeId: issue.assignee?.id,\n priority: this.mapLinearPriority(issue.priority),\n labels: Array.isArray(issue.labels)\n ? issue.labels.map((l: any) => l.name)\n : (issue.labels as any)?.nodes?.map((l: any) => l.name) || [],\n blockingIssues: [],\n };\n this.metricsQueries.upsertTask(task);\n }\n } catch (error: unknown) {\n console.error('Failed to sync from Linear API:', error);\n }\n }\n\n await this.notifyUpdate();\n }\n\n async syncFromTaskStore(): Promise<number> {\n if (!this.taskStore) return 0;\n\n try {\n // Get all tasks including completed ones\n const allTasks = this.getAllTasksFromStore();\n let synced = 0;\n\n for (const task of allTasks) {\n const analyticsTask: TaskAnalytics = {\n id: task.id,\n title: task.title,\n state: this.mapTaskStatus(task.status),\n createdAt: new Date(task.created_at * 1000),\n completedAt: task.completed_at\n ? new Date(task.completed_at * 1000)\n : undefined,\n estimatedEffort: task.estimated_effort,\n actualEffort: task.actual_effort,\n assigneeId: task.assignee,\n priority: task.priority as TaskAnalytics['priority'],\n labels: task.tags || [],\n blockingIssues: task.depends_on || [],\n };\n this.metricsQueries.upsertTask(analyticsTask);\n synced++;\n }\n\n return synced;\n } catch (error: unknown) {\n console.error('Failed to sync from task store:', error);\n return 0;\n }\n }\n\n private getAllTasksFromStore(): any[] {\n if (!this.taskStore) return [];\n\n try {\n // Access the db directly to get ALL tasks including completed\n const contextDbPath = path.join(\n this.projectPath,\n '.stackmemory',\n 'context.db'\n );\n const db = new Database(contextDbPath);\n\n const rows = db\n .prepare(\n `\n SELECT * FROM task_cache \n ORDER BY created_at DESC\n `\n )\n .all() as any[];\n\n db.close();\n\n // Hydrate the rows\n return rows.map((row) => ({\n id: row.id,\n title: row.title,\n description: row.description,\n status: row.status,\n priority: row.priority,\n created_at: row.created_at,\n completed_at: row.completed_at,\n estimated_effort: row.estimated_effort,\n actual_effort: row.actual_effort,\n assignee: row.assignee,\n tags: JSON.parse(row.tags || '[]'),\n depends_on: JSON.parse(row.depends_on || '[]'),\n }));\n } catch (error: unknown) {\n console.error('Failed to get all tasks:', error);\n return [];\n }\n }\n\n private mapTaskStatus(status: string): TaskAnalytics['state'] {\n const statusMap: Record<string, TaskAnalytics['state']> = {\n pending: 'todo',\n in_progress: 'in_progress',\n completed: 'completed',\n blocked: 'blocked',\n cancelled: 'blocked',\n };\n return statusMap[status] || 'todo';\n }\n\n private mapLinearState(linearState: string): TaskAnalytics['state'] {\n const stateMap: Record<string, TaskAnalytics['state']> = {\n backlog: 'todo',\n unstarted: 'todo',\n started: 'in_progress',\n completed: 'completed',\n done: 'completed',\n canceled: 'blocked',\n };\n return stateMap[linearState.toLowerCase()] || 'todo';\n }\n\n private mapLinearPriority(priority: number): TaskAnalytics['priority'] {\n if (priority === 1) return 'urgent';\n if (priority === 2) return 'high';\n if (priority === 3) return 'medium';\n return 'low';\n }\n\n async getDashboardState(query: AnalyticsQuery = {}): Promise<DashboardState> {\n const timeRange = query.timeRange || this.getDefaultTimeRange();\n\n const metrics = this.metricsQueries.getTaskMetrics({\n ...query,\n timeRange,\n });\n\n const recentTasks = this.metricsQueries.getRecentTasks({\n ...query,\n limit: 20,\n });\n\n const teamMetrics = await this.getTeamMetrics(query);\n\n return {\n metrics,\n teamMetrics,\n recentTasks,\n timeRange,\n teamFilter: query.userIds || [],\n isLive: this.updateCallbacks.size > 0,\n lastUpdated: new Date(),\n };\n }\n\n private async getTeamMetrics(query: AnalyticsQuery): Promise<TeamMetrics[]> {\n const uniqueUserIds = new Set<string>();\n const tasks = this.metricsQueries.getRecentTasks({ limit: 1000 });\n\n tasks.forEach((task) => {\n if (task.assigneeId) {\n uniqueUserIds.add(task.assigneeId);\n }\n });\n\n const teamMetrics: TeamMetrics[] = [];\n const totalCompleted = tasks.filter((t) => t.state === 'completed').length;\n\n for (const userId of uniqueUserIds) {\n const userQuery = { ...query, userIds: [userId] };\n const individualMetrics = this.metricsQueries.getTaskMetrics(userQuery);\n\n teamMetrics.push({\n userId,\n userName: await this.getUserName(userId),\n individualMetrics,\n contributionPercentage:\n totalCompleted > 0\n ? (individualMetrics.completedTasks / totalCompleted) * 100\n : 0,\n lastActive: new Date(),\n });\n }\n\n return teamMetrics.sort(\n (a, b) => b.contributionPercentage - a.contributionPercentage\n );\n }\n\n private async getUserName(userId: string): Promise<string> {\n // Stub for now - would need LinearClient to expose user query method\n return userId;\n }\n\n private getDefaultTimeRange(): TimeRange {\n const end = new Date();\n const start = new Date();\n start.setDate(start.getDate() - 7);\n\n return {\n start,\n end,\n preset: '7d',\n };\n }\n\n subscribeToUpdates(callback: (state: DashboardState) => void): () => void {\n this.updateCallbacks.add(callback);\n\n return () => {\n this.updateCallbacks.delete(callback);\n };\n }\n\n private async notifyUpdate(): Promise<void> {\n const state = await this.getDashboardState();\n this.updateCallbacks.forEach((callback) => callback(state));\n }\n\n async addTask(task: TaskAnalytics): Promise<void> {\n this.metricsQueries.upsertTask(task);\n await this.notifyUpdate();\n }\n\n async updateTask(\n taskId: string,\n updates: Partial<TaskAnalytics>\n ): Promise<void> {\n const tasks = this.metricsQueries.getRecentTasks({ limit: 1 });\n const existingTask = tasks.find((t) => t.id === taskId);\n\n if (existingTask) {\n const updatedTask = { ...existingTask, ...updates };\n this.metricsQueries.upsertTask(updatedTask);\n await this.notifyUpdate();\n }\n }\n\n close(): void {\n this.metricsQueries.close();\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,18 @@
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
+ export * from "./types/metrics.js";
6
+ export * from "./core/analytics-service.js";
7
+ export * from "./api/analytics-api.js";
8
+ export * from "./queries/metrics-queries.js";
9
+ import { AnalyticsService } from "./core/analytics-service.js";
10
+ import { AnalyticsAPI } from "./api/analytics-api.js";
11
+ var analytics_default = {
12
+ AnalyticsService,
13
+ AnalyticsAPI
14
+ };
15
+ export {
16
+ analytics_default as default
17
+ };
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/features/analytics/index.ts"],
4
+ "sourcesContent": ["export * from './types/metrics.js';\nexport * from './core/analytics-service.js';\nexport * from './api/analytics-api.js';\nexport * from './queries/metrics-queries.js';\n\nimport { AnalyticsService } from './core/analytics-service.js';\nimport { AnalyticsAPI } from './api/analytics-api.js';\n\nexport default {\n AnalyticsService,\n AnalyticsAPI,\n};\n"],
5
+ "mappings": ";;;;AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAEd,SAAS,wBAAwB;AACjC,SAAS,oBAAoB;AAE7B,IAAO,oBAAQ;AAAA,EACb;AAAA,EACA;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,277 @@
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 Database from "better-sqlite3";
6
+ import {
7
+ DatabaseError,
8
+ ErrorCode,
9
+ createErrorHandler
10
+ } from "../../../core/errors/index.js";
11
+ class MetricsQueries {
12
+ db;
13
+ constructor(dbPath) {
14
+ try {
15
+ this.db = new Database(dbPath, { readonly: false });
16
+ this.initializeTables();
17
+ } catch (error) {
18
+ throw new DatabaseError(
19
+ "Failed to initialize metrics database",
20
+ ErrorCode.DB_CONNECTION_FAILED,
21
+ {
22
+ dbPath,
23
+ operation: "constructor"
24
+ },
25
+ error instanceof Error ? error : void 0
26
+ );
27
+ }
28
+ }
29
+ initializeTables() {
30
+ const errorHandler = createErrorHandler({
31
+ operation: "initializeTables"
32
+ });
33
+ try {
34
+ this.db.exec(`
35
+ CREATE TABLE IF NOT EXISTS task_analytics (
36
+ id TEXT PRIMARY KEY,
37
+ title TEXT NOT NULL,
38
+ state TEXT NOT NULL,
39
+ created_at INTEGER NOT NULL,
40
+ completed_at INTEGER,
41
+ estimated_effort INTEGER,
42
+ actual_effort INTEGER,
43
+ assignee_id TEXT,
44
+ priority TEXT DEFAULT 'medium',
45
+ labels TEXT DEFAULT '[]',
46
+ blocking_issues TEXT DEFAULT '[]',
47
+ updated_at INTEGER DEFAULT (strftime('%s', 'now'))
48
+ );
49
+
50
+ CREATE INDEX IF NOT EXISTS idx_task_state ON task_analytics(state);
51
+ CREATE INDEX IF NOT EXISTS idx_task_created ON task_analytics(created_at);
52
+ CREATE INDEX IF NOT EXISTS idx_task_assignee ON task_analytics(assignee_id);
53
+ `);
54
+ } catch (error) {
55
+ const dbError = errorHandler(error, {
56
+ operation: "initializeTables",
57
+ schema: "task_analytics"
58
+ });
59
+ throw new DatabaseError(
60
+ "Failed to initialize analytics tables",
61
+ ErrorCode.DB_MIGRATION_FAILED,
62
+ {
63
+ operation: "initializeTables",
64
+ schema: "task_analytics"
65
+ },
66
+ error instanceof Error ? error : void 0
67
+ );
68
+ }
69
+ }
70
+ getTaskMetrics(query = {}) {
71
+ try {
72
+ const { timeRange, userIds, states, priorities } = query;
73
+ const whereConditions = ["1=1"];
74
+ const params = {};
75
+ if (timeRange) {
76
+ whereConditions.push(
77
+ "created_at >= @startTime AND created_at <= @endTime"
78
+ );
79
+ params.startTime = Math.floor(timeRange.start.getTime() / 1e3);
80
+ params.endTime = Math.floor(timeRange.end.getTime() / 1e3);
81
+ }
82
+ if (userIds && userIds.length > 0) {
83
+ whereConditions.push(
84
+ `assignee_id IN (${userIds.map((_, i) => `@user${i}`).join(",")})`
85
+ );
86
+ userIds.forEach((id, i) => params[`user${i}`] = id);
87
+ }
88
+ if (states && states.length > 0) {
89
+ whereConditions.push(
90
+ `state IN (${states.map((_, i) => `@state${i}`).join(",")})`
91
+ );
92
+ states.forEach((s, i) => params[`state${i}`] = s);
93
+ }
94
+ if (priorities && priorities.length > 0) {
95
+ whereConditions.push(
96
+ `priority IN (${priorities.map((_, i) => `@priority${i}`).join(",")})`
97
+ );
98
+ priorities.forEach((p, i) => params[`priority${i}`] = p);
99
+ }
100
+ const whereClause = whereConditions.join(" AND ");
101
+ const metricsQuery = this.db.prepare(`
102
+ SELECT
103
+ COUNT(*) as total_tasks,
104
+ SUM(CASE WHEN state = 'completed' THEN 1 ELSE 0 END) as completed_tasks,
105
+ SUM(CASE WHEN state = 'in_progress' THEN 1 ELSE 0 END) as in_progress_tasks,
106
+ SUM(CASE WHEN state = 'blocked' THEN 1 ELSE 0 END) as blocked_tasks,
107
+ AVG(CASE
108
+ WHEN state = 'completed' AND completed_at IS NOT NULL
109
+ THEN (completed_at - created_at) * 1000
110
+ ELSE NULL
111
+ END) as avg_time_to_complete,
112
+ AVG(CASE
113
+ WHEN actual_effort IS NOT NULL AND estimated_effort IS NOT NULL AND estimated_effort > 0
114
+ THEN (CAST(actual_effort AS REAL) / estimated_effort) * 100
115
+ ELSE NULL
116
+ END) as effort_accuracy,
117
+ SUM(CASE
118
+ WHEN json_array_length(blocking_issues) > 0
119
+ THEN json_array_length(blocking_issues)
120
+ ELSE 0
121
+ END) as blocking_issues_count
122
+ FROM task_analytics
123
+ WHERE ${whereClause}
124
+ `);
125
+ const result = metricsQuery.get(params);
126
+ const velocityQuery = this.db.prepare(`
127
+ SELECT
128
+ DATE(created_at, 'unixepoch') as day,
129
+ COUNT(*) as completed_count
130
+ FROM task_analytics
131
+ WHERE state = 'completed'
132
+ AND ${whereClause}
133
+ GROUP BY day
134
+ ORDER BY day DESC
135
+ LIMIT 30
136
+ `);
137
+ const velocityData = velocityQuery.all(params);
138
+ const velocityTrend = velocityData.map((v) => v.completed_count).reverse();
139
+ return {
140
+ totalTasks: result.total_tasks || 0,
141
+ completedTasks: result.completed_tasks || 0,
142
+ inProgressTasks: result.in_progress_tasks || 0,
143
+ blockedTasks: result.blocked_tasks || 0,
144
+ completionRate: result.total_tasks > 0 ? result.completed_tasks / result.total_tasks * 100 : 0,
145
+ averageTimeToComplete: result.avg_time_to_complete || 0,
146
+ effortAccuracy: result.effort_accuracy || 100,
147
+ blockingIssuesCount: result.blocking_issues_count || 0,
148
+ velocityTrend
149
+ };
150
+ } catch (error) {
151
+ throw new DatabaseError(
152
+ "Failed to get task metrics",
153
+ ErrorCode.DB_QUERY_FAILED,
154
+ {
155
+ query,
156
+ operation: "getTaskMetrics"
157
+ },
158
+ error instanceof Error ? error : void 0
159
+ );
160
+ }
161
+ }
162
+ getRecentTasks(query = {}) {
163
+ try {
164
+ const { limit = 100, offset = 0 } = query;
165
+ const tasksQuery = this.db.prepare(`
166
+ SELECT
167
+ id,
168
+ title,
169
+ state,
170
+ created_at,
171
+ completed_at,
172
+ estimated_effort,
173
+ actual_effort,
174
+ assignee_id,
175
+ priority,
176
+ labels,
177
+ blocking_issues
178
+ FROM task_analytics
179
+ ORDER BY updated_at DESC
180
+ LIMIT ? OFFSET ?
181
+ `);
182
+ const rows = tasksQuery.all(limit, offset);
183
+ return rows.map((row) => ({
184
+ id: row.id,
185
+ title: row.title,
186
+ state: row.state,
187
+ createdAt: new Date(row.created_at * 1e3),
188
+ completedAt: row.completed_at ? new Date(row.completed_at * 1e3) : void 0,
189
+ estimatedEffort: row.estimated_effort,
190
+ actualEffort: row.actual_effort,
191
+ assigneeId: row.assignee_id,
192
+ priority: row.priority,
193
+ labels: JSON.parse(row.labels),
194
+ blockingIssues: JSON.parse(row.blocking_issues)
195
+ }));
196
+ } catch (error) {
197
+ throw new DatabaseError(
198
+ "Failed to get recent tasks",
199
+ ErrorCode.DB_QUERY_FAILED,
200
+ {
201
+ limit: query.limit,
202
+ offset: query.offset,
203
+ operation: "getRecentTasks"
204
+ },
205
+ error instanceof Error ? error : void 0
206
+ );
207
+ }
208
+ }
209
+ upsertTask(task) {
210
+ try {
211
+ const stmt = this.db.prepare(`
212
+ INSERT INTO task_analytics (
213
+ id, title, state, created_at, completed_at,
214
+ estimated_effort, actual_effort, assignee_id,
215
+ priority, labels, blocking_issues
216
+ ) VALUES (
217
+ @id, @title, @state, @created_at, @completed_at,
218
+ @estimated_effort, @actual_effort, @assignee_id,
219
+ @priority, @labels, @blocking_issues
220
+ )
221
+ ON CONFLICT(id) DO UPDATE SET
222
+ title = @title,
223
+ state = @state,
224
+ completed_at = @completed_at,
225
+ estimated_effort = @estimated_effort,
226
+ actual_effort = @actual_effort,
227
+ assignee_id = @assignee_id,
228
+ priority = @priority,
229
+ labels = @labels,
230
+ blocking_issues = @blocking_issues,
231
+ updated_at = strftime('%s', 'now')
232
+ `);
233
+ stmt.run({
234
+ id: task.id,
235
+ title: task.title,
236
+ state: task.state,
237
+ created_at: Math.floor(task.createdAt.getTime() / 1e3),
238
+ completed_at: task.completedAt ? Math.floor(task.completedAt.getTime() / 1e3) : null,
239
+ estimated_effort: task.estimatedEffort || null,
240
+ actual_effort: task.actualEffort || null,
241
+ assignee_id: task.assigneeId || null,
242
+ priority: task.priority,
243
+ labels: JSON.stringify(task.labels),
244
+ blocking_issues: JSON.stringify(task.blockingIssues)
245
+ });
246
+ } catch (error) {
247
+ throw new DatabaseError(
248
+ `Failed to upsert task analytics: ${task.id}`,
249
+ ErrorCode.DB_QUERY_FAILED,
250
+ {
251
+ taskId: task.id,
252
+ taskState: task.state,
253
+ operation: "upsertTask"
254
+ },
255
+ error instanceof Error ? error : void 0
256
+ );
257
+ }
258
+ }
259
+ close() {
260
+ try {
261
+ this.db.close();
262
+ } catch (error) {
263
+ throw new DatabaseError(
264
+ "Failed to close analytics database",
265
+ ErrorCode.DB_CONNECTION_FAILED,
266
+ {
267
+ operation: "close"
268
+ },
269
+ error instanceof Error ? error : void 0
270
+ );
271
+ }
272
+ }
273
+ }
274
+ export {
275
+ MetricsQueries
276
+ };
277
+ //# sourceMappingURL=metrics-queries.js.map