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.
- package/package.json +33 -0
- package/packages/server/bin/cli.js +4 -0
- package/packages/server/src/agents/AgentGateway.js +64 -0
- package/packages/server/src/agents/BaseAgent.js +41 -0
- package/packages/server/src/agents/LoggingAgentWrapper.js +73 -0
- package/packages/server/src/agents/adapters/ClaudeCodeAdapter.js +33 -0
- package/packages/server/src/agents/adapters/CodexAdapter.js +26 -0
- package/packages/server/src/agents/types.js +43 -0
- package/packages/server/src/agents/vcr/CassetteStore.js +111 -0
- package/packages/server/src/agents/vcr/VCRAgentAdapter.js +126 -0
- package/packages/server/src/agents/vcr/VCRSummaryWrapper.js +71 -0
- package/packages/server/src/api/canvas-helpers.js +249 -0
- package/packages/server/src/api/canvas-trash-routes.js +205 -0
- package/packages/server/src/api/canvas.js +331 -0
- package/packages/server/src/api/commandButtons.js +312 -0
- package/packages/server/src/api/commands.js +169 -0
- package/packages/server/src/api/filesystem.js +62 -0
- package/packages/server/src/api/git.js +85 -0
- package/packages/server/src/api/index.js +44 -0
- package/packages/server/src/api/kanban.js +342 -0
- package/packages/server/src/api/metrics.js +194 -0
- package/packages/server/src/api/projects-helpers.js +43 -0
- package/packages/server/src/api/projects-session-helpers.js +295 -0
- package/packages/server/src/api/projects.js +384 -0
- package/packages/server/src/api/providers.js +249 -0
- package/packages/server/src/api/quickResponses.js +129 -0
- package/packages/server/src/api/sessions-archive.js +69 -0
- package/packages/server/src/api/sessions-commands.js +220 -0
- package/packages/server/src/api/sessions-conversations.js +168 -0
- package/packages/server/src/api/sessions-draft.js +72 -0
- package/packages/server/src/api/sessions-lifecycle.js +190 -0
- package/packages/server/src/api/sessions-messages.js +141 -0
- package/packages/server/src/api/sessions-notes.js +51 -0
- package/packages/server/src/api/sessions-patch.js +252 -0
- package/packages/server/src/api/sessions-streaming.js +86 -0
- package/packages/server/src/api/sessions.js +269 -0
- package/packages/server/src/api/settings.js +194 -0
- package/packages/server/src/api/templates.js +63 -0
- package/packages/server/src/app.js +51 -0
- package/packages/server/src/database.js +58 -0
- package/packages/server/src/db/AgentCallLogRepository.js +322 -0
- package/packages/server/src/db/AttachmentRepository.js +191 -0
- package/packages/server/src/db/BaseRepository.js +39 -0
- package/packages/server/src/db/CanvasItemRepository.js +315 -0
- package/packages/server/src/db/CommandButtonRepository.js +75 -0
- package/packages/server/src/db/CommandRunRepository.js +219 -0
- package/packages/server/src/db/ConversationRepository.js +379 -0
- package/packages/server/src/db/DatabaseManager.js +91 -0
- package/packages/server/src/db/KanbanBoardRepository.js +92 -0
- package/packages/server/src/db/KanbanCardRepository.js +286 -0
- package/packages/server/src/db/KanbanLaneRepository.js +279 -0
- package/packages/server/src/db/MessageRepository.js +156 -0
- package/packages/server/src/db/ProjectDefaultsRepository.js +173 -0
- package/packages/server/src/db/ProjectRepository.js +110 -0
- package/packages/server/src/db/ProviderRepository.js +307 -0
- package/packages/server/src/db/QuickResponseRepository.js +186 -0
- package/packages/server/src/db/SessionNoteRepository.js +60 -0
- package/packages/server/src/db/SessionRepository.js +314 -0
- package/packages/server/src/db/SessionSummaryRepository.js +200 -0
- package/packages/server/src/db/SessionTemplateRepository.js +171 -0
- package/packages/server/src/db/SettingsRepository.js +211 -0
- package/packages/server/src/db/TodoRepository.js +132 -0
- package/packages/server/src/db/WorkLogRepository.js +122 -0
- package/packages/server/src/db/conversation-helpers.js +119 -0
- package/packages/server/src/db/index.js +100 -0
- package/packages/server/src/db/migrations/canvasItemsMigrations.js +109 -0
- package/packages/server/src/db/migrations/conversationsMigrations.js +183 -0
- package/packages/server/src/db/migrations/index.js +199 -0
- package/packages/server/src/db/migrations/kanbanMigrations.js +99 -0
- package/packages/server/src/db/migrations/migrationUtils.js +55 -0
- package/packages/server/src/db/migrations/miscMigrations.js +242 -0
- package/packages/server/src/db/migrations/projectsMigrations.js +95 -0
- package/packages/server/src/db/migrations/sessionsMigrations.js +282 -0
- package/packages/server/src/db/session-helpers.js +150 -0
- package/packages/server/src/index.js +106 -0
- package/packages/server/src/logger.js +22 -0
- package/packages/server/src/middleware/sessionLookup.js +57 -0
- package/packages/server/src/middleware/upload.js +94 -0
- package/packages/server/src/schema.sql +363 -0
- package/packages/server/src/services/agentCallLogger.js +116 -0
- package/packages/server/src/services/canvasStore.js +56 -0
- package/packages/server/src/services/childSessionContext.js +61 -0
- package/packages/server/src/services/commandRunner.js +422 -0
- package/packages/server/src/services/conversationContext.js +72 -0
- package/packages/server/src/services/diffService.js +172 -0
- package/packages/server/src/services/draftSessionService.js +181 -0
- package/packages/server/src/services/encryption.js +134 -0
- package/packages/server/src/services/ghService.js +169 -0
- package/packages/server/src/services/gitService.js +520 -0
- package/packages/server/src/services/gitSessionSetup.js +48 -0
- package/packages/server/src/services/hookService.js +60 -0
- package/packages/server/src/services/kanbanService.js +262 -0
- package/packages/server/src/services/kanbanTriggers.js +273 -0
- package/packages/server/src/services/nodeSpawnHelper.js +63 -0
- package/packages/server/src/services/prStatusService.js +204 -0
- package/packages/server/src/services/prUrlService.js +224 -0
- package/packages/server/src/services/providerTestService.js +81 -0
- package/packages/server/src/services/scheduleService.js +110 -0
- package/packages/server/src/services/schedulerService.js +281 -0
- package/packages/server/src/services/sessionDuplicator.js +63 -0
- package/packages/server/src/services/sessionErrors.js +173 -0
- package/packages/server/src/services/sessionExecution.js +378 -0
- package/packages/server/src/services/sessionManager.js +356 -0
- package/packages/server/src/services/sessionPrompts.js +427 -0
- package/packages/server/src/services/sessionProvider.js +107 -0
- package/packages/server/src/services/slashCommandDiscovery.js +258 -0
- package/packages/server/src/services/slashCommandPluginDiscovery.js +216 -0
- package/packages/server/src/services/slashCommandService.js +306 -0
- package/packages/server/src/services/streamEventCallbacks.js +170 -0
- package/packages/server/src/services/streamEventHandler.js +488 -0
- package/packages/server/src/services/streamUsageHandler.js +228 -0
- package/packages/server/src/services/summaryBroadcast.js +61 -0
- package/packages/server/src/services/summaryClaudeClient.js +180 -0
- package/packages/server/src/services/summaryPrompts.js +169 -0
- package/packages/server/src/services/summaryService.js +552 -0
- package/packages/server/src/services/summaryStaleCheck.js +35 -0
- package/packages/server/src/services/systemMonitor.js +281 -0
- package/packages/server/src/services/templateTriggerService.js +197 -0
- package/packages/server/src/services/terminalOutput.js +160 -0
- package/packages/server/src/services/todoStore.js +58 -0
- package/packages/server/src/services/usageTracker.js +69 -0
- package/packages/server/src/services/withConcurrencyGuard.js +110 -0
- package/packages/server/src/websocket.js +10 -0
- package/packages/server/src/ws/WebSocketManager.js +240 -0
- package/packages/server/src/ws/index.js +50 -0
- package/packages/shared/package.json +27 -0
- package/packages/shared/src/constants.js +44 -0
- package/packages/shared/src/contracts/canvas.js +25 -0
- package/packages/shared/src/contracts/commandButtons.js +36 -0
- package/packages/shared/src/contracts/kanban.js +142 -0
- package/packages/shared/src/contracts/projects.js +63 -0
- package/packages/shared/src/contracts/providers.js +81 -0
- package/packages/shared/src/contracts/quickResponses.js +44 -0
- package/packages/shared/src/contracts/sessions.js +112 -0
- package/packages/shared/src/contracts/templates.js +51 -0
- package/packages/shared/src/index.js +5 -0
- package/packages/shared/src/protocol.js +76 -0
- package/packages/shared/src/routeParams.js +36 -0
- package/packages/shared/src/types.js +167 -0
- package/packages/shared/src/utils.js +101 -0
- package/packages/web/dist/assets/ActiveSessionsView-BQc76Jc8.js +1 -0
- package/packages/web/dist/assets/ActiveSessionsView-ofSvx-K1.css +1 -0
- package/packages/web/dist/assets/AgentLogsView-CTCjHjsu.js +2 -0
- package/packages/web/dist/assets/AgentLogsView-D90PnQVk.css +1 -0
- package/packages/web/dist/assets/ApiClient-Dbs1H78V.js +1 -0
- package/packages/web/dist/assets/ArchiveConfirmModal-CCxSZ52u.js +1 -0
- package/packages/web/dist/assets/ArchiveConfirmModal-CQZeuYBz.css +1 -0
- package/packages/web/dist/assets/CommandButtonDetailView-CF_-LXpU.js +1 -0
- package/packages/web/dist/assets/CommandButtonDetailView-DBm3rzhw.css +1 -0
- package/packages/web/dist/assets/EffortLevelSelector-BQaQmU2d.css +1 -0
- package/packages/web/dist/assets/EffortLevelSelector-DPofLvm-.js +1 -0
- package/packages/web/dist/assets/GeneralSettingsView-BCf53fpC.css +1 -0
- package/packages/web/dist/assets/GeneralSettingsView-BY1G-Kv8.js +1 -0
- package/packages/web/dist/assets/InterpolationHelp-CgdbNcJB.js +1 -0
- package/packages/web/dist/assets/InterpolationHelp-iNxTxmhs.css +1 -0
- package/packages/web/dist/assets/MarkdownEditor-CqT1U8lo.js +2 -0
- package/packages/web/dist/assets/MarkdownEditor-enuH2yvP.css +1 -0
- package/packages/web/dist/assets/ModelSelector-BBn_Ve0D.js +1 -0
- package/packages/web/dist/assets/ModelSelector-DPPD-92R.css +1 -0
- package/packages/web/dist/assets/NewSessionView-Bo5l49nu.js +3 -0
- package/packages/web/dist/assets/NewSessionView-Byoi1XdQ.css +1 -0
- package/packages/web/dist/assets/PathChooser-BoMGzeg2.css +1 -0
- package/packages/web/dist/assets/PathChooser-Cx9gQ-Qt.js +1 -0
- package/packages/web/dist/assets/ProjectEditView-BFuscj-V.js +1 -0
- package/packages/web/dist/assets/ProjectEditView-DNwBUNRk.css +1 -0
- package/packages/web/dist/assets/ProjectListView-C55H1JHQ.css +1 -0
- package/packages/web/dist/assets/ProjectListView-Dj0jBZ46.js +1 -0
- package/packages/web/dist/assets/ProjectNewView-Brdp-xUu.js +1 -0
- package/packages/web/dist/assets/ProjectNewView-CpgE4R-l.css +1 -0
- package/packages/web/dist/assets/ProvidersView-B_QQF3RM.css +1 -0
- package/packages/web/dist/assets/ProvidersView-Cxc-1skq.js +1 -0
- package/packages/web/dist/assets/QuickResponseSettings-B2eVAtHW.js +1 -0
- package/packages/web/dist/assets/QuickResponseSettings-B8188A1D.css +1 -0
- package/packages/web/dist/assets/QuickResponsesPanel-DIBQFj0W.css +1 -0
- package/packages/web/dist/assets/QuickResponsesPanel-lU8pW2B0.js +1 -0
- package/packages/web/dist/assets/ResizableTextarea-B5nAA0RV.css +1 -0
- package/packages/web/dist/assets/ResizableTextarea-DSy1mWGY.js +1 -0
- package/packages/web/dist/assets/SessionCard-BvjLwVYg.js +1 -0
- package/packages/web/dist/assets/SessionCard-D20G3bX8.css +1 -0
- package/packages/web/dist/assets/SessionDetailView-BQbPg-RJ.js +36 -0
- package/packages/web/dist/assets/SessionDetailView-BrMG4p2-.css +1 -0
- package/packages/web/dist/assets/SessionFormOptions-BgqFR-5f.js +1 -0
- package/packages/web/dist/assets/SessionFormOptions-BuLlDF-7.css +1 -0
- package/packages/web/dist/assets/SessionListView-BAIBtJF7.css +1 -0
- package/packages/web/dist/assets/SessionListView-CYIHI8qF.js +1 -0
- package/packages/web/dist/assets/SessionLogStream-B-FwUMJQ.js +18 -0
- package/packages/web/dist/assets/SessionLogStream-zPUTiGbe.css +1 -0
- package/packages/web/dist/assets/SettingsView-DC8-hTQ-.css +1 -0
- package/packages/web/dist/assets/SettingsView-fZxpiGp7.js +1 -0
- package/packages/web/dist/assets/SlashCommandWizard-BB30cSvo.css +1 -0
- package/packages/web/dist/assets/SlashCommandWizard-BgaOw9W3.js +1 -0
- package/packages/web/dist/assets/SummarySettingsView-DcsmSVJI.css +1 -0
- package/packages/web/dist/assets/SummarySettingsView-eeu1Xq86.js +1 -0
- package/packages/web/dist/assets/TemplateDetailView-DEPKSwDo.js +1 -0
- package/packages/web/dist/assets/TemplateDetailView-DT2m06W7.css +1 -0
- package/packages/web/dist/assets/apl-B4CMkyY2.js +1 -0
- package/packages/web/dist/assets/asciiarmor-Df11BRmG.js +1 -0
- package/packages/web/dist/assets/asn1-EdZsLKOL.js +1 -0
- package/packages/web/dist/assets/asterisk-B-8jnY81.js +1 -0
- package/packages/web/dist/assets/brainfuck-C4LP7Hcl.js +1 -0
- package/packages/web/dist/assets/clike-B9uivgTg.js +1 -0
- package/packages/web/dist/assets/clojure-BMjYHr_A.js +1 -0
- package/packages/web/dist/assets/cmake-BQqOBYOt.js +1 -0
- package/packages/web/dist/assets/cobol-CWcv1MsR.js +1 -0
- package/packages/web/dist/assets/coffeescript-S37ZYGWr.js +1 -0
- package/packages/web/dist/assets/commandButtons-DNSHH8IA.js +4 -0
- package/packages/web/dist/assets/commonlisp-DBKNyK5s.js +1 -0
- package/packages/web/dist/assets/crystal-SjHAIU92.js +1 -0
- package/packages/web/dist/assets/css-BnMrqG3P.js +1 -0
- package/packages/web/dist/assets/cypher-C_CwsFkJ.js +1 -0
- package/packages/web/dist/assets/d-pRatUO7H.js +1 -0
- package/packages/web/dist/assets/diff-DbItnlRl.js +1 -0
- package/packages/web/dist/assets/dockerfile-BKs6k2Af.js +1 -0
- package/packages/web/dist/assets/dtd-DF_7sFjM.js +1 -0
- package/packages/web/dist/assets/dylan-DwRh75JA.js +1 -0
- package/packages/web/dist/assets/ebnf-CDyGwa7X.js +1 -0
- package/packages/web/dist/assets/ecl-Cabwm37j.js +1 -0
- package/packages/web/dist/assets/eiffel-CnydiIhH.js +1 -0
- package/packages/web/dist/assets/elm-vLlmbW-K.js +1 -0
- package/packages/web/dist/assets/erlang-BNw1qcRV.js +1 -0
- package/packages/web/dist/assets/factor-kuTfRLto.js +1 -0
- package/packages/web/dist/assets/fcl-Kvtd6kyn.js +1 -0
- package/packages/web/dist/assets/forth-Ffai-XNe.js +1 -0
- package/packages/web/dist/assets/fortran-DYz_wnZ1.js +1 -0
- package/packages/web/dist/assets/gas-Bneqetm1.js +1 -0
- package/packages/web/dist/assets/gherkin-heZmZLOM.js +1 -0
- package/packages/web/dist/assets/groovy-D9Dt4D0W.js +1 -0
- package/packages/web/dist/assets/haskell-BWDZoCOh.js +1 -0
- package/packages/web/dist/assets/haxe-H-WmDvRZ.js +1 -0
- package/packages/web/dist/assets/http-DBlCnlav.js +1 -0
- package/packages/web/dist/assets/idl-BEugSyMb.js +1 -0
- package/packages/web/dist/assets/index-BZlHgDSz.js +1 -0
- package/packages/web/dist/assets/index-BhWX8AfE.js +2 -0
- package/packages/web/dist/assets/index-Bi3XvF_f.js +1 -0
- package/packages/web/dist/assets/index-BqXoPf_D.js +1 -0
- package/packages/web/dist/assets/index-CAuTOZSD.js +1 -0
- package/packages/web/dist/assets/index-CKYk-fkb.js +1 -0
- package/packages/web/dist/assets/index-CTumW_tV.js +318 -0
- package/packages/web/dist/assets/index-CVOJVSsC.js +82 -0
- package/packages/web/dist/assets/index-CXK2Z3_z.js +1 -0
- package/packages/web/dist/assets/index-CYllQ3Vd.js +1 -0
- package/packages/web/dist/assets/index-CpsfI08O.js +1 -0
- package/packages/web/dist/assets/index-DQkhDeTA.js +3 -0
- package/packages/web/dist/assets/index-DWP8iCBp.js +1 -0
- package/packages/web/dist/assets/index-DkVb9W_J.js +1 -0
- package/packages/web/dist/assets/index-DmKHPbIa.js +1 -0
- package/packages/web/dist/assets/index-DrlQi03X.js +1 -0
- package/packages/web/dist/assets/index-gmCCsCQ1.css +1 -0
- package/packages/web/dist/assets/index-prTEzzgO.js +1 -0
- package/packages/web/dist/assets/index-wqgejMCM.js +1 -0
- package/packages/web/dist/assets/index-yh0ZHIWw.js +7 -0
- package/packages/web/dist/assets/javascript-qCveANmP.js +1 -0
- package/packages/web/dist/assets/julia-DuME0IfC.js +1 -0
- package/packages/web/dist/assets/livescript-BwQOo05w.js +1 -0
- package/packages/web/dist/assets/lua-BgMRiT3U.js +1 -0
- package/packages/web/dist/assets/mathematica-DTrFuWx2.js +1 -0
- package/packages/web/dist/assets/mbox-CNhZ1qSd.js +1 -0
- package/packages/web/dist/assets/mirc-CjQqDB4T.js +1 -0
- package/packages/web/dist/assets/mllike-CXdrOF99.js +1 -0
- package/packages/web/dist/assets/modelica-Dc1JOy9r.js +1 -0
- package/packages/web/dist/assets/mscgen-BA5vi2Kp.js +1 -0
- package/packages/web/dist/assets/mumps-BT43cFF4.js +1 -0
- package/packages/web/dist/assets/nginx-DdIZxoE0.js +1 -0
- package/packages/web/dist/assets/nsis-LdVXkNf5.js +1 -0
- package/packages/web/dist/assets/ntriples-BfvgReVJ.js +1 -0
- package/packages/web/dist/assets/octave-Ck1zUtKM.js +1 -0
- package/packages/web/dist/assets/oz-BzwKVEFT.js +1 -0
- package/packages/web/dist/assets/pascal--L3eBynH.js +1 -0
- package/packages/web/dist/assets/perl-CdXCOZ3F.js +1 -0
- package/packages/web/dist/assets/pig-CevX1Tat.js +1 -0
- package/packages/web/dist/assets/powershell-CFHJl5sT.js +1 -0
- package/packages/web/dist/assets/projects-DbBQQH-V.js +1 -0
- package/packages/web/dist/assets/properties-C78fOPTZ.js +1 -0
- package/packages/web/dist/assets/protobuf-ChK-085T.js +1 -0
- package/packages/web/dist/assets/providers-ceCc4xRU.js +1 -0
- package/packages/web/dist/assets/pug-DukmZTjD.js +1 -0
- package/packages/web/dist/assets/puppet-DMA9R1ak.js +1 -0
- package/packages/web/dist/assets/python-BuPzkPfP.js +1 -0
- package/packages/web/dist/assets/q-pXgVlZs6.js +1 -0
- package/packages/web/dist/assets/r-DUYO_cvP.js +1 -0
- package/packages/web/dist/assets/rpm-CTu-6PCP.js +1 -0
- package/packages/web/dist/assets/ruby-B2Rjki9n.js +1 -0
- package/packages/web/dist/assets/sas-B4kiWyti.js +1 -0
- package/packages/web/dist/assets/scheme-C41bIUwD.js +1 -0
- package/packages/web/dist/assets/sessions-D681M81k.js +1 -0
- package/packages/web/dist/assets/settings-D0evez2V.js +1 -0
- package/packages/web/dist/assets/shell-CjFT_Tl9.js +1 -0
- package/packages/web/dist/assets/sieve-C3Gn_uJK.js +1 -0
- package/packages/web/dist/assets/simple-mode-GW_nhZxv.js +1 -0
- package/packages/web/dist/assets/smalltalk-CnHTOXQT.js +1 -0
- package/packages/web/dist/assets/solr-DehyRSwq.js +1 -0
- package/packages/web/dist/assets/sparql-DkYu6x3z.js +1 -0
- package/packages/web/dist/assets/spreadsheet-BCZA_wO0.js +1 -0
- package/packages/web/dist/assets/sql-D0XecflT.js +1 -0
- package/packages/web/dist/assets/stex-C3f8Ysf7.js +1 -0
- package/packages/web/dist/assets/style-BTin-zR_.css +1 -0
- package/packages/web/dist/assets/stylus-B533Al4x.js +1 -0
- package/packages/web/dist/assets/swift-BzpIVaGY.js +1 -0
- package/packages/web/dist/assets/tcl-DVfN8rqt.js +1 -0
- package/packages/web/dist/assets/textile-CnDTJFAw.js +1 -0
- package/packages/web/dist/assets/tiddlywiki-DO-Gjzrf.js +1 -0
- package/packages/web/dist/assets/tiki-DGYXhP31.js +1 -0
- package/packages/web/dist/assets/toml-Bm5Em-hy.js +1 -0
- package/packages/web/dist/assets/troff-wAsdV37c.js +1 -0
- package/packages/web/dist/assets/ttcn-CfJYG6tj.js +1 -0
- package/packages/web/dist/assets/ttcn-cfg-B9xdYoR4.js +1 -0
- package/packages/web/dist/assets/turtle-B1tBg_DP.js +1 -0
- package/packages/web/dist/assets/vb-CmGdzxic.js +1 -0
- package/packages/web/dist/assets/vbscript-BuJXcnF6.js +1 -0
- package/packages/web/dist/assets/velocity-D8B20fx6.js +1 -0
- package/packages/web/dist/assets/verilog-C6RDOZhf.js +1 -0
- package/packages/web/dist/assets/vhdl-lSbBsy5d.js +1 -0
- package/packages/web/dist/assets/webidl-ZXfAyPTL.js +1 -0
- package/packages/web/dist/assets/xquery-CQfU5ijd.js +1 -0
- package/packages/web/dist/assets/yacas-BJ4BC0dw.js +1 -0
- package/packages/web/dist/assets/z80-Hz9HOZM7.js +1 -0
- package/packages/web/dist/favicon.png +0 -0
- package/packages/web/dist/index.html +17 -0
- package/packages/web/dist/logo.png +0 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helpers for SessionRepository: SQL fragments, row mappers,
|
|
3
|
+
* config parsing, and update-clause builders.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** Reusable SQL fragment for computed activity fields on sessions */
|
|
7
|
+
export const ACTIVITY_FIELDS_SQL = `
|
|
8
|
+
(SELECT MAX(cm.timestamp) FROM conversation_messages cm WHERE cm.session_id = s.id) AS last_activity_at,
|
|
9
|
+
(CAST(
|
|
10
|
+
CASE
|
|
11
|
+
WHEN (SELECT MAX(cm2.timestamp) FROM conversation_messages cm2 WHERE cm2.session_id = s.id) IS NOT NULL
|
|
12
|
+
THEN (SELECT MAX(cm2.timestamp) FROM conversation_messages cm2 WHERE cm2.session_id = s.id)
|
|
13
|
+
- (SELECT MIN(cm2.timestamp) FROM conversation_messages cm2 WHERE cm2.session_id = s.id)
|
|
14
|
+
ELSE 0
|
|
15
|
+
END AS INTEGER)
|
|
16
|
+
) AS active_time_ms`;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Map token-usage columns from a DB row to a JS object.
|
|
20
|
+
* @param {Object} row - database row
|
|
21
|
+
* @returns {Object}
|
|
22
|
+
*/
|
|
23
|
+
export function mapTokenUsage(row) {
|
|
24
|
+
return {
|
|
25
|
+
inputTokens: row.input_tokens || 0,
|
|
26
|
+
outputTokens: row.output_tokens || 0,
|
|
27
|
+
cacheReadInputTokens: row.cache_read_input_tokens || 0,
|
|
28
|
+
cacheCreationInputTokens: row.cache_creation_input_tokens || 0,
|
|
29
|
+
webSearchRequests: row.web_search_requests || 0,
|
|
30
|
+
contextWindow: row.context_window || 200000,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Map scheduling columns from a DB row to a JS object.
|
|
36
|
+
* @param {Object} row - database row
|
|
37
|
+
* @returns {Object}
|
|
38
|
+
*/
|
|
39
|
+
export function mapScheduling(row) {
|
|
40
|
+
return {
|
|
41
|
+
scheduledAt: row.scheduled_at || null,
|
|
42
|
+
rescheduleDelayMinutes: row.reschedule_delay_minutes || 15,
|
|
43
|
+
autoRescheduleEnabled: Boolean(row.auto_reschedule_enabled),
|
|
44
|
+
rescheduleOnTokenLimit: Boolean(row.reschedule_on_token_limit),
|
|
45
|
+
rescheduleOnServiceError: Boolean(row.reschedule_on_service_error),
|
|
46
|
+
maxRescheduleCount: row.max_reschedule_count,
|
|
47
|
+
maxTotalTokens: row.max_total_tokens,
|
|
48
|
+
rescheduleCount: row.reschedule_count || 0,
|
|
49
|
+
rescheduleAtTokenCount: row.reschedule_at_token_count,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Default values for session-create config fields */
|
|
54
|
+
const CONFIG_DEFAULTS = {
|
|
55
|
+
mode: 'standard',
|
|
56
|
+
thinkingEnabled: false,
|
|
57
|
+
gitBranch: null,
|
|
58
|
+
parentSessionId: null,
|
|
59
|
+
status: 'starting',
|
|
60
|
+
model: null,
|
|
61
|
+
effortLevel: null,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
function buildConfig(src) {
|
|
65
|
+
return Object.fromEntries(
|
|
66
|
+
Object.entries(CONFIG_DEFAULTS).map(([k, d]) => [k, src[k] ?? d])
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Parse session-create options supporting both the modern object form
|
|
72
|
+
* and the legacy positional-arguments form.
|
|
73
|
+
* @param {Object|string} options
|
|
74
|
+
* @param {Array} extraArgs - additional positional arguments (legacy)
|
|
75
|
+
* @returns {Object} normalised config
|
|
76
|
+
*/
|
|
77
|
+
export function parseCreateConfig(options, extraArgs) {
|
|
78
|
+
if (typeof options !== 'string') return buildConfig(options);
|
|
79
|
+
|
|
80
|
+
const keys = ['mode', 'thinkingEnabled', 'gitBranch', 'parentSessionId', 'status', 'model'];
|
|
81
|
+
const vals = { mode: options };
|
|
82
|
+
keys.slice(1).forEach((k, i) => { vals[k] = extraArgs[i]; });
|
|
83
|
+
vals.effortLevel = (extraArgs[5] || {}).effortLevel;
|
|
84
|
+
return buildConfig(vals);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** camelCase -> snake_case column mapping for direct (non-boolean) fields */
|
|
88
|
+
export const DIRECT_FIELD_MAP = {
|
|
89
|
+
name: 'name',
|
|
90
|
+
status: 'status',
|
|
91
|
+
mode: 'mode',
|
|
92
|
+
gitBranch: 'git_branch',
|
|
93
|
+
gitWorktree: 'git_worktree',
|
|
94
|
+
prUrl: 'pr_url',
|
|
95
|
+
error: 'error',
|
|
96
|
+
costUsd: 'cost_usd',
|
|
97
|
+
claudeSessionId: 'claude_session_id',
|
|
98
|
+
model: 'model',
|
|
99
|
+
nextTemplateId: 'next_template_id',
|
|
100
|
+
parentSessionId: 'parent_session_id',
|
|
101
|
+
scheduledAt: 'scheduled_at',
|
|
102
|
+
rescheduleDelayMinutes: 'reschedule_delay_minutes',
|
|
103
|
+
maxRescheduleCount: 'max_reschedule_count',
|
|
104
|
+
maxTotalTokens: 'max_total_tokens',
|
|
105
|
+
rescheduleCount: 'reschedule_count',
|
|
106
|
+
rescheduleAtTokenCount: 'reschedule_at_token_count',
|
|
107
|
+
pendingPrompt: 'pending_prompt',
|
|
108
|
+
pendingModel: 'pending_model',
|
|
109
|
+
effortLevel: 'effort_level',
|
|
110
|
+
targetLaneId: 'target_lane_id',
|
|
111
|
+
laneTriggerDepth: 'lane_trigger_depth',
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
/** camelCase -> snake_case column mapping for boolean fields (converted to 1/0) */
|
|
115
|
+
export const BOOLEAN_FIELD_MAP = {
|
|
116
|
+
thinkingEnabled: 'thinking_enabled',
|
|
117
|
+
archived: 'archived',
|
|
118
|
+
starred: 'starred',
|
|
119
|
+
manuallyNamed: 'manually_named',
|
|
120
|
+
autoRescheduleEnabled: 'auto_reschedule_enabled',
|
|
121
|
+
rescheduleOnTokenLimit: 'reschedule_on_token_limit',
|
|
122
|
+
rescheduleOnServiceError: 'reschedule_on_service_error',
|
|
123
|
+
autoSendPendingPrompt: 'auto_send_pending_prompt',
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Build SET clause entries and parameter values from update data.
|
|
128
|
+
* @param {Object} data - camelCase update fields
|
|
129
|
+
* @returns {{ updates: string[], values: any[] }}
|
|
130
|
+
*/
|
|
131
|
+
export function buildUpdateClauses(data) {
|
|
132
|
+
const updates = [];
|
|
133
|
+
const values = [];
|
|
134
|
+
|
|
135
|
+
for (const [field, column] of Object.entries(DIRECT_FIELD_MAP)) {
|
|
136
|
+
if (data[field] !== undefined) {
|
|
137
|
+
updates.push(`${column} = ?`);
|
|
138
|
+
values.push(data[field]);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
for (const [field, column] of Object.entries(BOOLEAN_FIELD_MAP)) {
|
|
143
|
+
if (data[field] !== undefined) {
|
|
144
|
+
updates.push(`${column} = ?`);
|
|
145
|
+
values.push(data[field] ? 1 : 0);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return { updates, values };
|
|
150
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { createServer } from 'http';
|
|
2
|
+
import { parseArgs } from 'node:util';
|
|
3
|
+
import { execSync } from 'child_process';
|
|
4
|
+
import { createApp } from './app.js';
|
|
5
|
+
import { initDatabase } from './database.js';
|
|
6
|
+
import { initWebSocket } from './websocket.js';
|
|
7
|
+
import { DEFAULT_SERVER_PORT } from '../../shared/src/index.js';
|
|
8
|
+
import * as prStatusService from './services/prStatusService.js';
|
|
9
|
+
import * as systemMonitor from './services/systemMonitor.js';
|
|
10
|
+
import { schedulerService } from './services/schedulerService.js';
|
|
11
|
+
import * as sessionManager from './services/sessionManager.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Validate Node.js environment at startup.
|
|
15
|
+
* Warns if 'node' is not in PATH (common with nvm/fnm version managers).
|
|
16
|
+
*/
|
|
17
|
+
function validateNodeEnvironment() {
|
|
18
|
+
try {
|
|
19
|
+
execSync('node --version', { stdio: 'ignore' });
|
|
20
|
+
} catch {
|
|
21
|
+
console.warn('');
|
|
22
|
+
console.warn('[Warning] "node" is not found in PATH.');
|
|
23
|
+
console.warn('If using nvm/fnm/volta, ensure your shell is properly configured.');
|
|
24
|
+
console.warn(`Current Node binary: ${process.execPath}`);
|
|
25
|
+
console.warn('This will be used for child processes (Claude Code sessions).');
|
|
26
|
+
console.warn('');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const { values } = parseArgs({
|
|
31
|
+
options: {
|
|
32
|
+
port: {
|
|
33
|
+
type: 'string',
|
|
34
|
+
short: 'p',
|
|
35
|
+
default: String(DEFAULT_SERVER_PORT),
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const port = parseInt(values.port, 10);
|
|
41
|
+
process.env.PORT = String(port);
|
|
42
|
+
const production = process.env.NODE_ENV === 'production';
|
|
43
|
+
const dbPath = process.env.DB_PATH || 'circuschief.db';
|
|
44
|
+
|
|
45
|
+
// Catch uncaught exceptions
|
|
46
|
+
process.on('uncaughtException', (err) => {
|
|
47
|
+
console.error('Uncaught Exception:', err);
|
|
48
|
+
});
|
|
49
|
+
process.on('unhandledRejection', (reason, promise) => {
|
|
50
|
+
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Validate Node.js environment
|
|
54
|
+
validateNodeEnvironment();
|
|
55
|
+
|
|
56
|
+
// Initialize database
|
|
57
|
+
initDatabase(dbPath);
|
|
58
|
+
console.log(`Database initialized: ${dbPath}`);
|
|
59
|
+
|
|
60
|
+
// Create Express app
|
|
61
|
+
const app = createApp({ production });
|
|
62
|
+
|
|
63
|
+
// Create HTTP server
|
|
64
|
+
const server = createServer(app);
|
|
65
|
+
|
|
66
|
+
// Initialize WebSocket for app
|
|
67
|
+
initWebSocket(server);
|
|
68
|
+
|
|
69
|
+
// Initialize and start scheduler service
|
|
70
|
+
schedulerService.initialize(sessionManager);
|
|
71
|
+
schedulerService.start();
|
|
72
|
+
|
|
73
|
+
// Start PR status polling service
|
|
74
|
+
prStatusService.start();
|
|
75
|
+
|
|
76
|
+
// Start system metrics broadcast service
|
|
77
|
+
systemMonitor.start();
|
|
78
|
+
|
|
79
|
+
// Graceful shutdown
|
|
80
|
+
process.on('SIGTERM', () => {
|
|
81
|
+
console.log('SIGTERM received, shutting down gracefully');
|
|
82
|
+
schedulerService.stop();
|
|
83
|
+
prStatusService.stop();
|
|
84
|
+
systemMonitor.stop();
|
|
85
|
+
server.close(() => {
|
|
86
|
+
console.log('Server closed');
|
|
87
|
+
process.exit(0);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
process.on('SIGINT', () => {
|
|
92
|
+
console.log('SIGINT received, shutting down gracefully');
|
|
93
|
+
schedulerService.stop();
|
|
94
|
+
prStatusService.stop();
|
|
95
|
+
systemMonitor.stop();
|
|
96
|
+
server.close(() => {
|
|
97
|
+
console.log('Server closed');
|
|
98
|
+
process.exit(0);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Start server on all interfaces
|
|
103
|
+
server.listen(port, '0.0.0.0', () => {
|
|
104
|
+
console.log(`Server running on http://0.0.0.0:${port}`);
|
|
105
|
+
console.log(`WebSocket available at ws://0.0.0.0:${port}/ws`);
|
|
106
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple logger that respects NODE_ENV
|
|
3
|
+
* Suppresses debug logs during testing
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const logger = {
|
|
7
|
+
log: (...args) => {
|
|
8
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
9
|
+
console.log(...args);
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
error: (...args) => {
|
|
13
|
+
console.error(...args);
|
|
14
|
+
},
|
|
15
|
+
warn: (...args) => {
|
|
16
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
17
|
+
console.warn(...args);
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default logger;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { sessions, projects } from '../database.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Middleware: Look up a session by req.params.id and attach to req.session_.
|
|
5
|
+
* Returns 404 if session not found.
|
|
6
|
+
* Uses session_ to avoid conflict with express-session's req.session.
|
|
7
|
+
*/
|
|
8
|
+
export function requireSession(req, res, next) {
|
|
9
|
+
const session = sessions.getById(req.params.id);
|
|
10
|
+
if (!session) {
|
|
11
|
+
return res.status(404).json({ error: 'Session not found' });
|
|
12
|
+
}
|
|
13
|
+
req.session_ = session;
|
|
14
|
+
next();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Middleware: Look up session AND its project. Attaches req.session_ and req.project.
|
|
19
|
+
* Returns 404 if either is not found.
|
|
20
|
+
* Also resolves req.workingDirectory (gitWorktree || project.workingDirectory).
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Middleware factory: Validates that req.session_.status is one of the allowed statuses.
|
|
24
|
+
* Must be used AFTER requireSession or requireSessionAndProject middleware.
|
|
25
|
+
* @param {string[]} allowedStatuses - Array of allowed status strings
|
|
26
|
+
* @param {string} [errorMessage] - Optional custom error message
|
|
27
|
+
* @returns {Function} Express middleware
|
|
28
|
+
*/
|
|
29
|
+
export function requireSessionStatus(allowedStatuses, errorMessage) {
|
|
30
|
+
return (req, res, next) => {
|
|
31
|
+
if (!req.session_) {
|
|
32
|
+
return res.status(500).json({ error: 'requireSessionStatus must be used after requireSession' });
|
|
33
|
+
}
|
|
34
|
+
if (!allowedStatuses.includes(req.session_.status)) {
|
|
35
|
+
const message = errorMessage || `Session status must be one of: ${allowedStatuses.join(', ')}`;
|
|
36
|
+
return res.status(400).json({ error: message });
|
|
37
|
+
}
|
|
38
|
+
next();
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function requireSessionAndProject(req, res, next) {
|
|
43
|
+
const session = sessions.getById(req.params.id);
|
|
44
|
+
if (!session) {
|
|
45
|
+
return res.status(404).json({ error: 'Session not found' });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const project = projects.getById(session.projectId);
|
|
49
|
+
if (!project) {
|
|
50
|
+
return res.status(404).json({ error: 'Project not found' });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
req.session_ = session;
|
|
54
|
+
req.project = project;
|
|
55
|
+
req.workingDirectory = session.gitWorktree || project.workingDirectory;
|
|
56
|
+
next();
|
|
57
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import multer from 'multer';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Allowed MIME types for file uploads
|
|
5
|
+
*/
|
|
6
|
+
const ALLOWED_MIME_TYPES = [
|
|
7
|
+
// Images
|
|
8
|
+
'image/png',
|
|
9
|
+
'image/jpeg',
|
|
10
|
+
'image/gif',
|
|
11
|
+
'image/webp',
|
|
12
|
+
'image/svg+xml',
|
|
13
|
+
// Text files
|
|
14
|
+
'text/plain',
|
|
15
|
+
'text/markdown',
|
|
16
|
+
'text/csv',
|
|
17
|
+
'text/html',
|
|
18
|
+
'text/css',
|
|
19
|
+
'text/javascript',
|
|
20
|
+
'text/xml',
|
|
21
|
+
// Application types
|
|
22
|
+
'application/json',
|
|
23
|
+
'application/pdf',
|
|
24
|
+
'application/javascript',
|
|
25
|
+
'application/xml',
|
|
26
|
+
'application/x-yaml',
|
|
27
|
+
'application/x-sh',
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* File filter for multer - allows common file types
|
|
32
|
+
*/
|
|
33
|
+
function fileFilter(_req, file, cb) {
|
|
34
|
+
// Allow if MIME type is in allowed list or starts with 'text/'
|
|
35
|
+
if (ALLOWED_MIME_TYPES.includes(file.mimetype) || file.mimetype.startsWith('text/')) {
|
|
36
|
+
cb(null, true);
|
|
37
|
+
} else {
|
|
38
|
+
cb(new Error(`File type ${file.mimetype} not allowed`), false);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Multer configuration for file uploads
|
|
44
|
+
* - Uses memory storage (files are stored in memory as Buffer)
|
|
45
|
+
* - 10MB max file size
|
|
46
|
+
* - Max 10 files per request
|
|
47
|
+
*/
|
|
48
|
+
export const upload = multer({
|
|
49
|
+
storage: multer.memoryStorage(),
|
|
50
|
+
limits: {
|
|
51
|
+
fileSize: 10 * 1024 * 1024, // 10MB per file
|
|
52
|
+
files: 10, // Max 10 files per request
|
|
53
|
+
},
|
|
54
|
+
fileFilter,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Error handler middleware for multer errors
|
|
59
|
+
*/
|
|
60
|
+
export function handleUploadError(err, req, res, next) {
|
|
61
|
+
if (err instanceof multer.MulterError) {
|
|
62
|
+
if (err.code === 'LIMIT_FILE_SIZE') {
|
|
63
|
+
return res.status(400).json({ error: 'File too large. Maximum size is 10MB.' });
|
|
64
|
+
}
|
|
65
|
+
if (err.code === 'LIMIT_FILE_COUNT') {
|
|
66
|
+
return res.status(400).json({ error: 'Too many files. Maximum is 10 files per request.' });
|
|
67
|
+
}
|
|
68
|
+
return res.status(400).json({ error: err.message });
|
|
69
|
+
}
|
|
70
|
+
if (err) {
|
|
71
|
+
return res.status(400).json({ error: err.message });
|
|
72
|
+
}
|
|
73
|
+
next();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Wrapper that makes multer skip processing for non-multipart requests
|
|
78
|
+
* This allows the same route to handle both JSON and multipart/form-data requests
|
|
79
|
+
*/
|
|
80
|
+
export function uploadMiddleware(fieldName, maxCount) {
|
|
81
|
+
return (req, res, next) => {
|
|
82
|
+
// Check if the request is multipart/form-data
|
|
83
|
+
const contentType = req.get('content-type');
|
|
84
|
+
|
|
85
|
+
if (!contentType || !contentType.startsWith('multipart/form-data')) {
|
|
86
|
+
// Not a multipart request, skip multer processing
|
|
87
|
+
req.files = [];
|
|
88
|
+
return next();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Multipart request, use multer to process
|
|
92
|
+
upload.array(fieldName, maxCount)(req, res, next);
|
|
93
|
+
};
|
|
94
|
+
}
|