@witqq/agent-sdk 0.6.1 → 0.8.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/README.md +539 -6
- package/dist/{types-BvwNzZCj.d.cts → agent-CW9XbmG_.d.ts} +148 -95
- package/dist/{types-BvwNzZCj.d.ts → agent-DxY68NZL.d.cts} +148 -95
- package/dist/auth/index.cjs +260 -2
- package/dist/auth/index.cjs.map +1 -1
- package/dist/auth/index.d.cts +21 -138
- package/dist/auth/index.d.ts +21 -138
- package/dist/auth/index.js +260 -3
- package/dist/auth/index.js.map +1 -1
- package/dist/backends/claude.cjs +653 -140
- package/dist/backends/claude.cjs.map +1 -1
- package/dist/backends/claude.d.cts +4 -1
- package/dist/backends/claude.d.ts +4 -1
- package/dist/backends/claude.js +653 -140
- package/dist/backends/claude.js.map +1 -1
- package/dist/backends/copilot.cjs +428 -88
- package/dist/backends/copilot.cjs.map +1 -1
- package/dist/backends/copilot.d.cts +13 -4
- package/dist/backends/copilot.d.ts +13 -4
- package/dist/backends/copilot.js +428 -88
- package/dist/backends/copilot.js.map +1 -1
- package/dist/backends/vercel-ai.cjs +349 -77
- package/dist/backends/vercel-ai.cjs.map +1 -1
- package/dist/backends/vercel-ai.d.cts +3 -1
- package/dist/backends/vercel-ai.d.ts +3 -1
- package/dist/backends/vercel-ai.js +349 -77
- package/dist/backends/vercel-ai.js.map +1 -1
- package/dist/backends-BSrsBYFn.d.cts +39 -0
- package/dist/backends-BSrsBYFn.d.ts +39 -0
- package/dist/chat/accumulator.cjs +147 -0
- package/dist/chat/accumulator.cjs.map +1 -0
- package/dist/chat/accumulator.d.cts +64 -0
- package/dist/chat/accumulator.d.ts +64 -0
- package/dist/chat/accumulator.js +145 -0
- package/dist/chat/accumulator.js.map +1 -0
- package/dist/chat/backends.cjs +3524 -0
- package/dist/chat/backends.cjs.map +1 -0
- package/dist/chat/backends.d.cts +66 -0
- package/dist/chat/backends.d.ts +66 -0
- package/dist/chat/backends.js +3512 -0
- package/dist/chat/backends.js.map +1 -0
- package/dist/chat/context.cjs +280 -0
- package/dist/chat/context.cjs.map +1 -0
- package/dist/chat/context.d.cts +191 -0
- package/dist/chat/context.d.ts +191 -0
- package/dist/chat/context.js +277 -0
- package/dist/chat/context.js.map +1 -0
- package/dist/chat/core.cjs +305 -0
- package/dist/chat/core.cjs.map +1 -0
- package/dist/chat/core.d.cts +84 -0
- package/dist/chat/core.d.ts +84 -0
- package/dist/chat/core.js +282 -0
- package/dist/chat/core.js.map +1 -0
- package/dist/chat/errors.cjs +273 -0
- package/dist/chat/errors.cjs.map +1 -0
- package/dist/chat/errors.d.cts +97 -0
- package/dist/chat/errors.d.ts +97 -0
- package/dist/chat/errors.js +266 -0
- package/dist/chat/errors.js.map +1 -0
- package/dist/chat/events.cjs +203 -0
- package/dist/chat/events.cjs.map +1 -0
- package/dist/chat/events.d.cts +245 -0
- package/dist/chat/events.d.ts +245 -0
- package/dist/chat/events.js +196 -0
- package/dist/chat/events.js.map +1 -0
- package/dist/chat/index.cjs +5550 -0
- package/dist/chat/index.cjs.map +1 -0
- package/dist/chat/index.d.cts +77 -0
- package/dist/chat/index.d.ts +77 -0
- package/dist/chat/index.js +5505 -0
- package/dist/chat/index.js.map +1 -0
- package/dist/chat/react/theme.css +2517 -0
- package/dist/chat/react.cjs +3589 -0
- package/dist/chat/react.cjs.map +1 -0
- package/dist/chat/react.d.cts +1088 -0
- package/dist/chat/react.d.ts +1088 -0
- package/dist/chat/react.js +3547 -0
- package/dist/chat/react.js.map +1 -0
- package/dist/chat/runtime.cjs +1245 -0
- package/dist/chat/runtime.cjs.map +1 -0
- package/dist/chat/runtime.d.cts +182 -0
- package/dist/chat/runtime.d.ts +182 -0
- package/dist/chat/runtime.js +1243 -0
- package/dist/chat/runtime.js.map +1 -0
- package/dist/chat/server.cjs +2668 -0
- package/dist/chat/server.cjs.map +1 -0
- package/dist/chat/server.d.cts +648 -0
- package/dist/chat/server.d.ts +648 -0
- package/dist/chat/server.js +2628 -0
- package/dist/chat/server.js.map +1 -0
- package/dist/chat/sessions.cjs +380 -0
- package/dist/chat/sessions.cjs.map +1 -0
- package/dist/chat/sessions.d.cts +158 -0
- package/dist/chat/sessions.d.ts +158 -0
- package/dist/chat/sessions.js +376 -0
- package/dist/chat/sessions.js.map +1 -0
- package/dist/chat/sqlite.cjs +441 -0
- package/dist/chat/sqlite.cjs.map +1 -0
- package/dist/chat/sqlite.d.cts +128 -0
- package/dist/chat/sqlite.d.ts +128 -0
- package/dist/chat/sqlite.js +435 -0
- package/dist/chat/sqlite.js.map +1 -0
- package/dist/chat/state.cjs +190 -0
- package/dist/chat/state.cjs.map +1 -0
- package/dist/chat/state.d.cts +95 -0
- package/dist/chat/state.d.ts +95 -0
- package/dist/chat/state.js +180 -0
- package/dist/chat/state.js.map +1 -0
- package/dist/chat/storage.cjs +249 -0
- package/dist/chat/storage.cjs.map +1 -0
- package/dist/chat/storage.d.cts +197 -0
- package/dist/chat/storage.d.ts +197 -0
- package/dist/chat/storage.js +245 -0
- package/dist/chat/storage.js.map +1 -0
- package/dist/errors-C-so0M4t.d.cts +33 -0
- package/dist/errors-C-so0M4t.d.ts +33 -0
- package/dist/errors-CmVvczxZ.d.cts +28 -0
- package/dist/errors-CmVvczxZ.d.ts +28 -0
- package/dist/in-process-transport-C1JnJGVR.d.ts +228 -0
- package/dist/in-process-transport-C7DSqPyX.d.cts +228 -0
- package/dist/index.cjs +365 -59
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +322 -125
- package/dist/index.d.ts +322 -125
- package/dist/index.js +359 -60
- package/dist/index.js.map +1 -1
- package/dist/provider-types-PTSlRPNB.d.cts +39 -0
- package/dist/provider-types-PTSlRPNB.d.ts +39 -0
- package/dist/refresh-manager-B81PpYBr.d.cts +153 -0
- package/dist/refresh-manager-Dlv_iNZi.d.ts +153 -0
- package/dist/testing.cjs +383 -0
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.cts +132 -0
- package/dist/testing.d.ts +132 -0
- package/dist/testing.js +377 -0
- package/dist/testing.js.map +1 -0
- package/dist/token-store-CSUBgYwn.d.ts +48 -0
- package/dist/token-store-CuC4hB9Z.d.cts +48 -0
- package/dist/transport-Cdh3M0tS.d.cts +68 -0
- package/dist/transport-Ciap4PWK.d.ts +68 -0
- package/dist/types-4vbcmPTp.d.cts +143 -0
- package/dist/types-BxggH0Yh.d.ts +143 -0
- package/dist/types-DRgd_9R7.d.cts +363 -0
- package/dist/types-ajANVzf7.d.ts +363 -0
- package/package.json +178 -6
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { A as AgentSDKError } from '../errors-CmVvczxZ.cjs';
|
|
2
|
+
import { E as ErrorCode } from '../errors-C-so0M4t.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @witqq/agent-sdk/chat/storage
|
|
6
|
+
*
|
|
7
|
+
* Generic storage adapter layer with pluggable backends.
|
|
8
|
+
* Provides CRUD operations for any data type via `IStorageAdapter<T>`.
|
|
9
|
+
* Implementations: `InMemoryStorage` (Map-based) and `FileStorage` (JSON files).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Error thrown by storage operations.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* try {
|
|
18
|
+
* await store.get("missing-id");
|
|
19
|
+
* } catch (e) {
|
|
20
|
+
* if (e instanceof StorageError && e.code === ErrorCode.STORAGE_NOT_FOUND) {
|
|
21
|
+
* // handle missing item
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
declare class StorageError extends AgentSDKError {
|
|
27
|
+
/** Machine-readable error code from the unified ErrorCode enum */
|
|
28
|
+
readonly code: StorageErrorCode;
|
|
29
|
+
constructor(message: string, code: StorageErrorCode);
|
|
30
|
+
}
|
|
31
|
+
/** Storage-specific subset of ErrorCode */
|
|
32
|
+
type StorageErrorCode = ErrorCode.STORAGE_NOT_FOUND | ErrorCode.STORAGE_DUPLICATE_KEY | ErrorCode.STORAGE_IO_ERROR | ErrorCode.STORAGE_SERIALIZATION_ERROR;
|
|
33
|
+
/**
|
|
34
|
+
* Options for listing stored items.
|
|
35
|
+
*
|
|
36
|
+
* @typeParam T - The type of stored items
|
|
37
|
+
*/
|
|
38
|
+
interface ListOptions<T> {
|
|
39
|
+
/** Filter predicate — return `true` to include the item */
|
|
40
|
+
filter?: (item: T) => boolean;
|
|
41
|
+
/** Sort comparator — standard Array.sort semantics */
|
|
42
|
+
sort?: (a: T, b: T) => number;
|
|
43
|
+
/** Maximum number of items to return */
|
|
44
|
+
limit?: number;
|
|
45
|
+
/** Number of items to skip (for pagination) */
|
|
46
|
+
offset?: number;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Generic storage adapter for CRUD operations on any data type.
|
|
50
|
+
* Items are identified by a string key.
|
|
51
|
+
*
|
|
52
|
+
* @typeParam T - The type of stored items
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* const store: IStorageAdapter<{ name: string }> = new InMemoryStorage();
|
|
57
|
+
* await store.create("key1", { name: "Alice" });
|
|
58
|
+
* const item = await store.get("key1"); // { name: "Alice" }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
interface IStorageAdapter<T> {
|
|
62
|
+
/**
|
|
63
|
+
* Retrieve an item by key.
|
|
64
|
+
* @param key - Unique identifier
|
|
65
|
+
* @returns The item, or `null` if not found
|
|
66
|
+
*/
|
|
67
|
+
get(key: string): Promise<T | null>;
|
|
68
|
+
/**
|
|
69
|
+
* List items with optional filtering, sorting, and pagination.
|
|
70
|
+
* @param options - Filter, sort, limit, offset options
|
|
71
|
+
* @returns Array of matching items
|
|
72
|
+
*/
|
|
73
|
+
list(options?: ListOptions<T>): Promise<T[]>;
|
|
74
|
+
/**
|
|
75
|
+
* Create a new item. Throws `StorageError` with code `DUPLICATE_KEY` if key exists.
|
|
76
|
+
* @param key - Unique identifier
|
|
77
|
+
* @param item - Data to store
|
|
78
|
+
*/
|
|
79
|
+
create(key: string, item: T): Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* Update an existing item. Throws `StorageError` with code `NOT_FOUND` if key missing.
|
|
82
|
+
* @param key - Unique identifier
|
|
83
|
+
* @param item - Updated data
|
|
84
|
+
*/
|
|
85
|
+
update(key: string, item: T): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* Delete an item by key. Throws `StorageError` with code `NOT_FOUND` if key missing.
|
|
88
|
+
* @param key - Unique identifier
|
|
89
|
+
*/
|
|
90
|
+
delete(key: string): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Check whether a key exists.
|
|
93
|
+
* @param key - Unique identifier
|
|
94
|
+
* @returns `true` if key exists
|
|
95
|
+
*/
|
|
96
|
+
has(key: string): Promise<boolean>;
|
|
97
|
+
/**
|
|
98
|
+
* Return the number of stored items.
|
|
99
|
+
* @returns Count of items
|
|
100
|
+
*/
|
|
101
|
+
count(): Promise<number>;
|
|
102
|
+
/**
|
|
103
|
+
* Remove all items from storage.
|
|
104
|
+
*/
|
|
105
|
+
clear(): Promise<void>;
|
|
106
|
+
/**
|
|
107
|
+
* Release any resources held by this adapter (DB connections, file handles).
|
|
108
|
+
* Optional — adapters that don't hold resources need not implement this.
|
|
109
|
+
*/
|
|
110
|
+
dispose?(): Promise<void>;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* In-memory storage adapter backed by a `Map`.
|
|
114
|
+
* Suitable for development, testing, and short-lived processes.
|
|
115
|
+
* Data is lost when the process exits.
|
|
116
|
+
*
|
|
117
|
+
* @typeParam T - The type of stored items
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```typescript
|
|
121
|
+
* const store = new InMemoryStorage<{ name: string }>();
|
|
122
|
+
* await store.create("k1", { name: "Alice" });
|
|
123
|
+
* await store.create("k2", { name: "Bob" });
|
|
124
|
+
* const items = await store.list({ filter: i => i.name.startsWith("A") });
|
|
125
|
+
* // [{ name: "Alice" }]
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
declare class InMemoryStorage<T> implements IStorageAdapter<T> {
|
|
129
|
+
private readonly data;
|
|
130
|
+
/** @inheritdoc */
|
|
131
|
+
get(key: string): Promise<T | null>;
|
|
132
|
+
/** @inheritdoc */
|
|
133
|
+
list(options?: ListOptions<T>): Promise<T[]>;
|
|
134
|
+
/** @inheritdoc */
|
|
135
|
+
create(key: string, item: T): Promise<void>;
|
|
136
|
+
/** @inheritdoc */
|
|
137
|
+
update(key: string, item: T): Promise<void>;
|
|
138
|
+
/** @inheritdoc */
|
|
139
|
+
delete(key: string): Promise<void>;
|
|
140
|
+
/** @inheritdoc */
|
|
141
|
+
has(key: string): Promise<boolean>;
|
|
142
|
+
/** @inheritdoc */
|
|
143
|
+
count(): Promise<number>;
|
|
144
|
+
/** @inheritdoc */
|
|
145
|
+
clear(): Promise<void>;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Options for configuring `FileStorage`.
|
|
149
|
+
*/
|
|
150
|
+
interface FileStorageOptions {
|
|
151
|
+
/** Directory path where JSON files are stored */
|
|
152
|
+
directory: string;
|
|
153
|
+
/** File extension (default: `.json`) */
|
|
154
|
+
extension?: string;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* File-based storage adapter that persists each item as a JSON file.
|
|
158
|
+
* Suitable for local applications, CLI tools, and development.
|
|
159
|
+
* Creates the storage directory if it doesn't exist.
|
|
160
|
+
*
|
|
161
|
+
* @typeParam T - The type of stored items (must be JSON-serializable)
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* ```typescript
|
|
165
|
+
* const store = new FileStorage<ChatSession>({
|
|
166
|
+
* directory: "./data/sessions",
|
|
167
|
+
* });
|
|
168
|
+
* await store.create("session-1", mySession);
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
171
|
+
declare class FileStorage<T> implements IStorageAdapter<T> {
|
|
172
|
+
private readonly directory;
|
|
173
|
+
private readonly extension;
|
|
174
|
+
constructor(options: FileStorageOptions);
|
|
175
|
+
/** @inheritdoc */
|
|
176
|
+
get(key: string): Promise<T | null>;
|
|
177
|
+
/** @inheritdoc */
|
|
178
|
+
list(options?: ListOptions<T>): Promise<T[]>;
|
|
179
|
+
/** @inheritdoc */
|
|
180
|
+
create(key: string, item: T): Promise<void>;
|
|
181
|
+
/** @inheritdoc */
|
|
182
|
+
update(key: string, item: T): Promise<void>;
|
|
183
|
+
/** @inheritdoc */
|
|
184
|
+
delete(key: string): Promise<void>;
|
|
185
|
+
/** @inheritdoc */
|
|
186
|
+
has(key: string): Promise<boolean>;
|
|
187
|
+
/** @inheritdoc */
|
|
188
|
+
count(): Promise<number>;
|
|
189
|
+
/** @inheritdoc */
|
|
190
|
+
clear(): Promise<void>;
|
|
191
|
+
private keyToPath;
|
|
192
|
+
private ensureDirectory;
|
|
193
|
+
private readFile;
|
|
194
|
+
private writeFile;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export { FileStorage, type FileStorageOptions, type IStorageAdapter, InMemoryStorage, type ListOptions, StorageError, type StorageErrorCode };
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { A as AgentSDKError } from '../errors-CmVvczxZ.js';
|
|
2
|
+
import { E as ErrorCode } from '../errors-C-so0M4t.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @witqq/agent-sdk/chat/storage
|
|
6
|
+
*
|
|
7
|
+
* Generic storage adapter layer with pluggable backends.
|
|
8
|
+
* Provides CRUD operations for any data type via `IStorageAdapter<T>`.
|
|
9
|
+
* Implementations: `InMemoryStorage` (Map-based) and `FileStorage` (JSON files).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Error thrown by storage operations.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* try {
|
|
18
|
+
* await store.get("missing-id");
|
|
19
|
+
* } catch (e) {
|
|
20
|
+
* if (e instanceof StorageError && e.code === ErrorCode.STORAGE_NOT_FOUND) {
|
|
21
|
+
* // handle missing item
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
declare class StorageError extends AgentSDKError {
|
|
27
|
+
/** Machine-readable error code from the unified ErrorCode enum */
|
|
28
|
+
readonly code: StorageErrorCode;
|
|
29
|
+
constructor(message: string, code: StorageErrorCode);
|
|
30
|
+
}
|
|
31
|
+
/** Storage-specific subset of ErrorCode */
|
|
32
|
+
type StorageErrorCode = ErrorCode.STORAGE_NOT_FOUND | ErrorCode.STORAGE_DUPLICATE_KEY | ErrorCode.STORAGE_IO_ERROR | ErrorCode.STORAGE_SERIALIZATION_ERROR;
|
|
33
|
+
/**
|
|
34
|
+
* Options for listing stored items.
|
|
35
|
+
*
|
|
36
|
+
* @typeParam T - The type of stored items
|
|
37
|
+
*/
|
|
38
|
+
interface ListOptions<T> {
|
|
39
|
+
/** Filter predicate — return `true` to include the item */
|
|
40
|
+
filter?: (item: T) => boolean;
|
|
41
|
+
/** Sort comparator — standard Array.sort semantics */
|
|
42
|
+
sort?: (a: T, b: T) => number;
|
|
43
|
+
/** Maximum number of items to return */
|
|
44
|
+
limit?: number;
|
|
45
|
+
/** Number of items to skip (for pagination) */
|
|
46
|
+
offset?: number;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Generic storage adapter for CRUD operations on any data type.
|
|
50
|
+
* Items are identified by a string key.
|
|
51
|
+
*
|
|
52
|
+
* @typeParam T - The type of stored items
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* const store: IStorageAdapter<{ name: string }> = new InMemoryStorage();
|
|
57
|
+
* await store.create("key1", { name: "Alice" });
|
|
58
|
+
* const item = await store.get("key1"); // { name: "Alice" }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
interface IStorageAdapter<T> {
|
|
62
|
+
/**
|
|
63
|
+
* Retrieve an item by key.
|
|
64
|
+
* @param key - Unique identifier
|
|
65
|
+
* @returns The item, or `null` if not found
|
|
66
|
+
*/
|
|
67
|
+
get(key: string): Promise<T | null>;
|
|
68
|
+
/**
|
|
69
|
+
* List items with optional filtering, sorting, and pagination.
|
|
70
|
+
* @param options - Filter, sort, limit, offset options
|
|
71
|
+
* @returns Array of matching items
|
|
72
|
+
*/
|
|
73
|
+
list(options?: ListOptions<T>): Promise<T[]>;
|
|
74
|
+
/**
|
|
75
|
+
* Create a new item. Throws `StorageError` with code `DUPLICATE_KEY` if key exists.
|
|
76
|
+
* @param key - Unique identifier
|
|
77
|
+
* @param item - Data to store
|
|
78
|
+
*/
|
|
79
|
+
create(key: string, item: T): Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* Update an existing item. Throws `StorageError` with code `NOT_FOUND` if key missing.
|
|
82
|
+
* @param key - Unique identifier
|
|
83
|
+
* @param item - Updated data
|
|
84
|
+
*/
|
|
85
|
+
update(key: string, item: T): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* Delete an item by key. Throws `StorageError` with code `NOT_FOUND` if key missing.
|
|
88
|
+
* @param key - Unique identifier
|
|
89
|
+
*/
|
|
90
|
+
delete(key: string): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Check whether a key exists.
|
|
93
|
+
* @param key - Unique identifier
|
|
94
|
+
* @returns `true` if key exists
|
|
95
|
+
*/
|
|
96
|
+
has(key: string): Promise<boolean>;
|
|
97
|
+
/**
|
|
98
|
+
* Return the number of stored items.
|
|
99
|
+
* @returns Count of items
|
|
100
|
+
*/
|
|
101
|
+
count(): Promise<number>;
|
|
102
|
+
/**
|
|
103
|
+
* Remove all items from storage.
|
|
104
|
+
*/
|
|
105
|
+
clear(): Promise<void>;
|
|
106
|
+
/**
|
|
107
|
+
* Release any resources held by this adapter (DB connections, file handles).
|
|
108
|
+
* Optional — adapters that don't hold resources need not implement this.
|
|
109
|
+
*/
|
|
110
|
+
dispose?(): Promise<void>;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* In-memory storage adapter backed by a `Map`.
|
|
114
|
+
* Suitable for development, testing, and short-lived processes.
|
|
115
|
+
* Data is lost when the process exits.
|
|
116
|
+
*
|
|
117
|
+
* @typeParam T - The type of stored items
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```typescript
|
|
121
|
+
* const store = new InMemoryStorage<{ name: string }>();
|
|
122
|
+
* await store.create("k1", { name: "Alice" });
|
|
123
|
+
* await store.create("k2", { name: "Bob" });
|
|
124
|
+
* const items = await store.list({ filter: i => i.name.startsWith("A") });
|
|
125
|
+
* // [{ name: "Alice" }]
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
declare class InMemoryStorage<T> implements IStorageAdapter<T> {
|
|
129
|
+
private readonly data;
|
|
130
|
+
/** @inheritdoc */
|
|
131
|
+
get(key: string): Promise<T | null>;
|
|
132
|
+
/** @inheritdoc */
|
|
133
|
+
list(options?: ListOptions<T>): Promise<T[]>;
|
|
134
|
+
/** @inheritdoc */
|
|
135
|
+
create(key: string, item: T): Promise<void>;
|
|
136
|
+
/** @inheritdoc */
|
|
137
|
+
update(key: string, item: T): Promise<void>;
|
|
138
|
+
/** @inheritdoc */
|
|
139
|
+
delete(key: string): Promise<void>;
|
|
140
|
+
/** @inheritdoc */
|
|
141
|
+
has(key: string): Promise<boolean>;
|
|
142
|
+
/** @inheritdoc */
|
|
143
|
+
count(): Promise<number>;
|
|
144
|
+
/** @inheritdoc */
|
|
145
|
+
clear(): Promise<void>;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Options for configuring `FileStorage`.
|
|
149
|
+
*/
|
|
150
|
+
interface FileStorageOptions {
|
|
151
|
+
/** Directory path where JSON files are stored */
|
|
152
|
+
directory: string;
|
|
153
|
+
/** File extension (default: `.json`) */
|
|
154
|
+
extension?: string;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* File-based storage adapter that persists each item as a JSON file.
|
|
158
|
+
* Suitable for local applications, CLI tools, and development.
|
|
159
|
+
* Creates the storage directory if it doesn't exist.
|
|
160
|
+
*
|
|
161
|
+
* @typeParam T - The type of stored items (must be JSON-serializable)
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* ```typescript
|
|
165
|
+
* const store = new FileStorage<ChatSession>({
|
|
166
|
+
* directory: "./data/sessions",
|
|
167
|
+
* });
|
|
168
|
+
* await store.create("session-1", mySession);
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
171
|
+
declare class FileStorage<T> implements IStorageAdapter<T> {
|
|
172
|
+
private readonly directory;
|
|
173
|
+
private readonly extension;
|
|
174
|
+
constructor(options: FileStorageOptions);
|
|
175
|
+
/** @inheritdoc */
|
|
176
|
+
get(key: string): Promise<T | null>;
|
|
177
|
+
/** @inheritdoc */
|
|
178
|
+
list(options?: ListOptions<T>): Promise<T[]>;
|
|
179
|
+
/** @inheritdoc */
|
|
180
|
+
create(key: string, item: T): Promise<void>;
|
|
181
|
+
/** @inheritdoc */
|
|
182
|
+
update(key: string, item: T): Promise<void>;
|
|
183
|
+
/** @inheritdoc */
|
|
184
|
+
delete(key: string): Promise<void>;
|
|
185
|
+
/** @inheritdoc */
|
|
186
|
+
has(key: string): Promise<boolean>;
|
|
187
|
+
/** @inheritdoc */
|
|
188
|
+
count(): Promise<number>;
|
|
189
|
+
/** @inheritdoc */
|
|
190
|
+
clear(): Promise<void>;
|
|
191
|
+
private keyToPath;
|
|
192
|
+
private ensureDirectory;
|
|
193
|
+
private readFile;
|
|
194
|
+
private writeFile;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export { FileStorage, type FileStorageOptions, type IStorageAdapter, InMemoryStorage, type ListOptions, StorageError, type StorageErrorCode };
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { existsSync, readdirSync, unlinkSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
|
|
4
|
+
// src/chat/storage.ts
|
|
5
|
+
|
|
6
|
+
// src/errors.ts
|
|
7
|
+
var AgentSDKError = class extends Error {
|
|
8
|
+
/** @internal Marker for cross-bundle identity checks */
|
|
9
|
+
_agentSDKError = true;
|
|
10
|
+
/** Machine-readable error code. Prefer values from the ErrorCode enum. */
|
|
11
|
+
code;
|
|
12
|
+
/** Whether this error is safe to retry */
|
|
13
|
+
retryable;
|
|
14
|
+
/** HTTP status code hint for error classification */
|
|
15
|
+
httpStatus;
|
|
16
|
+
constructor(message, options) {
|
|
17
|
+
super(message, options);
|
|
18
|
+
this.name = "AgentSDKError";
|
|
19
|
+
this.code = options?.code;
|
|
20
|
+
this.retryable = options?.retryable ?? false;
|
|
21
|
+
this.httpStatus = options?.httpStatus;
|
|
22
|
+
}
|
|
23
|
+
/** Check if an error is an AgentSDKError (works across bundled copies) */
|
|
24
|
+
static is(error) {
|
|
25
|
+
return error instanceof Error && "_agentSDKError" in error && error._agentSDKError === true;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// src/chat/storage.ts
|
|
30
|
+
var StorageError = class extends AgentSDKError {
|
|
31
|
+
/** Machine-readable error code from the unified ErrorCode enum */
|
|
32
|
+
code;
|
|
33
|
+
constructor(message, code) {
|
|
34
|
+
super(message);
|
|
35
|
+
this.name = "StorageError";
|
|
36
|
+
this.code = code;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
var InMemoryStorage = class {
|
|
40
|
+
data = /* @__PURE__ */ new Map();
|
|
41
|
+
/** @inheritdoc */
|
|
42
|
+
async get(key) {
|
|
43
|
+
const item = this.data.get(key);
|
|
44
|
+
return item !== void 0 ? structuredClone(item) : null;
|
|
45
|
+
}
|
|
46
|
+
/** @inheritdoc */
|
|
47
|
+
async list(options) {
|
|
48
|
+
let items = Array.from(this.data.values()).map((item) => structuredClone(item));
|
|
49
|
+
if (options?.filter) {
|
|
50
|
+
items = items.filter(options.filter);
|
|
51
|
+
}
|
|
52
|
+
if (options?.sort) {
|
|
53
|
+
items.sort(options.sort);
|
|
54
|
+
}
|
|
55
|
+
if (options?.offset !== void 0) {
|
|
56
|
+
items = items.slice(options.offset);
|
|
57
|
+
}
|
|
58
|
+
if (options?.limit !== void 0) {
|
|
59
|
+
items = items.slice(0, options.limit);
|
|
60
|
+
}
|
|
61
|
+
return items;
|
|
62
|
+
}
|
|
63
|
+
/** @inheritdoc */
|
|
64
|
+
async create(key, item) {
|
|
65
|
+
if (this.data.has(key)) {
|
|
66
|
+
throw new StorageError(
|
|
67
|
+
`Item with key "${key}" already exists`,
|
|
68
|
+
"STORAGE_DUPLICATE_KEY" /* STORAGE_DUPLICATE_KEY */
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
this.data.set(key, structuredClone(item));
|
|
72
|
+
}
|
|
73
|
+
/** @inheritdoc */
|
|
74
|
+
async update(key, item) {
|
|
75
|
+
if (!this.data.has(key)) {
|
|
76
|
+
throw new StorageError(
|
|
77
|
+
`Item with key "${key}" not found`,
|
|
78
|
+
"STORAGE_NOT_FOUND" /* STORAGE_NOT_FOUND */
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
this.data.set(key, structuredClone(item));
|
|
82
|
+
}
|
|
83
|
+
/** @inheritdoc */
|
|
84
|
+
async delete(key) {
|
|
85
|
+
if (!this.data.has(key)) {
|
|
86
|
+
throw new StorageError(
|
|
87
|
+
`Item with key "${key}" not found`,
|
|
88
|
+
"STORAGE_NOT_FOUND" /* STORAGE_NOT_FOUND */
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
this.data.delete(key);
|
|
92
|
+
}
|
|
93
|
+
/** @inheritdoc */
|
|
94
|
+
async has(key) {
|
|
95
|
+
return this.data.has(key);
|
|
96
|
+
}
|
|
97
|
+
/** @inheritdoc */
|
|
98
|
+
async count() {
|
|
99
|
+
return this.data.size;
|
|
100
|
+
}
|
|
101
|
+
/** @inheritdoc */
|
|
102
|
+
async clear() {
|
|
103
|
+
this.data.clear();
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
var FileStorage = class {
|
|
107
|
+
directory;
|
|
108
|
+
extension;
|
|
109
|
+
constructor(options) {
|
|
110
|
+
this.directory = options.directory;
|
|
111
|
+
this.extension = options.extension ?? ".json";
|
|
112
|
+
this.ensureDirectory();
|
|
113
|
+
}
|
|
114
|
+
/** @inheritdoc */
|
|
115
|
+
async get(key) {
|
|
116
|
+
const filePath = this.keyToPath(key);
|
|
117
|
+
if (!existsSync(filePath)) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
return this.readFile(filePath);
|
|
121
|
+
}
|
|
122
|
+
/** @inheritdoc */
|
|
123
|
+
async list(options) {
|
|
124
|
+
this.ensureDirectory();
|
|
125
|
+
const files = readdirSync(this.directory).filter(
|
|
126
|
+
(f) => f.endsWith(this.extension)
|
|
127
|
+
);
|
|
128
|
+
let items = [];
|
|
129
|
+
for (const file of files) {
|
|
130
|
+
const item = this.readFile(join(this.directory, file));
|
|
131
|
+
items.push(item);
|
|
132
|
+
}
|
|
133
|
+
if (options?.filter) {
|
|
134
|
+
items = items.filter(options.filter);
|
|
135
|
+
}
|
|
136
|
+
if (options?.sort) {
|
|
137
|
+
items.sort(options.sort);
|
|
138
|
+
}
|
|
139
|
+
if (options?.offset !== void 0) {
|
|
140
|
+
items = items.slice(options.offset);
|
|
141
|
+
}
|
|
142
|
+
if (options?.limit !== void 0) {
|
|
143
|
+
items = items.slice(0, options.limit);
|
|
144
|
+
}
|
|
145
|
+
return items;
|
|
146
|
+
}
|
|
147
|
+
/** @inheritdoc */
|
|
148
|
+
async create(key, item) {
|
|
149
|
+
const filePath = this.keyToPath(key);
|
|
150
|
+
if (existsSync(filePath)) {
|
|
151
|
+
throw new StorageError(
|
|
152
|
+
`Item with key "${key}" already exists`,
|
|
153
|
+
"STORAGE_DUPLICATE_KEY" /* STORAGE_DUPLICATE_KEY */
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
this.writeFile(filePath, item);
|
|
157
|
+
}
|
|
158
|
+
/** @inheritdoc */
|
|
159
|
+
async update(key, item) {
|
|
160
|
+
const filePath = this.keyToPath(key);
|
|
161
|
+
if (!existsSync(filePath)) {
|
|
162
|
+
throw new StorageError(
|
|
163
|
+
`Item with key "${key}" not found`,
|
|
164
|
+
"STORAGE_NOT_FOUND" /* STORAGE_NOT_FOUND */
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
this.writeFile(filePath, item);
|
|
168
|
+
}
|
|
169
|
+
/** @inheritdoc */
|
|
170
|
+
async delete(key) {
|
|
171
|
+
const filePath = this.keyToPath(key);
|
|
172
|
+
if (!existsSync(filePath)) {
|
|
173
|
+
throw new StorageError(
|
|
174
|
+
`Item with key "${key}" not found`,
|
|
175
|
+
"STORAGE_NOT_FOUND" /* STORAGE_NOT_FOUND */
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
unlinkSync(filePath);
|
|
179
|
+
}
|
|
180
|
+
/** @inheritdoc */
|
|
181
|
+
async has(key) {
|
|
182
|
+
return existsSync(this.keyToPath(key));
|
|
183
|
+
}
|
|
184
|
+
/** @inheritdoc */
|
|
185
|
+
async count() {
|
|
186
|
+
this.ensureDirectory();
|
|
187
|
+
return readdirSync(this.directory).filter(
|
|
188
|
+
(f) => f.endsWith(this.extension)
|
|
189
|
+
).length;
|
|
190
|
+
}
|
|
191
|
+
/** @inheritdoc */
|
|
192
|
+
async clear() {
|
|
193
|
+
this.ensureDirectory();
|
|
194
|
+
const files = readdirSync(this.directory).filter(
|
|
195
|
+
(f) => f.endsWith(this.extension)
|
|
196
|
+
);
|
|
197
|
+
for (const file of files) {
|
|
198
|
+
unlinkSync(join(this.directory, file));
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
keyToPath(key) {
|
|
202
|
+
const safeKey = key.replace(
|
|
203
|
+
/[^a-zA-Z0-9_-]/g,
|
|
204
|
+
(c) => "%" + c.charCodeAt(0).toString(16).padStart(2, "0")
|
|
205
|
+
);
|
|
206
|
+
return join(this.directory, `${safeKey}${this.extension}`);
|
|
207
|
+
}
|
|
208
|
+
ensureDirectory() {
|
|
209
|
+
if (!existsSync(this.directory)) {
|
|
210
|
+
mkdirSync(this.directory, { recursive: true });
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
readFile(filePath) {
|
|
214
|
+
try {
|
|
215
|
+
const content = readFileSync(filePath, "utf-8");
|
|
216
|
+
return JSON.parse(content);
|
|
217
|
+
} catch (error) {
|
|
218
|
+
if (error instanceof SyntaxError) {
|
|
219
|
+
throw new StorageError(
|
|
220
|
+
`Failed to parse file: ${filePath}`,
|
|
221
|
+
"STORAGE_SERIALIZATION_ERROR" /* STORAGE_SERIALIZATION_ERROR */
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
throw new StorageError(
|
|
225
|
+
`Failed to read file: ${filePath}`,
|
|
226
|
+
"STORAGE_IO_ERROR" /* STORAGE_IO_ERROR */
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
writeFile(filePath, item) {
|
|
231
|
+
try {
|
|
232
|
+
const content = JSON.stringify(item, null, 2);
|
|
233
|
+
writeFileSync(filePath, content, "utf-8");
|
|
234
|
+
} catch {
|
|
235
|
+
throw new StorageError(
|
|
236
|
+
`Failed to write file: ${filePath}`,
|
|
237
|
+
"STORAGE_IO_ERROR" /* STORAGE_IO_ERROR */
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
export { FileStorage, InMemoryStorage, StorageError };
|
|
244
|
+
//# sourceMappingURL=storage.js.map
|
|
245
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/errors.ts","../../src/chat/storage.ts"],"names":[],"mappings":"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","file":"storage.js","sourcesContent":["import { ErrorCode } from \"./types/errors.js\";\n\n/** Options for constructing an AgentSDKError */\nexport interface AgentSDKErrorOptions extends ErrorOptions {\n /** Machine-readable error code */\n code?: string;\n /** Whether this error is retryable (default: false) */\n retryable?: boolean;\n /** HTTP status code hint (e.g. 401, 429, 500) */\n httpStatus?: number;\n}\n\n/** Base error class for agent-sdk.\n *\n * Use `AgentSDKError.is(err)` for reliable cross-module `instanceof` checks\n * (works across separately bundled entry points where `instanceof` may fail). */\nexport class AgentSDKError extends Error {\n /** @internal Marker for cross-bundle identity checks */\n readonly _agentSDKError = true as const;\n /** Machine-readable error code. Prefer values from the ErrorCode enum. */\n readonly code?: string;\n /** Whether this error is safe to retry */\n readonly retryable: boolean;\n /** HTTP status code hint for error classification */\n readonly httpStatus?: number;\n\n constructor(message: string, options?: AgentSDKErrorOptions) {\n super(message, options);\n this.name = \"AgentSDKError\";\n this.code = options?.code;\n this.retryable = options?.retryable ?? false;\n this.httpStatus = options?.httpStatus;\n }\n\n /** Check if an error is an AgentSDKError (works across bundled copies) */\n static is(error: unknown): error is AgentSDKError {\n return (\n error instanceof Error &&\n \"_agentSDKError\" in error &&\n (error as AgentSDKError)._agentSDKError === true\n );\n }\n}\n\n/** Thrown when agent.run() is called while already running (M8 re-entrancy guard) */\nexport class ReentrancyError extends AgentSDKError {\n constructor() {\n super(\"Agent is already running. Await the current run before starting another.\", {\n code: ErrorCode.REENTRANCY,\n });\n this.name = \"ReentrancyError\";\n }\n}\n\n/** Thrown when an operation is attempted on a disposed agent/service */\nexport class DisposedError extends AgentSDKError {\n constructor(entity: string) {\n super(`${entity} has been disposed and cannot be used.`, {\n code: ErrorCode.DISPOSED,\n });\n this.name = \"DisposedError\";\n }\n}\n\n/** Thrown when a backend is not found in the registry */\nexport class BackendNotFoundError extends AgentSDKError {\n constructor(backend: string) {\n super(\n `Unknown backend: \"${backend}\". ` +\n `Built-in: copilot, claude, vercel-ai. ` +\n `Custom: use registerBackend() first.`,\n { code: ErrorCode.BACKEND_NOT_INSTALLED },\n );\n this.name = \"BackendNotFoundError\";\n }\n}\n\n/** Thrown when a backend is already registered */\nexport class BackendAlreadyRegisteredError extends AgentSDKError {\n constructor(backend: string) {\n super(`Backend \"${backend}\" is already registered. Use a different name or unregister first.`);\n this.name = \"BackendAlreadyRegisteredError\";\n }\n}\n\n/** Thrown when subprocess management fails */\nexport class SubprocessError extends AgentSDKError {\n constructor(message: string, options?: ErrorOptions) {\n super(message, { ...options, code: ErrorCode.DEPENDENCY_MISSING });\n this.name = \"SubprocessError\";\n }\n}\n\n/** Thrown when a required peer dependency is not installed */\nexport class DependencyError extends AgentSDKError {\n public readonly packageName: string;\n\n constructor(packageName: string) {\n super(`${packageName} is not installed. Install it: npm install ${packageName}`, {\n code: ErrorCode.DEPENDENCY_MISSING,\n });\n this.name = \"DependencyError\";\n this.packageName = packageName;\n }\n}\n\n/** Thrown when an agent run is aborted */\nexport class AbortError extends AgentSDKError {\n constructor() {\n super(\"Agent run was aborted.\", { code: ErrorCode.ABORTED });\n this.name = \"AbortError\";\n }\n}\n\n/** Thrown when a tool execution fails */\nexport class ToolExecutionError extends AgentSDKError {\n public readonly toolName: string;\n\n constructor(toolName: string, message: string, options?: ErrorOptions) {\n super(`Tool \"${toolName}\" failed: ${message}`, { ...options, code: ErrorCode.TOOL_EXECUTION });\n this.name = \"ToolExecutionError\";\n this.toolName = toolName;\n }\n}\n\n/** Thrown when a stream has no activity within the configured timeout */\nexport class ActivityTimeoutError extends AgentSDKError {\n constructor(timeoutMs: number) {\n super(`Stream activity timeout: no event received within ${timeoutMs}ms.`, {\n code: ErrorCode.TIMEOUT,\n retryable: true,\n });\n this.name = \"ActivityTimeoutError\";\n }\n}\n\n/** Thrown when structured output parsing fails */\nexport class StructuredOutputError extends AgentSDKError {\n constructor(message: string, options?: ErrorOptions) {\n super(`Structured output error: ${message}`, { ...options, code: ErrorCode.INVALID_RESPONSE });\n this.name = \"StructuredOutputError\";\n }\n}\n","/**\n * @witqq/agent-sdk/chat/storage\n *\n * Generic storage adapter layer with pluggable backends.\n * Provides CRUD operations for any data type via `IStorageAdapter<T>`.\n * Implementations: `InMemoryStorage` (Map-based) and `FileStorage` (JSON files).\n */\n\nimport { existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { AgentSDKError } from \"../errors.js\";\nimport { ErrorCode } from \"../types/errors.js\";\n\n// ─── Storage Errors ────────────────────────────────────────────\n\n/**\n * Error thrown by storage operations.\n *\n * @example\n * ```typescript\n * try {\n * await store.get(\"missing-id\");\n * } catch (e) {\n * if (e instanceof StorageError && e.code === ErrorCode.STORAGE_NOT_FOUND) {\n * // handle missing item\n * }\n * }\n * ```\n */\nexport class StorageError extends AgentSDKError {\n /** Machine-readable error code from the unified ErrorCode enum */\n readonly code: StorageErrorCode;\n\n constructor(message: string, code: StorageErrorCode) {\n super(message);\n this.name = \"StorageError\";\n this.code = code;\n }\n}\n\n/** Storage-specific subset of ErrorCode */\nexport type StorageErrorCode =\n | ErrorCode.STORAGE_NOT_FOUND\n | ErrorCode.STORAGE_DUPLICATE_KEY\n | ErrorCode.STORAGE_IO_ERROR\n | ErrorCode.STORAGE_SERIALIZATION_ERROR;\n\n// ─── Storage Adapter Interface ─────────────────────────────────\n\n/**\n * Options for listing stored items.\n *\n * @typeParam T - The type of stored items\n */\nexport interface ListOptions<T> {\n /** Filter predicate — return `true` to include the item */\n filter?: (item: T) => boolean;\n /** Sort comparator — standard Array.sort semantics */\n sort?: (a: T, b: T) => number;\n /** Maximum number of items to return */\n limit?: number;\n /** Number of items to skip (for pagination) */\n offset?: number;\n}\n\n/**\n * Generic storage adapter for CRUD operations on any data type.\n * Items are identified by a string key.\n *\n * @typeParam T - The type of stored items\n *\n * @example\n * ```typescript\n * const store: IStorageAdapter<{ name: string }> = new InMemoryStorage();\n * await store.create(\"key1\", { name: \"Alice\" });\n * const item = await store.get(\"key1\"); // { name: \"Alice\" }\n * ```\n */\nexport interface IStorageAdapter<T> {\n /**\n * Retrieve an item by key.\n * @param key - Unique identifier\n * @returns The item, or `null` if not found\n */\n get(key: string): Promise<T | null>;\n\n /**\n * List items with optional filtering, sorting, and pagination.\n * @param options - Filter, sort, limit, offset options\n * @returns Array of matching items\n */\n list(options?: ListOptions<T>): Promise<T[]>;\n\n /**\n * Create a new item. Throws `StorageError` with code `DUPLICATE_KEY` if key exists.\n * @param key - Unique identifier\n * @param item - Data to store\n */\n create(key: string, item: T): Promise<void>;\n\n /**\n * Update an existing item. Throws `StorageError` with code `NOT_FOUND` if key missing.\n * @param key - Unique identifier\n * @param item - Updated data\n */\n update(key: string, item: T): Promise<void>;\n\n /**\n * Delete an item by key. Throws `StorageError` with code `NOT_FOUND` if key missing.\n * @param key - Unique identifier\n */\n delete(key: string): Promise<void>;\n\n /**\n * Check whether a key exists.\n * @param key - Unique identifier\n * @returns `true` if key exists\n */\n has(key: string): Promise<boolean>;\n\n /**\n * Return the number of stored items.\n * @returns Count of items\n */\n count(): Promise<number>;\n\n /**\n * Remove all items from storage.\n */\n clear(): Promise<void>;\n\n /**\n * Release any resources held by this adapter (DB connections, file handles).\n * Optional — adapters that don't hold resources need not implement this.\n */\n dispose?(): Promise<void>;\n}\n\n// ─── InMemoryStorage ───────────────────────────────────────────\n\n/**\n * In-memory storage adapter backed by a `Map`.\n * Suitable for development, testing, and short-lived processes.\n * Data is lost when the process exits.\n *\n * @typeParam T - The type of stored items\n *\n * @example\n * ```typescript\n * const store = new InMemoryStorage<{ name: string }>();\n * await store.create(\"k1\", { name: \"Alice\" });\n * await store.create(\"k2\", { name: \"Bob\" });\n * const items = await store.list({ filter: i => i.name.startsWith(\"A\") });\n * // [{ name: \"Alice\" }]\n * ```\n */\nexport class InMemoryStorage<T> implements IStorageAdapter<T> {\n private readonly data = new Map<string, T>();\n\n /** @inheritdoc */\n async get(key: string): Promise<T | null> {\n const item = this.data.get(key);\n return item !== undefined ? structuredClone(item) : null;\n }\n\n /** @inheritdoc */\n async list(options?: ListOptions<T>): Promise<T[]> {\n let items = Array.from(this.data.values()).map((item) => structuredClone(item));\n\n if (options?.filter) {\n items = items.filter(options.filter);\n }\n if (options?.sort) {\n items.sort(options.sort);\n }\n if (options?.offset !== undefined) {\n items = items.slice(options.offset);\n }\n if (options?.limit !== undefined) {\n items = items.slice(0, options.limit);\n }\n\n return items;\n }\n\n /** @inheritdoc */\n async create(key: string, item: T): Promise<void> {\n if (this.data.has(key)) {\n throw new StorageError(\n `Item with key \"${key}\" already exists`,\n ErrorCode.STORAGE_DUPLICATE_KEY,\n );\n }\n this.data.set(key, structuredClone(item));\n }\n\n /** @inheritdoc */\n async update(key: string, item: T): Promise<void> {\n if (!this.data.has(key)) {\n throw new StorageError(\n `Item with key \"${key}\" not found`,\n ErrorCode.STORAGE_NOT_FOUND,\n );\n }\n this.data.set(key, structuredClone(item));\n }\n\n /** @inheritdoc */\n async delete(key: string): Promise<void> {\n if (!this.data.has(key)) {\n throw new StorageError(\n `Item with key \"${key}\" not found`,\n ErrorCode.STORAGE_NOT_FOUND,\n );\n }\n this.data.delete(key);\n }\n\n /** @inheritdoc */\n async has(key: string): Promise<boolean> {\n return this.data.has(key);\n }\n\n /** @inheritdoc */\n async count(): Promise<number> {\n return this.data.size;\n }\n\n /** @inheritdoc */\n async clear(): Promise<void> {\n this.data.clear();\n }\n}\n\n// ─── FileStorage ───────────────────────────────────────────────\n\n/**\n * Options for configuring `FileStorage`.\n */\nexport interface FileStorageOptions {\n /** Directory path where JSON files are stored */\n directory: string;\n /** File extension (default: `.json`) */\n extension?: string;\n}\n\n/**\n * File-based storage adapter that persists each item as a JSON file.\n * Suitable for local applications, CLI tools, and development.\n * Creates the storage directory if it doesn't exist.\n *\n * @typeParam T - The type of stored items (must be JSON-serializable)\n *\n * @example\n * ```typescript\n * const store = new FileStorage<ChatSession>({\n * directory: \"./data/sessions\",\n * });\n * await store.create(\"session-1\", mySession);\n * ```\n */\nexport class FileStorage<T> implements IStorageAdapter<T> {\n private readonly directory: string;\n private readonly extension: string;\n\n constructor(options: FileStorageOptions) {\n this.directory = options.directory;\n this.extension = options.extension ?? \".json\";\n this.ensureDirectory();\n }\n\n /** @inheritdoc */\n async get(key: string): Promise<T | null> {\n const filePath = this.keyToPath(key);\n if (!existsSync(filePath)) {\n return null;\n }\n return this.readFile(filePath);\n }\n\n /** @inheritdoc */\n async list(options?: ListOptions<T>): Promise<T[]> {\n this.ensureDirectory();\n const files = readdirSync(this.directory).filter((f) =>\n f.endsWith(this.extension),\n );\n\n let items: T[] = [];\n for (const file of files) {\n const item = this.readFile(join(this.directory, file));\n items.push(item);\n }\n\n if (options?.filter) {\n items = items.filter(options.filter);\n }\n if (options?.sort) {\n items.sort(options.sort);\n }\n if (options?.offset !== undefined) {\n items = items.slice(options.offset);\n }\n if (options?.limit !== undefined) {\n items = items.slice(0, options.limit);\n }\n\n return items;\n }\n\n /** @inheritdoc */\n async create(key: string, item: T): Promise<void> {\n const filePath = this.keyToPath(key);\n if (existsSync(filePath)) {\n throw new StorageError(\n `Item with key \"${key}\" already exists`,\n ErrorCode.STORAGE_DUPLICATE_KEY,\n );\n }\n this.writeFile(filePath, item);\n }\n\n /** @inheritdoc */\n async update(key: string, item: T): Promise<void> {\n const filePath = this.keyToPath(key);\n if (!existsSync(filePath)) {\n throw new StorageError(\n `Item with key \"${key}\" not found`,\n ErrorCode.STORAGE_NOT_FOUND,\n );\n }\n this.writeFile(filePath, item);\n }\n\n /** @inheritdoc */\n async delete(key: string): Promise<void> {\n const filePath = this.keyToPath(key);\n if (!existsSync(filePath)) {\n throw new StorageError(\n `Item with key \"${key}\" not found`,\n ErrorCode.STORAGE_NOT_FOUND,\n );\n }\n unlinkSync(filePath);\n }\n\n /** @inheritdoc */\n async has(key: string): Promise<boolean> {\n return existsSync(this.keyToPath(key));\n }\n\n /** @inheritdoc */\n async count(): Promise<number> {\n this.ensureDirectory();\n return readdirSync(this.directory).filter((f) =>\n f.endsWith(this.extension),\n ).length;\n }\n\n /** @inheritdoc */\n async clear(): Promise<void> {\n this.ensureDirectory();\n const files = readdirSync(this.directory).filter((f) =>\n f.endsWith(this.extension),\n );\n for (const file of files) {\n unlinkSync(join(this.directory, file));\n }\n }\n\n private keyToPath(key: string): string {\n const safeKey = key.replace(/[^a-zA-Z0-9_-]/g, (c) =>\n \"%\" + c.charCodeAt(0).toString(16).padStart(2, \"0\"),\n );\n return join(this.directory, `${safeKey}${this.extension}`);\n }\n\n private ensureDirectory(): void {\n if (!existsSync(this.directory)) {\n mkdirSync(this.directory, { recursive: true });\n }\n }\n\n private readFile(filePath: string): T {\n try {\n const content = readFileSync(filePath, \"utf-8\");\n return JSON.parse(content) as T;\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new StorageError(\n `Failed to parse file: ${filePath}`,\n ErrorCode.STORAGE_SERIALIZATION_ERROR,\n );\n }\n throw new StorageError(\n `Failed to read file: ${filePath}`,\n ErrorCode.STORAGE_IO_ERROR,\n );\n }\n }\n\n private writeFile(filePath: string, item: T): void {\n try {\n const content = JSON.stringify(item, null, 2);\n writeFileSync(filePath, content, \"utf-8\");\n } catch {\n throw new StorageError(\n `Failed to write file: ${filePath}`,\n ErrorCode.STORAGE_IO_ERROR,\n );\n }\n }\n}\n"]}
|