@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/cli/index.js CHANGED
@@ -14577,413 +14577,6 @@ var init_slack = __esm(() => {
14577
14577
  };
14578
14578
  });
14579
14579
 
14580
- // src/datasource/skills/spotlight/connector.ts
14581
- import { spawn as spawn13 } from "node:child_process";
14582
- import { createHash as createHash10 } from "node:crypto";
14583
- import { readFile as fsReadFile, stat as stat2 } from "node:fs/promises";
14584
- import { basename as basename6, extname as extname6 } from "node:path";
14585
-
14586
- class SpotlightConnector {
14587
- options;
14588
- run;
14589
- readFile;
14590
- platform;
14591
- constructor(options = {}) {
14592
- this.options = options;
14593
- this.run = options.run ?? spawnRunner;
14594
- this.readFile = options.readFile ?? ((path) => fsReadFile(path, "utf8"));
14595
- this.platform = options.platform ?? process.platform;
14596
- }
14597
- async probe() {
14598
- const queries = (this.options.queries ?? []).map((query) => query.trim()).filter((query) => query.length > 0);
14599
- const failure = await this.readinessFailure(queries);
14600
- return failure ?? { ok: true, documents: [] };
14601
- }
14602
- async search(query, limit = DEFAULT_MAX_DOCUMENTS4, acceptDocument) {
14603
- const trimmed = query.trim();
14604
- if (trimmed.length === 0 || limit <= 0)
14605
- return { ok: true, documents: [] };
14606
- const queries = (this.options.queries ?? []).map((query) => query.trim()).filter((query) => query.length > 0);
14607
- const failure = await this.readinessFailure(queries);
14608
- if (failure !== undefined)
14609
- return failure;
14610
- const timeoutMs = this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS8;
14611
- const maxPerQuery = this.options.maxResultsPerQuery ?? DEFAULT_MAX_RESULTS_PER_QUERY;
14612
- const maxDocuments = Math.min(this.options.maxDocuments ?? DEFAULT_MAX_DOCUMENTS4, limit);
14613
- const seen = new Set;
14614
- const paths = [];
14615
- const textQuery = trimmed.split(/\s+/u).map((term) => `"${term.replace(/\\/gu, "\\\\").replace(/"/gu, "\\\"")}"`).join(" AND ");
14616
- let mdfindMissing = false;
14617
- let failedQueries = 0;
14618
- const failures = [];
14619
- for (const filter of queries) {
14620
- const query = `(${filter}) AND (${textQuery})`;
14621
- const args = this.options.onlyIn !== undefined ? ["-onlyin", this.options.onlyIn, query] : [query];
14622
- const result = await this.run("mdfind", args, timeoutMs);
14623
- if (!result.ok) {
14624
- if (result.error === "ENOENT") {
14625
- mdfindMissing = true;
14626
- break;
14627
- }
14628
- failedQueries += 1;
14629
- failures.push(result);
14630
- continue;
14631
- }
14632
- let kept = 0;
14633
- for (const line of result.stdout.split(`
14634
- `)) {
14635
- const path = line.trim();
14636
- if (path.length === 0 || seen.has(path))
14637
- continue;
14638
- if (kept >= maxPerQuery)
14639
- break;
14640
- seen.add(path);
14641
- paths.push(path);
14642
- kept += 1;
14643
- }
14644
- }
14645
- if (mdfindMissing) {
14646
- return { ok: false, reason: "unavailable", message: "mdfind binary not found; Spotlight requires macOS" };
14647
- }
14648
- if (failedQueries === queries.length) {
14649
- return {
14650
- ok: false,
14651
- reason: "unavailable",
14652
- message: "every configured mdfind query failed",
14653
- stderr: failures[0]?.stderr,
14654
- stdout: failures[0]?.stdout,
14655
- code: failures[0]?.code
14656
- };
14657
- }
14658
- const documents = [];
14659
- let permissionDenied = 0;
14660
- let readFailures = 0;
14661
- const maxBytes = this.options.maxBytesPerFile ?? DEFAULT_MAX_BYTES_PER_FILE2;
14662
- const maxContentChars = this.options.maxContentChars ?? MAX_CONTENT_CHARS3;
14663
- for (const path of paths) {
14664
- if (documents.length >= maxDocuments)
14665
- break;
14666
- const docId = createHash10("sha256").update(path).digest("hex").slice(0, 16);
14667
- if (acceptDocument !== undefined && !acceptDocument(docId))
14668
- continue;
14669
- try {
14670
- const info = await stat2(path);
14671
- if (!info.isFile() || info.size > maxBytes)
14672
- continue;
14673
- const text = await this.readFile(path);
14674
- const content = text.trim().slice(0, maxContentChars);
14675
- if (content.length === 0)
14676
- continue;
14677
- documents.push({
14678
- docId,
14679
- hierarchy: ["files"],
14680
- title: basename6(path),
14681
- content,
14682
- publishedAt: info.mtimeMs,
14683
- metadata: { path, extension: extname6(path).toLowerCase() }
14684
- });
14685
- } catch (error) {
14686
- const code = error.code;
14687
- if (code === "EPERM" || code === "EACCES")
14688
- permissionDenied += 1;
14689
- else
14690
- readFailures += 1;
14691
- }
14692
- }
14693
- if (documents.length === 0 && permissionDenied > 0) {
14694
- return {
14695
- ok: false,
14696
- reason: "permission",
14697
- message: `macOS denied access to all Spotlight hits; ${FDA_GUIDANCE}`
14698
- };
14699
- }
14700
- if (documents.length === 0 && failedQueries > 0) {
14701
- return {
14702
- ok: false,
14703
- reason: "unavailable",
14704
- message: "some mdfind queries failed and no readable hits remained",
14705
- stderr: failures[0]?.stderr,
14706
- stdout: failures[0]?.stdout,
14707
- code: failures[0]?.code
14708
- };
14709
- }
14710
- const warnings = [];
14711
- if (failedQueries > 0)
14712
- warnings.push(`${failedQueries} mdfind quer(y/ies) failed`);
14713
- if (permissionDenied > 0) {
14714
- warnings.push(`${permissionDenied} Spotlight hit(s) were denied by macOS privacy protections; ${FDA_GUIDANCE}`);
14715
- }
14716
- if (readFailures > 0)
14717
- warnings.push(`${readFailures} Spotlight hit(s) failed to read`);
14718
- return { ok: true, documents, ...warnings.length > 0 ? { warnings } : {} };
14719
- }
14720
- async readinessFailure(queries) {
14721
- if (this.platform !== "darwin") {
14722
- return { ok: false, reason: "unavailable", message: "spotlight datasource is supported on macOS only" };
14723
- }
14724
- if (queries.length === 0) {
14725
- return { ok: false, reason: "not-configured", message: "no spotlight queries configured" };
14726
- }
14727
- const timeoutMs = this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS8;
14728
- const status = await this.run("mdutil", ["-s", "/"], timeoutMs);
14729
- if (status.ok && /indexing disabled/iu.test(status.stdout)) {
14730
- return {
14731
- ok: false,
14732
- reason: "unavailable",
14733
- message: "Spotlight indexing is disabled; enable it with `sudo mdutil -i on /`"
14734
- };
14735
- }
14736
- return;
14737
- }
14738
- }
14739
- var DEFAULT_MAX_RESULTS_PER_QUERY = 100, DEFAULT_MAX_DOCUMENTS4 = 300, DEFAULT_MAX_BYTES_PER_FILE2, DEFAULT_TIMEOUT_MS8 = 15000, MAX_CONTENT_CHARS3 = 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) => {
14740
- const child = spawn13(command, [...args], { stdio: ["ignore", "pipe", "pipe"] });
14741
- let stdout = "";
14742
- let stderr = "";
14743
- let settled = false;
14744
- const finish = (result) => {
14745
- if (settled)
14746
- return;
14747
- settled = true;
14748
- clearTimeout(timer);
14749
- resolve(result);
14750
- };
14751
- const timer = setTimeout(() => {
14752
- child.kill("SIGKILL");
14753
- finish({ ok: false, stdout, stderr: "process timed out", code: null });
14754
- }, timeoutMs);
14755
- child.stdout.setEncoding("utf8");
14756
- child.stderr.setEncoding("utf8");
14757
- child.stdout.on("data", (chunk) => {
14758
- if (stdout.length < MAX_BUFFER_BYTES)
14759
- stdout += chunk;
14760
- });
14761
- child.stderr.on("data", (chunk) => {
14762
- if (stderr.length < MAX_BUFFER_BYTES)
14763
- stderr += chunk;
14764
- });
14765
- child.on("error", (error) => {
14766
- finish({ ok: false, stdout, stderr: error.message, code: null, error: error.code });
14767
- });
14768
- child.on("close", (code) => {
14769
- finish({ ok: code === 0, stdout, stderr, code });
14770
- });
14771
- });
14772
- var init_connector5 = __esm(() => {
14773
- DEFAULT_MAX_BYTES_PER_FILE2 = 256 * 1024;
14774
- MAX_BUFFER_BYTES = 4 * 1024 * 1024;
14775
- });
14776
-
14777
- // src/datasource/skills/spotlight/skill.ts
14778
- class SpotlightSkill {
14779
- connector;
14780
- skillName;
14781
- instanceId;
14782
- instances;
14783
- tags;
14784
- lastIndexedAt;
14785
- lastError;
14786
- constructor(options = {}) {
14787
- this.skillName = options.skillName ?? "spotlight";
14788
- this.instanceId = options.instanceId ?? "default";
14789
- this.instances = options.instances !== undefined && options.instances.length > 0 ? options.instances : [this.instanceId];
14790
- this.tags = options.tags ?? DEFAULT_TAGS4;
14791
- this.connector = options.connector ?? new SpotlightConnector(options.connectorOptions ?? {});
14792
- }
14793
- describe() {
14794
- return {
14795
- name: this.skillName,
14796
- id: this.skillName,
14797
- type: "spotlight-search",
14798
- description: "Live macOS Spotlight search via the built-in mdfind CLI",
14799
- capabilities: ["files", "macos-only", "local-search", "live-search", "scoped", "external-cli"],
14800
- tags: this.tags,
14801
- status: "active",
14802
- requiresExternalCli: true,
14803
- datasourceId: this.skillName,
14804
- instanceId: this.instanceId,
14805
- instances: this.instances
14806
- };
14807
- }
14808
- polling() {
14809
- return {
14810
- mode: "none",
14811
- ...this.lastIndexedAt !== undefined ? { lastIndexedAt: this.lastIndexedAt } : {},
14812
- ...this.lastError !== undefined ? { lastError: this.lastError } : {}
14813
- };
14814
- }
14815
- async index() {
14816
- try {
14817
- const result = await this.connector.probe();
14818
- if (!result.ok) {
14819
- const code = connectorFailureToDiagnosticCode(result.reason);
14820
- const message = boundDiagnosticText(result.message ?? result.reason);
14821
- this.lastError = message;
14822
- return this.fail(code, message);
14823
- }
14824
- this.lastError = undefined;
14825
- this.lastIndexedAt = Date.now();
14826
- return {
14827
- ok: true,
14828
- instanceId: this.instanceId,
14829
- skill: this.skillName,
14830
- chunkCount: 0,
14831
- indexedAt: this.lastIndexedAt,
14832
- diagnostics: [this.note(LIVE_NOTE, "datasource-empty", "info")]
14833
- };
14834
- } catch (error) {
14835
- const message = boundDiagnosticText(error instanceof Error ? error.message : "spotlight probe failed");
14836
- this.lastError = message;
14837
- return this.fail("datasource-unavailable", message);
14838
- }
14839
- }
14840
- retrievalMethods() {
14841
- return [new SpotlightLiveMethod(this)];
14842
- }
14843
- describeSources() {
14844
- return this.instances.map((instanceId) => ({
14845
- source: datasourceSourcePath(this.skillName, instanceId),
14846
- datasourceId: this.skillName,
14847
- skill: this.skillName,
14848
- instanceId,
14849
- contentType: "document",
14850
- metadata: { datasourceId: this.skillName, instanceId, tags: this.tags }
14851
- }));
14852
- }
14853
- skillManifest() {
14854
- const scopes = this.instances.map((instanceId) => `- \`${datasourceSourcePath(this.skillName, instanceId)}\``).join(`
14855
- `);
14856
- return {
14857
- name: `datasource-${this.skillName}`,
14858
- description: "Search the current macOS Spotlight index directly. AutoRAG keeps no file snapshot.",
14859
- content: [
14860
- "# macOS Spotlight (live mdfind search)",
14861
- "",
14862
- "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.",
14863
- "",
14864
- "## Platform requirements",
14865
- "- macOS only: this datasource is unavailable on any other platform.",
14866
- "- Spotlight indexing must be enabled (`sudo mdutil -i on /`; check with `mdutil -s /`).",
14867
- "- 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.",
14868
- "",
14869
- "## How to search",
14870
- `Call the dedicated \`${datasourceSearchToolName(this.skillName)}\` tool with a query and optional narrowing scope. Available scopes:`,
14871
- scopes,
14872
- "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`.",
14873
- "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.",
14874
- "",
14875
- "## Native CLI",
14876
- "- `mdfind <query>` searches Spotlight; `mdfind -onlyin <dir> <query>` scopes to a directory; `mdfind -name <text>` matches file names.",
14877
- "- `mdls <file>` shows Spotlight metadata for one file.",
14878
- "- `mdutil -s /` checks index status; `sudo mdutil -i on /` enables indexing."
14879
- ].join(`
14880
- `)
14881
- };
14882
- }
14883
- async search(query, options) {
14884
- const trimmed = query.trim();
14885
- if (trimmed.length === 0)
14886
- return [];
14887
- const scope = options.scope?.trim() ? normalizeVirtualPath2(options.scope) : undefined;
14888
- if (scope !== undefined) {
14889
- const chunksRoot = normalizeVirtualPath2(`/${this.skillName}/${this.instanceId}/chunks`);
14890
- const scopeProbe = datasourceSourcePath(this.skillName, this.instanceId, "__scope_probe__");
14891
- if (!matchesDatasourceScope(chunksRoot, scope) && !matchesDatasourceScope(scopeProbe, scope) && !scope.startsWith(`${chunksRoot}/`)) {
14892
- return [];
14893
- }
14894
- }
14895
- const topK = options.topK ?? DEFAULT_TOP_K9;
14896
- const result = await this.connector.search(trimmed, topK, (docId) => matchesDatasourceScope(datasourceSourcePath(this.skillName, this.instanceId, docId), scope));
14897
- if (!result.ok) {
14898
- throw datasourceCliError(this.skillName, "search", {
14899
- reason: result.reason,
14900
- stderr: result.stderr ?? result.message,
14901
- stdout: result.stdout,
14902
- code: result.code
14903
- });
14904
- }
14905
- const hits = [];
14906
- for (const [index, document] of result.documents.entries()) {
14907
- const source = datasourceSourcePath(this.skillName, this.instanceId, document.docId);
14908
- if (!matchesDatasourceScope(source, options.scope))
14909
- continue;
14910
- hits.push({
14911
- id: `${this.skillName}:${this.instanceId}:${document.docId}`,
14912
- content: document.content,
14913
- source,
14914
- score: 1 / (index + 1),
14915
- metadata: {
14916
- ...document.metadata,
14917
- method: `${this.skillName}-live`,
14918
- datasourceId: this.skillName,
14919
- instanceId: this.instanceId,
14920
- chunkId: document.docId,
14921
- ...document.title !== undefined ? { title: document.title } : {},
14922
- ...document.hierarchy !== undefined && document.hierarchy.length > 0 ? { hierarchy: document.hierarchy.join("/") } : {},
14923
- ...document.publishedAt !== undefined ? { publishedAt: document.publishedAt } : {},
14924
- ...result.warnings !== undefined && result.warnings.length > 0 ? { warnings: result.warnings } : {}
14925
- }
14926
- });
14927
- if (hits.length >= topK)
14928
- break;
14929
- }
14930
- return hits;
14931
- }
14932
- fail(code, message) {
14933
- return {
14934
- ok: false,
14935
- instanceId: this.instanceId,
14936
- skill: this.skillName,
14937
- indexedAt: Date.now(),
14938
- diagnostics: [
14939
- this.note(message, code, code === "datasource-unavailable" || code === "datasource-empty" ? "warning" : "error")
14940
- ],
14941
- error: message,
14942
- code,
14943
- message
14944
- };
14945
- }
14946
- note(message, code, severity) {
14947
- return { code, severity, message, instanceId: this.instanceId, source: this.skillName };
14948
- }
14949
- }
14950
-
14951
- class SpotlightLiveMethod {
14952
- skill;
14953
- constructor(skill) {
14954
- this.skill = skill;
14955
- }
14956
- describe() {
14957
- const descriptor = this.skill.describe();
14958
- return {
14959
- name: `${descriptor.datasourceId ?? "spotlight"}-live`,
14960
- type: "remote",
14961
- description: "Live macOS Spotlight search via mdfind",
14962
- status: "active",
14963
- capabilities: ["live-search", "scoped", "external-cli", "path-opaque-sources"],
14964
- datasourceId: descriptor.datasourceId,
14965
- tags: descriptor.tags
14966
- };
14967
- }
14968
- retrieve(query, options) {
14969
- return this.skill.search(query, options);
14970
- }
14971
- }
14972
- var DEFAULT_TAGS4, DEFAULT_TOP_K9 = 20, LIVE_NOTE = "live-search datasource: macOS owns the Spotlight index; AutoRAG stores no snapshot";
14973
- var init_skill12 = __esm(() => {
14974
- init_connector();
14975
- init_errors2();
14976
- init_scope2();
14977
- init_connector5();
14978
- DEFAULT_TAGS4 = ["spotlight", "files"];
14979
- });
14980
-
14981
- // src/datasource/skills/spotlight/index.ts
14982
- var init_spotlight = __esm(() => {
14983
- init_connector5();
14984
- init_skill12();
14985
- });
14986
-
14987
14580
  // src/datasource/skills/telecrawl/index.ts
