@mastra/s3 0.1.0 → 0.2.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,187 @@
1
1
  # @mastra/s3
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Added workspace and skill storage domains with full CRUD, versioning, and implementations across LibSQL, Postgres, and MongoDB. Added `editor.workspace` and `editor.skill` namespaces for managing workspace configurations and skill definitions through the editor. Agents stored in the editor can now reference workspaces (by ID or inline config) and skills, with full hydration to runtime `Workspace` instances during agent resolution. ([#13156](https://github.com/mastra-ai/mastra/pull/13156))
8
+
9
+ **Filesystem-native skill versioning (draft → publish model):**
10
+
11
+ Skills are versioned as filesystem trees with content-addressable blob storage. The editing surface (live filesystem) is separated from the serving surface (versioned blob store), enabling a `draft → publish` workflow:
12
+ - `editor.skill.publish(skillId, source, skillPath)` — Snapshots a skill directory from the filesystem into blob storage, creates a new version with a tree manifest, and sets `activeVersionId`
13
+ - Version switching via `editor.skill.update({ id, activeVersionId })` — Points the skill to a previous version without re-publishing
14
+ - Publishing a skill automatically invalidates cached agents that reference it, so they re-hydrate with the updated version on next access
15
+
16
+ **Agent skill resolution strategies:**
17
+
18
+ Agents can reference skills with different resolution strategies:
19
+ - `strategy: 'latest'` — Resolves the skill's active version (honors `activeVersionId` for rollback)
20
+ - `pin: '<versionId>'` — Pins to a specific version, immune to publishes
21
+ - `strategy: 'live'` — Reads directly from the live filesystem (no blob store)
22
+
23
+ **Blob storage infrastructure:**
24
+ - `BlobStore` abstract class for content-addressable storage keyed by SHA-256 hash
25
+ - `InMemoryBlobStore` for testing
26
+ - LibSQL, Postgres, and MongoDB implementations
27
+ - `S3BlobStore` for storing blobs in S3 or S3-compatible storage (AWS, R2, MinIO, DO Spaces)
28
+ - `BlobStoreProvider` interface and `MastraEditorConfig.blobStores` registry for pluggable blob storage
29
+ - `VersionedSkillSource` and `CompositeVersionedSkillSource` for reading skill files from the blob store at runtime
30
+
31
+ **New storage types:**
32
+ - `StorageWorkspaceSnapshotType` and `StorageSkillSnapshotType` with corresponding input/output types
33
+ - `StorageWorkspaceRef` for ID-based or inline workspace references on agents
34
+ - `StorageSkillConfig` for per-agent skill overrides (`pin`, `strategy`, description, instructions)
35
+ - `SkillVersionTree` and `SkillVersionTreeEntry` for tree manifests
36
+ - `StorageBlobEntry` for content-addressable blob entries
37
+ - `SKILL_BLOBS_SCHEMA` for the `mastra_skill_blobs` table
38
+
39
+ **New editor namespaces:**
40
+ - `editor.workspace` — CRUD for workspace configs, plus `hydrateSnapshotToWorkspace()` for resolving to runtime `Workspace` instances
41
+ - `editor.skill` — CRUD for skill definitions, plus `publish()` for filesystem-to-blob snapshots
42
+
43
+ **Provider registries:**
44
+ - `MastraEditorConfig` accepts `filesystems`, `sandboxes`, and `blobStores` provider registries (keyed by provider ID)
45
+ - Built-in `local` filesystem and sandbox providers are auto-registered
46
+ - `editor.resolveBlobStore()` resolves from provider registry or falls back to the storage backend's blobs domain
47
+ - Providers expose `id`, `name`, `description`, `configSchema` (JSON Schema for UI form rendering), and a factory method
48
+
49
+ **Storage adapter support:**
50
+ - LibSQL: Full `workspaces`, `skills`, and `blobs` domain implementations
51
+ - Postgres: Full `workspaces`, `skills`, and `blobs` domain implementations
52
+ - MongoDB: Full `workspaces`, `skills`, and `blobs` domain implementations
53
+ - All three include `workspace`, `skills`, and `skillsFormat` fields on agent versions
54
+
55
+ **Server endpoints:**
56
+ - `GET/POST/PATCH/DELETE /stored/workspaces` — CRUD for stored workspaces
57
+ - `GET/POST/PATCH/DELETE /stored/skills` — CRUD for stored skills
58
+ - `POST /stored/skills/:id/publish` — Publish a skill from a filesystem source
59
+
60
+ ```ts
61
+ import { MastraEditor } from '@mastra/editor';
62
+ import { s3FilesystemProvider, s3BlobStoreProvider } from '@mastra/s3';
63
+ import { e2bSandboxProvider } from '@mastra/e2b';
64
+
65
+ const editor = new MastraEditor({
66
+ filesystems: { s3: s3FilesystemProvider },
67
+ sandboxes: { e2b: e2bSandboxProvider },
68
+ blobStores: { s3: s3BlobStoreProvider },
69
+ });
70
+
71
+ // Create a skill and publish it
72
+ const skill = await editor.skill.create({
73
+ name: 'Code Review',
74
+ description: 'Reviews code for best practices',
75
+ instructions: 'Analyze the code and provide feedback...',
76
+ });
77
+ await editor.skill.publish(skill.id, source, 'skills/code-review');
78
+
79
+ // Agents resolve skills by strategy
80
+ await editor.agent.create({
81
+ name: 'Dev Assistant',
82
+ model: { provider: 'openai', name: 'gpt-4' },
83
+ workspace: { type: 'id', workspaceId: workspace.id },
84
+ skills: { [skill.id]: { strategy: 'latest' } },
85
+ skillsFormat: 'xml',
86
+ });
87
+ ```
88
+
89
+ ### Patch Changes
90
+
91
+ - Updated dependencies [[`252580a`](https://github.com/mastra-ai/mastra/commit/252580a71feb0e46d0ccab04a70a79ff6a2ee0ab), [`f8e819f`](https://github.com/mastra-ai/mastra/commit/f8e819fabdfdc43d2da546a3ad81ba23685f603d), [`5c75261`](https://github.com/mastra-ai/mastra/commit/5c7526120d936757d4ffb7b82232e1641ebd45cb), [`e27d832`](https://github.com/mastra-ai/mastra/commit/e27d83281b5e166fd63a13969689e928d8605944), [`e37ef84`](https://github.com/mastra-ai/mastra/commit/e37ef8404043c94ca0c8e35ecdedb093b8087878), [`6fdd3d4`](https://github.com/mastra-ai/mastra/commit/6fdd3d451a07a8e7e216c62ac364f8dd8e36c2af), [`10cf521`](https://github.com/mastra-ai/mastra/commit/10cf52183344743a0d7babe24cd24fd78870c354), [`efdb682`](https://github.com/mastra-ai/mastra/commit/efdb682887f6522149769383908f9790c188ab88), [`0dee7a0`](https://github.com/mastra-ai/mastra/commit/0dee7a0ff4c2507e6eb6e6ee5f9738877ebd4ad1), [`04c2c8e`](https://github.com/mastra-ai/mastra/commit/04c2c8e888984364194131aecb490a3d6e920e61), [`02dc07a`](https://github.com/mastra-ai/mastra/commit/02dc07acc4ad42d93335825e3308f5b42266eba2), [`bb7262b`](https://github.com/mastra-ai/mastra/commit/bb7262b7c0ca76320d985b40510b6ffbbb936582), [`cf1c6e7`](https://github.com/mastra-ai/mastra/commit/cf1c6e789b131f55638fed52183a89d5078b4876), [`5ffadfe`](https://github.com/mastra-ai/mastra/commit/5ffadfefb1468ac2612b20bb84d24c39de6961c0), [`1e1339c`](https://github.com/mastra-ai/mastra/commit/1e1339cc276e571a48cfff5014487877086bfe68), [`d03df73`](https://github.com/mastra-ai/mastra/commit/d03df73f8fe9496064a33e1c3b74ba0479bf9ee6), [`79b8f45`](https://github.com/mastra-ai/mastra/commit/79b8f45a6767e1a5c3d56cd3c5b1214326b81661), [`9bbf08e`](https://github.com/mastra-ai/mastra/commit/9bbf08e3c20731c79dea13a765895b9fcf29cbf1), [`0a25952`](https://github.com/mastra-ai/mastra/commit/0a259526b5e1ac11e6efa53db1f140272962af2d), [`ffa5468`](https://github.com/mastra-ai/mastra/commit/ffa546857fc4821753979b3a34e13b4d76fbbcd4), [`3264a04`](https://github.com/mastra-ai/mastra/commit/3264a04e30340c3c5447433300a035ea0878df85), [`6fdd3d4`](https://github.com/mastra-ai/mastra/commit/6fdd3d451a07a8e7e216c62ac364f8dd8e36c2af), [`088d9ba`](https://github.com/mastra-ai/mastra/commit/088d9ba2577518703c52b0dccd617178d9ee6b0d), [`74fbebd`](https://github.com/mastra-ai/mastra/commit/74fbebd918a03832a2864965a8bea59bf617d3a2), [`aea6217`](https://github.com/mastra-ai/mastra/commit/aea621790bfb2291431b08da0cc5e6e150303ae7), [`b6a855e`](https://github.com/mastra-ai/mastra/commit/b6a855edc056e088279075506442ba1d6fa6def9), [`ae408ea`](https://github.com/mastra-ai/mastra/commit/ae408ea7128f0d2710b78d8623185198e7cb19c1), [`17e942e`](https://github.com/mastra-ai/mastra/commit/17e942eee2ba44985b1f807e6208cdde672f82f9), [`2015cf9`](https://github.com/mastra-ai/mastra/commit/2015cf921649f44c3f5bcd32a2c052335f8e49b4), [`7ef454e`](https://github.com/mastra-ai/mastra/commit/7ef454eaf9dcec6de60021c8f42192052dd490d6), [`2be1d99`](https://github.com/mastra-ai/mastra/commit/2be1d99564ce79acc4846071082bff353035a87a), [`2708fa1`](https://github.com/mastra-ai/mastra/commit/2708fa1055ac91c03e08b598869f6b8fb51fa37f), [`ba74aef`](https://github.com/mastra-ai/mastra/commit/ba74aef5716142dbbe931351f5243c9c6e4128a9), [`ba74aef`](https://github.com/mastra-ai/mastra/commit/ba74aef5716142dbbe931351f5243c9c6e4128a9), [`ec53e89`](https://github.com/mastra-ai/mastra/commit/ec53e8939c76c638991e21af762e51378eff7543), [`9b5a8cb`](https://github.com/mastra-ai/mastra/commit/9b5a8cb13e120811b0bf14140ada314f1c067894), [`607e66b`](https://github.com/mastra-ai/mastra/commit/607e66b02dc7f531ee37799f3456aa2dc0ca7ac5), [`a215d06`](https://github.com/mastra-ai/mastra/commit/a215d06758dcf590eabfe0b7afd4ae39bdbf082c), [`6909c74`](https://github.com/mastra-ai/mastra/commit/6909c74a7781e0447d475e9dbc1dc871b700f426), [`192438f`](https://github.com/mastra-ai/mastra/commit/192438f8a90c4f375e955f8ff179bf8dc6821a83)]:
92
+ - @mastra/core@1.5.0
93
+
94
+ ## 0.2.0-alpha.0
95
+
96
+ ### Minor Changes
97
+
98
+ - Added workspace and skill storage domains with full CRUD, versioning, and implementations across LibSQL, Postgres, and MongoDB. Added `editor.workspace` and `editor.skill` namespaces for managing workspace configurations and skill definitions through the editor. Agents stored in the editor can now reference workspaces (by ID or inline config) and skills, with full hydration to runtime `Workspace` instances during agent resolution. ([#13156](https://github.com/mastra-ai/mastra/pull/13156))
99
+
100
+ **Filesystem-native skill versioning (draft → publish model):**
101
+
102
+ Skills are versioned as filesystem trees with content-addressable blob storage. The editing surface (live filesystem) is separated from the serving surface (versioned blob store), enabling a `draft → publish` workflow:
103
+ - `editor.skill.publish(skillId, source, skillPath)` — Snapshots a skill directory from the filesystem into blob storage, creates a new version with a tree manifest, and sets `activeVersionId`
104
+ - Version switching via `editor.skill.update({ id, activeVersionId })` — Points the skill to a previous version without re-publishing
105
+ - Publishing a skill automatically invalidates cached agents that reference it, so they re-hydrate with the updated version on next access
106
+
107
+ **Agent skill resolution strategies:**
108
+
109
+ Agents can reference skills with different resolution strategies:
110
+ - `strategy: 'latest'` — Resolves the skill's active version (honors `activeVersionId` for rollback)
111
+ - `pin: '<versionId>'` — Pins to a specific version, immune to publishes
112
+ - `strategy: 'live'` — Reads directly from the live filesystem (no blob store)
113
+
114
+ **Blob storage infrastructure:**
115
+ - `BlobStore` abstract class for content-addressable storage keyed by SHA-256 hash
116
+ - `InMemoryBlobStore` for testing
117
+ - LibSQL, Postgres, and MongoDB implementations
118
+ - `S3BlobStore` for storing blobs in S3 or S3-compatible storage (AWS, R2, MinIO, DO Spaces)
119
+ - `BlobStoreProvider` interface and `MastraEditorConfig.blobStores` registry for pluggable blob storage
120
+ - `VersionedSkillSource` and `CompositeVersionedSkillSource` for reading skill files from the blob store at runtime
121
+
122
+ **New storage types:**
123
+ - `StorageWorkspaceSnapshotType` and `StorageSkillSnapshotType` with corresponding input/output types
124
+ - `StorageWorkspaceRef` for ID-based or inline workspace references on agents
125
+ - `StorageSkillConfig` for per-agent skill overrides (`pin`, `strategy`, description, instructions)
126
+ - `SkillVersionTree` and `SkillVersionTreeEntry` for tree manifests
127
+ - `StorageBlobEntry` for content-addressable blob entries
128
+ - `SKILL_BLOBS_SCHEMA` for the `mastra_skill_blobs` table
129
+
130
+ **New editor namespaces:**
131
+ - `editor.workspace` — CRUD for workspace configs, plus `hydrateSnapshotToWorkspace()` for resolving to runtime `Workspace` instances
132
+ - `editor.skill` — CRUD for skill definitions, plus `publish()` for filesystem-to-blob snapshots
133
+
134
+ **Provider registries:**
135
+ - `MastraEditorConfig` accepts `filesystems`, `sandboxes`, and `blobStores` provider registries (keyed by provider ID)
136
+ - Built-in `local` filesystem and sandbox providers are auto-registered
137
+ - `editor.resolveBlobStore()` resolves from provider registry or falls back to the storage backend's blobs domain
138
+ - Providers expose `id`, `name`, `description`, `configSchema` (JSON Schema for UI form rendering), and a factory method
139
+
140
+ **Storage adapter support:**
141
+ - LibSQL: Full `workspaces`, `skills`, and `blobs` domain implementations
142
+ - Postgres: Full `workspaces`, `skills`, and `blobs` domain implementations
143
+ - MongoDB: Full `workspaces`, `skills`, and `blobs` domain implementations
144
+ - All three include `workspace`, `skills`, and `skillsFormat` fields on agent versions
145
+
146
+ **Server endpoints:**
147
+ - `GET/POST/PATCH/DELETE /stored/workspaces` — CRUD for stored workspaces
148
+ - `GET/POST/PATCH/DELETE /stored/skills` — CRUD for stored skills
149
+ - `POST /stored/skills/:id/publish` — Publish a skill from a filesystem source
150
+
151
+ ```ts
152
+ import { MastraEditor } from '@mastra/editor';
153
+ import { s3FilesystemProvider, s3BlobStoreProvider } from '@mastra/s3';
154
+ import { e2bSandboxProvider } from '@mastra/e2b';
155
+
156
+ const editor = new MastraEditor({
157
+ filesystems: { s3: s3FilesystemProvider },
158
+ sandboxes: { e2b: e2bSandboxProvider },
159
+ blobStores: { s3: s3BlobStoreProvider },
160
+ });
161
+
162
+ // Create a skill and publish it
163
+ const skill = await editor.skill.create({
164
+ name: 'Code Review',
165
+ description: 'Reviews code for best practices',
166
+ instructions: 'Analyze the code and provide feedback...',
167
+ });
168
+ await editor.skill.publish(skill.id, source, 'skills/code-review');
169
+
170
+ // Agents resolve skills by strategy
171
+ await editor.agent.create({
172
+ name: 'Dev Assistant',
173
+ model: { provider: 'openai', name: 'gpt-4' },
174
+ workspace: { type: 'id', workspaceId: workspace.id },
175
+ skills: { [skill.id]: { strategy: 'latest' } },
176
+ skillsFormat: 'xml',
177
+ });
178
+ ```
179
+
180
+ ### Patch Changes
181
+
182
+ - Updated dependencies [[`252580a`](https://github.com/mastra-ai/mastra/commit/252580a71feb0e46d0ccab04a70a79ff6a2ee0ab), [`f8e819f`](https://github.com/mastra-ai/mastra/commit/f8e819fabdfdc43d2da546a3ad81ba23685f603d), [`5c75261`](https://github.com/mastra-ai/mastra/commit/5c7526120d936757d4ffb7b82232e1641ebd45cb), [`e27d832`](https://github.com/mastra-ai/mastra/commit/e27d83281b5e166fd63a13969689e928d8605944), [`e37ef84`](https://github.com/mastra-ai/mastra/commit/e37ef8404043c94ca0c8e35ecdedb093b8087878), [`6fdd3d4`](https://github.com/mastra-ai/mastra/commit/6fdd3d451a07a8e7e216c62ac364f8dd8e36c2af), [`10cf521`](https://github.com/mastra-ai/mastra/commit/10cf52183344743a0d7babe24cd24fd78870c354), [`efdb682`](https://github.com/mastra-ai/mastra/commit/efdb682887f6522149769383908f9790c188ab88), [`0dee7a0`](https://github.com/mastra-ai/mastra/commit/0dee7a0ff4c2507e6eb6e6ee5f9738877ebd4ad1), [`04c2c8e`](https://github.com/mastra-ai/mastra/commit/04c2c8e888984364194131aecb490a3d6e920e61), [`02dc07a`](https://github.com/mastra-ai/mastra/commit/02dc07acc4ad42d93335825e3308f5b42266eba2), [`bb7262b`](https://github.com/mastra-ai/mastra/commit/bb7262b7c0ca76320d985b40510b6ffbbb936582), [`cf1c6e7`](https://github.com/mastra-ai/mastra/commit/cf1c6e789b131f55638fed52183a89d5078b4876), [`5ffadfe`](https://github.com/mastra-ai/mastra/commit/5ffadfefb1468ac2612b20bb84d24c39de6961c0), [`1e1339c`](https://github.com/mastra-ai/mastra/commit/1e1339cc276e571a48cfff5014487877086bfe68), [`d03df73`](https://github.com/mastra-ai/mastra/commit/d03df73f8fe9496064a33e1c3b74ba0479bf9ee6), [`79b8f45`](https://github.com/mastra-ai/mastra/commit/79b8f45a6767e1a5c3d56cd3c5b1214326b81661), [`9bbf08e`](https://github.com/mastra-ai/mastra/commit/9bbf08e3c20731c79dea13a765895b9fcf29cbf1), [`0a25952`](https://github.com/mastra-ai/mastra/commit/0a259526b5e1ac11e6efa53db1f140272962af2d), [`ffa5468`](https://github.com/mastra-ai/mastra/commit/ffa546857fc4821753979b3a34e13b4d76fbbcd4), [`3264a04`](https://github.com/mastra-ai/mastra/commit/3264a04e30340c3c5447433300a035ea0878df85), [`6fdd3d4`](https://github.com/mastra-ai/mastra/commit/6fdd3d451a07a8e7e216c62ac364f8dd8e36c2af), [`088d9ba`](https://github.com/mastra-ai/mastra/commit/088d9ba2577518703c52b0dccd617178d9ee6b0d), [`74fbebd`](https://github.com/mastra-ai/mastra/commit/74fbebd918a03832a2864965a8bea59bf617d3a2), [`aea6217`](https://github.com/mastra-ai/mastra/commit/aea621790bfb2291431b08da0cc5e6e150303ae7), [`b6a855e`](https://github.com/mastra-ai/mastra/commit/b6a855edc056e088279075506442ba1d6fa6def9), [`ae408ea`](https://github.com/mastra-ai/mastra/commit/ae408ea7128f0d2710b78d8623185198e7cb19c1), [`17e942e`](https://github.com/mastra-ai/mastra/commit/17e942eee2ba44985b1f807e6208cdde672f82f9), [`2015cf9`](https://github.com/mastra-ai/mastra/commit/2015cf921649f44c3f5bcd32a2c052335f8e49b4), [`7ef454e`](https://github.com/mastra-ai/mastra/commit/7ef454eaf9dcec6de60021c8f42192052dd490d6), [`2be1d99`](https://github.com/mastra-ai/mastra/commit/2be1d99564ce79acc4846071082bff353035a87a), [`2708fa1`](https://github.com/mastra-ai/mastra/commit/2708fa1055ac91c03e08b598869f6b8fb51fa37f), [`ba74aef`](https://github.com/mastra-ai/mastra/commit/ba74aef5716142dbbe931351f5243c9c6e4128a9), [`ba74aef`](https://github.com/mastra-ai/mastra/commit/ba74aef5716142dbbe931351f5243c9c6e4128a9), [`ec53e89`](https://github.com/mastra-ai/mastra/commit/ec53e8939c76c638991e21af762e51378eff7543), [`9b5a8cb`](https://github.com/mastra-ai/mastra/commit/9b5a8cb13e120811b0bf14140ada314f1c067894), [`607e66b`](https://github.com/mastra-ai/mastra/commit/607e66b02dc7f531ee37799f3456aa2dc0ca7ac5), [`a215d06`](https://github.com/mastra-ai/mastra/commit/a215d06758dcf590eabfe0b7afd4ae39bdbf082c), [`6909c74`](https://github.com/mastra-ai/mastra/commit/6909c74a7781e0447d475e9dbc1dc871b700f426), [`192438f`](https://github.com/mastra-ai/mastra/commit/192438f8a90c4f375e955f8ff179bf8dc6821a83)]:
183
+ - @mastra/core@1.5.0-alpha.0
184
+
3
185
  ## 0.1.0
4
186
 
5
187
  ### Minor Changes
@@ -0,0 +1,89 @@
1
+ import { BlobStore } from '@mastra/core/storage';
2
+ import type { StorageBlobEntry } from '@mastra/core/storage';
3
+ /**
4
+ * Configuration for S3BlobStore.
5
+ *
6
+ * Compatible with AWS S3, Cloudflare R2, MinIO, DigitalOcean Spaces, etc.
7
+ */
8
+ export interface S3BlobStoreOptions {
9
+ /** S3 bucket name */
10
+ bucket: string;
11
+ /** AWS region (use 'auto' for R2) */
12
+ region: string;
13
+ /** AWS access key ID */
14
+ accessKeyId: string;
15
+ /** AWS secret access key */
16
+ secretAccessKey: string;
17
+ /**
18
+ * Custom endpoint URL for S3-compatible storage.
19
+ * Examples:
20
+ * - Cloudflare R2: 'https://{accountId}.r2.cloudflarestorage.com'
21
+ * - MinIO: 'http://localhost:9000'
22
+ */
23
+ endpoint?: string;
24
+ /** Force path-style URLs (required for some S3-compatible services like MinIO) */
25
+ forcePathStyle?: boolean;
26
+ /**
27
+ * Key prefix for all blob objects.
28
+ * Defaults to 'mastra_skill_blobs/'.
29
+ */
30
+ prefix?: string;
31
+ }
32
+ /**
33
+ * S3-backed content-addressable blob store for skill versioning.
34
+ *
35
+ * Each blob is stored as an S3 object keyed by its SHA-256 hash.
36
+ * Metadata (size, mimeType, createdAt) is stored in S3 object user metadata.
37
+ *
38
+ * Since blobs are content-addressable, writes are idempotent — the same hash
39
+ * always maps to the same content, so overwrites are safe and equivalent to
40
+ * a no-op.
41
+ *
42
+ * @example AWS S3
43
+ * ```typescript
44
+ * import { S3BlobStore } from '@mastra/s3';
45
+ *
46
+ * const blobs = new S3BlobStore({
47
+ * bucket: 'my-skill-blobs',
48
+ * region: 'us-east-1',
49
+ * accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
50
+ * secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
51
+ * });
52
+ * ```
53
+ *
54
+ * @example MinIO (local)
55
+ * ```typescript
56
+ * import { S3BlobStore } from '@mastra/s3';
57
+ *
58
+ * const blobs = new S3BlobStore({
59
+ * bucket: 'skill-blobs',
60
+ * region: 'us-east-1',
61
+ * accessKeyId: 'minioadmin',
62
+ * secretAccessKey: 'minioadmin',
63
+ * endpoint: 'http://localhost:9000',
64
+ * forcePathStyle: true,
65
+ * });
66
+ * ```
67
+ */
68
+ export declare class S3BlobStore extends BlobStore {
69
+ private readonly bucket;
70
+ private readonly prefix;
71
+ private _client;
72
+ private readonly region;
73
+ private readonly accessKeyId;
74
+ private readonly secretAccessKey;
75
+ private readonly endpoint?;
76
+ private readonly forcePathStyle;
77
+ constructor(options: S3BlobStoreOptions);
78
+ private getClient;
79
+ private toKey;
80
+ init(): Promise<void>;
81
+ put(entry: StorageBlobEntry): Promise<void>;
82
+ get(hash: string): Promise<StorageBlobEntry | null>;
83
+ has(hash: string): Promise<boolean>;
84
+ delete(hash: string): Promise<boolean>;
85
+ putMany(entries: StorageBlobEntry[]): Promise<void>;
86
+ getMany(hashes: string[]): Promise<Map<string, StorageBlobEntry>>;
87
+ dangerouslyClearAll(): Promise<void>;
88
+ }
89
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/blob-store/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,wBAAwB;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kFAAkF;IAClF,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAWD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,qBAAa,WAAY,SAAQ,SAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,OAAO,CAAyB;IAExC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;gBAE7B,OAAO,EAAE,kBAAkB;IAWvC,OAAO,CAAC,SAAS;IAcjB,OAAO,CAAC,KAAK;IAIP,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,GAAG,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB3C,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IA4BnD,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAiBnC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAiBtC,OAAO,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAOnD,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAcjE,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;CA6B3C"}
package/dist/index.cjs CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  var clientS3 = require('@aws-sdk/client-s3');
4
4
  var workspace = require('@mastra/core/workspace');
5
+ var storage = require('@mastra/core/storage');
5
6
 
6
7
  // src/filesystem/index.ts
7
8
  var MIME_TYPES = {
@@ -587,7 +588,210 @@ var S3Filesystem = class extends workspace.MastraFilesystem {
587
588
  this._client = null;
588
589
  }
589
590
  };
591
+ function trimSlashes2(s) {
592
+ let start = 0;
593
+ let end = s.length;
594
+ while (start < end && s[start] === "/") start++;
595
+ while (end > start && s[end - 1] === "/") end--;
596
+ return s.slice(start, end);
597
+ }
598
+ var S3BlobStore = class extends storage.BlobStore {
599
+ bucket;
600
+ prefix;
601
+ _client = null;
602
+ region;
603
+ accessKeyId;
604
+ secretAccessKey;
605
+ endpoint;
606
+ forcePathStyle;
607
+ constructor(options) {
608
+ super();
609
+ this.bucket = options.bucket;
610
+ this.region = options.region;
611
+ this.accessKeyId = options.accessKeyId;
612
+ this.secretAccessKey = options.secretAccessKey;
613
+ this.endpoint = options.endpoint;
614
+ this.forcePathStyle = options.forcePathStyle ?? !!options.endpoint;
615
+ this.prefix = options.prefix ? trimSlashes2(options.prefix) + "/" : "mastra_skill_blobs/";
616
+ }
617
+ getClient() {
618
+ if (this._client) return this._client;
619
+ this._client = new clientS3.S3Client({
620
+ region: this.region,
621
+ credentials: {
622
+ accessKeyId: this.accessKeyId,
623
+ secretAccessKey: this.secretAccessKey
624
+ },
625
+ endpoint: this.endpoint,
626
+ forcePathStyle: this.forcePathStyle
627
+ });
628
+ return this._client;
629
+ }
630
+ toKey(hash) {
631
+ return this.prefix + hash;
632
+ }
633
+ async init() {
634
+ }
635
+ async put(entry) {
636
+ const client = this.getClient();
637
+ const now = entry.createdAt ?? /* @__PURE__ */ new Date();
638
+ await client.send(
639
+ new clientS3.PutObjectCommand({
640
+ Bucket: this.bucket,
641
+ Key: this.toKey(entry.hash),
642
+ Body: entry.content,
643
+ ContentType: entry.mimeType ?? "application/octet-stream",
644
+ Metadata: {
645
+ size: String(entry.size),
646
+ createdat: now.toISOString(),
647
+ ...entry.mimeType ? { mimetype: entry.mimeType } : {}
648
+ }
649
+ })
650
+ );
651
+ }
652
+ async get(hash) {
653
+ const client = this.getClient();
654
+ try {
655
+ const response = await client.send(
656
+ new clientS3.GetObjectCommand({
657
+ Bucket: this.bucket,
658
+ Key: this.toKey(hash)
659
+ })
660
+ );
661
+ const body = await response.Body?.transformToString("utf-8");
662
+ if (body === void 0 || body === null) return null;
663
+ const metadata = response.Metadata ?? {};
664
+ return {
665
+ hash,
666
+ content: body,
667
+ size: metadata.size != null ? Number(metadata.size) : Buffer.byteLength(body, "utf-8"),
668
+ mimeType: metadata.mimetype || response.ContentType || void 0,
669
+ createdAt: metadata.createdat ? new Date(metadata.createdat) : /* @__PURE__ */ new Date()
670
+ };
671
+ } catch (error) {
672
+ if (isNotFoundError2(error)) return null;
673
+ throw error;
674
+ }
675
+ }
676
+ async has(hash) {
677
+ const client = this.getClient();
678
+ try {
679
+ await client.send(
680
+ new clientS3.HeadObjectCommand({
681
+ Bucket: this.bucket,
682
+ Key: this.toKey(hash)
683
+ })
684
+ );
685
+ return true;
686
+ } catch (error) {
687
+ if (isNotFoundError2(error)) return false;
688
+ throw error;
689
+ }
690
+ }
691
+ async delete(hash) {
692
+ const existed = await this.has(hash);
693
+ if (!existed) return false;
694
+ const client = this.getClient();
695
+ await client.send(
696
+ new clientS3.DeleteObjectCommand({
697
+ Bucket: this.bucket,
698
+ Key: this.toKey(hash)
699
+ })
700
+ );
701
+ return true;
702
+ }
703
+ async putMany(entries) {
704
+ if (entries.length === 0) return;
705
+ await Promise.all(entries.map((entry) => this.put(entry)));
706
+ }
707
+ async getMany(hashes) {
708
+ const result = /* @__PURE__ */ new Map();
709
+ if (hashes.length === 0) return result;
710
+ const entries = await Promise.all(hashes.map((hash) => this.get(hash)));
711
+ for (const entry of entries) {
712
+ if (entry) {
713
+ result.set(entry.hash, entry);
714
+ }
715
+ }
716
+ return result;
717
+ }
718
+ async dangerouslyClearAll() {
719
+ const client = this.getClient();
720
+ let continuationToken;
721
+ do {
722
+ const listResponse = await client.send(
723
+ new clientS3.ListObjectsV2Command({
724
+ Bucket: this.bucket,
725
+ Prefix: this.prefix,
726
+ ContinuationToken: continuationToken
727
+ })
728
+ );
729
+ const objects = listResponse.Contents;
730
+ if (objects && objects.length > 0) {
731
+ await client.send(
732
+ new clientS3.DeleteObjectsCommand({
733
+ Bucket: this.bucket,
734
+ Delete: {
735
+ Objects: objects.filter((obj) => obj.Key != null).map((obj) => ({ Key: obj.Key })),
736
+ Quiet: true
737
+ }
738
+ })
739
+ );
740
+ }
741
+ continuationToken = listResponse.IsTruncated ? listResponse.NextContinuationToken : void 0;
742
+ } while (continuationToken);
743
+ }
744
+ };
745
+ function isNotFoundError2(error) {
746
+ if (!error || typeof error !== "object" || !("name" in error)) return false;
747
+ const name = error.name;
748
+ return name === "NotFound" || name === "NoSuchKey" || name === "404";
749
+ }
750
+
751
+ // src/provider.ts
752
+ var s3FilesystemProvider = {
753
+ id: "s3",
754
+ name: "Amazon S3",
755
+ description: "S3 or S3-compatible storage (AWS, R2, MinIO, DO Spaces)",
756
+ configSchema: {
757
+ type: "object",
758
+ required: ["bucket", "region"],
759
+ properties: {
760
+ bucket: { type: "string", description: "S3 bucket name" },
761
+ region: { type: "string", description: 'AWS region (use "auto" for R2)' },
762
+ accessKeyId: { type: "string", description: "AWS access key ID" },
763
+ secretAccessKey: { type: "string", description: "AWS secret access key" },
764
+ endpoint: { type: "string", description: "Custom endpoint URL for S3-compatible storage" },
765
+ forcePathStyle: { type: "boolean", description: "Force path-style URLs", default: false },
766
+ prefix: { type: "string", description: "Key prefix (acts like a subdirectory)" },
767
+ readOnly: { type: "boolean", description: "Mount as read-only", default: false }
768
+ }
769
+ },
770
+ createFilesystem: (config) => new S3Filesystem(config)
771
+ };
772
+ var s3BlobStoreProvider = {
773
+ id: "s3",
774
+ name: "Amazon S3 Blob Store",
775
+ description: "Content-addressable blob storage using S3 or S3-compatible storage (AWS, R2, MinIO, DO Spaces)",
776
+ configSchema: {
777
+ type: "object",
778
+ required: ["bucket", "region", "accessKeyId", "secretAccessKey"],
779
+ properties: {
780
+ bucket: { type: "string", description: "S3 bucket name" },
781
+ region: { type: "string", description: 'AWS region (use "auto" for R2)' },
782
+ accessKeyId: { type: "string", description: "AWS access key ID" },
783
+ secretAccessKey: { type: "string", description: "AWS secret access key" },
784
+ endpoint: { type: "string", description: "Custom endpoint URL for S3-compatible storage" },
785
+ forcePathStyle: { type: "boolean", description: "Force path-style URLs", default: false },
786
+ prefix: { type: "string", description: "Key prefix for blob objects (default: mastra_skill_blobs/)" }
787
+ }
788
+ },
789
+ createBlobStore: (config) => new S3BlobStore(config)
790
+ };
590
791
 
792
+ exports.S3BlobStore = S3BlobStore;
591
793
  exports.S3Filesystem = S3Filesystem;
794
+ exports.s3BlobStoreProvider = s3BlobStoreProvider;
795
+ exports.s3FilesystemProvider = s3FilesystemProvider;
592
796
  //# sourceMappingURL=index.cjs.map
593
797
  //# sourceMappingURL=index.cjs.map