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,211 @@
|
|
|
1
|
+
import { databaseManager } from './DatabaseManager.js';
|
|
2
|
+
import { DEFAULT_TOKEN_COST_WEIGHTS } from '../../../shared/src/index.js';
|
|
3
|
+
|
|
4
|
+
const TOKEN_WEIGHTS_KEY = 'token_cost_weights';
|
|
5
|
+
const SUMMARY_SETTINGS_KEY = 'summary_settings';
|
|
6
|
+
const GENERAL_SETTINGS_KEY = 'general_settings';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Settings repository for managing application-wide settings
|
|
10
|
+
*/
|
|
11
|
+
export class SettingsRepository {
|
|
12
|
+
get db() {
|
|
13
|
+
return databaseManager.get();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Get a setting value by key
|
|
18
|
+
* @param {string} key - Setting key
|
|
19
|
+
* @returns {string|null} Setting value or null if not found
|
|
20
|
+
*/
|
|
21
|
+
get(key) {
|
|
22
|
+
const row = this.db
|
|
23
|
+
.prepare('SELECT value FROM app_settings WHERE key = ?')
|
|
24
|
+
.get(key);
|
|
25
|
+
return row ? row.value : null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Set a setting value
|
|
30
|
+
* @param {string} key - Setting key
|
|
31
|
+
* @param {string} value - Setting value (must be string, use JSON.stringify for objects)
|
|
32
|
+
*/
|
|
33
|
+
set(key, value) {
|
|
34
|
+
const now = Date.now();
|
|
35
|
+
this.db
|
|
36
|
+
.prepare(
|
|
37
|
+
`INSERT INTO app_settings (key, value, updated_at)
|
|
38
|
+
VALUES (?, ?, ?)
|
|
39
|
+
ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at`
|
|
40
|
+
)
|
|
41
|
+
.run(key, value, now);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Delete a setting
|
|
46
|
+
* @param {string} key - Setting key
|
|
47
|
+
* @returns {boolean} True if deleted, false if not found
|
|
48
|
+
*/
|
|
49
|
+
delete(key) {
|
|
50
|
+
const result = this.db
|
|
51
|
+
.prepare('DELETE FROM app_settings WHERE key = ?')
|
|
52
|
+
.run(key);
|
|
53
|
+
return result.changes > 0;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Get token cost weights (returns defaults if not set)
|
|
58
|
+
* @returns {Object} Token cost weights
|
|
59
|
+
*/
|
|
60
|
+
getTokenCostWeights() {
|
|
61
|
+
const value = this.get(TOKEN_WEIGHTS_KEY);
|
|
62
|
+
if (!value) {
|
|
63
|
+
return { ...DEFAULT_TOKEN_COST_WEIGHTS };
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
const parsed = JSON.parse(value);
|
|
67
|
+
// Merge with defaults to ensure all keys exist
|
|
68
|
+
return {
|
|
69
|
+
input: parsed.input ?? DEFAULT_TOKEN_COST_WEIGHTS.input,
|
|
70
|
+
output: parsed.output ?? DEFAULT_TOKEN_COST_WEIGHTS.output,
|
|
71
|
+
cacheRead: parsed.cacheRead ?? DEFAULT_TOKEN_COST_WEIGHTS.cacheRead,
|
|
72
|
+
cacheCreation: parsed.cacheCreation ?? DEFAULT_TOKEN_COST_WEIGHTS.cacheCreation,
|
|
73
|
+
};
|
|
74
|
+
} catch {
|
|
75
|
+
return { ...DEFAULT_TOKEN_COST_WEIGHTS };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Set token cost weights
|
|
81
|
+
* @param {Object} weights - Token cost weights
|
|
82
|
+
* @param {number} weights.input - Input token weight
|
|
83
|
+
* @param {number} weights.output - Output token weight
|
|
84
|
+
* @param {number} weights.cacheRead - Cache read token weight
|
|
85
|
+
* @param {number} weights.cacheCreation - Cache creation token weight
|
|
86
|
+
*/
|
|
87
|
+
setTokenCostWeights(weights) {
|
|
88
|
+
// Validate that all weights are positive numbers
|
|
89
|
+
const validated = {
|
|
90
|
+
input: Math.max(0, Number(weights.input) || DEFAULT_TOKEN_COST_WEIGHTS.input),
|
|
91
|
+
output: Math.max(0, Number(weights.output) || DEFAULT_TOKEN_COST_WEIGHTS.output),
|
|
92
|
+
cacheRead: Math.max(0, Number(weights.cacheRead) || DEFAULT_TOKEN_COST_WEIGHTS.cacheRead),
|
|
93
|
+
cacheCreation: Math.max(0, Number(weights.cacheCreation) || DEFAULT_TOKEN_COST_WEIGHTS.cacheCreation),
|
|
94
|
+
};
|
|
95
|
+
this.set(TOKEN_WEIGHTS_KEY, JSON.stringify(validated));
|
|
96
|
+
return validated;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Reset token cost weights to defaults
|
|
101
|
+
* @returns {Object} The default weights
|
|
102
|
+
*/
|
|
103
|
+
resetTokenCostWeights() {
|
|
104
|
+
this.delete(TOKEN_WEIGHTS_KEY);
|
|
105
|
+
return { ...DEFAULT_TOKEN_COST_WEIGHTS };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Summary Settings
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Get summary settings with defaults
|
|
112
|
+
* @returns {Object} Summary settings
|
|
113
|
+
*/
|
|
114
|
+
getSummarySettings() {
|
|
115
|
+
const value = this.get(SUMMARY_SETTINGS_KEY);
|
|
116
|
+
if (!value) {
|
|
117
|
+
return {
|
|
118
|
+
disableSessionSummaries: false,
|
|
119
|
+
sessionTitlePrompt: '',
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
const parsed = JSON.parse(value);
|
|
124
|
+
return {
|
|
125
|
+
disableSessionSummaries: parsed.disableSessionSummaries || false,
|
|
126
|
+
sessionTitlePrompt: parsed.sessionTitlePrompt || '',
|
|
127
|
+
};
|
|
128
|
+
} catch {
|
|
129
|
+
return {
|
|
130
|
+
disableSessionSummaries: false,
|
|
131
|
+
sessionTitlePrompt: '',
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Set summary settings
|
|
138
|
+
* @param {Object} settings - Summary settings
|
|
139
|
+
* @param {boolean} settings.disableSessionSummaries - Disable session summaries
|
|
140
|
+
* @param {string} settings.sessionTitlePrompt - Custom session title prompt
|
|
141
|
+
*/
|
|
142
|
+
setSummarySettings(settings) {
|
|
143
|
+
const validated = {
|
|
144
|
+
disableSessionSummaries: Boolean(settings.disableSessionSummaries),
|
|
145
|
+
sessionTitlePrompt: String(settings.sessionTitlePrompt || ''),
|
|
146
|
+
};
|
|
147
|
+
this.set(SUMMARY_SETTINGS_KEY, JSON.stringify(validated));
|
|
148
|
+
return validated;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Reset summary settings to defaults
|
|
153
|
+
* @returns {Object} The default settings
|
|
154
|
+
*/
|
|
155
|
+
resetSummarySettings() {
|
|
156
|
+
this.delete(SUMMARY_SETTINGS_KEY);
|
|
157
|
+
return {
|
|
158
|
+
disableSessionSummaries: false,
|
|
159
|
+
sessionTitlePrompt: '',
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// General Settings
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Get general settings with defaults
|
|
167
|
+
* @returns {Object} General settings
|
|
168
|
+
*/
|
|
169
|
+
getGeneralSettings() {
|
|
170
|
+
const value = this.get(GENERAL_SETTINGS_KEY);
|
|
171
|
+
if (!value) {
|
|
172
|
+
return {
|
|
173
|
+
disableAnalytics: false,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
try {
|
|
177
|
+
const parsed = JSON.parse(value);
|
|
178
|
+
return {
|
|
179
|
+
disableAnalytics: Boolean(parsed.disableAnalytics),
|
|
180
|
+
};
|
|
181
|
+
} catch {
|
|
182
|
+
return {
|
|
183
|
+
disableAnalytics: false,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Set general settings
|
|
190
|
+
* @param {Object} settings - General settings
|
|
191
|
+
* @param {boolean} settings.disableAnalytics - Disable analytics tracking
|
|
192
|
+
*/
|
|
193
|
+
setGeneralSettings(settings) {
|
|
194
|
+
const validated = {
|
|
195
|
+
disableAnalytics: Boolean(settings.disableAnalytics),
|
|
196
|
+
};
|
|
197
|
+
this.set(GENERAL_SETTINGS_KEY, JSON.stringify(validated));
|
|
198
|
+
return validated;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Reset general settings to defaults
|
|
203
|
+
* @returns {Object} The default settings
|
|
204
|
+
*/
|
|
205
|
+
resetGeneralSettings() {
|
|
206
|
+
this.delete(GENERAL_SETTINGS_KEY);
|
|
207
|
+
return {
|
|
208
|
+
disableAnalytics: false,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { BaseRepository } from './BaseRepository.js';
|
|
2
|
+
import { databaseManager } from './DatabaseManager.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Session todo repository class
|
|
6
|
+
* Todos are scoped to conversations within sessions
|
|
7
|
+
*/
|
|
8
|
+
export class TodoRepository extends BaseRepository {
|
|
9
|
+
constructor() {
|
|
10
|
+
super('session_todos', TodoRepository.#mapTodo);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
static #mapTodo(row) {
|
|
14
|
+
return {
|
|
15
|
+
id: row.id,
|
|
16
|
+
sessionId: row.session_id,
|
|
17
|
+
conversationId: row.conversation_id,
|
|
18
|
+
content: row.content,
|
|
19
|
+
status: row.status,
|
|
20
|
+
position: row.position,
|
|
21
|
+
updatedAt: row.updated_at,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get all todos for a session, ordered by position
|
|
27
|
+
* @param {string} sessionId
|
|
28
|
+
* @returns {Array}
|
|
29
|
+
*/
|
|
30
|
+
getBySessionId(sessionId) {
|
|
31
|
+
const rows = this.db
|
|
32
|
+
.prepare('SELECT * FROM session_todos WHERE session_id = ? ORDER BY position ASC')
|
|
33
|
+
.all(sessionId);
|
|
34
|
+
return this.mapAll(rows);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Get all todos for a conversation, ordered by position
|
|
39
|
+
* @param {string} conversationId
|
|
40
|
+
* @returns {Array}
|
|
41
|
+
*/
|
|
42
|
+
getByConversationId(conversationId) {
|
|
43
|
+
const rows = this.db
|
|
44
|
+
.prepare('SELECT * FROM session_todos WHERE conversation_id = ? ORDER BY position ASC')
|
|
45
|
+
.all(conversationId);
|
|
46
|
+
return this.mapAll(rows);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Replace all todos for a session with a new list
|
|
51
|
+
* Called when Claude executes TodoWrite
|
|
52
|
+
* @param {string} sessionId
|
|
53
|
+
* @param {Array<{content: string, status: string}>} todos
|
|
54
|
+
* @returns {Array}
|
|
55
|
+
* @deprecated Use replaceAllForConversation instead
|
|
56
|
+
*/
|
|
57
|
+
replaceAll(sessionId, todos) {
|
|
58
|
+
const now = Date.now();
|
|
59
|
+
|
|
60
|
+
// Use a transaction for atomicity
|
|
61
|
+
const transaction = this.db.transaction(() => {
|
|
62
|
+
// Delete existing todos
|
|
63
|
+
this.db.prepare('DELETE FROM session_todos WHERE session_id = ?').run(sessionId);
|
|
64
|
+
|
|
65
|
+
// Insert new todos
|
|
66
|
+
const insert = this.db.prepare(
|
|
67
|
+
`INSERT INTO session_todos (id, session_id, content, status, position, updated_at)
|
|
68
|
+
VALUES (?, ?, ?, ?, ?, ?)`
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
for (let i = 0; i < todos.length; i++) {
|
|
72
|
+
const todo = todos[i];
|
|
73
|
+
const id = databaseManager.generateId();
|
|
74
|
+
insert.run(id, sessionId, todo.content, todo.status, i, now);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
transaction();
|
|
79
|
+
|
|
80
|
+
return this.getBySessionId(sessionId);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Replace all todos for a conversation with a new list
|
|
85
|
+
* Called when Claude executes TodoWrite
|
|
86
|
+
* @param {string} sessionId
|
|
87
|
+
* @param {string} conversationId
|
|
88
|
+
* @param {Array<{content: string, status: string}>} todos
|
|
89
|
+
* @returns {Array}
|
|
90
|
+
*/
|
|
91
|
+
replaceAllForConversation(sessionId, conversationId, todos) {
|
|
92
|
+
const now = Date.now();
|
|
93
|
+
|
|
94
|
+
// Use a transaction for atomicity
|
|
95
|
+
const transaction = this.db.transaction(() => {
|
|
96
|
+
// Delete existing todos for this conversation
|
|
97
|
+
this.db.prepare('DELETE FROM session_todos WHERE conversation_id = ?').run(conversationId);
|
|
98
|
+
|
|
99
|
+
// Insert new todos
|
|
100
|
+
const insert = this.db.prepare(
|
|
101
|
+
`INSERT INTO session_todos (id, session_id, conversation_id, content, status, position, updated_at)
|
|
102
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
for (let i = 0; i < todos.length; i++) {
|
|
106
|
+
const todo = todos[i];
|
|
107
|
+
const id = databaseManager.generateId();
|
|
108
|
+
insert.run(id, sessionId, conversationId, todo.content, todo.status, i, now);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
transaction();
|
|
113
|
+
|
|
114
|
+
return this.getByConversationId(conversationId);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Delete all todos for a session
|
|
119
|
+
* @param {string} sessionId
|
|
120
|
+
*/
|
|
121
|
+
deleteBySessionId(sessionId) {
|
|
122
|
+
this.db.prepare('DELETE FROM session_todos WHERE session_id = ?').run(sessionId);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Delete all todos for a conversation
|
|
127
|
+
* @param {string} conversationId
|
|
128
|
+
*/
|
|
129
|
+
deleteByConversationId(conversationId) {
|
|
130
|
+
this.db.prepare('DELETE FROM session_todos WHERE conversation_id = ?').run(conversationId);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { BaseRepository } from './BaseRepository.js';
|
|
2
|
+
import { databaseManager } from './DatabaseManager.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Work log repository class
|
|
6
|
+
*/
|
|
7
|
+
export class WorkLogRepository extends BaseRepository {
|
|
8
|
+
constructor() {
|
|
9
|
+
super('work_logs', WorkLogRepository.#mapWorkLog);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
static #mapWorkLog(row) {
|
|
13
|
+
return {
|
|
14
|
+
id: row.id,
|
|
15
|
+
sessionId: row.session_id,
|
|
16
|
+
messageId: row.message_id,
|
|
17
|
+
type: row.type,
|
|
18
|
+
toolName: row.tool_name,
|
|
19
|
+
content: row.content,
|
|
20
|
+
timestamp: row.timestamp,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Create a new work log entry
|
|
26
|
+
* @param {string} sessionId - Session ID
|
|
27
|
+
* @param {string} type - Log type ('thinking', 'tool_input', 'tool_output')
|
|
28
|
+
* @param {string} content - Log content
|
|
29
|
+
* @param {{ messageId?: string|null, toolName?: string|null }} options - Optional parameters
|
|
30
|
+
* @returns {Object} Created work log
|
|
31
|
+
*/
|
|
32
|
+
create(sessionId, type, content, options = {}) {
|
|
33
|
+
const { messageId = null, toolName = null } = options || {};
|
|
34
|
+
|
|
35
|
+
const id = databaseManager.generateId();
|
|
36
|
+
const now = Date.now();
|
|
37
|
+
this.db
|
|
38
|
+
.prepare(
|
|
39
|
+
`INSERT INTO work_logs (id, session_id, message_id, type, tool_name, content, timestamp)
|
|
40
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`
|
|
41
|
+
)
|
|
42
|
+
.run(id, sessionId, messageId, type, toolName, content, now);
|
|
43
|
+
return this.getById(id);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Get all work logs for a session
|
|
48
|
+
* @param {string} sessionId - Session ID
|
|
49
|
+
* @returns {Array} Work logs ordered by timestamp
|
|
50
|
+
*/
|
|
51
|
+
getBySessionId(sessionId) {
|
|
52
|
+
const rows = this.db
|
|
53
|
+
.prepare('SELECT * FROM work_logs WHERE session_id = ? ORDER BY timestamp ASC')
|
|
54
|
+
.all(sessionId);
|
|
55
|
+
return this.mapAll(rows);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Get work logs for a specific message
|
|
60
|
+
* @param {string} messageId - Message ID
|
|
61
|
+
* @returns {Array} Work logs for the message
|
|
62
|
+
*/
|
|
63
|
+
getByMessageId(messageId) {
|
|
64
|
+
const rows = this.db
|
|
65
|
+
.prepare('SELECT * FROM work_logs WHERE message_id = ? ORDER BY timestamp ASC')
|
|
66
|
+
.all(messageId);
|
|
67
|
+
return this.mapAll(rows);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Get work logs grouped by message for a session
|
|
72
|
+
* @param {string} sessionId - Session ID
|
|
73
|
+
* @returns {Object} Work logs keyed by message ID
|
|
74
|
+
*/
|
|
75
|
+
getBySessionIdGrouped(sessionId) {
|
|
76
|
+
const logs = this.getBySessionId(sessionId);
|
|
77
|
+
const grouped = {};
|
|
78
|
+
for (const log of logs) {
|
|
79
|
+
const key = log.messageId || '_unassociated';
|
|
80
|
+
if (!grouped[key]) {
|
|
81
|
+
grouped[key] = [];
|
|
82
|
+
}
|
|
83
|
+
grouped[key].push(log);
|
|
84
|
+
}
|
|
85
|
+
return grouped;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Update the message ID for work logs (used when associating pending logs with a message)
|
|
90
|
+
* @param {string} sessionId - Session ID
|
|
91
|
+
* @param {string} messageId - Message ID to associate
|
|
92
|
+
* @returns {number} Number of work logs that were associated
|
|
93
|
+
*/
|
|
94
|
+
associatePendingLogs(sessionId, messageId) {
|
|
95
|
+
const result = this.db
|
|
96
|
+
.prepare('UPDATE work_logs SET message_id = ? WHERE session_id = ? AND message_id IS NULL')
|
|
97
|
+
.run(messageId, sessionId);
|
|
98
|
+
return result.changes;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Get recent pending (unassociated) work logs for a session.
|
|
103
|
+
* These are logs from the current turn that haven't been finalized to a message yet.
|
|
104
|
+
* @param {string} sessionId - Session ID
|
|
105
|
+
* @param {number} limit - Maximum number of logs to return (default 15)
|
|
106
|
+
* @returns {Array} Work logs ordered by timestamp DESC, limited
|
|
107
|
+
*/
|
|
108
|
+
getRecentPendingBySessionId(sessionId, limit = 15) {
|
|
109
|
+
const rows = this.db
|
|
110
|
+
.prepare('SELECT * FROM work_logs WHERE session_id = ? AND message_id IS NULL ORDER BY timestamp DESC LIMIT ?')
|
|
111
|
+
.all(sessionId, limit);
|
|
112
|
+
return this.mapAll(rows);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Delete all work logs for a session
|
|
117
|
+
* @param {string} sessionId - Session ID
|
|
118
|
+
*/
|
|
119
|
+
deleteBySessionId(sessionId) {
|
|
120
|
+
this.db.prepare('DELETE FROM work_logs WHERE session_id = ?').run(sessionId);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { databaseManager } from './DatabaseManager.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Map a raw database row to a conversation object.
|
|
5
|
+
* @param {Object} row - The raw database row
|
|
6
|
+
* @returns {Object} The mapped conversation object
|
|
7
|
+
*/
|
|
8
|
+
export function mapConversationRow(row) {
|
|
9
|
+
return {
|
|
10
|
+
id: row.id,
|
|
11
|
+
sessionId: row.session_id,
|
|
12
|
+
name: row.name,
|
|
13
|
+
summary: row.summary,
|
|
14
|
+
summaryGeneratedAt: row.summary_generated_at,
|
|
15
|
+
isActive: row.is_active === 1,
|
|
16
|
+
claudeSessionId: row.claude_session_id,
|
|
17
|
+
|
|
18
|
+
// Branching fields
|
|
19
|
+
parentConversationId: row.parent_conversation_id || null,
|
|
20
|
+
branchFromMessageId: row.branch_from_message_id || null,
|
|
21
|
+
|
|
22
|
+
// Token usage fields
|
|
23
|
+
inputTokens: row.input_tokens || 0,
|
|
24
|
+
outputTokens: row.output_tokens || 0,
|
|
25
|
+
cacheReadInputTokens: row.cache_read_input_tokens || 0,
|
|
26
|
+
cacheCreationInputTokens: row.cache_creation_input_tokens || 0,
|
|
27
|
+
webSearchRequests: row.web_search_requests || 0,
|
|
28
|
+
contextWindow: row.context_window || 200000,
|
|
29
|
+
model: row.model,
|
|
30
|
+
|
|
31
|
+
createdAt: row.created_at,
|
|
32
|
+
updatedAt: row.updated_at,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Execute the branch operation: create a new conversation branching from an
|
|
38
|
+
* existing one at a specific message, copying earlier messages and adding a
|
|
39
|
+
* new prompt.
|
|
40
|
+
*
|
|
41
|
+
* @param {Object} repo - The ConversationRepository instance
|
|
42
|
+
* @param {string} conversationId - The source conversation ID
|
|
43
|
+
* @param {string} messageId - The message ID to branch from
|
|
44
|
+
* @param {Object} options - Branch options
|
|
45
|
+
* @param {string|null} [options.name] - Optional name for the new conversation
|
|
46
|
+
* @param {string} options.initialPrompt - The new prompt that replaces the branch point message
|
|
47
|
+
* @returns {Object} The created branch conversation
|
|
48
|
+
*/
|
|
49
|
+
export function executeBranch(repo, conversationId, messageId, options) {
|
|
50
|
+
const { name = null, initialPrompt } = options;
|
|
51
|
+
if (!initialPrompt || !initialPrompt.trim()) {
|
|
52
|
+
throw new Error('A prompt is required when branching');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const sourceConv = repo.getById(conversationId);
|
|
56
|
+
if (!sourceConv) {
|
|
57
|
+
throw new Error('Source conversation not found');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const branchMessage = repo.db
|
|
61
|
+
.prepare('SELECT * FROM conversation_messages WHERE id = ? AND conversation_id = ?')
|
|
62
|
+
.get(messageId, conversationId);
|
|
63
|
+
|
|
64
|
+
if (!branchMessage) {
|
|
65
|
+
throw new Error('Branch point message not found in conversation');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const id = databaseManager.generateId();
|
|
69
|
+
const now = Date.now();
|
|
70
|
+
|
|
71
|
+
// Auto-generate name from the prompt (first 40 chars)
|
|
72
|
+
const promptPreview = initialPrompt.length > 40
|
|
73
|
+
? `${initialPrompt.substring(0, 40)}...`
|
|
74
|
+
: initialPrompt;
|
|
75
|
+
const branchName = name || promptPreview;
|
|
76
|
+
|
|
77
|
+
// Deactivate all other conversations
|
|
78
|
+
repo.db
|
|
79
|
+
.prepare('UPDATE conversations SET is_active = 0, updated_at = ? WHERE session_id = ?')
|
|
80
|
+
.run(now, sourceConv.sessionId);
|
|
81
|
+
|
|
82
|
+
// Create the new branch conversation
|
|
83
|
+
repo.db
|
|
84
|
+
.prepare(
|
|
85
|
+
`INSERT INTO conversations (id, session_id, name, is_active, parent_conversation_id, branch_from_message_id, created_at, updated_at)
|
|
86
|
+
VALUES (?, ?, ?, 1, ?, ?, ?, ?)`
|
|
87
|
+
)
|
|
88
|
+
.run(id, sourceConv.sessionId, branchName, conversationId, messageId, now, now);
|
|
89
|
+
|
|
90
|
+
// Copy all messages BEFORE the branch point (NOT including it)
|
|
91
|
+
const messagesToCopy = repo.db
|
|
92
|
+
.prepare(
|
|
93
|
+
`SELECT * FROM conversation_messages
|
|
94
|
+
WHERE conversation_id = ? AND timestamp < ?
|
|
95
|
+
ORDER BY timestamp ASC`
|
|
96
|
+
)
|
|
97
|
+
.all(conversationId, branchMessage.timestamp);
|
|
98
|
+
|
|
99
|
+
for (const msg of messagesToCopy) {
|
|
100
|
+
const newMsgId = databaseManager.generateId();
|
|
101
|
+
repo.db
|
|
102
|
+
.prepare(
|
|
103
|
+
`INSERT INTO conversation_messages (id, session_id, conversation_id, role, content, tool_use, timestamp)
|
|
104
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`
|
|
105
|
+
)
|
|
106
|
+
.run(newMsgId, sourceConv.sessionId, id, msg.role, msg.content, msg.tool_use, msg.timestamp);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Add the new prompt as the replacement for the original user message
|
|
110
|
+
const promptMsgId = databaseManager.generateId();
|
|
111
|
+
repo.db
|
|
112
|
+
.prepare(
|
|
113
|
+
`INSERT INTO conversation_messages (id, session_id, conversation_id, role, content, timestamp)
|
|
114
|
+
VALUES (?, ?, ?, 'user', ?, ?)`
|
|
115
|
+
)
|
|
116
|
+
.run(promptMsgId, sourceConv.sessionId, id, initialPrompt.trim(), now);
|
|
117
|
+
|
|
118
|
+
return repo.getById(id);
|
|
119
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// Database manager
|
|
2
|
+
export { DatabaseManager, databaseManager } from './DatabaseManager.js';
|
|
3
|
+
|
|
4
|
+
// Base repository
|
|
5
|
+
export { BaseRepository } from './BaseRepository.js';
|
|
6
|
+
|
|
7
|
+
// Repository classes
|
|
8
|
+
export { ProjectRepository } from './ProjectRepository.js';
|
|
9
|
+
export { ProjectDefaultsRepository } from './ProjectDefaultsRepository.js';
|
|
10
|
+
export { SessionRepository } from './SessionRepository.js';
|
|
11
|
+
export { SessionTemplateRepository } from './SessionTemplateRepository.js';
|
|
12
|
+
export { MessageRepository } from './MessageRepository.js';
|
|
13
|
+
export { ConversationRepository } from './ConversationRepository.js';
|
|
14
|
+
export { CanvasItemRepository } from './CanvasItemRepository.js';
|
|
15
|
+
export { SessionNoteRepository } from './SessionNoteRepository.js';
|
|
16
|
+
export { TodoRepository } from './TodoRepository.js';
|
|
17
|
+
export { WorkLogRepository } from './WorkLogRepository.js';
|
|
18
|
+
export { SessionSummaryRepository } from './SessionSummaryRepository.js';
|
|
19
|
+
export { AttachmentRepository } from './AttachmentRepository.js';
|
|
20
|
+
export { CommandButtonRepository } from './CommandButtonRepository.js';
|
|
21
|
+
export { CommandRunRepository } from './CommandRunRepository.js';
|
|
22
|
+
export { QuickResponseRepository } from './QuickResponseRepository.js';
|
|
23
|
+
export { SettingsRepository } from './SettingsRepository.js';
|
|
24
|
+
// ProviderRepository replaces ModelProviderRepository; keep the old name exported for any leftover imports
|
|
25
|
+
export { ProviderRepository } from './ProviderRepository.js';
|
|
26
|
+
export { ProviderRepository as ModelProviderRepository } from './ProviderRepository.js';
|
|
27
|
+
export { AgentCallLogRepository } from './AgentCallLogRepository.js';
|
|
28
|
+
export { KanbanBoardRepository } from './KanbanBoardRepository.js';
|
|
29
|
+
export { KanbanLaneRepository } from './KanbanLaneRepository.js';
|
|
30
|
+
export { KanbanCardRepository } from './KanbanCardRepository.js';
|
|
31
|
+
|
|
32
|
+
// Singleton instances
|
|
33
|
+
import { ProjectRepository } from './ProjectRepository.js';
|
|
34
|
+
import { ProjectDefaultsRepository } from './ProjectDefaultsRepository.js';
|
|
35
|
+
import { MessageRepository } from './MessageRepository.js';
|
|
36
|
+
import { ConversationRepository } from './ConversationRepository.js';
|
|
37
|
+
import { CanvasItemRepository } from './CanvasItemRepository.js';
|
|
38
|
+
import { SessionNoteRepository } from './SessionNoteRepository.js';
|
|
39
|
+
import { TodoRepository } from './TodoRepository.js';
|
|
40
|
+
import { WorkLogRepository } from './WorkLogRepository.js';
|
|
41
|
+
import { SessionSummaryRepository } from './SessionSummaryRepository.js';
|
|
42
|
+
import { SessionTemplateRepository } from './SessionTemplateRepository.js';
|
|
43
|
+
import { AttachmentRepository } from './AttachmentRepository.js';
|
|
44
|
+
import { CommandButtonRepository } from './CommandButtonRepository.js';
|
|
45
|
+
import { CommandRunRepository } from './CommandRunRepository.js';
|
|
46
|
+
import { QuickResponseRepository } from './QuickResponseRepository.js';
|
|
47
|
+
import { SettingsRepository } from './SettingsRepository.js';
|
|
48
|
+
import { ProviderRepository } from './ProviderRepository.js';
|
|
49
|
+
import { AgentCallLogRepository } from './AgentCallLogRepository.js';
|
|
50
|
+
import { KanbanBoardRepository } from './KanbanBoardRepository.js';
|
|
51
|
+
import { KanbanLaneRepository } from './KanbanLaneRepository.js';
|
|
52
|
+
import { KanbanCardRepository } from './KanbanCardRepository.js';
|
|
53
|
+
|
|
54
|
+
export const projects = new ProjectRepository();
|
|
55
|
+
export const projectDefaults = new ProjectDefaultsRepository();
|
|
56
|
+
export const messages = new MessageRepository();
|
|
57
|
+
export const conversations = new ConversationRepository();
|
|
58
|
+
export const canvasItems = new CanvasItemRepository();
|
|
59
|
+
export const sessionNotes = new SessionNoteRepository();
|
|
60
|
+
export const todos = new TodoRepository();
|
|
61
|
+
export const workLogs = new WorkLogRepository();
|
|
62
|
+
export const sessionSummaries = new SessionSummaryRepository();
|
|
63
|
+
export const sessionTemplates = new SessionTemplateRepository();
|
|
64
|
+
export const attachments = new AttachmentRepository();
|
|
65
|
+
export const commandButtons = new CommandButtonRepository();
|
|
66
|
+
export const commandRuns = new CommandRunRepository();
|
|
67
|
+
export const quickResponses = new QuickResponseRepository();
|
|
68
|
+
export const settings = new SettingsRepository();
|
|
69
|
+
export const modelProviders = new ProviderRepository();
|
|
70
|
+
export const agentCallLogs = new AgentCallLogRepository();
|
|
71
|
+
export const kanbanBoards = new KanbanBoardRepository();
|
|
72
|
+
export const kanbanLanes = new KanbanLaneRepository();
|
|
73
|
+
export const kanbanCards = new KanbanCardRepository();
|
|
74
|
+
|
|
75
|
+
// SessionRepository needs to be instantiated after messages is available
|
|
76
|
+
import { SessionRepository } from './SessionRepository.js';
|
|
77
|
+
export const sessions = new SessionRepository();
|
|
78
|
+
|
|
79
|
+
// Legacy function exports for backward compatibility
|
|
80
|
+
import { databaseManager } from './DatabaseManager.js';
|
|
81
|
+
|
|
82
|
+
export function initDatabase(dbPath) {
|
|
83
|
+
return databaseManager.init(dbPath);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function getDatabase() {
|
|
87
|
+
return databaseManager.get();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function closeDatabase() {
|
|
91
|
+
return databaseManager.close();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function generateId() {
|
|
95
|
+
return databaseManager.generateId();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function transaction(fn) {
|
|
99
|
+
return databaseManager.transaction(fn);
|
|
100
|
+
}
|