claudia-orchestrator 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (296) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +109 -0
  3. package/dist/cli-parser.d.ts +11 -0
  4. package/dist/cli-parser.d.ts.map +1 -0
  5. package/dist/cli-parser.js +57 -0
  6. package/dist/cli-parser.js.map +1 -0
  7. package/dist/cui-server.d.ts +69 -0
  8. package/dist/cui-server.d.ts.map +1 -0
  9. package/dist/cui-server.js +705 -0
  10. package/dist/cui-server.js.map +1 -0
  11. package/dist/mcp-server/claudia-tools.d.ts +15 -0
  12. package/dist/mcp-server/claudia-tools.d.ts.map +1 -0
  13. package/dist/mcp-server/claudia-tools.js +366 -0
  14. package/dist/mcp-server/claudia-tools.js.map +1 -0
  15. package/dist/mcp-server/index.d.ts +3 -0
  16. package/dist/mcp-server/index.d.ts.map +1 -0
  17. package/dist/mcp-server/index.js +176 -0
  18. package/dist/mcp-server/index.js.map +1 -0
  19. package/dist/middleware/auth.d.ts +18 -0
  20. package/dist/middleware/auth.d.ts.map +1 -0
  21. package/dist/middleware/auth.js +136 -0
  22. package/dist/middleware/auth.js.map +1 -0
  23. package/dist/middleware/cors-setup.d.ts +7 -0
  24. package/dist/middleware/cors-setup.d.ts.map +1 -0
  25. package/dist/middleware/cors-setup.js +8 -0
  26. package/dist/middleware/cors-setup.js.map +1 -0
  27. package/dist/middleware/error-handler.d.ts +4 -0
  28. package/dist/middleware/error-handler.d.ts.map +1 -0
  29. package/dist/middleware/error-handler.js +27 -0
  30. package/dist/middleware/error-handler.js.map +1 -0
  31. package/dist/middleware/query-parser.d.ts +11 -0
  32. package/dist/middleware/query-parser.d.ts.map +1 -0
  33. package/dist/middleware/query-parser.js +68 -0
  34. package/dist/middleware/query-parser.js.map +1 -0
  35. package/dist/middleware/request-logger.d.ts +4 -0
  36. package/dist/middleware/request-logger.d.ts.map +1 -0
  37. package/dist/middleware/request-logger.js +29 -0
  38. package/dist/middleware/request-logger.js.map +1 -0
  39. package/dist/process-daemon/index.d.ts +14 -0
  40. package/dist/process-daemon/index.d.ts.map +1 -0
  41. package/dist/process-daemon/index.js +51 -0
  42. package/dist/process-daemon/index.js.map +1 -0
  43. package/dist/process-daemon/process-daemon.d.ts +78 -0
  44. package/dist/process-daemon/process-daemon.d.ts.map +1 -0
  45. package/dist/process-daemon/process-daemon.js +568 -0
  46. package/dist/process-daemon/process-daemon.js.map +1 -0
  47. package/dist/process-daemon/process-manager-client.d.ts +108 -0
  48. package/dist/process-daemon/process-manager-client.d.ts.map +1 -0
  49. package/dist/process-daemon/process-manager-client.js +314 -0
  50. package/dist/process-daemon/process-manager-client.js.map +1 -0
  51. package/dist/process-daemon/process-manager-interface.d.ts +47 -0
  52. package/dist/process-daemon/process-manager-interface.d.ts.map +1 -0
  53. package/dist/process-daemon/process-manager-interface.js +8 -0
  54. package/dist/process-daemon/process-manager-interface.js.map +1 -0
  55. package/dist/process-daemon/test-daemon.d.ts +12 -0
  56. package/dist/process-daemon/test-daemon.d.ts.map +1 -0
  57. package/dist/process-daemon/test-daemon.js +81 -0
  58. package/dist/process-daemon/test-daemon.js.map +1 -0
  59. package/dist/process-daemon/types.d.ts +85 -0
  60. package/dist/process-daemon/types.d.ts.map +1 -0
  61. package/dist/process-daemon/types.js +8 -0
  62. package/dist/process-daemon/types.js.map +1 -0
  63. package/dist/routes/claudia.routes.d.ts +10 -0
  64. package/dist/routes/claudia.routes.d.ts.map +1 -0
  65. package/dist/routes/claudia.routes.js +123 -0
  66. package/dist/routes/claudia.routes.js.map +1 -0
  67. package/dist/routes/config.routes.d.ts +4 -0
  68. package/dist/routes/config.routes.d.ts.map +1 -0
  69. package/dist/routes/config.routes.js +27 -0
  70. package/dist/routes/config.routes.js.map +1 -0
  71. package/dist/routes/conversation.routes.d.ts +8 -0
  72. package/dist/routes/conversation.routes.d.ts.map +1 -0
  73. package/dist/routes/conversation.routes.js +870 -0
  74. package/dist/routes/conversation.routes.js.map +1 -0
  75. package/dist/routes/filesystem.routes.d.ts +4 -0
  76. package/dist/routes/filesystem.routes.d.ts.map +1 -0
  77. package/dist/routes/filesystem.routes.js +86 -0
  78. package/dist/routes/filesystem.routes.js.map +1 -0
  79. package/dist/routes/gemini.routes.d.ts +4 -0
  80. package/dist/routes/gemini.routes.d.ts.map +1 -0
  81. package/dist/routes/gemini.routes.js +93 -0
  82. package/dist/routes/gemini.routes.js.map +1 -0
  83. package/dist/routes/insights.routes.d.ts +17 -0
  84. package/dist/routes/insights.routes.d.ts.map +1 -0
  85. package/dist/routes/insights.routes.js +417 -0
  86. package/dist/routes/insights.routes.js.map +1 -0
  87. package/dist/routes/license.routes.d.ts +3 -0
  88. package/dist/routes/license.routes.d.ts.map +1 -0
  89. package/dist/routes/license.routes.js +111 -0
  90. package/dist/routes/license.routes.js.map +1 -0
  91. package/dist/routes/log.routes.d.ts +3 -0
  92. package/dist/routes/log.routes.d.ts.map +1 -0
  93. package/dist/routes/log.routes.js +65 -0
  94. package/dist/routes/log.routes.js.map +1 -0
  95. package/dist/routes/notifications.routes.d.ts +4 -0
  96. package/dist/routes/notifications.routes.d.ts.map +1 -0
  97. package/dist/routes/notifications.routes.js +71 -0
  98. package/dist/routes/notifications.routes.js.map +1 -0
  99. package/dist/routes/permission.routes.d.ts +4 -0
  100. package/dist/routes/permission.routes.d.ts.map +1 -0
  101. package/dist/routes/permission.routes.js +116 -0
  102. package/dist/routes/permission.routes.js.map +1 -0
  103. package/dist/routes/question.routes.d.ts +8 -0
  104. package/dist/routes/question.routes.d.ts.map +1 -0
  105. package/dist/routes/question.routes.js +82 -0
  106. package/dist/routes/question.routes.js.map +1 -0
  107. package/dist/routes/streaming.routes.d.ts +4 -0
  108. package/dist/routes/streaming.routes.d.ts.map +1 -0
  109. package/dist/routes/streaming.routes.js +28 -0
  110. package/dist/routes/streaming.routes.js.map +1 -0
  111. package/dist/routes/system.routes.d.ts +5 -0
  112. package/dist/routes/system.routes.d.ts.map +1 -0
  113. package/dist/routes/system.routes.js +103 -0
  114. package/dist/routes/system.routes.js.map +1 -0
  115. package/dist/routes/working-directories.routes.d.ts +4 -0
  116. package/dist/routes/working-directories.routes.d.ts.map +1 -0
  117. package/dist/routes/working-directories.routes.js +25 -0
  118. package/dist/routes/working-directories.routes.js.map +1 -0
  119. package/dist/server.d.ts +3 -0
  120. package/dist/server.d.ts.map +1 -0
  121. package/dist/server.js +34 -0
  122. package/dist/server.js.map +1 -0
  123. package/dist/services/ToolMetricsService.d.ts +53 -0
  124. package/dist/services/ToolMetricsService.d.ts.map +1 -0
  125. package/dist/services/ToolMetricsService.js +230 -0
  126. package/dist/services/ToolMetricsService.js.map +1 -0
  127. package/dist/services/anthropic-service.d.ts +186 -0
  128. package/dist/services/anthropic-service.d.ts.map +1 -0
  129. package/dist/services/anthropic-service.js +1132 -0
  130. package/dist/services/anthropic-service.js.map +1 -0
  131. package/dist/services/claude-history-reader.d.ts +126 -0
  132. package/dist/services/claude-history-reader.d.ts.map +1 -0
  133. package/dist/services/claude-history-reader.js +717 -0
  134. package/dist/services/claude-history-reader.js.map +1 -0
  135. package/dist/services/claude-process-manager.d.ts +108 -0
  136. package/dist/services/claude-process-manager.d.ts.map +1 -0
  137. package/dist/services/claude-process-manager.js +909 -0
  138. package/dist/services/claude-process-manager.js.map +1 -0
  139. package/dist/services/claude-router-service.d.ts +19 -0
  140. package/dist/services/claude-router-service.d.ts.map +1 -0
  141. package/dist/services/claude-router-service.js +160 -0
  142. package/dist/services/claude-router-service.js.map +1 -0
  143. package/dist/services/claudia-service.d.ts +77 -0
  144. package/dist/services/claudia-service.d.ts.map +1 -0
  145. package/dist/services/claudia-service.js +194 -0
  146. package/dist/services/claudia-service.js.map +1 -0
  147. package/dist/services/commands-service.d.ts +18 -0
  148. package/dist/services/commands-service.d.ts.map +1 -0
  149. package/dist/services/commands-service.js +76 -0
  150. package/dist/services/commands-service.js.map +1 -0
  151. package/dist/services/config-service.d.ts +68 -0
  152. package/dist/services/config-service.d.ts.map +1 -0
  153. package/dist/services/config-service.js +429 -0
  154. package/dist/services/config-service.js.map +1 -0
  155. package/dist/services/conversation-cache.d.ts +86 -0
  156. package/dist/services/conversation-cache.d.ts.map +1 -0
  157. package/dist/services/conversation-cache.js +235 -0
  158. package/dist/services/conversation-cache.js.map +1 -0
  159. package/dist/services/conversation-status-manager.d.ts +98 -0
  160. package/dist/services/conversation-status-manager.d.ts.map +1 -0
  161. package/dist/services/conversation-status-manager.js +295 -0
  162. package/dist/services/conversation-status-manager.js.map +1 -0
  163. package/dist/services/cost-tracker.d.ts +87 -0
  164. package/dist/services/cost-tracker.d.ts.map +1 -0
  165. package/dist/services/cost-tracker.js +335 -0
  166. package/dist/services/cost-tracker.js.map +1 -0
  167. package/dist/services/file-system-service.d.ts +61 -0
  168. package/dist/services/file-system-service.d.ts.map +1 -0
  169. package/dist/services/file-system-service.js +348 -0
  170. package/dist/services/file-system-service.js.map +1 -0
  171. package/dist/services/gemini-service.d.ts +72 -0
  172. package/dist/services/gemini-service.d.ts.map +1 -0
  173. package/dist/services/gemini-service.js +431 -0
  174. package/dist/services/gemini-service.js.map +1 -0
  175. package/dist/services/insight-queue.d.ts +99 -0
  176. package/dist/services/insight-queue.d.ts.map +1 -0
  177. package/dist/services/insight-queue.js +277 -0
  178. package/dist/services/insight-queue.js.map +1 -0
  179. package/dist/services/insights-service.d.ts +102 -0
  180. package/dist/services/insights-service.d.ts.map +1 -0
  181. package/dist/services/insights-service.js +1152 -0
  182. package/dist/services/insights-service.js.map +1 -0
  183. package/dist/services/json-lines-parser.d.ts +19 -0
  184. package/dist/services/json-lines-parser.d.ts.map +1 -0
  185. package/dist/services/json-lines-parser.js +56 -0
  186. package/dist/services/json-lines-parser.js.map +1 -0
  187. package/dist/services/license-service.d.ts +69 -0
  188. package/dist/services/license-service.d.ts.map +1 -0
  189. package/dist/services/license-service.js +330 -0
  190. package/dist/services/license-service.js.map +1 -0
  191. package/dist/services/log-formatter.d.ts +5 -0
  192. package/dist/services/log-formatter.d.ts.map +1 -0
  193. package/dist/services/log-formatter.js +77 -0
  194. package/dist/services/log-formatter.js.map +1 -0
  195. package/dist/services/log-stream-buffer.d.ts +11 -0
  196. package/dist/services/log-stream-buffer.d.ts.map +1 -0
  197. package/dist/services/log-stream-buffer.js +36 -0
  198. package/dist/services/log-stream-buffer.js.map +1 -0
  199. package/dist/services/logger.d.ts +71 -0
  200. package/dist/services/logger.d.ts.map +1 -0
  201. package/dist/services/logger.js +215 -0
  202. package/dist/services/logger.js.map +1 -0
  203. package/dist/services/mcp-config-generator.d.ts +32 -0
  204. package/dist/services/mcp-config-generator.d.ts.map +1 -0
  205. package/dist/services/mcp-config-generator.js +126 -0
  206. package/dist/services/mcp-config-generator.js.map +1 -0
  207. package/dist/services/message-filter.d.ts +22 -0
  208. package/dist/services/message-filter.d.ts.map +1 -0
  209. package/dist/services/message-filter.js +57 -0
  210. package/dist/services/message-filter.js.map +1 -0
  211. package/dist/services/notification-service.d.ts +45 -0
  212. package/dist/services/notification-service.d.ts.map +1 -0
  213. package/dist/services/notification-service.js +184 -0
  214. package/dist/services/notification-service.js.map +1 -0
  215. package/dist/services/permission-tracker.d.ts +67 -0
  216. package/dist/services/permission-tracker.d.ts.map +1 -0
  217. package/dist/services/permission-tracker.js +161 -0
  218. package/dist/services/permission-tracker.js.map +1 -0
  219. package/dist/services/process-manager-factory.d.ts +81 -0
  220. package/dist/services/process-manager-factory.d.ts.map +1 -0
  221. package/dist/services/process-manager-factory.js +211 -0
  222. package/dist/services/process-manager-factory.js.map +1 -0
  223. package/dist/services/question-tracker.d.ts +47 -0
  224. package/dist/services/question-tracker.d.ts.map +1 -0
  225. package/dist/services/question-tracker.js +105 -0
  226. package/dist/services/question-tracker.js.map +1 -0
  227. package/dist/services/session-activity-watcher.d.ts +33 -0
  228. package/dist/services/session-activity-watcher.d.ts.map +1 -0
  229. package/dist/services/session-activity-watcher.js +194 -0
  230. package/dist/services/session-activity-watcher.js.map +1 -0
  231. package/dist/services/session-info-service.d.ts +228 -0
  232. package/dist/services/session-info-service.d.ts.map +1 -0
  233. package/dist/services/session-info-service.js +920 -0
  234. package/dist/services/session-info-service.js.map +1 -0
  235. package/dist/services/session-insights-service.d.ts +119 -0
  236. package/dist/services/session-insights-service.d.ts.map +1 -0
  237. package/dist/services/session-insights-service.js +889 -0
  238. package/dist/services/session-insights-service.js.map +1 -0
  239. package/dist/services/stream-manager.d.ts +62 -0
  240. package/dist/services/stream-manager.d.ts.map +1 -0
  241. package/dist/services/stream-manager.js +239 -0
  242. package/dist/services/stream-manager.js.map +1 -0
  243. package/dist/services/web-push-service.d.ts +48 -0
  244. package/dist/services/web-push-service.d.ts.map +1 -0
  245. package/dist/services/web-push-service.js +186 -0
  246. package/dist/services/web-push-service.js.map +1 -0
  247. package/dist/services/working-directories-service.d.ts +19 -0
  248. package/dist/services/working-directories-service.d.ts.map +1 -0
  249. package/dist/services/working-directories-service.js +103 -0
  250. package/dist/services/working-directories-service.js.map +1 -0
  251. package/dist/types/config.d.ts +111 -0
  252. package/dist/types/config.d.ts.map +1 -0
  253. package/dist/types/config.js +14 -0
  254. package/dist/types/config.js.map +1 -0
  255. package/dist/types/express.d.ts +5 -0
  256. package/dist/types/express.d.ts.map +1 -0
  257. package/dist/types/express.js +2 -0
  258. package/dist/types/express.js.map +1 -0
  259. package/dist/types/index.d.ts +325 -0
  260. package/dist/types/index.d.ts.map +1 -0
  261. package/dist/types/index.js +18 -0
  262. package/dist/types/index.js.map +1 -0
  263. package/dist/types/insights.d.ts +99 -0
  264. package/dist/types/insights.d.ts.map +1 -0
  265. package/dist/types/insights.js +7 -0
  266. package/dist/types/insights.js.map +1 -0
  267. package/dist/types/license.d.ts +70 -0
  268. package/dist/types/license.d.ts.map +1 -0
  269. package/dist/types/license.js +5 -0
  270. package/dist/types/license.js.map +1 -0
  271. package/dist/types/router-config.d.ts +13 -0
  272. package/dist/types/router-config.d.ts.map +1 -0
  273. package/dist/types/router-config.js +2 -0
  274. package/dist/types/router-config.js.map +1 -0
  275. package/dist/utils/constants.d.ts +26 -0
  276. package/dist/utils/constants.d.ts.map +1 -0
  277. package/dist/utils/constants.js +28 -0
  278. package/dist/utils/constants.js.map +1 -0
  279. package/dist/utils/machine-id.d.ts +7 -0
  280. package/dist/utils/machine-id.d.ts.map +1 -0
  281. package/dist/utils/machine-id.js +76 -0
  282. package/dist/utils/machine-id.js.map +1 -0
  283. package/dist/utils/server-startup.d.ts +13 -0
  284. package/dist/utils/server-startup.d.ts.map +1 -0
  285. package/dist/utils/server-startup.js +20 -0
  286. package/dist/utils/server-startup.js.map +1 -0
  287. package/dist/web/assets/main-DAc2rjJ2.css +1 -0
  288. package/dist/web/assets/main-DvlZ02mT.js +137 -0
  289. package/dist/web/favicon.png +0 -0
  290. package/dist/web/favicon.svg +22 -0
  291. package/dist/web/icon-192x192.png +0 -0
  292. package/dist/web/icon-512x512.png +0 -0
  293. package/dist/web/index.html +36 -0
  294. package/dist/web/manifest.json +61 -0
  295. package/package.json +174 -0
  296. package/scripts/postinstall.js +30 -0
