@autorag/librarian 2.3.0 → 2.4.0

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.
Files changed (72) hide show
  1. package/README.md +119 -14
  2. package/dist/agent/agent.d.ts +19 -7
  3. package/dist/agent/bash-tool.d.ts +2 -0
  4. package/dist/agent/search-bm25-tool.d.ts +11 -3
  5. package/dist/agent/search-documents.d.ts +2 -2
  6. package/dist/agent/search-minsync-tool.d.ts +2 -2
  7. package/dist/cli/commands/index.d.ts +3 -3
  8. package/dist/cli/commands/tui.d.ts +36 -0
  9. package/dist/cli/commands/ui.d.ts +13 -0
  10. package/dist/cli/config.d.ts +17 -8
  11. package/dist/cli/index.js +14474 -10610
  12. package/dist/cli/tui-commands.d.ts +16 -0
  13. package/dist/cli/tui-session-store.d.ts +16 -0
  14. package/dist/datasource/access-context.d.ts +6 -12
  15. package/dist/datasource/crawler-types.d.ts +2 -0
  16. package/dist/datasource/described-skill.d.ts +17 -0
  17. package/dist/datasource/index.d.ts +3 -3
  18. package/dist/datasource/result-filter.d.ts +2 -1
  19. package/dist/datasource/skills/clawgallery/client.d.ts +9 -0
  20. package/dist/datasource/skills/clawgallery/index.d.ts +5 -0
  21. package/dist/datasource/skills/clawgallery/methods.d.ts +19 -0
  22. package/dist/datasource/skills/clawgallery/paths.d.ts +7 -0
  23. package/dist/datasource/skills/clawgallery/skill.d.ts +35 -0
  24. package/dist/datasource/skills/clawgallery/types.d.ts +58 -0
  25. package/dist/datasource/skills/cloud-drive/index.d.ts +1 -0
  26. package/dist/datasource/skills/{gdrive → cloud-drive}/rclone-connector.d.ts +4 -0
  27. package/dist/datasource/skills/cloud-drive/skill.d.ts +1 -1
  28. package/dist/datasource/skills/discrawl/types.d.ts +4 -8
  29. package/dist/datasource/skills/factory.d.ts +2 -0
  30. package/dist/datasource/skills/gmail/himalaya-connector.d.ts +12 -1
  31. package/dist/datasource/skills/katok/methods.d.ts +6 -4
  32. package/dist/datasource/skills/katok/types.d.ts +8 -26
  33. package/dist/datasource/skills/mailcrawl/client.d.ts +15 -0
  34. package/dist/datasource/skills/mailcrawl/config.d.ts +2 -0
  35. package/dist/datasource/skills/mailcrawl/index.d.ts +4 -0
  36. package/dist/datasource/skills/mailcrawl/methods.d.ts +15 -0
  37. package/dist/datasource/skills/mailcrawl/skill.d.ts +34 -0
  38. package/dist/datasource/skills/mailcrawl/types.d.ts +71 -0
  39. package/dist/datasource/skills/obsidian/skill.d.ts +1 -0
  40. package/dist/datasource/skills/obsidian/types.d.ts +2 -0
  41. package/dist/datasource/types.d.ts +5 -2
  42. package/dist/filesystem/cloud-placeholder.d.ts +26 -0
  43. package/dist/index.js +2463 -1048
  44. package/dist/jikji/client.d.ts +1 -0
  45. package/dist/minsync/client.d.ts +5 -1
  46. package/dist/minsync/embedder-config.d.ts +4 -1
  47. package/dist/minsync/index.d.ts +4 -4
  48. package/dist/minsync/installer.d.ts +1 -0
  49. package/dist/minsync/method.d.ts +22 -1
  50. package/dist/minsync/types.d.ts +5 -0
  51. package/dist/mirror/sync.d.ts +1 -1
  52. package/dist/parser/defaults.d.ts +2 -0
  53. package/dist/parser/index.d.ts +2 -2
  54. package/dist/parser/opendataloader-pdf.d.ts +10 -0
  55. package/dist/parser/types.d.ts +7 -0
  56. package/dist/retrieval/index.d.ts +2 -2
  57. package/dist/retrieval/methods/bm25.d.ts +7 -36
  58. package/dist/ui/browse.d.ts +11 -0
  59. package/dist/ui/catalog.d.ts +59 -0
  60. package/dist/ui/config-store.d.ts +43 -0
  61. package/dist/ui/discover.d.ts +19 -0
  62. package/dist/ui/html.d.ts +2 -0
  63. package/dist/ui/probe.d.ts +24 -0
  64. package/dist/ui/prompt.d.ts +21 -0
  65. package/dist/ui/server.d.ts +28 -0
  66. package/package.json +13 -12
  67. package/skills/autorag/SKILL.md +48 -40
  68. package/skills/autorag-setup/SKILL.md +67 -36
  69. package/dist/datasource/skills/discrawl/config.d.ts +0 -9
  70. package/dist/datasource/skills/gdrive/connector.d.ts +0 -30
  71. package/dist/datasource/skills/gdrive/index.d.ts +0 -3
  72. package/dist/datasource/skills/gdrive/skill.d.ts +0 -24
package/README.md CHANGED
@@ -65,26 +65,62 @@ Different documents need different search strategies:
65
65
  | Legal documents, specifications | BM25 (keyword ranking) | Handles domain terminology well |
66
66
  | Mixed collections | Hybrid (vector + BM25) | Combines precision and recall |
67
67
 
