@aexol/spectral 0.9.200 → 0.9.202
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/extensions/image-generation/index.d.ts.map +1 -1
- package/dist/extensions/image-generation/index.js +81 -11
- package/dist/memory/tools/read-project-observations.d.ts.map +1 -1
- package/dist/memory/tools/read-project-observations.js +8 -4
- package/dist/memory/tools/write-project-observation.d.ts.map +1 -1
- package/dist/memory/tools/write-project-observation.js +5 -1
- package/dist/server/storage.d.ts +59 -2
- package/dist/server/storage.d.ts.map +1 -1
- package/dist/server/storage.js +287 -12
- package/dist/server/text/trigrams.d.ts +72 -0
- package/dist/server/text/trigrams.d.ts.map +1 -0
- package/dist/server/text/trigrams.js +128 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/extensions/image-generation/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAmB,YAAY,EAAkB,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/extensions/image-generation/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAmB,YAAY,EAAkB,MAAM,iCAAiC,CAAC;AAyLrG,wBAA8B,wBAAwB,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAwDvF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
|
-
import { mkdirSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { join } from "node:path";
|
|
2
|
+
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { extname, join, resolve } from "node:path";
|
|
4
4
|
import { generateImages, getImageModel, getImageModels } from "../../sdk/ai/index.js";
|
|
5
5
|
// App-layer routing helpers (mirror aexol-mcp.ts): obtain backendUrl +
|
|
6
6
|
// machineJwt the same way agent-bridge.ts gets them for text models, so image
|
|
@@ -9,13 +9,23 @@ import { generateImages, getImageModel, getImageModels } from "../../sdk/ai/inde
|
|
|
9
9
|
import { getApiUrl, readConfig } from "../../config.js";
|
|
10
10
|
import { loadMachine } from "../../relay/machine-store.js";
|
|
11
11
|
import { isJwtExpired } from "../../relay/registration.js";
|
|
12
|
+
const imageReferenceSchema = Type.Union([
|
|
13
|
+
Type.String({
|
|
14
|
+
description: "Path to a reference image file (relative to the project working directory or absolute).",
|
|
15
|
+
}),
|
|
16
|
+
Type.Object({
|
|
17
|
+
data: Type.String({ description: "Reference image as raw base64 or data URL." }),
|
|
18
|
+
mimeType: Type.Optional(Type.String({ default: "image/png", description: "Reference image MIME type." })),
|
|
19
|
+
}, { description: "Reference image provided inline as base64 data." }),
|
|
20
|
+
Type.Object({
|
|
21
|
+
path: Type.String({ description: "Path to a reference image file (relative to the project working directory or absolute)." }),
|
|
22
|
+
mimeType: Type.Optional(Type.String({ description: "Reference image MIME type. Defaults to the type detected from the file extension." })),
|
|
23
|
+
}, { description: "Reference image provided as a file path." }),
|
|
24
|
+
]);
|
|
12
25
|
const imageGenerateSchema = Type.Object({
|
|
13
26
|
prompt: Type.String({ description: "Text prompt describing the image to generate." }),
|
|
14
27
|
model: Type.Optional(Type.String({ default: "google/gemini-3.1-flash-lite-image", description: "OpenRouter image model id." })),
|
|
15
|
-
images: Type.Optional(Type.Array(
|
|
16
|
-
data: Type.String({ description: "Reference image as raw base64 or data URL." }),
|
|
17
|
-
mimeType: Type.Optional(Type.String({ default: "image/png", description: "Reference image MIME type." })),
|
|
18
|
-
}), { description: "Optional reference images for image-to-image generation." })),
|
|
28
|
+
images: Type.Optional(Type.Array(imageReferenceSchema, { description: "Optional reference images for image-to-image generation. Each element may be a file path string, an object { data: <base64 or data URL>, mimeType?: string }, or an object { path: <file path>, mimeType?: string }." })),
|
|
19
29
|
n: Type.Optional(Type.Number({ minimum: 1, maximum: 10, default: 1 })),
|
|
20
30
|
resolution: Type.Optional(Type.String({ description: "Resolution tier, e.g. 512, 1K, 2K, 4K." })),
|
|
21
31
|
aspect_ratio: Type.Optional(Type.String({ description: "Aspect ratio, e.g. 1:1, 16:9, 9:16, auto." })),
|
|
@@ -40,6 +50,70 @@ function extensionForMimeType(mimeType) {
|
|
|
40
50
|
return "webp";
|
|
41
51
|
return "png";
|
|
42
52
|
}
|
|
53
|
+
function mimeTypeForPath(filePath) {
|
|
54
|
+
switch (extname(filePath).toLowerCase()) {
|
|
55
|
+
case ".png":
|
|
56
|
+
return "image/png";
|
|
57
|
+
case ".jpg":
|
|
58
|
+
case ".jpeg":
|
|
59
|
+
return "image/jpeg";
|
|
60
|
+
case ".webp":
|
|
61
|
+
return "image/webp";
|
|
62
|
+
case ".gif":
|
|
63
|
+
return "image/gif";
|
|
64
|
+
default:
|
|
65
|
+
return "image/png";
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function readReferenceImageFromPath(filePath, mimeType) {
|
|
69
|
+
let data;
|
|
70
|
+
try {
|
|
71
|
+
data = readFileSync(filePath).toString("base64");
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
const code = error?.code;
|
|
75
|
+
if (code === "ENOENT") {
|
|
76
|
+
throw new Error(`Reference image file does not exist: ${filePath}`);
|
|
77
|
+
}
|
|
78
|
+
if (code === "EACCES" || code === "EPERM") {
|
|
79
|
+
throw new Error(`Permission denied while reading reference image: ${filePath}`);
|
|
80
|
+
}
|
|
81
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
82
|
+
throw new Error(`Failed to read reference image: ${filePath} (${detail})`);
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
type: "image",
|
|
86
|
+
data,
|
|
87
|
+
mimeType: mimeType ?? mimeTypeForPath(filePath),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function normalizeReferenceImages(images, cwd) {
|
|
91
|
+
if (!images)
|
|
92
|
+
return [];
|
|
93
|
+
return images.map((image, index) => {
|
|
94
|
+
if (typeof image === "string") {
|
|
95
|
+
return readReferenceImageFromPath(resolve(cwd, image), undefined);
|
|
96
|
+
}
|
|
97
|
+
if (typeof image !== "object" || image === null) {
|
|
98
|
+
throw new Error(`Invalid reference image at index ${index}: expected a file path string or an object with "data" or "path".`);
|
|
99
|
+
}
|
|
100
|
+
const reference = image;
|
|
101
|
+
if (typeof reference.data === "string" && typeof reference.path === "string") {
|
|
102
|
+
throw new Error(`Invalid reference image at index ${index}: provide only one of "data" (inline base64) or "path" (file path), not both.`);
|
|
103
|
+
}
|
|
104
|
+
if (typeof reference.data === "string") {
|
|
105
|
+
return {
|
|
106
|
+
type: "image",
|
|
107
|
+
data: reference.data,
|
|
108
|
+
mimeType: reference.mimeType ?? "image/png",
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
if (typeof reference.path === "string") {
|
|
112
|
+
return readReferenceImageFromPath(resolve(cwd, reference.path), reference.mimeType);
|
|
113
|
+
}
|
|
114
|
+
throw new Error(`Invalid reference image at index ${index}: expected a file path string or an object with "data" or "path".`);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
43
117
|
function slugFromPrompt(prompt) {
|
|
44
118
|
const slug = prompt
|
|
45
119
|
.normalize("NFKD")
|
|
@@ -120,11 +194,7 @@ export default async function imageGenerationExtension(ext) {
|
|
|
120
194
|
const context = {
|
|
121
195
|
input: [
|
|
122
196
|
{ type: "text", text: input.prompt },
|
|
123
|
-
...(input.images
|
|
124
|
-
type: "image",
|
|
125
|
-
data: image.data,
|
|
126
|
-
mimeType: image.mimeType ?? "image/png",
|
|
127
|
-
})),
|
|
197
|
+
...normalizeReferenceImages(input.images, ctx.cwd),
|
|
128
198
|
],
|
|
129
199
|
};
|
|
130
200
|
// Route through the backend image proxy (POST /image/generation) using
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read-project-observations.d.ts","sourceRoot":"","sources":["../../../src/memory/tools/read-project-observations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAGhF,eAAO,MAAM,mCAAmC,8BAA8B,CAAC;AAE/E,eAAO,MAAM,2BAA2B;;
|
|
1
|
+
{"version":3,"file":"read-project-observations.d.ts","sourceRoot":"","sources":["../../../src/memory/tools/read-project-observations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAGhF,eAAO,MAAM,mCAAmC,8BAA8B,CAAC;AAE/E,eAAO,MAAM,2BAA2B;;iFA4FtC,CAAC;AAEH,wBAAgB,mCAAmC,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAE3E"}
|
|
@@ -9,22 +9,26 @@ export const readProjectObservationsTool = defineTool({
|
|
|
9
9
|
"and per-working-directory (cwd). " +
|
|
10
10
|
"Use this when you need to recall project conventions, past decisions, " +
|
|
11
11
|
"file locations, or user preferences before editing or creating files. " +
|
|
12
|
-
"Uses
|
|
13
|
-
"
|
|
12
|
+
"Uses n-gram matching: multi-word queries match observations containing all terms; " +
|
|
13
|
+
"typo-tolerant fallback when nothing matches exactly. " +
|
|
14
|
+
"Returns up to 20 best-matching observations with relevance tags. " +
|
|
14
15
|
"Results are local to this machine and cwd; they are NOT synced across machines or teams.",
|
|
15
16
|
promptSnippet: "Use read_project_observations(<query>) to search past observations across sessions in this local project working directory.",
|
|
16
17
|
promptGuidelines: [
|
|
17
18
|
"Results are per-machine + per-cwd and cross-session; they are NOT shared across machines or teams.",
|
|
18
19
|
"Use read_project_observations before creating new files to find conventions for that file kind.",
|
|
19
20
|
"Use read_project_observations before editing a file to find past context about that file or its directory.",
|
|
20
|
-
"
|
|
21
|
+
"Search for file paths, technology names, or pattern keywords; multi-word queries match observations containing all terms.",
|
|
21
22
|
"Do not use for broad topic searches — keep queries narrow for relevant results.",
|
|
22
23
|
"Results include relevance tags (critical/high/medium/low) to help you prioritize.",
|
|
24
|
+
"Results are ranked by match quality, relevance tag, and recency.",
|
|
23
25
|
],
|
|
24
26
|
parameters: Type.Object({
|
|
25
27
|
query: Type.String({
|
|
26
28
|
minLength: 1,
|
|
27
|
-
description: "
|
|
29
|
+
description: "Search terms to look for in past observation content. " +
|
|
30
|
+
"Multi-word queries match observations containing all terms; " +
|
|
31
|
+
"minor typos are tolerated when nothing matches exactly. " +
|
|
28
32
|
"Use file paths (e.g. 'src/auth/middleware'), technology names, " +
|
|
29
33
|
"or pattern keywords (e.g. 'convention', 'api route').",
|
|
30
34
|
}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-project-observation.d.ts","sourceRoot":"","sources":["../../../src/memory/tools/write-project-observation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAIhF,eAAO,MAAM,mCAAmC,8BAA8B,CAAC;AAE/E,eAAO,MAAM,2BAA2B;;;
|
|
1
|
+
{"version":3,"file":"write-project-observation.d.ts","sourceRoot":"","sources":["../../../src/memory/tools/write-project-observation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAIhF,eAAO,MAAM,mCAAmC,8BAA8B,CAAC;AAE/E,eAAO,MAAM,2BAA2B;;;iFA+EtC,CAAC;AAEH,wBAAgB,mCAAmC,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAE3E"}
|
|
@@ -11,7 +11,9 @@ export const writeProjectObservationTool = defineTool({
|
|
|
11
11
|
"they are shared across sessions on this machine but are NOT synced across machines or teams. " +
|
|
12
12
|
"Use this to persist discovered conventions, architectural rules, " +
|
|
13
13
|
"gotchas, and directory purposes. Observations are deduplicated by " +
|
|
14
|
-
"content hash — writing the same fact twice is harmless (idempotent)
|
|
14
|
+
"content hash — writing the same fact twice is harmless (idempotent) — " +
|
|
15
|
+
"and near-duplicate rewordings (very similar content) automatically " +
|
|
16
|
+
"replace the older observation. " +
|
|
15
17
|
"Future sessions in this working directory can discover these via read_project_observations.",
|
|
16
18
|
promptSnippet: "Use write_project_observation(content, relevance) to persist local, cross-session knowledge for this working directory.",
|
|
17
19
|
promptGuidelines: [
|
|
@@ -22,6 +24,8 @@ export const writeProjectObservationTool = defineTool({
|
|
|
22
24
|
"Use relevance='medium' for useful patterns and directory purposes.",
|
|
23
25
|
"Content must be a single, self-contained sentence — no markdown, no lists.",
|
|
24
26
|
"Deduplication is automatic — same content = same ID → INSERT OR REPLACE.",
|
|
27
|
+
"Near-duplicate rewordings (very similar content) replace the older observation automatically — no need to delete or rewrite existing facts first.",
|
|
28
|
+
"A rewording that replaces a near-duplicate gets a new id; observation ids shared before the replacement may become unresolvable.",
|
|
25
29
|
],
|
|
26
30
|
parameters: Type.Object({
|
|
27
31
|
content: Type.String({
|
package/dist/server/storage.d.ts
CHANGED
|
@@ -154,9 +154,17 @@ export declare class SessionStore {
|
|
|
154
154
|
private stmtSetForkCompactSource;
|
|
155
155
|
private stmtGetForkCompactSource;
|
|
156
156
|
private stmtInsertProjectObs;
|
|
157
|
-
private stmtSearchProjectObs;
|
|
158
157
|
private stmtGetProjectObsById;
|
|
159
158
|
private stmtGetProjectByCwd;
|
|
159
|
+
private stmtListProjectObsByProject;
|
|
160
|
+
private stmtDeleteProjectObs;
|
|
161
|
+
private stmtCountProjectObs;
|
|
162
|
+
private ftsEnabled;
|
|
163
|
+
private stmtInsertProjectObsFts;
|
|
164
|
+
private stmtDeleteProjectObsFts;
|
|
165
|
+
private stmtDeleteProjectObsFtsByProject;
|
|
166
|
+
private stmtSearchProjectObsFts;
|
|
167
|
+
private stmtCountProjectObsFts;
|
|
160
168
|
private stmtUpsertProjectRecallSource;
|
|
161
169
|
private stmtGetProjectRecallSource;
|
|
162
170
|
private stmtEnqueuePrompt;
|
|
@@ -409,6 +417,12 @@ export declare class SessionStore {
|
|
|
409
417
|
/**
|
|
410
418
|
* Insert multiple project observations in a single transaction.
|
|
411
419
|
* Uses INSERT OR REPLACE so re-running after the same compaction is idempotent.
|
|
420
|
+
*
|
|
421
|
+
* Write-time near-duplicate detection: an observation whose content is a
|
|
422
|
+
* near-identical rewording (trigram Jaccard >= NEAR_DUPLICATE_SIMILARITY)
|
|
423
|
+
* of an existing row replaces it — new wording wins — so refinements of
|
|
424
|
+
* the same fact don't accumulate as duplicates. The FTS5 trigram index is
|
|
425
|
+
* synced in the same transaction.
|
|
412
426
|
*/
|
|
413
427
|
insertProjectObservations(projectId: string, sessionId: string, observations: Array<{
|
|
414
428
|
id: string;
|
|
@@ -416,7 +430,26 @@ export declare class SessionStore {
|
|
|
416
430
|
relevance: string;
|
|
417
431
|
}>, createdAt: number): void;
|
|
418
432
|
/**
|
|
419
|
-
*
|
|
433
|
+
* Find an existing project observation whose content is a near-identical
|
|
434
|
+
* rewording of `content` (trigram Jaccard >= NEAR_DUPLICATE_SIMILARITY).
|
|
435
|
+
*/
|
|
436
|
+
private findNearDuplicateObservation;
|
|
437
|
+
/**
|
|
438
|
+
* Search project observations using n-gram matching.
|
|
439
|
+
*
|
|
440
|
+
* Query tokens are matched via the FTS5 trigram index: each token becomes
|
|
441
|
+
* a quoted phrase joined with AND, so a multi-word query matches
|
|
442
|
+
* observations containing ALL tokens anywhere (case-insensitive substring
|
|
443
|
+
* semantics). Tokens shorter than 3 characters cannot be matched by the
|
|
444
|
+
* trigram tokenizer; they are applied as a complementary LIKE filter over
|
|
445
|
+
* the FTS candidates (or as a plain LIKE conjunction when every token is
|
|
446
|
+
* short, or when the index is unavailable). When no candidate survives,
|
|
447
|
+
* a typo-tolerant fallback keeps observations whose token-level trigram
|
|
448
|
+
* similarity to the query is >= TYPO_FALLBACK_MIN_MEAN_SIMILARITY.
|
|
449
|
+
*
|
|
450
|
+
* Results are ranked by a blend of text-match quality, relevance tag and
|
|
451
|
+
* recency. The return shape is unchanged from the previous substring
|
|
452
|
+
* search: { content, relevance, createdAt, sessionId }.
|
|
420
453
|
*/
|
|
421
454
|
searchProjectObservations(projectId: string, query: string, limit?: number): Array<{
|
|
422
455
|
content: string;
|
|
@@ -424,6 +457,30 @@ export declare class SessionStore {
|
|
|
424
457
|
createdAt: number;
|
|
425
458
|
sessionId: string;
|
|
426
459
|
}>;
|
|
460
|
+
/**
|
|
461
|
+
* Collect candidate observations for a tokenized query, assigning each a
|
|
462
|
+
* normalized text-match score in (0, 1].
|
|
463
|
+
*/
|
|
464
|
+
private findObservationCandidates;
|
|
465
|
+
/**
|
|
466
|
+
* FTS5 trigram MATCH over `longTokens`, then a complementary LIKE filter
|
|
467
|
+
* for tokens too short for the trigram tokenizer. Returns an empty array
|
|
468
|
+
* when the index yields nothing usable (the caller then falls back).
|
|
469
|
+
*/
|
|
470
|
+
private searchObservationsFts;
|
|
471
|
+
/**
|
|
472
|
+
* Rebuild the FTS index from project_observations when it is out of sync
|
|
473
|
+
* (empty or partial relative to the base table). Handles databases created
|
|
474
|
+
* before the FTS index existed and any drift (e.g. projects deleted by an
|
|
475
|
+
* older build without FTS cleanup). No-op when the counts already match.
|
|
476
|
+
*/
|
|
477
|
+
private backfillProjectObservationsFts;
|
|
478
|
+
/**
|
|
479
|
+
* Whether the FTS5 trigram index is active for project observations.
|
|
480
|
+
* Exposed for diagnostics and tests; false means search is running in
|
|
481
|
+
* LIKE-only degradation mode.
|
|
482
|
+
*/
|
|
483
|
+
isProjectObsFtsEnabled(): boolean;
|
|
427
484
|
/**
|
|
428
485
|
* Get a single project observation by id. Returns null if not found.
|
|
429
486
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/server/storage.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/server/storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAgBH,OAAO,KAAK,EACV,eAAe,EACf,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,kBAAkB,EACnB,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAsB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,sEAAsE;AACtE,MAAM,MAAM,aAAa,GAAG,WAAW,CAAC;AAExC,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC,wDAAwD;IACxD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sFAAsF;IACtF,MAAM,CAAC,EAAE,eAAe,EAAE,CAAC;IAC3B,0GAA0G;IAC1G,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mFAAmF;IACnF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,wDAAwD;IACxD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,sBAAsB,CAAC;IAChC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,+CAA+C;AAC/C,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,+BAA+B;IAC9C,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACb;AAqUD,UAAU,QAAQ;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AA0BD,qBAAa,YAAY;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,CAAgB;IAC1B,OAAO,CAAC,MAAM,CAAS;IAGvB,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAMhC;IACJ,OAAO,CAAC,gBAAgB,CAA2C;IACnE,OAAO,CAAC,cAAc,CAAwC;IAC9D,OAAO,CAAC,0BAA0B,CAAsC;IACxE,OAAO,CAAC,iBAAiB,CAA4D;IACrF,OAAO,CAAC,iBAAiB,CAAoD;IAC7E,OAAO,CAAC,2BAA2B,CAAiF;IACpH,OAAO,CAAC,iBAAiB,CAA4B;IACrD,OAAO,CAAC,yBAAyB,CAAiD;IAClF,OAAO,CAAC,2BAA2B,CAA4C;IAC/E,OAAO,CAAC,kCAAkC,CAAoD;IAC9F,OAAO,CAAC,kCAAkC,CAAoC;IAG9E,OAAO,CAAC,cAAc,CAAwC;IAC9D,OAAO,CAAC,iBAAiB,CAA4D;IACrF,OAAO,CAAC,iBAAiB,CAA4B;IACrD,OAAO,CAAC,gBAAgB,CAAwC;IAChE,OAAO,CAAC,oBAAoB,CAAgD;IAC5E,OAAO,CAAC,sBAAsB,CAAwE;IACtG,OAAO,CAAC,iCAAiC,CAAwE;IACjH,OAAO,CAAC,0BAA0B,CAAsC;IACxE,OAAO,CAAC,8BAA8B,CAAsC;IAC5E,OAAO,CAAC,iBAAiB,CAEvB;IACF,OAAO,CAAC,iBAAiB,CAAoD;IAC7E,OAAO,CAAC,oBAAoB,CAAwD;IACpF,OAAO,CAAC,wBAAwB,CAAoC;IACpE,OAAO,CAAC,iBAAiB,CAA4B;IACrD,OAAO,CAAC,2BAA2B,CAAoC;IACvE,OAAO,CAAC,2BAA2B,CAA4B;IAC/D,OAAO,CAAC,2BAA2B,CAAoC;IACvE,OAAO,CAAC,gBAAgB,CAAoC;IAC5D,OAAO,CAAC,uBAAuB,CAA4C;IAC3E,OAAO,CAAC,qBAAqB,CAA4C;IACzE,OAAO,CAAC,oBAAoB,CAAiD;IAC7E,OAAO,CAAC,4BAA4B,CAAsD;IAC1F,OAAO,CAAC,+BAA+B,CAA4D;IACnG,OAAO,CAAC,+BAA+B,CAA4B;IAEnE,OAAO,CAAC,mBAAmB,CAAyD;IACpF,OAAO,CAAC,mBAAmB,CAA2C;IACtE,OAAO,CAAC,yBAAyB,CAA6D;IAC9F,OAAO,CAAC,yBAAyB,CAA2C;IAC5E,OAAO,CAAC,6BAA6B,CAAiE;IACtG,OAAO,CAAC,6BAA6B,CAA2C;IAChF,OAAO,CAAC,8BAA8B,CAAmE;IACzG,OAAO,CAAC,8BAA8B,CAA2C;IAEjF,OAAO,CAAC,wBAAwB,CAA2C;IAC3E,OAAO,CAAC,wBAAwB,CAAuE;IAEvG,OAAO,CAAC,oBAAoB,CAAoE;IAChG,OAAO,CAAC,qBAAqB,CAA2D;IACxF,OAAO,CAAC,mBAAmB,CAA4C;IAEvE,OAAO,CAAC,2BAA2B,CAAmD;IACtF,OAAO,CAAC,oBAAoB,CAAoC;IAChE,OAAO,CAAC,mBAAmB,CAAgC;IAG3D,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,uBAAuB,CAA0D;IACzF,OAAO,CAAC,uBAAuB,CAAkD;IACjF,OAAO,CAAC,gCAAgC,CAA0C;IAClF,OAAO,CAAC,uBAAuB,CAAoE;IACnG,OAAO,CAAC,sBAAsB,CAA8C;IAC5E,OAAO,CAAC,6BAA6B,CAAoD;IACzF,OAAO,CAAC,0BAA0B,CAA4D;IAG9F,OAAO,CAAC,iBAAiB,CAAoE;IAC7F,OAAO,CAAC,kBAAkB,CAAsC;IAChE,OAAO,CAAC,iBAAiB,CAAsC;IAC/D,OAAO,CAAC,mBAAmB,CAAoC;IAC/D,OAAO,CAAC,qBAAqB,CAA4B;IACzD,OAAO,CAAC,kBAAkB,CAA4C;IAGtE,OAAO,CAAC,2BAA2B,CAEjC;IACF,OAAO,CAAC,0BAA0B,CAGhC;IACF,OAAO,CAAC,kCAAkC,CAAoC;IAC9E,OAAO,CAAC,mCAAmC,CAA4B;IACvE,OAAO,CAAC,+BAA+B,CAA4B;IAGnE,OAAO,CAAC,6BAA6B,CAA+C;IACpF,OAAO,CAAC,2BAA2B,CAAqD;IACxF,OAAO,CAAC,oCAAoC,CAA6D;IACzG,OAAO,CAAC,8BAA8B,CAEpC;gBAEU,IAAI,EAAE,MAAM;IAogBxB,8DAA8D;IAC9D,UAAU,IAAI,MAAM,EAAE;IAOtB,+EAA+E;IAC/E,OAAO,CAAC,uBAAuB;IAyB/B,YAAY,IAAI,WAAW,EAAE;IAI7B;;;;OAIG;IACG,iBAAiB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAOjD,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,WAAW;IAgBrD,iCAAiC;IACjC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAsB1C,wCAAwC;IAClC,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IA8B9D,uBAAuB,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI,GAAG,WAAW,GAAG,IAAI;IAYtF;;;;OAIG;IACH,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,WAAW,GAAG,IAAI;IAYxE;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,EAAE,CAAA;KAAE;IAWrE,4DAA4D;IAC5D,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,kBAAkB,EAAE;IAW9D,mDAAmD;IAC7C,0BAA0B,CAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAkBhC;;;;;;;;;;;;;;;;OAgBG;IACH,wBAAwB,CACtB,UAAU,EAAE,MAAM,EAAE,GACnB,GAAG,CAAC,MAAM,EAAE,kBAAkB,EAAE,CAAC;IA8BpC;;;;;;OAMG;IACG,6BAA6B,CACjC,UAAU,EAAE,MAAM,EAAE,GACnB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAkC7C,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,kBAAkB;IAyB5D,iCAAiC;IACjC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI;IAuBhD,oEAAoE;IACpE,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAK9C;;;;OAIG;IACH,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG;QAC1B,EAAE,EAAE,MAAM,CAAC;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,IAAI;IAYR,4CAA4C;IACtC,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAC7C,EAAE,EAAE,MAAM,CAAC;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,IAAI,CAAC;IAiBT,sEAAsE;IAChE,oBAAoB,CACxB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,aAAa,EAAE,CAAC;IAiB3B;;;;;;OAMG;IACG,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IASnE,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,EAAE;IAG/C,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,EAAE;IAGlE,iBAAiB,CACf,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE;QACJ,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,KAAK,EAAE,MAAM,CAAC;KACf,GACA,aAAa,EAAE;IAuBlB,+CAA+C;IACzC,sBAAsB,CAC1B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE;QACJ,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,KAAK,EAAE,MAAM,CAAC;KACf,GACA,OAAO,CAAC,aAAa,EAAE,CAAC;IAyC3B,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAGjD,0BAA0B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAGrD,oDAAoD;IAC9C,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAOrE,OAAO,CAAC,cAAc;IAgBtB;;;OAGG;IACH,kEAAkE;IAClE,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAY/B,mDAAmD;IACnD,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAYhD,mGAAmG;IACnG,4BAA4B,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM;IA0BtF,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,kBAAkB,GAAG,aAAa;IA6CxE;;;;OAIG;IACH,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAYlE;;;;;;;OAOG;IACH,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO;IASpE;;;;;;;OAOG;IACH,aAAa,CACX,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAC1B,kBAAkB,GAAG,IAAI;IAoB5B,OAAO,CAAC,cAAc;IAWtB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAKlC;;;;;OAKG;IACH,+BAA+B,CAC7B,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,GACpB;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,EAAE,CAAA;KAAE;IAgBrC,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,qBAAqB,GAAG,IAAI;IAqBzE,2BAA2B,CACzB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,IAAI,CAAC,qBAAqB,EAAE,WAAW,GAAG,WAAW,CAAC,GAC/D,IAAI;IAWP,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAQpD;;;;;;;OAOG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKjD;;;;;;OAMG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAGhE,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAGvD,mDAAmD;IAC7C,0BAA0B,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAO3E,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAIxE;;;;OAIG;IACH,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAK3D;;;;OAIG;IACH,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAIzE,6EAA6E;IAC7E,0BAA0B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAI5D,iGAAiG;IACjG,0BAA0B,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAQ9E;;;;;OAKG;IACH,WAAW,CACT,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,GAC/C,kBAAkB;IAsDrB;;;OAGG;IACH,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKtD,kDAAkD;IAC5C,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAQ1E;;;OAGG;IACH,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAQ/C;;;;;;;;;OASG;IACH,yBAAyB,CACvB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,EACvE,SAAS,EAAE,MAAM,GAChB,IAAI;IAwBP;;;OAGG;IACH,OAAO,CAAC,4BAA4B;IAgBpC;;;;;;;;;;;;;;;;OAgBG;IACH,yBAAyB,CACvB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,KAAK,SAAK,GACT,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAsBtF;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IA0CjC;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;IAmC7B;;;;;OAKG;IACH,OAAO,CAAC,8BAA8B;IAgBtC;;;;OAIG;IACH,sBAAsB,IAAI,OAAO;IAIjC;;OAEG;IACH,yBAAyB,CACvB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,GACpB;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAYlG;;;OAGG;IACH,4BAA4B,CAC1B,SAAS,EAAE,MAAM,EACjB,KAAK,SAAK,GACT,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAmBlG;;;OAGG;IACH,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAK3C;;;;OAIG;IACH,yBAAyB,CACvB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,KAAK,EAAE,GACf,IAAI;IASP;;;OAGG;IACH,sBAAsB,CACpB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,KAAK,EAAE,GAAG,IAAI;IAqBjB,uBAAuB,CAAC,GAAG,EAAE,iBAAiB,GAAG,IAAI;IAgBrD,sBAAsB,CAAC,KAAK,EAAE;QAC5B,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,aAAa,EAAE,OAAO,CAAC;KACxB,GAAG,iBAAiB,EAAE;IA2CvB,+BAA+B,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIlD,iCAAiC,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAQvD;;;OAGG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,eAAe,EAAE,GAAG,QAAQ;IAYvF;;;;OAIG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI;IAYjD;;OAEG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,EAAE;IAI7C;;;OAGG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAUrD;;OAEG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAQzC,OAAO,CAAC,0BAA0B;IAclC,yBAAyB,IAAI,oBAAoB,EAAE;IAMnD,uBAAuB,CAAC,EAAE,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI;IAKhE,+DAA+D;IAC/D,gCAAgC,CAC9B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,GACd,oBAAoB,GAAG,IAAI;IAK9B,0BAA0B,CACxB,KAAK,EAAE,+BAA+B,GACrC,oBAAoB;IAwBvB,KAAK,IAAI,IAAI;CAKd;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,OAAO,CAAC;IACZ,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,CAmB/D"}
|
package/dist/server/storage.js
CHANGED
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
* later (e.g. if we ever need to colocate with a remote service).
|
|
29
29
|
*/
|
|
30
30
|
import { createSqliteAdapter } from "./sqlite-adapter.js";
|
|
31
|
+
import { MIN_TRIGRAM_TOKEN_LENGTH, bestTokenTrigramJaccard, buildFtsMatchQuery, trigramJaccard, } from "./text/trigrams.js";
|
|
31
32
|
import { randomUUID } from "node:crypto";
|
|
32
33
|
import { mkdirSync, readFileSync } from "node:fs";
|
|
33
34
|
import { dirname, join, resolve } from "node:path";
|
|
@@ -149,6 +150,61 @@ CREATE TABLE IF NOT EXISTS dev_process_definitions (
|
|
|
149
150
|
updated_at INTEGER NOT NULL
|
|
150
151
|
);
|
|
151
152
|
`;
|
|
153
|
+
/**
|
|
154
|
+
* FTS5 trigram index over project-observation content, synced explicitly in
|
|
155
|
+
* code (same transaction as `insertProjectObservations`) rather than via
|
|
156
|
+
* triggers so the behavior is obvious and testable. `obs_id` stores the
|
|
157
|
+
* observation id so stale index rows can be deleted on INSERT OR REPLACE.
|
|
158
|
+
*
|
|
159
|
+
* Created outside SCHEMA_SQL on purpose: if the bundled SQLite build lacks
|
|
160
|
+
* FTS5, the store still opens and observation search degrades to LIKE
|
|
161
|
+
* filtering instead of failing at startup.
|
|
162
|
+
*/
|
|
163
|
+
const PROJECT_OBS_FTS_SQL = `
|
|
164
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS project_observations_fts USING fts5(
|
|
165
|
+
content,
|
|
166
|
+
project_id UNINDEXED,
|
|
167
|
+
obs_id UNINDEXED,
|
|
168
|
+
tokenize='trigram'
|
|
169
|
+
);
|
|
170
|
+
`;
|
|
171
|
+
// ---- observational-memory ranking constants ------------------------------
|
|
172
|
+
/** Weight of the text-match component (bm25-derived or trigram similarity). */
|
|
173
|
+
const WEIGHT_TEXT_MATCH = 0.6;
|
|
174
|
+
/** Weight of the relevance-tag component (critical=1.0 … low=0.25). */
|
|
175
|
+
const WEIGHT_RELEVANCE = 0.25;
|
|
176
|
+
/** Weight of the recency component. */
|
|
177
|
+
const WEIGHT_RECENCY = 0.15;
|
|
178
|
+
/** Recency decay constant: exp(-ageDays / RECENCY_DECAY_DAYS). */
|
|
179
|
+
const RECENCY_DECAY_DAYS = 30;
|
|
180
|
+
const MS_PER_DAY = 86_400_000;
|
|
181
|
+
/** Relevance-tag weights used by the ranking formula. */
|
|
182
|
+
const RELEVANCE_WEIGHTS = {
|
|
183
|
+
critical: 1.0,
|
|
184
|
+
high: 0.75,
|
|
185
|
+
medium: 0.5,
|
|
186
|
+
low: 0.25,
|
|
187
|
+
};
|
|
188
|
+
/** Minimum mean trigram Jaccard similarity for a typo-tolerant fallback match. */
|
|
189
|
+
const TYPO_FALLBACK_MIN_MEAN_SIMILARITY = 0.3;
|
|
190
|
+
/**
|
|
191
|
+
* Trigram Jaccard similarity at or above which a new observation is treated
|
|
192
|
+
* as a near-duplicate rewording of an existing row and replaces it.
|
|
193
|
+
*/
|
|
194
|
+
const NEAR_DUPLICATE_SIMILARITY = 0.9;
|
|
195
|
+
/**
|
|
196
|
+
* Final ranking score for a candidate observation: a weighted blend of
|
|
197
|
+
* normalized text-match quality, relevance tag and recency decay. Every
|
|
198
|
+
* component is in [0, 1]; higher is better.
|
|
199
|
+
*/
|
|
200
|
+
function scoreObservation(textScore, relevance, createdAt, now) {
|
|
201
|
+
const ageDays = Math.max(0, (now - createdAt) / MS_PER_DAY);
|
|
202
|
+
const recency = Math.exp(-ageDays / RECENCY_DECAY_DAYS);
|
|
203
|
+
const relevanceWeight = RELEVANCE_WEIGHTS[relevance] ?? RELEVANCE_WEIGHTS.low;
|
|
204
|
+
return (textScore * WEIGHT_TEXT_MATCH +
|
|
205
|
+
relevanceWeight * WEIGHT_RELEVANCE +
|
|
206
|
+
recency * WEIGHT_RECENCY);
|
|
207
|
+
}
|
|
152
208
|
/**
|
|
153
209
|
* Synchronous binding-file reader for a project at the given filesystem path.
|
|
154
210
|
* Returns null when no `.aexol/aexol.jsonc` exists at that path.
|
|
@@ -269,9 +325,20 @@ export class SessionStore {
|
|
|
269
325
|
stmtGetForkCompactSource;
|
|
270
326
|
// Project observations: cross-session durable memory.
|
|
271
327
|
stmtInsertProjectObs;
|
|
272
|
-
stmtSearchProjectObs;
|
|
273
328
|
stmtGetProjectObsById;
|
|
274
329
|
stmtGetProjectByCwd;
|
|
330
|
+
// Shared by the typo-tolerant search fallback and near-duplicate detection.
|
|
331
|
+
stmtListProjectObsByProject;
|
|
332
|
+
stmtDeleteProjectObs;
|
|
333
|
+
stmtCountProjectObs;
|
|
334
|
+
// FTS5 trigram index statements. Null when the bundled SQLite build has no
|
|
335
|
+
// FTS5 — the store then degrades to LIKE-only search (see `ftsEnabled`).
|
|
336
|
+
ftsEnabled = false;
|
|
337
|
+
stmtInsertProjectObsFts = null;
|
|
338
|
+
stmtDeleteProjectObsFts = null;
|
|
339
|
+
stmtDeleteProjectObsFtsByProject = null;
|
|
340
|
+
stmtSearchProjectObsFts = null;
|
|
341
|
+
stmtCountProjectObsFts = null;
|
|
275
342
|
stmtUpsertProjectRecallSource;
|
|
276
343
|
stmtGetProjectRecallSource;
|
|
277
344
|
// Prompt queue statements
|
|
@@ -539,14 +606,15 @@ export class SessionStore {
|
|
|
539
606
|
this.stmtGetForkCompactSource = this.db.prepare(`SELECT fork_compact_source_id FROM sessions WHERE id = ?`);
|
|
540
607
|
this.stmtInsertProjectObs = this.db.prepare(`INSERT OR REPLACE INTO project_observations (id, project_id, session_id, content, relevance, created_at)
|
|
541
608
|
VALUES (?, ?, ?, ?, ?, ?)`);
|
|
542
|
-
this.stmtSearchProjectObs = this.db.prepare(`SELECT id, project_id, session_id, content, relevance, created_at
|
|
543
|
-
FROM project_observations
|
|
544
|
-
WHERE project_id = ? AND content LIKE ?
|
|
545
|
-
ORDER BY created_at DESC
|
|
546
|
-
LIMIT 20`);
|
|
547
609
|
this.stmtGetProjectObsById = this.db.prepare(`SELECT id, project_id, session_id, content, relevance, created_at
|
|
548
610
|
FROM project_observations
|
|
549
611
|
WHERE project_id = ? AND id = ?`);
|
|
612
|
+
this.stmtListProjectObsByProject = this.db.prepare(`SELECT id, project_id, session_id, content, relevance, created_at
|
|
613
|
+
FROM project_observations
|
|
614
|
+
WHERE project_id = ?
|
|
615
|
+
ORDER BY created_at DESC`);
|
|
616
|
+
this.stmtDeleteProjectObs = this.db.prepare(`DELETE FROM project_observations WHERE id = ? AND project_id = ?`);
|
|
617
|
+
this.stmtCountProjectObs = this.db.prepare(`SELECT COUNT(*) AS count FROM project_observations`);
|
|
550
618
|
this.stmtGetProjectByCwd = this.db.prepare(`SELECT id FROM projects WHERE path = ? LIMIT 1`);
|
|
551
619
|
this.stmtUpsertProjectRecallSource = this.db.prepare(`INSERT OR REPLACE INTO project_recall_sources
|
|
552
620
|
(project_id, memory_id, entries_json, updated_at)
|
|
@@ -554,6 +622,35 @@ export class SessionStore {
|
|
|
554
622
|
this.stmtGetProjectRecallSource = this.db.prepare(`SELECT project_id, memory_id, entries_json, updated_at
|
|
555
623
|
FROM project_recall_sources
|
|
556
624
|
WHERE project_id = ? AND memory_id = ?`);
|
|
625
|
+
// ---- project-observation FTS trigram index ---------------------------
|
|
626
|
+
// The index is a standalone FTS5 virtual table synced explicitly in code
|
|
627
|
+
// (same transaction as insertProjectObservations). If the SQLite build
|
|
628
|
+
// lacks FTS5 we log a warning and degrade to LIKE-only search instead of
|
|
629
|
+
// failing to open the store.
|
|
630
|
+
try {
|
|
631
|
+
this.db.exec(PROJECT_OBS_FTS_SQL);
|
|
632
|
+
this.stmtInsertProjectObsFts = this.db.prepare(`INSERT INTO project_observations_fts (content, project_id, obs_id) VALUES (?, ?, ?)`);
|
|
633
|
+
this.stmtDeleteProjectObsFts = this.db.prepare(`DELETE FROM project_observations_fts WHERE obs_id = ? AND project_id = ?`);
|
|
634
|
+
this.stmtDeleteProjectObsFtsByProject = this.db.prepare(`DELETE FROM project_observations_fts WHERE project_id = ?`);
|
|
635
|
+
this.stmtSearchProjectObsFts = this.db.prepare(`SELECT o.id, o.session_id, o.content, o.relevance, o.created_at,
|
|
636
|
+
bm25(project_observations_fts) AS bm25_score
|
|
637
|
+
FROM project_observations_fts
|
|
638
|
+
JOIN project_observations o
|
|
639
|
+
ON o.id = project_observations_fts.obs_id
|
|
640
|
+
AND o.project_id = project_observations_fts.project_id
|
|
641
|
+
WHERE project_observations_fts MATCH ?
|
|
642
|
+
AND project_observations_fts.project_id = ?`);
|
|
643
|
+
this.stmtCountProjectObsFts = this.db.prepare(`SELECT COUNT(*) AS count FROM project_observations_fts`);
|
|
644
|
+
this.backfillProjectObservationsFts();
|
|
645
|
+
this.ftsEnabled = true;
|
|
646
|
+
}
|
|
647
|
+
catch (err) {
|
|
648
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
649
|
+
console.warn(`[storage] FTS5 trigram index unavailable (${msg}); ` +
|
|
650
|
+
`project-observation search degrades to a LIKE-conjunction ` +
|
|
651
|
+
`(exact token substring) scan without typo tolerance or bm25 ranking.`);
|
|
652
|
+
this.ftsEnabled = false;
|
|
653
|
+
}
|
|
557
654
|
// ---- prompt queue statements ----------------------------------------
|
|
558
655
|
this.stmtEnqueuePrompt = this.db.prepare(`INSERT INTO prompt_queue (id, session_id, content, images_json, position, created_at)
|
|
559
656
|
VALUES (?, ?, ?, ?, ?, ?)`);
|
|
@@ -736,6 +833,11 @@ export class SessionStore {
|
|
|
736
833
|
deleteProject(id) {
|
|
737
834
|
const sessionIds = this.stmtListSessionIdsByProject.all(id).map((r) => r.id);
|
|
738
835
|
const info = this.stmtDeleteProject.run(id);
|
|
836
|
+
if (info.changes > 0) {
|
|
837
|
+
// project_observations rows cascade via FK, but the standalone FTS
|
|
838
|
+
// index has no FK — clean it explicitly so it never accumulates orphans.
|
|
839
|
+
this.stmtDeleteProjectObsFtsByProject?.run(id);
|
|
840
|
+
}
|
|
739
841
|
return { deleted: info.changes > 0, sessionIds };
|
|
740
842
|
}
|
|
741
843
|
/** Sessions belonging to a single project, newest-first. */
|
|
@@ -1358,29 +1460,202 @@ export class SessionStore {
|
|
|
1358
1460
|
/**
|
|
1359
1461
|
* Insert multiple project observations in a single transaction.
|
|
1360
1462
|
* Uses INSERT OR REPLACE so re-running after the same compaction is idempotent.
|
|
1463
|
+
*
|
|
1464
|
+
* Write-time near-duplicate detection: an observation whose content is a
|
|
1465
|
+
* near-identical rewording (trigram Jaccard >= NEAR_DUPLICATE_SIMILARITY)
|
|
1466
|
+
* of an existing row replaces it — new wording wins — so refinements of
|
|
1467
|
+
* the same fact don't accumulate as duplicates. The FTS5 trigram index is
|
|
1468
|
+
* synced in the same transaction.
|
|
1361
1469
|
*/
|
|
1362
1470
|
insertProjectObservations(projectId, sessionId, observations, createdAt) {
|
|
1363
1471
|
if (observations.length === 0)
|
|
1364
1472
|
return;
|
|
1365
1473
|
const tx = this.db.transaction(() => {
|
|
1366
1474
|
for (const obs of observations) {
|
|
1475
|
+
// Near-duplicate detection: a reworded duplicate replaces the older
|
|
1476
|
+
// row. Identical re-inserts also match (similarity 1.0), which keeps
|
|
1477
|
+
// INSERT OR REPLACE idempotency intact.
|
|
1478
|
+
const duplicate = this.findNearDuplicateObservation(projectId, obs.content);
|
|
1479
|
+
if (duplicate) {
|
|
1480
|
+
this.stmtDeleteProjectObs.run(duplicate.id, projectId);
|
|
1481
|
+
this.stmtDeleteProjectObsFts?.run(duplicate.id, projectId);
|
|
1482
|
+
}
|
|
1367
1483
|
this.stmtInsertProjectObs.run(obs.id, projectId, sessionId, obs.content, obs.relevance, createdAt);
|
|
1484
|
+
if (this.ftsEnabled) {
|
|
1485
|
+
// INSERT OR REPLACE semantics: drop any stale index row for this id
|
|
1486
|
+
// before indexing the new content.
|
|
1487
|
+
this.stmtDeleteProjectObsFts?.run(obs.id, projectId);
|
|
1488
|
+
this.stmtInsertProjectObsFts?.run(obs.content, projectId, obs.id);
|
|
1489
|
+
}
|
|
1368
1490
|
}
|
|
1369
1491
|
});
|
|
1370
1492
|
tx();
|
|
1371
1493
|
}
|
|
1372
1494
|
/**
|
|
1373
|
-
*
|
|
1495
|
+
* Find an existing project observation whose content is a near-identical
|
|
1496
|
+
* rewording of `content` (trigram Jaccard >= NEAR_DUPLICATE_SIMILARITY).
|
|
1497
|
+
*/
|
|
1498
|
+
findNearDuplicateObservation(projectId, content) {
|
|
1499
|
+
let best = null;
|
|
1500
|
+
let bestSimilarity = 0;
|
|
1501
|
+
for (const row of this.stmtListProjectObsByProject.all(projectId)) {
|
|
1502
|
+
const similarity = trigramJaccard(content, row.content);
|
|
1503
|
+
if (similarity > bestSimilarity) {
|
|
1504
|
+
bestSimilarity = similarity;
|
|
1505
|
+
best = row;
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
return bestSimilarity >= NEAR_DUPLICATE_SIMILARITY ? best : null;
|
|
1509
|
+
}
|
|
1510
|
+
/**
|
|
1511
|
+
* Search project observations using n-gram matching.
|
|
1512
|
+
*
|
|
1513
|
+
* Query tokens are matched via the FTS5 trigram index: each token becomes
|
|
1514
|
+
* a quoted phrase joined with AND, so a multi-word query matches
|
|
1515
|
+
* observations containing ALL tokens anywhere (case-insensitive substring
|
|
1516
|
+
* semantics). Tokens shorter than 3 characters cannot be matched by the
|
|
1517
|
+
* trigram tokenizer; they are applied as a complementary LIKE filter over
|
|
1518
|
+
* the FTS candidates (or as a plain LIKE conjunction when every token is
|
|
1519
|
+
* short, or when the index is unavailable). When no candidate survives,
|
|
1520
|
+
* a typo-tolerant fallback keeps observations whose token-level trigram
|
|
1521
|
+
* similarity to the query is >= TYPO_FALLBACK_MIN_MEAN_SIMILARITY.
|
|
1522
|
+
*
|
|
1523
|
+
* Results are ranked by a blend of text-match quality, relevance tag and
|
|
1524
|
+
* recency. The return shape is unchanged from the previous substring
|
|
1525
|
+
* search: { content, relevance, createdAt, sessionId }.
|
|
1374
1526
|
*/
|
|
1375
1527
|
searchProjectObservations(projectId, query, limit = 20) {
|
|
1376
|
-
const
|
|
1377
|
-
|
|
1378
|
-
|
|
1528
|
+
const trimmed = query.trim();
|
|
1529
|
+
if (!trimmed)
|
|
1530
|
+
return [];
|
|
1531
|
+
const tokens = trimmed.split(/\s+/).filter((t) => t.length > 0);
|
|
1532
|
+
if (tokens.length === 0)
|
|
1533
|
+
return [];
|
|
1534
|
+
const now = Date.now();
|
|
1535
|
+
return this.findObservationCandidates(projectId, tokens)
|
|
1536
|
+
.map((candidate) => ({
|
|
1537
|
+
candidate,
|
|
1538
|
+
score: scoreObservation(candidate.textScore, candidate.relevance, candidate.created_at, now),
|
|
1539
|
+
}))
|
|
1540
|
+
.sort((a, b) => b.score - a.score || b.candidate.created_at - a.candidate.created_at)
|
|
1541
|
+
.slice(0, limit)
|
|
1542
|
+
.map(({ candidate }) => ({
|
|
1543
|
+
content: candidate.content,
|
|
1544
|
+
relevance: candidate.relevance,
|
|
1545
|
+
createdAt: candidate.created_at,
|
|
1546
|
+
sessionId: candidate.session_id,
|
|
1547
|
+
}));
|
|
1548
|
+
}
|
|
1549
|
+
/**
|
|
1550
|
+
* Collect candidate observations for a tokenized query, assigning each a
|
|
1551
|
+
* normalized text-match score in (0, 1].
|
|
1552
|
+
*/
|
|
1553
|
+
findObservationCandidates(projectId, tokens) {
|
|
1554
|
+
const longTokens = tokens.filter((t) => t.length >= MIN_TRIGRAM_TOKEN_LENGTH);
|
|
1555
|
+
const shortTokens = tokens.filter((t) => t.length < MIN_TRIGRAM_TOKEN_LENGTH);
|
|
1556
|
+
// Primary path: FTS5 trigram MATCH over the trigram-matchable tokens.
|
|
1557
|
+
if (longTokens.length > 0 && this.ftsEnabled) {
|
|
1558
|
+
const candidates = this.searchObservationsFts(projectId, longTokens, shortTokens);
|
|
1559
|
+
if (candidates.length > 0)
|
|
1560
|
+
return candidates;
|
|
1561
|
+
}
|
|
1562
|
+
else if (!this.ftsEnabled && longTokens.length > 0) {
|
|
1563
|
+
// FTS5 unavailable: LIKE-conjunction scan over the project's rows using
|
|
1564
|
+
// ALL tokens as needles, preserving the pre-FTS substring semantics for
|
|
1565
|
+
// non-token-aligned substrings (e.g. "igrate rollb").
|
|
1566
|
+
const needles = tokens.map((t) => t.toLowerCase());
|
|
1567
|
+
return this.stmtListProjectObsByProject
|
|
1568
|
+
.all(projectId)
|
|
1569
|
+
.filter((row) => {
|
|
1570
|
+
const content = row.content.toLowerCase();
|
|
1571
|
+
return needles.every((needle) => content.includes(needle));
|
|
1572
|
+
})
|
|
1573
|
+
.map((row) => ({ ...row, textScore: 1 }));
|
|
1574
|
+
}
|
|
1575
|
+
else if (longTokens.length === 0) {
|
|
1576
|
+
// All tokens shorter than a trigram: plain LIKE conjunction.
|
|
1577
|
+
const needles = shortTokens.map((t) => t.toLowerCase());
|
|
1578
|
+
return this.stmtListProjectObsByProject
|
|
1579
|
+
.all(projectId)
|
|
1580
|
+
.filter((row) => {
|
|
1581
|
+
const content = row.content.toLowerCase();
|
|
1582
|
+
return needles.every((needle) => content.includes(needle));
|
|
1583
|
+
})
|
|
1584
|
+
.map((row) => ({ ...row, textScore: 1 }));
|
|
1585
|
+
}
|
|
1586
|
+
// Typo-tolerant fallback: nothing matched exactly. Scan the project's
|
|
1587
|
+
// observations (small corpus) and keep near matches by trigram
|
|
1588
|
+
// similarity, which substitutes for the bm25 component in the ranking.
|
|
1589
|
+
return this.stmtListProjectObsByProject
|
|
1590
|
+
.all(projectId)
|
|
1591
|
+
.map((row) => ({ row, similarity: bestTokenTrigramJaccard(tokens, row.content) }))
|
|
1592
|
+
.filter(({ similarity }) => similarity >= TYPO_FALLBACK_MIN_MEAN_SIMILARITY)
|
|
1593
|
+
.map(({ row, similarity }) => ({ ...row, textScore: similarity }));
|
|
1594
|
+
}
|
|
1595
|
+
/**
|
|
1596
|
+
* FTS5 trigram MATCH over `longTokens`, then a complementary LIKE filter
|
|
1597
|
+
* for tokens too short for the trigram tokenizer. Returns an empty array
|
|
1598
|
+
* when the index yields nothing usable (the caller then falls back).
|
|
1599
|
+
*/
|
|
1600
|
+
searchObservationsFts(projectId, longTokens, shortTokens) {
|
|
1601
|
+
const matchQuery = buildFtsMatchQuery(longTokens);
|
|
1602
|
+
if (!matchQuery)
|
|
1603
|
+
return [];
|
|
1604
|
+
let rows;
|
|
1605
|
+
try {
|
|
1606
|
+
rows = this.stmtSearchProjectObsFts?.all(matchQuery, projectId) ?? [];
|
|
1607
|
+
}
|
|
1608
|
+
catch (err) {
|
|
1609
|
+
// Defensive: a MATCH failure should degrade to the fallback path, not
|
|
1610
|
+
// surface as a tool error.
|
|
1611
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1612
|
+
console.warn(`[storage] project-observation FTS query failed: ${msg}`);
|
|
1613
|
+
return [];
|
|
1614
|
+
}
|
|
1615
|
+
let candidates = rows.map((r) => ({
|
|
1616
|
+
id: r.id,
|
|
1617
|
+
project_id: projectId,
|
|
1618
|
+
session_id: r.session_id,
|
|
1379
1619
|
content: r.content,
|
|
1380
1620
|
relevance: r.relevance,
|
|
1381
|
-
|
|
1382
|
-
|
|
1621
|
+
created_at: r.created_at,
|
|
1622
|
+
// bm25() is negative with lower = better in SQLite; 1 - exp(bm25)
|
|
1623
|
+
// maps it to a bounded, higher-is-better text score in (0, 1].
|
|
1624
|
+
textScore: 1 - Math.exp(r.bm25_score),
|
|
1383
1625
|
}));
|
|
1626
|
+
for (const token of shortTokens) {
|
|
1627
|
+
const needle = token.toLowerCase();
|
|
1628
|
+
candidates = candidates.filter((c) => c.content.toLowerCase().includes(needle));
|
|
1629
|
+
}
|
|
1630
|
+
return candidates;
|
|
1631
|
+
}
|
|
1632
|
+
/**
|
|
1633
|
+
* Rebuild the FTS index from project_observations when it is out of sync
|
|
1634
|
+
* (empty or partial relative to the base table). Handles databases created
|
|
1635
|
+
* before the FTS index existed and any drift (e.g. projects deleted by an
|
|
1636
|
+
* older build without FTS cleanup). No-op when the counts already match.
|
|
1637
|
+
*/
|
|
1638
|
+
backfillProjectObservationsFts() {
|
|
1639
|
+
const obsCount = this.stmtCountProjectObs.get()?.count ?? 0;
|
|
1640
|
+
const ftsCount = this.stmtCountProjectObsFts?.get()?.count ?? 0;
|
|
1641
|
+
if (obsCount === ftsCount)
|
|
1642
|
+
return;
|
|
1643
|
+
const tx = this.db.transaction(() => {
|
|
1644
|
+
this.db.exec(`DELETE FROM project_observations_fts`);
|
|
1645
|
+
if (obsCount > 0) {
|
|
1646
|
+
this.db.exec(`INSERT INTO project_observations_fts (content, project_id, obs_id)
|
|
1647
|
+
SELECT content, project_id, id FROM project_observations`);
|
|
1648
|
+
}
|
|
1649
|
+
});
|
|
1650
|
+
tx();
|
|
1651
|
+
}
|
|
1652
|
+
/**
|
|
1653
|
+
* Whether the FTS5 trigram index is active for project observations.
|
|
1654
|
+
* Exposed for diagnostics and tests; false means search is running in
|
|
1655
|
+
* LIKE-only degradation mode.
|
|
1656
|
+
*/
|
|
1657
|
+
isProjectObsFtsEnabled() {
|
|
1658
|
+
return this.ftsEnabled;
|
|
1384
1659
|
}
|
|
1385
1660
|
/**
|
|
1386
1661
|
* Get a single project observation by id. Returns null if not found.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Character-trigram text utilities for observational memory.
|
|
3
|
+
*
|
|
4
|
+
* Shared by the storage layer for:
|
|
5
|
+
* - building FTS5 MATCH queries against the trigram-tokenized index
|
|
6
|
+
* (`buildFtsMatchQuery`),
|
|
7
|
+
* - typo-tolerant search fallback (`bestTokenTrigramJaccard`),
|
|
8
|
+
* - write-time near-duplicate detection (`trigramJaccard`).
|
|
9
|
+
*
|
|
10
|
+
* Pure functions with no SQLite dependency so the logic is unit-testable
|
|
11
|
+
* in isolation.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Minimum token length the SQLite trigram tokenizer can match. Tokens
|
|
15
|
+
* shorter than this cannot be satisfied by an FTS5 MATCH query and must be
|
|
16
|
+
* handled with complementary LIKE filtering (or the LIKE-only search path).
|
|
17
|
+
*/
|
|
18
|
+
export declare const MIN_TRIGRAM_TOKEN_LENGTH = 3;
|
|
19
|
+
/**
|
|
20
|
+
* Per-token floor for {@link bestTokenTrigramJaccard}: every trigram-matchable
|
|
21
|
+
* query token must reach this Jaccard similarity against some content token,
|
|
22
|
+
* otherwise the content is considered not to match the query at all. This
|
|
23
|
+
* mirrors the AND semantics of the FTS MATCH path — every term must be
|
|
24
|
+
* (approximately) present — while still tolerating typos.
|
|
25
|
+
*/
|
|
26
|
+
export declare const TYPO_FALLBACK_MIN_TOKEN_SIMILARITY = 0.2;
|
|
27
|
+
/** Normalize text for trigram comparison: lowercase and collapse whitespace. */
|
|
28
|
+
export declare function normalizeForTrigrams(text: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* Build the set of character trigrams of `text`.
|
|
31
|
+
*
|
|
32
|
+
* Strings shorter than one trigram collapse to a single pseudo-token so
|
|
33
|
+
* identical short strings still compare equal (Jaccard 1.0). Empty input
|
|
34
|
+
* yields an empty set.
|
|
35
|
+
*/
|
|
36
|
+
export declare function trigramSet(text: string): Set<string>;
|
|
37
|
+
/**
|
|
38
|
+
* Jaccard similarity between the character-trigram sets of two strings,
|
|
39
|
+
* in [0, 1]. Returns 0 when either side has no trigrams.
|
|
40
|
+
*/
|
|
41
|
+
export declare function trigramJaccard(a: string, b: string): number;
|
|
42
|
+
/**
|
|
43
|
+
* Typo-tolerant similarity between a whole query and a piece of content:
|
|
44
|
+
* the mean, over query tokens, of the best Jaccard similarity between that
|
|
45
|
+
* token and any single content token.
|
|
46
|
+
*
|
|
47
|
+
* Comparing token-to-token (instead of query-to-full-content) keeps the
|
|
48
|
+
* score robust to sentence length — a one-word typo in a long observation
|
|
49
|
+
* would otherwise be diluted below any useful threshold.
|
|
50
|
+
*
|
|
51
|
+
* Only `queryTokens` of trigram-matchable length are scored; shorter tokens
|
|
52
|
+
* are ignored so they do not drag the mean down for matches they can never
|
|
53
|
+
* express. Returns 0 — no match — when any such token fails to reach
|
|
54
|
+
* TYPO_FALLBACK_MIN_TOKEN_SIMILARITY against every content token (the token
|
|
55
|
+
* is absent, mirroring the AND semantics of the FTS path), or when no query
|
|
56
|
+
* token qualifies.
|
|
57
|
+
*/
|
|
58
|
+
export declare function bestTokenTrigramJaccard(queryTokens: string[], content: string): number;
|
|
59
|
+
/**
|
|
60
|
+
* Build an FTS5 MATCH query from search tokens.
|
|
61
|
+
*
|
|
62
|
+
* Each token becomes a quoted phrase (`"token"`); phrases are joined with
|
|
63
|
+
* AND. With the trigram tokenizer each quoted phrase acts as a
|
|
64
|
+
* case-insensitive substring match, so a multi-token query matches content
|
|
65
|
+
* containing all tokens anywhere. Embedded double quotes are escaped by
|
|
66
|
+
* doubling, which is how FTS5 string literals represent a literal quote.
|
|
67
|
+
*
|
|
68
|
+
* Returns an empty string when no non-empty tokens are supplied — callers
|
|
69
|
+
* must guard against that before running a MATCH query.
|
|
70
|
+
*/
|
|
71
|
+
export declare function buildFtsMatchQuery(tokens: string[]): string;
|
|
72
|
+
//# sourceMappingURL=trigrams.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trigrams.d.ts","sourceRoot":"","sources":["../../../src/server/text/trigrams.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C;;;;;;GAMG;AACH,eAAO,MAAM,kCAAkC,MAAM,CAAC;AAEtD,gFAAgF;AAChF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAWpD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAI3D;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,EAAE,EACrB,OAAO,EAAE,MAAM,GACd,MAAM,CAoBR;AAaD;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAK3D"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Character-trigram text utilities for observational memory.
|
|
3
|
+
*
|
|
4
|
+
* Shared by the storage layer for:
|
|
5
|
+
* - building FTS5 MATCH queries against the trigram-tokenized index
|
|
6
|
+
* (`buildFtsMatchQuery`),
|
|
7
|
+
* - typo-tolerant search fallback (`bestTokenTrigramJaccard`),
|
|
8
|
+
* - write-time near-duplicate detection (`trigramJaccard`).
|
|
9
|
+
*
|
|
10
|
+
* Pure functions with no SQLite dependency so the logic is unit-testable
|
|
11
|
+
* in isolation.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Minimum token length the SQLite trigram tokenizer can match. Tokens
|
|
15
|
+
* shorter than this cannot be satisfied by an FTS5 MATCH query and must be
|
|
16
|
+
* handled with complementary LIKE filtering (or the LIKE-only search path).
|
|
17
|
+
*/
|
|
18
|
+
export const MIN_TRIGRAM_TOKEN_LENGTH = 3;
|
|
19
|
+
/**
|
|
20
|
+
* Per-token floor for {@link bestTokenTrigramJaccard}: every trigram-matchable
|
|
21
|
+
* query token must reach this Jaccard similarity against some content token,
|
|
22
|
+
* otherwise the content is considered not to match the query at all. This
|
|
23
|
+
* mirrors the AND semantics of the FTS MATCH path — every term must be
|
|
24
|
+
* (approximately) present — while still tolerating typos.
|
|
25
|
+
*/
|
|
26
|
+
export const TYPO_FALLBACK_MIN_TOKEN_SIMILARITY = 0.2;
|
|
27
|
+
/** Normalize text for trigram comparison: lowercase and collapse whitespace. */
|
|
28
|
+
export function normalizeForTrigrams(text) {
|
|
29
|
+
return text.toLowerCase().replace(/\s+/g, " ").trim();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Build the set of character trigrams of `text`.
|
|
33
|
+
*
|
|
34
|
+
* Strings shorter than one trigram collapse to a single pseudo-token so
|
|
35
|
+
* identical short strings still compare equal (Jaccard 1.0). Empty input
|
|
36
|
+
* yields an empty set.
|
|
37
|
+
*/
|
|
38
|
+
export function trigramSet(text) {
|
|
39
|
+
const normalized = normalizeForTrigrams(text);
|
|
40
|
+
if (normalized.length === 0)
|
|
41
|
+
return new Set();
|
|
42
|
+
if (normalized.length < MIN_TRIGRAM_TOKEN_LENGTH) {
|
|
43
|
+
return new Set([normalized]);
|
|
44
|
+
}
|
|
45
|
+
const grams = new Set();
|
|
46
|
+
for (let i = 0; i + MIN_TRIGRAM_TOKEN_LENGTH <= normalized.length; i++) {
|
|
47
|
+
grams.add(normalized.slice(i, i + MIN_TRIGRAM_TOKEN_LENGTH));
|
|
48
|
+
}
|
|
49
|
+
return grams;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Jaccard similarity between the character-trigram sets of two strings,
|
|
53
|
+
* in [0, 1]. Returns 0 when either side has no trigrams.
|
|
54
|
+
*/
|
|
55
|
+
export function trigramJaccard(a, b) {
|
|
56
|
+
const setA = trigramSet(a);
|
|
57
|
+
const setB = trigramSet(b);
|
|
58
|
+
return jaccard(setA, setB);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Typo-tolerant similarity between a whole query and a piece of content:
|
|
62
|
+
* the mean, over query tokens, of the best Jaccard similarity between that
|
|
63
|
+
* token and any single content token.
|
|
64
|
+
*
|
|
65
|
+
* Comparing token-to-token (instead of query-to-full-content) keeps the
|
|
66
|
+
* score robust to sentence length — a one-word typo in a long observation
|
|
67
|
+
* would otherwise be diluted below any useful threshold.
|
|
68
|
+
*
|
|
69
|
+
* Only `queryTokens` of trigram-matchable length are scored; shorter tokens
|
|
70
|
+
* are ignored so they do not drag the mean down for matches they can never
|
|
71
|
+
* express. Returns 0 — no match — when any such token fails to reach
|
|
72
|
+
* TYPO_FALLBACK_MIN_TOKEN_SIMILARITY against every content token (the token
|
|
73
|
+
* is absent, mirroring the AND semantics of the FTS path), or when no query
|
|
74
|
+
* token qualifies.
|
|
75
|
+
*/
|
|
76
|
+
export function bestTokenTrigramJaccard(queryTokens, content) {
|
|
77
|
+
const scorable = queryTokens.filter((t) => t.length >= MIN_TRIGRAM_TOKEN_LENGTH);
|
|
78
|
+
if (scorable.length === 0)
|
|
79
|
+
return 0;
|
|
80
|
+
const contentTokens = content.split(/\s+/).filter((t) => t.length > 0);
|
|
81
|
+
const contentTokenGrams = contentTokens.map((token) => trigramSet(token));
|
|
82
|
+
let total = 0;
|
|
83
|
+
for (const queryToken of scorable) {
|
|
84
|
+
let best = 0;
|
|
85
|
+
const queryGrams = trigramSet(queryToken);
|
|
86
|
+
for (const grams of contentTokenGrams) {
|
|
87
|
+
const similarity = jaccard(queryGrams, grams);
|
|
88
|
+
if (similarity > best)
|
|
89
|
+
best = similarity;
|
|
90
|
+
if (best === 1)
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
if (best < TYPO_FALLBACK_MIN_TOKEN_SIMILARITY)
|
|
94
|
+
return 0;
|
|
95
|
+
total += best;
|
|
96
|
+
}
|
|
97
|
+
return total / scorable.length;
|
|
98
|
+
}
|
|
99
|
+
/** Jaccard similarity between two pre-built sets, in [0, 1]. */
|
|
100
|
+
function jaccard(a, b) {
|
|
101
|
+
if (a.size === 0 || b.size === 0)
|
|
102
|
+
return 0;
|
|
103
|
+
let intersection = 0;
|
|
104
|
+
for (const gram of a) {
|
|
105
|
+
if (b.has(gram))
|
|
106
|
+
intersection++;
|
|
107
|
+
}
|
|
108
|
+
const union = a.size + b.size - intersection;
|
|
109
|
+
return union === 0 ? 0 : intersection / union;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Build an FTS5 MATCH query from search tokens.
|
|
113
|
+
*
|
|
114
|
+
* Each token becomes a quoted phrase (`"token"`); phrases are joined with
|
|
115
|
+
* AND. With the trigram tokenizer each quoted phrase acts as a
|
|
116
|
+
* case-insensitive substring match, so a multi-token query matches content
|
|
117
|
+
* containing all tokens anywhere. Embedded double quotes are escaped by
|
|
118
|
+
* doubling, which is how FTS5 string literals represent a literal quote.
|
|
119
|
+
*
|
|
120
|
+
* Returns an empty string when no non-empty tokens are supplied — callers
|
|
121
|
+
* must guard against that before running a MATCH query.
|
|
122
|
+
*/
|
|
123
|
+
export function buildFtsMatchQuery(tokens) {
|
|
124
|
+
return tokens
|
|
125
|
+
.filter((token) => token.length > 0)
|
|
126
|
+
.map((token) => `"${token.replace(/"/g, '""')}"`)
|
|
127
|
+
.join(" AND ");
|
|
128
|
+
}
|