@@ -0,0 +1,235 @@
1
+ import { createLogger } from './logger.js';
2
+ /**
3
+ * Service for managing conversation cache with file modification tracking
4
+ */
5
+ export class ConversationCache {
6
+ cache = null;
7
+ logger;
8
+ parsingPromises = new Map();
9
+ constructor() {
10
+ this.logger = createLogger('ConversationCache');
11
+ }
12
+ /**
13
+ * Clear the conversation cache to force a refresh on next read
14
+ */
15
+ clear() {
16
+ this.logger.debug('Clearing conversation cache');
17
+ const previousStats = this.cache ? {
18
+ cachedFileCount: this.cache.fileCache.size,
19
+ totalEntries: Array.from(this.cache.fileCache.values())
20
+ .reduce((sum, cache) => sum + cache.entries.length, 0)
21
+ } : { cachedFileCount: 0, totalEntries: 0 };
22
+ this.cache = null;
23
+ this.parsingPromises.clear();
24
+ this.logger.info('Conversation cache cleared', {
25
+ previousStats,
26
+ timestamp: new Date().toISOString()
27
+ });
28
+ }
29
+ /**
30
+ * Get cached file entries, combining cached and newly parsed entries
31
+ */
32
+ async getCachedFileEntries(currentFileModTimes, parseFileFunction, getSourceProject) {
33
+ this.logger.debug('Getting cached file entries', {
34
+ hasCachedData: !!this.cache,
35
+ currentFileCount: currentFileModTimes.size
36
+ });
37
+ // Initialize cache if it doesn't exist
38
+ if (!this.cache) {
39
+ this.cache = {
40
+ fileCache: new Map(),
41
+ lastCacheTime: Date.now()
42
+ };
43
+ }
44
+ const allEntries = [];
45
+ let filesFromCache = 0;
46
+ let filesReparsed = 0;
47
+ // Process each file: use cache OR re-parse if changed
48
+ for (const [filePath, currentMtime] of currentFileModTimes) {
49
+ const cached = this.cache.fileCache.get(filePath);
50
+ if (cached && cached.mtime === currentMtime) {
51
+ // Use cached entries (skip expensive file I/O + JSON parsing)
52
+ const entriesWithSource = cached.entries.map(entry => ({
53
+ ...entry,
54
+ sourceProject: cached.sourceProject
55
+ }));
56
+ allEntries.push(...entriesWithSource);
57
+ filesFromCache++;
58
+ }
59
+ else {
60
+ // Re-parse this file (expensive operation)
61
+ try {
62
+ const entries = await parseFileFunction(filePath);
63
+ const sourceProject = getSourceProject(filePath);
64
+ // Update cache for this file
65
+ this.cache.fileCache.set(filePath, {
66
+ entries,
67
+ mtime: currentMtime,
68
+ sourceProject
69
+ });
70
+ const entriesWithSource = entries.map(entry => ({
71
+ ...entry,
72
+ sourceProject
73
+ }));
74
+ allEntries.push(...entriesWithSource);
75
+ filesReparsed++;
76
+ }
77
+ catch (error) {
78
+ this.logger.warn('Failed to parse file, skipping', { filePath, error });
79
+ // Remove from cache if it exists
80
+ this.cache.fileCache.delete(filePath);
81
+ }
82
+ }
83
+ }
84
+ // Clean up cache entries for files that no longer exist
85
+ for (const [cachedFilePath] of this.cache.fileCache) {
86
+ if (!currentFileModTimes.has(cachedFilePath)) {
87
+ this.logger.debug('Removing cache entry for deleted file', { filePath: cachedFilePath });
88
+ this.cache.fileCache.delete(cachedFilePath);
89
+ }
90
+ }
91
+ this.logger.debug('File cache processing complete', {
92
+ totalFiles: currentFileModTimes.size,
93
+ filesFromCache,
94
+ filesReparsed,
95
+ totalEntries: allEntries.length,
96
+ cachedFileCount: this.cache.fileCache.size
97
+ });
98
+ return allEntries;
99
+ }
100
+ /**
101
+ * Update a specific file's cache entry
102
+ */
103
+ updateFileCache(filePath, entries, mtime, sourceProject) {
104
+ if (!this.cache) {
105
+ this.cache = {
106
+ fileCache: new Map(),
107
+ lastCacheTime: Date.now()
108
+ };
109
+ }
110
+ this.cache.fileCache.set(filePath, {
111
+ entries,
112
+ mtime,
113
+ sourceProject
114
+ });
115
+ this.logger.debug('File cache updated', {
116
+ filePath,
117
+ entryCount: entries.length,
118
+ sourceProject,
119
+ mtime: new Date(mtime).toISOString()
120
+ });
121
+ }
122
+ /**
123
+ * Clear cache entry for a specific file
124
+ */
125
+ clearFileCache(filePath) {
126
+ if (this.cache?.fileCache.has(filePath)) {
127
+ this.cache.fileCache.delete(filePath);
128
+ this.logger.debug('File cache cleared', { filePath });
129
+ }
130
+ }
131
+ /**
132
+ * Check if a specific file's cache entry is valid
133
+ */
134
+ isFileCacheValid(filePath, currentMtime) {
135
+ if (!this.cache) {
136
+ return false;
137
+ }
138
+ const cached = this.cache.fileCache.get(filePath);
139
+ return cached ? cached.mtime === currentMtime : false;
140
+ }
141
+ /**
142
+ * Get or parse conversations with file-level caching and concurrency protection
143
+ */
144
+ async getOrParseConversations(currentFileModTimes, parseFileFunction, getSourceProject, processAllEntries) {
145
+ // Create cache key based on file set to avoid returning wrong results for different filters
146
+ const cacheKey = Array.from(currentFileModTimes.keys()).sort().join('|');
147
+ this.logger.debug('Request for conversations received', {
148
+ hasCachedData: !!this.cache,
149
+ activeParsings: this.parsingPromises.size,
150
+ currentFileCount: currentFileModTimes.size
151
+ });
152
+ // If already parsing THIS SAME file set, wait for it to complete
153
+ const existingPromise = this.parsingPromises.get(cacheKey);
154
+ if (existingPromise) {
155
+ this.logger.debug('Parsing already in progress for this file set, waiting for completion', {
156
+ fileCount: currentFileModTimes.size
157
+ });
158
+ try {
159
+ const result = await existingPromise;
160
+ this.logger.debug('Concurrent parsing completed, returning result', {
161
+ conversationCount: result.length
162
+ });
163
+ return result;
164
+ }
165
+ catch (error) {
166
+ this.logger.error('Concurrent parsing failed', error);
167
+ // Clear the failed promise and fall through to retry
168
+ this.parsingPromises.delete(cacheKey);
169
+ }
170
+ }
171
+ const parsingPromise = this.executeFileBasedParsing(currentFileModTimes, parseFileFunction, getSourceProject, processAllEntries);
172
+ this.parsingPromises.set(cacheKey, parsingPromise);
173
+ try {
174
+ const result = await parsingPromise;
175
+ this.parsingPromises.delete(cacheKey);
176
+ return result;
177
+ }
178
+ catch (error) {
179
+ this.parsingPromises.delete(cacheKey);
180
+ throw error;
181
+ }
182
+ }
183
+ /**
184
+ * Execute file-based parsing with proper logging
185
+ */
186
+ async executeFileBasedParsing(currentFileModTimes, parseFileFunction, getSourceProject, processAllEntries) {
187
+ const parseStartTime = Date.now();
188
+ this.logger.debug('Executing file-based parsing');
189
+ // Get all entries using file-level caching
190
+ const allEntries = await this.getCachedFileEntries(currentFileModTimes, parseFileFunction, getSourceProject);
191
+ // Process entries into conversations (cheap in-memory operation)
192
+ const conversations = processAllEntries(allEntries);
193
+ const parseElapsed = Date.now() - parseStartTime;
194
+ this.logger.debug('File-based parsing completed', {
195
+ conversationCount: conversations.length,
196
+ totalEntries: allEntries.length,
197
+ parseElapsedMs: parseElapsed
198
+ });
199
+ return conversations;
200
+ }
201
+ /**
202
+ * Get cache statistics for monitoring
203
+ */
204
+ getStats() {
205
+ if (!this.cache) {
206
+ return {
207
+ isLoaded: false,
208
+ cachedFileCount: 0,
209
+ totalCachedEntries: 0,
210
+ lastCacheTime: null,
211
+ cacheAge: null,
212
+ isCurrentlyParsing: this.parsingPromises.size > 0,
213
+ fileCacheDetails: []
214
+ };
215
+ }
216
+ const totalCachedEntries = Array.from(this.cache.fileCache.values())
217
+ .reduce((sum, cache) => sum + cache.entries.length, 0);
218
+ const fileCacheDetails = Array.from(this.cache.fileCache.entries())
219
+ .map(([filePath, cache]) => ({
220
+ filePath,
221
+ entryCount: cache.entries.length,
222
+ mtime: new Date(cache.mtime).toISOString()
223
+ }));
224
+ return {
225
+ isLoaded: true,
226
+ cachedFileCount: this.cache.fileCache.size,
227
+ totalCachedEntries,
228
+ lastCacheTime: this.cache.lastCacheTime,
229
+ cacheAge: Date.now() - this.cache.lastCacheTime,
230
+ isCurrentlyParsing: this.parsingPromises.size > 0,
231
+ fileCacheDetails
232
+ };
233
+ }
234
+ }
235
+ //# sourceMappingURL=conversation-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-cache.js","sourceRoot":"","sources":["../../src/services/conversation-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ import { EventEmitter } from 'events';
2
+ import { ConversationSummary, ConversationMessage, ConversationDetailsResponse } from '../types/index.js';
3
+ /**
4
+ * Context data stored for active conversations that have not yet been written to local directories
5
+ */
6
+ export interface ConversationStatusContext {
7
+ initialPrompt: string;
8
+ workingDirectory: string;
9
+ model: string;
10
+ timestamp: string;
11
+ inheritedMessages?: ConversationMessage[];
12
+ }
13
+ /**
14
+ * Unified service for managing conversation status and tracking active session status.
15
+ * This service combines the functionality of ConversationStatusTracker and optimistic conversation handling.
16
+ *
17
+ * Responsibilities:
18
+ * - Track active streaming sessions and their Claude session IDs
19
+ * - Store conversation status contexts for active sessions
20
+ * - Generate optimistic conversation summaries and details for UI feedback
21
+ * - Emit events for session lifecycle (started/ended)
22
+ */
23
+ export declare class ConversationStatusManager extends EventEmitter {
24
+ private sessionToStreaming;
25
+ private streamingToSession;
26
+ private sessionContext;
27
+ private logger;
28
+ constructor();
29
+ /**
30
+ * Register a new active streaming session with optional conversation context
31
+ * This is called when we extract the session_id from the first stream message
32
+ */
33
+ registerActiveSession(streamingId: string, claudeSessionId: string, conversationContext?: {
34
+ initialPrompt: string;
35
+ workingDirectory: string;
36
+ model?: string;
37
+ inheritedMessages?: ConversationMessage[];
38
+ }): void;
39
+ /**
40
+ * Unregister an active streaming session when it ends
41
+ */
42
+ unregisterActiveSession(streamingId: string): void;
43
+ /**
44
+ * Get conversation context for an active session
45
+ */
46
+ getConversationContext(claudeSessionId: string): ConversationStatusContext | undefined;
47
+ /**
48
+ * Check if a Claude session ID is currently active (has ongoing stream)
49
+ */
50
+ isSessionActive(claudeSessionId: string): boolean;
51
+ /**
52
+ * Get the streaming ID for an active Claude session
53
+ */
54
+ getStreamingId(claudeSessionId: string): string | undefined;
55
+ /**
56
+ * Get the Claude session ID for an active streaming session
57
+ */
58
+ getSessionId(streamingId: string): string | undefined;
59
+ /**
60
+ * Get all active Claude session IDs
61
+ */
62
+ getActiveSessionIds(): string[];
63
+ /**
64
+ * Get all active streaming IDs
65
+ */
66
+ getActiveStreamingIds(): string[];
67
+ /**
68
+ * Get conversation status for a Claude session ID
69
+ */
70
+ getConversationStatus(claudeSessionId: string): 'completed' | 'ongoing' | 'pending';
71
+ /**
72
+ * Get conversations that haven't appeared in history yet
73
+ * Used by the conversation list endpoint
74
+ */
75
+ getConversationsNotInHistory(existingSessionIds: Set<string>): ConversationSummary[];
76
+ /**
77
+ * Get conversation details if session is active but not in history
78
+ * Used by the conversation details endpoint
79
+ */
80
+ getActiveConversationDetails(sessionId: string): ConversationDetailsResponse | null;
81
+ /**
82
+ * Clear all mappings (useful for testing)
83
+ */
84
+ clear(): void;
85
+ /**
86
+ * Get statistics about tracked sessions
87
+ */
88
+ getStats(): {
89
+ activeSessionsCount: number;
90
+ activeStreamingIdsCount: number;
91
+ activeContextsCount: number;
92
+ activeSessions: Array<{
93
+ claudeSessionId: string;
94
+ streamingId: string;
95
+ }>;
96
+ };
97
+ }
98
+ //# sourceMappingURL=conversation-status-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-status-manager.d.ts","sourceRoot":"","sources":["../../src/services/conversation-status-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAC;AAEzG;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC3C;AAED;;;;;;;;;GASG;AACH,qBAAa,yBAA0B,SAAQ,YAAY;IAEzD,OAAO,CAAC,kBAAkB,CAAkC;IAE5D,OAAO,CAAC,kBAAkB,CAAkC;IAE5D,OAAO,CAAC,cAAc,CAAqD;IAC3E,OAAO,CAAC,MAAM,CAAS;;IAOvB;;;OAGG;IACH,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,mBAAmB,CAAC,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,iBAAiB,CAAC,EAAE,mBAAmB,EAAE,CAAA;KAAE,GAAG,IAAI;IAyD/M;;OAEG;IACH,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAuBlD;;OAEG;IACH,sBAAsB,CAAC,eAAe,EAAE,MAAM,GAAG,yBAAyB,GAAG,SAAS;IAStF;;OAEG;IACH,eAAe,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO;IAKjD;;OAEG;IACH,cAAc,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI3D;;OAEG;IACH,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IASrD;;OAEG;IACH,mBAAmB,IAAI,MAAM,EAAE;IAS/B;;OAEG;IACH,qBAAqB,IAAI,MAAM,EAAE;IASjC;;OAEG;IACH,qBAAqB,CAAC,eAAe,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS;IAMnF;;;OAGG;IACH,4BAA4B,CAAC,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,mBAAmB,EAAE;IA0DpF;;;OAGG;IACH,4BAA4B,CAAC,SAAS,EAAE,MAAM,GAAG,2BAA2B,GAAG,IAAI;IAyDnF;;OAEG;IACH,KAAK,IAAI,IAAI;IAOb;;OAEG;IACH,QAAQ,IAAI;QACV,mBAAmB,EAAE,MAAM,CAAC;QAC5B,uBAAuB,EAAE,MAAM,CAAC;QAChC,mBAAmB,EAAE,MAAM,CAAC;QAC5B,cAAc,EAAE,KAAK,CAAC;YAAE,eAAe,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACzE;CAYF"}
@@ -0,0 +1,295 @@
1
+ import { EventEmitter } from 'events';
2
+ import { createLogger } from './logger.js';
3
+ /**
4
+ * Unified service for managing conversation status and tracking active session status.
5
+ * This service combines the functionality of ConversationStatusTracker and optimistic conversation handling.
6
+ *
7
+ * Responsibilities:
8
+ * - Track active streaming sessions and their Claude session IDs
9
+ * - Store conversation status contexts for active sessions
10
+ * - Generate optimistic conversation summaries and details for UI feedback
11
+ * - Emit events for session lifecycle (started/ended)
12
+ */
13
+ export class ConversationStatusManager extends EventEmitter {
14
+ // Maps Claude session ID -> CUI streaming ID
15
+ sessionToStreaming = new Map();
16
+ // Maps CUI streaming ID -> Claude session ID (reverse lookup)
17
+ streamingToSession = new Map();
18
+ // Maps Claude session ID -> conversation context for active sessions
19
+ sessionContext = new Map();
20
+ logger;
21
+ constructor() {
22
+ super();
23
+ this.logger = createLogger('ConversationStatusManager');
24
+ }
25
+ /**
26
+ * Register a new active streaming session with optional conversation context
27
+ * This is called when we extract the session_id from the first stream message
28
+ */
29
+ registerActiveSession(streamingId, claudeSessionId, conversationContext) {
30
+ // Remove any existing mapping for this Claude session
31
+ const existingStreamingId = this.sessionToStreaming.get(claudeSessionId);
32
+ if (existingStreamingId && existingStreamingId !== streamingId) {
33
+ this.logger.debug('Removing existing mapping for Claude session', {
34
+ claudeSessionId,
35
+ oldStreamingId: existingStreamingId,
36
+ newStreamingId: streamingId
37
+ });
38
+ this.streamingToSession.delete(existingStreamingId);
39
+ }
40
+ // Remove any existing mapping for this streaming ID
41
+ const existingClaudeSessionId = this.streamingToSession.get(streamingId);
42
+ if (existingClaudeSessionId && existingClaudeSessionId !== claudeSessionId) {
43
+ this.logger.debug('Removing existing mapping for streaming ID', {
44
+ streamingId,
45
+ oldClaudeSessionId: existingClaudeSessionId,
46
+ newClaudeSessionId: claudeSessionId
47
+ });
48
+ this.sessionToStreaming.delete(existingClaudeSessionId);
49
+ this.sessionContext.delete(existingClaudeSessionId);
50
+ }
51
+ // Set the new mapping
52
+ this.sessionToStreaming.set(claudeSessionId, streamingId);
53
+ this.streamingToSession.set(streamingId, claudeSessionId);
54
+ // If conversation context is provided, store it immediately
55
+ if (conversationContext) {
56
+ const context = {
57
+ initialPrompt: conversationContext.initialPrompt,
58
+ workingDirectory: conversationContext.workingDirectory,
59
+ model: conversationContext.model || 'default',
60
+ timestamp: new Date().toISOString(),
61
+ inheritedMessages: conversationContext.inheritedMessages
62
+ };
63
+ this.sessionContext.set(claudeSessionId, context);
64
+ this.logger.debug('Stored conversation status context', {
65
+ claudeSessionId,
66
+ hasInitialPrompt: !!context.initialPrompt,
67
+ workingDirectory: context.workingDirectory,
68
+ model: context.model,
69
+ inheritedMessageCount: context.inheritedMessages?.length || 0
70
+ });
71
+ }
72
+ this.logger.info('[SESSION-TRACK] Session registered', {
73
+ streamingId: streamingId.slice(0, 8),
74
+ sessionId: claudeSessionId.slice(0, 8),
75
+ totalActive: this.sessionToStreaming.size
76
+ });
77
+ this.emit('session-started', { streamingId, claudeSessionId });
78
+ }
79
+ /**
80
+ * Unregister an active streaming session when it ends
81
+ */
82
+ unregisterActiveSession(streamingId) {
83
+ const claudeSessionId = this.streamingToSession.get(streamingId);
84
+ if (claudeSessionId) {
85
+ this.sessionToStreaming.delete(claudeSessionId);
86
+ this.streamingToSession.delete(streamingId);
87
+ this.sessionContext.delete(claudeSessionId);
88
+ this.logger.info('[SESSION-TRACK] Session unregistered', {
89
+ streamingId: streamingId.slice(0, 8),
90
+ sessionId: claudeSessionId.slice(0, 8),
91
+ remainingActive: this.sessionToStreaming.size
92
+ });
93
+ this.emit('session-ended', { streamingId, claudeSessionId });
94
+ }
95
+ else {
96
+ // This is normal during startup/restart - not worth logging at warn level
97
+ this.logger.debug('[SESSION-TRACK] Attempted to unregister unknown streamingId', {
98
+ streamingId: streamingId.slice(0, 8)
99
+ });
100
+ }
101
+ }
102
+ /**
103
+ * Get conversation context for an active session
104
+ */
105
+ getConversationContext(claudeSessionId) {
106
+ const context = this.sessionContext.get(claudeSessionId);
107
+ this.logger.debug('Getting conversation context', {
108
+ claudeSessionId,
109
+ hasContext: !!context
110
+ });
111
+ return context;
112
+ }
113
+ /**
114
+ * Check if a Claude session ID is currently active (has ongoing stream)
115
+ */
116
+ isSessionActive(claudeSessionId) {
117
+ const isActive = this.sessionToStreaming.has(claudeSessionId);
118
+ return isActive;
119
+ }
120
+ /**
121
+ * Get the streaming ID for an active Claude session
122
+ */
123
+ getStreamingId(claudeSessionId) {
124
+ return this.sessionToStreaming.get(claudeSessionId);
125
+ }
126
+ /**
127
+ * Get the Claude session ID for an active streaming session
128
+ */
129
+ getSessionId(streamingId) {
130
+ const claudeSessionId = this.streamingToSession.get(streamingId);
131
+ this.logger.debug('Getting Claude session ID for streaming ID', {
132
+ streamingId,
133
+ claudeSessionId: claudeSessionId || 'not found'
134
+ });
135
+ return claudeSessionId;
136
+ }
137
+ /**
138
+ * Get all active Claude session IDs
139
+ */
140
+ getActiveSessionIds() {
141
+ const sessions = Array.from(this.sessionToStreaming.keys());
142
+ this.logger.debug('Getting all active session IDs', {
143
+ count: sessions.length,
144
+ sessions
145
+ });
146
+ return sessions;
147
+ }
148
+ /**
149
+ * Get all active streaming IDs
150
+ */
151
+ getActiveStreamingIds() {
152
+ const streamingIds = Array.from(this.streamingToSession.keys());
153
+ this.logger.debug('Getting all active streaming IDs', {
154
+ count: streamingIds.length,
155
+ streamingIds
156
+ });
157
+ return streamingIds;
158
+ }
159
+ /**
160
+ * Get conversation status for a Claude session ID
161
+ */
162
+ getConversationStatus(claudeSessionId) {
163
+ const isActive = this.isSessionActive(claudeSessionId);
164
+ const status = isActive ? 'ongoing' : 'completed';
165
+ return status;
166
+ }
167
+ /**
168
+ * Get conversations that haven't appeared in history yet
169
+ * Used by the conversation list endpoint
170
+ */
171
+ getConversationsNotInHistory(existingSessionIds) {
172
+ const activeSessionIds = this.getActiveSessionIds();
173
+ const conversationsNotInHistory = activeSessionIds
174
+ .filter(sessionId => !existingSessionIds.has(sessionId))
175
+ .map(sessionId => {
176
+ const context = this.getConversationContext(sessionId);
177
+ const streamingId = this.getStreamingId(sessionId);
178
+ if (context && streamingId) {
179
+ // Create conversation entry for active session
180
+ const conversationSummary = {
181
+ sessionId,
182
+ projectPath: context.workingDirectory,
183
+ summary: '', // No summary for active conversation
184
+ sessionInfo: {
185
+ custom_name: '', // No custom name yet
186
+ created_at: context.timestamp,
187
+ updated_at: context.timestamp,
188
+ version: 4,
189
+ pinned: false,
190
+ archived: false,
191
+ continuation_session_id: '',
192
+ initial_commit_head: '',
193
+ permission_mode: 'default'
194
+ },
195
+ createdAt: context.timestamp,
196
+ updatedAt: context.timestamp,
197
+ messageCount: 1, // At least the initial user message
198
+ totalDuration: 0, // No duration yet
199
+ model: context.model || 'unknown',
200
+ status: 'ongoing',
201
+ streamingId
202
+ };
203
+ this.logger.debug('Created conversation summary for active session', {
204
+ sessionId,
205
+ streamingId,
206
+ workingDirectory: context.workingDirectory,
207
+ model: context.model
208
+ });
209
+ return conversationSummary;
210
+ }
211
+ return null;
212
+ })
213
+ .filter((conversation) => conversation !== null);
214
+ this.logger.debug('Generated conversations not in history', {
215
+ activeSessionCount: activeSessionIds.length,
216
+ existingSessionCount: existingSessionIds.size,
217
+ conversationsNotInHistoryCount: conversationsNotInHistory.length
218
+ });
219
+ return conversationsNotInHistory;
220
+ }
221
+ /**
222
+ * Get conversation details if session is active but not in history
223
+ * Used by the conversation details endpoint
224
+ */
225
+ getActiveConversationDetails(sessionId) {
226
+ const isActive = this.isSessionActive(sessionId);
227
+ const context = this.getConversationContext(sessionId);
228
+ this.logger.debug('Checking for active conversation details', {
229
+ sessionId,
230
+ isActive,
231
+ hasContext: !!context
232
+ });
233
+ if (!isActive || !context) {
234
+ return null;
235
+ }
236
+ // Create messages array
237
+ const messages = [];
238
+ // Add inherited messages first (if any)
239
+ if (context.inheritedMessages) {
240
+ messages.push(...context.inheritedMessages);
241
+ }
242
+ // Add the current initial prompt message
243
+ const activeMessage = {
244
+ uuid: `active-${sessionId}-user`,
245
+ type: 'user',
246
+ message: {
247
+ role: 'user',
248
+ content: context.initialPrompt
249
+ },
250
+ timestamp: context.timestamp,
251
+ sessionId: sessionId,
252
+ cwd: context.workingDirectory
253
+ };
254
+ messages.push(activeMessage);
255
+ const response = {
256
+ messages,
257
+ summary: '', // No summary for active conversation
258
+ projectPath: context.workingDirectory,
259
+ metadata: {
260
+ totalDuration: 0,
261
+ model: context.model || 'unknown'
262
+ }
263
+ };
264
+ this.logger.debug('Created active conversation details', {
265
+ sessionId,
266
+ workingDirectory: context.workingDirectory,
267
+ model: context.model,
268
+ totalMessageCount: messages.length,
269
+ inheritedMessageCount: context.inheritedMessages?.length || 0
270
+ });
271
+ return response;
272
+ }
273
+ /**
274
+ * Clear all mappings (useful for testing)
275
+ */
276
+ clear() {
277
+ this.logger.debug('Clearing all session mappings');
278
+ this.sessionToStreaming.clear();
279
+ this.streamingToSession.clear();
280
+ this.sessionContext.clear();
281
+ }
282
+ /**
283
+ * Get statistics about tracked sessions
284
+ */
285
+ getStats() {
286
+ const activeSessions = Array.from(this.sessionToStreaming.entries()).map(([claudeSessionId, streamingId]) => ({ claudeSessionId, streamingId }));
287
+ return {
288
+ activeSessionsCount: this.sessionToStreaming.size,
289
+ activeStreamingIdsCount: this.streamingToSession.size,
290
+ activeContextsCount: this.sessionContext.size,
291
+ activeSessions
292
+ };
293
+ }
294
+ }
295
+ //# sourceMappingURL=conversation-status-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-status-manager.js","sourceRoot":"","sources":["../../src/services/conversation-status-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,YAAY,EAAe,MAAM,aAAa,CAAC;AAcxD;;;;;;;;;GASG;AACH,MAAM,OAAO,yBAA0B,SAAQ,YAAY;IACzD,6CAA6C;IACrC,kBAAkB,GAAwB,IAAI,GAAG,EAAE,CAAC;IAC5D,8DAA8D;IACtD,kBAAkB,GAAwB,IAAI,GAAG,EAAE,CAAC;IAC5D,qEAAqE;IAC7D,cAAc,GAA2C,IAAI,GAAG,EAAE,CAAC;IACnE,MAAM,CAAS;IAEvB;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,MAAM,GAAG,YAAY,CAAC,2BAA2B,CAAC,CAAC;IAC1D,CAAC;IAED;;;OAGG;IACH,qBAAqB,CAAC,WAAmB,EAAE,eAAuB,EAAE,mBAAoI;QACtM,sDAAsD;QACtD,MAAM,mBAAmB,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QACzE,IAAI,mBAAmB,IAAI,mBAAmB,KAAK,WAAW,EAAE,CAAC;YAC/D,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,8CAA8C,EAAE;gBAChE,eAAe;gBACf,cAAc,EAAE,mBAAmB;gBACnC,cAAc,EAAE,WAAW;aAC5B,CAAC,CAAC;YACH,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;QACtD,CAAC;QAED,oDAAoD;QACpD,MAAM,uBAAuB,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACzE,IAAI,uBAAuB,IAAI,uBAAuB,KAAK,eAAe,EAAE,CAAC;YAC3E,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4CAA4C,EAAE;gBAC9D,WAAW;gBACX,kBAAkB,EAAE,uBAAuB;gBAC3C,kBAAkB,EAAE,eAAe;aACpC,CAAC,CAAC;YACH,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC;YACxD,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC;QACtD,CAAC;QAED,sBAAsB;QACtB,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC;QAC1D,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;QAE1D,4DAA4D;QAC5D,IAAI,mBAAmB,EAAE,CAAC;YACxB,MAAM,OAAO,GAA8B;gBACzC,aAAa,EAAE,mBAAmB,CAAC,aAAa;gBAChD,gBAAgB,EAAE,mBAAmB,CAAC,gBAAgB;gBACtD,KAAK,EAAE,mBAAmB,CAAC,KAAK,IAAI,SAAS;gBAC7C,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,iBAAiB,EAAE,mBAAmB,CAAC,iBAAiB;aACzD,CAAC;YACF,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;YAElD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oCAAoC,EAAE;gBACtD,eAAe;gBACf,gBAAgB,EAAE,CAAC,CAAC,OAAO,CAAC,aAAa;gBACzC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;gBAC1C,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,qBAAqB,EAAE,OAAO,CAAC,iBAAiB,EAAE,MAAM,IAAI,CAAC;aAC9D,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,oCAAoC,EAAE;YACrD,WAAW,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;YACpC,SAAS,EAAE,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;YACtC,WAAW,EAAE,IAAI,CAAC,kBAAkB,CAAC,IAAI;SAC1C,CAAC,CAAC;QAEH,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC,CAAC;IACjE,CAAC;IAED;;OAEG;IACH,uBAAuB,CAAC,WAAmB;QACzC,MAAM,eAAe,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAEjE,IAAI,eAAe,EAAE,CAAC;YACpB,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;YAChD,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YAC5C,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;YAE5C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,sCAAsC,EAAE;gBACvD,WAAW,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;gBACpC,SAAS,EAAE,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;gBACtC,eAAe,EAAE,IAAI,CAAC,kBAAkB,CAAC,IAAI;aAC9C,CAAC,CAAC;YAEH,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC,CAAC;QAC/D,CAAC;aAAM,CAAC;YACN,0EAA0E;YAC1E,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,6DAA6D,EAAE;gBAC/E,WAAW,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;aACrC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED;;OAEG;IACH,sBAAsB,CAAC,eAAuB;QAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,EAAE;YAChD,eAAe;YACf,UAAU,EAAE,CAAC,CAAC,OAAO;SACtB,CAAC,CAAC;QACH,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,eAAe,CAAC,eAAuB;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAC9D,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;OAEG;IACH,cAAc,CAAC,eAAuB;QACpC,OAAO,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACtD,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,WAAmB;QAC9B,MAAM,eAAe,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACjE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4CAA4C,EAAE;YAC9D,WAAW;YACX,eAAe,EAAE,eAAe,IAAI,WAAW;SAChD,CAAC,CAAC;QACH,OAAO,eAAe,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,mBAAmB;QACjB,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5D,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,EAAE;YAClD,KAAK,EAAE,QAAQ,CAAC,MAAM;YACtB,QAAQ;SACT,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;OAEG;IACH,qBAAqB;QACnB,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC;QAChE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,kCAAkC,EAAE;YACpD,KAAK,EAAE,YAAY,CAAC,MAAM;YAC1B,YAAY;SACb,CAAC,CAAC;QACH,OAAO,YAAY,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,qBAAqB,CAAC,eAAuB;QAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC;QAClD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;OAGG;IACH,4BAA4B,CAAC,kBAA+B;QAC1D,MAAM,gBAAgB,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAEpD,MAAM,yBAAyB,GAAG,gBAAgB;aAC/C,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,kBAAkB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;aACvD,GAAG,CAAC,SAAS,CAAC,EAAE;YACf,MAAM,OAAO,GAAG,IAAI,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC;YACvD,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;YAEnD,IAAI,OAAO,IAAI,WAAW,EAAE,CAAC;gBAC3B,+CAA+C;gBAC/C,MAAM,mBAAmB,GAAwB;oBAC/C,SAAS;oBACT,WAAW,EAAE,OAAO,CAAC,gBAAgB;oBACrC,OAAO,EAAE,EAAE,EAAE,qCAAqC;oBAClD,WAAW,EAAE;wBACX,WAAW,EAAE,EAAE,EAAE,qBAAqB;wBACtC,UAAU,EAAE,OAAO,CAAC,SAAS;wBAC7B,UAAU,EAAE,OAAO,CAAC,SAAS;wBAC7B,OAAO,EAAE,CAAC;wBACV,MAAM,EAAE,KAAK;wBACb,QAAQ,EAAE,KAAK;wBACf,uBAAuB,EAAE,EAAE;wBAC3B,mBAAmB,EAAE,EAAE;wBACvB,eAAe,EAAE,SAAS;qBAC3B;oBACD,SAAS,EAAE,OAAO,CAAC,SAAS;oBAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;oBAC5B,YAAY,EAAE,CAAC,EAAE,oCAAoC;oBACrD,aAAa,EAAE,CAAC,EAAE,kBAAkB;oBACpC,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,SAAS;oBACjC,MAAM,EAAE,SAAkB;oBAC1B,WAAW;iBACZ,CAAC;gBAEF,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,iDAAiD,EAAE;oBACnE,SAAS;oBACT,WAAW;oBACX,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;oBAC1C,KAAK,EAAE,OAAO,CAAC,KAAK;iBACrB,CAAC,CAAC;gBAEH,OAAO,mBAAmB,CAAC;YAC7B,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC,CAAC;aACD,MAAM,CAAC,CAAC,YAAY,EAAuC,EAAE,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC;QAExF,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,wCAAwC,EAAE;YAC1D,kBAAkB,EAAE,gBAAgB,CAAC,MAAM;YAC3C,oBAAoB,EAAE,kBAAkB,CAAC,IAAI;YAC7C,8BAA8B,EAAE,yBAAyB,CAAC,MAAM;SACjE,CAAC,CAAC;QAEH,OAAO,yBAAyB,CAAC;IACnC,CAAC;IAED;;;OAGG;IACH,4BAA4B,CAAC,SAAiB;QAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QACjD,MAAM,OAAO,GAAG,IAAI,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC;QAEvD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,0CAA0C,EAAE;YAC5D,SAAS;YACT,QAAQ;YACR,UAAU,EAAE,CAAC,CAAC,OAAO;SACtB,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,IAAI,CAAC,OAAO,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,wBAAwB;QACxB,MAAM,QAAQ,GAA0B,EAAE,CAAC;QAE3C,wCAAwC;QACxC,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;YAC9B,QAAQ,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;QAC9C,CAAC;QAED,yCAAyC;QACzC,MAAM,aAAa,GAAwB;YACzC,IAAI,EAAE,UAAU,SAAS,OAAO;YAChC,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACP,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,OAAO,CAAC,aAAa;aAC/B;YACD,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,SAAS,EAAE,SAAS;YACpB,GAAG,EAAE,OAAO,CAAC,gBAAgB;SAC9B,CAAC;QACF,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAE7B,MAAM,QAAQ,GAAgC;YAC5C,QAAQ;YACR,OAAO,EAAE,EAAE,EAAE,qCAAqC;YAClD,WAAW,EAAE,OAAO,CAAC,gBAAgB;YACrC,QAAQ,EAAE;gBACR,aAAa,EAAE,CAAC;gBAChB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,SAAS;aAClC;SACF,CAAC;QAEF,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,qCAAqC,EAAE;YACvD,SAAS;YACT,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;YAC1C,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,iBAAiB,EAAE,QAAQ,CAAC,MAAM;YAClC,qBAAqB,EAAE,OAAO,CAAC,iBAAiB,EAAE,MAAM,IAAI,CAAC;SAC9D,CAAC,CAAC;QAEH,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC;QAChC,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC;QAChC,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;IAC9B,CAAC;IAED;;OAEG;IACH,QAAQ;QAMN,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CACtE,CAAC,CAAC,eAAe,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,eAAe,EAAE,WAAW,EAAE,CAAC,CACvE,CAAC;QAEF,OAAO;YACL,mBAAmB,EAAE,IAAI,CAAC,kBAAkB,CAAC,IAAI;YACjD,uBAAuB,EAAE,IAAI,CAAC,kBAAkB,CAAC,IAAI;YACrD,mBAAmB,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI;YAC7C,cAAc;SACf,CAAC;IACJ,CAAC;CACF"}