@nhtio/adk 1.20260609.0 → 1.20260610.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/CHANGELOG.md +132 -9
- package/batteries/llm/ollama/helpers.cjs +9 -0
- package/batteries/llm/ollama/helpers.cjs.map +1 -1
- package/batteries/llm/ollama/helpers.mjs +9 -0
- package/batteries/llm/ollama/helpers.mjs.map +1 -1
- package/batteries/llm/openai_chat_completions/helpers.cjs +19 -0
- package/batteries/llm/openai_chat_completions/helpers.cjs.map +1 -1
- package/batteries/llm/openai_chat_completions/helpers.mjs +19 -0
- package/batteries/llm/openai_chat_completions/helpers.mjs.map +1 -1
- package/batteries/media/builder.d.ts +245 -0
- package/batteries/media/contracts.cjs +119 -0
- package/batteries/media/contracts.cjs.map +1 -0
- package/batteries/media/contracts.d.ts +321 -0
- package/batteries/media/contracts.mjs +110 -0
- package/batteries/media/contracts.mjs.map +1 -0
- package/batteries/media/engines/audio_decode.cjs +92 -0
- package/batteries/media/engines/audio_decode.cjs.map +1 -0
- package/batteries/media/engines/audio_decode.d.ts +46 -0
- package/batteries/media/engines/audio_decode.mjs +90 -0
- package/batteries/media/engines/audio_decode.mjs.map +1 -0
- package/batteries/media/engines/execa_executor.cjs +64 -0
- package/batteries/media/engines/execa_executor.cjs.map +1 -0
- package/batteries/media/engines/execa_executor.d.ts +54 -0
- package/batteries/media/engines/execa_executor.mjs +62 -0
- package/batteries/media/engines/execa_executor.mjs.map +1 -0
- package/batteries/media/engines/fs_workspace.cjs +84 -0
- package/batteries/media/engines/fs_workspace.cjs.map +1 -0
- package/batteries/media/engines/fs_workspace.d.ts +51 -0
- package/batteries/media/engines/fs_workspace.mjs +82 -0
- package/batteries/media/engines/fs_workspace.mjs.map +1 -0
- package/batteries/media/engines/jimp.cjs +116 -0
- package/batteries/media/engines/jimp.cjs.map +1 -0
- package/batteries/media/engines/jimp.d.ts +32 -0
- package/batteries/media/engines/jimp.mjs +114 -0
- package/batteries/media/engines/jimp.mjs.map +1 -0
- package/batteries/media/engines/sharp.cjs +120 -0
- package/batteries/media/engines/sharp.cjs.map +1 -0
- package/batteries/media/engines/sharp.d.ts +42 -0
- package/batteries/media/engines/sharp.mjs +117 -0
- package/batteries/media/engines/sharp.mjs.map +1 -0
- package/batteries/media/engines/soffice.cjs +246 -0
- package/batteries/media/engines/soffice.cjs.map +1 -0
- package/batteries/media/engines/soffice.d.ts +39 -0
- package/batteries/media/engines/soffice.mjs +244 -0
- package/batteries/media/engines/soffice.mjs.map +1 -0
- package/batteries/media/engines/tesseract_js.cjs +87 -0
- package/batteries/media/engines/tesseract_js.cjs.map +1 -0
- package/batteries/media/engines/tesseract_js.d.ts +41 -0
- package/batteries/media/engines/tesseract_js.mjs +85 -0
- package/batteries/media/engines/tesseract_js.mjs.map +1 -0
- package/batteries/media/engines/transformers_asr.cjs +111 -0
- package/batteries/media/engines/transformers_asr.cjs.map +1 -0
- package/batteries/media/engines/transformers_asr.d.ts +41 -0
- package/batteries/media/engines/transformers_asr.mjs +109 -0
- package/batteries/media/engines/transformers_asr.mjs.map +1 -0
- package/batteries/media/exceptions.d.ts +103 -0
- package/batteries/media/forge.cjs +403 -0
- package/batteries/media/forge.cjs.map +1 -0
- package/batteries/media/forge.d.ts +90 -0
- package/batteries/media/forge.mjs +399 -0
- package/batteries/media/forge.mjs.map +1 -0
- package/batteries/media/formats.d.ts +72 -0
- package/batteries/media/index.d.ts +136 -0
- package/batteries/media/lint.cjs +339 -0
- package/batteries/media/lint.cjs.map +1 -0
- package/batteries/media/lint.d.ts +117 -0
- package/batteries/media/lint.mjs +331 -0
- package/batteries/media/lint.mjs.map +1 -0
- package/batteries/media/pipe.d.ts +66 -0
- package/batteries/media/plan.d.ts +133 -0
- package/batteries/media/registry.d.ts +92 -0
- package/batteries/media/runtime.d.ts +105 -0
- package/batteries/media/steps/doc.d.ts +33 -0
- package/batteries/media/steps/image_audio.d.ts +24 -0
- package/batteries/media/steps/ingest.d.ts +25 -0
- package/batteries/media/steps/pages.d.ts +18 -0
- package/batteries/media/steps/sheet.d.ts +36 -0
- package/batteries/media/steps/slides.d.ts +35 -0
- package/batteries/media/steps/text.d.ts +43 -0
- package/batteries/media/validate.d.ts +49 -0
- package/batteries/media/verbs.d.ts +126 -0
- package/batteries/media.cjs +3049 -0
- package/batteries/media.cjs.map +1 -0
- package/batteries/media.mjs +3009 -0
- package/batteries/media.mjs.map +1 -0
- package/batteries/tools/_shared/index.d.ts +142 -0
- package/batteries/tools/_shared.cjs +173 -0
- package/batteries/tools/_shared.cjs.map +1 -0
- package/batteries/tools/_shared.mjs +164 -0
- package/batteries/tools/_shared.mjs.map +1 -0
- package/batteries/tools/index.d.ts +2 -0
- package/batteries/tools/scrapper/exceptions.d.ts +21 -0
- package/batteries/tools/scrapper/index.d.ts +172 -0
- package/batteries/tools/scrapper/shared.d.ts +146 -0
- package/batteries/tools/scrapper.cjs +8 -0
- package/batteries/tools/scrapper.mjs +2 -0
- package/batteries/tools/searxng/index.d.ts +54 -20
- package/batteries/tools/searxng.cjs +2 -1
- package/batteries/tools/searxng.mjs +2 -2
- package/batteries/tools/web_retrieval/index.d.ts +186 -0
- package/batteries/tools/web_retrieval.cjs +206 -0
- package/batteries/tools/web_retrieval.cjs.map +1 -0
- package/batteries/tools/web_retrieval.mjs +201 -0
- package/batteries/tools/web_retrieval.mjs.map +1 -0
- package/batteries/tools.cjs +13 -1
- package/batteries/tools.mjs +4 -2
- package/batteries.cjs +13 -1
- package/batteries.mjs +4 -2
- package/common.d.ts +1 -1
- package/eslint.cjs +1 -1
- package/eslint.mjs +1 -1
- package/exceptions-C7FSHEnV.mjs +87 -0
- package/exceptions-C7FSHEnV.mjs.map +1 -0
- package/exceptions-CQi_lNs1.js +152 -0
- package/exceptions-CQi_lNs1.js.map +1 -0
- package/index.cjs +2 -2
- package/index.mjs +2 -2
- package/mcp/adk-docs-corpus.json +1 -1
- package/package.json +301 -178
- package/scrapper-BOLWYGbD.js +463 -0
- package/scrapper-BOLWYGbD.js.map +1 -0
- package/scrapper-hDKlNuCT.mjs +433 -0
- package/scrapper-hDKlNuCT.mjs.map +1 -0
- package/{searxng-Bkrwhwhw.js → searxng-CJtEpa8p.js} +82 -85
- package/searxng-CJtEpa8p.js.map +1 -0
- package/{searxng-CyA-nEu5.mjs → searxng-riarj_0u.mjs} +76 -85
- package/searxng-riarj_0u.mjs.map +1 -0
- package/skills/adk-assembly/SKILL.md +2 -2
- package/validate-BFaUYHDN.js +1298 -0
- package/validate-BFaUYHDN.js.map +1 -0
- package/validate-DSZ3wicB.mjs +1215 -0
- package/validate-DSZ3wicB.mjs.map +1 -0
- package/searxng-Bkrwhwhw.js.map +0 -1
- package/searxng-CyA-nEu5.mjs.map +0 -1
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
require("../../../chunk-Ble4zEEl.js");
|
|
3
|
+
const require_tool_registry = require("../../../tool_registry-CKJPze3j.js");
|
|
4
|
+
require("../../../guards.cjs");
|
|
5
|
+
const require_exceptions = require("../../../exceptions-CQi_lNs1.js");
|
|
6
|
+
//#region src/batteries/media/engines/tesseract_js.ts
|
|
7
|
+
/**
|
|
8
|
+
* A cross-environment OCR {@link @nhtio/adk/batteries/media/contracts!MediaEngine}
|
|
9
|
+
* backed by tesseract.js (WASM Tesseract — Node and browsers, no binary).
|
|
10
|
+
*
|
|
11
|
+
* @module @nhtio/adk/batteries/media/engines/tesseract_js
|
|
12
|
+
*
|
|
13
|
+
* @remarks
|
|
14
|
+
* The local-by-default OCR engine. Language data files download on first use of each
|
|
15
|
+
* language; point `langPath`/`cachePath` at a writable location to control where (the
|
|
16
|
+
* factory requires `languages` up front so a deployment never silently fetches packs for
|
|
17
|
+
* languages it didn't plan for). Workers are created per recognize call and terminated in
|
|
18
|
+
* `finally` — slower than a pooled setup but leak-free by construction; consumers who need
|
|
19
|
+
* pooling can BYO an engine that holds a worker.
|
|
20
|
+
*
|
|
21
|
+
* `tesseract.js` is an optional peer dependency, lazily imported on first actual use.
|
|
22
|
+
*
|
|
23
|
+
* Declares one convert capability: `image/*` to `txt`/`hocr`/`json` (OCR is a format
|
|
24
|
+
* conversion — image in, text out). Language hints ride `request.options.languages`.
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Construct the tesseract.js OCR engine.
|
|
28
|
+
*
|
|
29
|
+
* @param options - Languages (required) and data-path overrides.
|
|
30
|
+
* @returns The engine.
|
|
31
|
+
*/
|
|
32
|
+
var tesseractJsEngine = (options) => {
|
|
33
|
+
if (!Array.isArray(options?.languages) || options.languages.length === 0) throw new require_exceptions.E_INVALID_MEDIA_PIPELINE_CONFIG(["tesseractJsEngine requires languages (e.g. [\"eng\"]) — language packs download on first use and are never chosen silently"]);
|
|
34
|
+
let modPromise;
|
|
35
|
+
const getModule = () => {
|
|
36
|
+
modPromise ??= Promise.resolve(options.tesseract ? options.tesseract() : import("tesseract.js")).catch((err) => {
|
|
37
|
+
throw new require_exceptions.E_INVALID_MEDIA_PIPELINE_CONFIG([`the tesseract.js engine could not load its peer dependency "tesseract.js": ${require_tool_registry.isError(err) ? err.message : String(err)} — install it (pnpm add tesseract.js)`]);
|
|
38
|
+
});
|
|
39
|
+
return modPromise;
|
|
40
|
+
};
|
|
41
|
+
const convert = async (request) => {
|
|
42
|
+
const mod = await getModule();
|
|
43
|
+
const languages = request.options?.languages ?? options.languages;
|
|
44
|
+
const worker = await mod.createWorker(languages, void 0, {
|
|
45
|
+
...options.langPath ? { langPath: options.langPath } : {},
|
|
46
|
+
...options.cachePath ? { cachePath: options.cachePath } : {}
|
|
47
|
+
});
|
|
48
|
+
try {
|
|
49
|
+
const result = await worker.recognize(typeof globalThis.Buffer !== "undefined" ? globalThis.Buffer.from(request.bytes.buffer, request.bytes.byteOffset, request.bytes.byteLength) : new Blob([request.bytes], { type: request.mimeType }));
|
|
50
|
+
let text = result.data.text;
|
|
51
|
+
let mimeType = "text/plain";
|
|
52
|
+
if (request.to === "json") {
|
|
53
|
+
text = JSON.stringify({
|
|
54
|
+
text: result.data.text,
|
|
55
|
+
confidence: result.data.confidence
|
|
56
|
+
});
|
|
57
|
+
mimeType = "application/json";
|
|
58
|
+
} else if (request.to === "hocr") {
|
|
59
|
+
const hocr = result.data.hocr;
|
|
60
|
+
text = hocr ?? result.data.text;
|
|
61
|
+
mimeType = hocr ? "text/html" : "text/plain";
|
|
62
|
+
}
|
|
63
|
+
return { outputs: [{
|
|
64
|
+
bytes: new TextEncoder().encode(text),
|
|
65
|
+
mimeType
|
|
66
|
+
}] };
|
|
67
|
+
} finally {
|
|
68
|
+
await worker.terminate();
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
return {
|
|
72
|
+
id: "tesseract.js",
|
|
73
|
+
converts: [{
|
|
74
|
+
from: ["image/*"],
|
|
75
|
+
to: [
|
|
76
|
+
"txt",
|
|
77
|
+
"hocr",
|
|
78
|
+
"json"
|
|
79
|
+
],
|
|
80
|
+
convert
|
|
81
|
+
}]
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
//#endregion
|
|
85
|
+
exports.tesseractJsEngine = tesseractJsEngine;
|
|
86
|
+
|
|
87
|
+
//# sourceMappingURL=tesseract_js.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tesseract_js.cjs","names":[],"sources":["../../../../src/batteries/media/engines/tesseract_js.ts"],"sourcesContent":["/**\n * A cross-environment OCR {@link @nhtio/adk/batteries/media/contracts!MediaEngine}\n * backed by tesseract.js (WASM Tesseract — Node and browsers, no binary).\n *\n * @module @nhtio/adk/batteries/media/engines/tesseract_js\n *\n * @remarks\n * The local-by-default OCR engine. Language data files download on first use of each\n * language; point `langPath`/`cachePath` at a writable location to control where (the\n * factory requires `languages` up front so a deployment never silently fetches packs for\n * languages it didn't plan for). Workers are created per recognize call and terminated in\n * `finally` — slower than a pooled setup but leak-free by construction; consumers who need\n * pooling can BYO an engine that holds a worker.\n *\n * `tesseract.js` is an optional peer dependency, lazily imported on first actual use.\n *\n * Declares one convert capability: `image/*` to `txt`/`hocr`/`json` (OCR is a format\n * conversion — image in, text out). Language hints ride `request.options.languages`.\n */\n\nimport { isError } from '@nhtio/adk/guards'\nimport { E_INVALID_MEDIA_PIPELINE_CONFIG } from '../exceptions'\nimport type * as TesseractNS from 'tesseract.js'\nimport type { MediaEngine, ConvertRequest, ConvertResult } from '../contracts'\n\ntype TesseractModule = typeof TesseractNS\n\n/** Options for {@link tesseractJsEngine}. */\nexport interface TesseractJsEngineOptions {\n /** Languages to load, e.g. `['eng']`. REQUIRED — language packs download on first use. */\n languages: readonly string[]\n /** Where language data is fetched from / cached (forwarded to createWorker). */\n langPath?: string\n /** Local cache directory for downloaded language data. */\n cachePath?: string\n /** Override the module resolution. Default: `import('tesseract.js')`. */\n tesseract?: () => TesseractModule | Promise<TesseractModule>\n}\n\n/**\n * Construct the tesseract.js OCR engine.\n *\n * @param options - Languages (required) and data-path overrides.\n * @returns The engine.\n */\nexport const tesseractJsEngine = (options: TesseractJsEngineOptions): MediaEngine => {\n if (!Array.isArray(options?.languages) || options.languages.length === 0) {\n throw new E_INVALID_MEDIA_PIPELINE_CONFIG([\n 'tesseractJsEngine requires languages (e.g. [\"eng\"]) — language packs download on first use and are never chosen silently',\n ])\n }\n let modPromise: Promise<TesseractModule> | undefined\n const getModule = (): Promise<TesseractModule> => {\n modPromise ??= Promise.resolve(\n options.tesseract ? options.tesseract() : import('tesseract.js')\n ).catch((err) => {\n const detail = isError(err) ? err.message : String(err)\n throw new E_INVALID_MEDIA_PIPELINE_CONFIG([\n `the tesseract.js engine could not load its peer dependency \"tesseract.js\": ${detail} — install it (pnpm add tesseract.js)`,\n ])\n })\n return modPromise\n }\n\n const convert = async (request: ConvertRequest): Promise<ConvertResult> => {\n const mod = await getModule()\n const languages = (request.options?.languages ?? options.languages) as string[]\n const worker = await mod.createWorker(languages, undefined, {\n ...(options.langPath ? { langPath: options.langPath } : {}),\n ...(options.cachePath ? { cachePath: options.cachePath } : {}),\n })\n try {\n const result = await worker.recognize(\n // tesseract.js accepts Buffer/Blob/ImageLike; raw bytes work via Buffer in Node\n typeof globalThis.Buffer !== 'undefined'\n ? globalThis.Buffer.from(\n request.bytes.buffer,\n request.bytes.byteOffset,\n request.bytes.byteLength\n )\n : new Blob([request.bytes as BlobPart], { type: request.mimeType })\n )\n let text = result.data.text\n let mimeType = 'text/plain'\n if (request.to === 'json') {\n text = JSON.stringify({ text: result.data.text, confidence: result.data.confidence })\n mimeType = 'application/json'\n } else if (request.to === 'hocr') {\n // hocr requires opting into the output at recognize time in tesseract.js v5+;\n // fall back to text when unavailable rather than failing the read.\n const hocr = (result.data as { hocr?: string | null }).hocr\n text = hocr ?? result.data.text\n mimeType = hocr ? 'text/html' : 'text/plain'\n }\n return { outputs: [{ bytes: new TextEncoder().encode(text), mimeType }] }\n } finally {\n await worker.terminate()\n }\n }\n\n return {\n id: 'tesseract.js',\n converts: [\n {\n from: ['image/*'],\n to: ['txt', 'hocr', 'json'],\n convert,\n },\n ],\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,IAAa,qBAAqB,YAAmD;CACnF,IAAI,CAAC,MAAM,QAAQ,SAAS,SAAS,KAAK,QAAQ,UAAU,WAAW,GACrE,MAAM,IAAI,mBAAA,gCAAgC,CACxC,4HACF,CAAC;CAEH,IAAI;CACJ,MAAM,kBAA4C;EAChD,eAAe,QAAQ,QACrB,QAAQ,YAAY,QAAQ,UAAU,IAAI,OAAO,eACnD,EAAE,OAAO,QAAQ;GAEf,MAAM,IAAI,mBAAA,gCAAgC,CACxC,8EAFa,sBAAA,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG,EAEiC,sCACvF,CAAC;EACH,CAAC;EACD,OAAO;CACT;CAEA,MAAM,UAAU,OAAO,YAAoD;EACzE,MAAM,MAAM,MAAM,UAAU;EAC5B,MAAM,YAAa,QAAQ,SAAS,aAAa,QAAQ;EACzD,MAAM,SAAS,MAAM,IAAI,aAAa,WAAW,KAAA,GAAW;GAC1D,GAAI,QAAQ,WAAW,EAAE,UAAU,QAAQ,SAAS,IAAI,CAAC;GACzD,GAAI,QAAQ,YAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;EAC9D,CAAC;EACD,IAAI;GACF,MAAM,SAAS,MAAM,OAAO,UAE1B,OAAO,WAAW,WAAW,cACzB,WAAW,OAAO,KAChB,QAAQ,MAAM,QACd,QAAQ,MAAM,YACd,QAAQ,MAAM,UAChB,IACA,IAAI,KAAK,CAAC,QAAQ,KAAiB,GAAG,EAAE,MAAM,QAAQ,SAAS,CAAC,CACtE;GACA,IAAI,OAAO,OAAO,KAAK;GACvB,IAAI,WAAW;GACf,IAAI,QAAQ,OAAO,QAAQ;IACzB,OAAO,KAAK,UAAU;KAAE,MAAM,OAAO,KAAK;KAAM,YAAY,OAAO,KAAK;IAAW,CAAC;IACpF,WAAW;GACb,OAAO,IAAI,QAAQ,OAAO,QAAQ;IAGhC,MAAM,OAAQ,OAAO,KAAkC;IACvD,OAAO,QAAQ,OAAO,KAAK;IAC3B,WAAW,OAAO,cAAc;GAClC;GACA,OAAO,EAAE,SAAS,CAAC;IAAE,OAAO,IAAI,YAAY,EAAE,OAAO,IAAI;IAAG;GAAS,CAAC,EAAE;EAC1E,UAAU;GACR,MAAM,OAAO,UAAU;EACzB;CACF;CAEA,OAAO;EACL,IAAI;EACJ,UAAU,CACR;GACE,MAAM,CAAC,SAAS;GAChB,IAAI;IAAC;IAAO;IAAQ;GAAM;GAC1B;EACF,CACF;CACF;AACF"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A cross-environment OCR {@link @nhtio/adk/batteries/media/contracts!MediaEngine}
|
|
3
|
+
* backed by tesseract.js (WASM Tesseract — Node and browsers, no binary).
|
|
4
|
+
*
|
|
5
|
+
* @module @nhtio/adk/batteries/media/engines/tesseract_js
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* The local-by-default OCR engine. Language data files download on first use of each
|
|
9
|
+
* language; point `langPath`/`cachePath` at a writable location to control where (the
|
|
10
|
+
* factory requires `languages` up front so a deployment never silently fetches packs for
|
|
11
|
+
* languages it didn't plan for). Workers are created per recognize call and terminated in
|
|
12
|
+
* `finally` — slower than a pooled setup but leak-free by construction; consumers who need
|
|
13
|
+
* pooling can BYO an engine that holds a worker.
|
|
14
|
+
*
|
|
15
|
+
* `tesseract.js` is an optional peer dependency, lazily imported on first actual use.
|
|
16
|
+
*
|
|
17
|
+
* Declares one convert capability: `image/*` to `txt`/`hocr`/`json` (OCR is a format
|
|
18
|
+
* conversion — image in, text out). Language hints ride `request.options.languages`.
|
|
19
|
+
*/
|
|
20
|
+
import type * as TesseractNS from 'tesseract.js';
|
|
21
|
+
import type { MediaEngine } from "../contracts";
|
|
22
|
+
type TesseractModule = typeof TesseractNS;
|
|
23
|
+
/** Options for {@link tesseractJsEngine}. */
|
|
24
|
+
export interface TesseractJsEngineOptions {
|
|
25
|
+
/** Languages to load, e.g. `['eng']`. REQUIRED — language packs download on first use. */
|
|
26
|
+
languages: readonly string[];
|
|
27
|
+
/** Where language data is fetched from / cached (forwarded to createWorker). */
|
|
28
|
+
langPath?: string;
|
|
29
|
+
/** Local cache directory for downloaded language data. */
|
|
30
|
+
cachePath?: string;
|
|
31
|
+
/** Override the module resolution. Default: `import('tesseract.js')`. */
|
|
32
|
+
tesseract?: () => TesseractModule | Promise<TesseractModule>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Construct the tesseract.js OCR engine.
|
|
36
|
+
*
|
|
37
|
+
* @param options - Languages (required) and data-path overrides.
|
|
38
|
+
* @returns The engine.
|
|
39
|
+
*/
|
|
40
|
+
export declare const tesseractJsEngine: (options: TesseractJsEngineOptions) => MediaEngine;
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { o as isError } from "../../../tool_registry-791Vrjtf.mjs";
|
|
2
|
+
import "../../../guards.mjs";
|
|
3
|
+
import { t as E_INVALID_MEDIA_PIPELINE_CONFIG } from "../../../exceptions-C7FSHEnV.mjs";
|
|
4
|
+
//#region src/batteries/media/engines/tesseract_js.ts
|
|
5
|
+
/**
|
|
6
|
+
* A cross-environment OCR {@link @nhtio/adk/batteries/media/contracts!MediaEngine}
|
|
7
|
+
* backed by tesseract.js (WASM Tesseract — Node and browsers, no binary).
|
|
8
|
+
*
|
|
9
|
+
* @module @nhtio/adk/batteries/media/engines/tesseract_js
|
|
10
|
+
*
|
|
11
|
+
* @remarks
|
|
12
|
+
* The local-by-default OCR engine. Language data files download on first use of each
|
|
13
|
+
* language; point `langPath`/`cachePath` at a writable location to control where (the
|
|
14
|
+
* factory requires `languages` up front so a deployment never silently fetches packs for
|
|
15
|
+
* languages it didn't plan for). Workers are created per recognize call and terminated in
|
|
16
|
+
* `finally` — slower than a pooled setup but leak-free by construction; consumers who need
|
|
17
|
+
* pooling can BYO an engine that holds a worker.
|
|
18
|
+
*
|
|
19
|
+
* `tesseract.js` is an optional peer dependency, lazily imported on first actual use.
|
|
20
|
+
*
|
|
21
|
+
* Declares one convert capability: `image/*` to `txt`/`hocr`/`json` (OCR is a format
|
|
22
|
+
* conversion — image in, text out). Language hints ride `request.options.languages`.
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Construct the tesseract.js OCR engine.
|
|
26
|
+
*
|
|
27
|
+
* @param options - Languages (required) and data-path overrides.
|
|
28
|
+
* @returns The engine.
|
|
29
|
+
*/
|
|
30
|
+
var tesseractJsEngine = (options) => {
|
|
31
|
+
if (!Array.isArray(options?.languages) || options.languages.length === 0) throw new E_INVALID_MEDIA_PIPELINE_CONFIG(["tesseractJsEngine requires languages (e.g. [\"eng\"]) — language packs download on first use and are never chosen silently"]);
|
|
32
|
+
let modPromise;
|
|
33
|
+
const getModule = () => {
|
|
34
|
+
modPromise ??= Promise.resolve(options.tesseract ? options.tesseract() : import("tesseract.js")).catch((err) => {
|
|
35
|
+
throw new E_INVALID_MEDIA_PIPELINE_CONFIG([`the tesseract.js engine could not load its peer dependency "tesseract.js": ${isError(err) ? err.message : String(err)} — install it (pnpm add tesseract.js)`]);
|
|
36
|
+
});
|
|
37
|
+
return modPromise;
|
|
38
|
+
};
|
|
39
|
+
const convert = async (request) => {
|
|
40
|
+
const mod = await getModule();
|
|
41
|
+
const languages = request.options?.languages ?? options.languages;
|
|
42
|
+
const worker = await mod.createWorker(languages, void 0, {
|
|
43
|
+
...options.langPath ? { langPath: options.langPath } : {},
|
|
44
|
+
...options.cachePath ? { cachePath: options.cachePath } : {}
|
|
45
|
+
});
|
|
46
|
+
try {
|
|
47
|
+
const result = await worker.recognize(typeof globalThis.Buffer !== "undefined" ? globalThis.Buffer.from(request.bytes.buffer, request.bytes.byteOffset, request.bytes.byteLength) : new Blob([request.bytes], { type: request.mimeType }));
|
|
48
|
+
let text = result.data.text;
|
|
49
|
+
let mimeType = "text/plain";
|
|
50
|
+
if (request.to === "json") {
|
|
51
|
+
text = JSON.stringify({
|
|
52
|
+
text: result.data.text,
|
|
53
|
+
confidence: result.data.confidence
|
|
54
|
+
});
|
|
55
|
+
mimeType = "application/json";
|
|
56
|
+
} else if (request.to === "hocr") {
|
|
57
|
+
const hocr = result.data.hocr;
|
|
58
|
+
text = hocr ?? result.data.text;
|
|
59
|
+
mimeType = hocr ? "text/html" : "text/plain";
|
|
60
|
+
}
|
|
61
|
+
return { outputs: [{
|
|
62
|
+
bytes: new TextEncoder().encode(text),
|
|
63
|
+
mimeType
|
|
64
|
+
}] };
|
|
65
|
+
} finally {
|
|
66
|
+
await worker.terminate();
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
return {
|
|
70
|
+
id: "tesseract.js",
|
|
71
|
+
converts: [{
|
|
72
|
+
from: ["image/*"],
|
|
73
|
+
to: [
|
|
74
|
+
"txt",
|
|
75
|
+
"hocr",
|
|
76
|
+
"json"
|
|
77
|
+
],
|
|
78
|
+
convert
|
|
79
|
+
}]
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
//#endregion
|
|
83
|
+
export { tesseractJsEngine };
|
|
84
|
+
|
|
85
|
+
//# sourceMappingURL=tesseract_js.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tesseract_js.mjs","names":[],"sources":["../../../../src/batteries/media/engines/tesseract_js.ts"],"sourcesContent":["/**\n * A cross-environment OCR {@link @nhtio/adk/batteries/media/contracts!MediaEngine}\n * backed by tesseract.js (WASM Tesseract — Node and browsers, no binary).\n *\n * @module @nhtio/adk/batteries/media/engines/tesseract_js\n *\n * @remarks\n * The local-by-default OCR engine. Language data files download on first use of each\n * language; point `langPath`/`cachePath` at a writable location to control where (the\n * factory requires `languages` up front so a deployment never silently fetches packs for\n * languages it didn't plan for). Workers are created per recognize call and terminated in\n * `finally` — slower than a pooled setup but leak-free by construction; consumers who need\n * pooling can BYO an engine that holds a worker.\n *\n * `tesseract.js` is an optional peer dependency, lazily imported on first actual use.\n *\n * Declares one convert capability: `image/*` to `txt`/`hocr`/`json` (OCR is a format\n * conversion — image in, text out). Language hints ride `request.options.languages`.\n */\n\nimport { isError } from '@nhtio/adk/guards'\nimport { E_INVALID_MEDIA_PIPELINE_CONFIG } from '../exceptions'\nimport type * as TesseractNS from 'tesseract.js'\nimport type { MediaEngine, ConvertRequest, ConvertResult } from '../contracts'\n\ntype TesseractModule = typeof TesseractNS\n\n/** Options for {@link tesseractJsEngine}. */\nexport interface TesseractJsEngineOptions {\n /** Languages to load, e.g. `['eng']`. REQUIRED — language packs download on first use. */\n languages: readonly string[]\n /** Where language data is fetched from / cached (forwarded to createWorker). */\n langPath?: string\n /** Local cache directory for downloaded language data. */\n cachePath?: string\n /** Override the module resolution. Default: `import('tesseract.js')`. */\n tesseract?: () => TesseractModule | Promise<TesseractModule>\n}\n\n/**\n * Construct the tesseract.js OCR engine.\n *\n * @param options - Languages (required) and data-path overrides.\n * @returns The engine.\n */\nexport const tesseractJsEngine = (options: TesseractJsEngineOptions): MediaEngine => {\n if (!Array.isArray(options?.languages) || options.languages.length === 0) {\n throw new E_INVALID_MEDIA_PIPELINE_CONFIG([\n 'tesseractJsEngine requires languages (e.g. [\"eng\"]) — language packs download on first use and are never chosen silently',\n ])\n }\n let modPromise: Promise<TesseractModule> | undefined\n const getModule = (): Promise<TesseractModule> => {\n modPromise ??= Promise.resolve(\n options.tesseract ? options.tesseract() : import('tesseract.js')\n ).catch((err) => {\n const detail = isError(err) ? err.message : String(err)\n throw new E_INVALID_MEDIA_PIPELINE_CONFIG([\n `the tesseract.js engine could not load its peer dependency \"tesseract.js\": ${detail} — install it (pnpm add tesseract.js)`,\n ])\n })\n return modPromise\n }\n\n const convert = async (request: ConvertRequest): Promise<ConvertResult> => {\n const mod = await getModule()\n const languages = (request.options?.languages ?? options.languages) as string[]\n const worker = await mod.createWorker(languages, undefined, {\n ...(options.langPath ? { langPath: options.langPath } : {}),\n ...(options.cachePath ? { cachePath: options.cachePath } : {}),\n })\n try {\n const result = await worker.recognize(\n // tesseract.js accepts Buffer/Blob/ImageLike; raw bytes work via Buffer in Node\n typeof globalThis.Buffer !== 'undefined'\n ? globalThis.Buffer.from(\n request.bytes.buffer,\n request.bytes.byteOffset,\n request.bytes.byteLength\n )\n : new Blob([request.bytes as BlobPart], { type: request.mimeType })\n )\n let text = result.data.text\n let mimeType = 'text/plain'\n if (request.to === 'json') {\n text = JSON.stringify({ text: result.data.text, confidence: result.data.confidence })\n mimeType = 'application/json'\n } else if (request.to === 'hocr') {\n // hocr requires opting into the output at recognize time in tesseract.js v5+;\n // fall back to text when unavailable rather than failing the read.\n const hocr = (result.data as { hocr?: string | null }).hocr\n text = hocr ?? result.data.text\n mimeType = hocr ? 'text/html' : 'text/plain'\n }\n return { outputs: [{ bytes: new TextEncoder().encode(text), mimeType }] }\n } finally {\n await worker.terminate()\n }\n }\n\n return {\n id: 'tesseract.js',\n converts: [\n {\n from: ['image/*'],\n to: ['txt', 'hocr', 'json'],\n convert,\n },\n ],\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,IAAa,qBAAqB,YAAmD;CACnF,IAAI,CAAC,MAAM,QAAQ,SAAS,SAAS,KAAK,QAAQ,UAAU,WAAW,GACrE,MAAM,IAAI,gCAAgC,CACxC,4HACF,CAAC;CAEH,IAAI;CACJ,MAAM,kBAA4C;EAChD,eAAe,QAAQ,QACrB,QAAQ,YAAY,QAAQ,UAAU,IAAI,OAAO,eACnD,EAAE,OAAO,QAAQ;GAEf,MAAM,IAAI,gCAAgC,CACxC,8EAFa,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG,EAEiC,sCACvF,CAAC;EACH,CAAC;EACD,OAAO;CACT;CAEA,MAAM,UAAU,OAAO,YAAoD;EACzE,MAAM,MAAM,MAAM,UAAU;EAC5B,MAAM,YAAa,QAAQ,SAAS,aAAa,QAAQ;EACzD,MAAM,SAAS,MAAM,IAAI,aAAa,WAAW,KAAA,GAAW;GAC1D,GAAI,QAAQ,WAAW,EAAE,UAAU,QAAQ,SAAS,IAAI,CAAC;GACzD,GAAI,QAAQ,YAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;EAC9D,CAAC;EACD,IAAI;GACF,MAAM,SAAS,MAAM,OAAO,UAE1B,OAAO,WAAW,WAAW,cACzB,WAAW,OAAO,KAChB,QAAQ,MAAM,QACd,QAAQ,MAAM,YACd,QAAQ,MAAM,UAChB,IACA,IAAI,KAAK,CAAC,QAAQ,KAAiB,GAAG,EAAE,MAAM,QAAQ,SAAS,CAAC,CACtE;GACA,IAAI,OAAO,OAAO,KAAK;GACvB,IAAI,WAAW;GACf,IAAI,QAAQ,OAAO,QAAQ;IACzB,OAAO,KAAK,UAAU;KAAE,MAAM,OAAO,KAAK;KAAM,YAAY,OAAO,KAAK;IAAW,CAAC;IACpF,WAAW;GACb,OAAO,IAAI,QAAQ,OAAO,QAAQ;IAGhC,MAAM,OAAQ,OAAO,KAAkC;IACvD,OAAO,QAAQ,OAAO,KAAK;IAC3B,WAAW,OAAO,cAAc;GAClC;GACA,OAAO,EAAE,SAAS,CAAC;IAAE,OAAO,IAAI,YAAY,EAAE,OAAO,IAAI;IAAG;GAAS,CAAC,EAAE;EAC1E,UAAU;GACR,MAAM,OAAO,UAAU;EACzB;CACF;CAEA,OAAO;EACL,IAAI;EACJ,UAAU,CACR;GACE,MAAM,CAAC,SAAS;GAChB,IAAI;IAAC;IAAO;IAAQ;GAAM;GAC1B;EACF,CACF;CACF;AACF"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
require("../../../chunk-Ble4zEEl.js");
|
|
3
|
+
const require_tool_registry = require("../../../tool_registry-CKJPze3j.js");
|
|
4
|
+
require("../../../guards.cjs");
|
|
5
|
+
const require_batteries_media_contracts = require("../contracts.cjs");
|
|
6
|
+
const require_exceptions = require("../../../exceptions-CQi_lNs1.js");
|
|
7
|
+
//#region src/batteries/media/engines/transformers_asr.ts
|
|
8
|
+
/**
|
|
9
|
+
* A cross-environment transcription {@link @nhtio/adk/batteries/media/contracts!MediaEngine}
|
|
10
|
+
* backed by `@huggingface/transformers` Whisper (ONNX in Node, WASM/WebGPU in browsers).
|
|
11
|
+
*
|
|
12
|
+
* @module @nhtio/adk/batteries/media/engines/transformers_asr
|
|
13
|
+
*
|
|
14
|
+
* @remarks
|
|
15
|
+
* The local-by-default speech-to-text engine: no external API, no binary. Declares one
|
|
16
|
+
* convert capability: the virtual `pcm` token to `txt`/`srt`/`vtt`/`json` (transcription is a
|
|
17
|
+
* format conversion — PCM in, text out). The Whisper model id is REQUIRED — models are
|
|
18
|
+
* multi-hundred-megabyte downloads on first use and the battery never triggers one silently
|
|
19
|
+
* (the loud-config rule). Input is 16 kHz mono PCM, exactly what the transcribe step
|
|
20
|
+
* supplies; `lang`/`translate` ride `request.options`. `srt`/`vtt` output is assembled from
|
|
21
|
+
* chunk timestamps; `json` returns the chunk structure verbatim.
|
|
22
|
+
*
|
|
23
|
+
* `@huggingface/transformers` is an optional peer dependency, lazily imported on first
|
|
24
|
+
* actual use.
|
|
25
|
+
*/
|
|
26
|
+
var pad = (n, width = 2) => String(Math.floor(n)).padStart(width, "0");
|
|
27
|
+
var formatTimestamp = (seconds, separator) => {
|
|
28
|
+
const h = Math.floor(seconds / 3600);
|
|
29
|
+
const m = Math.floor(seconds % 3600 / 60);
|
|
30
|
+
const s = Math.floor(seconds % 60);
|
|
31
|
+
const ms = Math.floor(seconds % 1 * 1e3);
|
|
32
|
+
return `${pad(h)}:${pad(m)}:${pad(s)}${separator}${String(ms).padStart(3, "0")}`;
|
|
33
|
+
};
|
|
34
|
+
var toSubtitles = (chunks, kind) => {
|
|
35
|
+
const sep = kind === "srt" ? "," : ".";
|
|
36
|
+
const blocks = chunks.map((chunk, i) => {
|
|
37
|
+
const [start, end] = chunk.timestamp;
|
|
38
|
+
const range = `${formatTimestamp(start, sep)} --> ${formatTimestamp(end ?? start, sep)}`;
|
|
39
|
+
return kind === "srt" ? `${i + 1}\n${range}\n${chunk.text.trim()}` : `${range}\n${chunk.text.trim()}`;
|
|
40
|
+
});
|
|
41
|
+
return kind === "vtt" ? `WEBVTT\n\n${blocks.join("\n\n")}\n` : `${blocks.join("\n\n")}\n`;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Construct the transformers.js Whisper ASR engine.
|
|
45
|
+
*
|
|
46
|
+
* @param options - Model id (required) and overrides.
|
|
47
|
+
* @returns The engine.
|
|
48
|
+
*/
|
|
49
|
+
var transformersAsrEngine = (options) => {
|
|
50
|
+
if (typeof options?.model !== "string" || options.model.length === 0) throw new require_exceptions.E_INVALID_MEDIA_PIPELINE_CONFIG(["transformersAsrEngine requires an explicit Whisper model id (e.g. onnx-community/whisper-base) — models are large downloads and are never chosen silently"]);
|
|
51
|
+
let pipePromise;
|
|
52
|
+
const getPipeline = () => {
|
|
53
|
+
pipePromise ??= (async () => {
|
|
54
|
+
let mod;
|
|
55
|
+
try {
|
|
56
|
+
mod = await (options.transformers ? options.transformers() : import("@huggingface/transformers"));
|
|
57
|
+
} catch (err) {
|
|
58
|
+
throw new require_exceptions.E_INVALID_MEDIA_PIPELINE_CONFIG([`the transformers ASR engine could not load its peer dependency "@huggingface/transformers": ${require_tool_registry.isError(err) ? err.message : String(err)} — install it (pnpm add @huggingface/transformers)`]);
|
|
59
|
+
}
|
|
60
|
+
return await mod.pipeline("automatic-speech-recognition", options.model, { ...options.pipelineOptions ?? {} });
|
|
61
|
+
})();
|
|
62
|
+
return pipePromise;
|
|
63
|
+
};
|
|
64
|
+
const convert = async (request) => {
|
|
65
|
+
const pipe = await getPipeline();
|
|
66
|
+
const lang = request.options?.lang;
|
|
67
|
+
const translate = request.options?.translate;
|
|
68
|
+
const wantsTimestamps = request.to === "srt" || request.to === "vtt" || request.to === "json";
|
|
69
|
+
const result = await pipe(require_batteries_media_contracts.bytesToPcm(request.bytes), {
|
|
70
|
+
...lang ? { language: lang } : {},
|
|
71
|
+
...translate ? { task: "translate" } : {},
|
|
72
|
+
...wantsTimestamps ? { return_timestamps: true } : {},
|
|
73
|
+
chunk_length_s: 30
|
|
74
|
+
});
|
|
75
|
+
const output = Array.isArray(result) ? result[0] : result;
|
|
76
|
+
let text;
|
|
77
|
+
let mimeType = "text/plain";
|
|
78
|
+
if (request.to === "json") {
|
|
79
|
+
text = JSON.stringify({
|
|
80
|
+
text: output.text,
|
|
81
|
+
chunks: output.chunks ?? []
|
|
82
|
+
});
|
|
83
|
+
mimeType = "application/json";
|
|
84
|
+
} else if (request.to === "srt" || request.to === "vtt") text = toSubtitles(output.chunks ?? [{
|
|
85
|
+
timestamp: [0, null],
|
|
86
|
+
text: output.text
|
|
87
|
+
}], request.to);
|
|
88
|
+
else text = output.text.trim();
|
|
89
|
+
return { outputs: [{
|
|
90
|
+
bytes: new TextEncoder().encode(text),
|
|
91
|
+
mimeType
|
|
92
|
+
}] };
|
|
93
|
+
};
|
|
94
|
+
return {
|
|
95
|
+
id: "transformers-asr",
|
|
96
|
+
converts: [{
|
|
97
|
+
from: [require_batteries_media_contracts.PCM_MIME],
|
|
98
|
+
to: [
|
|
99
|
+
"txt",
|
|
100
|
+
"srt",
|
|
101
|
+
"vtt",
|
|
102
|
+
"json"
|
|
103
|
+
],
|
|
104
|
+
convert
|
|
105
|
+
}]
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
//#endregion
|
|
109
|
+
exports.transformersAsrEngine = transformersAsrEngine;
|
|
110
|
+
|
|
111
|
+
//# sourceMappingURL=transformers_asr.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transformers_asr.cjs","names":[],"sources":["../../../../src/batteries/media/engines/transformers_asr.ts"],"sourcesContent":["/**\n * A cross-environment transcription {@link @nhtio/adk/batteries/media/contracts!MediaEngine}\n * backed by `@huggingface/transformers` Whisper (ONNX in Node, WASM/WebGPU in browsers).\n *\n * @module @nhtio/adk/batteries/media/engines/transformers_asr\n *\n * @remarks\n * The local-by-default speech-to-text engine: no external API, no binary. Declares one\n * convert capability: the virtual `pcm` token to `txt`/`srt`/`vtt`/`json` (transcription is a\n * format conversion — PCM in, text out). The Whisper model id is REQUIRED — models are\n * multi-hundred-megabyte downloads on first use and the battery never triggers one silently\n * (the loud-config rule). Input is 16 kHz mono PCM, exactly what the transcribe step\n * supplies; `lang`/`translate` ride `request.options`. `srt`/`vtt` output is assembled from\n * chunk timestamps; `json` returns the chunk structure verbatim.\n *\n * `@huggingface/transformers` is an optional peer dependency, lazily imported on first\n * actual use.\n */\n\nimport { isError } from '@nhtio/adk/guards'\nimport { bytesToPcm, PCM_MIME } from '../contracts'\nimport { E_INVALID_MEDIA_PIPELINE_CONFIG } from '../exceptions'\nimport type * as TransformersNS from '@huggingface/transformers'\nimport type { MediaEngine, ConvertRequest, ConvertResult } from '../contracts'\n\ntype TransformersModule = typeof TransformersNS\n\ninterface AsrChunk {\n timestamp: [number, number | null]\n text: string\n}\n\ninterface AsrPipelineOutput {\n text: string\n chunks?: AsrChunk[]\n}\n\ntype AsrPipelineFn = (\n audio: Float32Array,\n options: Record<string, unknown>\n) => Promise<AsrPipelineOutput | AsrPipelineOutput[]>\n\n/** Options for {@link transformersAsrEngine}. */\nexport interface TransformersAsrEngineOptions {\n /**\n * The Whisper model id, e.g. `onnx-community/whisper-base`. REQUIRED — no default, no\n * surprise downloads.\n */\n model: string\n /** Override the module resolution. Default: `import('@huggingface/transformers')`. */\n transformers?: () => TransformersModule | Promise<TransformersModule>\n /** Extra options forwarded to `pipeline()` (device, dtype, cache_dir…). */\n pipelineOptions?: Record<string, unknown>\n}\n\nconst pad = (n: number, width = 2): string => String(Math.floor(n)).padStart(width, '0')\n\nconst formatTimestamp = (seconds: number, separator: ',' | '.'): string => {\n const h = Math.floor(seconds / 3600)\n const m = Math.floor((seconds % 3600) / 60)\n const s = Math.floor(seconds % 60)\n const ms = Math.floor((seconds % 1) * 1000)\n return `${pad(h)}:${pad(m)}:${pad(s)}${separator}${String(ms).padStart(3, '0')}`\n}\n\nconst toSubtitles = (chunks: AsrChunk[], kind: 'srt' | 'vtt'): string => {\n const sep = kind === 'srt' ? ',' : '.'\n const blocks = chunks.map((chunk, i) => {\n const [start, end] = chunk.timestamp\n const range = `${formatTimestamp(start, sep)} --> ${formatTimestamp(end ?? start, sep)}`\n return kind === 'srt'\n ? `${i + 1}\\n${range}\\n${chunk.text.trim()}`\n : `${range}\\n${chunk.text.trim()}`\n })\n return kind === 'vtt' ? `WEBVTT\\n\\n${blocks.join('\\n\\n')}\\n` : `${blocks.join('\\n\\n')}\\n`\n}\n\n/**\n * Construct the transformers.js Whisper ASR engine.\n *\n * @param options - Model id (required) and overrides.\n * @returns The engine.\n */\nexport const transformersAsrEngine = (options: TransformersAsrEngineOptions): MediaEngine => {\n if (typeof options?.model !== 'string' || options.model.length === 0) {\n throw new E_INVALID_MEDIA_PIPELINE_CONFIG([\n 'transformersAsrEngine requires an explicit Whisper model id (e.g. onnx-community/whisper-base) — models are large downloads and are never chosen silently',\n ])\n }\n let pipePromise: Promise<AsrPipelineFn> | undefined\n const getPipeline = (): Promise<AsrPipelineFn> => {\n pipePromise ??= (async () => {\n let mod: TransformersModule\n try {\n mod = await (options.transformers\n ? options.transformers()\n : import('@huggingface/transformers'))\n } catch (err) {\n const detail = isError(err) ? err.message : String(err)\n throw new E_INVALID_MEDIA_PIPELINE_CONFIG([\n `the transformers ASR engine could not load its peer dependency \"@huggingface/transformers\": ${detail} — install it (pnpm add @huggingface/transformers)`,\n ])\n }\n const pipe = await mod.pipeline('automatic-speech-recognition', options.model, {\n ...(options.pipelineOptions ?? {}),\n } as never)\n return pipe as unknown as AsrPipelineFn\n })()\n return pipePromise\n }\n\n const convert = async (request: ConvertRequest): Promise<ConvertResult> => {\n const pipe = await getPipeline()\n const lang = request.options?.lang\n const translate = request.options?.translate\n const wantsTimestamps = request.to === 'srt' || request.to === 'vtt' || request.to === 'json'\n const result = await pipe(bytesToPcm(request.bytes), {\n ...(lang ? { language: lang } : {}),\n ...(translate ? { task: 'translate' } : {}),\n ...(wantsTimestamps ? { return_timestamps: true } : {}),\n chunk_length_s: 30,\n })\n const output = Array.isArray(result) ? result[0] : result\n let text: string\n let mimeType = 'text/plain'\n if (request.to === 'json') {\n text = JSON.stringify({ text: output.text, chunks: output.chunks ?? [] })\n mimeType = 'application/json'\n } else if (request.to === 'srt' || request.to === 'vtt') {\n const chunks = output.chunks ?? [\n { timestamp: [0, null] as [number, null], text: output.text },\n ]\n text = toSubtitles(chunks, request.to)\n } else {\n text = output.text.trim()\n }\n return { outputs: [{ bytes: new TextEncoder().encode(text), mimeType }] }\n }\n\n return {\n id: 'transformers-asr',\n converts: [\n {\n from: [PCM_MIME],\n to: ['txt', 'srt', 'vtt', 'json'],\n convert,\n },\n ],\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAuDA,IAAM,OAAO,GAAW,QAAQ,MAAc,OAAO,KAAK,MAAM,CAAC,CAAC,EAAE,SAAS,OAAO,GAAG;AAEvF,IAAM,mBAAmB,SAAiB,cAAiC;CACzE,MAAM,IAAI,KAAK,MAAM,UAAU,IAAI;CACnC,MAAM,IAAI,KAAK,MAAO,UAAU,OAAQ,EAAE;CAC1C,MAAM,IAAI,KAAK,MAAM,UAAU,EAAE;CACjC,MAAM,KAAK,KAAK,MAAO,UAAU,IAAK,GAAI;CAC1C,OAAO,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,IAAI,YAAY,OAAO,EAAE,EAAE,SAAS,GAAG,GAAG;AAC/E;AAEA,IAAM,eAAe,QAAoB,SAAgC;CACvE,MAAM,MAAM,SAAS,QAAQ,MAAM;CACnC,MAAM,SAAS,OAAO,KAAK,OAAO,MAAM;EACtC,MAAM,CAAC,OAAO,OAAO,MAAM;EAC3B,MAAM,QAAQ,GAAG,gBAAgB,OAAO,GAAG,EAAE,OAAO,gBAAgB,OAAO,OAAO,GAAG;EACrF,OAAO,SAAS,QACZ,GAAG,IAAI,EAAE,IAAI,MAAM,IAAI,MAAM,KAAK,KAAK,MACvC,GAAG,MAAM,IAAI,MAAM,KAAK,KAAK;CACnC,CAAC;CACD,OAAO,SAAS,QAAQ,aAAa,OAAO,KAAK,MAAM,EAAE,MAAM,GAAG,OAAO,KAAK,MAAM,EAAE;AACxF;;;;;;;AAQA,IAAa,yBAAyB,YAAuD;CAC3F,IAAI,OAAO,SAAS,UAAU,YAAY,QAAQ,MAAM,WAAW,GACjE,MAAM,IAAI,mBAAA,gCAAgC,CACxC,2JACF,CAAC;CAEH,IAAI;CACJ,MAAM,oBAA4C;EAChD,iBAAiB,YAAY;GAC3B,IAAI;GACJ,IAAI;IACF,MAAM,OAAO,QAAQ,eACjB,QAAQ,aAAa,IACrB,OAAO;GACb,SAAS,KAAK;IAEZ,MAAM,IAAI,mBAAA,gCAAgC,CACxC,+FAFa,sBAAA,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG,EAEkD,mDACxG,CAAC;GACH;GAIA,OAAO,MAHY,IAAI,SAAS,gCAAgC,QAAQ,OAAO,EAC7E,GAAI,QAAQ,mBAAmB,CAAC,EAClC,CAAU;EAEZ,GAAG;EACH,OAAO;CACT;CAEA,MAAM,UAAU,OAAO,YAAoD;EACzE,MAAM,OAAO,MAAM,YAAY;EAC/B,MAAM,OAAO,QAAQ,SAAS;EAC9B,MAAM,YAAY,QAAQ,SAAS;EACnC,MAAM,kBAAkB,QAAQ,OAAO,SAAS,QAAQ,OAAO,SAAS,QAAQ,OAAO;EACvF,MAAM,SAAS,MAAM,KAAK,kCAAA,WAAW,QAAQ,KAAK,GAAG;GACnD,GAAI,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;GACjC,GAAI,YAAY,EAAE,MAAM,YAAY,IAAI,CAAC;GACzC,GAAI,kBAAkB,EAAE,mBAAmB,KAAK,IAAI,CAAC;GACrD,gBAAgB;EAClB,CAAC;EACD,MAAM,SAAS,MAAM,QAAQ,MAAM,IAAI,OAAO,KAAK;EACnD,IAAI;EACJ,IAAI,WAAW;EACf,IAAI,QAAQ,OAAO,QAAQ;GACzB,OAAO,KAAK,UAAU;IAAE,MAAM,OAAO;IAAM,QAAQ,OAAO,UAAU,CAAC;GAAE,CAAC;GACxE,WAAW;EACb,OAAO,IAAI,QAAQ,OAAO,SAAS,QAAQ,OAAO,OAIhD,OAAO,YAHQ,OAAO,UAAU,CAC9B;GAAE,WAAW,CAAC,GAAG,IAAI;GAAqB,MAAM,OAAO;EAAK,CAC9D,GAC2B,QAAQ,EAAE;OAErC,OAAO,OAAO,KAAK,KAAK;EAE1B,OAAO,EAAE,SAAS,CAAC;GAAE,OAAO,IAAI,YAAY,EAAE,OAAO,IAAI;GAAG;EAAS,CAAC,EAAE;CAC1E;CAEA,OAAO;EACL,IAAI;EACJ,UAAU,CACR;GACE,MAAM,CAAC,kCAAA,QAAQ;GACf,IAAI;IAAC;IAAO;IAAO;IAAO;GAAM;GAChC;EACF,CACF;CACF;AACF"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A cross-environment transcription {@link @nhtio/adk/batteries/media/contracts!MediaEngine}
|
|
3
|
+
* backed by `@huggingface/transformers` Whisper (ONNX in Node, WASM/WebGPU in browsers).
|
|
4
|
+
*
|
|
5
|
+
* @module @nhtio/adk/batteries/media/engines/transformers_asr
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* The local-by-default speech-to-text engine: no external API, no binary. Declares one
|
|
9
|
+
* convert capability: the virtual `pcm` token to `txt`/`srt`/`vtt`/`json` (transcription is a
|
|
10
|
+
* format conversion — PCM in, text out). The Whisper model id is REQUIRED — models are
|
|
11
|
+
* multi-hundred-megabyte downloads on first use and the battery never triggers one silently
|
|
12
|
+
* (the loud-config rule). Input is 16 kHz mono PCM, exactly what the transcribe step
|
|
13
|
+
* supplies; `lang`/`translate` ride `request.options`. `srt`/`vtt` output is assembled from
|
|
14
|
+
* chunk timestamps; `json` returns the chunk structure verbatim.
|
|
15
|
+
*
|
|
16
|
+
* `@huggingface/transformers` is an optional peer dependency, lazily imported on first
|
|
17
|
+
* actual use.
|
|
18
|
+
*/
|
|
19
|
+
import type * as TransformersNS from '@huggingface/transformers';
|
|
20
|
+
import type { MediaEngine } from "../contracts";
|
|
21
|
+
type TransformersModule = typeof TransformersNS;
|
|
22
|
+
/** Options for {@link transformersAsrEngine}. */
|
|
23
|
+
export interface TransformersAsrEngineOptions {
|
|
24
|
+
/**
|
|
25
|
+
* The Whisper model id, e.g. `onnx-community/whisper-base`. REQUIRED — no default, no
|
|
26
|
+
* surprise downloads.
|
|
27
|
+
*/
|
|
28
|
+
model: string;
|
|
29
|
+
/** Override the module resolution. Default: `import('@huggingface/transformers')`. */
|
|
30
|
+
transformers?: () => TransformersModule | Promise<TransformersModule>;
|
|
31
|
+
/** Extra options forwarded to `pipeline()` (device, dtype, cache_dir…). */
|
|
32
|
+
pipelineOptions?: Record<string, unknown>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Construct the transformers.js Whisper ASR engine.
|
|
36
|
+
*
|
|
37
|
+
* @param options - Model id (required) and overrides.
|
|
38
|
+
* @returns The engine.
|
|
39
|
+
*/
|
|
40
|
+
export declare const transformersAsrEngine: (options: TransformersAsrEngineOptions) => MediaEngine;
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { o as isError } from "../../../tool_registry-791Vrjtf.mjs";
|
|
2
|
+
import "../../../guards.mjs";
|
|
3
|
+
import { PCM_MIME, bytesToPcm } from "../contracts.mjs";
|
|
4
|
+
import { t as E_INVALID_MEDIA_PIPELINE_CONFIG } from "../../../exceptions-C7FSHEnV.mjs";
|
|
5
|
+
//#region src/batteries/media/engines/transformers_asr.ts
|
|
6
|
+
/**
|
|
7
|
+
* A cross-environment transcription {@link @nhtio/adk/batteries/media/contracts!MediaEngine}
|
|
8
|
+
* backed by `@huggingface/transformers` Whisper (ONNX in Node, WASM/WebGPU in browsers).
|
|
9
|
+
*
|
|
10
|
+
* @module @nhtio/adk/batteries/media/engines/transformers_asr
|
|
11
|
+
*
|
|
12
|
+
* @remarks
|
|
13
|
+
* The local-by-default speech-to-text engine: no external API, no binary. Declares one
|
|
14
|
+
* convert capability: the virtual `pcm` token to `txt`/`srt`/`vtt`/`json` (transcription is a
|
|
15
|
+
* format conversion — PCM in, text out). The Whisper model id is REQUIRED — models are
|
|
16
|
+
* multi-hundred-megabyte downloads on first use and the battery never triggers one silently
|
|
17
|
+
* (the loud-config rule). Input is 16 kHz mono PCM, exactly what the transcribe step
|
|
18
|
+
* supplies; `lang`/`translate` ride `request.options`. `srt`/`vtt` output is assembled from
|
|
19
|
+
* chunk timestamps; `json` returns the chunk structure verbatim.
|
|
20
|
+
*
|
|
21
|
+
* `@huggingface/transformers` is an optional peer dependency, lazily imported on first
|
|
22
|
+
* actual use.
|
|
23
|
+
*/
|
|
24
|
+
var pad = (n, width = 2) => String(Math.floor(n)).padStart(width, "0");
|
|
25
|
+
var formatTimestamp = (seconds, separator) => {
|
|
26
|
+
const h = Math.floor(seconds / 3600);
|
|
27
|
+
const m = Math.floor(seconds % 3600 / 60);
|
|
28
|
+
const s = Math.floor(seconds % 60);
|
|
29
|
+
const ms = Math.floor(seconds % 1 * 1e3);
|
|
30
|
+
return `${pad(h)}:${pad(m)}:${pad(s)}${separator}${String(ms).padStart(3, "0")}`;
|
|
31
|
+
};
|
|
32
|
+
var toSubtitles = (chunks, kind) => {
|
|
33
|
+
const sep = kind === "srt" ? "," : ".";
|
|
34
|
+
const blocks = chunks.map((chunk, i) => {
|
|
35
|
+
const [start, end] = chunk.timestamp;
|
|
36
|
+
const range = `${formatTimestamp(start, sep)} --> ${formatTimestamp(end ?? start, sep)}`;
|
|
37
|
+
return kind === "srt" ? `${i + 1}\n${range}\n${chunk.text.trim()}` : `${range}\n${chunk.text.trim()}`;
|
|
38
|
+
});
|
|
39
|
+
return kind === "vtt" ? `WEBVTT\n\n${blocks.join("\n\n")}\n` : `${blocks.join("\n\n")}\n`;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Construct the transformers.js Whisper ASR engine.
|
|
43
|
+
*
|
|
44
|
+
* @param options - Model id (required) and overrides.
|
|
45
|
+
* @returns The engine.
|
|
46
|
+
*/
|
|
47
|
+
var transformersAsrEngine = (options) => {
|
|
48
|
+
if (typeof options?.model !== "string" || options.model.length === 0) throw new E_INVALID_MEDIA_PIPELINE_CONFIG(["transformersAsrEngine requires an explicit Whisper model id (e.g. onnx-community/whisper-base) — models are large downloads and are never chosen silently"]);
|
|
49
|
+
let pipePromise;
|
|
50
|
+
const getPipeline = () => {
|
|
51
|
+
pipePromise ??= (async () => {
|
|
52
|
+
let mod;
|
|
53
|
+
try {
|
|
54
|
+
mod = await (options.transformers ? options.transformers() : import("@huggingface/transformers"));
|
|
55
|
+
} catch (err) {
|
|
56
|
+
throw new E_INVALID_MEDIA_PIPELINE_CONFIG([`the transformers ASR engine could not load its peer dependency "@huggingface/transformers": ${isError(err) ? err.message : String(err)} — install it (pnpm add @huggingface/transformers)`]);
|
|
57
|
+
}
|
|
58
|
+
return await mod.pipeline("automatic-speech-recognition", options.model, { ...options.pipelineOptions ?? {} });
|
|
59
|
+
})();
|
|
60
|
+
return pipePromise;
|
|
61
|
+
};
|
|
62
|
+
const convert = async (request) => {
|
|
63
|
+
const pipe = await getPipeline();
|
|
64
|
+
const lang = request.options?.lang;
|
|
65
|
+
const translate = request.options?.translate;
|
|
66
|
+
const wantsTimestamps = request.to === "srt" || request.to === "vtt" || request.to === "json";
|
|
67
|
+
const result = await pipe(bytesToPcm(request.bytes), {
|
|
68
|
+
...lang ? { language: lang } : {},
|
|
69
|
+
...translate ? { task: "translate" } : {},
|
|
70
|
+
...wantsTimestamps ? { return_timestamps: true } : {},
|
|
71
|
+
chunk_length_s: 30
|
|
72
|
+
});
|
|
73
|
+
const output = Array.isArray(result) ? result[0] : result;
|
|
74
|
+
let text;
|
|
75
|
+
let mimeType = "text/plain";
|
|
76
|
+
if (request.to === "json") {
|
|
77
|
+
text = JSON.stringify({
|
|
78
|
+
text: output.text,
|
|
79
|
+
chunks: output.chunks ?? []
|
|
80
|
+
});
|
|
81
|
+
mimeType = "application/json";
|
|
82
|
+
} else if (request.to === "srt" || request.to === "vtt") text = toSubtitles(output.chunks ?? [{
|
|
83
|
+
timestamp: [0, null],
|
|
84
|
+
text: output.text
|
|
85
|
+
}], request.to);
|
|
86
|
+
else text = output.text.trim();
|
|
87
|
+
return { outputs: [{
|
|
88
|
+
bytes: new TextEncoder().encode(text),
|
|
89
|
+
mimeType
|
|
90
|
+
}] };
|
|
91
|
+
};
|
|
92
|
+
return {
|
|
93
|
+
id: "transformers-asr",
|
|
94
|
+
converts: [{
|
|
95
|
+
from: [PCM_MIME],
|
|
96
|
+
to: [
|
|
97
|
+
"txt",
|
|
98
|
+
"srt",
|
|
99
|
+
"vtt",
|
|
100
|
+
"json"
|
|
101
|
+
],
|
|
102
|
+
convert
|
|
103
|
+
}]
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
//#endregion
|
|
107
|
+
export { transformersAsrEngine };
|
|
108
|
+
|
|
109
|
+
//# sourceMappingURL=transformers_asr.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transformers_asr.mjs","names":[],"sources":["../../../../src/batteries/media/engines/transformers_asr.ts"],"sourcesContent":["/**\n * A cross-environment transcription {@link @nhtio/adk/batteries/media/contracts!MediaEngine}\n * backed by `@huggingface/transformers` Whisper (ONNX in Node, WASM/WebGPU in browsers).\n *\n * @module @nhtio/adk/batteries/media/engines/transformers_asr\n *\n * @remarks\n * The local-by-default speech-to-text engine: no external API, no binary. Declares one\n * convert capability: the virtual `pcm` token to `txt`/`srt`/`vtt`/`json` (transcription is a\n * format conversion — PCM in, text out). The Whisper model id is REQUIRED — models are\n * multi-hundred-megabyte downloads on first use and the battery never triggers one silently\n * (the loud-config rule). Input is 16 kHz mono PCM, exactly what the transcribe step\n * supplies; `lang`/`translate` ride `request.options`. `srt`/`vtt` output is assembled from\n * chunk timestamps; `json` returns the chunk structure verbatim.\n *\n * `@huggingface/transformers` is an optional peer dependency, lazily imported on first\n * actual use.\n */\n\nimport { isError } from '@nhtio/adk/guards'\nimport { bytesToPcm, PCM_MIME } from '../contracts'\nimport { E_INVALID_MEDIA_PIPELINE_CONFIG } from '../exceptions'\nimport type * as TransformersNS from '@huggingface/transformers'\nimport type { MediaEngine, ConvertRequest, ConvertResult } from '../contracts'\n\ntype TransformersModule = typeof TransformersNS\n\ninterface AsrChunk {\n timestamp: [number, number | null]\n text: string\n}\n\ninterface AsrPipelineOutput {\n text: string\n chunks?: AsrChunk[]\n}\n\ntype AsrPipelineFn = (\n audio: Float32Array,\n options: Record<string, unknown>\n) => Promise<AsrPipelineOutput | AsrPipelineOutput[]>\n\n/** Options for {@link transformersAsrEngine}. */\nexport interface TransformersAsrEngineOptions {\n /**\n * The Whisper model id, e.g. `onnx-community/whisper-base`. REQUIRED — no default, no\n * surprise downloads.\n */\n model: string\n /** Override the module resolution. Default: `import('@huggingface/transformers')`. */\n transformers?: () => TransformersModule | Promise<TransformersModule>\n /** Extra options forwarded to `pipeline()` (device, dtype, cache_dir…). */\n pipelineOptions?: Record<string, unknown>\n}\n\nconst pad = (n: number, width = 2): string => String(Math.floor(n)).padStart(width, '0')\n\nconst formatTimestamp = (seconds: number, separator: ',' | '.'): string => {\n const h = Math.floor(seconds / 3600)\n const m = Math.floor((seconds % 3600) / 60)\n const s = Math.floor(seconds % 60)\n const ms = Math.floor((seconds % 1) * 1000)\n return `${pad(h)}:${pad(m)}:${pad(s)}${separator}${String(ms).padStart(3, '0')}`\n}\n\nconst toSubtitles = (chunks: AsrChunk[], kind: 'srt' | 'vtt'): string => {\n const sep = kind === 'srt' ? ',' : '.'\n const blocks = chunks.map((chunk, i) => {\n const [start, end] = chunk.timestamp\n const range = `${formatTimestamp(start, sep)} --> ${formatTimestamp(end ?? start, sep)}`\n return kind === 'srt'\n ? `${i + 1}\\n${range}\\n${chunk.text.trim()}`\n : `${range}\\n${chunk.text.trim()}`\n })\n return kind === 'vtt' ? `WEBVTT\\n\\n${blocks.join('\\n\\n')}\\n` : `${blocks.join('\\n\\n')}\\n`\n}\n\n/**\n * Construct the transformers.js Whisper ASR engine.\n *\n * @param options - Model id (required) and overrides.\n * @returns The engine.\n */\nexport const transformersAsrEngine = (options: TransformersAsrEngineOptions): MediaEngine => {\n if (typeof options?.model !== 'string' || options.model.length === 0) {\n throw new E_INVALID_MEDIA_PIPELINE_CONFIG([\n 'transformersAsrEngine requires an explicit Whisper model id (e.g. onnx-community/whisper-base) — models are large downloads and are never chosen silently',\n ])\n }\n let pipePromise: Promise<AsrPipelineFn> | undefined\n const getPipeline = (): Promise<AsrPipelineFn> => {\n pipePromise ??= (async () => {\n let mod: TransformersModule\n try {\n mod = await (options.transformers\n ? options.transformers()\n : import('@huggingface/transformers'))\n } catch (err) {\n const detail = isError(err) ? err.message : String(err)\n throw new E_INVALID_MEDIA_PIPELINE_CONFIG([\n `the transformers ASR engine could not load its peer dependency \"@huggingface/transformers\": ${detail} — install it (pnpm add @huggingface/transformers)`,\n ])\n }\n const pipe = await mod.pipeline('automatic-speech-recognition', options.model, {\n ...(options.pipelineOptions ?? {}),\n } as never)\n return pipe as unknown as AsrPipelineFn\n })()\n return pipePromise\n }\n\n const convert = async (request: ConvertRequest): Promise<ConvertResult> => {\n const pipe = await getPipeline()\n const lang = request.options?.lang\n const translate = request.options?.translate\n const wantsTimestamps = request.to === 'srt' || request.to === 'vtt' || request.to === 'json'\n const result = await pipe(bytesToPcm(request.bytes), {\n ...(lang ? { language: lang } : {}),\n ...(translate ? { task: 'translate' } : {}),\n ...(wantsTimestamps ? { return_timestamps: true } : {}),\n chunk_length_s: 30,\n })\n const output = Array.isArray(result) ? result[0] : result\n let text: string\n let mimeType = 'text/plain'\n if (request.to === 'json') {\n text = JSON.stringify({ text: output.text, chunks: output.chunks ?? [] })\n mimeType = 'application/json'\n } else if (request.to === 'srt' || request.to === 'vtt') {\n const chunks = output.chunks ?? [\n { timestamp: [0, null] as [number, null], text: output.text },\n ]\n text = toSubtitles(chunks, request.to)\n } else {\n text = output.text.trim()\n }\n return { outputs: [{ bytes: new TextEncoder().encode(text), mimeType }] }\n }\n\n return {\n id: 'transformers-asr',\n converts: [\n {\n from: [PCM_MIME],\n to: ['txt', 'srt', 'vtt', 'json'],\n convert,\n },\n ],\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Battery-scoped exceptions for the media pipeline battery.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* Internal sibling of the `@nhtio/adk/batteries/media` entry — re-exported from the battery's
|
|
6
|
+
* own barrel per the battery-scoped-exceptions rule. These are the typed errors the
|
|
7
|
+
* implementor-facing API throws; the agent-facing forge catches them and renders readable
|
|
8
|
+
* failure strings the model can act on.
|
|
9
|
+
*
|
|
10
|
+
* Error layering (see the design doc, frozen section 0):
|
|
11
|
+
*
|
|
12
|
+
* - Config errors (`E_INVALID_MEDIA_PIPELINE_CONFIG`) throw at pipeline construction or first
|
|
13
|
+
* engine-resolver resolution. Fatal — a programmer mistake, not a runtime condition.
|
|
14
|
+
* - Syntactic pipe errors (`E_MEDIA_PIPE_SYNTAX`) carry line/col position plus a
|
|
15
|
+
* "write it like:" exemplar, because models repair from instructions, not carets.
|
|
16
|
+
* - Semantic plan errors (`E_MEDIA_UNKNOWN_VERB`, `E_MEDIA_UNKNOWN_ARG`, `E_MEDIA_BAD_ARG`,
|
|
17
|
+
* `E_MEDIA_MISSING_ARG`, `E_MEDIA_UNSUPPORTED_OP`, `E_MEDIA_ENGINE_REQUIRED`) are produced by
|
|
18
|
+
* the plan validator walking the AST against the full verb table and the configured engines.
|
|
19
|
+
* - Render errors (`E_MEDIA_NOT_PIPE_EXPRESSIBLE`) come from `toPipe()` on plans containing
|
|
20
|
+
* builder-only constructs.
|
|
21
|
+
* - Execution errors (`E_MEDIA_STEP_FAILED`, `E_MEDIA_STEP_UNAVAILABLE`) surface step-runtime
|
|
22
|
+
* failures with the original error as `cause`.
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Thrown when `createMediaPipeline` receives an invalid configuration — a malformed engine,
|
|
26
|
+
* a resolver that resolved to a value failing its contract guard, or an invalid option shape.
|
|
27
|
+
*/
|
|
28
|
+
export declare const E_INVALID_MEDIA_PIPELINE_CONFIG: import("../../factories").CreatedException<[
|
|
29
|
+
string
|
|
30
|
+
]>;
|
|
31
|
+
/**
|
|
32
|
+
* Thrown by `parsePipe` when the pipe expression fails to tokenize or parse. The message carries
|
|
33
|
+
* line/col position and a corrective exemplar.
|
|
34
|
+
*/
|
|
35
|
+
export declare const E_MEDIA_PIPE_SYNTAX: import("../../factories").CreatedException<[
|
|
36
|
+
string
|
|
37
|
+
]>;
|
|
38
|
+
/**
|
|
39
|
+
* Thrown when a statement names a verb that does not exist in the verb table. The message
|
|
40
|
+
* includes a did-you-mean suggestion (Levenshtein over folded verb forms, including suffix-word
|
|
41
|
+
* matches) and the list of verbs available in this deployment.
|
|
42
|
+
*/
|
|
43
|
+
export declare const E_MEDIA_UNKNOWN_VERB: import("../../factories").CreatedException<[
|
|
44
|
+
string
|
|
45
|
+
]>;
|
|
46
|
+
/**
|
|
47
|
+
* Thrown when a statement passes an arg a verb does not declare. The message includes a
|
|
48
|
+
* did-you-mean suggestion and the verb's declared args.
|
|
49
|
+
*/
|
|
50
|
+
export declare const E_MEDIA_UNKNOWN_ARG: import("../../factories").CreatedException<[
|
|
51
|
+
string
|
|
52
|
+
]>;
|
|
53
|
+
/**
|
|
54
|
+
* Thrown when an arg value fails its declared type/enum/constraint — including descending
|
|
55
|
+
* ranges, invalid regex sources, malformed embedded JSON, and out-of-enum values.
|
|
56
|
+
*/
|
|
57
|
+
export declare const E_MEDIA_BAD_ARG: import("../../factories").CreatedException<[
|
|
58
|
+
string
|
|
59
|
+
]>;
|
|
60
|
+
/** Thrown when a verb's required arg is absent from the statement. */
|
|
61
|
+
export declare const E_MEDIA_MISSING_ARG: import("../../factories").CreatedException<[
|
|
62
|
+
string
|
|
63
|
+
]>;
|
|
64
|
+
/**
|
|
65
|
+
* Thrown at plan validation when a verb cannot apply to the input's format family (e.g. a
|
|
66
|
+
* `sheet.*` verb on a PDF), or a namespace verb is used on the wrong media kind.
|
|
67
|
+
*/
|
|
68
|
+
export declare const E_MEDIA_UNSUPPORTED_OP: import("../../factories").CreatedException<[
|
|
69
|
+
string
|
|
70
|
+
]>;
|
|
71
|
+
/**
|
|
72
|
+
* Thrown at plan validation when a verb (or the specific input it is applied to) requires an
|
|
73
|
+
* engine that is not configured on this pipeline. The message states which engine slot is
|
|
74
|
+
* missing and — when the failure is input-specific — that the verb should not be retried on
|
|
75
|
+
* this media in this deployment.
|
|
76
|
+
*/
|
|
77
|
+
export declare const E_MEDIA_ENGINE_REQUIRED: import("../../factories").CreatedException<[
|
|
78
|
+
string
|
|
79
|
+
]>;
|
|
80
|
+
/**
|
|
81
|
+
* Thrown by `toPipe()` when the plan contains constructs the flat pipe grammar cannot express —
|
|
82
|
+
* currently only nested-builder media refs. Quoted-JSON structured args DO render; use `toOps()`
|
|
83
|
+
* for a total serialization.
|
|
84
|
+
*/
|
|
85
|
+
export declare const E_MEDIA_NOT_PIPE_EXPRESSIBLE: import("../../factories").CreatedException<[
|
|
86
|
+
string
|
|
87
|
+
]>;
|
|
88
|
+
/**
|
|
89
|
+
* Thrown by the step runtime when a step implementation fails mid-execution (corrupt input,
|
|
90
|
+
* engine error). Carries the underlying error as `cause`.
|
|
91
|
+
*/
|
|
92
|
+
export declare const E_MEDIA_STEP_FAILED: import("../../factories").CreatedException<[
|
|
93
|
+
string,
|
|
94
|
+
string
|
|
95
|
+
]>;
|
|
96
|
+
/**
|
|
97
|
+
* Thrown by the step runtime when a plan step has no registered implementation. Distinct from
|
|
98
|
+
* `E_MEDIA_ENGINE_REQUIRED`: this indicates the battery itself does not (yet) implement the
|
|
99
|
+
* verb, not that the consumer omitted an engine.
|
|
100
|
+
*/
|
|
101
|
+
export declare const E_MEDIA_STEP_UNAVAILABLE: import("../../factories").CreatedException<[
|
|
102
|
+
string
|
|
103
|
+
]>;
|