@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
123 lines • 5.52 kB
JavaScript
// ========= 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 { encodeText, utf8Locale } from "../../../shell/bytes.js";
import { specOf } from "../../spec/builtins.js";
import { FlagView } from "../../spec/flag_view.js";
import { IOResult, materialize } from "../../../io/types.js";
import { matcherSyntax, resolvePattern } from "../grep_pattern.js";
import { UsageError } from "../../errors.js";
import { GREP_STDIN_LABEL, STDIN_OPERAND } from "../utils/constants.js";
import { linkResolver } from "../utils/links.js";
import { operandLabel } from "../utils/stream.js";
import { decompressInputs } from "./decompress.js";
import { listingMode, maxCount } from "./grep.js";
import { exitCodeFor } from "../grep_scan.js";
import { openGrep, streamConfig, streamInput } from "../grep_stream.js";
import { OutputStream, closeQuietly, ensureStream } from "../../../io/stream.js";
import { closeStream } from "../../../rs/stream.js";
import { concat } from "../../../utils/bytes.js";
const ZGREP_NO_PATTERN = "zgrep: missing pattern; try `zgrep --help' for help";
function parseFlags(fl, neverMatch) {
const [filesOnly, filesWithoutMatch] = listingMode(fl);
const count = maxCount(fl);
return {
ignoreCase: fl.asBool('ignore_case'),
invert: fl.asBool('invert_match'),
countOnly: fl.asBool('count'),
filesOnly,
filesWithoutMatch,
lineNumbers: fl.asBool('line_number'),
byteOffsets: fl.asBool('byte_offset'),
fixedString: fl.asBool('fixed_strings') && !neverMatch,
syntax: matcherSyntax(fl),
withFilename: fl.asBool('with_filename'),
noFilename: fl.asBool('no_filename'),
onlyMatching: fl.asBool('only_matching'),
quiet: fl.asBool('quiet') && count !== 0,
wholeWord: fl.asBool('word_regexp'),
lineRegexp: fl.asBool('line_regexp'),
maxCount: count,
noMessages: false,
recursive: false,
afterContext: null,
beforeContext: null,
binaryMode: 'binary',
filters: { fileGlobs: [], excludeDir: [], text: false },
};
}
export async function zgrepGeneric(paths, texts, ctx, read, stat) {
const fl = new FlagView(ctx.flags, specOf('zgrep'));
const resolution = await resolvePattern('zgrep', texts, fl, read);
if (resolution.error !== null) {
return [null, new IOResult({ exitCode: 2, stderr: encodeText(resolution.error) })];
}
if (resolution.pattern === null) {
return [null, new IOResult({ exitCode: 2, stderr: encodeText(ZGREP_NO_PATTERN + '\n') })];
}
let f;
try {
f = parseFlags(fl, resolution.neverMatch);
}
catch (err) {
if (!(err instanceof UsageError))
throw err;
return [null, new IOResult({ exitCode: 2, stderr: encodeText(err.message + '\n') })];
}
const [stream, warnings] = await openGrep(streamConfig(f, resolution.neverMatch || f.maxCount === 0 ? null : resolution.pattern, utf8Locale(ctx.env)));
const showFilename = f.withFilename || (paths.length > 1 && !f.noFilename);
const resolver = linkResolver(ctx);
const result = new IOResult({ exitCode: 1, stderr: warnings.length ? warnings : null });
async function* run() {
let anyMatch = false;
let failed = false;
try {
for (const p of paths.length > 0 ? paths : [STDIN_OPERAND]) {
const [body, io] = await decompressInputs([p], read, {
stdin: ctx.stdin,
toStdout: true,
force: true,
quiet: true,
...(stat !== undefined ? { stat } : {}),
resolver,
});
const selected = new IOResult({ exitCode: 1 });
try {
yield* streamInput(ensureStream(body ?? new Uint8Array()), stream, operandLabel(p, GREP_STDIN_LABEL), showFilename, selected, false, null, ctx.signal, true, p.rawPath);
}
finally {
anyMatch ||= selected.exitCode === 0;
failed ||= io.exitCode === 1 || selected.exitCode === 2;
const diagnostic = concat([
await io.materializeStderr(),
await selected.materializeStderr(),
]);
if (diagnostic.length)
result.stderr = concat([await materialize(result.stderr), diagnostic]);
result.exitCode = exitCodeFor(anyMatch, failed, false);
}
}
}
finally {
await closeStream(stream);
}
}
return [
new OutputStream(run(), async () => {
await closeStream(stream);
await closeQuietly(ctx.stdin);
}),
result,
];
}
//# sourceMappingURL=zgrep.js.map