@autorag/librarian 2.13.3 → 2.13.4
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/NOTICE +3 -0
- package/README.md +0 -1
- package/dist/agent/context-token-guard.d.ts +11 -6
- package/dist/agent/token-count.d.ts +4 -0
- package/dist/cli/index.js +230 -631
- package/dist/core.js +146 -546
- package/dist/datasource/connector-skill.d.ts +1 -1
- package/dist/datasource/connector.d.ts +1 -1
- package/dist/datasource/index.d.ts +0 -1
- package/dist/index.js +148 -551
- package/dist/mcp/index.js +148 -548
- package/dist/profiles.js +231 -631
- package/package.json +2 -1
- package/skills/autorag-doctor/SKILL.md +1 -2
- package/skills/autorag-lite-setup/SKILL.md +1 -1
- package/skills/autorag-setup/SKILL.md +3 -4
- package/dist/datasource/skills/spotlight/connector.d.ts +0 -53
- package/dist/datasource/skills/spotlight/index.d.ts +0 -2
- package/dist/datasource/skills/spotlight/skill.d.ts +0 -33
package/dist/index.js
CHANGED
|
@@ -24334,413 +24334,6 @@ var init_slack = __esm(() => {
|
|
|
24334
24334
|
};
|
|
24335
24335
|
});
|
|
24336
24336
|
|
|
24337
|
-
// src/datasource/skills/spotlight/connector.ts
|
|
24338
|
-
import { spawn as spawn19 } from "node:child_process";
|
|
24339
|
-
import { createHash as createHash19 } from "node:crypto";
|
|
24340
|
-
import { readFile as fsReadFile, stat as stat5 } from "node:fs/promises";
|
|
24341
|
-
import { basename as basename11, extname as extname7 } from "node:path";
|
|
24342
|
-
|
|
24343
|
-
class SpotlightConnector {
|
|
24344
|
-
options;
|
|
24345
|
-
run;
|
|
24346
|
-
readFile;
|
|
24347
|
-
platform;
|
|
24348
|
-
constructor(options = {}) {
|
|
24349
|
-
this.options = options;
|
|
24350
|
-
this.run = options.run ?? spawnRunner;
|
|
24351
|
-
this.readFile = options.readFile ?? ((path) => fsReadFile(path, "utf8"));
|
|
24352
|
-
this.platform = options.platform ?? process.platform;
|
|
24353
|
-
}
|
|
24354
|
-
async probe() {
|
|
24355
|
-
const queries = (this.options.queries ?? []).map((query) => query.trim()).filter((query) => query.length > 0);
|
|
24356
|
-
const failure = await this.readinessFailure(queries);
|
|
24357
|
-
return failure ?? { ok: true, documents: [] };
|
|
24358
|
-
}
|
|
24359
|
-
async search(query, limit = DEFAULT_MAX_DOCUMENTS4, acceptDocument) {
|
|
24360
|
-
const trimmed = query.trim();
|
|
24361
|
-
if (trimmed.length === 0 || limit <= 0)
|
|
24362
|
-
return { ok: true, documents: [] };
|
|
24363
|
-
const queries = (this.options.queries ?? []).map((query) => query.trim()).filter((query) => query.length > 0);
|
|
24364
|
-
const failure = await this.readinessFailure(queries);
|
|
24365
|
-
if (failure !== undefined)
|
|
24366
|
-
return failure;
|
|
24367
|
-
const timeoutMs = this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS11;
|
|
24368
|
-
const maxPerQuery = this.options.maxResultsPerQuery ?? DEFAULT_MAX_RESULTS_PER_QUERY;
|
|
24369
|
-
const maxDocuments = Math.min(this.options.maxDocuments ?? DEFAULT_MAX_DOCUMENTS4, limit);
|
|
24370
|
-
const seen = new Set;
|
|
24371
|
-
const paths = [];
|
|
24372
|
-
const textQuery = trimmed.split(/\s+/u).map((term) => `"${term.replace(/\\/gu, "\\\\").replace(/"/gu, "\\\"")}"`).join(" AND ");
|
|
24373
|
-
let mdfindMissing = false;
|
|
24374
|
-
let failedQueries = 0;
|
|
24375
|
-
const failures = [];
|
|
24376
|
-
for (const filter of queries) {
|
|
24377
|
-
const query = `(${filter}) AND (${textQuery})`;
|
|
24378
|
-
const args = this.options.onlyIn !== undefined ? ["-onlyin", this.options.onlyIn, query] : [query];
|
|
24379
|
-
const result = await this.run("mdfind", args, timeoutMs);
|
|
24380
|
-
if (!result.ok) {
|
|
24381
|
-
if (result.error === "ENOENT") {
|
|
24382
|
-
mdfindMissing = true;
|
|
24383
|
-
break;
|
|
24384
|
-
}
|
|
24385
|
-
failedQueries += 1;
|
|
24386
|
-
failures.push(result);
|
|
24387
|
-
continue;
|
|
24388
|
-
}
|
|
24389
|
-
let kept = 0;
|
|
24390
|
-
for (const line of result.stdout.split(`
|
|
24391
|
-
`)) {
|
|
24392
|
-
const path = line.trim();
|
|
24393
|
-
if (path.length === 0 || seen.has(path))
|
|
24394
|
-
continue;
|
|
24395
|
-
if (kept >= maxPerQuery)
|
|
24396
|
-
break;
|
|
24397
|
-
seen.add(path);
|
|
24398
|
-
paths.push(path);
|
|
24399
|
-
kept += 1;
|
|
24400
|
-
}
|
|
24401
|
-
}
|
|
24402
|
-
if (mdfindMissing) {
|
|
24403
|
-
return { ok: false, reason: "unavailable", message: "mdfind binary not found; Spotlight requires macOS" };
|
|
24404
|
-
}
|
|
24405
|
-
if (failedQueries === queries.length) {
|
|
24406
|
-
return {
|
|
24407
|
-
ok: false,
|
|
24408
|
-
reason: "unavailable",
|
|
24409
|
-
message: "every configured mdfind query failed",
|
|
24410
|
-
stderr: failures[0]?.stderr,
|
|
24411
|
-
stdout: failures[0]?.stdout,
|
|
24412
|
-
code: failures[0]?.code
|
|
24413
|
-
};
|
|
24414
|
-
}
|
|
24415
|
-
const documents = [];
|
|
24416
|
-
let permissionDenied = 0;
|
|
24417
|
-
let readFailures = 0;
|
|
24418
|
-
const maxBytes = this.options.maxBytesPerFile ?? DEFAULT_MAX_BYTES_PER_FILE2;
|
|
24419
|
-
const maxContentChars = this.options.maxContentChars ?? MAX_CONTENT_CHARS4;
|
|
24420
|
-
for (const path of paths) {
|
|
24421
|
-
if (documents.length >= maxDocuments)
|
|
24422
|
-
break;
|
|
24423
|
-
const docId = createHash19("sha256").update(path).digest("hex").slice(0, 16);
|
|
24424
|
-
if (acceptDocument !== undefined && !acceptDocument(docId))
|
|
24425
|
-
continue;
|
|
24426
|
-
try {
|
|
24427
|
-
const info = await stat5(path);
|
|
24428
|
-
if (!info.isFile() || info.size > maxBytes)
|
|
24429
|
-
continue;
|
|
24430
|
-
const text = await this.readFile(path);
|
|
24431
|
-
const content = text.trim().slice(0, maxContentChars);
|
|
24432
|
-
if (content.length === 0)
|
|
24433
|
-
continue;
|
|
24434
|
-
documents.push({
|
|
24435
|
-
docId,
|
|
24436
|
-
hierarchy: ["files"],
|
|
24437
|
-
title: basename11(path),
|
|
24438
|
-
content,
|
|
24439
|
-
publishedAt: info.mtimeMs,
|
|
24440
|
-
metadata: { path, extension: extname7(path).toLowerCase() }
|
|
24441
|
-
});
|
|
24442
|
-
} catch (error) {
|
|
24443
|
-
const code = error.code;
|
|
24444
|
-
if (code === "EPERM" || code === "EACCES")
|
|
24445
|
-
permissionDenied += 1;
|
|
24446
|
-
else
|
|
24447
|
-
readFailures += 1;
|
|
24448
|
-
}
|
|
24449
|
-
}
|
|
24450
|
-
if (documents.length === 0 && permissionDenied > 0) {
|
|
24451
|
-
return {
|
|
24452
|
-
ok: false,
|
|
24453
|
-
reason: "permission",
|
|
24454
|
-
message: `macOS denied access to all Spotlight hits; ${FDA_GUIDANCE}`
|
|
24455
|
-
};
|
|
24456
|
-
}
|
|
24457
|
-
if (documents.length === 0 && failedQueries > 0) {
|
|
24458
|
-
return {
|
|
24459
|
-
ok: false,
|
|
24460
|
-
reason: "unavailable",
|
|
24461
|
-
message: "some mdfind queries failed and no readable hits remained",
|
|
24462
|
-
stderr: failures[0]?.stderr,
|
|
24463
|
-
stdout: failures[0]?.stdout,
|
|
24464
|
-
code: failures[0]?.code
|
|
24465
|
-
};
|
|
24466
|
-
}
|
|
24467
|
-
const warnings = [];
|
|
24468
|
-
if (failedQueries > 0)
|
|
24469
|
-
warnings.push(`${failedQueries} mdfind quer(y/ies) failed`);
|
|
24470
|
-
if (permissionDenied > 0) {
|
|
24471
|
-
warnings.push(`${permissionDenied} Spotlight hit(s) were denied by macOS privacy protections; ${FDA_GUIDANCE}`);
|
|
24472
|
-
}
|
|
24473
|
-
if (readFailures > 0)
|
|
24474
|
-
warnings.push(`${readFailures} Spotlight hit(s) failed to read`);
|
|
24475
|
-
return { ok: true, documents, ...warnings.length > 0 ? { warnings } : {} };
|
|
24476
|
-
}
|
|
24477
|
-
async readinessFailure(queries) {
|
|
24478
|
-
if (this.platform !== "darwin") {
|
|
24479
|
-
return { ok: false, reason: "unavailable", message: "spotlight datasource is supported on macOS only" };
|
|
24480
|
-
}
|
|
24481
|
-
if (queries.length === 0) {
|
|
24482
|
-
return { ok: false, reason: "not-configured", message: "no spotlight queries configured" };
|
|
24483
|
-
}
|
|
24484
|
-
const timeoutMs = this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS11;
|
|
24485
|
-
const status = await this.run("mdutil", ["-s", "/"], timeoutMs);
|
|
24486
|
-
if (status.ok && /indexing disabled/iu.test(status.stdout)) {
|
|
24487
|
-
return {
|
|
24488
|
-
ok: false,
|
|
24489
|
-
reason: "unavailable",
|
|
24490
|
-
message: "Spotlight indexing is disabled; enable it with `sudo mdutil -i on /`"
|
|
24491
|
-
};
|
|
24492
|
-
}
|
|
24493
|
-
return;
|
|
24494
|
-
}
|
|
24495
|
-
}
|
|
24496
|
-
var DEFAULT_MAX_RESULTS_PER_QUERY = 100, DEFAULT_MAX_DOCUMENTS4 = 300, DEFAULT_MAX_BYTES_PER_FILE2, DEFAULT_TIMEOUT_MS11 = 15000, MAX_CONTENT_CHARS4 = 1e5, MAX_BUFFER_BYTES, FDA_GUIDANCE = "grant Full Disk Access to the terminal or app running AutoRAG (System Settings -> Privacy & Security -> Full Disk Access), then restart it", spawnRunner = (command, args, timeoutMs) => new Promise((resolve) => {
|
|
24497
|
-
const child = spawn19(command, [...args], { stdio: ["ignore", "pipe", "pipe"] });
|
|
24498
|
-
let stdout = "";
|
|
24499
|
-
let stderr = "";
|
|
24500
|
-
let settled = false;
|
|
24501
|
-
const finish = (result) => {
|
|
24502
|
-
if (settled)
|
|
24503
|
-
return;
|
|
24504
|
-
settled = true;
|
|
24505
|
-
clearTimeout(timer);
|
|
24506
|
-
resolve(result);
|
|
24507
|
-
};
|
|
24508
|
-
const timer = setTimeout(() => {
|
|
24509
|
-
child.kill("SIGKILL");
|
|
24510
|
-
finish({ ok: false, stdout, stderr: "process timed out", code: null });
|
|
24511
|
-
}, timeoutMs);
|
|
24512
|
-
child.stdout.setEncoding("utf8");
|
|
24513
|
-
child.stderr.setEncoding("utf8");
|
|
24514
|
-
child.stdout.on("data", (chunk) => {
|
|
24515
|
-
if (stdout.length < MAX_BUFFER_BYTES)
|
|
24516
|
-
stdout += chunk;
|
|
24517
|
-
});
|
|
24518
|
-
child.stderr.on("data", (chunk) => {
|
|
24519
|
-
if (stderr.length < MAX_BUFFER_BYTES)
|
|
24520
|
-
stderr += chunk;
|
|
24521
|
-
});
|
|
24522
|
-
child.on("error", (error) => {
|
|
24523
|
-
finish({ ok: false, stdout, stderr: error.message, code: null, error: error.code });
|
|
24524
|
-
});
|
|
24525
|
-
child.on("close", (code) => {
|
|
24526
|
-
finish({ ok: code === 0, stdout, stderr, code });
|
|
24527
|
-
});
|
|
24528
|
-
});
|
|
24529
|
-
var init_connector5 = __esm(() => {
|
|
24530
|
-
DEFAULT_MAX_BYTES_PER_FILE2 = 256 * 1024;
|
|
24531
|
-
MAX_BUFFER_BYTES = 4 * 1024 * 1024;
|
|
24532
|
-
});
|
|
24533
|
-
|
|
24534
|
-
// src/datasource/skills/spotlight/skill.ts
|
|
24535
|
-
class SpotlightSkill {
|
|
24536
|
-
connector;
|
|
24537
|
-
skillName;
|
|
24538
|
-
instanceId;
|
|
24539
|
-
instances;
|
|
24540
|
-
tags;
|
|
24541
|
-
lastIndexedAt;
|
|
24542
|
-
lastError;
|
|
24543
|
-
constructor(options = {}) {
|
|
24544
|
-
this.skillName = options.skillName ?? "spotlight";
|
|
24545
|
-
this.instanceId = options.instanceId ?? "default";
|
|
24546
|
-
this.instances = options.instances !== undefined && options.instances.length > 0 ? options.instances : [this.instanceId];
|
|
24547
|
-
this.tags = options.tags ?? DEFAULT_TAGS4;
|
|
24548
|
-
this.connector = options.connector ?? new SpotlightConnector(options.connectorOptions ?? {});
|
|
24549
|
-
}
|
|
24550
|
-
describe() {
|
|
24551
|
-
return {
|
|
24552
|
-
name: this.skillName,
|
|
24553
|
-
id: this.skillName,
|
|
24554
|
-
type: "spotlight-search",
|
|
24555
|
-
description: "Live macOS Spotlight search via the built-in mdfind CLI",
|
|
24556
|
-
capabilities: ["files", "macos-only", "local-search", "live-search", "scoped", "external-cli"],
|
|
24557
|
-
tags: this.tags,
|
|
24558
|
-
status: "active",
|
|
24559
|
-
requiresExternalCli: true,
|
|
24560
|
-
datasourceId: this.skillName,
|
|
24561
|
-
instanceId: this.instanceId,
|
|
24562
|
-
instances: this.instances
|
|
24563
|
-
};
|
|
24564
|
-
}
|
|
24565
|
-
polling() {
|
|
24566
|
-
return {
|
|
24567
|
-
mode: "none",
|
|
24568
|
-
...this.lastIndexedAt !== undefined ? { lastIndexedAt: this.lastIndexedAt } : {},
|
|
24569
|
-
...this.lastError !== undefined ? { lastError: this.lastError } : {}
|
|
24570
|
-
};
|
|
24571
|
-
}
|
|
24572
|
-
async index() {
|
|
24573
|
-
try {
|
|
24574
|
-
const result = await this.connector.probe();
|
|
24575
|
-
if (!result.ok) {
|
|
24576
|
-
const code = connectorFailureToDiagnosticCode(result.reason);
|
|
24577
|
-
const message = boundDiagnosticText(result.message ?? result.reason);
|
|
24578
|
-
this.lastError = message;
|
|
24579
|
-
return this.fail(code, message);
|
|
24580
|
-
}
|
|
24581
|
-
this.lastError = undefined;
|
|
24582
|
-
this.lastIndexedAt = Date.now();
|
|
24583
|
-
return {
|
|
24584
|
-
ok: true,
|
|
24585
|
-
instanceId: this.instanceId,
|
|
24586
|
-
skill: this.skillName,
|
|
24587
|
-
chunkCount: 0,
|
|
24588
|
-
indexedAt: this.lastIndexedAt,
|
|
24589
|
-
diagnostics: [this.note(LIVE_NOTE, "datasource-empty", "info")]
|
|
24590
|
-
};
|
|
24591
|
-
} catch (error) {
|
|
24592
|
-
const message = boundDiagnosticText(error instanceof Error ? error.message : "spotlight probe failed");
|
|
24593
|
-
this.lastError = message;
|
|
24594
|
-
return this.fail("datasource-unavailable", message);
|
|
24595
|
-
}
|
|
24596
|
-
}
|
|
24597
|
-
retrievalMethods() {
|
|
24598
|
-
return [new SpotlightLiveMethod(this)];
|
|
24599
|
-
}
|
|
24600
|
-
describeSources() {
|
|
24601
|
-
return this.instances.map((instanceId) => ({
|
|
24602
|
-
source: datasourceSourcePath(this.skillName, instanceId),
|
|
24603
|
-
datasourceId: this.skillName,
|
|
24604
|
-
skill: this.skillName,
|
|
24605
|
-
instanceId,
|
|
24606
|
-
contentType: "document",
|
|
24607
|
-
metadata: { datasourceId: this.skillName, instanceId, tags: this.tags }
|
|
24608
|
-
}));
|
|
24609
|
-
}
|
|
24610
|
-
skillManifest() {
|
|
24611
|
-
const scopes = this.instances.map((instanceId) => `- \`${datasourceSourcePath(this.skillName, instanceId)}\``).join(`
|
|
24612
|
-
`);
|
|
24613
|
-
return {
|
|
24614
|
-
name: `datasource-${this.skillName}`,
|
|
24615
|
-
description: "Search the current macOS Spotlight index directly. AutoRAG keeps no file snapshot.",
|
|
24616
|
-
content: [
|
|
24617
|
-
"# macOS Spotlight (live mdfind search)",
|
|
24618
|
-
"",
|
|
24619
|
-
"Search files indexed by macOS Spotlight via the built-in `mdfind` CLI. macOS owns and refreshes the index; AutoRAG does not copy files into a local snapshot.",
|
|
24620
|
-
"",
|
|
24621
|
-
"## Platform requirements",
|
|
24622
|
-
"- macOS only: this datasource is unavailable on any other platform.",
|
|
24623
|
-
"- Spotlight indexing must be enabled (`sudo mdutil -i on /`; check with `mdutil -s /`).",
|
|
24624
|
-
"- Full Disk Access may be required to read protected hits. Grant it under System Settings -> Privacy & Security -> Full Disk Access, then restart the host app.",
|
|
24625
|
-
"",
|
|
24626
|
-
"## How to search",
|
|
24627
|
-
`Call the dedicated \`${datasourceSearchToolName(this.skillName)}\` tool with a query and optional narrowing scope. Available scopes:`,
|
|
24628
|
-
scopes,
|
|
24629
|
-
"Each configured Spotlight filter is AND-ed with the user query. Only the requested hits are read; refresh performs a readiness probe without running `mdfind`.",
|
|
24630
|
-
"Result metadata carries the real absolute file path (`path`) so hits are traceable back to disk. If paths must not leave this machine, run AutoRAG with a local LLM.",
|
|
24631
|
-
"",
|
|
24632
|
-
"## Native CLI",
|
|
24633
|
-
"- `mdfind <query>` searches Spotlight; `mdfind -onlyin <dir> <query>` scopes to a directory; `mdfind -name <text>` matches file names.",
|
|
24634
|
-
"- `mdls <file>` shows Spotlight metadata for one file.",
|
|
24635
|
-
"- `mdutil -s /` checks index status; `sudo mdutil -i on /` enables indexing."
|
|
24636
|
-
].join(`
|
|
24637
|
-
`)
|
|
24638
|
-
};
|
|
24639
|
-
}
|
|
24640
|
-
async search(query, options) {
|
|
24641
|
-
const trimmed = query.trim();
|
|
24642
|
-
if (trimmed.length === 0)
|
|
24643
|
-
return [];
|
|
24644
|
-
const scope = options.scope?.trim() ? normalizeVirtualPath2(options.scope) : undefined;
|
|
24645
|
-
if (scope !== undefined) {
|
|
24646
|
-
const chunksRoot = normalizeVirtualPath2(`/${this.skillName}/${this.instanceId}/chunks`);
|
|
24647
|
-
const scopeProbe = datasourceSourcePath(this.skillName, this.instanceId, "__scope_probe__");
|
|
24648
|
-
if (!matchesDatasourceScope(chunksRoot, scope) && !matchesDatasourceScope(scopeProbe, scope) && !scope.startsWith(`${chunksRoot}/`)) {
|
|
24649
|
-
return [];
|
|
24650
|
-
}
|
|
24651
|
-
}
|
|
24652
|
-
const topK = options.topK ?? DEFAULT_TOP_K9;
|
|
24653
|
-
const result = await this.connector.search(trimmed, topK, (docId) => matchesDatasourceScope(datasourceSourcePath(this.skillName, this.instanceId, docId), scope));
|
|
24654
|
-
if (!result.ok) {
|
|
24655
|
-
throw datasourceCliError(this.skillName, "search", {
|
|
24656
|
-
reason: result.reason,
|
|
24657
|
-
stderr: result.stderr ?? result.message,
|
|
24658
|
-
stdout: result.stdout,
|
|
24659
|
-
code: result.code
|
|
24660
|
-
});
|
|
24661
|
-
}
|
|
24662
|
-
const hits = [];
|
|
24663
|
-
for (const [index, document] of result.documents.entries()) {
|
|
24664
|
-
const source = datasourceSourcePath(this.skillName, this.instanceId, document.docId);
|
|
24665
|
-
if (!matchesDatasourceScope(source, options.scope))
|
|
24666
|
-
continue;
|
|
24667
|
-
hits.push({
|
|
24668
|
-
id: `${this.skillName}:${this.instanceId}:${document.docId}`,
|
|
24669
|
-
content: document.content,
|
|
24670
|
-
source,
|
|
24671
|
-
score: 1 / (index + 1),
|
|
24672
|
-
metadata: {
|
|
24673
|
-
...document.metadata,
|
|
24674
|
-
method: `${this.skillName}-live`,
|
|
24675
|
-
datasourceId: this.skillName,
|
|
24676
|
-
instanceId: this.instanceId,
|
|
24677
|
-
chunkId: document.docId,
|
|
24678
|
-
...document.title !== undefined ? { title: document.title } : {},
|
|
24679
|
-
...document.hierarchy !== undefined && document.hierarchy.length > 0 ? { hierarchy: document.hierarchy.join("/") } : {},
|
|
24680
|
-
...document.publishedAt !== undefined ? { publishedAt: document.publishedAt } : {},
|
|
24681
|
-
...result.warnings !== undefined && result.warnings.length > 0 ? { warnings: result.warnings } : {}
|
|
24682
|
-
}
|
|
24683
|
-
});
|
|
24684
|
-
if (hits.length >= topK)
|
|
24685
|
-
break;
|
|
24686
|
-
}
|
|
24687
|
-
return hits;
|
|
24688
|
-
}
|
|
24689
|
-
fail(code, message) {
|
|
24690
|
-
return {
|
|
24691
|
-
ok: false,
|
|
24692
|
-
instanceId: this.instanceId,
|
|
24693
|
-
skill: this.skillName,
|
|
24694
|
-
indexedAt: Date.now(),
|
|
24695
|
-
diagnostics: [
|
|
24696
|
-
this.note(message, code, code === "datasource-unavailable" || code === "datasource-empty" ? "warning" : "error")
|
|
24697
|
-
],
|
|
24698
|
-
error: message,
|
|
24699
|
-
code,
|
|
24700
|
-
message
|
|
24701
|
-
};
|
|
24702
|
-
}
|
|
24703
|
-
note(message, code, severity) {
|
|
24704
|
-
return { code, severity, message, instanceId: this.instanceId, source: this.skillName };
|
|
24705
|
-
}
|
|
24706
|
-
}
|
|
24707
|
-
|
|
24708
|
-
class SpotlightLiveMethod {
|
|
24709
|
-
skill;
|
|
24710
|
-
constructor(skill) {
|
|
24711
|
-
this.skill = skill;
|
|
24712
|
-
}
|
|
24713
|
-
describe() {
|
|
24714
|
-
const descriptor = this.skill.describe();
|
|
24715
|
-
return {
|
|
24716
|
-
name: `${descriptor.datasourceId ?? "spotlight"}-live`,
|
|
24717
|
-
type: "remote",
|
|
24718
|
-
description: "Live macOS Spotlight search via mdfind",
|
|
24719
|
-
status: "active",
|
|
24720
|
-
capabilities: ["live-search", "scoped", "external-cli", "path-opaque-sources"],
|
|
24721
|
-
datasourceId: descriptor.datasourceId,
|
|
24722
|
-
tags: descriptor.tags
|
|
24723
|
-
};
|
|
24724
|
-
}
|
|
24725
|
-
retrieve(query, options) {
|
|
24726
|
-
return this.skill.search(query, options);
|
|
24727
|
-
}
|
|
24728
|
-
}
|
|
24729
|
-
var DEFAULT_TAGS4, DEFAULT_TOP_K9 = 20, LIVE_NOTE = "live-search datasource: macOS owns the Spotlight index; AutoRAG stores no snapshot";
|
|
24730
|
-
var init_skill12 = __esm(() => {
|
|
24731
|
-
init_connector();
|
|
24732
|
-
init_errors4();
|
|
24733
|
-
init_scope2();
|
|
24734
|
-
init_connector5();
|
|
24735
|
-
DEFAULT_TAGS4 = ["spotlight", "files"];
|
|
24736
|
-
});
|
|
24737
|
-
|
|
24738
|
-
// src/datasource/skills/spotlight/index.ts
|
|
24739
|
-
var init_spotlight = __esm(() => {
|
|
24740
|
-
init_connector5();
|
|
24741
|
-
init_skill12();
|
|
24742
|
-
});
|
|
24743
|
-
|
|
24744
24337
|
// src/datasource/skills/telecrawl/index.ts
|
|
24745
24338
|
function globalArgs3(options) {
|
|
24746
24339
|
return [
|
|
@@ -25145,7 +24738,6 @@ var init_factory = __esm(() => {
|
|
|
25145
24738
|
init_obsidian();
|
|
25146
24739
|
init_rss();
|
|
25147
24740
|
init_slack();
|
|
25148
|
-
init_spotlight();
|
|
25149
24741
|
init_telecrawl();
|
|
25150
24742
|
init_wacrawl();
|
|
25151
24743
|
BUILDERS = {
|
|
@@ -25282,12 +24874,6 @@ var init_factory = __esm(() => {
|
|
|
25282
24874
|
...common(config, workspaceRoot),
|
|
25283
24875
|
skillName: registrationName,
|
|
25284
24876
|
connectorOptions: config.connector
|
|
25285
|
-
}),
|
|
25286
|
-
spotlight: (config, _workspaceRoot, registrationName) => new SpotlightSkill({
|
|
25287
|
-
...config.instanceId !== undefined ? { instanceId: config.instanceId } : {},
|
|
25288
|
-
...config.tags !== undefined ? { tags: config.tags } : {},
|
|
25289
|
-
skillName: registrationName,
|
|
25290
|
-
connectorOptions: config.connector
|
|
25291
24877
|
})
|
|
25292
24878
|
};
|
|
25293
24879
|
PLATFORM_ONLY_SKILLS = { kakao: "darwin" };
|
|
@@ -25297,7 +24883,7 @@ var init_factory = __esm(() => {
|
|
|
25297
24883
|
// src/cli/config.ts
|
|
25298
24884
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
25299
24885
|
import { existsSync as existsSync27, mkdirSync as mkdirSync22, readFileSync as readFileSync24, unlinkSync as unlinkSync3, writeFileSync as writeFileSync15 } from "node:fs";
|
|
25300
|
-
import { basename as
|
|
24886
|
+
import { basename as basename11, dirname as dirname23, isAbsolute as isAbsolute11, join as join42, resolve as resolve15 } from "node:path";
|
|
25301
24887
|
import { findEnvKeys, getEnvApiKey } from "@earendil-works/pi-ai/compat";
|
|
25302
24888
|
import { getAgentDir as getAgentDir2, ModelRuntime, SettingsManager } from "@earendil-works/pi-coding-agent";
|
|
25303
24889
|
function resolveConfigPath(input) {
|
|
@@ -25371,7 +24957,7 @@ function acquireConfigWriteLock(configPath) {
|
|
|
25371
24957
|
});
|
|
25372
24958
|
}
|
|
25373
24959
|
function replaceFileAtomically(path, contents, assertCommitAllowed) {
|
|
25374
|
-
const temporaryPath = join42(dirname23(path), `.${
|
|
24960
|
+
const temporaryPath = join42(dirname23(path), `.${basename11(path)}.${process.pid}.${randomUUID6()}.tmp`);
|
|
25375
24961
|
try {
|
|
25376
24962
|
writeFileSync15(temporaryPath, contents, { encoding: "utf8", flag: "wx", flush: true, mode: 384 });
|
|
25377
24963
|
assertCommitAllowed?.();
|
|
@@ -26882,6 +26468,42 @@ function loopGuardPrompt(rule) {
|
|
|
26882
26468
|
`);
|
|
26883
26469
|
}
|
|
26884
26470
|
|
|
26471
|
+
// src/agent/token-count.ts
|
|
26472
|
+
import { createHash as createHash19 } from "node:crypto";
|
|
26473
|
+
import { countTokens } from "gpt-tokenizer/encoding/o200k_base";
|
|
26474
|
+
function estimateTextTokens(text) {
|
|
26475
|
+
return Math.max(Math.ceil(text.length / 4), countText(text));
|
|
26476
|
+
}
|
|
26477
|
+
function tokensBeyondCharGuess(parts) {
|
|
26478
|
+
let excess = 0;
|
|
26479
|
+
for (const part of parts)
|
|
26480
|
+
excess += Math.max(0, countText(part) - Math.ceil(part.length / 4));
|
|
26481
|
+
return excess;
|
|
26482
|
+
}
|
|
26483
|
+
function countText(text) {
|
|
26484
|
+
if (text.length === 0)
|
|
26485
|
+
return 0;
|
|
26486
|
+
if (text.length < CACHE_MIN_CHARS)
|
|
26487
|
+
return countTokens(text, PLAIN_TEXT);
|
|
26488
|
+
const key = `${text.length}:${createHash19("sha1").update(text).digest("base64")}`;
|
|
26489
|
+
const hit = cache.get(key);
|
|
26490
|
+
if (hit !== undefined) {
|
|
26491
|
+
cache.delete(key);
|
|
26492
|
+
cache.set(key, hit);
|
|
26493
|
+
return hit;
|
|
26494
|
+
}
|
|
26495
|
+
const count = countTokens(text, PLAIN_TEXT);
|
|
26496
|
+
cache.set(key, count);
|
|
26497
|
+
if (cache.size > CACHE_ENTRIES)
|
|
26498
|
+
cache.delete(cache.keys().next().value);
|
|
26499
|
+
return count;
|
|
26500
|
+
}
|
|
26501
|
+
var PLAIN_TEXT, CACHE_MIN_CHARS = 2000, CACHE_ENTRIES = 64, cache;
|
|
26502
|
+
var init_token_count = __esm(() => {
|
|
26503
|
+
PLAIN_TEXT = { disallowedSpecial: new Set };
|
|
26504
|
+
cache = new Map;
|
|
26505
|
+
});
|
|
26506
|
+
|
|
26885
26507
|
// src/agent/context-token-guard.ts
|
|
26886
26508
|
import { calculateContextTokens, estimateTokens } from "@earendil-works/pi-coding-agent";
|
|
26887
26509
|
function createContextTokenGuardedTransform(model, base, fixedOverheadTokens = () => 0) {
|
|
@@ -26932,50 +26554,40 @@ function guardWithinBudget(model, messages, useReportedUsage = true, fixedOverhe
|
|
|
26932
26554
|
}
|
|
26933
26555
|
let guarded = messages;
|
|
26934
26556
|
if (candidates.length > 0) {
|
|
26935
|
-
const
|
|
26936
|
-
const maximumOmitted = candidates.reduce((total, section) => total + section.blocks.length, 0);
|
|
26557
|
+
const entries = candidates.flatMap((section, sectionIndex) => section.blocks.map((block, blockIndex) => ({ block, sectionIndex, blockIndex })));
|
|
26937
26558
|
const omissionMarker = (count) => `
|
|
26938
26559
|
|
|
26939
26560
|
${GUARD_MARKER} Retrieval candidates omitted: ${count}.
|
|
26940
26561
|
`;
|
|
26941
|
-
|
|
26942
|
-
|
|
26943
|
-
|
|
26944
|
-
|
|
26945
|
-
for (const
|
|
26946
|
-
|
|
26947
|
-
|
|
26948
|
-
if (tokens <= remaining) {
|
|
26949
|
-
kept[sectionIndex]?.push(block);
|
|
26950
|
-
remaining -= tokens;
|
|
26951
|
-
continue;
|
|
26952
|
-
}
|
|
26953
|
-
omitted += section.blocks.length - (kept[sectionIndex]?.length ?? 0);
|
|
26954
|
-
for (const later of candidates.slice(sectionIndex + 1))
|
|
26955
|
-
omitted += later.blocks.length;
|
|
26956
|
-
firstOmitted = sectionIndex;
|
|
26957
|
-
break;
|
|
26958
|
-
}
|
|
26959
|
-
if (firstOmitted !== -1)
|
|
26562
|
+
const markerTokens = candidates.length * Math.ceil(omissionMarker(entries.length).length / 4);
|
|
26563
|
+
let remaining = Math.max(0, budget - estimateContextMessageTokens(base, false) - markerTokens);
|
|
26564
|
+
entries.sort((a, b) => a.block.rank - b.block.rank || a.sectionIndex - b.sectionIndex || a.blockIndex - b.blockIndex);
|
|
26565
|
+
const kept = new Set;
|
|
26566
|
+
for (const { block } of entries) {
|
|
26567
|
+
const tokens = Math.max(1, estimateTextTokens(block.text));
|
|
26568
|
+
if (tokens > remaining)
|
|
26960
26569
|
break;
|
|
26570
|
+
remaining -= tokens;
|
|
26571
|
+
kept.add(block);
|
|
26961
26572
|
}
|
|
26962
|
-
if (
|
|
26963
|
-
const
|
|
26964
|
-
for (const [sectionIndex, messageIndex] of candidateIndexes.entries())
|
|
26965
|
-
candidateByMessage.set(messageIndex, sectionIndex);
|
|
26573
|
+
if (kept.size < entries.length) {
|
|
26574
|
+
const sectionByMessage = new Map(candidateIndexes.map((messageIndex, i) => [messageIndex, candidates[i]]));
|
|
26966
26575
|
guarded = base.map((message, index) => {
|
|
26967
|
-
const
|
|
26968
|
-
if (
|
|
26576
|
+
const section = sectionByMessage.get(index);
|
|
26577
|
+
if (section === undefined)
|
|
26969
26578
|
return message;
|
|
26970
|
-
const
|
|
26971
|
-
const
|
|
26972
|
-
|
|
26579
|
+
const keptBlocks = section.blocks.filter((block) => kept.has(block));
|
|
26580
|
+
const omitted = section.blocks.length - keptBlocks.length;
|
|
26581
|
+
if (omitted === 0)
|
|
26582
|
+
return messages[index] ?? message;
|
|
26583
|
+
const marker = omissionMarker(omitted);
|
|
26584
|
+
return replaceTextContent(message, `${section.prefix}${keptBlocks.map((block) => block.text).join("")}${marker}${section.suffix}`);
|
|
26973
26585
|
});
|
|
26974
26586
|
}
|
|
26975
26587
|
}
|
|
26976
|
-
if (estimateContextMessageTokens(guarded, false) <= budget
|
|
26588
|
+
if (guarded !== messages && estimateContextMessageTokens(guarded, false) <= budget)
|
|
26977
26589
|
return guarded;
|
|
26978
|
-
return
|
|
26590
|
+
return fitNewestToolResult(guarded, budget);
|
|
26979
26591
|
}
|
|
26980
26592
|
function estimateContextMessageTokens(messages, useReportedUsage = false) {
|
|
26981
26593
|
if (useReportedUsage) {
|
|
@@ -26986,82 +26598,37 @@ function estimateContextMessageTokens(messages, useReportedUsage = false) {
|
|
|
26986
26598
|
}
|
|
26987
26599
|
return messages.reduce((total, message) => total + estimateMessageTokens(message), 0);
|
|
26988
26600
|
}
|
|
26989
|
-
function
|
|
26990
|
-
const
|
|
26991
|
-
const
|
|
26992
|
-
|
|
26993
|
-
|
|
26994
|
-
const
|
|
26995
|
-
|
|
26996
|
-
|
|
26997
|
-
|
|
26998
|
-
|
|
26999
|
-
trimmed[index] = fitMessageToTokens(message, Math.max(floorTokens, inputBudget - others));
|
|
27000
|
-
};
|
|
27001
|
-
for (const [index, message] of trimmed.entries()) {
|
|
27002
|
-
if (index === lastIndex || index === queryIndex || message.role === "system")
|
|
27003
|
-
continue;
|
|
27004
|
-
const replacement = replaceMessageWithMarker(message);
|
|
27005
|
-
if (replacement === message || estimateMessageTokens(replacement) >= estimateMessageTokens(message))
|
|
27006
|
-
continue;
|
|
27007
|
-
trimmed[index] = replacement;
|
|
27008
|
-
if (fits())
|
|
27009
|
-
return trimmed;
|
|
27010
|
-
}
|
|
27011
|
-
if (lastIndex !== queryIndex && trimmed[lastIndex]?.role !== "system") {
|
|
27012
|
-
fitInto(lastIndex, 0);
|
|
27013
|
-
if (fits())
|
|
27014
|
-
return trimmed;
|
|
27015
|
-
}
|
|
27016
|
-
for (const [index, message] of trimmed.entries()) {
|
|
27017
|
-
if (message.role !== "system")
|
|
27018
|
-
continue;
|
|
27019
|
-
fitInto(index, 0);
|
|
27020
|
-
if (fits())
|
|
27021
|
-
return trimmed;
|
|
27022
|
-
}
|
|
27023
|
-
if (queryIndex >= 0)
|
|
27024
|
-
fitInto(queryIndex, MIN_QUERY_TOKENS);
|
|
27025
|
-
return trimmed;
|
|
26601
|
+
function fitNewestToolResult(messages, inputBudget) {
|
|
26602
|
+
const lastIndex = messages.length - 1;
|
|
26603
|
+
const last = messages[lastIndex];
|
|
26604
|
+
if (last?.role !== "toolResult")
|
|
26605
|
+
return messages;
|
|
26606
|
+
const others = messages.reduce((total, message, index) => index === lastIndex ? total : total + estimateMessageTokens(message), 0);
|
|
26607
|
+
if (others >= inputBudget)
|
|
26608
|
+
return messages;
|
|
26609
|
+
const fitted = fitMessageToTokens(last, inputBudget - others);
|
|
26610
|
+
return fitted === last ? messages : [...messages.slice(0, lastIndex), fitted];
|
|
27026
26611
|
}
|
|
27027
26612
|
function fitMessageToTokens(message, maxTokens) {
|
|
27028
26613
|
const original = textContent(message);
|
|
27029
26614
|
if (original === undefined)
|
|
27030
|
-
return
|
|
26615
|
+
return message;
|
|
27031
26616
|
const marker = `
|
|
27032
26617
|
|
|
27033
26618
|
${GUARD_MARKER}
|
|
27034
26619
|
`;
|
|
27035
|
-
|
|
27036
|
-
|
|
27037
|
-
let
|
|
27038
|
-
|
|
27039
|
-
const
|
|
27040
|
-
const
|
|
27041
|
-
if (
|
|
27042
|
-
|
|
27043
|
-
|
|
27044
|
-
|
|
27045
|
-
high = middle - 1;
|
|
27046
|
-
}
|
|
26620
|
+
const overhead = estimateMessageTokens(replaceTextContent(message, ""));
|
|
26621
|
+
const density = Math.max(0, estimateMessageTokens(message) - overhead) / Math.max(1, original.length);
|
|
26622
|
+
let chars = density > 0 ? Math.floor((maxTokens - overhead) / density) : original.length;
|
|
26623
|
+
for (let attempt = 0;attempt < MAX_FIT_ATTEMPTS && chars > 0; attempt++) {
|
|
26624
|
+
const candidate = replaceTextContent(message, excerpt(original, chars, marker));
|
|
26625
|
+
const tokens = estimateMessageTokens(candidate);
|
|
26626
|
+
if (tokens <= maxTokens)
|
|
26627
|
+
return candidate;
|
|
26628
|
+
const scaled = Math.floor(chars * Math.max(0, maxTokens - overhead) / Math.max(1, tokens - overhead) * 0.98);
|
|
26629
|
+
chars = Math.min(chars - 1, scaled);
|
|
27047
26630
|
}
|
|
27048
|
-
return
|
|
27049
|
-
}
|
|
27050
|
-
function stripNonTextContent(message) {
|
|
27051
|
-
if (message.role !== "user" || typeof message.content === "string")
|
|
27052
|
-
return replaceMessageWithMarker(message);
|
|
27053
|
-
const marker = `
|
|
27054
|
-
|
|
27055
|
-
${GUARD_MARKER}
|
|
27056
|
-
`;
|
|
27057
|
-
let replacedImage = false;
|
|
27058
|
-
const content = message.content.map((block) => {
|
|
27059
|
-
if (block.type === "text")
|
|
27060
|
-
return block;
|
|
27061
|
-
replacedImage = true;
|
|
27062
|
-
return { type: "text", text: marker };
|
|
27063
|
-
});
|
|
27064
|
-
return replacedImage ? { ...message, content } : message;
|
|
26631
|
+
return replaceTextContent(message, marker);
|
|
27065
26632
|
}
|
|
27066
26633
|
function excerpt(text, maxChars, marker) {
|
|
27067
26634
|
if (text.length <= maxChars)
|
|
@@ -27071,32 +26638,54 @@ function excerpt(text, maxChars, marker) {
|
|
|
27071
26638
|
const tail = Math.max(0, available - head);
|
|
27072
26639
|
return `${text.slice(0, head)}${marker}${tail > 0 ? text.slice(-tail) : ""}`;
|
|
27073
26640
|
}
|
|
27074
|
-
function replaceMessageWithMarker(message) {
|
|
27075
|
-
return replaceTextContent(message, `
|
|
27076
|
-
|
|
27077
|
-
${GUARD_MARKER}
|
|
27078
|
-
`);
|
|
27079
|
-
}
|
|
27080
26641
|
function estimateMessageTokens(message) {
|
|
27081
26642
|
if (message.role === "system")
|
|
27082
26643
|
return estimateSystemMessageTokens(message);
|
|
27083
|
-
const estimate = estimateTokens(message);
|
|
26644
|
+
const estimate = estimateTokens(message) + tokensBeyondCharGuess(messageTextParts(message));
|
|
27084
26645
|
return message.role === "toolResult" ? estimate + Math.ceil(message.toolName.length / 4) : estimate;
|
|
27085
26646
|
}
|
|
27086
26647
|
function estimateSystemMessageTokens(message) {
|
|
27087
|
-
|
|
27088
|
-
|
|
26648
|
+
const parts = [];
|
|
26649
|
+
let chars = 0;
|
|
26650
|
+
if (typeof message.content === "string")
|
|
26651
|
+
parts.push(message.content);
|
|
26652
|
+
else {
|
|
27089
26653
|
for (const block of message.content) {
|
|
27090
26654
|
if (block.type === "text")
|
|
27091
|
-
|
|
26655
|
+
parts.push(block.text);
|
|
27092
26656
|
else if (block.type === "image")
|
|
27093
26657
|
chars += 4800;
|
|
27094
26658
|
}
|
|
27095
26659
|
}
|
|
27096
|
-
|
|
27097
|
-
|
|
27098
|
-
|
|
27099
|
-
return Math.ceil(chars / 4);
|
|
26660
|
+
parts.push(JSON.stringify(message.sections ?? {}), JSON.stringify(message.toolsAdded ?? []), JSON.stringify(message.toolsRemoved ?? []));
|
|
26661
|
+
for (const part of parts)
|
|
26662
|
+
chars += part.length;
|
|
26663
|
+
return Math.ceil(chars / 4) + tokensBeyondCharGuess(parts);
|
|
26664
|
+
}
|
|
26665
|
+
function messageTextParts(message) {
|
|
26666
|
+
switch (message.role) {
|
|
26667
|
+
case "user":
|
|
26668
|
+
case "custom":
|
|
26669
|
+
case "toolResult":
|
|
26670
|
+
return typeof message.content === "string" ? [message.content] : message.content.flatMap((block) => block.type === "text" ? [block.text] : []);
|
|
26671
|
+
case "assistant":
|
|
26672
|
+
return message.content.flatMap((block) => {
|
|
26673
|
+
if (block.type === "text")
|
|
26674
|
+
return [block.text];
|
|
26675
|
+
if (block.type === "thinking")
|
|
26676
|
+
return [block.thinking];
|
|
26677
|
+
if (block.type === "toolCall")
|
|
26678
|
+
return [`${block.name}${JSON.stringify(block.arguments)}`];
|
|
26679
|
+
return [];
|
|
26680
|
+
});
|
|
26681
|
+
case "bashExecution":
|
|
26682
|
+
return [message.command, message.output];
|
|
26683
|
+
case "branchSummary":
|
|
26684
|
+
case "compactionSummary":
|
|
26685
|
+
return [message.summary];
|
|
26686
|
+
default:
|
|
26687
|
+
return [];
|
|
26688
|
+
}
|
|
27100
26689
|
}
|
|
27101
26690
|
function findLastAssistantUsage(messages) {
|
|
27102
26691
|
for (let index = messages.length - 1;index >= 0; index--) {
|
|
@@ -27170,7 +26759,7 @@ function parseCandidateSection(message, text) {
|
|
|
27170
26759
|
const sectionEnd = findBaselineSectionEnd(text, sectionStart);
|
|
27171
26760
|
if (!/^\[e?\d+\] /mu.test(text.slice(sectionStart, sectionEnd)))
|
|
27172
26761
|
return;
|
|
27173
|
-
return splitCandidates(text, sectionStart, sectionEnd);
|
|
26762
|
+
return splitCandidates(text, sectionStart, sectionEnd, { lists: true });
|
|
27174
26763
|
}
|
|
27175
26764
|
if (message.role !== "toolResult")
|
|
27176
26765
|
return;
|
|
@@ -27181,7 +26770,9 @@ function parseCandidateSection(message, text) {
|
|
|
27181
26770
|
const directiveStart = text.indexOf(`
|
|
27182
26771
|
|
|
27183
26772
|
directive:`);
|
|
27184
|
-
return splitCandidates(text, 0, directiveStart >= 0 ? directiveStart : text.length,
|
|
26773
|
+
return splitCandidates(text, 0, directiveStart >= 0 ? directiveStart : text.length, {
|
|
26774
|
+
pattern: /^- [^\n]*(?:\n|$)/gmu
|
|
26775
|
+
});
|
|
27185
26776
|
}
|
|
27186
26777
|
const diagnosticsStart = text.indexOf(`
|
|
27187
26778
|
|
|
@@ -27203,17 +26794,23 @@ Formatting and content rules`
|
|
|
27203
26794
|
const positions = endMarkers.map((marker) => text.indexOf(marker, startIndex)).filter((index) => index >= 0);
|
|
27204
26795
|
return positions.length > 0 ? Math.min(...positions) : text.length;
|
|
27205
26796
|
}
|
|
27206
|
-
function splitCandidates(text, sectionStart, sectionEnd,
|
|
26797
|
+
function splitCandidates(text, sectionStart, sectionEnd, options = {}) {
|
|
27207
26798
|
const region = text.slice(sectionStart, sectionEnd);
|
|
27208
|
-
const matches = [...region.matchAll(pattern)];
|
|
26799
|
+
const matches = [...region.matchAll(options.pattern ?? /^\[e?\d+\] [^\n]*(?:\n|$)/gmu)];
|
|
27209
26800
|
const firstStart = matches[0]?.index;
|
|
27210
26801
|
if (firstStart === undefined)
|
|
27211
26802
|
return;
|
|
27212
26803
|
const blocks = [];
|
|
26804
|
+
let rank = 0;
|
|
26805
|
+
let heading = "";
|
|
27213
26806
|
for (const [index, match] of matches.entries()) {
|
|
27214
26807
|
const start = match.index ?? 0;
|
|
27215
26808
|
const end = index + 1 < matches.length ? matches[index + 1]?.index ?? region.length : region.length;
|
|
27216
|
-
|
|
26809
|
+
const raw = region.slice(start, end);
|
|
26810
|
+
const tail = options.lists === true ? LIST_HEADING_TAIL.exec(raw) : null;
|
|
26811
|
+
blocks.push({ text: heading + (tail === null ? raw : raw.slice(0, tail.index)), rank });
|
|
26812
|
+
rank = tail === null ? rank + 1 : 0;
|
|
26813
|
+
heading = tail === null ? "" : tail[0];
|
|
27217
26814
|
}
|
|
27218
26815
|
return {
|
|
27219
26816
|
prefix: text.slice(0, sectionStart) + region.slice(0, firstStart),
|
|
@@ -27221,9 +26818,10 @@ function splitCandidates(text, sectionStart, sectionEnd, pattern = /^\[e?\d+\] [
|
|
|
27221
26818
|
blocks
|
|
27222
26819
|
};
|
|
27223
26820
|
}
|
|
27224
|
-
var CONTEXT_HEADROOM = 1.2, MAX_OUTPUT_TOKENS = 32000,
|
|
26821
|
+
var CONTEXT_HEADROOM = 1.2, MAX_OUTPUT_TOKENS = 32000, GUARD_MARKER = "[AutoRAG context guard: omitted context to stay within the model context budget.]", RETRIEVAL_TOOL_PREFIX = "search_datasource_", RETRIEVAL_TOOL_NAMES, MAX_FIT_ATTEMPTS = 6, LIST_HEADING_TAIL;
|
|
27225
26822
|
var init_context_token_guard = __esm(() => {
|
|
27226
26823
|
init_context_overflow();
|
|
26824
|
+
init_token_count();
|
|
27227
26825
|
RETRIEVAL_TOOL_NAMES = {
|
|
27228
26826
|
jikji_find: true,
|
|
27229
26827
|
search_all_documents: true,
|
|
@@ -27232,6 +26830,7 @@ var init_context_token_guard = __esm(() => {
|
|
|
27232
26830
|
everything_search: true,
|
|
27233
26831
|
fsearch_search: true
|
|
27234
26832
|
};
|
|
26833
|
+
LIST_HEADING_TAIL = /\n[^\n]*initial candidates[^\n]*:\n$/u;
|
|
27235
26834
|
});
|
|
27236
26835
|
|
|
27237
26836
|
// src/agent/current-date.ts
|
|
@@ -27677,7 +27276,7 @@ function guardContext(pi, contextTransform) {
|
|
|
27677
27276
|
pi.on("context", async (event, ctx) => {
|
|
27678
27277
|
const activeTools = new Set(pi.getActiveTools());
|
|
27679
27278
|
const toolDeclarations = pi.getAllTools().filter((tool) => activeTools.has(tool.name)).map(({ name, description, parameters }) => ({ name, description, parameters }));
|
|
27680
|
-
const fixedOverheadTokens =
|
|
27279
|
+
const fixedOverheadTokens = estimateTextTokens(ctx.getSystemPrompt()) + estimateTextTokens(JSON.stringify(toolDeclarations));
|
|
27681
27280
|
return {
|
|
27682
27281
|
messages: await createContextTokenGuardedTransform(ctx.model, contextTransform, () => fixedOverheadTokens)(event.messages)
|
|
27683
27282
|
};
|
|
@@ -27911,6 +27510,7 @@ var init_pi_session = __esm(() => {
|
|
|
27911
27510
|
init_intent_tracing();
|
|
27912
27511
|
init_mcp_client();
|
|
27913
27512
|
init_request_limits();
|
|
27513
|
+
init_token_count();
|
|
27914
27514
|
init_welcome_header();
|
|
27915
27515
|
PI_BUILTIN_TOOL_NAMES = ["read", "bash", "edit", "write", "grep", "find", "ls"];
|
|
27916
27516
|
});
|
|
@@ -29099,7 +28699,7 @@ var init_automation_tool = __esm(() => {
|
|
|
29099
28699
|
});
|
|
29100
28700
|
|
|
29101
28701
|
// src/agent/citation-links.ts
|
|
29102
|
-
import { basename as
|
|
28702
|
+
import { basename as basename12, isAbsolute as isAbsolute12 } from "node:path";
|
|
29103
28703
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
29104
28704
|
function openableTarget(source) {
|
|
29105
28705
|
if (/^https?:\/\//iu.test(source)) {
|
|
@@ -29117,7 +28717,7 @@ function linkCitations(markdown, sourceOf, isFile) {
|
|
|
29117
28717
|
for (const marker of answerMarkers(markdown, isFile)) {
|
|
29118
28718
|
if (marker.kind === "number")
|
|
29119
28719
|
continue;
|
|
29120
|
-
const labels = marker.kind === "file" ? [{ label:
|
|
28720
|
+
const labels = marker.kind === "file" ? [{ label: basename12(marker.path), source: marker.path }] : marker.ids.map((id) => ({ label: id, source: sourceOf(id) }));
|
|
29121
28721
|
let linked = false;
|
|
29122
28722
|
const parts = labels.map(({ label, source }) => {
|
|
29123
28723
|
const target = source === undefined ? undefined : openableTarget(source);
|
|
@@ -30356,7 +29956,7 @@ class DazziJevBackend {
|
|
|
30356
29956
|
this.apiKey = apiKey;
|
|
30357
29957
|
this.baseUrl = options.baseUrl ?? resolveBaseUrl(env);
|
|
30358
29958
|
this.defaultModel = options.defaultModel ?? DAZZI_DEFAULT_JEV_MODEL;
|
|
30359
|
-
this.timeoutMs = options.timeoutMs ??
|
|
29959
|
+
this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS11;
|
|
30360
29960
|
this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
30361
29961
|
this.fetchImpl = options.fetchImpl;
|
|
30362
29962
|
}
|
|
@@ -30543,7 +30143,7 @@ async function extractErrorMessage(response) {
|
|
|
30543
30143
|
function sleep6(ms) {
|
|
30544
30144
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
30545
30145
|
}
|
|
30546
|
-
var JEV_PATH, DAZZI_DEFAULT_JEV_MODEL = "jev-1.13",
|
|
30146
|
+
var JEV_PATH, DAZZI_DEFAULT_JEV_MODEL = "jev-1.13", DEFAULT_TIMEOUT_MS11 = 1e4, DEFAULT_MAX_RETRIES = 2, RETRY_BASE_MS = 500, RETRY_MAX_MS = 5000;
|
|
30547
30147
|
var init_jev_backend = __esm(() => {
|
|
30548
30148
|
init_config();
|
|
30549
30149
|
init_credential();
|
|
@@ -32027,7 +31627,7 @@ var init_page_loader = __esm(() => {
|
|
|
32027
31627
|
});
|
|
32028
31628
|
|
|
32029
31629
|
// src/web/fetch/url-target.ts
|
|
32030
|
-
import { extname as
|
|
31630
|
+
import { extname as extname7 } from "node:path";
|
|
32031
31631
|
function repairCollapsedScheme(value) {
|
|
32032
31632
|
const m = value.match(/^(https?):\/(?!\/)/i);
|
|
32033
31633
|
return m ? `${m[1]}://${value.slice(m[0].length)}` : value;
|
|
@@ -32046,7 +31646,7 @@ function getFilenameExtensionHint(filename) {
|
|
|
32046
31646
|
const lower = filename.toLowerCase();
|
|
32047
31647
|
if (lower.endsWith(".tar.gz"))
|
|
32048
31648
|
return ".tar.gz";
|
|
32049
|
-
return
|
|
31649
|
+
return extname7(filename).toLowerCase();
|
|
32050
31650
|
}
|
|
32051
31651
|
function getExtensionHint(url, contentDisposition) {
|
|
32052
31652
|
if (contentDisposition) {
|
|
@@ -32223,7 +31823,7 @@ var init_convert2 = __esm(() => {
|
|
|
32223
31823
|
});
|
|
32224
31824
|
|
|
32225
31825
|
// src/web/fetch/feeds.ts
|
|
32226
|
-
import { extname as
|
|
31826
|
+
import { extname as extname8 } from "node:path";
|
|
32227
31827
|
import { XMLParser as XMLParser3 } from "fast-xml-parser";
|
|
32228
31828
|
function getHtmlAttribute(tag, attribute) {
|
|
32229
31829
|
const pattern = new RegExp(`\\b${attribute}\\s*=\\s*(?:"([^"]*)"|'([^']*)'|([^\\s"'=<>]+))`, "i");
|
|
@@ -32286,7 +31886,7 @@ function extractDocumentLinks(html, baseUrl) {
|
|
|
32286
31886
|
const href = getHtmlAttribute(tag, "href");
|
|
32287
31887
|
if (!href)
|
|
32288
31888
|
continue;
|
|
32289
|
-
const ext =
|
|
31889
|
+
const ext = extname8(href).toLowerCase();
|
|
32290
31890
|
if (!CONVERTIBLE_EXTENSIONS2.has(ext))
|
|
32291
31891
|
continue;
|
|
32292
31892
|
const resolved = href.startsWith("http") ? href : new URL(href, baseUrl).href;
|
|
@@ -33954,7 +33554,7 @@ var init_web_search_tool = __esm(() => {
|
|
|
33954
33554
|
// src/agent/agent.ts
|
|
33955
33555
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
33956
33556
|
import { existsSync as existsSync34, watch as fsWatch, mkdirSync as mkdirSync25, realpathSync as realpathSync7, statSync as statSync9, writeFileSync as writeFileSync18 } from "node:fs";
|
|
33957
|
-
import { basename as
|
|
33557
|
+
import { basename as basename13, dirname as dirname26, join as join52, resolve as resolve18 } from "node:path";
|
|
33958
33558
|
import { clampThinkingLevel } from "@earendil-works/pi-ai/compat";
|
|
33959
33559
|
import { getAgentDir as getAgentDir5, keyText } from "@earendil-works/pi-coding-agent";
|
|
33960
33560
|
function positiveLimit(value, fallback, path) {
|
|
@@ -36877,7 +36477,7 @@ function toMinSyncReasonDiagnostic(reason) {
|
|
|
36877
36477
|
function pinExcludedPath(path) {
|
|
36878
36478
|
const resolvedPath = resolve18(path);
|
|
36879
36479
|
try {
|
|
36880
|
-
return join52(realpathSync7(dirname26(resolvedPath)),
|
|
36480
|
+
return join52(realpathSync7(dirname26(resolvedPath)), basename13(resolvedPath));
|
|
36881
36481
|
} catch {
|
|
36882
36482
|
return resolvedPath;
|
|
36883
36483
|
}
|
|
@@ -37960,7 +37560,6 @@ init_notion();
|
|
|
37960
37560
|
init_obsidian();
|
|
37961
37561
|
init_rss();
|
|
37962
37562
|
init_slack();
|
|
37963
|
-
init_spotlight();
|
|
37964
37563
|
init_telecrawl();
|
|
37965
37564
|
init_wacrawl();
|
|
37966
37565
|
|
|
@@ -37983,7 +37582,7 @@ import { z as z4 } from "zod";
|
|
|
37983
37582
|
// src/filesystem/name-search.ts
|
|
37984
37583
|
import { realpathSync as realpathSync8 } from "node:fs";
|
|
37985
37584
|
import { lstat, readdir as readdir3 } from "node:fs/promises";
|
|
37986
|
-
import { basename as
|
|
37585
|
+
import { basename as basename14, dirname as dirname27, isAbsolute as isAbsolute13, join as join53, relative as relative8, resolve as resolve19, sep as sep10 } from "node:path";
|
|
37987
37586
|
var SKIP_DIR_NAMES2 = {
|
|
37988
37587
|
".git": true,
|
|
37989
37588
|
".autorag": true,
|
|
@@ -38017,7 +37616,7 @@ function isContained(childReal, parentReal) {
|
|
|
38017
37616
|
function pinExcludedPath2(path) {
|
|
38018
37617
|
const resolvedPath = resolve19(path);
|
|
38019
37618
|
try {
|
|
38020
|
-
return join53(realpathSync8(dirname27(resolvedPath)),
|
|
37619
|
+
return join53(realpathSync8(dirname27(resolvedPath)), basename14(resolvedPath));
|
|
38021
37620
|
} catch {
|
|
38022
37621
|
return resolvedPath;
|
|
38023
37622
|
}
|
|
@@ -38808,8 +38407,6 @@ export {
|
|
|
38808
38407
|
SUPPORTED_RERANK_PROVIDERS,
|
|
38809
38408
|
SlackSkill,
|
|
38810
38409
|
SlacrawlClient,
|
|
38811
|
-
SpotlightConnector,
|
|
38812
|
-
SpotlightSkill,
|
|
38813
38410
|
TARGET_GROUPS,
|
|
38814
38411
|
TOKEN_PATH,
|
|
38815
38412
|
TelecrawlClient,
|