@stackmemoryai/stackmemory 0.2.7 → 0.2.9

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 (346) 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/digest/hybrid-digest-generator.d.ts +76 -0
  41. package/dist/src/core/digest/hybrid-digest-generator.d.ts.map +1 -0
  42. package/dist/src/core/digest/hybrid-digest-generator.js +629 -0
  43. package/dist/src/core/digest/hybrid-digest-generator.js.map +1 -0
  44. package/dist/src/core/digest/index.d.ts +7 -0
  45. package/dist/src/core/digest/index.d.ts.map +1 -0
  46. package/dist/src/core/digest/index.js +7 -0
  47. package/dist/src/core/digest/index.js.map +1 -0
  48. package/dist/src/core/digest/types.d.ts +154 -0
  49. package/dist/src/core/digest/types.d.ts.map +1 -0
  50. package/dist/src/core/digest/types.js +18 -0
  51. package/dist/src/core/digest/types.js.map +1 -0
  52. package/dist/src/core/monitoring/logger.d.ts +2 -2
  53. package/dist/src/core/monitoring/logger.d.ts.map +1 -1
  54. package/dist/src/core/monitoring/logger.js +10 -5
  55. package/dist/src/core/monitoring/logger.js.map +1 -1
  56. package/dist/src/core/monitoring/metrics.d.ts +3 -0
  57. package/dist/src/core/monitoring/metrics.d.ts.map +1 -1
  58. package/dist/src/core/monitoring/metrics.js +142 -3
  59. package/dist/src/core/monitoring/metrics.js.map +1 -1
  60. package/dist/src/core/persistence/postgres-adapter.d.ts +31 -0
  61. package/dist/src/core/persistence/postgres-adapter.d.ts.map +1 -0
  62. package/dist/src/core/persistence/postgres-adapter.js +316 -0
  63. package/dist/src/core/persistence/postgres-adapter.js.map +1 -0
  64. package/dist/src/core/query/query-parser.d.ts +104 -0
  65. package/dist/src/core/query/query-parser.d.ts.map +1 -0
  66. package/dist/src/core/query/query-parser.js +347 -0
  67. package/dist/src/core/query/query-parser.js.map +1 -0
  68. package/dist/src/core/retrieval/index.d.ts +8 -0
  69. package/dist/src/core/retrieval/index.d.ts.map +1 -0
  70. package/dist/src/core/retrieval/index.js +8 -0
  71. package/dist/src/core/retrieval/index.js.map +1 -0
  72. package/dist/src/core/retrieval/llm-context-retrieval.d.ts +71 -0
  73. package/dist/src/core/retrieval/llm-context-retrieval.d.ts.map +1 -0
  74. package/dist/src/core/retrieval/llm-context-retrieval.js +545 -0
  75. package/dist/src/core/retrieval/llm-context-retrieval.js.map +1 -0
  76. package/dist/src/core/retrieval/summary-generator.d.ts +63 -0
  77. package/dist/src/core/retrieval/summary-generator.d.ts.map +1 -0
  78. package/dist/src/core/retrieval/summary-generator.js +622 -0
  79. package/dist/src/core/retrieval/summary-generator.js.map +1 -0
  80. package/dist/src/core/retrieval/types.d.ts +257 -0
  81. package/dist/src/core/retrieval/types.d.ts.map +1 -0
  82. package/dist/src/core/retrieval/types.js +18 -0
  83. package/dist/src/core/retrieval/types.js.map +1 -0
  84. package/dist/src/core/trace/trace-detector.d.ts +108 -0
  85. package/dist/src/core/trace/trace-detector.d.ts.map +1 -0
  86. package/dist/src/core/trace/trace-detector.demo.d.ts +5 -0
  87. package/dist/src/core/trace/trace-detector.demo.d.ts.map +1 -0
  88. package/dist/src/core/trace/trace-detector.demo.js +145 -0
  89. package/dist/src/core/trace/trace-detector.demo.js.map +1 -0
  90. package/dist/src/core/trace/trace-detector.js +425 -0
  91. package/dist/src/core/trace/trace-detector.js.map +1 -0
  92. package/dist/src/core/trace/trace-store.d.ts +60 -0
  93. package/dist/src/core/trace/trace-store.d.ts.map +1 -0
  94. package/dist/src/core/trace/trace-store.js +323 -0
  95. package/dist/src/core/trace/trace-store.js.map +1 -0
  96. package/dist/src/core/trace/types.d.ts +81 -0
  97. package/dist/src/core/trace/types.d.ts.map +1 -0
  98. package/dist/src/core/trace/types.js +70 -0
  99. package/dist/src/core/trace/types.js.map +1 -0
  100. package/dist/src/core/types.d.ts +35 -0
  101. package/dist/src/core/types.d.ts.map +1 -0
  102. package/dist/src/core/types.js +2 -0
  103. package/dist/src/core/types.js.map +1 -0
  104. package/dist/src/integrations/linear/sync-manager.d.ts +76 -0
  105. package/dist/src/integrations/linear/sync-manager.d.ts.map +1 -0
  106. package/dist/src/integrations/linear/sync-manager.js +223 -0
  107. package/dist/src/integrations/linear/sync-manager.js.map +1 -0
  108. package/dist/src/integrations/mcp/server.d.ts +8 -0
  109. package/dist/src/integrations/mcp/server.d.ts.map +1 -1
  110. package/dist/src/integrations/mcp/server.js +369 -17
  111. package/dist/src/integrations/mcp/server.js.map +1 -1
  112. package/dist/src/integrations/mcp/trace-test.d.ts +5 -0
  113. package/dist/src/integrations/mcp/trace-test.d.ts.map +1 -0
  114. package/dist/src/integrations/mcp/trace-test.js +54 -0
  115. package/dist/src/integrations/mcp/trace-test.js.map +1 -0
  116. package/dist/src/integrations/pg-aiguide/embedding-provider.d.ts +48 -0
  117. package/dist/src/integrations/pg-aiguide/embedding-provider.d.ts.map +1 -0
  118. package/dist/src/integrations/pg-aiguide/embedding-provider.js +190 -0
  119. package/dist/src/integrations/pg-aiguide/embedding-provider.js.map +1 -0
  120. package/dist/src/integrations/pg-aiguide/semantic-search.d.ts +34 -0
  121. package/dist/src/integrations/pg-aiguide/semantic-search.d.ts.map +1 -0
  122. package/dist/src/integrations/pg-aiguide/semantic-search.js +154 -0
  123. package/dist/src/integrations/pg-aiguide/semantic-search.js.map +1 -0
  124. package/dist/src/integrations/pg-aiguide/timescale-analytics.d.ts +44 -0
  125. package/dist/src/integrations/pg-aiguide/timescale-analytics.d.ts.map +1 -0
  126. package/dist/src/integrations/pg-aiguide/timescale-analytics.js +215 -0
  127. package/dist/src/integrations/pg-aiguide/timescale-analytics.js.map +1 -0
  128. package/dist/src/models/user.model.d.ts +55 -0
  129. package/dist/src/models/user.model.d.ts.map +1 -0
  130. package/dist/src/models/user.model.js +263 -0
  131. package/dist/src/models/user.model.js.map +1 -0
  132. package/dist/src/servers/production/auth-middleware.d.ts +7 -0
  133. package/dist/src/servers/production/auth-middleware.d.ts.map +1 -1
  134. package/dist/src/servers/production/auth-middleware.js +201 -26
  135. package/dist/src/servers/production/auth-middleware.js.map +1 -1
  136. package/dist/src/servers/railway/index.js.map +1 -1
  137. package/dist/src/services/config-service.d.ts +1 -1
  138. package/dist/src/services/config-service.d.ts.map +1 -1
  139. package/dist/src/services/config-service.js.map +1 -1
  140. package/dist/src/types/task.d.ts +11 -1
  141. package/dist/src/types/task.d.ts.map +1 -1
  142. package/dist/src/utils/logger.d.ts +4 -4
  143. package/dist/src/utils/logger.d.ts.map +1 -1
  144. package/dist/src/utils/logger.js.map +1 -1
  145. package/package.json +14 -8
  146. package/dist/attention-scoring/src/attention-tracker.d.ts +0 -79
  147. package/dist/attention-scoring/src/attention-tracker.d.ts.map +0 -1
  148. package/dist/attention-scoring/src/attention-tracker.js +0 -488
  149. package/dist/attention-scoring/src/attention-tracker.js.map +0 -1
  150. package/dist/attention-scoring/src/mcp-integration.d.ts +0 -56
  151. package/dist/attention-scoring/src/mcp-integration.d.ts.map +0 -1
  152. package/dist/attention-scoring/src/mcp-integration.js +0 -369
  153. package/dist/attention-scoring/src/mcp-integration.js.map +0 -1
  154. package/dist/index.js +0 -382
  155. package/dist/p2p-sync/src/p2p-sync.d.ts +0 -81
  156. package/dist/p2p-sync/src/p2p-sync.d.ts.map +0 -1
  157. package/dist/p2p-sync/src/p2p-sync.js +0 -457
  158. package/dist/p2p-sync/src/p2p-sync.js.map +0 -1
  159. package/dist/p2p-sync/src/team-context-sync.d.ts +0 -99
  160. package/dist/p2p-sync/src/team-context-sync.d.ts.map +0 -1
  161. package/dist/p2p-sync/src/team-context-sync.js +0 -491
  162. package/dist/p2p-sync/src/team-context-sync.js.map +0 -1
  163. package/dist/scripts/merge-linear-duplicates.d.ts +0 -7
  164. package/dist/scripts/merge-linear-duplicates.d.ts.map +0 -1
  165. package/dist/scripts/merge-linear-duplicates.js +0 -126
  166. package/dist/scripts/merge-linear-duplicates.js.map +0 -1
  167. package/dist/src/analytics/api/analytics-api.d.ts +0 -24
  168. package/dist/src/analytics/api/analytics-api.d.ts.map +0 -1
  169. package/dist/src/analytics/api/analytics-api.js +0 -279
  170. package/dist/src/analytics/api/analytics-api.js.map +0 -1
  171. package/dist/src/analytics/core/analytics-service.d.ts +0 -23
  172. package/dist/src/analytics/core/analytics-service.d.ts.map +0 -1
  173. package/dist/src/analytics/core/analytics-service.js +0 -160
  174. package/dist/src/analytics/core/analytics-service.js.map +0 -1
  175. package/dist/src/analytics/index.d.ts +0 -12
  176. package/dist/src/analytics/index.d.ts.map +0 -1
  177. package/dist/src/analytics/index.js +0 -11
  178. package/dist/src/analytics/index.js.map +0 -1
  179. package/dist/src/analytics/queries/metrics-queries.d.ts +0 -11
  180. package/dist/src/analytics/queries/metrics-queries.d.ts.map +0 -1
  181. package/dist/src/analytics/queries/metrics-queries.js +0 -179
  182. package/dist/src/analytics/queries/metrics-queries.js.map +0 -1
  183. package/dist/src/analytics/types/metrics.d.ts +0 -60
  184. package/dist/src/analytics/types/metrics.d.ts.map +0 -1
  185. package/dist/src/analytics/types/metrics.js +0 -2
  186. package/dist/src/analytics/types/metrics.js.map +0 -1
  187. package/dist/src/beads/beads-task-store.d.ts +0 -117
  188. package/dist/src/beads/beads-task-store.d.ts.map +0 -1
  189. package/dist/src/beads/beads-task-store.js +0 -318
  190. package/dist/src/beads/beads-task-store.js.map +0 -1
  191. package/dist/src/beads/task-aware-context.d.ts +0 -103
  192. package/dist/src/beads/task-aware-context.d.ts.map +0 -1
  193. package/dist/src/beads/task-aware-context.js +0 -395
  194. package/dist/src/beads/task-aware-context.js.map +0 -1
  195. package/dist/src/beads-task-store.d.ts +0 -117
  196. package/dist/src/beads-task-store.d.ts.map +0 -1
  197. package/dist/src/beads-task-store.js +0 -318
  198. package/dist/src/beads-task-store.js.map +0 -1
  199. package/dist/src/cli/__tests__/index.test.d.ts +0 -5
  200. package/dist/src/cli/__tests__/index.test.d.ts.map +0 -1
  201. package/dist/src/cli/__tests__/index.test.js +0 -726
  202. package/dist/src/cli/__tests__/index.test.js.map +0 -1
  203. package/dist/src/cli/analytics-viewer.d.ts +0 -3
  204. package/dist/src/cli/analytics-viewer.d.ts.map +0 -1
  205. package/dist/src/cli/analytics-viewer.js +0 -89
  206. package/dist/src/cli/analytics-viewer.js.map +0 -1
  207. package/dist/src/cli/cli.d.ts +0 -7
  208. package/dist/src/cli/cli.d.ts.map +0 -1
  209. package/dist/src/cli/cli.js +0 -704
  210. package/dist/src/cli/cli.js.map +0 -1
  211. package/dist/src/cli/project-commands.d.ts +0 -8
  212. package/dist/src/cli/project-commands.d.ts.map +0 -1
  213. package/dist/src/cli/project-commands.js +0 -212
  214. package/dist/src/cli/project-commands.js.map +0 -1
  215. package/dist/src/cli.d.ts +0 -7
  216. package/dist/src/cli.d.ts.map +0 -1
  217. package/dist/src/cli.js +0 -73
  218. package/dist/src/cli.js.map +0 -1
  219. package/dist/src/core/context/__tests__/frame-manager.test.d.ts +0 -5
  220. package/dist/src/core/context/__tests__/frame-manager.test.d.ts.map +0 -1
  221. package/dist/src/core/context/__tests__/frame-manager.test.js +0 -892
  222. package/dist/src/core/context/__tests__/frame-manager.test.js.map +0 -1
  223. package/dist/src/core/error-handler.d.ts +0 -46
  224. package/dist/src/core/error-handler.d.ts.map +0 -1
  225. package/dist/src/core/error-handler.js +0 -212
  226. package/dist/src/core/error-handler.js.map +0 -1
  227. package/dist/src/core/errors/__tests__/error-handling.test.d.ts +0 -5
  228. package/dist/src/core/errors/__tests__/error-handling.test.d.ts.map +0 -1
  229. package/dist/src/core/errors/__tests__/error-handling.test.js +0 -239
  230. package/dist/src/core/errors/__tests__/error-handling.test.js.map +0 -1
  231. package/dist/src/core/frame-manager.d.ts +0 -106
  232. package/dist/src/core/frame-manager.d.ts.map +0 -1
  233. package/dist/src/core/frame-manager.js +0 -387
  234. package/dist/src/core/frame-manager.js.map +0 -1
  235. package/dist/src/core/logger.d.ts +0 -24
  236. package/dist/src/core/logger.d.ts.map +0 -1
  237. package/dist/src/core/logger.js +0 -121
  238. package/dist/src/core/logger.js.map +0 -1
  239. package/dist/src/core/logger.test.d.ts +0 -2
  240. package/dist/src/core/logger.test.d.ts.map +0 -1
  241. package/dist/src/core/logger.test.js +0 -31
  242. package/dist/src/core/logger.test.js.map +0 -1
  243. package/dist/src/core/progress-tracker.d.ts +0 -95
  244. package/dist/src/core/progress-tracker.d.ts.map +0 -1
  245. package/dist/src/core/progress-tracker.js +0 -178
  246. package/dist/src/core/progress-tracker.js.map +0 -1
  247. package/dist/src/core/project-manager.d.ts +0 -130
  248. package/dist/src/core/project-manager.d.ts.map +0 -1
  249. package/dist/src/core/project-manager.js +0 -582
  250. package/dist/src/core/project-manager.js.map +0 -1
  251. package/dist/src/core/update-checker.d.ts +0 -38
  252. package/dist/src/core/update-checker.d.ts.map +0 -1
  253. package/dist/src/core/update-checker.js +0 -156
  254. package/dist/src/core/update-checker.js.map +0 -1
  255. package/dist/src/error-handler.d.ts +0 -42
  256. package/dist/src/error-handler.d.ts.map +0 -1
  257. package/dist/src/error-handler.js +0 -155
  258. package/dist/src/error-handler.js.map +0 -1
  259. package/dist/src/features/tasks/__tests__/pebbles-task-store.test.d.ts +0 -5
  260. package/dist/src/features/tasks/__tests__/pebbles-task-store.test.d.ts.map +0 -1
  261. package/dist/src/features/tasks/__tests__/pebbles-task-store.test.js +0 -712
  262. package/dist/src/features/tasks/__tests__/pebbles-task-store.test.js.map +0 -1
  263. package/dist/src/frame-manager.d.ts +0 -106
  264. package/dist/src/frame-manager.d.ts.map +0 -1
  265. package/dist/src/frame-manager.js +0 -361
  266. package/dist/src/frame-manager.js.map +0 -1
  267. package/dist/src/integrations/browser-mcp.d.ts +0 -94
  268. package/dist/src/integrations/browser-mcp.d.ts.map +0 -1
  269. package/dist/src/integrations/browser-mcp.js +0 -431
  270. package/dist/src/integrations/browser-mcp.js.map +0 -1
  271. package/dist/src/integrations/linear/__tests__/auth.test.d.ts +0 -5
  272. package/dist/src/integrations/linear/__tests__/auth.test.d.ts.map +0 -1
  273. package/dist/src/integrations/linear/__tests__/auth.test.js +0 -517
  274. package/dist/src/integrations/linear/__tests__/auth.test.js.map +0 -1
  275. package/dist/src/integrations/linear/__tests__/sync-service.test.d.ts +0 -5
  276. package/dist/src/integrations/linear/__tests__/sync-service.test.d.ts.map +0 -1
  277. package/dist/src/integrations/linear/__tests__/sync-service.test.js +0 -700
  278. package/dist/src/integrations/linear/__tests__/sync-service.test.js.map +0 -1
  279. package/dist/src/integrations/linear-auth.d.ts +0 -99
  280. package/dist/src/integrations/linear-auth.d.ts.map +0 -1
  281. package/dist/src/integrations/linear-auth.js +0 -319
  282. package/dist/src/integrations/linear-auth.js.map +0 -1
  283. package/dist/src/integrations/linear-auto-sync.d.ts +0 -77
  284. package/dist/src/integrations/linear-auto-sync.d.ts.map +0 -1
  285. package/dist/src/integrations/linear-auto-sync.js +0 -268
  286. package/dist/src/integrations/linear-auto-sync.js.map +0 -1
  287. package/dist/src/integrations/linear-client.d.ts +0 -86
  288. package/dist/src/integrations/linear-client.d.ts.map +0 -1
  289. package/dist/src/integrations/linear-client.js +0 -277
  290. package/dist/src/integrations/linear-client.js.map +0 -1
  291. package/dist/src/integrations/linear-config.d.ts +0 -51
  292. package/dist/src/integrations/linear-config.d.ts.map +0 -1
  293. package/dist/src/integrations/linear-config.js +0 -103
  294. package/dist/src/integrations/linear-config.js.map +0 -1
  295. package/dist/src/integrations/linear-sync.d.ts +0 -97
  296. package/dist/src/integrations/linear-sync.d.ts.map +0 -1
  297. package/dist/src/integrations/linear-sync.js +0 -391
  298. package/dist/src/integrations/linear-sync.js.map +0 -1
  299. package/dist/src/integrations/mcp/__tests__/server.test.d.ts +0 -5
  300. package/dist/src/integrations/mcp/__tests__/server.test.d.ts.map +0 -1
  301. package/dist/src/integrations/mcp/__tests__/server.test.js +0 -790
  302. package/dist/src/integrations/mcp/__tests__/server.test.js.map +0 -1
  303. package/dist/src/logger.d.ts +0 -24
  304. package/dist/src/logger.d.ts.map +0 -1
  305. package/dist/src/logger.js +0 -120
  306. package/dist/src/logger.js.map +0 -1
  307. package/dist/src/mcp/mcp-server.d.ts +0 -40
  308. package/dist/src/mcp/mcp-server.d.ts.map +0 -1
  309. package/dist/src/mcp/mcp-server.js +0 -828
  310. package/dist/src/mcp/mcp-server.js.map +0 -1
  311. package/dist/src/mcp-server.d.ts +0 -32
  312. package/dist/src/mcp-server.d.ts.map +0 -1
  313. package/dist/src/mcp-server.js +0 -441
  314. package/dist/src/mcp-server.js.map +0 -1
  315. package/dist/src/pebbles/pebbles-task-store.d.ts +0 -117
  316. package/dist/src/pebbles/pebbles-task-store.d.ts.map +0 -1
  317. package/dist/src/pebbles/pebbles-task-store.js +0 -335
  318. package/dist/src/pebbles/pebbles-task-store.js.map +0 -1
  319. package/dist/src/pebbles/task-aware-context.d.ts +0 -103
  320. package/dist/src/pebbles/task-aware-context.d.ts.map +0 -1
  321. package/dist/src/pebbles/task-aware-context.js +0 -412
  322. package/dist/src/pebbles/task-aware-context.js.map +0 -1
  323. package/dist/src/railway/index.d.ts +0 -7
  324. package/dist/src/railway/index.d.ts.map +0 -1
  325. package/dist/src/railway/index.js +0 -401
  326. package/dist/src/railway/index.js.map +0 -1
  327. package/dist/src/runway/auth/auth-middleware.d.ts +0 -66
  328. package/dist/src/runway/auth/auth-middleware.d.ts.map +0 -1
  329. package/dist/src/runway/auth/auth-middleware.js +0 -337
  330. package/dist/src/runway/auth/auth-middleware.js.map +0 -1
  331. package/dist/src/runway/server/runway-mcp-server.d.ts +0 -46
  332. package/dist/src/runway/server/runway-mcp-server.d.ts.map +0 -1
  333. package/dist/src/runway/server/runway-mcp-server.js +0 -601
  334. package/dist/src/runway/server/runway-mcp-server.js.map +0 -1
  335. package/dist/src/runway.bak/auth/auth-middleware.d.ts +0 -66
  336. package/dist/src/runway.bak/auth/auth-middleware.d.ts.map +0 -1
  337. package/dist/src/runway.bak/auth/auth-middleware.js +0 -337
  338. package/dist/src/runway.bak/auth/auth-middleware.js.map +0 -1
  339. package/dist/src/runway.bak/server/runway-mcp-server.d.ts +0 -46
  340. package/dist/src/runway.bak/server/runway-mcp-server.d.ts.map +0 -1
  341. package/dist/src/runway.bak/server/runway-mcp-server.js +0 -601
  342. package/dist/src/runway.bak/server/runway-mcp-server.js.map +0 -1
  343. package/dist/src/task-aware-context.d.ts +0 -103
  344. package/dist/src/task-aware-context.d.ts.map +0 -1
  345. package/dist/src/task-aware-context.js +0 -395
  346. package/dist/src/task-aware-context.js.map +0 -1
