@polpo-ai/drizzle 0.11.0 → 0.12.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.
Files changed (41) hide show
  1. package/dist/__tests__/migrator-pg.test.js +2 -2
  2. package/dist/__tests__/migrator-pg.test.js.map +1 -1
  3. package/dist/__tests__/stores-pg.test.js +43 -109
  4. package/dist/__tests__/stores-pg.test.js.map +1 -1
  5. package/dist/__tests__/stores.test.js +48 -264
  6. package/dist/__tests__/stores.test.js.map +1 -1
  7. package/dist/index.d.ts +4 -302
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +13 -12
  10. package/dist/index.js.map +1 -1
  11. package/dist/migrate.d.ts.map +1 -1
  12. package/dist/migrate.js +0 -22
  13. package/dist/migrate.js.map +1 -1
  14. package/dist/migrator.d.ts.map +1 -1
  15. package/dist/migrator.js +2 -3
  16. package/dist/migrator.js.map +1 -1
  17. package/dist/schema/index.d.ts +0 -2
  18. package/dist/schema/index.d.ts.map +1 -1
  19. package/dist/schema/index.js +0 -2
  20. package/dist/schema/index.js.map +1 -1
  21. package/dist/sqlite-migrator.d.ts +26 -0
  22. package/dist/sqlite-migrator.d.ts.map +1 -0
  23. package/dist/sqlite-migrator.js +122 -0
  24. package/dist/sqlite-migrator.js.map +1 -0
  25. package/dist/stores/index.d.ts +0 -1
  26. package/dist/stores/index.d.ts.map +1 -1
  27. package/dist/stores/index.js +0 -1
  28. package/dist/stores/index.js.map +1 -1
  29. package/dist/stores/task-store.d.ts +6 -6
  30. package/dist/stores/task-store.d.ts.map +1 -1
  31. package/dist/stores/task-store.js +7 -7
  32. package/dist/stores/task-store.js.map +1 -1
  33. package/package.json +3 -3
  34. package/dist/schema/attachments.d.ts +0 -301
  35. package/dist/schema/attachments.d.ts.map +0 -1
  36. package/dist/schema/attachments.js +0 -29
  37. package/dist/schema/attachments.js.map +0 -1
  38. package/dist/stores/attachment-store.d.ts +0 -22
  39. package/dist/stores/attachment-store.d.ts.map +0 -1
  40. package/dist/stores/attachment-store.js +0 -66
  41. package/dist/stores/attachment-store.js.map +0 -1
@@ -7,6 +7,7 @@ import { describe, it, expect, beforeEach, afterEach } from "vitest";
7
7
  import { randomBytes } from "node:crypto";
8
8
  import Database from "better-sqlite3";
9
9
  import { drizzle } from "drizzle-orm/better-sqlite3";
10
+ import { migrateSqliteSchema } from "../sqlite-migrator.js";
10
11
  import { createSqliteStores } from "../index.js";
11
12
  // Provide a deterministic vault key for tests (32 bytes hex-encoded)
12
13
  process.env.POLPO_VAULT_KEY = randomBytes(32).toString("hex");
@@ -14,228 +15,11 @@ process.env.POLPO_VAULT_KEY = randomBytes(32).toString("hex");
14
15
  let sqlite;
15
16
  let db;
16
17
  let stores;
