@mastra/libsql 1.11.1 → 1.12.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,60 @@
1
1
  # @mastra/libsql
2
2
 
3
+ ## 1.12.0-alpha.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Added the `tool_provider_connections` storage domain. Stored agents can now persist per-agent ToolProvider config that round-trips on read/write/create. Runtime connection resolution (per-author, shared, caller-supplied) ships in a follow-up PR. ([#17247](https://github.com/mastra-ai/mastra/pull/17247))
8
+
9
+ **What you can do**
10
+ - Pin a connection on a stored agent's config and have it round-trip on read/write/create.
11
+ - Persist multiple connections per toolkit so a follow-up runtime PR can fan-out to the right one at execution time.
12
+
13
+ **Example**
14
+
15
+ ```ts
16
+ import { LibSQLStore } from '@mastra/libsql';
17
+
18
+ const storage = new LibSQLStore({ url: process.env.DATABASE_URL });
19
+
20
+ // Persist an OAuth connection that an agent can pin later
21
+ await storage.toolProviders.upsertConnection({
22
+ authorId: 'user-123',
23
+ providerId: 'composio',
24
+ connectionId: 'auth_abc',
25
+ toolkit: 'gmail',
26
+ label: 'Work inbox',
27
+ scope: 'per-author',
28
+ });
29
+
30
+ // List a user's own connections (admin can omit authorId to list across users)
31
+ const { items } = await storage.toolProviders.listConnectionsByAuthor({
32
+ authorId: 'user-123',
33
+ providerId: 'composio',
34
+ });
35
+ ```
36
+
37
+ Additive — existing stored agents continue to work unchanged. The runtime that consumes this domain ships in a follow-up PR.
38
+
39
+ PR 1 of 3 split from #17224.
40
+
41
+ ### Patch Changes
42
+
43
+ - Added a public `close()` method to `LibSQLStore` that releases SQLite file handles and cleans up the WAL/shm sidecar files. Previously these handles stayed open until the process exited, which on Windows caused `EBUSY` errors when removing the storage directory after shutdown. `Mastra.shutdown()` now calls `close()` automatically, so you no longer need to reach into private fields. ([#17306](https://github.com/mastra-ai/mastra/pull/17306))
44
+
45
+ ```typescript
46
+ const storage = new LibSQLStore({ id: 'my-store', url: 'file:./dev.db' });
47
+
48
+ // Release all file handles, including WAL/shm sidecar files
49
+ await storage.close();
50
+
51
+ // Now safe to remove the storage directory on all platforms, including Windows
52
+ await fs.rm('./dev.db', { recursive: true, force: true });
53
+ ```
54
+
55
+ - Updated dependencies [[`8ace89d`](https://github.com/mastra-ai/mastra/commit/8ace89df77f762e622d3b9f7f65ad7524350d050), [`fa63872`](https://github.com/mastra-ai/mastra/commit/fa6387280954e6b667bec5714b55ba082bc627ff), [`f07b646`](https://github.com/mastra-ai/mastra/commit/f07b64604ab7d25391179790b7fd4823df9e2dff), [`d8838ae`](https://github.com/mastra-ai/mastra/commit/d8838ae80b69780361693d27098f7f6684af12fe), [`40f9297`](https://github.com/mastra-ai/mastra/commit/40f9297003b921c62373d3e8d3a4bda76c9f6de3), [`0f0d1ba`](https://github.com/mastra-ai/mastra/commit/0f0d1ba67bfcb2204e571401662f1eceefc03357), [`8c31bcd`](https://github.com/mastra-ai/mastra/commit/8c31bcdb00e597880d5939b1b7d7566fbe5dacae), [`95b14cd`](https://github.com/mastra-ai/mastra/commit/95b14cdd820e86d97ac05fe568424c513a252e31), [`aa36be2`](https://github.com/mastra-ai/mastra/commit/aa36be23aa513b7dc53cb8ca16b7fab8f20e43ad), [`212c635`](https://github.com/mastra-ai/mastra/commit/212c635203e61d036ab41db8ff86c3893dc795b3), [`d8838ae`](https://github.com/mastra-ai/mastra/commit/d8838ae80b69780361693d27098f7f6684af12fe), [`9aa5a73`](https://github.com/mastra-ai/mastra/commit/9aa5a73e7e110f6e9365eec69364a33d5f03bb56), [`f73c789`](https://github.com/mastra-ai/mastra/commit/f73c789e8ef21561580395d2c410119cab5848c8), [`8bd16da`](https://github.com/mastra-ai/mastra/commit/8bd16da73a4cb874d739373643dbd6a6e7f88684), [`c8630f8`](https://github.com/mastra-ai/mastra/commit/c8630f80d4f40cb5d22e60ab162b618b1907167a), [`47f71dc`](https://github.com/mastra-ai/mastra/commit/47f71dc6fbcbd12d71e21a979e676e20a02bd77d), [`50ceae2`](https://github.com/mastra-ai/mastra/commit/50ceae270878e2f8fb2b2c6c2faab09df0007c8a), [`8cdde58`](https://github.com/mastra-ai/mastra/commit/8cdde5875bbba6702d9df226f2b20232b8d75d6c), [`847ff1e`](https://github.com/mastra-ai/mastra/commit/847ff1e0d94368d94b2e173e4e0908e115568ef3), [`259d409`](https://github.com/mastra-ai/mastra/commit/259d409a514174299dbde1ff5e1121209b3ba850), [`9e16c68`](https://github.com/mastra-ai/mastra/commit/9e16c6818b6485ccb43df28aba6f3a2219d28662), [`cefca33`](https://github.com/mastra-ai/mastra/commit/cefca33ae666e69810c935fedf95a929c173d1d7), [`d00e8c5`](https://github.com/mastra-ai/mastra/commit/d00e8c50daebe5bce5bf2f48bde39c86fc3d2fe4), [`36fa7e2`](https://github.com/mastra-ai/mastra/commit/36fa7e24d14e58a1eb46147097b32f583e5b8775), [`87e9774`](https://github.com/mastra-ai/mastra/commit/87e97741c1e493cd6d62f478eb810b49bda4d57c), [`65a72e7`](https://github.com/mastra-ai/mastra/commit/65a72e70c25eedea8ff985a6624b96be2850236b), [`0f77241`](https://github.com/mastra-ai/mastra/commit/0f7724108806703799a8ba80ad0f09414afd5066), [`92ff509`](https://github.com/mastra-ai/mastra/commit/92ff5098ef8a990438ca038077021a5f7541ec1d), [`3fce5e7`](https://github.com/mastra-ai/mastra/commit/3fce5e70d011d289043e75003ef3336ed4aa43c3), [`a763592`](https://github.com/mastra-ai/mastra/commit/a763592c3db46963ef1011cfe16fe372816e775e), [`80c7737`](https://github.com/mastra-ai/mastra/commit/80c7737e32d7917b5f356957d67c169d01744fd3), [`3f1cf47`](https://github.com/mastra-ai/mastra/commit/3f1cf476f74c1e4cc2df908837e05853a5347e31)]:
56
+ - @mastra/core@1.38.0-alpha.3
57
+
3
58
  ## 1.11.1
4
59
 
5
60
  ### Patch Changes
@@ -3,7 +3,7 @@ name: mastra-libsql
3
3
  description: Documentation for @mastra/libsql. Use when working with @mastra/libsql APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/libsql"
6
- version: "1.11.1"
6
+ version: "1.12.0-alpha.0"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -16,6 +16,8 @@ Read the individual reference documents for detailed explanations and code examp
16
16
 
17
17
  ### Docs
18
18
 
19
+ - [Deploying](references/docs-agent-builder-deploying.md) - Swap local Agent Builder primitives for cloud-backed storage, filesystems, sandboxes, an EE license, auth, and a public channel URL for production.
20
+ - [Agent Builder overview](references/docs-agent-builder-overview.md) - Let teammates create, configure, and operate Mastra agents from a browser, with admin-pinned defaults, RBAC, and channel integrations.
19
21
  - [Agent approval](references/docs-agents-agent-approval.md) - Learn how to require approvals, suspend tool execution, and automatically resume suspended tools while keeping humans in control of agent workflows.
20
22
  - [Agent networks](references/docs-agents-networks.md) - Coordinate multiple agents, workflows, and tools using agent networks for complex, non-deterministic task execution.
21
23
  - [Memory processors](references/docs-memory-memory-processors.md) - Learn how to use memory processors in Mastra to filter, trim, and transform messages before they're sent to the language model to manage context window limits.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.11.1",
2
+ "version": "1.12.0-alpha.0",
3
3
  "package": "@mastra/libsql",
4
4
  "exports": {},
5
5
  "modules": {}
@@ -0,0 +1,121 @@
1
+ # Deploying
2
+
3
+ > **Note:** The Agent Builder is part of the Mastra Enterprise Edition. Production deployments require a valid EE license. [Contact sales](https://mastra.ai/contact) for more information.
4
+
5
+ Production deployments swap the local primitives in the Quickstart for cloud-backed equivalents. The shape of the `Mastra` and `MastraEditor` config doesn't change — only the providers behind it.
6
+
7
+ ## What a production deployment needs
8
+
9
+ 1. **EE license** — a valid `MASTRA_EE_LICENSE` so the server will start with the Builder enabled.
10
+ 2. **Hosted storage** — a shared store for agents, skills, runs, and memory.
11
+ 3. **Shared workspace filesystem** — survives across instances; `local` is single-node only.
12
+ 4. **Cloud sandbox** — runs agent commands safely; `local` is unsafe in shared environments.
13
+ 5. **Auth and RBAC** — gates the Builder UI and `/agent-builder/*` routes.
14
+ 6. **Public base URL for channels** — Slack and other channel providers need a reachable URL.
15
+
16
+ ## EE license
17
+
18
+ Set `MASTRA_EE_LICENSE` in the deployment environment. The server refuses to start when `builder.enabled` is truthy without a valid license. Treat the license key as a secret.
19
+
20
+ ## Storage
21
+
22
+ Replace the file-backed LibSQL store with a hosted backend. LibSQL Cloud, PostgreSQL, and any other Mastra storage adapter all work.
23
+
24
+ ```typescript
25
+ import { Mastra } from '@mastra/core/mastra'
26
+ import { LibSQLStore } from '@mastra/libsql'
27
+
28
+ new Mastra({
29
+ storage: new LibSQLStore({
30
+ url: process.env.DATABASE_URL!,
31
+ authToken: process.env.DATABASE_AUTH_TOKEN,
32
+ }),
33
+ })
34
+ ```
35
+
36
+ ## Workspace filesystem and sandbox
37
+
38
+ `local` filesystem works only on the node that owns the directory. For multi-instance deployments, register cloud filesystem and sandbox providers on `MastraEditor` and reference them by id in the inline workspace config.
39
+
40
+ **npm**:
41
+
42
+ ```bash
43
+ npm install @mastra/s3 @mastra/e2b
44
+ ```
45
+
46
+ **pnpm**:
47
+
48
+ ```bash
49
+ pnpm add @mastra/s3 @mastra/e2b
50
+ ```
51
+
52
+ **Yarn**:
53
+
54
+ ```bash
55
+ yarn add @mastra/s3 @mastra/e2b
56
+ ```
57
+
58
+ **Bun**:
59
+
60
+ ```bash
61
+ bun add @mastra/s3 @mastra/e2b
62
+ ```
63
+
64
+ ```typescript
65
+ import { Mastra } from '@mastra/core/mastra'
66
+ import { MastraEditor } from '@mastra/editor'
67
+ import { s3FilesystemProvider } from '@mastra/s3'
68
+ import { e2bSandboxProvider } from '@mastra/e2b'
69
+
70
+ new Mastra({
71
+ editor: new MastraEditor({
72
+ filesystems: { [s3FilesystemProvider.id]: s3FilesystemProvider },
73
+ sandboxes: { [e2bSandboxProvider.id]: e2bSandboxProvider },
74
+ builder: {
75
+ enabled: true,
76
+ configuration: {
77
+ agent: {
78
+ workspace: {
79
+ type: 'inline',
80
+ config: {
81
+ name: 'builder-workspace',
82
+ filesystem: {
83
+ provider: s3FilesystemProvider.id,
84
+ config: {
85
+ bucket: process.env.S3_BUCKET!,
86
+ region: process.env.S3_REGION!,
87
+ },
88
+ },
89
+ sandbox: {
90
+ provider: e2bSandboxProvider.id,
91
+ config: { apiKey: process.env.E2B_API_KEY! },
92
+ },
93
+ },
94
+ },
95
+ },
96
+ },
97
+ },
98
+ }),
99
+ })
100
+ ```
101
+
102
+ `S3Filesystem` uses the default AWS credential chain (environment variables, `~/.aws` config, IAM roles, EC2 instance profile). For long-running deployments, use a credential provider function so credentials refresh automatically.
103
+
104
+ `DockerSandbox` and `VercelSandbox` are alternative cloud sandbox providers — pick whichever matches your runtime.
105
+
106
+ > **Warning:** A local sandbox can't run commands safely in a shared environment. Always register a cloud sandbox provider and reference it in the workspace config before deploying.
107
+
108
+ ## Auth and RBAC
109
+
110
+ A production deployment without authentication exposes the Builder to the public internet. Register a `Mastra.server.auth` provider (for example, WorkOS or your own provider) and a `Mastra.server.rbac` provider to gate access.
111
+
112
+ See [Access control](https://mastra.ai/docs/agent-builder/access-control) for the required role permissions and a WorkOS quickstart.
113
+
114
+ ## Public URL for channels
115
+
116
+ Slack needs to reach your server through a public URL. Pass `baseUrl` to `SlackProvider` with the deployed URL (no trailing slash). See [Channels](https://mastra.ai/docs/agent-builder/channels) for the full setup.
117
+
118
+ ## Related
119
+
120
+ - [Access control](https://mastra.ai/docs/agent-builder/access-control) — auth and RBAC setup.
121
+ - [Channels](https://mastra.ai/docs/agent-builder/channels) — Slack `baseUrl` and channel-specific setup.
@@ -0,0 +1,97 @@
1
+ # Agent Builder overview
2
+
3
+ > **Note:** The Agent Builder is part of the Mastra Enterprise Edition. Production deployments require a valid EE license. [Contact sales](https://mastra.ai/contact) for more information.
4
+
5
+ The Agent Builder lets you build, configure, and operate Mastra agents all within the UI. It runs inside your Mastra server, persists everything to `Mastra.storage`, and supports multi-tenant agent workflows with RBAC and channel integrations.
6
+
7
+ - [**Configuration**](https://mastra.ai/docs/agent-builder/configuration): Toggle UI sections and pin admin-controlled defaults for every new agent.
8
+ - [**Model policy**](https://mastra.ai/docs/agent-builder/model-policy): Restrict which providers and models the Builder exposes, and pin a default.
9
+ - [**Memory**](https://mastra.ai/docs/agent-builder/memory): Configure the default memory shape for every Builder-created agent.
10
+ - [**Access control**](https://mastra.ai/docs/agent-builder/access-control): Gate the Builder behind Mastra RBAC roles and permissions.
11
+ - [**Channels**](https://mastra.ai/docs/agent-builder/channels): Connect Builder-created agents to Slack and other channels.
12
+ - [**Skill registries**](https://mastra.ai/docs/agent-builder/skill-registries): Browse and install community skills from opt-in registries.
13
+ - [**Deploying**](https://mastra.ai/docs/agent-builder/deploying): Swap local primitives for cloud-backed storage, filesystems, and sandboxes.
14
+
15
+ For building agents entirely in code, see the [Agents overview](https://mastra.ai/docs/agents/overview). For editing code-defined agents through Studio, see the [Editor overview](https://mastra.ai/docs/editor/overview).
16
+
17
+ ## Get started
18
+
19
+ Install `@mastra/editor` alongside a storage adapter:
20
+
21
+ **npm**:
22
+
23
+ ```bash
24
+ npm install @mastra/editor @mastra/libsql
25
+ ```
26
+
27
+ **pnpm**:
28
+
29
+ ```bash
30
+ pnpm add @mastra/editor @mastra/libsql
31
+ ```
32
+
33
+ **Yarn**:
34
+
35
+ ```bash
36
+ yarn add @mastra/editor @mastra/libsql
37
+ ```
38
+
39
+ **Bun**:
40
+
41
+ ```bash
42
+ bun add @mastra/editor @mastra/libsql
43
+ ```
44
+
45
+ Wire the Agent Builder onto a `Mastra` instance:
46
+
47
+ ```typescript
48
+ import { Mastra } from '@mastra/core/mastra'
49
+ import { MastraEditor } from '@mastra/editor'
50
+ import { createBuilderAgent } from '@mastra/editor/ee'
51
+ import { LibSQLStore } from '@mastra/libsql'
52
+
53
+ export const mastra = new Mastra({
54
+ storage: new LibSQLStore({ url: 'file:./mastra.db' }),
55
+ agents: { builderAgent: createBuilderAgent() },
56
+ editor: new MastraEditor({
57
+ builder: {
58
+ enabled: true,
59
+ configuration: {
60
+ agent: {
61
+ memory: { observationalMemory: true },
62
+ },
63
+ },
64
+ },
65
+ }),
66
+ })
67
+ ```
68
+
69
+ Start the dev server:
70
+
71
+ ```bash
72
+ npx mastra dev
73
+ ```
74
+
75
+ The Agent Builder is mounted at `http://localhost:4111/agent-builder`.
76
+
77
+ ## Prerequisites
78
+
79
+ The Agent Builder requires:
80
+
81
+ - **Storage**: An `@mastra/core` storage adapter on the `Mastra` instance. Agents, memory, and workspace state all persist through `Mastra.storage`.
82
+ - **The Builder agent**: Register a Builder agent created with the `createBuilderAgent()` factory from `@mastra/editor/ee` on `Mastra.agents`. The chat-based editor invokes it through the same `Mastra.getAgent(id)` lookup as any other agent. Without this registration, the chat-based editor returns 404.
83
+ - **`OPENAI_API_KEY`**: The Builder agent created by `createBuilderAgent()` runs on an OpenAI model, so an `OPENAI_API_KEY` environment variable is required.
84
+
85
+ ## Disabling the Builder
86
+
87
+ Set `enabled: false` to keep the config in place but turn the surface off:
88
+
89
+ ```typescript
90
+ new MastraEditor({
91
+ builder: {
92
+ enabled: false,
93
+ },
94
+ })
95
+ ```
96
+
97
+ Omitting the `builder` field has the same effect.
@@ -86,6 +86,20 @@ for await (const chunk of stream.fullStream) {
86
86
  }
87
87
  ```
88
88
 
89
+ #### Conditional approval with a function
90
+
91
+ Instead of a boolean, `requireToolApproval` accepts a function that decides per tool call. It receives the `toolName`, the `args` the model passed, the `requestContext`, and the `workspace`. Return `true` to require approval for that call, or `false` to allow it. This lets you gate approval dynamically — for example, only for tools whose name matches a pattern:
92
+
93
+ ```typescript
94
+ const stream = await agent.stream('Clean up old records', {
95
+ requireToolApproval: ({ toolName }) => /^delete_/.test(toolName),
96
+ })
97
+ ```
98
+
99
+ A tool's own `requireApproval` setting still takes precedence: if a tool defines its own approval rule, that rule decides for that tool and the function above does not override it. If the function throws, the call requires approval (fail-safe).
100
+
101
+ > **Note:** Function-based `requireToolApproval` is only available on regular `stream()` / `generate()` calls. Durable agents and stored agents persist their options, and a function can't be serialized, so they accept only a boolean. If you pass a function in those contexts it falls back to requiring approval for every tool call.
102
+
89
103
  ### Runtime suspension with `suspend()`
90
104
 
91
105
  A tool can also pause _during_ its `execute` function by calling `suspend()`. This is useful when the tool starts running and then discovers it needs additional user input or confirmation before it can finish.
@@ -65,7 +65,7 @@ const memory = new Memory({
65
65
  export const collabAgent = new Agent({
66
66
  id: 'collab',
67
67
  name: 'CollabAgent',
68
- model: 'openai/gpt-5.4-mini',
68
+ model: '__OPENAI_MODEL_MINI__',
69
69
  memory,
70
70
  instructions: `
71
71
  You are a collaborative document assistant. Multiple users talk to you in the SAME thread.
@@ -247,7 +247,7 @@ const agent = new Agent({
247
247
  })
248
248
  ```
249
249
 
250
- The model router automatically handles API key detection from environment variables (`OPENAI_API_KEY`, `GOOGLE_GENERATIVE_AI_API_KEY`, `OPENROUTER_API_KEY`).
250
+ The model router automatically handles API key detection from environment variables (`OPENAI_API_KEY`, `GOOGLE_API_KEY`, `OPENROUTER_API_KEY`). Google models also fall back to `GOOGLE_GENERATIVE_AI_API_KEY`.
251
251
 
252
252
  ### Using AI SDK Packages
253
253
 
@@ -179,7 +179,7 @@ export const agent = new Agent({
179
179
  memory: new Memory({
180
180
  options: {
181
181
  generateTitle: {
182
- model: 'openai/gpt-5-mini',
182
+ model: '__OPENAI_MODEL_MINI__',
183
183
  instructions: 'Generate a 1 word title',
184
184
  },
185
185
  },
@@ -472,7 +472,10 @@ const initialResults = await pgVector.query({
472
472
  })
473
473
 
474
474
  // Create a relevance scorer
475
- const relevanceProvider = new MastraAgentRelevanceScorer('relevance-scorer', 'openai/gpt-5.4')
475
+ const relevanceProvider = new MastraAgentRelevanceScorer(
476
+ 'relevance-scorer',
477
+ 'openai/gpt-5.4',
478
+ )
476
479
 
477
480
  // Re-rank the results
478
481
  const rerankedResults = await rerank({
package/dist/index.cjs CHANGED
@@ -2275,7 +2275,15 @@ var AgentsLibSQL = class extends storage.AgentsStorage {
2275
2275
  await this.#db.alterTable({
2276
2276
  tableName: storage.TABLE_AGENT_VERSIONS,
2277
2277
  schema: storage.AGENT_VERSIONS_SCHEMA,
2278
- ifNotExists: ["mcpClients", "requestContextSchema", "workspace", "skills", "skillsFormat", "browser"]
2278
+ ifNotExists: [
2279
+ "mcpClients",
2280
+ "requestContextSchema",
2281
+ "workspace",
2282
+ "skills",
2283
+ "skillsFormat",
2284
+ "browser",
2285
+ "toolProviders"
2286
+ ]
2279
2287
  });
2280
2288
  await this.#migrateToolsToJsonbFormat();
2281
2289
  await this.#cleanupStaleDrafts();
@@ -2336,6 +2344,7 @@ var AgentsLibSQL = class extends storage.AgentsStorage {
2336
2344
  workflows: row.workflows ?? null,
2337
2345
  agents: row.agents ?? null,
2338
2346
  integrationTools: row.integrationTools ?? null,
2347
+ toolProviders: row.toolProviders ?? null,
2339
2348
  inputProcessors: row.inputProcessors ?? null,
2340
2349
  outputProcessors: row.outputProcessors ?? null,
2341
2350
  memory: row.memory ?? null,
@@ -2788,6 +2797,7 @@ var AgentsLibSQL = class extends storage.AgentsStorage {
2788
2797
  workflows: input.workflows ?? null,
2789
2798
  agents: input.agents ?? null,
2790
2799
  integrationTools: input.integrationTools ?? null,
2800
+ toolProviders: input.toolProviders ?? null,
2791
2801
  inputProcessors: input.inputProcessors ?? null,
2792
2802
  outputProcessors: input.outputProcessors ?? null,
2793
2803
  memory: input.memory ?? null,
@@ -3062,6 +3072,7 @@ var AgentsLibSQL = class extends storage.AgentsStorage {
3062
3072
  workflows: this.parseJson(row.workflows, "workflows"),
3063
3073
  agents: this.parseJson(row.agents, "agents"),
3064
3074
  integrationTools: this.parseJson(row.integrationTools, "integrationTools"),
3075
+ toolProviders: this.parseJson(row.toolProviders, "toolProviders"),
3065
3076
  inputProcessors: this.parseJson(row.inputProcessors, "inputProcessors"),
3066
3077
  outputProcessors: this.parseJson(row.outputProcessors, "outputProcessors"),
3067
3078
  memory: this.parseJson(row.memory, "memory"),
@@ -10980,6 +10991,197 @@ var SkillsLibSQL = class extends storage.SkillsStorage {
10980
10991
  };
10981
10992
  }
10982
10993
  };
10994
+ function normaliseScope(raw) {
10995
+ const value = raw == null ? "per-author" : String(raw);
10996
+ if (value === "shared") return "shared";
10997
+ if (value === "caller-supplied") return "caller-supplied";
10998
+ return "per-author";
10999
+ }
11000
+ function rowToToolProviderConnection(row) {
11001
+ return {
11002
+ authorId: String(row.authorId),
11003
+ providerId: String(row.providerId),
11004
+ toolkit: String(row.toolkit),
11005
+ connectionId: String(row.connectionId),
11006
+ label: row.label == null ? null : String(row.label),
11007
+ scope: normaliseScope(row.scope),
11008
+ createdAt: new Date(String(row.createdAt)),
11009
+ updatedAt: new Date(String(row.updatedAt))
11010
+ };
11011
+ }
11012
+ var ToolProviderConnectionsLibSQL = class extends storage.ToolProviderConnectionsStorage {
11013
+ #db;
11014
+ #client;
11015
+ constructor(config) {
11016
+ super();
11017
+ const client = resolveClient(config);
11018
+ this.#client = client;
11019
+ this.#db = new LibSQLDB({ client, maxRetries: config.maxRetries, initialBackoffMs: config.initialBackoffMs });
11020
+ }
11021
+ async init() {
11022
+ await this.#db.createTable({
11023
+ tableName: storage.TABLE_TOOL_PROVIDER_CONNECTIONS,
11024
+ schema: storage.TOOL_PROVIDER_CONNECTIONS_SCHEMA,
11025
+ compositePrimaryKey: ["authorId", "providerId", "connectionId"]
11026
+ });
11027
+ await this.#client.execute(
11028
+ `CREATE INDEX IF NOT EXISTS idx_tool_provider_connections_author ON "${storage.TABLE_TOOL_PROVIDER_CONNECTIONS}" ("authorId", "providerId", "toolkit")`
11029
+ );
11030
+ }
11031
+ async dangerouslyClearAll() {
11032
+ await this.#client.execute(`DELETE FROM "${storage.TABLE_TOOL_PROVIDER_CONNECTIONS}"`);
11033
+ }
11034
+ async getConnectionById({
11035
+ authorId,
11036
+ providerId,
11037
+ connectionId
11038
+ }) {
11039
+ try {
11040
+ const result = await this.#client.execute({
11041
+ sql: `SELECT * FROM "${storage.TABLE_TOOL_PROVIDER_CONNECTIONS}" WHERE "authorId" = ? AND "providerId" = ? AND "connectionId" = ? LIMIT 1`,
11042
+ args: [authorId, providerId, connectionId]
11043
+ });
11044
+ const row = result.rows?.[0];
11045
+ if (!row) return null;
11046
+ return rowToToolProviderConnection(row);
11047
+ } catch (error$1) {
11048
+ if (error$1 instanceof error.MastraError) throw error$1;
11049
+ throw new error.MastraError(
11050
+ {
11051
+ id: storage.createStorageErrorId("LIBSQL", "TOOL_PROVIDER_CONNECTION_GET", "FAILED"),
11052
+ domain: error.ErrorDomain.STORAGE,
11053
+ category: error.ErrorCategory.THIRD_PARTY,
11054
+ details: { authorId, providerId, connectionId }
11055
+ },
11056
+ error$1
11057
+ );
11058
+ }
11059
+ }
11060
+ async upsertConnection(input) {
11061
+ const { authorId, providerId, toolkit, connectionId, label } = input;
11062
+ const now = /* @__PURE__ */ new Date();
11063
+ const nowIso = now.toISOString();
11064
+ const labelValue = label == null ? null : label;
11065
+ try {
11066
+ const tx = await this.#client.transaction("write");
11067
+ try {
11068
+ const existing = await tx.execute({
11069
+ sql: `SELECT "createdAt", "scope" FROM "${storage.TABLE_TOOL_PROVIDER_CONNECTIONS}" WHERE "authorId" = ? AND "providerId" = ? AND "connectionId" = ? LIMIT 1`,
11070
+ args: [authorId, providerId, connectionId]
11071
+ });
11072
+ const existingRow = existing.rows?.[0];
11073
+ const createdAt = existingRow ? String(existingRow.createdAt) : nowIso;
11074
+ const existingScope = existingRow && existingRow.scope != null ? normaliseScope(existingRow.scope) : void 0;
11075
+ const scope = input.scope ?? existingScope ?? "per-author";
11076
+ if (existingRow) {
11077
+ await tx.execute({
11078
+ sql: `UPDATE "${storage.TABLE_TOOL_PROVIDER_CONNECTIONS}" SET "toolkit" = ?, "label" = ?, "scope" = ?, "updatedAt" = ? WHERE "authorId" = ? AND "providerId" = ? AND "connectionId" = ?`,
11079
+ args: [toolkit, labelValue, scope, nowIso, authorId, providerId, connectionId]
11080
+ });
11081
+ } else {
11082
+ await tx.execute({
11083
+ sql: `INSERT INTO "${storage.TABLE_TOOL_PROVIDER_CONNECTIONS}" ("authorId", "providerId", "toolkit", "connectionId", "label", "scope", "createdAt", "updatedAt") VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
11084
+ args: [authorId, providerId, toolkit, connectionId, labelValue, scope, createdAt, nowIso]
11085
+ });
11086
+ }
11087
+ await tx.commit();
11088
+ return {
11089
+ authorId,
11090
+ providerId,
11091
+ toolkit,
11092
+ connectionId,
11093
+ label: labelValue,
11094
+ scope,
11095
+ createdAt: new Date(createdAt),
11096
+ updatedAt: now
11097
+ };
11098
+ } catch (error) {
11099
+ if (!tx.closed) {
11100
+ await tx.rollback();
11101
+ }
11102
+ throw error;
11103
+ }
11104
+ } catch (error$1) {
11105
+ if (error$1 instanceof error.MastraError) throw error$1;
11106
+ throw new error.MastraError(
11107
+ {
11108
+ id: storage.createStorageErrorId("LIBSQL", "TOOL_PROVIDER_CONNECTION_UPSERT", "FAILED"),
11109
+ domain: error.ErrorDomain.STORAGE,
11110
+ category: error.ErrorCategory.THIRD_PARTY,
11111
+ details: { authorId, providerId, connectionId }
11112
+ },
11113
+ error$1
11114
+ );
11115
+ }
11116
+ }
11117
+ async listConnectionsByAuthor({
11118
+ authorId,
11119
+ providerId,
11120
+ toolkit,
11121
+ scope
11122
+ }) {
11123
+ try {
11124
+ const clauses = [];
11125
+ const args = [];
11126
+ if (authorId !== void 0) {
11127
+ clauses.push('"authorId" = ?');
11128
+ args.push(authorId);
11129
+ }
11130
+ if (providerId) {
11131
+ clauses.push('"providerId" = ?');
11132
+ args.push(providerId);
11133
+ }
11134
+ if (toolkit) {
11135
+ clauses.push('"toolkit" = ?');
11136
+ args.push(toolkit);
11137
+ }
11138
+ if (scope) {
11139
+ clauses.push('"scope" = ?');
11140
+ args.push(scope);
11141
+ }
11142
+ const whereClause = clauses.length > 0 ? ` WHERE ${clauses.join(" AND ")}` : "";
11143
+ const result = await this.#client.execute({
11144
+ sql: `SELECT * FROM "${storage.TABLE_TOOL_PROVIDER_CONNECTIONS}"${whereClause}`,
11145
+ args
11146
+ });
11147
+ return (result.rows ?? []).map((row) => rowToToolProviderConnection(row));
11148
+ } catch (error$1) {
11149
+ if (error$1 instanceof error.MastraError) throw error$1;
11150
+ throw new error.MastraError(
11151
+ {
11152
+ id: storage.createStorageErrorId("LIBSQL", "TOOL_PROVIDER_CONNECTION_LIST", "FAILED"),
11153
+ domain: error.ErrorDomain.STORAGE,
11154
+ category: error.ErrorCategory.THIRD_PARTY,
11155
+ details: { authorId: authorId ?? "", providerId: providerId ?? "", toolkit: toolkit ?? "" }
11156
+ },
11157
+ error$1
11158
+ );
11159
+ }
11160
+ }
11161
+ async deleteConnection({
11162
+ authorId,
11163
+ providerId,
11164
+ connectionId
11165
+ }) {
11166
+ try {
11167
+ await this.#client.execute({
11168
+ sql: `DELETE FROM "${storage.TABLE_TOOL_PROVIDER_CONNECTIONS}" WHERE "authorId" = ? AND "providerId" = ? AND "connectionId" = ?`,
11169
+ args: [authorId, providerId, connectionId]
11170
+ });
11171
+ } catch (error$1) {
11172
+ if (error$1 instanceof error.MastraError) throw error$1;
11173
+ throw new error.MastraError(
11174
+ {
11175
+ id: storage.createStorageErrorId("LIBSQL", "TOOL_PROVIDER_CONNECTION_DELETE", "FAILED"),
11176
+ domain: error.ErrorDomain.STORAGE,
11177
+ category: error.ErrorCategory.THIRD_PARTY,
11178
+ details: { authorId, providerId, connectionId }
11179
+ },
11180
+ error$1
11181
+ );
11182
+ }
11183
+ }
11184
+ };
10983
11185
  var WorkflowsLibSQL = class extends storage.WorkflowsStorage {
10984
11186
  #db;
10985
11187
  #client;
@@ -11916,6 +12118,7 @@ var LibSQLStore = class extends storage.MastraCompositeStore {
11916
12118
  const blobs = new BlobsLibSQL(domainConfig);
11917
12119
  const backgroundTasks = new BackgroundTasksLibSQL(domainConfig);
11918
12120
  const schedules = new SchedulesLibSQL(domainConfig);
12121
+ const toolProviderConnections = new ToolProviderConnectionsLibSQL(domainConfig);
11919
12122
  this.stores = {
11920
12123
  scores,
11921
12124
  workflows,
@@ -11934,7 +12137,8 @@ var LibSQLStore = class extends storage.MastraCompositeStore {
11934
12137
  favorites,
11935
12138
  blobs,
11936
12139
  backgroundTasks,
11937
- schedules
12140
+ schedules,
12141
+ toolProviderConnections
11938
12142
  };
11939
12143
  }
11940
12144
  async applyLocalPragmas() {
@@ -11994,6 +12198,34 @@ var LibSQLStore = class extends storage.MastraCompositeStore {
11994
12198
  }
11995
12199
  await this.initDomainsSequentially();
11996
12200
  }
12201
+ /**
12202
+ * Closes the underlying libsql client, releasing all OS file handles.
12203
+ *
12204
+ * For local file databases, first runs PRAGMA wal_checkpoint(TRUNCATE) and
12205
+ * switches back to journal_mode=DELETE so that Windows releases the -wal
12206
+ * and -shm sidecar files promptly. Without this, the handles stay open
12207
+ * until process exit, causing EBUSY errors when callers try to fs.rm the
12208
+ * storage directory after Mastra.shutdown().
12209
+ *
12210
+ * Remote (Turso) databases skip the WAL pragmas and just close the client.
12211
+ *
12212
+ * Safe to call more than once; subsequent calls are no-ops.
12213
+ */
12214
+ async close() {
12215
+ if (this.client.closed) {
12216
+ return;
12217
+ }
12218
+ const isLocalFileDb = this.isLocalDb || this.client.protocol === "file";
12219
+ if (isLocalFileDb) {
12220
+ try {
12221
+ await this.client.execute("PRAGMA wal_checkpoint(TRUNCATE);");
12222
+ await this.client.execute("PRAGMA journal_mode=DELETE;");
12223
+ } catch (err) {
12224
+ this.logger.warn("LibSQLStore: Failed to checkpoint WAL before close.", err);
12225
+ }
12226
+ }
12227
+ this.client.close();
12228
+ }
11997
12229
  };
11998
12230
 
11999
12231
  // src/vector/prompt.ts
@@ -12115,6 +12347,7 @@ exports.SchedulesLibSQL = SchedulesLibSQL;
12115
12347
  exports.ScorerDefinitionsLibSQL = ScorerDefinitionsLibSQL;
12116
12348
  exports.ScoresLibSQL = ScoresLibSQL;
12117
12349
  exports.SkillsLibSQL = SkillsLibSQL;
12350
+ exports.ToolProviderConnectionsLibSQL = ToolProviderConnectionsLibSQL;
12118
12351
  exports.WorkflowsLibSQL = WorkflowsLibSQL;
12119
12352
  exports.WorkspacesLibSQL = WorkspacesLibSQL;
12120
12353
  //# sourceMappingURL=index.cjs.map