bopodev-db 0.1.27 → 0.1.29
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/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-lint.log +1 -1
- package/.turbo/turbo-typecheck.log +1 -1
- package/dist/bootstrap.d.ts +3 -3
- package/dist/client.d.ts +34 -6
- package/dist/index.d.ts +2 -0
- package/dist/migrate.d.ts +1 -0
- package/dist/ping.d.ts +3 -0
- package/dist/repositories/companies.d.ts +32 -0
- package/dist/repositories/helpers.d.ts +16 -0
- package/dist/repositories/index.d.ts +3 -0
- package/dist/repositories/legacy.d.ts +1415 -0
- package/dist/repositories.d.ts +3 -36
- package/dist/schema.d.ts +218 -0
- package/drizzle.config.ts +10 -0
- package/package.json +12 -3
- package/src/bootstrap.ts +9 -595
- package/src/client.ts +634 -9
- package/src/default-paths.ts +1 -1
- package/src/index.ts +2 -0
- package/src/migrate.ts +20 -0
- package/src/migrations/0000_initial.sql +389 -0
- package/src/migrations/0001_issues_external_link.sql +1 -0
- package/src/migrations/0002_issues_goal_goals_owner_agent.sql +2 -0
- package/src/migrations/0003_issue_goals_junction.sql +12 -0
- package/src/migrations/meta/_journal.json +34 -0
- package/src/ping.ts +7 -0
- package/src/repositories/companies.ts +41 -0
- package/src/repositories/helpers.ts +104 -0
- package/src/repositories/index.ts +3 -0
- package/src/{repositories.ts → repositories/legacy.ts} +150 -123
- package/src/schema.ts +22 -0
package/src/bootstrap.ts
CHANGED
|
@@ -1,598 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createDb } from "./client";
|
|
1
|
+
import { applyDatabaseMigrations, createDb } from "./client";
|
|
3
2
|
|
|
4
3
|
export async function bootstrapDatabase(dbPath?: string) {
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
);
|
|
14
|
-
`);
|
|
15
|
-
await db.execute(sql`
|
|
16
|
-
CREATE TABLE IF NOT EXISTS projects (
|
|
17
|
-
id TEXT PRIMARY KEY,
|
|
18
|
-
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
19
|
-
name TEXT NOT NULL,
|
|
20
|
-
description TEXT,
|
|
21
|
-
status TEXT NOT NULL DEFAULT 'planned',
|
|
22
|
-
planned_start_at TIMESTAMP,
|
|
23
|
-
monthly_budget_usd NUMERIC(12, 4) NOT NULL DEFAULT 100,
|
|
24
|
-
used_budget_usd NUMERIC(12, 4) NOT NULL DEFAULT 0,
|
|
25
|
-
budget_window_start_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
26
|
-
execution_workspace_policy TEXT,
|
|
27
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
28
|
-
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
29
|
-
);
|
|
30
|
-
`);
|
|
31
|
-
await db.execute(sql`
|
|
32
|
-
ALTER TABLE projects
|
|
33
|
-
ADD COLUMN IF NOT EXISTS status TEXT NOT NULL DEFAULT 'planned';
|
|
34
|
-
`);
|
|
35
|
-
await db.execute(sql`
|
|
36
|
-
ALTER TABLE projects
|
|
37
|
-
ADD COLUMN IF NOT EXISTS planned_start_at TIMESTAMP;
|
|
38
|
-
`);
|
|
39
|
-
await db.execute(sql`
|
|
40
|
-
ALTER TABLE projects
|
|
41
|
-
ADD COLUMN IF NOT EXISTS execution_workspace_policy TEXT;
|
|
42
|
-
`);
|
|
43
|
-
await db.execute(sql`
|
|
44
|
-
ALTER TABLE projects
|
|
45
|
-
ADD COLUMN IF NOT EXISTS monthly_budget_usd NUMERIC(12, 4) NOT NULL DEFAULT 100;
|
|
46
|
-
`);
|
|
47
|
-
await db.execute(sql`
|
|
48
|
-
ALTER TABLE projects
|
|
49
|
-
ADD COLUMN IF NOT EXISTS used_budget_usd NUMERIC(12, 4) NOT NULL DEFAULT 0;
|
|
50
|
-
`);
|
|
51
|
-
await db.execute(sql`
|
|
52
|
-
ALTER TABLE projects
|
|
53
|
-
ADD COLUMN IF NOT EXISTS budget_window_start_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
|
|
54
|
-
`);
|
|
55
|
-
await db.execute(sql`
|
|
56
|
-
ALTER TABLE projects
|
|
57
|
-
ADD COLUMN IF NOT EXISTS updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
|
|
58
|
-
`);
|
|
59
|
-
await db.execute(sql`
|
|
60
|
-
CREATE TABLE IF NOT EXISTS project_workspaces (
|
|
61
|
-
id TEXT PRIMARY KEY,
|
|
62
|
-
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
63
|
-
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
64
|
-
name TEXT NOT NULL,
|
|
65
|
-
cwd TEXT,
|
|
66
|
-
repo_url TEXT,
|
|
67
|
-
repo_ref TEXT,
|
|
68
|
-
is_primary BOOLEAN NOT NULL DEFAULT false,
|
|
69
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
70
|
-
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
71
|
-
);
|
|
72
|
-
`);
|
|
73
|
-
await db.execute(sql`
|
|
74
|
-
CREATE INDEX IF NOT EXISTS idx_project_workspaces_company_project
|
|
75
|
-
ON project_workspaces (company_id, project_id, is_primary DESC, created_at ASC);
|
|
76
|
-
`);
|
|
77
|
-
await db.execute(sql`
|
|
78
|
-
CREATE TABLE IF NOT EXISTS goals (
|
|
79
|
-
id TEXT PRIMARY KEY,
|
|
80
|
-
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
81
|
-
project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
|
|
82
|
-
parent_goal_id TEXT,
|
|
83
|
-
level TEXT NOT NULL,
|
|
84
|
-
title TEXT NOT NULL,
|
|
85
|
-
description TEXT,
|
|
86
|
-
status TEXT NOT NULL DEFAULT 'draft',
|
|
87
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
88
|
-
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
89
|
-
);
|
|
90
|
-
`);
|
|
91
|
-
await db.execute(sql`
|
|
92
|
-
CREATE TABLE IF NOT EXISTS agents (
|
|
93
|
-
id TEXT PRIMARY KEY,
|
|
94
|
-
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
95
|
-
manager_agent_id TEXT,
|
|
96
|
-
role TEXT NOT NULL,
|
|
97
|
-
role_key TEXT,
|
|
98
|
-
title TEXT,
|
|
99
|
-
name TEXT NOT NULL,
|
|
100
|
-
provider_type TEXT NOT NULL,
|
|
101
|
-
status TEXT NOT NULL DEFAULT 'idle',
|
|
102
|
-
heartbeat_cron TEXT NOT NULL,
|
|
103
|
-
monthly_budget_usd NUMERIC(12, 4) NOT NULL DEFAULT 0,
|
|
104
|
-
used_budget_usd NUMERIC(12, 4) NOT NULL DEFAULT 0,
|
|
105
|
-
token_usage INTEGER NOT NULL DEFAULT 0,
|
|
106
|
-
can_hire_agents BOOLEAN NOT NULL DEFAULT false,
|
|
107
|
-
avatar_seed TEXT NOT NULL DEFAULT '',
|
|
108
|
-
runtime_command TEXT,
|
|
109
|
-
runtime_args_json TEXT NOT NULL DEFAULT '[]',
|
|
110
|
-
runtime_cwd TEXT,
|
|
111
|
-
runtime_env_json TEXT NOT NULL DEFAULT '{}',
|
|
112
|
-
runtime_model TEXT,
|
|
113
|
-
runtime_thinking_effort TEXT NOT NULL DEFAULT 'auto',
|
|
114
|
-
bootstrap_prompt TEXT,
|
|
115
|
-
runtime_timeout_sec INTEGER NOT NULL DEFAULT 0,
|
|
116
|
-
interrupt_grace_sec INTEGER NOT NULL DEFAULT 15,
|
|
117
|
-
run_policy_json TEXT NOT NULL DEFAULT '{}',
|
|
118
|
-
state_blob TEXT NOT NULL DEFAULT '{}',
|
|
119
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
120
|
-
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
121
|
-
);
|
|
122
|
-
`);
|
|
123
|
-
await db.execute(sql`
|
|
124
|
-
ALTER TABLE agents
|
|
125
|
-
ADD COLUMN IF NOT EXISTS avatar_seed TEXT NOT NULL DEFAULT '';
|
|
126
|
-
`);
|
|
127
|
-
await db.execute(sql`
|
|
128
|
-
ALTER TABLE agents
|
|
129
|
-
ADD COLUMN IF NOT EXISTS role_key TEXT;
|
|
130
|
-
`);
|
|
131
|
-
await db.execute(sql`
|
|
132
|
-
ALTER TABLE agents
|
|
133
|
-
ADD COLUMN IF NOT EXISTS title TEXT;
|
|
134
|
-
`);
|
|
135
|
-
await db.execute(sql`
|
|
136
|
-
ALTER TABLE agents
|
|
137
|
-
ADD COLUMN IF NOT EXISTS runtime_command TEXT;
|
|
138
|
-
`);
|
|
139
|
-
await db.execute(sql`
|
|
140
|
-
ALTER TABLE agents
|
|
141
|
-
ADD COLUMN IF NOT EXISTS runtime_args_json TEXT NOT NULL DEFAULT '[]';
|
|
142
|
-
`);
|
|
143
|
-
await db.execute(sql`
|
|
144
|
-
ALTER TABLE agents
|
|
145
|
-
ADD COLUMN IF NOT EXISTS runtime_cwd TEXT;
|
|
146
|
-
`);
|
|
147
|
-
await db.execute(sql`
|
|
148
|
-
ALTER TABLE agents
|
|
149
|
-
ADD COLUMN IF NOT EXISTS runtime_env_json TEXT NOT NULL DEFAULT '{}';
|
|
150
|
-
`);
|
|
151
|
-
await db.execute(sql`
|
|
152
|
-
ALTER TABLE agents
|
|
153
|
-
ADD COLUMN IF NOT EXISTS runtime_model TEXT;
|
|
154
|
-
`);
|
|
155
|
-
await db.execute(sql`
|
|
156
|
-
ALTER TABLE agents
|
|
157
|
-
ADD COLUMN IF NOT EXISTS runtime_thinking_effort TEXT NOT NULL DEFAULT 'auto';
|
|
158
|
-
`);
|
|
159
|
-
await db.execute(sql`
|
|
160
|
-
ALTER TABLE agents
|
|
161
|
-
ADD COLUMN IF NOT EXISTS bootstrap_prompt TEXT;
|
|
162
|
-
`);
|
|
163
|
-
await db.execute(sql`
|
|
164
|
-
ALTER TABLE agents
|
|
165
|
-
ADD COLUMN IF NOT EXISTS runtime_timeout_sec INTEGER NOT NULL DEFAULT 0;
|
|
166
|
-
`);
|
|
167
|
-
await db.execute(sql`
|
|
168
|
-
ALTER TABLE agents
|
|
169
|
-
ADD COLUMN IF NOT EXISTS interrupt_grace_sec INTEGER NOT NULL DEFAULT 15;
|
|
170
|
-
`);
|
|
171
|
-
await db.execute(sql`
|
|
172
|
-
ALTER TABLE agents
|
|
173
|
-
ADD COLUMN IF NOT EXISTS run_policy_json TEXT NOT NULL DEFAULT '{}';
|
|
174
|
-
`);
|
|
175
|
-
await db.execute(sql`
|
|
176
|
-
UPDATE agents
|
|
177
|
-
SET
|
|
178
|
-
runtime_command = COALESCE(runtime_command, state_blob::jsonb->'runtime'->>'command'),
|
|
179
|
-
runtime_args_json = CASE
|
|
180
|
-
WHEN runtime_args_json IS NULL OR btrim(runtime_args_json) = '' OR runtime_args_json = '[]'
|
|
181
|
-
THEN COALESCE((state_blob::jsonb->'runtime'->'args')::text, '[]')
|
|
182
|
-
ELSE runtime_args_json
|
|
183
|
-
END,
|
|
184
|
-
runtime_cwd = COALESCE(runtime_cwd, state_blob::jsonb->'runtime'->>'cwd'),
|
|
185
|
-
runtime_env_json = CASE
|
|
186
|
-
WHEN runtime_env_json IS NULL OR btrim(runtime_env_json) = '' OR runtime_env_json = '{}'
|
|
187
|
-
THEN COALESCE((state_blob::jsonb->'runtime'->'env')::text, '{}')
|
|
188
|
-
ELSE runtime_env_json
|
|
189
|
-
END,
|
|
190
|
-
runtime_timeout_sec = CASE
|
|
191
|
-
WHEN runtime_timeout_sec IS NULL OR runtime_timeout_sec = 0
|
|
192
|
-
THEN COALESCE(((state_blob::jsonb->'runtime'->>'timeoutMs')::int / 1000), 0)
|
|
193
|
-
ELSE runtime_timeout_sec
|
|
194
|
-
END
|
|
195
|
-
WHERE state_blob IS NOT NULL AND btrim(state_blob) <> '';
|
|
196
|
-
`);
|
|
197
|
-
await db.execute(sql`
|
|
198
|
-
CREATE TABLE IF NOT EXISTS issues (
|
|
199
|
-
id TEXT PRIMARY KEY,
|
|
200
|
-
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
201
|
-
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
202
|
-
parent_issue_id TEXT,
|
|
203
|
-
title TEXT NOT NULL,
|
|
204
|
-
body TEXT,
|
|
205
|
-
status TEXT NOT NULL DEFAULT 'todo',
|
|
206
|
-
priority TEXT NOT NULL DEFAULT 'none',
|
|
207
|
-
assignee_agent_id TEXT,
|
|
208
|
-
labels_json TEXT NOT NULL DEFAULT '[]',
|
|
209
|
-
tags_json TEXT NOT NULL DEFAULT '[]',
|
|
210
|
-
is_claimed BOOLEAN NOT NULL DEFAULT false,
|
|
211
|
-
claimed_by_heartbeat_run_id TEXT,
|
|
212
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
213
|
-
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
214
|
-
);
|
|
215
|
-
`);
|
|
216
|
-
await db.execute(sql`
|
|
217
|
-
CREATE TABLE IF NOT EXISTS issue_comments (
|
|
218
|
-
id TEXT PRIMARY KEY,
|
|
219
|
-
issue_id TEXT NOT NULL REFERENCES issues(id) ON DELETE CASCADE,
|
|
220
|
-
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
221
|
-
author_type TEXT NOT NULL,
|
|
222
|
-
author_id TEXT,
|
|
223
|
-
recipients_json TEXT NOT NULL DEFAULT '[]',
|
|
224
|
-
run_id TEXT,
|
|
225
|
-
body TEXT NOT NULL,
|
|
226
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
227
|
-
);
|
|
228
|
-
`);
|
|
229
|
-
await db.execute(sql`
|
|
230
|
-
ALTER TABLE issue_comments
|
|
231
|
-
ADD COLUMN IF NOT EXISTS recipients_json TEXT NOT NULL DEFAULT '[]';
|
|
232
|
-
`);
|
|
233
|
-
await db.execute(sql`
|
|
234
|
-
ALTER TABLE issue_comments
|
|
235
|
-
ADD COLUMN IF NOT EXISTS run_id TEXT;
|
|
236
|
-
`);
|
|
237
|
-
await db.execute(sql`
|
|
238
|
-
CREATE TABLE IF NOT EXISTS issue_attachments (
|
|
239
|
-
id TEXT PRIMARY KEY,
|
|
240
|
-
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
241
|
-
issue_id TEXT NOT NULL REFERENCES issues(id) ON DELETE CASCADE,
|
|
242
|
-
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
243
|
-
file_name TEXT NOT NULL,
|
|
244
|
-
mime_type TEXT,
|
|
245
|
-
file_size_bytes INTEGER NOT NULL,
|
|
246
|
-
relative_path TEXT NOT NULL,
|
|
247
|
-
uploaded_by_actor_type TEXT NOT NULL DEFAULT 'human',
|
|
248
|
-
uploaded_by_actor_id TEXT,
|
|
249
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
250
|
-
);
|
|
251
|
-
`);
|
|
252
|
-
await db.execute(sql`
|
|
253
|
-
CREATE TABLE IF NOT EXISTS activity_logs (
|
|
254
|
-
id TEXT PRIMARY KEY,
|
|
255
|
-
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
256
|
-
issue_id TEXT REFERENCES issues(id) ON DELETE SET NULL,
|
|
257
|
-
actor_type TEXT NOT NULL,
|
|
258
|
-
actor_id TEXT,
|
|
259
|
-
event_type TEXT NOT NULL,
|
|
260
|
-
payload_json TEXT NOT NULL DEFAULT '{}',
|
|
261
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
262
|
-
);
|
|
263
|
-
`);
|
|
264
|
-
await db.execute(sql`
|
|
265
|
-
CREATE TABLE IF NOT EXISTS heartbeat_runs (
|
|
266
|
-
id TEXT PRIMARY KEY,
|
|
267
|
-
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
268
|
-
agent_id TEXT NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
|
|
269
|
-
status TEXT NOT NULL DEFAULT 'started',
|
|
270
|
-
started_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
271
|
-
finished_at TIMESTAMP,
|
|
272
|
-
message TEXT
|
|
273
|
-
);
|
|
274
|
-
`);
|
|
275
|
-
await db.execute(sql`
|
|
276
|
-
CREATE TABLE IF NOT EXISTS heartbeat_run_queue (
|
|
277
|
-
id TEXT PRIMARY KEY,
|
|
278
|
-
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
279
|
-
agent_id TEXT NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
|
|
280
|
-
job_type TEXT NOT NULL,
|
|
281
|
-
payload_json TEXT NOT NULL DEFAULT '{}',
|
|
282
|
-
status TEXT NOT NULL DEFAULT 'pending',
|
|
283
|
-
priority INTEGER NOT NULL DEFAULT 100,
|
|
284
|
-
idempotency_key TEXT,
|
|
285
|
-
available_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
286
|
-
attempt_count INTEGER NOT NULL DEFAULT 0,
|
|
287
|
-
max_attempts INTEGER NOT NULL DEFAULT 10,
|
|
288
|
-
last_error TEXT,
|
|
289
|
-
started_at TIMESTAMP,
|
|
290
|
-
finished_at TIMESTAMP,
|
|
291
|
-
heartbeat_run_id TEXT REFERENCES heartbeat_runs(id) ON DELETE SET NULL,
|
|
292
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
293
|
-
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
294
|
-
);
|
|
295
|
-
`);
|
|
296
|
-
await db.execute(sql`
|
|
297
|
-
ALTER TABLE heartbeat_run_queue
|
|
298
|
-
ADD COLUMN IF NOT EXISTS idempotency_key TEXT;
|
|
299
|
-
`);
|
|
300
|
-
await db.execute(sql`
|
|
301
|
-
ALTER TABLE heartbeat_run_queue
|
|
302
|
-
ADD COLUMN IF NOT EXISTS heartbeat_run_id TEXT REFERENCES heartbeat_runs(id) ON DELETE SET NULL;
|
|
303
|
-
`);
|
|
304
|
-
await db.execute(sql`
|
|
305
|
-
CREATE TABLE IF NOT EXISTS heartbeat_run_messages (
|
|
306
|
-
id TEXT PRIMARY KEY,
|
|
307
|
-
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
308
|
-
run_id TEXT NOT NULL REFERENCES heartbeat_runs(id) ON DELETE CASCADE,
|
|
309
|
-
sequence INTEGER NOT NULL,
|
|
310
|
-
kind TEXT NOT NULL,
|
|
311
|
-
label TEXT,
|
|
312
|
-
text TEXT,
|
|
313
|
-
payload_json TEXT,
|
|
314
|
-
signal_level TEXT,
|
|
315
|
-
group_key TEXT,
|
|
316
|
-
source TEXT,
|
|
317
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
318
|
-
);
|
|
319
|
-
`);
|
|
320
|
-
await db.execute(sql`
|
|
321
|
-
ALTER TABLE heartbeat_run_messages
|
|
322
|
-
ADD COLUMN IF NOT EXISTS signal_level TEXT;
|
|
323
|
-
`);
|
|
324
|
-
await db.execute(sql`
|
|
325
|
-
ALTER TABLE heartbeat_run_messages
|
|
326
|
-
ADD COLUMN IF NOT EXISTS group_key TEXT;
|
|
327
|
-
`);
|
|
328
|
-
await db.execute(sql`
|
|
329
|
-
ALTER TABLE heartbeat_run_messages
|
|
330
|
-
ADD COLUMN IF NOT EXISTS source TEXT;
|
|
331
|
-
`);
|
|
332
|
-
await db.execute(sql`
|
|
333
|
-
CREATE TABLE IF NOT EXISTS approval_requests (
|
|
334
|
-
id TEXT PRIMARY KEY,
|
|
335
|
-
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
336
|
-
requested_by_agent_id TEXT,
|
|
337
|
-
action TEXT NOT NULL,
|
|
338
|
-
payload_json TEXT NOT NULL DEFAULT '{}',
|
|
339
|
-
status TEXT NOT NULL DEFAULT 'pending',
|
|
340
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
341
|
-
resolved_at TIMESTAMP
|
|
342
|
-
);
|
|
343
|
-
`);
|
|
344
|
-
await db.execute(sql`
|
|
345
|
-
CREATE TABLE IF NOT EXISTS approval_inbox_states (
|
|
346
|
-
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
347
|
-
actor_id TEXT NOT NULL,
|
|
348
|
-
approval_id TEXT NOT NULL REFERENCES approval_requests(id) ON DELETE CASCADE,
|
|
349
|
-
seen_at TIMESTAMP,
|
|
350
|
-
dismissed_at TIMESTAMP,
|
|
351
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
352
|
-
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
353
|
-
PRIMARY KEY (company_id, actor_id, approval_id)
|
|
354
|
-
);
|
|
355
|
-
`);
|
|
356
|
-
await db.execute(sql`
|
|
357
|
-
CREATE TABLE IF NOT EXISTS attention_inbox_states (
|
|
358
|
-
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
359
|
-
actor_id TEXT NOT NULL,
|
|
360
|
-
item_key TEXT NOT NULL,
|
|
361
|
-
seen_at TIMESTAMP,
|
|
362
|
-
acknowledged_at TIMESTAMP,
|
|
363
|
-
dismissed_at TIMESTAMP,
|
|
364
|
-
resolved_at TIMESTAMP,
|
|
365
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
366
|
-
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
367
|
-
PRIMARY KEY (company_id, actor_id, item_key)
|
|
368
|
-
);
|
|
369
|
-
`);
|
|
370
|
-
await db.execute(sql`
|
|
371
|
-
CREATE TABLE IF NOT EXISTS cost_ledger (
|
|
372
|
-
id TEXT PRIMARY KEY,
|
|
373
|
-
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
374
|
-
run_id TEXT REFERENCES heartbeat_runs(id) ON DELETE SET NULL,
|
|
375
|
-
project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
|
|
376
|
-
issue_id TEXT REFERENCES issues(id) ON DELETE SET NULL,
|
|
377
|
-
agent_id TEXT REFERENCES agents(id) ON DELETE SET NULL,
|
|
378
|
-
provider_type TEXT NOT NULL,
|
|
379
|
-
runtime_model_id TEXT,
|
|
380
|
-
pricing_provider_type TEXT,
|
|
381
|
-
pricing_model_id TEXT,
|
|
382
|
-
pricing_source TEXT,
|
|
383
|
-
token_input INTEGER NOT NULL DEFAULT 0,
|
|
384
|
-
token_output INTEGER NOT NULL DEFAULT 0,
|
|
385
|
-
usd_cost NUMERIC(12, 6) NOT NULL DEFAULT 0,
|
|
386
|
-
usd_cost_status TEXT,
|
|
387
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
388
|
-
);
|
|
389
|
-
`);
|
|
390
|
-
await db.execute(sql`
|
|
391
|
-
ALTER TABLE cost_ledger
|
|
392
|
-
ADD COLUMN IF NOT EXISTS run_id TEXT REFERENCES heartbeat_runs(id) ON DELETE SET NULL;
|
|
393
|
-
`);
|
|
394
|
-
await db.execute(sql`
|
|
395
|
-
ALTER TABLE cost_ledger
|
|
396
|
-
ADD COLUMN IF NOT EXISTS runtime_model_id TEXT;
|
|
397
|
-
`);
|
|
398
|
-
await db.execute(sql`
|
|
399
|
-
ALTER TABLE cost_ledger
|
|
400
|
-
ADD COLUMN IF NOT EXISTS pricing_provider_type TEXT;
|
|
401
|
-
`);
|
|
402
|
-
await db.execute(sql`
|
|
403
|
-
ALTER TABLE cost_ledger
|
|
404
|
-
ADD COLUMN IF NOT EXISTS pricing_model_id TEXT;
|
|
405
|
-
`);
|
|
406
|
-
await db.execute(sql`
|
|
407
|
-
ALTER TABLE cost_ledger
|
|
408
|
-
ADD COLUMN IF NOT EXISTS pricing_source TEXT;
|
|
409
|
-
`);
|
|
410
|
-
await db.execute(sql`
|
|
411
|
-
ALTER TABLE cost_ledger
|
|
412
|
-
ADD COLUMN IF NOT EXISTS usd_cost_status TEXT;
|
|
413
|
-
`);
|
|
414
|
-
await db.execute(sql`
|
|
415
|
-
DROP TABLE IF EXISTS model_pricing;
|
|
416
|
-
`);
|
|
417
|
-
await db.execute(sql`
|
|
418
|
-
CREATE TABLE IF NOT EXISTS audit_events (
|
|
419
|
-
id TEXT PRIMARY KEY,
|
|
420
|
-
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
421
|
-
actor_type TEXT NOT NULL,
|
|
422
|
-
actor_id TEXT,
|
|
423
|
-
event_type TEXT NOT NULL,
|
|
424
|
-
entity_type TEXT NOT NULL,
|
|
425
|
-
entity_id TEXT NOT NULL,
|
|
426
|
-
correlation_id TEXT,
|
|
427
|
-
payload_json TEXT NOT NULL DEFAULT '{}',
|
|
428
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
429
|
-
);
|
|
430
|
-
`);
|
|
431
|
-
await db.execute(sql`
|
|
432
|
-
CREATE TABLE IF NOT EXISTS plugins (
|
|
433
|
-
id TEXT PRIMARY KEY,
|
|
434
|
-
name TEXT NOT NULL,
|
|
435
|
-
version TEXT NOT NULL,
|
|
436
|
-
kind TEXT NOT NULL,
|
|
437
|
-
runtime_type TEXT NOT NULL,
|
|
438
|
-
runtime_entrypoint TEXT NOT NULL,
|
|
439
|
-
hooks_json TEXT NOT NULL DEFAULT '[]',
|
|
440
|
-
capabilities_json TEXT NOT NULL DEFAULT '[]',
|
|
441
|
-
manifest_json TEXT NOT NULL DEFAULT '{}',
|
|
442
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
443
|
-
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
444
|
-
);
|
|
445
|
-
`);
|
|
446
|
-
await db.execute(sql`
|
|
447
|
-
CREATE TABLE IF NOT EXISTS templates (
|
|
448
|
-
id TEXT PRIMARY KEY,
|
|
449
|
-
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
450
|
-
slug TEXT NOT NULL,
|
|
451
|
-
name TEXT NOT NULL,
|
|
452
|
-
description TEXT,
|
|
453
|
-
current_version TEXT NOT NULL DEFAULT '1.0.0',
|
|
454
|
-
status TEXT NOT NULL DEFAULT 'draft',
|
|
455
|
-
visibility TEXT NOT NULL DEFAULT 'company',
|
|
456
|
-
variables_json TEXT NOT NULL DEFAULT '[]',
|
|
457
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
458
|
-
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
459
|
-
);
|
|
460
|
-
`);
|
|
461
|
-
await db.execute(sql`
|
|
462
|
-
CREATE TABLE IF NOT EXISTS template_versions (
|
|
463
|
-
id TEXT PRIMARY KEY,
|
|
464
|
-
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
465
|
-
template_id TEXT NOT NULL REFERENCES templates(id) ON DELETE CASCADE,
|
|
466
|
-
version TEXT NOT NULL,
|
|
467
|
-
manifest_json TEXT NOT NULL DEFAULT '{}',
|
|
468
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
469
|
-
);
|
|
470
|
-
`);
|
|
471
|
-
await db.execute(sql`
|
|
472
|
-
CREATE TABLE IF NOT EXISTS template_installs (
|
|
473
|
-
id TEXT PRIMARY KEY,
|
|
474
|
-
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
475
|
-
template_id TEXT REFERENCES templates(id) ON DELETE SET NULL,
|
|
476
|
-
template_version_id TEXT REFERENCES template_versions(id) ON DELETE SET NULL,
|
|
477
|
-
status TEXT NOT NULL DEFAULT 'applied',
|
|
478
|
-
summary_json TEXT NOT NULL DEFAULT '{}',
|
|
479
|
-
variables_json TEXT NOT NULL DEFAULT '{}',
|
|
480
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
481
|
-
);
|
|
482
|
-
`);
|
|
483
|
-
await db.execute(sql`
|
|
484
|
-
CREATE TABLE IF NOT EXISTS plugin_configs (
|
|
485
|
-
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
486
|
-
plugin_id TEXT NOT NULL REFERENCES plugins(id) ON DELETE CASCADE,
|
|
487
|
-
enabled BOOLEAN NOT NULL DEFAULT false,
|
|
488
|
-
priority INTEGER NOT NULL DEFAULT 100,
|
|
489
|
-
config_json TEXT NOT NULL DEFAULT '{}',
|
|
490
|
-
granted_capabilities_json TEXT NOT NULL DEFAULT '[]',
|
|
491
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
492
|
-
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
493
|
-
PRIMARY KEY (company_id, plugin_id)
|
|
494
|
-
);
|
|
495
|
-
`);
|
|
496
|
-
await db.execute(sql`
|
|
497
|
-
CREATE TABLE IF NOT EXISTS plugin_runs (
|
|
498
|
-
id TEXT PRIMARY KEY,
|
|
499
|
-
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
500
|
-
run_id TEXT REFERENCES heartbeat_runs(id) ON DELETE CASCADE,
|
|
501
|
-
plugin_id TEXT NOT NULL REFERENCES plugins(id) ON DELETE CASCADE,
|
|
502
|
-
hook TEXT NOT NULL,
|
|
503
|
-
status TEXT NOT NULL,
|
|
504
|
-
duration_ms INTEGER NOT NULL DEFAULT 0,
|
|
505
|
-
error TEXT,
|
|
506
|
-
diagnostics_json TEXT NOT NULL DEFAULT '{}',
|
|
507
|
-
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
508
|
-
);
|
|
509
|
-
`);
|
|
510
|
-
await db.execute(sql`
|
|
511
|
-
CREATE TABLE IF NOT EXISTS agent_issue_labels (
|
|
512
|
-
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
513
|
-
issue_id TEXT NOT NULL REFERENCES issues(id) ON DELETE CASCADE,
|
|
514
|
-
label TEXT NOT NULL,
|
|
515
|
-
PRIMARY KEY (company_id, issue_id, label)
|
|
516
|
-
);
|
|
517
|
-
`);
|
|
518
|
-
await db.execute(sql`
|
|
519
|
-
CREATE INDEX IF NOT EXISTS idx_issues_company_status
|
|
520
|
-
ON issues (company_id, status, updated_at);
|
|
521
|
-
`);
|
|
522
|
-
await db.execute(sql`
|
|
523
|
-
CREATE INDEX IF NOT EXISTS idx_issues_assignee_claim_priority
|
|
524
|
-
ON issues (company_id, assignee_agent_id, is_claimed, status, priority, updated_at);
|
|
525
|
-
`);
|
|
526
|
-
await db.execute(sql`
|
|
527
|
-
CREATE INDEX IF NOT EXISTS idx_issue_attachments_company_issue
|
|
528
|
-
ON issue_attachments (company_id, issue_id, created_at DESC);
|
|
529
|
-
`);
|
|
530
|
-
await db.execute(sql`
|
|
531
|
-
CREATE INDEX IF NOT EXISTS idx_issue_attachments_company_project
|
|
532
|
-
ON issue_attachments (company_id, project_id, created_at DESC);
|
|
533
|
-
`);
|
|
534
|
-
await db.execute(sql`
|
|
535
|
-
CREATE INDEX IF NOT EXISTS idx_audit_events_company_created
|
|
536
|
-
ON audit_events (company_id, created_at DESC);
|
|
537
|
-
`);
|
|
538
|
-
await db.execute(sql`
|
|
539
|
-
CREATE INDEX IF NOT EXISTS idx_cost_ledger_company_created
|
|
540
|
-
ON cost_ledger (company_id, created_at DESC);
|
|
541
|
-
`);
|
|
542
|
-
await db.execute(sql`
|
|
543
|
-
CREATE UNIQUE INDEX IF NOT EXISTS idx_heartbeat_runs_single_started
|
|
544
|
-
ON heartbeat_runs (company_id, agent_id)
|
|
545
|
-
WHERE status = 'started';
|
|
546
|
-
`);
|
|
547
|
-
await db.execute(sql`
|
|
548
|
-
CREATE INDEX IF NOT EXISTS idx_heartbeat_run_queue_status_available_priority
|
|
549
|
-
ON heartbeat_run_queue (company_id, status, available_at ASC, priority ASC, created_at ASC);
|
|
550
|
-
`);
|
|
551
|
-
await db.execute(sql`
|
|
552
|
-
CREATE INDEX IF NOT EXISTS idx_heartbeat_run_queue_agent_status
|
|
553
|
-
ON heartbeat_run_queue (company_id, agent_id, status, available_at ASC, created_at ASC);
|
|
554
|
-
`);
|
|
555
|
-
await db.execute(sql`
|
|
556
|
-
CREATE UNIQUE INDEX IF NOT EXISTS idx_heartbeat_run_queue_idempotency
|
|
557
|
-
ON heartbeat_run_queue (company_id, agent_id, idempotency_key)
|
|
558
|
-
WHERE idempotency_key IS NOT NULL AND btrim(idempotency_key) <> '';
|
|
559
|
-
`);
|
|
560
|
-
await db.execute(sql`
|
|
561
|
-
CREATE INDEX IF NOT EXISTS idx_heartbeat_run_messages_company_run_sequence
|
|
562
|
-
ON heartbeat_run_messages (company_id, run_id, sequence ASC);
|
|
563
|
-
`);
|
|
564
|
-
await db.execute(sql`
|
|
565
|
-
CREATE INDEX IF NOT EXISTS idx_heartbeat_run_messages_company_created
|
|
566
|
-
ON heartbeat_run_messages (company_id, created_at DESC);
|
|
567
|
-
`);
|
|
568
|
-
await db.execute(sql`
|
|
569
|
-
CREATE INDEX IF NOT EXISTS idx_approval_inbox_states_company_actor_updated
|
|
570
|
-
ON approval_inbox_states (company_id, actor_id, updated_at DESC);
|
|
571
|
-
`);
|
|
572
|
-
await db.execute(sql`
|
|
573
|
-
CREATE INDEX IF NOT EXISTS idx_attention_inbox_states_company_actor_updated
|
|
574
|
-
ON attention_inbox_states (company_id, actor_id, updated_at DESC);
|
|
575
|
-
`);
|
|
576
|
-
await db.execute(sql`
|
|
577
|
-
CREATE INDEX IF NOT EXISTS idx_plugin_configs_company_enabled_priority
|
|
578
|
-
ON plugin_configs (company_id, enabled, priority ASC, plugin_id ASC);
|
|
579
|
-
`);
|
|
580
|
-
await db.execute(sql`
|
|
581
|
-
CREATE INDEX IF NOT EXISTS idx_plugin_runs_company_created
|
|
582
|
-
ON plugin_runs (company_id, created_at DESC);
|
|
583
|
-
`);
|
|
584
|
-
await db.execute(sql`
|
|
585
|
-
CREATE UNIQUE INDEX IF NOT EXISTS idx_templates_company_slug
|
|
586
|
-
ON templates (company_id, slug);
|
|
587
|
-
`);
|
|
588
|
-
await db.execute(sql`
|
|
589
|
-
CREATE INDEX IF NOT EXISTS idx_template_versions_company_template_created
|
|
590
|
-
ON template_versions (company_id, template_id, created_at DESC);
|
|
591
|
-
`);
|
|
592
|
-
await db.execute(sql`
|
|
593
|
-
CREATE INDEX IF NOT EXISTS idx_template_installs_company_created
|
|
594
|
-
ON template_installs (company_id, created_at DESC);
|
|
595
|
-
`);
|
|
596
|
-
|
|
597
|
-
return { db, client };
|
|
4
|
+
const connection = await createDb(dbPath);
|
|
5
|
+
try {
|
|
6
|
+
await applyDatabaseMigrations(connection.connectionString, { dataPath: connection.dataPath });
|
|
7
|
+
return { db: connection.db, client: connection.client };
|
|
8
|
+
} catch (error) {
|
|
9
|
+
await connection.client.close().catch(() => {});
|
|
10
|
+
throw error;
|
|
11
|
+
}
|
|
598
12
|
}
|