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