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,69 @@
|
|
|
1
|
+
/** @type {Map<string, {inputTokens: number, outputTokens: number, lastMessageOutput: number, cacheReadInputTokens: number, cacheCreationInputTokens: number}>}
|
|
2
|
+
* Current turn usage - accumulates across multiple messages within a turn
|
|
3
|
+
* Keyed by conversationId (Issue #175)
|
|
4
|
+
* - inputTokens: MAX seen across all messages (larger context with tool results)
|
|
5
|
+
* - outputTokens: ACCUMULATED across all messages
|
|
6
|
+
* - lastMessageOutput: Current message's output (to detect resets on message_start)
|
|
7
|
+
*/
|
|
8
|
+
const currentTurnUsage = new Map();
|
|
9
|
+
|
|
10
|
+
/** @type {Map<string, number>} Estimated output tokens from streamed content (for real-time updates) */
|
|
11
|
+
const estimatedOutputTokens = new Map();
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Rough token estimation: ~4 characters per token (standard for English text)
|
|
15
|
+
* @param {string} text
|
|
16
|
+
* @returns {number} Estimated token count
|
|
17
|
+
*/
|
|
18
|
+
function estimateTokens(text) {
|
|
19
|
+
return Math.ceil(text.length / 4);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Update current turn usage from stream events
|
|
24
|
+
* Accumulates across multiple messages within a single turn
|
|
25
|
+
* @param {string} conversationId
|
|
26
|
+
* @param {Object} usage - Usage from stream event (snake_case)
|
|
27
|
+
* @param {string} eventType - 'message_start' or 'message_delta'
|
|
28
|
+
* @returns {Object} Total turn usage (accumulated + current message)
|
|
29
|
+
*/
|
|
30
|
+
function updateTurnUsage(conversationId, usage, eventType) {
|
|
31
|
+
const current = currentTurnUsage.get(conversationId) || {
|
|
32
|
+
inputTokens: 0,
|
|
33
|
+
outputTokens: 0,
|
|
34
|
+
lastMessageOutput: 0,
|
|
35
|
+
cacheReadInputTokens: 0,
|
|
36
|
+
cacheCreationInputTokens: 0,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
if (eventType === 'message_start') {
|
|
40
|
+
// NEW MESSAGE STARTING
|
|
41
|
+
// 1. Finalize previous message's output
|
|
42
|
+
current.outputTokens += current.lastMessageOutput;
|
|
43
|
+
// 2. Reset tracker for new message
|
|
44
|
+
current.lastMessageOutput = 0;
|
|
45
|
+
// 3. Reset estimated output when actual message starts
|
|
46
|
+
estimatedOutputTokens.delete(conversationId);
|
|
47
|
+
// 4. For input tokens, keep the MAX (larger context with tool results)
|
|
48
|
+
current.inputTokens = Math.max(current.inputTokens, usage.input_tokens || 0);
|
|
49
|
+
current.cacheReadInputTokens = Math.max(current.cacheReadInputTokens, usage.cache_read_input_tokens || 0);
|
|
50
|
+
current.cacheCreationInputTokens = Math.max(current.cacheCreationInputTokens, usage.cache_creation_input_tokens || 0);
|
|
51
|
+
} else if (eventType === 'message_delta') {
|
|
52
|
+
// OUTPUT STREAMING - output_tokens is cumulative within this message
|
|
53
|
+
current.lastMessageOutput = usage.output_tokens || 0;
|
|
54
|
+
// Clear estimate when actual output tokens arrive
|
|
55
|
+
estimatedOutputTokens.delete(conversationId);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
currentTurnUsage.set(conversationId, current);
|
|
59
|
+
|
|
60
|
+
// Return the TOTAL (accumulated + current message's output)
|
|
61
|
+
return {
|
|
62
|
+
inputTokens: current.inputTokens,
|
|
63
|
+
outputTokens: current.outputTokens + current.lastMessageOutput,
|
|
64
|
+
cacheReadInputTokens: current.cacheReadInputTokens,
|
|
65
|
+
cacheCreationInputTokens: current.cacheCreationInputTokens,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export { estimateTokens, updateTurnUsage, currentTurnUsage, estimatedOutputTokens };
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Concurrency guard utility.
|
|
3
|
+
* Ensures only one async operation runs per key at a time.
|
|
4
|
+
* If a second call arrives while one is in-flight, it coalesces into a single
|
|
5
|
+
* follow-up execution after the current one completes.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Create a concurrency guard instance.
|
|
10
|
+
* Returns an object with `run` and `cleanup` methods plus access to internal state.
|
|
11
|
+
*
|
|
12
|
+
* @returns {{ run: Function, cleanup: Function, activeGenerations: Map, pendingRegenerations: Set }}
|
|
13
|
+
*/
|
|
14
|
+
export function createConcurrencyGuard() {
|
|
15
|
+
const activeGenerations = new Map(); // key -> Promise
|
|
16
|
+
const pendingRegenerations = new Set(); // keys that need follow-up after current completes
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Run an async function with concurrency guard.
|
|
20
|
+
* If a function is already running for this key, the call is coalesced
|
|
21
|
+
* and a single follow-up is scheduled after the current one completes.
|
|
22
|
+
*
|
|
23
|
+
* @param {string} key - The concurrency key (e.g., sessionId)
|
|
24
|
+
* @param {Function} fn - The async function to run
|
|
25
|
+
* @param {Object} options - Options
|
|
26
|
+
* @param {boolean} options.bypass - If true, skip the concurrency check (e.g., for user-initiated actions)
|
|
27
|
+
* @param {Function} options.onFollowUp - Function to call for follow-up generation after coalesced call
|
|
28
|
+
* @returns {Promise<*>} The result of fn()
|
|
29
|
+
*/
|
|
30
|
+
async function run(key, fn, options = {}) {
|
|
31
|
+
const { bypass = false, onFollowUp } = options;
|
|
32
|
+
|
|
33
|
+
// Concurrency guard: if a generation is already in-flight for this key,
|
|
34
|
+
// queue a single follow-up instead of running concurrently
|
|
35
|
+
if (activeGenerations.has(key) && !bypass) {
|
|
36
|
+
pendingRegenerations.add(key);
|
|
37
|
+
return activeGenerations.get(key);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const promise = fn();
|
|
41
|
+
activeGenerations.set(key, promise);
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
return await promise;
|
|
45
|
+
} finally {
|
|
46
|
+
activeGenerations.delete(key);
|
|
47
|
+
if (pendingRegenerations.has(key)) {
|
|
48
|
+
pendingRegenerations.delete(key);
|
|
49
|
+
// Schedule follow-up generation
|
|
50
|
+
if (onFollowUp) {
|
|
51
|
+
onFollowUp(key);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Clean up any pending and active state for a key (e.g., on session deletion)
|
|
59
|
+
* @param {string} key - The key to clean up
|
|
60
|
+
*/
|
|
61
|
+
function cleanup(key) {
|
|
62
|
+
activeGenerations.delete(key);
|
|
63
|
+
pendingRegenerations.delete(key);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Check if a generation is currently active for a key
|
|
68
|
+
* @param {string} key - The concurrency key
|
|
69
|
+
* @returns {boolean}
|
|
70
|
+
*/
|
|
71
|
+
function isActive(key) {
|
|
72
|
+
return activeGenerations.has(key);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Check if a regeneration is pending for a key
|
|
77
|
+
* @param {string} key - The concurrency key
|
|
78
|
+
* @returns {boolean}
|
|
79
|
+
*/
|
|
80
|
+
function isPending(key) {
|
|
81
|
+
return pendingRegenerations.has(key);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Get a snapshot of all active keys
|
|
86
|
+
* @returns {Array<string>}
|
|
87
|
+
*/
|
|
88
|
+
function activeKeys() {
|
|
89
|
+
return Array.from(activeGenerations.keys());
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get a snapshot of all pending keys
|
|
94
|
+
* @returns {Array<string>}
|
|
95
|
+
*/
|
|
96
|
+
function pendingKeys() {
|
|
97
|
+
return Array.from(pendingRegenerations);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
run,
|
|
102
|
+
cleanup,
|
|
103
|
+
isActive,
|
|
104
|
+
isPending,
|
|
105
|
+
activeKeys,
|
|
106
|
+
pendingKeys,
|
|
107
|
+
activeGenerations,
|
|
108
|
+
pendingRegenerations,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { WebSocketServer } from 'ws';
|
|
2
|
+
import { WS_MESSAGE_TYPES, parseMessage, createMessage } from '../../../shared/src/index.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* WebSocket manager class for handling WebSocket connections and messaging
|
|
6
|
+
*/
|
|
7
|
+
export class WebSocketManager {
|
|
8
|
+
/** @type {WebSocketServer|null} */
|
|
9
|
+
#wss = null;
|
|
10
|
+
|
|
11
|
+
/** @type {Set<import('ws').WebSocket>} */
|
|
12
|
+
#clients = new Set();
|
|
13
|
+
|
|
14
|
+
/** @type {Map<string, Set<import('ws').WebSocket>>} */
|
|
15
|
+
#sessionSubscriptions = new Map();
|
|
16
|
+
|
|
17
|
+
/** @type {Map<string, Set<import('ws').WebSocket>>} */
|
|
18
|
+
#projectSubscriptions = new Map();
|
|
19
|
+
|
|
20
|
+
/** @type {Map<string, Array<Object>>} */
|
|
21
|
+
#usageUpdateBuffer = new Map();
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Initialize WebSocket server
|
|
25
|
+
* @param {import('http').Server} server - HTTP server to attach to
|
|
26
|
+
* @returns {WebSocketServer}
|
|
27
|
+
*/
|
|
28
|
+
init(server) {
|
|
29
|
+
this.#wss = new WebSocketServer({ server, path: '/ws' });
|
|
30
|
+
|
|
31
|
+
this.#wss.on('connection', (ws) => {
|
|
32
|
+
this.#clients.add(ws);
|
|
33
|
+
|
|
34
|
+
ws.on('message', (data) => {
|
|
35
|
+
const message = parseMessage(data.toString());
|
|
36
|
+
if (!message) return;
|
|
37
|
+
|
|
38
|
+
this.#handleMessage(ws, message);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
ws.on('close', () => {
|
|
42
|
+
this.#clients.delete(ws);
|
|
43
|
+
// Remove from all session subscriptions
|
|
44
|
+
for (const subscribers of this.#sessionSubscriptions.values()) {
|
|
45
|
+
subscribers.delete(ws);
|
|
46
|
+
}
|
|
47
|
+
// Remove from all project subscriptions
|
|
48
|
+
for (const subscribers of this.#projectSubscriptions.values()) {
|
|
49
|
+
subscribers.delete(ws);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
ws.on('error', (error) => {
|
|
54
|
+
console.error('WebSocket error:', error);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
return this.#wss;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Handle incoming WebSocket message
|
|
63
|
+
* @param {import('ws').WebSocket} ws
|
|
64
|
+
* @param {Object} message
|
|
65
|
+
*/
|
|
66
|
+
#handleMessage(ws, message) {
|
|
67
|
+
const handlers = {
|
|
68
|
+
[WS_MESSAGE_TYPES.SUBSCRIBE_SESSION]: () => this.#handleSubscribeSession(ws, message),
|
|
69
|
+
[WS_MESSAGE_TYPES.UNSUBSCRIBE_SESSION]: () => this.#handleUnsubscribeSession(ws, message),
|
|
70
|
+
[WS_MESSAGE_TYPES.SUBSCRIBE_PROJECT]: () => this.#handleSubscribeProject(ws, message),
|
|
71
|
+
[WS_MESSAGE_TYPES.UNSUBSCRIBE_PROJECT]: () => this.#handleUnsubscribeProject(ws, message),
|
|
72
|
+
};
|
|
73
|
+
handlers[message.type]?.();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
#handleSubscribeSession(ws, message) {
|
|
77
|
+
const { sessionId } = message;
|
|
78
|
+
if (!sessionId) return;
|
|
79
|
+
|
|
80
|
+
if (!this.#sessionSubscriptions.has(sessionId)) {
|
|
81
|
+
this.#sessionSubscriptions.set(sessionId, new Set());
|
|
82
|
+
}
|
|
83
|
+
this.#sessionSubscriptions.get(sessionId).add(ws);
|
|
84
|
+
this.#replayBufferedUsageUpdates(ws, sessionId);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
#replayBufferedUsageUpdates(ws, sessionId) {
|
|
88
|
+
const buffered = this.#usageUpdateBuffer.get(sessionId);
|
|
89
|
+
if (!buffered || buffered.length === 0) return;
|
|
90
|
+
|
|
91
|
+
for (const bufferedMsg of buffered) {
|
|
92
|
+
const msg = createMessage(bufferedMsg.type, bufferedMsg);
|
|
93
|
+
if (ws.readyState === 1) {
|
|
94
|
+
ws.send(msg);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
this.#usageUpdateBuffer.delete(sessionId);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
#handleUnsubscribeSession(ws, message) {
|
|
101
|
+
const { sessionId } = message;
|
|
102
|
+
if (!sessionId) return;
|
|
103
|
+
this.#sessionSubscriptions.get(sessionId)?.delete(ws);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
#handleSubscribeProject(ws, message) {
|
|
107
|
+
const { projectId } = message;
|
|
108
|
+
if (!projectId) return;
|
|
109
|
+
|
|
110
|
+
if (!this.#projectSubscriptions.has(projectId)) {
|
|
111
|
+
this.#projectSubscriptions.set(projectId, new Set());
|
|
112
|
+
}
|
|
113
|
+
this.#projectSubscriptions.get(projectId).add(ws);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
#handleUnsubscribeProject(ws, message) {
|
|
117
|
+
const { projectId } = message;
|
|
118
|
+
if (!projectId) return;
|
|
119
|
+
this.#projectSubscriptions.get(projectId)?.delete(ws);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Broadcast message to all connected clients
|
|
124
|
+
* @param {string} type - Message type
|
|
125
|
+
* @param {Object} payload - Message payload
|
|
126
|
+
*/
|
|
127
|
+
broadcast(type, payload) {
|
|
128
|
+
const message = createMessage(type, payload);
|
|
129
|
+
for (const client of this.#clients) {
|
|
130
|
+
if (client.readyState === 1) {
|
|
131
|
+
// WebSocket.OPEN
|
|
132
|
+
client.send(message);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Broadcast message to clients subscribed to a session
|
|
139
|
+
* @param {string} sessionId - Session ID
|
|
140
|
+
* @param {string} type - Message type
|
|
141
|
+
* @param {Object} payload - Message payload
|
|
142
|
+
*/
|
|
143
|
+
broadcastToSession(sessionId, type, payload) {
|
|
144
|
+
const subscribers = this.#sessionSubscriptions.get(sessionId);
|
|
145
|
+
|
|
146
|
+
// Buffer SESSION_USAGE_UPDATE messages if no subscribers exist
|
|
147
|
+
if (type === 'session:usage_update' && (!subscribers || subscribers.size === 0)) {
|
|
148
|
+
if (!this.#usageUpdateBuffer.has(sessionId)) {
|
|
149
|
+
this.#usageUpdateBuffer.set(sessionId, []);
|
|
150
|
+
}
|
|
151
|
+
const buffer = this.#usageUpdateBuffer.get(sessionId);
|
|
152
|
+
buffer.push({ type, ...payload });
|
|
153
|
+
// Keep reasonable buffer size (max 50 messages)
|
|
154
|
+
if (buffer.length > 50) {
|
|
155
|
+
buffer.shift();
|
|
156
|
+
}
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (!subscribers || subscribers.size === 0) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const message = createMessage(type, payload);
|
|
165
|
+
for (const client of subscribers) {
|
|
166
|
+
if (client.readyState === 1) {
|
|
167
|
+
// WebSocket.OPEN
|
|
168
|
+
client.send(message);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Broadcast message to clients subscribed to a project
|
|
175
|
+
* @param {string} projectId - Project ID
|
|
176
|
+
* @param {string} type - Message type
|
|
177
|
+
* @param {Object} payload - Message payload
|
|
178
|
+
*/
|
|
179
|
+
broadcastToProject(projectId, type, payload) {
|
|
180
|
+
const subscribers = this.#projectSubscriptions.get(projectId);
|
|
181
|
+
if (!subscribers || subscribers.size === 0) return;
|
|
182
|
+
|
|
183
|
+
const message = createMessage(type, payload);
|
|
184
|
+
for (const client of subscribers) {
|
|
185
|
+
if (client.readyState === 1) {
|
|
186
|
+
// WebSocket.OPEN
|
|
187
|
+
client.send(message);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Get WebSocket server instance
|
|
194
|
+
* @returns {WebSocketServer|null}
|
|
195
|
+
*/
|
|
196
|
+
getServer() {
|
|
197
|
+
return this.#wss;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Get all connected clients
|
|
202
|
+
* @returns {Set<import('ws').WebSocket>}
|
|
203
|
+
*/
|
|
204
|
+
getClients() {
|
|
205
|
+
return this.#clients;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Get session subscriptions
|
|
210
|
+
* @returns {Map<string, Set<import('ws').WebSocket>>}
|
|
211
|
+
*/
|
|
212
|
+
getSessionSubscriptions() {
|
|
213
|
+
return this.#sessionSubscriptions;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Get project subscriptions
|
|
218
|
+
* @returns {Map<string, Set<import('ws').WebSocket>>}
|
|
219
|
+
*/
|
|
220
|
+
getProjectSubscriptions() {
|
|
221
|
+
return this.#projectSubscriptions;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Close the WebSocket server
|
|
226
|
+
*/
|
|
227
|
+
close() {
|
|
228
|
+
if (this.#wss) {
|
|
229
|
+
this.#wss.close();
|
|
230
|
+
this.#wss = null;
|
|
231
|
+
}
|
|
232
|
+
this.#clients.clear();
|
|
233
|
+
this.#sessionSubscriptions.clear();
|
|
234
|
+
this.#projectSubscriptions.clear();
|
|
235
|
+
this.#usageUpdateBuffer.clear();
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Singleton instance
|
|
240
|
+
export const webSocketManager = new WebSocketManager();
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export { WebSocketManager, webSocketManager } from './WebSocketManager.js';
|
|
2
|
+
|
|
3
|
+
// Legacy function exports for backward compatibility
|
|
4
|
+
import { webSocketManager } from './WebSocketManager.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Initialize WebSocket server
|
|
8
|
+
* @param {import('http').Server} server
|
|
9
|
+
* @returns {import('ws').WebSocketServer}
|
|
10
|
+
*/
|
|
11
|
+
export function initWebSocket(server) {
|
|
12
|
+
return webSocketManager.init(server);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Broadcast message to all connected clients
|
|
17
|
+
* @param {string} type
|
|
18
|
+
* @param {Object} payload
|
|
19
|
+
*/
|
|
20
|
+
export function broadcast(type, payload) {
|
|
21
|
+
webSocketManager.broadcast(type, payload);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Broadcast message to clients subscribed to a session
|
|
26
|
+
* @param {string} sessionId
|
|
27
|
+
* @param {string} type
|
|
28
|
+
* @param {Object} payload
|
|
29
|
+
*/
|
|
30
|
+
export function broadcastToSession(sessionId, type, payload) {
|
|
31
|
+
webSocketManager.broadcastToSession(sessionId, type, payload);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Broadcast message to clients subscribed to a project
|
|
36
|
+
* @param {string} projectId
|
|
37
|
+
* @param {string} type
|
|
38
|
+
* @param {Object} payload
|
|
39
|
+
*/
|
|
40
|
+
export function broadcastToProject(projectId, type, payload) {
|
|
41
|
+
webSocketManager.broadcastToProject(projectId, type, payload);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get WebSocket server instance
|
|
46
|
+
* @returns {import('ws').WebSocketServer|null}
|
|
47
|
+
*/
|
|
48
|
+
export function getWebSocketServer() {
|
|
49
|
+
return webSocketManager.getServer();
|
|
50
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@circuschief/shared",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "Apache-2.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./src/index.js",
|
|
9
|
+
"./types": "./src/types.js",
|
|
10
|
+
"./protocol": "./src/protocol.js",
|
|
11
|
+
"./constants": "./src/constants.js",
|
|
12
|
+
"./contracts/*": "./src/contracts/*.js",
|
|
13
|
+
"./utils": "./src/utils.js",
|
|
14
|
+
"./routeParams": "./src/routeParams.js"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"test": "vitest run",
|
|
18
|
+
"test:coverage": "vitest run --coverage",
|
|
19
|
+
"test:watch": "vitest"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"zod": "^4.2.1"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"vitest": "^4.0.16"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export const DEFAULT_SERVER_PORT = 5000;
|
|
2
|
+
|
|
3
|
+
export const API_PREFIX = '/api';
|
|
4
|
+
export const WS_PATH = '/ws';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Default token cost weights for calculating Billable Token Equivalent (BTE)
|
|
8
|
+
* These weights represent relative costs compared to input tokens (1.0 = base rate)
|
|
9
|
+
*/
|
|
10
|
+
export const DEFAULT_TOKEN_COST_WEIGHTS = {
|
|
11
|
+
input: 1.0, // Base rate
|
|
12
|
+
output: 5.0, // 5x input cost (output tokens are more expensive)
|
|
13
|
+
cacheRead: 0.1, // 90% discount for cache reads
|
|
14
|
+
cacheCreation: 1.25 // 25% premium for cache creation
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const MAX_JSON_SIZE = '50mb';
|
|
18
|
+
|
|
19
|
+
export const WS_RECONNECT_BASE_DELAY = 2000;
|
|
20
|
+
export const WS_RECONNECT_MAX_DELAY = 30000;
|
|
21
|
+
|
|
22
|
+
export const TOAST_DURATION = 5000;
|
|
23
|
+
|
|
24
|
+
export const DEFAULT_SYSTEM_PROMPT = `You are Claude Code, an AI coding assistant. You help users with software engineering tasks including writing code, debugging, refactoring, and explaining code. You have full access to the shell and can execute any commands needed to assist the user. Be helpful, accurate, and thorough.
|
|
25
|
+
|
|
26
|
+
IMPORTANT: Your working directory is already set correctly for this session. NEVER use \`cd\` to change to a hardcoded project path before running commands (e.g., \`cd /path/to/project && git status\`). This bypasses git worktree isolation and causes commands to run in the wrong directory. Always run commands directly without changing directory.
|
|
27
|
+
|
|
28
|
+
## Canvas Behavior
|
|
29
|
+
IMPORTANT: NEVER proactively put artifacts on the canvas unless the user explicitly requests it. Do not put images, markdown documents, code snippets, data visualizations, PDFs, or other artifacts on the canvas without being asked. Only use the canvas when the user specifically asks you to display or share something.
|
|
30
|
+
|
|
31
|
+
## Plan Files
|
|
32
|
+
When creating plan files or design documents, always write them to a temporary directory:
|
|
33
|
+
- Use \`~/.claude/plans/<descriptive-name>.md\` for plan files
|
|
34
|
+
- Use the Write tool to create these files
|
|
35
|
+
- This keeps plans organized and separate from the main codebase`;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Default prompt for generating session titles
|
|
39
|
+
*/
|
|
40
|
+
export const DEFAULT_SESSION_TITLE_PROMPT = `Guidelines for generating session titles:
|
|
41
|
+
- state the goal of the session - ignore the goal of the conversation, we're interested in the goal of the session as a whole
|
|
42
|
+
- If a PR was created, format as "PR #N: <strategic goal>"
|
|
43
|
+
- Only change the title if the session's fundamental purpose has changed
|
|
44
|
+
- Keep titles concise (max 60 characters)`;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
export const CreateCanvasItemRequest = z.object({
|
|
4
|
+
filePath: z.string(),
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
export const CanvasItemResponse = z.object({
|
|
8
|
+
id: z.string().uuid(),
|
|
9
|
+
sessionId: z.string().uuid().nullable(),
|
|
10
|
+
type: z.enum(['image', 'markdown', 'text', 'json', 'pdf', 'code']),
|
|
11
|
+
content: z.string().nullable(),
|
|
12
|
+
data: z.string().nullable(),
|
|
13
|
+
mimeType: z.string().nullable(),
|
|
14
|
+
filename: z.string().nullable(),
|
|
15
|
+
width: z.number().nullable(),
|
|
16
|
+
height: z.number().nullable(),
|
|
17
|
+
createdAt: z.number(),
|
|
18
|
+
updatedAt: z.number(),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export const UpdateCanvasItemRequest = z.object({
|
|
22
|
+
content: z.string().min(0),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export const CanvasListResponse = z.array(CanvasItemResponse);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
export const CreateCommandButtonRequest = z.object({
|
|
4
|
+
label: z.string().min(1, 'Label is required'),
|
|
5
|
+
command: z.string().min(1, 'Command is required'),
|
|
6
|
+
sortOrder: z.number().int().optional().default(0),
|
|
7
|
+
showOnList: z.boolean().optional().default(false),
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export const UpdateCommandButtonRequest = z.object({
|
|
11
|
+
label: z.string().min(1).optional(),
|
|
12
|
+
command: z.string().min(1).optional(),
|
|
13
|
+
sortOrder: z.number().int().optional(),
|
|
14
|
+
showOnList: z.boolean().optional(),
|
|
15
|
+
}).refine(obj => Object.keys(obj).length > 0, 'At least one field must be provided for update');
|
|
16
|
+
|
|
17
|
+
export const CommandButtonResponse = z.object({
|
|
18
|
+
id: z.string(),
|
|
19
|
+
projectId: z.string(),
|
|
20
|
+
label: z.string(),
|
|
21
|
+
command: z.string(),
|
|
22
|
+
sortOrder: z.number().int(),
|
|
23
|
+
showOnList: z.boolean(),
|
|
24
|
+
createdAt: z.number(),
|
|
25
|
+
updatedAt: z.number(),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export const CommandButtonListResponse = z.array(CommandButtonResponse);
|
|
29
|
+
|
|
30
|
+
export const CommandRunResponse = z.object({
|
|
31
|
+
runId: z.string(),
|
|
32
|
+
buttonId: z.string(),
|
|
33
|
+
status: z.enum(['running', 'success', 'error', 'killed']),
|
|
34
|
+
exitCode: z.number().int().nullable(),
|
|
35
|
+
output: z.string().optional(),
|
|
36
|
+
});
|