17
- /** Create all SQLite tables via raw SQL (mirrors what ensurePgSchema does for PG). */
18
- function createTables(raw) {
19
- raw.exec(`
20
- CREATE TABLE IF NOT EXISTS tasks (
21
- id TEXT PRIMARY KEY,
22
- title TEXT NOT NULL,
23
- description TEXT NOT NULL,
24
- assign_to TEXT NOT NULL,
25
- "group" TEXT,
26
- mission_id TEXT,
27
- depends_on TEXT NOT NULL DEFAULT '[]',
28
- status TEXT NOT NULL DEFAULT 'pending',
29
- retries INTEGER NOT NULL DEFAULT 0,
30
- max_retries INTEGER NOT NULL DEFAULT 2,
31
- max_duration INTEGER,
32
- retry_policy TEXT,
33
- expectations TEXT NOT NULL DEFAULT '[]',
34
- metrics TEXT NOT NULL DEFAULT '[]',
35
- result TEXT,
36
- phase TEXT,
37
- fix_attempts INTEGER NOT NULL DEFAULT 0,
38
- resolution_attempts INTEGER NOT NULL DEFAULT 0,
39
- original_description TEXT,
40
- session_id TEXT,
41
- notifications TEXT,
42
- outcomes TEXT,
43
- expected_outcomes TEXT,
44
- deadline TEXT,
45
- priority TEXT,
46
- side_effects INTEGER,
47
- revision_count INTEGER,
48
- "user" TEXT,
49
- created_at TEXT NOT NULL,
50
- updated_at TEXT NOT NULL
51
- );
52
- CREATE INDEX IF NOT EXISTS idx_tasks_user ON tasks("user");
53
- CREATE TABLE IF NOT EXISTS missions (
54
- id TEXT PRIMARY KEY,
55
- name TEXT NOT NULL UNIQUE,
56
- data TEXT NOT NULL,
57
- prompt TEXT,
58
- status TEXT NOT NULL DEFAULT 'draft',
59
- schedule TEXT,
60
- end_date TEXT,
61
- quality_threshold TEXT,
62
- deadline TEXT,
63
- notifications TEXT,
64
- execution_count INTEGER NOT NULL DEFAULT 0,
65
- "user" TEXT,
66
- created_at TEXT NOT NULL,
67
- updated_at TEXT NOT NULL
68
- );
69
- CREATE INDEX IF NOT EXISTS idx_missions_user ON missions("user");
70
- CREATE TABLE IF NOT EXISTS metadata (
71
- key TEXT PRIMARY KEY,
72
- value TEXT NOT NULL
73
- );
74
- CREATE TABLE IF NOT EXISTS processes (
75
- agent_name TEXT NOT NULL,
76
- pid INTEGER NOT NULL,
77
- task_id TEXT NOT NULL,
78
- started_at TEXT NOT NULL,
79
- alive INTEGER NOT NULL DEFAULT 1,
80
- activity TEXT NOT NULL DEFAULT '{}'
81
- );
82
- CREATE TABLE IF NOT EXISTS runs (
83
- id TEXT PRIMARY KEY,
84
- task_id TEXT NOT NULL,
85
- pid INTEGER NOT NULL DEFAULT 0,
86
- agent_name TEXT NOT NULL,
87
- adapter_type TEXT NOT NULL,
88
- session_id TEXT,
89
- status TEXT NOT NULL DEFAULT 'running',
90
- started_at TEXT NOT NULL,
91
- updated_at TEXT NOT NULL,
92
- activity TEXT NOT NULL DEFAULT '{}',
93
- result TEXT,
94
- outcomes TEXT,
95
- config TEXT,
96
- config_path TEXT NOT NULL,
97
- "user" TEXT
98
- );
99
- CREATE INDEX IF NOT EXISTS idx_runs_user ON runs("user");
100
- CREATE TABLE IF NOT EXISTS sessions (
101
- id TEXT PRIMARY KEY,
102
- title TEXT,
103
- agent TEXT,
104
- "user" TEXT,
105
- metadata TEXT,
106
- created_at TEXT NOT NULL,
107
- updated_at TEXT NOT NULL
108
- );
109
- CREATE INDEX IF NOT EXISTS idx_sessions_user ON sessions("user");
110
- CREATE TABLE IF NOT EXISTS messages (
111
- id TEXT PRIMARY KEY,
112
- session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
113
- role TEXT NOT NULL,
114
- content TEXT NOT NULL,
115
- ts TEXT NOT NULL,
116
- tool_calls TEXT
117
- );
118
- CREATE TABLE IF NOT EXISTS notifications (
119
- id TEXT PRIMARY KEY,
120
- timestamp TEXT NOT NULL,
121
- rule_id TEXT NOT NULL,
122
- rule_name TEXT NOT NULL,
123
- channel TEXT NOT NULL,
124
- channel_type TEXT NOT NULL,
125
- status TEXT NOT NULL,
126
- error TEXT,
127
- title TEXT NOT NULL,
128
- body TEXT NOT NULL,
129
- severity TEXT NOT NULL,
130
- source_event TEXT NOT NULL,
131
- attachment_count INTEGER NOT NULL DEFAULT 0,
132
- attachment_types TEXT
133
- );
134
- CREATE TABLE IF NOT EXISTS log_sessions (
135
- id TEXT PRIMARY KEY,
136
- started_at TEXT NOT NULL
137
- );
138
- CREATE TABLE IF NOT EXISTS log_entries (
139
- id TEXT PRIMARY KEY,
140
- session_id TEXT NOT NULL REFERENCES log_sessions(id) ON DELETE CASCADE,
141
- ts TEXT NOT NULL,
142
- event TEXT NOT NULL,
143
- data TEXT
144
- );
145
- CREATE TABLE IF NOT EXISTS approvals (
146
- id TEXT PRIMARY KEY,
147
- gate_id TEXT NOT NULL,
148
- gate_name TEXT NOT NULL,
149
- task_id TEXT,
150
- mission_id TEXT,
151
- status TEXT NOT NULL DEFAULT 'pending',
152
- payload TEXT,
153
- requested_at TEXT NOT NULL,
154
- resolved_at TEXT,
155
- resolved_by TEXT,
156
- note TEXT
157
- );
158
- CREATE TABLE IF NOT EXISTS memory (
159
- key TEXT PRIMARY KEY,
160
- content TEXT NOT NULL DEFAULT ''
161
- );
162
- CREATE TABLE IF NOT EXISTS peers (
163
- id TEXT PRIMARY KEY,
164
- channel TEXT NOT NULL,
165
- external_id TEXT NOT NULL,
166
- display_name TEXT,
167
- first_seen_at TEXT NOT NULL,
168
- last_seen_at TEXT NOT NULL,
169
- linked_to TEXT
170
- );
171
- CREATE TABLE IF NOT EXISTS peer_allowlist (
172
- peer_id TEXT PRIMARY KEY
173
- );
174
- CREATE TABLE IF NOT EXISTS pairing_requests (
175
- id TEXT PRIMARY KEY,
176
- peer_id TEXT NOT NULL,
177
- channel TEXT NOT NULL,
178
- external_id TEXT NOT NULL,
179
- display_name TEXT,
180
- code TEXT NOT NULL UNIQUE,
181
- created_at TEXT NOT NULL,
182
- expires_at TEXT NOT NULL,
183
- resolved INTEGER NOT NULL DEFAULT 0
184
- );
185
- CREATE TABLE IF NOT EXISTS peer_sessions (
186
- peer_id TEXT PRIMARY KEY,
187
- session_id TEXT NOT NULL
188
- );
189
- CREATE TABLE IF NOT EXISTS teams (
190
- name TEXT PRIMARY KEY,
191
- description TEXT,
192
- created_at TEXT NOT NULL,
193
- updated_at TEXT NOT NULL
194
- );
195
- CREATE TABLE IF NOT EXISTS agents (
196
- name TEXT PRIMARY KEY,
197
- team_name TEXT NOT NULL,
198
- config TEXT NOT NULL,
199
- created_at TEXT NOT NULL,
200
- updated_at TEXT NOT NULL
201
- );
202
- CREATE TABLE IF NOT EXISTS vault (
203
- agent TEXT NOT NULL,
204
- service TEXT NOT NULL,
205
- type TEXT NOT NULL,
206
- label TEXT,
207
- credentials TEXT NOT NULL,
208
- created_at TEXT NOT NULL,
209
- updated_at TEXT NOT NULL,
210
- PRIMARY KEY (agent, service)
211
- );
212
- CREATE TABLE IF NOT EXISTS playbooks (
213
- name TEXT PRIMARY KEY,
214
- description TEXT NOT NULL,
215
- mission TEXT NOT NULL,
216
- parameters TEXT,
217
- version TEXT,
218
- author TEXT,
219
- tags TEXT,
220
- created_at TEXT NOT NULL,
221
- updated_at TEXT NOT NULL
222
- );
223
- CREATE TABLE IF NOT EXISTS skills (
224
- name TEXT PRIMARY KEY,
225
- description TEXT NOT NULL DEFAULT '',
226
- source TEXT,
227
- installed_at TEXT NOT NULL,
228
- allowed_tools TEXT,
229
- tags TEXT,
230
- category TEXT
231
- );
232
- PRAGMA foreign_keys = ON;
233
- `);
234
- }
235
- beforeEach(() => {
18
+ beforeEach(async () => {
236
19
  sqlite = new Database(":memory:");
237
- createTables(sqlite);
20
+ sqlite.exec("PRAGMA foreign_keys = ON");
238
21
  db = drizzle(sqlite);
22
+ await migrateSqliteSchema(db);
239
23
  stores = createSqliteStores(db);
240
24
  });
241
25
  afterEach(() => {
@@ -245,8 +29,8 @@ afterEach(() => {
245
29
  // TaskStore
246
30
  // ═══════════════════════════════════════════════════════════════════════
247
31
  describe("DrizzleTaskStore", () => {
248
- it("addTask + getTask round-trip", async () => {
249
- const task = await stores.taskStore.addTask({
32
+ it("createTask + getTask round-trip", async () => {
33
+ const task = await stores.taskStore.createTask({
250
34
  title: "Fix bug",
251
35
  description: "Fix the login bug",
252
36
  assignTo: "claude",
@@ -264,8 +48,8 @@ describe("DrizzleTaskStore", () => {
264
48
  expect(fetched.title).toBe("Fix bug");
265
49
  expect(fetched.expectations).toEqual([{ type: "llm_review", criteria: "Login works" }]);
266
50
  });
267
- it("addTask persists OpenAI-compat user identifier", async () => {
268
- const task = await stores.taskStore.addTask({
51
+ it("createTask persists OpenAI-compat user identifier", async () => {
52
+ const task = await stores.taskStore.createTask({
269
53
  title: "Per-user task",
270
54
  description: "Scoped to end-user",
271
55
  assignTo: "claude",
@@ -279,20 +63,20 @@ describe("DrizzleTaskStore", () => {
279
63
  const fetched = await stores.taskStore.getTask(task.id);
280
64
  expect(fetched.user).toBe("u-42");
281
65
  });
282
- it("getAllTasks returns ordered by createdAt", async () => {
283
- await stores.taskStore.addTask({
66
+ it("listTasks returns ordered by createdAt", async () => {
67
+ await stores.taskStore.createTask({
284
68
  title: "A", description: "first", assignTo: "claude", dependsOn: [], maxRetries: 2, expectations: [], metrics: [],
285
69
  });
286
- await stores.taskStore.addTask({
70
+ await stores.taskStore.createTask({
287
71
  title: "B", description: "second", assignTo: "claude", dependsOn: [], maxRetries: 2, expectations: [], metrics: [],
288
72
  });
289
- const all = await stores.taskStore.getAllTasks();
73
+ const all = await stores.taskStore.listTasks();
290
74
  expect(all).toHaveLength(2);
291
75
  expect(all[0].title).toBe("A");
292
76
  expect(all[1].title).toBe("B");
293
77
  });
294
78
  it("updateTask merges fields", async () => {
295
- const task = await stores.taskStore.addTask({
79
+ const task = await stores.taskStore.createTask({
296
80
  title: "Original", description: "desc", assignTo: "claude", dependsOn: [], maxRetries: 2, expectations: [], metrics: [],
297
81
  });
298
82
  const updated = await stores.taskStore.updateTask(task.id, { title: "Updated" });
@@ -301,30 +85,30 @@ describe("DrizzleTaskStore", () => {
301
85
  const fetched = await stores.taskStore.getTask(task.id);
302
86
  expect(fetched.title).toBe("Updated");
303
87
  });
304
- it("removeTask deletes by ID", async () => {
305
- const task = await stores.taskStore.addTask({
88
+ it("deleteTask deletes by ID", async () => {
89
+ const task = await stores.taskStore.createTask({
306
90
  title: "Delete me", description: "d", assignTo: "claude", dependsOn: [], maxRetries: 2, expectations: [], metrics: [],
307
91
  });
308
- const removed = await stores.taskStore.removeTask(task.id);
92
+ const removed = await stores.taskStore.deleteTask(task.id);
309
93
  expect(removed).toBe(true);
310
94
  const fetched = await stores.taskStore.getTask(task.id);
311
95
  expect(fetched).toBeUndefined();
312
96
  });
313
- it("removeTasks with filter", async () => {
314
- await stores.taskStore.addTask({
97
+ it("deleteTasks with filter", async () => {
98
+ await stores.taskStore.createTask({
315
99
  title: "Keep", description: "d", assignTo: "claude", dependsOn: [], maxRetries: 2, expectations: [], metrics: [],
316
100
  });
317
- await stores.taskStore.addTask({
101
+ await stores.taskStore.createTask({
318
102
  title: "Remove", description: "d", assignTo: "claude", dependsOn: [], maxRetries: 2, expectations: [], metrics: [], group: "old",
319
103
  });
320
- const count = await stores.taskStore.removeTasks((t) => t.group === "old");
104
+ const count = await stores.taskStore.deleteTasks((t) => t.group === "old");
321
105
  expect(count).toBe(1);
322
- const all = await stores.taskStore.getAllTasks();
106
+ const all = await stores.taskStore.listTasks();
323
107
  expect(all).toHaveLength(1);
324
108
  expect(all[0].title).toBe("Keep");
325
109
  });
326
110
  it("transition validates state machine", async () => {
327
- const task = await stores.taskStore.addTask({
111
+ const task = await stores.taskStore.createTask({
328
112
  title: "T", description: "d", assignTo: "claude", dependsOn: [], maxRetries: 2, expectations: [], metrics: [],
329
113
  });
330
114
  // pending → assigned is valid
@@ -334,7 +118,7 @@ describe("DrizzleTaskStore", () => {
334
118
  await expect(stores.taskStore.transition(task.id, "pending")).rejects.toThrow();
335
119
  });
336
120
  it("transition increments retries on failed→pending", async () => {
337
- const task = await stores.taskStore.addTask({
121
+ const task = await stores.taskStore.createTask({
338
122
  title: "T", description: "d", assignTo: "claude", dependsOn: [], maxRetries: 3, expectations: [], metrics: [],
339
123
  });
340
124
  await stores.taskStore.transition(task.id, "assigned");
@@ -344,7 +128,7 @@ describe("DrizzleTaskStore", () => {
344
128
  expect(retried.retries).toBe(1);
345
129
  });
346
130
  it("unsafeSetStatus bypasses state machine", async () => {
347
- const task = await stores.taskStore.addTask({
131
+ const task = await stores.taskStore.createTask({
348
132
  title: "T", description: "d", assignTo: "claude", dependsOn: [], maxRetries: 2, expectations: [], metrics: [],
349
133
  });
350
134
  // pending → done is not a valid transition, but unsafeSetStatus allows it
@@ -352,43 +136,43 @@ describe("DrizzleTaskStore", () => {
352
136
  expect(result.status).toBe("done");
353
137
  });
354
138
  // ── Missions ────────────────────────────────────────────────────────
355
- it("saveMission + getMission round-trip", async () => {
356
- const mission = await stores.taskStore.saveMission({
139
+ it("createMission + getMission round-trip", async () => {
140
+ const mission = await stores.missionStore.createMission({
357
141
  name: "mission-1",
358
142
  data: '{"tasks":[]}',
359
143
  status: "draft",
360
144
  });
361
145
  expect(mission.id).toBeDefined();
362
146
  expect(mission.name).toBe("mission-1");
363
- const fetched = await stores.taskStore.getMission(mission.id);
147
+ const fetched = await stores.missionStore.getMission(mission.id);
364
148
  expect(fetched).toBeDefined();
365
149
  expect(fetched.name).toBe("mission-1");
366
150
  });
367
151
  it("getMissionByName finds by name", async () => {
368
- await stores.taskStore.saveMission({ name: "deploy-v2", data: "{}", status: "draft" });
369
- const found = await stores.taskStore.getMissionByName("deploy-v2");
152
+ await stores.missionStore.createMission({ name: "deploy-v2", data: "{}", status: "draft" });
153
+ const found = await stores.missionStore.getMissionByName("deploy-v2");
370
154
  expect(found).toBeDefined();
371
155
  expect(found.name).toBe("deploy-v2");
372
156
  });
373
157
  it("updateMission merges fields", async () => {
374
- const m = await stores.taskStore.saveMission({ name: "m-1", data: "{}", status: "draft" });
375
- const updated = await stores.taskStore.updateMission(m.id, { status: "active" });
158
+ const m = await stores.missionStore.createMission({ name: "m-1", data: "{}", status: "draft" });
159
+ const updated = await stores.missionStore.updateMission(m.id, { status: "active" });
376
160
  expect(updated.status).toBe("active");
377
161
  expect(updated.name).toBe("m-1");
378
162
  });
379
163
  it("deleteMission removes", async () => {
380
- const m = await stores.taskStore.saveMission({ name: "m-del", data: "{}", status: "draft" });
381
- const ok = await stores.taskStore.deleteMission(m.id);
164
+ const m = await stores.missionStore.createMission({ name: "m-del", data: "{}", status: "draft" });
165
+ const ok = await stores.missionStore.deleteMission(m.id);
382
166
  expect(ok).toBe(true);
383
- const fetched = await stores.taskStore.getMission(m.id);
167
+ const fetched = await stores.missionStore.getMission(m.id);
384
168
  expect(fetched).toBeUndefined();
385
169
  });
386
170
  it("nextMissionName increments", async () => {
387
- expect(await stores.taskStore.nextMissionName()).toBe("mission-1");
388
- await stores.taskStore.saveMission({ name: "mission-1", data: "{}", status: "draft" });
389
- expect(await stores.taskStore.nextMissionName()).toBe("mission-2");
390
- await stores.taskStore.saveMission({ name: "mission-5", data: "{}", status: "draft" });
391
- expect(await stores.taskStore.nextMissionName()).toBe("mission-6");
171
+ expect(await stores.missionStore.nextMissionName()).toBe("mission-1");
172
+ await stores.missionStore.createMission({ name: "mission-1", data: "{}", status: "draft" });
173
+ expect(await stores.missionStore.nextMissionName()).toBe("mission-2");
174
+ await stores.missionStore.createMission({ name: "mission-5", data: "{}", status: "draft" });
175
+ expect(await stores.missionStore.nextMissionName()).toBe("mission-6");
392
176
  });
393
177
  // ── State ────────────────────────────────────────────────────────────
394
178
  it("setState + getState round-trip", async () => {
@@ -511,7 +295,7 @@ describe("DrizzleRunStore", () => {
511
295
  // ═══════════════════════════════════════════════════════════════════════
512
296
  describe("DrizzleSessionStore", () => {
513
297
  it("create + getSession", async () => {
514
- const id = await stores.sessionStore.create("My Session");
298
+ const id = await stores.sessionStore.create({ title: "My Session" });
515
299
  const session = await stores.sessionStore.getSession(id);
516
300
  expect(session).toBeDefined();
517
301
  expect(session.title).toBe("My Session");
@@ -539,10 +323,10 @@ describe("DrizzleSessionStore", () => {
539
323
  expect(recent[1].content).toBe("3");
540
324
  });
541
325
  it("listSessions includes messageCount", async () => {
542
- const s1 = await stores.sessionStore.create("S1");
326
+ const s1 = await stores.sessionStore.create({ title: "S1" });
543
327
  await stores.sessionStore.addMessage(s1, "user", "msg1");
544
328
  await stores.sessionStore.addMessage(s1, "assistant", "msg2");
545
- await stores.sessionStore.create("S2");
329
+ await stores.sessionStore.create({ title: "S2" });
546
330
  const list = await stores.sessionStore.listSessions();
547
331
  expect(list).toHaveLength(2);
548
332
  const withMessages = list.find((s) => s.title === "S1");
@@ -595,14 +379,14 @@ describe("DrizzleSessionStore", () => {
595
379
  expect(acmeProd[0].title).toBe("Acme-prod");
596
380
  });
597
381
  it("renameSession updates title", async () => {
598
- const id = await stores.sessionStore.create("Old");
382
+ const id = await stores.sessionStore.create({ title: "Old" });
599
383
  const ok = await stores.sessionStore.renameSession(id, "New");
600
384
  expect(ok).toBe(true);
601
385
  const session = await stores.sessionStore.getSession(id);
602
386
  expect(session.title).toBe("New");
603
387
  });
604
388
  it("deleteSession cascade-deletes messages", async () => {
605
- const id = await stores.sessionStore.create("Del");
389
+ const id = await stores.sessionStore.create({ title: "Del" });
606
390
  await stores.sessionStore.addMessage(id, "user", "msg");
607
391
  const ok = await stores.sessionStore.deleteSession(id);
608
392
  expect(ok).toBe(true);
@@ -610,17 +394,17 @@ describe("DrizzleSessionStore", () => {
610
394
  expect(await stores.sessionStore.getMessages(id)).toEqual([]);
611
395
  });
612
396
  it("prune keeps the N most recent sessions", async () => {
613
- await stores.sessionStore.create("Old");
614
- await stores.sessionStore.create("New");
397
+ await stores.sessionStore.create({ title: "Old" });
398
+ await stores.sessionStore.create({ title: "New" });
615
399
  const pruned = await stores.sessionStore.prune(1);
616
400
  expect(pruned).toBe(1);
617
401
  const list = await stores.sessionStore.listSessions();
618
402
  expect(list).toHaveLength(1);
619
403
  });
620
404
  it("getLatestSession returns most recently updated", async () => {
621
- await stores.sessionStore.create("First");
405
+ await stores.sessionStore.create({ title: "First" });
622
406
  await new Promise((r) => setTimeout(r, 5));
623
- const id2 = await stores.sessionStore.create("Second");
407
+ const id2 = await stores.sessionStore.create({ title: "Second" });
624
408
  const latest = await stores.sessionStore.getLatestSession();
625
409
  expect(latest).toBeDefined();
626
410
  expect(latest.id).toBe(id2);