@stackmemoryai/stackmemory 0.3.7 → 0.3.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 (202) hide show
  1. package/dist/agents/core/agent-task-manager.js +5 -5
  2. package/dist/agents/core/agent-task-manager.js.map +2 -2
  3. package/dist/agents/verifiers/base-verifier.js +2 -2
  4. package/dist/agents/verifiers/base-verifier.js.map +2 -2
  5. package/dist/cli/claude-sm.js +0 -11
  6. package/dist/cli/claude-sm.js.map +2 -2
  7. package/dist/cli/codex-sm.js +0 -11
  8. package/dist/cli/codex-sm.js.map +2 -2
  9. package/dist/cli/commands/chromadb.js +64 -34
  10. package/dist/cli/commands/chromadb.js.map +2 -2
  11. package/dist/cli/commands/clear.js +9 -13
  12. package/dist/cli/commands/clear.js.map +2 -2
  13. package/dist/cli/commands/config.js +43 -33
  14. package/dist/cli/commands/config.js.map +2 -2
  15. package/dist/cli/commands/context.js.map +2 -2
  16. package/dist/cli/commands/dashboard.js +41 -13
  17. package/dist/cli/commands/dashboard.js.map +2 -2
  18. package/dist/cli/commands/gc.js +69 -20
  19. package/dist/cli/commands/gc.js.map +2 -2
  20. package/dist/cli/commands/handoff.js.map +2 -2
  21. package/dist/cli/commands/infinite-storage.js +60 -19
  22. package/dist/cli/commands/infinite-storage.js.map +2 -2
  23. package/dist/cli/commands/linear-create.js +36 -8
  24. package/dist/cli/commands/linear-create.js.map +2 -2
  25. package/dist/cli/commands/linear-list.js +33 -10
  26. package/dist/cli/commands/linear-list.js.map +2 -2
  27. package/dist/cli/commands/linear-migrate.js +17 -4
  28. package/dist/cli/commands/linear-migrate.js.map +2 -2
  29. package/dist/cli/commands/linear-test.js +14 -6
  30. package/dist/cli/commands/linear-test.js.map +2 -2
  31. package/dist/cli/commands/linear-unified.js +123 -35
  32. package/dist/cli/commands/linear-unified.js.map +2 -2
  33. package/dist/cli/commands/linear.js.map +2 -2
  34. package/dist/cli/commands/monitor.js.map +2 -2
  35. package/dist/cli/commands/onboard.js +35 -8
  36. package/dist/cli/commands/onboard.js.map +2 -2
  37. package/dist/cli/commands/quality.js +2 -7
  38. package/dist/cli/commands/quality.js.map +2 -2
  39. package/dist/cli/commands/session.js +23 -6
  40. package/dist/cli/commands/session.js.map +2 -2
  41. package/dist/cli/commands/skills.js +72 -27
  42. package/dist/cli/commands/skills.js.map +2 -2
  43. package/dist/cli/commands/storage.js +108 -38
  44. package/dist/cli/commands/storage.js.map +2 -2
  45. package/dist/cli/commands/tui.js.map +2 -2
  46. package/dist/cli/commands/webhook.js +57 -18
  47. package/dist/cli/commands/webhook.js.map +2 -2
  48. package/dist/cli/commands/workflow.js +8 -15
  49. package/dist/cli/commands/workflow.js.map +2 -2
  50. package/dist/cli/commands/worktree.js +34 -13
  51. package/dist/cli/commands/worktree.js.map +2 -2
  52. package/dist/cli/index.js +0 -11
  53. package/dist/cli/index.js.map +2 -2
  54. package/dist/core/config/types.js.map +1 -1
  55. package/dist/core/context/auto-context.js +10 -6
  56. package/dist/core/context/auto-context.js.map +2 -2
  57. package/dist/core/context/context-bridge.js.map +2 -2
  58. package/dist/core/context/frame-database.js +13 -3
  59. package/dist/core/context/frame-database.js.map +2 -2
  60. package/dist/core/context/frame-digest.js +7 -5
  61. package/dist/core/context/frame-digest.js.map +2 -2
  62. package/dist/core/context/frame-manager.js.map +2 -2
  63. package/dist/core/context/frame-stack.js +16 -5
  64. package/dist/core/context/frame-stack.js.map +2 -2
  65. package/dist/core/context/incremental-gc.js +10 -3
  66. package/dist/core/context/incremental-gc.js.map +2 -2
  67. package/dist/core/context/index.js.map +1 -1
  68. package/dist/core/context/permission-manager.js.map +2 -2
  69. package/dist/core/context/recursive-context-manager.js +582 -0
  70. package/dist/core/context/recursive-context-manager.js.map +7 -0
  71. package/dist/core/context/refactored-frame-manager.js +12 -3
  72. package/dist/core/context/refactored-frame-manager.js.map +2 -2
  73. package/dist/core/context/shared-context-layer.js +4 -2
  74. package/dist/core/context/shared-context-layer.js.map +2 -2
  75. package/dist/core/database/batch-operations.js +112 -86
  76. package/dist/core/database/batch-operations.js.map +2 -2
  77. package/dist/core/database/query-cache.js +19 -9
  78. package/dist/core/database/query-cache.js.map +2 -2
  79. package/dist/core/database/sqlite-adapter.js +1 -1
  80. package/dist/core/database/sqlite-adapter.js.map +2 -2
  81. package/dist/core/digest/enhanced-hybrid-digest.js +8 -2
  82. package/dist/core/digest/enhanced-hybrid-digest.js.map +2 -2
  83. package/dist/core/errors/recovery.js +9 -2
  84. package/dist/core/errors/recovery.js.map +2 -2
  85. package/dist/core/execution/parallel-executor.js +254 -0
  86. package/dist/core/execution/parallel-executor.js.map +7 -0
  87. package/dist/core/frame/workflow-templates-stub.js.map +1 -1
  88. package/dist/core/frame/workflow-templates.js +40 -1
  89. package/dist/core/frame/workflow-templates.js.map +2 -2
  90. package/dist/core/monitoring/logger.js +6 -1
  91. package/dist/core/monitoring/logger.js.map +2 -2
  92. package/dist/core/monitoring/metrics.js.map +2 -2
  93. package/dist/core/monitoring/progress-tracker.js.map +2 -2
  94. package/dist/core/performance/context-cache.js.map +2 -2
  95. package/dist/core/performance/lazy-context-loader.js +24 -20
  96. package/dist/core/performance/lazy-context-loader.js.map +2 -2
  97. package/dist/core/performance/optimized-frame-context.js +27 -12
  98. package/dist/core/performance/optimized-frame-context.js.map +2 -2
  99. package/dist/core/performance/performance-benchmark.js +10 -6
  100. package/dist/core/performance/performance-benchmark.js.map +2 -2
  101. package/dist/core/performance/performance-profiler.js +51 -14
  102. package/dist/core/performance/performance-profiler.js.map +2 -2
  103. package/dist/core/performance/streaming-jsonl-parser.js +5 -1
  104. package/dist/core/performance/streaming-jsonl-parser.js.map +2 -2
  105. package/dist/core/projects/project-manager.js +14 -20
  106. package/dist/core/projects/project-manager.js.map +2 -2
  107. package/dist/core/retrieval/context-retriever.js.map +1 -1
  108. package/dist/core/retrieval/llm-context-retrieval.js.map +2 -2
  109. package/dist/core/session/clear-survival-stub.js +5 -1
  110. package/dist/core/session/clear-survival-stub.js.map +2 -2
  111. package/dist/core/session/clear-survival.js +35 -0
  112. package/dist/core/session/clear-survival.js.map +2 -2
  113. package/dist/core/session/index.js.map +1 -1
  114. package/dist/core/session/session-manager.js.map +2 -2
  115. package/dist/core/storage/chromadb-adapter.js +6 -2
  116. package/dist/core/storage/chromadb-adapter.js.map +2 -2
  117. package/dist/core/storage/chromadb-simple.js +17 -5
  118. package/dist/core/storage/chromadb-simple.js.map +2 -2
  119. package/dist/core/storage/infinite-storage.js +109 -46
  120. package/dist/core/storage/infinite-storage.js.map +2 -2
  121. package/dist/core/storage/railway-optimized-storage.js +48 -22
  122. package/dist/core/storage/railway-optimized-storage.js.map +2 -2
  123. package/dist/core/storage/remote-storage.js +41 -23
  124. package/dist/core/storage/remote-storage.js.map +2 -2
  125. package/dist/core/trace/cli-trace-wrapper.js +9 -2
  126. package/dist/core/trace/cli-trace-wrapper.js.map +2 -2
  127. package/dist/core/trace/db-trace-wrapper.js +96 -68
  128. package/dist/core/trace/db-trace-wrapper.js.map +2 -2
  129. package/dist/core/trace/debug-trace.js +25 -8
  130. package/dist/core/trace/debug-trace.js.map +2 -2
  131. package/dist/core/trace/index.js +6 -2
  132. package/dist/core/trace/index.js.map +2 -2
  133. package/dist/core/trace/linear-api-wrapper.js +10 -5
  134. package/dist/core/trace/linear-api-wrapper.js.map +2 -2
  135. package/dist/core/trace/trace-demo.js +14 -10
  136. package/dist/core/trace/trace-demo.js.map +2 -2
  137. package/dist/core/trace/trace-detector.js +9 -2
  138. package/dist/core/trace/trace-detector.js.map +2 -2
  139. package/dist/core/trace/types.js.map +1 -1
  140. package/dist/core/utils/compression.js.map +1 -1
  141. package/dist/core/utils/update-checker.js.map +1 -1
  142. package/dist/core/worktree/worktree-manager.js +18 -7
  143. package/dist/core/worktree/worktree-manager.js.map +2 -2
  144. package/dist/features/analytics/core/analytics-service.js.map +2 -2
  145. package/dist/features/analytics/queries/metrics-queries.js +1 -1
  146. package/dist/features/analytics/queries/metrics-queries.js.map +2 -2
  147. package/dist/features/tasks/pebbles-task-store.js.map +1 -1
  148. package/dist/features/tui/components/analytics-panel.js +36 -15
  149. package/dist/features/tui/components/analytics-panel.js.map +2 -2
  150. package/dist/features/tui/components/pr-tracker.js +19 -7
  151. package/dist/features/tui/components/pr-tracker.js.map +2 -2
  152. package/dist/features/tui/components/session-monitor.js +22 -9
  153. package/dist/features/tui/components/session-monitor.js.map +2 -2
  154. package/dist/features/tui/components/subagent-fleet.js +20 -13
  155. package/dist/features/tui/components/subagent-fleet.js.map +2 -2
  156. package/dist/features/tui/components/task-board.js +26 -10
  157. package/dist/features/tui/components/task-board.js.map +2 -2
  158. package/dist/features/tui/index.js.map +2 -2
  159. package/dist/features/tui/services/data-service.js +6 -2
  160. package/dist/features/tui/services/data-service.js.map +2 -2
  161. package/dist/features/tui/services/linear-task-reader.js +3 -1
  162. package/dist/features/tui/services/linear-task-reader.js.map +2 -2
  163. package/dist/features/tui/services/websocket-client.js +3 -1
  164. package/dist/features/tui/services/websocket-client.js.map +2 -2
  165. package/dist/features/tui/terminal-compat.js +6 -2
  166. package/dist/features/tui/terminal-compat.js.map +2 -2
  167. package/dist/features/web/client/stores/task-store.js.map +2 -2
  168. package/dist/features/web/server/index.js +18 -10
  169. package/dist/features/web/server/index.js.map +2 -2
  170. package/dist/integrations/anthropic/client.js +259 -0
  171. package/dist/integrations/anthropic/client.js.map +7 -0
  172. package/dist/integrations/claude-code/subagent-client.js +404 -0
  173. package/dist/integrations/claude-code/subagent-client.js.map +7 -0
  174. package/dist/integrations/linear/sync-service.js +12 -13
  175. package/dist/integrations/linear/sync-service.js.map +2 -2
  176. package/dist/integrations/linear/sync.js +174 -12
  177. package/dist/integrations/linear/sync.js.map +2 -2
  178. package/dist/integrations/linear/unified-sync.js +1 -1
  179. package/dist/integrations/linear/unified-sync.js.map +1 -1
  180. package/dist/integrations/linear/webhook-server.js +15 -16
  181. package/dist/integrations/linear/webhook-server.js.map +2 -2
  182. package/dist/mcp/stackmemory-mcp-server.js +0 -11
  183. package/dist/mcp/stackmemory-mcp-server.js.map +2 -2
  184. package/dist/servers/production/auth-middleware.js.map +2 -2
  185. package/dist/servers/railway/index.js.map +2 -2
  186. package/dist/services/config-service.js +6 -7
  187. package/dist/services/config-service.js.map +2 -2
  188. package/dist/services/context-service.js +11 -12
  189. package/dist/services/context-service.js.map +2 -2
  190. package/dist/skills/claude-skills.js +101 -2
  191. package/dist/skills/claude-skills.js.map +2 -2
  192. package/dist/skills/dashboard-launcher.js.map +2 -2
  193. package/dist/skills/recursive-agent-orchestrator.js +559 -0
  194. package/dist/skills/recursive-agent-orchestrator.js.map +7 -0
  195. package/dist/skills/repo-ingestion-skill.js.map +2 -2
  196. package/dist/skills/security-secrets-scanner.js +265 -0
  197. package/dist/skills/security-secrets-scanner.js.map +7 -0
  198. package/dist/utils/env.js +46 -0
  199. package/dist/utils/env.js.map +7 -0
  200. package/dist/utils/logger.js +0 -11
  201. package/dist/utils/logger.js.map +2 -2
  202. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/core/monitoring/metrics.ts"],
