circuschief 0.6.0 → 0.8.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 +1 -1
- package/packages/server/src/agents/adapters/CodexAdapter.js +5 -4
- package/packages/server/src/api/canvas.js +22 -57
- package/packages/server/src/api/index.js +2 -0
- package/packages/server/src/api/kanban.js +4 -2
- package/packages/server/src/api/projects-helpers.js +20 -3
- package/packages/server/src/api/projects-session-helpers.js +35 -4
- package/packages/server/src/api/projects.js +11 -0
- package/packages/server/src/api/providers.js +11 -1
- package/packages/server/src/api/sessions-commands.js +35 -17
- package/packages/server/src/api/sessions-draft.js +1 -0
- package/packages/server/src/api/sessions-lifecycle.js +10 -10
- package/packages/server/src/api/sessions-patch.js +4 -0
- package/packages/server/src/api/sessions.js +6 -5
- package/packages/server/src/api/settings.js +52 -4
- package/packages/server/src/database.js +0 -2
- package/packages/server/src/db/ConversationRepository.js +16 -3
- package/packages/server/src/db/DatabaseManager.js +5 -1
- package/packages/server/src/db/ProjectDefaultsRepository.js +50 -40
- package/packages/server/src/db/ProviderRepository.js +87 -32
- package/packages/server/src/db/SessionRepository.js +13 -8
- package/packages/server/src/db/SettingsRepository.js +44 -16
- package/packages/server/src/db/conversation-helpers.js +1 -0
- package/packages/server/src/db/index.js +0 -3
- package/packages/server/src/db/migrations/index.js +36 -200
- package/packages/server/src/db/seedBaselineData.js +137 -0
- package/packages/server/src/db/session-helpers.js +9 -3
- package/packages/server/src/middleware/sessionLookup.js +81 -8
- package/packages/server/src/schema.sql +157 -132
- package/packages/server/src/scripts/backupDatabase.js +21 -0
- package/packages/server/src/scripts/dbUtils.js +81 -0
- package/packages/server/src/scripts/inspectDatabaseSchema.js +81 -0
- package/packages/server/src/scripts/validateDatabaseBaseline.js +212 -0
- package/packages/server/src/services/agentCallLogger.js +1 -1
- package/packages/server/src/services/codexSpawnHelper.js +9 -0
- package/packages/server/src/services/commandButtonPrompts.js +48 -0
- package/packages/server/src/services/commandRunner.js +7 -1
- package/packages/server/src/services/draftSessionService.js +2 -0
- package/packages/server/src/services/e2eSpawnCapture.js +147 -0
- package/packages/server/src/services/gitCommitAttribution.js +120 -0
- package/packages/server/src/services/gitService.js +11 -2
- package/packages/server/src/services/gitSessionSetup.js +11 -1
- package/packages/server/src/services/kanbanTriggers.js +6 -3
- package/packages/server/src/services/nodeSpawnHelper.js +9 -0
- package/packages/server/src/services/prUrlService.js +3 -3
- package/packages/server/src/services/queryParamBuilder.js +90 -0
- package/packages/server/src/services/sessionDuplicator.js +1 -5
- package/packages/server/src/services/sessionExecution.js +56 -106
- package/packages/server/src/services/sessionPrompts.js +16 -47
- package/packages/server/src/services/sessionProvider.js +16 -8
- package/packages/server/src/services/streamEventCallbacks.js +72 -40
- package/packages/server/src/services/streamEventHandler.js +13 -2
- package/packages/server/src/services/streamUsageHandler.js +6 -0
- package/packages/server/src/services/summaryClaudeClient.js +37 -12
- package/packages/server/src/services/summaryModelClient.js +154 -0
- package/packages/server/src/services/summaryModelResolver.js +148 -0
- package/packages/server/src/services/summaryService.js +11 -7
- package/packages/server/src/services/summaryStaleCheck.js +23 -4
- package/packages/server/src/services/templateTriggerService.js +3 -1
- package/packages/server/src/services/usageTracker.js +5 -1
- package/packages/server/src/services/visibleFinalErrorMessage.js +123 -0
- package/packages/shared/src/constants.js +4 -2
- package/packages/shared/src/contracts/commandButtons.js +16 -2
- package/packages/shared/src/contracts/projects.js +4 -2
- package/packages/shared/src/contracts/providers.js +60 -0
- package/packages/shared/src/contracts/sessions.js +2 -1
- package/packages/shared/src/contracts/templates.js +2 -2
- package/packages/shared/src/types.js +1 -9
- package/packages/shared/src/utils.js +11 -19
- package/packages/web/dist/assets/ActiveSessionsView-B0XHqLmv.js +1 -0
- package/packages/web/dist/assets/{AgentLogsView-Cdw4nmvd.js → AgentLogsView-DmsjUMlB.js} +2 -2
- package/packages/web/dist/assets/ApiClient-C3ztI9s9.js +1 -0
- package/packages/web/dist/assets/ArchiveConfirmModal-BlCyn5Vt.js +1 -0
- package/packages/web/dist/assets/ArchiveConfirmModal-DeoCVGXt.css +1 -0
- package/packages/web/dist/assets/{CommandButtonDetailView-DnFhJY5A.js → CommandButtonDetailView-CdSCPp78.js} +1 -1
- package/packages/web/dist/assets/EffortLevelSelector-hc2MNKg6.js +1 -0
- package/packages/web/dist/assets/{GeneralSettingsView-CQkmdczf.js → GeneralSettingsView-D1nI8_zk.js} +1 -1
- package/packages/web/dist/assets/InputWithButton-CAkttyqx.js +1 -0
- package/packages/web/dist/assets/{InputWithButton-cYdrEmTs.css → InputWithButton-D9HMvfR5.css} +1 -1
- package/packages/web/dist/assets/{InterpolationHelp-PfYR3KJo.js → InterpolationHelp-BO1j9Z3_.js} +1 -1
- package/packages/web/dist/assets/MarkdownEditor-ucRAP_UM.js +2 -0
- package/packages/web/dist/assets/{ModelSelector-BZOT1Jc6.css → ModelSelector-BSxKUSus.css} +1 -1
- package/packages/web/dist/assets/ModelSelector-CwTz8ZWO.js +1 -0
- package/packages/web/dist/assets/NewSessionView-BDPb-1qr.css +1 -0
- package/packages/web/dist/assets/NewSessionView-BsDrp8mj.js +3 -0
- package/packages/web/dist/assets/ProjectEditView-CwTOeSun.js +1 -0
- package/packages/web/dist/assets/ProjectEditView-J15mcsWz.css +1 -0
- package/packages/web/dist/assets/{ProjectListView-CuYMmd3O.js → ProjectListView-DcNyuINs.js} +1 -1
- package/packages/web/dist/assets/{ProjectNewView-CNaA4Maf.js → ProjectNewView-B5YV62hv.js} +1 -1
- package/packages/web/dist/assets/ProvidersView-bZemq_Rv.css +1 -0
- package/packages/web/dist/assets/ProvidersView-nY9GnDdO.js +1 -0
- package/packages/web/dist/assets/QuickResponseSettings-B352c75l.css +1 -0
- package/packages/web/dist/assets/QuickResponseSettings-BQwQXuL7.js +1 -0
- package/packages/web/dist/assets/{QuickResponsesPanel-DIBQFj0W.css → QuickResponsesPanel-BlFDvnZ2.css} +1 -1
- package/packages/web/dist/assets/{QuickResponsesPanel-BqMYSHb0.js → QuickResponsesPanel-BzSYcCSP.js} +1 -1
- package/packages/web/dist/assets/{ResizableTextarea-wYF3K2RO.js → ResizableTextarea-B3YIdIXv.js} +1 -1
- package/packages/web/dist/assets/{SessionCard-bLaQEWWX.js → SessionCard-CjE1tXiT.js} +1 -1
- package/packages/web/dist/assets/SessionDetailView-3cPZrbS3.js +36 -0
- package/packages/web/dist/assets/SessionDetailView-CZRZMrfM.css +1 -0
- package/packages/web/dist/assets/SessionFormOptions-B6AxyREh.js +1 -0
- package/packages/web/dist/assets/SessionFormOptions-BpUALRKn.css +1 -0
- package/packages/web/dist/assets/SessionListView-B5_6gW49.css +1 -0
- package/packages/web/dist/assets/SessionListView-CLXBfLcq.js +1 -0
- package/packages/web/dist/assets/{SessionLogStream-DTnDAF95.js → SessionLogStream-LlZ3z_Xj.js} +1 -1
- package/packages/web/dist/assets/{SettingsView-DNLUSsHV.js → SettingsView-CTGiGvR2.js} +1 -1
- package/packages/web/dist/assets/{SlashCommandWizard-CRGFaO8t.js → SlashCommandWizard-Cy04d7-o.js} +1 -1
- package/packages/web/dist/assets/{SlashCommandWizard-Dn7sNaBd.css → SlashCommandWizard-DJzw3LP5.css} +1 -1
- package/packages/web/dist/assets/SummarySettingsView-BR2ZjEa3.js +1 -0
- package/packages/web/dist/assets/SummarySettingsView-l2bxHmZZ.css +1 -0
- package/packages/web/dist/assets/TemplateDetailView-DH6Oswsp.js +1 -0
- package/packages/web/dist/assets/{commandButtons-Bbjf3fCt.js → commandButtons-BfqR-fqq.js} +1 -1
- package/packages/web/dist/assets/index-1zziPL6l.js +1 -0
- package/packages/web/dist/assets/index-7kzHPxSF.js +1 -0
- package/packages/web/dist/assets/index-B0N_obMc.js +1 -0
- package/packages/web/dist/assets/index-BNk_gdfI.js +1 -0
- package/packages/web/dist/assets/{index-gmCCsCQ1.css → index-BY174HVJ.css} +1 -1
- package/packages/web/dist/assets/index-CSqaAH-0.js +1 -0
- package/packages/web/dist/assets/index-C_q4WlK8.js +1 -0
- package/packages/web/dist/assets/index-D1wpU4y0.js +7 -0
- package/packages/web/dist/assets/index-D5zCA8sD.js +1 -0
- package/packages/web/dist/assets/index-DGR8ELWY.js +1 -0
- package/packages/web/dist/assets/index-DHga8pXo.js +1 -0
- package/packages/web/dist/assets/index-DSby02Wl.js +1 -0
- package/packages/web/dist/assets/{index-Cf6vdW-B.js → index-DgkC10TW.js} +3 -3
- package/packages/web/dist/assets/index-DqjXJTVI.js +1 -0
- package/packages/web/dist/assets/{index-Bs7Qf5D6.js → index-DtfUt785.js} +2 -2
- package/packages/web/dist/assets/index-_4S2uLDI.js +1 -0
- package/packages/web/dist/assets/{index-BQL_L4gL.js → index-fK8FIZgP.js} +15 -14
- package/packages/web/dist/assets/index-gmiZeFXN.js +1 -0
- package/packages/web/dist/assets/index-irD539ZM.js +3 -0
- package/packages/web/dist/assets/index-yq-E1Y00.js +1 -0
- package/packages/web/dist/assets/{projects-CPt3AB7U.js → projects-DXYQNJIi.js} +1 -1
- package/packages/web/dist/assets/{providers-ChfeMvUq.js → providers-1bnH-exJ.js} +1 -1
- package/packages/web/dist/assets/sessions-6zGUlFrt.js +1 -0
- package/packages/web/dist/assets/settings-MbfRir0d.js +1 -0
- package/packages/web/dist/index.html +2 -2
- package/packages/server/src/api/sessions-notes.js +0 -51
- package/packages/server/src/db/SessionNoteRepository.js +0 -60
- package/packages/server/src/db/migrations/canvasItemsMigrations.js +0 -109
- package/packages/server/src/db/migrations/conversationsMigrations.js +0 -183
- package/packages/server/src/db/migrations/kanbanMigrations.js +0 -99
- package/packages/server/src/db/migrations/miscMigrations.js +0 -369
- package/packages/server/src/db/migrations/projectsMigrations.js +0 -99
- package/packages/server/src/db/migrations/sessionsMigrations.js +0 -282
- package/packages/web/dist/assets/ActiveSessionsView-UCbQrF1b.js +0 -1
- package/packages/web/dist/assets/ApiClient-CWbXWDUY.js +0 -1
- package/packages/web/dist/assets/ArchiveConfirmModal-BQ-4gI0R.css +0 -1
- package/packages/web/dist/assets/ArchiveConfirmModal-J48eh3zw.js +0 -1
- package/packages/web/dist/assets/EffortLevelSelector-bXbPo4Zw.js +0 -1
- package/packages/web/dist/assets/InputWithButton-XyM3k6lN.js +0 -1
- package/packages/web/dist/assets/MarkdownEditor-P8F5kO-o.js +0 -2
- package/packages/web/dist/assets/ModelSelector-CowKfGMP.js +0 -1
- package/packages/web/dist/assets/NewSessionView-D_Hi7M9g.css +0 -1
- package/packages/web/dist/assets/NewSessionView-DkjFLvHU.js +0 -3
- package/packages/web/dist/assets/ProjectEditView-CpeKj-_w.css +0 -1
- package/packages/web/dist/assets/ProjectEditView-embVT7NC.js +0 -1
- package/packages/web/dist/assets/ProvidersView-C7rydtOd.js +0 -1
- package/packages/web/dist/assets/ProvidersView-DE82G_5W.css +0 -1
- package/packages/web/dist/assets/QuickResponseSettings-B8188A1D.css +0 -1
- package/packages/web/dist/assets/QuickResponseSettings-BTQEKhwJ.js +0 -1
- package/packages/web/dist/assets/SessionDetailView-Cv-xMzXp.css +0 -1
- package/packages/web/dist/assets/SessionDetailView-CvQOUsW2.js +0 -36
- package/packages/web/dist/assets/SessionFormOptions-3pzbgI2Q.js +0 -1
- package/packages/web/dist/assets/SessionFormOptions-DhhIkjIS.css +0 -1
- package/packages/web/dist/assets/SessionListView-Dranfb72.js +0 -1
- package/packages/web/dist/assets/SessionListView-fHlQyecX.css +0 -1
- package/packages/web/dist/assets/SummarySettingsView-C7G_suHp.js +0 -1
- package/packages/web/dist/assets/SummarySettingsView-DcsmSVJI.css +0 -1
- package/packages/web/dist/assets/TemplateDetailView-B78_DLMR.js +0 -1
- package/packages/web/dist/assets/index--V7c-VZf.js +0 -1
- package/packages/web/dist/assets/index-8Q04yd7H.js +0 -1
- package/packages/web/dist/assets/index-B47XRBDH.js +0 -1
- package/packages/web/dist/assets/index-BXbgZrhS.js +0 -1
- package/packages/web/dist/assets/index-CGhDVPen.js +0 -1
- package/packages/web/dist/assets/index-CKcRO1A6.js +0 -1
- package/packages/web/dist/assets/index-CTq-SLIW.js +0 -1
- package/packages/web/dist/assets/index-CYyos3iC.js +0 -1
- package/packages/web/dist/assets/index-CsCREAxF.js +0 -1
- package/packages/web/dist/assets/index-DJTTk_8T.js +0 -3
- package/packages/web/dist/assets/index-DPqUJ5JK.js +0 -1
- package/packages/web/dist/assets/index-EwAe1dKg.js +0 -1
- package/packages/web/dist/assets/index-JBA8axyA.js +0 -1
- package/packages/web/dist/assets/index-JkVHFtK5.js +0 -7
- package/packages/web/dist/assets/index-gMPUwT55.js +0 -1
- package/packages/web/dist/assets/index-wadc_0zT.js +0 -1
- package/packages/web/dist/assets/sessions-CwPsJOb1.js +0 -1
- package/packages/web/dist/assets/settings-BOj6wq6t.js +0 -1
|
@@ -8,7 +8,6 @@ import { requireSession, requireSessionAndProject } from '../middleware/sessionL
|
|
|
8
8
|
import { commandRunner } from '../services/commandRunner.js';
|
|
9
9
|
|
|
10
10
|
// Import sub-routers
|
|
11
|
-
import notesRouter from './sessions-notes.js';
|
|
12
11
|
import conversationsRouter from './sessions-conversations.js';
|
|
13
12
|
import commandsRouter from './sessions-commands.js';
|
|
14
13
|
import patchRouter from './sessions-patch.js';
|
|
@@ -21,7 +20,6 @@ import draftRouter from './sessions-draft.js';
|
|
|
21
20
|
const router = Router();
|
|
22
21
|
|
|
23
22
|
// Mount sub-routers
|
|
24
|
-
router.use('/', notesRouter);
|
|
25
23
|
router.use('/', conversationsRouter);
|
|
26
24
|
router.use('/', commandsRouter);
|
|
27
25
|
router.use('/', patchRouter);
|
|
@@ -108,11 +106,14 @@ router.get('/:id', requireSession, (req, res) => {
|
|
|
108
106
|
const allMessages = messages.getBySessionId(req.params.id);
|
|
109
107
|
const hasResponses = allMessages.some(msg => msg.role === 'assistant');
|
|
110
108
|
|
|
111
|
-
//
|
|
109
|
+
// Session details are for the requested session; command runs are workflow-root scoped.
|
|
110
|
+
const commandRunSessionId = sessions.getRootSessionId(req.params.id) || req.params.id;
|
|
111
|
+
|
|
112
|
+
// Get command run statuses (latest run per button for this workflow)
|
|
112
113
|
// Completed runs from DB
|
|
113
|
-
const dbRuns = commandRuns.getLatestRunsForSession(
|
|
114
|
+
const dbRuns = commandRuns.getLatestRunsForSession(commandRunSessionId);
|
|
114
115
|
// Currently running commands from memory - filter all runs for this session
|
|
115
|
-
const allRunning = commandRunner.getRunsBySession(
|
|
116
|
+
const allRunning = commandRunner.getRunsBySession(commandRunSessionId);
|
|
116
117
|
const runningRuns = allRunning.filter(run => run.status === 'running');
|
|
117
118
|
|
|
118
119
|
// Build map of buttonId -> run data
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
|
-
import { settings } from '../db/index.js';
|
|
2
|
+
import { modelProviders, settings } from '../db/index.js';
|
|
3
3
|
import { DEFAULT_SESSION_TITLE_PROMPT } from '../services/summaryService.js';
|
|
4
4
|
|
|
5
5
|
const router = Router();
|
|
6
|
+
const SUPPORTED_SUMMARY_PROVIDER_KINDS = new Set(['anthropic', 'openai']);
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* GET /api/settings/token-weights
|
|
@@ -93,19 +94,42 @@ router.get('/summary', (req, res) => {
|
|
|
93
94
|
*/
|
|
94
95
|
router.put('/summary', (req, res) => {
|
|
95
96
|
try {
|
|
96
|
-
const
|
|
97
|
+
const body = req.body || {};
|
|
98
|
+
const {
|
|
99
|
+
disableSessionSummaries,
|
|
100
|
+
sessionTitlePrompt,
|
|
101
|
+
summaryModel,
|
|
102
|
+
summaryProviderId,
|
|
103
|
+
} = body;
|
|
97
104
|
|
|
98
105
|
// Validate that all required fields are present
|
|
99
106
|
if (typeof disableSessionSummaries !== 'boolean' ||
|
|
100
|
-
typeof sessionTitlePrompt !== 'string'
|
|
107
|
+
typeof sessionTitlePrompt !== 'string' ||
|
|
108
|
+
!Object.prototype.hasOwnProperty.call(body, 'summaryModel') ||
|
|
109
|
+
!Object.prototype.hasOwnProperty.call(body, 'summaryProviderId')) {
|
|
101
110
|
return res.status(400).json({
|
|
102
|
-
error: 'Invalid summary settings. disableSessionSummaries must be a boolean, sessionTitlePrompt must be a string'
|
|
111
|
+
error: 'Invalid summary settings. disableSessionSummaries must be a boolean, sessionTitlePrompt must be a string, summaryModel must be present, and summaryProviderId must be present'
|
|
103
112
|
});
|
|
104
113
|
}
|
|
105
114
|
|
|
115
|
+
if (typeof summaryModel !== 'string') {
|
|
116
|
+
return res.status(400).json({ error: 'summaryModel must be a string' });
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (summaryProviderId !== null && typeof summaryProviderId !== 'string') {
|
|
120
|
+
return res.status(400).json({ error: 'summaryProviderId must be a string or null' });
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const validationError = validateSummaryModelSelection(summaryModel, summaryProviderId);
|
|
124
|
+
if (validationError) {
|
|
125
|
+
return res.status(400).json({ error: validationError });
|
|
126
|
+
}
|
|
127
|
+
|
|
106
128
|
const updatedSettings = settings.setSummarySettings({
|
|
107
129
|
disableSessionSummaries,
|
|
108
130
|
sessionTitlePrompt,
|
|
131
|
+
summaryModel,
|
|
132
|
+
summaryProviderId,
|
|
109
133
|
});
|
|
110
134
|
|
|
111
135
|
// Include the default prompt for UI display/editing
|
|
@@ -119,6 +143,30 @@ router.put('/summary', (req, res) => {
|
|
|
119
143
|
}
|
|
120
144
|
});
|
|
121
145
|
|
|
146
|
+
function validateSummaryModelSelection(summaryModel, summaryProviderId) {
|
|
147
|
+
if (!summaryModel) {
|
|
148
|
+
if (summaryProviderId !== null) {
|
|
149
|
+
return 'summaryProviderId must be null when summaryModel is empty';
|
|
150
|
+
}
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (!summaryProviderId) {
|
|
155
|
+
return 'summaryProviderId is required when summaryModel is set';
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const provider = modelProviders.getById(summaryProviderId);
|
|
159
|
+
if (!provider) return `Unknown summary provider: ${summaryProviderId}`;
|
|
160
|
+
if (!SUPPORTED_SUMMARY_PROVIDER_KINDS.has(provider.kind || 'anthropic')) {
|
|
161
|
+
return `Unsupported summary provider kind: ${provider.kind}`;
|
|
162
|
+
}
|
|
163
|
+
const ownsModel = provider.models?.some((model) => model.modelId === summaryModel);
|
|
164
|
+
if (!ownsModel) {
|
|
165
|
+
return `Provider ${summaryProviderId} does not own summary model ${summaryModel}`;
|
|
166
|
+
}
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
|
|
122
170
|
/**
|
|
123
171
|
* DELETE /api/settings/summary
|
|
124
172
|
* Reset summary settings to defaults
|
|
@@ -10,7 +10,6 @@ export {
|
|
|
10
10
|
MessageRepository,
|
|
11
11
|
ConversationRepository,
|
|
12
12
|
CanvasItemRepository,
|
|
13
|
-
SessionNoteRepository,
|
|
14
13
|
TodoRepository,
|
|
15
14
|
WorkLogRepository,
|
|
16
15
|
SessionSummaryRepository,
|
|
@@ -35,7 +34,6 @@ export {
|
|
|
35
34
|
messages,
|
|
36
35
|
conversations,
|
|
37
36
|
canvasItems,
|
|
38
|
-
sessionNotes,
|
|
39
37
|
todos,
|
|
40
38
|
workLogs,
|
|
41
39
|
sessionSummaries,
|
|
@@ -237,6 +237,7 @@ export class ConversationRepository extends BaseRepository {
|
|
|
237
237
|
* @param {Object} usage - Usage data
|
|
238
238
|
* @param {number} usage.inputTokens
|
|
239
239
|
* @param {number} usage.outputTokens
|
|
240
|
+
* @param {number} usage.thinkingTokens
|
|
240
241
|
* @param {number} usage.cacheReadInputTokens
|
|
241
242
|
* @param {number} usage.cacheCreationInputTokens
|
|
242
243
|
* @param {number} usage.webSearchRequests
|
|
@@ -255,6 +256,7 @@ export class ConversationRepository extends BaseRepository {
|
|
|
255
256
|
`UPDATE conversations SET
|
|
256
257
|
input_tokens = ?,
|
|
257
258
|
output_tokens = ?,
|
|
259
|
+
thinking_tokens = ?,
|
|
258
260
|
cache_read_input_tokens = ?,
|
|
259
261
|
cache_creation_input_tokens = ?,
|
|
260
262
|
web_search_requests = ?,
|
|
@@ -265,6 +267,7 @@ export class ConversationRepository extends BaseRepository {
|
|
|
265
267
|
.run(
|
|
266
268
|
usage.inputTokens,
|
|
267
269
|
usage.outputTokens,
|
|
270
|
+
usage.thinkingTokens || 0,
|
|
268
271
|
usage.cacheReadInputTokens,
|
|
269
272
|
usage.cacheCreationInputTokens,
|
|
270
273
|
usage.webSearchRequests,
|
|
@@ -290,9 +293,12 @@ export class ConversationRepository extends BaseRepository {
|
|
|
290
293
|
const now = Date.now();
|
|
291
294
|
|
|
292
295
|
this.db
|
|
293
|
-
|
|
294
|
-
`INSERT INTO conversations (id, session_id, name, summary, is_active,
|
|
295
|
-
|
|
296
|
+
.prepare(
|
|
297
|
+
`INSERT INTO conversations (id, session_id, name, summary, is_active,
|
|
298
|
+
input_tokens, output_tokens, thinking_tokens,
|
|
299
|
+
cache_read_input_tokens, cache_creation_input_tokens,
|
|
300
|
+
web_search_requests, context_window, created_at, updated_at)
|
|
301
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
296
302
|
)
|
|
297
303
|
.run(
|
|
298
304
|
id,
|
|
@@ -300,6 +306,13 @@ export class ConversationRepository extends BaseRepository {
|
|
|
300
306
|
conv.name,
|
|
301
307
|
conv.summary,
|
|
302
308
|
conv.isActive ? 1 : 0,
|
|
309
|
+
conv.inputTokens,
|
|
310
|
+
conv.outputTokens,
|
|
311
|
+
conv.thinkingTokens,
|
|
312
|
+
conv.cacheReadInputTokens,
|
|
313
|
+
conv.cacheCreationInputTokens,
|
|
314
|
+
conv.webSearchRequests,
|
|
315
|
+
conv.contextWindow,
|
|
303
316
|
now,
|
|
304
317
|
now
|
|
305
318
|
);
|
|
@@ -4,6 +4,7 @@ import { fileURLToPath } from 'url';
|
|
|
4
4
|
import { dirname, join } from 'path';
|
|
5
5
|
import crypto from 'crypto';
|
|
6
6
|
import { allMigrations } from './migrations/index.js';
|
|
7
|
+
import { seedBaselineData } from './seedBaselineData.js';
|
|
7
8
|
|
|
8
9
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
10
|
const __dirname = dirname(__filename);
|
|
@@ -32,7 +33,10 @@ export class DatabaseManager {
|
|
|
32
33
|
const schema = readFileSync(join(__dirname, '..', 'schema.sql'), 'utf-8');
|
|
33
34
|
this.#db.exec(schema);
|
|
34
35
|
|
|
35
|
-
//
|
|
36
|
+
// Seed required baseline data before future migrations run.
|
|
37
|
+
seedBaselineData(this.#db);
|
|
38
|
+
|
|
39
|
+
// Run post-baseline migrations for existing databases.
|
|
36
40
|
this.#runMigrations();
|
|
37
41
|
|
|
38
42
|
return this.#db;
|
|
@@ -12,6 +12,7 @@ const UPSERT_FIELD_MAP = [
|
|
|
12
12
|
{ key: 'gitMode', column: 'git_mode' },
|
|
13
13
|
{ key: 'gitBranch', column: 'git_branch' },
|
|
14
14
|
{ key: 'model', column: 'model' },
|
|
15
|
+
{ key: 'providerId', column: 'provider_id' },
|
|
15
16
|
{ key: 'effortLevel', column: 'effort_level' },
|
|
16
17
|
];
|
|
17
18
|
|
|
@@ -47,6 +48,7 @@ export class ProjectDefaultsRepository extends BaseRepository {
|
|
|
47
48
|
gitMode: row.git_mode || null,
|
|
48
49
|
gitBranch: row.git_branch || null,
|
|
49
50
|
model: row.model || null,
|
|
51
|
+
providerId: row.provider_id || null,
|
|
50
52
|
effortLevel: row.effort_level || null,
|
|
51
53
|
createdAt: row.created_at,
|
|
52
54
|
updatedAt: row.updated_at,
|
|
@@ -72,47 +74,53 @@ export class ProjectDefaultsRepository extends BaseRepository {
|
|
|
72
74
|
* @param {Object} data - Defaults data (all fields optional)
|
|
73
75
|
* @returns {Object} Updated defaults object
|
|
74
76
|
*/
|
|
77
|
+
#insertDefaults(projectId, data) {
|
|
78
|
+
const id = databaseManager.generateId();
|
|
79
|
+
const now = Date.now();
|
|
80
|
+
|
|
81
|
+
this.db
|
|
82
|
+
.prepare(
|
|
83
|
+
`INSERT INTO project_session_defaults
|
|
84
|
+
(id, project_id, mode, thinking_enabled, start_immediately, git_mode, git_branch, model, provider_id, effort_level, created_at, updated_at)
|
|
85
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
86
|
+
)
|
|
87
|
+
.run(
|
|
88
|
+
id,
|
|
89
|
+
projectId,
|
|
90
|
+
data.mode || null,
|
|
91
|
+
data.thinkingEnabled !== undefined ? (data.thinkingEnabled ? 1 : 0) : null,
|
|
92
|
+
data.startImmediately !== undefined ? (data.startImmediately ? 1 : 0) : null,
|
|
93
|
+
data.gitMode || null,
|
|
94
|
+
data.gitBranch || null,
|
|
95
|
+
data.model || null,
|
|
96
|
+
data.providerId || null,
|
|
97
|
+
data.effortLevel || null,
|
|
98
|
+
now,
|
|
99
|
+
now
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
#updateDefaults(projectId, data) {
|
|
104
|
+
const { updates, values } = buildUpdateFields(data);
|
|
105
|
+
|
|
106
|
+
if (updates.length > 0) {
|
|
107
|
+
updates.push('updated_at = ?');
|
|
108
|
+
values.push(Date.now());
|
|
109
|
+
values.push(projectId);
|
|
110
|
+
|
|
111
|
+
this.db
|
|
112
|
+
.prepare(`UPDATE project_session_defaults SET ${updates.join(', ')} WHERE project_id = ?`)
|
|
113
|
+
.run(...values);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
75
117
|
upsert(projectId, data) {
|
|
76
|
-
// Get existing defaults if any
|
|
77
118
|
const existing = this.getByProjectId(projectId);
|
|
78
119
|
|
|
79
120
|
if (!existing) {
|
|
80
|
-
|
|
81
|
-
const id = databaseManager.generateId();
|
|
82
|
-
const now = Date.now();
|
|
83
|
-
|
|
84
|
-
this.db
|
|
85
|
-
.prepare(
|
|
86
|
-
`INSERT INTO project_session_defaults
|
|
87
|
-
(id, project_id, mode, thinking_enabled, start_immediately, git_mode, git_branch, model, effort_level, created_at, updated_at)
|
|
88
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
89
|
-
)
|
|
90
|
-
.run(
|
|
91
|
-
id,
|
|
92
|
-
projectId,
|
|
93
|
-
data.mode || null,
|
|
94
|
-
data.thinkingEnabled !== undefined ? (data.thinkingEnabled ? 1 : 0) : null,
|
|
95
|
-
data.startImmediately !== undefined ? (data.startImmediately ? 1 : 0) : null,
|
|
96
|
-
data.gitMode || null,
|
|
97
|
-
data.gitBranch || null,
|
|
98
|
-
data.model || null,
|
|
99
|
-
data.effortLevel || null,
|
|
100
|
-
now,
|
|
101
|
-
now
|
|
102
|
-
);
|
|
121
|
+
this.#insertDefaults(projectId, data);
|
|
103
122
|
} else {
|
|
104
|
-
|
|
105
|
-
const { updates, values } = buildUpdateFields(data);
|
|
106
|
-
|
|
107
|
-
if (updates.length > 0) {
|
|
108
|
-
updates.push('updated_at = ?');
|
|
109
|
-
values.push(Date.now());
|
|
110
|
-
values.push(projectId);
|
|
111
|
-
|
|
112
|
-
this.db
|
|
113
|
-
.prepare(`UPDATE project_session_defaults SET ${updates.join(', ')} WHERE project_id = ?`)
|
|
114
|
-
.run(...values);
|
|
115
|
-
}
|
|
123
|
+
this.#updateDefaults(projectId, data);
|
|
116
124
|
}
|
|
117
125
|
|
|
118
126
|
return this.getByProjectId(projectId);
|
|
@@ -137,7 +145,8 @@ export class ProjectDefaultsRepository extends BaseRepository {
|
|
|
137
145
|
.prepare(
|
|
138
146
|
`UPDATE project_session_defaults
|
|
139
147
|
SET mode = NULL, thinking_enabled = NULL, start_immediately = NULL,
|
|
140
|
-
git_mode = NULL, git_branch = NULL, model = NULL,
|
|
148
|
+
git_mode = NULL, git_branch = NULL, model = NULL, provider_id = NULL,
|
|
149
|
+
effort_level = NULL, updated_at = ?
|
|
141
150
|
WHERE project_id = ?`
|
|
142
151
|
)
|
|
143
152
|
.run(Date.now(), projectId);
|
|
@@ -161,12 +170,13 @@ export class ProjectDefaultsRepository extends BaseRepository {
|
|
|
161
170
|
*/
|
|
162
171
|
static getSystemDefaults() {
|
|
163
172
|
return {
|
|
164
|
-
mode: '
|
|
165
|
-
thinkingEnabled:
|
|
173
|
+
mode: 'yolo',
|
|
174
|
+
thinkingEnabled: true,
|
|
166
175
|
startImmediately: true,
|
|
167
|
-
gitMode:
|
|
176
|
+
gitMode: 'worktree',
|
|
168
177
|
gitBranch: null,
|
|
169
178
|
model: null,
|
|
179
|
+
providerId: null,
|
|
170
180
|
effortLevel: null,
|
|
171
181
|
};
|
|
172
182
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BaseRepository } from './BaseRepository.js';
|
|
2
2
|
import { databaseManager } from './DatabaseManager.js';
|
|
3
3
|
import { encrypt, decrypt } from '../services/encryption.js';
|
|
4
|
+
import { normalizeCommitAttributionOverride } from '../../../shared/src/contracts/providers.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Valid values for `providers.kind`. Maps 1:1 to an agent adapter:
|
|
@@ -18,6 +19,55 @@ export const AGENT_TYPE_BY_KIND = Object.freeze({
|
|
|
18
19
|
openai: 'codex',
|
|
19
20
|
});
|
|
20
21
|
|
|
22
|
+
const BUILT_IN_MUTABLE_FIELDS = Object.freeze(['commitAttributionOverride']);
|
|
23
|
+
|
|
24
|
+
const UPDATE_COLUMN_BUILDERS = Object.freeze({
|
|
25
|
+
name: (value) => ['name = ?', value],
|
|
26
|
+
baseUrl: (value) => ['base_url = ?', value],
|
|
27
|
+
authToken: (value) => ['auth_token = ?', encrypt(value)],
|
|
28
|
+
apiTimeoutMs: (value) => ['api_timeout_ms = ?', value],
|
|
29
|
+
additionalEnvVars: (value) => [
|
|
30
|
+
'additional_env_vars = ?',
|
|
31
|
+
value ? JSON.stringify(value) : null,
|
|
32
|
+
],
|
|
33
|
+
commitAttributionOverride: (value) => [
|
|
34
|
+
'commit_attribution_override = ?',
|
|
35
|
+
normalizeCommitAttributionOverride(value),
|
|
36
|
+
],
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
function validateBuiltInUpdate(provider, data) {
|
|
40
|
+
if (!provider.isBuiltIn) return;
|
|
41
|
+
|
|
42
|
+
const unsupportedFields = Object.keys(data || {}).filter(
|
|
43
|
+
(key) => !BUILT_IN_MUTABLE_FIELDS.includes(key)
|
|
44
|
+
);
|
|
45
|
+
if (unsupportedFields.length > 0) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
`Built-in providers can only update commitAttributionOverride. Rejected fields: ${unsupportedFields.join(', ')}.`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function validateKindImmutable(data) {
|
|
53
|
+
if (!data || !Object.prototype.hasOwnProperty.call(data, 'kind')) return;
|
|
54
|
+
|
|
55
|
+
throw new Error(
|
|
56
|
+
"Provider kind is immutable after create. Delete and recreate the provider to change kind."
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function buildUpdateColumns(data = {}) {
|
|
61
|
+
return Object.entries(UPDATE_COLUMN_BUILDERS).reduce((result, [field, buildColumn]) => {
|
|
62
|
+
if (data[field] === undefined) return result;
|
|
63
|
+
|
|
64
|
+
const [update, value] = buildColumn(data[field]);
|
|
65
|
+
result.updates.push(update);
|
|
66
|
+
result.values.push(value);
|
|
67
|
+
return result;
|
|
68
|
+
}, { updates: [], values: [] });
|
|
69
|
+
}
|
|
70
|
+
|
|
21
71
|
/**
|
|
22
72
|
* Provider repository class (replaces ModelProviderRepository).
|
|
23
73
|
*
|
|
@@ -44,6 +94,7 @@ export class ProviderRepository extends BaseRepository {
|
|
|
44
94
|
authToken: decrypt(row.auth_token),
|
|
45
95
|
apiTimeoutMs: row.api_timeout_ms,
|
|
46
96
|
additionalEnvVars: row.additional_env_vars ? JSON.parse(row.additional_env_vars) : null,
|
|
97
|
+
commitAttributionOverride: row.commit_attribution_override ?? null,
|
|
47
98
|
isBuiltIn: row.is_built_in === 1,
|
|
48
99
|
kind: row.kind || 'anthropic',
|
|
49
100
|
createdAt: row.created_at,
|
|
@@ -83,6 +134,7 @@ export class ProviderRepository extends BaseRepository {
|
|
|
83
134
|
authToken = null,
|
|
84
135
|
apiTimeoutMs = null,
|
|
85
136
|
additionalEnvVars = null,
|
|
137
|
+
commitAttributionOverride = null,
|
|
86
138
|
kind = 'anthropic',
|
|
87
139
|
} = data;
|
|
88
140
|
|
|
@@ -95,8 +147,8 @@ export class ProviderRepository extends BaseRepository {
|
|
|
95
147
|
|
|
96
148
|
this.db
|
|
97
149
|
.prepare(
|
|
98
|
-
`INSERT INTO providers (id, name, base_url, auth_token, api_timeout_ms, additional_env_vars, kind, created_at, updated_at)
|
|
99
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
150
|
+
`INSERT INTO providers (id, name, base_url, auth_token, api_timeout_ms, additional_env_vars, commit_attribution_override, kind, created_at, updated_at)
|
|
151
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
100
152
|
)
|
|
101
153
|
.run(
|
|
102
154
|
id,
|
|
@@ -105,6 +157,7 @@ export class ProviderRepository extends BaseRepository {
|
|
|
105
157
|
encrypt(authToken),
|
|
106
158
|
apiTimeoutMs,
|
|
107
159
|
additionalEnvVars ? JSON.stringify(additionalEnvVars) : null,
|
|
160
|
+
normalizeCommitAttributionOverride(commitAttributionOverride),
|
|
108
161
|
kind,
|
|
109
162
|
now,
|
|
110
163
|
now
|
|
@@ -143,38 +196,13 @@ export class ProviderRepository extends BaseRepository {
|
|
|
143
196
|
* @returns {Object} Updated provider (with models array)
|
|
144
197
|
*/
|
|
145
198
|
update(id, data) {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
// this provider.
|
|
149
|
-
if (data && Object.prototype.hasOwnProperty.call(data, 'kind')) {
|
|
150
|
-
throw new Error(
|
|
151
|
-
"Provider kind is immutable after create. Delete and recreate the provider to change kind."
|
|
152
|
-
);
|
|
153
|
-
}
|
|
199
|
+
const provider = this.getById(id);
|
|
200
|
+
if (!provider) return null;
|
|
154
201
|
|
|
155
|
-
|
|
156
|
-
|
|
202
|
+
validateBuiltInUpdate(provider, data);
|
|
203
|
+
validateKindImmutable(data);
|
|
157
204
|
|
|
158
|
-
|
|
159
|
-
updates.push('name = ?');
|
|
160
|
-
values.push(data.name);
|
|
161
|
-
}
|
|
162
|
-
if (data.baseUrl !== undefined) {
|
|
163
|
-
updates.push('base_url = ?');
|
|
164
|
-
values.push(data.baseUrl);
|
|
165
|
-
}
|
|
166
|
-
if (data.authToken !== undefined) {
|
|
167
|
-
updates.push('auth_token = ?');
|
|
168
|
-
values.push(encrypt(data.authToken));
|
|
169
|
-
}
|
|
170
|
-
if (data.apiTimeoutMs !== undefined) {
|
|
171
|
-
updates.push('api_timeout_ms = ?');
|
|
172
|
-
values.push(data.apiTimeoutMs);
|
|
173
|
-
}
|
|
174
|
-
if (data.additionalEnvVars !== undefined) {
|
|
175
|
-
updates.push('additional_env_vars = ?');
|
|
176
|
-
values.push(data.additionalEnvVars ? JSON.stringify(data.additionalEnvVars) : null);
|
|
177
|
-
}
|
|
205
|
+
const { updates, values } = buildUpdateColumns(data);
|
|
178
206
|
|
|
179
207
|
if (updates.length > 0) {
|
|
180
208
|
updates.push('updated_at = ?');
|
|
@@ -348,6 +376,33 @@ export class ProviderRepository extends BaseRepository {
|
|
|
348
376
|
return provider;
|
|
349
377
|
}
|
|
350
378
|
|
|
379
|
+
/**
|
|
380
|
+
* Look up provider metadata for a model without applying runtime env fallback
|
|
381
|
+
* rules. Unlike getProviderByModelId, this returns built-in Anthropic too.
|
|
382
|
+
*
|
|
383
|
+
* @param {string|null|undefined} modelId
|
|
384
|
+
* @returns {Object|null}
|
|
385
|
+
*/
|
|
386
|
+
getProviderMetadataByModelId(modelId) {
|
|
387
|
+
if (!modelId) return null;
|
|
388
|
+
|
|
389
|
+
const tierNames = ['sonnet', 'opus', 'haiku'];
|
|
390
|
+
if (tierNames.includes(modelId.toLowerCase())) {
|
|
391
|
+
return this.getById('anthropic-default');
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const row = this.db
|
|
395
|
+
.prepare(
|
|
396
|
+
`SELECT p.id FROM providers p
|
|
397
|
+
JOIN provider_models pm ON p.id = pm.provider_id
|
|
398
|
+
WHERE pm.model_id = ?
|
|
399
|
+
ORDER BY p.is_built_in ASC, p.name ASC`
|
|
400
|
+
)
|
|
401
|
+
.get(modelId);
|
|
402
|
+
|
|
403
|
+
return row ? this.getById(row.id) : null;
|
|
404
|
+
}
|
|
405
|
+
|
|
351
406
|
/**
|
|
352
407
|
* Resolve a provider's agent type from its id.
|
|
353
408
|
* @param {string|null|undefined} providerId
|
|
@@ -45,6 +45,7 @@ export class SessionRepository extends BaseRepository {
|
|
|
45
45
|
status: row.status,
|
|
46
46
|
mode: row.mode,
|
|
47
47
|
model: row.model,
|
|
48
|
+
providerId: row.provider_id || null,
|
|
48
49
|
thinkingEnabled: Boolean(row.thinking_enabled),
|
|
49
50
|
archived: Boolean(row.archived),
|
|
50
51
|
starred: Boolean(row.starred),
|
|
@@ -52,6 +53,7 @@ export class SessionRepository extends BaseRepository {
|
|
|
52
53
|
gitBranch: row.git_branch,
|
|
53
54
|
gitWorktree: row.git_worktree,
|
|
54
55
|
prUrl: row.pr_url,
|
|
56
|
+
prUrlAutoLinkDisabled: Boolean(row.pr_url_auto_link_disabled),
|
|
55
57
|
error: row.error,
|
|
56
58
|
costUsd: row.cost_usd,
|
|
57
59
|
claudeSessionId: row.claude_session_id,
|
|
@@ -84,7 +86,7 @@ export class SessionRepository extends BaseRepository {
|
|
|
84
86
|
return this.map(row);
|
|
85
87
|
}
|
|
86
88
|
|
|
87
|
-
/** Create a new session with optional config (mode, thinkingEnabled, gitBranch, parentSessionId, status, model, effortLevel, agentType) */
|
|
89
|
+
/** Create a new session with optional config (mode, thinkingEnabled, gitBranch, parentSessionId, status, model, providerId, effortLevel, agentType) */
|
|
88
90
|
create(projectId, name, prompt, options = {}) {
|
|
89
91
|
const config = parseCreateConfig(options, Array.prototype.slice.call(arguments, 4));
|
|
90
92
|
|
|
@@ -98,8 +100,8 @@ export class SessionRepository extends BaseRepository {
|
|
|
98
100
|
const now = Date.now();
|
|
99
101
|
this.db
|
|
100
102
|
.prepare(
|
|
101
|
-
`INSERT INTO sessions (id, project_id, name, status, mode, thinking_enabled, git_branch, parent_session_id, model, effort_level, agent_type, created_at, updated_at)
|
|
102
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
103
|
+
`INSERT INTO sessions (id, project_id, name, status, mode, thinking_enabled, git_branch, parent_session_id, model, provider_id, effort_level, agent_type, created_at, updated_at)
|
|
104
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
103
105
|
)
|
|
104
106
|
.run(
|
|
105
107
|
id,
|
|
@@ -111,6 +113,7 @@ export class SessionRepository extends BaseRepository {
|
|
|
111
113
|
config.gitBranch,
|
|
112
114
|
config.parentSessionId,
|
|
113
115
|
config.model,
|
|
116
|
+
config.providerId,
|
|
114
117
|
config.effortLevel,
|
|
115
118
|
agentType,
|
|
116
119
|
now,
|
|
@@ -282,10 +285,10 @@ export class SessionRepository extends BaseRepository {
|
|
|
282
285
|
// Insert new session with same settings but new ID and status
|
|
283
286
|
this.db
|
|
284
287
|
.prepare(
|
|
285
|
-
`INSERT INTO sessions (id, project_id, name, status, mode, thinking_enabled, git_branch, model, effort_level, agent_type, context_window,
|
|
286
|
-
input_tokens, output_tokens, cache_read_input_tokens, cache_creation_input_tokens,
|
|
288
|
+
`INSERT INTO sessions (id, project_id, name, status, mode, thinking_enabled, git_branch, model, provider_id, effort_level, agent_type, context_window,
|
|
289
|
+
input_tokens, output_tokens, thinking_tokens, cache_read_input_tokens, cache_creation_input_tokens,
|
|
287
290
|
web_search_requests, cost_usd, created_at, updated_at)
|
|
288
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
291
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
289
292
|
)
|
|
290
293
|
.run(
|
|
291
294
|
id,
|
|
@@ -296,11 +299,13 @@ export class SessionRepository extends BaseRepository {
|
|
|
296
299
|
source.thinkingEnabled ? 1 : 0,
|
|
297
300
|
source.gitBranch, // Copy branch name (NOT worktree path)
|
|
298
301
|
source.model,
|
|
302
|
+
source.providerId,
|
|
299
303
|
source.effortLevel,
|
|
300
304
|
source.agentType || DEFAULT_AGENT_TYPE,
|
|
301
305
|
source.contextWindow,
|
|
302
306
|
source.inputTokens,
|
|
303
307
|
source.outputTokens,
|
|
308
|
+
source.thinkingTokens,
|
|
304
309
|
source.cacheReadInputTokens,
|
|
305
310
|
source.cacheCreationInputTokens,
|
|
306
311
|
source.webSearchRequests,
|
|
@@ -326,11 +331,11 @@ export class SessionRepository extends BaseRepository {
|
|
|
326
331
|
updateUsage(id, usage) {
|
|
327
332
|
this.db
|
|
328
333
|
.prepare(
|
|
329
|
-
`UPDATE sessions SET input_tokens = ?, output_tokens = ?, cache_read_input_tokens = ?,
|
|
334
|
+
`UPDATE sessions SET input_tokens = ?, output_tokens = ?, thinking_tokens = ?, cache_read_input_tokens = ?,
|
|
330
335
|
cache_creation_input_tokens = ?, web_search_requests = ?, context_window = ?, updated_at = ?
|
|
331
336
|
WHERE id = ?`
|
|
332
337
|
)
|
|
333
|
-
.run(usage.inputTokens, usage.outputTokens, usage.cacheReadInputTokens,
|
|
338
|
+
.run(usage.inputTokens, usage.outputTokens, usage.thinkingTokens || 0, usage.cacheReadInputTokens,
|
|
334
339
|
usage.cacheCreationInputTokens, usage.webSearchRequests, usage.contextWindow, Date.now(), id);
|
|
335
340
|
return this.getById(id);
|
|
336
341
|
}
|