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
|
@@ -4,93 +4,7 @@
|
|
|
4
4
|
* Each export is an array of { name, up(db) } migration objects.
|
|
5
5
|
*/
|
|
6
6
|
import { randomUUID } from 'node:crypto';
|
|
7
|
-
import {
|
|
8
|
-
import { addColumnIfMissing, tableExists } from './migrationUtils.js';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Seed the built-in Anthropic provider if it doesn't exist.
|
|
12
|
-
*/
|
|
13
|
-
function seedBuiltInAnthropicProvider(db) {
|
|
14
|
-
const providerId = 'anthropic-default';
|
|
15
|
-
|
|
16
|
-
const existing = db
|
|
17
|
-
.prepare('SELECT id FROM providers WHERE id = ?')
|
|
18
|
-
.get(providerId);
|
|
19
|
-
|
|
20
|
-
if (!existing) {
|
|
21
|
-
const now = Date.now();
|
|
22
|
-
db.prepare(
|
|
23
|
-
`INSERT INTO providers (id, name, is_built_in, created_at, updated_at)
|
|
24
|
-
VALUES (?, ?, 1, ?, ?)`
|
|
25
|
-
).run(providerId, 'Anthropic (Official)', now, now);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Seed default Anthropic models if they don't exist
|
|
29
|
-
const defaultModels = [
|
|
30
|
-
{ id: 'anthropic-haiku', modelId: 'claude-haiku-4-5-20251001', displayName: 'Haiku 4.5', description: 'Fast & lightweight', tier: 'haiku' },
|
|
31
|
-
{ id: 'anthropic-sonnet', modelId: 'claude-sonnet-4-6', displayName: 'Sonnet 4.6', description: 'Balanced', tier: 'sonnet' },
|
|
32
|
-
{ id: 'anthropic-opus', modelId: 'claude-opus-4-6', displayName: 'Opus 4.6', description: 'Previous generation', tier: 'opus' },
|
|
33
|
-
{ id: 'anthropic-opus-4-7', modelId: 'claude-opus-4-7', displayName: 'Opus 4.7', description: 'Most capable (default)', tier: 'opus' },
|
|
34
|
-
];
|
|
35
|
-
|
|
36
|
-
const insertModel = db.prepare(
|
|
37
|
-
`INSERT OR IGNORE INTO provider_models (id, provider_id, model_id, display_name, description, tier, created_at)
|
|
38
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)`
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
const now = Date.now();
|
|
42
|
-
for (const model of defaultModels) {
|
|
43
|
-
insertModel.run(model.id, providerId, model.modelId, model.displayName, model.description, model.tier, now);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Seed the built-in OpenAI/Codex provider if it doesn't exist.
|
|
49
|
-
*/
|
|
50
|
-
function seedBuiltInOpenAIProvider(db) {
|
|
51
|
-
const providerId = 'openai-default';
|
|
52
|
-
const now = Date.now();
|
|
53
|
-
|
|
54
|
-
db.prepare(
|
|
55
|
-
`INSERT OR IGNORE INTO providers (
|
|
56
|
-
id, name, base_url, auth_token, kind, is_built_in, created_at, updated_at
|
|
57
|
-
)
|
|
58
|
-
VALUES (?, ?, NULL, NULL, 'openai', 1, ?, ?)`
|
|
59
|
-
).run(providerId, 'OpenAI (Official)', now, now);
|
|
60
|
-
|
|
61
|
-
const insertModel = db.prepare(
|
|
62
|
-
`INSERT OR IGNORE INTO provider_models (id, provider_id, model_id, display_name, description, tier, created_at)
|
|
63
|
-
VALUES (?, ?, ?, ?, ?, 'custom', ?)`
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
for (const model of OPENAI_MODELS) {
|
|
67
|
-
insertModel.run(model.seedId, providerId, model.id, model.name, model.description, now);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function seedBuiltInProviders(db) {
|
|
72
|
-
seedBuiltInAnthropicProvider(db);
|
|
73
|
-
seedBuiltInOpenAIProvider(db);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Update built-in models to 4.6 versions.
|
|
78
|
-
*/
|
|
79
|
-
function updateBuiltInModels(db) {
|
|
80
|
-
const providerId = 'anthropic-default';
|
|
81
|
-
|
|
82
|
-
db.prepare(
|
|
83
|
-
`UPDATE provider_models
|
|
84
|
-
SET model_id = ?, display_name = ?
|
|
85
|
-
WHERE provider_id = ? AND id = ?`
|
|
86
|
-
).run('claude-sonnet-4-6', 'Sonnet 4.6', providerId, 'anthropic-sonnet');
|
|
87
|
-
|
|
88
|
-
db.prepare(
|
|
89
|
-
`UPDATE provider_models
|
|
90
|
-
SET model_id = ?, display_name = ?
|
|
91
|
-
WHERE provider_id = ? AND id = ?`
|
|
92
|
-
).run('claude-opus-4-6', 'Opus 4.6', providerId, 'anthropic-opus');
|
|
93
|
-
}
|
|
7
|
+
import { addColumnIfMissing } from './migrationUtils.js';
|
|
94
8
|
|
|
95
9
|
/**
|
|
96
10
|
* Prompt strings for the default global session templates.
|
|
@@ -116,7 +30,10 @@ Create a draft pr and ensure all changes are committed and pushed.`,
|
|
|
116
30
|
*/
|
|
117
31
|
function seedDefaultSessionTemplates(db) {
|
|
118
32
|
const count = db.prepare(
|
|
119
|
-
|
|
33
|
+
`SELECT COUNT(*) AS cnt
|
|
34
|
+
FROM session_templates
|
|
35
|
+
WHERE project_id IS NULL
|
|
36
|
+
AND legacy_quick_response_id IS NULL`
|
|
120
37
|
).get().cnt;
|
|
121
38
|
if (count > 0) return;
|
|
122
39
|
|
|
@@ -131,8 +48,10 @@ function seedDefaultSessionTemplates(db) {
|
|
|
131
48
|
id, project_id, name, prompt,
|
|
132
49
|
next_template_id, thinking_enabled,
|
|
133
50
|
git_branch, git_mode, model, mode, effort_level, target_lane_id,
|
|
51
|
+
show_in_quick_responses, quick_response_auto_submit,
|
|
52
|
+
quick_response_sort_order, legacy_quick_response_id,
|
|
134
53
|
created_at, updated_at
|
|
135
|
-
) VALUES (?, NULL, ?, ?, NULL, 1, NULL, NULL, NULL, 'yolo', NULL, NULL, ?, ?)
|
|
54
|
+
) VALUES (?, NULL, ?, ?, NULL, 1, NULL, NULL, NULL, 'yolo', NULL, NULL, 0, 0, 0, NULL, ?, ?)
|
|
136
55
|
`);
|
|
137
56
|
|
|
138
57
|
const now = Date.now();
|
|
@@ -174,6 +93,38 @@ function seedDefaultQuickResponses(db) {
|
|
|
174
93
|
}
|
|
175
94
|
}
|
|
176
95
|
|
|
96
|
+
function convertQuickResponsesToTemplates(db) {
|
|
97
|
+
const rows = db.prepare('SELECT * FROM quick_responses ORDER BY sort_order ASC, created_at ASC').all();
|
|
98
|
+
const exists = db.prepare(
|
|
99
|
+
'SELECT 1 FROM session_templates WHERE legacy_quick_response_id = ? LIMIT 1'
|
|
100
|
+
);
|
|
101
|
+
const insert = db.prepare(`
|
|
102
|
+
INSERT INTO session_templates (
|
|
103
|
+
id, project_id, name, prompt,
|
|
104
|
+
next_template_id, thinking_enabled,
|
|
105
|
+
git_branch, git_mode, model, mode, effort_level, target_lane_id,
|
|
106
|
+
show_in_quick_responses, quick_response_auto_submit,
|
|
107
|
+
quick_response_sort_order, legacy_quick_response_id,
|
|
108
|
+
created_at, updated_at
|
|
109
|
+
) VALUES (?, ?, ?, ?, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, ?, ?, ?, ?, ?)
|
|
110
|
+
`);
|
|
111
|
+
|
|
112
|
+
for (const row of rows) {
|
|
113
|
+
if (exists.get(row.id)) continue;
|
|
114
|
+
insert.run(
|
|
115
|
+
randomUUID(),
|
|
116
|
+
row.project_id || null,
|
|
117
|
+
row.label,
|
|
118
|
+
row.content,
|
|
119
|
+
row.auto_submit ? 1 : 0,
|
|
120
|
+
row.sort_order ?? 0,
|
|
121
|
+
row.id,
|
|
122
|
+
row.created_at,
|
|
123
|
+
row.updated_at
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
177
128
|
/** @type {Array<{name: string, up: (db: import('better-sqlite3').Database) => void}>} */
|
|
178
129
|
export const miscMigrations = [
|
|
179
130
|
// --- Command buttons ---
|
|
@@ -207,6 +158,20 @@ export const miscMigrations = [
|
|
|
207
158
|
);
|
|
208
159
|
},
|
|
209
160
|
},
|
|
161
|
+
{
|
|
162
|
+
name: 'session_templates-add-quick-response-fields',
|
|
163
|
+
up(db) {
|
|
164
|
+
addColumnIfMissing(db, 'session_templates', 'show_in_quick_responses', 'INTEGER NOT NULL DEFAULT 0');
|
|
165
|
+
addColumnIfMissing(db, 'session_templates', 'quick_response_auto_submit', 'INTEGER NOT NULL DEFAULT 0');
|
|
166
|
+
addColumnIfMissing(db, 'session_templates', 'quick_response_sort_order', 'INTEGER NOT NULL DEFAULT 0');
|
|
167
|
+
addColumnIfMissing(db, 'session_templates', 'legacy_quick_response_id', 'TEXT');
|
|
168
|
+
db.exec(`
|
|
169
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_session_templates_legacy_quick_response_id
|
|
170
|
+
ON session_templates(legacy_quick_response_id)
|
|
171
|
+
WHERE legacy_quick_response_id IS NOT NULL
|
|
172
|
+
`);
|
|
173
|
+
},
|
|
174
|
+
},
|
|
210
175
|
|
|
211
176
|
// --- App settings table ---
|
|
212
177
|
{
|
|
@@ -222,81 +187,6 @@ export const miscMigrations = [
|
|
|
222
187
|
},
|
|
223
188
|
},
|
|
224
189
|
|
|
225
|
-
// --- Legacy model_providers cleanup ---
|
|
226
|
-
{
|
|
227
|
-
name: 'model_providers-cleanup-legacy',
|
|
228
|
-
up(db) {
|
|
229
|
-
const hasLegacyTable = tableExists(db, 'model_providers');
|
|
230
|
-
if (hasLegacyTable) {
|
|
231
|
-
db.exec('DROP TABLE IF EXISTS provider_models');
|
|
232
|
-
db.exec('DROP TABLE IF EXISTS model_providers');
|
|
233
|
-
}
|
|
234
|
-
},
|
|
235
|
-
},
|
|
236
|
-
|
|
237
|
-
// --- Providers and provider_models tables ---
|
|
238
|
-
{
|
|
239
|
-
name: 'providers-create-tables',
|
|
240
|
-
up(db) {
|
|
241
|
-
db.exec(`
|
|
242
|
-
CREATE TABLE IF NOT EXISTS providers (
|
|
243
|
-
id TEXT PRIMARY KEY,
|
|
244
|
-
name TEXT NOT NULL,
|
|
245
|
-
base_url TEXT,
|
|
246
|
-
auth_token TEXT,
|
|
247
|
-
api_timeout_ms INTEGER,
|
|
248
|
-
additional_env_vars TEXT,
|
|
249
|
-
is_built_in INTEGER NOT NULL DEFAULT 0,
|
|
250
|
-
kind TEXT NOT NULL DEFAULT 'anthropic' CHECK(kind IN ('anthropic','openai')),
|
|
251
|
-
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
252
|
-
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
253
|
-
);
|
|
254
|
-
|
|
255
|
-
CREATE TABLE IF NOT EXISTS provider_models (
|
|
256
|
-
id TEXT PRIMARY KEY,
|
|
257
|
-
provider_id TEXT NOT NULL REFERENCES providers(id) ON DELETE CASCADE,
|
|
258
|
-
model_id TEXT NOT NULL,
|
|
259
|
-
display_name TEXT NOT NULL,
|
|
260
|
-
description TEXT,
|
|
261
|
-
tier TEXT CHECK(tier IN ('opus', 'sonnet', 'haiku', 'custom')),
|
|
262
|
-
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
263
|
-
);
|
|
264
|
-
CREATE INDEX IF NOT EXISTS idx_provider_models_provider ON provider_models(provider_id);
|
|
265
|
-
`);
|
|
266
|
-
},
|
|
267
|
-
},
|
|
268
|
-
|
|
269
|
-
// --- Add `kind` column to providers (for DBs that predate the CREATE TABLE change) ---
|
|
270
|
-
{
|
|
271
|
-
name: 'providers-add-kind',
|
|
272
|
-
up(db) {
|
|
273
|
-
addColumnIfMissing(
|
|
274
|
-
db,
|
|
275
|
-
'providers',
|
|
276
|
-
'kind',
|
|
277
|
-
"TEXT NOT NULL DEFAULT 'anthropic' CHECK(kind IN ('anthropic','openai'))"
|
|
278
|
-
);
|
|
279
|
-
},
|
|
280
|
-
},
|
|
281
|
-
|
|
282
|
-
// --- Seed built-in providers ---
|
|
283
|
-
{
|
|
284
|
-
name: 'providers-seed-built-in',
|
|
285
|
-
up(db) { seedBuiltInProviders(db); },
|
|
286
|
-
},
|
|
287
|
-
|
|
288
|
-
// --- Seed built-in OpenAI provider for DBs that already ran the original seed ---
|
|
289
|
-
{
|
|
290
|
-
name: 'providers-seed-built-in-openai',
|
|
291
|
-
up(db) { seedBuiltInOpenAIProvider(db); },
|
|
292
|
-
},
|
|
293
|
-
|
|
294
|
-
// --- Update built-in models to 4.6 ---
|
|
295
|
-
{
|
|
296
|
-
name: 'providers-update-built-in-models',
|
|
297
|
-
up(db) { updateBuiltInModels(db); },
|
|
298
|
-
},
|
|
299
|
-
|
|
300
190
|
// --- Agent call logs table ---
|
|
301
191
|
{
|
|
302
192
|
name: 'agent_call_logs-create-table',
|
|
@@ -340,30 +230,15 @@ export const miscMigrations = [
|
|
|
340
230
|
up(db) { seedDefaultQuickResponses(db); },
|
|
341
231
|
},
|
|
342
232
|
|
|
233
|
+
{
|
|
234
|
+
name: 'session_templates-convert-quick-responses',
|
|
235
|
+
up(db) { convertQuickResponsesToTemplates(db); },
|
|
236
|
+
},
|
|
237
|
+
|
|
343
238
|
// --- Seed default global session templates ---
|
|
344
239
|
{
|
|
345
240
|
name: 'session_templates-seed-defaults',
|
|
346
241
|
up(db) { seedDefaultSessionTemplates(db); },
|
|
347
242
|
},
|
|
348
243
|
|
|
349
|
-
// --- Add Opus 4.7 as a new built-in model (keep Opus 4.6 for existing sessions) ---
|
|
350
|
-
{
|
|
351
|
-
name: 'providers-update-built-in-opus-4-7',
|
|
352
|
-
up(db) {
|
|
353
|
-
const providerId = 'anthropic-default';
|
|
354
|
-
|
|
355
|
-
// Mark existing Opus 4.6 row as previous generation
|
|
356
|
-
db.prepare(
|
|
357
|
-
`UPDATE provider_models
|
|
358
|
-
SET description = ?
|
|
359
|
-
WHERE provider_id = ? AND id = ?`
|
|
360
|
-
).run('Previous generation', providerId, 'anthropic-opus');
|
|
361
|
-
|
|
362
|
-
// Insert new Opus 4.7 row (OR IGNORE in case seed already created it)
|
|
363
|
-
db.prepare(
|
|
364
|
-
`INSERT OR IGNORE INTO provider_models (id, provider_id, model_id, display_name, description, tier, created_at)
|
|
365
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)`
|
|
366
|
-
).run('anthropic-opus-4-7', providerId, 'claude-opus-4-7', 'Opus 4.7', 'Most capable (default)', 'opus', Date.now());
|
|
367
|
-
},
|
|
368
|
-
},
|
|
369
244
|
];
|
|
@@ -96,4 +96,35 @@ export const projectsMigrations = [
|
|
|
96
96
|
}
|
|
97
97
|
},
|
|
98
98
|
},
|
|
99
|
+
{
|
|
100
|
+
name: 'project_session_defaults-git_mode-add-current',
|
|
101
|
+
up(db) {
|
|
102
|
+
if (!tableExists(db, 'project_session_defaults')) return;
|
|
103
|
+
// SQLite doesn't support ALTER TABLE ... ALTER CONSTRAINT, so we recreate the table
|
|
104
|
+
db.exec(`
|
|
105
|
+
CREATE TABLE project_session_defaults_new (
|
|
106
|
+
id TEXT PRIMARY KEY,
|
|
107
|
+
project_id TEXT NOT NULL UNIQUE,
|
|
108
|
+
mode TEXT CHECK(mode IN ('plan', 'standard', 'yolo')),
|
|
109
|
+
thinking_enabled INTEGER,
|
|
110
|
+
start_immediately INTEGER,
|
|
111
|
+
git_mode TEXT CHECK(git_mode IN ('branch', 'worktree', 'current')),
|
|
112
|
+
git_branch TEXT,
|
|
113
|
+
model TEXT,
|
|
114
|
+
provider_id TEXT REFERENCES providers(id),
|
|
115
|
+
effort_level TEXT CHECK(effort_level IN ('low', 'medium', 'high', 'max', 'auto')),
|
|
116
|
+
created_at INTEGER NOT NULL,
|
|
117
|
+
updated_at INTEGER NOT NULL,
|
|
118
|
+
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
|
|
119
|
+
);
|
|
120
|
+
INSERT INTO project_session_defaults_new
|
|
121
|
+
SELECT id, project_id, mode, thinking_enabled, start_immediately, git_mode,
|
|
122
|
+
git_branch, model, provider_id, effort_level, created_at, updated_at
|
|
123
|
+
FROM project_session_defaults;
|
|
124
|
+
DROP TABLE project_session_defaults;
|
|
125
|
+
ALTER TABLE project_session_defaults_new RENAME TO project_session_defaults;
|
|
126
|
+
CREATE INDEX IF NOT EXISTS idx_project_defaults_projectId ON project_session_defaults(project_id);
|
|
127
|
+
`);
|
|
128
|
+
},
|
|
129
|
+
},
|
|
99
130
|
];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { normalizeCommitAttributionOverride } from '../../../../shared/src/contracts/providers.js';
|
|
2
|
+
import { tableExists } from './migrationUtils.js';
|
|
3
|
+
|
|
4
|
+
function normalizeProviderCommitAttributionOverrides(db) {
|
|
5
|
+
if (!tableExists(db, 'providers')) return;
|
|
6
|
+
const rows = db
|
|
7
|
+
.prepare('SELECT id, commit_attribution_override FROM providers WHERE commit_attribution_override IS NOT NULL')
|
|
8
|
+
.all();
|
|
9
|
+
const update = db.prepare('UPDATE providers SET commit_attribution_override = ? WHERE id = ?');
|
|
10
|
+
|
|
11
|
+
for (const row of rows) {
|
|
12
|
+
try {
|
|
13
|
+
const normalized = normalizeCommitAttributionOverride(row.commit_attribution_override);
|
|
14
|
+
if (normalized !== row.commit_attribution_override) {
|
|
15
|
+
update.run(normalized, row.id);
|
|
16
|
+
}
|
|
17
|
+
} catch {
|
|
18
|
+
// Irrecoverable legacy values, such as bare emails, are preserved until edited.
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const providerCommitAttributionMigrations = [
|
|
24
|
+
{
|
|
25
|
+
name: 'providers-normalize-commit_attribution_override',
|
|
26
|
+
up(db) {
|
|
27
|
+
normalizeProviderCommitAttributionOverrides(db);
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
];
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { OPENAI_MODELS } from '../../../../shared/src/index.js';
|
|
2
|
+
import { addColumnIfMissing, tableExists } from './migrationUtils.js';
|
|
3
|
+
|
|
4
|
+
function seedBuiltInAnthropicProvider(db) {
|
|
5
|
+
const providerId = 'anthropic-default';
|
|
6
|
+
const existing = db
|
|
7
|
+
.prepare('SELECT id FROM providers WHERE id = ?')
|
|
8
|
+
.get(providerId);
|
|
9
|
+
|
|
10
|
+
if (!existing) {
|
|
11
|
+
const now = Date.now();
|
|
12
|
+
db.prepare(
|
|
13
|
+
`INSERT INTO providers (id, name, is_built_in, created_at, updated_at)
|
|
14
|
+
VALUES (?, ?, 1, ?, ?)`
|
|
15
|
+
).run(providerId, 'Anthropic (Official)', now, now);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const defaultModels = [
|
|
19
|
+
{ id: 'anthropic-haiku', modelId: 'claude-haiku-4-5-20251001', displayName: 'Haiku 4.5', description: 'Fast & lightweight', tier: 'haiku' },
|
|
20
|
+
{ id: 'anthropic-sonnet', modelId: 'claude-sonnet-4-6', displayName: 'Sonnet 4.6', description: 'Balanced', tier: 'sonnet' },
|
|
21
|
+
{ id: 'anthropic-opus', modelId: 'claude-opus-4-6', displayName: 'Opus 4.6', description: 'Previous generation', tier: 'opus' },
|
|
22
|
+
{ id: 'anthropic-opus-4-7', modelId: 'claude-opus-4-7', displayName: 'Opus 4.7', description: 'Most capable (default)', tier: 'opus' },
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const insertModel = db.prepare(
|
|
26
|
+
`INSERT OR IGNORE INTO provider_models (id, provider_id, model_id, display_name, description, tier, created_at)
|
|
27
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
const now = Date.now();
|
|
31
|
+
for (const model of defaultModels) {
|
|
32
|
+
insertModel.run(model.id, providerId, model.modelId, model.displayName, model.description, model.tier, now);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function seedBuiltInOpenAIProvider(db) {
|
|
37
|
+
const providerId = 'openai-default';
|
|
38
|
+
const now = Date.now();
|
|
39
|
+
|
|
40
|
+
db.prepare(
|
|
41
|
+
`INSERT OR IGNORE INTO providers (
|
|
42
|
+
id, name, base_url, auth_token, kind, is_built_in, created_at, updated_at
|
|
43
|
+
)
|
|
44
|
+
VALUES (?, ?, NULL, NULL, 'openai', 1, ?, ?)`
|
|
45
|
+
).run(providerId, 'OpenAI (Official)', now, now);
|
|
46
|
+
|
|
47
|
+
const insertModel = db.prepare(
|
|
48
|
+
`INSERT OR IGNORE INTO provider_models (id, provider_id, model_id, display_name, description, tier, created_at)
|
|
49
|
+
VALUES (?, ?, ?, ?, ?, 'custom', ?)`
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
for (const model of OPENAI_MODELS) {
|
|
53
|
+
insertModel.run(model.seedId, providerId, model.id, model.name, model.description, now);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function seedBuiltInProviders(db) {
|
|
58
|
+
seedBuiltInAnthropicProvider(db);
|
|
59
|
+
seedBuiltInOpenAIProvider(db);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function updateBuiltInModels(db) {
|
|
63
|
+
const providerId = 'anthropic-default';
|
|
64
|
+
|
|
65
|
+
db.prepare(
|
|
66
|
+
`UPDATE provider_models
|
|
67
|
+
SET model_id = ?, display_name = ?
|
|
68
|
+
WHERE provider_id = ? AND id = ?`
|
|
69
|
+
).run('claude-sonnet-4-6', 'Sonnet 4.6', providerId, 'anthropic-sonnet');
|
|
70
|
+
|
|
71
|
+
db.prepare(
|
|
72
|
+
`UPDATE provider_models
|
|
73
|
+
SET model_id = ?, display_name = ?
|
|
74
|
+
WHERE provider_id = ? AND id = ?`
|
|
75
|
+
).run('claude-opus-4-6', 'Opus 4.6', providerId, 'anthropic-opus');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export const providerMigrations = [
|
|
79
|
+
{
|
|
80
|
+
name: 'model_providers-cleanup-legacy',
|
|
81
|
+
up(db) {
|
|
82
|
+
if (tableExists(db, 'model_providers')) {
|
|
83
|
+
db.exec('DROP TABLE IF EXISTS provider_models');
|
|
84
|
+
db.exec('DROP TABLE IF EXISTS model_providers');
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: 'providers-create-tables',
|
|
90
|
+
up(db) {
|
|
91
|
+
db.exec(`
|
|
92
|
+
CREATE TABLE IF NOT EXISTS providers (
|
|
93
|
+
id TEXT PRIMARY KEY,
|
|
94
|
+
name TEXT NOT NULL,
|
|
95
|
+
base_url TEXT,
|
|
96
|
+
auth_token TEXT,
|
|
97
|
+
api_timeout_ms INTEGER,
|
|
98
|
+
additional_env_vars TEXT,
|
|
99
|
+
commit_attribution_override TEXT,
|
|
100
|
+
is_built_in INTEGER NOT NULL DEFAULT 0,
|
|
101
|
+
kind TEXT NOT NULL DEFAULT 'anthropic' CHECK(kind IN ('anthropic','openai')),
|
|
102
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
103
|
+
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
CREATE TABLE IF NOT EXISTS provider_models (
|
|
107
|
+
id TEXT PRIMARY KEY,
|
|
108
|
+
provider_id TEXT NOT NULL REFERENCES providers(id) ON DELETE CASCADE,
|
|
109
|
+
model_id TEXT NOT NULL,
|
|
110
|
+
display_name TEXT NOT NULL,
|
|
111
|
+
description TEXT,
|
|
112
|
+
tier TEXT CHECK(tier IN ('opus', 'sonnet', 'haiku', 'custom')),
|
|
113
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
114
|
+
);
|
|
115
|
+
CREATE INDEX IF NOT EXISTS idx_provider_models_provider ON provider_models(provider_id);
|
|
116
|
+
`);
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: 'providers-add-kind',
|
|
121
|
+
up(db) {
|
|
122
|
+
addColumnIfMissing(
|
|
123
|
+
db,
|
|
124
|
+
'providers',
|
|
125
|
+
'kind',
|
|
126
|
+
"TEXT NOT NULL DEFAULT 'anthropic' CHECK(kind IN ('anthropic','openai'))"
|
|
127
|
+
);
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
name: 'providers-add-commit_attribution_override',
|
|
132
|
+
up(db) {
|
|
133
|
+
addColumnIfMissing(db, 'providers', 'commit_attribution_override', 'TEXT');
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: 'providers-seed-built-in',
|
|
138
|
+
up(db) { seedBuiltInProviders(db); },
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
name: 'providers-seed-built-in-openai',
|
|
142
|
+
up(db) { seedBuiltInOpenAIProvider(db); },
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
name: 'providers-update-built-in-models',
|
|
146
|
+
up(db) { updateBuiltInModels(db); },
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: 'providers-update-built-in-opus-4-7',
|
|
150
|
+
up(db) {
|
|
151
|
+
const providerId = 'anthropic-default';
|
|
152
|
+
|
|
153
|
+
db.prepare(
|
|
154
|
+
`UPDATE provider_models
|
|
155
|
+
SET description = ?
|
|
156
|
+
WHERE provider_id = ? AND id = ?`
|
|
157
|
+
).run('Previous generation', providerId, 'anthropic-opus');
|
|
158
|
+
|
|
159
|
+
db.prepare(
|
|
160
|
+
`INSERT OR IGNORE INTO provider_models (id, provider_id, model_id, display_name, description, tier, created_at)
|
|
161
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`
|
|
162
|
+
).run('anthropic-opus-4-7', providerId, 'claude-opus-4-7', 'Opus 4.7', 'Most capable (default)', 'opus', Date.now());
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
];
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper for recreating the sessions table during migrations that change
|
|
3
|
+
* column defaults or constraints (SQLite requires table recreation for these).
|
|
4
|
+
*/
|
|
5
|
+
import { getColumns } from './migrationUtils.js';
|
|
6
|
+
|
|
7
|
+
const TABLE_SESSIONS = 'sessions';
|
|
8
|
+
|
|
9
|
+
const SESSIONS_TARGET_MODE_DEFAULT = "'yolo'";
|
|
10
|
+
const SESSIONS_TARGET_THINKING_ENABLED_DEFAULT = '1';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* SQL column definitions for the sessions table with current defaults.
|
|
14
|
+
*/
|
|
15
|
+
export const SESSIONS_ALL_CURRENT_COLUMNS = `
|
|
16
|
+
id TEXT PRIMARY KEY,
|
|
17
|
+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
18
|
+
name TEXT NOT NULL,
|
|
19
|
+
status TEXT NOT NULL DEFAULT 'starting' CHECK (status IN ('starting', 'running', 'waiting', 'stopped', 'completed', 'error', 'scheduled')),
|
|
20
|
+
mode TEXT NOT NULL DEFAULT 'yolo' CHECK (mode IN ('plan', 'standard', 'yolo')),
|
|
21
|
+
thinking_enabled INTEGER NOT NULL DEFAULT 1,
|
|
22
|
+
archived INTEGER NOT NULL DEFAULT 0,
|
|
23
|
+
git_branch TEXT,
|
|
24
|
+
git_worktree TEXT,
|
|
25
|
+
pr_url TEXT,
|
|
26
|
+
error TEXT,
|
|
27
|
+
effort_level TEXT CHECK(effort_level IN ('low', 'medium', 'high', 'max', 'auto')),
|
|
28
|
+
cost_usd REAL DEFAULT 0,
|
|
29
|
+
claude_session_id TEXT,
|
|
30
|
+
model TEXT,
|
|
31
|
+
provider_id TEXT,
|
|
32
|
+
next_template_id TEXT REFERENCES session_templates(id) ON DELETE SET NULL,
|
|
33
|
+
parent_session_id TEXT REFERENCES sessions(id) ON DELETE SET NULL,
|
|
34
|
+
input_tokens INTEGER DEFAULT 0,
|
|
35
|
+
output_tokens INTEGER DEFAULT 0,
|
|
36
|
+
thinking_tokens INTEGER DEFAULT 0,
|
|
37
|
+
cache_read_input_tokens INTEGER DEFAULT 0,
|
|
38
|
+
cache_creation_input_tokens INTEGER DEFAULT 0,
|
|
39
|
+
web_search_requests INTEGER DEFAULT 0,
|
|
40
|
+
context_window INTEGER DEFAULT 200000,
|
|
41
|
+
starred INTEGER NOT NULL DEFAULT 0,
|
|
42
|
+
manually_named INTEGER NOT NULL DEFAULT 0,
|
|
43
|
+
scheduled_at INTEGER DEFAULT NULL,
|
|
44
|
+
reschedule_delay_minutes INTEGER DEFAULT 15,
|
|
45
|
+
auto_reschedule_enabled INTEGER DEFAULT 0,
|
|
46
|
+
reschedule_on_token_limit INTEGER DEFAULT 1,
|
|
47
|
+
reschedule_on_service_error INTEGER DEFAULT 1,
|
|
48
|
+
max_reschedule_count INTEGER DEFAULT NULL,
|
|
49
|
+
max_total_tokens INTEGER DEFAULT NULL,
|
|
50
|
+
reschedule_count INTEGER DEFAULT 0,
|
|
51
|
+
reschedule_at_token_count INTEGER DEFAULT NULL,
|
|
52
|
+
pending_prompt TEXT,
|
|
53
|
+
slash_commands TEXT,
|
|
54
|
+
pending_model TEXT,
|
|
55
|
+
auto_send_pending_prompt INTEGER DEFAULT 0,
|
|
56
|
+
agent_type TEXT DEFAULT 'claude-code',
|
|
57
|
+
target_lane_id TEXT REFERENCES kanban_lanes(id) ON DELETE SET NULL,
|
|
58
|
+
lane_trigger_depth INTEGER NOT NULL DEFAULT 0,
|
|
59
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
60
|
+
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
61
|
+
`;
|
|
62
|
+
|
|
63
|
+
export const SESSIONS_ALL_CURRENT_COLUMN_NAMES = [
|
|
64
|
+
'id', 'project_id', 'name', 'status', 'mode', 'thinking_enabled',
|
|
65
|
+
'archived', 'git_branch', 'git_worktree', 'pr_url', 'error',
|
|
66
|
+
'effort_level', 'cost_usd', 'claude_session_id', 'model', 'provider_id',
|
|
67
|
+
'next_template_id', 'parent_session_id', 'input_tokens', 'output_tokens',
|
|
68
|
+
'thinking_tokens', 'cache_read_input_tokens', 'cache_creation_input_tokens',
|
|
69
|
+
'web_search_requests', 'context_window', 'starred', 'manually_named',
|
|
70
|
+
'scheduled_at', 'reschedule_delay_minutes', 'auto_reschedule_enabled',
|
|
71
|
+
'reschedule_on_token_limit', 'reschedule_on_service_error',
|
|
72
|
+
'max_reschedule_count', 'max_total_tokens', 'reschedule_count',
|
|
73
|
+
'reschedule_at_token_count', 'pending_prompt', 'slash_commands',
|
|
74
|
+
'pending_model', 'auto_send_pending_prompt', 'agent_type', 'target_lane_id',
|
|
75
|
+
'lane_trigger_depth', 'created_at', 'updated_at',
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Recreate the sessions table with the given column SQL, preserving existing data.
|
|
80
|
+
* @param {import('better-sqlite3').Database} db
|
|
81
|
+
* @param {string} columnsSql
|
|
82
|
+
* @param {string[]} allColumnNames
|
|
83
|
+
*/
|
|
84
|
+
export function recreateSessionsTable(db, columnsSql, allColumnNames) {
|
|
85
|
+
const existingColumnNames = getColumns(db, TABLE_SESSIONS);
|
|
86
|
+
const selectColumns = allColumnNames
|
|
87
|
+
.filter((col) => existingColumnNames.includes(col))
|
|
88
|
+
.join(', ');
|
|
89
|
+
|
|
90
|
+
const foreignKeysEnabled = db.pragma('foreign_keys', { simple: true });
|
|
91
|
+
db.pragma('foreign_keys = OFF');
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
db.exec(`
|
|
95
|
+
CREATE TABLE sessions_new (${columnsSql});
|
|
96
|
+
INSERT INTO sessions_new (${selectColumns})
|
|
97
|
+
SELECT ${selectColumns} FROM sessions;
|
|
98
|
+
DROP TABLE sessions;
|
|
99
|
+
ALTER TABLE sessions_new RENAME TO sessions;
|
|
100
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_project ON sessions(project_id);
|
|
101
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_status ON sessions(status);
|
|
102
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_archived ON sessions(archived);
|
|
103
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_starred ON sessions(archived, starred);
|
|
104
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_next_template ON sessions(next_template_id);
|
|
105
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_parent ON sessions(parent_session_id);
|
|
106
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_scheduled ON sessions(scheduled_at) WHERE scheduled_at IS NOT NULL;
|
|
107
|
+
`);
|
|
108
|
+
|
|
109
|
+
const foreignKeyViolations = db.pragma('foreign_key_check');
|
|
110
|
+
if (foreignKeyViolations.length > 0) {
|
|
111
|
+
throw new Error('sessions table migration failed foreign key check');
|
|
112
|
+
}
|
|
113
|
+
} finally {
|
|
114
|
+
db.pragma(`foreign_keys = ${foreignKeysEnabled ? 'ON' : 'OFF'}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Migrate sessions table defaults: mode → 'yolo', thinking_enabled → 1.
|
|
120
|
+
* No-op if the table already has the target defaults.
|
|
121
|
+
* @param {import('better-sqlite3').Database} db
|
|
122
|
+
*/
|
|
123
|
+
export function migrateSessionsDefaultModeAndThinking(db) {
|
|
124
|
+
const columns = db.prepare(`PRAGMA table_info(${TABLE_SESSIONS})`).all();
|
|
125
|
+
const modeColumn = columns.find((col) => col.name === 'mode');
|
|
126
|
+
const thinkingEnabledColumn = columns.find((col) => col.name === 'thinking_enabled');
|
|
127
|
+
|
|
128
|
+
if (
|
|
129
|
+
modeColumn?.dflt_value === SESSIONS_TARGET_MODE_DEFAULT
|
|
130
|
+
&& thinkingEnabledColumn?.dflt_value === SESSIONS_TARGET_THINKING_ENABLED_DEFAULT
|
|
131
|
+
) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
recreateSessionsTable(db, SESSIONS_ALL_CURRENT_COLUMNS, SESSIONS_ALL_CURRENT_COLUMN_NAMES);
|
|
136
|
+
}
|