circuschief 0.6.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 +35 -4
- package/packages/server/src/api/projects.js +11 -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-draft.js +1 -0
- 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/api/settings.js +52 -4
- package/packages/server/src/database.js +0 -2
- package/packages/server/src/db/ConversationRepository.js +16 -3
- package/packages/server/src/db/DatabaseManager.js +5 -1
- package/packages/server/src/db/ProjectDefaultsRepository.js +50 -40
- package/packages/server/src/db/ProviderRepository.js +87 -32
- package/packages/server/src/db/SessionRepository.js +13 -8
- package/packages/server/src/db/SettingsRepository.js +44 -16
- package/packages/server/src/db/conversation-helpers.js +1 -0
- package/packages/server/src/db/index.js +0 -3
- package/packages/server/src/db/migrations/index.js +36 -200
- package/packages/server/src/db/seedBaselineData.js +137 -0
- package/packages/server/src/db/session-helpers.js +9 -3
- package/packages/server/src/middleware/sessionLookup.js +81 -8
- package/packages/server/src/schema.sql +157 -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/agentCallLogger.js +1 -1
- package/packages/server/src/services/codexSpawnHelper.js +9 -0
- package/packages/server/src/services/commandButtonPrompts.js +48 -0
- package/packages/server/src/services/commandRunner.js +7 -1
- package/packages/server/src/services/draftSessionService.js +2 -0
- 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 -106
- package/packages/server/src/services/sessionPrompts.js +16 -47
- package/packages/server/src/services/sessionProvider.js +16 -8
- package/packages/server/src/services/streamEventCallbacks.js +72 -40
- package/packages/server/src/services/streamEventHandler.js +13 -2
- package/packages/server/src/services/streamUsageHandler.js +6 -0
- package/packages/server/src/services/summaryClaudeClient.js +37 -12
- package/packages/server/src/services/summaryModelClient.js +154 -0
- package/packages/server/src/services/summaryModelResolver.js +148 -0
- package/packages/server/src/services/summaryService.js +11 -7
- package/packages/server/src/services/summaryStaleCheck.js +23 -4
- package/packages/server/src/services/templateTriggerService.js +3 -1
- package/packages/server/src/services/usageTracker.js +5 -1
- package/packages/server/src/services/visibleFinalErrorMessage.js +123 -0
- package/packages/shared/src/constants.js +4 -2
- package/packages/shared/src/contracts/commandButtons.js +16 -2
- package/packages/shared/src/contracts/projects.js +4 -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 +11 -19
- package/packages/web/dist/assets/ActiveSessionsView-B0XHqLmv.js +1 -0
- package/packages/web/dist/assets/{AgentLogsView-Cdw4nmvd.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-DnFhJY5A.js → CommandButtonDetailView-CdSCPp78.js} +1 -1
- package/packages/web/dist/assets/EffortLevelSelector-hc2MNKg6.js +1 -0
- package/packages/web/dist/assets/{GeneralSettingsView-CQkmdczf.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-PfYR3KJo.js → InterpolationHelp-BO1j9Z3_.js} +1 -1
- package/packages/web/dist/assets/MarkdownEditor-ucRAP_UM.js +2 -0
- package/packages/web/dist/assets/{ModelSelector-BZOT1Jc6.css → ModelSelector-BSxKUSus.css} +1 -1
- package/packages/web/dist/assets/ModelSelector-CwTz8ZWO.js +1 -0
- package/packages/web/dist/assets/NewSessionView-BDPb-1qr.css +1 -0
- 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-J15mcsWz.css +1 -0
- package/packages/web/dist/assets/{ProjectListView-CuYMmd3O.js → ProjectListView-DcNyuINs.js} +1 -1
- package/packages/web/dist/assets/{ProjectNewView-CNaA4Maf.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-BQwQXuL7.js +1 -0
- package/packages/web/dist/assets/{QuickResponsesPanel-DIBQFj0W.css → QuickResponsesPanel-BlFDvnZ2.css} +1 -1
- package/packages/web/dist/assets/{QuickResponsesPanel-BqMYSHb0.js → QuickResponsesPanel-BzSYcCSP.js} +1 -1
- package/packages/web/dist/assets/{ResizableTextarea-wYF3K2RO.js → ResizableTextarea-B3YIdIXv.js} +1 -1
- package/packages/web/dist/assets/{SessionCard-bLaQEWWX.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-B6AxyREh.js +1 -0
- package/packages/web/dist/assets/SessionFormOptions-BpUALRKn.css +1 -0
- 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-DTnDAF95.js → SessionLogStream-LlZ3z_Xj.js} +1 -1
- package/packages/web/dist/assets/{SettingsView-DNLUSsHV.js → SettingsView-CTGiGvR2.js} +1 -1
- package/packages/web/dist/assets/{SlashCommandWizard-CRGFaO8t.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-BR2ZjEa3.js +1 -0
- package/packages/web/dist/assets/SummarySettingsView-l2bxHmZZ.css +1 -0
- package/packages/web/dist/assets/TemplateDetailView-DH6Oswsp.js +1 -0
- package/packages/web/dist/assets/{commandButtons-Bbjf3fCt.js → commandButtons-BfqR-fqq.js} +1 -1
- package/packages/web/dist/assets/index-1zziPL6l.js +1 -0
- package/packages/web/dist/assets/index-7kzHPxSF.js +1 -0
- package/packages/web/dist/assets/index-B0N_obMc.js +1 -0
- package/packages/web/dist/assets/index-BNk_gdfI.js +1 -0
- package/packages/web/dist/assets/{index-gmCCsCQ1.css → index-BY174HVJ.css} +1 -1
- package/packages/web/dist/assets/index-CSqaAH-0.js +1 -0
- package/packages/web/dist/assets/index-C_q4WlK8.js +1 -0
- package/packages/web/dist/assets/index-D1wpU4y0.js +7 -0
- package/packages/web/dist/assets/index-D5zCA8sD.js +1 -0
- package/packages/web/dist/assets/index-DGR8ELWY.js +1 -0
- package/packages/web/dist/assets/index-DHga8pXo.js +1 -0
- package/packages/web/dist/assets/index-DSby02Wl.js +1 -0
- package/packages/web/dist/assets/{index-Cf6vdW-B.js → index-DgkC10TW.js} +3 -3
- package/packages/web/dist/assets/index-DqjXJTVI.js +1 -0
- package/packages/web/dist/assets/{index-Bs7Qf5D6.js → index-DtfUt785.js} +2 -2
- package/packages/web/dist/assets/index-_4S2uLDI.js +1 -0
- package/packages/web/dist/assets/{index-BQL_L4gL.js → index-fK8FIZgP.js} +15 -14
- package/packages/web/dist/assets/index-gmiZeFXN.js +1 -0
- package/packages/web/dist/assets/index-irD539ZM.js +3 -0
- package/packages/web/dist/assets/index-yq-E1Y00.js +1 -0
- package/packages/web/dist/assets/{projects-CPt3AB7U.js → projects-DXYQNJIi.js} +1 -1
- package/packages/web/dist/assets/{providers-ChfeMvUq.js → providers-1bnH-exJ.js} +1 -1
- package/packages/web/dist/assets/sessions-6zGUlFrt.js +1 -0
- package/packages/web/dist/assets/settings-MbfRir0d.js +1 -0
- 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 -183
- 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 -282
- package/packages/web/dist/assets/ActiveSessionsView-UCbQrF1b.js +0 -1
- package/packages/web/dist/assets/ApiClient-CWbXWDUY.js +0 -1
- package/packages/web/dist/assets/ArchiveConfirmModal-BQ-4gI0R.css +0 -1
- package/packages/web/dist/assets/ArchiveConfirmModal-J48eh3zw.js +0 -1
- package/packages/web/dist/assets/EffortLevelSelector-bXbPo4Zw.js +0 -1
- package/packages/web/dist/assets/InputWithButton-XyM3k6lN.js +0 -1
- package/packages/web/dist/assets/MarkdownEditor-P8F5kO-o.js +0 -2
- package/packages/web/dist/assets/ModelSelector-CowKfGMP.js +0 -1
- package/packages/web/dist/assets/NewSessionView-D_Hi7M9g.css +0 -1
- package/packages/web/dist/assets/NewSessionView-DkjFLvHU.js +0 -3
- package/packages/web/dist/assets/ProjectEditView-CpeKj-_w.css +0 -1
- package/packages/web/dist/assets/ProjectEditView-embVT7NC.js +0 -1
- package/packages/web/dist/assets/ProvidersView-C7rydtOd.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-BTQEKhwJ.js +0 -1
- package/packages/web/dist/assets/SessionDetailView-Cv-xMzXp.css +0 -1
- package/packages/web/dist/assets/SessionDetailView-CvQOUsW2.js +0 -36
- package/packages/web/dist/assets/SessionFormOptions-3pzbgI2Q.js +0 -1
- package/packages/web/dist/assets/SessionFormOptions-DhhIkjIS.css +0 -1
- package/packages/web/dist/assets/SessionListView-Dranfb72.js +0 -1
- package/packages/web/dist/assets/SessionListView-fHlQyecX.css +0 -1
- package/packages/web/dist/assets/SummarySettingsView-C7G_suHp.js +0 -1
- package/packages/web/dist/assets/SummarySettingsView-DcsmSVJI.css +0 -1
- package/packages/web/dist/assets/TemplateDetailView-B78_DLMR.js +0 -1
- package/packages/web/dist/assets/index--V7c-VZf.js +0 -1
- package/packages/web/dist/assets/index-8Q04yd7H.js +0 -1
- package/packages/web/dist/assets/index-B47XRBDH.js +0 -1
- package/packages/web/dist/assets/index-BXbgZrhS.js +0 -1
- package/packages/web/dist/assets/index-CGhDVPen.js +0 -1
- package/packages/web/dist/assets/index-CKcRO1A6.js +0 -1
- package/packages/web/dist/assets/index-CTq-SLIW.js +0 -1
- package/packages/web/dist/assets/index-CYyos3iC.js +0 -1
- package/packages/web/dist/assets/index-CsCREAxF.js +0 -1
- package/packages/web/dist/assets/index-DJTTk_8T.js +0 -3
- package/packages/web/dist/assets/index-DPqUJ5JK.js +0 -1
- package/packages/web/dist/assets/index-EwAe1dKg.js +0 -1
- package/packages/web/dist/assets/index-JBA8axyA.js +0 -1
- package/packages/web/dist/assets/index-JkVHFtK5.js +0 -7
- package/packages/web/dist/assets/index-gMPUwT55.js +0 -1
- package/packages/web/dist/assets/index-wadc_0zT.js +0 -1
- package/packages/web/dist/assets/sessions-CwPsJOb1.js +0 -1
- package/packages/web/dist/assets/settings-BOj6wq6t.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,90 +25,132 @@ 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,
|
|
77
|
+
input_tokens INTEGER DEFAULT 0,
|
|
78
|
+
output_tokens INTEGER DEFAULT 0,
|
|
79
|
+
thinking_tokens INTEGER DEFAULT 0,
|
|
80
|
+
cache_read_input_tokens INTEGER DEFAULT 0,
|
|
81
|
+
cache_creation_input_tokens INTEGER DEFAULT 0,
|
|
82
|
+
web_search_requests INTEGER DEFAULT 0,
|
|
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,
|
|
51
102
|
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
52
103
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
53
104
|
);
|
|
54
105
|
|
|
55
|
-
-- Conversations (multiple conversation threads per session)
|
|
56
106
|
CREATE TABLE IF NOT EXISTS conversations (
|
|
57
107
|
id TEXT PRIMARY KEY,
|
|
58
108
|
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
59
|
-
name TEXT,
|
|
60
|
-
summary TEXT,
|
|
61
|
-
summary_generated_at INTEGER,
|
|
62
|
-
is_active INTEGER NOT NULL DEFAULT 0,
|
|
63
|
-
claude_session_id TEXT,
|
|
64
|
-
-- 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,
|
|
65
114
|
input_tokens INTEGER DEFAULT 0,
|
|
66
115
|
output_tokens INTEGER DEFAULT 0,
|
|
116
|
+
thinking_tokens INTEGER DEFAULT 0,
|
|
67
117
|
cache_read_input_tokens INTEGER DEFAULT 0,
|
|
68
118
|
cache_creation_input_tokens INTEGER DEFAULT 0,
|
|
69
119
|
web_search_requests INTEGER DEFAULT 0,
|
|
70
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,
|
|
71
124
|
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
72
125
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
73
126
|
);
|
|
74
127
|
|
|
75
|
-
-- Conversation messages
|
|
76
128
|
CREATE TABLE IF NOT EXISTS conversation_messages (
|
|
77
129
|
id TEXT PRIMARY KEY,
|
|
78
130
|
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
79
131
|
conversation_id TEXT REFERENCES conversations(id) ON DELETE CASCADE,
|
|
80
132
|
role TEXT NOT NULL CHECK (role IN ('user', 'assistant', 'system')),
|
|
81
133
|
content TEXT NOT NULL,
|
|
82
|
-
tool_use TEXT,
|
|
83
|
-
model TEXT,
|
|
134
|
+
tool_use TEXT,
|
|
135
|
+
model TEXT,
|
|
84
136
|
timestamp INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
85
137
|
);
|
|
86
138
|
|
|
87
|
-
-- Canvas items
|
|
88
139
|
CREATE TABLE IF NOT EXISTS canvas_items (
|
|
89
140
|
id TEXT PRIMARY KEY,
|
|
90
141
|
session_id TEXT REFERENCES sessions(id) ON DELETE CASCADE,
|
|
91
142
|
type TEXT NOT NULL CHECK (type IN ('image', 'markdown', 'text', 'json', 'pdf', 'code')),
|
|
92
|
-
content TEXT,
|
|
93
|
-
data TEXT,
|
|
94
|
-
mime_type TEXT,
|
|
143
|
+
content TEXT,
|
|
144
|
+
data TEXT,
|
|
145
|
+
mime_type TEXT,
|
|
95
146
|
filename TEXT,
|
|
96
147
|
width INTEGER,
|
|
97
148
|
height INTEGER,
|
|
98
|
-
deleted_at INTEGER,
|
|
149
|
+
deleted_at INTEGER,
|
|
99
150
|
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
100
|
-
updated_at INTEGER
|
|
151
|
+
updated_at INTEGER
|
|
101
152
|
);
|
|
102
153
|
|
|
103
|
-
-- Session notes
|
|
104
|
-
CREATE TABLE IF NOT EXISTS session_notes (
|
|
105
|
-
id TEXT PRIMARY KEY,
|
|
106
|
-
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
107
|
-
content TEXT NOT NULL,
|
|
108
|
-
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
109
|
-
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
-- Global tool templates
|
|
113
154
|
CREATE TABLE IF NOT EXISTS global_tool_templates (
|
|
114
155
|
id TEXT PRIMARY KEY,
|
|
115
156
|
name TEXT NOT NULL,
|
|
@@ -119,7 +160,6 @@ CREATE TABLE IF NOT EXISTS global_tool_templates (
|
|
|
119
160
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
120
161
|
);
|
|
121
162
|
|
|
122
|
-
-- Project tool templates
|
|
123
163
|
CREATE TABLE IF NOT EXISTS project_tool_templates (
|
|
124
164
|
id TEXT PRIMARY KEY,
|
|
125
165
|
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
@@ -130,50 +170,46 @@ CREATE TABLE IF NOT EXISTS project_tool_templates (
|
|
|
130
170
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
131
171
|
);
|
|
132
172
|
|
|
133
|
-
-- Session todos (Claude's task list, scoped to conversations)
|
|
134
173
|
CREATE TABLE IF NOT EXISTS session_todos (
|
|
135
174
|
id TEXT PRIMARY KEY,
|
|
136
175
|
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
137
176
|
conversation_id TEXT REFERENCES conversations(id) ON DELETE CASCADE,
|
|
138
177
|
content TEXT NOT NULL,
|
|
139
|
-
status TEXT NOT NULL DEFAULT 'pending'
|
|
140
|
-
CHECK (status IN ('pending', 'in_progress', 'completed')),
|
|
178
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'in_progress', 'completed')),
|
|
141
179
|
position INTEGER NOT NULL,
|
|
142
180
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
143
181
|
);
|
|
144
182
|
|
|
145
|
-
-- Work logs (thinking, command outputs, tool executions)
|
|
146
183
|
CREATE TABLE IF NOT EXISTS work_logs (
|
|
147
184
|
id TEXT PRIMARY KEY,
|
|
148
185
|
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
149
186
|
message_id TEXT REFERENCES conversation_messages(id) ON DELETE CASCADE,
|
|
150
187
|
type TEXT NOT NULL CHECK (type IN ('thinking', 'tool_input', 'tool_output')),
|
|
151
|
-
tool_name TEXT,
|
|
152
|
-
content TEXT NOT NULL,
|
|
188
|
+
tool_name TEXT,
|
|
189
|
+
content TEXT NOT NULL,
|
|
153
190
|
timestamp INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
154
191
|
);
|
|
155
192
|
|
|
156
|
-
-- Session summaries (AI-generated)
|
|
157
193
|
CREATE TABLE IF NOT EXISTS session_summaries (
|
|
158
194
|
id TEXT PRIMARY KEY,
|
|
159
195
|
session_id TEXT NOT NULL UNIQUE REFERENCES sessions(id) ON DELETE CASCADE,
|
|
160
|
-
short_summary TEXT NOT NULL,
|
|
161
|
-
full_summary TEXT NOT NULL,
|
|
162
|
-
key_actions TEXT,
|
|
163
|
-
files_modified TEXT,
|
|
164
|
-
outcome TEXT,
|
|
165
|
-
message_count INTEGER,
|
|
166
|
-
pr_merged INTEGER,
|
|
167
|
-
pr_state TEXT,
|
|
168
|
-
has_merge_conflicts INTEGER,
|
|
169
|
-
ci_status TEXT,
|
|
170
|
-
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,
|
|
171
208
|
generated_at INTEGER NOT NULL,
|
|
172
209
|
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
173
210
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
174
211
|
);
|
|
175
212
|
|
|
176
|
-
-- Message attachments (files attached to user messages)
|
|
177
213
|
CREATE TABLE IF NOT EXISTS message_attachments (
|
|
178
214
|
id TEXT PRIMARY KEY,
|
|
179
215
|
message_id TEXT REFERENCES conversation_messages(id) ON DELETE CASCADE,
|
|
@@ -182,12 +218,11 @@ CREATE TABLE IF NOT EXISTS message_attachments (
|
|
|
182
218
|
mime_type TEXT NOT NULL,
|
|
183
219
|
size_bytes INTEGER NOT NULL,
|
|
184
220
|
storage_type TEXT NOT NULL DEFAULT 'base64' CHECK (storage_type IN ('base64', 'file_path', 'project_file')),
|
|
185
|
-
content TEXT,
|
|
186
|
-
file_path TEXT,
|
|
221
|
+
content TEXT,
|
|
222
|
+
file_path TEXT,
|
|
187
223
|
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
188
224
|
);
|
|
189
225
|
|
|
190
|
-
-- Command buttons (configurable buttons per project)
|
|
191
226
|
CREATE TABLE IF NOT EXISTS command_buttons (
|
|
192
227
|
id TEXT PRIMARY KEY,
|
|
193
228
|
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
@@ -199,7 +234,6 @@ CREATE TABLE IF NOT EXISTS command_buttons (
|
|
|
199
234
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
200
235
|
);
|
|
201
236
|
|
|
202
|
-
-- Command runs (execution history for command buttons)
|
|
203
237
|
CREATE TABLE IF NOT EXISTS command_runs (
|
|
204
238
|
id TEXT PRIMARY KEY,
|
|
205
239
|
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
@@ -211,7 +245,6 @@ CREATE TABLE IF NOT EXISTS command_runs (
|
|
|
211
245
|
completed_at INTEGER
|
|
212
246
|
);
|
|
213
247
|
|
|
214
|
-
-- Quick responses (reusable messages for conversation)
|
|
215
248
|
CREATE TABLE IF NOT EXISTS quick_responses (
|
|
216
249
|
id TEXT PRIMARY KEY,
|
|
217
250
|
project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
|
|
@@ -224,102 +257,51 @@ CREATE TABLE IF NOT EXISTS quick_responses (
|
|
|
224
257
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
225
258
|
);
|
|
226
259
|
|
|
227
|
-
|
|
228
|
-
CREATE TABLE IF NOT EXISTS providers (
|
|
260
|
+
CREATE TABLE IF NOT EXISTS project_session_defaults (
|
|
229
261
|
id TEXT PRIMARY KEY,
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
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
|
|
239
274
|
);
|
|
240
275
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
model_id TEXT NOT NULL,
|
|
246
|
-
display_name TEXT NOT NULL,
|
|
247
|
-
description TEXT,
|
|
248
|
-
tier TEXT CHECK(tier IN ('opus', 'sonnet', 'haiku', 'custom')),
|
|
249
|
-
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
|
|
250
280
|
);
|
|
251
281
|
|
|
252
|
-
-- Indexes
|
|
253
|
-
CREATE INDEX IF NOT EXISTS idx_sessions_project ON sessions(project_id);
|
|
254
|
-
CREATE INDEX IF NOT EXISTS idx_sessions_status ON sessions(status);
|
|
255
|
-
CREATE INDEX IF NOT EXISTS idx_sessions_archived ON sessions(archived);
|
|
256
|
-
CREATE INDEX IF NOT EXISTS idx_conversations_session ON conversations(session_id);
|
|
257
|
-
CREATE INDEX IF NOT EXISTS idx_messages_session ON conversation_messages(session_id);
|
|
258
|
-
-- Note: idx_messages_conversation is created in migrations to handle existing databases
|
|
259
|
-
-- that may not have the conversation_id column yet
|
|
260
|
-
CREATE INDEX IF NOT EXISTS idx_canvas_session ON canvas_items(session_id);
|
|
261
|
-
-- Note: idx_canvas_deleted is created in migrations to handle existing databases
|
|
262
|
-
-- that may not have the deleted_at column yet
|
|
263
|
-
CREATE INDEX IF NOT EXISTS idx_notes_session ON session_notes(session_id);
|
|
264
|
-
CREATE INDEX IF NOT EXISTS idx_project_tools ON project_tool_templates(project_id);
|
|
265
|
-
CREATE INDEX IF NOT EXISTS idx_session_templates_project ON session_templates(project_id);
|
|
266
|
-
-- Note: idx_sessions_next_template and idx_sessions_parent are created in migrations
|
|
267
|
-
-- to handle existing databases that may not have these columns yet
|
|
268
|
-
CREATE INDEX IF NOT EXISTS idx_todos_session ON session_todos(session_id);
|
|
269
|
-
-- Note: idx_todos_conversation is created in migrations to handle existing databases
|
|
270
|
-
-- that may not have the conversation_id column yet
|
|
271
|
-
CREATE INDEX IF NOT EXISTS idx_work_logs_session ON work_logs(session_id);
|
|
272
|
-
CREATE INDEX IF NOT EXISTS idx_work_logs_message ON work_logs(message_id);
|
|
273
|
-
CREATE INDEX IF NOT EXISTS idx_summaries_session ON session_summaries(session_id);
|
|
274
|
-
CREATE INDEX IF NOT EXISTS idx_attachments_message ON message_attachments(message_id);
|
|
275
|
-
CREATE INDEX IF NOT EXISTS idx_attachments_session ON message_attachments(session_id);
|
|
276
|
-
CREATE INDEX IF NOT EXISTS idx_command_buttons_project ON command_buttons(project_id);
|
|
277
|
-
CREATE INDEX IF NOT EXISTS idx_command_runs_session ON command_runs(session_id);
|
|
278
|
-
CREATE INDEX IF NOT EXISTS idx_command_runs_button ON command_runs(button_id);
|
|
279
|
-
CREATE INDEX IF NOT EXISTS idx_command_runs_status ON command_runs(status);
|
|
280
|
-
CREATE INDEX IF NOT EXISTS idx_quick_responses_project ON quick_responses(project_id);
|
|
281
|
-
CREATE INDEX IF NOT EXISTS idx_quick_responses_sort ON quick_responses(project_id, sort_order);
|
|
282
|
-
CREATE INDEX IF NOT EXISTS idx_provider_models_provider ON provider_models(provider_id);
|
|
283
|
-
|
|
284
|
-
-- Agent call logs (metrics and analytics for agent interactions)
|
|
285
282
|
CREATE TABLE IF NOT EXISTS agent_call_logs (
|
|
286
283
|
id TEXT PRIMARY KEY,
|
|
287
284
|
session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
|
|
288
285
|
conversation_id TEXT,
|
|
289
286
|
agent_type TEXT NOT NULL,
|
|
290
287
|
model TEXT,
|
|
291
|
-
|
|
292
|
-
-- Request info
|
|
293
|
-
call_type TEXT NOT NULL, -- 'runSession' | 'continueSession' | 'continueSessionWithExistingMessage'
|
|
288
|
+
call_type TEXT NOT NULL,
|
|
294
289
|
prompt_length INTEGER,
|
|
295
|
-
|
|
296
|
-
-- Response token info (updated during streaming and finalized at result)
|
|
297
290
|
input_tokens INTEGER DEFAULT 0,
|
|
298
291
|
output_tokens INTEGER DEFAULT 0,
|
|
299
292
|
thinking_tokens INTEGER DEFAULT 0,
|
|
300
293
|
cache_read_tokens INTEGER DEFAULT 0,
|
|
301
294
|
cache_write_tokens INTEGER DEFAULT 0,
|
|
302
295
|
total_tokens INTEGER DEFAULT 0,
|
|
303
|
-
|
|
304
|
-
-- Timing
|
|
305
296
|
started_at INTEGER NOT NULL,
|
|
306
297
|
completed_at INTEGER,
|
|
307
298
|
duration_ms INTEGER,
|
|
308
|
-
|
|
309
|
-
-- Status
|
|
310
299
|
status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending', 'streaming', 'completed', 'error')),
|
|
311
300
|
error_message TEXT,
|
|
312
|
-
|
|
313
|
-
-- Metadata (JSON blob for extensibility)
|
|
314
301
|
metadata TEXT,
|
|
315
|
-
|
|
316
302
|
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
317
303
|
);
|
|
318
304
|
|
|
319
|
-
CREATE INDEX IF NOT EXISTS idx_agent_call_logs_session ON agent_call_logs(session_id);
|
|
320
|
-
CREATE INDEX IF NOT EXISTS idx_agent_call_logs_started ON agent_call_logs(started_at);
|
|
321
|
-
|
|
322
|
-
-- Kanban boards (one per project)
|
|
323
305
|
CREATE TABLE IF NOT EXISTS kanban_boards (
|
|
324
306
|
id TEXT PRIMARY KEY,
|
|
325
307
|
project_id TEXT NOT NULL UNIQUE REFERENCES projects(id) ON DELETE CASCADE,
|
|
@@ -327,7 +309,6 @@ CREATE TABLE IF NOT EXISTS kanban_boards (
|
|
|
327
309
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
328
310
|
);
|
|
329
311
|
|
|
330
|
-
-- Kanban lanes (columns on the board)
|
|
331
312
|
CREATE TABLE IF NOT EXISTS kanban_lanes (
|
|
332
313
|
id TEXT PRIMARY KEY,
|
|
333
314
|
board_id TEXT NOT NULL REFERENCES kanban_boards(id) ON DELETE CASCADE,
|
|
@@ -335,11 +316,21 @@ CREATE TABLE IF NOT EXISTS kanban_lanes (
|
|
|
335
316
|
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
336
317
|
on_enter_template_id TEXT REFERENCES session_templates(id) ON DELETE SET NULL,
|
|
337
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,
|
|
338
330
|
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000),
|
|
339
331
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
340
332
|
);
|
|
341
333
|
|
|
342
|
-
-- Kanban cards (entries on the board, separate from sessions for future flexibility)
|
|
343
334
|
CREATE TABLE IF NOT EXISTS kanban_cards (
|
|
344
335
|
id TEXT PRIMARY KEY,
|
|
345
336
|
lane_id TEXT NOT NULL REFERENCES kanban_lanes(id) ON DELETE CASCADE,
|
|
@@ -348,7 +339,6 @@ CREATE TABLE IF NOT EXISTS kanban_cards (
|
|
|
348
339
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
349
340
|
);
|
|
350
341
|
|
|
351
|
-
-- Kanban card sessions (links cards to sessions, currently 1:1 but allows future N:1)
|
|
352
342
|
CREATE TABLE IF NOT EXISTS kanban_card_sessions (
|
|
353
343
|
id TEXT PRIMARY KEY,
|
|
354
344
|
card_id TEXT NOT NULL REFERENCES kanban_cards(id) ON DELETE CASCADE,
|
|
@@ -356,7 +346,42 @@ CREATE TABLE IF NOT EXISTS kanban_card_sessions (
|
|
|
356
346
|
created_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000)
|
|
357
347
|
);
|
|
358
348
|
|
|
359
|
-
|
|
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);
|
|
360
385
|
CREATE INDEX IF NOT EXISTS idx_kanban_boards_project ON kanban_boards(project_id);
|
|
361
386
|
CREATE INDEX IF NOT EXISTS idx_kanban_lanes_board ON kanban_lanes(board_id, sort_order);
|
|
362
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
|
+
}
|