Repository: mastra-ai/mastra
Pull request #2887: Add dynamic default storage
Author: login: wardpeet
Created: 2025-03-11T10:56:06Z | Merged: 2025-03-12T12:03:06Z

Problem:
Constructors cannot have async calls in them, which means we cannot dynamicaly import default storage.

Solution:
All the methods of storage are async so we can add a dynamic import of libsql before each call to make sure storage is set correctly


Diff:
diff --git a/.changeset/wet-keys-win.md b/.changeset/wet-keys-win.md
new file mode 100644
index 00000000000..abda048c084
--- /dev/null
+++ b/.changeset/wet-keys-win.md
@@ -0,0 +1,5 @@
+---
+'@mastra/core': patch
+---
+
+Enable dynamic import of default-storage to reduce runtime/bundle size when not using default storage
diff --git a/packages/core/src/mastra/index.ts b/packages/core/src/mastra/index.ts
index dcc3ead8357..b034fb396c9 100644
--- a/packages/core/src/mastra/index.ts
+++ b/packages/core/src/mastra/index.ts
@@ -4,8 +4,8 @@ import { LogLevel, createLogger, noopLogger } from '../logger';
 import type { Logger } from '../logger';
 import type { MastraMemory } from '../memory/memory';
 import type { MastraStorage } from '../storage';
-import { DefaultStorage } from '../storage/libsql';
-import { InstrumentClass, OTLPStorageExporter, Telemetry } from '../telemetry';
+import { DefaultProxyStorage } from '../storage/default-proxy-storage';
+import { InstrumentClass, Telemetry } from '../telemetry';
 import type { OtelConfig } from '../telemetry';
 import type { MastraTTS } from '../tts';
 import type { MastraVector } from '../vector';
@@ -62,20 +62,28 @@ export class Mastra<
     path: string;
   }> = [];
   #telemetry?: Telemetry;
+  #storage?: MastraStorage;
+  #memory?: MastraMemory;
+
   /**
-   * @deprecated use getStorage() instead
+   * @deprecated use getTelemetry() instead
    */
-  storage?: MastraStorage;
+  get telemetry() {
+    return this.#telemetry;
+  }
+
   /**
-   * @deprecated use getMemory() instead
+   * @deprecated use getStorage() instead
    */
-  memory?: MastraMemory;
+  get storage() {
+    return this.#storage;
+  }
 
   /**
-   * @deprecated use getTelemetry() instead
+   * @deprecated use getMemory() instead
    */
