@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/agent/agent.d.ts +10 -0
- package/dist/cli/commands/lite-find.d.ts +26 -0
- package/dist/cli/index.js +757 -42
- package/dist/core.d.ts +5 -0
- package/dist/core.js +102 -30
- package/dist/filesystem/path-exclusions.d.ts +12 -1
- package/dist/find/groups.d.ts +35 -0
- package/dist/find/index.d.ts +10 -0
- package/dist/find/relevance.d.ts +29 -0
- package/dist/find/run.d.ts +24 -0
- package/dist/find/text.d.ts +37 -0
- package/dist/find/types.d.ts +86 -0
- package/dist/index.js +177 -35
- package/dist/mcp/index.js +224 -38
- package/dist/mcp/reloading-lite.d.ts +25 -0
- package/dist/minsync/channel-union.d.ts +23 -0
- package/dist/mirror/sync.d.ts +1 -0
- package/dist/profiles.js +105 -39
- package/package.json +1 -1
package/dist/core.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { AutoRAGJikjiPrepareResult, AutoRAGRefreshOptions, AutoRAGRefreshRe
|
|
|
2
2
|
import type { AutoRAGResultsDetails } from "./agent/results.js";
|
|
3
3
|
import { type SearchDocumentsResponse } from "./agent/search-documents.js";
|
|
4
4
|
import { type CliConfig, type ResolveConfigInput } from "./cli/config.js";
|
|
5
|
+
import type { ConvertAndRelateResult, FileeConvertRequest } from "./convert/index.js";
|
|
5
6
|
import type { EverythingSearchRequest, EverythingSearchResult } from "./everything/index.js";
|
|
6
7
|
import type { FSearchSearchRequest, FSearchSearchResult } from "./fsearch/index.js";
|
|
7
8
|
import type { JikjiPrepareOptions } from "./jikji/index.js";
|
|
@@ -84,6 +85,10 @@ export declare class AutoRAGLite {
|
|
|
84
85
|
recordReport(query: string, details: AutoRAGResultsDetails): SearchDocumentsResponse;
|
|
85
86
|
/** Return a detached snapshot of persisted evidence state. */
|
|
86
87
|
getMemorySchema(): MemorySchema;
|
|
88
|
+
/** Convert files with Filee, then ask Dupey whether each output joins its source's family. */
|
|
89
|
+
convertFiles(request: FileeConvertRequest, signal?: AbortSignal): Promise<ConvertAndRelateResult>;
|
|
90
|
+
/** The formats Filee knows, or what one source format can become. */
|
|
91
|
+
listFileConversions(from?: string, signal?: AbortSignal): Promise<string>;
|
|
87
92
|
}
|
|
88
93
|
/** Resolve the existing CLI config and construct a model-free runtime. */
|
|
89
94
|
export declare function createAutoRAGLite(options?: AutoRAGLiteOptions): AutoRAGLite;
|
package/dist/core.js
CHANGED
|
@@ -3668,20 +3668,30 @@ var init_bundle = __esm(() => {
|
|
|
3668
3668
|
});
|
|
3669
3669
|
|
|
3670
3670
|
// src/filesystem/path-exclusions.ts
|
|
3671
|
-
import { posix as posix2, win32 as win322 } from "node:path";
|
|
3671
|
+
import { matchesGlob, posix as posix2, win32 as win322 } from "node:path";
|
|
3672
|
+
function isGlobExclusion(entry) {
|
|
3673
|
+
return /[*?[]/u.test(entry);
|
|
3674
|
+
}
|
|
3675
|
+
function matchesGlobExclusion(path, glob) {
|
|
3676
|
+
const slashed = path.replaceAll("\\", "/");
|
|
3677
|
+
if (matchesGlob(slashed, glob))
|
|
3678
|
+
return true;
|
|
3679
|
+
return glob.startsWith("**/") && matchesGlob(slashed, glob.slice(3));
|
|
3680
|
+
}
|
|
3672
3681
|
function createPathExclusionMatcher(excludedPaths, platform = process.platform) {
|
|
3673
3682
|
const paths = platform === "win32" ? win322 : posix2;
|
|
3674
3683
|
const normalize = (path) => {
|
|
3675
3684
|
const absolute = paths.resolve(path);
|
|
3676
3685
|
return platform === "win32" ? absolute.toLowerCase() : absolute;
|
|
3677
3686
|
};
|
|
3678
|
-
const
|
|
3687
|
+
const globs = excludedPaths.filter(isGlobExclusion).map((glob) => platform === "win32" ? glob.toLowerCase() : glob);
|
|
3688
|
+
const excluded = excludedPaths.filter((path) => !isGlobExclusion(path)).map((path) => {
|
|
3679
3689
|
const absolute = normalize(path);
|
|
3680
3690
|
return { absolute, prefix: absolute.endsWith(paths.sep) ? absolute : `${absolute}${paths.sep}` };
|
|
3681
3691
|
});
|
|
3682
3692
|
return (path) => {
|
|
3683
3693
|
const absolute = normalize(path);
|
|
3684
|
-
return excluded.some((entry) => absolute === entry.absolute || absolute.startsWith(entry.prefix));
|
|
3694
|
+
return excluded.some((entry) => absolute === entry.absolute || absolute.startsWith(entry.prefix)) || globs.some((glob) => matchesGlobExclusion(absolute, glob));
|
|
3685
3695
|
};
|
|
3686
3696
|
}
|
|
3687
3697
|
var init_path_exclusions = () => {};
|
|
@@ -7618,6 +7628,34 @@ var init_memory = __esm(() => {
|
|
|
7618
7628
|
});
|
|
7619
7629
|
});
|
|
7620
7630
|
|
|
7631
|
+
// src/minsync/channel-union.ts
|
|
7632
|
+
function unionChannelResults(channels, options = {}) {
|
|
7633
|
+
const byChunk = new Map;
|
|
7634
|
+
const depth = Math.max(0, ...channels.map((channel) => channel.results.length));
|
|
7635
|
+
for (let rank = 0;rank < depth; rank++) {
|
|
7636
|
+
for (const channel of channels) {
|
|
7637
|
+
const result = channel.results[rank];
|
|
7638
|
+
if (result === undefined)
|
|
7639
|
+
continue;
|
|
7640
|
+
const key = `${result.source}\x00${result.id}`;
|
|
7641
|
+
const existing = byChunk.get(key);
|
|
7642
|
+
if (existing === undefined)
|
|
7643
|
+
byChunk.set(key, { result, ranks: { [channel.channel]: rank + 1 } });
|
|
7644
|
+
else
|
|
7645
|
+
existing.ranks[channel.channel] ??= rank + 1;
|
|
7646
|
+
}
|
|
7647
|
+
}
|
|
7648
|
+
const union = [...byChunk.values()].map(({ result, ranks }) => ({
|
|
7649
|
+
...result,
|
|
7650
|
+
metadata: {
|
|
7651
|
+
...result.metadata,
|
|
7652
|
+
minsyncChannels: Object.keys(ranks).sort(),
|
|
7653
|
+
minsyncChannelRanks: ranks
|
|
7654
|
+
}
|
|
7655
|
+
}));
|
|
7656
|
+
return options.limit === undefined ? union : union.slice(0, options.limit);
|
|
7657
|
+
}
|
|
7658
|
+
|
|
7621
7659
|
// src/minsync/local-embedder.ts
|
|
7622
7660
|
import { spawn as spawn11 } from "node:child_process";
|
|
7623
7661
|
import { request } from "node:http";
|
|
@@ -10305,7 +10343,7 @@ var init_cloud = __esm(() => {
|
|
|
10305
10343
|
// src/mirror/sync.ts
|
|
10306
10344
|
import { createHash as createHash11 } from "node:crypto";
|
|
10307
10345
|
import { opendir, readFile, stat as stat3 } from "node:fs/promises";
|
|
10308
|
-
import { basename as basename9, dirname as dirname12, extname as extname6, join as join27, resolve as resolve11
|
|
10346
|
+
import { basename as basename9, dirname as dirname12, extname as extname6, join as join27, resolve as resolve11 } from "node:path";
|
|
10309
10347
|
import { setTimeout as sleep3 } from "node:timers/promises";
|
|
10310
10348
|
function errorCode(error) {
|
|
10311
10349
|
if (!(error instanceof Error))
|
|
@@ -10852,13 +10890,14 @@ function normalizeExtension2(extension) {
|
|
|
10852
10890
|
return lower.startsWith(".") ? lower : `.${lower}`;
|
|
10853
10891
|
}
|
|
10854
10892
|
function isPathExcluded(sourcePath, excluded) {
|
|
10855
|
-
if (excluded === undefined)
|
|
10893
|
+
if (excluded === undefined || excluded.size === 0)
|
|
10856
10894
|
return false;
|
|
10857
|
-
|
|
10858
|
-
|
|
10859
|
-
|
|
10895
|
+
let matcher = matcherBySet.get(excluded);
|
|
10896
|
+
if (matcher === undefined) {
|
|
10897
|
+
matcher = createPathExclusionMatcher([...excluded]);
|
|
10898
|
+
matcherBySet.set(excluded, matcher);
|
|
10860
10899
|
}
|
|
10861
|
-
return
|
|
10900
|
+
return matcher(sourcePath);
|
|
10862
10901
|
}
|
|
10863
10902
|
function walkLimits(options) {
|
|
10864
10903
|
return {
|
|
@@ -11025,10 +11064,11 @@ async function collectFiles(state, directory, depth) {
|
|
|
11025
11064
|
warnDirectoryUnreadable(state, directory, code);
|
|
11026
11065
|
}
|
|
11027
11066
|
}
|
|
11028
|
-
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;
|
|
11067
|
+
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;
|
|
11029
11068
|
var init_sync = __esm(() => {
|
|
11030
11069
|
init_cli2();
|
|
11031
11070
|
init_cloud_placeholder();
|
|
11071
|
+
init_path_exclusions();
|
|
11032
11072
|
init_source_paths();
|
|
11033
11073
|
init_binary();
|
|
11034
11074
|
init_stage();
|
|
@@ -11087,6 +11127,7 @@ var init_sync = __esm(() => {
|
|
|
11087
11127
|
}
|
|
11088
11128
|
};
|
|
11089
11129
|
STANDALONE_OCR_IMAGE_EXTENSIONS = new Set(KORDOC_IMAGE_EXTENSIONS);
|
|
11130
|
+
matcherBySet = new WeakMap;
|
|
11090
11131
|
SEARCH_ROOT_UNAVAILABLE_MESSAGES = {
|
|
11091
11132
|
gone: "A search root no longer exists; its previously indexed documents were left untouched.",
|
|
11092
11133
|
"not-a-directory": "A search root is no longer a directory; its previously indexed documents were left untouched.",
|
|
@@ -16161,7 +16202,7 @@ var init_automation_profiles = __esm(() => {
|
|
|
16161
16202
|
|
|
16162
16203
|
// src/automation/config.ts
|
|
16163
16204
|
import { existsSync as existsSync19, readFileSync as readFileSync14, realpathSync as realpathSync7 } from "node:fs";
|
|
16164
|
-
import { basename as basename10, dirname as dirname15, isAbsolute as isAbsolute8, join as join30, matchesGlob, relative as relative5, resolve as resolve12 } from "node:path";
|
|
16205
|
+
import { basename as basename10, dirname as dirname15, isAbsolute as isAbsolute8, join as join30, matchesGlob as matchesGlob2, relative as relative5, resolve as resolve12 } from "node:path";
|
|
16165
16206
|
function automationsConfigPath(env = process.env) {
|
|
16166
16207
|
return join30(resolveAutoRAGHome(env), "automations.json");
|
|
16167
16208
|
}
|
|
@@ -16337,9 +16378,9 @@ function deleteAutomation(configPath, id) {
|
|
|
16337
16378
|
function globMatches(relPosix, pattern) {
|
|
16338
16379
|
if (pattern === "**")
|
|
16339
16380
|
return true;
|
|
16340
|
-
if (
|
|
16381
|
+
if (matchesGlob2(relPosix, pattern))
|
|
16341
16382
|
return true;
|
|
16342
|
-
if (pattern.startsWith("**/") &&
|
|
16383
|
+
if (pattern.startsWith("**/") && matchesGlob2(relPosix, pattern.slice(3)))
|
|
16343
16384
|
return true;
|
|
16344
16385
|
return false;
|
|
16345
16386
|
}
|
|
@@ -17136,7 +17177,7 @@ var init_permission_judgment = __esm(() => {
|
|
|
17136
17177
|
|
|
17137
17178
|
// src/agent/permission-gate.ts
|
|
17138
17179
|
import { statSync as statSync7 } from "node:fs";
|
|
17139
|
-
import { isAbsolute as isAbsolute9, relative as relative6, sep as
|
|
17180
|
+
import { isAbsolute as isAbsolute9, relative as relative6, sep as sep6 } from "node:path";
|
|
17140
17181
|
import { matchesKey } from "@earendil-works/pi-tui";
|
|
17141
17182
|
function pathExists(path) {
|
|
17142
17183
|
try {
|
|
@@ -17199,7 +17240,7 @@ class PermissionController {
|
|
|
17199
17240
|
if (path === root)
|
|
17200
17241
|
return true;
|
|
17201
17242
|
const rel = relative6(root, path);
|
|
17202
|
-
if (rel !== "" && rel !== ".." && !rel.startsWith(`..${
|
|
17243
|
+
if (rel !== "" && rel !== ".." && !rel.startsWith(`..${sep6}`) && !isAbsolute9(rel))
|
|
17203
17244
|
return true;
|
|
17204
17245
|
}
|
|
17205
17246
|
return false;
|
|
@@ -18651,7 +18692,7 @@ var init_connector = () => {};
|
|
|
18651
18692
|
// src/datasource/sidecar/config.ts
|
|
18652
18693
|
import { readFileSync as readFileSync17 } from "node:fs";
|
|
18653
18694
|
import { homedir as homedir5 } from "node:os";
|
|
18654
|
-
import { dirname as dirname17, isAbsolute as isAbsolute10, join as join34, resolve as resolve14, sep as
|
|
18695
|
+
import { dirname as dirname17, isAbsolute as isAbsolute10, join as join34, resolve as resolve14, sep as sep7 } from "node:path";
|
|
18655
18696
|
import { parse as parseToml } from "smol-toml";
|
|
18656
18697
|
function resolveSidecarOptions(input) {
|
|
18657
18698
|
const { connector, workspaceRoot } = input;
|
|
@@ -18691,7 +18732,7 @@ function archivePathFromCrawlerConfig(input) {
|
|
|
18691
18732
|
function expandHome(path) {
|
|
18692
18733
|
if (path === "~")
|
|
18693
18734
|
return homedir5();
|
|
18694
|
-
const prefixed = path.startsWith("~/") ||
|
|
18735
|
+
const prefixed = path.startsWith("~/") || sep7 === "\\" && path.startsWith("~\\");
|
|
18695
18736
|
return prefixed ? join34(homedir5(), path.slice(2)) : path;
|
|
18696
18737
|
}
|
|
18697
18738
|
var init_config3 = __esm(() => {
|
|
@@ -25945,7 +25986,7 @@ import {
|
|
|
25945
25986
|
writeFileSync as writeFileSync13
|
|
25946
25987
|
} from "node:fs";
|
|
25947
25988
|
import { opendir as opendir2, stat as stat4 } from "node:fs/promises";
|
|
25948
|
-
import { basename as basename11, dirname as dirname23, extname as extname8, join as join40, relative as relative7, sep as
|
|
25989
|
+
import { basename as basename11, dirname as dirname23, extname as extname8, join as join40, relative as relative7, sep as sep8 } from "node:path";
|
|
25949
25990
|
function errnoCode2(error) {
|
|
25950
25991
|
const code = error instanceof Error ? error.code : undefined;
|
|
25951
25992
|
return typeof code === "string" ? code : "UNKNOWN";
|
|
@@ -26015,7 +26056,7 @@ async function listVaultNotes(vaultPath) {
|
|
|
26015
26056
|
return { notes, unreadableFolders, collisions };
|
|
26016
26057
|
}
|
|
26017
26058
|
function toRelative(vaultPath, path) {
|
|
26018
|
-
return relative7(vaultPath, path).split(
|
|
26059
|
+
return relative7(vaultPath, path).split(sep8).join("/").normalize("NFC");
|
|
26019
26060
|
}
|
|
26020
26061
|
function loadStagingState2(statePath) {
|
|
26021
26062
|
try {
|
|
@@ -26099,7 +26140,7 @@ function removeUnexpected(filesRoot, directory, wanted) {
|
|
|
26099
26140
|
return removed;
|
|
26100
26141
|
}
|
|
26101
26142
|
function toStagedRelative(filesRoot, path) {
|
|
26102
|
-
return relative7(filesRoot, path).split(
|
|
26143
|
+
return relative7(filesRoot, path).split(sep8).join("/").normalize("NFC");
|
|
26103
26144
|
}
|
|
26104
26145
|
var NOTE_EXTENSIONS, SKIPPED_DIRECTORIES, MAX_WALK_DEPTH = 64, VaultUnavailableError;
|
|
26105
26146
|
var init_staging = __esm(() => {
|
|
@@ -28020,7 +28061,7 @@ function resolveExcludePaths(value, origin) {
|
|
|
28020
28061
|
if (!Array.isArray(value) || value.some((path) => typeof path !== "string" || path.length === 0)) {
|
|
28021
28062
|
throw new ConfigError("Config field 'excludePaths' must be a non-empty string array");
|
|
28022
28063
|
}
|
|
28023
|
-
return
|
|
28064
|
+
return value.map((entry) => isGlobExclusion(entry) ? entry : resolvePersistedPath(entry, origin));
|
|
28024
28065
|
}
|
|
28025
28066
|
function resolvePersistedPath(path, origin) {
|
|
28026
28067
|
return isAbsolute11(path) ? path : resolve15(origin, path);
|
|
@@ -29325,6 +29366,7 @@ var init_config5 = __esm(() => {
|
|
|
29325
29366
|
init_factory();
|
|
29326
29367
|
init_embedding();
|
|
29327
29368
|
init_file_lock();
|
|
29369
|
+
init_path_exclusions();
|
|
29328
29370
|
init_language();
|
|
29329
29371
|
init_atomic_write();
|
|
29330
29372
|
init_rerank();
|
|
@@ -38578,7 +38620,7 @@ var init_web_search_tool = __esm(() => {
|
|
|
38578
38620
|
// src/agent/agent.ts
|
|
38579
38621
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
38580
38622
|
import { existsSync as existsSync34, watch as fsWatch, mkdirSync as mkdirSync24, realpathSync as realpathSync8, statSync as statSync11, writeFileSync as writeFileSync17 } from "node:fs";
|
|
38581
|
-
import { basename as basename15, dirname as dirname27, join as join55, relative as relative8, resolve as resolve18, sep as
|
|
38623
|
+
import { basename as basename15, dirname as dirname27, join as join55, relative as relative8, resolve as resolve18, sep as sep9 } from "node:path";
|
|
38582
38624
|
import { clampThinkingLevel } from "@earendil-works/pi-ai/compat";
|
|
38583
38625
|
import { getAgentDir as getAgentDir6, keyText } from "@earendil-works/pi-coding-agent";
|
|
38584
38626
|
function describeDecisionModel(status) {
|
|
@@ -38721,6 +38763,7 @@ class AutoRAGAgent {
|
|
|
38721
38763
|
reranker;
|
|
38722
38764
|
rerankTopN;
|
|
38723
38765
|
minSyncMethod;
|
|
38766
|
+
minSyncSparseMethod;
|
|
38724
38767
|
minSyncEmbedderConfig;
|
|
38725
38768
|
minSyncBinaryPath;
|
|
38726
38769
|
jikjiClient;
|
|
@@ -38843,6 +38886,7 @@ class AutoRAGAgent {
|
|
|
38843
38886
|
...this.limits.recordCut === undefined ? {} : { recordCut: this.limits.recordCut }
|
|
38844
38887
|
};
|
|
38845
38888
|
this.minSyncMethod = new MinSyncVectorMethod(minSyncDefaults);
|
|
38889
|
+
this.minSyncSparseMethod = isSparseOnlyEmbedder(options.minSync?.embedder) ? undefined : new MinSyncVectorMethod({ ...minSyncDefaults, mode: "sparse" });
|
|
38846
38890
|
this.methodRegistry.register(new MinSyncHybridMethod(minSyncDefaults));
|
|
38847
38891
|
const registeredDatasourceIds = new Set;
|
|
38848
38892
|
for (const skill of this.datasourceSkills) {
|
|
@@ -40317,13 +40361,7 @@ Warning: the edited config did not validate, so the previous config was restored
|
|
|
40317
40361
|
${list.map((entry, index) => `[${index + 1}] ${entry}`).join(`
|
|
40318
40362
|
`)}`;
|
|
40319
40363
|
const perQuery = await Promise.all(searchQueries.map((searchQuery) => Promise.all([
|
|
40320
|
-
this.
|
|
40321
|
-
count: (found) => found.length
|
|
40322
|
-
}).catch((error) => {
|
|
40323
|
-
if (error instanceof MinSyncRequiredError)
|
|
40324
|
-
throw error;
|
|
40325
|
-
return [];
|
|
40326
|
-
}),
|
|
40364
|
+
this.prefetchMinSyncCandidates(searchQuery, retrieveOptions),
|
|
40327
40365
|
Promise.all(datasources.map((datasourceId) => this.searchProgress.track(`datasource:${datasourceId}`, `Datasource ${datasourceId}`, this.searchSingleDatasourceDocuments(datasourceId, searchQuery, {
|
|
40328
40366
|
topK: this.limits.prefetch.datasourceTopK,
|
|
40329
40367
|
scope: options.scope,
|
|
@@ -40438,6 +40476,30 @@ ${result.content.replace(/\s+/gu, " ")}`).join(`
|
|
|
40438
40476
|
|
|
40439
40477
|
`);
|
|
40440
40478
|
}
|
|
40479
|
+
async prefetchMinSyncCandidates(searchQuery, options) {
|
|
40480
|
+
const sparse = this.reranker === undefined ? undefined : this.minSyncSparseMethod;
|
|
40481
|
+
const run = (id, label, method) => this.searchProgress.track(id, label, method.retrieve(searchQuery, options), { count: (found) => found.length }).catch((error) => {
|
|
40482
|
+
if (error instanceof MinSyncRequiredError)
|
|
40483
|
+
throw error;
|
|
40484
|
+
if (sparse !== undefined) {
|
|
40485
|
+
this.routingDiagnostics.push({
|
|
40486
|
+
code: "retrieval-method-failed",
|
|
40487
|
+
severity: "warning",
|
|
40488
|
+
message: `MinSync ${id === "minsync" ? "dense" : "SPLADE"} search failed and its candidates were skipped; the other channel's were used: ${describeRetrievalError(error)}`,
|
|
40489
|
+
source: id
|
|
40490
|
+
});
|
|
40491
|
+
}
|
|
40492
|
+
return [];
|
|
40493
|
+
});
|
|
40494
|
+
const dense = run("minsync", "MinSync semantic search", this.minSyncMethod);
|
|
40495
|
+
if (sparse === undefined)
|
|
40496
|
+
return dense;
|
|
40497
|
+
const [vector, splade] = await Promise.all([dense, run("minsync-sparse", "MinSync SPLADE search", sparse)]);
|
|
40498
|
+
return unionChannelResults([
|
|
40499
|
+
{ channel: "vector", results: vector },
|
|
40500
|
+
{ channel: "sparse", results: splade }
|
|
40501
|
+
]);
|
|
40502
|
+
}
|
|
40441
40503
|
async prefetchWebSearch(searchQuery, signal) {
|
|
40442
40504
|
const web = this.webSearchOptions;
|
|
40443
40505
|
if (web === undefined)
|
|
@@ -41231,7 +41293,7 @@ ${this.discoveryHint((tools) => `When exploring local files and folders, activel
|
|
|
41231
41293
|
return { ok: false, reason: "cloud-root-skipped", stdout: "", stderr: "", code: null };
|
|
41232
41294
|
}
|
|
41233
41295
|
const canonicalSourcePath = canonicalPath(sourcePath);
|
|
41234
|
-
const exclude = scope.nestedCloudRoots.map((root) => relative8(canonicalSourcePath, root.path).split(
|
|
41296
|
+
const exclude = scope.nestedCloudRoots.map((root) => relative8(canonicalSourcePath, root.path).split(sep9).join("/")).filter((pattern) => pattern !== "" && !pattern.startsWith(".."));
|
|
41235
41297
|
return client.prepare(sourcePath, { ...options, ...exclude.length === 0 ? {} : { exclude } });
|
|
41236
41298
|
}));
|
|
41237
41299
|
}
|
|
@@ -41745,6 +41807,8 @@ function toMinSyncReasonDiagnostic(reason) {
|
|
|
41745
41807
|
};
|
|
41746
41808
|
}
|
|
41747
41809
|
function pinExcludedPath(path) {
|
|
41810
|
+
if (isGlobExclusion(path))
|
|
41811
|
+
return path;
|
|
41748
41812
|
const resolvedPath = resolve18(path);
|
|
41749
41813
|
try {
|
|
41750
41814
|
return join55(realpathSync8(dirname27(resolvedPath)), basename15(resolvedPath));
|
|
@@ -41793,6 +41857,7 @@ var init_agent = __esm(() => {
|
|
|
41793
41857
|
init_embedding();
|
|
41794
41858
|
init_everything();
|
|
41795
41859
|
init_cloud_placeholder();
|
|
41860
|
+
init_path_exclusions();
|
|
41796
41861
|
init_fsearch();
|
|
41797
41862
|
init_diagnostics();
|
|
41798
41863
|
init_jikji();
|
|
@@ -41815,6 +41880,7 @@ var init_agent = __esm(() => {
|
|
|
41815
41880
|
init_merger();
|
|
41816
41881
|
init_rerank();
|
|
41817
41882
|
init_scope();
|
|
41883
|
+
init_skip();
|
|
41818
41884
|
init_search();
|
|
41819
41885
|
init_model_auth();
|
|
41820
41886
|
init_answer_citations();
|
|
@@ -41952,6 +42018,12 @@ class AutoRAGLite {
|
|
|
41952
42018
|
getMemorySchema() {
|
|
41953
42019
|
return structuredClone(this.memory.getSchema());
|
|
41954
42020
|
}
|
|
42021
|
+
convertFiles(request, signal) {
|
|
42022
|
+
return this.agent.convertFiles(request, signal);
|
|
42023
|
+
}
|
|
42024
|
+
listFileConversions(from, signal) {
|
|
42025
|
+
return this.agent.listFileConversions(from, signal);
|
|
42026
|
+
}
|
|
41955
42027
|
}
|
|
41956
42028
|
function createAutoRAGLite(options = {}) {
|
|
41957
42029
|
const input = { flags: options.flags ?? {} };
|
|
@@ -1,2 +1,13 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* An `excludePaths` entry with `*`, `?` or `[` is a glob over the whole absolute path (`**\/node_modules/**`,
|
|
3
|
+
* `**\/Downloads/**`, `**\/*.log`); any other entry is a file or directory path. A glob is never resolved against a
|
|
4
|
+
* directory: it would then stop matching anywhere else.
|
|
5
|
+
*/
|
|
6
|
+
export declare function isGlobExclusion(entry: string): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Whether an absolute path matches a glob entry. Separators are compared as `/`, and a leading `**\/` also matches at
|
|
9
|
+
* the filesystem root, because `matchesGlob("/a.log", "**\/*.log")` differs between platforms in Node 24.
|
|
10
|
+
*/
|
|
11
|
+
export declare function matchesGlobExclusion(path: string, glob: string): boolean;
|
|
12
|
+
/** Match exact paths and directory subtrees without matching sibling prefixes, and glob entries (see {@link isGlobExclusion}). */
|
|
2
13
|
export declare function createPathExclusionMatcher(excludedPaths: readonly string[], platform?: NodeJS.Platform): (path: string) => boolean;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The group runners behind `autorag lite find`: one model-free search per
|
|
3
|
+
* surface — the platform file-name index, local document content, and each
|
|
4
|
+
* connected datasource, each asked on its own so a slow one never blocks the
|
|
5
|
+
* rest.
|
|
6
|
+
*/
|
|
7
|
+
import type { RetrievalResult } from "../retrieval/types.js";
|
|
8
|
+
import type { FindGroupDescriptor, FindGroupStatus, FindHit, FindJudge, FindRuntime } from "./types.js";
|
|
9
|
+
/** The result of running one group. */
|
|
10
|
+
export interface FindGroupOutcome {
|
|
11
|
+
readonly status: FindGroupStatus;
|
|
12
|
+
readonly hits: readonly FindHit[];
|
|
13
|
+
readonly error: string | null;
|
|
14
|
+
}
|
|
15
|
+
export interface FindGroupRunner {
|
|
16
|
+
readonly key: string;
|
|
17
|
+
readonly descriptor: FindGroupDescriptor;
|
|
18
|
+
run(): Promise<FindGroupOutcome>;
|
|
19
|
+
}
|
|
20
|
+
export interface BuildGroupRunnersOptions {
|
|
21
|
+
readonly query: string;
|
|
22
|
+
readonly topK: number;
|
|
23
|
+
readonly runtime: FindRuntime;
|
|
24
|
+
readonly judge?: FindJudge;
|
|
25
|
+
readonly platform?: NodeJS.Platform;
|
|
26
|
+
/** Whether the platform file-name index is enabled in config (default true). */
|
|
27
|
+
readonly fileSearchEnabled?: boolean;
|
|
28
|
+
/** Whether local semantic search is enabled in config (default true). */
|
|
29
|
+
readonly semanticEnabled?: boolean;
|
|
30
|
+
/** The enabled, registered datasources, in config order. */
|
|
31
|
+
readonly datasources?: readonly FindGroupDescriptor[];
|
|
32
|
+
}
|
|
33
|
+
/** A retrieval result as a datasource hit; exported for tests. */
|
|
34
|
+
export declare function sourceHit(result: RetrievalResult, query: string): FindHit;
|
|
35
|
+
export declare function buildGroupRunners(options: BuildGroupRunnersOptions): FindGroupRunner[];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `autorag lite find`: a model-free whole search across the platform file-name
|
|
3
|
+
* index, local document content, and every connected datasource. Pure and
|
|
4
|
+
* injectable (runtime, judge); the CLI wires the real ones and prints NDJSON.
|
|
5
|
+
*/
|
|
6
|
+
export { type BuildGroupRunnersOptions, buildGroupRunners, type FindGroupOutcome, type FindGroupRunner, sourceHit, } from "./groups.js";
|
|
7
|
+
export { createRelevanceGate, JEV_RELEVANCE_THRESHOLD, type RelevanceCandidate, type RelevanceGateDeps, type SearchRelevanceGate, } from "./relevance.js";
|
|
8
|
+
export { type FindRunOptions, runFind } from "./run.js";
|
|
9
|
+
export { capContent, contentSnippet, escapeSearchRegex, everythingRegexQuery, fsearchRegexQuery, matchesQueryLexically, SEARCH_HIT_CONTENT_LIMIT, } from "./text.js";
|
|
10
|
+
export type { FindDoneLine, FindGroupDescriptor, FindGroupLine, FindGroupStatus, FindGroupsLine, FindHit, FindJudge, FindJudgment, FindKind, FindLine, FindRuntime, FindSearchAnswer, FindVerdict, } from "./types.js";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The relevance gate for the `content` and `source:*` groups.
|
|
3
|
+
*
|
|
4
|
+
* A deterministic lexical pass auto-keeps obvious hits; everything else goes to
|
|
5
|
+
* the decision model as batched `noul` questions, and only candidates with
|
|
6
|
+
* P(relevant) at or above {@link JEV_RELEVANCE_THRESHOLD} survive, ordered by
|
|
7
|
+
* probability. When no decision model can answer — the judge throws, or returns
|
|
8
|
+
* no numeric verdicts — every candidate is kept unfiltered (fail open).
|
|
9
|
+
*/
|
|
10
|
+
import type { FindJudge } from "./types.js";
|
|
11
|
+
/** Minimum judged probability `P(relevant)` required for a non-lexical hit to be shown. */
|
|
12
|
+
export declare const JEV_RELEVANCE_THRESHOLD = 0.5;
|
|
13
|
+
export interface RelevanceCandidate {
|
|
14
|
+
readonly id: string;
|
|
15
|
+
readonly sourceLabel: string;
|
|
16
|
+
readonly title?: string | null;
|
|
17
|
+
readonly subtitle?: string | null;
|
|
18
|
+
readonly content: string;
|
|
19
|
+
}
|
|
20
|
+
export interface SearchRelevanceGate {
|
|
21
|
+
filter<T extends RelevanceCandidate>(query: string, candidates: readonly T[]): Promise<T[]>;
|
|
22
|
+
}
|
|
23
|
+
export interface RelevanceGateDeps {
|
|
24
|
+
readonly judge: FindJudge;
|
|
25
|
+
readonly threshold?: number;
|
|
26
|
+
readonly maxQuestionsPerBatch?: number;
|
|
27
|
+
readonly maxConcurrentBatches?: number;
|
|
28
|
+
}
|
|
29
|
+
export declare function createRelevanceGate(deps: RelevanceGateDeps): SearchRelevanceGate;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Orchestrates a whole search: emit the group list immediately, run every group
|
|
3
|
+
* in parallel, stream one group line per group in completion order, and finish
|
|
4
|
+
* with the done line. One group throwing never affects the others.
|
|
5
|
+
*/
|
|
6
|
+
import type { FindGroupDescriptor, FindJudge, FindLine, FindRuntime } from "./types.js";
|
|
7
|
+
export interface FindRunOptions {
|
|
8
|
+
readonly query: string;
|
|
9
|
+
readonly topK: number;
|
|
10
|
+
readonly runtime: FindRuntime;
|
|
11
|
+
readonly judge?: FindJudge;
|
|
12
|
+
readonly platform?: NodeJS.Platform;
|
|
13
|
+
readonly fileSearchEnabled?: boolean;
|
|
14
|
+
readonly semanticEnabled?: boolean;
|
|
15
|
+
/** The enabled, registered datasources, in config order. */
|
|
16
|
+
readonly datasources?: readonly FindGroupDescriptor[];
|
|
17
|
+
/** `--groups` narrowing: run only these keys. */
|
|
18
|
+
readonly groups?: readonly string[];
|
|
19
|
+
/** Emit the `groups` line before running. Pass false when the caller already announced it. */
|
|
20
|
+
readonly announce?: boolean;
|
|
21
|
+
readonly emit: (line: FindLine) => void;
|
|
22
|
+
readonly now?: () => number;
|
|
23
|
+
}
|
|
24
|
+
export declare function runFind(options: FindRunOptions): Promise<void>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text helpers for the whole-search groups: the relevance gate's deterministic
|
|
3
|
+
* lexical pass, the one-line snippet, and the platform file-name regexes.
|
|
4
|
+
*
|
|
5
|
+
* The lexical pass is ported from the Finder's `matchesQueryLexicallyOrApprox`
|
|
6
|
+
* with the approximate edit-distance step dropped, so it stays dependency-free.
|
|
7
|
+
*/
|
|
8
|
+
/** Passed text a hit carries, capped at this many characters. */
|
|
9
|
+
export declare const SEARCH_HIT_CONTENT_LIMIT = 2000;
|
|
10
|
+
/** The passage as one line, cut to {@link SNIPPET_LENGTH} around the first query term that appears in it. */
|
|
11
|
+
export declare function contentSnippet(text: string, query: string): string;
|
|
12
|
+
/** The passage flattened to one line and capped at {@link SEARCH_HIT_CONTENT_LIMIT} characters. */
|
|
13
|
+
export declare function capContent(text: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Fast deterministic pass-through before Jev: exact query word match (NFKC
|
|
16
|
+
* case-folded, ASCII boundary-aware so `_`/`-`/Hangul neighbors work while
|
|
17
|
+
* partial stems like `art` in `start` do not, plus Korean postposition
|
|
18
|
+
* stripping like `비행기를` → `비행기`). The approximate edit-distance step the
|
|
19
|
+
* Finder had is intentionally dropped: this is dependency-free.
|
|
20
|
+
*/
|
|
21
|
+
export declare function matchesQueryLexically(query: string, candidateText: string): boolean;
|
|
22
|
+
/** Escape a literal query so an index's regex mode matches it as a substring. */
|
|
23
|
+
export declare function escapeSearchRegex(text: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Regex for the fsearch index. macOS stores Hangul file names decomposed (NFD)
|
|
26
|
+
* while typed queries are composed (NFC), and the index compares bytes, so a
|
|
27
|
+
* name matches only when the query uses the same form. Sending both forms as an
|
|
28
|
+
* alternation finds either spelling; a query that has one form (ASCII) stays the
|
|
29
|
+
* plain escaped substring.
|
|
30
|
+
*/
|
|
31
|
+
export declare function fsearchRegexQuery(text: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* Everything's `regex:` search function is the working regex surface on the
|
|
34
|
+
* bundled ES build. A bare space ends the function's argument, so spaces become
|
|
35
|
+
* `\x20` to keep a literal substring.
|
|
36
|
+
*/
|
|
37
|
+
export declare function everythingRegexQuery(text: string): string;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { Question } from "jev-use";
|
|
2
|
+
import type { EverythingSearchRequest, EverythingSearchResult } from "../everything/index.js";
|
|
3
|
+
import type { FSearchSearchRequest, FSearchSearchResult } from "../fsearch/index.js";
|
|
4
|
+
import type { RetrievalSelection } from "../retrieval/selection.js";
|
|
5
|
+
import type { RetrievalDiagnostic, RetrievalOptions, RetrievalResult, RetrievalUnsearchedSurface } from "../retrieval/types.js";
|
|
6
|
+
/** What a whole-search hit is: a file name, document content, or a datasource message. */
|
|
7
|
+
export type FindKind = "file" | "content" | "message";
|
|
8
|
+
/** One hit on one group, shared by the filename, content, and datasource surfaces. */
|
|
9
|
+
export interface FindHit {
|
|
10
|
+
readonly id: string;
|
|
11
|
+
readonly kind: FindKind;
|
|
12
|
+
readonly title: string;
|
|
13
|
+
readonly author: string | null;
|
|
14
|
+
readonly snippet: string;
|
|
15
|
+
/** Passed text, capped at {@link SEARCH_HIT_CONTENT_LIMIT} characters. */
|
|
16
|
+
readonly content: string;
|
|
17
|
+
/** Absolute local path for file and content hits; null for datasource messages. */
|
|
18
|
+
readonly path: string | null;
|
|
19
|
+
readonly line: number | null;
|
|
20
|
+
/** Epoch milliseconds, when the source states one. */
|
|
21
|
+
readonly timestamp: number | null;
|
|
22
|
+
readonly url: string | null;
|
|
23
|
+
readonly score: number | null;
|
|
24
|
+
}
|
|
25
|
+
/** The group list line, printed before any group runs. */
|
|
26
|
+
export interface FindGroupDescriptor {
|
|
27
|
+
readonly key: string;
|
|
28
|
+
readonly datasourceId?: string;
|
|
29
|
+
readonly datasourceType?: string;
|
|
30
|
+
}
|
|
31
|
+
/** `off` = the surface is disabled in config; `unavailable` = its index is not built. */
|
|
32
|
+
export type FindGroupStatus = "ready" | "error" | "off" | "unavailable";
|
|
33
|
+
export interface FindGroupsLine {
|
|
34
|
+
readonly type: "groups";
|
|
35
|
+
readonly groups: readonly FindGroupDescriptor[];
|
|
36
|
+
}
|
|
37
|
+
export interface FindGroupLine {
|
|
38
|
+
readonly type: "group";
|
|
39
|
+
readonly key: string;
|
|
40
|
+
readonly status: FindGroupStatus;
|
|
41
|
+
readonly hits: readonly FindHit[];
|
|
42
|
+
/** The group's own failure text verbatim, or null. */
|
|
43
|
+
readonly error: string | null;
|
|
44
|
+
readonly elapsedMs: number;
|
|
45
|
+
}
|
|
46
|
+
export interface FindDoneLine {
|
|
47
|
+
readonly type: "done";
|
|
48
|
+
readonly elapsedMs: number;
|
|
49
|
+
}
|
|
50
|
+
export type FindLine = FindGroupsLine | FindGroupLine | FindDoneLine;
|
|
51
|
+
/** The answer shape `searchSelected` returns; a structural subset of the retrieval engine's. */
|
|
52
|
+
export interface FindSearchAnswer {
|
|
53
|
+
readonly results: readonly RetrievalResult[];
|
|
54
|
+
readonly diagnostics: readonly RetrievalDiagnostic[];
|
|
55
|
+
readonly unsearched: readonly RetrievalUnsearchedSurface[];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The model-free runtime a whole search drives. `AutoRAGLite` satisfies it
|
|
59
|
+
* structurally; tests inject a fake. Only these methods are touched, so a
|
|
60
|
+
* search never enters the model-backed agent loop.
|
|
61
|
+
*/
|
|
62
|
+
export interface FindRuntime {
|
|
63
|
+
listDatasources(): readonly {
|
|
64
|
+
readonly datasourceId: string;
|
|
65
|
+
}[];
|
|
66
|
+
searchSelected(query: string, selection?: RetrievalSelection, options?: RetrievalOptions): Promise<FindSearchAnswer>;
|
|
67
|
+
searchFsearch(request: FSearchSearchRequest): Promise<FSearchSearchResult>;
|
|
68
|
+
searchEverything(request: EverythingSearchRequest): Promise<EverythingSearchResult>;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* One batched `noul` judgment over relevance questions. The real implementation
|
|
72
|
+
* is `createDecisionModels(...).judge`; a thrown error means "no decision model
|
|
73
|
+
* can answer", and the gate fails open.
|
|
74
|
+
*/
|
|
75
|
+
export type FindJudge = (state: string, questions: Question[]) => Promise<FindJudgment>;
|
|
76
|
+
/** The verdicts the gate reads; a structural subset of `jev-use`'s `JudgeResult`. */
|
|
77
|
+
export interface FindJudgment {
|
|
78
|
+
readonly verdicts: readonly FindVerdict[];
|
|
79
|
+
}
|
|
80
|
+
export interface FindVerdict {
|
|
81
|
+
readonly id: string;
|
|
82
|
+
readonly type?: string;
|
|
83
|
+
readonly answer: number | string | null;
|
|
84
|
+
readonly confidence?: number;
|
|
85
|
+
readonly escalate?: boolean;
|
|
86
|
+
}
|