@mastra/cloudflare 0.0.0-a2a-20250421213654
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/LICENSE.md +7 -0
- package/README.md +175 -0
- package/dist/_tsup-dts-rollup.d.cts +257 -0
- package/dist/_tsup-dts-rollup.d.ts +257 -0
- package/dist/index.cjs +1011 -0
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1005 -0
- package/package.json +47 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright 2025 Mastra AI, Inc.
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# @mastra/cloudflare
|
|
2
|
+
|
|
3
|
+
Cloudflare KV store for Mastra, providing scalable and serverless storage for threads, messages, workflow snapshots, and evaluations. Supports both Cloudflare Workers KV Bindings and the REST API for flexible deployment in serverless and Node.js environments.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @mastra/cloudflare
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
|
|
13
|
+
- Cloudflare account with KV namespaces set up
|
|
14
|
+
- Node.js 16 or higher
|
|
15
|
+
- (Optional) Cloudflare Worker for Workers API mode
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { CloudflareStore } from '@mastra/cloudflare';
|
|
21
|
+
|
|
22
|
+
// Using Workers Binding API
|
|
23
|
+
const store = new CloudflareStore({
|
|
24
|
+
bindings: {
|
|
25
|
+
threads: THREADS_KV_NAMESPACE,
|
|
26
|
+
messages: MESSAGES_KV_NAMESPACE,
|
|
27
|
+
workflow_snapshot: WORKFLOW_KV_NAMESPACE,
|
|
28
|
+
evals: EVALS_KV_NAMESPACE,
|
|
29
|
+
traces: TRACES_KV_NAMESPACE,
|
|
30
|
+
},
|
|
31
|
+
keyPrefix: 'myapp_', // Optional
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Or using REST API
|
|
35
|
+
const store = new CloudflareStore({
|
|
36
|
+
accountId: process.env.CLOUDFLARE_ACCOUNT_ID!,
|
|
37
|
+
apiToken: process.env.CLOUDFLARE_API_TOKEN!,
|
|
38
|
+
namespacePrefix: 'myapp_', // Optional
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Save a thread
|
|
42
|
+
await store.saveThread({
|
|
43
|
+
id: 'thread-123',
|
|
44
|
+
resourceId: 'resource-456',
|
|
45
|
+
title: 'My Thread',
|
|
46
|
+
metadata: { key: 'value' },
|
|
47
|
+
createdAt: new Date(),
|
|
48
|
+
updatedAt: new Date(),
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Add messages
|
|
52
|
+
await store.saveMessages({
|
|
53
|
+
messages: [
|
|
54
|
+
{
|
|
55
|
+
id: 'msg-1',
|
|
56
|
+
threadId: 'thread-123',
|
|
57
|
+
content: 'Hello Cloudflare!',
|
|
58
|
+
role: 'user',
|
|
59
|
+
createdAt: new Date(),
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Query messages
|
|
65
|
+
const messages = await store.getMessages({ threadId: 'thread-123' });
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Configuration
|
|
69
|
+
|
|
70
|
+
- **Workers API**: Use the `bindings` option to pass KV namespaces directly (for Cloudflare Workers).
|
|
71
|
+
- **REST API**: Use `accountId`, `apiToken`, and (optionally) `namespacePrefix` for server-side usage.
|
|
72
|
+
- `keyPrefix`/`namespacePrefix`: Useful for isolating environments (e.g., dev/test/prod).
|
|
73
|
+
|
|
74
|
+
## Features
|
|
75
|
+
|
|
76
|
+
### Storage Features
|
|
77
|
+
|
|
78
|
+
- Thread and message storage with JSON support
|
|
79
|
+
- Rich metadata support (JSON-encoded)
|
|
80
|
+
- Timestamp tracking for all records
|
|
81
|
+
- Workflow snapshot persistence
|
|
82
|
+
- Trace and evaluation storage
|
|
83
|
+
- Sorted message order using simulated sorted sets
|
|
84
|
+
- Supports both Cloudflare Workers KV Bindings and REST API
|
|
85
|
+
- Automatic JSON serialization/deserialization for metadata and custom fields
|
|
86
|
+
- Error handling and logging for all operations
|
|
87
|
+
|
|
88
|
+
### Consistency & Performance
|
|
89
|
+
|
|
90
|
+
- Eventually consistent (see Limitations)
|
|
91
|
+
- Low-latency access via Workers Binding API
|
|
92
|
+
- Scalable and serverless
|
|
93
|
+
|
|
94
|
+
## Supported Methods
|
|
95
|
+
|
|
96
|
+
### Thread Operations
|
|
97
|
+
|
|
98
|
+
- `saveThread(thread)`: Create or update a thread
|
|
99
|
+
- `getThreadById({ threadId })`: Get a thread by ID
|
|
100
|
+
- `getThreadsByResourceId({ resourceId })`: Fetch all threads associated with a resource.
|
|
101
|
+
- `updateThread({ id, title, metadata })`: Update thread title and metadata
|
|
102
|
+
- `deleteThread({ threadId })`: Delete a thread and its messages
|
|
103
|
+
|
|
104
|
+
### Message Operations
|
|
105
|
+
|
|
106
|
+
- `saveMessages({ messages })`: Save multiple messages
|
|
107
|
+
- `getMessages({ threadId, selectBy? })`: Get messages for a thread with optional filtering (last N, includes, etc)
|
|
108
|
+
|
|
109
|
+
### Workflow Operations
|
|
110
|
+
|
|
111
|
+
- `persistWorkflowSnapshot({ workflowName, runId, snapshot })`: Save workflow state for a given workflow/run.
|
|
112
|
+
- `loadWorkflowSnapshot({ workflowName, runId })`: Load ed workflow state.
|
|
113
|
+
|
|
114
|
+
### Trace Operations
|
|
115
|
+
|
|
116
|
+
- `getTraces({ name?, scope?, page, perPage, attributes? })`: Query trace records with optional filters and pagination.
|
|
117
|
+
|
|
118
|
+
### Utility
|
|
119
|
+
|
|
120
|
+
- `clearTable({ tableName })`: Remove all records from a logical table
|
|
121
|
+
- `batchInsert({ tableName, records })`: Batch insert multiple records.
|
|
122
|
+
- `insert({ tableName, record })`: Insert a single record into a table.
|
|
123
|
+
|
|
124
|
+
## Data Types
|
|
125
|
+
|
|
126
|
+
- `text`: String
|
|
127
|
+
- `timestamp`: ISO8601 string (converted to/from Date)
|
|
128
|
+
- `uuid`: String
|
|
129
|
+
- `jsonb`: JSON-encoded object
|
|
130
|
+
|
|
131
|
+
All records are stored as JSON in KV, with automatic serialization/deserialization for metadata, arrays, and custom fields.
|
|
132
|
+
|
|
133
|
+
## Configuration Reference
|
|
134
|
+
|
|
135
|
+
- **Workers Binding API**: Use the `bindings` option to pass KV namespaces directly (for Cloudflare Workers).
|
|
136
|
+
- **REST API**: Use `accountId`, `apiToken`, and (optionally) `namespacePrefix` for server-side usage.
|
|
137
|
+
- `keyPrefix`/`namespacePrefix`: Useful for isolating environments (e.g., dev/test/prod).
|
|
138
|
+
|
|
139
|
+
Example:
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
const store = new CloudflareStore({
|
|
143
|
+
bindings: { ... }, // for Workers
|
|
144
|
+
keyPrefix: 'dev_',
|
|
145
|
+
});
|
|
146
|
+
// or
|
|
147
|
+
const store = new CloudflareStore({
|
|
148
|
+
accountId: '...',
|
|
149
|
+
apiToken: '...',
|
|
150
|
+
namespacePrefix: 'prod_',
|
|
151
|
+
});
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Table/Namespace Mapping
|
|
155
|
+
|
|
156
|
+
Each logical Mastra table (threads, messages, workflow_snapshot, evals, traces) maps to a separate KV namespace. Keys are structured as `${prefix}${tableName}:${primaryKey}` or `${prefix}${tableName}:${threadId}:${messageId}` for messages. The prefix is set by `keyPrefix`/`namespacePrefix`.
|
|
157
|
+
|
|
158
|
+
## Limitations
|
|
159
|
+
|
|
160
|
+
- **Eventual Consistency:** Cloudflare KV is eventually consistent; concurrent operations may not be immediately visible across all reads.
|
|
161
|
+
- **No Transactions:** Atomic multi-key operations are not supported.
|
|
162
|
+
- **Rate Limits:** Large objects or high-frequency updates may be subject to Cloudflare KV rate limits.
|
|
163
|
+
- **Query Limitations:** No native querying; all filtering is done in-memory after fetching keys/records.
|
|
164
|
+
- **Best for:** Use for serverless, low-latency, and moderate-volume workloads. For relational or strongly consistent needs, consider D1 or a SQL backend.
|
|
165
|
+
|
|
166
|
+
## Cloudflare-Specific Notes
|
|
167
|
+
|
|
168
|
+
- **Workers Binding API** is recommended for production Workers deployments (low-latency, no API token required at runtime).
|
|
169
|
+
- **REST API** is ideal for server-side Node.js or test environments.
|
|
170
|
+
- Ensure your KV namespaces are provisioned and accessible by your Worker or API token.
|
|
171
|
+
- Namespaces and keys are automatically created as needed.
|
|
172
|
+
|
|
173
|
+
## Cleanup/Disconnect
|
|
174
|
+
|
|
175
|
+
No explicit cleanup or disconnect is required; Cloudflare KV is fully managed.
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import type { EvalRow } from '@mastra/core/storage';
|
|
2
|
+
import type { KVNamespace as KVNamespace_2 } from '@cloudflare/workers-types';
|
|
3
|
+
import { KVNamespaceListKey as KVNamespaceListKey_2 } from '@cloudflare/workers-types';
|
|
4
|
+
import { MastraStorage } from '@mastra/core/storage';
|
|
5
|
+
import type { MessageType } from '@mastra/core/memory';
|
|
6
|
+
import type { MessageType as MessageType_2 } from '@mastra/core';
|
|
7
|
+
import type { StorageColumn } from '@mastra/core/storage';
|
|
8
|
+
import type { StorageGetMessagesArg } from '@mastra/core/storage';
|
|
9
|
+
import type { StorageThreadType } from '@mastra/core/memory';
|
|
10
|
+
import type { TABLE_EVALS } from '@mastra/core/storage';
|
|
11
|
+
import type { TABLE_MESSAGES } from '@mastra/core/storage';
|
|
12
|
+
import type { TABLE_NAMES } from '@mastra/core/storage';
|
|
13
|
+
import type { TABLE_THREADS } from '@mastra/core/storage';
|
|
14
|
+
import type { TABLE_TRACES } from '@mastra/core/storage';
|
|
15
|
+
import type { TABLE_WORKFLOW_SNAPSHOT } from '@mastra/core/storage';
|
|
16
|
+
import type { WorkflowRuns } from '@mastra/core/storage';
|
|
17
|
+
import type { WorkflowRunState } from '@mastra/core/workflows';
|
|
18
|
+
import type { WorkflowRunState as WorkflowRunState_2 } from '@mastra/core';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Configuration for Cloudflare KV using REST API
|
|
22
|
+
*/
|
|
23
|
+
export declare interface CloudflareRestConfig {
|
|
24
|
+
/** Cloudflare account ID */
|
|
25
|
+
accountId: string;
|
|
26
|
+
/** Cloudflare API token with KV access */
|
|
27
|
+
apiToken: string;
|
|
28
|
+
/**
|
|
29
|
+
* Prefix for KV namespace names.
|
|
30
|
+
* Recommended for production use to ensure data isolation between different instances.
|
|
31
|
+
* If not provided, no prefix will be used
|
|
32
|
+
*/
|
|
33
|
+
namespacePrefix?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
declare class CloudflareStore extends MastraStorage {
|
|
37
|
+
private client?;
|
|
38
|
+
private accountId?;
|
|
39
|
+
private namespacePrefix;
|
|
40
|
+
private bindings?;
|
|
41
|
+
private validateWorkersConfig;
|
|
42
|
+
private validateRestConfig;
|
|
43
|
+
constructor(config: CloudflareStoreConfig);
|
|
44
|
+
private getBinding;
|
|
45
|
+
private listNamespaces;
|
|
46
|
+
private getNamespaceValue;
|
|
47
|
+
private putNamespaceValue;
|
|
48
|
+
private deleteNamespaceValue;
|
|
49
|
+
listNamespaceKeys(tableName: TABLE_NAMES, options?: {
|
|
50
|
+
limit?: number;
|
|
51
|
+
prefix?: string;
|
|
52
|
+
}): Promise<KVNamespaceListKey_2<unknown, string>[]>;
|
|
53
|
+
private createNamespaceById;
|
|
54
|
+
private getNamespaceIdByName;
|
|
55
|
+
private createNamespace;
|
|
56
|
+
private getOrCreateNamespaceId;
|
|
57
|
+
private getNamespaceId;
|
|
58
|
+
/**
|
|
59
|
+
* Helper to safely serialize data for KV storage
|
|
60
|
+
*/
|
|
61
|
+
private safeSerialize;
|
|
62
|
+
/**
|
|
63
|
+
* Helper to safely parse data from KV storage
|
|
64
|
+
*/
|
|
65
|
+
private safeParse;
|
|
66
|
+
private putKV;
|
|
67
|
+
private getKV;
|
|
68
|
+
private deleteKV;
|
|
69
|
+
private listKV;
|
|
70
|
+
private getSortedMessages;
|
|
71
|
+
private updateSorting;
|
|
72
|
+
private getIncludedMessagesWithContext;
|
|
73
|
+
private getRecentMessages;
|
|
74
|
+
private fetchAndParseMessages;
|
|
75
|
+
/**
|
|
76
|
+
* Queue for serializing sorted order updates.
|
|
77
|
+
* Updates the sorted order for a given key. This operation is eventually consistent.
|
|
78
|
+
*/
|
|
79
|
+
private updateQueue;
|
|
80
|
+
/**
|
|
81
|
+
* Updates the sorted order for a given key. This operation is eventually consistent.
|
|
82
|
+
* Note: Operations on the same orderKey are serialized using a queue to prevent
|
|
83
|
+
* concurrent updates from conflicting with each other.
|
|
84
|
+
*/
|
|
85
|
+
private updateSortedMessages;
|
|
86
|
+
private getRank;
|
|
87
|
+
private getRange;
|
|
88
|
+
private getLastN;
|
|
89
|
+
private getFullOrder;
|
|
90
|
+
private getKey;
|
|
91
|
+
private getSchemaKey;
|
|
92
|
+
private getTableSchema;
|
|
93
|
+
private validateColumnValue;
|
|
94
|
+
private validateAgainstSchema;
|
|
95
|
+
private validateRecord;
|
|
96
|
+
private ensureDate;
|
|
97
|
+
private serializeDate;
|
|
98
|
+
private ensureMetadata;
|
|
99
|
+
createTable({ tableName, schema, }: {
|
|
100
|
+
tableName: TABLE_NAMES;
|
|
101
|
+
schema: Record<string, StorageColumn>;
|
|
102
|
+
}): Promise<void>;
|
|
103
|
+
clearTable({ tableName }: {
|
|
104
|
+
tableName: TABLE_NAMES;
|
|
105
|
+
}): Promise<void>;
|
|
106
|
+
insert<T extends TABLE_NAMES>({ tableName, record }: {
|
|
107
|
+
tableName: T;
|
|
108
|
+
record: RecordTypes[T];
|
|
109
|
+
}): Promise<void>;
|
|
110
|
+
load<R>({ tableName, keys }: {
|
|
111
|
+
tableName: TABLE_NAMES;
|
|
112
|
+
keys: Record<string, string>;
|
|
113
|
+
}): Promise<R | null>;
|
|
114
|
+
getThreadById({ threadId }: {
|
|
115
|
+
threadId: string;
|
|
116
|
+
}): Promise<StorageThreadType | null>;
|
|
117
|
+
getThreadsByResourceId({ resourceId }: {
|
|
118
|
+
resourceId: string;
|
|
119
|
+
}): Promise<StorageThreadType[]>;
|
|
120
|
+
saveThread({ thread }: {
|
|
121
|
+
thread: StorageThreadType;
|
|
122
|
+
}): Promise<StorageThreadType>;
|
|
123
|
+
updateThread({ id, title, metadata, }: {
|
|
124
|
+
id: string;
|
|
125
|
+
title: string;
|
|
126
|
+
metadata: Record<string, unknown>;
|
|
127
|
+
}): Promise<StorageThreadType>;
|
|
128
|
+
deleteThread({ threadId }: {
|
|
129
|
+
threadId: string;
|
|
130
|
+
}): Promise<void>;
|
|
131
|
+
private getMessageKey;
|
|
132
|
+
private getThreadMessagesKey;
|
|
133
|
+
saveMessages({ messages }: {
|
|
134
|
+
messages: MessageType[];
|
|
135
|
+
}): Promise<MessageType[]>;
|
|
136
|
+
getMessages<T extends MessageType = MessageType>({ threadId, selectBy }: StorageGetMessagesArg): Promise<T[]>;
|
|
137
|
+
private validateWorkflowParams;
|
|
138
|
+
private validateWorkflowState;
|
|
139
|
+
private normalizeSteps;
|
|
140
|
+
private normalizeWorkflowState;
|
|
141
|
+
persistWorkflowSnapshot(params: {
|
|
142
|
+
namespace: string;
|
|
143
|
+
workflowName: string;
|
|
144
|
+
runId: string;
|
|
145
|
+
snapshot: WorkflowRunState;
|
|
146
|
+
}): Promise<void>;
|
|
147
|
+
loadWorkflowSnapshot(params: {
|
|
148
|
+
namespace: string;
|
|
149
|
+
workflowName: string;
|
|
150
|
+
runId: string;
|
|
151
|
+
}): Promise<WorkflowRunState | null>;
|
|
152
|
+
batchInsert<T extends TABLE_NAMES>(input: {
|
|
153
|
+
tableName: T;
|
|
154
|
+
records: Partial<RecordTypes[T]>[];
|
|
155
|
+
}): Promise<void>;
|
|
156
|
+
getTraces({ name, scope, page, perPage, attributes, }: {
|
|
157
|
+
name?: string;
|
|
158
|
+
scope?: string;
|
|
159
|
+
page: number;
|
|
160
|
+
perPage: number;
|
|
161
|
+
attributes?: Record<string, string>;
|
|
162
|
+
}): Promise<any[]>;
|
|
163
|
+
private parseJSON;
|
|
164
|
+
getEvalsByAgentName(_agentName: string, _type?: 'test' | 'live'): Promise<EvalRow[]>;
|
|
165
|
+
getWorkflowRuns(_args?: {
|
|
166
|
+
namespace?: string;
|
|
167
|
+
workflowName?: string;
|
|
168
|
+
fromDate?: Date;
|
|
169
|
+
toDate?: Date;
|
|
170
|
+
limit?: number;
|
|
171
|
+
offset?: number;
|
|
172
|
+
}): Promise<WorkflowRuns>;
|
|
173
|
+
close(): Promise<void>;
|
|
174
|
+
}
|
|
175
|
+
export { CloudflareStore }
|
|
176
|
+
export { CloudflareStore as CloudflareStore_alias_1 }
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Combined configuration type supporting both REST API and Workers Binding API
|
|
180
|
+
*/
|
|
181
|
+
export declare type CloudflareStoreConfig = CloudflareRestConfig | CloudflareWorkersConfig;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Configuration for Cloudflare KV using Workers Binding API
|
|
185
|
+
*/
|
|
186
|
+
export declare interface CloudflareWorkersConfig {
|
|
187
|
+
/** KV namespace bindings from Workers environment */
|
|
188
|
+
bindings: {
|
|
189
|
+
[key in TABLE_NAMES]: KVNamespace_2;
|
|
190
|
+
};
|
|
191
|
+
/** Optional prefix for keys within namespaces */
|
|
192
|
+
keyPrefix?: string;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export declare const createSampleMessage: (threadId: string) => MessageType_2;
|
|
196
|
+
|
|
197
|
+
export declare const createSampleThread: () => {
|
|
198
|
+
id: string;
|
|
199
|
+
resourceId: string;
|
|
200
|
+
title: string;
|
|
201
|
+
createdAt: Date;
|
|
202
|
+
updatedAt: Date;
|
|
203
|
+
metadata: {
|
|
204
|
+
key: string;
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
export declare const createSampleTrace: (name: string, scope?: string, attributes?: Record<string, string>) => {
|
|
209
|
+
id: string;
|
|
210
|
+
parentSpanId: string;
|
|
211
|
+
traceId: string;
|
|
212
|
+
name: string;
|
|
213
|
+
scope: string | undefined;
|
|
214
|
+
kind: string;
|
|
215
|
+
status: string;
|
|
216
|
+
events: string;
|
|
217
|
+
links: string;
|
|
218
|
+
attributes: string | undefined;
|
|
219
|
+
startTime: string;
|
|
220
|
+
endTime: string;
|
|
221
|
+
other: string;
|
|
222
|
+
createdAt: string;
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
export declare const createSampleWorkflowSnapshot: (threadId: string) => WorkflowRunState_2;
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Helper to determine if a config is using Workers bindings
|
|
229
|
+
*/
|
|
230
|
+
export declare function isWorkersConfig(config: CloudflareStoreConfig): config is CloudflareWorkersConfig;
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Interface for KV operations with type support
|
|
234
|
+
*/
|
|
235
|
+
export declare interface KVOperation {
|
|
236
|
+
/** Table/namespace to operate on */
|
|
237
|
+
tableName: TABLE_NAMES;
|
|
238
|
+
/** Key to read/write */
|
|
239
|
+
key: string;
|
|
240
|
+
/** Value to write (for put operations) */
|
|
241
|
+
value?: any;
|
|
242
|
+
/** Optional metadata to associate with the value */
|
|
243
|
+
metadata?: any;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export declare type RecordTypes = {
|
|
247
|
+
[TABLE_THREADS]: StorageThreadType;
|
|
248
|
+
[TABLE_MESSAGES]: MessageType;
|
|
249
|
+
[TABLE_WORKFLOW_SNAPSHOT]: WorkflowRunState;
|
|
250
|
+
[TABLE_EVALS]: EvalRow;
|
|
251
|
+
[TABLE_TRACES]: any;
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
export declare const retryUntil: <T>(fn: () => Promise<T>, condition: (result: T) => boolean, timeout?: number, // REST API needs longer timeout due to higher latency
|
|
255
|
+
interval?: number) => Promise<T>;
|
|
256
|
+
|
|
257
|
+
export { }
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import type { EvalRow } from '@mastra/core/storage';
|
|
2
|
+
import type { KVNamespace as KVNamespace_2 } from '@cloudflare/workers-types';
|
|
3
|
+
import { KVNamespaceListKey as KVNamespaceListKey_2 } from '@cloudflare/workers-types';
|
|
4
|
+
import { MastraStorage } from '@mastra/core/storage';
|
|
5
|
+
import type { MessageType } from '@mastra/core/memory';
|
|
6
|
+
import type { MessageType as MessageType_2 } from '@mastra/core';
|
|
7
|
+
import type { StorageColumn } from '@mastra/core/storage';
|
|
8
|
+
import type { StorageGetMessagesArg } from '@mastra/core/storage';
|
|
9
|
+
import type { StorageThreadType } from '@mastra/core/memory';
|
|
10
|
+
import type { TABLE_EVALS } from '@mastra/core/storage';
|
|
11
|
+
import type { TABLE_MESSAGES } from '@mastra/core/storage';
|
|
12
|
+
import type { TABLE_NAMES } from '@mastra/core/storage';
|
|
13
|
+
import type { TABLE_THREADS } from '@mastra/core/storage';
|
|
14
|
+
import type { TABLE_TRACES } from '@mastra/core/storage';
|
|
15
|
+
import type { TABLE_WORKFLOW_SNAPSHOT } from '@mastra/core/storage';
|
|
16
|
+
import type { WorkflowRuns } from '@mastra/core/storage';
|
|
17
|
+
import type { WorkflowRunState } from '@mastra/core/workflows';
|
|
18
|
+
import type { WorkflowRunState as WorkflowRunState_2 } from '@mastra/core';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Configuration for Cloudflare KV using REST API
|
|
22
|
+
*/
|
|
23
|
+
export declare interface CloudflareRestConfig {
|
|
24
|
+
/** Cloudflare account ID */
|
|
25
|
+
accountId: string;
|
|
26
|
+
/** Cloudflare API token with KV access */
|
|
27
|
+
apiToken: string;
|
|
28
|
+
/**
|
|
29
|
+
* Prefix for KV namespace names.
|
|
30
|
+
* Recommended for production use to ensure data isolation between different instances.
|
|
31
|
+
* If not provided, no prefix will be used
|
|
32
|
+
*/
|
|
33
|
+
namespacePrefix?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
declare class CloudflareStore extends MastraStorage {
|
|
37
|
+
private client?;
|
|
38
|
+
private accountId?;
|
|
39
|
+
private namespacePrefix;
|
|
40
|
+
private bindings?;
|
|
41
|
+
private validateWorkersConfig;
|
|
42
|
+
private validateRestConfig;
|
|
43
|
+
constructor(config: CloudflareStoreConfig);
|
|
44
|
+
private getBinding;
|
|
45
|
+
private listNamespaces;
|
|
46
|
+
private getNamespaceValue;
|
|
47
|
+
private putNamespaceValue;
|
|
48
|
+
private deleteNamespaceValue;
|
|
49
|
+
listNamespaceKeys(tableName: TABLE_NAMES, options?: {
|
|
50
|
+
limit?: number;
|
|
51
|
+
prefix?: string;
|
|
52
|
+
}): Promise<KVNamespaceListKey_2<unknown, string>[]>;
|
|
53
|
+
private createNamespaceById;
|
|
54
|
+
private getNamespaceIdByName;
|
|
55
|
+
private createNamespace;
|
|
56
|
+
private getOrCreateNamespaceId;
|
|
57
|
+
private getNamespaceId;
|
|
58
|
+
/**
|
|
59
|
+
* Helper to safely serialize data for KV storage
|
|
60
|
+
*/
|
|
61
|
+
private safeSerialize;
|
|
62
|
+
/**
|
|
63
|
+
* Helper to safely parse data from KV storage
|
|
64
|
+
*/
|
|
65
|
+
private safeParse;
|
|
66
|
+
private putKV;
|
|
67
|
+
private getKV;
|
|
68
|
+
private deleteKV;
|
|
69
|
+
private listKV;
|
|
70
|
+
private getSortedMessages;
|
|
71
|
+
private updateSorting;
|
|
72
|
+
private getIncludedMessagesWithContext;
|
|
73
|
+
private getRecentMessages;
|
|
74
|
+
private fetchAndParseMessages;
|
|
75
|
+
/**
|
|
76
|
+
* Queue for serializing sorted order updates.
|
|
77
|
+
* Updates the sorted order for a given key. This operation is eventually consistent.
|
|
78
|
+
*/
|
|
79
|
+
private updateQueue;
|
|
80
|
+
/**
|
|
81
|
+
* Updates the sorted order for a given key. This operation is eventually consistent.
|
|
82
|
+
* Note: Operations on the same orderKey are serialized using a queue to prevent
|
|
83
|
+
* concurrent updates from conflicting with each other.
|
|
84
|
+
*/
|
|
85
|
+
private updateSortedMessages;
|
|
86
|
+
private getRank;
|
|
87
|
+
private getRange;
|
|
88
|
+
private getLastN;
|
|
89
|
+
private getFullOrder;
|
|
90
|
+
private getKey;
|
|
91
|
+
private getSchemaKey;
|
|
92
|
+
private getTableSchema;
|
|
93
|
+
private validateColumnValue;
|
|
94
|
+
private validateAgainstSchema;
|
|
95
|
+
private validateRecord;
|
|
96
|
+
private ensureDate;
|
|
97
|
+
private serializeDate;
|
|
98
|
+
private ensureMetadata;
|
|
99
|
+
createTable({ tableName, schema, }: {
|
|
100
|
+
tableName: TABLE_NAMES;
|
|
101
|
+
schema: Record<string, StorageColumn>;
|
|
102
|
+
}): Promise<void>;
|
|
103
|
+
clearTable({ tableName }: {
|
|
104
|
+
tableName: TABLE_NAMES;
|
|
105
|
+
}): Promise<void>;
|
|
106
|
+
insert<T extends TABLE_NAMES>({ tableName, record }: {
|
|
107
|
+
tableName: T;
|
|
108
|
+
record: RecordTypes[T];
|
|
109
|
+
}): Promise<void>;
|
|
110
|
+
load<R>({ tableName, keys }: {
|
|
111
|
+
tableName: TABLE_NAMES;
|
|
112
|
+
keys: Record<string, string>;
|
|
113
|
+
}): Promise<R | null>;
|
|
114
|
+
getThreadById({ threadId }: {
|
|
115
|
+
threadId: string;
|
|
116
|
+
}): Promise<StorageThreadType | null>;
|
|
117
|
+
getThreadsByResourceId({ resourceId }: {
|
|
118
|
+
resourceId: string;
|
|
119
|
+
}): Promise<StorageThreadType[]>;
|
|
120
|
+
saveThread({ thread }: {
|
|
121
|
+
thread: StorageThreadType;
|
|
122
|
+
}): Promise<StorageThreadType>;
|
|
123
|
+
updateThread({ id, title, metadata, }: {
|
|
124
|
+
id: string;
|
|
125
|
+
title: string;
|
|
126
|
+
metadata: Record<string, unknown>;
|
|
127
|
+
}): Promise<StorageThreadType>;
|
|
128
|
+
deleteThread({ threadId }: {
|
|
129
|
+
threadId: string;
|
|
130
|
+
}): Promise<void>;
|
|
131
|
+
private getMessageKey;
|
|
132
|
+
private getThreadMessagesKey;
|
|
133
|
+
saveMessages({ messages }: {
|
|
134
|
+
messages: MessageType[];
|
|
135
|
+
}): Promise<MessageType[]>;
|
|
136
|
+
getMessages<T extends MessageType = MessageType>({ threadId, selectBy }: StorageGetMessagesArg): Promise<T[]>;
|
|
137
|
+
private validateWorkflowParams;
|
|
138
|
+
private validateWorkflowState;
|
|
139
|
+
private normalizeSteps;
|
|
140
|
+
private normalizeWorkflowState;
|
|
141
|
+
persistWorkflowSnapshot(params: {
|
|
142
|
+
namespace: string;
|
|
143
|
+
workflowName: string;
|
|
144
|
+
runId: string;
|
|
145
|
+
snapshot: WorkflowRunState;
|
|
146
|
+
}): Promise<void>;
|
|
147
|
+
loadWorkflowSnapshot(params: {
|
|
148
|
+
namespace: string;
|
|
149
|
+
workflowName: string;
|
|
150
|
+
runId: string;
|
|
151
|
+
}): Promise<WorkflowRunState | null>;
|
|
152
|
+
batchInsert<T extends TABLE_NAMES>(input: {
|
|
153
|
+
tableName: T;
|
|
154
|
+
records: Partial<RecordTypes[T]>[];
|
|
155
|
+
}): Promise<void>;
|
|
156
|
+
getTraces({ name, scope, page, perPage, attributes, }: {
|
|
157
|
+
name?: string;
|
|
158
|
+
scope?: string;
|
|
159
|
+
page: number;
|
|
160
|
+
perPage: number;
|
|
161
|
+
attributes?: Record<string, string>;
|
|
162
|
+
}): Promise<any[]>;
|
|
163
|
+
private parseJSON;
|
|
164
|
+
getEvalsByAgentName(_agentName: string, _type?: 'test' | 'live'): Promise<EvalRow[]>;
|
|
165
|
+
getWorkflowRuns(_args?: {
|
|
166
|
+
namespace?: string;
|
|
167
|
+
workflowName?: string;
|
|
168
|
+
fromDate?: Date;
|
|
169
|
+
toDate?: Date;
|
|
170
|
+
limit?: number;
|
|
171
|
+
offset?: number;
|
|
172
|
+
}): Promise<WorkflowRuns>;
|
|
173
|
+
close(): Promise<void>;
|
|
174
|
+
}
|
|
175
|
+
export { CloudflareStore }
|
|
176
|
+
export { CloudflareStore as CloudflareStore_alias_1 }
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Combined configuration type supporting both REST API and Workers Binding API
|
|
180
|
+
*/
|
|
181
|
+
export declare type CloudflareStoreConfig = CloudflareRestConfig | CloudflareWorkersConfig;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Configuration for Cloudflare KV using Workers Binding API
|
|
185
|
+
*/
|
|
186
|
+
export declare interface CloudflareWorkersConfig {
|
|
187
|
+
/** KV namespace bindings from Workers environment */
|
|
188
|
+
bindings: {
|
|
189
|
+
[key in TABLE_NAMES]: KVNamespace_2;
|
|
190
|
+
};
|
|
191
|
+
/** Optional prefix for keys within namespaces */
|
|
192
|
+
keyPrefix?: string;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export declare const createSampleMessage: (threadId: string) => MessageType_2;
|
|
196
|
+
|
|
197
|
+
export declare const createSampleThread: () => {
|
|
198
|
+
id: string;
|
|
199
|
+
resourceId: string;
|
|
200
|
+
title: string;
|
|
201
|
+
createdAt: Date;
|
|
202
|
+
updatedAt: Date;
|
|
203
|
+
metadata: {
|
|
204
|
+
key: string;
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
export declare const createSampleTrace: (name: string, scope?: string, attributes?: Record<string, string>) => {
|
|
209
|
+
id: string;
|
|
210
|
+
parentSpanId: string;
|
|
211
|
+
traceId: string;
|
|
212
|
+
name: string;
|
|
213
|
+
scope: string | undefined;
|
|
214
|
+
kind: string;
|
|
215
|
+
status: string;
|
|
216
|
+
events: string;
|
|
217
|
+
links: string;
|
|
218
|
+
attributes: string | undefined;
|
|
219
|
+
startTime: string;
|
|
220
|
+
endTime: string;
|
|
221
|
+
other: string;
|
|
222
|
+
createdAt: string;
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
export declare const createSampleWorkflowSnapshot: (threadId: string) => WorkflowRunState_2;
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Helper to determine if a config is using Workers bindings
|
|
229
|
+
*/
|
|
230
|
+
export declare function isWorkersConfig(config: CloudflareStoreConfig): config is CloudflareWorkersConfig;
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Interface for KV operations with type support
|
|
234
|
+
*/
|
|
235
|
+
export declare interface KVOperation {
|
|
236
|
+
/** Table/namespace to operate on */
|
|
237
|
+
tableName: TABLE_NAMES;
|
|
238
|
+
/** Key to read/write */
|
|
239
|
+
key: string;
|
|
240
|
+
/** Value to write (for put operations) */
|
|
241
|
+
value?: any;
|
|
242
|
+
/** Optional metadata to associate with the value */
|
|
243
|
+
metadata?: any;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export declare type RecordTypes = {
|
|
247
|
+
[TABLE_THREADS]: StorageThreadType;
|
|
248
|
+
[TABLE_MESSAGES]: MessageType;
|
|
249
|
+
[TABLE_WORKFLOW_SNAPSHOT]: WorkflowRunState;
|
|
250
|
+
[TABLE_EVALS]: EvalRow;
|
|
251
|
+
[TABLE_TRACES]: any;
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
export declare const retryUntil: <T>(fn: () => Promise<T>, condition: (result: T) => boolean, timeout?: number, // REST API needs longer timeout due to higher latency
|
|
255
|
+
interval?: number) => Promise<T>;
|
|
256
|
+
|
|
257
|
+
export { }
|