circuschief 0.7.0 → 1.0.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/commandButtons.js +16 -15
- package/packages/server/src/api/index.js +2 -0
- package/packages/server/src/api/kanban.js +4 -2
- package/packages/server/src/api/projects-commandButtons.js +6 -6
- package/packages/server/src/api/projects-helpers.js +20 -3
- package/packages/server/src/api/projects-session-create.js +109 -0
- package/packages/server/src/api/projects-session-defaults.js +51 -0
- package/packages/server/src/api/projects-session-helpers.js +57 -5
- package/packages/server/src/api/projects-templates.js +38 -0
- package/packages/server/src/api/projects.js +28 -170
- package/packages/server/src/api/providers.js +11 -1
- package/packages/server/src/api/sessions-commands.js +46 -25
- package/packages/server/src/api/sessions-lifecycle.js +10 -10
- package/packages/server/src/api/sessions-patch.js +45 -1
- package/packages/server/src/api/sessions.js +6 -5
- package/packages/server/src/database.js +0 -2
- package/packages/server/src/db/DatabaseManager.js +5 -1
- package/packages/server/src/db/ProjectDefaultsRepository.js +3 -3
- package/packages/server/src/db/ProviderRepository.js +87 -32
- package/packages/server/src/db/SessionRepository.js +2 -1
- package/packages/server/src/db/SessionTemplateRepository.js +23 -2
- package/packages/server/src/db/index.js +0 -3
- package/packages/server/src/db/migrations/index.js +60 -7
- package/packages/server/src/db/migrations/kanbanMigrations.js +1 -1
- package/packages/server/src/db/migrations/miscMigrations.js +59 -184
- package/packages/server/src/db/migrations/projectsMigrations.js +31 -0
- package/packages/server/src/db/migrations/providerCommitAttributionMigrations.js +30 -0
- package/packages/server/src/db/migrations/providerMigrations.js +165 -0
- package/packages/server/src/db/migrations/sessionTableRecreate.js +136 -0
- package/packages/server/src/db/migrations/sessionsMigrations.js +18 -5
- package/packages/server/src/db/seedBaselineData.js +137 -0
- package/packages/server/src/db/session-helpers.js +32 -4
- package/packages/server/src/middleware/sessionLookup.js +81 -8
- package/packages/server/src/schema.sql +153 -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/codexSpawnHelper.js +9 -0
- package/packages/server/src/services/commandButtonPrompts.js +14 -12
- package/packages/server/src/services/commandRunner.js +7 -1
- package/packages/server/src/services/e2eSpawnCapture.js +147 -0
- package/packages/server/src/services/gitCommitAttribution.js +150 -0
- package/packages/server/src/services/gitDiff.js +132 -0
- package/packages/server/src/services/gitRepoUrl.js +174 -0
- package/packages/server/src/services/gitService.js +48 -311
- package/packages/server/src/services/gitSessionSetup.js +11 -1
- package/packages/server/src/services/gitWorktree.js +127 -0
- 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 -108
- package/packages/server/src/services/sessionPrompts.js +12 -47
- package/packages/server/src/services/sessionProvider.js +10 -0
- package/packages/server/src/services/summaryService.js +5 -3
- package/packages/server/src/services/summaryStaleCheck.js +23 -4
- package/packages/server/src/services/templateTriggerService.js +3 -1
- package/packages/shared/src/constants.js +3 -0
- package/packages/shared/src/contracts/commandButtons.js +16 -2
- package/packages/shared/src/contracts/projects.js +2 -2
- package/packages/shared/src/contracts/providers.js +60 -0
- package/packages/shared/src/contracts/sessions.js +29 -2
- package/packages/shared/src/contracts/templates.js +12 -2
- package/packages/shared/src/types.js +1 -9
- package/packages/shared/src/utils.js +2 -2
- package/packages/web/dist/assets/{ActiveSessionsView-UJsCILDL.js → ActiveSessionsView-Cxh8mHmB.js} +1 -1
- package/packages/web/dist/assets/{AgentLogsView-BGFPLjLa.js → AgentLogsView-xdfI2bR6.js} +2 -2
- package/packages/web/dist/assets/ApiClient-DfbJwzpz.js +1 -0
- package/packages/web/dist/assets/ArchiveConfirmModal-DXZYdzHR.js +1 -0
- package/packages/web/dist/assets/ArchiveConfirmModal-DeoCVGXt.css +1 -0
- package/packages/web/dist/assets/CommandButtonDetailView-D8xfqLAp.js +1 -0
- package/packages/web/dist/assets/CommandButtonDetailView-D9zjx9ME.css +1 -0
- package/packages/web/dist/assets/EffortLevelSelector-D2Hdzc_8.js +1 -0
- package/packages/web/dist/assets/{GeneralSettingsView-DsHChEhv.js → GeneralSettingsView-sPXkLlLy.js} +1 -1
- package/packages/web/dist/assets/InputWithButton-B-o0DgMH.js +1 -0
- package/packages/web/dist/assets/{InputWithButton-cYdrEmTs.css → InputWithButton-D9HMvfR5.css} +1 -1
- package/packages/web/dist/assets/{InterpolationHelp-CIkOSkWX.js → InterpolationHelp-Dxn1li4l.js} +1 -1
- package/packages/web/dist/assets/MarkdownEditor-D4Kbb-9l.js +2 -0
- package/packages/web/dist/assets/ModelSelector-72C7MUH4.js +1 -0
- package/packages/web/dist/assets/{ModelSelector-D8hbTRIt.css → ModelSelector-BNYKujL-.css} +1 -1
- package/packages/web/dist/assets/NewSessionView-BR_COfgW.js +3 -0
- package/packages/web/dist/assets/NewSessionView-DBl7T2Xp.css +1 -0
- package/packages/web/dist/assets/ProjectEditView-DbqTbA0q.css +1 -0
- package/packages/web/dist/assets/ProjectEditView-WImU7sNd.js +1 -0
- package/packages/web/dist/assets/{ProjectListView-B9FuWESY.js → ProjectListView-CYmmAcBD.js} +1 -1
- package/packages/web/dist/assets/{ProjectNewView-D62jYlBL.js → ProjectNewView-DEhqw3Jv.js} +1 -1
- package/packages/web/dist/assets/ProvidersView-XZh3jkmH.js +1 -0
- package/packages/web/dist/assets/ProvidersView-bZemq_Rv.css +1 -0
- package/packages/web/dist/assets/QuickResponsesPanel-BqmnTd-D.js +1 -0
- package/packages/web/dist/assets/QuickResponsesPanel-dk-Rj8xx.css +1 -0
- package/packages/web/dist/assets/ResizableTextarea-BQNw5e0C.css +1 -0
- package/packages/web/dist/assets/ResizableTextarea-DpWdIAP6.js +1 -0
- package/packages/web/dist/assets/SessionCard-Bw77-KwD.js +1 -0
- package/packages/web/dist/assets/SessionDetailView-B59TEkr-.js +36 -0
- package/packages/web/dist/assets/SessionDetailView-CKVBnR4T.css +1 -0
- package/packages/web/dist/assets/{SessionFormOptions-DYUISplS.js → SessionFormOptions-hqijxc0S.js} +1 -1
- package/packages/web/dist/assets/SessionListView-3-xx6EVs.css +1 -0
- package/packages/web/dist/assets/SessionListView-DYXHM9I-.js +1 -0
- package/packages/web/dist/assets/{SessionLogStream-DpUE6Xsh.js → SessionLogStream-5NfVr9pF.js} +6 -6
- package/packages/web/dist/assets/{SettingsView-BC055tIA.js → SettingsView-DI8ncOAV.js} +1 -1
- package/packages/web/dist/assets/{SlashCommandWizard-DmTyNG9O.js → SlashCommandWizard-BQ_rMzn-.js} +1 -1
- package/packages/web/dist/assets/{SlashCommandWizard-Dn7sNaBd.css → SlashCommandWizard-DJzw3LP5.css} +1 -1
- package/packages/web/dist/assets/{SummarySettingsView-BgnRCwlq.js → SummarySettingsView-C2Qs35mm.js} +1 -1
- package/packages/web/dist/assets/TemplateDetailView-B5NI2oTR.css +1 -0
- package/packages/web/dist/assets/TemplateDetailView-zVkIvgtu.js +1 -0
- package/packages/web/dist/assets/{commandButtons-D4RPpLiu.js → commandButtons-CoU3G4zK.js} +1 -1
- package/packages/web/dist/assets/index-9yF1uCCA.js +1 -0
- package/packages/web/dist/assets/index-BKstCaYU.js +1 -0
- package/packages/web/dist/assets/index-BhbH7eOk.js +1 -0
- package/packages/web/dist/assets/{index-BGwH4Cfn.js → index-BjuRttEY.js} +3 -3
- package/packages/web/dist/assets/index-Bo7PdwM5.js +1 -0
- package/packages/web/dist/assets/index-C2QFVD7d.js +83 -0
- package/packages/web/dist/assets/index-C7Ww2auW.js +1 -0
- package/packages/web/dist/assets/index-CAGdsDh7.js +1 -0
- package/packages/web/dist/assets/index-CLRsVASf.js +3 -0
- package/packages/web/dist/assets/{index-Bn5xdGFM.js → index-CP-SxOlV.js} +1 -1
- package/packages/web/dist/assets/index-CslU0psO.js +1 -0
- package/packages/web/dist/assets/index-DI4NxaWD.js +1 -0
- package/packages/web/dist/assets/index-DOzONENy.js +1 -0
- package/packages/web/dist/assets/index-DUa7adFh.js +1 -0
- package/packages/web/dist/assets/index-DZBpETI5.js +1 -0
- package/packages/web/dist/assets/index-DsjWqc6R.js +7 -0
- package/packages/web/dist/assets/index-c99Bo3JV.js +1 -0
- package/packages/web/dist/assets/index-mT1JpxDc.js +1 -0
- package/packages/web/dist/assets/index-rkQx2tso.js +1 -0
- package/packages/web/dist/assets/{index-Cs2nxhrT.css → index-uySCcnA_.css} +1 -1
- package/packages/web/dist/assets/projectDefaults-B8esIcYq.js +1 -0
- package/packages/web/dist/assets/{projects-BUiOGmmb.js → projects-C-8PSxKi.js} +1 -1
- package/packages/web/dist/assets/{providers-Bh1ZiiJi.js → providers-oXifvvqN.js} +1 -1
- package/packages/web/dist/assets/sessions-Nq5VafSf.js +1 -0
- package/packages/web/dist/assets/{settings-Z4AVVmkJ.js → settings-DtpuiyT6.js} +1 -1
- 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/web/dist/assets/ApiClient-B4YTtyY4.js +0 -1
- package/packages/web/dist/assets/ArchiveConfirmModal-BQ-4gI0R.css +0 -1
- package/packages/web/dist/assets/ArchiveConfirmModal-OFaj_uX5.js +0 -1
- package/packages/web/dist/assets/CommandButtonDetailView-D8S258uP.js +0 -1
- package/packages/web/dist/assets/CommandButtonDetailView-DBm3rzhw.css +0 -1
- package/packages/web/dist/assets/EffortLevelSelector-C2378L8e.js +0 -1
- package/packages/web/dist/assets/InputWithButton-Ci15ox0a.js +0 -1
- package/packages/web/dist/assets/MarkdownEditor-5-bexzUT.js +0 -2
- package/packages/web/dist/assets/ModelSelector-BMpR0DPr.js +0 -1
- package/packages/web/dist/assets/NewSessionView-BCqtIgWH.js +0 -3
- package/packages/web/dist/assets/NewSessionView-CUUdHkfv.css +0 -1
- package/packages/web/dist/assets/ProjectEditView-D9sK0fdH.css +0 -1
- package/packages/web/dist/assets/ProjectEditView-RFaxHhAX.js +0 -1
- package/packages/web/dist/assets/ProvidersView-DDKMIQWZ.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-CDm5vwP7.js +0 -1
- package/packages/web/dist/assets/QuickResponsesPanel-BlFDvnZ2.css +0 -1
- package/packages/web/dist/assets/QuickResponsesPanel-DZ_Lre_l.js +0 -1
- package/packages/web/dist/assets/ResizableTextarea-DiIOEGjN.js +0 -1
- package/packages/web/dist/assets/ResizableTextarea-DsU3TVwF.css +0 -1
- package/packages/web/dist/assets/SessionCard-DmjnVYWn.js +0 -1
- package/packages/web/dist/assets/SessionDetailView-CL7nmfiB.js +0 -36
- package/packages/web/dist/assets/SessionDetailView-CupIkI7u.css +0 -1
- package/packages/web/dist/assets/SessionListView-BcxGz4aC.js +0 -1
- package/packages/web/dist/assets/SessionListView-fHlQyecX.css +0 -1
- package/packages/web/dist/assets/TemplateDetailView-BlhOmLUX.js +0 -1
- package/packages/web/dist/assets/TemplateDetailView-DT2m06W7.css +0 -1
- package/packages/web/dist/assets/index-4rhEeO0B.js +0 -1
- package/packages/web/dist/assets/index-9vb2KaAd.js +0 -1
- package/packages/web/dist/assets/index-B0CvZXuN.js +0 -7
- package/packages/web/dist/assets/index-B6G18FqB.js +0 -82
- package/packages/web/dist/assets/index-BUhvkAdF.js +0 -1
- package/packages/web/dist/assets/index-BcnkUk2o.js +0 -1
- package/packages/web/dist/assets/index-CNwkdB0T.js +0 -1
- package/packages/web/dist/assets/index-CfL84oGW.js +0 -1
- package/packages/web/dist/assets/index-CkmxO8Mm.js +0 -1
- package/packages/web/dist/assets/index-Cpy4-yv3.js +0 -1
- package/packages/web/dist/assets/index-CrAQJmoZ.js +0 -1
- package/packages/web/dist/assets/index-D6Ky9vJe.js +0 -3
- package/packages/web/dist/assets/index-DfrE0gAC.js +0 -1
- package/packages/web/dist/assets/index-KwEyz0F3.js +0 -1
- package/packages/web/dist/assets/index-OfCywayk.js +0 -1
- package/packages/web/dist/assets/index-PDesaJc6.js +0 -1
- package/packages/web/dist/assets/index-uB6nhSvz.js +0 -1
- package/packages/web/dist/assets/sessions-DH1R-NhV.js +0 -1
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
|
-
import { sessions, sessionTemplates, modelProviders } from '../database.js';
|
|
2
|
+
import { sessions, sessionTemplates, modelProviders, sessionSummaries } from '../database.js';
|
|
3
3
|
import { broadcastToSession, broadcastToProject } from '../websocket.js';
|
|
4
4
|
import { WS_MESSAGE_TYPES } from '../../../shared/src/index.js';
|
|
5
5
|
import * as summaryService from '../services/summaryService.js';
|
|
6
6
|
import { setSessionNameFromPr } from '../services/prUrlService.js';
|
|
7
|
+
import { checkSessionCiStatusNow } from '../services/prStatusService.js';
|
|
8
|
+
import { broadcastSummaryUpdate } from '../services/summaryBroadcast.js';
|
|
7
9
|
import { requireSession } from '../middleware/sessionLookup.js';
|
|
8
10
|
|
|
9
11
|
const router = Router();
|
|
@@ -158,6 +160,10 @@ function buildUpdateData(body) {
|
|
|
158
160
|
updateData.manuallyNamed = true;
|
|
159
161
|
}
|
|
160
162
|
|
|
163
|
+
if (body.prUrl !== undefined) {
|
|
164
|
+
updateData.prUrlAutoLinkDisabled = updateData.prUrl === null;
|
|
165
|
+
}
|
|
166
|
+
|
|
161
167
|
return { updateData };
|
|
162
168
|
}
|
|
163
169
|
|
|
@@ -191,6 +197,30 @@ function broadcastSessionUpdate(sessionId, projectId, updated, updateData) {
|
|
|
191
197
|
});
|
|
192
198
|
}
|
|
193
199
|
|
|
200
|
+
/**
|
|
201
|
+
* Reset all PR state fields in the session summary when the PR URL changes or is cleared.
|
|
202
|
+
* This ensures stale PR state (e.g., "merged") doesn't persist for a different PR
|
|
203
|
+
* and doesn't block summary regeneration.
|
|
204
|
+
* @param {string} sessionId
|
|
205
|
+
* @param {string|null} projectId - For broadcasting to project subscribers
|
|
206
|
+
*/
|
|
207
|
+
function resetPrStateForSession(sessionId, projectId) {
|
|
208
|
+
const existingSummary = sessionSummaries.getBySessionId(sessionId);
|
|
209
|
+
if (!existingSummary) return;
|
|
210
|
+
|
|
211
|
+
sessionSummaries.upsert(sessionId, {
|
|
212
|
+
prState: null,
|
|
213
|
+
prMerged: false,
|
|
214
|
+
hasMergeConflicts: false,
|
|
215
|
+
ciStatus: null,
|
|
216
|
+
ciFailures: [],
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
// Broadcast the reset to both session and project subscribers
|
|
220
|
+
const updatedSummary = sessionSummaries.getBySessionId(sessionId);
|
|
221
|
+
broadcastSummaryUpdate(sessionId, projectId, updatedSummary);
|
|
222
|
+
}
|
|
223
|
+
|
|
194
224
|
// PATCH /api/sessions/:id - Update session settings
|
|
195
225
|
router.patch('/:id', requireSession, (req, res) => {
|
|
196
226
|
const { updateData, error } = buildUpdateData(req.body);
|
|
@@ -205,6 +235,15 @@ router.patch('/:id', requireSession, (req, res) => {
|
|
|
205
235
|
|
|
206
236
|
const updated = sessions.update(req.params.id, updateData);
|
|
207
237
|
|
|
238
|
+
// Reset PR state when URL changes to a different PR or is cleared
|
|
239
|
+
const previousPrUrl = req.session_.prUrl;
|
|
240
|
+
const prUrlProvided = Object.prototype.hasOwnProperty.call(updateData, 'prUrl');
|
|
241
|
+
const prUrlChanged = prUrlProvided && previousPrUrl && previousPrUrl !== updateData.prUrl;
|
|
242
|
+
|
|
243
|
+
if (prUrlChanged) {
|
|
244
|
+
resetPrStateForSession(req.params.id, req.session_.projectId);
|
|
245
|
+
}
|
|
246
|
+
|
|
208
247
|
// Propagate PR URL to parent session if set (not when clearing)
|
|
209
248
|
if (updateData.prUrl) {
|
|
210
249
|
summaryService.propagatePrUrlToParent(req.params.id, updateData.prUrl);
|
|
@@ -214,6 +253,11 @@ router.patch('/:id', requireSession, (req, res) => {
|
|
|
214
253
|
setSessionNameFromPr(req.params.id, updateData.prUrl).catch(err => {
|
|
215
254
|
console.error(`[Sessions API] Failed to set session name from PR:`, err);
|
|
216
255
|
});
|
|
256
|
+
|
|
257
|
+
// Trigger immediate PR status check for the new/changed URL
|
|
258
|
+
checkSessionCiStatusNow(req.params.id).catch(err => {
|
|
259
|
+
console.error(`[Sessions API] Failed to check PR status after URL change:`, err);
|
|
260
|
+
});
|
|
217
261
|
}
|
|
218
262
|
|
|
219
263
|
broadcastSessionUpdate(req.params.id, req.session_.projectId, updated, updateData);
|
|
@@ -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
|
|
@@ -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,
|
|
@@ -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;
|
|
@@ -170,10 +170,10 @@ export class ProjectDefaultsRepository extends BaseRepository {
|
|
|
170
170
|
*/
|
|
171
171
|
static getSystemDefaults() {
|
|
172
172
|
return {
|
|
173
|
-
mode: '
|
|
174
|
-
thinkingEnabled:
|
|
173
|
+
mode: 'yolo',
|
|
174
|
+
thinkingEnabled: true,
|
|
175
175
|
startImmediately: true,
|
|
176
|
-
gitMode:
|
|
176
|
+
gitMode: 'worktree',
|
|
177
177
|
gitBranch: null,
|
|
178
178
|
model: null,
|
|
179
179
|
providerId: null,
|
|
@@ -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
|
|
@@ -53,6 +53,7 @@ export class SessionRepository extends BaseRepository {
|
|
|
53
53
|
gitBranch: row.git_branch,
|
|
54
54
|
gitWorktree: row.git_worktree,
|
|
55
55
|
prUrl: row.pr_url,
|
|
56
|
+
prUrlAutoLinkDisabled: Boolean(row.pr_url_auto_link_disabled),
|
|
56
57
|
error: row.error,
|
|
57
58
|
costUsd: row.cost_usd,
|
|
58
59
|
claudeSessionId: row.claude_session_id,
|
|
@@ -73,6 +74,7 @@ export class SessionRepository extends BaseRepository {
|
|
|
73
74
|
createdAt: row.created_at,
|
|
74
75
|
updatedAt: row.updated_at,
|
|
75
76
|
lastActivityAt: row.last_activity_at ?? null,
|
|
77
|
+
lastMessageAt: row.last_message_at ?? null,
|
|
76
78
|
activeTimeMs: row.active_time_ms || 0,
|
|
77
79
|
};
|
|
78
80
|
}
|
|
@@ -146,7 +148,6 @@ export class SessionRepository extends BaseRepository {
|
|
|
146
148
|
}
|
|
147
149
|
|
|
148
150
|
sql += ` ORDER BY
|
|
149
|
-
starred DESC,
|
|
150
151
|
COALESCE(last_activity_at, updated_at, created_at) DESC,
|
|
151
152
|
updated_at DESC,
|
|
152
153
|
created_at DESC,
|
|
@@ -23,6 +23,10 @@ export class SessionTemplateRepository extends BaseRepository {
|
|
|
23
23
|
mode: row.mode || null,
|
|
24
24
|
effortLevel: row.effort_level ?? null,
|
|
25
25
|
targetLaneId: row.target_lane_id || null,
|
|
26
|
+
showInQuickResponses: Boolean(row.show_in_quick_responses),
|
|
27
|
+
quickResponseAutoSubmit: Boolean(row.quick_response_auto_submit),
|
|
28
|
+
quickResponseSortOrder: row.quick_response_sort_order ?? 0,
|
|
29
|
+
legacyQuickResponseId: row.legacy_quick_response_id || null,
|
|
26
30
|
createdAt: row.created_at,
|
|
27
31
|
updatedAt: row.updated_at,
|
|
28
32
|
};
|
|
@@ -51,13 +55,22 @@ export class SessionTemplateRepository extends BaseRepository {
|
|
|
51
55
|
return value ? 1 : 0;
|
|
52
56
|
}
|
|
53
57
|
|
|
58
|
+
static #normalizeBoolean(value) {
|
|
59
|
+
return value ? 1 : 0;
|
|
60
|
+
}
|
|
61
|
+
|
|
54
62
|
create(data) {
|
|
55
63
|
const id = databaseManager.generateId();
|
|
56
64
|
const now = Date.now();
|
|
57
65
|
this.db
|
|
58
66
|
.prepare(
|
|
59
|
-
`INSERT INTO session_templates (
|
|
60
|
-
|
|
67
|
+
`INSERT INTO session_templates (
|
|
68
|
+
id, project_id, name, prompt, next_template_id, thinking_enabled,
|
|
69
|
+
git_branch, git_mode, model, mode, effort_level, target_lane_id,
|
|
70
|
+
show_in_quick_responses, quick_response_auto_submit,
|
|
71
|
+
quick_response_sort_order, legacy_quick_response_id,
|
|
72
|
+
created_at, updated_at
|
|
73
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
61
74
|
)
|
|
62
75
|
.run(
|
|
63
76
|
id,
|
|
@@ -72,6 +85,10 @@ export class SessionTemplateRepository extends BaseRepository {
|
|
|
72
85
|
data.mode !== undefined && data.mode !== null ? data.mode : null,
|
|
73
86
|
data.effortLevel ?? null,
|
|
74
87
|
data.targetLaneId || null,
|
|
88
|
+
SessionTemplateRepository.#normalizeBoolean(data.showInQuickResponses),
|
|
89
|
+
SessionTemplateRepository.#normalizeBoolean(data.quickResponseAutoSubmit),
|
|
90
|
+
data.quickResponseSortOrder ?? 0,
|
|
91
|
+
data.legacyQuickResponseId || null,
|
|
75
92
|
now,
|
|
76
93
|
now
|
|
77
94
|
);
|
|
@@ -93,6 +110,10 @@ export class SessionTemplateRepository extends BaseRepository {
|
|
|
93
110
|
mode: { column: 'mode', transform: (v) => v },
|
|
94
111
|
effortLevel: { column: 'effort_level', transform: (v) => v },
|
|
95
112
|
targetLaneId: { column: 'target_lane_id', transform: (v) => v },
|
|
113
|
+
showInQuickResponses: { column: 'show_in_quick_responses', transform: (v) => v ? 1 : 0 },
|
|
114
|
+
quickResponseAutoSubmit: { column: 'quick_response_auto_submit', transform: (v) => v ? 1 : 0 },
|
|
115
|
+
quickResponseSortOrder: { column: 'quick_response_sort_order', transform: (v) => v },
|
|
116
|
+
legacyQuickResponseId: { column: 'legacy_quick_response_id', transform: (v) => v || null },
|
|
96
117
|
};
|
|
97
118
|
|
|
98
119
|
/**
|
|
@@ -12,7 +12,6 @@ export { SessionTemplateRepository } from './SessionTemplateRepository.js';
|
|
|
12
12
|
export { MessageRepository } from './MessageRepository.js';
|
|
13
13
|
export { ConversationRepository } from './ConversationRepository.js';
|
|
14
14
|
export { CanvasItemRepository } from './CanvasItemRepository.js';
|
|
15
|
-
export { SessionNoteRepository } from './SessionNoteRepository.js';
|
|
16
15
|
export { TodoRepository } from './TodoRepository.js';
|
|
17
16
|
export { WorkLogRepository } from './WorkLogRepository.js';
|
|
18
17
|
export { SessionSummaryRepository } from './SessionSummaryRepository.js';
|
|
@@ -35,7 +34,6 @@ import { ProjectDefaultsRepository } from './ProjectDefaultsRepository.js';
|
|
|
35
34
|
import { MessageRepository } from './MessageRepository.js';
|
|
36
35
|
import { ConversationRepository } from './ConversationRepository.js';
|
|
37
36
|
import { CanvasItemRepository } from './CanvasItemRepository.js';
|
|
38
|
-
import { SessionNoteRepository } from './SessionNoteRepository.js';
|
|
39
37
|
import { TodoRepository } from './TodoRepository.js';
|
|
40
38
|
import { WorkLogRepository } from './WorkLogRepository.js';
|
|
41
39
|
import { SessionSummaryRepository } from './SessionSummaryRepository.js';
|
|
@@ -56,7 +54,6 @@ export const projectDefaults = new ProjectDefaultsRepository();
|
|
|
56
54
|
export const messages = new MessageRepository();
|
|
57
55
|
export const conversations = new ConversationRepository();
|
|
58
56
|
export const canvasItems = new CanvasItemRepository();
|
|
59
|
-
export const sessionNotes = new SessionNoteRepository();
|
|
60
57
|
export const todos = new TodoRepository();
|
|
61
58
|
export const workLogs = new WorkLogRepository();
|
|
62
59
|
export const sessionSummaries = new SessionSummaryRepository();
|
|
@@ -14,6 +14,8 @@ import { conversationsMigrations } from './conversationsMigrations.js';
|
|
|
14
14
|
import { canvasItemsMigrations } from './canvasItemsMigrations.js';
|
|
15
15
|
import { miscMigrations } from './miscMigrations.js';
|
|
16
16
|
import { kanbanMigrations } from './kanbanMigrations.js';
|
|
17
|
+
import { providerMigrations } from './providerMigrations.js';
|
|
18
|
+
import { providerCommitAttributionMigrations } from './providerCommitAttributionMigrations.js';
|
|
17
19
|
|
|
18
20
|
/**
|
|
19
21
|
* Build a lookup map from a migrations array keyed by migration name.
|
|
@@ -34,6 +36,41 @@ const c = toLookup(conversationsMigrations);
|
|
|
34
36
|
const ci = toLookup(canvasItemsMigrations);
|
|
35
37
|
const m = toLookup(miscMigrations);
|
|
36
38
|
const k = toLookup(kanbanMigrations);
|
|
39
|
+
const pr = toLookup(providerMigrations);
|
|
40
|
+
const pca = toLookup(providerCommitAttributionMigrations);
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Repair sessions whose parent link was lost during schema consolidation.
|
|
44
|
+
*
|
|
45
|
+
* Child sessions inherit their root session's worktree. When parent_session_id
|
|
46
|
+
* is missing, the final UUID segment of git_worktree can identify the owning
|
|
47
|
+
* root session. Only repair rows where that UUID belongs to another session in
|
|
48
|
+
* the same project.
|
|
49
|
+
*/
|
|
50
|
+
export const repairMissingSessionParentsFromWorktree = {
|
|
51
|
+
name: 'repair-missing-session-parents-from-worktree',
|
|
52
|
+
up(db) {
|
|
53
|
+
db.prepare(`
|
|
54
|
+
UPDATE sessions
|
|
55
|
+
SET parent_session_id = (
|
|
56
|
+
SELECT parent.id
|
|
57
|
+
FROM sessions AS parent
|
|
58
|
+
WHERE parent.id = substr(sessions.git_worktree, length(sessions.git_worktree) - 35, 36)
|
|
59
|
+
AND parent.project_id = sessions.project_id
|
|
60
|
+
AND parent.id <> sessions.id
|
|
61
|
+
)
|
|
62
|
+
WHERE parent_session_id IS NULL
|
|
63
|
+
AND git_worktree IS NOT NULL
|
|
64
|
+
AND EXISTS (
|
|
65
|
+
SELECT 1
|
|
66
|
+
FROM sessions AS parent
|
|
67
|
+
WHERE parent.id = substr(sessions.git_worktree, length(sessions.git_worktree) - 35, 36)
|
|
68
|
+
AND parent.project_id = sessions.project_id
|
|
69
|
+
AND parent.id <> sessions.id
|
|
70
|
+
)
|
|
71
|
+
`).run();
|
|
72
|
+
},
|
|
73
|
+
};
|
|
37
74
|
|
|
38
75
|
/**
|
|
39
76
|
* Flat, ordered list of every migration, matching the original execution order
|
|
@@ -134,6 +171,7 @@ export const allMigrations = validateMigrations([
|
|
|
134
171
|
s.get('sessions-add-archived'),
|
|
135
172
|
s.get('sessions-add-starred'),
|
|
136
173
|
s.get('sessions-add-manually_named'),
|
|
174
|
+
s.get('sessions-add-pr_url_auto_link_disabled'),
|
|
137
175
|
|
|
138
176
|
// --- Project session defaults table ---
|
|
139
177
|
p.get('project_session_defaults-create-table'),
|
|
@@ -158,6 +196,7 @@ export const allMigrations = validateMigrations([
|
|
|
158
196
|
m.get('session_templates-add-model'),
|
|
159
197
|
m.get('session_templates-add-mode'),
|
|
160
198
|
m.get('session_templates-add-effort_level'),
|
|
199
|
+
m.get('session_templates-add-quick-response-fields'),
|
|
161
200
|
|
|
162
201
|
// --- Conversation messages model ---
|
|
163
202
|
c.get('conversation_messages-add-model'),
|
|
@@ -166,13 +205,15 @@ export const allMigrations = validateMigrations([
|
|
|
166
205
|
m.get('app_settings-create-table'),
|
|
167
206
|
|
|
168
207
|
// --- Legacy model_providers cleanup ---
|
|
169
|
-
|
|
208
|
+
pr.get('model_providers-cleanup-legacy'),
|
|
170
209
|
|
|
171
210
|
// --- Providers + provider_models tables + seed ---
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
211
|
+
pr.get('providers-create-tables'),
|
|
212
|
+
pr.get('providers-add-kind'),
|
|
213
|
+
pr.get('providers-add-commit_attribution_override'),
|
|
214
|
+
pca.get('providers-normalize-commit_attribution_override'),
|
|
215
|
+
pr.get('providers-seed-built-in'),
|
|
216
|
+
pr.get('providers-seed-built-in-openai'),
|
|
176
217
|
|
|
177
218
|
// --- Sessions provider_id (from providers FK) ---
|
|
178
219
|
s.get('sessions-add-provider_id-from-providers'),
|
|
@@ -182,7 +223,7 @@ export const allMigrations = validateMigrations([
|
|
|
182
223
|
p.get('project_session_defaults-add-effort_level'),
|
|
183
224
|
|
|
184
225
|
// --- Update built-in models ---
|
|
185
|
-
|
|
226
|
+
pr.get('providers-update-built-in-models'),
|
|
186
227
|
|
|
187
228
|
// --- Sessions agent_type ---
|
|
188
229
|
s.get('sessions-add-agent_type'),
|
|
@@ -199,12 +240,24 @@ export const allMigrations = validateMigrations([
|
|
|
199
240
|
k.get('kanban_lanes-add-on_enter_prompt'),
|
|
200
241
|
k.get('kanban_lanes-add-agent-settings'),
|
|
201
242
|
|
|
243
|
+
// --- Sessions default mode / thinking defaults (table recreation) ---
|
|
244
|
+
s.get('sessions-migrate-default-mode-thinking'),
|
|
245
|
+
|
|
202
246
|
// --- Seed default global quick responses ---
|
|
203
247
|
m.get('quick_responses-seed-defaults'),
|
|
204
248
|
|
|
249
|
+
// --- Convert legacy quick responses into template-backed quick responses ---
|
|
250
|
+
m.get('session_templates-convert-quick-responses'),
|
|
251
|
+
|
|
205
252
|
// --- Seed default global session templates ---
|
|
206
253
|
m.get('session_templates-seed-defaults'),
|
|
207
254
|
|
|
208
255
|
// --- Update built-in Opus model to 4.7 ---
|
|
209
|
-
|
|
256
|
+
pr.get('providers-update-built-in-opus-4-7'),
|
|
257
|
+
|
|
258
|
+
// --- Project session defaults: add 'current' git mode ---
|
|
259
|
+
p.get('project_session_defaults-git_mode-add-current'),
|
|
260
|
+
|
|
261
|
+
// --- Repair missing session parent links from worktree paths ---
|
|
262
|
+
repairMissingSessionParentsFromWorktree,
|
|
210
263
|
]);
|
|
@@ -88,7 +88,7 @@ export const kanbanMigrations = [
|
|
|
88
88
|
addColumnIfMissing(db, 'kanban_lanes', 'on_enter_effort_level', 'TEXT');
|
|
89
89
|
addColumnIfMissing(db, 'kanban_lanes', 'on_enter_thinking_enabled', 'INTEGER');
|
|
90
90
|
addColumnIfMissing(db, 'kanban_lanes', 'on_enter_auto_reschedule_enabled', 'INTEGER DEFAULT 0');
|
|
91
|
-
addColumnIfMissing(db, 'kanban_lanes', 'on_enter_reschedule_delay_minutes', 'INTEGER DEFAULT
|
|
91
|
+
addColumnIfMissing(db, 'kanban_lanes', 'on_enter_reschedule_delay_minutes', 'INTEGER DEFAULT 60'); // keep in sync with DEFAULT_RESCHEDULE_DELAY_MINUTES
|
|
92
92
|
addColumnIfMissing(db, 'kanban_lanes', 'on_enter_reschedule_on_token_limit', 'INTEGER DEFAULT 1');
|
|
93
93
|
addColumnIfMissing(db, 'kanban_lanes', 'on_enter_reschedule_on_service_error', 'INTEGER DEFAULT 1');
|
|
94
94
|
addColumnIfMissing(db, 'kanban_lanes', 'on_enter_max_reschedule_count', 'INTEGER');
|