@mikesaintsg/core 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,7 +13,9 @@
13
13
  - ✅ **Shared Types** — Contracts used across multiple packages
14
14
  - ✅ **Result Pattern** — Functional error handling (`ok`, `err`, `map`, `chain`)
15
15
  - ✅ **Bridge Functions** — Connect packages without circular dependencies
16
- - ✅ **Interface Definitions** — Embedding, tool format, and persistence adapters
16
+ - ✅ **Adapter Interfaces** — Embedding, tool format, persistence, and policy adapters
17
+ - ✅ **Base Error Class** — `EcosystemError` for all package-specific errors
18
+ - ✅ **Content Hashing** — SHA-256 based deduplication support
17
19
  - ✅ **Zero dependencies** — Built on native platform APIs
18
20
  - ✅ **TypeScript first** — Full type safety with generics
19
21
  - ✅ **Tree-shakeable** — ESM-only, import what you need
@@ -30,6 +32,8 @@ npm install @mikesaintsg/core
30
32
 
31
33
  ## Quick Start
32
34
 
35
+ ### Result Pattern
36
+
33
37
  ```ts
34
38
  import { ok, err, isOk, map, chain } from '@mikesaintsg/core'
35
39
  import type { Result } from '@mikesaintsg/core'
@@ -55,6 +59,33 @@ function parse(s: string): Result<number, string> {
55
59
  const result = chain(ok('42'), parse) // ok(42)
56
60
  ```
57
61
 
62
+ ### Content Hashing
63
+
64
+ ```ts
65
+ import { computeContentHash } from '@mikesaintsg/core'
66
+
67
+ const hash = await computeContentHash('Hello, world!')
68
+ // 'a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e'
69
+ ```
70
+
71
+ ### Tool Call Bridge
72
+
73
+ ```ts
74
+ import { createToolCallBridge } from '@mikesaintsg/core'
75
+
76
+ const bridge = createToolCallBridge({
77
+ registry,
78
+ timeout: 30000,
79
+ onError: (error, toolCall) => console.error(error),
80
+ })
81
+
82
+ // Execute single call
83
+ const result = await bridge.execute(toolCall)
84
+
85
+ // Execute multiple calls in parallel
86
+ const results = await bridge.execute([call1, call2, call3])
87
+ ```
88
+
58
89
  ---
59
90
 
60
91
  ## Documentation
@@ -64,7 +95,6 @@ const result = chain(ok('42'), parse) // ok(42)
64
95
  ### Key Sections
65
96
 
