circuschief 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (319) hide show
  1. package/package.json +33 -0
  2. package/packages/server/bin/cli.js +4 -0
  3. package/packages/server/src/agents/AgentGateway.js +64 -0
  4. package/packages/server/src/agents/BaseAgent.js +41 -0
  5. package/packages/server/src/agents/LoggingAgentWrapper.js +73 -0
  6. package/packages/server/src/agents/adapters/ClaudeCodeAdapter.js +33 -0
  7. package/packages/server/src/agents/adapters/CodexAdapter.js +26 -0
  8. package/packages/server/src/agents/types.js +43 -0
  9. package/packages/server/src/agents/vcr/CassetteStore.js +111 -0
  10. package/packages/server/src/agents/vcr/VCRAgentAdapter.js +126 -0
  11. package/packages/server/src/agents/vcr/VCRSummaryWrapper.js +71 -0
  12. package/packages/server/src/api/canvas-helpers.js +249 -0
  13. package/packages/server/src/api/canvas-trash-routes.js +205 -0
  14. package/packages/server/src/api/canvas.js +331 -0
  15. package/packages/server/src/api/commandButtons.js +312 -0
  16. package/packages/server/src/api/commands.js +169 -0
  17. package/packages/server/src/api/filesystem.js +62 -0
  18. package/packages/server/src/api/git.js +85 -0
  19. package/packages/server/src/api/index.js +44 -0
  20. package/packages/server/src/api/kanban.js +342 -0
  21. package/packages/server/src/api/metrics.js +194 -0
  22. package/packages/server/src/api/projects-helpers.js +43 -0
  23. package/packages/server/src/api/projects-session-helpers.js +295 -0
  24. package/packages/server/src/api/projects.js +384 -0
  25. package/packages/server/src/api/providers.js +249 -0
  26. package/packages/server/src/api/quickResponses.js +129 -0
  27. package/packages/server/src/api/sessions-archive.js +69 -0
  28. package/packages/server/src/api/sessions-commands.js +220 -0
  29. package/packages/server/src/api/sessions-conversations.js +168 -0
  30. package/packages/server/src/api/sessions-draft.js +72 -0
  31. package/packages/server/src/api/sessions-lifecycle.js +190 -0
  32. package/packages/server/src/api/sessions-messages.js +141 -0
  33. package/packages/server/src/api/sessions-notes.js +51 -0
  34. package/packages/server/src/api/sessions-patch.js +252 -0
  35. package/packages/server/src/api/sessions-streaming.js +86 -0
  36. package/packages/server/src/api/sessions.js +269 -0
  37. package/packages/server/src/api/settings.js +194 -0
  38. package/packages/server/src/api/templates.js +63 -0
  39. package/packages/server/src/app.js +51 -0
  40. package/packages/server/src/database.js +58 -0
  41. package/packages/server/src/db/AgentCallLogRepository.js +322 -0
  42. package/packages/server/src/db/AttachmentRepository.js +191 -0
  43. package/packages/server/src/db/BaseRepository.js +39 -0
  44. package/packages/server/src/db/CanvasItemRepository.js +315 -0
  45. package/packages/server/src/db/CommandButtonRepository.js +75 -0
  46. package/packages/server/src/db/CommandRunRepository.js +219 -0
  47. package/packages/server/src/db/ConversationRepository.js +379 -0
  48. package/packages/server/src/db/DatabaseManager.js +91 -0
  49. package/packages/server/src/db/KanbanBoardRepository.js +92 -0
  50. package/packages/server/src/db/KanbanCardRepository.js +286 -0
  51. package/packages/server/src/db/KanbanLaneRepository.js +279 -0
  52. package/packages/server/src/db/MessageRepository.js +156 -0
  53. package/packages/server/src/db/ProjectDefaultsRepository.js +173 -0
  54. package/packages/server/src/db/ProjectRepository.js +110 -0
  55. package/packages/server/src/db/ProviderRepository.js +307 -0
  56. package/packages/server/src/db/QuickResponseRepository.js +186 -0
  57. package/packages/server/src/db/SessionNoteRepository.js +60 -0
  58. package/packages/server/src/db/SessionRepository.js +314 -0
  59. package/packages/server/src/db/SessionSummaryRepository.js +200 -0
  60. package/packages/server/src/db/SessionTemplateRepository.js +171 -0
  61. package/packages/server/src/db/SettingsRepository.js +211 -0
  62. package/packages/server/src/db/TodoRepository.js +132 -0
  63. package/packages/server/src/db/WorkLogRepository.js +122 -0
  64. package/packages/server/src/db/conversation-helpers.js +119 -0
  65. package/packages/server/src/db/index.js +100 -0
  66. package/packages/server/src/db/migrations/canvasItemsMigrations.js +109 -0
  67. package/packages/server/src/db/migrations/conversationsMigrations.js +183 -0
  68. package/packages/server/src/db/migrations/index.js +199 -0
  69. package/packages/server/src/db/migrations/kanbanMigrations.js +99 -0
  70. package/packages/server/src/db/migrations/migrationUtils.js +55 -0
  71. package/packages/server/src/db/migrations/miscMigrations.js +242 -0
  72. package/packages/server/src/db/migrations/projectsMigrations.js +95 -0
  73. package/packages/server/src/db/migrations/sessionsMigrations.js +282 -0
  74. package/packages/server/src/db/session-helpers.js +150 -0
  75. package/packages/server/src/index.js +106 -0
  76. package/packages/server/src/logger.js +22 -0
  77. package/packages/server/src/middleware/sessionLookup.js +57 -0
  78. package/packages/server/src/middleware/upload.js +94 -0
  79. package/packages/server/src/schema.sql +363 -0
  80. package/packages/server/src/services/agentCallLogger.js +116 -0
  81. package/packages/server/src/services/canvasStore.js +56 -0
  82. package/packages/server/src/services/childSessionContext.js +61 -0
  83. package/packages/server/src/services/commandRunner.js +422 -0
  84. package/packages/server/src/services/conversationContext.js +72 -0
  85. package/packages/server/src/services/diffService.js +172 -0
  86. package/packages/server/src/services/draftSessionService.js +181 -0
  87. package/packages/server/src/services/encryption.js +134 -0
  88. package/packages/server/src/services/ghService.js +169 -0
  89. package/packages/server/src/services/gitService.js +520 -0
  90. package/packages/server/src/services/gitSessionSetup.js +48 -0
  91. package/packages/server/src/services/hookService.js +60 -0
  92. package/packages/server/src/services/kanbanService.js +262 -0
  93. package/packages/server/src/services/kanbanTriggers.js +273 -0
  94. package/packages/server/src/services/nodeSpawnHelper.js +63 -0
  95. package/packages/server/src/services/prStatusService.js +204 -0
  96. package/packages/server/src/services/prUrlService.js +224 -0
  97. package/packages/server/src/services/providerTestService.js +81 -0
  98. package/packages/server/src/services/scheduleService.js +110 -0
  99. package/packages/server/src/services/schedulerService.js +281 -0
  100. package/packages/server/src/services/sessionDuplicator.js +63 -0
  101. package/packages/server/src/services/sessionErrors.js +173 -0
  102. package/packages/server/src/services/sessionExecution.js +378 -0
  103. package/packages/server/src/services/sessionManager.js +356 -0
  104. package/packages/server/src/services/sessionPrompts.js +427 -0
  105. package/packages/server/src/services/sessionProvider.js +107 -0
  106. package/packages/server/src/services/slashCommandDiscovery.js +258 -0
  107. package/packages/server/src/services/slashCommandPluginDiscovery.js +216 -0
  108. package/packages/server/src/services/slashCommandService.js +306 -0
  109. package/packages/server/src/services/streamEventCallbacks.js +170 -0
  110. package/packages/server/src/services/streamEventHandler.js +488 -0
  111. package/packages/server/src/services/streamUsageHandler.js +228 -0
  112. package/packages/server/src/services/summaryBroadcast.js +61 -0
  113. package/packages/server/src/services/summaryClaudeClient.js +180 -0
  114. package/packages/server/src/services/summaryPrompts.js +169 -0
  115. package/packages/server/src/services/summaryService.js +552 -0
  116. package/packages/server/src/services/summaryStaleCheck.js +35 -0
  117. package/packages/server/src/services/systemMonitor.js +281 -0
  118. package/packages/server/src/services/templateTriggerService.js +197 -0
  119. package/packages/server/src/services/terminalOutput.js +160 -0
  120. package/packages/server/src/services/todoStore.js +58 -0
  121. package/packages/server/src/services/usageTracker.js +69 -0
  122. package/packages/server/src/services/withConcurrencyGuard.js +110 -0
  123. package/packages/server/src/websocket.js +10 -0
  124. package/packages/server/src/ws/WebSocketManager.js +240 -0
  125. package/packages/server/src/ws/index.js +50 -0
  126. package/packages/shared/package.json +27 -0
  127. package/packages/shared/src/constants.js +44 -0
  128. package/packages/shared/src/contracts/canvas.js +25 -0
  129. package/packages/shared/src/contracts/commandButtons.js +36 -0
  130. package/packages/shared/src/contracts/kanban.js +142 -0
  131. package/packages/shared/src/contracts/projects.js +63 -0
  132. package/packages/shared/src/contracts/providers.js +81 -0
  133. package/packages/shared/src/contracts/quickResponses.js +44 -0
  134. package/packages/shared/src/contracts/sessions.js +112 -0
  135. package/packages/shared/src/contracts/templates.js +51 -0
  136. package/packages/shared/src/index.js +5 -0
  137. package/packages/shared/src/protocol.js +76 -0
  138. package/packages/shared/src/routeParams.js +36 -0
  139. package/packages/shared/src/types.js +167 -0
  140. package/packages/shared/src/utils.js +101 -0
  141. package/packages/web/dist/assets/ActiveSessionsView-BQc76Jc8.js +1 -0
  142. package/packages/web/dist/assets/ActiveSessionsView-ofSvx-K1.css +1 -0
  143. package/packages/web/dist/assets/AgentLogsView-CTCjHjsu.js +2 -0
  144. package/packages/web/dist/assets/AgentLogsView-D90PnQVk.css +1 -0
  145. package/packages/web/dist/assets/ApiClient-Dbs1H78V.js +1 -0
  146. package/packages/web/dist/assets/ArchiveConfirmModal-CCxSZ52u.js +1 -0
  147. package/packages/web/dist/assets/ArchiveConfirmModal-CQZeuYBz.css +1 -0
  148. package/packages/web/dist/assets/CommandButtonDetailView-CF_-LXpU.js +1 -0
  149. package/packages/web/dist/assets/CommandButtonDetailView-DBm3rzhw.css +1 -0
  150. package/packages/web/dist/assets/EffortLevelSelector-BQaQmU2d.css +1 -0
  151. package/packages/web/dist/assets/EffortLevelSelector-DPofLvm-.js +1 -0
  152. package/packages/web/dist/assets/GeneralSettingsView-BCf53fpC.css +1 -0
  153. package/packages/web/dist/assets/GeneralSettingsView-BY1G-Kv8.js +1 -0
  154. package/packages/web/dist/assets/InterpolationHelp-CgdbNcJB.js +1 -0
  155. package/packages/web/dist/assets/InterpolationHelp-iNxTxmhs.css +1 -0
  156. package/packages/web/dist/assets/MarkdownEditor-CqT1U8lo.js +2 -0
  157. package/packages/web/dist/assets/MarkdownEditor-enuH2yvP.css +1 -0
  158. package/packages/web/dist/assets/ModelSelector-BBn_Ve0D.js +1 -0
  159. package/packages/web/dist/assets/ModelSelector-DPPD-92R.css +1 -0
  160. package/packages/web/dist/assets/NewSessionView-Bo5l49nu.js +3 -0
  161. package/packages/web/dist/assets/NewSessionView-Byoi1XdQ.css +1 -0
  162. package/packages/web/dist/assets/PathChooser-BoMGzeg2.css +1 -0
  163. package/packages/web/dist/assets/PathChooser-Cx9gQ-Qt.js +1 -0
  164. package/packages/web/dist/assets/ProjectEditView-BFuscj-V.js +1 -0
  165. package/packages/web/dist/assets/ProjectEditView-DNwBUNRk.css +1 -0
  166. package/packages/web/dist/assets/ProjectListView-C55H1JHQ.css +1 -0
  167. package/packages/web/dist/assets/ProjectListView-Dj0jBZ46.js +1 -0
  168. package/packages/web/dist/assets/ProjectNewView-Brdp-xUu.js +1 -0
  169. package/packages/web/dist/assets/ProjectNewView-CpgE4R-l.css +1 -0
  170. package/packages/web/dist/assets/ProvidersView-B_QQF3RM.css +1 -0
  171. package/packages/web/dist/assets/ProvidersView-Cxc-1skq.js +1 -0
  172. package/packages/web/dist/assets/QuickResponseSettings-B2eVAtHW.js +1 -0
  173. package/packages/web/dist/assets/QuickResponseSettings-B8188A1D.css +1 -0
  174. package/packages/web/dist/assets/QuickResponsesPanel-DIBQFj0W.css +1 -0
  175. package/packages/web/dist/assets/QuickResponsesPanel-lU8pW2B0.js +1 -0
  176. package/packages/web/dist/assets/ResizableTextarea-B5nAA0RV.css +1 -0
  177. package/packages/web/dist/assets/ResizableTextarea-DSy1mWGY.js +1 -0
  178. package/packages/web/dist/assets/SessionCard-BvjLwVYg.js +1 -0
  179. package/packages/web/dist/assets/SessionCard-D20G3bX8.css +1 -0
  180. package/packages/web/dist/assets/SessionDetailView-BQbPg-RJ.js +36 -0
  181. package/packages/web/dist/assets/SessionDetailView-BrMG4p2-.css +1 -0
  182. package/packages/web/dist/assets/SessionFormOptions-BgqFR-5f.js +1 -0
  183. package/packages/web/dist/assets/SessionFormOptions-BuLlDF-7.css +1 -0
  184. package/packages/web/dist/assets/SessionListView-BAIBtJF7.css +1 -0
  185. package/packages/web/dist/assets/SessionListView-CYIHI8qF.js +1 -0
  186. package/packages/web/dist/assets/SessionLogStream-B-FwUMJQ.js +18 -0
  187. package/packages/web/dist/assets/SessionLogStream-zPUTiGbe.css +1 -0
  188. package/packages/web/dist/assets/SettingsView-DC8-hTQ-.css +1 -0
  189. package/packages/web/dist/assets/SettingsView-fZxpiGp7.js +1 -0
  190. package/packages/web/dist/assets/SlashCommandWizard-BB30cSvo.css +1 -0
  191. package/packages/web/dist/assets/SlashCommandWizard-BgaOw9W3.js +1 -0
  192. package/packages/web/dist/assets/SummarySettingsView-DcsmSVJI.css +1 -0
  193. package/packages/web/dist/assets/SummarySettingsView-eeu1Xq86.js +1 -0
  194. package/packages/web/dist/assets/TemplateDetailView-DEPKSwDo.js +1 -0
  195. package/packages/web/dist/assets/TemplateDetailView-DT2m06W7.css +1 -0
  196. package/packages/web/dist/assets/apl-B4CMkyY2.js +1 -0
  197. package/packages/web/dist/assets/asciiarmor-Df11BRmG.js +1 -0
  198. package/packages/web/dist/assets/asn1-EdZsLKOL.js +1 -0
  199. package/packages/web/dist/assets/asterisk-B-8jnY81.js +1 -0
  200. package/packages/web/dist/assets/brainfuck-C4LP7Hcl.js +1 -0
  201. package/packages/web/dist/assets/clike-B9uivgTg.js +1 -0
  202. package/packages/web/dist/assets/clojure-BMjYHr_A.js +1 -0
  203. package/packages/web/dist/assets/cmake-BQqOBYOt.js +1 -0
  204. package/packages/web/dist/assets/cobol-CWcv1MsR.js +1 -0
  205. package/packages/web/dist/assets/coffeescript-S37ZYGWr.js +1 -0
  206. package/packages/web/dist/assets/commandButtons-DNSHH8IA.js +4 -0
  207. package/packages/web/dist/assets/commonlisp-DBKNyK5s.js +1 -0
  208. package/packages/web/dist/assets/crystal-SjHAIU92.js +1 -0
  209. package/packages/web/dist/assets/css-BnMrqG3P.js +1 -0
  210. package/packages/web/dist/assets/cypher-C_CwsFkJ.js +1 -0
  211. package/packages/web/dist/assets/d-pRatUO7H.js +1 -0
  212. package/packages/web/dist/assets/diff-DbItnlRl.js +1 -0
  213. package/packages/web/dist/assets/dockerfile-BKs6k2Af.js +1 -0
  214. package/packages/web/dist/assets/dtd-DF_7sFjM.js +1 -0
  215. package/packages/web/dist/assets/dylan-DwRh75JA.js +1 -0
  216. package/packages/web/dist/assets/ebnf-CDyGwa7X.js +1 -0
  217. package/packages/web/dist/assets/ecl-Cabwm37j.js +1 -0
  218. package/packages/web/dist/assets/eiffel-CnydiIhH.js +1 -0
  219. package/packages/web/dist/assets/elm-vLlmbW-K.js +1 -0
  220. package/packages/web/dist/assets/erlang-BNw1qcRV.js +1 -0
  221. package/packages/web/dist/assets/factor-kuTfRLto.js +1 -0
  222. package/packages/web/dist/assets/fcl-Kvtd6kyn.js +1 -0
  223. package/packages/web/dist/assets/forth-Ffai-XNe.js +1 -0
  224. package/packages/web/dist/assets/fortran-DYz_wnZ1.js +1 -0
  225. package/packages/web/dist/assets/gas-Bneqetm1.js +1 -0
  226. package/packages/web/dist/assets/gherkin-heZmZLOM.js +1 -0
  227. package/packages/web/dist/assets/groovy-D9Dt4D0W.js +1 -0
  228. package/packages/web/dist/assets/haskell-BWDZoCOh.js +1 -0
  229. package/packages/web/dist/assets/haxe-H-WmDvRZ.js +1 -0
  230. package/packages/web/dist/assets/http-DBlCnlav.js +1 -0
  231. package/packages/web/dist/assets/idl-BEugSyMb.js +1 -0
  232. package/packages/web/dist/assets/index-BZlHgDSz.js +1 -0
  233. package/packages/web/dist/assets/index-BhWX8AfE.js +2 -0
  234. package/packages/web/dist/assets/index-Bi3XvF_f.js +1 -0
  235. package/packages/web/dist/assets/index-BqXoPf_D.js +1 -0
  236. package/packages/web/dist/assets/index-CAuTOZSD.js +1 -0
  237. package/packages/web/dist/assets/index-CKYk-fkb.js +1 -0
  238. package/packages/web/dist/assets/index-CTumW_tV.js +318 -0
  239. package/packages/web/dist/assets/index-CVOJVSsC.js +82 -0
  240. package/packages/web/dist/assets/index-CXK2Z3_z.js +1 -0
  241. package/packages/web/dist/assets/index-CYllQ3Vd.js +1 -0
  242. package/packages/web/dist/assets/index-CpsfI08O.js +1 -0
  243. package/packages/web/dist/assets/index-DQkhDeTA.js +3 -0
  244. package/packages/web/dist/assets/index-DWP8iCBp.js +1 -0
  245. package/packages/web/dist/assets/index-DkVb9W_J.js +1 -0
  246. package/packages/web/dist/assets/index-DmKHPbIa.js +1 -0
  247. package/packages/web/dist/assets/index-DrlQi03X.js +1 -0
  248. package/packages/web/dist/assets/index-gmCCsCQ1.css +1 -0
  249. package/packages/web/dist/assets/index-prTEzzgO.js +1 -0
  250. package/packages/web/dist/assets/index-wqgejMCM.js +1 -0
  251. package/packages/web/dist/assets/index-yh0ZHIWw.js +7 -0
  252. package/packages/web/dist/assets/javascript-qCveANmP.js +1 -0
  253. package/packages/web/dist/assets/julia-DuME0IfC.js +1 -0
  254. package/packages/web/dist/assets/livescript-BwQOo05w.js +1 -0
  255. package/packages/web/dist/assets/lua-BgMRiT3U.js +1 -0
  256. package/packages/web/dist/assets/mathematica-DTrFuWx2.js +1 -0
  257. package/packages/web/dist/assets/mbox-CNhZ1qSd.js +1 -0
  258. package/packages/web/dist/assets/mirc-CjQqDB4T.js +1 -0
  259. package/packages/web/dist/assets/mllike-CXdrOF99.js +1 -0
  260. package/packages/web/dist/assets/modelica-Dc1JOy9r.js +1 -0
  261. package/packages/web/dist/assets/mscgen-BA5vi2Kp.js +1 -0
  262. package/packages/web/dist/assets/mumps-BT43cFF4.js +1 -0
  263. package/packages/web/dist/assets/nginx-DdIZxoE0.js +1 -0
  264. package/packages/web/dist/assets/nsis-LdVXkNf5.js +1 -0
  265. package/packages/web/dist/assets/ntriples-BfvgReVJ.js +1 -0
  266. package/packages/web/dist/assets/octave-Ck1zUtKM.js +1 -0
  267. package/packages/web/dist/assets/oz-BzwKVEFT.js +1 -0
  268. package/packages/web/dist/assets/pascal--L3eBynH.js +1 -0
  269. package/packages/web/dist/assets/perl-CdXCOZ3F.js +1 -0
  270. package/packages/web/dist/assets/pig-CevX1Tat.js +1 -0
  271. package/packages/web/dist/assets/powershell-CFHJl5sT.js +1 -0
  272. package/packages/web/dist/assets/projects-DbBQQH-V.js +1 -0
  273. package/packages/web/dist/assets/properties-C78fOPTZ.js +1 -0
  274. package/packages/web/dist/assets/protobuf-ChK-085T.js +1 -0
  275. package/packages/web/dist/assets/providers-ceCc4xRU.js +1 -0
  276. package/packages/web/dist/assets/pug-DukmZTjD.js +1 -0
  277. package/packages/web/dist/assets/puppet-DMA9R1ak.js +1 -0
  278. package/packages/web/dist/assets/python-BuPzkPfP.js +1 -0
  279. package/packages/web/dist/assets/q-pXgVlZs6.js +1 -0
  280. package/packages/web/dist/assets/r-DUYO_cvP.js +1 -0
  281. package/packages/web/dist/assets/rpm-CTu-6PCP.js +1 -0
  282. package/packages/web/dist/assets/ruby-B2Rjki9n.js +1 -0
  283. package/packages/web/dist/assets/sas-B4kiWyti.js +1 -0
  284. package/packages/web/dist/assets/scheme-C41bIUwD.js +1 -0
  285. package/packages/web/dist/assets/sessions-D681M81k.js +1 -0
  286. package/packages/web/dist/assets/settings-D0evez2V.js +1 -0
  287. package/packages/web/dist/assets/shell-CjFT_Tl9.js +1 -0
  288. package/packages/web/dist/assets/sieve-C3Gn_uJK.js +1 -0
  289. package/packages/web/dist/assets/simple-mode-GW_nhZxv.js +1 -0
  290. package/packages/web/dist/assets/smalltalk-CnHTOXQT.js +1 -0
  291. package/packages/web/dist/assets/solr-DehyRSwq.js +1 -0
  292. package/packages/web/dist/assets/sparql-DkYu6x3z.js +1 -0
  293. package/packages/web/dist/assets/spreadsheet-BCZA_wO0.js +1 -0
  294. package/packages/web/dist/assets/sql-D0XecflT.js +1 -0
  295. package/packages/web/dist/assets/stex-C3f8Ysf7.js +1 -0
  296. package/packages/web/dist/assets/style-BTin-zR_.css +1 -0
  297. package/packages/web/dist/assets/stylus-B533Al4x.js +1 -0
  298. package/packages/web/dist/assets/swift-BzpIVaGY.js +1 -0
  299. package/packages/web/dist/assets/tcl-DVfN8rqt.js +1 -0
  300. package/packages/web/dist/assets/textile-CnDTJFAw.js +1 -0
  301. package/packages/web/dist/assets/tiddlywiki-DO-Gjzrf.js +1 -0
  302. package/packages/web/dist/assets/tiki-DGYXhP31.js +1 -0
  303. package/packages/web/dist/assets/toml-Bm5Em-hy.js +1 -0
  304. package/packages/web/dist/assets/troff-wAsdV37c.js +1 -0
  305. package/packages/web/dist/assets/ttcn-CfJYG6tj.js +1 -0
  306. package/packages/web/dist/assets/ttcn-cfg-B9xdYoR4.js +1 -0
  307. package/packages/web/dist/assets/turtle-B1tBg_DP.js +1 -0
  308. package/packages/web/dist/assets/vb-CmGdzxic.js +1 -0
  309. package/packages/web/dist/assets/vbscript-BuJXcnF6.js +1 -0
  310. package/packages/web/dist/assets/velocity-D8B20fx6.js +1 -0
  311. package/packages/web/dist/assets/verilog-C6RDOZhf.js +1 -0
  312. package/packages/web/dist/assets/vhdl-lSbBsy5d.js +1 -0
  313. package/packages/web/dist/assets/webidl-ZXfAyPTL.js +1 -0
  314. package/packages/web/dist/assets/xquery-CQfU5ijd.js +1 -0
  315. package/packages/web/dist/assets/yacas-BJ4BC0dw.js +1 -0
  316. package/packages/web/dist/assets/z80-Hz9HOZM7.js +1 -0
  317. package/packages/web/dist/favicon.png +0 -0
  318. package/packages/web/dist/index.html +17 -0
  319. package/packages/web/dist/logo.png +0 -0
