ework-daemon 0.4.6 → 0.4.7

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ework-daemon",
3
- "version": "0.4.6",
3
+ "version": "0.4.7",
4
4
  "description": "Issue-driven AI development daemon. Spawns opencode subprocesses to resolve Gitea issues.",
5
5
  "module": "src/index.ts",
6
6
  "type": "module",
package/src/db.ts CHANGED
@@ -323,18 +323,24 @@ async function runMigrations(db: AsyncDatabase): Promise<void> {
323
323
  await db.exec(`ALTER TABLE ${table} ADD COLUMN ${ddl}`);
324
324
  };
325
325
 
326
- // ── uid: surrogate AUTO_INCREMENT PK on issues/op_sessions/messages ──
326
+ // ── id/uid swap: id becomes AUTO_INCREMENT PK, uid holds the UUID ──
327
327
  // SQLite cannot ADD PRIMARY KEY via ALTER — must rebuild. Runs before
328
328
  // owner_daemon_id etc. so rebuild only copies base columns; ephemeral
329
329
  // coordination data (owner_daemon_id, nudge state) is re-added below.
330
330
  const tMessages = `${prefix}messages`;
331
- if (sqlite) {
332
- const UID_REBUILDS: { table: string; createSql: string; dataCols: string }[] = [
333
- {
334
- table: tIssues,
335
- createSql: `CREATE TABLE ${tIssues} (
336
- uid INTEGER PRIMARY KEY AUTOINCREMENT,
337
- id TEXT NOT NULL UNIQUE,
331
+
332
+ const UID_REBUILDS: {
333
+ table: string;
334
+ sqliteCreate: string;
335
+ mysqlCreate: string;
336
+ oldCols: string;
337
+ newCols: string;
338
+ }[] = [
339
+ {
340
+ table: tIssues,
341
+ sqliteCreate: `CREATE TABLE ${tIssues} (
342
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
343
+ uid TEXT NOT NULL UNIQUE,
338
344
  tracker_type TEXT NOT NULL,
339
345
  tracker_scope_key TEXT NOT NULL,
340
346
  tracker_scope TEXT NOT NULL,
@@ -345,15 +351,30 @@ async function runMigrations(db: AsyncDatabase): Promise<void> {
345
351
  updated_at TEXT NOT NULL,
346
352
  UNIQUE(tracker_type, tracker_scope_key, tracker_issue_id)
347
353
  )`,
348
- dataCols:
349
- "id, tracker_type, tracker_scope_key, tracker_scope, tracker_issue_id, state, title, created_at, updated_at",
350
- },
351
- {
352
- table: tSessions,
353
- createSql: `CREATE TABLE ${tSessions} (
354
- uid INTEGER PRIMARY KEY AUTOINCREMENT,
355
- id TEXT NOT NULL UNIQUE,
356
- issue_id TEXT NOT NULL REFERENCES ${tIssues}(id) ON DELETE CASCADE,
354
+ mysqlCreate: `CREATE TABLE ${tIssues} (
355
+ id BIGINT AUTO_INCREMENT PRIMARY KEY,
356
+ uid VARCHAR(36) NOT NULL UNIQUE,
357
+ tracker_type VARCHAR(64) NOT NULL,
358
+ tracker_scope_key VARCHAR(255) NOT NULL,
359
+ tracker_scope TEXT NOT NULL,
360
+ tracker_issue_id VARCHAR(64) NOT NULL,
361
+ state VARCHAR(16) NOT NULL DEFAULT 'created',
362
+ title VARCHAR(512) NOT NULL DEFAULT '',
363
+ created_at VARCHAR(40) NOT NULL,
364
+ updated_at VARCHAR(40) NOT NULL,
365
+ UNIQUE (tracker_type, tracker_scope_key, tracker_issue_id)
366
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4`,
367
+ oldCols:
368
+ "id, tracker_type, tracker_scope_key, tracker_scope, tracker_issue_id, state, title, created_at, updated_at",
369
+ newCols:
370
+ "uid, tracker_type, tracker_scope_key, tracker_scope, tracker_issue_id, state, title, created_at, updated_at",
371
+ },
372
+ {
373
+ table: tSessions,
374
+ sqliteCreate: `CREATE TABLE ${tSessions} (
375
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
376
+ uid TEXT NOT NULL UNIQUE,
377
+ issue_id TEXT NOT NULL REFERENCES ${tIssues}(uid) ON DELETE CASCADE,
357
378
  name TEXT NOT NULL,
358
379
  state TEXT NOT NULL DEFAULT 'idle',
359
380
  opencode_session_id TEXT,
@@ -366,15 +387,33 @@ async function runMigrations(db: AsyncDatabase): Promise<void> {
366
387
  current_prompt TEXT,
367
388
  UNIQUE(issue_id, name)
368
389
  )`,
369
- dataCols:
370
- "id, issue_id, name, state, opencode_session_id, opencode_pid, workdir, created_at, started_at, progress_comment_id, reaction_comment_id, current_prompt",
371
- },
372
- {
373
- table: tMessages,
374
- createSql: `CREATE TABLE ${tMessages} (
375
- uid INTEGER PRIMARY KEY AUTOINCREMENT,
376
- id TEXT NOT NULL UNIQUE,
377
- session_id TEXT NOT NULL REFERENCES ${tSessions}(id) ON DELETE CASCADE,
390
+ mysqlCreate: `CREATE TABLE ${tSessions} (
391
+ id BIGINT AUTO_INCREMENT PRIMARY KEY,
392
+ uid VARCHAR(36) NOT NULL UNIQUE,
393
+ issue_id VARCHAR(36) NOT NULL,
394
+ name VARCHAR(64) NOT NULL,
395
+ state VARCHAR(16) NOT NULL DEFAULT 'idle',
396
+ opencode_session_id VARCHAR(64),
397
+ opencode_pid BIGINT,
398
+ workdir VARCHAR(1024),
399
+ created_at VARCHAR(40) NOT NULL,
400
+ started_at BIGINT,
401
+ progress_comment_id VARCHAR(64),
402
+ reaction_comment_id VARCHAR(64),
403
+ current_prompt TEXT,
404
+ UNIQUE (issue_id, name)
405
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4`,
406
+ oldCols:
407
+ "id, issue_id, name, state, opencode_session_id, opencode_pid, workdir, created_at, started_at, progress_comment_id, reaction_comment_id, current_prompt",
408
+ newCols:
409
+ "uid, issue_id, name, state, opencode_session_id, opencode_pid, workdir, created_at, started_at, progress_comment_id, reaction_comment_id, current_prompt",
410
+ },
411
+ {
412
+ table: tMessages,
413
+ sqliteCreate: `CREATE TABLE ${tMessages} (
414
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
415
+ uid TEXT NOT NULL UNIQUE,
416
+ session_id TEXT NOT NULL REFERENCES ${tSessions}(uid) ON DELETE CASCADE,
378
417
  content TEXT NOT NULL,
379
418
  source_comment_id TEXT,
380
419
  reaction_comment_id TEXT,
@@ -384,46 +423,55 @@ async function runMigrations(db: AsyncDatabase): Promise<void> {
384
423
  created_at TEXT NOT NULL,
385
424
  updated_at TEXT NOT NULL
386
425
  )`,
387
- dataCols:
388
- "id, session_id, content, source_comment_id, reaction_comment_id, status, attempts, error, created_at, updated_at",
389
- },
390
- ];
426
+ mysqlCreate: `CREATE TABLE ${tMessages} (
427
+ id BIGINT AUTO_INCREMENT PRIMARY KEY,
428
+ uid VARCHAR(36) NOT NULL UNIQUE,
429
+ session_id VARCHAR(36) NOT NULL,
430
+ content LONGTEXT NOT NULL,
431
+ source_comment_id VARCHAR(64),
432
+ reaction_comment_id VARCHAR(64),
433
+ status VARCHAR(16) NOT NULL DEFAULT 'pending',
434
+ attempts INT NOT NULL DEFAULT 0,
435
+ error TEXT,
436
+ created_at VARCHAR(40) NOT NULL,
437
+ updated_at VARCHAR(40) NOT NULL
438
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4`,
439
+ oldCols:
440
+ "id, session_id, content, source_comment_id, reaction_comment_id, status, attempts, error, created_at, updated_at",
441
+ newCols:
442
+ "uid, session_id, content, source_comment_id, reaction_comment_id, status, attempts, error, created_at, updated_at",
443
+ },
444
+ ];
391
445
 
392
- for (const { table, createSql, dataCols } of UID_REBUILDS) {
393
- if (await hasColumn(table, "uid")) continue;
446
+ for (const { table, sqliteCreate, mysqlCreate, oldCols, newCols } of UID_REBUILDS) {
447
+ if (await hasColumn(table, "uid")) continue;
448
+ if (sqlite) {
394
449
  const exists = await db.get<{ cnt: number }>(
395
450
  `SELECT COUNT(*) AS cnt FROM sqlite_master WHERE type='table' AND name='${table}'`
396
451
  );
397
452
  if (Number(exists?.cnt ?? 0) === 0) continue;
398
-
399
453
  await db.exec("PRAGMA foreign_keys = OFF");
400
454
  try {
401
455
  await db.transaction(async () => {
402
- await db.exec(`ALTER TABLE ${table} RENAME TO ${table}__old_uid`);
403
- await db.exec(createSql);
404
- await db.exec(
405
- `CREATE INDEX IF NOT EXISTS idx_${table}__id ON ${table}(id)`
406
- );
407
- await db.exec(`INSERT INTO ${table} (${dataCols}) SELECT ${dataCols} FROM ${table}__old_uid`);
408
- await db.exec(`DROP TABLE ${table}__old_uid`);
456
+ await db.exec(`ALTER TABLE ${table} RENAME TO ${table}__old_id`);
457
+ await db.exec(sqliteCreate);
458
+ await db.exec(`INSERT INTO ${table} (${newCols}) SELECT ${oldCols} FROM ${table}__old_id`);
459
+ await db.exec(`DROP TABLE ${table}__old_id`);
409
460
  });
410
461
  } finally {
411
462
  await db.exec("PRAGMA foreign_keys = ON");
412
463
  }
413
- }
414
- } else {
415
- const uidMySqlTables = [tIssues, tSessions, tMessages];
416
- for (const tbl of uidMySqlTables) {
417
- if (await hasColumn(tbl, "uid")) continue;
464
+ } else {
418
465
  try {
419
- await db.exec(
420
- `ALTER TABLE ${tbl} DROP PRIMARY KEY, ` +
421
- `ADD COLUMN uid BIGINT AUTO_INCREMENT PRIMARY KEY FIRST, ` +
422
- `ADD UNIQUE INDEX uk_${tbl}_id (id)`
423
- );
424
- } catch (e) {
425
- if (e && typeof e === "object" && "errno" in e && (e as { errno: number }).errno === 1146) continue;
426
- throw e;
466
+ await db.exec("SET FOREIGN_KEY_CHECKS = 0");
467
+ await db.transaction(async () => {
468
+ await db.exec(`ALTER TABLE ${table} RENAME TO ${table}__old_id`);
469
+ await db.exec(mysqlCreate);
470
+ await db.exec(`INSERT INTO ${table} (${newCols}) SELECT ${oldCols} FROM ${table}__old_id`);
471
+ await db.exec(`DROP TABLE ${table}__old_id`);
472
+ });
473
+ } finally {
474
+ await db.exec("SET FOREIGN_KEY_CHECKS = 1");
427
475
  }
428
476
  }
429
477
  }
package/src/op.ts CHANGED
@@ -5,7 +5,7 @@ import type { TrackerRef, Issue, IssueState, OpSession, SessionState, Message }
5
5
  // ─── Row Types ───
6
6
 
7
7
  interface IssueRow {
8
- id: string;
8
+ uid: string;
9
9
  tracker_type: string;
10
10
  tracker_scope_key: string;
11
11
  tracker_scope: string;
@@ -18,7 +18,7 @@ interface IssueRow {
18
18
  }
19
19
 
20
20
  interface SessionRow {
21
- id: string;
21
+ uid: string;
22
22
  issue_id: string;
23
23
  name: string;
24
24
  state: string;
@@ -37,7 +37,7 @@ interface SessionRow {
37
37
  }
38
38
 
39
39
  interface MessageRow {
40
- id: string;
40
+ uid: string;
41
41
  session_id: string;
42
42
  content: string;
43
43
  source_comment_id: string | null;
@@ -55,7 +55,7 @@ function rowToIssue(row: IssueRow): Issue {
55
55
  let scope: Record<string, string>;
56
56
  try { scope = JSON.parse(row.tracker_scope); } catch { scope = {}; }
57
57
  return {
58
- id: row.id,
58
+ id: row.uid,
59
59
  trackerType: row.tracker_type,
60
60
  trackerScope: scope,
61
61
  trackerScopeKey: row.tracker_scope_key,
@@ -70,7 +70,7 @@ function rowToIssue(row: IssueRow): Issue {
70
70
 
71
71
  function rowToSession(row: SessionRow): OpSession {
72
72
  return {
73
- id: row.id,
73
+ id: row.uid,
74
74
  issueId: row.issue_id,
75
75
  name: row.name,
76
76
  state: row.state as SessionState,
@@ -91,7 +91,7 @@ function rowToSession(row: SessionRow): OpSession {
91
91
 
92
92
  function rowToMessage(row: MessageRow): Message {
93
93
  return {
94
- id: row.id,
94
+ id: row.uid,
95
95
  sessionId: row.session_id,
96
96
  content: row.content,
97
97
  sourceCommentId: row.source_comment_id ?? undefined,
@@ -121,7 +121,7 @@ export class Store {
121
121
  // ─── Issues ───
122
122
 
123
123
  async getIssue(id: string): Promise<Issue | undefined> {
124
- const row = await getDB().get<IssueRow>("SELECT * FROM {{issues}} WHERE id = ?", [id]);
124
+ const row = await getDB().get<IssueRow>("SELECT * FROM {{issues}} WHERE uid = ?", [id]);
125
125
  return row ? rowToIssue(row) : undefined;
126
126
  }
127
127
 
@@ -137,7 +137,7 @@ export class Store {
137
137
  const existing = await this.findIssue(ref.trackerType, scopeKey, ref.issueId);
138
138
  if (existing) {
139
139
  if (title && existing.title !== title) {
140
- await getDB().run("UPDATE {{issues}} SET title = ?, updated_at = ? WHERE id = ?", [
140
+ await getDB().run("UPDATE {{issues}} SET title = ?, updated_at = ? WHERE uid = ?", [
141
141
  title,
142
142
  new Date().toISOString(),
143
143
  existing.id,
@@ -150,7 +150,7 @@ export class Store {
150
150
  const now = new Date();
151
151
  const id = crypto.randomUUID();
152
152
  await getDB().run(
153
- "INSERT OR IGNORE INTO {{issues}} (id, tracker_type, tracker_scope_key, tracker_scope, tracker_issue_id, state, title, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
153
+ "INSERT OR IGNORE INTO {{issues}} (uid, tracker_type, tracker_scope_key, tracker_scope, tracker_issue_id, state, title, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
154
154
  [id, ref.trackerType, scopeKey, JSON.stringify(ref.scope), ref.issueId, "created", title, now.toISOString(), now.toISOString()]
155
155
  );
156
156
 
@@ -166,7 +166,7 @@ export class Store {
166
166
  }
167
167
 
168
168
  async updateIssueState(id: string, state: IssueState): Promise<void> {
169
- await getDB().run("UPDATE {{issues}} SET state = ?, updated_at = ? WHERE id = ?", [
169
+ await getDB().run("UPDATE {{issues}} SET state = ?, updated_at = ? WHERE uid = ?", [
170
170
  state,
171
171
  new Date().toISOString(),
172
172
  id,
@@ -186,7 +186,7 @@ export class Store {
186
186
  // ─── OpSessions ───
187
187
 
188
188
  async getSession(id: string): Promise<OpSession | undefined> {
189
- const row = await getDB().get<SessionRow>("SELECT * FROM {{op_sessions}} WHERE id = ?", [id]);
189
+ const row = await getDB().get<SessionRow>("SELECT * FROM {{op_sessions}} WHERE uid = ?", [id]);
190
190
  return row ? rowToSession(row) : undefined;
191
191
  }
192
192
 
@@ -218,14 +218,14 @@ export class Store {
218
218
  createdAt: new Date(),
219
219
  };
220
220
  await getDB().run(
221
- "INSERT OR IGNORE INTO {{op_sessions}} (id, issue_id, name, state, opencode_session_id, opencode_pid, workdir, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
221
+ "INSERT OR IGNORE INTO {{op_sessions}} (uid, issue_id, name, state, opencode_session_id, opencode_pid, workdir, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
222
222
  [session.id, session.issueId, session.name, session.state, null, null, null, session.createdAt.toISOString()]
223
223
  );
224
224
  return session;
225
225
  }
226
226
 
227
227
  async updateSession(id: string, patch: Partial<OpSession>): Promise<OpSession | undefined> {
228
- const row = await getDB().get<SessionRow>("SELECT * FROM {{op_sessions}} WHERE id = ?", [id]);
228
+ const row = await getDB().get<SessionRow>("SELECT * FROM {{op_sessions}} WHERE uid = ?", [id]);
229
229
  if (!row) return undefined;
230
230
  const existing = rowToSession(row);
231
231
  const updated = { ...existing, ...patch };
@@ -233,7 +233,7 @@ export class Store {
233
233
  await getDB().run(
234
234
  `UPDATE {{op_sessions}} SET state = ?, opencode_session_id = ?, opencode_pid = ?, workdir = ?,
235
235
  started_at = ?, progress_comment_id = ?, reaction_comment_id = ?, current_prompt = ?,
236
- last_output_at = ?, nudge_rounds = ?, stuck_nudge_rounds = ?, generation = ? WHERE id = ?`,
236
+ last_output_at = ?, nudge_rounds = ?, stuck_nudge_rounds = ?, generation = ? WHERE uid = ?`,
237
237
  [
238
238
  updated.state,
239
239
  updated.opencodeSessionId ?? null,
@@ -275,7 +275,7 @@ export class Store {
275
275
  const now = new Date().toISOString();
276
276
  const id = crypto.randomUUID();
277
277
  await getDB().run(
278
- "INSERT OR IGNORE INTO {{messages}} (id, session_id, content, source_comment_id, reaction_comment_id, status, attempts, error, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
278
+ "INSERT OR IGNORE INTO {{messages}} (uid, session_id, content, source_comment_id, reaction_comment_id, status, attempts, error, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
279
279
  [id, sessionId, content, sourceCommentId ?? null, reactionCommentId ?? null, "pending", 0, null, now, now]
280
280
  );
281
281
  return {
@@ -287,7 +287,7 @@ export class Store {
287
287
  }
288
288
 
289
289
  async getMessage(id: string): Promise<Message | undefined> {
290
- const row = await getDB().get<MessageRow>("SELECT * FROM {{messages}} WHERE id = ?", [id]);
290
+ const row = await getDB().get<MessageRow>("SELECT * FROM {{messages}} WHERE uid = ?", [id]);
291
291
  return row ? rowToMessage(row) : undefined;
292
292
  }
293
293
 
@@ -300,10 +300,10 @@ export class Store {
300
300
  }
301
301
 
302
302
  async updateMessageStatus(id: string, status: Message["status"], error?: string): Promise<void> {
303
- const row = await getDB().get<MessageRow>("SELECT * FROM {{messages}} WHERE id = ?", [id]);
303
+ const row = await getDB().get<MessageRow>("SELECT * FROM {{messages}} WHERE uid = ?", [id]);
304
304
  const attempts = row ? row.attempts + (status === "failed" ? 1 : 0) : 0;
305
305
  await getDB().run(
306
- "UPDATE {{messages}} SET status = ?, attempts = ?, error = ?, updated_at = ? WHERE id = ?",
306
+ "UPDATE {{messages}} SET status = ?, attempts = ?, error = ?, updated_at = ? WHERE uid = ?",
307
307
  [status, attempts, error ?? null, new Date().toISOString(), id]
308
308
  );
309
309
  }
@@ -436,7 +436,7 @@ export class Store {
436
436
  */
437
437
  async claimIssue(issueId: string, daemonId: number): Promise<boolean> {
438
438
  const res = await getDB().run(
439
- "UPDATE {{issues}} SET owner_daemon_id = ? WHERE id = ? AND owner_daemon_id IS NULL",
439
+ "UPDATE {{issues}} SET owner_daemon_id = ? WHERE uid = ? AND owner_daemon_id IS NULL",
440
440
  [daemonId, issueId]
441
441
  );
442
442
  return res.changes === 1;
@@ -454,7 +454,7 @@ export class Store {
454
454
  /** Atomic message claim: pending → running. False = lost or already done. */
455
455
  async claimMessage(messageId: string): Promise<boolean> {
456
456
  const res = await getDB().run(
457
- "UPDATE {{messages}} SET status = 'running', updated_at = ? WHERE id = ? AND status = 'pending'",
457
+ "UPDATE {{messages}} SET status = 'running', updated_at = ? WHERE uid = ? AND status = 'pending'",
458
458
  [new Date().toISOString(), messageId]
459
459
  );
460
460
  return res.changes === 1;
@@ -471,7 +471,7 @@ export class Store {
471
471
  async listOwnedSessions(daemonId: number): Promise<OpSession[]> {
472
472
  const rows = await getDB().all<SessionRow>(
473
473
  `SELECT s.* FROM {{op_sessions}} s
474
- INNER JOIN {{issues}} i ON i.id = s.issue_id
474
+ INNER JOIN {{issues}} i ON i.uid = s.issue_id
475
475
  WHERE i.owner_daemon_id = ?
476
476
  ORDER BY s.created_at`,
477
477
  [daemonId]
@@ -483,8 +483,8 @@ export class Store {
483
483
  async getOwnedPendingOrRunningMessages(daemonId: number): Promise<Message[]> {
484
484
  const rows = await getDB().all<MessageRow>(
485
485
  `SELECT m.* FROM {{messages}} m
486
- INNER JOIN {{op_sessions}} s ON s.id = m.session_id
487
- INNER JOIN {{issues}} i ON i.id = s.issue_id
486
+ INNER JOIN {{op_sessions}} s ON s.uid = m.session_id
487
+ INNER JOIN {{issues}} i ON i.uid = s.issue_id
488
488
  WHERE i.owner_daemon_id = ? AND m.status IN ('pending', 'running')
489
489
  ORDER BY m.created_at ASC`,
490
490
  [daemonId]
@@ -8,8 +8,8 @@
8
8
  -- tables InnoDB + utf8mb4 for FK CASCADE + full Unicode (emoji).
9
9
 
10
10
  CREATE TABLE IF NOT EXISTS {{issues}} (
11
- uid BIGINT AUTO_INCREMENT PRIMARY KEY,
12
- id VARCHAR(36) NOT NULL UNIQUE,
11
+ id BIGINT AUTO_INCREMENT PRIMARY KEY,
12
+ uid VARCHAR(36) NOT NULL UNIQUE,
13
13
  tracker_type VARCHAR(64) NOT NULL,
14
14
  tracker_scope_key VARCHAR(255) NOT NULL,
15
15
  tracker_scope TEXT NOT NULL,
@@ -22,8 +22,8 @@ CREATE TABLE IF NOT EXISTS {{issues}} (
22
22
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
23
23
 
24
24
  CREATE TABLE IF NOT EXISTS {{op_sessions}} (
25
- uid BIGINT AUTO_INCREMENT PRIMARY KEY,
26
- id VARCHAR(36) NOT NULL UNIQUE,
25
+ id BIGINT AUTO_INCREMENT PRIMARY KEY,
26
+ uid VARCHAR(36) NOT NULL UNIQUE,
27
27
  issue_id VARCHAR(36) NOT NULL,
28
28
  name VARCHAR(64) NOT NULL,
29
29
  state VARCHAR(16) NOT NULL DEFAULT 'idle',
@@ -36,15 +36,15 @@ CREATE TABLE IF NOT EXISTS {{op_sessions}} (
36
36
  reaction_comment_id VARCHAR(64),
37
37
  current_prompt TEXT,
38
38
  UNIQUE (issue_id, name),
39
- CONSTRAINT {{fk_sessions_issue}} FOREIGN KEY (issue_id) REFERENCES {{issues}}(id) ON DELETE CASCADE
39
+ CONSTRAINT {{fk_sessions_issue}} FOREIGN KEY (issue_id) REFERENCES {{issues}}(uid) ON DELETE CASCADE
40
40
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
41
41
  -- UNIQUE(issue_id, name) above creates a composite index whose leftmost
42
42
  -- prefix (issue_id) satisfies the FK's index requirement, so no separate
43
43
  -- idx_sessions_issue is needed on MySQL.
44
44
 
45
45
  CREATE TABLE IF NOT EXISTS {{messages}} (
46
- uid BIGINT AUTO_INCREMENT PRIMARY KEY,
47
- id VARCHAR(36) NOT NULL UNIQUE,
46
+ id BIGINT AUTO_INCREMENT PRIMARY KEY,
47
+ uid VARCHAR(36) NOT NULL UNIQUE,
48
48
  session_id VARCHAR(36) NOT NULL,
49
49
  content LONGTEXT NOT NULL,
50
50
  source_comment_id VARCHAR(64),
@@ -54,7 +54,7 @@ CREATE TABLE IF NOT EXISTS {{messages}} (
54
54
  error TEXT,
55
55
  created_at VARCHAR(40) NOT NULL,
56
56
  updated_at VARCHAR(40) NOT NULL,
57
- CONSTRAINT {{fk_messages_session}} FOREIGN KEY (session_id) REFERENCES {{op_sessions}}(id) ON DELETE CASCADE
57
+ CONSTRAINT {{fk_messages_session}} FOREIGN KEY (session_id) REFERENCES {{op_sessions}}(uid) ON DELETE CASCADE
58
58
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
59
59
  CREATE INDEX idx_messages_session ON {{messages}} (session_id);
60
60
  CREATE INDEX idx_messages_status ON {{messages}} (status);
@@ -4,8 +4,8 @@
4
4
  -- share one DB across multiple daemon instances.
5
5
 
6
6
  CREATE TABLE IF NOT EXISTS {{issues}} (
7
- uid INTEGER PRIMARY KEY AUTOINCREMENT,
8
- id TEXT NOT NULL UNIQUE,
7
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
8
+ uid TEXT NOT NULL UNIQUE,
9
9
  tracker_type TEXT NOT NULL,
10
10
  tracker_scope_key TEXT NOT NULL,
11
11
  tracker_scope TEXT NOT NULL,
@@ -18,9 +18,9 @@ CREATE TABLE IF NOT EXISTS {{issues}} (
18
18
  );
19
19
 
20
20
  CREATE TABLE IF NOT EXISTS {{op_sessions}} (
21
- uid INTEGER PRIMARY KEY AUTOINCREMENT,
22
- id TEXT NOT NULL UNIQUE,
23
- issue_id TEXT NOT NULL REFERENCES {{issues}}(id) ON DELETE CASCADE,
21
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
22
+ uid TEXT NOT NULL UNIQUE,
23
+ issue_id TEXT NOT NULL REFERENCES {{issues}}(uid) ON DELETE CASCADE,
24
24
  name TEXT NOT NULL,
25
25
  state TEXT NOT NULL DEFAULT 'idle',
26
26
  opencode_session_id TEXT,
@@ -35,9 +35,9 @@ CREATE TABLE IF NOT EXISTS {{op_sessions}} (
35
35
  );
36
36
 
37
37
  CREATE TABLE IF NOT EXISTS {{messages}} (
38
- uid INTEGER PRIMARY KEY AUTOINCREMENT,
39
- id TEXT NOT NULL UNIQUE,
40
- session_id TEXT NOT NULL REFERENCES {{op_sessions}}(id) ON DELETE CASCADE,
38
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
39
+ uid TEXT NOT NULL UNIQUE,
40
+ session_id TEXT NOT NULL REFERENCES {{op_sessions}}(uid) ON DELETE CASCADE,
41
41
  content TEXT NOT NULL,
42
42
  source_comment_id TEXT,
43
43
  reaction_comment_id TEXT,