@tangle-network/agent-knowledge 19.1.0 → 19.1.2
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 +16 -0
- package/README.md +5 -3
- package/dist/benchmarks/index.js +1 -1
- package/dist/{benchmarks-B3kU-Yxz.js → benchmarks-BjXxjAke.js} +2 -2
- package/dist/{benchmarks-B3kU-Yxz.js.map → benchmarks-BjXxjAke.js.map} +1 -1
- package/dist/cli.js +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +121 -37
- package/dist/index.js.map +1 -1
- package/dist/{inspect-CwIvMcno.js → inspect-C6c4zuKp.js} +284 -90
- package/dist/inspect-C6c4zuKp.js.map +1 -0
- package/dist/memory/index.js +2 -2
- package/dist/{memory-PlYkyv8x.js → memory-CUk1mgPY.js} +2 -2
- package/dist/{memory-PlYkyv8x.js.map → memory-CUk1mgPY.js.map} +1 -1
- package/dist/{search-Cbyj2shJ.js → search-BBr5eUyT.js} +59 -47
- package/dist/search-BBr5eUyT.js.map +1 -0
- package/docs/architecture.md +5 -0
- package/docs/knowledge-use-receipts.md +1 -0
- package/package.json +3 -3
- package/dist/inspect-CwIvMcno.js.map +0 -1
- package/dist/search-Cbyj2shJ.js.map +0 -1
|
@@ -1,12 +1,12 @@
|
|
|
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-
|
|
2
|
+
import { r as searchKnowledge } from "./search-BBr5eUyT.js";
|
|
3
3
|
import { createHash, randomUUID } from "node:crypto";
|
|
4
4
|
import { lstat, mkdir, mkdtemp, open, readFile, readdir, realpath, rename, rm } from "node:fs/promises";
|
|
5
5
|
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
6
6
|
import { canonicalCandidateBytes, canonicalCandidateDigest, sha256Bytes, sha256DigestSchema } from "@tangle-network/agent-interface";
|
|
7
7
|
import { contentHash } from "@tangle-network/agent-eval";
|
|
8
8
|
import { z } from "zod";
|
|
9
|
-
import { constants } from "node:fs";
|
|
9
|
+
import { constants, lstatSync } from "node:fs";
|
|
10
10
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
11
11
|
//#region src/adapters.ts
|
|
12
12
|
const textSourceAdapter = {
|
|
@@ -95,8 +95,7 @@ async function renameDurable(source, target) {
|
|
|
95
95
|
await withDirectoryHandle(sourceDir, async (sourceHandle, anchoredSourceDir) => {
|
|
96
96
|
await withDirectoryHandle(targetDir, async (targetHandle, anchoredTargetDir) => {
|
|
97
97
|
await rename(resolve(anchoredSourceDir, basename(source)), resolve(anchoredTargetDir, basename(target)));
|
|
98
|
-
await syncDirectoryHandle(sourceHandle);
|
|
99
|
-
if (targetDir !== sourceDir) await syncDirectoryHandle(targetHandle);
|
|
98
|
+
await Promise.all([syncDirectoryHandle(sourceHandle), targetDir === sourceDir ? void 0 : syncDirectoryHandle(targetHandle)]);
|
|
100
99
|
});
|
|
101
100
|
});
|
|
102
101
|
}
|
|
@@ -172,15 +171,20 @@ async function listRegularFileMetadataWithinRoot(root, relativeDirectory) {
|
|
|
172
171
|
const walk = async (directory, relative) => {
|
|
173
172
|
const out = [];
|
|
174
173
|
const entries = await readdir(directory, { withFileTypes: true });
|
|
175
|
-
|
|
174
|
+
const directories = entries.filter((entry) => entry.isDirectory());
|
|
175
|
+
for (let start = 0; start < directories.length; start += 8) {
|
|
176
|
+
const children = await Promise.all(directories.slice(start, start + 8).map((entry) => withSafeDirectory(directory, entry.name, false, (child) => walk(child, `${relative}/${entry.name}`))));
|
|
177
|
+
for (const child of children) out.push(...child);
|
|
178
|
+
}
|
|
176
179
|
const files = entries.filter((entry) => !entry.isDirectory());
|
|
177
|
-
for (let start = 0; start < files.length; start +=
|
|
178
|
-
|
|
180
|
+
for (let start = 0; start < files.length; start += 256) {
|
|
181
|
+
if (start > 0) await new Promise((resume) => setImmediate(resume));
|
|
182
|
+
for (const entry of files.slice(start, start + 256)) {
|
|
179
183
|
const path = `${relative}/${entry.name}`;
|
|
180
184
|
if (!entry.isFile()) throw new Error(`knowledge tree contains an unsupported filesystem entry: ${path}`);
|
|
181
|
-
const stat =
|
|
185
|
+
const stat = lstatSync(resolve(directory, entry.name), { bigint: true });
|
|
182
186
|
if (!stat.isFile()) throw new Error(`knowledge path is not a regular file: ${path}`);
|
|
183
|
-
|
|
187
|
+
out.push({
|
|
184
188
|
path,
|
|
185
189
|
bytes: Number(stat.size),
|
|
186
190
|
generation: [
|
|
@@ -190,9 +194,8 @@ async function listRegularFileMetadataWithinRoot(root, relativeDirectory) {
|
|
|
190
194
|
stat.mtimeNs,
|
|
191
195
|
stat.ctimeNs
|
|
192
196
|
].join(":")
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
out.push(...batch.flat());
|
|
197
|
+
});
|
|
198
|
+
}
|
|
196
199
|
}
|
|
197
200
|
return out.sort((left, right) => left.path.localeCompare(right.path));
|
|
198
201
|
};
|
|
@@ -488,10 +491,6 @@ async function prepareKnowledgeFileTransaction(input) {
|
|
|
488
491
|
const preparationDir = await mkdtemp(join(transactionRoot, "prepare-"));
|
|
489
492
|
let activated = false;
|
|
490
493
|
try {
|
|
491
|
-
for (const item of changed) {
|
|
492
|
-
if (item.before) await writeFileDurable(snapshotPath(preparationDir, "before", item.entry.index), item.before);
|
|
493
|
-
if (item.after) await writeFileDurable(snapshotPath(preparationDir, "after", item.entry.index), item.after);
|
|
494
|
-
}
|
|
495
494
|
const transaction = transactionSchema.parse({
|
|
496
495
|
kind: "knowledge-file-transaction",
|
|
497
496
|
transactionId: randomUUID(),
|
|
@@ -505,7 +504,11 @@ async function prepareKnowledgeFileTransaction(input) {
|
|
|
505
504
|
createdAt: (input.now ?? (() => /* @__PURE__ */ new Date()))().toISOString(),
|
|
506
505
|
entries: changed.map((item) => item.entry)
|
|
507
506
|
});
|
|
508
|
-
|
|
507
|
+
for (const side of ["before", "after"]) if (changed.some((item) => item[side])) await mkdir(join(preparationDir, side));
|
|
508
|
+
await Promise.all([...changed.flatMap((item) => ["before", "after"].flatMap((side) => {
|
|
509
|
+
const bytes = item[side];
|
|
510
|
+
return bytes ? [writeFileDurable(snapshotPath(preparationDir, side, item.entry.index), bytes)] : [];
|
|
511
|
+
})), writeJsonDurable(join(preparationDir, "transaction.json"), transaction)]);
|
|
509
512
|
const activeDir = join(transactionRoot, activeTransactionDirectoryName(transaction.transactionId));
|
|
510
513
|
await renameDurable(preparationDir, activeDir);
|
|
511
514
|
activated = true;
|
|
@@ -647,11 +650,13 @@ async function finishKnowledgeFileTransaction(input) {
|
|
|
647
650
|
if (transaction.retainHistory === true) await withSafeDirectory(input.root, ".agent-knowledge/history", true, async (historyRoot) => {
|
|
648
651
|
await renameDurable(join(transactionRoot, activeName), join(historyRoot, transaction.transactionId));
|
|
649
652
|
});
|
|
650
|
-
else
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
653
|
+
else {
|
|
654
|
+
await rm(join(transactionRoot, activeName), {
|
|
655
|
+
recursive: true,
|
|
656
|
+
force: false
|
|
657
|
+
});
|
|
658
|
+
await syncDirectory(transactionRoot);
|
|
659
|
+
}
|
|
655
660
|
});
|
|
656
661
|
}
|
|
657
662
|
async function hasRetainedTransaction(root, transaction) {
|
|
@@ -867,6 +872,86 @@ function loadLockfile() {
|
|
|
867
872
|
}
|
|
868
873
|
const activeRoots = new AsyncLocalStorage();
|
|
869
874
|
const activeReadRoots = new AsyncLocalStorage();
|
|
875
|
+
const gates = /* @__PURE__ */ new Map();
|
|
876
|
+
/** How long a same-process writer waits for admission before failing like a contended lock. */
|
|
877
|
+
const WRITER_ADMISSION_MS = 6e4;
|
|
878
|
+
function gateOf(root) {
|
|
879
|
+
let gate = gates.get(root);
|
|
880
|
+
if (!gate) {
|
|
881
|
+
gate = {
|
|
882
|
+
readers: 0,
|
|
883
|
+
writing: false,
|
|
884
|
+
readersWaiting: [],
|
|
885
|
+
writersWaiting: []
|
|
886
|
+
};
|
|
887
|
+
gates.set(root, gate);
|
|
888
|
+
}
|
|
889
|
+
return gate;
|
|
890
|
+
}
|
|
891
|
+
/** Admit whoever may go next: waiting readers after a write, otherwise a waiting writer first. */
|
|
892
|
+
function admitNext(root, gate, afterWrite) {
|
|
893
|
+
if (gate.writing) return;
|
|
894
|
+
if (gate.readersWaiting.length > 0 && (afterWrite || gate.writersWaiting.length === 0)) {
|
|
895
|
+
const admitted = gate.readersWaiting.splice(0);
|
|
896
|
+
gate.readers += admitted.length;
|
|
897
|
+
for (const admit of admitted) admit();
|
|
898
|
+
} else if (gate.readers === 0 && gate.writersWaiting.length > 0) {
|
|
899
|
+
gate.writing = true;
|
|
900
|
+
gate.writersWaiting.shift()();
|
|
901
|
+
} else if (gate.readers === 0) gates.delete(root);
|
|
902
|
+
}
|
|
903
|
+
async function enterGate(root, mode, timeoutMs) {
|
|
904
|
+
const gate = gateOf(root);
|
|
905
|
+
const release = mode === "read" ? () => {
|
|
906
|
+
gate.readers -= 1;
|
|
907
|
+
if (gate.readers === 0) admitNext(root, gate, false);
|
|
908
|
+
} : () => {
|
|
909
|
+
gate.writing = false;
|
|
910
|
+
admitNext(root, gate, true);
|
|
911
|
+
};
|
|
912
|
+
if (mode === "read" ? !gate.writing && gate.writersWaiting.length === 0 : !gate.writing && gate.readers === 0 && gate.writersWaiting.length === 0) {
|
|
913
|
+
if (mode === "read") gate.readers += 1;
|
|
914
|
+
else gate.writing = true;
|
|
915
|
+
return once(release);
|
|
916
|
+
}
|
|
917
|
+
const waiting = mode === "read" ? gate.readersWaiting : gate.writersWaiting;
|
|
918
|
+
return new Promise((resolve, reject) => {
|
|
919
|
+
let timer;
|
|
920
|
+
const admit = () => {
|
|
921
|
+
if (timer) clearTimeout(timer);
|
|
922
|
+
resolve(once(release));
|
|
923
|
+
};
|
|
924
|
+
waiting.push(admit);
|
|
925
|
+
timer = setTimeout(() => {
|
|
926
|
+
const position = waiting.indexOf(admit);
|
|
927
|
+
if (position < 0) return;
|
|
928
|
+
waiting.splice(position, 1);
|
|
929
|
+
admitNext(root, gate, mode === "write");
|
|
930
|
+
reject(mode === "read" ? /* @__PURE__ */ new Error("knowledge read could not observe a stable mutation epoch") : Object.assign(/* @__PURE__ */ new Error(`knowledge store is locked by this process: ${root}`), { code: "ELOCKED" }));
|
|
931
|
+
}, timeoutMs);
|
|
932
|
+
timer.unref?.();
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
function once(release) {
|
|
936
|
+
let released = false;
|
|
937
|
+
return () => {
|
|
938
|
+
if (released) return;
|
|
939
|
+
released = true;
|
|
940
|
+
release();
|
|
941
|
+
};
|
|
942
|
+
}
|
|
943
|
+
const mutationTimings = new AsyncLocalStorage();
|
|
944
|
+
/** Run `body` and report the lock timings of the store mutations it performed. */
|
|
945
|
+
async function measureKnowledgeMutation(body) {
|
|
946
|
+
const timings = [];
|
|
947
|
+
return {
|
|
948
|
+
value: await mutationTimings.run(timings, body),
|
|
949
|
+
timing: timings.length === 0 ? void 0 : timings.reduce((sum, next) => ({
|
|
950
|
+
lockWaitMs: sum.lockWaitMs + next.lockWaitMs,
|
|
951
|
+
lockHoldMs: sum.lockHoldMs + next.lockHoldMs
|
|
952
|
+
}))
|
|
953
|
+
};
|
|
954
|
+
}
|
|
870
955
|
var KnowledgeLockLostError = class extends Error {
|
|
871
956
|
constructor(message, options) {
|
|
872
957
|
super(message, options);
|
|
@@ -886,24 +971,42 @@ async function withKnowledgeMutation(root, mutate, options = {}) {
|
|
|
886
971
|
const resolvedRoot = resolve(root);
|
|
887
972
|
const existing = activeRoots.getStore()?.get(resolvedRoot);
|
|
888
973
|
if (existing?.active) return await runInlineMutation(existing.lock, mutate);
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
974
|
+
if (activeReadRoots.getStore()?.has(resolvedRoot)) throw new Error("a knowledge mutation cannot start inside a read of the same store");
|
|
975
|
+
const started = performance.now();
|
|
976
|
+
const leave = await enterGate(resolvedRoot, "write", noRetries(options.retries) ? 0 : WRITER_ADMISSION_MS);
|
|
977
|
+
try {
|
|
978
|
+
return await withSafeDirectory(resolvedRoot, ".agent-knowledge", true, async (cacheDir) => {
|
|
979
|
+
const acquired = await acquireDurableFileLock(resolvedRoot, {
|
|
980
|
+
lockfilePath: join(cacheDir, "mutation.lock.durable"),
|
|
981
|
+
staleMs: options.staleMs,
|
|
982
|
+
retries: options.retries ?? {
|
|
983
|
+
retries: 100,
|
|
984
|
+
factor: 1.1,
|
|
985
|
+
minTimeout: 10,
|
|
986
|
+
maxTimeout: 200,
|
|
987
|
+
randomize: true
|
|
988
|
+
}
|
|
989
|
+
});
|
|
990
|
+
const held = performance.now();
|
|
991
|
+
try {
|
|
992
|
+
return await runOwnedMutation(resolvedRoot, cacheDir, acquired, options, mutate);
|
|
993
|
+
} finally {
|
|
994
|
+
try {
|
|
995
|
+
await acquired.release();
|
|
996
|
+
} finally {
|
|
997
|
+
mutationTimings.getStore()?.push({
|
|
998
|
+
lockWaitMs: Math.round(held - started),
|
|
999
|
+
lockHoldMs: Math.round(performance.now() - held)
|
|
1000
|
+
});
|
|
1001
|
+
}
|
|
899
1002
|
}
|
|
900
1003
|
});
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
1004
|
+
} finally {
|
|
1005
|
+
leave();
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
function noRetries(retries) {
|
|
1009
|
+
return retries === 0 || typeof retries === "object" && !Array.isArray(retries) && retries.retries === 0;
|
|
907
1010
|
}
|
|
908
1011
|
/**
|
|
909
1012
|
* Run `body` inside this package's mutation scope for `root`, on a lock the caller already holds.
|
|
@@ -1048,21 +1151,26 @@ async function withKnowledgeRead(root, read, options = {}) {
|
|
|
1048
1151
|
if (activeReadRoots.getStore()?.has(resolvedRoot)) return await read();
|
|
1049
1152
|
const readRoots = new Set(activeReadRoots.getStore());
|
|
1050
1153
|
readRoots.add(resolvedRoot);
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
await
|
|
1057
|
-
|
|
1154
|
+
const retries = options.retries ?? DEFAULT_READ_RETRIES;
|
|
1155
|
+
const leave = await enterGate(resolvedRoot, "read", (retries + 1) * (options.waitMs ?? DEFAULT_READ_WAIT_MS));
|
|
1156
|
+
try {
|
|
1157
|
+
return await activeReadRoots.run(readRoots, async () => {
|
|
1158
|
+
for (let attempt = 0; attempt <= retries; attempt += 1) {
|
|
1159
|
+
const before = await readMutationEpoch(resolvedRoot);
|
|
1160
|
+
if (isOdd(before)) {
|
|
1161
|
+
await waitForActiveMutationEpoch(resolvedRoot, before, options);
|
|
1162
|
+
continue;
|
|
1163
|
+
}
|
|
1164
|
+
const result = await read();
|
|
1165
|
+
const after = await readMutationEpoch(resolvedRoot);
|
|
1166
|
+
if (before === after && !isOdd(after)) return result;
|
|
1167
|
+
if (isOdd(after)) await waitForActiveMutationEpoch(resolvedRoot, after, options);
|
|
1058
1168
|
}
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
throw new Error("knowledge read could not observe a stable mutation epoch");
|
|
1065
|
-
});
|
|
1169
|
+
throw new Error("knowledge read could not observe a stable mutation epoch");
|
|
1170
|
+
});
|
|
1171
|
+
} finally {
|
|
1172
|
+
leave();
|
|
1173
|
+
}
|
|
1066
1174
|
}
|
|
1067
1175
|
async function acquireDurableFileLock(target, options) {
|
|
1068
1176
|
const stale = Math.max(5e3, options.staleMs ?? DEFAULT_STALE_MS);
|
|
@@ -3686,6 +3794,26 @@ function knowledgePageDigest(page) {
|
|
|
3686
3794
|
}
|
|
3687
3795
|
/** Snapshot the exact ordered current/ancestor/shared page view. */
|
|
3688
3796
|
function createKnowledgeVisibilitySnapshot(visiblePages) {
|
|
3797
|
+
return snapshotVisibility(visiblePages, knowledgePageDigest);
|
|
3798
|
+
}
|
|
3799
|
+
/**
|
|
3800
|
+
* Snapshot a view whose pages are immutable, hashing each page object once across views.
|
|
3801
|
+
* The caller guarantees no page in `visiblePages` can change after this call.
|
|
3802
|
+
*/
|
|
3803
|
+
function snapshotImmutableVisibility(visiblePages) {
|
|
3804
|
+
return snapshotVisibility(visiblePages, immutablePageDigest);
|
|
3805
|
+
}
|
|
3806
|
+
const immutablePageDigests = /* @__PURE__ */ new WeakMap();
|
|
3807
|
+
/** `knowledgePageDigest` memoized by object identity, for pages that are deeply frozen. */
|
|
3808
|
+
function immutablePageDigest(page) {
|
|
3809
|
+
let pageDigest = immutablePageDigests.get(page);
|
|
3810
|
+
if (pageDigest === void 0) {
|
|
3811
|
+
pageDigest = knowledgePageDigest(page);
|
|
3812
|
+
if (Object.isFrozen(page)) immutablePageDigests.set(page, pageDigest);
|
|
3813
|
+
}
|
|
3814
|
+
return pageDigest;
|
|
3815
|
+
}
|
|
3816
|
+
function snapshotVisibility(visiblePages, digestOf) {
|
|
3689
3817
|
if (!Array.isArray(visiblePages)) throw new TypeError("knowledge visibility must be an array");
|
|
3690
3818
|
const identities = /* @__PURE__ */ new Set();
|
|
3691
3819
|
const entries = visiblePages.map((entry, position) => {
|
|
@@ -3700,20 +3828,35 @@ function createKnowledgeVisibilitySnapshot(visiblePages) {
|
|
|
3700
3828
|
pageId: entry.page.id,
|
|
3701
3829
|
origin,
|
|
3702
3830
|
path: entry.page.path,
|
|
3703
|
-
pageDigest:
|
|
3831
|
+
pageDigest: digestOf(entry.page),
|
|
3704
3832
|
sourceIds: Object.freeze([...entry.page.sourceIds]),
|
|
3705
3833
|
invalidated: entry.page.invalidation !== void 0
|
|
3706
3834
|
});
|
|
3707
3835
|
});
|
|
3708
3836
|
const material = visibilityMaterial(entries);
|
|
3837
|
+
const materialBytes = canonicalCandidateBytes(material);
|
|
3838
|
+
const snapshotDigest = sha256Bytes(materialBytes);
|
|
3709
3839
|
const snapshot = Object.freeze({
|
|
3710
3840
|
...material,
|
|
3711
|
-
snapshotDigest
|
|
3841
|
+
snapshotDigest,
|
|
3712
3842
|
entries: Object.freeze(entries)
|
|
3713
3843
|
});
|
|
3714
3844
|
visibilityIndexes.set(snapshot, indexVisibility(snapshot));
|
|
3845
|
+
encodedSnapshots.set(snapshot, encodedFromMaterial(materialBytes, snapshotDigest));
|
|
3715
3846
|
return snapshot;
|
|
3716
3847
|
}
|
|
3848
|
+
const encodedSnapshots = /* @__PURE__ */ new WeakMap();
|
|
3849
|
+
/**
|
|
3850
|
+
* RFC 8785 orders `snapshotDigest` after every material key, so the stored encoding is the
|
|
3851
|
+
* material's canonical bytes with that one member appended before the closing brace.
|
|
3852
|
+
*/
|
|
3853
|
+
function encodedFromMaterial(materialBytes, snapshotDigest) {
|
|
3854
|
+
const member = new TextEncoder().encode(`,"snapshotDigest":${JSON.stringify(snapshotDigest)}}`);
|
|
3855
|
+
const encoded = new Uint8Array(materialBytes.byteLength - 1 + member.byteLength);
|
|
3856
|
+
encoded.set(materialBytes.subarray(0, materialBytes.byteLength - 1));
|
|
3857
|
+
encoded.set(member, materialBytes.byteLength - 1);
|
|
3858
|
+
return encoded;
|
|
3859
|
+
}
|
|
3717
3860
|
/**
|
|
3718
3861
|
* Verify a snapshot's schema and canonical digest. The check runs once per
|
|
3719
3862
|
* snapshot object; later calls with the same object are free.
|
|
@@ -3724,6 +3867,8 @@ function verifyKnowledgeVisibilitySnapshot(snapshot) {
|
|
|
3724
3867
|
/** Canonical bytes of a verified snapshot, for durable storage. */
|
|
3725
3868
|
function encodeKnowledgeVisibilitySnapshot(snapshot) {
|
|
3726
3869
|
const verified = verifyKnowledgeVisibilitySnapshot(snapshot);
|
|
3870
|
+
const encoded = encodedSnapshots.get(verified);
|
|
3871
|
+
if (encoded !== void 0) return encoded.slice();
|
|
3727
3872
|
return canonicalCandidateBytes({
|
|
3728
3873
|
schemaVersion: verified.schemaVersion,
|
|
3729
3874
|
digestAlgorithm: verified.digestAlgorithm,
|
|
@@ -3978,43 +4123,92 @@ function createRunScopedStores(options) {
|
|
|
3978
4123
|
}
|
|
3979
4124
|
};
|
|
3980
4125
|
const roots = /* @__PURE__ */ new Map();
|
|
3981
|
-
let cachedBytes = 0;
|
|
3982
4126
|
let current;
|
|
3983
|
-
const
|
|
3984
|
-
|
|
3985
|
-
|
|
4127
|
+
const loadRoot = (root, previous) => withKnowledgeRead(root, async () => {
|
|
4128
|
+
let listed;
|
|
4129
|
+
try {
|
|
4130
|
+
listed = await listRegularFileMetadataWithinRoot(root, pagesDirectory);
|
|
4131
|
+
} catch (error) {
|
|
4132
|
+
if (!isMissingFile(error)) throw error;
|
|
4133
|
+
listed = [];
|
|
4134
|
+
}
|
|
4135
|
+
const generation = JSON.stringify(listed.map((file) => [file.path, file.generation]));
|
|
4136
|
+
if (previous?.generation === generation) return previous;
|
|
4137
|
+
const files = /* @__PURE__ */ new Map();
|
|
4138
|
+
const changed = [];
|
|
4139
|
+
for (const file of listed) {
|
|
4140
|
+
const known = previous?.files.get(file.path);
|
|
4141
|
+
if (known?.generation === file.generation) files.set(file.path, known);
|
|
4142
|
+
else if (!isKnowledgePagePath(file.path)) files.set(file.path, {
|
|
4143
|
+
generation: file.generation,
|
|
4144
|
+
page: void 0
|
|
4145
|
+
});
|
|
4146
|
+
else changed.push(file);
|
|
4147
|
+
}
|
|
4148
|
+
const parse = (path, generation, bytes) => files.set(path, {
|
|
4149
|
+
generation,
|
|
4150
|
+
page: freezeView(knowledgePageFromMarkdown(path, bytes.toString("utf8"), pagesDirectory))
|
|
4151
|
+
});
|
|
4152
|
+
if (changed.length > 64) {
|
|
4153
|
+
const wanted = new Map(changed.map((file) => [file.path, file.generation]));
|
|
4154
|
+
for (const file of await listRegularFilesWithinRoot(root, pagesDirectory)) {
|
|
4155
|
+
const generation = wanted.get(file.path);
|
|
4156
|
+
if (generation !== void 0) parse(file.path, generation, file.bytes);
|
|
4157
|
+
}
|
|
4158
|
+
} else await Promise.all(changed.map(async (file) => {
|
|
3986
4159
|
try {
|
|
3987
|
-
|
|
4160
|
+
parse(file.path, file.generation, (await readRegularFileWithinRoot(root, file.path)).bytes);
|
|
3988
4161
|
} catch (error) {
|
|
3989
4162
|
if (!isMissingFile(error)) throw error;
|
|
3990
|
-
files = [];
|
|
3991
4163
|
}
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4164
|
+
}));
|
|
4165
|
+
const pages = Object.freeze([...files.values()].flatMap((file) => file.page ? [file.page] : []).sort((a, b) => a.path.localeCompare(b.path)));
|
|
4166
|
+
return {
|
|
4167
|
+
generation,
|
|
4168
|
+
bytes: listed.reduce((sum, file) => sum + file.bytes, 0),
|
|
4169
|
+
files,
|
|
4170
|
+
pages
|
|
4171
|
+
};
|
|
4172
|
+
});
|
|
4173
|
+
const refreshes = /* @__PURE__ */ new Map();
|
|
4174
|
+
const readRoot = (root) => {
|
|
4175
|
+
let state = refreshes.get(root);
|
|
4176
|
+
if (!state) {
|
|
4177
|
+
state = {};
|
|
4178
|
+
refreshes.set(root, state);
|
|
4179
|
+
}
|
|
4180
|
+
const slot = state;
|
|
4181
|
+
const start = () => {
|
|
4182
|
+
const running = loadRoot(root, roots.get(root)).then((loaded) => retain(root, loaded)).finally(() => {
|
|
4183
|
+
if (slot.running === running) slot.running = void 0;
|
|
4184
|
+
if (!slot.running && !slot.next && refreshes.get(root) === slot) refreshes.delete(root);
|
|
4185
|
+
});
|
|
4186
|
+
slot.running = running;
|
|
4187
|
+
return running;
|
|
4188
|
+
};
|
|
4189
|
+
if (slot.next) return slot.next;
|
|
4190
|
+
if (!slot.running) return start();
|
|
4191
|
+
const next = slot.running.catch(() => void 0).then(() => {
|
|
4192
|
+
slot.next = void 0;
|
|
4193
|
+
return start();
|
|
4001
4194
|
});
|
|
4195
|
+
slot.next = next;
|
|
4196
|
+
return next;
|
|
4197
|
+
};
|
|
4198
|
+
const retain = (root, loaded) => {
|
|
4002
4199
|
const existing = roots.get(root);
|
|
4003
4200
|
if (existing?.generation === loaded.generation) return existing;
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
}
|
|
4016
|
-
roots.set(root, loaded);
|
|
4017
|
-
cachedBytes += loaded.bytes;
|
|
4201
|
+
roots.delete(root);
|
|
4202
|
+
roots.set(root, loaded);
|
|
4203
|
+
const live = new Set(current?.identities.map((identity) => JSON.parse(identity)[0]));
|
|
4204
|
+
live.add(root);
|
|
4205
|
+
let bytes = 0;
|
|
4206
|
+
for (const part of roots.values()) bytes += part.bytes;
|
|
4207
|
+
for (const [candidate, part] of roots) {
|
|
4208
|
+
if (roots.size <= MAX_CACHED_ROOTS && bytes <= MAX_CACHED_SOURCE_BYTES) break;
|
|
4209
|
+
if (live.has(candidate)) continue;
|
|
4210
|
+
roots.delete(candidate);
|
|
4211
|
+
bytes -= part.bytes;
|
|
4018
4212
|
}
|
|
4019
4213
|
return loaded;
|
|
4020
4214
|
};
|
|
@@ -4033,19 +4227,19 @@ function createRunScopedStores(options) {
|
|
|
4033
4227
|
origin: "shared"
|
|
4034
4228
|
});
|
|
4035
4229
|
const identities = scopes.map(({ root, origin }) => JSON.stringify([root, origin]));
|
|
4036
|
-
const parts =
|
|
4037
|
-
|
|
4038
|
-
if (
|
|
4230
|
+
const parts = await Promise.all(scopes.map((scope) => readRoot(scope.root)));
|
|
4231
|
+
const latest = current;
|
|
4232
|
+
if (latest && identities.length === latest.identities.length && identities.every((id, i) => id === latest.identities[i] && parts[i] === latest.parts[i])) return latest.chain;
|
|
4039
4233
|
const chain = Object.freeze(parts.flatMap((part, i) => part.pages.map((page) => Object.freeze({
|
|
4040
4234
|
page,
|
|
4041
4235
|
origin: scopes[i].origin
|
|
4042
4236
|
}))));
|
|
4043
4237
|
toolViews.add(chain);
|
|
4044
|
-
current =
|
|
4238
|
+
current = {
|
|
4045
4239
|
identities,
|
|
4046
4240
|
parts,
|
|
4047
4241
|
chain
|
|
4048
|
-
}
|
|
4242
|
+
};
|
|
4049
4243
|
return chain;
|
|
4050
4244
|
});
|
|
4051
4245
|
return stores;
|
|
@@ -4439,6 +4633,6 @@ function explainKnowledgeTarget(index, target) {
|
|
|
4439
4633
|
};
|
|
4440
4634
|
}
|
|
4441
4635
|
//#endregion
|
|
4442
|
-
export {
|
|
4636
|
+
export { snapshotSourceTextInput as $, mediaTypeFor$1 as $n, SourceRecordSchema as $t, validateKnowledgePage as A, finishKnowledgeFileTransaction as An, knowledgePageFromMarkdown as At, DEADLINE_EXIT_CODE as B, listRegularFilesWithinRoot as Bn, KnowledgeGraphEdgeSchema as Bt, immutablePageDigest as C, recoverPendingKnowledgeMutation as Cn, resolveKnowledgeCitations as Ct, normalizeVisibilityArtifact as D, applyKnowledgeFileTransaction as Dn, initKnowledgeBase as Dt, nonEmpty as E, withKnowledgeRead as En, SCAFFOLD_PAGE_BASENAMES as Et, detectNearDuplicatePages as F, normalizePagesDirectory as Fn, extractWikilinks as Ft, gradeFor as G, renameDurable as Gn, KnowledgeRelationGraphSchema as Gt, assertGradeableEvidence as H, readRegularFileWithinRoot as Hn, KnowledgeIndexSchema as Ht, normalizePageText as I, canonicalPathsEqual as In, normalizeLinkTarget as It, buildKnowledgeIndex as J, withSafeDirectory as Jn, ResearchClaimEvidenceSchema as Jt, verdictFor as K, syncDirectory as Kn, KnowledgeRelationNodeSchema as Kt, validateKnowledgeIndex as L, canonicalRelativeWithinRoot as Ln, DeepQuestionSchema as Lt, verifyKnowledgeVisibilitySnapshot as M, prepareKnowledgeFileTransaction as Mn, loadKnowledgePages as Mt, visibilityIdentity as N, rollbackKnowledgeFileTransaction as Nn, writeJson as Nt, normalizeVisibilityRef as O, assertKnowledgeMutationPath as On, isKnowledgePagePath as Ot, visibilityIndexOf as P, DEFAULT_PAGES_DIRECTORY as Pn, WIKILINK_REGEX as Pt, loadSourceRegistry as Q, writeJsonDurableWithinRoot as Qn, SourceAnchorSchema as Qt, lintKnowledgeIndex as R, isKernelAnchoredPath as Rn, KnowledgeBaseCandidateSchema as Rt, encodeKnowledgeVisibilitySnapshot as S, measureKnowledgeMutation as Sn, resolveKnowledgeCitation as St, knowledgeVisibilityArtifactRef as T, withKnowledgeMutation as Tn, resolveRunScopedCitations as Tt, claimCheckKey as U, relativeWithinRoot as Un, KnowledgePageInvalidationSchema as Ut, UncheckableClaimError as V, readRegularFileNoFollow as Vn, KnowledgeGraphNodeSchema as Vt, gradeClaims as W, removeDurable as Wn, KnowledgePageSchema as Wt, addSourcePath as X, writeFileDurableWithinRoot as Xn, ResearchClaimRecordSchema as Xt, writeKnowledgeIndex as Y, writeFileDurable as Yn, ResearchClaimLedgerSchema as Yt, addSourceText as Z, writeJsonDurable as Zn, ResearchSourceVersionSchema as Zt, KNOWLEDGE_USE_RECEIPT_SCHEMA_VERSION as _, formatFrontmatter as _n, assertRunScopedCitationsResolved as _t, applyKnowledgeWriteBlocksFile as a, assertTrackedClaimIntegrity as an, KB_EVENTS_PATH as at, decodeKnowledgeVisibilitySnapshot as b, inspectPendingKnowledgeMutation as bn, formatKnowledgeCitationReference as bt, KnowledgeDuplicateIntakeError as c, claimSourceHost as cn, MemoryKbStore as ct, createFileRunLineageAuthority as d, linkClaimContradictions as dn, knowledgePageRelations as dt, KNOWLEDGE_EVENT_TYPES as en, textSourceAdapter as er, sourceRegistryPath as et, createRunScopedStores as f, materializeRegisteredClaimEvidence as fn, KnowledgeCitationAuditError as ft, KNOWLEDGE_RECEIPT_DIGEST_ALGORITHM as g, researchSourceVersionKey as gn, assertKnowledgeCitationsResolved as gt, originatedPages as h, normalizeClaimText as hn, assertKnowledgeCitationAudit as ht, applyKnowledgeWriteBlocks as i, assertResearchClaimLedgerIntegrity as in, KB_CLAIM_LEDGER_DIR as it, validateOrigin as j, knowledgeFileTransactionPlanHash as jn, layoutFor as jt, snapshotImmutableVisibility as k, commitKnowledgeFileMutations as kn, isScaffoldPath as kt, assertKnowledgeWriteIntake as l, deepQuestionId as ln, assertClaimLedgerId as lt, loadKnowledgeToolChain as m, mergeTrackedClaims as mn, assertCurrentRunCitationsResolved as mt, inspectKnowledgeIndex as n, assertDeepQuestionIntegrity as nn, ClaimLedgerMigrationRequiredError as nt, isSafeKnowledgePath as o, claimEvidenceId as on, KB_INDEX_PATH as ot, isKnowledgeToolChain as p, mergeClaimLedgers as pn, KnowledgeCitationResolutionError as pt, verifyGradeableEvidence as q, withSafeDescendant as qn, KnowledgeRelationSchema as qt, stringMetadata as r, assertResearchClaimEvidenceIntegrity as rn, FileSystemKbStore as rt, parseKnowledgeWriteBlocks as s, claimId as sn, KB_STORE_DIR as st, explainKnowledgeTarget as t, ClaimLedgerGoalConflictError as tn, writeSourceRegistry as tt, RUN_LINEAGE_BASENAME as u, emptyClaimLedger as un, buildKnowledgeGraph as ut, assertSchemaVersion as v, parseFrontmatter as vn, auditCurrentRunCitations as vt, knowledgePageDigest as w, runInKnowledgeMutationScope as wn, resolveRunScopedCitation as wt, digest as x, isKnowledgeMutationHeld as xn, parseKnowledgeCitationReference as xt, createKnowledgeVisibilitySnapshot as y, acquireDurableFileLock as yn, auditKnowledgeCitations as yt, CHECKABLE_RUNG_THRESHOLD as z, isMissingFile as zn, KnowledgeEventSchema as zt };
|
|
4443
4637
|
|
|
4444
|
-
//# sourceMappingURL=inspect-
|
|
4638
|
+
//# sourceMappingURL=inspect-C6c4zuKp.js.map
|