mindcache 2.4.0 → 3.1.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.
@@ -1,3 +1,5 @@
1
+ import * as Y from 'yjs';
2
+
1
3
  /**
2
4
  * Access level for MindCache operations
3
5
  * - 'user': Can only manage content tags (default)
@@ -22,7 +24,7 @@ type SystemTag = 'SystemPrompt' | 'LLMRead' | 'LLMWrite' | 'protected' | 'ApplyT
22
24
  */
23
25
  interface KeyAttributes {
24
26
  /** The type of value stored */
25
- type: 'text' | 'image' | 'file' | 'json';
27
+ type: 'text' | 'image' | 'file' | 'json' | 'document';
26
28
  /** MIME type for files/images */
27
29
  contentType?: string;
28
30
  /** User-defined tags for organizing keys */
@@ -69,6 +71,26 @@ type GlobalListener = () => void;
69
71
  * Default attributes for new keys
70
72
  */
71
73
  declare const DEFAULT_KEY_ATTRIBUTES: KeyAttributes;
74
+ /**
75
+ * A single entry in the global history log
76
+ */
77
+ interface HistoryEntry {
78
+ /** Unique identifier for this history entry */
79
+ id: string;
80
+ /** Timestamp when the change occurred */
81
+ timestamp: number;
82
+ /** Keys that were affected by this change */
83
+ keysAffected?: string[];
84
+ }
85
+ /**
86
+ * History options for offline and cloud modes
87
+ */
88
+ interface HistoryOptions {
89
+ /** Max history entries to keep (default: 100) */
90
+ maxEntries?: number;
91
+ /** Save full snapshot every N entries for fast restore (default: 10) */
92
+ snapshotInterval?: number;
93
+ }
72
94
 
73
95
  /**
74
96
  * Cloud configuration options for MindCache constructor
@@ -99,206 +121,174 @@ interface MindCacheIndexedDBOptions {
99
121
  * Constructor options for MindCache
100
122
  */
101
123
  interface MindCacheOptions {
102
- /** Cloud sync configuration. If omitted, runs in local-only mode. */
124
+ /** Cloud sync configuration. If omitted, runs in local-only mode. IndexedDB auto-enabled for offline support. */
103
125
  cloud?: MindCacheCloudOptions;
104
- /** IndexedDB configuration */
126
+ /** IndexedDB configuration. Ignored in cloud mode (auto-enabled). */
105
127
  indexedDB?: MindCacheIndexedDBOptions;
128
+ /** History tracking options (enabled in IndexedDB and Cloud modes) */
129
+ history?: HistoryOptions;
106
130
  /** Access level for tag operations. 'system' allows managing system tags. */
107
131
  accessLevel?: AccessLevel;
108
132
  }
109
133
  type ConnectionState$1 = 'disconnected' | 'connecting' | 'connected' | 'error';
110
134
  declare class MindCache {
111
- private stm;
135
+ doc: Y.Doc;
136
+ private rootMap;
112
137
  private listeners;
113
138
  private globalListeners;
139
+ readonly version = "3.1.0";
114
140
  private _isRemoteUpdate;
115
- /**
116
- * Normalize system tags: migrate old tags to new ones
117
- * - 'prompt' → 'SystemPrompt'
118
- * - 'readonly' → remove 'LLMWrite' (or add if not readonly)
119
- */
120
141
  private normalizeSystemTags;
121
- /**
122
- * Check if key should be visible in system prompt
123
- */
124
- private hasSystemPrompt;
125
- /**
126
- * Check if key can be read by LLM (has LLMRead or SystemPrompt)
127
- */
128
- private hasLLMRead;
129
- /**
130
- * Check if key can be written by LLM (has LLMWrite and not readonly)
131
- */
132
- private hasLLMWrite;
133
142
  private _cloudAdapter;
134
143
  private _connectionState;
135
144
  private _isLoaded;
136
145
  private _cloudConfig;
137
146
  private _accessLevel;
138
147
  private _initPromise;
148
+ private _idbProvider;
149
+ private _undoManagers;
150
+ private _globalUndoManager;
151
+ private _history;
152
+ private _historyOptions;
153
+ private _historyEnabled;
139
154
  constructor(options?: MindCacheOptions);
155
+ private getUndoManager;
140
156
  /**
141
- * Get the current access level
157
+ * Undo changes for a specific key
142
158
  */
143
- get accessLevel(): AccessLevel;
159
+ undo(key: string): void;
144
160
  /**
145
- * Check if this instance has system-level access
161
+ * Redo changes for a specific key
146
162
  */
147
- get hasSystemAccess(): boolean;
148
- private _initCloud;
149
- private _initIndexedDB;
150
- protected _getIndexedDBAdapterClass(): Promise<any>;
163
+ redo(key: string): void;
164
+ getHistory(key: string): any[];
165
+ private initGlobalUndoManager;
151
166
  /**
152
- * Get the current cloud connection state
167
+ * Undo all recent local changes (across all keys)
168
+ * Only undoes YOUR changes, not changes from other users in cloud mode
153
169
  */
154
- get connectionState(): ConnectionState$1;
170
+ undoAll(): void;
155
171
  /**
156
- * Check if data is loaded (true for local, true after sync for cloud)
172
+ * Redo previously undone local changes
157
173
  */
158
- get isLoaded(): boolean;
174
+ redoAll(): void;
159
175
  /**
160
- * Protected method to load CloudAdapter class.
161
- * Can be overridden/mocked for testing.
176
+ * Check if there are changes to undo globally
162
177
  */
163
- protected _getCloudAdapterClass(): Promise<any>;
178
+ canUndoAll(): boolean;
164
179
  /**
165
- * Check if this instance is connected to cloud
180
+ * Check if there are changes to redo globally
166
181
  */
167
- get isCloud(): boolean;
182
+ canRedoAll(): boolean;
183
+ private enableHistory;
184
+ private generateId;
168
185
  /**
169
- * Wait for initial sync to complete (or resolve immediately if already synced/local).
170
- * Useful for scripts or linear execution flows.
186
+ * Get global history of all changes (available in IndexedDB and Cloud modes)
171
187
  */
172
- waitForSync(): Promise<void>;
188
+ getGlobalHistory(): HistoryEntry[];
173
189
  /**
174
- * Disconnect from cloud (if connected)
190
+ * Check if history tracking is enabled
175
191
  */
192
+ get historyEnabled(): boolean;
193
+ /**
194
+ * Restore to a specific version (time travel)
195
+ * Note: Full implementation requires storing update binaries, which is not yet implemented.
196
+ * @returns false - not yet fully implemented
197
+ */
198
+ restoreToVersion(_versionId: string): boolean;
199
+ get accessLevel(): AccessLevel;
200
+ get hasSystemAccess(): boolean;
201
+ private _initCloud;
202
+ private _initYIndexedDB;
203
+ private _initIndexedDB;
204
+ protected _getIndexedDBAdapterClass(): Promise<any>;
205
+ get connectionState(): ConnectionState$1;
206
+ get isLoaded(): boolean;
207
+ protected _getCloudAdapterClass(): Promise<any>;
208
+ get isCloud(): boolean;
209
+ waitForSync(): Promise<void>;
176
210
  disconnect(): void;
211
+ isRemoteUpdate(): boolean;
212
+ serialize(): STM;
213
+ deserialize(data: STM): void;
177
214
  private encodeFileToBase64;
178
215
  private createDataUrl;
179
216
  private validateContentType;
180
- /** @deprecated Use get_value instead */
181
- get(key: string): any;
217
+ private injectSTM;
218
+ getAll(): STM;
182
219
  get_value(key: string, _processingStack?: Set<string>): any;
183
220
  get_attributes(key: string): KeyAttributes | undefined;
184
221
  set_value(key: string, value: any, attributes?: Partial<KeyAttributes>): void;
185
- _setFromRemote(key: string, value: any, attributes: KeyAttributes): void;
186
- isRemoteUpdate(): boolean;
187
- _deleteFromRemote(key: string): void;
188
- _clearFromRemote(): void;
189
- set_attributes(key: string, attributes: Partial<KeyAttributes>): boolean;
190
- set(key: string, value: any): void;
191
- set_file(key: string, file: File, attributes?: Partial<KeyAttributes>): Promise<void>;
192
- set_base64(key: string, base64Data: string, contentType: string, type?: 'image' | 'file', attributes?: Partial<KeyAttributes>): void;
193
- add_image(key: string, base64Data: string, contentType?: string, attributes?: Partial<KeyAttributes>): void;
194
- get_data_url(key: string): string | undefined;
195
- get_base64(key: string): string | undefined;
196
- has(key: string): boolean;
197
- delete(key: string): boolean;
222
+ delete_key(key: string): void;
198
223
  clear(): void;
224
+ set_file(key: string, file: File, attributes?: Partial<KeyAttributes>): Promise<void>;
225
+ set_image(key: string, file: File, attributes?: Partial<KeyAttributes>): Promise<void>;
199
226
  /**
200
- * Get keys sorted by zIndex (ascending), then by key name
201
- */
202
- private getSortedKeys;
203
- keys(): string[];
204
- values(): any[];
205
- entries(): [string, any][];
206
- size(): number;
207
- getAll(): Record<string, any>;
208
- update(newValues: Record<string, any>): void;
209
- subscribe(key: string, listener: Listener): void;
210
- unsubscribe(key: string, listener: Listener): void;
211
- subscribeToAll(listener: GlobalListener): void;
212
- unsubscribeFromAll(listener: GlobalListener): void;
213
- private notifyGlobalListeners;
214
- injectSTM(template: string, _processingStack?: Set<string>): string;
215
- getSTM(): string;
216
- getSTMObject(): Record<string, any>;
217
- getSTMForAPI(): Array<{
218
- key: string;
219
- value: any;
220
- type: string;
221
- contentType?: string;
222
- }>;
223
- getVisibleImages(): Array<{
224
- type: 'file';
225
- mediaType: string;
226
- url: string;
227
- filename?: string;
228
- }>;
229
- toJSON(): string;
230
- fromJSON(jsonString: string): void;
231
- serialize(): Record<string, STMEntry>;
232
- deserialize(data: Record<string, STMEntry>): void;
233
- get_system_prompt(): string;
234
- private findKeyFromToolName;
235
- get_aisdk_tools(): Record<string, any>;
236
- executeToolCall(toolName: string, value: any): {
237
- result: string;
238
- key: string;
239
- value: any;
240
- } | null;
241
- /**
242
- * Add a content tag to a key (user-level organization)
243
- */
244
- addTag(key: string, tag: string): boolean;
245
- /**
246
- * Remove a content tag from a key
247
- */
248
- removeTag(key: string, tag: string): boolean;
249
- /**
250
- * Get all content tags for a key
251
- */
252
- getTags(key: string): string[];
253
- /**
254
- * Get all unique content tags across all keys
255
- */
256
- getAllTags(): string[];
257
- /**
258
- * Check if a key has a specific content tag
259
- */
260
- hasTag(key: string, tag: string): boolean;
261
- /**
262
- * Get all keys with a specific content tag as formatted string
227
+ * Create or get a collaborative document key.
228
+ * Uses Y.Text for character-level concurrent editing.
229
+ *
230
+ * Note: This exposes Yjs Y.Text directly for editor bindings (y-quill, y-codemirror, etc.)
263
231
  */
264
- getTagged(tag: string): string;
232
+ set_document(key: string, initialText?: string, attributes?: Partial<KeyAttributes>): void;
265
233
  /**
266
- * Get all keys with a specific content tag
234
+ * Get the Y.Text object for a document key.
235
+ * Use this to bind to editors (Quill, CodeMirror, Monaco, etc.)
236
+ *
237
+ * @returns Y.Text or undefined if key doesn't exist or isn't a document
267
238
  */
268
- getKeysByTag(tag: string): string[];
239
+ get_document(key: string): Y.Text | undefined;
269
240
  /**
270
- * Add a system tag to a key (requires system access)
271
- * System tags: 'prompt', 'readonly', 'protected', 'template'
241
+ * Get plain text content of a document key.
242
+ * For collaborative editing, use get_document() and bind to an editor.
272
243
  */
273
- systemAddTag(key: string, tag: SystemTag): boolean;
244
+ get_document_text(key: string): string | undefined;
274
245
  /**
275
- * Remove a system tag from a key (requires system access)
246
+ * Insert text at a position in a document key.
276
247
  */
277
- systemRemoveTag(key: string, tag: SystemTag): boolean;
248
+ insert_text(key: string, index: number, text: string): void;
278
249
  /**
279
- * Get all system tags for a key (requires system access)
250
+ * Delete text from a document key.
280
251
  */
281
- systemGetTags(key: string): SystemTag[];
252
+ delete_text(key: string, index: number, length: number): void;
282
253
  /**
283
- * Check if a key has a specific system tag (requires system access)
254
+ * Replace all text in a document key.
255
+ * Uses diff-based updates when changes are < diffThreshold (default 80%).
256
+ * This preserves concurrent edits and provides better undo granularity.
257
+ *
258
+ * @param key - The document key
259
+ * @param newText - The new text content
260
+ * @param diffThreshold - Percentage (0-1) of change above which full replace is used (default: 0.8)
284
261
  */
285
- systemHasTag(key: string, tag: SystemTag): boolean;
262
+ replace_document_text(key: string, newText: string, diffThreshold?: number): void;
263
+ subscribe(key: string, listener: Listener): () => void;
264
+ subscribeToAll(listener: GlobalListener): () => void;
265
+ unsubscribeFromAll(listener: GlobalListener): void;
266
+ private notifyGlobalListeners;
267
+ private sanitizeKeyForTool;
268
+ private findKeyFromSanitizedTool;
286
269
  /**
287
- * Set all system tags for a key at once (requires system access)
270
+ * Generate Vercel AI SDK compatible tools for writable keys.
271
+ * For document type keys, generates additional tools: append_, insert_, edit_
288
272
  */
289
- systemSetTags(key: string, tags: SystemTag[]): boolean;
273
+ get_aisdk_tools(): Record<string, any>;
290
274
  /**
291
- * Get all keys with a specific system tag (requires system access)
275
+ * Generate a system prompt containing all visible STM keys and their values.
276
+ * Indicates which tools can be used to modify writable keys.
292
277
  */
293
- systemGetKeysByTag(tag: SystemTag): string[];
278
+ get_system_prompt(): string;
294
279
  /**
295
- * Helper to sync legacy boolean attributes from system tags
280
+ * Execute a tool call by name with the given value.
281
+ * Returns the result or null if tool not found.
296
282
  */
297
- private syncLegacyFromSystemTags;
298
- toMarkdown(): string;
299
- fromMarkdown(markdown: string): void;
283
+ executeToolCall(toolName: string, value: any): {
284
+ result: string;
285
+ key: string;
286
+ value?: any;
287
+ } | null;
288
+ _setFromRemote(_key: string, _value: any, _attributes: KeyAttributes): void;
289
+ _deleteFromRemote(_key: string): void;
290
+ _clearFromRemote(): void;
300
291
  }
301
- declare const mindcache: MindCache;
302
292
 
303
293
  /**
304
294
  * Configuration for connecting to MindCache Cloud
@@ -346,24 +336,9 @@ interface CloudAdapterEvents {
346
336
  synced: () => void;
347
337
  }
348
338
 
349
- /**
350
- * CloudAdapter connects a MindCache instance to the cloud service
351
- * for real-time sync and persistence.
352
- *
353
- * Auth flow:
354
- * 1. SDK calls POST /api/ws-token with apiKey to get short-lived token
355
- * 2. SDK connects to WebSocket with token in query string
356
- * 3. Server validates token and upgrades to WebSocket
357
- *
358
- * Usage patterns:
359
- * - apiKey: SDK fetches tokens automatically (simple, good for demos)
360
- * - tokenEndpoint: Your backend fetches tokens (secure, apiKey stays server-side)
361
- * - tokenProvider: Custom token logic (advanced)
362
- */
363
339
  declare class CloudAdapter {
364
340
  private config;
365
341
  private ws;
366
- private queue;
367
342
  private mindcache;
368
343
  private unsubscribe;
369
344
  private reconnectAttempts;
@@ -372,64 +347,20 @@ declare class CloudAdapter {
372
347
  private listeners;
373
348
  private token;
374
349
  constructor(config: CloudConfig);
375
- /**
376
- * Set auth token (short-lived, from /api/ws-token)
377
- * Call this before connect() or use setTokenProvider for auto-refresh
378
- */
379
350
  setToken(token: string): void;
380
- /**
381
- * Set a function that returns a fresh token
382
- * Used for automatic token refresh on reconnect
383
- */
384
351
  setTokenProvider(provider: () => Promise<string>): void;
385
- /**
386
- * Get current connection state
387
- */
388
352
  get state(): ConnectionState;
389
- /**
390
- * Attach to a MindCache instance and start syncing
391
- */
392
353
  attach(mc: MindCache): void;
393
- /**
394
- * Detach from the MindCache instance
395
- */
396
354
  detach(): void;
397
- /**
398
- * Fetch a short-lived WebSocket token from the API using the API key.
399
- * This keeps the API key secure by only using it for a single HTTPS request,
400
- * then using the short-lived token for the WebSocket connection.
401
- *
402
- * Supports two key formats:
403
- * - API keys: mc_live_xxx or mc_test_xxx → Bearer token
404
- * - Delegate keys: del_xxx:sec_xxx → ApiKey format
405
- */
406
355
  private fetchTokenWithApiKey;
407
- /**
408
- * Connect to the cloud service
409
- */
410
356
  connect(): Promise<void>;
411
- /**
412
- * Disconnect from the cloud service
413
- */
414
357
  disconnect(): void;
415
- /**
416
- * Push an operation to the cloud
417
- */
418
- push(op: Operation): void;
419
- /**
420
- * Add event listener
421
- */
422
358
  on<K extends keyof CloudAdapterEvents>(event: K, listener: CloudAdapterEvents[K]): void;
423
- /**
424
- * Remove event listener
425
- */
426
359
  off<K extends keyof CloudAdapterEvents>(event: K, listener: CloudAdapterEvents[K]): void;
427
360
  private emit;
428
361
  private setupWebSocket;
429
- private handleMessage;
430
- private flushQueue;
362
+ private sendBinary;
431
363
  private scheduleReconnect;
432
- private syncLocalChanges;
433
364
  }
434
365
 
435
- export { CloudAdapter as C, DEFAULT_KEY_ATTRIBUTES as D, type KeyAttributes as K, type Listener as L, MindCache as M, type Operation as O, type STM as S, type MindCacheOptions as a, type STMEntry as b, type MindCacheCloudOptions as c, type MindCacheIndexedDBOptions as d, type CloudConfig as e, type ConnectionState as f, type CloudAdapterEvents as g, type SetOperation as h, type DeleteOperation as i, type ClearOperation as j, mindcache as m };
366
+ export { CloudAdapter as C, DEFAULT_KEY_ATTRIBUTES as D, type KeyAttributes as K, type Listener as L, MindCache as M, type Operation as O, type STM as S, type MindCacheOptions as a, type STMEntry as b, type MindCacheCloudOptions as c, type MindCacheIndexedDBOptions as d, type CloudConfig as e, type ConnectionState as f, type CloudAdapterEvents as g, type SetOperation as h, type DeleteOperation as i, type ClearOperation as j };