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
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Each export is an array of { name, up(db) } migration objects.
|
|
4
4
|
*/
|
|
5
5
|
import { addColumnIfMissing, getColumns, getTableSql } from './migrationUtils.js';
|
|
6
|
+
import { migrateSessionsDefaultModeAndThinking } from './sessionTableRecreate.js';
|
|
6
7
|
|
|
7
8
|
// Table name constants for migrations
|
|
8
9
|
const TABLE_SESSIONS = 'sessions';
|
|
@@ -18,11 +19,12 @@ const SESSIONS_BASE_COLUMNS = `
|
|
|
18
19
|
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
19
20
|
name TEXT NOT NULL,
|
|
20
21
|
status TEXT NOT NULL DEFAULT 'starting' CHECK (status IN ('starting', 'running', 'waiting', 'stopped', 'completed', 'error', 'scheduled')),
|
|
21
|
-
mode TEXT NOT NULL DEFAULT '
|
|
22
|
-
thinking_enabled INTEGER NOT NULL DEFAULT
|
|
22
|
+
mode TEXT NOT NULL DEFAULT 'yolo' CHECK (mode IN ('plan', 'standard', 'yolo')),
|
|
23
|
+
thinking_enabled INTEGER NOT NULL DEFAULT 1,
|
|
23
24
|
git_branch TEXT,
|
|
24
25
|
git_worktree TEXT,
|
|
25
26
|
pr_url TEXT,
|
|
27
|
+
pr_url_auto_link_disabled INTEGER NOT NULL DEFAULT 0,
|
|
26
28
|
error TEXT,
|
|
27
29
|
effort_level TEXT CHECK(effort_level IN ('low', 'medium', 'high', 'max', 'auto')),
|
|
28
30
|
cost_usd REAL DEFAULT 0,
|
|
@@ -41,7 +43,7 @@ const SESSIONS_BASE_COLUMNS = `
|
|
|
41
43
|
starred INTEGER NOT NULL DEFAULT 0,
|
|
42
44
|
manually_named INTEGER NOT NULL DEFAULT 0,
|
|
43
45
|
scheduled_at INTEGER DEFAULT NULL,
|
|
44
|
-
reschedule_delay_minutes INTEGER DEFAULT
|
|
46
|
+
reschedule_delay_minutes INTEGER DEFAULT 60, -- keep in sync with DEFAULT_RESCHEDULE_DELAY_MINUTES in shared/constants.js
|
|
45
47
|
auto_reschedule_enabled INTEGER DEFAULT 0,
|
|
46
48
|
reschedule_on_token_limit INTEGER DEFAULT 1,
|
|
47
49
|
reschedule_on_service_error INTEGER DEFAULT 1,
|
|
@@ -58,7 +60,7 @@ const SESSIONS_BASE_COLUMNS = `
|
|
|
58
60
|
*/
|
|
59
61
|
const SESSIONS_ALL_COLUMNS = [
|
|
60
62
|
'id', 'project_id', 'name', 'status', 'mode', 'thinking_enabled',
|
|
61
|
-
'git_branch', 'git_worktree', 'pr_url', 'error', 'effort_level',
|
|
63
|
+
'git_branch', 'git_worktree', 'pr_url', 'pr_url_auto_link_disabled', 'error', 'effort_level',
|
|
62
64
|
'cost_usd', 'claude_session_id', 'model', 'next_template_id',
|
|
63
65
|
'parent_session_id', 'input_tokens', 'output_tokens', 'thinking_tokens',
|
|
64
66
|
'cache_read_input_tokens', 'cache_creation_input_tokens',
|
|
@@ -139,7 +141,7 @@ export const sessionsMigrations = [
|
|
|
139
141
|
},
|
|
140
142
|
{
|
|
141
143
|
name: 'sessions-add-reschedule_delay_minutes',
|
|
142
|
-
up(db) { addColumnIfMissing(db, TABLE_SESSIONS, 'reschedule_delay_minutes', 'INTEGER DEFAULT
|
|
144
|
+
up(db) { addColumnIfMissing(db, TABLE_SESSIONS, 'reschedule_delay_minutes', 'INTEGER DEFAULT 60'); /* keep in sync with DEFAULT_RESCHEDULE_DELAY_MINUTES */ },
|
|
143
145
|
},
|
|
144
146
|
{
|
|
145
147
|
name: 'sessions-add-auto_reschedule_enabled',
|
|
@@ -252,6 +254,10 @@ export const sessionsMigrations = [
|
|
|
252
254
|
name: 'sessions-add-manually_named',
|
|
253
255
|
up(db) { addColumnIfMissing(db, TABLE_SESSIONS, 'manually_named', 'INTEGER NOT NULL DEFAULT 0'); },
|
|
254
256
|
},
|
|
257
|
+
{
|
|
258
|
+
name: 'sessions-add-pr_url_auto_link_disabled',
|
|
259
|
+
up(db) { addColumnIfMissing(db, TABLE_SESSIONS, 'pr_url_auto_link_disabled', 'INTEGER NOT NULL DEFAULT 0'); },
|
|
260
|
+
},
|
|
255
261
|
|
|
256
262
|
// --- Pending prompt / slash commands / pending model / auto send ---
|
|
257
263
|
{
|
|
@@ -284,4 +290,11 @@ export const sessionsMigrations = [
|
|
|
284
290
|
name: 'sessions-add-agent_type',
|
|
285
291
|
up(db) { addColumnIfMissing(db, TABLE_SESSIONS, 'agent_type', "TEXT DEFAULT 'claude-code'"); },
|
|
286
292
|
},
|
|
293
|
+
|
|
294
|
+
// --- Default mode / thinking changes ---
|
|
295
|
+
{
|
|
296
|
+
name: 'sessions-migrate-default-mode-thinking',
|
|
297
|
+
up(db) { migrateSessionsDefaultModeAndThinking(db); },
|
|
298
|
+
},
|
|
299
|
+
|
|
287
300
|
];
|
|
@@ -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,9 +3,36 @@
|
|
|
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
|
+
(
|
|
11
|
+
SELECT MAX(activity_at)
|
|
12
|
+
FROM (
|
|
13
|
+
SELECT cm.timestamp AS activity_at
|
|
14
|
+
FROM conversation_messages cm
|
|
15
|
+
WHERE cm.session_id = s.id
|
|
16
|
+
UNION ALL
|
|
17
|
+
SELECT ss.generated_at AS activity_at
|
|
18
|
+
FROM session_summaries ss
|
|
19
|
+
WHERE ss.session_id = s.id
|
|
20
|
+
UNION ALL
|
|
21
|
+
SELECT ss.updated_at AS activity_at
|
|
22
|
+
FROM session_summaries ss
|
|
23
|
+
WHERE ss.session_id = s.id
|
|
24
|
+
UNION ALL
|
|
25
|
+
SELECT COALESCE(cr.completed_at, cr.started_at) AS activity_at
|
|
26
|
+
FROM command_runs cr
|
|
27
|
+
WHERE cr.session_id = s.id
|
|
28
|
+
)
|
|
29
|
+
WHERE activity_at IS NOT NULL
|
|
30
|
+
) AS last_activity_at,
|
|
31
|
+
(
|
|
32
|
+
SELECT MAX(cm.timestamp)
|
|
33
|
+
FROM conversation_messages cm
|
|
34
|
+
WHERE cm.session_id = s.id
|
|
35
|
+
) AS last_message_at,
|
|
9
36
|
(CAST(
|
|
10
37
|
CASE
|
|
11
38
|
WHEN (SELECT MAX(cm2.timestamp) FROM conversation_messages cm2 WHERE cm2.session_id = s.id) IS NOT NULL
|
|
@@ -40,7 +67,7 @@ export function mapTokenUsage(row) {
|
|
|
40
67
|
export function mapScheduling(row) {
|
|
41
68
|
return {
|
|
42
69
|
scheduledAt: row.scheduled_at || null,
|
|
43
|
-
rescheduleDelayMinutes: row.reschedule_delay_minutes ||
|
|
70
|
+
rescheduleDelayMinutes: row.reschedule_delay_minutes || DEFAULT_RESCHEDULE_DELAY_MINUTES,
|
|
44
71
|
autoRescheduleEnabled: Boolean(row.auto_reschedule_enabled),
|
|
45
72
|
rescheduleOnTokenLimit: Boolean(row.reschedule_on_token_limit),
|
|
46
73
|
rescheduleOnServiceError: Boolean(row.reschedule_on_service_error),
|
|
@@ -53,8 +80,8 @@ export function mapScheduling(row) {
|
|
|
53
80
|
|
|
54
81
|
/** Default values for session-create config fields */
|
|
55
82
|
const CONFIG_DEFAULTS = {
|
|
56
|
-
mode: '
|
|
57
|
-
thinkingEnabled:
|
|
83
|
+
mode: 'yolo',
|
|
84
|
+
thinkingEnabled: true,
|
|
58
85
|
gitBranch: null,
|
|
59
86
|
parentSessionId: null,
|
|
60
87
|
status: 'starting',
|
|
@@ -125,6 +152,7 @@ export const BOOLEAN_FIELD_MAP = {
|
|
|
125
152
|
archived: 'archived',
|
|
126
153
|
starred: 'starred',
|
|
127
154
|
manuallyNamed: 'manually_named',
|
|
155
|
+
prUrlAutoLinkDisabled: 'pr_url_auto_link_disabled',
|
|
128
156
|
autoRescheduleEnabled: 'auto_reschedule_enabled',
|
|
129
157
|
rescheduleOnTokenLimit: 'reschedule_on_token_limit',
|
|
130
158
|
rescheduleOnServiceError: 'reschedule_on_service_error',
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { sessions, projects } from '../database.js';
|
|
2
2
|
|
|
3
|
+
const SESSION_NOT_FOUND = 'Session not found';
|
|
4
|
+
const PROJECT_NOT_FOUND = 'Project not found';
|
|
5
|
+
const SESSION_NOT_IN_PROJECT = 'Session does not belong to this project';
|
|
6
|
+
|
|
3
7
|
/**
|
|
4
8
|
* Middleware: Look up a session by req.params.id and attach to req.session_.
|
|
5
9
|
* Returns 404 if session not found.
|
|
@@ -8,17 +12,12 @@ import { sessions, projects } from '../database.js';
|
|
|
8
12
|
export function requireSession(req, res, next) {
|
|
9
13
|
const session = sessions.getById(req.params.id);
|
|
10
14
|
if (!session) {
|
|
11
|
-
return res.status(404).json({ error:
|
|
15
|
+
return res.status(404).json({ error: SESSION_NOT_FOUND });
|
|
12
16
|
}
|
|
13
17
|
req.session_ = session;
|
|
14
18
|
next();
|
|
15
19
|
}
|
|
16
20
|
|
|
17
|
-
/**
|
|
18
|
-
* Middleware: Look up session AND its project. Attaches req.session_ and req.project.
|
|
19
|
-
* Returns 404 if either is not found.
|
|
20
|
-
* Also resolves req.workingDirectory (gitWorktree || project.workingDirectory).
|
|
21
|
-
*/
|
|
22
21
|
/**
|
|
23
22
|
* Middleware factory: Validates that req.session_.status is one of the allowed statuses.
|
|
24
23
|
* Must be used AFTER requireSession or requireSessionAndProject middleware.
|
|
@@ -39,15 +38,20 @@ export function requireSessionStatus(allowedStatuses, errorMessage) {
|
|
|
39
38
|
};
|
|
40
39
|
}
|
|
41
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Middleware: Look up session AND its project. Attaches req.session_ and req.project.
|
|
43
|
+
* Returns 404 if either is not found.
|
|
44
|
+
* Also resolves req.workingDirectory (gitWorktree || project.workingDirectory).
|
|
45
|
+
*/
|
|
42
46
|
export function requireSessionAndProject(req, res, next) {
|
|
43
47
|
const session = sessions.getById(req.params.id);
|
|
44
48
|
if (!session) {
|
|
45
|
-
return res.status(404).json({ error:
|
|
49
|
+
return res.status(404).json({ error: SESSION_NOT_FOUND });
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
const project = projects.getById(session.projectId);
|
|
49
53
|
if (!project) {
|
|
50
|
-
return res.status(404).json({ error:
|
|
54
|
+
return res.status(404).json({ error: PROJECT_NOT_FOUND });
|
|
51
55
|
}
|
|
52
56
|
|
|
53
57
|
req.session_ = session;
|
|
@@ -55,3 +59,72 @@ export function requireSessionAndProject(req, res, next) {
|
|
|
55
59
|
req.workingDirectory = session.gitWorktree || project.workingDirectory;
|
|
56
60
|
next();
|
|
57
61
|
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Middleware: Look up the provided session ID, then attach the workflow root
|
|
65
|
+
* session/project for resources shared across a session tree.
|
|
66
|
+
*/
|
|
67
|
+
export function requireRootSessionAndProject(req, res, next) {
|
|
68
|
+
const providedSession = sessions.getById(req.params.id);
|
|
69
|
+
if (!providedSession) {
|
|
70
|
+
return res.status(404).json({ error: SESSION_NOT_FOUND });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const rootSessionId = sessions.getRootSessionId(providedSession.id) || providedSession.id;
|
|
74
|
+
const rootSession = sessions.getById(rootSessionId);
|
|
75
|
+
if (!rootSession) {
|
|
76
|
+
return res.status(404).json({ error: SESSION_NOT_FOUND });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (providedSession.projectId !== rootSession.projectId) {
|
|
80
|
+
return res.status(400).json({ error: 'Session parent chain crosses projects' });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const rootProject = projects.getById(rootSession.projectId);
|
|
84
|
+
if (!rootProject) {
|
|
85
|
+
return res.status(404).json({ error: PROJECT_NOT_FOUND });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
req.providedSession_ = providedSession;
|
|
89
|
+
req.rootSession_ = rootSession;
|
|
90
|
+
req.rootSessionId = rootSessionId;
|
|
91
|
+
req.rootProject = rootProject;
|
|
92
|
+
req.rootWorkingDirectory = rootSession.gitWorktree || rootProject.workingDirectory;
|
|
93
|
+
next();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Middleware factory for project-scoped endpoints that receive a sessionId in
|
|
98
|
+
* the JSON body and should operate on that session tree's root.
|
|
99
|
+
*/
|
|
100
|
+
export function resolveBodyRootSessionForProject(projectParam = 'projectId') {
|
|
101
|
+
return (req, res, next) => {
|
|
102
|
+
const providedSessionId = req.body?.sessionId;
|
|
103
|
+
if (!providedSessionId) {
|
|
104
|
+
return res.status(400).json({ error: 'sessionId is required' });
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const providedSession = sessions.getById(providedSessionId);
|
|
108
|
+
if (!providedSession) {
|
|
109
|
+
return res.status(404).json({ error: SESSION_NOT_FOUND });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (providedSession.projectId !== req.params[projectParam]) {
|
|
113
|
+
return res.status(400).json({ error: SESSION_NOT_IN_PROJECT });
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const rootSessionId = sessions.getRootSessionId(providedSession.id) || providedSession.id;
|
|
117
|
+
const rootSession = sessions.getById(rootSessionId);
|
|
118
|
+
if (!rootSession) {
|
|
119
|
+
return res.status(404).json({ error: SESSION_NOT_FOUND });
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (rootSession.projectId !== req.params[projectParam]) {
|
|
123
|
+
return res.status(400).json({ error: SESSION_NOT_IN_PROJECT });
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
req.bodyRootSession_ = rootSession;
|
|
127
|
+
req.bodyRootSessionId = rootSessionId;
|
|
128
|
+
next();
|
|
129
|
+
};
|
|
130
|
+
}
|