@autorag/librarian 2.9.0 → 2.10.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/README.md +57 -2
- package/dist/agent/agent.d.ts +27 -21
- package/dist/agent/answer-citations.d.ts +22 -0
- package/dist/agent/answer-guidelines.d.ts +9 -9
- package/dist/agent/citations.d.ts +35 -23
- package/dist/agent/evidence-ledger.d.ts +7 -12
- package/dist/agent/index.d.ts +2 -2
- package/dist/agent/{emit-results-tool.d.ts → results.d.ts} +5 -40
- package/dist/agent/search-documents.d.ts +14 -19
- package/dist/agent/self-config.d.ts +1 -1
- package/dist/cli/commands/report.d.ts +1 -1
- package/dist/cli/commands/tui.d.ts +3 -2
- package/dist/cli/index.js +1466 -984
- package/dist/cloud/authorize.d.ts +12 -0
- package/dist/cloud/callback-server.d.ts +33 -0
- package/dist/cloud/callback.d.ts +23 -0
- package/dist/cloud/config.d.ts +23 -0
- package/dist/cloud/errors.d.ts +46 -0
- package/dist/cloud/index.d.ts +12 -0
- package/dist/cloud/models.d.ts +32 -0
- package/dist/cloud/oauth-login.d.ts +22 -0
- package/dist/cloud/pkce.d.ts +20 -0
- package/dist/cloud/provider.d.ts +40 -0
- package/dist/cloud/token.d.ts +22 -0
- package/dist/core.d.ts +2 -5
- package/dist/core.js +1341 -918
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1463 -928
- package/dist/mcp/index.js +1404 -925
- package/dist/minsync/client.d.ts +1 -1
- package/dist/minsync/installer.d.ts +1 -1
- package/dist/observability/run-log.d.ts +1 -1
- package/dist/retrieval/index.d.ts +1 -1
- package/dist/retrieval/types.d.ts +0 -23
- package/package.json +1 -1
- package/skills/autorag-lite-setup/SKILL.md +1 -1
- package/skills/autorag-setup/SKILL.md +2 -2
- package/dist/agent/fast-answer-tool.d.ts +0 -56
package/dist/mcp/index.js
CHANGED
|
@@ -5607,7 +5607,7 @@ function isGitHubAsset(value) {
|
|
|
5607
5607
|
function isRecord5(value) {
|
|
5608
5608
|
return typeof value === "object" && value !== null;
|
|
5609
5609
|
}
|
|
5610
|
-
var LATEST_RELEASE_URL = "https://api.github.com/repos/NomaDamas/MinSync/releases/latest", SHA256_HEX_PATTERN, MINSYNC_VERSION = "0.4.
|
|
5610
|
+
var LATEST_RELEASE_URL = "https://api.github.com/repos/NomaDamas/MinSync/releases/latest", SHA256_HEX_PATTERN, MINSYNC_VERSION = "0.4.6", MINSYNC_CARGO_INSTALL_TIMEOUT_MS, CARGO_PROBE_TIMEOUT_MS = 5000, MinSyncReleaseError;
|
|
5611
5611
|
var init_installer2 = __esm(() => {
|
|
5612
5612
|
init_process();
|
|
5613
5613
|
SHA256_HEX_PATTERN = /^[a-f0-9]{64}$/;
|
|
@@ -8041,8 +8041,398 @@ var init_model_auth = __esm(() => {
|
|
|
8041
8041
|
};
|
|
8042
8042
|
});
|
|
8043
8043
|
|
|
8044
|
+
// src/agent/citations.ts
|
|
8045
|
+
function isAsciiDigit(code) {
|
|
8046
|
+
return code >= 48 && code <= 57;
|
|
8047
|
+
}
|
|
8048
|
+
function digitsEndAt(text, from) {
|
|
8049
|
+
let end = from;
|
|
8050
|
+
while (end < text.length && isAsciiDigit(text.charCodeAt(end)))
|
|
8051
|
+
end += 1;
|
|
8052
|
+
return end;
|
|
8053
|
+
}
|
|
8054
|
+
function continuesAsProse(answer, from) {
|
|
8055
|
+
if (answer[from] !== " " && answer[from] !== " ")
|
|
8056
|
+
return false;
|
|
8057
|
+
const next = answer.codePointAt(from + 1);
|
|
8058
|
+
return next !== undefined && /[\p{L}\p{N}]/u.test(String.fromCodePoint(next));
|
|
8059
|
+
}
|
|
8060
|
+
function evidenceMarkerAt(answer, index) {
|
|
8061
|
+
const ids = [];
|
|
8062
|
+
let cursor = index + 1;
|
|
8063
|
+
for (;; ) {
|
|
8064
|
+
if (answer[cursor] !== "e")
|
|
8065
|
+
return;
|
|
8066
|
+
const digitsEnd = digitsEndAt(answer, cursor + 1);
|
|
8067
|
+
if (digitsEnd === cursor + 1)
|
|
8068
|
+
return;
|
|
8069
|
+
ids.push(answer.slice(cursor, digitsEnd));
|
|
8070
|
+
cursor = digitsEnd;
|
|
8071
|
+
if (answer[cursor] === "]")
|
|
8072
|
+
return { ids, end: cursor + 1 };
|
|
8073
|
+
if (answer[cursor] !== ",")
|
|
8074
|
+
return;
|
|
8075
|
+
cursor += 1;
|
|
8076
|
+
while (answer[cursor] === " " || answer[cursor] === "\t")
|
|
8077
|
+
cursor += 1;
|
|
8078
|
+
}
|
|
8079
|
+
}
|
|
8080
|
+
function filePathFrom(raw) {
|
|
8081
|
+
const trimmed = raw.trim();
|
|
8082
|
+
return trimmed.startsWith("<") && trimmed.endsWith(">") ? trimmed.slice(1, -1).trim() : trimmed;
|
|
8083
|
+
}
|
|
8084
|
+
function fileMarkerAt(answer, index, isFile) {
|
|
8085
|
+
if (!answer.startsWith(FILE_MARKER_PREFIX, index))
|
|
8086
|
+
return;
|
|
8087
|
+
const bodyStart = index + FILE_MARKER_PREFIX.length;
|
|
8088
|
+
let closer = answer.indexOf("]", bodyStart);
|
|
8089
|
+
for (let attempt = 0;closer !== -1 && attempt < MAX_FILE_MARKER_CLOSERS; attempt++) {
|
|
8090
|
+
const path = filePathFrom(answer.slice(bodyStart, closer));
|
|
8091
|
+
if (path.length > 0 && isFile(path))
|
|
8092
|
+
return { path, end: closer + 1 };
|
|
8093
|
+
closer = answer.indexOf("]", closer + 1);
|
|
8094
|
+
}
|
|
8095
|
+
return;
|
|
8096
|
+
}
|
|
8097
|
+
function answerMarkers(answer, isFile = () => false) {
|
|
8098
|
+
const markers = [];
|
|
8099
|
+
let floor = 0;
|
|
8100
|
+
let closeIndex = -1;
|
|
8101
|
+
let index = 0;
|
|
8102
|
+
const leadingStart = (from) => {
|
|
8103
|
+
let start = from;
|
|
8104
|
+
while (start > floor && (answer[start - 1] === " " || answer[start - 1] === "\t"))
|
|
8105
|
+
start -= 1;
|
|
8106
|
+
return start;
|
|
8107
|
+
};
|
|
8108
|
+
while (index < answer.length) {
|
|
8109
|
+
const char = answer[index];
|
|
8110
|
+
if (char === "(" && answer[index + 1] === "<") {
|
|
8111
|
+
if (closeIndex < index + 2) {
|
|
8112
|
+
const found = answer.indexOf(">", index + 2);
|
|
8113
|
+
closeIndex = found === -1 ? answer.length : found;
|
|
8114
|
+
}
|
|
8115
|
+
if (answer[closeIndex + 1] === ")") {
|
|
8116
|
+
index = closeIndex + 2;
|
|
8117
|
+
floor = index;
|
|
8118
|
+
continue;
|
|
8119
|
+
}
|
|
8120
|
+
index += 1;
|
|
8121
|
+
continue;
|
|
8122
|
+
}
|
|
8123
|
+
if (char === "[") {
|
|
8124
|
+
const digitsEnd = digitsEndAt(answer, index + 1);
|
|
8125
|
+
if (digitsEnd > index + 1 && answer[digitsEnd] === "]" && answer[digitsEnd + 1] !== "(" && !continuesAsProse(answer, digitsEnd + 1)) {
|
|
8126
|
+
markers.push({
|
|
8127
|
+
kind: "number",
|
|
8128
|
+
start: leadingStart(index),
|
|
8129
|
+
end: digitsEnd + 1,
|
|
8130
|
+
number: Number(answer.slice(index + 1, digitsEnd))
|
|
8131
|
+
});
|
|
8132
|
+
index = digitsEnd + 1;
|
|
8133
|
+
floor = index;
|
|
8134
|
+
continue;
|
|
8135
|
+
}
|
|
8136
|
+
const evidence = evidenceMarkerAt(answer, index);
|
|
8137
|
+
if (evidence !== undefined && answer[evidence.end] !== "(") {
|
|
8138
|
+
markers.push({ kind: "evidence", start: leadingStart(index), end: evidence.end, ids: evidence.ids });
|
|
8139
|
+
index = evidence.end;
|
|
8140
|
+
floor = index;
|
|
8141
|
+
continue;
|
|
8142
|
+
}
|
|
8143
|
+
const file = fileMarkerAt(answer, index, isFile);
|
|
8144
|
+
if (file !== undefined && answer[file.end] !== "(") {
|
|
8145
|
+
markers.push({ kind: "file", start: leadingStart(index), end: file.end, path: file.path });
|
|
8146
|
+
index = file.end;
|
|
8147
|
+
floor = index;
|
|
8148
|
+
continue;
|
|
8149
|
+
}
|
|
8150
|
+
}
|
|
8151
|
+
index += 1;
|
|
8152
|
+
}
|
|
8153
|
+
return markers;
|
|
8154
|
+
}
|
|
8155
|
+
function stripUnresolvedCitations(answer, results) {
|
|
8156
|
+
const known = new Set(results.map((result) => result.number));
|
|
8157
|
+
const unresolved = new Set;
|
|
8158
|
+
let stripped = "";
|
|
8159
|
+
let cursor = 0;
|
|
8160
|
+
for (const marker of answerMarkers(answer)) {
|
|
8161
|
+
if (marker.kind !== "number" || known.has(marker.number))
|
|
8162
|
+
continue;
|
|
8163
|
+
unresolved.add(marker.number);
|
|
8164
|
+
stripped += answer.slice(cursor, marker.start);
|
|
8165
|
+
cursor = marker.end;
|
|
8166
|
+
}
|
|
8167
|
+
if (unresolved.size === 0)
|
|
8168
|
+
return { answer, unresolved: [] };
|
|
8169
|
+
return { answer: stripped + answer.slice(cursor), unresolved: [...unresolved].sort((a, b) => a - b) };
|
|
8170
|
+
}
|
|
8171
|
+
function formatCitationList(numbers) {
|
|
8172
|
+
return numbers.length === 0 ? "none" : numbers.map((number) => `[${number}]`).join(", ");
|
|
8173
|
+
}
|
|
8174
|
+
function duplicateNumbers(sortedNumbers) {
|
|
8175
|
+
const duplicates = [];
|
|
8176
|
+
for (let index = 1;index < sortedNumbers.length; index++) {
|
|
8177
|
+
const number = sortedNumbers[index];
|
|
8178
|
+
if (number === sortedNumbers[index - 1] && duplicates[duplicates.length - 1] !== number)
|
|
8179
|
+
duplicates.push(number);
|
|
8180
|
+
}
|
|
8181
|
+
return duplicates;
|
|
8182
|
+
}
|
|
8183
|
+
function assertResultsMappingOneToOne(label, results, mapping) {
|
|
8184
|
+
const resultNumbers = results.map((result) => result.number).sort((a, b) => a - b);
|
|
8185
|
+
const mappingNumbers = mapping.map((entry) => entry.number).sort((a, b) => a - b);
|
|
8186
|
+
const resultDuplicates = duplicateNumbers(resultNumbers);
|
|
8187
|
+
const mappingDuplicates = duplicateNumbers(mappingNumbers);
|
|
8188
|
+
const sameNumbers = resultNumbers.length === mappingNumbers.length && resultNumbers.every((number, index) => number === mappingNumbers[index]);
|
|
8189
|
+
if (sameNumbers && resultDuplicates.length === 0 && mappingDuplicates.length === 0)
|
|
8190
|
+
return;
|
|
8191
|
+
const duplicateNotes = [
|
|
8192
|
+
resultDuplicates.length > 0 ? `results repeat ${formatCitationList(resultDuplicates)}` : undefined,
|
|
8193
|
+
mappingDuplicates.length > 0 ? `mapping repeats ${formatCitationList(mappingDuplicates)}` : undefined
|
|
8194
|
+
].filter((note) => note !== undefined);
|
|
8195
|
+
throw new Error(`${label}: result numbers and mapping numbers must be one-to-one, but results contain ${formatCitationList(resultNumbers)} ` + `and mapping contains ${formatCitationList(mappingNumbers)}` + (duplicateNotes.length > 0 ? ` (${duplicateNotes.join("; ")})` : "") + ". Give every result a unique number with exactly one mapping entry carrying the same number and no mapping entry without a result.");
|
|
8196
|
+
}
|
|
8197
|
+
var MAX_FILE_MARKER_CLOSERS = 8, FILE_MARKER_PREFIX = "[file:";
|
|
8198
|
+
|
|
8199
|
+
// src/agent/evidence-ledger.ts
|
|
8200
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
8201
|
+
import { closeSync as closeSync2, openSync as openSync2, readSync, statSync } from "node:fs";
|
|
8202
|
+
import { isAbsolute as isAbsolute6 } from "node:path";
|
|
8203
|
+
function metadataString(metadata, key) {
|
|
8204
|
+
const value = metadata[key];
|
|
8205
|
+
return typeof value === "string" && value.trim().length > 0 ? value : undefined;
|
|
8206
|
+
}
|
|
8207
|
+
function metadataNumber(metadata, key) {
|
|
8208
|
+
const value = metadata[key];
|
|
8209
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
8210
|
+
}
|
|
8211
|
+
function isRegularFile2(path) {
|
|
8212
|
+
try {
|
|
8213
|
+
return statSync(path).isFile();
|
|
8214
|
+
} catch {
|
|
8215
|
+
return false;
|
|
8216
|
+
}
|
|
8217
|
+
}
|
|
8218
|
+
function readFileExcerpt(path) {
|
|
8219
|
+
let descriptor;
|
|
8220
|
+
try {
|
|
8221
|
+
descriptor = openSync2(path, "r");
|
|
8222
|
+
const buffer = Buffer.alloc(MAX_CONTENT_CHARS * 4);
|
|
8223
|
+
const bytes = readSync(descriptor, buffer, 0, buffer.length, 0);
|
|
8224
|
+
const head = buffer.subarray(0, bytes);
|
|
8225
|
+
return head.includes(0) ? path : head.toString("utf8").slice(0, MAX_CONTENT_CHARS);
|
|
8226
|
+
} catch {
|
|
8227
|
+
return path;
|
|
8228
|
+
} finally {
|
|
8229
|
+
if (descriptor !== undefined)
|
|
8230
|
+
closeSync2(descriptor);
|
|
8231
|
+
}
|
|
8232
|
+
}
|
|
8233
|
+
function toEvidenceRef(entry) {
|
|
8234
|
+
return {
|
|
8235
|
+
method: entry.method,
|
|
8236
|
+
source: entry.source,
|
|
8237
|
+
content: entry.content,
|
|
8238
|
+
retrieverMix: [...entry.retrieverMix],
|
|
8239
|
+
...entry.retrievalResultId !== undefined ? { retrievalResultId: entry.retrievalResultId } : {},
|
|
8240
|
+
...entry.chunkIndex !== undefined ? { chunkIndex: entry.chunkIndex } : {},
|
|
8241
|
+
...entry.lineNumber !== undefined ? { lineNumber: entry.lineNumber } : {},
|
|
8242
|
+
...entry.parserType !== undefined ? { parserType: entry.parserType } : {},
|
|
8243
|
+
...entry.documentType !== undefined ? { documentType: entry.documentType } : {},
|
|
8244
|
+
...entry.documentArea !== undefined ? { documentArea: entry.documentArea } : {},
|
|
8245
|
+
...entry.evidenceType !== undefined ? { evidenceType: entry.evidenceType } : {},
|
|
8246
|
+
...entry.evidenceLocation !== undefined ? { evidenceLocation: entry.evidenceLocation } : {}
|
|
8247
|
+
};
|
|
8248
|
+
}
|
|
8249
|
+
|
|
8250
|
+
class EvidenceLedger {
|
|
8251
|
+
entries = [];
|
|
8252
|
+
byKey = new Map;
|
|
8253
|
+
byId = new Map;
|
|
8254
|
+
lastOrdinal = 0;
|
|
8255
|
+
register(input) {
|
|
8256
|
+
const content = input.content.slice(0, MAX_CONTENT_CHARS);
|
|
8257
|
+
const digest = createHash10("sha256").update(input.content.replace(/\s+/gu, " ").trim()).digest("hex");
|
|
8258
|
+
const key = `${input.source}\x00${digest}`;
|
|
8259
|
+
const existing = this.byKey.get(key);
|
|
8260
|
+
if (existing !== undefined) {
|
|
8261
|
+
if (!existing.retrieverMix.includes(input.method))
|
|
8262
|
+
existing.retrieverMix.push(input.method);
|
|
8263
|
+
return existing.id;
|
|
8264
|
+
}
|
|
8265
|
+
const entry = {
|
|
8266
|
+
...input,
|
|
8267
|
+
content,
|
|
8268
|
+
id: `e${++this.lastOrdinal}`,
|
|
8269
|
+
retrieverMix: [input.method]
|
|
8270
|
+
};
|
|
8271
|
+
this.entries.push(entry);
|
|
8272
|
+
this.byKey.set(key, entry);
|
|
8273
|
+
this.byId.set(entry.id, entry);
|
|
8274
|
+
return entry.id;
|
|
8275
|
+
}
|
|
8276
|
+
registerResult(tool, result) {
|
|
8277
|
+
const metadata = result.metadata;
|
|
8278
|
+
const chunkIndex = metadataNumber(metadata, "chunkIndex");
|
|
8279
|
+
const lineNumber = metadataNumber(metadata, "lineNumber");
|
|
8280
|
+
const parserType = metadataString(metadata, "parserType");
|
|
8281
|
+
const documentType = metadataString(metadata, "documentType");
|
|
8282
|
+
const documentArea = metadataString(metadata, "documentArea");
|
|
8283
|
+
const evidenceType = metadataString(metadata, "evidenceType");
|
|
8284
|
+
const evidenceLocation = metadataString(metadata, "evidenceLocation");
|
|
8285
|
+
return this.register({
|
|
8286
|
+
method: metadataString(metadata, "method") ?? tool,
|
|
8287
|
+
source: result.source,
|
|
8288
|
+
content: result.content,
|
|
8289
|
+
retrievalResultId: result.id,
|
|
8290
|
+
...chunkIndex !== undefined ? { chunkIndex } : {},
|
|
8291
|
+
...lineNumber !== undefined ? { lineNumber } : {},
|
|
8292
|
+
...parserType !== undefined ? { parserType } : {},
|
|
8293
|
+
...documentType !== undefined ? { documentType } : {},
|
|
8294
|
+
...documentArea !== undefined ? { documentArea } : {},
|
|
8295
|
+
...evidenceType !== undefined ? { evidenceType } : {},
|
|
8296
|
+
...evidenceLocation !== undefined ? { evidenceLocation } : {}
|
|
8297
|
+
});
|
|
8298
|
+
}
|
|
8299
|
+
lookup(raw, options) {
|
|
8300
|
+
const trimmed = raw.trim();
|
|
8301
|
+
const ref = trimmed.startsWith("[") && trimmed.endsWith("]") ? trimmed.slice(1, -1).trim() : trimmed;
|
|
8302
|
+
const byId = this.byId.get(ref);
|
|
8303
|
+
if (byId !== undefined)
|
|
8304
|
+
return [toEvidenceRef(byId)];
|
|
8305
|
+
const bySource = this.entries.filter((entry) => entry.source === ref);
|
|
8306
|
+
if (bySource.length > 0)
|
|
8307
|
+
return bySource.map(toEvidenceRef);
|
|
8308
|
+
if (options.allowLocalFiles && isAbsolute6(ref) && isRegularFile2(ref)) {
|
|
8309
|
+
return [{ method: "bash", source: ref, content: readFileExcerpt(ref) }];
|
|
8310
|
+
}
|
|
8311
|
+
return [];
|
|
8312
|
+
}
|
|
8313
|
+
clear() {
|
|
8314
|
+
this.entries = [];
|
|
8315
|
+
this.byKey.clear();
|
|
8316
|
+
this.byId.clear();
|
|
8317
|
+
}
|
|
8318
|
+
}
|
|
8319
|
+
var MAX_CONTENT_CHARS = 2000;
|
|
8320
|
+
var init_evidence_ledger = () => {};
|
|
8321
|
+
|
|
8322
|
+
// src/agent/answer-citations.ts
|
|
8323
|
+
import { isAbsolute as isAbsolute7 } from "node:path";
|
|
8324
|
+
function claimBefore(text, end) {
|
|
8325
|
+
const window = text.slice(Math.max(0, end - CLAIM_LOOKBACK_CHARS), end);
|
|
8326
|
+
const lineStart = window.lastIndexOf(`
|
|
8327
|
+
`) + 1;
|
|
8328
|
+
const line = window.slice(lineStart).replace(EVIDENCE_MARKER_TEXT, "");
|
|
8329
|
+
let start = 0;
|
|
8330
|
+
for (let index = line.length - 2;index >= 0; index--) {
|
|
8331
|
+
if (SENTENCE_END.test(line.charAt(index)) && /\s/u.test(line.charAt(index + 1))) {
|
|
8332
|
+
start = index + 2;
|
|
8333
|
+
break;
|
|
8334
|
+
}
|
|
8335
|
+
}
|
|
8336
|
+
const claim = line.slice(start).replace(LEADING_LIST_MARK, "").replace(/\s+/gu, " ").trim();
|
|
8337
|
+
return claim.length > MAX_CLAIM_CHARS ? `${claim.slice(0, MAX_CLAIM_CHARS)}…` : claim;
|
|
8338
|
+
}
|
|
8339
|
+
function deriveResultsFromAnswer(text, ledger, options) {
|
|
8340
|
+
const isFile = (path) => options.allowLocalFiles && isAbsolute7(path) && isRegularFile2(path);
|
|
8341
|
+
const sources = new Map;
|
|
8342
|
+
const dropped = new Set;
|
|
8343
|
+
let answer = "";
|
|
8344
|
+
let cursor = 0;
|
|
8345
|
+
let lastEmitted;
|
|
8346
|
+
const cite = (reference, claimEnd) => {
|
|
8347
|
+
const refs = ledger.lookup(reference, options);
|
|
8348
|
+
const [primary] = refs;
|
|
8349
|
+
if (primary === undefined) {
|
|
8350
|
+
dropped.add(reference);
|
|
8351
|
+
return;
|
|
8352
|
+
}
|
|
8353
|
+
let cited = sources.get(primary.source);
|
|
8354
|
+
if (cited === undefined) {
|
|
8355
|
+
cited = { number: sources.size + 1, refs: [], chunkKeys: new Set, claim: claimBefore(text, claimEnd) };
|
|
8356
|
+
sources.set(primary.source, cited);
|
|
8357
|
+
}
|
|
8358
|
+
for (const ref of refs) {
|
|
8359
|
+
const chunkKey = `${ref.source}\x00${ref.content ?? ""}`;
|
|
8360
|
+
if (cited.chunkKeys.has(chunkKey))
|
|
8361
|
+
continue;
|
|
8362
|
+
cited.chunkKeys.add(chunkKey);
|
|
8363
|
+
cited.refs.push(ref);
|
|
8364
|
+
}
|
|
8365
|
+
return cited.number;
|
|
8366
|
+
};
|
|
8367
|
+
for (const marker of answerMarkers(text, isFile)) {
|
|
8368
|
+
answer += text.slice(cursor, marker.start);
|
|
8369
|
+
cursor = marker.end;
|
|
8370
|
+
if (marker.kind === "number") {
|
|
8371
|
+
dropped.add(`[${marker.number}]`);
|
|
8372
|
+
continue;
|
|
8373
|
+
}
|
|
8374
|
+
const references = marker.kind === "evidence" ? marker.ids : [`file:${marker.path}`];
|
|
8375
|
+
const numbers = [];
|
|
8376
|
+
for (const reference of references) {
|
|
8377
|
+
const number = cite(marker.kind === "file" ? marker.path : reference, marker.start);
|
|
8378
|
+
if (number !== undefined && !numbers.includes(number))
|
|
8379
|
+
numbers.push(number);
|
|
8380
|
+
}
|
|
8381
|
+
if (numbers.length === 0)
|
|
8382
|
+
continue;
|
|
8383
|
+
const adjacent = lastEmitted !== undefined && text.slice(lastEmitted.end, marker.start).trim() === "";
|
|
8384
|
+
const fresh = numbers.filter((number) => !(adjacent && lastEmitted?.number === number));
|
|
8385
|
+
lastEmitted = { number: numbers[numbers.length - 1], end: marker.end };
|
|
8386
|
+
if (fresh.length === 0)
|
|
8387
|
+
continue;
|
|
8388
|
+
const leading = LEADING_BLANK.exec(text.slice(marker.start, marker.end))?.[0] ?? "";
|
|
8389
|
+
answer += leading + fresh.map((number) => `[${number}]`).join("");
|
|
8390
|
+
}
|
|
8391
|
+
answer += text.slice(cursor);
|
|
8392
|
+
const results = [];
|
|
8393
|
+
const mapping = [];
|
|
8394
|
+
for (const [source, cited] of sources) {
|
|
8395
|
+
const [primary] = cited.refs;
|
|
8396
|
+
if (primary === undefined)
|
|
8397
|
+
continue;
|
|
8398
|
+
results.push({
|
|
8399
|
+
number: cited.number,
|
|
8400
|
+
title: source.split(/[\\/]/u).filter((part) => part.length > 0).pop() ?? source,
|
|
8401
|
+
summary: cited.claim,
|
|
8402
|
+
evidence: cited.refs.map((ref) => {
|
|
8403
|
+
const excerpt = (ref.content ?? "").replace(/\s+/gu, " ").trim().slice(0, MAX_EXCERPT_CHARS);
|
|
8404
|
+
return ref.lineNumber !== undefined ? { excerpt, lineNumber: ref.lineNumber } : { excerpt };
|
|
8405
|
+
})
|
|
8406
|
+
});
|
|
8407
|
+
mapping.push({
|
|
8408
|
+
number: cited.number,
|
|
8409
|
+
source,
|
|
8410
|
+
method: primary.method,
|
|
8411
|
+
content: primary.content ?? "",
|
|
8412
|
+
evidenceRefs: cited.refs
|
|
8413
|
+
});
|
|
8414
|
+
}
|
|
8415
|
+
const diagnostics = dropped.size === 0 ? [] : [
|
|
8416
|
+
{
|
|
8417
|
+
code: "citation-without-result",
|
|
8418
|
+
severity: "warning",
|
|
8419
|
+
message: `Dropped ${dropped.size} answer citation(s) that matched no evidence retrieved in this run: ${[...dropped].join(", ")}. Every remaining citation resolves to a recorded source.`,
|
|
8420
|
+
source: "agent"
|
|
8421
|
+
}
|
|
8422
|
+
];
|
|
8423
|
+
return { details: { answer: answer.trim(), results, mapping, warnings: [] }, diagnostics };
|
|
8424
|
+
}
|
|
8425
|
+
var MAX_EXCERPT_CHARS = 400, MAX_CLAIM_CHARS = 280, CLAIM_LOOKBACK_CHARS = 600, SENTENCE_END, LEADING_LIST_MARK, EVIDENCE_MARKER_TEXT, LEADING_BLANK;
|
|
8426
|
+
var init_answer_citations = __esm(() => {
|
|
8427
|
+
init_evidence_ledger();
|
|
8428
|
+
SENTENCE_END = /[.!?。!?]/u;
|
|
8429
|
+
LEADING_LIST_MARK = /^[\s\-*•>]+/u;
|
|
8430
|
+
EVIDENCE_MARKER_TEXT = /\[(?:e\d+(?:,\s*)?)+\]|\[file:[^\]]*\]/gu;
|
|
8431
|
+
LEADING_BLANK = /^[ \t]*/u;
|
|
8432
|
+
});
|
|
8433
|
+
|
|
8044
8434
|
// src/agent/answer-guidelines.ts
|
|
8045
|
-
var ANSWER_IMAGE_EMBED_RULE = "**Images**: when a retrieved result is itself an image file (png, jpg, jpeg, gif, webp, svg, bmp, avif, heic, tiff) and showing it answers the question, embed it in
|
|
8435
|
+
var ANSWER_IMAGE_EMBED_RULE = "**Images**: when a retrieved result is itself an image file (png, jpg, jpeg, gif, webp, svg, bmp, avif, heic, tiff) and showing it answers the question, embed it in the answer as a markdown image on its own line: ``, followed by its citation, e.g. ` [e2]`. Use only the real source path of retrieved evidence. Never invent a path, use relative paths, or embed remote URLs. Apart from these image embeds, the no-file-paths rule stands.", ANSWER_IMAGE_DELTA_RULE = "An image already embedded in the first answer must not be embedded again.", ANSWER_CITATION_RULE = "**Citations**: cite supporting evidence inline with the evidence id shown next to each retrieved result, in square brackets (e.g. [e3], or [e3][e7] for two). Copy ids exactly; never invent one. For a local file you opened yourself with `bash`, cite `[file:<absolute path>]`. Cite the evidence that backs a sentence at the end of that sentence. Do not cite numbers, paths, or anything else.";
|
|
8046
8436
|
|
|
8047
8437
|
// src/agent/datasource-skill.ts
|
|
8048
8438
|
import { Type as Type2 } from "typebox";
|
|
@@ -8243,230 +8633,8 @@ var init_dupey_tool = __esm(() => {
|
|
|
8243
8633
|
scanDuplicateDocumentsSchema = Type3.Object({});
|
|
8244
8634
|
});
|
|
8245
8635
|
|
|
8246
|
-
// src/agent/citations.ts
|
|
8247
|
-
function isAsciiDigit(code) {
|
|
8248
|
-
return code >= 48 && code <= 57;
|
|
8249
|
-
}
|
|
8250
|
-
function citationMarkers(answer) {
|
|
8251
|
-
const markers = [];
|
|
8252
|
-
let floor = 0;
|
|
8253
|
-
let closeIndex = -1;
|
|
8254
|
-
let index = 0;
|
|
8255
|
-
while (index < answer.length) {
|
|
8256
|
-
const char = answer[index];
|
|
8257
|
-
if (char === "(" && answer[index + 1] === "<") {
|
|
8258
|
-
if (closeIndex < index + 2) {
|
|
8259
|
-
const found = answer.indexOf(">", index + 2);
|
|
8260
|
-
closeIndex = found === -1 ? answer.length : found;
|
|
8261
|
-
}
|
|
8262
|
-
if (answer[closeIndex + 1] === ")") {
|
|
8263
|
-
index = closeIndex + 2;
|
|
8264
|
-
floor = index;
|
|
8265
|
-
continue;
|
|
8266
|
-
}
|
|
8267
|
-
index += 1;
|
|
8268
|
-
continue;
|
|
8269
|
-
}
|
|
8270
|
-
if (char === "[") {
|
|
8271
|
-
let digitsEnd = index + 1;
|
|
8272
|
-
while (digitsEnd < answer.length && isAsciiDigit(answer.charCodeAt(digitsEnd)))
|
|
8273
|
-
digitsEnd += 1;
|
|
8274
|
-
if (digitsEnd > index + 1 && answer[digitsEnd] === "]" && answer[digitsEnd + 1] !== "(") {
|
|
8275
|
-
let start = index;
|
|
8276
|
-
while (start > floor && (answer[start - 1] === " " || answer[start - 1] === "\t"))
|
|
8277
|
-
start -= 1;
|
|
8278
|
-
markers.push({ start, end: digitsEnd + 1, number: Number(answer.slice(index + 1, digitsEnd)) });
|
|
8279
|
-
index = digitsEnd + 1;
|
|
8280
|
-
floor = index;
|
|
8281
|
-
continue;
|
|
8282
|
-
}
|
|
8283
|
-
}
|
|
8284
|
-
index += 1;
|
|
8285
|
-
}
|
|
8286
|
-
return markers;
|
|
8287
|
-
}
|
|
8288
|
-
function unresolvedCitations(answer, results) {
|
|
8289
|
-
const known = new Set(results.map((result) => result.number));
|
|
8290
|
-
const unresolved = new Set;
|
|
8291
|
-
for (const marker of citationMarkers(answer)) {
|
|
8292
|
-
if (!known.has(marker.number))
|
|
8293
|
-
unresolved.add(marker.number);
|
|
8294
|
-
}
|
|
8295
|
-
return [...unresolved].sort((a, b) => a - b);
|
|
8296
|
-
}
|
|
8297
|
-
function stripUnresolvedCitations(answer, results) {
|
|
8298
|
-
const known = new Set(results.map((result) => result.number));
|
|
8299
|
-
const unresolved = new Set;
|
|
8300
|
-
let stripped = "";
|
|
8301
|
-
let cursor = 0;
|
|
8302
|
-
for (const marker of citationMarkers(answer)) {
|
|
8303
|
-
if (known.has(marker.number))
|
|
8304
|
-
continue;
|
|
8305
|
-
unresolved.add(marker.number);
|
|
8306
|
-
stripped += answer.slice(cursor, marker.start);
|
|
8307
|
-
cursor = marker.end;
|
|
8308
|
-
}
|
|
8309
|
-
if (unresolved.size === 0)
|
|
8310
|
-
return { answer, unresolved: [] };
|
|
8311
|
-
return { answer: stripped + answer.slice(cursor), unresolved: [...unresolved].sort((a, b) => a - b) };
|
|
8312
|
-
}
|
|
8313
|
-
function formatCitationList(numbers) {
|
|
8314
|
-
return numbers.length === 0 ? "none" : numbers.map((number) => `[${number}]`).join(", ");
|
|
8315
|
-
}
|
|
8316
|
-
function duplicateNumbers(sortedNumbers) {
|
|
8317
|
-
const duplicates = [];
|
|
8318
|
-
for (let index = 1;index < sortedNumbers.length; index++) {
|
|
8319
|
-
const number = sortedNumbers[index];
|
|
8320
|
-
if (number === sortedNumbers[index - 1] && duplicates[duplicates.length - 1] !== number)
|
|
8321
|
-
duplicates.push(number);
|
|
8322
|
-
}
|
|
8323
|
-
return duplicates;
|
|
8324
|
-
}
|
|
8325
|
-
function assertUniqueResultNumbers(label, results) {
|
|
8326
|
-
const duplicates = duplicateNumbers(results.map((result) => result.number).sort((a, b) => a - b));
|
|
8327
|
-
if (duplicates.length === 0)
|
|
8328
|
-
return;
|
|
8329
|
-
throw new Error(`${label}: result numbers must be unique, but results repeat ${formatCitationList(duplicates)}. Give every result its own number and re-emit.`);
|
|
8330
|
-
}
|
|
8331
|
-
function assertResultsMappingOneToOne(label, results, mapping) {
|
|
8332
|
-
const resultNumbers = results.map((result) => result.number).sort((a, b) => a - b);
|
|
8333
|
-
const mappingNumbers = mapping.map((entry) => entry.number).sort((a, b) => a - b);
|
|
8334
|
-
const resultDuplicates = duplicateNumbers(resultNumbers);
|
|
8335
|
-
const mappingDuplicates = duplicateNumbers(mappingNumbers);
|
|
8336
|
-
const sameNumbers = resultNumbers.length === mappingNumbers.length && resultNumbers.every((number, index) => number === mappingNumbers[index]);
|
|
8337
|
-
if (sameNumbers && resultDuplicates.length === 0 && mappingDuplicates.length === 0)
|
|
8338
|
-
return;
|
|
8339
|
-
const duplicateNotes = [
|
|
8340
|
-
resultDuplicates.length > 0 ? `results repeat ${formatCitationList(resultDuplicates)}` : undefined,
|
|
8341
|
-
mappingDuplicates.length > 0 ? `mapping repeats ${formatCitationList(mappingDuplicates)}` : undefined
|
|
8342
|
-
].filter((note) => note !== undefined);
|
|
8343
|
-
throw new Error(`${label}: result numbers and mapping numbers must be one-to-one, but results contain ${formatCitationList(resultNumbers)} ` + `and mapping contains ${formatCitationList(mappingNumbers)}` + (duplicateNotes.length > 0 ? ` (${duplicateNotes.join("; ")})` : "") + ". Give every result a unique number with exactly one mapping entry carrying the same number and no mapping entry without a result. Re-emit with consistent numbering.");
|
|
8344
|
-
}
|
|
8345
|
-
function assertCitationsResolve(label, answer, results) {
|
|
8346
|
-
const unresolved = unresolvedCitations(answer, results);
|
|
8347
|
-
if (unresolved.length === 0)
|
|
8348
|
-
return;
|
|
8349
|
-
const emitted = [...new Set(results.map((result) => result.number))].sort((a, b) => a - b);
|
|
8350
|
-
throw new Error(`${label}: answer cites ${formatCitationList(unresolved)} but results only contain ${formatCitationList(emitted)}. ` + "Every bracketed citation in answer must be the number of a result in results of this same call; " + "candidate numbers from retrieval context or an earlier answer are not citation numbers. Re-emit with consistent numbering.");
|
|
8351
|
-
}
|
|
8352
|
-
|
|
8353
|
-
// src/agent/emit-results-tool.ts
|
|
8354
|
-
import { Type as Type4 } from "typebox";
|
|
8355
|
-
function createEmitResultsTool(capture, options) {
|
|
8356
|
-
return {
|
|
8357
|
-
name: EMIT_AUTORAG_RESULTS_TOOL_NAME,
|
|
8358
|
-
label: "Emit AutoRAG Results",
|
|
8359
|
-
description: "Return the final structured AutoRAG answer. Call this exactly once as your last action after searching, reading, and curating. Cite each result's supporting evidence in its refs, using the evidence ids shown next to retrieved results (e.g. e3); the source paths are attached for you. A call whose answer cites a number missing from results, whose result numbers repeat, or whose refs name evidence no tool returned is rejected; fix it and call again.",
|
|
8360
|
-
parameters: emitResultsSchema,
|
|
8361
|
-
async execute(_toolCallId, params) {
|
|
8362
|
-
assertCitationsResolve(EMIT_AUTORAG_RESULTS_TOOL_NAME, params.answer, params.results);
|
|
8363
|
-
assertUniqueResultNumbers(EMIT_AUTORAG_RESULTS_TOOL_NAME, params.results);
|
|
8364
|
-
const mapping = params.results.map((result) => {
|
|
8365
|
-
const evidenceRefs = options.ledger.resolve(result.refs, {
|
|
8366
|
-
label: EMIT_AUTORAG_RESULTS_TOOL_NAME,
|
|
8367
|
-
number: result.number,
|
|
8368
|
-
fallbackContent: result.evidence.map((evidence) => evidence.excerpt).join(`
|
|
8369
|
-
`) || result.summary,
|
|
8370
|
-
allowLocalFiles: options.allowLocalFiles
|
|
8371
|
-
});
|
|
8372
|
-
const primary = evidenceRefs[0];
|
|
8373
|
-
if (primary === undefined) {
|
|
8374
|
-
throw new Error(`${EMIT_AUTORAG_RESULTS_TOOL_NAME}: result ${result.number} resolved no evidence. Give it at least one valid ref.`);
|
|
8375
|
-
}
|
|
8376
|
-
return {
|
|
8377
|
-
number: result.number,
|
|
8378
|
-
source: primary.source,
|
|
8379
|
-
method: primary.method,
|
|
8380
|
-
content: primary.content ?? "",
|
|
8381
|
-
evidenceRefs
|
|
8382
|
-
};
|
|
8383
|
-
});
|
|
8384
|
-
const details = {
|
|
8385
|
-
answer: params.answer,
|
|
8386
|
-
results: params.results.map((result) => ({
|
|
8387
|
-
number: result.number,
|
|
8388
|
-
title: result.title,
|
|
8389
|
-
summary: result.summary,
|
|
8390
|
-
evidence: result.evidence.map((evidence) => evidence.lineNumber !== undefined ? { excerpt: evidence.excerpt, lineNumber: evidence.lineNumber } : { excerpt: evidence.excerpt }),
|
|
8391
|
-
confidence: result.confidence
|
|
8392
|
-
})),
|
|
8393
|
-
mapping,
|
|
8394
|
-
warnings: params.warnings ?? []
|
|
8395
|
-
};
|
|
8396
|
-
capture(details);
|
|
8397
|
-
return {
|
|
8398
|
-
content: [{ type: "text", text: "AutoRAG results emitted." }],
|
|
8399
|
-
details,
|
|
8400
|
-
terminate: true
|
|
8401
|
-
};
|
|
8402
|
-
}
|
|
8403
|
-
};
|
|
8404
|
-
}
|
|
8405
|
-
var EMIT_AUTORAG_RESULTS_TOOL_NAME = "emit_autorag_results", evidenceRefSchema, answerSchema, warningsSchema, curatedResultFields, emitResultsSchema, reportSchema;
|
|
8406
|
-
var init_emit_results_tool = __esm(() => {
|
|
8407
|
-
evidenceRefSchema = Type4.Object({
|
|
8408
|
-
method: Type4.String({ description: "Retrieval method namespace for this evidence chunk" }),
|
|
8409
|
-
source: Type4.String({ description: "Internal opaque source identifier for this evidence chunk" }),
|
|
8410
|
-
excerpt: Type4.Optional(Type4.String({ description: "Evidence excerpt used for stable ID normalization" })),
|
|
8411
|
-
content: Type4.Optional(Type4.String({ description: "Evidence content used for stable ID normalization" })),
|
|
8412
|
-
retrievalResultId: Type4.Optional(Type4.String({ description: "Backend retrieval ID when path-opaque and stable" })),
|
|
8413
|
-
chunkIndex: Type4.Optional(Type4.Integer({ description: "Chunk index, if available" })),
|
|
8414
|
-
lineNumber: Type4.Optional(Type4.Integer({ description: "Line number, if available" })),
|
|
8415
|
-
stableEvidenceId: Type4.Optional(Type4.String({ description: "Stable evidence ID, if already normalized" })),
|
|
8416
|
-
retrieverMix: Type4.Optional(Type4.Array(Type4.String({ maxLength: 64 }), {
|
|
8417
|
-
description: "Retrievers that contributed to this result",
|
|
8418
|
-
maxItems: 8
|
|
8419
|
-
})),
|
|
8420
|
-
parserType: Type4.Optional(Type4.String({ description: "Parser that produced this evidence", maxLength: 120 })),
|
|
8421
|
-
documentType: Type4.Optional(Type4.String({ description: "Document type, if known", maxLength: 120 })),
|
|
8422
|
-
documentArea: Type4.Optional(Type4.String({ description: "Document collection area, if known", maxLength: 120 })),
|
|
8423
|
-
evidenceType: Type4.Optional(Type4.String({ description: "Evidence type, if known", maxLength: 120 })),
|
|
8424
|
-
evidenceLocation: Type4.Optional(Type4.String({ description: "Human-readable evidence location", maxLength: 120 })),
|
|
8425
|
-
confidence: Type4.Optional(Type4.Number({ description: "Evidence confidence, 0..1", minimum: 0, maximum: 1 }))
|
|
8426
|
-
});
|
|
8427
|
-
answerSchema = Type4.String({
|
|
8428
|
-
description: `Answer for the caller. When a first answer was already delivered to the caller during this run, this MUST contain only the corrections and newly verified findings relative to it — never restate the first answer; otherwise it is the complete answer. At most 5 bullet points (plus optional explanation); reference results by bracketed number (e.g. [1], [2]) without file paths or raw chunk text, except the image-embed exception below. ${ANSWER_CITATION_RULE} ${ANSWER_IMAGE_EMBED_RULE} ${ANSWER_IMAGE_DELTA_RULE}`
|
|
8429
|
-
});
|
|
8430
|
-
warningsSchema = Type4.Optional(Type4.Array(Type4.String(), { description: "Optional warnings about this result set" }));
|
|
8431
|
-
curatedResultFields = {
|
|
8432
|
-
number: Type4.Integer({ description: "1-based result number" }),
|
|
8433
|
-
title: Type4.String({ description: "Short name of the curated knowledge unit" }),
|
|
8434
|
-
summary: Type4.String({ description: "Key insight: purpose, details, and line range" }),
|
|
8435
|
-
evidence: Type4.Array(Type4.Object({
|
|
8436
|
-
excerpt: Type4.String({ description: "Supporting excerpt" }),
|
|
8437
|
-
lineNumber: Type4.Optional(Type4.Integer({ description: "Line number of the excerpt, if known" }))
|
|
8438
|
-
})),
|
|
8439
|
-
confidence: Type4.Number({ description: "Confidence in this result, 0..1", minimum: 0, maximum: 1 })
|
|
8440
|
-
};
|
|
8441
|
-
emitResultsSchema = Type4.Object({
|
|
8442
|
-
answer: answerSchema,
|
|
8443
|
-
results: Type4.Array(Type4.Object({
|
|
8444
|
-
...curatedResultFields,
|
|
8445
|
-
refs: Type4.Array(Type4.String(), {
|
|
8446
|
-
minItems: 1,
|
|
8447
|
-
description: "Evidence ids supporting this result, copied from the ids shown next to retrieved results (e.g. e3). For a local file you opened yourself with bash, give its absolute path instead."
|
|
8448
|
-
})
|
|
8449
|
-
}), { description: "Numbered curated knowledge units." }),
|
|
8450
|
-
warnings: warningsSchema
|
|
8451
|
-
});
|
|
8452
|
-
reportSchema = Type4.Object({
|
|
8453
|
-
answer: answerSchema,
|
|
8454
|
-
results: Type4.Array(Type4.Object(curatedResultFields), { description: "Numbered curated knowledge units." }),
|
|
8455
|
-
mapping: Type4.Array(Type4.Object({
|
|
8456
|
-
number: Type4.Integer({ description: "Matches the result number this entry maps" }),
|
|
8457
|
-
source: Type4.String({ description: "Source identifier — a real file path or a datasource id" }),
|
|
8458
|
-
method: Type4.String({ description: "Retrieval method or tool that produced the source" }),
|
|
8459
|
-
content: Type4.String({ description: "Raw content snippet of the evidence behind this result" }),
|
|
8460
|
-
evidenceRefs: Type4.Optional(Type4.Array(evidenceRefSchema, {
|
|
8461
|
-
description: "Hidden evidence chunk references supporting this curated result"
|
|
8462
|
-
}))
|
|
8463
|
-
}), { description: "Internal number -> source/method mapping. One entry per result number." }),
|
|
8464
|
-
warnings: warningsSchema
|
|
8465
|
-
});
|
|
8466
|
-
});
|
|
8467
|
-
|
|
8468
8636
|
// src/agent/everything-search-tool.ts
|
|
8469
|
-
import { Type as
|
|
8637
|
+
import { Type as Type4 } from "typebox";
|
|
8470
8638
|
function createEverythingSearchTool(provider) {
|
|
8471
8639
|
return {
|
|
8472
8640
|
name: EVERYTHING_SEARCH_TOOL_NAME,
|
|
@@ -8518,28 +8686,28 @@ ${lines.join(`
|
|
|
8518
8686
|
}
|
|
8519
8687
|
var EVERYTHING_SEARCH_TOOL_NAME = "everything_search", MAX_RESULTS_CAP2 = 1000, DEFAULT_MAX_RESULTS3 = 100, everythingSearchSchema;
|
|
8520
8688
|
var init_everything_search_tool = __esm(() => {
|
|
8521
|
-
everythingSearchSchema =
|
|
8522
|
-
query:
|
|
8689
|
+
everythingSearchSchema = Type4.Object({
|
|
8690
|
+
query: Type4.String({
|
|
8523
8691
|
description: 'Everything search syntax over file and folder names: space = AND, | = OR, ! = NOT, "quoted phrase", wildcards (*.pdf), ext:pdf;docx, dm:thisweek, size:>10mb, parent:<folder>, path fragments like \\reports\\ when matchPath is true.'
|
|
8524
8692
|
}),
|
|
8525
|
-
regex:
|
|
8526
|
-
matchCase:
|
|
8527
|
-
matchPath:
|
|
8528
|
-
wholeWord:
|
|
8529
|
-
kind:
|
|
8530
|
-
path:
|
|
8531
|
-
sort:
|
|
8532
|
-
|
|
8533
|
-
|
|
8534
|
-
|
|
8535
|
-
|
|
8536
|
-
|
|
8537
|
-
|
|
8538
|
-
|
|
8539
|
-
|
|
8693
|
+
regex: Type4.Optional(Type4.Boolean({ description: "Treat query as a regular expression." })),
|
|
8694
|
+
matchCase: Type4.Optional(Type4.Boolean()),
|
|
8695
|
+
matchPath: Type4.Optional(Type4.Boolean({ description: "Match against the full path instead of the name." })),
|
|
8696
|
+
wholeWord: Type4.Optional(Type4.Boolean()),
|
|
8697
|
+
kind: Type4.Optional(Type4.Union([Type4.Literal("files"), Type4.Literal("folders")])),
|
|
8698
|
+
path: Type4.Optional(Type4.String({ description: "Absolute folder to search within." })),
|
|
8699
|
+
sort: Type4.Optional(Type4.Union([
|
|
8700
|
+
Type4.Literal("name-ascending"),
|
|
8701
|
+
Type4.Literal("name-descending"),
|
|
8702
|
+
Type4.Literal("path-ascending"),
|
|
8703
|
+
Type4.Literal("path-descending"),
|
|
8704
|
+
Type4.Literal("size-ascending"),
|
|
8705
|
+
Type4.Literal("size-descending"),
|
|
8706
|
+
Type4.Literal("date-modified-ascending"),
|
|
8707
|
+
Type4.Literal("date-modified-descending")
|
|
8540
8708
|
])),
|
|
8541
|
-
offset:
|
|
8542
|
-
maxResults:
|
|
8709
|
+
offset: Type4.Optional(Type4.Integer({ minimum: 0, description: "Skip this many results (pagination)." })),
|
|
8710
|
+
maxResults: Type4.Optional(Type4.Integer({
|
|
8543
8711
|
minimum: 1,
|
|
8544
8712
|
description: `Maximum results (default ${DEFAULT_MAX_RESULTS3}, cap ${MAX_RESULTS_CAP2}).`
|
|
8545
8713
|
}))
|
|
@@ -8671,146 +8839,6 @@ var init_evidence_judgment = __esm(() => {
|
|
|
8671
8839
|
};
|
|
8672
8840
|
});
|
|
8673
8841
|
|
|
8674
|
-
// src/agent/evidence-ledger.ts
|
|
8675
|
-
import { createHash as createHash10 } from "node:crypto";
|
|
8676
|
-
import { statSync } from "node:fs";
|
|
8677
|
-
import { isAbsolute as isAbsolute6 } from "node:path";
|
|
8678
|
-
function metadataString(metadata, key) {
|
|
8679
|
-
const value = metadata[key];
|
|
8680
|
-
return typeof value === "string" && value.trim().length > 0 ? value : undefined;
|
|
8681
|
-
}
|
|
8682
|
-
function metadataNumber(metadata, key) {
|
|
8683
|
-
const value = metadata[key];
|
|
8684
|
-
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
8685
|
-
}
|
|
8686
|
-
function isRegularFile2(path) {
|
|
8687
|
-
try {
|
|
8688
|
-
return statSync(path).isFile();
|
|
8689
|
-
} catch {
|
|
8690
|
-
return false;
|
|
8691
|
-
}
|
|
8692
|
-
}
|
|
8693
|
-
function toEvidenceRef(entry) {
|
|
8694
|
-
return {
|
|
8695
|
-
method: entry.method,
|
|
8696
|
-
source: entry.source,
|
|
8697
|
-
content: entry.content,
|
|
8698
|
-
retrieverMix: [...entry.retrieverMix],
|
|
8699
|
-
...entry.retrievalResultId !== undefined ? { retrievalResultId: entry.retrievalResultId } : {},
|
|
8700
|
-
...entry.chunkIndex !== undefined ? { chunkIndex: entry.chunkIndex } : {},
|
|
8701
|
-
...entry.lineNumber !== undefined ? { lineNumber: entry.lineNumber } : {},
|
|
8702
|
-
...entry.parserType !== undefined ? { parserType: entry.parserType } : {},
|
|
8703
|
-
...entry.documentType !== undefined ? { documentType: entry.documentType } : {},
|
|
8704
|
-
...entry.documentArea !== undefined ? { documentArea: entry.documentArea } : {},
|
|
8705
|
-
...entry.evidenceType !== undefined ? { evidenceType: entry.evidenceType } : {},
|
|
8706
|
-
...entry.evidenceLocation !== undefined ? { evidenceLocation: entry.evidenceLocation } : {}
|
|
8707
|
-
};
|
|
8708
|
-
}
|
|
8709
|
-
|
|
8710
|
-
class EvidenceLedger {
|
|
8711
|
-
entries = [];
|
|
8712
|
-
byKey = new Map;
|
|
8713
|
-
byId = new Map;
|
|
8714
|
-
lastOrdinal = 0;
|
|
8715
|
-
register(input) {
|
|
8716
|
-
const content = input.content.slice(0, MAX_CONTENT_CHARS);
|
|
8717
|
-
const digest = createHash10("sha256").update(input.content.replace(/\s+/gu, " ").trim()).digest("hex");
|
|
8718
|
-
const key = `${input.source}\x00${digest}`;
|
|
8719
|
-
const existing = this.byKey.get(key);
|
|
8720
|
-
if (existing !== undefined) {
|
|
8721
|
-
if (!existing.retrieverMix.includes(input.method))
|
|
8722
|
-
existing.retrieverMix.push(input.method);
|
|
8723
|
-
return existing.id;
|
|
8724
|
-
}
|
|
8725
|
-
const entry = {
|
|
8726
|
-
...input,
|
|
8727
|
-
content,
|
|
8728
|
-
id: `e${++this.lastOrdinal}`,
|
|
8729
|
-
retrieverMix: [input.method]
|
|
8730
|
-
};
|
|
8731
|
-
this.entries.push(entry);
|
|
8732
|
-
this.byKey.set(key, entry);
|
|
8733
|
-
this.byId.set(entry.id, entry);
|
|
8734
|
-
return entry.id;
|
|
8735
|
-
}
|
|
8736
|
-
registerResult(tool, result) {
|
|
8737
|
-
const metadata = result.metadata;
|
|
8738
|
-
const chunkIndex = metadataNumber(metadata, "chunkIndex");
|
|
8739
|
-
const lineNumber = metadataNumber(metadata, "lineNumber");
|
|
8740
|
-
const parserType = metadataString(metadata, "parserType");
|
|
8741
|
-
const documentType = metadataString(metadata, "documentType");
|
|
8742
|
-
const documentArea = metadataString(metadata, "documentArea");
|
|
8743
|
-
const evidenceType = metadataString(metadata, "evidenceType");
|
|
8744
|
-
const evidenceLocation = metadataString(metadata, "evidenceLocation");
|
|
8745
|
-
return this.register({
|
|
8746
|
-
method: metadataString(metadata, "method") ?? tool,
|
|
8747
|
-
source: result.source,
|
|
8748
|
-
content: result.content,
|
|
8749
|
-
retrievalResultId: result.id,
|
|
8750
|
-
...chunkIndex !== undefined ? { chunkIndex } : {},
|
|
8751
|
-
...lineNumber !== undefined ? { lineNumber } : {},
|
|
8752
|
-
...parserType !== undefined ? { parserType } : {},
|
|
8753
|
-
...documentType !== undefined ? { documentType } : {},
|
|
8754
|
-
...documentArea !== undefined ? { documentArea } : {},
|
|
8755
|
-
...evidenceType !== undefined ? { evidenceType } : {},
|
|
8756
|
-
...evidenceLocation !== undefined ? { evidenceLocation } : {}
|
|
8757
|
-
});
|
|
8758
|
-
}
|
|
8759
|
-
resolve(refs, options) {
|
|
8760
|
-
const resolved = [];
|
|
8761
|
-
const seen = new Set;
|
|
8762
|
-
const push = (entry) => {
|
|
8763
|
-
if (seen.has(entry.id))
|
|
8764
|
-
return;
|
|
8765
|
-
seen.add(entry.id);
|
|
8766
|
-
resolved.push(toEvidenceRef(entry));
|
|
8767
|
-
};
|
|
8768
|
-
for (const raw of refs) {
|
|
8769
|
-
const trimmed = raw.trim();
|
|
8770
|
-
const ref = trimmed.startsWith("[") && trimmed.endsWith("]") ? trimmed.slice(1, -1).trim() : trimmed;
|
|
8771
|
-
const byId = this.byId.get(ref);
|
|
8772
|
-
if (byId !== undefined) {
|
|
8773
|
-
push(byId);
|
|
8774
|
-
continue;
|
|
8775
|
-
}
|
|
8776
|
-
const bySource = this.entries.filter((entry) => entry.source === ref);
|
|
8777
|
-
if (bySource.length > 0) {
|
|
8778
|
-
for (const entry of bySource)
|
|
8779
|
-
push(entry);
|
|
8780
|
-
continue;
|
|
8781
|
-
}
|
|
8782
|
-
if (options.allowLocalFiles && isAbsolute6(ref) && isRegularFile2(ref)) {
|
|
8783
|
-
const key = `file\x00${ref}`;
|
|
8784
|
-
if (seen.has(key))
|
|
8785
|
-
continue;
|
|
8786
|
-
seen.add(key);
|
|
8787
|
-
resolved.push({
|
|
8788
|
-
method: "bash",
|
|
8789
|
-
source: ref,
|
|
8790
|
-
content: (options.fallbackContent.trim() || ref).slice(0, MAX_CONTENT_CHARS)
|
|
8791
|
-
});
|
|
8792
|
-
continue;
|
|
8793
|
-
}
|
|
8794
|
-
throw new Error(this.unresolvedMessage(ref, EVIDENCE_ID_PATTERN.test(ref), options));
|
|
8795
|
-
}
|
|
8796
|
-
return resolved;
|
|
8797
|
-
}
|
|
8798
|
-
clear() {
|
|
8799
|
-
this.entries = [];
|
|
8800
|
-
this.byKey.clear();
|
|
8801
|
-
this.byId.clear();
|
|
8802
|
-
}
|
|
8803
|
-
unresolvedMessage(ref, looksLikeId, options) {
|
|
8804
|
-
const known = this.entries.length === 0 ? "No search or fetch has returned evidence in this run yet." : `Evidence ids issued in this run: ${this.entries[0]?.id}${this.entries.length > 1 ? `..${this.entries[this.entries.length - 1]?.id}` : ""}.`;
|
|
8805
|
-
const local = options.allowLocalFiles ? " For a file you opened yourself with bash, pass its absolute path." : "";
|
|
8806
|
-
return `${options.label}: result ${options.number} cites evidence "${ref}" that no tool returned in this run` + `${looksLikeId ? " (unknown evidence id)" : ""}. ${known} ` + `Cite only the evidence ids shown next to retrieved results (e.g. e3).${local} Re-emit with valid refs.`;
|
|
8807
|
-
}
|
|
8808
|
-
}
|
|
8809
|
-
var MAX_CONTENT_CHARS = 2000, EVIDENCE_ID_PATTERN;
|
|
8810
|
-
var init_evidence_ledger = __esm(() => {
|
|
8811
|
-
EVIDENCE_ID_PATTERN = /^e\d+$/u;
|
|
8812
|
-
});
|
|
8813
|
-
|
|
8814
8842
|
// src/agent/evidence-origins.ts
|
|
8815
8843
|
function normalize3(text) {
|
|
8816
8844
|
return text.normalize("NFC").toLowerCase().replace(/\s+/g, " ").trim();
|
|
@@ -8909,170 +8937,690 @@ class EvidenceOriginIndex {
|
|
|
8909
8937
|
}
|
|
8910
8938
|
}
|
|
8911
8939
|
}
|
|
8912
|
-
return;
|
|
8940
|
+
return;
|
|
8941
|
+
}
|
|
8942
|
+
clear() {
|
|
8943
|
+
this.candidates.length = 0;
|
|
8944
|
+
this.seen.clear();
|
|
8945
|
+
}
|
|
8946
|
+
}
|
|
8947
|
+
var MAX_CANDIDATES = 2000, MAX_CONTENT_LENGTH = 4000, MIN_MATCH_LENGTH = 12;
|
|
8948
|
+
|
|
8949
|
+
// src/agent/fsearch-search-tool.ts
|
|
8950
|
+
import { Type as Type5 } from "typebox";
|
|
8951
|
+
function createFSearchSearchTool(provider) {
|
|
8952
|
+
return {
|
|
8953
|
+
name: FSEARCH_SEARCH_TOOL_NAME,
|
|
8954
|
+
label: "FSearch Search",
|
|
8955
|
+
description: "Instantly find files and folders by name, extension, path, size, or modified date across the configured search folders using fsearch-cli/FSearch (macOS/Linux), falling back to a slow filesystem walk when fsearch-cli is not installed. Returns absolute paths; read file contents with bash.",
|
|
8956
|
+
parameters: fsearchSearchSchema,
|
|
8957
|
+
async execute(_toolCallId, params) {
|
|
8958
|
+
const query = params.query.trim();
|
|
8959
|
+
if (query.length === 0) {
|
|
8960
|
+
return {
|
|
8961
|
+
content: [{ type: "text", text: "FSearch query was empty; nothing searched." }],
|
|
8962
|
+
details: { method: FSEARCH_SEARCH_TOOL_NAME, resultCount: 0, sources: [], results: [] }
|
|
8963
|
+
};
|
|
8964
|
+
}
|
|
8965
|
+
const request = {
|
|
8966
|
+
...params,
|
|
8967
|
+
query,
|
|
8968
|
+
maxResults: Math.min(params.maxResults ?? DEFAULT_MAX_RESULTS4, MAX_RESULTS_CAP3)
|
|
8969
|
+
};
|
|
8970
|
+
const result = await provider.searchFsearch(request);
|
|
8971
|
+
if (!result.ok) {
|
|
8972
|
+
return {
|
|
8973
|
+
content: [{ type: "text", text: `FSearch ${result.reason}: ${result.message}` }],
|
|
8974
|
+
details: { method: FSEARCH_SEARCH_TOOL_NAME, resultCount: 0, sources: [], results: [] }
|
|
8975
|
+
};
|
|
8976
|
+
}
|
|
8977
|
+
const lines = result.results.map((entry, index) => {
|
|
8978
|
+
const parts = [`[${index + 1}] ${entry.type} ${entry.path}`];
|
|
8979
|
+
if (entry.size !== undefined)
|
|
8980
|
+
parts.push(`size=${entry.size}`);
|
|
8981
|
+
if (entry.dateModified !== undefined)
|
|
8982
|
+
parts.push(`modified=${entry.dateModified}`);
|
|
8983
|
+
return parts.join(" ");
|
|
8984
|
+
});
|
|
8985
|
+
const backendLabel = result.backend === "walk" ? "FSearch slow filesystem walk (fsearch-cli unavailable)" : "FSearch";
|
|
8986
|
+
const limitNote = result.backend === "fsearch-cli" && (result.total ?? 0) > lines.length && lines.length === request.maxResults ? ` of ${result.total} total (limit reached; narrow the query or page with offset)` : "";
|
|
8987
|
+
const noteSuffix = result.note !== undefined ? `
|
|
8988
|
+
${result.note}` : "";
|
|
8989
|
+
const text = lines.length === 0 ? `${backendLabel} found no files or folders matching: ${query}${noteSuffix}` : `${backendLabel} found ${lines.length} item(s)${limitNote}:
|
|
8990
|
+
${lines.join(`
|
|
8991
|
+
`)}${noteSuffix}`;
|
|
8992
|
+
return {
|
|
8993
|
+
content: [{ type: "text", text }],
|
|
8994
|
+
details: {
|
|
8995
|
+
method: FSEARCH_SEARCH_TOOL_NAME,
|
|
8996
|
+
resultCount: result.results.length,
|
|
8997
|
+
sources: result.results.map((entry) => entry.path),
|
|
8998
|
+
results: result.results.map((entry, index) => ({ source: entry.path, excerpt: lines[index] }))
|
|
8999
|
+
}
|
|
9000
|
+
};
|
|
9001
|
+
}
|
|
9002
|
+
};
|
|
9003
|
+
}
|
|
9004
|
+
var FSEARCH_SEARCH_TOOL_NAME = "fsearch_search", MAX_RESULTS_CAP3 = 1000, DEFAULT_MAX_RESULTS4 = 100, fsearchSearchSchema;
|
|
9005
|
+
var init_fsearch_search_tool = __esm(() => {
|
|
9006
|
+
fsearchSearchSchema = Type5.Object({
|
|
9007
|
+
query: Type5.String({
|
|
9008
|
+
description: 'FSearch query syntax over file and folder names: space = AND, OR keyword = OR (never the pipe |), ! = NOT, "quoted phrase", wildcards (*.pdf), ext:pdf;docx, size:>10mb, path:<fragment>, case:, regex:. When the slow-walk fallback answers (fsearch-cli not installed), only substring/regex name matching applies.'
|
|
9009
|
+
}),
|
|
9010
|
+
regex: Type5.Optional(Type5.Boolean({ description: "Treat query as a regular expression." })),
|
|
9011
|
+
matchCase: Type5.Optional(Type5.Boolean()),
|
|
9012
|
+
matchPath: Type5.Optional(Type5.Boolean({ description: "Match against the full path instead of the name." })),
|
|
9013
|
+
kind: Type5.Optional(Type5.Union([Type5.Literal("files"), Type5.Literal("folders")])),
|
|
9014
|
+
path: Type5.Optional(Type5.String({ description: "Absolute folder to search within." })),
|
|
9015
|
+
sort: Type5.Optional(Type5.Union([
|
|
9016
|
+
Type5.Literal("name-ascending"),
|
|
9017
|
+
Type5.Literal("name-descending"),
|
|
9018
|
+
Type5.Literal("path-ascending"),
|
|
9019
|
+
Type5.Literal("path-descending"),
|
|
9020
|
+
Type5.Literal("size-ascending"),
|
|
9021
|
+
Type5.Literal("size-descending"),
|
|
9022
|
+
Type5.Literal("date-modified-ascending"),
|
|
9023
|
+
Type5.Literal("date-modified-descending")
|
|
9024
|
+
])),
|
|
9025
|
+
offset: Type5.Optional(Type5.Integer({ minimum: 0, description: "Skip this many results (pagination)." })),
|
|
9026
|
+
maxResults: Type5.Optional(Type5.Integer({
|
|
9027
|
+
minimum: 1,
|
|
9028
|
+
description: `Maximum results (default ${DEFAULT_MAX_RESULTS4}, cap ${MAX_RESULTS_CAP3}).`
|
|
9029
|
+
}))
|
|
9030
|
+
});
|
|
9031
|
+
});
|
|
9032
|
+
|
|
9033
|
+
// src/cloud/config.ts
|
|
9034
|
+
function normalizeBaseUrl(value) {
|
|
9035
|
+
const trimmed = value.trim();
|
|
9036
|
+
let end = trimmed.length;
|
|
9037
|
+
while (end > 0 && trimmed.charCodeAt(end - 1) === 47)
|
|
9038
|
+
end--;
|
|
9039
|
+
return trimmed.slice(0, end);
|
|
9040
|
+
}
|
|
9041
|
+
function resolveBaseUrl(env) {
|
|
9042
|
+
const configured = env[AUTORAG_BASE_URL_ENV];
|
|
9043
|
+
const value = typeof configured === "string" && configured.trim() !== "" ? configured : DEFAULT_BASE_URL;
|
|
9044
|
+
return normalizeBaseUrl(value);
|
|
9045
|
+
}
|
|
9046
|
+
var PROVIDER_ID = "autorag", PROVIDER_NAME = "AutoRAG", DEFAULT_BASE_URL = "https://api.dazziapp.com", AUTORAG_BASE_URL_ENV = "AUTORAG_BASE_URL", AUTORAG_API_KEY_ENV = "AUTORAG_API_KEY", API_PATH = "/v1", MODELS_PATH = "/v1/models", AUTHORIZE_PATH = "/desktop/authorize", TOKEN_PATH = "/api/desktop/token", OAUTH_CLIENT_ID = "agent", API_KEY_CONFIG_VALUE;
|
|
9047
|
+
var init_config = __esm(() => {
|
|
9048
|
+
API_KEY_CONFIG_VALUE = `$${AUTORAG_API_KEY_ENV}`;
|
|
9049
|
+
});
|
|
9050
|
+
|
|
9051
|
+
// src/cloud/errors.ts
|
|
9052
|
+
function extractErrorPayload(body) {
|
|
9053
|
+
if (typeof body !== "object" || body === null)
|
|
9054
|
+
return {};
|
|
9055
|
+
const record = body;
|
|
9056
|
+
const error = record.error;
|
|
9057
|
+
if (typeof error === "string")
|
|
9058
|
+
return error.length > 0 ? { message: error } : {};
|
|
9059
|
+
if (typeof error === "object" && error !== null) {
|
|
9060
|
+
const inner = error;
|
|
9061
|
+
const payload = {};
|
|
9062
|
+
if (typeof inner.message === "string")
|
|
9063
|
+
payload.message = inner.message;
|
|
9064
|
+
if (typeof inner.code === "string")
|
|
9065
|
+
payload.code = inner.code;
|
|
9066
|
+
if (typeof inner.type === "string")
|
|
9067
|
+
payload.type = inner.type;
|
|
9068
|
+
return payload;
|
|
9069
|
+
}
|
|
9070
|
+
return typeof record.message === "string" ? { message: record.message } : {};
|
|
9071
|
+
}
|
|
9072
|
+
var AutoragError, AutoragOAuthError, AutoragHttpError;
|
|
9073
|
+
var init_errors3 = __esm(() => {
|
|
9074
|
+
AutoragError = class AutoragError extends Error {
|
|
9075
|
+
constructor(message, options) {
|
|
9076
|
+
super(message, options);
|
|
9077
|
+
this.name = "AutoragError";
|
|
9078
|
+
}
|
|
9079
|
+
};
|
|
9080
|
+
AutoragOAuthError = class AutoragOAuthError extends AutoragError {
|
|
9081
|
+
constructor(message, options) {
|
|
9082
|
+
super(message, options);
|
|
9083
|
+
this.name = "AutoragOAuthError";
|
|
9084
|
+
}
|
|
9085
|
+
};
|
|
9086
|
+
AutoragHttpError = class AutoragHttpError extends AutoragError {
|
|
9087
|
+
status;
|
|
9088
|
+
code;
|
|
9089
|
+
type;
|
|
9090
|
+
constructor(message, options) {
|
|
9091
|
+
super(message, { cause: options.cause });
|
|
9092
|
+
this.name = "AutoragHttpError";
|
|
9093
|
+
this.status = options.status;
|
|
9094
|
+
if (options.code !== undefined)
|
|
9095
|
+
this.code = options.code;
|
|
9096
|
+
if (options.type !== undefined)
|
|
9097
|
+
this.type = options.type;
|
|
9098
|
+
}
|
|
9099
|
+
};
|
|
9100
|
+
});
|
|
9101
|
+
|
|
9102
|
+
// src/cloud/models.ts
|
|
9103
|
+
function resolveCredentialKey(credential) {
|
|
9104
|
+
if (credential === undefined)
|
|
9105
|
+
return;
|
|
9106
|
+
const value = credential.type === "oauth" ? credential.access : credential.key;
|
|
9107
|
+
return typeof value === "string" && value !== "" ? value : undefined;
|
|
9108
|
+
}
|
|
9109
|
+
async function fetchModels(options) {
|
|
9110
|
+
const doFetch = options.fetchImpl ?? fetch;
|
|
9111
|
+
let response;
|
|
9112
|
+
try {
|
|
9113
|
+
response = await doFetch(`${normalizeBaseUrl(options.baseUrl)}${MODELS_PATH}`, {
|
|
9114
|
+
headers: { authorization: `Bearer ${options.apiKey}`, accept: "application/json" },
|
|
9115
|
+
signal: options.signal
|
|
9116
|
+
});
|
|
9117
|
+
} catch (cause) {
|
|
9118
|
+
if (options.signal?.aborted) {
|
|
9119
|
+
throw new AutoragOAuthError("AutoRAG model refresh was cancelled.", { cause });
|
|
9120
|
+
}
|
|
9121
|
+
throw new AutoragOAuthError(`AutoRAG model listing could not reach ${normalizeBaseUrl(options.baseUrl)}.`, {
|
|
9122
|
+
cause
|
|
9123
|
+
});
|
|
9124
|
+
}
|
|
9125
|
+
let body;
|
|
9126
|
+
try {
|
|
9127
|
+
body = await response.json();
|
|
9128
|
+
} catch {
|
|
9129
|
+
body = undefined;
|
|
9130
|
+
}
|
|
9131
|
+
if (!response.ok)
|
|
9132
|
+
throw mapModelsError(response.status, body);
|
|
9133
|
+
return mapServerModels(body);
|
|
9134
|
+
}
|
|
9135
|
+
function mapModelsError(status, body) {
|
|
9136
|
+
const payload = extractErrorPayload(body);
|
|
9137
|
+
if (status === 401) {
|
|
9138
|
+
return new AutoragHttpError("AutoRAG rejected the API key (HTTP 401). Run /login again or set AUTORAG_API_KEY.", {
|
|
9139
|
+
status,
|
|
9140
|
+
code: payload.code ?? "unauthorized",
|
|
9141
|
+
type: payload.type
|
|
9142
|
+
});
|
|
9143
|
+
}
|
|
9144
|
+
const reason = payload.message ?? "the server returned no error message";
|
|
9145
|
+
return new AutoragHttpError(`AutoRAG model listing failed (HTTP ${status}): ${reason}`, {
|
|
9146
|
+
status,
|
|
9147
|
+
code: payload.code,
|
|
9148
|
+
type: payload.type
|
|
9149
|
+
});
|
|
9150
|
+
}
|
|
9151
|
+
function mapServerModels(payload) {
|
|
9152
|
+
if (typeof payload !== "object" || payload === null)
|
|
9153
|
+
return [];
|
|
9154
|
+
const data = payload.data;
|
|
9155
|
+
if (!Array.isArray(data))
|
|
9156
|
+
return [];
|
|
9157
|
+
const models = [];
|
|
9158
|
+
for (const entry of data) {
|
|
9159
|
+
if (typeof entry !== "object" || entry === null)
|
|
9160
|
+
continue;
|
|
9161
|
+
const model = mapServerModel(entry);
|
|
9162
|
+
if (model !== undefined)
|
|
9163
|
+
models.push(model);
|
|
9164
|
+
}
|
|
9165
|
+
return models;
|
|
9166
|
+
}
|
|
9167
|
+
function mapServerModel(entry) {
|
|
9168
|
+
const id = readString2(entry.id);
|
|
9169
|
+
if (id === undefined)
|
|
9170
|
+
return;
|
|
9171
|
+
return {
|
|
9172
|
+
type: "chat",
|
|
9173
|
+
id,
|
|
9174
|
+
name: readString2(entry.name) ?? id,
|
|
9175
|
+
input: readInputModalities(entry.input_modalities),
|
|
9176
|
+
cost: readPricing(entry.pricing),
|
|
9177
|
+
reasoning: entry.reasoning === true,
|
|
9178
|
+
contextWindow: readPositiveNumber(entry.context_window) ?? DEFAULT_CONTEXT_WINDOW,
|
|
9179
|
+
maxTokens: readPositiveNumber(entry.max_output_tokens) ?? DEFAULT_MAX_TOKENS
|
|
9180
|
+
};
|
|
9181
|
+
}
|
|
9182
|
+
function buildStoreEntry(models, providerId, baseUrl) {
|
|
9183
|
+
const stored = [];
|
|
9184
|
+
for (const model of models) {
|
|
9185
|
+
if (model.type === "image" || model.type === "classifier")
|
|
9186
|
+
continue;
|
|
9187
|
+
stored.push({
|
|
9188
|
+
type: "chat",
|
|
9189
|
+
id: model.id,
|
|
9190
|
+
name: model.name,
|
|
9191
|
+
api: model.api ?? "openai-responses",
|
|
9192
|
+
provider: providerId,
|
|
9193
|
+
baseUrl: model.baseUrl ?? baseUrl,
|
|
9194
|
+
input: model.input,
|
|
9195
|
+
cost: model.cost,
|
|
9196
|
+
reasoning: model.reasoning,
|
|
9197
|
+
contextWindow: model.contextWindow,
|
|
9198
|
+
maxTokens: model.maxTokens
|
|
9199
|
+
});
|
|
9200
|
+
}
|
|
9201
|
+
return { models: stored, checkedAt: Date.now() };
|
|
9202
|
+
}
|
|
9203
|
+
function modelsFromStore(stored) {
|
|
9204
|
+
if (stored === undefined)
|
|
9205
|
+
return [];
|
|
9206
|
+
const models = [];
|
|
9207
|
+
for (const entry of stored.models) {
|
|
9208
|
+
if (entry.type === "image" || entry.type === "classifier")
|
|
9209
|
+
continue;
|
|
9210
|
+
models.push({
|
|
9211
|
+
type: "chat",
|
|
9212
|
+
id: entry.id,
|
|
9213
|
+
name: entry.name,
|
|
9214
|
+
input: entry.input,
|
|
9215
|
+
cost: entry.cost,
|
|
9216
|
+
reasoning: entry.reasoning,
|
|
9217
|
+
contextWindow: entry.contextWindow,
|
|
9218
|
+
maxTokens: entry.maxTokens
|
|
9219
|
+
});
|
|
9220
|
+
}
|
|
9221
|
+
return models;
|
|
9222
|
+
}
|
|
9223
|
+
function readString2(value) {
|
|
9224
|
+
return typeof value === "string" && value.trim() !== "" ? value.trim() : undefined;
|
|
9225
|
+
}
|
|
9226
|
+
function readPositiveNumber(value) {
|
|
9227
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : undefined;
|
|
9228
|
+
}
|
|
9229
|
+
function readInputModalities(value) {
|
|
9230
|
+
if (!Array.isArray(value))
|
|
9231
|
+
return ["text"];
|
|
9232
|
+
const modalities = value.filter((item) => item === "text" || item === "image");
|
|
9233
|
+
const unique = Array.from(new Set(modalities));
|
|
9234
|
+
return unique.length > 0 ? unique : ["text"];
|
|
9235
|
+
}
|
|
9236
|
+
function readPricing(value) {
|
|
9237
|
+
const pricing = typeof value === "object" && value !== null ? value : {};
|
|
9238
|
+
return {
|
|
9239
|
+
input: readPositiveNumber(pricing.input) ?? 0,
|
|
9240
|
+
output: readPositiveNumber(pricing.output) ?? 0,
|
|
9241
|
+
cacheRead: readPositiveNumber(pricing.cache_read) ?? 0,
|
|
9242
|
+
cacheWrite: readPositiveNumber(pricing.cache_write) ?? 0
|
|
9243
|
+
};
|
|
9244
|
+
}
|
|
9245
|
+
var DEFAULT_CONTEXT_WINDOW = 128000, DEFAULT_MAX_TOKENS = 16384;
|
|
9246
|
+
var init_models = __esm(() => {
|
|
9247
|
+
init_config();
|
|
9248
|
+
init_errors3();
|
|
9249
|
+
});
|
|
9250
|
+
|
|
9251
|
+
// src/cloud/authorize.ts
|
|
9252
|
+
function buildAuthorizeUrl(params) {
|
|
9253
|
+
const url = new URL(`${normalizeBaseUrl(params.baseUrl)}${AUTHORIZE_PATH}`);
|
|
9254
|
+
url.searchParams.set("client", OAUTH_CLIENT_ID);
|
|
9255
|
+
url.searchParams.set("redirect_uri", params.redirectUri);
|
|
9256
|
+
url.searchParams.set("state", params.state);
|
|
9257
|
+
url.searchParams.set("code_challenge", params.codeChallenge);
|
|
9258
|
+
url.searchParams.set("code_challenge_method", "S256");
|
|
9259
|
+
return url.toString();
|
|
9260
|
+
}
|
|
9261
|
+
var init_authorize = __esm(() => {
|
|
9262
|
+
init_config();
|
|
9263
|
+
});
|
|
9264
|
+
|
|
9265
|
+
// src/cloud/callback.ts
|
|
9266
|
+
function parseCallbackQuery(params) {
|
|
9267
|
+
const result = {};
|
|
9268
|
+
const code = params.get("code");
|
|
9269
|
+
const error = params.get("error");
|
|
9270
|
+
const state = params.get("state");
|
|
9271
|
+
if (code !== null && code !== "")
|
|
9272
|
+
result.code = code;
|
|
9273
|
+
if (error !== null && error !== "")
|
|
9274
|
+
result.error = error;
|
|
9275
|
+
if (state !== null && state !== "")
|
|
9276
|
+
result.state = state;
|
|
9277
|
+
return result;
|
|
9278
|
+
}
|
|
9279
|
+
function parseCallbackInput(input) {
|
|
9280
|
+
const trimmed = input.trim();
|
|
9281
|
+
if (trimmed === "") {
|
|
9282
|
+
throw new AutoragOAuthError("AutoRAG sign-in failed: nothing was pasted.");
|
|
9283
|
+
}
|
|
9284
|
+
if (/^https?:\/\//i.test(trimmed)) {
|
|
9285
|
+
try {
|
|
9286
|
+
return parseCallbackQuery(new URL(trimmed).searchParams);
|
|
9287
|
+
} catch {
|
|
9288
|
+
throw new AutoragOAuthError("AutoRAG sign-in failed: the pasted URL is not valid.");
|
|
9289
|
+
}
|
|
9290
|
+
}
|
|
9291
|
+
const query = trimmed.startsWith("?") ? trimmed.slice(1) : trimmed;
|
|
9292
|
+
if (!query.includes(" ")) {
|
|
9293
|
+
const params = new URLSearchParams(query);
|
|
9294
|
+
if (params.has("code") || params.has("error") || params.has("state")) {
|
|
9295
|
+
return parseCallbackQuery(params);
|
|
9296
|
+
}
|
|
9297
|
+
}
|
|
9298
|
+
return { code: trimmed };
|
|
9299
|
+
}
|
|
9300
|
+
function requireAuthorizationCode(result, expectedState) {
|
|
9301
|
+
if (result.state !== undefined && result.state !== expectedState) {
|
|
9302
|
+
throw new AutoragOAuthError("AutoRAG sign-in failed: state mismatch (the callback did not originate from this login attempt).");
|
|
9303
|
+
}
|
|
9304
|
+
if (result.error !== undefined) {
|
|
9305
|
+
throw new AutoragOAuthError(result.error === "access_denied" ? "AutoRAG sign-in was cancelled in the browser." : `AutoRAG sign-in failed: ${result.error}.`);
|
|
9306
|
+
}
|
|
9307
|
+
if (result.code === undefined) {
|
|
9308
|
+
throw new AutoragOAuthError("AutoRAG sign-in failed: the callback carried no authorization code.");
|
|
9309
|
+
}
|
|
9310
|
+
return { code: result.code };
|
|
9311
|
+
}
|
|
9312
|
+
var init_callback = __esm(() => {
|
|
9313
|
+
init_errors3();
|
|
9314
|
+
});
|
|
9315
|
+
|
|
9316
|
+
// src/cloud/callback-server.ts
|
|
9317
|
+
import { createServer as createServer3 } from "node:http";
|
|
9318
|
+
function createDeferred() {
|
|
9319
|
+
let resolve;
|
|
9320
|
+
let reject;
|
|
9321
|
+
const promise = new Promise((res, rej) => {
|
|
9322
|
+
resolve = res;
|
|
9323
|
+
reject = rej;
|
|
9324
|
+
});
|
|
9325
|
+
return { promise, resolve, reject };
|
|
9326
|
+
}
|
|
9327
|
+
function renderCallbackPage(failed) {
|
|
9328
|
+
const message = failed ? "AutoRAG sign-in did not complete. You can close this tab and try again." : "Signed in to AutoRAG. You can close this tab.";
|
|
9329
|
+
return [
|
|
9330
|
+
"<!doctype html>",
|
|
9331
|
+
'<html lang="en">',
|
|
9332
|
+
"<head>",
|
|
9333
|
+
'<meta charset="utf-8">',
|
|
9334
|
+
'<meta name="viewport" content="width=device-width, initial-scale=1">',
|
|
9335
|
+
"<title>AutoRAG</title>",
|
|
9336
|
+
"</head>",
|
|
9337
|
+
'<body style="font-family: system-ui, sans-serif; margin: 4rem auto; max-width: 32rem; text-align: center;">',
|
|
9338
|
+
`<p>${message}</p>`,
|
|
9339
|
+
"</body>",
|
|
9340
|
+
"</html>"
|
|
9341
|
+
].join(`
|
|
9342
|
+
`);
|
|
9343
|
+
}
|
|
9344
|
+
function startCallbackServer(options) {
|
|
9345
|
+
const host = options.host ?? "127.0.0.1";
|
|
9346
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_LOGIN_TIMEOUT_MS;
|
|
9347
|
+
const server = createServer3();
|
|
9348
|
+
const started = createDeferred();
|
|
9349
|
+
const callback = createDeferred();
|
|
9350
|
+
callback.promise.catch(() => {});
|
|
9351
|
+
let finished = false;
|
|
9352
|
+
let startSettled = false;
|
|
9353
|
+
let timer;
|
|
9354
|
+
function cleanup() {
|
|
9355
|
+
clearTimeout(timer);
|
|
9356
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
9357
|
+
if (server.listening) {
|
|
9358
|
+
server.closeAllConnections();
|
|
9359
|
+
server.close();
|
|
9360
|
+
}
|
|
9361
|
+
}
|
|
9362
|
+
function fail(error) {
|
|
9363
|
+
if (finished)
|
|
9364
|
+
return;
|
|
9365
|
+
finished = true;
|
|
9366
|
+
cleanup();
|
|
9367
|
+
callback.reject(error);
|
|
9368
|
+
}
|
|
9369
|
+
function onAbort() {
|
|
9370
|
+
fail(new AutoragOAuthError("AutoRAG sign-in was cancelled."));
|
|
9371
|
+
}
|
|
9372
|
+
server.on("request", (req, res) => {
|
|
9373
|
+
const url = new URL(req.url ?? "/", `http://${host}`);
|
|
9374
|
+
if (req.method !== "GET" || url.pathname !== CALLBACK_PATH) {
|
|
9375
|
+
res.writeHead(404, { "content-type": "text/plain; charset=utf-8" });
|
|
9376
|
+
res.end("Not found");
|
|
9377
|
+
return;
|
|
9378
|
+
}
|
|
9379
|
+
if (finished) {
|
|
9380
|
+
res.writeHead(410, { "content-type": "text/plain; charset=utf-8" });
|
|
9381
|
+
res.end("Callback already handled");
|
|
9382
|
+
return;
|
|
9383
|
+
}
|
|
9384
|
+
const params = url.searchParams;
|
|
9385
|
+
const code = params.get("code");
|
|
9386
|
+
const oauthError = params.get("error");
|
|
9387
|
+
const hasResponse = code !== null && code !== "" || oauthError !== null && oauthError !== "";
|
|
9388
|
+
if (params.get("state") !== options.state || !hasResponse) {
|
|
9389
|
+
res.writeHead(400, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store" });
|
|
9390
|
+
res.end(renderCallbackPage(true));
|
|
9391
|
+
return;
|
|
9392
|
+
}
|
|
9393
|
+
finished = true;
|
|
9394
|
+
res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store" });
|
|
9395
|
+
res.end(renderCallbackPage(params.has("error")));
|
|
9396
|
+
cleanup();
|
|
9397
|
+
callback.resolve(params);
|
|
9398
|
+
});
|
|
9399
|
+
server.on("error", (error) => {
|
|
9400
|
+
const wrapped = error instanceof Error ? error : new Error(String(error));
|
|
9401
|
+
if (!startSettled) {
|
|
9402
|
+
startSettled = true;
|
|
9403
|
+
cleanup();
|
|
9404
|
+
started.reject(wrapped);
|
|
9405
|
+
return;
|
|
9406
|
+
}
|
|
9407
|
+
fail(wrapped);
|
|
9408
|
+
});
|
|
9409
|
+
server.listen(0, host, () => {
|
|
9410
|
+
const address = server.address();
|
|
9411
|
+
const port = typeof address === "object" && address !== null ? address.port : 0;
|
|
9412
|
+
const redirectUri = `http://${host}:${port}${CALLBACK_PATH}`;
|
|
9413
|
+
timer = setTimeout(() => fail(new AutoragOAuthError("AutoRAG sign-in timed out waiting for the browser callback.")), timeoutMs);
|
|
9414
|
+
if (options.signal?.aborted)
|
|
9415
|
+
onAbort();
|
|
9416
|
+
else
|
|
9417
|
+
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
9418
|
+
startSettled = true;
|
|
9419
|
+
options.onListening?.(redirectUri);
|
|
9420
|
+
started.resolve({
|
|
9421
|
+
redirectUri,
|
|
9422
|
+
waitForCallback: () => callback.promise,
|
|
9423
|
+
close: () => {
|
|
9424
|
+
if (!finished)
|
|
9425
|
+
fail(new AutoragOAuthError("AutoRAG sign-in was cancelled."));
|
|
9426
|
+
}
|
|
9427
|
+
});
|
|
9428
|
+
});
|
|
9429
|
+
return started.promise;
|
|
9430
|
+
}
|
|
9431
|
+
var CALLBACK_PATH = "/callback", DEFAULT_LOGIN_TIMEOUT_MS;
|
|
9432
|
+
var init_callback_server = __esm(() => {
|
|
9433
|
+
init_errors3();
|
|
9434
|
+
DEFAULT_LOGIN_TIMEOUT_MS = 5 * 60 * 1000;
|
|
9435
|
+
});
|
|
9436
|
+
|
|
9437
|
+
// src/cloud/pkce.ts
|
|
9438
|
+
import { createHash as createHash11, randomBytes } from "node:crypto";
|
|
9439
|
+
function base64UrlEncode(bytes) {
|
|
9440
|
+
return Buffer.from(bytes).toString("base64url");
|
|
9441
|
+
}
|
|
9442
|
+
function createCodeChallenge(verifier) {
|
|
9443
|
+
return base64UrlEncode(createHash11("sha256").update(verifier, "ascii").digest());
|
|
9444
|
+
}
|
|
9445
|
+
function createCodeVerifier(byteLength = 32) {
|
|
9446
|
+
return base64UrlEncode(randomBytes(byteLength));
|
|
9447
|
+
}
|
|
9448
|
+
function createState(byteLength = 24) {
|
|
9449
|
+
return base64UrlEncode(randomBytes(byteLength));
|
|
9450
|
+
}
|
|
9451
|
+
function createPkcePair(byteLength = 32) {
|
|
9452
|
+
const verifier = createCodeVerifier(byteLength);
|
|
9453
|
+
return { verifier, challenge: createCodeChallenge(verifier) };
|
|
9454
|
+
}
|
|
9455
|
+
var init_pkce = () => {};
|
|
9456
|
+
|
|
9457
|
+
// src/cloud/token.ts
|
|
9458
|
+
function mapTokenExchangeError(status, body) {
|
|
9459
|
+
const payload = extractErrorPayload(body);
|
|
9460
|
+
const reason = payload.message ?? "the server returned no error message";
|
|
9461
|
+
return new AutoragHttpError(`AutoRAG token exchange failed (HTTP ${status}): ${reason}`, {
|
|
9462
|
+
status,
|
|
9463
|
+
code: payload.code,
|
|
9464
|
+
type: payload.type
|
|
9465
|
+
});
|
|
9466
|
+
}
|
|
9467
|
+
async function exchangeCodeForToken(options) {
|
|
9468
|
+
const doFetch = options.fetchImpl ?? fetch;
|
|
9469
|
+
let response;
|
|
9470
|
+
try {
|
|
9471
|
+
response = await doFetch(`${normalizeBaseUrl(options.baseUrl)}${TOKEN_PATH}`, {
|
|
9472
|
+
method: "POST",
|
|
9473
|
+
headers: { "content-type": "application/json", accept: "application/json" },
|
|
9474
|
+
body: JSON.stringify({
|
|
9475
|
+
code: options.code,
|
|
9476
|
+
code_verifier: options.codeVerifier,
|
|
9477
|
+
redirect_uri: options.redirectUri
|
|
9478
|
+
}),
|
|
9479
|
+
signal: options.signal
|
|
9480
|
+
});
|
|
9481
|
+
} catch (cause) {
|
|
9482
|
+
if (options.signal?.aborted) {
|
|
9483
|
+
throw new AutoragOAuthError("AutoRAG sign-in was cancelled.", { cause });
|
|
9484
|
+
}
|
|
9485
|
+
throw new AutoragOAuthError(`AutoRAG token exchange could not reach ${normalizeBaseUrl(options.baseUrl)}.`, {
|
|
9486
|
+
cause
|
|
9487
|
+
});
|
|
8913
9488
|
}
|
|
8914
|
-
|
|
8915
|
-
|
|
8916
|
-
|
|
9489
|
+
let body;
|
|
9490
|
+
try {
|
|
9491
|
+
body = await response.json();
|
|
9492
|
+
} catch {
|
|
9493
|
+
body = undefined;
|
|
8917
9494
|
}
|
|
9495
|
+
if (!response.ok)
|
|
9496
|
+
throw mapTokenExchangeError(response.status, body);
|
|
9497
|
+
const accessToken = readAccessToken(body);
|
|
9498
|
+
if (accessToken === undefined) {
|
|
9499
|
+
throw new AutoragOAuthError("AutoRAG token exchange succeeded but returned no access token.");
|
|
9500
|
+
}
|
|
9501
|
+
const email = readEmail(body);
|
|
9502
|
+
return email === undefined ? { accessToken } : { accessToken, email };
|
|
8918
9503
|
}
|
|
8919
|
-
|
|
8920
|
-
|
|
8921
|
-
|
|
8922
|
-
|
|
8923
|
-
|
|
8924
|
-
return {
|
|
8925
|
-
name: EMIT_FAST_ANSWER_TOOL_NAME,
|
|
8926
|
-
label: "Emit Fast Answer",
|
|
8927
|
-
description: "Deliver the immediate first answer to the user. Call this exactly once during the fast phase with a complete, self-contained answer built only from the baseline retrieval evidence. Do not call any other tool before this one. The run continues afterwards for verification. A call whose answer cites a number missing from results, or whose refs name evidence that was not provided, is rejected; fix it and call again.",
|
|
8928
|
-
parameters: fastAnswerSchema,
|
|
8929
|
-
async execute(_toolCallId, params) {
|
|
8930
|
-
assertCitationsResolve(EMIT_FAST_ANSWER_TOOL_NAME, params.answer, params.results);
|
|
8931
|
-
const evidenceRefs = [];
|
|
8932
|
-
for (const result of params.results) {
|
|
8933
|
-
if (result.refs === undefined || result.refs.length === 0)
|
|
8934
|
-
continue;
|
|
8935
|
-
const refs = options.ledger.resolve(result.refs, {
|
|
8936
|
-
label: EMIT_FAST_ANSWER_TOOL_NAME,
|
|
8937
|
-
number: result.number,
|
|
8938
|
-
fallbackContent: result.summary,
|
|
8939
|
-
allowLocalFiles: false
|
|
8940
|
-
});
|
|
8941
|
-
if (refs.length > 0)
|
|
8942
|
-
evidenceRefs.push({ number: result.number, refs });
|
|
8943
|
-
}
|
|
8944
|
-
const details = {
|
|
8945
|
-
answer: params.answer,
|
|
8946
|
-
results: params.results.map((result) => ({
|
|
8947
|
-
number: result.number,
|
|
8948
|
-
title: result.title,
|
|
8949
|
-
summary: result.summary,
|
|
8950
|
-
evidence: (result.evidence ?? []).map((evidence) => evidence.lineNumber !== undefined ? { excerpt: evidence.excerpt, lineNumber: evidence.lineNumber } : { excerpt: evidence.excerpt }),
|
|
8951
|
-
...result.confidence !== undefined ? { confidence: result.confidence } : {}
|
|
8952
|
-
})),
|
|
8953
|
-
sources: evidenceRefs.flatMap((entry) => {
|
|
8954
|
-
const [primary] = entry.refs;
|
|
8955
|
-
return primary === undefined ? [] : [{ number: entry.number, source: primary.source }];
|
|
8956
|
-
}),
|
|
8957
|
-
evidenceRefs
|
|
8958
|
-
};
|
|
8959
|
-
capture(details);
|
|
8960
|
-
return {
|
|
8961
|
-
content: [
|
|
8962
|
-
{
|
|
8963
|
-
type: "text",
|
|
8964
|
-
text: "Fast answer delivered to the user. Stop now; a deeper verification pass follows separately."
|
|
8965
|
-
}
|
|
8966
|
-
],
|
|
8967
|
-
details
|
|
8968
|
-
};
|
|
8969
|
-
}
|
|
8970
|
-
};
|
|
9504
|
+
function readAccessToken(body) {
|
|
9505
|
+
if (typeof body !== "object" || body === null)
|
|
9506
|
+
return;
|
|
9507
|
+
const value = body.access_token;
|
|
9508
|
+
return typeof value === "string" && value !== "" ? value : undefined;
|
|
8971
9509
|
}
|
|
8972
|
-
|
|
8973
|
-
|
|
8974
|
-
|
|
8975
|
-
|
|
8976
|
-
|
|
8977
|
-
|
|
8978
|
-
|
|
8979
|
-
|
|
8980
|
-
|
|
8981
|
-
|
|
8982
|
-
|
|
8983
|
-
|
|
8984
|
-
|
|
8985
|
-
|
|
8986
|
-
|
|
8987
|
-
|
|
8988
|
-
|
|
8989
|
-
|
|
8990
|
-
|
|
9510
|
+
function readEmail(body) {
|
|
9511
|
+
if (typeof body !== "object" || body === null)
|
|
9512
|
+
return;
|
|
9513
|
+
const value = body.email;
|
|
9514
|
+
return typeof value === "string" && value !== "" ? value : undefined;
|
|
9515
|
+
}
|
|
9516
|
+
var init_token = __esm(() => {
|
|
9517
|
+
init_config();
|
|
9518
|
+
init_errors3();
|
|
9519
|
+
});
|
|
9520
|
+
|
|
9521
|
+
// src/cloud/oauth-login.ts
|
|
9522
|
+
function refreshAutoragCredentials(credentials) {
|
|
9523
|
+
return credentials;
|
|
9524
|
+
}
|
|
9525
|
+
async function loginAutorag(callbacks, options) {
|
|
9526
|
+
const { verifier, challenge } = createPkcePair();
|
|
9527
|
+
const state = createState();
|
|
9528
|
+
const server = await startCallbackServer({
|
|
9529
|
+
state,
|
|
9530
|
+
timeoutMs: options.timeoutMs ?? DEFAULT_LOGIN_TIMEOUT_MS,
|
|
9531
|
+
signal: callbacks.signal
|
|
8991
9532
|
});
|
|
9533
|
+
try {
|
|
9534
|
+
callbacks.onAuth({
|
|
9535
|
+
url: buildAuthorizeUrl({
|
|
9536
|
+
baseUrl: options.baseUrl,
|
|
9537
|
+
redirectUri: server.redirectUri,
|
|
9538
|
+
state,
|
|
9539
|
+
codeChallenge: challenge
|
|
9540
|
+
}),
|
|
9541
|
+
instructions: `Waiting for the AutoRAG sign-in callback on ${server.redirectUri}. If the browser cannot reach this machine, paste the final redirect URL or the code instead.`
|
|
9542
|
+
});
|
|
9543
|
+
callbacks.onProgress?.(`Listening for the AutoRAG sign-in callback on ${server.redirectUri}`);
|
|
9544
|
+
const outcome = await Promise.race([
|
|
9545
|
+
server.waitForCallback().then((params) => ({ params })),
|
|
9546
|
+
callbacks.onPrompt({
|
|
9547
|
+
message: "Complete the AutoRAG sign-in in your browser, or paste the final redirect URL / authorization code here:",
|
|
9548
|
+
placeholder: server.redirectUri,
|
|
9549
|
+
allowEmpty: true
|
|
9550
|
+
}).then((value) => ({ value }))
|
|
9551
|
+
]);
|
|
9552
|
+
const parsed = "params" in outcome ? parseCallbackQuery(outcome.params) : parseCallbackInput(outcome.value);
|
|
9553
|
+
const { code } = requireAuthorizationCode(parsed, state);
|
|
9554
|
+
const token = await exchangeCodeForToken({
|
|
9555
|
+
baseUrl: options.baseUrl,
|
|
9556
|
+
code,
|
|
9557
|
+
codeVerifier: verifier,
|
|
9558
|
+
redirectUri: server.redirectUri,
|
|
9559
|
+
signal: callbacks.signal,
|
|
9560
|
+
fetchImpl: options.fetchImpl
|
|
9561
|
+
});
|
|
9562
|
+
return {
|
|
9563
|
+
access: token.accessToken,
|
|
9564
|
+
refresh: "",
|
|
9565
|
+
expires: Number.MAX_SAFE_INTEGER,
|
|
9566
|
+
...token.email !== undefined ? { email: token.email } : {}
|
|
9567
|
+
};
|
|
9568
|
+
} finally {
|
|
9569
|
+
server.close();
|
|
9570
|
+
}
|
|
9571
|
+
}
|
|
9572
|
+
var init_oauth_login = __esm(() => {
|
|
9573
|
+
init_authorize();
|
|
9574
|
+
init_callback();
|
|
9575
|
+
init_callback_server();
|
|
9576
|
+
init_pkce();
|
|
9577
|
+
init_token();
|
|
8992
9578
|
});
|
|
8993
9579
|
|
|
8994
|
-
// src/
|
|
8995
|
-
|
|
8996
|
-
|
|
9580
|
+
// src/cloud/provider.ts
|
|
9581
|
+
async function refreshAutoragModels(context, endpoints) {
|
|
9582
|
+
const stored = modelsFromStore(context.stored);
|
|
9583
|
+
const apiKey = resolveCredentialKey(context.credential);
|
|
9584
|
+
if (!context.allowNetwork || apiKey === undefined)
|
|
9585
|
+
return stored;
|
|
9586
|
+
let models;
|
|
9587
|
+
try {
|
|
9588
|
+
models = await fetchModels({ baseUrl: endpoints.baseUrl, apiKey, signal: context.signal });
|
|
9589
|
+
} catch {
|
|
9590
|
+
return stored;
|
|
9591
|
+
}
|
|
9592
|
+
if (models.length === 0)
|
|
9593
|
+
return stored;
|
|
9594
|
+
try {
|
|
9595
|
+
await context.publish({ persist: buildStoreEntry(models, PROVIDER_ID, endpoints.apiBaseUrl) });
|
|
9596
|
+
} catch {}
|
|
9597
|
+
return models;
|
|
9598
|
+
}
|
|
9599
|
+
function createAutoRAGProviderConfig(env = process.env) {
|
|
9600
|
+
const baseUrl = resolveBaseUrl(env);
|
|
9601
|
+
const endpoints = { baseUrl, apiBaseUrl: `${baseUrl}${API_PATH}` };
|
|
8997
9602
|
return {
|
|
8998
|
-
name:
|
|
8999
|
-
|
|
9000
|
-
|
|
9001
|
-
|
|
9002
|
-
|
|
9003
|
-
|
|
9004
|
-
|
|
9005
|
-
|
|
9006
|
-
|
|
9007
|
-
|
|
9008
|
-
|
|
9009
|
-
}
|
|
9010
|
-
const request = {
|
|
9011
|
-
...params,
|
|
9012
|
-
query,
|
|
9013
|
-
maxResults: Math.min(params.maxResults ?? DEFAULT_MAX_RESULTS4, MAX_RESULTS_CAP3)
|
|
9014
|
-
};
|
|
9015
|
-
const result = await provider.searchFsearch(request);
|
|
9016
|
-
if (!result.ok) {
|
|
9017
|
-
return {
|
|
9018
|
-
content: [{ type: "text", text: `FSearch ${result.reason}: ${result.message}` }],
|
|
9019
|
-
details: { method: FSEARCH_SEARCH_TOOL_NAME, resultCount: 0, sources: [], results: [] }
|
|
9020
|
-
};
|
|
9021
|
-
}
|
|
9022
|
-
const lines = result.results.map((entry, index) => {
|
|
9023
|
-
const parts = [`[${index + 1}] ${entry.type} ${entry.path}`];
|
|
9024
|
-
if (entry.size !== undefined)
|
|
9025
|
-
parts.push(`size=${entry.size}`);
|
|
9026
|
-
if (entry.dateModified !== undefined)
|
|
9027
|
-
parts.push(`modified=${entry.dateModified}`);
|
|
9028
|
-
return parts.join(" ");
|
|
9029
|
-
});
|
|
9030
|
-
const backendLabel = result.backend === "walk" ? "FSearch slow filesystem walk (fsearch-cli unavailable)" : "FSearch";
|
|
9031
|
-
const limitNote = result.backend === "fsearch-cli" && (result.total ?? 0) > lines.length && lines.length === request.maxResults ? ` of ${result.total} total (limit reached; narrow the query or page with offset)` : "";
|
|
9032
|
-
const noteSuffix = result.note !== undefined ? `
|
|
9033
|
-
${result.note}` : "";
|
|
9034
|
-
const text = lines.length === 0 ? `${backendLabel} found no files or folders matching: ${query}${noteSuffix}` : `${backendLabel} found ${lines.length} item(s)${limitNote}:
|
|
9035
|
-
${lines.join(`
|
|
9036
|
-
`)}${noteSuffix}`;
|
|
9037
|
-
return {
|
|
9038
|
-
content: [{ type: "text", text }],
|
|
9039
|
-
details: {
|
|
9040
|
-
method: FSEARCH_SEARCH_TOOL_NAME,
|
|
9041
|
-
resultCount: result.results.length,
|
|
9042
|
-
sources: result.results.map((entry) => entry.path),
|
|
9043
|
-
results: result.results.map((entry, index) => ({ source: entry.path, excerpt: lines[index] }))
|
|
9044
|
-
}
|
|
9045
|
-
};
|
|
9046
|
-
}
|
|
9603
|
+
name: PROVIDER_NAME,
|
|
9604
|
+
baseUrl: endpoints.apiBaseUrl,
|
|
9605
|
+
api: "openai-responses",
|
|
9606
|
+
apiKey: API_KEY_CONFIG_VALUE,
|
|
9607
|
+
oauth: {
|
|
9608
|
+
name: PROVIDER_NAME,
|
|
9609
|
+
login: (callbacks) => loginAutorag(callbacks, { baseUrl }),
|
|
9610
|
+
refreshToken: async (credentials) => refreshAutoragCredentials(credentials),
|
|
9611
|
+
getApiKey: (credentials) => credentials.access
|
|
9612
|
+
},
|
|
9613
|
+
refreshModels: (context) => refreshAutoragModels(context, endpoints)
|
|
9047
9614
|
};
|
|
9048
9615
|
}
|
|
9049
|
-
|
|
9050
|
-
|
|
9051
|
-
|
|
9052
|
-
|
|
9053
|
-
|
|
9054
|
-
|
|
9055
|
-
|
|
9056
|
-
|
|
9057
|
-
matchPath: Type7.Optional(Type7.Boolean({ description: "Match against the full path instead of the name." })),
|
|
9058
|
-
kind: Type7.Optional(Type7.Union([Type7.Literal("files"), Type7.Literal("folders")])),
|
|
9059
|
-
path: Type7.Optional(Type7.String({ description: "Absolute folder to search within." })),
|
|
9060
|
-
sort: Type7.Optional(Type7.Union([
|
|
9061
|
-
Type7.Literal("name-ascending"),
|
|
9062
|
-
Type7.Literal("name-descending"),
|
|
9063
|
-
Type7.Literal("path-ascending"),
|
|
9064
|
-
Type7.Literal("path-descending"),
|
|
9065
|
-
Type7.Literal("size-ascending"),
|
|
9066
|
-
Type7.Literal("size-descending"),
|
|
9067
|
-
Type7.Literal("date-modified-ascending"),
|
|
9068
|
-
Type7.Literal("date-modified-descending")
|
|
9069
|
-
])),
|
|
9070
|
-
offset: Type7.Optional(Type7.Integer({ minimum: 0, description: "Skip this many results (pagination)." })),
|
|
9071
|
-
maxResults: Type7.Optional(Type7.Integer({
|
|
9072
|
-
minimum: 1,
|
|
9073
|
-
description: `Maximum results (default ${DEFAULT_MAX_RESULTS4}, cap ${MAX_RESULTS_CAP3}).`
|
|
9074
|
-
}))
|
|
9075
|
-
});
|
|
9616
|
+
async function registerAutoRAGProvider(runtime, env = process.env) {
|
|
9617
|
+
runtime.registerProvider(PROVIDER_ID, createAutoRAGProviderConfig(env));
|
|
9618
|
+
await runtime.refresh({ allowNetwork: false, providers: [PROVIDER_ID] });
|
|
9619
|
+
}
|
|
9620
|
+
var init_provider = __esm(() => {
|
|
9621
|
+
init_config();
|
|
9622
|
+
init_models();
|
|
9623
|
+
init_oauth_login();
|
|
9076
9624
|
});
|
|
9077
9625
|
|
|
9078
9626
|
// src/agent/pi-session.ts
|
|
@@ -9201,6 +9749,7 @@ async function createAutoRAGPiSession(options) {
|
|
|
9201
9749
|
authPath: join21(agentDir, "auth.json"),
|
|
9202
9750
|
modelsPath: join21(agentDir, "models.json")
|
|
9203
9751
|
});
|
|
9752
|
+
await registerAutoRAGProvider(modelRuntime);
|
|
9204
9753
|
await configureModelRuntime(modelRuntime, options.model, options.apiKey, options.providerApiKeys);
|
|
9205
9754
|
const customTools = [...options.customTools];
|
|
9206
9755
|
const extensionToolNames = [...options.extensionToolNames ?? []];
|
|
@@ -9250,6 +9799,7 @@ async function createAutoRAGPiInteractiveRuntime(options) {
|
|
|
9250
9799
|
authPath: join21(agentDir, "auth.json"),
|
|
9251
9800
|
modelsPath: join21(agentDir, "models.json")
|
|
9252
9801
|
});
|
|
9802
|
+
await registerAutoRAGProvider(modelRuntime);
|
|
9253
9803
|
await configureModelRuntime(modelRuntime, options.model, options.apiKey, options.providerApiKeys);
|
|
9254
9804
|
const sessionManager = options.sessionPath ? SessionManager.open(options.sessionPath, options.sessionDir, options.cwd) : SessionManager.create(options.cwd, options.sessionDir);
|
|
9255
9805
|
const createRuntime = async ({
|
|
@@ -9299,12 +9849,13 @@ async function createAutoRAGPiInteractiveRuntime(options) {
|
|
|
9299
9849
|
}
|
|
9300
9850
|
var PI_BUILTIN_TOOL_NAMES, EMBEDDED_AUTH_MARKER = "<autorag-embedded-model>";
|
|
9301
9851
|
var init_pi_session = __esm(() => {
|
|
9852
|
+
init_provider();
|
|
9302
9853
|
PI_BUILTIN_TOOL_NAMES = ["read", "bash", "edit", "write", "grep", "find", "ls"];
|
|
9303
9854
|
});
|
|
9304
9855
|
|
|
9305
9856
|
// src/agent/jev-extension.ts
|
|
9306
9857
|
import { Jev } from "jev-use";
|
|
9307
|
-
import { Type as
|
|
9858
|
+
import { Type as Type6 } from "typebox";
|
|
9308
9859
|
function createJevJudge(options = {}) {
|
|
9309
9860
|
let client;
|
|
9310
9861
|
return async (state, questions, callOptions = {}) => {
|
|
@@ -9357,32 +9908,32 @@ var JEV_TOOL_NAME = "jev", OPENROUTER_DEFAULT_MODEL = "typesafe/jev-1.13", BACKE
|
|
|
9357
9908
|
var init_jev_extension = __esm(() => {
|
|
9358
9909
|
init_pi_session();
|
|
9359
9910
|
BACKEND_DEFAULT_MODEL = { openrouter: OPENROUTER_DEFAULT_MODEL };
|
|
9360
|
-
jevQuestionSchema =
|
|
9361
|
-
id:
|
|
9362
|
-
type:
|
|
9911
|
+
jevQuestionSchema = Type6.Object({
|
|
9912
|
+
id: Type6.Optional(Type6.String({ description: "Caller-assigned id, echoed back in the verdict" })),
|
|
9913
|
+
type: Type6.Union([Type6.Literal("noul"), Type6.Literal("choice"), Type6.Literal("score")], {
|
|
9363
9914
|
description: "noul = P(yes), choice = pick one option, score = ordered level index"
|
|
9364
9915
|
}),
|
|
9365
|
-
question:
|
|
9916
|
+
question: Type6.String({
|
|
9366
9917
|
minLength: 1,
|
|
9367
9918
|
description: "One narrow question about the state. Jev answers exactly this."
|
|
9368
9919
|
}),
|
|
9369
|
-
options:
|
|
9920
|
+
options: Type6.Optional(Type6.Union([Type6.Array(Type6.String()), Type6.Record(Type6.String(), Type6.String())], {
|
|
9370
9921
|
description: "choice only: at least two option labels (or label -> meaning)"
|
|
9371
9922
|
})),
|
|
9372
|
-
levels:
|
|
9923
|
+
levels: Type6.Optional(Type6.Array(Type6.String(), {
|
|
9373
9924
|
description: "score only: at least two ordered level descriptions; the answer indexes into them"
|
|
9374
9925
|
})),
|
|
9375
|
-
criteria:
|
|
9926
|
+
criteria: Type6.Optional(Type6.Object({ true: Type6.String(), false: Type6.String() }, { description: "noul only: what yes and no mean, to sharpen calibration" }))
|
|
9376
9927
|
});
|
|
9377
|
-
jevParameters =
|
|
9378
|
-
state:
|
|
9928
|
+
jevParameters = Type6.Object({
|
|
9929
|
+
state: Type6.Unknown({
|
|
9379
9930
|
description: "Text, JSON object, or JSON array Jev should judge. Keep it small and self-contained."
|
|
9380
9931
|
}),
|
|
9381
|
-
questions:
|
|
9932
|
+
questions: Type6.Array(jevQuestionSchema, {
|
|
9382
9933
|
minItems: 1,
|
|
9383
9934
|
description: "Named questions, all evaluated against the same state in one batched request."
|
|
9384
9935
|
}),
|
|
9385
|
-
confidence_threshold:
|
|
9936
|
+
confidence_threshold: Type6.Optional(Type6.Number({
|
|
9386
9937
|
minimum: 0,
|
|
9387
9938
|
maximum: 1,
|
|
9388
9939
|
description: "Escalate any verdict below this confidence; omitted uses jev-use's per-source defaults"
|
|
@@ -9391,7 +9942,7 @@ var init_jev_extension = __esm(() => {
|
|
|
9391
9942
|
});
|
|
9392
9943
|
|
|
9393
9944
|
// src/agent/jikji-find-tool.ts
|
|
9394
|
-
import { Type as
|
|
9945
|
+
import { Type as Type7 } from "typebox";
|
|
9395
9946
|
function createJikjiFindTool(provider, ledger = new EvidenceLedger) {
|
|
9396
9947
|
return {
|
|
9397
9948
|
name: JIKJI_FIND_TOOL_NAME,
|
|
@@ -9522,10 +10073,10 @@ function formatDirective(policy) {
|
|
|
9522
10073
|
var JIKJI_FIND_TOOL_NAME = "jikji_find", jikjiFindSchema;
|
|
9523
10074
|
var init_jikji_find_tool = __esm(() => {
|
|
9524
10075
|
init_evidence_ledger();
|
|
9525
|
-
jikjiFindSchema =
|
|
9526
|
-
query:
|
|
9527
|
-
topK:
|
|
9528
|
-
first:
|
|
10076
|
+
jikjiFindSchema = Type7.Object({
|
|
10077
|
+
query: Type7.String({ description: "Query for Jikji local file discovery." }),
|
|
10078
|
+
topK: Type7.Optional(Type7.Integer({ description: "Maximum number of answer paths / candidates to return." })),
|
|
10079
|
+
first: Type7.Optional(Type7.Boolean({ description: "Return only the first/best answer." }))
|
|
9529
10080
|
});
|
|
9530
10081
|
});
|
|
9531
10082
|
|
|
@@ -10494,57 +11045,57 @@ var init_policy = __esm(() => {
|
|
|
10494
11045
|
});
|
|
10495
11046
|
|
|
10496
11047
|
// src/p2p/wire.ts
|
|
10497
|
-
import { Type as
|
|
11048
|
+
import { Type as Type8 } from "typebox";
|
|
10498
11049
|
var PeerRefusalCodeSchema, PeerDiagnosticSchema, PeerFileEntrySchema, PeerResultEntrySchema, PeerQueryRequestSchema, PeerQueryResponseSchema;
|
|
10499
11050
|
var init_wire = __esm(() => {
|
|
10500
|
-
PeerRefusalCodeSchema =
|
|
10501
|
-
|
|
10502
|
-
|
|
10503
|
-
|
|
10504
|
-
|
|
10505
|
-
|
|
10506
|
-
|
|
10507
|
-
|
|
11051
|
+
PeerRefusalCodeSchema = Type8.Union([
|
|
11052
|
+
Type8.Literal("auth-error"),
|
|
11053
|
+
Type8.Literal("replay-rejected"),
|
|
11054
|
+
Type8.Literal("rate-limited"),
|
|
11055
|
+
Type8.Literal("injection-detected"),
|
|
11056
|
+
Type8.Literal("policy-denied"),
|
|
11057
|
+
Type8.Literal("queue-full"),
|
|
11058
|
+
Type8.Literal("internal-error")
|
|
10508
11059
|
]);
|
|
10509
|
-
PeerDiagnosticSchema =
|
|
10510
|
-
code:
|
|
10511
|
-
message:
|
|
11060
|
+
PeerDiagnosticSchema = Type8.Object({
|
|
11061
|
+
code: Type8.String({ minLength: 1, description: "Diagnostic or refusal code" }),
|
|
11062
|
+
message: Type8.String({ description: "Human-readable diagnostic message" })
|
|
10512
11063
|
});
|
|
10513
|
-
PeerFileEntrySchema =
|
|
10514
|
-
source:
|
|
11064
|
+
PeerFileEntrySchema = Type8.Object({
|
|
11065
|
+
source: Type8.String({
|
|
10515
11066
|
description: "Canonical retrieval source identifier"
|
|
10516
11067
|
}),
|
|
10517
|
-
contentBase64:
|
|
10518
|
-
redacted:
|
|
11068
|
+
contentBase64: Type8.String({ description: "Base64-encoded file content" }),
|
|
11069
|
+
redacted: Type8.Boolean({ description: "Whether the content was PII-redacted" })
|
|
10519
11070
|
});
|
|
10520
|
-
PeerResultEntrySchema =
|
|
10521
|
-
number:
|
|
10522
|
-
title:
|
|
10523
|
-
summary:
|
|
10524
|
-
source:
|
|
11071
|
+
PeerResultEntrySchema = Type8.Object({
|
|
11072
|
+
number: Type8.Integer({ minimum: 1, description: "1-based result number" }),
|
|
11073
|
+
title: Type8.String({ minLength: 1, description: "Short title of the result" }),
|
|
11074
|
+
summary: Type8.String({ description: "Key insight summary" }),
|
|
11075
|
+
source: Type8.String({
|
|
10525
11076
|
description: "Canonical retrieval source identifier"
|
|
10526
11077
|
}),
|
|
10527
|
-
excerpt:
|
|
11078
|
+
excerpt: Type8.String({ description: "Supporting excerpt" })
|
|
10528
11079
|
});
|
|
10529
|
-
PeerQueryRequestSchema =
|
|
10530
|
-
v:
|
|
10531
|
-
query:
|
|
10532
|
-
topK:
|
|
10533
|
-
scope:
|
|
11080
|
+
PeerQueryRequestSchema = Type8.Object({
|
|
11081
|
+
v: Type8.Literal(1, { description: "Protocol version" }),
|
|
11082
|
+
query: Type8.String({ minLength: 1, maxLength: 4096, description: "Search query (max 4096 chars)" }),
|
|
11083
|
+
topK: Type8.Optional(Type8.Integer({ minimum: 1, maximum: 20, description: "Max results to return (max 20)" })),
|
|
11084
|
+
scope: Type8.Optional(Type8.String({ description: "Optional search scope hint" }))
|
|
10534
11085
|
});
|
|
10535
|
-
PeerQueryResponseSchema =
|
|
10536
|
-
v:
|
|
10537
|
-
status:
|
|
11086
|
+
PeerQueryResponseSchema = Type8.Object({
|
|
11087
|
+
v: Type8.Literal(1, { description: "Protocol version" }),
|
|
11088
|
+
status: Type8.Union([Type8.Literal("ok"), Type8.Literal("rejected")], {
|
|
10538
11089
|
description: "Response status"
|
|
10539
11090
|
}),
|
|
10540
|
-
answer:
|
|
10541
|
-
results:
|
|
11091
|
+
answer: Type8.String({ description: "Curated answer text" }),
|
|
11092
|
+
results: Type8.Array(PeerResultEntrySchema, {
|
|
10542
11093
|
description: "Curated result entries with opaque source ids"
|
|
10543
11094
|
}),
|
|
10544
|
-
files:
|
|
11095
|
+
files: Type8.Array(PeerFileEntrySchema, {
|
|
10545
11096
|
description: "Attached original files with opaque source ids"
|
|
10546
11097
|
}),
|
|
10547
|
-
diagnostics:
|
|
11098
|
+
diagnostics: Type8.Array(PeerDiagnosticSchema, {
|
|
10548
11099
|
description: "Diagnostic messages (degraded-mode, rejection reasons, etc.)"
|
|
10549
11100
|
})
|
|
10550
11101
|
});
|
|
@@ -10791,7 +11342,7 @@ var init_simplex_query_store = __esm(() => {
|
|
|
10791
11342
|
// src/p2p/simplex-server.ts
|
|
10792
11343
|
import { existsSync as existsSync19, mkdirSync as mkdirSync15, readFileSync as readFileSync16, writeFileSync as writeFileSync13 } from "node:fs";
|
|
10793
11344
|
import { join as join26 } from "node:path";
|
|
10794
|
-
import { Type as
|
|
11345
|
+
import { Type as Type9 } from "typebox";
|
|
10795
11346
|
import { Value as Value2 } from "typebox/value";
|
|
10796
11347
|
function targetTokens(value) {
|
|
10797
11348
|
return new Set((value.toLocaleLowerCase().match(TARGET_TOKEN_PATTERN) ?? []).filter((token) => token.length > 1));
|
|
@@ -11105,11 +11656,11 @@ var init_simplex_server = __esm(() => {
|
|
|
11105
11656
|
shareBytes: false,
|
|
11106
11657
|
redact: true
|
|
11107
11658
|
};
|
|
11108
|
-
SimplexWireEnvelopeSchema =
|
|
11109
|
-
v:
|
|
11110
|
-
kind:
|
|
11111
|
-
id:
|
|
11112
|
-
payload:
|
|
11659
|
+
SimplexWireEnvelopeSchema = Type9.Object({
|
|
11660
|
+
v: Type9.Literal(1, { description: "Envelope version" }),
|
|
11661
|
+
kind: Type9.Union([Type9.Literal("query"), Type9.Literal("response")], { description: "Payload kind" }),
|
|
11662
|
+
id: Type9.String({ minLength: 1, maxLength: 128, description: "Correlation id" }),
|
|
11663
|
+
payload: Type9.Unknown({ description: "PeerQueryRequest or PeerQueryResponse" })
|
|
11113
11664
|
});
|
|
11114
11665
|
TARGET_TOKEN_PATTERN = /[\p{L}\p{N}]+/gu;
|
|
11115
11666
|
PEERS_DIR = join26(".autorag", "p2p");
|
|
@@ -11122,7 +11673,7 @@ var init_simplex_server = __esm(() => {
|
|
|
11122
11673
|
});
|
|
11123
11674
|
|
|
11124
11675
|
// src/agent/peer-target-tool.ts
|
|
11125
|
-
import { Type as
|
|
11676
|
+
import { Type as Type10 } from "typebox";
|
|
11126
11677
|
function createRecommendPeerTargetsTool(workspacePath) {
|
|
11127
11678
|
return {
|
|
11128
11679
|
name: RECOMMEND_PEER_TARGETS_TOOL_NAME,
|
|
@@ -11155,8 +11706,8 @@ function createRecommendPeerTargetsTool(workspacePath) {
|
|
|
11155
11706
|
var RECOMMEND_PEER_TARGETS_TOOL_NAME = "recommend_peer_targets", recommendPeerTargetsSchema;
|
|
11156
11707
|
var init_peer_target_tool = __esm(() => {
|
|
11157
11708
|
init_simplex_server();
|
|
11158
|
-
recommendPeerTargetsSchema =
|
|
11159
|
-
query:
|
|
11709
|
+
recommendPeerTargetsSchema = Type10.Object({
|
|
11710
|
+
query: Type10.String({ description: "Question or topic to match against local peer personas." })
|
|
11160
11711
|
});
|
|
11161
11712
|
});
|
|
11162
11713
|
|
|
@@ -11232,7 +11783,7 @@ var MAX_DECOMPOSED_QUERIES = 5;
|
|
|
11232
11783
|
var init_query_decomposition = () => {};
|
|
11233
11784
|
|
|
11234
11785
|
// src/agent/query-peer-tool.ts
|
|
11235
|
-
import { Type as
|
|
11786
|
+
import { Type as Type11 } from "typebox";
|
|
11236
11787
|
function failure(alias, message) {
|
|
11237
11788
|
const details = { method: "query_peer_agent", ok: false, alias, message };
|
|
11238
11789
|
return { content: [{ type: "text", text: message }], details };
|
|
@@ -11347,11 +11898,11 @@ var init_query_peer_tool = __esm(() => {
|
|
|
11347
11898
|
init_simplex_query_store();
|
|
11348
11899
|
init_simplex_server();
|
|
11349
11900
|
init_evidence_ledger();
|
|
11350
|
-
queryPeerAgentSchema =
|
|
11351
|
-
alias:
|
|
11352
|
-
query:
|
|
11353
|
-
topK:
|
|
11354
|
-
scope:
|
|
11901
|
+
queryPeerAgentSchema = Type11.Object({
|
|
11902
|
+
alias: Type11.String({ minLength: 1 }),
|
|
11903
|
+
query: Type11.String({ minLength: 1, maxLength: 4096 }),
|
|
11904
|
+
topK: Type11.Optional(Type11.Integer({ minimum: 1, maximum: 20 })),
|
|
11905
|
+
scope: Type11.Optional(Type11.String())
|
|
11355
11906
|
});
|
|
11356
11907
|
});
|
|
11357
11908
|
|
|
@@ -11618,29 +12169,29 @@ function reconcileCitations(answer, results) {
|
|
|
11618
12169
|
]
|
|
11619
12170
|
};
|
|
11620
12171
|
}
|
|
11621
|
-
function
|
|
11622
|
-
|
|
11623
|
-
const results = details.results.map((result) => ({
|
|
12172
|
+
function toSearchResults(details, sourceByNumber) {
|
|
12173
|
+
return details.results.map((result) => ({
|
|
11624
12174
|
number: result.number,
|
|
11625
12175
|
title: result.title,
|
|
11626
12176
|
summary: result.summary,
|
|
11627
12177
|
evidence: result.evidence.map((evidence) => evidence.lineNumber !== undefined ? { excerpt: evidence.excerpt, lineNumber: evidence.lineNumber } : { excerpt: evidence.excerpt }),
|
|
11628
|
-
confidence: confidenceFrom(result.confidence
|
|
12178
|
+
...result.confidence !== undefined ? { confidence: confidenceFrom(result.confidence) } : {},
|
|
11629
12179
|
source: sourceByNumber.get(result.number)
|
|
11630
12180
|
}));
|
|
11631
|
-
|
|
12181
|
+
}
|
|
12182
|
+
function createPreliminarySearchDocumentsResponse(sessionId, query, details, diagnostics = []) {
|
|
12183
|
+
const sourceByNumber = new Map(details.mapping.map((entry) => [entry.number, entry.source]));
|
|
11632
12184
|
return {
|
|
11633
12185
|
sessionId,
|
|
11634
12186
|
query,
|
|
11635
|
-
results,
|
|
11636
|
-
answer:
|
|
12187
|
+
results: toSearchResults(details, sourceByNumber),
|
|
12188
|
+
answer: details.answer,
|
|
11637
12189
|
searched: details.results.length,
|
|
11638
12190
|
warnings: [],
|
|
11639
|
-
diagnostics: [...
|
|
12191
|
+
diagnostics: [...diagnostics]
|
|
11640
12192
|
};
|
|
11641
12193
|
}
|
|
11642
|
-
function createEmptySearchDocumentsResponse(sessionId, query,
|
|
11643
|
-
sessions.set(sessionId, { query, registry: new Map });
|
|
12194
|
+
function createEmptySearchDocumentsResponse(sessionId, query, diagnostics = []) {
|
|
11644
12195
|
return {
|
|
11645
12196
|
sessionId,
|
|
11646
12197
|
query,
|
|
@@ -11656,7 +12207,7 @@ function normalizeEntryEvidenceRefs(entry) {
|
|
|
11656
12207
|
const derivedRetrieverMix = Array.from(new Set(rawRefs.map((ref) => ref.method)));
|
|
11657
12208
|
return rawRefs.map((ref) => {
|
|
11658
12209
|
if (ref.excerpt === undefined && ref.content === undefined) {
|
|
11659
|
-
throw new Error("
|
|
12210
|
+
throw new Error("results: every evidenceRef must include excerpt or content");
|
|
11660
12211
|
}
|
|
11661
12212
|
return normalizeSessionEvidenceRef({
|
|
11662
12213
|
method: ref.method,
|
|
@@ -11677,19 +12228,11 @@ function normalizeEntryEvidenceRefs(entry) {
|
|
|
11677
12228
|
});
|
|
11678
12229
|
});
|
|
11679
12230
|
}
|
|
11680
|
-
function recordStructuredResultsSession(sessionId, query, details,
|
|
11681
|
-
assertResultsMappingOneToOne("
|
|
11682
|
-
const registry = new Map;
|
|
12231
|
+
function recordStructuredResultsSession(sessionId, query, details, memory, componentDiagnostics = [], options = {}) {
|
|
12232
|
+
assertResultsMappingOneToOne("results", details.results, details.mapping);
|
|
11683
12233
|
const memoryResults = [];
|
|
11684
12234
|
for (const entry of details.mapping) {
|
|
11685
12235
|
const evidenceRefs = normalizeEntryEvidenceRefs(entry);
|
|
11686
|
-
registry.set(entry.number, {
|
|
11687
|
-
index: entry.number,
|
|
11688
|
-
content: entry.content,
|
|
11689
|
-
source: entry.source,
|
|
11690
|
-
method: entry.method,
|
|
11691
|
-
evidenceRefs
|
|
11692
|
-
});
|
|
11693
12236
|
const emittedResult = details.results.find((result) => result.number === entry.number);
|
|
11694
12237
|
memoryResults.push({
|
|
11695
12238
|
number: entry.number,
|
|
@@ -11698,23 +12241,15 @@ function recordStructuredResultsSession(sessionId, query, details, sessions, mem
|
|
|
11698
12241
|
content: entry.content,
|
|
11699
12242
|
method: entry.method,
|
|
11700
12243
|
source: entry.source,
|
|
11701
|
-
...emittedResult !== undefined ? { confidence: confidenceFrom(emittedResult.confidence) } : {},
|
|
12244
|
+
...emittedResult?.confidence !== undefined ? { confidence: confidenceFrom(emittedResult.confidence) } : {},
|
|
11702
12245
|
evidenceRefs
|
|
11703
12246
|
});
|
|
11704
12247
|
}
|
|
11705
|
-
sessions.set(sessionId, { query, registry });
|
|
11706
12248
|
if (!options.isolateMemory) {
|
|
11707
12249
|
memory.recordCuratedResultsSession({ sessionId, query, results: memoryResults });
|
|
11708
12250
|
memory.save();
|
|
11709
12251
|
}
|
|
11710
|
-
const results = details.
|
|
11711
|
-
number: result.number,
|
|
11712
|
-
title: result.title,
|
|
11713
|
-
summary: result.summary,
|
|
11714
|
-
evidence: result.evidence.map((evidence) => evidence.lineNumber !== undefined ? { excerpt: evidence.excerpt, lineNumber: evidence.lineNumber } : { excerpt: evidence.excerpt }),
|
|
11715
|
-
confidence: confidenceFrom(result.confidence),
|
|
11716
|
-
source: registry.get(result.number)?.source || undefined
|
|
11717
|
-
}));
|
|
12252
|
+
const results = toSearchResults(details, new Map(details.mapping.map((entry) => [entry.number, entry.source || undefined])));
|
|
11718
12253
|
const citations = reconcileCitations(details.answer, results);
|
|
11719
12254
|
const answer = citations.answer;
|
|
11720
12255
|
const diagnostics = [...citations.diagnostics];
|
|
@@ -11744,7 +12279,7 @@ var init_search_documents = __esm(() => {
|
|
|
11744
12279
|
});
|
|
11745
12280
|
|
|
11746
12281
|
// src/agent/search-all-tool.ts
|
|
11747
|
-
import { Type as
|
|
12282
|
+
import { Type as Type12 } from "typebox";
|
|
11748
12283
|
function createSearchAllDocumentsTool(provider, ledger = new EvidenceLedger) {
|
|
11749
12284
|
return {
|
|
11750
12285
|
name: SEARCH_ALL_DOCUMENTS_TOOL_NAME,
|
|
@@ -11799,17 +12334,17 @@ var SEARCH_ALL_DOCUMENTS_TOOL_NAME = "search_all_documents", searchAllSchema;
|
|
|
11799
12334
|
var init_search_all_tool = __esm(() => {
|
|
11800
12335
|
init_evidence_ledger();
|
|
11801
12336
|
init_search_documents();
|
|
11802
|
-
searchAllSchema =
|
|
11803
|
-
query:
|
|
11804
|
-
topK:
|
|
12337
|
+
searchAllSchema = Type12.Object({
|
|
12338
|
+
query: Type12.String({ description: "Query to search across all configured retrieval methods." }),
|
|
12339
|
+
topK: Type12.Optional(Type12.Integer({
|
|
11805
12340
|
description: "Upper bound on returned evidence. Omit it to receive every distinct chunk the methods found; set it only when you deliberately want a shorter list."
|
|
11806
12341
|
})),
|
|
11807
|
-
scope:
|
|
12342
|
+
scope: Type12.Optional(Type12.String({ description: "Optional opaque virtual-path scope, e.g. /docs or /docs/**." }))
|
|
11808
12343
|
});
|
|
11809
12344
|
});
|
|
11810
12345
|
|
|
11811
12346
|
// src/agent/search-minsync-tool.ts
|
|
11812
|
-
import { Type as
|
|
12347
|
+
import { Type as Type13 } from "typebox";
|
|
11813
12348
|
function createSearchMinSyncDocumentsTool(getMethod, resolveScope = (scope) => scope, ledger = new EvidenceLedger) {
|
|
11814
12349
|
return {
|
|
11815
12350
|
name: SEARCH_MINSYNC_DOCUMENTS_TOOL_NAME,
|
|
@@ -11859,12 +12394,12 @@ var SEARCH_MINSYNC_DOCUMENTS_TOOL_NAME = "semantic_search_local_docs", searchMin
|
|
|
11859
12394
|
var init_search_minsync_tool = __esm(() => {
|
|
11860
12395
|
init_evidence_ledger();
|
|
11861
12396
|
init_search_documents();
|
|
11862
|
-
searchMinSyncSchema =
|
|
11863
|
-
query:
|
|
12397
|
+
searchMinSyncSchema = Type13.Object({
|
|
12398
|
+
query: Type13.String({
|
|
11864
12399
|
description: "Semantic query to search parsed document mirrors with MinSync vector retrieval."
|
|
11865
12400
|
}),
|
|
11866
|
-
topK:
|
|
11867
|
-
scope:
|
|
12401
|
+
topK: Type13.Optional(Type13.Integer({ description: "Maximum number of MinSync semantic chunks to return. Defaults to 50." })),
|
|
12402
|
+
scope: Type13.Optional(Type13.String({ description: "Optional opaque virtual-path scope, e.g. /docs or /docs/**." }))
|
|
11868
12403
|
});
|
|
11869
12404
|
});
|
|
11870
12405
|
|
|
@@ -11882,7 +12417,7 @@ function datasourceSearchToolName(datasourceId) {
|
|
|
11882
12417
|
}
|
|
11883
12418
|
|
|
11884
12419
|
// src/agent/search-single-datasource-tool.ts
|
|
11885
|
-
import { Type as
|
|
12420
|
+
import { Type as Type14 } from "typebox";
|
|
11886
12421
|
function createSingleDatasourceSearchTools(provider, specs, ledger = new EvidenceLedger) {
|
|
11887
12422
|
return specs.map((spec) => createTool(provider, spec, ledger));
|
|
11888
12423
|
}
|
|
@@ -11948,10 +12483,10 @@ var init_search_single_datasource_tool = __esm(() => {
|
|
|
11948
12483
|
init_evidence_ledger();
|
|
11949
12484
|
init_search_documents();
|
|
11950
12485
|
singleDatasourceToolName = datasourceSearchToolName;
|
|
11951
|
-
searchSingleDatasourceSchema =
|
|
11952
|
-
query:
|
|
11953
|
-
topK:
|
|
11954
|
-
scope:
|
|
12486
|
+
searchSingleDatasourceSchema = Type14.Object({
|
|
12487
|
+
query: Type14.String({ description: "Query to search within this datasource connection." }),
|
|
12488
|
+
topK: Type14.Optional(Type14.Integer({ description: "Maximum number of chunks to return. Defaults to 20." })),
|
|
12489
|
+
scope: Type14.Optional(Type14.String({ description: "Optional scope narrowing inside this datasource, e.g. one instance root." }))
|
|
11955
12490
|
});
|
|
11956
12491
|
});
|
|
11957
12492
|
|
|
@@ -12036,7 +12571,7 @@ ${input.skill}
|
|
|
12036
12571
|
|
|
12037
12572
|
${input.query}
|
|
12038
12573
|
|
|
12039
|
-
` + `When done,
|
|
12574
|
+
` + `When done, reply with a short report as your final message, with no tool call: what you changed (field: old → new), what you verified and how, ` + `and anything that still needs the user (for example an unset API-key environment variable, by name only). ` + `If you changed nothing, say why.`;
|
|
12040
12575
|
}
|
|
12041
12576
|
var SETUP_SKILL_RELATIVE_PATH;
|
|
12042
12577
|
var init_self_config = __esm(() => {
|
|
@@ -12067,7 +12602,6 @@ function buildSystemPrompt(config) {
|
|
|
12067
12602
|
toolLine(config, "check_memory", "inspect evidence earlier searches found for similar questions"),
|
|
12068
12603
|
toolLine(config, "recommend_peer_targets", "recommend local peer personas to ask about a topic without contacting them"),
|
|
12069
12604
|
toolLine(config, "query_peer_agent", "ask one trusted peer agent over SimpleX"),
|
|
12070
|
-
toolLine(config, "emit_autorag_results", "return the final structured answer with evidence ids for each result"),
|
|
12071
12605
|
...config.toolNames.filter((name) => name.startsWith("search_datasource_")).map((name) => `- **${name}**: search only the ${name.slice("search_datasource_".length).replace(/_/g, "-")} datasource connection, spawning no other datasource CLIs`),
|
|
12072
12606
|
...config.toolNames.filter((name) => ![
|
|
12073
12607
|
"bash",
|
|
@@ -12083,8 +12617,7 @@ function buildSystemPrompt(config) {
|
|
|
12083
12617
|
"jev",
|
|
12084
12618
|
"check_memory",
|
|
12085
12619
|
"recommend_peer_targets",
|
|
12086
|
-
"query_peer_agent"
|
|
12087
|
-
"emit_autorag_results"
|
|
12620
|
+
"query_peer_agent"
|
|
12088
12621
|
].includes(name) && !name.startsWith("search_datasource_")).map((name) => `- **${name}**: caller-provided tool`)
|
|
12089
12622
|
].filter((line) => line !== undefined);
|
|
12090
12623
|
const manifests = config.manifests.length === 0 ? "" : `
|
|
@@ -12148,12 +12681,12 @@ Your job is to retrieve candidates, read the relevant source material directly,
|
|
|
12148
12681
|
## Workflow
|
|
12149
12682
|
|
|
12150
12683
|
Searches follow a progressive, two-phase loop:
|
|
12151
|
-
1. **PLAN & FAST ANSWER** — Decide whether the query is answerable from general knowledge or memory. When baseline retrieval evidence is provided,
|
|
12684
|
+
1. **PLAN & FAST ANSWER** — Decide whether the query is answerable from general knowledge or memory. When baseline retrieval evidence is provided, write a complete, self-contained immediate first answer from that evidence as your reply, right away, without calling tools or waiting.
|
|
12152
12685
|
2. **EXPLORE & RETRIEVE** — Immediately following the fast answer, begin deeper exploration: ${discovery ? `use ${discovery} actively to locate relevant files and folders, and ` : ""}fan out across MinSync lexical/vector/hybrid retrieval, combined retrieval, and datasource search to expand candidates and fill evidence gaps.
|
|
12153
12686
|
3. **READ & VERIFY** — Use \`bash\` to open and verify relevant local files directly when needed, and in local sessions to organize files when the user asks (see File Organization); rely on Jikji and retrieval rather than blind directory browsing.
|
|
12154
12687
|
4. **JUDGE & RESOLVE** — Evaluate relevance, sufficiency, conflicts, and temporal context. When search results or evidence contain conflicting information, treat the freshest (most recent) information as authoritative and correct.
|
|
12155
12688
|
5. **CURATE** — Produce concise numbered knowledge units grounded in source evidence.
|
|
12156
|
-
6. **FINALIZE** —
|
|
12689
|
+
6. **FINALIZE** — End with the final answer as a plain reply, with no tool call. Earlier replies that are followed by a tool call are progress notes; only the last reply is the answer.
|
|
12157
12690
|
|
|
12158
12691
|
## Available Tools
|
|
12159
12692
|
|
|
@@ -12198,17 +12731,17 @@ ${fsearch}
|
|
|
12198
12731
|
${manifests}
|
|
12199
12732
|
## Output Format
|
|
12200
12733
|
|
|
12201
|
-
|
|
12202
|
-
-
|
|
12203
|
-
-
|
|
12204
|
-
-
|
|
12734
|
+
Your answer is your final reply, written as plain text, never as a tool call. Cite evidence inline with the ids the retrieval tools print next to each result:
|
|
12735
|
+
- Put the id in square brackets at the end of the sentence it supports, e.g. \`The cap is 28% [e3].\` Use \`[e3][e7]\` or \`[e3, e7]\` for several. Copy ids exactly as printed; never invent one.
|
|
12736
|
+
- For a local file you opened yourself with \`bash\`, cite \`[file:<absolute path>]\`.
|
|
12737
|
+
- The harness resolves every id to its recorded source, number the citations \`[1]\`, \`[2]\`, … in order of first appearance, and attaches the sources for you. Never type a source path, a chunk, or a citation number yourself.
|
|
12738
|
+
- A citation whose id no tool returned in this run is dropped, so cite only ids you saw.
|
|
12205
12739
|
|
|
12206
12740
|
## Answer Guidelines
|
|
12207
12741
|
|
|
12208
12742
|
- **Complete vs. delta answer**: When no first answer reached the caller, give the complete core answer. When a first answer was already delivered, return only the delta against it — corrections and newly verified findings — and never repeat its unchanged content; if nothing changed, confirm the first answer in one short line.
|
|
12209
12743
|
- **Bullet-point core answer**: Provide the core answer to the user's question in at most 5 bullet points. If additional explanation or context is necessary, append it after the bullet points.
|
|
12210
|
-
- **Direct answer only**: The caller only needs the answer to their question. Never include specific file paths, datasource descriptions, or retrieval mechanics/principles in
|
|
12211
|
-
- **Citation style**: Cite supporting evidence chunks using bracketed numbers only (e.g. [1], [2]). Do not quote raw chunk text or mention source paths directly in \`answer\`.
|
|
12744
|
+
- **Direct answer only**: The caller only needs the answer to their question. Never include specific file paths, datasource descriptions, or retrieval mechanics/principles in the answer (source paths are attached to each citation from the evidence ids you cite). Do not quote raw chunk text.
|
|
12212
12745
|
- ${ANSWER_CITATION_RULE}
|
|
12213
12746
|
- ${ANSWER_IMAGE_EMBED_RULE} ${ANSWER_IMAGE_DELTA_RULE}
|
|
12214
12747
|
- **No per-source negative reports**: Never report individual negative findings per source (e.g. "no information found in Slack" or "checked Drive but found nothing"). Simply omit unproductive sources from the answer and focus on what was found or provide a concise overall conclusion.
|
|
@@ -12221,7 +12754,7 @@ Call \`emit_autorag_results\` exactly once with:
|
|
|
12221
12754
|
- **Curate, don't dump**: return useful knowledge units, not raw search output.
|
|
12222
12755
|
- **Address intent**: answer the caller's actual need.
|
|
12223
12756
|
- **Preserve traceability**: cite evidence by the ids retrieval tools show, so source paths and excerpts are attached for you.
|
|
12224
|
-
- **Finalize once**: the
|
|
12757
|
+
- **Finalize once**: the last reply, with no tool call, is the final answer.
|
|
12225
12758
|
`;
|
|
12226
12759
|
}
|
|
12227
12760
|
var init_system_prompt = __esm(() => {
|
|
@@ -14208,7 +14741,7 @@ var init_render = __esm(() => {
|
|
|
14208
14741
|
});
|
|
14209
14742
|
|
|
14210
14743
|
// src/agent/web-fetch-tool.ts
|
|
14211
|
-
import { Type as
|
|
14744
|
+
import { Type as Type15 } from "typebox";
|
|
14212
14745
|
function truncateHead(output, maxBytes, maxLines) {
|
|
14213
14746
|
const lines = output.split(`
|
|
14214
14747
|
`);
|
|
@@ -14312,9 +14845,9 @@ var init_web_fetch_tool = __esm(() => {
|
|
|
14312
14845
|
init_render();
|
|
14313
14846
|
init_evidence_ledger();
|
|
14314
14847
|
FETCH_MAX_OUTPUT_BYTES = 50 * 1024;
|
|
14315
|
-
webFetchSchema =
|
|
14316
|
-
url:
|
|
14317
|
-
raw:
|
|
14848
|
+
webFetchSchema = Type15.Object({
|
|
14849
|
+
url: Type15.String({ description: "The http(s) URL to fetch and read." }),
|
|
14850
|
+
raw: Type15.Optional(Type15.Boolean({ description: "Return the raw response body without markdown rendering or formatting." }))
|
|
14318
14851
|
});
|
|
14319
14852
|
});
|
|
14320
14853
|
|
|
@@ -15273,7 +15806,7 @@ function parseResponse(data) {
|
|
|
15273
15806
|
} : {}
|
|
15274
15807
|
};
|
|
15275
15808
|
}
|
|
15276
|
-
var
|
|
15809
|
+
var DEFAULT_BASE_URL2 = "https://generativelanguage.googleapis.com", API_VERSION = "v1beta", DEFAULT_MODEL = "gemini-3.8-flash", MAX_RESPONSE_BYTES, MAX_ERROR_BYTES, GeminiProvider;
|
|
15277
15810
|
var init_gemini = __esm(() => {
|
|
15278
15811
|
init_model_auth();
|
|
15279
15812
|
init_query();
|
|
@@ -15295,7 +15828,7 @@ var init_gemini = __esm(() => {
|
|
|
15295
15828
|
const model = envCredential("GEMINI_SEARCH_MODEL") ?? (credential.source === "injected" ? credential.modelId : undefined) ?? DEFAULT_MODEL;
|
|
15296
15829
|
const parsed = params.parsedQuery ?? parseSearchQuery(params.query);
|
|
15297
15830
|
const query = parsed.hasDirectives ? formatQuery(parsed, GOOGLE_QUERY_SYNTAX) : params.query;
|
|
15298
|
-
const baseUrl = (credential.baseUrl ??
|
|
15831
|
+
const baseUrl = (credential.baseUrl ?? DEFAULT_BASE_URL2).replace(/\/+$/, "");
|
|
15299
15832
|
const fetchImpl = params.fetch ?? fetch;
|
|
15300
15833
|
const response = await fetchImpl(`${baseUrl}/${API_VERSION}/models/${model}:generateContent`, {
|
|
15301
15834
|
method: "POST",
|
|
@@ -15440,7 +15973,7 @@ function parseResponse2(response) {
|
|
|
15440
15973
|
...response.id !== undefined ? { requestId: response.id } : {}
|
|
15441
15974
|
};
|
|
15442
15975
|
}
|
|
15443
|
-
var
|
|
15976
|
+
var DEFAULT_BASE_URL3 = "https://api.anthropic.com", DEFAULT_MODEL2 = "claude-haiku-5-5", DEFAULT_MAX_TOKENS2 = 4096, MAX_RESPONSE_BYTES2, MAX_ERROR_BYTES2, WEB_SEARCH_TOOL_TYPE = "web_search_20250305", ANTHROPIC_QUERY_SYNTAX, AnthropicProvider;
|
|
15444
15977
|
var init_anthropic = __esm(() => {
|
|
15445
15978
|
init_model_auth();
|
|
15446
15979
|
init_query();
|
|
@@ -15471,7 +16004,7 @@ var init_anthropic = __esm(() => {
|
|
|
15471
16004
|
const model = envCredential("ANTHROPIC_SEARCH_MODEL") ?? (credential.source === "injected" ? credential.modelId : undefined) ?? DEFAULT_MODEL2;
|
|
15472
16005
|
const parsed = params.parsedQuery ?? parseSearchQuery(params.query);
|
|
15473
16006
|
const plan = planQuery(params.query, parsed);
|
|
15474
|
-
const baseUrl = (credential.baseUrl ??
|
|
16007
|
+
const baseUrl = (credential.baseUrl ?? DEFAULT_BASE_URL3).replace(/\/+$/, "");
|
|
15475
16008
|
const fetchImpl = params.fetch ?? fetch;
|
|
15476
16009
|
const response = await fetchImpl(`${baseUrl}/v1/messages?beta=true`, {
|
|
15477
16010
|
method: "POST",
|
|
@@ -15483,7 +16016,7 @@ var init_anthropic = __esm(() => {
|
|
|
15483
16016
|
},
|
|
15484
16017
|
body: JSON.stringify({
|
|
15485
16018
|
model,
|
|
15486
|
-
max_tokens: params.maxOutputTokens ??
|
|
16019
|
+
max_tokens: params.maxOutputTokens ?? DEFAULT_MAX_TOKENS2,
|
|
15487
16020
|
...params.systemPrompt ? { system: params.systemPrompt } : {},
|
|
15488
16021
|
messages: [{ role: "user", content: plan.query }],
|
|
15489
16022
|
tools: [
|
|
@@ -17566,7 +18099,7 @@ async function searchPublicWeb(params, deadlines = {}) {
|
|
|
17566
18099
|
}
|
|
17567
18100
|
var PUBLIC_ENGINE_IDS, DEFAULT_NUM_RESULTS8 = 15, MAX_NUM_RESULTS8 = 30, SOFT_DEADLINE_MS = 5000, HARD_DEADLINE_MS = 30000, PublicWebProvider;
|
|
17568
18101
|
var init_public = __esm(() => {
|
|
17569
|
-
|
|
18102
|
+
init_provider2();
|
|
17570
18103
|
init_types3();
|
|
17571
18104
|
init_utils();
|
|
17572
18105
|
PUBLIC_ENGINE_IDS = [
|
|
@@ -17640,7 +18173,7 @@ function resolveProviderCandidates(routing = {}) {
|
|
|
17640
18173
|
return candidates;
|
|
17641
18174
|
}
|
|
17642
18175
|
var PROVIDER_META, instanceCache;
|
|
17643
|
-
var
|
|
18176
|
+
var init_provider2 = __esm(() => {
|
|
17644
18177
|
init_types3();
|
|
17645
18178
|
init_types3();
|
|
17646
18179
|
PROVIDER_META = {
|
|
@@ -17826,15 +18359,15 @@ async function executeWebSearch(params, options = {}) {
|
|
|
17826
18359
|
}
|
|
17827
18360
|
var TOTAL_TIMEOUT_MULTIPLIER = 2;
|
|
17828
18361
|
var init_search = __esm(() => {
|
|
17829
|
-
|
|
18362
|
+
init_provider2();
|
|
17830
18363
|
init_query();
|
|
17831
18364
|
init_types3();
|
|
17832
|
-
|
|
18365
|
+
init_provider2();
|
|
17833
18366
|
init_types3();
|
|
17834
18367
|
});
|
|
17835
18368
|
|
|
17836
18369
|
// src/agent/web-search-tool.ts
|
|
17837
|
-
import { Type as
|
|
18370
|
+
import { Type as Type16 } from "typebox";
|
|
17838
18371
|
function createWebSearchTool(options = {}, ledger = new EvidenceLedger) {
|
|
17839
18372
|
return {
|
|
17840
18373
|
name: WEB_SEARCH_TOOL_NAME,
|
|
@@ -17910,15 +18443,15 @@ var WEB_SEARCH_TOOL_NAME = "web_search", webSearchSchema;
|
|
|
17910
18443
|
var init_web_search_tool = __esm(() => {
|
|
17911
18444
|
init_search();
|
|
17912
18445
|
init_evidence_ledger();
|
|
17913
|
-
webSearchSchema =
|
|
17914
|
-
query:
|
|
18446
|
+
webSearchSchema = Type16.Object({
|
|
18447
|
+
query: Type16.String({
|
|
17915
18448
|
description: 'Search query. Supports Google-style directives: site:/-site:, after:/before: (YYYY-MM-DD), inurl:, intitle:, filetype:, "exact phrase", -term, OR.'
|
|
17916
18449
|
}),
|
|
17917
|
-
recency:
|
|
18450
|
+
recency: Type16.Optional(Type16.Union([Type16.Literal("day"), Type16.Literal("week"), Type16.Literal("month"), Type16.Literal("year")], {
|
|
17918
18451
|
description: "Optional recency window for results (pure time filter)."
|
|
17919
18452
|
})),
|
|
17920
|
-
limit:
|
|
17921
|
-
num_search_results:
|
|
18453
|
+
limit: Type16.Optional(Type16.Integer({ description: "Maximum number of results to return." })),
|
|
18454
|
+
num_search_results: Type16.Optional(Type16.Integer({ description: "Alias for limit (result count hint)." }))
|
|
17922
18455
|
});
|
|
17923
18456
|
});
|
|
17924
18457
|
|
|
@@ -17965,10 +18498,7 @@ class AutoRAGAgent {
|
|
|
17965
18498
|
runLogger;
|
|
17966
18499
|
lastQuery;
|
|
17967
18500
|
lastSessionId;
|
|
17968
|
-
sessions = new Map;
|
|
17969
18501
|
activeRun = false;
|
|
17970
|
-
resultCapture;
|
|
17971
|
-
interactiveFastAnswerCallback;
|
|
17972
18502
|
modelNativeSearchAuth;
|
|
17973
18503
|
retrievalTrace = [];
|
|
17974
18504
|
evidenceLedger = new EvidenceLedger;
|
|
@@ -18130,10 +18660,6 @@ class AutoRAGAgent {
|
|
|
18130
18660
|
const searchMinSyncTool = createSearchMinSyncDocumentsTool(() => this.remoteFilteredRetrievalMethod(this.minSyncMethod), (scope) => this.resolveRetrievalScope(scope), this.evidenceLedger);
|
|
18131
18661
|
const searchAllTool = createSearchAllDocumentsTool(this, this.evidenceLedger);
|
|
18132
18662
|
const loadDatasourceSkillTool = createLoadDatasourceSkillTool(this);
|
|
18133
|
-
const emitResultsTool = createEmitResultsTool((details) => this.resultCapture?.(details), {
|
|
18134
|
-
ledger: this.evidenceLedger,
|
|
18135
|
-
allowLocalFiles: !this.remoteSession
|
|
18136
|
-
});
|
|
18137
18663
|
const scanDuplicateDocumentsTool = this.dupeyOptions === false ? undefined : createScanDuplicateDocumentsTool(this);
|
|
18138
18664
|
this.jevJudge = options.jev === undefined || options.jev === false || this.remoteSession ? undefined : createJevJudge(options.jev);
|
|
18139
18665
|
this.jevExtension = this.jevJudge === undefined ? undefined : createJevExtension(this.jevJudge);
|
|
@@ -18168,8 +18694,6 @@ class AutoRAGAgent {
|
|
|
18168
18694
|
"check_memory",
|
|
18169
18695
|
...singleDatasourceTools.map((tool) => tool.name),
|
|
18170
18696
|
LOAD_DATASOURCE_SKILL_TOOL_NAME,
|
|
18171
|
-
EMIT_AUTORAG_RESULTS_TOOL_NAME,
|
|
18172
|
-
EMIT_FAST_ANSWER_TOOL_NAME,
|
|
18173
18697
|
SEARCH_MINSYNC_DOCUMENTS_TOOL_NAME,
|
|
18174
18698
|
SEARCH_ALL_DOCUMENTS_TOOL_NAME,
|
|
18175
18699
|
JIKJI_FIND_TOOL_NAME,
|
|
@@ -18200,7 +18724,6 @@ class AutoRAGAgent {
|
|
|
18200
18724
|
loadDatasourceSkillTool,
|
|
18201
18725
|
...webSearchTool !== undefined ? [webSearchTool] : [],
|
|
18202
18726
|
...webFetchTool !== undefined ? [webFetchTool] : [],
|
|
18203
|
-
emitResultsTool,
|
|
18204
18727
|
...scanDuplicateDocumentsTool !== undefined ? [scanDuplicateDocumentsTool] : [],
|
|
18205
18728
|
...jikjiFindTool !== undefined ? [jikjiFindTool] : [],
|
|
18206
18729
|
...everythingSearchTool !== undefined ? [everythingSearchTool] : [],
|
|
@@ -18347,12 +18870,11 @@ ${context.text}
|
|
|
18347
18870
|
source: "memory"
|
|
18348
18871
|
};
|
|
18349
18872
|
}
|
|
18350
|
-
const registry = this.sessions.get(sessionId)?.registry;
|
|
18351
18873
|
const resultByNumber = new Map(details.results.map((result) => [result.number, result]));
|
|
18352
18874
|
const units = [];
|
|
18353
18875
|
for (const entry of details.mapping) {
|
|
18354
18876
|
const result = resultByNumber.get(entry.number);
|
|
18355
|
-
const refs =
|
|
18877
|
+
const refs = normalizeEntryEvidenceRefs(entry);
|
|
18356
18878
|
if (result === undefined || refs.length === 0)
|
|
18357
18879
|
continue;
|
|
18358
18880
|
for (const ref of refs) {
|
|
@@ -18433,7 +18955,7 @@ ${context.text}
|
|
|
18433
18955
|
providerApiKeys: { [local.provider]: local.apiKey }
|
|
18434
18956
|
};
|
|
18435
18957
|
}
|
|
18436
|
-
async createSearchSession(resolved, systemPrompt
|
|
18958
|
+
async createSearchSession(resolved, systemPrompt) {
|
|
18437
18959
|
if (this.boundPiRuntime !== undefined) {
|
|
18438
18960
|
const session = this.boundPiRuntime.session;
|
|
18439
18961
|
return {
|
|
@@ -18453,10 +18975,7 @@ ${context.text}
|
|
|
18453
18975
|
apiKey: resolved.apiKey,
|
|
18454
18976
|
providerApiKeys: resolved.providerApiKeys,
|
|
18455
18977
|
getSystemPrompt: () => systemPrompt,
|
|
18456
|
-
customTools:
|
|
18457
|
-
...this.tools.filter((tool) => !PI_BUILTIN_TOOL_NAMES.includes(tool.name)),
|
|
18458
|
-
...extraTools
|
|
18459
|
-
],
|
|
18978
|
+
customTools: this.tools.filter((tool) => !PI_BUILTIN_TOOL_NAMES.includes(tool.name)),
|
|
18460
18979
|
remoteSession: this.remoteSession,
|
|
18461
18980
|
contextTransform: (messages) => this.withMemoryContext(messages),
|
|
18462
18981
|
...this.jevExtension !== undefined ? { extensionFactories: [this.jevExtension], extensionToolNames: [JEV_TOOL_NAME] } : {}
|
|
@@ -18537,19 +19056,12 @@ ${context.text}
|
|
|
18537
19056
|
modelId: this.boundPiRuntime?.session.model?.id ?? resolved?.model.id
|
|
18538
19057
|
})),
|
|
18539
19058
|
contextTransform: (messages) => this.withMemoryContext(messages),
|
|
18540
|
-
customTools:
|
|
18541
|
-
...this.tools.filter((tool) => !PI_BUILTIN_TOOL_NAMES.includes(tool.name)),
|
|
18542
|
-
createEmitFastAnswerTool((details) => this.interactiveFastAnswerCallback?.(details), {
|
|
18543
|
-
ledger: this.evidenceLedger
|
|
18544
|
-
})
|
|
18545
|
-
],
|
|
19059
|
+
customTools: this.tools.filter((tool) => !PI_BUILTIN_TOOL_NAMES.includes(tool.name)),
|
|
18546
19060
|
onQuery: (query, pi) => this.runInteractivePiQuery(query, pi),
|
|
18547
|
-
inactiveToolNames: [EMIT_FAST_ANSWER_TOOL_NAME],
|
|
18548
19061
|
...this.jevExtension !== undefined ? { extensionFactories: [this.jevExtension], extensionToolNames: [JEV_TOOL_NAME] } : {},
|
|
18549
19062
|
...this.updateNotice === undefined ? {} : { updateNotice: this.updateNotice }
|
|
18550
19063
|
});
|
|
18551
19064
|
this.boundPiRuntime = runtime.runtime;
|
|
18552
|
-
runtime.runtime.session.setActiveToolsByName(runtime.runtime.session.getActiveToolNames().filter((name) => name !== EMIT_FAST_ANSWER_TOOL_NAME));
|
|
18553
19065
|
const dispose = runtime.dispose;
|
|
18554
19066
|
return {
|
|
18555
19067
|
...runtime,
|
|
@@ -18560,17 +19072,14 @@ ${context.text}
|
|
|
18560
19072
|
}
|
|
18561
19073
|
};
|
|
18562
19074
|
}
|
|
19075
|
+
deriveAnswer(text) {
|
|
19076
|
+
const derived = deriveResultsFromAnswer(text, this.evidenceLedger, { allowLocalFiles: !this.remoteSession });
|
|
19077
|
+
this.routingDiagnostics.push(...derived.diagnostics);
|
|
19078
|
+
return derived.details;
|
|
19079
|
+
}
|
|
18563
19080
|
async runInteractivePiQuery(query, pi) {
|
|
18564
19081
|
pi.setSessionName(query.slice(0, 80));
|
|
18565
|
-
for await (const
|
|
18566
|
-
const text = event.type === "progress" ? event.text : event.response.answer;
|
|
18567
|
-
pi.sendMessage({
|
|
18568
|
-
customType: `autorag.${event.type}`,
|
|
18569
|
-
content: [{ type: "text", text }],
|
|
18570
|
-
display: true,
|
|
18571
|
-
details: event
|
|
18572
|
-
}, { triggerTurn: false });
|
|
18573
|
-
}
|
|
19082
|
+
for await (const _event of this.searchDocumentsStream(query)) {}
|
|
18574
19083
|
}
|
|
18575
19084
|
abort() {
|
|
18576
19085
|
this.activeSession?.abort();
|
|
@@ -18601,11 +19110,6 @@ ${context.text}
|
|
|
18601
19110
|
this.refreshing = false;
|
|
18602
19111
|
}
|
|
18603
19112
|
}
|
|
18604
|
-
getResultRegistry(sessionId) {
|
|
18605
|
-
const sid = sessionId ?? this.lastSessionId;
|
|
18606
|
-
const session = sid ? this.sessions.get(sid) : undefined;
|
|
18607
|
-
return session?.registry ?? new Map;
|
|
18608
|
-
}
|
|
18609
19113
|
async searchDocuments(query, options = {}) {
|
|
18610
19114
|
if (this.activeRun) {
|
|
18611
19115
|
throw new Error("AutoRAG agent is busy; await the in-flight searchDocuments() call before starting another");
|
|
@@ -18617,7 +19121,7 @@ ${context.text}
|
|
|
18617
19121
|
if (trimmedQuery.length === 0) {
|
|
18618
19122
|
this.lastQuery = trimmedQuery;
|
|
18619
19123
|
this.lastSessionId = sessionId;
|
|
18620
|
-
return createEmptySearchDocumentsResponse(sessionId, trimmedQuery, this.
|
|
19124
|
+
return createEmptySearchDocumentsResponse(sessionId, trimmedQuery, this.startupDiagnostics);
|
|
18621
19125
|
}
|
|
18622
19126
|
options = this.normalizeRetrievalOptions(options);
|
|
18623
19127
|
if (this.remoteSession && options.observedSources !== undefined)
|
|
@@ -18653,11 +19157,7 @@ ${context.text}
|
|
|
18653
19157
|
publishPreliminary(details);
|
|
18654
19158
|
};
|
|
18655
19159
|
let session;
|
|
18656
|
-
this.interactiveFastAnswerCallback = emitPreliminary;
|
|
18657
19160
|
let unsubscribers = [];
|
|
18658
|
-
this.resultCapture = (details) => {
|
|
18659
|
-
captured = details;
|
|
18660
|
-
};
|
|
18661
19161
|
let searchStarted = false;
|
|
18662
19162
|
try {
|
|
18663
19163
|
const resolved = await this.resolveSessionModel();
|
|
@@ -18675,7 +19175,7 @@ ${context.text}
|
|
|
18675
19175
|
model: resolved.model.id
|
|
18676
19176
|
});
|
|
18677
19177
|
searchStarted = true;
|
|
18678
|
-
session = await this.createSearchSession(resolved, buildSystemPrompt(this.currentSystemPromptConfig({ modelId: resolved.model.id }))
|
|
19178
|
+
session = await this.createSearchSession(resolved, buildSystemPrompt(this.currentSystemPromptConfig({ modelId: resolved.model.id })));
|
|
18679
19179
|
this.activeSession = session;
|
|
18680
19180
|
unsubscribers = this.configureSearchSession(session);
|
|
18681
19181
|
let timeout;
|
|
@@ -18684,45 +19184,36 @@ ${context.text}
|
|
|
18684
19184
|
await Promise.race([
|
|
18685
19185
|
(async () => {
|
|
18686
19186
|
const plan = await this.planQuery(trimmedQuery, resolved, planAbort.signal);
|
|
18687
|
-
const sessionAgent = session.piSession;
|
|
18688
19187
|
const activeSession = session;
|
|
18689
|
-
const
|
|
18690
|
-
|
|
18691
|
-
|
|
18692
|
-
|
|
18693
|
-
|
|
18694
|
-
|
|
18695
|
-
|
|
18696
|
-
|
|
18697
|
-
activeSession.agent.state.thinkingLevel = clampThinkingLevel(resolved.model, this.fastThinkingLevel);
|
|
18698
|
-
activeSession.agent.state.tools = [
|
|
18699
|
-
...this.tools,
|
|
18700
|
-
{ name: EMIT_FAST_ANSWER_TOOL_NAME }
|
|
18701
|
-
];
|
|
18702
|
-
}
|
|
19188
|
+
const sessionAgent = activeSession.piSession;
|
|
19189
|
+
const transcript = () => sessionAgent?.messages ?? activeSession.agent.state.messages;
|
|
19190
|
+
const setThinking = (level) => {
|
|
19191
|
+
const clamped = clampThinkingLevel(resolved.model, level);
|
|
19192
|
+
if (sessionAgent !== undefined)
|
|
19193
|
+
sessionAgent.setThinkingLevel(clamped);
|
|
19194
|
+
else
|
|
19195
|
+
activeSession.agent.state.thinkingLevel = clamped;
|
|
18703
19196
|
};
|
|
18704
19197
|
if (plan.route === "config" && plan.selfConfigSkill !== undefined && this.selfConfig !== undefined) {
|
|
18705
19198
|
selfConfigRun = true;
|
|
18706
19199
|
mkdirSync17(this.workspaceProjectRoot, { recursive: true });
|
|
18707
19200
|
const previousTools = sessionAgent?.getActiveToolNames();
|
|
18708
|
-
|
|
18709
|
-
|
|
18710
|
-
sessionAgent.setActiveToolsByName([...PI_BUILTIN_TOOL_NAMES
|
|
18711
|
-
|
|
18712
|
-
activeSession.agent.state.
|
|
18713
|
-
activeSession.agent.state.tools = this.tools.filter((tool) => tool.name === EMIT_AUTORAG_RESULTS_TOOL_NAME);
|
|
18714
|
-
}
|
|
19201
|
+
setThinking(this.finalThinkingLevel);
|
|
19202
|
+
if (sessionAgent !== undefined)
|
|
19203
|
+
sessionAgent.setActiveToolsByName([...PI_BUILTIN_TOOL_NAMES]);
|
|
19204
|
+
else
|
|
19205
|
+
activeSession.agent.state.tools = [];
|
|
18715
19206
|
const configBefore = snapshotConfigFile(this.selfConfig.configPath);
|
|
18716
19207
|
try {
|
|
18717
|
-
await
|
|
19208
|
+
await activeSession.prompt(buildSelfConfigPrompt({
|
|
18718
19209
|
query: trimmedQuery,
|
|
18719
19210
|
configPath: this.selfConfig.configPath,
|
|
18720
19211
|
agentDir: this.piAgentDir ?? getAgentDir2(),
|
|
18721
19212
|
skill: plan.selfConfigSkill
|
|
18722
19213
|
}));
|
|
18723
|
-
|
|
18724
|
-
|
|
18725
|
-
|
|
19214
|
+
const report = finalAnswerText(transcript());
|
|
19215
|
+
if (report !== undefined)
|
|
19216
|
+
captured = this.deriveAnswer(report);
|
|
18726
19217
|
const rolledBack = await rollbackIfBroken(this.selfConfig, configBefore);
|
|
18727
19218
|
if (rolledBack !== undefined) {
|
|
18728
19219
|
this.routingDiagnostics.push({
|
|
@@ -18731,11 +19222,10 @@ ${context.text}
|
|
|
18731
19222
|
message: `The edited config did not validate, so the previous config was restored. ${rolledBack}`,
|
|
18732
19223
|
source: "self-config"
|
|
18733
19224
|
});
|
|
18734
|
-
|
|
18735
|
-
if (emitted !== undefined) {
|
|
19225
|
+
if (captured !== undefined) {
|
|
18736
19226
|
captured = {
|
|
18737
|
-
...
|
|
18738
|
-
answer: `${
|
|
19227
|
+
...captured,
|
|
19228
|
+
answer: `${captured.answer}
|
|
18739
19229
|
|
|
18740
19230
|
Warning: the edited config did not validate, so the previous config was restored (nothing was changed). Problem: ${rolledBack}`
|
|
18741
19231
|
};
|
|
@@ -18749,49 +19239,35 @@ Warning: the edited config did not validate, so the previous config was restored
|
|
|
18749
19239
|
return;
|
|
18750
19240
|
}
|
|
18751
19241
|
if (plan.route === "direct") {
|
|
18752
|
-
|
|
18753
|
-
await
|
|
18754
|
-
const answer =
|
|
19242
|
+
setThinking(this.fastThinkingLevel);
|
|
19243
|
+
await activeSession.prompt(this.buildDirectAnswerPrompt(trimmedQuery));
|
|
19244
|
+
const answer = finalAnswerText(transcript());
|
|
18755
19245
|
if (answer !== undefined)
|
|
18756
|
-
captured =
|
|
19246
|
+
captured = this.deriveAnswer(answer);
|
|
18757
19247
|
return;
|
|
18758
19248
|
}
|
|
18759
19249
|
const baseline = await this.prefetchInitialRetrievalContext(trimmedQuery, plan.queries, options, plan.datasources);
|
|
18760
|
-
|
|
18761
|
-
await
|
|
18762
|
-
|
|
18763
|
-
|
|
18764
|
-
const text = lastAssistantText(session.piSession?.messages ?? session.agent.state.messages);
|
|
18765
|
-
if (text !== undefined)
|
|
18766
|
-
preliminary = { answer: text, results: [], sources: [], evidenceRefs: [] };
|
|
18767
|
-
}
|
|
18768
|
-
if (preliminary !== undefined)
|
|
18769
|
-
emitPreliminary(preliminary);
|
|
18770
|
-
if (captured !== undefined)
|
|
18771
|
-
return;
|
|
19250
|
+
setThinking(this.fastThinkingLevel);
|
|
19251
|
+
await activeSession.prompt(this.buildFastAnswerPrompt(trimmedQuery, options, baseline));
|
|
19252
|
+
const fastText = finalAnswerText(transcript());
|
|
19253
|
+
const preliminary = fastText === undefined ? undefined : this.deriveAnswer(fastText);
|
|
18772
19254
|
if (preliminary !== undefined) {
|
|
19255
|
+
emitPreliminary(preliminary);
|
|
18773
19256
|
const followUp = await this.shouldFollowUp(trimmedQuery, preliminary);
|
|
18774
19257
|
if (planAbort.signal.aborted)
|
|
18775
19258
|
return;
|
|
18776
19259
|
if (!followUp) {
|
|
18777
|
-
captured =
|
|
19260
|
+
captured = preliminary;
|
|
18778
19261
|
return;
|
|
18779
19262
|
}
|
|
18780
|
-
}
|
|
18781
|
-
if (preliminary !== undefined)
|
|
18782
19263
|
publishPreliminary(preliminary);
|
|
18783
|
-
if (sessionAgent !== undefined) {
|
|
18784
|
-
sessionAgent.setThinkingLevel(clampThinkingLevel(resolved.model, this.finalThinkingLevel));
|
|
18785
|
-
sessionAgent.setActiveToolsByName(sessionAgent.getActiveToolNames().filter((name) => name !== EMIT_FAST_ANSWER_TOOL_NAME));
|
|
18786
|
-
} else {
|
|
18787
|
-
session.agent.state.thinkingLevel = clampThinkingLevel(resolved.model, this.finalThinkingLevel);
|
|
18788
|
-
session.agent.state.tools = [...this.tools];
|
|
18789
19264
|
}
|
|
19265
|
+
setThinking(this.finalThinkingLevel);
|
|
18790
19266
|
const fastAnswerDelivered = preliminary !== undefined && this.preliminaryCallback !== undefined;
|
|
18791
|
-
await
|
|
18792
|
-
|
|
18793
|
-
|
|
18794
|
-
|
|
19267
|
+
await activeSession.prompt(this.buildRefinementPrompt(trimmedQuery, options, fastText, fastAnswerDelivered));
|
|
19268
|
+
const finalText = finalAnswerText(transcript());
|
|
19269
|
+
if (finalText !== undefined)
|
|
19270
|
+
captured = this.deriveAnswer(finalText);
|
|
18795
19271
|
})(),
|
|
18796
19272
|
new Promise((resolve, reject) => {
|
|
18797
19273
|
timeout = setTimeout(() => {
|
|
@@ -18811,7 +19287,7 @@ Warning: the edited config did not validate, so the previous config was restored
|
|
|
18811
19287
|
clearTimeout(timeout);
|
|
18812
19288
|
}
|
|
18813
19289
|
if (captured === undefined && timedOutAfterFastAnswer && fastCaptured !== undefined) {
|
|
18814
|
-
const response = recordStructuredResultsSession(sessionId, trimmedQuery,
|
|
19290
|
+
const response = recordStructuredResultsSession(sessionId, trimmedQuery, fastCaptured, this.memory, [
|
|
18815
19291
|
...this.collectComponentDiagnostics(),
|
|
18816
19292
|
{
|
|
18817
19293
|
code: "search-timeout",
|
|
@@ -18845,15 +19321,15 @@ Warning: the edited config did not validate, so the previous config was restored
|
|
|
18845
19321
|
sessionId,
|
|
18846
19322
|
query: trimmedQuery,
|
|
18847
19323
|
results: [],
|
|
18848
|
-
answer:
|
|
19324
|
+
answer: buildMissingFinalAnswer(trimmedQuery, reason, this.retrievalTrace, modelError),
|
|
18849
19325
|
searched: this.retrievalTrace.reduce((total, entry) => total + entry.resultCount, 0),
|
|
18850
19326
|
warnings: [],
|
|
18851
19327
|
diagnostics: [
|
|
18852
19328
|
...this.collectComponentDiagnostics(),
|
|
18853
19329
|
{
|
|
18854
|
-
code: "
|
|
19330
|
+
code: "no-final-answer",
|
|
18855
19331
|
severity: "warning",
|
|
18856
|
-
message: "The agent ended its run without
|
|
19332
|
+
message: "The agent ended its run without a final answer message; returning a degraded response that carries the run's retrieval trace."
|
|
18857
19333
|
},
|
|
18858
19334
|
...modelError === undefined ? [] : [
|
|
18859
19335
|
{
|
|
@@ -18899,7 +19375,7 @@ Warning: the edited config did not validate, so the previous config was restored
|
|
|
18899
19375
|
source: "agent"
|
|
18900
19376
|
});
|
|
18901
19377
|
}
|
|
18902
|
-
const recorded = recordStructuredResultsSession(sessionId, trimmedQuery, captured, this.
|
|
19378
|
+
const recorded = recordStructuredResultsSession(sessionId, trimmedQuery, captured, this.memory, componentDiagnostics, { isolateMemory: this.remoteSession || selfConfigRun });
|
|
18903
19379
|
const memoryDiagnostic = selfConfigRun ? undefined : await this.recordJudgedEvidence(sessionId, trimmedQuery, captured);
|
|
18904
19380
|
const response = memoryDiagnostic === undefined ? recorded : { ...recorded, diagnostics: [...recorded.diagnostics ?? [], memoryDiagnostic] };
|
|
18905
19381
|
this.runLogger.write({
|
|
@@ -18940,36 +19416,25 @@ Warning: the edited config did not validate, so the previous config was restored
|
|
|
18940
19416
|
});
|
|
18941
19417
|
}
|
|
18942
19418
|
this.activeSession = undefined;
|
|
18943
|
-
this.resultCapture = undefined;
|
|
18944
19419
|
this.activeRetrievalOptions = undefined;
|
|
18945
19420
|
this.preliminaryCallback = undefined;
|
|
18946
|
-
if (this.interactiveFastAnswerCallback === emitPreliminary)
|
|
18947
|
-
this.interactiveFastAnswerCallback = undefined;
|
|
18948
19421
|
this.activeRun = false;
|
|
18949
19422
|
this.memoryContextCache = undefined;
|
|
18950
19423
|
}
|
|
18951
19424
|
}
|
|
18952
19425
|
async* searchDocumentsStream(query, options = {}) {
|
|
18953
19426
|
const queue = [];
|
|
18954
|
-
let progressBuffer = "";
|
|
18955
19427
|
let wake;
|
|
18956
19428
|
let settled = false;
|
|
18957
19429
|
const unsubscribe = this.subscribe((event) => {
|
|
18958
|
-
if (event.type !== "
|
|
19430
|
+
if (event.type !== "message_end" || event.message.role !== "assistant")
|
|
18959
19431
|
return;
|
|
18960
|
-
|
|
18961
|
-
if (text.trim().length === 0)
|
|
19432
|
+
if (event.message.stopReason !== "toolUse")
|
|
18962
19433
|
return;
|
|
18963
|
-
|
|
18964
|
-
if (
|
|
19434
|
+
const text = event.message.content.filter((block) => block.type === "text").map((block) => block.text).join("").trim();
|
|
19435
|
+
if (text === "")
|
|
18965
19436
|
return;
|
|
18966
|
-
queue.push({
|
|
18967
|
-
type: "progress",
|
|
18968
|
-
sessionId: this.lastSessionId ?? "",
|
|
18969
|
-
query: query.trim(),
|
|
18970
|
-
text: progressBuffer
|
|
18971
|
-
});
|
|
18972
|
-
progressBuffer = "";
|
|
19437
|
+
queue.push({ type: "progress", sessionId: this.lastSessionId ?? "", query: query.trim(), text });
|
|
18973
19438
|
wake?.();
|
|
18974
19439
|
wake = undefined;
|
|
18975
19440
|
});
|
|
@@ -18985,15 +19450,6 @@ Warning: the edited config did not validate, so the previous config was restored
|
|
|
18985
19450
|
wake = undefined;
|
|
18986
19451
|
};
|
|
18987
19452
|
const run = this.searchDocuments(query, options).then((response) => {
|
|
18988
|
-
if (progressBuffer.trim() !== "") {
|
|
18989
|
-
queue.push({
|
|
18990
|
-
type: "progress",
|
|
18991
|
-
sessionId: this.lastSessionId ?? "",
|
|
18992
|
-
query: query.trim(),
|
|
18993
|
-
text: progressBuffer
|
|
18994
|
-
});
|
|
18995
|
-
progressBuffer = "";
|
|
18996
|
-
}
|
|
18997
19453
|
queue.push({ type: "complete", response });
|
|
18998
19454
|
}).catch((error) => {
|
|
18999
19455
|
settled = true;
|
|
@@ -19384,7 +19840,7 @@ ${result.content.replace(/\s+/gu, " ")}`).join(`
|
|
|
19384
19840
|
}
|
|
19385
19841
|
}
|
|
19386
19842
|
buildFastAnswerPrompt(query, options, baseline) {
|
|
19387
|
-
const limit = typeof options.topK === "number" ? `
|
|
19843
|
+
const limit = typeof options.topK === "number" ? ` Cite at most ${options.topK} sources.` : "";
|
|
19388
19844
|
const scope = options.scope ? ` Restrict search to virtual path scope ${options.scope}.` : "";
|
|
19389
19845
|
return `Answer this original query immediately: ${query}${limit}${scope}
|
|
19390
19846
|
|
|
@@ -19396,21 +19852,18 @@ ${baseline}
|
|
|
19396
19852
|
` + `Formatting and content rules for the answer:
|
|
19397
19853
|
` + `- Provide the core answer to the user's question in at most 5 bullet points. If additional explanation is necessary, append it after the bullet points.
|
|
19398
19854
|
` + `- Answer the question directly. Do not include specific file paths, datasource descriptions, or retrieval mechanics in the answer text.
|
|
19399
|
-
` + `- Cite evidence with bracketed numbers only (e.g. [1], [2]); do not quote raw chunks or mention source paths directly in the answer.
|
|
19400
19855
|
` + `- ${ANSWER_CITATION_RULE}
|
|
19401
19856
|
` + `- ${ANSWER_IMAGE_EMBED_RULE}
|
|
19402
19857
|
` + `- Do not report per-source negative findings (e.g. "no information found in Slack" or "checked Drive but found nothing").
|
|
19403
19858
|
` + `- When evidence conflicts, treat the freshest (most recent) information as the correct source of truth.
|
|
19404
19859
|
` + `- If information is incomplete or uncertain, acknowledge it briefly without lengthy explanations, stating that it is difficult to answer fully with the given information and searching continues. If there are partial clues or leads (even if not the exact answer), mention those clues concisely.
|
|
19405
19860
|
|
|
19406
|
-
` + `
|
|
19861
|
+
` + `Write the answer as your reply, then stop.`;
|
|
19407
19862
|
}
|
|
19408
19863
|
buildDirectAnswerPrompt(query) {
|
|
19409
19864
|
return `Answer this query directly from your own general knowledge: ${query}
|
|
19410
19865
|
|
|
19411
|
-
` + `It needs no search: it is general knowledge, simple reasoning, or conversation. Do NOT call any search, retrieval, web, or file-reading tools. ` + `Reply naturally and concisely; for small talk, just respond conversationally. Do not cite sources or mention retrieval
|
|
19412
|
-
|
|
19413
|
-
` + `Call emit_fast_answer exactly once with the answer and an empty results list, then stop.`;
|
|
19866
|
+
` + `It needs no search: it is general knowledge, simple reasoning, or conversation. Do NOT call any search, retrieval, web, or file-reading tools. ` + `Reply naturally and concisely; for small talk, just respond conversationally. Do not cite sources or mention retrieval.`;
|
|
19414
19867
|
}
|
|
19415
19868
|
discoveryHint(sentence) {
|
|
19416
19869
|
const names = this.tools.map((tool) => tool.name).filter((name) => name === JIKJI_FIND_TOOL_NAME || name === EVERYTHING_SEARCH_TOOL_NAME);
|
|
@@ -19424,22 +19877,20 @@ ${baseline}
|
|
|
19424
19877
|
return `When local evidence is missing, thin, or possibly outdated — or the question concerns current events, recent releases, prices, or other public facts — use ${WEB_SEARCH_TOOL_NAME}${fetch2} to confirm or correct claims and fill gaps; use URLs as result sources for web-derived evidence. `;
|
|
19425
19878
|
}
|
|
19426
19879
|
buildRefinementPrompt(query, options, fastAnswer, fastAnswerDelivered) {
|
|
19427
|
-
const limit = typeof options.topK === "number" ? `
|
|
19880
|
+
const limit = typeof options.topK === "number" ? ` Cite at most ${options.topK} sources.` : "";
|
|
19428
19881
|
const scope = options.scope ? ` Restrict search to virtual path scope ${options.scope}.` : "";
|
|
19429
19882
|
const firstAnswer = formatFirstAnswerContext(fastAnswer, fastAnswerDelivered);
|
|
19430
|
-
const answerRules = fastAnswerDelivered ? `Formatting and content rules for
|
|
19431
|
-
` + `- The user already has the first answer above.
|
|
19883
|
+
const answerRules = fastAnswerDelivered ? `Formatting and content rules for your final answer (DELTA ONLY):
|
|
19884
|
+
` + `- The user already has the first answer above. Your final answer MUST contain only the delta against it: (a) corrections to anything in the first answer that is wrong, unsupported, or outdated, and (b) newly verified findings that were not present in the first answer.
|
|
19432
19885
|
` + `- NEVER restate or re-list first-answer facts that remain correct, and never repeat its bullet list.
|
|
19433
19886
|
` + `- Mark each item clearly as a correction or as a new finding.
|
|
19434
19887
|
` + `- If verification changed nothing and found nothing new, say so in one short line (the first answer is confirmed as-is) instead of restating it.
|
|
19435
|
-
` + `-
|
|
19436
|
-
` + `- ${ANSWER_CITATION_RULE} A correction or new finding that relies on a first-answer unit must re-emit that evidence as a result of this call and cite its new number.
|
|
19888
|
+
` + `- ${ANSWER_CITATION_RULE} A correction or new finding that relies on evidence the first answer cited must cite that evidence's id again.
|
|
19437
19889
|
` + `- ${ANSWER_IMAGE_EMBED_RULE} ${ANSWER_IMAGE_DELTA_RULE}
|
|
19438
19890
|
` + `- Do not report per-source negative findings (e.g. "no information found in Slack").
|
|
19439
19891
|
` + `- When evidence conflicts, treat the freshest (most recent) information as the correct source of truth.` : `Formatting and content rules for the final answer (COMPLETE — no first answer reached the caller):
|
|
19440
19892
|
` + `- Provide the core answer to the user's question in at most 5 bullet points. If additional explanation is necessary, append it after the bullet points.
|
|
19441
19893
|
` + `- Answer the question directly. Do not include specific file paths, datasource descriptions, or retrieval mechanics in the answer text.
|
|
19442
|
-
` + `- Cite evidence with bracketed numbers only (e.g. [1], [2]); do not quote raw chunks or mention source paths directly in the answer.
|
|
19443
19894
|
` + `- ${ANSWER_CITATION_RULE}
|
|
19444
19895
|
` + `- ${ANSWER_IMAGE_EMBED_RULE}
|
|
19445
19896
|
` + `- Do not report per-source negative findings (e.g. "no information found in Slack").
|
|
@@ -19448,35 +19899,34 @@ ${baseline}
|
|
|
19448
19899
|
|
|
19449
19900
|
` + `${firstAnswer}
|
|
19450
19901
|
|
|
19451
|
-
` + `Now verify it rigorously. ${this.discoveryHint((tools) => `Actively use ${tools} when discovering or exploring local files and folders. `)}Check important claims against source files with bash when needed, correct anything wrong or unsupported, fill gaps with retrieval tools, and resolve conflicts and freshness. ${this.webFallbackHint()}
|
|
19902
|
+
` + `Now verify it rigorously. ${this.discoveryHint((tools) => `Actively use ${tools} when discovering or exploring local files and folders. `)}Check important claims against source files with bash when needed, correct anything wrong or unsupported, fill gaps with retrieval tools, and resolve conflicts and freshness. ${this.webFallbackHint()}
|
|
19452
19903
|
|
|
19453
19904
|
` + `${answerRules}
|
|
19454
19905
|
|
|
19455
|
-
` + `Do not use broad grep/find or recursive filesystem scans: only inspect a path or narrow neighborhood surfaced by retrieval, and only when evidence clearly points there. ` + `Avoid spinning repeated near-identical queries against the same datasource; once additional attempts stop surfacing new evidence, conclude from the evidence available. ` + `If more search is needed, first write a brief 1–2 line progress update stating the best current hypothesis and what you are checking next, then call retrieval tools. ` + `When finished,
|
|
19906
|
+
` + `Do not use broad grep/find or recursive filesystem scans: only inspect a path or narrow neighborhood surfaced by retrieval, and only when evidence clearly points there. ` + `Avoid spinning repeated near-identical queries against the same datasource; once additional attempts stop surfacing new evidence, conclude from the evidence available. ` + `If more search is needed, first write a brief 1–2 line progress update stating the best current hypothesis and what you are checking next, then call retrieval tools. ` + `When finished, reply with the final answer and no tool call: that last reply is what the user receives, so keep progress notes out of it.`;
|
|
19456
19907
|
}
|
|
19457
19908
|
buildSearchPrompt(query, options, initialRetrievalContext) {
|
|
19458
|
-
const limit = typeof options.topK === "number" ? `
|
|
19909
|
+
const limit = typeof options.topK === "number" ? ` Cite at most ${options.topK} sources.` : "";
|
|
19459
19910
|
const scope = options.scope ? ` Restrict search to virtual path scope ${options.scope}.` : "";
|
|
19460
19911
|
return `Find and curate information for this original query: ${query}${limit}${scope}
|
|
19461
19912
|
|
|
19462
|
-
` + `Start by deciding whether this is answerable from general knowledge or memory. If it is a generic, stable question, answer it immediately without retrieval
|
|
19913
|
+
` + `Start by deciding whether this is answerable from general knowledge or memory. If it is a generic, stable question, answer it immediately without retrieval. ` + `Otherwise, baseline MinSync and Jikji retrieval is already running in parallel; do not give the final answer until its next message arrives.
|
|
19463
19914
|
|
|
19464
19915
|
` + `Baseline retrieval context:
|
|
19465
19916
|
${initialRetrievalContext ?? "Pending; continue only with a brief progress statement."}
|
|
19466
19917
|
|
|
19467
|
-
` + `Treat candidates as unverified evidence, verify important claims against source files when needed, and use additional tools when needed. ` + `Judge relevance, conflicts, freshness, and sufficiency in this agent loop.
|
|
19918
|
+
` + `Treat candidates as unverified evidence, verify important claims against source files when needed, and use additional tools when needed. ` + `Judge relevance, conflicts, freshness, and sufficiency in this agent loop.
|
|
19468
19919
|
|
|
19469
19920
|
` + `Formatting and content rules for the answer:
|
|
19470
19921
|
` + `- Provide the core answer to the user's question in at most 5 bullet points. If additional explanation is necessary, append it after the bullet points.
|
|
19471
19922
|
` + `- Answer the question directly. Do not include specific file paths, datasource descriptions, or retrieval mechanics in the answer text.
|
|
19472
|
-
` + `- Cite evidence with bracketed numbers only (e.g. [1], [2]); do not quote raw chunks or mention source paths directly in the answer.
|
|
19473
19923
|
` + `- ${ANSWER_CITATION_RULE}
|
|
19474
19924
|
` + `- ${ANSWER_IMAGE_EMBED_RULE}
|
|
19475
19925
|
` + `- Do not report per-source negative findings (e.g. "no information found in Slack").
|
|
19476
19926
|
` + `- When evidence conflicts, treat the freshest (most recent) information as the correct source of truth.
|
|
19477
19927
|
` + `- If information is incomplete or uncertain, acknowledge it briefly without lengthy explanations. If there are partial clues or leads, mention them concisely.
|
|
19478
19928
|
|
|
19479
|
-
` + `${this.discoveryHint((tools) => `When exploring local files and folders, actively use ${tools} rather than exploratory bash commands. `)}If more search is needed, first write a brief 1–2 line progress update stating the best current hypothesis and what you are checking next, then call retrieval tools. ` + `Never repeat a generic status message. Do not use broad grep/find or recursive filesystem scans: only inspect a path or narrow neighborhood surfaced by retrieval, and only when evidence clearly points there. ` + `Avoid spinning repeated near-identical queries against the same datasource; once additional attempts stop surfacing new evidence, conclude from the evidence available. ` + `When finished,
|
|
19929
|
+
` + `${this.discoveryHint((tools) => `When exploring local files and folders, actively use ${tools} rather than exploratory bash commands. `)}If more search is needed, first write a brief 1–2 line progress update stating the best current hypothesis and what you are checking next, then call retrieval tools. ` + `Never repeat a generic status message. Do not use broad grep/find or recursive filesystem scans: only inspect a path or narrow neighborhood surfaced by retrieval, and only when evidence clearly points there. ` + `Avoid spinning repeated near-identical queries against the same datasource; once additional attempts stop surfacing new evidence, conclude from the evidence available. ` + `When finished, reply with the final answer and no tool call: that last reply is what the user receives, so keep progress notes out of it.`;
|
|
19480
19930
|
}
|
|
19481
19931
|
async refresh(force = false, opts) {
|
|
19482
19932
|
const methods = opts?.methods;
|
|
@@ -20108,57 +20558,21 @@ ${initialRetrievalContext ?? "Pending; continue only with a brief progress state
|
|
|
20108
20558
|
function formatRerankedBaseline(results, evidenceIds) {
|
|
20109
20559
|
const lines = results.map((result, index) => `[${evidenceIds[index]}] ${result.source}
|
|
20110
20560
|
${result.content.replace(/\s+/gu, " ")}`);
|
|
20111
|
-
return `Reranked initial candidates (ordered by relevance to the query; cite evidence by its [eN] id
|
|
20561
|
+
return `Reranked initial candidates (ordered by relevance to the query; cite evidence by its [eN] id):
|
|
20112
20562
|
${lines.join(`
|
|
20113
20563
|
`)}`;
|
|
20114
20564
|
}
|
|
20115
|
-
function fastAnswerAsFinal(fastAnswer) {
|
|
20116
|
-
const refsByNumber = new Map(fastAnswer.evidenceRefs.map((entry) => [entry.number, entry.refs]));
|
|
20117
|
-
return {
|
|
20118
|
-
answer: fastAnswer.answer,
|
|
20119
|
-
results: fastAnswer.results.map((result) => ({
|
|
20120
|
-
number: result.number,
|
|
20121
|
-
title: result.title,
|
|
20122
|
-
summary: result.summary,
|
|
20123
|
-
evidence: result.evidence,
|
|
20124
|
-
confidence: result.confidence ?? 0.5
|
|
20125
|
-
})),
|
|
20126
|
-
mapping: fastAnswer.results.map((result) => {
|
|
20127
|
-
const refs = refsByNumber.get(result.number) ?? [];
|
|
20128
|
-
const primary = refs[0];
|
|
20129
|
-
return {
|
|
20130
|
-
number: result.number,
|
|
20131
|
-
source: primary?.source ?? "",
|
|
20132
|
-
method: primary?.method ?? EMIT_FAST_ANSWER_TOOL_NAME,
|
|
20133
|
-
content: primary?.content ?? (result.evidence.map((evidence) => evidence.excerpt).join(`
|
|
20134
|
-
`) || result.summary),
|
|
20135
|
-
evidenceRefs: refs
|
|
20136
|
-
};
|
|
20137
|
-
}),
|
|
20138
|
-
warnings: []
|
|
20139
|
-
};
|
|
20140
|
-
}
|
|
20141
20565
|
function formatFirstAnswerContext(fastAnswer, delivered) {
|
|
20142
20566
|
if (fastAnswer === undefined) {
|
|
20143
20567
|
return "(the fast phase produced no answer — write the complete answer)";
|
|
20144
20568
|
}
|
|
20145
|
-
const header = delivered ? "The user has ALREADY received this immediate first answer:" : "An internal first-pass draft was produced but was NOT shown to the caller; write the complete answer:";
|
|
20146
|
-
const units = fastAnswer.results.length === 0 ? "" : `
|
|
20147
|
-
|
|
20148
|
-
Numbered units of that first answer (its own numbering — NOT citation numbers for your final answer; cite only the results you emit):
|
|
20149
|
-
${fastAnswer.results.map((result) => `[${result.number}] ${result.title} — ${result.summary}`).join(`
|
|
20150
|
-
`)}`;
|
|
20151
|
-
const sources = fastAnswer.sources.length === 0 ? "" : `
|
|
20152
|
-
|
|
20153
|
-
Sources of that first answer:
|
|
20154
|
-
${fastAnswer.sources.map((entry) => `[${entry.number}] -> ${entry.source}`).join(`
|
|
20155
|
-
`)}`;
|
|
20569
|
+
const header = delivered ? "The user has ALREADY received this immediate first answer (its citations were renumbered for the user; the [eN] ids below are still valid for you):" : "An internal first-pass draft was produced but was NOT shown to the caller; write the complete answer:";
|
|
20156
20570
|
return `${header}
|
|
20157
|
-
${fastAnswer
|
|
20571
|
+
${fastAnswer}`;
|
|
20158
20572
|
}
|
|
20159
|
-
function
|
|
20573
|
+
function buildMissingFinalAnswer(query, reason, trace, modelError) {
|
|
20160
20574
|
const lines = [
|
|
20161
|
-
`The search run for "${query}" ended without
|
|
20575
|
+
`The search run for "${query}" ended without a final answer: the agent stopped before writing one, so no curated answer is available within the configured search range.`,
|
|
20162
20576
|
...modelError === undefined ? [] : [`The model request failed: ${modelError}`],
|
|
20163
20577
|
...reason === undefined ? modelError === undefined ? ["The agent did not record why it stopped."] : [] : [`The agent's last note before stopping: "${reason.length > 500 ? `${reason.slice(0, 500)}…` : reason}"`],
|
|
20164
20578
|
modelError === undefined ? "Next steps: broaden the configured searchPaths, connect additional datasources via the datasources configuration, or retry with a narrower or different query." : "Next steps: fix the model provider error above (rate limit, quota, credentials, or model id) and retry the same query.",
|
|
@@ -20179,8 +20593,17 @@ function lastModelRequestError(messages) {
|
|
|
20179
20593
|
}
|
|
20180
20594
|
return;
|
|
20181
20595
|
}
|
|
20182
|
-
function
|
|
20183
|
-
|
|
20596
|
+
function finalAnswerText(messages) {
|
|
20597
|
+
for (let index = messages.length - 1;index >= 0; index--) {
|
|
20598
|
+
const message = messages[index];
|
|
20599
|
+
if (message.role !== "assistant")
|
|
20600
|
+
continue;
|
|
20601
|
+
if (message.stopReason !== "stop")
|
|
20602
|
+
return;
|
|
20603
|
+
const text = message.content.filter((block) => block.type === "text").map((block) => block.text).join("").trim();
|
|
20604
|
+
return text === "" ? undefined : text;
|
|
20605
|
+
}
|
|
20606
|
+
return;
|
|
20184
20607
|
}
|
|
20185
20608
|
function lastAssistantText(messages) {
|
|
20186
20609
|
for (let index = messages.length - 1;index >= 0; index--) {
|
|
@@ -20342,13 +20765,12 @@ var init_agent = __esm(() => {
|
|
|
20342
20765
|
init_rerank();
|
|
20343
20766
|
init_scope();
|
|
20344
20767
|
init_model_auth();
|
|
20768
|
+
init_answer_citations();
|
|
20345
20769
|
init_datasource_skill();
|
|
20346
20770
|
init_dupey_tool();
|
|
20347
|
-
init_emit_results_tool();
|
|
20348
20771
|
init_everything_search_tool();
|
|
20349
20772
|
init_evidence_judgment();
|
|
20350
20773
|
init_evidence_ledger();
|
|
20351
|
-
init_fast_answer_tool();
|
|
20352
20774
|
init_fsearch_search_tool();
|
|
20353
20775
|
init_jev_extension();
|
|
20354
20776
|
init_jikji_find_tool();
|
|
@@ -20790,7 +21212,7 @@ function datasourceCliError(datasourceId, command, failure) {
|
|
|
20790
21212
|
return new DatasourceCliError(datasourceId, command, failure);
|
|
20791
21213
|
}
|
|
20792
21214
|
var DatasourceCliError;
|
|
20793
|
-
var
|
|
21215
|
+
var init_errors4 = __esm(() => {
|
|
20794
21216
|
DatasourceCliError = class DatasourceCliError extends Error {
|
|
20795
21217
|
datasourceId;
|
|
20796
21218
|
command;
|
|
@@ -20882,7 +21304,7 @@ function toResult(hit, source, mode, instanceId) {
|
|
|
20882
21304
|
};
|
|
20883
21305
|
}
|
|
20884
21306
|
var init_methods = __esm(() => {
|
|
20885
|
-
|
|
21307
|
+
init_errors4();
|
|
20886
21308
|
init_scope2();
|
|
20887
21309
|
});
|
|
20888
21310
|
|
|
@@ -21476,7 +21898,7 @@ var init_rclone_connector = __esm(() => {
|
|
|
21476
21898
|
});
|
|
21477
21899
|
|
|
21478
21900
|
// src/datasource/connector.ts
|
|
21479
|
-
import { createHash as
|
|
21901
|
+
import { createHash as createHash12 } from "node:crypto";
|
|
21480
21902
|
function connectorFailureToDiagnosticCode(reason) {
|
|
21481
21903
|
switch (reason) {
|
|
21482
21904
|
case "auth":
|
|
@@ -21510,7 +21932,7 @@ function sanitizeIdSegment(value) {
|
|
|
21510
21932
|
const cleaned = normalized.slice(start, end);
|
|
21511
21933
|
if (cleaned === value && cleaned.length > 0 && cleaned.length <= 80)
|
|
21512
21934
|
return cleaned;
|
|
21513
|
-
const hash =
|
|
21935
|
+
const hash = createHash12("sha256").update(value).digest("hex").slice(0, 8);
|
|
21514
21936
|
const stem = cleaned.slice(0, 60);
|
|
21515
21937
|
return stem.length > 0 ? `${stem}-${hash}` : hash;
|
|
21516
21938
|
}
|
|
@@ -22709,7 +23131,7 @@ function toRetrievalResult(hit, source, methodName, instanceId, mode, diagnostic
|
|
|
22709
23131
|
}
|
|
22710
23132
|
var DISCORD_DATASOURCE_ID = "discord", DEFAULT_DISCORD_TAGS, DEFAULT_TOP_K2 = 20;
|
|
22711
23133
|
var init_methods2 = __esm(() => {
|
|
22712
|
-
|
|
23134
|
+
init_errors4();
|
|
22713
23135
|
init_scope2();
|
|
22714
23136
|
init_paths3();
|
|
22715
23137
|
DEFAULT_DISCORD_TAGS = ["discord", "chat", "pii"];
|
|
@@ -23007,7 +23429,7 @@ class GitHubConnector {
|
|
|
23007
23429
|
if (repos.length === 0)
|
|
23008
23430
|
return { ok: false, reason: "not-configured", message: "no repositories configured" };
|
|
23009
23431
|
const token = resolveToken(this.options.token, this.options.tokenEnv ?? DEFAULT_TOKEN_ENV);
|
|
23010
|
-
const baseUrl = this.options.baseUrl ??
|
|
23432
|
+
const baseUrl = this.options.baseUrl ?? DEFAULT_BASE_URL4;
|
|
23011
23433
|
const request = {
|
|
23012
23434
|
headers: {
|
|
23013
23435
|
Accept: "application/vnd.github+json",
|
|
@@ -23080,7 +23502,7 @@ ${body}` : title,
|
|
|
23080
23502
|
return { ok: true, documents, ...warnings.length > 0 ? { warnings } : {} };
|
|
23081
23503
|
}
|
|
23082
23504
|
}
|
|
23083
|
-
var
|
|
23505
|
+
var DEFAULT_BASE_URL4 = "https://api.github.com", DEFAULT_TOKEN_ENV = "GITHUB_TOKEN", DEFAULT_MAX_PAGES = 10, DEFAULT_MAX_DOCUMENTS2 = 500;
|
|
23084
23506
|
var init_connector2 = () => {};
|
|
23085
23507
|
|
|
23086
23508
|
// src/datasource/skills/github/skill.ts
|
|
@@ -23147,7 +23569,7 @@ class GitHubGistConnector {
|
|
|
23147
23569
|
message: "no GitHub token: set GITHUB_TOKEN (or connector.tokenEnv) or authenticate the gh CLI"
|
|
23148
23570
|
};
|
|
23149
23571
|
}
|
|
23150
|
-
const baseUrl = this.options.baseUrl ??
|
|
23572
|
+
const baseUrl = this.options.baseUrl ?? DEFAULT_BASE_URL5;
|
|
23151
23573
|
const request = {
|
|
23152
23574
|
headers: {
|
|
23153
23575
|
Accept: "application/vnd.github+json",
|
|
@@ -23296,15 +23718,15 @@ ${content}`);
|
|
|
23296
23718
|
}
|
|
23297
23719
|
};
|
|
23298
23720
|
}
|
|
23299
|
-
var
|
|
23721
|
+
var DEFAULT_BASE_URL5 = "https://api.github.com", DEFAULT_TOKEN_ENV2 = "GITHUB_TOKEN", DEFAULT_MAX_PAGES2 = 10, DEFAULT_MAX_GISTS = 500, GH_TOKEN_TIMEOUT_MS = 5000, STATE_VERSION = 1;
|
|
23300
23722
|
var init_connector3 = () => {};
|
|
23301
23723
|
|
|
23302
23724
|
// src/datasource/skills/github-gist/semantic.ts
|
|
23303
|
-
import { createHash as
|
|
23725
|
+
import { createHash as createHash13 } from "node:crypto";
|
|
23304
23726
|
import { existsSync as existsSync26, mkdirSync as mkdirSync22, readFileSync as readFileSync23, writeFileSync as writeFileSync21 } from "node:fs";
|
|
23305
23727
|
import { dirname as dirname21 } from "node:path";
|
|
23306
23728
|
function contentHash(chunk) {
|
|
23307
|
-
return
|
|
23729
|
+
return createHash13("sha256").update(`${chunk.title ?? ""}
|
|
23308
23730
|
${chunk.content}`).digest("hex");
|
|
23309
23731
|
}
|
|
23310
23732
|
function sameIdentity(a, b) {
|
|
@@ -24234,7 +24656,7 @@ function isRemoteEmbedder(value) {
|
|
|
24234
24656
|
}
|
|
24235
24657
|
var CHAT_TAG = "lark:chat", DOCS_TAG = "lark:docs", DEFAULT_TAGS2, REMOTE_NOTE = "remote-search datasource: no local mirror";
|
|
24236
24658
|
var init_skill6 = __esm(() => {
|
|
24237
|
-
|
|
24659
|
+
init_errors4();
|
|
24238
24660
|
init_scope2();
|
|
24239
24661
|
init_client7();
|
|
24240
24662
|
DEFAULT_TAGS2 = [CHAT_TAG, DOCS_TAG];
|
|
@@ -24762,7 +25184,7 @@ function toRetrievalResult2(hit, source, methodName, instanceId, mode) {
|
|
|
24762
25184
|
}
|
|
24763
25185
|
var KAKAO_DATASOURCE_ID = "kakao", DEFAULT_KAKAO_TAGS, DEFAULT_TOP_K4 = 20;
|
|
24764
25186
|
var init_methods3 = __esm(() => {
|
|
24765
|
-
|
|
25187
|
+
init_errors4();
|
|
24766
25188
|
init_paths4();
|
|
24767
25189
|
DEFAULT_KAKAO_TAGS = ["kakaotalk", "personal", "pii"];
|
|
24768
25190
|
});
|
|
@@ -25116,7 +25538,7 @@ function ensurePrivateMailcrawlDataDir(path) {
|
|
|
25116
25538
|
if (process.platform !== "win32")
|
|
25117
25539
|
chmodSync(path, 448);
|
|
25118
25540
|
}
|
|
25119
|
-
var
|
|
25541
|
+
var init_config2 = () => {};
|
|
25120
25542
|
|
|
25121
25543
|
// src/datasource/skills/mailcrawl/client.ts
|
|
25122
25544
|
import { spawn as spawn15 } from "node:child_process";
|
|
@@ -25442,7 +25864,7 @@ function truncateUtf8(value, maxBytes) {
|
|
|
25442
25864
|
var DEFAULT_BINARY4 = "mailcrawl", DEFAULT_SEARCH_TIMEOUT_MS3 = 60000, DEFAULT_INDEX_TIMEOUT_MS3 = 1800000, DEFAULT_MAX_BUFFER_BYTES4 = 1048576, LOOPBACK_HOSTS2, SAFE_ENV_KEYS2, SAFE_MAILCRAWL_ENV_KEYS, REMOTE_EMBEDDING_ENV_KEYS;
|
|
25443
25865
|
var init_client9 = __esm(() => {
|
|
25444
25866
|
init_portable_spawn();
|
|
25445
|
-
|
|
25867
|
+
init_config2();
|
|
25446
25868
|
LOOPBACK_HOSTS2 = new Set(["127.0.0.1", "localhost", "[::1]", "::1"]);
|
|
25447
25869
|
SAFE_ENV_KEYS2 = new Set(["HOME", "LANG", "LC_ALL", "PATH", "TMPDIR", "TMP", "TEMP", "NO_COLOR"]);
|
|
25448
25870
|
SAFE_MAILCRAWL_ENV_KEYS = new Set([
|
|
@@ -25541,7 +25963,7 @@ class MailcrawlMethod {
|
|
|
25541
25963
|
}
|
|
25542
25964
|
var modes, MAILCRAWL_MODES;
|
|
25543
25965
|
var init_methods4 = __esm(() => {
|
|
25544
|
-
|
|
25966
|
+
init_errors4();
|
|
25545
25967
|
init_scope2();
|
|
25546
25968
|
modes = ["bm25", "semantic", "hybrid"];
|
|
25547
25969
|
MAILCRAWL_MODES = modes;
|
|
@@ -25689,7 +26111,7 @@ var TAGS;
|
|
|
25689
26111
|
var init_skill9 = __esm(() => {
|
|
25690
26112
|
init_scope2();
|
|
25691
26113
|
init_client9();
|
|
25692
|
-
|
|
26114
|
+
init_config2();
|
|
25693
26115
|
init_methods4();
|
|
25694
26116
|
TAGS = ["mailcrawl", "email", "pii"];
|
|
25695
26117
|
});
|
|
@@ -25909,7 +26331,7 @@ function failureCode2(reason) {
|
|
|
25909
26331
|
}
|
|
25910
26332
|
var DEFAULT_INSTANCE_ID5 = "default", DEFAULT_POLLING_INTERVAL_MS4;
|
|
25911
26333
|
var init_crawler_skill = __esm(() => {
|
|
25912
|
-
|
|
26334
|
+
init_errors4();
|
|
25913
26335
|
init_scope2();
|
|
25914
26336
|
DEFAULT_POLLING_INTERVAL_MS4 = 15 * 60 * 1000;
|
|
25915
26337
|
});
|
|
@@ -26095,7 +26517,7 @@ var DEFAULT_QMD_BINARY = "qmd", DEFAULT_QMD_TIMEOUT_MS = 60000, DEFAULT_QMD_MAX_
|
|
|
26095
26517
|
// src/datasource/skills/obsidian/client.ts
|
|
26096
26518
|
import { spawn as spawn16 } from "node:child_process";
|
|
26097
26519
|
import { mkdirSync as mkdirSync24, writeFileSync as writeFileSync22 } from "node:fs";
|
|
26098
|
-
import { isAbsolute as
|
|
26520
|
+
import { isAbsolute as isAbsolute8, resolve as resolve14 } from "node:path";
|
|
26099
26521
|
|
|
26100
26522
|
class QmdClient {
|
|
26101
26523
|
options;
|
|
@@ -26191,7 +26613,7 @@ function resolveVaultPath(vaultPath) {
|
|
|
26191
26613
|
if (vaultPath === undefined || vaultPath.trim().length === 0)
|
|
26192
26614
|
return;
|
|
26193
26615
|
const trimmed = vaultPath.trim();
|
|
26194
|
-
return
|
|
26616
|
+
return isAbsolute8(trimmed) ? trimmed : resolve14(trimmed);
|
|
26195
26617
|
}
|
|
26196
26618
|
function controlledEnv5(options) {
|
|
26197
26619
|
const instanceId = options.instanceId ?? "default";
|
|
@@ -26547,7 +26969,7 @@ function toRetrievalResult3(hit, source, methodName, instanceId, mode) {
|
|
|
26547
26969
|
}
|
|
26548
26970
|
var OBSIDIAN_DATASOURCE_ID = "obsidian", DEFAULT_OBSIDIAN_TAGS, DEFAULT_TOP_K5 = 20;
|
|
26549
26971
|
var init_methods5 = __esm(() => {
|
|
26550
|
-
|
|
26972
|
+
init_errors4();
|
|
26551
26973
|
init_scope2();
|
|
26552
26974
|
DEFAULT_OBSIDIAN_TAGS = ["obsidian", "notes"];
|
|
26553
26975
|
});
|
|
@@ -27085,7 +27507,7 @@ var init_slack = __esm(() => {
|
|
|
27085
27507
|
|
|
27086
27508
|
// src/datasource/skills/spotlight/connector.ts
|
|
27087
27509
|
import { spawn as spawn17 } from "node:child_process";
|
|
27088
|
-
import { createHash as
|
|
27510
|
+
import { createHash as createHash14 } from "node:crypto";
|
|
27089
27511
|
import { readFile as fsReadFile, stat as stat7 } from "node:fs/promises";
|
|
27090
27512
|
import { basename as basename13, extname as extname8 } from "node:path";
|
|
27091
27513
|
|
|
@@ -27170,7 +27592,7 @@ class SpotlightConnector {
|
|
|
27170
27592
|
if (content.length === 0)
|
|
27171
27593
|
continue;
|
|
27172
27594
|
documents.push({
|
|
27173
|
-
docId:
|
|
27595
|
+
docId: createHash14("sha256").update(path).digest("hex").slice(0, 16),
|
|
27174
27596
|
hierarchy: ["files"],
|
|
27175
27597
|
title: basename13(path),
|
|
27176
27598
|
content,
|
|
@@ -27765,7 +28187,7 @@ var init_factory = __esm(() => {
|
|
|
27765
28187
|
// src/cli/config.ts
|
|
27766
28188
|
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
27767
28189
|
import { existsSync as existsSync28, mkdirSync as mkdirSync25, readFileSync as readFileSync24, renameSync as renameSync11, unlinkSync as unlinkSync5, writeFileSync as writeFileSync23 } from "node:fs";
|
|
27768
|
-
import { basename as basename14, dirname as dirname23, isAbsolute as
|
|
28190
|
+
import { basename as basename14, dirname as dirname23, isAbsolute as isAbsolute9, join as join36, resolve as resolve15 } from "node:path";
|
|
27769
28191
|
import { findEnvKeys, getEnvApiKey } from "@earendil-works/pi-ai/compat";
|
|
27770
28192
|
import { getAgentDir as getAgentDir3, ModelRuntime as ModelRuntime2, SettingsManager as SettingsManager2 } from "@earendil-works/pi-coding-agent";
|
|
27771
28193
|
function resolveConfigPath(input) {
|
|
@@ -27893,7 +28315,7 @@ function resolveSearchPaths(searchPaths, origin) {
|
|
|
27893
28315
|
return searchPaths.map((searchPath) => resolvePersistedPath(searchPath, origin));
|
|
27894
28316
|
}
|
|
27895
28317
|
function resolvePersistedPath(path, origin) {
|
|
27896
|
-
return
|
|
28318
|
+
return isAbsolute9(path) ? path : resolve15(origin, path);
|
|
27897
28319
|
}
|
|
27898
28320
|
function normalizeLegacyConfigPaths(partial, origin) {
|
|
27899
28321
|
const workspacePath = resolvePersistedPath(partial.workspacePath ?? ".", origin);
|
|
@@ -28733,11 +29155,15 @@ function getModelRuntime(agentDir) {
|
|
|
28733
29155
|
const cached = modelRuntimeCache.get(agentDir);
|
|
28734
29156
|
if (cached !== undefined)
|
|
28735
29157
|
return cached;
|
|
28736
|
-
const created =
|
|
28737
|
-
|
|
28738
|
-
|
|
28739
|
-
|
|
28740
|
-
|
|
29158
|
+
const created = (async () => {
|
|
29159
|
+
const runtime = await ModelRuntime2.create({
|
|
29160
|
+
authPath: join36(agentDir, "auth.json"),
|
|
29161
|
+
modelsPath: join36(agentDir, "models.json"),
|
|
29162
|
+
allowModelNetwork: false
|
|
29163
|
+
});
|
|
29164
|
+
await registerAutoRAGProvider(runtime);
|
|
29165
|
+
return runtime;
|
|
29166
|
+
})();
|
|
28741
29167
|
modelRuntimeCache.set(agentDir, created);
|
|
28742
29168
|
created.catch(() => {
|
|
28743
29169
|
modelRuntimeCache.delete(agentDir);
|
|
@@ -29066,8 +29492,9 @@ function writeDefaultConfig(path, partial, opts = {}) {
|
|
|
29066
29492
|
}
|
|
29067
29493
|
}
|
|
29068
29494
|
var DEFAULT_CONFIG_FILENAME = "config.json", LEGACY_CONFIG_FILENAME = "autorag.config.json", CONFIG_LOCK_RETRY_MS = 10, CONFIG_LOCK_TIMEOUT_MS = 1e4, CONFIG_LOCK_STALE_MS = 30000, ConfigError, MINSYNC_REQUIRED_MESSAGE = "MinSync is required and cannot be disabled; remove `minSync: false` / `minSync.enabled: false` from the config.", AGENT_MODEL_APIS, AGENT_MODEL_INPUTS, API_KEY_ENV_PATTERN2, POSITIVE_INT_FIELDS, EMBEDDER_ALLOWLIST, MINSYNC_ALLOWLIST, MINSYNC_LEGACY_IGNORED, P2P_ALLOWLIST, P2P_QUOTA_ALLOWLIST, LIMITS_ALLOWLIST, LIMITS_PREFETCH_ALLOWLIST, JEV_CONFIG_FIELDS, JEV_BACKEND_NAMES, DEFAULT_JEV_BACKEND = "openrouter", DEFAULT_QUERY_DECOMPOSITION_MODEL, RERANK_ALLOWLIST, UNKNOWN_MODEL_HINT = "Add baseUrl (and optional api/apiKeyEnv) for an OpenAI-compatible endpoint outside the pi-ai catalog, or use a pi-ai catalog model id.", modelRuntimeCache;
|
|
29069
|
-
var
|
|
29495
|
+
var init_config3 = __esm(() => {
|
|
29070
29496
|
init_local_model();
|
|
29497
|
+
init_provider();
|
|
29071
29498
|
init_home();
|
|
29072
29499
|
init_factory();
|
|
29073
29500
|
init_file_lock();
|
|
@@ -29162,7 +29589,6 @@ class AutoRAGLite {
|
|
|
29162
29589
|
agent;
|
|
29163
29590
|
retrievalEngine;
|
|
29164
29591
|
memory;
|
|
29165
|
-
sessions = new Map;
|
|
29166
29592
|
constructor(config) {
|
|
29167
29593
|
this.config = config;
|
|
29168
29594
|
const agentOptions = buildAgentOptions(config);
|
|
@@ -29217,14 +29643,11 @@ class AutoRAGLite {
|
|
|
29217
29643
|
return this.retrievalEngine.retrieveByMethod(query, options);
|
|
29218
29644
|
}
|
|
29219
29645
|
recordStructuredResultsSession(sessionId, query, details) {
|
|
29220
|
-
return recordStructuredResultsSession(sessionId, query, details, this.
|
|
29646
|
+
return recordStructuredResultsSession(sessionId, query, details, this.memory);
|
|
29221
29647
|
}
|
|
29222
29648
|
recordReport(query, details) {
|
|
29223
29649
|
return this.recordStructuredResultsSession(randomUUID10(), query, details);
|
|
29224
29650
|
}
|
|
29225
|
-
getResultRegistry(sessionId) {
|
|
29226
|
-
return this.sessions.get(sessionId)?.registry ?? new Map;
|
|
29227
|
-
}
|
|
29228
29651
|
getMemorySchema() {
|
|
29229
29652
|
return structuredClone(this.memory.getSchema());
|
|
29230
29653
|
}
|
|
@@ -29242,9 +29665,9 @@ function createAutoRAGLite(options = {}) {
|
|
|
29242
29665
|
var init_core = __esm(() => {
|
|
29243
29666
|
init_agent();
|
|
29244
29667
|
init_search_documents();
|
|
29245
|
-
|
|
29668
|
+
init_config3();
|
|
29246
29669
|
init_memory();
|
|
29247
|
-
|
|
29670
|
+
init_config3();
|
|
29248
29671
|
});
|
|
29249
29672
|
|
|
29250
29673
|
// src/cli/output.ts
|
|
@@ -29418,7 +29841,8 @@ function searchEnvelope(resp, debug) {
|
|
|
29418
29841
|
if (r.source !== undefined)
|
|
29419
29842
|
base.source = r.source;
|
|
29420
29843
|
if (debug) {
|
|
29421
|
-
|
|
29844
|
+
if (r.confidence !== undefined)
|
|
29845
|
+
base.confidence = r.confidence;
|
|
29422
29846
|
base.evidence = r.evidence.map((e) => {
|
|
29423
29847
|
const ev = { excerpt: e.excerpt };
|
|
29424
29848
|
if (e.lineNumber !== undefined)
|
|
@@ -29455,7 +29879,8 @@ function renderSearchHuman(resp, debug) {
|
|
|
29455
29879
|
if (r.summary)
|
|
29456
29880
|
lines.push(` ${r.summary}`);
|
|
29457
29881
|
if (debug) {
|
|
29458
|
-
|
|
29882
|
+
if (r.confidence !== undefined)
|
|
29883
|
+
lines.push(` confidence: ${r.confidence}`);
|
|
29459
29884
|
for (const ev of r.evidence) {
|
|
29460
29885
|
const ln = ev.lineNumber !== undefined ? ` (line ${ev.lineNumber})` : "";
|
|
29461
29886
|
lines.push(` evidence${ln}: ${ev.excerpt}`);
|
|
@@ -29687,7 +30112,61 @@ async function runEvidence(ctx) {
|
|
|
29687
30112
|
}
|
|
29688
30113
|
var init_evidence = __esm(() => {
|
|
29689
30114
|
init_memory();
|
|
29690
|
-
|
|
30115
|
+
init_config3();
|
|
30116
|
+
});
|
|
30117
|
+
|
|
30118
|
+
// src/agent/results.ts
|
|
30119
|
+
import { Type as Type17 } from "typebox";
|
|
30120
|
+
var evidenceRefSchema, answerSchema, warningsSchema, curatedResultFields, reportSchema;
|
|
30121
|
+
var init_results = __esm(() => {
|
|
30122
|
+
evidenceRefSchema = Type17.Object({
|
|
30123
|
+
method: Type17.String({ description: "Retrieval method namespace for this evidence chunk" }),
|
|
30124
|
+
source: Type17.String({ description: "Internal opaque source identifier for this evidence chunk" }),
|
|
30125
|
+
excerpt: Type17.Optional(Type17.String({ description: "Evidence excerpt used for stable ID normalization" })),
|
|
30126
|
+
content: Type17.Optional(Type17.String({ description: "Evidence content used for stable ID normalization" })),
|
|
30127
|
+
retrievalResultId: Type17.Optional(Type17.String({ description: "Backend retrieval ID when path-opaque and stable" })),
|
|
30128
|
+
chunkIndex: Type17.Optional(Type17.Integer({ description: "Chunk index, if available" })),
|
|
30129
|
+
lineNumber: Type17.Optional(Type17.Integer({ description: "Line number, if available" })),
|
|
30130
|
+
stableEvidenceId: Type17.Optional(Type17.String({ description: "Stable evidence ID, if already normalized" })),
|
|
30131
|
+
retrieverMix: Type17.Optional(Type17.Array(Type17.String({ maxLength: 64 }), {
|
|
30132
|
+
description: "Retrievers that contributed to this result",
|
|
30133
|
+
maxItems: 8
|
|
30134
|
+
})),
|
|
30135
|
+
parserType: Type17.Optional(Type17.String({ description: "Parser that produced this evidence", maxLength: 120 })),
|
|
30136
|
+
documentType: Type17.Optional(Type17.String({ description: "Document type, if known", maxLength: 120 })),
|
|
30137
|
+
documentArea: Type17.Optional(Type17.String({ description: "Document collection area, if known", maxLength: 120 })),
|
|
30138
|
+
evidenceType: Type17.Optional(Type17.String({ description: "Evidence type, if known", maxLength: 120 })),
|
|
30139
|
+
evidenceLocation: Type17.Optional(Type17.String({ description: "Human-readable evidence location", maxLength: 120 })),
|
|
30140
|
+
confidence: Type17.Optional(Type17.Number({ description: "Evidence confidence, 0..1", minimum: 0, maximum: 1 }))
|
|
30141
|
+
});
|
|
30142
|
+
answerSchema = Type17.String({
|
|
30143
|
+
description: `Answer for the caller. At most 5 bullet points (plus optional explanation); reference results by bracketed number (e.g. [1], [2]) without file paths or raw chunk text, except the image-embed exception below. ${ANSWER_CITATION_RULE} ${ANSWER_IMAGE_EMBED_RULE}`
|
|
30144
|
+
});
|
|
30145
|
+
warningsSchema = Type17.Optional(Type17.Array(Type17.String(), { description: "Optional warnings about this result set" }));
|
|
30146
|
+
curatedResultFields = {
|
|
30147
|
+
number: Type17.Integer({ description: "1-based result number" }),
|
|
30148
|
+
title: Type17.String({ description: "Short name of the curated knowledge unit" }),
|
|
30149
|
+
summary: Type17.String({ description: "Key insight: purpose, details, and line range" }),
|
|
30150
|
+
evidence: Type17.Array(Type17.Object({
|
|
30151
|
+
excerpt: Type17.String({ description: "Supporting excerpt" }),
|
|
30152
|
+
lineNumber: Type17.Optional(Type17.Integer({ description: "Line number of the excerpt, if known" }))
|
|
30153
|
+
})),
|
|
30154
|
+
confidence: Type17.Number({ description: "Confidence in this result, 0..1", minimum: 0, maximum: 1 })
|
|
30155
|
+
};
|
|
30156
|
+
reportSchema = Type17.Object({
|
|
30157
|
+
answer: answerSchema,
|
|
30158
|
+
results: Type17.Array(Type17.Object(curatedResultFields), { description: "Numbered curated knowledge units." }),
|
|
30159
|
+
mapping: Type17.Array(Type17.Object({
|
|
30160
|
+
number: Type17.Integer({ description: "Matches the result number this entry maps" }),
|
|
30161
|
+
source: Type17.String({ description: "Source identifier — a real file path or a datasource id" }),
|
|
30162
|
+
method: Type17.String({ description: "Retrieval method or tool that produced the source" }),
|
|
30163
|
+
content: Type17.String({ description: "Raw content snippet of the evidence behind this result" }),
|
|
30164
|
+
evidenceRefs: Type17.Optional(Type17.Array(evidenceRefSchema, {
|
|
30165
|
+
description: "Hidden evidence chunk references supporting this curated result"
|
|
30166
|
+
}))
|
|
30167
|
+
}), { description: "Internal number -> source/method mapping. One entry per result number." }),
|
|
30168
|
+
warnings: warningsSchema
|
|
30169
|
+
});
|
|
29691
30170
|
});
|
|
29692
30171
|
|
|
29693
30172
|
// src/cli/commands/report.ts
|
|
@@ -29785,9 +30264,9 @@ async function runReport(ctx) {
|
|
|
29785
30264
|
}
|
|
29786
30265
|
var MAX_REPORTED_SCHEMA_ERRORS = 8;
|
|
29787
30266
|
var init_report = __esm(() => {
|
|
29788
|
-
|
|
30267
|
+
init_results();
|
|
29789
30268
|
init_core();
|
|
29790
|
-
|
|
30269
|
+
init_config3();
|
|
29791
30270
|
});
|
|
29792
30271
|
|
|
29793
30272
|
// src/mcp/index.ts
|
|
@@ -29809,7 +30288,7 @@ import { z as z2 } from "zod";
|
|
|
29809
30288
|
// src/filesystem/name-search.ts
|
|
29810
30289
|
import { realpathSync as realpathSync6 } from "node:fs";
|
|
29811
30290
|
import { lstat, readdir as readdir4 } from "node:fs/promises";
|
|
29812
|
-
import { basename as basename15, dirname as dirname24, isAbsolute as
|
|
30291
|
+
import { basename as basename15, dirname as dirname24, isAbsolute as isAbsolute10, join as join37, relative as relative6, resolve as resolve16, sep as sep7 } from "node:path";
|
|
29813
30292
|
var SKIP_DIR_NAMES2 = {
|
|
29814
30293
|
".git": true,
|
|
29815
30294
|
".autorag": true,
|
|
@@ -29956,7 +30435,7 @@ async function pinConfiguredRoots(roots, diagnostics) {
|
|
|
29956
30435
|
return outermost;
|
|
29957
30436
|
}
|
|
29958
30437
|
async function resolveRequestRoots(requestRoot, pinnedRoots) {
|
|
29959
|
-
const candidates =
|
|
30438
|
+
const candidates = isAbsolute10(requestRoot) ? [requestRoot] : pinnedRoots.map((root) => resolve16(root, requestRoot));
|
|
29960
30439
|
const allowed = [];
|
|
29961
30440
|
for (const candidate of candidates) {
|
|
29962
30441
|
let real;
|