@autorag/librarian 2.10.6 → 2.11.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 +8 -0
- package/README.md +46 -7
- package/dist/agent/agent.d.ts +6 -1
- package/dist/agent/answer-guidelines.d.ts +22 -1
- package/dist/agent/mcp-client.d.ts +27 -0
- package/dist/agent/pi-session.d.ts +8 -0
- package/dist/agent/search-progress.d.ts +96 -0
- package/dist/agent/welcome-header.d.ts +35 -0
- package/dist/cli/commands/setup.d.ts +2 -0
- package/dist/cli/index.js +11740 -10176
- package/dist/cli/setup.d.ts +9 -0
- package/dist/core.js +1841 -865
- 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/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/index.js +1894 -915
- package/dist/mcp/index.js +1891 -915
- package/dist/minsync/workspace-lock.d.ts +7 -0
- package/dist/process/terminate-tree.d.ts +4 -5
- package/licenses/hister-AGPL-3.0-notice.txt +47 -0
- package/package.json +2 -2
- package/skills/autorag/SKILL.md +6 -3
- package/skills/autorag-doctor/SKILL.md +5 -4
- package/skills/autorag-lite-setup/SKILL.md +23 -5
- package/skills/autorag-setup/SKILL.md +60 -3
- package/dist/datasource/skills/obsidian/client.d.ts +0 -15
- package/dist/datasource/skills/obsidian/types.d.ts +0 -92
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* pipeline reports the surface as unsearched and hands the operator the CLI's
|
|
7
7
|
* own words: failure kind, exit status, and stderr verbatim.
|
|
8
8
|
*/
|
|
9
|
-
/** The failure payload every datasource CLI client returns (lazykatok, discrawl,
|
|
9
|
+
/** The failure payload every datasource CLI client returns (lazykatok, discrawl, mailcrawl, …). */
|
|
10
10
|
export interface DatasourceCliFailure {
|
|
11
11
|
readonly reason: string;
|
|
12
12
|
readonly stderr?: string;
|
|
@@ -10,13 +10,14 @@ export { CLOUD_DRIVE_SKILL_DEFINITION, CloudDriveSkill, type CloudDriveSkillOpti
|
|
|
10
10
|
export { DEFAULT_DISCRAWL_EMBEDDING_MODEL, DEFAULT_DISCRAWL_MODE, DiscrawlClient, type DiscrawlFailureReason, DiscrawlFtsMethod, DiscrawlHybridMethod, type DiscrawlOptions, type DiscrawlSearchHit, type DiscrawlSearchMode, type DiscrawlSearchOptions, type DiscrawlSearchResult, DiscrawlSemanticMethod, DiscrawlSkill, type DiscrawlSkillClient, type DiscrawlSkillOptions, ENGLISH_ONLY_EMBEDDING_MODELS, } from "./skills/discrawl/index.js";
|
|
11
11
|
export { BUILTIN_DATASOURCE_SKILL_NAMES, type BuildDatasourceSkillsResult, buildDatasourceSkills, type DatasourceSkillConfig, type DatasourcesConfig, } from "./skills/factory.js";
|
|
12
12
|
export { GitHubConnector, type GitHubConnectorOptions, GitHubSkill, type GitHubSkillOptions, } from "./skills/github/index.js";
|
|
13
|
+
export { HISTER_SKILL_TYPE, HisterClient, type HisterClientOptions, HisterSkill, type HisterSkillOptions, } from "./skills/hister/index.js";
|
|
13
14
|
export { LarkClient, type LarkClientOptions, LarkSkill, type LarkSkillOptions } from "./skills/lark/index.js";
|
|
14
15
|
export type { LazykatokFailureReason, LazykatokHit, LazykatokOptions, LazykatokSearchMode, LazykatokSearchOptions, LazykatokSearchResult, LazykatokSkillClient, LazykatokSkillOptions, } from "./skills/lazykatok/index.js";
|
|
15
16
|
export { LazykatokBm25Method, LazykatokClient, LazykatokSemanticMethod, LazykatokSkill, } from "./skills/lazykatok/index.js";
|
|
16
17
|
export { MailExportConnector, type MailExportConnectorOptions, MailExportSkill, type MailExportSkillOptions, } from "./skills/mail-export/index.js";
|
|
17
18
|
export { MAILCRAWL_MODES, MailcrawlClient, type MailcrawlFailure, type MailcrawlFailureReason, type MailcrawlIndexInfo, MailcrawlMethod, type MailcrawlOptions, type MailcrawlSearchHit, type MailcrawlSearchMode, type MailcrawlSearchResult, MailcrawlSkill, type MailcrawlSyncInfo, type MailcrawlSyncResult, } from "./skills/mailcrawl/index.js";
|
|
18
19
|
export { NotcrawlClient, type NotcrawlOptions, NotionSkill, type NotionSkillOptions, } from "./skills/notion/index.js";
|
|
19
|
-
export { ObsidianBm25Method,
|
|
20
|
+
export { ObsidianBm25Method, type ObsidianMethodOptions, ObsidianSemanticMethod, ObsidianSkill, type ObsidianSkillOptions, } from "./skills/obsidian/index.js";
|
|
20
21
|
export { RssConnector, type RssConnectorOptions, type RssFeedConfig, RssSkill, type RssSkillOptions, } from "./skills/rss/index.js";
|
|
21
22
|
export { SlackSkill, type SlackSkillOptions, SlacrawlClient, type SlacrawlOptions, } from "./skills/slack/index.js";
|
|
22
23
|
export { SpotlightConnector, type SpotlightConnectorOptions, SpotlightSkill, type SpotlightSkillOptions, } from "./skills/spotlight/index.js";
|
|
@@ -11,6 +11,7 @@ import type { Embedder } from "../../embedding/embedder.js";
|
|
|
11
11
|
import type { EmbeddingEndpointSource } from "../embedding-env.js";
|
|
12
12
|
import type { DatasourceSkill } from "../types.js";
|
|
13
13
|
import { type DiscrawlEmbeddingRuntime } from "./discrawl/index.js";
|
|
14
|
+
import { type ObsidianMinSyncOptions } from "./obsidian/index.js";
|
|
14
15
|
/** One configured datasource entry (the trusted `datasources.<name>` value). */
|
|
15
16
|
export interface DatasourceSkillConfig {
|
|
16
17
|
readonly enabled?: boolean;
|
|
@@ -46,6 +47,8 @@ export interface DatasourceEmbeddingOptions {
|
|
|
46
47
|
readonly discrawl?: DiscrawlEmbeddingRuntime | (() => Promise<DiscrawlEmbeddingRuntime | undefined>);
|
|
47
48
|
/** For CLIs that embed for themselves through env (mailcrawl, lazykatok): where the shared backend is. */
|
|
48
49
|
readonly cliEndpoint?: EmbeddingEndpointSource;
|
|
50
|
+
/** MinSync binary, embedder and chunking shared with the local-file index; vault indexes run on it too. */
|
|
51
|
+
readonly minSync?: ObsidianMinSyncOptions;
|
|
49
52
|
}
|
|
50
53
|
/** Skill names this factory can build. */
|
|
51
54
|
export declare const BUILTIN_DATASOURCE_SKILL_NAMES: readonly string[];
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client for a running Hister server (https://github.com/asciimoo/hister, AGPL-3.0).
|
|
3
|
+
*
|
|
4
|
+
* Hister is a separate program. AutoRAG never links, embeds, copies, or modifies its code: this file speaks
|
|
5
|
+
* Hister's public `GET /search` and `GET /api/config` JSON endpoints over HTTP, exactly like Hister's own
|
|
6
|
+
* `hister search` CLI. Hister owns its index, its browser-extension capture, its credentials, and its embeddings.
|
|
7
|
+
*/
|
|
8
|
+
export interface HisterClientOptions {
|
|
9
|
+
/** Hister server, default `http://127.0.0.1:4433`. */
|
|
10
|
+
readonly baseUrl?: string;
|
|
11
|
+
/** Name of the environment variable holding Hister's `app.access_token`. The token itself is never configured. */
|
|
12
|
+
readonly tokenEnv?: string;
|
|
13
|
+
readonly timeoutMs?: number;
|
|
14
|
+
readonly fetchImpl?: typeof fetch;
|
|
15
|
+
readonly env?: Readonly<Record<string, string | undefined>>;
|
|
16
|
+
}
|
|
17
|
+
export interface HisterHit {
|
|
18
|
+
readonly url: string;
|
|
19
|
+
readonly domain: string;
|
|
20
|
+
readonly title: string;
|
|
21
|
+
/** Highlighted-mark-free snippet (or the matched semantic chunk). */
|
|
22
|
+
readonly snippet: string;
|
|
23
|
+
readonly score: number;
|
|
24
|
+
/** Epoch ms of the last visit/update. */
|
|
25
|
+
readonly updatedAt: number | undefined;
|
|
26
|
+
readonly addedAt: number | undefined;
|
|
27
|
+
readonly language: string | undefined;
|
|
28
|
+
readonly description: string | undefined;
|
|
29
|
+
}
|
|
30
|
+
export type HisterFailureKind = "unavailable" | "auth" | "http" | "invalid-output" | "semantic-disabled";
|
|
31
|
+
export interface HisterFailure {
|
|
32
|
+
readonly ok: false;
|
|
33
|
+
readonly kind: HisterFailureKind;
|
|
34
|
+
/** Verbatim: HTTP status and body, or the connection error. */
|
|
35
|
+
readonly message: string;
|
|
36
|
+
}
|
|
37
|
+
export type HisterResult<T> = {
|
|
38
|
+
readonly ok: true;
|
|
39
|
+
readonly value: T;
|
|
40
|
+
} | HisterFailure;
|
|
41
|
+
export interface HisterSearchOptions {
|
|
42
|
+
readonly topK?: number;
|
|
43
|
+
readonly signal?: AbortSignal;
|
|
44
|
+
/** Restrict to one domain (exact match, Hister `domain:`). */
|
|
45
|
+
readonly domain?: string;
|
|
46
|
+
}
|
|
47
|
+
export declare class HisterClient {
|
|
48
|
+
readonly baseUrl: string;
|
|
49
|
+
private readonly tokenEnv;
|
|
50
|
+
private readonly timeoutMs;
|
|
51
|
+
private readonly fetchImpl;
|
|
52
|
+
private readonly env;
|
|
53
|
+
constructor(options?: HisterClientOptions);
|
|
54
|
+
/** Lexical search over web pages only. */
|
|
55
|
+
searchLexical(query: string, options?: HisterSearchOptions): Promise<HisterResult<readonly HisterHit[]>>;
|
|
56
|
+
/**
|
|
57
|
+
* Semantic search. Hister embeds the query itself through the endpoint the operator configured on the server;
|
|
58
|
+
* AutoRAG sends only the question text. `semantic_hits` carry the matched chunk and similarity.
|
|
59
|
+
*/
|
|
60
|
+
searchSemantic(query: string, options?: HisterSearchOptions): Promise<HisterResult<readonly HisterHit[]>>;
|
|
61
|
+
/** Count documents matching a Hister query. */
|
|
62
|
+
count(text: string, signal?: AbortSignal): Promise<HisterResult<number>>;
|
|
63
|
+
/** Reachability and authentication probe. Returns Hister's `/api/config` body. */
|
|
64
|
+
config(signal?: AbortSignal): Promise<HisterResult<Record<string, unknown>>>;
|
|
65
|
+
private search;
|
|
66
|
+
private request;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Wrap a free-text question as a Hister query confined to web pages.
|
|
70
|
+
*
|
|
71
|
+
* Hister ANDs bare terms, so a natural-language question would match almost nothing. Plain words become one
|
|
72
|
+
* alternation group `(a|b|c)`. That pipe is Hister's only OR: the word `OR` is not an operator there, it is searched
|
|
73
|
+
* as the literal English word, which matches most English pages. Hister's own syntax (quoted phrases,
|
|
74
|
+
* `field:value`, wildcards, negation) passes through untouched, and a query using any of it is sent with its plain
|
|
75
|
+
* words ANDed, exactly as written. A `sort:` directive is hoisted out of the group because Hister only honours it at
|
|
76
|
+
* the top level.
|
|
77
|
+
*/
|
|
78
|
+
export declare function buildWebQuery(question: string, domain?: string): string | undefined;
|
|
79
|
+
/** Hister snippets carry `<mark>` highlights and HTML entities; the model reads plain text. */
|
|
80
|
+
export declare function plainSnippet(snippet: string): string;
|
|
81
|
+
/** Stable, opaque id for one page: the same URL always maps to the same chunk id. */
|
|
82
|
+
export declare function pageId(url: string): string;
|
|
83
|
+
export declare function isLoopback(hostname: string): boolean;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sharing AutoRAG's embedding backend with Hister.
|
|
3
|
+
*
|
|
4
|
+
* Hister keeps its own vector store and embeds with whatever `semantic_search` in its config.yml names, so the
|
|
5
|
+
* only way the two can use one model is to copy the shared endpoint (the `minsync serve` daemon by default) into
|
|
6
|
+
* that block. Mismatched models are not an error anywhere: the vectors simply do not line up and results degrade
|
|
7
|
+
* silently. This module derives the block from {@link ResolvedEmbeddingEndpoint}, reads what Hister currently has,
|
|
8
|
+
* and rewrites only the six keys involved. Hister itself is never modified; its config.yml is its documented
|
|
9
|
+
* interface.
|
|
10
|
+
*
|
|
11
|
+
* `yaml` is a dev dependency of this package, so the file is edited line by line. Only the `semantic_search`
|
|
12
|
+
* block's own keys are touched and every other byte is preserved; the tests compare the result with a real YAML
|
|
13
|
+
* parser.
|
|
14
|
+
*/
|
|
15
|
+
import type { ResolvedEmbeddingEndpoint } from "../../embedding-env.js";
|
|
16
|
+
/** The `semantic_search` keys that must agree with the shared embedding backend. */
|
|
17
|
+
export interface HisterSemanticSettings {
|
|
18
|
+
readonly enable: boolean;
|
|
19
|
+
readonly embedding_endpoint: string;
|
|
20
|
+
readonly embedding_model: string;
|
|
21
|
+
readonly dimensions: number;
|
|
22
|
+
readonly query_prefix: string;
|
|
23
|
+
readonly document_prefix: string;
|
|
24
|
+
}
|
|
25
|
+
export type HisterSemanticKey = keyof HisterSemanticSettings;
|
|
26
|
+
/**
|
|
27
|
+
* What Hister uses when its config does not say (v0.20.0 `config.go`): semantic search off, an Ollama endpoint, and
|
|
28
|
+
* a `query: ` prefix. Used only to report a missing key; the apply step always writes every key.
|
|
29
|
+
*/
|
|
30
|
+
export declare const HISTER_SEMANTIC_DEFAULTS: HisterSemanticSettings;
|
|
31
|
+
export type DeriveResult = {
|
|
32
|
+
readonly ok: true;
|
|
33
|
+
readonly settings: HisterSemanticSettings;
|
|
34
|
+
} | {
|
|
35
|
+
readonly ok: false;
|
|
36
|
+
readonly reason: string;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* The settings that make Hister embed exactly like AutoRAG does. Refuses what Hister cannot do faithfully:
|
|
40
|
+
* - a TEI endpoint (Hister only calls the OpenAI `/v1/embeddings` route);
|
|
41
|
+
* - a remote endpoint (browsing text would leave the machine, and Hister's config would have to hold the key).
|
|
42
|
+
*/
|
|
43
|
+
export declare function deriveHisterSemanticSettings(endpoint: ResolvedEmbeddingEndpoint): DeriveResult;
|
|
44
|
+
export declare function differingSemanticKeys(current: HisterSemanticSettings, wanted: HisterSemanticSettings): readonly HisterSemanticKey[];
|
|
45
|
+
export declare function reindexRequired(changed: readonly HisterSemanticKey[]): boolean;
|
|
46
|
+
export type ReadResult = {
|
|
47
|
+
readonly ok: true;
|
|
48
|
+
readonly settings: HisterSemanticSettings;
|
|
49
|
+
/** Keys the file sets itself; the rest are Hister's defaults. */
|
|
50
|
+
readonly explicit: readonly HisterSemanticKey[];
|
|
51
|
+
} | {
|
|
52
|
+
readonly ok: false;
|
|
53
|
+
readonly reason: string;
|
|
54
|
+
};
|
|
55
|
+
export declare function readHisterSemanticSettings(text: string): ReadResult;
|
|
56
|
+
export type ApplyResult = {
|
|
57
|
+
readonly ok: true;
|
|
58
|
+
readonly text: string;
|
|
59
|
+
} | {
|
|
60
|
+
readonly ok: false;
|
|
61
|
+
readonly reason: string;
|
|
62
|
+
};
|
|
63
|
+
/** Set every {@link KEYS} entry inside `semantic_search`, creating the block when it is absent. */
|
|
64
|
+
export declare function applyHisterSemanticSettings(text: string, settings: HisterSemanticSettings): ApplyResult;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { buildWebQuery, HisterClient, type HisterClientOptions, type HisterFailure, type HisterFailureKind, type HisterHit, type HisterResult, type HisterSearchOptions, pageId, } from "./client.js";
|
|
2
|
+
export { HISTER_SKILL_TYPE, HisterSkill, type HisterSkillOptions } from "./skill.js";
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `autorag setup` support for the Hister datasource: is Hister installed and running, and does it embed with the
|
|
3
|
+
* same model as the rest of AutoRAG?
|
|
4
|
+
*
|
|
5
|
+
* Detection never writes anything. Writing Hister's config and restarting its service only happen when the operator
|
|
6
|
+
* passes `--sync-hister`, because that file and that login item belong to Hister and its operator. Hister is never
|
|
7
|
+
* modified; this only edits its documented config.yml, keeps a backup first, and restarts the service the same way
|
|
8
|
+
* the operator would.
|
|
9
|
+
*/
|
|
10
|
+
import type { ManagedEmbedder } from "../../../embedding/embedder.js";
|
|
11
|
+
import { type HisterSemanticKey } from "./embedding.js";
|
|
12
|
+
export interface HisterSetupEmbedding {
|
|
13
|
+
/** Hister's config already matches the shared embedding backend. */
|
|
14
|
+
readonly inSync: boolean;
|
|
15
|
+
/** `semantic_search` keys that differ from the shared backend, sorted. */
|
|
16
|
+
readonly differs: readonly HisterSemanticKey[];
|
|
17
|
+
/** Hister's config file was rewritten by this run. */
|
|
18
|
+
readonly applied: boolean;
|
|
19
|
+
/** Hister must be restarted to read the new config (it was not, or could not be). */
|
|
20
|
+
readonly restartRequired?: boolean;
|
|
21
|
+
/** Existing pages must be re-embedded (`hister reindex`) and that was not done. */
|
|
22
|
+
readonly reindexRequired?: boolean;
|
|
23
|
+
readonly reason?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface HisterSetupReport {
|
|
26
|
+
readonly datasource: string;
|
|
27
|
+
readonly installed: boolean;
|
|
28
|
+
readonly running?: boolean;
|
|
29
|
+
readonly configPath?: string;
|
|
30
|
+
readonly embedding?: HisterSetupEmbedding;
|
|
31
|
+
readonly reason?: string;
|
|
32
|
+
/** What the operator (or an agent) should run next. */
|
|
33
|
+
readonly remediation?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface HisterServiceDeps {
|
|
36
|
+
/** Hister's config.yml path, or undefined when it cannot be determined. */
|
|
37
|
+
readonly configPath?: () => string | undefined;
|
|
38
|
+
/** `GET /api/config` against the datasource's baseUrl. */
|
|
39
|
+
readonly health?: (baseUrl: string) => Promise<{
|
|
40
|
+
readonly reachable: boolean;
|
|
41
|
+
readonly semanticEnabled?: boolean;
|
|
42
|
+
readonly reason?: string;
|
|
43
|
+
}>;
|
|
44
|
+
/** Restart the Hister service. Omitted means the operator must do it. */
|
|
45
|
+
readonly restart?: () => Promise<{
|
|
46
|
+
readonly ok: boolean;
|
|
47
|
+
readonly reason?: string;
|
|
48
|
+
}>;
|
|
49
|
+
/** `hister reindex` against the running server. Omitted means the operator must do it. */
|
|
50
|
+
readonly reindex?: (baseUrl: string) => Promise<{
|
|
51
|
+
readonly ok: boolean;
|
|
52
|
+
readonly reason?: string;
|
|
53
|
+
}>;
|
|
54
|
+
readonly now?: () => number;
|
|
55
|
+
/** Pause between polls while a restarted server comes up. Tests replace it. */
|
|
56
|
+
readonly sleep?: (ms: number) => Promise<void>;
|
|
57
|
+
/** How long to wait for a restarted server before giving up on the reindex. Default 30s. */
|
|
58
|
+
readonly waitMs?: number;
|
|
59
|
+
}
|
|
60
|
+
interface HisterEntry {
|
|
61
|
+
readonly name: string;
|
|
62
|
+
readonly baseUrl: string;
|
|
63
|
+
readonly semantic: boolean;
|
|
64
|
+
readonly tokenEnv?: string;
|
|
65
|
+
}
|
|
66
|
+
/** The first configured `hister` datasource (by template `type` or by name), with its connector options. */
|
|
67
|
+
export declare function findHisterEntries(raw: Record<string, unknown>): readonly HisterEntry[];
|
|
68
|
+
/** Where Hister reads its config on this platform, in the order Hister itself searches (docs/configuration). */
|
|
69
|
+
export declare function defaultHisterConfigPath(env: NodeJS.ProcessEnv, exists?: (path: string) => boolean, platform?: NodeJS.Platform, home?: string): string | undefined;
|
|
70
|
+
/** The real service deps. Restart is only offered where a service manager is known: Homebrew on macOS/Linux. */
|
|
71
|
+
export declare function systemHisterDeps(env: NodeJS.ProcessEnv, hister: string | undefined): HisterServiceDeps;
|
|
72
|
+
/**
|
|
73
|
+
* Probe Hister for every configured `hister` datasource. Writes only when `sync` is true, and then only Hister's own
|
|
74
|
+
* config.yml (after a backup), followed by the service restart and reindex the change needs.
|
|
75
|
+
*/
|
|
76
|
+
export declare function setupHister(options: {
|
|
77
|
+
readonly entries: readonly HisterEntry[];
|
|
78
|
+
readonly embedder: ManagedEmbedder;
|
|
79
|
+
readonly executable: (name: string) => string | undefined;
|
|
80
|
+
readonly deps: HisterServiceDeps;
|
|
81
|
+
readonly sync: boolean;
|
|
82
|
+
readonly assertLockOwned?: () => void;
|
|
83
|
+
}): Promise<{
|
|
84
|
+
readonly reports: readonly HisterSetupReport[];
|
|
85
|
+
readonly changed: boolean;
|
|
86
|
+
}>;
|
|
87
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser web-history datasource backed by a running Hister server.
|
|
3
|
+
*
|
|
4
|
+
* Hister (https://github.com/asciimoo/hister, AGPL-3.0-or-later) is a separate program. It captures the pages a
|
|
5
|
+
* Chromium or Firefox browser visits (through its own extension), keeps the full text, and owns the lexical and
|
|
6
|
+
* semantic indexes, incremental updates, and credentials. AutoRAG only sends search requests to its public HTTP
|
|
7
|
+
* API and maps the answers. It does not link, embed, bundle, copy, or modify Hister, and never hides that Hister
|
|
8
|
+
* is the backend: the manifest names it, its license, and its source.
|
|
9
|
+
*
|
|
10
|
+
* Web pages only: every query is confined to `type:web`, and any document Hister reports with another type
|
|
11
|
+
* (watched local files, remote file snapshots) is dropped. Local directory indexing in Hister is never used.
|
|
12
|
+
*/
|
|
13
|
+
import type { RetrievalMethod, RetrievalOptions, RetrievalResult } from "../../../retrieval/types.js";
|
|
14
|
+
import type { DatasourceIndexOptions, DatasourceIndexResult, DatasourceSkill, DatasourceSkillDescriptor, DatasourceSkillManifest, PollingMetadata, SourceDescription } from "../../types.js";
|
|
15
|
+
import { HisterClient, type HisterClientOptions } from "./client.js";
|
|
16
|
+
export declare const HISTER_SKILL_TYPE = "hister-web-history";
|
|
17
|
+
export interface HisterSkillOptions extends HisterClientOptions {
|
|
18
|
+
readonly client?: HisterClient;
|
|
19
|
+
readonly datasourceId?: string;
|
|
20
|
+
readonly instanceId?: string;
|
|
21
|
+
readonly instances?: readonly string[];
|
|
22
|
+
readonly tags?: readonly string[];
|
|
23
|
+
/**
|
|
24
|
+
* Also register Hister's semantic search. Requires `semantic_search.enable` and an embedding endpoint in the
|
|
25
|
+
* Hister server config; Hister embeds the query text through the endpoint the operator chose there.
|
|
26
|
+
*/
|
|
27
|
+
readonly semantic?: boolean;
|
|
28
|
+
}
|
|
29
|
+
type Mode = "lexical" | "semantic";
|
|
30
|
+
export declare class HisterSkill implements DatasourceSkill {
|
|
31
|
+
private readonly datasourceId;
|
|
32
|
+
private readonly instanceId;
|
|
33
|
+
private readonly instances;
|
|
34
|
+
private readonly tags;
|
|
35
|
+
private readonly semantic;
|
|
36
|
+
private readonly client;
|
|
37
|
+
/** A bad `baseUrl` or token setup is reported through `index()`/search, never thrown out of config loading. */
|
|
38
|
+
private readonly configError;
|
|
39
|
+
private lastIndexedAt;
|
|
40
|
+
private lastError;
|
|
41
|
+
constructor(options?: HisterSkillOptions);
|
|
42
|
+
describe(): DatasourceSkillDescriptor;
|
|
43
|
+
polling(): PollingMetadata;
|
|
44
|
+
/**
|
|
45
|
+
* Hister indexes pages itself the moment the browser extension sends them, so there is nothing to copy.
|
|
46
|
+
* `index()` is a read-only probe: reachability, authentication, how many web pages are searchable, and whether
|
|
47
|
+
* Hister also holds non-web documents that this datasource will never return.
|
|
48
|
+
*/
|
|
49
|
+
index(options?: DatasourceIndexOptions): Promise<DatasourceIndexResult>;
|
|
50
|
+
retrievalMethods(): readonly RetrievalMethod[];
|
|
51
|
+
describeSources(): readonly SourceDescription[];
|
|
52
|
+
skillManifest(): DatasourceSkillManifest;
|
|
53
|
+
search(mode: Mode, query: string, options: RetrievalOptions): Promise<RetrievalResult[]>;
|
|
54
|
+
/** Opaque, stable identity: `/<id>/<instance>/pages/<domain>/<hash of the URL>`. */
|
|
55
|
+
private sourceFor;
|
|
56
|
+
private toResult;
|
|
57
|
+
/** Does the scope reach this datasource at all, and can it be pushed down to Hister as `domain:`? */
|
|
58
|
+
private scopeTarget;
|
|
59
|
+
private failFrom;
|
|
60
|
+
private fail;
|
|
61
|
+
private note;
|
|
62
|
+
}
|
|
63
|
+
export {};
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
5
|
-
export type { QmdEmbedResult, QmdEnsureResult, QmdFailureReason, QmdOptions, QmdSearchHit, QmdSearchMode, QmdSearchOptions, QmdSearchResult, QmdUpdateResult, } from "./types.js";
|
|
6
|
-
export { DEFAULT_QMD_BINARY, DEFAULT_QMD_MAX_BUFFER_BYTES, DEFAULT_QMD_TIMEOUT_MS, } from "./types.js";
|
|
1
|
+
export { ObsidianBm25Method, type ObsidianMethodOptions, ObsidianSemanticMethod } from "./methods.js";
|
|
2
|
+
export { encodeSourceSegment, obsidianDatasourceDir, obsidianInstanceSource, obsidianMinSyncWorkspace, obsidianNoteSource, } from "./paths.js";
|
|
3
|
+
export { ObsidianSkill, type ObsidianSkillOptions } from "./skill.js";
|
|
4
|
+
export type { ObsidianMinSyncOptions, ObsidianSearchMode } from "./vault-index.js";
|
|
@@ -1,26 +1,22 @@
|
|
|
1
1
|
import type { RetrievalMethod, RetrievalMethodDescriptor, RetrievalOptions, RetrievalResult } from "../../../retrieval/types.js";
|
|
2
|
-
import type {
|
|
3
|
-
export interface ObsidianSearchClient {
|
|
4
|
-
search(mode: QmdSearchMode, query: string, options?: QmdSearchOptions): Promise<QmdSearchResult>;
|
|
5
|
-
}
|
|
2
|
+
import type { ObsidianSearchMode, ObsidianVaultIndex } from "./vault-index.js";
|
|
6
3
|
export interface ObsidianMethodOptions {
|
|
7
|
-
readonly
|
|
8
|
-
readonly
|
|
9
|
-
readonly tags?: readonly string[];
|
|
4
|
+
readonly index: ObsidianVaultIndex;
|
|
5
|
+
readonly tags: readonly string[];
|
|
10
6
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
private readonly
|
|
7
|
+
/** One MinSync query mode over one vault. A failure reaches the pipeline verbatim and is reported as unsearched. */
|
|
8
|
+
declare class ObsidianMinSyncMethod implements RetrievalMethod {
|
|
9
|
+
private readonly index;
|
|
14
10
|
private readonly tags;
|
|
15
|
-
|
|
11
|
+
private readonly mode;
|
|
12
|
+
constructor(mode: ObsidianSearchMode, options: ObsidianMethodOptions);
|
|
16
13
|
describe(): RetrievalMethodDescriptor;
|
|
17
14
|
retrieve(query: string, options: RetrievalOptions): Promise<RetrievalResult[]>;
|
|
18
15
|
}
|
|
19
|
-
export declare class
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
export declare class ObsidianBm25Method extends ObsidianMinSyncMethod {
|
|
17
|
+
constructor(options: ObsidianMethodOptions);
|
|
18
|
+
}
|
|
19
|
+
export declare class ObsidianSemanticMethod extends ObsidianMinSyncMethod {
|
|
23
20
|
constructor(options: ObsidianMethodOptions);
|
|
24
|
-
describe(): RetrievalMethodDescriptor;
|
|
25
|
-
retrieve(query: string, options: RetrievalOptions): Promise<RetrievalResult[]>;
|
|
26
21
|
}
|
|
22
|
+
export {};
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Path helpers for the Obsidian
|
|
2
|
+
* Path helpers for the Obsidian datasource.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* `<workspaceRoot>/.autorag/datasources/obsidian/<
|
|
6
|
-
* `
|
|
7
|
-
*
|
|
8
|
-
* the form `/obsidian/<instance-
|
|
4
|
+
* Everything AutoRAG owns for one vault lives under
|
|
5
|
+
* `<workspaceRoot>/.autorag/datasources/obsidian/<instance>/`: a MinSync workspace of its own
|
|
6
|
+
* (`minsync/`, never shared with the local-file index) and the staging record (`staging.json`)
|
|
7
|
+
* that maps staged notes back to the vault. Callers see slash-hierarchical opaque sources of
|
|
8
|
+
* the form `/obsidian/<instance>/<vault-relative note path>`.
|
|
9
9
|
*/
|
|
10
|
-
export declare const
|
|
11
|
-
export declare const
|
|
12
|
-
export declare
|
|
13
|
-
|
|
14
|
-
export declare function
|
|
15
|
-
/**
|
|
16
|
-
export declare function
|
|
17
|
-
/**
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
export declare function
|
|
26
|
-
/**
|
|
27
|
-
export declare function
|
|
10
|
+
export declare const OBSIDIAN_DATASOURCE_ID = "obsidian";
|
|
11
|
+
export declare const OBSIDIAN_SKILL_TYPE = "obsidian-vault";
|
|
12
|
+
export declare function obsidianDatasourceDir(workspaceRoot: string, instanceId: string): string;
|
|
13
|
+
/** The MinSync workspace this vault is indexed in; staged notes live in its `files/` folder. */
|
|
14
|
+
export declare function obsidianMinSyncWorkspace(workspaceRoot: string, instanceId: string): string;
|
|
15
|
+
/** Kept beside the MinSync workspace, outside the tree MinSync indexes. */
|
|
16
|
+
export declare function obsidianStagingStatePath(workspaceRoot: string, instanceId: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Escape what would change the meaning of a source segment: `%` (the escape itself), `/` (the
|
|
19
|
+
* separator, possible in an instance id), `#` (datasource sources never carry a fragment), `\`
|
|
20
|
+
* (not valid in a virtual path) and `*` (a scope glob). Everything else, spaces and non-Latin
|
|
21
|
+
* letters included, stays readable.
|
|
22
|
+
*/
|
|
23
|
+
export declare function encodeSourceSegment(segment: string): string;
|
|
24
|
+
/** The root source of one vault: the scope that selects every note in it. */
|
|
25
|
+
export declare function obsidianInstanceSource(instanceId: string): string;
|
|
26
|
+
/** The source of one note, from its vault-relative path written with `/` separators. */
|
|
27
|
+
export declare function obsidianNoteSource(instanceId: string, relativePath: string): string;
|
|
@@ -1,37 +1,33 @@
|
|
|
1
1
|
import type { RetrievalMethod } from "../../../retrieval/types.js";
|
|
2
2
|
import type { DatasourceIndexOptions, DatasourceIndexResult, DatasourceSkill, DatasourceSkillDescriptor, DatasourceSkillManifest, PollingMetadata, SourceDescription } from "../../types.js";
|
|
3
|
-
import { type
|
|
4
|
-
import type { QmdEmbedResult, QmdEnsureResult, QmdUpdateResult } from "./types.js";
|
|
5
|
-
export interface ObsidianSkillClient extends ObsidianSearchClient {
|
|
6
|
-
ensureCollection(signal?: AbortSignal): Promise<QmdEnsureResult>;
|
|
7
|
-
update(signal?: AbortSignal): Promise<QmdUpdateResult>;
|
|
8
|
-
embed(signal?: AbortSignal): Promise<QmdEmbedResult>;
|
|
9
|
-
}
|
|
3
|
+
import { type ObsidianMinSyncOptions } from "./vault-index.js";
|
|
10
4
|
export interface ObsidianSkillOptions {
|
|
11
5
|
readonly datasourceId?: string;
|
|
12
|
-
readonly client?: ObsidianSkillClient;
|
|
13
6
|
readonly vaultPath?: string;
|
|
14
|
-
readonly binaryPath?: string;
|
|
15
7
|
readonly instanceId?: string;
|
|
16
8
|
readonly instances?: readonly string[];
|
|
17
9
|
readonly pollingIntervalMs?: number;
|
|
18
10
|
readonly tags?: readonly string[];
|
|
19
11
|
readonly lastIndexedAt?: number;
|
|
12
|
+
/** Where `.autorag/datasources/obsidian/<instance>` is kept. Required to index or search. */
|
|
20
13
|
readonly workspaceRoot?: string;
|
|
21
|
-
|
|
22
|
-
readonly
|
|
23
|
-
readonly configPath?: string;
|
|
14
|
+
/** The install's MinSync binary, embedder and chunking, shared with the local-file index. */
|
|
15
|
+
readonly minSync?: ObsidianMinSyncOptions;
|
|
24
16
|
readonly connectorOptions?: {
|
|
25
17
|
readonly vaultPath?: string;
|
|
26
18
|
};
|
|
27
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* An Obsidian vault as a datasource: its markdown notes are indexed by MinSync (BM25 and
|
|
22
|
+
* semantic) in a workspace of their own, and a note's source is its vault-relative path, so a
|
|
23
|
+
* folder is an ordinary `scope`.
|
|
24
|
+
*/
|
|
28
25
|
export declare class ObsidianSkill implements DatasourceSkill {
|
|
29
|
-
private readonly
|
|
26
|
+
private readonly vaultIndex;
|
|
30
27
|
private readonly instanceId;
|
|
31
28
|
private readonly instances;
|
|
32
29
|
private readonly pollingIntervalMs;
|
|
33
30
|
private readonly tags;
|
|
34
|
-
private readonly vaultPath;
|
|
35
31
|
private lastIndexedAt;
|
|
36
32
|
private lastError;
|
|
37
33
|
constructor(options?: ObsidianSkillOptions);
|
|
@@ -41,5 +37,4 @@ export declare class ObsidianSkill implements DatasourceSkill {
|
|
|
41
37
|
retrievalMethods(): readonly RetrievalMethod[];
|
|
42
38
|
describeSources(): readonly SourceDescription[];
|
|
43
39
|
skillManifest(): DatasourceSkillManifest;
|
|
44
|
-
private fail;
|
|
45
40
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export interface VaultNote {
|
|
2
|
+
/** Vault-relative path, NFC-normalized, `/`-separated. */
|
|
3
|
+
readonly relativePath: string;
|
|
4
|
+
readonly sourcePath: string;
|
|
5
|
+
readonly size: number;
|
|
6
|
+
/** Exact nanosecond mtime as a decimal string (it exceeds a double's integer range). */
|
|
7
|
+
readonly mtimeNs: string;
|
|
8
|
+
}
|
|
9
|
+
export interface VaultListing {
|
|
10
|
+
readonly notes: ReadonlyMap<string, VaultNote>;
|
|
11
|
+
/** Folders (vault-relative) that could not be read; their staged notes are kept as they were. */
|
|
12
|
+
readonly unreadableFolders: readonly string[];
|
|
13
|
+
/** Notes dropped because another note has the same NFC-normalized path. */
|
|
14
|
+
readonly collisions: readonly string[];
|
|
15
|
+
}
|
|
16
|
+
export declare class VaultUnavailableError extends Error {
|
|
17
|
+
readonly code: string;
|
|
18
|
+
constructor(code: string);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* List the vault's notes. Dot-prefixed folders and files (`.obsidian`, `.trash`, `.git`),
|
|
22
|
+
* `node_modules`, and symlinks are not part of the vault's knowledge and are skipped.
|
|
23
|
+
* Throws {@link VaultUnavailableError} when the vault root itself cannot be read.
|
|
24
|
+
*/
|
|
25
|
+
export declare function listVaultNotes(vaultPath: string): Promise<VaultListing>;
|
|
26
|
+
interface StagingEntry {
|
|
27
|
+
readonly sourcePath: string;
|
|
28
|
+
readonly size: number;
|
|
29
|
+
readonly mtimeNs: string;
|
|
30
|
+
}
|
|
31
|
+
export interface StagingState {
|
|
32
|
+
readonly version: 1;
|
|
33
|
+
readonly entries: Readonly<Record<string, StagingEntry>>;
|
|
34
|
+
}
|
|
35
|
+
export declare function loadStagingState(statePath: string): StagingState;
|
|
36
|
+
export interface StageResult {
|
|
37
|
+
readonly staged: number;
|
|
38
|
+
readonly copied: number;
|
|
39
|
+
readonly removed: number;
|
|
40
|
+
/** Notes that could not be copied this time; an earlier staged copy, if any, was kept. */
|
|
41
|
+
readonly failed: readonly string[];
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Bring `<filesRoot>` in line with the vault: copy new and changed notes, delete notes that no
|
|
45
|
+
* longer exist, and leave notes under an unreadable folder exactly as they were.
|
|
46
|
+
*/
|
|
47
|
+
export declare function stageNotes(filesRoot: string, statePath: string, listing: VaultListing, options?: {
|
|
48
|
+
readonly force?: boolean;
|
|
49
|
+
}): StageResult;
|
|
50
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { MinSyncVectorMethodOptions } from "../../../minsync/method.js";
|
|
2
|
+
import type { RetrievalResult } from "../../../retrieval/types.js";
|
|
3
|
+
import type { DatasourceDiagnostic, DatasourceDiagnosticCode } from "../../types.js";
|
|
4
|
+
/** The MinSync settings a vault shares with the rest of the install: binary, embedder, chunking. */
|
|
5
|
+
export type ObsidianMinSyncOptions = Pick<MinSyncVectorMethodOptions, "binaryPath" | "autoInstall" | "installer" | "embedder" | "maxChunkSize">;
|
|
6
|
+
export interface ObsidianVaultIndexOptions {
|
|
7
|
+
readonly instanceId: string;
|
|
8
|
+
readonly vaultPath: string | undefined;
|
|
9
|
+
readonly workspaceRoot: string | undefined;
|
|
10
|
+
readonly minSync?: ObsidianMinSyncOptions;
|
|
11
|
+
}
|
|
12
|
+
export type ObsidianSearchMode = "bm25" | "semantic";
|
|
13
|
+
export interface ObsidianSearchOptions {
|
|
14
|
+
readonly topK?: number;
|
|
15
|
+
readonly scope?: string;
|
|
16
|
+
readonly signal?: AbortSignal;
|
|
17
|
+
}
|
|
18
|
+
export type VaultSyncOutcome = {
|
|
19
|
+
readonly ok: true;
|
|
20
|
+
readonly notes: number;
|
|
21
|
+
readonly diagnostics: readonly DatasourceDiagnostic[];
|
|
22
|
+
} | {
|
|
23
|
+
readonly ok: false;
|
|
24
|
+
readonly code: DatasourceDiagnosticCode;
|
|
25
|
+
readonly message: string;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* One vault, indexed by MinSync in a workspace of its own. Notes are staged under the workspace's
|
|
29
|
+
* `files/` folder (see `staging.ts`), `minsync sync` embeds and indexes them incrementally, and a
|
|
30
|
+
* query runs against that index and maps each chunk back to its note.
|
|
31
|
+
*/
|
|
32
|
+
export declare class ObsidianVaultIndex {
|
|
33
|
+
private readonly instanceId;
|
|
34
|
+
private readonly vaultPath;
|
|
35
|
+
private readonly workspaceRoot;
|
|
36
|
+
private readonly minSync;
|
|
37
|
+
constructor(options: ObsidianVaultIndexOptions);
|
|
38
|
+
/** Mirror the vault's notes into the MinSync workspace and sync it. Never throws except on abort. */
|
|
39
|
+
sync(signal?: AbortSignal): Promise<VaultSyncOutcome>;
|
|
40
|
+
private syncLocked;
|
|
41
|
+
/** Search the indexed vault. Rejects, with the reason, when the vault was never indexed or a sync is running. */
|
|
42
|
+
query(mode: ObsidianSearchMode, text: string, options?: ObsidianSearchOptions): Promise<RetrievalResult[]>;
|
|
43
|
+
private queryLocked;
|
|
44
|
+
}
|