@stackmemoryai/stackmemory 0.2.7 → 0.2.8

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 (297) hide show
  1. package/README.md +25 -8
  2. package/dist/scripts/cancel-duplicate-tasks.js +2 -1
  3. package/dist/scripts/cancel-duplicate-tasks.js.map +1 -1
  4. package/dist/scripts/list-linear-tasks.js +3 -4
  5. package/dist/scripts/list-linear-tasks.js.map +1 -1
  6. package/dist/scripts/merge-linear-duplicates-safe.js +4 -2
  7. package/dist/scripts/merge-linear-duplicates-safe.js.map +1 -1
  8. package/dist/scripts/show-linear-summary.js +4 -1
  9. package/dist/scripts/show-linear-summary.js.map +1 -1
  10. package/dist/scripts/status.js +6 -2
  11. package/dist/scripts/status.js.map +1 -1
  12. package/dist/src/cli/auto-detect.js.map +1 -1
  13. package/dist/src/cli/claude-sm.js.map +1 -1
  14. package/dist/src/cli/commands/config.d.ts +6 -0
  15. package/dist/src/cli/commands/config.d.ts.map +1 -0
  16. package/dist/src/cli/commands/config.js +224 -0
  17. package/dist/src/cli/commands/config.js.map +1 -0
  18. package/dist/src/cli/commands/linear.d.ts.map +1 -1
  19. package/dist/src/cli/commands/linear.js +123 -47
  20. package/dist/src/cli/commands/linear.js.map +1 -1
  21. package/dist/src/cli/index.d.ts.map +1 -1
  22. package/dist/src/cli/index.js +48 -1
  23. package/dist/src/cli/index.js.map +1 -1
  24. package/dist/src/core/config/config-manager.d.ts +95 -0
  25. package/dist/src/core/config/config-manager.d.ts.map +1 -0
  26. package/dist/src/core/config/config-manager.js +359 -0
  27. package/dist/src/core/config/config-manager.js.map +1 -0
  28. package/dist/src/core/config/types.d.ts +72 -0
  29. package/dist/src/core/config/types.d.ts.map +1 -0
  30. package/dist/src/core/config/types.js +127 -0
  31. package/dist/src/core/config/types.js.map +1 -0
  32. package/dist/src/core/context/compaction-handler.d.ts +119 -0
  33. package/dist/src/core/context/compaction-handler.d.ts.map +1 -0
  34. package/dist/src/core/context/compaction-handler.js +306 -0
  35. package/dist/src/core/context/compaction-handler.js.map +1 -0
  36. package/dist/src/core/context/model-aware-compaction.d.ts +101 -0
  37. package/dist/src/core/context/model-aware-compaction.d.ts.map +1 -0
  38. package/dist/src/core/context/model-aware-compaction.js +616 -0
  39. package/dist/src/core/context/model-aware-compaction.js.map +1 -0
  40. package/dist/src/core/query/query-parser.d.ts +104 -0
  41. package/dist/src/core/query/query-parser.d.ts.map +1 -0
  42. package/dist/src/core/query/query-parser.js +347 -0
  43. package/dist/src/core/query/query-parser.js.map +1 -0
  44. package/dist/src/core/retrieval/index.d.ts +8 -0
  45. package/dist/src/core/retrieval/index.d.ts.map +1 -0
  46. package/dist/src/core/retrieval/index.js +8 -0
  47. package/dist/src/core/retrieval/index.js.map +1 -0
  48. package/dist/src/core/retrieval/llm-context-retrieval.d.ts +71 -0
  49. package/dist/src/core/retrieval/llm-context-retrieval.d.ts.map +1 -0
  50. package/dist/src/core/retrieval/llm-context-retrieval.js +545 -0
  51. package/dist/src/core/retrieval/llm-context-retrieval.js.map +1 -0
  52. package/dist/src/core/retrieval/summary-generator.d.ts +63 -0
  53. package/dist/src/core/retrieval/summary-generator.d.ts.map +1 -0
  54. package/dist/src/core/retrieval/summary-generator.js +622 -0
  55. package/dist/src/core/retrieval/summary-generator.js.map +1 -0
  56. package/dist/src/core/retrieval/types.d.ts +257 -0
  57. package/dist/src/core/retrieval/types.d.ts.map +1 -0
  58. package/dist/src/core/retrieval/types.js +18 -0
  59. package/dist/src/core/retrieval/types.js.map +1 -0
  60. package/dist/src/core/trace/trace-detector.d.ts +108 -0
  61. package/dist/src/core/trace/trace-detector.d.ts.map +1 -0
  62. package/dist/src/core/trace/trace-detector.demo.d.ts +5 -0
  63. package/dist/src/core/trace/trace-detector.demo.d.ts.map +1 -0
  64. package/dist/src/core/trace/trace-detector.demo.js +145 -0
  65. package/dist/src/core/trace/trace-detector.demo.js.map +1 -0
  66. package/dist/src/core/trace/trace-detector.js +425 -0
  67. package/dist/src/core/trace/trace-detector.js.map +1 -0
  68. package/dist/src/core/trace/trace-store.d.ts +60 -0
  69. package/dist/src/core/trace/trace-store.d.ts.map +1 -0
  70. package/dist/src/core/trace/trace-store.js +323 -0
  71. package/dist/src/core/trace/trace-store.js.map +1 -0
  72. package/dist/src/core/trace/types.d.ts +81 -0
  73. package/dist/src/core/trace/types.d.ts.map +1 -0
  74. package/dist/src/core/trace/types.js +70 -0
  75. package/dist/src/core/trace/types.js.map +1 -0
  76. package/dist/src/integrations/linear/sync-manager.d.ts +76 -0
  77. package/dist/src/integrations/linear/sync-manager.d.ts.map +1 -0
  78. package/dist/src/integrations/linear/sync-manager.js +223 -0
  79. package/dist/src/integrations/linear/sync-manager.js.map +1 -0
  80. package/dist/src/integrations/mcp/server.d.ts +8 -0
  81. package/dist/src/integrations/mcp/server.d.ts.map +1 -1
  82. package/dist/src/integrations/mcp/server.js +368 -16
  83. package/dist/src/integrations/mcp/server.js.map +1 -1
  84. package/dist/src/integrations/mcp/trace-test.d.ts +5 -0
  85. package/dist/src/integrations/mcp/trace-test.d.ts.map +1 -0
  86. package/dist/src/integrations/mcp/trace-test.js +54 -0
  87. package/dist/src/integrations/mcp/trace-test.js.map +1 -0
  88. package/dist/src/services/config-service.d.ts +1 -1
  89. package/dist/src/services/config-service.d.ts.map +1 -1
  90. package/dist/src/services/config-service.js.map +1 -1
  91. package/dist/src/types/task.d.ts +11 -1
  92. package/dist/src/types/task.d.ts.map +1 -1
  93. package/dist/src/utils/logger.d.ts +4 -4
  94. package/dist/src/utils/logger.d.ts.map +1 -1
  95. package/dist/src/utils/logger.js.map +1 -1
  96. package/package.json +9 -8
  97. package/dist/attention-scoring/src/attention-tracker.d.ts +0 -79
  98. package/dist/attention-scoring/src/attention-tracker.d.ts.map +0 -1
  99. package/dist/attention-scoring/src/attention-tracker.js +0 -488
  100. package/dist/attention-scoring/src/attention-tracker.js.map +0 -1
  101. package/dist/attention-scoring/src/mcp-integration.d.ts +0 -56
  102. package/dist/attention-scoring/src/mcp-integration.d.ts.map +0 -1
  103. package/dist/attention-scoring/src/mcp-integration.js +0 -369
  104. package/dist/attention-scoring/src/mcp-integration.js.map +0 -1
  105. package/dist/index.js +0 -382
  106. package/dist/p2p-sync/src/p2p-sync.d.ts +0 -81
  107. package/dist/p2p-sync/src/p2p-sync.d.ts.map +0 -1
  108. package/dist/p2p-sync/src/p2p-sync.js +0 -457
  109. package/dist/p2p-sync/src/p2p-sync.js.map +0 -1
  110. package/dist/p2p-sync/src/team-context-sync.d.ts +0 -99
  111. package/dist/p2p-sync/src/team-context-sync.d.ts.map +0 -1
  112. package/dist/p2p-sync/src/team-context-sync.js +0 -491
  113. package/dist/p2p-sync/src/team-context-sync.js.map +0 -1
  114. package/dist/scripts/merge-linear-duplicates.d.ts +0 -7
  115. package/dist/scripts/merge-linear-duplicates.d.ts.map +0 -1
  116. package/dist/scripts/merge-linear-duplicates.js +0 -126
  117. package/dist/scripts/merge-linear-duplicates.js.map +0 -1
  118. package/dist/src/analytics/api/analytics-api.d.ts +0 -24
  119. package/dist/src/analytics/api/analytics-api.d.ts.map +0 -1
  120. package/dist/src/analytics/api/analytics-api.js +0 -279
  121. package/dist/src/analytics/api/analytics-api.js.map +0 -1
  122. package/dist/src/analytics/core/analytics-service.d.ts +0 -23
  123. package/dist/src/analytics/core/analytics-service.d.ts.map +0 -1
  124. package/dist/src/analytics/core/analytics-service.js +0 -160
  125. package/dist/src/analytics/core/analytics-service.js.map +0 -1
  126. package/dist/src/analytics/index.d.ts +0 -12
  127. package/dist/src/analytics/index.d.ts.map +0 -1
  128. package/dist/src/analytics/index.js +0 -11
  129. package/dist/src/analytics/index.js.map +0 -1
  130. package/dist/src/analytics/queries/metrics-queries.d.ts +0 -11
  131. package/dist/src/analytics/queries/metrics-queries.d.ts.map +0 -1
  132. package/dist/src/analytics/queries/metrics-queries.js +0 -179
  133. package/dist/src/analytics/queries/metrics-queries.js.map +0 -1
  134. package/dist/src/analytics/types/metrics.d.ts +0 -60
  135. package/dist/src/analytics/types/metrics.d.ts.map +0 -1
  136. package/dist/src/analytics/types/metrics.js +0 -2
  137. package/dist/src/analytics/types/metrics.js.map +0 -1
  138. package/dist/src/beads/beads-task-store.d.ts +0 -117
  139. package/dist/src/beads/beads-task-store.d.ts.map +0 -1
  140. package/dist/src/beads/beads-task-store.js +0 -318
  141. package/dist/src/beads/beads-task-store.js.map +0 -1
  142. package/dist/src/beads/task-aware-context.d.ts +0 -103
  143. package/dist/src/beads/task-aware-context.d.ts.map +0 -1
  144. package/dist/src/beads/task-aware-context.js +0 -395
  145. package/dist/src/beads/task-aware-context.js.map +0 -1
  146. package/dist/src/beads-task-store.d.ts +0 -117
  147. package/dist/src/beads-task-store.d.ts.map +0 -1
  148. package/dist/src/beads-task-store.js +0 -318
  149. package/dist/src/beads-task-store.js.map +0 -1
  150. package/dist/src/cli/__tests__/index.test.d.ts +0 -5
  151. package/dist/src/cli/__tests__/index.test.d.ts.map +0 -1
  152. package/dist/src/cli/__tests__/index.test.js +0 -726
  153. package/dist/src/cli/__tests__/index.test.js.map +0 -1
  154. package/dist/src/cli/analytics-viewer.d.ts +0 -3
  155. package/dist/src/cli/analytics-viewer.d.ts.map +0 -1
  156. package/dist/src/cli/analytics-viewer.js +0 -89
  157. package/dist/src/cli/analytics-viewer.js.map +0 -1
  158. package/dist/src/cli/cli.d.ts +0 -7
  159. package/dist/src/cli/cli.d.ts.map +0 -1
  160. package/dist/src/cli/cli.js +0 -704
  161. package/dist/src/cli/cli.js.map +0 -1
  162. package/dist/src/cli/project-commands.d.ts +0 -8
  163. package/dist/src/cli/project-commands.d.ts.map +0 -1
  164. package/dist/src/cli/project-commands.js +0 -212
  165. package/dist/src/cli/project-commands.js.map +0 -1
  166. package/dist/src/cli.d.ts +0 -7
  167. package/dist/src/cli.d.ts.map +0 -1
  168. package/dist/src/cli.js +0 -73
  169. package/dist/src/cli.js.map +0 -1
  170. package/dist/src/core/context/__tests__/frame-manager.test.d.ts +0 -5
  171. package/dist/src/core/context/__tests__/frame-manager.test.d.ts.map +0 -1
  172. package/dist/src/core/context/__tests__/frame-manager.test.js +0 -892
  173. package/dist/src/core/context/__tests__/frame-manager.test.js.map +0 -1
  174. package/dist/src/core/error-handler.d.ts +0 -46
  175. package/dist/src/core/error-handler.d.ts.map +0 -1
  176. package/dist/src/core/error-handler.js +0 -212
  177. package/dist/src/core/error-handler.js.map +0 -1
  178. package/dist/src/core/errors/__tests__/error-handling.test.d.ts +0 -5
  179. package/dist/src/core/errors/__tests__/error-handling.test.d.ts.map +0 -1
  180. package/dist/src/core/errors/__tests__/error-handling.test.js +0 -239
  181. package/dist/src/core/errors/__tests__/error-handling.test.js.map +0 -1
  182. package/dist/src/core/frame-manager.d.ts +0 -106
  183. package/dist/src/core/frame-manager.d.ts.map +0 -1
  184. package/dist/src/core/frame-manager.js +0 -387
  185. package/dist/src/core/frame-manager.js.map +0 -1
  186. package/dist/src/core/logger.d.ts +0 -24
  187. package/dist/src/core/logger.d.ts.map +0 -1
  188. package/dist/src/core/logger.js +0 -121
  189. package/dist/src/core/logger.js.map +0 -1
  190. package/dist/src/core/logger.test.d.ts +0 -2
  191. package/dist/src/core/logger.test.d.ts.map +0 -1
  192. package/dist/src/core/logger.test.js +0 -31
  193. package/dist/src/core/logger.test.js.map +0 -1
  194. package/dist/src/core/progress-tracker.d.ts +0 -95
  195. package/dist/src/core/progress-tracker.d.ts.map +0 -1
  196. package/dist/src/core/progress-tracker.js +0 -178
  197. package/dist/src/core/progress-tracker.js.map +0 -1
  198. package/dist/src/core/project-manager.d.ts +0 -130
  199. package/dist/src/core/project-manager.d.ts.map +0 -1
  200. package/dist/src/core/project-manager.js +0 -582
  201. package/dist/src/core/project-manager.js.map +0 -1
  202. package/dist/src/core/update-checker.d.ts +0 -38
  203. package/dist/src/core/update-checker.d.ts.map +0 -1
  204. package/dist/src/core/update-checker.js +0 -156
  205. package/dist/src/core/update-checker.js.map +0 -1
  206. package/dist/src/error-handler.d.ts +0 -42
  207. package/dist/src/error-handler.d.ts.map +0 -1
  208. package/dist/src/error-handler.js +0 -155
  209. package/dist/src/error-handler.js.map +0 -1
  210. package/dist/src/features/tasks/__tests__/pebbles-task-store.test.d.ts +0 -5
  211. package/dist/src/features/tasks/__tests__/pebbles-task-store.test.d.ts.map +0 -1
  212. package/dist/src/features/tasks/__tests__/pebbles-task-store.test.js +0 -712
  213. package/dist/src/features/tasks/__tests__/pebbles-task-store.test.js.map +0 -1
  214. package/dist/src/frame-manager.d.ts +0 -106
  215. package/dist/src/frame-manager.d.ts.map +0 -1
  216. package/dist/src/frame-manager.js +0 -361
  217. package/dist/src/frame-manager.js.map +0 -1
  218. package/dist/src/integrations/browser-mcp.d.ts +0 -94
  219. package/dist/src/integrations/browser-mcp.d.ts.map +0 -1
  220. package/dist/src/integrations/browser-mcp.js +0 -431
  221. package/dist/src/integrations/browser-mcp.js.map +0 -1
  222. package/dist/src/integrations/linear/__tests__/auth.test.d.ts +0 -5
  223. package/dist/src/integrations/linear/__tests__/auth.test.d.ts.map +0 -1
  224. package/dist/src/integrations/linear/__tests__/auth.test.js +0 -517
  225. package/dist/src/integrations/linear/__tests__/auth.test.js.map +0 -1
  226. package/dist/src/integrations/linear/__tests__/sync-service.test.d.ts +0 -5
  227. package/dist/src/integrations/linear/__tests__/sync-service.test.d.ts.map +0 -1
  228. package/dist/src/integrations/linear/__tests__/sync-service.test.js +0 -700
  229. package/dist/src/integrations/linear/__tests__/sync-service.test.js.map +0 -1
  230. package/dist/src/integrations/linear-auth.d.ts +0 -99
  231. package/dist/src/integrations/linear-auth.d.ts.map +0 -1
  232. package/dist/src/integrations/linear-auth.js +0 -319
  233. package/dist/src/integrations/linear-auth.js.map +0 -1
  234. package/dist/src/integrations/linear-auto-sync.d.ts +0 -77
  235. package/dist/src/integrations/linear-auto-sync.d.ts.map +0 -1
  236. package/dist/src/integrations/linear-auto-sync.js +0 -268
  237. package/dist/src/integrations/linear-auto-sync.js.map +0 -1
  238. package/dist/src/integrations/linear-client.d.ts +0 -86
  239. package/dist/src/integrations/linear-client.d.ts.map +0 -1
  240. package/dist/src/integrations/linear-client.js +0 -277
  241. package/dist/src/integrations/linear-client.js.map +0 -1
  242. package/dist/src/integrations/linear-config.d.ts +0 -51
  243. package/dist/src/integrations/linear-config.d.ts.map +0 -1
  244. package/dist/src/integrations/linear-config.js +0 -103
  245. package/dist/src/integrations/linear-config.js.map +0 -1
  246. package/dist/src/integrations/linear-sync.d.ts +0 -97
  247. package/dist/src/integrations/linear-sync.d.ts.map +0 -1
  248. package/dist/src/integrations/linear-sync.js +0 -391
  249. package/dist/src/integrations/linear-sync.js.map +0 -1
  250. package/dist/src/integrations/mcp/__tests__/server.test.d.ts +0 -5
  251. package/dist/src/integrations/mcp/__tests__/server.test.d.ts.map +0 -1
  252. package/dist/src/integrations/mcp/__tests__/server.test.js +0 -790
  253. package/dist/src/integrations/mcp/__tests__/server.test.js.map +0 -1
  254. package/dist/src/logger.d.ts +0 -24
  255. package/dist/src/logger.d.ts.map +0 -1
  256. package/dist/src/logger.js +0 -120
  257. package/dist/src/logger.js.map +0 -1
  258. package/dist/src/mcp/mcp-server.d.ts +0 -40
  259. package/dist/src/mcp/mcp-server.d.ts.map +0 -1
  260. package/dist/src/mcp/mcp-server.js +0 -828
  261. package/dist/src/mcp/mcp-server.js.map +0 -1
  262. package/dist/src/mcp-server.d.ts +0 -32
  263. package/dist/src/mcp-server.d.ts.map +0 -1
  264. package/dist/src/mcp-server.js +0 -441
  265. package/dist/src/mcp-server.js.map +0 -1
  266. package/dist/src/pebbles/pebbles-task-store.d.ts +0 -117
  267. package/dist/src/pebbles/pebbles-task-store.d.ts.map +0 -1
  268. package/dist/src/pebbles/pebbles-task-store.js +0 -335
  269. package/dist/src/pebbles/pebbles-task-store.js.map +0 -1
  270. package/dist/src/pebbles/task-aware-context.d.ts +0 -103
  271. package/dist/src/pebbles/task-aware-context.d.ts.map +0 -1
  272. package/dist/src/pebbles/task-aware-context.js +0 -412
  273. package/dist/src/pebbles/task-aware-context.js.map +0 -1
  274. package/dist/src/railway/index.d.ts +0 -7
  275. package/dist/src/railway/index.d.ts.map +0 -1
  276. package/dist/src/railway/index.js +0 -401
  277. package/dist/src/railway/index.js.map +0 -1
  278. package/dist/src/runway/auth/auth-middleware.d.ts +0 -66
  279. package/dist/src/runway/auth/auth-middleware.d.ts.map +0 -1
  280. package/dist/src/runway/auth/auth-middleware.js +0 -337
  281. package/dist/src/runway/auth/auth-middleware.js.map +0 -1
  282. package/dist/src/runway/server/runway-mcp-server.d.ts +0 -46
  283. package/dist/src/runway/server/runway-mcp-server.d.ts.map +0 -1
  284. package/dist/src/runway/server/runway-mcp-server.js +0 -601
  285. package/dist/src/runway/server/runway-mcp-server.js.map +0 -1
  286. package/dist/src/runway.bak/auth/auth-middleware.d.ts +0 -66
  287. package/dist/src/runway.bak/auth/auth-middleware.d.ts.map +0 -1
  288. package/dist/src/runway.bak/auth/auth-middleware.js +0 -337
  289. package/dist/src/runway.bak/auth/auth-middleware.js.map +0 -1
  290. package/dist/src/runway.bak/server/runway-mcp-server.d.ts +0 -46
  291. package/dist/src/runway.bak/server/runway-mcp-server.d.ts.map +0 -1
  292. package/dist/src/runway.bak/server/runway-mcp-server.js +0 -601
  293. package/dist/src/runway.bak/server/runway-mcp-server.js.map +0 -1
  294. package/dist/src/task-aware-context.d.ts +0 -103
  295. package/dist/src/task-aware-context.d.ts.map +0 -1
  296. package/dist/src/task-aware-context.js +0 -395
  297. package/dist/src/task-aware-context.js.map +0 -1