14988
14581
  function globalArgs3(options) {
14989
14582
  return [
@@ -15388,7 +14981,6 @@ var init_factory = __esm(() => {
15388
14981
  init_obsidian();
15389
14982
  init_rss();
15390
14983
  init_slack();
15391
- init_spotlight();
15392
14984
  init_telecrawl();
15393
14985
  init_wacrawl();
15394
14986
  BUILDERS = {
@@ -15525,12 +15117,6 @@ var init_factory = __esm(() => {
15525
15117
  ...common(config, workspaceRoot),
15526
15118
  skillName: registrationName,
15527
15119
  connectorOptions: config.connector
15528
- }),
15529
- spotlight: (config, _workspaceRoot, registrationName) => new SpotlightSkill({
15530
- ...config.instanceId !== undefined ? { instanceId: config.instanceId } : {},
15531
- ...config.tags !== undefined ? { tags: config.tags } : {},
15532
- skillName: registrationName,
15533
- connectorOptions: config.connector
15534
15120
  })
15535
15121
  };
15536
15122
  PLATFORM_ONLY_SKILLS = { kakao: "darwin" };
@@ -15812,7 +15398,7 @@ var init_types3 = __esm(() => {
15812
15398
  // src/cli/config.ts
15813
15399
  import { randomUUID as randomUUID4 } from "node:crypto";
15814
15400
  import { existsSync as existsSync16, mkdirSync as mkdirSync14, readFileSync as readFileSync19, unlinkSync as unlinkSync2, writeFileSync as writeFileSync10 } from "node:fs";
15815
- import { basename as basename7, dirname as dirname15, isAbsolute as isAbsolute6, join as join27, resolve as resolve7 } from "node:path";
15401
+ import { basename as basename6, dirname as dirname15, isAbsolute as isAbsolute6, join as join27, resolve as resolve7 } from "node:path";
15816
15402
  import { findEnvKeys, getEnvApiKey } from "@earendil-works/pi-ai/compat";
15817
15403
  import { getAgentDir as getAgentDir2, ModelRuntime, SettingsManager } from "@earendil-works/pi-coding-agent";
15818
15404
  function resolveConfigPath(input) {
@@ -15886,7 +15472,7 @@ function acquireConfigWriteLock(configPath) {
15886
15472
  });
15887
15473
  }
15888
15474
  function replaceFileAtomically(path, contents, assertCommitAllowed) {
15889
- const temporaryPath = join27(dirname15(path), `.${basename7(path)}.${process.pid}.${randomUUID4()}.tmp`);
15475
+ const temporaryPath = join27(dirname15(path), `.${basename6(path)}.${process.pid}.${randomUUID4()}.tmp`);
15890
15476
  try {
15891
15477
  writeFileSync10(temporaryPath, contents, { encoding: "utf8", flag: "wx", flush: true, mode: 384 });
15892
15478
  assertCommitAllowed?.();
@@ -17398,7 +16984,7 @@ function loopGuardPrompt(rule) {
17398
16984
  }
17399
16985
 
17400
16986
  // src/convert/cli.ts
17401
- import { spawn as spawn14 } from "node:child_process";
16987
+ import { spawn as spawn13 } from "node:child_process";
17402
16988
  import { accessSync as accessSync2, constants as constants2, existsSync as existsSync17 } from "node:fs";
17403
16989
  import { delimiter as delimiter4, dirname as dirname16, join as join29, resolve as resolve8 } from "node:path";
17404
16990
  async function convertWithFilee(request, options = {}) {
@@ -17476,7 +17062,7 @@ function spawnFilee(executable, args, options) {
17476
17062
  }
17477
17063
  const portable = portableSpawnCommand(executable, args);
17478
17064
  const env = options.dataDir === undefined ? process.env : { ...process.env, FILEE_DATA_DIR: resolve8(options.dataDir) };
17479
- const child = spawn14(portable.command, [...portable.args], {
17065
+ const child = spawn13(portable.command, [...portable.args], {
17480
17066
  cwd: options.cwd,
17481
17067
  env,
17482
17068
  stdio: ["ignore", "pipe", "pipe"]
@@ -17548,7 +17134,7 @@ var init_cli = __esm(() => {
17548
17134
  });
17549
17135
 
17550
17136
  // src/convert/installer.ts
17551
- import { createHash as createHash11 } from "node:crypto";
17137
+ import { createHash as createHash10 } from "node:crypto";
17552
17138
  import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, existsSync as existsSync18, mkdirSync as mkdirSync15, readdirSync as readdirSync4, renameSync as renameSync4, rmSync as rmSync6 } from "node:fs";
17553
17139
  import { mkdtemp as mkdtemp2 } from "node:fs/promises";
17554
17140
  import { join as join30 } from "node:path";
@@ -17621,7 +17207,7 @@ async function downloadFile2(url, destination) {
17621
17207
  await pipeline2(Readable.fromWeb(response.body), createWriteStream2(destination));
17622
17208
  }
17623
17209
  async function verifySha2562(path, expected, name) {
17624
- const hash = createHash11("sha256");
17210
+ const hash = createHash10("sha256");
17625
17211
  await pipeline2(createReadStream2(path), hash);
17626
17212
  const actual = hash.digest("hex");
17627
17213
  if (actual !== expected) {
@@ -18165,7 +17751,7 @@ var init_matrix = __esm(() => {
18165
17751
  });
18166
17752
 
18167
17753
  // src/dupey/cli.ts
18168
- import { spawn as spawn15 } from "node:child_process";
17754
+ import { spawn as spawn14 } from "node:child_process";
18169
17755
  import { resolve as resolve9 } from "node:path";
18170
17756
  function runDupey(args, options) {
18171
17757
  return options.run ? options.run(args) : spawnDupey(options.executable ?? "dupey", args, options);
@@ -18237,7 +17823,7 @@ function isScanResult(value) {
18237
17823
  function spawnDupey(executable, args, options) {
18238
17824
  return new Promise((resolveOutput, reject) => {
18239
17825
  const portable = portableSpawnCommand(executable, args);
18240
- const child = spawn15(portable.command, [...portable.args], {
17826
+ const child = spawn14(portable.command, [...portable.args], {
18241
17827
  cwd: options.cwd,
18242
17828
  stdio: ["ignore", "pipe", "pipe"]
18243
17829
  });
@@ -18285,7 +17871,7 @@ var init_cli2 = __esm(() => {
18285
17871
  });
18286
17872
 
18287
17873
  // src/dupey/filter.ts
18288
- import { stat as stat3 } from "node:fs/promises";
17874
+ import { stat as stat2 } from "node:fs/promises";
18289
17875
  import { resolve as resolve10 } from "node:path";
18290
17876
  async function selectExactDuplicateExclusions(root, scan, isUnavailable) {
18291
17877
  const byHash = new Map;
@@ -18340,7 +17926,7 @@ async function rankExactCandidates(paths, dupeyRanking, errors) {
18340
17926
  }
18341
17927
  const ranked = await Promise.all(paths.map(async (path) => {
18342
17928
  try {
18343
- const info = await stat3(path);
17929
+ const info = await stat2(path);
18344
17930
  return { path, mtimeMs: info.mtimeMs };
18345
17931
  } catch {
18346
17932
  errors.push("dupey exact duplicate path disappeared before indexing.");
@@ -18509,7 +18095,7 @@ var init_retry = __esm(() => {
18509
18095
  });
18510
18096
 
18511
18097
  // src/everything/bundle.ts
18512
- import { createHash as createHash12 } from "node:crypto";
18098
+ import { createHash as createHash11 } from "node:crypto";
18513
18099
  import { existsSync as existsSync19, mkdirSync as mkdirSync16, readFileSync as readFileSync20, rmSync as rmSync7, writeFileSync as writeFileSync11 } from "node:fs";
18514
18100
  import { dirname as dirname17, join as join31 } from "node:path";
18515
18101
  import { fileURLToPath as fileURLToPath2 } from "node:url";
@@ -18627,7 +18213,7 @@ function writeAtomic(path, bytes) {
18627
18213
  }
18628
18214
  }
18629
18215
  function sha256(bytes) {
18630
- return createHash12("sha256").update(bytes).digest("hex");
18216
+ return createHash11("sha256").update(bytes).digest("hex");
18631
18217
  }
18632
18218
  function errorMessage2(error) {
18633
18219
  return error instanceof Error ? error.message : String(error);
@@ -18657,13 +18243,13 @@ function createPathExclusionMatcher(excludedPaths, platform = process.platform)
18657
18243
  var init_path_exclusions = () => {};
18658
18244
 
18659
18245
  // src/everything/client.ts
18660
- import { spawn as spawn16 } from "node:child_process";
18661
- import { createHash as createHash13 } from "node:crypto";
18246
+ import { spawn as spawn15 } from "node:child_process";
18247
+ import { createHash as createHash12 } from "node:crypto";
18662
18248
  import { mkdirSync as mkdirSync17, writeFileSync as writeFileSync12 } from "node:fs";
18663
18249
  import { join as join32, resolve as resolve11 } from "node:path";
18664
18250
  import { setTimeout as sleep } from "node:timers/promises";
18665
18251
  function everythingInstanceName(root) {
18666
- return `autorag-${createHash13("sha256").update(resolve11(root).toLowerCase()).digest("hex").slice(0, 12)}`;
18252
+ return `autorag-${createHash12("sha256").update(resolve11(root).toLowerCase()).digest("hex").slice(0, 12)}`;
18667
18253
  }
18668
18254
  function buildEverythingIni(input) {
18669
18255
  const list = (values) => values.map((value) => `"${value.replace(/\\/g, "\\\\")}"`).join(",");
@@ -18802,7 +18388,7 @@ class EverythingClient {
18802
18388
  };
18803
18389
  }
18804
18390
  const es = { ok: true, esPath: binaries.esPath };
18805
- const timeoutMs = this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS9;
18391
+ const timeoutMs = this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS8;
18806
18392
  if ((this.options.excludeFolders?.length ?? 0) > 0) {
18807
18393
  return this.searchWithExclusions(es.esPath, request, timeoutMs);
18808
18394
  }
@@ -18887,7 +18473,7 @@ class EverythingClient {
18887
18473
  const binaries = await this.resolveBinaries("cached");
18888
18474
  if (!binaries.ok)
18889
18475
  return;
18890
- await this.run(binaries.esPath, ["-instance", this.instanceName, "-exit"], this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS9);
18476
+ await this.run(binaries.esPath, ["-instance", this.instanceName, "-exit"], this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS8);
18891
18477
  });
18892
18478
  }
18893
18479
  serialize(task) {
@@ -18917,7 +18503,7 @@ class EverythingClient {
18917
18503
  const binaries = await this.resolveBinaries("install");
18918
18504
  if (!binaries.ok)
18919
18505
  return binaries;
18920
- const timeoutMs = this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS9;
18506
+ const timeoutMs = this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS8;
18921
18507
  let ping = await this.ping(binaries.esPath);
18922
18508
  if (ping.code === 0 && !reconfigure)
18923
18509
  return { ok: true, esPath: binaries.esPath };
@@ -18974,7 +18560,7 @@ class EverythingClient {
18974
18560
  };
18975
18561
  }
18976
18562
  async ping(esPath) {
18977
- const result = await this.run(esPath, ["-instance", this.instanceName, "-get-everything-version"], this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS9);
18563
+ const result = await this.run(esPath, ["-instance", this.instanceName, "-get-everything-version"], this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS8);
18978
18564
  return result.code === 0 && !VERSION_PATTERN.test(result.stdout.trim()) ? { ...result, code: -1 } : result;
18979
18565
  }
18980
18566
  failure(reason, esPath, args, result) {
@@ -18990,7 +18576,7 @@ function runProcess(command, args, timeoutMs) {
18990
18576
  const promise = new Promise((resolve) => {
18991
18577
  resolvePromise = resolve;
18992
18578
  });
18993
- const child = spawn16(command, args, { windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
18579
+ const child = spawn15(command, args, { windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
18994
18580
  const stdout = [];
18995
18581
  const stderr = [];
18996
18582
  let bytes = 0;
@@ -19025,11 +18611,11 @@ killed by ${signal} after ${timeoutMs}ms` : err
19025
18611
  return promise;
19026
18612
  }
19027
18613
  function launchDetached(command, args) {
19028
- const child = spawn16(command, args, { detached: true, stdio: "ignore", windowsHide: true });
18614
+ const child = spawn15(command, args, { detached: true, stdio: "ignore", windowsHide: true });
19029
18615
  child.on("error", () => {});
19030
18616
  child.unref();
19031
18617
  }
19032
- var DEFAULT_TIMEOUT_MS9 = 30000, DEFAULT_STARTUP_TIMEOUT_MS = 20000, DEFAULT_INDEX_TIMEOUT_MS2, DEFAULT_POLL_INTERVAL_MS = 250, DEFAULT_MAX_RESULTS = 100, MAX_FILTER_CANDIDATES = 1000, MAX_OUTPUT_BYTES, VERSION_PATTERN;
18618
+ var DEFAULT_TIMEOUT_MS8 = 30000, DEFAULT_STARTUP_TIMEOUT_MS = 20000, DEFAULT_INDEX_TIMEOUT_MS2, DEFAULT_POLL_INTERVAL_MS = 250, DEFAULT_MAX_RESULTS = 100, MAX_FILTER_CANDIDATES = 1000, MAX_OUTPUT_BYTES, VERSION_PATTERN;
19033
18619
  var init_client8 = __esm(() => {
19034
18620
  init_path_exclusions();
19035
18621
  init_bundle();
@@ -19045,8 +18631,8 @@ var init_everything = __esm(() => {
19045
18631
  });
19046
18632
 
19047
18633
  // src/fsearch/walk.ts
19048
- import { readdir, stat as stat4 } from "node:fs/promises";
19049
- import { basename as basename8, join as join33, sep as sep5 } from "node:path";
18634
+ import { readdir, stat as stat3 } from "node:fs/promises";
18635
+ import { basename as basename7, join as join33, sep as sep5 } from "node:path";
19050
18636
  function compare(a, b) {
19051
18637
  return a < b ? -1 : a > b ? 1 : 0;
19052
18638
  }
@@ -19057,11 +18643,11 @@ async function walkFileSearch(folders, request, options = {}) {
19057
18643
  const deadline = Date.now() + (options.deadlineMs ?? DEFAULT_DEADLINE_MS);
19058
18644
  const matches = request.regex ? (() => {
19059
18645
  const pattern = new RegExp(request.query, request.matchCase ? "" : "i");
19060
- return (path) => pattern.test(request.matchPath ? path : basename8(path));
18646
+ return (path) => pattern.test(request.matchPath ? path : basename7(path));
19061
18647
  })() : (() => {
19062
18648
  const needle = request.matchCase ? request.query : request.query.toLowerCase();
19063
18649
  return (path) => {
19064
- const haystack = request.matchPath ? path : basename8(path);
18650
+ const haystack = request.matchPath ? path : basename7(path);
19065
18651
  return (request.matchCase ? haystack : haystack.toLowerCase()).includes(needle);
19066
18652
  };
19067
18653
  })();
@@ -19109,14 +18695,14 @@ async function walkFileSearch(folders, request, options = {}) {
19109
18695
  if (!matches(path))
19110
18696
  continue;
19111
18697
  try {
19112
- const info = await stat4(path);
18698
+ const info = await stat3(path);
19113
18699
  if (request.kind === "folders" && !info.isDirectory())
19114
18700
  continue;
19115
18701
  if (request.kind === "files" && info.isDirectory())
19116
18702
  continue;
19117
18703
  collected.push({
19118
18704
  path,
19119
- name: basename8(path),
18705
+ name: basename7(path),
19120
18706
  type: info.isDirectory() ? "folder" : "file",
19121
18707
  size: info.isDirectory() ? undefined : info.size,
19122
18708
  dateModified: info.mtime.toISOString()
@@ -19136,12 +18722,12 @@ async function walkFileSearch(folders, request, options = {}) {
19136
18722
  if (request.kind === "files")
19137
18723
  continue;
19138
18724
  try {
19139
- const info = await stat4(folder);
18725
+ const info = await stat3(folder);
19140
18726
  if (!info.isDirectory())
19141
18727
  continue;
19142
18728
  collected.push({
19143
18729
  path: folder,
19144
- name: basename8(folder),
18730
+ name: basename7(folder),
19145
18731
  type: "folder",
19146
18732
  size: undefined,
19147
18733
  dateModified: info.mtime.toISOString()
@@ -19171,10 +18757,10 @@ var init_walk = __esm(() => {
19171
18757
  });
19172
18758
 
19173
18759
  // src/fsearch/client.ts
19174
- import { spawn as spawn17 } from "node:child_process";
19175
- import { createHash as createHash14 } from "node:crypto";
18760
+ import { spawn as spawn16 } from "node:child_process";
18761
+ import { createHash as createHash13 } from "node:crypto";
19176
18762
  import { existsSync as existsSync20, mkdirSync as mkdirSync18, readFileSync as readFileSync21, realpathSync as realpathSync3, rmSync as rmSync8, writeFileSync as writeFileSync13 } from "node:fs";
19177
- import { basename as basename9, join as join34, resolve as resolve12, sep as sep6 } from "node:path";
18763
+ import { basename as basename8, join as join34, resolve as resolve12, sep as sep6 } from "node:path";
19178
18764
  import { setTimeout as sleep2 } from "node:timers/promises";
19179
18765
  function fsearchSocketPath(dbPath) {
19180
18766
  let canonical;
@@ -19183,7 +18769,7 @@ function fsearchSocketPath(dbPath) {
19183
18769
  } catch {
19184
18770
  canonical = resolve12(dbPath);
19185
18771
  }
19186
- const hash = createHash14("sha256").update(canonical).digest("hex").slice(0, 12);
18772
+ const hash = createHash13("sha256").update(canonical).digest("hex").slice(0, 12);
19187
18773
  return `/tmp/autorag-fsearch-${process.getuid?.() ?? 0}-${hash}.sock`;
19188
18774
  }
19189
18775
  function buildFSearchSearchArgs(dbPath, socketPath, request) {
@@ -19238,7 +18824,7 @@ function parseFSearchJsonLines(stdout) {
19238
18824
  const path = String(record.path ?? "");
19239
18825
  entries.push({
19240
18826
  path,
19241
- name: basename9(path),
18827
+ name: basename8(path),
19242
18828
  type: record.type === "folder" ? "folder" : "file",
19243
18829
  size: typeof record.size === "number" ? record.size : undefined,
19244
18830
  dateModified: typeof record.mtime === "number" ? new Date(record.mtime * 1000).toISOString() : undefined
@@ -19316,7 +18902,7 @@ class FSearchClient {
19316
18902
  const hasExclusions = (this.options.excludeFolders?.length ?? 0) > 0;
19317
18903
  const nativeRequest = hasExclusions ? { ...request, offset: 0, maxResults: MAX_RESULTS_CAP } : request;
19318
18904
  const args = buildFSearchSearchArgs(this.dbPath, this.socketPath(), nativeRequest);
19319
- const result = await this.run(binary.path, args, this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS10);
18905
+ const result = await this.run(binary.path, args, this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS9);
19320
18906
  if (result.code !== 0)
19321
18907
  return this.failure("search-failed", binary.path, args, result);
19322
18908
  let parsed;
@@ -19383,7 +18969,7 @@ class FSearchClient {
19383
18969
  if (indexed.code !== 0)
19384
18970
  return this.failure("index-failed", binaryPath, indexArgs, indexed);
19385
18971
  const statsArgs = ["stats", "--db", this.dbPath, "--socket", this.socketPath()];
19386
- const stats = await this.run(binaryPath, statsArgs, this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS10);
18972
+ const stats = await this.run(binaryPath, statsArgs, this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS9);
19387
18973
  if (stats.code !== 0)
19388
18974
  return this.failure("index-failed", binaryPath, statsArgs, stats);
19389
18975
  let counts;
@@ -19431,7 +19017,7 @@ class FSearchClient {
19431
19017
  }
19432
19018
  }
19433
19019
  async serving(binaryPath) {
19434
- const stats = await this.run(binaryPath, ["stats", "--db", this.dbPath, "--socket", this.socketPath()], this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS10);
19020
+ const stats = await this.run(binaryPath, ["stats", "--db", this.dbPath, "--socket", this.socketPath()], this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS9);
19435
19021
  if (stats.code !== 0)
19436
19022
  return false;
19437
19023
  try {
@@ -19464,7 +19050,7 @@ class FSearchClient {
19464
19050
  if (this.binary !== undefined)
19465
19051
  return this.binary;
19466
19052
  const path = this.options.binaryPath ?? "fsearch-cli";
19467
- const probe = await this.run(path, ["--version"], this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS10);
19053
+ const probe = await this.run(path, ["--version"], this.options.timeoutMs ?? DEFAULT_TIMEOUT_MS9);
19468
19054
  this.binary = probe.code === 0 ? { ok: true, path } : {
19469
19055
  ok: false,
19470
19056
  reason: "binary-missing",
@@ -19492,7 +19078,7 @@ function runProcess2(command, args, timeoutMs) {
19492
19078
  const promise = new Promise((resolve) => {
19493
19079
  resolvePromise = resolve;
19494
19080
  });
19495
- const child = spawn17(command, args, { windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
19081
+ const child = spawn16(command, args, { windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
19496
19082
  const stdout = [];
19497
19083
  const stderr = [];
19498
19084
  let bytes = 0;
@@ -19527,7 +19113,7 @@ killed by ${signal} after ${timeoutMs}ms` : err
19527
19113
  return promise;
19528
19114
  }
19529
19115
  function launchDetached2(command, args) {
19530
- const child = spawn17(command, args, { detached: true, stdio: "ignore", windowsHide: true });
19116
+ const child = spawn16(command, args, { detached: true, stdio: "ignore", windowsHide: true });
19531
19117
  child.on("error", () => {});
19532
19118
  child.unref();
19533
19119
  return child.pid;
@@ -19540,7 +19126,7 @@ function defaultIsProcessAlive(pid) {
19540
19126
  return false;
19541
19127
  }
19542
19128
  }
19543
- var DEFAULT_TIMEOUT_MS10 = 30000, DEFAULT_STARTUP_TIMEOUT_MS2 = 1e4, STOP_TIMEOUT_MS2 = 2000, DEFAULT_INDEX_TIMEOUT_MS3, DEFAULT_POLL_INTERVAL_MS2 = 250, DEFAULT_MAX_RESULTS2 = 100, MAX_RESULTS_CAP = 1000, MAX_OUTPUT_BYTES2, SORT_KEYS;
19129
+ var DEFAULT_TIMEOUT_MS9 = 30000, DEFAULT_STARTUP_TIMEOUT_MS2 = 1e4, STOP_TIMEOUT_MS2 = 2000, DEFAULT_INDEX_TIMEOUT_MS3, DEFAULT_POLL_INTERVAL_MS2 = 250, DEFAULT_MAX_RESULTS2 = 100, MAX_RESULTS_CAP = 1000, MAX_OUTPUT_BYTES2, SORT_KEYS;
19544
19130
  var init_client9 = __esm(() => {
19545
19131
  init_path_exclusions();
19546
19132
  init_walk();
@@ -19770,7 +19356,7 @@ var init_answer_pack = __esm(() => {
19770
19356
  });
19771
19357
 
19772
19358
  // src/jikji/installer.ts
19773
- import { spawn as spawn18 } from "node:child_process";
19359
+ import { spawn as spawn17 } from "node:child_process";
19774
19360
  import { existsSync as existsSync21 } from "node:fs";
19775
19361
  import { delimiter as delimiter5, join as join36 } from "node:path";
19776
19362
  function jikjiExecutableName(platform = process.platform) {
@@ -19797,7 +19383,7 @@ function lookupExecutableInPath(executable, env) {
19797
19383
  }
19798
19384
  function defaultRunner(cargo, env) {
19799
19385
  return (args, timeoutMs) => new Promise((resolvePromise) => {
19800
- const child = spawn18(cargo, args, { env, stdio: ["ignore", "ignore", "pipe"] });
19386
+ const child = spawn17(cargo, args, { env, stdio: ["ignore", "ignore", "pipe"] });
19801
19387
  let stderr = "";
19802
19388
  const timeout = setTimeout(() => {
19803
19389
  if (!child.killed)
@@ -19911,7 +19497,7 @@ class SerialQueue {
19911
19497
  }
19912
19498
 
19913
19499
  // src/jikji/client.ts
19914
- import { spawn as spawn19 } from "node:child_process";
19500
+ import { spawn as spawn18 } from "node:child_process";
19915
19501
  import { existsSync as existsSync22, realpathSync as realpathSync5 } from "node:fs";
19916
19502
 
19917
19503
  class JikjiClient {
@@ -20025,7 +19611,7 @@ class JikjiClient {
20025
19611
  if (perFile <= 0)
20026
19612
  return;
20027
19613
  const files = await countFiles(root, options.includeHidden === true, signal);
20028
- return scaledPrepareTimeoutMs(options.timeoutMs ?? DEFAULT_TIMEOUT_MS11, perFile, files);
19614
+ return scaledPrepareTimeoutMs(options.timeoutMs ?? DEFAULT_TIMEOUT_MS10, perFile, files);
20029
19615
  }
20030
19616
  async spawn(request) {
20031
19617
  return spawnJikji({
@@ -20038,7 +19624,7 @@ function spawnJikji(request) {
20038
19624
  return new Promise((resolve) => {
20039
19625
  const options = request.options;
20040
19626
  const portable = portableSpawnCommand(request.command, request.args);
20041
- const child = spawn19(portable.command, [...portable.args], {
19627
+ const child = spawn18(portable.command, [...portable.args], {
20042
19628
  env: controlledEnv4(options.env),
20043
19629
  ...request.cwd === undefined ? {} : { cwd: request.cwd },
20044
19630
  detached: process.platform !== "win32",
@@ -20070,7 +19656,7 @@ function spawnJikji(request) {
20070
19656
  const timeout = setTimeout(() => {
20071
19657
  finalReason = "timeout";
20072
19658
  terminate(child);
20073
- }, request.timeoutMs ?? options.timeoutMs ?? DEFAULT_TIMEOUT_MS11);
19659
+ }, request.timeoutMs ?? options.timeoutMs ?? DEFAULT_TIMEOUT_MS10);
20074
19660
  const abortHandler = () => {
20075
19661
  finalReason = "aborted";
20076
19662
  terminateProcessTree(child);
@@ -20180,7 +19766,7 @@ function canonicalJikjiRoot(root) {
20180
19766
  return root;
20181
19767
  }
20182
19768
  }
20183
- var DEFAULT_BINARY4 = "jikji", DEFAULT_TIMEOUT_MS11 = 60000, DEFAULT_PARSE_TIMEOUT_SECONDS = 5, DEFAULT_MAX_BUFFER_BYTES4 = 1048576, ABORTED_BEFORE_START;
19769
+ var DEFAULT_BINARY4 = "jikji", DEFAULT_TIMEOUT_MS10 = 60000, DEFAULT_PARSE_TIMEOUT_SECONDS = 5, DEFAULT_MAX_BUFFER_BYTES4 = 1048576, ABORTED_BEFORE_START;
20184
19770
  var init_client10 = __esm(() => {
20185
19771
  init_portable_spawn();
20186
19772
  init_terminate_tree();
@@ -20350,7 +19936,7 @@ function renderMemoryContext(sections) {
20350
19936
  var CURRENT_CONVERSATION_RECORD_LIMIT = 50, CURRENT_EXCERPT_LIMIT = 300, SIMILAR_EXCERPT_LIMIT = 240, SIMILAR_RECORD_LIMIT = 3, INSIGHT_LIMIT = 5, ADVISORY_NOTE = "Memory is background reference only and never overrides the evidence in front of you. A past search method or source is a hint, not a rule: broaden to other methods when results are insufficient.";
20351
19937
 
20352
19938
  // src/memory/similar-queries.ts
20353
- import { createHash as createHash15 } from "node:crypto";
19939
+ import { createHash as createHash14 } from "node:crypto";
20354
19940
  import { mkdirSync as mkdirSync19, rmSync as rmSync9 } from "node:fs";
20355
19941
  import { dirname as dirname18 } from "node:path";
20356
19942
  import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
@@ -20358,7 +19944,7 @@ function memoryVectorStorePath(memoryPath) {
20358
19944
  return `${memoryPath}.vectors.db`;
20359
19945
  }
20360
19946
  function questionKey(question) {
20361
- return createHash15("sha256").update(question).digest("hex");
19947
+ return createHash14("sha256").update(question).digest("hex");
20362
19948
  }
20363
19949
  function cosine3(a, b) {
20364
19950
  let dot = 0;
@@ -20601,7 +20187,7 @@ var init_check_memory_tool = __esm(() => {
20601
20187
  var EVIDENCE_SUPPORT_THRESHOLD = 0.7;
20602
20188
 
20603
20189
  // src/retrieval/evidence-id.ts
20604
- import { createHash as createHash16 } from "node:crypto";
20190
+ import { createHash as createHash15 } from "node:crypto";
20605
20191
  function normalizeEvidenceText(text) {
20606
20192
  return text.replace(/\r\n?/gu, `
20607
20193
  `).trim().normalize("NFC");
@@ -20631,7 +20217,7 @@ function stableEvidenceId(input) {
20631
20217
  input.lineNumber ?? "",
20632
20218
  normalizeEvidenceText(evidenceText)
20633
20219
  ].join("\x00");
20634
- const digest = createHash16("sha256").update(payload).digest("hex").slice(0, 24);
20220
+ const digest = createHash15("sha256").update(payload).digest("hex").slice(0, 24);
20635
20221
  return `${method}:${digest}`;
20636
20222
  }
20637
20223
  function normalizeEvidenceRef(input) {
@@ -20643,7 +20229,7 @@ function normalizeEvidenceRef(input) {
20643
20229
  var init_evidence_id = () => {};
20644
20230
 
20645
20231
  // src/memory/memory.ts
20646
- import { createHash as createHash17, randomUUID as randomUUID5 } from "node:crypto";
20232
+ import { createHash as createHash16, randomUUID as randomUUID5 } from "node:crypto";
20647
20233
  import { existsSync as existsSync23, mkdirSync as mkdirSync20, readFileSync as readFileSync22, unlinkSync as unlinkSync3, writeFileSync as writeFileSync14 } from "node:fs";
20648
20234
  import { dirname as dirname19 } from "node:path";
20649
20235
  import { z as z2 } from "zod";
@@ -20737,7 +20323,7 @@ function normalizeEvidenceChunkRecord(record) {
20737
20323
  return { ...base, ...normalizeEvidenceContext(record) };
20738
20324
  }
20739
20325
  function hashText(value) {
20740
- return createHash17("sha256").update(value).digest("hex");
20326
+ return createHash16("sha256").update(value).digest("hex");
20741
20327
  }
20742
20328
  function resultId(sessionId, number) {
20743
20329
  return `${sessionId}:${number}`;
@@ -21271,7 +20857,7 @@ import {
21271
20857
  rmSync as rmSync10,
21272
20858
  writeFileSync as writeFileSync15
21273
20859
  } from "node:fs";
21274
- import { basename as basename10, dirname as dirname20, isAbsolute as isAbsolute9, join as join39, relative as relative7, sep as sep8 } from "node:path";
20860
+ import { basename as basename9, dirname as dirname20, isAbsolute as isAbsolute9, join as join39, relative as relative7, sep as sep8 } from "node:path";
21275
20861
  function syncMinSyncWorkspace(root, options = {}) {
21276
20862
  const workspacePath = options.workspacePath ?? minSyncWorkspaceRoot(root);
21277
20863
  const filesRoot = join39(workspacePath, "files");
@@ -21312,7 +20898,7 @@ function syncMinSyncWorkspace(root, options = {}) {
21312
20898
  return { workspacePath, entries, excluded };
21313
20899
  }
21314
20900
  function stagingStatePath(workspacePath) {
21315
- return join39(dirname20(workspacePath), `.${basename10(workspacePath)}-autorag-staging.json`);
20901
+ return join39(dirname20(workspacePath), `.${basename9(workspacePath)}-autorag-staging.json`);
21316
20902
  }
21317
20903
  function loadStagingState2(workspacePath) {
21318
20904
  const path = stagingStatePath(workspacePath);
@@ -21363,7 +20949,7 @@ function ensureManagedDirectory(filesRoot, directory) {
21363
20949
  }
21364
20950
  }
21365
20951
  function copyFileAtomically(source, destination) {
21366
- const temporaryPath = join39(dirname20(destination), `.${basename10(destination)}.${randomUUID6()}.tmp`);
20952
+ const temporaryPath = join39(dirname20(destination), `.${basename9(destination)}.${randomUUID6()}.tmp`);
21367
20953
  try {
21368
20954
  copyFileSync4(source, temporaryPath);
21369
20955
  renameWithRetry(temporaryPath, destination);
@@ -21417,7 +21003,7 @@ var init_workspace = __esm(() => {
21417
21003
 
21418
21004
  // src/minsync/method.ts
21419
21005
  import { existsSync as existsSync25, readFileSync as readFileSync24, realpathSync as realpathSync6, statSync as statSync7 } from "node:fs";
21420
- import { basename as basename11, join as join40, normalize as normalize2 } from "node:path";
21006
+ import { basename as basename10, join as join40, normalize as normalize2 } from "node:path";
21421
21007
 
21422
21008
  class MinSyncVectorMethod {
21423
21009
  root;
@@ -21518,7 +21104,7 @@ class MinSyncVectorMethod {
21518
21104
  const entry = byPath.get(hit.path);
21519
21105
  if (!entry || !matchesVirtualPathScope(entry.virtualPath, options.scope))
21520
21106
  continue;
21521
- const chunkDiscriminator = hit.docId ?? basename11(hit.path);
21107
+ const chunkDiscriminator = hit.docId ?? basename10(hit.path);
21522
21108
  const chunkId = `minsync:${entry.virtualPath}:${chunkDiscriminator}`;
21523
21109
  const location = locateChunkInMirror(mirrorTexts, entry, hit.text);
21524
21110
  results.push({
@@ -21759,9 +21345,9 @@ var init_isolated = __esm(() => {
21759
21345
  });
21760
21346
 
21761
21347
  // src/mirror/sync.ts
21762
- import { createHash as createHash18 } from "node:crypto";
21763
- import { opendir as opendir2, readFile as readFile2, stat as stat5 } from "node:fs/promises";
21764
- import { basename as basename12, extname as extname7, join as join42, resolve as resolve15, sep as sep9 } from "node:path";
21348
+ import { createHash as createHash17 } from "node:crypto";
21349
+ import { opendir as opendir2, readFile as readFile2, stat as stat4 } from "node:fs/promises";
21350
+ import { basename as basename11, extname as extname6, join as join42, resolve as resolve15, sep as sep9 } from "node:path";
21765
21351
  import { setTimeout as sleep3 } from "node:timers/promises";
21766
21352
  function errorCode(error) {
21767
21353
  if (!(error instanceof Error))
@@ -21811,7 +21397,7 @@ function parseFingerprint(options) {
21811
21397
  }
21812
21398
  return value;
21813
21399
  };
21814
- return createHash18("sha256").update(JSON.stringify(stable({ format: 1, parser: outputParserOptions(options.parserOptions) }))).digest("hex");
21400
+ return createHash17("sha256").update(JSON.stringify(stable({ format: 1, parser: outputParserOptions(options.parserOptions) }))).digest("hex");
21815
21401
  }
21816
21402
  function outputParserOptions(options = {}) {
21817
21403
  const { fileTimeoutMs: _timeout, maxHeapMb: _heap, ocr, ...parser } = options;
@@ -21819,7 +21405,7 @@ function outputParserOptions(options = {}) {
21819
21405
  }
21820
21406
  function retryFingerprint(options, fingerprint) {
21821
21407
  const parser = options.parserOptions;
21822
- return createHash18("sha256").update(JSON.stringify({
21408
+ return createHash17("sha256").update(JSON.stringify({
21823
21409
  fingerprint,
21824
21410
  fileTimeoutMs: parser?.fileTimeoutMs,
21825
21411
  maxHeapMb: parser?.maxHeapMb,
@@ -22038,7 +21624,7 @@ async function syncWithRegistry(options, registry, isolated) {
22038
21624
  }
22039
21625
  let info;
22040
21626
  try {
22041
- info = await stat5(entry.sourcePath, { bigint: true });
21627
+ info = await stat4(entry.sourcePath, { bigint: true });
22042
21628
  } catch (error) {
22043
21629
  await skipFile(entry, sourceReadFailure(error));
22044
21630
  continue;
@@ -22070,7 +21656,7 @@ async function syncWithRegistry(options, registry, isolated) {
22070
21656
  continue;
22071
21657
  }
22072
21658
  await session.commit(mirrorStageKey(entry.virtualPath), versions.get(entry.virtualPath), {
22073
- path: basename12(outputPath),
21659
+ path: basename11(outputPath),
22074
21660
  size: Buffer.byteLength(markdown)
22075
21661
  });
22076
21662
  for (const diagnostic of parsed.diagnostics ?? [])
@@ -22146,7 +21732,7 @@ async function detectMirrorStaleness(options) {
22146
21732
  }
22147
21733
  }
22148
21734
  function standaloneImageTooSmallMessage(virtualPath, bytes) {
22149
- if (!STANDALONE_OCR_IMAGE_EXTENSIONS.has(normalizeExtension2(extname7(virtualPath))))
21735
+ if (!STANDALONE_OCR_IMAGE_EXTENSIONS.has(normalizeExtension2(extname6(virtualPath))))
22150
21736
  return;
22151
21737
  return ocrImageTooSmallMessage(bytes);
22152
21738
  }
@@ -22202,7 +21788,7 @@ function errnoCode2(error) {
22202
21788
  async function probeSearchRoot(rootPath) {
22203
21789
  let isDirectory;
22204
21790
  try {
22205
- isDirectory = (await stat5(rootPath)).isDirectory();
21791
+ isDirectory = (await stat4(rootPath)).isDirectory();
22206
21792
  } catch (error) {
22207
21793
  const code = errnoCode2(error);
22208
21794
  return code === "ENOENT" || code === "ENOTDIR" ? "gone" : "unreadable";
@@ -22314,12 +21900,12 @@ async function collectFiles(state, directory, depth) {
22314
21900
  }
22315
21901
  if (!entry.isFile())
22316
21902
  continue;
22317
- const extension = normalizeExtension2(extname7(entry.name));
21903
+ const extension = normalizeExtension2(extname6(entry.name));
22318
21904
  if (!state.supportedExtensions.has(extension))
22319
21905
  continue;
22320
21906
  let fileStat;
22321
21907
  try {
22322
- fileStat = await stat5(sourcePath, { bigint: true });
21908
+ fileStat = await stat4(sourcePath, { bigint: true });
22323
21909
  } catch (error) {
22324
21910
  const code = errnoCode2(error);
22325
21911
  if (code === undefined)
@@ -26495,7 +26081,7 @@ var init_citations = __esm(() => {
26495
26081
  });
26496
26082
 
26497
26083
  // src/agent/evidence-ledger.ts
26498
- import { createHash as createHash19 } from "node:crypto";
26084
+ import { createHash as createHash18 } from "node:crypto";
26499
26085
  import { closeSync as closeSync2, openSync as openSync2, readSync, statSync as statSync8 } from "node:fs";
26500
26086
  import { isAbsolute as isAbsolute10 } from "node:path";
26501
26087
  import { Type as Type3 } from "typebox";
@@ -26530,10 +26116,10 @@ function readFileExcerpt(path) {
26530
26116
  let descriptor;
26531
26117
  try {
26532
26118
  descriptor = openSync2(path, "r");
26533
- const buffer = Buffer.alloc(MAX_CONTENT_CHARS4 * 4);
26119
+ const buffer = Buffer.alloc(MAX_CONTENT_CHARS3 * 4);
26534
26120
  const bytes = readSync(descriptor, buffer, 0, buffer.length, 0);
26535
26121
  const head = buffer.subarray(0, bytes);
26536
- return head.includes(0) ? path : head.toString("utf8").slice(0, MAX_CONTENT_CHARS4);
26122
+ return head.includes(0) ? path : head.toString("utf8").slice(0, MAX_CONTENT_CHARS3);
26537
26123
  } catch {
26538
26124
  return path;
26539
26125
  } finally {
@@ -26566,8 +26152,8 @@ class EvidenceLedger {
26566
26152
  unsaved = new Set;
26567
26153
  lastOrdinal = 0;
26568
26154
  register(input) {
26569
- const content = input.content.slice(0, MAX_CONTENT_CHARS4);
26570
- const digest = createHash19("sha256").update(input.content.replace(/\s+/gu, " ").trim()).digest("hex");
26155
+ const content = input.content.slice(0, MAX_CONTENT_CHARS3);
26156
+ const digest = createHash18("sha256").update(input.content.replace(/\s+/gu, " ").trim()).digest("hex");
26571
26157
  const key = `${input.source}\x00${digest}`;
26572
26158
  const existing = this.byKey.get(key);
26573
26159
  if (existing !== undefined) {
@@ -26653,7 +26239,7 @@ class EvidenceLedger {
26653
26239
  this.lastOrdinal = Math.max(this.lastOrdinal, ordinalFloor, highestOrdinal(this.entries));
26654
26240
  }
26655
26241
  }
26656
- var MAX_CONTENT_CHARS4 = 2000, EVIDENCE_ENTRY_TYPE = "autorag.evidence", ledgerEntrySchema, persistedEvidenceSchema;
26242
+ var MAX_CONTENT_CHARS3 = 2000, EVIDENCE_ENTRY_TYPE = "autorag.evidence", ledgerEntrySchema, persistedEvidenceSchema;
26657
26243
  var init_evidence_ledger = __esm(() => {
26658
26244
  ledgerEntrySchema = Type3.Object({
26659
26245
  id: Type3.String({ pattern: "^e[1-9][0-9]*$" }),
@@ -26885,7 +26471,7 @@ var init_ask_user = () => {};
26885
26471
 
26886
26472
  // src/automation/service.ts
26887
26473
  import { execFile as execFile2 } from "node:child_process";
26888
- import { createHash as createHash20 } from "node:crypto";
26474
+ import { createHash as createHash19 } from "node:crypto";
26889
26475
  import { existsSync as existsSync28, mkdirSync as mkdirSync23, rmSync as rmSync11, writeFileSync as writeFileSync16 } from "node:fs";
26890
26476
  import { dirname as dirname24, join as join44, resolve as resolve16 } from "node:path";
26891
26477
  import { setTimeout as sleep5 } from "node:timers/promises";
@@ -26916,7 +26502,7 @@ function automationServiceDescriptor(options = {}) {
26916
26502
  const userHome = resolveUserHome(env);
26917
26503
  const defaultHome = resolve16(join44(userHome, ".autorag"));
26918
26504
  const home = resolve16(options.home ?? resolveAutoRAGHome(env));
26919
- const suffix = home === defaultHome ? "" : `-${createHash20("sha256").update(home).digest("hex").slice(0, 8)}`;
26505
+ const suffix = home === defaultHome ? "" : `-${createHash19("sha256").update(home).digest("hex").slice(0, 8)}`;
26920
26506
  const automationsDir = join44(home, "automations");
26921
26507
  const envFilePath = join44(automationsDir, "service.env");
26922
26508
  const logPath = join44(automationsDir, "daemon.log");
@@ -27352,7 +26938,7 @@ var init_automation_tool = __esm(() => {
27352
26938
  });
27353
26939
 
27354
26940
  // src/agent/citation-links.ts
27355
- import { basename as basename13, isAbsolute as isAbsolute12 } from "node:path";
26941
+ import { basename as basename12, isAbsolute as isAbsolute12 } from "node:path";
27356
26942
  import { pathToFileURL as pathToFileURL3 } from "node:url";
27357
26943
  function openableTarget(source) {
27358
26944
  if (/^https?:\/\//iu.test(source)) {
@@ -27370,7 +26956,7 @@ function linkCitations(markdown, sourceOf, isFile) {
27370
26956
  for (const marker of answerMarkers(markdown, isFile)) {
27371
26957
  if (marker.kind === "number")
27372
26958
  continue;
27373
- const labels = marker.kind === "file" ? [{ label: basename13(marker.path), source: marker.path }] : marker.ids.map((id) => ({ label: id, source: sourceOf(id) }));
26959
+ const labels = marker.kind === "file" ? [{ label: basename12(marker.path), source: marker.path }] : marker.ids.map((id) => ({ label: id, source: sourceOf(id) }));
27374
26960
  let linked = false;
27375
26961
  const parts = labels.map(({ label, source }) => {
27376
26962
  const target = source === undefined ? undefined : openableTarget(source);
@@ -28718,7 +28304,7 @@ class DazziJevBackend {
28718
28304
  this.apiKey = apiKey;
28719
28305
  this.baseUrl = options.baseUrl ?? resolveBaseUrl(env);
28720
28306
  this.defaultModel = options.defaultModel ?? DAZZI_DEFAULT_JEV_MODEL;
28721
- this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS12;
28307
+ this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS11;
28722
28308
  this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;
28723
28309
  this.fetchImpl = options.fetchImpl;
28724
28310
  }
@@ -28905,13 +28491,49 @@ async function extractErrorMessage(response) {
28905
28491
  function sleep6(ms) {
28906
28492
  return new Promise((resolve) => setTimeout(resolve, ms));
28907
28493
  }
28908
- 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;
28494
+ 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;
28909
28495
  var init_jev_backend = __esm(() => {
28910
28496
  init_config2();
28911
28497
  init_credential();
28912
28498
  JEV_PATH = `${API_PATH}/jev`;
28913
28499
  });
28914
28500
 
28501
+ // src/agent/token-count.ts
28502
+ import { createHash as createHash20 } from "node:crypto";
28503
+ import { countTokens } from "gpt-tokenizer/encoding/o200k_base";
28504
+ function estimateTextTokens(text) {
28505
+ return Math.max(Math.ceil(text.length / 4), countText(text));
28506
+ }
28507
+ function tokensBeyondCharGuess(parts) {
28508
+ let excess = 0;
28509
+ for (const part of parts)
28510
+ excess += Math.max(0, countText(part) - Math.ceil(part.length / 4));
28511
+ return excess;
28512
+ }
28513
+ function countText(text) {
28514
+ if (text.length === 0)
28515
+ return 0;
28516
+ if (text.length < CACHE_MIN_CHARS)
28517
+ return countTokens(text, PLAIN_TEXT);
28518
+ const key = `${text.length}:${createHash20("sha1").update(text).digest("base64")}`;
28519
+ const hit = cache.get(key);
28520
+ if (hit !== undefined) {
28521
+ cache.delete(key);
28522
+ cache.set(key, hit);
28523
+ return hit;
28524
+ }
28525
+ const count = countTokens(text, PLAIN_TEXT);
28526
+ cache.set(key, count);
28527
+ if (cache.size > CACHE_ENTRIES)
28528
+ cache.delete(cache.keys().next().value);
28529
+ return count;
28530
+ }
28531
+ var PLAIN_TEXT, CACHE_MIN_CHARS = 2000, CACHE_ENTRIES = 64, cache;
28532
+ var init_token_count = __esm(() => {
28533
+ PLAIN_TEXT = { disallowedSpecial: new Set };
28534
+ cache = new Map;
28535
+ });
28536
+
28915
28537
  // src/agent/context-token-guard.ts
28916
28538
  import { calculateContextTokens, estimateTokens } from "@earendil-works/pi-coding-agent";
28917
28539
  function createContextTokenGuardedTransform(model, base, fixedOverheadTokens = () => 0) {
@@ -28962,50 +28584,40 @@ function guardWithinBudget(model, messages, useReportedUsage = true, fixedOverhe
28962
28584
  }
28963
28585
  let guarded = messages;
28964
28586
  if (candidates.length > 0) {
28965
- const fixedTokens = estimateContextMessageTokens(base, false);
28966
- const maximumOmitted = candidates.reduce((total, section) => total + section.blocks.length, 0);
28587
+ const entries = candidates.flatMap((section, sectionIndex) => section.blocks.map((block, blockIndex) => ({ block, sectionIndex, blockIndex })));
28967
28588
  const omissionMarker = (count) => `
28968
28589
 
28969
28590
  ${GUARD_MARKER} Retrieval candidates omitted: ${count}.
28970
28591
  `;
28971
- let remaining = Math.max(0, budget - fixedTokens - Math.ceil(omissionMarker(maximumOmitted).length / 4));
28972
- const kept = candidates.map(() => []);
28973
- let omitted = 0;
28974
- let firstOmitted = -1;
28975
- for (const [sectionIndex, section] of candidates.entries()) {
28976
- for (const block of section.blocks) {
28977
- const tokens = Math.max(1, Math.ceil(block.length / 4));
28978
- if (tokens <= remaining) {
28979
- kept[sectionIndex]?.push(block);
28980
- remaining -= tokens;
28981
- continue;
28982
- }
28983
- omitted += section.blocks.length - (kept[sectionIndex]?.length ?? 0);
28984
- for (const later of candidates.slice(sectionIndex + 1))
28985
- omitted += later.blocks.length;
28986
- firstOmitted = sectionIndex;
28987
- break;
28988
- }
28989
- if (firstOmitted !== -1)
28592
+ const markerTokens = candidates.length * Math.ceil(omissionMarker(entries.length).length / 4);
28593
+ let remaining = Math.max(0, budget - estimateContextMessageTokens(base, false) - markerTokens);
28594
+ entries.sort((a, b) => a.block.rank - b.block.rank || a.sectionIndex - b.sectionIndex || a.blockIndex - b.blockIndex);
28595
+ const kept = new Set;
28596
+ for (const { block } of entries) {
28597
+ const tokens = Math.max(1, estimateTextTokens(block.text));
28598
+ if (tokens > remaining)
28990
28599
  break;
28600
+ remaining -= tokens;
28601
+ kept.add(block);
28991
28602
  }
28992
- if (omitted > 0) {
28993
- const candidateByMessage = new Map;
28994
- for (const [sectionIndex, messageIndex] of candidateIndexes.entries())
28995
- candidateByMessage.set(messageIndex, sectionIndex);
28603
+ if (kept.size < entries.length) {
28604
+ const sectionByMessage = new Map(candidateIndexes.map((messageIndex, i) => [messageIndex, candidates[i]]));
28996
28605
  guarded = base.map((message, index) => {
28997
- const sectionIndex = candidateByMessage.get(index);
28998
- if (sectionIndex === undefined)
28606
+ const section = sectionByMessage.get(index);
28607
+ if (section === undefined)
28999
28608
  return message;
29000
- const section = candidates[sectionIndex];
29001
- const marker = sectionIndex === firstOmitted ? omissionMarker(omitted) : "";
29002
- return replaceTextContent(message, `${section.prefix}${kept[sectionIndex]?.join("") ?? ""}${marker}${section.suffix}`);
28609
+ const keptBlocks = section.blocks.filter((block) => kept.has(block));
28610
+ const omitted = section.blocks.length - keptBlocks.length;
28611
+ if (omitted === 0)
28612
+ return messages[index] ?? message;
28613
+ const marker = omissionMarker(omitted);
28614
+ return replaceTextContent(message, `${section.prefix}${keptBlocks.map((block) => block.text).join("")}${marker}${section.suffix}`);
29003
28615
  });
29004
28616
  }
29005
28617
  }
29006
- if (estimateContextMessageTokens(guarded, false) <= budget && guarded !== messages)
28618
+ if (guarded !== messages && estimateContextMessageTokens(guarded, false) <= budget)
29007
28619
  return guarded;
29008
- return trimFixedContext(guarded, budget);
28620
+ return fitNewestToolResult(guarded, budget);
29009
28621
  }
29010
28622
  function estimateContextMessageTokens(messages, useReportedUsage = false) {
29011
28623
  if (useReportedUsage) {
@@ -29016,82 +28628,37 @@ function estimateContextMessageTokens(messages, useReportedUsage = false) {
29016
28628
  }
29017
28629
  return messages.reduce((total, message) => total + estimateMessageTokens(message), 0);
29018
28630
  }
29019
- function trimFixedContext(messages, inputBudget) {
29020
- const trimmed = messages.slice();
29021
- const lastIndex = trimmed.length - 1;
29022
- const queryIndex = trimmed.reduce((found, message, index) => message.role === "user" ? index : found, -1);
29023
- const fits = () => estimateContextMessageTokens(trimmed, false) <= inputBudget;
29024
- const fitInto = (index, floorTokens) => {
29025
- const message = trimmed[index];
29026
- if (message === undefined)
29027
- return;
29028
- const others = trimmed.reduce((total, other, i) => i === index ? total : total + estimateMessageTokens(other), 0);
29029
- trimmed[index] = fitMessageToTokens(message, Math.max(floorTokens, inputBudget - others));
29030
- };
29031
- for (const [index, message] of trimmed.entries()) {
29032
- if (index === lastIndex || index === queryIndex || message.role === "system")
29033
- continue;
29034
- const replacement = replaceMessageWithMarker(message);
29035
- if (replacement === message || estimateMessageTokens(replacement) >= estimateMessageTokens(message))
29036
- continue;
29037
- trimmed[index] = replacement;
29038
- if (fits())
29039
- return trimmed;
29040
- }
29041
- if (lastIndex !== queryIndex && trimmed[lastIndex]?.role !== "system") {
29042
- fitInto(lastIndex, 0);
29043
- if (fits())
29044
- return trimmed;
29045
- }
29046
- for (const [index, message] of trimmed.entries()) {
29047
- if (message.role !== "system")
29048
- continue;
29049
- fitInto(index, 0);
29050
- if (fits())
29051
- return trimmed;
29052
- }
29053
- if (queryIndex >= 0)
29054
- fitInto(queryIndex, MIN_QUERY_TOKENS);
29055
- return trimmed;
28631
+ function fitNewestToolResult(messages, inputBudget) {
28632
+ const lastIndex = messages.length - 1;
28633
+ const last = messages[lastIndex];
28634
+ if (last?.role !== "toolResult")
28635
+ return messages;
28636
+ const others = messages.reduce((total, message, index) => index === lastIndex ? total : total + estimateMessageTokens(message), 0);
28637
+ if (others >= inputBudget)
28638
+ return messages;
28639
+ const fitted = fitMessageToTokens(last, inputBudget - others);
28640
+ return fitted === last ? messages : [...messages.slice(0, lastIndex), fitted];
29056
28641
  }
29057
28642
  function fitMessageToTokens(message, maxTokens) {
29058
28643
  const original = textContent(message);
29059
28644
  if (original === undefined)
29060
- return stripNonTextContent(message);
28645
+ return message;
29061
28646
  const marker = `
29062
28647
 
29063
28648
  ${GUARD_MARKER}
29064
28649
  `;
29065
- let low = 0;
29066
- let high = original.length;
29067
- let best = replaceTextContent(message, marker);
29068
- while (low <= high) {
29069
- const middle = Math.floor((low + high) / 2);
29070
- const candidate = replaceTextContent(message, excerpt(original, middle, marker));
29071
- if (estimateMessageTokens(candidate) <= maxTokens) {
29072
- best = candidate;
29073
- low = middle + 1;
29074
- } else {
29075
- high = middle - 1;
29076
- }
28650
+ const overhead = estimateMessageTokens(replaceTextContent(message, ""));
28651
+ const density = Math.max(0, estimateMessageTokens(message) - overhead) / Math.max(1, original.length);
28652
+ let chars = density > 0 ? Math.floor((maxTokens - overhead) / density) : original.length;
28653
+ for (let attempt = 0;attempt < MAX_FIT_ATTEMPTS && chars > 0; attempt++) {
28654
+ const candidate = replaceTextContent(message, excerpt(original, chars, marker));
28655
+ const tokens = estimateMessageTokens(candidate);
28656
+ if (tokens <= maxTokens)
28657
+ return candidate;
28658
+ const scaled = Math.floor(chars * Math.max(0, maxTokens - overhead) / Math.max(1, tokens - overhead) * 0.98);
28659
+ chars = Math.min(chars - 1, scaled);
29077
28660
  }
29078
- return best;
29079
- }
29080
- function stripNonTextContent(message) {
29081
- if (message.role !== "user" || typeof message.content === "string")
29082
- return replaceMessageWithMarker(message);
29083
- const marker = `
29084
-
29085
- ${GUARD_MARKER}
29086
- `;
29087
- let replacedImage = false;
29088
- const content = message.content.map((block) => {
29089
- if (block.type === "text")
29090
- return block;
29091
- replacedImage = true;
29092
- return { type: "text", text: marker };
29093
- });
29094
- return replacedImage ? { ...message, content } : message;
28661
+ return replaceTextContent(message, marker);
29095
28662
  }
29096
28663
  function excerpt(text, maxChars, marker) {
29097
28664
  if (text.length <= maxChars)
@@ -29101,32 +28668,54 @@ function excerpt(text, maxChars, marker) {
29101
28668
  const tail = Math.max(0, available - head);
29102
28669
  return `${text.slice(0, head)}${marker}${tail > 0 ? text.slice(-tail) : ""}`;
29103
28670
  }
29104
- function replaceMessageWithMarker(message) {
29105
- return replaceTextContent(message, `
29106
-
29107
- ${GUARD_MARKER}
29108
- `);
29109
- }
29110
28671
  function estimateMessageTokens(message) {
29111
28672
  if (message.role === "system")
29112
28673
  return estimateSystemMessageTokens(message);
29113
- const estimate = estimateTokens(message);
28674
+ const estimate = estimateTokens(message) + tokensBeyondCharGuess(messageTextParts(message));
29114
28675
  return message.role === "toolResult" ? estimate + Math.ceil(message.toolName.length / 4) : estimate;
29115
28676
  }
29116
28677
  function estimateSystemMessageTokens(message) {
29117
- let chars = typeof message.content === "string" ? message.content.length : 0;
29118
- if (Array.isArray(message.content)) {
28678
+ const parts = [];
28679
+ let chars = 0;
28680
+ if (typeof message.content === "string")
28681
+ parts.push(message.content);
28682
+ else {
29119
28683
  for (const block of message.content) {
29120
28684
  if (block.type === "text")
29121
- chars += block.text.length;
28685
+ parts.push(block.text);
29122
28686
  else if (block.type === "image")
29123
28687
  chars += 4800;
29124
28688
  }
29125
28689
  }
29126
- chars += JSON.stringify(message.sections ?? {}).length;
29127
- chars += JSON.stringify(message.toolsAdded ?? []).length;
29128
- chars += JSON.stringify(message.toolsRemoved ?? []).length;
29129
- return Math.ceil(chars / 4);
28690
+ parts.push(JSON.stringify(message.sections ?? {}), JSON.stringify(message.toolsAdded ?? []), JSON.stringify(message.toolsRemoved ?? []));
28691
+ for (const part of parts)
28692
+ chars += part.length;
28693
+ return Math.ceil(chars / 4) + tokensBeyondCharGuess(parts);
28694
+ }
28695
+ function messageTextParts(message) {
28696
+ switch (message.role) {
28697
+ case "user":
28698
+ case "custom":
28699
+ case "toolResult":
28700
+ return typeof message.content === "string" ? [message.content] : message.content.flatMap((block) => block.type === "text" ? [block.text] : []);
28701
+ case "assistant":
28702
+ return message.content.flatMap((block) => {
28703
+ if (block.type === "text")
28704
+ return [block.text];
28705
+ if (block.type === "thinking")
28706
+ return [block.thinking];
28707
+ if (block.type === "toolCall")
28708
+ return [`${block.name}${JSON.stringify(block.arguments)}`];
28709
+ return [];
28710
+ });
28711
+ case "bashExecution":
28712
+ return [message.command, message.output];
28713
+ case "branchSummary":
28714
+ case "compactionSummary":
28715
+ return [message.summary];
28716
+ default:
28717
+ return [];
28718
+ }
29130
28719
  }
29131
28720
  function findLastAssistantUsage(messages) {
29132
28721
  for (let index = messages.length - 1;index >= 0; index--) {
@@ -29200,7 +28789,7 @@ function parseCandidateSection(message, text) {
29200
28789
  const sectionEnd = findBaselineSectionEnd(text, sectionStart);
29201
28790
  if (!/^\[e?\d+\] /mu.test(text.slice(sectionStart, sectionEnd)))
29202
28791
  return;
29203
- return splitCandidates(text, sectionStart, sectionEnd);
28792
+ return splitCandidates(text, sectionStart, sectionEnd, { lists: true });
29204
28793
  }
29205
28794
  if (message.role !== "toolResult")
29206
28795
  return;
@@ -29211,7 +28800,9 @@ function parseCandidateSection(message, text) {
29211
28800
  const directiveStart = text.indexOf(`
29212
28801
 
29213
28802
  directive:`);
29214
- return splitCandidates(text, 0, directiveStart >= 0 ? directiveStart : text.length, /^- [^\n]*(?:\n|$)/gmu);
28803
+ return splitCandidates(text, 0, directiveStart >= 0 ? directiveStart : text.length, {
28804
+ pattern: /^- [^\n]*(?:\n|$)/gmu
28805
+ });
29215
28806
  }
29216
28807
  const diagnosticsStart = text.indexOf(`
29217
28808
 
@@ -29233,17 +28824,23 @@ Formatting and content rules`
29233
28824
  const positions = endMarkers.map((marker) => text.indexOf(marker, startIndex)).filter((index) => index >= 0);
29234
28825
  return positions.length > 0 ? Math.min(...positions) : text.length;
29235
28826
  }
29236
- function splitCandidates(text, sectionStart, sectionEnd, pattern = /^\[e?\d+\] [^\n]*(?:\n|$)/gmu) {
28827
+ function splitCandidates(text, sectionStart, sectionEnd, options = {}) {
29237
28828
  const region = text.slice(sectionStart, sectionEnd);
29238
- const matches = [...region.matchAll(pattern)];
28829
+ const matches = [...region.matchAll(options.pattern ?? /^\[e?\d+\] [^\n]*(?:\n|$)/gmu)];
29239
28830
  const firstStart = matches[0]?.index;
29240
28831
  if (firstStart === undefined)
29241
28832
  return;
29242
28833
  const blocks = [];
28834
+ let rank = 0;
28835
+ let heading = "";
29243
28836
  for (const [index, match] of matches.entries()) {
29244
28837
  const start = match.index ?? 0;
29245
28838
  const end = index + 1 < matches.length ? matches[index + 1]?.index ?? region.length : region.length;
29246
- blocks.push(region.slice(start, end));
28839
+ const raw = region.slice(start, end);
28840
+ const tail = options.lists === true ? LIST_HEADING_TAIL.exec(raw) : null;
28841
+ blocks.push({ text: heading + (tail === null ? raw : raw.slice(0, tail.index)), rank });
28842
+ rank = tail === null ? rank + 1 : 0;
28843
+ heading = tail === null ? "" : tail[0];
29247
28844
  }
29248
28845
  return {
29249
28846
  prefix: text.slice(0, sectionStart) + region.slice(0, firstStart),
@@ -29251,9 +28848,10 @@ function splitCandidates(text, sectionStart, sectionEnd, pattern = /^\[e?\d+\] [
29251
28848
  blocks
29252
28849
  };
29253
28850
  }
29254
- 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;
28851
+ 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;
29255
28852
  var init_context_token_guard = __esm(() => {
29256
28853
  init_context_overflow();
28854
+ init_token_count();
29257
28855
  RETRIEVAL_TOOL_NAMES = {
29258
28856
  jikji_find: true,
29259
28857
  search_all_documents: true,
@@ -29262,6 +28860,7 @@ var init_context_token_guard = __esm(() => {
29262
28860
  everything_search: true,
29263
28861
  fsearch_search: true
29264
28862
  };
28863
+ LIST_HEADING_TAIL = /\n[^\n]*initial candidates[^\n]*:\n$/u;
29265
28864
  });
29266
28865
 
29267
28866
  // src/agent/current-date.ts
@@ -29598,7 +29197,7 @@ function guardContext(pi, contextTransform) {
29598
29197
  pi.on("context", async (event, ctx) => {
29599
29198
  const activeTools = new Set(pi.getActiveTools());
29600
29199
  const toolDeclarations = pi.getAllTools().filter((tool) => activeTools.has(tool.name)).map(({ name, description, parameters }) => ({ name, description, parameters }));
29601
- const fixedOverheadTokens = Math.ceil((ctx.getSystemPrompt().length + JSON.stringify(toolDeclarations).length) / 4);
29200
+ const fixedOverheadTokens = estimateTextTokens(ctx.getSystemPrompt()) + estimateTextTokens(JSON.stringify(toolDeclarations));
29602
29201
  return {
29603
29202
  messages: await createContextTokenGuardedTransform(ctx.model, contextTransform, () => fixedOverheadTokens)(event.messages)
29604
29203
  };
@@ -29832,6 +29431,7 @@ var init_pi_session = __esm(() => {
29832
29431
  init_intent_tracing();
29833
29432
  init_mcp_client();
29834
29433
  init_request_limits();
29434
+ init_token_count();
29835
29435
  init_welcome_header();
29836
29436
  PI_BUILTIN_TOOL_NAMES = ["read", "bash", "edit", "write", "grep", "find", "ls"];
29837
29437
  });
@@ -31603,7 +31203,7 @@ var init_page_loader = __esm(() => {
31603
31203
  });
31604
31204
 
31605
31205
  // src/web/fetch/url-target.ts
31606
- import { extname as extname8 } from "node:path";
31206
+ import { extname as extname7 } from "node:path";
31607
31207
  function repairCollapsedScheme(value) {
31608
31208
  const m = value.match(/^(https?):\/(?!\/)/i);
31609
31209
  return m ? `${m[1]}://${value.slice(m[0].length)}` : value;
@@ -31622,7 +31222,7 @@ function getFilenameExtensionHint(filename) {
31622
31222
  const lower = filename.toLowerCase();
31623
31223
  if (lower.endsWith(".tar.gz"))
31624
31224
  return ".tar.gz";
31625
- return extname8(filename).toLowerCase();
31225
+ return extname7(filename).toLowerCase();
31626
31226
  }
31627
31227
  function getExtensionHint(url, contentDisposition) {
31628
31228
  if (contentDisposition) {
@@ -31799,7 +31399,7 @@ var init_convert2 = __esm(() => {
31799
31399
  });
31800
31400
 
31801
31401
  // src/web/fetch/feeds.ts
31802
- import { extname as extname9 } from "node:path";
31402
+ import { extname as extname8 } from "node:path";
31803
31403
  import { XMLParser as XMLParser3 } from "fast-xml-parser";
31804
31404
  function getHtmlAttribute(tag, attribute) {
31805
31405
  const pattern = new RegExp(`\\b${attribute}\\s*=\\s*(?:"([^"]*)"|'([^']*)'|([^\\s"'=<>]+))`, "i");
@@ -31862,7 +31462,7 @@ function extractDocumentLinks(html, baseUrl) {
31862
31462
  const href = getHtmlAttribute(tag, "href");
31863
31463
  if (!href)
31864
31464
  continue;
31865
- const ext = extname9(href).toLowerCase();
31465
+ const ext = extname8(href).toLowerCase();
31866
31466
  if (!CONVERTIBLE_EXTENSIONS2.has(ext))
31867
31467
  continue;
31868
31468
  const resolved = href.startsWith("http") ? href : new URL(href, baseUrl).href;
@@ -33530,7 +33130,7 @@ var init_web_search_tool = __esm(() => {
33530
33130
  // src/agent/agent.ts
33531
33131
  import { randomUUID as randomUUID7 } from "node:crypto";
33532
33132
  import { existsSync as existsSync32, watch as fsWatch, mkdirSync as mkdirSync24, realpathSync as realpathSync7, statSync as statSync9, writeFileSync as writeFileSync18 } from "node:fs";
33533
- import { basename as basename14, dirname as dirname26, join as join50, resolve as resolve17 } from "node:path";
33133
+ import { basename as basename13, dirname as dirname26, join as join50, resolve as resolve17 } from "node:path";
33534
33134
  import { clampThinkingLevel } from "@earendil-works/pi-ai/compat";
33535
33135
  import { getAgentDir as getAgentDir4, keyText } from "@earendil-works/pi-coding-agent";
33536
33136
  function positiveLimit(value, fallback, path) {
@@ -36453,7 +36053,7 @@ function toMinSyncReasonDiagnostic(reason) {
36453
36053
  function pinExcludedPath(path) {
36454
36054
  const resolvedPath = resolve17(path);
36455
36055
  try {
36456
- return join50(realpathSync7(dirname26(resolvedPath)), basename14(resolvedPath));
36056
+ return join50(realpathSync7(dirname26(resolvedPath)), basename13(resolvedPath));
36457
36057
  } catch {
36458
36058
  return resolvedPath;
36459
36059
  }
@@ -37869,7 +37469,7 @@ var init_embedding2 = __esm(() => {
37869
37469
  });
37870
37470
 
37871
37471
  // src/datasource/skills/hister/setup.ts
37872
- import { spawn as spawn20 } from "node:child_process";
37472
+ import { spawn as spawn19 } from "node:child_process";
37873
37473
  import { copyFileSync as copyFileSync5, existsSync as existsSync36, readFileSync as readFileSync31, writeFileSync as writeFileSync19 } from "node:fs";
37874
37474
  import { homedir as homedir7 } from "node:os";
37875
37475
  import { dirname as dirname28, join as join53 } from "node:path";
@@ -37916,7 +37516,7 @@ function defaultHisterConfigPath(env, exists = existsSync36, platform = process.
37916
37516
  function commandRun(command, args, timeoutMs) {
37917
37517
  return new Promise((resolve) => {
37918
37518
  let stderr = "";
37919
- const child = spawn20(command, args, { stdio: ["ignore", "ignore", "pipe"] });
37519
+ const child = spawn19(command, args, { stdio: ["ignore", "ignore", "pipe"] });
37920
37520
  const timer = setTimeout(() => {
37921
37521
  child.kill("SIGTERM");
37922
37522
  resolve({ ok: false, reason: `${command} ${args.join(" ")} timed out after ${timeoutMs}ms` });
@@ -38205,8 +37805,7 @@ function datasourceNames(config, platform) {
38205
37805
  "github",
38206
37806
  "cloud-drive",
38207
37807
  "obsidian",
38208
- "rss",
38209
- "spotlight"
37808
+ "rss"
38210
37809
  ])
38211
37810
  ];
38212
37811
  }
@@ -39010,7 +38609,7 @@ function sanitizeMessage(raw) {
39010
38609
  function parseTimeoutMs(flags) {
39011
38610
  const raw = flags["timeout-ms"];
39012
38611
  if (raw === undefined || raw === true)
39013
- return DEFAULT_TIMEOUT_MS13;
38612
+ return DEFAULT_TIMEOUT_MS12;
39014
38613
  const text = typeof raw === "string" ? raw.trim() : "";
39015
38614
  if (!/^\d+$/.test(text) || Number(text) <= 0) {
39016
38615
  return `--timeout-ms must be a positive integer (got "${text}")`;
@@ -39193,7 +38792,7 @@ async function runHealth(ctx, deps = {}) {
39193
38792
  ctx.stdout(renderHealth(report, { json: ctx.json, debug: ctx.debug }));
39194
38793
  return exitCode(probe.category);
39195
38794
  }
39196
- var DEFAULT_TIMEOUT_MS13 = 1e4;
38795
+ var DEFAULT_TIMEOUT_MS12 = 1e4;
39197
38796
  var init_health = __esm(() => {
39198
38797
  init_config5();
39199
38798
  init_output();
@@ -39258,7 +38857,7 @@ var init_duplicates = __esm(() => {
39258
38857
  });
39259
38858
 
39260
38859
  // src/cli/open-target.ts
39261
- import { spawn as spawn21 } from "node:child_process";
38860
+ import { spawn as spawn20 } from "node:child_process";
39262
38861
  import { fileURLToPath as fileURLToPath5 } from "node:url";
39263
38862
  function systemOpener(url) {
39264
38863
  if (process.platform === "darwin")
@@ -39283,7 +38882,7 @@ function launch(spawnFn, command, args, onFailure) {
39283
38882
  });
39284
38883
  child.unref();
39285
38884
  }
39286
- function openCitationTarget(url, spawnFn = spawn21) {
38885
+ function openCitationTarget(url, spawnFn = spawn20) {
39287
38886
  const [command, args] = systemOpener(url);
39288
38887
  if (!url.startsWith("file:")) {
39289
38888
  launch(spawnFn, command, args);