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