68
- AutoRAG supports **pluggable retrieval methods**. It ships with lexical **BM25** and semantic **MinSync** methods wired through the `RetrievalMethodRegistry`, and the architecture is ready for additional vector and hybrid backends. The librarian invokes retrieval tools, reads the underlying documents directly through `bash`, and curates one unified result set after `ResultMerger` score normalization and deduplication.
68
+ AutoRAG supports **pluggable retrieval methods**. Local lexical BM25, semantic vector, and hybrid retrieval all go through **MinSync** over one shared CDC chunk lifecycle, wired through the `RetrievalMethodRegistry`. The librarian invokes retrieval tools, reads the underlying documents directly through `bash`, and curates one unified result set after `ResultMerger` score normalization and deduplication. External datasources keep their own archive/index lifecycle.
69
69
 
70
- BM25 and MinSync are **enabled by default** — no explicit configuration is needed for standard lexical + semantic retrieval. Both can be disabled by setting `"bm25": false` or `"minSync": false` in the config file. MinSync uses a pre-installed binary (`autoInstall: false`); configure `minSync.embedder` via `autorag init --embedder-*` flags for remote embedding endpoints. AutoRAG never forces TEI or any external embedding service.
70
+ BM25, vector, and hybrid are **enabled by default** whenever MinSync is enabled. Disable local indexing with `"minSync": false`, or disable only lexical search with `"bm25": false`. MinSync auto-installs a verified release into `<workspace>/.autorag/bin` on first use (`autoInstall: true`); set `"autoInstall": false` only when managing the binary yourself. Configure `minSync.embedder` via `autorag init --embedder-*` flags for remote embedding endpoints, and set `minSync.maxChunkSize` (or `--minsync-max-chunk-size`) when a local embedder has a smaller context window. AutoRAG never forces TEI or any external embedding service.
71
+
72
+ See [docs/minsync-setup.md](docs/minsync-setup.md) for automatic installation,
73
+ managed binary paths, and the local EmbeddingGemma QA flow.
71
74
 
72
75
  ### Real directory access
73
76
 
74
- AutoRAG reads configured source directories directly through its built-in `bash` tool. Retrieval tools can supply candidate paths, but the same agent opens the source material before curating. Answers are returned as a structured `SearchDocumentsResponse`; results carry their real source (file path or datasource id) in the internal mapping for feedback and curation. BM25 and MinSync index parsed markdown mirrors under `.autorag`.
77
+ AutoRAG reads configured source directories directly through its built-in `bash` tool. Retrieval tools can supply candidate paths, but the same agent opens the source material before curating. Answers are returned as a structured `SearchDocumentsResponse`; results carry their real source (file path or datasource id) in the internal mapping for feedback and curation. MinSync indexes parsed markdown mirrors under `.autorag` for BM25, vector, and hybrid retrieval.
78
+
79
+ ### Thin PDF extraction retry
80
+
81
+ The default PDF parser performs a cheap quality check for multi-page PDFs.
82
+ When local markdown is unusually sparse (fewer than 800 characters or fewer
83
+ than 40 characters per detected page, for at least three pages), it retries
84
+ through OpenDataLoader's `docling-fast` hybrid backend with `hybridMode:
85
+ "auto"` and a 30-second timeout. Dense PDFs are not retried, and hybrid is
86
+ never used for single-page PDFs or as the first path for images.
87
+
88
+ The gate is parser-owned and can be tuned through trusted programmatic
89
+ `parserOptions`:
90
+
91
+ ```typescript
92
+ new AutoRAGAgent({
93
+ searchPaths: ["/path/to/documents"],
94
+ parserOptions: {
95
+ thinExtract: {
96
+ minPages: 3,
97
+ minChars: 800,
98
+ minCharsPerPage: 40,
99
+ timeoutMs: 30_000,
100
+ hybrid: "docling-fast",
101
+ hybridMode: "auto",
102
+ },
103
+ },
104
+ });
105
+ ```
106
+
107
+ If the hybrid sidecar is missing, times out, or fails, AutoRAG keeps the local
108
+ markdown and emits `pdf-extract-thin` plus `pdf-hybrid-unavailable`
109
+ diagnostics; refresh remains successful.
110
+
111
+ ### Default Jikji discovery and indexing
75
112
 
76
- ### Optional Jikji discovery and indexing
113
+ AutoRAG uses [Jikji](https://github.com/NomaDamas/jikji) by default as a local CLI-backed **find-first discovery and indexing** layer. Jikji is not registered as a retrieval backend: it supplies bounded discovery answer packs while the librarian still reads original files directly.
77
114
 
78
- AutoRAG can opt into [Jikji](https://github.com/NomaDamas/jikji) as a local CLI-backed **find-first discovery and indexing** layer. Jikji is optional: AutoRAG does not vendor it, install it, or register it as a retrieval backend when enabled.
115
+ The default agent calls `jikji find ROOT "query" --json` via the `jikji_find` tool. The tool parses and validates the upstream answer pack and exposes its `handoff_action`, `tool_call_policy`, and `agent_should_not_rerank` to the librarian. Direct file reading remains available for source verification. `prepare`/`refresh` remain for indexing only and do not answer queries directly. If the binary or Rust toolchain is unavailable, Jikji reports a diagnostic and the normal filesystem/retrieval paths continue.
79
116
 
80
- When Jikji is configured, AutoRAG calls `jikji find ROOT "query" --json` via the `jikji_find` tool. The tool parses and validates the upstream answer pack and exposes its `handoff_action`, `tool_call_policy`, and `agent_should_not_rerank` to the librarian. Direct file reading remains available for source verification. `prepare`/`refresh` remain for indexing only and do not answer queries directly.
117
+ New `autorag init` configs include `"jikji": {}`. To opt out, set `"jikji": false` in `config.json`; programmatic callers can pass `jikji: false`.
81
118
 
82
119
  Programmatic use:
83
120
 
84
121
  ```typescript
