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,58 @@
|
|
|
1
|
+
// Re-export everything from db module for backward compatibility
|
|
2
|
+
export {
|
|
3
|
+
// Classes
|
|
4
|
+
DatabaseManager,
|
|
5
|
+
BaseRepository,
|
|
6
|
+
ProjectRepository,
|
|
7
|
+
ProjectDefaultsRepository,
|
|
8
|
+
SessionRepository,
|
|
9
|
+
SessionTemplateRepository,
|
|
10
|
+
MessageRepository,
|
|
11
|
+
ConversationRepository,
|
|
12
|
+
CanvasItemRepository,
|
|
13
|
+
SessionNoteRepository,
|
|
14
|
+
TodoRepository,
|
|
15
|
+
WorkLogRepository,
|
|
16
|
+
SessionSummaryRepository,
|
|
17
|
+
AttachmentRepository,
|
|
18
|
+
CommandButtonRepository,
|
|
19
|
+
CommandRunRepository,
|
|
20
|
+
QuickResponseRepository,
|
|
21
|
+
ProviderRepository,
|
|
22
|
+
// Kept for any code that still imports ModelProviderRepository by name
|
|
23
|
+
ModelProviderRepository,
|
|
24
|
+
SettingsRepository,
|
|
25
|
+
AgentCallLogRepository,
|
|
26
|
+
KanbanBoardRepository,
|
|
27
|
+
KanbanLaneRepository,
|
|
28
|
+
KanbanCardRepository,
|
|
29
|
+
// Singleton instances
|
|
30
|
+
databaseManager,
|
|
31
|
+
projects,
|
|
32
|
+
projectDefaults,
|
|
33
|
+
sessions,
|
|
34
|
+
sessionTemplates,
|
|
35
|
+
messages,
|
|
36
|
+
conversations,
|
|
37
|
+
canvasItems,
|
|
38
|
+
sessionNotes,
|
|
39
|
+
todos,
|
|
40
|
+
workLogs,
|
|
41
|
+
sessionSummaries,
|
|
42
|
+
attachments,
|
|
43
|
+
commandButtons,
|
|
44
|
+
commandRuns,
|
|
45
|
+
quickResponses,
|
|
46
|
+
modelProviders,
|
|
47
|
+
settings,
|
|
48
|
+
agentCallLogs,
|
|
49
|
+
kanbanBoards,
|
|
50
|
+
kanbanLanes,
|
|
51
|
+
kanbanCards,
|
|
52
|
+
// Legacy functions
|
|
53
|
+
initDatabase,
|
|
54
|
+
getDatabase,
|
|
55
|
+
closeDatabase,
|
|
56
|
+
generateId,
|
|
57
|
+
transaction,
|
|
58
|
+
} from './db/index.js';
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import { BaseRepository } from './BaseRepository.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Compute total tokens from passed values (preferring provided over DB row values).
|
|
5
|
+
*/
|
|
6
|
+
function computeTotalTokens(provided, row) {
|
|
7
|
+
const finalInput = provided.inputTokens ?? row?.input_tokens ?? 0;
|
|
8
|
+
const finalOutput = provided.outputTokens ?? row?.output_tokens ?? 0;
|
|
9
|
+
const finalThinking = row?.thinking_tokens ?? 0;
|
|
10
|
+
const finalCacheRead = provided.cacheReadTokens ?? row?.cache_read_tokens ?? 0;
|
|
11
|
+
const finalCacheWrite = provided.cacheWriteTokens ?? row?.cache_write_tokens ?? 0;
|
|
12
|
+
return finalInput + finalOutput + finalThinking + finalCacheRead + finalCacheWrite;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function mapRow(row) {
|
|
16
|
+
if (!row) return null;
|
|
17
|
+
return {
|
|
18
|
+
id: row.id,
|
|
19
|
+
sessionId: row.session_id,
|
|
20
|
+
conversationId: row.conversation_id,
|
|
21
|
+
agentType: row.agent_type,
|
|
22
|
+
model: row.model,
|
|
23
|
+
callType: row.call_type,
|
|
24
|
+
promptLength: row.prompt_length,
|
|
25
|
+
inputTokens: row.input_tokens,
|
|
26
|
+
outputTokens: row.output_tokens,
|
|
27
|
+
thinkingTokens: row.thinking_tokens,
|
|
28
|
+
cacheReadTokens: row.cache_read_tokens,
|
|
29
|
+
cacheWriteTokens: row.cache_write_tokens,
|
|
30
|
+
totalTokens: row.total_tokens,
|
|
31
|
+
startedAt: row.started_at,
|
|
32
|
+
completedAt: row.completed_at,
|
|
33
|
+
durationMs: row.duration_ms,
|
|
34
|
+
status: row.status,
|
|
35
|
+
errorMessage: row.error_message,
|
|
36
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : null,
|
|
37
|
+
createdAt: row.created_at,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export class AgentCallLogRepository extends BaseRepository {
|
|
42
|
+
constructor() {
|
|
43
|
+
super('agent_call_logs', mapRow);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Create a new call log entry
|
|
48
|
+
*/
|
|
49
|
+
create({ id, sessionId, conversationId, agentType, model, callType, promptLength, metadata = {} }) {
|
|
50
|
+
const now = Date.now();
|
|
51
|
+
const metadataJson = Object.keys(metadata).length > 0
|
|
52
|
+
? JSON.stringify(metadata)
|
|
53
|
+
: null;
|
|
54
|
+
|
|
55
|
+
this.db
|
|
56
|
+
.prepare(
|
|
57
|
+
`INSERT INTO agent_call_logs (id, session_id, conversation_id, agent_type, model, call_type, prompt_length, metadata, started_at, status, created_at)
|
|
58
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'pending', ?)`
|
|
59
|
+
)
|
|
60
|
+
.run(id, sessionId, conversationId, agentType, model, callType, promptLength, metadataJson, now, now);
|
|
61
|
+
return this.getById(id);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Update usage tokens during streaming
|
|
66
|
+
*/
|
|
67
|
+
updateUsage(
|
|
68
|
+
id,
|
|
69
|
+
{ inputTokens, outputTokens, thinkingTokens, cacheReadTokens, cacheWriteTokens }
|
|
70
|
+
) {
|
|
71
|
+
this.db
|
|
72
|
+
.prepare(
|
|
73
|
+
`UPDATE agent_call_logs SET
|
|
74
|
+
input_tokens = COALESCE(?, input_tokens),
|
|
75
|
+
output_tokens = COALESCE(?, output_tokens),
|
|
76
|
+
thinking_tokens = COALESCE(?, thinking_tokens),
|
|
77
|
+
cache_read_tokens = COALESCE(?, cache_read_tokens),
|
|
78
|
+
cache_write_tokens = COALESCE(?, cache_write_tokens),
|
|
79
|
+
status = 'streaming'
|
|
80
|
+
WHERE id = ?`
|
|
81
|
+
)
|
|
82
|
+
.run(inputTokens, outputTokens, thinkingTokens, cacheReadTokens, cacheWriteTokens, id);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Mark a call as completed or errored
|
|
87
|
+
*/
|
|
88
|
+
complete(
|
|
89
|
+
id,
|
|
90
|
+
{ success, inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens, errorMessage }
|
|
91
|
+
) {
|
|
92
|
+
const now = Date.now();
|
|
93
|
+
const row = this.db
|
|
94
|
+
.prepare(
|
|
95
|
+
'SELECT started_at, input_tokens, output_tokens, thinking_tokens, cache_read_tokens, cache_write_tokens FROM agent_call_logs WHERE id = ?'
|
|
96
|
+
)
|
|
97
|
+
.get(id);
|
|
98
|
+
const durationMs = row ? now - row.started_at : null;
|
|
99
|
+
|
|
100
|
+
// Compute totalTokens using passed values (if provided) or existing DB values.
|
|
101
|
+
// thinkingTokens is only set via updateUsage() during streaming, so we always
|
|
102
|
+
// read it from the existing row rather than expecting it as a parameter here.
|
|
103
|
+
const totalTokens = computeTotalTokens(
|
|
104
|
+
{ inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens },
|
|
105
|
+
row
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
this.db
|
|
109
|
+
.prepare(
|
|
110
|
+
`UPDATE agent_call_logs SET
|
|
111
|
+
input_tokens = COALESCE(?, input_tokens),
|
|
112
|
+
output_tokens = COALESCE(?, output_tokens),
|
|
113
|
+
cache_read_tokens = COALESCE(?, cache_read_tokens),
|
|
114
|
+
cache_write_tokens = COALESCE(?, cache_write_tokens),
|
|
115
|
+
total_tokens = ?,
|
|
116
|
+
completed_at = ?,
|
|
117
|
+
duration_ms = ?,
|
|
118
|
+
status = ?,
|
|
119
|
+
error_message = ?
|
|
120
|
+
WHERE id = ?`
|
|
121
|
+
)
|
|
122
|
+
.run(
|
|
123
|
+
inputTokens,
|
|
124
|
+
outputTokens,
|
|
125
|
+
cacheReadTokens,
|
|
126
|
+
cacheWriteTokens,
|
|
127
|
+
totalTokens,
|
|
128
|
+
now,
|
|
129
|
+
durationMs,
|
|
130
|
+
success ? 'completed' : 'error',
|
|
131
|
+
errorMessage || null,
|
|
132
|
+
id
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Get all call logs with optional filtering, sorting, and pagination.
|
|
138
|
+
* Returns { rows, total } where total is the full count (before limit/offset).
|
|
139
|
+
*/
|
|
140
|
+
getAll({
|
|
141
|
+
limit = 25,
|
|
142
|
+
offset = 0,
|
|
143
|
+
agentType,
|
|
144
|
+
callType,
|
|
145
|
+
status,
|
|
146
|
+
startDate,
|
|
147
|
+
endDate,
|
|
148
|
+
sessionId,
|
|
149
|
+
model,
|
|
150
|
+
sortBy = 'started_at',
|
|
151
|
+
sortOrder = 'DESC',
|
|
152
|
+
} = {}) {
|
|
153
|
+
const SORTABLE_COLUMNS = [
|
|
154
|
+
'started_at',
|
|
155
|
+
'status',
|
|
156
|
+
'agent_type',
|
|
157
|
+
'call_type',
|
|
158
|
+
'model',
|
|
159
|
+
'total_tokens',
|
|
160
|
+
'duration_ms',
|
|
161
|
+
];
|
|
162
|
+
const safeSortBy = SORTABLE_COLUMNS.includes(sortBy) ? sortBy : 'started_at';
|
|
163
|
+
const safeSortOrder = sortOrder === 'ASC' ? 'ASC' : 'DESC';
|
|
164
|
+
|
|
165
|
+
const conditions = [];
|
|
166
|
+
const params = [];
|
|
167
|
+
|
|
168
|
+
if (agentType) {
|
|
169
|
+
conditions.push('acl.agent_type = ?');
|
|
170
|
+
params.push(agentType);
|
|
171
|
+
}
|
|
172
|
+
if (callType) {
|
|
173
|
+
conditions.push('acl.call_type = ?');
|
|
174
|
+
params.push(callType);
|
|
175
|
+
}
|
|
176
|
+
if (status) {
|
|
177
|
+
conditions.push('acl.status = ?');
|
|
178
|
+
params.push(status);
|
|
179
|
+
}
|
|
180
|
+
if (model) {
|
|
181
|
+
conditions.push('acl.model = ?');
|
|
182
|
+
params.push(model);
|
|
183
|
+
}
|
|
184
|
+
if (sessionId) {
|
|
185
|
+
conditions.push('acl.session_id = ?');
|
|
186
|
+
params.push(sessionId);
|
|
187
|
+
}
|
|
188
|
+
if (startDate) {
|
|
189
|
+
conditions.push('acl.started_at >= ?');
|
|
190
|
+
params.push(startDate);
|
|
191
|
+
}
|
|
192
|
+
if (endDate) {
|
|
193
|
+
conditions.push('acl.started_at <= ?');
|
|
194
|
+
params.push(endDate);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const whereClause = conditions.length > 0 ? `WHERE ${ conditions.join(' AND ')}` : '';
|
|
198
|
+
|
|
199
|
+
const countRow = this.db
|
|
200
|
+
.prepare(`SELECT COUNT(*) as count FROM agent_call_logs acl ${whereClause}`)
|
|
201
|
+
.get(...params);
|
|
202
|
+
const total = countRow.count;
|
|
203
|
+
|
|
204
|
+
const rows = this.db
|
|
205
|
+
.prepare(
|
|
206
|
+
`SELECT acl.*, s.name AS session_name
|
|
207
|
+
FROM agent_call_logs acl
|
|
208
|
+
LEFT JOIN sessions s ON acl.session_id = s.id
|
|
209
|
+
${whereClause}
|
|
210
|
+
ORDER BY acl.${safeSortBy} ${safeSortOrder}
|
|
211
|
+
LIMIT ? OFFSET ?`
|
|
212
|
+
)
|
|
213
|
+
.all(...params, limit, offset);
|
|
214
|
+
|
|
215
|
+
const mappedRows = rows
|
|
216
|
+
.map((row) => {
|
|
217
|
+
const mapped = mapRow(row);
|
|
218
|
+
if (mapped) mapped.sessionName = row.session_name || null;
|
|
219
|
+
return mapped;
|
|
220
|
+
})
|
|
221
|
+
.filter(Boolean);
|
|
222
|
+
|
|
223
|
+
return { rows: mappedRows, total };
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Get distinct filter option values from the database.
|
|
228
|
+
* Returns { agentTypes, callTypes, statuses, models }
|
|
229
|
+
*/
|
|
230
|
+
getFilterOptions() {
|
|
231
|
+
const agentTypes = this.db
|
|
232
|
+
.prepare(
|
|
233
|
+
'SELECT DISTINCT agent_type FROM agent_call_logs WHERE agent_type IS NOT NULL ORDER BY agent_type'
|
|
234
|
+
)
|
|
235
|
+
.all()
|
|
236
|
+
.map((r) => r.agent_type);
|
|
237
|
+
const callTypes = this.db
|
|
238
|
+
.prepare(
|
|
239
|
+
'SELECT DISTINCT call_type FROM agent_call_logs WHERE call_type IS NOT NULL ORDER BY call_type'
|
|
240
|
+
)
|
|
241
|
+
.all()
|
|
242
|
+
.map((r) => r.call_type);
|
|
243
|
+
const statuses = this.db
|
|
244
|
+
.prepare(
|
|
245
|
+
'SELECT DISTINCT status FROM agent_call_logs WHERE status IS NOT NULL ORDER BY status'
|
|
246
|
+
)
|
|
247
|
+
.all()
|
|
248
|
+
.map((r) => r.status);
|
|
249
|
+
const models = this.db
|
|
250
|
+
.prepare(
|
|
251
|
+
'SELECT DISTINCT model FROM agent_call_logs WHERE model IS NOT NULL ORDER BY model'
|
|
252
|
+
)
|
|
253
|
+
.all()
|
|
254
|
+
.map((r) => r.model);
|
|
255
|
+
return { agentTypes, callTypes, statuses, models };
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Get all call logs for a session
|
|
260
|
+
*/
|
|
261
|
+
getBySessionId(sessionId, { limit = 100, offset = 0 } = {}) {
|
|
262
|
+
const rows = this.db
|
|
263
|
+
.prepare(
|
|
264
|
+
`SELECT * FROM agent_call_logs WHERE session_id = ?
|
|
265
|
+
ORDER BY started_at DESC LIMIT ? OFFSET ?`
|
|
266
|
+
)
|
|
267
|
+
.all(sessionId, limit, offset);
|
|
268
|
+
return this.mapAll(rows);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Get aggregated stats for a session, grouped by call_type
|
|
273
|
+
*/
|
|
274
|
+
getSessionStats(sessionId) {
|
|
275
|
+
return this.db
|
|
276
|
+
.prepare(
|
|
277
|
+
`SELECT
|
|
278
|
+
call_type,
|
|
279
|
+
COUNT(*) as call_count,
|
|
280
|
+
SUM(input_tokens) as total_input_tokens,
|
|
281
|
+
SUM(output_tokens) as total_output_tokens,
|
|
282
|
+
SUM(total_tokens) as total_tokens,
|
|
283
|
+
AVG(duration_ms) as avg_duration_ms,
|
|
284
|
+
SUM(duration_ms) as total_duration_ms
|
|
285
|
+
FROM agent_call_logs
|
|
286
|
+
WHERE session_id = ?
|
|
287
|
+
GROUP BY call_type`
|
|
288
|
+
)
|
|
289
|
+
.all(sessionId);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Get global stats grouped by agent_type within a date range
|
|
294
|
+
*/
|
|
295
|
+
getGlobalStats(startDate, endDate) {
|
|
296
|
+
return this.db
|
|
297
|
+
.prepare(
|
|
298
|
+
`SELECT
|
|
299
|
+
agent_type,
|
|
300
|
+
call_type,
|
|
301
|
+
COUNT(*) as call_count,
|
|
302
|
+
SUM(total_tokens) as total_tokens,
|
|
303
|
+
SUM(input_tokens) as total_input_tokens,
|
|
304
|
+
SUM(output_tokens) as total_output_tokens,
|
|
305
|
+
AVG(duration_ms) as avg_duration_ms
|
|
306
|
+
FROM agent_call_logs
|
|
307
|
+
WHERE started_at >= ? AND started_at <= ?
|
|
308
|
+
GROUP BY agent_type, call_type
|
|
309
|
+
ORDER BY total_tokens DESC`
|
|
310
|
+
)
|
|
311
|
+
.all(startDate, endDate);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Delete all call logs from the database.
|
|
316
|
+
* Returns the number of deleted rows.
|
|
317
|
+
*/
|
|
318
|
+
deleteAll() {
|
|
319
|
+
const result = this.db.prepare('DELETE FROM agent_call_logs').run();
|
|
320
|
+
return result.changes;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { BaseRepository } from './BaseRepository.js';
|
|
2
|
+
import { databaseManager } from './DatabaseManager.js';
|
|
3
|
+
import { mkdirSync, writeFileSync, rmSync, existsSync } from 'fs';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
|
|
6
|
+
/** Directory name for storing attachments within working directory */
|
|
7
|
+
export const ATTACHMENTS_DIR = '.attachments';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Get the attachments directory path for a session
|
|
11
|
+
* @param {string} workingDirectory - Project working directory
|
|
12
|
+
* @param {string} sessionId - Session ID
|
|
13
|
+
* @returns {string} Path to attachments directory
|
|
14
|
+
*/
|
|
15
|
+
export function getAttachmentsDir(workingDirectory, sessionId) {
|
|
16
|
+
return join(workingDirectory, ATTACHMENTS_DIR, sessionId);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Attachment repository class for message file attachments
|
|
21
|
+
*/
|
|
22
|
+
export class AttachmentRepository extends BaseRepository {
|
|
23
|
+
constructor() {
|
|
24
|
+
super('message_attachments', AttachmentRepository.#mapAttachment);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static #mapAttachment(row) {
|
|
28
|
+
return {
|
|
29
|
+
id: row.id,
|
|
30
|
+
messageId: row.message_id,
|
|
31
|
+
sessionId: row.session_id,
|
|
32
|
+
filename: row.filename,
|
|
33
|
+
mimeType: row.mime_type,
|
|
34
|
+
size: row.size_bytes,
|
|
35
|
+
storageType: row.storage_type,
|
|
36
|
+
content: row.content,
|
|
37
|
+
filePath: row.file_path,
|
|
38
|
+
createdAt: row.created_at,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Create an attachment - stores in DB and saves to disk
|
|
44
|
+
* @param {string} sessionId - Session ID
|
|
45
|
+
* @param {string|null} messageId - Message ID (null for initial session creation)
|
|
46
|
+
* @param {Object} file - File object with buffer, originalname, mimetype, size
|
|
47
|
+
* @param {string} workingDirectory - Working directory to save file to
|
|
48
|
+
* @returns {Object} Created attachment
|
|
49
|
+
*/
|
|
50
|
+
create(sessionId, messageId, file, workingDirectory) {
|
|
51
|
+
const id = databaseManager.generateId();
|
|
52
|
+
const now = Date.now();
|
|
53
|
+
|
|
54
|
+
// Store as base64 for backwards compatibility
|
|
55
|
+
const content = file.buffer.toString('base64');
|
|
56
|
+
|
|
57
|
+
// Save file to disk if working directory provided
|
|
58
|
+
let filePath = null;
|
|
59
|
+
if (workingDirectory) {
|
|
60
|
+
const attachmentsDir = getAttachmentsDir(workingDirectory, sessionId);
|
|
61
|
+
mkdirSync(attachmentsDir, { recursive: true });
|
|
62
|
+
|
|
63
|
+
// Use ID prefix to ensure uniqueness, preserve original filename for readability
|
|
64
|
+
const diskFilename = `${id}_${file.originalname}`;
|
|
65
|
+
filePath = join(attachmentsDir, diskFilename);
|
|
66
|
+
writeFileSync(filePath, file.buffer);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
this.db
|
|
70
|
+
.prepare(
|
|
71
|
+
`INSERT INTO message_attachments
|
|
72
|
+
(id, message_id, session_id, filename, mime_type, size_bytes, storage_type, content, file_path, created_at)
|
|
73
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
74
|
+
)
|
|
75
|
+
.run(
|
|
76
|
+
id,
|
|
77
|
+
messageId,
|
|
78
|
+
sessionId,
|
|
79
|
+
file.originalname,
|
|
80
|
+
file.mimetype,
|
|
81
|
+
file.size,
|
|
82
|
+
'base64',
|
|
83
|
+
content,
|
|
84
|
+
filePath,
|
|
85
|
+
now
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
return this.getById(id);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Create multiple attachments at once
|
|
93
|
+
* @param {string} sessionId - Session ID
|
|
94
|
+
* @param {string|null} messageId - Message ID
|
|
95
|
+
* @param {Array} files - Array of file objects
|
|
96
|
+
* @param {string} workingDirectory - Working directory to save files to
|
|
97
|
+
* @returns {Array} Created attachments
|
|
98
|
+
*/
|
|
99
|
+
createBatch(sessionId, messageId, files, workingDirectory) {
|
|
100
|
+
if (!files || files.length === 0) return [];
|
|
101
|
+
return files.map((file) => this.create(sessionId, messageId, file, workingDirectory));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Get attachments by message ID
|
|
106
|
+
* @param {string} messageId - Message ID
|
|
107
|
+
* @returns {Array} Attachments for the message
|
|
108
|
+
*/
|
|
109
|
+
getByMessageId(messageId) {
|
|
110
|
+
const rows = this.db
|
|
111
|
+
.prepare('SELECT * FROM message_attachments WHERE message_id = ? ORDER BY created_at ASC')
|
|
112
|
+
.all(messageId);
|
|
113
|
+
return this.mapAll(rows);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Get attachments by session ID
|
|
118
|
+
* @param {string} sessionId - Session ID
|
|
119
|
+
* @returns {Array} Attachments for the session
|
|
120
|
+
*/
|
|
121
|
+
getBySessionId(sessionId) {
|
|
122
|
+
const rows = this.db
|
|
123
|
+
.prepare('SELECT * FROM message_attachments WHERE session_id = ? ORDER BY created_at ASC')
|
|
124
|
+
.all(sessionId);
|
|
125
|
+
return this.mapAll(rows);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Get attachments without content (for listing)
|
|
130
|
+
* @param {string} messageId - Message ID
|
|
131
|
+
* @returns {Array} Attachments without content field
|
|
132
|
+
*/
|
|
133
|
+
getByMessageIdWithoutContent(messageId) {
|
|
134
|
+
const rows = this.db
|
|
135
|
+
.prepare(
|
|
136
|
+
`SELECT id, message_id, session_id, filename, mime_type, size_bytes, storage_type, file_path, created_at
|
|
137
|
+
FROM message_attachments WHERE message_id = ? ORDER BY created_at ASC`
|
|
138
|
+
)
|
|
139
|
+
.all(messageId);
|
|
140
|
+
return rows.map((row) => ({
|
|
141
|
+
id: row.id,
|
|
142
|
+
messageId: row.message_id,
|
|
143
|
+
sessionId: row.session_id,
|
|
144
|
+
filename: row.filename,
|
|
145
|
+
mimeType: row.mime_type,
|
|
146
|
+
size: row.size_bytes,
|
|
147
|
+
storageType: row.storage_type,
|
|
148
|
+
filePath: row.file_path,
|
|
149
|
+
createdAt: row.created_at,
|
|
150
|
+
}));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Update message ID for attachments (used when associating with a message)
|
|
155
|
+
* @param {string} sessionId - Session ID
|
|
156
|
+
* @param {string} messageId - Message ID to set
|
|
157
|
+
*/
|
|
158
|
+
updateMessageIdForSession(sessionId, messageId) {
|
|
159
|
+
this.db
|
|
160
|
+
.prepare('UPDATE message_attachments SET message_id = ? WHERE session_id = ? AND message_id IS NULL')
|
|
161
|
+
.run(messageId, sessionId);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Get pending attachments (those without a message ID)
|
|
166
|
+
* @param {string} sessionId - Session ID
|
|
167
|
+
* @returns {Array} Attachments without message ID
|
|
168
|
+
*/
|
|
169
|
+
getPendingBySessionId(sessionId) {
|
|
170
|
+
const rows = this.db
|
|
171
|
+
.prepare(
|
|
172
|
+
'SELECT * FROM message_attachments WHERE session_id = ? AND message_id IS NULL ORDER BY created_at ASC'
|
|
173
|
+
)
|
|
174
|
+
.all(sessionId);
|
|
175
|
+
return this.mapAll(rows);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Delete all attachments for a session from disk
|
|
180
|
+
* @param {string} workingDirectory - Working directory
|
|
181
|
+
* @param {string} sessionId - Session ID
|
|
182
|
+
*/
|
|
183
|
+
deleteSessionAttachmentsFromDisk(workingDirectory, sessionId) {
|
|
184
|
+
if (!workingDirectory) return;
|
|
185
|
+
|
|
186
|
+
const attachmentsDir = getAttachmentsDir(workingDirectory, sessionId);
|
|
187
|
+
if (existsSync(attachmentsDir)) {
|
|
188
|
+
rmSync(attachmentsDir, { recursive: true, force: true });
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { databaseManager } from './DatabaseManager.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Base repository class with common CRUD patterns
|
|
5
|
+
*/
|
|
6
|
+
export class BaseRepository {
|
|
7
|
+
#tableName;
|
|
8
|
+
#mapFn;
|
|
9
|
+
|
|
10
|
+
constructor(tableName, mapFn) {
|
|
11
|
+
this.#tableName = tableName;
|
|
12
|
+
this.#mapFn = mapFn;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
get tableName() {
|
|
16
|
+
return this.#tableName;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
get db() {
|
|
20
|
+
return databaseManager.get();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
map(row) {
|
|
24
|
+
return row ? this.#mapFn(row) : null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
mapAll(rows) {
|
|
28
|
+
return rows.map(this.#mapFn);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
getById(id) {
|
|
32
|
+
const row = this.db.prepare(`SELECT * FROM ${this.#tableName} WHERE id = ?`).get(id);
|
|
33
|
+
return this.map(row);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
delete(id) {
|
|
37
|
+
this.db.prepare(`DELETE FROM ${this.#tableName} WHERE id = ?`).run(id);
|
|
38
|
+
}
|
|
39
|
+
}
|