@@ -0,0 +1,181 @@
1
+ import { sessions, messages, projects, conversations, attachments } from '../database.js';
2
+ import { broadcastToSession, broadcastToProject } from '../websocket.js';
3
+ import { WS_MESSAGE_TYPES } from '../../../shared/src/index.js';
4
+ import * as slashCommandService from './slashCommandService.js';
5
+
6
+ /**
7
+ * Validates that a session is a draft (waiting status with no assistant messages).
8
+ * @param {object} session - The session object
9
+ * @returns {{ valid: boolean, error?: string }}
10
+ */
11
+ export function validateDraftSession(session) {
12
+ if (session.status !== 'waiting') {
13
+ return { valid: false, error: 'Session must be in waiting status to start' };
14
+ }
15
+
16
+ const allMessages = messages.getBySessionId(session.id);
17
+ const hasAssistantMessages = allMessages.some(msg => msg.role === 'assistant');
18
+ if (hasAssistantMessages) {
19
+ return { valid: false, error: 'Session is not a draft - it already has responses' };
20
+ }
21
+
22
+ return { valid: true };
23
+ }
24
+
25
+ /**
26
+ * Validate that a prompt is non-empty.
27
+ * @param {*} prompt
28
+ * @returns {boolean}
29
+ */
30
+ function isValidPrompt(prompt) {
31
+ return prompt && typeof prompt === 'string' && prompt.trim() !== '';
32
+ }
33
+
34
+ /**
35
+ * Create the initial user message for a draft session.
36
+ * @param {object} session
37
+ * @param {string} promptToUse
38
+ * @returns {object} The created message
39
+ */
40
+ function createInitialMessage(session, promptToUse) {
41
+ const activeConv = conversations.getActiveBySessionId(session.id);
42
+ if (!activeConv) {
43
+ throw new DraftSessionError('No active conversation found', 500);
44
+ }
45
+
46
+ const initialMessage = messages.create(session.id, 'user', promptToUse, { toolUse: null, conversationId: activeConv.id });
47
+ sessions.update(session.id, { pendingPrompt: null });
48
+
49
+ broadcastToSession(session.id, WS_MESSAGE_TYPES.MESSAGE_CREATED, {
50
+ sessionId: session.id,
51
+ message: initialMessage,
52
+ });
53
+
54
+ return initialMessage;
55
+ }
56
+
57
+ /**
58
+ * Update an existing initial message with a new prompt.
59
+ * @param {object} session
60
+ * @param {object} initialMessage
61
+ * @param {string} newPrompt
62
+ * @returns {object} The updated message
63
+ */
64
+ function updateInitialMessage(session, initialMessage, newPrompt) {
65
+ const updatedMessage = messages.updateContent(initialMessage.id, newPrompt);
66
+
67
+ broadcastToSession(session.id, WS_MESSAGE_TYPES.MESSAGE_UPDATED, {
68
+ sessionId: session.id,
69
+ message: updatedMessage,
70
+ });
71
+
72
+ return updatedMessage;
73
+ }
74
+
75
+ /**
76
+ * Get or create the initial user message for a draft session.
77
+ * @param {object} session
78
+ * @param {object} options
79
+ * @returns {object} The initial message
80
+ */
81
+ function getOrCreateInitialMessage(session, options) {
82
+ const allMessages = messages.getBySessionId(session.id);
83
+ const userMessages = allMessages.filter(msg => msg.role === 'user');
84
+
85
+ // No existing user messages - create one
86
+ if (userMessages.length === 0) {
87
+ const promptToUse = options.prompt || session.pendingPrompt;
88
+ if (!isValidPrompt(promptToUse)) {
89
+ throw new DraftSessionError('No initial prompt found', 400);
90
+ }
91
+ return createInitialMessage(session, promptToUse);
92
+ }
93
+
94
+ // Existing user message - optionally update it
95
+ let initialMessage = userMessages[0];
96
+ if (options.prompt !== undefined) {
97
+ if (!isValidPrompt(options.prompt)) {
98
+ throw new DraftSessionError('Prompt must be a non-empty string', 400);
99
+ }
100
+ initialMessage = updateInitialMessage(session, initialMessage, options.prompt);
101
+ }
102
+
103
+ return initialMessage;
104
+ }
105
+
106
+ /**
107
+ * Starts a draft session by resolving the prompt, creating messages if needed,
108
+ * and kicking off the session manager.
109
+ *
110
+ * @param {object} session - The session object (from req.session_)
111
+ * @param {object} options
112
+ * @param {string} [options.prompt] - Optional new prompt to use/override
113
+ * @param {string} [options.model] - Optional model override
114
+ * @returns {Promise<object>} The updated session
115
+ */
116
+ export async function startDraft(session, options = {}) {
117
+ const project = projects.getById(session.projectId);
118
+ if (!project) {
119
+ throw new DraftSessionError('Project not found', 404);
120
+ }
121
+
122
+ // Use gitWorktree if set, otherwise use project's working directory
123
+ const workingDirectory = session.gitWorktree || project.workingDirectory;
124
+
125
+ // Model to use for this session (optional - SDK will use default if not provided)
126
+ const model = options.model || session.pendingModel || session.model || null;
127
+
128
+ // Get or create the initial user message
129
+ const initialMessage = getOrCreateInitialMessage(session, options);
130
+ const finalPrompt = initialMessage.content;
131
+
132
+ // Get session attachments for context
133
+ const sessionAttachments = attachments.getBySessionId(session.id);
134
+
135
+ // Update session status to starting and clear pendingModel (mirrors pendingPrompt cleanup above)
136
+ sessions.update(session.id, { status: 'starting', pendingModel: null });
137
+
138
+ // Resolve skill/command invocations so skill body goes into system prompt
139
+ const resolved = await slashCommandService.resolvePromptSkillOrCommand(
140
+ workingDirectory, finalPrompt, project.systemPrompt
141
+ );
142
+ const effectivePrompt = resolved ? resolved.userMessage : finalPrompt;
143
+ const effectiveSystemPrompt = resolved ? resolved.systemPrompt : project.systemPrompt;
144
+
145
+ // Start session manager (non-blocking)
146
+ const { runSession } = await import('./sessionManager.js');
147
+ runSession(session.id, effectivePrompt, workingDirectory, { systemPrompt: effectiveSystemPrompt, fileAttachments: sessionAttachments, model }).catch((error) => {
148
+ console.error('Session error:', error);
149
+ sessions.update(session.id, { status: 'error', error: error.message });
150
+ });
151
+
152
+ // Broadcast status update
153
+ broadcastToSession(session.id, WS_MESSAGE_TYPES.SESSION_STATUS, {
154
+ sessionId: session.id,
155
+ status: 'starting',
156
+ });
157
+
158
+ // Broadcast to project subscribers
159
+ broadcastToProject(session.projectId, WS_MESSAGE_TYPES.SESSION_UPDATED, {
160
+ projectId: session.projectId,
161
+ sessionId: session.id,
162
+ session: sessions.getById(session.id),
163
+ });
164
+
165
+ return sessions.getById(session.id);
166
+ }
167
+
168
+ /**
169
+ * Custom error class for draft session operations, includes HTTP status code.
170
+ */
171
+ export class DraftSessionError extends Error {
172
+ /**
173
+ * @param {string} message
174
+ * @param {number} statusCode
175
+ */
176
+ constructor(message, statusCode) {
177
+ super(message);
178
+ this.name = 'DraftSessionError';
179
+ this.statusCode = statusCode;
180
+ }
181
+ }
@@ -0,0 +1,134 @@
1
+ import crypto from 'crypto';
2
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
3
+ import { join } from 'path';
4
+ import { homedir } from 'os';
5
+
6
+ const ALGORITHM = 'aes-256-gcm';
7
+ const KEY_LENGTH = 32; // 256 bits for AES-256
8
+ const IV_LENGTH = 12; // 96 bits is recommended for GCM
9
+ const SEPARATOR = ':';
10
+ const PARTS_COUNT = 3;
11
+
12
+ // Allow tests to override the key directory so they never touch the real ~/.circuschief/secret.key
13
+ let _keyDirOverride = null;
14
+
15
+ /**
16
+ * Get or generate the encryption key.
17
+ * Uses ~/.circuschief/secret.key file (auto-generated on first run)
18
+ * @returns {Buffer} - 32-byte encryption key
19
+ */
20
+ function getEncryptionKey() {
21
+ const keyDir = _keyDirOverride || join(homedir(), '.circuschief');
22
+ const keyPath = join(keyDir, 'secret.key');
23
+
24
+ if (existsSync(keyPath)) {
25
+ const keyHex = readFileSync(keyPath, 'utf-8').trim();
26
+ // Validate the key is a 64-char hex string (32 bytes)
27
+ if (/^[0-9a-fA-F]{64}$/.test(keyHex)) {
28
+ return Buffer.from(keyHex, 'hex');
29
+ }
30
+ // Key is invalid, log warning and regenerate
31
+ console.warn(`[encryption] Invalid key file at ${keyPath}, regenerating...`);
32
+ }
33
+
34
+ // Generate a new key
35
+ const key = crypto.randomBytes(KEY_LENGTH);
36
+ mkdirSync(keyDir, { recursive: true });
37
+ writeFileSync(keyPath, key.toString('hex'), { mode: 0o600 });
38
+ return key;
39
+ }
40
+
41
+ // Lazily initialize the key so it's only loaded when first needed
42
+ let _key = null;
43
+
44
+ function getKey() {
45
+ if (!_key) {
46
+ _key = getEncryptionKey();
47
+ }
48
+ return _key;
49
+ }
50
+
51
+ /**
52
+ * Encrypt a plaintext string using AES-256-GCM.
53
+ * Returns a string in the format: <iv_hex>:<authTag_hex>:<ciphertext_hex>
54
+ * Returns the original value unchanged if it is null, undefined, or empty.
55
+ * @param {string|null|undefined} plaintext
56
+ * @returns {string|null|undefined}
57
+ */
58
+ export function encrypt(plaintext) {
59
+ if (plaintext == null || plaintext === '') return plaintext;
60
+
61
+ const key = getKey();
62
+ const iv = crypto.randomBytes(IV_LENGTH);
63
+ const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
64
+
65
+ const encrypted = Buffer.concat([
66
+ cipher.update(plaintext, 'utf-8'),
67
+ cipher.final(),
68
+ ]);
69
+ const authTag = cipher.getAuthTag();
70
+
71
+ return [iv.toString('hex'), authTag.toString('hex'), encrypted.toString('hex')].join(SEPARATOR);
72
+ }
73
+
74
+ /**
75
+ * Decrypt a ciphertext string that was encrypted with `encrypt()`.
76
+ * Gracefully handles plaintext values (legacy data not yet encrypted) by returning them as-is.
77
+ * Returns the original value unchanged if it is null, undefined, or empty.
78
+ * @param {string|null|undefined} ciphertext
79
+ * @returns {string|null|undefined}
80
+ */
81
+ export function decrypt(ciphertext) {
82
+ if (ciphertext == null || ciphertext === '') return ciphertext;
83
+
84
+ // If the value doesn't look like our format, treat it as plaintext (legacy)
85
+ const parts = ciphertext.split(SEPARATOR);
86
+ if (parts.length !== PARTS_COUNT) return ciphertext;
87
+
88
+ // Validate hex format and expected lengths
89
+ // IV should be 24 hex chars (12 bytes), auth tag should be 32 hex chars (16 bytes)
90
+ const ivHex = parts[0];
91
+ const authTagHex = parts[1];
92
+
93
+ if (!/^[0-9a-fA-F]{24}$/.test(ivHex) || !/^[0-9a-fA-F]{32}$/.test(authTagHex)) {
94
+ return ciphertext; // Legacy plaintext
95
+ }
96
+
97
+ try {
98
+ const key = getKey();
99
+ const iv = Buffer.from(parts[0], 'hex');
100
+ const authTag = Buffer.from(parts[1], 'hex');
101
+ const encrypted = Buffer.from(parts[2], 'hex');
102
+
103
+ const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
104
+ decipher.setAuthTag(authTag);
105
+
106
+ return decipher.update(encrypted) + decipher.final('utf-8');
107
+ } catch {
108
+ // Decryption failed — value is likely legacy plaintext, return as-is
109
+ console.warn('[encryption] Failed to decrypt value — returning as-is (possible key mismatch or legacy plaintext)');
110
+ return ciphertext;
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Reset the cached encryption key.
116
+ * Only intended for test isolation.
117
+ * @internal
118
+ */
119
+ export function _resetKeyForTesting() {
120
+ _key = null;
121
+ }
122
+
123
+ /**
124
+ * Override the key directory so tests use an isolated temp path
125
+ * instead of the real ~/.circuschief/ directory.
126
+ * Pass null to restore the default behaviour.
127
+ * Only intended for test isolation.
128
+ * @param {string|null} dir
129
+ * @internal
130
+ */
131
+ export function _setKeyDirForTesting(dir) {
132
+ _keyDirOverride = dir;
133
+ _key = null; // also clear the cached key so the new path takes effect
134
+ }
@@ -0,0 +1,169 @@
1
+ import { exec } from 'child_process';
2
+ import { promisify } from 'util';
3
+
4
+ const execAsync = promisify(exec);
5
+
6
+ // Cache gh availability check
7
+ let ghAvailable = null;
8
+
9
+ /**
10
+ * Check if gh CLI is installed and authenticated
11
+ * @returns {Promise<boolean>}
12
+ */
13
+ export async function isGhAvailable() {
14
+ if (ghAvailable !== null) return ghAvailable;
15
+ try {
16
+ await execAsync('gh --version');
17
+ await execAsync('gh auth status');
18
+ ghAvailable = true;
19
+ } catch {
20
+ ghAvailable = false;
21
+ }
22
+ return ghAvailable;
23
+ }
24
+
25
+ /**
26
+ * Reset the gh availability cache (useful for testing)
27
+ */
28
+ export function resetGhAvailableCache() {
29
+ ghAvailable = null;
30
+ }
31
+
32
+ /**
33
+ * Extract repository information from a PR URL
34
+ * @param {string} prUrl - GitHub PR URL
35
+ * @returns {Object|null} - { owner, repo, number } or null if invalid
36
+ */
37
+ export function extractPrInfo(prUrl) {
38
+ if (!prUrl) return null;
39
+
40
+ try {
41
+ // Match GitHub PR URL pattern: https://github.com/{owner}/{repo}/pull/{number}
42
+ const match = prUrl.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)$/);
43
+ if (!match) return null;
44
+
45
+ return {
46
+ owner: match[1],
47
+ repo: match[2],
48
+ number: parseInt(match[3], 10),
49
+ };
50
+ } catch {
51
+ return null;
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Validate that a PR URL belongs to the expected repository
57
+ * @param {string} prUrl - GitHub PR URL
58
+ * @param {string} expectedRepoUrl - Expected repository URL (https://github.com/owner/repo)
59
+ * @returns {Object} - { valid: boolean, mismatch: boolean, error: string|null }
60
+ */
61
+ export function validatePrRepository(prUrl, expectedRepoUrl) {
62
+ if (!prUrl) {
63
+ return { valid: false, mismatch: false, error: 'No PR URL provided' };
64
+ }
65
+
66
+ const prInfo = extractPrInfo(prUrl);
67
+ if (!prInfo) {
68
+ return { valid: false, mismatch: false, error: 'Invalid PR URL format' };
69
+ }
70
+
71
+ // If no expected repo URL, we can't validate - accept it
72
+ if (!expectedRepoUrl) {
73
+ return { valid: true, mismatch: false, error: null };
74
+ }
75
+
76
+ // Extract owner/repo from expected repo URL
77
+ const expectedMatch = expectedRepoUrl.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)\/?$/);
78
+ if (!expectedMatch) {
79
+ return { valid: true, mismatch: false, error: null };
80
+ }
81
+
82
+ const expectedOwner = expectedMatch[1];
83
+ const expectedRepo = expectedMatch[2];
84
+
85
+ // Check if PR belongs to expected repository
86
+ if (prInfo.owner !== expectedOwner || prInfo.repo !== expectedRepo) {
87
+ return {
88
+ valid: false,
89
+ mismatch: true,
90
+ error: `PR from ${prInfo.owner}/${prInfo.repo} does not match expected ${expectedOwner}/${expectedRepo}`
91
+ };
92
+ }
93
+
94
+ return { valid: true, mismatch: false, error: null };
95
+ }
96
+
97
+ /**
98
+ * Get comprehensive PR info including state, merge conflicts, and CI status
99
+ * @param {string} prUrl - GitHub PR URL
100
+ * @returns {Promise<Object|null>} PR info or null if unavailable
101
+ */
102
+ export async function getPrInfo(prUrl) {
103
+ if (!(await isGhAvailable())) return null;
104
+
105
+ try {
106
+ // First fetch basic PR info (this should always work)
107
+ const { stdout: basicStdout } = await execAsync(
108
+ `gh pr view "${prUrl}" --json state,mergedAt,mergeable,isDraft,title`
109
+ );
110
+ const data = JSON.parse(basicStdout);
111
+
112
+ // Determine PR state
113
+ let state = data.state.toLowerCase();
114
+ if (data.mergedAt) state = 'merged';
115
+ else if (data.isDraft) state = 'draft';
116
+
117
+ // Check for merge conflicts
118
+ // mergeable can be: 'MERGEABLE', 'CONFLICTING', 'UNKNOWN'
119
+ const hasMergeConflicts = data.mergeable === 'CONFLICTING';
120
+
121
+ // Try to fetch CI status separately (may fail due to token permissions)
122
+ let ciStatus = null;
123
+ let ciFailures = [];
124
+
125
+ try {
126
+ const { stdout: ciStdout } = await execAsync(
127
+ `gh pr view "${prUrl}" --json statusCheckRollup`
128
+ );
129
+ const ciData = JSON.parse(ciStdout);
130
+ const checks = ciData.statusCheckRollup || [];
131
+
132
+ if (checks.length > 0) {
133
+ // Get failed checks with their names
134
+ const failedChecks = checks.filter(
135
+ (c) => c.conclusion === 'FAILURE' || c.conclusion === 'TIMED_OUT'
136
+ );
137
+ ciFailures = failedChecks.map((c) => c.name || c.context || 'Unknown check');
138
+
139
+ // Determine overall CI status
140
+ const hasPending = checks.some(
141
+ (c) => c.status === 'IN_PROGRESS' || c.status === 'QUEUED' || c.status === 'PENDING'
142
+ );
143
+
144
+ if (failedChecks.length > 0) {
145
+ ciStatus = 'failure';
146
+ } else if (hasPending) {
147
+ ciStatus = 'pending';
148
+ } else {
149
+ ciStatus = 'success';
150
+ }
151
+ }
152
+ } catch (ciError) {
153
+ // CI status unavailable (likely token permissions) - continue without it
154
+ console.warn('[ghService] CI status unavailable:', ciError.message);
155
+ }
156
+
157
+ return {
158
+ state,
159
+ merged: Boolean(data.mergedAt),
160
+ hasMergeConflicts,
161
+ ciStatus,
162
+ ciFailures,
163
+ title: data.title || null,
164
+ };
165
+ } catch (error) {
166
+ console.warn('[ghService] Failed to get PR info:', error.message);
167
+ return null;
168
+ }
169
+ }