@pstdio/opfs-utils
Version:
Utilities for the browser's OPFS: ls, grep, safe file read, unified diff patching, and MIME helpers.
1,629 lines • 65.5 kB
JavaScript
import * as y from "isomorphic-git";
import { fs as Tt, configureSingle as Ct } from "@zenfs/core";
import { WebAccess as Ot } from "@zenfs/dom";
import { applyPatch as Q, parsePatch as It } from "diff";
let B = null, tt = null;
function Pt() {
if (typeof navigator > "u" || !navigator.storage) return null;
const t = navigator.storage.getDirectory;
return typeof t == "function" ? t.bind(navigator.storage) : null;
}
async function lt(t, e) {
if (!t) return !1;
const n = t;
if (typeof n.isSameEntry == "function")
try {
return await n.isSameEntry(e);
} catch {
}
return t === e;
}
async function Mt(t) {
if (await lt(tt, t)) {
B && await B;
return;
}
B && (await B, await lt(tt, t)) || (B = (async () => {
try {
await Ct({ backend: Ot, handle: t }), tt = t;
} finally {
B = null;
}
})(), await B);
}
async function k() {
const t = Pt();
if (!t)
throw new Error("OPFS is not supported (navigator.storage.getDirectory unavailable).");
const e = await t();
return await Mt(e), Tt;
}
async function Lt(t, e) {
const { dir: n } = t, i = await k(), s = String(e || "").trim();
if (!s) throw new Error("resolveOid: ref/sha is required");
try {
return await y.resolveRef({ fs: i, dir: n, ref: s });
} catch {
if (!/^[0-9a-fA-F]{4,40}$/.test(s)) throw new Error(`resolveOid: cannot resolve ref '${e}'`);
return s.length === 40 ? s : await y.expandOid({ fs: i, dir: n, oid: s });
}
}
async function H(t, e = {}) {
const { dir: n } = t, i = e.defaultBranch ?? "main", s = await k();
let r = !1, a;
try {
a = await y.currentBranch({ fs: s, dir: n, fullname: !1 });
} catch {
a = void 0;
}
if (!a)
try {
await y.resolveRef({ fs: s, dir: n, ref: "HEAD" }), a = await y.currentBranch({ fs: s, dir: n, fullname: !1 });
} catch {
await y.init({ fs: s, dir: n, defaultBranch: i }), r = !0, a = i;
}
if (e.name)
try {
await y.setConfig({ fs: s, dir: n, path: "user.name", value: e.name });
} catch {
}
if (e.email)
try {
await y.setConfig({ fs: s, dir: n, path: "user.email", value: e.email });
} catch {
}
return { created: r, currentBranch: typeof a == "string" && a ? a : i };
}
async function Bt(t) {
const { dir: e } = t, n = await k(), i = await y.statusMatrix({ fs: n, dir: e }), s = [], r = [], a = [], l = [], o = [], c = [], u = [], f = [], d = [];
for (const m of i) {
const [h, p, w, E] = m;
if (p === 0 && w === 2 && E === 0) {
l.push(h);
continue;
}
if (p === 0 && (E === 2 || E === 3)) {
s.push(h), o.push(h);
continue;
}
if (p === 1 && w === 2) {
r.push(h), E === 2 ? c.push(h) : E === 1 && f.push(h);
continue;
}
if (p === 1 && w === 0) {
a.push(h), E === 0 ? u.push(h) : E === 1 && d.push(h);
continue;
}
}
return {
added: s,
modified: r,
deleted: a,
untracked: l,
stagedAdded: o,
stagedModified: c,
stagedDeleted: u,
unstagedModified: f,
unstagedDeleted: d
};
}
async function zt(t, e) {
const { dir: n } = t, { message: i, author: s, branch: r, dryRun: a } = e;
if (!i?.trim())
throw new Error("commitAll: commit message is required");
if (!s?.name || !s?.email)
throw new Error("commitAll: author { name, email } is required");
const l = await k();
await H(t);
const o = await Bt(t), c = [...o.added, ...o.modified, ...o.untracked], u = [...o.deleted];
for (const m of c)
a || await y.add({ fs: l, dir: n, filepath: m });
for (const m of u)
a || await y.remove({ fs: l, dir: n, filepath: m });
if (c.length === 0 && u.length === 0)
return {
oid: null,
added: [],
modified: [],
deleted: [],
summary: "No changes to commit.",
dryRun: a
};
let f = null;
if (!a) {
try {
const m = await y.currentBranch({ fs: l, dir: n, fullname: !1 });
r && m !== r && await y.writeRef({ fs: l, dir: n, ref: "HEAD", value: `refs/heads/${r}`, force: !0, symbolic: !0 });
} catch {
}
f = await y.commit({
fs: l,
dir: n,
message: i,
author: s,
committer: s
});
}
const d = (a ? "[dry-run] " : "") + `Committed ${c.length + u.length} change(s)` + (c.length ? ` (+${c.length})` : "") + (u.length ? ` (-${u.length})` : "") + ".";
return { oid: f, added: c, modified: o.modified, deleted: u, summary: d, dryRun: a };
}
async function je(t, e = {}) {
const { dir: n } = t, { limit: i = 20 } = e, s = await k();
let r = e.ref;
return r || (r = await y.currentBranch({ fs: s, dir: n, fullname: !1 }) ?? "HEAD"), (await y.log({ fs: s, dir: n, ref: r, depth: i })).map((l) => {
const o = l.commit || {}, c = o.author || {}, u = o.committer || {}, f = typeof u.timestamp == "number" ? new Date(u.timestamp * 1e3).toISOString() : void 0;
return {
oid: l.oid,
message: String(o.message || "").trim(),
author: c.name,
email: c.email,
isoDate: f,
parents: Array.isArray(l.parents) ? l.parents : []
};
});
}
async function Ue(t, e = {}) {
const { dir: n } = t, i = await k();
await H(t);
const s = e.perRefDepth ?? 200;
let r = e.refs;
if (!r) {
const o = await y.listBranches({ fs: i, dir: n }), c = e.includeTags ?? !0 ? await y.listTags({ fs: i, dir: n }) : [];
r = [...o, ...c];
}
const a = /* @__PURE__ */ new Map();
for (const o of r) {
let c = [];
try {
c = await y.log({ fs: i, dir: n, ref: o, depth: s });
} catch {
continue;
}
for (const u of c) {
const f = u.oid, d = u.commit || {}, m = d.author || {}, h = d.committer || {}, p = typeof h.timestamp == "number" ? new Date(h.timestamp * 1e3).toISOString() : void 0, w = Array.isArray(u.parents) ? u.parents : [], E = String(d.message || "").trim(), v = a.get(f);
v ? v.refs.includes(o) || v.refs.push(o) : a.set(f, {
oid: f,
message: E,
author: m.name,
email: m.email,
isoDate: p,
parents: w,
refs: [o]
});
}
}
const l = Array.from(a.values());
return l.sort((o, c) => (c.isoDate || "").localeCompare(o.isoDate || "")), typeof e.limit == "number" ? l.slice(0, e.limit) : l;
}
async function Wt(t, e) {
const { dir: n } = t, { to: i } = e, s = e.mode ?? "hard", r = e.force ?? !0;
if (!i || !String(i).trim()) throw new Error("revertToCommit: `to` is required");
const a = await k();
let l = "";
const o = String(i).trim(), c = /^[0-9a-fA-F]{4,40}$/.test(o);
try {
l = await y.resolveRef({ fs: a, dir: n, ref: o });
} catch {
if (!c)
throw new Error(`revertToCommit: cannot resolve ref '${i}'`);
try {
l = o.length === 40 ? o : await y.expandOid({ fs: a, dir: n, oid: o });
} catch {
throw new Error(`revertToCommit: cannot resolve OID '${i}'`);
}
}
await H(t);
let u = "";
try {
u = await y.currentBranch({ fs: a, dir: n, fullname: !1 }) || "";
} catch {
u = "";
}
if (s === "hard" && u) {
await y.writeRef({ fs: a, dir: n, ref: `refs/heads/${u}`, value: l, force: !0 });
try {
await y.writeRef({
fs: a,
dir: n,
ref: "HEAD",
value: `refs/heads/${u}`,
force: !0,
symbolic: !0
});
} catch {
}
await y.checkout({ fs: a, dir: n, ref: u, force: r });
const d = l.slice(0, 7);
return {
oid: l,
branch: u,
detached: !1,
summary: `Checked out ${d} on ${u} (hard)`
};
}
await y.writeRef({ fs: a, dir: n, ref: "HEAD", value: l, force: !0 }), await y.checkout({ fs: a, dir: n, force: r });
const f = l.slice(0, 7);
return {
oid: l,
detached: !0,
summary: `Detached HEAD at ${f}`
};
}
async function qe(t, e, n = !0) {
return Wt(t, { to: e, mode: "detached", force: n });
}
async function Ge(t, e) {
const { dir: n } = t, { at: i } = e, s = e.force ?? !0, r = e.paths && e.paths.length ? e.paths : void 0;
if (!i || !String(i).trim()) throw new Error("checkoutAtCommit: `at` is required");
const a = await k();
let l = "";
const o = String(i).trim(), c = /^[0-9a-fA-F]{4,40}$/.test(o);
try {
l = await y.resolveRef({ fs: a, dir: n, ref: o });
} catch {
if (!c)
throw new Error(`checkoutAtCommit: cannot resolve ref '${i}'`);
try {
l = o.length === 40 ? o : await y.expandOid({ fs: a, dir: n, oid: o });
} catch {
throw new Error(`checkoutAtCommit: cannot resolve OID '${i}'`);
}
}
await H(t), await y.checkout({ fs: a, dir: n, ref: l, filepaths: r, noUpdateHead: !0, force: s });
const u = l.slice(0, 7);
return {
oid: l,
paths: r,
summary: `Checked out ${r ? r.join(", ") : "all files"} from ${u}`
};
}
async function ut(t) {
const { dir: e } = t, n = await k();
let i;
try {
const s = await y.currentBranch({ fs: n, dir: e, fullname: !1, test: !0 });
typeof s == "string" && s.length > 0 && (i = s);
} catch {
}
if (i)
return { currentBranch: i, detached: !1 };
try {
return { detached: !0, headOid: await y.resolveRef({ fs: n, dir: e, ref: "HEAD" }) };
} catch {
return { detached: !0 };
}
}
async function Xe(t, e, n = {}) {
const { dir: i } = t, { createIfMissing: s = !0, force: r = !0 } = n, a = await k();
if (!e || !e.trim()) throw new Error("attachHeadToBranch: `branch` is required");
await H(t);
let l = !0;
try {
await y.resolveRef({ fs: a, dir: i, ref: `refs/heads/${e}` });
} catch {
l = !1;
}
let o = !1;
if (!l) {
if (!s)
throw new Error(`attachHeadToBranch: branch '${e}' does not exist`);
const c = await y.resolveRef({ fs: a, dir: i, ref: "HEAD" });
await y.writeRef({ fs: a, dir: i, ref: `refs/heads/${e}`, value: c, force: !0 }), o = !0;
}
return await y.writeRef({ fs: a, dir: i, ref: "HEAD", value: `refs/heads/${e}`, force: !0, symbolic: !0 }), await y.checkout({ fs: a, dir: i, ref: e, force: r }), {
branch: e,
created: o,
summary: o ? `Created and attached HEAD to '${e}'` : `Attached HEAD to '${e}'`
};
}
async function Ht(t, e) {
const { dir: n } = t, i = await k(), s = e.force ?? !0, r = e.refuseUpdateExisting ?? !0;
await H(t);
const a = await Lt(t, e.to), l = a.slice(0, 7), o = await y.listBranches({ fs: i, dir: n }), c = [];
for (const h of o)
try {
await y.resolveRef({ fs: i, dir: n, ref: `refs/heads/${h}` }) === a && c.push(h);
} catch {
}
if (c.length > 0) {
const h = c.includes("main") ? "main" : c[0];
return await y.writeRef({ fs: i, dir: n, ref: "HEAD", value: `refs/heads/${h}`, force: !0, symbolic: !0 }), await y.checkout({ fs: i, dir: n, ref: h, force: s }), {
branch: h,
oid: a,
created: !1,
summary: `Attached to '${h}' at ${l}`
};
}
const u = e.branch && e.branch.trim().length ? e.branch : `continue/${l}`;
let f = !0, d = "";
try {
d = await y.resolveRef({ fs: i, dir: n, ref: `refs/heads/${u}` });
} catch {
f = !1;
}
let m = !1;
if (!f)
await y.writeRef({ fs: i, dir: n, ref: `refs/heads/${u}`, value: a, force: !0 }), m = !0;
else if (d !== a) {
if (r)
throw new Error(
`continueFromCommit: branch '${u}' exists at ${d.slice(0, 7)}; choose a different name`
);
await y.writeRef({ fs: i, dir: n, ref: `refs/heads/${u}`, value: a, force: !0 });
}
return await y.writeRef({ fs: i, dir: n, ref: "HEAD", value: `refs/heads/${u}`, force: !0, symbolic: !0 }), await y.checkout({ fs: i, dir: n, ref: u, force: s }), {
branch: u,
oid: a,
created: m,
summary: `${m ? "Created" : "Attached to"} '${u}' at ${l}`
};
}
async function Ve({ dir: t, message: e, author: n }) {
await H({ dir: t });
const i = await ut({ dir: t });
i.detached && await Ht({ dir: t }, { to: i.headOid || "HEAD", force: !0, refuseUpdateExisting: !0 });
const s = await ut({ dir: t }), r = !s.detached && s.currentBranch ? s.currentBranch : void 0;
await zt(
{ dir: t },
{
message: e,
author: n,
...r ? { branch: r } : {}
}
);
}
function C(t) {
const e = [];
for (const n of t.split("/")) {
const i = n.trim();
if (!(!i || i === ".")) {
if (i === "..") {
e.length && e.pop();
continue;
}
e.push(i);
}
}
return e;
}
function A(t) {
return t.split("/").filter(Boolean).join("/");
}
function W(t) {
return $t(t).replace(/\\/g, "/").replace(/^\/+/, "").trim();
}
function x(t, e) {
return A(t ? e ? t + "/" + e : t : e);
}
function L(t) {
const e = t.lastIndexOf("/");
return e === -1 ? "" : t.slice(0, e);
}
function M(t) {
const e = t.lastIndexOf("/");
return e === -1 ? t : t.slice(e + 1);
}
function jt(t) {
if (!t) return !1;
const e = t.replace(/\\/g, "/");
return /(?:^|\/)\.\.(?:\/|$)/.test(e);
}
function Ut(t, e) {
const n = C(t).join("/"), i = C(e).join("/");
return !i || n === i ? !0 : n.startsWith(i + "/");
}
function Je(t, e) {
const n = C(t).join("/"), i = C(e).join("/"), s = n ? `${n}/${i}` : i;
if (!Ut(s, n))
throw new Error(`Path escapes workspace: "${e}" not under "${t}"`);
return s || ".";
}
function O(t) {
return "/" + C(t.replace(/\\/g, "/")).join("/");
}
async function rt(t, e) {
const n = await k();
if (e) {
await n.promises.mkdir?.(t, { recursive: !0 });
return;
}
try {
if (!(await n.promises.stat(t)).isDirectory()) {
const s = new Error(`Not a directory: ${t}`);
throw s.name = "TypeMismatchError", s;
}
} catch (i) {
if (i && (i.code === "ENOENT" || i.name === "NotFoundError")) {
const s = new Error(`Directory not found: ${t}`);
throw s.name = "NotFoundError", s;
}
throw i;
}
}
async function Ye(t = "") {
const e = O(t || "");
return e === "/" || await rt(
e,
/*create*/
!1
), e;
}
async function j(t, e = !1) {
const n = O(t || "");
return n === "/" || await rt(n, e), n;
}
async function at(t, e) {
const n = O(t || "");
return n === "/" || await rt(n, e), n;
}
async function q(t, e) {
const n = await k(), i = O(t);
O(L(t));
try {
if (!(await n.promises.stat(i)).isFile()) {
const r = new Error(`Not a file: ${i}`);
throw r.name = "TypeMismatchError", r;
}
return i;
} catch (s) {
if (s && (s.code === "ENOENT" || s.name === "NotFoundError")) {
const r = new Error(`File not found: ${i}`);
throw r.name = "NotFoundError", r;
}
throw s;
}
}
async function G(t) {
const e = await k(), n = O(t);
try {
return await e.promises.readFile(n, "utf8");
} catch (i) {
if (i && (i.code === "ENOENT" || i.name === "NotFoundError" || i.code === 1)) return null;
throw i;
}
}
async function z(t, e) {
const n = await k(), i = O(t), s = O(L(t));
await n.promises.mkdir?.(s, { recursive: !0 }), await n.promises.writeFile(i, e, "utf8");
}
async function U(t) {
const e = await k(), n = O(t);
try {
await e.promises.unlink(n);
} catch (i) {
if (i && (i.code === "ENOENT" || i.name === "NotFoundError" || i.code === 1)) return;
throw i;
}
}
function $t(t) {
if (typeof t != "string") return t;
const e = /[\u001B\u009B][[()#;?]*(?:\d{1,4}(?:;\d{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
return t.replace(e, "");
}
async function Ke(t) {
const { workDir: e = "", diffContent: n, signal: i, git: s, sanitizeAnsiDiff: r = !0, maxOffsetLines: a = 200 } = t, l = r ? $t(n) : n, c = Zt(l) ?? l, u = /^(---|\+\+\+)\s/m.test(c), f = /^@@/m.test(c);
if (u && !f)
return { success: !0, output: "No changes in patch (no hunks)." };
const d = await j(e, !0);
let m;
try {
m = await Vt({
diffText: c,
baseDir: d,
maxOffsetLines: a
});
} catch (_) {
return u && !f ? { success: !0, output: "No changes in patch (no hunks)." } : { success: !1, output: "Failed to parse patch: " + Z(_) };
}
if (m = Kt(m), !m.length)
return { success: !1, output: "No file hunks found in patch." };
const h = new Yt(), p = new qt(s, e, h), w = [];
for (const _ of m) {
if (i?.aborted) break;
const g = K(_.oldFileName), $ = K(_.newFileName), b = g === null && $ !== null, N = $ === null && g !== null, D = g !== null && $ !== null && g !== $, F = $ ?? g;
if (F !== null)
try {
if (b) {
const T = Q("", _);
if (T === !1) throw new Error("Hunks failed to apply for creation");
await z(x(d, F), T), h.created.push(F), await p.add(F), w.push(async () => {
await U(x(d, F)), await p.remove(F);
});
continue;
}
if (N) {
const T = await G(x(d, g));
if (T === null)
await U(x(d, g)), h.deleted.push(g), await p.remove(g);
else {
if (Q(T, _) === !1) throw new Error("Hunks failed to apply for deletion");
await U(x(d, g)), h.deleted.push(g), await p.remove(g), w.push(async () => {
await z(x(d, g), T), await p.add(g);
});
}
continue;
}
const S = await G(x(d, g));
if (S === null) throw new Error("Target file not found: " + g);
const R = Gt(_), I = D && !R ? S : Q(S, _);
if (I === !1) throw new Error("Hunks failed to apply");
D ? (await z(x(d, $), I), await U(x(d, g)), h.renamed.push({ from: g, to: $ }), await p.add($), await p.remove(g), w.push(async () => {
await z(x(d, g), S), await U(x(d, $)), await p.add(g), await p.remove($);
})) : (await z(x(d, g), I), h.modified.push(g), await p.add(g), w.push(async () => {
await z(x(d, g), S), await p.add(g);
}));
} catch (S) {
h.failed.push({ path: F, reason: Z(S) });
}
}
const E = h.failed.length === 0 && !i?.aborted;
if (!E) {
for (const _ of w.reverse())
try {
await _();
} catch {
}
h.created = [], h.modified = [], h.deleted = [], h.renamed = [];
}
const v = h.summary(E, i?.aborted) + (E ? "" : " Changes reverted.");
return {
success: E,
output: v,
details: {
created: h.created,
modified: h.modified,
deleted: h.deleted,
renamed: h.renamed,
failed: h.failed
}
};
}
class qt {
ctx;
shouldStage;
workDir;
tracker;
constructor(e, n, i) {
this.ctx = e, this.workDir = n, this.shouldStage = !!(e && (e.stage ?? !0)), this.tracker = i;
}
async add(e) {
if (!(!this.shouldStage || !this.ctx))
try {
await this.ctx.git.add({
fs: this.ctx.fs,
dir: this.ctx.dir,
filepath: ft(this.workDir, e, this.ctx.dir)
});
} catch (n) {
this.tracker.failed.push({ path: e, reason: "git add failed: " + Z(n) });
}
}
async remove(e) {
if (!(!this.shouldStage || !this.ctx))
try {
await this.ctx.git.remove({
fs: this.ctx.fs,
dir: this.ctx.dir,
filepath: ft(this.workDir, e, this.ctx.dir)
});
} catch (n) {
this.tracker.failed.push({
path: e,
reason: "git remove failed: " + Z(n)
});
}
}
}
function ft(t, e, n) {
const i = t ? C(t).join("/") : "";
return i ? x(i, e) : e;
}
function K(t) {
if (!t || t === "/dev/null") return null;
const e = t.replace(/^[ab]\//, "").replace(/^\/+/, "").replace(/\\/g, "/");
return C(e).join("/");
}
function Z(t) {
return t instanceof Error ? t.message : String(t);
}
function Gt(t) {
return t.hunks?.some((e) => e.lines?.some((n) => n.startsWith("+") || n.startsWith("-"))) ?? !0;
}
const Xt = /^@@\s+-([0-9]+)(?:,([0-9]+))?\s+\+([0-9]+)(?:,([0-9]+))?\s+@@/, dt = /^@@/;
async function Vt(t) {
const { diffText: e, baseDir: n, maxOffsetLines: i } = t;
let s = null;
try {
s = It(e).map((l) => ({
oldFileName: l.oldFileName,
newFileName: l.newFileName,
hunks: (l.hunks || []).map((o) => ({
header: "",
oldStart: typeof o.oldStart == "number" && Number.isFinite(o.oldStart) ? o.oldStart : void 0,
oldLines: typeof o.oldLines == "number" && Number.isFinite(o.oldLines) ? o.oldLines : void 0,
newStart: typeof o.newStart == "number" && Number.isFinite(o.newStart) ? o.newStart : void 0,
newLines: typeof o.newLines == "number" && Number.isFinite(o.newLines) ? o.newLines : void 0,
lines: o.lines || []
}))
}));
} catch {
}
if (s || (s = Jt(e)), !s.length) return [];
const r = [];
for (const a of s) {
const l = K(a.oldFileName), o = K(a.newFileName), c = l !== null && o === null, u = l ? await G(x(n, l)) : null, f = (u ?? "").split(/\r?\n/), d = [];
let m = 0;
for (const h of a.hunks) {
const p = (h.lines || []).filter((b) => b?.startsWith(" ") || b?.startsWith("+") || b?.startsWith("-")), w = p.filter((b) => b.startsWith(" ") || b.startsWith("-")), E = p.filter((b) => b.startsWith(" ") || b.startsWith("+")), v = w.length, _ = E.length;
let g = h.oldStart;
if (h.oldStart && l && f.length) {
const b = h.oldStart - 1, N = Math.max(0, b - i), D = Math.min(f.length, b + i + 1), F = w.map((R) => R.slice(1)), S = mt(f, F, N, D);
S === -1 ? g = b + 1 : g = S + 1;
}
if (!g)
if (!l)
g = 1;
else if (c && u === null)
g = 1;
else {
const b = w.map((D) => D.slice(1)), N = mt(f, b, 0, f.length);
g = (N === -1 ? 0 : N) + 1;
}
const $ = Math.max(1, g + m);
d.push({
oldStart: g,
oldLines: v,
newStart: $,
newLines: _,
lines: p
}), m += _ - v;
}
r.push({
oldFileName: a.oldFileName,
newFileName: a.newFileName,
hunks: d
});
}
return r;
}
function Jt(t) {
const e = t.split(/\r?\n/), n = [];
let i = 0;
for (; i < e.length; ) {
const s = e[i];
if (s?.startsWith("--- ")) {
const r = ht(s.slice(4)), a = e[i + 1] || "";
if (!a.startsWith("+++ ")) {
i++;
continue;
}
const l = ht(a.slice(4));
i += 2;
const o = [];
for (; i < e.length && dt.test(e[i] || ""); ) {
const c = e[i] || "";
let u, f, d, m;
const h = c.match(Xt);
h && (u = Y(h[1]), f = Y(h[2] ?? "1"), d = Y(h[3]), m = Y(h[4] ?? "1")), i++;
const p = [];
for (; i < e.length; ) {
const w = e[i];
if (w?.startsWith("--- ") || dt.test(w || "") || w?.startsWith("diff --git ")) break;
if (w?.startsWith("\\ No newline at end of file")) {
i++;
continue;
}
if (!w?.startsWith(" ") && !w?.startsWith("+") && !w?.startsWith("-")) break;
p.push(w), i++;
}
o.push({ header: c, oldStart: u, oldLines: f, newStart: d, newLines: m, lines: p });
}
n.push({ oldFileName: r, newFileName: l, hunks: o });
continue;
}
i++;
}
return n;
}
function ht(t) {
return (t.split(/\t|\s/)[0] ?? t).trim();
}
function Y(t) {
const e = parseInt(t, 10);
return Number.isFinite(e) && e > 0 ? e : 1;
}
function mt(t, e, n, i) {
if (e.length === 0) return n;
const s = Math.min(t.length, i);
for (let r = n; r <= s - e.length; r++) {
let a = !0;
for (let l = 0; l < e.length; l++)
if (t[r + l] !== e[l]) {
a = !1;
break;
}
if (a) return r;
}
return -1;
}
class Yt {
created = [];
modified = [];
deleted = [];
renamed = [];
failed = [];
summary(e, n) {
return [
n ? "Patch aborted." : e ? "Patch applied successfully." : "Patch completed with errors.",
this.created.length ? `Created: ${this.created.length}` : "",
this.modified.length ? `Modified: ${this.modified.length}` : "",
this.deleted.length ? `Deleted: ${this.deleted.length}` : "",
this.renamed.length ? `Renamed: ${this.renamed.length}` : "",
this.failed.length ? `Failed: ${this.failed.length}` : ""
].filter(Boolean).join(" ");
}
}
function Kt(t) {
return t.map((e) => ({
...e,
hunks: (e.hunks || []).map((n) => ({
...n,
lines: (n.lines || []).filter((i) => typeof i == "string" && /^[ +-]/.test(i))
}))
}));
}
function Zt(t) {
if (!/\*\*\*\s+(Begin Patch|Update File:|Add File:|Delete File:)/.test(t)) return null;
const n = t.split(/\r?\n/), i = [];
let s = 0;
for (; s < n.length; ) {
const r = n[s] || "";
if (/^\*\*\*\s+Begin Patch/.test(r) || /^\*\*\*\s+End Patch/.test(r)) {
s++;
continue;
}
const a = r.match(/^\*\*\*\s+(Update|Add|Delete) File:\s+(.*)$/);
if (a) {
const l = a[1];
let o = (a[2] || "").trim(), c = null;
n[s + 1] && /^\*\*\*\s+Move to:\s+/.test(n[s + 1]) && (c = (n[s + 1].replace(/^\*\*\*\s+Move to:\s+/, "") || "").trim(), s++);
const u = (h) => h.replace(/^\/+/, "").replace(/\\/g, "/");
o = u(o);
const f = c ? u(c) : null;
let d, m;
for (l === "Add" ? (d = "/dev/null", m = `b/${o}`) : l === "Delete" ? (d = `a/${o}`, m = "/dev/null") : (d = `a/${o}`, m = f ? `b/${f}` : `b/${o}`), i.push(`--- ${d}`), i.push(`+++ ${m}`), s++; s < n.length; ) {
const h = n[s] || "";
if (/^\*\*\*\s+(Update|Add|Delete) File:/.test(h) || /^\*\*\*\s+End Patch/.test(h)) break;
if (/^\*\*\*\s+Move to:/.test(h)) {
s++;
continue;
}
if (h.startsWith("@@")) {
i.push(h), s++;
continue;
}
if (h.startsWith(" ") || h.startsWith("+") || h.startsWith("-")) {
i.push(h), s++;
continue;
}
if (h.startsWith("\\ No newline at end of file")) {
s++;
continue;
}
if (h.trim() === "") {
i.push(""), s++;
continue;
}
break;
}
i.length && i[i.length - 1] !== "" && i.push("");
continue;
}
s++;
}
return i.length ? i.join(`
`) : null;
}
async function Qt(t, e, n) {
if (!t.length) return "";
const i = [];
for (const s of t)
s === "-n" || s === "-e" || s === "-E" || i.push(s);
return i.join(" ");
}
function X(t, e = {}) {
const n = e.dot ?? !0, i = e.caseSensitive ?? !0;
let s = "^", r = 0;
for (; r < t.length; ) {
const l = t[r];
if (l === "*") {
t[r + 1] === "*" ? (s += ".*", r += 2) : (s += n ? "[^/]*" : "(?!\\.)[^/]*", r++);
continue;
}
if (l === "?") {
s += n ? "[^/]" : "(?!\\.)[^/]", r++;
continue;
}
if (l === "[") {
const { src: o, newIndex: c } = te(t, r);
s += o, r = c;
continue;
}
if (l === "\\") {
r + 1 < t.length ? (s += pt(t[r + 1]), r += 2) : (s += "\\\\", r++);
continue;
}
if (l === "/") {
s += "/", r++;
continue;
}
s += pt(l), r++;
}
s += "$";
const a = i ? "" : "i";
return new RegExp(s, a);
}
function te(t, e) {
let n = e + 1, i = !1;
t[n] === "!" && (i = !0, n++);
let s = "";
for (t[n] === "]" && (s += "\\]", n++); n < t.length && t[n] !== "]"; ) {
const l = t[n];
l === "\\" ? n + 1 < t.length ? (s += "\\" + t[n + 1], n += 2) : (s += "\\\\", n++) : "^$.|+(){}".includes(l) ? (s += "\\" + l, n++) : (s += l, n++);
}
if (n >= t.length || t[n] !== "]")
return { src: "\\[", newIndex: e + 1 };
const r = t[n];
return n++, { src: "[" + (i ? "^" : "") + s + r, newIndex: n };
}
function pt(t) {
return /[\\^$.*+?()[\]{}|]/.test(t) ? "\\" + t : t;
}
function V(t) {
const e = ee(t);
if (!e) return [t];
const { start: n, end: i } = e, s = t.slice(0, n), r = t.slice(n + 1, i), a = t.slice(i + 1), l = ne(r);
return l.length <= 1 ? [t] : l.map((c) => `${s}${c}${a}`).flatMap(V);
}
function ee(t) {
let e = 0, n = -1;
for (let i = 0; i < t.length; i++) {
const s = t[i];
if (s === "\\") {
i++;
continue;
}
if (s === "{")
e === 0 && (n = i), e++;
else if (s === "}" && e > 0 && (e--, e === 0))
return { start: n, end: i };
}
return null;
}
function ne(t) {
const e = [];
let n = "", i = 0;
for (let s = 0; s < t.length; s++) {
const r = t[s];
if (r === "\\") {
n += r, s + 1 < t.length && (n += t[s + 1], s++);
continue;
}
if (r === "{") {
i++, n += r;
continue;
}
if (r === "}") {
i > 0 && i--, n += r;
continue;
}
if (r === "," && i === 0) {
e.push(n), n = "";
continue;
}
n += r;
}
return e.push(n), e;
}
async function ie(t, e) {
const {
pattern: n,
flags: i,
include: s,
exclude: r,
maxFileSize: a = 20 * 1024 * 1024,
concurrency: l = 4,
encoding: o = "utf-8",
signal: c,
onMatch: u
} = e, f = (s ?? []).flatMap((v) => V(v)).map((v) => X(v)), d = (r ?? []).flatMap((v) => V(v)).map((v) => X(v)), m = se(n, i), h = await j(t || "", !1), p = [];
for await (const v of St(h, "", { signal: c })) {
if (re(v, f, d)) continue;
const _ = x(h, v);
p.push({ path: v, abs: _ });
}
const w = [], E = await k();
return await ae(p, Math.max(1, l), async (v) => {
if (!c?.aborted)
try {
if (((await E.promises.stat("/" + A(v.abs))).size ?? 0) > a) return;
const g = await E.promises.readFile("/" + A(v.abs)), b = (typeof g == "string" ? g : new TextDecoder(o, { fatal: !1 }).decode(g)).split(`
`);
for (let N = 0; N < b.length; N++) {
let D = b[N];
D.endsWith("\r") && (D = D.slice(0, -1)), m.lastIndex = 0;
let F;
for (; (F = m.exec(D)) !== null; ) {
const S = (F.index ?? 0) + 1, R = {
file: v.path,
line: N + 1,
column: S,
match: F[0],
lineText: D
};
w.push(R), u && await u(R), F[0] === "" && m.lastIndex++;
}
}
} catch {
}
}), w;
}
async function* St(t, e = "", { signal: n } = {}) {
if (n?.aborted) return;
const i = await k(), s = "/" + (e ? x(t, e) : A(t));
let r = [];
try {
r = await i.promises.readdir(s);
} catch {
return;
}
for (const a of r) {
if (n?.aborted) return;
const l = e ? `${e}/${a}` : a, o = "/" + x(t, l);
let c;
try {
c = await i.promises.stat(o);
} catch {
continue;
}
if (c.isFile?.()) {
yield l;
continue;
}
c.isDirectory?.() && (yield* St(t, l, { signal: n }));
}
}
function se(t, e) {
if (t instanceof RegExp) {
const s = t.flags.includes("g") ? t.flags : t.flags + "g";
return new RegExp(t.source, s);
}
const n = e ?? "", i = n.includes("g") ? n : n + "g";
return new RegExp(t, i);
}
function re(t, e, n) {
const i = t.replace(/\\/g, "/");
return !!(n.some((s) => s.test(i)) || e.length > 0 && !e.some((s) => s.test(i)));
}
async function ae(t, e, n) {
let i = 0;
const s = Array.from({ length: Math.min(e, t.length || 1) }, async function() {
for (; i < t.length; ) {
const a = i++;
await n(t[a]);
}
});
await Promise.all(s);
}
async function et(t, e = {}) {
const {
maxDepth: n = 1,
include: i,
exclude: s,
showHidden: r = !1,
kinds: a = ["file", "directory"],
stat: l = !1,
concurrency: o = 4,
signal: c,
onEntry: u,
sortBy: f = "name",
sortOrder: d = "asc",
dirsFirst: m = !0
} = e, h = (i ?? []).flatMap((g) => V(g)).map((g) => X(g, { dot: !0, caseSensitive: !0 })), p = (s ?? []).flatMap((g) => V(g)).map((g) => X(g, { dot: !0, caseSensitive: !0 })), w = [], E = [], v = await j(
t || "",
/*create*/
!1
), _ = await k();
return await kt(_, v, "", 0, {
maxDepth: n,
showHidden: r,
excludeREs: p,
signal: c,
onDir: async (g, $, b) => {
const N = $ ? `${$}/${g}` : g;
if (a.includes("directory") && !yt(N, h, p, r, g)) {
const F = { path: N, name: g, kind: "directory", depth: b };
w.push(F), u && await u(F);
}
},
onFile: async (g, $, b) => {
const N = $ ? `${$}/${g}` : g;
if (!(a.includes("file") && !yt(N, h, p, r, g))) return;
const F = { path: N, name: g, kind: "file", depth: b };
if (w.push(F), l) {
const S = "/" + x(v, N);
E.push(async () => {
try {
const R = await _.promises.stat(S);
F.size = Number(R.size ?? 0), F.lastModified = Number(R.mtimeMs ?? 0);
} catch {
}
u && await u(F);
});
} else
u && await u(F);
}
}), E.length > 0 && await ue(E, Math.max(1, o), (g) => g()), le(w, { sortBy: f, sortOrder: d, dirsFirst: m }), w;
}
function oe(t) {
if (t == null) return "-";
const e = ["B", "KB", "MB", "GB", "TB"];
let n = 0, i = t;
for (; i >= 1024 && n < e.length - 1; )
i /= 1024, n++;
return (n === 0 ? i.toString() : i.toFixed(1)) + " " + e[n];
}
function ce(t) {
if (t == null) return "-";
const e = new Date(t), n = (i) => i < 10 ? "0" + i : "" + i;
return e.getFullYear() + "-" + n(e.getMonth() + 1) + "-" + n(e.getDate()) + " " + n(e.getHours()) + ":" + n(e.getMinutes());
}
function wt(t) {
const e = [];
for (const n of t) {
const i = n.kind === "directory" ? "d" : "-", s = n.kind === "file" ? oe(n.size) : "-", r = n.kind === "file" ? ce(n.lastModified) : "-";
e.push(`${i} ${s.padStart(10)} ${r} ${n.path}`);
}
return e.join(`
`);
}
function Ze(t) {
const e = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Set(), i = (c) => {
const u = c.lastIndexOf("/");
return u === -1 ? c : c.slice(u + 1);
}, s = (c) => (e.has(c) || e.set(c, []), e.get(c)), r = (c) => {
if (c === "" || n.has(c)) return;
const u = gt(c);
r(u), s(u).push({ path: c, name: i(c), kind: "directory" }), n.add(c), s(c);
};
for (const c of t) {
const u = c.path.replace(/\\/g, "/");
if (c.kind === "directory")
r(u);
else {
const f = gt(u);
r(f), n.has(u) || (s(f).push({ path: u, name: c.name, kind: "file" }), n.add(u));
}
}
for (const c of e.values())
c.sort((u, f) => u.kind !== f.kind ? u.kind === "directory" ? -1 : 1 : u.name.localeCompare(f.name));
const a = [], l = (c, u) => {
const f = e.get(c) || [];
f.forEach((d, m) => {
const h = m === f.length - 1, p = h ? "└── " : "├── ", w = u + (h ? " " : "│ ");
a.push(u + p + (d.kind === "directory" ? d.name + "/" : d.name)), d.kind === "directory" && l(d.path, w);
});
};
return l("", ""), a.join(`
`) || "<empty>";
}
function gt(t) {
const e = t.lastIndexOf("/");
return e === -1 ? "" : t.slice(0, e);
}
function le(t, e) {
const n = e.sortOrder === "asc" ? 1 : -1;
t.sort((i, s) => {
if (e.dirsFirst && i.kind !== s.kind)
return i.kind === "directory" ? -1 : 1;
const r = e.sortBy === "name" ? i.name : e.sortBy === "path" ? i.path : e.sortBy === "size" ? i.size ?? -1 : i.lastModified ?? 0, a = e.sortBy === "name" ? s.name : e.sortBy === "path" ? s.path : e.sortBy === "size" ? s.size ?? -1 : s.lastModified ?? 0;
return typeof r == "string" && typeof a == "string" ? r.localeCompare(a) * n : (r < a ? -1 : r > a ? 1 : 0) * n;
});
}
function yt(t, e, n, i, s) {
if (!i && s.startsWith(".")) return !0;
const r = t.replace(/\\/g, "/");
return !!(n.some((a) => a.test(r)) || e.length > 0 && !e.some((a) => a.test(r)));
}
async function ue(t, e, n) {
let i = 0;
const s = Array.from({ length: Math.min(e, t.length || 1) }, async function() {
for (; i < t.length; ) {
const a = i++;
await n(t[a]);
}
});
await Promise.all(s);
}
async function kt(t, e, n, i, s) {
if (s.signal?.aborted || i >= s.maxDepth) return;
const r = "/" + (n ? x(e, n) : e);
let a = [];
try {
a = await t.promises.readdir(r);
} catch {
return;
}
for (const l of a) {
if (s.signal?.aborted) return;
const o = l.startsWith("."), c = n ? `${n}/${l}` : l, u = "/" + x(e, c);
let f;
try {
f = await t.promises.stat(u);
} catch {
continue;
}
const d = i + 1;
if (f.isDirectory?.()) {
if (o && !s.showHidden || s.excludeREs.some((m) => m.test(c))) continue;
await s.onDir(l, n, d), await kt(t, e, c, d, s);
} else f.isFile?.() && await s.onFile(l, n, d);
}
}
async function fe(t, e) {
let n, i, s, r, a = 0;
for (let h = 0; h < t.length; h++) {
const p = t[h];
if (p === "-name")
i = t[++h];
else if (p === "-type") {
const w = t[++h];
w === "f" ? s = "file" : w === "d" && (s = "directory");
} else if (p === "-maxdepth") {
const w = parseInt(t[++h] ?? "", 10);
!Number.isNaN(w) && w >= 0 && (r = w);
} else if (p === "-mindepth") {
const w = parseInt(t[++h] ?? "", 10);
!Number.isNaN(w) && w >= 0 && (a = w);
} else p.startsWith("-") || n == null && (n = p);
}
const o = A(n ?? "."), c = A(x(e.cwd, o));
let u;
try {
await j(
c,
/*create*/
!1
), u = "directory";
} catch {
await q(
c
), u = "file";
}
const f = i ? X(i) : void 0, d = [], m = (h) => !(s && h.kind !== s || f && !f.test(h.name) || h.depth < a || r != null && h.depth > r);
if (u === "directory") {
a <= 0 && m({
name: o === "." ? "." : M(o),
kind: "directory",
depth: 0
}) && d.push(o);
const h = await et(c, {
maxDepth: r == null ? 1 / 0 : Math.max(0, r),
showHidden: !0,
kinds: ["file", "directory"],
stat: !1,
dirsFirst: !1
});
for (const p of h) {
const w = p.depth, E = { name: p.name, kind: p.kind, depth: w };
if (!m(E)) continue;
const v = o === "." ? p.path : `${o}/${p.path}`;
d.push(v);
}
} else
a <= 0 && m({ name: M(c), kind: "file", depth: 0 }) && d.push(o);
return d.join(`
`);
}
function Nt(t) {
return t.startsWith('"') && t.endsWith('"') || t.startsWith("'") && t.endsWith("'") ? t.slice(1, -1) : t;
}
function de(t) {
return t.replace(/[\\*?[\]{}()!+@]/g, (e) => "\\" + e);
}
async function he(t, e) {
const n = A(x(e.cwd, t));
return await j(
n,
/*create*/
!1
), { full: n };
}
async function Dt(t, e) {
const n = A(x(t.cwd, e));
return await q(
n
), { full: n };
}
async function me(t, e) {
let n = !1, i = !1, s = !1;
const r = [];
for (const u of t)
u.startsWith("-") ? (n = n || u.includes("l"), i = i || u.includes("a"), s = s || u.includes("R")) : r.push(u);
const a = r[0] ?? ".", l = A(a);
if (jt(l))
throw new Error("Parent directory traversal ('..') is not supported");
const o = A(x(e.cwd, l));
let c;
try {
await j(
o,
/*create*/
!1
), c = "directory";
} catch {
await q(
o
), c = "file";
}
if (c === "directory") {
const u = await et(o, {
maxDepth: s ? 1 / 0 : 1,
showHidden: i,
stat: n,
sortBy: "name",
sortOrder: "asc",
dirsFirst: !0
});
return n ? wt(u) : u.map((f) => f.path).join(`
`);
} else if (n) {
const u = L(o), f = M(o), d = await et(u, {
maxDepth: 1,
include: [de(f)],
showHidden: !0,
stat: !0
});
return wt(d.filter((m) => m.path === f));
} else
return M(l);
}
async function pe(t, e, n) {
let i = "t", s = 6, r = " ";
const a = [];
for (let f = 0; f < t.length; f++) {
const d = t[f];
if (!d.startsWith("-")) {
a.push(d);
continue;
}
if (d === "-b") {
const m = t[++f];
(m === "a" || m === "t") && (i = m);
continue;
}
if (d.startsWith("-b") && d.length > 2) {
const m = d.slice(2);
(m === "a" || m === "t") && (i = m);
continue;
}
if (d === "-w") {
const m = parseInt(t[++f] ?? "", 10);
!Number.isNaN(m) && m > 0 && (s = m);
continue;
}
if (d.startsWith("-w") && d.length > 2) {
const m = parseInt(d.slice(2), 10);
!Number.isNaN(m) && m > 0 && (s = m);
continue;
}
if (d === "-s") {
r = t[++f] ?? r;
continue;
}
if (d.startsWith("-s") && d.length > 2) {
r = d.slice(2);
continue;
}
}
let l;
if (a.length > 0) {
const f = a[0], { full: d } = await Dt(e, f);
l = await (await k()).promises.readFile("/" + d, "utf8");
} else
l = n ?? "";
const o = l.split(`
`);
o.length && o[o.length - 1] === "" && o.pop();
const c = [];
let u = 1;
for (const f of o) {
const d = f.length === 0;
if (i === "a" ? !0 : !d) {
const h = String(u++).padStart(s, " ");
c.push(h + r + f);
} else
c.push("");
}
return c.join(`
`);
}
async function we(t, e) {
let n = !1, i = !1;
const s = [];
for (const f of t)
f === "-n" ? n = !0 : f === "-S" ? i = !0 : s.push(f);
if (s.length === 0) throw new Error("rg: missing pattern");
const r = Nt(s[0]), a = s[1] ?? ".";
let l = "";
i && !/[A-Z]/.test(r) && (l += "i");
const o = new RegExp(r, l.includes("g") ? l : l + "g"), { full: c } = await he(a, e);
return (await ie(c, {
pattern: o,
exclude: ["**/node_modules/**", "**/.git/**"],
onMatch: void 0
})).map(
(f) => n ? `${f.file}:${f.line}:${f.column}: ${f.lineText}` : `${f.file}:${f.line}:${f.column}: ${f.match}`
).join(`
`);
}
var P = /* @__PURE__ */ ((t) => (t.UNHANDLED_EXCEPTION = "unhandled_exception", t.EXECUTION_FAILED = "execution_failed", t.FILE_NOT_FOUND = "file_not_found", t.FILE_WRITE_FAILURE = "file_write_failure", t.READ_CONTENT_FAILURE = "read_content_failure", t.ATTEMPT_TO_CREATE_EXISTING_FILE = "attempt_to_create_existing_file", t.FILE_TOO_LARGE = "file_too_large", t.PERMISSION_DENIED = "permission_denied", t.NO_SPACE_LEFT = "no_space_left", t.TARGET_IS_DIRECTORY = "target_is_directory", t.PATH_NOT_IN_WORKSPACE = "path_not_in_workspace", t.SEARCH_PATH_NOT_FOUND = "search_path_not_found", t.SEARCH_PATH_NOT_A_DIRECTORY = "search_path_not_a_directory", t.EDIT_PREPARATION_FAILURE = "edit_preparation_failure", t.EDIT_NO_OCCURRENCE_FOUND = "edit_no_occurrence_found", t.EDIT_EXPECTED_OCCURRENCE_MISMATCH = "edit_expected_occurrence_mismatch", t.EDIT_NO_CHANGE = "edit_no_change", t.GLOB_EXECUTION_ERROR = "glob_execution_error", t.GREP_EXECUTION_ERROR = "grep_execution_error", t.LS_EXECUTION_ERROR = "ls_execution_error", t.PATH_IS_NOT_A_DIRECTORY = "path_is_not_a_directory", t.READ_MANY_FILES_SEARCH_ERROR = "read_many_files_search_error", t))(P || {});
const ge = 2e3, ye = 2e3;
function nt(t) {
return t.replace(/\\/g, "/");
}
function it(t) {
t = nt(t);
const e = t.split("/").filter(Boolean), n = [];
for (const i of e)
i !== "." && (i === ".." ? n.pop() : n.push(i));
return n.join("/");
}
function Et(t) {
const e = it(t);
return e ? e.split("/") : [];
}
function vt(t, e) {
const n = Et(t), i = Et(e);
let s = 0;
for (; s < n.length && s < i.length && n[s] === i[s]; ) s++;
const r = new Array(n.length - s).fill(".."), a = i.slice(s);
return [...r, ...a].join("/") || ".";
}
const Ee = {
// Text
txt: "text/plain",
md: "text/markdown",
markdown: "text/markdown",
html: "text/html",
htm: "text/html",
css: "text/css",
csv: "text/csv",
tsv: "text/tab-separated-values",
sql: "application/sql",
xml: "application/xml",
json: "application/json",
yaml: "application/yaml",
yml: "application/yaml",
// Scripts
js: "application/javascript",
mjs: "application/javascript",
cjs: "application/javascript",
ts: "text/plain",
// treat as text (avoid video/MP2T misclassification)
tsx: "text/plain",
jsx: "text/plain",
// Images
png: "image/png",
jpg: "image/jpeg",
jpeg: "image/jpeg",
gif: "image/gif",
webp: "image/webp",
bmp: "image/bmp",
avif: "image/avif",
ico: "image/x-icon",
cur: "image/x-icon",
svg: "image/svg+xml",
svgz: "image/svg+xml",
// Audio
mp3: "audio/mpeg",
mpeg: "audio/mpeg",
wav: "audio/wav",
oga: "audio/ogg",
ogg: "audio/ogg",
m4a: "audio/mp4",
aac: "audio/aac",
flac: "audio/flac",
opus: "audio/opus",
// Video
mp4: "video/mp4",
m4v: "video/mp4",
mov: "video/quicktime",
webm: "video/webm",
ogv: "video/ogg",
mkv: "video/x-matroska",
// Docs/other
pdf: "application/pdf",
zip: "application/zip",
gz: "application/gzip",
tar: "application/x-tar",
"7z": "application/x-7z-compressed",
wasm: "application/wasm",
woff: "font/woff",
woff2: "font/woff2",
ttf: "font/ttf",
otf: "font/otf"
};
function ve(t) {
const e = t.split("/").pop() || t, n = e.lastIndexOf(".");
if (!(n < 0 || n === e.length - 1))
return e.slice(n + 1).toLowerCase();
}
function Rt(t) {
const e = ve(t);
if (e)
return Ee[e];
}
function Fe(t) {
const e = t instanceof Uint8Array ? t : new Uint8Array(t);
let n = "";
const i = 32768;
for (let s = 0; s < e.length; s += i)
n += String.fromCharCode(...e.subarray(s, s + i));
return btoa(n);
}
async function xe(t, e) {
const n = t.toLowerCase(), i = n.lastIndexOf("."), s = i >= 0 ? n.slice(i) : "";
if ([".ts", ".mts", ".cts"].includes(s)) return "text";
if (s === ".svg") return "svg";
const r = Rt(t);
if (r) {
if (r === "image/svg+xml") return "svg";
if (r.startsWith("image/")) return "image";
if (r.startsWith("audio/")) return "audio";
if (r.startsWith("video/")) return "video";
if (r === "application/pdf") return "pdf";
}
return [
".zip",
".tar",
".gz",
".7z",
".exe",
".dll",
".so",
".class",
".jar",
".war",
".doc",
".docx",
".xls",
".xlsx",
".ppt",
".pptx",
".odt",
".ods",
".odp",
".bin",
".dat",
".obj",
".o",
".a",
".lib",
".wasm",
".pyc",
".pyo"
].includes(s) ? "binary" : "text";
}
async function be(t, e, n, i, s, r) {
const a = it(t), l = it(e);
try {
let o;
try {
o = await q(
a,
/*create*/
!1
);
} catch (p) {
if (p?.name === "TypeMismatchError")
return {
llmContent: "Could not read file because the provided path is a directory, not a file.",
returnDisplay: "Path is a directory.",
error: `Path is a directory, not a file: ${a}`,
errorType: P.TARGET_IS_DIRECTORY
};
if (p?.name === "NotFoundError" || p?.code === "ENOENT" || p?.code === 404)
return {
llmContent: "Could not read file because no file was found at the specified path.",
returnDisplay: "File not found.",
error: `File not found: ${a}`,
errorType: P.FILE_NOT_FOUND
};
throw p;
}
const c = await k(), u = await c.promises.stat(o), f = r?.maxFileSizeMB ?? 20, d = u.size / (1024 * 1024);
if (d > f)
return {
llmContent: `File size exceeds the ${f}MB limit.`,
returnDisplay: `File size exceeds the ${f}MB limit.`,
error: `File size exceeds the ${f}MB limit: ${a} (${d.toFixed(2)}MB)`,
errorType: P.FILE_TOO_LARGE
};
const m = await xe(a), h = nt(vt(l, a));
switch (m) {
case "binary":
return {
llmContent: `Cannot display content of binary file: ${h}`,
returnDisplay: `Skipped binary file: ${h}`
};
case "svg":
return u.size > 1048576 ? {
llmContent: `Cannot display content of SVG file larger than 1MB: ${h}`,
returnDisplay: `Skipped large SVG file (>1MB): ${h}`
} : {
llmContent: await c.promises.readFile(o, "utf8"),
returnDisplay: `Read SVG as text: ${h}`
};
case "text": {
const w = (await c.promises.readFile(o, "utf8")).split(`
`), E = w.length, v = i || 0, _ = r?.defaultMaxLines ?? ge, $ = Math.min(v + (s === void 0 ? _ : s), E), b = Math.min(v, E), N = w.slice(b, $);
let D = !1;
const F = N.map((J) => {
const ct = r?.maxLineLength ?? ye;
return J.length > ct ? (D = !0, J.substring(0, ct) + "... [truncated]") : J;
}), S = v > 0 || $ < E, R = S || D, I = F.join(`
`);
let T = "";
return S ? (T = `Read lines ${b + 1}-${$} of ${E} from ${h}`, D && (T += " (some lines were shortened)")) : D && (T = `Read all ${E} lines from ${h} (some lines were shortened)`), {
llmContent: I,
returnDisplay: T,
isTruncated: R,
originalLineCount: E,
linesShown: [b + 1, $]
};
}
case "image":
case "pdf":
case "audio":
case "video": {
const p = await c.promises.readFile(o);
return {
llmContent: {
inlineData: {
data: Fe(p),
mimeType: Rt(a) || "application/octet-stream"
}
},
returnDisplay: `Read ${m} file: ${h}`
};
}
default:
return {
llmContent: `Unhandled file type: ${m}`,
returnDisplay: `Skipped unhandled file type: ${h}`,
error: `Unhandled file type for ${a}`
};
}
} catch (o) {
const c = o instanceof Error ? o.message : String(o), u = nt(vt(l, a));
let f = P.READ_CONTENT_FAILURE;
return o?.name === "NotFoundError" ? f = P.FILE_NOT_FOUND : o?.name === "TypeMismatchError" ? f = P.TARGET_IS_DIRECTORY : o?.name === "SecurityError" && (f = P.READ_CONTENT_FAILURE), {
llmContent: `Error reading file ${u}: ${c}`,
returnDisplay: `Error reading file ${u}: ${c}`,
error: `Error reading file ${a}: ${c}`,
errorType: f
};
}
}
async function _e(t, e, n) {
let i = !1;
const s = [];
for (const d of t)
d === "-n" ? i = !0 : s.push(d);
if (s.length === 0) throw new Error("sed: missing script");
const r = Nt(s[0]), a = s[1], l = /^(\d+),\s*(\d+)p$/.exec(r) || /^(\d+)p$/.exec(r);
if (!l) throw new Error(`sed: unsupported script "${r}" (use 'N,Mp' or 'Np')`);
const o = parseInt(l[1], 10), c = l.length === 3 ? parseInt(l[2], 10) : o, u = Math.max(0, o - 1), f = Math.max(0, c - u);
if (a) {
const d = A(x(e.cwd, a)), m = await be(d, e.cwd || "", void 0, u, f), h = typeof m.llmContent == "string" ? m.llmContent : St