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,211 @@
1
+ /**
2
+ * Process Manager Factory
3
+ *
4
+ * Creates either a direct ClaudeProcessManager or a ProcessManagerClient
5
+ * depending on configuration. This allows cui-server to work with either mode.
6
+ */
7
+ import { EventEmitter } from 'events';
8
+ import { ClaudeProcessManager } from './claude-process-manager.js';
9
+ import { ProcessManagerClient } from '../process-daemon/process-manager-client.js';
10
+ import { DEFAULT_SOCKET_PATH } from '../process-daemon/types.js';
11
+ import { createLogger } from './logger.js';
12
+ const logger = createLogger('ProcessManagerFactory');
13
+ /**
14
+ * Unified process manager type - wraps either implementation
15
+ * and provides a consistent interface to cui-server.
16
+ */
17
+ export class UnifiedProcessManager extends EventEmitter {
18
+ _direct = null;
19
+ _client = null;
20
+ _mode;
21
+ _activeSessions = new Set();
22
+ constructor(mode) {
23
+ super();
24
+ this._mode = mode;
25
+ }
26
+ get mode() {
27
+ return this._mode;
28
+ }
29
+ /**
30
+ * Initialize with direct process manager
31
+ */
32
+ initDirect(manager) {
33
+ this._direct = manager;
34
+ // Forward events
35
+ manager.on('claude-message', (data) => {
36
+ this._activeSessions.add(data.streamingId);
37
+ this.emit('claude-message', data);
38
+ });
39
+ manager.on('process-closed', (data) => {
40
+ this._activeSessions.delete(data.streamingId);
41
+ this.emit('process-closed', data);
42
+ });
43
+ manager.on('process-error', (data) => this.emit('process-error', data));
44
+ }
45
+ /**
46
+ * Initialize with daemon client
47
+ */
48
+ async initClient(client) {
49
+ this._client = client;
50
+ await client.connect();
51
+ // Forward events
52
+ client.on('claude-message', (data) => {
53
+ this._activeSessions.add(data.streamingId);
54
+ this.emit('claude-message', data);
55
+ });
56
+ client.on('process-closed', (data) => {
57
+ this._activeSessions.delete(data.streamingId);
58
+ this.emit('process-closed', data);
59
+ });
60
+ client.on('process-error', (data) => this.emit('process-error', data));
61
+ // Sync initial active sessions from daemon
62
+ try {
63
+ const sessions = await client.getActiveSessions();
64
+ for (const s of sessions) {
65
+ this._activeSessions.add(s);
66
+ }
67
+ logger.info('Synced active sessions from daemon', { count: sessions.length });
68
+ }
69
+ catch (error) {
70
+ logger.warn('Failed to sync active sessions from daemon', { error });
71
+ }
72
+ }
73
+ // ============================================================================
74
+ // Unified Interface - matches ClaudeProcessManager signature
75
+ // ============================================================================
76
+ async startConversation(config) {
77
+ if (this._direct) {
78
+ return this._direct.startConversation(config);
79
+ }
80
+ if (this._client) {
81
+ return this._client.startConversation(config);
82
+ }
83
+ throw new Error('Process manager not initialized');
84
+ }
85
+ async stopConversation(streamingId) {
86
+ if (this._direct) {
87
+ return this._direct.stopConversation(streamingId);
88
+ }
89
+ if (this._client) {
90
+ return this._client.stopConversation(streamingId);
91
+ }
92
+ throw new Error('Process manager not initialized');
93
+ }
94
+ forceKillConversation(streamingId) {
95
+ if (this._direct) {
96
+ return this._direct.forceKillConversation(streamingId);
97
+ }
98
+ if (this._client) {
99
+ return this._client.forceKillConversation(streamingId);
100
+ }
101
+ throw new Error('Process manager not initialized');
102
+ }
103
+ /**
104
+ * Get active sessions - SYNCHRONOUS for backwards compatibility
105
+ * Uses local cache that's kept in sync via events
106
+ */
107
+ getActiveSessions() {
108
+ return Array.from(this._activeSessions);
109
+ }
110
+ /**
111
+ * Check if session is active - SYNCHRONOUS for backwards compatibility
112
+ */
113
+ isSessionActive(streamingId) {
114
+ return this._activeSessions.has(streamingId);
115
+ }
116
+ /**
117
+ * Send question answer
118
+ */
119
+ sendQuestionAnswer(streamingId, answer) {
120
+ if (this._direct) {
121
+ return this._direct.sendQuestionAnswer(streamingId, answer);
122
+ }
123
+ if (this._client) {
124
+ // Fire and forget for sync interface
125
+ this._client.sendQuestionAnswer(streamingId, answer).catch((err) => {
126
+ logger.error('Failed to send question answer', err);
127
+ });
128
+ return true;
129
+ }
130
+ return false;
131
+ }
132
+ /**
133
+ * Send stdin message
134
+ */
135
+ sendStdinMessage(streamingId, message) {
136
+ if (this._direct) {
137
+ return this._direct.sendStdinMessage(streamingId, message);
138
+ }
139
+ if (this._client) {
140
+ // Fire and forget for sync interface
141
+ this._client.sendStdinMessage(streamingId, message).catch((err) => {
142
+ logger.error('Failed to send stdin message', err);
143
+ });
144
+ return true;
145
+ }
146
+ return false;
147
+ }
148
+ // ============================================================================
149
+ // Configuration Methods (delegated or no-op)
150
+ // ============================================================================
151
+ setMCPConfigPath(path) {
152
+ if (this._direct) {
153
+ this._direct.setMCPConfigPath(path);
154
+ }
155
+ // No-op in client mode - daemon handles this
156
+ }
157
+ setConversationStatusManager(service) {
158
+ if (this._direct) {
159
+ this._direct.setConversationStatusManager(service);
160
+ }
161
+ // No-op in client mode
162
+ }
163
+ setNotificationService(service) {
164
+ if (this._direct) {
165
+ this._direct.setNotificationService(service);
166
+ }
167
+ // No-op in client mode
168
+ }
169
+ setRouterService(service) {
170
+ if (this._direct) {
171
+ this._direct.setRouterService(service);
172
+ }
173
+ // No-op in client mode
174
+ }
175
+ /**
176
+ * Disconnect from daemon (daemon mode) or cleanup (direct mode)
177
+ * Must be called during server shutdown to prevent reconnection loops
178
+ */
179
+ disconnect() {
180
+ if (this._client) {
181
+ logger.info('Disconnecting from process daemon');
182
+ this._client.disconnect();
183
+ }
184
+ // Direct mode: nothing to disconnect, processes are managed directly
185
+ }
186
+ }
187
+ /**
188
+ * Create a process manager based on configuration
189
+ */
190
+ export async function createProcessManager(options) {
191
+ // Always use daemon mode - the daemon runs independently and survives server restarts
192
+ const mode = options.mode || 'daemon';
193
+ const socketPath = options.daemonSocketPath || process.env.CUI_DAEMON_SOCKET || DEFAULT_SOCKET_PATH;
194
+ logger.info('Creating process manager', { mode, socketPath: mode === 'daemon' ? socketPath : undefined });
195
+ const unified = new UnifiedProcessManager(mode);
196
+ if (mode === 'daemon') {
197
+ const client = new ProcessManagerClient(socketPath);
198
+ await unified.initClient(client);
199
+ logger.info('Process manager initialized in daemon mode');
200
+ }
201
+ else {
202
+ if (!options.historyReader || !options.statusTracker) {
203
+ throw new Error('Direct mode requires historyReader and statusTracker');
204
+ }
205
+ const direct = new ClaudeProcessManager(options.historyReader, options.statusTracker, undefined, undefined, options.toolMetricsService, options.sessionInfoService, options.fileSystemService);
206
+ unified.initDirect(direct);
207
+ logger.info('Process manager initialized in direct mode');
208
+ }
209
+ return unified;
210
+ }
211
+ //# sourceMappingURL=process-manager-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-manager-factory.js","sourceRoot":"","sources":["../../src/services/process-manager-factory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import { EventEmitter } from 'events';
2
+ import { QuestionRequest, QuestionDefinition } from '../types/index.js';
3
+ /**
4
+ * Service to track AskUserQuestion requests from Claude CLI.
5
+ * Unlike permissions (which use MCP polling), questions are answered via stdin.
6
+ */
7
+ export declare class QuestionTracker extends EventEmitter {
8
+ private questionRequests;
9
+ constructor();
10
+ /**
11
+ * Add a new question request from AskUserQuestion tool
12
+ */
13
+ addQuestionRequest(toolUseId: string, questions: QuestionDefinition[], streamingId: string): QuestionRequest;
14
+ /**
15
+ * Get all question requests
16
+ */
17
+ getAllQuestionRequests(): QuestionRequest[];
18
+ /**
19
+ * Get question requests filtered by criteria
20
+ */
21
+ getQuestionRequests(filter?: {
22
+ streamingId?: string;
23
+ status?: 'pending' | 'answered';
24
+ }): QuestionRequest[];
25
+ /**
26
+ * Get a specific question request by ID
27
+ */
28
+ getQuestionRequest(id: string): QuestionRequest | undefined;
29
+ /**
30
+ * Mark a question as answered
31
+ */
32
+ markAnswered(id: string, answers: Record<string, string>): boolean;
33
+ /**
34
+ * Clear all question requests (for testing)
35
+ */
36
+ clear(): void;
37
+ /**
38
+ * Get the number of question requests
39
+ */
40
+ size(): number;
41
+ /**
42
+ * Remove all questions for a specific streaming ID
43
+ * Used for cleanup when a conversation ends
44
+ */
45
+ removeQuestionsByStreamingId(streamingId: string): number;
46
+ }
47
+ //# sourceMappingURL=question-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"question-tracker.d.ts","sourceRoot":"","sources":["../../src/services/question-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAGvE;;;GAGG;AACH,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,OAAO,CAAC,gBAAgB,CAA2C;;IAMnE;;OAEG;IACH,kBAAkB,CAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,kBAAkB,EAAE,EAC/B,WAAW,EAAE,MAAM,GAClB,eAAe;IAoBlB;;OAEG;IACH,sBAAsB,IAAI,eAAe,EAAE;IAI3C;;OAEG;IACH,mBAAmB,CAAC,MAAM,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,SAAS,GAAG,UAAU,CAAA;KAAE,GAAG,eAAe,EAAE;IAc1G;;OAEG;IACH,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAI3D;;OAEG;IACH,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO;IAgBlE;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,IAAI,IAAI,MAAM;IAId;;;OAGG;IACH,4BAA4B,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;CAoB1D"}
@@ -0,0 +1,105 @@
1
+ import { EventEmitter } from 'events';
2
+ import { v4 as uuidv4 } from 'uuid';
3
+ import { logger } from '../services/logger.js';
4
+ /**
5
+ * Service to track AskUserQuestion requests from Claude CLI.
6
+ * Unlike permissions (which use MCP polling), questions are answered via stdin.
7
+ */
8
+ export class QuestionTracker extends EventEmitter {
9
+ questionRequests = new Map();
10
+ constructor() {
11
+ super();
12
+ }
13
+ /**
14
+ * Add a new question request from AskUserQuestion tool
15
+ */
16
+ addQuestionRequest(toolUseId, questions, streamingId) {
17
+ const id = uuidv4();
18
+ const request = {
19
+ id,
20
+ streamingId,
21
+ toolUseId,
22
+ questions,
23
+ timestamp: new Date().toISOString(),
24
+ status: 'pending',
25
+ };
26
+ this.questionRequests.set(id, request);
27
+ logger.info('Question request added', { id, toolUseId, streamingId, questionCount: questions.length });
28
+ // Emit event for new question request
29
+ this.emit('question_request', request);
30
+ return request;
31
+ }
32
+ /**
33
+ * Get all question requests
34
+ */
35
+ getAllQuestionRequests() {
36
+ return Array.from(this.questionRequests.values());
37
+ }
38
+ /**
39
+ * Get question requests filtered by criteria
40
+ */
41
+ getQuestionRequests(filter) {
42
+ let requests = Array.from(this.questionRequests.values());
43
+ if (filter?.streamingId) {
44
+ requests = requests.filter(req => req.streamingId === filter.streamingId);
45
+ }
46
+ if (filter?.status) {
47
+ requests = requests.filter(req => req.status === filter.status);
48
+ }
49
+ return requests;
50
+ }
51
+ /**
52
+ * Get a specific question request by ID
53
+ */
54
+ getQuestionRequest(id) {
55
+ return this.questionRequests.get(id);
56
+ }
57
+ /**
58
+ * Mark a question as answered
59
+ */
60
+ markAnswered(id, answers) {
61
+ const request = this.questionRequests.get(id);
62
+ if (!request) {
63
+ logger.warn('Question request not found', { id });
64
+ return false;
65
+ }
66
+ request.status = 'answered';
67
+ request.answers = answers;
68
+ logger.info('Question request answered', { id, answers });
69
+ this.emit('question_answered', request);
70
+ return true;
71
+ }
72
+ /**
73
+ * Clear all question requests (for testing)
74
+ */
75
+ clear() {
76
+ this.questionRequests.clear();
77
+ }
78
+ /**
79
+ * Get the number of question requests
80
+ */
81
+ size() {
82
+ return this.questionRequests.size;
83
+ }
84
+ /**
85
+ * Remove all questions for a specific streaming ID
86
+ * Used for cleanup when a conversation ends
87
+ */
88
+ removeQuestionsByStreamingId(streamingId) {
89
+ const toRemove = [];
90
+ for (const [id, request] of this.questionRequests.entries()) {
91
+ if (request.streamingId === streamingId) {
92
+ toRemove.push(id);
93
+ }
94
+ }
95
+ toRemove.forEach(id => this.questionRequests.delete(id));
96
+ if (toRemove.length > 0) {
97
+ logger.info('Removed questions for streaming session', {
98
+ streamingId,
99
+ removedCount: toRemove.length
100
+ });
101
+ }
102
+ return toRemove.length;
103
+ }
104
+ }
105
+ //# sourceMappingURL=question-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"question-tracker.js","sourceRoot":"","sources":["../../src/services/question-tracker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { EventEmitter } from 'events';
2
+ /**
3
+ * Watches Claude session JSONL files for changes and emits activity updates
4
+ */
5
+ export declare class SessionActivityWatcher extends EventEmitter {
6
+ private logger;
7
+ private insightsService;
8
+ private historyReader;
9
+ private watchers;
10
+ private debounceTimers;
11
+ private projectsDir;
12
+ private isWatching;
13
+ private readonly DEBOUNCE_MS;
14
+ constructor();
15
+ /**
16
+ * Start watching for session file changes
17
+ */
18
+ start(): void;
19
+ /**
20
+ * Emit an insights update event (called by InsightsEventHandler)
21
+ */
22
+ emitInsightsUpdate(sessionId: string, type: 'generated' | 'patched'): Promise<void>;
23
+ /**
24
+ * Stop watching
25
+ */
26
+ stop(): void;
27
+ private watchDirectory;
28
+ private watchProjectDirectory;
29
+ private handleFileChange;
30
+ private extractAndEmit;
31
+ }
32
+ export declare function getSessionActivityWatcher(): SessionActivityWatcher;
33
+ //# sourceMappingURL=session-activity-watcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-activity-watcher.d.ts","sourceRoot":"","sources":["../../src/services/session-activity-watcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AA0BtC;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,YAAY;IACtD,OAAO,CAAC,MAAM,CAA0C;IACxD,OAAO,CAAC,eAAe,CAAyB;IAChD,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,QAAQ,CAAwC;IACxD,OAAO,CAAC,cAAc,CAA0C;IAChE,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAAS;IAG3B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAO;;IASnC;;OAEG;IACH,KAAK,IAAI,IAAI;IA6Bb;;OAEG;IACG,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IA6BzF;;OAEG;IACH,IAAI,IAAI,IAAI;IAgBZ,OAAO,CAAC,cAAc;IAsBtB,OAAO,CAAC,qBAAqB;IAkB7B,OAAO,CAAC,gBAAgB;YAqBV,cAAc;CAgC7B;AAKD,wBAAgB,yBAAyB,IAAI,sBAAsB,CAKlE"}
@@ -0,0 +1,194 @@
1
+ import { EventEmitter } from 'events';
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+ import * as os from 'os';
5
+ import { createLogger } from './logger.js';
6
+ import { SessionInsightsService } from './session-insights-service.js';
7
+ import { ClaudeHistoryReader } from './claude-history-reader.js';
8
+ /**
9
+ * Watches Claude session JSONL files for changes and emits activity updates
10
+ */
11
+ export class SessionActivityWatcher extends EventEmitter {
12
+ logger = createLogger('SessionActivityWatcher');
13
+ insightsService;
14
+ historyReader;
15
+ watchers = new Map();
16
+ debounceTimers = new Map();
17
+ projectsDir;
18
+ isWatching = false;
19
+ // Debounce file changes to avoid rapid-fire updates
20
+ DEBOUNCE_MS = 100;
21
+ constructor() {
22
+ super();
23
+ this.historyReader = new ClaudeHistoryReader();
24
+ this.insightsService = new SessionInsightsService(this.historyReader);
25
+ this.projectsDir = path.join(os.homedir(), '.claude', 'projects');
26
+ }
27
+ /**
28
+ * Start watching for session file changes
29
+ */
30
+ start() {
31
+ if (this.isWatching)
32
+ return;
33
+ this.logger.info('Starting session activity watcher', { projectsDir: this.projectsDir });
34
+ try {
35
+ // Watch the projects directory for new project folders
36
+ this.watchDirectory(this.projectsDir);
37
+ // Watch existing project directories
38
+ if (fs.existsSync(this.projectsDir)) {
39
+ const projects = fs.readdirSync(this.projectsDir);
40
+ for (const project of projects) {
41
+ const projectPath = path.join(this.projectsDir, project);
42
+ if (fs.statSync(projectPath).isDirectory()) {
43
+ this.watchProjectDirectory(projectPath);
44
+ }
45
+ }
46
+ }
47
+ this.isWatching = true;
48
+ this.logger.info('Session activity watcher started', {
49
+ watcherCount: this.watchers.size
50
+ });
51
+ }
52
+ catch (error) {
53
+ this.logger.error('Failed to start session activity watcher', error);
54
+ }
55
+ }
56
+ /**
57
+ * Emit an insights update event (called by InsightsEventHandler)
58
+ */
59
+ async emitInsightsUpdate(sessionId, type) {
60
+ // Try to fetch identity image to include in the update
61
+ let identityImage;
62
+ try {
63
+ const { SessionInfoService } = await import('./session-info-service.js');
64
+ const sessionInfoService = SessionInfoService.getInstance();
65
+ const sessionInfo = await sessionInfoService.getSessionInfo(sessionId);
66
+ identityImage = sessionInfo.identity_image ?? undefined;
67
+ }
68
+ catch (error) {
69
+ // Identity image not available yet, that's okay
70
+ this.logger.debug('No identity image available for insights update', {
71
+ sessionId: sessionId.slice(0, 8)
72
+ });
73
+ }
74
+ const update = {
75
+ sessionId,
76
+ type,
77
+ timestamp: Date.now(),
78
+ identityImage
79
+ };
80
+ this.logger.debug('Emitting insights update', {
81
+ sessionId: sessionId.slice(0, 8),
82
+ type,
83
+ hasIdentityImage: !!identityImage
84
+ });
85
+ this.emit('insights', update);
86
+ }
87
+ /**
88
+ * Stop watching
89
+ */
90
+ stop() {
91
+ this.logger.info('Stopping session activity watcher');
92
+ for (const [path, watcher] of this.watchers) {
93
+ watcher.close();
94
+ }
95
+ this.watchers.clear();
96
+ for (const timer of this.debounceTimers.values()) {
97
+ clearTimeout(timer);
98
+ }
99
+ this.debounceTimers.clear();
100
+ this.isWatching = false;
101
+ }
102
+ watchDirectory(dirPath) {
103
+ if (this.watchers.has(dirPath))
104
+ return;
105
+ try {
106
+ const watcher = fs.watch(dirPath, { persistent: false }, (eventType, filename) => {
107
+ if (!filename)
108
+ return;
109
+ const fullPath = path.join(dirPath, filename);
110
+ // Check if it's a new project directory
111
+ if (fs.existsSync(fullPath) && fs.statSync(fullPath).isDirectory()) {
112
+ this.watchProjectDirectory(fullPath);
113
+ }
114
+ });
115
+ this.watchers.set(dirPath, watcher);
116
+ this.logger.debug('Watching directory', { dirPath });
117
+ }
118
+ catch (error) {
119
+ this.logger.warn('Failed to watch directory', { dirPath, error });
120
+ }
121
+ }
122
+ watchProjectDirectory(projectPath) {
123
+ if (this.watchers.has(projectPath))
124
+ return;
125
+ try {
126
+ const watcher = fs.watch(projectPath, { persistent: false }, (eventType, filename) => {
127
+ if (!filename || !filename.endsWith('.jsonl'))
128
+ return;
129
+ const filePath = path.join(projectPath, filename);
130
+ this.handleFileChange(filePath, filename);
131
+ });
132
+ this.watchers.set(projectPath, watcher);
133
+ this.logger.debug('Watching project directory', { projectPath });
134
+ }
135
+ catch (error) {
136
+ this.logger.warn('Failed to watch project directory', { projectPath, error });
137
+ }
138
+ }
139
+ handleFileChange(filePath, filename) {
140
+ // Extract session ID from filename (e.g., "abc123-def456.jsonl" -> "abc123-def456")
141
+ const sessionId = filename.replace('.jsonl', '');
142
+ this.logger.debug('File change detected', {
143
+ sessionId: sessionId.slice(0, 8),
144
+ filename
145
+ });
146
+ // Debounce rapid changes
147
+ const existingTimer = this.debounceTimers.get(sessionId);
148
+ if (existingTimer) {
149
+ clearTimeout(existingTimer);
150
+ }
151
+ this.debounceTimers.set(sessionId, setTimeout(async () => {
152
+ this.debounceTimers.delete(sessionId);
153
+ await this.extractAndEmit(sessionId, filePath);
154
+ }, this.DEBOUNCE_MS));
155
+ }
156
+ async extractAndEmit(sessionId, filePath) {
157
+ try {
158
+ const { messages } = await this.historyReader.fetchConversationDirect(sessionId);
159
+ const recentActions = this.insightsService.extractRecentActions(messages, 10);
160
+ // Only emit when we have something to show
161
+ if (recentActions.length === 0) {
162
+ this.logger.debug('Skipping empty activity update', {
163
+ sessionId: sessionId.slice(0, 8)
164
+ });
165
+ return;
166
+ }
167
+ const update = {
168
+ sessionId,
169
+ recentActions,
170
+ timestamp: Date.now()
171
+ };
172
+ this.logger.debug('Emitting activity update', {
173
+ sessionId: sessionId.slice(0, 8),
174
+ actionCount: recentActions.length
175
+ });
176
+ this.emit('activity', update);
177
+ }
178
+ catch (error) {
179
+ this.logger.debug('Failed to extract activity', {
180
+ sessionId: sessionId.slice(0, 8),
181
+ error
182
+ });
183
+ }
184
+ }
185
+ }
186
+ // Singleton instance
187
+ let instance = null;
188
+ export function getSessionActivityWatcher() {
189
+ if (!instance) {
190
+ instance = new SessionActivityWatcher();
191
+ }
192
+ return instance;
193
+ }
194
+ //# sourceMappingURL=session-activity-watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-activity-watcher.js","sourceRoot":"","sources":["../../src/services/session-activity-watcher.ts"],"names":[],"mappings":"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"}