@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
111 lines • 5.33 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 { isStdin, resolveSource } from "../../utils/stream.js";
import { IOResult } from "../../../../io/types.js";
import { formatFsError } from "../../../../errors/render.js";
import { isFsError } from "../../../../errors/fs.js";
import { strategyFor } from "./detect.js";
import { runFanout } from "./fanout/index.js";
import { runOperands, mergeOperandIos } from "./utils.js";
import { Strategy } from "./types.js";
import { runRelay } from "./relay/index.js";
import { runStream } from "./stream/index.js";
import { runSearch } from "./search.js";
import { runDu } from "./du.js";
import { readFailExitCode } from "../../../spec/usage.js";
import { UsageError } from "../../../errors.js";
import { encodeText, utf8Locale } from "../../../../shell/bytes.js";
// Run a command whose path operands span mounts. Every command combines
// per-mount work under one of three strategies (see Strategy): STREAM merges
// raw per-operand bytes and runs the command once on the merged stream,
// FANOUT runs the command natively once per operand and combines the
// outputs, RELAY moves per-file data through the dispatcher into one shared
// generic. STREAM and FANOUT execute through `runSingle`, so each mount
// expands its own glob operands and uses its own native command
// implementation. grep, rg and du compose each mount's own command instead: a
// search from its owned scopes (`runSearch`), du from its measurement
// (`runDu`).
export async function handleCrossMount(cmdName, scopes, textArgs, flagKwargs, dispatch, runSingle, stdin = null,
// Maps an operand to its storage identity (RELAY's transfer commands).
storageKey,
// Name-plane facts for the RELAY generics that render them (ls).
vfs,
// The session view, for the RELAY generic that renders the
// session's profile (ls).
sessionView,
// The session's working directory, which a typed operand resolves against
// (cp's link sources).
cwd = '/', argv = [], aggregate = null, checkUnlink,
// The line's operand resolution, which a walk through the dispatcher's
// globs take.
follow, diff, ids, signal) {
const native = runSingle;
const input = resolveSource(stdin);
runSingle = (name, paths, texts, flags, options) => native(name, paths, texts, flags, {
...options,
stdin: paths.some((p) => isStdin(p)) ? input : (options?.stdin ?? null),
});
try {
if (aggregate !== null) {
const results = await runOperands(runSingle, cmdName, scopes, textArgs, flagKwargs);
const body = aggregate(results.map((r) => [r.scope.virtual, r.data]));
return [
body,
await mergeOperandIos(results, Math.max(0, ...results.map((r) => r.io.exitCode))),
];
}
if (cmdName === 'grep' || cmdName === 'rg') {
return await runSearch(cmdName, scopes, textArgs, flagKwargs, dispatch, runSingle, cwd, vfs, input, utf8Locale(sessionView?.snapshot()));
}
if (cmdName === 'du') {
return await runDu(scopes, textArgs, flagKwargs, dispatch, runSingle, cwd, vfs, input, undefined, false, follow);
}
const cmd = cmdName;
const strategy = strategyFor(cmd);
if (strategy === Strategy.RELAY) {
return await runRelay(cmd, scopes, textArgs, flagKwargs, dispatch, runSingle, storageKey, vfs, sessionView, stdin, cwd, argv, checkUnlink, diff, ids, signal);
}
if (strategy === Strategy.STREAM) {
return await runStream(cmd, scopes, textArgs, flagKwargs, runSingle);
}
return await runFanout(cmd, scopes, textArgs, flagKwargs, runSingle);
}
catch (err) {
// The command's own usage refusal (cmp's bad skip, an extra operand) is
// its result, and the rest of the line runs, as the single-mount path
// answers it.
if (err instanceof UsageError) {
return [
null,
new IOResult({
exitCode: err.exitCode,
stderr: encodeText(`${err.message}\n`),
}),
];
}
// Only typed fs errors format as a GNU operand line, matching the
// Python chokepoint (FS_ERRORS). Internal errors keep propagating
// instead of being mangled into a plausible-looking stderr line.
if (!isFsError(err))
throw err;
return [
null,
new IOResult({
exitCode: readFailExitCode(cmdName, err),
stderr: formatFsError(cmdName, err, scopes),
}),
];
}
}
//# sourceMappingURL=route.js.map