@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.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { StorageAdapter, GetMessagesOptions, CreateConversationInput, Conversation, ConversationQueryOptions, WorkingMemoryScope, WorkflowStateEntry, ObservabilityStorageAdapter, ObservabilitySpan, ObservabilityLogRecord, LogFilter, VectorAdapter, VectorItem, VectorSearchOptions, SearchResult } from '@voltagent/core';
1
+ import { StorageAdapter, ConversationStepRecord, GetMessagesOptions, GetConversationStepsOptions, CreateConversationInput, Conversation, ConversationQueryOptions, WorkingMemoryScope, WorkflowStateEntry, ObservabilityStorageAdapter, ObservabilitySpan, ObservabilityLogRecord, LogFilter, VectorAdapter, VectorItem, VectorSearchOptions, SearchResult } from '@voltagent/core';
2
2
  import { Logger } from '@voltagent/logger';
3
3
  import { UIMessage } from 'ai';
4
4
 
@@ -78,6 +78,11 @@ declare class LibSQLMemoryAdapter implements StorageAdapter {
78
78
  * Updates messages with user_id='default' to use the actual user_id from their conversation
79
79
  */
80
80
  private migrateDefaultUserIds;
81
+ /**
82
+ * Add new columns to workflow_states table for event persistence
83
+ * This migration adds support for events, output, and cancellation tracking
84
+ */
85
+ private addWorkflowStateColumns;
81
86
  /**
82
87
  * Add a single message
83
88
  */
@@ -86,10 +91,12 @@ declare class LibSQLMemoryAdapter implements StorageAdapter {
86
91
  * Add multiple messages
87
92
  */
88
93
  addMessages(messages: UIMessage[], userId: string, conversationId: string): Promise<void>;
94
+ saveConversationSteps(steps: ConversationStepRecord[]): Promise<void>;
89
95
  /**
90
96
  * Get messages with optional filtering
91
97
  */
92
98
  getMessages(userId: string, conversationId: string, options?: GetMessagesOptions): Promise<UIMessage[]>;
99
+ getConversationSteps(userId: string, conversationId: string, options?: GetConversationStepsOptions): Promise<ConversationStepRecord[]>;
93
100
  /**
94
101
  * Clear messages for a user
95
102
  */
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { StorageAdapter, GetMessagesOptions, CreateConversationInput, Conversation, ConversationQueryOptions, WorkingMemoryScope, WorkflowStateEntry, ObservabilityStorageAdapter, ObservabilitySpan, ObservabilityLogRecord, LogFilter, VectorAdapter, VectorItem, VectorSearchOptions, SearchResult } from '@voltagent/core';
1
+ import { StorageAdapter, ConversationStepRecord, GetMessagesOptions, GetConversationStepsOptions, CreateConversationInput, Conversation, ConversationQueryOptions, WorkingMemoryScope, WorkflowStateEntry, ObservabilityStorageAdapter, ObservabilitySpan, ObservabilityLogRecord, LogFilter, VectorAdapter, VectorItem, VectorSearchOptions, SearchResult } from '@voltagent/core';
2
2
  import { Logger } from '@voltagent/logger';
3
3
  import { UIMessage } from 'ai';
4
4
 
@@ -78,6 +78,11 @@ declare class LibSQLMemoryAdapter implements StorageAdapter {
78
78
  * Updates messages with user_id='default' to use the actual user_id from their conversation
79
79
  */
80
80
  private migrateDefaultUserIds;
81
+ /**
82
+ * Add new columns to workflow_states table for event persistence
83
+ * This migration adds support for events, output, and cancellation tracking
84
+ */
85
+ private addWorkflowStateColumns;
81
86
  /**
82
87
  * Add a single message
83
88
  */
@@ -86,10 +91,12 @@ declare class LibSQLMemoryAdapter implements StorageAdapter {
86
91
  * Add multiple messages
87
92
  */
88
93
  addMessages(messages: UIMessage[], userId: string, conversationId: string): Promise<void>;
94
+ saveConversationSteps(steps: ConversationStepRecord[]): Promise<void>;
89
95
  /**
90
96
  * Get messages with optional filtering
91
97
  */
92
98
  getMessages(userId: string, conversationId: string, options?: GetMessagesOptions): Promise<UIMessage[]>;
99
+ getConversationSteps(userId: string, conversationId: string, options?: GetConversationStepsOptions): Promise<ConversationStepRecord[]>;
93
100
  /**
94
101
  * Clear messages for a user
95
102
  */
package/dist/index.js CHANGED
@@ -111,6 +111,7 @@ var LibSQLMemoryAdapter = class {
111
111
  const messagesTable = `${this.tablePrefix}_messages`;
112
112
  const usersTable = `${this.tablePrefix}_users`;
113
113
  const workflowStatesTable = `${this.tablePrefix}_workflow_states`;
114
+ const stepsTable = `${this.tablePrefix}_steps`;
114
115
  const isMemoryDb = this.url === ":memory:" || this.url.includes("mode=memory");
115
116
  if (!isMemoryDb && (this.url.startsWith("file:") || this.url.startsWith("libsql:"))) {
116
117
  try {
@@ -171,11 +172,34 @@ var LibSQLMemoryAdapter = class {
171
172
  workflow_name TEXT NOT NULL,
172
173
  status TEXT NOT NULL,
173
174
  suspension TEXT,
175
+ events TEXT,
176
+ output TEXT,
177
+ cancellation TEXT,
174
178
  user_id TEXT,
175
179
  conversation_id TEXT,
176
180
  metadata TEXT,
177
181
  created_at TEXT NOT NULL,
178
182
  updated_at TEXT NOT NULL
183
+ )`,
184
+ // Create conversation steps table
185
+ `CREATE TABLE IF NOT EXISTS ${stepsTable} (
186
+ id TEXT PRIMARY KEY,
187
+ conversation_id TEXT NOT NULL,
188
+ user_id TEXT NOT NULL,
189
+ agent_id TEXT NOT NULL,
190
+ agent_name TEXT,
191
+ operation_id TEXT,
192
+ step_index INTEGER NOT NULL,
193
+ type TEXT NOT NULL,
194
+ role TEXT NOT NULL,
195
+ content TEXT,
196
+ arguments TEXT,
197
+ result TEXT,
198
+ usage TEXT,
199
+ sub_agent_id TEXT,
200
+ sub_agent_name TEXT,
201
+ created_at TEXT NOT NULL,
202
+ FOREIGN KEY (conversation_id) REFERENCES ${conversationsTable}(id) ON DELETE CASCADE
179
203
  )`,
180
204
  // Create indexes for better performance
181
205
  `CREATE INDEX IF NOT EXISTS idx_${conversationsTable}_user_id ON ${conversationsTable}(user_id)`,
@@ -183,11 +207,14 @@ var LibSQLMemoryAdapter = class {
183
207
  `CREATE INDEX IF NOT EXISTS idx_${messagesTable}_conversation_id ON ${messagesTable}(conversation_id)`,
184
208
  `CREATE INDEX IF NOT EXISTS idx_${messagesTable}_created_at ON ${messagesTable}(created_at)`,
185
209
  `CREATE INDEX IF NOT EXISTS idx_${workflowStatesTable}_workflow_id ON ${workflowStatesTable}(workflow_id)`,
186
- `CREATE INDEX IF NOT EXISTS idx_${workflowStatesTable}_status ON ${workflowStatesTable}(status)`
210
+ `CREATE INDEX IF NOT EXISTS idx_${workflowStatesTable}_status ON ${workflowStatesTable}(status)`,
211
+ `CREATE INDEX IF NOT EXISTS idx_${stepsTable}_conversation ON ${stepsTable}(conversation_id, step_index)`,
212
+ `CREATE INDEX IF NOT EXISTS idx_${stepsTable}_operation ON ${stepsTable}(conversation_id, operation_id)`
187
213
  ]);
188
214
  }, "initialize database schema");
189
215
  await this.addV2ColumnsToMessagesTable();
190
216
  await this.migrateDefaultUserIds();
217
+ await this.addWorkflowStateColumns();
191
218
  this.initialized = true;
192
219
  this.logger.debug("Database schema initialized");
193
220
  }
@@ -319,6 +346,42 @@ var LibSQLMemoryAdapter = class {
319
346
  this.logger.error("Failed to migrate default user_ids", error);
320
347
  }
321
348
  }
349
+ /**
350
+ * Add new columns to workflow_states table for event persistence
351
+ * This migration adds support for events, output, and cancellation tracking
352
+ */
353
+ async addWorkflowStateColumns() {
354
+ const workflowStatesTable = `${this.tablePrefix}_workflow_states`;
355
+ try {
356
+ const tableInfo = await this.client.execute(`PRAGMA table_info(${workflowStatesTable})`);
357
+ const columns = tableInfo.rows.map((row) => row.name);
358
+ if (!columns.includes("events")) {
359
+ try {
360
+ await this.client.execute(`ALTER TABLE ${workflowStatesTable} ADD COLUMN events TEXT`);
361
+ this.logger.debug("Added 'events' column to workflow_states table");
362
+ } catch (_e) {
363
+ }
364
+ }
365
+ if (!columns.includes("output")) {
366
+ try {
367
+ await this.client.execute(`ALTER TABLE ${workflowStatesTable} ADD COLUMN output TEXT`);
368
+ this.logger.debug("Added 'output' column to workflow_states table");
369
+ } catch (_e) {
370
+ }
371
+ }
372
+ if (!columns.includes("cancellation")) {
373
+ try {
374
+ await this.client.execute(
375
+ `ALTER TABLE ${workflowStatesTable} ADD COLUMN cancellation TEXT`
376
+ );
377
+ this.logger.debug("Added 'cancellation' column to workflow_states table");
378
+ } catch (_e) {
379
+ }
380
+ }
381
+ } catch (error) {
382
+ this.logger.warn("Failed to add workflow state columns (non-critical)", error);
383
+ }
384
+ }
322
385
  // ============================================================================
323
386
  // Message Operations
324
387
  // ============================================================================
@@ -381,6 +444,72 @@ var LibSQLMemoryAdapter = class {
381
444
  );
382
445
  }, "add batch messages");
383
446
  }
447
+ async saveConversationSteps(steps) {
448
+ if (steps.length === 0) return;
449
+ await this.initialize();
450
+ const stepsTable = `${this.tablePrefix}_steps`;
451
+ await this.executeWithRetry(async () => {
452
+ await this.client.batch(
453
+ steps.map((step) => {
454
+ const createdAt = step.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
455
+ return {
456
+ sql: `INSERT INTO ${stepsTable} (
457
+ id,
458
+ conversation_id,
459
+ user_id,
460
+ agent_id,
461
+ agent_name,
462
+ operation_id,
463
+ step_index,
464
+ type,
465
+ role,
466
+ content,
467
+ arguments,
468
+ result,
469
+ usage,
470
+ sub_agent_id,
471
+ sub_agent_name,
472
+ created_at
473
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
474
+ ON CONFLICT(id) DO UPDATE SET
475
+ conversation_id = excluded.conversation_id,
476
+ user_id = excluded.user_id,
477
+ agent_id = excluded.agent_id,
478
+ agent_name = excluded.agent_name,
479
+ operation_id = excluded.operation_id,
480
+ step_index = excluded.step_index,
481
+ type = excluded.type,
482
+ role = excluded.role,
483
+ content = excluded.content,
484
+ arguments = excluded.arguments,
485
+ result = excluded.result,
486
+ usage = excluded.usage,
487
+ sub_agent_id = excluded.sub_agent_id,
488
+ sub_agent_name = excluded.sub_agent_name,
489
+ created_at = excluded.created_at`,
490
+ args: [
491
+ step.id,
492
+ step.conversationId,
493
+ step.userId,
494
+ step.agentId,
495
+ step.agentName ?? null,
496
+ step.operationId ?? null,
497
+ step.stepIndex,
498
+ step.type,
499
+ step.role,
500
+ step.content ?? null,
501
+ step.arguments ? (0, import_internal.safeStringify)(step.arguments) : null,
502
+ step.result ? (0, import_internal.safeStringify)(step.result) : null,
503
+ step.usage ? (0, import_internal.safeStringify)(step.usage) : null,
504
+ step.subAgentId ?? null,
505
+ step.subAgentName ?? null,
506
+ createdAt
507
+ ]
508
+ };
509
+ })
510
+ );
511
+ }, "save conversation steps");
512
+ }
384
513
  /**
385
514
  * Get messages with optional filtering
386
515
  */
@@ -442,6 +571,51 @@ var LibSQLMemoryAdapter = class {
442
571
  };
443
572
  });
444
573
  }
574
+ async getConversationSteps(userId, conversationId, options) {
575
+ await this.initialize();
576
+ const stepsTable = `${this.tablePrefix}_steps`;
577
+ const limit = options?.limit && options.limit > 0 ? options.limit : void 0;
578
+ let sql = `SELECT * FROM ${stepsTable} WHERE conversation_id = ? AND user_id = ?`;
579
+ const args = [conversationId, userId];
580
+ if (options?.operationId) {
581
+ sql += " AND operation_id = ?";
582
+ args.push(options.operationId);
583
+ }
584
+ sql += " ORDER BY step_index ASC";
585
+ if (limit !== void 0) {
586
+ sql += " LIMIT ?";
587
+ args.push(limit);
588
+ }
589
+ const result = await this.client.execute({ sql, args });
590
+ const parseJsonField = /* @__PURE__ */ __name((value) => {
591
+ if (typeof value !== "string" || value.length === 0) {
592
+ return void 0;
593
+ }
594
+ try {
595
+ return JSON.parse(value);
596
+ } catch {
597
+ return void 0;
598
+ }
599
+ }, "parseJsonField");
600
+ return result.rows.map((row) => ({
601
+ id: row.id,
602
+ conversationId: row.conversation_id,
603
+ userId: row.user_id,
604
+ agentId: row.agent_id,
605
+ agentName: row.agent_name ?? void 0,
606
+ operationId: row.operation_id ?? void 0,
607
+ stepIndex: typeof row.step_index === "number" ? row.step_index : Number(row.step_index ?? 0),
608
+ type: row.type,
609
+ role: row.role,
610
+ content: row.content ?? void 0,
611
+ arguments: parseJsonField(row.arguments),
612
+ result: parseJsonField(row.result),
613
+ usage: parseJsonField(row.usage),
614
+ subAgentId: row.sub_agent_id ?? void 0,
615
+ subAgentName: row.sub_agent_name ?? void 0,
616
+ createdAt: row.created_at ?? (/* @__PURE__ */ new Date()).toISOString()
617
+ }));
618
+ }
445
619
  /**
446
620
  * Clear messages for a user
447
621
  */
@@ -449,11 +623,16 @@ var LibSQLMemoryAdapter = class {
449
623
  await this.initialize();
450
624
  const messagesTable = `${this.tablePrefix}_messages`;
451
625
  const conversationsTable = `${this.tablePrefix}_conversations`;
626
+ const stepsTable = `${this.tablePrefix}_steps`;
452
627
  if (conversationId) {
453
628
  await this.client.execute({
454
629
  sql: `DELETE FROM ${messagesTable} WHERE conversation_id = ? AND user_id = ?`,
455
630
  args: [conversationId, userId]
456
631
  });
632
+ await this.client.execute({
633
+ sql: `DELETE FROM ${stepsTable} WHERE conversation_id = ? AND user_id = ?`,
634
+ args: [conversationId, userId]
635
+ });
457
636
  } else {
458
637
  await this.client.execute({
459
638
  sql: `DELETE FROM ${messagesTable}
@@ -462,6 +641,13 @@ var LibSQLMemoryAdapter = class {
462
641
  )`,
463
642
  args: [userId]
464
643
  });
644
+ await this.client.execute({
645
+ sql: `DELETE FROM ${stepsTable}
646
+ WHERE conversation_id IN (
647
+ SELECT id FROM ${conversationsTable} WHERE user_id = ?
648
+ )`,
649
+ args: [userId]
650
+ });
465
651
  }
466
652
  }
467
653
  // ============================================================================
@@ -753,6 +939,9 @@ var LibSQLMemoryAdapter = class {
753
939
  workflowName: row.workflow_name,
754
940
  status: row.status,
755
941
  suspension: row.suspension ? JSON.parse(row.suspension) : void 0,
942
+ events: row.events ? JSON.parse(row.events) : void 0,
943
+ output: row.output ? JSON.parse(row.output) : void 0,
944
+ cancellation: row.cancellation ? JSON.parse(row.cancellation) : void 0,
756
945
  userId: row.user_id,
757
946
  conversationId: row.conversation_id,
758
947
  metadata: row.metadata ? JSON.parse(row.metadata) : void 0,
@@ -767,15 +956,18 @@ var LibSQLMemoryAdapter = class {
767
956
  await this.initialize();
768
957
  const workflowStatesTable = `${this.tablePrefix}_workflow_states`;
769
958
  await this.client.execute({
770
- sql: `INSERT OR REPLACE INTO ${workflowStatesTable}
771
- (id, workflow_id, workflow_name, status, suspension, user_id, conversation_id, metadata, created_at, updated_at)
772
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
959
+ sql: `INSERT OR REPLACE INTO ${workflowStatesTable}
960
+ (id, workflow_id, workflow_name, status, suspension, events, output, cancellation, user_id, conversation_id, metadata, created_at, updated_at)
961
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
773
962
  args: [
774
963
  executionId,
775
964
  state.workflowId,
776
965
  state.workflowName,
777
966
  state.status,
778
967
  state.suspension ? (0, import_internal.safeStringify)(state.suspension) : null,
968
+ state.events ? (0, import_internal.safeStringify)(state.events) : null,
969
+ state.output ? (0, import_internal.safeStringify)(state.output) : null,
970
+ state.cancellation ? (0, import_internal.safeStringify)(state.cancellation) : null,
779
971
  state.userId || null,
780
972
  state.conversationId || null,
781
973
  state.metadata ? (0, import_internal.safeStringify)(state.metadata) : null,
@@ -816,6 +1008,9 @@ var LibSQLMemoryAdapter = class {
816
1008
  workflowName: row.workflow_name,
817
1009
  status: "suspended",
818
1010
  suspension: row.suspension ? JSON.parse(row.suspension) : void 0,
1011
+ events: row.events ? JSON.parse(row.events) : void 0,
1012
+ output: row.output ? JSON.parse(row.output) : void 0,
1013
+ cancellation: row.cancellation ? JSON.parse(row.cancellation) : void 0,
819
1014
  userId: row.user_id,
820
1015
  conversationId: row.conversation_id,
821
1016
  metadata: row.metadata ? JSON.parse(row.metadata) : void 0,