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
|
@@ -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
|
+
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
-- Projects table
|
|
2
1
|
CREATE TABLE IF NOT EXISTS projects (
|
|
3
2
|
id TEXT PRIMARY KEY,
|
|
4
3
|
name TEXT NOT NULL,
|
|
@@ -6,14 +5,14 @@ CREATE TABLE IF NOT EXISTS projects (
|
|
|
6
5
|
system_prompt TEXT,
|
|
7
6
|
on_session_created TEXT,
|
|
8
7
|
on_session_deleted TEXT,
|
|
9
|
-
pr_poll_interval INTEGER NOT NULL DEFAULT 60000,
|
|
10
|
-
repo_url TEXT,
|
|
8
|
+
pr_poll_interval INTEGER NOT NULL DEFAULT 60000,
|
|
9
|
+
repo_url TEXT,
|
|
10
|
+
worktree_path TEXT,
|
|
11
|
+
kanban_enabled INTEGER NOT NULL DEFAULT 1,
|
|
11
12
|
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
12
13
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
13
14
|
);
|
|
14
15
|
|
|
15
|
-
-- Session templates (reusable prompts that can chain sessions)
|
|
16
|
-
-- Must be created before sessions due to foreign key reference
|
|
17
16
|
CREATE TABLE IF NOT EXISTS session_templates (
|
|
18
17
|
id TEXT PRIMARY KEY,
|
|
19
18
|
project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
|
|
@@ -26,26 +25,53 @@ CREATE TABLE IF NOT EXISTS session_templates (
|
|
|
26
25
|
model TEXT,
|
|
27
26
|
mode TEXT DEFAULT 'yolo' CHECK(mode IN ('plan', 'standard', 'yolo')),
|
|
28
27
|
effort_level TEXT CHECK(effort_level IN ('low', 'medium', 'high', 'max', 'auto')),
|
|
28
|
+
target_lane_id TEXT REFERENCES kanban_lanes(id) ON DELETE SET NULL,
|
|
29
29
|
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
30
30
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
31
31
|
);
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
CREATE TABLE IF NOT EXISTS providers (
|
|
34
|
+
id TEXT PRIMARY KEY,
|
|
35
|
+
name TEXT NOT NULL,
|
|
36
|
+
base_url TEXT,
|
|
37
|
+
auth_token TEXT,
|
|
38
|
+
api_timeout_ms INTEGER,
|
|
39
|
+
additional_env_vars TEXT,
|
|
40
|
+
commit_attribution_override TEXT,
|
|
41
|
+
is_built_in INTEGER NOT NULL DEFAULT 0,
|
|
42
|
+
kind TEXT NOT NULL DEFAULT 'anthropic' CHECK(kind IN ('anthropic','openai')),
|
|
43
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
44
|
+
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
CREATE TABLE IF NOT EXISTS provider_models (
|
|
48
|
+
id TEXT PRIMARY KEY,
|
|
49
|
+
provider_id TEXT NOT NULL REFERENCES providers(id) ON DELETE CASCADE,
|
|
50
|
+
model_id TEXT NOT NULL,
|
|
51
|
+
display_name TEXT NOT NULL,
|
|
52
|
+
description TEXT,
|
|
53
|
+
tier TEXT CHECK(tier IN ('opus', 'sonnet', 'haiku', 'custom')),
|
|
54
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
55
|
+
);
|
|
56
|
+
|
|
34
57
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
35
58
|
id TEXT PRIMARY KEY,
|
|
36
59
|
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
37
60
|
name TEXT NOT NULL,
|
|
38
61
|
status TEXT NOT NULL DEFAULT 'starting' CHECK (status IN ('starting', 'running', 'waiting', 'stopped', 'completed', 'error', 'scheduled')),
|
|
39
|
-
mode TEXT NOT NULL DEFAULT '
|
|
40
|
-
thinking_enabled INTEGER NOT NULL DEFAULT
|
|
62
|
+
mode TEXT NOT NULL DEFAULT 'yolo' CHECK (mode IN ('plan', 'standard', 'yolo')),
|
|
63
|
+
thinking_enabled INTEGER NOT NULL DEFAULT 1,
|
|
41
64
|
archived INTEGER NOT NULL DEFAULT 0,
|
|
42
65
|
git_branch TEXT,
|
|
43
66
|
git_worktree TEXT,
|
|
44
67
|
pr_url TEXT,
|
|
68
|
+
pr_url_auto_link_disabled INTEGER NOT NULL DEFAULT 0,
|
|
45
69
|
error TEXT,
|
|
46
70
|
effort_level TEXT CHECK(effort_level IN ('low', 'medium', 'high', 'max', 'auto')),
|
|
47
71
|
cost_usd REAL DEFAULT 0,
|
|
48
72
|
claude_session_id TEXT,
|
|
73
|
+
model TEXT,
|
|
74
|
+
provider_id TEXT REFERENCES providers(id),
|
|
49
75
|
next_template_id TEXT REFERENCES session_templates(id) ON DELETE SET NULL,
|
|
50
76
|
parent_session_id TEXT REFERENCES sessions(id) ON DELETE SET NULL,
|
|
51
77
|
input_tokens INTEGER DEFAULT 0,
|
|
@@ -55,20 +81,36 @@ CREATE TABLE IF NOT EXISTS sessions (
|
|
|
55
81
|
cache_creation_input_tokens INTEGER DEFAULT 0,
|
|
56
82
|
web_search_requests INTEGER DEFAULT 0,
|
|
57
83
|
context_window INTEGER DEFAULT 200000,
|
|
84
|
+
starred INTEGER NOT NULL DEFAULT 0,
|
|
85
|
+
manually_named INTEGER NOT NULL DEFAULT 0,
|
|
86
|
+
scheduled_at INTEGER DEFAULT NULL,
|
|
87
|
+
reschedule_delay_minutes INTEGER DEFAULT 60,
|
|
88
|
+
auto_reschedule_enabled INTEGER DEFAULT 0,
|
|
89
|
+
reschedule_on_token_limit INTEGER DEFAULT 1,
|
|
90
|
+
reschedule_on_service_error INTEGER DEFAULT 1,
|
|
91
|
+
max_reschedule_count INTEGER DEFAULT NULL,
|
|
92
|
+
max_total_tokens INTEGER DEFAULT NULL,
|
|
93
|
+
reschedule_count INTEGER DEFAULT 0,
|
|
94
|
+
reschedule_at_token_count INTEGER DEFAULT NULL,
|
|
95
|
+
pending_prompt TEXT,
|
|
96
|
+
slash_commands TEXT,
|
|
97
|
+
pending_model TEXT,
|
|
98
|
+
auto_send_pending_prompt INTEGER DEFAULT 0,
|
|
99
|
+
agent_type TEXT DEFAULT 'claude-code',
|
|
100
|
+
target_lane_id TEXT REFERENCES kanban_lanes(id) ON DELETE SET NULL,
|
|
101
|
+
lane_trigger_depth INTEGER NOT NULL DEFAULT 0,
|
|
58
102
|
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
59
103
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
60
104
|
);
|
|
61
105
|
|
|
62
|
-
-- Conversations (multiple conversation threads per session)
|
|
63
106
|
CREATE TABLE IF NOT EXISTS conversations (
|
|
64
107
|
id TEXT PRIMARY KEY,
|
|
65
108
|
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
66
|
-
name TEXT,
|
|
67
|
-
summary TEXT,
|
|
68
|
-
summary_generated_at INTEGER,
|
|
69
|
-
is_active INTEGER NOT NULL DEFAULT 0,
|
|
70
|
-
claude_session_id TEXT,
|
|
71
|
-
-- Token usage fields (per-conversation tracking)
|
|
109
|
+
name TEXT,
|
|
110
|
+
summary TEXT,
|
|
111
|
+
summary_generated_at INTEGER,
|
|
112
|
+
is_active INTEGER NOT NULL DEFAULT 0,
|
|
113
|
+
claude_session_id TEXT,
|
|
72
114
|
input_tokens INTEGER DEFAULT 0,
|
|
73
115
|
output_tokens INTEGER DEFAULT 0,
|
|
74
116
|
thinking_tokens INTEGER DEFAULT 0,
|
|
@@ -76,48 +118,39 @@ CREATE TABLE IF NOT EXISTS conversations (
|
|
|
76
118
|
cache_creation_input_tokens INTEGER DEFAULT 0,
|
|
77
119
|
web_search_requests INTEGER DEFAULT 0,
|
|
78
120
|
context_window INTEGER DEFAULT 200000,
|
|
121
|
+
model TEXT,
|
|
122
|
+
parent_conversation_id TEXT REFERENCES conversations(id) ON DELETE SET NULL,
|
|
123
|
+
branch_from_message_id TEXT REFERENCES conversation_messages(id) ON DELETE SET NULL,
|
|
79
124
|
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
80
125
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
81
126
|
);
|
|
82
127
|
|
|
83
|
-
-- Conversation messages
|
|
84
128
|
CREATE TABLE IF NOT EXISTS conversation_messages (
|
|
85
129
|
id TEXT PRIMARY KEY,
|
|
86
130
|
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
87
131
|
conversation_id TEXT REFERENCES conversations(id) ON DELETE CASCADE,
|
|
88
132
|
role TEXT NOT NULL CHECK (role IN ('user', 'assistant', 'system')),
|
|
89
133
|
content TEXT NOT NULL,
|
|
90
|
-
tool_use TEXT,
|
|
91
|
-
model TEXT,
|
|
134
|
+
tool_use TEXT,
|
|
135
|
+
model TEXT,
|
|
92
136
|
timestamp INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
93
137
|
);
|
|
94
138
|
|
|
95
|
-
-- Canvas items
|
|
96
139
|
CREATE TABLE IF NOT EXISTS canvas_items (
|
|
97
140
|
id TEXT PRIMARY KEY,
|
|
98
141
|
session_id TEXT REFERENCES sessions(id) ON DELETE CASCADE,
|
|
99
142
|
type TEXT NOT NULL CHECK (type IN ('image', 'markdown', 'text', 'json', 'pdf', 'code')),
|
|
100
|
-
content TEXT,
|
|
101
|
-
data TEXT,
|
|
102
|
-
mime_type TEXT,
|
|
143
|
+
content TEXT,
|
|
144
|
+
data TEXT,
|
|
145
|
+
mime_type TEXT,
|
|
103
146
|
filename TEXT,
|
|
104
147
|
width INTEGER,
|
|
105
148
|
height INTEGER,
|
|
106
|
-
deleted_at INTEGER,
|
|
107
|
-
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
108
|
-
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
109
|
-
);
|
|
110
|
-
|
|
111
|
-
-- Session notes
|
|
112
|
-
CREATE TABLE IF NOT EXISTS session_notes (
|
|
113
|
-
id TEXT PRIMARY KEY,
|
|
114
|
-
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
115
|
-
content TEXT NOT NULL,
|
|
149
|
+
deleted_at INTEGER,
|
|
116
150
|
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
117
|
-
updated_at INTEGER
|
|
151
|
+
updated_at INTEGER
|
|
118
152
|
);
|
|
119
153
|
|
|
120
|
-
-- Global tool templates
|
|
121
154
|
CREATE TABLE IF NOT EXISTS global_tool_templates (
|
|
122
155
|
id TEXT PRIMARY KEY,
|
|
123
156
|
name TEXT NOT NULL,
|
|
@@ -127,7 +160,6 @@ CREATE TABLE IF NOT EXISTS global_tool_templates (
|
|
|
127
160
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
128
161
|
);
|
|
129
162
|
|
|
130
|
-
-- Project tool templates
|
|
131
163
|
CREATE TABLE IF NOT EXISTS project_tool_templates (
|
|
132
164
|
id TEXT PRIMARY KEY,
|
|
133
165
|
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
@@ -138,50 +170,46 @@ CREATE TABLE IF NOT EXISTS project_tool_templates (
|
|
|
138
170
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
139
171
|
);
|
|
140
172
|
|
|
141
|
-
-- Session todos (Claude's task list, scoped to conversations)
|
|
142
173
|
CREATE TABLE IF NOT EXISTS session_todos (
|
|
143
174
|
id TEXT PRIMARY KEY,
|
|
144
175
|
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
145
176
|
conversation_id TEXT REFERENCES conversations(id) ON DELETE CASCADE,
|
|
146
177
|
content TEXT NOT NULL,
|
|
147
|
-
status TEXT NOT NULL DEFAULT 'pending'
|
|
148
|
-
CHECK (status IN ('pending', 'in_progress', 'completed')),
|
|
178
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'in_progress', 'completed')),
|
|
149
179
|
position INTEGER NOT NULL,
|
|
150
180
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
151
181
|
);
|
|
152
182
|
|
|
153
|
-
-- Work logs (thinking, command outputs, tool executions)
|
|
154
183
|
CREATE TABLE IF NOT EXISTS work_logs (
|
|
155
184
|
id TEXT PRIMARY KEY,
|
|
156
185
|
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
157
186
|
message_id TEXT REFERENCES conversation_messages(id) ON DELETE CASCADE,
|
|
158
187
|
type TEXT NOT NULL CHECK (type IN ('thinking', 'tool_input', 'tool_output')),
|
|
159
|
-
tool_name TEXT,
|
|
160
|
-
content TEXT NOT NULL,
|
|
188
|
+
tool_name TEXT,
|
|
189
|
+
content TEXT NOT NULL,
|
|
161
190
|
timestamp INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
162
191
|
);
|
|
163
192
|
|
|
164
|
-
-- Session summaries (AI-generated)
|
|
165
193
|
CREATE TABLE IF NOT EXISTS session_summaries (
|
|
166
194
|
id TEXT PRIMARY KEY,
|
|
167
195
|
session_id TEXT NOT NULL UNIQUE REFERENCES sessions(id) ON DELETE CASCADE,
|
|
168
|
-
short_summary TEXT NOT NULL,
|
|
169
|
-
full_summary TEXT NOT NULL,
|
|
170
|
-
key_actions TEXT,
|
|
171
|
-
files_modified TEXT,
|
|
172
|
-
outcome TEXT,
|
|
173
|
-
message_count INTEGER,
|
|
174
|
-
pr_merged INTEGER,
|
|
175
|
-
pr_state TEXT,
|
|
176
|
-
has_merge_conflicts INTEGER,
|
|
177
|
-
ci_status TEXT,
|
|
178
|
-
ci_failures TEXT,
|
|
196
|
+
short_summary TEXT NOT NULL,
|
|
197
|
+
full_summary TEXT NOT NULL,
|
|
198
|
+
key_actions TEXT,
|
|
199
|
+
files_modified TEXT,
|
|
200
|
+
outcome TEXT,
|
|
201
|
+
message_count INTEGER,
|
|
202
|
+
pr_merged INTEGER,
|
|
203
|
+
pr_state TEXT,
|
|
204
|
+
has_merge_conflicts INTEGER,
|
|
205
|
+
ci_status TEXT,
|
|
206
|
+
ci_failures TEXT,
|
|
207
|
+
last_summarized_message_id TEXT,
|
|
179
208
|
generated_at INTEGER NOT NULL,
|
|
180
209
|
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
181
210
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
182
211
|
);
|
|
183
212
|
|
|
184
|
-
-- Message attachments (files attached to user messages)
|
|
185
213
|
CREATE TABLE IF NOT EXISTS message_attachments (
|
|
186
214
|
id TEXT PRIMARY KEY,
|
|
187
215
|
message_id TEXT REFERENCES conversation_messages(id) ON DELETE CASCADE,
|
|
@@ -190,12 +218,11 @@ CREATE TABLE IF NOT EXISTS message_attachments (
|
|
|
190
218
|
mime_type TEXT NOT NULL,
|
|
191
219
|
size_bytes INTEGER NOT NULL,
|
|
192
220
|
storage_type TEXT NOT NULL DEFAULT 'base64' CHECK (storage_type IN ('base64', 'file_path', 'project_file')),
|
|
193
|
-
content TEXT,
|
|
194
|
-
file_path TEXT,
|
|
221
|
+
content TEXT,
|
|
222
|
+
file_path TEXT,
|
|
195
223
|
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
196
224
|
);
|
|
197
225
|
|
|
198
|
-
-- Command buttons (configurable buttons per project)
|
|
199
226
|
CREATE TABLE IF NOT EXISTS command_buttons (
|
|
200
227
|
id TEXT PRIMARY KEY,
|
|
201
228
|
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
@@ -207,7 +234,6 @@ CREATE TABLE IF NOT EXISTS command_buttons (
|
|
|
207
234
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
208
235
|
);
|
|
209
236
|
|
|
210
|
-
-- Command runs (execution history for command buttons)
|
|
211
237
|
CREATE TABLE IF NOT EXISTS command_runs (
|
|
212
238
|
id TEXT PRIMARY KEY,
|
|
213
239
|
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
@@ -219,7 +245,6 @@ CREATE TABLE IF NOT EXISTS command_runs (
|
|
|
219
245
|
completed_at INTEGER
|
|
220
246
|
);
|
|
221
247
|
|
|
222
|
-
-- Quick responses (reusable messages for conversation)
|
|
223
248
|
CREATE TABLE IF NOT EXISTS quick_responses (
|
|
224
249
|
id TEXT PRIMARY KEY,
|
|
225
250
|
project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
|
|
@@ -232,102 +257,51 @@ CREATE TABLE IF NOT EXISTS quick_responses (
|
|
|
232
257
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
233
258
|
);
|
|
234
259
|
|
|
235
|
-
|
|
236
|
-
CREATE TABLE IF NOT EXISTS providers (
|
|
260
|
+
CREATE TABLE IF NOT EXISTS project_session_defaults (
|
|
237
261
|
id TEXT PRIMARY KEY,
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
262
|
+
project_id TEXT NOT NULL UNIQUE,
|
|
263
|
+
mode TEXT CHECK(mode IN ('plan', 'standard', 'yolo')),
|
|
264
|
+
thinking_enabled INTEGER,
|
|
265
|
+
start_immediately INTEGER,
|
|
266
|
+
git_mode TEXT CHECK(git_mode IN ('branch', 'worktree', 'current')),
|
|
267
|
+
git_branch TEXT,
|
|
268
|
+
model TEXT,
|
|
269
|
+
provider_id TEXT REFERENCES providers(id),
|
|
270
|
+
effort_level TEXT CHECK(effort_level IN ('low', 'medium', 'high', 'max', 'auto')),
|
|
271
|
+
created_at INTEGER NOT NULL,
|
|
272
|
+
updated_at INTEGER NOT NULL,
|
|
273
|
+
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
|
|
247
274
|
);
|
|
248
275
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
model_id TEXT NOT NULL,
|
|
254
|
-
display_name TEXT NOT NULL,
|
|
255
|
-
description TEXT,
|
|
256
|
-
tier TEXT CHECK(tier IN ('opus', 'sonnet', 'haiku', 'custom')),
|
|
257
|
-
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
276
|
+
CREATE TABLE IF NOT EXISTS app_settings (
|
|
277
|
+
key TEXT PRIMARY KEY,
|
|
278
|
+
value TEXT NOT NULL,
|
|
279
|
+
updated_at INTEGER NOT NULL
|
|
258
280
|
);
|
|
259
281
|
|
|
260
|
-
-- Indexes
|
|
261
|
-
CREATE INDEX IF NOT EXISTS idx_sessions_project ON sessions(project_id);
|
|
262
|
-
CREATE INDEX IF NOT EXISTS idx_sessions_status ON sessions(status);
|
|
263
|
-
CREATE INDEX IF NOT EXISTS idx_sessions_archived ON sessions(archived);
|
|
264
|
-
CREATE INDEX IF NOT EXISTS idx_conversations_session ON conversations(session_id);
|
|
265
|
-
CREATE INDEX IF NOT EXISTS idx_messages_session ON conversation_messages(session_id);
|
|
266
|
-
-- Note: idx_messages_conversation is created in migrations to handle existing databases
|
|
267
|
-
-- that may not have the conversation_id column yet
|
|
268
|
-
CREATE INDEX IF NOT EXISTS idx_canvas_session ON canvas_items(session_id);
|
|
269
|
-
-- Note: idx_canvas_deleted is created in migrations to handle existing databases
|
|
270
|
-
-- that may not have the deleted_at column yet
|
|
271
|
-
CREATE INDEX IF NOT EXISTS idx_notes_session ON session_notes(session_id);
|
|
272
|
-
CREATE INDEX IF NOT EXISTS idx_project_tools ON project_tool_templates(project_id);
|
|
273
|
-
CREATE INDEX IF NOT EXISTS idx_session_templates_project ON session_templates(project_id);
|
|
274
|
-
-- Note: idx_sessions_next_template and idx_sessions_parent are created in migrations
|
|
275
|
-
-- to handle existing databases that may not have these columns yet
|
|
276
|
-
CREATE INDEX IF NOT EXISTS idx_todos_session ON session_todos(session_id);
|
|
277
|
-
-- Note: idx_todos_conversation is created in migrations to handle existing databases
|
|
278
|
-
-- that may not have the conversation_id column yet
|
|
279
|
-
CREATE INDEX IF NOT EXISTS idx_work_logs_session ON work_logs(session_id);
|
|
280
|
-
CREATE INDEX IF NOT EXISTS idx_work_logs_message ON work_logs(message_id);
|
|
281
|
-
CREATE INDEX IF NOT EXISTS idx_summaries_session ON session_summaries(session_id);
|
|
282
|
-
CREATE INDEX IF NOT EXISTS idx_attachments_message ON message_attachments(message_id);
|
|
283
|
-
CREATE INDEX IF NOT EXISTS idx_attachments_session ON message_attachments(session_id);
|
|
284
|
-
CREATE INDEX IF NOT EXISTS idx_command_buttons_project ON command_buttons(project_id);
|
|
285
|
-
CREATE INDEX IF NOT EXISTS idx_command_runs_session ON command_runs(session_id);
|
|
286
|
-
CREATE INDEX IF NOT EXISTS idx_command_runs_button ON command_runs(button_id);
|
|
287
|
-
CREATE INDEX IF NOT EXISTS idx_command_runs_status ON command_runs(status);
|
|
288
|
-
CREATE INDEX IF NOT EXISTS idx_quick_responses_project ON quick_responses(project_id);
|
|
289
|
-
CREATE INDEX IF NOT EXISTS idx_quick_responses_sort ON quick_responses(project_id, sort_order);
|
|
290
|
-
CREATE INDEX IF NOT EXISTS idx_provider_models_provider ON provider_models(provider_id);
|
|
291
|
-
|
|
292
|
-
-- Agent call logs (metrics and analytics for agent interactions)
|
|
293
282
|
CREATE TABLE IF NOT EXISTS agent_call_logs (
|
|
294
283
|
id TEXT PRIMARY KEY,
|
|
295
284
|
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
296
285
|
conversation_id TEXT,
|
|
297
286
|
agent_type TEXT NOT NULL,
|
|
298
287
|
model TEXT,
|
|
299
|
-
|
|
300
|
-
-- Request info
|
|
301
|
-
call_type TEXT NOT NULL, -- 'runSession' | 'continueSession' | 'continueSessionWithExistingMessage'
|
|
288
|
+
call_type TEXT NOT NULL,
|
|
302
289
|
prompt_length INTEGER,
|
|
303
|
-
|
|
304
|
-
-- Response token info (updated during streaming and finalized at result)
|
|
305
290
|
input_tokens INTEGER DEFAULT 0,
|
|
306
291
|
output_tokens INTEGER DEFAULT 0,
|
|
307
292
|
thinking_tokens INTEGER DEFAULT 0,
|
|
308
293
|
cache_read_tokens INTEGER DEFAULT 0,
|
|
309
294
|
cache_write_tokens INTEGER DEFAULT 0,
|
|
310
295
|
total_tokens INTEGER DEFAULT 0,
|
|
311
|
-
|
|
312
|
-
-- Timing
|
|
313
296
|
started_at INTEGER NOT NULL,
|
|
314
297
|
completed_at INTEGER,
|
|
315
298
|
duration_ms INTEGER,
|
|
316
|
-
|
|
317
|
-
-- Status
|
|
318
299
|
status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending', 'streaming', 'completed', 'error')),
|
|
319
300
|
error_message TEXT,
|
|
320
|
-
|
|
321
|
-
-- Metadata (JSON blob for extensibility)
|
|
322
301
|
metadata TEXT,
|
|
323
|
-
|
|
324
302
|
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
325
303
|
);
|
|
326
304
|
|
|
327
|
-
CREATE INDEX IF NOT EXISTS idx_agent_call_logs_session ON agent_call_logs(session_id);
|
|
328
|
-
CREATE INDEX IF NOT EXISTS idx_agent_call_logs_started ON agent_call_logs(started_at);
|
|
329
|
-
|
|
330
|
-
-- Kanban boards (one per project)
|
|
331
305
|
CREATE TABLE IF NOT EXISTS kanban_boards (
|
|
332
306
|
id TEXT PRIMARY KEY,
|
|
333
307
|
project_id TEXT NOT NULL UNIQUE REFERENCES projects(id) ON DELETE CASCADE,
|
|
@@ -335,7 +309,6 @@ CREATE TABLE IF NOT EXISTS kanban_boards (
|
|
|
335
309
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
336
310
|
);
|
|
337
311
|
|
|
338
|
-
-- Kanban lanes (columns on the board)
|
|
339
312
|
CREATE TABLE IF NOT EXISTS kanban_lanes (
|
|
340
313
|
id TEXT PRIMARY KEY,
|
|
341
314
|
board_id TEXT NOT NULL REFERENCES kanban_boards(id) ON DELETE CASCADE,
|
|
@@ -343,11 +316,21 @@ CREATE TABLE IF NOT EXISTS kanban_lanes (
|
|
|
343
316
|
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
344
317
|
on_enter_template_id TEXT REFERENCES session_templates(id) ON DELETE SET NULL,
|
|
345
318
|
on_enter_prompt TEXT,
|
|
319
|
+
on_enter_mode TEXT,
|
|
320
|
+
on_enter_model TEXT,
|
|
321
|
+
on_enter_effort_level TEXT,
|
|
322
|
+
on_enter_thinking_enabled INTEGER,
|
|
323
|
+
on_enter_auto_reschedule_enabled INTEGER DEFAULT 0,
|
|
324
|
+
on_enter_reschedule_delay_minutes INTEGER DEFAULT 60,
|
|
325
|
+
on_enter_reschedule_on_token_limit INTEGER DEFAULT 1,
|
|
326
|
+
on_enter_reschedule_on_service_error INTEGER DEFAULT 1,
|
|
327
|
+
on_enter_max_reschedule_count INTEGER,
|
|
328
|
+
on_enter_max_total_tokens INTEGER,
|
|
329
|
+
on_enter_reschedule_at_token_count INTEGER,
|
|
346
330
|
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
347
331
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
348
332
|
);
|
|
349
333
|
|
|
350
|
-
-- Kanban cards (entries on the board, separate from sessions for future flexibility)
|
|
351
334
|
CREATE TABLE IF NOT EXISTS kanban_cards (
|
|
352
335
|
id TEXT PRIMARY KEY,
|
|
353
336
|
lane_id TEXT NOT NULL REFERENCES kanban_lanes(id) ON DELETE CASCADE,
|
|
@@ -356,7 +339,6 @@ CREATE TABLE IF NOT EXISTS kanban_cards (
|
|
|
356
339
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
357
340
|
);
|
|
358
341
|
|
|
359
|
-
-- Kanban card sessions (links cards to sessions, currently 1:1 but allows future N:1)
|
|
360
342
|
CREATE TABLE IF NOT EXISTS kanban_card_sessions (
|
|
361
343
|
id TEXT PRIMARY KEY,
|
|
362
344
|
card_id TEXT NOT NULL REFERENCES kanban_cards(id) ON DELETE CASCADE,
|
|
@@ -364,7 +346,42 @@ CREATE TABLE IF NOT EXISTS kanban_card_sessions (
|
|
|
364
346
|
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
365
347
|
);
|
|
366
348
|
|
|
367
|
-
|
|
349
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_project ON sessions(project_id);
|
|
350
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_status ON sessions(status);
|
|
351
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_archived ON sessions(archived);
|
|
352
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_starred ON sessions(archived, starred);
|
|
353
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_next_template ON sessions(next_template_id);
|
|
354
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_parent ON sessions(parent_session_id);
|
|
355
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_scheduled ON sessions(scheduled_at) WHERE scheduled_at IS NOT NULL;
|
|
356
|
+
CREATE INDEX IF NOT EXISTS idx_conversations_session ON conversations(session_id);
|
|
357
|
+
CREATE INDEX IF NOT EXISTS idx_conversations_parent ON conversations(parent_conversation_id);
|
|
358
|
+
CREATE INDEX IF NOT EXISTS idx_messages_session ON conversation_messages(session_id);
|
|
359
|
+
CREATE INDEX IF NOT EXISTS idx_messages_conversation ON conversation_messages(conversation_id);
|
|
360
|
+
CREATE INDEX IF NOT EXISTS idx_canvas_session ON canvas_items(session_id);
|
|
361
|
+
CREATE INDEX IF NOT EXISTS idx_canvas_deleted ON canvas_items(deleted_at);
|
|
362
|
+
CREATE INDEX IF NOT EXISTS idx_project_tools ON project_tool_templates(project_id);
|
|
363
|
+
CREATE INDEX IF NOT EXISTS idx_session_templates_project ON session_templates(project_id);
|
|
364
|
+
CREATE INDEX IF NOT EXISTS idx_todos_session ON session_todos(session_id);
|
|
365
|
+
CREATE INDEX IF NOT EXISTS idx_todos_conversation ON session_todos(conversation_id);
|
|
366
|
+
CREATE INDEX IF NOT EXISTS idx_work_logs_session ON work_logs(session_id);
|
|
367
|
+
CREATE INDEX IF NOT EXISTS idx_work_logs_message ON work_logs(message_id);
|
|
368
|
+
CREATE INDEX IF NOT EXISTS idx_summaries_session ON session_summaries(session_id);
|
|
369
|
+
CREATE INDEX IF NOT EXISTS idx_attachments_message ON message_attachments(message_id);
|
|
370
|
+
CREATE INDEX IF NOT EXISTS idx_attachments_session ON message_attachments(session_id);
|
|
371
|
+
CREATE INDEX IF NOT EXISTS idx_command_buttons_project ON command_buttons(project_id);
|
|
372
|
+
CREATE INDEX IF NOT EXISTS idx_command_runs_session ON command_runs(session_id);
|
|
373
|
+
CREATE INDEX IF NOT EXISTS idx_command_runs_button ON command_runs(button_id);
|
|
374
|
+
CREATE INDEX IF NOT EXISTS idx_command_runs_status ON command_runs(status);
|
|
375
|
+
CREATE INDEX IF NOT EXISTS idx_quick_responses_project ON quick_responses(project_id);
|
|
376
|
+
CREATE INDEX IF NOT EXISTS idx_quick_responses_sort ON quick_responses(project_id, sort_order);
|
|
377
|
+
CREATE INDEX IF NOT EXISTS idx_provider_models_provider ON provider_models(provider_id);
|
|
378
|
+
CREATE INDEX IF NOT EXISTS idx_project_defaults_projectId ON project_session_defaults(project_id);
|
|
379
|
+
CREATE INDEX IF NOT EXISTS idx_agent_call_logs_session ON agent_call_logs(session_id);
|
|
380
|
+
CREATE INDEX IF NOT EXISTS idx_agent_call_logs_started ON agent_call_logs(started_at);
|
|
381
|
+
CREATE INDEX IF NOT EXISTS idx_agent_call_logs_agent_type ON agent_call_logs(agent_type);
|
|
382
|
+
CREATE INDEX IF NOT EXISTS idx_agent_call_logs_call_type ON agent_call_logs(call_type);
|
|
383
|
+
CREATE INDEX IF NOT EXISTS idx_agent_call_logs_status ON agent_call_logs(status);
|
|
384
|
+
CREATE INDEX IF NOT EXISTS idx_agent_call_logs_model ON agent_call_logs(model);
|
|
368
385
|
CREATE INDEX IF NOT EXISTS idx_kanban_boards_project ON kanban_boards(project_id);
|
|
369
386
|
CREATE INDEX IF NOT EXISTS idx_kanban_lanes_board ON kanban_lanes(board_id, sort_order);
|
|
370
387
|
CREATE INDEX IF NOT EXISTS idx_kanban_cards_lane ON kanban_cards(lane_id, sort_order);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { copyDatabaseBackups } from './dbUtils.js';
|
|
3
|
+
|
|
4
|
+
export function main() {
|
|
5
|
+
const result = copyDatabaseBackups();
|
|
6
|
+
|
|
7
|
+
if (result.copied.length === 0) {
|
|
8
|
+
console.log(`No database found at ${result.dbPath}; nothing to back up.`);
|
|
9
|
+
return 0;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
console.log(`Database backup directory: ${result.backupDir}`);
|
|
13
|
+
for (const file of result.copied) {
|
|
14
|
+
console.log(`${file.source} -> ${file.target}`);
|
|
15
|
+
}
|
|
16
|
+
return 0;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
20
|
+
process.exit(main());
|
|
21
|
+
}
|