@autorag/librarian 2.5.1 → 2.5.2

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 (73) hide show
  1. package/NOTICE +3 -0
  2. package/README.md +229 -490
  3. package/dist/agent/agent.d.ts +44 -2
  4. package/dist/agent/index.d.ts +1 -0
  5. package/dist/agent/search-datasource-tool.d.ts +1 -0
  6. package/dist/agent/search-single-datasource-tool.d.ts +57 -0
  7. package/dist/agent/web-fetch-tool.d.ts +32 -0
  8. package/dist/agent/web-search-tool.d.ts +48 -0
  9. package/dist/cli/commands/lite-retrieve.d.ts +15 -0
  10. package/dist/cli/commands/search.d.ts +6 -0
  11. package/dist/cli/config.d.ts +20 -0
  12. package/dist/cli/index.js +6478 -372
  13. package/dist/core.d.ts +3 -1
  14. package/dist/core.js +6499 -409
  15. package/dist/datasource/connector-skill.d.ts +6 -0
  16. package/dist/datasource/crawler-skill.d.ts +2 -0
  17. package/dist/datasource/errors.d.ts +26 -0
  18. package/dist/datasource/skills/slack/index.d.ts +8 -0
  19. package/dist/datasource/tool-naming.d.ts +11 -0
  20. package/dist/index.js +6508 -419
  21. package/dist/minsync/types.d.ts +7 -0
  22. package/dist/retrieval/engine.d.ts +14 -5
  23. package/dist/retrieval/index.d.ts +2 -1
  24. package/dist/retrieval/merger.d.ts +30 -5
  25. package/dist/retrieval/skip.d.ts +41 -0
  26. package/dist/retrieval/types.d.ts +23 -2
  27. package/dist/web/entities.d.ts +10 -0
  28. package/dist/web/fetch/convert.d.ts +35 -0
  29. package/dist/web/fetch/feeds.d.ts +37 -0
  30. package/dist/web/fetch/html-renderer.d.ts +54 -0
  31. package/dist/web/fetch/index.d.ts +12 -0
  32. package/dist/web/fetch/negotiate.d.ts +27 -0
  33. package/dist/web/fetch/page-loader.d.ts +60 -0
  34. package/dist/web/fetch/render.d.ts +23 -0
  35. package/dist/web/fetch/turndown/gfm.d.ts +11 -0
  36. package/dist/web/fetch/turndown/html.d.ts +5 -0
  37. package/dist/web/fetch/turndown/index.d.ts +10 -0
  38. package/dist/web/fetch/turndown/service.d.ts +21 -0
  39. package/dist/web/fetch/turndown/types.d.ts +73 -0
  40. package/dist/web/fetch/url-target.d.ts +29 -0
  41. package/dist/web/search/browser-headers.d.ts +17 -0
  42. package/dist/web/search/browser-loader.d.ts +56 -0
  43. package/dist/web/search/browser-page.d.ts +41 -0
  44. package/dist/web/search/credentials.d.ts +10 -0
  45. package/dist/web/search/format.d.ts +30 -0
  46. package/dist/web/search/index.d.ts +46 -0
  47. package/dist/web/search/model-auth.d.ts +36 -0
  48. package/dist/web/search/provider.d.ts +62 -0
  49. package/dist/web/search/providers/anthropic.d.ts +9 -0
  50. package/dist/web/search/providers/base.d.ts +106 -0
  51. package/dist/web/search/providers/codex.d.ts +9 -0
  52. package/dist/web/search/providers/duckduckgo.d.ts +22 -0
  53. package/dist/web/search/providers/ecosia.d.ts +29 -0
  54. package/dist/web/search/providers/gemini.d.ts +9 -0
  55. package/dist/web/search/providers/google.d.ts +22 -0
  56. package/dist/web/search/providers/mojeek.d.ts +24 -0
  57. package/dist/web/search/providers/parallel.d.ts +10 -0
  58. package/dist/web/search/providers/perplexity.d.ts +10 -0
  59. package/dist/web/search/providers/public.d.ts +15 -0
  60. package/dist/web/search/providers/responses-api.d.ts +26 -0
  61. package/dist/web/search/providers/searxng.d.ts +19 -0
  62. package/dist/web/search/providers/startpage.d.ts +25 -0
  63. package/dist/web/search/providers/utils.d.ts +39 -0
  64. package/dist/web/search/providers/xai.d.ts +9 -0
  65. package/dist/web/search/query.d.ts +193 -0
  66. package/dist/web/search/types.d.ts +198 -0
  67. package/dist/web/search/utils.d.ts +8 -0
  68. package/package.json +2 -1
  69. package/skills/autorag/SKILL.md +2 -1
  70. package/skills/autorag-doctor/SKILL.md +237 -0
  71. package/skills/autorag-lite-search/SKILL.md +29 -7
  72. package/skills/autorag-lite-setup/SKILL.md +20 -13
  73. package/skills/autorag-setup/SKILL.md +32 -14
