@cerefox/memory 1.0.3 → 1.0.5
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/bin/cerefox.js +124 -65
- package/dist/frontend/assets/index-Csj-6UHY.js.map +1 -1
- package/dist/server-assets/_shared/ef-meta/index.ts +2 -2
- package/dist/server-assets/_shared/mcp-tools/_utils.ts +15 -0
- package/dist/server-assets/_shared/mcp-tools/search.ts +32 -1
- package/dist/server-assets/db/rpcs.sql +68 -15
- package/dist/server-assets/db/schema.sql +1 -1
- package/docs/guides/configuration.md +9 -0
- package/package.json +1 -1
package/dist/bin/cerefox.js
CHANGED
|
@@ -7184,7 +7184,7 @@ var exports_meta = {};
|
|
|
7184
7184
|
__export(exports_meta, {
|
|
7185
7185
|
PKG_VERSION: () => PKG_VERSION
|
|
7186
7186
|
});
|
|
7187
|
-
var PKG_VERSION = "1.0.
|
|
7187
|
+
var PKG_VERSION = "1.0.5";
|
|
7188
7188
|
var init_meta = () => {};
|
|
7189
7189
|
|
|
7190
7190
|
// ../../node_modules/.bun/tslib@2.8.1/node_modules/tslib/tslib.js
|
|
@@ -25225,6 +25225,13 @@ function getMinSearchScore() {
|
|
|
25225
25225
|
const n = Number.parseFloat(raw);
|
|
25226
25226
|
return Number.isNaN(n) || n < 0 || n > 1 ? fallback : n;
|
|
25227
25227
|
}
|
|
25228
|
+
function getMinTermCoverage() {
|
|
25229
|
+
const raw = globalThis.process?.env?.CEREFOX_MIN_TERM_COVERAGE;
|
|
25230
|
+
if (raw === undefined || raw === "")
|
|
25231
|
+
return;
|
|
25232
|
+
const n = Number.parseFloat(raw);
|
|
25233
|
+
return Number.isNaN(n) || n < 0 || n > 1 ? undefined : n;
|
|
25234
|
+
}
|
|
25228
25235
|
function applyByteBudget(rows, maxBytes) {
|
|
25229
25236
|
const accepted = [];
|
|
25230
25237
|
let usedBytes = 0;
|
|
@@ -55572,6 +55579,8 @@ async function handler9(supabase, args, ctx) {
|
|
|
55572
55579
|
const mode = args.mode ?? "docs";
|
|
55573
55580
|
const alpha = args.alpha ?? 0.7;
|
|
55574
55581
|
const min_score = args.min_score ?? getMinSearchScore();
|
|
55582
|
+
const min_term_coverage = args.min_term_coverage ?? getMinTermCoverage();
|
|
55583
|
+
const coverageParam = min_term_coverage !== undefined ? { p_min_term_coverage: min_term_coverage } : {};
|
|
55575
55584
|
const metadata_filter = args.metadata_filter ?? null;
|
|
55576
55585
|
const requested_max_bytes = args.max_bytes;
|
|
55577
55586
|
const ceiling = getMaxResponseBytes();
|
|
@@ -55603,7 +55612,8 @@ async function handler9(supabase, args, ctx) {
|
|
|
55603
55612
|
p_query_text: query,
|
|
55604
55613
|
p_match_count: match_count,
|
|
55605
55614
|
p_project_id: projectId,
|
|
55606
|
-
...metaFilterParam
|
|
55615
|
+
...metaFilterParam,
|
|
55616
|
+
...coverageParam
|
|
55607
55617
|
};
|
|
55608
55618
|
} else if (mode === "hybrid") {
|
|
55609
55619
|
rpcName = "cerefox_hybrid_search";
|
|
@@ -55615,7 +55625,8 @@ async function handler9(supabase, args, ctx) {
|
|
|
55615
55625
|
p_use_upgrade: false,
|
|
55616
55626
|
p_project_id: projectId,
|
|
55617
55627
|
p_min_score: min_score,
|
|
55618
|
-
...metaFilterParam
|
|
55628
|
+
...metaFilterParam,
|
|
55629
|
+
...coverageParam
|
|
55619
55630
|
};
|
|
55620
55631
|
} else {
|
|
55621
55632
|
rpcName = "cerefox_search_docs";
|
|
@@ -55626,7 +55637,8 @@ async function handler9(supabase, args, ctx) {
|
|
|
55626
55637
|
p_alpha: alpha,
|
|
55627
55638
|
p_project_id: projectId,
|
|
55628
55639
|
p_min_score: min_score,
|
|
55629
|
-
...metaFilterParam
|
|
55640
|
+
...metaFilterParam,
|
|
55641
|
+
...coverageParam
|
|
55630
55642
|
};
|
|
55631
55643
|
}
|
|
55632
55644
|
const { data, error: error2 } = await supabase.rpc(rpcName, rpcParams);
|
|
@@ -55699,6 +55711,23 @@ var init_search = __esm(() => {
|
|
|
55699
55711
|
description: 'Optional JSONB containment filter. Only documents whose metadata contains ALL specified key-value pairs are returned. Example: {"type": "decision", "status": "active"}. Call cerefox_list_metadata_keys first to discover available keys and values. Omit to search all documents.',
|
|
55700
55712
|
additionalProperties: { type: "string" }
|
|
55701
55713
|
},
|
|
55714
|
+
mode: {
|
|
55715
|
+
type: "string",
|
|
55716
|
+
enum: ["docs", "hybrid", "fts", "semantic"],
|
|
55717
|
+
description: "Search mode (default: docs — full reconstructed documents). hybrid: ranked chunks; fts: keyword-only (no embedding); semantic: vector-only."
|
|
55718
|
+
},
|
|
55719
|
+
alpha: {
|
|
55720
|
+
type: "number",
|
|
55721
|
+
description: "Hybrid fusion weight 0–1 (default 0.7): 1 = pure semantic, 0 = pure keyword."
|
|
55722
|
+
},
|
|
55723
|
+
min_score: {
|
|
55724
|
+
type: "number",
|
|
55725
|
+
description: "Minimum cosine similarity for vector-side results (default: server-configured, 0.5 OpenAI / 0.6 local embedder)."
|
|
55726
|
+
},
|
|
55727
|
+
min_term_coverage: {
|
|
55728
|
+
type: "number",
|
|
55729
|
+
description: "Keyword OR-fallback confidence bar 0–1 (default 0.5): fraction of the query's meaningful terms a result must match to count as a confident hit; weaker matches return flagged below-confidence. 0 = any matching term. Needs schema ≥ 0.9.1."
|
|
55730
|
+
},
|
|
55702
55731
|
max_bytes: {
|
|
55703
55732
|
type: "integer",
|
|
55704
55733
|
description: "Optional response size budget in bytes. Results are dropped whole until the budget is satisfied; a truncated flag is set when results are dropped. Defaults to the server maximum (200000). Pass a smaller value if your context window is limited. Values above the server maximum are silently capped."
|
|
@@ -69032,10 +69061,35 @@ init_cli_core();
|
|
|
69032
69061
|
|
|
69033
69062
|
// src/cli/commands/backup.ts
|
|
69034
69063
|
init_cli_core();
|
|
69035
|
-
init_client();
|
|
69036
69064
|
import { existsSync as existsSync2, mkdirSync, writeFileSync } from "node:fs";
|
|
69037
69065
|
import { homedir as homedir2 } from "node:os";
|
|
69038
69066
|
import { join as join2, resolve } from "node:path";
|
|
69067
|
+
|
|
69068
|
+
// ../../_shared/db-client/paginate.ts
|
|
69069
|
+
async function fetchAllPages(makeQuery, batchSize = 200) {
|
|
69070
|
+
const results = [];
|
|
69071
|
+
let offset = 0;
|
|
69072
|
+
let serverTotal = null;
|
|
69073
|
+
for (;; ) {
|
|
69074
|
+
const { data, error, count } = await makeQuery(offset, offset + batchSize - 1);
|
|
69075
|
+
if (error)
|
|
69076
|
+
throw new Error(error.message ?? JSON.stringify(error));
|
|
69077
|
+
if (typeof count === "number")
|
|
69078
|
+
serverTotal = count;
|
|
69079
|
+
const page = data ?? [];
|
|
69080
|
+
results.push(...page);
|
|
69081
|
+
if (page.length < batchSize)
|
|
69082
|
+
break;
|
|
69083
|
+
offset += batchSize;
|
|
69084
|
+
}
|
|
69085
|
+
if (serverTotal !== null && results.length !== serverTotal) {
|
|
69086
|
+
throw new Error(`Paginated read returned ${results.length} row(s) but the server reports ` + `${serverTotal}. Refusing to return a partial result — retry, and if this ` + `persists please report it (the rows may be changing under the read).`);
|
|
69087
|
+
}
|
|
69088
|
+
return results;
|
|
69089
|
+
}
|
|
69090
|
+
|
|
69091
|
+
// src/cli/commands/backup.ts
|
|
69092
|
+
init_client();
|
|
69039
69093
|
function expandHome(path) {
|
|
69040
69094
|
if (path === "~")
|
|
69041
69095
|
return homedir2();
|
|
@@ -69056,21 +69110,25 @@ async function action(options) {
|
|
|
69056
69110
|
const filename = `cerefox-${stamp}${options.label ? "-" + options.label : ""}.json`;
|
|
69057
69111
|
const dest = join2(outDir, filename);
|
|
69058
69112
|
const client = getClient();
|
|
69059
|
-
|
|
69060
|
-
|
|
69061
|
-
|
|
69062
|
-
|
|
69113
|
+
let docs;
|
|
69114
|
+
try {
|
|
69115
|
+
docs = await fetchAllPages((from, to) => client.raw.from("cerefox_documents").select("id, title, content_hash, source, metadata, total_chars, chunk_count, " + "review_status, created_at, updated_at, deleted_at").is("deleted_at", null).order("created_at", { ascending: true }).order("id", { ascending: true }).range(from, to));
|
|
69116
|
+
} catch (err) {
|
|
69117
|
+
throw systemError(`Document fetch failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
69118
|
+
}
|
|
69063
69119
|
let chunkTotal = 0;
|
|
69064
69120
|
const enriched = [];
|
|
69065
69121
|
for (let i = 0;i < docs.length; i++) {
|
|
69066
69122
|
const doc = docs[i];
|
|
69067
69123
|
const docId = doc.id;
|
|
69068
|
-
|
|
69069
|
-
|
|
69070
|
-
|
|
69124
|
+
let chunks;
|
|
69125
|
+
try {
|
|
69126
|
+
chunks = await fetchAllPages((from, to) => client.raw.from("cerefox_chunks").select("*").eq("document_id", docId).is("version_id", null).order("chunk_index", { ascending: true }).range(from, to));
|
|
69127
|
+
} catch (err) {
|
|
69128
|
+
throw systemError(`Chunk fetch failed for ${docId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
69071
69129
|
}
|
|
69072
|
-
chunkTotal +=
|
|
69073
|
-
enriched.push({ ...doc, chunks
|
|
69130
|
+
chunkTotal += chunks.length;
|
|
69131
|
+
enriched.push({ ...doc, chunks });
|
|
69074
69132
|
if (process.stdout.isTTY) {
|
|
69075
69133
|
process.stderr.write(`\r Dumping documents: ${i + 1}/${docs.length} (${chunkTotal} chunks so far)…`);
|
|
69076
69134
|
}
|
|
@@ -74948,8 +75006,8 @@ import { homedir as homedir6 } from "node:os";
|
|
|
74948
75006
|
import { join as join9 } from "node:path";
|
|
74949
75007
|
|
|
74950
75008
|
// ../../_shared/ef-meta/index.ts
|
|
74951
|
-
var EF_VERSION = "1.0.
|
|
74952
|
-
var EF_LAST_CHANGED = "1.0.
|
|
75009
|
+
var EF_VERSION = "1.0.5";
|
|
75010
|
+
var EF_LAST_CHANGED = "1.0.4";
|
|
74953
75011
|
|
|
74954
75012
|
// src/cli/util/checks.ts
|
|
74955
75013
|
init_config();
|
|
@@ -75475,9 +75533,9 @@ async function checkEdgeFunctionsCompat() {
|
|
|
75475
75533
|
}
|
|
75476
75534
|
return {
|
|
75477
75535
|
name: "edge functions",
|
|
75478
|
-
status: "
|
|
75479
|
-
detail: `Deployed Edge Functions (v${deployed}) are older than
|
|
75480
|
-
hint: "
|
|
75536
|
+
status: "warn",
|
|
75537
|
+
detail: `Deployed Edge Functions (v${deployed}) are older than this client's bundled v${EF_VERSION} and predate server-side fixes shipped in v${EF_LAST_CHANGED}. Still compatible, but you are missing those fixes.`,
|
|
75538
|
+
hint: "Update the Edge Functions (see remediation below)."
|
|
75481
75539
|
};
|
|
75482
75540
|
default:
|
|
75483
75541
|
return {
|
|
@@ -75576,11 +75634,11 @@ async function action15(options) {
|
|
|
75576
75634
|
const needsEf = stale("edge functions");
|
|
75577
75635
|
let remediation = null;
|
|
75578
75636
|
if (needsSchema && needsEf) {
|
|
75579
|
-
remediation = "
|
|
75637
|
+
remediation = "This release needs a server update (schema + RPCs + Edge Functions): cerefox server deploy";
|
|
75580
75638
|
} else if (needsSchema) {
|
|
75581
|
-
remediation = "
|
|
75639
|
+
remediation = "This release needs a schema + RPC update: cerefox server deploy --schema-only";
|
|
75582
75640
|
} else if (needsEf) {
|
|
75583
|
-
remediation = "
|
|
75641
|
+
remediation = "This release needs an Edge Function update: cerefox server deploy --functions-only";
|
|
75584
75642
|
}
|
|
75585
75643
|
if (remediation) {
|
|
75586
75644
|
println(cErr.yellow("→ " + remediation));
|
|
@@ -75807,7 +75865,7 @@ class IngestionDbBridge {
|
|
|
75807
75865
|
return rows.length > 0 ? rows[0] : null;
|
|
75808
75866
|
}
|
|
75809
75867
|
async listChunksForDocument(documentId) {
|
|
75810
|
-
const
|
|
75868
|
+
const data = await fetchAllPages((from, to) => this.supabase.from("cerefox_chunks").select("id, document_id, chunk_index, heading_path, heading_level, title, content, char_count").eq("document_id", documentId).is("version_id", null).order("chunk_index").range(from, to));
|
|
75811
75869
|
return data ?? [];
|
|
75812
75870
|
}
|
|
75813
75871
|
async getDocumentProjectIds(documentId) {
|
|
@@ -77239,18 +77297,22 @@ async function action27(options) {
|
|
|
77239
77297
|
}
|
|
77240
77298
|
const reindexAll = Boolean(options.all);
|
|
77241
77299
|
const dryRun = Boolean(options.dryRun);
|
|
77242
|
-
let query = supabase.from("cerefox_chunks").select("id, document_id, content, embedder_primary, cerefox_documents(title)").is("version_id", null);
|
|
77243
|
-
if (options.documentId) {
|
|
77244
|
-
query = query.eq("document_id", options.documentId);
|
|
77245
|
-
}
|
|
77246
77300
|
const targetModel = activeEmbedderName();
|
|
77247
|
-
|
|
77248
|
-
|
|
77301
|
+
let chunks;
|
|
77302
|
+
try {
|
|
77303
|
+
chunks = await fetchAllPages((from, to) => {
|
|
77304
|
+
let query = supabase.from("cerefox_chunks").select("id, document_id, content, embedder_primary, cerefox_documents(title)").is("version_id", null);
|
|
77305
|
+
if (options.documentId) {
|
|
77306
|
+
query = query.eq("document_id", options.documentId);
|
|
77307
|
+
}
|
|
77308
|
+
if (!reindexAll) {
|
|
77309
|
+
query = query.neq("embedder_primary", targetModel);
|
|
77310
|
+
}
|
|
77311
|
+
return query.order("id", { ascending: true }).range(from, to);
|
|
77312
|
+
}, 1000);
|
|
77313
|
+
} catch (err) {
|
|
77314
|
+
throw systemError(`Failed to list chunks: ${err instanceof Error ? err.message : String(err)}`);
|
|
77249
77315
|
}
|
|
77250
|
-
const { data, error: error3 } = await query;
|
|
77251
|
-
if (error3)
|
|
77252
|
-
throw systemError(`Failed to list chunks: ${error3.message}`);
|
|
77253
|
-
const chunks = data ?? [];
|
|
77254
77316
|
if (chunks.length === 0) {
|
|
77255
77317
|
println(c.dim("(nothing to reindex)"));
|
|
77256
77318
|
return;
|
|
@@ -77420,6 +77482,8 @@ async function action29(query, options) {
|
|
|
77420
77482
|
const matchCount = parsePositiveInt(options.matchCount, "--match-count", 5);
|
|
77421
77483
|
const alpha = parseFloat01(options.alpha, "--alpha", 0.7);
|
|
77422
77484
|
const minScore = parseFloat01(options.minScore, "--min-score", getMinSearchScore());
|
|
77485
|
+
const envCoverage = getMinTermCoverage();
|
|
77486
|
+
const coverageParam = options.minTermCoverage !== undefined ? { p_min_term_coverage: parseFloat01(options.minTermCoverage, "--min-term-coverage", envCoverage ?? 0.5) } : envCoverage !== undefined ? { p_min_term_coverage: envCoverage } : {};
|
|
77423
77487
|
const maxBytes = parseNonNegativeInt(options.maxBytes, "--max-bytes", getMaxResponseBytes());
|
|
77424
77488
|
const mode = options.mode ?? "docs";
|
|
77425
77489
|
if (!["docs", "hybrid", "fts"].includes(mode)) {
|
|
@@ -77450,7 +77514,8 @@ async function action29(query, options) {
|
|
|
77450
77514
|
p_query_text: query,
|
|
77451
77515
|
p_match_count: matchCount,
|
|
77452
77516
|
p_project_id: projectId,
|
|
77453
|
-
...metaFilterParam
|
|
77517
|
+
...metaFilterParam,
|
|
77518
|
+
...coverageParam
|
|
77454
77519
|
};
|
|
77455
77520
|
} else if (mode === "hybrid") {
|
|
77456
77521
|
rpcName = "cerefox_hybrid_search";
|
|
@@ -77462,7 +77527,8 @@ async function action29(query, options) {
|
|
|
77462
77527
|
p_use_upgrade: false,
|
|
77463
77528
|
p_project_id: projectId,
|
|
77464
77529
|
p_min_score: minScore,
|
|
77465
|
-
...metaFilterParam
|
|
77530
|
+
...metaFilterParam,
|
|
77531
|
+
...coverageParam
|
|
77466
77532
|
};
|
|
77467
77533
|
} else {
|
|
77468
77534
|
rpcName = "cerefox_search_docs";
|
|
@@ -77473,7 +77539,8 @@ async function action29(query, options) {
|
|
|
77473
77539
|
p_alpha: alpha,
|
|
77474
77540
|
p_project_id: projectId,
|
|
77475
77541
|
p_min_score: minScore,
|
|
77476
|
-
...metaFilterParam
|
|
77542
|
+
...metaFilterParam,
|
|
77543
|
+
...coverageParam
|
|
77477
77544
|
};
|
|
77478
77545
|
}
|
|
77479
77546
|
const results = await client.rpc(rpcName, rpcParams);
|
|
@@ -77572,7 +77639,7 @@ async function action29(query, options) {
|
|
|
77572
77639
|
}
|
|
77573
77640
|
}
|
|
77574
77641
|
function registerSearch(program2) {
|
|
77575
|
-
program2.command("search").description("Search the knowledge base (hybrid FTS + semantic).").argument("<query>", "Natural-language search query.").option("-c, --match-count <n>", "Maximum number of documents to return.", "5").option("-p, --project-name <name>", "Filter results to a specific project.").option("-f, --metadata-filter <json>", "JSON containment filter; only docs whose metadata contains ALL pairs are returned.").option("--mode <mode>", "Search mode: docs (default), hybrid, fts.", "docs").option("--alpha <float>", "Semantic weight 0..1 (default: 0.7).", "0.7").option("--min-score <float>", "Minimum cosine similarity threshold (default: CEREFOX_MIN_SEARCH_SCORE; else 0.5, or 0.6 with the local embedder).").option("--max-bytes <n>", "Response size budget in bytes (default: CEREFOX_MAX_RESPONSE_BYTES or 200000).").option("-r, --requestor <name>", "Agent / user name (recorded in usage log).").option("--json", "Emit machine-readable JSON instead of the default text.").option("--only-metadata", "List matching docs (id, score, chunks, chars, partial/full) WITHOUT their content — like the web UI's collapsed result list. Grab a [id:…] then `cerefox document get <id>`.").action(action29);
|
|
77642
|
+
program2.command("search").description("Search the knowledge base (hybrid FTS + semantic).").argument("<query>", "Natural-language search query.").option("-c, --match-count <n>", "Maximum number of documents to return.", "5").option("-p, --project-name <name>", "Filter results to a specific project.").option("-f, --metadata-filter <json>", "JSON containment filter; only docs whose metadata contains ALL pairs are returned.").option("--mode <mode>", "Search mode: docs (default), hybrid, fts.", "docs").option("--alpha <float>", "Semantic weight 0..1 (default: 0.7).", "0.7").option("--min-score <float>", "Minimum cosine similarity threshold (default: CEREFOX_MIN_SEARCH_SCORE; else 0.5, or 0.6 with the local embedder).").option("--min-term-coverage <float>", "OR-fallback keyword matches must cover at least this fraction of the query's meaningful terms to count as confident hits (default: CEREFOX_MIN_TERM_COVERAGE; else the server default 0.5; needs schema ≥ 0.9.1).").option("--max-bytes <n>", "Response size budget in bytes (default: CEREFOX_MAX_RESPONSE_BYTES or 200000).").option("-r, --requestor <name>", "Agent / user name (recorded in usage log).").option("--json", "Emit machine-readable JSON instead of the default text.").option("--only-metadata", "List matching docs (id, score, chunks, chars, partial/full) WITHOUT their content — like the web UI's collapsed result list. Grab a [id:…] then `cerefox document get <id>`.").action(action29);
|
|
77576
77643
|
}
|
|
77577
77644
|
|
|
77578
77645
|
// src/cli/commands/self-update.ts
|
|
@@ -81390,23 +81457,18 @@ function parseMetadataFilter(raw2) {
|
|
|
81390
81457
|
}
|
|
81391
81458
|
async function listDocuments(ctx, opts) {
|
|
81392
81459
|
const { projectId, limit, offset = 0 } = opts;
|
|
81393
|
-
|
|
81394
|
-
|
|
81395
|
-
|
|
81396
|
-
|
|
81397
|
-
throw error4;
|
|
81398
|
-
docIds = (data2 ?? []).map((r) => r.document_id);
|
|
81399
|
-
if (docIds.length === 0)
|
|
81400
|
-
return [];
|
|
81401
|
-
}
|
|
81402
|
-
let q = ctx.supabase.from("cerefox_documents").select(DOC_COLS).is("deleted_at", null).order("updated_at", { ascending: false });
|
|
81403
|
-
if (docIds)
|
|
81404
|
-
q = q.in("id", docIds);
|
|
81460
|
+
const selectCols = projectId ? `${DOC_COLS}, cerefox_document_projects!inner(project_id)` : DOC_COLS;
|
|
81461
|
+
let q = ctx.supabase.from("cerefox_documents").select(selectCols).is("deleted_at", null).order("updated_at", { ascending: false });
|
|
81462
|
+
if (projectId)
|
|
81463
|
+
q = q.eq("cerefox_document_projects.project_id", projectId);
|
|
81405
81464
|
q = q.range(offset, offset + limit - 1);
|
|
81406
81465
|
const { data, error: error3 } = await q;
|
|
81407
81466
|
if (error3)
|
|
81408
81467
|
throw error3;
|
|
81409
|
-
return data ?? []
|
|
81468
|
+
return (data ?? []).map((row) => {
|
|
81469
|
+
const { cerefox_document_projects: _j, ...doc2 } = row;
|
|
81470
|
+
return doc2;
|
|
81471
|
+
});
|
|
81410
81472
|
}
|
|
81411
81473
|
async function listAllProjects(ctx) {
|
|
81412
81474
|
const { data, error: error3 } = await ctx.supabase.from("cerefox_projects").select("*").order("name");
|
|
@@ -81444,10 +81506,8 @@ async function getProjectDocCounts(ctx, projectIds) {
|
|
|
81444
81506
|
if (projectIds.length === 0)
|
|
81445
81507
|
return { active, deleted };
|
|
81446
81508
|
try {
|
|
81447
|
-
const
|
|
81448
|
-
|
|
81449
|
-
throw error3;
|
|
81450
|
-
for (const row of data ?? []) {
|
|
81509
|
+
const rows = await fetchAllPages((from, to) => ctx.supabase.from("cerefox_document_projects").select("project_id, cerefox_documents(deleted_at)").in("project_id", projectIds).order("document_id", { ascending: true }).order("project_id", { ascending: true }).range(from, to));
|
|
81510
|
+
for (const row of rows) {
|
|
81451
81511
|
const pid = row.project_id;
|
|
81452
81512
|
if (!(pid in active))
|
|
81453
81513
|
continue;
|
|
@@ -81491,16 +81551,13 @@ async function getRecentDocAuthors(ctx, docIds) {
|
|
|
81491
81551
|
return out;
|
|
81492
81552
|
}
|
|
81493
81553
|
async function countDocumentsForProject(ctx, projectId) {
|
|
81494
|
-
const {
|
|
81554
|
+
const { count, error: error3 } = await ctx.supabase.from("cerefox_document_projects").select("document_id, cerefox_documents!inner(deleted_at)", {
|
|
81555
|
+
count: "exact",
|
|
81556
|
+
head: true
|
|
81557
|
+
}).eq("project_id", projectId).is("cerefox_documents.deleted_at", null);
|
|
81495
81558
|
if (error3)
|
|
81496
81559
|
throw error3;
|
|
81497
|
-
|
|
81498
|
-
for (const row of data ?? []) {
|
|
81499
|
-
if (row.cerefox_documents && row.cerefox_documents.deleted_at === null) {
|
|
81500
|
-
n += 1;
|
|
81501
|
-
}
|
|
81502
|
-
}
|
|
81503
|
-
return n;
|
|
81560
|
+
return count ?? 0;
|
|
81504
81561
|
}
|
|
81505
81562
|
function dashboardDocFromRow(row, projectIds) {
|
|
81506
81563
|
return {
|
|
@@ -81527,7 +81584,8 @@ function projectDocResult(r) {
|
|
|
81527
81584
|
chunk_count: r.chunk_count ?? 0,
|
|
81528
81585
|
total_chars: r.total_chars ?? 0,
|
|
81529
81586
|
doc_updated_at: r.doc_updated_at ?? null,
|
|
81530
|
-
is_partial: r.is_partial ?? false
|
|
81587
|
+
is_partial: r.is_partial ?? false,
|
|
81588
|
+
below_confidence: r.below_confidence ?? false
|
|
81531
81589
|
};
|
|
81532
81590
|
}
|
|
81533
81591
|
function projectChunkResult(r) {
|
|
@@ -81543,7 +81601,8 @@ function projectChunkResult(r) {
|
|
|
81543
81601
|
doc_title: r.doc_title ?? "",
|
|
81544
81602
|
doc_source: r.doc_source ?? null,
|
|
81545
81603
|
doc_project_ids: r.doc_project_ids ?? [],
|
|
81546
|
-
doc_metadata: r.doc_metadata ?? {}
|
|
81604
|
+
doc_metadata: r.doc_metadata ?? {},
|
|
81605
|
+
below_confidence: r.below_confidence ?? false
|
|
81547
81606
|
};
|
|
81548
81607
|
}
|
|
81549
81608
|
async function runSearch(ctx, opts) {
|
|
@@ -82023,7 +82082,7 @@ function registerDocumentReadRoutes(app, ctx) {
|
|
|
82023
82082
|
});
|
|
82024
82083
|
app.get("/api/v1/documents/:document_id/chunks", async (c2) => {
|
|
82025
82084
|
const documentId = c2.req.param("document_id");
|
|
82026
|
-
const { data, error: error3 } = await ctx.supabase.from("cerefox_chunks").select("id, document_id, chunk_index, heading_path, heading_level, title, content, char_count").eq("document_id", documentId).is("version_id", null).order("chunk_index");
|
|
82085
|
+
const { data, error: error3 } = await ctx.supabase.from("cerefox_chunks").select("id, document_id, chunk_index, heading_path, heading_level, title, content, char_count").eq("document_id", documentId).is("version_id", null).order("chunk_index").range(0, 4999);
|
|
82027
82086
|
if (error3)
|
|
82028
82087
|
return c2.json({ detail: error3.message }, 500);
|
|
82029
82088
|
const rows = data ?? [];
|