@pattern-js/mod-vectors 0.4.0-main.c8eb671

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.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +21 -0
  3. package/dist/admin.d.ts +20 -0
  4. package/dist/admin.d.ts.map +1 -0
  5. package/dist/admin.js +249 -0
  6. package/dist/admin.js.map +1 -0
  7. package/dist/chunk.d.ts +28 -0
  8. package/dist/chunk.d.ts.map +1 -0
  9. package/dist/chunk.js +74 -0
  10. package/dist/chunk.js.map +1 -0
  11. package/dist/engine-local.d.ts +62 -0
  12. package/dist/engine-local.d.ts.map +1 -0
  13. package/dist/engine-local.js +418 -0
  14. package/dist/engine-local.js.map +1 -0
  15. package/dist/index.d.ts +9 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +9 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/mod.d.ts +21 -0
  20. package/dist/mod.d.ts.map +1 -0
  21. package/dist/mod.js +49 -0
  22. package/dist/mod.js.map +1 -0
  23. package/dist/ops.d.ts +12 -0
  24. package/dist/ops.d.ts.map +1 -0
  25. package/dist/ops.js +138 -0
  26. package/dist/ops.js.map +1 -0
  27. package/dist/service.d.ts +72 -0
  28. package/dist/service.d.ts.map +1 -0
  29. package/dist/service.js +166 -0
  30. package/dist/service.js.map +1 -0
  31. package/dist/types.d.ts +104 -0
  32. package/dist/types.d.ts.map +1 -0
  33. package/dist/types.js +33 -0
  34. package/dist/types.js.map +1 -0
  35. package/docs/index.md +94 -0
  36. package/docs/ops/vectors.chunk.md +8 -0
  37. package/docs/ops/vectors.collection.ensure.md +7 -0
  38. package/docs/ops/vectors.collections.ingest.md +10 -0
  39. package/docs/ops/vectors.collections.list.md +3 -0
  40. package/docs/ops/vectors.collections.search.md +7 -0
  41. package/docs/ops/vectors.delete.md +5 -0
  42. package/docs/ops/vectors.index.md +7 -0
  43. package/docs/ops/vectors.query.md +13 -0
  44. package/docs/ops/vectors.upsert.md +8 -0
  45. package/package.json +53 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Makkr Studio
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # @pattern-js/mod-vectors
2
+
3
+ Vector search for [Pattern](https://github.com/makkr-studio/pattern):
4
+ embedding collections that **declare their embedding alias** (so
5
+ index-with-one-model-query-with-another is unrepresentable), filterable
6
+ metadata pruned before scoring, hybrid vector+keyword retrieval with RRF
7
+ fusion, a no-tokenizer text chunker, and a zero-dependency sqlite-backed
8
+ local engine — durable and offload-safe — with a driver SPI for sqlite-vec
9
+ and pgvector later.
10
+
11
+ ```jsonc
12
+ // pattern.config.json
13
+ { "mods": ["@pattern-js/mod-ai", "@pattern-js/mod-vectors"] }
14
+ ```
15
+
16
+ Ops: `vectors.collection.ensure`, `vectors.index` (chunk→embed→upsert),
17
+ `vectors.chunk`, `vectors.upsert`, `vectors.query` (vector | keyword |
18
+ hybrid, `filter: { field: value }`), `vectors.delete`.
19
+
20
+ Full chapter: your app's `/docs` → **Vectors** (or
21
+ [the handbook source](./docs/index.md)).
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @pattern-js/mod-vectors — the admin surface (Tier-1 declarative, zero build).
3
+ *
4
+ * One Vectors page under Data, three sections: the collections table (what is
5
+ * indexed, through which model), **Ingest text** (paste → chunk → embed —
6
+ * feeding a knowledge base is a form, not a curl), and **Search** (try a
7
+ * hybrid query, see scored matches). Together they are the whole RAG loop
8
+ * without leaving the admin. Each section is backed by its own dedicated
9
+ * admin-scoped route.
10
+ */
11
+ import { type FrontendContribution, type OpDefinition, type Workflow } from "@pattern-js/core";
12
+ /** Backing op for the collections table (privileged; the route carries the admin gate). */
13
+ export declare const collectionsListOp: OpDefinition;
14
+ /** Paste-to-RAG (admin): chunk a text and index it, creating the collection when new. */
15
+ export declare const collectionsIngestOp: OpDefinition;
16
+ /** Try a query (admin): hybrid by default, scored matches back — the smoke test for what got indexed. */
17
+ export declare const collectionsSearchOp: OpDefinition;
18
+ export declare function vectorsAdminRoutes(): Workflow[];
19
+ export declare function vectorsFrontend(): FrontendContribution;
20
+ //# sourceMappingURL=admin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../src/admin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAoC,KAAK,oBAAoB,EAAkB,KAAK,YAAY,EAAE,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAsCjJ,2FAA2F;AAC3F,eAAO,MAAM,iBAAiB,EAAE,YAuB/B,CAAC;AAEF,yFAAyF;AACzF,eAAO,MAAM,mBAAmB,EAAE,YAsCjC,CAAC;AAEF,yGAAyG;AACzG,eAAO,MAAM,mBAAmB,EAAE,YAmCjC,CAAC;AAEF,wBAAgB,kBAAkB,IAAI,QAAQ,EAAE,CA8B/C;AAED,wBAAgB,eAAe,IAAI,oBAAoB,CA8DtD"}
package/dist/admin.js ADDED
@@ -0,0 +1,249 @@
1
+ /**
2
+ * @pattern-js/mod-vectors — the admin surface (Tier-1 declarative, zero build).
3
+ *
4
+ * One Vectors page under Data, three sections: the collections table (what is
5
+ * indexed, through which model), **Ingest text** (paste → chunk → embed —
6
+ * feeding a knowledge base is a form, not a curl), and **Search** (try a
7
+ * hybrid query, see scored matches). Together they are the whole RAG loop
8
+ * without leaving the admin. Each section is backed by its own dedicated
9
+ * admin-scoped route.
10
+ */
11
+ import { httpEndpoint, fromBody, value, z } from "@pattern-js/core";
12
+ import { chunkDoc } from "./chunk.js";
13
+ import { VECTORS_SERVICE } from "./service.js";
14
+ import { collectionSpecSchema } from "./types.js";
15
+ const PATH = "/vectors/api/collections";
16
+ const INGEST_PATH = "/vectors/api/ingest";
17
+ const SEARCH_PATH = "/vectors/api/search";
18
+ const API = "/admin/api";
19
+ function requireService(ctx) {
20
+ const svc = ctx.services[VECTORS_SERVICE];
21
+ if (!svc)
22
+ throw new Error("vectors: service not available — is @pattern-js/mod-vectors listed in pattern.config.json mods?");
23
+ return svc;
24
+ }
25
+ /** Stable content hash (djb2) — re-pasting the same text re-uses the doc id, so dedupe holds. */
26
+ function stableHash(s) {
27
+ let h = 5381;
28
+ for (let i = 0; i < s.length; i++)
29
+ h = ((h << 5) + h + s.charCodeAt(i)) >>> 0;
30
+ return h.toString(36);
31
+ }
32
+ /** The form's meta field is a JSON string (or empty); a workflow may pass an object. */
33
+ function parseMeta(raw) {
34
+ if (raw == null)
35
+ return undefined;
36
+ if (typeof raw === "object")
37
+ return raw;
38
+ const s = String(raw).trim();
39
+ if (!s)
40
+ return undefined;
41
+ try {
42
+ const parsed = JSON.parse(s);
43
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed))
44
+ return parsed;
45
+ }
46
+ catch {
47
+ /* fall through to the located error */
48
+ }
49
+ throw new Error(`meta must be a JSON object, e.g. {"topic":"billing"} — got: ${s.slice(0, 60)}`);
50
+ }
51
+ /** Backing op for the collections table (privileged; the route carries the admin gate). */
52
+ export const collectionsListOp = {
53
+ type: "vectors.collections.list",
54
+ title: "vectors.collections.list",
55
+ description: "List vector collections with alias, dims, filterables, row count and the active engine (admin).",
56
+ reusable: false,
57
+ sensitivity: "privileged",
58
+ inputs: {},
59
+ outputs: { collections: value() },
60
+ execute: async (ctx) => {
61
+ const svc = ctx.services[VECTORS_SERVICE];
62
+ if (!svc)
63
+ return { collections: [] };
64
+ const collections = await svc.listCollections();
65
+ return {
66
+ collections: collections.map((c) => ({
67
+ name: c.name,
68
+ alias: c.alias,
69
+ dims: c.dims ?? "(locks on first write)",
70
+ filterables: c.filterables.join(", ") || "—",
71
+ rows: c.rows,
72
+ engine: svc.engineId(),
73
+ })),
74
+ };
75
+ },
76
+ };
77
+ /** Paste-to-RAG (admin): chunk a text and index it, creating the collection when new. */
78
+ export const collectionsIngestOp = {
79
+ type: "vectors.collections.ingest",
80
+ title: "vectors.collections.ingest",
81
+ description: "Ingest pasted text into a collection (admin): chunk → embed → upsert, creating the collection (with the " +
82
+ "given embedding alias) when it doesn't exist yet. Re-pasting the same text re-uses its content-derived doc id, " +
83
+ "so unchanged chunks are skipped. Args { collection, text, alias?, docId?, meta? (JSON object) }.",
84
+ reusable: false,
85
+ sensitivity: "privileged",
86
+ inputs: {
87
+ collection: value(z.string()),
88
+ text: value(z.string()),
89
+ alias: value(z.string().optional()),
90
+ docId: value(z.string().optional()),
91
+ meta: value(z.unknown().optional()),
92
+ },
93
+ outputs: { result: value() },
94
+ execute: async (ctx) => {
95
+ const svc = requireService(ctx);
96
+ const collection = String((await ctx.input.value("collection")) ?? "").trim();
97
+ const text = String((await ctx.input.value("text")) ?? "");
98
+ if (!collection)
99
+ throw new Error("collection is required");
100
+ if (!text.trim())
101
+ throw new Error("nothing to ingest — paste some text");
102
+ const alias = ctx.input.has("alias") ? String((await ctx.input.value("alias")) ?? "").trim() : "";
103
+ const docIdIn = ctx.input.has("docId") ? String((await ctx.input.value("docId")) ?? "").trim() : "";
104
+ const meta = parseMeta(ctx.input.has("meta") ? await ctx.input.value("meta") : undefined);
105
+ // Only a NEW collection takes the alias — an existing one already declared
106
+ // its embedding model, and silently re-pointing it would corrupt the space.
107
+ const exists = (await svc.listCollections()).some((c) => c.name === collection);
108
+ // Through the schema, so metric/filterables defaults apply like the canvas op's config does.
109
+ if (!exists)
110
+ await svc.ensureCollection(collectionSpecSchema.parse({ name: collection, alias: alias || "embeddings" }));
111
+ const docId = docIdIn || `paste-${stableHash(text)}`;
112
+ const chunks = chunkDoc({ id: docId, text, meta }, { maxChars: 1200, overlap: 150, separators: ["\n\n", "\n", ". "] });
113
+ const res = await svc.upsert(collection, chunks.map((c) => ({ id: c.id, text: c.text, meta: c.meta })), ctx);
114
+ return { result: { ok: true, collection, docId, chunks: chunks.length, indexed: res.count, embedded: res.embedded } };
115
+ },
116
+ };
117
+ /** Try a query (admin): hybrid by default, scored matches back — the smoke test for what got indexed. */
118
+ export const collectionsSearchOp = {
119
+ type: "vectors.collections.search",
120
+ title: "vectors.collections.search",
121
+ description: "Search a collection from the admin (hybrid by default): top-k scored matches with their text and meta — " +
122
+ "the quickest way to verify what an ingest actually indexed. Args { collection, query, k?, mode? (vector/keyword/hybrid) }.",
123
+ reusable: false,
124
+ sensitivity: "privileged",
125
+ inputs: {
126
+ collection: value(z.string()),
127
+ query: value(z.string()),
128
+ k: value(z.union([z.string(), z.number()]).optional()),
129
+ mode: value(z.string().optional()),
130
+ },
131
+ outputs: { matches: value() },
132
+ execute: async (ctx) => {
133
+ const svc = requireService(ctx);
134
+ const collection = String((await ctx.input.value("collection")) ?? "").trim();
135
+ const query = String((await ctx.input.value("query")) ?? "");
136
+ if (!collection || !query.trim())
137
+ throw new Error("collection and query are required");
138
+ const kRaw = ctx.input.has("k") ? String((await ctx.input.value("k")) ?? "").trim() : "";
139
+ const k = kRaw ? Number(kRaw) : 5;
140
+ if (!Number.isFinite(k) || k <= 0)
141
+ throw new Error("k must be a positive number");
142
+ const modeRaw = ctx.input.has("mode") ? String((await ctx.input.value("mode")) ?? "").trim() : "";
143
+ const mode = (modeRaw || "hybrid");
144
+ const matches = await svc.query(collection, { text: query, k, mode }, ctx);
145
+ return {
146
+ matches: matches.map((m) => ({
147
+ score: Number(m.score.toFixed(4)),
148
+ id: m.id,
149
+ text: (m.text ?? "").length > 200 ? `${(m.text ?? "").slice(0, 200)}…` : (m.text ?? ""),
150
+ meta: m.meta ?? {},
151
+ })),
152
+ };
153
+ },
154
+ };
155
+ export function vectorsAdminRoutes() {
156
+ return [
157
+ httpEndpoint({
158
+ id: "vectors.route.admin.collections",
159
+ name: `Vectors · GET ${API}${PATH}`,
160
+ method: "GET",
161
+ path: `${API}${PATH}`,
162
+ op: "vectors.collections.list",
163
+ io: { out: "collections" },
164
+ auth: { scopes: ["admin"] },
165
+ }),
166
+ httpEndpoint({
167
+ id: "vectors.route.admin.ingest",
168
+ name: `Vectors · POST ${API}${INGEST_PATH}`,
169
+ method: "POST",
170
+ path: `${API}${INGEST_PATH}`,
171
+ op: "vectors.collections.ingest",
172
+ io: { in: { collection: fromBody(), text: fromBody(), alias: fromBody(), docId: fromBody(), meta: fromBody() }, out: "result" },
173
+ auth: { scopes: ["admin"] },
174
+ }),
175
+ httpEndpoint({
176
+ id: "vectors.route.admin.search",
177
+ name: `Vectors · POST ${API}${SEARCH_PATH}`,
178
+ method: "POST",
179
+ path: `${API}${SEARCH_PATH}`,
180
+ op: "vectors.collections.search",
181
+ io: { in: { collection: fromBody(), query: fromBody(), k: fromBody(), mode: fromBody() }, out: "matches" },
182
+ auth: { scopes: ["admin"] },
183
+ }),
184
+ ];
185
+ }
186
+ export function vectorsFrontend() {
187
+ return {
188
+ menu: [{ category: "Data", label: "Vectors", icon: "network", path: "/x/vectors/collections", order: 30 }],
189
+ pages: [
190
+ {
191
+ // The whole RAG loop on one page: what's indexed, paste to ingest, search to verify.
192
+ path: "/x/vectors/collections",
193
+ views: [
194
+ {
195
+ title: "Collections",
196
+ view: {
197
+ kind: "table",
198
+ route: { method: "GET", path: PATH },
199
+ columns: [
200
+ { key: "name", label: "Collection" },
201
+ { key: "alias", label: "Embedding alias" },
202
+ { key: "dims", label: "Dims" },
203
+ { key: "filterables", label: "Filterables" },
204
+ { key: "rows", label: "Rows" },
205
+ { key: "engine", label: "Engine" },
206
+ ],
207
+ },
208
+ },
209
+ {
210
+ title: "Ingest text",
211
+ view: {
212
+ kind: "form",
213
+ schema: {
214
+ type: "object",
215
+ properties: {
216
+ collection: { type: "string", default: "kb", description: "Target collection (created if new)" },
217
+ text: { type: "string", format: "multiline", description: "Paste anything — it's chunked, embedded and indexed" },
218
+ alias: { type: "string", default: "embeddings", description: "Embedding alias for a NEW collection (Settings → AI Providers)" },
219
+ docId: { type: "string", description: "Stable id for re-ingesting updates (empty = derived from the text)" },
220
+ meta: { type: "string", description: 'JSON object stamped on every chunk, e.g. {"topic":"billing"} — filterable if declared' },
221
+ },
222
+ required: ["collection", "text"],
223
+ },
224
+ route: { method: "POST", path: INGEST_PATH },
225
+ },
226
+ },
227
+ {
228
+ title: "Search",
229
+ view: {
230
+ kind: "form",
231
+ schema: {
232
+ type: "object",
233
+ properties: {
234
+ collection: { type: "string", default: "kb", description: "Collection to search" },
235
+ query: { type: "string", description: "What are you looking for?" },
236
+ k: { type: "string", default: "5", description: "How many matches" },
237
+ mode: { type: "string", enum: ["hybrid", "vector", "keyword"], description: "hybrid = vector + keyword, RRF-fused" },
238
+ },
239
+ required: ["collection", "query"],
240
+ },
241
+ route: { method: "POST", path: SEARCH_PATH },
242
+ },
243
+ },
244
+ ],
245
+ },
246
+ ],
247
+ };
248
+ }
249
+ //# sourceMappingURL=admin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.js","sourceRoot":"","sources":["../src/admin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAA+E,MAAM,kBAAkB,CAAC;AACjJ,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,eAAe,EAAuB,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAkB,MAAM,YAAY,CAAC;AAElE,MAAM,IAAI,GAAG,0BAA0B,CAAC;AACxC,MAAM,WAAW,GAAG,qBAAqB,CAAC;AAC1C,MAAM,WAAW,GAAG,qBAAqB,CAAC;AAC1C,MAAM,GAAG,GAAG,YAAY,CAAC;AAEzB,SAAS,cAAc,CAAC,GAAc;IACpC,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,eAAe,CAA+B,CAAC;IACxE,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,iGAAiG,CAAC,CAAC;IAC7H,OAAO,GAAG,CAAC;AACb,CAAC;AAED,iGAAiG;AACjG,SAAS,UAAU,CAAC,CAAS;IAC3B,IAAI,CAAC,GAAG,IAAI,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC9E,OAAO,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACxB,CAAC;AAED,wFAAwF;AACxF,SAAS,SAAS,CAAC,GAAY;IAC7B,IAAI,GAAG,IAAI,IAAI;QAAE,OAAO,SAAS,CAAC;IAClC,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAA8B,CAAC;IACnE,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACzB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAY,CAAC;QACxC,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,MAAiC,CAAC;IAC/G,CAAC;IAAC,MAAM,CAAC;QACP,uCAAuC;IACzC,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;AACnG,CAAC;AAED,2FAA2F;AAC3F,MAAM,CAAC,MAAM,iBAAiB,GAAiB;IAC7C,IAAI,EAAE,0BAA0B;IAChC,KAAK,EAAE,0BAA0B;IACjC,WAAW,EAAE,iGAAiG;IAC9G,QAAQ,EAAE,KAAK;IACf,WAAW,EAAE,YAAY;IACzB,MAAM,EAAE,EAAE;IACV,OAAO,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE;IACjC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACrB,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,eAAe,CAA+B,CAAC;QACxE,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;QACrC,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,eAAe,EAAE,CAAC;QAChD,OAAO;YACL,WAAW,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACnC,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,wBAAwB;gBACxC,WAAW,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG;gBAC5C,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,MAAM,EAAE,GAAG,CAAC,QAAQ,EAAE;aACvB,CAAC,CAAC;SACJ,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,yFAAyF;AACzF,MAAM,CAAC,MAAM,mBAAmB,GAAiB;IAC/C,IAAI,EAAE,4BAA4B;IAClC,KAAK,EAAE,4BAA4B;IACnC,WAAW,EACT,0GAA0G;QAC1G,iHAAiH;QACjH,kGAAkG;IACpG,QAAQ,EAAE,KAAK;IACf,WAAW,EAAE,YAAY;IACzB,MAAM,EAAE;QACN,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAC7B,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QACvB,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC;QACnC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC;QACnC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC;KACpC;IACD,OAAO,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;IAC5B,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACrB,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QAChC,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9E,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3D,IAAI,CAAC,UAAU;YAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC3D,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACzE,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClG,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpG,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAE1F,2EAA2E;QAC3E,4EAA4E;QAC5E,MAAM,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;QAChF,6FAA6F;QAC7F,IAAI,CAAC,MAAM;YAAE,MAAM,GAAG,CAAC,gBAAgB,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,IAAI,YAAY,EAAE,CAAC,CAAC,CAAC;QAExH,MAAM,KAAK,GAAG,OAAO,IAAI,SAAS,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrD,MAAM,MAAM,GAAG,QAAQ,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QACvH,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC7G,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC;IACxH,CAAC;CACF,CAAC;AAEF,yGAAyG;AACzG,MAAM,CAAC,MAAM,mBAAmB,GAAiB;IAC/C,IAAI,EAAE,4BAA4B;IAClC,KAAK,EAAE,4BAA4B;IACnC,WAAW,EACT,0GAA0G;QAC1G,4HAA4H;IAC9H,QAAQ,EAAE,KAAK;IACf,WAAW,EAAE,YAAY;IACzB,MAAM,EAAE;QACN,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAC7B,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QACxB,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QACtD,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC;KACnC;IACD,OAAO,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;IAC7B,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACrB,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QAChC,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9E,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACvF,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzF,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAClF,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClG,MAAM,IAAI,GAAG,CAAC,OAAO,IAAI,QAAQ,CAAc,CAAC;QAChD,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;QAC3E,OAAO;YACL,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC3B,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBACjC,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;gBACvF,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE;aACnB,CAAC,CAAC;SACJ,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,MAAM,UAAU,kBAAkB;IAChC,OAAO;QACL,YAAY,CAAC;YACX,EAAE,EAAE,iCAAiC;YACrC,IAAI,EAAE,iBAAiB,GAAG,GAAG,IAAI,EAAE;YACnC,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,GAAG,GAAG,GAAG,IAAI,EAAE;YACrB,EAAE,EAAE,0BAA0B;YAC9B,EAAE,EAAE,EAAE,GAAG,EAAE,aAAa,EAAE;YAC1B,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE;SAC5B,CAAC;QACF,YAAY,CAAC;YACX,EAAE,EAAE,4BAA4B;YAChC,IAAI,EAAE,kBAAkB,GAAG,GAAG,WAAW,EAAE;YAC3C,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,GAAG,GAAG,GAAG,WAAW,EAAE;YAC5B,EAAE,EAAE,4BAA4B;YAChC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE;YAC/H,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE;SAC5B,CAAC;QACF,YAAY,CAAC;YACX,EAAE,EAAE,4BAA4B;YAChC,IAAI,EAAE,kBAAkB,GAAG,GAAG,WAAW,EAAE;YAC3C,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,GAAG,GAAG,GAAG,WAAW,EAAE;YAC5B,EAAE,EAAE,4BAA4B;YAChC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE;YAC1G,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE;SAC5B,CAAC;KACH,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO;QACL,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,wBAAwB,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QAC1G,KAAK,EAAE;YACL;gBACE,qFAAqF;gBACrF,IAAI,EAAE,wBAAwB;gBAC9B,KAAK,EAAE;oBACL;wBACE,KAAK,EAAE,aAAa;wBACpB,IAAI,EAAE;4BACJ,IAAI,EAAE,OAAO;4BACb,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE;4BACpC,OAAO,EAAE;gCACP,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE;gCACpC,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE;gCAC1C,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;gCAC9B,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,EAAE;gCAC5C,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;gCAC9B,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;6BACnC;yBACF;qBACF;oBACD;wBACE,KAAK,EAAE,aAAa;wBACpB,IAAI,EAAE;4BACJ,IAAI,EAAE,MAAM;4BACZ,MAAM,EAAE;gCACN,IAAI,EAAE,QAAQ;gCACd,UAAU,EAAE;oCACV,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,oCAAoC,EAAE;oCAChG,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,qDAAqD,EAAE;oCACjH,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,gEAAgE,EAAE;oCAC/H,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,oEAAoE,EAAE;oCAC5G,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uFAAuF,EAAE;iCAC/H;gCACD,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC;6BACjC;4BACD,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE;yBAC7C;qBACF;oBACD;wBACE,KAAK,EAAE,QAAQ;wBACf,IAAI,EAAE;4BACJ,IAAI,EAAE,MAAM;4BACZ,MAAM,EAAE;gCACN,IAAI,EAAE,QAAQ;gCACd,UAAU,EAAE;oCACV,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,sBAAsB,EAAE;oCAClF,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,2BAA2B,EAAE;oCACnE,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,kBAAkB,EAAE;oCACpE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,WAAW,EAAE,sCAAsC,EAAE;iCACrH;gCACD,QAAQ,EAAE,CAAC,YAAY,EAAE,OAAO,CAAC;6BAClC;4BACD,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE;yBAC7C;qBACF;iBACF;aACF;SACF;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @pattern-js/mod-vectors — the text chunker.
3
+ *
4
+ * A recursive character splitter (no tokenizer dependency): split on the
5
+ * coarsest separator that still yields pieces under `maxChars`, recurse into
6
+ * oversized pieces with the next separator, then re-join neighbors greedily
7
+ * and carry `overlap` characters of context across chunk boundaries.
8
+ */
9
+ export interface ChunkOptions {
10
+ maxChars?: number;
11
+ overlap?: number;
12
+ separators?: string[];
13
+ }
14
+ export interface Chunk {
15
+ /** `${docId}#${i}` when a doc id is known, else `#${i}`. */
16
+ id: string;
17
+ text: string;
18
+ meta?: Record<string, unknown>;
19
+ }
20
+ /** Greedily merge neighbor pieces up to maxChars, threading `overlap` chars across boundaries. */
21
+ export declare function chunkText(text: string, opts?: ChunkOptions): string[];
22
+ /** Chunk one document into id-stamped chunks carrying the doc's meta. */
23
+ export declare function chunkDoc(doc: {
24
+ id?: string;
25
+ text: string;
26
+ meta?: Record<string, unknown>;
27
+ }, opts?: ChunkOptions): Chunk[];
28
+ //# sourceMappingURL=chunk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk.d.ts","sourceRoot":"","sources":["../src/chunk.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,KAAK;IACpB,4DAA4D;IAC5D,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAyBD,kGAAkG;AAClG,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,YAAiB,GAAG,MAAM,EAAE,CA0BzE;AAED,yEAAyE;AACzE,wBAAgB,QAAQ,CACtB,GAAG,EAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,EAClE,IAAI,GAAE,YAAiB,GACtB,KAAK,EAAE,CAMT"}
package/dist/chunk.js ADDED
@@ -0,0 +1,74 @@
1
+ /**
2
+ * @pattern-js/mod-vectors — the text chunker.
3
+ *
4
+ * A recursive character splitter (no tokenizer dependency): split on the
5
+ * coarsest separator that still yields pieces under `maxChars`, recurse into
6
+ * oversized pieces with the next separator, then re-join neighbors greedily
7
+ * and carry `overlap` characters of context across chunk boundaries.
8
+ */
9
+ const DEFAULTS = { maxChars: 1200, overlap: 150, separators: ["\n\n", "\n", ". "] };
10
+ /** Split `text` recursively so every piece fits in maxChars. */
11
+ function split(text, maxChars, separators) {
12
+ if (text.length <= maxChars)
13
+ return text.trim() ? [text] : [];
14
+ const [sep, ...rest] = separators;
15
+ if (!sep) {
16
+ // Out of separators — hard-cut (pathological input: one giant unbroken run).
17
+ const out = [];
18
+ for (let i = 0; i < text.length; i += maxChars)
19
+ out.push(text.slice(i, i + maxChars));
20
+ return out;
21
+ }
22
+ const parts = text.split(sep);
23
+ if (parts.length === 1)
24
+ return split(text, maxChars, rest);
25
+ const out = [];
26
+ for (const part of parts) {
27
+ const piece = part.trim() ? part + (sep === ". " ? "." : "") : "";
28
+ if (!piece)
29
+ continue;
30
+ out.push(...(piece.length > maxChars ? split(piece, maxChars, rest) : [piece]));
31
+ }
32
+ return out;
33
+ }
34
+ /** Greedily merge neighbor pieces up to maxChars, threading `overlap` chars across boundaries. */
35
+ export function chunkText(text, opts = {}) {
36
+ const { maxChars, overlap, separators } = { ...DEFAULTS, ...opts };
37
+ if (maxChars <= 0)
38
+ throw new Error("vectors.chunk: maxChars must be positive");
39
+ if (overlap >= maxChars)
40
+ throw new Error("vectors.chunk: overlap must be smaller than maxChars");
41
+ const pieces = split(text, maxChars, separators);
42
+ const chunks = [];
43
+ let current = "";
44
+ for (const piece of pieces) {
45
+ const candidate = current ? `${current}\n${piece}` : piece;
46
+ if (candidate.length <= maxChars) {
47
+ current = candidate;
48
+ continue;
49
+ }
50
+ if (current)
51
+ chunks.push(current);
52
+ // Overlap: seed the next chunk with the tail of the previous one.
53
+ const tail = overlap > 0 && current ? current.slice(-overlap) : "";
54
+ current = tail ? `${tail}\n${piece}` : piece;
55
+ // The seeded piece may itself overflow (tail + long piece) — flush the tail alone.
56
+ if (current.length > maxChars) {
57
+ if (tail)
58
+ chunks.push(tail);
59
+ current = piece;
60
+ }
61
+ }
62
+ if (current.trim())
63
+ chunks.push(current);
64
+ return chunks;
65
+ }
66
+ /** Chunk one document into id-stamped chunks carrying the doc's meta. */
67
+ export function chunkDoc(doc, opts = {}) {
68
+ return chunkText(doc.text, opts).map((text, i) => ({
69
+ id: `${doc.id ?? ""}#${i}`,
70
+ text,
71
+ ...(doc.meta ? { meta: doc.meta } : {}),
72
+ }));
73
+ }
74
+ //# sourceMappingURL=chunk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk.js","sourceRoot":"","sources":["../src/chunk.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * @pattern-js/mod-vectors — the default "local" engine.
3
+ *
4
+ * node:sqlite-backed (WAL + busy_timeout, the mod-store recipe): durable AND
5
+ * offload-safe — a worker's own service instance opens the SAME file, so
6
+ * offloaded workflows see every vector the host wrote. Vectors are Float32
7
+ * BLOBs, L2-normalized at write time so cosine similarity is a dot product;
8
+ * search is an honest brute-force scan with a top-k heap (fine to ~100k
9
+ * vectors — past that, register a real driver: the SPI carries filter+mode).
10
+ *
11
+ * Filterables prune BEFORE the scan through the indexed `vec_meta` side
12
+ * table. Keyword ranking uses FTS5 when this sqlite build has it (probed at
13
+ * open) and a zero-dep token-overlap scorer otherwise; hybrid fuses the two
14
+ * rankings with reciprocal-rank fusion (RRF, k=60) — no score calibration.
15
+ */
16
+ import type { CollectionInfo, CollectionSpec, EngineQuery, EngineRow, Filter, Match, VectorsEngine } from "./types.js";
17
+ /** L2-normalize into a fresh Float32Array (cosine ≡ dot afterwards). */
18
+ export declare function normalize(vector: number[] | Float32Array): Float32Array;
19
+ /** Reciprocal-rank fusion of one or more rankings (RRF, k=60). */
20
+ export declare function rrfFuse(rankings: string[][], k?: number): Map<string, number>;
21
+ export interface LocalEngineOptions {
22
+ /** ":memory:" works too (tests). */
23
+ path: string;
24
+ /** Test seam: pretend this sqlite build has no FTS5 (exercise the fallback scorer). */
25
+ disableFts?: boolean;
26
+ }
27
+ export declare class LocalVectorsEngine implements VectorsEngine {
28
+ readonly id = "local";
29
+ private readonly db;
30
+ /** Whether this sqlite build compiled FTS5 (probed at open). */
31
+ readonly hasFts: boolean;
32
+ constructor(opts: LocalEngineOptions);
33
+ private runMigrations;
34
+ ensureCollection(spec: CollectionSpec): Promise<void>;
35
+ getCollection(name: string): Promise<CollectionSpec | null>;
36
+ listCollections(): Promise<CollectionInfo[]>;
37
+ /** Lock dims on the collection's first vector write; mismatch names the alias. */
38
+ private lockDims;
39
+ hashes(collection: string, ids: string[]): Promise<Map<string, string>>;
40
+ upsert(collection: string, rows: EngineRow[]): Promise<void>;
41
+ delete(collection: string, ids: string[]): Promise<number>;
42
+ query(collection: string, q: EngineQuery): Promise<Match[]>;
43
+ list(collection: string, q: {
44
+ filter?: Filter;
45
+ limit?: number;
46
+ offset?: number;
47
+ }): Promise<Array<{
48
+ id: string;
49
+ text: string | null;
50
+ meta: Record<string, unknown> | null;
51
+ updatedAt: number;
52
+ }>>;
53
+ /** AND of equality/any-of via the side table: one indexed lookup per field, intersected. */
54
+ private filterIds;
55
+ /** Brute-force cosine over the (possibly pruned) rows with a bounded top-k. */
56
+ private vectorRank;
57
+ private keywordRank;
58
+ private loadRows;
59
+ private hydrate;
60
+ close(): Promise<void>;
61
+ }
62
+ //# sourceMappingURL=engine-local.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine-local.d.ts","sourceRoot":"","sources":["../src/engine-local.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,WAAW,EACX,SAAS,EACT,MAAM,EAEN,KAAK,EACL,aAAa,EACd,MAAM,YAAY,CAAC;AAgDpB,wEAAwE;AACxE,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,YAAY,GAAG,YAAY,CAOvE;AAcD,kEAAkE;AAClE,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,SAAK,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAQzE;AAED,MAAM,WAAW,kBAAkB;IACjC,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,uFAAuF;IACvF,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,qBAAa,kBAAmB,YAAW,aAAa;IACtD,QAAQ,CAAC,EAAE,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAc;IACjC,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;gBAEb,IAAI,EAAE,kBAAkB;IA2BpC,OAAO,CAAC,aAAa;IAmBf,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBrD,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAY3D,eAAe,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAelD,kFAAkF;IAClF,OAAO,CAAC,QAAQ;IAmBV,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAWvE,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAmC5D,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAoB1D,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAsB3D,IAAI,CACR,UAAU,EAAE,MAAM,EAClB,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GACtD,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IA2B/G,4FAA4F;IAC5F,OAAO,CAAC,SAAS;IAoBjB,+EAA+E;IAC/E,OAAO,CAAC,UAAU;IAuBlB,OAAO,CAAC,WAAW;IA6BnB,OAAO,CAAC,QAAQ;IAyBhB,OAAO,CAAC,OAAO;IAUT,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}