latticesql 2.2.3 → 2.2.4

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 (2) hide show
  1. package/dist/cli.js +64 -3
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -22606,6 +22606,45 @@ function labelColumn(cols) {
22606
22606
  const text = Object.keys(cols).find((c) => !STRUCTURAL.has(c) && !c.endsWith("_id"));
22607
22607
  return text ?? null;
22608
22608
  }
22609
+ var TEXT_COL_RE = /\b(TEXT|VARCHAR|CHAR|CLOB|CHARACTER|STRING|NAME|CITEXT)\b/i;
22610
+ async function requiredTextFileColumns(db) {
22611
+ const out = /* @__PURE__ */ new Set();
22612
+ try {
22613
+ if (db.getDialect() === "postgres") {
22614
+ const rows = await allAsyncOrSync(
22615
+ db.adapter,
22616
+ `SELECT column_name AS name, data_type AS type, is_nullable, column_default AS dflt
22617
+ FROM information_schema.columns
22618
+ WHERE table_name = 'files' AND table_schema = current_schema()`
22619
+ );
22620
+ for (const r of rows) {
22621
+ if (String(r.is_nullable).toUpperCase() === "NO" && r.dflt == null && TEXT_COL_RE.test(String(r.type))) {
22622
+ out.add(String(r.name));
22623
+ }
22624
+ }
22625
+ } else {
22626
+ const rows = await allAsyncOrSync(db.adapter, `PRAGMA table_info("files")`);
22627
+ for (const r of rows) {
22628
+ if (Number(r.notnull) === 1 && r.dflt_value == null && Number(r.pk) === 0 && TEXT_COL_RE.test(String(r.type))) {
22629
+ out.add(String(r.name));
22630
+ }
22631
+ }
22632
+ }
22633
+ } catch {
22634
+ }
22635
+ return out;
22636
+ }
22637
+ async function requiredFileDefaults(db, displayName, id, provided) {
22638
+ const required = await requiredTextFileColumns(db);
22639
+ const label = displayName.trim() || "file";
22640
+ const out = {};
22641
+ for (const col of required) {
22642
+ if (STRUCTURAL.has(col)) continue;
22643
+ if (provided[col] != null) continue;
22644
+ out[col] = /slug/i.test(col) ? fileSlug(displayName, id) : label;
22645
+ }
22646
+ return out;
22647
+ }
22609
22648
  async function buildCatalog(db, descriptions) {
22610
22649
  const out = [];
22611
22650
  for (const name of db.getRegisteredTableNames()) {
@@ -22907,9 +22946,19 @@ async function dispatchIngestRoute(req, res, ctx) {
22907
22946
  await rm(tmp, { force: true }).catch(() => void 0);
22908
22947
  }
22909
22948
  const fileId = crypto.randomUUID();
22910
- const { id: id2 } = await createRow(mctx, "files", {
22949
+ const rawFilePath = typeof req.headers["x-filepath"] === "string" && req.headers["x-filepath"] || "";
22950
+ let realPath = "";
22951
+ if (rawFilePath) {
22952
+ try {
22953
+ realPath = decodeURIComponent(rawFilePath);
22954
+ } catch {
22955
+ realPath = rawFilePath;
22956
+ }
22957
+ }
22958
+ const uploadRow = {
22911
22959
  id: fileId,
22912
22960
  ...fileIdentity(name2, fileId),
22961
+ ...realPath ? { path: realPath } : {},
22913
22962
  original_name: name2,
22914
22963
  mime: mime2,
22915
22964
  size_bytes: buf.length,
@@ -22917,6 +22966,10 @@ async function dispatchIngestRoute(req, res, ctx) {
22917
22966
  description: describe(result.text, mime2, name2),
22918
22967
  extraction_status: result.skip ? "skipped" : "extracted",
22919
22968
  ...blob ? { ref_kind: "blob", blob_path: blob.blob_path, sha256: blob.sha256 } : {}
22969
+ };
22970
+ const { id: id2 } = await createRow(mctx, "files", {
22971
+ ...await requiredFileDefaults(ctx.db, name2, fileId, uploadRow),
22972
+ ...uploadRow
22920
22973
  });
22921
22974
  let suggestedLinks = [];
22922
22975
  if (!result.skip) {
@@ -22961,7 +23014,7 @@ async function dispatchIngestRoute(req, res, ctx) {
22961
23014
  }
22962
23015
  }
22963
23016
  const textFileId = crypto.randomUUID();
22964
- const { id: id2 } = await createRow(mctx, "files", {
23017
+ const textRow = {
22965
23018
  id: textFileId,
22966
23019
  ...fileIdentity(title, textFileId),
22967
23020
  original_name: title,
@@ -22971,6 +23024,10 @@ async function dispatchIngestRoute(req, res, ctx) {
22971
23024
  description: describe(content, mime2, title),
22972
23025
  extraction_status: "extracted",
22973
23026
  ...sourceUrl ? { ref_kind: "cloud_ref", ref_uri: sourceUrl, ref_provider: "web" } : {}
23027
+ };
23028
+ const { id: id2 } = await createRow(mctx, "files", {
23029
+ ...await requiredFileDefaults(ctx.db, title, textFileId, textRow),
23030
+ ...textRow
22974
23031
  });
22975
23032
  const suggestedLinks = await enrichOrFail(mctx, ctx.db, id2, content, title, ctx, res);
22976
23033
  if (suggestedLinks === null) return true;
@@ -23002,7 +23059,7 @@ async function dispatchIngestRoute(req, res, ctx) {
23002
23059
  const name = basename10(abs);
23003
23060
  const mime = mimeFor(name);
23004
23061
  const localFileId = crypto.randomUUID();
23005
- const { id } = await createRow(mctx, "files", {
23062
+ const localRow = {
23006
23063
  id: localFileId,
23007
23064
  ...fileIdentity(name, localFileId),
23008
23065
  path: abs,
@@ -23010,6 +23067,10 @@ async function dispatchIngestRoute(req, res, ctx) {
23010
23067
  mime,
23011
23068
  size_bytes: size,
23012
23069
  extraction_status: "pending"
23070
+ };
23071
+ const { id } = await createRow(mctx, "files", {
23072
+ ...await requiredFileDefaults(ctx.db, name, localFileId, localRow),
23073
+ ...localRow
23013
23074
  });
23014
23075
  try {
23015
23076
  const result = await extractSource(ctx.db, abs, mime, name);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "latticesql",
3
- "version": "2.2.3",
3
+ "version": "2.2.4",
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",