@tangle-network/agent-knowledge 20.0.0 → 21.0.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/CHANGELOG.md +15 -0
- package/README.md +6 -5
- package/dist/cli.js +2 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +100 -118
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +242 -3
- package/dist/index.js.map +1 -1
- package/dist/{inspect-CMigdsD5.js → inspect-DXN6SE2o.js} +277 -295
- package/dist/inspect-DXN6SE2o.js.map +1 -0
- package/dist/search/index.d.ts +3 -0
- package/dist/search/index.js +2 -0
- package/dist/search-BBr5eUyT.js +275 -0
- package/dist/search-BBr5eUyT.js.map +1 -0
- package/dist/search-Dde0PEtY.d.ts +120 -0
- package/dist/search-Dde0PEtY.d.ts.map +1 -0
- package/docs/agent-tools.md +60 -0
- package/docs/architecture.md +40 -1
- package/docs/cli.md +19 -0
- package/docs/compatibility.md +11 -0
- package/docs/improvement.md +79 -0
- package/docs/memory.md +12 -0
- package/docs/provenance.md +50 -0
- package/docs/rag-evaluation.md +82 -0
- package/package.json +13 -7
- package/dist/inspect-CMigdsD5.js.map +0 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { i as textSourceId, n as slugify, r as stableId, t as sha256 } from "./ids-Bevz_pXV.js";
|
|
2
|
+
import { r as searchKnowledge } from "./search-BBr5eUyT.js";
|
|
2
3
|
import { canonicalCandidateBytes, canonicalCandidateDigest, sha256Bytes, sha256DigestSchema } from "@tangle-network/agent-interface";
|
|
3
4
|
import { contentHash } from "@tangle-network/agent-eval";
|
|
4
5
|
import { z } from "zod";
|
|
5
6
|
import { createHash, randomUUID } from "node:crypto";
|
|
6
|
-
import { constants, lstatSync } from "node:fs";
|
|
7
|
+
import { closeSync, constants, fstatSync, lstatSync, openSync, readFileSync } from "node:fs";
|
|
7
8
|
import { lstat, mkdir, mkdtemp, open, readFile, readdir, realpath, rename, rm } from "node:fs/promises";
|
|
8
9
|
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
9
10
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -399,6 +400,19 @@ function normalizePagesDirectory(value = DEFAULT_PAGES_DIRECTORY) {
|
|
|
399
400
|
return normalized;
|
|
400
401
|
}
|
|
401
402
|
//#endregion
|
|
403
|
+
//#region src/bounded-file-io.ts
|
|
404
|
+
/** Keep filesystem descriptors bounded and drain a failed batch before its owner releases handles. */
|
|
405
|
+
async function mapFileIo(values, operation) {
|
|
406
|
+
const results = [];
|
|
407
|
+
for (let start = 0; start < values.length; start += 8) {
|
|
408
|
+
const batch = await Promise.allSettled(values.slice(start, start + 8).map((value, offset) => Promise.resolve().then(() => operation(value, start + offset))));
|
|
409
|
+
const failed = batch.find((result) => result.status === "rejected");
|
|
410
|
+
if (failed?.status === "rejected") throw failed.reason;
|
|
411
|
+
for (const result of batch) if (result.status === "fulfilled") results.push(result.value);
|
|
412
|
+
}
|
|
413
|
+
return results;
|
|
414
|
+
}
|
|
415
|
+
//#endregion
|
|
402
416
|
//#region src/file-transaction.ts
|
|
403
417
|
const digestSchema = z.string().regex(/^[a-f0-9]{64}$/);
|
|
404
418
|
const fileModeSchema = z.number().int().min(0).max(511);
|
|
@@ -460,7 +474,7 @@ async function prepareKnowledgeFileTransaction(input) {
|
|
|
460
474
|
const activeTransactions = await activeTransactionDirectoryNames(transactionRoot);
|
|
461
475
|
if (activeTransactions.length > 0) throw new Error(`knowledge file transaction is already active: ${activeTransactions.join(", ")}`);
|
|
462
476
|
const paths = /* @__PURE__ */ new Set();
|
|
463
|
-
const changed = (await
|
|
477
|
+
const changed = (await mapFileIo(input.mutations, async (mutation, index) => {
|
|
464
478
|
const path = assertKnowledgeMutationPath(mutation.path, boundPagesDirectory, input.researchState);
|
|
465
479
|
if (paths.has(path)) throw new Error(`knowledge file transaction repeats path: ${path}`);
|
|
466
480
|
if (mutation.content === null && mutation.mode !== void 0) throw new Error(`deleted knowledge file cannot declare a mode: ${path}`);
|
|
@@ -485,7 +499,7 @@ async function prepareKnowledgeFileTransaction(input) {
|
|
|
485
499
|
before: before?.bytes ?? null,
|
|
486
500
|
after
|
|
487
501
|
};
|
|
488
|
-
}))
|
|
502
|
+
})).filter((entry) => entry !== null);
|
|
489
503
|
if (changed.length === 0) return null;
|
|
490
504
|
const preparationDir = await mkdtemp(join(transactionRoot, "prepare-"));
|
|
491
505
|
let activated = false;
|
|
@@ -504,10 +518,14 @@ async function prepareKnowledgeFileTransaction(input) {
|
|
|
504
518
|
entries: changed.map((item) => item.entry)
|
|
505
519
|
});
|
|
506
520
|
for (const side of ["before", "after"]) if (changed.some((item) => item[side])) await mkdir(join(preparationDir, side));
|
|
507
|
-
await
|
|
521
|
+
await mapFileIo(changed.flatMap((item) => ["before", "after"].flatMap((side) => {
|
|
508
522
|
const bytes = item[side];
|
|
509
|
-
return bytes ? [
|
|
510
|
-
|
|
523
|
+
return bytes ? [{
|
|
524
|
+
path: snapshotPath(preparationDir, side, item.entry.index),
|
|
525
|
+
bytes
|
|
526
|
+
}] : [];
|
|
527
|
+
})), (item) => writeFileDurable(item.path, item.bytes));
|
|
528
|
+
await writeJsonDurable(join(preparationDir, "transaction.json"), transaction);
|
|
511
529
|
const activeDir = join(transactionRoot, activeTransactionDirectoryName(transaction.transactionId));
|
|
512
530
|
await renameDurable(preparationDir, activeDir);
|
|
513
531
|
activated = true;
|
|
@@ -833,7 +851,7 @@ function knowledgeMutationPathPrefixes(pagesDirectory) {
|
|
|
833
851
|
}
|
|
834
852
|
function assertKnowledgeMutationPath(path, pagesDirectory, researchState = false) {
|
|
835
853
|
const normalized = normalizeTransactionPath(path);
|
|
836
|
-
if (normalized === SOURCE_REGISTRY_PATH || researchState && (normalized === ".agent-knowledge/events.json" || /^\.agent-knowledge\/claim-ledgers\/[^/]+\.json$/.test(normalized)) || knowledgeMutationPathPrefixes(pagesDirectory).some((prefix) => normalized.startsWith(prefix))) return normalized;
|
|
854
|
+
if (normalized === SOURCE_REGISTRY_PATH || researchState && (normalized === ".agent-knowledge/events.json" || normalized === "events.json" || /^(?:\.agent-knowledge\/)?event-log\/(?:state\.json|(?:records\/[a-f0-9]{64}|index\/[a-f0-9]{2,64})\.json)$/.test(normalized) || /^\.agent-knowledge\/claim-ledgers\/[^/]+\.json$/.test(normalized)) || knowledgeMutationPathPrefixes(pagesDirectory).some((prefix) => normalized.startsWith(prefix))) return normalized;
|
|
837
855
|
throw new Error(`knowledge transaction contains an unsupported path: ${path}`);
|
|
838
856
|
}
|
|
839
857
|
function normalizeTransactionPath(path) {
|
|
@@ -2448,6 +2466,249 @@ function citedPageId(persisted) {
|
|
|
2448
2466
|
}
|
|
2449
2467
|
}
|
|
2450
2468
|
//#endregion
|
|
2469
|
+
//#region src/event-store.ts
|
|
2470
|
+
/** Durable immutable event payloads with bounded, hash-partitioned metadata buckets. */
|
|
2471
|
+
const stateSchema = z.object({
|
|
2472
|
+
version: z.literal(1),
|
|
2473
|
+
sequence: z.number().int().nonnegative().safe(),
|
|
2474
|
+
count: z.number().int().nonnegative().safe()
|
|
2475
|
+
}).strict();
|
|
2476
|
+
const entrySchema = z.object({
|
|
2477
|
+
id: z.string().min(1),
|
|
2478
|
+
createdAt: z.string().min(1),
|
|
2479
|
+
type: KnowledgeEventSchema.shape.type,
|
|
2480
|
+
target: z.string().optional(),
|
|
2481
|
+
sequence: z.number().int().nonnegative().safe(),
|
|
2482
|
+
digest: z.string().regex(/^[a-f0-9]{64}$/)
|
|
2483
|
+
}).strict();
|
|
2484
|
+
const MAX_BUCKET_ENTRIES = 256;
|
|
2485
|
+
const bucketSchema = z.discriminatedUnion("kind", [z.object({ kind: z.literal("branch") }).strict(), z.object({
|
|
2486
|
+
kind: z.literal("leaf"),
|
|
2487
|
+
entries: z.array(entrySchema).max(MAX_BUCKET_ENTRIES)
|
|
2488
|
+
}).strict()]);
|
|
2489
|
+
const encode = (value) => `${JSON.stringify(value)}\n`;
|
|
2490
|
+
const recordPath = (directory, digest) => `${directory}/records/${digest}.json`;
|
|
2491
|
+
const bucketPath = (directory, prefix) => `${directory}/index/${prefix}.json`;
|
|
2492
|
+
async function readOptional(root, path) {
|
|
2493
|
+
try {
|
|
2494
|
+
return (await readRegularFileWithinRoot(root, path)).bytes;
|
|
2495
|
+
} catch (error) {
|
|
2496
|
+
if (isMissingFile(error)) return void 0;
|
|
2497
|
+
throw error;
|
|
2498
|
+
}
|
|
2499
|
+
}
|
|
2500
|
+
async function assertNoLegacy(root, path) {
|
|
2501
|
+
if (await withSafeDescendant(root, path, async (target) => {
|
|
2502
|
+
try {
|
|
2503
|
+
await lstat(target);
|
|
2504
|
+
return true;
|
|
2505
|
+
} catch (error) {
|
|
2506
|
+
if (isMissingFile(error)) return false;
|
|
2507
|
+
throw error;
|
|
2508
|
+
}
|
|
2509
|
+
})) throw new Error("legacy event history reappeared after migration; reconcile the older writer before proceeding");
|
|
2510
|
+
}
|
|
2511
|
+
function ordered(entries) {
|
|
2512
|
+
return entries.sort((a, b) => a.createdAt.localeCompare(b.createdAt) || a.sequence - b.sequence);
|
|
2513
|
+
}
|
|
2514
|
+
async function putStoredEvent(root, legacyPath, event) {
|
|
2515
|
+
const directory = legacyPath === "events.json" ? "event-log" : ".agent-knowledge/event-log";
|
|
2516
|
+
const statePath = `${directory}/state.json`;
|
|
2517
|
+
const parsed = KnowledgeEventSchema.parse(structuredClone(event));
|
|
2518
|
+
const purpose = `event-put:${sha256(encode({
|
|
2519
|
+
legacyPath,
|
|
2520
|
+
event: parsed
|
|
2521
|
+
}))}`;
|
|
2522
|
+
await withKnowledgeMutation(root, async (lock) => {
|
|
2523
|
+
const saved = await readOptional(root, statePath);
|
|
2524
|
+
let sequence = 0;
|
|
2525
|
+
let count = 0;
|
|
2526
|
+
const mutations = /* @__PURE__ */ new Map();
|
|
2527
|
+
const add = (path, content) => mutations.set(path, {
|
|
2528
|
+
path,
|
|
2529
|
+
content
|
|
2530
|
+
});
|
|
2531
|
+
const bucketCache = /* @__PURE__ */ new Map();
|
|
2532
|
+
const writeBucket = (prefix, entries) => {
|
|
2533
|
+
const writeTree = (prefix, entries) => {
|
|
2534
|
+
if (entries.length <= MAX_BUCKET_ENTRIES) {
|
|
2535
|
+
const bucket = {
|
|
2536
|
+
kind: "leaf",
|
|
2537
|
+
entries: entries.sort((a, b) => a.id.localeCompare(b.id))
|
|
2538
|
+
};
|
|
2539
|
+
bucketCache.set(prefix, bucket);
|
|
2540
|
+
add(bucketPath(directory, prefix), encode(bucket));
|
|
2541
|
+
return;
|
|
2542
|
+
}
|
|
2543
|
+
if (prefix.length >= 64) throw new Error("event id hash collision");
|
|
2544
|
+
const branch = { kind: "branch" };
|
|
2545
|
+
bucketCache.set(prefix, branch);
|
|
2546
|
+
add(bucketPath(directory, prefix), encode(branch));
|
|
2547
|
+
const groups = /* @__PURE__ */ new Map();
|
|
2548
|
+
for (const entry of entries) {
|
|
2549
|
+
const child = sha256(entry.id).slice(0, prefix.length + 1);
|
|
2550
|
+
const group = groups.get(child) ?? [];
|
|
2551
|
+
group.push(entry);
|
|
2552
|
+
groups.set(child, group);
|
|
2553
|
+
}
|
|
2554
|
+
for (const [child, group] of groups) writeTree(child, group);
|
|
2555
|
+
};
|
|
2556
|
+
writeTree(prefix, entries);
|
|
2557
|
+
};
|
|
2558
|
+
const putIndexEntry = async (entry) => {
|
|
2559
|
+
const idHash = sha256(entry.id);
|
|
2560
|
+
for (let length = 2; length <= 64; length++) {
|
|
2561
|
+
const prefix = idHash.slice(0, length);
|
|
2562
|
+
let bucket = bucketCache.get(prefix);
|
|
2563
|
+
if (!bucket) {
|
|
2564
|
+
const bytes = await readOptional(root, bucketPath(directory, prefix));
|
|
2565
|
+
bucket = bytes ? parseBucket(prefix, bytes, sequence) : {
|
|
2566
|
+
kind: "leaf",
|
|
2567
|
+
entries: []
|
|
2568
|
+
};
|
|
2569
|
+
bucketCache.set(prefix, bucket);
|
|
2570
|
+
}
|
|
2571
|
+
if (bucket.kind === "branch") continue;
|
|
2572
|
+
if (!bucket.entries.some((value) => value.id === entry.id)) count += 1;
|
|
2573
|
+
writeBucket(prefix, [...bucket.entries.filter((value) => value.id !== entry.id), entry]);
|
|
2574
|
+
return;
|
|
2575
|
+
}
|
|
2576
|
+
throw new Error("event index has an invalid terminal branch");
|
|
2577
|
+
};
|
|
2578
|
+
const append = async (value) => {
|
|
2579
|
+
if (sequence >= Number.MAX_SAFE_INTEGER) throw new Error("event sequence exhausted");
|
|
2580
|
+
sequence += 1;
|
|
2581
|
+
const content = encode(value);
|
|
2582
|
+
const digest = sha256(content);
|
|
2583
|
+
add(recordPath(directory, digest), content);
|
|
2584
|
+
await putIndexEntry({
|
|
2585
|
+
id: value.id,
|
|
2586
|
+
createdAt: value.createdAt,
|
|
2587
|
+
type: value.type,
|
|
2588
|
+
...value.target === void 0 ? {} : { target: value.target },
|
|
2589
|
+
sequence,
|
|
2590
|
+
digest
|
|
2591
|
+
});
|
|
2592
|
+
};
|
|
2593
|
+
if (saved) {
|
|
2594
|
+
const state = stateSchema.parse(JSON.parse(saved.toString("utf8")));
|
|
2595
|
+
sequence = state.sequence;
|
|
2596
|
+
count = state.count;
|
|
2597
|
+
await assertNoLegacy(root, legacyPath);
|
|
2598
|
+
} else {
|
|
2599
|
+
await assertEmptyLog(root, directory);
|
|
2600
|
+
const legacy = await readOptional(root, legacyPath);
|
|
2601
|
+
if (legacy) {
|
|
2602
|
+
const events = z.array(KnowledgeEventSchema).parse(JSON.parse(legacy.toString("utf8")));
|
|
2603
|
+
for (const value of events) await append(value);
|
|
2604
|
+
add(legacyPath, null);
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
2607
|
+
await append(parsed);
|
|
2608
|
+
add(statePath, encode({
|
|
2609
|
+
version: 1,
|
|
2610
|
+
sequence,
|
|
2611
|
+
count
|
|
2612
|
+
}));
|
|
2613
|
+
await commitKnowledgeFileMutations({
|
|
2614
|
+
root,
|
|
2615
|
+
transactionRoot: lock.transactionRoot,
|
|
2616
|
+
purpose,
|
|
2617
|
+
researchState: true,
|
|
2618
|
+
mutations: [...mutations.values()],
|
|
2619
|
+
assertOwned: lock.assertOwned
|
|
2620
|
+
});
|
|
2621
|
+
}, { resumeTransaction: { purpose } });
|
|
2622
|
+
}
|
|
2623
|
+
async function listStoredEvents(root, legacyPath, query) {
|
|
2624
|
+
const directory = legacyPath === "events.json" ? "event-log" : ".agent-knowledge/event-log";
|
|
2625
|
+
const statePath = `${directory}/state.json`;
|
|
2626
|
+
return withKnowledgeRead(root, async () => {
|
|
2627
|
+
const saved = await readOptional(root, statePath);
|
|
2628
|
+
if (!saved) {
|
|
2629
|
+
await assertEmptyLog(root, directory);
|
|
2630
|
+
const bytes = await readOptional(root, legacyPath);
|
|
2631
|
+
let events = bytes ? z.array(KnowledgeEventSchema).parse(JSON.parse(bytes.toString("utf8"))) : [];
|
|
2632
|
+
if (query.type) events = events.filter((event) => event.type === query.type);
|
|
2633
|
+
if (query.target) events = events.filter((event) => event.target === query.target);
|
|
2634
|
+
return events.slice(-(query.limit ?? events.length));
|
|
2635
|
+
}
|
|
2636
|
+
const state = stateSchema.parse(JSON.parse(saved.toString("utf8")));
|
|
2637
|
+
await assertNoLegacy(root, legacyPath);
|
|
2638
|
+
const entries = [];
|
|
2639
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
2640
|
+
for (const file of await readEventIndex(root, `${directory}/index`)) {
|
|
2641
|
+
const prefix = file.path.slice(`${directory}/index/`.length, -5);
|
|
2642
|
+
buckets.set(prefix, parseBucket(prefix, file.bytes, state.sequence));
|
|
2643
|
+
}
|
|
2644
|
+
let count = 0;
|
|
2645
|
+
for (const [prefix, bucket] of buckets) {
|
|
2646
|
+
for (let length = 2; length < prefix.length; length++) if (buckets.get(prefix.slice(0, length))?.kind !== "branch") throw new Error("event index has an orphaned bucket");
|
|
2647
|
+
if (bucket.kind === "branch") {
|
|
2648
|
+
if (![...buckets.keys()].some((child) => child.length === prefix.length + 1 && child.startsWith(prefix))) throw new Error("event index branch has no children");
|
|
2649
|
+
continue;
|
|
2650
|
+
}
|
|
2651
|
+
count += bucket.entries.length;
|
|
2652
|
+
for (const entry of bucket.entries) {
|
|
2653
|
+
if (query.type && entry.type !== query.type) continue;
|
|
2654
|
+
if (query.target && entry.target !== query.target) continue;
|
|
2655
|
+
entries.push(entry);
|
|
2656
|
+
}
|
|
2657
|
+
}
|
|
2658
|
+
if (count !== state.count) throw new Error("event index entry count mismatch");
|
|
2659
|
+
return mapFileIo(ordered(entries).slice(-(query.limit ?? entries.length)), async (entry) => {
|
|
2660
|
+
const bytes = (await readRegularFileWithinRoot(root, recordPath(directory, entry.digest))).bytes;
|
|
2661
|
+
if (createHash("sha256").update(bytes).digest("hex") !== entry.digest) throw new Error("event payload digest mismatch");
|
|
2662
|
+
const event = KnowledgeEventSchema.parse(JSON.parse(bytes.toString("utf8")));
|
|
2663
|
+
if (event.id !== entry.id || event.createdAt !== entry.createdAt || event.type !== entry.type || event.target !== entry.target) throw new Error("event payload index mismatch");
|
|
2664
|
+
return event;
|
|
2665
|
+
});
|
|
2666
|
+
});
|
|
2667
|
+
}
|
|
2668
|
+
async function assertEmptyLog(root, directory) {
|
|
2669
|
+
try {
|
|
2670
|
+
if ((await listRegularFilesWithinRoot(root, directory)).length) throw new Error("event log state is missing; recover the log before proceeding");
|
|
2671
|
+
} catch (error) {
|
|
2672
|
+
if (!isMissingFile(error)) throw error;
|
|
2673
|
+
}
|
|
2674
|
+
}
|
|
2675
|
+
async function readEventIndex(root, relativeDirectory) {
|
|
2676
|
+
return withSafeDirectory(root, relativeDirectory, false, async (directory) => {
|
|
2677
|
+
const entries = await readdir(directory, { withFileTypes: true });
|
|
2678
|
+
const files = [];
|
|
2679
|
+
for (let start = 0; start < entries.length; start += 64) {
|
|
2680
|
+
if (start > 0) await new Promise((resolve) => setImmediate(resolve));
|
|
2681
|
+
for (const entry of entries.slice(start, start + 64)) {
|
|
2682
|
+
if (!entry.isFile() || !/^[a-f0-9]{2,64}\.json$/.test(entry.name)) throw new Error("event index contains an unsupported entry");
|
|
2683
|
+
const fd = openSync(join(directory, entry.name), constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
2684
|
+
try {
|
|
2685
|
+
if (!fstatSync(fd).isFile()) throw new Error("event index contains an unsupported entry");
|
|
2686
|
+
files.push({
|
|
2687
|
+
path: `${relativeDirectory}/${entry.name}`,
|
|
2688
|
+
bytes: readFileSync(fd)
|
|
2689
|
+
});
|
|
2690
|
+
} finally {
|
|
2691
|
+
closeSync(fd);
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2694
|
+
}
|
|
2695
|
+
return files;
|
|
2696
|
+
});
|
|
2697
|
+
}
|
|
2698
|
+
function parseBucket(prefix, bytes, sequence) {
|
|
2699
|
+
const bucket = bucketSchema.parse(JSON.parse(bytes.toString("utf8")));
|
|
2700
|
+
if (bucket.kind === "branch") {
|
|
2701
|
+
if (prefix.length >= 64) throw new Error("event index has an invalid terminal branch");
|
|
2702
|
+
return bucket;
|
|
2703
|
+
}
|
|
2704
|
+
const ids = /* @__PURE__ */ new Set();
|
|
2705
|
+
for (const entry of bucket.entries) {
|
|
2706
|
+
if (!sha256(entry.id).startsWith(prefix) || entry.sequence > sequence || ids.has(entry.id)) throw new Error("event index identity mismatch");
|
|
2707
|
+
ids.add(entry.id);
|
|
2708
|
+
}
|
|
2709
|
+
return bucket;
|
|
2710
|
+
}
|
|
2711
|
+
//#endregion
|
|
2451
2712
|
//#region src/kb-store.ts
|
|
2452
2713
|
/**
|
|
2453
2714
|
* Where a filesystem knowledge base keeps its machine-written records, relative
|
|
@@ -2462,6 +2723,7 @@ function citedPageId(persisted) {
|
|
|
2462
2723
|
*/
|
|
2463
2724
|
const KB_STORE_DIR = ".agent-knowledge";
|
|
2464
2725
|
const KB_INDEX_PATH = `${KB_STORE_DIR}/index.json`;
|
|
2726
|
+
/** Legacy array import path; new events live in the adjacent event-log directory. */
|
|
2465
2727
|
const KB_EVENTS_PATH = `${KB_STORE_DIR}/events.json`;
|
|
2466
2728
|
const KB_CLAIM_LEDGER_DIR = `${KB_STORE_DIR}/claim-ledgers`;
|
|
2467
2729
|
/**
|
|
@@ -2525,6 +2787,8 @@ var MemoryKbStore = class {
|
|
|
2525
2787
|
};
|
|
2526
2788
|
}
|
|
2527
2789
|
async putEvent(event) {
|
|
2790
|
+
const position = this.events.findIndex((entry) => entry.id === event.id);
|
|
2791
|
+
if (position !== -1) this.events.splice(position, 1);
|
|
2528
2792
|
this.events.push(clone(event));
|
|
2529
2793
|
}
|
|
2530
2794
|
async listEvents(query = {}) {
|
|
@@ -2551,7 +2815,6 @@ var MemoryKbStore = class {
|
|
|
2551
2815
|
return clone(next);
|
|
2552
2816
|
}
|
|
2553
2817
|
};
|
|
2554
|
-
const knowledgeEventsSchema = z.array(KnowledgeEventSchema);
|
|
2555
2818
|
var FileSystemKbStore = class {
|
|
2556
2819
|
root;
|
|
2557
2820
|
indexPath;
|
|
@@ -2616,19 +2879,10 @@ var FileSystemKbStore = class {
|
|
|
2616
2879
|
return withKnowledgeRead(this.root, () => this.readIndex());
|
|
2617
2880
|
}
|
|
2618
2881
|
async putEvent(event) {
|
|
2619
|
-
|
|
2620
|
-
await withKnowledgeMutation(this.root, async () => {
|
|
2621
|
-
const next = [...(await this.readEvents()).filter((entry) => entry.id !== parsed.id), parsed].sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
2622
|
-
await writeJsonDurableWithinRoot(this.root, this.eventsPath, next);
|
|
2623
|
-
});
|
|
2882
|
+
await putStoredEvent(this.root, this.eventsPath, event);
|
|
2624
2883
|
}
|
|
2625
2884
|
async listEvents(query = {}) {
|
|
2626
|
-
return
|
|
2627
|
-
let events = await this.readEvents();
|
|
2628
|
-
if (query.type) events = events.filter((event) => event.type === query.type);
|
|
2629
|
-
if (query.target) events = events.filter((event) => event.target === query.target);
|
|
2630
|
-
return clone(events.slice(-(query.limit ?? events.length)));
|
|
2631
|
-
});
|
|
2885
|
+
return this.readEvents(query);
|
|
2632
2886
|
}
|
|
2633
2887
|
async putClaimLedger(ledger) {
|
|
2634
2888
|
const parsed = parseResearchClaimLedger(ledger);
|
|
@@ -2678,8 +2932,8 @@ var FileSystemKbStore = class {
|
|
|
2678
2932
|
async readIndex() {
|
|
2679
2933
|
return readJsonFile(this.root, this.indexPath, KnowledgeIndexSchema);
|
|
2680
2934
|
}
|
|
2681
|
-
async readEvents() {
|
|
2682
|
-
return
|
|
2935
|
+
async readEvents(query = {}) {
|
|
2936
|
+
return listStoredEvents(this.root, this.eventsPath, query);
|
|
2683
2937
|
}
|
|
2684
2938
|
claimLedgerPath(id) {
|
|
2685
2939
|
return `${this.claimLedgerDir}/${assertClaimLedgerId(id)}.json`;
|
|
@@ -4556,278 +4810,6 @@ function stringMetadata(metadata, key) {
|
|
|
4556
4810
|
return typeof value === "string" ? value : void 0;
|
|
4557
4811
|
}
|
|
4558
4812
|
//#endregion
|
|
4559
|
-
//#region src/lexical-postings.ts
|
|
4560
|
-
const DEFAULT_FIELD_BOOSTS = Object.freeze({
|
|
4561
|
-
title: 3,
|
|
4562
|
-
path: 2,
|
|
4563
|
-
text: 1
|
|
4564
|
-
});
|
|
4565
|
-
function lexicalPageTerms(page, tokenize, fieldBoosts) {
|
|
4566
|
-
const frequencies = /* @__PURE__ */ new Map();
|
|
4567
|
-
let length = 0;
|
|
4568
|
-
for (const [text, boost] of [
|
|
4569
|
-
[page.title, fieldBoosts.title],
|
|
4570
|
-
[page.path.replace(/\.md$/, ""), fieldBoosts.path],
|
|
4571
|
-
[page.text, fieldBoosts.text]
|
|
4572
|
-
]) {
|
|
4573
|
-
if (boost === 0) continue;
|
|
4574
|
-
for (const token of tokenize(text)) {
|
|
4575
|
-
frequencies.set(token, (frequencies.get(token) ?? 0) + boost);
|
|
4576
|
-
length += boost;
|
|
4577
|
-
}
|
|
4578
|
-
}
|
|
4579
|
-
return {
|
|
4580
|
-
frequencies,
|
|
4581
|
-
length
|
|
4582
|
-
};
|
|
4583
|
-
}
|
|
4584
|
-
/** Inverted index from per-page terms already computed with `tokenize` and `fieldBoosts`. */
|
|
4585
|
-
function assembleLexicalIndex(pages, terms, tokenize, fieldBoosts) {
|
|
4586
|
-
const postings = /* @__PURE__ */ new Map();
|
|
4587
|
-
const documentLengths = [];
|
|
4588
|
-
let totalLength = 0;
|
|
4589
|
-
terms.forEach(({ frequencies, length }, ordinal) => {
|
|
4590
|
-
documentLengths.push(length);
|
|
4591
|
-
totalLength += length;
|
|
4592
|
-
for (const [term, tf] of frequencies) {
|
|
4593
|
-
let list = postings.get(term);
|
|
4594
|
-
if (!list) {
|
|
4595
|
-
list = [];
|
|
4596
|
-
postings.set(term, list);
|
|
4597
|
-
}
|
|
4598
|
-
list.push({
|
|
4599
|
-
ordinal,
|
|
4600
|
-
tf
|
|
4601
|
-
});
|
|
4602
|
-
}
|
|
4603
|
-
});
|
|
4604
|
-
return {
|
|
4605
|
-
pages,
|
|
4606
|
-
postings,
|
|
4607
|
-
documentLengths,
|
|
4608
|
-
averageDocumentLength: pages.length > 0 ? totalLength / pages.length : 0,
|
|
4609
|
-
documentCount: pages.length,
|
|
4610
|
-
tokenize,
|
|
4611
|
-
fieldBoosts
|
|
4612
|
-
};
|
|
4613
|
-
}
|
|
4614
|
-
//#endregion
|
|
4615
|
-
//#region src/lexical-index.ts
|
|
4616
|
-
const STOP_WORDS = /* @__PURE__ */ new Set([
|
|
4617
|
-
"the",
|
|
4618
|
-
"is",
|
|
4619
|
-
"a",
|
|
4620
|
-
"an",
|
|
4621
|
-
"what",
|
|
4622
|
-
"how",
|
|
4623
|
-
"are",
|
|
4624
|
-
"was",
|
|
4625
|
-
"were",
|
|
4626
|
-
"to",
|
|
4627
|
-
"for",
|
|
4628
|
-
"of",
|
|
4629
|
-
"with",
|
|
4630
|
-
"by",
|
|
4631
|
-
"in",
|
|
4632
|
-
"on",
|
|
4633
|
-
"and"
|
|
4634
|
-
]);
|
|
4635
|
-
/**
|
|
4636
|
-
* The token stream of one text: lower-cased, split on whitespace and
|
|
4637
|
-
* punctuation, single characters and stop words removed, and a CJK run
|
|
4638
|
-
* expanded into its bigrams and characters. Repeats are kept so a term
|
|
4639
|
-
* frequency can be counted. Indexing and querying share this function, so the
|
|
4640
|
-
* two vocabularies cannot drift.
|
|
4641
|
-
*/
|
|
4642
|
-
function tokenizeText(text) {
|
|
4643
|
-
const raw = text.toLowerCase().split(/[\s,,。!?、;:""''()()\-_/\\·~~…]+/).filter((token) => token.length > 1 && !STOP_WORDS.has(token));
|
|
4644
|
-
const tokens = [];
|
|
4645
|
-
for (const token of raw) {
|
|
4646
|
-
if (/[\u4e00-\u9fff\u3400-\u4dbf]/.test(token) && token.length > 2) {
|
|
4647
|
-
const chars = [...token];
|
|
4648
|
-
for (let i = 0; i < chars.length - 1; i++) tokens.push(chars[i] + chars[i + 1]);
|
|
4649
|
-
tokens.push(...chars);
|
|
4650
|
-
}
|
|
4651
|
-
tokens.push(token);
|
|
4652
|
-
}
|
|
4653
|
-
return tokens;
|
|
4654
|
-
}
|
|
4655
|
-
/** The distinct query terms, in first-occurrence order. */
|
|
4656
|
-
function tokenizeQuery(query) {
|
|
4657
|
-
return [...new Set(tokenizeText(query))];
|
|
4658
|
-
}
|
|
4659
|
-
function buildKnowledgeLexicalIndex(pages, options = {}) {
|
|
4660
|
-
const tokenize = options.tokenize ?? tokenizeText;
|
|
4661
|
-
const fieldBoosts = resolveFieldBoosts(options.fieldBoosts);
|
|
4662
|
-
return assembleLexicalIndex(pages, pages.map((page) => lexicalPageTerms(page, tokenize, fieldBoosts)), tokenize, fieldBoosts);
|
|
4663
|
-
}
|
|
4664
|
-
/**
|
|
4665
|
-
* Okapi BM25 over the distinct query terms, with the Lucene inverse document
|
|
4666
|
-
* frequency `ln(1 + (N - df + 0.5) / (df + 0.5))`, which is positive for every
|
|
4667
|
-
* indexed term. Pages with no matching term are absent. The result is ordered
|
|
4668
|
-
* by score, then by path, so it does not depend on page order.
|
|
4669
|
-
*/
|
|
4670
|
-
function scoreBm25(index, tokens, options = {}) {
|
|
4671
|
-
const k1 = options.k1 ?? 1.2;
|
|
4672
|
-
const b = options.b ?? .75;
|
|
4673
|
-
if (!Number.isFinite(k1) || k1 < 0) throw new Error(`bm25 k1 must be >= 0, got ${String(k1)}`);
|
|
4674
|
-
if (!Number.isFinite(b) || b < 0 || b > 1) throw new Error(`bm25 b must lie in [0, 1], got ${String(b)}`);
|
|
4675
|
-
const scores = /* @__PURE__ */ new Map();
|
|
4676
|
-
const { documentCount, averageDocumentLength, documentLengths } = index;
|
|
4677
|
-
for (const term of new Set(tokens)) {
|
|
4678
|
-
const list = index.postings.get(term);
|
|
4679
|
-
if (!list) continue;
|
|
4680
|
-
const df = list.length;
|
|
4681
|
-
const idf = Math.log(1 + (documentCount - df + .5) / (df + .5));
|
|
4682
|
-
for (const { ordinal, tf } of list) {
|
|
4683
|
-
const lengthRatio = averageDocumentLength > 0 ? documentLengths[ordinal] / averageDocumentLength : 1;
|
|
4684
|
-
const saturated = tf * (k1 + 1) / (tf + k1 * (1 - b + b * lengthRatio));
|
|
4685
|
-
scores.set(ordinal, (scores.get(ordinal) ?? 0) + idf * saturated);
|
|
4686
|
-
}
|
|
4687
|
-
}
|
|
4688
|
-
return [...scores.entries()].map(([ordinal, score]) => ({
|
|
4689
|
-
page: index.pages[ordinal],
|
|
4690
|
-
score
|
|
4691
|
-
})).sort((left, right) => right.score - left.score || left.page.path.localeCompare(right.page.path));
|
|
4692
|
-
}
|
|
4693
|
-
function resolveFieldBoosts(boosts) {
|
|
4694
|
-
const resolved = {
|
|
4695
|
-
...DEFAULT_FIELD_BOOSTS,
|
|
4696
|
-
...boosts
|
|
4697
|
-
};
|
|
4698
|
-
for (const [field, boost] of Object.entries(resolved)) if (!Number.isFinite(boost) || boost < 0) throw new Error(`lexical field boost ${field} must be >= 0, got ${String(boost)}`);
|
|
4699
|
-
return Object.freeze(resolved);
|
|
4700
|
-
}
|
|
4701
|
-
//#endregion
|
|
4702
|
-
//#region src/search.ts
|
|
4703
|
-
const RRF_K = 60;
|
|
4704
|
-
/**
|
|
4705
|
-
* Identity of the ranking `searchKnowledge` performs: BM25 over title, path,
|
|
4706
|
-
* and body, exact-title and phrase matches ahead of bag-of-words matches, and
|
|
4707
|
-
* reciprocal rank fusion with link and shared-source structure. Declare it as
|
|
4708
|
-
* the retriever id of a retrieval receipt minted from these results.
|
|
4709
|
-
*/
|
|
4710
|
-
const KNOWLEDGE_SEARCH_RETRIEVER_ID = "bm25-rrf-v1";
|
|
4711
|
-
function searchKnowledge(index, query, limitOrOptions = 10) {
|
|
4712
|
-
return searchKnowledgePages(index.pages, query, limitOrOptions);
|
|
4713
|
-
}
|
|
4714
|
-
/**
|
|
4715
|
-
* Rank a page set that is not a built index, such as the chain a run can see.
|
|
4716
|
-
*
|
|
4717
|
-
* `searchKnowledge` is this function over `index.pages`, so both entry points
|
|
4718
|
-
* rank identically and neither can drift from the other.
|
|
4719
|
-
*/
|
|
4720
|
-
function searchKnowledgePages(pages, query, limitOrOptions = 10) {
|
|
4721
|
-
const trimmed = query.trim();
|
|
4722
|
-
if (trimmed === "") return [];
|
|
4723
|
-
const options = typeof limitOrOptions === "number" ? { limit: limitOrOptions } : { ...limitOrOptions };
|
|
4724
|
-
const limit = options.limit ?? 10;
|
|
4725
|
-
if (!Number.isInteger(limit) || limit < 0) throw new Error(`search limit must be a non-negative integer, got ${String(limit)}`);
|
|
4726
|
-
const matched = filterPages(pages, options);
|
|
4727
|
-
const lexicalRanked = rankLexical(matched, trimmed, options.lexicalIndex ? assertLexicalIndexMatches(options.lexicalIndex, pages) : buildKnowledgeLexicalIndex(pages));
|
|
4728
|
-
const ranked = [...fuseRanks([lexicalRanked, rankByGraph(matched, lexicalRanked, pages)]).entries()].map(([page, score]) => ({
|
|
4729
|
-
page,
|
|
4730
|
-
score
|
|
4731
|
-
})).sort((a, b) => b.score - a.score || comparePages(a.page, b.page)).slice(0, limit);
|
|
4732
|
-
const topScore = ranked[0]?.score ?? 0;
|
|
4733
|
-
return ranked.map((item, i) => ({
|
|
4734
|
-
citationId: item.page.id,
|
|
4735
|
-
page: item.page,
|
|
4736
|
-
score: item.score,
|
|
4737
|
-
rrfScore: item.score,
|
|
4738
|
-
normalizedScore: topScore > 0 ? item.score / topScore : 0,
|
|
4739
|
-
rank: i + 1,
|
|
4740
|
-
snippet: buildSnippet(item.page.text, trimmed),
|
|
4741
|
-
reasons: reasonsFor(item.page, trimmed)
|
|
4742
|
-
}));
|
|
4743
|
-
}
|
|
4744
|
-
function reciprocalRankFusion(rankLists, k = RRF_K) {
|
|
4745
|
-
return fuseRanks(rankLists, k);
|
|
4746
|
-
}
|
|
4747
|
-
function fuseRanks(rankLists, k = RRF_K) {
|
|
4748
|
-
const scores = /* @__PURE__ */ new Map();
|
|
4749
|
-
for (const list of rankLists) list.forEach((id, idx) => {
|
|
4750
|
-
scores.set(id, (scores.get(id) ?? 0) + 1 / (k + idx + 1));
|
|
4751
|
-
});
|
|
4752
|
-
return scores;
|
|
4753
|
-
}
|
|
4754
|
-
function filterPages(pages, options) {
|
|
4755
|
-
const pageIds = options.pageIds ? new Set(options.pageIds) : null;
|
|
4756
|
-
const tags = options.tags ? new Set(options.tags) : null;
|
|
4757
|
-
const kinds = options.kinds ? new Set(options.kinds) : null;
|
|
4758
|
-
return pages.filter((page) => {
|
|
4759
|
-
if (options.excludeInvalidated && page.invalidation !== void 0) return false;
|
|
4760
|
-
if (pageIds && !pageIds.has(page.id)) return false;
|
|
4761
|
-
if (tags && !page.tags.some((tag) => tags.has(tag))) return false;
|
|
4762
|
-
if (kinds) {
|
|
4763
|
-
const kind = page.frontmatter.kind;
|
|
4764
|
-
if (typeof kind !== "string" || !kinds.has(kind)) return false;
|
|
4765
|
-
}
|
|
4766
|
-
return options.predicate?.(page) ?? true;
|
|
4767
|
-
});
|
|
4768
|
-
}
|
|
4769
|
-
function assertLexicalIndexMatches(lexicalIndex, pages) {
|
|
4770
|
-
if (lexicalIndex.pages.length !== pages.length || lexicalIndex.pages.some((page, ordinal) => page !== pages[ordinal])) throw new Error("lexical index was not built from the searched pages");
|
|
4771
|
-
return lexicalIndex;
|
|
4772
|
-
}
|
|
4773
|
-
/**
|
|
4774
|
-
* The lexical rank list. An exact title or path match outranks a title that
|
|
4775
|
-
* contains the query, which outranks a body that contains the query, which
|
|
4776
|
-
* outranks a bag-of-words match; BM25 orders pages inside each of those tiers.
|
|
4777
|
-
* The tiers are an ordering, not a score, so a strong bag-of-words page cannot
|
|
4778
|
-
* overtake an exact match by term repetition alone.
|
|
4779
|
-
*/
|
|
4780
|
-
function rankLexical(pages, query, lexicalIndex) {
|
|
4781
|
-
const tokens = [...new Set(lexicalIndex.tokenize(query))];
|
|
4782
|
-
const bm25 = new Map(scoreBm25(lexicalIndex, tokens).map((hit) => [hit.page, hit.score]));
|
|
4783
|
-
const phrase = query.toLowerCase();
|
|
4784
|
-
return pages.flatMap((page) => {
|
|
4785
|
-
const score = bm25.get(page) ?? 0;
|
|
4786
|
-
if (score === 0 && tokens.length > 0) return [];
|
|
4787
|
-
const tier = phraseTier(page, phrase);
|
|
4788
|
-
if (score === 0 && tier === 0) return [];
|
|
4789
|
-
return [{
|
|
4790
|
-
page,
|
|
4791
|
-
tier,
|
|
4792
|
-
score
|
|
4793
|
-
}];
|
|
4794
|
-
}).sort((a, b) => b.tier - a.tier || b.score - a.score || comparePages(a.page, b.page)).map((item) => item.page);
|
|
4795
|
-
}
|
|
4796
|
-
function phraseTier(page, phrase) {
|
|
4797
|
-
const title = page.title.toLowerCase();
|
|
4798
|
-
if (title === phrase || page.path.toLowerCase().endsWith(`${phrase}.md`)) return 3;
|
|
4799
|
-
if (title.includes(phrase)) return 2;
|
|
4800
|
-
if (page.text.toLowerCase().includes(phrase)) return 1;
|
|
4801
|
-
return 0;
|
|
4802
|
-
}
|
|
4803
|
-
function rankByGraph(pages, lexicalRanked, visiblePages) {
|
|
4804
|
-
if (lexicalRanked.length === 0) return [];
|
|
4805
|
-
const counts = /* @__PURE__ */ new Map();
|
|
4806
|
-
for (const page of visiblePages) counts.set(page.id, (counts.get(page.id) ?? 0) + 1);
|
|
4807
|
-
const seeds = new Set(lexicalRanked.slice(0, 5).filter((page) => counts.get(page.id) === 1).map((page) => page.id));
|
|
4808
|
-
return pages.map((page) => ({
|
|
4809
|
-
page,
|
|
4810
|
-
score: page.outLinks.filter((link) => seeds.has(link)).length + page.sourceIds.filter((source) => lexicalRanked.some((seed) => seed.sourceIds.includes(source))).length
|
|
4811
|
-
})).filter((item) => item.score > 0).sort((a, b) => b.score - a.score || comparePages(a.page, b.page)).map((item) => item.page);
|
|
4812
|
-
}
|
|
4813
|
-
function comparePages(a, b) {
|
|
4814
|
-
return a.path.localeCompare(b.path) || a.id.localeCompare(b.id);
|
|
4815
|
-
}
|
|
4816
|
-
function buildSnippet(text, query) {
|
|
4817
|
-
const compact = text.replace(/\s+/g, " ").trim();
|
|
4818
|
-
const idx = compact.toLowerCase().indexOf(query.toLowerCase());
|
|
4819
|
-
if (idx < 0) return compact.slice(0, 180);
|
|
4820
|
-
return compact.slice(Math.max(0, idx - 80), Math.min(compact.length, idx + query.length + 100));
|
|
4821
|
-
}
|
|
4822
|
-
function reasonsFor(page, query) {
|
|
4823
|
-
const lower = `${page.title}\n${page.text}`.toLowerCase();
|
|
4824
|
-
const reasons = [];
|
|
4825
|
-
if (lower.includes(query.toLowerCase())) reasons.push("phrase");
|
|
4826
|
-
if (page.sourceIds.length > 0) reasons.push("sourced");
|
|
4827
|
-
if (page.outLinks.length > 0) reasons.push("linked");
|
|
4828
|
-
return reasons;
|
|
4829
|
-
}
|
|
4830
|
-
//#endregion
|
|
4831
4813
|
//#region src/inspect.ts
|
|
4832
4814
|
function inspectKnowledgeIndex(index, options = {}) {
|
|
4833
4815
|
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
@@ -4891,6 +4873,6 @@ function explainKnowledgeTarget(index, target) {
|
|
|
4891
4873
|
};
|
|
4892
4874
|
}
|
|
4893
4875
|
//#endregion
|
|
4894
|
-
export {
|
|
4876
|
+
export { snapshotSourceTextInput as $, ClaimLedgerGoalConflictError as $t, validateKnowledgePage as A, prepareKnowledgeFileTransaction as An, knowledgePageFromMarkdown as At, DEADLINE_EXIT_CODE as B, readRegularFileWithinRoot as Bn, KnowledgeGraphEdgeSchema as Bt, immutablePageDigest as C, withKnowledgeMutation as Cn, resolveKnowledgeCitations as Ct, normalizeVisibilityArtifact as D, commitKnowledgeFileMutations as Dn, initKnowledgeBase as Dt, nonEmpty as E, assertKnowledgeMutationPath as En, SCAFFOLD_PAGE_BASENAMES as Et, detectNearDuplicatePages as F, canonicalRelativeWithinRoot as Fn, extractWikilinks as Ft, gradeFor as G, withSafeDescendant as Gn, KnowledgeRelationSchema as Gt, assertGradeableEvidence as H, removeDurable as Hn, KnowledgeIndexSchema as Ht, normalizePageText as I, isKernelAnchoredPath as In, normalizeLinkTarget as It, buildKnowledgeIndex as J, writeFileDurableWithinRoot as Jn, ResearchClaimRecordSchema as Jt, verdictFor as K, withSafeDirectory as Kn, ResearchClaimEvidenceSchema as Kt, validateKnowledgeIndex as L, isMissingFile as Ln, DeepQuestionSchema as Lt, verifyKnowledgeVisibilitySnapshot as M, DEFAULT_PAGES_DIRECTORY as Mn, loadKnowledgePages as Mt, visibilityIdentity as N, normalizePagesDirectory as Nn, writeJson as Nt, normalizeVisibilityRef as O, finishKnowledgeFileTransaction as On, isKnowledgePagePath as Ot, visibilityIndexOf as P, canonicalPathsEqual as Pn, WIKILINK_REGEX as Pt, loadSourceRegistry as Q, textSourceAdapter as Qn, KNOWLEDGE_EVENT_TYPES as Qt, lintKnowledgeIndex as R, listRegularFilesWithinRoot as Rn, KnowledgeBaseCandidateSchema as Rt, encodeKnowledgeVisibilitySnapshot as S, runInKnowledgeMutationScope as Sn, resolveKnowledgeCitation as St, knowledgeVisibilityArtifactRef as T, applyKnowledgeFileTransaction as Tn, resolveRunScopedCitations as Tt, claimCheckKey as U, renameDurable as Un, KnowledgePageInvalidationSchema as Ut, UncheckableClaimError as V, relativeWithinRoot as Vn, KnowledgeGraphNodeSchema as Vt, gradeClaims as W, syncDirectory as Wn, KnowledgePageSchema as Wt, addSourcePath as X, writeJsonDurableWithinRoot as Xn, SourceAnchorSchema as Xt, writeKnowledgeIndex as Y, writeJsonDurable as Yn, ResearchSourceVersionSchema as Yt, addSourceText as Z, mediaTypeFor$1 as Zn, SourceRecordSchema as Zt, KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION as _, acquireDurableFileLock as _n, assertRunScopedCitationsResolved as _t, applyKnowledgeWriteBlocksFile as a, claimId as an, KB_EVENTS_PATH as at, decodeKnowledgeVisibilitySnapshot as b, measureKnowledgeMutation as bn, formatKnowledgeCitationReference as bt, KnowledgeDuplicateIntakeError as c, emptyClaimLedger as cn, MemoryKbStore as ct, createFileRunLineageAuthority as d, mergeClaimLedgers as dn, knowledgePageRelations as dt, assertDeepQuestionIntegrity as en, sourceRegistryPath as et, createRunScopedStores as f, mergeTrackedClaims as fn, KnowledgeCitationAuditError as ft, KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM as g, parseFrontmatter as gn, assertKnowledgeCitationsResolved as gt, originatedPages as h, formatFrontmatter as hn, assertKnowledgeCitationAudit as ht, applyKnowledgeWriteBlocks as i, claimEvidenceId as in, KB_CLAIM_LEDGER_DIR as it, validateOrigin as j, rollbackKnowledgeFileTransaction as jn, layoutFor as jt, snapshotImmutableVisibility as k, knowledgeFileTransactionPlanHash as kn, isScaffoldPath as kt, assertKnowledgeWriteIntake as l, linkClaimContradictions as ln, assertClaimLedgerId as lt, loadKnowledgeToolChain as m, researchSourceVersionKey as mn, assertCurrentRunCitationsResolved as mt, inspectKnowledgeIndex as n, assertResearchClaimLedgerIntegrity as nn, ClaimLedgerMigrationRequiredError as nt, isSafeKnowledgePath as o, claimSourceHost as on, KB_INDEX_PATH as ot, isKnowledgeToolChain as p, normalizeClaimText as pn, KnowledgeCitationResolutionError as pt, verifyGradeableEvidence as q, writeFileDurable as qn, ResearchClaimLedgerSchema as qt, stringMetadata as r, assertTrackedClaimIntegrity as rn, FileSystemKbStore as rt, parseKnowledgeWriteBlocks as s, deepQuestionId as sn, KB_STORE_DIR as st, explainKnowledgeTarget as t, assertResearchClaimEvidenceIntegrity as tn, writeSourceRegistry as tt, RUN_LINEAGE_BASENAME as u, materializeRegisteredClaimEvidence as un, buildKnowledgeGraph as ut, assertSchemaVersion as v, inspectPendingKnowledgeMutation as vn, auditCurrentRunCitations as vt, knowledgePageDigest as w, withKnowledgeRead as wn, resolveRunScopedCitation as wt, digest as x, recoverPendingKnowledgeMutation as xn, parseKnowledgeCitationReference as xt, createKnowledgeVisibilitySnapshot as y, isKnowledgeMutationHeld as yn, auditKnowledgeCitations as yt, CHECKABLE_RUNG_THRESHOLD as z, readRegularFileNoFollow as zn, KnowledgeEventSchema as zt };
|
|
4895
4877
|
|
|
4896
|
-
//# sourceMappingURL=inspect-
|
|
4878
|
+
//# sourceMappingURL=inspect-DXN6SE2o.js.map
|