UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

86 lines • 4.12 kB
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. ========= // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ========= Copyright 2026 @ Strukto.AI All Rights Reserved. ========= import { stdinStream, stdinStat } from "../utils/stream.js"; import { asyncChain, ensureStream } from "../../../io/stream.js"; import { IOResult } from "../../../io/types.js"; import { FileType, Limit, } from "../../../types.js"; import { reportedStream, splitReadable } from "../utils/operands.js"; import { resolveSource, streamOutput } from "../utils/stream.js"; import { openStream } from "../../../rs/stream.js"; import { FlagView } from "../../spec/flag_view.js"; import {} from "../../spec/types.js"; import { specOf } from "../../spec/builtins.js"; import { CHAR_DEVICE_MAX_BYTES } from "../utils/constants.js"; import { truncateStream } from "../utils/limit.js"; import { encodeText } from "../../../shell/bytes.js"; function parseFlags(bag) { const fl = new FlagView(bag, specOf('cat')); const showAll = fl.asBool('show_all'); return { numberLines: fl.asBool('number'), numberNonblank: fl.asBool('number_nonblank'), showEnds: fl.asBool('show_ends') || fl.asBool('e') || showAll, showTabs: fl.asBool('show_tabs') || fl.asBool('t') || showAll, showNonprinting: fl.asBool('show_nonprinting') || fl.asBool('e') || fl.asBool('t') || showAll, squeezeBlank: fl.asBool('squeeze_blank'), }; } async function displayLines(source, display, signal) { return streamOutput(await openStream('cat', { number_lines: display.numberLines, number_nonblank: display.numberNonblank, show_ends: display.showEnds, show_tabs: display.showTabs, show_nonprinting: display.showNonprinting, squeeze_blank: display.squeezeBlank, }), source, signal); } export async function catGeneric(paths, texts, ctx, stat, stream) { stat = stdinStat(stat); stream = stdinStream(stream, ctx.stdin); const display = parseFlags(ctx.flags); const wantsDisplay = Object.values(display).some(Boolean); if (paths.length > 0) { const stats = new Map(); const rememberStat = async (p) => { const row = await stat(p); stats.set(p.virtual, row); return row; }; const [readable, err] = await splitReadable(paths, rememberStat, 'cat'); const errBytes = err === '' ? null : encodeText(err); if (readable.length === 0) { return [null, new IOResult({ exitCode: err === '' ? 0 : 1, stderr: errBytes })]; } const outputs = []; const io = new IOResult({ exitCode: err === '' ? 0 : 1, stderr: errBytes }); for (const p of readable) { let source = stream(p); if (stats.get(p.virtual)?.type === FileType.CHAR_DEVICE) { source = truncateStream(source, io, new Limit({ maxBytes: CHAR_DEVICE_MAX_BYTES })); } const out = ensureStream(source); outputs.push(readable.length === 1 ? out : reportedStream(out, io, p, 'cat')); } const merged = outputs.length === 1 ? outputs[0] : asyncChain(outputs); if (merged === undefined) throw new Error('cat: missing readable stream'); const out = wantsDisplay ? await displayLines(merged, display, ctx.signal) : merged; return [out, io]; } const source = resolveSource(ctx.stdin); const out = wantsDisplay ? await displayLines(source, display, ctx.signal) : source; return [out, new IOResult()]; } //# sourceMappingURL=cat.js.map