@autorag/librarian 2.11.0 → 2.12.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 (60) hide show
  1. package/NOTICE +6 -0
  2. package/README.md +7 -4
  3. package/dist/agent/agent.d.ts +64 -1
  4. package/dist/agent/answer-citations.d.ts +34 -2
  5. package/dist/agent/answer-guidelines.d.ts +2 -2
  6. package/dist/agent/ask-user.d.ts +8 -0
  7. package/dist/agent/automation-tool.d.ts +45 -0
  8. package/dist/agent/citation-links.d.ts +23 -0
  9. package/dist/agent/citation-numbers.d.ts +68 -0
  10. package/dist/agent/citation-relevance.d.ts +37 -0
  11. package/dist/agent/conversation-queries.d.ts +31 -0
  12. package/dist/agent/convert-tool.d.ts +28 -0
  13. package/dist/agent/evidence-persistence.d.ts +17 -11
  14. package/dist/agent/index.d.ts +1 -0
  15. package/dist/agent/intent-tracing.d.ts +33 -0
  16. package/dist/agent/permission-gate.d.ts +78 -0
  17. package/dist/agent/permission-judgment.d.ts +72 -0
  18. package/dist/agent/permission-paths.d.ts +23 -0
  19. package/dist/agent/query-routing.d.ts +14 -17
  20. package/dist/agent/search-documents.d.ts +1 -1
  21. package/dist/agent/self-config.d.ts +2 -0
  22. package/dist/agent/user-requests.d.ts +52 -0
  23. package/dist/automation/config.d.ts +48 -0
  24. package/dist/automation/daemon.d.ts +31 -0
  25. package/dist/automation/dispatch.d.ts +13 -0
  26. package/dist/automation/run-agent.d.ts +22 -0
  27. package/dist/automation/run.d.ts +32 -0
  28. package/dist/automation/service.d.ts +61 -0
  29. package/dist/cli/commands/automate.d.ts +2 -0
  30. package/dist/cli/config.d.ts +21 -0
  31. package/dist/cli/index.d.ts +1 -1
  32. package/dist/cli/index.js +8336 -4254
  33. package/dist/cli/open-target.d.ts +9 -0
  34. package/dist/cli/setup.d.ts +12 -0
  35. package/dist/convert/cli.d.ts +77 -0
  36. package/dist/convert/index.d.ts +4 -0
  37. package/dist/convert/installer.d.ts +84 -0
  38. package/dist/convert/matrix.d.ts +27 -0
  39. package/dist/convert/relate.d.ts +30 -0
  40. package/dist/core.js +32002 -28171
  41. package/dist/datasource/connector-timeouts.d.ts +6 -2
  42. package/dist/datasource/crawler-types.d.ts +1 -1
  43. package/dist/datasource/skills/lazykatok/types.d.ts +2 -2
  44. package/dist/datasource/skills/mailcrawl/types.d.ts +1 -1
  45. package/dist/dupey/cli.d.ts +18 -0
  46. package/dist/index.d.ts +1 -0
  47. package/dist/index.js +32047 -28192
  48. package/dist/mcp/index.js +32054 -28223
  49. package/dist/minsync/installer.d.ts +1 -1
  50. package/dist/profiles/agent-factory.d.ts +60 -0
  51. package/dist/profiles/automation-profiles.d.ts +25 -0
  52. package/dist/profiles/loop-guard.d.ts +23 -0
  53. package/dist/profiles/retrieval-tools.d.ts +24 -0
  54. package/dist/profiles/session-model.d.ts +69 -0
  55. package/dist/profiles.d.ts +13 -0
  56. package/dist/profiles.js +34739 -0
  57. package/dist/retrieval/rerank.d.ts +6 -0
  58. package/package.json +8 -2
  59. package/skills/autorag/SKILL.md +73 -2
  60. package/skills/autorag-setup/SKILL.md +8 -4
package/NOTICE CHANGED
@@ -24,6 +24,9 @@ License: MIT
24
24
  @modelcontextprotocol/server@2.3.1
25
25
  License: Apache-2.0
26
26
 
27
+ @parcel/watcher@2.6.0
28
+ License: MIT
29
+
27
30
  chardet@2.2.0
28
31
  License: MIT
29
32
 
@@ -51,6 +54,9 @@ License: MIT
51
54
  pdfjs-dist@6.4.299
52
55
  License: Apache-2.0
53
56
 
57
+ pi-ask-user@0.17.0
58
+ License: MIT
59
+
54
60
  pi-discord-remote@0.2.4
55
61
  License: MIT
56
62
 
package/README.md CHANGED
@@ -222,7 +222,7 @@ A fresh session — at launch and after `/new` (or `/reload`) — opens on AutoR
222
222
 
223
223
  Typing while a search runs works like steering one of Pi's own turns. **Enter** steers the running search: AutoRAG treats the text as a correction of a search that is going wrong, delivers it before the search's next model request (also between phases, where no turn is streaming), cuts in-flight retrieval short so the correction lands promptly, and always runs the verification phase so the answer reflects the correction. **Alt+Enter** queues a new question that runs after the current search answers. **Esc** stops the search instead of letting it continue into its next phase. Pi's registered `/` commands still run during a search; any other line starting with `/` (a path, for example) is a steer like any other text. A query typed after a search answers is a new search in the same session, as before.
224
224
 
225
- From the moment a question is submitted, a live progress widget sits above the editor: a spinner, the elapsed time, and one line per step the search is running (routing, splitting the question, each retrieval source with its hit count and time, ranking, the first answer, verification). A slow source shows its own running timer, a failing source shows its error text verbatim, and the widget disappears when the answer is final or **Esc** stops the search. While the model streams, Pi's own `Working` loader takes over and the widget keeps only the header and steps.
225
+ From the moment a question is submitted, a live progress widget sits above the editor: a spinner, the elapsed time, and one line per step the search is running (routing, splitting the question, each retrieval source with its hit count and time, ranking, the first answer, verification). A slow source shows its own running timer, a failing source shows its error text verbatim, and the widget disappears when the answer is final or **Esc** stops the search. While the model streams, Pi's own `Working` loader takes over and the widget keeps only the header and steps. Every tool call also carries a short model-written intent (the `i` argument): Pi's `Working` loader shows the newest one, and `autorag search` and the desktop app receive it as progress, so the model does not write separate progress notes before tool calls.
226
226
 
