@hraness/kb 0.17.1
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/DISCLOSURE +43 -0
- package/LICENSE +21 -0
- package/README.md +545 -0
- package/dist/agent-context.js +35 -0
- package/dist/agent-guide-audit.js +18 -0
- package/dist/attachments.js +19 -0
- package/dist/authoring.js +33 -0
- package/dist/benchmark.js +19 -0
- package/dist/capture.js +49 -0
- package/dist/cli.js +3646 -0
- package/dist/clip/acquire.js +57 -0
- package/dist/clip/args.js +21 -0
- package/dist/clip/bounded-byte-buffer.js +9 -0
- package/dist/clip/browser-profiles.js +17 -0
- package/dist/clip/bundle-reader.js +11 -0
- package/dist/clip/cli.js +27 -0
- package/dist/clip/cookies.js +21 -0
- package/dist/clip/defuddle-worker.js +84 -0
- package/dist/clip/doctor.js +32 -0
- package/dist/clip/jobs.js +784 -0
- package/dist/clip/network-proxy.js +9 -0
- package/dist/clip/network.js +28 -0
- package/dist/clip/persist.js +30 -0
- package/dist/clip/refresh.js +11 -0
- package/dist/clip/terminal.js +11 -0
- package/dist/evaluation-builder.js +12238 -0
- package/dist/evaluation-kb.js +26 -0
- package/dist/evaluation.js +35 -0
- package/dist/git.js +39 -0
- package/dist/graph.js +39 -0
- package/dist/index-01jj6rbv.js +1103 -0
- package/dist/index-06c9ctr6.js +738 -0
- package/dist/index-0kavxzqj.js +2480 -0
- package/dist/index-1gwbassd.js +743 -0
- package/dist/index-1n418kb9.js +827 -0
- package/dist/index-1vrd1rmn.js +56 -0
- package/dist/index-1xxnjn0d.js +171 -0
- package/dist/index-3rm7cz6h.js +373 -0
- package/dist/index-3v2z4f0q.js +328 -0
- package/dist/index-48pz4jpc.js +392 -0
- package/dist/index-4j3tt0c3.js +234 -0
- package/dist/index-5n05se68.js +307 -0
- package/dist/index-5vwpzb5a.js +764 -0
- package/dist/index-6g2pv9d2.js +370 -0
- package/dist/index-7fzc32gf.js +712 -0
- package/dist/index-84x0vjjp.js +432 -0
- package/dist/index-adx6khj5.js +488 -0
- package/dist/index-b88v3vtm.js +805 -0
- package/dist/index-cv6fh7z5.js +462 -0
- package/dist/index-cxfrakt7.js +1067 -0
- package/dist/index-d13v9ckt.js +150 -0
- package/dist/index-dycjbhw2.js +1943 -0
- package/dist/index-dyqwejk5.js +531 -0
- package/dist/index-e5fbsywq.js +658 -0
- package/dist/index-f984hw45.js +927 -0
- package/dist/index-gh719d91.js +63 -0
- package/dist/index-hgve9rh2.js +2046 -0
- package/dist/index-hya40gb2.js +474 -0
- package/dist/index-j4zgmzjr.js +152 -0
- package/dist/index-jsmvyyvf.js +1166 -0
- package/dist/index-kh0pwvdd.js +1974 -0
- package/dist/index-mqx4nd6v.js +119 -0
- package/dist/index-mxxxytys.js +1254 -0
- package/dist/index-n5dd7r0v.js +711 -0
- package/dist/index-npg9z1a4.js +431 -0
- package/dist/index-pj501bh1.js +140 -0
- package/dist/index-qry4vhxk.js +1041 -0
- package/dist/index-s2gw5aw9.js +199 -0
- package/dist/index-vvdj6kca.js +70 -0
- package/dist/index-w2zc0vwa.js +571 -0
- package/dist/index-x3fthpsc.js +585 -0
- package/dist/index-zr53sf63.js +44 -0
- package/dist/index-zxdy5pby.js +2728 -0
- package/dist/index-zzhgcwyt.js +966 -0
- package/dist/index.js +453 -0
- package/dist/navigation.js +13 -0
- package/dist/pdf.js +85 -0
- package/dist/percolate.js +24 -0
- package/dist/portfolio.js +77 -0
- package/dist/query.js +29 -0
- package/dist/repository-memory.js +60 -0
- package/dist/sdk.js +36 -0
- package/dist/search-rules.js +34 -0
- package/dist/search.js +22 -0
- package/dist/semantic.js +39 -0
- package/dist/source-inbox.js +17 -0
- package/dist/untrusted-content.js +32 -0
- package/dist/url-intelligence.js +74 -0
- package/dist/workflow.js +23 -0
- package/dist/workflows/decision-context.js +20 -0
- package/dist/workflows/explain-change.js +8 -0
- package/dist/workflows/index.js +28 -0
- package/dist/workflows/plan-radar.js +10 -0
- package/package.json +409 -0
- package/skills/kb/AGENTS.md +19 -0
- package/skills/kb/SKILL.md +82 -0
- package/skills/kb/agents/openai.yaml +4 -0
- package/skills/kb/references/pdf-review.md +51 -0
- package/skills/kb/references/percolate.md +144 -0
- package/skills/kb/references/plan-structure.md +105 -0
- package/skills/kb/references/plan.md +115 -0
- package/skills/kb/references/query.md +231 -0
- package/skills/kb/references/refresh.md +133 -0
- package/skills/kb/references/save-pdf.md +125 -0
- package/skills/kb/references/save-url.md +178 -0
- package/skills/kb/references/url-authentication.md +75 -0
- package/skills/kb/references/url-platforms.md +25 -0
- package/src/agent-context.ts +1241 -0
- package/src/agent-guide-audit.ts +750 -0
- package/src/attachments.ts +723 -0
- package/src/authoring.ts +1725 -0
- package/src/benchmark.ts +362 -0
- package/src/capture.ts +68 -0
- package/src/cli.ts +3660 -0
- package/src/clip/acquire.ts +1273 -0
- package/src/clip/archive-today.ts +402 -0
- package/src/clip/args.ts +423 -0
- package/src/clip/assets.ts +262 -0
- package/src/clip/bounded-byte-buffer.ts +75 -0
- package/src/clip/browser-profiles.ts +372 -0
- package/src/clip/bundle-reader.ts +608 -0
- package/src/clip/capture.ts +1054 -0
- package/src/clip/cli.ts +181 -0
- package/src/clip/cookies.ts +512 -0
- package/src/clip/doctor.ts +1110 -0
- package/src/clip/extract.ts +868 -0
- package/src/clip/jobs.ts +959 -0
- package/src/clip/lib.ts +861 -0
- package/src/clip/media.ts +1474 -0
- package/src/clip/metadata-search-tool/Cargo.lock +2498 -0
- package/src/clip/metadata-search-tool/Cargo.toml +18 -0
- package/src/clip/metadata-search-tool/runner.ts +685 -0
- package/src/clip/metadata-search-tool/src/main.rs +389 -0
- package/src/clip/metadata-search.ts +687 -0
- package/src/clip/network-proxy.ts +627 -0
- package/src/clip/network.ts +950 -0
- package/src/clip/package-root.ts +54 -0
- package/src/clip/persist.ts +1472 -0
- package/src/clip/platforms.ts +1824 -0
- package/src/clip/refresh.ts +197 -0
- package/src/clip/structured.ts +432 -0
- package/src/clip/terminal.ts +197 -0
- package/src/clip/url-intelligence.ts +581 -0
- package/src/clip/url-metadata-backfill.ts +616 -0
- package/src/clip/url-metadata-cli.ts +251 -0
- package/src/clip/url-metadata.ts +1397 -0
- package/src/evaluation-analysis-v2.ts +1440 -0
- package/src/evaluation-builder.ts +2539 -0
- package/src/evaluation-corpus-authoring.ts +2052 -0
- package/src/evaluation-evidence.ts +1147 -0
- package/src/evaluation-execution-v2.ts +426 -0
- package/src/evaluation-implementation.ts +131 -0
- package/src/evaluation-kb-closure.ts +1430 -0
- package/src/evaluation-kb-runner-v2.ts +735 -0
- package/src/evaluation-kb-v2.ts +2567 -0
- package/src/evaluation-kb.ts +1018 -0
- package/src/evaluation-measurement-v2.ts +1462 -0
- package/src/evaluation-packing-v2.ts +452 -0
- package/src/evaluation-redaction.ts +28 -0
- package/src/evaluation-v2.ts +3857 -0
- package/src/evaluation.ts +1220 -0
- package/src/git.ts +1276 -0
- package/src/graph.ts +1487 -0
- package/src/index.ts +20 -0
- package/src/init.ts +123 -0
- package/src/navigation.ts +277 -0
- package/src/note-lock.ts +529 -0
- package/src/pdf/args.ts +202 -0
- package/src/pdf/capture.ts +298 -0
- package/src/pdf/cli.ts +159 -0
- package/src/pdf/extract.ts +303 -0
- package/src/pdf/layout.ts +618 -0
- package/src/pdf/markdown.ts +154 -0
- package/src/pdf/model.ts +234 -0
- package/src/pdf/ocr.ts +190 -0
- package/src/pdf/persist.ts +314 -0
- package/src/pdf/source.ts +135 -0
- package/src/pdf/tools.ts +146 -0
- package/src/pdf.ts +92 -0
- package/src/percolate.ts +877 -0
- package/src/portfolio-audit.ts +574 -0
- package/src/portfolio-identity.ts +162 -0
- package/src/portfolio-registry.ts +473 -0
- package/src/portfolio.ts +765 -0
- package/src/query.ts +646 -0
- package/src/repository-memory.ts +1150 -0
- package/src/sdk.ts +1452 -0
- package/src/search-rules.ts +712 -0
- package/src/search.ts +710 -0
- package/src/semantic-runtime.ts +1139 -0
- package/src/semantic.ts +2480 -0
- package/src/source-inbox.ts +232 -0
- package/src/untrusted-content.ts +401 -0
- package/src/url-intelligence.ts +104 -0
- package/src/vault.ts +636 -0
- package/src/workflow.ts +653 -0
- package/src/workflows/decision-context.ts +81 -0
- package/src/workflows/explain-change.ts +73 -0
- package/src/workflows/index.ts +3 -0
- package/src/workflows/plan-radar.ts +101 -0
|
@@ -0,0 +1,711 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
MAX_SEARCH_RESULTS,
|
|
4
|
+
openKnowledgeBase
|
|
5
|
+
} from "./index-zzhgcwyt.js";
|
|
6
|
+
import {
|
|
7
|
+
scanVault
|
|
8
|
+
} from "./index-zxdy5pby.js";
|
|
9
|
+
import {
|
|
10
|
+
runGitCommand
|
|
11
|
+
} from "./index-1gwbassd.js";
|
|
12
|
+
import {
|
|
13
|
+
MAX_EVALUATION_EVIDENCE_BYTES,
|
|
14
|
+
redactEvaluationMachinePaths
|
|
15
|
+
} from "./index-b88v3vtm.js";
|
|
16
|
+
import {
|
|
17
|
+
MAX_REPOSITORY_MEMORY_DETAIL_LIMIT,
|
|
18
|
+
MAX_REPOSITORY_MEMORY_GROUP_LIMIT,
|
|
19
|
+
buildRepositoryMemoryContext,
|
|
20
|
+
repositoryMemoryGroupKeys
|
|
21
|
+
} from "./index-06c9ctr6.js";
|
|
22
|
+
import {
|
|
23
|
+
inspectAgentContextRepository
|
|
24
|
+
} from "./index-5vwpzb5a.js";
|
|
25
|
+
|
|
26
|
+
// src/evaluation-kb.ts
|
|
27
|
+
import { realpath, stat } from "fs/promises";
|
|
28
|
+
import { isAbsolute, relative, resolve, sep } from "path";
|
|
29
|
+
var objectIdPattern = /^[0-9a-f]{40}(?:[0-9a-f]{24})?$/u;
|
|
30
|
+
var SNAPSHOT_GIT_TIMEOUT_MS = 1e4;
|
|
31
|
+
var SNAPSHOT_GIT_OUTPUT_BYTES = 64 * 1024;
|
|
32
|
+
var DIAGNOSTIC_MESSAGE_BYTES = 16 * 1024;
|
|
33
|
+
var knowledgeBaseEvaluationRetrieverIds = Object.freeze([
|
|
34
|
+
"exact",
|
|
35
|
+
"keyword",
|
|
36
|
+
"semantic",
|
|
37
|
+
"hybrid",
|
|
38
|
+
"metadata",
|
|
39
|
+
"graph",
|
|
40
|
+
"path-context",
|
|
41
|
+
"git"
|
|
42
|
+
]);
|
|
43
|
+
|
|
44
|
+
class FrozenEvaluationSnapshotError extends Error {
|
|
45
|
+
constructor(message, options) {
|
|
46
|
+
super(message, options);
|
|
47
|
+
this.name = "FrozenEvaluationSnapshotError";
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function pathIsWithin(root, candidate) {
|
|
51
|
+
const fromRoot = relative(root, candidate);
|
|
52
|
+
return fromRoot === "" || fromRoot !== ".." && !fromRoot.startsWith(`..${sep}`) && !isAbsolute(fromRoot);
|
|
53
|
+
}
|
|
54
|
+
function decodedOutput(output, label, maximumBytes = SNAPSHOT_GIT_OUTPUT_BYTES) {
|
|
55
|
+
const bytes = typeof output === "string" ? Buffer.from(output, "utf8") : Buffer.from(output);
|
|
56
|
+
if (bytes.byteLength > maximumBytes) {
|
|
57
|
+
throw new FrozenEvaluationSnapshotError(`${label} exceeded the ${maximumBytes.toLocaleString("en-US")}-byte output limit.`);
|
|
58
|
+
}
|
|
59
|
+
return bytes.toString("utf8");
|
|
60
|
+
}
|
|
61
|
+
async function gitOutput(runGit, repository, args, label) {
|
|
62
|
+
const result = await runGit({
|
|
63
|
+
arguments: args,
|
|
64
|
+
cwd: repository,
|
|
65
|
+
timeoutMs: SNAPSHOT_GIT_TIMEOUT_MS,
|
|
66
|
+
maxOutputBytes: SNAPSHOT_GIT_OUTPUT_BYTES
|
|
67
|
+
});
|
|
68
|
+
if (result.status !== "ok") {
|
|
69
|
+
throw new FrozenEvaluationSnapshotError(`${label} could not be verified: ${result.status === "unavailable" ? result.message : result.message}`);
|
|
70
|
+
}
|
|
71
|
+
return decodedOutput(result.stdout, label);
|
|
72
|
+
}
|
|
73
|
+
function gitObjectId(output, label) {
|
|
74
|
+
const value = output.trim();
|
|
75
|
+
if (!objectIdPattern.test(value)) {
|
|
76
|
+
throw new FrozenEvaluationSnapshotError(`${label} returned a malformed Git object ID.`);
|
|
77
|
+
}
|
|
78
|
+
return value;
|
|
79
|
+
}
|
|
80
|
+
async function verifyFrozenEvaluationSnapshot(options) {
|
|
81
|
+
const resolveRealpath = options.realpath ?? realpath;
|
|
82
|
+
const readStat = options.stat ?? stat;
|
|
83
|
+
const repository = await resolveRealpath(resolve(options.repository));
|
|
84
|
+
const repositoryState = await readStat(repository);
|
|
85
|
+
if (!repositoryState.isDirectory()) {
|
|
86
|
+
throw new FrozenEvaluationSnapshotError("The evaluation repository must be a directory.");
|
|
87
|
+
}
|
|
88
|
+
const root = await resolveRealpath(resolve(options.root));
|
|
89
|
+
const rootState = await readStat(root);
|
|
90
|
+
if (!rootState.isDirectory()) {
|
|
91
|
+
throw new FrozenEvaluationSnapshotError("The evaluation vault root must be a directory.");
|
|
92
|
+
}
|
|
93
|
+
if (!pathIsWithin(repository, root)) {
|
|
94
|
+
throw new FrozenEvaluationSnapshotError("The evaluation vault root must resolve inside the repository.");
|
|
95
|
+
}
|
|
96
|
+
const declaredRoot = await resolveRealpath(resolve(repository, options.corpus.frozen.vaultRoot));
|
|
97
|
+
if (!pathIsWithin(repository, declaredRoot) || declaredRoot !== root) {
|
|
98
|
+
throw new FrozenEvaluationSnapshotError("The evaluation vault root must resolve to frozen.vaultRoot inside the repository.");
|
|
99
|
+
}
|
|
100
|
+
const runGit = options.runGit ?? runGitCommand;
|
|
101
|
+
const repositoryPrefix = (await gitOutput(runGit, repository, ["rev-parse", "--show-prefix"], "Git repository root")).trim();
|
|
102
|
+
if (repositoryPrefix !== "") {
|
|
103
|
+
throw new FrozenEvaluationSnapshotError(`The evaluation repository must be the Git working-tree root; Git reported prefix ${JSON.stringify(repositoryPrefix)}.`);
|
|
104
|
+
}
|
|
105
|
+
const head = gitObjectId(await gitOutput(runGit, repository, ["rev-parse", "--verify", "HEAD"], "Git HEAD"), "Git HEAD");
|
|
106
|
+
if (head !== options.corpus.frozen.repositoryCommit) {
|
|
107
|
+
throw new FrozenEvaluationSnapshotError(`Frozen repository commit ${options.corpus.frozen.repositoryCommit} does not match HEAD ${head}.`);
|
|
108
|
+
}
|
|
109
|
+
const vaultRevision = options.corpus.frozen.vaultRoot === "." ? "HEAD^{tree}" : `HEAD:${options.corpus.frozen.vaultRoot}`;
|
|
110
|
+
const vaultTree = gitObjectId(await gitOutput(runGit, repository, ["rev-parse", "--verify", vaultRevision], "Git vault tree"), "Git vault tree");
|
|
111
|
+
if (vaultTree !== options.corpus.frozen.vaultTree) {
|
|
112
|
+
throw new FrozenEvaluationSnapshotError(`Frozen vault tree ${options.corpus.frozen.vaultTree} does not match ${vaultRevision} ${vaultTree}.`);
|
|
113
|
+
}
|
|
114
|
+
const objectType = (await gitOutput(runGit, repository, ["cat-file", "-t", vaultRevision], "Git vault object type")).trim();
|
|
115
|
+
if (objectType !== "tree") {
|
|
116
|
+
throw new FrozenEvaluationSnapshotError(`${vaultRevision} must identify a Git tree, but Git reported ${JSON.stringify(objectType)}.`);
|
|
117
|
+
}
|
|
118
|
+
const status = await gitOutput(runGit, repository, [
|
|
119
|
+
"status",
|
|
120
|
+
"--porcelain=v1",
|
|
121
|
+
"--untracked-files=all",
|
|
122
|
+
"--",
|
|
123
|
+
options.corpus.frozen.vaultRoot
|
|
124
|
+
], "Git vault status");
|
|
125
|
+
if (status.trim() !== "") {
|
|
126
|
+
const firstChange = status.trim().split(/\r?\n/u)[0] ?? "unknown vault change";
|
|
127
|
+
throw new FrozenEvaluationSnapshotError(`The frozen evaluation vault has tracked or untracked changes: ${firstChange}.`);
|
|
128
|
+
}
|
|
129
|
+
return Object.freeze({
|
|
130
|
+
repository,
|
|
131
|
+
root,
|
|
132
|
+
vaultRoot: options.corpus.frozen.vaultRoot,
|
|
133
|
+
repositoryCommit: head,
|
|
134
|
+
vaultTree
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
function elapsed(startedAt, now) {
|
|
138
|
+
const duration = now() - startedAt;
|
|
139
|
+
return Number.isFinite(duration) && duration > 0 ? duration : 0;
|
|
140
|
+
}
|
|
141
|
+
function utf8Prefix(value, maximumBytes) {
|
|
142
|
+
let bytes = 0;
|
|
143
|
+
let end = 0;
|
|
144
|
+
for (const character of value) {
|
|
145
|
+
const width = Buffer.byteLength(character, "utf8");
|
|
146
|
+
if (bytes + width > maximumBytes)
|
|
147
|
+
break;
|
|
148
|
+
bytes += width;
|
|
149
|
+
end += character.length;
|
|
150
|
+
}
|
|
151
|
+
return value.slice(0, end);
|
|
152
|
+
}
|
|
153
|
+
function diagnosticMessage(parts) {
|
|
154
|
+
const joined = redactEvaluationMachinePaths(parts.join(" ").normalize("NFC").replace(/[\0\r\n]+/gu, " ").trim());
|
|
155
|
+
if (joined === "")
|
|
156
|
+
return;
|
|
157
|
+
return utf8Prefix(joined, DIAGNOSTIC_MESSAGE_BYTES);
|
|
158
|
+
}
|
|
159
|
+
function evidenceSnapshot(value) {
|
|
160
|
+
const serialized = JSON.stringify(value, (_key, candidate) => typeof candidate === "string" ? redactEvaluationMachinePaths(candidate) : candidate);
|
|
161
|
+
if (serialized === undefined)
|
|
162
|
+
return null;
|
|
163
|
+
const bytes = Buffer.byteLength(serialized, "utf8");
|
|
164
|
+
if (bytes <= MAX_EVALUATION_EVIDENCE_BYTES) {
|
|
165
|
+
return JSON.parse(serialized);
|
|
166
|
+
}
|
|
167
|
+
let prefixBytes = MAX_EVALUATION_EVIDENCE_BYTES - 1024;
|
|
168
|
+
while (prefixBytes > 0) {
|
|
169
|
+
const snapshot = {
|
|
170
|
+
truncated: true,
|
|
171
|
+
originalUtf8Bytes: bytes,
|
|
172
|
+
jsonPrefix: utf8Prefix(serialized, prefixBytes)
|
|
173
|
+
};
|
|
174
|
+
if (Buffer.byteLength(JSON.stringify(snapshot), "utf8") <= MAX_EVALUATION_EVIDENCE_BYTES) {
|
|
175
|
+
return snapshot;
|
|
176
|
+
}
|
|
177
|
+
prefixBytes = Math.floor(prefixBytes * 0.75);
|
|
178
|
+
}
|
|
179
|
+
return { truncated: true, originalUtf8Bytes: bytes, jsonPrefix: "" };
|
|
180
|
+
}
|
|
181
|
+
function unavailable(id, requiredInput, noteCount) {
|
|
182
|
+
return Object.freeze({
|
|
183
|
+
status: "unavailable",
|
|
184
|
+
hits: Object.freeze([]),
|
|
185
|
+
diagnostics: Object.freeze([Object.freeze({
|
|
186
|
+
lane: id,
|
|
187
|
+
status: "unavailable",
|
|
188
|
+
message: `${id} retrieval requires ${requiredInput}.`
|
|
189
|
+
})]),
|
|
190
|
+
timings: Object.freeze({}),
|
|
191
|
+
resources: Object.freeze({ noteCount })
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
function textHitProvenance(hit) {
|
|
195
|
+
const exactEvidence = hit.evidence.find((evidence) => evidence.kind === "exact");
|
|
196
|
+
const qmdEvidence = hit.evidence.filter((evidence) => evidence.kind === "qmd");
|
|
197
|
+
const explicitLocators = hit.evidence.flatMap((evidence) => evidence.kind !== "exact" ? [] : evidence.matches.flatMap((match) => {
|
|
198
|
+
if (match.field === "title") {
|
|
199
|
+
return [Object.freeze({ kind: "title", title: hit.title })];
|
|
200
|
+
}
|
|
201
|
+
if (match.field === "alias") {
|
|
202
|
+
return [Object.freeze({
|
|
203
|
+
kind: "frontmatter-field-any",
|
|
204
|
+
fields: Object.freeze(["aliases", "alias"])
|
|
205
|
+
})];
|
|
206
|
+
}
|
|
207
|
+
if (match.field === "tag") {
|
|
208
|
+
return [Object.freeze({ kind: "frontmatter-field", field: "tags" })];
|
|
209
|
+
}
|
|
210
|
+
if (match.field === "metadata") {
|
|
211
|
+
return [Object.freeze({ kind: "frontmatter-value", value: match.value })];
|
|
212
|
+
}
|
|
213
|
+
if (match.field === "path") {
|
|
214
|
+
return [Object.freeze({ kind: "source-path", sourcePath: hit.path })];
|
|
215
|
+
}
|
|
216
|
+
return [];
|
|
217
|
+
}));
|
|
218
|
+
const exactContentLocators = hit.line !== undefined && exactEvidence?.matches.some(({ field }) => field === "content") === true && (exactEvidence.identity || qmdEvidence.length === 0) ? [Object.freeze({ kind: "line", line: hit.line })] : [];
|
|
219
|
+
const sameDocumentLocators = [...explicitLocators, ...exactContentLocators];
|
|
220
|
+
const sameDocument = sameDocumentLocators.map((locator) => Object.freeze({
|
|
221
|
+
targetDocumentId: hit.id,
|
|
222
|
+
evidenceDocumentId: hit.id,
|
|
223
|
+
sourcePath: hit.path,
|
|
224
|
+
locator
|
|
225
|
+
}));
|
|
226
|
+
const qmd = qmdEvidence.flatMap((evidence) => evidence.line === undefined || evidence.path === undefined ? [] : [Object.freeze({
|
|
227
|
+
targetDocumentId: hit.id,
|
|
228
|
+
evidenceDocumentId: hit.id,
|
|
229
|
+
sourcePath: evidence.path,
|
|
230
|
+
locator: Object.freeze({ kind: "line", line: evidence.line })
|
|
231
|
+
})]);
|
|
232
|
+
const unique = [...new Map([...sameDocument, ...qmd].map((provenance) => [JSON.stringify(provenance), provenance])).values()];
|
|
233
|
+
return Object.freeze(unique);
|
|
234
|
+
}
|
|
235
|
+
function statusFromDiagnostics(diagnostics, hits) {
|
|
236
|
+
if (hits.length === 0 && diagnostics.length > 0 && diagnostics.every(({ status }) => status === "unavailable"))
|
|
237
|
+
return "unavailable";
|
|
238
|
+
return diagnostics.some(({ status }) => status !== "ready") ? "degraded" : "ready";
|
|
239
|
+
}
|
|
240
|
+
function textResult(result) {
|
|
241
|
+
const hits = Object.freeze(result.results.map((hit) => {
|
|
242
|
+
const provenance = textHitProvenance(hit);
|
|
243
|
+
return Object.freeze({
|
|
244
|
+
documentId: hit.id,
|
|
245
|
+
rank: hit.rank,
|
|
246
|
+
score: hit.score,
|
|
247
|
+
evidence: evidenceSnapshot({
|
|
248
|
+
mode: result.mode,
|
|
249
|
+
path: hit.path,
|
|
250
|
+
title: hit.title,
|
|
251
|
+
identity: hit.identity,
|
|
252
|
+
...hit.line === undefined ? {} : { line: hit.line },
|
|
253
|
+
snippet: hit.snippet,
|
|
254
|
+
evidence: hit.evidence,
|
|
255
|
+
contributions: hit.contributions,
|
|
256
|
+
...provenance.length === 0 ? {} : { provenance }
|
|
257
|
+
})
|
|
258
|
+
});
|
|
259
|
+
}));
|
|
260
|
+
const diagnostics = Object.freeze(result.diagnostics.lanes.map((lane) => Object.freeze({
|
|
261
|
+
lane: lane.lane,
|
|
262
|
+
status: lane.status,
|
|
263
|
+
...lane.message === undefined ? {} : { message: diagnosticMessage([lane.message]) ?? "Search diagnostic unavailable." }
|
|
264
|
+
})));
|
|
265
|
+
const laneResults = new Map(result.diagnostics.lanes.map(({ lane, results }) => [lane, results]));
|
|
266
|
+
return Object.freeze({
|
|
267
|
+
status: statusFromDiagnostics(diagnostics, hits),
|
|
268
|
+
hits,
|
|
269
|
+
diagnostics,
|
|
270
|
+
timings: Object.freeze({ searchMs: result.diagnostics.elapsedMs }),
|
|
271
|
+
resources: Object.freeze({
|
|
272
|
+
noteCount: result.diagnostics.notes,
|
|
273
|
+
resultCount: result.results.length,
|
|
274
|
+
partial: Number(result.partial),
|
|
275
|
+
exactResultCount: laneResults.get("exact") ?? 0,
|
|
276
|
+
qmdResultCount: laneResults.get("qmd") ?? 0,
|
|
277
|
+
...result.diagnostics.queryEmbedding == null ? {} : {
|
|
278
|
+
queryEmbeddingCalls: result.diagnostics.queryEmbedding.calls,
|
|
279
|
+
queryEmbeddingInputTokens: result.diagnostics.queryEmbedding.inputTokens,
|
|
280
|
+
queryEmbeddingDurationMs: result.diagnostics.queryEmbedding.durationMs
|
|
281
|
+
}
|
|
282
|
+
})
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
function stableHits(candidates, limit) {
|
|
286
|
+
const unique = new Map;
|
|
287
|
+
for (const candidate of candidates) {
|
|
288
|
+
if (!unique.has(candidate.documentId))
|
|
289
|
+
unique.set(candidate.documentId, candidate);
|
|
290
|
+
}
|
|
291
|
+
return Object.freeze([...unique.values()].slice(0, limit).map((candidate, index) => Object.freeze({
|
|
292
|
+
documentId: candidate.documentId,
|
|
293
|
+
rank: index + 1,
|
|
294
|
+
...candidate.score === undefined ? {} : { score: candidate.score },
|
|
295
|
+
evidence: evidenceSnapshot(candidate.evidence)
|
|
296
|
+
})));
|
|
297
|
+
}
|
|
298
|
+
function metadataRetriever(session, now) {
|
|
299
|
+
return Object.freeze({
|
|
300
|
+
id: "metadata",
|
|
301
|
+
retrieve: ({ query, limit, signal }) => {
|
|
302
|
+
if (query.inputs.metadata === undefined) {
|
|
303
|
+
return Promise.resolve(unavailable("metadata", "query.inputs.metadata", session.noteCount));
|
|
304
|
+
}
|
|
305
|
+
throwIfAborted(signal);
|
|
306
|
+
const startedAt = now();
|
|
307
|
+
const rows = session.list({
|
|
308
|
+
filters: query.inputs.metadata.filters,
|
|
309
|
+
tags: query.inputs.metadata.tags,
|
|
310
|
+
limit
|
|
311
|
+
});
|
|
312
|
+
throwIfAborted(signal);
|
|
313
|
+
const provenanceFields = [
|
|
314
|
+
...query.inputs.metadata.filters.map(({ path }) => path.split(".")[0]),
|
|
315
|
+
...query.inputs.metadata.tags.length === 0 ? [] : ["tags"]
|
|
316
|
+
].filter((field) => field !== undefined && field !== "");
|
|
317
|
+
const provenanceFieldList = [...new Set(provenanceFields)];
|
|
318
|
+
const hits = Object.freeze(rows.map((row, index) => Object.freeze({
|
|
319
|
+
documentId: row.id,
|
|
320
|
+
rank: index + 1,
|
|
321
|
+
evidence: evidenceSnapshot({
|
|
322
|
+
...row,
|
|
323
|
+
...provenanceFieldList.length === 0 ? {} : {
|
|
324
|
+
provenance: provenanceFieldList.map((field) => ({
|
|
325
|
+
targetDocumentId: row.id,
|
|
326
|
+
evidenceDocumentId: row.id,
|
|
327
|
+
sourcePath: row.path,
|
|
328
|
+
locator: { kind: "frontmatter-field", field }
|
|
329
|
+
}))
|
|
330
|
+
}
|
|
331
|
+
})
|
|
332
|
+
})));
|
|
333
|
+
return Promise.resolve(Object.freeze({
|
|
334
|
+
status: "ready",
|
|
335
|
+
hits,
|
|
336
|
+
diagnostics: Object.freeze([Object.freeze({
|
|
337
|
+
lane: "metadata",
|
|
338
|
+
status: "ready"
|
|
339
|
+
})]),
|
|
340
|
+
timings: Object.freeze({ listMs: elapsed(startedAt, now) }),
|
|
341
|
+
resources: Object.freeze({ noteCount: session.noteCount, resultCount: rows.length })
|
|
342
|
+
}));
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
function graphRetriever(session, now) {
|
|
347
|
+
return Object.freeze({
|
|
348
|
+
id: "graph",
|
|
349
|
+
retrieve: ({ query, limit, signal }) => {
|
|
350
|
+
const input = query.inputs.graph;
|
|
351
|
+
if (input === undefined) {
|
|
352
|
+
return Promise.resolve(unavailable("graph", "query.inputs.graph", session.noteCount));
|
|
353
|
+
}
|
|
354
|
+
throwIfAborted(signal);
|
|
355
|
+
const startedAt = now();
|
|
356
|
+
const matches = new Map;
|
|
357
|
+
const diagnostics = [];
|
|
358
|
+
let edges = 0;
|
|
359
|
+
let relations = 0;
|
|
360
|
+
for (const [seedIndex, seed] of input.seeds.entries()) {
|
|
361
|
+
const neighborhood = session.links(seed, {
|
|
362
|
+
direction: "both",
|
|
363
|
+
depth: input.depth,
|
|
364
|
+
limit
|
|
365
|
+
});
|
|
366
|
+
edges += neighborhood.edges.length;
|
|
367
|
+
relations += neighborhood.relations.length;
|
|
368
|
+
diagnostics.push(Object.freeze({
|
|
369
|
+
lane: "graph",
|
|
370
|
+
status: neighborhood.truncated ? "degraded" : "ready",
|
|
371
|
+
...neighborhood.truncated ? { message: `Graph traversal from ${JSON.stringify(seed)} reached its result limit.` } : {}
|
|
372
|
+
}));
|
|
373
|
+
const nodeIdByPath = new Map(neighborhood.nodes.map((node) => [node.path, node.id]));
|
|
374
|
+
for (const [nodeIndex, node] of neighborhood.nodes.entries()) {
|
|
375
|
+
const links = neighborhood.edges.filter((edge) => edge.source === node.path || edge.target === node.path);
|
|
376
|
+
const authoredRelations = neighborhood.relations.filter((relation) => relation.source === node.id || relation.target === node.id);
|
|
377
|
+
const connections = Object.freeze([
|
|
378
|
+
...links.map((edge) => Object.freeze({ kind: "link", edge })),
|
|
379
|
+
...authoredRelations.map((relation) => Object.freeze({
|
|
380
|
+
kind: "relation",
|
|
381
|
+
relation
|
|
382
|
+
}))
|
|
383
|
+
]);
|
|
384
|
+
const provenance = Object.freeze([...new Map([
|
|
385
|
+
...links.flatMap((link) => {
|
|
386
|
+
const evidenceDocumentId = nodeIdByPath.get(link.source);
|
|
387
|
+
return evidenceDocumentId === undefined ? [] : [Object.freeze({
|
|
388
|
+
targetDocumentId: node.id,
|
|
389
|
+
evidenceDocumentId,
|
|
390
|
+
sourcePath: link.source,
|
|
391
|
+
locator: Object.freeze({ kind: "line", line: link.line })
|
|
392
|
+
})];
|
|
393
|
+
}),
|
|
394
|
+
...authoredRelations.map((relation) => Object.freeze({
|
|
395
|
+
targetDocumentId: node.id,
|
|
396
|
+
evidenceDocumentId: relation.source,
|
|
397
|
+
sourcePath: relation.provenance.source,
|
|
398
|
+
locator: Object.freeze({
|
|
399
|
+
kind: "line",
|
|
400
|
+
line: relation.provenance.line
|
|
401
|
+
})
|
|
402
|
+
}))
|
|
403
|
+
].map((candidate) => [JSON.stringify(candidate), candidate])).values()]);
|
|
404
|
+
const raw = Object.freeze({
|
|
405
|
+
seed,
|
|
406
|
+
node,
|
|
407
|
+
connections,
|
|
408
|
+
...provenance.length === 0 ? {} : { provenance }
|
|
409
|
+
});
|
|
410
|
+
const existing = matches.get(node.id);
|
|
411
|
+
if (existing === undefined) {
|
|
412
|
+
matches.set(node.id, {
|
|
413
|
+
documentId: node.id,
|
|
414
|
+
distance: node.distance,
|
|
415
|
+
seedIndex,
|
|
416
|
+
nodeIndex,
|
|
417
|
+
evidence: [raw]
|
|
418
|
+
});
|
|
419
|
+
} else {
|
|
420
|
+
existing.evidence.push(raw);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
const candidates = [...matches.values()].toSorted((left, right) => left.distance - right.distance || left.seedIndex - right.seedIndex || left.nodeIndex - right.nodeIndex || left.documentId.localeCompare(right.documentId));
|
|
425
|
+
const hits = stableHits(candidates.map((candidate) => ({
|
|
426
|
+
documentId: candidate.documentId,
|
|
427
|
+
score: 1 / (candidate.distance + 1),
|
|
428
|
+
evidence: {
|
|
429
|
+
neighborhoods: candidate.evidence,
|
|
430
|
+
...(() => {
|
|
431
|
+
const provenance = [...new Map(candidate.evidence.flatMap((entry) => entry.provenance ?? []).map((entry) => [JSON.stringify(entry), entry])).values()];
|
|
432
|
+
return provenance.length === 0 ? {} : { provenance: Object.freeze(provenance) };
|
|
433
|
+
})()
|
|
434
|
+
}
|
|
435
|
+
})), limit);
|
|
436
|
+
throwIfAborted(signal);
|
|
437
|
+
return Promise.resolve(Object.freeze({
|
|
438
|
+
status: statusFromDiagnostics(diagnostics, hits),
|
|
439
|
+
hits,
|
|
440
|
+
diagnostics: Object.freeze(diagnostics),
|
|
441
|
+
timings: Object.freeze({ linksMs: elapsed(startedAt, now) }),
|
|
442
|
+
resources: Object.freeze({
|
|
443
|
+
noteCount: session.noteCount,
|
|
444
|
+
seedCount: input.seeds.length,
|
|
445
|
+
resultCount: hits.length,
|
|
446
|
+
edgeCount: edges,
|
|
447
|
+
relationCount: relations
|
|
448
|
+
})
|
|
449
|
+
}));
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
function pathContextDiagnostics(inspection, memory) {
|
|
454
|
+
const inspectionMessage = diagnosticMessage(inspection.issues.map(({ message }) => message));
|
|
455
|
+
const memoryMessages = [
|
|
456
|
+
...memory.invalidRecords.details.flatMap(({ issues }) => issues),
|
|
457
|
+
...memory.advisories.details.map(({ message }) => message),
|
|
458
|
+
...repositoryMemoryGroupKeys.some((key) => memory.groups[key].truncated) ? ["Repository-memory results were truncated by the evaluation limit."] : []
|
|
459
|
+
];
|
|
460
|
+
const memoryMessage = diagnosticMessage(memoryMessages);
|
|
461
|
+
return Object.freeze([
|
|
462
|
+
Object.freeze({
|
|
463
|
+
lane: "agent-context",
|
|
464
|
+
status: inspection.issues.length === 0 ? "ready" : "degraded",
|
|
465
|
+
...inspectionMessage === undefined ? {} : { message: inspectionMessage }
|
|
466
|
+
}),
|
|
467
|
+
Object.freeze({
|
|
468
|
+
lane: "repository-memory",
|
|
469
|
+
status: memoryMessages.length === 0 ? "ready" : "degraded",
|
|
470
|
+
...memoryMessage === undefined ? {} : { message: memoryMessage }
|
|
471
|
+
})
|
|
472
|
+
]);
|
|
473
|
+
}
|
|
474
|
+
function pathContextRetriever(session, snapshot, repository, inspectContext, buildMemory, now) {
|
|
475
|
+
return Object.freeze({
|
|
476
|
+
id: "path-context",
|
|
477
|
+
retrieve: async ({ query, limit, signal }) => {
|
|
478
|
+
const input = query.inputs.context;
|
|
479
|
+
if (input === undefined) {
|
|
480
|
+
return unavailable("path-context", "query.inputs.context", session.noteCount);
|
|
481
|
+
}
|
|
482
|
+
throwIfAborted(signal);
|
|
483
|
+
const inspectionStartedAt = now();
|
|
484
|
+
const inspection = await inspectContext(snapshot.notes, {
|
|
485
|
+
repositoryRoot: repository,
|
|
486
|
+
target: input.repositoryPath,
|
|
487
|
+
targetKind: "auto"
|
|
488
|
+
});
|
|
489
|
+
const inspectionMs = elapsed(inspectionStartedAt, now);
|
|
490
|
+
throwIfAborted(signal);
|
|
491
|
+
const memoryStartedAt = now();
|
|
492
|
+
const memory = await buildMemory(snapshot.notes, {
|
|
493
|
+
repositoryRoot: repository,
|
|
494
|
+
target: input.repositoryPath,
|
|
495
|
+
groupLimit: Math.min(limit, MAX_REPOSITORY_MEMORY_GROUP_LIMIT),
|
|
496
|
+
detailLimit: Math.min(limit, MAX_REPOSITORY_MEMORY_DETAIL_LIMIT)
|
|
497
|
+
});
|
|
498
|
+
const memoryMs = elapsed(memoryStartedAt, now);
|
|
499
|
+
throwIfAborted(signal);
|
|
500
|
+
const candidates = [
|
|
501
|
+
...inspection.matchingContexts.map((hub) => ({
|
|
502
|
+
documentId: hub.note.id,
|
|
503
|
+
evidence: {
|
|
504
|
+
kind: "agent-context",
|
|
505
|
+
path: hub.note.path,
|
|
506
|
+
rawScope: hub.rawScope,
|
|
507
|
+
scope: hub.scope,
|
|
508
|
+
canonicalId: hub.canonicalId,
|
|
509
|
+
canonicalPath: hub.canonicalPath,
|
|
510
|
+
guidePath: hub.guidePath,
|
|
511
|
+
canonical: hub.canonical,
|
|
512
|
+
reciprocal: hub.reciprocal,
|
|
513
|
+
valid: hub.valid,
|
|
514
|
+
provenance: [{
|
|
515
|
+
targetDocumentId: hub.note.id,
|
|
516
|
+
evidenceDocumentId: hub.note.id,
|
|
517
|
+
sourcePath: hub.note.path,
|
|
518
|
+
locator: { kind: "frontmatter-field", field: "scope" }
|
|
519
|
+
}]
|
|
520
|
+
}
|
|
521
|
+
})),
|
|
522
|
+
...repositoryMemoryGroupKeys.flatMap((group) => memory.groups[group].records.map((record) => ({
|
|
523
|
+
documentId: record.id,
|
|
524
|
+
evidence: {
|
|
525
|
+
kind: "repository-memory",
|
|
526
|
+
group,
|
|
527
|
+
record,
|
|
528
|
+
provenance: [{
|
|
529
|
+
targetDocumentId: record.id,
|
|
530
|
+
evidenceDocumentId: record.id,
|
|
531
|
+
sourcePath: record.path,
|
|
532
|
+
locator: { kind: "frontmatter-field", field: "repository_scopes" }
|
|
533
|
+
}]
|
|
534
|
+
}
|
|
535
|
+
})))
|
|
536
|
+
];
|
|
537
|
+
const hits = stableHits(candidates, limit);
|
|
538
|
+
const diagnostics = pathContextDiagnostics(inspection, memory);
|
|
539
|
+
return Object.freeze({
|
|
540
|
+
status: statusFromDiagnostics(diagnostics, hits),
|
|
541
|
+
hits,
|
|
542
|
+
diagnostics,
|
|
543
|
+
timings: Object.freeze({ inspectionMs, memoryMs }),
|
|
544
|
+
resources: Object.freeze({
|
|
545
|
+
noteCount: session.noteCount,
|
|
546
|
+
resultCount: hits.length,
|
|
547
|
+
matchingContextCount: inspection.matchingContexts.length,
|
|
548
|
+
inheritedGuideCount: inspection.inheritedGuides.length,
|
|
549
|
+
contextIssueCount: inspection.issues.length,
|
|
550
|
+
memoryMatchedCount: memory.counts.matched,
|
|
551
|
+
memoryReturnedCount: memory.counts.returned,
|
|
552
|
+
memoryInvalidCount: memory.counts.invalid,
|
|
553
|
+
memoryAdvisoryCount: memory.counts.advisories
|
|
554
|
+
})
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
function gitDiagnostic(lane, result) {
|
|
560
|
+
if (result.status === "unavailable") {
|
|
561
|
+
return Object.freeze({
|
|
562
|
+
lane,
|
|
563
|
+
status: "unavailable",
|
|
564
|
+
message: diagnosticMessage([result.reason]) ?? "Git retrieval is unavailable."
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
const limited = result.limitedCommits ?? [];
|
|
568
|
+
return Object.freeze({
|
|
569
|
+
lane,
|
|
570
|
+
status: limited.length === 0 ? "ready" : "degraded",
|
|
571
|
+
...limited.length === 0 ? {} : { message: `${limited.length} oversized Git commit record(s) have limited evidence.` }
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
function gitRetriever(session, frozenCommit, now) {
|
|
575
|
+
return Object.freeze({
|
|
576
|
+
id: "git",
|
|
577
|
+
retrieve: async ({ query, limit, signal }) => {
|
|
578
|
+
const input = query.inputs.history;
|
|
579
|
+
if (input === undefined) {
|
|
580
|
+
return unavailable("git", "query.inputs.history", session.noteCount);
|
|
581
|
+
}
|
|
582
|
+
throwIfAborted(signal);
|
|
583
|
+
const searchStartedAt = now();
|
|
584
|
+
const searched = await session.searchHistory({
|
|
585
|
+
query: input.query,
|
|
586
|
+
limit: Math.min(limit, 100)
|
|
587
|
+
});
|
|
588
|
+
const searchMs = elapsed(searchStartedAt, now);
|
|
589
|
+
throwIfAborted(signal);
|
|
590
|
+
const historyStartedAt = now();
|
|
591
|
+
const history = await session.history(input.noteIds);
|
|
592
|
+
const historyMs = elapsed(historyStartedAt, now);
|
|
593
|
+
throwIfAborted(signal);
|
|
594
|
+
for (const result of [searched, history]) {
|
|
595
|
+
if (result.status === "ready" && result.head !== frozenCommit) {
|
|
596
|
+
throw new FrozenEvaluationSnapshotError(`Git retrieval observed HEAD ${result.head}, expected frozen commit ${frozenCommit}.`);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
const searchedById = new Map(searched.status === "ready" ? searched.hits.map((hit) => [hit.id, hit]) : []);
|
|
600
|
+
const historyById = new Map(history.status === "ready" ? history.notes.map((note) => [note.id, note]) : []);
|
|
601
|
+
const orderedIds = [
|
|
602
|
+
...input.noteIds.filter((id) => historyById.has(id)),
|
|
603
|
+
...searched.status === "ready" ? searched.hits.map(({ id }) => id) : []
|
|
604
|
+
];
|
|
605
|
+
const candidates = orderedIds.map((documentId) => {
|
|
606
|
+
const searchedHit = searchedById.get(documentId);
|
|
607
|
+
const provenance = historyById.get(documentId);
|
|
608
|
+
return {
|
|
609
|
+
documentId,
|
|
610
|
+
...searchedHit === undefined ? {} : { score: searchedHit.score },
|
|
611
|
+
evidence: {
|
|
612
|
+
...provenance === undefined ? {} : { history: provenance },
|
|
613
|
+
...searchedHit === undefined ? {} : { search: searchedHit }
|
|
614
|
+
}
|
|
615
|
+
};
|
|
616
|
+
});
|
|
617
|
+
const hits = stableHits(candidates, limit);
|
|
618
|
+
const diagnostics = Object.freeze([
|
|
619
|
+
gitDiagnostic("git-search", searched),
|
|
620
|
+
gitDiagnostic("git-history", history)
|
|
621
|
+
]);
|
|
622
|
+
const searchedLimited = searched.status === "ready" ? searched.limitedCommits?.length ?? 0 : 0;
|
|
623
|
+
const historyLimited = history.status === "ready" ? history.limitedCommits?.length ?? 0 : 0;
|
|
624
|
+
return Object.freeze({
|
|
625
|
+
status: statusFromDiagnostics(diagnostics, hits),
|
|
626
|
+
hits,
|
|
627
|
+
diagnostics,
|
|
628
|
+
timings: Object.freeze({ searchHistoryMs: searchMs, historyMs }),
|
|
629
|
+
resources: Object.freeze({
|
|
630
|
+
noteCount: session.noteCount,
|
|
631
|
+
resultCount: hits.length,
|
|
632
|
+
searchResultCount: searched.status === "ready" ? searched.hits.length : 0,
|
|
633
|
+
historyResultCount: history.status === "ready" ? history.notes.length : 0,
|
|
634
|
+
limitedCommitCount: searchedLimited + historyLimited
|
|
635
|
+
})
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
function throwIfAborted(signal) {
|
|
641
|
+
if (!signal.aborted)
|
|
642
|
+
return;
|
|
643
|
+
if (signal.reason instanceof Error)
|
|
644
|
+
throw signal.reason;
|
|
645
|
+
throw new Error("Knowledge-base evaluation retrieval was aborted.");
|
|
646
|
+
}
|
|
647
|
+
function textRetriever(id, session) {
|
|
648
|
+
return Object.freeze({
|
|
649
|
+
id,
|
|
650
|
+
retrieve: async ({ query, limit, signal }) => {
|
|
651
|
+
const text = query.inputs.text;
|
|
652
|
+
if (text === undefined)
|
|
653
|
+
return unavailable(id, "query.inputs.text", session.noteCount);
|
|
654
|
+
throwIfAborted(signal);
|
|
655
|
+
const result = await session.search({
|
|
656
|
+
query: text,
|
|
657
|
+
mode: id,
|
|
658
|
+
limit: Math.min(limit, MAX_SEARCH_RESULTS),
|
|
659
|
+
graph: false,
|
|
660
|
+
history: false
|
|
661
|
+
});
|
|
662
|
+
throwIfAborted(signal);
|
|
663
|
+
return textResult(result);
|
|
664
|
+
}
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
function knowledgeBaseDependencies(options, snapshot) {
|
|
668
|
+
const git = options.git === undefined && options.runGit === undefined ? undefined : {
|
|
669
|
+
...options.git,
|
|
670
|
+
...options.git?.runGit !== undefined || options.runGit === undefined ? {} : { runGit: options.runGit }
|
|
671
|
+
};
|
|
672
|
+
return {
|
|
673
|
+
scanVault: () => Promise.resolve(snapshot),
|
|
674
|
+
...options.semantic === undefined ? {} : { semantic: options.semantic },
|
|
675
|
+
...options.openSemanticSearchSession === undefined ? {} : { openSemanticSearchSession: options.openSemanticSearchSession },
|
|
676
|
+
...git === undefined ? {} : { git },
|
|
677
|
+
...options.indexGitHistory === undefined ? {} : { indexGitHistory: options.indexGitHistory }
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
async function openKnowledgeBaseEvaluation(options) {
|
|
681
|
+
const verified = await verifyFrozenEvaluationSnapshot(options);
|
|
682
|
+
const scanner = options.scanVault ?? scanVault;
|
|
683
|
+
const snapshot = await scanner(verified.root, { mentionScope: false });
|
|
684
|
+
const open = options.openKnowledgeBase ?? openKnowledgeBase;
|
|
685
|
+
const session = await open({
|
|
686
|
+
root: verified.root,
|
|
687
|
+
repository: verified.repository,
|
|
688
|
+
...options.database === undefined ? {} : { database: options.database },
|
|
689
|
+
...options.embeddingModelFile === undefined ? {} : { embeddingModelFile: options.embeddingModelFile },
|
|
690
|
+
...options.embeddingModelLease === undefined ? {} : { embeddingModelLease: options.embeddingModelLease },
|
|
691
|
+
...options.requireStoreLocalVectorBoundary === undefined ? {} : {
|
|
692
|
+
requireStoreLocalVectorBoundary: options.requireStoreLocalVectorBoundary
|
|
693
|
+
}
|
|
694
|
+
}, knowledgeBaseDependencies(options, snapshot));
|
|
695
|
+
const now = options.now ?? performance.now.bind(performance);
|
|
696
|
+
const inspectContext = options.inspectAgentContextRepository ?? inspectAgentContextRepository;
|
|
697
|
+
const buildMemory = options.buildRepositoryMemoryContext ?? buildRepositoryMemoryContext;
|
|
698
|
+
const retrievers = Object.freeze([
|
|
699
|
+
textRetriever("exact", session),
|
|
700
|
+
textRetriever("keyword", session),
|
|
701
|
+
textRetriever("semantic", session),
|
|
702
|
+
textRetriever("hybrid", session),
|
|
703
|
+
metadataRetriever(session, now),
|
|
704
|
+
graphRetriever(session, now),
|
|
705
|
+
pathContextRetriever(session, snapshot, verified.repository, inspectContext, buildMemory, now),
|
|
706
|
+
gitRetriever(session, verified.repositoryCommit, now)
|
|
707
|
+
]);
|
|
708
|
+
return Object.freeze({ retrievers, close: session.close });
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
export { knowledgeBaseEvaluationRetrieverIds, FrozenEvaluationSnapshotError, verifyFrozenEvaluationSnapshot, openKnowledgeBaseEvaluation };
|