85
122
  const agent = new AutoRAGAgent({
86
123
  searchPaths: ["/path/to/documents"],
87
- jikji: { binaryPath: "jikji" },
88
124
  });
89
125
  await agent.prepareJikji();
90
126
  ```
@@ -118,7 +154,7 @@ searchable:
118
154
  If `dupey` is not installed or fails, refresh continues without exclusion and
119
155
  reports no destructive action; install it with `cargo install dupey`.
120
156
 
121
- The same `.autorag/jikji.json` shape configures Jikji when present:
157
+ The same configuration shape customizes Jikji when needed:
122
158
 
123
159
  ```json
124
160
  {
@@ -153,7 +189,7 @@ channel or group chat as its own datasource.
153
189
 
154
190
  Security defaults are intentionally strict:
155
191
 
156
- - datasource access is default-deny unless trusted server/API configuration supplies `datasourceAccess.allowedTags` and `datasourceAccess.allowedScopes`;
192
+ - datasource access is default-deny unless trusted server/API configuration supplies `datasourceAccess.allowedTags`; `allowedScopes` applies only to datasource methods that advertise the `scoped` capability;
157
193
  - model/tool arguments never grant datasource tags or scopes;
158
194
  - `search_datasource_documents` accepts only `{ query, topK?, scope? }`, and `scope` can only narrow trusted access.
159
195
 
@@ -171,6 +207,7 @@ Security defaults are intentionally strict:
171
207
  | Cloud drives | `cloud-drive` | **[`rclone`](https://rclone.org) CLI** | Incremental Google Drive Tier-1; OneDrive/network remotes; iCloud experimental |
172
208
  | Gmail / IMAP | `gmail` | Gmail REST v1, or **[`himalaya`](https://pimalaya.org) CLI** (`backend: "himalaya"`) | the himalaya backend indexes any IMAP/Maildir account it has configured — no OAuth plumbing |
173
209
  | Local mail exports | `mail-export` | filesystem (`.mbox` / `.eml`) | classic `From_` splitting, mailparser-based; count-only warnings |
210
+ | Mail archives | `mailcrawl` | external [`mailcrawl`](https://github.com/NomaDamas/mailcrawl) CLI | local email sync plus BM25, semantic, and hybrid retrieval |
174
211
  | Obsidian vault | `obsidian` | external [`qmd`](https://github.com/tobi/qmd) CLI | incremental `qmd update`, BM25 `qmd search`, semantic `qmd vsearch`; vault path via `connector.vaultPath` |
175
212
  | RSS / news | `rss` | HTTP feed polling | RSS 2.0 + Atom, feed/category hierarchy, 24h dedupe window |
176
213
 
@@ -187,14 +224,15 @@ Configure them in `config.json` (CLI) or pass `datasourceSkills` programmaticall
187
224
  "notion": { "connector": { "binaryPath": "notcrawl", "configPath": "/path/to/notcrawl.yaml" } },
188
225
  "github": { "connector": { "repos": ["owner/repo"] } },
189
226
  "gmail": { "connector": { "backend": "himalaya", "account": "gmail", "folder": "INBOX" } },
227
+ "mailcrawl": { "instanceId": "personal", "connector": { "account": "personal", "mailbox": "INBOX", "binaryPath": "mailcrawl" } },
190
228
  "personal-google-drive": { "type": "cloud-drive", "instanceId": "personal", "connector": { "provider": "google-drive", "remote": "personal-gdrive:", "include": ["**/*.md"] } },
191
229
  "company-onedrive": { "type": "cloud-drive", "instanceId": "work", "connector": { "provider": "onedrive", "remote": "company-onedrive:Documents" } },
192
230
  "obsidian": { "connector": { "vaultPath": "/path/to/vault" } },
193
231
  "rss": { "connector": { "feeds": [{ "url": "https://example.com/feed.xml" }] } }
194
232
  },
195
233
  "datasourceAccess": {
196
- "allowedTags": ["whatsapp", "telegram", "slack", "notion", "github", "gmail", "cloud-drive", "obsidian", "rss"],
197
- "allowedScopes": ["/whatsapp/**", "/telegram/**", "/slack/**", "/notion/**", "/github/**", "/gmail/**", "/personal-google-drive/**", "/company-onedrive/**", "/obsidian/**", "/rss/**"]
234
+ "allowedTags": ["whatsapp", "telegram", "slack", "notion", "github", "gmail", "mailcrawl", "cloud-drive", "obsidian", "rss"],
235
+ "allowedScopes": ["/whatsapp/**", "/telegram/**", "/slack/**", "/notion/**", "/github/**", "/gmail/**", "/mailcrawl/**", "/personal-google-drive/**", "/company-onedrive/**", "/obsidian/**", "/rss/**"]
198
236
  }
199
237
  }
200
238
  ```
@@ -207,6 +245,15 @@ Install slacrawl with `brew install openclaw/tap/slacrawl`. AutoRAG invokes `sla
207
245
 
208
246
  Install notcrawl with `brew install openclaw/tap/notcrawl`. AutoRAG invokes `notcrawl sync` during datasource refresh and `notcrawl search --json` during retrieval. Optional trusted connector fields are `binaryPath` and `configPath`. Notion credentials and workspace definitions remain in notcrawl's own configuration rather than AutoRAG.
209
247
 
248
+ Install and configure [`mailcrawl`](https://github.com/NomaDamas/mailcrawl)
249
+ `@nomadamas/mailcrawl@0.1.4` or newer separately. AutoRAG invokes
250
+ `mailcrawl sync` followed by `mailcrawl index` during datasource refresh, then
251
+ calls `mailcrawl search` in BM25, semantic, or hybrid mode. The archive remains
252
+ in mailcrawl's native store unless the operator explicitly sets
253
+ `connector.dataDir`; Himalaya credentials and provider configuration remain
254
+ owned by mailcrawl. 0.1.3 and earlier fail a repeated
255
+ `index` after a no-op sync.
256
+
210
257
  Install and authenticate rclone separately (`brew install rclone && rclone
211
258
  config` on macOS), then configure the provider-neutral `cloud-drive` skill.
212
259
  `cloud-drive` is a reusable `type`: each datasource config key is a connection
@@ -240,7 +287,6 @@ const agent = new AutoRAGAgent({
240
287
  datasourceSkills: [kakao],
241
288
  datasourceAccess: {
242
289
  allowedTags: ["kakaotalk"],
243
- allowedScopes: ["/kakao/personal/**"],
244
290
  },
245
291
  });
246
292
 
@@ -271,7 +317,6 @@ const agent = new AutoRAGAgent({
271
317
  datasourceSkills: [discord],
272
318
  datasourceAccess: {
273
319
  allowedTags: ["discord"],
274
- allowedScopes: ["/discord/community/**"],
275
320
  },
276
321
  });
277
322
  ```
@@ -297,7 +342,7 @@ Or through the trusted config factory:
297
342
  Two defaults are deliberate and worth keeping:
298
343
 
299
344
  - **`defaultMode: "hybrid"`** — discrawl's FTS index strips newlines without substituting a space, welding words across line breaks into a single unsearchable token (measured at ~47% of post-newline words on a real archive). Semantic recall covers that gap. See [#1413](https://github.com/Marker-Inc-Korea/AutoRAG/issues/1413).
300
- - **`embeddingProvider: "ollama"` + `embeddingModel: "embeddinggemma"`** — semantic search requires an embedding provider (`ollama serve && ollama pull embeddinggemma`). For workspace-managed discrawl state, AutoRAG writes these values to `.autorag/datasources/discrawl/config.toml` while preserving unrelated discrawl settings. An explicit `connector.configPath` remains operator-owned and is never rewritten. EmbeddingGemma (Gemma 3 300M, 768-dim, 100+ languages) is the same model family katok uses for KakaoTalk, so all CLI-backed datasources share one local embedder. Do **not** use `nomic-embed-text`: it is English-only and collapses non-English text into one narrow similarity band, silently degrading semantic search to noise. AutoRAG emits a diagnostic when an English-only model is configured. See [#1414](https://github.com/Marker-Inc-Korea/AutoRAG/issues/1414).
345
+ - **`embeddingProvider: "ollama"` + `embeddingModel: "embeddinggemma"`** — semantic search requires an embedding provider (`ollama serve && ollama pull embeddinggemma`). Configure these values in discrawl's own config; AutoRAG uses discrawl's native store unless an explicit `connector.configPath` is supplied. EmbeddingGemma (Gemma 3 300M, 768-dim, 100+ languages) is the same model family katok uses for KakaoTalk, so all CLI-backed datasources can share one local embedder. Do **not** use `nomic-embed-text`: it is English-only and collapses non-English text into one narrow similarity band, silently degrading semantic search to noise. AutoRAG emits a diagnostic when an English-only model is configured. See [#1414](https://github.com/Marker-Inc-Korea/AutoRAG/issues/1414).
301
346
 
302
347
  A datasource skill should provide polling/cron metadata for routine indexing, source descriptions for the agent prompt, slash-hierarchical opaque source paths such as `/kakao/personal/chunks/<chunk-id>`, and permission tags that match your server-side access policy.
303
348
 
@@ -349,6 +394,30 @@ Config path precedence is `--config` > `AUTORAG_CONFIG` > `~/.autorag/config.jso
349
394
 
350
395
  `autorag health` checks model/provider auth before a search — it resolves the model, verifies credential presence, and optionally probes one completion call. Use it to diagnose model, provider, auth, or timeout failures. `autorag status` remains the model-free index-health command (corpus freshness and BM25/MinSync readiness). When `autorag search` fails for a model/provider reason, the error output includes a hint pointing to `autorag health`.
351
396
 
397
+ `autorag ui` opens a loopback-only page (`127.0.0.1`) to connect local folders and datasource skills without editing JSON. It writes the same trusted `datasources` / `datasourceAccess` fields as a hand-edited config, stores env-var *names* rather than secrets, and refuses non-loopback binds. Use `--no-open` to print the URL without launching a browser.
398
+
399
+ For a deliberately deployed UI, opt in explicitly in `config.json`. Keep the
400
+ session token in the environment, set the public URL used by the browser, and
401
+ allow only the frontend origins that should make credentialed API requests:
402
+
403
+ ```json
404
+ {
405
+ "ui": {
406
+ "host": "0.0.0.0",
407
+ "port": 8787,
408
+ "allowRemote": true,
409
+ "publicOrigin": "https://autorag.example.com",
410
+ "corsOrigins": ["https://autorag.example.com"],
411
+ "tokenEnv": "AUTORAG_UI_TOKEN"
412
+ }
413
+ }
414
+ ```
415
+
416
+ Start it with `AUTORAG_UI_TOKEN` set to a random value of at least 16
417
+ characters. Local use remains the safe default: omit `ui` (or leave
418
+ `allowRemote` false) and AutoRAG binds to loopback, including a working
419
+ `localhost` URL on systems that resolve it to IPv6.
420
+
352
421
  ## Installation
353
422
 
354
423
  Published as `@autorag/librarian` (dist bundled with Bun, runtime Node ≥ 24 or Bun):
@@ -360,9 +429,45 @@ bun install -g @autorag/librarian # autorag CLI
360
429
  bun add github:NomaDamas/AutoRAG-2.0
361
430
  ```
362
431
 
432
+ PDF parsing requires **Java 11 or newer** because the bundled
433
+ `@opendataloader/pdf` runtime is compiled for Java 11. This applies to
434
+ Windows, macOS, and Linux. Verify the runtime that will be selected from
435
+ `PATH` before indexing PDFs:
436
+
437
+ ```bash
438
+ java -version
439
+ ```
440
+
441
+ On Windows, ensure a Java 11+ installation appears before older Java
442
+ installations in `PATH` (or set `JAVA_HOME` to the Java 11+ installation and
443
+ start a new shell). Java 8 is not supported by the PDF parser.
444
+
363
445
  Git-based installs build `dist/` via the `prepare` script and require Bun on the installing machine.
364
446
  External tool binaries auto-install on first use into `<workspace>/.autorag/bin`: **MinSync** downloads a verified GitHub release asset (on by default; `minSync.autoInstall: false` to opt out), and **Jikji** compiles the [`jikji-cli`](https://crates.io/crates/jikji-cli) crate via cargo (requires the [Rust toolchain](https://rustup.rs); `jikji.autoInstall: false` to opt out). New `autorag init` configs enable Jikji find-first discovery by default. KakaoTalk (`katok`) and Discord (`discrawl`) stay manual, optional installs. All of them degrade gracefully when missing — core BM25 search works without any of them.
365
447
 
448
+ ### Experimental TUI (beta)
449
+
450
+ The latest TUI work is currently available on the `feat/experimental-tui`
451
+ branch. To use this beta version from source:
452
+
453
+ ```bash
454
+ git clone --branch feat/experimental-tui https://github.com/Marker-Inc-Korea/AutoRAG.git
455
+ cd AutoRAG
456
+ bun install
457
+ bun run build
458
+
459
+ # Configure your document roots and model once:
460
+ node dist/cli/index.js init --search-paths /path/to/documents
461
+
462
+ # Start the beta TUI:
463
+ node dist/cli/index.js tui
464
+ ```
465
+
466
+ Inside the TUI, use `/resume` to browse saved sessions. Selecting a session
467
+ replaces the current view with that session instead of mixing the two
468
+ conversation histories. This branch is experimental and may change before the
469
+ feature is included in a published release.
470
+
366
471
  ## Quick Start
367
472
 
368
473
  ```typescript
@@ -5,10 +5,10 @@ import type { DatasourceIndexResult, DatasourceSkill } from "../datasource/types
5
5
  import { type DupeyCliOptions } from "../dupey/index.js";
6
6
  import { type JikjiFailureReason, type JikjiOptions } from "../jikji/index.js";
7
7
  import type { ResultFeedback } from "../memory/memory.js";
8
- import { type MinSyncSyncResult, type MinSyncVectorMethodOptions } from "../minsync/index.js";
8
+ import { type MinSyncBM25MethodOptions, type MinSyncSyncResult, type MinSyncVectorMethodOptions } from "../minsync/index.js";
9
9
  import { type ParsedMirrorSyncResult } from "../mirror/sync.js";
10
10
  import type { DefaultParserRegistryOptions } from "../parser/index.js";
11
- import { type BM25MethodOptions, type BM25SyncResult } from "../retrieval/methods/bm25.js";
11
+ import { type BM25SyncResult } from "../retrieval/methods/bm25.js";
12
12
  import { RetrievalMethodRegistry } from "../retrieval/registry.js";
13
13
  import type { CuratedResult, RetrievalDiagnostic, RetrievalOptions, RetrievalResult } from "../retrieval/types.js";
14
14
  import { type ScanDuplicateDocumentsDetails } from "./dupey-tool.js";
@@ -30,7 +30,8 @@ export interface AutoRAGMinSyncRefreshResult {
30
30
  readonly synced: number;
31
31
  readonly reason?: string;
32
32
  }
33
- export interface AutoRAGRefreshResult extends ParsedMirrorSyncResult {
33
+ export interface AutoRAGRefreshResult extends Omit<ParsedMirrorSyncResult, "diagnostics"> {
34
+ readonly diagnostics: readonly SearchDocumentDiagnostic[];
34
35
  readonly bm25?: BM25SyncResult;
35
36
  readonly minsync?: AutoRAGMinSyncRefreshResult;
36
37
  readonly datasources?: readonly DatasourceIndexResult[];
@@ -77,14 +78,20 @@ export interface AutoRAGAgentOptions {
77
78
  workspacePath?: string;
78
79
  tools?: AgentTool[];
79
80
  minSync?: Omit<MinSyncVectorMethodOptions, "root"> | false;
80
- bm25?: Omit<BM25MethodOptions, "root"> | false;
81
- jikji?: JikjiOptions;
81
+ bm25?: Omit<MinSyncBM25MethodOptions, "root"> | false;
82
+ jikji?: JikjiOptions | false;
82
83
  autoRefresh?: AutoRefreshOptions;
83
84
  parserOptions?: DefaultParserRegistryOptions;
84
85
  dupey?: DupeyCliOptions | false;
85
86
  excludeExactDuplicates?: boolean;
86
87
  datasourceSkills?: readonly DatasourceSkill[];
87
88
  datasourceAccess?: DatasourceAccessContextOptions;
89
+ /** Non-fatal diagnostics from config/agent construction (e.g. skipped unknown datasources). */
90
+ startupDiagnostics?: readonly SearchDocumentDiagnostic[];
91
+ /** Maximum time a model/tool search may run before it is aborted. */
92
+ searchTimeoutMs?: number;
93
+ /** Maximum number of retrieval/tool executions allowed in one search. */
94
+ maxSearchToolCalls?: number;
88
95
  }
89
96
  export interface AutoRAGSearchSession {
90
97
  readonly agent: Agent;
@@ -134,12 +141,16 @@ export declare class AutoRAGAgent {
134
141
  private readonly jikjiClient;
135
142
  private readonly datasourceSkills;
136
143
  private readonly datasourceAccessOptions;
144
+ private readonly startupDiagnostics;
137
145
  private readonly datasourceAgentSkills;
138
146
  private readonly parserOptions;
139
147
  private readonly dupeyOptions;
140
148
  private readonly excludeExactDuplicates;
141
149
  private readonly baseSystemPromptConfig;
142
150
  private readonly droppedCallerToolNames;
151
+ private readonly searchTimeoutMs;
152
+ private readonly maxSearchToolCalls;
153
+ private searchToolCallCount;
143
154
  constructor(options: AutoRAGAgentOptions);
144
155
  scanDuplicateDocuments(): Promise<ScanDuplicateDocumentsDetails>;
145
156
  private withMemoryContext;
@@ -182,7 +193,8 @@ export declare class AutoRAGAgent {
182
193
  private indexDatasources;
183
194
  /** Path-opaque component diagnostics (e.g. BM25 readiness) for the search response. */
184
195
  private collectComponentDiagnostics;
185
- buildSearchPrompt(query: string, options: RetrievalOptions): string;
196
+ private prefetchInitialRetrievalContext;
197
+ buildSearchPrompt(query: string, options: RetrievalOptions, initialRetrievalContext?: string): string;
186
198
  refresh(force?: boolean, opts?: AutoRAGRefreshOptions): Promise<AutoRAGRefreshResult>;
187
199
  /**
188
200
  * Path-opaque snapshot of corpus freshness and the last refresh outcome. Runs
@@ -209,7 +221,7 @@ export declare class AutoRAGAgent {
209
221
  */
210
222
  private scanMirrorStaleness;
211
223
  private exactDuplicateExclusions;
212
- syncBM25(): Promise<BM25SyncResult | undefined>;
224
+ syncBM25(minsync?: MinSyncSyncResult): Promise<BM25SyncResult | undefined>;
213
225
  syncMinSync(): Promise<MinSyncSyncResult | undefined>;
214
226
  prepareJikji(): Promise<readonly AutoRAGJikjiPrepareResult[] | undefined>;
215
227
  private executeJikjiPrepare;
@@ -17,7 +17,9 @@ export interface BashToolOptions {
17
17
  export interface BashToolDetails {
18
18
  readonly method: "bash";
19
19
  readonly command: string;
20
+ readonly aborted: boolean;
20
21
  readonly exitCode: number | undefined;
22
+ readonly terminationFailed: boolean;
21
23
  readonly timedOut: boolean;
22
24
  readonly truncated: boolean;
23
25
  }
@@ -1,7 +1,8 @@
1
1
  import type { AgentTool } from "@earendil-works/pi-agent-core";
2
2
  import { Type } from "typebox";
3
- import type { BM25Method, BM25Status } from "../retrieval/methods/bm25.js";
4
- export declare const SEARCH_BM25_DOCUMENTS_TOOL_NAME = "search_bm25_documents";
3
+ import type { BM25Status } from "../retrieval/methods/bm25.js";
4
+ import type { RetrievalResult } from "../retrieval/types.js";
5
+ export declare const SEARCH_BM25_DOCUMENTS_TOOL_NAME = "lexical_search_local_docs";
5
6
  declare const searchBM25Schema: Type.TObject<{
6
7
  query: Type.TString;
7
8
  topK: Type.TOptional<Type.TInteger>;
@@ -14,5 +15,12 @@ export interface SearchBM25DocumentsDetails {
14
15
  readonly readiness: BM25Status["readiness"];
15
16
  readonly engine: BM25Status["engine"];
16
17
  }
17
- export declare function createSearchBM25DocumentsTool(getMethod: () => BM25Method | undefined, resolveScope?: (scope: string | undefined) => string | undefined): AgentTool<typeof searchBM25Schema, SearchBM25DocumentsDetails>;
18
+ export interface BM25SearchMethod {
19
+ getStatus(): BM25Status;
20
+ retrieve(query: string, options: {
21
+ topK?: number;
22
+ scope?: string;
23
+ }): Promise<RetrievalResult[]>;
24
+ }
25
+ export declare function createSearchBM25DocumentsTool(getMethod: () => BM25SearchMethod | undefined, resolveScope?: (scope: string | undefined) => string | undefined): AgentTool<typeof searchBM25Schema, SearchBM25DocumentsDetails>;
18
26
  export {};
@@ -9,7 +9,7 @@ export type SearchDocumentDiagnosticSeverity = "info" | "warning" | "error";
9
9
  * (#21/#22) does not require another source-breaking type change; codes not yet
10
10
  * emitted are still valid members.
11
11
  */
12
- export type SearchDocumentDiagnosticCode = "empty-query" | "unknown-warning" | "caller-tool-dropped" | "bm25-unavailable" | "bm25-degraded-fallback" | "minsync-unavailable" | "parser-skipped" | "parser-failed" | "duplicate-excluded" | "unsupported-file" | "stale-index" | "deleted-mirror" | "retrieval-method-failed" | "jikji-unavailable" | "jikji-prepare-failed" | "jikji-find-failed" | "refresh-failed" | "watch-failed" | "watch-limited";
12
+ export type SearchDocumentDiagnosticCode = "empty-query" | "unknown-warning" | "caller-tool-dropped" | "bm25-unavailable" | "bm25-degraded-fallback" | "minsync-unavailable" | "parser-skipped" | "parser-failed" | "pdf-java-version" | "duplicate-excluded" | "unsupported-file" | "stale-index" | "deleted-mirror" | "pdf-extract-thin" | "pdf-hybrid-unavailable" | "retrieval-method-failed" | "jikji-unavailable" | "jikji-prepare-failed" | "jikji-find-failed" | "refresh-failed" | "watch-failed" | "watch-limited" | "unknown-datasource-skill";
13
13
  export interface SearchDocumentDiagnostic {
14
14
  readonly code: SearchDocumentDiagnosticCode;
15
15
  readonly severity: SearchDocumentDiagnosticSeverity;
@@ -51,7 +51,7 @@ type ReadonlySearchSessions = ReadonlyMap<string, {
51
51
  query: string;
52
52
  registry: ReadonlyMap<number, CuratedResult>;
53
53
  }>;
54
- export declare function createEmptySearchDocumentsResponse(sessionId: string, query: string, sessions: SearchSessions): SearchDocumentsResponse;
54
+ export declare function createEmptySearchDocumentsResponse(sessionId: string, query: string, sessions: SearchSessions, diagnostics?: readonly SearchDocumentDiagnostic[]): SearchDocumentsResponse;
55
55
  export declare function recordStructuredResultsSession(sessionId: string, query: string, details: AutoRAGResultsDetails, sessions: SearchSessions, memory: RetrievalMemory, componentDiagnostics?: readonly SearchDocumentDiagnostic[]): SearchDocumentsResponse;
56
56
  export declare function recordNumberedFeedback(sessions: ReadonlySearchSessions, memory: RetrievalMemory, sessionId: string, usefulNumbers: readonly number[], notUsefulNumbers: readonly number[]): void;
57
57
  export {};
@@ -1,14 +1,14 @@
1
1
  import type { AgentTool } from "@earendil-works/pi-agent-core";
2
2
  import { Type } from "typebox";
3
3
  import type { MinSyncVectorMethod } from "../minsync/method.js";
4
- export declare const SEARCH_MINSYNC_DOCUMENTS_TOOL_NAME = "search_minsync_documents";
4
+ export declare const SEARCH_MINSYNC_DOCUMENTS_TOOL_NAME = "semantic_search_local_docs";
5
5
  declare const searchMinSyncSchema: Type.TObject<{
6
6
  query: Type.TString;
7
7
  topK: Type.TOptional<Type.TInteger>;
8
8
  scope: Type.TOptional<Type.TString>;
9
9
  }>;
10
10
  export interface SearchMinSyncDocumentsDetails {
11
- readonly method: "search_minsync_documents";
11
+ readonly method: "semantic_search_local_docs";
12
12
  readonly resultCount: number;
13
13
  readonly sources: readonly string[];
14
14
  readonly available: boolean;
@@ -1,8 +1,8 @@
1
1
  import type { CommandContext } from "./types.js";
2
2
  /**
3
- * Run the `autorag index` command. `reset` removes the parsed mirror, BM25,
4
- * and MinSync index directories under `.autorag` (preserving `bin`,
5
- * `datasources`, and the memory file). `rebuild` resets then re-runs a forced
3
+ * Run the `autorag index` command. `reset` removes the parsed mirror
4
+ * MinSync, and leftover legacy BM25 index directories under `.autorag`
5
+ * (preserving `bin`, `datasources`, and the memory file). `rebuild` resets then re-runs a forced
6
6
  * refresh. Returns 0 on success, 2 for usage/decline errors, 1 for runtime
7
7
  * errors including path-escape guard violations.
8
8
  */
@@ -0,0 +1,36 @@
1
+ import type { AgentEvent } from "@earendil-works/pi-agent-core";
2
+ import { AutoRAGAgent, type AutoRAGAgentOptions } from "../../agent/agent.js";
3
+ import { type CliConfig, type ResolvedAgentModel } from "../config.js";
4
+ import { type TuiSessionRecord, type TuiSessionStore } from "../tui-session-store.js";
5
+ import type { CommandContext } from "./types.js";
6
+ export { parseSlashCommand } from "../tui-commands.js";
7
+ export interface TuiDriver {
8
+ submissions: string[];
9
+ rendered: string[];
10
+ started: boolean;
11
+ stopped: boolean;
12
+ onSubmit?: (text: string) => void | Promise<void>;
13
+ onExit?: () => void;
14
+ onEvent?: (event: AgentEvent) => void;
15
+ onInput?: (data: string) => void;
16
+ }
17
+ export interface TuiPresenter {
18
+ handle(event: AgentEvent): void;
19
+ lines(): readonly string[];
20
+ working(): boolean;
21
+ setWorking(active: boolean): void;
22
+ beginRun(): void;
23
+ interrupt(): void;
24
+ status(): string;
25
+ reset(): void;
26
+ }
27
+ type TuiAgent = Pick<AutoRAGAgent, "searchDocuments"> & Partial<Pick<AutoRAGAgent, "subscribe" | "abort">>;
28
+ export interface TuiDeps {
29
+ agentFactory?: (opts?: AutoRAGAgentOptions) => TuiAgent;
30
+ modelResolver?: (config: CliConfig) => ResolvedAgentModel;
31
+ tuiFactory?: (ctx: CommandContext) => TuiDriver;
32
+ sessionStore?: TuiSessionStore;
33
+ }
34
+ export declare function createTuiPresenter(): TuiPresenter;
35
+ export declare function renderTuiSessionView(session: TuiSessionRecord | undefined, input: string): string;
36
+ export declare function runTui(ctx: CommandContext, deps?: TuiDeps): Promise<number>;
@@ -0,0 +1,13 @@
1
+ import { startUiServer, type UiServer } from "../../ui/server.js";
2
+ import type { CommandContext } from "./types.js";
3
+ export interface UiCommandDeps {
4
+ readonly startServer?: typeof startUiServer;
5
+ readonly openBrowser?: (url: string) => Promise<void>;
6
+ readonly waitUntilStopped?: (server: UiServer) => Promise<void>;
7
+ readonly createToken?: () => string;
8
+ }
9
+ /**
10
+ * `autorag ui` — local loopback dashboard for folders and datasource connections.
11
+ */
12
+ export declare function runUi(ctx: CommandContext, deps?: UiCommandDeps): Promise<number>;
13
+ export declare function openBrowser(url: string): Promise<void>;
@@ -4,7 +4,6 @@ import { type LoadLocalAutoRAGModelOptions } from "../agent/local-model.js";
4
4
  import type { DatasourceAccessContextOptions } from "../datasource/access-context.js";
5
5
  import { type DatasourcesConfig } from "../datasource/skills/factory.js";
6
6
  import type { EnsureMinSyncBinaryOptions, MinSyncEmbedderConfig } from "../minsync/index.js";
7
- import type { BM25Engine, BM25FallbackMode } from "../retrieval/methods/bm25.js";
8
7
  export declare const DEFAULT_CONFIG_FILENAME = "config.json";
9
8
  export declare const LEGACY_CONFIG_FILENAME = "autorag.config.json";
10
9
  export { AUTORAG_HOME_ENV, resolveAutoRAGHome } from "../config/home.js";
@@ -17,14 +16,10 @@ export declare class ConfigError extends Error {
17
16
  */
18
17
  export interface Bm25MethodConfig {
19
18
  enabled?: boolean;
20
- indexPath?: string;
21
- fallback?: BM25FallbackMode;
22
- forceEngine?: Exclude<BM25Engine, "none">;
23
- importBinding?: () => Promise<typeof import("@pngwasi/node-tantivy-binding")>;
24
19
  }
25
20
  /**
26
21
  * Typed MinSync method config persisted in `config.json`. Missing `enabled`
27
- * means enabled (true); `autoInstall` defaults to false. `embedder` carries
22
+ * means enabled (true); `autoInstall` defaults to true. `embedder` carries
28
23
  * the MinSync vector embedder settings validated by {@link normalizeEmbedder}.
29
24
  */
30
25
  export interface MinSyncMethodConfig {
@@ -32,6 +27,7 @@ export interface MinSyncMethodConfig {
32
27
  autoInstall?: boolean;
33
28
  binaryPath?: string;
34
29
  workspacePath?: string;
30
+ maxChunkSize?: number;
35
31
  installer?: Omit<EnsureMinSyncBinaryOptions, "root">;
36
32
  embedder?: MinSyncEmbedderConfig;
37
33
  }
@@ -45,6 +41,14 @@ export interface NormalizedIndexingConfig {
45
41
  bm25: Bm25MethodConfig;
46
42
  minSync: MinSyncMethodConfig;
47
43
  }
44
+ export interface UiConfig {
45
+ host?: string;
46
+ port?: number;
47
+ allowRemote?: boolean;
48
+ publicOrigin?: string;
49
+ corsOrigins?: string[];
50
+ tokenEnv?: string;
51
+ }
48
52
  export interface AgentModelConfig {
49
53
  /** Provider identity used for auth lookup and Model.provider (e.g. openrouter, fireworks, ollama). */
50
54
  provider: string;
@@ -79,7 +83,7 @@ export interface CliConfig {
79
83
  model?: AgentModelConfig;
80
84
  minSync?: MinSyncMethodConfig;
81
85
  bm25?: Bm25MethodConfig;
82
- jikji?: Record<string, unknown>;
86
+ jikji?: Record<string, unknown> | false;
83
87
  parserOptions?: Record<string, unknown>;
84
88
  dupey?: {
85
89
  enabled?: boolean;
@@ -91,6 +95,8 @@ export interface CliConfig {
91
95
  datasources?: DatasourcesConfig;
92
96
  /** Trusted datasource allow-tags/allow-scopes. Absent ⇒ default-deny. */
93
97
  datasourceAccess?: DatasourceAccessContextOptions;
98
+ /** Optional local/deployment settings for the datasource UI. */
99
+ ui?: UiConfig;
94
100
  }
95
101
  export interface ResolveConfigInput {
96
102
  flags: Record<string, string | boolean | undefined>;
@@ -115,7 +121,7 @@ export declare function normalizeEmbedder(raw: unknown, path: string): MinSyncEm
115
121
  /**
116
122
  * Normalize raw indexing method config into a fully-populated shape.
117
123
  *
118
- * - `undefined` / missing key => `{ enabled: true }` (minSync `autoInstall: false`)
124
+ * - `undefined` / missing key => `{ enabled: true, autoInstall: true }`
119
125
  * - `false` => `{ enabled: false }` (disabled marker)
120
126
  * - object merges with `enabled: true` default and is validated
121
127
  *
@@ -166,6 +172,9 @@ export interface ResolvedAgentModelDetailed {
166
172
  }
167
173
  export declare function resolveAgentModel(config: CliConfig, localOptions?: LoadLocalAutoRAGModelOptions): ResolvedAgentModel;
168
174
  export declare function resolveAgentModelDetailed(config: CliConfig, localOptions?: LoadLocalAutoRAGModelOptions): ResolvedAgentModelDetailed;
175
+ export declare function readRawConfigObject(path: string): Record<string, unknown>;
176
+ /** Atomically replace a config file, preserving the caller's JSON object. */
177
+ export declare function writeConfigObject(path: string, config: unknown): void;
169
178
  export declare function writeDefaultConfig(path: string, partial: Partial<CliConfig>, opts?: {
170
179
  force?: boolean;
171
180
  atomicCreate?: boolean;