@mikesaintsg/core 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,20 +1,11 @@
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) {
@@ -23,13 +14,13 @@ function S(e) {
23
14
  function I(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) {
@@ -43,21 +34,34 @@ function B(e, t) {
43
34
  function G(e, t) {
44
35
  return e.ok ? e : I(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 k(e) {
45
+ return typeof e == "object" && e !== null && "id" in e && "name" in e && "arguments" in e;
46
+ }
47
+ function l(e, t, s, a) {
48
+ return s.includes(e) ? !0 : 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 k(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 l(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,
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,
235
224
  I as err,
236
- P as isCoreError,
237
- F as isEcosystemError,
238
- q as isErr,
239
- b as isOk,
225
+ M as formatScoredResult,
226
+ b as isEcosystemError,
227
+ P as isErr,
228
+ F as isOk,
229
+ k as isToolCall,
240
230
  B as map,
241
231
  G as mapErr,
242
232
  S as ok,
243
- O as unwrap,
233
+ l 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\treturn onlyFromPages !== undefined && !onlyFromPages.includes(from)\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\tRetrievalToolInterface,\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): RetrievalToolInterface {\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.4",
4
4
  "type": "module",
5
5
  "description": "Type-safe FileSystem wrapper with full TypeScript support. Zero runtime dependencies.",
6
6
  "keywords": [