@@ -50,4 +50,11 @@ export interface MinSyncQueryHit {
50
50
  readonly path: string;
51
51
  readonly score: number;
52
52
  readonly text: string;
53
+ /**
54
+ * MinSync's per-chunk identity (`doc_id` in its JSON). Several chunks of one
55
+ * parsed mirror share a `path`, so this is what distinguishes them; without
56
+ * it every passage of a document collapses into a single evidence id.
57
+ * Optional because older MinSync builds omit it.
58
+ */
59
+ readonly docId?: string;
53
60
  }
@@ -15,7 +15,7 @@
15
15
  */
16
16
  import { DatasourceAccessContext, type DatasourceAccessContextOptions } from "../datasource/access-context.js";
17
17
  import { RetrievalMethodRegistry } from "./registry.js";
18
- import type { RetrievalDiagnostic, RetrievalMethod, RetrievalOptions, RetrievalResult } from "./types.js";
18
+ import type { RetrievalDiagnostic, RetrievalMethod, RetrievalOptions, RetrievalResult, RetrievalUnsearchedSurface } from "./types.js";
19
19
  /** Options for constructing a standalone {@link RetrievalEngine}. */
20
20
  export interface RetrievalEngineOptions {
21
21
  /**
@@ -23,7 +23,12 @@ export interface RetrievalEngineOptions {
23
23
  * @default { allowedTags: undefined, allowedScopes: undefined }
24
24
  */
25
25
  readonly datasourceAccess?: DatasourceAccessContextOptions;
26
- /** Default `topK` when the caller omits it. @default 20 */
26
+ /**
27
+ * Default `topK` when the caller omits it. This is a safety ceiling on
28
+ * merged evidence, not a relevance cut: the merger returns every distinct
29
+ * chunk, so the effective size is whatever the registered methods returned.
30
+ * @default 500
31
+ */
27
32
  readonly defaultTopK?: number;
28
33
  /** Default deduplication flag. @default true */
29
34
  readonly defaultDedup?: boolean;
@@ -44,7 +49,7 @@ export interface RetrievalEngineOptions {
44
49
  * methods = registry.list()
45
50
  * byMethod = retriever.retrieveWithDiagnostics(methods, query, options)
46
51
  * filtered = filter.filter(byMethod, methods, ctx, options.scope)
47
- * merged = merger.merge(filtered, { topK, dedup: true })
52
+ * merged = merger.merge(filtered, { topK, dedup: true }) // distinct chunks, pure duplicates dropped
48
53
  * → { results: merged, diagnostics }
49
54
  * ```
50
55
  *
@@ -93,6 +98,7 @@ export declare class RetrievalEngine {
93
98
  retrieve(query: string, options?: RetrievalOptions): Promise<{
94
99
  results: RetrievalResult[];
95
100
  diagnostics: RetrievalDiagnostic[];
101
+ unsearched: RetrievalUnsearchedSurface[];
96
102
  }>;
97
103
  /**
98
104
  * Run retrieval and return results keyed per method (unmerged) with
@@ -102,6 +108,7 @@ export declare class RetrievalEngine {
102
108
  retrieveByMethod(query: string, options?: RetrievalOptions): Promise<{
103
109
  byMethod: Map<string, RetrievalResult[]>;
104
110
  diagnostics: RetrievalDiagnostic[];
111
+ unsearched: RetrievalUnsearchedSurface[];
105
112
  }>;
106
113
  /**
107
114
  * Post-check for MinSync binary-missing diagnostic.
@@ -111,9 +118,11 @@ export declare class RetrievalEngine {
111
118
  * a diagnostic. This method checks whether the minsync binary is unavailable
112
119
  * and emits a `minsync-unavailable` diagnostic when every minsync method's
113
120
  * result set is empty, exactly matching the existing {@link AutoRAGAgent}
114
- * behavior (see `agent.src/agent/agent.ts` `retrieveWithDiagnostics`).
121
+ * behavior (see `agent.src/agent/agent.ts` `retrieveWithDiagnostics`). The
122
+ * same check reports the MinSync surface as unsearched, so a caller reading
123
+ * only the skip report still learns that local sources were not queried.
115
124
  */
116
- private appendMinSyncUnavailableDiagnostic;
125
+ private appendMinSyncUnavailable;
117
126
  /**
118
127
  * Build a datasource access context scoped to the caller's options.
119
128
  * Model/tool arguments (allowedTags, allowedScopes) from options can only
@@ -3,4 +3,5 @@ export type { MergeOptions } from "./merger.js";
3
3
  export { ParallelRetriever, ResultMerger } from "./merger.js";
4
4
  export { RetrievalMethodRegistry } from "./registry.js";
5
5
  export { matchesVirtualPathScope, normalizeVirtualPath, normalizeVirtualPathScope, virtualPathScopeToRegExp, } from "./scope.js";
6
- export type { CuratedResult, NumberedResult, RetrievalDiagnostic, RetrievalDiagnosticCode, RetrievalMethod, RetrievalMethodDescriptor, RetrievalOptions, RetrievalResult, RetrievalWithDiagnostics, } from "./types.js";
6
+ export { describeRetrievalError, groupUnsearchedSurfaces, MINSYNC_SURFACE, type RetrievalSkip, retrievalSurfaceFor, } from "./skip.js";
7
+ export type { CuratedResult, NumberedResult, RetrievalDiagnostic, RetrievalDiagnosticCode, RetrievalMethod, RetrievalMethodDescriptor, RetrievalOptions, RetrievalResult, RetrievalUnsearchedSurface, RetrievalWithDiagnostics, } from "./types.js";
@@ -1,19 +1,44 @@
1
1
  import type { RetrievalMethod, RetrievalOptions, RetrievalResult, RetrievalWithDiagnostics } from "./types.js";
2
2
  export interface MergeOptions {
3
+ /**
4
+ * Upper bound on returned evidence. This is a safety ceiling, not a
5
+ * relevance filter: the merger is expected to return every distinct chunk
6
+ * it was given. Callers that want the full pool pass a large value.
7
+ */
3
8
  topK: number;
4
- /** Retained for API compatibility; exact-source aggregation is always enabled. */
9
+ /** Retained for API compatibility; pure-duplicate removal is always enabled. */
5
10
  dedup: boolean;
6
11
  }
12
+ /**
13
+ * Cross-method evidence collator.
14
+ *
15
+ * `search_all_documents` is the *exhaustive* retrieval surface: it fans out to
16
+ * every configured method and the librarian is expected to judge the evidence
17
+ * itself. Collapsing that fan-out to one chunk per source threw away most of
18
+ * what was retrieved — a document whose several passages all matched surfaced
19
+ * only its single best chunk, and a datasource that returned twenty relevant
20
+ * messages could be reduced to one. Modern context windows hold the full pool
21
+ * (a live 16-method run over this repository's own corpus measured ~26k tokens
22
+ * on average, ~53k at its worst), so withholding it bought nothing.
23
+ *
24
+ * This merger therefore preserves every distinct chunk and removes only *pure*
25
+ * duplicates: the same evidence identity (`source` + `id`) seen more than once.
26
+ * Ranking still normalizes each method's scores into a comparable 0..1 band and
27
+ * gives a bounded bonus to sources corroborated by several chunks or methods,
28
+ * so the strongest evidence stays at the top of a complete list.
29
+ */
7
30
  export declare class ResultMerger {
8
31
  merge(results: Map<string, RetrievalResult[]>, options: MergeOptions): RetrievalResult[];
9
32
  }
10
33
  export declare class ParallelRetriever {
11
34
  retrieve(methods: RetrievalMethod[], query: string, options: RetrievalOptions): Promise<Map<string, RetrievalResult[]>>;
12
35
  /**
13
- * Like {@link retrieve} but also returns path-opaque diagnostics for methods
14
- * that failed. Partial results from healthy methods are preserved; failed
15
- * methods yield an empty result set plus a diagnostic. The legacy
16
- * {@link retrieve} return shape is intentionally unchanged for compatibility.
36
+ * Like {@link retrieve} but also returns diagnostics for methods that failed,
37
+ * plus the retrieval surfaces those methods belong to. Partial results from
38
+ * healthy methods are preserved; a failed method yields an empty result set,
39
+ * a diagnostic quoting the underlying error, and an entry in `unsearched`
40
+ * carrying that error verbatim. The legacy {@link retrieve} return shape is
41
+ * intentionally unchanged for compatibility.
17
42
  */
18
43
  retrieveWithDiagnostics(methods: RetrievalMethod[], query: string, options: RetrievalOptions): Promise<RetrievalWithDiagnostics>;
19
44
  }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Skip reporting for the retrieval pipeline.
3
+ *
4
+ * A method that throws is skipped, not fatal: healthy methods still answer. The
5
+ * helpers here turn those skips into a first-class report of the retrieval
6
+ * *surfaces* (local MinSync files, a datasource) that were not searched.
7
+ *
8
+ * The reason is the underlying error, verbatim. AutoRAG does not classify,
9
+ * rewrite, or suppress it: the operator searching their own machine is the one
10
+ * who has to debug the failure, so they get the CLI's own words — exit codes,
11
+ * stderr, paths and all.
12
+ */
13
+ import type { RetrievalMethodDescriptor, RetrievalUnsearchedSurface } from "./types.js";
14
+ /** Surface label shared by every MinSync-backed local method (vector, BM25, hybrid). */
15
+ export declare const MINSYNC_SURFACE = "minsync";
16
+ /** One method that did not run, with the error that stopped it. */
17
+ export interface RetrievalSkip {
18
+ readonly method: string;
19
+ readonly surface: string;
20
+ /** The underlying failure, verbatim. */
21
+ readonly reason: string;
22
+ }
23
+ /**
24
+ * Map a method descriptor onto the surface a caller reasons about: datasource
25
+ * methods keep their datasource id, MinSync-backed local methods collapse into
26
+ * one shared surface, and anything else reports under its own method name.
27
+ */
28
+ export declare function retrievalSurfaceFor(descriptor: RetrievalMethodDescriptor): string;
29
+ /**
30
+ * Render a thrown value as the text a human needs to debug it. Nothing is
31
+ * stripped: whatever the method (or the CLI behind it) said comes through,
32
+ * including paths and exit status. The JS stack is left out because it points at
33
+ * AutoRAG's own frames, not at the failure the operator has to fix.
34
+ */
35
+ export declare function describeRetrievalError(error: unknown): string;
36
+ /**
37
+ * Collapse per-method skips into one entry per surface. Distinct failures on
38
+ * the same surface are all preserved verbatim in the reason; methods are
39
+ * merged. Deterministically ordered.
40
+ */
41
+ export declare function groupUnsearchedSurfaces(skips: readonly RetrievalSkip[]): RetrievalUnsearchedSurface[];
@@ -27,17 +27,38 @@ export interface RetrievalMethod {
27
27
  retrieve(query: string, options: RetrievalOptions): Promise<RetrievalResult[]>;
28
28
  }
29
29
  export type RetrievalDiagnosticCode = "retrieval-method-failed" | "minsync-unavailable";
30
- /** Path-opaque diagnostic emitted by the multi-method retrieval pipeline. */
30
+ /**
31
+ * A retrieval surface (local MinSync files or one datasource) that was not
32
+ * searched for this query. Reported next to partial results so a caller that
33
+ * reads only the result list can still tell the answer is incomplete.
34
+ */
35
+ export interface RetrievalUnsearchedSurface {
36
+ /** Surface label: "minsync" for local files, or the datasource id. */
37
+ surface: string;
38
+ /** Registered retrieval method names on this surface that did not run. */
39
+ methods: string[];
40
+ /**
41
+ * Why the surface did not run: the underlying error verbatim (CLI stderr,
42
+ * exit status, paths included). Never classified or suppressed — the operator
43
+ * debugging their own machine needs the real text.
44
+ */
45
+ reason: string;
46
+ }
47
+ /** Diagnostic emitted by the multi-method retrieval pipeline. */
31
48
  export interface RetrievalDiagnostic {
32
49
  code: RetrievalDiagnosticCode;
33
50
  severity: "info" | "warning" | "error";
34
51
  message: string;
35
- /** Component/method label — never a real filesystem path. */
52
+ /** Component/method label. */
36
53
  source?: string;
54
+ /** The underlying failure verbatim when the diagnostic reports a method that did not run. */
55
+ reason?: string;
37
56
  }
38
57
  export interface RetrievalWithDiagnostics {
39
58
  results: Map<string, RetrievalResult[]>;
40
59
  diagnostics: RetrievalDiagnostic[];
60
+ /** Surfaces that were not searched for this query. Empty when every method ran. */
61
+ unsearched: RetrievalUnsearchedSurface[];
41
62
  }
42
63
  export interface NumberedResult {
43
64
  index: number;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * HTML entity decoding shared by the web search providers and the fetch
3
+ * pipeline.
4
+ *
5
+ * Single-pass by construction: one alternation regex decodes each entity
6
+ * exactly once, so an entity produced by decoding (`&amp;lt;` → `&lt;`) is
7
+ * never re-decoded into markup (CodeQL js/double-escaping). Unknown entities
8
+ * and bare ampersands pass through untouched.
9
+ */
10
+ export declare function decodeHtmlEntities(value: string): string;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Binary download and conversion — adapted from oh-my-pi's
3
+ * `packages/coding-agent/src/web/scrapers/utils.ts` (MIT licensed).
4
+ *
5
+ * `convertBinaryPayload` uses AutoRAG's parser registry for PDF/DOCX/PPTX/XLSX.
6
+ * EPUB and other unsupported extensions fall through to the binary-notice
7
+ * fallback, since AutoRAG's default registry has no EPUB parser. This is a
8
+ * deliberate deviation from oh-my-pi (which uses markit for all convertible
9
+ * types including EPUB) — see the report for rationale.
10
+ */
11
+ import { buildBinaryNotice } from "./url-target.js";
12
+ export interface BinaryFetchSuccess {
13
+ ok: true;
14
+ buffer: Uint8Array;
15
+ contentDisposition?: string;
16
+ }
17
+ export type BinaryFetchResult = BinaryFetchSuccess | {
18
+ ok: false;
19
+ error?: string;
20
+ };
21
+ /**
22
+ * Fetch binary content from a URL with a size limit.
23
+ */
24
+ export declare function fetchBinary(url: string, timeout?: number, signal?: AbortSignal, fetchImpl?: typeof fetch): Promise<BinaryFetchResult>;
25
+ export interface ConvertResult {
26
+ content: string;
27
+ ok: boolean;
28
+ error?: string;
29
+ }
30
+ /**
31
+ * Convert a binary payload to markdown using AutoRAG's parser registry.
32
+ * Falls back to the binary-notice string when no parser handles the extension.
33
+ */
34
+ export declare function convertBinaryPayload(buffer: Uint8Array, extension: string, _finalUrl: string, signal?: AbortSignal): Promise<ConvertResult>;
35
+ export { buildBinaryNotice };
@@ -0,0 +1,37 @@
1
+ /**
2
+ * RSS/Atom feed parsing and JSON formatting — ported from oh-my-pi's
3
+ * `packages/coding-agent/src/tools/fetch.ts` (MIT licensed).
4
+ *
5
+ * Feed parsing uses `fast-xml-parser` (already an AutoRAG dependency) instead
6
+ * of oh-my-pi's `parseHTML`/DOM utils, which are not available here.
7
+ */
8
+ /**
9
+ * Read a single HTML attribute from a tag string.
10
+ */
11
+ export declare function getHtmlAttribute(tag: string, attribute: string): string | null;
12
+ /**
13
+ * Extract bounded `<head>` markup to avoid expensive whole-page parsing.
14
+ */
15
+ export declare function extractHeadHtml(html: string): string;
16
+ /**
17
+ * Parse alternate links from HTML head.
18
+ */
19
+ export declare function parseAlternateLinks(html: string, pageUrl: string): string[];
20
+ /**
21
+ * Extract document links from HTML (for PDF/DOCX wrapper pages).
22
+ */
23
+ export declare function extractDocumentLinks(html: string, baseUrl: string): string[];
24
+ /**
25
+ * Strip a CDATA wrapper and clean text. Only a full-string wrapper is
26
+ * unwrapped (anchored): a stray `]]>` inside content is data, not markup.
27
+ * Entity decoding is single-pass (see `../entities.ts`).
28
+ */
29
+ export declare function cleanFeedText(text: string): string;
30
+ /**
31
+ * Parse RSS/Atom feed XML to markdown using fast-xml-parser.
32
+ */
33
+ export declare function parseFeedToMarkdown(content: string, maxItems?: number): string;
34
+ /**
35
+ * Pretty-print JSON content.
36
+ */
37
+ export declare function formatJson(content: string): string;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * HTML rendering backend chain — ported from oh-my-pi's
3
+ * `packages/coding-agent/src/tools/fetch.ts` (MIT licensed).
4
+ *
5
+ * FetchProvider order: native → lynx → firecrawl → jina.
6
+ * trafilatura is dropped (requires oh-my-pi's pip ensureTool).
7
+ * parallel is dropped (requires oh-my-pi's keyed client port).
8
+ * lynx is used only when found on PATH via a `which` check.
9
+ * firecrawl via FIRECRAWL_API_KEY env.
10
+ * jina via keyless https://r.jina.ai/ with optional JINA_API_KEY.
11
+ */
12
+ export type FetchProvider = "native" | "lynx" | "firecrawl" | "jina";
13
+ export interface RenderHtmlToTextOptions {
14
+ /** Overall render budget in seconds (default 30). */
15
+ timeoutSeconds?: number;
16
+ signal?: AbortSignal;
17
+ fetch?: typeof fetch;
18
+ firecrawlApiKey?: string;
19
+ jinaApiKey?: string;
20
+ /**
21
+ * Inject custom backend runners for testing. Keys must cover every
22
+ * FetchProvider in FETCH_PROVIDER_ORDER. A runner returns the rendered
23
+ * markdown or null to signal "not available / low quality / error."
24
+ */
25
+ runners?: Record<FetchProvider, () => Promise<string | null>>;
26
+ }
27
+ /**
28
+ * Parse the `Markdown Content:` marker from a Jina Reader response body.
29
+ */
30
+ export declare function parseJinaReaderContent(responseBody: string): string | null;
31
+ /**
32
+ * Check if rendered output looks JS-gated or mostly navigation.
33
+ */
34
+ export declare function isLowQualityOutput(content: string): boolean;
35
+ /**
36
+ * Convert HTML to markdown using the vendored Turndown with GFM support.
37
+ * Script/style elements are dropped by a parser-level turndown rule — never
38
+ * by regex pre-stripping (CodeQL js/bad-tag-filter,
39
+ * js/incomplete-multi-character-sanitization).
40
+ */
41
+ export declare function htmlToBasicMarkdown(html: string): string;
42
+ /**
43
+ * Render HTML to markdown by trying reader backends in priority order:
44
+ * native (in-process), lynx, firecrawl, then jina.
45
+ *
46
+ * Every backend's output must clear the quality gate (>100 non-whitespace
47
+ * chars and not isLowQualityOutput) before it is accepted; otherwise the
48
+ * next backend is tried.
49
+ */
50
+ export declare function renderHtmlToText(url: string, html: string, options: RenderHtmlToTextOptions): Promise<{
51
+ content: string;
52
+ ok: boolean;
53
+ method: FetchProvider | "none";
54
+ }>;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * URL fetch/render pipeline — self-contained module backing the future
3
+ * `web_fetch` agent tool. Ported from oh-my-pi (MIT licensed).
4
+ */
5
+ export { type BinaryFetchResult, type ConvertResult, convertBinaryPayload, fetchBinary } from "./convert.js";
6
+ export { cleanFeedText, extractDocumentLinks, extractHeadHtml, formatJson, getHtmlAttribute, parseAlternateLinks, parseFeedToMarkdown, } from "./feeds.js";
7
+ export { type FetchProvider, htmlToBasicMarkdown, isLowQualityOutput, parseJinaReaderContent, type RenderHtmlToTextOptions, renderHtmlToText, } from "./html-renderer.js";
8
+ export { buildLlmEndpointCandidates, tryContentNegotiation, tryLlmEndpoints, tryMdSuffix } from "./negotiate.js";
9
+ export type { LoadPageOptions, LoadPageResult, RenderResult } from "./page-loader.js";
10
+ export { decodeHtmlEntities, finalizeOutput, loadPage, looksLikeHtml, MAX_BYTES, MAX_OUTPUT_CHARS, } from "./page-loader.js";
11
+ export { type RenderUrlOptions, renderUrl } from "./render.js";
12
+ export { buildBinaryNotice, getExtensionHint, getFilenameExtensionHint, isConvertible, normalizeMime, normalizeUrl, sampleLooksBinary, } from "./url-target.js";
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Content negotiation and LLM endpoint discovery — ported from oh-my-pi's
3
+ * `packages/coding-agent/src/tools/fetch.ts` (MIT licensed).
4
+ */
5
+ import { type FetchImpl } from "./page-loader.js";
6
+ /**
7
+ * Build llms.txt / llms.md candidates scoped to the requested URL.
8
+ */
9
+ export declare function buildLlmEndpointCandidates(url: string): string[];
10
+ /**
11
+ * Try fetching URL with .md appended (llms.txt convention).
12
+ */
13
+ export declare function tryMdSuffix(url: string, timeout: number, signal?: AbortSignal, fetchImpl?: FetchImpl): Promise<string | null>;
14
+ /**
15
+ * Try to fetch LLM-friendly endpoints (llms.txt, llms.md).
16
+ */
17
+ export declare function tryLlmEndpoints(url: string, timeout: number, signal?: AbortSignal, fetchImpl?: FetchImpl): Promise<{
18
+ content: string;
19
+ endpoint: string;
20
+ } | null>;
21
+ /**
22
+ * Try content negotiation for markdown/plain.
23
+ */
24
+ export declare function tryContentNegotiation(url: string, timeout: number, signal?: AbortSignal, fetchImpl?: FetchImpl): Promise<{
25
+ content: string;
26
+ type: string;
27
+ } | null>;
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Page loader and output finalization — ported from oh-my-pi's
3
+ * `packages/coding-agent/src/web/scrapers/types.ts` (MIT licensed).
4
+ *
5
+ * Provides: loadPage (UA rotation, 429 Retry-After backoff, streaming
6
+ * maxBytes cap, charset-aware decodeBody), finalizeOutput, looksLikeHtml,
7
+ * decodeHtmlEntities, MAX_BYTES, MAX_OUTPUT_CHARS, RenderResult types.
8
+ */
9
+ export interface RenderResult {
10
+ readonly url: string;
11
+ readonly finalUrl: string;
12
+ readonly contentType: string;
13
+ readonly method: string;
14
+ readonly content: string;
15
+ readonly fetchedAt: string;
16
+ readonly truncated: boolean;
17
+ readonly notes: string[];
18
+ }
19
+ export declare const MAX_OUTPUT_CHARS = 500000;
20
+ export declare const MAX_BYTES: number;
21
+ /** Transport signature accepted for injection (tests, proxies). */
22
+ export type FetchImpl = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
23
+ export interface LoadPageOptions {
24
+ timeout?: number;
25
+ /** Transport injection; defaults to global fetch. */
26
+ fetch?: FetchImpl;
27
+ headers?: Record<string, string>;
28
+ method?: string;
29
+ body?: string;
30
+ maxBytes?: number;
31
+ signal?: AbortSignal;
32
+ skipBodyForContentType?: (contentType: string) => boolean;
33
+ }
34
+ export interface LoadPageResult {
35
+ content: string;
36
+ contentType: string;
37
+ finalUrl: string;
38
+ ok: boolean;
39
+ status?: number;
40
+ truncated?: boolean;
41
+ error?: string;
42
+ bodySkipped?: boolean;
43
+ }
44
+ export declare function finalizeOutput(content: string): {
45
+ content: string;
46
+ truncated: boolean;
47
+ };
48
+ /**
49
+ * Fetch a page with timeout and size limit.
50
+ */
51
+ export declare function loadPage(url: string, options?: LoadPageOptions): Promise<LoadPageResult>;
52
+ /**
53
+ * Check if content looks like HTML by inspecting the leading tag.
54
+ */
55
+ export declare function looksLikeHtml(content: string): boolean;
56
+ /**
57
+ * Decode common HTML entities. Single-pass: an entity produced by decoding
58
+ * is never re-decoded (see `../entities.ts`).
59
+ */
60
+ export { decodeHtmlEntities } from "../entities.js";
@@ -0,0 +1,23 @@
1
+ /**
2
+ * renderUrl — the full URL-fetch/render pipeline — ported from oh-my-pi's
3
+ * `packages/coding-agent/src/tools/fetch.ts` (MIT licensed).
4
+ *
5
+ * Special site handlers (step 1), images, sqlite, archives, and notebooks
6
+ * are NOT ported. Binary payloads (zip, pdf, etc.) return a textual binary
7
+ * notice. The markit conversion step uses AutoRAG's parser registry for
8
+ * PDF/DOCX/PPTX/XLSX; EPUB and other unsupported types fall through to the
9
+ * binary-notice fallback.
10
+ */
11
+ import { type RenderResult } from "./page-loader.js";
12
+ export interface RenderUrlOptions {
13
+ timeoutSeconds?: number;
14
+ raw?: boolean;
15
+ signal?: AbortSignal;
16
+ fetch?: typeof fetch;
17
+ firecrawlApiKey?: string;
18
+ jinaApiKey?: string;
19
+ }
20
+ /**
21
+ * Fetch and render a URL to markdown or text.
22
+ */
23
+ export declare function renderUrl(url: string, options?: RenderUrlOptions): Promise<RenderResult>;
@@ -0,0 +1,11 @@
1
+ import type { TurndownPlugin } from "./types.js";
2
+ /** Install GitHub fenced code blocks selected by `highlight-source-*` wrappers. */
3
+ export declare const highlightedCodeBlock: TurndownPlugin;
4
+ /** Install GFM strikethrough conversion. */
5
+ export declare const strikethrough: TurndownPlugin;
6
+ /** Install GFM task-list checkbox conversion. */
7
+ export declare const taskListItems: TurndownPlugin;
8
+ /** Install GFM table conversion for tables with a heading row. */
9
+ export declare const tables: TurndownPlugin;
10
+ /** Install every GFM rule used by the coding agent. */
11
+ export declare const gfm: TurndownPlugin;
@@ -0,0 +1,5 @@
1
+ import type { TurndownNode } from "./types.js";
2
+ /** Parse an HTML fragment into the small DOM subset needed by Turndown. */
3
+ export declare function parseHtmlFragment(html: string): TurndownNode;
4
+ /** Serialize a standards-shaped or internal HTML node. */
5
+ export declare function serializeNode(node: TurndownNode): string;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Vendored from oh-my-pi (packages/utils/src/turndown) — MIT licensed.
3
+ * Behavior-compatible Turndown reimplementation used as the `native`
4
+ * HTML-to-markdown backend by `src/web/fetch/html-renderer.ts`.
5
+ *
6
+ * Source: https://github.com/oh-my-pi/oh-my-pi
7
+ */
8
+ export * from "./gfm.js";
9
+ export { default, default as TurndownService } from "./service.js";
10
+ export * from "./types.js";
@@ -0,0 +1,21 @@
1
+ import type { ResolvedTurndownOptions, RuleFilter, TurndownNode, TurndownOptions, TurndownPlugin, TurndownRule } from "./types.js";
2
+ /** Convert HTML fragments to Markdown with extensible Turndown-compatible rules. */
3
+ export default class TurndownService {
4
+ #private;
5
+ readonly options: ResolvedTurndownOptions;
6
+ constructor(options?: TurndownOptions);
7
+ /** Install a highest-priority named conversion rule. */
8
+ addRule(key: string, rule: TurndownRule): this;
9
+ /** Preserve matching elements as HTML when no custom rule handles them. */
10
+ keep(filter: RuleFilter): this;
11
+ /** Drop matching elements and all of their converted content. */
12
+ remove(filter: RuleFilter): this;
13
+ /** Install one plugin or an ordered list of plugins. */
14
+ use(plugin: TurndownPlugin | readonly TurndownPlugin[]): this;
15
+ /** Escape Markdown punctuation using Turndown's public escaping rules. */
16
+ escape(text: string): string;
17
+ /** Convert an HTML string or standards-shaped DOM node to Markdown. */
18
+ turndown(input: string | TurndownNode): string;
19
+ /** Convert only a node's children within the active conversion. */
20
+ convertChildren(node: TurndownNode): string;
21
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Behavior-compatible reimplementation of turndown's used surface.
3
+ * Vendored from oh-my-pi (can1357/oh-my-pi, MIT) `packages/utils/src/turndown/types.ts`.
4
+ */
5
+ /** A DOM-shaped node accepted by conversion rules. */
6
+ export interface TurndownNode {
7
+ readonly nodeType: number;
8
+ readonly nodeName: string;
9
+ readonly parentNode: TurndownNode | null;
10
+ readonly childNodes: ArrayLike<TurndownNode>;
11
+ readonly children: ArrayLike<TurndownNode>;
12
+ readonly firstChild: TurndownNode | null;
13
+ readonly lastChild: TurndownNode | null;
14
+ readonly nextSibling: TurndownNode | null;
15
+ readonly previousSibling: TurndownNode | null;
16
+ readonly textContent: string | null;
17
+ readonly outerHTML?: string;
18
+ getAttribute(name: string): string | null;
19
+ hasAttribute(name: string): boolean;
20
+ }
21
+ /** Options supported by the HTML-to-Markdown converter. */
22
+ export interface TurndownOptions {
23
+ headingStyle?: "setext" | "atx";
24
+ hr?: string;
25
+ bulletListMarker?: "*" | "-" | "+";
26
+ codeBlockStyle?: "indented" | "fenced";
27
+ fence?: string;
28
+ emDelimiter?: "_" | "*";
29
+ strongDelimiter?: "**" | "__";
30
+ linkStyle?: "inlined" | "referenced";
31
+ linkReferenceStyle?: "full" | "collapsed" | "shortcut";
32
+ preformattedCode?: boolean;
33
+ blankReplacement?: ReplacementFunction;
34
+ keepReplacement?: ReplacementFunction;
35
+ defaultReplacement?: ReplacementFunction;
36
+ }
37
+ /** Fully resolved options passed to replacement callbacks. */
38
+ export interface ResolvedTurndownOptions {
39
+ headingStyle: "setext" | "atx";
40
+ hr: string;
41
+ bulletListMarker: "*" | "-" | "+";
42
+ codeBlockStyle: "indented" | "fenced";
43
+ fence: string;
44
+ emDelimiter: "_" | "*";
45
+ strongDelimiter: "**" | "__";
46
+ linkStyle: "inlined" | "referenced";
47
+ linkReferenceStyle: "full" | "collapsed" | "shortcut";
48
+ preformattedCode: boolean;
49
+ blankReplacement?: ReplacementFunction;
50
+ keepReplacement?: ReplacementFunction;
51
+ defaultReplacement?: ReplacementFunction;
52
+ }
53
+ /** A tag name, list of tag names, or predicate selecting nodes for a rule. */
54
+ export type RuleFilter = string | readonly string[] | ((node: TurndownNode, options: ResolvedTurndownOptions) => boolean);
55
+ /** Produces Markdown for a matched node and its already-converted children. */
56
+ export type ReplacementFunction = (content: string, node: TurndownNode, options: ResolvedTurndownOptions) => string;
57
+ /** A named conversion rule accepted by `addRule`. */
58
+ export interface TurndownRule {
59
+ filter: RuleFilter;
60
+ replacement: ReplacementFunction;
61
+ }
62
+ /** A plugin that installs one or more conversion rules. */
63
+ export type TurndownPlugin = (service: TurndownServiceLike) => void;
64
+ /** Structural service surface available to plugins. */
65
+ export interface TurndownServiceLike {
66
+ readonly options: ResolvedTurndownOptions;
67
+ addRule(key: string, rule: TurndownRule): this;
68
+ convertChildren(node: TurndownNode): string;
69
+ keep(filter: RuleFilter): this;
70
+ remove(filter: RuleFilter): this;
71
+ turndown(input: string | TurndownNode): string;
72
+ escape(text: string): string;
73
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * URL normalization, MIME classification, and binary detection — ported from
3
+ * oh-my-pi's `packages/coding-agent/src/tools/fetch.ts` (MIT licensed).
4
+ */
5
+ /**
6
+ * Normalize a URL: repair a collapsed scheme, then add `https://` if missing.
7
+ */
8
+ export declare function normalizeUrl(url: string): string;
9
+ /**
10
+ * Normalize a MIME type (lowercase, strip charset/params).
11
+ */
12
+ export declare function normalizeMime(contentType: string): string;
13
+ export declare function getFilenameExtensionHint(filename: string): string;
14
+ /**
15
+ * Get extension from URL or Content-Disposition.
16
+ */
17
+ export declare function getExtensionHint(url: string, contentDisposition?: string): string;
18
+ /**
19
+ * Check if content type is convertible via AutoRAG's parser registry.
20
+ */
21
+ export declare function isConvertible(mime: string, extensionHint: string): boolean;
22
+ /**
23
+ * Heuristic: does the text sample look like binary (NUL bytes or high U+FFFD density)?
24
+ */
25
+ export declare function sampleLooksBinary(text: string): boolean;
26
+ /**
27
+ * Build a textual binary notice for unsupported binary payloads.
28
+ */
29
+ export declare function buildBinaryNotice(finalUrl: string, mime: string, byteLength?: number): string;