lattice-orchestrator 0.7.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 (440) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +58 -0
  3. package/config/logrotate.conf +15 -0
  4. package/dist/cli-parser.d.ts +11 -0
  5. package/dist/cli-parser.d.ts.map +1 -0
  6. package/dist/cli-parser.js +48 -0
  7. package/dist/cli-parser.js.map +1 -0
  8. package/dist/lattice-server.d.ts +70 -0
  9. package/dist/lattice-server.d.ts.map +1 -0
  10. package/dist/lattice-server.js +969 -0
  11. package/dist/lattice-server.js.map +1 -0
  12. package/dist/mcp-server/index.d.ts +3 -0
  13. package/dist/mcp-server/index.d.ts.map +1 -0
  14. package/dist/mcp-server/index.js +190 -0
  15. package/dist/mcp-server/index.js.map +1 -0
  16. package/dist/mcp-server/lattice-tools.d.ts +15 -0
  17. package/dist/mcp-server/lattice-tools.d.ts.map +1 -0
  18. package/dist/mcp-server/lattice-tools.js +366 -0
  19. package/dist/mcp-server/lattice-tools.js.map +1 -0
  20. package/dist/middleware/cors-setup.d.ts +7 -0
  21. package/dist/middleware/cors-setup.d.ts.map +1 -0
  22. package/dist/middleware/cors-setup.js +8 -0
  23. package/dist/middleware/cors-setup.js.map +1 -0
  24. package/dist/middleware/error-handler.d.ts +4 -0
  25. package/dist/middleware/error-handler.d.ts.map +1 -0
  26. package/dist/middleware/error-handler.js +27 -0
  27. package/dist/middleware/error-handler.js.map +1 -0
  28. package/dist/middleware/query-parser.d.ts +11 -0
  29. package/dist/middleware/query-parser.d.ts.map +1 -0
  30. package/dist/middleware/query-parser.js +68 -0
  31. package/dist/middleware/query-parser.js.map +1 -0
  32. package/dist/middleware/request-logger.d.ts +4 -0
  33. package/dist/middleware/request-logger.d.ts.map +1 -0
  34. package/dist/middleware/request-logger.js +6 -0
  35. package/dist/middleware/request-logger.js.map +1 -0
  36. package/dist/process-daemon/index.d.ts +14 -0
  37. package/dist/process-daemon/index.d.ts.map +1 -0
  38. package/dist/process-daemon/index.js +51 -0
  39. package/dist/process-daemon/index.js.map +1 -0
  40. package/dist/process-daemon/process-daemon.d.ts +101 -0
  41. package/dist/process-daemon/process-daemon.d.ts.map +1 -0
  42. package/dist/process-daemon/process-daemon.js +846 -0
  43. package/dist/process-daemon/process-daemon.js.map +1 -0
  44. package/dist/process-daemon/process-manager-client.d.ts +123 -0
  45. package/dist/process-daemon/process-manager-client.d.ts.map +1 -0
  46. package/dist/process-daemon/process-manager-client.js +329 -0
  47. package/dist/process-daemon/process-manager-client.js.map +1 -0
  48. package/dist/process-daemon/process-manager-interface.d.ts +61 -0
  49. package/dist/process-daemon/process-manager-interface.d.ts.map +1 -0
  50. package/dist/process-daemon/process-manager-interface.js +8 -0
  51. package/dist/process-daemon/process-manager-interface.js.map +1 -0
  52. package/dist/process-daemon/test-daemon.d.ts +12 -0
  53. package/dist/process-daemon/test-daemon.d.ts.map +1 -0
  54. package/dist/process-daemon/test-daemon.js +81 -0
  55. package/dist/process-daemon/test-daemon.js.map +1 -0
  56. package/dist/process-daemon/types.d.ts +97 -0
  57. package/dist/process-daemon/types.d.ts.map +1 -0
  58. package/dist/process-daemon/types.js +8 -0
  59. package/dist/process-daemon/types.js.map +1 -0
  60. package/dist/routes/analysis.routes.d.ts +13 -0
  61. package/dist/routes/analysis.routes.d.ts.map +1 -0
  62. package/dist/routes/analysis.routes.js +520 -0
  63. package/dist/routes/analysis.routes.js.map +1 -0
  64. package/dist/routes/config.routes.d.ts +4 -0
  65. package/dist/routes/config.routes.d.ts.map +1 -0
  66. package/dist/routes/config.routes.js +27 -0
  67. package/dist/routes/config.routes.js.map +1 -0
  68. package/dist/routes/conversation.routes.d.ts +43 -0
  69. package/dist/routes/conversation.routes.d.ts.map +1 -0
  70. package/dist/routes/conversation.routes.js +79 -0
  71. package/dist/routes/conversation.routes.js.map +1 -0
  72. package/dist/routes/filesystem.routes.d.ts +4 -0
  73. package/dist/routes/filesystem.routes.d.ts.map +1 -0
  74. package/dist/routes/filesystem.routes.js +86 -0
  75. package/dist/routes/filesystem.routes.js.map +1 -0
  76. package/dist/routes/insights.routes.d.ts +17 -0
  77. package/dist/routes/insights.routes.d.ts.map +1 -0
  78. package/dist/routes/insights.routes.js +633 -0
  79. package/dist/routes/insights.routes.js.map +1 -0
  80. package/dist/routes/lattice.routes.d.ts +10 -0
  81. package/dist/routes/lattice.routes.d.ts.map +1 -0
  82. package/dist/routes/lattice.routes.js +123 -0
  83. package/dist/routes/lattice.routes.js.map +1 -0
  84. package/dist/routes/license.routes.d.ts +3 -0
  85. package/dist/routes/license.routes.d.ts.map +1 -0
  86. package/dist/routes/license.routes.js +95 -0
  87. package/dist/routes/license.routes.js.map +1 -0
  88. package/dist/routes/log.routes.d.ts +3 -0
  89. package/dist/routes/log.routes.d.ts.map +1 -0
  90. package/dist/routes/log.routes.js +184 -0
  91. package/dist/routes/log.routes.js.map +1 -0
  92. package/dist/routes/pending-question.routes.d.ts +9 -0
  93. package/dist/routes/pending-question.routes.d.ts.map +1 -0
  94. package/dist/routes/pending-question.routes.js +162 -0
  95. package/dist/routes/pending-question.routes.js.map +1 -0
  96. package/dist/routes/permission.routes.d.ts +18 -0
  97. package/dist/routes/permission.routes.d.ts.map +1 -0
  98. package/dist/routes/permission.routes.js +370 -0
  99. package/dist/routes/permission.routes.js.map +1 -0
  100. package/dist/routes/process-events.routes.d.ts +9 -0
  101. package/dist/routes/process-events.routes.d.ts.map +1 -0
  102. package/dist/routes/process-events.routes.js +141 -0
  103. package/dist/routes/process-events.routes.js.map +1 -0
  104. package/dist/routes/prototype.routes.d.ts +9 -0
  105. package/dist/routes/prototype.routes.d.ts.map +1 -0
  106. package/dist/routes/prototype.routes.js +757 -0
  107. package/dist/routes/prototype.routes.js.map +1 -0
  108. package/dist/routes/question.routes.d.ts +8 -0
  109. package/dist/routes/question.routes.d.ts.map +1 -0
  110. package/dist/routes/question.routes.js +83 -0
  111. package/dist/routes/question.routes.js.map +1 -0
  112. package/dist/routes/session-control.routes.d.ts +29 -0
  113. package/dist/routes/session-control.routes.d.ts.map +1 -0
  114. package/dist/routes/session-control.routes.js +455 -0
  115. package/dist/routes/session-control.routes.js.map +1 -0
  116. package/dist/routes/session-lifecycle.routes.d.ts +21 -0
  117. package/dist/routes/session-lifecycle.routes.d.ts.map +1 -0
  118. package/dist/routes/session-lifecycle.routes.js +256 -0
  119. package/dist/routes/session-lifecycle.routes.js.map +1 -0
  120. package/dist/routes/session-query.routes.d.ts +25 -0
  121. package/dist/routes/session-query.routes.d.ts.map +1 -0
  122. package/dist/routes/session-query.routes.js +363 -0
  123. package/dist/routes/session-query.routes.js.map +1 -0
  124. package/dist/routes/session-stream.routes.d.ts +21 -0
  125. package/dist/routes/session-stream.routes.d.ts.map +1 -0
  126. package/dist/routes/session-stream.routes.js +235 -0
  127. package/dist/routes/session-stream.routes.js.map +1 -0
  128. package/dist/routes/streaming.routes.d.ts +4 -0
  129. package/dist/routes/streaming.routes.d.ts.map +1 -0
  130. package/dist/routes/streaming.routes.js +33 -0
  131. package/dist/routes/streaming.routes.js.map +1 -0
  132. package/dist/routes/system.routes.d.ts +7 -0
  133. package/dist/routes/system.routes.d.ts.map +1 -0
  134. package/dist/routes/system.routes.js +214 -0
  135. package/dist/routes/system.routes.js.map +1 -0
  136. package/dist/routes/walkthrough.routes.d.ts +19 -0
  137. package/dist/routes/walkthrough.routes.d.ts.map +1 -0
  138. package/dist/routes/walkthrough.routes.js +688 -0
  139. package/dist/routes/walkthrough.routes.js.map +1 -0
  140. package/dist/routes/working-directories.routes.d.ts +4 -0
  141. package/dist/routes/working-directories.routes.d.ts.map +1 -0
  142. package/dist/routes/working-directories.routes.js +25 -0
  143. package/dist/routes/working-directories.routes.js.map +1 -0
  144. package/dist/server.d.ts +3 -0
  145. package/dist/server.d.ts.map +1 -0
  146. package/dist/server.js +34 -0
  147. package/dist/server.js.map +1 -0
  148. package/dist/services/ToolMetricsService.d.ts +53 -0
  149. package/dist/services/ToolMetricsService.d.ts.map +1 -0
  150. package/dist/services/ToolMetricsService.js +230 -0
  151. package/dist/services/ToolMetricsService.js.map +1 -0
  152. package/dist/services/claude-router-service.d.ts +19 -0
  153. package/dist/services/claude-router-service.d.ts.map +1 -0
  154. package/dist/services/claude-router-service.js +160 -0
  155. package/dist/services/claude-router-service.js.map +1 -0
  156. package/dist/services/commands-service.d.ts +20 -0
  157. package/dist/services/commands-service.d.ts.map +1 -0
  158. package/dist/services/commands-service.js +115 -0
  159. package/dist/services/commands-service.js.map +1 -0
  160. package/dist/services/connection-debug-logger.d.ts +85 -0
  161. package/dist/services/connection-debug-logger.d.ts.map +1 -0
  162. package/dist/services/connection-debug-logger.js +221 -0
  163. package/dist/services/connection-debug-logger.js.map +1 -0
  164. package/dist/services/debug-log.d.ts +6 -0
  165. package/dist/services/debug-log.d.ts.map +1 -0
  166. package/dist/services/debug-log.js +27 -0
  167. package/dist/services/debug-log.js.map +1 -0
  168. package/dist/services/gemini-service.d.ts +35 -0
  169. package/dist/services/gemini-service.d.ts.map +1 -0
  170. package/dist/services/gemini-service.js +256 -0
  171. package/dist/services/gemini-service.js.map +1 -0
  172. package/dist/services/infrastructure/config-service.d.ts +79 -0
  173. package/dist/services/infrastructure/config-service.d.ts.map +1 -0
  174. package/dist/services/infrastructure/config-service.js +431 -0
  175. package/dist/services/infrastructure/config-service.js.map +1 -0
  176. package/dist/services/infrastructure/cost-tracker.d.ts +112 -0
  177. package/dist/services/infrastructure/cost-tracker.d.ts.map +1 -0
  178. package/dist/services/infrastructure/cost-tracker.js +423 -0
  179. package/dist/services/infrastructure/cost-tracker.js.map +1 -0
  180. package/dist/services/infrastructure/file-system-service.d.ts +61 -0
  181. package/dist/services/infrastructure/file-system-service.d.ts.map +1 -0
  182. package/dist/services/infrastructure/file-system-service.js +348 -0
  183. package/dist/services/infrastructure/file-system-service.js.map +1 -0
  184. package/dist/services/infrastructure/log-formatter.d.ts +5 -0
  185. package/dist/services/infrastructure/log-formatter.d.ts.map +1 -0
  186. package/dist/services/infrastructure/log-formatter.js +77 -0
  187. package/dist/services/infrastructure/log-formatter.js.map +1 -0
  188. package/dist/services/infrastructure/log-stream-buffer.d.ts +11 -0
  189. package/dist/services/infrastructure/log-stream-buffer.d.ts.map +1 -0
  190. package/dist/services/infrastructure/log-stream-buffer.js +36 -0
  191. package/dist/services/infrastructure/log-stream-buffer.js.map +1 -0
  192. package/dist/services/infrastructure/logger.d.ts +71 -0
  193. package/dist/services/infrastructure/logger.d.ts.map +1 -0
  194. package/dist/services/infrastructure/logger.js +215 -0
  195. package/dist/services/infrastructure/logger.js.map +1 -0
  196. package/dist/services/infrastructure/service-registry.d.ts +86 -0
  197. package/dist/services/infrastructure/service-registry.d.ts.map +1 -0
  198. package/dist/services/infrastructure/service-registry.js +162 -0
  199. package/dist/services/infrastructure/service-registry.js.map +1 -0
  200. package/dist/services/infrastructure/stream-manager.d.ts +87 -0
  201. package/dist/services/infrastructure/stream-manager.d.ts.map +1 -0
  202. package/dist/services/infrastructure/stream-manager.js +436 -0
  203. package/dist/services/infrastructure/stream-manager.js.map +1 -0
  204. package/dist/services/infrastructure/timing.d.ts +72 -0
  205. package/dist/services/infrastructure/timing.d.ts.map +1 -0
  206. package/dist/services/infrastructure/timing.js +115 -0
  207. package/dist/services/infrastructure/timing.js.map +1 -0
  208. package/dist/services/insights/anthropic-service.d.ts +224 -0
  209. package/dist/services/insights/anthropic-service.d.ts.map +1 -0
  210. package/dist/services/insights/anthropic-service.js +1062 -0
  211. package/dist/services/insights/anthropic-service.js.map +1 -0
  212. package/dist/services/insights/insight-audit-repository.d.ts +119 -0
  213. package/dist/services/insights/insight-audit-repository.d.ts.map +1 -0
  214. package/dist/services/insights/insight-audit-repository.js +242 -0
  215. package/dist/services/insights/insight-audit-repository.js.map +1 -0
  216. package/dist/services/insights/insight-queue.d.ts +99 -0
  217. package/dist/services/insights/insight-queue.d.ts.map +1 -0
  218. package/dist/services/insights/insight-queue.js +277 -0
  219. package/dist/services/insights/insight-queue.js.map +1 -0
  220. package/dist/services/insights/insights-computer.d.ts +132 -0
  221. package/dist/services/insights/insights-computer.d.ts.map +1 -0
  222. package/dist/services/insights/insights-computer.js +936 -0
  223. package/dist/services/insights/insights-computer.js.map +1 -0
  224. package/dist/services/insights/insights-coordinator.d.ts +165 -0
  225. package/dist/services/insights/insights-coordinator.d.ts.map +1 -0
  226. package/dist/services/insights/insights-coordinator.js +1678 -0
  227. package/dist/services/insights/insights-coordinator.js.map +1 -0
  228. package/dist/services/insights/insights-event-log.d.ts +196 -0
  229. package/dist/services/insights/insights-event-log.d.ts.map +1 -0
  230. package/dist/services/insights/insights-event-log.js +319 -0
  231. package/dist/services/insights/insights-event-log.js.map +1 -0
  232. package/dist/services/lattice-service.d.ts +77 -0
  233. package/dist/services/lattice-service.d.ts.map +1 -0
  234. package/dist/services/lattice-service.js +195 -0
  235. package/dist/services/lattice-service.js.map +1 -0
  236. package/dist/services/license-service.d.ts +69 -0
  237. package/dist/services/license-service.d.ts.map +1 -0
  238. package/dist/services/license-service.js +330 -0
  239. package/dist/services/license-service.js.map +1 -0
  240. package/dist/services/mcp-config-generator.d.ts +32 -0
  241. package/dist/services/mcp-config-generator.d.ts.map +1 -0
  242. package/dist/services/mcp-config-generator.js +126 -0
  243. package/dist/services/mcp-config-generator.js.map +1 -0
  244. package/dist/services/message-filter.d.ts +22 -0
  245. package/dist/services/message-filter.d.ts.map +1 -0
  246. package/dist/services/message-filter.js +57 -0
  247. package/dist/services/message-filter.js.map +1 -0
  248. package/dist/services/notification-service.d.ts +45 -0
  249. package/dist/services/notification-service.d.ts.map +1 -0
  250. package/dist/services/notification-service.js +184 -0
  251. package/dist/services/notification-service.js.map +1 -0
  252. package/dist/services/pending-question-service.d.ts +97 -0
  253. package/dist/services/pending-question-service.d.ts.map +1 -0
  254. package/dist/services/pending-question-service.js +223 -0
  255. package/dist/services/pending-question-service.js.map +1 -0
  256. package/dist/services/permission-event-log.d.ts +136 -0
  257. package/dist/services/permission-event-log.d.ts.map +1 -0
  258. package/dist/services/permission-event-log.js +252 -0
  259. package/dist/services/permission-event-log.js.map +1 -0
  260. package/dist/services/permission-pattern-matcher.d.ts +82 -0
  261. package/dist/services/permission-pattern-matcher.d.ts.map +1 -0
  262. package/dist/services/permission-pattern-matcher.js +294 -0
  263. package/dist/services/permission-pattern-matcher.js.map +1 -0
  264. package/dist/services/permission-tracker.d.ts +67 -0
  265. package/dist/services/permission-tracker.d.ts.map +1 -0
  266. package/dist/services/permission-tracker.js +162 -0
  267. package/dist/services/permission-tracker.js.map +1 -0
  268. package/dist/services/process/claude-process-manager.d.ts +142 -0
  269. package/dist/services/process/claude-process-manager.d.ts.map +1 -0
  270. package/dist/services/process/claude-process-manager.js +1218 -0
  271. package/dist/services/process/claude-process-manager.js.map +1 -0
  272. package/dist/services/process/conversation-status-manager.d.ts +110 -0
  273. package/dist/services/process/conversation-status-manager.d.ts.map +1 -0
  274. package/dist/services/process/conversation-status-manager.js +349 -0
  275. package/dist/services/process/conversation-status-manager.js.map +1 -0
  276. package/dist/services/process/json-lines-parser.d.ts +19 -0
  277. package/dist/services/process/json-lines-parser.d.ts.map +1 -0
  278. package/dist/services/process/json-lines-parser.js +59 -0
  279. package/dist/services/process/json-lines-parser.js.map +1 -0
  280. package/dist/services/process/process-event-log.d.ts +263 -0
  281. package/dist/services/process/process-event-log.d.ts.map +1 -0
  282. package/dist/services/process/process-event-log.js +509 -0
  283. package/dist/services/process/process-event-log.js.map +1 -0
  284. package/dist/services/process/process-manager-factory.d.ts +109 -0
  285. package/dist/services/process/process-manager-factory.d.ts.map +1 -0
  286. package/dist/services/process/process-manager-factory.js +338 -0
  287. package/dist/services/process/process-manager-factory.js.map +1 -0
  288. package/dist/services/question-tracker.d.ts +51 -0
  289. package/dist/services/question-tracker.d.ts.map +1 -0
  290. package/dist/services/question-tracker.js +111 -0
  291. package/dist/services/question-tracker.js.map +1 -0
  292. package/dist/services/sessions/claude-history-reader.d.ts +139 -0
  293. package/dist/services/sessions/claude-history-reader.d.ts.map +1 -0
  294. package/dist/services/sessions/claude-history-reader.js +864 -0
  295. package/dist/services/sessions/claude-history-reader.js.map +1 -0
  296. package/dist/services/sessions/conversation-cache.d.ts +98 -0
  297. package/dist/services/sessions/conversation-cache.d.ts.map +1 -0
  298. package/dist/services/sessions/conversation-cache.js +329 -0
  299. package/dist/services/sessions/conversation-cache.js.map +1 -0
  300. package/dist/services/sessions/session-activity-watcher.d.ts +67 -0
  301. package/dist/services/sessions/session-activity-watcher.d.ts.map +1 -0
  302. package/dist/services/sessions/session-activity-watcher.js +236 -0
  303. package/dist/services/sessions/session-activity-watcher.js.map +1 -0
  304. package/dist/services/sessions/session-analysis-service.d.ts +72 -0
  305. package/dist/services/sessions/session-analysis-service.d.ts.map +1 -0
  306. package/dist/services/sessions/session-analysis-service.js +373 -0
  307. package/dist/services/sessions/session-analysis-service.js.map +1 -0
  308. package/dist/services/sessions/session-branch-service.d.ts +76 -0
  309. package/dist/services/sessions/session-branch-service.d.ts.map +1 -0
  310. package/dist/services/sessions/session-branch-service.js +355 -0
  311. package/dist/services/sessions/session-branch-service.js.map +1 -0
  312. package/dist/services/sessions/session-info-service.d.ts +455 -0
  313. package/dist/services/sessions/session-info-service.d.ts.map +1 -0
  314. package/dist/services/sessions/session-info-service.js +1640 -0
  315. package/dist/services/sessions/session-info-service.js.map +1 -0
  316. package/dist/services/sessions/session-marks-repository.d.ts +78 -0
  317. package/dist/services/sessions/session-marks-repository.d.ts.map +1 -0
  318. package/dist/services/sessions/session-marks-repository.js +263 -0
  319. package/dist/services/sessions/session-marks-repository.js.map +1 -0
  320. package/dist/services/sessions/session-marks-service.d.ts +137 -0
  321. package/dist/services/sessions/session-marks-service.d.ts.map +1 -0
  322. package/dist/services/sessions/session-marks-service.js +562 -0
  323. package/dist/services/sessions/session-marks-service.js.map +1 -0
  324. package/dist/services/sessions/session-review-service.d.ts +98 -0
  325. package/dist/services/sessions/session-review-service.d.ts.map +1 -0
  326. package/dist/services/sessions/session-review-service.js +629 -0
  327. package/dist/services/sessions/session-review-service.js.map +1 -0
  328. package/dist/services/sessions/turn-capture-service.d.ts +83 -0
  329. package/dist/services/sessions/turn-capture-service.d.ts.map +1 -0
  330. package/dist/services/sessions/turn-capture-service.js +477 -0
  331. package/dist/services/sessions/turn-capture-service.js.map +1 -0
  332. package/dist/services/sessions/turn-repository.d.ts +48 -0
  333. package/dist/services/sessions/turn-repository.d.ts.map +1 -0
  334. package/dist/services/sessions/turn-repository.js +103 -0
  335. package/dist/services/sessions/turn-repository.js.map +1 -0
  336. package/dist/services/walkthrough-service.d.ts +226 -0
  337. package/dist/services/walkthrough-service.d.ts.map +1 -0
  338. package/dist/services/walkthrough-service.js +1112 -0
  339. package/dist/services/walkthrough-service.js.map +1 -0
  340. package/dist/services/walkthrough-skill-prompt.d.ts +34 -0
  341. package/dist/services/walkthrough-skill-prompt.d.ts.map +1 -0
  342. package/dist/services/walkthrough-skill-prompt.js +313 -0
  343. package/dist/services/walkthrough-skill-prompt.js.map +1 -0
  344. package/dist/services/web-push-service.d.ts +48 -0
  345. package/dist/services/web-push-service.d.ts.map +1 -0
  346. package/dist/services/web-push-service.js +186 -0
  347. package/dist/services/web-push-service.js.map +1 -0
  348. package/dist/services/working-directories-service.d.ts +19 -0
  349. package/dist/services/working-directories-service.d.ts.map +1 -0
  350. package/dist/services/working-directories-service.js +103 -0
  351. package/dist/services/working-directories-service.js.map +1 -0
  352. package/dist/types/config.d.ts +122 -0
  353. package/dist/types/config.d.ts.map +1 -0
  354. package/dist/types/config.js +21 -0
  355. package/dist/types/config.js.map +1 -0
  356. package/dist/types/express.d.ts +5 -0
  357. package/dist/types/express.d.ts.map +1 -0
  358. package/dist/types/express.js +2 -0
  359. package/dist/types/express.js.map +1 -0
  360. package/dist/types/index.d.ts +400 -0
  361. package/dist/types/index.d.ts.map +1 -0
  362. package/dist/types/index.js +41 -0
  363. package/dist/types/index.js.map +1 -0
  364. package/dist/types/insights.d.ts +176 -0
  365. package/dist/types/insights.d.ts.map +1 -0
  366. package/dist/types/insights.js +23 -0
  367. package/dist/types/insights.js.map +1 -0
  368. package/dist/types/license.d.ts +70 -0
  369. package/dist/types/license.d.ts.map +1 -0
  370. package/dist/types/license.js +5 -0
  371. package/dist/types/license.js.map +1 -0
  372. package/dist/types/router-config.d.ts +13 -0
  373. package/dist/types/router-config.d.ts.map +1 -0
  374. package/dist/types/router-config.js +2 -0
  375. package/dist/types/router-config.js.map +1 -0
  376. package/dist/utils/constants.d.ts +26 -0
  377. package/dist/utils/constants.d.ts.map +1 -0
  378. package/dist/utils/constants.js +28 -0
  379. package/dist/utils/constants.js.map +1 -0
  380. package/dist/utils/machine-id.d.ts +7 -0
  381. package/dist/utils/machine-id.d.ts.map +1 -0
  382. package/dist/utils/machine-id.js +76 -0
  383. package/dist/utils/machine-id.js.map +1 -0
  384. package/dist/utils/server-startup.d.ts +11 -0
  385. package/dist/utils/server-startup.d.ts.map +1 -0
  386. package/dist/utils/server-startup.js +9 -0
  387. package/dist/utils/server-startup.js.map +1 -0
  388. package/dist/utils/update-check.d.ts +13 -0
  389. package/dist/utils/update-check.d.ts.map +1 -0
  390. package/dist/utils/update-check.js +90 -0
  391. package/dist/utils/update-check.js.map +1 -0
  392. package/dist/web/assets/ArchivedCardPrototype-S9ifiasa.js +5 -0
  393. package/dist/web/assets/BannerGallery-B__rJV6F.js +1 -0
  394. package/dist/web/assets/BannerPrototype-DBKP9Uiu.js +52 -0
  395. package/dist/web/assets/CodeHikeExperiment-B8jjWAFy.js +15 -0
  396. package/dist/web/assets/ContextTooltipVariations-DzklAFam.js +1 -0
  397. package/dist/web/assets/FontShowcasePrototype-KIMEWeP2.js +13 -0
  398. package/dist/web/assets/GeometricGallery-DddlWhHK.js +1 -0
  399. package/dist/web/assets/HistoryWalkthroughPrototype-DeniRRdw.js +18 -0
  400. package/dist/web/assets/InlineWalkthroughPrototype-Csd5r_Hk.js +1 -0
  401. package/dist/web/assets/MarkButtonPrototype-CxhxE0RP.js +1 -0
  402. package/dist/web/assets/MenuStylesPrototype-D7neA6YM.js +1 -0
  403. package/dist/web/assets/MomentCardVariations-2GT7GyFn.js +1 -0
  404. package/dist/web/assets/MomentHeaderVariations-DhGEw4XC.js +1 -0
  405. package/dist/web/assets/NarrativeWalkthroughDemo-B5C566fu.js +389 -0
  406. package/dist/web/assets/OutcomeVariations-BrZfsVcs.js +1 -0
  407. package/dist/web/assets/PermissionPatternPickerPrototype-CBOhe2Me.js +1 -0
  408. package/dist/web/assets/PermissionPrototype-BcF-a5an.js +1 -0
  409. package/dist/web/assets/PipelineGallery-BJhyM0rx.js +1 -0
  410. package/dist/web/assets/ScopeHeaderPrototype-GD1HNfaO.js +1 -0
  411. package/dist/web/assets/ScopeHeaderStylesPrototype-aa4uNJJ1.js +1 -0
  412. package/dist/web/assets/ScrollycodingPrototype-CKW1bf72.js +70 -0
  413. package/dist/web/assets/SectionHeaderVariations-DM8vUwfj.js +1 -0
  414. package/dist/web/assets/SemanticGallery-CtQEo7St.js +1 -0
  415. package/dist/web/assets/SessionCardPrototype-CgHCIMHe.js +1 -0
  416. package/dist/web/assets/SessionSidebarVariations-DMQL3Azj.js +3 -0
  417. package/dist/web/assets/SessionStartPrototype-Cwsv01Rr.js +1 -0
  418. package/dist/web/assets/SmartMenuPrototype-Br37Qbs_.js +1 -0
  419. package/dist/web/assets/StyleGallery-rZgrploB.js +1 -0
  420. package/dist/web/assets/TimelineCardPrototype-lzPc5mhe.js +19 -0
  421. package/dist/web/assets/ToolbarPrototype-Dm4BNZra.js +1 -0
  422. package/dist/web/assets/TooltipExperiment-Dy8QzTIP.js +13 -0
  423. package/dist/web/assets/WalkthroughCTAPrototype-uHoovujd.js +1 -0
  424. package/dist/web/assets/WalkthroughHeaderVariations-Do7Di1g1.js +1 -0
  425. package/dist/web/assets/WalkthroughShowcase-sGmRoPoM.js +112 -0
  426. package/dist/web/assets/arrow-right-D46Nx1mC.js +1 -0
  427. package/dist/web/assets/brain-BXIZKtOZ.js +1 -0
  428. package/dist/web/assets/grid-3x3-Cb81B62m.js +1 -0
  429. package/dist/web/assets/main-B1fyog77.js +321 -0
  430. package/dist/web/assets/main-C2PK2Klg.css +1 -0
  431. package/dist/web/assets/semantic-variations-Bd-W7ea2.js +1 -0
  432. package/dist/web/assets/target-Cf92wDTW.js +1 -0
  433. package/dist/web/favicon.png +0 -0
  434. package/dist/web/favicon.svg +22 -0
  435. package/dist/web/icon-192x192.png +0 -0
  436. package/dist/web/icon-512x512.png +0 -0
  437. package/dist/web/index.html +45 -0
  438. package/dist/web/manifest.json +61 -0
  439. package/package.json +192 -0
  440. package/scripts/postinstall.js +60 -0
