@autorag/librarian 2.13.8 → 2.13.10

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/profiles.js CHANGED
@@ -14789,6 +14789,35 @@ var init_embedding = __esm(() => {
14789
14789
  created = new Set;
14790
14790
  });
14791
14791
 
14792
+ // src/filesystem/path-exclusions.ts
14793
+ import { matchesGlob, posix as posix3, win32 as win322 } from "node:path";
14794
+ function isGlobExclusion(entry) {
14795
+ return /[*?[]/u.test(entry);
14796
+ }
14797
+ function matchesGlobExclusion(path, glob) {
14798
+ const slashed = path.replaceAll("\\", "/");
14799
+ if (matchesGlob(slashed, glob))
14800
+ return true;
14801
+ return glob.startsWith("**/") && matchesGlob(slashed, glob.slice(3));
14802
+ }
14803
+ function createPathExclusionMatcher(excludedPaths, platform = process.platform) {
14804
+ const paths = platform === "win32" ? win322 : posix3;
14805
+ const normalize = (path) => {
14806
+ const absolute = paths.resolve(path);
14807
+ return platform === "win32" ? absolute.toLowerCase() : absolute;
14808
+ };
14809
+ const globs = excludedPaths.filter(isGlobExclusion).map((glob) => platform === "win32" ? glob.toLowerCase() : glob);
14810
+ const excluded = excludedPaths.filter((path) => !isGlobExclusion(path)).map((path) => {
14811
+ const absolute = normalize(path);
14812
+ return { absolute, prefix: absolute.endsWith(paths.sep) ? absolute : `${absolute}${paths.sep}` };
14813
+ });
14814
+ return (path) => {
14815
+ const absolute = normalize(path);
14816
+ return excluded.some((entry) => absolute === entry.absolute || absolute.startsWith(entry.prefix)) || globs.some((glob) => matchesGlobExclusion(absolute, glob));
14817
+ };
14818
+ }
14819
+ var init_path_exclusions = () => {};
14820
+
14792
14821
  // src/language.ts
14793
14822
  function supportedList() {
14794
14823
  return AUTORAG_LANGUAGE_TAGS.join(", ");
@@ -15377,7 +15406,7 @@ function resolveExcludePaths(value, origin) {
15377
15406
  if (!Array.isArray(value) || value.some((path) => typeof path !== "string" || path.length === 0)) {
15378
15407
  throw new ConfigError("Config field 'excludePaths' must be a non-empty string array");
15379
15408
  }
15380
- return resolveSearchPaths(value, origin);
15409
+ return value.map((entry) => isGlobExclusion(entry) ? entry : resolvePersistedPath(entry, origin));
15381
15410
  }
15382
15411
  function resolvePersistedPath(path, origin) {
15383
15412
  return isAbsolute5(path) ? path : resolve6(origin, path);
@@ -16682,6 +16711,7 @@ var init_config4 = __esm(() => {
16682
16711
  init_factory();
16683
16712
  init_embedding();
16684
16713
  init_file_lock();
16714
+ init_path_exclusions();
16685
16715
  init_language();
16686
16716
  init_atomic_write();
16687
16717
  init_rerank();
@@ -16978,7 +17008,7 @@ var init_automation_profiles = __esm(() => {
16978
17008
 
16979
17009
  // src/automation/config.ts
16980
17010
  import { existsSync as existsSync14, readFileSync as readFileSync16, realpathSync as realpathSync2 } from "node:fs";
16981
- import { basename as basename6, dirname as dirname12, isAbsolute as isAbsolute6, join as join24, matchesGlob, relative as relative4, resolve as resolve7 } from "node:path";
17011
+ import { basename as basename6, dirname as dirname12, isAbsolute as isAbsolute6, join as join24, matchesGlob as matchesGlob2, relative as relative4, resolve as resolve7 } from "node:path";
16982
17012
  function automationsConfigPath(env = process.env) {
16983
17013
  return join24(resolveAutoRAGHome(env), "automations.json");
16984
17014
  }
@@ -17154,9 +17184,9 @@ function deleteAutomation(configPath, id) {
17154
17184
  function globMatches(relPosix, pattern) {
17155
17185
  if (pattern === "**")
17156
17186
  return true;
17157
- if (matchesGlob(relPosix, pattern))
17187
+ if (matchesGlob2(relPosix, pattern))
17158
17188
  return true;
17159
- if (pattern.startsWith("**/") && matchesGlob(relPosix, pattern.slice(3)))
17189
+ if (pattern.startsWith("**/") && matchesGlob2(relPosix, pattern.slice(3)))
17160
17190
  return true;
17161
17191
  return false;
17162
17192
  }
@@ -18612,25 +18642,6 @@ var init_bundle = __esm(() => {
18612
18642
  init_atomic_write();
18613
18643
  });
18614
18644
 
18615
- // src/filesystem/path-exclusions.ts
18616
- import { posix as posix3, win32 as win322 } from "node:path";
18617
- function createPathExclusionMatcher(excludedPaths, platform = process.platform) {
18618
- const paths = platform === "win32" ? win322 : posix3;
18619
- const normalize = (path) => {
18620
- const absolute = paths.resolve(path);
18621
- return platform === "win32" ? absolute.toLowerCase() : absolute;
18622
- };
18623
- const excluded = excludedPaths.map((path) => {
18624
- const absolute = normalize(path);
18625
- return { absolute, prefix: absolute.endsWith(paths.sep) ? absolute : `${absolute}${paths.sep}` };
18626
- });
18627
- return (path) => {
18628
- const absolute = normalize(path);
18629
- return excluded.some((entry) => absolute === entry.absolute || absolute.startsWith(entry.prefix));
18630
- };
18631
- }
18632
- var init_path_exclusions = () => {};
18633
-
18634
18645
  // src/filesystem/shared-exclusive-queue.ts
18635
18646
  class SharedExclusiveQueue {
18636
18647
  sharedSinceExclusive = [];
@@ -22145,6 +22156,34 @@ var init_memory = __esm(() => {
22145
22156
  });
22146
22157
  });
22147
22158
 
22159
+ // src/minsync/channel-union.ts
22160
+ function unionChannelResults(channels, options = {}) {
22161
+ const byChunk = new Map;
22162
+ const depth = Math.max(0, ...channels.map((channel) => channel.results.length));
22163
+ for (let rank = 0;rank < depth; rank++) {
22164
+ for (const channel of channels) {
22165
+ const result = channel.results[rank];
22166
+ if (result === undefined)
22167
+ continue;
22168
+ const key = `${result.source}\x00${result.id}`;
22169
+ const existing = byChunk.get(key);
22170
+ if (existing === undefined)
22171
+ byChunk.set(key, { result, ranks: { [channel.channel]: rank + 1 } });
22172
+ else
22173
+ existing.ranks[channel.channel] ??= rank + 1;
22174
+ }
22175
+ }
22176
+ const union = [...byChunk.values()].map(({ result, ranks }) => ({
22177
+ ...result,
22178
+ metadata: {
22179
+ ...result.metadata,
22180
+ minsyncChannels: Object.keys(ranks).sort(),
22181
+ minsyncChannelRanks: ranks
22182
+ }
22183
+ }));
22184
+ return options.limit === undefined ? union : union.slice(0, options.limit);
22185
+ }
22186
+
22148
22187
  // src/retrieval/chunk-location.ts
22149
22188
  function sectionLabel(line) {
22150
22189
  const text = line.trim();
@@ -24183,7 +24222,7 @@ var init_cloud = __esm(() => {
24183
24222
  // src/mirror/sync.ts
24184
24223
  import { createHash as createHash17 } from "node:crypto";
24185
24224
  import { opendir as opendir2, readFile as readFile2, stat as stat4 } from "node:fs/promises";
24186
- import { basename as basename13, dirname as dirname21, extname as extname9, join as join42, resolve as resolve15, sep as sep9 } from "node:path";
24225
+ import { basename as basename13, dirname as dirname21, extname as extname9, join as join42, resolve as resolve15 } from "node:path";
24187
24226
  import { setTimeout as sleep4 } from "node:timers/promises";
24188
24227
  function errorCode(error) {
24189
24228
  if (!(error instanceof Error))
@@ -24730,13 +24769,14 @@ function normalizeExtension2(extension) {
24730
24769
  return lower.startsWith(".") ? lower : `.${lower}`;
24731
24770
  }
24732
24771
  function isPathExcluded(sourcePath, excluded) {
24733
- if (excluded === undefined)
24772
+ if (excluded === undefined || excluded.size === 0)
24734
24773
  return false;
24735
- for (const excludedPath of excluded) {
24736
- if (sourcePath === excludedPath || sourcePath.startsWith(`${excludedPath}${sep9}`))
24737
- return true;
24774
+ let matcher = matcherBySet.get(excluded);
24775
+ if (matcher === undefined) {
24776
+ matcher = createPathExclusionMatcher([...excluded]);
24777
+ matcherBySet.set(excluded, matcher);
24738
24778
  }
24739
- return false;
24779
+ return matcher(sourcePath);
24740
24780
  }
24741
24781
  function walkLimits(options) {
24742
24782
  return {
@@ -24903,10 +24943,11 @@ async function collectFiles(state, directory, depth) {
24903
24943
  warnDirectoryUnreadable(state, directory, code);
24904
24944
  }
24905
24945
  }
24906
- var DEFAULT_MAX_SOURCE_BYTES, DEFAULT_MAX_DELETE_RATIO = 0.3, MASS_DELETE_FLOOR = 100, DEFAULT_MAX_SCANNED_ENTRIES = 2000000, DEFAULT_MAX_WALK_DEPTH = 64, DEFAULT_MIRROR_BATCH_SIZE = 25, PRODUCT_ARTIFACT_FILE_NAMES, SKIP_DIR_NAMES, PARSER_FAILURE_MESSAGE = "The registered parser failed on this file; it was skipped during indexing.", PARSER_CRASH_MESSAGE = "The registered parser crashed unexpectedly on this file; it was skipped during indexing.", DEFAULT_TRANSIENT_RETRIES = 3, DEFAULT_TRANSIENT_BACKOFF_MS = 50, TRANSIENT_ERROR_CODES, WORKSPACE_ERROR_CODES, MirrorWorkspaceError, STANDALONE_OCR_IMAGE_EXTENSIONS, SEARCH_ROOT_UNAVAILABLE_MESSAGES;
24946
+ var DEFAULT_MAX_SOURCE_BYTES, DEFAULT_MAX_DELETE_RATIO = 0.3, MASS_DELETE_FLOOR = 100, DEFAULT_MAX_SCANNED_ENTRIES = 2000000, DEFAULT_MAX_WALK_DEPTH = 64, DEFAULT_MIRROR_BATCH_SIZE = 25, PRODUCT_ARTIFACT_FILE_NAMES, SKIP_DIR_NAMES, PARSER_FAILURE_MESSAGE = "The registered parser failed on this file; it was skipped during indexing.", PARSER_CRASH_MESSAGE = "The registered parser crashed unexpectedly on this file; it was skipped during indexing.", DEFAULT_TRANSIENT_RETRIES = 3, DEFAULT_TRANSIENT_BACKOFF_MS = 50, TRANSIENT_ERROR_CODES, WORKSPACE_ERROR_CODES, MirrorWorkspaceError, STANDALONE_OCR_IMAGE_EXTENSIONS, matcherBySet, SEARCH_ROOT_UNAVAILABLE_MESSAGES;
24907
24947
  var init_sync = __esm(() => {
24908
24948
  init_cli2();
24909
24949
  init_cloud_placeholder();
24950
+ init_path_exclusions();
24910
24951
  init_source_paths();
24911
24952
  init_binary();
24912
24953
  init_stage();
@@ -24965,6 +25006,7 @@ var init_sync = __esm(() => {
24965
25006
  }
24966
25007
  };
24967
25008
  STANDALONE_OCR_IMAGE_EXTENSIONS = new Set(KORDOC_IMAGE_EXTENSIONS);
25009
+ matcherBySet = new WeakMap;
24968
25010
  SEARCH_ROOT_UNAVAILABLE_MESSAGES = {
24969
25011
  gone: "A search root no longer exists; its previously indexed documents were left untouched.",
24970
25012
  "not-a-directory": "A search root is no longer a directory; its previously indexed documents were left untouched.",
@@ -38520,7 +38562,7 @@ var init_web_search_tool = __esm(() => {
38520
38562
  // src/agent/agent.ts
38521
38563
  import { randomUUID as randomUUID7 } from "node:crypto";
38522
38564
  import { existsSync as existsSync34, watch as fsWatch, mkdirSync as mkdirSync24, realpathSync as realpathSync8, statSync as statSync11, writeFileSync as writeFileSync17 } from "node:fs";
38523
- import { basename as basename15, dirname as dirname27, join as join54, relative as relative8, resolve as resolve18, sep as sep10 } from "node:path";
38565
+ import { basename as basename15, dirname as dirname27, join as join54, relative as relative8, resolve as resolve18, sep as sep9 } from "node:path";
38524
38566
  import { clampThinkingLevel } from "@earendil-works/pi-ai/compat";
38525
38567
  import { getAgentDir as getAgentDir6, keyText } from "@earendil-works/pi-coding-agent";
38526
38568
  function describeDecisionModel(status) {
@@ -38663,6 +38705,7 @@ class AutoRAGAgent {
38663
38705
  reranker;
38664
38706
  rerankTopN;
38665
38707
  minSyncMethod;
38708
+ minSyncSparseMethod;
38666
38709
  minSyncEmbedderConfig;
38667
38710
  minSyncBinaryPath;
38668
38711
  jikjiClient;
@@ -38785,6 +38828,7 @@ class AutoRAGAgent {
38785
38828
  ...this.limits.recordCut === undefined ? {} : { recordCut: this.limits.recordCut }
38786
38829
  };
38787
38830
  this.minSyncMethod = new MinSyncVectorMethod(minSyncDefaults);
38831
+ this.minSyncSparseMethod = isSparseOnlyEmbedder(options.minSync?.embedder) ? undefined : new MinSyncVectorMethod({ ...minSyncDefaults, mode: "sparse" });
38788
38832
  this.methodRegistry.register(new MinSyncHybridMethod(minSyncDefaults));
38789
38833
  const registeredDatasourceIds = new Set;
38790
38834
  for (const skill of this.datasourceSkills) {
@@ -40259,13 +40303,7 @@ Warning: the edited config did not validate, so the previous config was restored
40259
40303
  ${list.map((entry, index) => `[${index + 1}] ${entry}`).join(`
40260
40304
  `)}`;
40261
40305
  const perQuery = await Promise.all(searchQueries.map((searchQuery) => Promise.all([
40262
- this.searchProgress.track("minsync", "MinSync semantic search", this.minSyncMethod.retrieve(searchQuery, retrieveOptions), {
40263
- count: (found) => found.length
40264
- }).catch((error) => {
40265
- if (error instanceof MinSyncRequiredError)
40266
- throw error;
40267
- return [];
40268
- }),
40306
+ this.prefetchMinSyncCandidates(searchQuery, retrieveOptions),
40269
40307
  Promise.all(datasources.map((datasourceId) => this.searchProgress.track(`datasource:${datasourceId}`, `Datasource ${datasourceId}`, this.searchSingleDatasourceDocuments(datasourceId, searchQuery, {
40270
40308
  topK: this.limits.prefetch.datasourceTopK,
40271
40309
  scope: options.scope,
@@ -40380,6 +40418,30 @@ ${result.content.replace(/\s+/gu, " ")}`).join(`
40380
40418
 
40381
40419
  `);
40382
40420
  }
40421
+ async prefetchMinSyncCandidates(searchQuery, options) {
40422
+ const sparse = this.reranker === undefined ? undefined : this.minSyncSparseMethod;
40423
+ const run = (id, label, method) => this.searchProgress.track(id, label, method.retrieve(searchQuery, options), { count: (found) => found.length }).catch((error) => {
40424
+ if (error instanceof MinSyncRequiredError)
40425
+ throw error;
40426
+ if (sparse !== undefined) {
40427
+ this.routingDiagnostics.push({
40428
+ code: "retrieval-method-failed",
40429
+ severity: "warning",
40430
+ message: `MinSync ${id === "minsync" ? "dense" : "SPLADE"} search failed and its candidates were skipped; the other channel's were used: ${describeRetrievalError(error)}`,
40431
+ source: id
40432
+ });
40433
+ }
40434
+ return [];
40435
+ });
40436
+ const dense = run("minsync", "MinSync semantic search", this.minSyncMethod);
40437
+ if (sparse === undefined)
40438
+ return dense;
40439
+ const [vector, splade] = await Promise.all([dense, run("minsync-sparse", "MinSync SPLADE search", sparse)]);
40440
+ return unionChannelResults([
40441
+ { channel: "vector", results: vector },
40442
+ { channel: "sparse", results: splade }
40443
+ ]);
40444
+ }
40383
40445
  async prefetchWebSearch(searchQuery, signal) {
40384
40446
  const web = this.webSearchOptions;
40385
40447
  if (web === undefined)
@@ -41173,7 +41235,7 @@ ${this.discoveryHint((tools) => `When exploring local files and folders, activel
41173
41235
  return { ok: false, reason: "cloud-root-skipped", stdout: "", stderr: "", code: null };
41174
41236
  }
41175
41237
  const canonicalSourcePath = canonicalPath(sourcePath);
41176
- const exclude = scope.nestedCloudRoots.map((root) => relative8(canonicalSourcePath, root.path).split(sep10).join("/")).filter((pattern) => pattern !== "" && !pattern.startsWith(".."));
41238
+ const exclude = scope.nestedCloudRoots.map((root) => relative8(canonicalSourcePath, root.path).split(sep9).join("/")).filter((pattern) => pattern !== "" && !pattern.startsWith(".."));
41177
41239
  return client.prepare(sourcePath, { ...options, ...exclude.length === 0 ? {} : { exclude } });
41178
41240
  }));
41179
41241
  }
@@ -41687,6 +41749,8 @@ function toMinSyncReasonDiagnostic(reason) {
41687
41749
  };
41688
41750
  }
41689
41751
  function pinExcludedPath(path) {
41752
+ if (isGlobExclusion(path))
41753
+ return path;
41690
41754
  const resolvedPath = resolve18(path);
41691
41755
  try {
41692
41756
  return join54(realpathSync8(dirname27(resolvedPath)), basename15(resolvedPath));
@@ -41735,6 +41799,7 @@ var init_agent = __esm(() => {
41735
41799
  init_embedding();
41736
41800
  init_everything();
41737
41801
  init_cloud_placeholder();
41802
+ init_path_exclusions();
41738
41803
  init_fsearch();
41739
41804
  init_diagnostics();
41740
41805
  init_jikji();
@@ -41757,6 +41822,7 @@ var init_agent = __esm(() => {
41757
41822
  init_merger();
41758
41823
  init_rerank();
41759
41824
  init_scope();
41825
+ init_skip();
41760
41826
  init_search();
41761
41827
  init_model_auth();
41762
41828
  init_answer_citations();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autorag/librarian",
3
- "version": "2.13.8",
3
+ "version": "2.13.10",
4
4
  "description": "Personal librarian agent for office work on the Pi framework, with pluggable retrieval methods",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {