@forbocai/browser 0.5.7 → 0.5.8

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.d.mts CHANGED
@@ -5,27 +5,42 @@ declare const createCortex: (config?: CortexConfig) => ICortex;
5
5
 
6
6
  interface IBrowserMemory {
7
7
  store(text: string, type?: string, importance?: number): Promise<MemoryItem>;
8
- recall(query: string, limit?: number): Promise<MemoryItem[]>;
8
+ recall(query: string, limit?: number, threshold?: number): Promise<MemoryItem[]>;
9
+ list(limit?: number, offset?: number): Promise<MemoryItem[]>;
9
10
  clear(): Promise<void>;
11
+ export(): Promise<MemoryItem[]>;
12
+ import(memories: MemoryItem[]): Promise<void>;
10
13
  }
11
14
  declare const createBrowserMemory: (config?: {
12
15
  decay?: "none" | "temporal";
13
16
  maxContextWindow?: number;
14
17
  }) => {
15
18
  store: (text: string, type?: string, importance?: number) => Promise<MemoryItem>;
16
- recall: (query: string, limit?: number) => Promise<MemoryItem[]>;
19
+ recall: (query: string, limit?: number, threshold?: number) => Promise<MemoryItem[]>;
20
+ list: (limit?: number, offset?: number) => Promise<MemoryItem[]>;
17
21
  clear: () => Promise<void>;
22
+ export: () => Promise<MemoryItem[]>;
23
+ import: (memories: MemoryItem[]) => Promise<void>;
18
24
  };
19
25
  declare const createMemory: (config?: {
20
26
  decay?: "none" | "temporal";
21
27
  maxContextWindow?: number;
22
28
  }) => {
23
29
  store: (text: string, type?: string, importance?: number) => Promise<MemoryItem>;
24
- recall: (query: string, limit?: number) => Promise<MemoryItem[]>;
30
+ recall: (query: string, limit?: number, threshold?: number) => Promise<MemoryItem[]>;
31
+ list: (limit?: number, offset?: number) => Promise<MemoryItem[]>;
25
32
  clear: () => Promise<void>;
33
+ export: () => Promise<MemoryItem[]>;
34
+ import: (memories: MemoryItem[]) => Promise<void>;
26
35
  };
27
36
 
37
+ /**
38
+ * Initialize the vector engine.
39
+ */
28
40
  declare const initVectorEngine: () => Promise<void>;
41
+ /**
42
+ * Generate embeddings using Transformers.js.
43
+ */
29
44
  declare const generateEmbedding: (text: string) => Promise<number[]>;
30
45
 
31
46
  export { type IBrowserMemory, createBrowserCortex, createBrowserMemory, createCortex, createMemory, generateEmbedding, initVectorEngine };
package/dist/index.d.ts CHANGED
@@ -5,27 +5,42 @@ declare const createCortex: (config?: CortexConfig) => ICortex;
5
5
 
6
6
  interface IBrowserMemory {
7
7
  store(text: string, type?: string, importance?: number): Promise<MemoryItem>;
8
- recall(query: string, limit?: number): Promise<MemoryItem[]>;
8
+ recall(query: string, limit?: number, threshold?: number): Promise<MemoryItem[]>;
9
+ list(limit?: number, offset?: number): Promise<MemoryItem[]>;
9
10
  clear(): Promise<void>;
11
+ export(): Promise<MemoryItem[]>;
12
+ import(memories: MemoryItem[]): Promise<void>;
10
13
  }
11
14
  declare const createBrowserMemory: (config?: {
12
15
  decay?: "none" | "temporal";
13
16
  maxContextWindow?: number;
14
17
  }) => {
15
18
  store: (text: string, type?: string, importance?: number) => Promise<MemoryItem>;
16
- recall: (query: string, limit?: number) => Promise<MemoryItem[]>;
19
+ recall: (query: string, limit?: number, threshold?: number) => Promise<MemoryItem[]>;
20
+ list: (limit?: number, offset?: number) => Promise<MemoryItem[]>;
17
21
  clear: () => Promise<void>;
22
+ export: () => Promise<MemoryItem[]>;
23
+ import: (memories: MemoryItem[]) => Promise<void>;
18
24
  };
