@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,90 @@
|
|
|
1
|
+
import { o as isError } from "../../../tool_registry-791Vrjtf.mjs";
|
|
2
|
+
import "../../../guards.mjs";
|
|
3
|
+
import { PCM_MIME, pcmToBytes } from "../contracts.mjs";
|
|
4
|
+
import { t as E_INVALID_MEDIA_PIPELINE_CONFIG } from "../../../exceptions-C7FSHEnV.mjs";
|
|
5
|
+
//#region src/batteries/media/engines/audio_decode.ts
|
|
6
|
+
/**
|
|
7
|
+
* A cross-environment audio-decoding {@link @nhtio/adk/batteries/media/contracts!MediaEngine}
|
|
8
|
+
* backed by the `audio-decode` package (pure JS/WASM codecs — no ffmpeg, no native bindings;
|
|
9
|
+
* works in Node and browsers).
|
|
10
|
+
*
|
|
11
|
+
* @module @nhtio/adk/batteries/media/engines/audio_decode
|
|
12
|
+
*
|
|
13
|
+
* @remarks
|
|
14
|
+
* Declares one convert capability: audio containers to the virtual `pcm` token (mp3 /
|
|
15
|
+
* m4a-aac / ogg-vorbis / opus / flac / wav), downmixed to mono. The PCM output reports the
|
|
16
|
+
* SOURCE sample rate in `meta.sampleRate` — the pipeline's transcribe step resamples to the
|
|
17
|
+
* 16 kHz transcription engines expect. For exotic containers, compose an ffmpeg-backed
|
|
18
|
+
* engine instead; the capability declaration is the seam.
|
|
19
|
+
*
|
|
20
|
+
* `audio-decode` is an optional peer dependency, lazily imported on first actual use.
|
|
21
|
+
*/
|
|
22
|
+
var channelsOf = (buffer) => {
|
|
23
|
+
if (Array.isArray(buffer.channelData)) return buffer.channelData;
|
|
24
|
+
if (typeof buffer.getChannelData === "function") {
|
|
25
|
+
const count = buffer.numberOfChannels ?? 1;
|
|
26
|
+
return Array.from({ length: count }, (_, c) => buffer.getChannelData(c));
|
|
27
|
+
}
|
|
28
|
+
throw new Error("audio-decode returned an unrecognized buffer shape");
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Construct the audio-decode-backed engine.
|
|
32
|
+
*
|
|
33
|
+
* @param options - Optional module resolver override.
|
|
34
|
+
* @returns The engine.
|
|
35
|
+
*/
|
|
36
|
+
var audioDecodeEngine = (options = {}) => {
|
|
37
|
+
let fnPromise;
|
|
38
|
+
const getDecode = () => {
|
|
39
|
+
fnPromise ??= Promise.resolve(options.audioDecode ? options.audioDecode() : import("audio-decode")).then((mod) => {
|
|
40
|
+
const fn = typeof mod === "function" ? mod : mod.default;
|
|
41
|
+
if (typeof fn !== "function") throw new Error("audio-decode did not resolve to a decode function");
|
|
42
|
+
return fn;
|
|
43
|
+
}).catch((err) => {
|
|
44
|
+
throw new E_INVALID_MEDIA_PIPELINE_CONFIG([`the audio-decode engine could not load its peer dependency "audio-decode": ${isError(err) ? err.message : String(err)} — install it (pnpm add audio-decode)`]);
|
|
45
|
+
});
|
|
46
|
+
return fnPromise;
|
|
47
|
+
};
|
|
48
|
+
const convert = async (request) => {
|
|
49
|
+
const buffer = await (await getDecode())(request.bytes);
|
|
50
|
+
const channels = channelsOf(buffer);
|
|
51
|
+
let pcm;
|
|
52
|
+
if (channels.length <= 1) pcm = channels[0];
|
|
53
|
+
else {
|
|
54
|
+
const length = channels[0].length;
|
|
55
|
+
const mono = new Float32Array(length);
|
|
56
|
+
for (const data of channels) for (let i = 0; i < length; i++) mono[i] += data[i] / channels.length;
|
|
57
|
+
pcm = mono;
|
|
58
|
+
}
|
|
59
|
+
return { outputs: [{
|
|
60
|
+
bytes: pcmToBytes(pcm),
|
|
61
|
+
mimeType: PCM_MIME,
|
|
62
|
+
meta: { sampleRate: buffer.sampleRate }
|
|
63
|
+
}] };
|
|
64
|
+
};
|
|
65
|
+
return {
|
|
66
|
+
id: "audio-decode",
|
|
67
|
+
converts: [{
|
|
68
|
+
from: [
|
|
69
|
+
"audio/mpeg",
|
|
70
|
+
"audio/mp3",
|
|
71
|
+
"audio/mp4",
|
|
72
|
+
"audio/aac",
|
|
73
|
+
"audio/x-m4a",
|
|
74
|
+
"audio/ogg",
|
|
75
|
+
"audio/opus",
|
|
76
|
+
"audio/flac",
|
|
77
|
+
"audio/x-flac",
|
|
78
|
+
"audio/wav",
|
|
79
|
+
"audio/x-wav",
|
|
80
|
+
"audio/wave"
|
|
81
|
+
],
|
|
82
|
+
to: ["pcm"],
|
|
83
|
+
convert
|
|
84
|
+
}]
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
//#endregion
|
|
88
|
+
export { audioDecodeEngine };
|
|
89
|
+
|
|
90
|
+
//# sourceMappingURL=audio_decode.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audio_decode.mjs","names":[],"sources":["../../../../src/batteries/media/engines/audio_decode.ts"],"sourcesContent":["/**\n * A cross-environment audio-decoding {@link @nhtio/adk/batteries/media/contracts!MediaEngine}\n * backed by the `audio-decode` package (pure JS/WASM codecs — no ffmpeg, no native bindings;\n * works in Node and browsers).\n *\n * @module @nhtio/adk/batteries/media/engines/audio_decode\n *\n * @remarks\n * Declares one convert capability: audio containers to the virtual `pcm` token (mp3 /\n * m4a-aac / ogg-vorbis / opus / flac / wav), downmixed to mono. The PCM output reports the\n * SOURCE sample rate in `meta.sampleRate` — the pipeline's transcribe step resamples to the\n * 16 kHz transcription engines expect. For exotic containers, compose an ffmpeg-backed\n * engine instead; the capability declaration is the seam.\n *\n * `audio-decode` is an optional peer dependency, lazily imported on first actual use.\n */\n\nimport { isError } from '@nhtio/adk/guards'\nimport { pcmToBytes, PCM_MIME } from '../contracts'\nimport { E_INVALID_MEDIA_PIPELINE_CONFIG } from '../exceptions'\nimport type { MediaEngine, ConvertRequest, ConvertResult } from '../contracts'\n\n/**\n * The decoded shapes audio-decode resolves to. Some codecs return an AudioBuffer-compatible\n * object (`numberOfChannels` + `getChannelData`); others (e.g. the wav path in Node) return a\n * plain `{ channelData: Float32Array[], sampleRate }` record. The engine normalizes both.\n */\ninterface AudioBufferLike {\n numberOfChannels?: number\n sampleRate: number\n getChannelData?(channel: number): Float32Array\n channelData?: Float32Array[]\n}\n\ntype AudioDecodeFn = (bytes: Uint8Array | ArrayBuffer) => Promise<AudioBufferLike>\n\nconst channelsOf = (buffer: AudioBufferLike): Float32Array[] => {\n if (Array.isArray(buffer.channelData)) return buffer.channelData\n if (typeof buffer.getChannelData === 'function') {\n const count = buffer.numberOfChannels ?? 1\n return Array.from({ length: count }, (_, c) => buffer.getChannelData!(c))\n }\n throw new Error('audio-decode returned an unrecognized buffer shape')\n}\n\n/** Options for {@link audioDecodeEngine}. */\nexport interface AudioDecodeEngineOptions {\n /** Override the module resolution. Default: `import('audio-decode')`. */\n audioDecode?: () =>\n | AudioDecodeFn\n | { default: AudioDecodeFn }\n | Promise<AudioDecodeFn | { default: AudioDecodeFn }>\n}\n\n/**\n * Construct the audio-decode-backed engine.\n *\n * @param options - Optional module resolver override.\n * @returns The engine.\n */\nexport const audioDecodeEngine = (options: AudioDecodeEngineOptions = {}): MediaEngine => {\n let fnPromise: Promise<AudioDecodeFn> | undefined\n const getDecode = (): Promise<AudioDecodeFn> => {\n fnPromise ??= Promise.resolve(\n options.audioDecode ? options.audioDecode() : import('audio-decode')\n )\n .then((mod) => {\n const fn = typeof mod === 'function' ? mod : (mod as { default: AudioDecodeFn }).default\n if (typeof fn !== 'function') {\n throw new Error('audio-decode did not resolve to a decode function')\n }\n return fn\n })\n .catch((err) => {\n const detail = isError(err) ? err.message : String(err)\n throw new E_INVALID_MEDIA_PIPELINE_CONFIG([\n `the audio-decode engine could not load its peer dependency \"audio-decode\": ${detail} — install it (pnpm add audio-decode)`,\n ])\n })\n return fnPromise\n }\n\n const convert = async (request: ConvertRequest): Promise<ConvertResult> => {\n const decode = await getDecode()\n const buffer = await decode(request.bytes)\n const channels = channelsOf(buffer)\n let pcm: Float32Array\n if (channels.length <= 1) {\n pcm = channels[0]\n } else {\n // Downmix to mono by averaging channels.\n const length = channels[0].length\n const mono = new Float32Array(length)\n for (const data of channels) {\n for (let i = 0; i < length; i++) mono[i] += data[i] / channels.length\n }\n pcm = mono\n }\n return {\n outputs: [\n { bytes: pcmToBytes(pcm), mimeType: PCM_MIME, meta: { sampleRate: buffer.sampleRate } },\n ],\n }\n }\n\n return {\n id: 'audio-decode',\n converts: [\n {\n from: [\n 'audio/mpeg',\n 'audio/mp3',\n 'audio/mp4',\n 'audio/aac',\n 'audio/x-m4a',\n 'audio/ogg',\n 'audio/opus',\n 'audio/flac',\n 'audio/x-flac',\n 'audio/wav',\n 'audio/x-wav',\n 'audio/wave',\n ],\n to: ['pcm'],\n convert,\n },\n ],\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAoCA,IAAM,cAAc,WAA4C;CAC9D,IAAI,MAAM,QAAQ,OAAO,WAAW,GAAG,OAAO,OAAO;CACrD,IAAI,OAAO,OAAO,mBAAmB,YAAY;EAC/C,MAAM,QAAQ,OAAO,oBAAoB;EACzC,OAAO,MAAM,KAAK,EAAE,QAAQ,MAAM,IAAI,GAAG,MAAM,OAAO,eAAgB,CAAC,CAAC;CAC1E;CACA,MAAM,IAAI,MAAM,oDAAoD;AACtE;;;;;;;AAiBA,IAAa,qBAAqB,UAAoC,CAAC,MAAmB;CACxF,IAAI;CACJ,MAAM,kBAA0C;EAC9C,cAAc,QAAQ,QACpB,QAAQ,cAAc,QAAQ,YAAY,IAAI,OAAO,eACvD,EACG,MAAM,QAAQ;GACb,MAAM,KAAK,OAAO,QAAQ,aAAa,MAAO,IAAmC;GACjF,IAAI,OAAO,OAAO,YAChB,MAAM,IAAI,MAAM,mDAAmD;GAErE,OAAO;EACT,CAAC,EACA,OAAO,QAAQ;GAEd,MAAM,IAAI,gCAAgC,CACxC,8EAFa,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG,EAEiC,sCACvF,CAAC;EACH,CAAC;EACH,OAAO;CACT;CAEA,MAAM,UAAU,OAAO,YAAoD;EAEzE,MAAM,SAAS,OAAM,MADA,UAAU,GACH,QAAQ,KAAK;EACzC,MAAM,WAAW,WAAW,MAAM;EAClC,IAAI;EACJ,IAAI,SAAS,UAAU,GACrB,MAAM,SAAS;OACV;GAEL,MAAM,SAAS,SAAS,GAAG;GAC3B,MAAM,OAAO,IAAI,aAAa,MAAM;GACpC,KAAK,MAAM,QAAQ,UACjB,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,KAAK,KAAK,MAAM,KAAK,KAAK,SAAS;GAEjE,MAAM;EACR;EACA,OAAO,EACL,SAAS,CACP;GAAE,OAAO,WAAW,GAAG;GAAG,UAAU;GAAU,MAAM,EAAE,YAAY,OAAO,WAAW;EAAE,CACxF,EACF;CACF;CAEA,OAAO;EACL,IAAI;EACJ,UAAU,CACR;GACE,MAAM;IACJ;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;GACF;GACA,IAAI,CAAC,KAAK;GACV;EACF,CACF;CACF;AACF"}
|
|
@@ -0,0 +1,64 @@
|
|
|
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/execa_executor.ts
|
|
7
|
+
/**
|
|
8
|
+
* A {@link @nhtio/adk/batteries/media/contracts!BinaryExecutor} implementation that runs
|
|
9
|
+
* invocations as local child processes via execa.
|
|
10
|
+
*
|
|
11
|
+
* @module @nhtio/adk/batteries/media/engines/execa_executor
|
|
12
|
+
*
|
|
13
|
+
* @remarks
|
|
14
|
+
* The bundled local-process executor. `execa` is an optional peer dependency acquired through
|
|
15
|
+
* an async resolver (default: a lazy dynamic import) — importing this module pulls nothing;
|
|
16
|
+
* constructing the executor is what resolves the peer, and only on first `exec`.
|
|
17
|
+
*
|
|
18
|
+
* Process execution is a movable seam: anything implementing the `BinaryExecutor` contract —
|
|
19
|
+
* a remote runner, a sandbox, a container shim — composes into binary engines exactly like
|
|
20
|
+
* this one. The paired `ScratchWorkspace` must produce paths this executor can open; for the
|
|
21
|
+
* local-process case, the bundled `fs_workspace` is the natural pair.
|
|
22
|
+
*/
|
|
23
|
+
var resolveExeca = async (supplied) => {
|
|
24
|
+
let value = supplied ?? (() => import("execa"));
|
|
25
|
+
if (typeof value === "function" && !("exec" in value)) try {
|
|
26
|
+
value = await value();
|
|
27
|
+
} catch (err) {
|
|
28
|
+
throw new require_exceptions.E_INVALID_MEDIA_PIPELINE_CONFIG([`execa resolver failed: ${require_tool_registry.isError(err) ? err.message : String(err)} — install the optional peer dependency "execa" or supply your own`]);
|
|
29
|
+
}
|
|
30
|
+
if (require_tool_registry.isObject(value) && "execa" in value) value = value.execa;
|
|
31
|
+
if (typeof value !== "function") throw new require_exceptions.E_INVALID_MEDIA_PIPELINE_CONFIG(["execa resolver did not resolve to a function"]);
|
|
32
|
+
return value;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Construct the bundled local-process {@link BinaryExecutor}.
|
|
36
|
+
*
|
|
37
|
+
* @param options - The execa resolver and defaults.
|
|
38
|
+
* @returns A `BinaryExecutor` running invocations as local child processes.
|
|
39
|
+
*/
|
|
40
|
+
var execaExecutor = (options = {}) => {
|
|
41
|
+
let execaPromise;
|
|
42
|
+
const getExeca = () => {
|
|
43
|
+
execaPromise ??= resolveExeca(options.execa);
|
|
44
|
+
return execaPromise;
|
|
45
|
+
};
|
|
46
|
+
return { async exec(invocation) {
|
|
47
|
+
const result = await (await getExeca())(invocation.cmd, invocation.args, {
|
|
48
|
+
timeout: invocation.timeoutMs ?? options.defaultTimeoutMs ?? 12e4,
|
|
49
|
+
cancelSignal: invocation.signal,
|
|
50
|
+
reject: false,
|
|
51
|
+
stripFinalNewline: true
|
|
52
|
+
});
|
|
53
|
+
return {
|
|
54
|
+
exitCode: result.exitCode ?? -1,
|
|
55
|
+
stdout: typeof result.stdout === "string" ? result.stdout : "",
|
|
56
|
+
stderr: typeof result.stderr === "string" ? result.stderr : "",
|
|
57
|
+
failed: result.failed
|
|
58
|
+
};
|
|
59
|
+
} };
|
|
60
|
+
};
|
|
61
|
+
//#endregion
|
|
62
|
+
exports.execaExecutor = execaExecutor;
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=execa_executor.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execa_executor.cjs","names":[],"sources":["../../../../src/batteries/media/engines/execa_executor.ts"],"sourcesContent":["/**\n * A {@link @nhtio/adk/batteries/media/contracts!BinaryExecutor} implementation that runs\n * invocations as local child processes via execa.\n *\n * @module @nhtio/adk/batteries/media/engines/execa_executor\n *\n * @remarks\n * The bundled local-process executor. `execa` is an optional peer dependency acquired through\n * an async resolver (default: a lazy dynamic import) — importing this module pulls nothing;\n * constructing the executor is what resolves the peer, and only on first `exec`.\n *\n * Process execution is a movable seam: anything implementing the `BinaryExecutor` contract —\n * a remote runner, a sandbox, a container shim — composes into binary engines exactly like\n * this one. The paired `ScratchWorkspace` must produce paths this executor can open; for the\n * local-process case, the bundled `fs_workspace` is the natural pair.\n */\n\nimport { isError, isObject } from '@nhtio/adk/guards'\nimport { E_INVALID_MEDIA_PIPELINE_CONFIG } from '../exceptions'\nimport type { BinaryExecutor, BinaryInvocation, BinaryExecResult } from '../contracts'\n\n/** The slice of execa this executor uses (kept minimal for BYO substitution in tests). */\nexport interface ExecaLike {\n (\n cmd: string,\n args: readonly string[],\n options: {\n timeout?: number\n cancelSignal?: AbortSignal\n reject: false\n stripFinalNewline?: boolean\n }\n ): Promise<{\n exitCode?: number\n stdout?: unknown\n stderr?: unknown\n failed: boolean\n }>\n}\n\n/** Resolver forms accepted for the execa module. */\nexport type ExecaResolver =\n | ExecaLike\n | (() => ExecaLike | { execa: ExecaLike } | Promise<ExecaLike | { execa: ExecaLike }>)\n\n/** Options for {@link execaExecutor}. */\nexport interface ExecaExecutorOptions {\n /**\n * The execa function or an async resolver for it. Defaults to a lazy dynamic import of the\n * `execa` package (optional peer).\n */\n execa?: ExecaResolver\n /** Default timeout applied when an invocation does not specify one. */\n defaultTimeoutMs?: number\n}\n\nconst resolveExeca = async (supplied: ExecaResolver | undefined): Promise<ExecaLike> => {\n let value: unknown = supplied ?? ((): Promise<{ execa: ExecaLike }> => import('execa'))\n if (typeof value === 'function' && !('exec' in (value as object))) {\n try {\n value = await (value as () => unknown)()\n } catch (err) {\n const detail = isError(err) ? err.message : String(err)\n throw new E_INVALID_MEDIA_PIPELINE_CONFIG([\n `execa resolver failed: ${detail} — install the optional peer dependency \"execa\" or supply your own`,\n ])\n }\n }\n if (isObject(value) && 'execa' in value) {\n value = (value as { execa: unknown }).execa\n }\n if (typeof value !== 'function') {\n throw new E_INVALID_MEDIA_PIPELINE_CONFIG(['execa resolver did not resolve to a function'])\n }\n return value as ExecaLike\n}\n\n/**\n * Construct the bundled local-process {@link BinaryExecutor}.\n *\n * @param options - The execa resolver and defaults.\n * @returns A `BinaryExecutor` running invocations as local child processes.\n */\nexport const execaExecutor = (options: ExecaExecutorOptions = {}): BinaryExecutor => {\n let execaPromise: Promise<ExecaLike> | undefined\n const getExeca = (): Promise<ExecaLike> => {\n execaPromise ??= resolveExeca(options.execa)\n return execaPromise\n }\n return {\n async exec(invocation: BinaryInvocation): Promise<BinaryExecResult> {\n const execa = await getExeca()\n const result = await execa(invocation.cmd, invocation.args, {\n timeout: invocation.timeoutMs ?? options.defaultTimeoutMs ?? 120_000,\n cancelSignal: invocation.signal,\n reject: false,\n stripFinalNewline: true,\n })\n return {\n exitCode: result.exitCode ?? -1,\n stdout: typeof result.stdout === 'string' ? result.stdout : '',\n stderr: typeof result.stderr === 'string' ? result.stderr : '',\n failed: result.failed,\n }\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAwDA,IAAM,eAAe,OAAO,aAA4D;CACtF,IAAI,QAAiB,mBAAkD,OAAO;CAC9E,IAAI,OAAO,UAAU,cAAc,EAAE,UAAW,QAC9C,IAAI;EACF,QAAQ,MAAO,MAAwB;CACzC,SAAS,KAAK;EAEZ,MAAM,IAAI,mBAAA,gCAAgC,CACxC,0BAFa,sBAAA,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG,EAEnB,mEACnC,CAAC;CACH;CAEF,IAAI,sBAAA,SAAS,KAAK,KAAK,WAAW,OAChC,QAAS,MAA6B;CAExC,IAAI,OAAO,UAAU,YACnB,MAAM,IAAI,mBAAA,gCAAgC,CAAC,8CAA8C,CAAC;CAE5F,OAAO;AACT;;;;;;;AAQA,IAAa,iBAAiB,UAAgC,CAAC,MAAsB;CACnF,IAAI;CACJ,MAAM,iBAAqC;EACzC,iBAAiB,aAAa,QAAQ,KAAK;EAC3C,OAAO;CACT;CACA,OAAO,EACL,MAAM,KAAK,YAAyD;EAElE,MAAM,SAAS,OAAM,MADD,SAAS,GACF,WAAW,KAAK,WAAW,MAAM;GAC1D,SAAS,WAAW,aAAa,QAAQ,oBAAoB;GAC7D,cAAc,WAAW;GACzB,QAAQ;GACR,mBAAmB;EACrB,CAAC;EACD,OAAO;GACL,UAAU,OAAO,YAAY;GAC7B,QAAQ,OAAO,OAAO,WAAW,WAAW,OAAO,SAAS;GAC5D,QAAQ,OAAO,OAAO,WAAW,WAAW,OAAO,SAAS;GAC5D,QAAQ,OAAO;EACjB;CACF,EACF;AACF"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A {@link @nhtio/adk/batteries/media/contracts!BinaryExecutor} implementation that runs
|
|
3
|
+
* invocations as local child processes via execa.
|
|
4
|
+
*
|
|
5
|
+
* @module @nhtio/adk/batteries/media/engines/execa_executor
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* The bundled local-process executor. `execa` is an optional peer dependency acquired through
|
|
9
|
+
* an async resolver (default: a lazy dynamic import) — importing this module pulls nothing;
|
|
10
|
+
* constructing the executor is what resolves the peer, and only on first `exec`.
|
|
11
|
+
*
|
|
12
|
+
* Process execution is a movable seam: anything implementing the `BinaryExecutor` contract —
|
|
13
|
+
* a remote runner, a sandbox, a container shim — composes into binary engines exactly like
|
|
14
|
+
* this one. The paired `ScratchWorkspace` must produce paths this executor can open; for the
|
|
15
|
+
* local-process case, the bundled `fs_workspace` is the natural pair.
|
|
16
|
+
*/
|
|
17
|
+
import type { BinaryExecutor } from "../contracts";
|
|
18
|
+
/** The slice of execa this executor uses (kept minimal for BYO substitution in tests). */
|
|
19
|
+
export interface ExecaLike {
|
|
20
|
+
(cmd: string, args: readonly string[], options: {
|
|
21
|
+
timeout?: number;
|
|
22
|
+
cancelSignal?: AbortSignal;
|
|
23
|
+
reject: false;
|
|
24
|
+
stripFinalNewline?: boolean;
|
|
25
|
+
}): Promise<{
|
|
26
|
+
exitCode?: number;
|
|
27
|
+
stdout?: unknown;
|
|
28
|
+
stderr?: unknown;
|
|
29
|
+
failed: boolean;
|
|
30
|
+
}>;
|
|
31
|
+
}
|
|
32
|
+
/** Resolver forms accepted for the execa module. */
|
|
33
|
+
export type ExecaResolver = ExecaLike | (() => ExecaLike | {
|
|
34
|
+
execa: ExecaLike;
|
|
35
|
+
} | Promise<ExecaLike | {
|
|
36
|
+
execa: ExecaLike;
|
|
37
|
+
}>);
|
|
38
|
+
/** Options for {@link execaExecutor}. */
|
|
39
|
+
export interface ExecaExecutorOptions {
|
|
40
|
+
/**
|
|
41
|
+
* The execa function or an async resolver for it. Defaults to a lazy dynamic import of the
|
|
42
|
+
* `execa` package (optional peer).
|
|
43
|
+
*/
|
|
44
|
+
execa?: ExecaResolver;
|
|
45
|
+
/** Default timeout applied when an invocation does not specify one. */
|
|
46
|
+
defaultTimeoutMs?: number;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Construct the bundled local-process {@link BinaryExecutor}.
|
|
50
|
+
*
|
|
51
|
+
* @param options - The execa resolver and defaults.
|
|
52
|
+
* @returns A `BinaryExecutor` running invocations as local child processes.
|
|
53
|
+
*/
|
|
54
|
+
export declare const execaExecutor: (options?: ExecaExecutorOptions) => BinaryExecutor;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { c as isObject, 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/execa_executor.ts
|
|
5
|
+
/**
|
|
6
|
+
* A {@link @nhtio/adk/batteries/media/contracts!BinaryExecutor} implementation that runs
|
|
7
|
+
* invocations as local child processes via execa.
|
|
8
|
+
*
|
|
9
|
+
* @module @nhtio/adk/batteries/media/engines/execa_executor
|
|
10
|
+
*
|
|
11
|
+
* @remarks
|
|
12
|
+
* The bundled local-process executor. `execa` is an optional peer dependency acquired through
|
|
13
|
+
* an async resolver (default: a lazy dynamic import) — importing this module pulls nothing;
|
|
14
|
+
* constructing the executor is what resolves the peer, and only on first `exec`.
|
|
15
|
+
*
|
|
16
|
+
* Process execution is a movable seam: anything implementing the `BinaryExecutor` contract —
|
|
17
|
+
* a remote runner, a sandbox, a container shim — composes into binary engines exactly like
|
|
18
|
+
* this one. The paired `ScratchWorkspace` must produce paths this executor can open; for the
|
|
19
|
+
* local-process case, the bundled `fs_workspace` is the natural pair.
|
|
20
|
+
*/
|
|
21
|
+
var resolveExeca = async (supplied) => {
|
|
22
|
+
let value = supplied ?? (() => import("execa"));
|
|
23
|
+
if (typeof value === "function" && !("exec" in value)) try {
|
|
24
|
+
value = await value();
|
|
25
|
+
} catch (err) {
|
|
26
|
+
throw new E_INVALID_MEDIA_PIPELINE_CONFIG([`execa resolver failed: ${isError(err) ? err.message : String(err)} — install the optional peer dependency "execa" or supply your own`]);
|
|
27
|
+
}
|
|
28
|
+
if (isObject(value) && "execa" in value) value = value.execa;
|
|
29
|
+
if (typeof value !== "function") throw new E_INVALID_MEDIA_PIPELINE_CONFIG(["execa resolver did not resolve to a function"]);
|
|
30
|
+
return value;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Construct the bundled local-process {@link BinaryExecutor}.
|
|
34
|
+
*
|
|
35
|
+
* @param options - The execa resolver and defaults.
|
|
36
|
+
* @returns A `BinaryExecutor` running invocations as local child processes.
|
|
37
|
+
*/
|
|
38
|
+
var execaExecutor = (options = {}) => {
|
|
39
|
+
let execaPromise;
|
|
40
|
+
const getExeca = () => {
|
|
41
|
+
execaPromise ??= resolveExeca(options.execa);
|
|
42
|
+
return execaPromise;
|
|
43
|
+
};
|
|
44
|
+
return { async exec(invocation) {
|
|
45
|
+
const result = await (await getExeca())(invocation.cmd, invocation.args, {
|
|
46
|
+
timeout: invocation.timeoutMs ?? options.defaultTimeoutMs ?? 12e4,
|
|
47
|
+
cancelSignal: invocation.signal,
|
|
48
|
+
reject: false,
|
|
49
|
+
stripFinalNewline: true
|
|
50
|
+
});
|
|
51
|
+
return {
|
|
52
|
+
exitCode: result.exitCode ?? -1,
|
|
53
|
+
stdout: typeof result.stdout === "string" ? result.stdout : "",
|
|
54
|
+
stderr: typeof result.stderr === "string" ? result.stderr : "",
|
|
55
|
+
failed: result.failed
|
|
56
|
+
};
|
|
57
|
+
} };
|
|
58
|
+
};
|
|
59
|
+
//#endregion
|
|
60
|
+
export { execaExecutor };
|
|
61
|
+
|
|
62
|
+
//# sourceMappingURL=execa_executor.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execa_executor.mjs","names":[],"sources":["../../../../src/batteries/media/engines/execa_executor.ts"],"sourcesContent":["/**\n * A {@link @nhtio/adk/batteries/media/contracts!BinaryExecutor} implementation that runs\n * invocations as local child processes via execa.\n *\n * @module @nhtio/adk/batteries/media/engines/execa_executor\n *\n * @remarks\n * The bundled local-process executor. `execa` is an optional peer dependency acquired through\n * an async resolver (default: a lazy dynamic import) — importing this module pulls nothing;\n * constructing the executor is what resolves the peer, and only on first `exec`.\n *\n * Process execution is a movable seam: anything implementing the `BinaryExecutor` contract —\n * a remote runner, a sandbox, a container shim — composes into binary engines exactly like\n * this one. The paired `ScratchWorkspace` must produce paths this executor can open; for the\n * local-process case, the bundled `fs_workspace` is the natural pair.\n */\n\nimport { isError, isObject } from '@nhtio/adk/guards'\nimport { E_INVALID_MEDIA_PIPELINE_CONFIG } from '../exceptions'\nimport type { BinaryExecutor, BinaryInvocation, BinaryExecResult } from '../contracts'\n\n/** The slice of execa this executor uses (kept minimal for BYO substitution in tests). */\nexport interface ExecaLike {\n (\n cmd: string,\n args: readonly string[],\n options: {\n timeout?: number\n cancelSignal?: AbortSignal\n reject: false\n stripFinalNewline?: boolean\n }\n ): Promise<{\n exitCode?: number\n stdout?: unknown\n stderr?: unknown\n failed: boolean\n }>\n}\n\n/** Resolver forms accepted for the execa module. */\nexport type ExecaResolver =\n | ExecaLike\n | (() => ExecaLike | { execa: ExecaLike } | Promise<ExecaLike | { execa: ExecaLike }>)\n\n/** Options for {@link execaExecutor}. */\nexport interface ExecaExecutorOptions {\n /**\n * The execa function or an async resolver for it. Defaults to a lazy dynamic import of the\n * `execa` package (optional peer).\n */\n execa?: ExecaResolver\n /** Default timeout applied when an invocation does not specify one. */\n defaultTimeoutMs?: number\n}\n\nconst resolveExeca = async (supplied: ExecaResolver | undefined): Promise<ExecaLike> => {\n let value: unknown = supplied ?? ((): Promise<{ execa: ExecaLike }> => import('execa'))\n if (typeof value === 'function' && !('exec' in (value as object))) {\n try {\n value = await (value as () => unknown)()\n } catch (err) {\n const detail = isError(err) ? err.message : String(err)\n throw new E_INVALID_MEDIA_PIPELINE_CONFIG([\n `execa resolver failed: ${detail} — install the optional peer dependency \"execa\" or supply your own`,\n ])\n }\n }\n if (isObject(value) && 'execa' in value) {\n value = (value as { execa: unknown }).execa\n }\n if (typeof value !== 'function') {\n throw new E_INVALID_MEDIA_PIPELINE_CONFIG(['execa resolver did not resolve to a function'])\n }\n return value as ExecaLike\n}\n\n/**\n * Construct the bundled local-process {@link BinaryExecutor}.\n *\n * @param options - The execa resolver and defaults.\n * @returns A `BinaryExecutor` running invocations as local child processes.\n */\nexport const execaExecutor = (options: ExecaExecutorOptions = {}): BinaryExecutor => {\n let execaPromise: Promise<ExecaLike> | undefined\n const getExeca = (): Promise<ExecaLike> => {\n execaPromise ??= resolveExeca(options.execa)\n return execaPromise\n }\n return {\n async exec(invocation: BinaryInvocation): Promise<BinaryExecResult> {\n const execa = await getExeca()\n const result = await execa(invocation.cmd, invocation.args, {\n timeout: invocation.timeoutMs ?? options.defaultTimeoutMs ?? 120_000,\n cancelSignal: invocation.signal,\n reject: false,\n stripFinalNewline: true,\n })\n return {\n exitCode: result.exitCode ?? -1,\n stdout: typeof result.stdout === 'string' ? result.stdout : '',\n stderr: typeof result.stderr === 'string' ? result.stderr : '',\n failed: result.failed,\n }\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAwDA,IAAM,eAAe,OAAO,aAA4D;CACtF,IAAI,QAAiB,mBAAkD,OAAO;CAC9E,IAAI,OAAO,UAAU,cAAc,EAAE,UAAW,QAC9C,IAAI;EACF,QAAQ,MAAO,MAAwB;CACzC,SAAS,KAAK;EAEZ,MAAM,IAAI,gCAAgC,CACxC,0BAFa,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG,EAEnB,mEACnC,CAAC;CACH;CAEF,IAAI,SAAS,KAAK,KAAK,WAAW,OAChC,QAAS,MAA6B;CAExC,IAAI,OAAO,UAAU,YACnB,MAAM,IAAI,gCAAgC,CAAC,8CAA8C,CAAC;CAE5F,OAAO;AACT;;;;;;;AAQA,IAAa,iBAAiB,UAAgC,CAAC,MAAsB;CACnF,IAAI;CACJ,MAAM,iBAAqC;EACzC,iBAAiB,aAAa,QAAQ,KAAK;EAC3C,OAAO;CACT;CACA,OAAO,EACL,MAAM,KAAK,YAAyD;EAElE,MAAM,SAAS,OAAM,MADD,SAAS,GACF,WAAW,KAAK,WAAW,MAAM;GAC1D,SAAS,WAAW,aAAa,QAAQ,oBAAoB;GAC7D,cAAc,WAAW;GACzB,QAAQ;GACR,mBAAmB;EACrB,CAAC;EACD,OAAO;GACL,UAAU,OAAO,YAAY;GAC7B,QAAQ,OAAO,OAAO,WAAW,WAAW,OAAO,SAAS;GAC5D,QAAQ,OAAO,OAAO,WAAW,WAAW,OAAO,SAAS;GAC5D,QAAQ,OAAO;EACjB;CACF,EACF;AACF"}
|
|
@@ -0,0 +1,84 @@
|
|
|
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/fs_workspace.ts
|
|
7
|
+
/**
|
|
8
|
+
* A {@link @nhtio/adk/batteries/media/contracts!ScratchWorkspace} implementation backed by the
|
|
9
|
+
* local filesystem via `node:fs/promises`.
|
|
10
|
+
*
|
|
11
|
+
* @module @nhtio/adk/batteries/media/engines/fs_workspace
|
|
12
|
+
*
|
|
13
|
+
* @remarks
|
|
14
|
+
* The bundled filesystem workspace. `node:fs/promises` is acquired through an async resolver
|
|
15
|
+
* (default: a lazy dynamic import) so this module carries no static `node:*` import and the
|
|
16
|
+
* builtin loads only when a workspace is actually minted.
|
|
17
|
+
*
|
|
18
|
+
* The factory requires an explicit `root` directory — there is no `os.tmpdir()` silent
|
|
19
|
+
* default. Each minted workspace is a fresh unique subdirectory of `root`, removed on
|
|
20
|
+
* `dispose()`. Any BYO implementation whose paths the paired `BinaryExecutor` can open
|
|
21
|
+
* satisfies the same contract (tmpfs mounts, container volumes, sandbox dirs…).
|
|
22
|
+
*/
|
|
23
|
+
var resolveFs = async (supplied) => {
|
|
24
|
+
let value = supplied ?? (() => import("node:fs/promises"));
|
|
25
|
+
if (typeof value === "function") try {
|
|
26
|
+
value = await value();
|
|
27
|
+
} catch (err) {
|
|
28
|
+
throw new require_exceptions.E_INVALID_MEDIA_PIPELINE_CONFIG([`fs resolver failed: ${require_tool_registry.isError(err) ? err.message : String(err)}`]);
|
|
29
|
+
}
|
|
30
|
+
if (value === null || typeof value !== "object" || typeof value.writeFile !== "function") throw new require_exceptions.E_INVALID_MEDIA_PIPELINE_CONFIG(["fs resolver did not resolve to a node:fs/promises-compatible module"]);
|
|
31
|
+
return value;
|
|
32
|
+
};
|
|
33
|
+
var counter = 0;
|
|
34
|
+
var uniqueName = () => {
|
|
35
|
+
counter = (counter + 1) % Number.MAX_SAFE_INTEGER;
|
|
36
|
+
return `media-${Array.from(crypto.getRandomValues(new Uint8Array(6))).map((b) => b.toString(16).padStart(2, "0")).join("")}-${counter}`;
|
|
37
|
+
};
|
|
38
|
+
var joinPath = (...parts) => parts.join("/").replace(/\/{2,}/g, "/");
|
|
39
|
+
/**
|
|
40
|
+
* Construct a {@link ScratchWorkspaceFactory} minting per-invocation directories under `root`.
|
|
41
|
+
*
|
|
42
|
+
* @param options - The root directory and fs resolver.
|
|
43
|
+
* @returns A factory binary engines call once per invocation.
|
|
44
|
+
*/
|
|
45
|
+
var fsScratchWorkspace = (options) => {
|
|
46
|
+
if (typeof options?.root !== "string" || options.root.length === 0) throw new require_exceptions.E_INVALID_MEDIA_PIPELINE_CONFIG(["fsScratchWorkspace requires an explicit root directory (no platform default)"]);
|
|
47
|
+
let fsPromise;
|
|
48
|
+
const getFs = () => {
|
|
49
|
+
fsPromise ??= resolveFs(options.fs);
|
|
50
|
+
return fsPromise;
|
|
51
|
+
};
|
|
52
|
+
return async () => {
|
|
53
|
+
const fs = await getFs();
|
|
54
|
+
const dir = joinPath(options.root, uniqueName());
|
|
55
|
+
await fs.mkdir(dir, { recursive: true });
|
|
56
|
+
return {
|
|
57
|
+
async materialize(bytes, filename) {
|
|
58
|
+
const path = joinPath(dir, filename.replace(/[/\\]/g, "_"));
|
|
59
|
+
await fs.writeFile(path, bytes);
|
|
60
|
+
return path;
|
|
61
|
+
},
|
|
62
|
+
async read(path) {
|
|
63
|
+
const bytes = await fs.readFile(path);
|
|
64
|
+
return require_tool_registry.isInstanceOf(bytes, "Uint8Array", Uint8Array) ? bytes : new Uint8Array(bytes);
|
|
65
|
+
},
|
|
66
|
+
dir() {
|
|
67
|
+
return dir;
|
|
68
|
+
},
|
|
69
|
+
async list() {
|
|
70
|
+
return fs.readdir(dir);
|
|
71
|
+
},
|
|
72
|
+
async dispose() {
|
|
73
|
+
await fs.rm(dir, {
|
|
74
|
+
recursive: true,
|
|
75
|
+
force: true
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
//#endregion
|
|
82
|
+
exports.fsScratchWorkspace = fsScratchWorkspace;
|
|
83
|
+
|
|
84
|
+
//# sourceMappingURL=fs_workspace.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs_workspace.cjs","names":[],"sources":["../../../../src/batteries/media/engines/fs_workspace.ts"],"sourcesContent":["/**\n * A {@link @nhtio/adk/batteries/media/contracts!ScratchWorkspace} implementation backed by the\n * local filesystem via `node:fs/promises`.\n *\n * @module @nhtio/adk/batteries/media/engines/fs_workspace\n *\n * @remarks\n * The bundled filesystem workspace. `node:fs/promises` is acquired through an async resolver\n * (default: a lazy dynamic import) so this module carries no static `node:*` import and the\n * builtin loads only when a workspace is actually minted.\n *\n * The factory requires an explicit `root` directory — there is no `os.tmpdir()` silent\n * default. Each minted workspace is a fresh unique subdirectory of `root`, removed on\n * `dispose()`. Any BYO implementation whose paths the paired `BinaryExecutor` can open\n * satisfies the same contract (tmpfs mounts, container volumes, sandbox dirs…).\n */\n\nimport { isError, isInstanceOf } from '@nhtio/adk/guards'\nimport { E_INVALID_MEDIA_PIPELINE_CONFIG } from '../exceptions'\nimport type { ScratchWorkspace, ScratchWorkspaceFactory } from '../contracts'\n\n/** The slice of `node:fs/promises` the workspace uses. */\nexport interface FsLike {\n /** Create a directory (recursively). */\n mkdir(path: string, options: { recursive: true }): Promise<unknown>\n /** Write bytes to a path. */\n writeFile(path: string, data: Uint8Array): Promise<void>\n /** Read a file's bytes. */\n readFile(path: string): Promise<Uint8Array>\n /** List directory entries (basenames). */\n readdir(path: string): Promise<string[]>\n /** Remove a path recursively, ignoring absence. */\n rm(path: string, options: { recursive: true; force: true }): Promise<void>\n}\n\n/** Resolver forms accepted for the fs module. */\nexport type FsResolver = FsLike | (() => FsLike | Promise<FsLike>)\n\n/** Options for {@link fsScratchWorkspace}. */\nexport interface FsScratchWorkspaceOptions {\n /** The directory all workspaces are minted under. Required — no platform default. */\n root: string\n /** The fs module or a resolver for it. Defaults to a lazy `import('node:fs/promises')`. */\n fs?: FsResolver\n}\n\nconst resolveFs = async (supplied: FsResolver | undefined): Promise<FsLike> => {\n let value: unknown = supplied ?? ((): Promise<FsLike> => import('node:fs/promises'))\n if (typeof value === 'function') {\n try {\n value = await (value as () => unknown)()\n } catch (err) {\n const detail = isError(err) ? err.message : String(err)\n throw new E_INVALID_MEDIA_PIPELINE_CONFIG([`fs resolver failed: ${detail}`])\n }\n }\n if (\n value === null ||\n typeof value !== 'object' ||\n typeof (value as FsLike).writeFile !== 'function'\n ) {\n throw new E_INVALID_MEDIA_PIPELINE_CONFIG([\n 'fs resolver did not resolve to a node:fs/promises-compatible module',\n ])\n }\n return value as FsLike\n}\n\nlet counter = 0\nconst uniqueName = (): string => {\n counter = (counter + 1) % Number.MAX_SAFE_INTEGER\n const rand = Array.from(crypto.getRandomValues(new Uint8Array(6)))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n return `media-${rand}-${counter}`\n}\n\nconst joinPath = (...parts: string[]): string => parts.join('/').replace(/\\/{2,}/g, '/')\n\n/**\n * Construct a {@link ScratchWorkspaceFactory} minting per-invocation directories under `root`.\n *\n * @param options - The root directory and fs resolver.\n * @returns A factory binary engines call once per invocation.\n */\nexport const fsScratchWorkspace = (options: FsScratchWorkspaceOptions): ScratchWorkspaceFactory => {\n if (typeof options?.root !== 'string' || options.root.length === 0) {\n throw new E_INVALID_MEDIA_PIPELINE_CONFIG([\n 'fsScratchWorkspace requires an explicit root directory (no platform default)',\n ])\n }\n let fsPromise: Promise<FsLike> | undefined\n const getFs = (): Promise<FsLike> => {\n fsPromise ??= resolveFs(options.fs)\n return fsPromise\n }\n\n return async (): Promise<ScratchWorkspace> => {\n const fs = await getFs()\n const dir = joinPath(options.root, uniqueName())\n await fs.mkdir(dir, { recursive: true })\n return {\n async materialize(bytes: Uint8Array, filename: string): Promise<string> {\n const safe = filename.replace(/[/\\\\]/g, '_')\n const path = joinPath(dir, safe)\n await fs.writeFile(path, bytes)\n return path\n },\n async read(path: string): Promise<Uint8Array> {\n const bytes = await fs.readFile(path)\n return isInstanceOf(bytes, 'Uint8Array', Uint8Array) ? bytes : new Uint8Array(bytes)\n },\n dir(): string {\n return dir\n },\n async list(): Promise<string[]> {\n return fs.readdir(dir)\n },\n async dispose(): Promise<void> {\n await fs.rm(dir, { recursive: true, force: true })\n },\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA8CA,IAAM,YAAY,OAAO,aAAsD;CAC7E,IAAI,QAAiB,mBAAoC,OAAO;CAChE,IAAI,OAAO,UAAU,YACnB,IAAI;EACF,QAAQ,MAAO,MAAwB;CACzC,SAAS,KAAK;EAEZ,MAAM,IAAI,mBAAA,gCAAgC,CAAC,uBAD5B,sBAAA,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG,GACoB,CAAC;CAC7E;CAEF,IACE,UAAU,QACV,OAAO,UAAU,YACjB,OAAQ,MAAiB,cAAc,YAEvC,MAAM,IAAI,mBAAA,gCAAgC,CACxC,qEACF,CAAC;CAEH,OAAO;AACT;AAEA,IAAI,UAAU;AACd,IAAM,mBAA2B;CAC/B,WAAW,UAAU,KAAK,OAAO;CAIjC,OAAO,SAHM,MAAM,KAAK,OAAO,gBAAgB,IAAI,WAAW,CAAC,CAAC,CAAC,EAC9D,KAAK,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAC1C,KAAK,EACQ,EAAK,GAAG;AAC1B;AAEA,IAAM,YAAY,GAAG,UAA4B,MAAM,KAAK,GAAG,EAAE,QAAQ,WAAW,GAAG;;;;;;;AAQvF,IAAa,sBAAsB,YAAgE;CACjG,IAAI,OAAO,SAAS,SAAS,YAAY,QAAQ,KAAK,WAAW,GAC/D,MAAM,IAAI,mBAAA,gCAAgC,CACxC,8EACF,CAAC;CAEH,IAAI;CACJ,MAAM,cAA+B;EACnC,cAAc,UAAU,QAAQ,EAAE;EAClC,OAAO;CACT;CAEA,OAAO,YAAuC;EAC5C,MAAM,KAAK,MAAM,MAAM;EACvB,MAAM,MAAM,SAAS,QAAQ,MAAM,WAAW,CAAC;EAC/C,MAAM,GAAG,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;EACvC,OAAO;GACL,MAAM,YAAY,OAAmB,UAAmC;IAEtE,MAAM,OAAO,SAAS,KADT,SAAS,QAAQ,UAAU,GACb,CAAI;IAC/B,MAAM,GAAG,UAAU,MAAM,KAAK;IAC9B,OAAO;GACT;GACA,MAAM,KAAK,MAAmC;IAC5C,MAAM,QAAQ,MAAM,GAAG,SAAS,IAAI;IACpC,OAAO,sBAAA,aAAa,OAAO,cAAc,UAAU,IAAI,QAAQ,IAAI,WAAW,KAAK;GACrF;GACA,MAAc;IACZ,OAAO;GACT;GACA,MAAM,OAA0B;IAC9B,OAAO,GAAG,QAAQ,GAAG;GACvB;GACA,MAAM,UAAyB;IAC7B,MAAM,GAAG,GAAG,KAAK;KAAE,WAAW;KAAM,OAAO;IAAK,CAAC;GACnD;EACF;CACF;AACF"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A {@link @nhtio/adk/batteries/media/contracts!ScratchWorkspace} implementation backed by the
|
|
3
|
+
* local filesystem via `node:fs/promises`.
|
|
4
|
+
*
|
|
5
|
+
* @module @nhtio/adk/batteries/media/engines/fs_workspace
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* The bundled filesystem workspace. `node:fs/promises` is acquired through an async resolver
|
|
9
|
+
* (default: a lazy dynamic import) so this module carries no static `node:*` import and the
|
|
10
|
+
* builtin loads only when a workspace is actually minted.
|
|
11
|
+
*
|
|
12
|
+
* The factory requires an explicit `root` directory — there is no `os.tmpdir()` silent
|
|
13
|
+
* default. Each minted workspace is a fresh unique subdirectory of `root`, removed on
|
|
14
|
+
* `dispose()`. Any BYO implementation whose paths the paired `BinaryExecutor` can open
|
|
15
|
+
* satisfies the same contract (tmpfs mounts, container volumes, sandbox dirs…).
|
|
16
|
+
*/
|
|
17
|
+
import type { ScratchWorkspaceFactory } from "../contracts";
|
|
18
|
+
/** The slice of `node:fs/promises` the workspace uses. */
|
|
19
|
+
export interface FsLike {
|
|
20
|
+
/** Create a directory (recursively). */
|
|
21
|
+
mkdir(path: string, options: {
|
|
22
|
+
recursive: true;
|
|
23
|
+
}): Promise<unknown>;
|
|
24
|
+
/** Write bytes to a path. */
|
|
25
|
+
writeFile(path: string, data: Uint8Array): Promise<void>;
|
|
26
|
+
/** Read a file's bytes. */
|
|
27
|
+
readFile(path: string): Promise<Uint8Array>;
|
|
28
|
+
/** List directory entries (basenames). */
|
|
29
|
+
readdir(path: string): Promise<string[]>;
|
|
30
|
+
/** Remove a path recursively, ignoring absence. */
|
|
31
|
+
rm(path: string, options: {
|
|
32
|
+
recursive: true;
|
|
33
|
+
force: true;
|
|
34
|
+
}): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
/** Resolver forms accepted for the fs module. */
|
|
37
|
+
export type FsResolver = FsLike | (() => FsLike | Promise<FsLike>);
|
|
38
|
+
/** Options for {@link fsScratchWorkspace}. */
|
|
39
|
+
export interface FsScratchWorkspaceOptions {
|
|
40
|
+
/** The directory all workspaces are minted under. Required — no platform default. */
|
|
41
|
+
root: string;
|
|
42
|
+
/** The fs module or a resolver for it. Defaults to a lazy `import('node:fs/promises')`. */
|
|
43
|
+
fs?: FsResolver;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Construct a {@link ScratchWorkspaceFactory} minting per-invocation directories under `root`.
|
|
47
|
+
*
|
|
48
|
+
* @param options - The root directory and fs resolver.
|
|
49
|
+
* @returns A factory binary engines call once per invocation.
|
|
50
|
+
*/
|
|
51
|
+
export declare const fsScratchWorkspace: (options: FsScratchWorkspaceOptions) => ScratchWorkspaceFactory;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { o as isError, s as isInstanceOf } 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/fs_workspace.ts
|
|
5
|
+
/**
|
|
6
|
+
* A {@link @nhtio/adk/batteries/media/contracts!ScratchWorkspace} implementation backed by the
|
|
7
|
+
* local filesystem via `node:fs/promises`.
|
|
8
|
+
*
|
|
9
|
+
* @module @nhtio/adk/batteries/media/engines/fs_workspace
|
|
10
|
+
*
|
|
11
|
+
* @remarks
|
|
12
|
+
* The bundled filesystem workspace. `node:fs/promises` is acquired through an async resolver
|
|
13
|
+
* (default: a lazy dynamic import) so this module carries no static `node:*` import and the
|
|
14
|
+
* builtin loads only when a workspace is actually minted.
|
|
15
|
+
*
|
|
16
|
+
* The factory requires an explicit `root` directory — there is no `os.tmpdir()` silent
|
|
17
|
+
* default. Each minted workspace is a fresh unique subdirectory of `root`, removed on
|
|
18
|
+
* `dispose()`. Any BYO implementation whose paths the paired `BinaryExecutor` can open
|
|
19
|
+
* satisfies the same contract (tmpfs mounts, container volumes, sandbox dirs…).
|
|
20
|
+
*/
|
|
21
|
+
var resolveFs = async (supplied) => {
|
|
22
|
+
let value = supplied ?? (() => import("node:fs/promises"));
|
|
23
|
+
if (typeof value === "function") try {
|
|
24
|
+
value = await value();
|
|
25
|
+
} catch (err) {
|
|
26
|
+
throw new E_INVALID_MEDIA_PIPELINE_CONFIG([`fs resolver failed: ${isError(err) ? err.message : String(err)}`]);
|
|
27
|
+
}
|
|
28
|
+
if (value === null || typeof value !== "object" || typeof value.writeFile !== "function") throw new E_INVALID_MEDIA_PIPELINE_CONFIG(["fs resolver did not resolve to a node:fs/promises-compatible module"]);
|
|
29
|
+
return value;
|
|
30
|
+
};
|
|
31
|
+
var counter = 0;
|
|
32
|
+
var uniqueName = () => {
|
|
33
|
+
counter = (counter + 1) % Number.MAX_SAFE_INTEGER;
|
|
34
|
+
return `media-${Array.from(crypto.getRandomValues(new Uint8Array(6))).map((b) => b.toString(16).padStart(2, "0")).join("")}-${counter}`;
|
|
35
|
+
};
|
|
36
|
+
var joinPath = (...parts) => parts.join("/").replace(/\/{2,}/g, "/");
|
|
37
|
+
/**
|
|
38
|
+
* Construct a {@link ScratchWorkspaceFactory} minting per-invocation directories under `root`.
|
|
39
|
+
*
|
|
40
|
+
* @param options - The root directory and fs resolver.
|
|
41
|
+
* @returns A factory binary engines call once per invocation.
|
|
42
|
+
*/
|
|
43
|
+
var fsScratchWorkspace = (options) => {
|
|
44
|
+
if (typeof options?.root !== "string" || options.root.length === 0) throw new E_INVALID_MEDIA_PIPELINE_CONFIG(["fsScratchWorkspace requires an explicit root directory (no platform default)"]);
|
|
45
|
+
let fsPromise;
|
|
46
|
+
const getFs = () => {
|
|
47
|
+
fsPromise ??= resolveFs(options.fs);
|
|
48
|
+
return fsPromise;
|
|
49
|
+
};
|
|
50
|
+
return async () => {
|
|
51
|
+
const fs = await getFs();
|
|
52
|
+
const dir = joinPath(options.root, uniqueName());
|
|
53
|
+
await fs.mkdir(dir, { recursive: true });
|
|
54
|
+
return {
|
|
55
|
+
async materialize(bytes, filename) {
|
|
56
|
+
const path = joinPath(dir, filename.replace(/[/\\]/g, "_"));
|
|
57
|
+
await fs.writeFile(path, bytes);
|
|
58
|
+
return path;
|
|
59
|
+
},
|
|
60
|
+
async read(path) {
|
|
61
|
+
const bytes = await fs.readFile(path);
|
|
62
|
+
return isInstanceOf(bytes, "Uint8Array", Uint8Array) ? bytes : new Uint8Array(bytes);
|
|
63
|
+
},
|
|
64
|
+
dir() {
|
|
65
|
+
return dir;
|
|
66
|
+
},
|
|
67
|
+
async list() {
|
|
68
|
+
return fs.readdir(dir);
|
|
69
|
+
},
|
|
70
|
+
async dispose() {
|
|
71
|
+
await fs.rm(dir, {
|
|
72
|
+
recursive: true,
|
|
73
|
+
force: true
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
//#endregion
|
|
80
|
+
export { fsScratchWorkspace };
|
|
81
|
+
|
|
82
|
+
//# sourceMappingURL=fs_workspace.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs_workspace.mjs","names":[],"sources":["../../../../src/batteries/media/engines/fs_workspace.ts"],"sourcesContent":["/**\n * A {@link @nhtio/adk/batteries/media/contracts!ScratchWorkspace} implementation backed by the\n * local filesystem via `node:fs/promises`.\n *\n * @module @nhtio/adk/batteries/media/engines/fs_workspace\n *\n * @remarks\n * The bundled filesystem workspace. `node:fs/promises` is acquired through an async resolver\n * (default: a lazy dynamic import) so this module carries no static `node:*` import and the\n * builtin loads only when a workspace is actually minted.\n *\n * The factory requires an explicit `root` directory — there is no `os.tmpdir()` silent\n * default. Each minted workspace is a fresh unique subdirectory of `root`, removed on\n * `dispose()`. Any BYO implementation whose paths the paired `BinaryExecutor` can open\n * satisfies the same contract (tmpfs mounts, container volumes, sandbox dirs…).\n */\n\nimport { isError, isInstanceOf } from '@nhtio/adk/guards'\nimport { E_INVALID_MEDIA_PIPELINE_CONFIG } from '../exceptions'\nimport type { ScratchWorkspace, ScratchWorkspaceFactory } from '../contracts'\n\n/** The slice of `node:fs/promises` the workspace uses. */\nexport interface FsLike {\n /** Create a directory (recursively). */\n mkdir(path: string, options: { recursive: true }): Promise<unknown>\n /** Write bytes to a path. */\n writeFile(path: string, data: Uint8Array): Promise<void>\n /** Read a file's bytes. */\n readFile(path: string): Promise<Uint8Array>\n /** List directory entries (basenames). */\n readdir(path: string): Promise<string[]>\n /** Remove a path recursively, ignoring absence. */\n rm(path: string, options: { recursive: true; force: true }): Promise<void>\n}\n\n/** Resolver forms accepted for the fs module. */\nexport type FsResolver = FsLike | (() => FsLike | Promise<FsLike>)\n\n/** Options for {@link fsScratchWorkspace}. */\nexport interface FsScratchWorkspaceOptions {\n /** The directory all workspaces are minted under. Required — no platform default. */\n root: string\n /** The fs module or a resolver for it. Defaults to a lazy `import('node:fs/promises')`. */\n fs?: FsResolver\n}\n\nconst resolveFs = async (supplied: FsResolver | undefined): Promise<FsLike> => {\n let value: unknown = supplied ?? ((): Promise<FsLike> => import('node:fs/promises'))\n if (typeof value === 'function') {\n try {\n value = await (value as () => unknown)()\n } catch (err) {\n const detail = isError(err) ? err.message : String(err)\n throw new E_INVALID_MEDIA_PIPELINE_CONFIG([`fs resolver failed: ${detail}`])\n }\n }\n if (\n value === null ||\n typeof value !== 'object' ||\n typeof (value as FsLike).writeFile !== 'function'\n ) {\n throw new E_INVALID_MEDIA_PIPELINE_CONFIG([\n 'fs resolver did not resolve to a node:fs/promises-compatible module',\n ])\n }\n return value as FsLike\n}\n\nlet counter = 0\nconst uniqueName = (): string => {\n counter = (counter + 1) % Number.MAX_SAFE_INTEGER\n const rand = Array.from(crypto.getRandomValues(new Uint8Array(6)))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n return `media-${rand}-${counter}`\n}\n\nconst joinPath = (...parts: string[]): string => parts.join('/').replace(/\\/{2,}/g, '/')\n\n/**\n * Construct a {@link ScratchWorkspaceFactory} minting per-invocation directories under `root`.\n *\n * @param options - The root directory and fs resolver.\n * @returns A factory binary engines call once per invocation.\n */\nexport const fsScratchWorkspace = (options: FsScratchWorkspaceOptions): ScratchWorkspaceFactory => {\n if (typeof options?.root !== 'string' || options.root.length === 0) {\n throw new E_INVALID_MEDIA_PIPELINE_CONFIG([\n 'fsScratchWorkspace requires an explicit root directory (no platform default)',\n ])\n }\n let fsPromise: Promise<FsLike> | undefined\n const getFs = (): Promise<FsLike> => {\n fsPromise ??= resolveFs(options.fs)\n return fsPromise\n }\n\n return async (): Promise<ScratchWorkspace> => {\n const fs = await getFs()\n const dir = joinPath(options.root, uniqueName())\n await fs.mkdir(dir, { recursive: true })\n return {\n async materialize(bytes: Uint8Array, filename: string): Promise<string> {\n const safe = filename.replace(/[/\\\\]/g, '_')\n const path = joinPath(dir, safe)\n await fs.writeFile(path, bytes)\n return path\n },\n async read(path: string): Promise<Uint8Array> {\n const bytes = await fs.readFile(path)\n return isInstanceOf(bytes, 'Uint8Array', Uint8Array) ? bytes : new Uint8Array(bytes)\n },\n dir(): string {\n return dir\n },\n async list(): Promise<string[]> {\n return fs.readdir(dir)\n },\n async dispose(): Promise<void> {\n await fs.rm(dir, { recursive: true, force: true })\n },\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA8CA,IAAM,YAAY,OAAO,aAAsD;CAC7E,IAAI,QAAiB,mBAAoC,OAAO;CAChE,IAAI,OAAO,UAAU,YACnB,IAAI;EACF,QAAQ,MAAO,MAAwB;CACzC,SAAS,KAAK;EAEZ,MAAM,IAAI,gCAAgC,CAAC,uBAD5B,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG,GACoB,CAAC;CAC7E;CAEF,IACE,UAAU,QACV,OAAO,UAAU,YACjB,OAAQ,MAAiB,cAAc,YAEvC,MAAM,IAAI,gCAAgC,CACxC,qEACF,CAAC;CAEH,OAAO;AACT;AAEA,IAAI,UAAU;AACd,IAAM,mBAA2B;CAC/B,WAAW,UAAU,KAAK,OAAO;CAIjC,OAAO,SAHM,MAAM,KAAK,OAAO,gBAAgB,IAAI,WAAW,CAAC,CAAC,CAAC,EAC9D,KAAK,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAC1C,KAAK,EACQ,EAAK,GAAG;AAC1B;AAEA,IAAM,YAAY,GAAG,UAA4B,MAAM,KAAK,GAAG,EAAE,QAAQ,WAAW,GAAG;;;;;;;AAQvF,IAAa,sBAAsB,YAAgE;CACjG,IAAI,OAAO,SAAS,SAAS,YAAY,QAAQ,KAAK,WAAW,GAC/D,MAAM,IAAI,gCAAgC,CACxC,8EACF,CAAC;CAEH,IAAI;CACJ,MAAM,cAA+B;EACnC,cAAc,UAAU,QAAQ,EAAE;EAClC,OAAO;CACT;CAEA,OAAO,YAAuC;EAC5C,MAAM,KAAK,MAAM,MAAM;EACvB,MAAM,MAAM,SAAS,QAAQ,MAAM,WAAW,CAAC;EAC/C,MAAM,GAAG,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;EACvC,OAAO;GACL,MAAM,YAAY,OAAmB,UAAmC;IAEtE,MAAM,OAAO,SAAS,KADT,SAAS,QAAQ,UAAU,GACb,CAAI;IAC/B,MAAM,GAAG,UAAU,MAAM,KAAK;IAC9B,OAAO;GACT;GACA,MAAM,KAAK,MAAmC;IAC5C,MAAM,QAAQ,MAAM,GAAG,SAAS,IAAI;IACpC,OAAO,aAAa,OAAO,cAAc,UAAU,IAAI,QAAQ,IAAI,WAAW,KAAK;GACrF;GACA,MAAc;IACZ,OAAO;GACT;GACA,MAAM,OAA0B;IAC9B,OAAO,GAAG,QAAQ,GAAG;GACvB;GACA,MAAM,UAAyB;IAC7B,MAAM,GAAG,GAAG,KAAK;KAAE,WAAW;KAAM,OAAO;IAAK,CAAC;GACnD;EACF;CACF;AACF"}
|