@tangle-network/agent-knowledge 10.7.0 → 10.8.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 +40 -0
- package/dist/benchmarks/index.js +1 -1
- package/dist/{benchmarks-B6fCb6AD.js → benchmarks-Qk94Gnj4.js} +48 -10
- package/dist/benchmarks-Qk94Gnj4.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index-DZeFm-BP.d.ts.map +1 -1
- package/dist/index.d.ts +43 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +32 -27
- package/dist/index.js.map +1 -1
- package/dist/{inspect-DALsvG10.js → inspect-yYqLQuM4.js} +86 -13
- package/dist/inspect-yYqLQuM4.js.map +1 -0
- package/dist/memory/index.js +2 -2
- package/dist/{memory-BRGsy2QN.js → memory-DFSo2iLi.js} +3 -12
- package/dist/memory-DFSo2iLi.js.map +1 -0
- package/package.json +7 -6
- package/dist/benchmarks-B6fCb6AD.js.map +0 -1
- package/dist/inspect-DALsvG10.js.map +0 -1
- package/dist/memory-BRGsy2QN.js.map +0 -1
|
@@ -2,7 +2,7 @@ import { i as textSourceId, n as slugify, r as stableId, t as sha256 } from "./i
|
|
|
2
2
|
import { r as searchKnowledge } from "./search-Cw6eYfSd.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
|
-
import { basename, dirname, isAbsolute, join, relative, resolve
|
|
5
|
+
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
6
6
|
import { contentHash } from "@tangle-network/agent-eval";
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
import { constants } from "node:fs";
|
|
@@ -244,6 +244,72 @@ async function openDirectory(path) {
|
|
|
244
244
|
function isKernelAnchoredPath(path) {
|
|
245
245
|
return process.platform === "linux" && /^\/proc\/self\/fd\/\d+(?:\/|$)/.test(path);
|
|
246
246
|
}
|
|
247
|
+
/**
|
|
248
|
+
* The path from `root` down to `candidate`, or undefined when `candidate` is not
|
|
249
|
+
* strictly inside `root`.
|
|
250
|
+
*
|
|
251
|
+
* The comparison is lexical, so both arguments must already share one
|
|
252
|
+
* canonicalization basis. Use `canonicalRelativeWithinRoot` when either side can
|
|
253
|
+
* carry a different basis.
|
|
254
|
+
*
|
|
255
|
+
* An empty result means the two paths are equal. A root is not inside itself,
|
|
256
|
+
* and a caller that treats it as a descendant would hand its own root to
|
|
257
|
+
* machinery that may remove the directory it is given.
|
|
258
|
+
*/
|
|
259
|
+
function relativeWithinRoot(root, candidate) {
|
|
260
|
+
const value = relative(resolve(root), resolve(candidate)).replace(/\\/g, "/");
|
|
261
|
+
if (value === "" || value === ".." || value.startsWith("../") || isAbsolute(value)) return;
|
|
262
|
+
return value;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* The path from `root` down to `candidate`, with both sides canonicalized before
|
|
266
|
+
* they are compared.
|
|
267
|
+
*
|
|
268
|
+
* `resolve` is lexical: it cannot read a symbolic link, so a path that has been
|
|
269
|
+
* through `realpath` and one that has not describe the same directory with
|
|
270
|
+
* different strings, and comparing the two rejects a directory that genuinely
|
|
271
|
+
* sits inside the root. `openSafeDirectoryTree` canonicalizes the root it opens,
|
|
272
|
+
* so any path that reaches a caller through `withSafeDirectory` carries the
|
|
273
|
+
* canonical form while a path the caller built itself does not.
|
|
274
|
+
*
|
|
275
|
+
* Canonicalizing both sides also tightens the boundary: a candidate that leaves
|
|
276
|
+
* the root through a symbolic link is rejected here, where a lexical comparison
|
|
277
|
+
* admits it.
|
|
278
|
+
*
|
|
279
|
+
* Neither path has to exist. The deepest existing ancestor of each is
|
|
280
|
+
* canonicalized and the remaining segments are appended, so a directory that is
|
|
281
|
+
* about to be created is measured against the same root as one that already is.
|
|
282
|
+
*/
|
|
283
|
+
async function canonicalRelativeWithinRoot(root, candidate) {
|
|
284
|
+
return relativeWithinRoot(isKernelAnchoredPath(root) ? root : await canonicalizeThroughMissing(root), isKernelAnchoredPath(candidate) ? candidate : await canonicalizeThroughMissing(candidate));
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Whether two paths name the same location, with both sides canonicalized first.
|
|
288
|
+
*
|
|
289
|
+
* A path stored by one caller and a path supplied by another reach this
|
|
290
|
+
* comparison through different routes, so the same location can arrive under two
|
|
291
|
+
* spellings. Comparing the resolved strings reports a mismatch that does not
|
|
292
|
+
* exist.
|
|
293
|
+
*/
|
|
294
|
+
async function canonicalPathsEqual(left, right) {
|
|
295
|
+
const [canonicalLeft, canonicalRight] = await Promise.all([isKernelAnchoredPath(left) ? left : canonicalizeThroughMissing(left), isKernelAnchoredPath(right) ? right : canonicalizeThroughMissing(right)]);
|
|
296
|
+
return canonicalLeft === canonicalRight;
|
|
297
|
+
}
|
|
298
|
+
/** The canonical form of a path whose trailing segments may not exist yet. */
|
|
299
|
+
async function canonicalizeThroughMissing(path) {
|
|
300
|
+
const missing = [];
|
|
301
|
+
let current = resolve(path);
|
|
302
|
+
for (;;) try {
|
|
303
|
+
const existing = await realpath(current);
|
|
304
|
+
return missing.length === 0 ? existing : join(existing, ...missing.reverse());
|
|
305
|
+
} catch (error) {
|
|
306
|
+
if (!isMissingFile(error)) throw error;
|
|
307
|
+
const parent = dirname(current);
|
|
308
|
+
if (parent === current) throw error;
|
|
309
|
+
missing.push(basename(current));
|
|
310
|
+
current = parent;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
247
313
|
function anchoredDirectoryPath(handle, fallback) {
|
|
248
314
|
return process.platform === "linux" ? `/proc/self/fd/${handle.fd}` : fallback;
|
|
249
315
|
}
|
|
@@ -340,20 +406,21 @@ const transactionDirectionSchema = z.object({
|
|
|
340
406
|
transactionId: z.string().uuid(),
|
|
341
407
|
direction: z.literal("rollback")
|
|
342
408
|
}).strict();
|
|
343
|
-
function knowledgeFileTransactionPlanHash(entries) {
|
|
344
|
-
const normalized = entries.map((entry) => normalizePlanEntry(entry)).sort((left, right) => left.path.localeCompare(right.path));
|
|
409
|
+
function knowledgeFileTransactionPlanHash(entries, pagesDirectory) {
|
|
410
|
+
const normalized = entries.map((entry) => normalizePlanEntry(entry, pagesDirectory)).sort((left, right) => left.path.localeCompare(right.path));
|
|
345
411
|
if (new Set(normalized.map((entry) => entry.path)).size !== normalized.length) throw new Error("knowledge transaction plan repeats a path");
|
|
346
412
|
return contentHash(normalized);
|
|
347
413
|
}
|
|
348
414
|
async function prepareKnowledgeFileTransaction(input) {
|
|
349
415
|
if (input.mutations.length === 0) throw new Error("knowledge file transaction has no mutations");
|
|
350
416
|
const pagesDirectory = input.pagesDirectory === void 0 ? void 0 : normalizePagesDirectory(input.pagesDirectory);
|
|
417
|
+
const boundPagesDirectory = normalizePagesDirectory(input.pagesDirectory);
|
|
351
418
|
return withTransactionRoot(input.root, input.transactionRoot, true, async (transactionRoot) => {
|
|
352
419
|
const activeTransactions = await activeTransactionDirectoryNames(transactionRoot);
|
|
353
420
|
if (activeTransactions.length > 0) throw new Error(`knowledge file transaction is already active: ${activeTransactions.join(", ")}`);
|
|
354
421
|
const paths = /* @__PURE__ */ new Set();
|
|
355
422
|
const changed = (await Promise.all(input.mutations.map(async (mutation, index) => {
|
|
356
|
-
const path = assertKnowledgeMutationPath(mutation.path,
|
|
423
|
+
const path = assertKnowledgeMutationPath(mutation.path, boundPagesDirectory);
|
|
357
424
|
if (paths.has(path)) throw new Error(`knowledge file transaction repeats path: ${path}`);
|
|
358
425
|
if (mutation.content === null && mutation.mode !== void 0) throw new Error(`deleted knowledge file cannot declare a mode: ${path}`);
|
|
359
426
|
paths.add(path);
|
|
@@ -637,16 +704,16 @@ async function withTransactionRoot(root, transactionRoot, create, use) {
|
|
|
637
704
|
if (!match?.[1]) throw new Error("knowledge transaction directory has an invalid anchor");
|
|
638
705
|
return withSafeDirectory(match[1], match[2] ?? "", create, use);
|
|
639
706
|
}
|
|
640
|
-
const
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
return withSafeDirectory(root, relative(resolvedRoot, resolvedTransactionRoot).replace(/\\/g, "/"), create, use);
|
|
707
|
+
const within = await canonicalRelativeWithinRoot(root, transactionRoot);
|
|
708
|
+
if (within === void 0) throw new Error("knowledge transaction directory escaped its root");
|
|
709
|
+
return withSafeDirectory(root, within, create, use);
|
|
644
710
|
}
|
|
645
711
|
function assertTransactionEntries(transaction) {
|
|
646
712
|
const indexes = /* @__PURE__ */ new Set();
|
|
647
713
|
const paths = /* @__PURE__ */ new Set();
|
|
714
|
+
const boundPagesDirectory = normalizePagesDirectory(transaction.pagesDirectory);
|
|
648
715
|
for (const entry of transaction.entries) {
|
|
649
|
-
const normalized = assertKnowledgeMutationPath(entry.path,
|
|
716
|
+
const normalized = assertKnowledgeMutationPath(entry.path, boundPagesDirectory);
|
|
650
717
|
if (entry.path !== normalized || indexes.has(entry.index) || paths.has(entry.path)) throw new Error("knowledge file transaction has duplicate or unsafe entries");
|
|
651
718
|
assertHashModePair(entry.path, "before", entry.beforeHash, entry.beforeMode);
|
|
652
719
|
assertHashModePair(entry.path, "after", entry.afterHash, entry.afterMode);
|
|
@@ -654,8 +721,8 @@ function assertTransactionEntries(transaction) {
|
|
|
654
721
|
paths.add(entry.path);
|
|
655
722
|
}
|
|
656
723
|
}
|
|
657
|
-
function normalizePlanEntry(entry) {
|
|
658
|
-
const path = assertKnowledgeMutationPath(entry.path);
|
|
724
|
+
function normalizePlanEntry(entry, pagesDirectory) {
|
|
725
|
+
const path = assertKnowledgeMutationPath(entry.path, pagesDirectory);
|
|
659
726
|
assertHashModePair(path, "before", entry.beforeHash, entry.beforeMode);
|
|
660
727
|
assertHashModePair(path, "after", entry.afterHash, entry.afterMode);
|
|
661
728
|
return {
|
|
@@ -674,6 +741,12 @@ function assertHashModePair(path, side, hash, mode) {
|
|
|
674
741
|
* Root-relative prefixes a knowledge transaction may write under. The pages
|
|
675
742
|
* directory is the only caller-selected member; the source registry file and
|
|
676
743
|
* the `raw/` evidence tree are package-owned and always present.
|
|
744
|
+
*
|
|
745
|
+
* The pages directory is stated rather than defaulted. A store laid out under
|
|
746
|
+
* `kb/pages/` is checked against a different allowlist from one laid out under
|
|
747
|
+
* `knowledge/`, so a caller that omits it is not asking for a safe default: it
|
|
748
|
+
* is asking for someone else's allowlist. Pass `DEFAULT_PAGES_DIRECTORY` where
|
|
749
|
+
* the default is the deliberate answer.
|
|
677
750
|
*/
|
|
678
751
|
function knowledgeMutationPathPrefixes(pagesDirectory) {
|
|
679
752
|
return [`${normalizePagesDirectory(pagesDirectory)}/`, "raw/"];
|
|
@@ -3721,6 +3794,6 @@ function explainKnowledgeTarget(index, target) {
|
|
|
3721
3794
|
};
|
|
3722
3795
|
}
|
|
3723
3796
|
//#endregion
|
|
3724
|
-
export { resolveKnowledgeCitations as $, withKnowledgeRead as $t, sourceRegistryPath as A, KNOWLEDGE_EVENT_TYPES as At, buildKnowledgeGraph as B, emptyClaimLedger as Bt, verifyGradeableEvidence as C,
|
|
3797
|
+
export { resolveKnowledgeCitations as $, withKnowledgeRead as $t, sourceRegistryPath as A, KNOWLEDGE_EVENT_TYPES as At, buildKnowledgeGraph as B, emptyClaimLedger as Bt, verifyGradeableEvidence as C, writeFileDurableWithinRoot as Cn, KnowledgeRelationSchema as Ct, addSourceText as D, textSourceAdapter as Dn, ResearchSourceVersionSchema as Dt, addSourcePath as E, mediaTypeFor$1 as En, ResearchClaimRecordSchema as Et, KB_EVENTS_PATH as F, assertTrackedClaimIntegrity as Ft, assertKnowledgeCitationAudit as G, normalizeClaimText as Gt, KnowledgeCitationAuditError as H, materializeRegisteredClaimEvidence as Ht, KB_INDEX_PATH as I, claimEvidenceId as It, auditCurrentRunCitations as J, parseFrontmatter as Jt, assertKnowledgeCitationsResolved as K, researchSourceVersionKey as Kt, KB_STORE_DIR as L, claimId as Lt, ClaimLedgerMigrationRequiredError as M, assertDeepQuestionIntegrity as Mt, FileSystemKbStore as N, assertResearchClaimEvidenceIntegrity as Nt, loadSourceRegistry as O, SourceAnchorSchema as Ot, KB_CLAIM_LEDGER_DIR as P, assertResearchClaimLedgerIntegrity as Pt, resolveKnowledgeCitation as Q, withKnowledgeMutation as Qt, MemoryKbStore as R, claimSourceHost as Rt, verdictFor as S, writeFileDurable as Sn, KnowledgeRelationNodeSchema as St, writeKnowledgeIndex as T, writeJsonDurableWithinRoot as Tn, ResearchClaimLedgerSchema as Tt, KnowledgeCitationResolutionError as U, mergeClaimLedgers as Ut, knowledgePageRelations as V, linkClaimContradictions as Vt, assertCurrentRunCitationsResolved as W, mergeTrackedClaims as Wt, formatKnowledgeCitationReference as X, inspectPendingKnowledgeMutation as Xt, auditKnowledgeCitations as Y, acquireDurableFileLock as Yt, parseKnowledgeCitationReference as Z, recoverPendingKnowledgeMutation as Zt, lintKnowledgeIndex as _, removeDurable as _n, KnowledgeGraphNodeSchema as _t, applyKnowledgeWriteBlocksFile as a, prepareKnowledgeFileTransaction as an, isScaffoldPath as at, assertGradeableEvidence as b, withSafeDescendant as bn, KnowledgePageSchema as bt, KnowledgeDuplicateIntakeError as c, normalizePagesDirectory as cn, loadKnowledgePages as ct, createFileRunLineageAuthority as d, isKernelAnchoredPath as dn, extractWikilinks as dt, applyKnowledgeFileTransaction as en, resolveRunScopedCitation as et, createRunScopedStores as f, isMissingFile as fn, normalizeLinkTarget as ft, validateKnowledgeIndex as g, relativeWithinRoot as gn, KnowledgeGraphEdgeSchema as gt, normalizePageText as h, readRegularFileWithinRoot as hn, KnowledgeEventSchema as ht, applyKnowledgeWriteBlocks as i, knowledgeFileTransactionPlanHash as in, isKnowledgePagePath as it, writeSourceRegistry as j, ClaimLedgerGoalConflictError as jt, snapshotSourceTextInput as k, SourceRecordSchema as kt, assertKnowledgeWriteIntake as l, canonicalPathsEqual as ln, writeJson as lt, detectNearDuplicatePages as m, readRegularFileNoFollow as mn, KnowledgeBaseCandidateSchema as mt, inspectKnowledgeIndex as n, commitKnowledgeFileMutations as nn, SCAFFOLD_PAGE_BASENAMES as nt, isSafeKnowledgePath as o, rollbackKnowledgeFileTransaction as on, knowledgePageFromMarkdown as ot, originatedPages as p, listRegularFilesWithinRoot as pn, DeepQuestionSchema as pt, assertRunScopedCitationsResolved as q, formatFrontmatter as qt, stringMetadata as r, finishKnowledgeFileTransaction as rn, initKnowledgeBase as rt, parseKnowledgeWriteBlocks as s, DEFAULT_PAGES_DIRECTORY as sn, layoutFor as st, explainKnowledgeTarget as t, assertKnowledgeMutationPath as tn, resolveRunScopedCitations as tt, RUN_LINEAGE_BASENAME as u, canonicalRelativeWithinRoot as un, WIKILINK_REGEX as ut, CHECKABLE_RUNG_THRESHOLD as v, renameDurable as vn, KnowledgeIndexSchema as vt, buildKnowledgeIndex as w, writeJsonDurable as wn, ResearchClaimEvidenceSchema as wt, gradeFor as x, withSafeDirectory as xn, KnowledgeRelationGraphSchema as xt, UncheckableClaimError as y, syncDirectory as yn, KnowledgePageInvalidationSchema as yt, assertClaimLedgerId as z, deepQuestionId as zt };
|
|
3725
3798
|
|
|
3726
|
-
//# sourceMappingURL=inspect-
|
|
3799
|
+
//# sourceMappingURL=inspect-yYqLQuM4.js.map
|