@@ -1,726 +0,0 @@
1
- /**
2
- * Tests for StackMemory CLI Commands
3
- */
4
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
5
- import { program } from 'commander';
6
- import { join } from 'path';
7
- import { mkdtempSync, rmSync, writeFileSync, existsSync, mkdirSync } from 'fs';
8
- import { tmpdir } from 'os';
9
- // Mock dependencies
10
- vi.mock('../core/monitoring/logger', () => ({
11
- logger: {
12
- info: vi.fn(),
13
- error: vi.fn(),
14
- debug: vi.fn(),
15
- warn: vi.fn()
16
- }
17
- }));
18
- vi.mock('better-sqlite3', () => ({
19
- default: vi.fn().mockImplementation(() => ({
20
- exec: vi.fn(),
21
- prepare: vi.fn(() => ({
22
- run: vi.fn(),
23
- get: vi.fn(),
24
- all: vi.fn(() => [])
25
- })),
26
- close: vi.fn()
27
- }))
28
- }));
29
- vi.mock('../core/context/frame-manager', () => ({
30
- FrameManager: vi.fn().mockImplementation(() => ({
31
- createFrame: vi.fn(() => 'frame-123'),
32
- getActiveFramePath: vi.fn(() => []),
33
- getStackDepth: vi.fn(() => 0),
34
- getHotStackContext: vi.fn(() => [])
35
- }))
36
- }));
37
- vi.mock('../features/tasks/pebbles-task-store.js', () => ({
38
- PebblesTaskStore: vi.fn().mockImplementation(() => ({
39
- createTask: vi.fn(() => 'task-123'),
40
- getActiveTasks: vi.fn(() => []),
41
- getMetrics: vi.fn(() => ({
42
- total_tasks: 0,
43
- completion_rate: 0,
44
- blocked_tasks: 0
45
- }))
46
- }))
47
- }));
48
- vi.mock('../integrations/linear/auth', () => ({
49
- LinearAuthManager: vi.fn().mockImplementation(() => ({
50
- isConfigured: vi.fn(() => false),
51
- loadConfig: vi.fn(),
52
- loadTokens: vi.fn()
53
- })),
54
- LinearOAuthSetup: vi.fn().mockImplementation(() => ({
55
- setupInteractive: vi.fn(),
56
- completeAuth: vi.fn(),
57
- testConnection: vi.fn()
58
- }))
59
- }));
60
- vi.mock('../integrations/linear/sync', () => ({
61
- LinearSyncEngine: vi.fn().mockImplementation(() => ({
62
- sync: vi.fn(() => ({
63
- success: true,
64
- synced: { toLinear: 1, fromLinear: 2, updated: 0 },
65
- conflicts: [],
66
- errors: []
67
- }))
68
- })),
69
- DEFAULT_SYNC_CONFIG: {
70
- enabled: true,
71
- direction: 'bidirectional'
72
- }
73
- }));
74
- vi.mock('../core/utils/update-checker', () => ({
75
- UpdateChecker: {
76
- checkForUpdates: vi.fn(),
77
- forceCheck: vi.fn()
78
- }
79
- }));
80
- vi.mock('../core/monitoring/progress-tracker', () => ({
81
- ProgressTracker: vi.fn().mockImplementation(() => ({
82
- getSummary: vi.fn(() => 'Progress summary'),
83
- updateLinearStatus: vi.fn()
84
- }))
85
- }));
86
- // Mock child_process for git operations
87
- vi.mock('child_process', () => ({
88
- execSync: vi.fn(() => Buffer.from('mock git output'))
89
- }));
90
- // Mock the command registration functions
91
- vi.mock('./commands/projects', () => ({
92
- registerProjectCommands: vi.fn()
93
- }));
94
- vi.mock('./commands/linear', () => ({
95
- registerLinearCommands: vi.fn()
96
- }));
97
- vi.mock('./commands/linear-test', () => ({
98
- registerLinearTestCommand: vi.fn()
99
- }));
100
- vi.mock('./commands/session', () => ({
101
- createSessionCommands: vi.fn()
102
- }));
103
- vi.mock('./commands/worktree', () => ({
104
- registerWorktreeCommands: vi.fn()
105
- }));
106
- vi.mock('./commands/onboard', () => ({
107
- registerOnboardingCommand: vi.fn()
108
- }));
109
- vi.mock('./commands/webhook', () => ({
110
- webhookCommand: vi.fn(() => ({ name: 'webhook' }))
111
- }));
112
- vi.mock('../core/projects/project-manager.js', () => ({
113
- ProjectManager: {
114
- getInstance: vi.fn(() => ({
115
- detectProject: vi.fn()
116
- }))
117
- }
118
- }));
119
- vi.mock('../core/session/index.js', () => ({
120
- sessionManager: {
121
- initialize: vi.fn(),
122
- getOrCreateSession: vi.fn(() => ({
123
- sessionId: 'test-session-123',
124
- projectId: 'test-project',
125
- state: 'active',
126
- startedAt: Date.now() - 600000, // 10 minutes ago
127
- branch: 'main'
128
- })),
129
- listSessions: vi.fn(() => [])
130
- },
131
- FrameQueryMode: {
132
- CURRENT_SESSION: 'current_session',
133
- ALL_ACTIVE: 'all_active',
134
- PROJECT_ACTIVE: 'project_active',
135
- HISTORICAL: 'historical'
136
- }
137
- }));
138
- describe('CLI Commands', () => {
139
- let tempDir;
140
- let originalCwd;
141
- let originalArgv;
142
- let consoleSpy;
143
- beforeEach(() => {
144
- // Setup temp directory
145
- tempDir = mkdtempSync(join(tmpdir(), 'stackmemory-cli-test-'));
146
- originalCwd = process.cwd();
147
- originalArgv = [...process.argv];
148
- // Mock process.cwd() to return our temp directory
149
- vi.spyOn(process, 'cwd').mockReturnValue(tempDir);
150
- // Mock console methods
151
- consoleSpy = {
152
- log: vi.spyOn(console, 'log').mockImplementation(() => { }),
153
- error: vi.spyOn(console, 'error').mockImplementation(() => { }),
154
- };
155
- // Mock process.exit to prevent tests from exiting
156
- vi.spyOn(process, 'exit').mockImplementation(() => {
157
- throw new Error('process.exit() called');
158
- });
159
- // Clear commander program
160
- program.commands.length = 0;
161
- program.options.length = 0;
162
- });
163
- afterEach(() => {
164
- // Restore original state
165
- vi.spyOn(process, 'cwd').mockRestore();
166
- process.argv = originalArgv;
167
- consoleSpy.log.mockRestore();
168
- consoleSpy.error.mockRestore();
169
- vi.spyOn(process, 'exit').mockRestore();
170
- // Cleanup temp directory
171
- if (tempDir) {
172
- rmSync(tempDir, { recursive: true, force: true });
173
- }
174
- vi.clearAllMocks();
175
- });
176
- describe('init command', () => {
177
- beforeEach(async () => {
178
- // Dynamically import to get fresh instance
179
- delete require.cache[require.resolve('../index.js')];
180
- await import('../index.js');
181
- });
182
- it('should initialize StackMemory in current directory', async () => {
183
- process.argv = ['node', 'stackmemory', 'init'];
184
- try {
185
- await program.parseAsync();
186
- }
187
- catch (error) {
188
- // Expect process.exit to be called
189
- expect(error.message).toBe('process.exit() called');
190
- }
191
- const stackmemoryDir = join(tempDir, '.stackmemory');
192
- expect(existsSync(stackmemoryDir)).toBe(true);
193
- expect(consoleSpy.log).toHaveBeenCalledWith('✅ StackMemory initialized in', tempDir);
194
- });
195
- it('should handle initialization errors', async () => {
196
- // Mock FrameManager to throw error
197
- const { FrameManager } = await import('../core/context/frame-manager');
198
- FrameManager.mockImplementationOnce(() => {
199
- throw new Error('Database error');
200
- });
201
- process.argv = ['node', 'stackmemory', 'init'];
202
- try {
203
- await program.parseAsync();
204
- }
205
- catch (error) {
206
- expect(error.message).toBe('process.exit() called');
207
- }
208
- expect(consoleSpy.error).toHaveBeenCalledWith('❌ Initialization failed:', 'Database error');
209
- });
210
- });
211
- describe('status command', () => {
212
- beforeEach(async () => {
213
- // Create a test database file
214
- const dbDir = join(tempDir, '.stackmemory');
215
- mkdirSync(dbDir, { recursive: true });
216
- writeFileSync(join(dbDir, 'context.db'), '');
217
- delete require.cache[require.resolve('../index.js')];
218
- await import('../index.js');
219
- });
220
- it('should show status when StackMemory is initialized', async () => {
221
- process.argv = ['node', 'stackmemory', 'status'];
222
- await program.parseAsync();
223
- expect(consoleSpy.log).toHaveBeenCalledWith('📊 StackMemory Status:');
224
- });
225
- it('should show error when StackMemory is not initialized', async () => {
226
- // Remove the database file
227
- rmSync(join(tempDir, '.stackmemory'), { recursive: true });
228
- process.argv = ['node', 'stackmemory', 'status'];
229
- await program.parseAsync();
230
- expect(consoleSpy.log).toHaveBeenCalledWith('❌ StackMemory not initialized. Run "stackmemory init" first.');
231
- });
232
- it('should handle --all option', async () => {
233
- process.argv = ['node', 'stackmemory', 'status', '--all'];
234
- await program.parseAsync();
235
- expect(consoleSpy.log).toHaveBeenCalledWith('📊 StackMemory Status:');
236
- });
237
- it('should handle --project option', async () => {
238
- process.argv = ['node', 'stackmemory', 'status', '--project'];
239
- await program.parseAsync();
240
- expect(consoleSpy.log).toHaveBeenCalledWith('📊 StackMemory Status:');
241
- });
242
- it('should handle --session option', async () => {
243
- process.argv = ['node', 'stackmemory', 'status', '--session', 'test-session-id'];
244
- await program.parseAsync();
245
- expect(consoleSpy.log).toHaveBeenCalledWith('📊 StackMemory Status:');
246
- });
247
- it('should handle status check errors', async () => {
248
- // Mock FrameManager to throw error
249
- const { FrameManager } = await import('../core/context/frame-manager');
250
- FrameManager.mockImplementationOnce(() => {
251
- throw new Error('Status error');
252
- });
253
- process.argv = ['node', 'stackmemory', 'status'];
254
- try {
255
- await program.parseAsync();
256
- }
257
- catch (error) {
258
- expect(error.message).toBe('process.exit() called');
259
- }
260
- expect(consoleSpy.error).toHaveBeenCalledWith('❌ Status check failed:', 'Status error');
261
- });
262
- });
263
- describe('Linear commands', () => {
264
- beforeEach(async () => {
265
- delete require.cache[require.resolve('../index.js')];
266
- await import('../index.js');
267
- });
268
- describe('linear setup', () => {
269
- it('should setup Linear OAuth integration', async () => {
270
- const { LinearOAuthSetup } = await import('../integrations/linear/auth');
271
- const mockSetup = LinearOAuthSetup;
272
- mockSetup.mockImplementation(() => ({
273
- setupInteractive: vi.fn().mockResolvedValue({
274
- authUrl: 'https://linear.app/oauth/authorize?client_id=test',
275
- instructions: [
276
- 'Step 1: Visit the authorization URL',
277
- 'Step 2: Complete authorization'
278
- ]
279
- })
280
- }));
281
- process.argv = ['node', 'stackmemory', 'linear', 'setup'];
282
- await program.parseAsync();
283
- expect(consoleSpy.log).toHaveBeenCalledWith('🔗 Linear OAuth Setup\n');
284
- });
285
- it('should handle setup errors', async () => {
286
- const { LinearOAuthSetup } = await import('../integrations/linear/auth');
287
- const mockSetup = LinearOAuthSetup;
288
- mockSetup.mockImplementation(() => ({
289
- setupInteractive: vi.fn().mockRejectedValue(new Error('Setup failed'))
290
- }));
291
- process.argv = ['node', 'stackmemory', 'linear', 'setup'];
292
- try {
293
- await program.parseAsync();
294
- }
295
- catch (error) {
296
- expect(error.message).toBe('process.exit() called');
297
- }
298
- expect(consoleSpy.error).toHaveBeenCalledWith('❌ Setup failed:', 'Setup failed');
299
- });
300
- });
301
- describe('linear authorize', () => {
302
- it('should complete Linear authorization', async () => {
303
- const { LinearOAuthSetup } = await import('../integrations/linear/auth');
304
- const mockSetup = LinearOAuthSetup;
305
- mockSetup.mockImplementation(() => ({
306
- completeAuth: vi.fn().mockResolvedValue(true),
307
- testConnection: vi.fn().mockResolvedValue(true)
308
- }));
309
- process.argv = ['node', 'stackmemory', 'linear', 'authorize', 'auth-code-123'];
310
- await program.parseAsync();
311
- expect(consoleSpy.log).toHaveBeenCalledWith('✅ Linear integration authorized successfully!');
312
- expect(consoleSpy.log).toHaveBeenCalledWith('✅ Linear connection test passed!');
313
- });
314
- it('should handle authorization failure', async () => {
315
- const { LinearOAuthSetup } = await import('../integrations/linear/auth');
316
- const mockSetup = LinearOAuthSetup;
317
- mockSetup.mockImplementation(() => ({
318
- completeAuth: vi.fn().mockResolvedValue(false)
319
- }));
320
- process.argv = ['node', 'stackmemory', 'linear', 'authorize', 'invalid-code'];
321
- try {
322
- await program.parseAsync();
323
- }
324
- catch (error) {
325
- expect(error.message).toBe('process.exit() called');
326
- }
327
- expect(consoleSpy.error).toHaveBeenCalledWith('❌ Authorization failed. Please try again.');
328
- });
329
- it('should handle connection test failure after successful auth', async () => {
330
- const { LinearOAuthSetup } = await import('../integrations/linear/auth');
331
- const mockSetup = LinearOAuthSetup;
332
- mockSetup.mockImplementation(() => ({
333
- completeAuth: vi.fn().mockResolvedValue(true),
334
- testConnection: vi.fn().mockResolvedValue(false)
335
- }));
336
- process.argv = ['node', 'stackmemory', 'linear', 'authorize', 'auth-code-123'];
337
- await program.parseAsync();
338
- expect(consoleSpy.log).toHaveBeenCalledWith('✅ Linear integration authorized successfully!');
339
- expect(consoleSpy.log).toHaveBeenCalledWith('⚠️ Linear connection test failed. Check your configuration.');
340
- });
341
- });
342
- describe('linear status', () => {
343
- it('should show status when not configured', async () => {
344
- process.argv = ['node', 'stackmemory', 'linear', 'status'];
345
- await program.parseAsync();
346
- expect(consoleSpy.log).toHaveBeenCalledWith('📊 Linear Integration Status:');
347
- expect(consoleSpy.log).toHaveBeenCalledWith(' Configured: ❌');
348
- });
349
- it('should show detailed status when configured', async () => {
350
- const { LinearAuthManager } = await import('../integrations/linear/auth');
351
- const mockAuthManager = LinearAuthManager;
352
- mockAuthManager.mockImplementation(() => ({
353
- isConfigured: vi.fn(() => true),
354
- loadConfig: vi.fn(() => ({
355
- clientId: 'test-client-id'
356
- })),
357
- loadTokens: vi.fn(() => ({
358
- accessToken: 'test-token',
359
- expiresAt: Date.now() + 3600000
360
- }))
361
- }));
362
- const { LinearOAuthSetup } = await import('../integrations/linear/auth');
363
- const mockSetup = LinearOAuthSetup;
364
- mockSetup.mockImplementation(() => ({
365
- testConnection: vi.fn().mockResolvedValue(true)
366
- }));
367
- process.argv = ['node', 'stackmemory', 'linear', 'status'];
368
- await program.parseAsync();
369
- expect(consoleSpy.log).toHaveBeenCalledWith(' Configured: ✅');
370
- expect(consoleSpy.log).toHaveBeenCalledWith(' Connection: ✅ OK');
371
- });
372
- });
373
- describe('linear sync', () => {
374
- beforeEach(() => {
375
- // Create database directory for sync commands
376
- const dbDir = join(tempDir, '.stackmemory');
377
- mkdirSync(dbDir, { recursive: true });
378
- writeFileSync(join(dbDir, 'context.db'), '');
379
- });
380
- it('should sync with Linear when configured', async () => {
381
- const { LinearAuthManager } = await import('../integrations/linear/auth');
382
- const mockAuthManager = LinearAuthManager;
383
- mockAuthManager.mockImplementation(() => ({
384
- isConfigured: vi.fn(() => true)
385
- }));
386
- process.argv = ['node', 'stackmemory', 'linear', 'sync'];
387
- await program.parseAsync();
388
- expect(consoleSpy.log).toHaveBeenCalledWith('🔄 Starting bidirectional sync with Linear...');
389
- expect(consoleSpy.log).toHaveBeenCalledWith('✅ Sync completed successfully!');
390
- });
391
- it('should handle sync with custom direction', async () => {
392
- const { LinearAuthManager } = await import('../integrations/linear/auth');
393
- const mockAuthManager = LinearAuthManager;
394
- mockAuthManager.mockImplementation(() => ({
395
- isConfigured: vi.fn(() => true)
396
- }));
397
- process.argv = ['node', 'stackmemory', 'linear', 'sync', '--direction', 'to_linear'];
398
- await program.parseAsync();
399
- expect(consoleSpy.log).toHaveBeenCalledWith('🔄 Starting to_linear sync with Linear...');
400
- });
401
- it('should handle sync errors', async () => {
402
- const { LinearAuthManager } = await import('../integrations/linear/auth');
403
- const mockAuthManager = LinearAuthManager;
404
- mockAuthManager.mockImplementation(() => ({
405
- isConfigured: vi.fn(() => true)
406
- }));
407
- const { LinearSyncEngine } = await import('../integrations/linear/sync');
408
- const mockSyncEngine = LinearSyncEngine;
409
- mockSyncEngine.mockImplementation(() => ({
410
- sync: vi.fn().mockResolvedValue({
411
- success: false,
412
- errors: ['Sync error occurred']
413
- })
414
- }));
415
- process.argv = ['node', 'stackmemory', 'linear', 'sync'];
416
- await program.parseAsync();
417
- expect(consoleSpy.log).toHaveBeenCalledWith('❌ Sync failed');
418
- });
419
- it('should show warning when not configured', async () => {
420
- process.argv = ['node', 'stackmemory', 'linear', 'sync'];
421
- await program.parseAsync();
422
- expect(consoleSpy.log).toHaveBeenCalledWith('❌ Linear not configured. Set LINEAR_API_KEY environment variable or run "stackmemory linear setup" first.');
423
- });
424
- it('should show warning when not initialized', async () => {
425
- rmSync(join(tempDir, '.stackmemory'), { recursive: true });
426
- process.argv = ['node', 'stackmemory', 'linear', 'sync'];
427
- await program.parseAsync();
428
- expect(consoleSpy.log).toHaveBeenCalledWith('❌ StackMemory not initialized. Run "stackmemory init" first.');
429
- });
430
- });
431
- });
432
- describe('context:test command', () => {
433
- beforeEach(() => {
434
- // Create database directory for context commands
435
- const dbDir = join(tempDir, '.stackmemory');
436
- mkdirSync(dbDir, { recursive: true });
437
- writeFileSync(join(dbDir, 'context.db'), '');
438
- });
439
- it('should create test context frames', async () => {
440
- delete require.cache[require.resolve('../index.js')];
441
- await import('../index.js');
442
- const { FrameManager } = await import('../core/context/frame-manager');
443
- const mockFrameManager = FrameManager;
444
- let frameCallCount = 0;
445
- mockFrameManager.mockImplementation(() => ({
446
- createFrame: vi.fn(() => `frame-${++frameCallCount}`),
447
- addEvent: vi.fn(),
448
- closeFrame: vi.fn(),
449
- getStackDepth: vi.fn(() => frameCallCount),
450
- getActiveFramePath: vi.fn(() => [])
451
- }));
452
- process.argv = ['node', 'stackmemory', 'context:test'];
453
- await program.parseAsync();
454
- expect(consoleSpy.log).toHaveBeenCalledWith('📝 Creating test context frames...');
455
- expect(consoleSpy.log).toHaveBeenCalledWith('✅ Test frames created!');
456
- });
457
- it('should handle context test errors', async () => {
458
- delete require.cache[require.resolve('../index.js')];
459
- await import('../index.js');
460
- const { FrameManager } = await import('../core/context/frame-manager');
461
- const mockFrameManager = FrameManager;
462
- mockFrameManager.mockImplementation(() => {
463
- throw new Error('Context test error');
464
- });
465
- process.argv = ['node', 'stackmemory', 'context:test'];
466
- try {
467
- await program.parseAsync();
468
- }
469
- catch (error) {
470
- expect(error.message).toBe('process.exit() called');
471
- }
472
- expect(consoleSpy.error).toHaveBeenCalledWith('❌ Test failed:', 'Context test error');
473
- });
474
- it('should show warning when not initialized', async () => {
475
- rmSync(join(tempDir, '.stackmemory'), { recursive: true });
476
- delete require.cache[require.resolve('../index.js')];
477
- await import('../index.js');
478
- process.argv = ['node', 'stackmemory', 'context:test'];
479
- await program.parseAsync();
480
- expect(consoleSpy.log).toHaveBeenCalledWith('❌ StackMemory not initialized. Run "stackmemory init" first.');
481
- });
482
- });
483
- describe('update-check command', () => {
484
- beforeEach(async () => {
485
- delete require.cache[require.resolve('../index.js')];
486
- await import('../index.js');
487
- });
488
- it('should check for updates', async () => {
489
- const { UpdateChecker } = await import('../core/utils/update-checker');
490
- UpdateChecker.forceCheck = vi.fn().mockResolvedValue(undefined);
491
- process.argv = ['node', 'stackmemory', 'update-check'];
492
- await program.parseAsync();
493
- expect(consoleSpy.log).toHaveBeenCalledWith('🔍 Checking for updates...');
494
- expect(UpdateChecker.forceCheck).toHaveBeenCalled();
495
- });
496
- it('should handle update check errors', async () => {
497
- const { UpdateChecker } = await import('../core/utils/update-checker');
498
- UpdateChecker.forceCheck = vi.fn().mockRejectedValue(new Error('Update check failed'));
499
- process.argv = ['node', 'stackmemory', 'update-check'];
500
- try {
501
- await program.parseAsync();
502
- }
503
- catch (error) {
504
- expect(error.message).toBe('process.exit() called');
505
- }
506
- expect(consoleSpy.error).toHaveBeenCalledWith('❌ Update check failed:', 'Update check failed');
507
- });
508
- });
509
- describe('progress command', () => {
510
- beforeEach(() => {
511
- const dbDir = join(tempDir, '.stackmemory');
512
- mkdirSync(dbDir, { recursive: true });
513
- writeFileSync(join(dbDir, 'context.db'), '');
514
- });
515
- it('should show progress summary', async () => {
516
- delete require.cache[require.resolve('../index.js')];
517
- await import('../index.js');
518
- process.argv = ['node', 'stackmemory', 'progress'];
519
- await program.parseAsync();
520
- expect(consoleSpy.log).toHaveBeenCalledWith('Progress summary');
521
- });
522
- it('should handle progress errors', async () => {
523
- delete require.cache[require.resolve('../index.js')];
524
- await import('../index.js');
525
- const { ProgressTracker } = await import('../core/monitoring/progress-tracker');
526
- const mockProgressTracker = ProgressTracker;
527
- mockProgressTracker.mockImplementation(() => ({
528
- getSummary: vi.fn(() => {
529
- throw new Error('Progress error');
530
- })
531
- }));
532
- process.argv = ['node', 'stackmemory', 'progress'];
533
- try {
534
- await program.parseAsync();
535
- }
536
- catch (error) {
537
- expect(error.message).toBe('process.exit() called');
538
- }
539
- expect(consoleSpy.error).toHaveBeenCalledWith('❌ Failed to show progress:', 'Progress error');
540
- });
541
- it('should show warning when not initialized', async () => {
542
- rmSync(join(tempDir, '.stackmemory'), { recursive: true });
543
- delete require.cache[require.resolve('../index.js')];
544
- await import('../index.js');
545
- process.argv = ['node', 'stackmemory', 'progress'];
546
- await program.parseAsync();
547
- expect(consoleSpy.log).toHaveBeenCalledWith('❌ StackMemory not initialized. Run "stackmemory init" first.');
548
- });
549
- });
550
- describe('mcp-server command', () => {
551
- beforeEach(async () => {
552
- delete require.cache[require.resolve('../index.js')];
553
- });
554
- it('should start MCP server with default options', async () => {
555
- // Mock the MCP server module
556
- vi.doMock('../integrations/mcp/server.js', () => ({
557
- runMCPServer: vi.fn().mockResolvedValue(undefined)
558
- }));
559
- await import('../index.js');
560
- process.argv = ['node', 'stackmemory', 'mcp-server'];
561
- await program.parseAsync();
562
- expect(consoleSpy.log).toHaveBeenCalledWith('🚀 Starting StackMemory MCP Server...');
563
- expect(process.env.PROJECT_ROOT).toBe(tempDir);
564
- });
565
- it('should start MCP server with custom project path', async () => {
566
- const customPath = '/custom/project/path';
567
- vi.doMock('../integrations/mcp/server.js', () => ({
568
- runMCPServer: vi.fn().mockResolvedValue(undefined)
569
- }));
570
- await import('../index.js');
571
- process.argv = ['node', 'stackmemory', 'mcp-server', '--project', customPath];
572
- await program.parseAsync();
573
- expect(consoleSpy.log).toHaveBeenCalledWith(` Project: ${customPath}`);
574
- expect(process.env.PROJECT_ROOT).toBe(customPath);
575
- });
576
- it('should handle MCP server errors', async () => {
577
- vi.doMock('../integrations/mcp/server.js', () => ({
578
- runMCPServer: vi.fn().mockRejectedValue(new Error('MCP server error'))
579
- }));
580
- await import('../index.js');
581
- process.argv = ['node', 'stackmemory', 'mcp-server'];
582
- try {
583
- await program.parseAsync();
584
- }
585
- catch (error) {
586
- expect(error.message).toBe('process.exit() called');
587
- }
588
- expect(consoleSpy.error).toHaveBeenCalledWith('❌ MCP server failed:', 'MCP server error');
589
- });
590
- });
591
- describe('Command registration', () => {
592
- it('should register all command modules', async () => {
593
- const registerProjectCommands = (await import('./commands/projects')).registerProjectCommands;
594
- const registerLinearCommands = (await import('./commands/linear')).registerLinearCommands;
595
- const registerLinearTestCommand = (await import('./commands/linear-test')).registerLinearTestCommand;
596
- const createSessionCommands = (await import('./commands/session')).createSessionCommands;
597
- const registerWorktreeCommands = (await import('./commands/worktree')).registerWorktreeCommands;
598
- const registerOnboardingCommand = (await import('./commands/onboard')).registerOnboardingCommand;
599
- const webhookCommand = (await import('./commands/webhook')).webhookCommand;
600
- delete require.cache[require.resolve('../index.js')];
601
- await import('../index.js');
602
- expect(registerProjectCommands).toHaveBeenCalledWith(expect.any(Object));
603
- expect(registerLinearCommands).toHaveBeenCalledWith(expect.any(Object));
604
- expect(registerLinearTestCommand).toHaveBeenCalledWith(expect.any(Object));
605
- expect(createSessionCommands).toHaveBeenCalledWith(expect.any(Object));
606
- expect(registerWorktreeCommands).toHaveBeenCalledWith(expect.any(Object));
607
- expect(registerOnboardingCommand).toHaveBeenCalledWith(expect.any(Object));
608
- expect(webhookCommand).toHaveBeenCalled();
609
- });
610
- });
611
- describe('Error handling and edge cases', () => {
612
- beforeEach(async () => {
613
- delete require.cache[require.resolve('../index.js')];
614
- await import('../index.js');
615
- });
616
- it('should handle missing command arguments gracefully', async () => {
617
- process.argv = ['node', 'stackmemory'];
618
- await program.parseAsync();
619
- // Should not throw error and should show help
620
- expect(consoleSpy.error).not.toHaveBeenCalled();
621
- });
622
- it('should handle unknown commands gracefully', async () => {
623
- process.argv = ['node', 'stackmemory', 'unknown-command'];
624
- try {
625
- await program.parseAsync();
626
- }
627
- catch (error) {
628
- // Commander will handle unknown commands
629
- expect(error.name).toBe('CommanderError');
630
- }
631
- });
632
- it('should handle interrupted operations gracefully', async () => {
633
- const { FrameManager } = await import('../core/context/frame-manager');
634
- const mockFrameManager = FrameManager;
635
- // Simulate an interruption during initialization
636
- mockFrameManager.mockImplementation(() => {
637
- const error = new Error('Operation interrupted');
638
- error.code = 'EINT';
639
- throw error;
640
- });
641
- const dbDir = join(tempDir, '.stackmemory');
642
- mkdirSync(dbDir, { recursive: true });
643
- writeFileSync(join(dbDir, 'context.db'), '');
644
- process.argv = ['node', 'stackmemory', 'status'];
645
- try {
646
- await program.parseAsync();
647
- }
648
- catch (error) {
649
- expect(error.message).toBe('process.exit() called');
650
- }
651
- });
652
- it('should validate command options properly', async () => {
653
- process.argv = ['node', 'stackmemory', 'linear', 'sync', '--direction', 'invalid-direction'];
654
- const dbDir = join(tempDir, '.stackmemory');
655
- mkdirSync(dbDir, { recursive: true });
656
- writeFileSync(join(dbDir, 'context.db'), '');
657
- // Should handle invalid option values gracefully
658
- await program.parseAsync();
659
- });
660
- it('should handle environment variable issues', async () => {
661
- // Test with missing environment variables
662
- delete process.env.HOME;
663
- delete process.env.USER;
664
- const dbDir = join(tempDir, '.stackmemory');
665
- mkdirSync(dbDir, { recursive: true });
666
- writeFileSync(join(dbDir, 'context.db'), '');
667
- process.argv = ['node', 'stackmemory', 'status'];
668
- // Should still work despite missing env vars
669
- await program.parseAsync();
670
- expect(consoleSpy.log).toHaveBeenCalledWith('📊 StackMemory Status:');
671
- });
672
- });
673
- describe('Integration with external services', () => {
674
- beforeEach(() => {
675
- const dbDir = join(tempDir, '.stackmemory');
676
- mkdirSync(dbDir, { recursive: true });
677
- writeFileSync(join(dbDir, 'context.db'), '');
678
- });
679
- it('should handle network failures in Linear integration', async () => {
680
- delete require.cache[require.resolve('../index.js')];
681
- await import('../index.js');
682
- const { LinearSyncEngine } = await import('../integrations/linear/sync');
683
- const mockSyncEngine = LinearSyncEngine;
684
- mockSyncEngine.mockImplementation(() => ({
685
- sync: vi.fn().mockRejectedValue(new Error('Network timeout'))
686
- }));
687
- const { LinearAuthManager } = await import('../integrations/linear/auth');
688
- const mockAuthManager = LinearAuthManager;
689
- mockAuthManager.mockImplementation(() => ({
690
- isConfigured: vi.fn(() => true)
691
- }));
692
- process.argv = ['node', 'stackmemory', 'linear', 'sync'];
693
- try {
694
- await program.parseAsync();
695
- }
696
- catch (error) {
697
- expect(error.message).toBe('process.exit() called');
698
- }
699
- expect(consoleSpy.error).toHaveBeenCalledWith('❌ Sync failed:', 'Network timeout');
700
- });
701
- it('should handle file system permission issues', async () => {
702
- delete require.cache[require.resolve('../index.js')];
703
- await import('../index.js');
704
- // Mock fs operations to throw permission errors
705
- const originalWriteFileSync = require('fs').writeFileSync;
706
- require('fs').writeFileSync = vi.fn(() => {
707
- const error = new Error('Permission denied');
708
- error.code = 'EACCES';
709
- throw error;
710
- });
711
- try {
712
- process.argv = ['node', 'stackmemory', 'init'];
713
- try {
714
- await program.parseAsync();
715
- }
716
- catch (error) {
717
- expect(error.message).toBe('process.exit() called');
718
- }
719
- }
720
- finally {
721
- require('fs').writeFileSync = originalWriteFileSync;
722
- }
723
- });
724
- });
725
- });
726
- //# sourceMappingURL=index.test.js.map