@autorag/librarian 2.10.6 → 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.
- package/NOTICE +14 -0
- package/README.md +52 -10
- package/dist/agent/agent.d.ts +70 -2
- package/dist/agent/answer-citations.d.ts +34 -2
- package/dist/agent/answer-guidelines.d.ts +24 -3
- package/dist/agent/ask-user.d.ts +8 -0
- package/dist/agent/automation-tool.d.ts +45 -0
- package/dist/agent/citation-links.d.ts +23 -0
- package/dist/agent/citation-numbers.d.ts +68 -0
- package/dist/agent/citation-relevance.d.ts +37 -0
- package/dist/agent/conversation-queries.d.ts +31 -0
- package/dist/agent/convert-tool.d.ts +28 -0
- package/dist/agent/evidence-persistence.d.ts +17 -11
- package/dist/agent/index.d.ts +1 -0
- package/dist/agent/intent-tracing.d.ts +33 -0
- package/dist/agent/mcp-client.d.ts +27 -0
- package/dist/agent/permission-gate.d.ts +78 -0
- package/dist/agent/permission-judgment.d.ts +72 -0
- package/dist/agent/permission-paths.d.ts +23 -0
- package/dist/agent/pi-session.d.ts +8 -0
- package/dist/agent/query-routing.d.ts +14 -17
- package/dist/agent/search-documents.d.ts +1 -1
- package/dist/agent/search-progress.d.ts +96 -0
- package/dist/agent/self-config.d.ts +2 -0
- package/dist/agent/user-requests.d.ts +52 -0
- package/dist/agent/welcome-header.d.ts +35 -0
- package/dist/automation/config.d.ts +48 -0
- package/dist/automation/daemon.d.ts +31 -0
- package/dist/automation/dispatch.d.ts +13 -0
- package/dist/automation/run-agent.d.ts +22 -0
- package/dist/automation/run.d.ts +32 -0
- package/dist/automation/service.d.ts +61 -0
- package/dist/cli/commands/automate.d.ts +2 -0
- package/dist/cli/commands/setup.d.ts +2 -0
- package/dist/cli/config.d.ts +21 -0
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +26740 -21094
- package/dist/cli/open-target.d.ts +9 -0
- package/dist/cli/setup.d.ts +21 -0
- package/dist/convert/cli.d.ts +77 -0
- package/dist/convert/index.d.ts +4 -0
- package/dist/convert/installer.d.ts +84 -0
- package/dist/convert/matrix.d.ts +27 -0
- package/dist/convert/relate.d.ts +30 -0
- package/dist/core.js +32095 -27288
- package/dist/datasource/connector-timeouts.d.ts +6 -2
- package/dist/datasource/crawler-types.d.ts +1 -1
- package/dist/datasource/errors.d.ts +1 -1
- package/dist/datasource/index.d.ts +2 -1
- package/dist/datasource/skills/factory.d.ts +3 -0
- package/dist/datasource/skills/hister/client.d.ts +83 -0
- package/dist/datasource/skills/hister/embedding.d.ts +64 -0
- package/dist/datasource/skills/hister/index.d.ts +2 -0
- package/dist/datasource/skills/hister/setup.d.ts +87 -0
- package/dist/datasource/skills/hister/skill.d.ts +63 -0
- package/dist/datasource/skills/lazykatok/types.d.ts +2 -2
- package/dist/datasource/skills/mailcrawl/types.d.ts +1 -1
- package/dist/datasource/skills/obsidian/index.d.ts +4 -6
- package/dist/datasource/skills/obsidian/methods.d.ts +13 -17
- package/dist/datasource/skills/obsidian/paths.d.ts +24 -24
- package/dist/datasource/skills/obsidian/skill.d.ts +10 -15
- package/dist/datasource/skills/obsidian/staging.d.ts +50 -0
- package/dist/datasource/skills/obsidian/vault-index.d.ts +44 -0
- package/dist/dupey/cli.d.ts +18 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +32263 -27429
- package/dist/mcp/index.js +32149 -27342
- package/dist/minsync/installer.d.ts +1 -1
- package/dist/minsync/workspace-lock.d.ts +7 -0
- package/dist/process/terminate-tree.d.ts +4 -5
- package/dist/profiles/agent-factory.d.ts +60 -0
- package/dist/profiles/automation-profiles.d.ts +25 -0
- package/dist/profiles/loop-guard.d.ts +23 -0
- package/dist/profiles/retrieval-tools.d.ts +24 -0
- package/dist/profiles/session-model.d.ts +69 -0
- package/dist/profiles.d.ts +13 -0
- package/dist/profiles.js +34739 -0
- package/dist/retrieval/rerank.d.ts +6 -0
- package/licenses/hister-AGPL-3.0-notice.txt +47 -0
- package/package.json +9 -3
- package/skills/autorag/SKILL.md +79 -5
- package/skills/autorag-doctor/SKILL.md +5 -4
- package/skills/autorag-lite-setup/SKILL.md +23 -5
- package/skills/autorag-setup/SKILL.md +68 -7
- package/dist/datasource/skills/obsidian/client.d.ts +0 -15
- package/dist/datasource/skills/obsidian/types.d.ts +0 -92
|
@@ -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.
|
|
10
|
-
* other branches
|
|
11
|
-
*
|
|
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
|
|
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
|
|
17
|
-
* file, next to the transcript that shows the
|
|
18
|
-
*
|
|
19
|
-
* the
|
|
20
|
-
*
|
|
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 {};
|
package/dist/agent/index.d.ts
CHANGED
|
@@ -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";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
/**
|
|
3
|
+
* Intent tracing: every tool the model can call also takes a short `i` argument, one line saying
|
|
4
|
+
* what that call is for. The text is shown while the model works (pi's `Working` loader in the TUI,
|
|
5
|
+
* `progress` events of `searchDocumentsStream` for the CLI and the desktop app), so a long search
|
|
6
|
+
* says what it is doing without the model writing separate progress notes.
|
|
7
|
+
*
|
|
8
|
+
* Pi has no such feature; this mirrors oh-my-pi's. The field exists only on the wire: it is added to
|
|
9
|
+
* the tool declarations of each model request and removed again before the tool validates and runs,
|
|
10
|
+
* so no tool ever sees it.
|
|
11
|
+
*/
|
|
12
|
+
export declare const INTENT_FIELD = "i";
|
|
13
|
+
/** The text to show for a model-written intent, or `undefined` when it is not a usable label. */
|
|
14
|
+
export declare function normalizeIntent(value: unknown): string | undefined;
|
|
15
|
+
/** The intent of the last tool call in an assistant message that carries one, or `undefined`. */
|
|
16
|
+
export declare function intentOfMessage(message: {
|
|
17
|
+
readonly role?: string;
|
|
18
|
+
readonly content?: unknown;
|
|
19
|
+
}): string | undefined;
|
|
20
|
+
/** Whether the tool schema already has its own `i` parameter, which then belongs to the tool. */
|
|
21
|
+
export declare function schemaDefinesIntent(schema: unknown): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* The wire schema of a tool with the required `i` field first. A schema that is not an object, that
|
|
24
|
+
* already defines `i`, or that rejects unknown properties comes back unchanged: the tool would
|
|
25
|
+
* refuse the field once the model filled it in.
|
|
26
|
+
*/
|
|
27
|
+
export declare function withIntentField(schema: unknown): unknown;
|
|
28
|
+
/**
|
|
29
|
+
* Wires intent tracing into a pi session: declares `i` on every tool, takes it off the arguments
|
|
30
|
+
* before the tool runs, and, when the session has a terminal UI, shows the newest intent as the
|
|
31
|
+
* working message. Register it in every session whose model calls AutoRAG's tools.
|
|
32
|
+
*/
|
|
33
|
+
export declare function registerIntentTracing(pi: ExtensionAPI): void;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type ExtensionFactory } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
/** pi's system-prompt section naming the MCP servers whose tools the model does not see declared. */
|
|
3
|
+
export declare const MCP_SERVERS_SECTION = "mcp_servers";
|
|
4
|
+
/**
|
|
5
|
+
* Tools pi's MCP integration owns. pi's `tools` allow-list keeps only named tools active, so every
|
|
6
|
+
* one of them has to be named: `mcp__*` covers each server tool, the rest are the codemode and
|
|
7
|
+
* tool-search entry points and the resource readers.
|
|
8
|
+
*/
|
|
9
|
+
export declare const MCP_TOOL_NAMES: string[];
|
|
10
|
+
export interface AutoRAGMcpClient {
|
|
11
|
+
/** Extensions that connect the servers; the host registers them next to its own. */
|
|
12
|
+
readonly extensionFactories: readonly ExtensionFactory[];
|
|
13
|
+
/** Entries the session's `tools` allow-list needs so the extensions' tools stay active. */
|
|
14
|
+
readonly toolNames: readonly string[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Connects the user's external MCP servers to an AutoRAG pi session, or returns `undefined` when
|
|
18
|
+
* `<agentDir>/mcp.json` is absent or names no enabled server, leaving the tool surface unchanged.
|
|
19
|
+
*
|
|
20
|
+
* Only the user-level file is read. pi would also load a project `.pi/mcp.json`, but that lets any
|
|
21
|
+
* directory AutoRAG starts in choose which processes run, so it is ignored by design. Entries go
|
|
22
|
+
* through `pi.registerMcpServer`, which validates them with pi's own rules; a rejected entry or an
|
|
23
|
+
* unreadable file is reported verbatim at session start and never stops the other servers.
|
|
24
|
+
*/
|
|
25
|
+
export declare function createAutoRAGMcpClient(agentDir: string): AutoRAGMcpClient | undefined;
|
|
26
|
+
/** The prompt block for the servers pi reported in `sections`, or "" when it reported none. */
|
|
27
|
+
export declare function mcpPromptAddendum(sections: Readonly<Record<string, string>> | undefined): string;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { ExtensionFactory } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import type { JevJudge } from "./jev-extension.js";
|
|
3
|
+
import { type PermissionKind } from "./permission-judgment.js";
|
|
4
|
+
import { type UserRequestLog } from "./user-requests.js";
|
|
5
|
+
export { AUTO_APPROVE_MIN_CONFIDENCE, DEFAULT_MAX_STATE_CHARS, PERMISSION_GATE_QUESTION_ID, } from "./permission-judgment.js";
|
|
6
|
+
/**
|
|
7
|
+
* How much the agent may do to the user's files without asking.
|
|
8
|
+
*
|
|
9
|
+
* - `full`: no gate; the agent does everything on its own, and Jev is never asked.
|
|
10
|
+
* - `ask`: every `bash`, `write`, `edit`, and saved automation is put to the user. Jev is not used.
|
|
11
|
+
* - `auto` (default): Jev classifies each of those calls first. One it finds safe runs; one it flags is approved
|
|
12
|
+
* by Jev when the user's request clearly covers it, and only what Jev will not approve confidently reaches
|
|
13
|
+
* the user.
|
|
14
|
+
*/
|
|
15
|
+
export type PermissionMode = "full" | "ask" | "auto";
|
|
16
|
+
/** Order Shift+Tab cycles through. */
|
|
17
|
+
export declare const PERMISSION_MODES: readonly PermissionMode[];
|
|
18
|
+
/** Mode a fresh interactive or CLI session starts in. */
|
|
19
|
+
export declare const DEFAULT_PERMISSION_MODE: PermissionMode;
|
|
20
|
+
export declare function parsePermissionMode(value: unknown): PermissionMode | undefined;
|
|
21
|
+
export declare function cyclePermissionMode(mode: PermissionMode): PermissionMode;
|
|
22
|
+
type ModeListener = (mode: PermissionMode) => void;
|
|
23
|
+
/** What a session grant covers: one category of change, every call Jev could not classify, or (`ask`) every call. */
|
|
24
|
+
export type GrantKey = PermissionKind | "unclassified" | "all";
|
|
25
|
+
/**
|
|
26
|
+
* Session-wide permission state: the mode, and what the user allowed for the rest of the session. One
|
|
27
|
+
* controller is shared by every pi session of an agent.
|
|
28
|
+
*/
|
|
29
|
+
export declare class PermissionController {
|
|
30
|
+
private current;
|
|
31
|
+
private readonly listeners;
|
|
32
|
+
private readonly granted;
|
|
33
|
+
private readonly created;
|
|
34
|
+
constructor(mode?: PermissionMode);
|
|
35
|
+
get mode(): PermissionMode;
|
|
36
|
+
/** Switches mode. Session grants end with the mode they were given in. */
|
|
37
|
+
set(mode: PermissionMode): void;
|
|
38
|
+
cycle(): PermissionMode;
|
|
39
|
+
subscribe(listener: ModeListener): () => void;
|
|
40
|
+
isGranted(key: GrantKey): boolean;
|
|
41
|
+
grant(keys: readonly GrantKey[]): void;
|
|
42
|
+
/** Records paths a successful call brought into existence: the agent's own files, not the user's originals. */
|
|
43
|
+
markCreated(paths: readonly string[]): void;
|
|
44
|
+
/** Whether the agent created this path, or a folder it lies in, earlier in this session. */
|
|
45
|
+
isCreated(path: string): boolean;
|
|
46
|
+
}
|
|
47
|
+
export interface PermissionGateOptions {
|
|
48
|
+
readonly controller: PermissionController;
|
|
49
|
+
/**
|
|
50
|
+
* Jev, which classifies every gated call. Without one the gate cannot classify, so in `ask` and `auto` it
|
|
51
|
+
* asks the user about every `bash`, `write`, and `edit` call.
|
|
52
|
+
*/
|
|
53
|
+
readonly judge?: JevJudge;
|
|
54
|
+
/**
|
|
55
|
+
* What the user has said in this conversation: the first question, every follow-up, every steer. Jev judges
|
|
56
|
+
* the call against all of it. The host feeds it from the user's own input, so AutoRAG's internal phase
|
|
57
|
+
* prompts are never in it.
|
|
58
|
+
*/
|
|
59
|
+
readonly requests?: UserRequestLog;
|
|
60
|
+
/** Cap on the state shown to Jev, in characters. Default: Jev's context ceiling with a safety margin. */
|
|
61
|
+
readonly maxStateChars?: number;
|
|
62
|
+
/** Files the agent may always write and edit without Jev being asked (the config its self-configuration turn edits). */
|
|
63
|
+
readonly trustedPaths?: readonly string[];
|
|
64
|
+
}
|
|
65
|
+
/** Appended to the system prompt while a gate is active, so the model stays on the happy path. */
|
|
66
|
+
export declare const PERMISSION_PROMPT_ADDENDUM: string;
|
|
67
|
+
/** `ask` addendum: the user sees every call, so the model should batch work and still not refuse requests. */
|
|
68
|
+
export declare const ASK_PROMPT_ADDENDUM: string;
|
|
69
|
+
/**
|
|
70
|
+
* pi extension that gates what the agent does to existing files.
|
|
71
|
+
*
|
|
72
|
+
* Every `bash`, `write`, `edit`, and `manage_automations save` call is gated (reads, searches, and other tools
|
|
73
|
+
* never touch originals and are not asked about). In `ask` each one is put to the user. In `auto` Jev
|
|
74
|
+
* classifies it first: a call it finds safe runs, one it flags is approved by Jev when the user's request
|
|
75
|
+
* clearly covers it, and otherwise put to the user. Shift+Tab and `/permissions` switch the mode; the footer
|
|
76
|
+
* shows it.
|
|
77
|
+
*/
|
|
78
|
+
export declare function createPermissionGate(options: PermissionGateOptions): ExtensionFactory;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { SessionEntry } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import type { JevJudge } from "./jev-extension.js";
|
|
3
|
+
import { type ProposedCall } from "./permission-paths.js";
|
|
4
|
+
import { type UserRequest } from "./user-requests.js";
|
|
5
|
+
/**
|
|
6
|
+
* What a tool call does to the user's existing files, as Jev judges it. A call can be several at once
|
|
7
|
+
* (`mkdir x && mv a x/ && rm b` is a move and a delete).
|
|
8
|
+
*
|
|
9
|
+
* `unclear` is for code whose effect cannot be told from what is shown: an unseen script file, `make clean`,
|
|
10
|
+
* an encoded command. It is asked about like any other category.
|
|
11
|
+
*/
|
|
12
|
+
export declare const PERMISSION_KINDS: readonly ["delete", "move", "rename", "overwrite", "edit", "unclear"];
|
|
13
|
+
export type PermissionKind = (typeof PERMISSION_KINDS)[number];
|
|
14
|
+
export declare function permissionKindQuestionId(kind: PermissionKind): string;
|
|
15
|
+
/** Jev question id of the "may this run without asking?" check that `auto` mode adds to the same batch. */
|
|
16
|
+
export declare const PERMISSION_GATE_QUESTION_ID = "permission_gate";
|
|
17
|
+
/** Jev must be at least this sure before `auto` skips the user. Stricter than jev-use's own 0.5 default. */
|
|
18
|
+
export declare const AUTO_APPROVE_MIN_CONFIDENCE = 0.8;
|
|
19
|
+
/**
|
|
20
|
+
* Largest state the gate shows Jev, in characters. jev-use hands every question back ("oversized") once the
|
|
21
|
+
* state passes {@link DEFAULT_MAX_STATE_TOKENS} estimated tokens (about 4 characters each), and then the gate
|
|
22
|
+
* could not classify anything. The ceiling is read from jev-use so it cannot drift, and 10% is left for
|
|
23
|
+
* jev-use's own estimate being rough.
|
|
24
|
+
*/
|
|
25
|
+
export declare const DEFAULT_MAX_STATE_CHARS: number;
|
|
26
|
+
/** The tool calls the gate classifies. Everything else (reads, searches, MCP tools) never touches originals. */
|
|
27
|
+
export declare function isGatedCall(toolName: string, input: Readonly<Record<string, unknown>>): boolean;
|
|
28
|
+
/** One line (or the command) naming what a call does, for the approval dialog and the notice. */
|
|
29
|
+
export declare function summarizeCall(call: ProposedCall): string;
|
|
30
|
+
/** The earlier calls of this session that ran and succeeded, oldest first. */
|
|
31
|
+
export declare function successfulCalls(branch: readonly SessionEntry[]): ProposedCall[];
|
|
32
|
+
export interface JudgedState {
|
|
33
|
+
readonly call: ProposedCall;
|
|
34
|
+
readonly requests: readonly UserRequest[];
|
|
35
|
+
readonly history: readonly ProposedCall[];
|
|
36
|
+
readonly maxStateChars: number;
|
|
37
|
+
/** Whether the agent itself brought this path into existence earlier in the session. */
|
|
38
|
+
readonly isCreated?: (path: string) => boolean;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The state Jev judges, within `maxStateChars`: how to judge, what the user said, what the agent already did,
|
|
42
|
+
* and the call itself. The call and the history are cut first (the call to 40% of the budget, the history to
|
|
43
|
+
* 20%, each keeping the start and end), and the conversation gets whatever is left, so the whole stays under
|
|
44
|
+
* the ceiling however long any one part is.
|
|
45
|
+
*/
|
|
46
|
+
export declare function buildJudgedState({ call, requests, history, maxStateChars, isCreated }: JudgedState): string;
|
|
47
|
+
export interface FlaggedKind {
|
|
48
|
+
readonly kind: PermissionKind;
|
|
49
|
+
/** Jev's probability that the call is in this category; undefined when Jev was unsure and gave none. */
|
|
50
|
+
readonly probability: number | undefined;
|
|
51
|
+
}
|
|
52
|
+
export interface Approval {
|
|
53
|
+
readonly approved: boolean;
|
|
54
|
+
/** Why not, when it was not approved. */
|
|
55
|
+
readonly why: string;
|
|
56
|
+
}
|
|
57
|
+
/** Jev's reading of one call, or the reason it could not give one. */
|
|
58
|
+
export type Classification = {
|
|
59
|
+
readonly status: "classified";
|
|
60
|
+
readonly flagged: readonly FlaggedKind[];
|
|
61
|
+
readonly approval: Approval;
|
|
62
|
+
} | {
|
|
63
|
+
readonly status: "failed";
|
|
64
|
+
readonly why: string;
|
|
65
|
+
};
|
|
66
|
+
export type ClassifyOptions = JudgedState;
|
|
67
|
+
/**
|
|
68
|
+
* Asks Jev what `options.call` does to existing files, in one batched request. Never throws: no answer
|
|
69
|
+
* (unreachable, timed out, oversized, a missing verdict) is a `failed` classification, and the gate then
|
|
70
|
+
* asks the user instead of letting the call through.
|
|
71
|
+
*/
|
|
72
|
+
export declare function classifyCall(judge: JevJudge, options: ClassifyOptions): Promise<Classification>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** A tool call the gate is about to judge. */
|
|
2
|
+
export interface ProposedCall {
|
|
3
|
+
readonly tool: string;
|
|
4
|
+
readonly input: Readonly<Record<string, unknown>>;
|
|
5
|
+
readonly cwd: string;
|
|
6
|
+
}
|
|
7
|
+
/** `raw` as an absolute path: relative to `cwd`, with `~` expanded. */
|
|
8
|
+
export declare function resolveToolPath(raw: string, cwd: string): string;
|
|
9
|
+
export interface NamedPath {
|
|
10
|
+
readonly path: string;
|
|
11
|
+
/**
|
|
12
|
+
* True when the word is certainly a path (absolute, `~/`, `./`, `../`, a file name with an extension) or
|
|
13
|
+
* names something that exists. A plain word that exists nowhere (`fresh` in `mkdir fresh`) is only a
|
|
14
|
+
* candidate: the gate watches whether the call brings it into existence, and shows it to Jev only then.
|
|
15
|
+
*/
|
|
16
|
+
readonly always: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The paths a call names, for the facts Jev is shown (does each exist, did the agent make it). This does not
|
|
20
|
+
* decide anything and does not understand the command: it picks out the words that look like paths. A word it
|
|
21
|
+
* misses is a fact Jev lacks; a word it wrongly takes is a harmless "does not exist" line.
|
|
22
|
+
*/
|
|
23
|
+
export declare function pathsNamedBy(call: ProposedCall): NamedPath[];
|
|
@@ -81,11 +81,19 @@ export interface AutoRAGPiInteractiveRuntimeOptions extends Omit<AutoRAGPiSessio
|
|
|
81
81
|
* launch.
|
|
82
82
|
*/
|
|
83
83
|
readonly updateNotice?: () => Promise<string | undefined>;
|
|
84
|
+
/**
|
|
85
|
+
* AutoRAG version shown on the welcome banner. Set only by the TUI: when present,
|
|
86
|
+
* every session start (launch, `/new`, `/resume`, `/reload`) replaces pi's startup
|
|
87
|
+
* header with the AutoRAG banner and hides pi's loaded-resource listing.
|
|
88
|
+
*/
|
|
89
|
+
readonly welcomeVersion?: string;
|
|
84
90
|
}
|
|
85
91
|
export interface AutoRAGPiSession {
|
|
86
92
|
readonly session: AgentSession;
|
|
87
93
|
readonly baseToolNames: readonly string[];
|
|
88
94
|
readonly sessionFile: string | undefined;
|
|
95
|
+
/** Stops what extensions started (MCP server processes), then disposes the session. */
|
|
96
|
+
readonly dispose: () => Promise<void>;
|
|
89
97
|
}
|
|
90
98
|
/** Adapts a pi-agent-core {@link AgentTool} to pi's extension {@link ToolDefinition}. */
|
|
91
99
|
export declare function toToolDefinition(tool: AgentTool): ToolDefinition;
|
|
@@ -6,11 +6,17 @@ import type { JevJudge } from "./jev-extension.js";
|
|
|
6
6
|
* Local retrieval runs first; web search is left to the agent after the fast
|
|
7
7
|
* answer, when local evidence falls short.
|
|
8
8
|
* - `direct`: intrinsic knowledge or small talk the model answers on its own.
|
|
9
|
+
* - `organize`: the user wants files or folders acted on — move, rename in
|
|
10
|
+
* bulk, rename by content, convert, sort, tidy — rather than information
|
|
11
|
+
* found. No retrieval and no verification: one tool-capable turn does it.
|
|
12
|
+
* - `extra`: none of the other branches (committing code, opening a pull
|
|
13
|
+
* request, running a build, any other task for the agent's tools). The Jev
|
|
14
|
+
* gate is skipped: no retrieval, no verification, tools stay available.
|
|
9
15
|
* - `config`: the user wants to inspect or change AutoRAG's own settings
|
|
10
16
|
* (model, providers, datasources). Offered only when the host enables
|
|
11
17
|
* agent self-configuration.
|
|
12
18
|
*/
|
|
13
|
-
export type QueryRoute = "local" | "direct" | "config";
|
|
19
|
+
export type QueryRoute = "local" | "direct" | "organize" | "extra" | "config";
|
|
14
20
|
/** Jev question id of the intrinsic-knowledge / local branch. */
|
|
15
21
|
export declare const QUERY_ROUTE_QUESTION_ID = "route";
|
|
16
22
|
/** Jev question id of the "does this need decomposition?" check. */
|
|
@@ -23,15 +29,6 @@ export declare const FALLBACK_QUERY_ROUTE: QueryRoute;
|
|
|
23
29
|
export declare const DECOMPOSE_PROBABILITY_THRESHOLD = 0.5;
|
|
24
30
|
/** A `noul` probability at or above this sends the fast answer on to verification. */
|
|
25
31
|
export declare const FOLLOW_UP_PROBABILITY_THRESHOLD = 0.5;
|
|
26
|
-
/**
|
|
27
|
-
* Minimum Jev branch probability required to leave local search. A `direct`
|
|
28
|
-
* branch at or below this floor — or one Jev reported without a probability —
|
|
29
|
-
* keeps the run on local search, the corpus-grounded default.
|
|
30
|
-
* Without the floor a weakly-favored `direct` verdict (observed at p 0.57-0.63
|
|
31
|
-
* on personal-corpus questions) skips retrieval entirely and answers from
|
|
32
|
-
* general knowledge, so the caller loses the evidence the question depends on.
|
|
33
|
-
*/
|
|
34
|
-
export declare const NON_LOCAL_ROUTE_PROBABILITY_THRESHOLD = 0.75;
|
|
35
32
|
/** A `noul` probability at or above this searches that datasource before the fast answer. */
|
|
36
33
|
export declare const DATASOURCE_PROBABILITY_THRESHOLD = 0.5;
|
|
37
34
|
/** Jev question id of the "search this datasource?" check for one datasource. */
|
|
@@ -52,11 +49,11 @@ export interface FollowUpDecision {
|
|
|
52
49
|
*/
|
|
53
50
|
export declare function needsFollowUp(judge: JevJudge, query: string, answer: string): Promise<FollowUpDecision>;
|
|
54
51
|
export interface QueryRouteDecision {
|
|
55
|
-
/** Most probable branch; {@link FALLBACK_QUERY_ROUTE} when Jev gave none
|
|
52
|
+
/** Most probable branch; {@link FALLBACK_QUERY_ROUTE} when Jev gave none. */
|
|
56
53
|
readonly route: QueryRoute;
|
|
57
|
-
/** True when Jev judged the question needs decomposition (
|
|
54
|
+
/** True when Jev judged the question needs decomposition (only ever for `local`). */
|
|
58
55
|
readonly decompose: boolean;
|
|
59
|
-
/** Probability Jev gave the winning branch
|
|
56
|
+
/** Probability Jev gave the winning branch; absent when Jev reported none. */
|
|
60
57
|
readonly routeProbability?: number;
|
|
61
58
|
/** Jev's P(decomposition needed), when it answered. */
|
|
62
59
|
readonly decomposeProbability?: number;
|
|
@@ -69,10 +66,10 @@ export interface RouteQueryOptions {
|
|
|
69
66
|
}
|
|
70
67
|
/**
|
|
71
68
|
* Ask Jev, in one batched call about the user question, which branch answers
|
|
72
|
-
* it and whether it needs decomposition.
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
69
|
+
* it and whether it needs decomposition. The most probable branch wins, with
|
|
70
|
+
* no confidence floor. Never throws: a missing credential, an unreachable
|
|
71
|
+
* backend, or an unusable verdict falls back to a single local search, with
|
|
72
|
+
* the reason recorded.
|
|
76
73
|
*/
|
|
77
74
|
export declare function routeQuery(judge: JevJudge, query: string, options?: RouteQueryOptions): Promise<QueryRouteDecision>;
|
|
78
75
|
/** One configured datasource Jev may send the question to. */
|
|
@@ -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" | "no-verified-results" | "unknown-warning" | "caller-tool-dropped" | "minsync-staging-excluded" | "minsync-file-skipped" | "minsync-sync-failed" | "minsync-lock-held" | "embedder-unavailable" | "embedding-identity-mismatch" | "lexical-tokenizer-unavailable" | "parser-skipped" | "parser-failed" | "parser-crashed" | "source-vanished" | "source-unreadable" | "source-read-failed" | "mirror-write-failed" | "parser-warning" | "duplicate-excluded" | "unsupported-file" | "stale-index" | "deleted-mirror" | "search-root-unavailable" | "mass-delete-suppressed" | "walk-truncated" | "directory-unreadable" | "pdf-extract-thin" | "retrieval-method-failed" | "rerank-failed" | "jikji-unavailable" | "jikji-prepare-failed" | "jikji-find-failed" | "everything-index-failed" | "fsearch-index-failed" | "fsearch-binary-missing" | "refresh-failed" | "refresh-interrupted" | "watch-failed" | "watch-limited" | "unknown-datasource-skill" | "no-final-answer" | "model-request-failed" | "tool-call-burst" | "query-routed" | "query-route-fallback" | "query-decomposition-failed" | "follow-up-skipped" | "follow-up-check-fallback" | "datasources-selected" | "datasource-selection-fallback" | "citation-without-result" | "evidence-judged" | "evidence-judgment-fallback" | "memory-search-fallback" | "self-config-unavailable" | "self-config-rolled-back" | "embedding-unavailable";
|
|
12
|
+
export type SearchDocumentDiagnosticCode = "empty-query" | "no-verified-results" | "unknown-warning" | "caller-tool-dropped" | "minsync-staging-excluded" | "minsync-file-skipped" | "minsync-sync-failed" | "minsync-lock-held" | "embedder-unavailable" | "embedding-identity-mismatch" | "lexical-tokenizer-unavailable" | "parser-skipped" | "parser-failed" | "parser-crashed" | "source-vanished" | "source-unreadable" | "source-read-failed" | "mirror-write-failed" | "parser-warning" | "duplicate-excluded" | "unsupported-file" | "stale-index" | "deleted-mirror" | "search-root-unavailable" | "mass-delete-suppressed" | "walk-truncated" | "directory-unreadable" | "pdf-extract-thin" | "retrieval-method-failed" | "rerank-failed" | "jikji-unavailable" | "jikji-prepare-failed" | "jikji-find-failed" | "everything-index-failed" | "fsearch-index-failed" | "fsearch-binary-missing" | "refresh-failed" | "refresh-interrupted" | "watch-failed" | "watch-limited" | "unknown-datasource-skill" | "no-final-answer" | "model-request-failed" | "tool-call-burst" | "query-routed" | "query-route-fallback" | "query-decomposition-failed" | "follow-up-skipped" | "follow-up-check-fallback" | "datasources-selected" | "datasource-selection-fallback" | "citation-without-result" | "citation-irrelevant" | "citation-relevance-fallback" | "evidence-judged" | "evidence-judgment-fallback" | "memory-search-fallback" | "self-config-unavailable" | "self-config-rolled-back" | "embedding-unavailable";
|
|
13
13
|
export interface SearchDocumentDiagnostic {
|
|
14
14
|
readonly code: SearchDocumentDiagnosticCode;
|
|
15
15
|
readonly severity: SearchDocumentDiagnosticSeverity;
|