@mcoda/db 0.1.4
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/CHANGELOG.md +7 -0
- package/LICENSE +21 -0
- package/README.md +9 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/migrations/global/GlobalMigrations.d.ts +9 -0
- package/dist/migrations/global/GlobalMigrations.d.ts.map +1 -0
- package/dist/migrations/global/GlobalMigrations.js +319 -0
- package/dist/migrations/workspace/WorkspaceMigrations.d.ts +9 -0
- package/dist/migrations/workspace/WorkspaceMigrations.d.ts.map +1 -0
- package/dist/migrations/workspace/WorkspaceMigrations.js +246 -0
- package/dist/repositories/global/GlobalRepository.d.ts +71 -0
- package/dist/repositories/global/GlobalRepository.d.ts.map +1 -0
- package/dist/repositories/global/GlobalRepository.js +281 -0
- package/dist/repositories/workspace/WorkspaceRepository.d.ts +341 -0
- package/dist/repositories/workspace/WorkspaceRepository.d.ts.map +1 -0
- package/dist/repositories/workspace/WorkspaceRepository.js +871 -0
- package/dist/sqlite/connection.d.ts +12 -0
- package/dist/sqlite/connection.d.ts.map +1 -0
- package/dist/sqlite/connection.js +32 -0
- package/dist/sqlite/pragmas.d.ts +5 -0
- package/dist/sqlite/pragmas.d.ts.map +1 -0
- package/dist/sqlite/pragmas.js +8 -0
- package/package.json +42 -0
package/CHANGELOG.md
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 bekir dag
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from "./sqlite/connection.js";
|
|
2
|
+
export * from "./migrations/global/GlobalMigrations.js";
|
|
3
|
+
export * from "./migrations/workspace/WorkspaceMigrations.js";
|
|
4
|
+
export * from "./repositories/global/GlobalRepository.js";
|
|
5
|
+
export * from "./repositories/workspace/WorkspaceRepository.js";
|
|
6
|
+
export type { Database } from "sqlite";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,yCAAyC,CAAC;AACxD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,iDAAiD,CAAC;AAChE,YAAY,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export * from "./sqlite/connection.js";
|
|
2
|
+
export * from "./migrations/global/GlobalMigrations.js";
|
|
3
|
+
export * from "./migrations/workspace/WorkspaceMigrations.js";
|
|
4
|
+
export * from "./repositories/global/GlobalRepository.js";
|
|
5
|
+
export * from "./repositories/workspace/WorkspaceRepository.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Database } from "sqlite";
|
|
2
|
+
/**
|
|
3
|
+
* Global database migrations for ~/.mcoda/mcoda.db.
|
|
4
|
+
* Only includes tables required for the agent registry and routing defaults.
|
|
5
|
+
*/
|
|
6
|
+
export declare class GlobalMigrations {
|
|
7
|
+
static run(db: Database): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=GlobalMigrations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GlobalMigrations.d.ts","sourceRoot":"","sources":["../../../src/migrations/global/GlobalMigrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC;;;GAGG;AACH,qBAAa,gBAAgB;WACd,GAAG,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAwU9C"}
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global database migrations for ~/.mcoda/mcoda.db.
|
|
3
|
+
* Only includes tables required for the agent registry and routing defaults.
|
|
4
|
+
*/
|
|
5
|
+
export class GlobalMigrations {
|
|
6
|
+
static async run(db) {
|
|
7
|
+
const createSchema = async () => {
|
|
8
|
+
await db.exec(`
|
|
9
|
+
CREATE TABLE IF NOT EXISTS agents (
|
|
10
|
+
id TEXT PRIMARY KEY,
|
|
11
|
+
slug TEXT UNIQUE NOT NULL,
|
|
12
|
+
adapter TEXT NOT NULL,
|
|
13
|
+
default_model TEXT,
|
|
14
|
+
rating INTEGER,
|
|
15
|
+
reasoning_rating INTEGER,
|
|
16
|
+
best_usage TEXT,
|
|
17
|
+
cost_per_million REAL,
|
|
18
|
+
config_json TEXT,
|
|
19
|
+
created_at TEXT NOT NULL,
|
|
20
|
+
updated_at TEXT NOT NULL
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
CREATE TABLE IF NOT EXISTS agent_auth (
|
|
24
|
+
agent_id TEXT PRIMARY KEY REFERENCES agents(id) ON DELETE CASCADE,
|
|
25
|
+
encrypted_secret TEXT NOT NULL,
|
|
26
|
+
last_verified_at TEXT,
|
|
27
|
+
created_at TEXT NOT NULL,
|
|
28
|
+
updated_at TEXT NOT NULL
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
CREATE TABLE IF NOT EXISTS agent_capabilities (
|
|
32
|
+
agent_id TEXT NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
|
|
33
|
+
capability TEXT NOT NULL,
|
|
34
|
+
PRIMARY KEY (agent_id, capability)
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
CREATE TABLE IF NOT EXISTS agent_prompts (
|
|
38
|
+
agent_id TEXT PRIMARY KEY REFERENCES agents(id) ON DELETE CASCADE,
|
|
39
|
+
job_prompt TEXT,
|
|
40
|
+
character_prompt TEXT,
|
|
41
|
+
command_prompts_json TEXT,
|
|
42
|
+
job_path TEXT,
|
|
43
|
+
character_path TEXT,
|
|
44
|
+
created_at TEXT NOT NULL,
|
|
45
|
+
updated_at TEXT NOT NULL
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
CREATE TABLE IF NOT EXISTS agent_health (
|
|
49
|
+
agent_id TEXT PRIMARY KEY REFERENCES agents(id) ON DELETE CASCADE,
|
|
50
|
+
status TEXT NOT NULL,
|
|
51
|
+
last_checked_at TEXT NOT NULL,
|
|
52
|
+
latency_ms INTEGER,
|
|
53
|
+
details_json TEXT
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
CREATE TABLE IF NOT EXISTS agent_models (
|
|
57
|
+
agent_id TEXT NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
|
|
58
|
+
model_name TEXT NOT NULL,
|
|
59
|
+
is_default INTEGER DEFAULT 0,
|
|
60
|
+
config_json TEXT,
|
|
61
|
+
PRIMARY KEY (agent_id, model_name)
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
CREATE TABLE IF NOT EXISTS workspace_defaults (
|
|
65
|
+
workspace_id TEXT NOT NULL,
|
|
66
|
+
command_name TEXT NOT NULL,
|
|
67
|
+
agent_id TEXT NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
|
|
68
|
+
qa_profile TEXT,
|
|
69
|
+
docdex_scope TEXT,
|
|
70
|
+
updated_at TEXT NOT NULL,
|
|
71
|
+
PRIMARY KEY (workspace_id, command_name)
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
CREATE TABLE IF NOT EXISTS command_runs (
|
|
75
|
+
id TEXT PRIMARY KEY,
|
|
76
|
+
command_name TEXT NOT NULL,
|
|
77
|
+
started_at TEXT NOT NULL,
|
|
78
|
+
completed_at TEXT,
|
|
79
|
+
status TEXT NOT NULL,
|
|
80
|
+
exit_code INTEGER,
|
|
81
|
+
error_summary TEXT,
|
|
82
|
+
payload_json TEXT,
|
|
83
|
+
result_json TEXT
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
CREATE TABLE IF NOT EXISTS token_usage (
|
|
87
|
+
id TEXT PRIMARY KEY,
|
|
88
|
+
agent_id TEXT REFERENCES agents(id) ON DELETE SET NULL,
|
|
89
|
+
command_run_id TEXT REFERENCES command_runs(id) ON DELETE SET NULL,
|
|
90
|
+
model_name TEXT,
|
|
91
|
+
tokens_prompt INTEGER,
|
|
92
|
+
tokens_completion INTEGER,
|
|
93
|
+
tokens_total INTEGER,
|
|
94
|
+
cost_estimate REAL,
|
|
95
|
+
duration_seconds REAL,
|
|
96
|
+
timestamp TEXT NOT NULL,
|
|
97
|
+
metadata_json TEXT
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
CREATE INDEX IF NOT EXISTS idx_token_usage_command_run_id ON token_usage(command_run_id);
|
|
101
|
+
`);
|
|
102
|
+
};
|
|
103
|
+
await createSchema();
|
|
104
|
+
let agentsInfo = await db.all("PRAGMA table_info(agents)");
|
|
105
|
+
const hasAgentId = agentsInfo.some((col) => col.name === "id");
|
|
106
|
+
const hasAgentSlug = agentsInfo.some((col) => col.name === "slug");
|
|
107
|
+
// If the agents table is from a legacy schema (name/provider/model), reset the global DB schema.
|
|
108
|
+
if (!hasAgentId || !hasAgentSlug) {
|
|
109
|
+
await db.exec(`
|
|
110
|
+
DROP TABLE IF EXISTS agent_auth;
|
|
111
|
+
DROP TABLE IF EXISTS agent_capabilities;
|
|
112
|
+
DROP TABLE IF EXISTS agent_prompts;
|
|
113
|
+
DROP TABLE IF EXISTS agent_health;
|
|
114
|
+
DROP TABLE IF EXISTS agent_models;
|
|
115
|
+
DROP TABLE IF EXISTS workspace_defaults;
|
|
116
|
+
DROP TABLE IF EXISTS command_runs;
|
|
117
|
+
DROP TABLE IF EXISTS token_usage;
|
|
118
|
+
DROP TABLE IF EXISTS routing_rules;
|
|
119
|
+
DROP TABLE IF EXISTS agent_secrets;
|
|
120
|
+
DROP TABLE IF EXISTS releases;
|
|
121
|
+
DROP TABLE IF EXISTS schema_migrations;
|
|
122
|
+
DROP TABLE IF EXISTS agents;
|
|
123
|
+
`);
|
|
124
|
+
await createSchema();
|
|
125
|
+
}
|
|
126
|
+
agentsInfo = await db.all("PRAGMA table_info(agents)");
|
|
127
|
+
const hasAgentRating = agentsInfo.some((col) => col.name === "rating");
|
|
128
|
+
const hasAgentReasoningRating = agentsInfo.some((col) => col.name === "reasoning_rating");
|
|
129
|
+
const hasAgentBestUsage = agentsInfo.some((col) => col.name === "best_usage");
|
|
130
|
+
const hasAgentCost = agentsInfo.some((col) => col.name === "cost_per_million");
|
|
131
|
+
if (!hasAgentRating) {
|
|
132
|
+
await db.exec("ALTER TABLE agents ADD COLUMN rating INTEGER");
|
|
133
|
+
}
|
|
134
|
+
if (!hasAgentReasoningRating) {
|
|
135
|
+
await db.exec("ALTER TABLE agents ADD COLUMN reasoning_rating INTEGER");
|
|
136
|
+
}
|
|
137
|
+
if (!hasAgentBestUsage) {
|
|
138
|
+
await db.exec("ALTER TABLE agents ADD COLUMN best_usage TEXT");
|
|
139
|
+
}
|
|
140
|
+
if (!hasAgentCost) {
|
|
141
|
+
await db.exec("ALTER TABLE agents ADD COLUMN cost_per_million REAL");
|
|
142
|
+
}
|
|
143
|
+
await db.exec(`
|
|
144
|
+
UPDATE agents
|
|
145
|
+
SET
|
|
146
|
+
rating = COALESCE(
|
|
147
|
+
rating,
|
|
148
|
+
CASE
|
|
149
|
+
WHEN lower(slug) = 'codex-deputy' THEN 9.2
|
|
150
|
+
WHEN lower(slug) = 'gemini-junior' THEN 7.0
|
|
151
|
+
WHEN lower(slug) = 'gemini-deep-read' THEN 9.9
|
|
152
|
+
WHEN lower(slug) = 'codex-stabilizer' THEN 9.0
|
|
153
|
+
WHEN lower(slug) = 'gemini-consultant' THEN 7.5
|
|
154
|
+
WHEN lower(slug) = 'codex-test-lead' THEN 9.0
|
|
155
|
+
WHEN lower(slug) = 'gemini-scribe' THEN 7.0
|
|
156
|
+
WHEN lower(slug) = 'gemini-stable' THEN 9.8
|
|
157
|
+
WHEN lower(slug) = 'glm-hotfix' THEN 9.0
|
|
158
|
+
WHEN lower(slug) = 'gateway-router' THEN 10
|
|
159
|
+
WHEN lower(slug) = 'codex-architect' THEN 10
|
|
160
|
+
WHEN lower(slug) = 'glm-worker' THEN 9
|
|
161
|
+
WHEN lower(slug) = 'gemini-architect' THEN 9
|
|
162
|
+
WHEN lower(slug) = 'devstral-local' THEN 6
|
|
163
|
+
WHEN lower(slug) = 'gpt-oss-qa' THEN 9
|
|
164
|
+
WHEN lower(default_model) LIKE '%gpt-5.2-codex%' OR lower(slug) LIKE '%gpt-5.2-codex%' THEN 10
|
|
165
|
+
WHEN lower(default_model) LIKE '%gpt-5.1-codex-max%' OR lower(slug) LIKE '%gpt-5.1-codex-max%' THEN 9
|
|
166
|
+
WHEN lower(default_model) LIKE '%glm-4.7%' OR lower(slug) LIKE '%glm-4.7%' THEN 6
|
|
167
|
+
WHEN lower(default_model) LIKE '%devstral-small-2%' OR lower(slug) LIKE '%devstral-small-2%' THEN 4
|
|
168
|
+
WHEN lower(default_model) LIKE '%gpt-oss:20b%' OR lower(slug) LIKE '%gpt-oss:20b%' THEN 3
|
|
169
|
+
WHEN lower(slug) LIKE '%codex%' OR lower(default_model) LIKE '%codex%' THEN 5
|
|
170
|
+
WHEN lower(slug) LIKE '%gemini%' OR lower(default_model) LIKE '%gemini%' THEN 4
|
|
171
|
+
WHEN lower(slug) LIKE '%glm%' OR lower(default_model) LIKE '%glm%' THEN 3
|
|
172
|
+
WHEN lower(slug) LIKE '%devstral%' OR lower(default_model) LIKE '%devstral%' THEN 2
|
|
173
|
+
WHEN lower(slug) LIKE '%ollama%' OR lower(adapter) LIKE 'ollama%' THEN 2
|
|
174
|
+
WHEN lower(adapter) LIKE 'qa%' THEN 3
|
|
175
|
+
ELSE 3
|
|
176
|
+
END
|
|
177
|
+
),
|
|
178
|
+
reasoning_rating = COALESCE(
|
|
179
|
+
reasoning_rating,
|
|
180
|
+
CASE
|
|
181
|
+
WHEN lower(slug) = 'codex-deputy' THEN 8.9
|
|
182
|
+
WHEN lower(slug) = 'gemini-junior' THEN 6.5
|
|
183
|
+
WHEN lower(slug) = 'gemini-deep-read' THEN 9.0
|
|
184
|
+
WHEN lower(slug) = 'codex-stabilizer' THEN 8.5
|
|
185
|
+
WHEN lower(slug) = 'gemini-consultant' THEN 7.0
|
|
186
|
+
WHEN lower(slug) = 'codex-test-lead' THEN 8.5
|
|
187
|
+
WHEN lower(slug) = 'gemini-scribe' THEN 6.5
|
|
188
|
+
WHEN lower(slug) = 'gemini-stable' THEN 8.8
|
|
189
|
+
WHEN lower(slug) = 'glm-hotfix' THEN 8.5
|
|
190
|
+
WHEN lower(slug) = 'gateway-router' THEN 10
|
|
191
|
+
WHEN lower(slug) = 'codex-architect' THEN 10
|
|
192
|
+
WHEN lower(slug) = 'glm-worker' THEN 9
|
|
193
|
+
WHEN lower(slug) = 'gemini-architect' THEN 8
|
|
194
|
+
WHEN lower(slug) = 'devstral-local' THEN 6
|
|
195
|
+
WHEN lower(slug) = 'gpt-oss-qa' THEN 8
|
|
196
|
+
WHEN lower(default_model) LIKE '%gpt-5.2-codex%' OR lower(slug) LIKE '%gpt-5.2-codex%' THEN 10
|
|
197
|
+
WHEN lower(default_model) LIKE '%gpt-5.1-codex-max%' OR lower(slug) LIKE '%gpt-5.1-codex-max%' THEN 9
|
|
198
|
+
WHEN lower(default_model) LIKE '%gemini-3-pro%' OR lower(slug) LIKE '%gemini-3-pro%' THEN 8
|
|
199
|
+
WHEN lower(default_model) LIKE '%glm-4.7%' OR lower(slug) LIKE '%glm-4.7%' THEN 6
|
|
200
|
+
WHEN lower(default_model) LIKE '%devstral-small-2%' OR lower(slug) LIKE '%devstral-small-2%' THEN 4
|
|
201
|
+
WHEN lower(default_model) LIKE '%gpt-oss:20b%' OR lower(slug) LIKE '%gpt-oss:20b%' THEN 3
|
|
202
|
+
WHEN lower(slug) LIKE '%codex%' OR lower(default_model) LIKE '%codex%' THEN 7
|
|
203
|
+
WHEN lower(slug) LIKE '%gemini%' OR lower(default_model) LIKE '%gemini%' THEN 6
|
|
204
|
+
WHEN lower(slug) LIKE '%glm%' OR lower(default_model) LIKE '%glm%' THEN 5
|
|
205
|
+
WHEN lower(slug) LIKE '%devstral%' OR lower(default_model) LIKE '%devstral%' THEN 4
|
|
206
|
+
WHEN lower(slug) LIKE '%ollama%' OR lower(adapter) LIKE 'ollama%' THEN 3
|
|
207
|
+
WHEN lower(adapter) LIKE 'qa%' THEN 5
|
|
208
|
+
ELSE 4
|
|
209
|
+
END
|
|
210
|
+
),
|
|
211
|
+
best_usage = COALESCE(
|
|
212
|
+
best_usage,
|
|
213
|
+
CASE
|
|
214
|
+
WHEN lower(slug) = 'codex-deputy' THEN 'code_review_secondary'
|
|
215
|
+
WHEN lower(slug) = 'gemini-junior' THEN 'log_analysis'
|
|
216
|
+
WHEN lower(slug) = 'gemini-deep-read' THEN 'deep_research'
|
|
217
|
+
WHEN lower(slug) = 'codex-stabilizer' THEN 'legacy_maintenance'
|
|
218
|
+
WHEN lower(slug) = 'gemini-consultant' THEN 'alternative_solution_generation'
|
|
219
|
+
WHEN lower(slug) = 'codex-test-lead' THEN 'test_strategy'
|
|
220
|
+
WHEN lower(slug) = 'gemini-scribe' THEN 'doc_polish'
|
|
221
|
+
WHEN lower(slug) = 'gemini-stable' THEN 'production_verification'
|
|
222
|
+
WHEN lower(slug) = 'glm-hotfix' THEN 'rapid_prototyping'
|
|
223
|
+
WHEN lower(slug) = 'gateway-router' THEN 'orchestration'
|
|
224
|
+
WHEN lower(slug) = 'codex-architect' THEN 'architectural_design'
|
|
225
|
+
WHEN lower(slug) = 'glm-worker' THEN 'code_write'
|
|
226
|
+
WHEN lower(slug) = 'gemini-architect' THEN 'doc_generation'
|
|
227
|
+
WHEN lower(slug) = 'devstral-local' THEN 'coding_light'
|
|
228
|
+
WHEN lower(slug) = 'gpt-oss-qa' THEN 'qa_testing'
|
|
229
|
+
WHEN lower(slug) LIKE '%devstral%' OR lower(default_model) LIKE '%devstral%' THEN 'coding'
|
|
230
|
+
WHEN lower(slug) LIKE '%glm%' OR lower(default_model) LIKE '%glm%' THEN 'coding'
|
|
231
|
+
WHEN lower(slug) LIKE '%codex%' OR lower(default_model) LIKE '%codex%' THEN 'code_write'
|
|
232
|
+
WHEN lower(slug) LIKE '%gemini%' OR lower(default_model) LIKE '%gemini%' THEN 'ui_ux_docs'
|
|
233
|
+
WHEN lower(adapter) LIKE 'qa%' THEN 'qa'
|
|
234
|
+
WHEN lower(slug) LIKE '%ollama%' OR lower(adapter) LIKE 'ollama%' THEN 'coding'
|
|
235
|
+
ELSE 'general'
|
|
236
|
+
END
|
|
237
|
+
),
|
|
238
|
+
cost_per_million = COALESCE(
|
|
239
|
+
cost_per_million,
|
|
240
|
+
CASE
|
|
241
|
+
WHEN lower(slug) = 'codex-deputy' THEN 10.0
|
|
242
|
+
WHEN lower(slug) = 'gemini-junior' THEN 2.5
|
|
243
|
+
WHEN lower(slug) = 'gemini-deep-read' THEN 18.0
|
|
244
|
+
WHEN lower(slug) = 'codex-stabilizer' THEN 10.0
|
|
245
|
+
WHEN lower(slug) = 'gemini-consultant' THEN 15.0
|
|
246
|
+
WHEN lower(slug) = 'codex-test-lead' THEN 10.0
|
|
247
|
+
WHEN lower(slug) = 'gemini-scribe' THEN 2.5
|
|
248
|
+
WHEN lower(slug) = 'gemini-stable' THEN 18.0
|
|
249
|
+
WHEN lower(slug) = 'glm-hotfix' THEN 2.2
|
|
250
|
+
WHEN lower(slug) = 'gemini-architect' THEN 3.0
|
|
251
|
+
WHEN lower(slug) = 'gateway-router' THEN 14.0
|
|
252
|
+
WHEN lower(slug) = 'codex-architect' THEN 14.0
|
|
253
|
+
WHEN lower(slug) = 'glm-worker' THEN 2.2
|
|
254
|
+
WHEN lower(slug) = 'devstral-local' THEN 0
|
|
255
|
+
WHEN lower(slug) = 'gpt-oss-qa' THEN 0
|
|
256
|
+
WHEN lower(adapter) LIKE 'ollama%' OR lower(adapter) = 'local-model' OR lower(adapter) = 'qa-cli' THEN 0
|
|
257
|
+
WHEN lower(default_model) LIKE '%gpt-5.2%' OR lower(slug) LIKE '%gpt-5.2%' THEN 14.0
|
|
258
|
+
WHEN lower(default_model) LIKE '%glm-4.7%' OR lower(slug) LIKE '%glm-4.7%' THEN 2.2
|
|
259
|
+
WHEN lower(default_model) LIKE '%gpt-5.1%' AND (lower(default_model) LIKE '%codex%' OR lower(slug) LIKE '%codex%') THEN 10.0
|
|
260
|
+
WHEN lower(default_model) LIKE '%gemini-3-pro%' OR lower(slug) LIKE '%gemini-3-pro%' THEN 18.0
|
|
261
|
+
WHEN lower(default_model) LIKE '%devstral%' OR lower(slug) LIKE '%devstral%' THEN 0
|
|
262
|
+
ELSE NULL
|
|
263
|
+
END
|
|
264
|
+
)
|
|
265
|
+
WHERE rating IS NULL OR reasoning_rating IS NULL OR best_usage IS NULL OR cost_per_million IS NULL;
|
|
266
|
+
`);
|
|
267
|
+
const workspaceDefaultsInfo = await db.all("PRAGMA table_info(workspace_defaults)");
|
|
268
|
+
const hasWorkspaceId = workspaceDefaultsInfo.some((col) => col.name === "workspace_id");
|
|
269
|
+
const hasWorkspace = workspaceDefaultsInfo.some((col) => col.name === "workspace");
|
|
270
|
+
const hasQaProfile = workspaceDefaultsInfo.some((col) => col.name === "qa_profile");
|
|
271
|
+
const hasDocdexScope = workspaceDefaultsInfo.some((col) => col.name === "docdex_scope");
|
|
272
|
+
// Migrate legacy workspace_defaults schema: workspace -> workspace_id, default_agent -> agent_id, add command_name.
|
|
273
|
+
if (!hasWorkspaceId) {
|
|
274
|
+
if (hasWorkspace) {
|
|
275
|
+
await db.exec("ALTER TABLE workspace_defaults RENAME TO workspace_defaults_legacy");
|
|
276
|
+
await db.exec(`
|
|
277
|
+
CREATE TABLE workspace_defaults (
|
|
278
|
+
workspace_id TEXT NOT NULL,
|
|
279
|
+
command_name TEXT NOT NULL,
|
|
280
|
+
agent_id TEXT NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
|
|
281
|
+
qa_profile TEXT,
|
|
282
|
+
docdex_scope TEXT,
|
|
283
|
+
updated_at TEXT NOT NULL,
|
|
284
|
+
PRIMARY KEY (workspace_id, command_name)
|
|
285
|
+
);
|
|
286
|
+
`);
|
|
287
|
+
const legacyRows = await db.all("SELECT workspace, default_agent, qa_profile, docdex_scope, updated_at FROM workspace_defaults_legacy");
|
|
288
|
+
for (const row of legacyRows) {
|
|
289
|
+
await db.run(`INSERT OR IGNORE INTO workspace_defaults (workspace_id, command_name, agent_id, qa_profile, docdex_scope, updated_at)
|
|
290
|
+
VALUES (?, ?, ?, ?, ?, ?)`, row.workspace, "default", row.default_agent, row.qa_profile ?? null, row.docdex_scope ?? null, row.updated_at ?? new Date().toISOString());
|
|
291
|
+
}
|
|
292
|
+
await db.exec("DROP TABLE workspace_defaults_legacy");
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
// If the table exists but has an unknown shape, reset to the expected schema.
|
|
296
|
+
await db.exec("DROP TABLE IF EXISTS workspace_defaults");
|
|
297
|
+
await db.exec(`
|
|
298
|
+
CREATE TABLE IF NOT EXISTS workspace_defaults (
|
|
299
|
+
workspace_id TEXT NOT NULL,
|
|
300
|
+
command_name TEXT NOT NULL,
|
|
301
|
+
agent_id TEXT NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
|
|
302
|
+
qa_profile TEXT,
|
|
303
|
+
docdex_scope TEXT,
|
|
304
|
+
updated_at TEXT NOT NULL,
|
|
305
|
+
PRIMARY KEY (workspace_id, command_name)
|
|
306
|
+
);
|
|
307
|
+
`);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
if (!hasQaProfile) {
|
|
312
|
+
await db.exec("ALTER TABLE workspace_defaults ADD COLUMN qa_profile TEXT");
|
|
313
|
+
}
|
|
314
|
+
if (!hasDocdexScope) {
|
|
315
|
+
await db.exec("ALTER TABLE workspace_defaults ADD COLUMN docdex_scope TEXT");
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Database } from "sqlite";
|
|
2
|
+
/**
|
|
3
|
+
* Workspace database migrations for the local `.mcoda/mcoda.db` file.
|
|
4
|
+
* The schema matches the planning/task model defined in the SDS.
|
|
5
|
+
*/
|
|
6
|
+
export declare class WorkspaceMigrations {
|
|
7
|
+
static run(db: Database): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=WorkspaceMigrations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkspaceMigrations.d.ts","sourceRoot":"","sources":["../../../src/migrations/workspace/WorkspaceMigrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC;;;GAGG;AACH,qBAAa,mBAAmB;WACjB,GAAG,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAgP9C"}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace database migrations for the local `.mcoda/mcoda.db` file.
|
|
3
|
+
* The schema matches the planning/task model defined in the SDS.
|
|
4
|
+
*/
|
|
5
|
+
export class WorkspaceMigrations {
|
|
6
|
+
static async run(db) {
|
|
7
|
+
await db.exec(`
|
|
8
|
+
PRAGMA foreign_keys = ON;
|
|
9
|
+
|
|
10
|
+
-- Create tables idempotently to avoid wiping existing workspace data.
|
|
11
|
+
CREATE TABLE IF NOT EXISTS projects (
|
|
12
|
+
id TEXT PRIMARY KEY,
|
|
13
|
+
key TEXT NOT NULL UNIQUE,
|
|
14
|
+
name TEXT,
|
|
15
|
+
description TEXT,
|
|
16
|
+
metadata_json TEXT,
|
|
17
|
+
created_at TEXT NOT NULL,
|
|
18
|
+
updated_at TEXT NOT NULL
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
CREATE TABLE IF NOT EXISTS epics (
|
|
22
|
+
id TEXT PRIMARY KEY,
|
|
23
|
+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
24
|
+
key TEXT NOT NULL,
|
|
25
|
+
title TEXT NOT NULL,
|
|
26
|
+
description TEXT,
|
|
27
|
+
story_points_total REAL,
|
|
28
|
+
priority INTEGER,
|
|
29
|
+
metadata_json TEXT,
|
|
30
|
+
created_at TEXT NOT NULL,
|
|
31
|
+
updated_at TEXT NOT NULL,
|
|
32
|
+
UNIQUE(project_id, key)
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
CREATE TABLE IF NOT EXISTS user_stories (
|
|
36
|
+
id TEXT PRIMARY KEY,
|
|
37
|
+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
38
|
+
epic_id TEXT NOT NULL REFERENCES epics(id) ON DELETE CASCADE,
|
|
39
|
+
key TEXT NOT NULL,
|
|
40
|
+
title TEXT NOT NULL,
|
|
41
|
+
description TEXT,
|
|
42
|
+
acceptance_criteria TEXT,
|
|
43
|
+
story_points_total REAL,
|
|
44
|
+
priority INTEGER,
|
|
45
|
+
metadata_json TEXT,
|
|
46
|
+
created_at TEXT NOT NULL,
|
|
47
|
+
updated_at TEXT NOT NULL,
|
|
48
|
+
UNIQUE(epic_id, key)
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
CREATE TABLE IF NOT EXISTS tasks (
|
|
52
|
+
id TEXT PRIMARY KEY,
|
|
53
|
+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
54
|
+
epic_id TEXT NOT NULL REFERENCES epics(id) ON DELETE CASCADE,
|
|
55
|
+
user_story_id TEXT NOT NULL REFERENCES user_stories(id) ON DELETE CASCADE,
|
|
56
|
+
key TEXT NOT NULL,
|
|
57
|
+
title TEXT NOT NULL,
|
|
58
|
+
description TEXT,
|
|
59
|
+
type TEXT,
|
|
60
|
+
status TEXT NOT NULL,
|
|
61
|
+
story_points REAL,
|
|
62
|
+
priority INTEGER,
|
|
63
|
+
assigned_agent_id TEXT,
|
|
64
|
+
assignee_human TEXT,
|
|
65
|
+
vcs_branch TEXT,
|
|
66
|
+
vcs_base_branch TEXT,
|
|
67
|
+
vcs_last_commit_sha TEXT,
|
|
68
|
+
metadata_json TEXT,
|
|
69
|
+
openapi_version_at_creation TEXT,
|
|
70
|
+
created_at TEXT NOT NULL,
|
|
71
|
+
updated_at TEXT NOT NULL,
|
|
72
|
+
UNIQUE(user_story_id, key)
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
CREATE TABLE IF NOT EXISTS task_dependencies (
|
|
76
|
+
id TEXT PRIMARY KEY,
|
|
77
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
78
|
+
depends_on_task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
79
|
+
relation_type TEXT NOT NULL,
|
|
80
|
+
created_at TEXT NOT NULL,
|
|
81
|
+
updated_at TEXT NOT NULL,
|
|
82
|
+
UNIQUE(task_id, depends_on_task_id, relation_type)
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
CREATE TABLE IF NOT EXISTS jobs (
|
|
86
|
+
id TEXT PRIMARY KEY,
|
|
87
|
+
workspace_id TEXT NOT NULL,
|
|
88
|
+
type TEXT NOT NULL,
|
|
89
|
+
state TEXT NOT NULL,
|
|
90
|
+
command_name TEXT,
|
|
91
|
+
payload_json TEXT,
|
|
92
|
+
total_items INTEGER,
|
|
93
|
+
processed_items INTEGER,
|
|
94
|
+
last_checkpoint TEXT,
|
|
95
|
+
created_at TEXT NOT NULL,
|
|
96
|
+
updated_at TEXT NOT NULL,
|
|
97
|
+
completed_at TEXT,
|
|
98
|
+
error_summary TEXT
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
CREATE TABLE IF NOT EXISTS command_runs (
|
|
102
|
+
id TEXT PRIMARY KEY,
|
|
103
|
+
workspace_id TEXT NOT NULL,
|
|
104
|
+
command_name TEXT NOT NULL,
|
|
105
|
+
job_id TEXT REFERENCES jobs(id) ON DELETE SET NULL,
|
|
106
|
+
task_ids_json TEXT,
|
|
107
|
+
git_branch TEXT,
|
|
108
|
+
git_base_branch TEXT,
|
|
109
|
+
started_at TEXT NOT NULL,
|
|
110
|
+
completed_at TEXT,
|
|
111
|
+
status TEXT NOT NULL,
|
|
112
|
+
error_summary TEXT,
|
|
113
|
+
duration_seconds REAL,
|
|
114
|
+
sp_processed REAL
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
CREATE TABLE IF NOT EXISTS task_runs (
|
|
118
|
+
id TEXT PRIMARY KEY,
|
|
119
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
120
|
+
command TEXT NOT NULL,
|
|
121
|
+
job_id TEXT REFERENCES jobs(id) ON DELETE SET NULL,
|
|
122
|
+
command_run_id TEXT REFERENCES command_runs(id) ON DELETE SET NULL,
|
|
123
|
+
agent_id TEXT,
|
|
124
|
+
status TEXT NOT NULL,
|
|
125
|
+
started_at TEXT NOT NULL,
|
|
126
|
+
finished_at TEXT,
|
|
127
|
+
story_points_at_run REAL,
|
|
128
|
+
sp_per_hour_effective REAL,
|
|
129
|
+
git_branch TEXT,
|
|
130
|
+
git_base_branch TEXT,
|
|
131
|
+
git_commit_sha TEXT,
|
|
132
|
+
run_context_json TEXT
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
CREATE TABLE IF NOT EXISTS task_locks (
|
|
136
|
+
task_id TEXT PRIMARY KEY REFERENCES tasks(id) ON DELETE CASCADE,
|
|
137
|
+
task_run_id TEXT NOT NULL REFERENCES task_runs(id) ON DELETE CASCADE,
|
|
138
|
+
job_id TEXT,
|
|
139
|
+
acquired_at TEXT NOT NULL,
|
|
140
|
+
expires_at TEXT NOT NULL
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
CREATE INDEX IF NOT EXISTS idx_task_locks_expires_at ON task_locks(expires_at);
|
|
144
|
+
|
|
145
|
+
CREATE TABLE IF NOT EXISTS task_qa_runs (
|
|
146
|
+
id TEXT PRIMARY KEY,
|
|
147
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
148
|
+
task_run_id TEXT REFERENCES task_runs(id) ON DELETE SET NULL,
|
|
149
|
+
job_id TEXT REFERENCES jobs(id) ON DELETE SET NULL,
|
|
150
|
+
command_run_id TEXT REFERENCES command_runs(id) ON DELETE SET NULL,
|
|
151
|
+
agent_id TEXT,
|
|
152
|
+
model_name TEXT,
|
|
153
|
+
source TEXT NOT NULL,
|
|
154
|
+
mode TEXT,
|
|
155
|
+
profile_name TEXT,
|
|
156
|
+
runner TEXT,
|
|
157
|
+
raw_outcome TEXT,
|
|
158
|
+
recommendation TEXT,
|
|
159
|
+
evidence_url TEXT,
|
|
160
|
+
artifacts_json TEXT,
|
|
161
|
+
raw_result_json TEXT,
|
|
162
|
+
started_at TEXT,
|
|
163
|
+
finished_at TEXT,
|
|
164
|
+
metadata_json TEXT,
|
|
165
|
+
created_at TEXT NOT NULL
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
CREATE TABLE IF NOT EXISTS task_logs (
|
|
169
|
+
id TEXT PRIMARY KEY,
|
|
170
|
+
task_run_id TEXT NOT NULL REFERENCES task_runs(id) ON DELETE CASCADE,
|
|
171
|
+
sequence INTEGER NOT NULL,
|
|
172
|
+
timestamp TEXT NOT NULL,
|
|
173
|
+
level TEXT,
|
|
174
|
+
source TEXT,
|
|
175
|
+
message TEXT,
|
|
176
|
+
details_json TEXT,
|
|
177
|
+
UNIQUE(task_run_id, sequence)
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
CREATE TABLE IF NOT EXISTS task_revisions (
|
|
181
|
+
id TEXT PRIMARY KEY,
|
|
182
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
183
|
+
job_id TEXT,
|
|
184
|
+
command_run_id TEXT,
|
|
185
|
+
snapshot_before_json TEXT,
|
|
186
|
+
snapshot_after_json TEXT,
|
|
187
|
+
created_at TEXT NOT NULL
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
CREATE TABLE IF NOT EXISTS task_comments (
|
|
191
|
+
id TEXT PRIMARY KEY,
|
|
192
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
193
|
+
task_run_id TEXT REFERENCES task_runs(id) ON DELETE SET NULL,
|
|
194
|
+
job_id TEXT REFERENCES jobs(id) ON DELETE SET NULL,
|
|
195
|
+
source_command TEXT NOT NULL,
|
|
196
|
+
author_type TEXT NOT NULL,
|
|
197
|
+
author_agent_id TEXT,
|
|
198
|
+
category TEXT,
|
|
199
|
+
file TEXT,
|
|
200
|
+
line INTEGER,
|
|
201
|
+
path_hint TEXT,
|
|
202
|
+
body TEXT NOT NULL,
|
|
203
|
+
metadata_json TEXT,
|
|
204
|
+
created_at TEXT NOT NULL,
|
|
205
|
+
resolved_at TEXT,
|
|
206
|
+
resolved_by TEXT
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
CREATE TABLE IF NOT EXISTS task_reviews (
|
|
210
|
+
id TEXT PRIMARY KEY,
|
|
211
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
212
|
+
job_id TEXT REFERENCES jobs(id) ON DELETE SET NULL,
|
|
213
|
+
agent_id TEXT,
|
|
214
|
+
model_name TEXT,
|
|
215
|
+
decision TEXT NOT NULL,
|
|
216
|
+
summary TEXT,
|
|
217
|
+
findings_json TEXT,
|
|
218
|
+
test_recommendations_json TEXT,
|
|
219
|
+
metadata_json TEXT,
|
|
220
|
+
created_at TEXT NOT NULL,
|
|
221
|
+
created_by TEXT
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
CREATE TABLE IF NOT EXISTS token_usage (
|
|
225
|
+
id TEXT PRIMARY KEY,
|
|
226
|
+
workspace_id TEXT NOT NULL,
|
|
227
|
+
agent_id TEXT,
|
|
228
|
+
model_name TEXT,
|
|
229
|
+
job_id TEXT REFERENCES jobs(id) ON DELETE SET NULL,
|
|
230
|
+
command_run_id TEXT REFERENCES command_runs(id) ON DELETE SET NULL,
|
|
231
|
+
task_run_id TEXT REFERENCES task_runs(id) ON DELETE SET NULL,
|
|
232
|
+
task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
|
|
233
|
+
project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
|
|
234
|
+
epic_id TEXT REFERENCES epics(id) ON DELETE SET NULL,
|
|
235
|
+
user_story_id TEXT REFERENCES user_stories(id) ON DELETE SET NULL,
|
|
236
|
+
tokens_prompt INTEGER,
|
|
237
|
+
tokens_completion INTEGER,
|
|
238
|
+
tokens_total INTEGER,
|
|
239
|
+
cost_estimate REAL,
|
|
240
|
+
duration_seconds REAL,
|
|
241
|
+
timestamp TEXT NOT NULL,
|
|
242
|
+
metadata_json TEXT
|
|
243
|
+
);
|
|
244
|
+
`);
|
|
245
|
+
}
|
|
246
|
+
}
|