@kb-labs/mind-core 2.94.0 → 2.96.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,169 @@
1
+ import { mkdtempSync, mkdirSync, writeFileSync } from 'fs';
2
+ import { tmpdir } from 'os';
3
+ import { join, dirname } from 'path';
4
+
5
+ // src/testing.ts
6
+ var EMBED_DIM = 64;
7
+ var DeterministicEmbedder = class {
8
+ dimensions = EMBED_DIM;
9
+ /** Number of texts embedded — lets tests assert delta re-indexing skips work. */
10
+ embedCount = 0;
11
+ async embed(text) {
12
+ this.embedCount += 1;
13
+ const vec = new Array(EMBED_DIM).fill(0);
14
+ for (const token of text.toLowerCase().split(/[^a-z0-9]+/).filter(Boolean)) {
15
+ let h = 0;
16
+ for (let i = 0; i < token.length; i++) {
17
+ h = h * 31 + token.charCodeAt(i) >>> 0;
18
+ }
19
+ const idx = h % EMBED_DIM;
20
+ vec[idx] = (vec[idx] ?? 0) + 1;
21
+ }
22
+ return vec;
23
+ }
24
+ async embedBatch(texts) {
25
+ return Promise.all(texts.map((t) => this.embed(t)));
26
+ }
27
+ async getDimensions() {
28
+ return EMBED_DIM;
29
+ }
30
+ };
31
+ function cosine(a, b) {
32
+ let dot = 0;
33
+ let na = 0;
34
+ let nb = 0;
35
+ for (let i = 0; i < a.length; i++) {
36
+ const x = a[i] ?? 0;
37
+ const y = b[i] ?? 0;
38
+ dot += x * y;
39
+ na += x * x;
40
+ nb += y * y;
41
+ }
42
+ const d = Math.sqrt(na) * Math.sqrt(nb);
43
+ return d === 0 ? 0 : dot / d;
44
+ }
45
+ var TestVectorStore = class {
46
+ ns = /* @__PURE__ */ new Map();
47
+ part(namespace) {
48
+ const key = namespace ?? "";
49
+ let p = this.ns.get(key);
50
+ if (!p) {
51
+ p = /* @__PURE__ */ new Map();
52
+ this.ns.set(key, p);
53
+ }
54
+ return p;
55
+ }
56
+ async search(query, limit, _filter, namespace) {
57
+ return [...this.part(namespace).values()].map((r) => ({ id: r.id, score: cosine(query, r.vector), metadata: r.metadata })).sort((a, b) => b.score - a.score).slice(0, limit);
58
+ }
59
+ async upsert(vectors, namespace) {
60
+ const p = this.part(namespace);
61
+ for (const v of vectors) {
62
+ p.set(v.id, v);
63
+ }
64
+ }
65
+ async delete(ids, namespace) {
66
+ const p = this.part(namespace);
67
+ for (const id of ids) {
68
+ p.delete(id);
69
+ }
70
+ }
71
+ async count(namespace) {
72
+ return this.part(namespace).size;
73
+ }
74
+ async query(_filter, namespace) {
75
+ return [...this.part(namespace).values()];
76
+ }
77
+ };
78
+ var TestStorage = class {
79
+ files = /* @__PURE__ */ new Map();
80
+ seed(path, content) {
81
+ this.files.set(path, Buffer.from(content, "utf8"));
82
+ }
83
+ async read(path) {
84
+ return this.files.get(path) ?? null;
85
+ }
86
+ async write(path, data) {
87
+ this.files.set(path, data);
88
+ }
89
+ async delete(path) {
90
+ this.files.delete(path);
91
+ }
92
+ async list(prefix) {
93
+ return [...this.files.keys()].filter((p) => p.startsWith(prefix));
94
+ }
95
+ async exists(path) {
96
+ return this.files.has(path);
97
+ }
98
+ };
99
+ var noopLogger = {
100
+ debug() {
101
+ },
102
+ info() {
103
+ },
104
+ warn() {
105
+ },
106
+ error() {
107
+ },
108
+ fatal() {
109
+ },
110
+ trace() {
111
+ },
112
+ child() {
113
+ return noopLogger;
114
+ }
115
+ };
116
+ var stubCache = {
117
+ async get() {
118
+ return null;
119
+ },
120
+ async set() {
121
+ },
122
+ async delete() {
123
+ },
124
+ async clear() {
125
+ },
126
+ async zadd() {
127
+ },
128
+ async zrangebyscore() {
129
+ return [];
130
+ }
131
+ };
132
+ var stubLLM = {
133
+ async complete() {
134
+ return { content: "", usage: { promptTokens: 0, completionTokens: 0 } };
135
+ }
136
+ };
137
+ function makeScriptedLLM(content) {
138
+ return {
139
+ async complete() {
140
+ return { content, usage: { promptTokens: 0, completionTokens: 0 } };
141
+ }
142
+ };
143
+ }
144
+ function makeTestServices(overrides = {}) {
145
+ const storage = new TestStorage();
146
+ const vectorStore = new TestVectorStore();
147
+ return {
148
+ storage,
149
+ vectorStore,
150
+ embeddings: new DeterministicEmbedder(),
151
+ cache: stubCache,
152
+ llm: stubLLM,
153
+ logger: noopLogger,
154
+ ...overrides
155
+ };
156
+ }
157
+ function makeTestWorkspace(files, overrides = {}) {
158
+ const cwd = mkdtempSync(join(tmpdir(), "mind-test-"));
159
+ for (const [rel, content] of Object.entries(files)) {
160
+ const abs = join(cwd, rel);
161
+ mkdirSync(dirname(abs), { recursive: true });
162
+ writeFileSync(abs, content, "utf8");
163
+ }
164
+ return { cwd, services: makeTestServices(overrides) };
165
+ }
166
+
167
+ export { DeterministicEmbedder, TestStorage, TestVectorStore, makeScriptedLLM, makeTestServices, makeTestWorkspace };
168
+ //# sourceMappingURL=testing.js.map
169
+ //# sourceMappingURL=testing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/testing.ts"],"names":[],"mappings":"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","file":"testing.js","sourcesContent":["/**\n * Functional in-memory test harness for the engine.\n *\n * `@kb-labs/sdk/testing`'s `createTestContext` returns *mock* platform services\n * (empty/noop) — fine for handler wiring, useless for exercising retrieval.\n * This harness provides REAL behaviour: a deterministic bag-of-words embedder\n * and working in-memory vector store / storage, so ingest+retrieve and\n * namespace isolation can be tested end-to-end without a daemon or network.\n *\n * Imports only types from `@kb-labs/sdk`; the implementations are local.\n */\n\nimport { mkdtempSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { join, dirname } from 'node:path';\nimport type {\n MindServices,\n IVectorStore,\n IEmbeddings,\n IStorage,\n ICache,\n ILLM,\n ILogger,\n VectorRecord,\n VectorSearchResult,\n VectorFilter,\n} from './services';\n\nconst EMBED_DIM = 64;\n\n/** Deterministic bag-of-words embedder: shared tokens → higher cosine similarity. */\nexport class DeterministicEmbedder implements IEmbeddings {\n readonly dimensions = EMBED_DIM;\n /** Number of texts embedded — lets tests assert delta re-indexing skips work. */\n embedCount = 0;\n\n async embed(text: string): Promise<number[]> {\n this.embedCount += 1;\n const vec = new Array<number>(EMBED_DIM).fill(0);\n for (const token of text.toLowerCase().split(/[^a-z0-9]+/).filter(Boolean)) {\n let h = 0;\n for (let i = 0; i < token.length; i++) {\n h = (h * 31 + token.charCodeAt(i)) >>> 0;\n }\n const idx = h % EMBED_DIM;\n vec[idx] = (vec[idx] ?? 0) + 1;\n }\n return vec;\n }\n\n async embedBatch(texts: string[]): Promise<number[][]> {\n return Promise.all(texts.map((t) => this.embed(t)));\n }\n\n async getDimensions(): Promise<number> {\n return EMBED_DIM;\n }\n}\n\nfunction cosine(a: number[], b: number[]): number {\n let dot = 0;\n let na = 0;\n let nb = 0;\n for (let i = 0; i < a.length; i++) {\n const x = a[i] ?? 0;\n const y = b[i] ?? 0;\n dot += x * y;\n na += x * x;\n nb += y * y;\n }\n const d = Math.sqrt(na) * Math.sqrt(nb);\n return d === 0 ? 0 : dot / d;\n}\n\n/** Minimal namespace-partitioned in-memory vector store (mirrors platform semantics). */\nexport class TestVectorStore implements IVectorStore {\n private ns = new Map<string, Map<string, VectorRecord>>();\n\n private part(namespace?: string): Map<string, VectorRecord> {\n const key = namespace ?? '';\n let p = this.ns.get(key);\n if (!p) {\n p = new Map();\n this.ns.set(key, p);\n }\n return p;\n }\n\n async search(query: number[], limit: number, _filter?: VectorFilter, namespace?: string): Promise<VectorSearchResult[]> {\n return [...this.part(namespace).values()]\n .map((r) => ({ id: r.id, score: cosine(query, r.vector), metadata: r.metadata }))\n .sort((a, b) => b.score - a.score)\n .slice(0, limit);\n }\n\n async upsert(vectors: VectorRecord[], namespace?: string): Promise<void> {\n const p = this.part(namespace);\n for (const v of vectors) {\n p.set(v.id, v);\n }\n }\n\n async delete(ids: string[], namespace?: string): Promise<void> {\n const p = this.part(namespace);\n for (const id of ids) {\n p.delete(id);\n }\n }\n\n async count(namespace?: string): Promise<number> {\n return this.part(namespace).size;\n }\n\n async query(_filter: VectorFilter, namespace?: string): Promise<VectorRecord[]> {\n return [...this.part(namespace).values()];\n }\n}\n\n/** Minimal in-memory storage with prefix listing. */\nexport class TestStorage implements IStorage {\n private files = new Map<string, Buffer>();\n\n seed(path: string, content: string): void {\n this.files.set(path, Buffer.from(content, 'utf8'));\n }\n\n async read(path: string): Promise<Buffer | null> {\n return this.files.get(path) ?? null;\n }\n\n async write(path: string, data: Buffer): Promise<void> {\n this.files.set(path, data);\n }\n\n async delete(path: string): Promise<void> {\n this.files.delete(path);\n }\n\n async list(prefix: string): Promise<string[]> {\n return [...this.files.keys()].filter((p) => p.startsWith(prefix));\n }\n\n async exists(path: string): Promise<boolean> {\n return this.files.has(path);\n }\n}\n\nconst noopLogger = {\n debug() {},\n info() {},\n warn() {},\n error() {},\n fatal() {},\n trace() {},\n child() {\n return noopLogger;\n },\n} as unknown as ILogger;\n\nconst stubCache: ICache = {\n async get() {\n return null;\n },\n async set() {},\n async delete() {},\n async clear() {},\n async zadd() {},\n async zrangebyscore() {\n return [];\n },\n} as unknown as ICache;\n\nconst stubLLM: ILLM = {\n async complete() {\n return { content: '', usage: { promptTokens: 0, completionTokens: 0 } };\n },\n} as unknown as ILLM;\n\n/** Scripted LLM that returns a fixed completion — for testing agent synthesis. */\nexport function makeScriptedLLM(content: string): ILLM {\n return {\n async complete() {\n return { content, usage: { promptTokens: 0, completionTokens: 0 } };\n },\n } as unknown as ILLM;\n}\n\nexport interface TestServices extends MindServices {\n storage: TestStorage;\n vectorStore: TestVectorStore;\n}\n\n/** Build functional in-memory `MindServices` for engine tests. */\nexport function makeTestServices(overrides: Partial<MindServices> = {}): TestServices {\n const storage = new TestStorage();\n const vectorStore = new TestVectorStore();\n return {\n storage,\n vectorStore,\n embeddings: new DeterministicEmbedder(),\n cache: stubCache,\n llm: stubLLM,\n logger: noopLogger,\n ...overrides,\n } as TestServices;\n}\n\nexport interface TestWorkspace {\n /** Workspace root (a real temp dir) — pass as `createMind(..., { cwd })`. */\n cwd: string;\n /** In-memory services (vector store + manifest storage). */\n services: TestServices;\n}\n\n/**\n * Materialize source files on disk (a temp dir) so the engine exercises its\n * REAL discovery (globby + fs + ignores) instead of in-memory seeding — this is\n * what catches discovery bugs (e.g. node_modules recursion). The vector store\n * and manifest stay in-memory via `makeTestServices`.\n */\nexport function makeTestWorkspace(\n files: Record<string, string>,\n overrides: Partial<MindServices> = {},\n): TestWorkspace {\n const cwd = mkdtempSync(join(tmpdir(), 'mind-test-'));\n for (const [rel, content] of Object.entries(files)) {\n const abs = join(cwd, rel);\n mkdirSync(dirname(abs), { recursive: true });\n writeFileSync(abs, content, 'utf8');\n }\n return { cwd, services: makeTestServices(overrides) };\n}\n"]}
package/package.json CHANGED
@@ -1,15 +1,18 @@
1
1
  {
2
2
  "name": "@kb-labs/mind-core",
3
- "description": "Core contracts, errors, and utilities for KB Labs Mind",
4
- "version": "2.94.0",
3
+ "description": "Core RAG engine for KB Labs Mind: ingest, retrieval, answer. Dry business logic over platform adapters.",
4
+ "version": "2.96.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
8
8
  "exports": {
9
9
  ".": {
10
10
  "types": "./dist/index.d.ts",
11
- "import": "./dist/index.js",
12
- "require": "./dist/index.js"
11
+ "import": "./dist/index.js"
12
+ },
13
+ "./testing": {
14
+ "types": "./dist/testing.d.ts",
15
+ "import": "./dist/testing.js"
13
16
  },
14
17
  "./dist/*": "./dist/*"
15
18
  },
@@ -19,16 +22,17 @@
19
22
  "LICENSE"
20
23
  ],
