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,306 @@
|
|
|
1
|
+
import { readFile } from 'fs/promises';
|
|
2
|
+
import {
|
|
3
|
+
parseCommandFile as _parseCommandFile,
|
|
4
|
+
parseSkillFile as _parseSkillFile,
|
|
5
|
+
discoverAllCommands,
|
|
6
|
+
} from './slashCommandDiscovery.js';
|
|
7
|
+
|
|
8
|
+
// Re-export parsing functions so existing consumers continue to work
|
|
9
|
+
export const parseCommandFile = _parseCommandFile;
|
|
10
|
+
export const parseSkillFile = _parseSkillFile;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Get all available slash commands for a working directory
|
|
14
|
+
* Commands are discovered from:
|
|
15
|
+
* 1. Project .claude/commands/ (highest priority)
|
|
16
|
+
* 2. User ~/.claude/commands/
|
|
17
|
+
* 3. Installed plugins
|
|
18
|
+
* 4. Built-in commands (lowest priority)
|
|
19
|
+
*
|
|
20
|
+
* @param {string} workingDirectory - The project working directory
|
|
21
|
+
* @returns {Promise<Array>} Array of command objects
|
|
22
|
+
*/
|
|
23
|
+
export async function getCommands(workingDirectory) {
|
|
24
|
+
return discoverAllCommands(workingDirectory);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get a single command by name
|
|
29
|
+
* @param {string} workingDirectory - The project working directory
|
|
30
|
+
* @param {string} name - Command name
|
|
31
|
+
* @returns {Promise<Object|null>} Command object or null if not found
|
|
32
|
+
*/
|
|
33
|
+
export async function getCommand(workingDirectory, name) {
|
|
34
|
+
const commands = await getCommands(workingDirectory);
|
|
35
|
+
return commands.find(cmd => cmd.name === name) || null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Get the command body content (the actual prompt to send to Claude)
|
|
40
|
+
* @param {string} workingDirectory - The project working directory
|
|
41
|
+
* @param {string} name - Command name
|
|
42
|
+
* @returns {Promise<string|null>} Command body or null if not found/builtin
|
|
43
|
+
*/
|
|
44
|
+
export async function getCommandBody(workingDirectory, name) {
|
|
45
|
+
const command = await getCommand(workingDirectory, name);
|
|
46
|
+
|
|
47
|
+
if (!command) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Built-in commands don't have a body - they're handled by Claude natively
|
|
52
|
+
if (command.source === 'builtin') {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Read and parse the file to get the body
|
|
57
|
+
try {
|
|
58
|
+
const content = await readFile(command.filePath, 'utf-8');
|
|
59
|
+
if (command.isSkill) {
|
|
60
|
+
const parsed = parseSkillFile(content, command.name);
|
|
61
|
+
return parsed.body;
|
|
62
|
+
}
|
|
63
|
+
const parsed = parseCommandFile(content);
|
|
64
|
+
return parsed.body;
|
|
65
|
+
} catch (err) {
|
|
66
|
+
console.error(`Failed to read command body for ${name}:`, err.message);
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Build the command string to send to Claude
|
|
73
|
+
* For built-in commands: "/help", "/compact"
|
|
74
|
+
* For custom commands: "/<name> <args...>" with body content
|
|
75
|
+
*
|
|
76
|
+
* @param {string} workingDirectory - The project working directory
|
|
77
|
+
* @param {string} name - Command name
|
|
78
|
+
* @param {Object} args - Argument values keyed by argument name
|
|
79
|
+
* @returns {Promise<string>} The command string to send
|
|
80
|
+
*/
|
|
81
|
+
export async function buildCommandString(workingDirectory, name, args = {}) {
|
|
82
|
+
const command = await getCommand(workingDirectory, name);
|
|
83
|
+
|
|
84
|
+
if (!command) {
|
|
85
|
+
throw new Error(`Command not found: ${name}`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// For built-in commands, just return the slash command
|
|
89
|
+
if (command.source === 'builtin') {
|
|
90
|
+
return `/${name}`;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// For skills, use different argument substitution
|
|
94
|
+
if (command.isSkill) {
|
|
95
|
+
return buildSkillCommandString(workingDirectory, name, args);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Build argument string for commands
|
|
99
|
+
const argParts = buildArgParts(command, args);
|
|
100
|
+
|
|
101
|
+
// Get command body (the actual prompt content)
|
|
102
|
+
const body = await getCommandBody(workingDirectory, name);
|
|
103
|
+
|
|
104
|
+
// If there's a body, we need to send it as context
|
|
105
|
+
// The body may contain $ARGUMENTS placeholder for arg substitution
|
|
106
|
+
if (body) {
|
|
107
|
+
return substituteCommandArgs(body, command, args, argParts);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Build the full command
|
|
111
|
+
let commandString = `/${name}`;
|
|
112
|
+
if (argParts.length > 0) {
|
|
113
|
+
commandString += ` ${argParts.join(' ')}`;
|
|
114
|
+
}
|
|
115
|
+
return commandString;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Build argument parts array from command definition and provided args
|
|
120
|
+
*/
|
|
121
|
+
function buildArgParts(command, args) {
|
|
122
|
+
const argParts = [];
|
|
123
|
+
for (const argDef of command.arguments) {
|
|
124
|
+
const value = args[argDef.name];
|
|
125
|
+
if (value !== undefined && value !== '') {
|
|
126
|
+
if (typeof value === 'string' && value.includes(' ')) {
|
|
127
|
+
argParts.push(`"${value}"`);
|
|
128
|
+
} else {
|
|
129
|
+
argParts.push(String(value));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return argParts;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Substitute argument placeholders in command body
|
|
138
|
+
*/
|
|
139
|
+
function substituteCommandArgs(body, command, args, argParts) {
|
|
140
|
+
let processedBody = body;
|
|
141
|
+
|
|
142
|
+
// Replace argument placeholders like $environment or ${environment}
|
|
143
|
+
for (const argDef of command.arguments) {
|
|
144
|
+
const value = args[argDef.name] || '';
|
|
145
|
+
processedBody = processedBody
|
|
146
|
+
.replace(new RegExp(`\\$\\{${argDef.name}\\}`, 'g'), value)
|
|
147
|
+
.replace(new RegExp(`\\$${argDef.name}\\b`, 'g'), value);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// If body has $ARGUMENTS, replace with all args
|
|
151
|
+
const allArgsStr = argParts.join(' ');
|
|
152
|
+
processedBody = processedBody
|
|
153
|
+
.replace(/\$\{ARGUMENTS\}/g, allArgsStr)
|
|
154
|
+
.replace(/\$ARGUMENTS\b/g, allArgsStr);
|
|
155
|
+
|
|
156
|
+
return processedBody;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Process $ARGUMENTS and positional args in a skill body
|
|
161
|
+
*/
|
|
162
|
+
function substituteSkillArgs(body, rawArgs) {
|
|
163
|
+
let processedBody = body;
|
|
164
|
+
|
|
165
|
+
// Replace $ARGUMENTS with raw args string
|
|
166
|
+
processedBody = processedBody
|
|
167
|
+
.replace(/\$\{ARGUMENTS\}/g, rawArgs)
|
|
168
|
+
.replace(/\$ARGUMENTS\b/g, rawArgs);
|
|
169
|
+
|
|
170
|
+
// Replace positional args $0, $1, $2, etc.
|
|
171
|
+
const argParts = rawArgs.split(/\s+/).filter(Boolean);
|
|
172
|
+
for (let i = 0; i < argParts.length; i++) {
|
|
173
|
+
processedBody = processedBody
|
|
174
|
+
.replace(new RegExp(`\\$\\{${i}\\}`, 'g'), argParts[i])
|
|
175
|
+
.replace(new RegExp(`\\$${i}\\b`, 'g'), argParts[i]);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return processedBody;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Build a command string for a skill invocation
|
|
183
|
+
*/
|
|
184
|
+
async function buildSkillCommandString(workingDirectory, name, args) {
|
|
185
|
+
const body = await getCommandBody(workingDirectory, name);
|
|
186
|
+
if (!body) return `/${name}`;
|
|
187
|
+
const rawArgs = args._raw || '';
|
|
188
|
+
return substituteSkillArgs(body, rawArgs);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Build a structured skill invocation, separating skill content (for system prompt)
|
|
193
|
+
* from user arguments (for user message).
|
|
194
|
+
*
|
|
195
|
+
* Returns null if the command is not a skill or not found.
|
|
196
|
+
*
|
|
197
|
+
* @param {string} workingDirectory - The project working directory
|
|
198
|
+
* @param {string} name - Skill name
|
|
199
|
+
* @param {Object} args - Arguments object, with _raw for the raw argument string
|
|
200
|
+
* @returns {Promise<{skillContent: string, userMessage: string|null, skillName: string}|null>}
|
|
201
|
+
*/
|
|
202
|
+
export async function buildSkillInvocation(workingDirectory, name, args = {}) {
|
|
203
|
+
const command = await getCommand(workingDirectory, name);
|
|
204
|
+
if (!command || !command.isSkill) return null;
|
|
205
|
+
|
|
206
|
+
const body = await getCommandBody(workingDirectory, name);
|
|
207
|
+
if (!body) return null;
|
|
208
|
+
|
|
209
|
+
const rawArgs = args._raw || '';
|
|
210
|
+
|
|
211
|
+
return {
|
|
212
|
+
skillContent: substituteSkillArgs(body, rawArgs),
|
|
213
|
+
userMessage: rawArgs.trim() || null,
|
|
214
|
+
skillName: name,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Build a system prompt that includes skill content as context.
|
|
220
|
+
*
|
|
221
|
+
* @param {string|null} projectSystemPrompt - The project's custom system prompt
|
|
222
|
+
* @param {{skillContent: string, skillName: string}} skillInvocation - From buildSkillInvocation()
|
|
223
|
+
* @returns {string} Combined system prompt
|
|
224
|
+
*/
|
|
225
|
+
export function buildSkillSystemPrompt(projectSystemPrompt, skillInvocation) {
|
|
226
|
+
const parts = [];
|
|
227
|
+
if (projectSystemPrompt) {
|
|
228
|
+
parts.push(projectSystemPrompt);
|
|
229
|
+
}
|
|
230
|
+
parts.push(`<skill name="${skillInvocation.skillName}">\n${skillInvocation.skillContent}\n</skill>`);
|
|
231
|
+
return parts.join('\n\n');
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Build the user message for a skill invocation.
|
|
236
|
+
*
|
|
237
|
+
* @param {{userMessage: string|null, skillName: string}} skillInvocation - From buildSkillInvocation()
|
|
238
|
+
* @returns {string} User message to send
|
|
239
|
+
*/
|
|
240
|
+
export function buildSkillUserMessage(skillInvocation) {
|
|
241
|
+
return skillInvocation.userMessage
|
|
242
|
+
|| `The user invoked the /${skillInvocation.skillName} skill. Follow the skill instructions above and ask the user what they would like you to build.`;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Detect and resolve a skill or command invocation from a prompt string.
|
|
247
|
+
* Returns null if the prompt is not a recognized skill/command.
|
|
248
|
+
*
|
|
249
|
+
* @param {string} workingDirectory - Project working directory for command discovery
|
|
250
|
+
* @param {string} prompt - The user's prompt text
|
|
251
|
+
* @param {string|null} projectSystemPrompt - The project's system prompt
|
|
252
|
+
* @returns {Promise<{type: 'skill'|'command', userMessage: string, systemPrompt: string|null}|null>}
|
|
253
|
+
*/
|
|
254
|
+
export async function resolvePromptSkillOrCommand(workingDirectory, prompt, projectSystemPrompt) {
|
|
255
|
+
if (!prompt || typeof prompt !== 'string' || !prompt.startsWith('/')) return null;
|
|
256
|
+
|
|
257
|
+
const match = prompt.match(/^\/(\S+)(?:\s+([\s\S]*))?$/);
|
|
258
|
+
if (!match) return null;
|
|
259
|
+
|
|
260
|
+
const [, commandName, rawArgs] = match;
|
|
261
|
+
|
|
262
|
+
// Try skill first -- skills take precedence over commands
|
|
263
|
+
try {
|
|
264
|
+
const skillInvocation = await buildSkillInvocation(
|
|
265
|
+
workingDirectory, commandName, { _raw: rawArgs || '' }
|
|
266
|
+
);
|
|
267
|
+
if (skillInvocation) {
|
|
268
|
+
return {
|
|
269
|
+
type: 'skill',
|
|
270
|
+
userMessage: buildSkillUserMessage(skillInvocation),
|
|
271
|
+
systemPrompt: buildSkillSystemPrompt(projectSystemPrompt, skillInvocation),
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
} catch (err) {
|
|
275
|
+
// Skill lookup failed -- fall through
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Try regular (non-skill) command
|
|
279
|
+
try {
|
|
280
|
+
const commandString = await buildCommandString(workingDirectory, commandName, { _raw: rawArgs || '' });
|
|
281
|
+
if (commandString) {
|
|
282
|
+
return {
|
|
283
|
+
type: 'command',
|
|
284
|
+
userMessage: commandString,
|
|
285
|
+
systemPrompt: projectSystemPrompt || null,
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
} catch (err) {
|
|
289
|
+
// Command not found -- fall through
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export default {
|
|
296
|
+
getCommands,
|
|
297
|
+
getCommand,
|
|
298
|
+
getCommandBody,
|
|
299
|
+
buildCommandString,
|
|
300
|
+
buildSkillInvocation,
|
|
301
|
+
buildSkillSystemPrompt,
|
|
302
|
+
buildSkillUserMessage,
|
|
303
|
+
resolvePromptSkillOrCommand,
|
|
304
|
+
parseCommandFile,
|
|
305
|
+
parseSkillFile,
|
|
306
|
+
};
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { sessions, conversations } from '../database.js';
|
|
2
|
+
import { broadcastToSession } from '../websocket.js';
|
|
3
|
+
import { WS_MESSAGE_TYPES } from '../../../shared/src/index.js';
|
|
4
|
+
import * as summaryService from './summaryService.js';
|
|
5
|
+
import * as kanbanService from './kanbanService.js';
|
|
6
|
+
import {
|
|
7
|
+
lastMessageIds,
|
|
8
|
+
activeSessions,
|
|
9
|
+
activeConversationIds,
|
|
10
|
+
associateAndBroadcastWorkLogs,
|
|
11
|
+
broadcastSessionStatus,
|
|
12
|
+
broadcastChangesUpdate,
|
|
13
|
+
} from './streamEventHandler.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Handle post-turn completion logic (after stream loop ends successfully)
|
|
17
|
+
* Encapsulates the duplicated completion block from runSession/continueSession/continueSessionWithExistingMessage
|
|
18
|
+
* @param {string} sessionId
|
|
19
|
+
* @param {string} workingDirectory
|
|
20
|
+
* @param {{ handleTemplateTriggerIfNeeded?: Function, checkProactiveReschedule?: Function, handleAutoSendIfNeeded?: Function }} callbacks
|
|
21
|
+
*/
|
|
22
|
+
export async function handleTurnCompletion(sessionId, workingDirectory, callbacks = {}) {
|
|
23
|
+
const { handleTemplateTriggerIfNeeded, checkProactiveReschedule: _checkProactiveReschedule, handleAutoSendIfNeeded } = callbacks;
|
|
24
|
+
// Associate work logs with the last message now that the turn is complete
|
|
25
|
+
const lastMessageId = lastMessageIds.get(sessionId);
|
|
26
|
+
if (lastMessageId) {
|
|
27
|
+
associateAndBroadcastWorkLogs(sessionId, lastMessageId);
|
|
28
|
+
lastMessageIds.delete(sessionId);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Session ready for follow-up - set to waiting instead of completed
|
|
32
|
+
const activeSession = activeSessions.get(sessionId);
|
|
33
|
+
if (activeSession && !activeSession.controller?.signal?.aborted) {
|
|
34
|
+
sessions.update(sessionId, { status: 'waiting' });
|
|
35
|
+
broadcastSessionStatus(sessionId, 'waiting');
|
|
36
|
+
|
|
37
|
+
// Check if session should be proactively rescheduled based on token threshold
|
|
38
|
+
if (_checkProactiveReschedule) {
|
|
39
|
+
const wasRescheduled = await _checkProactiveReschedule(sessionId);
|
|
40
|
+
if (wasRescheduled) {
|
|
41
|
+
return true; // Session was rescheduled, don't continue with normal completion
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Extract PR URL immediately (lightweight, no API call)
|
|
46
|
+
summaryService.extractPrUrlIfNeeded(sessionId);
|
|
47
|
+
// Trigger debounced summary generation on turn completion (not complete yet)
|
|
48
|
+
summaryService.onSessionActivity(sessionId);
|
|
49
|
+
|
|
50
|
+
// Broadcast changes update when turn completes (real-time indicator)
|
|
51
|
+
const currentSession = sessions.getById(sessionId);
|
|
52
|
+
if (currentSession) {
|
|
53
|
+
await broadcastChangesUpdate(sessionId, currentSession.projectId, workingDirectory);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Handle kanban lane movements based on targetLaneId
|
|
57
|
+
await kanbanService.handleTurnCompletion(sessionId);
|
|
58
|
+
|
|
59
|
+
// Auto-send queued prompt if enabled (runs BEFORE template trigger)
|
|
60
|
+
let autoSendFired = false;
|
|
61
|
+
if (handleAutoSendIfNeeded) {
|
|
62
|
+
autoSendFired = await handleAutoSendIfNeeded(sessionId);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Only trigger next template if auto-send did NOT fire
|
|
66
|
+
// (if auto-send fired, template will trigger after that turn completes)
|
|
67
|
+
if (!autoSendFired && handleTemplateTriggerIfNeeded) {
|
|
68
|
+
await handleTemplateTriggerIfNeeded(sessionId);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Try to reschedule the session due to an error.
|
|
76
|
+
* Returns true if rescheduled, false otherwise.
|
|
77
|
+
* @param {string} sessionId
|
|
78
|
+
* @param {Error} error
|
|
79
|
+
* @param {Function} shouldRescheduleOnError
|
|
80
|
+
* @param {Object} schedulerService
|
|
81
|
+
* @returns {Promise<boolean>}
|
|
82
|
+
*/
|
|
83
|
+
async function tryRescheduleOnError(sessionId, error, shouldRescheduleOnError, schedulerService) {
|
|
84
|
+
const session = sessions.getById(sessionId);
|
|
85
|
+
if (!session || !shouldRescheduleOnError(session, error, sessionId)) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
const rescheduled = await schedulerService.rescheduleSession(sessionId, error.message);
|
|
89
|
+
if (rescheduled) {
|
|
90
|
+
console.log(`[SessionManager] Session ${sessionId} rescheduled due to error`);
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Broadcast the final conversation state for error handling.
|
|
98
|
+
* @param {string} sessionId
|
|
99
|
+
*/
|
|
100
|
+
function broadcastFinalConversationState(sessionId) {
|
|
101
|
+
const errorConversationId = activeConversationIds.get(sessionId);
|
|
102
|
+
const finalConversation = errorConversationId
|
|
103
|
+
? conversations.getById(errorConversationId)
|
|
104
|
+
: null;
|
|
105
|
+
if (finalConversation) {
|
|
106
|
+
broadcastToSession(sessionId, WS_MESSAGE_TYPES.CONVERSATION_UPDATED, {
|
|
107
|
+
sessionId,
|
|
108
|
+
conversation: finalConversation,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
broadcastSessionStatus(sessionId, 'error');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Safely trigger the template handler, catching any errors.
|
|
116
|
+
* @param {string} sessionId
|
|
117
|
+
* @param {Function} handleTemplateTriggerIfNeeded
|
|
118
|
+
*/
|
|
119
|
+
async function safeTriggerTemplate(sessionId, handleTemplateTriggerIfNeeded) {
|
|
120
|
+
try {
|
|
121
|
+
await handleTemplateTriggerIfNeeded(sessionId);
|
|
122
|
+
} catch (templateError) {
|
|
123
|
+
console.error(`[handleSessionError] Template trigger failed for session ${sessionId}:`, templateError);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Handle session error with optional rescheduling
|
|
129
|
+
* Encapsulates the duplicated error handling block from runSession/continueSession/continueSessionWithExistingMessage
|
|
130
|
+
* @param {string} sessionId
|
|
131
|
+
* @param {Error} error
|
|
132
|
+
* @param {{ controller: AbortController, shouldRescheduleOnError: Function, schedulerService: Object, errorLabel?: string, broadcastConversationState?: boolean, handleTemplateTriggerIfNeeded?: Function }} options
|
|
133
|
+
*/
|
|
134
|
+
export async function handleSessionError(sessionId, error, options = {}) {
|
|
135
|
+
const { controller, shouldRescheduleOnError, schedulerService } = options;
|
|
136
|
+
const errorLabel = options.errorLabel || 'Session error';
|
|
137
|
+
console.error(`${errorLabel}:`, error);
|
|
138
|
+
console.error('Error stack:', error.stack);
|
|
139
|
+
|
|
140
|
+
if (controller.signal.aborted) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Check if we should reschedule instead of marking as error
|
|
145
|
+
const rescheduled = await tryRescheduleOnError(sessionId, error, shouldRescheduleOnError, schedulerService);
|
|
146
|
+
if (rescheduled) {
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Normal error handling (no reschedule or reschedule limits reached)
|
|
151
|
+
sessions.update(sessionId, { status: 'error', error: error.message });
|
|
152
|
+
broadcastToSession(sessionId, WS_MESSAGE_TYPES.SESSION_ERROR, { sessionId, error: error.message });
|
|
153
|
+
|
|
154
|
+
// Optionally broadcast final conversation state (continueSession does this)
|
|
155
|
+
if (options.broadcastConversationState) {
|
|
156
|
+
broadcastFinalConversationState(sessionId);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Extract PR URL before generating summary (PR may have been created before error)
|
|
160
|
+
summaryService.extractPrUrlIfNeeded(sessionId);
|
|
161
|
+
// Trigger summary generation on error
|
|
162
|
+
summaryService.onSessionComplete(sessionId);
|
|
163
|
+
|
|
164
|
+
// Trigger next template if configured (e.g., session completed work but process exited with error code)
|
|
165
|
+
if (options.handleTemplateTriggerIfNeeded) {
|
|
166
|
+
await safeTriggerTemplate(sessionId, options.handleTemplateTriggerIfNeeded);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return false; // Not rescheduled
|
|
170
|
+
}
|