@voltagent/libsql 1.0.9 → 1.0.11

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/dist/index.mjs CHANGED
@@ -79,6 +79,7 @@ var LibSQLMemoryAdapter = class {
79
79
  const messagesTable = `${this.tablePrefix}_messages`;
80
80
  const usersTable = `${this.tablePrefix}_users`;
81
81
  const workflowStatesTable = `${this.tablePrefix}_workflow_states`;
82
+ const stepsTable = `${this.tablePrefix}_steps`;
82
83
  const isMemoryDb = this.url === ":memory:" || this.url.includes("mode=memory");
83
84
  if (!isMemoryDb && (this.url.startsWith("file:") || this.url.startsWith("libsql:"))) {
84
85
  try {
@@ -139,11 +140,34 @@ var LibSQLMemoryAdapter = class {
139
140
  workflow_name TEXT NOT NULL,
140
141
  status TEXT NOT NULL,
141
142
  suspension TEXT,
143
+ events TEXT,
144
+ output TEXT,
145
+ cancellation TEXT,
142
146
  user_id TEXT,
143
147
  conversation_id TEXT,
144
148
  metadata TEXT,
145
149
  created_at TEXT NOT NULL,
146
150
  updated_at TEXT NOT NULL
151
+ )`,
152
+ // Create conversation steps table
153
+ `CREATE TABLE IF NOT EXISTS ${stepsTable} (
154
+ id TEXT PRIMARY KEY,
155
+ conversation_id TEXT NOT NULL,
156
+ user_id TEXT NOT NULL,
157
+ agent_id TEXT NOT NULL,
158
+ agent_name TEXT,
159
+ operation_id TEXT,
160
+ step_index INTEGER NOT NULL,
161
+ type TEXT NOT NULL,
162
+ role TEXT NOT NULL,
163
+ content TEXT,
164
+ arguments TEXT,
165
+ result TEXT,
166
+ usage TEXT,
167
+ sub_agent_id TEXT,
168
+ sub_agent_name TEXT,
169
+ created_at TEXT NOT NULL,
170
+ FOREIGN KEY (conversation_id) REFERENCES ${conversationsTable}(id) ON DELETE CASCADE
147
171
  )`,
148
172
  // Create indexes for better performance
149
173
  `CREATE INDEX IF NOT EXISTS idx_${conversationsTable}_user_id ON ${conversationsTable}(user_id)`,
@@ -151,11 +175,14 @@ var LibSQLMemoryAdapter = class {
151
175
  `CREATE INDEX IF NOT EXISTS idx_${messagesTable}_conversation_id ON ${messagesTable}(conversation_id)`,
152
176
  `CREATE INDEX IF NOT EXISTS idx_${messagesTable}_created_at ON ${messagesTable}(created_at)`,
153
177
  `CREATE INDEX IF NOT EXISTS idx_${workflowStatesTable}_workflow_id ON ${workflowStatesTable}(workflow_id)`,
154
- `CREATE INDEX IF NOT EXISTS idx_${workflowStatesTable}_status ON ${workflowStatesTable}(status)`
178
+ `CREATE INDEX IF NOT EXISTS idx_${workflowStatesTable}_status ON ${workflowStatesTable}(status)`,
179
+ `CREATE INDEX IF NOT EXISTS idx_${stepsTable}_conversation ON ${stepsTable}(conversation_id, step_index)`,
180
+ `CREATE INDEX IF NOT EXISTS idx_${stepsTable}_operation ON ${stepsTable}(conversation_id, operation_id)`
155
181
  ]);
156
182
  }, "initialize database schema");
157
183
  await this.addV2ColumnsToMessagesTable();
158
184
  await this.migrateDefaultUserIds();
185
+ await this.addWorkflowStateColumns();
159
186
  this.initialized = true;
160
187
  this.logger.debug("Database schema initialized");
161
188
  }
@@ -287,6 +314,42 @@ var LibSQLMemoryAdapter = class {
287
314
  this.logger.error("Failed to migrate default user_ids", error);
288
315
  }
289
316
  }
317
+ /**
318
+ * Add new columns to workflow_states table for event persistence
319
+ * This migration adds support for events, output, and cancellation tracking
320
+ */
321
+ async addWorkflowStateColumns() {
322
+ const workflowStatesTable = `${this.tablePrefix}_workflow_states`;
323
+ try {
324
+ const tableInfo = await this.client.execute(`PRAGMA table_info(${workflowStatesTable})`);
325
+ const columns = tableInfo.rows.map((row) => row.name);
326
+ if (!columns.includes("events")) {
327
+ try {
328
+ await this.client.execute(`ALTER TABLE ${workflowStatesTable} ADD COLUMN events TEXT`);
329
+ this.logger.debug("Added 'events' column to workflow_states table");
330
+ } catch (_e) {
331
+ }
332
+ }
333
+ if (!columns.includes("output")) {
334
+ try {
335
+ await this.client.execute(`ALTER TABLE ${workflowStatesTable} ADD COLUMN output TEXT`);
336
+ this.logger.debug("Added 'output' column to workflow_states table");
337
+ } catch (_e) {
338
+ }
339
+ }
340
+ if (!columns.includes("cancellation")) {
341
+ try {
342
+ await this.client.execute(
343
+ `ALTER TABLE ${workflowStatesTable} ADD COLUMN cancellation TEXT`
344
+ );
345
+ this.logger.debug("Added 'cancellation' column to workflow_states table");
346
+ } catch (_e) {
347
+ }
348
+ }
349
+ } catch (error) {
350
+ this.logger.warn("Failed to add workflow state columns (non-critical)", error);
351
+ }
352
+ }
290
353
  // ============================================================================
291
354
  // Message Operations
292
355
  // ============================================================================
@@ -349,6 +412,72 @@ var LibSQLMemoryAdapter = class {
349
412
  );
350
413
  }, "add batch messages");
351
414
  }
415
+ async saveConversationSteps(steps) {
416
+ if (steps.length === 0) return;
417
+ await this.initialize();
418
+ const stepsTable = `${this.tablePrefix}_steps`;
419
+ await this.executeWithRetry(async () => {
420
+ await this.client.batch(
421
+ steps.map((step) => {
422
+ const createdAt = step.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
423
+ return {
424
+ sql: `INSERT INTO ${stepsTable} (
425
+ id,
426
+ conversation_id,
427
+ user_id,
428
+ agent_id,
429
+ agent_name,
430
+ operation_id,
431
+ step_index,
432
+ type,
433
+ role,
434
+ content,
435
+ arguments,
436
+ result,
437
+ usage,
438
+ sub_agent_id,
439
+ sub_agent_name,
440
+ created_at
441
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
442
+ ON CONFLICT(id) DO UPDATE SET
443
+ conversation_id = excluded.conversation_id,
444
+ user_id = excluded.user_id,
445
+ agent_id = excluded.agent_id,
446
+ agent_name = excluded.agent_name,
447
+ operation_id = excluded.operation_id,
448
+ step_index = excluded.step_index,
449
+ type = excluded.type,
450
+ role = excluded.role,
451
+ content = excluded.content,
452
+ arguments = excluded.arguments,
453
+ result = excluded.result,
454
+ usage = excluded.usage,
455
+ sub_agent_id = excluded.sub_agent_id,
456
+ sub_agent_name = excluded.sub_agent_name,
457
+ created_at = excluded.created_at`,
458
+ args: [
459
+ step.id,
460
+ step.conversationId,
461
+ step.userId,
462
+ step.agentId,
463
+ step.agentName ?? null,
464
+ step.operationId ?? null,
465
+ step.stepIndex,
466
+ step.type,
467
+ step.role,
468
+ step.content ?? null,
469
+ step.arguments ? safeStringify(step.arguments) : null,
470
+ step.result ? safeStringify(step.result) : null,
471
+ step.usage ? safeStringify(step.usage) : null,
472
+ step.subAgentId ?? null,
473
+ step.subAgentName ?? null,
474
+ createdAt
475
+ ]
476
+ };
477
+ })
478
+ );
479
+ }, "save conversation steps");
480
+ }
352
481
  /**
353
482
  * Get messages with optional filtering
354
483
  */
@@ -410,6 +539,51 @@ var LibSQLMemoryAdapter = class {
410
539
  };
411
540
  });
412
541
  }
542
+ async getConversationSteps(userId, conversationId, options) {
543
+ await this.initialize();
544
+ const stepsTable = `${this.tablePrefix}_steps`;
545
+ const limit = options?.limit && options.limit > 0 ? options.limit : void 0;
546
+ let sql = `SELECT * FROM ${stepsTable} WHERE conversation_id = ? AND user_id = ?`;
547
+ const args = [conversationId, userId];
548
+ if (options?.operationId) {
549
+ sql += " AND operation_id = ?";
550
+ args.push(options.operationId);
551
+ }
552
+ sql += " ORDER BY step_index ASC";
553
+ if (limit !== void 0) {
554
+ sql += " LIMIT ?";
555
+ args.push(limit);
556
+ }
557
+ const result = await this.client.execute({ sql, args });
558
+ const parseJsonField = /* @__PURE__ */ __name((value) => {
559
+ if (typeof value !== "string" || value.length === 0) {
560
+ return void 0;
561
+ }
562
+ try {
563
+ return JSON.parse(value);
564
+ } catch {
565
+ return void 0;
566
+ }
567
+ }, "parseJsonField");
568
+ return result.rows.map((row) => ({
569
+ id: row.id,
570
+ conversationId: row.conversation_id,
571
+ userId: row.user_id,
572
+ agentId: row.agent_id,
573
+ agentName: row.agent_name ?? void 0,
574
+ operationId: row.operation_id ?? void 0,
575
+ stepIndex: typeof row.step_index === "number" ? row.step_index : Number(row.step_index ?? 0),
576
+ type: row.type,
577
+ role: row.role,
578
+ content: row.content ?? void 0,
579
+ arguments: parseJsonField(row.arguments),
580
+ result: parseJsonField(row.result),
581
+ usage: parseJsonField(row.usage),
582
+ subAgentId: row.sub_agent_id ?? void 0,
583
+ subAgentName: row.sub_agent_name ?? void 0,
584
+ createdAt: row.created_at ?? (/* @__PURE__ */ new Date()).toISOString()
585
+ }));
586
+ }
413
587
  /**
414
588
  * Clear messages for a user
415
589
  */
@@ -417,11 +591,16 @@ var LibSQLMemoryAdapter = class {
417
591
  await this.initialize();
418
592
  const messagesTable = `${this.tablePrefix}_messages`;
419
593
  const conversationsTable = `${this.tablePrefix}_conversations`;
594
+ const stepsTable = `${this.tablePrefix}_steps`;
420
595
  if (conversationId) {
421
596
  await this.client.execute({
422
597
  sql: `DELETE FROM ${messagesTable} WHERE conversation_id = ? AND user_id = ?`,
423
598
  args: [conversationId, userId]
424
599
  });
600
+ await this.client.execute({
601
+ sql: `DELETE FROM ${stepsTable} WHERE conversation_id = ? AND user_id = ?`,
602
+ args: [conversationId, userId]
603
+ });
425
604
  } else {
426
605
  await this.client.execute({
427
606
  sql: `DELETE FROM ${messagesTable}
@@ -430,6 +609,13 @@ var LibSQLMemoryAdapter = class {
430
609
  )`,
431
610
  args: [userId]
432
611
  });
612
+ await this.client.execute({
613
+ sql: `DELETE FROM ${stepsTable}
614
+ WHERE conversation_id IN (
615
+ SELECT id FROM ${conversationsTable} WHERE user_id = ?
616
+ )`,
617
+ args: [userId]
618
+ });
433
619
  }
434
620
  }
435
621
  // ============================================================================
@@ -721,6 +907,9 @@ var LibSQLMemoryAdapter = class {
721
907
  workflowName: row.workflow_name,
722
908
  status: row.status,
723
909
  suspension: row.suspension ? JSON.parse(row.suspension) : void 0,
910
+ events: row.events ? JSON.parse(row.events) : void 0,
911
+ output: row.output ? JSON.parse(row.output) : void 0,
912
+ cancellation: row.cancellation ? JSON.parse(row.cancellation) : void 0,
724
913
  userId: row.user_id,
725
914
  conversationId: row.conversation_id,
726
915
  metadata: row.metadata ? JSON.parse(row.metadata) : void 0,
@@ -735,15 +924,18 @@ var LibSQLMemoryAdapter = class {
735
924
  await this.initialize();
736
925
  const workflowStatesTable = `${this.tablePrefix}_workflow_states`;
737
926
  await this.client.execute({
738
- sql: `INSERT OR REPLACE INTO ${workflowStatesTable}
739
- (id, workflow_id, workflow_name, status, suspension, user_id, conversation_id, metadata, created_at, updated_at)
740
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
927
+ sql: `INSERT OR REPLACE INTO ${workflowStatesTable}
928
+ (id, workflow_id, workflow_name, status, suspension, events, output, cancellation, user_id, conversation_id, metadata, created_at, updated_at)
929
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
741
930
  args: [
742
931
  executionId,
743
932
  state.workflowId,
744
933
  state.workflowName,
745
934
  state.status,
746
935
  state.suspension ? safeStringify(state.suspension) : null,
936
+ state.events ? safeStringify(state.events) : null,
937
+ state.output ? safeStringify(state.output) : null,
938
+ state.cancellation ? safeStringify(state.cancellation) : null,
747
939
  state.userId || null,
748
940
  state.conversationId || null,
749
941
  state.metadata ? safeStringify(state.metadata) : null,
@@ -784,6 +976,9 @@ var LibSQLMemoryAdapter = class {
784
976
  workflowName: row.workflow_name,
785
977
  status: "suspended",
786
978
  suspension: row.suspension ? JSON.parse(row.suspension) : void 0,
979
+ events: row.events ? JSON.parse(row.events) : void 0,
980
+ output: row.output ? JSON.parse(row.output) : void 0,
981
+ cancellation: row.cancellation ? JSON.parse(row.cancellation) : void 0,
787
982
  userId: row.user_id,
788
983
  conversationId: row.conversation_id,
789
984
  metadata: row.metadata ? JSON.parse(row.metadata) : void 0,