@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
60 lines • 2.66 kB
JavaScript
import { encodeText } from "../../shell/bytes.js";
import { NodeType as NT } from "../../shell/types.js";
const DEFAULT_FORMAT = '\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS';
const TOKEN = /%(?:([0-9])?(l)?([RUS])|([%P]))/g;
const PREFIXES = new Set([NT.TIMED_STATEMENT, NT.NEGATED_COMMAND]);
/** CPU time is zero: browsers lack per-job counters and process totals include unrelated agents. */
export function timingReport(elapsed, portable, format) {
if (portable)
return encodeText(`real ${elapsed.toFixed(2)}\nuser 0.00\nsys 0.00\n`);
const template = format ?? DEFAULT_FORMAT;
if (template === '')
return new Uint8Array();
const pieces = [];
let cursor = 0;
for (const match of template.matchAll(TOKEN)) {
const gap = template.slice(cursor, match.index);
if (gap.includes('%'))
return encodeText('mirage: TIMEFORMAT: invalid format character\n');
pieces.push(gap);
if (match[4] !== undefined)
pieces.push(match[4] === '%' ? '%' : '0.00');
else {
const precision = Math.min(Number(match[1] ?? 3), 3);
const value = match[3] === 'R' ? elapsed : 0;
pieces.push(match[2] === undefined
? value.toFixed(precision)
: `${String(Math.floor(value / 60))}m${(value % 60).toFixed(precision)}s`);
}
cursor = match.index + match[0].length;
}
const tail = template.slice(cursor);
if (tail.includes('%'))
return encodeText('mirage: TIMEFORMAT: invalid format character\n');
return encodeText(pieces.join('') + tail + '\n');
}
/**
* How a `time` reports its pipeline. bash times a pipeline once, however
* many `time` words and `!` lead it: the outermost `time` reports,
* portable when any of them takes `-p`. Null when an outer `time` already
* times the pipeline. Mirrors Python's timed_by.
*/
export function timedBy(node) {
let current = node;
for (let parent = node.parent ?? null; parent !== null &&
(PREFIXES.has(parent.type) ||
(parent.type === NT.PIPELINE && parent.startIndex === current.startIndex));) {
if (parent.type === NT.TIMED_STATEMENT)
return null;
current = parent;
parent = parent.parent ?? null;
}
let portable = false;
for (let inner = node; inner !== undefined && (PREFIXES.has(inner.type) || inner.type === NT.PIPELINE);) {
if (inner.type === NT.TIMED_STATEMENT && inner.children.some((child) => child.type === '-p'))
portable = true;
inner = inner.namedChildren[0];
}
return portable;
}
//# sourceMappingURL=timing.js.map