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,249 @@
1
+ import { extname } from 'path';
2
+ import { broadcastToSession } from '../websocket.js';
3
+ import { WS_MESSAGE_TYPES } from '../../../shared/src/index.js';
4
+
5
+ // Common MIME type constants
6
+ const MIME_TEXT_PLAIN = 'text/plain';
7
+ const MIME_TEXT_MARKDOWN = 'text/markdown';
8
+
9
+ // Map file extensions to MIME types for binary files (images/PDF)
10
+ export const MIME_TYPES = {
11
+ '.png': 'image/png',
12
+ '.jpg': 'image/jpeg',
13
+ '.jpeg': 'image/jpeg',
14
+ '.gif': 'image/gif',
15
+ '.webp': 'image/webp',
16
+ '.svg': 'image/svg+xml',
17
+ '.bmp': 'image/bmp',
18
+ '.ico': 'image/x-icon',
19
+ '.pdf': 'application/pdf',
20
+ };
21
+
22
+ // Text-based file extensions mapped to MIME types
23
+ export const TEXT_EXTENSIONS = {
24
+ // Code files
25
+ '.js': 'text/javascript',
26
+ '.mjs': 'text/javascript',
27
+ '.cjs': 'text/javascript',
28
+ '.ts': 'text/typescript',
29
+ '.mts': 'text/typescript',
30
+ '.cts': 'text/typescript',
31
+ '.jsx': 'text/javascript',
32
+ '.tsx': 'text/typescript',
33
+ '.py': 'text/x-python',
34
+ '.rb': 'text/x-ruby',
35
+ '.go': 'text/x-go',
36
+ '.rs': 'text/x-rust',
37
+ '.java': 'text/x-java',
38
+ '.c': 'text/x-c',
39
+ '.cpp': 'text/x-c++',
40
+ '.h': 'text/x-c',
41
+ '.hpp': 'text/x-c++',
42
+ '.cs': 'text/x-csharp',
43
+ '.php': 'text/x-php',
44
+ '.swift': 'text/x-swift',
45
+ '.kt': 'text/x-kotlin',
46
+ '.scala': 'text/x-scala',
47
+ '.sh': 'text/x-shellscript',
48
+ '.bash': 'text/x-shellscript',
49
+ '.zsh': 'text/x-shellscript',
50
+ '.sql': 'text/x-sql',
51
+ '.html': 'text/html',
52
+ '.htm': 'text/html',
53
+ '.css': 'text/css',
54
+ '.scss': 'text/x-scss',
55
+ '.sass': 'text/x-sass',
56
+ '.less': 'text/x-less',
57
+ '.vue': 'text/x-vue',
58
+ '.svelte': 'text/x-svelte',
59
+ // Config/data files
60
+ '.yaml': 'text/yaml',
61
+ '.yml': 'text/yaml',
62
+ '.toml': 'text/x-toml',
63
+ '.xml': 'text/xml',
64
+ '.ini': MIME_TEXT_PLAIN,
65
+ '.cfg': MIME_TEXT_PLAIN,
66
+ '.conf': MIME_TEXT_PLAIN,
67
+ '.env': MIME_TEXT_PLAIN,
68
+ '.properties': MIME_TEXT_PLAIN,
69
+ // Special files
70
+ '.gitignore': MIME_TEXT_PLAIN,
71
+ '.dockerignore': MIME_TEXT_PLAIN,
72
+ '.editorconfig': MIME_TEXT_PLAIN,
73
+ '.prettierrc': MIME_TEXT_PLAIN,
74
+ '.eslintrc': MIME_TEXT_PLAIN,
75
+ // Markdown
76
+ '.md': MIME_TEXT_MARKDOWN,
77
+ '.mdx': MIME_TEXT_MARKDOWN,
78
+ '.markdown': MIME_TEXT_MARKDOWN,
79
+ // Plain text
80
+ '.txt': MIME_TEXT_PLAIN,
81
+ '.log': MIME_TEXT_PLAIN,
82
+ '.csv': 'text/csv',
83
+ // JSON
84
+ '.json': 'application/json',
85
+ '.jsonc': 'application/json',
86
+ '.json5': 'application/json',
87
+ };
88
+
89
+ /**
90
+ * Check if a buffer contains binary content by looking for null bytes
91
+ * @param {Buffer} buffer - The buffer to check
92
+ * @returns {boolean} True if binary content detected
93
+ */
94
+ export function isBinaryContent(buffer) {
95
+ // Check first 8KB for null bytes (common indicator of binary content)
96
+ const checkLength = Math.min(buffer.length, 8192);
97
+ for (let i = 0; i < checkLength; i++) {
98
+ if (buffer[i] === 0) return true;
99
+ }
100
+ return false;
101
+ }
102
+
103
+ /**
104
+ * Determine canvas type from file extension
105
+ * @param {string} ext - The file extension (with leading dot)
106
+ * @returns {string|null} The canvas type or null if unknown
107
+ */
108
+ export function getTypeFromExtension(ext) {
109
+ if (MIME_TYPES[ext]) {
110
+ return ext === '.pdf' ? 'pdf' : 'image';
111
+ }
112
+ if (ext === '.json' || ext === '.jsonc' || ext === '.json5') {
113
+ return 'json';
114
+ }
115
+ if (ext === '.md' || ext === '.mdx' || ext === '.markdown') {
116
+ return 'markdown';
117
+ }
118
+ if (TEXT_EXTENSIONS[ext]) {
119
+ return 'code';
120
+ }
121
+ return null; // Unknown, will try binary detection
122
+ }
123
+
124
+ /**
125
+ * Get MIME type for a canvas type
126
+ * @param {string} type - The canvas type (text, markdown, code, json)
127
+ * @returns {string} The MIME type
128
+ */
129
+ function getMimeTypeForType(type) {
130
+ switch (type) {
131
+ case 'text':
132
+ return MIME_TEXT_PLAIN;
133
+ case 'markdown':
134
+ return MIME_TEXT_MARKDOWN;
135
+ case 'code':
136
+ return MIME_TEXT_PLAIN;
137
+ case 'json':
138
+ return 'application/json';
139
+ default:
140
+ return MIME_TEXT_PLAIN;
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Process a file buffer and build canvas item data.
146
+ * Handles type detection, binary vs text classification, and data encoding.
147
+ * @param {Buffer} fileBuffer - The file contents as a buffer
148
+ * @param {string} itemFilename - The filename for the canvas item
149
+ * @returns {{ error: string } | { itemData: object }} Result with either error or itemData
150
+ */
151
+ export function processFileBuffer(fileBuffer, itemFilename) {
152
+ const ext = extname(itemFilename).toLowerCase();
153
+ let detectedType = getTypeFromExtension(ext);
154
+ let detectedMimeType = MIME_TYPES[ext] || TEXT_EXTENSIONS[ext];
155
+
156
+ // For unknown extensions, detect if binary or text
157
+ if (!detectedType) {
158
+ if (isBinaryContent(fileBuffer)) {
159
+ return {
160
+ error: `Unsupported binary file format: ${ext}. Supported binary formats: ${Object.keys(MIME_TYPES).join(', ')}`
161
+ };
162
+ }
163
+ // It's a text file with unknown extension, treat as code
164
+ detectedType = 'code';
165
+ detectedMimeType = MIME_TEXT_PLAIN;
166
+ }
167
+
168
+ // Handle binary types (image, pdf)
169
+ if (detectedType === 'image' || detectedType === 'pdf') {
170
+ const base64 = fileBuffer.toString('base64');
171
+ return {
172
+ itemData: {
173
+ type: detectedType,
174
+ data: base64,
175
+ mimeType: detectedMimeType,
176
+ filename: itemFilename,
177
+ }
178
+ };
179
+ }
180
+
181
+ // Handle text-based types (code, markdown, json)
182
+ const textContent = fileBuffer.toString('utf-8');
183
+ return {
184
+ itemData: {
185
+ type: detectedType,
186
+ content: detectedType === 'json' ? null : textContent,
187
+ data: detectedType === 'json' ? textContent : null,
188
+ mimeType: detectedMimeType,
189
+ filename: itemFilename,
190
+ }
191
+ };
192
+ }
193
+
194
+ export const VALID_INLINE_TYPES = ['text', 'markdown', 'code', 'json'];
195
+
196
+ /**
197
+ * Validate that the given type is valid for inline canvas content.
198
+ * @param {string} type - The canvas type to validate
199
+ * @returns {string|null} Error message if invalid, null if valid
200
+ */
201
+ export function validateInlineType(type) {
202
+ if (!VALID_INLINE_TYPES.includes(type)) {
203
+ return `Invalid type for inline content: ${type}. Valid types: ${VALID_INLINE_TYPES.join(', ')}`;
204
+ }
205
+ return null;
206
+ }
207
+
208
+ /**
209
+ * Build canvas item data from inline content.
210
+ * @param {string} type - The canvas type
211
+ * @param {string} content - The content string
212
+ * @param {string} itemFilename - The filename
213
+ * @returns {object} The canvas item data
214
+ */
215
+ export function buildInlineItemData(type, content, itemFilename) {
216
+ return {
217
+ type,
218
+ content: type === 'json' ? null : content,
219
+ data: type === 'json' ? content : null,
220
+ mimeType: getMimeTypeForType(type),
221
+ filename: itemFilename,
222
+ };
223
+ }
224
+
225
+ /**
226
+ * Broadcast a canvas update to all session subscribers.
227
+ * @param {string} sessionId - The session ID
228
+ * @param {object} item - The canvas item to broadcast
229
+ */
230
+ export function broadcastCanvasUpdate(sessionId, item) {
231
+ broadcastToSession(sessionId, WS_MESSAGE_TYPES.CANVAS_ADD, { item });
232
+ }
233
+
234
+ /**
235
+ * Write a canvas item to a file based on its type.
236
+ * @param {Object} item - The canvas item
237
+ * @param {string} filePath - The file path to write to
238
+ */
239
+ export async function writeCanvasItemToFile(item, filePath) {
240
+ const { writeFile } = await import('fs/promises');
241
+ if (item.type === 'image' || item.type === 'pdf') {
242
+ const buffer = Buffer.from(item.data, 'base64');
243
+ await writeFile(filePath, buffer);
244
+ } else if (item.type === 'json') {
245
+ await writeFile(filePath, item.data || item.content || '{}');
246
+ } else {
247
+ await writeFile(filePath, item.content || '');
248
+ }
249
+ }
@@ -0,0 +1,205 @@
1
+ import { Router } from 'express';
2
+ import { sessions, canvasItems } from '../database.js';
3
+ import { broadcastToSession } from '../websocket.js';
4
+ import { WS_MESSAGE_TYPES } from '../../../shared/src/index.js';
5
+
6
+ // Error message constants
7
+ const ERR_SESSION_NOT_FOUND = 'Session not found';
8
+
9
+ const router = Router();
10
+
11
+ // DELETE /api/sessions/:id/canvas/bulk-delete-permanent - Permanently delete multiple items from trash
12
+ // NOTE: This must be defined BEFORE /:id/canvas/:itemId to avoid Express matching it as :itemId = "bulk-delete-permanent"
13
+ router.delete('/:id/canvas/bulk-delete-permanent', (req, res) => {
14
+ const session = sessions.getById(req.params.id);
15
+ if (!session) {
16
+ return res.status(404).json({ error: ERR_SESSION_NOT_FOUND });
17
+ }
18
+
19
+ const { itemIds } = req.body;
20
+ if (!Array.isArray(itemIds)) {
21
+ return res.status(400).json({ error: 'itemIds must be an array' });
22
+ }
23
+
24
+ if (itemIds.length === 0) {
25
+ return res.json({ deletedCount: 0 });
26
+ }
27
+
28
+ // Verify all items are in trash and belong to this session
29
+ for (const itemId of itemIds) {
30
+ const item = canvasItems.getById(itemId);
31
+ if (!item || item.sessionId !== req.params.id) {
32
+ return res.status(404).json({ error: `Item ${itemId} not found in session` });
33
+ }
34
+ if (!item.deletedAt) {
35
+ return res.status(400).json({ error: `Item ${itemId} is not in trash (cannot permanently delete active items)` });
36
+ }
37
+ }
38
+
39
+ // Expand to include all versions of each file
40
+ const expandedIds = canvasItems.expandToAllVersions(itemIds, { deletedOnly: true });
41
+ const deletedCount = canvasItems.permanentDeleteBatch(expandedIds);
42
+
43
+ // Broadcast each deleted item to session subscribers
44
+ expandedIds.forEach(itemId => {
45
+ broadcastToSession(req.params.id, WS_MESSAGE_TYPES.CANVAS_REMOVE, { sessionId: req.params.id, itemId });
46
+ });
47
+
48
+ res.json({ deletedCount, deletedIds: expandedIds });
49
+ });
50
+
51
+ // DELETE /api/sessions/:id/canvas/:itemId - Soft delete canvas item (move to trash)
52
+ router.delete('/:id/canvas/:itemId', (req, res) => {
53
+ const item = canvasItems.getById(req.params.itemId);
54
+ if (!item || item.sessionId !== req.params.id) {
55
+ return res.status(404).json({ error: 'Canvas item not found' });
56
+ }
57
+
58
+ // Soft delete instead of hard delete
59
+ const deletedItem = canvasItems.softDelete(req.params.itemId);
60
+
61
+ // Broadcast to session subscribers
62
+ broadcastToSession(req.params.id, WS_MESSAGE_TYPES.CANVAS_REMOVE, { sessionId: req.params.id, itemId: req.params.itemId });
63
+
64
+ res.json(deletedItem);
65
+ });
66
+
67
+ // GET /api/sessions/:id/canvas-trash - List deleted items in trash
68
+ router.get('/:id/canvas-trash', (req, res) => {
69
+ const session = sessions.getById(req.params.id);
70
+ if (!session) {
71
+ return res.status(404).json({ error: ERR_SESSION_NOT_FOUND });
72
+ }
73
+
74
+ const items = canvasItems.getDeletedBySessionId(req.params.id);
75
+ // Strip content/data from list responses to reduce payload size.
76
+ res.json(items.map(({ content: _content, data: _data, ...meta }) => meta));
77
+ });
78
+
79
+ // POST /api/sessions/:id/canvas/:itemId/recover - Recover a single item from trash
80
+ router.post('/:id/canvas/:itemId/recover', (req, res) => {
81
+ const item = canvasItems.getById(req.params.itemId);
82
+ if (!item || item.sessionId !== req.params.id) {
83
+ return res.status(404).json({ error: 'Canvas item not found' });
84
+ }
85
+ if (!item.deletedAt) {
86
+ return res.status(400).json({ error: 'Item is not deleted' });
87
+ }
88
+
89
+ const recoveredItem = canvasItems.recover(req.params.itemId);
90
+
91
+ // Broadcast recovery - same as add
92
+ broadcastToSession(req.params.id, WS_MESSAGE_TYPES.CANVAS_ADD, { item: recoveredItem });
93
+
94
+ res.json(recoveredItem);
95
+ });
96
+
97
+ // POST /api/sessions/:id/canvas-trash/recover-file/:filename - Recover all versions of a file
98
+ router.post('/:id/canvas-trash/recover-file/:filename', (req, res) => {
99
+ const session = sessions.getById(req.params.id);
100
+ if (!session) {
101
+ return res.status(404).json({ error: ERR_SESSION_NOT_FOUND });
102
+ }
103
+
104
+ const { filename } = req.params;
105
+ canvasItems.recoverByFilename(req.params.id, filename);
106
+ const items = canvasItems.getAllVersionsByFilename(req.params.id, filename);
107
+
108
+ // Broadcast each recovered item
109
+ items.forEach(item => {
110
+ broadcastToSession(req.params.id, WS_MESSAGE_TYPES.CANVAS_ADD, { item });
111
+ });
112
+
113
+ res.json({ recovered: items.length });
114
+ });
115
+
116
+ // DELETE /api/sessions/:id/canvas/:itemId/permanent - Permanently delete from trash
117
+ router.delete('/:id/canvas/:itemId/permanent', (req, res) => {
118
+ const item = canvasItems.getById(req.params.itemId);
119
+ if (!item || item.sessionId !== req.params.id) {
120
+ return res.status(404).json({ error: 'Canvas item not found' });
121
+ }
122
+ if (!item.deletedAt) {
123
+ return res.status(400).json({ error: 'Item must be in trash before permanent deletion' });
124
+ }
125
+
126
+ canvasItems.permanentDelete(req.params.itemId);
127
+ res.status(204).send();
128
+ });
129
+
130
+ // POST /api/sessions/:id/canvas/bulk-delete - Soft delete multiple items
131
+ router.post('/:id/canvas/bulk-delete', (req, res) => {
132
+ const session = sessions.getById(req.params.id);
133
+ if (!session) {
134
+ return res.status(404).json({ error: ERR_SESSION_NOT_FOUND });
135
+ }
136
+
137
+ const { itemIds } = req.body;
138
+ if (!Array.isArray(itemIds)) {
139
+ return res.status(400).json({ error: 'itemIds must be an array' });
140
+ }
141
+
142
+ if (itemIds.length === 0) {
143
+ return res.json({ deletedCount: 0 });
144
+ }
145
+
146
+ // Verify all items belong to this session
147
+ for (const itemId of itemIds) {
148
+ const item = canvasItems.getById(itemId);
149
+ if (!item || item.sessionId !== req.params.id) {
150
+ return res.status(404).json({ error: `Item ${itemId} not found in session` });
151
+ }
152
+ }
153
+
154
+ // Expand to include all versions of each file
155
+ const expandedIds = canvasItems.expandToAllVersions(itemIds, { activeOnly: true });
156
+ const deletedCount = canvasItems.softDeleteBatch(expandedIds);
157
+
158
+ // Broadcast each deleted item to session subscribers
159
+ expandedIds.forEach(itemId => {
160
+ broadcastToSession(req.params.id, WS_MESSAGE_TYPES.CANVAS_REMOVE, { sessionId: req.params.id, itemId });
161
+ });
162
+
163
+ res.json({ deletedCount, deletedIds: expandedIds });
164
+ });
165
+
166
+ // POST /api/sessions/:id/canvas/bulk-recover - Recover multiple items from trash
167
+ router.post('/:id/canvas/bulk-recover', (req, res) => {
168
+ const session = sessions.getById(req.params.id);
169
+ if (!session) {
170
+ return res.status(404).json({ error: ERR_SESSION_NOT_FOUND });
171
+ }
172
+
173
+ const { itemIds } = req.body;
174
+ if (!Array.isArray(itemIds)) {
175
+ return res.status(400).json({ error: 'itemIds must be an array' });
176
+ }
177
+
178
+ if (itemIds.length === 0) {
179
+ return res.json({ recoveredCount: 0 });
180
+ }
181
+
182
+ // Validate all items belong to this session
183
+ for (const itemId of itemIds) {
184
+ const item = canvasItems.getById(itemId);
185
+ if (!item || item.sessionId !== req.params.id) {
186
+ return res.status(404).json({ error: `Item ${itemId} not found in session` });
187
+ }
188
+ }
189
+
190
+ // Expand to include all versions of each file
191
+ const expandedIds = canvasItems.expandToAllVersions(itemIds, { deletedOnly: true });
192
+ const recoveredCount = canvasItems.recoverBatch(expandedIds);
193
+
194
+ // Broadcast each recovered item to session subscribers
195
+ expandedIds.forEach(itemId => {
196
+ const item = canvasItems.getById(itemId);
197
+ if (item) {
198
+ broadcastToSession(req.params.id, WS_MESSAGE_TYPES.CANVAS_ADD, { item });
199
+ }
200
+ });
201
+
202
+ res.json({ recoveredCount, recoveredIds: expandedIds });
203
+ });
204
+
205
+ export default router;