@cerefox/memory 1.15.2 → 1.15.3

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.
@@ -5318,7 +5318,7 @@ var init_cli_core = __esm(() => {
5318
5318
  });
5319
5319
 
5320
5320
  // src/meta.ts
5321
- var PKG_VERSION = "1.15.2";
5321
+ var PKG_VERSION = "1.15.3";
5322
5322
  var init_meta = () => {};
5323
5323
 
5324
5324
  // ../../_shared/config/paths.ts
@@ -23799,7 +23799,7 @@ var init__utils = __esm(() => {
23799
23799
  });
23800
23800
 
23801
23801
  // ../../_shared/server-assets/index.ts
23802
- import { existsSync as existsSync5 } from "node:fs";
23802
+ import { existsSync as existsSync5, readFileSync as readFileSync5 } from "node:fs";
23803
23803
  import { dirname as dirname2, join as join5 } from "node:path";
23804
23804
  import { fileURLToPath } from "node:url";
23805
23805
  import { cwd as processCwd2 } from "node:process";
@@ -23845,7 +23845,20 @@ function resolveServerAssets(opts = {}) {
23845
23845
  }
23846
23846
  return sourceServerAssets(join5(here, "..", ".."));
23847
23847
  }
23848
- var init_server_assets = () => {};
23848
+ function bundledSchemaVersion(opts = {}) {
23849
+ try {
23850
+ const assets = resolveServerAssets(opts);
23851
+ if (!existsSync5(assets.schemaFile))
23852
+ return null;
23853
+ return readFileSync5(assets.schemaFile, "utf8").match(SCHEMA_VERSION_RE)?.[1] ?? null;
23854
+ } catch {
23855
+ return null;
23856
+ }
23857
+ }
23858
+ var SCHEMA_VERSION_RE;
23859
+ var init_server_assets = __esm(() => {
23860
+ SCHEMA_VERSION_RE = /^--\s*@version:\s*(\S+)/m;
23861
+ });
23849
23862
 
23850
23863
  // ../../node_modules/.bun/postgres@3.4.9/node_modules/postgres/src/query.js
