@limo-labs/deity 0.1.1-alpha.2 → 0.1.1-alpha.4

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.
@@ -0,0 +1,696 @@
1
+ /**
2
+ * State checkpoint types and utilities.
3
+ * Supports semantic versioning and explicit save points.
4
+ */
5
+ /**
6
+ * State checkpoint record.
7
+ * Represents a single save point in workflow execution.
8
+ */
9
+ interface StateCheckpoint {
10
+ /** Unique checkpoint ID (developer-defined) */
11
+ id: string;
12
+ /** Semantic version (major.minor.patch) */
13
+ version: string;
14
+ /** Checkpoint label (e.g., "after-planning", "analysis-complete") */
15
+ label: string;
16
+ /** Arbitrary state data */
17
+ state: Record<string, unknown>;
18
+ /** Stage outputs captured at this point */
19
+ outputs: Record<string, unknown>;
20
+ /** Creation timestamp (ISO 8601) */
21
+ timestamp: string;
22
+ /** Optional metadata */
23
+ metadata?: Record<string, unknown>;
24
+ }
25
+ /**
26
+ * Checkpoint store interface.
27
+ * Manages persistence of state checkpoints.
28
+ */
29
+ interface CheckpointStore {
30
+ /**
31
+ * Save a checkpoint.
32
+ */
33
+ save(checkpoint: StateCheckpoint): Promise<void>;
34
+ /**
35
+ * Load a checkpoint by ID.
36
+ */
37
+ load(checkpointId: string): Promise<StateCheckpoint | undefined>;
38
+ /**
39
+ * List all available checkpoints.
40
+ */
41
+ list(): Promise<StateCheckpoint[]>;
42
+ /**
43
+ * Get the latest checkpoint.
44
+ */
45
+ getLatest(): Promise<StateCheckpoint | undefined>;
46
+ /**
47
+ * Delete a checkpoint by ID.
48
+ */
49
+ delete(checkpointId: string): Promise<void>;
50
+ /**
51
+ * Clear all checkpoints.
52
+ */
53
+ clear(): Promise<void>;
54
+ }
55
+ /**
56
+ * Semantic version utilities.
57
+ */
58
+ /**
59
+ * Parse a semantic version string into components.
60
+ */
61
+ declare function parseVersion(version: string): {
62
+ major: number;
63
+ minor: number;
64
+ patch: number;
65
+ };
66
+ /**
67
+ * Check if a checkpoint version is compatible with the current version.
68
+ * Only major version changes break compatibility.
69
+ */
70
+ declare function isCompatible(checkpointVersion: string, currentVersion: string): boolean;
71
+ /**
72
+ * Compare two semantic versions.
73
+ * Returns -1 if a < b, 0 if a === b, 1 if a > b
74
+ */
75
+ declare function compareVersions(a: string, b: string): number;
76
+ /**
77
+ * Validate a semantic version string.
78
+ */
79
+ declare function isValidVersion(version: string): boolean;
80
+
81
+ /**
82
+ * Simplified state store interface for basic use cases.
83
+ *
84
+ * This interface provides a minimal API for simple key-value storage,
85
+ * reducing complexity for users who don't need advanced checkpoint features.
86
+ *
87
+ * ## Design Philosophy
88
+ *
89
+ * - **Minimal**: Only 4 essential methods (get, set, delete, has)
90
+ * - **Async-first**: All methods return Promises for I/O flexibility
91
+ * - **Type-safe**: Full TypeScript support with unknown type safety
92
+ * - **Framework-agnostic**: Can be used standalone or with Deity workflow
93
+ *
94
+ * ## Usage
95
+ *
96
+ * ```typescript
97
+ * import { SimpleStateStore } from '@limo-labs/deity/state';
98
+ *
99
+ * // Implement your own store
100
+ * class MyStore implements SimpleStateStore {
101
+ * async get(key: string) { ... }
102
+ * async set(key: string, value: unknown) { ... }
103
+ * async delete(key: string) { ... }
104
+ * async has(key: string) { ... }
105
+ * }
106
+ *
107
+ * // Or use built-in implementations
108
+ * import { createInMemoryStore, createFileStore } from '@limo-labs/deity/helpers';
109
+ *
110
+ * const memStore = createInMemoryStore();
111
+ * const fileStore = createFileStore('./data');
112
+ * ```
113
+ *
114
+ * ## When to Use
115
+ *
116
+ * **Use SimpleStateStore when:**
117
+ * - You need basic key-value storage
118
+ * - You don't need checkpoint versioning
119
+ * - You want minimal implementation overhead
120
+ * - You're prototyping or testing
121
+ *
122
+ * **Use full StateStore/CheckpointStore when:**
123
+ * - You need semantic versioning
124
+ * - You need event sourcing
125
+ * - You need workflow checkpoint/resume
126
+ * - You need time-travel debugging
127
+ *
128
+ * @module state/simple-store
129
+ * @since 3.0.0
130
+ */
131
+ /**
132
+ * Simplified state store interface.
133
+ *
134
+ * Provides minimal key-value storage without checkpoint metadata.
135
+ * All values are serializable (JSON-compatible).
136
+ *
137
+ * @example
138
+ * ```typescript
139
+ * const store: SimpleStateStore = createInMemoryStore();
140
+ *
141
+ * // Set a value
142
+ * await store.set('user:123', { name: 'Alice', age: 30 });
143
+ *
144
+ * // Get a value
145
+ * const user = await store.get('user:123');
146
+ *
147
+ * // Check existence
148
+ * if (await store.has('user:123')) {
149
+ * console.log('User exists');
150
+ * }
151
+ *
152
+ * // Delete a value
153
+ * await store.delete('user:123');
154
+ * ```
155
+ */
156
+ interface SimpleStateStore {
157
+ /**
158
+ * Get a value by key.
159
+ *
160
+ * @param key - The key to retrieve
161
+ * @returns The stored value, or undefined if not found
162
+ *
163
+ * @example
164
+ * ```typescript
165
+ * const data = await store.get('my-key');
166
+ * if (data) {
167
+ * console.log('Found:', data);
168
+ * }
169
+ * ```
170
+ */
171
+ get(key: string): Promise<unknown | undefined>;
172
+ /**
173
+ * Set a value for a key.
174
+ *
175
+ * @param key - The key to store under
176
+ * @param value - The value to store (must be JSON-serializable)
177
+ *
178
+ * @example
179
+ * ```typescript
180
+ * await store.set('config', { theme: 'dark', lang: 'en' });
181
+ * ```
182
+ */
183
+ set(key: string, value: unknown): Promise<void>;
184
+ /**
185
+ * Delete a value by key.
186
+ *
187
+ * @param key - The key to delete
188
+ *
189
+ * @example
190
+ * ```typescript
191
+ * await store.delete('temp-data');
192
+ * ```
193
+ */
194
+ delete(key: string): Promise<void>;
195
+ /**
196
+ * Check if a key exists.
197
+ *
198
+ * @param key - The key to check
199
+ * @returns True if the key exists, false otherwise
200
+ *
201
+ * @example
202
+ * ```typescript
203
+ * if (await store.has('cache:results')) {
204
+ * const results = await store.get('cache:results');
205
+ * }
206
+ * ```
207
+ */
208
+ has(key: string): Promise<boolean>;
209
+ }
210
+ /**
211
+ * Extended simple store interface with optional clear operation.
212
+ *
213
+ * Some implementations may support bulk delete operations.
214
+ */
215
+ interface SimpleStateStoreWithClear extends SimpleStateStore {
216
+ /**
217
+ * Clear all stored values.
218
+ * Optional - not all implementations support this.
219
+ */
220
+ clear?(): Promise<void>;
221
+ }
222
+
223
+ /**
224
+ * In-memory implementation of SimpleStateStore.
225
+ *
226
+ * Fast, lightweight key-value store using a Map.
227
+ * Supports optional TTL (time-to-live) and size limits.
228
+ *
229
+ * ## Features
230
+ *
231
+ * - **Fast**: O(1) get/set/delete operations
232
+ * - **TTL support**: Auto-expire entries after timeout
233
+ * - **Size limits**: Prevent unbounded memory growth
234
+ * - **LRU eviction**: When size limit reached, evict oldest entries
235
+ *
236
+ * ## Usage
237
+ *
238
+ * ```typescript
239
+ * import { InMemoryStateStore } from '@limo-labs/deity/state';
240
+ *
241
+ * // Basic usage
242
+ * const store = new InMemoryStateStore();
243
+ *
244
+ * // With TTL (entries expire after 1 hour)
245
+ * const cacheStore = new InMemoryStateStore({
246
+ * ttl: 3600000 // 1 hour in ms
247
+ * });
248
+ *
249
+ * // With size limit (max 1000 entries)
250
+ * const limitedStore = new InMemoryStateStore({
251
+ * maxSize: 1000
252
+ * });
253
+ * ```
254
+ *
255
+ * @module state/memory-store
256
+ * @since 3.0.0
257
+ */
258
+
259
+ /**
260
+ * In-memory state store configuration.
261
+ */
262
+ interface InMemoryStateStoreOptions {
263
+ /**
264
+ * Time-to-live in milliseconds.
265
+ * Entries older than this will be automatically deleted.
266
+ * Default: undefined (no expiration)
267
+ */
268
+ ttl?: number;
269
+ /**
270
+ * Maximum number of entries.
271
+ * When limit is reached, oldest entries are evicted (LRU).
272
+ * Default: undefined (no limit)
273
+ */
274
+ maxSize?: number;
275
+ /**
276
+ * Enable automatic cleanup of expired entries.
277
+ * When enabled, runs a cleanup check every cleanupInterval ms.
278
+ * Default: true
279
+ */
280
+ autoCleanup?: boolean;
281
+ /**
282
+ * Cleanup interval in milliseconds.
283
+ * Only used when autoCleanup is enabled.
284
+ * Default: 60000 (1 minute)
285
+ */
286
+ cleanupInterval?: number;
287
+ }
288
+ /**
289
+ * In-memory state store implementation.
290
+ *
291
+ * Stores data in a Map with optional TTL and size limits.
292
+ * All operations are synchronous but wrapped in Promises for API consistency.
293
+ *
294
+ * @example
295
+ * ```typescript
296
+ * // Create store with 5-minute TTL
297
+ * const store = new InMemoryStateStore({
298
+ * ttl: 5 * 60 * 1000,
299
+ * maxSize: 500
300
+ * });
301
+ *
302
+ * // Use like any SimpleStateStore
303
+ * await store.set('session:abc', { userId: 123 });
304
+ * const session = await store.get('session:abc');
305
+ *
306
+ * // Entries expire after 5 minutes
307
+ * await new Promise(resolve => setTimeout(resolve, 5 * 60 * 1000 + 100));
308
+ * const expired = await store.get('session:abc'); // undefined
309
+ * ```
310
+ */
311
+ declare class InMemoryStateStore implements SimpleStateStore {
312
+ private data;
313
+ private options;
314
+ private cleanupTimer?;
315
+ constructor(options?: InMemoryStateStoreOptions);
316
+ /**
317
+ * Get a value by key.
318
+ * Returns undefined if key doesn't exist or has expired.
319
+ */
320
+ get(key: string): Promise<unknown | undefined>;
321
+ /**
322
+ * Set a value for a key.
323
+ * Evicts old entries if size limit is reached.
324
+ */
325
+ set(key: string, value: unknown): Promise<void>;
326
+ /**
327
+ * Delete a value by key.
328
+ */
329
+ delete(key: string): Promise<void>;
330
+ /**
331
+ * Check if a key exists and is not expired.
332
+ */
333
+ has(key: string): Promise<boolean>;
334
+ /**
335
+ * Clear all stored values.
336
+ */
337
+ clear(): Promise<void>;
338
+ /**
339
+ * Get the current number of stored entries (including expired).
340
+ */
341
+ get size(): number;
342
+ /**
343
+ * Get statistics about the store.
344
+ */
345
+ getStats(): {
346
+ totalEntries: number;
347
+ activeEntries: number;
348
+ expiredEntries: number;
349
+ oldestEntry?: number;
350
+ newestEntry?: number;
351
+ };
352
+ /**
353
+ * Manually clean up expired entries.
354
+ * Returns the number of entries removed.
355
+ */
356
+ cleanup(): Promise<number>;
357
+ /**
358
+ * Stop auto-cleanup timer.
359
+ */
360
+ destroy(): void;
361
+ /**
362
+ * Check if an entry has expired.
363
+ */
364
+ private isExpired;
365
+ /**
366
+ * Evict the oldest entry (LRU).
367
+ */
368
+ private evictOldest;
369
+ /**
370
+ * Start automatic cleanup timer.
371
+ */
372
+ private startAutoCleanup;
373
+ }
374
+ /**
375
+ * Create an in-memory state store with default options.
376
+ *
377
+ * @param options - Store configuration options
378
+ * @returns A new InMemoryStateStore instance
379
+ *
380
+ * @example
381
+ * ```typescript
382
+ * // Simple cache with 10-minute TTL
383
+ * const cache = createInMemoryStore({
384
+ * ttl: 10 * 60 * 1000,
385
+ * maxSize: 100
386
+ * });
387
+ * ```
388
+ */
389
+ declare function createInMemoryStore(options?: InMemoryStateStoreOptions): InMemoryStateStore;
390
+
391
+ /**
392
+ * File system implementation of SimpleStateStore.
393
+ *
394
+ * Stores each key-value pair as a separate JSON file.
395
+ * Provides durable storage with atomic write guarantees.
396
+ *
397
+ * ## Features
398
+ *
399
+ * - **Durable**: Data persists across process restarts
400
+ * - **Atomic writes**: Uses write-then-rename for safety
401
+ * - **One file per key**: Simple directory structure
402
+ * - **Safe concurrent access**: Atomic filesystem operations
403
+ *
404
+ * ## Usage
405
+ *
406
+ * ```typescript
407
+ * import { FileSystemStateStore } from '@limo-labs/deity/state';
408
+ *
409
+ * const store = new FileSystemStateStore('./my-data');
410
+ * await store.set('config', { version: '1.0' });
411
+ * const config = await store.get('config');
412
+ * ```
413
+ *
414
+ * ## Directory Structure
415
+ *
416
+ * ```
417
+ * ./my-data/
418
+ * ├── state-config.json
419
+ * ├── state-user-123.json
420
+ * └── state-session-abc.json
421
+ * ```
422
+ *
423
+ * @module state/file-store
424
+ * @since 3.0.0
425
+ */
426
+
427
+ /**
428
+ * File system state store configuration.
429
+ */
430
+ interface FileSystemStateStoreOptions {
431
+ /**
432
+ * Pretty-print JSON files.
433
+ * Makes files human-readable but slightly larger.
434
+ * Default: false
435
+ */
436
+ prettyPrint?: boolean;
437
+ /**
438
+ * File name prefix for state files.
439
+ * Default: "state-"
440
+ */
441
+ filePrefix?: string;
442
+ /**
443
+ * File extension for state files.
444
+ * Default: ".json"
445
+ */
446
+ fileExtension?: string;
447
+ /**
448
+ * Use atomic writes (write to temp file, then rename).
449
+ * Safer but slightly slower.
450
+ * Default: true
451
+ */
452
+ atomicWrites?: boolean;
453
+ }
454
+ /**
455
+ * File system state store implementation.
456
+ *
457
+ * Stores each key as a separate JSON file in a directory.
458
+ * Provides durable, crash-safe storage.
459
+ *
460
+ * @example
461
+ * ```typescript
462
+ * // Create store in './data' directory
463
+ * const store = new FileSystemStateStore('./data');
464
+ *
465
+ * // Store some data
466
+ * await store.set('user:alice', {
467
+ * name: 'Alice',
468
+ * email: 'alice@example.com'
469
+ * });
470
+ *
471
+ * // Retrieve data
472
+ * const user = await store.get('user:alice');
473
+ *
474
+ * // Data persists across restarts
475
+ * ```
476
+ */
477
+ declare class FileSystemStateStore implements SimpleStateStore {
478
+ private directory;
479
+ private options;
480
+ constructor(directory: string, options?: FileSystemStateStoreOptions);
481
+ /**
482
+ * Get a value by key.
483
+ */
484
+ get(key: string): Promise<unknown | undefined>;
485
+ /**
486
+ * Set a value for a key.
487
+ */
488
+ set(key: string, value: unknown): Promise<void>;
489
+ /**
490
+ * Delete a value by key.
491
+ */
492
+ delete(key: string): Promise<void>;
493
+ /**
494
+ * Check if a key exists.
495
+ */
496
+ has(key: string): Promise<boolean>;
497
+ /**
498
+ * Clear all stored values.
499
+ */
500
+ clear(): Promise<void>;
501
+ /**
502
+ * List all keys in the store.
503
+ */
504
+ keys(): Promise<string[]>;
505
+ /**
506
+ * Get statistics about the store.
507
+ */
508
+ getStats(): Promise<{
509
+ totalKeys: number;
510
+ totalSize: number;
511
+ directory: string;
512
+ }>;
513
+ /**
514
+ * Ensure the storage directory exists.
515
+ */
516
+ private ensureDirectory;
517
+ /**
518
+ * Get the file path for a key.
519
+ */
520
+ private getFilePath;
521
+ /**
522
+ * Get a temporary file path for atomic writes.
523
+ */
524
+ private getTempFilePath;
525
+ /**
526
+ * Sanitize a key to be filesystem-safe.
527
+ * Replaces special characters with dashes and hashes long keys.
528
+ */
529
+ private sanitizeKey;
530
+ /**
531
+ * Extract the original key from a file name.
532
+ */
533
+ private keyFromFileName;
534
+ }
535
+ /**
536
+ * Create a file system state store.
537
+ *
538
+ * @param directory - Directory to store state files
539
+ * @param options - Store configuration options
540
+ * @returns A new FileSystemStateStore instance
541
+ *
542
+ * @example
543
+ * ```typescript
544
+ * // Basic usage
545
+ * const store = createFileStore('./data');
546
+ *
547
+ * // With pretty-printed JSON
548
+ * const prettyStore = createFileStore('./data', {
549
+ * prettyPrint: true
550
+ * });
551
+ * ```
552
+ */
553
+ declare function createFileStore(directory: string, options?: FileSystemStateStoreOptions): FileSystemStateStore;
554
+
555
+ /**
556
+ * Adapter for using SimpleStateStore with the full CheckpointStore interface.
557
+ *
558
+ * This adapter wraps a SimpleStateStore and provides the full CheckpointStore
559
+ * API, including checkpoint versioning, metadata, and listing.
560
+ *
561
+ * ## Purpose
562
+ *
563
+ * Allows simple key-value stores to be used with Deity's checkpoint system
564
+ * without implementing the full CheckpointStore interface.
565
+ *
566
+ * ## Usage
567
+ *
568
+ * ```typescript
569
+ * import { createStateStoreAdapter } from '@limo-labs/deity/state';
570
+ * import { createInMemoryStore } from '@limo-labs/deity/helpers';
571
+ *
572
+ * // Create simple store
573
+ * const simpleStore = createInMemoryStore();
574
+ *
575
+ * // Wrap with adapter
576
+ * const checkpointStore = createStateStoreAdapter(simpleStore);
577
+ *
578
+ * // Use as CheckpointStore
579
+ * await checkpointStore.save({
580
+ * id: 'checkpoint-1',
581
+ * version: '1.0.0',
582
+ * label: 'After analysis',
583
+ * state: {},
584
+ * outputs: { result: 42 },
585
+ * timestamp: new Date().toISOString()
586
+ * });
587
+ * ```
588
+ *
589
+ * @module state/adapter
590
+ * @since 3.0.0
591
+ */
592
+
593
+ /**
594
+ * State store adapter implementation.
595
+ *
596
+ * Wraps a SimpleStateStore and implements CheckpointStore by:
597
+ * - Storing checkpoints with a prefix
598
+ * - Maintaining an index of all checkpoints
599
+ * - Providing list/query operations
600
+ *
601
+ * @example
602
+ * ```typescript
603
+ * const simpleStore = createInMemoryStore();
604
+ * const adapter = new StateStoreAdapter(simpleStore);
605
+ *
606
+ * await adapter.save({
607
+ * id: 'cp1',
608
+ * version: '1.0.0',
609
+ * label: 'Start',
610
+ * state: {},
611
+ * outputs: {},
612
+ * timestamp: new Date().toISOString()
613
+ * });
614
+ *
615
+ * const checkpoints = await adapter.list();
616
+ * console.log(checkpoints); // [{ id: 'cp1', ... }]
617
+ * ```
618
+ */
619
+ declare class StateStoreAdapter implements CheckpointStore {
620
+ private store;
621
+ constructor(store: SimpleStateStore);
622
+ /**
623
+ * Save a checkpoint.
624
+ */
625
+ save(checkpoint: StateCheckpoint): Promise<void>;
626
+ /**
627
+ * Load a checkpoint by ID.
628
+ */
629
+ load(checkpointId: string): Promise<StateCheckpoint | undefined>;
630
+ /**
631
+ * List all available checkpoints.
632
+ * Returns checkpoints sorted by timestamp (oldest first).
633
+ */
634
+ list(): Promise<StateCheckpoint[]>;
635
+ /**
636
+ * Get the latest checkpoint (most recent).
637
+ */
638
+ getLatest(): Promise<StateCheckpoint | undefined>;
639
+ /**
640
+ * Delete a checkpoint by ID.
641
+ */
642
+ delete(checkpointId: string): Promise<void>;
643
+ /**
644
+ * Clear all checkpoints.
645
+ */
646
+ clear(): Promise<void>;
647
+ /**
648
+ * Get the storage key for a checkpoint.
649
+ */
650
+ private getCheckpointKey;
651
+ /**
652
+ * Load the checkpoint index.
653
+ */
654
+ private loadIndex;
655
+ /**
656
+ * Save the checkpoint index.
657
+ */
658
+ private saveIndex;
659
+ /**
660
+ * Update the index with a new checkpoint.
661
+ */
662
+ private updateIndex;
663
+ /**
664
+ * Remove a checkpoint from the index.
665
+ */
666
+ private removeFromIndex;
667
+ }
668
+ /**
669
+ * Create a CheckpointStore from a SimpleStateStore.
670
+ *
671
+ * @param store - The simple store to wrap
672
+ * @returns A CheckpointStore adapter
673
+ *
674
+ * @example
675
+ * ```typescript
676
+ * import { createInMemoryStore } from '@limo-labs/deity/helpers';
677
+ * import { createStateStoreAdapter } from '@limo-labs/deity/state';
678
+ *
679
+ * const simpleStore = createInMemoryStore();
680
+ * const checkpointStore = createStateStoreAdapter(simpleStore);
681
+ *
682
+ * // Use with state manager
683
+ * const stateManager = createStateManager({
684
+ * directory: '.deity',
685
+ * version: '1.0.0',
686
+ * checkpointStore // Uses the adapted store
687
+ * });
688
+ * ```
689
+ */
690
+ declare function createStateStoreAdapter(store: SimpleStateStore): CheckpointStore;
691
+ /**
692
+ * Type guard to check if a store is a SimpleStateStore.
693
+ */
694
+ declare function isSimpleStateStore(store: unknown): store is SimpleStateStore;
695
+
696
+ export { type CheckpointStore as C, FileSystemStateStore as F, InMemoryStateStore as I, type StateCheckpoint as S, createInMemoryStore as a, createStateStoreAdapter as b, createFileStore as c, type FileSystemStateStoreOptions as d, type InMemoryStateStoreOptions as e, type SimpleStateStore as f, type SimpleStateStoreWithClear as g, StateStoreAdapter as h, compareVersions as i, isCompatible as j, isSimpleStateStore as k, isValidVersion as l, parseVersion as p };