21
24
  "dependencies": {
25
+ "globby": "^11.0.0",
22
26
  "@kb-labs/sdk": "2.21.2",
23
- "@kb-labs/mind-types": "2.94.0"
27
+ "@kb-labs/mind-contracts": "2.96.0"
24
28
  },
25
29
  "devDependencies": {
26
30
  "@types/node": "^24.3.3",
27
31
  "rimraf": "^6.0.1",
28
32
  "tsup": "^8.5.0",
29
33
  "typescript": "^5.6.3",
30
- "vitest": "^3.2.4",
31
- "@kb-labs/devkit": "2.94.0"
34
+ "vitest": "^3.2.6",
35
+ "@kb-labs/devkit": "2.96.0"
32
36
  },
33
37
  "engines": {
34
38
  "node": ">=20.0.0",
@@ -39,8 +43,9 @@
39
43
  "build": "tsup --config tsup.config.ts",
40
44
  "clean": "rimraf dist",
41
45
  "dev": "tsup --config tsup.config.ts --watch",
42
- "lint": "eslint src --ext .ts,.tsx,.js,.jsx",
46
+ "lint": "eslint src --ext .ts",
43
47
  "lint:fix": "eslint . --fix",
48
+ "pretype-check": "pnpm --filter @kb-labs/mind-core build",
44
49
  "test": "vitest run --passWithNoTests",
45
50
  "test:watch": "vitest",
46
51
  "type-check": "tsc --noEmit"