@voltagent/libsql 1.0.10 → 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
 
@@ -91,10 +91,12 @@ declare class LibSQLMemoryAdapter implements StorageAdapter {
91
91
  * Add multiple messages
92
92
  */
93
93
  addMessages(messages: UIMessage[], userId: string, conversationId: string): Promise<void>;
94
+ saveConversationSteps(steps: ConversationStepRecord[]): Promise<void>;
94
95
  /**
95
96
  * Get messages with optional filtering
96
97
  */
97
98
  getMessages(userId: string, conversationId: string, options?: GetMessagesOptions): Promise<UIMessage[]>;
99
+ getConversationSteps(userId: string, conversationId: string, options?: GetConversationStepsOptions): Promise<ConversationStepRecord[]>;
98
100
  /**
99
101
  * Clear messages for a user
100
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
 
@@ -91,10 +91,12 @@ declare class LibSQLMemoryAdapter implements StorageAdapter {
91
91
  * Add multiple messages
92
92
  */
93
93
  addMessages(messages: UIMessage[], userId: string, conversationId: string): Promise<void>;
94
+ saveConversationSteps(steps: ConversationStepRecord[]): Promise<void>;
94
95
  /**
95
96
  * Get messages with optional filtering
96
97
  */
97
98
  getMessages(userId: string, conversationId: string, options?: GetMessagesOptions): Promise<UIMessage[]>;
99
+ getConversationSteps(userId: string, conversationId: string, options?: GetConversationStepsOptions): Promise<ConversationStepRecord[]>;
98
100
  /**
99
101
  * Clear messages for a user
100
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 {
@@ -179,6 +180,26 @@ var LibSQLMemoryAdapter = class {
179
180
  metadata TEXT,
180
181
  created_at TEXT NOT NULL,
181
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
182
203
  )`,
183
204
  // Create indexes for better performance
184
205
  `CREATE INDEX IF NOT EXISTS idx_${conversationsTable}_user_id ON ${conversationsTable}(user_id)`,
@@ -186,7 +207,9 @@ var LibSQLMemoryAdapter = class {
186
207
  `CREATE INDEX IF NOT EXISTS idx_${messagesTable}_conversation_id ON ${messagesTable}(conversation_id)`,
187
208
  `CREATE INDEX IF NOT EXISTS idx_${messagesTable}_created_at ON ${messagesTable}(created_at)`,
188
209
  `CREATE INDEX IF NOT EXISTS idx_${workflowStatesTable}_workflow_id ON ${workflowStatesTable}(workflow_id)`,
189
- `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)`
190
213
  ]);
191
214
  }, "initialize database schema");
192
215
  await this.addV2ColumnsToMessagesTable();
@@ -421,6 +444,72 @@ var LibSQLMemoryAdapter = class {
421
444
  );
422
445
  }, "add batch messages");
423
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
+ }
424
513
  /**
425
514
  * Get messages with optional filtering
426
515
  */
@@ -482,6 +571,51 @@ var LibSQLMemoryAdapter = class {
482
571
  };
483
572
  });
484
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
+ }
485
619
  /**
486
620
  * Clear messages for a user
487
621
  */
@@ -489,11 +623,16 @@ var LibSQLMemoryAdapter = class {
489
623
  await this.initialize();
490
624
  const messagesTable = `${this.tablePrefix}_messages`;
491
625
  const conversationsTable = `${this.tablePrefix}_conversations`;
626
+ const stepsTable = `${this.tablePrefix}_steps`;
492
627
  if (conversationId) {
493
628
  await this.client.execute({
494
629
  sql: `DELETE FROM ${messagesTable} WHERE conversation_id = ? AND user_id = ?`,
495
630
  args: [conversationId, userId]
496
631
  });
632
+ await this.client.execute({
633
+ sql: `DELETE FROM ${stepsTable} WHERE conversation_id = ? AND user_id = ?`,
634
+ args: [conversationId, userId]
635
+ });
497
636
  } else {
498
637
  await this.client.execute({
499
638
  sql: `DELETE FROM ${messagesTable}
@@ -502,6 +641,13 @@ var LibSQLMemoryAdapter = class {
502
641
  )`,
503
642
  args: [userId]
504
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
+ });
505
651
  }
506
652
  }
507
653
  // ============================================================================