latticesql 2.2.3 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +84 -10
- package/dist/index.cjs +10 -1
- package/dist/index.js +10 -1
- package/package.json +8 -9
package/dist/cli.js
CHANGED
|
@@ -21571,10 +21571,14 @@ var textDecoder = new TextDecoder("utf-8");
|
|
|
21571
21571
|
function decodeUtf8(bytes) {
|
|
21572
21572
|
return textDecoder.decode(bytes);
|
|
21573
21573
|
}
|
|
21574
|
-
async function
|
|
21574
|
+
async function loadParser(specifier) {
|
|
21575
21575
|
try {
|
|
21576
21576
|
return await import(specifier);
|
|
21577
|
-
} catch {
|
|
21577
|
+
} catch (err) {
|
|
21578
|
+
console.error(
|
|
21579
|
+
`[latticesql] document parser "${specifier}" failed to load \u2014 document extraction is degraded (likely a broken/partial install or incompatible build). Reinstall dependencies (\`npm install\`). Cause:`,
|
|
21580
|
+
err
|
|
21581
|
+
);
|
|
21578
21582
|
return null;
|
|
21579
21583
|
}
|
|
21580
21584
|
}
|
|
@@ -21716,7 +21720,7 @@ function stripHtml(html) {
|
|
|
21716
21720
|
return text.replace(/[ \t\f\r]+/g, " ").replace(/ *\n */g, "\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
21717
21721
|
}
|
|
21718
21722
|
async function unzip(path2) {
|
|
21719
|
-
const fflate = await
|
|
21723
|
+
const fflate = await loadParser("fflate");
|
|
21720
21724
|
if (!fflate || typeof fflate.unzipSync !== "function") return null;
|
|
21721
21725
|
try {
|
|
21722
21726
|
const buf = await readFile(path2);
|
|
@@ -21735,7 +21739,7 @@ async function unzip(path2) {
|
|
|
21735
21739
|
}
|
|
21736
21740
|
}
|
|
21737
21741
|
async function extractDocx(path2) {
|
|
21738
|
-
const mod = await
|
|
21742
|
+
const mod = await loadParser("mammoth");
|
|
21739
21743
|
const lib = mod?.default ?? mod;
|
|
21740
21744
|
if (!lib || typeof lib.extractRawText !== "function") return null;
|
|
21741
21745
|
try {
|
|
@@ -21746,7 +21750,7 @@ async function extractDocx(path2) {
|
|
|
21746
21750
|
}
|
|
21747
21751
|
}
|
|
21748
21752
|
async function extractDoc(path2) {
|
|
21749
|
-
const mod = await
|
|
21753
|
+
const mod = await loadParser(
|
|
21750
21754
|
"word-extractor"
|
|
21751
21755
|
);
|
|
21752
21756
|
const Ctor = mod && "default" in mod ? mod.default : mod;
|
|
@@ -21759,7 +21763,7 @@ async function extractDoc(path2) {
|
|
|
21759
21763
|
}
|
|
21760
21764
|
}
|
|
21761
21765
|
async function extractPdf(path2) {
|
|
21762
|
-
const unpdf = await
|
|
21766
|
+
const unpdf = await loadParser("unpdf");
|
|
21763
21767
|
if (!unpdf || typeof unpdf.getDocumentProxy !== "function") return null;
|
|
21764
21768
|
try {
|
|
21765
21769
|
const buf = await readFile(path2);
|
|
@@ -22461,8 +22465,17 @@ function titleFromUrl(rawUrl) {
|
|
|
22461
22465
|
}
|
|
22462
22466
|
}
|
|
22463
22467
|
async function sniffMime(body) {
|
|
22468
|
+
let ft;
|
|
22469
|
+
try {
|
|
22470
|
+
ft = await import("file-type");
|
|
22471
|
+
} catch (err) {
|
|
22472
|
+
console.error(
|
|
22473
|
+
`[latticesql] mime sniffer "file-type" failed to load \u2014 crawl mime detection is degraded (likely a broken/partial install). Reinstall dependencies (\`npm install\`). Cause:`,
|
|
22474
|
+
err
|
|
22475
|
+
);
|
|
22476
|
+
return "";
|
|
22477
|
+
}
|
|
22464
22478
|
try {
|
|
22465
|
-
const ft = await import("file-type");
|
|
22466
22479
|
const result = await ft.fileTypeFromBuffer(body);
|
|
22467
22480
|
return result?.mime ?? "";
|
|
22468
22481
|
} catch {
|
|
@@ -22606,6 +22619,45 @@ function labelColumn(cols) {
|
|
|
22606
22619
|
const text = Object.keys(cols).find((c) => !STRUCTURAL.has(c) && !c.endsWith("_id"));
|
|
22607
22620
|
return text ?? null;
|
|
22608
22621
|
}
|
|
22622
|
+
var TEXT_COL_RE = /\b(TEXT|VARCHAR|CHAR|CLOB|CHARACTER|STRING|NAME|CITEXT)\b/i;
|
|
22623
|
+
async function requiredTextFileColumns(db) {
|
|
22624
|
+
const out = /* @__PURE__ */ new Set();
|
|
22625
|
+
try {
|
|
22626
|
+
if (db.getDialect() === "postgres") {
|
|
22627
|
+
const rows = await allAsyncOrSync(
|
|
22628
|
+
db.adapter,
|
|
22629
|
+
`SELECT column_name AS name, data_type AS type, is_nullable, column_default AS dflt
|
|
22630
|
+
FROM information_schema.columns
|
|
22631
|
+
WHERE table_name = 'files' AND table_schema = current_schema()`
|
|
22632
|
+
);
|
|
22633
|
+
for (const r of rows) {
|
|
22634
|
+
if (String(r.is_nullable).toUpperCase() === "NO" && r.dflt == null && TEXT_COL_RE.test(String(r.type))) {
|
|
22635
|
+
out.add(String(r.name));
|
|
22636
|
+
}
|
|
22637
|
+
}
|
|
22638
|
+
} else {
|
|
22639
|
+
const rows = await allAsyncOrSync(db.adapter, `PRAGMA table_info("files")`);
|
|
22640
|
+
for (const r of rows) {
|
|
22641
|
+
if (Number(r.notnull) === 1 && r.dflt_value == null && Number(r.pk) === 0 && TEXT_COL_RE.test(String(r.type))) {
|
|
22642
|
+
out.add(String(r.name));
|
|
22643
|
+
}
|
|
22644
|
+
}
|
|
22645
|
+
}
|
|
22646
|
+
} catch {
|
|
22647
|
+
}
|
|
22648
|
+
return out;
|
|
22649
|
+
}
|
|
22650
|
+
async function requiredFileDefaults(db, displayName, id, provided) {
|
|
22651
|
+
const required = await requiredTextFileColumns(db);
|
|
22652
|
+
const label = displayName.trim() || "file";
|
|
22653
|
+
const out = {};
|
|
22654
|
+
for (const col of required) {
|
|
22655
|
+
if (STRUCTURAL.has(col)) continue;
|
|
22656
|
+
if (provided[col] != null) continue;
|
|
22657
|
+
out[col] = /slug/i.test(col) ? fileSlug(displayName, id) : label;
|
|
22658
|
+
}
|
|
22659
|
+
return out;
|
|
22660
|
+
}
|
|
22609
22661
|
async function buildCatalog(db, descriptions) {
|
|
22610
22662
|
const out = [];
|
|
22611
22663
|
for (const name of db.getRegisteredTableNames()) {
|
|
@@ -22907,9 +22959,19 @@ async function dispatchIngestRoute(req, res, ctx) {
|
|
|
22907
22959
|
await rm(tmp, { force: true }).catch(() => void 0);
|
|
22908
22960
|
}
|
|
22909
22961
|
const fileId = crypto.randomUUID();
|
|
22910
|
-
const
|
|
22962
|
+
const rawFilePath = typeof req.headers["x-filepath"] === "string" && req.headers["x-filepath"] || "";
|
|
22963
|
+
let realPath = "";
|
|
22964
|
+
if (rawFilePath) {
|
|
22965
|
+
try {
|
|
22966
|
+
realPath = decodeURIComponent(rawFilePath);
|
|
22967
|
+
} catch {
|
|
22968
|
+
realPath = rawFilePath;
|
|
22969
|
+
}
|
|
22970
|
+
}
|
|
22971
|
+
const uploadRow = {
|
|
22911
22972
|
id: fileId,
|
|
22912
22973
|
...fileIdentity(name2, fileId),
|
|
22974
|
+
...realPath ? { path: realPath } : {},
|
|
22913
22975
|
original_name: name2,
|
|
22914
22976
|
mime: mime2,
|
|
22915
22977
|
size_bytes: buf.length,
|
|
@@ -22917,6 +22979,10 @@ async function dispatchIngestRoute(req, res, ctx) {
|
|
|
22917
22979
|
description: describe(result.text, mime2, name2),
|
|
22918
22980
|
extraction_status: result.skip ? "skipped" : "extracted",
|
|
22919
22981
|
...blob ? { ref_kind: "blob", blob_path: blob.blob_path, sha256: blob.sha256 } : {}
|
|
22982
|
+
};
|
|
22983
|
+
const { id: id2 } = await createRow(mctx, "files", {
|
|
22984
|
+
...await requiredFileDefaults(ctx.db, name2, fileId, uploadRow),
|
|
22985
|
+
...uploadRow
|
|
22920
22986
|
});
|
|
22921
22987
|
let suggestedLinks = [];
|
|
22922
22988
|
if (!result.skip) {
|
|
@@ -22961,7 +23027,7 @@ async function dispatchIngestRoute(req, res, ctx) {
|
|
|
22961
23027
|
}
|
|
22962
23028
|
}
|
|
22963
23029
|
const textFileId = crypto.randomUUID();
|
|
22964
|
-
const
|
|
23030
|
+
const textRow = {
|
|
22965
23031
|
id: textFileId,
|
|
22966
23032
|
...fileIdentity(title, textFileId),
|
|
22967
23033
|
original_name: title,
|
|
@@ -22971,6 +23037,10 @@ async function dispatchIngestRoute(req, res, ctx) {
|
|
|
22971
23037
|
description: describe(content, mime2, title),
|
|
22972
23038
|
extraction_status: "extracted",
|
|
22973
23039
|
...sourceUrl ? { ref_kind: "cloud_ref", ref_uri: sourceUrl, ref_provider: "web" } : {}
|
|
23040
|
+
};
|
|
23041
|
+
const { id: id2 } = await createRow(mctx, "files", {
|
|
23042
|
+
...await requiredFileDefaults(ctx.db, title, textFileId, textRow),
|
|
23043
|
+
...textRow
|
|
22974
23044
|
});
|
|
22975
23045
|
const suggestedLinks = await enrichOrFail(mctx, ctx.db, id2, content, title, ctx, res);
|
|
22976
23046
|
if (suggestedLinks === null) return true;
|
|
@@ -23002,7 +23072,7 @@ async function dispatchIngestRoute(req, res, ctx) {
|
|
|
23002
23072
|
const name = basename10(abs);
|
|
23003
23073
|
const mime = mimeFor(name);
|
|
23004
23074
|
const localFileId = crypto.randomUUID();
|
|
23005
|
-
const
|
|
23075
|
+
const localRow = {
|
|
23006
23076
|
id: localFileId,
|
|
23007
23077
|
...fileIdentity(name, localFileId),
|
|
23008
23078
|
path: abs,
|
|
@@ -23010,6 +23080,10 @@ async function dispatchIngestRoute(req, res, ctx) {
|
|
|
23010
23080
|
mime,
|
|
23011
23081
|
size_bytes: size,
|
|
23012
23082
|
extraction_status: "pending"
|
|
23083
|
+
};
|
|
23084
|
+
const { id } = await createRow(mctx, "files", {
|
|
23085
|
+
...await requiredFileDefaults(ctx.db, name, localFileId, localRow),
|
|
23086
|
+
...localRow
|
|
23013
23087
|
});
|
|
23014
23088
|
try {
|
|
23015
23089
|
const result = await extractSource(ctx.db, abs, mime, name);
|
package/dist/index.cjs
CHANGED
|
@@ -9607,8 +9607,17 @@ function titleFromUrl(rawUrl) {
|
|
|
9607
9607
|
}
|
|
9608
9608
|
}
|
|
9609
9609
|
async function sniffMime(body) {
|
|
9610
|
+
let ft;
|
|
9611
|
+
try {
|
|
9612
|
+
ft = await import("file-type");
|
|
9613
|
+
} catch (err) {
|
|
9614
|
+
console.error(
|
|
9615
|
+
`[latticesql] mime sniffer "file-type" failed to load \u2014 crawl mime detection is degraded (likely a broken/partial install). Reinstall dependencies (\`npm install\`). Cause:`,
|
|
9616
|
+
err
|
|
9617
|
+
);
|
|
9618
|
+
return "";
|
|
9619
|
+
}
|
|
9610
9620
|
try {
|
|
9611
|
-
const ft = await import("file-type");
|
|
9612
9621
|
const result = await ft.fileTypeFromBuffer(body);
|
|
9613
9622
|
return result?.mime ?? "";
|
|
9614
9623
|
} catch {
|
package/dist/index.js
CHANGED
|
@@ -9472,8 +9472,17 @@ function titleFromUrl(rawUrl) {
|
|
|
9472
9472
|
}
|
|
9473
9473
|
}
|
|
9474
9474
|
async function sniffMime(body) {
|
|
9475
|
+
let ft;
|
|
9476
|
+
try {
|
|
9477
|
+
ft = await import("file-type");
|
|
9478
|
+
} catch (err) {
|
|
9479
|
+
console.error(
|
|
9480
|
+
`[latticesql] mime sniffer "file-type" failed to load \u2014 crawl mime detection is degraded (likely a broken/partial install). Reinstall dependencies (\`npm install\`). Cause:`,
|
|
9481
|
+
err
|
|
9482
|
+
);
|
|
9483
|
+
return "";
|
|
9484
|
+
}
|
|
9475
9485
|
try {
|
|
9476
|
-
const ft = await import("file-type");
|
|
9477
9486
|
const result = await ft.fileTypeFromBuffer(body);
|
|
9478
9487
|
return result?.mime ?? "";
|
|
9479
9488
|
} catch {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "latticesql",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "Persistent structured memory for AI agent systems — pluggable SQLite or Postgres backend, LLM context bridge",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -43,10 +43,16 @@
|
|
|
43
43
|
"prepublishOnly": "npm run check:generic && npm run build && npm run typecheck && npm test"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
+
"@anthropic-ai/sdk": "^0.71.2",
|
|
46
47
|
"@mozilla/readability": "^0.5.0",
|
|
47
48
|
"@scarf/scarf": "^1.4.0",
|
|
49
|
+
"fflate": "^0.8.3",
|
|
50
|
+
"file-type": "^19.6.0",
|
|
48
51
|
"jsdom": "^25.0.1",
|
|
52
|
+
"mammoth": "^1.12.0",
|
|
53
|
+
"unpdf": "^1.6.2",
|
|
49
54
|
"uuid": "^13.0.0",
|
|
55
|
+
"word-extractor": "^1.0.4",
|
|
50
56
|
"yaml": "^2.8.3"
|
|
51
57
|
},
|
|
52
58
|
"scarfSettings": {
|
|
@@ -56,18 +62,11 @@
|
|
|
56
62
|
"better-sqlite3": ">=11 <13"
|
|
57
63
|
},
|
|
58
64
|
"optionalDependencies": {
|
|
59
|
-
"@anthropic-ai/sdk": "^0.71.2",
|
|
60
|
-
"fflate": "^0.8.3",
|
|
61
|
-
"file-type": "^19.6.0",
|
|
62
|
-
"mammoth": "^1.12.0",
|
|
63
65
|
"pg": "^8.11.0",
|
|
64
66
|
"playwright": "^1.48.0",
|
|
65
|
-
"sharp": "^0.33.5"
|
|
66
|
-
"unpdf": "^1.6.2",
|
|
67
|
-
"word-extractor": "^1.0.4"
|
|
67
|
+
"sharp": "^0.33.5"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
|
-
"@anthropic-ai/sdk": "^0.71.0",
|
|
71
70
|
"@eslint/js": "^9.0.0",
|
|
72
71
|
"@playwright/test": "^1.48.0",
|
|
73
72
|
"@types/better-sqlite3": "^7.6.12",
|