-  get telemetry() {
-    return this.#telemetry;
+  get memory() {
+    return this.#memory;
   }
 
   constructor(config?: Config<TAgents, TWorkflows, TVectors, TTTS, TLogger>) {
@@ -106,7 +114,7 @@ export class Mastra<
 
     let storage = config?.storage;
     if (!storage) {
-      storage = new DefaultStorage({
+      storage = new DefaultProxyStorage({
         config: {
           url: process.env.MASTRA_DEFAULT_STORAGE_URL || `:memory:`,
         },
@@ -116,46 +124,18 @@ export class Mastra<
     /*
     Telemetry
     */
-    // if storage is a libsql instance, we need to default the telemetry exporter to OTLPStorageExporter
-    if (storage instanceof DefaultStorage && config?.telemetry?.export?.type !== 'custom') {
-      const newTelemetry = {
-        ...(config?.telemetry || {}),
-        export: {
-          type: 'custom',
-          exporter: new OTLPStorageExporter({
-            logger: this.getLogger(),
-            storage,
-          }),
-        },
-      };
-      this.#telemetry = Telemetry.init(newTelemetry as OtelConfig);
-    } else if (config?.telemetry) {
-      this.#telemetry = Telemetry.init(config?.telemetry);
-    }
-
-    /**
-     * Deployer
-     **/
-    if (config?.deployer) {
-      this.#deployer = config.deployer;
-      if (this.#telemetry) {
-        this.#deployer = this.#telemetry.traceClass(config.deployer, {
-          excludeMethods: ['__setTelemetry', '__getTelemetry'],
-        });
-        this.#deployer.__setTelemetry(this.#telemetry);
-      }
-    }
+    this.#telemetry = Telemetry.init(config?.telemetry);
 
     /*
       Storage
     */
     if (this.#telemetry) {
-      this.storage = this.#telemetry.traceClass(storage, {
+      this.#storage = this.#telemetry.traceClass(storage, {
         excludeMethods: ['__setTelemetry', '__getTelemetry'],
       });
-      this.storage.__setTelemetry(this.#telemetry);
+      this.#storage.__setTelemetry(this.#telemetry);
     } else {
-      this.storage = storage;
+      this.#storage = storage;
     }
 
     /*
@@ -182,12 +162,12 @@ export class Mastra<
     }
 
     if (config?.memory) {
-      this.memory = config.memory;
+      this.#memory = config.memory;
       if (this.#telemetry) {
-        this.memory = this.#telemetry.traceClass(config.memory, {
+        this.#memory = this.#telemetry.traceClass(config.memory, {
           excludeMethods: ['__setTelemetry', '__getTelemetry'],
         });
-        this.memory.__setTelemetry(this.#telemetry);
+        this.#memory.__setTelemetry(this.#telemetry);
       }
     }
 
@@ -329,7 +309,7 @@ This is a warning for now, but will throw an error in the future
   }
 
   public setStorage(storage: MastraStorage) {
-    this.storage = storage;
+    this.#storage = storage;
   }
 
   public setLogger({ logger }: { logger: TLogger }) {
@@ -341,8 +321,8 @@ This is a warning for now, but will throw an error in the future
       });
     }
 
-    if (this.memory) {
-      this.memory.__setLogger(this.#logger);
+    if (this.#memory) {
+      this.#memory.__setLogger(this.#logger);
     }
 
     if (this.#deployer) {
@@ -355,8 +335,8 @@ This is a warning for now, but will throw an error in the future
       });
     }
 
-    if (this.storage) {
-      this.storage.__setLogger(this.#logger);
+    if (this.#storage) {
+      this.#storage.__setLogger(this.#logger);
     }
 
     if (this.#vectors) {
@@ -377,11 +357,11 @@ This is a warning for now, but will throw an error in the future
       });
     }
 
-    if (this.memory) {
-      this.memory = this.#telemetry.traceClass(this.memory, {
+    if (this.#memory) {
+      this.#memory = this.#telemetry.traceClass(this.#memory, {
         excludeMethods: ['__setTelemetry', '__getTelemetry'],
       });
-      this.memory.__setTelemetry(this.#telemetry);
+      this.#memory.__setTelemetry(this.#telemetry);
     }
 
     if (this.#deployer) {
@@ -404,11 +384,11 @@ This is a warning for now, but will throw an error in the future
       this.#tts = tts as TTTS;
     }
 
-    if (this.storage) {
-      this.storage = this.#telemetry.traceClass(this.storage, {
+    if (this.#storage) {
+      this.#storage = this.#telemetry.traceClass(this.#storage, {
         excludeMethods: ['__setTelemetry', '__getTelemetry'],
       });
-      this.storage.__setTelemetry(this.#telemetry);
+      this.#storage.__setTelemetry(this.#telemetry);
     }
 
     if (this.#vectors) {
@@ -438,11 +418,11 @@ This is a warning for now, but will throw an error in the future
   }
 
   public getMemory() {
-    return this.memory;
+    return this.#memory;
   }
 
   public getStorage() {
-    return this.storage;
+    return this.#storage;
   }
 
   public getServerMiddleware() {
diff --git a/packages/core/src/memory/memory.ts b/packages/core/src/memory/memory.ts
index bf3ee1673de..da1c59001e8 100644
--- a/packages/core/src/memory/memory.ts
+++ b/packages/core/src/memory/memory.ts
@@ -12,7 +12,7 @@ import type {
 
 import { MastraBase } from '../base';
 import type { MastraStorage, StorageGetMessagesArg } from '../storage';
-import { DefaultStorage } from '../storage/libsql';
+import { DefaultProxyStorage } from '../storage/default-proxy-storage';
 import type { CoreTool } from '../tools';
 import { deepMerge } from '../utils';
 import type { MastraVector } from '../vector';
@@ -45,7 +45,7 @@ export abstract class MastraMemory extends MastraBase {
 
     this.storage =
       config.storage ||
-      new DefaultStorage({
+      new DefaultProxyStorage({
         config: {
           url: 'file:memory.db',
         },
diff --git a/packages/core/src/storage/README.md b/packages/core/src/storage/README.md
index 56a42f738b5..181bf681a1d 100644
--- a/packages/core/src/storage/README.md
+++ b/packages/core/src/storage/README.md
@@ -57,8 +57,8 @@ import { Memory } from '@mastra/memory';
 const memory = new Memory({
   options: {
     lastMessages: 10,
-    semanticRecall: true
-  }
+    semanticRecall: true,
+  },
 });
 ```
 
@@ -70,7 +70,7 @@ import { DefaultStorage } from '@mastra/core/storage';
 const storage = new DefaultStorage({
   name: 'my-storage',
   config: {
-    url: 'file:my-database.db', // or 'file:memory:' for in-memory
+    url: 'file:my-database.db', // or 'file::memory:' for in-memory
   },
 });
 
diff --git a/packages/core/src/storage/bundle.test.ts b/packages/core/src/storage/bundle.test.ts
index a31b1d12a17..b61592bcfbc 100644
--- a/packages/core/src/storage/bundle.test.ts
+++ b/packages/core/src/storage/bundle.test.ts
@@ -1,11 +1,17 @@
 import { spawn as spwn } from 'child_process';
+import path, { dirname, join } from 'path';
+import { fileURLToPath } from 'url';
 import type { RollupOutput } from 'rollup';
 import { rollup } from 'rollup';
 import { expect, beforeAll, it } from 'vitest';
 
+const _dirname = dirname(fileURLToPath(import.meta.url));
 const spawn = (cmd: string, args: ReadonlyArray<string>) =>
   new Promise((resolve, reject) => {
-    const cp = spwn(cmd, args);
+    const cp = spwn(cmd, args, {
+      shell: true,
+      cwd: join(_dirname, '..', '..'),
+    });
     const error: string[] = [];
     const stdout: string[] = [];
     cp.stdout.on('data', data => {
@@ -31,7 +37,7 @@ beforeAll(async () => {
 
   const bundler = await rollup({
     logLevel: 'silent',
-    input: 'dist/storage/index.js',
+    input: join(_dirname, '..', '..', 'dist', 'storage', 'index.js'),
     preserveSymlinks: true,
   });
   const { output: bundlerOutput } = await bundler.generate({
diff --git a/packages/core/src/storage/default-proxy-storage.test.ts b/packages/core/src/storage/default-proxy-storage.test.ts
new file mode 100644
index 00000000000..beb2004cd50
--- /dev/null
+++ b/packages/core/src/storage/default-proxy-storage.test.ts
@@ -0,0 +1,11 @@
+import { DefaultProxyStorage } from './default-proxy-storage';
+import { createTestSuite } from './test-utils/storage';
+
+// Test database configuration
+const TEST_DB_URL = 'file::memory:?cache=shared'; // Use in-memory SQLite for tests
+
+createTestSuite(
+  new DefaultProxyStorage({
+    config: { url: TEST_DB_URL },
+  }),
+);
diff --git a/packages/core/src/storage/default-proxy-storage.ts b/packages/core/src/storage/default-proxy-storage.ts
new file mode 100644
index 00000000000..7fc511dc78d
--- /dev/null
+++ b/packages/core/src/storage/default-proxy-storage.ts
@@ -0,0 +1,124 @@
+import type { MessageType, StorageThreadType } from '../memory/types';
+import { MastraStorage } from './base';
+import type { TABLE_NAMES } from './constants';
+import type { DefaultStorage, type LibSQLConfig } from './libsql';
+import type { EvalRow, StorageColumn, StorageGetMessagesArg } from './types';
+
+/**
+ * A proxy for the DefaultStorage (LibSQLStore) to allow for dynamically loading the storage in a constructor
+ */
+export class DefaultProxyStorage extends MastraStorage {
+  private storage: DefaultStorage | null = null;
+  private storageConfig: LibSQLConfig;
+  private isInitializingPromise: Promise<void> | null = null;
+
+  constructor({ config }: { config: LibSQLConfig }) {
+    super({ name: 'DefaultStorage' });
+    this.storageConfig = config;
+  }
+
+  private setupStorage() {
+    if (!this.isInitializingPromise) {
+      this.isInitializingPromise = new Promise((resolve, reject) => {
+        import('./libsql')
+          .then(({ DefaultStorage }) => {
+            this.storage = new DefaultStorage({ config: this.storageConfig });
+            resolve();
+          })
+          .catch(reject);
+      });
+    }
+
+    return this.isInitializingPromise;
+  }
+
+  async createTable({
+    tableName,
+    schema,
+  }: {
+    tableName: TABLE_NAMES;
+    schema: Record<string, StorageColumn>;
+  }): Promise<void> {
+    await this.setupStorage();
+    return this.storage!.createTable({ tableName, schema });
+  }
+
+  async clearTable({ tableName }: { tableName: TABLE_NAMES }): Promise<void> {
+    await this.setupStorage();
+    return this.storage!.clearTable({ tableName });
+  }
+
+  async insert({ tableName, record }: { tableName: TABLE_NAMES; record: Record<string, any> }): Promise<void> {
+    await this.setupStorage();
+    return this.storage!.insert({ tableName, record });
+  }
+
+  async batchInsert({ tableName, records }: { tableName: TABLE_NAMES; records: Record<string, any>[] }): Promise<void> {
+    await this.setupStorage();
+    return this.storage!.batchInsert({ tableName, records });
+  }
+
+  async load<R>({ tableName, keys }: { tableName: TABLE_NAMES; keys: Record<string, string> }): Promise<R | null> {
+    await this.setupStorage();
+    return this.storage!.load<R>({ tableName, keys });
+  }
+
+  async getThreadById({ threadId }: { threadId: string }): Promise<StorageThreadType | null> {
+    await this.setupStorage();
+    return this.storage!.getThreadById({ threadId });
+  }
+
+  async getThreadsByResourceId({ resourceId }: { resourceId: string }): Promise<StorageThreadType[]> {
+    await this.setupStorage();
+    return this.storage!.getThreadsByResourceId({ resourceId });
+  }
+
+  async saveThread({ thread }: { thread: StorageThreadType }): Promise<StorageThreadType> {
+    await this.setupStorage();
+    return this.storage!.saveThread({ thread });
+  }
+
+  async updateThread({
+    id,
+    title,
+    metadata,
+  }: {
+    id: string;
+    title: string;
+    metadata: Record<string, unknown>;
+  }): Promise<StorageThreadType> {
+    await this.setupStorage();
+    return this.storage!.updateThread({ id, title, metadata });
+  }
+
+  async deleteThread({ threadId }: { threadId: string }): Promise<void> {
+    await this.setupStorage();
+    return this.storage!.deleteThread({ threadId });
+  }
+
+  async getMessages<T extends MessageType[]>({ threadId, selectBy }: StorageGetMessagesArg): Promise<T> {
+    await this.setupStorage();
+    return this.storage!.getMessages<T>({ threadId, selectBy });
+  }
+
+  async saveMessages({ messages }: { messages: MessageType[] }): Promise<MessageType[]> {
+    await this.setupStorage();
+    return this.storage!.saveMessages({ messages });
+  }
+
+  async getEvalsByAgentName(agentName: string, type?: 'test' | 'live'): Promise<EvalRow[]> {
+    await this.setupStorage();
+    return this.storage!.getEvalsByAgentName(agentName, type);
+  }
+
+  async getTraces(options?: {
+    name?: string;
+    scope?: string;
+    page: number;
+    perPage: number;
+    attributes?: Record<string, string>;
+  }): Promise<any[]> {
+    await this.setupStorage();
+    return this.storage!.getTraces(options);
+  }
+}
diff --git a/packages/core/src/storage/libsql/index.test.ts b/packages/core/src/storage/libsql/index.test.ts
index f6bfdc52cff..0ceaf6d88e1 100644
--- a/packages/core/src/storage/libsql/index.test.ts
+++ b/packages/core/src/storage/libsql/index.test.ts
@@ -1,418 +1,12 @@
-import { randomUUID } from 'crypto';
-import { describe, it, expect, beforeAll, beforeEach, afterAll } from 'vitest';
-
-import type { WorkflowRunState } from '../../workflows';
+import { createTestSuite } from '../test-utils/storage';
 
 import { DefaultStorage } from './index';
 
 // Test database configuration
-const TEST_DB_URL = 'file:memory:'; // Use in-memory SQLite for tests
+const TEST_DB_URL = 'file::memory:?cache=shared'; // Use in-memory SQLite for tests
 
-describe('DefaultStorage', () => {
-  const storage = new DefaultStorage({
+createTestSuite(
+  new DefaultStorage({
     config: { url: TEST_DB_URL },
-  });
-
-  // Sample test data factory functions to ensure unique records
-  const createSampleThread = () => ({
-    id: `thread-${randomUUID()}`,
-    resourceId: `resource-${randomUUID()}`,
-    title: 'Test Thread',
-    createdAt: new Date(),
-    updatedAt: new Date(),
-    metadata: { key: 'value' },
-  });
-
-  const createSampleThreadWithParams = (threadId: string, resourceId: string, createdAt: Date, updatedAt: Date) => ({
-    id: threadId,
-    resourceId,
-    title: 'Test Thread with given ThreadId and ResourceId',
-    createdAt,
-    updatedAt,
-    metadata: { key: 'value' },
-  });
-
-  const createSampleMessage = (threadId: string) =>
-    ({
-      id: `msg-${randomUUID()}`,
-      role: 'user',
-      type: 'text',
-      threadId,
-      content: [{ type: 'text', text: 'Hello' }],
-      createdAt: new Date(),
-    }) as any;
-
-  beforeAll(async () => {
-    await storage.init();
-  });
-
-  beforeEach(async () => {
-    // Clear tables before each test
-    await storage.clearTable({ tableName: 'mastra_workflow_snapshot' });
-    await storage.clearTable({ tableName: 'mastra_evals' });
-    await storage.clearTable({ tableName: 'mastra_messages' });
-    await storage.clearTable({ tableName: 'mastra_threads' });
-  });
-
-  afterAll(async () => {
-    // Clear tables after tests
-    await storage.clearTable({ tableName: 'mastra_workflow_snapshot' });
-    await storage.clearTable({ tableName: 'mastra_evals' });
-    await storage.clearTable({ tableName: 'mastra_messages' });
-    await storage.clearTable({ tableName: 'mastra_threads' });
-  });
-
-  describe('Thread Operations', () => {
-    it('should create and retrieve a thread', async () => {
-      const thread = createSampleThread();
-
-      // Save thread
-      const savedThread = await storage.__saveThread({ thread });
-      expect(savedThread).toEqual(thread);
-
-      // Retrieve thread
-      const retrievedThread = await storage.__getThreadById({ threadId: thread.id });
-      expect(retrievedThread?.title).toEqual(thread.title);
-    });
-
-    it('should create and retrieve a thread with the same given threadId and resourceId', async () => {
-      const exampleThreadId = '1346362547862769664';
-      const exampleResourceId = '532374164040974346';
-      const createdAt = new Date();
-      const updatedAt = new Date();
-      const thread = createSampleThreadWithParams(exampleThreadId, exampleResourceId, createdAt, updatedAt);
-
-      // Save thread
-      const savedThread = await storage.__saveThread({ thread });
-      expect(savedThread).toEqual(thread);
-
-      // Retrieve thread
-      const retrievedThread = await storage.__getThreadById({ threadId: thread.id });
-      expect(retrievedThread?.id).toEqual(exampleThreadId);
-      expect(retrievedThread?.resourceId).toEqual(exampleResourceId);
-      expect(retrievedThread?.title).toEqual(thread.title);
-      expect(retrievedThread?.createdAt).toEqual(createdAt.toISOString());
-      expect(retrievedThread?.updatedAt).toEqual(updatedAt.toISOString());
-    });
-
-    it('should return null for non-existent thread', async () => {
-      const result = await storage.__getThreadById({ threadId: 'non-existent' });
-      expect(result).toBeNull();
-    });
-
-    it('should get threads by resource ID', async () => {
-      const thread1 = createSampleThread();
-      const thread2 = { ...createSampleThread(), resourceId: thread1.resourceId };
-
-      await storage.saveThread({ thread: thread1 });
-      await storage.saveThread({ thread: thread2 });
-
-      const threads = await storage.getThreadsByResourceId({ resourceId: thread1.resourceId });
-      expect(threads).toHaveLength(2);
-      expect(threads.map(t => t.id)).toEqual(expect.arrayContaining([thread1.id, thread2.id]));
-    });
-
-    it('should update thread title and metadata', async () => {
-      const thread = createSampleThread();
-      await storage.__saveThread({ thread });
-
-      const newMetadata = { newKey: 'newValue' };
-      const updatedThread = await storage.__updateThread({
-        id: thread.id,
-        title: 'Updated Title',
-        metadata: newMetadata,
-      });
-
-      expect(updatedThread.title).toBe('Updated Title');
-      expect(updatedThread.metadata).toEqual({
-        ...thread.metadata,
-        ...newMetadata,
-      });
-
-      // Verify persistence
-      const retrievedThread = await storage.getThreadById({ threadId: thread.id });
-      expect(retrievedThread).toEqual(updatedThread);
-    });
-
-    it('should delete thread', async () => {
-      const thread = createSampleThread();
-      await storage.saveThread({ thread });
-
-      await storage.deleteThread({ threadId: thread.id });
-
-      const retrievedThread = await storage.getThreadById({ threadId: thread.id });
-      expect(retrievedThread).toBeNull();
-    });
-  });
-
-  describe('Message Operations', () => {
-    it('should save and retrieve messages', async () => {
-      const thread = createSampleThread();
-      await storage.saveThread({ thread });
-
-      const messages = [createSampleMessage(thread.id), createSampleMessage(thread.id)];
-
-      // Save messages
-      const savedMessages = await storage.__saveMessages({ messages });
-
-      expect(savedMessages).toEqual(messages);
-
-      // Retrieve messages
-      const retrievedMessages = await storage.__getMessages({ threadId: thread.id });
-
-      expect(retrievedMessages).toHaveLength(2);
-
-      expect(retrievedMessages).toEqual(expect.arrayContaining(messages));
-    });
-
-    it('should handle empty message array', async () => {
-      const result = await storage.saveMessages({ messages: [] });
-      expect(result).toEqual([]);
-    });
-
-    it('should maintain message order', async () => {
-      const thread = createSampleThread();
-      await storage.saveThread({ thread });
-
-      const messages = [
-        { ...createSampleMessage(thread.id), content: [{ type: 'text', text: 'First' }] },
-        { ...createSampleMessage(thread.id), content: [{ type: 'text', text: 'Second' }] },
-        { ...createSampleMessage(thread.id), content: [{ type: 'text', text: 'Third' }] },
-      ];
-
-      await storage.saveMessages({ messages });
-
-      const retrievedMessages = await storage.getMessages({ threadId: thread.id });
-
-      expect(retrievedMessages).toHaveLength(3);
-
-      // Verify order is maintained
-      retrievedMessages.forEach((_msg, _idx) => {
-        // expect(msg.content[0]).toBe(messages[idx].content.text)
-      });
-    });
-
-    it('should rollback on error during message save', async () => {
-      const thread = createSampleThread();
-      await storage.saveThread({ thread });
-
-      const messages = [
-        createSampleMessage(thread.id),
-        { ...createSampleMessage(thread.id), id: null }, // This will cause an error
-      ];
-
-      await expect(storage.saveMessages({ messages })).rejects.toThrow();
-
-      // Verify no messages were saved
-      const savedMessages = await storage.getMessages({ threadId: thread.id });
-      expect(savedMessages).toHaveLength(0);
-    });
-  });
-
-  describe('Edge Cases and Error Handling', () => {
-    it('should handle large metadata objects', async () => {
-      const thread = createSampleThread();
-      const largeMetadata = {
-        ...thread.metadata,
-        largeArray: Array.from({ length: 1000 }, (_, i) => ({ index: i, data: 'test'.repeat(100) })),
-      };
-
-      const threadWithLargeMetadata = {
-        ...thread,
-        metadata: largeMetadata,
-      };
-
-      await storage.saveThread({ thread: threadWithLargeMetadata });
-      const retrieved = await storage.getThreadById({ threadId: thread.id });
-
-      expect(retrieved?.metadata).toEqual(largeMetadata);
-    });
-
-    it('should handle special characters in thread titles', async () => {
-      const thread = {
-        ...createSampleThread(),
-        title: 'Special \'quotes\' and "double quotes" and emoji 🎉',
-      };
-
-      await storage.saveThread({ thread });
-      const retrieved = await storage.getThreadById({ threadId: thread.id });
-
-      expect(retrieved?.title).toBe(thread.title);
-    });
-
-    it('should handle concurrent thread updates', async () => {
-      const thread = createSampleThread();
-      await storage.saveThread({ thread });
-
-      // Perform multiple updates concurrently
-      const updates = Array.from({ length: 5 }, (_, i) =>
-        storage.updateThread({
-          id: thread.id,
-          title: `Update ${i}`,
-          metadata: { update: i },
-        }),
-      );
-
-      await expect(Promise.all(updates)).resolves.toBeDefined();
-
-      // Verify final state
-      const finalThread = await storage.getThreadById({ threadId: thread.id });
-      expect(finalThread).toBeDefined();
-    });
-  });
-
-  describe('Workflow Snapshots', () => {
-    beforeAll(async () => {
-      // Create workflow_snapshot table
-      await storage.createTable({
-        tableName: 'mastra_workflow_snapshot',
-        schema: {
-          workflow_name: { type: 'text', nullable: false },
-          run_id: { type: 'text', nullable: false },
-          snapshot: { type: 'text', nullable: false },
-          created_at: { type: 'timestamp', nullable: false },
-          updated_at: { type: 'timestamp', nullable: false },
-        },
-      });
-    });
-
-    it('should persist and load workflow snapshots', async () => {
-      const workflowName = 'test-workflow';
-      const runId = `run-${randomUUID()}`;
-      const snapshot = {
-        status: 'running',
-        context: {
-          stepResults: {},
-          attempts: {},
-          triggerData: { type: 'manual' },
-        },
-      } as any;
-
-      await storage.persistWorkflowSnapshot({
-        workflowName,
-        runId,
-        snapshot,
-      });
-
-      const loadedSnapshot = await storage.loadWorkflowSnapshot({
-        workflowName,
-        runId,
-      });
-
-      expect(loadedSnapshot).toEqual(snapshot);
-    });
-
-    it('should return null for non-existent workflow snapshot', async () => {
-      const result = await storage.loadWorkflowSnapshot({
-        workflowName: 'non-existent',
-        runId: 'non-existent',
-      });
-
-      expect(result).toBeNull();
-    });
-
-    it('should update existing workflow snapshot', async () => {
-      const workflowName = 'test-workflow';
-      const runId = `run-${randomUUID()}`;
-      const initialSnapshot = {
-        status: 'running',
-        context: {
-          stepResults: {},
-          attempts: {},
-          triggerData: { type: 'manual' },
-        },
-      };
-
-      await storage.persistWorkflowSnapshot({
-        workflowName,
-        runId,
-        snapshot: initialSnapshot as any,
-      });
-
-      const updatedSnapshot = {
-        status: 'completed',
-        context: {
-          stepResults: {
-            'step-1': { status: 'success', result: { data: 'test' } },
-          },
-          attempts: { 'step-1': 1 },
-          triggerData: { type: 'manual' },
-        },
-      } as any;
-
-      await storage.persistWorkflowSnapshot({
-        workflowName,
-        runId,
-        snapshot: updatedSnapshot,
-      });
-
-      const loadedSnapshot = await storage.loadWorkflowSnapshot({
-        workflowName,
-        runId,
-      });
-
-      expect(loadedSnapshot).toEqual(updatedSnapshot);
-    });
-
-    it('should handle complex workflow state', async () => {
-      const workflowName = 'complex-workflow';
-      const runId = `run-${randomUUID()}`;
-      const complexSnapshot = {
-        value: { currentState: 'running' },
-        context: {
-          stepResults: {
-            'step-1': {
-              status: 'success',
-              result: {
-                nestedData: {
-                  array: [1, 2, 3],
-                  object: { key: 'value' },
-                  date: new Date().toISOString(),
-                },
-              },
-            },
-            'step-2': {
-              status: 'waiting',
-              dependencies: ['step-3', 'step-4'],
-            },
-          },
-          attempts: { 'step-1': 1, 'step-2': 0 },
-          triggerData: {
-            type: 'scheduled',
-            metadata: {
-              schedule: '0 0 * * *',
-              timezone: 'UTC',
-            },
-          },
-        },
-        activePaths: [
-          {
-            stepPath: ['step-1'],
-            stepId: 'step-1',
-            status: 'success',
-          },
-          {
-            stepPath: ['step-2'],
-            stepId: 'step-2',
-            status: 'waiting',
-          },
-        ],
-        runId: runId,
-        timestamp: Date.now(),
-      };
-
-      await storage.persistWorkflowSnapshot({
-        workflowName,
-        runId,
-        snapshot: complexSnapshot as WorkflowRunState,
-      });
-
-      const loadedSnapshot = await storage.loadWorkflowSnapshot({
-        workflowName,
-        runId,
-      });
-
-      expect(loadedSnapshot).toEqual(complexSnapshot);
-    });
-  });
-});
+  }),
+);
diff --git a/packages/core/src/storage/libsql/index.ts b/packages/core/src/storage/libsql/index.ts
index 7e21d75e8bb..56873ee0d62 100644
--- a/packages/core/src/storage/libsql/index.ts
+++ b/packages/core/src/storage/libsql/index.ts
@@ -29,7 +29,7 @@ export class LibSQLStore extends MastraStorage {
     super({ name: `LibSQLStore` });
 
     // need to re-init every time for in memory dbs or the tables might not exist
-    if (config.url === ':memory:') {
+    if (config.url === ':memory:' || config.url.startsWith('file::memory:')) {
       this.shouldCacheInit = false;
     }
 
@@ -51,7 +51,7 @@ export class LibSQLStore extends MastraStorage {
   // this means `file:` urls are always relative to project root
   // TODO: can we make this easier via bundling? https://github.com/mastra-ai/mastra/pull/2783#pullrequestreview-2662444241
   protected rewriteDbUrl(url: string): string {
-    if (url.startsWith('file:')) {
+    if (url.startsWith('file:') && url !== 'file::memory:') {
       const pathPart = url.slice('file:'.length);
 
       if (isAbsolute(pathPart)) {
diff --git a/packages/core/src/storage/libsql/url.test.ts b/packages/core/src/storage/libsql/url.test.ts
index c7ada25bf7a..d87bc79d59e 100644
--- a/packages/core/src/storage/libsql/url.test.ts
+++ b/packages/core/src/storage/libsql/url.test.ts
@@ -1,4 +1,5 @@
-import { rmSync, mkdirSync, existsSync } from 'node:fs';
+import { existsSync } from 'node:fs';
+import { rm, stat, mkdir, mkdtemp } from 'node:fs/promises';
 import { tmpdir } from 'node:os';
 import { join } from 'node:path';
 
@@ -20,21 +21,27 @@ describe('LibSQLStore URL rewriting', () => {
   let originalCwd: string;
   let parentDir: string;
 
-  beforeEach(() => {
-    tmpDir = join(tmpdir(), 'mastra-test-libsql-store-url');
-    if (existsSync(tmpDir)) {
-      rmSync(tmpDir, { recursive: true, force: true });
+  beforeEach(async () => {
+    try {
+      tmpDir = await mkdtemp(join(tmpdir(), 'mastra-test-libsql-'));
+    } catch {
+      // ignore
     }
-    mkdirSync(tmpDir);
+
     originalCwd = process.cwd();
     process.chdir(tmpDir);
     parentDir = join(tmpDir, '..');
   });
 
-  afterEach(() => {
+  afterEach(async () => {
     process.chdir(originalCwd);
-    if (existsSync(tmpDir)) {
-      rmSync(tmpDir, { recursive: true, force: true });
+
+    try {
+      if (await stat(tmpDir)) {
+        await rm(tmpDir, { recursive: true, force: true });
+      }
+    } catch {
+      // ignore
     }
   });
 
@@ -42,6 +49,7 @@ describe('LibSQLStore URL rewriting', () => {
     it('should create db file in project root when running from project root', async () => {
       const store = new LibSQLStore({ config: { url: 'file:test.db' } });
       await store.init();
+
       expect(existsSync(join(tmpDir, 'test.db'))).toBe(true);
       expect(existsSync(join(tmpDir, '.mastra', 'test.db'))).toBe(false);
       expect(existsSync(join(tmpDir, '.mastra', 'output', 'test.db'))).toBe(false);
@@ -50,7 +58,7 @@ describe('LibSQLStore URL rewriting', () => {
 
     it('should create db file in project root when running from .mastra/output', async () => {
       const mastraOutputDir = join(tmpDir, '.mastra', 'output');
-      mkdirSync(mastraOutputDir, { recursive: true });
+      await mkdir(mastraOutputDir, { recursive: true });
       process.chdir(mastraOutputDir);
       const store = new LibSQLStore({ config: { url: 'file:test.db' } });
       await store.init();
@@ -62,7 +70,7 @@ describe('LibSQLStore URL rewriting', () => {
 
     it('should create db file in .mastra directory when explicitly specified', async () => {
       const mastraDir = join(tmpDir, '.mastra');
-      mkdirSync(mastraDir, { recursive: true });
+      await mkdir(mastraDir, { recursive: true });
       const store = new LibSQLStore({ config: { url: 'file:.mastra/test.db' } });
       await store.init();
       expect(existsSync(join(tmpDir, 'test.db'))).toBe(false);
@@ -74,7 +82,7 @@ describe('LibSQLStore URL rewriting', () => {
     it('should create db file in .mastra directory when explicitly specified and running from .mastra/output', async () => {
       const mastraDir = join(tmpDir, '.mastra');
       const mastraOutputDir = join(mastraDir, 'output');
-      mkdirSync(mastraOutputDir, { recursive: true });
+      await mkdir(mastraOutputDir, { recursive: true });
       process.chdir(mastraOutputDir);
       const store = new LibSQLStore({ config: { url: 'file:.mastra/test.db' } });
       await store.init();
@@ -107,7 +115,7 @@ describe('LibSQLStore URL rewriting', () => {
 
       // Switch to .mastra/output and write another record
       const mastraOutputDir = join(tmpDir, '.mastra', 'output');
-      mkdirSync(mastraOutputDir, { recursive: true });
+      await mkdir(mastraOutputDir, { recursive: true });
       process.chdir(mastraOutputDir);
 
       const store2 = new LibSQLStore({ config: { url: 'file:test.db' } });
@@ -157,4 +165,3 @@ describe('LibSQLStore URL rewriting', () => {
     });
   });
 });
-
diff --git a/packages/core/src/storage/test-utils/storage.ts b/packages/core/src/storage/test-utils/storage.ts
new file mode 100644
index 00000000000..73a81b965dd
--- /dev/null
+++ b/packages/core/src/storage/test-utils/storage.ts
@@ -0,0 +1,414 @@
+import { randomUUID } from 'crypto';
+import { describe, it, expect, beforeAll, beforeEach, afterAll } from 'vitest';
+
+import type { WorkflowRunState } from '../../workflows';
+
+import type { MastraStorage } from '../base';
+import { TABLE_WORKFLOW_SNAPSHOT } from '../constants';
+
+export function createTestSuite(storage: MastraStorage) {
+  describe('DefaultStorage', () => {
+    // Sample test data factory functions to ensure unique records
+    const createSampleThread = () => ({
+      id: `thread-${randomUUID()}`,
+      resourceId: `resource-${randomUUID()}`,
+      title: 'Test Thread',
+      createdAt: new Date(),
+      updatedAt: new Date(),
+      metadata: { key: 'value' },
+    });
+
+    const createSampleThreadWithParams = (threadId: string, resourceId: string, createdAt: Date, updatedAt: Date) => ({
+      id: threadId,
+      resourceId,
+      title: 'Test Thread with given ThreadId and ResourceId',
+      createdAt,
+      updatedAt,
+      metadata: { key: 'value' },
+    });
+
+    const createSampleMessage = (threadId: string) =>
+      ({
+        id: `msg-${randomUUID()}`,
+        role: 'user',
+        type: 'text',
+        threadId,
+        content: [{ type: 'text', text: 'Hello' }],
+        createdAt: new Date(),
+      }) as any;
+
+    beforeAll(async () => {
+      await storage.init();
+    });
+
+    beforeEach(async () => {
+      // Clear tables before each test
+      await storage.clearTable({ tableName: TABLE_WORKFLOW_SNAPSHOT });
+      await storage.clearTable({ tableName: 'mastra_evals' });
+      await storage.clearTable({ tableName: 'mastra_messages' });
+      await storage.clearTable({ tableName: 'mastra_threads' });
+    });
+
+    afterAll(async () => {
+      // Clear tables after tests
+      await storage.clearTable({ tableName: TABLE_WORKFLOW_SNAPSHOT });
+      await storage.clearTable({ tableName: 'mastra_evals' });
+      await storage.clearTable({ tableName: 'mastra_messages' });
+      await storage.clearTable({ tableName: 'mastra_threads' });
+    });
+
+    describe('Thread Operations', () => {
+      it('should create and retrieve a thread', async () => {
+        const thread = createSampleThread();
+
+        // Save thread
+        const savedThread = await storage.__saveThread({ thread });
+        expect(savedThread).toEqual(thread);
+
+        // Retrieve thread
+        const retrievedThread = await storage.__getThreadById({ threadId: thread.id });
+        expect(retrievedThread?.title).toEqual(thread.title);
+      });
+
+      it('should create and retrieve a thread with the same given threadId and resourceId', async () => {
+        const exampleThreadId = '1346362547862769664';
+        const exampleResourceId = '532374164040974346';
+        const createdAt = new Date();
+        const updatedAt = new Date();
+        const thread = createSampleThreadWithParams(exampleThreadId, exampleResourceId, createdAt, updatedAt);
+
+        // Save thread
+        const savedThread = await storage.__saveThread({ thread });
+        expect(savedThread).toEqual(thread);
+
+        // Retrieve thread
+        const retrievedThread = await storage.__getThreadById({ threadId: thread.id });
+        expect(retrievedThread?.id).toEqual(exampleThreadId);
+        expect(retrievedThread?.resourceId).toEqual(exampleResourceId);
+        expect(retrievedThread?.title).toEqual(thread.title);
+        expect(retrievedThread?.createdAt).toEqual(createdAt.toISOString());
+        expect(retrievedThread?.updatedAt).toEqual(updatedAt.toISOString());
+      });
+
+      it('should return null for non-existent thread', async () => {
+        const result = await storage.__getThreadById({ threadId: 'non-existent' });
+        expect(result).toBeNull();
+      });
+
+      it('should get threads by resource ID', async () => {
+        const thread1 = createSampleThread();
+        const thread2 = { ...createSampleThread(), resourceId: thread1.resourceId };
+
+        await storage.saveThread({ thread: thread1 });
+        await storage.saveThread({ thread: thread2 });
+
+        const threads = await storage.getThreadsByResourceId({ resourceId: thread1.resourceId });
+        expect(threads).toHaveLength(2);
+        expect(threads.map(t => t.id)).toEqual(expect.arrayContaining([thread1.id, thread2.id]));
+      });
+
+      it('should update thread title and metadata', async () => {
+        const thread = createSampleThread();
+        await storage.__saveThread({ thread });
+
+        const newMetadata = { newKey: 'newValue' };
+        const updatedThread = await storage.__updateThread({
+          id: thread.id,
+          title: 'Updated Title',
+          metadata: newMetadata,
+        });
+
+        expect(updatedThread.title).toBe('Updated Title');
+        expect(updatedThread.metadata).toEqual({
+          ...thread.metadata,
+          ...newMetadata,
+        });
+
+        // Verify persistence
+        const retrievedThread = await storage.getThreadById({ threadId: thread.id });
+        expect(retrievedThread).toEqual(updatedThread);
+      });
+
+      it('should delete thread', async () => {
+        const thread = createSampleThread();
+        await storage.saveThread({ thread });
+
+        await storage.deleteThread({ threadId: thread.id });
+
+        const retrievedThread = await storage.getThreadById({ threadId: thread.id });
+        expect(retrievedThread).toBeNull();
+      });
+    });
+
+    describe('Message Operations', () => {
+      it('should save and retrieve messages', async () => {
+        const thread = createSampleThread();
+        await storage.saveThread({ thread });
+
+        const messages = [createSampleMessage(thread.id), createSampleMessage(thread.id)];
+
+        // Save messages
+        const savedMessages = await storage.__saveMessages({ messages });
+
+        expect(savedMessages).toEqual(messages);
+
+        // Retrieve messages
+        const retrievedMessages = await storage.__getMessages({ threadId: thread.id });
+
+        expect(retrievedMessages).toHaveLength(2);
+
+        expect(retrievedMessages).toEqual(expect.arrayContaining(messages));
+      });
+
+      it('should handle empty message array', async () => {
+        const result = await storage.saveMessages({ messages: [] });
+        expect(result).toEqual([]);
+      });
+
+      it('should maintain message order', async () => {
+        const thread = createSampleThread();
+        await storage.saveThread({ thread });
+
+        const messages = [
+          { ...createSampleMessage(thread.id), content: [{ type: 'text', text: 'First' }] },
+          { ...createSampleMessage(thread.id), content: [{ type: 'text', text: 'Second' }] },
+          { ...createSampleMessage(thread.id), content: [{ type: 'text', text: 'Third' }] },
+        ];
+
+        await storage.saveMessages({ messages });
+
+        const retrievedMessages = await storage.getMessages({ threadId: thread.id });
+
+        expect(retrievedMessages).toHaveLength(3);
+
+        // Verify order is maintained
+        retrievedMessages.forEach((_msg, _idx) => {
+          // expect(msg.content[0]).toBe(messages[idx].content.text)
+        });
+      });
+
+      it('should rollback on error during message save', async () => {
+        const thread = createSampleThread();
+        await storage.saveThread({ thread });
+
+        const messages = [
+          createSampleMessage(thread.id),
+          { ...createSampleMessage(thread.id), id: null }, // This will cause an error
+        ];
+
+        await expect(storage.saveMessages({ messages })).rejects.toThrow();
+
+        // Verify no messages were saved
+        const savedMessages = await storage.getMessages({ threadId: thread.id });
+        expect(savedMessages).toHaveLength(0);
+      });
+    });
+
+    describe('Edge Cases and Error Handling', () => {
+      it('should handle large metadata objects', async () => {
+        const thread = createSampleThread();
+        const largeMetadata = {
+          ...thread.metadata,
+          largeArray: Array.from({ length: 1000 }, (_, i) => ({ index: i, data: 'test'.repeat(100) })),
+        };
+
+        const threadWithLargeMetadata = {
+          ...thread,
+          metadata: largeMetadata,
+        };
+
+        await storage.saveThread({ thread: threadWithLargeMetadata });
+        const retrieved = await storage.getThreadById({ threadId: thread.id });
+
+        expect(retrieved?.metadata).toEqual(largeMetadata);
+      });
+
+      it('should handle special characters in thread titles', async () => {
+        const thread = {
+          ...createSampleThread(),
+          title: 'Special \'quotes\' and "double quotes" and emoji 🎉',
+        };
+
+        await storage.saveThread({ thread });
+        const retrieved = await storage.getThreadById({ threadId: thread.id });
+
+        expect(retrieved?.title).toBe(thread.title);
+      });
+
+      it('should handle concurrent thread updates', async () => {
+        const thread = createSampleThread();
+        await storage.saveThread({ thread });
+
+        // Perform multiple updates concurrently
+        const updates = Array.from({ length: 5 }, (_, i) =>
+          storage.updateThread({
+            id: thread.id,
+            title: `Update ${i}`,
+            metadata: { update: i },
+          }),
+        );
+
+        await expect(Promise.all(updates)).resolves.toBeDefined();
+
+        // Verify final state
+        const finalThread = await storage.getThreadById({ threadId: thread.id });
+        expect(finalThread).toBeDefined();
+      });
+    });
+
+    describe('Workflow Snapshots', () => {
+      beforeAll(async () => {
+        // Create workflow_snapshot table
+        await storage.createTable({
+          tableName: TABLE_WORKFLOW_SNAPSHOT,
+          schema: {
+            workflow_name: { type: 'text', nullable: false },
+            run_id: { type: 'text', nullable: false },
+            snapshot: { type: 'text', nullable: false },
+            created_at: { type: 'timestamp', nullable: false },
+            updated_at: { type: 'timestamp', nullable: false },
+          },
+        });
+      });
+
+      it('should persist and load workflow snapshots', async () => {
+        const workflowName = 'test-workflow';
+        const runId = `run-${randomUUID()}`;
+        const snapshot = {
+          status: 'running',
+          context: {
+            stepResults: {},
+            attempts: {},
+            triggerData: { type: 'manual' },
+          },
+        } as any;
+
+        await storage.persistWorkflowSnapshot({
+          workflowName,
+          runId,
+          snapshot,
+        });
+
+        const loadedSnapshot = await storage.loadWorkflowSnapshot({
+          workflowName,
+          runId,
+        });
+
+        expect(loadedSnapshot).toEqual(snapshot);
+      });
+
+      it('should return null for non-existent workflow snapshot', async () => {
+        const result = await storage.loadWorkflowSnapshot({
+          workflowName: 'non-existent',
+          runId: 'non-existent',
+        });
+
+        expect(result).toBeNull();
+      });
+
+      it('should update existing workflow snapshot', async () => {
+        const workflowName = 'test-workflow';
+        const runId = `run-${randomUUID()}`;
+        const initialSnapshot = {
+          status: 'running',
+          context: {
+            stepResults: {},
+            attempts: {},
+            triggerData: { type: 'manual' },
+          },
+        };
+
+        await storage.persistWorkflowSnapshot({
+          workflowName,
+          runId,
+          snapshot: initialSnapshot as any,
+        });
+
+        const updatedSnapshot = {
+          status: 'completed',
+          context: {
+            stepResults: {
+              'step-1': { status: 'success', result: { data: 'test' } },
+            },
+            attempts: { 'step-1': 1 },
+            triggerData: { type: 'manual' },
+          },
+        } as any;
+
+        await storage.persistWorkflowSnapshot({
+          workflowName,
+          runId,
+          snapshot: updatedSnapshot,
+        });
+
+        const loadedSnapshot = await storage.loadWorkflowSnapshot({
+          workflowName,
+          runId,
+        });
+
+        expect(loadedSnapshot).toEqual(updatedSnapshot);
+      });
+
+      it('should handle complex workflow state', async () => {
+        const workflowName = 'complex-workflow';
+        const runId = `run-${randomUUID()}`;
+        const complexSnapshot = {
+          value: { currentState: 'running' },
+          context: {
+            stepResults: {
+              'step-1': {
+                status: 'success',
+                result: {
+                  nestedData: {
+                    array: [1, 2, 3],
+                    object: { key: 'value' },
+                    date: new Date().toISOString(),
+                  },
+                },
+              },
+              'step-2': {
+                status: 'waiting',
+                dependencies: ['step-3', 'step-4'],
+              },
+            },
+            attempts: { 'step-1': 1, 'step-2': 0 },
+            triggerData: {
+              type: 'scheduled',
+              metadata: {
+                schedule: '0 0 * * *',
+                timezone: 'UTC',
+              },
+            },
+          },
+          activePaths: [
+            {
+              stepPath: ['step-1'],
+              stepId: 'step-1',
+              status: 'success',
+            },
+            {
+              stepPath: ['step-2'],
+              stepId: 'step-2',
+              status: 'waiting',
+            },
+          ],
+          runId: runId,
+          timestamp: Date.now(),
+        };
+
+        await storage.persistWorkflowSnapshot({
+          workflowName,
+          runId,
+          snapshot: complexSnapshot as unknown as WorkflowRunState,
+        });
+
+        const loadedSnapshot = await storage.loadWorkflowSnapshot({
+          workflowName,
+          runId,
+        });
+
+        expect(loadedSnapshot).toEqual(complexSnapshot);
+      });
+    });
+  });
+}
diff --git a/packages/core/src/vector/libsql/index.test.ts b/packages/core/src/vector/libsql/index.test.ts
index 3f85bc54f03..16c76b3994a 100644
--- a/packages/core/src/vector/libsql/index.test.ts
+++ b/packages/core/src/vector/libsql/index.test.ts
@@ -5,7 +5,7 @@ import { DefaultVectorDB } from './index.js';
 describe('DefaultVectorDB', () => {
   let vectorDB: DefaultVectorDB;
   const testIndexName = 'test_vectors';
-  const testIndexName2 = 'test_vectors1';
+  // const testIndexName2 = 'test_vectors1';
 
   beforeAll(async () => {
     vectorDB = new DefaultVectorDB({
@@ -21,10 +21,6 @@ describe('DefaultVectorDB', () => {
   // Index Management Tests
   describe('Index Management', () => {
     describe('createIndex', () => {
-      afterAll(async () => {
-        await vectorDB.deleteIndex(testIndexName2);
-      });
-
       it('should create a new vector table with specified dimensions', async () => {
         await vectorDB.createIndex({ indexName: testIndexName, dimension: 3 });
 
diff --git a/packages/core/src/vector/libsql/url.test.ts b/packages/core/src/vector/libsql/url.test.ts
index 108feb2f5ca..999804ffbc5 100644
--- a/packages/core/src/vector/libsql/url.test.ts
+++ b/packages/core/src/vector/libsql/url.test.ts
@@ -1,4 +1,5 @@
-import { existsSync, mkdirSync, rmSync } from 'fs';
+import { existsSync, mkdirSync } from 'fs';
+import { stat, mkdir, rm, mkdtemp } from 'fs/promises';
 import { tmpdir } from 'os';
 import { join } from 'path';
 import { describe, it, expect, beforeEach, afterEach } from 'vitest';
@@ -9,21 +10,27 @@ describe('LibSQLVector URL rewriting', () => {
   let originalCwd: string;
   let parentDir: string;
 
-  beforeEach(() => {
-    tmpDir = join(tmpdir(), 'mastra-test-libsql-vector-url');
-    if (existsSync(tmpDir)) {
-      rmSync(tmpDir, { recursive: true, force: true });
+  beforeEach(async () => {
+    try {
+      tmpDir = await mkdtemp(join(tmpdir(), 'mastra-test-libsql-'));
+    } catch {
+      // ignore
     }
-    mkdirSync(tmpDir);
+
     originalCwd = process.cwd();
     process.chdir(tmpDir);
     parentDir = join(tmpDir, '..');
   });
 
-  afterEach(() => {
+  afterEach(async () => {
     process.chdir(originalCwd);
-    if (existsSync(tmpDir)) {
-      rmSync(tmpDir, { recursive: true, force: true });
+
+    try {
+      if (await stat(tmpDir)) {
+        await rm(tmpDir, { recursive: true, force: true });
+      }
+    } catch {
+      // ignore
     }
   });
 
@@ -164,4 +171,3 @@ describe('LibSQLVector URL rewriting', () => {
     expect(existsSync(join(parentDir, 'test.db'))).toBe(false);
   });
 });
-
diff --git a/packages/core/src/workflows/workflow.test.ts b/packages/core/src/workflows/workflow.test.ts
index 2cee9eb5cdd..ef53b65012e 100644
--- a/packages/core/src/workflows/workflow.test.ts
+++ b/packages/core/src/workflows/workflow.test.ts
@@ -10,12 +10,12 @@ import { Telemetry } from '../telemetry';
 import { createTool } from '../tools';
 
 import { Step } from './step';
-import { WhenConditionReturnValue, type WorkflowContext, type WorkflowResumeResult } from './types';
+import type { WorkflowContext, WorkflowResumeResult } from './types';
 import { Workflow } from './workflow';
 
 const storage = new DefaultStorage({
   config: {
-    url: 'file:mastra.db',
+    url: 'file::memory:?cache=shared',
   },
 });
 
@@ -1376,6 +1376,7 @@ describe('Workflow', async () => {
         logger: createLogger({
           name: 'Workflow',
         }),
+        storage,
       });
 
       const workflow = new Workflow({
@@ -1402,6 +1403,7 @@ describe('Workflow', async () => {
         logger: createLogger({
           name: 'Workflow',
         }),
+        storage,
       });
 
       const workflow = new Workflow({
@@ -1561,8 +1563,6 @@ describe('Workflow', async () => {
       const run = workflow.createRun();
       const result = await run.start();
 
-      console.log({ result });
-
       expect(step1Action).toHaveBeenCalled();
       expect(step2Action).toHaveBeenCalled();
       expect(step3Action).toHaveBeenCalled();
@@ -1829,7 +1829,7 @@ describe('Workflow', async () => {
       // Create a new storage instance for initial run
       const initialStorage = new DefaultStorage({
         config: {
-          url: 'file:mastra.db',
+          url: 'file::memory:',
         },
       });
       await initialStorage.init();
@@ -1962,6 +1962,7 @@ describe('Workflow', async () => {
       const mastra = new Mastra({
         logger,
         workflows: { 'test-workflow': workflow },
+        storage,
       });
 
       const wf = mastra.getWorkflow('test-workflow');
@@ -2113,6 +2114,7 @@ describe('Workflow', async () => {
       const mastra = new Mastra({
         logger,
         workflows: { 'test-workflow': workflow },
+        storage,
       });
 
       const wf = mastra.getWorkflow('test-workflow');
@@ -2264,6 +2266,7 @@ describe('Workflow', async () => {
       const mastra = new Mastra({
         logger,
         workflows: { 'test-workflow': promptEvalWorkflow },
+        storage,
       });
 
       const wf = mastra.getWorkflow('test-workflow');
@@ -2347,6 +2350,7 @@ describe('Workflow', async () => {
       const mastra = new Mastra({
         logger,
         workflows: { 'test-workflow': workflow },
+        storage,
       });
 
       const wf = mastra.getWorkflow('test-workflow');
@@ -2364,7 +2368,7 @@ describe('Workflow', async () => {
       loggerSpy.mockClear();
     });
 
-    it('should be able to access the new Mastra primitives', async () => {
+    it.only('should be able to access the new Mastra primitives', async () => {
       let telemetry: Telemetry | undefined;
       const step1 = new Step({
         id: 'step1',
@@ -2381,6 +2385,7 @@ describe('Workflow', async () => {
       const mastra = new Mastra({
         logger,
         workflows: { 'test-workflow': workflow },
+        storage,
       });
 
       const wf = mastra.getWorkflow('test-workflow');
diff --git a/packages/evals/src/metrics/llm/contextual-recall/index.test.ts b/packages/evals/src/metrics/llm/contextual-recall/index.test.ts
index b35d74e291a..015fc596370 100644
--- a/packages/evals/src/metrics/llm/contextual-recall/index.test.ts
+++ b/packages/evals/src/metrics/llm/contextual-recall/index.test.ts
@@ -72,7 +72,6 @@ describe(
       const testCase = testCases[1]!;
       const metric = new ContextualRecallMetric(model, { context: testCase.context });
       const result = await metric.measure(testCase.input, testCase.output);
-      console.log(result.score, testCase.expectedResult.score);
 
       expect(isCloserTo(result.score, testCase.expectedResult.score, 1)).toBe(true);
     });
diff --git a/packages/evals/src/metrics/llm/summarization/index.test.ts b/packages/evals/src/metrics/llm/summarization/index.test.ts
index b1d29ceb992..c1b636cebf8 100644
--- a/packages/evals/src/metrics/llm/summarization/index.test.ts
+++ b/packages/evals/src/metrics/llm/summarization/index.test.ts
@@ -262,7 +262,6 @@ describe('SummarizationMetric', () => {
   it('should handle repetitive summary', async () => {
     const testCase = testCases[13]!;
     const result = await metric.measure(testCase.input, testCase.output);
-    console.log(result.score, testCase.expectedResult.score);
     expect(isCloserTo(result.score, testCase.expectedResult.score, 1)).toBe(true);
   });
 
diff --git a/packages/mcp/src/client.test.ts b/packages/mcp/src/client.test.ts
index 7cb3bd67776..d41d0e01d95 100644
--- a/packages/mcp/src/client.test.ts
+++ b/packages/mcp/src/client.test.ts
@@ -44,8 +44,6 @@ describe.skip('MastraMCPClient', () => {
       },
     });
 
-    console.log(response.text);
-
     expect(Object.keys(tools).length).toBeGreaterThan(0);
   }, 50000);
 });


Reviews:
user: login: rase-
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-11T11:09:11Z
user: login: TylerBarnes
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-03-11T16:52:46Z
user: login: TylerBarnes
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-11T16:55:56Z
user: login: wardpeet
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-11T20:32:26Z
user: login: wardpeet
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-11T20:33:10Z
user: login: wardpeet
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-11T20:33:49Z

Review comments:
diff_hunk: @@ -0,0 +1,114 @@
+import type { MessageType, StorageThreadType } from '../memory/types';
path: packages/core/src/storage/defaultProxyStorage.ts
user: login: TylerBarnes
body: should keep file naming consistent `default-proxy-storage.ts`
created_at: 2025-03-11T16:48:55Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,114 @@
+import type { MessageType, StorageThreadType } from '../memory/types';
+import { MastraStorage } from './base';
+import type { TABLE_NAMES } from './constants';
+import type { DefaultStorage, type LibSQLConfig } from './libsql';
+import type { EvalRow, StorageColumn, StorageGetMessagesArg } from './types';
+
+/**
+ * A proxy for the DefaultStorage (LibSQLStore) to allow for dynamically loading the storage in a constructor
+ */
+export class DefaultProxyStorage extends MastraStorage {
+  private storage: DefaultStorage | null = null;
+  private storageConfig: LibSQLConfig;
+
+  constructor({ config }: { config: LibSQLConfig }) {
+    super({ name: 'DefaultStorage' });
+    this.storageConfig = config;
+  }
+
+  private async setupStorage() {
+    const { DefaultStorage } = await import('./libsql');
+
+    this.storage = new DefaultStorage({ config: this.storageConfig });
path: packages/core/src/storage/defaultProxyStorage.ts
user: login: TylerBarnes
body: we need an init guard right? looks like this will get re-initialized in every method call
created_at: 2025-03-11T16:49:53Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,114 @@
+import type { MessageType, StorageThreadType } from '../memory/types';
+import { MastraStorage } from './base';
+import type { TABLE_NAMES } from './constants';
+import type { DefaultStorage, type LibSQLConfig } from './libsql';
+import type { EvalRow, StorageColumn, StorageGetMessagesArg } from './types';
+
+/**
+ * A proxy for the DefaultStorage (LibSQLStore) to allow for dynamically loading the storage in a constructor
+ */
+export class DefaultProxyStorage extends MastraStorage {
+  private storage: DefaultStorage | null = null;
+  private storageConfig: LibSQLConfig;
+
+  constructor({ config }: { config: LibSQLConfig }) {
+    super({ name: 'DefaultStorage' });
+    this.storageConfig = config;
+  }
+
+  private async setupStorage() {
+    const { DefaultStorage } = await import('./libsql');
+
+    this.storage = new DefaultStorage({ config: this.storageConfig });
path: packages/core/src/storage/defaultProxyStorage.ts
user: login: TylerBarnes
body: Also curious why we don't make these changes inside the libsql class directly - users always need to call an async method before interacting with it so we should be able to do the same inside it right?
created_at: 2025-03-11T16:52:06Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,114 @@
+import type { MessageType, StorageThreadType } from '../memory/types';
+import { MastraStorage } from './base';
+import type { TABLE_NAMES } from './constants';
+import type { DefaultStorage, type LibSQLConfig } from './libsql';
+import type { EvalRow, StorageColumn, StorageGetMessagesArg } from './types';
+
+/**
+ * A proxy for the DefaultStorage (LibSQLStore) to allow for dynamically loading the storage in a constructor
+ */
+export class DefaultProxyStorage extends MastraStorage {
+  private storage: DefaultStorage | null = null;
+  private storageConfig: LibSQLConfig;
+
+  constructor({ config }: { config: LibSQLConfig }) {
+    super({ name: 'DefaultStorage' });
+    this.storageConfig = config;
+  }
+
+  private async setupStorage() {
+    const { DefaultStorage } = await import('./libsql');
+
+    this.storage = new DefaultStorage({ config: this.storageConfig });
path: packages/core/src/storage/defaultProxyStorage.ts
user: login: TylerBarnes
body: need to guard against init race conditions too or multiple simultaneous method calls will import/init at the same time https://github.com/mastra-ai/mastra/blob/main/packages/core/src/storage/base.ts#L152
created_at: 2025-03-11T16:55:56Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,114 @@
+import type { MessageType, StorageThreadType } from '../memory/types';
+import { MastraStorage } from './base';
+import type { TABLE_NAMES } from './constants';
+import type { DefaultStorage, type LibSQLConfig } from './libsql';
+import type { EvalRow, StorageColumn, StorageGetMessagesArg } from './types';
+
+/**
+ * A proxy for the DefaultStorage (LibSQLStore) to allow for dynamically loading the storage in a constructor
+ */
+export class DefaultProxyStorage extends MastraStorage {
+  private storage: DefaultStorage | null = null;
+  private storageConfig: LibSQLConfig;
+
+  constructor({ config }: { config: LibSQLConfig }) {
+    super({ name: 'DefaultStorage' });
+    this.storageConfig = config;
+  }
+
+  private async setupStorage() {
+    const { DefaultStorage } = await import('./libsql');
+
+    this.storage = new DefaultStorage({ config: this.storageConfig });
path: packages/core/src/storage/defaultProxyStorage.ts
user: login: wardpeet
body: If you use libsql yourself, you intentionally want it, which means we fail early if something goes wrong. So this is mostly to patch default behavior when you don't even want it, now that I think of it, it might be a simple no-op for evals and tracing.
created_at: 2025-03-11T20:32:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,114 @@
+import type { MessageType, StorageThreadType } from '../memory/types';
+import { MastraStorage } from './base';
+import type { TABLE_NAMES } from './constants';
+import type { DefaultStorage, type LibSQLConfig } from './libsql';
+import type { EvalRow, StorageColumn, StorageGetMessagesArg } from './types';
+
+/**
+ * A proxy for the DefaultStorage (LibSQLStore) to allow for dynamically loading the storage in a constructor
+ */
+export class DefaultProxyStorage extends MastraStorage {
+  private storage: DefaultStorage | null = null;
+  private storageConfig: LibSQLConfig;
+
+  constructor({ config }: { config: LibSQLConfig }) {
+    super({ name: 'DefaultStorage' });
+    this.storageConfig = config;
+  }
+
+  private async setupStorage() {
+    const { DefaultStorage } = await import('./libsql');
+
+    this.storage = new DefaultStorage({ config: this.storageConfig });
path: packages/core/src/storage/defaultProxyStorage.ts
user: login: wardpeet
body: @TylerBarnes what race condition are you talking about? we do have the promise set?
created_at: 2025-03-11T20:33:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,114 @@
+import type { MessageType, StorageThreadType } from '../memory/types';
+import { MastraStorage } from './base';
+import type { TABLE_NAMES } from './constants';
+import type { DefaultStorage, type LibSQLConfig } from './libsql';
+import type { EvalRow, StorageColumn, StorageGetMessagesArg } from './types';
+
+/**
+ * A proxy for the DefaultStorage (LibSQLStore) to allow for dynamically loading the storage in a constructor
+ */
+export class DefaultProxyStorage extends MastraStorage {
+  private storage: DefaultStorage | null = null;
+  private storageConfig: LibSQLConfig;
+
+  constructor({ config }: { config: LibSQLConfig }) {
+    super({ name: 'DefaultStorage' });
+    this.storageConfig = config;
+  }
+
+  private async setupStorage() {
+    const { DefaultStorage } = await import('./libsql');
+
+    this.storage = new DefaultStorage({ config: this.storageConfig });
path: packages/core/src/storage/defaultProxyStorage.ts
user: login: wardpeet
body: ah i get it, fuck good catch

created_at: 2025-03-11T20:33:49Z
author_association: CONTRIBUTOR

PR comments:
user: login: codesandbox[bot]
created_at: 2025-03-11T10:56:09Z
body: #### Review or Edit in CodeSandbox

Open the branch in <a href="https://codesandbox.io/p/github/mastra-ai/mastra/dynamic-load-libsql?mode=review&utm_source=gh_app">Web Editor</a> &bull; <a href="https://codesandbox.io/p/vscode?owner=mastra-ai&repo=mastra&branch=dynamic-load-libsql&utm_source=gh_app">VS Code</a> &bull; <a href="https://codesandbox.io/p/vscode?owner=mastra-ai&repo=mastra&branch=dynamic-load-libsql&insiders=true&utm_source=gh_app">Insiders</a><br>
Open <a href="https://codesandbox.io/p/devtool/preview/mastra-ai/mastra/dynamic-load-libsql?task=preview&port=51423&redirect=true&utm_source=gh_app">Preview</a>

<!-- open-in-codesandbox:complete -->

author_association: NONE
user: login: changeset-bot[bot]
created_at: 2025-03-11T10:56:10Z
body: ###  🦋  Changeset detected

Latest commit: 64c203a2555e6f0908d34f05de5355d8c28743c2

**The changes in this PR will be included in the next version bump.**

<details><summary>This PR includes changesets to release 44 packages</summary>

  | Name                        | Type  |
| --------------------------- | ----- |
| @mastra/core                | Patch |
| mastra                      | Patch |
| @mastra/deployer            | Patch |
| @mastra/evals               | Patch |
| @mastra/loggers             | Patch |
| @mastra/mcp                 | Patch |
| @mastra/memory              | Patch |
| @mastra/playground-ui       | Patch |
| @mastra/rag                 | Patch |
| @mastra/deployer-cloudflare | Patch |
| @mastra/deployer-netlify    | Patch |
| @mastra/deployer-vercel     | Patch |
| @mastra/astra               | Patch |
| @mastra/chroma              | Patch |
| @mastra/pg                  | Patch |
| @mastra/pinecone            | Patch |
| @mastra/qdrant              | Patch |
| @mastra/turbopuffer         | Patch |
| @mastra/upstash             | Patch |
| @mastra/vectorize           | Patch |
| @mastra/speech-azure        | Patch |
| @mastra/speech-deepgram     | Patch |
| @mastra/speech-elevenlabs   | Patch |
| @mastra/speech-google       | Patch |
| @mastra/speech-ibm          | Patch |
| @mastra/speech-murf         | Patch |
| @mastra/speech-openai       | Patch |
| @mastra/speech-playai       | Patch |
| @mastra/speech-replicate    | Patch |
| @mastra/speech-speechify    | Patch |
| @mastra/voice-deepgram      | Patch |
| @mastra/voice-elevenlabs    | Patch |
| @mastra/voice-google        | Patch |
| @mastra/voice-murf          | Patch |
| @mastra/voice-openai        | Patch |
| @mastra/voice-playai        | Patch |
| @mastra/voice-speechify     | Patch |
| @mastra/client-js           | Patch |
| @mastra/composio            | Patch |
| @mastra/firecrawl           | Patch |
| @mastra/github              | Patch |
| @mastra/ragie               | Patch |
| @mastra/stabilityai         | Patch |
| @mastra/dane                | Patch |

</details>

Not sure what this means? [Click here  to learn what changesets are](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add another changeset to this PR](https://github.com/mastra-ai/mastra/new/dynamic-load-libsql?filename=.changeset/empty-suits-vanish.md&value=---%0A%22%40mastra%2Fcore%22%3A%20patch%0A%22%40mastra%2Fevals%22%3A%20patch%0A%22%40mastra%2Fmcp%22%3A%20patch%0A---%0A%0AAdd%20dynamic%20default%20storage%0A)


author_association: NONE
user: login: vercel[bot]
created_at: 2025-03-11T10:56:11Z
body: [vc]: #tbkfqc1YeNJ1fF5oDOnA1ZvTr3qwsBtEXVpokQorTHU=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJtYXN0cmEtZG9jcyIsInJvb3REaXJlY3RvcnkiOiJkb2NzIiwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL2tlcGxlci1hYjFiZjVhYi9tYXN0cmEtZG9jcy83UWgyTlh4N0dDb1JnUzhLYk50NXNYeWM3Tkp4IiwicHJldmlld1VybCI6Im1hc3RyYS1kb2NzLWdpdC1keW5hbWljLWxvYWQtbGlic3FsLWtlcGxlci1hYjFiZjVhYi52ZXJjZWwuYXBwIiwibmV4dENvbW1pdFN0YXR1cyI6IkRFUExPWUVEIiwibGl2ZUZlZWRiYWNrIjp7InJlc29sdmVkIjowLCJ1bnJlc29sdmVkIjowLCJ0b3RhbCI6MCwibGluayI6Im1hc3RyYS1kb2NzLWdpdC1keW5hbWljLWxvYWQtbGlic3FsLWtlcGxlci1hYjFiZjVhYi52ZXJjZWwuYXBwIn19LHsibmFtZSI6ImNyeXB0by1jaGF0Ym90Iiwicm9vdERpcmVjdG9yeSI6ImV4YW1wbGVzL2NyeXB0by1jaGF0Ym90IiwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL2tlcGxlci1hYjFiZjVhYi9jcnlwdG8tY2hhdGJvdC9DaXhWSGg2N0UzUnVvam5nSjRlQ0ZUWmtxV3lyIiwicHJldmlld1VybCI6ImNyeXB0by1jaGF0Ym90LWdpdC1keW5hbWljLWxvYWQtbGlic3FsLWtlcGxlci1hYjFiZjVhYi52ZXJjZWwuYXBwIiwibmV4dENvbW1pdFN0YXR1cyI6IkRFUExPWUVEIiwibGl2ZUZlZWRiYWNrIjp7InJlc29sdmVkIjowLCJ1bnJlc29sdmVkIjowLCJ0b3RhbCI6MCwibGluayI6ImNyeXB0by1jaGF0Ym90LWdpdC1keW5hbWljLWxvYWQtbGlic3FsLWtlcGxlci1hYjFiZjVhYi52ZXJjZWwuYXBwIn19LHsibmFtZSI6Im9wZW5hcGktc3BlYy13cml0ZXIiLCJyb290RGlyZWN0b3J5IjoiZXhhbXBsZXMvb3BlbmFwaS1zcGVjLXdyaXRlciIsImluc3BlY3RvclVybCI6Imh0dHBzOi8vdmVyY2VsLmNvbS9rZXBsZXItYWIxYmY1YWIvb3BlbmFwaS1zcGVjLXdyaXRlci80MjQ4VnNIdXhvRVVZWlFMWHoxcjJvUExTRDVSIiwicHJldmlld1VybCI6Im9wZW5hcGktc3BlYy13cml0ZXItZ2l0LWR5bmFtaWMtbG9hZC1saWJzcWwta2VwbGVyLWFiMWJmNWFiLnZlcmNlbC5hcHAiLCJuZXh0Q29tbWl0U3RhdHVzIjoiREVQTE9ZRUQiLCJsaXZlRmVlZGJhY2siOnsicmVzb2x2ZWQiOjAsInVucmVzb2x2ZWQiOjAsInRvdGFsIjowLCJsaW5rIjoib3BlbmFwaS1zcGVjLXdyaXRlci1naXQtZHluYW1pYy1sb2FkLWxpYnNxbC1rZXBsZXItYWIxYmY1YWIudmVyY2VsLmFwcCJ9fSx7Im5hbWUiOiJhc3Npc3RhbnQtdWkiLCJyb290RGlyZWN0b3J5IjoiZXhhbXBsZXMvYXNzaXN0YW50LXVpIiwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL2tlcGxlci1hYjFiZjVhYi9hc3Npc3RhbnQtdWkvQjhNaGRqY0RzTFk5SmRpZ1dXd3lWUTlhbjZEOSIsInByZXZpZXdVcmwiOiJhc3Npc3RhbnQtdWktZ2l0LWR5bmFtaWMtbG9hZC1saWJzcWwta2VwbGVyLWFiMWJmNWFiLnZlcmNlbC5hcHAiLCJuZXh0Q29tbWl0U3RhdHVzIjoiREVQTE9ZRUQiLCJsaXZlRmVlZGJhY2siOnsicmVzb2x2ZWQiOjAsInVucmVzb2x2ZWQiOjAsInRvdGFsIjowLCJsaW5rIjoiYXNzaXN0YW50LXVpLWdpdC1keW5hbWljLWxvYWQtbGlic3FsLWtlcGxlci1hYjFiZjVhYi52ZXJjZWwuYXBwIn19LHsibmFtZSI6InRyYXZlbC1haSIsInJvb3REaXJlY3RvcnkiOiJleGFtcGxlcy90cmF2ZWwtYXBwIiwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL2tlcGxlci1hYjFiZjVhYi90cmF2ZWwtYWkvSGJGeXRTV0dkeHo4cVI5VW1tNk45cm15WW5GbiIsInByZXZpZXdVcmwiOiJ0cmF2ZWwtYWktZ2l0LWR5bmFtaWMtbG9hZC1saWJzcWwta2VwbGVyLWFiMWJmNWFiLnZlcmNlbC5hcHAiLCJuZXh0Q29tbWl0U3RhdHVzIjoiREVQTE9ZRUQiLCJsaXZlRmVlZGJhY2siOnsicmVzb2x2ZWQiOjAsInVucmVzb2x2ZWQiOjAsInRvdGFsIjowLCJsaW5rIjoidHJhdmVsLWFpLWdpdC1keW5hbWljLWxvYWQtbGlic3FsLWtlcGxlci1hYjFiZjVhYi52ZXJjZWwuYXBwIn19LHsibmFtZSI6ImJpcmQtY2hlY2tlciIsInJvb3REaXJlY3RvcnkiOiJleGFtcGxlcy9iaXJkLWNoZWNrZXItd2l0aC1uZXh0anMiLCJpbnNwZWN0b3JVcmwiOiJodHRwczovL3ZlcmNlbC5jb20va2VwbGVyLWFiMWJmNWFiL2JpcmQtY2hlY2tlci85SGY1eVZ3VlprRHpQdE13R1pQNjN4dnlLZ0JiIiwicHJldmlld1VybCI6ImJpcmQtY2hlY2tlci1naXQtZHluYW1pYy1sb2FkLWxpYnNxbC1rZXBsZXItYWIxYmY1YWIudmVyY2VsLmFwcCIsIm5leHRDb21taXRTdGF0dXMiOiJERVBMT1lFRCIsImxpdmVGZWVkYmFjayI6eyJyZXNvbHZlZCI6MCwidW5yZXNvbHZlZCI6MCwidG90YWwiOjAsImxpbmsiOiJiaXJkLWNoZWNrZXItZ2l0LWR5bmFtaWMtbG9hZC1saWJzcWwta2VwbGVyLWFiMWJmNWFiLnZlcmNlbC5hcHAifX1dfQ==
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Comments | Updated (UTC) |
| :--- | :----- | :------ | :------- | :------ |
| **assistant-ui** | ✅ Ready ([Inspect](https://vercel.com/kepler-ab1bf5ab/assistant-ui/B8MhdjcDsLY9JdigWWwyVQ9an6D9)) | [Visit Preview](https://assistant-ui-git-dynamic-load-libsql-kepler-ab1bf5ab.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/assistant-ui-git-dynamic-load-libsql-kepler-ab1bf5ab.vercel.app?via=pr-comment-feedback-link) | Mar 12, 2025 0:59am |
| **bird-checker** | ✅ Ready ([Inspect](https://vercel.com/kepler-ab1bf5ab/bird-checker/9Hf5yVwVZkDzPtMwGZP63xvyKgBb)) | [Visit Preview](https://bird-checker-git-dynamic-load-libsql-kepler-ab1bf5ab.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/bird-checker-git-dynamic-load-libsql-kepler-ab1bf5ab.vercel.app?via=pr-comment-feedback-link) | Mar 12, 2025 0:59am |
| **crypto-chatbot** | ✅ Ready ([Inspect](https://vercel.com/kepler-ab1bf5ab/crypto-chatbot/CixVHh67E3RuojngJ4eCFTZkqWyr)) | [Visit Preview](https://crypto-chatbot-git-dynamic-load-libsql-kepler-ab1bf5ab.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/crypto-chatbot-git-dynamic-load-libsql-kepler-ab1bf5ab.vercel.app?via=pr-comment-feedback-link) | Mar 12, 2025 0:59am |
| **mastra-docs** | ✅ Ready ([Inspect](https://vercel.com/kepler-ab1bf5ab/mastra-docs/7Qh2NXx7GCoRgS8KbNt5sXyc7NJx)) | [Visit Preview](https://mastra-docs-git-dynamic-load-libsql-kepler-ab1bf5ab.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/mastra-docs-git-dynamic-load-libsql-kepler-ab1bf5ab.vercel.app?via=pr-comment-feedback-link) | Mar 12, 2025 0:59am |
| **openapi-spec-writer** | ✅ Ready ([Inspect](https://vercel.com/kepler-ab1bf5ab/openapi-spec-writer/4248VsHuxoEUYZQLXz1r2oPLSD5R)) | [Visit Preview](https://openapi-spec-writer-git-dynamic-load-libsql-kepler-ab1bf5ab.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/openapi-spec-writer-git-dynamic-load-libsql-kepler-ab1bf5ab.vercel.app?via=pr-comment-feedback-link) | Mar 12, 2025 0:59am |
| **travel-ai** | ✅ Ready ([Inspect](https://vercel.com/kepler-ab1bf5ab/travel-ai/HbFytSWGdxz8qR9Umm6N9rmyYnFn)) | [Visit Preview](https://travel-ai-git-dynamic-load-libsql-kepler-ab1bf5ab.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/travel-ai-git-dynamic-load-libsql-kepler-ab1bf5ab.vercel.app?via=pr-comment-feedback-link) | Mar 12, 2025 0:59am |







author_association: NONE
user: login: promptless[bot]
created_at: 2025-03-11T10:57:53Z
body: 📝 Documentation updates detected! You can review documentation updates [here](https://app.gopromptless.ai/change-history/bdebf8e1-ec81-4ab5-9105-eb872a3fb785)
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-03-11T23:02:36Z
body: ## Braintrust eval report
No experiments to report
<!-- braintrust_bot_comment mastra-ai/mastra/.github/workflows/bird-checker-eval.yml@refs/heads/dynamic-load-libsql-__braintrustdata_eval-action -->
author_association: CONTRIBUTOR