circuschief 0.7.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 +10 -4
- package/packages/server/src/api/projects.js +10 -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-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/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 +1 -0
- package/packages/server/src/db/index.js +0 -3
- package/packages/server/src/db/migrations/index.js +36 -202
- package/packages/server/src/db/seedBaselineData.js +137 -0
- package/packages/server/src/db/session-helpers.js +6 -3
- package/packages/server/src/middleware/sessionLookup.js +81 -8
- package/packages/server/src/schema.sql +149 -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 +8 -8
- 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 +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 -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 +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 +2 -2
- package/packages/web/dist/assets/{ActiveSessionsView-UJsCILDL.js → ActiveSessionsView-B0XHqLmv.js} +1 -1
- package/packages/web/dist/assets/{AgentLogsView-BGFPLjLa.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-D8S258uP.js → CommandButtonDetailView-CdSCPp78.js} +1 -1
- package/packages/web/dist/assets/EffortLevelSelector-hc2MNKg6.js +1 -0
- package/packages/web/dist/assets/{GeneralSettingsView-DsHChEhv.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-CIkOSkWX.js → InterpolationHelp-BO1j9Z3_.js} +1 -1
- package/packages/web/dist/assets/MarkdownEditor-ucRAP_UM.js +2 -0
- package/packages/web/dist/assets/{ModelSelector-D8hbTRIt.css → ModelSelector-BSxKUSus.css} +1 -1
- package/packages/web/dist/assets/{ModelSelector-BMpR0DPr.js → ModelSelector-CwTz8ZWO.js} +1 -1
- package/packages/web/dist/assets/{NewSessionView-CUUdHkfv.css → NewSessionView-BDPb-1qr.css} +1 -1
- 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-D9sK0fdH.css → ProjectEditView-J15mcsWz.css} +1 -1
- package/packages/web/dist/assets/{ProjectListView-B9FuWESY.js → ProjectListView-DcNyuINs.js} +1 -1
- package/packages/web/dist/assets/{ProjectNewView-D62jYlBL.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-CDm5vwP7.js → QuickResponseSettings-BQwQXuL7.js} +1 -1
- package/packages/web/dist/assets/{QuickResponsesPanel-DZ_Lre_l.js → QuickResponsesPanel-BzSYcCSP.js} +1 -1
- package/packages/web/dist/assets/{ResizableTextarea-DiIOEGjN.js → ResizableTextarea-B3YIdIXv.js} +1 -1
- package/packages/web/dist/assets/{SessionCard-DmjnVYWn.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-DYUISplS.js → SessionFormOptions-B6AxyREh.js} +1 -1
- 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-DpUE6Xsh.js → SessionLogStream-LlZ3z_Xj.js} +1 -1
- package/packages/web/dist/assets/{SettingsView-BC055tIA.js → SettingsView-CTGiGvR2.js} +1 -1
- package/packages/web/dist/assets/{SlashCommandWizard-DmTyNG9O.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-BgnRCwlq.js → SummarySettingsView-BR2ZjEa3.js} +1 -1
- package/packages/web/dist/assets/{TemplateDetailView-BlhOmLUX.js → TemplateDetailView-DH6Oswsp.js} +1 -1
- package/packages/web/dist/assets/{commandButtons-D4RPpLiu.js → commandButtons-BfqR-fqq.js} +1 -1
- package/packages/web/dist/assets/{index-CfL84oGW.js → index-1zziPL6l.js} +1 -1
- package/packages/web/dist/assets/{index-OfCywayk.js → index-7kzHPxSF.js} +1 -1
- package/packages/web/dist/assets/{index-PDesaJc6.js → index-B0N_obMc.js} +1 -1
- package/packages/web/dist/assets/{index-Cpy4-yv3.js → index-BNk_gdfI.js} +1 -1
- package/packages/web/dist/assets/{index-Cs2nxhrT.css → index-BY174HVJ.css} +1 -1
- package/packages/web/dist/assets/{index-9vb2KaAd.js → index-CSqaAH-0.js} +1 -1
- package/packages/web/dist/assets/{index-CNwkdB0T.js → index-C_q4WlK8.js} +1 -1
- package/packages/web/dist/assets/{index-B0CvZXuN.js → index-D1wpU4y0.js} +1 -1
- package/packages/web/dist/assets/{index-4rhEeO0B.js → index-D5zCA8sD.js} +1 -1
- package/packages/web/dist/assets/{index-CkmxO8Mm.js → index-DGR8ELWY.js} +1 -1
- package/packages/web/dist/assets/{index-CrAQJmoZ.js → index-DHga8pXo.js} +1 -1
- package/packages/web/dist/assets/{index-BUhvkAdF.js → index-DSby02Wl.js} +1 -1
- package/packages/web/dist/assets/{index-BGwH4Cfn.js → index-DgkC10TW.js} +3 -3
- package/packages/web/dist/assets/{index-DfrE0gAC.js → index-DqjXJTVI.js} +1 -1
- package/packages/web/dist/assets/{index-Bn5xdGFM.js → index-DtfUt785.js} +1 -1
- package/packages/web/dist/assets/{index-KwEyz0F3.js → index-_4S2uLDI.js} +1 -1
- package/packages/web/dist/assets/{index-B6G18FqB.js → index-fK8FIZgP.js} +15 -14
- package/packages/web/dist/assets/{index-BcnkUk2o.js → index-gmiZeFXN.js} +1 -1
- package/packages/web/dist/assets/{index-D6Ky9vJe.js → index-irD539ZM.js} +1 -1
- package/packages/web/dist/assets/{index-uB6nhSvz.js → index-yq-E1Y00.js} +1 -1
- package/packages/web/dist/assets/{projects-BUiOGmmb.js → projects-DXYQNJIi.js} +1 -1
- package/packages/web/dist/assets/{providers-Bh1ZiiJi.js → providers-1bnH-exJ.js} +1 -1
- package/packages/web/dist/assets/sessions-6zGUlFrt.js +1 -0
- package/packages/web/dist/assets/{settings-Z4AVVmkJ.js → settings-MbfRir0d.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/server/src/db/migrations/canvasItemsMigrations.js +0 -109
- package/packages/server/src/db/migrations/conversationsMigrations.js +0 -187
- 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 -287
- 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/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/NewSessionView-BCqtIgWH.js +0 -3
- 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/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/sessions-DH1R-NhV.js +0 -1
|
@@ -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,
|
|
@@ -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();
|
|
@@ -1,210 +1,44 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Repair sessions whose parent link was lost during schema consolidation.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* The ordering below mirrors the original #runMigrations() top-to-bottom flow
|
|
9
|
-
* as closely as possible.
|
|
4
|
+
* Child sessions inherit their root session's worktree. When parent_session_id
|
|
5
|
+
* is missing, the final UUID segment of git_worktree can identify the owning
|
|
6
|
+
* root session. Only repair rows where that UUID belongs to another session in
|
|
7
|
+
* the same project.
|
|
10
8
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const m = toLookup(miscMigrations);
|
|
36
|
-
const k = toLookup(kanbanMigrations);
|
|
9
|
+
export const repairMissingSessionParentsFromWorktree = {
|
|
10
|
+
name: 'repair-missing-session-parents-from-worktree',
|
|
11
|
+
up(db) {
|
|
12
|
+
db.prepare(`
|
|
13
|
+
UPDATE sessions
|
|
14
|
+
SET parent_session_id = (
|
|
15
|
+
SELECT parent.id
|
|
16
|
+
FROM sessions AS parent
|
|
17
|
+
WHERE parent.id = substr(sessions.git_worktree, length(sessions.git_worktree) - 35, 36)
|
|
18
|
+
AND parent.project_id = sessions.project_id
|
|
19
|
+
AND parent.id <> sessions.id
|
|
20
|
+
)
|
|
21
|
+
WHERE parent_session_id IS NULL
|
|
22
|
+
AND git_worktree IS NOT NULL
|
|
23
|
+
AND EXISTS (
|
|
24
|
+
SELECT 1
|
|
25
|
+
FROM sessions AS parent
|
|
26
|
+
WHERE parent.id = substr(sessions.git_worktree, length(sessions.git_worktree) - 35, 36)
|
|
27
|
+
AND parent.project_id = sessions.project_id
|
|
28
|
+
AND parent.id <> sessions.id
|
|
29
|
+
)
|
|
30
|
+
`).run();
|
|
31
|
+
},
|
|
32
|
+
};
|
|
37
33
|
|
|
38
34
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
35
|
+
* Post-baseline database migrations.
|
|
36
|
+
*
|
|
37
|
+
* Pre-release migration history was consolidated into schema.sql. Future
|
|
38
|
+
* shipped schema changes should be added here as explicit migrations.
|
|
41
39
|
*
|
|
42
40
|
* @type {Array<{name: string, up: (db: import('better-sqlite3').Database) => void}>}
|
|
43
41
|
*/
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (!migration || typeof migration.up !== 'function') {
|
|
48
|
-
const name = migration?.name || 'unknown';
|
|
49
|
-
throw new Error(`Migration "${name}" is undefined or missing an up() function`);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return migrationsArray;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export const allMigrations = validateMigrations([
|
|
56
|
-
// --- Sessions initial columns ---
|
|
57
|
-
s.get('sessions-add-cost_usd'),
|
|
58
|
-
s.get('sessions-add-claude_session_id'),
|
|
59
|
-
s.get('sessions-add-model'),
|
|
60
|
-
s.get('sessions-add-provider_id-early'),
|
|
61
|
-
s.get('sessions-add-effort_level'),
|
|
62
|
-
|
|
63
|
-
// --- Projects columns ---
|
|
64
|
-
p.get('projects-add-system_prompt'),
|
|
65
|
-
p.get('projects-add-on_session_created'),
|
|
66
|
-
p.get('projects-add-on_session_deleted'),
|
|
67
|
-
p.get('projects-add-repo_url'),
|
|
68
|
-
p.get('projects-add-worktree_path'),
|
|
69
|
-
p.get('projects-drop-summary-columns'),
|
|
70
|
-
|
|
71
|
-
// --- Sessions scheduling columns ---
|
|
72
|
-
s.get('sessions-add-scheduled_at'),
|
|
73
|
-
s.get('sessions-add-reschedule_delay_minutes'),
|
|
74
|
-
s.get('sessions-add-auto_reschedule_enabled'),
|
|
75
|
-
s.get('sessions-add-reschedule_on_token_limit'),
|
|
76
|
-
s.get('sessions-add-reschedule_on_service_error'),
|
|
77
|
-
s.get('sessions-add-max_reschedule_count'),
|
|
78
|
-
s.get('sessions-add-max_total_tokens'),
|
|
79
|
-
s.get('sessions-add-reschedule_count'),
|
|
80
|
-
s.get('sessions-add-reschedule_at_token_count'),
|
|
81
|
-
|
|
82
|
-
// --- Sessions status constraint migration (table recreation) ---
|
|
83
|
-
s.get('sessions-migrate-status-constraint'),
|
|
84
|
-
|
|
85
|
-
// --- Session summaries PR columns ---
|
|
86
|
-
c.get('session_summaries-add-pr_merged'),
|
|
87
|
-
c.get('session_summaries-add-pr_state'),
|
|
88
|
-
c.get('session_summaries-add-has_merge_conflicts'),
|
|
89
|
-
c.get('session_summaries-add-ci_status'),
|
|
90
|
-
c.get('session_summaries-add-ci_failures'),
|
|
91
|
-
c.get('session_summaries-add-last_summarized_message_id'),
|
|
92
|
-
|
|
93
|
-
// --- Sessions template chaining ---
|
|
94
|
-
s.get('sessions-add-next_template_id'),
|
|
95
|
-
s.get('sessions-add-parent_session_id'),
|
|
96
|
-
s.get('sessions-template-chaining-indexes'),
|
|
97
|
-
|
|
98
|
-
// --- Message attachments ---
|
|
99
|
-
c.get('message_attachments-add-file_path'),
|
|
100
|
-
|
|
101
|
-
// --- Conversation messages: conversation_id ---
|
|
102
|
-
c.get('conversation_messages-add-conversation_id'),
|
|
103
|
-
|
|
104
|
-
// --- Migrate existing sessions to conversations ---
|
|
105
|
-
c.get('conversations-migrate-existing-sessions'),
|
|
106
|
-
|
|
107
|
-
// --- Canvas items ---
|
|
108
|
-
ci.get('canvas_items-migrate-type-constraint'),
|
|
109
|
-
ci.get('canvas_items-add-deleted_at'),
|
|
110
|
-
ci.get('canvas_items-drop-label'),
|
|
111
|
-
ci.get('canvas_items-add-updated_at'),
|
|
112
|
-
|
|
113
|
-
// --- Conversations: claude_session_id + token usage ---
|
|
114
|
-
c.get('conversations-add-claude_session_id'),
|
|
115
|
-
c.get('conversations-add-input_tokens'),
|
|
116
|
-
c.get('conversations-add-output_tokens'),
|
|
117
|
-
c.get('conversations-add-thinking_tokens'),
|
|
118
|
-
c.get('conversations-add-cache_read_input_tokens'),
|
|
119
|
-
c.get('conversations-add-cache_creation_input_tokens'),
|
|
120
|
-
c.get('conversations-add-web_search_requests'),
|
|
121
|
-
c.get('conversations-add-context_window'),
|
|
122
|
-
c.get('conversations-add-model'),
|
|
123
|
-
|
|
124
|
-
// --- Sessions token usage ---
|
|
125
|
-
s.get('sessions-add-input_tokens'),
|
|
126
|
-
s.get('sessions-add-output_tokens'),
|
|
127
|
-
s.get('sessions-add-thinking_tokens'),
|
|
128
|
-
s.get('sessions-add-cache_read_input_tokens'),
|
|
129
|
-
s.get('sessions-add-cache_creation_input_tokens'),
|
|
130
|
-
s.get('sessions-add-web_search_requests'),
|
|
131
|
-
s.get('sessions-add-context_window'),
|
|
132
|
-
|
|
133
|
-
// --- Sessions archived / starred / manually_named ---
|
|
134
|
-
s.get('sessions-add-archived'),
|
|
135
|
-
s.get('sessions-add-starred'),
|
|
136
|
-
s.get('sessions-add-manually_named'),
|
|
137
|
-
|
|
138
|
-
// --- Project session defaults table ---
|
|
139
|
-
p.get('project_session_defaults-create-table'),
|
|
140
|
-
|
|
141
|
-
// --- Command buttons ---
|
|
142
|
-
m.get('command_buttons-add-show_on_list'),
|
|
143
|
-
|
|
144
|
-
// --- Session todos ---
|
|
145
|
-
c.get('session_todos-add-conversation_id'),
|
|
146
|
-
|
|
147
|
-
// --- Conversation branching ---
|
|
148
|
-
c.get('conversations-add-parent_conversation_id'),
|
|
149
|
-
c.get('conversations-add-branch_from_message_id'),
|
|
150
|
-
|
|
151
|
-
// --- Sessions pending prompt / slash commands / pending model / auto send ---
|
|
152
|
-
s.get('sessions-add-pending_prompt'),
|
|
153
|
-
s.get('sessions-add-slash_commands'),
|
|
154
|
-
s.get('sessions-add-pending_model'),
|
|
155
|
-
s.get('sessions-add-auto_send_pending_prompt'),
|
|
156
|
-
|
|
157
|
-
// --- Session templates ---
|
|
158
|
-
m.get('session_templates-add-model'),
|
|
159
|
-
m.get('session_templates-add-mode'),
|
|
160
|
-
m.get('session_templates-add-effort_level'),
|
|
161
|
-
|
|
162
|
-
// --- Conversation messages model ---
|
|
163
|
-
c.get('conversation_messages-add-model'),
|
|
164
|
-
|
|
165
|
-
// --- App settings table ---
|
|
166
|
-
m.get('app_settings-create-table'),
|
|
167
|
-
|
|
168
|
-
// --- Legacy model_providers cleanup ---
|
|
169
|
-
m.get('model_providers-cleanup-legacy'),
|
|
170
|
-
|
|
171
|
-
// --- Providers + provider_models tables + seed ---
|
|
172
|
-
m.get('providers-create-tables'),
|
|
173
|
-
m.get('providers-add-kind'),
|
|
174
|
-
m.get('providers-seed-built-in'),
|
|
175
|
-
m.get('providers-seed-built-in-openai'),
|
|
176
|
-
|
|
177
|
-
// --- Sessions provider_id (from providers FK) ---
|
|
178
|
-
s.get('sessions-add-provider_id-from-providers'),
|
|
179
|
-
|
|
180
|
-
// --- Project session defaults provider_id / effort_level ---
|
|
181
|
-
p.get('project_session_defaults-add-provider_id'),
|
|
182
|
-
p.get('project_session_defaults-add-effort_level'),
|
|
183
|
-
|
|
184
|
-
// --- Update built-in models ---
|
|
185
|
-
m.get('providers-update-built-in-models'),
|
|
186
|
-
|
|
187
|
-
// --- Sessions agent_type ---
|
|
188
|
-
s.get('sessions-add-agent_type'),
|
|
189
|
-
|
|
190
|
-
// --- Agent call logs table ---
|
|
191
|
-
m.get('agent_call_logs-create-table'),
|
|
192
|
-
|
|
193
|
-
// --- Kanban feature ---
|
|
194
|
-
k.get('projects-add-kanban_enabled'),
|
|
195
|
-
k.get('kanban-create-tables'),
|
|
196
|
-
k.get('sessions-add-target_lane_id'),
|
|
197
|
-
k.get('sessions-add-lane_trigger_depth'),
|
|
198
|
-
k.get('session_templates-add-target_lane_id'),
|
|
199
|
-
k.get('kanban_lanes-add-on_enter_prompt'),
|
|
200
|
-
k.get('kanban_lanes-add-agent-settings'),
|
|
201
|
-
|
|
202
|
-
// --- Seed default global quick responses ---
|
|
203
|
-
m.get('quick_responses-seed-defaults'),
|
|
204
|
-
|
|
205
|
-
// --- Seed default global session templates ---
|
|
206
|
-
m.get('session_templates-seed-defaults'),
|
|
207
|
-
|
|
208
|
-
// --- Update built-in Opus model to 4.7 ---
|
|
209
|
-
m.get('providers-update-built-in-opus-4-7'),
|
|
210
|
-
]);
|
|
42
|
+
export const allMigrations = [
|
|
43
|
+
repairMissingSessionParentsFromWorktree,
|
|
44
|
+
];
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { OPENAI_MODELS } from '../../../shared/src/index.js';
|
|
3
|
+
|
|
4
|
+
export const BUILT_IN_ANTHROPIC_PROVIDER = {
|
|
5
|
+
id: 'anthropic-default',
|
|
6
|
+
name: 'Anthropic (Official)',
|
|
7
|
+
kind: 'anthropic',
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const BUILT_IN_OPENAI_PROVIDER = {
|
|
11
|
+
id: 'openai-default',
|
|
12
|
+
name: 'OpenAI (Official)',
|
|
13
|
+
kind: 'openai',
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const BUILT_IN_ANTHROPIC_MODELS = [
|
|
17
|
+
{ id: 'anthropic-haiku', providerId: BUILT_IN_ANTHROPIC_PROVIDER.id, modelId: 'claude-haiku-4-5-20251001', displayName: 'Haiku 4.5', description: 'Fast & lightweight', tier: 'haiku' },
|
|
18
|
+
{ id: 'anthropic-sonnet', providerId: BUILT_IN_ANTHROPIC_PROVIDER.id, modelId: 'claude-sonnet-4-6', displayName: 'Sonnet 4.6', description: 'Balanced', tier: 'sonnet' },
|
|
19
|
+
{ id: 'anthropic-opus', providerId: BUILT_IN_ANTHROPIC_PROVIDER.id, modelId: 'claude-opus-4-6', displayName: 'Opus 4.6', description: 'Previous generation', tier: 'opus' },
|
|
20
|
+
{ id: 'anthropic-opus-4-7', providerId: BUILT_IN_ANTHROPIC_PROVIDER.id, modelId: 'claude-opus-4-7', displayName: 'Opus 4.7', description: 'Most capable (default)', tier: 'opus' },
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
export const BUILT_IN_OPENAI_MODELS = OPENAI_MODELS.map((model) => ({
|
|
24
|
+
id: model.seedId,
|
|
25
|
+
providerId: BUILT_IN_OPENAI_PROVIDER.id,
|
|
26
|
+
modelId: model.id,
|
|
27
|
+
displayName: model.name,
|
|
28
|
+
description: model.description,
|
|
29
|
+
tier: 'custom',
|
|
30
|
+
}));
|
|
31
|
+
|
|
32
|
+
export const DEFAULT_QUICK_RESPONSES = [
|
|
33
|
+
{ label: 'Put a plan on the canvas', content: 'Put a plan on the canvas to get this done', autoSubmit: false, sortOrder: 0 },
|
|
34
|
+
{ label: 'Yes', content: 'Yes', autoSubmit: true, sortOrder: 1 },
|
|
35
|
+
{ label: 'Review the plan', content: `Review the plan on the canvas. Are there any issues that you can find? Is test coverage specified explicitly enough? Does the current code match the assumptions in the plan?\n\nList the issues that you find and then update the plan on the canvas to address any issues that you find. Don't talk about issues with the original plan in the plan itself. Just tell me what the issues are, and update the plan so that the plan doesn't have the issues.`, autoSubmit: true, sortOrder: 2 },
|
|
36
|
+
{ label: 'Implement the plan on the canvas', content: 'Implement the plan on the canvas', autoSubmit: true, sortOrder: 3 },
|
|
37
|
+
{ label: 'Create / Update PR', content: `Ensure all relevant changes are committed and pushed. Then look at the session's summary and create a draft PR if no PR already exists.`, autoSubmit: true, sortOrder: 4 },
|
|
38
|
+
{ label: 'Review PR', content: 'Look at the PR related to the root session. Review the PR. Are there any issues? Are best practices adhered to? Does the PR accomplish the goal? Are all changes covered by tests?', autoSubmit: true, sortOrder: 5 },
|
|
39
|
+
{ label: 'Add tests', content: 'Inspect the changes on our branch. For each change, ensure we have tests that assert the change is working in the expected way. Implement the tests.', autoSubmit: true, sortOrder: 6 },
|
|
40
|
+
{ label: 'Merge in main', content: 'Merge in the latest main branch', autoSubmit: true, sortOrder: 7 },
|
|
41
|
+
{ label: 'Add tests to the plan', content: 'Call out specific test cases in the plan, we should have an assertion for each change called for in the plan', autoSubmit: true, sortOrder: 8 },
|
|
42
|
+
{ label: 'Tests are failing', content: 'Tests are failing. Look at the canvas for details', autoSubmit: true, sortOrder: 9 },
|
|
43
|
+
{ label: 'Continue', content: 'Continue', autoSubmit: true, sortOrder: 10 },
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
export const DEFAULT_SESSION_TEMPLATE_PROMPTS = {
|
|
47
|
+
REVIEW: `Review the plan on the canvas. If there's more than one plan then review the most recently updated plan. if there are no plans on the canvas then look for the most recently updated plan on the root session canvas.
|
|
48
|
+
|
|
49
|
+
Make sure there are tests explicitly called out for all changes. Make sure that all context necessary to hand off the task is included in the plan.
|
|
50
|
+
|
|
51
|
+
Are there any gaps in the plan? Is test coverage spelled out explicitly? Does the code match the assumptions in the plan?
|
|
52
|
+
|
|
53
|
+
Update the plan according to your review recommendations.`,
|
|
54
|
+
IMPLEMENT: `Implement the plan on the canvas. If there's more than one plan on the canvas then use the most recently updated plan. If you don't see a plan on the canvas then look at the parent session's canvas.`,
|
|
55
|
+
PR: `Ensure all relevant changes are committed and pushed. Then determine the session's goals. You can typically find details about the goals of the session by looking at the most recently modified markdown documents on the root session's canvas - these are typically plans that were implemented during the session. You can also look at the root session's summary, but don't trigger a new summary to be created if the summary is missing.
|
|
56
|
+
|
|
57
|
+
Create a draft pr and ensure all changes are committed and pushed.`,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const DEFAULT_SESSION_TEMPLATES = [
|
|
61
|
+
{ name: 'Review the plan', prompt: DEFAULT_SESSION_TEMPLATE_PROMPTS.REVIEW },
|
|
62
|
+
{ name: 'Implement the plan on the canvas', prompt: DEFAULT_SESSION_TEMPLATE_PROMPTS.IMPLEMENT },
|
|
63
|
+
{ name: 'Create/update PR', prompt: DEFAULT_SESSION_TEMPLATE_PROMPTS.PR },
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
function seedBuiltInProviders(db) {
|
|
67
|
+
const now = Date.now();
|
|
68
|
+
|
|
69
|
+
db.prepare(
|
|
70
|
+
`INSERT OR IGNORE INTO providers (
|
|
71
|
+
id, name, base_url, auth_token, kind, is_built_in, created_at, updated_at
|
|
72
|
+
)
|
|
73
|
+
VALUES (?, ?, NULL, NULL, ?, 1, ?, ?)`
|
|
74
|
+
).run(BUILT_IN_ANTHROPIC_PROVIDER.id, BUILT_IN_ANTHROPIC_PROVIDER.name, BUILT_IN_ANTHROPIC_PROVIDER.kind, now, now);
|
|
75
|
+
|
|
76
|
+
db.prepare(
|
|
77
|
+
`INSERT OR IGNORE INTO providers (
|
|
78
|
+
id, name, base_url, auth_token, kind, is_built_in, created_at, updated_at
|
|
79
|
+
)
|
|
80
|
+
VALUES (?, ?, NULL, NULL, ?, 1, ?, ?)`
|
|
81
|
+
).run(BUILT_IN_OPENAI_PROVIDER.id, BUILT_IN_OPENAI_PROVIDER.name, BUILT_IN_OPENAI_PROVIDER.kind, now, now);
|
|
82
|
+
|
|
83
|
+
const insertModel = db.prepare(
|
|
84
|
+
`INSERT OR IGNORE INTO provider_models (
|
|
85
|
+
id, provider_id, model_id, display_name, description, tier, created_at
|
|
86
|
+
)
|
|
87
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
for (const model of [...BUILT_IN_ANTHROPIC_MODELS, ...BUILT_IN_OPENAI_MODELS]) {
|
|
91
|
+
insertModel.run(model.id, model.providerId, model.modelId, model.displayName, model.description, model.tier, now);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function seedDefaultQuickResponses(db) {
|
|
96
|
+
const count = db.prepare('SELECT COUNT(*) AS cnt FROM quick_responses').get().cnt;
|
|
97
|
+
if (count > 0) return;
|
|
98
|
+
|
|
99
|
+
const now = Date.now();
|
|
100
|
+
const stmt = db.prepare(
|
|
101
|
+
`INSERT INTO quick_responses (
|
|
102
|
+
id, project_id, label, content, auto_submit, category, sort_order, created_at, updated_at
|
|
103
|
+
)
|
|
104
|
+
VALUES (?, NULL, ?, ?, ?, NULL, ?, ?, ?)`
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
for (const item of DEFAULT_QUICK_RESPONSES) {
|
|
108
|
+
stmt.run(randomUUID(), item.label, item.content, item.autoSubmit ? 1 : 0, item.sortOrder, now, now);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function seedDefaultSessionTemplates(db) {
|
|
113
|
+
const count = db.prepare(
|
|
114
|
+
'SELECT COUNT(*) AS cnt FROM session_templates WHERE project_id IS NULL'
|
|
115
|
+
).get().cnt;
|
|
116
|
+
if (count > 0) return;
|
|
117
|
+
|
|
118
|
+
const now = Date.now();
|
|
119
|
+
const stmt = db.prepare(`
|
|
120
|
+
INSERT INTO session_templates (
|
|
121
|
+
id, project_id, name, prompt,
|
|
122
|
+
next_template_id, thinking_enabled,
|
|
123
|
+
git_branch, git_mode, model, mode, effort_level, target_lane_id,
|
|
124
|
+
created_at, updated_at
|
|
125
|
+
) VALUES (?, NULL, ?, ?, NULL, 1, NULL, NULL, NULL, 'yolo', NULL, NULL, ?, ?)
|
|
126
|
+
`);
|
|
127
|
+
|
|
128
|
+
for (const item of DEFAULT_SESSION_TEMPLATES) {
|
|
129
|
+
stmt.run(randomUUID(), item.name, item.prompt, now, now);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function seedBaselineData(db) {
|
|
134
|
+
seedBuiltInProviders(db);
|
|
135
|
+
seedDefaultQuickResponses(db);
|
|
136
|
+
seedDefaultSessionTemplates(db);
|
|
137
|
+
}
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* config parsing, and update-clause builders.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { DEFAULT_RESCHEDULE_DELAY_MINUTES } from '../../../shared/src/index.js';
|
|
7
|
+
|
|
6
8
|
/** Reusable SQL fragment for computed activity fields on sessions */
|
|
7
9
|
export const ACTIVITY_FIELDS_SQL = `
|
|
8
10
|
(SELECT MAX(cm.timestamp) FROM conversation_messages cm WHERE cm.session_id = s.id) AS last_activity_at,
|
|
@@ -40,7 +42,7 @@ export function mapTokenUsage(row) {
|
|
|
40
42
|
export function mapScheduling(row) {
|
|
41
43
|
return {
|
|
42
44
|
scheduledAt: row.scheduled_at || null,
|
|
43
|
-
rescheduleDelayMinutes: row.reschedule_delay_minutes ||
|
|
45
|
+
rescheduleDelayMinutes: row.reschedule_delay_minutes || DEFAULT_RESCHEDULE_DELAY_MINUTES,
|
|
44
46
|
autoRescheduleEnabled: Boolean(row.auto_reschedule_enabled),
|
|
45
47
|
rescheduleOnTokenLimit: Boolean(row.reschedule_on_token_limit),
|
|
46
48
|
rescheduleOnServiceError: Boolean(row.reschedule_on_service_error),
|
|
@@ -53,8 +55,8 @@ export function mapScheduling(row) {
|
|
|
53
55
|
|
|
54
56
|
/** Default values for session-create config fields */
|
|
55
57
|
const CONFIG_DEFAULTS = {
|
|
56
|
-
mode: '
|
|
57
|
-
thinkingEnabled:
|
|
58
|
+
mode: 'yolo',
|
|
59
|
+
thinkingEnabled: true,
|
|
58
60
|
gitBranch: null,
|
|
59
61
|
parentSessionId: null,
|
|
60
62
|
status: 'starting',
|
|
@@ -125,6 +127,7 @@ export const BOOLEAN_FIELD_MAP = {
|
|
|
125
127
|
archived: 'archived',
|
|
126
128
|
starred: 'starred',
|
|
127
129
|
manuallyNamed: 'manually_named',
|
|
130
|
+
prUrlAutoLinkDisabled: 'pr_url_auto_link_disabled',
|
|
128
131
|
autoRescheduleEnabled: 'auto_reschedule_enabled',
|
|
129
132
|
rescheduleOnTokenLimit: 'reschedule_on_token_limit',
|
|
130
133
|
rescheduleOnServiceError: 'reschedule_on_service_error',
|