23851
23864
  function cachedError(xs) {
@@ -26142,7 +26155,7 @@ var init__projects = __esm(() => {
26142
26155
  });
26143
26156
 
26144
26157
  // src/cli/util/bundled-docs.ts
26145
- import { existsSync as existsSync8, readdirSync as readdirSync3, readFileSync as readFileSync6, statSync } from "node:fs";
26158
+ import { existsSync as existsSync8, readdirSync as readdirSync3, readFileSync as readFileSync7, statSync } from "node:fs";
26146
26159
  import { dirname as dirname3, join as join7, resolve as resolve2 } from "node:path";
26147
26160
  import { fileURLToPath as fileURLToPath2 } from "node:url";
26148
26161
  function findPackageRoot() {
@@ -26151,7 +26164,7 @@ function findPackageRoot() {
26151
26164
  const pkgJson = join7(dir, "package.json");
26152
26165
  if (existsSync8(pkgJson)) {
26153
26166
  try {
26154
- const parsed = JSON.parse(readFileSync6(pkgJson, "utf8"));
26167
+ const parsed = JSON.parse(readFileSync7(pkgJson, "utf8"));
26155
26168
  if (parsed.name === "@cerefox/memory")
26156
26169
  return dir;
26157
26170
  } catch {}
@@ -26226,7 +26239,7 @@ function readBundledDoc(topic) {
26226
26239
  return {
26227
26240
  topic: entry.topic,
26228
26241
  path: entry.path,
26229
- content: readFileSync6(entry.path, "utf8")
26242
+ content: readFileSync7(entry.path, "utf8")
26230
26243
  };
26231
26244
  }
26232
26245
  var PACKAGE_ROOT;
@@ -26235,7 +26248,7 @@ var init_bundled_docs = __esm(() => {
26235
26248
  });
26236
26249
 
26237
26250
  // ../../_shared/ef-meta/index.ts
26238
- var EF_VERSION = "1.15.2", CEREFOX_VERSION = "1.15.2", EF_LAST_CHANGED = "1.15.2";
26251
+ var EF_VERSION = "1.15.3", CEREFOX_VERSION = "1.15.3", EF_LAST_CHANGED = "1.15.3";
26239
26252
  var init_ef_meta = () => {};
26240
26253
 
26241
26254
  // ../../_shared/compatibility/index.ts
@@ -26380,6 +26393,7 @@ __export(exports_onnx_embedder, {
26380
26393
  ONNX_MODEL_ID: () => ONNX_MODEL_ID,
26381
26394
  ONNX_MODEL_NAME: () => ONNX_MODEL_NAME,
26382
26395
  buildPrefixedInputs: () => buildPrefixedInputs,
26396
+ isModelCached: () => isModelCached,
26383
26397
  nomicPrefix: () => nomicPrefix,
26384
26398
  onnxEmbed: () => onnxEmbed,
26385
26399
  warmup: () => warmup
@@ -26394,6 +26408,9 @@ function buildPrefixedInputs(texts, role) {
26394
26408
  const p = nomicPrefix(role);
26395
26409
  return texts.map((t) => p + t);
26396
26410
  }
26411
+ function isModelCached(dir = getCacheDir()) {
26412
+ return MODEL_FILES.every((f) => existsSync10(join9(dir, f)));
26413
+ }
26397
26414
  function getCacheDir() {
26398
26415
  const env = globalThis.process?.env ?? {};
26399
26416
  if (env.CEREFOX_MODELS_DIR)
@@ -26436,6 +26453,12 @@ async function ensurePipeline() {
26436
26453
  return pipelinePromise;
26437
26454
  pipelinePromise = (async () => {
26438
26455
  const transformers = await loadTransformers();
26456
+ if (isModelCached()) {
26457
+ const pipe = await transformers.pipeline("feature-extraction", ONNX_MODEL_ID, {
26458
+ dtype: ONNX_MODEL_DTYPE
26459
+ });
26460
+ return pipe;
26461
+ }
26439
26462
  const mb = ONNX_MODEL_APPROX_MB;
26440
26463
  const fmt = (s) => s < 60 ? `${s}s` : `${Math.round(s / 60)}m`;
26441
26464
  process.stderr.write(`[cerefox-embed] loading "${ONNX_MODEL_NAME}" from HuggingFace (~${mb} MB; est. ${fmt(Math.round(mb * 8 / 50))}-${fmt(Math.round(mb * 8 / 10))} at 50-10 Mbps; first-run only)…
@@ -26559,8 +26582,15 @@ async function onnxEmbed(texts, role) {
26559
26582
  }
26560
26583
  return vectors;
26561
26584
  }
26562
- var ONNX_MODEL_ID = "nomic-ai/nomic-embed-text-v1.5", ONNX_MODEL_NAME = "nomic-embed-text-v1.5", ONNX_MODEL_DTYPE = "q8", ONNX_MODEL_DIM = 768, ONNX_MODEL_APPROX_MB = 130, transformersModule = null, pipelinePromise = null, DEFAULT_ONNX_BATCH = 4;
26563
- var init_onnx_embedder = () => {};
26585
+ var ONNX_MODEL_ID = "nomic-ai/nomic-embed-text-v1.5", ONNX_MODEL_NAME = "nomic-embed-text-v1.5", ONNX_MODEL_DTYPE = "q8", ONNX_MODEL_DIM = 768, ONNX_MODEL_APPROX_MB = 130, MODEL_FILES, transformersModule = null, pipelinePromise = null, DEFAULT_ONNX_BATCH = 4;
26586
+ var init_onnx_embedder = __esm(() => {
26587
+ MODEL_FILES = [
26588
+ "config.json",
26589
+ "tokenizer.json",
26590
+ "tokenizer_config.json",
26591
+ `onnx/model_quantized.onnx`
26592
+ ].map((f) => join9(ONNX_MODEL_ID, f));
26593
+ });
26564
26594
 
26565
26595
  // ../../_shared/embeddings/index.ts
26566
26596
  function openaiEmbeddingConfig() {
@@ -51652,6 +51682,7 @@ async function handler6(supabase, args, ctx) {
51652
51682
  throw new McpInvalidParams('metadata must be a JSON object of key/value pairs, e.g. {"type":"note"} — not a string, number, or array');
51653
51683
  }
51654
51684
  const update_if_exists = args.update_if_exists ?? false;
51685
+ const overrideNote = args.update_if_exists === false ? " Note: update_if_exists flag was overridden by document_id." : "";
51655
51686
  const author = callerIdentity(args) ?? DEFAULT_IDENTITY;
51656
51687
  const author_type = "agent";
51657
51688
  const expected_content_hash = args.expected_content_hash?.trim() || null;
@@ -51677,7 +51708,7 @@ async function handler6(supabase, args, ctx) {
51677
51708
  throw new McpInvalidParams(`Document ${document_id} ("${existingDoc.title}") is soft-deleted (in the trash). ` + `A trashed document cannot be updated — restore it first with ` + `cerefox_restore_document, then retry, or create a new document instead.`);
51678
51709
  }
51679
51710
  if (existingDoc.content_hash === contentHash) {
51680
- const note = update_if_exists ? "" : " Note: update_if_exists flag was overridden by document_id.";
51711
+ const note = overrideNote;
51681
51712
  return `Document already up-to-date: "${existingDoc.title}" (id: ${existingDoc.id}). Content hash unchanged (${contentHash}).${note}`;
51682
51713
  }
51683
51714
  if (!last_write_wins && expected_content_hash && expected_content_hash !== existingDoc.content_hash) {
@@ -51727,7 +51758,7 @@ async function handler6(supabase, args, ctx) {
51727
51758
  } else if (project_name) {
51728
51759
  await ensureDocumentInProject(supabase, existingDoc.id, project_name, { author, authorType: author_type });
51729
51760
  }
51730
- const note = update_if_exists ? "" : " Note: update_if_exists flag was overridden by document_id.";
51761
+ const note = overrideNote;
51731
51762
  return `Document updated: "${title}" (id: ${existingDoc.id}), ${chunks.length} chunk(s), ${totalChars} chars. New content_hash: ${contentHash}.${note}${escapedContentNote(content)}`;
51732
51763
  }
51733
51764
  if (update_if_exists) {
@@ -53467,7 +53498,7 @@ var require_cli_progress = __commonJS(function(exports, module) {
53467
53498
  });
53468
53499
 
53469
53500
  // src/cli/commands/sync-self-docs.ts
53470
- import { readFileSync as readFileSync12 } from "node:fs";
53501
+ import { readFileSync as readFileSync13 } from "node:fs";
53471
53502
  import { basename as basename4, extname as extname5 } from "node:path";
53472
53503
  async function runSyncSelfDocs(options = {}) {
53473
53504
  const project = options.project ?? "_cerefox-self-docs";
@@ -53494,7 +53525,7 @@ async function runSyncSelfDocs(options = {}) {
53494
53525
  const authorType = resolveAuthorType("agent");
53495
53526
  const outcomes = [];
53496
53527
  for (const doc of docs) {
53497
- const content = readFileSync12(doc.path, "utf8");
53528
+ const content = readFileSync13(doc.path, "utf8");
53498
53529
  const m = content.match(/^#\s+(.+)$/m);
53499
53530
  const title = m ? m[1].trim() : basename4(doc.path, extname5(doc.path));
53500
53531
  try {
@@ -63058,7 +63089,6 @@ var init_stdio2 = __esm(() => {
63058
63089
  });
63059
63090
 
63060
63091
  // src/server.ts
63061
- import { existsSync as existsSync13, readFileSync as readFileSync14 } from "node:fs";
63062
63092
  function buildServer() {
63063
63093
  const settings = loadSettings();
63064
63094
  if (!settings.supabaseUrl || !settings.supabaseKey) {
@@ -63109,14 +63139,7 @@ async function warnIfSchemaVersionMismatch(supabase) {
63109
63139
  const deployed = typeof data === "string" ? data : null;
63110
63140
  if (!deployed)
63111
63141
  return;
63112
- let bundled = null;
63113
- try {
63114
- const assets = resolveServerAssets();
63115
- if (existsSync13(assets.schemaFile)) {
63116
- const m = readFileSync14(assets.schemaFile, "utf8").match(SCHEMA_VERSION_RE2);
63117
- bundled = m ? m[1] : null;
63118
- }
63119
- } catch {}
63142
+ const bundled = bundledSchemaVersion();
63120
63143
  if (!bundled)
63121
63144
  return;
63122
63145
  if (compareSemver(deployed, bundled) < 0) {
@@ -63125,7 +63148,7 @@ async function warnIfSchemaVersionMismatch(supabase) {
63125
63148
  }
63126
63149
  } catch {}
63127
63150
  }
63128
- var SERVER_NAME = "cerefox", SCHEMA_VERSION_RE2;
63151
+ var SERVER_NAME = "cerefox";
63129
63152
  var init_server3 = __esm(() => {
63130
63153
  init_server2();
63131
63154
  init_stdio2();
@@ -63136,7 +63159,6 @@ var init_server3 = __esm(() => {
63136
63159
  init_server_assets();
63137
63160
  init_mcp_tools();
63138
63161
  init_meta();
63139
- SCHEMA_VERSION_RE2 = /^--\s*@version:\s*(\S+)/m;
63140
63162
  });
63141
63163
 
63142
63164
  // src/bin/cerefox.ts
@@ -67439,7 +67461,7 @@ import { readdirSync as readdirSync2 } from "node:fs";
67439
67461
 
67440
67462
  // ../../_shared/db-deploy/index.ts
67441
67463
  init_src();
67442
- import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync } from "node:fs";
67464
+ import { existsSync as existsSync6, readFileSync as readFileSync6, readdirSync } from "node:fs";
67443
67465
  import { join as join6 } from "node:path";
67444
67466
  var RESET_SQL = `
67445
67467
  DROP TABLE IF EXISTS cerefox_chunks CASCADE;
@@ -67462,8 +67484,8 @@ function listMigrationFiles(migrationsDir) {
67462
67484
  return readdirSync(migrationsDir).filter((n) => n.endsWith(".sql")).sort();
67463
67485
  }
67464
67486
  function buildDeploySteps(assets, opts = {}) {
67465
- const schemaSql = readFileSync5(assets.schemaFile, "utf8");
67466
- const rpcsSql = readFileSync5(assets.rpcsFile, "utf8");
67487
+ const schemaSql = readFileSync6(assets.schemaFile, "utf8");
67488
+ const rpcsSql = readFileSync6(assets.rpcsFile, "utf8");
67467
67489
  const steps = [];
67468
67490
  if (opts.reset) {
67469
67491
  steps.push({ label: "Reset: drop existing Cerefox objects", sql: RESET_SQL });
@@ -67575,7 +67597,7 @@ async function runDbMigrate(opts) {
67575
67597
  }
67576
67598
  const applied = [];
67577
67599
  for (const f of pending) {
67578
- const body = readFileSync5(join6(opts.assets.migrationsDir, f), "utf8");
67600
+ const body = readFileSync6(join6(opts.assets.migrationsDir, f), "utf8");
67579
67601
  log(`Applying ${f}…`);
67580
67602
  try {
67581
67603
  await sql.begin(async (tx) => {
@@ -67605,7 +67627,7 @@ async function applyRpcs(opts) {
67605
67627
  log("Refresh RPCs (rpcs.sql)…");
67606
67628
  if (opts.dryRun)
67607
67629
  return { ok: true };
67608
- const rpcsSql = readFileSync5(opts.assets.rpcsFile, "utf8");
67630
+ const rpcsSql = readFileSync6(opts.assets.rpcsFile, "utf8");
67609
67631
  const sql = src_default(opts.dbUrl, { prepare: false, onnotice: () => {} });
67610
67632
  try {
67611
67633
  await sql.unsafe(rpcsSql);
@@ -71723,7 +71745,7 @@ init_config();
71723
71745
  init_config();
71724
71746
  init_compatibility();
71725
71747
  init_server_assets();
71726
- import { existsSync as existsSync11, readFileSync as readFileSync8, realpathSync, statSync as statSync2 } from "node:fs";
71748
+ import { existsSync as existsSync11, readFileSync as readFileSync9, realpathSync, statSync as statSync2 } from "node:fs";
71727
71749
  import { homedir as homedir7 } from "node:os";
71728
71750
  import { join as join10 } from "node:path";
71729
71751
 
@@ -71733,7 +71755,7 @@ import {
71733
71755
  existsSync as existsSync9,
71734
71756
  mkdirSync as mkdirSync3,
71735
71757
  openSync,
71736
- readFileSync as readFileSync7,
71758
+ readFileSync as readFileSync8,
71737
71759
  rmSync,
71738
71760
  writeFileSync as writeFileSync4
71739
71761
  } from "node:fs";
@@ -71757,7 +71779,7 @@ function readPidFile() {
71757
71779
  if (!existsSync9(PID_FILE))
71758
71780
  return null;
71759
71781
  try {
71760
- const parsed = JSON.parse(readFileSync7(PID_FILE, "utf8"));
71782
+ const parsed = JSON.parse(readFileSync8(PID_FILE, "utf8"));
71761
71783
  if (typeof parsed.pid !== "number")
71762
71784
  return null;
71763
71785
  return {
@@ -72153,18 +72175,6 @@ async function checkOpenAI() {
72153
72175
  };
72154
72176
  }
72155
72177
  }
72156
- var SCHEMA_VERSION_RE = /^--\s*@version:\s*(\S+)/m;
72157
- function readBundledSchemaVersion() {
72158
- try {
72159
- const assets = resolveServerAssets();
72160
- if (!existsSync11(assets.schemaFile))
72161
- return null;
72162
- const m = readFileSync8(assets.schemaFile, "utf8").match(SCHEMA_VERSION_RE);
72163
- return m ? m[1] : null;
72164
- } catch {
72165
- return null;
72166
- }
72167
- }
72168
72178
  var SCHEMA_CHECK_NAME = "schema + RPCs";
72169
72179
  async function checkSchemaVersion() {
72170
72180
  const settings = loadSettings();
@@ -72195,7 +72205,7 @@ async function checkSchemaVersion() {
72195
72205
  };
72196
72206
  }
72197
72207
  const deployed = await resp.json();
72198
- const bundled = readBundledSchemaVersion();
72208
+ const bundled = bundledSchemaVersion();
72199
72209
  const level = classifyCompat(deployed, COMPATIBILITY.minSchema, bundled);
72200
72210
  switch (level) {
72201
72211
  case "below-min":
@@ -72405,7 +72415,7 @@ function hasCerefoxInJsonFile(path) {
72405
72415
  if (!existsSync11(path))
72406
72416
  return false;
72407
72417
  try {
72408
- const parsed = JSON.parse(readFileSync8(path, "utf8"));
72418
+ const parsed = JSON.parse(readFileSync9(path, "utf8"));
72409
72419
  const mcpServers = parsed.mcpServers;
72410
72420
  return Boolean(mcpServers && typeof mcpServers === "object" && "cerefox" in mcpServers);
72411
72421
  } catch {
@@ -73059,11 +73069,11 @@ function registerGetDoc(program) {
73059
73069
  init_dist4();
73060
73070
  init_cli_core();
73061
73071
  init_config();
73062
- import { readFileSync as readFileSync10 } from "node:fs";
73072
+ import { readFileSync as readFileSync11 } from "node:fs";
73063
73073
  import { basename as basename2, extname as extname3 } from "node:path";
73064
73074
 
73065
73075
  // src/ingestion/pipeline.ts
73066
- import { readFileSync as readFileSync9 } from "node:fs";
73076
+ import { readFileSync as readFileSync10 } from "node:fs";
73067
73077
  import { basename, extname as extname2, resolve as resolve3 } from "node:path";
73068
73078
  // ../../_shared/ingest/pipeline-helpers.ts
73069
73079
  import { createHash } from "node:crypto";
@@ -73389,6 +73399,10 @@ async function fileToMarkdown(filename, data) {
73389
73399
  }
73390
73400
 
73391
73401
  // src/ingestion/pipeline.ts
73402
+ function updateByIdNote(updateExisting) {
73403
+ return updateExisting === false ? "document_id provided; update_if_exists flag was overridden" : undefined;
73404
+ }
73405
+
73392
73406
  class IngestionPipeline {
73393
73407
  db;
73394
73408
  apiKey;
@@ -73453,9 +73467,9 @@ class IngestionPipeline {
73453
73467
  result.projectIds = await this.db.getDocumentProjectIds(documentId);
73454
73468
  }
73455
73469
  }
73456
- if (!updateExisting) {
73457
- result.note = "document_id provided; update_if_exists flag was overridden";
73458
- }
73470
+ const note = updateByIdNote(opts.updateExisting);
73471
+ if (note)
73472
+ result.note = note;
73459
73473
  return result;
73460
73474
  }
73461
73475
  if (updateExisting) {
@@ -73729,7 +73743,7 @@ class IngestionPipeline {
73729
73743
  };
73730
73744
  }
73731
73745
  async ingestFile(path, opts = {}) {
73732
- const text = await fileToMarkdown(path, readFileSync9(path));
73746
+ const text = await fileToMarkdown(path, readFileSync10(path));
73733
73747
  const absPath = resolve3(path);
73734
73748
  const stem = basename(absPath, extname2(absPath));
73735
73749
  return this.ingestText({
@@ -73764,7 +73778,7 @@ async function readContent(path, paste) {
73764
73778
  }
73765
73779
  let content;
73766
73780
  try {
73767
- content = readFileSync10(path, "utf8");
73781
+ content = readFileSync11(path, "utf8");
73768
73782
  } catch (err) {
73769
73783
  const msg = err instanceof Error ? err.message : String(err);
73770
73784
  throw userError(`Cannot read ${path}: ${msg}`);
@@ -73822,7 +73836,7 @@ async function action20(path, options) {
73822
73836
  projectName: options.projectName ?? null,
73823
73837
  projectNames: projectNames ?? null,
73824
73838
  metadata: metadata ?? null,
73825
- updateExisting: Boolean(options.updateIfExists),
73839
+ updateExisting: options.updateIfExists ? true : undefined,
73826
73840
  documentId: options.documentId ?? null,
73827
73841
  author,
73828
73842
  authorType,
@@ -73836,7 +73850,7 @@ async function action20(path, options) {
73836
73850
  projectName: options.projectName ?? null,
73837
73851
  projectNames: projectNames ?? null,
73838
73852
  metadata: metadata ?? null,
73839
- updateExisting: Boolean(options.updateIfExists),
73853
+ updateExisting: options.updateIfExists ? true : undefined,
73840
73854
  documentId: options.documentId ?? null,
73841
73855
  author,
73842
73856
  authorType,
@@ -73874,14 +73888,14 @@ init_cli_core();
73874
73888
  init_mcp_tools();
73875
73889
  init_config();
73876
73890
  init_client();
73877
- import { readFileSync as readFileSync11 } from "node:fs";
73891
+ import { readFileSync as readFileSync12 } from "node:fs";
73878
73892
  function resolveText(value, what) {
73879
73893
  if (value === undefined)
73880
73894
  throw userError(`${what} is required.`);
73881
73895
  if (value === "-")
73882
- return readFileSync11(0, "utf8");
73896
+ return readFileSync12(0, "utf8");
73883
73897
  if (value.startsWith("@"))
73884
- return readFileSync11(value.slice(1), "utf8");
73898
+ return readFileSync12(value.slice(1), "utf8");
73885
73899
  return value;
73886
73900
  }
73887
73901
  function context() {
@@ -74014,7 +74028,7 @@ async function action21(dir, options) {
74014
74028
  sourceOnCreate: "cli",
74015
74029
  projectName: options.projectName ?? null,
74016
74030
  metadata: metadata ?? null,
74017
- updateExisting: Boolean(options.updateIfExists),
74031
+ updateExisting: options.updateIfExists ? true : undefined,
74018
74032
  author,
74019
74033
  authorType,
74020
74034
  lastWriteWins: true
@@ -74057,7 +74071,7 @@ import {
74057
74071
  copyFileSync as copyFileSync2,
74058
74072
  existsSync as existsSync12,
74059
74073
  mkdirSync as mkdirSync5,
74060
- readFileSync as readFileSync13,
74074
+ readFileSync as readFileSync14,
74061
74075
  writeFileSync as writeFileSync5
74062
74076
  } from "node:fs";
74063
74077
  import { homedir as homedir8 } from "node:os";
@@ -74068,7 +74082,7 @@ async function readConfigFile(path) {
74068
74082
  }
74069
74083
  let parsed;
74070
74084
  try {
74071
- parsed = JSON.parse(readFileSync13(path, "utf8"));
74085
+ parsed = JSON.parse(readFileSync14(path, "utf8"));
74072
74086
  } catch (err) {
74073
74087
  throw userError(`--config: invalid JSON in ${path}: ${err instanceof Error ? err.message : String(err)}`);
74074
74088
  }
@@ -74110,7 +74124,7 @@ function parseDotEnvFile(content) {
74110
74124
  return map;
74111
74125
  }
74112
74126
  function answersFromEnvFile(path) {
74113
- const parsed = parseDotEnvFile(readFileSync13(path, "utf8"));
74127
+ const parsed = parseDotEnvFile(readFileSync14(path, "utf8"));
74114
74128
  const required = ["CEREFOX_SUPABASE_URL", "CEREFOX_SUPABASE_KEY", "OPENAI_API_KEY"];
74115
74129
  for (const key of required) {
74116
74130
  if (!parsed[key] || parsed[key].trim() === "") {
@@ -75046,7 +75060,7 @@ function registerMigrateFormat(program) {
75046
75060
  // src/cli/commands/restore.ts
75047
75061
  init_cli_core();
75048
75062
  init_client();
75049
- import { existsSync as existsSync14, readFileSync as readFileSync15, readdirSync as readdirSync5, statSync as statSync4 } from "node:fs";
75063
+ import { existsSync as existsSync13, readFileSync as readFileSync15, readdirSync as readdirSync5, statSync as statSync4 } from "node:fs";
75050
75064
  import { homedir as homedir9 } from "node:os";
75051
75065
  import { join as join13, resolve as resolve4 } from "node:path";
75052
75066
  function expandHome2(path) {
@@ -75058,7 +75072,7 @@ function expandHome2(path) {
75058
75072
  }
75059
75073
  function resolveBackupFile(target) {
75060
75074
  const path = resolve4(expandHome2(target));
75061
- if (!existsSync14(path)) {
75075
+ if (!existsSync13(path)) {
75062
75076
  throw userError(`Backup path not found: ${target}`);
75063
75077
  }
75064
75078
  const stat = statSync4(path);
@@ -75549,7 +75563,7 @@ init_config();
75549
75563
  import { randomBytes } from "node:crypto";
75550
75564
 
75551
75565
  // src/cli/util/env-file.ts
75552
- import { copyFileSync as copyFileSync3, existsSync as existsSync15, readFileSync as readFileSync16, writeFileSync as writeFileSync6 } from "node:fs";
75566
+ import { copyFileSync as copyFileSync3, existsSync as existsSync14, readFileSync as readFileSync16, writeFileSync as writeFileSync6 } from "node:fs";
75553
75567
  import { dirname as dirname5 } from "node:path";
75554
75568
  import { spawnSync as spawnSync6 } from "node:child_process";
75555
75569
  function escapeRegExp(s) {
@@ -75559,7 +75573,7 @@ function upsertEnvVar(path, key, value, opts = {}) {
75559
75573
  const line = `${key}=${value}`;
75560
75574
  const header = opts.comment ? `# ${opts.comment}
75561
75575
  ` : "";
75562
- if (!existsSync15(path)) {
75576
+ if (!existsSync14(path)) {
75563
75577
  writeFileSync6(path, `${header}${line}
75564
75578
  `, { mode: 384 });
75565
75579
  return { path, action: "created" };
@@ -75589,7 +75603,7 @@ ${header}${line}
75589
75603
  return { path, action, backupPath };
75590
75604
  }
75591
75605
  function readEnvVar(path, key) {
75592
- if (!existsSync15(path))
75606
+ if (!existsSync14(path))
75593
75607
  return null;
75594
75608
  const m = readFileSync16(path, "utf8").match(new RegExp(`^\\s*${escapeRegExp(key)}=(.*)$`, "m"));
75595
75609
  return m ? m[1].trim() : null;
@@ -75612,7 +75626,7 @@ function envGitignoreWarning(path) {
75612
75626
  }
75613
75627
 
75614
75628
  // src/web/auth.ts
75615
- import { existsSync as existsSync16 } from "node:fs";
75629
+ import { existsSync as existsSync15 } from "node:fs";
75616
75630
 
75617
75631
  // ../../node_modules/.bun/@hono+node-server@2.1.1+2ac783cc5e75a70c/node_modules/@hono/node-server/dist/conninfo.mjs
75618
75632
  var getConnInfo = (c) => {
@@ -75677,7 +75691,7 @@ var LOOPBACK_ADDRESSES = new Set([
75677
75691
  ]);
75678
75692
  function isContainerised() {
75679
75693
  try {
75680
- return existsSync16("/.dockerenv");
75694
+ return existsSync15("/.dockerenv");
75681
75695
  } catch {
75682
75696
  return false;
75683
75697
  }
@@ -77556,7 +77570,7 @@ var _baseMimes = {
77556
77570
  var baseMimes = _baseMimes;
77557
77571
 
77558
77572
  // ../../node_modules/.bun/@hono+node-server@2.1.1+2ac783cc5e75a70c/node_modules/@hono/node-server/dist/serve-static.mjs
77559
- import { createReadStream, existsSync as existsSync17, statSync as statSync5 } from "node:fs";
77573
+ import { createReadStream, existsSync as existsSync16, statSync as statSync5 } from "node:fs";
77560
77574
  import { join as join14 } from "node:path";
77561
77575
  var COMPRESSIBLE_CONTENT_TYPE_REGEX = /^\s*(?:text\/[^;\s]+|application\/(?:javascript|json|xml|xml-dtd|ecmascript|dart|postscript|rtf|tar|toml|vnd\.dart|vnd\.ms-fontobject|vnd\.ms-opentype|wasm|x-httpd-php|x-javascript|x-ns-proxy-autoconfig|x-sh|x-tar|x-virtualbox-hdd|x-virtualbox-ova|x-virtualbox-ovf|x-virtualbox-vbox|x-virtualbox-vdi|x-virtualbox-vhd|x-virtualbox-vmdk|x-www-form-urlencoded)|font\/(?:otf|ttf)|image\/(?:bmp|vnd\.adobe\.photoshop|vnd\.microsoft\.icon|vnd\.ms-dds|x-icon|x-ms-bmp)|message\/rfc822|model\/gltf-binary|x-shader\/x-fragment|x-shader\/x-vertex|[^;\s]+?\+(?:json|text|xml|yaml))(?:[;\s]|$)/i;
77562
77576
  var ENCODINGS = {
@@ -77630,7 +77644,7 @@ var tryDecodeURI = (str) => tryDecode(str, decodeURI);
77630
77644
  var serveStatic = (options = { root: "" }) => {
77631
77645
  const root = options.root || "";
77632
77646
  const optionPath = options.path;
77633
- if (root !== "" && !existsSync17(root))
77647
+ if (root !== "" && !existsSync16(root))
77634
77648
  console.error(`serveStatic: root path '${root}' is not found, are you sure it's correct?`);
77635
77649
  return async (c, next) => {
77636
77650
  if (c.finalized)
@@ -77713,7 +77727,7 @@ var serveStatic = (options = { root: "" }) => {
77713
77727
  };
77714
77728
 
77715
77729
  // src/web/server.ts
77716
- import { existsSync as existsSync21 } from "node:fs";
77730
+ import { existsSync as existsSync20 } from "node:fs";
77717
77731
  import { readFileSync as readFileSync19, statSync as statSync8 } from "node:fs";
77718
77732
  import { join as join18 } from "node:path";
77719
77733
 
@@ -80790,7 +80804,7 @@ function registerIngestRoutes(app, ctx) {
80790
80804
  projectNames: Array.isArray(body.project_names) ? body.project_names : null,
80791
80805
  projectName: typeof body.project_name === "string" ? body.project_name : null,
80792
80806
  metadata: body.metadata ?? null,
80793
- updateExisting: body.update_existing === true || body.update_if_exists === true,
80807
+ updateExisting: body.update_existing == null && body.update_if_exists == null ? undefined : body.update_existing === true || body.update_if_exists === true,
80794
80808
  documentId: body.document_id ?? null,
80795
80809
  author: who.identity.author,
80796
80810
  authorType: who.identity.authorType,
@@ -80955,12 +80969,13 @@ function registerIngestRoutes(app, ctx) {
80955
80969
  }
80956
80970
 
80957
80971
  // src/web/routes/meta.ts
80972
+ init_server_assets();
80958
80973
  init_meta();
80959
80974
  import { execFileSync } from "node:child_process";
80960
80975
 
80961
80976
  // src/web/docs.ts
80962
80977
  import {
80963
- existsSync as existsSync18,
80978
+ existsSync as existsSync17,
80964
80979
  readFileSync as readFileSync17,
80965
80980
  readdirSync as readdirSync6,
80966
80981
  statSync as statSync6
@@ -80993,7 +81008,7 @@ function resolveDocsRoots() {
80993
81008
  let pkgTopLevel = null;
80994
81009
  for (const pkg of pkgRootCandidates) {
80995
81010
  const guides = join15(pkg, "docs", "guides");
80996
- if (existsSync18(guides) && statSync6(guides).isDirectory()) {
81011
+ if (existsSync17(guides) && statSync6(guides).isDirectory()) {
80997
81012
  pkgGuides = guides;
80998
81013
  pkgTopLevel = pkg;
80999
81014
  break;
@@ -81005,8 +81020,8 @@ function resolveDocsRoots() {
81005
81020
  return {
81006
81021
  pkgGuides,
81007
81022
  pkgTopLevel,
81008
- repoGuides: existsSync18(repoGuides) ? repoGuides : null,
81009
- repoTopLevel: existsSync18(join15(repoTopLevel, "README.md")) ? repoTopLevel : null
81023
+ repoGuides: existsSync17(repoGuides) ? repoGuides : null,
81024
+ repoTopLevel: existsSync17(join15(repoTopLevel, "README.md")) ? repoTopLevel : null
81010
81025
  };
81011
81026
  }
81012
81027
  function readH1(filePath) {
@@ -81032,7 +81047,7 @@ function listBundledDocs2() {
81032
81047
  if (topRoot) {
81033
81048
  for (const t of TOP_LEVEL_DOCS) {
81034
81049
  const abs = join15(topRoot, t.filename);
81035
- if (existsSync18(abs)) {
81050
+ if (existsSync17(abs)) {
81036
81051
  entries.push(entryForFile(abs, t.path, t.category));
81037
81052
  }
81038
81053
  }
@@ -81059,7 +81074,7 @@ function readDoc(docPath) {
81059
81074
  if (!candidate.startsWith(rootResolved + "/") && candidate !== rootResolved) {
81060
81075
  return null;
81061
81076
  }
81062
- if (existsSync18(candidate) && statSync6(candidate).isFile()) {
81077
+ if (existsSync17(candidate) && statSync6(candidate).isFile()) {
81063
81078
  try {
81064
81079
  return readFileSync17(candidate, "utf8");
81065
81080
  } catch {
@@ -81068,6 +81083,18 @@ function readDoc(docPath) {
81068
81083
  }
81069
81084
  return null;
81070
81085
  }
81086
+ function readOpenApiDocument() {
81087
+ const here = moduleDir2();
81088
+ const candidates = [
81089
+ join15(here, "..", "..", "docs", "api", "openapi.json"),
81090
+ join15(here, "..", "..", "..", "..", "docs", "api", "openapi.json")
81091
+ ];
81092
+ for (const p of candidates) {
81093
+ if (existsSync17(p))
81094
+ return readFileSync17(p, "utf8");
81095
+ }
81096
+ return null;
81097
+ }
81071
81098
 
81072
81099
  // src/web/routes/meta.ts
81073
81100
  init_compatibility();
@@ -81090,7 +81117,6 @@ var VERSION_INFO = {
81090
81117
  git_commit_short: resolveGitCommitShort(),
81091
81118
  build_date: process.env.CEREFOX_BUILD_DATE ?? null
81092
81119
  };
81093
- var SCHEMA_VERSION_RE3 = /^--\s*@version:\s*(\S+)/m;
81094
81120
  function registerMetaRoutes(app, ctx) {
81095
81121
  app.get("/api/v1/version", (c) => {
81096
81122
  const label = (process.env.CEREFOX_ENV_LABEL ?? "").trim();
@@ -81107,28 +81133,15 @@ function registerMetaRoutes(app, ctx) {
81107
81133
  "Content-Type": "text/markdown; charset=utf-8"
81108
81134
  });
81109
81135
  });
81110
- app.get("/api/v1/schema-version", async (c) => {
81111
- let bundled = null;
81112
- try {
81113
- const { readFileSync, existsSync } = await import("node:fs");
81114
- const { fileURLToPath } = await import("node:url");
81115
- const { dirname, join } = await import("node:path");
81116
- const here = dirname(fileURLToPath(import.meta.url));
81117
- const candidates = [
81118
- join(here, "..", "..", "..", "db", "schema.sql"),
81119
- join(here, "..", "..", "..", "..", "..", "src", "cerefox", "db", "schema.sql")
81120
- ];
81121
- for (const path of candidates) {
81122
- if (existsSync(path)) {
81123
- const sql = readFileSync(path, "utf8");
81124
- const match = sql.match(SCHEMA_VERSION_RE3);
81125
- bundled = match ? match[1] : null;
81126
- break;
81127
- }
81128
- }
81129
- } catch {
81130
- bundled = null;
81136
+ app.get("/api/v1/openapi.json", (c) => {
81137
+ const doc = readOpenApiDocument();
81138
+ if (doc === null) {
81139
+ return c.json({ detail: "The OpenAPI document is not bundled with this build." }, 404);
81131
81140
  }
81141
+ return c.body(doc, 200, { "Content-Type": "application/json; charset=utf-8" });
81142
+ });
81143
+ app.get("/api/v1/schema-version", async (c) => {
81144
+ const bundled = bundledSchemaVersion();
81132
81145
  let deployed = null;
81133
81146
  if (ctx) {
81134
81147
  try {
@@ -81157,8 +81170,8 @@ function registerMetaRoutes(app, ctx) {
81157
81170
  }
81158
81171
  } catch {}
81159
81172
  }
81160
- const mismatch = Boolean(bundled && deployed && bundled !== deployed);
81161
81173
  const level = classifyCompat(deployed, COMPATIBILITY.minSchema, bundled);
81174
+ const mismatch = level === "above-min-but-old";
81162
81175
  return c.json({
81163
81176
  bundled,
81164
81177
  deployed,
@@ -81216,7 +81229,7 @@ function registerPostgrestProxy(app) {
81216
81229
 
81217
81230
  // src/web/routes/preferences.ts
81218
81231
  init_config();
81219
- import { existsSync as existsSync19, mkdirSync as mkdirSync6, readFileSync as readFileSync18, writeFileSync as writeFileSync7 } from "node:fs";
81232
+ import { existsSync as existsSync18, mkdirSync as mkdirSync6, readFileSync as readFileSync18, writeFileSync as writeFileSync7 } from "node:fs";
81220
81233
  import { join as join16 } from "node:path";
81221
81234
  function isTheme(v) {
81222
81235
  return v === "auto" || v === "light" || v === "dark";
@@ -81242,7 +81255,7 @@ function registerPreferencesRoutes(app) {
81242
81255
  const next = { ...readPrefs(), theme: body.theme };
81243
81256
  try {
81244
81257
  const dir = userStateDir();
81245
- if (!existsSync19(dir))
81258
+ if (!existsSync18(dir))
81246
81259
  mkdirSync6(dir, { recursive: true });
81247
81260
  writeFileSync7(prefsFile(), `${JSON.stringify(next, null, 2)}
81248
81261
  `);
@@ -81379,14 +81392,14 @@ function registerProjectsRoutes(app, ctx) {
81379
81392
  }
81380
81393
 
81381
81394
  // src/web/static.ts
81382
- import { existsSync as existsSync20, statSync as statSync7 } from "node:fs";
81395
+ import { existsSync as existsSync19, statSync as statSync7 } from "node:fs";
81383
81396
  import { dirname as dirname7, join as join17 } from "node:path";
81384
81397
  import { fileURLToPath as fileURLToPath4 } from "node:url";
81385
81398
  function moduleDir3() {
81386
81399
  return dirname7(fileURLToPath4(import.meta.url));
81387
81400
  }
81388
81401
  function isUsableSpaDir(dir) {
81389
- return existsSync20(dir) && statSync7(dir).isDirectory() && existsSync20(join17(dir, "index.html"));
81402
+ return existsSync19(dir) && statSync7(dir).isDirectory() && existsSync19(join17(dir, "index.html"));
81390
81403
  }
81391
81404
  function resolveSpaDist() {
81392
81405
  const here = moduleDir3();
@@ -81408,7 +81421,7 @@ function resolveStaticDir() {
81408
81421
  join17(here, "..", "..", "..", "..", "web", "static")
81409
81422
  ];
81410
81423
  for (const c of candidates) {
81411
- if (existsSync20(c) && statSync7(c).isDirectory())
81424
+ if (existsSync19(c) && statSync7(c).isDirectory())
81412
81425
  return c;
81413
81426
  }
81414
81427
  return null;
@@ -81455,11 +81468,16 @@ init_ef_meta();
81455
81468
  init_cli_core();
81456
81469
  init_config();
81457
81470
  init_compatibility();
81471
+ var OPENAPI_PATH = "/api/v1/openapi.json";
81458
81472
  function buildApp(ctx = buildWebContext()) {
81459
81473
  const app = new Hono2;
81460
81474
  if (true) {
81461
81475
  app.use(logger((message, ...rest) => console.log(`${localTimestamp()} ${message}`, ...rest)));
81462
81476
  }
81477
+ app.use("/api/v1/*", async (c, next) => {
81478
+ await next();
81479
+ c.res.headers.set("Link", `<${OPENAPI_PATH}>; rel="service-desc"`);
81480
+ });
81463
81481
  app.use("/api/v1/*", apiAuth());
81464
81482
  app.use("/rest/v1/*", apiAuth());
81465
81483
  registerMetaRoutes(app, ctx);
@@ -81500,7 +81518,7 @@ function buildApp(ctx = buildWebContext()) {
81500
81518
  }));
81501
81519
  app.get("/app/assets/*", (c) => c.text("Not found", 404));
81502
81520
  const indexPath = join18(spaDist, "index.html");
81503
- if (existsSync21(indexPath)) {
81521
+ if (existsSync20(indexPath)) {
81504
81522
  let cached = null;
81505
81523
  const readIndex = () => {
81506
81524
  try {