4
- "sourcesContent": ["import { EventEmitter } from 'events';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { logger } from './logger.js';\n// Type-safe environment variable access\nfunction getEnv(key: string, defaultValue?: string): string {\n const value = process.env[key];\n if (value === undefined) {\n if (defaultValue !== undefined) return defaultValue;\n throw new Error(`Environment variable ${key} is required`);\n }\n return value;\n}\n\nfunction getOptionalEnv(key: string): string | undefined {\n return process.env[key];\n}\n\n\ninterface MetricEntry {\n timestamp: Date;\n metric: string;\n value: number;\n type: 'counter' | 'gauge' | 'timing';\n tags?: Record<string, string>;\n}\n\nclass MetricsCollector extends EventEmitter {\n private metrics: MetricEntry[] = [];\n private metricsFile?: string;\n private flushInterval: NodeJS.Timeout | null = null;\n private aggregates: Map<\n string,\n { sum: number; count: number; min: number; max: number }\n > = new Map();\n\n constructor() {\n super();\n\n // Set up metrics file if enabled\n if (process.env['STACKMEMORY_METRICS_ENABLED'] === 'true') {\n const metricsDir = path.join(\n process.env['HOME'] || '.',\n '.stackmemory',\n 'metrics'\n );\n if (!fs.existsSync(metricsDir)) {\n fs.mkdirSync(metricsDir, { recursive: true });\n }\n this.metricsFile = path.join(\n metricsDir,\n `metrics-${new Date().toISOString().split('T')[0]}.jsonl`\n );\n\n // Flush metrics every 30 seconds\n this.flushInterval = setInterval(() => this.flush(), 30000);\n }\n }\n\n async record(\n metric: string,\n value: number,\n tags?: Record<string, string>\n ): Promise<void> {\n const entry: MetricEntry = {\n timestamp: new Date(),\n metric,\n value,\n type: 'gauge',\n tags,\n };\n\n this.metrics.push(entry);\n this.updateAggregates(metric, value);\n this.emit('metric', entry);\n\n // Auto-flush if buffer is large\n if (this.metrics.length > 1000) {\n await this.flush();\n }\n }\n\n async increment(\n metric: string,\n tags?: Record<string, string>,\n value = 1\n ): Promise<void> {\n const entry: MetricEntry = {\n timestamp: new Date(),\n metric,\n value,\n type: 'counter',\n tags,\n };\n\n this.metrics.push(entry);\n this.updateAggregates(metric, value);\n this.emit('metric', entry);\n }\n\n async timing(\n metric: string,\n duration: number,\n tags?: Record<string, string>\n ): Promise<void> {\n const entry: MetricEntry = {\n timestamp: new Date(),\n metric,\n value: duration,\n type: 'timing',\n tags,\n };\n\n this.metrics.push(entry);\n this.updateAggregates(metric, duration);\n this.emit('metric', entry);\n }\n\n private updateAggregates(metric: string, value: number): void {\n const existing = this.aggregates.get(metric) || {\n sum: 0,\n count: 0,\n min: Infinity,\n max: -Infinity,\n };\n\n this.aggregates.set(metric, {\n sum: existing.sum + value,\n count: existing.count + 1,\n min: Math.min(existing.min, value),\n max: Math.max(existing.max, value),\n });\n }\n\n async flush(): Promise<void> {\n if (this.metrics.length === 0) return;\n\n const toFlush = [...this.metrics];\n this.metrics = [];\n\n if (this.metricsFile) {\n try {\n const lines = toFlush.map((m) => JSON.stringify(m)).join('\\n') + '\\n';\n await fs.promises.appendFile(this.metricsFile, lines);\n } catch (error: unknown) {\n logger.error(\n 'Failed to write metrics',\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n\n // Emit batch event for external processors\n this.emit('flush', toFlush);\n }\n\n getStats(metric?: string): Record<string, any> {\n if (metric) {\n const stats = this.aggregates.get(metric);\n if (!stats) return {};\n\n return {\n [metric]: {\n ...stats,\n avg: stats.count > 0 ? stats.sum / stats.count : 0,\n },\n };\n }\n\n const result: Record<string, any> = {};\n for (const [key, stats] of this.aggregates.entries()) {\n result[key] = {\n ...stats,\n avg: stats.count > 0 ? stats.sum / stats.count : 0,\n };\n }\n return result;\n }\n\n reset(): void {\n this.metrics = [];\n this.aggregates.clear();\n }\n\n destroy(): void {\n if (this.flushInterval) {\n clearInterval(this.flushInterval);\n this.flushInterval = null;\n }\n this.flush();\n }\n}\n\n// Singleton instance\nconst collector = new MetricsCollector();\n\n// Cleanup on exit\nprocess.on('beforeExit', () => collector.destroy());\n\nexport class Metrics {\n static async record(\n metric: string,\n value: number,\n tags?: Record<string, string>\n ): Promise<void> {\n await collector.record(metric, value, tags);\n }\n\n static async increment(\n metric: string,\n tags?: Record<string, string>\n ): Promise<void> {\n await collector.increment(metric, tags);\n }\n\n static async timing(\n metric: string,\n duration: number,\n tags?: Record<string, string>\n ): Promise<void> {\n await collector.timing(metric, duration, tags);\n }\n\n static getStats(metric?: string): Record<string, any> {\n return collector.getStats(metric);\n }\n\n static reset(): void {\n collector.reset();\n }\n\n static on(event: string, listener: (...args: any[]) => void): void {\n collector.on(event, listener);\n }\n}\n\nexport const metrics = Metrics;\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { EventEmitter } from 'events';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { logger } from './logger.js';\n// Type-safe environment variable access\nfunction getEnv(key: string, defaultValue?: string): string {\n const value = process.env[key];\n if (value === undefined) {\n if (defaultValue !== undefined) return defaultValue;\n throw new Error(`Environment variable ${key} is required`);\n }\n return value;\n}\n\nfunction getOptionalEnv(key: string): string | undefined {\n return process.env[key];\n}\n\ninterface MetricEntry {\n timestamp: Date;\n metric: string;\n value: number;\n type: 'counter' | 'gauge' | 'timing';\n tags?: Record<string, string>;\n}\n\nclass MetricsCollector extends EventEmitter {\n private metrics: MetricEntry[] = [];\n private metricsFile?: string;\n private flushInterval: NodeJS.Timeout | null = null;\n private aggregates: Map<\n string,\n { sum: number; count: number; min: number; max: number }\n > = new Map();\n\n constructor() {\n super();\n\n // Set up metrics file if enabled\n if (process.env['STACKMEMORY_METRICS_ENABLED'] === 'true') {\n const metricsDir = path.join(\n process.env['HOME'] || '.',\n '.stackmemory',\n 'metrics'\n );\n if (!fs.existsSync(metricsDir)) {\n fs.mkdirSync(metricsDir, { recursive: true });\n }\n this.metricsFile = path.join(\n metricsDir,\n `metrics-${new Date().toISOString().split('T')[0]}.jsonl`\n );\n\n // Flush metrics every 30 seconds\n this.flushInterval = setInterval(() => this.flush(), 30000);\n }\n }\n\n async record(\n metric: string,\n value: number,\n tags?: Record<string, string>\n ): Promise<void> {\n const entry: MetricEntry = {\n timestamp: new Date(),\n metric,\n value,\n type: 'gauge',\n tags,\n };\n\n this.metrics.push(entry);\n this.updateAggregates(metric, value);\n this.emit('metric', entry);\n\n // Auto-flush if buffer is large\n if (this.metrics.length > 1000) {\n await this.flush();\n }\n }\n\n async increment(\n metric: string,\n tags?: Record<string, string>,\n value = 1\n ): Promise<void> {\n const entry: MetricEntry = {\n timestamp: new Date(),\n metric,\n value,\n type: 'counter',\n tags,\n };\n\n this.metrics.push(entry);\n this.updateAggregates(metric, value);\n this.emit('metric', entry);\n }\n\n async timing(\n metric: string,\n duration: number,\n tags?: Record<string, string>\n ): Promise<void> {\n const entry: MetricEntry = {\n timestamp: new Date(),\n metric,\n value: duration,\n type: 'timing',\n tags,\n };\n\n this.metrics.push(entry);\n this.updateAggregates(metric, duration);\n this.emit('metric', entry);\n }\n\n private updateAggregates(metric: string, value: number): void {\n const existing = this.aggregates.get(metric) || {\n sum: 0,\n count: 0,\n min: Infinity,\n max: -Infinity,\n };\n\n this.aggregates.set(metric, {\n sum: existing.sum + value,\n count: existing.count + 1,\n min: Math.min(existing.min, value),\n max: Math.max(existing.max, value),\n });\n }\n\n async flush(): Promise<void> {\n if (this.metrics.length === 0) return;\n\n const toFlush = [...this.metrics];\n this.metrics = [];\n\n if (this.metricsFile) {\n try {\n const lines = toFlush.map((m) => JSON.stringify(m)).join('\\n') + '\\n';\n await fs.promises.appendFile(this.metricsFile, lines);\n } catch (error: unknown) {\n logger.error(\n 'Failed to write metrics',\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n\n // Emit batch event for external processors\n this.emit('flush', toFlush);\n }\n\n getStats(metric?: string): Record<string, any> {\n if (metric) {\n const stats = this.aggregates.get(metric);\n if (!stats) return {};\n\n return {\n [metric]: {\n ...stats,\n avg: stats.count > 0 ? stats.sum / stats.count : 0,\n },\n };\n }\n\n const result: Record<string, any> = {};\n for (const [key, stats] of this.aggregates.entries()) {\n result[key] = {\n ...stats,\n avg: stats.count > 0 ? stats.sum / stats.count : 0,\n };\n }\n return result;\n }\n\n reset(): void {\n this.metrics = [];\n this.aggregates.clear();\n }\n\n destroy(): void {\n if (this.flushInterval) {\n clearInterval(this.flushInterval);\n this.flushInterval = null;\n }\n this.flush();\n }\n}\n\n// Singleton instance\nconst collector = new MetricsCollector();\n\n// Cleanup on exit\nprocess.on('beforeExit', () => collector.destroy());\n\nexport class Metrics {\n static async record(\n metric: string,\n value: number,\n tags?: Record<string, string>\n ): Promise<void> {\n await collector.record(metric, value, tags);\n }\n\n static async increment(\n metric: string,\n tags?: Record<string, string>\n ): Promise<void> {\n await collector.increment(metric, tags);\n }\n\n static async timing(\n metric: string,\n duration: number,\n tags?: Record<string, string>\n ): Promise<void> {\n await collector.timing(metric, duration, tags);\n }\n\n static getStats(metric?: string): Record<string, any> {\n return collector.getStats(metric);\n }\n\n static reset(): void {\n collector.reset();\n }\n\n static on(event: string, listener: (...args: any[]) => void): void {\n collector.on(event, listener);\n }\n}\n\nexport const metrics = Metrics;\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/core/monitoring/progress-tracker.ts"],
4
- "sourcesContent": ["/**\n * Progress Tracker for StackMemory\n * Maintains a JSON file with recent changes and progress\n */\n\nimport { existsSync, readFileSync, writeFileSync } from 'fs';\nimport { join } from 'path';\n// Type-safe environment variable access\nfunction getEnv(key: string, defaultValue?: string): string {\n const value = process.env[key];\n if (value === undefined) {\n if (defaultValue !== undefined) return defaultValue;\n throw new Error(`Environment variable ${key} is required`);\n }\n return value;\n}\n\nfunction getOptionalEnv(key: string): string | undefined {\n return process.env[key];\n}\n\n\nexport interface TaskProgress {\n task: string;\n completedAt?: string;\n startedAt?: string;\n status: 'completed' | 'in_progress' | 'pending';\n changes?: string[];\n}\n\nexport interface Change {\n date: string;\n version: string;\n type: 'feature' | 'bugfix' | 'refactor' | 'docs';\n description: string;\n files?: string[];\n}\n\nexport interface ProgressData {\n version: string;\n lastUpdated: string;\n currentSession?: {\n startTime: string;\n tasksCompleted: TaskProgress[];\n inProgress: string[];\n };\n recentChanges: Change[];\n linearIntegration?: {\n status: string;\n lastSync?: string;\n tasksSynced?: number;\n issues?: string[];\n };\n roadmap?: {\n immediate: string[];\n thisWeek: string[];\n nextSprint: string[];\n };\n metrics?: Record<string, any>;\n notes?: string[];\n}\n\nexport class ProgressTracker {\n private progressFile: string;\n private data: ProgressData;\n\n constructor(projectRoot: string) {\n this.progressFile = join(projectRoot, '.stackmemory', 'progress.json');\n this.data = this.load();\n }\n\n /**\n * Load progress data from file\n */\n private load(): ProgressData {\n if (existsSync(this.progressFile)) {\n try {\n const content = readFileSync(this.progressFile, 'utf-8');\n return JSON.parse(content);\n } catch {\n // Start with empty data if file is corrupted\n }\n }\n\n // Default structure\n return {\n version: process.env['npm_package_version'] || '0.2.3',\n lastUpdated: new Date().toISOString(),\n recentChanges: [],\n };\n }\n\n /**\n * Save progress data to file\n */\n private save(): void {\n this.data.lastUpdated = new Date().toISOString();\n writeFileSync(this.progressFile, JSON.stringify(this.data, null, 2));\n }\n\n /**\n * Start a new session\n */\n startSession(): void {\n this.data.currentSession = {\n startTime: new Date().toISOString(),\n tasksCompleted: [],\n inProgress: [],\n };\n this.save();\n }\n\n /**\n * Add a task as in progress\n */\n startTask(task: string): void {\n if (!this.data.currentSession) {\n this.startSession();\n }\n\n if (this.data.currentSession!.inProgress.indexOf(task) === -1) {\n this.data.currentSession!.inProgress.push(task);\n }\n this.save();\n }\n\n /**\n * Mark a task as completed\n */\n completeTask(task: string, changes?: string[]): void {\n if (!this.data.currentSession) {\n this.startSession();\n }\n\n // Remove from in progress\n const index = this.data.currentSession!.inProgress.indexOf(task);\n if (index > -1) {\n this.data.currentSession!.inProgress.splice(index, 1);\n }\n\n // Add to completed\n this.data.currentSession!.tasksCompleted.push({\n task,\n completedAt: new Date().toISOString(),\n status: 'completed',\n changes,\n });\n\n this.save();\n }\n\n /**\n * Add a recent change\n */\n addChange(change: Change): void {\n // Keep only last 20 changes\n this.data.recentChanges.unshift(change);\n if (this.data.recentChanges.length > 20) {\n this.data.recentChanges = this.data.recentChanges.slice(0, 20);\n }\n this.save();\n }\n\n /**\n * Update Linear integration status\n */\n updateLinearStatus(status: {\n lastSync?: string;\n tasksSynced?: number;\n issues?: string[];\n }): void {\n if (!this.data.linearIntegration) {\n this.data.linearIntegration = {\n status: 'active',\n };\n }\n\n Object.assign(this.data.linearIntegration, status);\n this.save();\n }\n\n /**\n * Add a note\n */\n addNote(note: string): void {\n if (!this.data.notes) {\n this.data.notes = [];\n }\n\n // Add to beginning and keep last 10\n this.data.notes.unshift(note);\n if (this.data.notes.length > 10) {\n this.data.notes = this.data.notes.slice(0, 10);\n }\n this.save();\n }\n\n /**\n * Get current progress\n */\n getProgress(): ProgressData {\n return this.data;\n }\n\n /**\n * Get summary for display\n */\n getSummary(): string {\n const lines: string[] = [];\n\n lines.push(`\uD83D\uDCCA StackMemory Progress (v${this.data.version})`);\n lines.push(`Last updated: ${this.data.lastUpdated}`);\n\n if (this.data.currentSession) {\n lines.push('\\n\uD83D\uDCCD Current Session:');\n lines.push(` Started: ${this.data.currentSession.startTime}`);\n lines.push(\n ` Completed: ${this.data.currentSession.tasksCompleted.length} tasks`\n );\n\n if (this.data.currentSession.inProgress.length > 0) {\n lines.push(` In Progress:`);\n this.data.currentSession.inProgress.forEach((task) => {\n lines.push(` - ${task}`);\n });\n }\n }\n\n if (this.data.recentChanges.length > 0) {\n lines.push('\\n\uD83D\uDD04 Recent Changes:');\n this.data.recentChanges.slice(0, 5).forEach((change) => {\n lines.push(` [${change.date}] ${change.type}: ${change.description}`);\n });\n }\n\n if (this.data.linearIntegration) {\n lines.push('\\n\uD83D\uDD17 Linear Integration:');\n lines.push(` Status: ${this.data.linearIntegration.status}`);\n if (this.data.linearIntegration.lastSync) {\n lines.push(` Last sync: ${this.data.linearIntegration.lastSync}`);\n }\n if (this.data.linearIntegration.tasksSynced) {\n lines.push(\n ` Tasks synced: ${this.data.linearIntegration.tasksSynced}`\n );\n }\n }\n\n if (this.data.notes && this.data.notes.length > 0) {\n lines.push('\\n\uD83D\uDCDD Recent Notes:');\n this.data.notes.slice(0, 3).forEach((note) => {\n lines.push(` \u2022 ${note}`);\n });\n }\n\n return lines.join('\\n');\n }\n\n /**\n * Clear current session\n */\n endSession(): void {\n delete this.data.currentSession;\n this.save();\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Progress Tracker for StackMemory\n * Maintains a JSON file with recent changes and progress\n */\n\nimport { existsSync, readFileSync, writeFileSync } from 'fs';\nimport { join } from 'path';\n// Type-safe environment variable access\nfunction getEnv(key: string, defaultValue?: string): string {\n const value = process.env[key];\n if (value === undefined) {\n if (defaultValue !== undefined) return defaultValue;\n throw new Error(`Environment variable ${key} is required`);\n }\n return value;\n}\n\nfunction getOptionalEnv(key: string): string | undefined {\n return process.env[key];\n}\n\nexport interface TaskProgress {\n task: string;\n completedAt?: string;\n startedAt?: string;\n status: 'completed' | 'in_progress' | 'pending';\n changes?: string[];\n}\n\nexport interface Change {\n date: string;\n version: string;\n type: 'feature' | 'bugfix' | 'refactor' | 'docs';\n description: string;\n files?: string[];\n}\n\nexport interface ProgressData {\n version: string;\n lastUpdated: string;\n currentSession?: {\n startTime: string;\n tasksCompleted: TaskProgress[];\n inProgress: string[];\n };\n recentChanges: Change[];\n linearIntegration?: {\n status: string;\n lastSync?: string;\n tasksSynced?: number;\n issues?: string[];\n };\n roadmap?: {\n immediate: string[];\n thisWeek: string[];\n nextSprint: string[];\n };\n metrics?: Record<string, any>;\n notes?: string[];\n}\n\nexport class ProgressTracker {\n private progressFile: string;\n private data: ProgressData;\n\n constructor(projectRoot: string) {\n this.progressFile = join(projectRoot, '.stackmemory', 'progress.json');\n this.data = this.load();\n }\n\n /**\n * Load progress data from file\n */\n private load(): ProgressData {\n if (existsSync(this.progressFile)) {\n try {\n const content = readFileSync(this.progressFile, 'utf-8');\n return JSON.parse(content);\n } catch {\n // Start with empty data if file is corrupted\n }\n }\n\n // Default structure\n return {\n version: process.env['npm_package_version'] || '0.2.3',\n lastUpdated: new Date().toISOString(),\n recentChanges: [],\n };\n }\n\n /**\n * Save progress data to file\n */\n private save(): void {\n this.data.lastUpdated = new Date().toISOString();\n writeFileSync(this.progressFile, JSON.stringify(this.data, null, 2));\n }\n\n /**\n * Start a new session\n */\n startSession(): void {\n this.data.currentSession = {\n startTime: new Date().toISOString(),\n tasksCompleted: [],\n inProgress: [],\n };\n this.save();\n }\n\n /**\n * Add a task as in progress\n */\n startTask(task: string): void {\n if (!this.data.currentSession) {\n this.startSession();\n }\n\n if (this.data.currentSession!.inProgress.indexOf(task) === -1) {\n this.data.currentSession!.inProgress.push(task);\n }\n this.save();\n }\n\n /**\n * Mark a task as completed\n */\n completeTask(task: string, changes?: string[]): void {\n if (!this.data.currentSession) {\n this.startSession();\n }\n\n // Remove from in progress\n const index = this.data.currentSession!.inProgress.indexOf(task);\n if (index > -1) {\n this.data.currentSession!.inProgress.splice(index, 1);\n }\n\n // Add to completed\n this.data.currentSession!.tasksCompleted.push({\n task,\n completedAt: new Date().toISOString(),\n status: 'completed',\n changes,\n });\n\n this.save();\n }\n\n /**\n * Add a recent change\n */\n addChange(change: Change): void {\n // Keep only last 20 changes\n this.data.recentChanges.unshift(change);\n if (this.data.recentChanges.length > 20) {\n this.data.recentChanges = this.data.recentChanges.slice(0, 20);\n }\n this.save();\n }\n\n /**\n * Update Linear integration status\n */\n updateLinearStatus(status: {\n lastSync?: string;\n tasksSynced?: number;\n issues?: string[];\n }): void {\n if (!this.data.linearIntegration) {\n this.data.linearIntegration = {\n status: 'active',\n };\n }\n\n Object.assign(this.data.linearIntegration, status);\n this.save();\n }\n\n /**\n * Add a note\n */\n addNote(note: string): void {\n if (!this.data.notes) {\n this.data.notes = [];\n }\n\n // Add to beginning and keep last 10\n this.data.notes.unshift(note);\n if (this.data.notes.length > 10) {\n this.data.notes = this.data.notes.slice(0, 10);\n }\n this.save();\n }\n\n /**\n * Get current progress\n */\n getProgress(): ProgressData {\n return this.data;\n }\n\n /**\n * Get summary for display\n */\n getSummary(): string {\n const lines: string[] = [];\n\n lines.push(`\uD83D\uDCCA StackMemory Progress (v${this.data.version})`);\n lines.push(`Last updated: ${this.data.lastUpdated}`);\n\n if (this.data.currentSession) {\n lines.push('\\n\uD83D\uDCCD Current Session:');\n lines.push(` Started: ${this.data.currentSession.startTime}`);\n lines.push(\n ` Completed: ${this.data.currentSession.tasksCompleted.length} tasks`\n );\n\n if (this.data.currentSession.inProgress.length > 0) {\n lines.push(` In Progress:`);\n this.data.currentSession.inProgress.forEach((task) => {\n lines.push(` - ${task}`);\n });\n }\n }\n\n if (this.data.recentChanges.length > 0) {\n lines.push('\\n\uD83D\uDD04 Recent Changes:');\n this.data.recentChanges.slice(0, 5).forEach((change) => {\n lines.push(` [${change.date}] ${change.type}: ${change.description}`);\n });\n }\n\n if (this.data.linearIntegration) {\n lines.push('\\n\uD83D\uDD17 Linear Integration:');\n lines.push(` Status: ${this.data.linearIntegration.status}`);\n if (this.data.linearIntegration.lastSync) {\n lines.push(` Last sync: ${this.data.linearIntegration.lastSync}`);\n }\n if (this.data.linearIntegration.tasksSynced) {\n lines.push(\n ` Tasks synced: ${this.data.linearIntegration.tasksSynced}`\n );\n }\n }\n\n if (this.data.notes && this.data.notes.length > 0) {\n lines.push('\\n\uD83D\uDCDD Recent Notes:');\n this.data.notes.slice(0, 3).forEach((note) => {\n lines.push(` \u2022 ${note}`);\n });\n }\n\n return lines.join('\\n');\n }\n\n /**\n * Clear current session\n */\n endSession(): void {\n delete this.data.currentSession;\n this.save();\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/core/performance/context-cache.ts"],
4
- "sourcesContent": ["/**\n * High-Performance Context Cache\n * LRU cache with TTL for frequently accessed context data\n */\n\nimport { EventEmitter } from 'events';\nimport { logger } from '../monitoring/logger.js';\n\nexport interface CacheEntry<T> {\n value: T;\n size: number;\n hits: number;\n createdAt: number;\n lastAccessed: number;\n ttl?: number;\n}\n\nexport interface CacheStats {\n hits: number;\n misses: number;\n evictions: number;\n size: number;\n itemCount: number;\n hitRate: number;\n avgAccessTime: number;\n}\n\nexport interface CacheOptions {\n maxSize?: number; // Max memory in bytes\n maxItems?: number; // Max number of items\n defaultTTL?: number; // Default TTL in ms\n enableStats?: boolean;\n onEvict?: (key: string, entry: CacheEntry<any>) => void;\n}\n\nexport class ContextCache<T = any> extends EventEmitter {\n private cache = new Map<string, CacheEntry<T>>();\n private accessOrder: string[] = [];\n private options: Required<CacheOptions>;\n private stats: CacheStats;\n private currentSize = 0;\n\n constructor(options: CacheOptions = {}) {\n super();\n this.options = {\n maxSize: options.maxSize || 100 * 1024 * 1024, // 100MB default\n maxItems: options.maxItems || 10000,\n defaultTTL: options.defaultTTL || 3600000, // 1 hour default\n enableStats: options.enableStats ?? true,\n onEvict: options.onEvict || (() => {}),\n };\n\n this.stats = {\n hits: 0,\n misses: 0,\n evictions: 0,\n size: 0,\n itemCount: 0,\n hitRate: 0,\n avgAccessTime: 0,\n };\n }\n\n /**\n * Get item from cache\n */\n get(key: string): T | undefined {\n const startTime = Date.now();\n const entry = this.cache.get(key);\n\n if (!entry) {\n this.stats.misses++;\n this.updateHitRate();\n return undefined;\n }\n\n // Check TTL\n if (entry.ttl && Date.now() - entry.createdAt > entry.ttl) {\n this.delete(key);\n this.stats.misses++;\n this.updateHitRate();\n return undefined;\n }\n\n // Update access tracking\n entry.hits++;\n entry.lastAccessed = Date.now();\n this.updateAccessOrder(key);\n\n this.stats.hits++;\n this.updateHitRate();\n this.updateAvgAccessTime(Date.now() - startTime);\n\n return entry.value;\n }\n\n /**\n * Set item in cache\n */\n set(key: string, value: T, options: { ttl?: number; size?: number } = {}): void {\n const size = options.size || this.estimateSize(value);\n const ttl = options.ttl ?? this.options.defaultTTL;\n\n // Check if we need to evict\n if (this.cache.size >= this.options.maxItems || \n this.currentSize + size > this.options.maxSize) {\n this.evict(size);\n }\n\n // Remove old entry if exists\n if (this.cache.has(key)) {\n this.delete(key);\n }\n\n const entry: CacheEntry<T> = {\n value,\n size,\n hits: 0,\n createdAt: Date.now(),\n lastAccessed: Date.now(),\n ttl,\n };\n\n this.cache.set(key, entry);\n this.accessOrder.push(key);\n this.currentSize += size;\n this.stats.size = this.currentSize;\n this.stats.itemCount = this.cache.size;\n\n this.emit('set', key, value);\n }\n\n /**\n * Delete item from cache\n */\n delete(key: string): boolean {\n const entry = this.cache.get(key);\n if (!entry) return false;\n\n this.cache.delete(key);\n this.currentSize -= entry.size;\n this.accessOrder = this.accessOrder.filter((k: any) => k !== key);\n \n this.stats.size = this.currentSize;\n this.stats.itemCount = this.cache.size;\n\n this.emit('delete', key);\n return true;\n }\n\n /**\n * Clear entire cache\n */\n clear(): void {\n const oldSize = this.cache.size;\n this.cache.clear();\n this.accessOrder = [];\n this.currentSize = 0;\n \n this.stats.size = 0;\n this.stats.itemCount = 0;\n this.stats.evictions += oldSize;\n\n this.emit('clear');\n }\n\n /**\n * Check if key exists and is valid\n */\n has(key: string): boolean {\n const entry = this.cache.get(key);\n if (!entry) return false;\n \n // Check TTL\n if (entry.ttl && Date.now() - entry.createdAt > entry.ttl) {\n this.delete(key);\n return false;\n }\n \n return true;\n }\n\n /**\n * Get cache statistics\n */\n getStats(): CacheStats {\n return { ...this.stats };\n }\n\n /**\n * Get cache size info\n */\n getSize(): { bytes: number; items: number; utilization: number } {\n return {\n bytes: this.currentSize,\n items: this.cache.size,\n utilization: this.currentSize / this.options.maxSize,\n };\n }\n\n /**\n * Preload multiple items\n */\n preload(entries: Array<{ key: string; value: T; ttl?: number; size?: number }>): void {\n const startTime = Date.now();\n \n for (const entry of entries) {\n this.set(entry.key, entry.value, {\n ttl: entry.ttl,\n size: entry.size,\n });\n }\n\n logger.debug('Cache preload complete', {\n items: entries.length,\n duration: Date.now() - startTime,\n cacheSize: this.currentSize,\n });\n }\n\n /**\n * Get multiple items efficiently\n */\n getMany(keys: string[]): Map<string, T> {\n const results = new Map<string, T>();\n \n for (const key of keys) {\n const value = this.get(key);\n if (value !== undefined) {\n results.set(key, value);\n }\n }\n \n return results;\n }\n\n /**\n * Warm cache with computed values\n */\n async warmUp(\n keys: string[],\n compute: (key: string) => Promise<T>,\n options: { ttl?: number; parallel?: boolean } = {}\n ): Promise<void> {\n const { parallel = true } = options;\n \n if (parallel) {\n const promises = keys.map(async key => {\n if (!this.has(key)) {\n const value = await compute(key);\n this.set(key, value, { ttl: options.ttl });\n }\n });\n await Promise.all(promises);\n } else {\n for (const key of keys) {\n if (!this.has(key)) {\n const value = await compute(key);\n this.set(key, value, { ttl: options.ttl });\n }\n }\n }\n }\n\n /**\n * Get or compute value\n */\n async getOrCompute(\n key: string,\n compute: () => Promise<T>,\n options: { ttl?: number; size?: number } = {}\n ): Promise<T> {\n const cached = this.get(key);\n if (cached !== undefined) {\n return cached;\n }\n\n const value = await compute();\n this.set(key, value, options);\n return value;\n }\n\n // Private methods\n\n private evict(requiredSize: number): void {\n const startEvictions = this.stats.evictions;\n \n // LRU eviction\n while ((this.cache.size >= this.options.maxItems || \n this.currentSize + requiredSize > this.options.maxSize) && \n this.accessOrder.length > 0) {\n const keyToEvict = this.accessOrder.shift()!;\n const entry = this.cache.get(keyToEvict);\n \n if (entry) {\n this.cache.delete(keyToEvict);\n this.currentSize -= entry.size;\n this.stats.evictions++;\n this.options.onEvict(keyToEvict, entry);\n this.emit('evict', keyToEvict, entry);\n }\n }\n\n if (this.stats.evictions > startEvictions) {\n logger.debug('Cache eviction', {\n evicted: this.stats.evictions - startEvictions,\n currentSize: this.currentSize,\n requiredSize,\n });\n }\n }\n\n private updateAccessOrder(key: string): void {\n const index = this.accessOrder.indexOf(key);\n if (index > -1) {\n this.accessOrder.splice(index, 1);\n }\n this.accessOrder.push(key);\n }\n\n private estimateSize(value: T): number {\n // Simple size estimation - can be overridden for specific types\n if (typeof value === 'string') {\n return value.length * 2; // UTF-16\n }\n if (typeof value === 'object' && value !== null) {\n return JSON.stringify(value).length * 2;\n }\n return 8; // Default for primitives\n }\n\n private updateHitRate(): void {\n const total = this.stats.hits + this.stats.misses;\n this.stats.hitRate = total > 0 ? this.stats.hits / total : 0;\n }\n\n private updateAvgAccessTime(time: number): void {\n const alpha = 0.1; // Exponential moving average factor\n this.stats.avgAccessTime = this.stats.avgAccessTime * (1 - alpha) + time * alpha;\n }\n\n /**\n * Cleanup expired entries periodically\n */\n startCleanup(intervalMs: number = 60000): NodeJS.Timeout {\n return setInterval(() => {\n let cleaned = 0;\n for (const [key, entry] of this.cache.entries()) {\n if (entry.ttl && Date.now() - entry.createdAt > entry.ttl) {\n this.delete(key);\n cleaned++;\n }\n }\n if (cleaned > 0) {\n logger.debug('Cache cleanup', { cleaned, remaining: this.cache.size });\n }\n }, intervalMs);\n }\n}"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * High-Performance Context Cache\n * LRU cache with TTL for frequently accessed context data\n */\n\nimport { EventEmitter } from 'events';\nimport { logger } from '../monitoring/logger.js';\n\nexport interface CacheEntry<T> {\n value: T;\n size: number;\n hits: number;\n createdAt: number;\n lastAccessed: number;\n ttl?: number;\n}\n\nexport interface CacheStats {\n hits: number;\n misses: number;\n evictions: number;\n size: number;\n itemCount: number;\n hitRate: number;\n avgAccessTime: number;\n}\n\nexport interface CacheOptions {\n maxSize?: number; // Max memory in bytes\n maxItems?: number; // Max number of items\n defaultTTL?: number; // Default TTL in ms\n enableStats?: boolean;\n onEvict?: (key: string, entry: CacheEntry<any>) => void;\n}\n\nexport class ContextCache<T = any> extends EventEmitter {\n private cache = new Map<string, CacheEntry<T>>();\n private accessOrder: string[] = [];\n private options: Required<CacheOptions>;\n private stats: CacheStats;\n private currentSize = 0;\n\n constructor(options: CacheOptions = {}) {\n super();\n this.options = {\n maxSize: options.maxSize || 100 * 1024 * 1024, // 100MB default\n maxItems: options.maxItems || 10000,\n defaultTTL: options.defaultTTL || 3600000, // 1 hour default\n enableStats: options.enableStats ?? true,\n onEvict: options.onEvict || (() => {}),\n };\n\n this.stats = {\n hits: 0,\n misses: 0,\n evictions: 0,\n size: 0,\n itemCount: 0,\n hitRate: 0,\n avgAccessTime: 0,\n };\n }\n\n /**\n * Get item from cache\n */\n get(key: string): T | undefined {\n const startTime = Date.now();\n const entry = this.cache.get(key);\n\n if (!entry) {\n this.stats.misses++;\n this.updateHitRate();\n return undefined;\n }\n\n // Check TTL\n if (entry.ttl && Date.now() - entry.createdAt > entry.ttl) {\n this.delete(key);\n this.stats.misses++;\n this.updateHitRate();\n return undefined;\n }\n\n // Update access tracking\n entry.hits++;\n entry.lastAccessed = Date.now();\n this.updateAccessOrder(key);\n\n this.stats.hits++;\n this.updateHitRate();\n this.updateAvgAccessTime(Date.now() - startTime);\n\n return entry.value;\n }\n\n /**\n * Set item in cache\n */\n set(\n key: string,\n value: T,\n options: { ttl?: number; size?: number } = {}\n ): void {\n const size = options.size || this.estimateSize(value);\n const ttl = options.ttl ?? this.options.defaultTTL;\n\n // Check if we need to evict\n if (\n this.cache.size >= this.options.maxItems ||\n this.currentSize + size > this.options.maxSize\n ) {\n this.evict(size);\n }\n\n // Remove old entry if exists\n if (this.cache.has(key)) {\n this.delete(key);\n }\n\n const entry: CacheEntry<T> = {\n value,\n size,\n hits: 0,\n createdAt: Date.now(),\n lastAccessed: Date.now(),\n ttl,\n };\n\n this.cache.set(key, entry);\n this.accessOrder.push(key);\n this.currentSize += size;\n this.stats.size = this.currentSize;\n this.stats.itemCount = this.cache.size;\n\n this.emit('set', key, value);\n }\n\n /**\n * Delete item from cache\n */\n delete(key: string): boolean {\n const entry = this.cache.get(key);\n if (!entry) return false;\n\n this.cache.delete(key);\n this.currentSize -= entry.size;\n this.accessOrder = this.accessOrder.filter((k: any) => k !== key);\n\n this.stats.size = this.currentSize;\n this.stats.itemCount = this.cache.size;\n\n this.emit('delete', key);\n return true;\n }\n\n /**\n * Clear entire cache\n */\n clear(): void {\n const oldSize = this.cache.size;\n this.cache.clear();\n this.accessOrder = [];\n this.currentSize = 0;\n\n this.stats.size = 0;\n this.stats.itemCount = 0;\n this.stats.evictions += oldSize;\n\n this.emit('clear');\n }\n\n /**\n * Check if key exists and is valid\n */\n has(key: string): boolean {\n const entry = this.cache.get(key);\n if (!entry) return false;\n\n // Check TTL\n if (entry.ttl && Date.now() - entry.createdAt > entry.ttl) {\n this.delete(key);\n return false;\n }\n\n return true;\n }\n\n /**\n * Get cache statistics\n */\n getStats(): CacheStats {\n return { ...this.stats };\n }\n\n /**\n * Get cache size info\n */\n getSize(): { bytes: number; items: number; utilization: number } {\n return {\n bytes: this.currentSize,\n items: this.cache.size,\n utilization: this.currentSize / this.options.maxSize,\n };\n }\n\n /**\n * Preload multiple items\n */\n preload(\n entries: Array<{ key: string; value: T; ttl?: number; size?: number }>\n ): void {\n const startTime = Date.now();\n\n for (const entry of entries) {\n this.set(entry.key, entry.value, {\n ttl: entry.ttl,\n size: entry.size,\n });\n }\n\n logger.debug('Cache preload complete', {\n items: entries.length,\n duration: Date.now() - startTime,\n cacheSize: this.currentSize,\n });\n }\n\n /**\n * Get multiple items efficiently\n */\n getMany(keys: string[]): Map<string, T> {\n const results = new Map<string, T>();\n\n for (const key of keys) {\n const value = this.get(key);\n if (value !== undefined) {\n results.set(key, value);\n }\n }\n\n return results;\n }\n\n /**\n * Warm cache with computed values\n */\n async warmUp(\n keys: string[],\n compute: (key: string) => Promise<T>,\n options: { ttl?: number; parallel?: boolean } = {}\n ): Promise<void> {\n const { parallel = true } = options;\n\n if (parallel) {\n const promises = keys.map(async (key) => {\n if (!this.has(key)) {\n const value = await compute(key);\n this.set(key, value, { ttl: options.ttl });\n }\n });\n await Promise.all(promises);\n } else {\n for (const key of keys) {\n if (!this.has(key)) {\n const value = await compute(key);\n this.set(key, value, { ttl: options.ttl });\n }\n }\n }\n }\n\n /**\n * Get or compute value\n */\n async getOrCompute(\n key: string,\n compute: () => Promise<T>,\n options: { ttl?: number; size?: number } = {}\n ): Promise<T> {\n const cached = this.get(key);\n if (cached !== undefined) {\n return cached;\n }\n\n const value = await compute();\n this.set(key, value, options);\n return value;\n }\n\n // Private methods\n\n private evict(requiredSize: number): void {\n const startEvictions = this.stats.evictions;\n\n // LRU eviction\n while (\n (this.cache.size >= this.options.maxItems ||\n this.currentSize + requiredSize > this.options.maxSize) &&\n this.accessOrder.length > 0\n ) {\n const keyToEvict = this.accessOrder.shift()!;\n const entry = this.cache.get(keyToEvict);\n\n if (entry) {\n this.cache.delete(keyToEvict);\n this.currentSize -= entry.size;\n this.stats.evictions++;\n this.options.onEvict(keyToEvict, entry);\n this.emit('evict', keyToEvict, entry);\n }\n }\n\n if (this.stats.evictions > startEvictions) {\n logger.debug('Cache eviction', {\n evicted: this.stats.evictions - startEvictions,\n currentSize: this.currentSize,\n requiredSize,\n });\n }\n }\n\n private updateAccessOrder(key: string): void {\n const index = this.accessOrder.indexOf(key);\n if (index > -1) {\n this.accessOrder.splice(index, 1);\n }\n this.accessOrder.push(key);\n }\n\n private estimateSize(value: T): number {\n // Simple size estimation - can be overridden for specific types\n if (typeof value === 'string') {\n return value.length * 2; // UTF-16\n }\n if (typeof value === 'object' && value !== null) {\n return JSON.stringify(value).length * 2;\n }\n return 8; // Default for primitives\n }\n\n private updateHitRate(): void {\n const total = this.stats.hits + this.stats.misses;\n this.stats.hitRate = total > 0 ? this.stats.hits / total : 0;\n }\n\n private updateAvgAccessTime(time: number): void {\n const alpha = 0.1; // Exponential moving average factor\n this.stats.avgAccessTime =\n this.stats.avgAccessTime * (1 - alpha) + time * alpha;\n }\n\n /**\n * Cleanup expired entries periodically\n */\n startCleanup(intervalMs: number = 60000): NodeJS.Timeout {\n return setInterval(() => {\n let cleaned = 0;\n for (const [key, entry] of this.cache.entries()) {\n if (entry.ttl && Date.now() - entry.createdAt > entry.ttl) {\n this.delete(key);\n cleaned++;\n }\n }\n if (cleaned > 0) {\n logger.debug('Cache cleanup', { cleaned, remaining: this.cache.size });\n }\n }, intervalMs);\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -48,13 +48,16 @@ class LazyContextLoader {
48
48
  */
49
49
  lazyFrame(frameId) {
50
50
  if (!this.frameLoaders.has(frameId)) {
51
- this.frameLoaders.set(frameId, new LazyProxy(async () => {
52
- const frame = this.loadFrame(frameId);
53
- if (!frame) {
54
- throw new Error(`Frame not found: ${frameId}`);
55
- }
56
- return frame;
57
- }));
51
+ this.frameLoaders.set(
52
+ frameId,
53
+ new LazyProxy(async () => {
54
+ const frame = this.loadFrame(frameId);
55
+ if (!frame) {
56
+ throw new Error(`Frame not found: ${frameId}`);
57
+ }
58
+ return frame;
59
+ })
60
+ );
58
61
  }
59
62
  return this.frameLoaders.get(frameId);
60
63
  }
@@ -63,9 +66,12 @@ class LazyContextLoader {
63
66
  */
64
67
  lazyAnchors(frameId) {
65
68
  if (!this.anchorLoaders.has(frameId)) {
66
- this.anchorLoaders.set(frameId, new LazyProxy(async () => {
67
- return this.loadAnchors(frameId);
68
- }));
69
+ this.anchorLoaders.set(
70
+ frameId,
71
+ new LazyProxy(async () => {
72
+ return this.loadAnchors(frameId);
73
+ })
74
+ );
69
75
  }
70
76
  return this.anchorLoaders.get(frameId);
71
77
  }
@@ -75,9 +81,12 @@ class LazyContextLoader {
75
81
  lazyEvents(frameId, limit = 100) {
76
82
  const key = `${frameId}:${limit}`;
77
83
  if (!this.eventLoaders.has(key)) {
78
- this.eventLoaders.set(key, new LazyProxy(async () => {
79
- return this.loadEvents(frameId, limit);
80
- }));
84
+ this.eventLoaders.set(
85
+ key,
86
+ new LazyProxy(async () => {
87
+ return this.loadEvents(frameId, limit);
88
+ })
89
+ );
81
90
  }
82
91
  return this.eventLoaders.get(key);
83
92
  }
@@ -85,10 +94,7 @@ class LazyContextLoader {
85
94
  * Progressive context loading with chunking
86
95
  */
87
96
  async *loadContextProgressive(frameIds, options = {}) {
88
- const {
89
- chunkSize = 10,
90
- priority = "recency"
91
- } = options;
97
+ const { chunkSize = 10, priority = "recency" } = options;
92
98
  const sortedIds = this.sortByPriority(frameIds, priority);
93
99
  const totalChunks = Math.ceil(sortedIds.length / chunkSize);
94
100
  for (let i = 0; i < sortedIds.length; i += chunkSize) {
@@ -220,9 +226,7 @@ class LazyContextLoader {
220
226
  // Private methods
221
227
  loadFrame(frameId) {
222
228
  try {
223
- const row = this.db.prepare(
224
- "SELECT * FROM frames WHERE id = ?"
225
- ).get(frameId);
229
+ const row = this.db.prepare("SELECT * FROM frames WHERE id = ?").get(frameId);
226
230
  if (!row) return null;
227
231
  return {
228
232
  ...row,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/core/performance/lazy-context-loader.ts"],
4
- "sourcesContent": ["/**\n * Lazy Context Loader\n * Deferred loading and progressive enhancement for context data\n */\n\nimport Database from 'better-sqlite3';\nimport { Frame, Anchor, Event } from '../context/frame-manager.js';\nimport { logger } from '../monitoring/logger.js';\n\nexport interface LazyLoadOptions {\n preloadDepth?: number; // How many levels to preload\n chunkSize?: number; // Items per chunk\n priority?: 'recency' | 'relevance' | 'frequency';\n}\n\nexport interface ContextChunk {\n frames: Frame[];\n anchors: Anchor[];\n events: Event[];\n metadata: {\n chunkId: number;\n totalChunks: number;\n hasMore: boolean;\n nextCursor?: string;\n };\n}\n\n/**\n * Lazy proxy for deferred data loading\n */\nexport class LazyProxy<T> {\n private _value?: T;\n private _promise?: Promise<T>;\n private _loader: () => Promise<T>;\n private _loaded = false;\n\n constructor(loader: () => Promise<T>) {\n this._loader = loader;\n }\n\n async get(): Promise<T> {\n if (this._loaded && this._value !== undefined) {\n return this._value;\n }\n\n if (!this._promise) {\n this._promise = this._loader().then(value => {\n this._value = value;\n this._loaded = true;\n return value;\n });\n }\n\n return this._promise;\n }\n\n isLoaded(): boolean {\n return this._loaded;\n }\n\n peek(): T | undefined {\n return this._value;\n }\n\n reset(): void {\n this._value = undefined;\n this._promise = undefined;\n this._loaded = false;\n }\n}\n\nexport class LazyContextLoader {\n private db: Database.Database;\n private projectId: string;\n \n // Lazy loading registries\n private frameLoaders = new Map<string, LazyProxy<Frame>>();\n private anchorLoaders = new Map<string, LazyProxy<Anchor[]>>();\n private eventLoaders = new Map<string, LazyProxy<Event[]>>();\n \n constructor(db: Database.Database, projectId: string) {\n this.db = db;\n this.projectId = projectId;\n }\n\n /**\n * Create a lazy frame reference\n */\n lazyFrame(frameId: string): LazyProxy<Frame> {\n if (!this.frameLoaders.has(frameId)) {\n this.frameLoaders.set(frameId, new LazyProxy(async () => {\n const frame = this.loadFrame(frameId);\n if (!frame) {\n throw new Error(`Frame not found: ${frameId}`);\n }\n return frame;\n }));\n }\n return this.frameLoaders.get(frameId)!;\n }\n\n /**\n * Create lazy anchor references\n */\n lazyAnchors(frameId: string): LazyProxy<Anchor[]> {\n if (!this.anchorLoaders.has(frameId)) {\n this.anchorLoaders.set(frameId, new LazyProxy(async () => {\n return this.loadAnchors(frameId);\n }));\n }\n return this.anchorLoaders.get(frameId)!;\n }\n\n /**\n * Create lazy event references\n */\n lazyEvents(frameId: string, limit = 100): LazyProxy<Event[]> {\n const key = `${frameId}:${limit}`;\n if (!this.eventLoaders.has(key)) {\n this.eventLoaders.set(key, new LazyProxy(async () => {\n return this.loadEvents(frameId, limit);\n }));\n }\n return this.eventLoaders.get(key)!;\n }\n\n /**\n * Progressive context loading with chunking\n */\n async* loadContextProgressive(\n frameIds: string[],\n options: LazyLoadOptions = {}\n ): AsyncGenerator<ContextChunk, void, unknown> {\n const {\n chunkSize = 10,\n priority = 'recency',\n } = options;\n\n // Sort frame IDs by priority\n const sortedIds = this.sortByPriority(frameIds, priority);\n const totalChunks = Math.ceil(sortedIds.length / chunkSize);\n\n for (let i = 0; i < sortedIds.length; i += chunkSize) {\n const chunkIds = sortedIds.slice(i, i + chunkSize);\n const chunkNumber = Math.floor(i / chunkSize) + 1;\n\n const frames: Frame[] = [];\n const anchors: Anchor[] = [];\n const events: Event[] = [];\n\n // Load chunk data\n for (const frameId of chunkIds) {\n const frame = await this.lazyFrame(frameId).get();\n frames.push(frame);\n\n // Load associated data\n const frameAnchors = await this.lazyAnchors(frameId).get();\n anchors.push(...frameAnchors);\n\n const frameEvents = await this.lazyEvents(frameId).get();\n events.push(...frameEvents);\n }\n\n yield {\n frames,\n anchors,\n events,\n metadata: {\n chunkId: chunkNumber,\n totalChunks,\n hasMore: i + chunkSize < sortedIds.length,\n nextCursor: i + chunkSize < sortedIds.length \n ? sortedIds[i + chunkSize] \n : undefined,\n },\n };\n }\n }\n\n /**\n * Preload context data for better performance\n */\n async preloadContext(\n frameIds: string[],\n options: { parallel?: boolean; depth?: number } = {}\n ): Promise<void> {\n const { parallel = true, depth = 1 } = options;\n const startTime = Date.now();\n\n if (parallel) {\n const promises: Promise<any>[] = [];\n \n for (const frameId of frameIds) {\n promises.push(this.lazyFrame(frameId).get());\n \n if (depth > 0) {\n promises.push(this.lazyAnchors(frameId).get());\n }\n \n if (depth > 1) {\n promises.push(this.lazyEvents(frameId).get());\n }\n }\n \n await Promise.all(promises);\n } else {\n for (const frameId of frameIds) {\n await this.lazyFrame(frameId).get();\n \n if (depth > 0) {\n await this.lazyAnchors(frameId).get();\n }\n \n if (depth > 1) {\n await this.lazyEvents(frameId).get();\n }\n }\n }\n\n logger.debug('Context preload complete', {\n frames: frameIds.length,\n depth,\n duration: Date.now() - startTime,\n });\n }\n\n /**\n * Load only frame headers (lightweight)\n */\n async loadFrameHeaders(frameIds: string[]): Promise<Map<string, any>> {\n const placeholders = frameIds.map(() => '?').join(',');\n const query = `\n SELECT id, type, name, state, score, created_at, updated_at\n FROM frames \n WHERE id IN (${placeholders})\n `;\n\n const rows = this.db.prepare(query).all(...frameIds) as any[];\n const headers = new Map<string, any>();\n\n for (const row of rows) {\n headers.set(row.id, {\n id: row.id,\n type: row.type,\n name: row.name,\n state: row.state,\n score: row.score,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n });\n }\n\n return headers;\n }\n\n /**\n * Stream context data for memory efficiency\n */\n async* streamContext(\n query: string,\n params: any[] = []\n ): AsyncGenerator<Frame | Anchor | Event, void, unknown> {\n const stmt = this.db.prepare(query);\n const iterator = stmt.iterate(...params);\n\n for (const row of iterator) {\n yield row as any;\n }\n }\n\n /**\n * Clear lazy loading cache\n */\n clearCache(): void {\n this.frameLoaders.clear();\n this.anchorLoaders.clear();\n this.eventLoaders.clear();\n }\n\n /**\n * Get cache statistics\n */\n getCacheStats(): {\n frames: number;\n anchors: number;\n events: number;\n loaded: number;\n } {\n let loaded = 0;\n \n for (const loader of this.frameLoaders.values()) {\n if (loader.isLoaded()) loaded++;\n }\n \n for (const loader of this.anchorLoaders.values()) {\n if (loader.isLoaded()) loaded++;\n }\n \n for (const loader of this.eventLoaders.values()) {\n if (loader.isLoaded()) loaded++;\n }\n\n return {\n frames: this.frameLoaders.size,\n anchors: this.anchorLoaders.size,\n events: this.eventLoaders.size,\n loaded,\n };\n }\n\n // Private methods\n\n private loadFrame(frameId: string): Frame | null {\n try {\n const row = this.db.prepare(\n 'SELECT * FROM frames WHERE id = ?'\n ).get(frameId) as any;\n\n if (!row) return null;\n\n return {\n ...row,\n metadata: JSON.parse(row.metadata || '{}'),\n };\n } catch (error: unknown) {\n // Return mock frame if table doesn't exist (for benchmarking)\n if (frameId.startsWith('frame-')) {\n return {\n id: frameId,\n type: 'mock',\n name: `Mock ${frameId}`,\n state: 'open',\n score: 0.5,\n created_at: Date.now(),\n updated_at: Date.now(),\n metadata: {},\n } as any;\n }\n return null;\n }\n }\n\n private loadAnchors(frameId: string): Anchor[] {\n try {\n const rows = this.db.prepare(\n 'SELECT * FROM anchors WHERE frame_id = ? ORDER BY priority DESC, created_at DESC'\n ).all(frameId) as any[];\n\n return rows.map((row: any) => ({\n ...row,\n metadata: JSON.parse(row.metadata || '{}'),\n }));\n } catch {\n return []; // Return empty array if table doesn't exist\n }\n }\n\n private loadEvents(frameId: string, limit: number): Event[] {\n try {\n const rows = this.db.prepare(\n 'SELECT * FROM events WHERE frame_id = ? ORDER BY timestamp DESC LIMIT ?'\n ).all(frameId, limit) as any[];\n\n return rows.map((row: any) => ({\n ...row,\n data: JSON.parse(row.data || '{}'),\n metadata: JSON.parse(row.metadata || '{}'),\n }));\n } catch {\n return []; // Return empty array if table doesn't exist\n }\n }\n\n private sortByPriority(\n frameIds: string[],\n priority: 'recency' | 'relevance' | 'frequency'\n ): string[] {\n try {\n switch (priority) {\n case 'recency': {\n // Get timestamps and sort\n const query = `\n SELECT id, updated_at FROM frames \n WHERE id IN (${frameIds.map(() => '?').join(',')})\n ORDER BY updated_at DESC\n `;\n const rows = this.db.prepare(query).all(...frameIds) as any[];\n return rows.map((r: any) => r.id);\n }\n \n case 'relevance': {\n // Get scores and sort\n const query = `\n SELECT id, score FROM frames \n WHERE id IN (${frameIds.map(() => '?').join(',')})\n ORDER BY score DESC\n `;\n const rows = this.db.prepare(query).all(...frameIds) as any[];\n return rows.map((r: any) => r.id);\n }\n \n case 'frequency': {\n // Get event counts and sort\n const query = `\n SELECT f.id, COUNT(e.id) as event_count\n FROM frames f\n LEFT JOIN events e ON f.id = e.frame_id\n WHERE f.id IN (${frameIds.map(() => '?').join(',')})\n GROUP BY f.id\n ORDER BY event_count DESC\n `;\n const rows = this.db.prepare(query).all(...frameIds) as any[];\n return rows.map((r: any) => r.id);\n }\n \n default:\n return frameIds;\n }\n } catch {\n // Return original order if tables don't exist\n return frameIds;\n }\n }\n}"],
5
- "mappings": "AAOA,SAAS,cAAc;AAuBhB,MAAM,UAAa;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EAElB,YAAY,QAA0B;AACpC,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,MAAM,MAAkB;AACtB,QAAI,KAAK,WAAW,KAAK,WAAW,QAAW;AAC7C,aAAO,KAAK;AAAA,IACd;AAEA,QAAI,CAAC,KAAK,UAAU;AAClB,WAAK,WAAW,KAAK,QAAQ,EAAE,KAAK,WAAS;AAC3C,aAAK,SAAS;AACd,aAAK,UAAU;AACf,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAEA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,WAAoB;AAClB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,OAAsB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,QAAc;AACZ,SAAK,SAAS;AACd,SAAK,WAAW;AAChB,SAAK,UAAU;AAAA,EACjB;AACF;AAEO,MAAM,kBAAkB;AAAA,EACrB;AAAA,EACA;AAAA;AAAA,EAGA,eAAe,oBAAI,IAA8B;AAAA,EACjD,gBAAgB,oBAAI,IAAiC;AAAA,EACrD,eAAe,oBAAI,IAAgC;AAAA,EAE3D,YAAY,IAAuB,WAAmB;AACpD,SAAK,KAAK;AACV,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,SAAmC;AAC3C,QAAI,CAAC,KAAK,aAAa,IAAI,OAAO,GAAG;AACnC,WAAK,aAAa,IAAI,SAAS,IAAI,UAAU,YAAY;AACvD,cAAM,QAAQ,KAAK,UAAU,OAAO;AACpC,YAAI,CAAC,OAAO;AACV,gBAAM,IAAI,MAAM,oBAAoB,OAAO,EAAE;AAAA,QAC/C;AACA,eAAO;AAAA,MACT,CAAC,CAAC;AAAA,IACJ;AACA,WAAO,KAAK,aAAa,IAAI,OAAO;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,SAAsC;AAChD,QAAI,CAAC,KAAK,cAAc,IAAI,OAAO,GAAG;AACpC,WAAK,cAAc,IAAI,SAAS,IAAI,UAAU,YAAY;AACxD,eAAO,KAAK,YAAY,OAAO;AAAA,MACjC,CAAC,CAAC;AAAA,IACJ;AACA,WAAO,KAAK,cAAc,IAAI,OAAO;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,SAAiB,QAAQ,KAAyB;AAC3D,UAAM,MAAM,GAAG,OAAO,IAAI,KAAK;AAC/B,QAAI,CAAC,KAAK,aAAa,IAAI,GAAG,GAAG;AAC/B,WAAK,aAAa,IAAI,KAAK,IAAI,UAAU,YAAY;AACnD,eAAO,KAAK,WAAW,SAAS,KAAK;AAAA,MACvC,CAAC,CAAC;AAAA,IACJ;AACA,WAAO,KAAK,aAAa,IAAI,GAAG;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,uBACL,UACA,UAA2B,CAAC,GACiB;AAC7C,UAAM;AAAA,MACJ,YAAY;AAAA,MACZ,WAAW;AAAA,IACb,IAAI;AAGJ,UAAM,YAAY,KAAK,eAAe,UAAU,QAAQ;AACxD,UAAM,cAAc,KAAK,KAAK,UAAU,SAAS,SAAS;AAE1D,aAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK,WAAW;AACpD,YAAM,WAAW,UAAU,MAAM,GAAG,IAAI,SAAS;AACjD,YAAM,cAAc,KAAK,MAAM,IAAI,SAAS,IAAI;AAEhD,YAAM,SAAkB,CAAC;AACzB,YAAM,UAAoB,CAAC;AAC3B,YAAM,SAAkB,CAAC;AAGzB,iBAAW,WAAW,UAAU;AAC9B,cAAM,QAAQ,MAAM,KAAK,UAAU,OAAO,EAAE,IAAI;AAChD,eAAO,KAAK,KAAK;AAGjB,cAAM,eAAe,MAAM,KAAK,YAAY,OAAO,EAAE,IAAI;AACzD,gBAAQ,KAAK,GAAG,YAAY;AAE5B,cAAM,cAAc,MAAM,KAAK,WAAW,OAAO,EAAE,IAAI;AACvD,eAAO,KAAK,GAAG,WAAW;AAAA,MAC5B;AAEA,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA,UAAU;AAAA,UACR,SAAS;AAAA,UACT;AAAA,UACA,SAAS,IAAI,YAAY,UAAU;AAAA,UACnC,YAAY,IAAI,YAAY,UAAU,SAClC,UAAU,IAAI,SAAS,IACvB;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eACJ,UACA,UAAkD,CAAC,GACpC;AACf,UAAM,EAAE,WAAW,MAAM,QAAQ,EAAE,IAAI;AACvC,UAAM,YAAY,KAAK,IAAI;AAE3B,QAAI,UAAU;AACZ,YAAM,WAA2B,CAAC;AAElC,iBAAW,WAAW,UAAU;AAC9B,iBAAS,KAAK,KAAK,UAAU,OAAO,EAAE,IAAI,CAAC;AAE3C,YAAI,QAAQ,GAAG;AACb,mBAAS,KAAK,KAAK,YAAY,OAAO,EAAE,IAAI,CAAC;AAAA,QAC/C;AAEA,YAAI,QAAQ,GAAG;AACb,mBAAS,KAAK,KAAK,WAAW,OAAO,EAAE,IAAI,CAAC;AAAA,QAC9C;AAAA,MACF;AAEA,YAAM,QAAQ,IAAI,QAAQ;AAAA,IAC5B,OAAO;AACL,iBAAW,WAAW,UAAU;AAC9B,cAAM,KAAK,UAAU,OAAO,EAAE,IAAI;AAElC,YAAI,QAAQ,GAAG;AACb,gBAAM,KAAK,YAAY,OAAO,EAAE,IAAI;AAAA,QACtC;AAEA,YAAI,QAAQ,GAAG;AACb,gBAAM,KAAK,WAAW,OAAO,EAAE,IAAI;AAAA,QACrC;AAAA,MACF;AAAA,IACF;AAEA,WAAO,MAAM,4BAA4B;AAAA,MACvC,QAAQ,SAAS;AAAA,MACjB;AAAA,MACA,UAAU,KAAK,IAAI,IAAI;AAAA,IACzB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAiB,UAA+C;AACpE,UAAM,eAAe,SAAS,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG;AACrD,UAAM,QAAQ;AAAA;AAAA;AAAA,qBAGG,YAAY;AAAA;AAG7B,UAAM,OAAO,KAAK,GAAG,QAAQ,KAAK,EAAE,IAAI,GAAG,QAAQ;AACnD,UAAM,UAAU,oBAAI,IAAiB;AAErC,eAAW,OAAO,MAAM;AACtB,cAAQ,IAAI,IAAI,IAAI;AAAA,QAClB,IAAI,IAAI;AAAA,QACR,MAAM,IAAI;AAAA,QACV,MAAM,IAAI;AAAA,QACV,OAAO,IAAI;AAAA,QACX,OAAO,IAAI;AAAA,QACX,WAAW,IAAI;AAAA,QACf,WAAW,IAAI;AAAA,MACjB,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,cACL,OACA,SAAgB,CAAC,GACsC;AACvD,UAAM,OAAO,KAAK,GAAG,QAAQ,KAAK;AAClC,UAAM,WAAW,KAAK,QAAQ,GAAG,MAAM;AAEvC,eAAW,OAAO,UAAU;AAC1B,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAmB;AACjB,SAAK,aAAa,MAAM;AACxB,SAAK,cAAc,MAAM;AACzB,SAAK,aAAa,MAAM;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,gBAKE;AACA,QAAI,SAAS;AAEb,eAAW,UAAU,KAAK,aAAa,OAAO,GAAG;AAC/C,UAAI,OAAO,SAAS,EAAG;AAAA,IACzB;AAEA,eAAW,UAAU,KAAK,cAAc,OAAO,GAAG;AAChD,UAAI,OAAO,SAAS,EAAG;AAAA,IACzB;AAEA,eAAW,UAAU,KAAK,aAAa,OAAO,GAAG;AAC/C,UAAI,OAAO,SAAS,EAAG;AAAA,IACzB;AAEA,WAAO;AAAA,MACL,QAAQ,KAAK,aAAa;AAAA,MAC1B,SAAS,KAAK,cAAc;AAAA,MAC5B,QAAQ,KAAK,aAAa;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAIQ,UAAU,SAA+B;AAC/C,QAAI;AACF,YAAM,MAAM,KAAK,GAAG;AAAA,QAClB;AAAA,MACF,EAAE,IAAI,OAAO;AAEb,UAAI,CAAC,IAAK,QAAO;AAEjB,aAAO;AAAA,QACL,GAAG;AAAA,QACH,UAAU,KAAK,MAAM,IAAI,YAAY,IAAI;AAAA,MAC3C;AAAA,IACF,SAAS,OAAgB;AAEvB,UAAI,QAAQ,WAAW,QAAQ,GAAG;AAChC,eAAO;AAAA,UACL,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,MAAM,QAAQ,OAAO;AAAA,UACrB,OAAO;AAAA,UACP,OAAO;AAAA,UACP,YAAY,KAAK,IAAI;AAAA,UACrB,YAAY,KAAK,IAAI;AAAA,UACrB,UAAU,CAAC;AAAA,QACb;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,YAAY,SAA2B;AAC7C,QAAI;AACF,YAAM,OAAO,KAAK,GAAG;AAAA,QACnB;AAAA,MACF,EAAE,IAAI,OAAO;AAEb,aAAO,KAAK,IAAI,CAAC,SAAc;AAAA,QAC7B,GAAG;AAAA,QACH,UAAU,KAAK,MAAM,IAAI,YAAY,IAAI;AAAA,MAC3C,EAAE;AAAA,IACJ,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EAEQ,WAAW,SAAiB,OAAwB;AAC1D,QAAI;AACF,YAAM,OAAO,KAAK,GAAG;AAAA,QACnB;AAAA,MACF,EAAE,IAAI,SAAS,KAAK;AAEpB,aAAO,KAAK,IAAI,CAAC,SAAc;AAAA,QAC7B,GAAG;AAAA,QACH,MAAM,KAAK,MAAM,IAAI,QAAQ,IAAI;AAAA,QACjC,UAAU,KAAK,MAAM,IAAI,YAAY,IAAI;AAAA,MAC3C,EAAE;AAAA,IACJ,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EAEQ,eACN,UACA,UACU;AACV,QAAI;AACF,cAAQ,UAAU;AAAA,QAChB,KAAK,WAAW;AAEd,gBAAM,QAAQ;AAAA;AAAA,2BAEG,SAAS,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC;AAAA;AAAA;AAGlD,gBAAM,OAAO,KAAK,GAAG,QAAQ,KAAK,EAAE,IAAI,GAAG,QAAQ;AACnD,iBAAO,KAAK,IAAI,CAAC,MAAW,EAAE,EAAE;AAAA,QAClC;AAAA,QAEA,KAAK,aAAa;AAEhB,gBAAM,QAAQ;AAAA;AAAA,2BAEG,SAAS,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC;AAAA;AAAA;AAGlD,gBAAM,OAAO,KAAK,GAAG,QAAQ,KAAK,EAAE,IAAI,GAAG,QAAQ;AACnD,iBAAO,KAAK,IAAI,CAAC,MAAW,EAAE,EAAE;AAAA,QAClC;AAAA,QAEA,KAAK,aAAa;AAEhB,gBAAM,QAAQ;AAAA;AAAA;AAAA;AAAA,6BAIK,SAAS,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC;AAAA;AAAA;AAAA;AAIpD,gBAAM,OAAO,KAAK,GAAG,QAAQ,KAAK,EAAE,IAAI,GAAG,QAAQ;AACnD,iBAAO,KAAK,IAAI,CAAC,MAAW,EAAE,EAAE;AAAA,QAClC;AAAA,QAEA;AACE,iBAAO;AAAA,MACX;AAAA,IACF,QAAQ;AAEN,aAAO;AAAA,IACT;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["/**\n * Lazy Context Loader\n * Deferred loading and progressive enhancement for context data\n */\n\nimport Database from 'better-sqlite3';\nimport { Frame, Anchor, Event } from '../context/frame-manager.js';\nimport { logger } from '../monitoring/logger.js';\n\nexport interface LazyLoadOptions {\n preloadDepth?: number; // How many levels to preload\n chunkSize?: number; // Items per chunk\n priority?: 'recency' | 'relevance' | 'frequency';\n}\n\nexport interface ContextChunk {\n frames: Frame[];\n anchors: Anchor[];\n events: Event[];\n metadata: {\n chunkId: number;\n totalChunks: number;\n hasMore: boolean;\n nextCursor?: string;\n };\n}\n\n/**\n * Lazy proxy for deferred data loading\n */\nexport class LazyProxy<T> {\n private _value?: T;\n private _promise?: Promise<T>;\n private _loader: () => Promise<T>;\n private _loaded = false;\n\n constructor(loader: () => Promise<T>) {\n this._loader = loader;\n }\n\n async get(): Promise<T> {\n if (this._loaded && this._value !== undefined) {\n return this._value;\n }\n\n if (!this._promise) {\n this._promise = this._loader().then((value) => {\n this._value = value;\n this._loaded = true;\n return value;\n });\n }\n\n return this._promise;\n }\n\n isLoaded(): boolean {\n return this._loaded;\n }\n\n peek(): T | undefined {\n return this._value;\n }\n\n reset(): void {\n this._value = undefined;\n this._promise = undefined;\n this._loaded = false;\n }\n}\n\nexport class LazyContextLoader {\n private db: Database.Database;\n private projectId: string;\n\n // Lazy loading registries\n private frameLoaders = new Map<string, LazyProxy<Frame>>();\n private anchorLoaders = new Map<string, LazyProxy<Anchor[]>>();\n private eventLoaders = new Map<string, LazyProxy<Event[]>>();\n\n constructor(db: Database.Database, projectId: string) {\n this.db = db;\n this.projectId = projectId;\n }\n\n /**\n * Create a lazy frame reference\n */\n lazyFrame(frameId: string): LazyProxy<Frame> {\n if (!this.frameLoaders.has(frameId)) {\n this.frameLoaders.set(\n frameId,\n new LazyProxy(async () => {\n const frame = this.loadFrame(frameId);\n if (!frame) {\n throw new Error(`Frame not found: ${frameId}`);\n }\n return frame;\n })\n );\n }\n return this.frameLoaders.get(frameId)!;\n }\n\n /**\n * Create lazy anchor references\n */\n lazyAnchors(frameId: string): LazyProxy<Anchor[]> {\n if (!this.anchorLoaders.has(frameId)) {\n this.anchorLoaders.set(\n frameId,\n new LazyProxy(async () => {\n return this.loadAnchors(frameId);\n })\n );\n }\n return this.anchorLoaders.get(frameId)!;\n }\n\n /**\n * Create lazy event references\n */\n lazyEvents(frameId: string, limit = 100): LazyProxy<Event[]> {\n const key = `${frameId}:${limit}`;\n if (!this.eventLoaders.has(key)) {\n this.eventLoaders.set(\n key,\n new LazyProxy(async () => {\n return this.loadEvents(frameId, limit);\n })\n );\n }\n return this.eventLoaders.get(key)!;\n }\n\n /**\n * Progressive context loading with chunking\n */\n async *loadContextProgressive(\n frameIds: string[],\n options: LazyLoadOptions = {}\n ): AsyncGenerator<ContextChunk, void, unknown> {\n const { chunkSize = 10, priority = 'recency' } = options;\n\n // Sort frame IDs by priority\n const sortedIds = this.sortByPriority(frameIds, priority);\n const totalChunks = Math.ceil(sortedIds.length / chunkSize);\n\n for (let i = 0; i < sortedIds.length; i += chunkSize) {\n const chunkIds = sortedIds.slice(i, i + chunkSize);\n const chunkNumber = Math.floor(i / chunkSize) + 1;\n\n const frames: Frame[] = [];\n const anchors: Anchor[] = [];\n const events: Event[] = [];\n\n // Load chunk data\n for (const frameId of chunkIds) {\n const frame = await this.lazyFrame(frameId).get();\n frames.push(frame);\n\n // Load associated data\n const frameAnchors = await this.lazyAnchors(frameId).get();\n anchors.push(...frameAnchors);\n\n const frameEvents = await this.lazyEvents(frameId).get();\n events.push(...frameEvents);\n }\n\n yield {\n frames,\n anchors,\n events,\n metadata: {\n chunkId: chunkNumber,\n totalChunks,\n hasMore: i + chunkSize < sortedIds.length,\n nextCursor:\n i + chunkSize < sortedIds.length\n ? sortedIds[i + chunkSize]\n : undefined,\n },\n };\n }\n }\n\n /**\n * Preload context data for better performance\n */\n async preloadContext(\n frameIds: string[],\n options: { parallel?: boolean; depth?: number } = {}\n ): Promise<void> {\n const { parallel = true, depth = 1 } = options;\n const startTime = Date.now();\n\n if (parallel) {\n const promises: Promise<any>[] = [];\n\n for (const frameId of frameIds) {\n promises.push(this.lazyFrame(frameId).get());\n\n if (depth > 0) {\n promises.push(this.lazyAnchors(frameId).get());\n }\n\n if (depth > 1) {\n promises.push(this.lazyEvents(frameId).get());\n }\n }\n\n await Promise.all(promises);\n } else {\n for (const frameId of frameIds) {\n await this.lazyFrame(frameId).get();\n\n if (depth > 0) {\n await this.lazyAnchors(frameId).get();\n }\n\n if (depth > 1) {\n await this.lazyEvents(frameId).get();\n }\n }\n }\n\n logger.debug('Context preload complete', {\n frames: frameIds.length,\n depth,\n duration: Date.now() - startTime,\n });\n }\n\n /**\n * Load only frame headers (lightweight)\n */\n async loadFrameHeaders(frameIds: string[]): Promise<Map<string, any>> {\n const placeholders = frameIds.map(() => '?').join(',');\n const query = `\n SELECT id, type, name, state, score, created_at, updated_at\n FROM frames \n WHERE id IN (${placeholders})\n `;\n\n const rows = this.db.prepare(query).all(...frameIds) as any[];\n const headers = new Map<string, any>();\n\n for (const row of rows) {\n headers.set(row.id, {\n id: row.id,\n type: row.type,\n name: row.name,\n state: row.state,\n score: row.score,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n });\n }\n\n return headers;\n }\n\n /**\n * Stream context data for memory efficiency\n */\n async *streamContext(\n query: string,\n params: any[] = []\n ): AsyncGenerator<Frame | Anchor | Event, void, unknown> {\n const stmt = this.db.prepare(query);\n const iterator = stmt.iterate(...params);\n\n for (const row of iterator) {\n yield row as any;\n }\n }\n\n /**\n * Clear lazy loading cache\n */\n clearCache(): void {\n this.frameLoaders.clear();\n this.anchorLoaders.clear();\n this.eventLoaders.clear();\n }\n\n /**\n * Get cache statistics\n */\n getCacheStats(): {\n frames: number;\n anchors: number;\n events: number;\n loaded: number;\n } {\n let loaded = 0;\n\n for (const loader of this.frameLoaders.values()) {\n if (loader.isLoaded()) loaded++;\n }\n\n for (const loader of this.anchorLoaders.values()) {\n if (loader.isLoaded()) loaded++;\n }\n\n for (const loader of this.eventLoaders.values()) {\n if (loader.isLoaded()) loaded++;\n }\n\n return {\n frames: this.frameLoaders.size,\n anchors: this.anchorLoaders.size,\n events: this.eventLoaders.size,\n loaded,\n };\n }\n\n // Private methods\n\n private loadFrame(frameId: string): Frame | null {\n try {\n const row = this.db\n .prepare('SELECT * FROM frames WHERE id = ?')\n .get(frameId) as any;\n\n if (!row) return null;\n\n return {\n ...row,\n metadata: JSON.parse(row.metadata || '{}'),\n };\n } catch (error: unknown) {\n // Return mock frame if table doesn't exist (for benchmarking)\n if (frameId.startsWith('frame-')) {\n return {\n id: frameId,\n type: 'mock',\n name: `Mock ${frameId}`,\n state: 'open',\n score: 0.5,\n created_at: Date.now(),\n updated_at: Date.now(),\n metadata: {},\n } as any;\n }\n return null;\n }\n }\n\n private loadAnchors(frameId: string): Anchor[] {\n try {\n const rows = this.db\n .prepare(\n 'SELECT * FROM anchors WHERE frame_id = ? ORDER BY priority DESC, created_at DESC'\n )\n .all(frameId) as any[];\n\n return rows.map((row: any) => ({\n ...row,\n metadata: JSON.parse(row.metadata || '{}'),\n }));\n } catch {\n return []; // Return empty array if table doesn't exist\n }\n }\n\n private loadEvents(frameId: string, limit: number): Event[] {\n try {\n const rows = this.db\n .prepare(\n 'SELECT * FROM events WHERE frame_id = ? ORDER BY timestamp DESC LIMIT ?'\n )\n .all(frameId, limit) as any[];\n\n return rows.map((row: any) => ({\n ...row,\n data: JSON.parse(row.data || '{}'),\n metadata: JSON.parse(row.metadata || '{}'),\n }));\n } catch {\n return []; // Return empty array if table doesn't exist\n }\n }\n\n private sortByPriority(\n frameIds: string[],\n priority: 'recency' | 'relevance' | 'frequency'\n ): string[] {\n try {\n switch (priority) {\n case 'recency': {\n // Get timestamps and sort\n const query = `\n SELECT id, updated_at FROM frames \n WHERE id IN (${frameIds.map(() => '?').join(',')})\n ORDER BY updated_at DESC\n `;\n const rows = this.db.prepare(query).all(...frameIds) as any[];\n return rows.map((r: any) => r.id);\n }\n\n case 'relevance': {\n // Get scores and sort\n const query = `\n SELECT id, score FROM frames \n WHERE id IN (${frameIds.map(() => '?').join(',')})\n ORDER BY score DESC\n `;\n const rows = this.db.prepare(query).all(...frameIds) as any[];\n return rows.map((r: any) => r.id);\n }\n\n case 'frequency': {\n // Get event counts and sort\n const query = `\n SELECT f.id, COUNT(e.id) as event_count\n FROM frames f\n LEFT JOIN events e ON f.id = e.frame_id\n WHERE f.id IN (${frameIds.map(() => '?').join(',')})\n GROUP BY f.id\n ORDER BY event_count DESC\n `;\n const rows = this.db.prepare(query).all(...frameIds) as any[];\n return rows.map((r: any) => r.id);\n }\n\n default:\n return frameIds;\n }\n } catch {\n // Return original order if tables don't exist\n return frameIds;\n }\n }\n}\n"],
5
+ "mappings": "AAOA,SAAS,cAAc;AAuBhB,MAAM,UAAa;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EAElB,YAAY,QAA0B;AACpC,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,MAAM,MAAkB;AACtB,QAAI,KAAK,WAAW,KAAK,WAAW,QAAW;AAC7C,aAAO,KAAK;AAAA,IACd;AAEA,QAAI,CAAC,KAAK,UAAU;AAClB,WAAK,WAAW,KAAK,QAAQ,EAAE,KAAK,CAAC,UAAU;AAC7C,aAAK,SAAS;AACd,aAAK,UAAU;AACf,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAEA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,WAAoB;AAClB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,OAAsB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,QAAc;AACZ,SAAK,SAAS;AACd,SAAK,WAAW;AAChB,SAAK,UAAU;AAAA,EACjB;AACF;AAEO,MAAM,kBAAkB;AAAA,EACrB;AAAA,EACA;AAAA;AAAA,EAGA,eAAe,oBAAI,IAA8B;AAAA,EACjD,gBAAgB,oBAAI,IAAiC;AAAA,EACrD,eAAe,oBAAI,IAAgC;AAAA,EAE3D,YAAY,IAAuB,WAAmB;AACpD,SAAK,KAAK;AACV,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,SAAmC;AAC3C,QAAI,CAAC,KAAK,aAAa,IAAI,OAAO,GAAG;AACnC,WAAK,aAAa;AAAA,QAChB;AAAA,QACA,IAAI,UAAU,YAAY;AACxB,gBAAM,QAAQ,KAAK,UAAU,OAAO;AACpC,cAAI,CAAC,OAAO;AACV,kBAAM,IAAI,MAAM,oBAAoB,OAAO,EAAE;AAAA,UAC/C;AACA,iBAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF;AACA,WAAO,KAAK,aAAa,IAAI,OAAO;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,SAAsC;AAChD,QAAI,CAAC,KAAK,cAAc,IAAI,OAAO,GAAG;AACpC,WAAK,cAAc;AAAA,QACjB;AAAA,QACA,IAAI,UAAU,YAAY;AACxB,iBAAO,KAAK,YAAY,OAAO;AAAA,QACjC,CAAC;AAAA,MACH;AAAA,IACF;AACA,WAAO,KAAK,cAAc,IAAI,OAAO;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,SAAiB,QAAQ,KAAyB;AAC3D,UAAM,MAAM,GAAG,OAAO,IAAI,KAAK;AAC/B,QAAI,CAAC,KAAK,aAAa,IAAI,GAAG,GAAG;AAC/B,WAAK,aAAa;AAAA,QAChB;AAAA,QACA,IAAI,UAAU,YAAY;AACxB,iBAAO,KAAK,WAAW,SAAS,KAAK;AAAA,QACvC,CAAC;AAAA,MACH;AAAA,IACF;AACA,WAAO,KAAK,aAAa,IAAI,GAAG;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,uBACL,UACA,UAA2B,CAAC,GACiB;AAC7C,UAAM,EAAE,YAAY,IAAI,WAAW,UAAU,IAAI;AAGjD,UAAM,YAAY,KAAK,eAAe,UAAU,QAAQ;AACxD,UAAM,cAAc,KAAK,KAAK,UAAU,SAAS,SAAS;AAE1D,aAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK,WAAW;AACpD,YAAM,WAAW,UAAU,MAAM,GAAG,IAAI,SAAS;AACjD,YAAM,cAAc,KAAK,MAAM,IAAI,SAAS,IAAI;AAEhD,YAAM,SAAkB,CAAC;AACzB,YAAM,UAAoB,CAAC;AAC3B,YAAM,SAAkB,CAAC;AAGzB,iBAAW,WAAW,UAAU;AAC9B,cAAM,QAAQ,MAAM,KAAK,UAAU,OAAO,EAAE,IAAI;AAChD,eAAO,KAAK,KAAK;AAGjB,cAAM,eAAe,MAAM,KAAK,YAAY,OAAO,EAAE,IAAI;AACzD,gBAAQ,KAAK,GAAG,YAAY;AAE5B,cAAM,cAAc,MAAM,KAAK,WAAW,OAAO,EAAE,IAAI;AACvD,eAAO,KAAK,GAAG,WAAW;AAAA,MAC5B;AAEA,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA,UAAU;AAAA,UACR,SAAS;AAAA,UACT;AAAA,UACA,SAAS,IAAI,YAAY,UAAU;AAAA,UACnC,YACE,IAAI,YAAY,UAAU,SACtB,UAAU,IAAI,SAAS,IACvB;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eACJ,UACA,UAAkD,CAAC,GACpC;AACf,UAAM,EAAE,WAAW,MAAM,QAAQ,EAAE,IAAI;AACvC,UAAM,YAAY,KAAK,IAAI;AAE3B,QAAI,UAAU;AACZ,YAAM,WAA2B,CAAC;AAElC,iBAAW,WAAW,UAAU;AAC9B,iBAAS,KAAK,KAAK,UAAU,OAAO,EAAE,IAAI,CAAC;AAE3C,YAAI,QAAQ,GAAG;AACb,mBAAS,KAAK,KAAK,YAAY,OAAO,EAAE,IAAI,CAAC;AAAA,QAC/C;AAEA,YAAI,QAAQ,GAAG;AACb,mBAAS,KAAK,KAAK,WAAW,OAAO,EAAE,IAAI,CAAC;AAAA,QAC9C;AAAA,MACF;AAEA,YAAM,QAAQ,IAAI,QAAQ;AAAA,IAC5B,OAAO;AACL,iBAAW,WAAW,UAAU;AAC9B,cAAM,KAAK,UAAU,OAAO,EAAE,IAAI;AAElC,YAAI,QAAQ,GAAG;AACb,gBAAM,KAAK,YAAY,OAAO,EAAE,IAAI;AAAA,QACtC;AAEA,YAAI,QAAQ,GAAG;AACb,gBAAM,KAAK,WAAW,OAAO,EAAE,IAAI;AAAA,QACrC;AAAA,MACF;AAAA,IACF;AAEA,WAAO,MAAM,4BAA4B;AAAA,MACvC,QAAQ,SAAS;AAAA,MACjB;AAAA,MACA,UAAU,KAAK,IAAI,IAAI;AAAA,IACzB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAiB,UAA+C;AACpE,UAAM,eAAe,SAAS,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG;AACrD,UAAM,QAAQ;AAAA;AAAA;AAAA,qBAGG,YAAY;AAAA;AAG7B,UAAM,OAAO,KAAK,GAAG,QAAQ,KAAK,EAAE,IAAI,GAAG,QAAQ;AACnD,UAAM,UAAU,oBAAI,IAAiB;AAErC,eAAW,OAAO,MAAM;AACtB,cAAQ,IAAI,IAAI,IAAI;AAAA,QAClB,IAAI,IAAI;AAAA,QACR,MAAM,IAAI;AAAA,QACV,MAAM,IAAI;AAAA,QACV,OAAO,IAAI;AAAA,QACX,OAAO,IAAI;AAAA,QACX,WAAW,IAAI;AAAA,QACf,WAAW,IAAI;AAAA,MACjB,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,cACL,OACA,SAAgB,CAAC,GACsC;AACvD,UAAM,OAAO,KAAK,GAAG,QAAQ,KAAK;AAClC,UAAM,WAAW,KAAK,QAAQ,GAAG,MAAM;AAEvC,eAAW,OAAO,UAAU;AAC1B,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAmB;AACjB,SAAK,aAAa,MAAM;AACxB,SAAK,cAAc,MAAM;AACzB,SAAK,aAAa,MAAM;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,gBAKE;AACA,QAAI,SAAS;AAEb,eAAW,UAAU,KAAK,aAAa,OAAO,GAAG;AAC/C,UAAI,OAAO,SAAS,EAAG;AAAA,IACzB;AAEA,eAAW,UAAU,KAAK,cAAc,OAAO,GAAG;AAChD,UAAI,OAAO,SAAS,EAAG;AAAA,IACzB;AAEA,eAAW,UAAU,KAAK,aAAa,OAAO,GAAG;AAC/C,UAAI,OAAO,SAAS,EAAG;AAAA,IACzB;AAEA,WAAO;AAAA,MACL,QAAQ,KAAK,aAAa;AAAA,MAC1B,SAAS,KAAK,cAAc;AAAA,MAC5B,QAAQ,KAAK,aAAa;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAIQ,UAAU,SAA+B;AAC/C,QAAI;AACF,YAAM,MAAM,KAAK,GACd,QAAQ,mCAAmC,EAC3C,IAAI,OAAO;AAEd,UAAI,CAAC,IAAK,QAAO;AAEjB,aAAO;AAAA,QACL,GAAG;AAAA,QACH,UAAU,KAAK,MAAM,IAAI,YAAY,IAAI;AAAA,MAC3C;AAAA,IACF,SAAS,OAAgB;AAEvB,UAAI,QAAQ,WAAW,QAAQ,GAAG;AAChC,eAAO;AAAA,UACL,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,MAAM,QAAQ,OAAO;AAAA,UACrB,OAAO;AAAA,UACP,OAAO;AAAA,UACP,YAAY,KAAK,IAAI;AAAA,UACrB,YAAY,KAAK,IAAI;AAAA,UACrB,UAAU,CAAC;AAAA,QACb;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,YAAY,SAA2B;AAC7C,QAAI;AACF,YAAM,OAAO,KAAK,GACf;AAAA,QACC;AAAA,MACF,EACC,IAAI,OAAO;AAEd,aAAO,KAAK,IAAI,CAAC,SAAc;AAAA,QAC7B,GAAG;AAAA,QACH,UAAU,KAAK,MAAM,IAAI,YAAY,IAAI;AAAA,MAC3C,EAAE;AAAA,IACJ,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EAEQ,WAAW,SAAiB,OAAwB;AAC1D,QAAI;AACF,YAAM,OAAO,KAAK,GACf;AAAA,QACC;AAAA,MACF,EACC,IAAI,SAAS,KAAK;AAErB,aAAO,KAAK,IAAI,CAAC,SAAc;AAAA,QAC7B,GAAG;AAAA,QACH,MAAM,KAAK,MAAM,IAAI,QAAQ,IAAI;AAAA,QACjC,UAAU,KAAK,MAAM,IAAI,YAAY,IAAI;AAAA,MAC3C,EAAE;AAAA,IACJ,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EAEQ,eACN,UACA,UACU;AACV,QAAI;AACF,cAAQ,UAAU;AAAA,QAChB,KAAK,WAAW;AAEd,gBAAM,QAAQ;AAAA;AAAA,2BAEG,SAAS,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC;AAAA;AAAA;AAGlD,gBAAM,OAAO,KAAK,GAAG,QAAQ,KAAK,EAAE,IAAI,GAAG,QAAQ;AACnD,iBAAO,KAAK,IAAI,CAAC,MAAW,EAAE,EAAE;AAAA,QAClC;AAAA,QAEA,KAAK,aAAa;AAEhB,gBAAM,QAAQ;AAAA;AAAA,2BAEG,SAAS,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC;AAAA;AAAA;AAGlD,gBAAM,OAAO,KAAK,GAAG,QAAQ,KAAK,EAAE,IAAI,GAAG,QAAQ;AACnD,iBAAO,KAAK,IAAI,CAAC,MAAW,EAAE,EAAE;AAAA,QAClC;AAAA,QAEA,KAAK,aAAa;AAEhB,gBAAM,QAAQ;AAAA;AAAA;AAAA;AAAA,6BAIK,SAAS,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC;AAAA;AAAA;AAAA;AAIpD,gBAAM,OAAO,KAAK,GAAG,QAAQ,KAAK,EAAE,IAAI,GAAG,QAAQ;AACnD,iBAAO,KAAK,IAAI,CAAC,MAAW,EAAE,EAAE;AAAA,QAClC;AAAA,QAEA;AACE,iBAAO;AAAA,MACX;AAAA,IACF,QAAQ;AAEN,aAAO;AAAA,IACT;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -59,10 +59,7 @@ class OptimizedContextAssembler {
59
59
  async getFrameContext(frameId, options = {}) {
60
60
  const startTime = performance.now();
61
61
  const stats = { cacheHits: 0, dbQueries: 0, totalRows: 0 };
62
- const {
63
- maxEvents = 50,
64
- enableCaching = true
65
- } = options;
62
+ const { maxEvents = 50, enableCaching = true } = options;
66
63
  const cacheKey = createCacheKey("frame_context", [frameId, maxEvents]);
67
64
  if (enableCaching) {
68
65
  const cached = this.cache.getFrameContext(cacheKey);
@@ -78,7 +75,11 @@ class OptimizedContextAssembler {
78
75
  }
79
76
  }
80
77
  try {
81
- const context = await this.assembleFrameContext(frameId, maxEvents, stats);
78
+ const context = await this.assembleFrameContext(
79
+ frameId,
80
+ maxEvents,
81
+ stats
82
+ );
82
83
  if (!context) return null;
83
84
  if (enableCaching) {
84
85
  this.cache.cacheFrameContext(cacheKey, context);
@@ -254,12 +255,20 @@ class OptimizedContextAssembler {
254
255
  * Assemble single frame context
255
256
  */
256
257
  async assembleFrameContext(frameId, maxEvents, stats) {
257
- const frame = await this.batchGetFrames([frameId], stats).then((map) => map.get(frameId));
258
+ const frame = await this.batchGetFrames([frameId], stats).then(
259
+ (map) => map.get(frameId)
260
+ );
258
261
  if (!frame) return null;
259
262
  const [events, anchors, artifacts] = await Promise.all([
260
- this.batchGetEvents([frameId], maxEvents, stats).then((map) => map.get(frameId) || []),
261
- this.batchGetAnchors([frameId], stats).then((map) => map.get(frameId) || []),
262
- this.batchGetArtifacts([frameId], stats).then((map) => map.get(frameId) || [])
263
+ this.batchGetEvents([frameId], maxEvents, stats).then(
264
+ (map) => map.get(frameId) || []
265
+ ),
266
+ this.batchGetAnchors([frameId], stats).then(
267
+ (map) => map.get(frameId) || []
268
+ ),
269
+ this.batchGetArtifacts([frameId], stats).then(
270
+ (map) => map.get(frameId) || []
271
+ )
263
272
  ]);
264
273
  return {
265
274
  frameId,
@@ -300,13 +309,19 @@ class OptimizedContextAssembler {
300
309
  );
301
310
  this.preparedStatements.set(
302
311
  "frame_events",
303
- this.db.prepare("SELECT * FROM events WHERE frame_id = ? ORDER BY seq DESC LIMIT ?")
312
+ this.db.prepare(
313
+ "SELECT * FROM events WHERE frame_id = ? ORDER BY seq DESC LIMIT ?"
314
+ )
304
315
  );
305
316
  this.preparedStatements.set(
306
317
  "frame_anchors",
307
- this.db.prepare("SELECT * FROM anchors WHERE frame_id = ? ORDER BY priority DESC, created_at ASC")
318
+ this.db.prepare(
319
+ "SELECT * FROM anchors WHERE frame_id = ? ORDER BY priority DESC, created_at ASC"
320
+ )
321
+ );
322
+ logger.info(
323
+ "Prepared statements initialized for optimized context assembly"
308
324
  );
309
- logger.info("Prepared statements initialized for optimized context assembly");
310
325
  } catch (error) {
311
326
  logger.error("Failed to initialize prepared statements", error);
312
327
  throw error;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/core/performance/optimized-frame-context.ts"],
4
- "sourcesContent": ["/**\n * Optimized Frame Context Assembly\n * High-performance context retrieval with caching and batching\n */\n\nimport Database from 'better-sqlite3';\nimport { getQueryCache, createCacheKey } from '../database/query-cache.js';\nimport { logger } from '../monitoring/logger.js';\nimport { Frame, FrameContext, Anchor, Event } from '../context/frame-manager.js';\n\nexport interface ContextAssemblyOptions {\n maxEvents?: number;\n includeClosed?: boolean;\n enableCaching?: boolean;\n batchSize?: number;\n}\n\nexport interface OptimizedFrameContext extends FrameContext {\n performance: {\n assemblyTimeMs: number;\n cacheHits: number;\n dbQueries: number;\n totalRows: number;\n };\n}\n\n/**\n * Optimized context assembly with caching and batching\n */\nexport class OptimizedContextAssembler {\n private db: Database.Database;\n private cache = getQueryCache();\n private preparedStatements = new Map<string, Database.Statement>();\n\n constructor(db: Database.Database) {\n this.db = db;\n this.initializePreparedStatements();\n }\n\n /**\n * Get hot stack context with optimizations\n */\n async getHotStackContext(\n activeStack: string[],\n options: ContextAssemblyOptions = {}\n ): Promise<OptimizedFrameContext[]> {\n const startTime = performance.now();\n const stats = {\n cacheHits: 0,\n dbQueries: 0,\n totalRows: 0,\n };\n\n const {\n maxEvents = 20,\n includeClosed = false,\n enableCaching = true,\n batchSize = 10,\n } = options;\n\n try {\n // Batch process frames for better performance\n const contexts: OptimizedFrameContext[] = [];\n \n for (let i = 0; i < activeStack.length; i += batchSize) {\n const batch = activeStack.slice(i, i + batchSize);\n const batchContexts = await this.processBatch(\n batch,\n maxEvents,\n includeClosed,\n enableCaching,\n stats\n );\n contexts.push(...batchContexts);\n }\n\n const assemblyTimeMs = performance.now() - startTime;\n\n // Add performance stats to each context\n return contexts.map((context: any) => ({\n ...context,\n performance: {\n assemblyTimeMs: assemblyTimeMs / contexts.length,\n ...stats,\n },\n }));\n\n } catch (error: unknown) {\n logger.error('Failed to assemble hot stack context', error as Error, {\n activeStack,\n options,\n });\n throw error;\n }\n }\n\n /**\n * Get single frame context with full optimization\n */\n async getFrameContext(\n frameId: string,\n options: ContextAssemblyOptions = {}\n ): Promise<OptimizedFrameContext | null> {\n const startTime = performance.now();\n const stats = { cacheHits: 0, dbQueries: 0, totalRows: 0 };\n\n const {\n maxEvents = 50,\n enableCaching = true,\n } = options;\n\n // Check cache first\n const cacheKey = createCacheKey('frame_context', [frameId, maxEvents]);\n if (enableCaching) {\n const cached = this.cache.getFrameContext(cacheKey);\n if (cached) {\n stats.cacheHits++;\n return {\n ...cached,\n performance: {\n assemblyTimeMs: performance.now() - startTime,\n ...stats,\n },\n };\n }\n }\n\n try {\n const context = await this.assembleFrameContext(frameId, maxEvents, stats);\n \n if (!context) return null;\n\n // Cache the result\n if (enableCaching) {\n this.cache.cacheFrameContext(cacheKey, context);\n }\n\n const result: OptimizedFrameContext = {\n ...context,\n performance: {\n assemblyTimeMs: performance.now() - startTime,\n ...stats,\n },\n };\n\n return result;\n\n } catch (error: unknown) {\n logger.error('Failed to get frame context', error as Error, { frameId });\n throw error;\n }\n }\n\n /**\n * Process a batch of frames efficiently\n */\n private async processBatch(\n frameIds: string[],\n maxEvents: number,\n includeClosed: boolean,\n enableCaching: boolean,\n stats: { cacheHits: number; dbQueries: number; totalRows: number }\n ): Promise<OptimizedFrameContext[]> {\n const contexts: OptimizedFrameContext[] = [];\n \n // Get cached contexts first\n const uncachedIds = [];\n for (const frameId of frameIds) {\n const cacheKey = createCacheKey('frame_context', [frameId, maxEvents]);\n if (enableCaching) {\n const cached = this.cache.getFrameContext(cacheKey);\n if (cached) {\n stats.cacheHits++;\n contexts.push(cached);\n continue;\n }\n }\n uncachedIds.push(frameId);\n }\n\n if (uncachedIds.length === 0) {\n return contexts;\n }\n\n // Batch fetch uncached frames\n const frames = await this.batchGetFrames(uncachedIds, stats);\n const allEvents = await this.batchGetEvents(uncachedIds, maxEvents, stats);\n const allAnchors = await this.batchGetAnchors(uncachedIds, stats);\n const allArtifacts = await this.batchGetArtifacts(uncachedIds, stats);\n\n // Assemble contexts from batched data\n for (const frameId of uncachedIds) {\n const frame = frames.get(frameId);\n if (!frame || (!includeClosed && frame.state === 'closed')) {\n continue;\n }\n\n const context: FrameContext = {\n frameId,\n header: {\n goal: frame.name,\n constraints: this.extractConstraints(frame.inputs),\n definitions: frame.inputs.definitions,\n },\n anchors: allAnchors.get(frameId) || [],\n recentEvents: allEvents.get(frameId) || [],\n activeArtifacts: allArtifacts.get(frameId) || [],\n };\n\n // Cache the context\n if (enableCaching) {\n const cacheKey = createCacheKey('frame_context', [frameId, maxEvents]);\n this.cache.cacheFrameContext(cacheKey, context);\n }\n\n contexts.push(context as OptimizedFrameContext);\n }\n\n return contexts;\n }\n\n /**\n * Batch get frames with single query\n */\n private async batchGetFrames(\n frameIds: string[],\n stats: { dbQueries: number; totalRows: number }\n ): Promise<Map<string, Frame>> {\n if (frameIds.length === 0) return new Map();\n\n const stmt = this.preparedStatements.get('batch_frames');\n if (!stmt) throw new Error('Prepared statement not found: batch_frames');\n\n const placeholders = frameIds.map(() => '?').join(',');\n const query = `SELECT * FROM frames WHERE frame_id IN (${placeholders})`;\n \n stats.dbQueries++;\n const rows = this.db.prepare(query).all(...frameIds) as any[];\n stats.totalRows += rows.length;\n\n const frameMap = new Map<string, Frame>();\n for (const row of rows) {\n frameMap.set(row.frame_id, {\n ...row,\n inputs: JSON.parse(row.inputs || '{}'),\n outputs: JSON.parse(row.outputs || '{}'),\n digest_json: JSON.parse(row.digest_json || '{}'),\n });\n }\n\n return frameMap;\n }\n\n /**\n * Batch get events for multiple frames\n */\n private async batchGetEvents(\n frameIds: string[],\n maxEvents: number,\n stats: { dbQueries: number; totalRows: number }\n ): Promise<Map<string, Event[]>> {\n if (frameIds.length === 0) return new Map();\n\n const placeholders = frameIds.map(() => '?').join(',');\n const query = `\n SELECT *, ROW_NUMBER() OVER (PARTITION BY frame_id ORDER BY seq DESC) as rn\n FROM events \n WHERE frame_id IN (${placeholders}) \n AND rn <= ${maxEvents}\n ORDER BY frame_id, seq DESC\n `;\n\n stats.dbQueries++;\n const rows = this.db.prepare(query).all(...frameIds) as any[];\n stats.totalRows += rows.length;\n\n const eventMap = new Map<string, Event[]>();\n for (const row of rows) {\n if (!eventMap.has(row.frame_id)) {\n eventMap.set(row.frame_id, []);\n }\n eventMap.get(row.frame_id)!.push({\n ...row,\n payload: JSON.parse(row.payload),\n });\n }\n\n return eventMap;\n }\n\n /**\n * Batch get anchors for multiple frames\n */\n private async batchGetAnchors(\n frameIds: string[],\n stats: { dbQueries: number; totalRows: number }\n ): Promise<Map<string, Anchor[]>> {\n if (frameIds.length === 0) return new Map();\n\n const placeholders = frameIds.map(() => '?').join(',');\n const query = `\n SELECT * FROM anchors \n WHERE frame_id IN (${placeholders}) \n ORDER BY frame_id, priority DESC, created_at ASC\n `;\n\n stats.dbQueries++;\n const rows = this.db.prepare(query).all(...frameIds) as any[];\n stats.totalRows += rows.length;\n\n const anchorMap = new Map<string, Anchor[]>();\n for (const row of rows) {\n if (!anchorMap.has(row.frame_id)) {\n anchorMap.set(row.frame_id, []);\n }\n anchorMap.get(row.frame_id)!.push({\n ...row,\n metadata: JSON.parse(row.metadata || '{}'),\n });\n }\n\n return anchorMap;\n }\n\n /**\n * Batch get active artifacts for multiple frames\n */\n private async batchGetArtifacts(\n frameIds: string[],\n stats: { dbQueries: number; totalRows: number }\n ): Promise<Map<string, string[]>> {\n if (frameIds.length === 0) return new Map();\n\n const placeholders = frameIds.map(() => '?').join(',');\n const query = `\n SELECT frame_id, payload\n FROM events \n WHERE frame_id IN (${placeholders}) \n AND event_type = 'artifact'\n ORDER BY frame_id, ts DESC\n `;\n\n stats.dbQueries++;\n const rows = this.db.prepare(query).all(...frameIds) as any[];\n stats.totalRows += rows.length;\n\n const artifactMap = new Map<string, string[]>();\n for (const row of rows) {\n const payload = JSON.parse(row.payload);\n if (!artifactMap.has(row.frame_id)) {\n artifactMap.set(row.frame_id, []);\n }\n if (payload.path) {\n artifactMap.get(row.frame_id)!.push(payload.path);\n }\n }\n\n return artifactMap;\n }\n\n /**\n * Assemble single frame context\n */\n private async assembleFrameContext(\n frameId: string,\n maxEvents: number,\n stats: { dbQueries: number; totalRows: number }\n ): Promise<FrameContext | null> {\n // Single frame operations - these could be further optimized with prepared statements\n const frame = await this.batchGetFrames([frameId], stats).then(map => map.get(frameId));\n if (!frame) return null;\n\n const [events, anchors, artifacts] = await Promise.all([\n this.batchGetEvents([frameId], maxEvents, stats).then(map => map.get(frameId) || []),\n this.batchGetAnchors([frameId], stats).then(map => map.get(frameId) || []),\n this.batchGetArtifacts([frameId], stats).then(map => map.get(frameId) || []),\n ]);\n\n return {\n frameId,\n header: {\n goal: frame.name,\n constraints: this.extractConstraints(frame.inputs),\n definitions: frame.inputs.definitions,\n },\n anchors,\n recentEvents: events,\n activeArtifacts: artifacts,\n };\n }\n\n /**\n * Extract constraints from frame inputs\n */\n private extractConstraints(inputs: Record<string, any>): string[] {\n const constraints: string[] = [];\n \n if (inputs.constraints && Array.isArray(inputs.constraints)) {\n constraints.push(...inputs.constraints);\n }\n \n if (inputs.requirements && Array.isArray(inputs.requirements)) {\n constraints.push(...inputs.requirements);\n }\n \n if (inputs.limitations && Array.isArray(inputs.limitations)) {\n constraints.push(...inputs.limitations);\n }\n\n return constraints;\n }\n\n /**\n * Initialize prepared statements for common queries\n */\n private initializePreparedStatements(): void {\n try {\n // Single frame query\n this.preparedStatements.set(\n 'single_frame',\n this.db.prepare('SELECT * FROM frames WHERE frame_id = ?')\n );\n\n // Frame events with limit\n this.preparedStatements.set(\n 'frame_events',\n this.db.prepare('SELECT * FROM events WHERE frame_id = ? ORDER BY seq DESC LIMIT ?')\n );\n\n // Frame anchors\n this.preparedStatements.set(\n 'frame_anchors',\n this.db.prepare('SELECT * FROM anchors WHERE frame_id = ? ORDER BY priority DESC, created_at ASC')\n );\n\n logger.info('Prepared statements initialized for optimized context assembly');\n } catch (error: unknown) {\n logger.error('Failed to initialize prepared statements', error as Error);\n throw error;\n }\n }\n\n /**\n * Clear cache and reset prepared statements\n */\n cleanup(): void {\n this.cache.clear();\n // Modern better-sqlite3 automatically handles cleanup\n this.preparedStatements.clear();\n }\n}"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Optimized Frame Context Assembly\n * High-performance context retrieval with caching and batching\n */\n\nimport Database from 'better-sqlite3';\nimport { getQueryCache, createCacheKey } from '../database/query-cache.js';\nimport { logger } from '../monitoring/logger.js';\nimport {\n Frame,\n FrameContext,\n Anchor,\n Event,\n} from '../context/frame-manager.js';\n\nexport interface ContextAssemblyOptions {\n maxEvents?: number;\n includeClosed?: boolean;\n enableCaching?: boolean;\n batchSize?: number;\n}\n\nexport interface OptimizedFrameContext extends FrameContext {\n performance: {\n assemblyTimeMs: number;\n cacheHits: number;\n dbQueries: number;\n totalRows: number;\n };\n}\n\n/**\n * Optimized context assembly with caching and batching\n */\nexport class OptimizedContextAssembler {\n private db: Database.Database;\n private cache = getQueryCache();\n private preparedStatements = new Map<string, Database.Statement>();\n\n constructor(db: Database.Database) {\n this.db = db;\n this.initializePreparedStatements();\n }\n\n /**\n * Get hot stack context with optimizations\n */\n async getHotStackContext(\n activeStack: string[],\n options: ContextAssemblyOptions = {}\n ): Promise<OptimizedFrameContext[]> {\n const startTime = performance.now();\n const stats = {\n cacheHits: 0,\n dbQueries: 0,\n totalRows: 0,\n };\n\n const {\n maxEvents = 20,\n includeClosed = false,\n enableCaching = true,\n batchSize = 10,\n } = options;\n\n try {\n // Batch process frames for better performance\n const contexts: OptimizedFrameContext[] = [];\n\n for (let i = 0; i < activeStack.length; i += batchSize) {\n const batch = activeStack.slice(i, i + batchSize);\n const batchContexts = await this.processBatch(\n batch,\n maxEvents,\n includeClosed,\n enableCaching,\n stats\n );\n contexts.push(...batchContexts);\n }\n\n const assemblyTimeMs = performance.now() - startTime;\n\n // Add performance stats to each context\n return contexts.map((context: any) => ({\n ...context,\n performance: {\n assemblyTimeMs: assemblyTimeMs / contexts.length,\n ...stats,\n },\n }));\n } catch (error: unknown) {\n logger.error('Failed to assemble hot stack context', error as Error, {\n activeStack,\n options,\n });\n throw error;\n }\n }\n\n /**\n * Get single frame context with full optimization\n */\n async getFrameContext(\n frameId: string,\n options: ContextAssemblyOptions = {}\n ): Promise<OptimizedFrameContext | null> {\n const startTime = performance.now();\n const stats = { cacheHits: 0, dbQueries: 0, totalRows: 0 };\n\n const { maxEvents = 50, enableCaching = true } = options;\n\n // Check cache first\n const cacheKey = createCacheKey('frame_context', [frameId, maxEvents]);\n if (enableCaching) {\n const cached = this.cache.getFrameContext(cacheKey);\n if (cached) {\n stats.cacheHits++;\n return {\n ...cached,\n performance: {\n assemblyTimeMs: performance.now() - startTime,\n ...stats,\n },\n };\n }\n }\n\n try {\n const context = await this.assembleFrameContext(\n frameId,\n maxEvents,\n stats\n );\n\n if (!context) return null;\n\n // Cache the result\n if (enableCaching) {\n this.cache.cacheFrameContext(cacheKey, context);\n }\n\n const result: OptimizedFrameContext = {\n ...context,\n performance: {\n assemblyTimeMs: performance.now() - startTime,\n ...stats,\n },\n };\n\n return result;\n } catch (error: unknown) {\n logger.error('Failed to get frame context', error as Error, { frameId });\n throw error;\n }\n }\n\n /**\n * Process a batch of frames efficiently\n */\n private async processBatch(\n frameIds: string[],\n maxEvents: number,\n includeClosed: boolean,\n enableCaching: boolean,\n stats: { cacheHits: number; dbQueries: number; totalRows: number }\n ): Promise<OptimizedFrameContext[]> {\n const contexts: OptimizedFrameContext[] = [];\n\n // Get cached contexts first\n const uncachedIds = [];\n for (const frameId of frameIds) {\n const cacheKey = createCacheKey('frame_context', [frameId, maxEvents]);\n if (enableCaching) {\n const cached = this.cache.getFrameContext(cacheKey);\n if (cached) {\n stats.cacheHits++;\n contexts.push(cached);\n continue;\n }\n }\n uncachedIds.push(frameId);\n }\n\n if (uncachedIds.length === 0) {\n return contexts;\n }\n\n // Batch fetch uncached frames\n const frames = await this.batchGetFrames(uncachedIds, stats);\n const allEvents = await this.batchGetEvents(uncachedIds, maxEvents, stats);\n const allAnchors = await this.batchGetAnchors(uncachedIds, stats);\n const allArtifacts = await this.batchGetArtifacts(uncachedIds, stats);\n\n // Assemble contexts from batched data\n for (const frameId of uncachedIds) {\n const frame = frames.get(frameId);\n if (!frame || (!includeClosed && frame.state === 'closed')) {\n continue;\n }\n\n const context: FrameContext = {\n frameId,\n header: {\n goal: frame.name,\n constraints: this.extractConstraints(frame.inputs),\n definitions: frame.inputs.definitions,\n },\n anchors: allAnchors.get(frameId) || [],\n recentEvents: allEvents.get(frameId) || [],\n activeArtifacts: allArtifacts.get(frameId) || [],\n };\n\n // Cache the context\n if (enableCaching) {\n const cacheKey = createCacheKey('frame_context', [frameId, maxEvents]);\n this.cache.cacheFrameContext(cacheKey, context);\n }\n\n contexts.push(context as OptimizedFrameContext);\n }\n\n return contexts;\n }\n\n /**\n * Batch get frames with single query\n */\n private async batchGetFrames(\n frameIds: string[],\n stats: { dbQueries: number; totalRows: number }\n ): Promise<Map<string, Frame>> {\n if (frameIds.length === 0) return new Map();\n\n const stmt = this.preparedStatements.get('batch_frames');\n if (!stmt) throw new Error('Prepared statement not found: batch_frames');\n\n const placeholders = frameIds.map(() => '?').join(',');\n const query = `SELECT * FROM frames WHERE frame_id IN (${placeholders})`;\n\n stats.dbQueries++;\n const rows = this.db.prepare(query).all(...frameIds) as any[];\n stats.totalRows += rows.length;\n\n const frameMap = new Map<string, Frame>();\n for (const row of rows) {\n frameMap.set(row.frame_id, {\n ...row,\n inputs: JSON.parse(row.inputs || '{}'),\n outputs: JSON.parse(row.outputs || '{}'),\n digest_json: JSON.parse(row.digest_json || '{}'),\n });\n }\n\n return frameMap;\n }\n\n /**\n * Batch get events for multiple frames\n */\n private async batchGetEvents(\n frameIds: string[],\n maxEvents: number,\n stats: { dbQueries: number; totalRows: number }\n ): Promise<Map<string, Event[]>> {\n if (frameIds.length === 0) return new Map();\n\n const placeholders = frameIds.map(() => '?').join(',');\n const query = `\n SELECT *, ROW_NUMBER() OVER (PARTITION BY frame_id ORDER BY seq DESC) as rn\n FROM events \n WHERE frame_id IN (${placeholders}) \n AND rn <= ${maxEvents}\n ORDER BY frame_id, seq DESC\n `;\n\n stats.dbQueries++;\n const rows = this.db.prepare(query).all(...frameIds) as any[];\n stats.totalRows += rows.length;\n\n const eventMap = new Map<string, Event[]>();\n for (const row of rows) {\n if (!eventMap.has(row.frame_id)) {\n eventMap.set(row.frame_id, []);\n }\n eventMap.get(row.frame_id)!.push({\n ...row,\n payload: JSON.parse(row.payload),\n });\n }\n\n return eventMap;\n }\n\n /**\n * Batch get anchors for multiple frames\n */\n private async batchGetAnchors(\n frameIds: string[],\n stats: { dbQueries: number; totalRows: number }\n ): Promise<Map<string, Anchor[]>> {\n if (frameIds.length === 0) return new Map();\n\n const placeholders = frameIds.map(() => '?').join(',');\n const query = `\n SELECT * FROM anchors \n WHERE frame_id IN (${placeholders}) \n ORDER BY frame_id, priority DESC, created_at ASC\n `;\n\n stats.dbQueries++;\n const rows = this.db.prepare(query).all(...frameIds) as any[];\n stats.totalRows += rows.length;\n\n const anchorMap = new Map<string, Anchor[]>();\n for (const row of rows) {\n if (!anchorMap.has(row.frame_id)) {\n anchorMap.set(row.frame_id, []);\n }\n anchorMap.get(row.frame_id)!.push({\n ...row,\n metadata: JSON.parse(row.metadata || '{}'),\n });\n }\n\n return anchorMap;\n }\n\n /**\n * Batch get active artifacts for multiple frames\n */\n private async batchGetArtifacts(\n frameIds: string[],\n stats: { dbQueries: number; totalRows: number }\n ): Promise<Map<string, string[]>> {\n if (frameIds.length === 0) return new Map();\n\n const placeholders = frameIds.map(() => '?').join(',');\n const query = `\n SELECT frame_id, payload\n FROM events \n WHERE frame_id IN (${placeholders}) \n AND event_type = 'artifact'\n ORDER BY frame_id, ts DESC\n `;\n\n stats.dbQueries++;\n const rows = this.db.prepare(query).all(...frameIds) as any[];\n stats.totalRows += rows.length;\n\n const artifactMap = new Map<string, string[]>();\n for (const row of rows) {\n const payload = JSON.parse(row.payload);\n if (!artifactMap.has(row.frame_id)) {\n artifactMap.set(row.frame_id, []);\n }\n if (payload.path) {\n artifactMap.get(row.frame_id)!.push(payload.path);\n }\n }\n\n return artifactMap;\n }\n\n /**\n * Assemble single frame context\n */\n private async assembleFrameContext(\n frameId: string,\n maxEvents: number,\n stats: { dbQueries: number; totalRows: number }\n ): Promise<FrameContext | null> {\n // Single frame operations - these could be further optimized with prepared statements\n const frame = await this.batchGetFrames([frameId], stats).then((map) =>\n map.get(frameId)\n );\n if (!frame) return null;\n\n const [events, anchors, artifacts] = await Promise.all([\n this.batchGetEvents([frameId], maxEvents, stats).then(\n (map) => map.get(frameId) || []\n ),\n this.batchGetAnchors([frameId], stats).then(\n (map) => map.get(frameId) || []\n ),\n this.batchGetArtifacts([frameId], stats).then(\n (map) => map.get(frameId) || []\n ),\n ]);\n\n return {\n frameId,\n header: {\n goal: frame.name,\n constraints: this.extractConstraints(frame.inputs),\n definitions: frame.inputs.definitions,\n },\n anchors,\n recentEvents: events,\n activeArtifacts: artifacts,\n };\n }\n\n /**\n * Extract constraints from frame inputs\n */\n private extractConstraints(inputs: Record<string, any>): string[] {\n const constraints: string[] = [];\n\n if (inputs.constraints && Array.isArray(inputs.constraints)) {\n constraints.push(...inputs.constraints);\n }\n\n if (inputs.requirements && Array.isArray(inputs.requirements)) {\n constraints.push(...inputs.requirements);\n }\n\n if (inputs.limitations && Array.isArray(inputs.limitations)) {\n constraints.push(...inputs.limitations);\n }\n\n return constraints;\n }\n\n /**\n * Initialize prepared statements for common queries\n */\n private initializePreparedStatements(): void {\n try {\n // Single frame query\n this.preparedStatements.set(\n 'single_frame',\n this.db.prepare('SELECT * FROM frames WHERE frame_id = ?')\n );\n\n // Frame events with limit\n this.preparedStatements.set(\n 'frame_events',\n this.db.prepare(\n 'SELECT * FROM events WHERE frame_id = ? ORDER BY seq DESC LIMIT ?'\n )\n );\n\n // Frame anchors\n this.preparedStatements.set(\n 'frame_anchors',\n this.db.prepare(\n 'SELECT * FROM anchors WHERE frame_id = ? ORDER BY priority DESC, created_at ASC'\n )\n );\n\n logger.info(\n 'Prepared statements initialized for optimized context assembly'\n );\n } catch (error: unknown) {\n logger.error('Failed to initialize prepared statements', error as Error);\n throw error;\n }\n }\n\n /**\n * Clear cache and reset prepared statements\n */\n cleanup(): void {\n this.cache.clear();\n // Modern better-sqlite3 automatically handles cleanup\n this.preparedStatements.clear();\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -129,9 +129,7 @@ class PerformanceBenchmark {
129
129
  const loader = new LazyContextLoader(db, projectId);
130
130
  let frames = [];
131
131
  try {
132
- frames = db.prepare(
133
- "SELECT id FROM frames ORDER BY updated_at DESC LIMIT ?"
134
- ).all(frameCount);
132
+ frames = db.prepare("SELECT id FROM frames ORDER BY updated_at DESC LIMIT ?").all(frameCount);
135
133
  } catch (error) {
136
134
  logger.warn("Frames table not found, using mock data for benchmark");
137
135
  frames = Array.from({ length: Math.min(frameCount, 10) }, (_, i) => ({
@@ -227,17 +225,23 @@ class PerformanceBenchmark {
227
225
  for (const result of suite.results) {
228
226
  console.log(`\u{1F4CA} ${result.name}`);
229
227
  console.log(` Duration: ${result.duration.toFixed(2)}ms`);
230
- console.log(` Memory: ${(result.memoryUsed / 1024 / 1024).toFixed(2)}MB`);
228
+ console.log(
229
+ ` Memory: ${(result.memoryUsed / 1024 / 1024).toFixed(2)}MB`
230
+ );
231
231
  console.log(` Throughput: ${result.throughput.toFixed(0)} items/sec`);
232
232
  if (result.improvement !== void 0) {
233
233
  const icon = result.improvement > 0 ? "\u{1F680}" : "\u26A0\uFE0F";
234
- console.log(` ${icon} Improvement: ${result.improvement.toFixed(1)}%`);
234
+ console.log(
235
+ ` ${icon} Improvement: ${result.improvement.toFixed(1)}%`
236
+ );
235
237
  }
236
238
  console.log("");
237
239
  }
238
240
  console.log("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
239
241
  console.log(`\u23F1\uFE0F Total Duration: ${suite.totalDuration.toFixed(2)}ms`);
240
- console.log(`\u{1F4C8} Average Improvement: ${suite.averageImprovement.toFixed(1)}%`);
242
+ console.log(
243
+ `\u{1F4C8} Average Improvement: ${suite.averageImprovement.toFixed(1)}%`
244
+ );
241
245
  console.log("");
242
246
  logger.info("Performance Benchmark Complete", {
243
247
  suite: suite.name,