@stackmemoryai/stackmemory 0.2.8 → 0.3.0

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