@@ -0,0 +1,846 @@
1
+ /**
2
+ * Process Daemon - Long-running process that owns Claude CLI PTY processes
3
+ *
4
+ * This daemon runs independently of the web server and survives nodemon restarts.
5
+ * It communicates with cui-server via Unix socket IPC.
6
+ */
7
+ import * as pty from 'node-pty';
8
+ import * as net from 'net';
9
+ import * as fs from 'fs';
10
+ import { spawn } from 'child_process';
11
+ import { EventEmitter } from 'events';
12
+ import { v4 as uuidv4 } from 'uuid';
13
+ import path from 'path';
14
+ import os from 'os';
15
+ import { existsSync } from 'fs';
16
+ import { fileURLToPath } from 'url';
17
+ // ESM equivalent of __dirname
18
+ const __filename = fileURLToPath(import.meta.url);
19
+ const __dirname = path.dirname(__filename);
20
+ import { JsonLinesParser } from '../services/process/json-lines-parser.js';
21
+ import { LatticeError } from '../types/index.js';
22
+ import { DEFAULT_SOCKET_PATH, } from './types.js';
23
+ /**
24
+ * Expand tilde (~) in paths to the user's home directory.
25
+ */
26
+ function expandTilde(filePath) {
27
+ if (filePath === '~' || filePath.startsWith('~/')) {
28
+ return path.join(os.homedir(), filePath.slice(1));
29
+ }
30
+ return filePath;
31
+ }
32
+ /**
33
+ * Simple console logger for daemon (avoids importing pino for standalone operation)
34
+ */
35
+ const timestamp = () => new Date().toISOString();
36
+ const logger = {
37
+ info: (msg, data) => {
38
+ console.warn(`[${timestamp()}] [DAEMON] ${msg}`, data ? JSON.stringify(data) : '');
39
+ },
40
+ debug: (msg, data) => {
41
+ if (process.env.LOG_LEVEL === 'debug') {
42
+ console.warn(`[${timestamp()}] [DAEMON:DEBUG] ${msg}`, data ? JSON.stringify(data) : '');
43
+ }
44
+ },
45
+ warn: (msg, data) => {
46
+ console.warn(`[${timestamp()}] [DAEMON:WARN] ${msg}`, data ? JSON.stringify(data) : '');
47
+ },
48
+ error: (msg, error, data) => {
49
+ console.error(`[${timestamp()}] [DAEMON:ERROR] ${msg}`, error, data ? JSON.stringify(data) : '');
50
+ },
51
+ };
52
+ /**
53
+ * Process Daemon - owns and manages Claude CLI PTY processes
54
+ */
55
+ export class ProcessDaemon extends EventEmitter {
56
+ processes = new Map();
57
+ outputBuffers = new Map();
58
+ timeouts = new Map();
59
+ conversationConfigs = new Map();
60
+ sessionIds = new Map(); // streamingId -> claude session_id
61
+ killedProcesses = new Set();
62
+ ipcServer = null;
63
+ connectedClients = new Set();
64
+ socketPath;
65
+ claudeExecutablePath;
66
+ envOverrides;
67
+ // Pending system init resolvers (streamingId -> {resolve, reject})
68
+ pendingSystemInits = new Map();
69
+ constructor(config = { socketPath: DEFAULT_SOCKET_PATH }) {
70
+ super();
71
+ this.socketPath = config.socketPath;
72
+ this.claudeExecutablePath = config.claudeExecutablePath || this.findClaudeExecutable();
73
+ this.envOverrides = config.envOverrides || {};
74
+ }
75
+ /**
76
+ * Find the Claude executable
77
+ */
78
+ findClaudeExecutable() {
79
+ // Check common installation paths including user-local installs
80
+ const userLocalPath = path.join(os.homedir(), '.local', 'bin', 'claude');
81
+ const candidatePaths = [
82
+ userLocalPath, // ~/.local/bin/claude (common for user installs)
83
+ '/usr/local/bin/claude',
84
+ '/usr/bin/claude',
85
+ ];
86
+ for (const candidate of candidatePaths) {
87
+ if (existsSync(candidate)) {
88
+ return candidate;
89
+ }
90
+ }
91
+ const pathEnv = process.env.PATH || '';
92
+ const pathDirs = pathEnv.split(path.delimiter);
93
+ for (const dir of pathDirs) {
94
+ if (dir.includes('node_modules'))
95
+ continue;
96
+ const candidate = path.join(dir, 'claude');
97
+ if (existsSync(candidate)) {
98
+ return candidate;
99
+ }
100
+ }
101
+ throw new Error('Claude CLI not found.\n\n' +
102
+ 'Claudia Orchestrator requires Claude Code CLI to be installed.\n' +
103
+ 'Install it with: npm install -g @anthropic-ai/claude-code\n' +
104
+ 'Then authenticate with: claude\n\n' +
105
+ 'More info: https://docs.anthropic.com/en/docs/claude-code');
106
+ }
107
+ /**
108
+ * Check if another daemon is already running by attempting to connect to the socket.
109
+ * Returns true if a daemon is actively listening, false if socket is stale or missing.
110
+ */
111
+ async isExistingDaemonRunning() {
112
+ if (!fs.existsSync(this.socketPath)) {
113
+ return false;
114
+ }
115
+ return new Promise((resolve) => {
116
+ const testSocket = new net.Socket();
117
+ const timeout = setTimeout(() => {
118
+ testSocket.destroy();
119
+ resolve(false); // Timeout = no daemon responding
120
+ }, 1000);
121
+ testSocket.on('connect', () => {
122
+ clearTimeout(timeout);
123
+ testSocket.destroy();
124
+ resolve(true); // Connected = daemon is running
125
+ });
126
+ testSocket.on('error', () => {
127
+ clearTimeout(timeout);
128
+ testSocket.destroy();
129
+ resolve(false); // Error = socket is stale
130
+ });
131
+ testSocket.connect(this.socketPath);
132
+ });
133
+ }
134
+ /**
135
+ * Start the IPC server
136
+ */
137
+ async start() {
138
+ // Check if another daemon is already running
139
+ const existingDaemon = await this.isExistingDaemonRunning();
140
+ if (existingDaemon) {
141
+ logger.warn('Another daemon is already running on this socket', { socketPath: this.socketPath });
142
+ throw new Error(`Another daemon is already listening on ${this.socketPath}. Kill the existing daemon first or use a different socket path.`);
143
+ }
144
+ // Clean up stale socket file (we know no daemon is listening now)
145
+ if (fs.existsSync(this.socketPath)) {
146
+ logger.info('Removing stale socket file', { path: this.socketPath });
147
+ fs.unlinkSync(this.socketPath);
148
+ }
149
+ return new Promise((resolve, reject) => {
150
+ this.ipcServer = net.createServer((socket) => {
151
+ this.handleClientConnection(socket);
152
+ });
153
+ this.ipcServer.on('error', (err) => {
154
+ logger.error('IPC server error', err);
155
+ reject(err);
156
+ });
157
+ this.ipcServer.listen(this.socketPath, () => {
158
+ // Set socket permissions so any local user can connect
159
+ fs.chmodSync(this.socketPath, 0o777);
160
+ logger.info('Process daemon started', {
161
+ socketPath: this.socketPath,
162
+ claudePath: this.claudeExecutablePath,
163
+ });
164
+ resolve();
165
+ });
166
+ });
167
+ }
168
+ /**
169
+ * Stop the daemon gracefully
170
+ */
171
+ async stop() {
172
+ logger.info('Stopping process daemon...');
173
+ // Stop all active processes
174
+ const sessions = Array.from(this.processes.keys());
175
+ for (const streamingId of sessions) {
176
+ await this.stopConversation(streamingId);
177
+ }
178
+ // Close all client connections
179
+ for (const client of this.connectedClients) {
180
+ client.destroy();
181
+ }
182
+ this.connectedClients.clear();
183
+ // Close IPC server
184
+ if (this.ipcServer) {
185
+ await new Promise((resolve) => {
186
+ this.ipcServer.close(() => {
187
+ logger.info('IPC server closed');
188
+ resolve();
189
+ });
190
+ });
191
+ }
192
+ // Clean up socket file
193
+ if (fs.existsSync(this.socketPath)) {
194
+ fs.unlinkSync(this.socketPath);
195
+ }
196
+ logger.info('Process daemon stopped');
197
+ }
198
+ /**
199
+ * Handle a new client connection
200
+ */
201
+ handleClientConnection(socket) {
202
+ logger.info('Client connected');
203
+ this.connectedClients.add(socket);
204
+ let buffer = '';
205
+ socket.on('data', (data) => {
206
+ buffer += data.toString();
207
+ // Parse newline-delimited JSON messages
208
+ const lines = buffer.split('\n');
209
+ buffer = lines.pop() || '';
210
+ for (const line of lines) {
211
+ if (line.trim()) {
212
+ try {
213
+ const request = JSON.parse(line);
214
+ this.handleRequest(socket, request);
215
+ }
216
+ catch (err) {
217
+ logger.error('Failed to parse IPC message', err, { line });
218
+ }
219
+ }
220
+ }
221
+ });
222
+ socket.on('close', () => {
223
+ logger.info('Client disconnected');
224
+ this.connectedClients.delete(socket);
225
+ });
226
+ socket.on('error', (err) => {
227
+ logger.error('Client socket error', err);
228
+ this.connectedClients.delete(socket);
229
+ });
230
+ }
231
+ /**
232
+ * Handle an IPC request
233
+ */
234
+ async handleRequest(socket, request) {
235
+ logger.debug('Received request', { method: request.method, id: request.id });
236
+ try {
237
+ let result;
238
+ switch (request.method) {
239
+ case 'spawn':
240
+ result = await this.handleSpawn(request.params);
241
+ break;
242
+ case 'stop':
243
+ result = await this.handleStop(request.params);
244
+ break;
245
+ case 'forceKill':
246
+ result = this.handleForceKill(request.params);
247
+ break;
248
+ case 'interrupt':
249
+ result = this.handleInterrupt(request.params);
250
+ break;
251
+ case 'write':
252
+ result = this.handleWrite(request.params);
253
+ break;
254
+ case 'sendQuestionAnswer':
255
+ result = this.handleSendQuestionAnswer(request.params);
256
+ break;
257
+ case 'list':
258
+ result = { sessions: this.getActiveSessions() };
259
+ break;
260
+ case 'isActive':
261
+ result = { active: this.isSessionActive(request.params.streamingId) };
262
+ break;
263
+ default:
264
+ throw new Error(`Unknown method: ${request.method}`);
265
+ }
266
+ this.sendResponse(socket, { id: request.id, result });
267
+ }
268
+ catch (error) {
269
+ const err = error instanceof Error ? error : new Error(String(error));
270
+ this.sendResponse(socket, {
271
+ id: request.id,
272
+ error: {
273
+ code: error instanceof LatticeError ? error.code : 'INTERNAL_ERROR',
274
+ message: err.message,
275
+ },
276
+ });
277
+ }
278
+ }
279
+ /**
280
+ * Send a response to a specific client
281
+ */
282
+ sendResponse(socket, response) {
283
+ socket.write(JSON.stringify(response) + '\n');
284
+ }
285
+ /**
286
+ * Broadcast an event to all connected clients
287
+ */
288
+ broadcastEvent(event) {
289
+ const message = JSON.stringify(event) + '\n';
290
+ for (const client of this.connectedClients) {
291
+ try {
292
+ client.write(message);
293
+ }
294
+ catch (err) {
295
+ logger.error('Failed to broadcast to client', err);
296
+ }
297
+ }
298
+ }
299
+ // ============================================================================
300
+ // Process Management (extracted from ClaudeProcessManager)
301
+ // ============================================================================
302
+ async handleSpawn(params) {
303
+ const { config } = params;
304
+ const isResume = !!config.resumedSessionId;
305
+ const streamingId = uuidv4();
306
+ const spawnStartTime = Date.now();
307
+ logger.info('Spawning conversation', { streamingId, isResume });
308
+ // Store config
309
+ this.conversationConfigs.set(streamingId, config);
310
+ try {
311
+ const hasMultimodalContent = !!(config.initialContent && config.initialContent.length > 0);
312
+ // For multimodal, don't pass message as CLI arg - we'll send via stdin
313
+ const args = isResume && config.resumedSessionId
314
+ ? this.buildResumeArgs({ sessionId: config.resumedSessionId, message: config.initialPrompt, permissionMode: config.permissionMode, streamingId, hasMultimodalContent })
315
+ : this.buildStartArgs(config, streamingId);
316
+ const cwd = expandTilde(config.workingDirectory || process.cwd());
317
+ logger.info('Spawn cwd', { streamingId, configWorkingDirectory: config.workingDirectory, resolvedCwd: cwd, processCwd: process.cwd() });
318
+ // Clean environment - destructure to remove unwanted vars
319
+ const { NODE_OPTIONS: _NO, VSCODE_INSPECTOR_OPTIONS: _VIO, CLAUDECODE: _CC, CLAUDE_CODE_ENTRYPOINT: _CCE, ...cleanEnv } = process.env;
320
+ const env = {
321
+ ...cleanEnv,
322
+ ...this.envOverrides,
323
+ CUI_STREAMING_ID: streamingId,
324
+ PWD: cwd,
325
+ INIT_CWD: cwd,
326
+ };
327
+ let managedProcess;
328
+ if (hasMultimodalContent) {
329
+ // Use piped spawn for multimodal - stdin will be a pipe, not a TTY
330
+ // This allows CLI to block waiting for stdin input
331
+ logger.info('Using piped spawn for multimodal content', { streamingId });
332
+ const childProcess = spawn(this.claudeExecutablePath, args, {
333
+ cwd,
334
+ env: env,
335
+ stdio: ['pipe', 'pipe', 'pipe'],
336
+ });
337
+ if (!childProcess.pid) {
338
+ throw new LatticeError('PROCESS_SPAWN_FAILED', 'Failed to spawn Claude process - no PID assigned', 500);
339
+ }
340
+ managedProcess = {
341
+ type: 'pipe',
342
+ child: childProcess,
343
+ pid: childProcess.pid,
344
+ write: (data) => childProcess.stdin?.write(data),
345
+ kill: (signal) => childProcess.kill(signal),
346
+ endStdin: () => childProcess.stdin?.end(),
347
+ };
348
+ this.processes.set(streamingId, managedProcess);
349
+ this.setupPipedProcessHandlers(streamingId, childProcess);
350
+ }
351
+ else {
352
+ // Use PTY for regular text - provides better terminal experience
353
+ const ptyProcess = pty.spawn(this.claudeExecutablePath, args, {
354
+ name: 'xterm-256color',
355
+ cols: 200,
356
+ rows: 50,
357
+ cwd,
358
+ env: env,
359
+ });
360
+ if (!ptyProcess.pid) {
361
+ throw new LatticeError('PROCESS_SPAWN_FAILED', 'Failed to spawn Claude process - no PID assigned', 500);
362
+ }
363
+ managedProcess = {
364
+ type: 'pty',
365
+ pty: ptyProcess,
366
+ pid: ptyProcess.pid,
367
+ write: (data) => ptyProcess.write(data),
368
+ kill: (signal) => ptyProcess.kill(signal),
369
+ };
370
+ this.processes.set(streamingId, managedProcess);
371
+ this.setupPtyProcessHandlers(streamingId, ptyProcess);
372
+ }
373
+ // Broadcast process-spawned event so clients can start buffering
374
+ this.broadcastEvent({
375
+ event: 'process-spawned',
376
+ data: { streamingId },
377
+ });
378
+ const spawnMs = Date.now() - spawnStartTime;
379
+ logger.info('Process spawned', { streamingId, pid: managedProcess.pid, spawnMs, type: managedProcess.type });
380
+ // For multimodal, send stdin message BEFORE waiting for init
381
+ // The CLI will process this and emit system init
382
+ if (hasMultimodalContent && config.initialContent) {
383
+ const contentBlocks = [
384
+ ...config.initialContent,
385
+ ...(config.initialPrompt ? [{ type: 'text', text: config.initialPrompt }] : [])
386
+ ];
387
+ const stdinMessage = JSON.stringify({
388
+ type: 'user',
389
+ message: {
390
+ role: 'user',
391
+ content: contentBlocks
392
+ },
393
+ session_id: config.resumedSessionId || ''
394
+ });
395
+ logger.info('Sending multimodal content via stdin', {
396
+ streamingId,
397
+ contentBlockCount: contentBlocks.length,
398
+ messageLength: stdinMessage.length
399
+ });
400
+ managedProcess.write(stdinMessage + '\n');
401
+ // Close stdin to signal end of input - CLI will process and exit
402
+ managedProcess.endStdin?.();
403
+ }
404
+ // Wait for system init message
405
+ const systemInit = await this.waitForSystemInit(streamingId);
406
+ const totalSpawnMs = Date.now() - spawnStartTime;
407
+ logger.info('System init received', { streamingId, totalSpawnMs, waitForInitMs: totalSpawnMs - spawnMs });
408
+ // Store session ID mapping
409
+ this.sessionIds.set(streamingId, systemInit.session_id);
410
+ return { streamingId, systemInit };
411
+ }
412
+ catch (error) {
413
+ // Cleanup on failure
414
+ this.cleanup(streamingId);
415
+ throw error;
416
+ }
417
+ }
418
+ async handleStop(params) {
419
+ const success = await this.stopConversation(params.streamingId);
420
+ return { success };
421
+ }
422
+ handleForceKill(params) {
423
+ const success = this.forceKillConversation(params.streamingId);
424
+ return { success };
425
+ }
426
+ handleInterrupt(params) {
427
+ const success = this.interruptConversation(params.streamingId);
428
+ return { success };
429
+ }
430
+ handleWrite(params) {
431
+ const process = this.processes.get(params.streamingId);
432
+ if (!process) {
433
+ logger.warn('handleWrite: process not found', { streamingId: params.streamingId });
434
+ return { success: false };
435
+ }
436
+ logger.info('handleWrite: writing to PTY', {
437
+ streamingId: params.streamingId,
438
+ messageLength: params.message.length,
439
+ messagePreview: params.message.slice(0, 100)
440
+ });
441
+ process.write(params.message + '\n');
442
+ return { success: true };
443
+ }
444
+ handleSendQuestionAnswer(params) {
445
+ const process = this.processes.get(params.streamingId);
446
+ const sessionId = this.sessionIds.get(params.streamingId);
447
+ if (!process || !sessionId) {
448
+ return { success: false };
449
+ }
450
+ // Build the tool result content per SDK docs:
451
+ // { questions: [...], answers: { "Question text?": "Selected label" } }
452
+ const toolResultContent = JSON.stringify({
453
+ questions: params.questions,
454
+ answers: params.answers
455
+ });
456
+ // Format as a tool_result message per Claude CLI stream-json protocol
457
+ const stdinMessage = JSON.stringify({
458
+ type: 'user',
459
+ message: {
460
+ role: 'user',
461
+ content: [{
462
+ type: 'tool_result',
463
+ tool_use_id: params.toolUseId,
464
+ content: toolResultContent
465
+ }]
466
+ },
467
+ session_id: sessionId,
468
+ });
469
+ process.write(stdinMessage + '\n');
470
+ return { success: true };
471
+ }
472
+ async stopConversation(streamingId) {
473
+ const process = this.processes.get(streamingId);
474
+ if (!process) {
475
+ return false;
476
+ }
477
+ try {
478
+ if (!this.killedProcesses.has(streamingId)) {
479
+ logger.info('Sending SIGTERM to process', { streamingId, pid: process.pid });
480
+ process.kill('SIGTERM');
481
+ this.killedProcesses.add(streamingId);
482
+ // Force kill after 3s if process hasn't exited
483
+ const killTimeout = setTimeout(() => {
484
+ try {
485
+ if (this.processes.has(streamingId)) {
486
+ logger.warn('Process not responding to SIGTERM, sending SIGKILL', { streamingId, pid: process.pid });
487
+ process.kill('SIGKILL');
488
+ }
489
+ }
490
+ catch {
491
+ // Process may have already exited
492
+ }
493
+ }, 3000);
494
+ const sessionTimeouts = this.timeouts.get(streamingId) || [];
495
+ sessionTimeouts.push(killTimeout);
496
+ this.timeouts.set(streamingId, sessionTimeouts);
497
+ }
498
+ // Note: cleanup happens in onExit handler, not here
499
+ logger.info('Stop signal sent', { streamingId });
500
+ return true;
501
+ }
502
+ catch (error) {
503
+ logger.error('Error stopping conversation', error, { streamingId });
504
+ return false;
505
+ }
506
+ }
507
+ forceKillConversation(streamingId) {
508
+ const process = this.processes.get(streamingId);
509
+ if (!process) {
510
+ return false;
511
+ }
512
+ try {
513
+ logger.warn('Force killing process with SIGKILL', { streamingId, pid: process.pid });
514
+ process.kill('SIGKILL');
515
+ this.killedProcesses.add(streamingId);
516
+ return true;
517
+ }
518
+ catch (error) {
519
+ logger.error('Error force killing conversation', error, { streamingId });
520
+ return false;
521
+ }
522
+ }
523
+ interruptConversation(streamingId) {
524
+ const process = this.processes.get(streamingId);
525
+ if (!process) {
526
+ return false;
527
+ }
528
+ try {
529
+ logger.info('Sending SIGINT to process', { streamingId, pid: process.pid });
530
+ process.kill('SIGINT');
531
+ return true;
532
+ }
533
+ catch (error) {
534
+ logger.error('Error interrupting conversation', error, { streamingId });
535
+ return false;
536
+ }
537
+ }
538
+ getActiveSessions() {
539
+ return Array.from(this.processes.keys()).map(streamingId => ({
540
+ streamingId,
541
+ sessionId: this.sessionIds.get(streamingId) || ''
542
+ })).filter(s => s.sessionId); // Only return sessions we have IDs for
543
+ }
544
+ isSessionActive(streamingId) {
545
+ return this.processes.has(streamingId);
546
+ }
547
+ cleanup(streamingId) {
548
+ const timeouts = this.timeouts.get(streamingId);
549
+ if (timeouts) {
550
+ timeouts.forEach((t) => clearTimeout(t));
551
+ this.timeouts.delete(streamingId);
552
+ }
553
+ this.processes.delete(streamingId);
554
+ this.outputBuffers.delete(streamingId);
555
+ this.conversationConfigs.delete(streamingId);
556
+ this.sessionIds.delete(streamingId);
557
+ this.killedProcesses.delete(streamingId);
558
+ }
559
+ // ============================================================================
560
+ // Process Handlers
561
+ // ============================================================================
562
+ /**
563
+ * Setup handlers for PTY-based processes (normal text conversations)
564
+ */
565
+ setupPtyProcessHandlers(streamingId, process) {
566
+ const parser = new JsonLinesParser();
567
+ this.outputBuffers.set(streamingId, '');
568
+ parser.on('data', (message) => {
569
+ // Skip echoed stdin messages - PTY echoes our input back
570
+ // BUT: tool_result messages are also type: 'user' (Claude API protocol:
571
+ // user = input TO Claude, assistant = output FROM Claude)
572
+ // We need to let tool_result messages through so the UI can update tool status
573
+ if (message?.type === 'user') {
574
+ const content = message.message?.content;
575
+ if (!content) {
576
+ return;
577
+ }
578
+ const isToolResult = Array.isArray(content) &&
579
+ content.some((block) => block.type === 'tool_result');
580
+ if (!isToolResult) {
581
+ // Filter non-tool-result user messages (echoed stdin)
582
+ return;
583
+ }
584
+ // Fall through to emit tool_result messages
585
+ logger.debug('Allowing tool_result message through', {
586
+ streamingId,
587
+ toolResultCount: content.filter(b => b.type === 'tool_result').length
588
+ });
589
+ }
590
+ this.handleClaudeMessage(streamingId, message);
591
+ });
592
+ parser.on('error', (error) => {
593
+ this.handleProcessError(streamingId, error);
594
+ });
595
+ process.onData((data) => {
596
+ // Strip ANSI escape sequences
597
+ const cleanedData = data.replace(/\x1b\[[0-9;]*[a-zA-Z]|\x1b\][^\x07]*\x07/g, '');
598
+ if (cleanedData.trim()) {
599
+ // Debug: log first chunk to see if we're getting any output
600
+ if (!this.outputBuffers.get(streamingId)) {
601
+ logger.debug('First PTY data received', {
602
+ streamingId,
603
+ dataLength: data.length,
604
+ cleanedLength: cleanedData.length,
605
+ preview: cleanedData.substring(0, 200)
606
+ });
607
+ this.outputBuffers.set(streamingId, 'received');
608
+ }
609
+ parser.write(cleanedData);
610
+ }
611
+ });
612
+ process.onExit(({ exitCode }) => {
613
+ this.handleProcessClose(streamingId, exitCode);
614
+ });
615
+ }
616
+ /**
617
+ * Setup handlers for piped child processes (multimodal with images)
618
+ * No stdin echo filtering needed since pipes don't echo
619
+ */
620
+ setupPipedProcessHandlers(streamingId, childProcess) {
621
+ const parser = new JsonLinesParser();
622
+ this.outputBuffers.set(streamingId, '');
623
+ parser.on('data', (message) => {
624
+ // Piped processes don't echo stdin, but still filter non-tool-result user messages
625
+ if (message?.type === 'user') {
626
+ const content = message.message?.content;
627
+ if (!content) {
628
+ return;
629
+ }
630
+ const isToolResult = Array.isArray(content) &&
631
+ content.some((block) => block.type === 'tool_result');
632
+ if (!isToolResult) {
633
+ return;
634
+ }
635
+ logger.debug('Allowing tool_result message through (piped)', {
636
+ streamingId,
637
+ toolResultCount: content.filter(b => b.type === 'tool_result').length
638
+ });
639
+ }
640
+ this.handleClaudeMessage(streamingId, message);
641
+ });
642
+ parser.on('error', (error) => {
643
+ this.handleProcessError(streamingId, error);
644
+ });
645
+ childProcess.stdout?.on('data', (data) => {
646
+ const str = data.toString();
647
+ if (str.trim()) {
648
+ if (!this.outputBuffers.get(streamingId)) {
649
+ logger.debug('First piped stdout data received', {
650
+ streamingId,
651
+ dataLength: str.length,
652
+ preview: str.substring(0, 200)
653
+ });
654
+ this.outputBuffers.set(streamingId, 'received');
655
+ }
656
+ parser.write(str);
657
+ }
658
+ });
659
+ childProcess.stderr?.on('data', (data) => {
660
+ logger.warn('Claude CLI stderr (piped)', { streamingId, stderr: data.toString() });
661
+ });
662
+ childProcess.on('close', (code) => {
663
+ this.handleProcessClose(streamingId, code);
664
+ });
665
+ childProcess.on('error', (error) => {
666
+ this.handleProcessError(streamingId, error);
667
+ });
668
+ }
669
+ handleClaudeMessage(streamingId, message) {
670
+ // Check if this is the system init we're waiting for
671
+ if (message?.type === 'system' && 'subtype' in message && message.subtype === 'init') {
672
+ const initMessage = message;
673
+ logger.info('System init message received with MCP servers', {
674
+ streamingId,
675
+ mcpServerCount: initMessage.mcp_servers?.length || 0,
676
+ mcpServers: initMessage.mcp_servers,
677
+ });
678
+ const pending = this.pendingSystemInits.get(streamingId);
679
+ if (pending) {
680
+ clearTimeout(pending.timeout);
681
+ this.pendingSystemInits.delete(streamingId);
682
+ pending.resolve(initMessage);
683
+ }
684
+ }
685
+ // Broadcast to all connected clients
686
+ this.broadcastEvent({
687
+ event: 'claude-message',
688
+ data: { streamingId, message },
689
+ });
690
+ // Also emit locally for internal handlers
691
+ this.emit('claude-message', { streamingId, message });
692
+ }
693
+ handleProcessClose(streamingId, code) {
694
+ // Capture sessionId and pid BEFORE cleanup deletes them
695
+ const sessionId = this.sessionIds.get(streamingId);
696
+ const process = this.processes.get(streamingId);
697
+ const pid = process?.pid;
698
+ logger.info('Process closed', { streamingId, code, sessionId, pid });
699
+ // Reject any pending system init
700
+ const pending = this.pendingSystemInits.get(streamingId);
701
+ if (pending) {
702
+ clearTimeout(pending.timeout);
703
+ this.pendingSystemInits.delete(streamingId);
704
+ pending.reject(new LatticeError('CLAUDE_PROCESS_EXITED_EARLY', 'Claude CLI process exited before sending system init', 500));
705
+ }
706
+ this.cleanup(streamingId);
707
+ this.broadcastEvent({
708
+ event: 'process-closed',
709
+ data: { streamingId, code, sessionId, pid },
710
+ });
711
+ this.emit('process-closed', { streamingId, code, sessionId, pid });
712
+ }
713
+ handleProcessError(streamingId, error) {
714
+ logger.error('Process error', error, { streamingId });
715
+ this.broadcastEvent({
716
+ event: 'process-error',
717
+ data: { streamingId, error: error.message },
718
+ });
719
+ this.emit('process-error', { streamingId, error: error.message });
720
+ }
721
+ // ============================================================================
722
+ // Argument Building
723
+ // ============================================================================
724
+ buildBaseArgs() {
725
+ return ['-p'];
726
+ }
727
+ buildResumeArgs(config) {
728
+ const args = this.buildBaseArgs();
729
+ // For multimodal: no CLI arg message - full content sent via piped stdin
730
+ // For text-only: use the actual message as CLI arg (PTY spawn)
731
+ if (config.message && !config.hasMultimodalContent) {
732
+ args.push(config.message);
733
+ }
734
+ args.push('--resume', config.sessionId, '--output-format', 'stream-json', '--input-format', 'stream-json', '--verbose');
735
+ // Apply permission mode
736
+ this.applyPermissionMode(args, config.permissionMode, config.streamingId);
737
+ return args;
738
+ }
739
+ /**
740
+ * Apply permission mode flags to CLI args
741
+ * Modes:
742
+ * - "bypassPermissions" (default): Skip all permission prompts (--dangerously-skip-permissions)
743
+ * - "default": Delegate to MCP permission server via --permission-prompt-tool
744
+ * - "acceptEdits": Auto-accept file edits but prompt for other tools
745
+ * - "plan": Plan mode - research only, no edits
746
+ */
747
+ applyPermissionMode(args, permissionMode, streamingId) {
748
+ switch (permissionMode) {
749
+ case 'default':
750
+ // Delegate permission decisions to our MCP permission server
751
+ this.applyMcpPermissionPrompt(args, streamingId);
752
+ break;
753
+ case 'acceptEdits':
754
+ args.push('--permission-mode', 'acceptEdits');
755
+ break;
756
+ case 'plan':
757
+ args.push('--permission-mode', 'plan');
758
+ break;
759
+ case 'bypassPermissions':
760
+ default:
761
+ // Default to bypass for backwards compatibility
762
+ args.push('--dangerously-skip-permissions');
763
+ break;
764
+ }
765
+ }
766
+ /**
767
+ * Configure MCP permission prompt tool for interactive permission handling
768
+ */
769
+ applyMcpPermissionPrompt(args, streamingId) {
770
+ // Paths to our MCP servers
771
+ const mcpServerPath = path.join(__dirname, '..', 'mcp-server', 'index.js');
772
+ const claudiaToolsPath = path.join(__dirname, '..', 'mcp-server', 'claudia-tools.js');
773
+ // MCP server config - the server needs CUI_STREAMING_ID to associate permissions
774
+ const mcpConfig = {
775
+ mcpServers: {
776
+ 'claudia-permissions': {
777
+ command: 'node',
778
+ args: [mcpServerPath],
779
+ env: {
780
+ CUI_STREAMING_ID: streamingId || 'unknown',
781
+ CUI_SERVER_URL: `http://localhost:${process.env.PORT || 3001}`,
782
+ },
783
+ },
784
+ 'claudia-orchestrator': {
785
+ command: 'node',
786
+ args: [claudiaToolsPath],
787
+ env: {
788
+ CUI_STREAMING_ID: streamingId || 'unknown',
789
+ CUI_SERVER_URL: `http://localhost:${process.env.PORT || 3001}`,
790
+ },
791
+ },
792
+ },
793
+ };
794
+ args.push('--mcp-config', JSON.stringify(mcpConfig));
795
+ args.push('--permission-prompt-tool', 'mcp__claudia-permissions__permission_prompt');
796
+ logger.info('Applied MCP config', { streamingId, mcpServerPath, claudiaToolsPath });
797
+ }
798
+ buildStartArgs(config, streamingId) {
799
+ const args = this.buildBaseArgs();
800
+ // Add initial prompt as CLI arg - skip if multimodal content will be sent via stdin
801
+ const hasMultimodalContent = !!(config.initialContent && config.initialContent.length > 0);
802
+ if (config.initialPrompt && !hasMultimodalContent) {
803
+ args.push(config.initialPrompt);
804
+ }
805
+ args.push('--output-format', 'stream-json', '--input-format', 'stream-json', '--verbose');
806
+ if (config.model) {
807
+ args.push('--model', config.model);
808
+ }
809
+ if (config.allowedTools?.length) {
810
+ args.push('--allowedTools', config.allowedTools.join(','));
811
+ }
812
+ if (config.disallowedTools?.length) {
813
+ args.push('--disallowedTools', config.disallowedTools.join(','));
814
+ }
815
+ // Add system prompt with Claudia environment info
816
+ const claudiaEnvInfo = `
817
+ ## Claudia Orchestrator Environment
818
+
819
+ You are running inside the Claudia orchestrator dashboard.
820
+
821
+ **Server logs** (for debugging issues):
822
+ - \`~/.claudia/logs/server.log\` - Express server logs
823
+ - \`~/.claudia/logs/daemon.log\` - Process daemon logs
824
+ `;
825
+ const systemPrompt = config.systemPrompt
826
+ ? `${config.systemPrompt}\n${claudiaEnvInfo}`
827
+ : claudiaEnvInfo;
828
+ args.push('--system-prompt', systemPrompt);
829
+ // Apply permission mode
830
+ this.applyPermissionMode(args, config.permissionMode, streamingId);
831
+ return args;
832
+ }
833
+ // ============================================================================
834
+ // System Init Waiting
835
+ // ============================================================================
836
+ waitForSystemInit(streamingId) {
837
+ return new Promise((resolve, reject) => {
838
+ const timeout = setTimeout(() => {
839
+ this.pendingSystemInits.delete(streamingId);
840
+ reject(new LatticeError('SYSTEM_INIT_TIMEOUT', 'Timeout waiting for system initialization from Claude CLI', 500));
841
+ }, 60000);
842
+ this.pendingSystemInits.set(streamingId, { resolve, reject, timeout });
843
+ });
844
+ }
845
+ }
846
+ //# sourceMappingURL=process-daemon.js.map