@mikesaintsg/core 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +365 -0
- package/dist/index.d.ts +1299 -0
- package/dist/index.js +828 -0
- package/dist/index.js.map +1 -0
- package/package.json +64 -0
package/README.md
ADDED
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
# @mikesaintsg/core
|
|
2
|
+
|
|
3
|
+
> Shared types, contracts, bridge functions, and adapters for the @mikesaintsg ecosystem.
|
|
4
|
+
|
|
5
|
+
[](https://www.typescriptlang.org/)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
`@mikesaintsg/core` provides the integration layer for the @mikesaintsg ecosystem, including:
|
|
11
|
+
|
|
12
|
+
- **Shared Types** — Contracts used across multiple packages
|
|
13
|
+
- **Result Pattern** — Functional error handling helpers
|
|
14
|
+
- **Embedding Adapters** — OpenAI, Anthropic (Voyage AI), batched, cached
|
|
15
|
+
- **Tool Format Adapters** — Convert between internal and provider formats
|
|
16
|
+
- **Persistence Adapters** — IndexedDB, OPFS, HTTP for VectorStore
|
|
17
|
+
- **Bridge Functions** — Connect packages without circular dependencies
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @mikesaintsg/core
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
### Result Pattern
|
|
28
|
+
|
|
29
|
+
Handle errors functionally without try/catch:
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { ok, err, isOk, map, chain } from '@mikesaintsg/core'
|
|
33
|
+
import type { Result } from '@mikesaintsg/core'
|
|
34
|
+
|
|
35
|
+
// Create results
|
|
36
|
+
const success = ok(42)
|
|
37
|
+
const failure = err('NOT_FOUND')
|
|
38
|
+
|
|
39
|
+
// Check and unwrap
|
|
40
|
+
if (isOk(success)) {
|
|
41
|
+
console.log(success.value) // 42
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Transform values
|
|
45
|
+
const doubled = map(ok(5), x => x * 2) // ok(10)
|
|
46
|
+
|
|
47
|
+
// Chain operations
|
|
48
|
+
function parse(s: string): Result<number, string> {
|
|
49
|
+
const n = parseInt(s, 10)
|
|
50
|
+
return isNaN(n) ? err('PARSE_ERROR') : ok(n)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const result = chain(ok('42'), parse) // ok(42)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Tool Call Bridge
|
|
57
|
+
|
|
58
|
+
Connect LLM tool calls to a tool registry:
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import { createToolCallBridge } from '@mikesaintsg/core'
|
|
62
|
+
import type { ToolRegistryMinimal, ToolCall } from '@mikesaintsg/core'
|
|
63
|
+
|
|
64
|
+
// Create a minimal registry (from contextprotocol or custom)
|
|
65
|
+
const registry: ToolRegistryMinimal = {
|
|
66
|
+
has: (name) => name === 'get_weather',
|
|
67
|
+
execute: async (name, args) => {
|
|
68
|
+
if (name === 'get_weather') {
|
|
69
|
+
return { temperature: 72, conditions: 'sunny' }
|
|
70
|
+
}
|
|
71
|
+
throw new Error('Unknown tool')
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Create bridge
|
|
76
|
+
const bridge = createToolCallBridge({
|
|
77
|
+
registry,
|
|
78
|
+
timeout: 30000,
|
|
79
|
+
onError: (error, toolCall) => console.error(`Tool ${toolCall.name} failed:`, error),
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
// Execute tool calls from LLM
|
|
83
|
+
const toolCall: ToolCall = {
|
|
84
|
+
id: 'call-1',
|
|
85
|
+
name: 'get_weather',
|
|
86
|
+
arguments: { location: 'Seattle' },
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const result = await bridge.execute(toolCall)
|
|
90
|
+
// { callId: 'call-1', name: 'get_weather', success: true, value: { temperature: 72, conditions: 'sunny' } }
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Retrieval Tool Factory
|
|
94
|
+
|
|
95
|
+
Create vectorstore-backed tools for RAG:
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { createRetrievalTool } from '@mikesaintsg/core'
|
|
99
|
+
import type { VectorStoreMinimal } from '@mikesaintsg/core'
|
|
100
|
+
|
|
101
|
+
// Your vectorstore implementation
|
|
102
|
+
const vectorStore: VectorStoreMinimal = {
|
|
103
|
+
search: async (query, options) => {
|
|
104
|
+
// Return scored results from your vector database
|
|
105
|
+
return [
|
|
106
|
+
{ id: '1', content: 'Relevant document', score: 0.95 },
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Create retrieval tool
|
|
112
|
+
const { schema, handler } = createRetrievalTool({
|
|
113
|
+
vectorStore,
|
|
114
|
+
name: 'search_knowledge',
|
|
115
|
+
description: 'Search the knowledge base for relevant information',
|
|
116
|
+
defaultLimit: 5,
|
|
117
|
+
scoreThreshold: 0.7,
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
// Register with your tool registry
|
|
121
|
+
registry.register(schema.name, handler)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Form Dirty Guard
|
|
125
|
+
|
|
126
|
+
Prevent navigation when forms have unsaved changes:
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
import { createFormDirtyGuard } from '@mikesaintsg/core'
|
|
130
|
+
import type { FormMinimal } from '@mikesaintsg/core'
|
|
131
|
+
|
|
132
|
+
const form: FormMinimal = {
|
|
133
|
+
isDirty: () => formState.hasUnsavedChanges,
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const guard = createFormDirtyGuard({
|
|
137
|
+
form,
|
|
138
|
+
confirmFn: (message) => window.confirm(message),
|
|
139
|
+
message: 'You have unsaved changes. Are you sure you want to leave?',
|
|
140
|
+
excludePages: ['logout', 'help'],
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
// Use with your router
|
|
144
|
+
router.beforeNavigate(guard)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Session Persistence
|
|
148
|
+
|
|
149
|
+
Persist inference sessions to IndexedDB:
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
import { createSessionPersistence } from '@mikesaintsg/core'
|
|
153
|
+
import type { MinimalDatabaseAccess } from '@mikesaintsg/core'
|
|
154
|
+
|
|
155
|
+
// Your database implementation (from @mikesaintsg/indexeddb)
|
|
156
|
+
const database: MinimalDatabaseAccess = createDatabase({ name: 'sessions' })
|
|
157
|
+
|
|
158
|
+
const persistence = createSessionPersistence({
|
|
159
|
+
database,
|
|
160
|
+
storeName: 'chat_sessions',
|
|
161
|
+
autoprune: 7 * 24 * 60 * 60 * 1000, // 7 days
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
// Save session
|
|
165
|
+
await persistence.save('session-1', session)
|
|
166
|
+
|
|
167
|
+
// Load session
|
|
168
|
+
const saved = await persistence.load('session-1')
|
|
169
|
+
|
|
170
|
+
// List all sessions
|
|
171
|
+
const sessionIds = await persistence.list()
|
|
172
|
+
|
|
173
|
+
// Prune old sessions
|
|
174
|
+
const prunedCount = await persistence.prune(24 * 60 * 60 * 1000)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Embedding Adapters
|
|
178
|
+
|
|
179
|
+
Generate embeddings with OpenAI or Anthropic:
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
import {
|
|
183
|
+
createOpenAIEmbeddingAdapter,
|
|
184
|
+
createAnthropicEmbeddingAdapter,
|
|
185
|
+
createBatchedEmbeddingAdapter,
|
|
186
|
+
createEmbeddingCache,
|
|
187
|
+
} from '@mikesaintsg/core'
|
|
188
|
+
|
|
189
|
+
// OpenAI adapter
|
|
190
|
+
const openai = createOpenAIEmbeddingAdapter({
|
|
191
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
192
|
+
model: 'text-embedding-3-small',
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
// Anthropic adapter (uses Voyage AI)
|
|
196
|
+
const anthropic = createAnthropicEmbeddingAdapter({
|
|
197
|
+
apiKey: process.env.VOYAGE_API_KEY,
|
|
198
|
+
model: 'voyage-2',
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
// Add batching and caching
|
|
202
|
+
const cache = createEmbeddingCache({ maxEntries: 1000, ttlMs: 3600000 })
|
|
203
|
+
const batched = createBatchedEmbeddingAdapter(openai, {
|
|
204
|
+
maxBatchSize: 100,
|
|
205
|
+
flushDelayMs: 50,
|
|
206
|
+
deduplicate: true,
|
|
207
|
+
cache,
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
// Generate embeddings
|
|
211
|
+
const embeddings = await batched.queueBatch([
|
|
212
|
+
'Hello, world!',
|
|
213
|
+
'How are you?',
|
|
214
|
+
])
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Tool Format Adapters
|
|
218
|
+
|
|
219
|
+
Convert tool schemas between formats:
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
import {
|
|
223
|
+
createOpenAIToolFormatAdapter,
|
|
224
|
+
createAnthropicToolFormatAdapter,
|
|
225
|
+
} from '@mikesaintsg/core'
|
|
226
|
+
import type { ToolSchema } from '@mikesaintsg/core'
|
|
227
|
+
|
|
228
|
+
const schema: ToolSchema = {
|
|
229
|
+
name: 'get_weather',
|
|
230
|
+
description: 'Get the current weather',
|
|
231
|
+
parameters: {
|
|
232
|
+
type: 'object',
|
|
233
|
+
properties: {
|
|
234
|
+
location: { type: 'string', description: 'City name' },
|
|
235
|
+
},
|
|
236
|
+
required: ['location'],
|
|
237
|
+
},
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// OpenAI format
|
|
241
|
+
const openaiAdapter = createOpenAIToolFormatAdapter()
|
|
242
|
+
const openaiTools = openaiAdapter.formatSchemas([schema])
|
|
243
|
+
|
|
244
|
+
// Anthropic format
|
|
245
|
+
const anthropicAdapter = createAnthropicToolFormatAdapter()
|
|
246
|
+
const anthropicTools = anthropicAdapter.formatSchemas([schema])
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Persistence Adapters
|
|
250
|
+
|
|
251
|
+
Store VectorStore data in different backends:
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
import {
|
|
255
|
+
createIndexedDBVectorStorePersistence,
|
|
256
|
+
createOPFSVectorStorePersistence,
|
|
257
|
+
createHTTPVectorStorePersistence,
|
|
258
|
+
} from '@mikesaintsg/core'
|
|
259
|
+
|
|
260
|
+
// IndexedDB
|
|
261
|
+
const idbPersistence = createIndexedDBVectorStorePersistence({
|
|
262
|
+
database,
|
|
263
|
+
documentsStore: 'embeddings',
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
// OPFS (Origin Private File System)
|
|
267
|
+
const opfsPersistence = createOPFSVectorStorePersistence({
|
|
268
|
+
directory,
|
|
269
|
+
chunkSize: 100,
|
|
270
|
+
})
|
|
271
|
+
|
|
272
|
+
// HTTP (remote storage)
|
|
273
|
+
const httpPersistence = createHTTPVectorStorePersistence({
|
|
274
|
+
baseURL: 'https://api.example.com/vectors',
|
|
275
|
+
headers: { Authorization: 'Bearer token' },
|
|
276
|
+
timeout: 30000,
|
|
277
|
+
})
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## API Reference
|
|
281
|
+
|
|
282
|
+
### Result Pattern
|
|
283
|
+
|
|
284
|
+
| Function | Description |
|
|
285
|
+
|----------|-------------|
|
|
286
|
+
| `ok(value)` | Create a success result |
|
|
287
|
+
| `err(error)` | Create a failure result |
|
|
288
|
+
| `isOk(result)` | Check if result is success |
|
|
289
|
+
| `isErr(result)` | Check if result is failure |
|
|
290
|
+
| `unwrap(result, default)` | Get value or default |
|
|
291
|
+
| `unwrapOrThrow(result)` | Get value or throw |
|
|
292
|
+
| `map(result, fn)` | Transform success value |
|
|
293
|
+
| `mapErr(result, fn)` | Transform error value |
|
|
294
|
+
| `chain(result, fn)` | Sequence operations |
|
|
295
|
+
|
|
296
|
+
### Bridge Functions
|
|
297
|
+
|
|
298
|
+
| Function | Description |
|
|
299
|
+
|----------|-------------|
|
|
300
|
+
| `createToolCallBridge(options)` | Connect tool calls to registry |
|
|
301
|
+
| `createRetrievalTool(options)` | Create vectorstore search tool |
|
|
302
|
+
| `createFormDirtyGuard(options)` | Navigation guard for dirty forms |
|
|
303
|
+
| `createSessionPersistence(options)` | Persist sessions to IndexedDB |
|
|
304
|
+
|
|
305
|
+
### Embedding Adapters
|
|
306
|
+
|
|
307
|
+
| Function | Description |
|
|
308
|
+
|----------|-------------|
|
|
309
|
+
| `createOpenAIEmbeddingAdapter(options)` | OpenAI embeddings API |
|
|
310
|
+
| `createAnthropicEmbeddingAdapter(options)` | Voyage AI embeddings |
|
|
311
|
+
| `createBatchedEmbeddingAdapter(adapter, options)` | Batching wrapper |
|
|
312
|
+
| `createEmbeddingCache(options)` | LRU cache with TTL |
|
|
313
|
+
|
|
314
|
+
### Tool Format Adapters
|
|
315
|
+
|
|
316
|
+
| Function | Description |
|
|
317
|
+
|----------|-------------|
|
|
318
|
+
| `createOpenAIToolFormatAdapter(options)` | OpenAI tool format |
|
|
319
|
+
| `createAnthropicToolFormatAdapter(options)` | Anthropic tool format |
|
|
320
|
+
|
|
321
|
+
### Persistence Adapters
|
|
322
|
+
|
|
323
|
+
| Function | Description |
|
|
324
|
+
|----------|-------------|
|
|
325
|
+
| `createIndexedDBVectorStorePersistence(options)` | IndexedDB storage |
|
|
326
|
+
| `createOPFSVectorStorePersistence(options)` | OPFS storage |
|
|
327
|
+
| `createHTTPVectorStorePersistence(options)` | HTTP storage |
|
|
328
|
+
|
|
329
|
+
## Types
|
|
330
|
+
|
|
331
|
+
All types are exported from the main entry point:
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
import type {
|
|
335
|
+
// Result pattern
|
|
336
|
+
Result, Ok, Err,
|
|
337
|
+
|
|
338
|
+
// Embedding types
|
|
339
|
+
Embedding, EmbeddingAdapterInterface, EmbeddingModelMetadata,
|
|
340
|
+
|
|
341
|
+
// Tool types
|
|
342
|
+
ToolCall, ToolResult, ToolSchema, JSONSchema7,
|
|
343
|
+
|
|
344
|
+
// Bridge types
|
|
345
|
+
ToolCallBridgeInterface, ToolRegistryMinimal,
|
|
346
|
+
RetrievalToolOptions, VectorStoreMinimal,
|
|
347
|
+
FormDirtyGuardOptions, NavigationGuard,
|
|
348
|
+
SessionPersistenceInterface, SerializedSession,
|
|
349
|
+
|
|
350
|
+
// Persistence types
|
|
351
|
+
VectorStorePersistenceAdapterInterface, StoredDocument,
|
|
352
|
+
|
|
353
|
+
// Minimal cross-package interfaces
|
|
354
|
+
MinimalDatabaseAccess, MinimalStoreAccess,
|
|
355
|
+
MinimalDirectoryAccess, MinimalFileAccess,
|
|
356
|
+
} from '@mikesaintsg/core'
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
## License
|
|
360
|
+
|
|
361
|
+
MIT © mikesaintsg
|
|
362
|
+
|
|
363
|
+
## Contributing
|
|
364
|
+
|
|
365
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.
|