@fortemi/core 2026.5.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.
@@ -0,0 +1,2375 @@
1
+ import { PGlite } from '@electric-sql/pglite';
2
+ import { z, ZodType } from 'zod';
3
+
4
+ /**
5
+ * Generate a RFC 9562 UUIDv7 identifier.
6
+ *
7
+ * UUIDv7 embeds a Unix timestamp in the high bits, making IDs
8
+ * time-sortable and monotonic within the same millisecond.
9
+ */
10
+ declare function generateId(): string;
11
+
12
+ /**
13
+ * Typed event bus with IDisposable subscriptions (Monaco-style).
14
+ * SSE-style pub/sub across all layers.
15
+ *
16
+ * Features:
17
+ * - Exact event subscriptions via on() and once()
18
+ * - Wildcard prefix subscriptions: on('note.*', handler)
19
+ * - Cross-context bridging via bridge(port: MessagePort)
20
+ */
21
+ interface IDisposable {
22
+ dispose(): void;
23
+ }
24
+ interface EventMap {
25
+ 'note.created': {
26
+ id: string;
27
+ };
28
+ 'note.updated': {
29
+ id: string;
30
+ };
31
+ 'note.deleted': {
32
+ id: string;
33
+ };
34
+ 'note.restored': {
35
+ id: string;
36
+ };
37
+ 'note.revised': {
38
+ id: string;
39
+ revisionNumber: number;
40
+ };
41
+ 'search.reindexed': Record<string, never>;
42
+ 'embedding.ready': {
43
+ noteId: string;
44
+ };
45
+ 'capability.ready': {
46
+ name: string;
47
+ };
48
+ 'capability.disabled': {
49
+ name: string;
50
+ };
51
+ 'capability.loading': {
52
+ name: string;
53
+ progress?: number;
54
+ };
55
+ 'job.completed': {
56
+ id: string;
57
+ noteId: string;
58
+ type: string;
59
+ };
60
+ 'job.failed': {
61
+ id: string;
62
+ noteId: string;
63
+ type: string;
64
+ error: string;
65
+ };
66
+ 'archive.switched': {
67
+ name: string;
68
+ };
69
+ 'migration.applied': {
70
+ version: number;
71
+ };
72
+ 'provider.added': {
73
+ id: string;
74
+ name: string;
75
+ };
76
+ 'provider.removed': {
77
+ id: string;
78
+ };
79
+ 'provider.active': {
80
+ id: string;
81
+ name: string;
82
+ };
83
+ 'provider.fallback': {
84
+ fromProvider: string;
85
+ toProvider: string;
86
+ errorCategory: string;
87
+ error: string;
88
+ };
89
+ 'provider.cooldown': {
90
+ providerId: string;
91
+ errorCategory: string;
92
+ cooldownMs: number;
93
+ expiresAt: number;
94
+ };
95
+ }
96
+ type EventHandler<T> = (payload: T) => void;
97
+ /** Wildcard pattern: a string literal ending with '.*' */
98
+ type WildcardPattern = `${string}.*`;
99
+ declare class TypedEventBus {
100
+ private listeners;
101
+ private wildcardListeners;
102
+ on<K extends keyof EventMap>(event: K, handler: EventHandler<EventMap[K]>): IDisposable;
103
+ on(pattern: WildcardPattern, handler: EventHandler<unknown>): IDisposable;
104
+ private _onExact;
105
+ private _onWildcard;
106
+ once<K extends keyof EventMap>(event: K, handler: EventHandler<EventMap[K]>): IDisposable;
107
+ emit<K extends keyof EventMap>(event: K, payload: EventMap[K]): void;
108
+ bridge(port: MessagePort): IDisposable;
109
+ removeAllListeners(): void;
110
+ }
111
+
112
+ /**
113
+ * PGlite database factory.
114
+ * Enforces PGlite 0.4.x conventions (explicit database: 'postgres').
115
+ * Selects persistence adapter based on config.
116
+ */
117
+
118
+ type PersistenceMode = 'opfs' | 'idb' | 'memory';
119
+ declare function createPGliteInstance(persistence: PersistenceMode, archiveName?: string): Promise<PGlite>;
120
+
121
+ interface QueryResult<T = Record<string, unknown>> {
122
+ rows: T[];
123
+ fields?: Array<{
124
+ name: string;
125
+ dataTypeID: number;
126
+ }>;
127
+ }
128
+ interface QueryExecutor {
129
+ query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<QueryResult<T>>;
130
+ exec(sql: string): Promise<unknown>;
131
+ }
132
+ interface DatabaseClient extends QueryExecutor {
133
+ transaction<T>(fn: (tx: QueryExecutor) => Promise<T>): Promise<T>;
134
+ }
135
+ interface StorageBackend extends DatabaseClient {
136
+ readonly id: string;
137
+ readonly mode: 'readwrite' | 'readonly';
138
+ close(): Promise<void>;
139
+ }
140
+ interface StorageOpenRequest {
141
+ archiveName: string;
142
+ persistence: PersistenceMode;
143
+ }
144
+ interface StorageBackendFactory {
145
+ open(input: StorageOpenRequest): Promise<StorageBackend>;
146
+ }
147
+ interface StorageTopology {
148
+ primary: StorageBackend;
149
+ secondary?: StorageBackend;
150
+ policy: 'primary-only' | 'read-through-secondary' | 'explicit-replication';
151
+ }
152
+ declare class PGliteStorageBackend implements StorageBackend {
153
+ readonly id: string;
154
+ private db;
155
+ readonly mode = "readwrite";
156
+ constructor(id: string, db: PGlite);
157
+ query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<QueryResult<T>>;
158
+ exec(sql: string): Promise<unknown>;
159
+ transaction<T>(fn: (tx: QueryExecutor) => Promise<T>): Promise<T>;
160
+ close(): Promise<void>;
161
+ }
162
+ declare class PGliteStorageBackendFactory implements StorageBackendFactory {
163
+ open(input: StorageOpenRequest): Promise<StorageBackend>;
164
+ }
165
+ declare const defaultStorageBackendFactory: PGliteStorageBackendFactory;
166
+
167
+ /**
168
+ * Capability module system (ADR-002).
169
+ * Tracks opt-in WASM module states. No WASM loaded by default (CAP-001).
170
+ *
171
+ * State machine (valid transitions):
172
+ * unloaded -> loading (via enable)
173
+ * loading -> ready (via markReady or successful loader)
174
+ * loading -> error (via markError or failed loader)
175
+ * ready -> disabled (via disable)
176
+ * disabled -> loading (via enable, re-enable)
177
+ * error -> loading (via enable, retry)
178
+ */
179
+
180
+ type CapabilityState = 'unloaded' | 'loading' | 'ready' | 'error' | 'disabled';
181
+ type CapabilityName = 'semantic' | 'llm' | 'audio' | 'vision' | 'pdf';
182
+ declare class CapabilityManager {
183
+ private events;
184
+ private capabilities;
185
+ private loaders;
186
+ private progressMessages;
187
+ constructor(events: TypedEventBus);
188
+ /**
189
+ * Register an async loader for a capability.
190
+ * Called by enable(); if no loader is registered the capability transitions
191
+ * directly to ready (useful for capabilities that require no async init).
192
+ */
193
+ registerLoader(name: CapabilityName, loader: () => Promise<void>): void;
194
+ getState(name: CapabilityName): CapabilityState;
195
+ isReady(name: CapabilityName): boolean;
196
+ /**
197
+ * Enable a capability.
198
+ * Valid from: unloaded, disabled, error (retry).
199
+ * Runs the registered loader if present; transitions to ready on success,
200
+ * error on failure.
201
+ */
202
+ enable(name: CapabilityName): Promise<void>;
203
+ /**
204
+ * Disable a ready capability.
205
+ * Valid from: ready only.
206
+ */
207
+ disable(name: CapabilityName): void;
208
+ /**
209
+ * Mark a loading capability as ready (external use, e.g. bridge protocol).
210
+ * Valid from: loading only.
211
+ */
212
+ markReady(name: CapabilityName): void;
213
+ /**
214
+ * Mark a loading capability as errored (external use, e.g. bridge protocol).
215
+ * Valid from: loading only.
216
+ */
217
+ markError(name: CapabilityName, error: string): void;
218
+ /**
219
+ * Report loading progress (0-100).
220
+ * Emits capability.loading with progress if the capability is currently loading.
221
+ * No-op if the capability is not in loading state.
222
+ */
223
+ reportProgress(name: CapabilityName, progress: number): void;
224
+ /** Set a human-readable progress message for a loading capability */
225
+ setProgress(name: CapabilityName, message: string): void;
226
+ /** Get the current progress message for a capability */
227
+ getProgress(name: CapabilityName): string | undefined;
228
+ getError(name: CapabilityName): string | undefined;
229
+ listAll(): Array<{
230
+ name: CapabilityName;
231
+ state: CapabilityState;
232
+ }>;
233
+ }
234
+
235
+ /**
236
+ * Sequential SQL migration runner for DatabaseClient.
237
+ * Tracks applied migrations in a schema_version table.
238
+ * Each migration runs in a transaction; version updated atomically.
239
+ */
240
+
241
+ interface Migration {
242
+ version: number;
243
+ name: string;
244
+ sql: string;
245
+ }
246
+ declare class MigrationRunner {
247
+ private db;
248
+ private events?;
249
+ constructor(db: DatabaseClient, events?: TypedEventBus | undefined);
250
+ ensureSchemaTable(): Promise<void>;
251
+ getCurrentVersion(): Promise<number>;
252
+ apply(migrations: Migration[]): Promise<number>;
253
+ getAppliedMigrations(): Promise<Array<{
254
+ version: number;
255
+ name: string;
256
+ }>>;
257
+ }
258
+
259
+ declare const allMigrations: Migration[];
260
+
261
+ /**
262
+ * Multi-archive manager for Fortemi.
263
+ * Each archive is a separate PGlite instance with its own persistence path.
264
+ * Migrations are applied automatically on open.
265
+ */
266
+
267
+ interface ArchiveInfo {
268
+ name: string;
269
+ createdAt: string;
270
+ }
271
+ declare class ArchiveManager {
272
+ private events?;
273
+ private currentArchive;
274
+ private db;
275
+ private archives;
276
+ private persistence;
277
+ private backendFactory;
278
+ constructor(persistenceOrFactory: PersistenceMode | StorageBackendFactory, events?: TypedEventBus | undefined);
279
+ getCurrentArchiveName(): string;
280
+ getDb(): StorageBackend | null;
281
+ open(archiveName?: string): Promise<StorageBackend>;
282
+ create(archiveName: string): Promise<StorageBackend>;
283
+ switchTo(archiveName: string): Promise<StorageBackend>;
284
+ delete(archiveName: string): Promise<void>;
285
+ listArchives(): ArchiveInfo[];
286
+ close(): Promise<void>;
287
+ }
288
+
289
+ /**
290
+ * Factory function for creating a FortemiCore instance.
291
+ * All deployment modes use this entry point.
292
+ */
293
+
294
+ interface FortemiConfig {
295
+ persistence: 'opfs' | 'idb' | 'memory';
296
+ archiveName?: string;
297
+ }
298
+ interface FortemiCore {
299
+ events: TypedEventBus;
300
+ config: FortemiConfig;
301
+ destroy(): void;
302
+ }
303
+ declare function createFortemi(config: FortemiConfig): FortemiCore;
304
+
305
+ /**
306
+ * Compute a SHA-256 content hash for the given byte array.
307
+ *
308
+ * Returns a string in `algorithm:hex` format to match the server-side
309
+ * convention, e.g. `sha256:a3b4c5...` (64 hex characters after the prefix).
310
+ *
311
+ * @param data - Raw bytes to hash
312
+ * @returns `'sha256:<64-char lowercase hex>'`
313
+ */
314
+ declare function computeHash(data: Uint8Array): string;
315
+
316
+ interface SWRegistrationResult {
317
+ registered: boolean;
318
+ registration?: ServiceWorkerRegistration;
319
+ error?: string;
320
+ }
321
+ declare function registerServiceWorker(swUrl?: string): Promise<SWRegistrationResult>;
322
+
323
+ /**
324
+ * REST route definitions for Service Worker.
325
+ * These are pure functions that transform HTTP Request → tool input and tool output → Response.
326
+ * The actual DB connection is injected at registration time.
327
+ *
328
+ * All routes currently return 503 Not Implemented — the DB wiring happens in a later issue.
329
+ * The URL structure and request/response shapes are the valuable contract defined here.
330
+ */
331
+ interface RouteHandler {
332
+ method: string;
333
+ pattern: RegExp;
334
+ handler: (request: Request, match: RegExpMatchArray, params: URLSearchParams) => Promise<Response>;
335
+ }
336
+ /**
337
+ * Create route handlers.
338
+ * db parameter will be injected when the SW gets access to PGlite.
339
+ * For now, returns 503 Not Implemented for all routes.
340
+ */
341
+ declare function createRoutes(): RouteHandler[];
342
+ /**
343
+ * Match a request against the registered routes and return the first matching
344
+ * handler, or null if no route matches.
345
+ */
346
+ declare function matchRoute(routes: RouteHandler[], request: Request, url: URL): RouteHandler | null;
347
+
348
+ /**
349
+ * Content-addressable blob storage.
350
+ *
351
+ * Path format: blobs/{dir1}/{dir2}/{hash}
352
+ * dir1 = first 2 hex chars of hash
353
+ * dir2 = next 2 hex chars of hash
354
+ * filename = full hash
355
+ *
356
+ * Two implementations are provided:
357
+ * - OpfsBlobStore — Origin Private File System (Chrome/Edge 86+)
358
+ * - IdbBlobStore — IndexedDB fallback (Firefox, Safari)
359
+ *
360
+ * Use createBlobStore() to get the best available implementation.
361
+ * Export MemoryBlobStore for use in tests.
362
+ */
363
+ interface BlobStore {
364
+ write(hash: string, data: Uint8Array): Promise<void>;
365
+ read(hash: string): Promise<Uint8Array | null>;
366
+ remove(hash: string): Promise<void>;
367
+ exists(hash: string): Promise<boolean>;
368
+ }
369
+ declare class MemoryBlobStore implements BlobStore {
370
+ private store;
371
+ write(hash: string, data: Uint8Array): Promise<void>;
372
+ read(hash: string): Promise<Uint8Array | null>;
373
+ remove(hash: string): Promise<void>;
374
+ exists(hash: string): Promise<boolean>;
375
+ }
376
+ declare function createBlobStore(archiveName: string): BlobStore;
377
+
378
+ /**
379
+ * Shared postMessage protocol types for the PGlite worker.
380
+ *
381
+ * WorkerRequest — messages sent from the client to the worker.
382
+ * WorkerResponse — messages sent from the worker back to the client.
383
+ *
384
+ * Every request carries a unique `id` that the worker echoes in its response,
385
+ * allowing the client to correlate replies with pending promises.
386
+ * The READY broadcast is the only message without an `id` — it is sent once
387
+ * on startup before any requests are processed.
388
+ */
389
+ /** Messages from client to worker */
390
+ type WorkerRequest = {
391
+ id: string;
392
+ type: 'QUERY';
393
+ sql: string;
394
+ params?: unknown[];
395
+ } | {
396
+ id: string;
397
+ type: 'EXEC';
398
+ sql: string;
399
+ } | {
400
+ id: string;
401
+ type: 'BEGIN';
402
+ isolationLevel?: string;
403
+ } | {
404
+ id: string;
405
+ type: 'COMMIT';
406
+ txId: string;
407
+ } | {
408
+ id: string;
409
+ type: 'ROLLBACK';
410
+ txId: string;
411
+ } | {
412
+ id: string;
413
+ type: 'TX_QUERY';
414
+ txId: string;
415
+ sql: string;
416
+ params?: unknown[];
417
+ } | {
418
+ id: string;
419
+ type: 'TX_EXEC';
420
+ txId: string;
421
+ sql: string;
422
+ } | {
423
+ id: string;
424
+ type: 'CLOSE';
425
+ } | {
426
+ id: string;
427
+ type: 'PING';
428
+ };
429
+ /** Messages from worker to client */
430
+ type WorkerResponse = {
431
+ id: string;
432
+ type: 'RESULT';
433
+ rows: unknown[];
434
+ fields?: Array<{
435
+ name: string;
436
+ dataTypeID: number;
437
+ }>;
438
+ } | {
439
+ id: string;
440
+ type: 'EXEC_DONE';
441
+ affectedRows?: number;
442
+ } | {
443
+ id: string;
444
+ type: 'TX_STARTED';
445
+ txId: string;
446
+ } | {
447
+ id: string;
448
+ type: 'TX_DONE';
449
+ } | {
450
+ id: string;
451
+ type: 'ERROR';
452
+ error: string;
453
+ } | {
454
+ id: string;
455
+ type: 'PONG';
456
+ } | {
457
+ type: 'READY';
458
+ };
459
+
460
+ /**
461
+ * Type-safe client for the PGlite Worker.
462
+ *
463
+ * PGliteWorkerClient wraps a Worker instance and exposes the same surface as
464
+ * PGlite (query / exec / transaction) but serialises every call to a typed
465
+ * postMessage exchange. Each outgoing request is tagged with a UUIDv7 `id`;
466
+ * the worker echoes that id in its reply so the client can resolve or reject
467
+ * the matching Promise.
468
+ *
469
+ * TransactionProxy is a lightweight wrapper handed to the callback in
470
+ * transaction(), forwarding TX_QUERY / TX_EXEC messages with the active txId.
471
+ */
472
+ declare class PGliteWorkerClient {
473
+ private worker;
474
+ private pending;
475
+ private readyPromise;
476
+ private resolveReady;
477
+ constructor(worker: Worker);
478
+ /** Resolves when the worker broadcasts READY after database initialisation. */
479
+ waitReady(): Promise<void>;
480
+ private send;
481
+ query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<{
482
+ rows: T[];
483
+ fields?: Array<{
484
+ name: string;
485
+ dataTypeID: number;
486
+ }>;
487
+ }>;
488
+ exec(sql: string): Promise<void>;
489
+ transaction<T>(fn: (tx: TransactionProxy) => Promise<T>): Promise<T>;
490
+ /** Forward TX_QUERY for TransactionProxy — not part of the public surface. */
491
+ _txQuery<T>(txId: string, sql: string, params?: unknown[]): Promise<{
492
+ rows: T[];
493
+ }>;
494
+ /** Forward TX_EXEC for TransactionProxy — not part of the public surface. */
495
+ _txExec(txId: string, sql: string): Promise<void>;
496
+ ping(): Promise<void>;
497
+ close(): Promise<void>;
498
+ }
499
+ /** Proxy passed to the transaction callback — scopes queries to the active txId. */
500
+ declare class TransactionProxy {
501
+ private client;
502
+ private txId;
503
+ constructor(client: PGliteWorkerClient, txId: string);
504
+ query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<{
505
+ rows: T[];
506
+ }>;
507
+ exec(sql: string): Promise<void>;
508
+ }
509
+
510
+ /**
511
+ * Shared types for repository layer.
512
+ * All repository methods use these types as inputs and outputs.
513
+ */
514
+ interface NoteSummary {
515
+ id: string;
516
+ title: string | null;
517
+ format: string;
518
+ source: string;
519
+ visibility: string;
520
+ is_starred: boolean;
521
+ is_pinned: boolean;
522
+ is_archived: boolean;
523
+ created_at: Date;
524
+ updated_at: Date;
525
+ deleted_at: Date | null;
526
+ tags: string[];
527
+ }
528
+ interface NoteFull extends NoteSummary {
529
+ archive_id: string | null;
530
+ revision_mode: string;
531
+ original: {
532
+ id: string;
533
+ content: string;
534
+ content_hash: string;
535
+ created_at: Date;
536
+ };
537
+ current: {
538
+ content: string;
539
+ ai_metadata: unknown | null;
540
+ generation_count: number;
541
+ model: string | null;
542
+ is_user_edited: boolean;
543
+ updated_at: Date;
544
+ };
545
+ }
546
+ interface NoteCreateInput {
547
+ content: string;
548
+ title?: string;
549
+ format?: string;
550
+ source?: string;
551
+ visibility?: string;
552
+ tags?: string[];
553
+ archive_id?: string;
554
+ }
555
+ interface NoteUpdateInput {
556
+ title?: string;
557
+ content?: string;
558
+ format?: string;
559
+ visibility?: string;
560
+ }
561
+ interface NoteListOptions {
562
+ limit?: number;
563
+ offset?: number;
564
+ sort?: 'created_at' | 'updated_at' | 'title';
565
+ order?: 'asc' | 'desc';
566
+ is_starred?: boolean;
567
+ is_pinned?: boolean;
568
+ is_archived?: boolean;
569
+ include_deleted?: boolean;
570
+ include_archived?: boolean;
571
+ collection_id?: string;
572
+ tags?: string[];
573
+ }
574
+ interface PaginatedResult<T> {
575
+ items: T[];
576
+ total: number;
577
+ limit: number;
578
+ offset: number;
579
+ }
580
+ interface SearchResult {
581
+ id: string;
582
+ title: string | null;
583
+ snippet: string;
584
+ rank: number;
585
+ created_at: Date;
586
+ updated_at: Date;
587
+ tags: string[];
588
+ has_embedding?: boolean;
589
+ }
590
+ interface SearchFacets {
591
+ tags: {
592
+ tag: string;
593
+ count: number;
594
+ }[];
595
+ collections: {
596
+ id: string;
597
+ name: string;
598
+ count: number;
599
+ }[];
600
+ }
601
+ interface SearchResponse {
602
+ results: SearchResult[];
603
+ total: number;
604
+ query: string;
605
+ mode: 'text' | 'semantic' | 'hybrid';
606
+ semantic_available: boolean;
607
+ limit: number;
608
+ offset: number;
609
+ facets?: SearchFacets;
610
+ }
611
+ interface SearchOptions {
612
+ limit?: number;
613
+ offset?: number;
614
+ tags?: string[];
615
+ collection_id?: string;
616
+ date_from?: Date;
617
+ date_to?: Date;
618
+ is_starred?: boolean;
619
+ is_archived?: boolean;
620
+ format?: string;
621
+ source?: string;
622
+ visibility?: string;
623
+ include_facets?: boolean;
624
+ mode?: 'text' | 'semantic' | 'hybrid' | 'auto';
625
+ }
626
+ interface NoteRevision {
627
+ id: string;
628
+ note_id: string;
629
+ revision_number: number;
630
+ type: string;
631
+ content: string;
632
+ ai_metadata: unknown | null;
633
+ model: string | null;
634
+ created_at: Date;
635
+ }
636
+
637
+ /**
638
+ * NotesRepository — CRUD and lifecycle operations for the note entity.
639
+ *
640
+ * Responsibilities:
641
+ * - Create notes with immutable original content and mutable current revision
642
+ * - Manage note lifecycle: soft-delete, restore, star, pin, archive
643
+ * - List notes with filtering, pagination, and sorting
644
+ * - Emit domain events via TypedEventBus on every mutation
645
+ */
646
+
647
+ declare class NotesRepository {
648
+ private db;
649
+ private events?;
650
+ constructor(db: DatabaseClient, events?: TypedEventBus | undefined);
651
+ /**
652
+ * Create a new note with its original content record, current revision,
653
+ * optional tags, and an auto-queued title_generation job when no title
654
+ * is provided.
655
+ *
656
+ * All writes happen in a single transaction.
657
+ */
658
+ create(input: NoteCreateInput): Promise<NoteFull>;
659
+ /**
660
+ * Fetch a single note by its ID.
661
+ * Returns NoteFull which includes original content, current revision, and tags.
662
+ * Throws when the note does not exist.
663
+ */
664
+ get(id: string): Promise<NoteFull>;
665
+ /**
666
+ * List notes with optional filtering, sorting, and pagination.
667
+ * Excludes soft-deleted notes by default (pass include_deleted: true to override).
668
+ */
669
+ list(options?: NoteListOptions): Promise<PaginatedResult<NoteSummary>>;
670
+ /**
671
+ * Update mutable note fields.
672
+ * When content changes, the previous current content is saved as a numbered
673
+ * revision before the new content is applied.
674
+ */
675
+ update(id: string, input: NoteUpdateInput): Promise<NoteFull>;
676
+ /**
677
+ * Soft-delete a note by setting deleted_at to the current timestamp.
678
+ */
679
+ delete(id: string): Promise<void>;
680
+ /**
681
+ * Restore a soft-deleted note by clearing deleted_at.
682
+ */
683
+ restore(id: string): Promise<NoteFull>;
684
+ /**
685
+ * Toggle the is_starred field on a note.
686
+ */
687
+ star(id: string, starred: boolean): Promise<void>;
688
+ /**
689
+ * Toggle the is_pinned field on a note.
690
+ */
691
+ pin(id: string, pinned: boolean): Promise<void>;
692
+ /**
693
+ * Toggle the is_archived field on a note.
694
+ */
695
+ archive(id: string, archived: boolean): Promise<void>;
696
+ /**
697
+ * Get revision history for a note, ordered by revision_number descending.
698
+ */
699
+ getRevisions(noteId: string): Promise<NoteRevision[]>;
700
+ }
701
+
702
+ /**
703
+ * SearchRepository — full-text search using DatabaseClient tsvector/tsquery,
704
+ * with optional semantic search (pgvector) and hybrid (BM25 + vector RRF).
705
+ *
706
+ * Search strategy:
707
+ * - Title match uses the STORED tsvector column (weight A).
708
+ * - Content match uses an ad-hoc to_tsvector on note_revised_current.content (weight B).
709
+ * - ts_rank combines both weighted vectors to rank title matches higher.
710
+ * - ts_headline generates highlighted snippets from content.
711
+ * - Empty / whitespace-only queries fall back to returning recent notes.
712
+ * - semanticSearch uses pgvector cosine distance (<=>).
713
+ * - hybridSearch combines BM25 and vector with Reciprocal Rank Fusion (k=60).
714
+ * - Quoted phrases use phraseto_tsquery for exact phrase matching.
715
+ *
716
+ * @implements #64 semantic and hybrid search
717
+ * @implements #77 correct mode field
718
+ * @implements #79 date range filter
719
+ * @implements #80 starred/archived filters
720
+ * @implements #81 format/source/visibility filters
721
+ * @implements #82 collection filter on semantic/hybrid
722
+ * @implements #83 phrase search
723
+ * @implements #87 shared condition builder
724
+ * @implements #89 search mode selector
725
+ * @implements #94 per-result embedding status
726
+ */
727
+
728
+ declare class SearchRepository {
729
+ private db;
730
+ private semanticAvailable;
731
+ constructor(db: DatabaseClient, semanticAvailable?: boolean);
732
+ /** Select tsquery function based on whether query contains quoted phrases */
733
+ private tsqueryFn;
734
+ /** Returns a Set of note IDs that have an embedding record */
735
+ private fetchEmbeddingSet;
736
+ /** Attach has_embedding to each SearchResult using the provided embedding set */
737
+ private attachEmbeddingStatus;
738
+ search(query: string, options?: SearchOptions, queryEmbedding?: number[]): Promise<SearchResponse>;
739
+ /**
740
+ * Semantic search using pgvector cosine distance.
741
+ * Returns notes ranked by vector similarity to the query embedding.
742
+ */
743
+ semanticSearch(queryEmbedding: number[], options?: SearchOptions): Promise<SearchResponse>;
744
+ /**
745
+ * Hybrid search combining BM25 (full-text) and vector similarity using
746
+ * Reciprocal Rank Fusion (RRF, k=60).
747
+ */
748
+ hybridSearch(query: string, queryEmbedding: number[], options?: SearchOptions): Promise<SearchResponse>;
749
+ private recentNotes;
750
+ /**
751
+ * Fetch faceted aggregate counts for tags and collections across all matching note IDs.
752
+ * Uses the full (unpaginated) result set for accurate counts.
753
+ */
754
+ private fetchFacets;
755
+ private fetchTagMap;
756
+ }
757
+
758
+ /**
759
+ * Shared SQL condition builder for note filtering.
760
+ * Used by both SearchRepository and NotesRepository to prevent drift
761
+ * when adding new filter fields.
762
+ *
763
+ * @implements #87 shared condition builder
764
+ */
765
+
766
+ interface ConditionResult {
767
+ conditions: string[];
768
+ params: unknown[];
769
+ nextIdx: number;
770
+ }
771
+ /**
772
+ * Build WHERE clause conditions for note filtering.
773
+ * Generates parameterized SQL conditions for all shared filter fields.
774
+ *
775
+ * @param options - Filter options (any subset of SearchOptions fields)
776
+ * @param startIdx - Starting parameter index ($N)
777
+ * @param includeDeleted - Whether to include soft-deleted notes (default: false)
778
+ */
779
+ declare function buildNoteConditions(options: Pick<SearchOptions, 'tags' | 'collection_id' | 'date_from' | 'date_to' | 'is_starred' | 'is_archived' | 'format' | 'source' | 'visibility'>, startIdx: number, includeDeleted?: boolean): ConditionResult;
780
+
781
+ /**
782
+ * Job queue worker — polls job_queue for pending jobs, dispatches to registered
783
+ * handlers, manages status transitions and exponential backoff retries.
784
+ *
785
+ * Job types and priorities (lower = runs first):
786
+ * ai_revision: 1 (LLM enriches content first, requires llm)
787
+ * title_generation: 2 (generate title from enriched content)
788
+ * embedding: 3 (vectorize final content, requires semantic)
789
+ * concept_tagging: 4 (extract concepts from enriched content, requires llm)
790
+ * linking: 5 (find related notes, requires embeddings to exist)
791
+ */
792
+
793
+ interface JobQueueOptions {
794
+ /** How often to poll for new jobs (ms). Default: 5000 */
795
+ pollIntervalMs?: number;
796
+ /** Global max retries used when job.max_retries is 0. Default: 3 */
797
+ maxRetries?: number;
798
+ /** Base delay for exponential backoff (ms). Default: 1000 */
799
+ backoffBaseMs?: number;
800
+ /** Maximum backoff delay cap (ms). Default: 300000 (5 min) */
801
+ backoffMaxMs?: number;
802
+ }
803
+ interface Job {
804
+ id: string;
805
+ note_id: string;
806
+ job_type: string;
807
+ status: string;
808
+ priority: number;
809
+ required_capability: string | null;
810
+ retry_count: number;
811
+ max_retries: number;
812
+ error: string | null;
813
+ result: unknown | null;
814
+ created_at: Date;
815
+ updated_at: Date;
816
+ }
817
+ type JobHandler = (job: Job, db: DatabaseClient) => Promise<unknown>;
818
+ /** Job types listed in execution priority order (lower number = runs first) */
819
+ type JobType = 'ai_revision' | 'title_generation' | 'embedding' | 'concept_tagging' | 'linking';
820
+ /**
821
+ * Job priorities — lower number = runs first.
822
+ * Correct dependency order:
823
+ * 1. ai_revision — LLM enriches content first
824
+ * 2. title_generation — generate title from enriched content
825
+ * 3. embedding — vectorize final content
826
+ * 4. concept_tagging — extract concepts from enriched content
827
+ * 5. linking — find related notes (requires embeddings to exist)
828
+ */
829
+ declare const JOB_PRIORITIES: Record<JobType, number>;
830
+ declare const JOB_CAPABILITIES: Partial<Record<JobType, string>>;
831
+ interface EnqueueJobInput {
832
+ noteId: string;
833
+ jobType: JobType;
834
+ priority?: number;
835
+ requiredCapability?: string | null;
836
+ }
837
+ /** Enqueue a job into the job_queue table. Returns the new job ID. */
838
+ declare function enqueueJob(db: DatabaseClient, input: EnqueueJobInput): Promise<string>;
839
+ /** Enqueue the note creation pipeline: revision → title → embedding. */
840
+ declare function enqueueNoteCreationJobs(db: DatabaseClient, noteId: string, hasTitle: boolean): Promise<void>;
841
+ /**
842
+ * Enqueue the complete workflow for a note.
843
+ * Order: revision → title → embedding → concepts → linking.
844
+ * Jobs run in priority order so each step has the richest content available.
845
+ */
846
+ declare function enqueueFullWorkflow(db: DatabaseClient, noteId: string): Promise<void>;
847
+ interface JobStatus {
848
+ id: string;
849
+ note_id: string;
850
+ job_type: string;
851
+ status: string;
852
+ priority: number;
853
+ required_capability: string | null;
854
+ retry_count: number;
855
+ max_retries: number;
856
+ error: string | null;
857
+ result: unknown | null;
858
+ created_at: Date;
859
+ updated_at: Date;
860
+ }
861
+ /** Query job queue status. Optionally filter by note_id. */
862
+ declare function getJobQueueStatus(db: DatabaseClient, noteId?: string): Promise<JobStatus[]>;
863
+ declare class JobQueueWorker {
864
+ private db;
865
+ private events?;
866
+ private capabilityManager?;
867
+ private handlers;
868
+ private running;
869
+ private timer;
870
+ private options;
871
+ constructor(db: DatabaseClient, events?: TypedEventBus | undefined, options?: JobQueueOptions, capabilityManager?: CapabilityManager | undefined);
872
+ registerHandler(jobType: string, handler: JobHandler): void;
873
+ start(): Promise<void>;
874
+ /** Reset any 'processing' jobs back to 'pending' — they were interrupted by a restart */
875
+ private recoverStaleJobs;
876
+ stop(): void;
877
+ /** Process one batch of pending jobs. Useful for testing without polling. */
878
+ processOnce(): Promise<number>;
879
+ private poll;
880
+ private processPendingJobs;
881
+ getBackoffDelay(retryCount: number): number;
882
+ }
883
+ /** Title generation: LLM first, fallback to first-line extraction */
884
+ declare function titleGenerationHandler(job: Job, db: DatabaseClient): Promise<unknown>;
885
+ /** AI revision: LLM enhances note content, creates a revision record */
886
+ declare function aiRevisionHandler(job: Job, db: DatabaseClient): Promise<unknown>;
887
+ /** Concept tagging: LLM extracts SKOS concepts from revised content */
888
+ declare function conceptTaggingHandler(job: Job, db: DatabaseClient): Promise<unknown>;
889
+ /** Linking: find semantically related notes using FTS + vector RRF */
890
+ declare function linkingHandler(job: Job, db: DatabaseClient): Promise<unknown>;
891
+
892
+ /**
893
+ * TagsRepository — free-form tag management for notes.
894
+ *
895
+ * Responsibilities:
896
+ * - Add and remove tags from notes
897
+ * - Look up tags by note or notes by tag
898
+ * - List all tags with usage counts
899
+ */
900
+
901
+ declare class TagsRepository {
902
+ private db;
903
+ constructor(db: DatabaseClient);
904
+ addTag(noteId: string, tag: string): Promise<void>;
905
+ removeTag(noteId: string, tag: string): Promise<void>;
906
+ getTagsForNote(noteId: string): Promise<string[]>;
907
+ getNotesForTag(tag: string): Promise<string[]>;
908
+ listAllTags(): Promise<Array<{
909
+ tag: string;
910
+ count: number;
911
+ }>>;
912
+ }
913
+
914
+ /**
915
+ * CollectionsRepository — folder/category management for notes.
916
+ *
917
+ * Responsibilities:
918
+ * - Create, read, update, and soft-delete collections
919
+ * - Prevent circular parent references
920
+ * - Assign and unassign notes from collections
921
+ * - Return flat list and shallow tree views
922
+ */
923
+
924
+ interface CollectionRow {
925
+ id: string;
926
+ name: string;
927
+ description: string | null;
928
+ parent_id: string | null;
929
+ position: number;
930
+ created_at: Date;
931
+ updated_at: Date;
932
+ deleted_at: Date | null;
933
+ }
934
+ interface CollectionCreateInput {
935
+ name: string;
936
+ description?: string;
937
+ parent_id?: string;
938
+ }
939
+ declare class CollectionsRepository {
940
+ private db;
941
+ constructor(db: DatabaseClient);
942
+ create(input: CollectionCreateInput): Promise<CollectionRow>;
943
+ get(id: string): Promise<CollectionRow>;
944
+ list(): Promise<CollectionRow[]>;
945
+ listTree(): Promise<Array<CollectionRow & {
946
+ children: CollectionRow[];
947
+ }>>;
948
+ update(id: string, fields: Partial<Pick<CollectionRow, 'name' | 'description' | 'parent_id' | 'position'>>): Promise<CollectionRow>;
949
+ delete(id: string): Promise<void>;
950
+ assignNote(collectionId: string, noteId: string): Promise<void>;
951
+ unassignNote(collectionId: string, noteId: string): Promise<void>;
952
+ getNotesInCollection(collectionId: string): Promise<string[]>;
953
+ }
954
+
955
+ /**
956
+ * LinksRepository — bidirectional note link management.
957
+ *
958
+ * Responsibilities:
959
+ * - Create typed links between notes with duplicate prevention
960
+ * - Soft-delete links
961
+ * - Query outbound, inbound, and backlinks for a note
962
+ */
963
+
964
+ interface LinkRow {
965
+ id: string;
966
+ source_note_id: string;
967
+ target_note_id: string;
968
+ link_type: string;
969
+ confidence: number | null;
970
+ created_at: Date;
971
+ updated_at: Date | null;
972
+ deleted_at: Date | null;
973
+ }
974
+ declare class LinksRepository {
975
+ private db;
976
+ constructor(db: DatabaseClient);
977
+ create(sourceNoteId: string, targetNoteId: string, linkType?: string): Promise<LinkRow>;
978
+ get(id: string): Promise<LinkRow>;
979
+ listForNote(noteId: string): Promise<{
980
+ outbound: LinkRow[];
981
+ inbound: LinkRow[];
982
+ }>;
983
+ getBacklinks(noteId: string): Promise<string[]>;
984
+ delete(id: string): Promise<void>;
985
+ }
986
+
987
+ /**
988
+ * SkosRepository — SKOS taxonomy management (schemes, concepts, relations).
989
+ *
990
+ * Responsibilities:
991
+ * - Create and soft-delete SKOS schemes (taxonomy containers)
992
+ * - Create, list, and soft-delete SKOS concepts within schemes
993
+ * - Create and query broader/narrower/related concept relations
994
+ */
995
+
996
+ interface SkosScheme {
997
+ id: string;
998
+ title: string;
999
+ description: string | null;
1000
+ created_at: Date;
1001
+ updated_at: Date;
1002
+ deleted_at: Date | null;
1003
+ }
1004
+ interface SkosConcept {
1005
+ id: string;
1006
+ scheme_id: string;
1007
+ pref_label: string;
1008
+ alt_labels: string[];
1009
+ definition: string | null;
1010
+ created_at: Date;
1011
+ updated_at: Date;
1012
+ deleted_at: Date | null;
1013
+ }
1014
+ interface SkosRelation {
1015
+ id: string;
1016
+ source_concept_id: string;
1017
+ target_concept_id: string;
1018
+ relation_type: string;
1019
+ created_at: Date;
1020
+ }
1021
+ declare class SkosRepository {
1022
+ private db;
1023
+ constructor(db: DatabaseClient);
1024
+ createScheme(title: string, description?: string): Promise<SkosScheme>;
1025
+ listSchemes(): Promise<SkosScheme[]>;
1026
+ deleteScheme(id: string): Promise<void>;
1027
+ createConcept(schemeId: string, prefLabel: string, options?: {
1028
+ altLabels?: string[];
1029
+ definition?: string;
1030
+ }): Promise<SkosConcept>;
1031
+ listConcepts(schemeId: string): Promise<SkosConcept[]>;
1032
+ deleteConcept(id: string): Promise<void>;
1033
+ createRelation(sourceConceptId: string, targetConceptId: string, relationType: 'broader' | 'narrower' | 'related'): Promise<SkosRelation>;
1034
+ getRelations(conceptId: string): Promise<SkosRelation[]>;
1035
+ }
1036
+
1037
+ /**
1038
+ * captureKnowledge — tool function for creating notes.
1039
+ *
1040
+ * Supports three sub-actions:
1041
+ * create — create a single note from content
1042
+ * bulk_create — create multiple notes in sequence
1043
+ * from_template — interpolate a template string and create a note
1044
+ *
1045
+ * Input is Zod-validated at entry. All writes delegate to NotesRepository.
1046
+ */
1047
+
1048
+ interface CaptureKnowledgeResult {
1049
+ action: string;
1050
+ notes: NoteFull[];
1051
+ }
1052
+ declare function captureKnowledge(db: DatabaseClient, rawInput: unknown, events?: TypedEventBus): Promise<CaptureKnowledgeResult>;
1053
+
1054
+ /**
1055
+ * manageNote — tool function for note lifecycle operations.
1056
+ *
1057
+ * Supports: update, delete, restore, archive, unarchive, star, unstar.
1058
+ *
1059
+ * Input is Zod-validated at entry. All mutations delegate to NotesRepository.
1060
+ */
1061
+
1062
+ interface ManageNoteResult {
1063
+ action: string;
1064
+ note_id: string;
1065
+ note?: NoteFull;
1066
+ }
1067
+ declare function manageNote(db: DatabaseClient, rawInput: unknown, events?: TypedEventBus): Promise<ManageNoteResult>;
1068
+
1069
+ /**
1070
+ * searchTool — tool function wrapping SearchRepository.
1071
+ *
1072
+ * Only 'text' mode is currently supported. Semantic and hybrid modes throw a
1073
+ * descriptive error so callers can surface appropriate feedback.
1074
+ *
1075
+ * Input is Zod-validated at entry.
1076
+ */
1077
+
1078
+ declare function searchTool(db: DatabaseClient, rawInput: unknown): Promise<SearchResponse>;
1079
+
1080
+ /**
1081
+ * Zod schemas for tool function inputs.
1082
+ *
1083
+ * These schemas are the contract between callers (e.g. Plinyverse bridge) and
1084
+ * the tool functions. All inputs are validated at the tool boundary so that
1085
+ * repository methods only receive well-typed data.
1086
+ */
1087
+
1088
+ declare const CaptureKnowledgeInputSchema: z.ZodObject<{
1089
+ action: z.ZodEnum<["create", "bulk_create", "from_template"]>;
1090
+ content: z.ZodOptional<z.ZodString>;
1091
+ title: z.ZodOptional<z.ZodString>;
1092
+ format: z.ZodDefault<z.ZodEnum<["markdown", "plain", "html"]>>;
1093
+ source: z.ZodDefault<z.ZodString>;
1094
+ visibility: z.ZodDefault<z.ZodEnum<["private", "shared", "public"]>>;
1095
+ tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1096
+ archive_id: z.ZodOptional<z.ZodString>;
1097
+ notes: z.ZodOptional<z.ZodArray<z.ZodObject<{
1098
+ content: z.ZodString;
1099
+ title: z.ZodOptional<z.ZodString>;
1100
+ format: z.ZodDefault<z.ZodEnum<["markdown", "plain", "html"]>>;
1101
+ tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1102
+ }, "strip", z.ZodTypeAny, {
1103
+ format: "markdown" | "plain" | "html";
1104
+ content: string;
1105
+ title?: string | undefined;
1106
+ tags?: string[] | undefined;
1107
+ }, {
1108
+ content: string;
1109
+ title?: string | undefined;
1110
+ format?: "markdown" | "plain" | "html" | undefined;
1111
+ tags?: string[] | undefined;
1112
+ }>, "many">>;
1113
+ template: z.ZodOptional<z.ZodString>;
1114
+ variables: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1115
+ }, "strip", z.ZodTypeAny, {
1116
+ source: string;
1117
+ format: "markdown" | "plain" | "html";
1118
+ visibility: "private" | "shared" | "public";
1119
+ action: "create" | "bulk_create" | "from_template";
1120
+ title?: string | undefined;
1121
+ archive_id?: string | undefined;
1122
+ tags?: string[] | undefined;
1123
+ content?: string | undefined;
1124
+ notes?: {
1125
+ format: "markdown" | "plain" | "html";
1126
+ content: string;
1127
+ title?: string | undefined;
1128
+ tags?: string[] | undefined;
1129
+ }[] | undefined;
1130
+ template?: string | undefined;
1131
+ variables?: Record<string, string> | undefined;
1132
+ }, {
1133
+ action: "create" | "bulk_create" | "from_template";
1134
+ source?: string | undefined;
1135
+ title?: string | undefined;
1136
+ archive_id?: string | undefined;
1137
+ format?: "markdown" | "plain" | "html" | undefined;
1138
+ visibility?: "private" | "shared" | "public" | undefined;
1139
+ tags?: string[] | undefined;
1140
+ content?: string | undefined;
1141
+ notes?: {
1142
+ content: string;
1143
+ title?: string | undefined;
1144
+ format?: "markdown" | "plain" | "html" | undefined;
1145
+ tags?: string[] | undefined;
1146
+ }[] | undefined;
1147
+ template?: string | undefined;
1148
+ variables?: Record<string, string> | undefined;
1149
+ }>;
1150
+ type CaptureKnowledgeInput = z.infer<typeof CaptureKnowledgeInputSchema>;
1151
+ declare const ManageNoteInputSchema: z.ZodObject<{
1152
+ action: z.ZodEnum<["update", "delete", "restore", "archive", "unarchive", "star", "unstar"]>;
1153
+ note_id: z.ZodString;
1154
+ title: z.ZodOptional<z.ZodString>;
1155
+ content: z.ZodOptional<z.ZodString>;
1156
+ format: z.ZodOptional<z.ZodString>;
1157
+ visibility: z.ZodOptional<z.ZodString>;
1158
+ }, "strip", z.ZodTypeAny, {
1159
+ action: "update" | "delete" | "restore" | "archive" | "unarchive" | "star" | "unstar";
1160
+ note_id: string;
1161
+ title?: string | undefined;
1162
+ format?: string | undefined;
1163
+ visibility?: string | undefined;
1164
+ content?: string | undefined;
1165
+ }, {
1166
+ action: "update" | "delete" | "restore" | "archive" | "unarchive" | "star" | "unstar";
1167
+ note_id: string;
1168
+ title?: string | undefined;
1169
+ format?: string | undefined;
1170
+ visibility?: string | undefined;
1171
+ content?: string | undefined;
1172
+ }>;
1173
+ type ManageNoteInput = z.infer<typeof ManageNoteInputSchema>;
1174
+ declare const SearchInputSchema: z.ZodObject<{
1175
+ query: z.ZodString;
1176
+ mode: z.ZodDefault<z.ZodEnum<["text", "semantic", "hybrid"]>>;
1177
+ limit: z.ZodDefault<z.ZodNumber>;
1178
+ offset: z.ZodDefault<z.ZodNumber>;
1179
+ tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1180
+ collection_id: z.ZodOptional<z.ZodString>;
1181
+ date_from: z.ZodOptional<z.ZodDate>;
1182
+ date_to: z.ZodOptional<z.ZodDate>;
1183
+ is_starred: z.ZodOptional<z.ZodBoolean>;
1184
+ is_archived: z.ZodOptional<z.ZodBoolean>;
1185
+ format: z.ZodOptional<z.ZodEnum<["markdown", "plain", "html"]>>;
1186
+ source: z.ZodOptional<z.ZodString>;
1187
+ visibility: z.ZodOptional<z.ZodEnum<["private", "shared", "public"]>>;
1188
+ include_facets: z.ZodDefault<z.ZodBoolean>;
1189
+ }, "strip", z.ZodTypeAny, {
1190
+ limit: number;
1191
+ offset: number;
1192
+ include_facets: boolean;
1193
+ mode: "semantic" | "text" | "hybrid";
1194
+ query: string;
1195
+ source?: string | undefined;
1196
+ format?: "markdown" | "plain" | "html" | undefined;
1197
+ visibility?: "private" | "shared" | "public" | undefined;
1198
+ is_starred?: boolean | undefined;
1199
+ is_archived?: boolean | undefined;
1200
+ tags?: string[] | undefined;
1201
+ collection_id?: string | undefined;
1202
+ date_from?: Date | undefined;
1203
+ date_to?: Date | undefined;
1204
+ }, {
1205
+ query: string;
1206
+ source?: string | undefined;
1207
+ format?: "markdown" | "plain" | "html" | undefined;
1208
+ visibility?: "private" | "shared" | "public" | undefined;
1209
+ is_starred?: boolean | undefined;
1210
+ is_archived?: boolean | undefined;
1211
+ tags?: string[] | undefined;
1212
+ limit?: number | undefined;
1213
+ offset?: number | undefined;
1214
+ collection_id?: string | undefined;
1215
+ date_from?: Date | undefined;
1216
+ date_to?: Date | undefined;
1217
+ include_facets?: boolean | undefined;
1218
+ mode?: "semantic" | "text" | "hybrid" | undefined;
1219
+ }>;
1220
+ type SearchInput = z.infer<typeof SearchInputSchema>;
1221
+
1222
+ /**
1223
+ * FortemiToolManifest — registry of all Mnemos tool definitions.
1224
+ *
1225
+ * Defines the full set of tool schemas and provides PlinyCapability
1226
+ * projection for bridge registration. Each tool definition follows the
1227
+ * WHEN/WHAT/HOW/OUT description pattern so consumers understand call sites.
1228
+ *
1229
+ * The 10 tools defined here are the initial subset covering core Mnemos
1230
+ * operations. Additional tools will be added incrementally as repositories
1231
+ * are implemented.
1232
+ */
1233
+
1234
+ interface FortemiToolDefinition {
1235
+ id: string;
1236
+ name: string;
1237
+ description: string;
1238
+ category: 'capture' | 'search' | 'manage' | 'organize' | 'process' | 'analyze' | 'system';
1239
+ inputSchema: ZodType;
1240
+ tags: string[];
1241
+ sideEffects: boolean;
1242
+ requiredCapability?: string;
1243
+ }
1244
+ interface PlinyCapability {
1245
+ id: string;
1246
+ name: string;
1247
+ description: string;
1248
+ inputSchema: Record<string, unknown>;
1249
+ tags: string[];
1250
+ sideEffects: boolean;
1251
+ }
1252
+ declare class FortemiToolManifest {
1253
+ private tools;
1254
+ constructor();
1255
+ /** Look up a single tool by its fully-qualified id. */
1256
+ get(id: string): FortemiToolDefinition | undefined;
1257
+ /** Return all registered tools as a snapshot array. */
1258
+ list(): FortemiToolDefinition[];
1259
+ /** Return tools matching a custom predicate. */
1260
+ filter(predicate: (tool: FortemiToolDefinition) => boolean): FortemiToolDefinition[];
1261
+ /** Return tools belonging to a specific category. */
1262
+ byCategory(category: string): FortemiToolDefinition[];
1263
+ /**
1264
+ * Full-text search across tool name, description, and tags.
1265
+ * Case-insensitive.
1266
+ */
1267
+ search(query: string): FortemiToolDefinition[];
1268
+ /** Project all tools as PlinyCapability entries for bridge registration. */
1269
+ toPlinyCapabilities(): PlinyCapability[];
1270
+ /** Return the count of tools in each category. */
1271
+ getCategoryCounts(): Record<string, number>;
1272
+ }
1273
+ declare const fortemiManifest: FortemiToolManifest;
1274
+
1275
+ declare const GetNoteInputSchema: z.ZodObject<{
1276
+ note_id: z.ZodString;
1277
+ }, "strip", z.ZodTypeAny, {
1278
+ note_id: string;
1279
+ }, {
1280
+ note_id: string;
1281
+ }>;
1282
+ type GetNoteInput = z.infer<typeof GetNoteInputSchema>;
1283
+ declare function getNote(db: DatabaseClient, rawInput: unknown, events?: TypedEventBus): Promise<NoteFull>;
1284
+
1285
+ declare const ListNotesInputSchema: z.ZodObject<{
1286
+ limit: z.ZodDefault<z.ZodNumber>;
1287
+ offset: z.ZodDefault<z.ZodNumber>;
1288
+ sort: z.ZodDefault<z.ZodEnum<["created_at", "updated_at", "title"]>>;
1289
+ order: z.ZodDefault<z.ZodEnum<["asc", "desc"]>>;
1290
+ is_starred: z.ZodOptional<z.ZodBoolean>;
1291
+ is_archived: z.ZodOptional<z.ZodBoolean>;
1292
+ tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
1293
+ collection_id: z.ZodOptional<z.ZodString>;
1294
+ include_deleted: z.ZodOptional<z.ZodBoolean>;
1295
+ }, "strip", z.ZodTypeAny, {
1296
+ limit: number;
1297
+ offset: number;
1298
+ sort: "created_at" | "updated_at" | "title";
1299
+ order: "asc" | "desc";
1300
+ is_starred?: boolean | undefined;
1301
+ is_archived?: boolean | undefined;
1302
+ tags?: string[] | undefined;
1303
+ include_deleted?: boolean | undefined;
1304
+ collection_id?: string | undefined;
1305
+ }, {
1306
+ is_starred?: boolean | undefined;
1307
+ is_archived?: boolean | undefined;
1308
+ tags?: string[] | undefined;
1309
+ limit?: number | undefined;
1310
+ offset?: number | undefined;
1311
+ sort?: "created_at" | "updated_at" | "title" | undefined;
1312
+ order?: "asc" | "desc" | undefined;
1313
+ include_deleted?: boolean | undefined;
1314
+ collection_id?: string | undefined;
1315
+ }>;
1316
+ type ListNotesInput = z.infer<typeof ListNotesInputSchema>;
1317
+ declare function listNotes(db: DatabaseClient, rawInput: unknown, events?: TypedEventBus): Promise<PaginatedResult<NoteSummary>>;
1318
+
1319
+ declare const ManageTagsInputSchema: z.ZodObject<{
1320
+ action: z.ZodEnum<["add", "remove", "list_for_note", "list_all"]>;
1321
+ note_id: z.ZodOptional<z.ZodString>;
1322
+ tag: z.ZodOptional<z.ZodString>;
1323
+ }, "strip", z.ZodTypeAny, {
1324
+ action: "add" | "remove" | "list_for_note" | "list_all";
1325
+ note_id?: string | undefined;
1326
+ tag?: string | undefined;
1327
+ }, {
1328
+ action: "add" | "remove" | "list_for_note" | "list_all";
1329
+ note_id?: string | undefined;
1330
+ tag?: string | undefined;
1331
+ }>;
1332
+ type ManageTagsInput = z.infer<typeof ManageTagsInputSchema>;
1333
+ interface ManageTagsResult {
1334
+ action: string;
1335
+ tags?: string[];
1336
+ all_tags?: Array<{
1337
+ tag: string;
1338
+ count: number;
1339
+ }>;
1340
+ }
1341
+ declare function manageTags(db: DatabaseClient, rawInput: unknown): Promise<ManageTagsResult>;
1342
+
1343
+ declare const ManageCollectionsInputSchema: z.ZodObject<{
1344
+ action: z.ZodEnum<["create", "list", "list_tree", "assign", "unassign", "delete"]>;
1345
+ name: z.ZodOptional<z.ZodString>;
1346
+ description: z.ZodOptional<z.ZodString>;
1347
+ parent_id: z.ZodOptional<z.ZodString>;
1348
+ collection_id: z.ZodOptional<z.ZodString>;
1349
+ note_id: z.ZodOptional<z.ZodString>;
1350
+ }, "strip", z.ZodTypeAny, {
1351
+ action: "create" | "delete" | "list" | "assign" | "unassign" | "list_tree";
1352
+ name?: string | undefined;
1353
+ collection_id?: string | undefined;
1354
+ description?: string | undefined;
1355
+ parent_id?: string | undefined;
1356
+ note_id?: string | undefined;
1357
+ }, {
1358
+ action: "create" | "delete" | "list" | "assign" | "unassign" | "list_tree";
1359
+ name?: string | undefined;
1360
+ collection_id?: string | undefined;
1361
+ description?: string | undefined;
1362
+ parent_id?: string | undefined;
1363
+ note_id?: string | undefined;
1364
+ }>;
1365
+ type ManageCollectionsInput = z.infer<typeof ManageCollectionsInputSchema>;
1366
+ interface ManageCollectionsResult {
1367
+ action: string;
1368
+ collection?: CollectionRow;
1369
+ collections?: CollectionRow[];
1370
+ tree?: Array<CollectionRow & {
1371
+ children: CollectionRow[];
1372
+ }>;
1373
+ collection_id?: string;
1374
+ note_id?: string;
1375
+ }
1376
+ declare function manageCollections(db: DatabaseClient, rawInput: unknown): Promise<ManageCollectionsResult>;
1377
+
1378
+ declare const ManageLinksInputSchema: z.ZodObject<{
1379
+ action: z.ZodEnum<["create", "list", "backlinks", "delete"]>;
1380
+ source_note_id: z.ZodOptional<z.ZodString>;
1381
+ target_note_id: z.ZodOptional<z.ZodString>;
1382
+ link_id: z.ZodOptional<z.ZodString>;
1383
+ link_type: z.ZodDefault<z.ZodString>;
1384
+ note_id: z.ZodOptional<z.ZodString>;
1385
+ }, "strip", z.ZodTypeAny, {
1386
+ action: "create" | "delete" | "list" | "backlinks";
1387
+ link_type: string;
1388
+ note_id?: string | undefined;
1389
+ source_note_id?: string | undefined;
1390
+ target_note_id?: string | undefined;
1391
+ link_id?: string | undefined;
1392
+ }, {
1393
+ action: "create" | "delete" | "list" | "backlinks";
1394
+ note_id?: string | undefined;
1395
+ source_note_id?: string | undefined;
1396
+ target_note_id?: string | undefined;
1397
+ link_id?: string | undefined;
1398
+ link_type?: string | undefined;
1399
+ }>;
1400
+ type ManageLinksInput = z.infer<typeof ManageLinksInputSchema>;
1401
+ interface ManageLinksResult {
1402
+ action: string;
1403
+ link?: LinkRow;
1404
+ outbound?: LinkRow[];
1405
+ inbound?: LinkRow[];
1406
+ backlinks?: string[];
1407
+ link_id?: string;
1408
+ }
1409
+ declare function manageLinks(db: DatabaseClient, rawInput: unknown): Promise<ManageLinksResult>;
1410
+
1411
+ declare const ManageArchiveInputSchema: z.ZodObject<{
1412
+ action: z.ZodEnum<["list", "create", "switch", "delete"]>;
1413
+ name: z.ZodOptional<z.ZodString>;
1414
+ }, "strip", z.ZodTypeAny, {
1415
+ action: "create" | "delete" | "list" | "switch";
1416
+ name?: string | undefined;
1417
+ }, {
1418
+ action: "create" | "delete" | "list" | "switch";
1419
+ name?: string | undefined;
1420
+ }>;
1421
+ type ManageArchiveInput = z.infer<typeof ManageArchiveInputSchema>;
1422
+ interface ManageArchiveResult {
1423
+ action: string;
1424
+ archives?: ArchiveInfo[];
1425
+ current?: string;
1426
+ name?: string;
1427
+ }
1428
+ declare function manageArchive(archiveManager: ArchiveManager, rawInput: unknown): Promise<ManageArchiveResult>;
1429
+
1430
+ declare const ManageCapabilitiesInputSchema: z.ZodObject<{
1431
+ action: z.ZodEnum<["list", "enable", "disable", "status"]>;
1432
+ capability: z.ZodOptional<z.ZodString>;
1433
+ }, "strip", z.ZodTypeAny, {
1434
+ action: "enable" | "disable" | "status" | "list";
1435
+ capability?: string | undefined;
1436
+ }, {
1437
+ action: "enable" | "disable" | "status" | "list";
1438
+ capability?: string | undefined;
1439
+ }>;
1440
+ type ManageCapabilitiesInput = z.infer<typeof ManageCapabilitiesInputSchema>;
1441
+ interface CapabilityInfo {
1442
+ name: CapabilityName;
1443
+ state: CapabilityState;
1444
+ error?: string;
1445
+ }
1446
+ interface ManageCapabilitiesResult {
1447
+ action: string;
1448
+ capabilities?: Array<{
1449
+ name: CapabilityName;
1450
+ state: CapabilityState;
1451
+ }>;
1452
+ capability?: CapabilityInfo;
1453
+ }
1454
+ declare function manageCapabilities(capabilityManager: CapabilityManager, rawInput: unknown): Promise<ManageCapabilitiesResult>;
1455
+
1456
+ /**
1457
+ * AttachmentsRepository — attach and retrieve binary files linked to notes.
1458
+ *
1459
+ * Responsibilities:
1460
+ * - Content-addressed blob deduplication via SHA-256 hash
1461
+ * - Store blob metadata in DatabaseClient (attachment_blob table)
1462
+ * - Store binary data in a BlobStore implementation
1463
+ * - Create/soft-delete attachment records linked to notes
1464
+ * - List active attachments for a note
1465
+ */
1466
+
1467
+ interface AttachmentRow {
1468
+ id: string;
1469
+ note_id: string;
1470
+ blob_id: string;
1471
+ document_type_id: string | null;
1472
+ filename: string;
1473
+ display_name: string | null;
1474
+ position: number;
1475
+ created_at: Date;
1476
+ deleted_at: Date | null;
1477
+ }
1478
+ interface AttachmentBlobRow {
1479
+ id: string;
1480
+ content_hash: string;
1481
+ size_bytes: number;
1482
+ storage_path: string | null;
1483
+ created_at: Date;
1484
+ }
1485
+ interface AttachInput {
1486
+ noteId: string;
1487
+ data: Uint8Array;
1488
+ filename: string;
1489
+ mimeType?: string;
1490
+ displayName?: string;
1491
+ }
1492
+ declare class AttachmentsRepository {
1493
+ private db;
1494
+ private blobStore;
1495
+ constructor(db: DatabaseClient, blobStore: BlobStore);
1496
+ /**
1497
+ * Attach a binary file to a note.
1498
+ *
1499
+ * If a blob with the same SHA-256 content hash already exists, the existing
1500
+ * blob row is reused (deduplication). Otherwise a new blob row is inserted
1501
+ * and the raw bytes are written to the BlobStore.
1502
+ *
1503
+ * Returns the newly created AttachmentRow.
1504
+ */
1505
+ attach(input: AttachInput): Promise<AttachmentRow>;
1506
+ /**
1507
+ * Fetch an attachment row by its ID.
1508
+ * Throws when no row exists.
1509
+ */
1510
+ get(id: string): Promise<AttachmentRow>;
1511
+ /**
1512
+ * Retrieve the raw binary data for an attachment.
1513
+ * Returns null if the blob cannot be found in the BlobStore.
1514
+ */
1515
+ getBlob(attachmentId: string): Promise<Uint8Array | null>;
1516
+ /**
1517
+ * List active (non-deleted) attachments for a note.
1518
+ * Ordered by position ascending, then created_at ascending.
1519
+ */
1520
+ list(noteId: string): Promise<AttachmentRow[]>;
1521
+ /**
1522
+ * Soft-delete an attachment by setting deleted_at to the current timestamp.
1523
+ * The underlying blob row and BlobStore data are not removed.
1524
+ */
1525
+ delete(id: string): Promise<void>;
1526
+ }
1527
+
1528
+ declare const ManageAttachmentsInputSchema: z.ZodObject<{
1529
+ action: z.ZodEnum<["attach", "list", "get", "get_blob", "delete"]>;
1530
+ note_id: z.ZodOptional<z.ZodString>;
1531
+ attachment_id: z.ZodOptional<z.ZodString>;
1532
+ /** Base64-encoded file data for the 'attach' action */
1533
+ data_base64: z.ZodOptional<z.ZodString>;
1534
+ filename: z.ZodOptional<z.ZodString>;
1535
+ mime_type: z.ZodOptional<z.ZodString>;
1536
+ display_name: z.ZodOptional<z.ZodString>;
1537
+ }, "strip", z.ZodTypeAny, {
1538
+ action: "delete" | "list" | "attach" | "get" | "get_blob";
1539
+ filename?: string | undefined;
1540
+ note_id?: string | undefined;
1541
+ attachment_id?: string | undefined;
1542
+ data_base64?: string | undefined;
1543
+ mime_type?: string | undefined;
1544
+ display_name?: string | undefined;
1545
+ }, {
1546
+ action: "delete" | "list" | "attach" | "get" | "get_blob";
1547
+ filename?: string | undefined;
1548
+ note_id?: string | undefined;
1549
+ attachment_id?: string | undefined;
1550
+ data_base64?: string | undefined;
1551
+ mime_type?: string | undefined;
1552
+ display_name?: string | undefined;
1553
+ }>;
1554
+ type ManageAttachmentsInput = z.infer<typeof ManageAttachmentsInputSchema>;
1555
+ interface ManageAttachmentsResult {
1556
+ action: string;
1557
+ attachment?: AttachmentRow;
1558
+ attachments?: AttachmentRow[];
1559
+ attachment_id?: string;
1560
+ /** Base64-encoded blob data for 'get_blob' action */
1561
+ data_base64?: string;
1562
+ size_bytes?: number;
1563
+ }
1564
+ declare function manageAttachments(db: DatabaseClient, blobStore: BlobStore, rawInput: unknown): Promise<ManageAttachmentsResult>;
1565
+
1566
+ /**
1567
+ * GPU capability detection for WebGPU-based LLM inference.
1568
+ * Used to select appropriate model tier based on available GPU memory.
1569
+ *
1570
+ * @implements #61 GPU capability detection
1571
+ */
1572
+ interface GpuCapabilities {
1573
+ webgpuAvailable: boolean;
1574
+ vendor: string;
1575
+ architecture: string;
1576
+ maxBufferSizeBytes: number;
1577
+ supportsF16: boolean;
1578
+ }
1579
+ type VramTier = 'low' | 'medium' | 'high' | 'unknown';
1580
+ declare function detectGpuCapabilities(): Promise<GpuCapabilities>;
1581
+ declare function estimateVramTier(caps: GpuCapabilities): VramTier;
1582
+ /**
1583
+ * Select an LLM model based on VRAM tier and f16 shader support.
1584
+ * Uses f32 quantization when f16 shaders aren't available (e.g., SwiftShader).
1585
+ */
1586
+ declare function selectLlmModel(tier: VramTier, supportsF16?: boolean): string;
1587
+
1588
+ /**
1589
+ * Enhanced inference capability detection.
1590
+ * Extends gpu-detect.ts with VRAM estimation, model fit, Chrome AI, and WebNN detection.
1591
+ *
1592
+ * @implements #115 hardware capability detection improvements
1593
+ */
1594
+
1595
+ type RecommendedTier = 'high' | 'medium' | 'low' | 'cpu-only';
1596
+ interface InferenceCapabilities {
1597
+ webgpu: boolean;
1598
+ wasm: boolean;
1599
+ webnn: boolean;
1600
+ sharedArrayBuffer: boolean;
1601
+ chromeAI: boolean;
1602
+ estimatedVramMB: number;
1603
+ recommendedTier: RecommendedTier;
1604
+ gpu: GpuCapabilities;
1605
+ vramTier: VramTier;
1606
+ }
1607
+ interface ModelFitResult {
1608
+ fits: boolean;
1609
+ estimatedVramMB: number;
1610
+ availableVramMB: number;
1611
+ recommendation: string;
1612
+ }
1613
+ /**
1614
+ * Estimate VRAM in MB using known GPU heuristics.
1615
+ * Falls back to maxBufferSize-based estimation if no match.
1616
+ */
1617
+ declare function estimateVramMB(gpu: GpuCapabilities): number;
1618
+ /**
1619
+ * Estimate whether a model will fit in available VRAM.
1620
+ */
1621
+ declare function estimateModelFit(modelSizeMB: number, availableVramMB: number): ModelFitResult;
1622
+ /**
1623
+ * Comprehensive inference capability detection.
1624
+ * Superset of detectGpuCapabilities() — adds VRAM estimation, WebNN, Chrome AI, etc.
1625
+ */
1626
+ declare function detectInferenceCapabilities(): Promise<InferenceCapabilities>;
1627
+
1628
+ /**
1629
+ * Text chunking utility for embedding generation.
1630
+ * Splits long text into overlapping chunks suitable for embedding models.
1631
+ *
1632
+ * @implements #63 embedding pipeline prerequisite
1633
+ */
1634
+ /** Split text into overlapping chunks for embedding. */
1635
+ declare function chunkText(text: string, maxChars?: number, overlap?: number): string[];
1636
+
1637
+ /**
1638
+ * Embedding generation job handler.
1639
+ * Generates and stores vector embeddings for note content.
1640
+ * Embed function is injected via setEmbedFunction — no WASM loaded by default.
1641
+ *
1642
+ * @implements #63 embedding generation
1643
+ */
1644
+
1645
+ /** Type for the embed function — injected by the semantic capability module */
1646
+ type EmbedFunction = (texts: string[]) => Promise<number[][]>;
1647
+ declare function setEmbedFunction(fn: EmbedFunction | null): void;
1648
+ declare function getEmbedFunction(): EmbedFunction | null;
1649
+ /** Job handler for embedding generation. Registered in JobQueueWorker. */
1650
+ declare function embeddingGenerationHandler(job: {
1651
+ note_id: string;
1652
+ }, db: DatabaseClient): Promise<unknown>;
1653
+
1654
+ /**
1655
+ * LLM completion function injection.
1656
+ * Provides the slot for an LLM function — injected by the llm capability module.
1657
+ * No model loading by default (CAP-001).
1658
+ *
1659
+ * @implements #66 AI title generation
1660
+ */
1661
+ /** Type for the LLM completion function — injected by the llm capability module */
1662
+ type LlmCompleteFn = (prompt: string, options?: {
1663
+ maxTokens?: number;
1664
+ temperature?: number;
1665
+ }) => Promise<string>;
1666
+ declare function setLlmFunction(fn: LlmCompleteFn | null): void;
1667
+ declare function getLlmFunction(): LlmCompleteFn | null;
1668
+
1669
+ /**
1670
+ * Auto-tagging utility using embedding similarity.
1671
+ * Suggests tags based on cosine similarity between note and tag vocabulary embeddings.
1672
+ *
1673
+ * @implements #67 auto-tagging
1674
+ */
1675
+ /** Cosine similarity between two normalized vectors (dot product) */
1676
+ declare function cosineSimilarity(a: number[], b: number[]): number;
1677
+ /**
1678
+ * Suggest tags based on embedding similarity to tag vocabulary centroids.
1679
+ * Returns tags sorted by descending similarity score, filtered by threshold.
1680
+ */
1681
+ declare function suggestTags(noteEmbedding: number[], tagEmbeddings: Map<string, number[]>, threshold?: number, maxTags?: number): string[];
1682
+
1683
+ /**
1684
+ * Semantic capability loader — registers the embedding pipeline with CapabilityManager.
1685
+ *
1686
+ * In production (browser), this loads @huggingface/transformers in a Web Worker.
1687
+ * In tests, call registerSemanticCapability() with a mock embed function.
1688
+ *
1689
+ * @implements #62 semantic capability loader
1690
+ */
1691
+
1692
+ /**
1693
+ * Register the semantic capability with a CapabilityManager.
1694
+ * The loader will be called when capabilityManager.enable('semantic') is invoked.
1695
+ *
1696
+ * @param manager - The CapabilityManager instance
1697
+ * @param embedFn - The embedding function (from transformers.js worker or mock)
1698
+ * @param onProgress - Optional progress callback for model download
1699
+ */
1700
+ declare function registerSemanticCapability(manager: CapabilityManager, embedFn: EmbedFunction, onProgress?: (pct: number) => void): void;
1701
+ /**
1702
+ * Unregister the semantic capability — clears the embed function.
1703
+ * Called when the capability is disabled.
1704
+ */
1705
+ declare function unregisterSemanticCapability(): void;
1706
+
1707
+ /**
1708
+ * LLM capability loader — registers the local LLM with CapabilityManager.
1709
+ *
1710
+ * In production (browser), this loads @mlc-ai/web-llm in a Web Worker.
1711
+ * In tests, call registerLlmCapability() with a mock completion function.
1712
+ *
1713
+ * @implements #65 LLM capability loader
1714
+ */
1715
+
1716
+ interface LlmCapabilityOptions {
1717
+ modelOverride?: string;
1718
+ onProgress?: (pct: number, text: string) => void;
1719
+ }
1720
+ /**
1721
+ * Register the LLM capability with a CapabilityManager.
1722
+ * The loader checks WebGPU availability before loading.
1723
+ *
1724
+ * @param manager - The CapabilityManager instance
1725
+ * @param completeFn - The LLM completion function (from WebLLM worker or mock)
1726
+ * @param options - Optional model override and progress callback
1727
+ */
1728
+ declare function registerLlmCapability(manager: CapabilityManager, completeFn: LlmCompleteFn, options?: LlmCapabilityOptions): void;
1729
+ /**
1730
+ * Unregister the LLM capability — clears the completion function.
1731
+ */
1732
+ declare function unregisterLlmCapability(): void;
1733
+
1734
+ /**
1735
+ * Formal InferenceProvider interface.
1736
+ * Core contract for all inference providers — remote APIs, local servers, in-browser models.
1737
+ * Core stays dependency-free: interface only, no implementations.
1738
+ *
1739
+ * @implements #112 formal InferenceProvider interface
1740
+ */
1741
+ interface ProviderCapabilities {
1742
+ embeddings: boolean;
1743
+ chat: boolean;
1744
+ streaming: boolean;
1745
+ vision: boolean;
1746
+ toolCalling: boolean;
1747
+ structuredOutput: boolean;
1748
+ maxContextTokens?: number;
1749
+ }
1750
+ interface EmbedRequest {
1751
+ texts: string[];
1752
+ model?: string;
1753
+ }
1754
+ interface EmbedResponse {
1755
+ vectors: number[][];
1756
+ model: string;
1757
+ usage?: {
1758
+ totalTokens: number;
1759
+ };
1760
+ }
1761
+ interface CompletionRequest {
1762
+ prompt: string;
1763
+ model?: string;
1764
+ maxTokens?: number;
1765
+ temperature?: number;
1766
+ systemPrompt?: string;
1767
+ stopSequences?: string[];
1768
+ }
1769
+ interface CompletionResponse {
1770
+ text: string;
1771
+ model: string;
1772
+ usage?: {
1773
+ promptTokens: number;
1774
+ completionTokens: number;
1775
+ };
1776
+ finishReason?: 'stop' | 'length' | 'content_filter';
1777
+ }
1778
+ interface StreamChunk {
1779
+ text: string;
1780
+ done: boolean;
1781
+ }
1782
+ interface ModelInfo {
1783
+ id: string;
1784
+ name?: string;
1785
+ capabilities: Partial<ProviderCapabilities>;
1786
+ contextWindow?: number;
1787
+ owned_by?: string;
1788
+ }
1789
+ type ProbeStatus = 'ok' | 'degraded' | 'down';
1790
+ interface ProbeResult {
1791
+ status: ProbeStatus;
1792
+ latencyMs: number;
1793
+ message?: string;
1794
+ }
1795
+ type ProviderTier = 'remote' | 'local-server' | 'in-browser' | 'chrome-ai';
1796
+ interface InferenceProvider {
1797
+ readonly id: string;
1798
+ readonly name: string;
1799
+ readonly tier: ProviderTier;
1800
+ readonly capabilities: ProviderCapabilities;
1801
+ /** Generate embeddings for text inputs */
1802
+ embed?(request: EmbedRequest): Promise<EmbedResponse>;
1803
+ /** Generate a completion (non-streaming) */
1804
+ complete?(request: CompletionRequest): Promise<CompletionResponse>;
1805
+ /** Generate a streaming completion */
1806
+ stream?(request: CompletionRequest): AsyncIterable<StreamChunk>;
1807
+ /** List available models from this provider */
1808
+ listModels(): Promise<ModelInfo[]>;
1809
+ /** Health check — probe the provider */
1810
+ probe(): Promise<ProbeResult>;
1811
+ /** Clean up resources */
1812
+ dispose(): void;
1813
+ }
1814
+
1815
+ /**
1816
+ * ProviderRegistry — manages InferenceProvider instances.
1817
+ * Supports add/remove/getActive/setActive and derives CapabilityManager state.
1818
+ *
1819
+ * @implements #112 provider registry
1820
+ */
1821
+
1822
+ declare class ProviderRegistry {
1823
+ private events?;
1824
+ private providers;
1825
+ private activeId;
1826
+ constructor(events?: TypedEventBus | undefined);
1827
+ /** Register a provider. First provider with embedding capability becomes active. */
1828
+ add(provider: InferenceProvider): void;
1829
+ /** Remove a provider by ID. If it was active, clears active. */
1830
+ remove(id: string): void;
1831
+ /** Set the active provider by ID */
1832
+ setActive(id: string): void;
1833
+ /** Get the currently active provider */
1834
+ getActive(): InferenceProvider | null;
1835
+ /** Get a provider by ID */
1836
+ get(id: string): InferenceProvider | undefined;
1837
+ /** List all registered providers */
1838
+ list(): InferenceProvider[];
1839
+ /** Get provider count */
1840
+ get size(): number;
1841
+ /** Check if any provider supports embeddings */
1842
+ hasEmbeddings(): boolean;
1843
+ /** Check if any provider supports chat */
1844
+ hasChat(): boolean;
1845
+ /** Find first provider supporting a given capability */
1846
+ findByCapability(cap: keyof InferenceProvider['capabilities']): InferenceProvider | undefined;
1847
+ /** Convenience: embed using active provider */
1848
+ embed(request: EmbedRequest): Promise<EmbedResponse>;
1849
+ /** Convenience: complete using active provider */
1850
+ complete(request: CompletionRequest): Promise<CompletionResponse>;
1851
+ /** Convenience: stream using active provider */
1852
+ stream(request: CompletionRequest): AsyncIterable<StreamChunk>;
1853
+ /** Dispose all providers */
1854
+ dispose(): void;
1855
+ /**
1856
+ * Sync the legacy bare function slots with the active provider.
1857
+ * This maintains backward compatibility: job-queue-worker.ts and other
1858
+ * consumers that call getEmbedFunction() / getLlmFunction() still work.
1859
+ */
1860
+ private syncLegacyFunctions;
1861
+ }
1862
+ /**
1863
+ * Create an InferenceProvider from legacy bare functions.
1864
+ * Used by setEmbedFunction/setLlmFunction backward compat layer.
1865
+ */
1866
+ declare function createLegacyProvider(options: {
1867
+ embedFn?: EmbedFunction | null;
1868
+ llmFn?: LlmCompleteFn | null;
1869
+ id?: string;
1870
+ name?: string;
1871
+ }): InferenceProvider;
1872
+
1873
+ /**
1874
+ * OpenAI-compatible inference provider.
1875
+ * Works with OpenAI, OpenRouter, Anthropic (via OpenRouter), Ollama, LM Studio,
1876
+ * llama.cpp, vLLM, Jan, and any OpenAI-compatible endpoint.
1877
+ *
1878
+ * No SDK dependencies — uses raw fetch() to keep @fortemi/core lightweight.
1879
+ *
1880
+ * @implements #113 remote provider support
1881
+ */
1882
+
1883
+ interface OpenAIProviderConfig {
1884
+ id: string;
1885
+ name: string;
1886
+ baseURL: string;
1887
+ apiKey?: string;
1888
+ defaultModel?: string;
1889
+ defaultEmbeddingModel?: string;
1890
+ tier?: ProviderTier;
1891
+ headers?: Record<string, string>;
1892
+ timeoutMs?: number;
1893
+ }
1894
+ declare class OpenAICompatibleProvider implements InferenceProvider {
1895
+ readonly id: string;
1896
+ readonly name: string;
1897
+ readonly tier: ProviderTier;
1898
+ readonly capabilities: ProviderCapabilities;
1899
+ private baseURL;
1900
+ private apiKey?;
1901
+ private defaultModel;
1902
+ private defaultEmbeddingModel;
1903
+ private extraHeaders;
1904
+ private timeoutMs;
1905
+ private abortController;
1906
+ constructor(config: OpenAIProviderConfig);
1907
+ embed(request: EmbedRequest): Promise<EmbedResponse>;
1908
+ complete(request: CompletionRequest): Promise<CompletionResponse>;
1909
+ stream(request: CompletionRequest): AsyncIterable<StreamChunk>;
1910
+ listModels(): Promise<ModelInfo[]>;
1911
+ probe(): Promise<ProbeResult>;
1912
+ dispose(): void;
1913
+ private buildMessages;
1914
+ private mapFinishReason;
1915
+ private isEmbeddingModel;
1916
+ private isLocalURL;
1917
+ private fetch;
1918
+ private rawFetch;
1919
+ }
1920
+
1921
+ /**
1922
+ * Local inference server auto-discovery.
1923
+ * Probes known local endpoints (Ollama, LM Studio, llama.cpp, vLLM, Jan, LocalAI)
1924
+ * and returns discovered providers ready for registration.
1925
+ *
1926
+ * @implements #116 local server auto-discovery
1927
+ */
1928
+
1929
+ interface LocalEndpoint {
1930
+ id: string;
1931
+ name: string;
1932
+ baseURL: string;
1933
+ defaultPort: number;
1934
+ }
1935
+ interface DiscoveredProvider {
1936
+ id: string;
1937
+ name: string;
1938
+ baseURL: string;
1939
+ models: ModelInfo[];
1940
+ }
1941
+ interface DiscoveryOptions {
1942
+ /** Additional endpoints to probe beyond the defaults */
1943
+ extraEndpoints?: LocalEndpoint[];
1944
+ /** Probe timeout per endpoint in ms (default: 2000) */
1945
+ timeoutMs?: number;
1946
+ /** Ports to skip (e.g., if you know a port is used for something else) */
1947
+ skipPorts?: number[];
1948
+ }
1949
+ declare const LOCAL_ENDPOINTS: LocalEndpoint[];
1950
+ type ModelCategory = 'embedding' | 'vision' | 'chat';
1951
+ /**
1952
+ * Classify a model by its ID/name into embedding, vision, or chat.
1953
+ */
1954
+ declare function classifyModel(modelId: string): ModelCategory;
1955
+ /**
1956
+ * Discover local inference servers by probing known endpoints.
1957
+ * Returns all reachable providers with their available models.
1958
+ */
1959
+ declare function discoverLocalProviders(options?: DiscoveryOptions): Promise<DiscoveredProvider[]>;
1960
+
1961
+ /**
1962
+ * FallbackRouter — wraps multiple InferenceProviders with automatic failover.
1963
+ * Routes requests to the highest-priority available provider, falling through
1964
+ * on errors. Failed providers enter cooldown before retry.
1965
+ *
1966
+ * @implements #114 provider fallback chains with cooldown
1967
+ */
1968
+
1969
+ interface FallbackRouterConfig {
1970
+ /** Ordered list of providers (highest priority first) */
1971
+ providers: InferenceProvider[];
1972
+ /** Cooldown durations by error type in ms */
1973
+ cooldowns?: CooldownConfig;
1974
+ /** Event bus for fallback notifications */
1975
+ events?: TypedEventBus;
1976
+ }
1977
+ interface CooldownConfig {
1978
+ /** Cooldown for rate limit errors (HTTP 429) — default 30s */
1979
+ rateLimit?: number;
1980
+ /** Cooldown for server errors (HTTP 5xx) — default 60s */
1981
+ serverError?: number;
1982
+ /** Cooldown for connection failures — default 300s */
1983
+ connectionFailure?: number;
1984
+ /** Cooldown for content policy errors — default 0 (immediate retry with next) */
1985
+ contentPolicy?: number;
1986
+ }
1987
+ type ErrorCategory = 'rate_limit' | 'server_error' | 'connection_failure' | 'content_policy' | 'context_window' | 'unknown';
1988
+ declare function classifyError(error: unknown): ErrorCategory;
1989
+ interface FallbackEvent {
1990
+ fromProvider: string;
1991
+ toProvider: string;
1992
+ errorCategory: ErrorCategory;
1993
+ error: string;
1994
+ }
1995
+ interface CooldownEvent {
1996
+ providerId: string;
1997
+ errorCategory: ErrorCategory;
1998
+ cooldownMs: number;
1999
+ expiresAt: number;
2000
+ }
2001
+ declare class FallbackRouter implements InferenceProvider {
2002
+ readonly id = "fallback-router";
2003
+ readonly name = "Fallback Router";
2004
+ readonly tier: ProviderTier;
2005
+ private providers;
2006
+ private cooldowns;
2007
+ private cooldownMap;
2008
+ private events?;
2009
+ get capabilities(): ProviderCapabilities;
2010
+ constructor(config: FallbackRouterConfig);
2011
+ /** Get providers not currently in cooldown */
2012
+ getAvailableProviders(): InferenceProvider[];
2013
+ /** Get providers in cooldown with their expiry info */
2014
+ getCoolingDown(): Array<{
2015
+ providerId: string;
2016
+ category: ErrorCategory;
2017
+ expiresAt: number;
2018
+ }>;
2019
+ /** Manually clear cooldown for a provider */
2020
+ clearCooldown(providerId: string): void;
2021
+ /** Clear all cooldowns */
2022
+ clearAllCooldowns(): void;
2023
+ /** Add a provider to the chain (appended at lowest priority) */
2024
+ addProvider(provider: InferenceProvider): void;
2025
+ /** Remove a provider from the chain */
2026
+ removeProvider(id: string): void;
2027
+ /** Reorder providers (new priority order) */
2028
+ setOrder(ids: string[]): void;
2029
+ embed(request: EmbedRequest): Promise<EmbedResponse>;
2030
+ complete(request: CompletionRequest): Promise<CompletionResponse>;
2031
+ stream(request: CompletionRequest): AsyncIterable<StreamChunk>;
2032
+ listModels(): Promise<ModelInfo[]>;
2033
+ probe(): Promise<ProbeResult>;
2034
+ dispose(): void;
2035
+ private withFallback;
2036
+ private applyCooldown;
2037
+ }
2038
+
2039
+ type CspDirectiveName = 'default-src' | 'base-uri' | 'object-src' | 'frame-ancestors' | 'img-src' | 'font-src' | 'style-src' | 'script-src' | 'connect-src' | 'worker-src' | 'manifest-src' | 'report-uri';
2040
+ type CspDirectives = Partial<Record<CspDirectiveName, string[]>>;
2041
+ interface PluginCspOptions {
2042
+ scriptSrc?: string[];
2043
+ connectSrc?: string[];
2044
+ imgSrc?: string[];
2045
+ styleSrc?: string[];
2046
+ reportUri?: string;
2047
+ extraDirectives?: CspDirectives;
2048
+ }
2049
+ interface PluginScriptPolicy {
2050
+ allowedOrigins: string[];
2051
+ allowedUrls?: string[];
2052
+ requireSri?: boolean;
2053
+ }
2054
+ interface PluginScriptDescriptor {
2055
+ url: string;
2056
+ integrity?: string;
2057
+ crossOrigin?: 'anonymous' | 'use-credentials';
2058
+ }
2059
+ interface LoadedPluginScript {
2060
+ url: string;
2061
+ integrity: string;
2062
+ bytes: Uint8Array;
2063
+ text: string;
2064
+ }
2065
+ interface CspViolationReport {
2066
+ documentUri?: string;
2067
+ violatedDirective?: string;
2068
+ effectiveDirective?: string;
2069
+ blockedUri?: string;
2070
+ originalPolicy?: string;
2071
+ disposition?: string;
2072
+ sourceFile?: string;
2073
+ lineNumber?: number;
2074
+ columnNumber?: number;
2075
+ raw: unknown;
2076
+ }
2077
+ declare function buildPluginCsp(options?: PluginCspOptions): string;
2078
+ declare function computeSri(data: Uint8Array | ArrayBuffer, algorithm?: string): Promise<string>;
2079
+ declare function verifySri(data: Uint8Array | ArrayBuffer, integrity: string): Promise<boolean>;
2080
+ declare function isPluginScriptAllowed(url: string, policy: PluginScriptPolicy): boolean;
2081
+ declare function fetchPluginScript(descriptor: PluginScriptDescriptor, policy: PluginScriptPolicy, fetchFn?: typeof fetch): Promise<LoadedPluginScript>;
2082
+ declare function appendPluginScript(descriptor: PluginScriptDescriptor, policy: PluginScriptPolicy, doc?: Document): Promise<HTMLScriptElement>;
2083
+ declare function parseCspReport(body: unknown): CspViolationReport;
2084
+ declare function createCspReportHandler(onReport: (report: CspViolationReport) => void | Promise<void>): (request: Request) => Promise<Response>;
2085
+
2086
+ /**
2087
+ * Shard format types — matches the fortemi server matric-shard specification.
2088
+ *
2089
+ * A shard is a gzip-compressed tar archive (.shard) containing serialized
2090
+ * knowledge data with a manifest for integrity verification.
2091
+ */
2092
+ declare const CURRENT_SHARD_VERSION = "1.0.0";
2093
+ declare const SHARD_FORMAT = "matric-shard";
2094
+ /** Components that can appear in a shard archive. */
2095
+ type ShardComponent = 'notes' | 'collections' | 'tags' | 'links' | 'embedding_sets' | 'embedding_set_members' | 'embedding_configs' | 'embeddings';
2096
+ /** Manifest included in every shard as manifest.json. */
2097
+ interface ShardManifest {
2098
+ version: string;
2099
+ matric_version: string;
2100
+ format: typeof SHARD_FORMAT;
2101
+ created_at: string;
2102
+ components: ShardComponent[];
2103
+ counts: Partial<Record<ShardComponent, number>>;
2104
+ checksums: Record<string, string>;
2105
+ min_reader_version: string;
2106
+ }
2107
+ /** Options for shard export. */
2108
+ interface ExportOptions {
2109
+ includeEmbeddings?: boolean;
2110
+ /** Filter to specific collection (export only notes in this collection). */
2111
+ collectionId?: string;
2112
+ /** Filter to notes with this tag (e.g. 'app:research' for app-scoped export). */
2113
+ tag?: string;
2114
+ }
2115
+ /** Conflict resolution strategy for shard import. */
2116
+ type ConflictStrategy = 'skip' | 'replace' | 'error';
2117
+ /** Options for shard import. */
2118
+ interface ImportOptions {
2119
+ conflictStrategy?: ConflictStrategy;
2120
+ }
2121
+ /** Per-entity import counts. */
2122
+ interface ImportCounts {
2123
+ notes: number;
2124
+ collections: number;
2125
+ tags: number;
2126
+ links: number;
2127
+ embedding_sets: number;
2128
+ embedding_set_members: number;
2129
+ embeddings: number;
2130
+ }
2131
+ /** Result of a shard import operation. */
2132
+ interface ImportResult {
2133
+ success: boolean;
2134
+ counts: ImportCounts;
2135
+ skipped: Partial<ImportCounts>;
2136
+ warnings: string[];
2137
+ errors: string[];
2138
+ duration_ms: number;
2139
+ }
2140
+ /** Note as serialized in the shard JSONL. */
2141
+ interface ShardNote {
2142
+ id: string;
2143
+ title: string | null;
2144
+ original_content: string;
2145
+ revised_content: string | null;
2146
+ format: string;
2147
+ source: string;
2148
+ starred: boolean;
2149
+ archived: boolean;
2150
+ tags: string[];
2151
+ created_at: string;
2152
+ updated_at: string;
2153
+ deleted_at: string | null;
2154
+ }
2155
+ /** Collection as serialized in the shard JSON array. */
2156
+ interface ShardCollection {
2157
+ id: string;
2158
+ name: string;
2159
+ description: string | null;
2160
+ parent_id: string | null;
2161
+ created_at: string;
2162
+ note_count?: number;
2163
+ }
2164
+ /** Tag as serialized in the shard JSON array. */
2165
+ interface ShardTag {
2166
+ name: string;
2167
+ created_at: string;
2168
+ }
2169
+ /** Link as serialized in the shard JSONL. */
2170
+ interface ShardLink {
2171
+ id: string;
2172
+ from_note_id: string;
2173
+ to_note_id: string;
2174
+ kind: string;
2175
+ score: number | null;
2176
+ created_at: string;
2177
+ metadata?: Record<string, unknown>;
2178
+ }
2179
+ /** Embedding set as serialized in the shard JSON array. */
2180
+ interface ShardEmbeddingSet {
2181
+ id: string;
2182
+ model: string;
2183
+ dimension: number;
2184
+ created_at: string;
2185
+ }
2186
+ /** Embedding set member as serialized in the shard JSONL. */
2187
+ interface ShardEmbeddingSetMember {
2188
+ embedding_set_id: string;
2189
+ note_id: string;
2190
+ embedding_id: string;
2191
+ }
2192
+ /** Embedding as serialized in the shard JSONL. */
2193
+ interface ShardEmbedding {
2194
+ id: string;
2195
+ note_id: string;
2196
+ embedding_set_id: string;
2197
+ vector: number[];
2198
+ created_at: string;
2199
+ }
2200
+
2201
+ /**
2202
+ * Minimal tar + gzip packing/unpacking for shard archives.
2203
+ *
2204
+ * Uses fflate for gzip compression and implements a lightweight POSIX tar
2205
+ * encoder/decoder (512-byte block headers, ustar format).
2206
+ */
2207
+ /**
2208
+ * Pack files into a gzip-compressed tar archive.
2209
+ *
2210
+ * @param files Map of filename → file contents
2211
+ * @returns Compressed archive bytes (suitable for .shard file)
2212
+ */
2213
+ declare function packTarGz(files: Map<string, Uint8Array>): Uint8Array;
2214
+ /**
2215
+ * Unpack a gzip-compressed tar archive.
2216
+ *
2217
+ * @param data Compressed archive bytes
2218
+ * @returns Map of filename → file contents
2219
+ */
2220
+ declare function unpackTarGz(data: Uint8Array): Map<string, Uint8Array>;
2221
+
2222
+ /**
2223
+ * SHA-256 checksum utilities for shard integrity verification.
2224
+ * Uses the Web Crypto API (browser-native, no extra dependencies).
2225
+ */
2226
+ /**
2227
+ * Compute SHA-256 hex digest of a Uint8Array.
2228
+ * Returns lowercase hex string (64 characters).
2229
+ */
2230
+ declare function sha256Hex(data: Uint8Array): Promise<string>;
2231
+ /**
2232
+ * Validate checksums listed in a shard manifest against actual file contents.
2233
+ *
2234
+ * @returns Object with `valid` flag and list of failed filenames.
2235
+ */
2236
+ declare function validateChecksums(checksums: Record<string, string>, files: Map<string, Uint8Array>): Promise<{
2237
+ valid: boolean;
2238
+ failures: string[];
2239
+ }>;
2240
+
2241
+ /**
2242
+ * Field mapper — converts between browser schema and shard (server) schema.
2243
+ *
2244
+ * The browser uses different field names than the server shard format.
2245
+ * This module handles all rename transforms bidirectionally.
2246
+ */
2247
+
2248
+ /** Browser-format note row from the export query (denormalized). */
2249
+ interface BrowserNoteExport {
2250
+ id: string;
2251
+ title: string | null;
2252
+ format: string;
2253
+ source: string;
2254
+ is_starred: boolean;
2255
+ is_archived: boolean;
2256
+ created_at: Date | string;
2257
+ updated_at: Date | string;
2258
+ deleted_at: Date | string | null;
2259
+ original_content: string;
2260
+ revised_content: string | null;
2261
+ tags: string[];
2262
+ }
2263
+ /** Convert a browser note to shard format. */
2264
+ declare function noteToShard(note: BrowserNoteExport): ShardNote;
2265
+ /** Convert a shard note back to browser-insertable format. */
2266
+ declare function noteFromShard(shard: ShardNote): BrowserNoteExport;
2267
+ /** Convert a browser link to shard format. */
2268
+ declare function linkToShard(link: LinkRow): ShardLink;
2269
+ /** Convert a shard link back to browser-insertable format. */
2270
+ declare function linkFromShard(shard: ShardLink): {
2271
+ id: string;
2272
+ source_note_id: string;
2273
+ target_note_id: string;
2274
+ link_type: string;
2275
+ confidence: number | null;
2276
+ created_at: string;
2277
+ };
2278
+ /** Convert a browser collection to shard format. */
2279
+ declare function collectionToShard(collection: CollectionRow, noteCount?: number): ShardCollection;
2280
+ /** Convert a shard collection back to browser-insertable format. */
2281
+ declare function collectionFromShard(shard: ShardCollection): {
2282
+ id: string;
2283
+ name: string;
2284
+ description: string | null;
2285
+ parent_id: string | null;
2286
+ created_at: string;
2287
+ };
2288
+ /**
2289
+ * Convert SKOS concepts + note_tag associations into shard flat tag format.
2290
+ * Shard tags are simple string arrays — deduplicated across all notes.
2291
+ */
2292
+ declare function tagsToShard(allTags: Array<{
2293
+ name: string;
2294
+ created_at: Date | string;
2295
+ }>): ShardTag[];
2296
+ /**
2297
+ * Convert shard flat tags to browser format for insertion.
2298
+ * Returns unique tag names ready for note_tag association.
2299
+ */
2300
+ declare function tagsFromShard(shardTags: ShardTag[]): string[];
2301
+ /** Convert a browser embedding_set to shard format. */
2302
+ declare function embeddingSetToShard(set: {
2303
+ id: string;
2304
+ model_name: string;
2305
+ dimensions: number;
2306
+ created_at: Date | string;
2307
+ }): ShardEmbeddingSet;
2308
+ /** Convert a shard embedding set back to browser format. */
2309
+ declare function embeddingSetFromShard(shard: ShardEmbeddingSet): {
2310
+ id: string;
2311
+ model_name: string;
2312
+ dimensions: number;
2313
+ created_at: string;
2314
+ };
2315
+ /** Convert a browser embedding_set_member to shard format. */
2316
+ declare function embeddingSetMemberToShard(member: {
2317
+ embedding_set_id: string;
2318
+ note_id: string;
2319
+ embedding_id: string;
2320
+ }): ShardEmbeddingSetMember;
2321
+ /** Convert a browser embedding to shard format. */
2322
+ declare function embeddingToShard(emb: {
2323
+ id: string;
2324
+ note_id: string;
2325
+ embedding_set_id: string;
2326
+ vector: string | number[];
2327
+ created_at: Date | string;
2328
+ }): ShardEmbedding;
2329
+ /** Convert a shard embedding back to browser format. */
2330
+ declare function embeddingFromShard(shard: ShardEmbedding): {
2331
+ id: string;
2332
+ note_id: string;
2333
+ embedding_set_id: string;
2334
+ vector: string;
2335
+ created_at: string;
2336
+ };
2337
+
2338
+ /**
2339
+ * Shard export pipeline — query all entities, serialize, pack into .shard archive.
2340
+ *
2341
+ * Pipeline: query DB → field-map → serialize (JSONL/JSON) → compute checksums → build manifest → tar.gz
2342
+ */
2343
+
2344
+ /**
2345
+ * Export knowledge data from the database as a .shard archive (Uint8Array).
2346
+ *
2347
+ * @param db DatabaseClient database instance
2348
+ * @param options Export options (includeEmbeddings, collectionId filter)
2349
+ * @returns Compressed shard archive bytes
2350
+ */
2351
+ declare function exportShard(db: DatabaseClient, options?: ExportOptions): Promise<Uint8Array>;
2352
+
2353
+ /**
2354
+ * Shard import pipeline — unpack, validate, field-map, transactional insert.
2355
+ *
2356
+ * Pipeline: ArrayBuffer → gunzip → untar → parse manifest → validate checksums →
2357
+ * parse components → field-map → BEGIN transaction → INSERT all → COMMIT
2358
+ */
2359
+
2360
+ /**
2361
+ * Import a .shard archive into the database.
2362
+ *
2363
+ * The entire import is wrapped in a single transaction — if anything fails,
2364
+ * all changes are rolled back.
2365
+ *
2366
+ * @param db DatabaseClient database instance
2367
+ * @param data Raw archive bytes (from File API or fetch)
2368
+ * @param options Import options (conflict strategy)
2369
+ * @returns Import result with counts, warnings, and errors
2370
+ */
2371
+ declare function importShard(db: DatabaseClient, data: Uint8Array | ArrayBuffer, options?: ImportOptions): Promise<ImportResult>;
2372
+
2373
+ declare const VERSION = "2026.5.0";
2374
+
2375
+ export { type ArchiveInfo, ArchiveManager, type AttachInput, type AttachmentBlobRow, type AttachmentRow, AttachmentsRepository, type BlobStore, type BrowserNoteExport, CURRENT_SHARD_VERSION, type CapabilityInfo, CapabilityManager, type CapabilityName, type CapabilityState, type CaptureKnowledgeInput, CaptureKnowledgeInputSchema, type CaptureKnowledgeResult, type CollectionCreateInput, type CollectionRow, CollectionsRepository, type CompletionRequest, type CompletionResponse, type ConditionResult, type ConflictStrategy, type CooldownConfig, type CooldownEvent, type CspDirectiveName, type CspDirectives, type CspViolationReport, type DatabaseClient, type DiscoveredProvider, type DiscoveryOptions, type EmbedFunction, type EmbedRequest, type EmbedResponse, type EnqueueJobInput, type ErrorCategory, type EventMap, type ExportOptions, type FallbackEvent, FallbackRouter, type FallbackRouterConfig, type FortemiConfig, type FortemiCore, type FortemiToolDefinition, FortemiToolManifest, type GetNoteInput, GetNoteInputSchema, type GpuCapabilities, type IDisposable, type ImportCounts, type ImportOptions, type ImportResult, type InferenceCapabilities, type InferenceProvider, JOB_CAPABILITIES, JOB_PRIORITIES, type JobQueueOptions, JobQueueWorker, type JobStatus, type JobType, LOCAL_ENDPOINTS, type LinkRow, LinksRepository, type ListNotesInput, ListNotesInputSchema, type LlmCapabilityOptions, type LlmCompleteFn, type LoadedPluginScript, type LocalEndpoint, type ManageArchiveInput, ManageArchiveInputSchema, type ManageArchiveResult, type ManageAttachmentsInput, ManageAttachmentsInputSchema, type ManageAttachmentsResult, type ManageCapabilitiesInput, ManageCapabilitiesInputSchema, type ManageCapabilitiesResult, type ManageCollectionsInput, ManageCollectionsInputSchema, type ManageCollectionsResult, type ManageLinksInput, ManageLinksInputSchema, type ManageLinksResult, type ManageNoteInput, ManageNoteInputSchema, type ManageNoteResult, type ManageTagsInput, ManageTagsInputSchema, type ManageTagsResult, MemoryBlobStore, type Migration, MigrationRunner, type ModelCategory, type ModelFitResult, type ModelInfo, type NoteCreateInput, type NoteFull, type NoteListOptions, type NoteRevision, type NoteSummary, type NoteUpdateInput, NotesRepository, OpenAICompatibleProvider, type OpenAIProviderConfig, PGliteStorageBackend, PGliteStorageBackendFactory, PGliteWorkerClient, type PaginatedResult, type PersistenceMode, type PlinyCapability, type PluginCspOptions, type PluginScriptDescriptor, type PluginScriptPolicy, type ProbeResult, type ProbeStatus, type ProviderCapabilities, ProviderRegistry, type ProviderTier, type QueryExecutor, type QueryResult, type RecommendedTier, type RouteHandler, SHARD_FORMAT, type SWRegistrationResult, type SearchFacets, type SearchInput, SearchInputSchema, type SearchOptions, SearchRepository, type SearchResponse, type SearchResult, type ShardCollection, type ShardComponent, type ShardEmbedding, type ShardEmbeddingSet, type ShardEmbeddingSetMember, type ShardLink, type ShardManifest, type ShardNote, type ShardTag, type SkosConcept, type SkosRelation, SkosRepository, type SkosScheme, type StorageBackend, type StorageBackendFactory, type StorageOpenRequest, type StorageTopology, type StreamChunk, TagsRepository, TransactionProxy, TypedEventBus, VERSION, type VramTier, type WorkerRequest, type WorkerResponse, aiRevisionHandler, allMigrations, appendPluginScript, buildNoteConditions, buildPluginCsp, captureKnowledge, chunkText, classifyError, classifyModel, collectionFromShard, collectionToShard, computeHash, computeSri, conceptTaggingHandler, cosineSimilarity, createBlobStore, createCspReportHandler, createFortemi, createLegacyProvider, createPGliteInstance, createRoutes, defaultStorageBackendFactory, detectGpuCapabilities, detectInferenceCapabilities, discoverLocalProviders, embeddingFromShard, embeddingGenerationHandler, embeddingSetFromShard, embeddingSetMemberToShard, embeddingSetToShard, embeddingToShard, enqueueFullWorkflow, enqueueJob, enqueueNoteCreationJobs, estimateModelFit, estimateVramMB, estimateVramTier, exportShard, fetchPluginScript, fortemiManifest, generateId, getEmbedFunction, getJobQueueStatus, getLlmFunction, getNote, importShard, isPluginScriptAllowed, linkFromShard, linkToShard, linkingHandler, listNotes, manageArchive, manageAttachments, manageCapabilities, manageCollections, manageLinks, manageNote, manageTags, matchRoute, noteFromShard, noteToShard, packTarGz, parseCspReport, registerLlmCapability, registerSemanticCapability, registerServiceWorker, searchTool, selectLlmModel, setEmbedFunction, setLlmFunction, sha256Hex, suggestTags, tagsFromShard, tagsToShard, titleGenerationHandler, unpackTarGz, unregisterLlmCapability, unregisterSemanticCapability, validateChecksums, verifySri };