@asaidimu/utils-workspace 2.0.0 → 2.1.1
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 +283 -249
- package/index.d.mts +676 -204
- package/index.d.ts +676 -204
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/package.json +5 -1
package/index.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { QueryFilter, PaginationOptions } from '@asaidimu/query';
|
|
2
|
+
import { IndexDefinition, SchemaDefinition, SchemaChange, DataTransform } from '@asaidimu/anansi';
|
|
3
|
+
|
|
1
4
|
type UUID = string;
|
|
2
5
|
type Timestamp = string;
|
|
3
6
|
type URI = string;
|
|
@@ -29,7 +32,7 @@ type WorkspaceError = {
|
|
|
29
32
|
};
|
|
30
33
|
interface Settings {
|
|
31
34
|
language: string;
|
|
32
|
-
defaultRole
|
|
35
|
+
defaultRole?: string;
|
|
33
36
|
prompt?: string;
|
|
34
37
|
}
|
|
35
38
|
interface Project {
|
|
@@ -61,8 +64,7 @@ type ResolvedBlob = {
|
|
|
61
64
|
};
|
|
62
65
|
/**
|
|
63
66
|
* Full registry entry for a blob. BlobRef is a Pick of this type, so
|
|
64
|
-
* a BlobRecord is always assignable to BlobRef.
|
|
65
|
-
* removed — callers that previously used BlobSummary use BlobRecord directly.
|
|
67
|
+
* a BlobRecord is always assignable to BlobRef.
|
|
66
68
|
*/
|
|
67
69
|
interface BlobRecord {
|
|
68
70
|
sha256: SHA256;
|
|
@@ -124,11 +126,26 @@ interface Turn {
|
|
|
124
126
|
role: TurnRole;
|
|
125
127
|
blocks: ContentBlock[];
|
|
126
128
|
timestamp: Timestamp;
|
|
129
|
+
/**
|
|
130
|
+
* The name of the role active when this turn was recorded.
|
|
131
|
+
* Snapshot so history is stable even if the role is later renamed.
|
|
132
|
+
*/
|
|
127
133
|
roleSnapshot?: string;
|
|
134
|
+
/**
|
|
135
|
+
* Parent pointer. Null for root turns.
|
|
136
|
+
* This is plain data stored on the document — the DAG is reconstructed
|
|
137
|
+
* in memory by TurnTree.buildNodeGraph() at session open time.
|
|
138
|
+
*/
|
|
128
139
|
parent: {
|
|
129
140
|
id: UUID;
|
|
130
141
|
version: number;
|
|
131
142
|
} | null;
|
|
143
|
+
/**
|
|
144
|
+
* Partition key. Stored on the Turn document so Collection.filter
|
|
145
|
+
* can retrieve all turns for a session in a single query.
|
|
146
|
+
* Not present on Turn objects used purely in memory (e.g. dirty buffer).
|
|
147
|
+
*/
|
|
148
|
+
sessionId?: UUID;
|
|
132
149
|
}
|
|
133
150
|
interface TurnNode {
|
|
134
151
|
id: UUID;
|
|
@@ -145,63 +162,53 @@ interface TurnNode {
|
|
|
145
162
|
children: Record<number, UUID[]>;
|
|
146
163
|
}
|
|
147
164
|
interface BranchInfo {
|
|
148
|
-
/** All sibling versions at this level, in insertion order. */
|
|
149
165
|
versions: number[];
|
|
150
|
-
/** Index of this turn within siblings (0-based). */
|
|
151
166
|
currentIndex: number;
|
|
152
|
-
/** Convenience: number of siblings (siblings.length). */
|
|
153
167
|
total: number;
|
|
154
|
-
/** True when there is a branch to the left. */
|
|
155
168
|
hasPrev: boolean;
|
|
156
|
-
/** True when there is a branch to the right. */
|
|
157
169
|
hasNext: boolean;
|
|
158
170
|
}
|
|
159
|
-
interface
|
|
171
|
+
interface Role {
|
|
160
172
|
name: string;
|
|
161
173
|
label: string;
|
|
162
174
|
description?: string;
|
|
163
|
-
|
|
175
|
+
persona: string;
|
|
176
|
+
preferences: UUID[];
|
|
164
177
|
}
|
|
165
|
-
interface
|
|
178
|
+
interface Preference {
|
|
166
179
|
id: UUID;
|
|
180
|
+
content: string;
|
|
167
181
|
topics: string[];
|
|
168
182
|
timestamp: Timestamp;
|
|
169
|
-
snippet?: string;
|
|
170
183
|
}
|
|
171
|
-
|
|
184
|
+
type ContextContent = {
|
|
185
|
+
kind: 'text';
|
|
186
|
+
value: string;
|
|
187
|
+
} | {
|
|
188
|
+
kind: 'json';
|
|
189
|
+
value: unknown;
|
|
190
|
+
} | {
|
|
191
|
+
kind: 'blob';
|
|
192
|
+
sha256: SHA256;
|
|
193
|
+
mediaType: BlobMediaType;
|
|
194
|
+
sizeBytes: number;
|
|
195
|
+
filename?: string;
|
|
196
|
+
} | {
|
|
197
|
+
kind: 'remote';
|
|
198
|
+
uri: URI;
|
|
199
|
+
mediaType?: BlobMediaType;
|
|
200
|
+
};
|
|
201
|
+
interface Context {
|
|
172
202
|
key: string;
|
|
173
203
|
topics: string[];
|
|
204
|
+
content: ContextContent;
|
|
174
205
|
timestamp: Timestamp;
|
|
175
|
-
mime?: string;
|
|
176
|
-
size?: number;
|
|
177
|
-
preview?: string;
|
|
178
|
-
source?: string;
|
|
179
206
|
metadata?: Record<string, any>;
|
|
180
207
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
metadata?: {
|
|
186
|
-
created?: Timestamp;
|
|
187
|
-
updated?: Timestamp;
|
|
188
|
-
entries?: number;
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
interface Workspace {
|
|
192
|
-
id: UUID;
|
|
193
|
-
settings: Settings;
|
|
194
|
-
project: Project;
|
|
195
|
-
index: Index;
|
|
196
|
-
}
|
|
197
|
-
interface Index {
|
|
198
|
-
format: string;
|
|
199
|
-
roles: Record<string, RoleSummary>;
|
|
200
|
-
preferences: Record<UUID, PreferenceSummary>;
|
|
201
|
-
context: Record<string, ContextSummary>;
|
|
202
|
-
sessions: Record<UUID, SessionMeta>;
|
|
203
|
-
topics: Record<string, TopicIndex>;
|
|
204
|
-
}
|
|
208
|
+
/**
|
|
209
|
+
* SessionMeta is stored as a document in the 'session' collection.
|
|
210
|
+
* The head pointer lives here — no separate session_heads store needed.
|
|
211
|
+
*/
|
|
205
212
|
interface SessionMeta {
|
|
206
213
|
id: UUID;
|
|
207
214
|
label: string;
|
|
@@ -218,69 +225,64 @@ interface SessionMeta {
|
|
|
218
225
|
version: number;
|
|
219
226
|
} | null;
|
|
220
227
|
}
|
|
221
|
-
interface
|
|
222
|
-
id: UUID;
|
|
228
|
+
interface RoleSummary {
|
|
223
229
|
name: string;
|
|
224
230
|
label: string;
|
|
225
|
-
persona: string;
|
|
226
231
|
description?: string;
|
|
227
|
-
|
|
232
|
+
/** Number of preference IDs listed on the role. */
|
|
233
|
+
preferences: number;
|
|
228
234
|
}
|
|
229
|
-
interface
|
|
235
|
+
interface PreferenceSummary {
|
|
230
236
|
id: UUID;
|
|
231
|
-
content: string;
|
|
232
237
|
topics: string[];
|
|
233
238
|
timestamp: Timestamp;
|
|
239
|
+
snippet?: string;
|
|
234
240
|
}
|
|
235
|
-
interface
|
|
241
|
+
interface ContextSummary {
|
|
236
242
|
key: string;
|
|
237
|
-
content: ContextContent;
|
|
238
243
|
topics: string[];
|
|
239
244
|
timestamp: Timestamp;
|
|
245
|
+
mime?: string;
|
|
246
|
+
size?: number;
|
|
247
|
+
preview?: string;
|
|
248
|
+
source?: string;
|
|
240
249
|
metadata?: Record<string, any>;
|
|
241
|
-
remoteIds?: Record<string, string>;
|
|
242
|
-
refCount?: number;
|
|
243
250
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
} | {
|
|
248
|
-
kind: 'json';
|
|
249
|
-
value: object;
|
|
250
|
-
} | {
|
|
251
|
-
kind: 'blob';
|
|
252
|
-
} & BlobRef | {
|
|
253
|
-
kind: 'remote';
|
|
254
|
-
uri: URI;
|
|
255
|
-
mediaType: BlobMediaType;
|
|
256
|
-
};
|
|
257
|
-
interface Session$1 {
|
|
258
|
-
id: UUID;
|
|
259
|
-
label: string;
|
|
260
|
-
role: string;
|
|
261
|
-
topics: string[];
|
|
251
|
+
interface TopicIndex {
|
|
252
|
+
topic: string;
|
|
253
|
+
contextKeys: string[];
|
|
262
254
|
preferences: UUID[];
|
|
263
|
-
|
|
264
|
-
metadata: {
|
|
255
|
+
metadata?: {
|
|
265
256
|
created?: Timestamp;
|
|
266
257
|
updated?: Timestamp;
|
|
258
|
+
entries?: number;
|
|
267
259
|
};
|
|
268
260
|
}
|
|
261
|
+
interface Index {
|
|
262
|
+
roles: Record<string, RoleSummary>;
|
|
263
|
+
preferences: Record<UUID, PreferenceSummary>;
|
|
264
|
+
context: Record<string, ContextSummary>;
|
|
265
|
+
sessions: Record<UUID, SessionMeta>;
|
|
266
|
+
topics: Record<string, TopicIndex>;
|
|
267
|
+
blobs: Record<SHA256, BlobRecord>;
|
|
268
|
+
}
|
|
269
|
+
interface Workspace {
|
|
270
|
+
id: UUID;
|
|
271
|
+
settings: Settings;
|
|
272
|
+
project: Project;
|
|
273
|
+
index: Index;
|
|
274
|
+
}
|
|
269
275
|
interface WorkspaceBundle {
|
|
270
276
|
format: 'aiworkspace/4.0';
|
|
271
277
|
workspace: Workspace;
|
|
272
278
|
roles: Record<string, Role>;
|
|
273
279
|
preferences: Record<UUID, Preference>;
|
|
274
280
|
context: Record<string, Context>;
|
|
275
|
-
sessions: Record<UUID,
|
|
281
|
+
sessions: Record<UUID, SessionMeta & {
|
|
282
|
+
turns: Turn[];
|
|
283
|
+
}>;
|
|
276
284
|
blobs: Record<SHA256, BlobRecord>;
|
|
277
285
|
}
|
|
278
|
-
interface TranscriptWindow {
|
|
279
|
-
sessionId: UUID;
|
|
280
|
-
turns: Turn[];
|
|
281
|
-
flushedCount: number;
|
|
282
|
-
hasMore: boolean;
|
|
283
|
-
}
|
|
284
286
|
interface EffectiveSession {
|
|
285
287
|
session: SessionMeta;
|
|
286
288
|
role: Role;
|
|
@@ -293,7 +295,6 @@ interface CacheConfig {
|
|
|
293
295
|
roles?: number;
|
|
294
296
|
preferences?: number;
|
|
295
297
|
context?: number;
|
|
296
|
-
transcriptWindows?: number;
|
|
297
298
|
}
|
|
298
299
|
interface FlushConfig {
|
|
299
300
|
maxBufferSize: number;
|
|
@@ -302,7 +303,6 @@ interface FlushConfig {
|
|
|
302
303
|
interface ContentStoreConfig {
|
|
303
304
|
cache?: CacheConfig;
|
|
304
305
|
flush?: FlushConfig;
|
|
305
|
-
transcriptWindowSize?: number;
|
|
306
306
|
}
|
|
307
307
|
interface BaseCommand {
|
|
308
308
|
type: string;
|
|
@@ -452,14 +452,16 @@ interface DeleteSession extends BaseCommand {
|
|
|
452
452
|
}
|
|
453
453
|
interface RegisterBlob extends BaseCommand {
|
|
454
454
|
type: 'blob:register';
|
|
455
|
-
payload:
|
|
455
|
+
payload: {
|
|
456
|
+
data: Uint8Array;
|
|
457
|
+
mediaType: BlobMediaType;
|
|
458
|
+
filename?: string;
|
|
459
|
+
};
|
|
456
460
|
}
|
|
457
|
-
interface
|
|
458
|
-
type: 'blob:
|
|
461
|
+
interface RetainBlob extends BaseCommand {
|
|
462
|
+
type: 'blob:retain';
|
|
459
463
|
payload: {
|
|
460
464
|
sha256: SHA256;
|
|
461
|
-
providerId: string;
|
|
462
|
-
fileId: string;
|
|
463
465
|
};
|
|
464
466
|
}
|
|
465
467
|
interface ReleaseBlob extends BaseCommand {
|
|
@@ -468,7 +470,22 @@ interface ReleaseBlob extends BaseCommand {
|
|
|
468
470
|
sha256: SHA256;
|
|
469
471
|
};
|
|
470
472
|
}
|
|
471
|
-
|
|
473
|
+
interface PurgeBlob extends BaseCommand {
|
|
474
|
+
type: 'blob:purge';
|
|
475
|
+
payload: {
|
|
476
|
+
sha256: SHA256;
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
interface RecordBlobRemoteId extends BaseCommand {
|
|
480
|
+
type: 'blob:record_remote_id';
|
|
481
|
+
payload: {
|
|
482
|
+
sha256: SHA256;
|
|
483
|
+
providerId: string;
|
|
484
|
+
fileId: string;
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
type BlobCommand = RegisterBlob | RetainBlob | ReleaseBlob | PurgeBlob | RecordBlobRemoteId;
|
|
488
|
+
type Command = CreateWorkspace | AddRole | UpdateRole | DeleteRole | AddPreference | UpdatePreference | DeletePreference | CreateSession | AddContext | UpdateContext | DeleteContext | AddTurn | EditTurn | BranchTurn | DeleteTurn | SwitchRole | AddSessionTopics | OverrideSessionPreferences | ForkSession | DeleteSession | BlobCommand;
|
|
472
489
|
interface TokenBudget {
|
|
473
490
|
total: number;
|
|
474
491
|
estimator?: (text: string) => number;
|
|
@@ -486,7 +503,7 @@ interface ContextRelevanceConfig {
|
|
|
486
503
|
freshnessHalfLifeDays?: number;
|
|
487
504
|
}
|
|
488
505
|
/**
|
|
489
|
-
*
|
|
506
|
+
* Prompt.transcript.turns is Turn[].
|
|
490
507
|
* Synthetic turns produced by PromptAssembler (summary blocks, truncation
|
|
491
508
|
* notices, referential attachments) carry generated UUIDs and version 0,
|
|
492
509
|
* with parent: null. They are ephemeral — never stored, never patched.
|
|
@@ -515,36 +532,448 @@ interface Prompt {
|
|
|
515
532
|
warnings: string[];
|
|
516
533
|
conflicts: PreferenceConflict[];
|
|
517
534
|
}
|
|
535
|
+
interface TranscriptWindow {
|
|
536
|
+
sessionId: UUID;
|
|
537
|
+
turns: Turn[];
|
|
538
|
+
flushedCount: number;
|
|
539
|
+
hasMore: boolean;
|
|
540
|
+
}
|
|
518
541
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
542
|
+
/**
|
|
543
|
+
* Buffers write operations across one or more stores and commits them atomically.
|
|
544
|
+
*
|
|
545
|
+
* ## How atomicity works
|
|
546
|
+
*
|
|
547
|
+
* ### IndexedDB stores (same database)
|
|
548
|
+
* At commit time, TransactionContext collects the names of every IDB store that
|
|
549
|
+
* received operations, then opens a **single** `IDBTransaction` spanning all of
|
|
550
|
+
* them via `ConnectionManager.openTransaction`. Each store's `executeInTransaction`
|
|
551
|
+
* receives that shared transaction object and performs its writes against it
|
|
552
|
+
* without opening a new transaction of its own. IDB commits or aborts the
|
|
553
|
+
* entire multi-store transaction as one unit.
|
|
554
|
+
*
|
|
555
|
+
* ### MemoryStore
|
|
556
|
+
* MemoryStore's `executeInTransaction` receives `null` for the shared transaction.
|
|
557
|
+
* It applies ops against an internal staging map and returns. If a later
|
|
558
|
+
* participant fails, TransactionContext calls `rollbackMemory` on each
|
|
559
|
+
* MemoryStore that already applied its staged ops. MemoryStore restores its
|
|
560
|
+
* pre-transaction snapshot.
|
|
561
|
+
*
|
|
562
|
+
* ### Mixed (IDB + Memory in the same transaction)
|
|
563
|
+
* All IDB stores are committed first as a single atomic IDB transaction, then
|
|
564
|
+
* each MemoryStore is committed. If a MemoryStore fails after IDB has already
|
|
565
|
+
* committed, the IDB side cannot be rolled back — this is an inherent limitation
|
|
566
|
+
* of mixing two different storage engines. In practice the schema store is
|
|
567
|
+
* always MemoryStore-or-IDB consistently, so mixed transactions should not arise
|
|
568
|
+
* in normal usage.
|
|
569
|
+
*/
|
|
570
|
+
declare class TransactionContext {
|
|
571
|
+
readonly id: string;
|
|
572
|
+
/**
|
|
573
|
+
* Flat list of every operation staged so far, in the order they were added.
|
|
574
|
+
* We keep the store reference alongside the op so commit() can group them.
|
|
575
|
+
*/
|
|
576
|
+
private staged;
|
|
577
|
+
private done;
|
|
578
|
+
constructor();
|
|
579
|
+
/**
|
|
580
|
+
* Stages a single write operation against a store.
|
|
581
|
+
* Does NOT touch the store — no I/O happens until commit().
|
|
582
|
+
*/
|
|
583
|
+
addOp<T extends Record<string, any>>(store: Store<T>, type: "put" | "delete" | "add", data: any): Promise<void>;
|
|
584
|
+
/**
|
|
585
|
+
* Commits all staged operations atomically.
|
|
586
|
+
*
|
|
587
|
+
* For IDB stores: opens one shared IDBTransaction across all participating
|
|
588
|
+
* stores, then dispatches ops to each store's executeInTransaction.
|
|
589
|
+
* For MemoryStores: dispatches sequentially; rolls back on failure.
|
|
590
|
+
*/
|
|
591
|
+
commit(): Promise<void>;
|
|
592
|
+
/**
|
|
593
|
+
* Discards all staged operations. No I/O has occurred so there is nothing
|
|
594
|
+
* to undo — we simply clear the buffer.
|
|
595
|
+
*/
|
|
596
|
+
rollback(): void;
|
|
597
|
+
/**
|
|
598
|
+
* Opens ONE IDBTransaction across all participating IDB stores and lets
|
|
599
|
+
* each store execute its ops against the shared transaction handle.
|
|
600
|
+
*
|
|
601
|
+
* We obtain the IDBDatabase from the first store (they all share the same
|
|
602
|
+
* ConnectionManager / database) and open the transaction ourselves so that
|
|
603
|
+
* the commit/abort lifecycle belongs entirely to this method.
|
|
604
|
+
*/
|
|
605
|
+
private commitIDB;
|
|
606
|
+
/**
|
|
607
|
+
* Commits MemoryStore groups sequentially.
|
|
608
|
+
* Maintains a list of stores that have already applied their ops; if any
|
|
609
|
+
* store throws, all previously-applied stores are rolled back via the
|
|
610
|
+
* store-level `_rollbackMemory(snapshot)` escape hatch.
|
|
611
|
+
*/
|
|
612
|
+
private commitMemory;
|
|
613
|
+
completed(): boolean;
|
|
546
614
|
}
|
|
547
615
|
|
|
616
|
+
interface CursorCallbackResult<T> {
|
|
617
|
+
value: T | null;
|
|
618
|
+
done: boolean;
|
|
619
|
+
offset?: number;
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* Callback function for cursor iteration over store records.
|
|
623
|
+
*
|
|
624
|
+
* @template T - The type of records stored.
|
|
625
|
+
* @param value - The current record value (cloned, not a live reference).
|
|
626
|
+
* @param key - The key (ID) of the current record.
|
|
627
|
+
* @param cursor - The underlying cursor object (implementation-specific; may be `null` in memory adapters).
|
|
628
|
+
* @returns A promise resolving to an object indicating whether iteration should stop,
|
|
629
|
+
* and an optional offset to advance.
|
|
630
|
+
*/
|
|
631
|
+
type CursorCallback<T> = (value: T, key: string | number, cursor: any) => Promise<CursorCallbackResult<T>>;
|
|
632
|
+
/**
|
|
633
|
+
* A generic representation of a key range, replacing the browser-specific IDBKeyRange.
|
|
634
|
+
*/
|
|
635
|
+
interface StoreKeyRange {
|
|
636
|
+
lower?: any;
|
|
637
|
+
upper?: any;
|
|
638
|
+
lowerOpen?: boolean;
|
|
639
|
+
upperOpen?: boolean;
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* A single buffered operation staged inside a TransactionContext.
|
|
643
|
+
* Kept intentionally minimal — the context only needs to know what to
|
|
644
|
+
* replay against a store during commit.
|
|
645
|
+
*/
|
|
646
|
+
type BufferedOperation<T> = {
|
|
647
|
+
type: "add" | "put";
|
|
648
|
+
data: T | T[];
|
|
649
|
+
} | {
|
|
650
|
+
type: "delete";
|
|
651
|
+
data: string | number | (string | number)[];
|
|
652
|
+
};
|
|
653
|
+
/**
|
|
654
|
+
* Storage adapter interface for a single object store (collection).
|
|
655
|
+
*
|
|
656
|
+
* Stores own their indexes. Index lifecycle (create, drop) and index-aware reads
|
|
657
|
+
* (findByIndex) are part of this contract so that both MemoryStore and IndexedDBStore
|
|
658
|
+
* implement them natively — MemoryStore via in-memory index maps, IndexedDB via its
|
|
659
|
+
* native index mechanism.
|
|
660
|
+
*
|
|
661
|
+
* @template T - The type of objects stored. Must include the key path property.
|
|
662
|
+
*/
|
|
663
|
+
interface Store<T extends Record<string, any> = Record<string, any>> {
|
|
664
|
+
/**
|
|
665
|
+
* Returns the name of this store (the IDB object store / collection name).
|
|
666
|
+
* Used by TransactionContext to group operations and open a correctly-scoped
|
|
667
|
+
* multi-store IDB transaction at commit time.
|
|
668
|
+
*/
|
|
669
|
+
name(): string;
|
|
670
|
+
/**
|
|
671
|
+
* Opens the store, ensuring underlying storage structures exist.
|
|
672
|
+
*/
|
|
673
|
+
open(): Promise<void>;
|
|
674
|
+
/**
|
|
675
|
+
* Adds one or more records to the store.
|
|
676
|
+
* If a record does not have a value for the store's key path, an automatic
|
|
677
|
+
* key may be assigned. Throws if a record with the same key already exists.
|
|
678
|
+
*/
|
|
679
|
+
add(data: T | T[]): Promise<string | number | (string | number)[]>;
|
|
680
|
+
/**
|
|
681
|
+
* Removes all records from the store without destroying index structures.
|
|
682
|
+
*/
|
|
683
|
+
clear(): Promise<void>;
|
|
684
|
+
/**
|
|
685
|
+
* Returns the total number of records in the store.
|
|
686
|
+
*/
|
|
687
|
+
count(): Promise<number>;
|
|
688
|
+
/**
|
|
689
|
+
* Deletes one or more records by their keys.
|
|
690
|
+
*/
|
|
691
|
+
delete(id: string | number | (string | number)[]): Promise<void>;
|
|
692
|
+
/**
|
|
693
|
+
* Retrieves a single record by its primary key.
|
|
694
|
+
*/
|
|
695
|
+
getById(id: string | number): Promise<T | undefined>;
|
|
696
|
+
/**
|
|
697
|
+
* Retrieves the first record matching an exact index key (point lookup).
|
|
698
|
+
* Useful for unique indexes — returns the single matching record or undefined.
|
|
699
|
+
*
|
|
700
|
+
* @param indexName - The name of the index to query.
|
|
701
|
+
* @param key - The exact key value to look up.
|
|
702
|
+
*/
|
|
703
|
+
getByIndex(indexName: string, key: any): Promise<T | undefined>;
|
|
704
|
+
/**
|
|
705
|
+
* Retrieves all records from a named index, optionally filtered by a key range.
|
|
706
|
+
* Use this for range scans over an index (e.g. all records where age >= 18).
|
|
707
|
+
*
|
|
708
|
+
* @param indexName - The name of the index to query.
|
|
709
|
+
* @param keyRange - Optional range to filter results.
|
|
710
|
+
*/
|
|
711
|
+
getByKeyRange(indexName: string, keyRange?: StoreKeyRange): Promise<T[]>;
|
|
712
|
+
/**
|
|
713
|
+
* Retrieves all records from the store without index involvement.
|
|
714
|
+
*/
|
|
715
|
+
getAll(): Promise<T[]>;
|
|
716
|
+
/**
|
|
717
|
+
* Inserts or replaces a record. Validates OCC if a record with the same key exists.
|
|
718
|
+
*/
|
|
719
|
+
put(data: T): Promise<string | number>;
|
|
720
|
+
/**
|
|
721
|
+
* Iterates over records using a cursor, allowing early termination and skipping.
|
|
722
|
+
*
|
|
723
|
+
* @param callback - Invoked for each record; return `{ done: true }` to stop,
|
|
724
|
+
* `{ offset: n }` to skip ahead n records.
|
|
725
|
+
* @param direction - Iteration order.
|
|
726
|
+
* @param keyRange - Optional range to restrict iteration.
|
|
727
|
+
*/
|
|
728
|
+
cursor(callback: CursorCallback<T>, direction?: "forward" | "backward", keyRange?: StoreKeyRange): Promise<T | null>;
|
|
729
|
+
/**
|
|
730
|
+
* Executes a batch of write operations atomically within this store.
|
|
731
|
+
* All operations succeed or fail together.
|
|
732
|
+
*
|
|
733
|
+
* Used for standalone (single-store) atomic writes. For cross-store atomicity,
|
|
734
|
+
* use executeInTransaction instead.
|
|
735
|
+
*/
|
|
736
|
+
batch(operations: Array<{
|
|
737
|
+
type: "add" | "put";
|
|
738
|
+
data: T | T[];
|
|
739
|
+
} | {
|
|
740
|
+
type: "delete";
|
|
741
|
+
data: string | number | (string | number)[];
|
|
742
|
+
}>): Promise<void>;
|
|
743
|
+
/**
|
|
744
|
+
* Registers a new index on the store. Idempotent — no-op if the index already exists.
|
|
745
|
+
* For IndexedDB, this triggers a database version upgrade.
|
|
746
|
+
* For MemoryStore, this builds the index map from existing records.
|
|
747
|
+
*
|
|
748
|
+
* @param definition - The full index definition from the schema.
|
|
749
|
+
*/
|
|
750
|
+
createIndex(definition: IndexDefinition): Promise<void>;
|
|
751
|
+
/**
|
|
752
|
+
* Removes a named index from the store.
|
|
753
|
+
* For IndexedDB, this triggers a database version upgrade.
|
|
754
|
+
* For MemoryStore, this drops the in-memory index map.
|
|
755
|
+
*
|
|
756
|
+
* @param name - The index name as declared in IndexDefinition.name.
|
|
757
|
+
*/
|
|
758
|
+
dropIndex(name: string): Promise<void>;
|
|
759
|
+
/**
|
|
760
|
+
* Returns all records matching an exact index key.
|
|
761
|
+
* Unlike getByIndex (which returns only the first match), this returns all matches —
|
|
762
|
+
* essential for non-unique indexes where multiple records share the same indexed value.
|
|
763
|
+
*
|
|
764
|
+
* @param indexName - The name of the index to query.
|
|
765
|
+
* @param value - The exact value to look up.
|
|
766
|
+
*/
|
|
767
|
+
findByIndex(indexName: string, value: any): Promise<T[]>;
|
|
768
|
+
/**
|
|
769
|
+
* Executes a set of buffered operations as part of a cross-store atomic transaction.
|
|
770
|
+
*
|
|
771
|
+
* For IndexedDBStore: `sharedTx` is the single IDBTransaction opened across all
|
|
772
|
+
* participating stores. Operations are applied directly to `sharedTx.objectStore(name)`
|
|
773
|
+
* without opening a new transaction — IDB commits or aborts the whole thing atomically.
|
|
774
|
+
*
|
|
775
|
+
* For MemoryStore: `sharedTx` is null. The store applies ops against its own staging
|
|
776
|
+
* area. The caller (TransactionContext) is responsible for coordinating rollback across
|
|
777
|
+
* all MemoryStores if any participant fails.
|
|
778
|
+
*
|
|
779
|
+
* This method must NOT open, commit, or abort any transaction itself.
|
|
780
|
+
*
|
|
781
|
+
* @param ops - The buffered operations to apply.
|
|
782
|
+
* @param sharedTx - The shared IDBTransaction (IndexedDB only), or null (MemoryStore).
|
|
783
|
+
*/
|
|
784
|
+
executeInTransaction(ops: BufferedOperation<T>[], sharedTx: IDBTransaction | null): Promise<void>;
|
|
785
|
+
}
|
|
786
|
+
interface Collection<T> {
|
|
787
|
+
/**
|
|
788
|
+
* Finds a single document matching the query.
|
|
789
|
+
*/
|
|
790
|
+
find: (query: QueryFilter<T>) => Promise<Document<T> | null>;
|
|
791
|
+
/**
|
|
792
|
+
* Lists documents with pagination. Returns an AsyncIterator so consumers can
|
|
793
|
+
* wrap it in their own iteration protocol (e.g. for-await-of via AsyncIterable).
|
|
794
|
+
*/
|
|
795
|
+
list: (query: PaginationOptions) => Promise<AsyncIterator<Document<T>[]>>;
|
|
796
|
+
/**
|
|
797
|
+
* Filters all documents matching the query.
|
|
798
|
+
*/
|
|
799
|
+
filter: (query: QueryFilter<T>) => Promise<Document<T>[]>;
|
|
800
|
+
/**
|
|
801
|
+
* Creates a new document in the collection.
|
|
802
|
+
*
|
|
803
|
+
* When a TransactionContext is provided the initial store.add is buffered into
|
|
804
|
+
* the transaction rather than written immediately. The document is returned in
|
|
805
|
+
* its fully initialised in-memory state regardless — callers can use it before
|
|
806
|
+
* the transaction commits.
|
|
807
|
+
*
|
|
808
|
+
* @param initial - The initial data for the document.
|
|
809
|
+
* @param tx - Optional transaction to buffer the write into.
|
|
810
|
+
*/
|
|
811
|
+
create: (initial: T, tx?: TransactionContext) => Promise<Document<T>>;
|
|
812
|
+
/**
|
|
813
|
+
* Subscribes to collection-level events.
|
|
814
|
+
*/
|
|
815
|
+
subscribe: (event: CollectionEventType | TelemetryEventType, callback: (event: CollectionEvent<T> | TelemetryEvent) => void) => () => void;
|
|
816
|
+
/**
|
|
817
|
+
* Validates data against the collection's schema.
|
|
818
|
+
*/
|
|
819
|
+
validate(data: Record<string, any>): Promise<{
|
|
820
|
+
value?: any;
|
|
821
|
+
issues: Array<{
|
|
822
|
+
message: string;
|
|
823
|
+
path: Array<string>;
|
|
824
|
+
}>;
|
|
825
|
+
}>;
|
|
826
|
+
invalidate(): void;
|
|
827
|
+
}
|
|
828
|
+
/**
|
|
829
|
+
* Event payload for Collection events.
|
|
830
|
+
*/
|
|
831
|
+
type CollectionEventType = "document:create" | "collection:read" | "migration:start" | "migration:end";
|
|
832
|
+
type CollectionEvent<T> = {
|
|
833
|
+
type: CollectionEventType;
|
|
834
|
+
document?: T;
|
|
835
|
+
model?: string;
|
|
836
|
+
method?: keyof Collection<T>;
|
|
837
|
+
metadata?: Record<string, unknown>;
|
|
838
|
+
timestamp: number;
|
|
839
|
+
};
|
|
840
|
+
interface Database {
|
|
841
|
+
/**
|
|
842
|
+
* Opens an existing collection by name.
|
|
843
|
+
*/
|
|
844
|
+
collection: <T>(schemaName: string) => Promise<Collection<T>>;
|
|
845
|
+
/**
|
|
846
|
+
* Creates a new collection from a schema definition.
|
|
847
|
+
*/
|
|
848
|
+
createCollection: <T>(schema: SchemaDefinition) => Promise<Collection<T>>;
|
|
849
|
+
/**
|
|
850
|
+
* Deletes a collection and its schema record.
|
|
851
|
+
*/
|
|
852
|
+
deleteCollection: (schemaName: string) => Promise<boolean>;
|
|
853
|
+
/**
|
|
854
|
+
* Updates an existing collection's schema record.
|
|
855
|
+
*/
|
|
856
|
+
updateCollection: (schema: SchemaDefinition) => Promise<boolean>;
|
|
857
|
+
/**
|
|
858
|
+
* Migrates an existing collection's data and schema definition.
|
|
859
|
+
* Processes data in a streaming fashion to avoid loading the full collection
|
|
860
|
+
* into memory.
|
|
861
|
+
*/
|
|
862
|
+
migrateCollection: <T>(name: string, opts: CollectionMigrationOptions, batchSize?: number) => Promise<Collection<T>>;
|
|
863
|
+
/**
|
|
864
|
+
* Executes a callback within a TransactionContext.
|
|
865
|
+
* Writes buffered inside the callback are flushed atomically on commit.
|
|
866
|
+
* If the callback throws, the buffer is discarded (no writes are flushed).
|
|
867
|
+
*/
|
|
868
|
+
transaction: (callback: (tx: TransactionContext) => Promise<void>) => Promise<void>;
|
|
869
|
+
/**
|
|
870
|
+
* Subscribes to database-level events.
|
|
871
|
+
*/
|
|
872
|
+
subscribe: (event: DatabaseEventType | "telemetry", callback: (event: DatabaseEvent | TelemetryEvent) => void) => () => void;
|
|
873
|
+
/**
|
|
874
|
+
* Releases in-memory references and event bus subscriptions.
|
|
875
|
+
* Does not delete any persisted data.
|
|
876
|
+
*/
|
|
877
|
+
close: () => void;
|
|
878
|
+
clear: () => Promise<void>;
|
|
879
|
+
/**
|
|
880
|
+
* Ensures a collection exists; creates it if it doesn't. Idempotent.
|
|
881
|
+
*/
|
|
882
|
+
ensureCollection: (schema: SchemaDefinition) => Promise<void>;
|
|
883
|
+
/**
|
|
884
|
+
* Ensures multiple collections exist; creates any that don't. Idempotent.
|
|
885
|
+
*/
|
|
886
|
+
setupCollections: (schemas: SchemaDefinition[]) => Promise<void>;
|
|
887
|
+
}
|
|
888
|
+
type CollectionMigrationOptions = {
|
|
889
|
+
changes: SchemaChange<any>[];
|
|
890
|
+
description: string;
|
|
891
|
+
rollback?: SchemaChange<any>[];
|
|
892
|
+
transform?: string | DataTransform<any, any>;
|
|
893
|
+
};
|
|
894
|
+
type DatabaseEventType = "collection:create" | "collection:delete" | "collection:update" | "collection:read" | "migrate";
|
|
895
|
+
type DatabaseEvent = {
|
|
896
|
+
type: DatabaseEventType;
|
|
897
|
+
schema?: SchemaDefinition | Partial<SchemaDefinition>;
|
|
898
|
+
timestamp: number;
|
|
899
|
+
};
|
|
900
|
+
type Document<T> = {
|
|
901
|
+
readonly [K in keyof T]: T[K];
|
|
902
|
+
} & {
|
|
903
|
+
$id?: string;
|
|
904
|
+
$created?: string | Date;
|
|
905
|
+
$updated?: string | Date;
|
|
906
|
+
$version?: number;
|
|
907
|
+
read: () => Promise<boolean>;
|
|
908
|
+
save: (tx?: TransactionContext) => Promise<boolean>;
|
|
909
|
+
update: (props: Partial<T>, tx?: TransactionContext) => Promise<boolean>;
|
|
910
|
+
delete: (tx?: TransactionContext) => Promise<boolean>;
|
|
911
|
+
subscribe: (event: DocumentEventType | TelemetryEventType, callback: (event: DocumentEvent<T> | TelemetryEvent) => void) => () => void;
|
|
912
|
+
state(): T;
|
|
913
|
+
};
|
|
914
|
+
type DocumentEventType = "document:create" | "document:write" | "document:update" | "document:delete" | "document:read";
|
|
915
|
+
type DocumentEvent<T> = {
|
|
916
|
+
type: DocumentEventType;
|
|
917
|
+
data?: Partial<T>;
|
|
918
|
+
timestamp: number;
|
|
919
|
+
};
|
|
920
|
+
type TelemetryEventType = "telemetry";
|
|
921
|
+
type TelemetryEvent = {
|
|
922
|
+
type: TelemetryEventType;
|
|
923
|
+
method: string;
|
|
924
|
+
timestamp: number;
|
|
925
|
+
source: any;
|
|
926
|
+
metadata: {
|
|
927
|
+
args: any[];
|
|
928
|
+
performance: {
|
|
929
|
+
durationMs: number;
|
|
930
|
+
};
|
|
931
|
+
source: {
|
|
932
|
+
level: "database" | "collection" | "document";
|
|
933
|
+
collection?: string;
|
|
934
|
+
document?: string;
|
|
935
|
+
};
|
|
936
|
+
result?: {
|
|
937
|
+
type: "array" | string;
|
|
938
|
+
size?: number;
|
|
939
|
+
};
|
|
940
|
+
error: {
|
|
941
|
+
message: string;
|
|
942
|
+
name: string;
|
|
943
|
+
stack?: string;
|
|
944
|
+
} | null;
|
|
945
|
+
};
|
|
946
|
+
};
|
|
947
|
+
|
|
948
|
+
interface WorkspaceDatabase {
|
|
949
|
+
/**
|
|
950
|
+
* Open the database. Registers core schemas followed by any extension
|
|
951
|
+
* schemas supplied by the caller (domain plugins).
|
|
952
|
+
*
|
|
953
|
+
* Idempotent — safe to call multiple times; subsequent calls are no-ops
|
|
954
|
+
* if the database is already open.
|
|
955
|
+
*/
|
|
956
|
+
open(extensionSchemas?: SchemaDefinition[]): Promise<void>;
|
|
957
|
+
/**
|
|
958
|
+
* Access a collection by schema name.
|
|
959
|
+
* Throws if the schema has not been registered.
|
|
960
|
+
*/
|
|
961
|
+
collection<T>(schemaName: string): Promise<Collection<T>>;
|
|
962
|
+
/**
|
|
963
|
+
* Close the database connection.
|
|
964
|
+
*/
|
|
965
|
+
close(): void;
|
|
966
|
+
}
|
|
967
|
+
declare function createWorkspaceDatabase(db: Database): WorkspaceDatabase;
|
|
968
|
+
declare const COLLECTIONS: {
|
|
969
|
+
readonly ROLE: "role";
|
|
970
|
+
readonly PREFERENCE: "preference";
|
|
971
|
+
readonly CONTEXT: "context";
|
|
972
|
+
readonly SESSION: "session";
|
|
973
|
+
readonly TURN: "turn";
|
|
974
|
+
};
|
|
975
|
+
type CollectionName = typeof COLLECTIONS[keyof typeof COLLECTIONS];
|
|
976
|
+
|
|
548
977
|
/**
|
|
549
978
|
* Utility type for representing partial updates to the state, allowing deep nesting.
|
|
550
979
|
* It makes all properties optional and applies the same transformation recursively
|
|
@@ -560,65 +989,14 @@ declare function del<T>(): T;
|
|
|
560
989
|
declare const merge: <T extends object>(original: T, changes: DeepPartial<T> | symbol) => T;
|
|
561
990
|
declare function ok<T>(value: T): Result<T, never>;
|
|
562
991
|
declare function err<E = WorkspaceError>(error: E): Result<never, E>;
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
open(): Promise<void>;
|
|
572
|
-
private createSchema;
|
|
573
|
-
close(): void;
|
|
574
|
-
deleteDatabase(): Promise<void>;
|
|
575
|
-
private getDB;
|
|
576
|
-
private readTx;
|
|
577
|
-
private writeTx;
|
|
578
|
-
saveRole(role: Role): Promise<void>;
|
|
579
|
-
loadRole(name: string): Promise<Role | null>;
|
|
580
|
-
deleteRole(name: string): Promise<void>;
|
|
581
|
-
savePreference(preference: Preference): Promise<void>;
|
|
582
|
-
loadPreference(id: UUID): Promise<Preference | null>;
|
|
583
|
-
deletePreference(id: UUID): Promise<void>;
|
|
584
|
-
saveContext(context: Context): Promise<void>;
|
|
585
|
-
loadContext(key: string): Promise<Context | null>;
|
|
586
|
-
loadContextBatch(keys: string[]): Promise<Map<string, Context>>;
|
|
587
|
-
deleteContext(key: string): Promise<void>;
|
|
588
|
-
saveTurn(sessionId: UUID, turn: Turn): Promise<void>;
|
|
589
|
-
loadTurn(sessionId: UUID, turnId: UUID, version: number): Promise<Turn | null>;
|
|
590
|
-
loadAllTurns(sessionId: UUID): Promise<Turn[]>;
|
|
591
|
-
deleteTurn(sessionId: UUID, turnId: UUID, version: number): Promise<void>;
|
|
592
|
-
setSessionHead(sessionId: UUID, head: {
|
|
593
|
-
id: UUID;
|
|
594
|
-
version: number;
|
|
595
|
-
} | null): Promise<void>;
|
|
596
|
-
getSessionHead(sessionId: UUID): Promise<{
|
|
597
|
-
id: UUID;
|
|
598
|
-
version: number;
|
|
599
|
-
} | null>;
|
|
600
|
-
storeBytes(sha256: SHA256, data: Uint8Array): Promise<void>;
|
|
601
|
-
loadBytes(sha256: SHA256): Promise<Uint8Array | null>;
|
|
602
|
-
deleteBytes(sha256: SHA256): Promise<void>;
|
|
603
|
-
exportAllBytes(): Promise<Array<[SHA256, Uint8Array]>>;
|
|
604
|
-
saveWorkspace(state: Workspace): Promise<void>;
|
|
605
|
-
loadWorkspace(): Promise<Workspace | null>;
|
|
606
|
-
exportBundle(): Promise<{
|
|
607
|
-
roles: Record<string, Role>;
|
|
608
|
-
preferences: Record<UUID, Preference>;
|
|
609
|
-
context: Record<string, Context>;
|
|
610
|
-
transcripts: Record<UUID, Turn[]>;
|
|
611
|
-
workspace: Workspace | null;
|
|
612
|
-
}>;
|
|
613
|
-
importBundle(data: {
|
|
614
|
-
roles: Record<string, Role>;
|
|
615
|
-
preferences: Record<UUID, Preference>;
|
|
616
|
-
context: Record<string, Context>;
|
|
617
|
-
transcripts: Record<UUID, Turn[]>;
|
|
618
|
-
workspace?: Workspace;
|
|
619
|
-
}): Promise<void>;
|
|
620
|
-
private getAllFromStore;
|
|
621
|
-
}
|
|
992
|
+
declare function omitNullUndefined<T extends Record<string, any>>(obj: T): Partial<T>;
|
|
993
|
+
declare function createSimpleWorkspace({ name, owner, language }: {
|
|
994
|
+
name: string;
|
|
995
|
+
language: string;
|
|
996
|
+
owner: string;
|
|
997
|
+
}): Workspace;
|
|
998
|
+
declare function extractBlobRecord(patch: DeepPartial<Workspace>): BlobRecord | null;
|
|
999
|
+
declare function extractBlobRef(record: BlobRecord): BlobRef;
|
|
622
1000
|
|
|
623
1001
|
/**
|
|
624
1002
|
* Persistence contract for binary blob content and blob registry records.
|
|
@@ -672,19 +1050,26 @@ interface TurnRef {
|
|
|
672
1050
|
version: number;
|
|
673
1051
|
}
|
|
674
1052
|
declare class TurnTree {
|
|
675
|
-
private readonly
|
|
676
|
-
constructor(
|
|
1053
|
+
private readonly db;
|
|
1054
|
+
constructor(db: WorkspaceDatabase);
|
|
1055
|
+
private turns;
|
|
1056
|
+
private sessions;
|
|
1057
|
+
/**
|
|
1058
|
+
* Compound filter for a specific (sessionId, id, version) tuple.
|
|
1059
|
+
* Uses only declared schema fields — never $id.
|
|
1060
|
+
*/
|
|
1061
|
+
private turnFilter;
|
|
1062
|
+
getHead(sessionId: UUID): Promise<TurnRef | null>;
|
|
1063
|
+
setHead(sessionId: UUID, head: TurnRef | null): Promise<void>;
|
|
677
1064
|
append(sessionId: UUID, turn: Turn): Promise<Turn>;
|
|
678
|
-
appendBatch(sessionId: UUID, turns: Turn[]): Promise<void>;
|
|
1065
|
+
appendBatch(sessionId: UUID, turns: Turn[], finalHead: TurnRef | null): Promise<void>;
|
|
679
1066
|
replaceVersion(sessionId: UUID, newTurn: Turn): Promise<void>;
|
|
680
1067
|
branch(sessionId: UUID, newTurn: Turn): Promise<void>;
|
|
1068
|
+
loadAllTurns(sessionId: UUID): Promise<Turn[]>;
|
|
681
1069
|
getActiveChain(sessionId: UUID, dirtyBuffer?: readonly Turn[]): Promise<Turn[]>;
|
|
682
|
-
countChained(sessionId: UUID, dirtyBuffer?: readonly Turn[]): Promise<number>;
|
|
683
1070
|
buildNodeGraph(sessionId: UUID, dirtyBuffer?: readonly Turn[]): Promise<Record<UUID, TurnNode>>;
|
|
684
1071
|
deleteSubtree(sessionId: UUID, turnId: UUID, version: number, newHead: TurnRef | null): Promise<void>;
|
|
685
1072
|
copyTranscript(sourceSessionId: UUID, targetSessionId: UUID): Promise<void>;
|
|
686
|
-
getHead(sessionId: UUID): Promise<TurnRef | null>;
|
|
687
|
-
setHead(sessionId: UUID, head: TurnRef | null): Promise<void>;
|
|
688
1073
|
}
|
|
689
1074
|
|
|
690
1075
|
declare function computeSHA256(data: Uint8Array): Promise<SHA256>;
|
|
@@ -741,29 +1126,55 @@ declare class BlobStore {
|
|
|
741
1126
|
}
|
|
742
1127
|
|
|
743
1128
|
declare class ContentStore {
|
|
744
|
-
private readonly
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
1129
|
+
private readonly db;
|
|
1130
|
+
readonly tree: TurnTree;
|
|
1131
|
+
readonly blobs: BlobStore;
|
|
1132
|
+
private readonly roleCache;
|
|
1133
|
+
private readonly preferenceCache;
|
|
1134
|
+
private readonly contextCache;
|
|
1135
|
+
/**
|
|
1136
|
+
* Called after any blob registry change with the sha256 and updated
|
|
1137
|
+
* BlobRecord (null on deletion). Wire this to your state manager to
|
|
1138
|
+
* keep Index.blobs current.
|
|
1139
|
+
*
|
|
1140
|
+
* ContentStore sets this on BlobStore.onRegistryChanged internally.
|
|
1141
|
+
* Consumers set this property to receive the forwarded notifications.
|
|
1142
|
+
*/
|
|
1143
|
+
onBlobRegistryChanged?: (sha256: SHA256, record: BlobRecord | null) => void;
|
|
1144
|
+
private constructor();
|
|
1145
|
+
static create(db: WorkspaceDatabase, blobStorage: BlobStorage, config?: ContentStoreConfig): Promise<ContentStore>;
|
|
1146
|
+
private init;
|
|
748
1147
|
getTurnTree(): TurnTree;
|
|
749
1148
|
getRole(name: string): Promise<Result<Role, WorkspaceError>>;
|
|
750
|
-
getPreference(id: UUID): Promise<Result<Preference, WorkspaceError>>;
|
|
751
|
-
getContext(key: string): Promise<Result<Context, WorkspaceError>>;
|
|
752
|
-
getContextByTopics(indexState: Index, topics: string[]): Promise<Context[]>;
|
|
753
1149
|
saveRole(role: Role): Promise<void>;
|
|
754
|
-
savePreference(preference: Preference): Promise<void>;
|
|
755
|
-
saveContext(context: Context): Promise<void>;
|
|
756
1150
|
deleteRole(name: string): Promise<void>;
|
|
1151
|
+
getPreference(id: UUID): Promise<Result<Preference, WorkspaceError>>;
|
|
1152
|
+
savePreference(preference: Preference): Promise<void>;
|
|
757
1153
|
deletePreference(id: UUID): Promise<void>;
|
|
1154
|
+
getContext(key: string): Promise<Result<Context, WorkspaceError>>;
|
|
1155
|
+
saveContext(context: Context): Promise<void>;
|
|
758
1156
|
deleteContext(key: string): Promise<void>;
|
|
1157
|
+
getContextByTopics(indexState: Index, topics: string[]): Promise<Context[]>;
|
|
1158
|
+
saveSession(meta: SessionMeta): Promise<void>;
|
|
1159
|
+
updateSessionMeta(sessionId: UUID, patch: DeepPartial<SessionMeta>): Promise<void>;
|
|
1160
|
+
deleteSession(sessionId: UUID): Promise<void>;
|
|
1161
|
+
registerBlob(data: Uint8Array, mediaType: BlobMediaType, filename?: string): Promise<Result<BlobRef, WorkspaceError>>;
|
|
1162
|
+
retainBlob(sha256: SHA256): Promise<Result<void, WorkspaceError>>;
|
|
1163
|
+
releaseBlob(sha256: SHA256): Promise<Result<void, WorkspaceError>>;
|
|
1164
|
+
purgeBlob(sha256: SHA256): Promise<Result<void, WorkspaceError>>;
|
|
1165
|
+
recordBlobRemoteId(sha256: SHA256, providerId: string, fileId: string): Promise<Result<void, WorkspaceError>>;
|
|
1166
|
+
getBlobRecord(sha256: SHA256): BlobRecord | null;
|
|
1167
|
+
getAllBlobRecords(): Record<SHA256, BlobRecord>;
|
|
1168
|
+
/**
|
|
1169
|
+
* Returns the blob resolver function expected by PromptBuilder.
|
|
1170
|
+
* Closes over the internal BlobStore — no BlobStore reference leaks out.
|
|
1171
|
+
*/
|
|
1172
|
+
getBlobResolver(): BlobStore['resolveRefs'];
|
|
759
1173
|
recordTurn(sessionId: UUID, turn: Turn): Promise<Result<void, WorkspaceError>>;
|
|
760
1174
|
editTurn(sessionId: UUID, turnId: UUID, newBlocks: ContentBlock[], newVersion: number, roleSnapshot?: string): Promise<Result<void, WorkspaceError>>;
|
|
761
1175
|
branchTurn(sessionId: UUID, newTurn: Turn): Promise<Result<void, WorkspaceError>>;
|
|
762
1176
|
deleteTurnSubtree(sessionId: UUID, turnId: UUID, version: number, newHead: TurnRef | null): Promise<Result<void, WorkspaceError>>;
|
|
763
1177
|
copyTranscript(sourceSessionId: UUID, targetSessionId: UUID): Promise<void>;
|
|
764
|
-
storeBytes(sha256: SHA256, data: Uint8Array): Promise<void>;
|
|
765
|
-
loadBytes(sha256: SHA256): Promise<Uint8Array | null>;
|
|
766
|
-
deleteBytes(sha256: SHA256): Promise<void>;
|
|
767
1178
|
resolveSession(workspace: Workspace, sessionId: UUID, transcript?: Turn[]): Promise<Result<EffectiveSession, WorkspaceError>>;
|
|
768
1179
|
}
|
|
769
1180
|
|
|
@@ -771,6 +1182,12 @@ declare function workspaceReducer({ index: state }: Workspace, command: Command)
|
|
|
771
1182
|
|
|
772
1183
|
declare class WorkspaceManager {
|
|
773
1184
|
private readonly contentStore;
|
|
1185
|
+
/**
|
|
1186
|
+
* Called when BlobStore triggers a registry change outside of a dispatch()
|
|
1187
|
+
* call — e.g. eagerEviction deleting a blob on release. The caller should
|
|
1188
|
+
* merge this patch into their Workspace.
|
|
1189
|
+
*/
|
|
1190
|
+
onWorkspacePatch?: (patch: DeepPartial<Workspace>) => void;
|
|
774
1191
|
constructor(contentStore: ContentStore);
|
|
775
1192
|
reduce(workspace: Workspace, command: Command): Result<DeepPartial<Workspace>, WorkspaceError>;
|
|
776
1193
|
dispatch(workspace: Workspace, command: Command): Promise<Result<DeepPartial<Workspace>, WorkspaceError>>;
|
|
@@ -902,18 +1319,6 @@ declare function buildTurnNode(turn: Turn, children?: UUID[]): TurnNode;
|
|
|
902
1319
|
interface SessionManagerConfig {
|
|
903
1320
|
flush?: Partial<FlushConfig>;
|
|
904
1321
|
}
|
|
905
|
-
/**
|
|
906
|
-
* Returned by SessionManager.open().
|
|
907
|
-
*
|
|
908
|
-
* session — the live Session instance. Store this in your component or
|
|
909
|
-
* module; pass it to every subsequent session.* call.
|
|
910
|
-
*
|
|
911
|
-
* patch — a DeepPartial<Workspace> that the caller should merge into
|
|
912
|
-
* their Workspace immediately after open(). Currently empty
|
|
913
|
-
* (the Workspace index already holds SessionMeta), but present
|
|
914
|
-
* for forward compatibility — future versions may update head
|
|
915
|
-
* or flushedTurnCount as part of opening.
|
|
916
|
-
*/
|
|
917
1322
|
interface OpenResult {
|
|
918
1323
|
session: Session;
|
|
919
1324
|
patch: DeepPartial<Workspace>;
|
|
@@ -928,4 +1333,71 @@ declare class SessionManager {
|
|
|
928
1333
|
get workspace(): WorkspaceManager;
|
|
929
1334
|
}
|
|
930
1335
|
|
|
931
|
-
|
|
1336
|
+
/**
|
|
1337
|
+
* In-process implementation backed by plain Maps.
|
|
1338
|
+
* Suitable for development, testing, and server-side runtimes without
|
|
1339
|
+
* access to IndexedDB.
|
|
1340
|
+
*/
|
|
1341
|
+
declare class MemoryBlobStorage implements BlobStorage {
|
|
1342
|
+
private readonly bytes;
|
|
1343
|
+
private readonly records;
|
|
1344
|
+
storeBytes(sha256: SHA256, data: Uint8Array): Promise<void>;
|
|
1345
|
+
loadBytes(sha256: SHA256): Promise<Uint8Array | null>;
|
|
1346
|
+
hasBytes(sha256: SHA256): Promise<boolean>;
|
|
1347
|
+
deleteBytes(sha256: SHA256): Promise<void>;
|
|
1348
|
+
saveRecord(record: BlobRecord): Promise<void>;
|
|
1349
|
+
loadRecord(sha256: SHA256): Promise<BlobRecord | null>;
|
|
1350
|
+
deleteRecord(sha256: SHA256): Promise<void>;
|
|
1351
|
+
listRecords(): Promise<BlobRecord[]>;
|
|
1352
|
+
exportAllBytes(): Promise<Array<[SHA256, Uint8Array]>>;
|
|
1353
|
+
/**
|
|
1354
|
+
* Atomic register for MemoryBlobStorage — sequential ops are atomic
|
|
1355
|
+
* in a single-threaded JS runtime, so this is equivalent to two separate
|
|
1356
|
+
* calls, but we implement it for interface consistency.
|
|
1357
|
+
*/
|
|
1358
|
+
registerBlob(record: BlobRecord, data: Uint8Array): Promise<void>;
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
interface IndexedDBBlobConfig {
|
|
1362
|
+
/** Name of the IndexedDB database. Defaults to 'aiworkspace-blobs'. */
|
|
1363
|
+
dbName?: string;
|
|
1364
|
+
}
|
|
1365
|
+
/**
|
|
1366
|
+
* IndexedDB-backed blob storage.
|
|
1367
|
+
*
|
|
1368
|
+
* Bytes are stored as raw Uint8Array — IndexedDB handles binary natively,
|
|
1369
|
+
* no base64 encoding at rest. This is important for large files.
|
|
1370
|
+
*
|
|
1371
|
+
* Transaction discipline: never await inside an active transaction.
|
|
1372
|
+
* All multi-step operations chain synchronous IDB request handlers
|
|
1373
|
+
* inside a single Promise.
|
|
1374
|
+
*/
|
|
1375
|
+
declare class IndexedDBBlobStorage implements BlobStorage {
|
|
1376
|
+
private readonly dbName;
|
|
1377
|
+
private db;
|
|
1378
|
+
constructor(config?: IndexedDBBlobConfig);
|
|
1379
|
+
open(): Promise<void>;
|
|
1380
|
+
private createSchema;
|
|
1381
|
+
close(): void;
|
|
1382
|
+
deleteDatabase(): Promise<void>;
|
|
1383
|
+
private getDB;
|
|
1384
|
+
private readTx;
|
|
1385
|
+
private writeTx;
|
|
1386
|
+
storeBytes(sha256: SHA256, data: Uint8Array): Promise<void>;
|
|
1387
|
+
loadBytes(sha256: SHA256): Promise<Uint8Array | null>;
|
|
1388
|
+
hasBytes(sha256: SHA256): Promise<boolean>;
|
|
1389
|
+
deleteBytes(sha256: SHA256): Promise<void>;
|
|
1390
|
+
saveRecord(record: BlobRecord): Promise<void>;
|
|
1391
|
+
loadRecord(sha256: SHA256): Promise<BlobRecord | null>;
|
|
1392
|
+
deleteRecord(sha256: SHA256): Promise<void>;
|
|
1393
|
+
listRecords(): Promise<BlobRecord[]>;
|
|
1394
|
+
exportAllBytes(): Promise<Array<[SHA256, Uint8Array]>>;
|
|
1395
|
+
/**
|
|
1396
|
+
* Atomically stores bytes and saves a record together.
|
|
1397
|
+
* Preferred over calling storeBytes + saveRecord separately when both
|
|
1398
|
+
* are new — avoids a window where bytes exist without a record.
|
|
1399
|
+
*/
|
|
1400
|
+
registerBlob(record: BlobRecord, data: Uint8Array): Promise<void>;
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
export { type AddContext, type AddPreference, type AddRole, type AddSessionTopics, type AddTurn, type BaseCommand, type BlobCommand, type BlobMediaType, type BlobRecord, type BlobRef, type BlobStorage, BlobStore, type BlobStoreConfig, type BranchInfo, type BranchTurn, COLLECTIONS, type CacheConfig, type CollectionName, type Command, type ContentBlock, ContentStore, type ContentStoreConfig, type Context, type ContextContent, type ContextRelevanceConfig, type ContextSummary, type CreateSession, type CreateWorkspace, type DeleteContext, type DeletePreference, type DeleteRole, type DeleteSession, type DeleteTurn, type DocumentBlock, type DocumentMediaType, type EditTurn, type EffectiveSession, type FlushConfig, type ForkSession, type ImageBlock, type ImageMediaType, type Index, type IndexedDBBlobConfig, IndexedDBBlobStorage, MemoryBlobStorage, type OpenResult, type OverrideSessionPreferences, type Preference, type PreferenceConflict, type PreferenceSummary, type Project, type Prompt, PromptBuilder, type PurgeBlob, type RecordBlobRemoteId, type RegisterBlob, type ReleaseBlob, type ResolvedBlob, type Result, type RetainBlob, type Role, type RoleSummary, type RoleTransitionBlock, type SHA256, Session, SessionManager, type SessionManagerConfig, type SessionMeta, type Settings, type SummaryBlock, type SwitchRole, type TextBlock, type ThinkingBlock, type Timestamp, type TokenBudget, type ToolResultBlock, type ToolUseBlock, type TopicIndex, type TranscriptWindow, type Turn, type TurnNode, type TurnRef, type TurnRole, TurnTree, type URI, type UUID, type UpdateContext, type UpdatePreference, type UpdateRole, type Workspace, type WorkspaceBundle, type WorkspaceDatabase, type WorkspaceError, WorkspaceManager, buildTurnNode, computeSHA256, createSimpleWorkspace, createWorkspaceDatabase, del, err, extractBlobRecord, extractBlobRef, merge, ok, omitNullUndefined, workspaceReducer };
|