66
97
  - [Introduction](./guides/core.md#introduction) — Value proposition and use cases
67
- - [Quick Start](./guides/core.md#quick-start) — Get started in minutes
68
98
  - [Core Concepts](./guides/core.md#core-concepts) — Understand the fundamentals
69
99
  - [Result Pattern](./guides/core.md#result-pattern) — Functional error handling
70
100
  - [Bridge Interfaces](./guides/core.md#bridge-interfaces) — Cross-package communication
@@ -76,17 +106,33 @@ const result = chain(ok('42'), parse) // ok(42)
76
106
 
77
107
  ### Result Functions
78
108
 
79
- | Function | Description |
80
- |---------------------------|----------------------------|
81
- | `ok(value)` | Create a success result |
82
- | `err(error)` | Create a failure result |
83
- | `isOk(result)` | Check if result is success |
84
- | `isErr(result)` | Check if result is failure |
85
- | `unwrap(result, default)` | Get value or default |
86
- | `map(result, fn)` | Transform success value |
87
- | `chain(result, fn)` | Chain results (flatMap) |
109
+ | Function | Description |
110
+ |------------------------------|------------------------------|
111
+ | `ok(value)` | Create a success result |
112
+ | `err(error)` | Create a failure result |
113
+ | `isOk(result)` | Check if result is success |
114
+ | `isErr(result)` | Check if result is failure |
115
+ | `unwrap(result, default)` | Get value or default |
116
+ | `unwrapOrThrow(result)` | Get value or throw error |
117
+ | `map(result, fn)` | Transform success value |
118
+ | `mapErr(result, fn)` | Transform error value |
119
+ | `chain(result, fn)` | Chain results (flatMap) |
120
+
121
+ ### Content Hashing
88
122
 
89
- ### Bridge Functions
123
+ | Function | Description |
124
+ |------------------------------|------------------------------|
125
+ | `computeContentHash(text)` | SHA-256 hash for text |
126
+
127
+ ### Bridge Helper Functions
128
+
129
+ | Function | Description |
130
+ |------------------------------|-----------------------------------|
131
+ | `isToolCall(value)` | Type guard for ToolCall objects |
132
+ | `shouldSkipFormGuard(...)` | Check if form guard should skip |
133
+ | `formatScoredResult(result)` | Default result formatter |
134
+
135
+ ### Factory Functions
90
136
 
91
137
  | Function | Description |
92
138
  |-------------------------------------|----------------------------------|
@@ -95,15 +141,57 @@ const result = chain(ok('42'), parse) // ok(42)
95
141
  | `createFormDirtyGuard(options)` | Navigation guard for dirty forms |
96
142
  | `createSessionPersistence(options)` | Session storage adapter |
97
143
 
144
+ ### Error Handling
145
+
146
+ | Export | Description |
147
+ |------------------------|------------------------------------|
148
+ | `EcosystemError` | Base error class for all packages |
149
+ | `isEcosystemError(e)` | Type guard for ecosystem errors |
150
+
98
151
  ### Shared Types
99
152
 
100
- | Type | Description |
101
- |------------------------------|---------------------------------|
102
- | `Result<T, E>` | Success or failure union |
103
- | `Unsubscribe` | Cleanup function type |
104
- | `EmbeddingAdapterInterface` | Embedding generation contract |
105
- | `ToolFormatAdapterInterface` | Tool format conversion |
106
- | `BuiltContext` | Assembled context for inference |
153
+ | Type | Description |
154
+ |-------------------------------------------|---------------------------------------|
155
+ | `Result<T, E>` | Success or failure union |
156
+ | `Ok<T>`, `Err<E>` | Result discriminants |
157
+ | `Unsubscribe` | Cleanup function type |
158
+ | `DestroyFn` | Resource cleanup function |
159
+ | `SubscriptionToHook<T>` | Convert subscriptions to hooks |
160
+ | `Embedding` | Float32Array embedding vector |
161
+ | `ToolCall`, `ToolResult`, `ToolSchema` | Tool-related types |
162
+ | `ScoredResult` | Search result with score |
163
+ | `ContextFrame`, `BuiltContext` | Context management types |
164
+ | `TokenBudgetState`, `TokenBudgetLevel` | Token budget types |
165
+
166
+ ### Adapter Interfaces
167
+
168
+ | Interface | Category | Description |
169
+ |-------------------------------------------|---------------|--------------------------------|
170
+ | `EmbeddingAdapterInterface` | Source | Embedding generation |
171
+ | `ToolFormatAdapterInterface` | Transform | Provider tool formatting |
172
+ | `SimilarityAdapterInterface` | Transform | Vector similarity computation |
173
+ | `DeduplicationAdapterInterface` | Transform | Frame deduplication |
174
+ | `TruncationAdapterInterface` | Transform | Context truncation |
175
+ | `PriorityAdapterInterface` | Transform | Frame priority ordering |
176
+ | `RetryAdapterInterface` | Policy | Retry behavior |
177
+ | `RateLimitAdapterInterface` | Policy | Rate limiting |
178
+ | `EmbeddingCacheAdapterInterface` | Enhancement | Embedding caching |
179
+ | `BatchAdapterInterface` | Enhancement | Batch processing |
180
+ | `RerankerAdapterInterface` | Enhancement | Result reranking |
181
+ | `VectorStorePersistenceAdapterInterface` | Persistence | Vector storage |
182
+
183
+ ### Minimal Cross-Package Interfaces
184
+
185
+ | Interface | Description |
186
+ |-----------------------------|--------------------------------------|
187
+ | `MinimalDatabaseAccess<T>` | IndexedDB access without dependency |
188
+ | `MinimalStoreAccess<T>` | Store operations interface |
189
+ | `MinimalDirectoryAccess` | OPFS directory access |
190
+ | `MinimalFileAccess` | OPFS file access |
191
+ | `ToolRegistryMinimal` | Tool registry without dependency |
192
+ | `VectorStoreMinimal<T>` | Vector store without dependency |
193
+ | `FormMinimal<T>` | Form state without dependency |
194
+ | `SerializableSession` | Session serialization interface |
107
195
 
108
196
  ---
109
197
 
@@ -112,7 +200,7 @@ const result = chain(ok('42'), parse) // ok(42)
112
200
  ### Result Pattern
113
201
 
114
202
  ```ts
115
- import { ok, err, isOk, unwrap } from '@mikesaintsg/core'
203
+ import { ok, err, isOk, unwrap, map, chain } from '@mikesaintsg/core'
116
204
 
117
205
  function divide(a: number, b: number) {
118
206
  if (b === 0) return err('DIVISION_BY_ZERO')
@@ -121,52 +209,109 @@ function divide(a: number, b: number) {
121
209
 
122
210
  const result = divide(10, 2)
123
211
  const value = unwrap(result, 0) // 5
212
+
213
+ // Chain operations
214
+ const doubled = chain(divide(10, 2), n => ok(n * 2)) // ok(10)
124
215
  ```
125
216
 
126
- ### Tool Call Bridge
217
+ ### Custom Error Class
127
218
 
128
219
  ```ts
129
- import { createToolCallBridge } from '@mikesaintsg/core'
220
+ import { EcosystemError, isEcosystemError } from '@mikesaintsg/core'
130
221
 
131
- const bridge = createToolCallBridge({
132
- registry,
133
- timeout: 30000,
134
- onError: (error, toolCall) => console.error(error),
222
+ type StorageErrorCode = 'NOT_FOUND' | 'QUOTA_EXCEEDED' | 'WRITE_FAILED'
223
+
224
+ class StorageError extends EcosystemError {
225
+ readonly code: StorageErrorCode
226
+
227
+ constructor(code: StorageErrorCode, message: string, cause?: Error) {
228
+ super(message, cause)
229
+ this.code = code
230
+ }
231
+ }
232
+
233
+ try {
234
+ throw new StorageError('NOT_FOUND', 'Document not found')
235
+ } catch (error) {
236
+ if (isEcosystemError(error)) {
237
+ console.log(error.code) // 'NOT_FOUND'
238
+ }
239
+ }
240
+ ```
241
+
242
+ ### Retrieval Tool
243
+
244
+ ```ts
245
+ import { createRetrievalTool } from '@mikesaintsg/core'
246
+
247
+ const { schema, handler } = createRetrievalTool({
248
+ vectorStore,
249
+ name: 'search_docs',
250
+ description: 'Search documentation for relevant information',
251
+ defaultLimit: 5,
252
+ scoreThreshold: 0.7,
135
253
  })
136
254
 
137
- const result = await bridge.execute(toolCall)
255
+ // Register with tool registry
256
+ registry.register(schema, handler)
138
257
  ```
139
258
 
140
- ### With TypeScript
259
+ ### Session Persistence
141
260
 
142
261
  ```ts
143
- import type {
144
- EmbeddingAdapterInterface,
145
- Result
146
- } from '@mikesaintsg/core'
262
+ import { createSessionPersistence } from '@mikesaintsg/core'
147
263
 
148
- // Type-safe adapter interface
149
- const adapter: EmbeddingAdapterInterface = createAdapter()
264
+ const persistence = createSessionPersistence({
265
+ database,
266
+ storeName: 'chat_sessions',
267
+ autoprune: 7 * 24 * 60 * 60 * 1000, // 7 days
268
+ })
150
269
 
151
- // Inferred result types
152
- function safeParse(input: string): Result<number, 'PARSE_ERROR'> {
153
- const n = parseInt(input, 10)
154
- return isNaN(n) ? err('PARSE_ERROR') : ok(n)
155
- }
270
+ await persistence.save('session-1', session)
271
+ const loaded = await persistence.load('session-1')
156
272
  ```
157
273
 
274
+ ### Form Dirty Guard
275
+
276
+ ```ts
277
+ import { createFormDirtyGuard } from '@mikesaintsg/core'
278
+
279
+ const guard = createFormDirtyGuard({
280
+ form,
281
+ confirmFn: (message) => window.confirm(message),
282
+ message: 'You have unsaved changes. Continue?',
283
+ excludePages: ['logout'],
284
+ })
285
+
286
+ router.beforeNavigate(guard)
287
+ ```
288
+
289
+ ---
290
+
291
+ ## Constants
292
+
293
+ | Constant | Value | Description |
294
+ |------------------------------|--------|--------------------------------|
295
+ | `BRIDGE_DEFAULT_TIMEOUT` | 30000 | Default bridge timeout (ms) |
296
+ | `RETRIEVAL_DEFAULT_LIMIT` | 10 | Default retrieval result limit |
297
+ | `RETRIEVAL_MAX_LIMIT` | 100 | Maximum retrieval result limit |
298
+ | `FORM_DIRTY_DEFAULT_MESSAGE` | string | Default form guard message |
299
+
158
300
  ---
159
301
 
160
302
  ## Ecosystem Integration
161
303
 
162
304
  | Package | Integration |
163
305
  |--------------------------------|------------------------------------------------|
164
- | `@mikesaintsg/adapters` | Provider and embedding adapter implementations |
306
+ | `@mikesaintsg/adapters` | Implements adapter interfaces |
165
307
  | `@mikesaintsg/inference` | Uses shared types and bridge functions |
166
308
  | `@mikesaintsg/vectorstore` | Uses embedding and persistence interfaces |
167
309
  | `@mikesaintsg/contextprotocol` | Uses tool types and registry interface |
310
+ | `@mikesaintsg/contextbuilder` | Uses context frame and budget types |
311
+ | `@mikesaintsg/indexeddb` | Implements MinimalDatabaseAccess |
312
+ | `@mikesaintsg/filesystem` | Implements MinimalDirectoryAccess |
168
313
 
169
- See [Integration Patterns](./guides/core.md#integration-patterns) for details.
314
+ See [Integration Guide](./guides/integration.md) for detailed patterns.
170
315
 
171
316
  ---
172
317
 
package/dist/index.d.ts CHANGED
@@ -3,13 +3,17 @@ export declare interface AbortableOptions {
3
3
  readonly signal?: AbortSignal;
4
4
  }
5
5
 
6
- /** Batched embedding adapter interface - extends base with batching */
7
- export declare interface BatchedEmbeddingAdapterInterface extends EmbeddingAdapterInterface {
8
- queue(text: string, options?: AbortableOptions): Promise<Embedding>;
9
- queueBatch(texts: readonly string[], options?: AbortableOptions): Promise<readonly Embedding[]>;
10
- flush(): Promise<void>;
11
- getPendingCount(): number;
12
- getCache(): EmbeddingCacheInterface | undefined;
6
+ /**
7
+ * Batch adapter interface.
8
+ * Controls batching behavior for bulk operations.
9
+ */
10
+ export declare interface BatchAdapterInterface {
11
+ /** Maximum items per batch */
12
+ getBatchSize(): number;
13
+ /** Delay between batches (ms) */
14
+ getDelayMs(): number;
15
+ /** Whether to deduplicate items within a batch */
16
+ shouldDeduplicate(): boolean;
13
17
  }
14
18
 
15
19
  /** Default timeout for bridge operations in milliseconds */
@@ -26,6 +30,14 @@ export declare interface BuiltContext {
26
30
  readonly timestamp: number;
27
31
  }
28
32
 
33
+ /** Cache statistics */
34
+ export declare interface CacheStats {
35
+ readonly hits: number;
36
+ readonly misses: number;
37
+ readonly size: number;
38
+ readonly maxSize?: number;
39
+ }
40
+
29
41
  /**
30
42
  * Chain results (flatMap). Apply a function that returns a Result to a success value.
31
43
  *
@@ -76,26 +88,6 @@ export declare interface ContextFrame {
76
88
  readonly metadata?: FrameMetadata;
77
89
  }
78
90
 
79
- /**
80
- * Core package error.
81
- *
82
- * @example
83
- * ```ts
84
- * throw new CoreError('ADAPTER_ERROR', 'Failed to connect to OpenAI')
85
- * ```
86
- */
87
- export declare class CoreError extends Error {
88
- readonly code: CoreErrorCode;
89
- readonly cause: Error | undefined;
90
- constructor(code: CoreErrorCode, message: string, cause?: Error);
91
- }
92
-
93
- /** Core package error codes */
94
- export declare type CoreErrorCode = 'ADAPTER_ERROR' | 'BRIDGE_ERROR' | 'VALIDATION_ERROR' | 'NOT_FOUND' | 'TIMEOUT' | 'ABORTED';
95
-
96
- /** Factory function for creating embedding cache */
97
- export declare type CreateEmbeddingCache = (options?: EmbeddingCacheOptions) => EmbeddingCacheInterface;
98
-
99
91
  /**
100
92
  * Create a navigation guard that prevents leaving when form is dirty.
101
93
  *
@@ -198,11 +190,23 @@ export declare function createSessionPersistence(options: SessionPersistenceOpti
198
190
  * })
199
191
  *
200
192
  * // Execute tool calls from LLM response
201
- * const results = await bridge.executeAll(response.toolCalls)
193
+ * const results = await bridge.execute(response.toolCalls)
202
194
  * ```
203
195
  */
204
196
  export declare function createToolCallBridge(options: ToolCallBridgeOptions): ToolCallBridgeInterface;
205
197
 
198
+ /**
199
+ * Deduplication adapter interface.
200
+ * Determines how to handle duplicate frames based on content hash.
201
+ * Implemented in @mikesaintsg/adapters.
202
+ */
203
+ export declare interface DeduplicationAdapterInterface {
204
+ /** Select which frame to keep from duplicates with the same content hash */
205
+ select(frames: readonly ContextFrame[]): ContextFrame;
206
+ /** Check if a frame should be preserved regardless of deduplication */
207
+ shouldPreserve(frame: ContextFrame): boolean;
208
+ }
209
+
206
210
  /** Deduplication result summary */
207
211
  export declare interface DeduplicationResult {
208
212
  readonly originalCount: number;
@@ -212,73 +216,87 @@ export declare interface DeduplicationResult {
212
216
  readonly tokensSaved: number;
213
217
  }
214
218
 
219
+ /** Deduplication strategy for default adapter */
220
+ export declare type DeduplicationStrategy = 'keep_latest' | 'keep_first' | 'keep_highest_priority' | 'merge';
221
+
222
+ /** Resource that must be explicitly destroyed */
223
+ export declare interface Destroyable {
224
+ /** Release all resources held by this instance. After calling, the instance is unusable. */
225
+ destroy(): void;
226
+ }
227
+
228
+ /**
229
+ * @mikesaintsg/core
230
+ *
231
+ * Base error class and utilities for the ecosystem.
232
+ */
215
233
  /**
216
234
  * Base error class for all ecosystem errors.
217
235
  * All package-specific errors should extend this class.
236
+ *
237
+ * @example
238
+ * ```ts
239
+ * class StorageError extends EcosystemError {
240
+ * readonly code: StorageErrorCode
241
+ *
242
+ * constructor(code: StorageErrorCode, message: string, cause?: Error) {
243
+ * super(message, cause)
244
+ * this.code = code
245
+ * }
246
+ * }
247
+ * ```
218
248
  */
219
249
  export declare abstract class EcosystemError extends Error {
250
+ /** Error code for programmatic handling */
220
251
  abstract readonly code: string;
252
+ /** Original error that caused this one */
221
253
  readonly cause: Error | undefined;
222
254
  constructor(message: string, cause?: Error);
223
255
  }
224
256
 
225
- /** Embedding vector */
257
+ /** A single embedding vector. Float32Array for memory efficiency and typed array operations. */
226
258
  export declare type Embedding = Float32Array;
227
259
 
228
- /** Embedding generation contract */
260
+ /**
261
+ * Contract for embedding generation.
262
+ * Implemented by adapters, consumed by vectorstore.
263
+ */
229
264
  export declare interface EmbeddingAdapterInterface {
265
+ /**
266
+ * Generate embeddings for one or more texts.
267
+ * @param texts - Texts to embed
268
+ * @param options - Optional abort signal
269
+ * @returns Embeddings in same order as input texts
270
+ */
230
271
  embed(texts: readonly string[], options?: AbortableOptions): Promise<readonly Embedding[]>;
272
+ /** Get metadata about the embedding model. Used for compatibility checking. */
231
273
  getModelMetadata(): EmbeddingModelMetadata;
232
274
  }
233
275
 
234
- /** Embedding batch options */
235
- export declare interface EmbeddingBatchOptions {
236
- readonly maxBatchSize?: number;
237
- readonly flushDelayMs?: number;
238
- readonly deduplicate?: boolean;
239
- readonly cache?: EmbeddingCacheInterface;
240
- }
241
-
242
- /** Embedding cache entry */
243
- export declare interface EmbeddingCacheEntry {
244
- readonly embedding: Embedding;
245
- readonly contentHash: ContentHash;
246
- readonly modelId: string;
247
- readonly createdAt: number;
248
- readonly hitCount: number;
249
- }
250
-
251
- /** Embedding cache interface */
252
- export declare interface EmbeddingCacheInterface {
253
- get(contentHash: ContentHash): Embedding | undefined;
254
- set(contentHash: ContentHash, embedding: Embedding): void;
255
- has(contentHash: ContentHash): boolean;
256
- remove(contentHash: ContentHash): boolean;
276
+ /**
277
+ * Embedding cache adapter interface.
278
+ * Provides caching for embedding operations.
279
+ */
280
+ export declare interface EmbeddingCacheAdapterInterface {
281
+ /** Get cached embedding for text */
282
+ get(text: string): Embedding | undefined;
283
+ /** Store embedding in cache */
284
+ set(text: string, embedding: Embedding): void;
285
+ /** Check if text is cached */
286
+ has(text: string): boolean;
287
+ /** Clear all cached embeddings */
257
288
  clear(): void;
258
- getStats(): EmbeddingCacheStats;
289
+ /** Optional: Get cache statistics */
290
+ getStats?(): CacheStats;
259
291
  }
260
292
 
261
- /** LRU cache eviction options */
262
- export declare interface EmbeddingCacheOptions {
263
- readonly maxEntries?: number;
264
- readonly maxBytes?: number;
265
- readonly ttlMs?: number;
266
- readonly onEvict?: (contentHash: ContentHash, embedding: Embedding) => void;
267
- }
268
-
269
- /** Embedding cache statistics */
270
- export declare interface EmbeddingCacheStats {
271
- readonly entries: number;
272
- readonly hits: number;
273
- readonly misses: number;
274
- readonly hitRate: number;
275
- readonly estimatedBytes: number;
276
- }
277
-
278
- /** Embedding model info */
293
+ /** Metadata identifying an embedding model. Used to ensure vector compatibility. */
279
294
  export declare interface EmbeddingModelMetadata {
295
+ /** Provider name (e.g., 'openai', 'anthropic') */
280
296
  readonly provider: string;
297
+ /** Model identifier (e.g., 'text-embedding-3-small') */
281
298
  readonly model: string;
299
+ /** Vector dimensions produced by this model */
282
300
  readonly dimensions: number;
283
301
  }
284
302
 
@@ -303,12 +321,23 @@ export declare interface Err<E> {
303
321
  */
304
322
  export declare function err<E>(error: E): Err<E>;
305
323
 
306
- /** Extract error code type */
307
- export declare type ErrorCode<T extends EcosystemError> = T['code'];
324
+ /** Extract error code type from an error class */
325
+ export declare type ErrorCode<T extends {
326
+ readonly code: string;
327
+ }> = T['code'];
308
328
 
309
329
  /** Default form dirty guard message */
310
330
  export declare const FORM_DIRTY_DEFAULT_MESSAGE = "You have unsaved changes. Are you sure you want to leave?";
311
331
 
332
+ /**
333
+ * Default result formatter for retrieval tools.
334
+ * Returns content, score, and metadata.
335
+ *
336
+ * @param result - Scored result to format
337
+ * @returns Formatted result object
338
+ */
339
+ export declare function formatScoredResult(result: ScoredResult): unknown;
340
+
312
341
  /** Form dirty guard options */
313
342
  export declare interface FormDirtyGuardOptions<TFormData = unknown, TPage extends string = string> {
314
343
  readonly form: FormMinimal<TFormData>;
@@ -352,54 +381,6 @@ export declare interface FrameSummary {
352
381
  /** Frame type discriminator */
353
382
  export declare type FrameType = 'system' | 'instruction' | 'section' | 'file' | 'document' | 'example' | 'tool' | 'memory' | 'retrieval' | 'custom';
354
383
 
355
- /** Generation defaults for provider adapters */
356
- export declare interface GenerationDefaults {
357
- readonly model?: string;
358
- readonly temperature?: number;
359
- readonly maxTokens?: number;
360
- readonly topP?: number;
361
- readonly stop?: readonly string[];
362
- }
363
-
364
- /** HTTP persistence options */
365
- export declare interface HTTPPersistenceOptions {
366
- readonly baseURL: string;
367
- readonly headers?: Readonly<Record<string, string>>;
368
- readonly timeout?: number;
369
- }
370
-
371
- /** IndexedDB VectorStore persistence options */
372
- export declare interface IndexedDBVectorStorePersistenceOptions {
373
- readonly database: MinimalDatabaseAccess;
374
- readonly documentsStore?: string;
375
- readonly metadataStore?: string;
376
- }
377
-
378
- /** In-memory embedding cache options */
379
- export declare interface InMemoryEmbeddingCacheOptions {
380
- readonly maxEntries?: number;
381
- readonly ttlMs?: number;
382
- }
383
-
384
- /**
385
- * Type guard to check if an error is a CoreError.
386
- *
387
- * @param error - The value to check
388
- * @returns True if the error is a CoreError
389
- *
390
- * @example
391
- * ```ts
392
- * try {
393
- * await adapter.embed(['text'])
394
- * } catch (error) {
395
- * if (isCoreError(error)) {
396
- * console.log('Code:', error.code)
397
- * }
398
- * }
399
- * ```
400
- */
401
- export declare function isCoreError(error: unknown): error is CoreError;
402
-
403
384
  /**
404
385
  * Type guard for ecosystem errors.
405
386
  *
@@ -451,6 +432,18 @@ export declare function isErr<T, E>(result: Result<T, E>): result is Err<E>;
451
432
  */
452
433
  export declare function isOk<T, E>(result: Result<T, E>): result is Ok<T>;
453
434
 
435
+ /**
436
+ * Check if a value is a single ToolCall (not an array).
437
+ *
438
+ * @param value - Value to check
439
+ * @returns True if the value is a single ToolCall
440
+ */
441
+ export declare function isToolCall(value: unknown): value is {
442
+ id: string;
443
+ name: string;
444
+ arguments: unknown;
445
+ };
446
+
454
447
  /** JSON Schema 7 subset for tool parameters */
455
448
  export declare interface JSONSchema7 {
456
449
  readonly type?: string | readonly string[];
@@ -507,7 +500,7 @@ export declare function mapErr<T, E, F>(result: Result<T, E>, fn: (error: E) =>
507
500
 
508
501
  /**
509
502
  * Minimal database access interface for cross-package adapters.
510
- * Used by vectorstore persistence adapters to access IndexedDB without
503
+ * Used by persistence adapters to access IndexedDB without
511
504
  * creating a hard dependency on the indexeddb package.
512
505
  */
513
506
  export declare interface MinimalDatabaseAccess<T = unknown> {
@@ -516,7 +509,7 @@ export declare interface MinimalDatabaseAccess<T = unknown> {
516
509
 
517
510
  /**
518
511
  * Minimal directory access interface for cross-package adapters.
519
- * Used by vectorstore OPFS persistence adapters without creating
512
+ * Used by OPFS persistence adapters without creating
520
513
  * a hard dependency on the filesystem package.
521
514
  */
522
515
  export declare interface MinimalDirectoryAccess {
@@ -576,15 +569,9 @@ export declare interface Ok<T> {
576
569
  */
577
570
  export declare function ok<T>(value: T): Ok<T>;
578
571
 
579
- /** OPFS VectorStore persistence options */
580
- export declare interface OPFSVectorStorePersistenceOptions {
581
- readonly directory: MinimalDirectoryAccess;
582
- readonly chunkSize?: number;
583
- }
584
-
585
572
  /**
586
573
  * Generic error data interface for package-specific errors.
587
- * Use this as a base for error data interfaces in packages.
574
+ * Packages extend this to define their error structure.
588
575
  *
589
576
  * @example
590
577
  * ```ts
@@ -599,13 +586,16 @@ export declare interface PackageErrorData<TCode extends string> {
599
586
  readonly cause?: Error;
600
587
  }
601
588
 
602
- /** Provider capabilities information */
603
- export declare interface ProviderCapabilities {
604
- readonly supportsTools: boolean;
605
- readonly supportsStreaming: boolean;
606
- readonly supportsVision: boolean;
607
- readonly supportsFunctions: boolean;
608
- readonly models: readonly string[];
589
+ /**
590
+ * Priority adapter interface.
591
+ * Provides priority weights and comparison logic.
592
+ * Implemented in @mikesaintsg/adapters.
593
+ */
594
+ export declare interface PriorityAdapterInterface {
595
+ /** Get numeric weight for a priority level. Higher values = more important. */
596
+ getWeight(priority: FramePriority): number;
597
+ /** Compare two frames by priority */
598
+ compare(a: ContextFrame, b: ContextFrame): number;
609
599
  }
610
600
 
611
601
  /** Prune result information */
@@ -614,7 +604,42 @@ export declare interface PruneResult {
614
604
  readonly remainingCount: number;
615
605
  }
616
606
 
617
- /** Result union */
607
+ /**
608
+ * Rate limit adapter interface.
609
+ * Controls request rate to external services.
610
+ */
611
+ export declare interface RateLimitAdapterInterface {
612
+ /** Acquire a request slot, waits if none available */
613
+ acquire(): Promise<void>;
614
+ /** Release a request slot */
615
+ release(): void;
616
+ /** Get current rate limit state */
617
+ getState(): RateLimitState;
618
+ /** Dynamically adjust rate limit (e.g., from Retry-After header) */
619
+ setLimit(requestsPerMinute: number): void;
620
+ }
621
+
622
+ /** Rate limit state */
623
+ export declare interface RateLimitState {
624
+ readonly activeRequests: number;
625
+ readonly maxConcurrent: number;
626
+ readonly requestsInWindow: number;
627
+ readonly requestsPerMinute: number;
628
+ readonly windowResetIn: number;
629
+ }
630
+
631
+ /**
632
+ * Reranker adapter interface.
633
+ * Reranks search results using a cross-encoder or similar model.
634
+ */
635
+ export declare interface RerankerAdapterInterface {
636
+ /** Rerank documents for a given query */
637
+ rerank(query: string, docs: readonly ScoredResult[]): Promise<readonly ScoredResult[]>;
638
+ /** Get the model ID used for reranking */
639
+ getModelId(): string;
640
+ }
641
+
642
+ /** Result union - discriminated union for operation results */
618
643
  export declare type Result<T, E> = Ok<T> | Err<E>;
619
644
 
620
645
  /** Default retrieval limit for retrieval tool */
@@ -642,6 +667,21 @@ export declare interface RetrievalToolOptions<TMetadata = unknown> {
642
667
  readonly buildFilter?: (params: Readonly<Record<string, unknown>>) => TMetadata | undefined;
643
668
  }
644
669
 
670
+ /**
671
+ * Retry adapter interface.
672
+ * Determines retry behavior for failed operations.
673
+ */
674
+ export declare interface RetryAdapterInterface {
675
+ /** Determine if an error should trigger a retry */
676
+ shouldRetry(error: unknown, attempt: number): boolean;
677
+ /** Get delay before next retry attempt (ms) */
678
+ getDelay(attempt: number): number;
679
+ /** Maximum number of retry attempts */
680
+ getMaxAttempts(): number;
681
+ /** Optional callback before each retry */
682
+ onRetry?(error: unknown, attempt: number, delayMs: number): void;
683
+ }
684
+
645
685
  /** Scored result from similarity search or retrieval */
646
686
  export declare interface ScoredResult {
647
687
  readonly id: string;
@@ -704,6 +744,28 @@ export declare interface SessionPersistenceOptions {
704
744
  readonly onSaveError?: (error: unknown, sessionId: string) => void;
705
745
  }
706
746
 
747
+ /**
748
+ * Determine if form dirty guard should be skipped for a navigation.
749
+ *
750
+ * @param to - Target page
751
+ * @param from - Source page
752
+ * @param excludePages - Pages to exclude from guard
753
+ * @param onlyFromPages - Only guard from these pages (if specified)
754
+ * @returns True if guard should be skipped
755
+ */
756
+ export declare function shouldSkipFormGuard<TPage extends string>(to: TPage, from: TPage, excludePages: readonly TPage[], onlyFromPages: readonly TPage[] | undefined): boolean;
757
+
758
+ /**
759
+ * Similarity adapter interface.
760
+ * Computes similarity between embedding vectors.
761
+ */
762
+ export declare interface SimilarityAdapterInterface {
763
+ /** Compute similarity score between two embeddings */
764
+ compute(a: Embedding, b: Embedding): number;
765
+ /** Name of the similarity function */
766
+ readonly name: string;
767
+ }
768
+
707
769
  /** Storage information (quota and usage) */
708
770
  export declare interface StorageInfo {
709
771
  readonly usage: number;
@@ -745,7 +807,7 @@ export declare interface TokenBudgetState {
745
807
  export declare interface ToolCall {
746
808
  readonly id: string;
747
809
  readonly name: string;
748
- readonly arguments: Record<string, unknown>;
810
+ readonly arguments: Readonly<Record<string, unknown>>;
749
811
  }
750
812
 
751
813
  /**
@@ -753,8 +815,15 @@ export declare interface ToolCall {
753
815
  * Connects inference tool calls to contextprotocol tool registry.
754
816
  */
755
817
  export declare interface ToolCallBridgeInterface {
756
- execute(toolCall: ToolCall): Promise<ToolResult>;
757
- executeAll(toolCalls: readonly ToolCall[]): Promise<readonly ToolResult[]>;
818
+ /**
819
+ * Execute tool call(s).
820
+ * Accepts single call or array of calls.
821
+ * @param toolCalls - Single tool call or array of calls
822
+ * @returns Single result or array of results
823
+ */
824
+ execute(toolCalls: ToolCall): Promise<ToolResult>;
825
+ execute(toolCalls: readonly ToolCall[]): Promise<readonly ToolResult[]>;
826
+ /** Check if tool exists */
758
827
  hasTool(name: string): boolean;
759
828
  }
760
829
 
@@ -773,8 +842,11 @@ export declare interface ToolCallBridgeOptions {
773
842
  * Implemented in @mikesaintsg/adapters.
774
843
  */
775
844
  export declare interface ToolFormatAdapterInterface {
845
+ /** Convert tool schemas to provider-specific format */
776
846
  formatSchemas(schemas: readonly ToolSchema[]): unknown;
847
+ /** Parse tool calls from provider response */
777
848
  parseToolCalls(response: unknown): readonly ToolCall[];
849
+ /** Format tool result for provider */
778
850
  formatResult(result: ToolResult): unknown;
779
851
  }
780
852
 
@@ -804,6 +876,18 @@ export declare interface ToolSchema {
804
876
  readonly returns?: JSONSchema7;
805
877
  }
806
878
 
879
+ /**
880
+ * Truncation adapter interface.
881
+ * Determines which frames to remove when budget is exceeded.
882
+ * Implemented in @mikesaintsg/adapters.
883
+ */
884
+ export declare interface TruncationAdapterInterface {
885
+ /** Sort frames for truncation order. Frames at the end are removed first. */
886
+ sort(frames: readonly ContextFrame[]): readonly ContextFrame[];
887
+ /** Check if a frame should be preserved regardless of truncation */
888
+ shouldPreserve(frame: ContextFrame): boolean;
889
+ }
890
+
807
891
  /** Truncation information */
808
892
  export declare interface TruncationInfo {
809
893
  readonly originalFrameCount: number;
@@ -818,6 +902,13 @@ export declare type TruncationReason = 'budget_exceeded' | 'priority_too_low' |
818
902
  /** Truncation strategy */
819
903
  export declare type TruncationStrategy = 'priority' | 'fifo' | 'lifo' | 'score' | 'custom';
820
904
 
905
+ /**
906
+ * @mikesaintsg/core
907
+ *
908
+ * Shared type definitions for the @mikesaintsg ecosystem.
909
+ * Contains ONLY types and interfaces — no implementations.
910
+ * All public types and interfaces are defined here as the SOURCE OF TRUTH.
911
+ */
821
912
  /** Cleanup function returned by event subscriptions */
822
913
  export declare type Unsubscribe = () => void;
823
914
 
package/dist/index.js CHANGED
@@ -1,35 +1,26 @@
1
- class x extends Error {
2
- cause;
3
- constructor(t, o) {
4
- super(t), this.name = this.constructor.name, this.cause = o;
5
- }
6
- }
7
- function F(e) {
8
- return e instanceof x;
9
- }
10
1
  class A extends Error {
11
- code;
2
+ /** Original error that caused this one */
12
3
  cause;
13
- constructor(t, o, s) {
14
- super(o), this.name = "CoreError", this.code = t, this.cause = s;
4
+ constructor(t, s) {
5
+ super(t), this.name = this.constructor.name, this.cause = s;
15
6
  }
16
7
  }
17
- function P(e) {
8
+ function b(e) {
18
9
  return e instanceof A;
19
10
  }
20
11
  function S(e) {
21
12
  return { ok: !0, value: e };
22
13
  }
23
- function I(e) {
14
+ function l(e) {
24
15
  return { ok: !1, error: e };
25
16
  }
26
- function b(e) {
17
+ function F(e) {
27
18
  return e.ok === !0;
28
19
  }
29
- function q(e) {
20
+ function P(e) {
30
21
  return !e.ok;
31
22
  }
32
- function O(e, t) {
23
+ function q(e, t) {
33
24
  return e.ok ? e.value : t;
34
25
  }
35
26
  function U(e) {
@@ -41,23 +32,36 @@ function B(e, t) {
41
32
  return e.ok ? S(t(e.value)) : e;
42
33
  }
43
34
  function G(e, t) {
44
- return e.ok ? e : I(t(e.error));
35
+ return e.ok ? e : l(t(e.error));
45
36
  }
46
- function $(e, t) {
37
+ function O(e, t) {
47
38
  return e.ok ? t(e.value) : e;
48
39
  }
49
- async function j(e) {
50
- const o = new TextEncoder().encode(e), s = await crypto.subtle.digest("SHA-256", o);
51
- return Array.from(new Uint8Array(s)).map((a) => a.toString(16).padStart(2, "0")).join("");
40
+ async function $(e) {
41
+ const s = new TextEncoder().encode(e), a = await crypto.subtle.digest("SHA-256", s);
42
+ return Array.from(new Uint8Array(a)).map((o) => o.toString(16).padStart(2, "0")).join("");
52
43
  }
53
- const k = 3e4, M = 10, R = 100, L = "You have unsaved changes. Are you sure you want to leave?";
54
- function H(e) {
44
+ function I(e) {
45
+ return typeof e == "object" && e !== null && "id" in e && "name" in e && "arguments" in e;
46
+ }
47
+ function k(e, t, s, a) {
48
+ return !!(s.includes(e) || a !== void 0 && !a.includes(t));
49
+ }
50
+ function M(e) {
51
+ return {
52
+ content: e.content,
53
+ score: e.score,
54
+ metadata: e.metadata
55
+ };
56
+ }
57
+ const R = 3e4, L = 10, _ = 100, D = "You have unsaved changes. Are you sure you want to leave?";
58
+ function j(e) {
55
59
  const {
56
60
  registry: t,
57
- timeout: o = k,
58
- onError: s,
59
- onBeforeExecute: i,
60
- onAfterExecute: a
61
+ timeout: s = R,
62
+ onError: a,
63
+ onBeforeExecute: c,
64
+ onAfterExecute: o
61
65
  } = e;
62
66
  async function u(r) {
63
67
  if (!t.has(r.name))
@@ -67,40 +71,37 @@ function H(e) {
67
71
  success: !1,
68
72
  error: `Tool not found: ${r.name}`
69
73
  };
70
- i?.(r);
74
+ c?.(r);
71
75
  try {
72
76
  const n = new Promise((f, m) => {
73
77
  setTimeout(() => {
74
- m(new Error(`Tool execution timed out after ${o}ms`));
75
- }, o);
76
- }), c = await Promise.race([
78
+ m(new Error(`Tool execution timed out after ${s}ms`));
79
+ }, s);
80
+ }), i = await Promise.race([
77
81
  t.execute(r.name, r.arguments),
78
82
  n
79
83
  ]);
80
- return a?.(r, c), {
84
+ return o?.(r, i), {
81
85
  callId: r.id,
82
86
  name: r.name,
83
87
  success: !0,
84
- value: c
88
+ value: i
85
89
  };
86
90
  } catch (n) {
87
- s?.(n, r);
88
- const c = n instanceof Error ? n.message : String(n);
91
+ a?.(n, r);
92
+ const i = n instanceof Error ? n.message : String(n);
89
93
  return {
90
94
  callId: r.id,
91
95
  name: r.name,
92
96
  success: !1,
93
- error: c
97
+ error: i
94
98
  };
95
99
  }
96
100
  }
97
101
  return {
98
- async execute(r) {
99
- return u(r);
100
- },
101
- async executeAll(r) {
102
- return await Promise.all(
103
- r.map((c) => u(c))
102
+ execute(r) {
103
+ return I(r) ? u(r) : Promise.all(
104
+ r.map((n) => u(n))
104
105
  );
105
106
  },
106
107
  hasTool(r) {
@@ -108,17 +109,17 @@ function H(e) {
108
109
  }
109
110
  };
110
111
  }
111
- function N(e) {
112
+ function H(e) {
112
113
  const {
113
114
  vectorStore: t,
114
- name: o,
115
- description: s,
116
- defaultLimit: i = M,
117
- maxLimit: a = R,
115
+ name: s,
116
+ description: a,
117
+ defaultLimit: c = L,
118
+ maxLimit: o = _,
118
119
  scoreThreshold: u,
119
- formatResult: r = _,
120
+ formatResult: r = M,
120
121
  extendParameters: n = {},
121
- buildFilter: c
122
+ buildFilter: i
122
123
  } = e, f = {
123
124
  type: "object",
124
125
  properties: {
@@ -128,17 +129,17 @@ function N(e) {
128
129
  },
129
130
  limit: {
130
131
  type: "integer",
131
- description: `Maximum number of results to return (default: ${i}, max: ${a})`,
132
+ description: `Maximum number of results to return (default: ${c}, max: ${o})`,
132
133
  minimum: 1,
133
- maximum: a,
134
- default: i
134
+ maximum: o,
135
+ default: c
135
136
  },
136
137
  ...n
137
138
  },
138
139
  required: ["query"]
139
140
  }, m = {
140
- name: o,
141
- description: s,
141
+ name: s,
142
+ description: a,
142
143
  parameters: f
143
144
  };
144
145
  async function d(h) {
@@ -146,73 +147,62 @@ function N(e) {
146
147
  if (typeof y != "string" || y.length === 0)
147
148
  return [];
148
149
  const p = h.limit;
149
- let E = i;
150
- typeof p == "number" && Number.isInteger(p) && (E = Math.min(Math.max(1, p), a));
151
- const l = c?.(h), v = l !== void 0 ? { limit: E, filter: l } : { limit: E }, w = await t.search(y, v);
152
- let g = w;
153
- return u !== void 0 && (g = w.filter((T) => T.score >= u)), g.map(r);
150
+ let E = c;
151
+ typeof p == "number" && Number.isInteger(p) && (E = Math.min(Math.max(1, p), o));
152
+ const w = i?.(h), v = w !== void 0 ? { limit: E, filter: w } : { limit: E }, g = await t.search(y, v);
153
+ let T = g;
154
+ return u !== void 0 && (T = g.filter((x) => x.score >= u)), T.map(r);
154
155
  }
155
156
  return { schema: m, handler: d };
156
157
  }
157
- function _(e) {
158
- return {
159
- content: e.content,
160
- score: e.score,
161
- metadata: e.metadata
162
- };
163
- }
164
- function V(e) {
158
+ function N(e) {
165
159
  const {
166
160
  form: t,
167
- confirmFn: o,
168
- message: s = L,
169
- excludePages: i = [],
170
- onlyFromPages: a
161
+ confirmFn: s,
162
+ message: a = D,
163
+ excludePages: c = [],
164
+ onlyFromPages: o
171
165
  } = e;
172
166
  return async function(r, n) {
173
- return D(r, n, i, a) || !t.isDirty() ? !0 : await Promise.resolve(o(s));
167
+ return k(r, n, c, o) || !t.isDirty() ? !0 : Promise.resolve(s(a));
174
168
  };
175
169
  }
176
- function D(e, t, o, s) {
177
- return !!(o.includes(e) || s !== void 0 && !s.includes(t));
178
- }
179
- function Y(e) {
170
+ function V(e) {
180
171
  const {
181
172
  database: t,
182
- storeName: o,
183
- autoprune: s,
184
- onSaveError: i
185
- } = e, a = t.store(o);
186
- s !== void 0 && s > 0 && u(s);
173
+ storeName: s,
174
+ autoprune: a,
175
+ onSaveError: c
176
+ } = e, o = t.store(s);
187
177
  async function u(r) {
188
- const c = Date.now() - r, f = await a.all();
178
+ const i = Date.now() - r, f = await o.all();
189
179
  let m = 0;
190
180
  for (const d of f)
191
- d.updatedAt < c && (await a.remove(d.id), m++);
181
+ d.updatedAt < i && (await o.remove(d.id), m++);
192
182
  return m;
193
183
  }
194
- return {
184
+ return a !== void 0 && a > 0 && u(a), {
195
185
  async save(r, n) {
196
186
  try {
197
- const c = {
187
+ const i = {
198
188
  id: r,
199
189
  messages: [...n.getMessages()],
200
190
  metadata: n.getMetadata(),
201
191
  updatedAt: Date.now()
202
192
  };
203
- await a.set(c, r);
204
- } catch (c) {
205
- throw i?.(c, r), c;
193
+ await o.set(i, r);
194
+ } catch (i) {
195
+ throw c?.(i, r), i;
206
196
  }
207
197
  },
208
198
  async load(r) {
209
- return a.get(r);
199
+ return o.get(r);
210
200
  },
211
201
  async delete(r) {
212
- await a.remove(r);
202
+ await o.remove(r);
213
203
  },
214
204
  async list() {
215
- return (await a.all()).map((n) => n.id);
205
+ return (await o.all()).map((n) => n.id);
216
206
  },
217
207
  async prune(r) {
218
208
  return u(r);
@@ -220,27 +210,28 @@ function Y(e) {
220
210
  };
221
211
  }
222
212
  export {
223
- k as BRIDGE_DEFAULT_TIMEOUT,
224
- A as CoreError,
225
- x as EcosystemError,
226
- L as FORM_DIRTY_DEFAULT_MESSAGE,
227
- M as RETRIEVAL_DEFAULT_LIMIT,
228
- R as RETRIEVAL_MAX_LIMIT,
229
- $ as chain,
230
- j as computeContentHash,
231
- V as createFormDirtyGuard,
232
- N as createRetrievalTool,
233
- Y as createSessionPersistence,
234
- H as createToolCallBridge,
235
- I as err,
236
- P as isCoreError,
237
- F as isEcosystemError,
238
- q as isErr,
239
- b as isOk,
213
+ R as BRIDGE_DEFAULT_TIMEOUT,
214
+ A as EcosystemError,
215
+ D as FORM_DIRTY_DEFAULT_MESSAGE,
216
+ L as RETRIEVAL_DEFAULT_LIMIT,
217
+ _ as RETRIEVAL_MAX_LIMIT,
218
+ O as chain,
219
+ $ as computeContentHash,
220
+ N as createFormDirtyGuard,
221
+ H as createRetrievalTool,
222
+ V as createSessionPersistence,
223
+ j as createToolCallBridge,
224
+ l as err,
225
+ M as formatScoredResult,
226
+ b as isEcosystemError,
227
+ P as isErr,
228
+ F as isOk,
229
+ I as isToolCall,
240
230
  B as map,
241
231
  G as mapErr,
242
232
  S as ok,
243
- O as unwrap,
233
+ k as shouldSkipFormGuard,
234
+ q as unwrap,
244
235
  U as unwrapOrThrow
245
236
  };
246
237
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/errors.ts","../src/helpers.ts","../src/constants.ts","../src/bridges/tool-call.ts","../src/bridges/retrieval-tool.ts","../src/bridges/form-dirty-guard.ts","../src/bridges/session-persistence.ts"],"sourcesContent":["/**\r\n * @mikesaintsg/core\r\n *\r\n * Error utilities and re-exports.\r\n */\r\n\r\n// ============================================================================\r\n// Base Ecosystem Error\r\n// ============================================================================\r\n\r\nimport { CoreErrorCode } from './types'\r\n\r\n/**\r\n * Base error class for all ecosystem errors.\r\n * All package-specific errors should extend this class.\r\n */\r\nexport abstract class EcosystemError extends Error {\r\n\tabstract readonly code: string\r\n\toverride readonly cause: Error | undefined\r\n\r\n\tconstructor(message: string, cause?: Error) {\r\n\t\tsuper(message)\r\n\t\tthis.name = this.constructor.name\r\n\t\tthis.cause = cause\r\n\t}\r\n}\r\n\r\n/**\r\n * Type guard for ecosystem errors.\r\n *\r\n * @param error - The value to check\r\n * @returns True if the error is an EcosystemError\r\n *\r\n * @example\r\n * ```ts\r\n * try {\r\n * await someOperation()\r\n * } catch (error) {\r\n * if (isEcosystemError(error)) {\r\n * console.log('Code:', error.code)\r\n * }\r\n * }\r\n * ```\r\n */\r\nexport function isEcosystemError(error: unknown): error is EcosystemError {\r\n\treturn error instanceof EcosystemError\r\n}\r\n\r\n// ============================================================================\r\n// Core Error Class\r\n// ============================================================================\r\n\r\n/**\r\n * Core package error.\r\n *\r\n * @example\r\n * ```ts\r\n * throw new CoreError('ADAPTER_ERROR', 'Failed to connect to OpenAI')\r\n * ```\r\n */\r\nexport class CoreError extends Error {\r\n\treadonly code: CoreErrorCode\r\n\toverride readonly cause: Error | undefined\r\n\r\n\tconstructor(code: CoreErrorCode, message: string, cause?: Error) {\r\n\t\tsuper(message)\r\n\t\tthis.name = 'CoreError'\r\n\t\tthis.code = code\r\n\t\tthis.cause = cause\r\n\t}\r\n}\r\n\r\n/**\r\n * Type guard to check if an error is a CoreError.\r\n *\r\n * @param error - The value to check\r\n * @returns True if the error is a CoreError\r\n *\r\n * @example\r\n * ```ts\r\n * try {\r\n * await adapter.embed(['text'])\r\n * } catch (error) {\r\n * if (isCoreError(error)) {\r\n * console.log('Code:', error.code)\r\n * }\r\n * }\r\n * ```\r\n */\r\nexport function isCoreError(error: unknown): error is CoreError {\r\n\treturn error instanceof CoreError\r\n}\r\n","/**\r\n * @mikesaintsg/core\r\n *\r\n * Helper functions and type guards.\r\n */\r\n\r\nimport type { Ok, Err, Result, ContentHash } from './types.js'\r\n\r\n// ============================================================================\r\n// Result Pattern Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Create a success result.\r\n *\r\n * @param value - The success value\r\n * @returns An Ok result containing the value\r\n *\r\n * @example\r\n * ```ts\r\n * const result = ok(42)\r\n * // result.ok === true\r\n * // result.value === 42\r\n * ```\r\n */\r\nexport function ok<T>(value: T): Ok<T> {\r\n\treturn { ok: true, value }\r\n}\r\n\r\n/**\r\n * Create a failure result.\r\n *\r\n * @param error - The error value\r\n * @returns An Err result containing the error\r\n *\r\n * @example\r\n * ```ts\r\n * const result = err('NOT_FOUND')\r\n * // result.ok === false\r\n * // result.error === 'NOT_FOUND'\r\n * ```\r\n */\r\nexport function err<E>(error: E): Err<E> {\r\n\treturn { ok: false, error }\r\n}\r\n\r\n/**\r\n * Check if a result is a success.\r\n *\r\n * @param result - The result to check\r\n * @returns True if the result is Ok, false otherwise\r\n *\r\n * @example\r\n * ```ts\r\n * const result: Result<number, string> = ok(42)\r\n * if (isOk(result)) {\r\n * console.log(result.value) // TypeScript knows result is Ok<number>\r\n * }\r\n * ```\r\n */\r\nexport function isOk<T, E>(result: Result<T, E>): result is Ok<T> {\r\n\treturn result.ok === true\r\n}\r\n\r\n/**\r\n * Check if a result is a failure.\r\n *\r\n * @param result - The result to check\r\n * @returns True if the result is Err, false otherwise\r\n *\r\n * @example\r\n * ```ts\r\n * const result: Result<number, string> = err('NOT_FOUND')\r\n * if (isErr(result)) {\r\n * console.log(result.error) // TypeScript knows result is Err<string>\r\n * }\r\n * ```\r\n */\r\nexport function isErr<T, E>(result: Result<T, E>): result is Err<E> {\r\n\treturn !result.ok\r\n}\r\n\r\n/**\r\n * Unwrap a result, returning the value or a default.\r\n *\r\n * @param result - The result to unwrap\r\n * @param defaultValue - Value to return if result is an error\r\n * @returns The success value or the default value\r\n *\r\n * @example\r\n * ```ts\r\n * const value = unwrap(ok(42), 0) // 42\r\n * const fallback = unwrap(err('oops'), 0) // 0\r\n * ```\r\n */\r\nexport function unwrap<T, E>(result: Result<T, E>, defaultValue: T): T {\r\n\treturn result.ok ? result.value : defaultValue\r\n}\r\n\r\n/**\r\n * Unwrap a result, throwing if it's an error.\r\n *\r\n * @param result - The result to unwrap\r\n * @returns The success value\r\n * @throws The error if result is Err\r\n *\r\n * @example\r\n * ```ts\r\n * const value = unwrapOrThrow(ok(42)) // 42\r\n * unwrapOrThrow(err(new Error('oops'))) // throws Error('oops')\r\n * ```\r\n */\r\nexport function unwrapOrThrow<T, E>(result: Result<T, E>): T {\r\n\tif (result.ok) {\r\n\t\treturn result.value\r\n\t}\r\n\tif (result.error instanceof Error) {\r\n\t\tthrow result.error\r\n\t}\r\n\tthrow new Error(String(result.error))\r\n}\r\n\r\n/**\r\n * Map a function over a success value.\r\n *\r\n * @param result - The result to map over\r\n * @param fn - Function to apply to the success value\r\n * @returns A new result with the mapped value, or the original error\r\n *\r\n * @example\r\n * ```ts\r\n * const doubled = map(ok(5), x => x * 2) // ok(10)\r\n * const failed = map(err('oops'), x => x * 2) // err('oops')\r\n * ```\r\n */\r\nexport function map<T, U, E>(\r\n\tresult: Result<T, E>,\r\n\tfn: (value: T) => U,\r\n): Result<U, E> {\r\n\treturn result.ok ? ok(fn(result.value)) : result\r\n}\r\n\r\n/**\r\n * Map a function over an error value.\r\n *\r\n * @param result - The result to map over\r\n * @param fn - Function to apply to the error value\r\n * @returns A new result with the mapped error, or the original value\r\n *\r\n * @example\r\n * ```ts\r\n * const wrapped = mapErr(err('oops'), e => new Error(e)) // err(Error('oops'))\r\n * const unchanged = mapErr(ok(42), e => new Error(e)) // ok(42)\r\n * ```\r\n */\r\nexport function mapErr<T, E, F>(\r\n\tresult: Result<T, E>,\r\n\tfn: (error: E) => F,\r\n): Result<T, F> {\r\n\treturn result.ok ? result : err(fn(result.error))\r\n}\r\n\r\n/**\r\n * Chain results (flatMap). Apply a function that returns a Result to a success value.\r\n *\r\n * @param result - The result to chain\r\n * @param fn - Function returning a new Result\r\n * @returns The result of applying fn, or the original error\r\n *\r\n * @example\r\n * ```ts\r\n * const parsed = chain(ok('42'), s => {\r\n * const n = parseInt(s, 10)\r\n * return isNaN(n) ? err('PARSE_ERROR') : ok(n)\r\n * })\r\n * // parsed = ok(42)\r\n * ```\r\n */\r\nexport function chain<T, U, E>(\r\n\tresult: Result<T, E>,\r\n\tfn: (value: T) => Result<U, E>,\r\n): Result<U, E> {\r\n\treturn result.ok ? fn(result.value) : result\r\n}\r\n\r\n// ============================================================================\r\n// Content Hashing Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Compute a SHA-256 content hash for text.\r\n *\r\n * @param text - The text to hash\r\n * @returns A hex string content hash\r\n *\r\n * @example\r\n * ```ts\r\n * const hash = await computeContentHash('Hello, world!')\r\n * // hash = 'a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e'\r\n * ```\r\n */\r\nexport async function computeContentHash(text: string): Promise<ContentHash> {\r\n\tconst encoder = new TextEncoder()\r\n\tconst data = encoder.encode(text)\r\n\tconst hashBuffer = await crypto.subtle.digest('SHA-256', data)\r\n\tconst hashArray = Array.from(new Uint8Array(hashBuffer))\r\n\treturn hashArray.map(b => b.toString(16).padStart(2, '0')).join('')\r\n}\r\n","/**\r\n * @mikesaintsg/core\r\n *\r\n * Shared constants for the core library.\r\n */\r\n\r\n// ============================================================================\r\n// Bridge Constants\r\n// ============================================================================\r\n\r\n/** Default timeout for bridge operations in milliseconds */\r\nexport const BRIDGE_DEFAULT_TIMEOUT = 30000\r\n\r\n/** Default retrieval limit for retrieval tool */\r\nexport const RETRIEVAL_DEFAULT_LIMIT = 10\r\n\r\n/** Maximum retrieval limit for retrieval tool */\r\nexport const RETRIEVAL_MAX_LIMIT = 100\r\n\r\n/** Default form dirty guard message */\r\nexport const FORM_DIRTY_DEFAULT_MESSAGE = 'You have unsaved changes. Are you sure you want to leave?'\r\n","/**\r\n * @mikesaintsg/core\r\n *\r\n * Tool call bridge that connects inference tool calls to contextprotocol tool registry.\r\n */\r\n\r\nimport type {\r\n\tToolCall,\r\n\tToolResult,\r\n\tToolCallBridgeOptions,\r\n\tToolCallBridgeInterface,\r\n} from '../types.js'\r\nimport { BRIDGE_DEFAULT_TIMEOUT } from '../constants.js'\r\n\r\n/**\r\n * Create a tool call bridge.\r\n *\r\n * @param options - Bridge configuration options\r\n * @returns A tool call bridge instance\r\n *\r\n * @example\r\n * ```ts\r\n * import { createToolRegistry } from '@mikesaintsg/contextprotocol'\r\n * import { createToolCallBridge } from '@mikesaintsg/core'\r\n *\r\n * const registry = createToolRegistry()\r\n * registry.register(weatherTool)\r\n *\r\n * const bridge = createToolCallBridge({\r\n * registry,\r\n * timeout: 30000,\r\n * onError: (error, toolCall) => console.error(`Tool ${toolCall.name} failed:`, error),\r\n * })\r\n *\r\n * // Execute tool calls from LLM response\r\n * const results = await bridge.executeAll(response.toolCalls)\r\n * ```\r\n */\r\nexport function createToolCallBridge(\r\n\toptions: ToolCallBridgeOptions,\r\n): ToolCallBridgeInterface {\r\n\tconst {\r\n\t\tregistry,\r\n\t\ttimeout = BRIDGE_DEFAULT_TIMEOUT,\r\n\t\tonError,\r\n\t\tonBeforeExecute,\r\n\t\tonAfterExecute,\r\n\t} = options\r\n\r\n\t/**\r\n\t * Execute a single tool call with timeout.\r\n\t */\r\n\tasync function executeWithTimeout(\r\n\t\ttoolCall: ToolCall,\r\n\t): Promise<ToolResult> {\r\n\t\t// Check if tool exists\r\n\t\tif (!registry.has(toolCall.name)) {\r\n\t\t\tconst result: ToolResult = {\r\n\t\t\t\tcallId: toolCall.id,\r\n\t\t\t\tname: toolCall.name,\r\n\t\t\t\tsuccess: false,\r\n\t\t\t\terror: `Tool not found: ${toolCall.name}`,\r\n\t\t\t}\r\n\t\t\treturn result\r\n\t\t}\r\n\r\n\t\t// Call lifecycle hook\r\n\t\tonBeforeExecute?.(toolCall)\r\n\r\n\t\ttry {\r\n\t\t\t// Create timeout promise\r\n\t\t\tconst timeoutPromise = new Promise<never>((_, reject) => {\r\n\t\t\t\tsetTimeout(() => {\r\n\t\t\t\t\treject(new Error(`Tool execution timed out after ${timeout}ms`))\r\n\t\t\t\t}, timeout)\r\n\t\t\t})\r\n\r\n\t\t\t// Execute tool with timeout\r\n\t\t\tconst value = await Promise.race([\r\n\t\t\t\tregistry.execute(toolCall.name, toolCall.arguments),\r\n\t\t\t\ttimeoutPromise,\r\n\t\t\t])\r\n\r\n\t\t\t// Call lifecycle hook\r\n\t\t\tonAfterExecute?.(toolCall, value)\r\n\r\n\t\t\treturn {\r\n\t\t\t\tcallId: toolCall.id,\r\n\t\t\t\tname: toolCall.name,\r\n\t\t\t\tsuccess: true,\r\n\t\t\t\tvalue,\r\n\t\t\t}\r\n\t\t} catch (error) {\r\n\t\t\t// Call error hook\r\n\t\t\tonError?.(error, toolCall)\r\n\r\n\t\t\tconst errorMessage = error instanceof Error\r\n\t\t\t\t? error.message\r\n\t\t\t\t: String(error)\r\n\r\n\t\t\treturn {\r\n\t\t\t\tcallId: toolCall.id,\r\n\t\t\t\tname: toolCall.name,\r\n\t\t\t\tsuccess: false,\r\n\t\t\t\terror: errorMessage,\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn {\r\n\t\tasync execute(toolCall: ToolCall): Promise<ToolResult> {\r\n\t\t\treturn executeWithTimeout(toolCall)\r\n\t\t},\r\n\r\n\t\tasync executeAll(toolCalls: readonly ToolCall[]): Promise<readonly ToolResult[]> {\r\n\t\t\t// Execute all tool calls in parallel\r\n\t\t\tconst results = await Promise.all(\r\n\t\t\t\ttoolCalls.map(toolCall => executeWithTimeout(toolCall)),\r\n\t\t\t)\r\n\t\t\treturn results\r\n\t\t},\r\n\r\n\t\thasTool(name: string): boolean {\r\n\t\t\treturn registry.has(name)\r\n\t\t},\r\n\t}\r\n}\r\n","/**\r\n * @mikesaintsg/core\r\n *\r\n * Retrieval tool factory that connects vectorstore to contextprotocol.\r\n */\r\n\r\nimport type {\r\n\tRetrievalToolOptions,\r\n\tRetrievalToolCreated,\r\n\tToolSchema,\r\n\tJSONSchema7,\r\n\tScoredResult,\r\n} from '../types.js'\r\nimport {\r\n\tRETRIEVAL_DEFAULT_LIMIT,\r\n\tRETRIEVAL_MAX_LIMIT,\r\n} from '../constants.js'\r\n\r\n/**\r\n * Create a retrieval tool for use with contextprotocol tool registry.\r\n *\r\n * @param options - Retrieval tool configuration options\r\n * @returns A tool schema and handler for registration\r\n *\r\n * @example\r\n * ```ts\r\n * import { createVectorStore } from '@mikesaintsg/vectorstore'\r\n * import { createToolRegistry } from '@mikesaintsg/contextprotocol'\r\n * import { createRetrievalTool } from '@mikesaintsg/core'\r\n *\r\n * const vectorStore = createVectorStore({ ... })\r\n * const registry = createToolRegistry()\r\n *\r\n * const { schema, handler } = createRetrievalTool({\r\n * vectorStore,\r\n * name: 'search_docs',\r\n * description: 'Search documentation for relevant information',\r\n * defaultLimit: 5,\r\n * scoreThreshold: 0.7,\r\n * })\r\n *\r\n * registry.register({ ...schema, execute: handler })\r\n * ```\r\n */\r\nexport function createRetrievalTool<TMetadata = unknown>(\r\n\toptions: RetrievalToolOptions<TMetadata>,\r\n): RetrievalToolCreated {\r\n\tconst {\r\n\t\tvectorStore,\r\n\t\tname,\r\n\t\tdescription,\r\n\t\tdefaultLimit = RETRIEVAL_DEFAULT_LIMIT,\r\n\t\tmaxLimit = RETRIEVAL_MAX_LIMIT,\r\n\t\tscoreThreshold,\r\n\t\tformatResult = defaultFormatResult,\r\n\t\textendParameters = {},\r\n\t\tbuildFilter,\r\n\t} = options\r\n\r\n\t// Build tool schema parameters\r\n\tconst parameters: JSONSchema7 = {\r\n\t\ttype: 'object',\r\n\t\tproperties: {\r\n\t\t\tquery: {\r\n\t\t\t\ttype: 'string',\r\n\t\t\t\tdescription: 'The search query to find relevant documents',\r\n\t\t\t},\r\n\t\t\tlimit: {\r\n\t\t\t\ttype: 'integer',\r\n\t\t\t\tdescription: `Maximum number of results to return (default: ${defaultLimit}, max: ${maxLimit})`,\r\n\t\t\t\tminimum: 1,\r\n\t\t\t\tmaximum: maxLimit,\r\n\t\t\t\tdefault: defaultLimit,\r\n\t\t\t},\r\n\t\t\t...extendParameters,\r\n\t\t},\r\n\t\trequired: ['query'],\r\n\t}\r\n\r\n\tconst schema: ToolSchema = {\r\n\t\tname,\r\n\t\tdescription,\r\n\t\tparameters,\r\n\t}\r\n\r\n\tasync function handler(\r\n\t\targs: Readonly<Record<string, unknown>>,\r\n\t): Promise<readonly unknown[]> {\r\n\t\tconst query = args.query\r\n\t\tif (typeof query !== 'string' || query.length === 0) {\r\n\t\t\treturn []\r\n\t\t}\r\n\r\n\t\tconst requestedLimit = args.limit\r\n\t\tlet limit = defaultLimit\r\n\t\tif (typeof requestedLimit === 'number' && Number.isInteger(requestedLimit)) {\r\n\t\t\tlimit = Math.min(Math.max(1, requestedLimit), maxLimit)\r\n\t\t}\r\n\r\n\t\t// Build filter if provided\r\n\t\tconst filter = buildFilter?.(args)\r\n\r\n\t\t// Search vectorstore - only include filter if defined\r\n\t\tconst searchOptions = filter !== undefined\r\n\t\t\t? { limit, filter }\r\n\t\t\t: { limit }\r\n\t\tconst results = await vectorStore.search(query, searchOptions)\r\n\r\n\t\t// Filter by score threshold\r\n\t\tlet filteredResults = results\r\n\t\tif (scoreThreshold !== undefined) {\r\n\t\t\tfilteredResults = results.filter(r => r.score >= scoreThreshold)\r\n\t\t}\r\n\r\n\t\t// Format results\r\n\t\treturn filteredResults.map(formatResult)\r\n\t}\r\n\r\n\treturn { schema, handler }\r\n}\r\n\r\n/**\r\n * Default result formatter - returns content and metadata.\r\n */\r\nfunction defaultFormatResult(result: ScoredResult): unknown {\r\n\treturn {\r\n\t\tcontent: result.content,\r\n\t\tscore: result.score,\r\n\t\tmetadata: result.metadata,\r\n\t}\r\n}\r\n","/**\r\n * @mikesaintsg/core\r\n *\r\n * Form dirty guard that prevents navigation when form has unsaved changes.\r\n */\r\n\r\nimport type {\r\n\tFormDirtyGuardOptions,\r\n\tNavigationGuard,\r\n} from '../types.js'\r\nimport { FORM_DIRTY_DEFAULT_MESSAGE } from '../constants.js'\r\n\r\n/**\r\n * Create a navigation guard that prevents leaving when form is dirty.\r\n *\r\n * @param options - Form dirty guard configuration options\r\n * @returns A navigation guard function\r\n *\r\n * @example\r\n * ```ts\r\n * import { createForm } from '@mikesaintsg/form'\r\n * import { createFormDirtyGuard } from '@mikesaintsg/core'\r\n *\r\n * const form = createForm({ ... })\r\n *\r\n * const guard = createFormDirtyGuard({\r\n * form,\r\n * confirmFn: (message) => window.confirm(message),\r\n * message: 'You have unsaved changes. Continue?',\r\n * excludePages: ['settings'],\r\n * })\r\n *\r\n * // Use with router\r\n * router.beforeNavigate(guard)\r\n * ```\r\n */\r\nexport function createFormDirtyGuard<TFormData = unknown, TPage extends string = string>(\r\n\toptions: FormDirtyGuardOptions<TFormData, TPage>,\r\n): NavigationGuard<TPage> {\r\n\tconst {\r\n\t\tform,\r\n\t\tconfirmFn,\r\n\t\tmessage = FORM_DIRTY_DEFAULT_MESSAGE,\r\n\t\texcludePages = [],\r\n\t\tonlyFromPages,\r\n\t} = options\r\n\r\n\treturn async function guard(to: TPage, from: TPage): Promise<boolean> {\r\n\t\t// Check if we should skip guard for this navigation\r\n\t\tif (shouldSkipGuard(to, from, excludePages, onlyFromPages)) {\r\n\t\t\treturn true\r\n\t\t}\r\n\r\n\t\t// If form is not dirty, allow navigation\r\n\t\tif (!form.isDirty()) {\r\n\t\t\treturn true\r\n\t\t}\r\n\r\n\t\t// Form is dirty, ask for confirmation\r\n\t\tconst confirmed = await Promise.resolve(confirmFn(message))\r\n\t\treturn confirmed\r\n\t}\r\n}\r\n\r\n/**\r\n * Determine if guard should be skipped for this navigation.\r\n */\r\nfunction shouldSkipGuard<TPage extends string>(\r\n\tto: TPage,\r\n\tfrom: TPage,\r\n\texcludePages: readonly TPage[],\r\n\tonlyFromPages: readonly TPage[] | undefined,\r\n): boolean {\r\n\t// Skip if navigating to excluded page\r\n\tif (excludePages.includes(to)) {\r\n\t\treturn true\r\n\t}\r\n\r\n\t// Skip if from page is not in onlyFromPages (if specified)\r\n\tif (onlyFromPages !== undefined && !onlyFromPages.includes(from)) {\r\n\t\treturn true\r\n\t}\r\n\r\n\treturn false\r\n}\r\n","/**\r\n * @mikesaintsg/core\r\n *\r\n * Session persistence bridge that connects inference sessions to IndexedDB storage.\r\n */\r\n\r\nimport type {\r\n\tSessionPersistenceOptions,\r\n\tSessionPersistenceInterface,\r\n\tSerializableSession,\r\n\tSerializedSession,\r\n} from '../types.js'\r\n\r\n/**\r\n * Create a session persistence adapter for storing inference sessions.\r\n *\r\n * @param options - Session persistence configuration options\r\n * @returns A session persistence instance\r\n *\r\n * @example\r\n * ```ts\r\n * import { createDatabase } from '@mikesaintsg/indexeddb'\r\n * import { createSessionPersistence } from '@mikesaintsg/core'\r\n *\r\n * const db = await createDatabase({ name: 'sessions' })\r\n * const persistence = createSessionPersistence({\r\n * database: db,\r\n * storeName: 'chat_sessions',\r\n * autoprune: 7 * 24 * 60 * 60 * 1000, // 7 days\r\n * })\r\n *\r\n * // Save session\r\n * await persistence.save('session-1', session)\r\n *\r\n * // Load session\r\n * const savedSession = await persistence.load('session-1')\r\n * ```\r\n */\r\nexport function createSessionPersistence(\r\n\toptions: SessionPersistenceOptions,\r\n): SessionPersistenceInterface {\r\n\tconst {\r\n\t\tdatabase,\r\n\t\tstoreName,\r\n\t\tautoprune,\r\n\t\tonSaveError,\r\n\t} = options\r\n\r\n\tconst store = database.store<SerializedSession>(storeName)\r\n\r\n\t// Auto-prune on creation if configured\r\n\tif (autoprune !== undefined && autoprune > 0) {\r\n\t\tvoid pruneOldSessions(autoprune)\r\n\t}\r\n\r\n\t/**\r\n\t * Prune sessions older than maxAgeMs.\r\n\t */\r\n\tasync function pruneOldSessions(maxAgeMs: number): Promise<number> {\r\n\t\tconst now = Date.now()\r\n\t\tconst cutoff = now - maxAgeMs\r\n\r\n\t\tconst allSessions = await store.all()\r\n\t\tlet prunedCount = 0\r\n\r\n\t\tfor (const session of allSessions) {\r\n\t\t\tif (session.updatedAt < cutoff) {\r\n\t\t\t\tawait store.remove(session.id)\r\n\t\t\t\tprunedCount++\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn prunedCount\r\n\t}\r\n\r\n\treturn {\r\n\t\tasync save(id: string, session: SerializableSession): Promise<void> {\r\n\t\t\ttry {\r\n\t\t\t\tconst serialized: SerializedSession = {\r\n\t\t\t\t\tid,\r\n\t\t\t\t\tmessages: [...session.getMessages()],\r\n\t\t\t\t\tmetadata: session.getMetadata(),\r\n\t\t\t\t\tupdatedAt: Date.now(),\r\n\t\t\t\t}\r\n\r\n\t\t\t\tawait store.set(serialized, id)\r\n\t\t\t} catch (error) {\r\n\t\t\t\tonSaveError?.(error, id)\r\n\t\t\t\tthrow error\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tasync load(id: string): Promise<SerializedSession | undefined> {\r\n\t\t\treturn store.get(id)\r\n\t\t},\r\n\r\n\t\tasync delete(id: string): Promise<void> {\r\n\t\t\tawait store.remove(id)\r\n\t\t},\r\n\r\n\t\tasync list(): Promise<readonly string[]> {\r\n\t\t\tconst allSessions = await store.all()\r\n\t\t\treturn allSessions.map(s => s.id)\r\n\t\t},\r\n\r\n\t\tasync prune(maxAgeMs: number): Promise<number> {\r\n\t\t\treturn pruneOldSessions(maxAgeMs)\r\n\t\t},\r\n\t}\r\n}\r\n"],"names":["EcosystemError","message","cause","isEcosystemError","error","CoreError","code","isCoreError","ok","value","err","isOk","result","isErr","unwrap","defaultValue","unwrapOrThrow","map","fn","mapErr","chain","computeContentHash","text","data","hashBuffer","b","BRIDGE_DEFAULT_TIMEOUT","RETRIEVAL_DEFAULT_LIMIT","RETRIEVAL_MAX_LIMIT","FORM_DIRTY_DEFAULT_MESSAGE","createToolCallBridge","options","registry","timeout","onError","onBeforeExecute","onAfterExecute","executeWithTimeout","toolCall","timeoutPromise","_","reject","errorMessage","toolCalls","name","createRetrievalTool","vectorStore","description","defaultLimit","maxLimit","scoreThreshold","formatResult","defaultFormatResult","extendParameters","buildFilter","parameters","schema","handler","args","query","requestedLimit","limit","filter","searchOptions","results","filteredResults","r","createFormDirtyGuard","form","confirmFn","excludePages","onlyFromPages","to","from","shouldSkipGuard","createSessionPersistence","database","storeName","autoprune","onSaveError","store","pruneOldSessions","maxAgeMs","cutoff","allSessions","prunedCount","session","id","serialized","s"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/errors.ts","../src/helpers.ts","../src/constants.ts","../src/factories.ts"],"sourcesContent":["/**\n * @mikesaintsg/core\n *\n * Base error class and utilities for the ecosystem.\n */\n// ============================================================================\n// Base Ecosystem Error\n// ============================================================================\n/**\n * Base error class for all ecosystem errors.\n * All package-specific errors should extend this class.\n *\n * @example\n * ```ts\n * class StorageError extends EcosystemError {\n * readonly code: StorageErrorCode\n *\n * constructor(code: StorageErrorCode, message: string, cause?: Error) {\n * super(message, cause)\n * this.code = code\n * }\n * }\n * ```\n */\nexport abstract class EcosystemError extends Error {\n\t/** Error code for programmatic handling */\n\tabstract readonly code: string\n\t/** Original error that caused this one */\n\toverride readonly cause: Error | undefined\n\n\tconstructor(message: string, cause?: Error) {\n\t\tsuper(message)\n\t\tthis.name = this.constructor.name\n\t\tthis.cause = cause\n\t}\n}\n/**\n * Type guard for ecosystem errors.\n *\n * @param error - The value to check\n * @returns True if the error is an EcosystemError\n *\n * @example\n * ```ts\n * try {\n * await someOperation()\n * } catch (error) {\n * if (isEcosystemError(error)) {\n * console.log('Code:', error.code)\n * }\n * }\n * ```\n */\nexport function isEcosystemError(error: unknown): error is EcosystemError {\n\treturn error instanceof EcosystemError\n}\n","/**\r\n * @mikesaintsg/core\r\n *\r\n * Helper functions and type guards.\r\n */\r\n\r\nimport type { Ok, Err, Result, ContentHash, ScoredResult } from './types.js'\r\n\r\n// ============================================================================\r\n// Result Pattern Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Create a success result.\r\n *\r\n * @param value - The success value\r\n * @returns An Ok result containing the value\r\n *\r\n * @example\r\n * ```ts\r\n * const result = ok(42)\r\n * // result.ok === true\r\n * // result.value === 42\r\n * ```\r\n */\r\nexport function ok<T>(value: T): Ok<T> {\r\n\treturn { ok: true, value }\r\n}\r\n\r\n/**\r\n * Create a failure result.\r\n *\r\n * @param error - The error value\r\n * @returns An Err result containing the error\r\n *\r\n * @example\r\n * ```ts\r\n * const result = err('NOT_FOUND')\r\n * // result.ok === false\r\n * // result.error === 'NOT_FOUND'\r\n * ```\r\n */\r\nexport function err<E>(error: E): Err<E> {\r\n\treturn { ok: false, error }\r\n}\r\n\r\n/**\r\n * Check if a result is a success.\r\n *\r\n * @param result - The result to check\r\n * @returns True if the result is Ok, false otherwise\r\n *\r\n * @example\r\n * ```ts\r\n * const result: Result<number, string> = ok(42)\r\n * if (isOk(result)) {\r\n * console.log(result.value) // TypeScript knows result is Ok<number>\r\n * }\r\n * ```\r\n */\r\nexport function isOk<T, E>(result: Result<T, E>): result is Ok<T> {\r\n\treturn result.ok === true\r\n}\r\n\r\n/**\r\n * Check if a result is a failure.\r\n *\r\n * @param result - The result to check\r\n * @returns True if the result is Err, false otherwise\r\n *\r\n * @example\r\n * ```ts\r\n * const result: Result<number, string> = err('NOT_FOUND')\r\n * if (isErr(result)) {\r\n * console.log(result.error) // TypeScript knows result is Err<string>\r\n * }\r\n * ```\r\n */\r\nexport function isErr<T, E>(result: Result<T, E>): result is Err<E> {\r\n\treturn !result.ok\r\n}\r\n\r\n/**\r\n * Unwrap a result, returning the value or a default.\r\n *\r\n * @param result - The result to unwrap\r\n * @param defaultValue - Value to return if result is an error\r\n * @returns The success value or the default value\r\n *\r\n * @example\r\n * ```ts\r\n * const value = unwrap(ok(42), 0) // 42\r\n * const fallback = unwrap(err('oops'), 0) // 0\r\n * ```\r\n */\r\nexport function unwrap<T, E>(result: Result<T, E>, defaultValue: T): T {\r\n\treturn result.ok ? result.value : defaultValue\r\n}\r\n\r\n/**\r\n * Unwrap a result, throwing if it's an error.\r\n *\r\n * @param result - The result to unwrap\r\n * @returns The success value\r\n * @throws The error if result is Err\r\n *\r\n * @example\r\n * ```ts\r\n * const value = unwrapOrThrow(ok(42)) // 42\r\n * unwrapOrThrow(err(new Error('oops'))) // throws Error('oops')\r\n * ```\r\n */\r\nexport function unwrapOrThrow<T, E>(result: Result<T, E>): T {\r\n\tif (result.ok) {\r\n\t\treturn result.value\r\n\t}\r\n\tif (result.error instanceof Error) {\r\n\t\tthrow result.error\r\n\t}\r\n\tthrow new Error(String(result.error))\r\n}\r\n\r\n/**\r\n * Map a function over a success value.\r\n *\r\n * @param result - The result to map over\r\n * @param fn - Function to apply to the success value\r\n * @returns A new result with the mapped value, or the original error\r\n *\r\n * @example\r\n * ```ts\r\n * const doubled = map(ok(5), x => x * 2) // ok(10)\r\n * const failed = map(err('oops'), x => x * 2) // err('oops')\r\n * ```\r\n */\r\nexport function map<T, U, E>(\r\n\tresult: Result<T, E>,\r\n\tfn: (value: T) => U,\r\n): Result<U, E> {\r\n\treturn result.ok ? ok(fn(result.value)) : result\r\n}\r\n\r\n/**\r\n * Map a function over an error value.\r\n *\r\n * @param result - The result to map over\r\n * @param fn - Function to apply to the error value\r\n * @returns A new result with the mapped error, or the original value\r\n *\r\n * @example\r\n * ```ts\r\n * const wrapped = mapErr(err('oops'), e => new Error(e)) // err(Error('oops'))\r\n * const unchanged = mapErr(ok(42), e => new Error(e)) // ok(42)\r\n * ```\r\n */\r\nexport function mapErr<T, E, F>(\r\n\tresult: Result<T, E>,\r\n\tfn: (error: E) => F,\r\n): Result<T, F> {\r\n\treturn result.ok ? result : err(fn(result.error))\r\n}\r\n\r\n/**\r\n * Chain results (flatMap). Apply a function that returns a Result to a success value.\r\n *\r\n * @param result - The result to chain\r\n * @param fn - Function returning a new Result\r\n * @returns The result of applying fn, or the original error\r\n *\r\n * @example\r\n * ```ts\r\n * const parsed = chain(ok('42'), s => {\r\n * const n = parseInt(s, 10)\r\n * return isNaN(n) ? err('PARSE_ERROR') : ok(n)\r\n * })\r\n * // parsed = ok(42)\r\n * ```\r\n */\r\nexport function chain<T, U, E>(\r\n\tresult: Result<T, E>,\r\n\tfn: (value: T) => Result<U, E>,\r\n): Result<U, E> {\r\n\treturn result.ok ? fn(result.value) : result\r\n}\r\n\r\n// ============================================================================\r\n// Content Hashing Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Compute a SHA-256 content hash for text.\r\n *\r\n * @param text - The text to hash\r\n * @returns A hex string content hash\r\n *\r\n * @example\r\n * ```ts\r\n * const hash = await computeContentHash('Hello, world!')\r\n * // hash = 'a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e'\r\n * ```\r\n */\r\nexport async function computeContentHash(text: string): Promise<ContentHash> {\r\n\tconst encoder = new TextEncoder()\r\n\tconst data = encoder.encode(text)\r\n\tconst hashBuffer = await crypto.subtle.digest('SHA-256', data)\r\n\tconst hashArray = Array.from(new Uint8Array(hashBuffer))\r\n\treturn hashArray.map(b => b.toString(16).padStart(2, '0')).join('')\r\n}\r\n\r\n// ============================================================================\r\n// Bridge Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Check if a value is a single ToolCall (not an array).\r\n *\r\n * @param value - Value to check\r\n * @returns True if the value is a single ToolCall\r\n */\r\nexport function isToolCall(value: unknown): value is { id: string; name: string; arguments: unknown } {\r\n\treturn (\r\n\t\ttypeof value === 'object' &&\r\n\t\tvalue !== null &&\r\n\t\t'id' in value &&\r\n\t\t'name' in value &&\r\n\t\t'arguments' in value\r\n\t)\r\n}\r\n\r\n/**\r\n * Determine if form dirty guard should be skipped for a navigation.\r\n *\r\n * @param to - Target page\r\n * @param from - Source page\r\n * @param excludePages - Pages to exclude from guard\r\n * @param onlyFromPages - Only guard from these pages (if specified)\r\n * @returns True if guard should be skipped\r\n */\r\nexport function shouldSkipFormGuard<TPage extends string>(\r\n\tto: TPage,\r\n\tfrom: TPage,\r\n\texcludePages: readonly TPage[],\r\n\tonlyFromPages: readonly TPage[] | undefined,\r\n): boolean {\r\n\t// Skip if navigating to excluded page\r\n\tif (excludePages.includes(to)) {\r\n\t\treturn true\r\n\t}\r\n\r\n\t// Skip if from page is not in onlyFromPages (if specified)\r\n\tif (onlyFromPages !== undefined && !onlyFromPages.includes(from)) {\r\n\t\treturn true\r\n\t}\r\n\r\n\treturn false\r\n}\r\n\r\n/**\r\n * Default result formatter for retrieval tools.\r\n * Returns content, score, and metadata.\r\n *\r\n * @param result - Scored result to format\r\n * @returns Formatted result object\r\n */\r\nexport function formatScoredResult(result: ScoredResult): unknown {\r\n\treturn {\r\n\t\tcontent: result.content,\r\n\t\tscore: result.score,\r\n\t\tmetadata: result.metadata,\r\n\t}\r\n}\r\n","/**\r\n * @mikesaintsg/core\r\n *\r\n * Shared constants for the core library.\r\n */\r\n\r\n// ============================================================================\r\n// Bridge Constants\r\n// ============================================================================\r\n\r\n/** Default timeout for bridge operations in milliseconds */\r\nexport const BRIDGE_DEFAULT_TIMEOUT = 30000\r\n\r\n/** Default retrieval limit for retrieval tool */\r\nexport const RETRIEVAL_DEFAULT_LIMIT = 10\r\n\r\n/** Maximum retrieval limit for retrieval tool */\r\nexport const RETRIEVAL_MAX_LIMIT = 100\r\n\r\n/** Default form dirty guard message */\r\nexport const FORM_DIRTY_DEFAULT_MESSAGE = 'You have unsaved changes. Are you sure you want to leave?'\r\n","/**\n * @mikesaintsg/core\n *\n * Factory functions for creating bridge instances.\n */\n\nimport type {\n\tToolCall,\n\tToolResult,\n\tToolCallBridgeOptions,\n\tToolCallBridgeInterface,\n\tRetrievalToolOptions,\n\tRetrievalToolCreated,\n\tToolSchema,\n\tJSONSchema7,\n\tFormDirtyGuardOptions,\n\tNavigationGuard,\n\tSessionPersistenceOptions,\n\tSessionPersistenceInterface,\n\tSerializableSession,\n\tSerializedSession,\n} from './types.js'\nimport {\n\tBRIDGE_DEFAULT_TIMEOUT,\n\tRETRIEVAL_DEFAULT_LIMIT,\n\tRETRIEVAL_MAX_LIMIT,\n\tFORM_DIRTY_DEFAULT_MESSAGE,\n} from './constants.js'\nimport {\n\tisToolCall,\n\tshouldSkipFormGuard,\n\tformatScoredResult,\n} from './helpers.js'\n\n// ============================================================================\n// Tool Call Bridge Factory\n// ============================================================================\n\n/**\n * Create a tool call bridge.\n *\n * @param options - Bridge configuration options\n * @returns A tool call bridge instance\n *\n * @example\n * ```ts\n * import { createToolRegistry } from '@mikesaintsg/contextprotocol'\n * import { createToolCallBridge } from '@mikesaintsg/core'\n *\n * const registry = createToolRegistry()\n * registry.register(weatherTool)\n *\n * const bridge = createToolCallBridge({\n * registry,\n * timeout: 30000,\n * onError: (error, toolCall) => console.error(`Tool ${toolCall.name} failed:`, error),\n * })\n *\n * // Execute tool calls from LLM response\n * const results = await bridge.execute(response.toolCalls)\n * ```\n */\nexport function createToolCallBridge(\n\toptions: ToolCallBridgeOptions,\n): ToolCallBridgeInterface {\n\tconst {\n\t\tregistry,\n\t\ttimeout = BRIDGE_DEFAULT_TIMEOUT,\n\t\tonError,\n\t\tonBeforeExecute,\n\t\tonAfterExecute,\n\t} = options\n\n\tasync function executeWithTimeout(toolCall: ToolCall): Promise<ToolResult> {\n\t\t// Check if tool exists\n\t\tif (!registry.has(toolCall.name)) {\n\t\t\treturn {\n\t\t\t\tcallId: toolCall.id,\n\t\t\t\tname: toolCall.name,\n\t\t\t\tsuccess: false,\n\t\t\t\terror: `Tool not found: ${toolCall.name}`,\n\t\t\t}\n\t\t}\n\n\t\t// Call lifecycle hook\n\t\tonBeforeExecute?.(toolCall)\n\n\t\ttry {\n\t\t\t// Create timeout promise\n\t\t\tconst timeoutPromise = new Promise<never>((_, reject) => {\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\treject(new Error(`Tool execution timed out after ${timeout}ms`))\n\t\t\t\t}, timeout)\n\t\t\t})\n\n\t\t\t// Execute tool with timeout\n\t\t\tconst value = await Promise.race([\n\t\t\t\tregistry.execute(toolCall.name, toolCall.arguments),\n\t\t\t\ttimeoutPromise,\n\t\t\t])\n\n\t\t\t// Call lifecycle hook\n\t\t\tonAfterExecute?.(toolCall, value)\n\n\t\t\treturn {\n\t\t\t\tcallId: toolCall.id,\n\t\t\t\tname: toolCall.name,\n\t\t\t\tsuccess: true,\n\t\t\t\tvalue,\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Call error hook\n\t\t\tonError?.(error, toolCall)\n\n\t\t\tconst errorMessage = error instanceof Error\n\t\t\t\t? error.message\n\t\t\t\t: String(error)\n\n\t\t\treturn {\n\t\t\t\tcallId: toolCall.id,\n\t\t\t\tname: toolCall.name,\n\t\t\t\tsuccess: false,\n\t\t\t\terror: errorMessage,\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\texecute(toolCallOrCalls: ToolCall | readonly ToolCall[]) {\n\t\t\tif (isToolCall(toolCallOrCalls)) {\n\t\t\t\treturn executeWithTimeout(toolCallOrCalls)\n\t\t\t}\n\t\t\treturn Promise.all(\n\t\t\t\t(toolCallOrCalls).map(tc => executeWithTimeout(tc)),\n\t\t\t)\n\t\t},\n\n\t\thasTool(name: string): boolean {\n\t\t\treturn registry.has(name)\n\t\t},\n\t} as ToolCallBridgeInterface\n}\n\n// ============================================================================\n// Retrieval Tool Factory\n// ============================================================================\n\n/**\n * Create a retrieval tool for use with contextprotocol tool registry.\n *\n * @param options - Retrieval tool configuration options\n * @returns A tool schema and handler for registration\n *\n * @example\n * ```ts\n * import { createVectorStore } from '@mikesaintsg/vectorstore'\n * import { createToolRegistry } from '@mikesaintsg/contextprotocol'\n * import { createRetrievalTool } from '@mikesaintsg/core'\n *\n * const vectorStore = createVectorStore({ ... })\n * const registry = createToolRegistry()\n *\n * const { schema, handler } = createRetrievalTool({\n * vectorStore,\n * name: 'search_docs',\n * description: 'Search documentation for relevant information',\n * defaultLimit: 5,\n * scoreThreshold: 0.7,\n * })\n *\n * registry.register({ ...schema, execute: handler })\n * ```\n */\nexport function createRetrievalTool<TMetadata = unknown>(\n\toptions: RetrievalToolOptions<TMetadata>,\n): RetrievalToolCreated {\n\tconst {\n\t\tvectorStore,\n\t\tname,\n\t\tdescription,\n\t\tdefaultLimit = RETRIEVAL_DEFAULT_LIMIT,\n\t\tmaxLimit = RETRIEVAL_MAX_LIMIT,\n\t\tscoreThreshold,\n\t\tformatResult = formatScoredResult,\n\t\textendParameters = {},\n\t\tbuildFilter,\n\t} = options\n\n\t// Build tool schema parameters\n\tconst parameters: JSONSchema7 = {\n\t\ttype: 'object',\n\t\tproperties: {\n\t\t\tquery: {\n\t\t\t\ttype: 'string',\n\t\t\t\tdescription: 'The search query to find relevant documents',\n\t\t\t},\n\t\t\tlimit: {\n\t\t\t\ttype: 'integer',\n\t\t\t\tdescription: `Maximum number of results to return (default: ${defaultLimit}, max: ${maxLimit})`,\n\t\t\t\tminimum: 1,\n\t\t\t\tmaximum: maxLimit,\n\t\t\t\tdefault: defaultLimit,\n\t\t\t},\n\t\t\t...extendParameters,\n\t\t},\n\t\trequired: ['query'],\n\t}\n\n\tconst schema: ToolSchema = {\n\t\tname,\n\t\tdescription,\n\t\tparameters,\n\t}\n\n\tasync function handler(\n\t\targs: Readonly<Record<string, unknown>>,\n\t): Promise<readonly unknown[]> {\n\t\tconst query = args.query\n\t\tif (typeof query !== 'string' || query.length === 0) {\n\t\t\treturn []\n\t\t}\n\n\t\tconst requestedLimit = args.limit\n\t\tlet limit = defaultLimit\n\t\tif (typeof requestedLimit === 'number' && Number.isInteger(requestedLimit)) {\n\t\t\tlimit = Math.min(Math.max(1, requestedLimit), maxLimit)\n\t\t}\n\n\t\t// Build filter if provided\n\t\tconst filter = buildFilter?.(args)\n\n\t\t// Search vectorstore - only include filter if defined\n\t\tconst searchOptions = filter !== undefined\n\t\t\t? { limit, filter }\n\t\t\t: { limit }\n\t\tconst results = await vectorStore.search(query, searchOptions)\n\n\t\t// Filter by score threshold\n\t\tlet filteredResults = results\n\t\tif (scoreThreshold !== undefined) {\n\t\t\tfilteredResults = results.filter(r => r.score >= scoreThreshold)\n\t\t}\n\n\t\t// Format results\n\t\treturn filteredResults.map(formatResult)\n\t}\n\n\treturn { schema, handler }\n}\n\n// ============================================================================\n// Form Dirty Guard Factory\n// ============================================================================\n\n/**\n * Create a navigation guard that prevents leaving when form is dirty.\n *\n * @param options - Form dirty guard configuration options\n * @returns A navigation guard function\n *\n * @example\n * ```ts\n * import { createForm } from '@mikesaintsg/form'\n * import { createFormDirtyGuard } from '@mikesaintsg/core'\n *\n * const form = createForm({ ... })\n *\n * const guard = createFormDirtyGuard({\n * form,\n * confirmFn: (message) => window.confirm(message),\n * message: 'You have unsaved changes. Continue?',\n * excludePages: ['settings'],\n * })\n *\n * // Use with router\n * router.beforeNavigate(guard)\n * ```\n */\nexport function createFormDirtyGuard<TFormData = unknown, TPage extends string = string>(\n\toptions: FormDirtyGuardOptions<TFormData, TPage>,\n): NavigationGuard<TPage> {\n\tconst {\n\t\tform,\n\t\tconfirmFn,\n\t\tmessage = FORM_DIRTY_DEFAULT_MESSAGE,\n\t\texcludePages = [],\n\t\tonlyFromPages,\n\t} = options\n\n\treturn async function guard(to: TPage, from: TPage): Promise<boolean> {\n\t\t// Check if we should skip guard for this navigation\n\t\tif (shouldSkipFormGuard(to, from, excludePages, onlyFromPages)) {\n\t\t\treturn true\n\t\t}\n\n\t\t// If form is not dirty, allow navigation\n\t\tif (!form.isDirty()) {\n\t\t\treturn true\n\t\t}\n\n\t\t// Form is dirty, ask for confirmation\n\t\treturn Promise.resolve(confirmFn(message))\n\t}\n}\n\n// ============================================================================\n// Session Persistence Factory\n// ============================================================================\n\n/**\n * Create a session persistence adapter for storing inference sessions.\n *\n * @param options - Session persistence configuration options\n * @returns A session persistence instance\n *\n * @example\n * ```ts\n * import { createDatabase } from '@mikesaintsg/indexeddb'\n * import { createSessionPersistence } from '@mikesaintsg/core'\n *\n * const db = await createDatabase({ name: 'sessions' })\n * const persistence = createSessionPersistence({\n * database: db,\n * storeName: 'chat_sessions',\n * autoprune: 7 * 24 * 60 * 60 * 1000, // 7 days\n * })\n *\n * // Save session\n * await persistence.save('session-1', session)\n *\n * // Load session\n * const savedSession = await persistence.load('session-1')\n * ```\n */\nexport function createSessionPersistence(\n\toptions: SessionPersistenceOptions,\n): SessionPersistenceInterface {\n\tconst {\n\t\tdatabase,\n\t\tstoreName,\n\t\tautoprune,\n\t\tonSaveError,\n\t} = options\n\n\tconst store = database.store<SerializedSession>(storeName)\n\n\tasync function pruneOldSessions(maxAgeMs: number): Promise<number> {\n\t\tconst now = Date.now()\n\t\tconst cutoff = now - maxAgeMs\n\n\t\tconst allSessions = await store.all()\n\t\tlet prunedCount = 0\n\n\t\tfor (const session of allSessions) {\n\t\t\tif (session.updatedAt < cutoff) {\n\t\t\t\tawait store.remove(session.id)\n\t\t\t\tprunedCount++\n\t\t\t}\n\t\t}\n\n\t\treturn prunedCount\n\t}\n\n\t// Auto-prune on creation if configured\n\tif (autoprune !== undefined && autoprune > 0) {\n\t\tvoid pruneOldSessions(autoprune)\n\t}\n\n\treturn {\n\t\tasync save(id: string, session: SerializableSession): Promise<void> {\n\t\t\ttry {\n\t\t\t\tconst serialized: SerializedSession = {\n\t\t\t\t\tid,\n\t\t\t\t\tmessages: [...session.getMessages()],\n\t\t\t\t\tmetadata: session.getMetadata(),\n\t\t\t\t\tupdatedAt: Date.now(),\n\t\t\t\t}\n\n\t\t\t\tawait store.set(serialized, id)\n\t\t\t} catch (error) {\n\t\t\t\tonSaveError?.(error, id)\n\t\t\t\tthrow error\n\t\t\t}\n\t\t},\n\n\t\tasync load(id: string): Promise<SerializedSession | undefined> {\n\t\t\treturn store.get(id)\n\t\t},\n\n\t\tasync delete(id: string): Promise<void> {\n\t\t\tawait store.remove(id)\n\t\t},\n\n\t\tasync list(): Promise<readonly string[]> {\n\t\t\tconst allSessions = await store.all()\n\t\t\treturn allSessions.map(s => s.id)\n\t\t},\n\n\t\tasync prune(maxAgeMs: number): Promise<number> {\n\t\t\treturn pruneOldSessions(maxAgeMs)\n\t\t},\n\t}\n}\n"],"names":["EcosystemError","message","cause","isEcosystemError","error","ok","value","err","isOk","result","isErr","unwrap","defaultValue","unwrapOrThrow","map","fn","mapErr","chain","computeContentHash","text","data","hashBuffer","b","isToolCall","shouldSkipFormGuard","to","from","excludePages","onlyFromPages","formatScoredResult","BRIDGE_DEFAULT_TIMEOUT","RETRIEVAL_DEFAULT_LIMIT","RETRIEVAL_MAX_LIMIT","FORM_DIRTY_DEFAULT_MESSAGE","createToolCallBridge","options","registry","timeout","onError","onBeforeExecute","onAfterExecute","executeWithTimeout","toolCall","timeoutPromise","_","reject","errorMessage","toolCallOrCalls","tc","name","createRetrievalTool","vectorStore","description","defaultLimit","maxLimit","scoreThreshold","formatResult","extendParameters","buildFilter","parameters","schema","handler","args","query","requestedLimit","limit","filter","searchOptions","results","filteredResults","r","createFormDirtyGuard","form","confirmFn","createSessionPersistence","database","storeName","autoprune","onSaveError","store","pruneOldSessions","maxAgeMs","cutoff","allSessions","prunedCount","session","id","serialized","s"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikesaintsg/core",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "type": "module",
5
5
  "description": "Type-safe FileSystem wrapper with full TypeScript support. Zero runtime dependencies.",
6
6
  "keywords": [