227
227
  Update notices are AutoRAG's, not Pi's: `autorag tui` suppresses Pi's "run `pi update`" banner (Pi is a bundled host, not a separate install) and instead checks the published `@autorag/librarian` release, showing a one-line notice in the session when a newer version exists. Set `AUTORAG_NO_UPDATE_CHECK=1` to skip the lookup; `AUTORAG_UPDATE_CHECK_URL` overrides the registry endpoint.
228
228
 
@@ -263,6 +263,7 @@ bun add @autorag/librarian
263
263
  - **Rust Toolchain (Optional):** Automatically compiles Jikji (`jikji-cli`) if installed.
264
264
  - **MinSync:** Automatically downloaded and installed into `<workspace>/.autorag/bin` on first run.
265
265
  - **Everything (Windows only, bundled):** The package ships the portable Everything 1.4.1.1032 and its ES 1.1.0.38 CLI (x64 and ARM64, SHA-256 pinned). On Windows, AutoRAG extracts them into `<workspace>/.autorag/everything/` and runs a private, user-level instance that indexes only your configured search roots: no administrator rights, no Everything service, no whole-drive scan, no HTTP/ETP server, and no change to any Everything you already run. Set `"everything": false` in the config to turn it off. macOS and Linux are not affected.
266
+ - **filee-cli (file conversion, automatic):** `autorag setup` and the TUI download the pinned filee-cli release (~85 MB, SHA-256 verified) into `<AUTORAG_HOME>/tools/filee-cli/<version>/`, so the agent can convert between 255 formats offline with `convert_files`. A `filee`/`filee-cli` already on `PATH` is used instead. Set `"filee": { "autoInstall": false }` to forbid the download or `"filee": { "enabled": false }` to remove the tools. Filee fetches its own engines (FFmpeg, Pandoc, LibreOffice, calibre, Ghostscript; hundreds of MB, only when a conversion needs one) on first use.
266
267
  - **FSearch (macOS/Linux only, separate install):** Install [`fsearch-cli`](https://github.com/NomaDamas/fsearch-mac) yourself (e.g. `brew install NomaDamas/fsearch-mac/fsearch-mac` (installs the `fsearch-cli` binary); GPL-2.0, spawned as a separate process, never bundled or linked). On macOS and Linux, AutoRAG builds a per-workspace database at `<workspace>/.autorag/fsearch/` indexing only your configured search roots, and keeps a `fsearch-cli watch` daemon live (FSEvents/inotify) for sub-second name search. It never touches the FSearch app's own database. Without fsearch-cli, name search falls back to a slow bounded filesystem walk. Set `"fsearch": false` in the config to turn it off. Windows is not affected (Everything covers it).
267
268
 
268
269
  ---
@@ -475,7 +476,7 @@ mirrored are kept and not re-parsed on the next run. `onProgress` reports `parse
475
476
  | `autorag health` | Check model provider authentication, token validity, and API reachability |
476
477
  | `autorag models list` | List chat models the pi runtime can resolve (built-ins, `models.json`, custom/extension providers) with provider auth status; never prints credential values |
477
478
  | `autorag update-check` | Compare the running `autorag` against the published npm version (also runs on `autorag tui` launch) |
478
- | `autorag tui` | Open Pi's interactive librarian TUI (`/login`, `/model`, `/resume`, …); `--telegram` / `--whatsapp` / `--discord` add the Telegram / WhatsApp / Discord remote-control bridges |
479
+ | `autorag tui` | Open Pi's interactive librarian TUI (`/login`, `/model`, `/resume`, …); the agent can stop and ask you a multiple-choice or open question through the [`ask_user` tool](docs/ask-user.md); `--telegram` / `--whatsapp` / `--discord` add the Telegram / WhatsApp / Discord remote-control bridges; `--permission-mode ask\|auto\|full` (Shift+Tab, `/permissions`) sets the [approval gate for file changes](docs/permissions.md) |
479
480
  | `autorag duplicates [DIR]` | Read-only scan for exact and near-duplicate document families with `dupey` |
480
481
  | `autorag lite ...` | CLI bootstrap, indexing repair, terminal maintenance, and fallback interface; agents use MCP for normal Lite operation |
481
482
  | `autorag memory inspect` | Render a read-only, path-opaque snapshot of retrieval memory (judged evidence, curated results, evidence chunks, insights); model-free |
@@ -649,7 +650,7 @@ AutoRAG Agent connects to external tools and communication platforms using dedic
649
650
  | **macOS Spotlight** | `spotlight` | Native `mdfind` CLI | macOS system metadata and content index | System Native |
650
651
  | **Browser History** | `hister` | [Hister](https://github.com/asciimoo/hister) server (AGPL-3.0-or-later, separate program, HTTP API) | Pages visited in Chrome/Chromium/Firefox, captured by Hister's own extension and indexed by Hister (web pages only; its local-file indexing is never used) | Lexical full-text; optional Semantic via Hister's own embedding endpoint |
651
652
 
652
- For configuration syntax and connector details, see [docs/datasource-skills.md](docs/datasource-skills.md). Non-interactive `sync`/`index` steps get a 30-minute per-connector budget (`connector.indexTimeoutMs`) because first-run imports routinely take minutes; interactive search keeps its 60-second default.
653
+ For configuration syntax and connector details, see [docs/datasource-skills.md](docs/datasource-skills.md). Non-interactive `sync`/`index` steps get a one-hour per-connector budget (`connector.indexTimeoutMs`) because first-run imports routinely take minutes; interactive search keeps its 60-second default.
653
654
 
654
655
  ---
655
656
 
@@ -729,7 +730,7 @@ Deep dive into AutoRAG Agent's architecture, security, and integration guides:
729
730
  - **[Telegram Remote Control](docs/telegram.md):** Ask the librarian from a Telegram chat through a running `autorag tui --telegram` session: setup, commands, and keeping it alive.
730
731
  - **[Datasource Skills Reference](docs/datasource-skills.md):** Full configuration contracts, connection aliases, and connector options.
731
732
  - **[Apple Calendar & Reminders via EventKit MCP](docs/eventkit-mcp.md):** macOS-only: read Calendar events and Reminders (Google/iCloud/Exchange accounts already in Calendar.app) by running `mcp-server-apple-events` beside `autorag-mcp`. Live, read-only; not indexed.
732
- - **[Jev Decisions](docs/jev-decisions.md):** Jev query pipeline, **on by default** via Dazzi Models when signed in (OpenRouter otherwise): it routes each question to a direct answer (intrinsic knowledge) or local search (everything needing more information; web search is left to the agent after the fast answer), splits multi-part questions into up to five parallel searches (`dazzi/openai/gpt-6-luna` when signed in, else `openrouter/qwen/qwen3.7-flash`), picks which registered datasources to search before the fast answer, and ends the run after the fast answer when that answer is complete. Also covers the `jev` judgment tool, backends (OpenRouter, TypeSafe, Vercel AI Gateway), and how to opt out.
733
+ - **[Jev Decisions](docs/jev-decisions.md):** Jev query pipeline, **on by default** via Dazzi Models when signed in (OpenRouter otherwise): it routes each question to a direct answer (intrinsic knowledge), local search (everything needing more information; web search is left to the agent after the fast answer), `organize` (move, rename, convert, or sort files and folders), or `extra` (any other action such as committing code; no retrieval), splits multi-part questions into up to five parallel searches (`dazzi/openai/gpt-6-luna` when signed in, else `openrouter/qwen/qwen3.7-flash`), picks which registered datasources to search before the fast answer, and ends the run after the fast answer when that answer is complete. Also covers the `jev` judgment tool, backends (OpenRouter, TypeSafe, Vercel AI Gateway), and how to opt out.
733
734
  - **[Manual QA & Datasource Test Harnesses](docs/manual-qa-datasources.md):** Real-world testing guides for Discord, KakaoTalk, Slack, Notion, and email.
734
735
  - **[Supply Chain Security & License Audits](docs/supply-chain.md):** Software bill of materials (SBOM) and dependency gate policies.
735
736
  - **[Competitive Landscape Study](docs/competitive-landscape-2026-09.md):** In-depth analysis of why in-place federation outperforms centralized RAG.
@@ -742,6 +743,7 @@ Deep dive into AutoRAG Agent's architecture, security, and integration guides:
742
743
  AutoRAG Agent is an open-source project built by the community. We welcome contributions, bug reports, datasource connectors, and ideas!
743
744
 
744
745
  - **Contributing:** Feel free to open an issue or pull request. Start with [CONTRIBUTING.md](CONTRIBUTING.md) — development setup, the `make ci` check we ask for, the `Signed-off-by` trailer every commit needs, and when to run the live end-to-end lanes. [MAINTAINERS](MAINTAINERS) lists who reviews which area. AI tools are allowed; unverified dumps are not — see [AI_POLICY.md](AI_POLICY.md).
746
+ - **Discussions:** For questions, usage help, ideas, and open-ended design talk, please use [GitHub Discussions](https://github.com/Marker-Inc-Korea/AutoRAG/discussions) instead of opening an issue. Keep issues for confirmed bugs and concrete, actionable work.
745
747
  - **Security:** Private vulnerability reports and the response SLA live in [SECURITY.md](SECURITY.md).
746
748
  - **GitHub Contributors:** [View all contributors](https://github.com/Marker-Inc-Korea/AutoRAG/graphs/contributors) on GitHub.
747
749
 
@@ -758,6 +760,7 @@ AutoRAG Agent stands on the shoulders of fantastic open-source projects:
758
760
  - **[FSearch](https://github.com/cboxdoerfer/fsearch)** and **[fsearch-cli](https://github.com/NomaDamas/fsearch-mac)** — Everything-style file-name search for macOS/Linux (GPL-2.0-or-later). Never bundled or linked: users install fsearch-cli separately and AutoRAG spawns it as a separate process (mere aggregation per the FSF GPL FAQ).
759
761
  - **[Hister](https://github.com/asciimoo/hister)** by [asciimoo](https://github.com/asciimoo) and contributors — Self-hosted browser web-history search (AGPL-3.0-or-later). Never bundled, linked, copied, or modified: users run Hister as a separate program and AutoRAG only calls its public HTTP search API (mere aggregation). Hister is always named as the backend of the `hister` datasource.
760
762
  - **[dupey](https://github.com/NomaDamas/dupey)** by [NomaDamas](https://github.com/NomaDamas) — Fast duplicate and near-duplicate document family detection.
763
+ - **[Filee](https://github.com/KnifeLemon/Filee)** by [KnifeLemon](https://github.com/KnifeLemon) — Offline conversion of 240+ file formats (MIT). Never bundled or linked: AutoRAG downloads the SHA-256-pinned [`filee-cli`](https://github.com/NomaDamas/filee-cli) release (NomaDamas' CLI-only redistribution, MIT) into `<AUTORAG_HOME>/tools/filee-cli/` on `autorag setup` / first conversion and spawns it as a separate process. An existing `filee`/`filee-cli` on `PATH` or `filee.binaryPath` wins. Filee downloads its own engines (FFmpeg, Pandoc, LibreOffice, …) on first use.
761
764
  - **Federated CLI Authors:** External datasource tools [`lazykatok`](https://github.com/changeroa/lazykatok), [`discrawl`](https://github.com/openclaw/discrawl), [`mailcrawl`](https://github.com/NomaDamas/mailcrawl), [`wacrawl`](https://github.com/openclaw/wacrawl), [`telecrawl`](https://github.com/openclaw/telecrawl), [`slacrawl`](https://github.com/openclaw/slacrawl), [`notcrawl`](https://github.com/openclaw/notcrawl), and [`rclone`](https://rclone.org).
762
765
  - **[kordoc](https://github.com/chrisryugj/kordoc)** by [chrisryugj](https://github.com/chrisryugj) — HWP/HWPX/HWPML, PDF, DOCX and XLSX parsing with nested-table fidelity, used as AutoRAG's default document parser.
763
766
 
@@ -1,5 +1,6 @@
1
1
  import type { Agent, AgentTool } from "@earendil-works/pi-agent-core";
2
2
  import type { Api, ImageContent, Model } from "@earendil-works/pi-ai";
3
+ import { type FileeCliOptions, type FileeConvertRequest } from "../convert/index.js";
3
4
  import { type DatasourceRetryOptions } from "../datasource/retry.js";
4
5
  import type { DatasourceIndexResult, DatasourceSkill } from "../datasource/types.js";
5
6
  import { type DupeyCliOptions } from "../dupey/index.js";
@@ -15,10 +16,12 @@ import { RetrievalEngine } from "../retrieval/engine.js";
15
16
  import { RetrievalMethodRegistry } from "../retrieval/registry.js";
16
17
  import type { DatasourceCatalogEntry } from "../retrieval/selection.js";
17
18
  import type { RetrievalDiagnostic, RetrievalOptions, RetrievalResult } from "../retrieval/types.js";
19
+ import { type ConvertFilesDetails } from "./convert-tool.js";
18
20
  import { type DatasourceAgentSkill } from "./datasource-skill.js";
19
21
  import { type ScanDuplicateDocumentsDetails } from "./dupey-tool.js";
20
22
  import { type JevToolOptions } from "./jev-extension.js";
21
23
  import { type JikjiFindProviderResult } from "./jikji-find-tool.js";
24
+ import { PermissionController, type PermissionMode } from "./permission-gate.js";
22
25
  import { type AutoRAGPiInteractiveRuntime, type AutoRAGPiSession } from "./pi-session.js";
23
26
  import { type RefreshProgressCounts, type RefreshProgressPhase } from "./refresh-progress.js";
24
27
  import { type SearchDocumentDiagnostic, type SearchDocumentsResponse, type SearchDocumentsStreamEvent } from "./search-documents.js";
@@ -256,6 +259,12 @@ export interface AutoRAGAgentOptions {
256
259
  autoRefresh?: AutoRefreshOptions;
257
260
  parserOptions?: DefaultParserRegistryOptions;
258
261
  dupey?: DupeyCliOptions | false;
262
+ /**
263
+ * Filee command line behind `convert_files` and `list_file_conversions`.
264
+ * `false` leaves both tools out. The duplicate-family check on converted
265
+ * copies follows `dupey`.
266
+ */
267
+ filee?: FileeCliOptions | false;
259
268
  /**
260
269
  * Jev (TypeSafe's judgment model: typed questions in, calibrated
261
270
  * probabilities out). When set, the two-phase search asks Jev before the
@@ -358,6 +367,15 @@ export interface AutoRAGAgentOptions {
358
367
  * owner pairing live in pi's `telegram.json`, never in AutoRAG config.
359
368
  */
360
369
  telegram?: boolean;
370
+ /**
371
+ * Approval gate for what the agent does to existing files. `full` (the programmatic default) installs a
372
+ * gate that never asks; `ask` and `auto` approve deletes, moves, renames, and in-place edits of originals
373
+ * (copying and creating new files never ask). `auto` asks Jev first and only falls back to the user when
374
+ * Jev will not approve. See {@link PermissionMode}.
375
+ */
376
+ permissionMode?: PermissionMode;
377
+ /** Share one controller (mode, session grants) with a host that switches modes itself. Wins over `permissionMode`. */
378
+ permissionController?: PermissionController;
361
379
  }
362
380
  /** Post-merge reranking options. Mirrors the CLI `RerankConfig` (secrets via env). */
363
381
  export interface RerankAgentOptions {
@@ -406,6 +424,8 @@ export declare class AutoRAGAgent {
406
424
  private readonly memory;
407
425
  private readonly runLogger;
408
426
  private lastQuery;
427
+ /** What the user has said in this conversation; Jev's permission gate judges file changes against it. */
428
+ private readonly userRequests;
409
429
  private lastSessionId;
410
430
  private activeRun;
411
431
  /**
@@ -428,6 +448,10 @@ export declare class AutoRAGAgent {
428
448
  * run starts from an empty ledger.
429
449
  */
430
450
  private readonly evidenceLedger;
451
+ /** The result numbers (`[n]`) this conversation has shown, kept next to the ledger's `e<N>` ordinals. */
452
+ private readonly citationNumbers;
453
+ /** Everything the user typed in this conversation; Jev reads it to judge whether a citation relates to what was asked. */
454
+ private readonly conversationQueries;
431
455
  private preliminaryCallback;
432
456
  /** Per-phase thinking levels of the two-phase search. */
433
457
  private readonly fastThinkingLevel;
@@ -460,10 +484,14 @@ export declare class AutoRAGAgent {
460
484
  private readonly datasourceAgentSkills;
461
485
  private readonly parserOptions;
462
486
  private readonly dupeyOptions;
487
+ private readonly fileeOptions;
463
488
  /** pi extension registering the optional `jev` tool; undefined when disabled. */
464
489
  private readonly jevExtension;
465
490
  /** Jev judge shared by the `jev` tool and the query router; undefined when disabled. */
466
491
  private readonly jevJudge;
492
+ /** Mode and grants of the file-change approval gate; shared by every pi session this agent creates. */
493
+ private readonly permissions;
494
+ private readonly permissionGate;
467
495
  /** Self-configuration, enabled only with Jev on a local session. */
468
496
  private readonly selfConfig;
469
497
  private readonly queryDecompositionModel;
@@ -497,11 +525,15 @@ export declare class AutoRAGAgent {
497
525
  /** The memory context loaded for the in-flight run; cleared whenever a run starts. */
498
526
  private memoryContextCache;
499
527
  private readonly discordRemote;
528
+ /** Whether the bound interactive session offers `ask_user`; the phase prompts name it only then. */
529
+ private askUserOffered;
500
530
  private activeRetrievalOptions;
501
531
  private readonly toolBurstGuard;
502
532
  private readonly limits;
503
533
  private readonly refreshLimits;
504
534
  constructor(options: AutoRAGAgentOptions);
535
+ convertFiles(request: FileeConvertRequest, signal?: AbortSignal): Promise<ConvertFilesDetails>;
536
+ listFileConversions(from?: string, signal?: AbortSignal): Promise<string>;
505
537
  scanDuplicateDocuments(): Promise<ScanDuplicateDocumentsDetails>;
506
538
  /**
507
539
  * Reference memory for the current question: everything judged earlier in
@@ -544,6 +576,8 @@ export declare class AutoRAGAgent {
544
576
  private configureSearchSession;
545
577
  private recordSearchToolEvent;
546
578
  private currentSystemPromptConfig;
579
+ /** The approval gate's controller: read or switch the permission mode of this agent's sessions. */
580
+ get permissionControl(): PermissionController;
547
581
  subscribe(listener: Parameters<Agent["subscribe"]>[0]): () => void;
548
582
  createPiInteractiveRuntime(): Promise<AutoRAGPiInteractiveRuntime>;
549
583
  /**
@@ -565,7 +599,12 @@ export declare class AutoRAGAgent {
565
599
  * matters, so the steer reaches the model before the next request.
566
600
  */
567
601
  private interruptibleBySteer;
568
- /** Resolve the model's inline `[eN]` citations against this run's evidence and derive the structured results. */
602
+ /**
603
+ * Resolve the model's inline `[eN]` citations against this run's evidence and derive the structured results.
604
+ * With Jev on, every cited chunk is first checked for relevance to the sentence that cites it and to what
605
+ * the user typed in this conversation; a chunk Jev finds unrelated (a table of contents, a footer) is dropped
606
+ * from the citations before the answer is returned or judged for memory.
607
+ */
569
608
  private deriveAnswer;
570
609
  /**
571
610
  * Routes one TUI input the way pi routes typed input for its own turns. With
@@ -718,6 +757,12 @@ export declare class AutoRAGAgent {
718
757
  * continues on the retrieval-order fallback.
719
758
  */
720
759
  private reportRerankFailure;
760
+ /**
761
+ * Sentence for the phase prompts that forbid tool calls: `ask_user` is not a search tool, and a request
762
+ * that hinges on a choice only the user can make must be asked, not guessed. Empty when the session does
763
+ * not offer the tool.
764
+ */
765
+ private askUserException;
721
766
  /**
722
767
  * Fast-phase prompt for two-phase searches. The baseline retrieval context
723
768
  * is already gathered, so the model answers immediately with minimal thinking,
@@ -736,6 +781,24 @@ export declare class AutoRAGAgent {
736
781
  * reply is the final answer.
737
782
  */
738
783
  buildDirectAnswerPrompt(query: string): string;
784
+ /**
785
+ * Tools an `organize` turn keeps: pi's file tools plus the converter, the
786
+ * duplicate scan, and file-name discovery, whichever this agent registered.
787
+ * The retrieval, datasource, and web tools stay out: the turn acts on files.
788
+ */
789
+ private organizeToolNames;
790
+ /**
791
+ * Prompt for a request Jev routed to `organize`: act on files and folders
792
+ * (move, rename, convert, sort). No retrieval ran and no verification
793
+ * follows; the model's plain final message is the answer.
794
+ */
795
+ buildOrganizePrompt(query: string): string;
796
+ /**
797
+ * Prompt for a request Jev routed to `extra`: a task that is neither
798
+ * knowledge, the user's records, file organization, nor configuration.
799
+ * The model acts with every tool it has; there is no retrieval or verification phase.
800
+ */
801
+ buildExtraPrompt(query: string): string;
739
802
  /** Discovery-tool hint naming only the registered discovery tools; empty when none. */
740
803
  private discoveryHint;
741
804
  /**
@@ -1,3 +1,4 @@
1
+ import type { CitationNumbers } from "./citation-numbers.js";
1
2
  import { type EvidenceLedger } from "./evidence-ledger.js";
2
3
  import type { AutoRAGResultsDetails } from "./results.js";
3
4
  import type { SearchDocumentDiagnostic } from "./search-documents.js";
@@ -5,6 +6,31 @@ export interface DerivedAnswer {
5
6
  readonly details: AutoRAGResultsDetails;
6
7
  readonly diagnostics: readonly SearchDocumentDiagnostic[];
7
8
  }
9
+ /**
10
+ * Identity of one cited chunk: the source plus the recorded chunk text. A
11
+ * source can back several chunks, so a chunk is judged and excluded on its own.
12
+ */
13
+ export declare function citedChunkKey(ref: {
14
+ readonly source: string;
15
+ readonly content?: string;
16
+ }): string;
17
+ /** One chunk the answer cites, with the sentences that cite it. */
18
+ export interface CitedChunk {
19
+ /** {@link citedChunkKey} of the chunk. */
20
+ readonly key: string;
21
+ readonly source: string;
22
+ readonly content: string;
23
+ /** Each distinct sentence ending in a marker that cites this chunk, in answer order. */
24
+ readonly sentences: readonly string[];
25
+ }
26
+ /**
27
+ * Every chunk the answer cites, read from the raw markers. It resolves ids the
28
+ * way {@link deriveResultsFromAnswer} does but numbers nothing, so judging a
29
+ * citation never touches the conversation's result numbers.
30
+ */
31
+ export declare function citedChunks(text: string, ledger: EvidenceLedger, options: {
32
+ readonly allowLocalFiles: boolean;
33
+ }): CitedChunk[];
8
34
  /**
9
35
  * Turn the model's plain answer into the structured results the rest of the
10
36
  * harness consumes. The model cites with the evidence ids the retrieval tools
@@ -12,11 +38,17 @@ export interface DerivedAnswer {
12
38
  * itself. Each id is resolved against the run's evidence ledger, so a source,
13
39
  * method, and chunk always come from recorded evidence, never from model text.
14
40
  *
15
- * Results are one per cited source, numbered by first appearance, and every
16
- * marker in the returned answer is rewritten to its result number (`[1]`).
41
+ * Results are one per cited source, in order of first appearance in this answer. A source's
42
+ * number comes from the conversation's {@link CitationNumbers}: a source
43
+ * numbered in an earlier answer (or an earlier phase of this turn) keeps its
44
+ * number, a new source gets the next unused one, and every marker in the
45
+ * returned answer is rewritten to its result number (`[1]`).
17
46
  * A marker that matches no evidence, and any numeric marker the model wrote on
18
47
  * its own, is dropped and reported: it can never point at the wrong result.
19
48
  */
20
49
  export declare function deriveResultsFromAnswer(text: string, ledger: EvidenceLedger, options: {
21
50
  readonly allowLocalFiles: boolean;
51
+ readonly numbers: CitationNumbers;
52
+ /** Chunks ({@link citedChunkKey}) a relevance judgment rejected: a citation of only these is dropped silently. */
53
+ readonly excludedChunks?: ReadonlySet<string>;
22
54
  }): DerivedAnswer;
@@ -34,8 +34,8 @@ export declare const ANSWER_UNCERTAINTY_RULE = "**Uncertainty placement**: when
34
34
  /**
35
35
  * Inline evidence citations. The model writes the id the retrieval tools print
36
36
  * next to each result; the harness resolves it to the recorded source and
37
- * renumbers the markers `[1]`, `[2]`, ... in order of first appearance, so the
38
- * caller only ever sees numbered citations backed by recorded evidence.
37
+ * renumbers the markers `[1]`, `[2]`, ... (a source keeps its number for the whole
38
+ * conversation), so the caller only ever sees numbered citations backed by recorded evidence.
39
39
  */
40
40
  export declare const ANSWER_CITATION_RULE = "**Citations**: cite supporting evidence inline with the evidence id shown next to each retrieved result, in square brackets (e.g. [e3], or [e3][e7] for two). Copy ids exactly; never invent one. For a local file you opened yourself with `bash`, cite `[file:<absolute path>]`. Cite the evidence that backs a sentence at the end of that sentence. Do not cite numbers, paths, or anything else.";
41
41
  /**
@@ -0,0 +1,8 @@
1
+ /** Tool the `pi-ask-user` extension registers; pi's allow-list must name it to keep it active. */
2
+ export declare const ASK_USER_TOOL_NAME = "ask_user";
3
+ /**
4
+ * Entry file of the community `pi-ask-user` extension (the most-installed pi package for this: Claude
5
+ * Code's AskUserQuestion, with a searchable single/multi-select sheet, freeform answers, and 2-4 question
6
+ * batches). It ships TypeScript source and no `main`, so pi's own extension loader runs it from this path.
7
+ */
8
+ export declare function resolveAskUserExtensionPath(): string;
@@ -0,0 +1,45 @@
1
+ import type { AgentTool } from "@earendil-works/pi-agent-core";
2
+ import { Type } from "typebox";
3
+ import type { AutomationRunRecord } from "../automation/run.js";
4
+ import { type ServiceCommandExec } from "../automation/service.js";
5
+ export declare const MANAGE_AUTOMATIONS_TOOL_NAME = "manage_automations";
6
+ declare const manageAutomationsSchema: Type.TObject<{
7
+ action: Type.TUnion<[Type.TLiteral<"list">, Type.TLiteral<"save">, Type.TLiteral<"delete">, Type.TLiteral<"run">, Type.TLiteral<"install_service">, Type.TLiteral<"uninstall_service">]>;
8
+ id: Type.TOptional<Type.TString>;
9
+ automation: Type.TOptional<Type.TObject<{
10
+ paths: Type.TArray<Type.TString>;
11
+ events: Type.TOptional<Type.TArray<Type.TUnion<[Type.TLiteral<"create">, Type.TLiteral<"update">, Type.TLiteral<"delete">]>>>;
12
+ include: Type.TOptional<Type.TArray<Type.TString>>;
13
+ exclude: Type.TOptional<Type.TArray<Type.TString>>;
14
+ run: Type.TOptional<Type.TArray<Type.TString>>;
15
+ agent: Type.TOptional<Type.TObject<{
16
+ profile: Type.TString;
17
+ task: Type.TString;
18
+ retrieval: Type.TOptional<Type.TObject<{
19
+ searchAll: Type.TOptional<Type.TBoolean>;
20
+ datasources: Type.TOptional<Type.TArray<Type.TString>>;
21
+ }>>;
22
+ }>>;
23
+ appendFiles: Type.TOptional<Type.TBoolean>;
24
+ debounceMs: Type.TOptional<Type.TInteger>;
25
+ timeoutMs: Type.TOptional<Type.TInteger>;
26
+ }>>;
27
+ events: Type.TOptional<Type.TArray<Type.TObject<{
28
+ type: Type.TUnion<[Type.TLiteral<"create">, Type.TLiteral<"update">, Type.TLiteral<"delete">]>;
29
+ path: Type.TString;
30
+ }>>>;
31
+ }>;
32
+ export interface ManageAutomationsToolOptions {
33
+ readonly home?: string;
34
+ readonly env?: NodeJS.ProcessEnv;
35
+ readonly platform?: NodeJS.Platform;
36
+ readonly exec?: ServiceCommandExec;
37
+ readonly waitForRunningMs?: number;
38
+ }
39
+ export interface ManageAutomationsDetails {
40
+ readonly action: string;
41
+ readonly id?: string;
42
+ readonly run?: AutomationRunRecord;
43
+ }
44
+ export declare function createManageAutomationsTool(options?: ManageAutomationsToolOptions): AgentTool<typeof manageAutomationsSchema, ManageAutomationsDetails>;
45
+ export {};
@@ -0,0 +1,23 @@
1
+ import type { ExtensionFactory } from "@earendil-works/pi-coding-agent";
2
+ import { type EvidenceLedger } from "./evidence-ledger.js";
3
+ /** `file://` URL of an absolute local path, an http(s) URL as is, otherwise undefined (a datasource id, a message id). */
4
+ export declare function openableTarget(source: string): string | undefined;
5
+ /**
6
+ * Rewrite the citation markers of an assistant answer into Markdown links, so
7
+ * pi renders them as terminal hyperlinks that open the cited file or page.
8
+ *
9
+ * `[e3]` and `[e3, e7]` keep their brackets and ids; each id that resolves to
10
+ * an openable source becomes a link. `[file:/abs/path]` becomes `[<file name>]`
11
+ * linked to that file. Markers that resolve to nothing openable stay as the
12
+ * model wrote them.
13
+ *
14
+ * `sourceOf` maps an evidence id to its recorded source; `isFile` says whether
15
+ * a `[file:...]` path is a real local file.
16
+ */
17
+ export declare function linkCitations(markdown: string, sourceOf: (id: string) => string | undefined, isFile: (path: string) => boolean): string;
18
+ /**
19
+ * pi extension that makes the citations in the interactive transcript
20
+ * clickable. The model cites by evidence id; the ledger recorded the source
21
+ * each id names, so the link target is never model-written text.
22
+ */
23
+ export declare function createCitationLinks(ledger: EvidenceLedger): ExtensionFactory;
@@ -0,0 +1,68 @@
1
+ import { type Static, Type } from "typebox";
2
+ /** Custom session entry type under which a conversation persists its result numbers. */
3
+ export declare const CITATION_NUMBERS_ENTRY_TYPE = "autorag.citation-numbers";
4
+ declare const citationNumberEntrySchema: Type.TObject<{
5
+ source: Type.TString;
6
+ number: Type.TInteger;
7
+ }>;
8
+ /** One source and the result number (`[n]`) the user was shown for it. */
9
+ export type CitationNumberEntry = Static<typeof citationNumberEntrySchema>;
10
+ /**
11
+ * Entries a session persisted under {@link CITATION_NUMBERS_ENTRY_TYPE}. A
12
+ * malformed entry is skipped: its source is then numbered afresh, never
13
+ * under a number it was not shown with.
14
+ */
15
+ export declare function parseCitationNumberEntries(data: unknown): CitationNumberEntry[];
16
+ /** Highest result number among `entries`; 0 when there are none. */
17
+ export declare function highestCitationNumber(entries: readonly CitationNumberEntry[]): number;
18
+ /**
19
+ * The result numbers (`[1]`, `[2]`, ...) one conversation has shown the user.
20
+ *
21
+ * A source keeps the number it was first shown with in every later answer of
22
+ * the conversation, and a new source gets the next unused number. Numbers are
23
+ * never reissued, mirroring the `e<N>` ordinals of the `EvidenceLedger`: the
24
+ * quick and verification answers of one turn, and every turn after them,
25
+ * share one numbering, so a `[n]` a user saw never names a different source.
26
+ *
27
+ * The hosting session persists what {@link takeUnsaved} returns (through the
28
+ * sink installed with {@link setSink}) and rebuilds the numbers with
29
+ * {@link restore} when a conversation is resumed.
30
+ */
31
+ export declare class CitationNumbers {
32
+ private readonly bySource;
33
+ /** Entries issued since the last {@link takeUnsaved}. */
34
+ private unsaved;
35
+ private sink;
36
+ /**
37
+ * The last number issued. Survives {@link clear} and {@link restore}: a
38
+ * conversation keeps earlier answers in view, so restarting at 1 would let
39
+ * an old `[n]` silently name a different source.
40
+ */
41
+ private lastNumber;
42
+ /** The number for `source`: the one it already has, else the next unused number. */
43
+ numberFor(source: string): number;
44
+ /** Forget every source. Numbers are never reissued, so a previous conversation's `[n]` stays unused. */
45
+ clear(): void;
46
+ /** Forget every source and restart at 1: for a run that owns no conversation, where no earlier `[n]` is in view. */
47
+ reset(): void;
48
+ /** Numbers issued since the last call, for the hosting session to persist. */
49
+ takeUnsaved(): CitationNumberEntry[];
50
+ /** Where {@link flush} writes numbers: the hosting session. Replaces any earlier sink. */
51
+ setSink(sink: ((entries: CitationNumberEntry[]) => void) | undefined): void;
52
+ /**
53
+ * Persist numbers issued since the last save right now. Answers are derived
54
+ * after a turn's last session event, so without this the final answer's new
55
+ * numbers would not reach the session file until the next turn. With no
56
+ * sink installed the numbers stay unsaved for the next save.
57
+ */
58
+ flush(): void;
59
+ /**
60
+ * Rebuild the numbers from persisted entries, such as the ones on the
61
+ * resumed conversation branch; a later entry for the same source replaces an
62
+ * earlier one. Numbers keep counting past every restored number and past
63
+ * `numberFloor`, the highest number issued anywhere in the conversation
64
+ * (other branches included).
65
+ */
66
+ restore(entries: readonly CitationNumberEntry[], numberFloor?: number): void;
67
+ }
68
+ export {};
@@ -0,0 +1,37 @@
1
+ import type { CitedChunk } from "./answer-citations.js";
2
+ import type { JevJudge } from "./jev-extension.js";
3
+ /**
4
+ * The model sometimes cites a chunk that has nothing to do with the sentence it
5
+ * backs or with what the user asked: a table of contents, a navigation bar, a
6
+ * copyright footer, a generic introduction. Before the answer is returned,
7
+ * every cited chunk is put to Jev as one relevance question, and a chunk Jev
8
+ * finds unrelated is removed from the answer's citations.
9
+ *
10
+ * This is deliberately weaker than the memory judgment in `evidence-judgment.ts`
11
+ * ("does it directly support, and is it needed"): that gate decides what is
12
+ * worth remembering and rejects any chunk that does not state the claim. Here a
13
+ * chunk that is merely on topic, or backs only part of the claim, must stay, so
14
+ * the only thing rejected is evidence with no information on the subject at all.
15
+ */
16
+ /** A chunk is kept when Jev's P(relevant) is at or above this; below it the chunk is rejected. */
17
+ export declare const CITATION_RELEVANCE_FLOOR = 0.3;
18
+ /** Jev question id prefix of one citation relevance check. */
19
+ export declare const CITATION_QUESTION_ID_PREFIX = "citation:";
20
+ export interface CitationRelevanceInput {
21
+ /** Everything the user typed in the conversation, oldest first; the last is the question being answered. */
22
+ readonly userMessages: readonly string[];
23
+ /** The chunks the answer cites, with the sentences citing each. */
24
+ readonly chunks: readonly CitedChunk[];
25
+ }
26
+ export interface CitationRelevance {
27
+ /** {@link CitedChunk.key} of every chunk Jev found unrelated. */
28
+ readonly rejected: ReadonlySet<string>;
29
+ /** Set when Jev gave no usable verdict for ANY chunk; nothing was rejected. Absent when Jev decided. */
30
+ readonly fallbackReason?: string;
31
+ }
32
+ /**
33
+ * Ask Jev, in one batched call, whether each cited chunk is relevant to the
34
+ * sentences that cite it and to what the user asked. Never throws: a rejecting
35
+ * judge rejects nothing and reports why, and a chunk Jev left unanswered is kept.
36
+ */
37
+ export declare function judgeCitationRelevance(judge: JevJudge, input: CitationRelevanceInput): Promise<CitationRelevance>;
@@ -0,0 +1,31 @@
1
+ /** Custom session entry type under which a conversation persists what the user typed. */
2
+ export declare const CONVERSATION_QUERIES_ENTRY_TYPE = "autorag.queries";
3
+ /** The queries a session persisted under {@link CONVERSATION_QUERIES_ENTRY_TYPE}; a malformed entry is skipped. */
4
+ export declare function parseQueryEntries(data: unknown): string[];
5
+ /**
6
+ * Everything the user typed in one conversation: each question and each
7
+ * steer, as typed. The transcript cannot stand in for it, because the first
8
+ * turn's user message there is the harness prompt that wraps the question
9
+ * with baseline evidence and formatting rules.
10
+ *
11
+ * The hosting session persists what {@link flush} hands to the sink and
12
+ * rebuilds the list with {@link restore} when a conversation is resumed or
13
+ * a new one starts, the way the evidence ledger and result numbers are.
14
+ */
15
+ export declare class ConversationQueries {
16
+ private queries;
17
+ /** Queries added since the last {@link flush}. */
18
+ private unsaved;
19
+ private sink;
20
+ add(query: string): void;
21
+ /** Every query of the conversation, oldest first. */
22
+ all(): readonly string[];
23
+ /** Where {@link flush} writes queries: the hosting session. Replaces any earlier sink. */
24
+ setSink(sink: ((entries: string[]) => void) | undefined): void;
25
+ /** Persist queries added since the last save. With no sink installed they stay unsaved for the next save. */
26
+ flush(): void;
27
+ /** Replace the conversation's queries with already-persisted ones; an empty list forgets everything. */
28
+ restore(queries: readonly string[]): void;
29
+ /** Forget every query, saved or not: a run that owns no conversation starts over. */
30
+ reset(): void;
31
+ }
@@ -0,0 +1,28 @@
1
+ import type { AgentTool } from "@earendil-works/pi-agent-core";
2
+ import { Type } from "typebox";
3
+ import type { ConvertAndRelateResult, FileeConvertRequest } from "../convert/index.js";
4
+ export declare const CONVERT_FILES_TOOL_NAME = "convert_files";
5
+ export declare const LIST_FILE_CONVERSIONS_TOOL_NAME = "list_file_conversions";
6
+ export type ConvertFilesDetails = ConvertAndRelateResult;
7
+ export interface FileConversionProvider {
8
+ convertFiles(request: FileeConvertRequest, signal?: AbortSignal): Promise<ConvertFilesDetails>;
9
+ listFileConversions(from?: string, signal?: AbortSignal): Promise<string>;
10
+ }
11
+ declare const convertFilesSchema: Type.TObject<{
12
+ inputs: Type.TArray<Type.TString>;
13
+ to: Type.TString;
14
+ outputDir: Type.TOptional<Type.TString>;
15
+ recursive: Type.TOptional<Type.TBoolean>;
16
+ quality: Type.TOptional<Type.TInteger>;
17
+ overwrite: Type.TOptional<Type.TBoolean>;
18
+ skipExisting: Type.TOptional<Type.TBoolean>;
19
+ keepDates: Type.TOptional<Type.TBoolean>;
20
+ }>;
21
+ export declare function createConvertFilesTool(provider: FileConversionProvider): AgentTool<typeof convertFilesSchema, ConvertFilesDetails>;
22
+ declare const listConversionsSchema: Type.TObject<{
23
+ from: Type.TOptional<Type.TString>;
24
+ }>;
25
+ export declare function createListFileConversionsTool(provider: FileConversionProvider): AgentTool<typeof listConversionsSchema, {
26
+ readonly from?: string;
27
+ }>;
28
+ export {};
@@ -1,4 +1,6 @@
1
1
  import type { ExtensionFactory, SessionEntry } from "@earendil-works/pi-coding-agent";
2
+ import { type CitationNumbers } from "./citation-numbers.js";
3
+ import { type ConversationQueries } from "./conversation-queries.js";
2
4
  import { type EvidenceLedger } from "./evidence-ledger.js";
3
5
  /** The part of pi's session manager the ledger is rebuilt from. */
4
6
  interface SessionEntries {
@@ -6,19 +8,23 @@ interface SessionEntries {
6
8
  getEntries(): SessionEntry[];
7
9
  }
8
10
  /**
9
- * Rebuild `ledger` for the conversation branch `session` is on. Evidence from
10
- * other branches stays out of reach (their transcripts are not in context), but
11
- * its ids still count: new evidence never reuses an id issued anywhere in the
12
- * conversation.
11
+ * Rebuild `ledger`, `numbers`, and `queries` for the conversation branch `session` is on.
12
+ * Evidence and result numbers from other branches stay out of reach (their
13
+ * transcripts are not in context), but their ids and numbers still count: new
14
+ * evidence and new results never reuse one issued anywhere in the conversation.
15
+ * What the user typed follows the branch exactly: a query typed on a branch the
16
+ * user left is not part of the conversation in view.
13
17
  */
14
- export declare function restoreEvidenceLedger(ledger: EvidenceLedger, session: SessionEntries): void;
18
+ export declare function restoreConversationState(ledger: EvidenceLedger, numbers: CitationNumbers, queries: ConversationQueries, session: SessionEntries): void;
15
19
  /**
16
- * pi extension that keeps the conversation's evidence ledger in the session
17
- * file, next to the transcript that shows the model its `[eN]` ids. Evidence is
18
- * appended as the tools return it; switching, resuming, forking, or navigating
19
- * the session tree rebuilds the ledger from the branch now in view. An id the
20
- * model saw therefore resolves, and is never reissued, whatever turns, tool
20
+ * pi extension that keeps the conversation's evidence ledger, result numbers,
21
+ * and typed queries in the session file, next to the transcript that shows the
22
+ * model its `[eN]` ids and the user its `[n]` results. Evidence is appended as
23
+ * the tools return it, result numbers as answers are derived, and queries as
24
+ * they are typed; switching, resuming, forking, or navigating the session tree
25
+ * rebuilds all three from the branch now in view. An id the model saw therefore
26
+ * resolves, and an id or result number is never reissued, whatever turns, tool
21
27
  * calls, resumes, or restarts happened in between.
22
28
  */
23
- export declare function createEvidencePersistence(ledger: EvidenceLedger): ExtensionFactory;
29
+ export declare function createEvidencePersistence(ledger: EvidenceLedger, numbers: CitationNumbers, queries: ConversationQueries): ExtensionFactory;
24
30
  export {};
@@ -1,5 +1,6 @@
1
1
  export type { AutoRAGAgentOptions, AutoRefreshOptions } from "./agent.js";
2
2
  export { AutoRAGAgent } from "./agent.js";
3
+ export { CONVERT_FILES_TOOL_NAME, type ConvertFilesDetails, createConvertFilesTool, createListFileConversionsTool, type FileConversionProvider, LIST_FILE_CONVERSIONS_TOOL_NAME, } from "./convert-tool.js";
3
4
  export { buildDatasourceSkillsPrompt, createLoadDatasourceSkillTool, type DatasourceSkillProvider, datasourceSkillLocation, formatDatasourceSkillInvocation, LOAD_DATASOURCE_SKILL_TOOL_NAME, type LoadDatasourceSkillDetails, toDatasourceAgentSkill, } from "./datasource-skill.js";
4
5
  export { createScanDuplicateDocumentsTool, SCAN_DUPLICATE_DOCUMENTS_TOOL_NAME, type ScanDuplicateDocumentsDetails, type ScanDuplicateDocumentsProvider, } from "./dupey-tool.js";
5
6
  export { createJevExtension, JEV_TOOL_NAME, type JevBackendName, type JevToolOptions, } from "./jev-extension.js";