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,757 @@
1
+ /**
2
+ * Prototype routes - experimental features for testing and development.
3
+ *
4
+ * In production builds, these routes are gated and return 404 by default.
5
+ * They can be enabled by setting CLAUDIA_ENABLE_PROTOTYPES=true.
6
+ */
7
+ import { Router } from 'express';
8
+ import sharp from 'sharp';
9
+ import Anthropic from '@anthropic-ai/sdk';
10
+ import { createLogger } from '../services/infrastructure/logger.js';
11
+ import { GoogleGenAI } from '@google/genai';
12
+ import { ConfigService } from '../services/infrastructure/config-service.js';
13
+ import { readFileSync, existsSync } from 'fs';
14
+ const logger = createLogger('PrototypeRoutes');
15
+ /**
16
+ * Middleware to gate prototype routes in production.
17
+ * Returns 404 unless CLAUDIA_ENABLE_PROTOTYPES=true.
18
+ */
19
+ function prototypeGate(req, res, next) {
20
+ const isProduction = process.env.NODE_ENV === 'production';
21
+ const prototypesEnabled = process.env.CLAUDIA_ENABLE_PROTOTYPES === 'true';
22
+ if (isProduction && !prototypesEnabled) {
23
+ logger.debug('Prototype route blocked in production', {
24
+ path: req.path,
25
+ method: req.method,
26
+ });
27
+ res.status(404).json({ error: 'Not found' });
28
+ return;
29
+ }
30
+ next();
31
+ }
32
+ // Rich color palette for diverse banners
33
+ const COLORS = [
34
+ 'electric blue', 'hot pink', 'lime green', 'golden yellow', 'coral orange',
35
+ 'deep purple', 'cyan', 'magenta', 'mint green', 'amber',
36
+ 'crimson red', 'teal', 'lavender', 'peach', 'electric violet',
37
+ 'neon orange', 'sky blue', 'rose pink', 'chartreuse', 'copper'
38
+ ];
39
+ // Style seeds - different visual languages
40
+ const STYLE_SEEDS = [
41
+ 'flowing and organic',
42
+ 'sharp and angular',
43
+ 'scattered particles',
44
+ 'layered waves',
45
+ 'crystalline shards',
46
+ 'soft gradients',
47
+ 'circuit-like traces',
48
+ 'bold geometric',
49
+ 'wispy and ethereal',
50
+ 'dense and textured',
51
+ 'minimal and sparse',
52
+ 'dynamic and energetic'
53
+ ];
54
+ // Composition hints
55
+ const COMPOSITIONS = [
56
+ 'asymmetric, weighted left',
57
+ 'asymmetric, weighted right',
58
+ 'centered focal point',
59
+ 'scattered across the frame',
60
+ 'diagonal flow',
61
+ 'horizontal bands',
62
+ 'clustered elements'
63
+ ];
64
+ function pickRandom(arr) {
65
+ return arr[Math.floor(Math.random() * arr.length)];
66
+ }
67
+ function pickTwo(arr) {
68
+ const first = pickRandom(arr);
69
+ let second = pickRandom(arr);
70
+ while (second === first && arr.length > 1) {
71
+ second = pickRandom(arr);
72
+ }
73
+ return [first, second];
74
+ }
75
+ // Prompt templates for banner generation
76
+ const PROMPT_TEMPLATES = {
77
+ neonSymbol: (mission, color) => `Add a glowing neon icon to this black image.
78
+
79
+ TASK: ${mission}
80
+ COLOR: ${color} glow
81
+
82
+ Requirements:
83
+ - Single bold central symbol
84
+ - Neon glow effect
85
+ - Keep the black background intact
86
+ - No text, no faces
87
+ - Tech/circuit aesthetic optional`,
88
+ horizontalNeon: (mission, color) => `Add a horizontal neon design element to this wide black banner.
89
+
90
+ TASK: ${mission}
91
+ COLOR: ${color} neon glow
92
+
93
+ Requirements:
94
+ - Design should flow horizontally across the banner
95
+ - Could be: flowing lines, circuit traces, abstract waves, or a stretched icon
96
+ - Strong neon glow effect with ${color} color
97
+ - Keep the black background
98
+ - No text, no faces
99
+ - Subtle tech/digital aesthetic`,
100
+ minimalGlyph: (mission, color) => `Add a minimal glowing glyph to this black banner.
101
+
102
+ TASK: ${mission}
103
+ COLOR: ${color} glow
104
+
105
+ Create a single, abstract symbol that represents the essence of this work.
106
+ - Centered in the horizontal space
107
+ - Bold but simple - 1-3 strokes maximum
108
+ - Strong ${color} neon glow
109
+ - Pure black background
110
+ - No text`,
111
+ abstractWave: (mission, color) => `Add an abstract wave pattern to this black banner.
112
+
113
+ TASK: ${mission}
114
+ COLOR: ${color}
115
+
116
+ Create a flowing horizontal wave or energy pattern:
117
+ - Spans the full width of the banner
118
+ - ${color} glowing effect
119
+ - Abstract, not literal
120
+ - Subtle gradient from edges to center
121
+ - Pure black background`,
122
+ circuitTrace: (mission, color) => `Add circuit board trace patterns to this black banner.
123
+
124
+ TASK: ${mission}
125
+ COLOR: ${color}
126
+
127
+ Design specifications:
128
+ - Horizontal circuit traces flowing left to right
129
+ - Small nodes/points at intersections
130
+ - ${color} neon glow
131
+ - Technical, digital aesthetic
132
+ - Black background`,
133
+ };
134
+ export function createPrototypeRoutes() {
135
+ const router = Router();
136
+ // Apply gate to all prototype routes
137
+ router.use(prototypeGate);
138
+ // Generate a banner image with custom dimensions and prompt
139
+ router.post('/generate-banner', async (req, res) => {
140
+ const requestId = req.requestId;
141
+ const { mission, color, template, width, height, customPrompt } = req.body;
142
+ logger.info('Generate banner request', {
143
+ requestId,
144
+ mission: mission?.slice(0, 50),
145
+ color,
146
+ template,
147
+ width,
148
+ height,
149
+ hasCustomPrompt: !!customPrompt
150
+ });
151
+ try {
152
+ // Validate inputs
153
+ if (!width || !height) {
154
+ res.status(400).json({ error: 'Missing required fields: width, height' });
155
+ return;
156
+ }
157
+ let prompt;
158
+ if (customPrompt) {
159
+ // Use custom prompt directly
160
+ prompt = customPrompt;
161
+ }
162
+ else {
163
+ // Use template-based prompt
164
+ if (!mission || !color || !template) {
165
+ res.status(400).json({ error: 'Missing required fields: mission, color, template (or provide customPrompt)' });
166
+ return;
167
+ }
168
+ const promptFn = PROMPT_TEMPLATES[template];
169
+ if (!promptFn) {
170
+ res.status(400).json({ error: `Unknown template: ${template}` });
171
+ return;
172
+ }
173
+ prompt = promptFn(mission, color);
174
+ }
175
+ // Get Gemini API key
176
+ const config = ConfigService.getInstance().getConfig();
177
+ const apiKey = config.gemini?.apiKey || process.env.GOOGLE_API_KEY;
178
+ if (!apiKey) {
179
+ res.status(500).json({ error: 'Gemini API key not configured' });
180
+ return;
181
+ }
182
+ // Create black canvas at higher resolution (will resize after)
183
+ // Use 2x or 3x for quality, scaled to max 1024 on any dimension
184
+ const scale = Math.min(3, 1024 / Math.max(width, height));
185
+ const canvasWidth = Math.round(width * scale);
186
+ const canvasHeight = Math.round(height * scale);
187
+ logger.debug('Creating black canvas', { canvasWidth, canvasHeight, scale });
188
+ const blackCanvas = await sharp({
189
+ create: {
190
+ width: canvasWidth,
191
+ height: canvasHeight,
192
+ channels: 3,
193
+ background: { r: 0, g: 0, b: 0 }
194
+ }
195
+ }).png().toBuffer();
196
+ const blackCanvasBase64 = blackCanvas.toString('base64');
197
+ // Call Gemini image generation
198
+ const genAI = new GoogleGenAI({ apiKey });
199
+ logger.debug('Calling Gemini image generation', { prompt: prompt.slice(0, 100) });
200
+ const response = await genAI.models.generateContent({
201
+ model: 'gemini-3-pro-image-preview',
202
+ contents: [
203
+ {
204
+ role: 'user',
205
+ parts: [
206
+ { inlineData: { mimeType: 'image/png', data: blackCanvasBase64 } },
207
+ { text: prompt }
208
+ ]
209
+ }
210
+ ],
211
+ config: {
212
+ responseModalities: ['TEXT', 'IMAGE'],
213
+ }
214
+ });
215
+ // Extract image from response
216
+ if (response.candidates?.[0]?.content?.parts) {
217
+ for (const part of response.candidates[0].content.parts) {
218
+ if (part.inlineData) {
219
+ const rawImageBuffer = Buffer.from(part.inlineData.data, 'base64');
220
+ // Resize to target dimensions
221
+ const resizedBuffer = await sharp(rawImageBuffer)
222
+ .resize(width, height, { fit: 'cover' })
223
+ .jpeg({ quality: 85 })
224
+ .toBuffer();
225
+ const resizedBase64 = resizedBuffer.toString('base64');
226
+ logger.info('Banner generated successfully', {
227
+ requestId,
228
+ originalSize: rawImageBuffer.length,
229
+ resizedSize: resizedBuffer.length,
230
+ dimensions: `${width}x${height}`
231
+ });
232
+ res.json({
233
+ imageData: resizedBase64,
234
+ mimeType: 'image/jpeg',
235
+ dimensions: { width, height }
236
+ });
237
+ return;
238
+ }
239
+ }
240
+ }
241
+ res.status(500).json({ error: 'No image was generated in the response' });
242
+ }
243
+ catch (error) {
244
+ const errorMessage = error instanceof Error ? error.message : String(error);
245
+ logger.error('Banner generation failed', {
246
+ requestId,
247
+ errorMessage,
248
+ errorType: error?.constructor?.name
249
+ });
250
+ res.status(500).json({ error: `Generation failed: ${errorMessage}` });
251
+ }
252
+ });
253
+ // Full semantic pipeline: extract visual concepts from session context, then generate banner
254
+ router.post('/semantic-banner', async (req, res) => {
255
+ const requestId = req.requestId;
256
+ const { mission, theme, project } = req.body;
257
+ logger.info('Semantic banner pipeline request', {
258
+ requestId,
259
+ mission: mission?.slice(0, 50),
260
+ theme,
261
+ project
262
+ });
263
+ try {
264
+ if (!mission) {
265
+ res.status(400).json({ error: 'Missing required field: mission' });
266
+ return;
267
+ }
268
+ // Get config early since we need API keys
269
+ const config = ConfigService.getInstance().getConfig();
270
+ // Step 1: Extract visual concepts using Claude
271
+ const extractionPrompt = `You are helping generate a visual identity banner for a coding session. Given the session context below, extract visual concepts that could represent this work.
272
+
273
+ <session_context>
274
+ Mission: ${mission}
275
+ Theme: ${theme || 'implementing'}
276
+ Project: ${project || 'Unknown'}
277
+ </session_context>
278
+
279
+ Analyze what this session is fundamentally about and output a JSON object with:
280
+
281
+ 1. "primary_metaphor": A concrete visual metaphor for the core work (e.g., "a lock being examined" for auth debugging, "flowing streams merging" for data pipeline work, "tangled wires being organized" for refactoring)
282
+
283
+ 2. "visual_elements": 2-3 specific visual elements that could appear in a horizontal banner (e.g., "diagnostic scan lines", "glowing nodes", "geometric shapes reorganizing")
284
+
285
+ 3. "mood": The emotional/energy quality (e.g., "urgent and focused", "methodical and precise", "creative and exploratory")
286
+
287
+ 4. "color_suggestion": A neon color that fits the mood (choose from: cyan/blue, amber/orange, green/emerald, purple/violet, magenta/pink, gold/yellow)
288
+
289
+ 5. "icon_hint": A single simple icon/symbol that captures the essence (e.g., "magnifying glass", "shield", "gear", "lightning bolt", "compass", "lock", "branch", "pulse")
290
+
291
+ Output ONLY the JSON object, no other text.`;
292
+ logger.debug('Extracting visual concepts', { requestId });
293
+ // Get Anthropic API key
294
+ const anthropicApiKey = config.anthropic?.apiKey || process.env.ANTHROPIC_API_KEY;
295
+ if (!anthropicApiKey) {
296
+ res.status(500).json({ error: 'Anthropic API key not configured' });
297
+ return;
298
+ }
299
+ const anthropic = new Anthropic({ apiKey: anthropicApiKey });
300
+ const extractionResponse = await anthropic.messages.create({
301
+ model: 'claude-haiku-4-5-20251001',
302
+ max_tokens: 500,
303
+ messages: [{ role: 'user', content: extractionPrompt }],
304
+ });
305
+ const extractionText = extractionResponse.content[0].type === 'text'
306
+ ? extractionResponse.content[0].text
307
+ : '';
308
+ // Parse concepts
309
+ let concepts;
310
+ try {
311
+ concepts = JSON.parse(extractionText);
312
+ }
313
+ catch {
314
+ const jsonMatch = extractionText.match(/\{[\s\S]*\}/);
315
+ if (jsonMatch) {
316
+ concepts = JSON.parse(jsonMatch[0]);
317
+ }
318
+ else {
319
+ throw new Error(`Failed to parse concepts: ${extractionText.slice(0, 200)}`);
320
+ }
321
+ }
322
+ logger.info('Visual concepts extracted', {
323
+ requestId,
324
+ metaphor: concepts.primary_metaphor,
325
+ color: concepts.color_suggestion,
326
+ icon: concepts.icon_hint
327
+ });
328
+ // Step 2: Build image prompt from concepts
329
+ const imagePrompt = `Add a glowing neon design to this black banner image.
330
+
331
+ VISUAL CONCEPT: ${concepts.primary_metaphor}
332
+
333
+ Elements to include:
334
+ ${concepts.visual_elements.map(e => `- ${e}`).join('\n')}
335
+
336
+ Style:
337
+ - ${concepts.mood}
338
+ - ${concepts.color_suggestion} neon glow
339
+ - Consider incorporating a ${concepts.icon_hint} motif
340
+ - Horizontal composition flowing across the banner
341
+ - Pure black background
342
+ - No text, no faces
343
+ - Abstract/stylized, not photorealistic`;
344
+ // Step 3: Generate the image
345
+ const apiKey = config.gemini?.apiKey || process.env.GOOGLE_API_KEY;
346
+ if (!apiKey) {
347
+ res.status(500).json({ error: 'Gemini API key not configured' });
348
+ return;
349
+ }
350
+ const width = 401;
351
+ const height = 64;
352
+ const scale = Math.min(3, 1024 / Math.max(width, height));
353
+ const canvasWidth = Math.round(width * scale);
354
+ const canvasHeight = Math.round(height * scale);
355
+ const blackCanvas = await sharp({
356
+ create: {
357
+ width: canvasWidth,
358
+ height: canvasHeight,
359
+ channels: 3,
360
+ background: { r: 0, g: 0, b: 0 }
361
+ }
362
+ }).png().toBuffer();
363
+ const blackCanvasBase64 = blackCanvas.toString('base64');
364
+ const genAI = new GoogleGenAI({ apiKey });
365
+ logger.debug('Generating image with Gemini', { requestId });
366
+ const imageResponse = await genAI.models.generateContent({
367
+ model: 'gemini-3-pro-image-preview',
368
+ contents: [
369
+ {
370
+ role: 'user',
371
+ parts: [
372
+ { inlineData: { mimeType: 'image/png', data: blackCanvasBase64 } },
373
+ { text: imagePrompt }
374
+ ]
375
+ }
376
+ ],
377
+ config: {
378
+ responseModalities: ['TEXT', 'IMAGE'],
379
+ }
380
+ });
381
+ // Extract image from response
382
+ if (imageResponse.candidates?.[0]?.content?.parts) {
383
+ for (const part of imageResponse.candidates[0].content.parts) {
384
+ if (part.inlineData) {
385
+ const rawImageBuffer = Buffer.from(part.inlineData.data, 'base64');
386
+ const resizedBuffer = await sharp(rawImageBuffer)
387
+ .resize(width, height, { fit: 'cover' })
388
+ .jpeg({ quality: 85 })
389
+ .toBuffer();
390
+ const resizedBase64 = resizedBuffer.toString('base64');
391
+ logger.info('Semantic banner generated successfully', {
392
+ requestId,
393
+ dimensions: `${width}x${height}`
394
+ });
395
+ res.json({
396
+ imageData: resizedBase64,
397
+ mimeType: 'image/jpeg',
398
+ dimensions: { width, height },
399
+ concepts,
400
+ imagePrompt,
401
+ });
402
+ return;
403
+ }
404
+ }
405
+ }
406
+ res.status(500).json({ error: 'No image was generated in the response' });
407
+ }
408
+ catch (error) {
409
+ const errorMessage = error instanceof Error ? error.message : String(error);
410
+ logger.error('Semantic banner pipeline failed', {
411
+ requestId,
412
+ errorMessage,
413
+ errorType: error?.constructor?.name
414
+ });
415
+ res.status(500).json({ error: `Pipeline failed: ${errorMessage}` });
416
+ }
417
+ });
418
+ // New diversity-focused banner generation
419
+ router.post('/diverse-banner', async (req, res) => {
420
+ const requestId = req.requestId;
421
+ const { context } = req.body;
422
+ // Pick random visual parameters
423
+ const [primaryColor, accentColor] = pickTwo(COLORS);
424
+ const style = pickRandom(STYLE_SEEDS);
425
+ const composition = pickRandom(COMPOSITIONS);
426
+ logger.info('Diverse banner generation request', {
427
+ requestId,
428
+ primaryColor,
429
+ accentColor,
430
+ style,
431
+ composition,
432
+ context: context?.slice(0, 50)
433
+ });
434
+ try {
435
+ const config = ConfigService.getInstance().getConfig();
436
+ const apiKey = config.gemini?.apiKey || process.env.GOOGLE_API_KEY;
437
+ if (!apiKey) {
438
+ res.status(500).json({ error: 'Gemini API key not configured' });
439
+ return;
440
+ }
441
+ const prompt = `Create a unique abstract banner on this black background. No text, no faces, no realistic objects.
442
+
443
+ Colors: ${primaryColor} as primary, ${accentColor} as accent
444
+ Style: ${style}
445
+ Composition: ${composition}
446
+
447
+ ${context ? `Inspiration (interpret freely, don't be literal): ${context}` : ''}
448
+
449
+ Be creative and make this visually distinctive. Pure black background must be preserved.`;
450
+ const width = 401;
451
+ const height = 64;
452
+ const scale = Math.min(3, 1024 / Math.max(width, height));
453
+ const canvasWidth = Math.round(width * scale);
454
+ const canvasHeight = Math.round(height * scale);
455
+ const blackCanvas = await sharp({
456
+ create: {
457
+ width: canvasWidth,
458
+ height: canvasHeight,
459
+ channels: 3,
460
+ background: { r: 0, g: 0, b: 0 }
461
+ }
462
+ }).png().toBuffer();
463
+ const blackCanvasBase64 = blackCanvas.toString('base64');
464
+ const genAI = new GoogleGenAI({ apiKey });
465
+ const response = await genAI.models.generateContent({
466
+ model: 'gemini-3-pro-image-preview',
467
+ contents: [
468
+ {
469
+ role: 'user',
470
+ parts: [
471
+ { inlineData: { mimeType: 'image/png', data: blackCanvasBase64 } },
472
+ { text: prompt }
473
+ ]
474
+ }
475
+ ],
476
+ config: {
477
+ responseModalities: ['TEXT', 'IMAGE'],
478
+ }
479
+ });
480
+ if (response.candidates?.[0]?.content?.parts) {
481
+ for (const part of response.candidates[0].content.parts) {
482
+ if (part.inlineData) {
483
+ const rawImageBuffer = Buffer.from(part.inlineData.data, 'base64');
484
+ const resizedBuffer = await sharp(rawImageBuffer)
485
+ .resize(width, height, { fit: 'cover' })
486
+ .jpeg({ quality: 90 })
487
+ .toBuffer();
488
+ const resizedBase64 = resizedBuffer.toString('base64');
489
+ logger.info('Diverse banner generated successfully', {
490
+ requestId,
491
+ dimensions: `${width}x${height}`,
492
+ primaryColor,
493
+ accentColor,
494
+ style
495
+ });
496
+ res.json({
497
+ imageData: resizedBase64,
498
+ mimeType: 'image/jpeg',
499
+ dimensions: { width, height },
500
+ params: { primaryColor, accentColor, style, composition, context }
501
+ });
502
+ return;
503
+ }
504
+ }
505
+ }
506
+ res.status(500).json({ error: 'No image was generated in the response' });
507
+ }
508
+ catch (error) {
509
+ const errorMessage = error instanceof Error ? error.message : String(error);
510
+ logger.error('Diverse banner generation failed', {
511
+ requestId,
512
+ errorMessage,
513
+ errorType: error?.constructor?.name
514
+ });
515
+ res.status(500).json({ error: `Generation failed: ${errorMessage}` });
516
+ }
517
+ });
518
+ // Serve demo walkthrough data
519
+ router.get('/walkthrough/demo', (_req, res) => {
520
+ const demoPath = '/tmp/walkthrough-demo.json';
521
+ if (!existsSync(demoPath)) {
522
+ res.status(404).json({ error: 'Demo walkthrough not found. Generate with: npx tsx scripts/generate-walkthrough.ts <session.jsonl> > /tmp/walkthrough-demo.json' });
523
+ return;
524
+ }
525
+ try {
526
+ const data = JSON.parse(readFileSync(demoPath, 'utf-8'));
527
+ res.json(data);
528
+ }
529
+ catch (_err) {
530
+ res.status(500).json({ error: 'Failed to read demo walkthrough' });
531
+ }
532
+ });
533
+ // Serve the image experiment gallery page
534
+ router.get('/image-gallery', (_req, res) => {
535
+ const html = `<!DOCTYPE html>
536
+ <html>
537
+ <head>
538
+ <title>Banner Diversity Experiment</title>
539
+ <style>
540
+ * { box-sizing: border-box; }
541
+ body {
542
+ background: #0a0a0a;
543
+ color: #eee;
544
+ font-family: system-ui, -apple-system, sans-serif;
545
+ padding: 2rem;
546
+ margin: 0;
547
+ }
548
+ h1 {
549
+ text-align: center;
550
+ margin-bottom: 0.5rem;
551
+ font-weight: 400;
552
+ font-size: 1.5rem;
553
+ }
554
+ .subtitle {
555
+ text-align: center;
556
+ color: #666;
557
+ margin-bottom: 2rem;
558
+ font-size: 0.9rem;
559
+ }
560
+ .controls {
561
+ display: flex;
562
+ justify-content: center;
563
+ gap: 1rem;
564
+ margin-bottom: 2rem;
565
+ flex-wrap: wrap;
566
+ }
567
+ button {
568
+ background: #222;
569
+ color: #eee;
570
+ border: 1px solid #444;
571
+ padding: 0.75rem 1.5rem;
572
+ border-radius: 6px;
573
+ cursor: pointer;
574
+ font-size: 0.9rem;
575
+ transition: all 0.15s;
576
+ }
577
+ button:hover {
578
+ background: #333;
579
+ border-color: #666;
580
+ }
581
+ button:disabled {
582
+ opacity: 0.5;
583
+ cursor: not-allowed;
584
+ }
585
+ .gallery {
586
+ display: grid;
587
+ grid-template-columns: repeat(auto-fill, minmax(420px, 1fr));
588
+ gap: 1rem;
589
+ max-width: 1800px;
590
+ margin: 0 auto;
591
+ }
592
+ .card {
593
+ background: #151515;
594
+ border-radius: 8px;
595
+ overflow: hidden;
596
+ border: 1px solid #252525;
597
+ }
598
+ .card img {
599
+ width: 100%;
600
+ height: auto;
601
+ display: block;
602
+ }
603
+ .card.loading {
604
+ min-height: 100px;
605
+ display: flex;
606
+ align-items: center;
607
+ justify-content: center;
608
+ }
609
+ .card.loading::after {
610
+ content: 'Generating...';
611
+ color: #555;
612
+ font-size: 0.85rem;
613
+ }
614
+ .info {
615
+ padding: 0.75rem;
616
+ }
617
+ .params {
618
+ display: flex;
619
+ flex-wrap: wrap;
620
+ gap: 0.4rem;
621
+ }
622
+ .param {
623
+ padding: 0.2rem 0.5rem;
624
+ border-radius: 4px;
625
+ font-size: 0.7rem;
626
+ background: #222;
627
+ color: #888;
628
+ }
629
+ .param.color {
630
+ color: #000;
631
+ font-weight: 500;
632
+ }
633
+ .context {
634
+ margin-top: 0.5rem;
635
+ font-size: 0.8rem;
636
+ color: #666;
637
+ font-style: italic;
638
+ }
639
+ .context-input {
640
+ width: 100%;
641
+ max-width: 500px;
642
+ padding: 0.5rem 0.75rem;
643
+ background: #1a1a1a;
644
+ border: 1px solid #333;
645
+ border-radius: 6px;
646
+ color: #eee;
647
+ font-size: 0.9rem;
648
+ }
649
+ .context-input::placeholder {
650
+ color: #555;
651
+ }
652
+ </style>
653
+ </head>
654
+ <body>
655
+ <h1>Banner Diversity Experiment</h1>
656
+ <p class="subtitle">Random colors + styles + loose context = distinctive banners</p>
657
+
658
+ <div class="controls">
659
+ <input type="text" class="context-input" id="contextInput" placeholder="Optional context (e.g., 'debugging auth flow')">
660
+ <button onclick="generateOne()">Generate 1</button>
661
+ <button onclick="generateBatch(5)">Generate 5</button>
662
+ <button onclick="generateBatch(10)">Generate 10</button>
663
+ <button onclick="clearGallery()">Clear</button>
664
+ </div>
665
+
666
+ <div class="gallery" id="gallery"></div>
667
+
668
+ <script>
669
+ const gallery = document.getElementById('gallery');
670
+ const contextInput = document.getElementById('contextInput');
671
+
672
+ const colorMap = {
673
+ 'electric blue': '#0066ff',
674
+ 'hot pink': '#ff1493',
675
+ 'lime green': '#32cd32',
676
+ 'golden yellow': '#ffd700',
677
+ 'coral orange': '#ff7f50',
678
+ 'deep purple': '#673ab7',
679
+ 'cyan': '#00bcd4',
680
+ 'magenta': '#e91e63',
681
+ 'mint green': '#98ff98',
682
+ 'amber': '#ffbf00',
683
+ 'crimson red': '#dc143c',
684
+ 'teal': '#008080',
685
+ 'lavender': '#b57edc',
686
+ 'peach': '#ffcba4',
687
+ 'electric violet': '#8f00ff',
688
+ 'neon orange': '#ff6600',
689
+ 'sky blue': '#87ceeb',
690
+ 'rose pink': '#ff66b2',
691
+ 'chartreuse': '#7fff00',
692
+ 'copper': '#b87333'
693
+ };
694
+
695
+ async function generateOne() {
696
+ const card = document.createElement('div');
697
+ card.className = 'card loading';
698
+ gallery.prepend(card);
699
+
700
+ try {
701
+ const context = contextInput.value.trim() || undefined;
702
+ const response = await fetch('/api/prototype/diverse-banner', {
703
+ method: 'POST',
704
+ headers: { 'Content-Type': 'application/json' },
705
+ body: JSON.stringify({ context })
706
+ });
707
+
708
+ const data = await response.json();
709
+
710
+ if (data.error) {
711
+ card.innerHTML = '<div class="info" style="color: #f55;">' + data.error + '</div>';
712
+ card.classList.remove('loading');
713
+ return;
714
+ }
715
+
716
+ const primaryCss = colorMap[data.params.primaryColor] || '#888';
717
+ const accentCss = colorMap[data.params.accentColor] || '#888';
718
+
719
+ card.innerHTML = \`
720
+ <img src="data:\${data.mimeType};base64,\${data.imageData}" alt="Generated banner">
721
+ <div class="info">
722
+ <div class="params">
723
+ <span class="param color" style="background: \${primaryCss}">\${data.params.primaryColor}</span>
724
+ <span class="param color" style="background: \${accentCss}">\${data.params.accentColor}</span>
725
+ <span class="param">\${data.params.style}</span>
726
+ <span class="param">\${data.params.composition}</span>
727
+ </div>
728
+ \${data.params.context ? '<div class="context">' + data.params.context + '</div>' : ''}
729
+ </div>
730
+ \`;
731
+ card.classList.remove('loading');
732
+ } catch (err) {
733
+ card.innerHTML = '<div class="info" style="color: #f55;">Error: ' + err.message + '</div>';
734
+ card.classList.remove('loading');
735
+ }
736
+ }
737
+
738
+ async function generateBatch(count) {
739
+ for (let i = 0; i < count; i++) {
740
+ generateOne();
741
+ if (i < count - 1) {
742
+ await new Promise(r => setTimeout(r, 500));
743
+ }
744
+ }
745
+ }
746
+
747
+ function clearGallery() {
748
+ gallery.innerHTML = '';
749
+ }
750
+ </script>
751
+ </body>
752
+ </html>`;
753
+ res.type('html').send(html);
754
+ });
755
+ return router;
756
+ }
757
+ //# sourceMappingURL=prototype.routes.js.map