@@ -1,892 +0,0 @@
1
- /**
2
- * Tests for FrameManager - Call Stack Implementation
3
- */
4
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
5
- import Database from 'better-sqlite3';
6
- import { FrameManager } from '../frame-manager';
7
- import { DatabaseError, FrameError, ErrorCode } from '../../errors/index';
8
- import { join } from 'path';
9
- import { mkdtempSync, rmSync } from 'fs';
10
- import { tmpdir } from 'os';
11
- describe('FrameManager', () => {
12
- let db;
13
- let frameManager;
14
- let tempDir;
15
- const projectId = 'test-project';
16
- beforeEach(() => {
17
- // Create a temporary directory for test database
18
- tempDir = mkdtempSync(join(tmpdir(), 'stackmemory-test-'));
19
- const dbPath = join(tempDir, 'test.db');
20
- // Initialize database
21
- db = new Database(dbPath);
22
- // Create frame manager
23
- frameManager = new FrameManager(db, projectId);
24
- });
25
- afterEach(() => {
26
- // Clean up
27
- if (db) {
28
- db.close();
29
- }
30
- if (tempDir) {
31
- rmSync(tempDir, { recursive: true, force: true });
32
- }
33
- });
34
- describe('Initialization', () => {
35
- it('should initialize database schema correctly', () => {
36
- // Check if tables exist
37
- const tables = db.prepare(`
38
- SELECT name FROM sqlite_master
39
- WHERE type='table' AND name IN ('frames', 'events', 'anchors')
40
- `).all();
41
- expect(tables).toHaveLength(3);
42
- expect(tables.map((t) => t.name)).toContain('frames');
43
- expect(tables.map((t) => t.name)).toContain('events');
44
- expect(tables.map((t) => t.name)).toContain('anchors');
45
- });
46
- it('should load empty active stack on initialization', () => {
47
- const stackDepth = frameManager.getStackDepth();
48
- expect(stackDepth).toBe(0);
49
- });
50
- });
51
- describe('Frame Creation', () => {
52
- it('should create a new frame successfully', () => {
53
- const frameId = frameManager.createFrame({
54
- type: 'task',
55
- name: 'Test Task',
56
- inputs: { input: 'test' },
57
- });
58
- expect(frameId).toBeDefined();
59
- expect(typeof frameId).toBe('string');
60
- const frame = frameManager.getFrame(frameId);
61
- expect(frame).toBeDefined();
62
- expect(frame.frame_id).toBe(frameId);
63
- expect(frame.name).toBe('Test Task');
64
- expect(frame.type).toBe('task');
65
- expect(frame.state).toBe('active');
66
- expect(frame.inputs).toEqual({ input: 'test' });
67
- expect(frame.depth).toBe(0);
68
- });
69
- it('should create nested frames with correct depth', () => {
70
- const parentFrameId = frameManager.createFrame({
71
- type: 'task',
72
- name: 'Parent',
73
- });
74
- const childFrameId = frameManager.createFrame({
75
- type: 'subtask',
76
- name: 'Child',
77
- });
78
- const parentFrame = frameManager.getFrame(parentFrameId);
79
- const childFrame = frameManager.getFrame(childFrameId);
80
- expect(parentFrame.depth).toBe(0);
81
- expect(childFrame.depth).toBe(1);
82
- expect(childFrame.parent_frame_id).toBe(parentFrameId);
83
- });
84
- it('should update active stack when creating frames', () => {
85
- const frame1Id = frameManager.createFrame({
86
- type: 'task',
87
- name: 'Frame 1',
88
- });
89
- const frame2Id = frameManager.createFrame({
90
- type: 'subtask',
91
- name: 'Frame 2',
92
- });
93
- const stackDepth = frameManager.getStackDepth();
94
- expect(stackDepth).toBe(2);
95
- expect(frameManager.getCurrentFrameId()).toBe(frame2Id);
96
- });
97
- it('should handle frame creation errors', () => {
98
- // Close the database to simulate an error
99
- db.close();
100
- expect(() => {
101
- frameManager.createFrame({
102
- type: 'task',
103
- name: 'Error Frame',
104
- });
105
- }).toThrow(DatabaseError);
106
- });
107
- it('should handle different frame types', () => {
108
- const frameTypes = ['task', 'subtask', 'tool_scope', 'review', 'write', 'debug'];
109
- frameTypes.forEach(type => {
110
- const frameId = frameManager.createFrame({
111
- type,
112
- name: `${type} frame`,
113
- });
114
- const frame = frameManager.getFrame(frameId);
115
- expect(frame.type).toBe(type);
116
- });
117
- });
118
- it('should create frames with specific parent', () => {
119
- const rootFrameId = frameManager.createFrame({
120
- type: 'task',
121
- name: 'Root Frame',
122
- });
123
- const childFrameId = frameManager.createFrame({
124
- type: 'subtask',
125
- name: 'Child Frame',
126
- parentFrameId: rootFrameId,
127
- });
128
- const childFrame = frameManager.getFrame(childFrameId);
129
- expect(childFrame.parent_frame_id).toBe(rootFrameId);
130
- expect(childFrame.depth).toBe(1);
131
- });
132
- });
133
- describe('Frame Closing', () => {
134
- it('should close a frame successfully', () => {
135
- const frameId = frameManager.createFrame({
136
- type: 'task',
137
- name: 'Test Frame',
138
- });
139
- frameManager.closeFrame(frameId, {
140
- result: 'completed',
141
- data: 'output'
142
- });
143
- const closedFrame = frameManager.getFrame(frameId);
144
- expect(closedFrame.state).toBe('closed');
145
- expect(closedFrame.outputs).toMatchObject({ data: 'output' });
146
- expect(closedFrame.closed_at).toBeDefined();
147
- });
148
- it('should generate digest when closing frame', () => {
149
- const frameId = frameManager.createFrame({
150
- type: 'task',
151
- name: 'Digest Test',
152
- });
153
- // Add some events
154
- frameManager.addEvent('user_message', {
155
- content: 'Test message'
156
- }, frameId);
157
- frameManager.closeFrame(frameId, {
158
- result: 'success'
159
- });
160
- const closedFrame = frameManager.getFrame(frameId);
161
- expect(closedFrame.digest_text).toBeDefined();
162
- expect(closedFrame.digest_json).toBeDefined();
163
- expect(closedFrame.digest_text).toContain('Digest Test');
164
- });
165
- it('should remove from active stack when closing', () => {
166
- const frame1Id = frameManager.createFrame({
167
- type: 'task',
168
- name: 'Frame 1',
169
- });
170
- const frame2Id = frameManager.createFrame({
171
- type: 'subtask',
172
- name: 'Frame 2',
173
- });
174
- frameManager.closeFrame(frame2Id);
175
- const stackDepth = frameManager.getStackDepth();
176
- expect(stackDepth).toBe(1);
177
- expect(frameManager.getCurrentFrameId()).toBe(frame1Id);
178
- });
179
- it('should close current frame when no frameId specified', () => {
180
- const frame1Id = frameManager.createFrame({
181
- type: 'task',
182
- name: 'Frame 1',
183
- });
184
- const frame2Id = frameManager.createFrame({
185
- type: 'subtask',
186
- name: 'Frame 2',
187
- });
188
- expect(frameManager.getCurrentFrameId()).toBe(frame2Id);
189
- frameManager.closeFrame(); // Close current frame
190
- const closedFrame = frameManager.getFrame(frame2Id);
191
- expect(closedFrame.state).toBe('closed');
192
- expect(frameManager.getCurrentFrameId()).toBe(frame1Id);
193
- });
194
- it('should throw error when closing non-existent frame', () => {
195
- expect(() => {
196
- frameManager.closeFrame('non-existent-id');
197
- }).toThrow(FrameError);
198
- });
199
- it('should warn when closing already closed frame', () => {
200
- const frameId = frameManager.createFrame({
201
- type: 'task',
202
- name: 'Test',
203
- });
204
- frameManager.closeFrame(frameId);
205
- // Should not throw, but should warn
206
- expect(() => {
207
- frameManager.closeFrame(frameId);
208
- }).not.toThrow();
209
- });
210
- it('should close child frames recursively', () => {
211
- const rootId = frameManager.createFrame({
212
- type: 'task',
213
- name: 'Root',
214
- });
215
- const child1Id = frameManager.createFrame({
216
- type: 'subtask',
217
- name: 'Child 1',
218
- });
219
- const child2Id = frameManager.createFrame({
220
- type: 'tool_scope',
221
- name: 'Child 2',
222
- });
223
- // Close the root frame
224
- frameManager.closeFrame(rootId);
225
- // All frames should be closed
226
- expect(frameManager.getFrame(rootId).state).toBe('closed');
227
- expect(frameManager.getFrame(child1Id).state).toBe('closed');
228
- expect(frameManager.getFrame(child2Id).state).toBe('closed');
229
- expect(frameManager.getStackDepth()).toBe(0);
230
- });
231
- it('should throw error when no active frame to close', () => {
232
- expect(() => {
233
- frameManager.closeFrame(); // No frames created
234
- }).toThrow(FrameError);
235
- });
236
- });
237
- describe('Event Management', () => {
238
- it('should add events to a frame', () => {
239
- const frameId = frameManager.createFrame({
240
- type: 'task',
241
- name: 'Event Test',
242
- });
243
- const eventId = frameManager.addEvent('user_message', { content: 'Hello' }, frameId);
244
- expect(eventId).toBeDefined();
245
- expect(typeof eventId).toBe('string');
246
- const events = frameManager.getFrameEvents(frameId);
247
- expect(events).toHaveLength(1);
248
- expect(events[0].event_id).toBe(eventId);
249
- expect(events[0].frame_id).toBe(frameId);
250
- expect(events[0].event_type).toBe('user_message');
251
- expect(events[0].payload).toEqual({ content: 'Hello' });
252
- });
253
- it('should add events to current frame when no frameId specified', () => {
254
- const frameId = frameManager.createFrame({
255
- type: 'task',
256
- name: 'Current Frame Test',
257
- });
258
- const eventId = frameManager.addEvent('user_message', { content: 'Hello' });
259
- const events = frameManager.getFrameEvents(frameId);
260
- expect(events).toHaveLength(1);
261
- expect(events[0].event_id).toBe(eventId);
262
- });
263
- it('should retrieve frame events', () => {
264
- const frameId = frameManager.createFrame({
265
- type: 'task',
266
- name: 'Event Retrieval',
267
- });
268
- frameManager.addEvent('user_message', { msg: '1' }, frameId);
269
- frameManager.addEvent('tool_call', { tool: 'test' }, frameId);
270
- frameManager.addEvent('tool_result', { result: 'ok' }, frameId);
271
- const events = frameManager.getFrameEvents(frameId);
272
- expect(events).toHaveLength(3);
273
- expect(events[0].event_type).toBe('user_message');
274
- expect(events[1].event_type).toBe('tool_call');
275
- expect(events[2].event_type).toBe('tool_result');
276
- });
277
- it('should maintain event sequence numbers', () => {
278
- const frameId = frameManager.createFrame({
279
- type: 'task',
280
- name: 'Sequence Test',
281
- });
282
- frameManager.addEvent('user_message', { index: 1 }, frameId);
283
- frameManager.addEvent('user_message', { index: 2 }, frameId);
284
- frameManager.addEvent('user_message', { index: 3 }, frameId);
285
- const events = frameManager.getFrameEvents(frameId);
286
- expect(events[0].seq).toBe(1);
287
- expect(events[1].seq).toBe(2);
288
- expect(events[2].seq).toBe(3);
289
- });
290
- it('should limit frame events when requested', () => {
291
- const frameId = frameManager.createFrame({
292
- type: 'task',
293
- name: 'Limit Test',
294
- });
295
- // Add many events
296
- for (let i = 0; i < 20; i++) {
297
- frameManager.addEvent('user_message', { index: i }, frameId);
298
- }
299
- const limitedEvents = frameManager.getFrameEvents(frameId, 5);
300
- expect(limitedEvents).toHaveLength(5);
301
- // Should get the last 5 events (most recent)
302
- expect(limitedEvents[0].payload.index).toBe(19);
303
- expect(limitedEvents[4].payload.index).toBe(15);
304
- });
305
- it('should throw error when adding event with no active frame', () => {
306
- expect(() => {
307
- frameManager.addEvent('user_message', { content: 'test' });
308
- }).toThrow(FrameError);
309
- });
310
- it('should handle different event types', () => {
311
- const frameId = frameManager.createFrame({
312
- type: 'task',
313
- name: 'Event Types Test',
314
- });
315
- const eventTypes = [
316
- 'user_message',
317
- 'assistant_message',
318
- 'tool_call',
319
- 'tool_result',
320
- 'decision',
321
- 'constraint',
322
- 'artifact',
323
- 'observation'
324
- ];
325
- eventTypes.forEach((type) => {
326
- frameManager.addEvent(type, { type }, frameId);
327
- });
328
- const events = frameManager.getFrameEvents(frameId);
329
- expect(events).toHaveLength(eventTypes.length);
330
- eventTypes.forEach((type, index) => {
331
- expect(events[index].event_type).toBe(type);
332
- });
333
- });
334
- });
335
- describe('Anchor Management', () => {
336
- it('should add anchors to a frame', () => {
337
- const frameId = frameManager.createFrame({
338
- type: 'task',
339
- name: 'Anchor Test',
340
- });
341
- const anchorId = frameManager.addAnchor('FACT', 'Important fact', 9 // priority 0-10
342
- );
343
- expect(anchorId).toBeDefined();
344
- expect(typeof anchorId).toBe('string');
345
- });
346
- it('should add anchors to current frame when no frameId specified', () => {
347
- const frameId = frameManager.createFrame({
348
- type: 'task',
349
- name: 'Current Frame Anchor Test',
350
- });
351
- const anchorId = frameManager.addAnchor('FACT', 'Important fact', 9);
352
- expect(anchorId).toBeDefined();
353
- });
354
- it('should handle different anchor types', () => {
355
- const frameId = frameManager.createFrame({
356
- type: 'task',
357
- name: 'Anchor Types',
358
- });
359
- const anchorTypes = [
360
- 'FACT',
361
- 'DECISION',
362
- 'CONSTRAINT',
363
- 'INTERFACE_CONTRACT',
364
- 'TODO',
365
- 'RISK'
366
- ];
367
- anchorTypes.forEach(type => {
368
- const anchorId = frameManager.addAnchor(type, `${type} content`, 5, { testMetadata: true }, frameId);
369
- expect(anchorId).toBeDefined();
370
- });
371
- });
372
- it('should handle metadata in anchors', () => {
373
- const frameId = frameManager.createFrame({
374
- type: 'task',
375
- name: 'Metadata Test',
376
- });
377
- const metadata = {
378
- source: 'test',
379
- confidence: 0.95,
380
- tags: ['important', 'decision']
381
- };
382
- const anchorId = frameManager.addAnchor('DECISION', 'Decision with metadata', 8, metadata, frameId);
383
- expect(anchorId).toBeDefined();
384
- });
385
- it('should use default priority when not specified', () => {
386
- const frameId = frameManager.createFrame({
387
- type: 'task',
388
- name: 'Default Priority Test',
389
- });
390
- const anchorId = frameManager.addAnchor('TODO', 'Task without priority');
391
- expect(anchorId).toBeDefined();
392
- });
393
- it('should throw error when adding anchor with no active frame', () => {
394
- expect(() => {
395
- frameManager.addAnchor('FACT', 'No active frame');
396
- }).toThrow(FrameError);
397
- });
398
- });
399
- describe('Context Assembly', () => {
400
- it('should get hot stack context with active frames', () => {
401
- const frame1Id = frameManager.createFrame({
402
- type: 'task',
403
- name: 'Frame 1',
404
- });
405
- const frame2Id = frameManager.createFrame({
406
- type: 'subtask',
407
- name: 'Frame 2',
408
- });
409
- const frame3Id = frameManager.createFrame({
410
- type: 'tool_scope',
411
- name: 'Frame 3',
412
- });
413
- const hotStack = frameManager.getHotStackContext(5);
414
- expect(hotStack).toHaveLength(3);
415
- expect(hotStack[0].frameId).toBe(frame1Id);
416
- expect(hotStack[1].frameId).toBe(frame2Id);
417
- expect(hotStack[2].frameId).toBe(frame3Id);
418
- });
419
- it('should assemble frame context correctly', () => {
420
- const frameId = frameManager.createFrame({
421
- type: 'task',
422
- name: 'Context Test',
423
- inputs: {
424
- constraints: ['constraint1', 'constraint2'],
425
- definitions: { key: 'value' }
426
- }
427
- });
428
- // Add events and anchors
429
- frameManager.addEvent('user_message', {
430
- content: 'Test message'
431
- }, frameId);
432
- frameManager.addAnchor('FACT', 'Important fact', 9, {}, frameId);
433
- const hotStack = frameManager.getHotStackContext(10);
434
- const context = hotStack.find(ctx => ctx.frameId === frameId);
435
- expect(context).toBeDefined();
436
- expect(context.frameId).toBe(frameId);
437
- expect(context.header.goal).toBe('Context Test');
438
- expect(context.header.constraints).toEqual(['constraint1', 'constraint2']);
439
- expect(context.header.definitions).toEqual({ key: 'value' });
440
- expect(context.anchors).toHaveLength(1);
441
- expect(context.recentEvents).toHaveLength(1);
442
- });
443
- it('should limit events in context assembly', () => {
444
- const frameId = frameManager.createFrame({
445
- type: 'task',
446
- name: 'Event Limit Test',
447
- });
448
- // Add many events
449
- for (let i = 0; i < 20; i++) {
450
- frameManager.addEvent('user_message', { index: i }, frameId);
451
- }
452
- const hotStack = frameManager.getHotStackContext(5);
453
- const context = hotStack.find(ctx => ctx.frameId === frameId);
454
- expect(context.recentEvents).toHaveLength(5);
455
- });
456
- it('should return empty hot stack when no active frames', () => {
457
- const hotStack = frameManager.getHotStackContext();
458
- expect(hotStack).toHaveLength(0);
459
- });
460
- it('should get active frame path', () => {
461
- const frame1Id = frameManager.createFrame({
462
- type: 'task',
463
- name: 'Root Frame',
464
- });
465
- const frame2Id = frameManager.createFrame({
466
- type: 'subtask',
467
- name: 'Child Frame',
468
- });
469
- const activePath = frameManager.getActiveFramePath();
470
- expect(activePath).toHaveLength(2);
471
- expect(activePath[0].frame_id).toBe(frame1Id);
472
- expect(activePath[0].name).toBe('Root Frame');
473
- expect(activePath[1].frame_id).toBe(frame2Id);
474
- expect(activePath[1].name).toBe('Child Frame');
475
- });
476
- it('should extract active artifacts from events', () => {
477
- const frameId = frameManager.createFrame({
478
- type: 'task',
479
- name: 'Artifact Test',
480
- });
481
- frameManager.addEvent('artifact', {
482
- ref: '/path/to/file1.ts',
483
- kind: 'file'
484
- }, frameId);
485
- frameManager.addEvent('artifact', {
486
- ref: '/path/to/file2.ts',
487
- kind: 'file'
488
- }, frameId);
489
- const hotStack = frameManager.getHotStackContext();
490
- const context = hotStack.find(ctx => ctx.frameId === frameId);
491
- expect(context.activeArtifacts).toHaveLength(2);
492
- expect(context.activeArtifacts).toContain('/path/to/file1.ts');
493
- expect(context.activeArtifacts).toContain('/path/to/file2.ts');
494
- });
495
- });
496
- describe('Frame Retrieval', () => {
497
- it('should get frame by ID', () => {
498
- const frameId = frameManager.createFrame({
499
- type: 'task',
500
- name: 'Get Test',
501
- });
502
- const retrieved = frameManager.getFrame(frameId);
503
- expect(retrieved).toBeDefined();
504
- expect(retrieved.frame_id).toBe(frameId);
505
- expect(retrieved.name).toBe('Get Test');
506
- });
507
- it('should return undefined for non-existent frame', () => {
508
- const frame = frameManager.getFrame('non-existent');
509
- expect(frame).toBeUndefined();
510
- });
511
- it('should get current frame ID (top of stack)', () => {
512
- const frame1Id = frameManager.createFrame({
513
- type: 'task',
514
- name: 'Frame 1',
515
- });
516
- const frame2Id = frameManager.createFrame({
517
- type: 'subtask',
518
- name: 'Frame 2',
519
- });
520
- const currentFrameId = frameManager.getCurrentFrameId();
521
- expect(currentFrameId).toBe(frame2Id);
522
- });
523
- it('should return undefined when stack is empty', () => {
524
- const currentFrameId = frameManager.getCurrentFrameId();
525
- expect(currentFrameId).toBeUndefined();
526
- });
527
- it('should get stack depth', () => {
528
- expect(frameManager.getStackDepth()).toBe(0);
529
- frameManager.createFrame({
530
- type: 'task',
531
- name: 'Frame 1',
532
- });
533
- expect(frameManager.getStackDepth()).toBe(1);
534
- frameManager.createFrame({
535
- type: 'subtask',
536
- name: 'Frame 2',
537
- });
538
- expect(frameManager.getStackDepth()).toBe(2);
539
- });
540
- it('should handle frame with all properties', () => {
541
- const frameId = frameManager.createFrame({
542
- type: 'task',
543
- name: 'Complete Test',
544
- inputs: {
545
- test: true,
546
- data: { nested: 'value' },
547
- list: [1, 2, 3]
548
- }
549
- });
550
- const frame = frameManager.getFrame(frameId);
551
- expect(frame.frame_id).toBe(frameId);
552
- expect(frame.run_id).toBeDefined();
553
- expect(frame.project_id).toBe(projectId);
554
- expect(frame.parent_frame_id).toBeNull();
555
- expect(frame.depth).toBe(0);
556
- expect(frame.type).toBe('task');
557
- expect(frame.name).toBe('Complete Test');
558
- expect(frame.state).toBe('active');
559
- expect(frame.inputs).toEqual({
560
- test: true,
561
- data: { nested: 'value' },
562
- list: [1, 2, 3]
563
- });
564
- expect(frame.outputs).toEqual({});
565
- expect(frame.digest_json).toEqual({});
566
- expect(frame.created_at).toBeDefined();
567
- expect(frame.closed_at).toBeNull();
568
- });
569
- });
570
- describe('Digest Generation', () => {
571
- it('should generate meaningful digest', async () => {
572
- const frameId = frameManager.createFrame({
573
- type: 'task',
574
- name: 'Digest Frame',
575
- });
576
- // Add various events
577
- frameManager.addEvent('user_message', {
578
- content: 'What is the weather?'
579
- }, frameId);
580
- frameManager.addEvent('tool_call', {
581
- tool: 'weather_api',
582
- params: { location: 'NYC' }
583
- }, frameId);
584
- frameManager.addEvent('tool_result', {
585
- result: 'Sunny, 72°F'
586
- }, frameId);
587
- frameManager.addEvent('artifact', {
588
- kind: 'file',
589
- ref: '/path/to/weather.json'
590
- }, frameId);
591
- // Add anchors
592
- frameManager.addAnchor('FACT', 'Weather is sunny', 9, {}, frameId);
593
- frameManager.addAnchor('DECISION', 'No umbrella needed', 8, {}, frameId);
594
- frameManager.addAnchor('RISK', 'Rain possible later', 3, {}, frameId);
595
- // Add a delay to ensure duration > 0 (need at least 1000ms for 1 second difference)
596
- await new Promise(resolve => setTimeout(resolve, 1100));
597
- frameManager.closeFrame(frameId, {
598
- result: 'Weather information provided',
599
- data: 'temperature: 72°F'
600
- });
601
- const closedFrame = frameManager.getFrame(frameId);
602
- expect(closedFrame.digest_text).toContain('Completed: Digest Frame');
603
- expect(closedFrame.digest_text).toContain('Decisions made');
604
- expect(closedFrame.digest_text).toContain('No umbrella needed');
605
- expect(closedFrame.digest_text).toContain('Rain possible later');
606
- expect(closedFrame.digest_text).toContain('4 events');
607
- expect(closedFrame.digest_text).toContain('1 tool calls');
608
- const digest = closedFrame.digest_json;
609
- expect(digest.result).toBe('Digest Frame');
610
- expect(digest.decisions).toHaveLength(1);
611
- expect(digest.decisions[0].text).toBe('No umbrella needed');
612
- expect(digest.risks).toHaveLength(1);
613
- expect(digest.risks[0].text).toBe('Rain possible later');
614
- expect(digest.artifacts).toHaveLength(1);
615
- expect(digest.artifacts[0].ref).toBe('/path/to/weather.json');
616
- expect(digest.tool_calls_count).toBe(1);
617
- expect(digest.duration_seconds).toBeGreaterThanOrEqual(0);
618
- });
619
- });
620
- describe('Error Handling', () => {
621
- it('should handle database errors gracefully', () => {
622
- const frameId = frameManager.createFrame({
623
- type: 'task',
624
- name: 'Error Test',
625
- });
626
- // Close database to simulate error
627
- db.close();
628
- expect(() => {
629
- frameManager.addEvent('user_message', {}, frameId);
630
- }).toThrow(DatabaseError);
631
- });
632
- it('should validate frame types', () => {
633
- const validTypes = [
634
- 'task',
635
- 'subtask',
636
- 'tool_scope',
637
- 'review',
638
- 'write',
639
- 'debug'
640
- ];
641
- validTypes.forEach(type => {
642
- const frameId = frameManager.createFrame({
643
- type,
644
- name: `${type} frame`,
645
- });
646
- const frame = frameManager.getFrame(frameId);
647
- expect(frame.type).toBe(type);
648
- });
649
- });
650
- it('should handle concurrent frame operations', () => {
651
- const frameIds = [];
652
- // Create multiple frames quickly
653
- for (let i = 0; i < 10; i++) {
654
- frameIds.push(frameManager.createFrame({
655
- type: 'task',
656
- name: `Frame ${i}`,
657
- }));
658
- }
659
- expect(frameIds).toHaveLength(10);
660
- expect(frameManager.getStackDepth()).toBe(10);
661
- // Close them in reverse order (child to parent)
662
- for (let i = 9; i >= 0; i--) {
663
- frameManager.closeFrame(frameIds[i]);
664
- }
665
- expect(frameManager.getStackDepth()).toBe(0);
666
- });
667
- it('should handle database query errors gracefully', () => {
668
- // This tests the error handling in various methods
669
- const frameId = frameManager.createFrame({
670
- type: 'task',
671
- name: 'Query Error Test',
672
- });
673
- db.close();
674
- expect(() => frameManager.getFrame(frameId)).toThrow(DatabaseError);
675
- expect(() => frameManager.getFrameEvents(frameId)).toThrow(DatabaseError);
676
- });
677
- it('should provide meaningful error messages', () => {
678
- try {
679
- frameManager.closeFrame('invalid-frame-id');
680
- expect.fail('Should have thrown an error');
681
- }
682
- catch (error) {
683
- expect(error).toBeInstanceOf(FrameError);
684
- expect(error.message).toContain('Frame not found');
685
- expect(error.code).toBe(ErrorCode.FRAME_NOT_FOUND);
686
- }
687
- });
688
- it('should include context in error metadata', () => {
689
- try {
690
- frameManager.addAnchor('FACT', 'Test fact');
691
- expect.fail('Should have thrown an error');
692
- }
693
- catch (error) {
694
- expect(error).toBeInstanceOf(FrameError);
695
- expect(error.context).toMatchObject({
696
- operation: 'addAnchor',
697
- anchorType: 'FACT'
698
- });
699
- }
700
- });
701
- });
702
- describe('Complex Scenarios', () => {
703
- it('should handle deep nesting', () => {
704
- const frameIds = [];
705
- const maxDepth = 10;
706
- for (let i = 0; i < maxDepth; i++) {
707
- const frameId = frameManager.createFrame({
708
- type: i === 0 ? 'task' : 'subtask',
709
- name: `Level ${i}`,
710
- });
711
- frameIds.push(frameId);
712
- const frame = frameManager.getFrame(frameId);
713
- expect(frame.depth).toBe(i);
714
- }
715
- expect(frameManager.getStackDepth()).toBe(maxDepth);
716
- // Close from deepest to root
717
- for (let i = maxDepth - 1; i >= 0; i--) {
718
- frameManager.closeFrame(frameIds[i]);
719
- }
720
- expect(frameManager.getStackDepth()).toBe(0);
721
- });
722
- it('should handle frame with many events and anchors', () => {
723
- const frameId = frameManager.createFrame({
724
- type: 'task',
725
- name: 'Heavy Frame',
726
- });
727
- // Add 100 events
728
- for (let i = 0; i < 100; i++) {
729
- frameManager.addEvent('user_message', { index: i }, frameId);
730
- }
731
- // Add 50 anchors of different types
732
- const anchorTypes = ['FACT', 'DECISION', 'CONSTRAINT', 'TODO', 'RISK'];
733
- for (let i = 0; i < 50; i++) {
734
- frameManager.addAnchor(anchorTypes[i % anchorTypes.length], `Content ${i}`, Math.floor(Math.random() * 10), { index: i }, frameId);
735
- }
736
- const events = frameManager.getFrameEvents(frameId);
737
- expect(events).toHaveLength(100);
738
- // Close and check digest is generated correctly
739
- frameManager.closeFrame(frameId, {
740
- result: 'Heavy frame completed',
741
- processedEvents: 100,
742
- processedAnchors: 50
743
- });
744
- const closedFrame = frameManager.getFrame(frameId);
745
- expect(closedFrame.digest_text).toBeDefined();
746
- expect(closedFrame.digest_json).toBeDefined();
747
- expect(closedFrame.digest_json.tool_calls_count).toBe(0); // No tool calls
748
- expect(closedFrame.state).toBe('closed');
749
- });
750
- it('should handle frame inheritance with specific parent', () => {
751
- const rootId = frameManager.createFrame({
752
- type: 'task',
753
- name: 'Root Task',
754
- });
755
- const childId = frameManager.createFrame({
756
- type: 'subtask',
757
- name: 'Child Task',
758
- parentFrameId: rootId,
759
- });
760
- const grandchildId = frameManager.createFrame({
761
- type: 'tool_scope',
762
- name: 'Grandchild Task',
763
- parentFrameId: childId,
764
- });
765
- const rootFrame = frameManager.getFrame(rootId);
766
- const childFrame = frameManager.getFrame(childId);
767
- const grandchildFrame = frameManager.getFrame(grandchildId);
768
- expect(rootFrame.depth).toBe(0);
769
- expect(childFrame.depth).toBe(1);
770
- expect(grandchildFrame.depth).toBe(2);
771
- expect(rootFrame.parent_frame_id).toBeNull();
772
- expect(childFrame.parent_frame_id).toBe(rootId);
773
- expect(grandchildFrame.parent_frame_id).toBe(childId);
774
- });
775
- it('should handle session recovery with existing frames', () => {
776
- // Simulate existing frames in database
777
- const frame1Id = frameManager.createFrame({
778
- type: 'task',
779
- name: 'Existing Frame 1',
780
- });
781
- const frame2Id = frameManager.createFrame({
782
- type: 'subtask',
783
- name: 'Existing Frame 2',
784
- });
785
- // Create new frame manager with same database and runId (simulating session recovery)
786
- const originalRunId = frameManager.currentRunId;
787
- const newFrameManager = new FrameManager(db, projectId, originalRunId);
788
- // Should have restored the active stack
789
- expect(newFrameManager.getStackDepth()).toBe(2);
790
- expect(newFrameManager.getCurrentFrameId()).toBe(frame2Id);
791
- // Should be able to work with existing frames
792
- newFrameManager.addEvent('observation', { message: 'Session recovered' });
793
- newFrameManager.closeFrame();
794
- expect(newFrameManager.getStackDepth()).toBe(1);
795
- expect(newFrameManager.getCurrentFrameId()).toBe(frame1Id);
796
- });
797
- it('should handle mixed event and anchor operations', () => {
798
- const frameId = frameManager.createFrame({
799
- type: 'task',
800
- name: 'Mixed Operations',
801
- });
802
- // Interleave events and anchors
803
- frameManager.addEvent('user_message', { msg: 'Start task' }, frameId);
804
- frameManager.addAnchor('FACT', 'Task started', 8, {}, frameId);
805
- frameManager.addEvent('tool_call', { tool: 'analyzer' }, frameId);
806
- frameManager.addAnchor('DECISION', 'Use analyzer tool', 9, {}, frameId);
807
- frameManager.addEvent('tool_result', { result: 'Analysis complete' }, frameId);
808
- frameManager.addAnchor('CONSTRAINT', 'Must validate results', 7, {}, frameId);
809
- frameManager.addEvent('assistant_message', { msg: 'Task complete' }, frameId);
810
- frameManager.addAnchor('TODO', 'Document findings', 5, {}, frameId);
811
- const events = frameManager.getFrameEvents(frameId);
812
- expect(events).toHaveLength(4);
813
- const hotStack = frameManager.getHotStackContext();
814
- const context = hotStack.find(ctx => ctx.frameId === frameId);
815
- expect(context.anchors).toHaveLength(4);
816
- expect(context.recentEvents).toHaveLength(4);
817
- // Events should be chronological, anchors should be by priority
818
- // Check that we have the right events (order may vary based on implementation)
819
- const eventMessages = context.recentEvents.map(e => e.payload.msg).filter(Boolean);
820
- expect(eventMessages).toContain('Start task');
821
- expect(eventMessages).toContain('Task complete');
822
- });
823
- it('should handle closing frames out of order', () => {
824
- const rootId = frameManager.createFrame({
825
- type: 'task',
826
- name: 'Root',
827
- });
828
- const child1Id = frameManager.createFrame({
829
- type: 'subtask',
830
- name: 'Child 1',
831
- });
832
- const child2Id = frameManager.createFrame({
833
- type: 'tool_scope',
834
- name: 'Child 2',
835
- });
836
- expect(frameManager.getStackDepth()).toBe(3);
837
- // Close the middle frame
838
- frameManager.closeFrame(child1Id);
839
- // Child 2 should also be closed (child of child1)
840
- expect(frameManager.getFrame(child1Id).state).toBe('closed');
841
- expect(frameManager.getFrame(child2Id).state).toBe('closed');
842
- expect(frameManager.getStackDepth()).toBe(1);
843
- expect(frameManager.getCurrentFrameId()).toBe(rootId);
844
- });
845
- });
846
- describe('Database Schema and Persistence', () => {
847
- it('should initialize all required tables', () => {
848
- const tables = db.prepare(`
849
- SELECT name FROM sqlite_master
850
- WHERE type='table' AND name IN ('frames', 'events', 'anchors')
851
- `).all();
852
- expect(tables).toHaveLength(3);
853
- expect(tables.map((t) => t.name)).toContain('frames');
854
- expect(tables.map((t) => t.name)).toContain('events');
855
- expect(tables.map((t) => t.name)).toContain('anchors');
856
- });
857
- it('should create required indexes', () => {
858
- const indexes = db.prepare(`
859
- SELECT name FROM sqlite_master
860
- WHERE type='index' AND name LIKE 'idx_%'
861
- `).all();
862
- const expectedIndexes = [
863
- 'idx_frames_run',
864
- 'idx_frames_parent',
865
- 'idx_frames_state',
866
- 'idx_events_frame',
867
- 'idx_events_seq',
868
- 'idx_anchors_frame'
869
- ];
870
- expectedIndexes.forEach(expectedIndex => {
871
- expect(indexes.some((idx) => idx.name === expectedIndex)).toBe(true);
872
- });
873
- });
874
- it('should handle JSON serialization correctly', () => {
875
- const complexInputs = {
876
- nested: { deep: { value: 'test' } },
877
- array: [1, 2, { key: 'value' }],
878
- boolean: true,
879
- number: 42.5,
880
- null: null
881
- };
882
- const frameId = frameManager.createFrame({
883
- type: 'task',
884
- name: 'JSON Test',
885
- inputs: complexInputs,
886
- });
887
- const frame = frameManager.getFrame(frameId);
888
- expect(frame.inputs).toEqual(complexInputs);
889
- });
890
- });
891
- });
892
- //# sourceMappingURL=frame-manager.test.js.map