19
25
  declare const createMemory: (config?: {
20
26
  decay?: "none" | "temporal";
21
27
  maxContextWindow?: number;
22
28
  }) => {
23
29
  store: (text: string, type?: string, importance?: number) => Promise<MemoryItem>;
24
- recall: (query: string, limit?: number) => Promise<MemoryItem[]>;
30
+ recall: (query: string, limit?: number, threshold?: number) => Promise<MemoryItem[]>;
31
+ list: (limit?: number, offset?: number) => Promise<MemoryItem[]>;
25
32
  clear: () => Promise<void>;
33
+ export: () => Promise<MemoryItem[]>;
34
+ import: (memories: MemoryItem[]) => Promise<void>;
26
35
  };
27
36
 
37
+ /**
38
+ * Initialize the vector engine.
39
+ */
28
40
  declare const initVectorEngine: () => Promise<void>;
41
+ /**
42
+ * Generate embeddings using Transformers.js.
43
+ */
29
44
  declare const generateEmbedding: (text: string) => Promise<number[]>;
30
45
 
31
46
  export { type IBrowserMemory, createBrowserCortex, createBrowserMemory, createCortex, createMemory, generateEmbedding, initVectorEngine };
package/dist/index.js CHANGED
@@ -49,43 +49,57 @@ var MODEL_ALIASES = {
49
49
  "llama3-8b": "Llama-3.1-8B-Instruct-q4f16_1-MLC"
50
50
  };
51
51
  var resolveModelId = (alias) => MODEL_ALIASES[alias] ?? alias;
52
+ var yieldTokens = async function* (iterator) {
53
+ const { value, done } = await iterator.next();
54
+ if (done) return;
55
+ const content = value.choices[0]?.delta?.content || "";
56
+ if (content) yield content;
57
+ yield* yieldTokens(iterator);
58
+ };
52
59
  var createBrowserCortex = (config = {}) => {
53
60
  const friendlyModel = config.model || DEFAULT_MODEL;
54
- let engine = null;
55
- let status = {
56
- id: "browser-init",
57
- model: friendlyModel,
58
- ready: false,
59
- engine: "web-llm"
61
+ const modelId = resolveModelId(friendlyModel);
62
+ let _state = {
63
+ engine: null,
64
+ status: {
65
+ id: "browser-init",
66
+ model: friendlyModel,
67
+ ready: false,
68
+ engine: "web-llm"
69
+ }
60
70
  };
61
71
  const init = async (onProgress) => {
62
- if (status.ready) return status;
72
+ if (_state.status.ready) return _state.status;
63
73
  if (typeof window === "undefined") {
64
- throw new Error("BrowserCortex can only be initialized in a browser environment");
74
+ throw new Error("BrowserCortex requires a browser environment");
65
75
  }
66
76
  const { CreateWebWorkerMLCEngine } = await import("@mlc-ai/web-llm");
67
77
  const initProgressCallback = (report) => {
68
78
  const match = report.text?.match(/(\d+)%/);
69
- if (onProgress && match) {
70
- onProgress(parseInt(match[1], 10));
71
- }
79
+ if (onProgress && match) onProgress(parseInt(match[1], 10));
72
80
  };
73
- const modelId = resolveModelId(friendlyModel);
74
- engine = await CreateWebWorkerMLCEngine(
81
+ const engine = await CreateWebWorkerMLCEngine(
75
82
  new Worker(new URL("./worker.js", import_meta.url), { type: "module" }),
76
83
  modelId,
77
84
  { initProgressCallback }
78
85
  );
79
- status = {
80
- id: `ctx_web_${Date.now()}`,
81
- model: modelId,
82
- ready: true,
83
- engine: "web-llm"
86
+ _state = {
87
+ engine,
88
+ status: {
89
+ id: `ctx_web_${Date.now()}`,
90
+ model: modelId,
91
+ ready: true,
92
+ engine: "web-llm"
93
+ }
84
94
  };
85
- return status;
95
+ return _state.status;
96
+ };
97
+ const ensureReady = async () => {
98
+ if (!_state.status.ready) await init();
99
+ return _state;
86
100
  };
87
101
  const complete = async (prompt, options = {}) => {
88
- if (!status.ready) await init();
102
+ const { engine } = await ensureReady();
89
103
  const reply = await engine.chat.completions.create({
90
104
  messages: [{ role: "user", content: prompt }],
91
105
  max_gen_len: options.maxTokens,
@@ -94,43 +108,37 @@ var createBrowserCortex = (config = {}) => {
94
108
  return reply.choices[0].message.content || "";
95
109
  };
96
110
  const completeStream = async function* (prompt, options = {}) {
97
- if (!status.ready) await init();
111
+ const { engine } = await ensureReady();
98
112
  const chunks = await engine.chat.completions.create({
99
113
  messages: [{ role: "user", content: prompt }],
100
114
  max_gen_len: options.maxTokens,
101
115
  temperature: options.temperature,
102
116
  stream: true
103
117
  });
104
- for await (const chunk of chunks) {
105
- const content = chunk.choices[0]?.delta?.content || "";
106
- if (content) yield content;
107
- }
108
- };
109
- return {
110
- init,
111
- complete,
112
- completeStream
118
+ yield* yieldTokens(chunks[Symbol.asyncIterator]());
113
119
  };
120
+ return { init, complete, completeStream };
114
121
  };
115
122
  var createCortex = (config = {}) => createBrowserCortex(config);
116
123
 
124
+ // src/memory.ts
125
+ var import_core2 = require("@forbocai/core");
126
+
117
127
  // src/vector.ts
118
- var embedder = null;
119
- var initVectorEngine = async () => {
120
- if (embedder) return;
128
+ var import_core = require("@forbocai/core");
129
+ var getEmbedder = (0, import_core.memoiseAsync)(async () => {
121
130
  if (typeof window === "undefined") {
122
- throw new Error("BrowserVectorEngine can only be initialized in a browser environment");
123
- }
124
- try {
125
- const { pipeline } = await import("@huggingface/transformers");
126
- embedder = await pipeline("feature-extraction", "Xenova/all-MiniLM-L6-v2");
127
- } catch (e) {
128
- console.error("Failed to init Browser Vector Engine:", e);
131
+ throw new Error("BrowserVectorEngine requires a browser environment");
129
132
  }
133
+ const { pipeline } = await import("@huggingface/transformers");
134
+ return pipeline("feature-extraction", "Xenova/all-MiniLM-L6-v2");
135
+ });
136
+ var initVectorEngine = async () => {
137
+ await getEmbedder();
130
138
  };
131
139
  var generateEmbedding = async (text) => {
132
- if (!embedder) await initVectorEngine();
133
140
  try {
141
+ const embedder = await getEmbedder();
134
142
  const result = await embedder(text, { pooling: "mean", normalize: true });
135
143
  return Array.from(result.data);
136
144
  } catch (e) {
@@ -141,14 +149,12 @@ var generateEmbedding = async (text) => {
141
149
 
142
150
  // src/memory.ts
143
151
  var createBrowserMemory = (config = {}) => {
144
- let db = null;
145
- const init = async () => {
146
- if (db) return db;
152
+ const getDb = (0, import_core2.memoiseAsync)(async () => {
147
153
  if (typeof window === "undefined") {
148
- throw new Error("BrowserMemory can only be initialized in a browser environment");
154
+ throw new Error("BrowserMemory requires a browser environment");
149
155
  }
150
156
  const { create } = await import("@orama/orama");
151
- db = await create({
157
+ return create({
152
158
  schema: {
153
159
  id: "string",
154
160
  text: "string",
@@ -156,13 +162,11 @@ var createBrowserMemory = (config = {}) => {
156
162
  type: "string",
157
163
  importance: "number",
158
164
  embedding: "vector[384]"
159
- // all-MiniLM-L6-v2
160
165
  }
161
166
  });
162
- return db;
163
- };
167
+ });
164
168
  const store = async (text, type = "observation", importance = 0.5) => {
165
- const instance = await init();
169
+ const instance = await getDb();
166
170
  const item = {
167
171
  id: `mem_br_${Date.now()}_${Math.random().toString(36).substring(7)}`,
168
172
  text,
@@ -172,31 +176,34 @@ var createBrowserMemory = (config = {}) => {
172
176
  };
173
177
  const embedding = await generateEmbedding(text);
174
178
  const { insert } = await import("@orama/orama");
175
- await insert(instance, {
176
- ...item,
177
- embedding
178
- });
179
+ await insert(instance, { ...item, embedding });
179
180
  return item;
180
181
  };
181
- const recall = async (query, limit = 5) => {
182
- const instance = await init();
182
+ const recall = async (query, limit = 5, threshold) => {
183
+ const instance = await getDb();
183
184
  const embedding = await generateEmbedding(query);
184
185
  const { search } = await import("@orama/orama");
185
186
  const results = await search(instance, {
186
187
  mode: "vector",
187
- vector: {
188
- value: embedding,
189
- property: "embedding"
190
- },
191
- similarity: 0.5,
188
+ vector: { value: embedding, property: "embedding" },
189
+ similarity: threshold ?? 0.5,
192
190
  limit
193
191
  });
194
192
  return results.hits.map((hit) => hit.document);
195
193
  };
194
+ const list = async (limit = 50, offset = 0) => {
195
+ const instance = await getDb();
196
+ const { search } = await import("@orama/orama");
197
+ const results = await search(instance, { term: "", limit: limit + offset });
198
+ return results.hits.slice(offset).map((hit) => hit.document);
199
+ };
196
200
  const clear = async () => {
197
- db = null;
198
201
  };
199
- return { store, recall, clear };
202
+ const exportMemories = async () => list(1e4);
203
+ const importMemories = async (memories) => {
204
+ await Promise.all(memories.map((m) => store(m.text, m.type, m.importance)));
205
+ };
206
+ return { store, recall, list, clear, export: exportMemories, import: importMemories };
200
207
  };
201
208
  var createMemory = (config = {}) => createBrowserMemory(config);
202
209
  // Annotate the CommonJS export names for ESM import in node:
package/dist/index.mjs CHANGED
@@ -7,43 +7,57 @@ var MODEL_ALIASES = {
7
7
  "llama3-8b": "Llama-3.1-8B-Instruct-q4f16_1-MLC"
8
8
  };
9
9
  var resolveModelId = (alias) => MODEL_ALIASES[alias] ?? alias;
10
+ var yieldTokens = async function* (iterator) {
11
+ const { value, done } = await iterator.next();
12
+ if (done) return;
13
+ const content = value.choices[0]?.delta?.content || "";
14
+ if (content) yield content;
15
+ yield* yieldTokens(iterator);
16
+ };
10
17
  var createBrowserCortex = (config = {}) => {
11
18
  const friendlyModel = config.model || DEFAULT_MODEL;
12
- let engine = null;
13
- let status = {
14
- id: "browser-init",
15
- model: friendlyModel,
16
- ready: false,
17
- engine: "web-llm"
19
+ const modelId = resolveModelId(friendlyModel);
20
+ let _state = {
21
+ engine: null,
22
+ status: {
23
+ id: "browser-init",
24
+ model: friendlyModel,
25
+ ready: false,
26
+ engine: "web-llm"
27
+ }
18
28
  };
19
29
  const init = async (onProgress) => {
20
- if (status.ready) return status;
30
+ if (_state.status.ready) return _state.status;
21
31
  if (typeof window === "undefined") {
22
- throw new Error("BrowserCortex can only be initialized in a browser environment");
32
+ throw new Error("BrowserCortex requires a browser environment");
23
33
  }
24
34
  const { CreateWebWorkerMLCEngine } = await import("@mlc-ai/web-llm");
25
35
  const initProgressCallback = (report) => {
26
36
  const match = report.text?.match(/(\d+)%/);
27
- if (onProgress && match) {
28
- onProgress(parseInt(match[1], 10));
29
- }
37
+ if (onProgress && match) onProgress(parseInt(match[1], 10));
30
38
  };
31
- const modelId = resolveModelId(friendlyModel);
32
- engine = await CreateWebWorkerMLCEngine(
39
+ const engine = await CreateWebWorkerMLCEngine(
33
40
  new Worker(new URL("./worker.js", import.meta.url), { type: "module" }),
34
41
  modelId,
35
42
  { initProgressCallback }
36
43
  );
37
- status = {
38
- id: `ctx_web_${Date.now()}`,
39
- model: modelId,
40
- ready: true,
41
- engine: "web-llm"
44
+ _state = {
45
+ engine,
46
+ status: {
47
+ id: `ctx_web_${Date.now()}`,
48
+ model: modelId,
49
+ ready: true,
50
+ engine: "web-llm"
51
+ }
42
52
  };
43
- return status;
53
+ return _state.status;
54
+ };
55
+ const ensureReady = async () => {
56
+ if (!_state.status.ready) await init();
57
+ return _state;
44
58
  };
45
59
  const complete = async (prompt, options = {}) => {
46
- if (!status.ready) await init();
60
+ const { engine } = await ensureReady();
47
61
  const reply = await engine.chat.completions.create({
48
62
  messages: [{ role: "user", content: prompt }],
49
63
  max_gen_len: options.maxTokens,
@@ -52,43 +66,37 @@ var createBrowserCortex = (config = {}) => {
52
66
  return reply.choices[0].message.content || "";
53
67
  };
54
68
  const completeStream = async function* (prompt, options = {}) {
55
- if (!status.ready) await init();
69
+ const { engine } = await ensureReady();
56
70
  const chunks = await engine.chat.completions.create({
57
71
  messages: [{ role: "user", content: prompt }],
58
72
  max_gen_len: options.maxTokens,
59
73
  temperature: options.temperature,
60
74
  stream: true
61
75
  });
62
- for await (const chunk of chunks) {
63
- const content = chunk.choices[0]?.delta?.content || "";
64
- if (content) yield content;
65
- }
66
- };
67
- return {
68
- init,
69
- complete,
70
- completeStream
76
+ yield* yieldTokens(chunks[Symbol.asyncIterator]());
71
77
  };
78
+ return { init, complete, completeStream };
72
79
  };
73
80
  var createCortex = (config = {}) => createBrowserCortex(config);
74
81
 
82
+ // src/memory.ts
83
+ import { memoiseAsync as memoiseAsync2 } from "@forbocai/core";
84
+
75
85
  // src/vector.ts
76
- var embedder = null;
77
- var initVectorEngine = async () => {
78
- if (embedder) return;
86
+ import { memoiseAsync } from "@forbocai/core";
87
+ var getEmbedder = memoiseAsync(async () => {
79
88
  if (typeof window === "undefined") {
80
- throw new Error("BrowserVectorEngine can only be initialized in a browser environment");
81
- }
82
- try {
83
- const { pipeline } = await import("@huggingface/transformers");
84
- embedder = await pipeline("feature-extraction", "Xenova/all-MiniLM-L6-v2");
85
- } catch (e) {
86
- console.error("Failed to init Browser Vector Engine:", e);
89
+ throw new Error("BrowserVectorEngine requires a browser environment");
87
90
  }
91
+ const { pipeline } = await import("@huggingface/transformers");
92
+ return pipeline("feature-extraction", "Xenova/all-MiniLM-L6-v2");
93
+ });
94
+ var initVectorEngine = async () => {
95
+ await getEmbedder();
88
96
  };
89
97
  var generateEmbedding = async (text) => {
90
- if (!embedder) await initVectorEngine();
91
98
  try {
99
+ const embedder = await getEmbedder();
92
100
  const result = await embedder(text, { pooling: "mean", normalize: true });
93
101
  return Array.from(result.data);
94
102
  } catch (e) {
@@ -99,14 +107,12 @@ var generateEmbedding = async (text) => {
99
107
 
100
108
  // src/memory.ts
101
109
  var createBrowserMemory = (config = {}) => {
102
- let db = null;
103
- const init = async () => {
104
- if (db) return db;
110
+ const getDb = memoiseAsync2(async () => {
105
111
  if (typeof window === "undefined") {
106
- throw new Error("BrowserMemory can only be initialized in a browser environment");
112
+ throw new Error("BrowserMemory requires a browser environment");
107
113
  }
108
114
  const { create } = await import("@orama/orama");
109
- db = await create({
115
+ return create({
110
116
  schema: {
111
117
  id: "string",
112
118
  text: "string",
@@ -114,13 +120,11 @@ var createBrowserMemory = (config = {}) => {
114
120
  type: "string",
115
121
  importance: "number",
116
122
  embedding: "vector[384]"
117
- // all-MiniLM-L6-v2
118
123
  }
119
124
  });
120
- return db;
121
- };
125
+ });
122
126
  const store = async (text, type = "observation", importance = 0.5) => {
123
- const instance = await init();
127
+ const instance = await getDb();
124
128
  const item = {
125
129
  id: `mem_br_${Date.now()}_${Math.random().toString(36).substring(7)}`,
126
130
  text,
@@ -130,31 +134,34 @@ var createBrowserMemory = (config = {}) => {
130
134
  };
131
135
  const embedding = await generateEmbedding(text);
132
136
  const { insert } = await import("@orama/orama");
133
- await insert(instance, {
134
- ...item,
135
- embedding
136
- });
137
+ await insert(instance, { ...item, embedding });
137
138
  return item;
138
139
  };
139
- const recall = async (query, limit = 5) => {
140
- const instance = await init();
140
+ const recall = async (query, limit = 5, threshold) => {
141
+ const instance = await getDb();
141
142
  const embedding = await generateEmbedding(query);
142
143
  const { search } = await import("@orama/orama");
143
144
  const results = await search(instance, {
144
145
  mode: "vector",
145
- vector: {
146
- value: embedding,
147
- property: "embedding"
148
- },
149
- similarity: 0.5,
146
+ vector: { value: embedding, property: "embedding" },
147
+ similarity: threshold ?? 0.5,
150
148
  limit
151
149
  });
152
150
  return results.hits.map((hit) => hit.document);
153
151
  };
152
+ const list = async (limit = 50, offset = 0) => {
153
+ const instance = await getDb();
154
+ const { search } = await import("@orama/orama");
155
+ const results = await search(instance, { term: "", limit: limit + offset });
156
+ return results.hits.slice(offset).map((hit) => hit.document);
157
+ };
154
158
  const clear = async () => {
155
- db = null;
156
159
  };
157
- return { store, recall, clear };
160
+ const exportMemories = async () => list(1e4);
161
+ const importMemories = async (memories) => {
162
+ await Promise.all(memories.map((m) => store(m.text, m.type, m.importance)));
163
+ };
164
+ return { store, recall, list, clear, export: exportMemories, import: importMemories };
158
165
  };
159
166
  var createMemory = (config = {}) => createBrowserMemory(config);
160
167
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forbocai/browser",
3
- "version": "0.5.7",
3
+ "version": "0.5.8",
4
4
  "license": "UNLICENSED",
5
5
  "description": "Web Browser implementation for ForbocAI SDK",
6
6
  "main": "dist/index.js",
@@ -12,7 +12,7 @@
12
12
  "test": "vitest"
13
13
  },
14
14
  "dependencies": {
15
- "@forbocai/core": "^0.5.7",
15
+ "@forbocai/core": "^0.5.8",
16
16
  "@mlc-ai/web-llm": "^0.2.46",
17
17
  "@orama/orama": "^2.0.26",
18
18
  "@huggingface/transformers": "^3.0.0"